[
  {
    "path": ".gitattributes",
    "content": "* eol=lf\nbin/mlscript-opt.js linguist-vendored\n*.mjs linguist-generated\nhkmc2/shared/src/test/mlscript-compile/RuntimeJS.mjs -linguist-generated\n"
  },
  {
    "path": ".github/skills/hkmc2-difftests/SKILL.md",
    "content": "---\nname: hkmc2-difftests\ndescription: Work with HKMC2 DiffTests where golden snapshots are embedded in `.mls` files as `//│ ...` lines and updated in place by the test runner. Use when editing or reviewing files under `hkmc2/shared/src/test/**/*.mls`, running `hkmc2DiffTests` or watcher loops, diagnosing mismatches between diagnostics and expectations (`:e`, `:re`, `:expect`, etc.), or deciding whether rewritten snapshot lines should be committed.\n---\n\n# HKMC2 DiffTests\n\nRun HKMC2 inline golden-file tests and treat file rewrites as first-class test output.\n\n## Quick Workflow\n1. Verify local environment once per machine.\n2. Edit `.mls` test blocks and test commands. Use `hkmc2/shared/src/test/mlscript/HkScratch.mls` for temporary experiments, or create a new `.mls` file for a new test case.\n3. Run direct `sbt` commands (never `cs launch sbt` for this repo).\n4. Review rewritten `//│` lines with git diff.\n5. Keep intentional rewrites, then rerun until clean.\n6. Revert temporary `HkScratch.mls` edits before committing.\n\nRead [execution-workflow.md](references/execution-workflow.md) for exact commands and onboarding flow.\n\n## Block Model And Rewrite Model\n- Parse each `.mls` file as sequential blocks, usually split by blank lines.\n- Parse `:command` lines as per-block options.\n- Ignore existing `//│ ...` lines as old snapshots.\n- Compile/run the block and emit fresh `//│ ...` lines.\n- Rewrite the file in place when generated output differs.\n- Fail only on policy violations (unexpected diagnostics, missing expected diagnostics, failed `:expect`, etc.).\n\nDo not treat rewritten files as automatic failures. Treat them as candidate snapshot updates and review them.\n\n## Command Semantics To Apply\n- `:js`: execute JS backend for the block.\n- `:silent`: suppress auto-printing of defined values.\n- `:expect <text>`: assert final rendered result equals exact text.\n- `:pe`, `:e`, `:re`, `:ge`, `:w`: expect parse/type/runtime/codegen/warning diagnostics.\n- `:fixme` or `:todo`: tolerate temporary failures under current policy.\n- `:wasm`, `:wat`, `:fwat`, `:swat`, `:llir`: enable lower-level backend outputs.\n\nRead [commands-and-policies.md](references/commands-and-policies.md) when you need deeper behavior details or troubleshooting logic.\n\n## Discovery Scope\n- Discover test files from `hkmc2/shared/src/test/**/*.mls`.\n- Diff runs exclude paths containing `staging` and `mlscript-compile`.\n- Assume `.mls` is the only supported extension for these diff tests.\n\n## Guardrails\n- Use repo README commands as source of truth for test execution.\n- Use direct `sbt ...` commands for this project.\n- For focused runs or updates on specific test files, follow the targeted workflows documented in `README.md` (for example `testOnly ... -- -z ...`, focused sets, and `ChangedTests.cmd` with watcher).\n- Run `npm install` before JS/Wasm-heavy test workflows when dependencies are missing.\n- Prefer reviewing `git diff`/`git status` immediately after a diff-test run.\n- Reset only unintended rewritten test files; keep intentional snapshot updates.\n"
  },
  {
    "path": ".github/skills/hkmc2-difftests/agents/openai.yaml",
    "content": "interface:\n  display_name: \"HKMC2 DiffTests\"\n  short_description: \"Work with HKMC2 inline golden-file DiffTests in .mls files\"\n  default_prompt: \"Use this skill to edit, run, and validate HKMC2 DiffTests that rewrite //│ snapshots in .mls files.\"\n"
  },
  {
    "path": ".github/skills/hkmc2-difftests/references/commands-and-policies.md",
    "content": "# Commands And Policies\n\n## Runner And Discovery\n- Discovery root: `hkmc2/shared/src/test`.\n- File type: `.mls`.\n- Diff test runs exclude paths containing `staging` and `mlscript-compile`.\n- `DiffMaker.run()` rewrites file content whenever generated output differs from current file text.\n\n## Per-Block Processing Model\n1. Read lines sequentially.\n2. Parse `:command` lines and update command state.\n3. Skip old snapshot lines starting with `//│ ` as input.\n4. Execute compilation/runtime pipeline for the block.\n5. Emit new `//│ ` output lines.\n6. Compare full generated content to original file content; write back if changed.\n\n## High-Value Commands\n- `:js`: run JS backend path and print/evaluate runtime results.\n- `:silent`: suppress automatic value printing.\n- `:expect <text>`: assert the rendered final result equals `<text>`.\n- `:pe`: expect parse errors.\n- `:e`: expect type errors.\n- `:re`: expect runtime errors.\n- `:ge`: expect compilation/codegen errors.\n- `:w`: expect warnings.\n- `:fixme` and `:todo`: expect and tolerate failures (failing in their absence).\n- `:breakme`: tolerate temporary expected lack of failures.\n- `:ignore`: ignore failures, but do not expect them, either.\n- `:wasm`: enable Wasm path.\n- `:wat`, `:fwat`, `:swat`: print Wasm text variants.\n- `:llir`: enable LLIR generation (with optional LLIR/C++ helpers in the same family).\n\n## Failure Policy\n- Unexpected diagnostics fail (error/warning kind mismatches).\n- Missing expected diagnostics fail (for `:pe`, `:e`, `:re`, `:ge`, `:w`) unless tolerated by `:todo`/`breakme` policy paths.\n- `:expect` mismatch fails as a runtime diagnostic.\n- Rewritten files alone are not a failure; they are snapshot updates to review.\n\n## Practical Review Rules\n- Treat `//│` changes as test artifacts, not source edits.\n- Commit snapshot rewrites only when behavior changes are intentional.\n- Prefer narrow reruns (`hkmc2DiffTests/test` or watcher) while iterating on a small set of `.mls` files.\n"
  },
  {
    "path": ".github/skills/hkmc2-difftests/references/execution-workflow.md",
    "content": "# Execution Workflow\n\n## Prerequisites\n- Install JDK, `sbt`, and Node.js.\n- **Run `npm install` in the repository root** to install all required npm packages (TypeScript, Binaryen, etc.).\n  This step is **mandatory** for JS and WASM test paths. In particular, the WASM tests\n  (`hkmc2/shared/src/test/mlscript/wasm/`) depend on the `binaryen` npm package for\n  WAT validation, formatting, and compilation to WebAssembly binary. Skipping `npm install`\n  will cause all WASM tests to fail with module-not-found errors at runtime.\n\n## Core Commands\n- Full HKMC2 test pass: `sbt hkmc2AllTests/test`\n- Compiler compile tests: `sbt hkmc2JVM/test`\n- Diff tests only: `sbt hkmc2DiffTests/test`\n- Diff watcher: `sbt \"~hkmc2DiffTests/Test/run\"`\n\nUse direct `sbt` commands for this repo. Avoid `cs launch sbt` because of known environment differences.\n\n## Typical Loop\n1. Edit a `.mls` test file under `hkmc2/shared/src/test/`.\n2. Use `hkmc2/shared/src/test/mlscript/HkScratch.mls` for temporary checks, or create a dedicated new `.mls` file for durable test coverage.\n3. Run `sbt hkmc2DiffTests/test` or watcher mode.\n4. Inspect rewritten `//│ ...` lines and diagnostics.\n5. Check `git status` and `git diff`.\n6. Keep intentional output updates; discard accidental rewrites and rerun.\n7. Revert temporary `HkScratch.mls` edits before committing.\n\n## Targeted Runs And Updates\n- Use README-guided focused execution when iterating on specific test files:\n  - `testOnly ... -- -z <pattern>` for name-filtered runs.\n  - Focused test path sets in the Scala test harness when needed.\n  - `ChangedTests.cmd` with watcher mode to rerun only unstaged changed tests.\n- Treat `README.md` as source of truth for exact syntax and current project-specific examples.\n\n## If Results Look Wrong\n- Confirm you are running from repo root.\n- Confirm `npm install` completed.\n- Check whether command markers in the test block changed behavior (`:js`, `:silent`, `:expect`, `:e`, `:re`, etc.).\n- Re-run with direct `sbt`.\n"
  },
  {
    "path": ".github/workflows/nix.yml",
    "content": "name: CI with Nix\n\non:\n  pull_request:\n  push:\n    branches: [ mlscript, hkmc2 ]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - name: Install Nix\n        uses: DeterminateSystems/nix-installer-action@main\n      - uses: rrbutani/use-nix-shell-action@v1\n        with:\n          devShell: .#default\n      - name: Install npm dependencies (TypeScript, Binaryen, etc.)\n        run: npm ci\n      - name: Run test\n        id: run_test\n        # Not running all tests because those outside of hkmc2 are obsolete (will be removed)\n        run: sbt -J-Xmx4096M -J-Xss8M hkmc2AllTests/test\n        # It's useful to see how the tests fail by seeing the diff through the next step\n        continue-on-error: true\n      - name: Check no changes\n        run: |\n          git update-index -q --refresh\n          git diff-files -p --exit-code\n      - name: Fail if tests failed\n        if: steps.run_test.outcome == 'failure'\n        run: exit 1\n"
  },
  {
    "path": ".gitignore",
    "content": "target/\n.bloop/\n.metals/\n.bsp/\nnode_modules/\nmetals.sbt\nproject/Dependencies.scala\nproject/metals.sbt\n**.worksheet.sc\n.DS_Store\n/sbt/\n"
  },
  {
    "path": ".sbtopts",
    "content": "# [2025-09-23] LP: I recommend running the official JDK 21 from Oracle's website,\n#   as it appears to be at least 2x faster than the community editions, at least on an Apple M2 Ultra\n#   (using GraalVM also appears to be similarly slow, surprisingly)\n\n-J-server\n\n-J-Xss8M\n\n# The options below were inspired by a message I got on some runs with more than usual memory retention:\n#   [warn] In the last 10 seconds, 5.067 (50.7%) were spent in GC. [Heap: 0.01GB free of 1.00GB, max 1.00GB] Consider increasing the JVM heap using `-Xmx` or try a different collector, e.g. `-XX:+UseG1GC`, for better performance.\n\n# Reduces warm-up time the first time the tests are run\n-J-Xms2G\n\n# Reduces time spent doing GC\n-J-Xmx4G\n\n#-J-XX:+UseG1GC # does not seem to make much of a difference\n\n"
  },
  {
    "path": ".scalafmt.conf",
    "content": "version = \"3.10.7\"\nrunner.dialect = scala3\n\nproject {\n  includePaths = [\n    \"glob:**/hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/**\",\n    \"glob:**/hkmc2DiffTests/src/test/scala/hkmc2/WasmDiffMaker.scala\"\n  ]\n}\nalign.preset = none\nalign.stripMargin = false\ndocstrings.style = SpaceAsterisk\nmaxColumn = 120\nnewlines.source = keep\nrewrite.rules = [SortModifiers]\nrewrite.scala3.convertToNewSyntax = true\nrewrite.scala3.endMarker.insertMinSpan = 20\nrewrite.scala3.removeOptionalBraces = true\nrewrite.trailingCommas.style = always\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"files.associations\": {\n        \"*.fun\": \"typescript\",\n        \"*.mls\": \"mlscript\"\n    },\n    \"typescript.validate.enable\": false,\n    \"files.watcherExclude\": {\n        \"**/target\": true\n    },\n    \"[typescript]\": {\n        \"editor.quickSuggestions\": {\n            \"comments\": \"off\",\n            \"other\": \"off\",\n            \"strings\": \"off\"\n        }\n    },\n    \"files.autoSave\": \"off\"\n}\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# Using the MLscript code base\n\n\n## Workflow\n\nIt is best to leave the SBT shell open (by just typing the `sbt` command line)\nand issue commands directly in that shell, as SBT startup is very slow.\n\nBefore running individual tests, make sure to first run `hkmc2JVM/test`,\nso that the compilation-tests (in `hkmc2/shared/src/test/mlscript-compile/`) are run\nand produce the JS files that are needed at runtime for the other tests (in `hkmc2/shared/src/test/mlscript/`).\n\nBefore finishing your work, run `hkmc2AllTests/test` to make sure the codebase compiles and all tests succeed.\n\nAfter you are done fixing all the problems and all the tests pass,\n*you need to commit the resulting golden test output changes*.\nAny commit that does not include the latest changes to test outputs will fail the CI.\n\nPlease also read the files in `.github/skills/hkmc2-difftests`.\n\n\n## Coding Style\n\nNever use `asInstanceOf` unless absolutely necessary. If you find yourself using `asInstanceOf`, it's a sign that your code may need to be refactored to be more type-safe.\n\nNever use default arguments in core business logic. Default arguments should be reserved for user-facing APIs.\n\nDo not remove existing `end` markers.\n\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Here are some quick notes on contributing to MLscript. (Written by Lionel, aka @LPTK.)\n\n## Contribution Quality\n\nThe bar for contributing to this project is quite high.\nIf you're a student, you should be ready to put a lot more efforts and polishing into your changes\nthan you would for a course or personal project.\nIn fact, I expect a lot more polishing than would be expected for many other research projects.\n\n### For Draft PRs\n\nIt is okay for draft PRs to contain work-in-progress changes that are not expected to be merged yet.\nYou can ask my opinion on your changes or on specific design considerations,\nbut you should not expect a full and detailed review from me if your PR is a draft.\n\n### For Non-Draft PRs\n\nI am an extremely detail-oriented person,\nand I will usually look at every single line of changed source code in your PR.\nTherefore, **before you request a review from me**,\nplease make sure that **you have reviewed _the entire diff_ of your changes carefully**.\nI should not have to put in more work than you in revieweing the diff\n– if I end up doing so, it means you have somehow failed at your contribution job and you have wasted some of my time.\nYou should be able to explain and defend every single line of your changes.\nIn particular, please be mindful not to pollute your PR with random whitespace changes\nand other leftovers from your local experimentations.\n\nIdeally, I should be able to review your changes\nby asking a few clarifying questions and making a few minor suggestions.\nIf some code is not clear enough to understand with a little bit of context,\nit would be best to document the logic in the code using comments.\n\nThe way this is _not_ supposed to happen is that I have to keep coming back to your PR,\ncontinually finding more problems and more unpolished or unclear changes,\nand having to go through lots of back-and-forth interactions this way.\nThis will only lead to growing frustration on both ends.\nPlease be considerate of my time, which is often extremely scarce,\nand make sure I never have to ask for a change or clarification more than once.\n\n## Pull Request Etiquette\n\nDuring the PR review process, we make use of GitHub comments to track suggestions\nand clarification requests.\nResolving all comment threads is necessary for GitHub to allow the PR to be merged.\n\nI realize it is not always clear to everyone when comment threads should be resolved, and by whom.\nThe general principles are the following:\n\n * If the comment is a change suggestion...\n \n   * If it's clear and uncontroversial how to apply the suggestion,\n     you should resolve the comment after you have made the corresponding changes to your code _and_ pushed that code to your branch.\n   \n   * If you are not 100% sure that you have applied the suggestion correctly,\n     leave a comment asking me to have a look.\n     DO NOT resolve the comment in this case.\n   \n   * If you don't fully understand or agree with the suggestion, reply to the comment with your questions and rebuttals.\n     DO NOT resolve the comment in this case.\n   \n * If the comment is a clarification request, answer it as best you can and wait for my feedback.\n   DO NOT resolve the comment in this case.\n   I will either come back with further questions or suggestions, or close the comment MYSELF if I find your answer satisfactory.\n\nEssentially, a comment that I made must _either_ receive an answer from you (as a child comment) and left unresolved\n_or_ be 100% addressed in your code and marked resolved (but only if you are sure about it; if not, leave a child comment and don't resolve the discussion).\n\nThe reason for these guidleines is mostly that GitHub's UI is poor and rather inappropriate.\nIn particular, I will not see a comment answer you make if you resolve the conversation,\nbecause the UI will usually not show your response to me.  \n(As a small digression, I think the UI would be better if _both_ the commenter _and_ the PR author would need to independently mark a comment as resolved\nbefore the comment is considered truly resolved by GitHub and subsequently hidden.)\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 Lionel Parreaux\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# MLscript\n\nWhat would TypeScript look like if was designed with type inference, soundness, and pattern matching in mind?\n\nThis original question lead to the creation of the MLscript programming language,\na modern object-oriented and functional programming language for the Web.\n\nSince then, the goals of the language have evolved,\nand MLscript has become a more ambitious effort at defining a next-generation high-level programming language,\naiming to maximize reliability, expressiveness, and performance.\nWe are notably adding new backends, such as WASM, so this is no longer \"just\" a scripting language.\nHence, the name of the next iteration of the language will also most likely change.\n\nThis repository contains a few iterations of the MLscript experimental compiler,\nand most notably:\n\n- [MLscript Compiler Version 1](#mlscript-compiler-version-1)\n- [MLscript Compiler Version 2 (hkmc2)](#mlscript-compiler-version-2-hkmc2)\n\nThe latter is in active development, on the `hkmc2` branch.\nThe continuous integration (CI) has been set up to only test this version of the compiler.\nThe `mlscript` branch contains the last commit where the CI was set up to test the old version-1 compiler.\n\nThe webpage at https://hkust-taco.github.io/mlscript/ still demonstrates the old version-1 compiler.\nAn online demo of hkmc2 (already somewhat outdated) can be found at https://mlscript.fun/.\n\n\n# MLscript Compiler Version 1\n\nThis legacy version of the compiler provided basic JavaScript code-gen along with advanced type checking for object-oriented and functional programming with records, generic classes, mix-in traits, first-class unions and intersections, instance matching, and ML-style principal type inference.\nThese features can be used to implement expressive class hierarchies as well as extensible sums and products.\n\nThe approach supports union, intersection, and complement (or negation) connectives, making sure they form a Boolean algebra, and adds enough structure to derive a sound and complete type inference algorithm.\n\nMany extensions were also added over time and splintered off into supporting research paper artifacts, such as more advanced extensible programming support, expressive pattern matching syntax and compilation, and first-class polymorphism (see: [Publications](#publications)).\n\n\n\n## Getting Started\n\n### Project Structure\n\n- The `shared/src/main/scala/mlscript` directory contains the sources of the MLscript compiler.\n\n- The `shared/src/test/scala/mlscript` directory contains the sources of the testing infrastructure.\n\n- The `shared/src/test/diff` directory contains the actual tests.\n\n- The `ts2mls/js/src/main/scala/ts2mls` directory contains the sources of the ts2mls module.\n\n- The `ts2mls/js/src/test/scala/ts2mls` directory contains the sources of the ts2mls declaration generation test code.\n\n- The `ts2mls/jvm/src/test/scala/ts2mls` directory contains the sources of the ts2mls diff test code.\n\n- The `ts2mls/js/src/test/typescript` directory contains the TypeScript test code.\n\n- The `ts2mls/js/src/test/diff` directory contains the declarations generated by ts2mls.\n\n- The `ts2mls` experimental sub-project allows one to use TypeScript libraries in MLscript. It can generate libraries' declaration information in MLscript by parsing TypeScript AST, which can be used in MLscript type checking.\n\n### Prerequisites\n\nYou need [JDK supported by Scala][supported-jdk-versions], [sbt][sbt], [Node.js][node.js], and TypeScript to compile the project and run the tests.\n\nWe recommend you to install JDK and sbt via [coursier][coursier]. The versions of Node.js that passed our tests are from v16.14 to v16.17, v17 and v18. **Run `npm install` in the repository root** to install required npm packages (including TypeScript). **Note that ScalaJS cannot find globally installed TypeScript.** We explicitly support TypeScript v4.7.4.\n\n[supported-jdk-versions]: https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html\n[sbt]: https://www.scala-sbt.org/\n[node.js]: https://nodejs.org/\n[coursier]: https://get-coursier.io/\n\n### Running the tests\n\nRunning the main MLscript tests only requires the Scala Build Tool installed.\nIn the terminal, run `sbt mlscriptJVM/test`.\n\nRunning the ts2mls MLscript tests requires NodeJS, and TypeScript in addition.\nIn the terminal, run `sbt ts2mlsTest/test`.\n\nYou can also run all tests simultaneously.\nIn the terminal, run `sbt test`.\n\n### Running tests individually\n\nIndividual tests can be run with `-z`.\nFor example, `~mlscriptJVM/testOnly mlscript.DiffTests -- -z parser` will watch for file changes and continuously run all parser tests (those that have \"parser\" in their name).\n\nYou can also indicate the test you want in `shared/src/test/scala/mlscript/DiffTests.scala`:\n\n```scala\n  // Allow overriding which specific tests to run, sometimes easier for development:\n  private val focused = Set[Str](\n    // Add the test file path here like this:\n    \"shared/src/test/diff/mlscript/Methods.mls\"\n  ).map(os.RelPath(_))\n```\n\nTo run the tests in ts2mls sub-project individually,\nyou can indicate the test you want in `ts2mls/js/src/test/scala/ts2mls/TSTypeGenerationTests.scala`:\n\n```scala\nprivate val testsData = List(\n    // Put all input files in the `Seq`\n    // Then indicate the output file's name\n    (Seq(\"Array.ts\"), \"Array.d.mls\")\n  )\n```\n\n### Running the web demo locally\n\nTo run the demo on your computer, compile the project with `sbt fastOptJS`, then open the `local_testing.html` file in your browser.\n\nYou can make changes to the type inference code\nin `shared/src/main/scala/mlscript`,\nhave it compile to JavaScript on file change with command\n`sbt ~fastOptJS`,\nand immediately see the results in your browser by refreshing the page with `F5`.\n\n\n\n\n\n# MLscript Compiler Version 2 (hkmc2)\n\n\nThis is the second iteration of the MLscript compiler,\nnicknamed _hkmc2_ (Hong Kong MLscript Compiler v2).\n\n\n## Getting Started\n\n### Project Structure\n\nMost of the important code of the new compiler is in the `hkmc2` folder.\n\n### Prerequisites\n\nYou need [JDK supported by Scala][supported-jdk-versions], [sbt][sbt], [Node.js][node.js], and TypeScript to compile the project and run the tests.\n\nWe recommend you to install JDK and sbt via [coursier][coursier]. The versions of Node.js that passed our tests are from v16.14 to v16.17, v17 and v18.\n\n**Run `npm install` in the repository root** to install the required npm packages.\nThis installs TypeScript (used by the JS backend tests) as well as [Binaryen][binaryen] (used by the WASM backend tests in `hkmc2/shared/src/test/mlscript/wasm/`).\nIf you skip this step, **WASM tests will fail** at runtime because the `binaryen` module cannot be found by Node.js.\n\n**Note that ScalaJS cannot find globally installed TypeScript.** We explicitly support TypeScript v4.7.4.\n\n[supported-jdk-versions]: https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html\n[sbt]: https://www.scala-sbt.org/\n[node.js]: https://nodejs.org/\n[coursier]: https://get-coursier.io/\n[binaryen]: https://github.com/WebAssembly/binaryen\n\nSome tests in the `compiler` subproject generate and compile C++ while making use of some libraries.\nYou can run these by installing `nix` (for MacOS, we recommend https://determinate.systems/posts/graphical-nix-installer/)\nand running `nix develop` before launching SBT.\nIf you don't want to use nix, you can install the dependencies manually as follows, but this has not been tested on non-MacOS systems:\n```bash\nbrew install mimalloc boost gmp\n```\n\n### Running the tests\n\nRunning the tests requires the Scala Build Tool (SBT) installed.\n\nWe recommend running all tests in the SBT shell,\ni.e., do not restart SBT every time,\nbut launch it in shell mode (with command `sbt`)\nand then use one of the following commands.\n\n- `hkmc2JVM/test` for running only the main compilation tests, in `hkmc2/shared/src/test/mlscript-compile`.\n- `hkmc2DiffTests/test` for running only the main diff-tests, in `hkmc2/shared/src/test/mlscript`.\n- `hkmc2MainTests/test` for running the above two.\n- `hkmc2AppsTests/test` for running the applications compile and diff tests.\n- `hkmc2NofibTests/test` for running the nofib compile and diff tests.\n- `hkmc2WasmTests/test` for running the wasm compile and diff tests.\n- `hkmc2MostTests/test` for running all of the above.\n- `hkmc2AllTests/test` for running all hkmc2 tests, including ScalaJS-compiled tests.\n- `~hkmc2DiffTests/Test/run` for running the test watcher,\n  which updates test files as you save them and recompiles the Scala sources automatically on change.\n- `test` for compiling all JVM and JS subprojects\n  and running every single test in the repository,\n  including obsolete ones.\n\nAnother useful SBT incantation is `; hkmc2MostTests/test; ~hkmc2DiffTests/Test/run`.\nThis command runs all hkmc2 tests once and then starts the test watcher.\nThis is a useful command to use periodically while making changes to the compiler,\nto check that you haven't broken anything.\n\nNote that when saved, the special file `ChangedTests.cmd` will trigger the test watcher to run\nall tests that currently have unstaged changes in git.\nThis is useful when you have a working subset of tests that you want to run periodically.\n\n### Running tests individually\n\nIndividual tests can be run with `-z`.\nFor example, `~mlscriptJVM/testOnly mlscript.DiffTests -- -z parser` will watch for file changes and continuously run all parser tests (those that have \"parser\" in their name).\n\n\n\n\n\n# Publications\n\nThe following research publications notably used various iterations of the MLscript compiler for their implementations.\nLinks to the individual paper artifact repositories are provided at the corresponding paper webpages.\n\n* [**OOPSLA '22**] [MLstruct: Principal Type Inference in a Boolean](https://cse.hkust.edu.hk/~parreaux/publication/oopsla22a/)\n  used v1 with the old ML-like syntax.\n* [**ECOOP '23**] [super-Charging Object-Oriented Programming Through Precise Typing of Open Recursion](https://cse.hkust.edu.hk/~parreaux/publication/ecoop23/) (🏆 Distinguished Artifact!)\n  used v1 with the current Scala-like syntax and a new object system.\n* [**OOPSLA '23**] [Getting into the Flow: Towards Better Type Error Messages for Constraint-Based Type Inference](https://cse.hkust.edu.hk/~parreaux/publication/oopsla23/)\n  used v1 with an OCaml-syntax parser and heavily modified type checker.\n* [**POPL '24**] [When Subtyping Constraints Liberate: A Novel Approach to Type Inference for First-Class Polymorphism](https://cse.hkust.edu.hk/~parreaux/publication/popl24/)\n  used v1 with the old ML-like syntax.\n* [**OOPSLA '24**] [The Ultimate Conditional Syntax](https://cse.hkust.edu.hk/~parreaux/publication/oopsla24b/) (🏆 Distinguished Paper!)\n  used v1 with the current Scala-like syntax;\n  the parser had many problems – the reimplementation of the Ultimate Conditional Syntax in hkmc2 is of much higher quality.\n* [**GPCE '24**] [Seamless Scope-Safe Metaprogramming Through Polymorphic Subtype Inference](https://cse.hkust.edu.hk/~parreaux/publication/gpce24/)\n  used v1 with the current Scala-like syntax.\n* [**OOPSLA '25**] [A Lightweight Type-and-Effect System for Invalidation Safety](https://cse.hkust.edu.hk/~parreaux/publication/oopsla25/)\n  used hkmc2.\n\n\n\n\n"
  },
  {
    "path": "bin/mlscript-opt.js",
    "content": "let typecheck;\n(function(){\n'use strict';var f,aaa=Object.freeze({esVersion:6,assumingES6:!0,productionMode:!0,linkerVersion:\"1.11.0\",fileLevelThis:this}),aa;function baa(a){for(var b in a)return b}function ba(a){this.eQ=a}ba.prototype.toString=function(){return String.fromCharCode(this.eQ)};var daa=function caa(a,b,c){var e=new a.Ia(b[c]);if(c<b.length-1){a=a.kB;c+=1;for(var g=e.a,h=0;h<g.length;h++)g[h]=caa(a,b,c)}return e};\nfunction ca(a){switch(typeof a){case \"string\":return da(fa);case \"number\":return ha(a)?a<<24>>24===a?da(eaa):a<<16>>16===a?da(faa):da(gaa):ja(a)?da(haa):da(iaa);case \"boolean\":return da(jaa);case \"undefined\":return da(la);default:return null===a?a.N0():a instanceof ma?da(kaa):a instanceof ba?da(laa):a&&a.$classData?da(a.$classData):null}}\nfunction na(a){switch(typeof a){case \"string\":return\"java.lang.String\";case \"number\":return ha(a)?a<<24>>24===a?\"java.lang.Byte\":a<<16>>16===a?\"java.lang.Short\":\"java.lang.Integer\":ja(a)?\"java.lang.Float\":\"java.lang.Double\";case \"boolean\":return\"java.lang.Boolean\";case \"undefined\":return\"java.lang.Void\";default:return null===a?a.N0():a instanceof ma?\"java.lang.Long\":a instanceof ba?\"java.lang.Character\":a&&a.$classData?a.$classData.name:null.qi.name}}\nfunction oa(a,b){switch(typeof a){case \"string\":return pa(a,b);case \"number\":return maa(qa(),a,b);case \"boolean\":return a===b?0:a?1:-1;default:return a instanceof ma?ua(xa(),a.W,a.Y,b.W,b.Y):a instanceof ba?Ea(a)-Ea(b)|0:a.sl(b)}}\nfunction La(a,b){switch(typeof a){case \"string\":return a===b;case \"number\":return Object.is(a,b);case \"boolean\":return a===b;case \"undefined\":return a===b;default:return a&&a.$classData||null===a?a=a.i(b):a instanceof ma?b instanceof ma?(b=Za(b),a=a.W===b.W&&a.Y===b.Y):a=!1:a=a instanceof ba?b instanceof ba?Ea(a)===Ea(b):!1:gb.prototype.i.call(a,b),a}}\nfunction ib(a){switch(typeof a){case \"string\":return lb(a);case \"number\":return mb(a);case \"boolean\":return a?1231:1237;case \"undefined\":return 0;default:return a&&a.$classData||null===a?a.B():a instanceof ma?a.W^a.Y:a instanceof ba?Ea(a):gb.prototype.B.call(a)}}function nb(a){return void 0===a?\"undefined\":a.toString()}function pb(a,b){if(0===b)throw new qb(\"/ by zero\");return a/b|0}function Bb(a,b){if(0===b)throw new qb(\"/ by zero\");return a%b|0}\nfunction Eb(a){return 2147483647<a?2147483647:-2147483648>a?-2147483648:a|0}function Fb(a,b,c,d,e){if(a!==c||d<b||(b+e|0)<d)for(var g=0;g<e;g=g+1|0)c[d+g|0]=a[b+g|0];else for(g=e-1|0;0<=g;g=g-1|0)c[d+g|0]=a[b+g|0]}var Kb=0,Mb=new WeakMap;\nfunction Qb(a){switch(typeof a){case \"string\":return lb(a);case \"number\":return mb(a);case \"bigint\":var b=0;for(a<BigInt(0)&&(a=~a);a!==BigInt(0);)b^=Number(BigInt.asIntN(32,a)),a>>=BigInt(32);return b;case \"boolean\":return a?1231:1237;case \"undefined\":return 0;case \"symbol\":return a=a.description,void 0===a?0:lb(a);default:if(null===a)return 0;b=Mb.get(a);void 0===b&&(Kb=b=Kb+1|0,Mb.set(a,b));return b}}function Zb(a){return\"number\"===typeof a&&a<<24>>24===a&&1/a!==1/-0}\nfunction $b(a){return\"number\"===typeof a&&a<<16>>16===a&&1/a!==1/-0}function ha(a){return\"number\"===typeof a&&(a|0)===a&&1/a!==1/-0}function ja(a){return\"number\"===typeof a&&(a!==a||Math.fround(a)===a)}function hc(a){return new ba(a)}function Ea(a){return null===a?0:a.eQ}function Za(a){return null===a?aa:a}function tc(){return new gb}function gb(){}gb.prototype.constructor=gb;function p(){}p.prototype=gb.prototype;gb.prototype.B=function(){return Qb(this)};\ngb.prototype.i=function(a){return this===a};gb.prototype.u=function(){var a=this.B();return na(this)+\"@\"+(+(a>>>0)).toString(16)};gb.prototype.toString=function(){return this.u()};function zc(a){if(\"number\"===typeof a){this.a=Array(a);for(var b=0;b<a;b++)this.a[b]=null}else this.a=a}zc.prototype=new p;zc.prototype.constructor=zc;zc.prototype.wa=function(a,b,c,d){Fb(this.a,a,b.a,c,d)};zc.prototype.ia=function(){return new zc(this.a.slice())};function Dc(){}Dc.prototype=zc.prototype;\nfunction Ec(a){if(\"number\"===typeof a){this.a=Array(a);for(var b=0;b<a;b++)this.a[b]=!1}else this.a=a}Ec.prototype=new p;Ec.prototype.constructor=Ec;Ec.prototype.wa=function(a,b,c,d){Fb(this.a,a,b.a,c,d)};Ec.prototype.ia=function(){return new Ec(this.a.slice())};function Ic(a){this.a=\"number\"===typeof a?new Uint16Array(a):a}Ic.prototype=new p;Ic.prototype.constructor=Ic;Ic.prototype.wa=function(a,b,c,d){b.a.set(this.a.subarray(a,a+d|0),c)};Ic.prototype.ia=function(){return new Ic(this.a.slice())};\nfunction Pc(a){this.a=\"number\"===typeof a?new Int8Array(a):a}Pc.prototype=new p;Pc.prototype.constructor=Pc;Pc.prototype.wa=function(a,b,c,d){b.a.set(this.a.subarray(a,a+d|0),c)};Pc.prototype.ia=function(){return new Pc(this.a.slice())};function Sc(a){this.a=\"number\"===typeof a?new Int16Array(a):a}Sc.prototype=new p;Sc.prototype.constructor=Sc;Sc.prototype.wa=function(a,b,c,d){b.a.set(this.a.subarray(a,a+d|0),c)};Sc.prototype.ia=function(){return new Sc(this.a.slice())};\nfunction Xc(a){this.a=\"number\"===typeof a?new Int32Array(a):a}Xc.prototype=new p;Xc.prototype.constructor=Xc;Xc.prototype.wa=function(a,b,c,d){b.a.set(this.a.subarray(a,a+d|0),c)};Xc.prototype.ia=function(){return new Xc(this.a.slice())};function Zc(a){if(\"number\"===typeof a){this.a=Array(a);for(var b=0;b<a;b++)this.a[b]=aa}else this.a=a}Zc.prototype=new p;Zc.prototype.constructor=Zc;Zc.prototype.wa=function(a,b,c,d){Fb(this.a,a,b.a,c,d)};Zc.prototype.ia=function(){return new Zc(this.a.slice())};\nfunction $c(a){this.a=\"number\"===typeof a?new Float32Array(a):a}$c.prototype=new p;$c.prototype.constructor=$c;$c.prototype.wa=function(a,b,c,d){b.a.set(this.a.subarray(a,a+d|0),c)};$c.prototype.ia=function(){return new $c(this.a.slice())};function ed(a){this.a=\"number\"===typeof a?new Float64Array(a):a}ed.prototype=new p;ed.prototype.constructor=ed;ed.prototype.wa=function(a,b,c,d){b.a.set(this.a.subarray(a,a+d|0),c)};ed.prototype.ia=function(){return new ed(this.a.slice())};\nfunction fd(){this.Ia=void 0;this.fy=this.kB=this.rb=null;this.gy=0;this.jz=null;this.lv=\"\";this.iz=this.sv=this.bB=this.rJ=void 0;this.name=\"\";this.isJSClass=this.isArrayClass=this.isInterface=this.isPrimitive=!1;this.isInstance=void 0}function gd(a,b,c,d,e){var g=new fd;g.rb={};g.jz=a;g.lv=b;g.sv=h=>h===g;g.name=c;g.isPrimitive=!0;g.isInstance=()=>!1;void 0!==d&&(g.bB=id(g,d,e));return g}\nfunction q(a,b,c,d,e){var g=new fd,h=baa(a);g.rb=d;g.lv=\"L\"+c+\";\";g.sv=k=>!!k.rb[h];g.name=c;g.isInterface=b;g.isInstance=e||(k=>!!(k&&k.$classData&&k.$classData.rb[h]));return g}function id(a,b,c,d){var e=new fd;b.prototype.$classData=e;var g=\"[\"+a.lv;e.Ia=b;e.rb={g:1,Ff:1,l:1};e.kB=a;e.fy=a;e.gy=1;e.lv=g;e.name=g;e.isArrayClass=!0;e.sv=d||(h=>e===h);e.iz=c?h=>new b(new c(h)):h=>new b(h);e.isInstance=h=>h instanceof b;return e}\nfunction naa(a){function b(k){if(\"number\"===typeof k){this.a=Array(k);for(var l=0;l<k;l++)this.a[l]=null}else this.a=k}var c=new fd;b.prototype=new Dc;b.prototype.constructor=b;b.prototype.wa=function(k,l,m,n){Fb(this.a,k,l.a,m,n)};b.prototype.ia=function(){return new b(this.a.slice())};var d=a.fy||a,e=a.gy+1;b.prototype.$classData=c;var g=\"[\"+a.lv;c.Ia=b;c.rb={g:1,Ff:1,l:1};c.kB=a;c.fy=d;c.gy=e;c.lv=g;c.name=g;c.isArrayClass=!0;var h=k=>{var l=k.gy;return l===e?d.sv(k.fy):l>e&&d===jd};c.sv=h;c.iz=\nk=>new b(k);c.isInstance=k=>{k=k&&k.$classData;return!!k&&(k===c||h(k))};return c}function md(a){a.bB||(a.bB=naa(a));return a.bB}function da(a){a.rJ||(a.rJ=new nd(a));return a.rJ}fd.prototype.isAssignableFrom=function(a){return this===a||this.sv(a)};fd.prototype.checkCast=function(){};fd.prototype.getSuperclass=function(){return this.S2?da(this.S2):null};fd.prototype.getComponentType=function(){return this.kB?da(this.kB):null};\nfd.prototype.newArrayOfThisClass=function(a){for(var b=this,c=0;c<a.length;c++)b=md(b);return daa(b,a,0)};var jd=new fd;jd.rb={g:1};jd.lv=\"Ljava.lang.Object;\";jd.sv=a=>!a.isPrimitive;jd.name=\"java.lang.Object\";jd.isInstance=a=>null!==a;jd.bB=id(jd,zc,void 0,a=>{var b=a.gy;return 1===b?!a.fy.isPrimitive:1<b});gb.prototype.$classData=jd;\nvar pd=gd(void 0,\"V\",\"void\",void 0,void 0),rd=gd(!1,\"Z\",\"boolean\",Ec,void 0),td=gd(0,\"C\",\"char\",Ic,Uint16Array),xd=gd(0,\"B\",\"byte\",Pc,Int8Array),Cd=gd(0,\"S\",\"short\",Sc,Int16Array),Ed=gd(0,\"I\",\"int\",Xc,Int32Array),Fd=gd(null,\"J\",\"long\",Zc,void 0),Gd=gd(0,\"F\",\"float\",$c,Float32Array),Ld=gd(0,\"D\",\"double\",ed,Float64Array);\nfunction oaa(a,b){try{t();var c=(0,eval)(b),d=Md(new Nd,c);Od();var e=Pd(u(),d);return new Ud(e)}catch(g){return c=g instanceof Vd?g:new $d(g),b=ce(),ee(b,'\\x3cfont color\\x3d\"red\"\\x3eRuntime error occurred:\\x3c/font\\x3e'),c=\"\"+a.as+c.qj(),ee(b,c),ee(b,a.as),ee(b,a.as),t(),new fe(b.yf.ja)}}\nfunction paa(a){var b=ce(),c=he(\"\\x3ctr\\x3e\\n                      |  \\x3ctd\\x3eName\\x3c/td\\x3e\\n                      |  \\x3ctd\\x3eValue\\x3c/td\\x3e\\n                      |\\x3c/tr\\x3e\\n                      |\");for(ee(b,c);!a.b();)c=a.e(),c='\\x3ctr\\x3e\\n                         |  \\x3ctd class\\x3d\"name\"\\x3e'+je(je(c.h(),\"  \",\"\\x26nbsp;\\x26nbsp;\"),\"\\n\",\"\\x3cbr/\\x3e\")+\"\\x3c/td\\x3e\\n                         |  \\x3ctd\\x3e\"+je(je(c.j(),\"  \",\"\\x26nbsp;\\x26nbsp;\"),\"\\n\",\"\\x3cbr/\\x3e\")+\"\\x3c/td\\x3e\\n                         |\\x3c/tr\\x3e\\n                         |\",\nc=he(c),ee(b,c),a=a.f();return b.yf.ja}function ke(a,b){if(null===a)throw le();return a.sb?a.vb:me(a,new ne(b))}function oe(){this.as=\"\\x3cbr /\\x3e\"}oe.prototype=new p;oe.prototype.constructor=oe;function qe(a,b){b=b.target;if(b instanceof HTMLTextAreaElement)se(a,b.value);else throw new w(b);}\nfunction se(a,b){var c=document.querySelector(\"#mlscript-output\"),d=null;d=\"\";try{var e=ue(ve(),b),g=we(xe(),e);ze(g,\"\",\"\",\"\");var h=Ae(new Fe,b,g),k=new Ge(\"\\x3cinput\\x3e\",1,h),l=qaa(new Je(k,new y(vb=>{throw vb;}),!1)),m=new Ke(k,l),n=Le(m),r=Me(m,new Ne(136),new Oe(\"parseAll\"));a:{if(r instanceof z){var v=r.z;if(null!==v){var x=v.h(),A=v.j();for(b=r;;){if(b.b())C=!1;else var B=b.e().h(),C=Pe(new E(B),Se());if(C)b=b.f();else break}var D=b.Jg(),F=D.b()?G(new H,x,A):D.o();if(null===F)throw new w(F);\nvar I=F.h(),M=F.j(),N=new Te(new Ue(J(new K,[\"Expected end of input; found \",\" instead\"]))),P=[We(Xe(),I.jb())],T=Ye(N,J(new K,P));t();var Y=G(new H,T,new L(M)),Z=O().c;Ze(m,new z(Y,Z));break a}}var S=O().c;if(null===S?null!==r:!S.i(r))throw new w(r);}var ea=new $e,ia=new cf(ef(n));ff(gf(),\"Parsed: \"+ia+\"\\n\");var X=new hf(!1,!1,!1,!0),sa=new y(vb=>{throw vb;}),Ja=mf(raa(X));t();var Xa=nf(),Fa=of(X,n,t().d,tf(Ja),sa,Xa),za=saa(ea.sb?ea.vb:ke(ea,X),Fa,(t(),new L(!0)),(ea.sb||ke(ea,X),!0),Ja),Qa=uf(X,\nza,!1,Ja);Q();vf();var Ma=O().c,Ga=wf(0,new z(Qa,Ma),!0,\"'\"),ab=yf(Qa,0,Ga),Hb=je(je(zf(ab),\"  \",\"\\x26nbsp;\\x26nbsp;\"),\"\\n\",\"\\x3cbr/\\x3e\"),bc=\"\"+he('\\x3cdiv\\x3e\\x3ctable width\\x3d\"100%\"\\x3e\\n                            |  \\x3ctr\\x3e\\n                            |    \\x3ctd colspan\\x3d\"2\"\\x3e\\x3ch4\\x3e\\x3ci\\x3eTyping Results:\\x3c/i\\x3e\\x3c/h4\\x3e\\x3c/td\\x3e\\n                            |  \\x3c/tr\\x3e\\n                            |')+he('\\x3ctr\\x3e\\n                            |  \\x3ctd colspan\\x3d\"2\"\\x3e'+\nHb+\"\\x3c/td\\x3e\\n                            |\\x3c/tr\\x3e\\n                            |\"),yb=taa(new Af,ia);if(null===yb)throw new w(yb);var tb=yb.j(),eb=ze(yb.h(),\"\",\"\\n\",\"\"),kb=oaa(a,eb);if(kb instanceof fe)var Rb=kb.aa;else{if(!(kb instanceof Ud))throw new w(kb);Rb=paa(Bf(tb,kb.fa))}var Gb=\"\"+he('\\x3ctr\\x3e\\n                          |  \\x3ctd colspan\\x3d\"2\"\\x3e\\x3ch4\\x3e\\x3ci\\x3eExecution Results:\\x3c/i\\x3e\\x3c/h4\\x3e\\x3c/td\\x3e\\n                          |\\x3c/tr\\x3e\\n                          |')+\nRb+\"\\x3c/table\\x3e\";a=bc+Gb}catch(vb){if(m=vb instanceof Vd?vb:new $d(vb),m instanceof Df){n=null;n=ce();Xe();x=m.vt().m();x=uaa(new Ef(x,new y(Tb=>Tb.h())));if(m instanceof Ff)A='\\u2554\\u2550\\u2550 \\x3cstrong style\\x3d\"color: #E74C3C\"\\x3e[ERROR]\\x3c/strong\\x3e ';else{if(!(m instanceof Gf))throw new w(m);A='\\u2554\\u2550\\u2550 \\x3cstrong style\\x3d\"color: #F39C12\"\\x3e[WARNING]\\x3c/strong\\x3e '}B=-1+m.vt().K()|0;C=C=0;for(D=Hf(m.vt());!D.b();){I=D.e();a:{if(null!==I&&(F=I.h(),M=I.Sc(),null!==F)){N=F.h();\nI=F.j();F=Lf(new E(M),B);N=Mf(N,x);Lf(new E(M),0)?(M=A+N,ee(n,d),ee(n,M)):(M=(F&&I.b()?\"\\u2559\\u2500\\u2500\":\"\\u255f\\u2500\\u2500\")+\" \"+N,ee(n,d),ee(n,M));ee(n,a.as);I.b()?(M=m.vt().K(),M=Lf(new E(M),1)):M=!1;M&&(ee(n,d),ee(n,\"\\u2559\\u2500\\u2500\"),ee(n,a.as));if(!I.b()){I=I.o();M=Nf(I.dh.Us,I.fh);if(null===M)throw new w(M);P=M.kc|0;T=M.Rd|0;Lf(new E(C),0)&&(C=C+(-1+P|0)|0);N=Nf(I.dh.Us,I.eh);if(null===N)throw new w(N);M=N.kc|0;N=N.Rd|0;for(ia=T;P<=M;)T=\"l.\"+(-1+(I.dh.rx+P|0)|0)+\": \",Z=I.dh.Us.$C.va(-1+\nP|0),ea=Lf(new E(P),M)?N:1+Z.length|0,Y=Of(Q(),Z,0,-1+ia|0),ia='\\x3cu style\\x3d\"text-decoration: #E74C3C dashed underline\"\\x3e'+Of(Q(),Z,-1+ia|0,-1+ea|0)+\"\\x3c/u\\x3e\",Z=Of(Q(),Z,-1+ea|0,Z.length),T=\"\\u2551  \"+T+\"\\t\"+Y+ia+Z,ee(n,d),ee(n,T),ee(n,a.as),ia=1,P=1+P|0,F&&(ee(n,d),ee(n,\"\\u2559\\u2500\\u2500\"),ee(n,a.as))}break a}throw new w(I);}D=D.f()}m.vt().b()&&(ee(n,d),ee(n,\"\\u2559\\u2500\\u2500\"),ee(n,a.as));a=n.yf.ja}else a='\\n      \\x3cfont color\\x3d\"Red\"\\x3e\\n      Unexpected error: '+m+(vaa(m),\"\")+\n\"\\x3c/font\\x3e\"}c.innerHTML=a}oe.prototype.$classData=q({uT:0},!1,\"Main$\",{uT:1,g:1});var Pf;function Qf(){Pf||(Pf=new oe);return Pf}function Rf(){}Rf.prototype=new p;Rf.prototype.constructor=Rf;Rf.prototype.$classData=q({xT:0},!1,\"fastparse.internal.Util$\",{xT:1,g:1});var Sf;function nd(a){this.$J=null;this.qi=a}nd.prototype=new p;nd.prototype.constructor=nd;nd.prototype.u=function(){return(this.qi.isInterface?\"interface \":Yf(this)?\"\":\"class \")+this.qi.name};\nfunction Zf(a,b){return!!a.qi.isAssignableFrom(b.qi)}function $f(a){return!!a.qi.isArrayClass}function Yf(a){return!!a.qi.isPrimitive}\nfunction ag(a){if(null===a.$J){if($f(a))var b=ag(bg(a))+\"[]\";else{b=a.qi.name;for(var c=-1+b.length|0;;)if(0<=c&&36===b.charCodeAt(c))c=-1+c|0;else break;if(0<=c){var d=b.charCodeAt(c);d=48<=d&&57>=d}else d=!1;if(d){for(c=-1+c|0;;)if(0<=c?(d=b.charCodeAt(c),d=48<=d&&57>=d):d=!1,d)c=-1+c|0;else break;for(;;)if(0<=c&&36===b.charCodeAt(c))c=-1+c|0;else break}for(;;)if(0<=c?(d=b.charCodeAt(c),d=46!==d&&36!==d):d=!1,d)c=-1+c|0;else break;b=b.substring(1+c|0)}a.$J=b}return a.$J}\nfunction bg(a){return a.qi.getComponentType()}nd.prototype.$classData=q({W0:0},!1,\"java.lang.Class\",{W0:1,g:1});function cg(){this.dK=this.cK=this.Dt=this.qB=null;this.bK=!1;this.BQ=this.AQ=0;dg=this;this.qB=new ArrayBuffer(8);this.Dt=new Int32Array(this.qB,0,2);this.cK=new Float32Array(this.qB,0,2);this.dK=new Float64Array(this.qB,0,1);this.Dt[0]=16909060;this.AQ=(this.bK=1===((new Int8Array(this.qB,0,8))[0]|0))?0:1;this.BQ=this.bK?1:0}cg.prototype=new p;cg.prototype.constructor=cg;\nfunction ig(a,b){var c=b|0;if(c===b&&-Infinity!==1/b)return c;a.dK[0]=b;return(a.Dt[0]|0)^(a.Dt[1]|0)}function jg(a,b){a.Dt[0]=b;return Math.fround(a.cK[0])}function kg(a,b){a.cK[0]=b;return a.Dt[0]|0}function lg(a,b){a.dK[0]=b;return new ma(a.Dt[a.BQ]|0,a.Dt[a.AQ]|0)}cg.prototype.$classData=q({a1:0},!1,\"java.lang.FloatingPointBits$\",{a1:1,g:1});var dg;function mg(){dg||(dg=new cg);return dg}function pg(a,b,c,d){this.j1=a;this.DQ=b;this.l1=c;this.k1=d}pg.prototype=new p;pg.prototype.constructor=pg;\npg.prototype.$classData=q({i1:0},!1,\"java.lang.Long$StringRadixInfo\",{i1:1,g:1});function qg(){}qg.prototype=new p;qg.prototype.constructor=qg;qg.prototype.$classData=q({m1:0},!1,\"java.lang.Math$\",{m1:1,g:1});var rg;\nfunction sg(a,b){var c=tg(a);if(ug().ny.call(c,b))a=tg(a)[b];else a:for(c=0;;)if(c<(Dg(a).length|0)){var d=Dg(a)[c];if(0<=b.length&&b.substring(0,d.length)===d){a=\"\"+Eg(a)[d]+b.substring(d.length);break a}c=1+c|0}else{a=0<=b.length&&\"L\"===b.substring(0,1)?b.substring(1):b;break a}return a.split(\"_\").join(\".\").split(\"\\uff3f\").join(\"_\")}\nfunction tg(a){if(0===(1&a.ln)<<24>>24&&0===(1&a.ln)<<24>>24){for(var b={O:\"java_lang_Object\",T:\"java_lang_String\"},c=0;22>=c;)2<=c&&(b[\"T\"+c]=\"scala_Tuple\"+c),b[\"F\"+c]=\"scala_Function\"+c,c=1+c|0;a.FQ=b;a.ln=(1|a.ln)<<24>>24}return a.FQ}\nfunction Eg(a){0===(2&a.ln)<<24>>24&&0===(2&a.ln)<<24>>24&&(a.GQ={sjsr_:\"scala_scalajs_runtime_\",sjs_:\"scala_scalajs_\",sci_:\"scala_collection_immutable_\",scm_:\"scala_collection_mutable_\",scg_:\"scala_collection_generic_\",sc_:\"scala_collection_\",sr_:\"scala_runtime_\",s_:\"scala_\",jl_:\"java_lang_\",ju_:\"java_util_\"},a.ln=(2|a.ln)<<24>>24);return a.GQ}function Dg(a){0===(4&a.ln)<<24>>24&&0===(4&a.ln)<<24>>24&&(a.EQ=Object.keys(Eg(a)),a.ln=(4|a.ln)<<24>>24);return a.EQ}\nfunction Fg(a){return(a.stack+\"\\n\").replace(Gg(\"^[\\\\s\\\\S]+?\\\\s+at\\\\s+\"),\" at \").replace(Rg(\"^\\\\s+(at eval )?at\\\\s+\",\"gm\"),\"\").replace(Rg(\"^([^\\\\(]+?)([\\\\n])\",\"gm\"),\"{anonymous}() ($1)$2\").replace(Rg(\"^Object.\\x3canonymous\\x3e\\\\s*\\\\(([^\\\\)]+)\\\\)\",\"gm\"),\"{anonymous}() ($1)\").replace(Rg(\"^([^\\\\(]+|\\\\{anonymous\\\\}\\\\(\\\\)) \\\\((.+)\\\\)$\",\"gm\"),\"$1@$2\").split(\"\\n\").slice(0,-1)}\nfunction Sg(a){var b=Rg(\"Line (\\\\d+).*script (?:in )?(\\\\S+)\",\"i\");a=a.message.split(\"\\n\");for(var c=[],d=2,e=a.length|0;d<e;){var g=b.exec(a[d]);null!==g&&c.push(\"{anonymous}()@\"+g[2]+\":\"+g[1]);d=2+d|0}return c}function Tg(){this.EQ=this.GQ=this.FQ=null;this.ln=0}Tg.prototype=new p;Tg.prototype.constructor=Tg;Tg.prototype.$classData=q({r1:0},!1,\"java.lang.StackTrace$\",{r1:1,g:1});var Ug;function Vg(){}Vg.prototype=new p;Vg.prototype.constructor=Vg;\nfunction Gg(a){Wg||(Wg=new Vg);return new RegExp(a)}function Rg(a,b){Wg||(Wg=new Vg);return new RegExp(a,b)}Vg.prototype.$classData=q({s1:0},!1,\"java.lang.StackTrace$StringRE$\",{s1:1,g:1});var Wg;function Xg(){this.HQ=this.IQ=null;Yg=this;this.IQ=new Zg(!1);this.HQ=new Zg(!0)}Xg.prototype=new p;Xg.prototype.constructor=Xg;Xg.prototype.$classData=q({y1:0},!1,\"java.lang.System$Streams$\",{y1:1,g:1});var Yg;function ch(){Yg||(Yg=new Xg);return Yg}\nfunction dh(){this.JQ=this.fK=null;eh=this;var a={\"java.version\":\"1.8\",\"java.vm.specification.version\":\"1.8\",\"java.vm.specification.vendor\":\"Oracle Corporation\",\"java.vm.specification.name\":\"Java Virtual Machine Specification\",\"java.vm.name\":\"Scala.js\"};a[\"java.vm.version\"]=aaa.linkerVersion;a[\"java.specification.version\"]=\"1.8\";a[\"java.specification.vendor\"]=\"Oracle Corporation\";a[\"java.specification.name\"]=\"Java Platform API Specification\";a[\"file.separator\"]=\"/\";a[\"path.separator\"]=\":\";a[\"line.separator\"]=\n\"\\n\";this.fK=a;this.JQ=null}dh.prototype=new p;dh.prototype.constructor=dh;function fh(a,b,c){return null!==a.fK?(a=a.fK,ug().ny.call(a,b)?a[b]:c):fh(a.JQ,b,c)}dh.prototype.$classData=q({z1:0},!1,\"java.lang.System$SystemProperties$\",{z1:1,g:1});var eh;function gh(){eh||(eh=new dh);return eh}function hh(){this.ny=null;oh=this;this.ny=Object.prototype.hasOwnProperty}hh.prototype=new p;hh.prototype.constructor=hh;hh.prototype.$classData=q({B1:0},!1,\"java.lang.Utils$Cache$\",{B1:1,g:1});var oh;\nfunction ug(){oh||(oh=new hh);return oh}function ph(a){return!!(a&&a.$classData&&1===a.$classData.gy&&a.$classData.fy.rb.NQ)}var la=q({NQ:0},!1,\"java.lang.Void\",{NQ:1,g:1},a=>void 0===a);function qh(){}qh.prototype=new p;qh.prototype.constructor=qh;function rh(a,b,c){return b.qi.newArrayOfThisClass([c])}qh.prototype.$classData=q({C1:0},!1,\"java.lang.reflect.Array$\",{C1:1,g:1});var sh;function th(){sh||(sh=new qh);return sh}function uh(a,b){this.nM=a;this.oM=b}uh.prototype=new p;\nuh.prototype.constructor=uh;uh.prototype.$classData=q({ET:0},!1,\"java.math.BigInteger$QuotAndRem\",{ET:1,g:1});function xh(){}xh.prototype=new p;xh.prototype.constructor=xh;function yh(a,b){if(0===b.Ya)return 0;a=b.wb<<5;var c=b.Qa.a[-1+b.wb|0];0>b.Ya&&zh(b)===(-1+b.wb|0)&&(c=-1+c|0);return a=a-Math.clz32(c)|0}function Fh(a,b,c){a=c>>5;c&=31;var d=(b.wb+a|0)+(0===c?0:1)|0,e=new Xc(d);Gh(0,e,b.Qa,a,c);b=Hh(b.Ya,d,e);Ih(b);return b}\nfunction Gh(a,b,c,d,e){if(0===e)c.wa(0,b,d,b.a.length-d|0);else{a=32-e|0;b.a[-1+b.a.length|0]=0;for(var g=-1+b.a.length|0;g>d;){var h=g;b.a[h]=b.a[h]|c.a[-1+(g-d|0)|0]>>>a|0;b.a[-1+g|0]=c.a[-1+(g-d|0)|0]<<e;g=-1+g|0}}for(c=0;c<d;)b.a[c]=0,c=1+c|0}function Nh(a,b,c,d){for(var e=a=0;e<d;){var g=e,h=c.a[g];b.a[g]=h<<1|a;a=h>>>31|0;e=1+e|0}0!==a&&(b.a[d]=a)}\nfunction Oh(a,b,c){a=c>>5;var d=31&c;if(a>=b.wb)return 0>b.Ya?Ph().MC:Ph().nq;c=b.wb-a|0;var e=new Xc(1+c|0);Qh(0,e,c,b.Qa,a,d);if(0>b.Ya){for(var g=0;g<a&&0===b.Qa.a[g];)g=1+g|0;var h=0!==b.Qa.a[g]<<(32-d|0);if(g<a||0<d&&h){for(g=0;g<c&&-1===e.a[g];)e.a[g]=0,g=1+g|0;g===c&&(c=1+c|0);a=g;e.a[a]=1+e.a[a]|0}}b=Hh(b.Ya,c,e);Ih(b);return b}\nfunction Qh(a,b,c,d,e,g){for(a=0;a<e;)a=1+a|0;if(0===g)d.wa(e,b,0,c);else{var h=32-g|0;for(a=0;a<(-1+c|0);)b.a[a]=d.a[a+e|0]>>>g|0|d.a[1+(a+e|0)|0]<<h,a=1+a|0;b.a[a]=d.a[a+e|0]>>>g|0}}xh.prototype.$classData=q({FT:0},!1,\"java.math.BitLevel$\",{FT:1,g:1});var Rh;function Sh(){Rh||(Rh=new xh);return Rh}\nfunction Th(){this.tH=this.uH=null;Uh=this;this.uH=new Xc(new Int32Array([-1,-1,31,19,15,13,11,11,10,9,9,8,8,8,8,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5]));this.tH=new Xc(new Int32Array([-2147483648,1162261467,1073741824,1220703125,362797056,1977326743,1073741824,387420489,1E9,214358881,429981696,815730721,1475789056,170859375,268435456,410338673,612220032,893871739,128E7,1801088541,113379904,148035889,191102976,244140625,308915776,387420489,481890304,594823321,729E6,887503681,1073741824,1291467969,\n1544804416,1838265625,60466176]))}Th.prototype=new p;Th.prototype.constructor=Th;\nfunction Vh(a,b){a=b.Ya;var c=b.wb,d=b.Qa;if(0===a)return\"0\";if(1===c)return b=(+(d.a[0]>>>0)).toString(10),0>a?\"-\"+b:b;b=\"\";var e=new Xc(c);for(d.wa(0,e,0,c);;){var g=0;for(d=-1+c|0;0<=d;){var h=g;g=e.a[d];var k=Wh(xa(),g,h,1E9,0);e.a[d]=k;h=k>>31;var l=65535&k;k=k>>>16|0;var m=Math.imul(51712,l);l=Math.imul(15258,l);var n=Math.imul(51712,k);m=m+((l+n|0)<<16)|0;Math.imul(1E9,h);Math.imul(15258,k);g=g-m|0;d=-1+d|0}d=\"\"+g;for(b=\"000000000\".substring(d.length)+d+b;0!==c&&0===e.a[-1+c|0];)c=-1+c|0;if(0===\nc)break}e=0;for(c=b.length;;)if(e<c&&48===b.charCodeAt(e))e=1+e|0;else break;b=b.substring(e);return 0>a?\"-\"+b:b}\nfunction waa(a,b,c){if(0===b.W&&0===b.Y)switch(c){case 0:return\"0\";case 1:return\"0.0\";case 2:return\"0.00\";case 3:return\"0.000\";case 4:return\"0.0000\";case 5:return\"0.00000\";case 6:return\"0.000000\";default:return(0>c?\"0E+\":\"0E\")+(-2147483648===c?\"2147483648\":\"\"+(-c|0))}else{a=0>b.Y;var d=\"\";var e=18;if(a){var g=b.W;b=b.Y;b=new ma(-g|0,0!==g?~b:-b|0)}g=b.W;for(var h=b.Y;;){b=g;var k=h;h=xa();g=$h(h,g,k,10,0);h=h.Qc;e=-1+e|0;k=h;var l=g,m=l>>>16|0;l=Math.imul(10,65535&l);m=Math.imul(10,m);m=l+(m<<16)|\n0;Math.imul(10,k);d=\"\"+(b-m|0)+d;b=h;if(0===g&&0===b)break}g=18-e|0;h=g>>31;k=c>>31;b=g-c|0;g=(-2147483648^b)>(-2147483648^g)?-1+(h-k|0)|0:h-k|0;b=-1+b|0;g=-1!==b?g:-1+g|0;if(0<c&&(-1===g?2147483642<=(-2147483648^b):-1<g))if(c=1+b|0,0<c)d=d.substring(0,c)+\".\"+d.substring(c);else{c=-c|0;for(e=0;e<c;)d=\"0\"+d,e=1+e|0;d=\"0.\"+d}else 0!==c&&(c=(0===g?0!==b:0<g)?\"E+\"+new ma(b,g):\"E\"+new ma(b,g),d=1<(18-e|0)?d.substring(0,1)+\".\"+d.substring(1)+c:d+c);return a?\"-\"+d:d}}\nTh.prototype.$classData=q({GT:0},!1,\"java.math.Conversion$\",{GT:1,g:1});var Uh;function bi(){Uh||(Uh=new Th);return Uh}function ci(){}ci.prototype=new p;ci.prototype.constructor=ci;\nfunction di(a,b,c,d,e,g,h){a=new Xc(1+e|0);var k=new Xc(1+h|0),l=Math.clz32(g.a[-1+h|0]);0!==l?(Gh(Sh(),k,g,0,l),Gh(Sh(),a,d,0,l)):(d.wa(0,a,0,e),g.wa(0,k,0,h));d=k.a[-1+h|0];for(c=-1+c|0;0<=c;){if(a.a[e]===d)g=-1;else{var m=a.a[e],n=a.a[-1+e|0];g=xa();var r=Wh(g,n,m,d,0);m=g.Qc;g=r;var v=65535&r;r=r>>>16|0;var x=65535&d,A=d>>>16|0,B=Math.imul(v,x);x=Math.imul(r,x);v=Math.imul(v,A);v=B+((x+v|0)<<16)|0;Math.imul(m,d);Math.imul(r,A);n=n-v|0;if(0!==g)for(g=1+g|0;;){r=g=-1+g|0;A=k.a[-2+h|0];m=65535&r;\nr=r>>>16|0;B=65535&A;A=A>>>16|0;v=Math.imul(m,B);B=Math.imul(r,B);x=Math.imul(m,A);m=v+((B+x|0)<<16)|0;v=(v>>>16|0)+x|0;v=(Math.imul(r,A)+(v>>>16|0)|0)+(((65535&v)+B|0)>>>16|0)|0;A=n;r=a.a[-2+e|0];B=n+d|0;if(0===((-2147483648^B)<(-2147483648^n)?1:0)&&(n=B,v^=-2147483648,A^=-2147483648,v===A?(-2147483648^m)>(-2147483648^r):v>A))continue;break}}if(n=0!==g){ei();n=a;m=e-h|0;A=k;r=h;v=g;var C=0;var D;for(B=D=0;B<r;){x=B;fi();var F=A.a[x],I=65535&F;F=F>>>16|0;var M=65535&v,N=v>>>16|0,P=Math.imul(I,M);\nM=Math.imul(F,M);var T=Math.imul(I,N);I=P+((M+T|0)<<16)|0;P=(P>>>16|0)+T|0;N=(Math.imul(F,N)+(P>>>16|0)|0)+(((65535&P)+M|0)>>>16|0)|0;F=I+C|0;C=(-2147483648^F)<(-2147483648^I)?1+N|0:N;N=n.a[m+x|0];F=N-F|0;N=(-2147483648^F)>(-2147483648^N)?-1:0;I=D;D=I>>31;I=F+I|0;D=(-2147483648^I)<(-2147483648^F)?1+(N+D|0)|0:N+D|0;n.a[m+x|0]=I;B=1+B|0}v=n.a[m+r|0];A=v-C|0;v=(-2147483648^A)>(-2147483648^v)?-1:0;x=D;B=x>>31;x=A+x|0;n.a[m+r|0]=x;n=0!==((-2147483648^x)<(-2147483648^A)?1+(v+B|0)|0:v+B|0)}if(n)for(g=-1+\ng|0,n=B=v=0;n<h;)m=n,A=a.a[(e-h|0)+m|0],r=A+k.a[m]|0,A=(-2147483648^r)<(-2147483648^A)?1:0,r=v+r|0,A=(-2147483648^r)<(-2147483648^v)?1+(B+A|0)|0:B+A|0,v=r,B=A,a.a[(e-h|0)+m|0]=v,v=B,B=0,n=1+n|0;null!==b&&(b.a[c]=g);e=-1+e|0;c=-1+c|0}if(0!==l)return Qh(Sh(),k,h,a,0,l),k;a.wa(0,k,0,h);return a}\nfunction gi(a,b,c,d,e){a=0;for(d=-1+d|0;0<=d;){var g=a;a=c.a[d];var h=xa();g=Wh(h,a,g,e,0);h=h.Qc;var k=65535&g,l=g>>>16|0,m=65535&e,n=e>>>16|0,r=Math.imul(k,m);m=Math.imul(l,m);k=Math.imul(k,n);r=r+((m+k|0)<<16)|0;Math.imul(h,e);Math.imul(l,n);a=a-r|0;b.a[d]=g;d=-1+d|0}return a}ci.prototype.$classData=q({HT:0},!1,\"java.math.Division$\",{HT:1,g:1});var hi;function ei(){hi||(hi=new ci);return hi}\nfunction ii(a,b,c,d){var e=new Xc(1+b|0),g=1,h=a.a[0],k=h+c.a[0]|0;e.a[0]=k;h=(-2147483648^k)<(-2147483648^h)?1:0;if(b>=d){for(;g<d;){var l=a.a[g];k=l+c.a[g]|0;l=(-2147483648^k)<(-2147483648^l)?1:0;h=k+h|0;k=(-2147483648^h)<(-2147483648^k)?1+l|0:l;e.a[g]=h;h=k;g=1+g|0}for(;g<b;)c=a.a[g],d=c+h|0,c=(-2147483648^d)<(-2147483648^c)?1:0,e.a[g]=d,h=c,g=1+g|0}else{for(;g<b;)l=a.a[g],k=l+c.a[g]|0,l=(-2147483648^k)<(-2147483648^l)?1:0,h=k+h|0,k=(-2147483648^h)<(-2147483648^k)?1+l|0:l,e.a[g]=h,h=k,g=1+g|0;\nfor(;g<d;)a=c.a[g],b=a+h|0,a=(-2147483648^b)<(-2147483648^a)?1:0,e.a[g]=b,h=a,g=1+g|0}0!==h&&(e.a[g]=h);return e}function ji(a,b,c,d){for(var e=new Xc(b),g=0,h=0;g<d;){var k=a.a[g],l=k-c.a[g]|0;k=(-2147483648^l)>(-2147483648^k)?-1:0;var m=h;h=m>>31;m=l+m|0;l=(-2147483648^m)<(-2147483648^l)?1+(k+h|0)|0:k+h|0;e.a[g]=m;h=l;g=1+g|0}for(;g<b;)c=a.a[g],l=h,d=l>>31,l=c+l|0,c=(-2147483648^l)<(-2147483648^c)?1+d|0:d,e.a[g]=l,h=c,g=1+g|0;return e}function ki(){}ki.prototype=new p;ki.prototype.constructor=ki;\nfunction li(a,b,c){a=b.Ya;var d=c.Ya,e=b.wb,g=c.wb;if(0===a)return c;if(0===d)return b;if(2===(e+g|0)){b=b.Qa.a[0];c=c.Qa.a[0];if(a===d)return d=b+c|0,c=(-2147483648^d)<(-2147483648^b)?1:0,0===c?qi(a,d):Hh(a,2,new Xc(new Int32Array([d,c])));d=Ph();0>a?(a=b=c-b|0,c=(-2147483648^b)>(-2147483648^c)?-1:0):(a=c=b-c|0,c=(-2147483648^c)>(-2147483648^b)?-1:0);return ri(d,new ma(a,c))}if(a===d)d=e>=g?ii(b.Qa,e,c.Qa,g):ii(c.Qa,g,b.Qa,e);else{var h=e!==g?e>g?1:-1:si(0,b.Qa,c.Qa,e);if(0===h)return Ph().nq;1===\nh?d=ji(b.Qa,e,c.Qa,g):(c=ji(c.Qa,g,b.Qa,e),a=d,d=c)}a=Hh(a|0,d.a.length,d);Ih(a);return a}function si(a,b,c,d){for(a=-1+d|0;0<=a&&b.a[a]===c.a[a];)a=-1+a|0;return 0>a?0:(-2147483648^b.a[a])<(-2147483648^c.a[a])?-1:1}\nfunction ti(a,b,c){var d=b.Ya;a=c.Ya;var e=b.wb,g=c.wb;if(0===a)return b;if(0===d)return ui(c);if(2===(e+g|0))return b=b.Qa.a[0],e=0,c=c.Qa.a[0],g=0,0>d&&(d=b,b=-d|0,e=0!==d?~e:-e|0),0>a&&(a=c,d=g,c=-a|0,g=0!==a?~d:-d|0),a=Ph(),d=b,b=e,e=g,c=d-c|0,ri(a,new ma(c,(-2147483648^c)>(-2147483648^d)?-1+(b-e|0)|0:b-e|0));var h=e!==g?e>g?1:-1:si(vi(),b.Qa,c.Qa,e);if(d===a&&0===h)return Ph().nq;-1===h?(c=d===a?ji(c.Qa,g,b.Qa,e):ii(c.Qa,g,b.Qa,e),a=-a|0):d===a?(c=ji(b.Qa,e,c.Qa,g),a=d):(c=ii(b.Qa,e,c.Qa,g),\na=d);a=Hh(a|0,c.a.length,c);Ih(a);return a}ki.prototype.$classData=q({IT:0},!1,\"java.math.Elementary$\",{IT:1,g:1});var wi;function vi(){wi||(wi=new ki);return wi}function xi(a,b){this.ds=a;this.Fw=b}xi.prototype=new p;xi.prototype.constructor=xi;xi.prototype.i=function(a){return a instanceof xi?this.ds===a.ds?this.Fw===a.Fw:!1:!1};xi.prototype.B=function(){return this.ds<<3|this.Fw.NF};xi.prototype.u=function(){return\"precision\\x3d\"+this.ds+\" roundingMode\\x3d\"+this.Fw};\nxi.prototype.$classData=q({JT:0},!1,\"java.math.MathContext\",{JT:1,g:1});function yi(){this.qM=null;zi=this;Ai();var a=Bi().OC;this.qM=new xi(34,a);Ai();Bi();Ai();Bi();Ai();Bi()}yi.prototype=new p;yi.prototype.constructor=yi;yi.prototype.$classData=q({KT:0},!1,\"java.math.MathContext$\",{KT:1,g:1});var zi;function Ai(){zi||(zi=new yi);return zi}\nfunction Fi(a,b,c,d){for(var e,g=e=0;g<c;){var h=g;fi();var k=b.a[h],l=65535&k;k=k>>>16|0;var m=65535&d,n=d>>>16|0,r=Math.imul(l,m);m=Math.imul(k,m);var v=Math.imul(l,n);l=r+((m+v|0)<<16)|0;r=(r>>>16|0)+v|0;k=(Math.imul(k,n)+(r>>>16|0)|0)+(((65535&r)+m|0)>>>16|0)|0;e=l+e|0;k=(-2147483648^e)<(-2147483648^l)?1+k|0:k;a.a[h]=e;e=k;g=1+g|0}return e}function Gi(a,b){for(var c=new Xc(a),d=c.a[0]=1;d<a;){var e=d;c.a[e]=Math.imul(c.a[-1+e|0],b);d=1+d|0}}\nfunction Hi(){this.es=this.fs=null;Ii=this;Gi(10,10);Gi(14,5);this.fs=new (md(Ji).Ia)(32);this.es=new (md(Ji).Ia)(32);var a;var b=1;for(var c=a=0;32>c;){var d=c;if(18>=d){fi().es.a[d]=ri(Ph(),new ma(b,a));var e=fi().fs,g=Ph(),h=a,k=b;e.a[d]=ri(g,new ma(0===(32&d)?k<<d:0,0===(32&d)?(k>>>1|0)>>>(31-d|0)|0|h<<d:k<<d));d=b;b=d>>>16|0;d=Math.imul(5,65535&d);e=Math.imul(5,b);b=d+(e<<16)|0;d=(d>>>16|0)+e|0;a=Math.imul(5,a)+(d>>>16|0)|0}else fi().es.a[d]=Ki(fi().es.a[-1+d|0],fi().es.a[1]),fi().fs.a[d]=Ki(fi().fs.a[-1+\nd|0],Ph().mq);c=1+c|0}}Hi.prototype=new p;Hi.prototype.constructor=Hi;\nfunction Li(a,b,c){for(var d,e=0;e<b;){var g=e;d=0;for(var h=1+g|0;h<b;){fi();var k=a.a[g],l=a.a[h],m=c.a[g+h|0],n=d,r=65535&k;d=k>>>16|0;var v=65535&l;l=l>>>16|0;k=Math.imul(r,v);v=Math.imul(d,v);var x=Math.imul(r,l);r=k+((v+x|0)<<16)|0;k=(k>>>16|0)+x|0;d=(Math.imul(d,l)+(k>>>16|0)|0)+(((65535&k)+v|0)>>>16|0)|0;m=r+m|0;d=(-2147483648^m)<(-2147483648^r)?1+d|0:d;n=m+n|0;m=(-2147483648^n)<(-2147483648^m)?1+d|0:d;c.a[g+h|0]=n;d=m;h=1+h|0}c.a[g+b|0]=d;e=1+e|0}Nh(Sh(),c,c,b<<1);for(g=e=d=0;e<b;)m=a.a[e],\nr=a.a[e],n=c.a[g],h=d,l=65535&m,m=m>>>16|0,k=65535&r,d=r>>>16|0,r=Math.imul(l,k),k=Math.imul(m,k),v=Math.imul(l,d),l=r+((k+v|0)<<16)|0,r=(r>>>16|0)+v|0,m=(Math.imul(m,d)+(r>>>16|0)|0)+(((65535&r)+k|0)>>>16|0)|0,n=l+n|0,m=(-2147483648^n)<(-2147483648^l)?1+m|0:m,h=n+h|0,n=(-2147483648^h)<(-2147483648^n)?1+m|0:m,c.a[g]=h,g=1+g|0,h=n+c.a[g]|0,n=(-2147483648^h)<(-2147483648^n)?1:0,c.a[g]=h,d=n,e=1+e|0,g=1+g|0;return c}\nfunction Mi(a,b,c){if(c.wb>b.wb)var d=c;else d=b,b=c;var e=d,g=b;if(63>g.wb){d=e.wb;b=g.wb;c=d+b|0;a=e.Ya!==g.Ya?-1:1;if(2===c){d=e.Qa.a[0];b=g.Qa.a[0];c=65535&d;d=d>>>16|0;g=65535&b;b=b>>>16|0;e=Math.imul(c,g);g=Math.imul(d,g);var h=Math.imul(c,b);c=e+((g+h|0)<<16)|0;e=(e>>>16|0)+h|0;d=(Math.imul(d,b)+(e>>>16|0)|0)+(((65535&e)+g|0)>>>16|0)|0;a=0===d?qi(a,c):Hh(a,2,new Xc(new Int32Array([c,d])))}else{e=e.Qa;g=g.Qa;h=new Xc(c);if(0!==d&&0!==b)if(1===d)h.a[b]=Fi(h,g,b,e.a[0]);else if(1===b)h.a[d]=Fi(h,\ne,d,g.a[0]);else if(e===g&&d===b)Li(e,d,h);else for(var k=0;k<d;){for(var l=k,m=0,n=e.a[l],r=0;r<b;){fi();var v=g.a[r],x=h.a[l+r|0],A=65535&n,B=n>>>16|0,C=65535&v;v=v>>>16|0;var D=Math.imul(A,C);C=Math.imul(B,C);var F=Math.imul(A,v);A=D+((C+F|0)<<16)|0;D=(D>>>16|0)+F|0;B=(Math.imul(B,v)+(D>>>16|0)|0)+(((65535&D)+C|0)>>>16|0)|0;x=A+x|0;B=(-2147483648^x)<(-2147483648^A)?1+B|0:B;m=x+m|0;x=(-2147483648^m)<(-2147483648^x)?1+B|0:B;h.a[l+r|0]=m;m=x;r=1+r|0}h.a[l+b|0]=m;k=1+k|0}a=Hh(a,c,h);Ih(a)}return a}d=\n(-2&e.wb)<<4;c=Ni(e,d);h=Ni(g,d);b=Oi(c,d);k=ti(vi(),e,b);b=Oi(h,d);g=ti(vi(),g,b);e=Mi(a,c,h);b=Mi(a,k,g);a=Mi(a,ti(vi(),c,k),ti(vi(),g,h));c=e;a=li(vi(),a,c);a=li(vi(),a,b);a=Oi(a,d);d=e=Oi(e,d<<1);a=li(vi(),d,a);return li(vi(),a,b)}\nfunction Pi(a,b){var c=a.fs.a.length,d=c>>31,e=b.Y;if(e===d?(-2147483648^b.W)<(-2147483648^c):e<d)return a.fs.a[b.W];c=b.Y;if(0===c?-2147483598>=(-2147483648^b.W):0>c)return Qi(Ph().mq,b.W);c=b.Y;if(0===c?-1>=(-2147483648^b.W):0>c)return Oi(Qi(a.es.a[1],b.W),b.W);var g=Qi(a.es.a[1],2147483647);c=g;e=b.Y;var h=-2147483647+b.W|0;d=h;h=1>(-2147483648^h)?e:-1+e|0;for(e=Ri(xa(),b.W,b.Y,2147483647,0);;){var k=d,l=h;if(0===l?-1<(-2147483648^k):0<l)c=Ki(c,g),d=-2147483647+d|0,h=1>(-2147483648^d)?h:-1+h|0;\nelse break}c=Ki(c,Qi(a.es.a[1],e));c=Oi(c,2147483647);a=b.Y;d=b=-2147483647+b.W|0;for(h=1>(-2147483648^b)?a:-1+a|0;;)if(b=d,a=h,0===a?-1<(-2147483648^b):0<a)c=Oi(c,2147483647),b=h,a=-2147483647+d|0,b=1>(-2147483648^a)?b:-1+b|0,d=a,h=b;else break;return Oi(c,e)}Hi.prototype.$classData=q({LT:0},!1,\"java.math.Multiplication$\",{LT:1,g:1});var Ii;function fi(){Ii||(Ii=new Hi);return Ii}function Si(){}Si.prototype=new p;Si.prototype.constructor=Si;\nfunction Ti(a,b){var c=Ui(),d=Ui(),e=b.a.length;16<e?Vi(a,b,new Xc(b.a.length),0,e,c,d):Zi(b,0,e,c,d)}function $i(a,b){var c=aj(),d=aj(),e=b.a.length;16<e?Vi(a,b,new Zc(b.a.length),0,e,c,d):Zi(b,0,e,c,d)}function bj(a,b){var c=cj(),d=cj(),e=b.a.length;16<e?Vi(a,b,new Sc(b.a.length),0,e,c,d):Zi(b,0,e,c,d)}function dj(a,b){var c=ej(),d=ej(),e=b.a.length;16<e?Vi(a,b,new Ic(b.a.length),0,e,c,d):Zi(b,0,e,c,d)}\nfunction fj(a,b){var c=gj(),d=gj(),e=b.a.length;16<e?Vi(a,b,new Pc(b.a.length),0,e,c,d):Zi(b,0,e,c,d)}function hj(a,b,c){c=null===c?ij():c;var d=jj(),e=b.a.length;if(16<e){var g=b.a.length,h=ca(b);Vi(a,b,rh(th(),bg(h),g),0,e,c,d)}else Zi(b,0,e,c,d)}\nfunction Vi(a,b,c,d,e,g,h){var k=e-d|0;if(16<k){var l=d+(k/2|0)|0;Vi(a,b,c,d,l,g,h);Vi(a,b,c,l,e,g,h);for(var m=a=d,n=l;a<e;)m<l&&(n>=e||0>=g.Da(h.Wj(b,m),h.Wj(b,n)))?(h.Qo(c,a,h.Wj(b,m)),m=1+m|0):(h.Qo(c,a,h.Wj(b,n)),n=1+n|0),a=1+a|0;c.wa(d,b,d,k)}else Zi(b,d,e,g,h)}\nfunction Zi(a,b,c,d,e){c=c-b|0;if(2<=c){var g=e.Wj(a,b),h=e.Wj(a,1+b|0);0<d.Da(g,h)&&(e.Qo(a,b,h),e.Qo(a,1+b|0,g));for(g=2;g<c;){h=e.Wj(a,b+g|0);if(0>d.Da(h,e.Wj(a,-1+(b+g|0)|0))){for(var k=b,l=-1+(b+g|0)|0;1<(l-k|0);){var m=(k+l|0)>>>1|0;0>d.Da(h,e.Wj(a,m))?l=m:k=m}k=k+(0>d.Da(h,e.Wj(a,k))?0:1)|0;for(l=b+g|0;l>k;)e.Qo(a,l,e.Wj(a,-1+l|0)),l=-1+l|0;e.Qo(a,k,h)}g=1+g|0}}}\nfunction kj(a,b,c){a=0;for(var d=b.a.length;;){if(a===d)return-1-a|0;var e=(a+d|0)>>>1|0,g=b.a[e];g=c===g?0:c<g?-1:1;if(0>g)d=e;else{if(0===g)return e;a=1+e|0}}}function pj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){var e=b.a[d],g=c.a[d],h=g.Y;if(e.W!==g.W||e.Y!==h)return!1;d=1+d|0}return!0}\nfunction qj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){if(b.a[d]!==c.a[d])return!1;d=1+d|0}return!0}function sj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){if(b.a[d]!==c.a[d])return!1;d=1+d|0}return!0}\nfunction tj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){if(b.a[d]!==c.a[d])return!1;d=1+d|0}return!0}function uj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){if(b.a[d]!==c.a[d])return!1;d=1+d|0}return!0}\nfunction vj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){if(b.a[d]!==c.a[d])return!1;d=1+d|0}return!0}function wj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){if(!Object.is(b.a[d],c.a[d]))return!1;d=1+d|0}return!0}\nfunction xj(a,b,c){if(b===c)return!0;if(null===b||null===c)return!1;a=b.a.length;if(c.a.length!==a)return!1;for(var d=0;d!==a;){if(!Object.is(b.a[d],c.a[d]))return!1;d=1+d|0}return!0}function yj(a,b,c){a=b.a.length;for(var d=0;d!==a;)b.a[d]=c,d=1+d|0}function zj(a,b,c){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;var d=ca(b);c=rh(th(),bg(d),c);b.wa(0,c,0,a);return c}function Cj(a,b,c,d){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;c=rh(th(),bg(d),c);b.wa(0,c,0,a);return c}\nfunction Dj(a,b,c){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;c=new Pc(c);b.wa(0,c,0,a);return c}function Ej(a,b,c){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;c=new Sc(c);b.wa(0,c,0,a);return c}function Fj(a,b,c){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;c=new Xc(c);b.wa(0,c,0,a);return c}function Gj(a,b,c){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;c=new Zc(c);b.wa(0,c,0,a);return c}function Hj(a,b,c){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;c=new Ic(c);b.wa(0,c,0,a);return c}\nfunction Ij(a,b,c){if(0>c)throw new Aj;a=b.a.length;a=c<a?c:a;c=new Ec(c);b.wa(0,c,0,a);return c}function Jj(a,b,c,d){if(c>d)throw Kj(c+\" \\x3e \"+d);a=d-c|0;d=b.a.length-c|0;d=a<d?a:d;var e=ca(b);a=rh(th(),bg(e),a);b.wa(c,a,0,d);return a}Si.prototype.$classData=q({G1:0},!1,\"java.util.Arrays$\",{G1:1,g:1});var Lj;function Pj(){Lj||(Lj=new Si);return Lj}\nfunction Qj(){this.PQ=this.QQ=null;Rj=this;this.QQ=RegExp(\"(?:(\\\\d+)\\\\$)?([-#+ 0,\\\\(\\x3c]*)(\\\\d+)?(?:\\\\.(\\\\d+))?[%A-Za-z]\",\"g\");this.PQ=new Xc(new Int32Array([96,126,638,770,32,256,2,126,-1,-1,-1,-1,-1,-1,800,-1,-1,-1,124,-1,-1,-1,-1,544,-1,-1]))}Qj.prototype=new p;Qj.prototype.constructor=Qj;function Sj(a,b){if(20>=b)return\"00000000000000000000\".substring(0,b);for(a=\"\";20<b;)a+=\"00000000000000000000\",b=-20+b|0;return\"\"+a+\"00000000000000000000\".substring(0,b)}\nQj.prototype.$classData=q({P1:0},!1,\"java.util.Formatter$\",{P1:1,g:1});var Rj;function Tj(){Rj||(Rj=new Qj);return Rj}function Uj(a,b){var c=a.wr,d=c.length;if(0>b)return new Vj(a.Ft,\"0\",0);if(b>=d)return a;if(53>c.charCodeAt(b))return 0===b?new Vj(a.Ft,\"0\",0):new Vj(a.Ft,c.substring(0,b),a.vr-(d-b|0)|0);for(b=-1+b|0;;)if(0<=b&&57===c.charCodeAt(b))b=-1+b|0;else break;c=0>b?\"1\":\"\"+c.substring(0,b)+hc(65535&(1+c.charCodeAt(b)|0));return new Vj(a.Ft,c,a.vr-(d-(1+b|0)|0)|0)}\nfunction Vj(a,b,c){this.Ft=a;this.wr=b;this.vr=c}Vj.prototype=new p;Vj.prototype.constructor=Vj;function Wj(a,b){Tj();if(!(0<b))throw new Yj(\"Decimal.round() called with non-positive precision\");return Uj(a,b)}Vj.prototype.u=function(){return\"Decimal(\"+this.Ft+\", \"+this.wr+\", \"+this.vr+\")\"};Vj.prototype.$classData=q({Q1:0},!1,\"java.util.Formatter$Decimal\",{Q1:1,g:1});function Zj(){}Zj.prototype=new p;Zj.prototype.constructor=Zj;function ak(){}ak.prototype=Zj.prototype;function bk(a){this.py=a}\nbk.prototype=new p;bk.prototype.constructor=bk;bk.prototype.i=function(a){return a instanceof bk?Object.is(this.py,a.py):!1};bk.prototype.B=function(){return Qb(this.py)};bk.prototype.$classData=q({a2:0},!1,\"java.util.IdentityHashMap$IdentityBox\",{a2:1,g:1});function ck(a){return!!(a&&a.$classData&&a.$classData.rb.TQ)}function dk(a,b){throw new ek(b,a.ri,a.P);}function fk(a,b){for(var c=\"\",d=b.length,e=0;e!==d;){var g=gk(b,e);c=\"\"+c+hk(a,g);e=e+(65536<=g?2:1)|0}return c}\nfunction hk(a,b){var c=ik(jk(),b);if(128>b)switch(b){case 94:case 36:case 92:case 46:case 42:case 43:case 63:case 40:case 41:case 91:case 93:case 123:case 125:case 124:return\"\\\\\"+c;default:return 2!==(66&a.Ue)?c:65<=b&&90>=b?\"[\"+c+ik(jk(),32+b|0)+\"]\":97<=b&&122>=b?\"[\"+ik(jk(),-32+b|0)+c+\"]\":c}else return 56320===(-1024&b)?\"(?:\"+c+\")\":c}\nfunction kk(a){for(var b=a.ri,c=b.length;;){if(a.P!==c)switch(b.charCodeAt(a.P)){case 32:case 9:case 10:case 11:case 12:case 13:a.P=1+a.P|0;continue;case 35:lk(a);continue}break}}\nfunction xaa(a,b,c){var d=a.ri,e=d.length,g=a.P,h=g===e?46:d.charCodeAt(g);if(63===h||42===h||43===h||123===h){g=a.ri;var k=a.P;a.P=1+a.P|0;if(123===h){h=g.length;if(a.P===h)var l=!0;else l=g.charCodeAt(a.P),l=!(48<=l&&57>=l);for(l&&dk(a,\"Illegal repetition\");;)if(a.P!==h?(l=g.charCodeAt(a.P),l=48<=l&&57>=l):l=!1,l)a.P=1+a.P|0;else break;a.P===h&&dk(a,\"Illegal repetition\");if(44===g.charCodeAt(a.P))for(a.P=1+a.P|0;;)if(a.P!==h?(l=g.charCodeAt(a.P),l=48<=l&&57>=l):l=!1,l)a.P=1+a.P|0;else break;a.P!==\nh&&125===g.charCodeAt(a.P)||dk(a,\"Illegal repetition\");a.P=1+a.P|0}g=g.substring(k,a.P);if(a.P!==e)switch(d.charCodeAt(a.P)){case 43:return a.P=1+a.P|0,yaa(a,b,c,g);case 63:return a.P=1+a.P|0,\"\"+c+g+\"?\";default:return\"\"+c+g}else return\"\"+c+g}else return c}\nfunction yaa(a,b,c,d){for(var e=a.nn.length|0,g=0;g<e;){var h=g,k=a.nn[h]|0;k>b&&(a.nn[h]=1+k|0);g=1+g|0}c=c.replace(jk().dR,(l,m,n)=>{0!==(m.length%2|0)&&(n=parseInt(n,10)|0,l=n>b?\"\"+m+(1+n|0):l);return l});a.mn=1+a.mn|0;return\"(?:(?\\x3d(\"+c+d+\"))\\\\\"+(1+b|0)+\")\"}\nfunction zaa(a){var b=a.ri,c=b.length;(1+a.P|0)===c&&dk(a,\"\\\\ at end of pattern\");a.P=1+a.P|0;var d=b.charCodeAt(a.P);switch(d){case 100:case 68:case 104:case 72:case 115:case 83:case 118:case 86:case 119:case 87:case 112:case 80:switch(a=mk(a,d),b=a.nK,b){case 0:return\"\\\\p{\"+a.yr+\"}\";case 1:return\"\\\\P{\"+a.yr+\"}\";case 2:return\"[\"+a.yr+\"]\";case 3:return nk(jk(),a.yr);default:throw new Yj(b);}case 98:if(\"b{g}\"===b.substring(a.P,4+a.P|0))dk(a,\"\\\\b{g} is not supported\");else if(0!==(320&a.Ue))ok(a,\"\\\\b with UNICODE_CASE\");\nelse return a.P=1+a.P|0,\"\\\\b\";break;case 66:if(0!==(320&a.Ue))ok(a,\"\\\\B with UNICODE_CASE\");else return a.P=1+a.P|0,\"\\\\B\";break;case 65:return a.P=1+a.P|0,\"(?:^)\";case 71:dk(a,\"\\\\G in the middle of a pattern is not supported\");break;case 90:return a.P=1+a.P|0,\"(?\\x3d\"+(0!==(1&a.Ue)?\"\\n\":\"(?:\\r\\n?|[\\n\\u0085\\u2028\\u2029])\")+\"?$)\";case 122:return a.P=1+a.P|0,\"(?:$)\";case 82:return a.P=1+a.P|0,\"(?:\\r\\n|[\\n-\\r\\u0085\\u2028\\u2029])\";case 88:dk(a,\"\\\\X is not supported\");break;case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:var e=\na.P;for(d=1+e|0;;){if(d!==c){var g=b.charCodeAt(d);g=48<=g&&57>=g}else g=!1;g?(g=b.substring(e,1+d|0),g=(parseInt(g,10)|0)<=(-1+(a.nn.length|0)|0)):g=!1;if(g)d=1+d|0;else break}b=b.substring(e,d);b=parseInt(b,10)|0;b>(-1+(a.nn.length|0)|0)&&dk(a,\"numbered capturing group \\x3c\"+b+\"\\x3e does not exist\");b=a.nn[b]|0;a.P=d;return\"(?:\\\\\"+b+\")\";case 107:return a.P=1+a.P|0,a.P!==c&&60===b.charCodeAt(a.P)||dk(a,\"\\\\k is not followed by '\\x3c' for named capturing group\"),a.P=1+a.P|0,b=pk(a),d=a.$F,ug().ny.call(d,\nb)||dk(a,\"named capturing group \\x3c\"+b+\"\\x3e does not exit\"),b=a.nn[d[b]|0]|0,a.P=1+a.P|0,\"(?:\\\\\"+b+\")\";case 81:d=1+a.P|0;c=b.indexOf(\"\\\\E\",d)|0;if(0>c)return a.P=b.length,fk(a,b.substring(d));a.P=2+c|0;return fk(a,b.substring(d,c));default:return hk(a,qk(a))}}\nfunction qk(a){var b=a.ri,c=gk(b,a.P);switch(c){case 48:return Aaa(a);case 120:return b=a.ri,c=1+a.P|0,c!==b.length&&123===b.charCodeAt(c)?(c=1+c|0,b=b.indexOf(\"}\",c)|0,0>b&&dk(a,\"Unclosed hexadecimal escape sequence\"),c=rk(a,c,b,\"hexadecimal\"),a.P=1+b|0,a=c):(b=rk(a,c,2+c|0,\"hexadecimal\"),a.P=2+c|0,a=b),a;case 117:a:{b=a.ri;var d=1+a.P|0;c=4+d|0;d=rk(a,d,c,\"Unicode\");a.P=c;var e=2+c|0,g=4+e|0;if(55296===(-1024&d)&&\"\\\\u\"===b.substring(c,e)&&(b=rk(a,e,g,\"Unicode\"),56320===(-1024&b))){a.P=g;a=(64+(1023&\nd)|0)<<10|1023&b;break a}a=d}return a;case 78:dk(a,\"\\\\N is not supported\");break;case 97:return a.P=1+a.P|0,7;case 116:return a.P=1+a.P|0,9;case 110:return a.P=1+a.P|0,10;case 102:return a.P=1+a.P|0,12;case 114:return a.P=1+a.P|0,13;case 101:return a.P=1+a.P|0,27;case 99:return a.P=1+a.P|0,a.P===b.length&&dk(a,\"Illegal control escape sequence\"),b=gk(b,a.P),a.P=a.P+(65536<=b?2:1)|0,64^b;default:return(65<=c&&90>=c||97<=c&&122>=c)&&dk(a,\"Illegal/unsupported escape sequence\"),a.P=a.P+(65536<=c?2:1)|\n0,c}}function Aaa(a){var b=a.ri,c=b.length,d=a.P,e=(1+d|0)<c?-48+b.charCodeAt(1+d|0)|0:-1;(0>e||7<e)&&dk(a,\"Illegal octal escape sequence\");var g=(2+d|0)<c?-48+b.charCodeAt(2+d|0)|0:-1;if(0>g||7<g)return a.P=2+a.P|0,e;if(3<e)return a.P=3+a.P|0,(e<<3)+g|0;b=(3+d|0)<c?-48+b.charCodeAt(3+d|0)|0:-1;if(0>b||7<b)return a.P=3+a.P|0,(e<<3)+g|0;a.P=4+a.P|0;return((e<<6)+(g<<3)|0)+b|0}\nfunction rk(a,b,c,d){var e=a.ri,g=e.length;(b===c||c>g)&&dk(a,\"Illegal \"+d+\" escape sequence\");for(g=b;g<c;){var h=e.charCodeAt(g);48<=h&&57>=h||65<=h&&70>=h||97<=h&&102>=h||dk(a,\"Illegal \"+d+\" escape sequence\");g=1+g|0}6<(c-b|0)?b=1114112:(b=e.substring(b,c),b=parseInt(b,16)|0);1114111<b&&dk(a,\"Hexadecimal codepoint is too big\");return b}\nfunction mk(a,b){a.P=1+a.P|0;switch(b){case 100:case 68:a=jk().YQ;break;case 104:case 72:a=jk().aR;break;case 115:case 83:a=jk().ZQ;break;case 118:case 86:a=jk().bR;break;case 119:case 87:a=jk().$Q;break;case 112:case 80:var c=a.ri,d=a.P;if(d===c.length)c=\"?\";else if(123===c.charCodeAt(d)){d=1+d|0;var e=c.indexOf(\"}\",d)|0;0>e&&dk(a,\"Unclosed character family\");a.P=e;c=c.substring(d,e)}else c=c.substring(d,1+d|0);d=jk().qK;ug().ny.call(d,c)||ok(a,\"Unicode character family\");c=2!==(66&a.Ue)||\"Lower\"!==\nc&&\"Upper\"!==c?c:\"Alpha\";c=jk().qK[c];a.P=1+a.P|0;a=c;break;default:throw new Yj(hc(b));}97<=b?b=a:a.mK?b=a.oK:(b=a,b.mK||(b.oK=new sk(1^b.nK,b.yr),b.mK=!0),b=b.oK);return b}\nvar Caa=function Baa(a){var c=a.ri,d=c.length;a.P=1+a.P|0;var e=a.P!==d?94===c.charCodeAt(a.P):!1;e&&(a.P=1+a.P|0);for(e=new tk(2===(66&a.Ue),e);a.P!==d;){var g=gk(c,a.P);a:{switch(g){case 93:return a.P=1+a.P|0,a=e,c=uk(a),\"\"===a.ZF?c:\"(?:\"+a.ZF+c+\")\";case 38:a.P=1+a.P|0;if(a.P!==d&&38===c.charCodeAt(a.P)){a.P=1+a.P|0;g=e;var h=uk(g);g.ZF+=g.XQ?h+\"|\":\"(?\\x3d\"+h+\")\";g.bm=\"\";g.pg=\"\"}else vk(a,38,d,c,e);break a;case 91:g=Baa(a);e.bm=\"\"===e.bm?g:e.bm+\"|\"+g;break a;case 92:a.P=1+a.P|0;a.P===d&&dk(a,\"Illegal escape sequence\");\nh=c.charCodeAt(a.P);switch(h){case 100:case 68:case 104:case 72:case 115:case 83:case 118:case 86:case 119:case 87:case 112:case 80:g=e;h=mk(a,h);var k=h.nK;switch(k){case 0:g.pg=g.pg+(\"\\\\p{\"+h.yr)+\"}\";break;case 1:g.pg=g.pg+(\"\\\\P{\"+h.yr)+\"}\";break;case 2:g.pg=\"\"+g.pg+h.yr;break;case 3:h=nk(jk(),h.yr);g.bm=\"\"===g.bm?h:g.bm+\"|\"+h;break;default:throw new Yj(k);}break;case 81:a.P=1+a.P|0;g=c.indexOf(\"\\\\E\",a.P)|0;0>g&&dk(a,\"Unclosed character class\");h=e;k=c;for(var l=g,m=a.P;m!==l;){var n=gk(k,m);wk(h,\nn);m=m+(65536<=n?2:1)|0}a.P=2+g|0;break;default:vk(a,qk(a),d,c,e)}break a;case 32:case 9:case 10:case 11:case 12:case 13:if(0!==(4&a.Ue))a.P=1+a.P|0;else break;break a;case 35:if(0!==(4&a.Ue)){lk(a);break a}}a.P=a.P+(65536<=g?2:1)|0;vk(a,g,d,c,e)}}dk(a,\"Unclosed character class\")};\nfunction Daa(a){var b=a.ri,c=b.length,d=a.P;if((1+d|0)===c||63!==b.charCodeAt(1+d|0))return a.P=1+d|0,a.mn=1+a.mn|0,a.nn.push(a.mn),\"(\"+xk(a,!0)+\")\";(2+d|0)===c&&dk(a,\"Unclosed group\");var e=b.charCodeAt(2+d|0);if(58===e||61===e||33===e)return a.P=3+d|0,\"\"+b.substring(d,3+d|0)+xk(a,!0)+\")\";if(60===e){(3+d|0)===c&&dk(a,\"Unclosed group\");b=b.charCodeAt(3+d|0);if(65<=b&&90>=b||97<=b&&122>=b)return a.P=3+d|0,d=pk(a),b=a.$F,ug().ny.call(b,d)&&dk(a,\"named capturing group \\x3c\"+d+\"\\x3e is already defined\"),\na.mn=1+a.mn|0,a.nn.push(a.mn),a.$F[d]=-1+(a.nn.length|0)|0,a.P=1+a.P|0,\"(\"+xk(a,!0)+\")\";61!==b&&33!==b&&dk(a,\"Unknown look-behind group\");ok(a,\"Look-behind group\")}else{if(62===e)return a.P=3+d|0,a.mn=1+a.mn|0,d=a.mn,\"(?:(?\\x3d(\"+xk(a,!0)+\"))\\\\\"+d+\")\";dk(a,\"Embedded flag expression in the middle of a pattern is not supported\")}}\nfunction pk(a){for(var b=a.ri,c=b.length,d=a.P;;){if(a.P!==c){var e=b.charCodeAt(a.P);e=65<=e&&90>=e||97<=e&&122>=e||48<=e&&57>=e}else e=!1;if(e)a.P=1+a.P|0;else break}a.P!==c&&62===b.charCodeAt(a.P)||dk(a,\"named capturing group is missing trailing '\\x3e'\");return b.substring(d,a.P)}\nfunction vk(a,b,c,d,e){0!==(4&a.Ue)&&kk(a);a.P!==c&&45===d.charCodeAt(a.P)?(a.P=1+a.P|0,0!==(4&a.Ue)&&kk(a),a.P===c&&dk(a,\"Unclosed character class\"),c=gk(d,a.P),91===c||93===c?(wk(e,b),wk(e,45)):(a.P=a.P+(65536<=c?2:1)|0,c=92===c?qk(a):c,c<b&&dk(a,\"Illegal character range\"),a=yk(b)+\"-\"+yk(c),e.pg=56320===(-1024&b)?a+e.pg:e.pg+a,e.WQ&&(a=65<b?b:65,d=90>c?c:90,a<=d&&(d=32+d|0,e.pg+=yk(32+a|0)+\"-\"+yk(d)),b=97<b?b:97,c=122>c?c:122,b<=c&&(c=-32+c|0,e.pg+=yk(-32+b|0)+\"-\"+yk(c))))):wk(e,b)}\nfunction zk(a,b){this.ri=a;this.Ue=b;this.rK=!1;this.mn=this.P=0;this.nn=[0];this.$F={}}zk.prototype=new p;zk.prototype.constructor=zk;function ok(a,b){dk(a,b+\" is not supported because it requires RegExp features of ECMAScript 2018.\\nIf you only target environments with ES2018+, you can enable ES2018 features with\\n  scalaJSLinkerConfig ~\\x3d { _.withESFeatures(_.withESVersion(ESVersion.ES2018)) }\\nor an equivalent configuration depending on your build tool.\")}\nfunction xk(a,b){for(var c=a.ri,d=c.length,e=\"\";a.P!==d;){var g=gk(c,a.P);a:{switch(g){case 41:return b||dk(a,\"Unmatched closing ')'\"),a.P=1+a.P|0,e;case 124:a.rK&&!b&&dk(a,\"\\\\G is not supported when there is an alternative at the top level\");a.P=1+a.P|0;e+=\"|\";break a;case 32:case 9:case 10:case 11:case 12:case 13:if(0!==(4&a.Ue))a.P=1+a.P|0;else break;break a;case 35:if(0!==(4&a.Ue))lk(a);else break;break a;case 63:case 42:case 43:case 123:dk(a,\"Dangling meta character '\"+ik(jk(),g)+\"'\")}var h=\na.mn;switch(g){case 92:g=zaa(a);break;case 91:g=Caa(a);break;case 40:g=Daa(a);break;case 94:a.P=1+a.P|0;g=\"(?:^)\";break;case 36:a.P=1+a.P|0;g=\"(?:$)\";break;case 46:a.P=1+a.P|0;g=0!==(32&a.Ue)?\"\":0!==(1&a.Ue)?\"\\n\":\"\\n\\r\\u0085\\u2028\\u2029\";g=nk(jk(),g);break;default:a.P=a.P+(65536<=g?2:1)|0,g=hk(a,g)}e=\"\"+e+xaa(a,h,g)}}b&&dk(a,\"Unclosed group\");return e}\nfunction lk(a){for(var b=a.ri,c=b.length;;){if(a.P!==c){var d=b.charCodeAt(a.P);d=!(10===d||13===d||133===d||8232===d||8233===d)}else d=!1;if(d)a.P=1+a.P|0;else break}}zk.prototype.$classData=q({G2:0},!1,\"java.util.regex.PatternCompiler\",{G2:1,g:1});function Ak(a){try{return RegExp(\"\",a),!0}catch(b){return!1}}\nfunction Bk(){this.dR=this.cR=null;this.pK=!1;this.qK=this.$Q=this.bR=this.ZQ=this.aR=this.YQ=null;Ck=this;this.cR=RegExp(\"^\\\\(\\\\?([idmsuxU]*)(?:-([idmsuxU]*))?\\\\)\");this.dR=RegExp(\"(\\\\\\\\+)(\\\\d+)\",\"g\");this.pK=Ak(\"us\");Ak(\"d\");this.YQ=new sk(2,\"0-9\");this.aR=new sk(2,\"\\t \\u00a0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000\");this.ZQ=new sk(2,\"\\t-\\r \");this.bR=new sk(2,\"\\n-\\r\\u0085\\u2028\\u2029\");this.$Q=new sk(2,\"a-zA-Z_0-9\");var a={};a.Lower=new sk(2,\"a-z\");a.Upper=new sk(2,\"A-Z\");a.ASCII=new sk(2,\"\\x00-\\u007f\");\na.Alpha=new sk(2,\"A-Za-z\");a.Digit=new sk(2,\"0-9\");a.Alnum=new sk(2,\"0-9A-Za-z\");a.Punct=new sk(2,\"!-/:-@[-`{-~\");a.Graph=new sk(2,\"!-~\");a.Print=new sk(2,\" -~\");a.Blank=new sk(2,\"\\t \");a.Cntrl=new sk(2,\"\\x00-\\u001f\\u007f\");a.XDigit=new sk(2,\"0-9A-Fa-f\");a.Space=new sk(2,\"\\t-\\r \");this.qK=a}Bk.prototype=new p;Bk.prototype.constructor=Bk;\nfunction Dk(a){jk();a=new zk(a,0);0!==(256&a.Ue)&&(a.Ue|=64);var b=0!==(16&a.Ue);if(!b){var c=jk().cR.exec(a.ri);if(null!==c){var d=c[1];if(void 0!==d)for(var e=d.length,g=0;g<e;){var h=g;a.Ue|=Ek(jk(),d.charCodeAt(h));g=1+g|0}0!==(256&a.Ue)&&(a.Ue|=64);d=c[2];if(void 0!==d)for(e=d.length,g=0;g<e;)h=g,a.Ue&=~Ek(jk(),d.charCodeAt(h)),g=1+g|0;a.P=a.P+c[0].length|0}}0!==(128&a.Ue)&&dk(a,\"CANON_EQ is not supported\");0!==(8&a.Ue)&&ok(a,\"MULTILINE\");0!==(256&a.Ue)&&ok(a,\"UNICODE_CHARACTER_CLASS\");b?b=fk(a,\na.ri):(\"\\\\G\"===a.ri.substring(a.P,2+a.P|0)&&(a.rK=!0,a.P=2+a.P|0),b=xk(a,!1));c=jk().pK?\"us\":\"u\";return new Fk(a.ri,a.Ue,b,66===(66&a.Ue)?c+\"i\":c,a.rK,-1+(a.nn.length|0)|0,a.nn,a.$F)}function Ek(a,b){switch(b){case 105:return 2;case 100:return 1;case 109:return 8;case 115:return 32;case 117:return 64;case 120:return 4;case 85:return 256;default:throw Kj(\"bad in-pattern flag\");}}function nk(a,b){return\"\"!==b?\"[^\"+b+\"]\":jk().pK?\".\":\"[\\\\d\\\\D]\"}function ik(a,b){return String.fromCodePoint(b)}\nBk.prototype.$classData=q({H2:0},!1,\"java.util.regex.PatternCompiler$\",{H2:1,g:1});var Ck;function jk(){Ck||(Ck=new Bk);return Ck}function uk(a){if(a.XQ){var b=nk(jk(),a.pg);return\"\"===a.bm?b:\"(?:(?!\"+a.bm+\")\"+b+\")\"}return\"\"===a.pg?\"\"===a.bm?\"[^\\\\d\\\\D]\":\"(?:\"+a.bm+\")\":\"\"===a.bm?\"[\"+a.pg+\"]\":\"(?:\"+a.bm+\"|[\"+a.pg+\"])\"}function yk(a){var b=ik(jk(),a);return 93===a||92===a||45===a||94===a?\"\\\\\"+b:b}function tk(a,b){this.WQ=a;this.XQ=b;this.pg=this.bm=this.ZF=\"\"}tk.prototype=new p;\ntk.prototype.constructor=tk;function wk(a,b){var c=yk(b);a.pg=56320===(-1024&b)?\"\"+c+a.pg:\"\"+a.pg+c;a.WQ&&(65<=b&&90>=b?a.pg=\"\"+a.pg+ik(jk(),32+b|0):97<=b&&122>=b&&(a.pg=\"\"+a.pg+ik(jk(),-32+b|0)))}tk.prototype.$classData=q({I2:0},!1,\"java.util.regex.PatternCompiler$CharacterClassBuilder\",{I2:1,g:1});function sk(a,b){this.oK=null;this.mK=!1;this.nK=a;this.yr=b}sk.prototype=new p;sk.prototype.constructor=sk;\nsk.prototype.$classData=q({J2:0},!1,\"java.util.regex.PatternCompiler$CompiledCharClass\",{J2:1,g:1});function Hk(a){if(0===(1&a.ci)<<24>>24&&0===(1&a.ci)<<24>>24){if(Ik()===a)var b=\"(\",c=\")\";else if(Jk()===a)b=\"{\",c=\"}\";else if(Kk()===a)b=\"[\",c=\"]\";else if(Lk()===a)b=\"\\u2039\",c=\"\\u203a\";else if(Mk()===a)b=\"\\u2192\",c=\"\\u2190\";else if(Nk()===a)b='code\"',c='\"';else if(Ok()===a)b='code\"\"\"',c='\"\"\"';else{if(Pk()!==a)throw new w(a);b=\"${\";c=\"}\"}a.Wo=G(new H,b,c);a.ci=(1|a.ci)<<24>>24}return a.Wo}\nfunction Qk(){this.Vo=this.Uo=this.Wo=null;this.ci=0}Qk.prototype=new p;Qk.prototype.constructor=Qk;function Rk(){}Rk.prototype=Qk.prototype;function Sk(a){0===(2&a.ci)<<24>>24&&0===(2&a.ci)<<24>>24&&(a.Uo=Hk(a).h(),a.ci=(2|a.ci)<<24>>24);return a.Uo}function Tk(a){0===(4&a.ci)<<24>>24&&0===(4&a.ci)<<24>>24&&(a.Vo=Hk(a).j(),a.ci=(4|a.ci)<<24>>24);return a.Vo}\nQk.prototype.Ua=function(){if(Ik()===this)return\"parenthesis\";if(Jk()===this)return\"curly brace\";if(Kk()===this)return\"square bracket\";if(Lk()===this)return\"angle bracket\";if(Mk()===this)return\"indentation\";if(Nk()===this)return\"quasiquote\";if(Ok()===this)return\"quasiquote triple\";if(Pk()===this)return\"unquote\";throw new w(this);};function Uk(){}Uk.prototype=new p;Uk.prototype.constructor=Uk;function Vk(a,b){return Wk(new Xk).Ob(hc(b),new y(()=>{t();return R()}))}\nUk.prototype.$classData=q({$T:0},!1,\"mlscript.BracketKind$\",{$T:1,g:1});var Yk;function Zk(){Yk||(Yk=new Uk);return Yk}var Eaa=function bl(a){var c=a.vK();if(c instanceof cl&&Pe(new E(c.Yo),a.Yo))c=bl(c);else{c=a.vK();var d=O().c;c=new z(c,d)}d=a.DK();d instanceof cl&&Pe(new E(d.Yo),a.Yo)?a=bl(d):(a=a.DK(),d=O().c,a=new z(a,d));return dl(a,c)};\nfunction Faa(a){var b=k=>a.Yo?Pe(new E(k),el()):Pe(new E(k),gl()),c=Eaa(a);a:for(;;)if(c.b()){b=u();break}else{var d=c.e(),e=c.f();if(!0===!!b(d))c=e;else for(;;){if(e.b())b=c;else{d=e.e();if(!0!==!!b(d)){e=e.f();continue}d=e;e=new z(c.e(),u());var g=c.f();for(c=e;g!==d;){var h=new z(g.e(),u());c=c.p=h;g=g.f()}for(g=d=d.f();!d.b();){h=d.e();if(!0===!!b(h)){for(;g!==d;)h=new z(g.e(),u()),c=c.p=h,g=g.f();g=d.f()}d=d.f()}g.b()||(c.p=g);b=e}break a}}return hl(b)}function il(){}il.prototype=new p;\nil.prototype.constructor=il;function jl(){}jl.prototype=il.prototype;function Ae(a,b,c){a.TM=b;a.$C=c;Sf||(Sf=new Rf);c=kl();for(var d=0,e=1,g=null;d<b.length;){var h=b.charCodeAt(d);13===h?(ml(nl(),g,hc(10))||1!==e||ol(c,d),e=1):10===h?(ml(nl(),g,hc(13))||1!==e||ol(c,d),e=1):(1===e&&ol(c,d),e=1+e|0);g=hc(h);d=1+d|0}1===e&&ol(c,d);rl();if(0<=c.Zg)b=new Xc(c.Zg),c.Gc(b,0,2147483647),c=b;else{b=[];for(c=sl(c).m();c.s();)d=c.t(),b.push(null===d?0:d);c=new Xc(new Int32Array(b))}a.ZC=c;return a}\nfunction Gaa(){var a=new Fe;Ae(a,\"\",ue(ve(),\"\"));return a}function Fe(){this.ZC=this.$C=this.TM=null}Fe.prototype=new p;Fe.prototype.constructor=Fe;function Nf(a,b){var c=a.ZC;a:{for(var d=0;d<c.a.length;){if(c.a[d]>b){c=d;break a}d=1+d|0}c=-1}c=-1===c?a.ZC.a.length:1>c?1:c;d=a.$C.K();d=-1+(c<d?c:d)|0;b=1+(b-a.ZC.a[d]|0)|0;a=a.$C.va(d);return new tl(c,a,b)}Fe.prototype.$classData=q({QU:0},!1,\"mlscript.FastParseHelpers\",{QU:1,g:1});\nvar hm=function ul(a,b,c){for(;;){var e=b;if(e instanceof vl)return c=wl(c,e.x),new xl(c);if(e instanceof yl){var g=e.ll;c=(k=>l=>{if(null!==l){var m=l.h(),n=l.j();if(null!==m&&(m=m.x,null!==n&&(n=n.ya,n instanceof vl))){l=wl(k,n.x);m=zl(Al(),m);if(l===m)return l=t().d,G(new H,m,l);t();return G(new H,m,new L(new xl(l)))}}if(null!==l&&(n=l.h(),m=l.j(),null!==n&&(n=n.x,null!==m)))return l=m.ya,m=zl(Al(),n),t(),l=ul(a,l,k),G(new H,m,new L(l));throw new w(l);})(c);if(g===u())c=u();else{b=g.e();e=b=new z(c(b),\nu());for(g=g.f();g!==u();){var h=g.e();h=new z(c(h),u());e=e.p=h;g=g.f()}c=b}return new Bl(c)}if(e instanceof Cl)b=e.ai;else{if(e instanceof Dl)return new El;if(e instanceof Fl)b=e.gg;else{if(e instanceof Gl){g=e.Ra;c=(k=>l=>{if(null!==l){var m=l.j();if(null!==m)return ul(a,m.ya,k)}throw new w(l);})(c);if(g===u())c=u();else{b=g.e();e=b=new z(c(b),u());for(g=g.f();g!==u();)h=g.e(),h=new z(c(h),u()),e=e.p=h,g=g.f();c=b}return new Hl(c)}if(e instanceof Il)b=e.nl;else if(e instanceof Kl)b=e.cp;else if(e instanceof\nMl)b=e.Ml;else{if(e instanceof Ol||e instanceof Pl||e instanceof Ql||e instanceof Rl||e instanceof Sl||e instanceof Tl||e instanceof Ul||e instanceof Vl||e instanceof Wl||e instanceof Xl||e instanceof Yl||e instanceof Zl||e instanceof $l||e instanceof am||e instanceof bm||e instanceof cm||e instanceof dm||e instanceof em||e instanceof fm)throw new gm(\"term \"+b+\" is not a valid pattern\");throw new w(e);}}}}};\nfunction im(a,b,c){if(b instanceof Gl){var d=b.Ra;b=k=>{if(null!==k){var l=new L(k);if(!l.b()){var m=l.k.h();l=l.k.j();if(t().d===m&&null!==l)return hm(a,l.ya,c)}}if(null!==k&&(l=new L(k),!l.b()&&(m=l.k.h(),l=l.k.j(),m instanceof L&&(m=m.k,null!==l))))return hm(a,m,c);throw new w(k);};if(d===u())return u();var e=d.e(),g=e=new z(b(e),u());for(d=d.f();d!==u();){var h=d.e();h=new z(b(h),u());g=g.p=h;d=d.f()}return e}throw new gm(\"term \"+b+\" is not a valid parameter list\");}\nfunction jm(a,b,c){var d=a.CK();d.b()?c=new km(a.Ua()):(d=d.o(),lm(c,d).sF=!0,c=new km(d),d=a.Ua(),c=om(Al(),c,d));return b&&!a.UJ()?om(Al(),c,\"class\"):c}function pm(a,b){a=new vl(a);var c=h=>{var k=t().d;h=new sm(tm().Cg,h);return G(new H,k,h)};if(b===u())c=u();else{var d=b.e(),e=d=new z(c(d),u());for(b=b.f();b!==u();){var g=b.e();g=new z(c(g),u());e=e.p=g;b=b.f()}c=d}return new Pl(a,new Gl(c))}\nvar Iaa=function Haa(a,b,c,d,e){if(b instanceof um){var h=b.Tn,k=b.Un;b=vm(a,b.Xo,c,d,e);h=vm(a,h,c,d,e);a=Haa(a,k,c,d,e);if(a instanceof fe)return a=a.aa,t(),c=O().c,b=pm(\"Case\",new z(b,new z(h,new z(a,c)))),new fe(b);if(a instanceof Ud){a=a.fa;if(b instanceof wm)return t(),b=new um(b,h,a),new Ud(b);xm(\"Program reached and unexpected state.\")}else throw new w(a);}else{if(b instanceof ym){b=b.dn;if(d)return t(),b=vm(a,b,c,d,e),h=O().c,b=pm(\"Wildcard\",new z(b,h)),new fe(b);t();b=new ym(vm(a,b,c,d,\ne));return new Ud(b)}if(zm()===b){if(d)return t(),b=pm(\"NoCases\",O().c),new fe(b);t();b=zm();return new Ud(b)}throw new w(b);}};function Am(a){switch(a){case \"+.\":return\"+\";case \"-.\":return\"-\";case \"*.\":return\"*\";default:return a}}\nvar vm=function Bm(a,b,c,d,e){for(;;){var h=!1,k=null,l=b;if(l instanceof vl){var m=l.x,n=e.xH.L(m);if(d||n){var r=Cm(c,m);if(r.b())throw new gm(\"unbound free variable \"+m+\" is not supported yet.\");var v=r.o().zo();if(n){var x=new vl(v),A=O().c;return pm(\"Var\",new z(x,A))}var B=new Dm(v),C=O().c;return pm(\"Var\",new z(B,C))}return b}if(l instanceof Em){var D=l;if(d){var F=O().c;return pm(\"IntLit\",new z(D,F))}return D}if(l instanceof Fm){var I=l;if(d){var M=O().c;return pm(\"DecLit\",new z(I,M))}return I}if(l instanceof\nDm){var N=l;if(d){var P=O().c;return pm(\"StrLit\",new z(N,P))}return N}if(l instanceof Gm){var T=l;if(d){var Y=O().c;return pm(\"UnitLit\",new z(T,Y))}return T}if(l instanceof Ol){var Z=l,S=Z.Ej,ea=Z.Fj;if(d){var ia=Hm(c);if(S instanceof Gl){var X=S.Ra,sa=(Jh=>If=>{if(null!==If){var Hg=new L(If);if(!Hg.b()){var He=Hg.k.h();Hg=Hg.k.j();if(t().d===He&&null!==Hg&&(He=Hg.ya,He instanceof vl))return If=He.x,wl(Jh,If),He=Im(Jh,If,(t(),new L(!1)),!1,t().d).re,G(new H,If,He)}}if(null!==If&&(He=new L(If),!He.b()&&\n(He=He.k.h(),He instanceof L&&(He=He.k,null!==He))))return If=He.x,wl(Jh,If),He=Im(Jh,If,(t(),new L(!1)),!1,t().d).re,G(new H,If,He);throw new gm(\"parameter \"+If+\" is not supported in quasiquote\");})(ia);if(X===u())var Ja=u();else{for(var Xa=X.e(),Fa=new z(sa(Xa),u()),za=Fa,Qa=X.f();Qa!==u();){var Ma=Qa.e(),Ga=new z(sa(Ma),u());za=za.p=Ga;Qa=Qa.f()}Ja=Fa}var ab=d,Hb=e.xH;if(Ja===u())var bc=u();else{for(var yb=Ja.e(),tb=new z(yb.h(),u()),eb=tb,kb=Ja.f();kb!==u();){var Rb=kb.e(),Gb=new z(Rb.h(),u());\neb=eb.p=Gb;kb=kb.f()}bc=tb}for(var vb=Bm(a,ea,ia,ab,new Jm(a,Hb.Ce(bc))),Tb=Km(Ja);!Tb.b();){var Nb=Tb.e(),ic=vb,Va=new vl(Nb.j()),cb=new Dm(Nb.h()),zb=O().c,Ub=pm(\"freshName\",new z(cb,zb)),jb=new vl(Nb.j()),db=O().c,ub=pm(\"Var\",new z(jb,db)),Aa=O().c;vb=new Rl(!1,Va,Ub,pm(\"Lam\",new z(ub,new z(ic,Aa))));Tb=Tb.f()}return vb}throw new gm(\"term \"+S+\" is not a valid parameter list\");}return new Ol(S,Bm(a,ea,c,d,e))}if(l instanceof fm){var va=l.jt;if(d){var Ra=Hm(c);b=va;c=Ra;d=!1;continue}else throw new gm(\"unquoted term should be wrapped by quotes.\");\n}if(l instanceof em){var rb=l.Iq,xb=Hm(c),mc=Bm(a,rb,xb,!0,e);if(d)throw new gm(\"nested quotation is not allowed.\");return mc}if(l instanceof Pl){h=!0;k=l;var Ha=k.Za,Ka=k.Qb;if(Ha instanceof vl){var Oa=Ha.x;if(Ka instanceof Gl){var Na=Ka.Ra;if(Na instanceof z){var Da=Na,ta=Da.z,Ya=Da.p;if(null!==ta){var dc=new L(ta);if(!dc.b()){var ka=dc.k.h(),ya=dc.k.j();if(t().d===ka&&null!==ya){var Sa=ya.yb,xc=ya.ya;if(Ya instanceof z){var Sb=Ya,uc=Sb.z,Lb=Sb.p;if(null!==uc){var lc=new L(uc);if(!lc.b()){var Xb=\nlc.k.h(),ec=lc.k.j();if(t().d===Xb&&null!==ec){var Ab=ec.yb,Ob=ec.ya,fb=O().c;if((null===fb?null===Lb:fb.i(Lb))&&Lm().gD.L(Am(Oa))&&(!Mm(a,Oa,!0,c).tv()||Nm(new E(Oa),Am(Oa)))){if(d){var Wa=new Dm(Am(Oa)),bb=O().c,Ia=pm(\"Var\",new z(Wa,bb)),Ua=Bm(a,xc,c,d,e),pc=Bm(a,Ob,c,d,e),sc=O().c;return pm(\"App\",new z(Ia,new z(Ua,new z(pc,sc))))}var Ba=new vl(Oa),ob=t().d,nc=new sm(Sa,Bm(a,xc,c,d,e)),Ib=G(new H,ob,nc),vc=t().d,Vb=new sm(Ab,Bm(a,Ob,c,d,e)),fc=G(new H,vc,Vb),Bc=O().c;return new Pl(Ba,new Gl(new z(Ib,\nnew z(fc,Bc))))}}}}}}}}}}}}if(h){var Pb=k.Za,Jb=k.Qb;if(d){var gc=Bm(a,Pb,c,d,e),Cb=Bm(a,Jb,c,d,e),cc=O().c;return pm(\"App\",new z(gc,new z(Cb,cc)))}return new Pl(Bm(a,Pb,c,d,e),Bm(a,Jb,c,d,e))}if(l instanceof yl){var yc=l.ll;if(d){for(var Mc=c,qc=d,oc=yc,Qc=null,jc=null;oc!==u();){for(var sb=oc.e(),Gc=new Dm(sb.h().x),Wb=O().c,Cc=pm(\"Var\",new z(Gc,Wb)),Fc=Bm(a,sb.j().ya,Mc,qc,e),qd=O().c,Yb=new Om(new z(Cc,new z(Fc,qd)));Yb.s();){var Nc=new z(Yb.t(),u());null===jc?Qc=Nc:jc.p=Nc;jc=Nc}oc=oc.f()}return pm(\"Rcd\",\nnull===Qc?u():Qc)}var ad=((Jh,If,Hg)=>He=>G(new H,He.h(),new sm(He.j().yb,Bm(a,He.j().ya,Jh,If,Hg))))(c,d,e);if(yc===u())var Uc=u();else{for(var cd=yc.e(),kc=new z(ad(cd),u()),Vc=kc,Hc=yc.f();Hc!==u();){var rc=Hc.e(),sd=new z(ad(rc),u());Vc=Vc.p=sd;Hc=Hc.f()}Uc=kc}return new yl(Uc)}if(l instanceof Fl){var Kc=l,Qd=Kc.bi,Ad=Kc.gg;if(d){var kd=Bm(a,Ad,c,d,e),Hd=O().c;return pm(\"Bra\",new z(kd,Hd))}return new Fl(Qd,Bm(a,Ad,c,d,e))}if(l instanceof Ql){var Rd=l,Bd=Rd.Vl,ae=Rd.ml;if(null!==ae){var dd=ae.x;\nif(d){var od=Bm(a,Bd,c,d,e),Ta=new Dm(dd),wb=O().c,$a=pm(\"Var\",new z(Ta,wb)),wa=O().c;return pm(\"Sel\",new z(od,new z($a,wa)))}return new Ql(Bm(a,Bd,c,d,e),ae)}}if(l instanceof Rl){var hb=l,ra=hb.ep,wc=hb.Zn,ac=hb.$n,Id=hb.Mm;if(null!==wc){var ud=wc.x,be=Hm(c);if(d){wl(be,ud);var re=Im(be,ud,(t(),new L(!1)),!1,t().d).re,pe=new vl(re),bd=new Dm(ud),Rc=O().c,Wc=pm(\"freshName\",new z(bd,Rc)),Wd=new vl(re),zd=O().c,Pa=pm(\"Var\",new z(Wd,zd)),Db=Bm(a,ac,c,d,e),Oc=d,Tc=e.xH,Sd=O().c,Jc=Bm(a,Id,be,Oc,new Jm(a,\nTc.Ce(new z(ud,Sd)))),vd=O().c;return new Rl(!1,pe,Wc,pm(\"Let\",new z(Pa,new z(Db,new z(Jc,vd)))))}return new Rl(ra,new vl(ud),Bm(a,ac,c,d,e),Bm(a,Id,be,d,e))}}if(l instanceof Sl){var hd=l.Dj,de=((Jh,If,Hg)=>He=>{if(He instanceof Pm)return Bm(a,He,Jh,If,Hg);throw new gm(\"statement \"+He+\" is not supported in quasiquotes\");})(Hm(c),d,e);if(hd===u())var ye=u();else{for(var jf=hd.e(),af=new z(de(jf),u()),pf=af,kf=hd.f();kf!==u();){var Be=kf.e(),Kd=new z(de(Be),u());pf=pf.p=Kd;kf=kf.f()}ye=af}return d?\npm(\"Blk\",ye):new Sl(ye)}if(l instanceof Gl){var ld=l.Ra;if(d){for(var Jd=c,Dd=d,Xd=ld,Yc=null,Ce=null;Xd!==u();){var te=Xd.e();a:{if(null!==te){var Ie=new L(te);if(!Ie.b()){var Jf=Ie.k.h(),df=Ie.k.j();if(Jf instanceof L){var vg=Jf.k;if(null!==vg){var wg=vg.x;if(null!==df){var xg=df.yb,eg=df.ya,vh=new vl(wg),fg=O().c,ih=pm(\"Var\",new z(vh,fg)),Ig=Bm(a,eg,Jd,Dd,e),Tf=Xm(xg),Jg=pm(\"Fld\",new z(Ig,Tf)),jh=O().c;var yg=new z(ih,new z(Jg,jh));break a}}}}}if(null!==te){var gg=new L(te);if(!gg.b()){var Cf=\ngg.k.h(),Uf=gg.k.j();if(t().d===Cf&&null!==Uf){var $g=Uf.yb,Ah=Bm(a,Uf.ya,Jd,Dd,e),Kg=Xm($g),Vf=pm(\"Fld\",new z(Ah,Kg)),hg=O().c;yg=new z(Vf,hg);break a}}}throw new w(te);}for(var zg=new Om(yg);zg.s();){var Lg=new z(zg.t(),u());null===Ce?Yc=Lg:Ce.p=Lg;Ce=Lg}Xd=Xd.f()}return pm(\"Tup\",null===Yc?u():Yc)}var Mg=((Jh,If,Hg)=>He=>{if(null!==He){var lj=new L(He);if(!lj.b()){var Wi=lj.k.h();lj=lj.k.j();if(null!==lj)return He=new sm(lj.yb,Bm(a,lj.ya,Jh,If,Hg)),G(new H,Wi,He)}}throw new w(He);})(c,d,e);if(ld===\nu())var Wf=u();else{for(var Ng=ld.e(),Kf=new z(Mg(Ng),u()),xf=Kf,Og=ld.f();Og!==u();){var mi=Og.e(),Ci=new z(Mg(mi),u());xf=xf.p=Ci;Og=Og.f()}Wf=Kf}return new Gl(Wf)}if(l instanceof Vl){var Xh=l,wh=Xh.lp,Bh=Xh.mp;if(d){var ng=Bm(a,wh,c,d,e),kh=Bm(a,Bh,c,d,e),Kh=O().c;return pm(\"Subs\",new z(ng,new z(kh,Kh)))}return new Vl(Bm(a,wh,c,d,e),Bm(a,Bh,c,d,e))}if(l instanceof Cl){var ni=l,Lh=ni.ai,lh=ni.Fm;if(d){b=Lh;continue}else return new Cl(Bm(a,Lh,c,d,e),lh)}if(l instanceof Tl){var Ch=l,Dh=Ch.br,Yh=Ch.ar;\nif(null!==Yh){var ah=Yh.ll;if(d){var oi=Bm(a,Dh,c,d,e),mj=Bm(a,Yh,c,d,e),wd=O().c;return pm(\"With\",new z(oi,new z(mj,wd)))}var ge=Bm(a,Dh,c,d,e),De=((Jh,If,Hg)=>He=>G(new H,He.h(),new sm(He.j().yb,Bm(a,He.j().ya,Jh,If,Hg))))(c,d,e);if(ah===u())var qf=u();else{for(var og=ah.e(),Xf=new z(De(og),u()),mh=Xf,Ag=ah.f();Ag!==u();){var Bg=Ag.e(),Eh=new z(De(Bg),u());mh=mh.p=Eh;Ag=Ag.f()}qf=Xf}return new Tl(ge,new yl(qf))}}if(l instanceof Ul){var Pg=l,Di=Pg.Sn,Mh=Iaa(a,Pg.Hm,c,d,e);if(Mh instanceof fe){var pi=\nMh.aa,Xi=Bm(a,Di,c,d,e),Qg=O().c;return pm(\"CaseOf\",new z(Xi,new z(pi,Qg)))}if(Mh instanceof Ud){var nh=Mh.fa;return new Ul(Bm(a,Di,c,d,e),nh)}throw new w(Mh);}if(b.oc.b()){if(l instanceof Wl){var bh=l,Mj=bh.Gm,Nj=bh.Qn;if(!d)return new Wl(Bm(a,Mj,c,d,e),Bm(a,Nj,c,d,e))}if(l instanceof Yl){var ie=l.hp;if(!d)return new Yl(Bm(a,ie,c,d,e))}if(l instanceof Il){var Ac=l,Ve=Ac.nl,Td=Ac.np;if(!d)return new Il(Bm(a,Ve,c,d,e),Td)}if(l instanceof Zl){var lf=l,Yi=lf.qq,Jl=lf.$o;if(!d)return new Zl(Yi,Bm(a,Jl,\nc,d,e))}if(l instanceof Kl){var ll=l.cp;if(!d)return new Kl(Bm(a,ll,c,d,e))}if(l instanceof am&&!d)return b;if(l instanceof bm){var Bj=l,$k=Bj.Vn,Zh=Bj.Zo;if(!d)return new bm($k,Bm(a,Zh,c,d,e))}if(l instanceof Ml){var Ei=l,Yd=Ei.Ml;return new Ml(Bm(a,Ei.gs,c,d,e),Bm(a,Yd,c,d,e))}if(l instanceof dm){var bf=l,rf=bf.$q,Cg=bf.Zq;if(!d)return new dm(Bm(a,rf,c,d,e),Bm(a,Cg,c,d,e))}if(l instanceof Xl||l instanceof $l||l instanceof cm||l instanceof Wl||l instanceof Yl||l instanceof Il||l instanceof Zl||l instanceof\nKl||l instanceof am||l instanceof bm||l instanceof dm)throw new gm(\"this quote syntax is not supported yet.\");throw new w(l);}var nj=b.oc;nj.b()&&xm(\"Program reached and unexpected state.\");b=nj.o()}},en=function Jaa(a,b,c,d){if(c instanceof um){var g=c.Un;return Ym(a,b,c.Xo,d).ba(Zm(a,c.Tn,d),Jaa(a,b,g,d))}if(c instanceof ym)return Zm(a,c.dn,d);if(zm()===c)return a=t().d,b=O().c,t(),c=new $m(new km(\"Error\")),d=an(\"non-exhaustive case expression\"),g=O().c,c=new bn(new cn(c,new z(d,g))),d=O().c,new dn(a,\nb,new Ud(new z(c,d)),O().c);throw new w(c);};\nfunction Ym(a,b,c,d){return new fn((e,g)=>{var h=!1,k=null;a:{if(c instanceof vl&&(h=!0,k=c,\"int\"===k.x)){h=om(Al(),new km(\"Number\"),\"isInteger\");k=O().c;h=new cn(h,new z(b,k));break a}if(h&&\"bool\"===k.x)h=new gn(\"\\x3d\\x3d\\x3d\",om(Al(),b,\"constructor\"),new hn(\"Boolean\"));else{if(h){var l=k.x;if(\"true\"===l||\"false\"===l){h=new gn(\"\\x3d\\x3d\\x3d\",b,new hn(l));break a}}if(h&&\"string\"===k.x)h=new gn(\"\\x3d\\x3d\\x3d\",om(Al(),b,\"constructor\"),new hn(\"String\"));else{if(h){h=k.x;k=!1;l=null;var m=Cm(d,h);if(m instanceof\nL&&(k=!0,l=m,m=l.k,m instanceof jn)){h=new kn(b,jm(m,!0,d));break a}if(k&&(k=l.k,k instanceof ln)){h=new kn(b,jm(k,!0,d));break a}k=!1;l=null;m=a.di.ko.U(h);m instanceof L&&(k=!0,l=m);if(k&&(m=l.k,m instanceof mn)){h=new km(m.Tx);h=om(Al(),h,\"is\");k=J(new K,[b]);h=new cn(h,(Od(),Pd(u(),k)));break a}if(k&&l.k instanceof nn)throw new gm(\"cannot match type alias \"+h);throw new gm(\"unknown match case: \"+h);}if(c instanceof Dl)h=new gn(\"\\x3d\\x3d\\x3d\",b,Zm(a,c,d));else throw new w(c);}}}return new on(h,\ne,g)})}function Kaa(a,b){if(a instanceof z){var c=a.z;a=a.p;t();for(c=pn(c,new km(\"Object\"),!1,b);!a.b();){var d=a.e();c=pn(d,c,!0,b);a=a.f()}return new L(c)}b=O().c;if(null===b?null===a:b.i(a))return t().d;throw new w(a);}\nfunction Laa(a,b,c,d,e){var g=b.uq.x,h=n=>{var r=Im(e,n,new L(!1),!1,t().d);return new qn(r.re,new km(\"this.#\"+n))};if(c===u())h=u();else{var k=c.e(),l=k=new z(h(k),u());for(c=c.f();c!==u();){var m=c.e();m=new z(h(m),u());l=l.p=m;c=c.f()}h=k}l=b.bx.aa;l instanceof Ol?(b=l.Fj,k=im(a,l.Ej,e),t(),k=new L(k),l=b):k=t().d;b=k;a=rn(Zm(a,l,e));k=sn(e.lo);k instanceof L?(k=k.k,l=O().c,k=new z(k,l)):k=O().c;d.b()?d=O().c:(d=d.o(),d=tn(lm(e,d)));t();d=un(un(h,k),d);h=O().c;d=un(d,new z(a,h));d=new Ud(d);if(b instanceof\nL)return new vn(g,b.k,d);if(t().d===b)return new wn(g,d);throw new w(b);}function xn(a,b){b=a.di.ko.U(b);if(b instanceof L){var c=b.k;if(c instanceof mn){b=yn(c.Sx);c=zn(c.Sx);for(var d=null,e=null;c!==u();){var g=c.e();for(g=xn(a,g).m();g.s();){var h=new z(g.t(),u());null===e?d=h:e.p=h;e=h}c=c.f()}a=null===d?u():d;return un(b,a)}}a=b instanceof L&&null!==b.k?!0:t().d===b?!0:!1;if(a)return O().c;throw new w(b);}function An(a){return a?new vl(\"true\"):new vl(\"false\")}\nfunction Xm(a){var b=An(a.je),c=An(a.ch);a=An(a.Bh);var d=O().c;return new z(b,new z(c,new z(a,d)))}\nfunction pn(a,b,c,d){a:for(;;)if(a instanceof Pl)a=a.Za;else{if(a instanceof vl){a=a.x;break a}if(a instanceof Ql){var e=a.ml;if(null!==e){a=e.x;break a}}if(a instanceof Il)a=a.nl;else throw new gm(\"unsupported parents.\");}e=!1;var g=null,h=Cm(d,a);if(h instanceof L&&(e=!0,g=h,g.k instanceof mn))return b;if(e){var k=g.k;if(k instanceof Hn)return c=jm(k,!0,d),t(),b=J(new K,[b]),new cn(c,Pd(u(),b))}if(e&&(b=g.k)&&b.$classData&&b.$classData.rb.pF&&!c)return jm(b,!0,d);if(e)throw new gm(\"unexpected parent symbol \"+\ng.k+\".\");if(t().d===h)throw new gm(\"unresolved parent \"+a+\".\");throw new w(h);}function Mn(a,b){if(null===b)throw le();return b.sb?b.vb:me(b,new On(a))}function Pn(a){a=Qn(a);if(a instanceof fe)return gl();if(a instanceof Ud)return a.fa;throw new w(a);}\nfunction Rn(a,b,c,d,e){var g=v=>{if(null!==v){var x=v.h(),A=v.j();if(x instanceof L&&(x=x.k,null!==A)){var B=A.yb;A=A.ya;if(null!==B)return v=B.je,A=Pn(A),v=new Sn(v?(t(),new L(A)):t().d,A),G(new H,x,v)}}if(null!==v&&(x=v.h(),v=v.j(),t().d===x&&null!==v&&(A=v.yb,x=v.ya,null!==A&&(v=A.je,x instanceof vl))))return v?(t(),v=el(),v=new L(v)):v=t().d,v=new Sn(v,gl()),G(new H,x,v);xm(\"Program reached and unexpected state.\")};if(c===u())g=u();else{for(var h=c.e(),k=h=new z(g(h),u()),l=c.f();l!==u();){var m=\nl.e();m=new z(g(m),u());k=k.p=m;l=l.f()}g=h}h=v=>null!==v&&(v=v.j(),null!==v)?v.yb.Bh:!1;k=c;a:for(;;)if(k.b()){l=u();break}else if(l=k.e(),c=k.f(),!1===!!h(l))k=c;else for(;;){if(c.b())l=k;else{l=c.e();if(!1!==!!h(l)){c=c.f();continue}l=c;c=new z(k.e(),u());m=k.f();for(k=c;m!==l;){var n=new z(m.e(),u());k=k.p=n;m=m.f()}for(m=l=l.f();!l.b();){n=l.e();if(!1===!!h(n)){for(;m!==l;)n=new z(m.e(),u()),k=k.p=n,m=m.f();m=l.f()}l=l.f()}m.b()||(k.p=m);l=c}break a}h=v=>{if(null!==v){var x=v.h();if(x instanceof\nL)return x.k.x}if(null!==v&&(x=v.h(),v=v.j(),t().d===x&&null!==v&&(v=v.ya,v instanceof vl)))return v.x;xm(\"Program reached and unexpected state.\")};if(l===u())h=u();else{c=l.e();k=c=new z(h(c),u());for(l=l.f();l!==u();)m=l.e(),m=new z(h(m),u()),k=k.p=m,l=l.f();h=c}if(d===u())d=u();else{c=d.e();k=c=new z(Pn(c),u());for(d=d.f();d!==u();)l=d.e(),l=new z(Pn(l),u()),k=k.p=l,d=d.f();d=c}d=d.mf(new Tn(g),Un());c=Vn();g=Wn(ef(e),new Xn(a,c,b));b=Wn(ef(e),new Yn(a,c,b));c=v=>{var x=!1,A=null;if(v instanceof\nCl){x=!0;A=v;var B=A.ai;if(B instanceof vl&&\"this\"===B.x)return!1}return x&&A.ai instanceof am?!1:v instanceof Zn&&(x=v.wd,A=v.Yc,x instanceof L&&!1===!!x.k&&A instanceof fe)?!0:v instanceof Pm?!0:!1};l=ef(e);a:for(;;)if(l.b()){c=u();break}else if(m=l.e(),k=l.f(),!1===!!c(m))l=k;else for(;;){if(k.b())c=l;else{m=k.e();if(!1!==!!c(m)){k=k.f();continue}m=k;k=new z(l.e(),u());n=l.f();for(l=k;n!==m;){var r=new z(n.e(),u());l=l.p=r;n=n.f()}for(n=m=m.f();!m.b();){r=m.e();if(!1===!!c(r)){for(;n!==m;)r=new z(n.e(),\nu()),l=l.p=r,n=n.f();n=m.f()}m=m.f()}n.b()||(l.p=n);c=k}break a}a=Wn(ef(e),new ao(a));return new bo(d,g,b,c,a,h)}function co(){this.Cs=this.di=null}co.prototype=new p;co.prototype.constructor=co;function eo(){}eo.prototype=co.prototype;function fo(a,b,c,d){a=Mm(a,b,c,d);if(!(a instanceof Ud)){if(a instanceof fe)throw a.aa;throw new w(a);}return a.fa}\nfunction Mm(a,b,c,d){O();var e=!1,g=null,h=Cm(d,b);a:{if(h instanceof L){e=!0;g=h;var k=g.k;if(k instanceof go){k.DP=!0;a.Cs.Yz.L(k.Nx)||ho(a.Cs,k.Nx,k.bF);b=new km(k.bF);\"error\"===k.Nx&&(d=u(),b=new cn(b,d));break a}}if(e&&(k=g.k,k instanceof io)){if(!k.z_)throw new jo(k);b=new km(k.nt);break a}if(e&&(k=g.k,k instanceof ko)){d=k.hJ;if((d.b()?0:d.o())&&!k.iJ)throw new gm(\"unguarded recursive use of by-value binding \"+b);k.sF=!0;b=new km(k.re);k.hJ.b()&&!k.iJ&&(d=u(),b=new cn(b,d));break a}if(e&&(k=\ng.k)&&k.$classData&&k.$classData.rb.pF){b=jm(k,c,d);break a}if(e&&(c=g.k,c instanceof lo)){e=c.Ox;if((e.b()?0:e.o())&&!c.Px)throw new gm(\"unguarded recursive use of by-value binding \"+b);b=c.FA;if(b.b())throw new gm(\"unqualified member symbol \"+c);b=b.o();c.OP=!0;lm(d,b).sF=!0;c.EA?b=new km(b+\".#\"+c.dr):(b=new km(b),d=c.dr,b=om(Al(),b,d));c.Ox.b()&&!c.Px&&(d=u(),b=new cn(b,d));break a}if(e&&g.k instanceof mn)return O(),b=new gm(\"trait used in term position\"),new fe(b);if(t().d===h){e=!1;d=d.ko.U(b);\nif(d instanceof L&&(e=!0,d.k instanceof nn))return O(),b=new gm(\"type alias \"+b+\" is not a valid expression\"),new fe(b);e&&xm(\"register mismatch in scope\");if(t().d===d)return O(),b=new gm(\"unresolved symbol \"+b),new fe(b);throw new w(d);}throw new w(h);}return new Ud(b)}\nfunction Maa(a,b,c){if(null!==b){var d=b.Za,e=b.Qb;if(d instanceof Pl){var g=d.Qb;if(d.Za instanceof vl&&g instanceof Gl&&(d=g.Ra,d instanceof z&&(g=d.z,d=d.p,null!==g))){var h=new L(g);h.b()||(g=h.k.h(),h=h.k.j(),t().d===g&&null!==h&&(g=O().c,(null===g?null===d:g.i(d))&&e instanceof Gl&&(e=e.Ra,e instanceof z&&(d=e.z,e=e.p,null!==d&&(g=new L(d),g.b()||(d=g.k.h(),g=g.k.j(),t().d===d&&null!==g&&(d=O().c,null===d?null===e:d.i(e))))))))}}}if(null!==b&&(e=b.Za,d=b.Qb,e instanceof vl&&(e=e.x,d instanceof\nGl&&(g=d.Ra,g instanceof z&&(d=g.z,g=g.p,null!==d&&(h=new L(d),!h.b()&&(d=h.k.h(),h=h.k.j(),t().d===d&&null!==h&&(d=h.ya,g instanceof z&&(h=g.z,g=g.p,null!==h))))))))){var k=new L(h);if(!k.b()&&(h=k.k.h(),k=k.k.j(),t().d===h&&null!==k&&(h=k.ya,k=O().c,(null===k?null===g:k.i(g))&&Lm().gD.L(Am(e))&&(!Mm(a,e,!0,c).tv()||Nm(new E(e),Am(e))))))return new gn(Am(e),Zm(a,d,c),Zm(a,h,c))}if(null!==b&&(g=b.Za,e=b.Qb,g instanceof Pl&&(d=g.Za,g=g.Qb,d instanceof Pl&&(h=d.Za,d=d.Qb,h instanceof vl&&\"if\"===h.x&&\nd instanceof Gl&&(h=d.Ra,h instanceof z&&(d=h.z,h=h.p,null!==d&&(d=d.j(),null!==d&&(d=d.ya,k=O().c,(null===k?null===h:k.i(h))&&g instanceof Gl&&(h=g.Ra,h instanceof z&&(g=h.z,h=h.p,null!==g&&(g=g.j(),null!==g&&(g=g.ya,k=O().c,(null===k?null===h:k.i(h))&&e instanceof Gl&&(e=e.Ra,e instanceof z&&(h=e.z,e=e.p,null!==h&&(h=h.j(),null!==h&&(h=h.ya,k=O().c,null===k?null===e:k.i(e)))))))))))))))))return new on(Zm(a,d,c),Zm(a,g,c),Zm(a,h,c));null!==b&&(e=b.Za,e instanceof Pl&&(e=e.Za,e instanceof Pl&&(e=\ne.Za,e instanceof vl&&\"if\"===e.x&&xm(\"Program reached and unexpected state.\"))));if(null!==b&&(e=b.Za,d=b.Qb,d instanceof Gl)){h=d.Ra;b=Zm(a,e,c);e=l=>{if(null!==l){var m=l.j();if(null!==m)return Zm(a,m.ya,c)}throw new w(l);};if(h===u())e=u();else{d=h.e();g=d=new z(e(d),u());for(h=h.f();h!==u();)k=h.e(),k=new z(e(k),u()),g=g.p=k,h=h.f();e=d}return new cn(b,e)}null!==b&&no();throw new gm(\"ill-formed application \"+b);}\nfunction Zm(a,b,c){var d=!1,e=null,g=!1,h=null,k=!1,l=null;if(!b.oc.b()){var m=b.oc;m.b()&&xm(\"Program reached and unexpected state.\");return Zm(a,m.o(),c)}if(b instanceof vl)return fo(a,b.x,!1,c);if(b instanceof am)return new km(\"super\");if(b instanceof Ol){var n=b.Ej,r=b.Fj,v=Hm(c),x=im(a,n,v);return new oo(x,po(v.lo,Zm(a,r,v)))}if(b instanceof Pl)return Maa(a,b,c);if(b instanceof yl){var A=b.ll,B=wa=>{if(null!==wa){var hb=wa.h(),ra=wa.j();if(null!==ra)return wa=hb.x,ra=Zm(a,ra.ya,c),G(new H,wa,\nra)}throw new w(wa);};if(A===u())var C=u();else{for(var D=A.e(),F=new z(B(D),u()),I=F,M=A.f();M!==u();){var N=M.e(),P=new z(B(N),u());I=I.p=P;M=M.f()}C=F}return new vo(C,O().c)}if(b instanceof Ql){var T=b.Vl,Y=b.ml;return om(Al(),Zm(a,T,c),Y.x)}if(b instanceof Rl){d=!0;e=b;var Z=e.Zn,S=e.$n,ea=e.Mm;if(!0===e.ep&&null!==Z){var ia=Z.x;if(S instanceof Ol){var X=S.Ej,sa=S.Fj,Ja=Hm(c),Xa=wl(Ja,ia),Fa=Hm(Ja),za=im(a,X,Fa),Qa=po(Fa.lo,Zm(a,sa,Fa));t();var Ma=new L(Xa);if(Qa instanceof Ud)var Ga=Qa.fa;else{if(!(Qa instanceof\nfe))throw new w(Qa);var ab=rn(Qa.aa),Hb=O().c;Ga=new z(ab,Hb)}var bc=new wo(Ma,za,Ga),yb=t().d,tb=new xl(Xa),eb=O().c,kb=new z(tb,eb),Rb=po(Ja.lo,Zm(a,ea,Ja)),Gb=O().c;return new dn(yb,kb,Rb,new z(bc,Gb))}}}if(d){var vb=e.Zn;if(!0===e.ep&&null!==vb)throw new gm(\"recursive non-function definition \"+vb.x+\" is not supported\");}if(d){var Tb=e.Zn,Nb=e.$n,ic=e.Mm;if(null!==Tb){var Va=Tb.x,cb=Hm(c),zb=wl(cb,Va),Ub=t().d,jb=new xl(zb),db=O().c,ub=new z(jb,db),Aa=po(cb.lo,Zm(a,ic,cb)),va=Zm(a,Nb,c),Ra=O().c;\nreturn new dn(Ub,ub,Aa,new z(va,Ra))}}if(b instanceof Sl){var rb=b.Dj,xb=Hm(c),mc=rb.m(),Ha=new xo(mc,new y(wa=>{if(wa instanceof yo){var hb=O().c;return new z(wa,hb)}if(wa instanceof Zn){hb=wa.Rb;var ra=wa.hj;null!==hb&&(hb=hb.x,ra.b()?ra=R():(ra=ra.o(),ra=new L(ra.x)),zo(xb,hb,t().d,ra))}return wa.nv().j()}));Od();var Ka=Pd(u(),Ha),Oa=t().d,Na=O().c;t();var Da=xb.lo,ta=Ka.m(),Ya=new Ao(ta),dc=new Ef(Ya,new y(wa=>{if(null!==wa){var hb=wa.h(),ra=wa.Sc();if(hb instanceof Pm&&(1+ra|0)===Ka.K())return rn(Zm(a,\nhb,xb))}if(null!==wa&&(hb=wa.h(),hb instanceof Pm))return new Bo(Zm(a,hb,xb));if(null!==wa){var wc=wa.h();if(wc instanceof Zn){hb=wc.wd;ra=wc.Rb;var ac=wc.hj;wc=wc.Yc;if(null!==ra&&(ra=ra.x,wc instanceof fe))return wa=wc.aa,ac.b()?ac=R():(ac=ac.o(),ac=new L(ac.x)),wc=hb.b()||Co(new Do(a,wa)),hb=Im(xb,ra,hb,wc,ac),t(),hb=hb.re,t(),wa=Zm(a,wa,xb),wa=[G(new H,hb,new L(wa))],wa=J(new K,wa),new Eo(Pd(u(),wa))}}if(null!==wa&&(hb=wa.h(),hb instanceof yo)){a:{wa=O().c;ac=Fo(a,new z(hb,wa),t().d,xb);if(null===\nac)throw new w(ac);ra=ac.oj;wa=ac.oi;ac=ac.Xi;if(ra instanceof z)wa=ra.z,t(),wa=new L(wa);else{wc=O().c;if(null===wc?null!==ra:!wc.i(ra))throw new w(ra);if(wa instanceof z)wa=wa.z,t(),wa=new L(wa);else{ra=O().c;if(null===ra?null!==wa:!ra.i(wa))throw new w(wa);ac instanceof z?(wa=ac.z,t(),wa=new L(wa)):wa=t().d}}ra=!1;ac=null;if(wa instanceof L&&(ra=!0,ac=wa,wa=ac.k,wa instanceof jn)){ra=Hm(xb);hb=Go(a,wa,t().d,!1,ra);ra=Im(ra,\"ctor\",new L(!1),!1,t().d).re;ac=Ho(hb);if(null===ac)throw new w(ac);wc=\nac.h();var Id=ac.j();if(wa.$u)t(),t(),ra=J(new K,[new Io(new L(new km(wa.mi)))]),ra=Pd(u(),ra);else{t();Jo();t();ac=J(new K,[ra]);ac=Ko(Pd(u(),ac));var ud=new km(ra);t();wc=new Bo(new Lo(ud,new oo(wc,new fe(new cn(new $m(new km(wa.mi)),Id)))));Id=new km(ra);Id=new Bo(new Lo(om(Al(),Id,\"class\"),new km(wa.mi)));t();ra=J(new K,[ac,wc,Id,new Io(new L(new km(ra)))]);ra=Pd(u(),ra)}wa=wa.mi;ac=t().d;wc=O().c;t();wa=new qn(wa,new dn(ac,wc,new Ud(new z(hb,ra)),O().c));break a}if(ra&&(wa=ac.k,wa instanceof\nHn)){hb=Hm(xb);ra=Im(hb,\"base\",new L(!1),!1,t().d);hb=Go(a,wa,(t(),new L(ra)),!1,hb);wa=wa.Hp;t();ra=J(new K,[new xl(ra.re)]);ra=Pd(u(),ra);t();t();t();hb=J(new K,[new Io(new L(new Mo(hb)))]);hb=Pd(u(),hb);wa=new qn(wa,new oo(ra,new Ud(hb)));break a}if(ra&&(ac=ac.k,ac instanceof ln)){wa=Hm(xb);wc=Go(a,ac,t().d,!1,wa);Id=Im(wa,\"ins\",new L(!1),!1,t().d).re;wa=ac.lj;hb=t().d;ra=O().c;t();t();Jo();t();ud=J(new K,[Id]);ud=Ko(Pd(u(),ud));var be=new Lo(new km(Id),new cn(new $m(new km(ac.lj)),O().c));be=\nnew Bo(be);var re=new km(Id);ac=new Bo(new Lo(om(Al(),re,\"class\"),new km(ac.lj)));t();ac=J(new K,[wc,ud,be,ac,new Io(new L(new km(Id)))]);ac=Pd(u(),ac);wa=new qn(wa,new dn(hb,ra,new Ud(ac),O().c));break a}throw new gm(\"unsupported NuTypeDef in local blocks: \"+hb);}return wa}if(null!==wa&&(wa.h()instanceof No||wa.h()instanceof Oo||wa.h()instanceof Zn||wa.h()instanceof Po))throw new gm(\"unsupported definitions in blocks\");throw new w(wa);}));Od();var ka=Qo(Da,Pd(u(),dc));return new dn(Oa,Na,new Ud(ka),\nO().c)}if(b instanceof Ul){g=!0;h=b;var ya=h.Sn,Sa=h.Hm;if(Sa instanceof ym){var xc=Sa.dn,Sb=Zm(a,ya,c),uc=Zm(a,xc,c),Lb=O().c;return new Ro(new z(Sb,new z(uc,Lb)))}}if(g){var lc=h.Sn,Xb=h.Hm;if(Xb instanceof um){var ec=Xb.Xo,Ab=Xb.Tn,Ob=Xb.Un;if(Ob instanceof ym){var fb=Ob.dn;return Ym(a,Zm(a,lc,c),ec,c).ba(Zm(a,Ab,c),Zm(a,fb,c))}}}if(g){var Wa=h.Hm,bb=Zm(a,h.Sn,c);if(bb.VJ())return en(a,bb,Wa,c);var Ia=Naa(c);c.lo.SA.oh(Ia);var Ua=new km(Ia),pc=new Lo(Ua,bb),sc=en(a,Ua,Wa,c),Ba=O().c;return new Ro(new z(pc,\nnew z(sc,Ba)))}if(b instanceof Em){var ob=b.rq,nc=ob.u();So||(So=new To);return new hn(nc+(Oaa(ob)?\"\":\"n\"))}if(b instanceof Fm)return new hn(b.uu.gd.u());if(b instanceof Dm)return an(b.Lu);if(b instanceof Gm)return new hn(b.Xq?\"undefined\":\"null\");if(b instanceof Cl)return Zm(a,b.ai,c);if(b instanceof Tl){var Ib=b.br,vc=b.ar;if(null!==vc){var Vb=vc.ll,fc=a.Cs.Yz.U(\"withConstruct\");if(fc instanceof L)var Bc=fc.k;else if(t().d===fc)Bc=ho(a.Cs,\"withConstruct\",Uo(a.di,\"withConstruct\"));else throw new w(fc);\nvar Pb=new km(Bc),Jb=Zm(a,Ib,c),gc=wa=>{if(null!==wa){var hb=wa.h(),ra=wa.j();if(null!==hb&&(hb=hb.x,null!==ra))return wa=Zm(a,ra.ya,c),G(new H,hb,wa)}throw new w(wa);};if(Vb===u())var Cb=u();else{for(var cc=Vb.e(),yc=new z(gc(cc),u()),Mc=yc,qc=Vb.f();qc!==u();){var oc=qc.e(),Qc=new z(gc(oc),u());Mc=Mc.p=Qc;qc=qc.f()}Cb=yc}var jc=new vo(Cb,O().c),sb=O().c;return new cn(Pb,new z(Jb,new z(jc,sb)))}}if(b instanceof Fl){k=!0;l=b;var Gc=l.gg;if(!1===l.bi){if(Gc instanceof Pl){var Wb=Gc.Za;if(Wb instanceof\nvl){var Cc=Wb.x;if(Lm().gD.L(Cc))return new Vo(Zm(a,Gc,c))}}return Zm(a,Gc,c)}}if(k)return Zm(a,l.gg,c);if(b instanceof Gl){var Fc=b.Ra,qd=wa=>{if(null!==wa){var hb=wa.j();if(null!==hb)return Zm(a,hb.ya,c)}throw new w(wa);};if(Fc===u())var Yb=u();else{for(var Nc=Fc.e(),ad=new z(qd(Nc),u()),Uc=ad,cd=Fc.f();cd!==u();){var kc=cd.e(),Vc=new z(qd(kc),u());Uc=Uc.p=Vc;cd=cd.f()}Yb=ad}return new Wo(Yb)}if(b instanceof Vl){var Hc=b.mp,rc=Zm(a,b.lp,c),sd=Zm(a,Hc,c);return Xo(new Yo,rc,sd)}if(b instanceof dm){var Kc=\nb.$q,Qd=b.Zq,Ad=t().d,kd=O().c;t();var Hd=new Zo(Zm(a,Kc,c),Zm(a,Qd,c)),Rd=O().c;return new dn(Ad,kd,new Ud(new z(Hd,Rd)),O().c)}if(b instanceof Wl){var Bd=b.Gm,ae=b.Qn;if(Bd instanceof Vl||Bd instanceof Ql||Bd instanceof vl)return new $o(\"void\",new Lo(Zm(a,Bd,c),Zm(a,ae,c)));throw new gm(\"illegal assignemnt left-hand side: \"+Bd);}if(b instanceof Kl)return Zm(a,b.cp,c);if(b instanceof Xl)throw new gm(\"if expression was not desugared\");if(b instanceof Yl){var dd=b.hp;if(dd instanceof vl){var od=fo(a,\ndd.x,!0,c);return od instanceof $m?od:new $m(od)}throw new gm(\"Unsupported `new` class term: \"+dd);}if(b instanceof Zl)return Zm(a,b.$o,c);if(b instanceof Il)return Zm(a,b.nl,c);if(b instanceof bm){var Ta=b.Vn;if(null!==Ta)throw new gm(\"assignment of \"+Ta.x+\" is not supported outside a constructor\");}if(b instanceof em){var wb=b.Iq,$a=Hm(c);return Zm(a,vm(a,wb,$a,!0,new Jm(a,ap())),$a)}if(b instanceof Ml)return Zm(a,b.Ml,c);if(b instanceof Xl||b instanceof $l||b instanceof cm||b instanceof fm)throw new gm(\"cannot generate code for term \"+\nb);throw new w(b);}function tn(a){if(a.sF){a=new qn(a.re,new km(\"this\"));var b=O().c;return new z(a,b)}return O().c}\nfunction bp(a,b){if(null!==a){var c=a.pb,d=a.gb;if(cp()===c&&null!==d){c=d.V;a=new km(\"globalThis\");a=om(Al(),a,c);d=new xl(\"base\");var e=O().c;d=new z(d,e);t();b=new km(b);b=om(Al(),b,c);c=new km(\"base\");e=O().c;return new Bo(new Lo(a,new oo(d,new fe(new cn(b,new z(c,e))))))}}if(null!==a&&(c=a.gb,null!==c))return a=c.V,c=new km(\"globalThis\"),c=om(Al(),c,a),b=new km(b),b=new Lo(c,om(Al(),b,a)),new Bo(b);throw new w(a);}\nfunction Paa(a,b,c,d){c=Im(d,\"base\",new L(!1),!1,t().d);a=Go(a,b,(t(),new L(c)),!1,d);d=b.CA;d.b()&&xm(\"Program reached and unexpected state.\");d=d.o();d=new qn(d,new km(\"this\"));b=b.Hp;t();c=J(new K,[new xl(c.re)]);c=Pd(u(),c);t();var e=O().c;d=new z(d,e);t();t();a=J(new K,[new Io(new L(new Mo(a)))]);a=dl(Pd(u(),a),d);return new vn(b,c,new Ud(a))}\nfunction Qaa(a,b,c,d){d=Go(a,b,t().d,!1,d);c=new km(\"this.#\"+b.lj);a=b.DA;a.b()&&xm(\"Program reached and unexpected state.\");a=a.o();var e=new qn(a,new km(\"this\"));a=b.lj;t();var g=O().c;e=new z(e,g);t();g=new gn(\"\\x3d\\x3d\\x3d\",c,new km(\"undefined\"));t();b=[d,new Bo(new Lo(c,new $m(new cn(new km(b.lj),O().c)))),new Bo(new Lo(om(Al(),c,\"class\"),new km(b.lj)))];b=J(new K,b);b=[new dp(g,Pd(u(),b),O().c),new Io((t(),new L(c)))];b=J(new K,b);b=dl(Pd(u(),b),e);return new wn(a,new Ud(b))}\nfunction Ho(a){var b=a.sq;if(b===u())var c=u();else{c=b.e();var d=c=new z(new xl(c),u());for(b=b.f();b!==u();){var e=b.e();e=new z(new xl(e),u());d=d.p=e;b=b.f()}}b=a.sq;if(b===u())a=u();else for(a=b.e(),d=a=new z(new km(a),u()),b=b.f();b!==u();)e=b.e(),e=new z(new km(e),u()),d=d.p=e,b=b.f();return G(new H,c,a)}\nfunction Raa(a,b,c,d){a=Go(a,b,t().d,!1,d);c=Ho(a);if(null===c)throw new w(c);var e=c.h(),g=c.j();d=new km(\"this.#\"+b.mi);c=b.Qx;c.b()&&xm(\"Program reached and unexpected state.\");c=c.o();c=new qn(c,new km(\"this\"));if(b.$u)t(),e=J(new K,[new Bo(new Lo(d,new km(b.mi)))]),e=Pd(u(),e);else{t();t();var h=new km(\"Object\");h=om(Al(),h,\"freeze\");t();g=J(new K,[new cn(new $m(new km(b.mi)),g)]);g=new cn(h,Pd(u(),g));e=new Bo(new Lo(d,new oo(e,new fe(g))));g=new Bo(new Lo(om(Al(),d,\"class\"),new km(b.mi)));\nh=om(Al(),d,\"unapply\");var k=new km(b.mi);e=[e,g,new Bo(new Lo(h,om(Al(),k,\"unapply\")))];e=J(new K,e);e=Pd(u(),e)}b=b.mi;t();t();a=[new dp(new gn(\"\\x3d\\x3d\\x3d\",d,new km(\"undefined\")),new z(new Bo(new Mo(a)),e),O().c),new Io((t(),new L(d)))];a=J(new K,a);a=Pd(u(),a);return new wn(b,new Ud(new z(c,a)))}\nfunction Go(a,b,c,d,e){var g=new $e,h=Hm(e,b.u()),k=Hm(h,b.Ua()+\" inheritance\"),l=Hm(h,b.Ua()+\" body\"),m=Hm(l,b.Ua()+\" constructor\"),n=u(),r=ep(new fp,n),v=u(),x=ep(new fp,v),A=b.FB(),B=Zd=>{var sf=Hm(l),oj=gp(sf,\"qualifier\");Zd=Zd.Cf.x;var al=g.sb?g.vb:Mn(a,g);sf=new np(al.fD,sf,oj);return G(new H,Zd,sf)};if(A===u())var C=u();else{for(var D=A.e(),F=new z(B(D),u()),I=F,M=A.f();M!==u();){var N=M.e(),P=new z(B(N),u());I=I.p=P;M=M.f()}C=F}var T=b.EB(),Y=Zd=>{var sf=Hm(l),oj=gp(sf,\"qualifier\");Zd=Zd.uq.x;\nvar al=g.sb?g.vb:Mn(a,g);sf=new np(al.fD,sf,oj);return G(new H,Zd,sf)};if(T===u())var Z=u();else{for(var S=T.e(),ea=new z(Y(S),u()),ia=ea,X=T.f();X!==u();){var sa=X.e(),Ja=new z(Y(sa),u());ia=ia.p=Ja;X=X.f()}Z=ea}var Xa=un(C,Z);op();var Fa=pp(qp(),Xa),za=new rp(Fa),Qa=sp(za);if(Qa.b()){t();var Ma=gp(m,\"qualifier\"),Ga=new L(Ma)}else{for(var ab=Qa.o(),Hb=(new rp(Fa)).m();Hb.s();){var bc=Hb.t();if(bc.dp!==ab.dp)throw new Yj(\"assertion failed: the expected qualifier's runtime name should be \"+(ab.dp+\n\", \"+bc.dp)+\" found\");}tp();var yb=gp(m,ab.dp);up(0,yb===ab.dp);t();Ga=new L(ab.dp)}for(var tb=b.wK(),eb=zn(b.mv()),kb=null,Rb=null;eb!==u();){for(var Gb=eb.e(),vb=xn(a,Gb).m();vb.s();){var Tb=new z(vb.t(),u());null===Rb?kb=Tb:Rb.p=Tb;Rb=Tb}eb=eb.f()}var Nb=null===kb?u():kb,ic=un(tb,Nb),Va=new fp,cb=b.GF();if(cb.b()){var zb=Zd=>{var sf=new lo(Zd,new L(!1),!1,!b.vy().L(Zd),Ga);vp(l,sf);wp(r,sf);Im(k,Zd,new L(!1),!1,t().d);return Im(m,Zd,new L(!1),!1,t().d).re};if(ic===u())var Ub=u();else{for(var jb=\nic.e(),db=new z(zb(jb),u()),ub=db,Aa=ic.f();Aa!==u();){var va=Aa.e(),Ra=new z(zb(va),u());ub=ub.p=Ra;Aa=Aa.f()}Ub=db}}else{var rb=cb.o(),xb=Zd=>{if(Zd.cy()){var sf=new lo(Zd.h(),new L(!1),!1,!1,Ga);vp(l,sf);wp(r,sf);sf=G(new H,!1,Zd.h());wp(Va,sf)}return Im(m,Zd.h(),new L(!1),!1,t().d).re};if(rb===u())Ub=u();else{for(var mc=rb.e(),Ha=new z(xb(mc),u()),Ka=Ha,Oa=rb.f();Oa!==u();){var Na=Oa.e(),Da=new z(xb(Na),u());Ka=Ka.p=Da;Oa=Oa.f()}Ub=Ha}}var ta=Va.ha(),Ya=Zd=>{if(null!==Zd)return Zd=Zd.j(),new Bo(new Lo(new km(\"this.#\"+\nZd),new km(Zd)));throw new w(Zd);};if(ta===u())var dc=u();else{for(var ka=ta.e(),ya=new z(Ya(ka),u()),Sa=ya,xc=ta.f();xc!==u();){var Sb=xc.e(),uc=new z(Ya(Sb),u());Sa=Sa.p=uc;xc=xc.f()}dc=ya}for(var Lb=b.EB();!Lb.b();){var lc=Lb.e(),Xb=new lo(lc.uq.x,t().d,!0,!1,Ga);vp(l,Xb);wp(r,Xb);Lb=Lb.f()}for(var ec=b.ZL();!ec.b();){var Ab=ec.e().uq.x,Ob=t().d,fb=zo(l,Ab,t().d,Ob);wp(r,fb);ec=ec.f()}for(var Wa=b.HF();!Wa.b();){var bb=Wa.e();if(bb instanceof Zn){var Ia=bb,Ua=Ia.wd,pc=Ia.Rb;if(null!==pc){var sc=\nnew lo(pc.x,Ua,!1,!Ia.Pl,Ga);vp(l,sc);wp(r,sc)}}Wa=Wa.f()}var Ba=Fo(a,b.FB(),Ga,l);if(null===Ba)throw new w(Ba);var ob=Ba.oj,nc=Ba.oi,Ib=Ba.Xi;d&&Fo(a,b.FB(),t().d,a.di);for(var vc=ob;!vc.b();){var Vb=vc.e();wp(r,Vb);wp(x,Vb.mi);vc=vc.f()}for(var fc=nc;!fc.b();){var Bc=fc.e();wp(r,Bc);fc=fc.f()}for(var Pb=Ib;!Pb.b();){var Jb=Pb.e();wp(r,Jb);wp(x,Jb.lj);Pb=Pb.f()}var gc=b.EB(),Cb=Zd=>Laa(a,Zd,ic,Ga,Fa.Se(Zd.uq.x,new U(()=>{xm(\"Program reached and unexpected state.\")})).zu);if(gc===u())var cc=u();else{for(var yc=\ngc.e(),Mc=new z(Cb(yc),u()),qc=Mc,oc=gc.f();oc!==u();){var Qc=oc.e(),jc=new z(Cb(Qc),u());qc=qc.p=jc;oc=oc.f()}cc=Mc}var sb=Zd=>Paa(a,Zd,r.ha(),Fa.Se(Zd.Hp,new U(()=>{xm(\"Program reached and unexpected state.\")})).zu);if(nc===u())var Gc=u();else{for(var Wb=nc.e(),Cc=new z(sb(Wb),u()),Fc=Cc,qd=nc.f();qd!==u();){var Yb=qd.e(),Nc=new z(sb(Yb),u());Fc=Fc.p=Nc;qd=qd.f()}Gc=Cc}var ad=un(cc,Gc),Uc=Zd=>Qaa(a,Zd,r.ha(),Fa.Se(Zd.lj,new U(()=>{xm(\"Program reached and unexpected state.\")})).zu);if(Ib===u())var cd=\nu();else{for(var kc=Ib.e(),Vc=new z(Uc(kc),u()),Hc=Vc,rc=Ib.f();rc!==u();){var sd=rc.e(),Kc=new z(Uc(sd),u());Hc=Hc.p=Kc;rc=rc.f()}cd=Vc}var Qd=un(ad,cd),Ad=Zd=>Raa(a,Zd,r.ha(),Fa.Se(Zd.mi,new U(()=>{xm(\"Program reached and unexpected state.\")})).zu);if(ob===u())var kd=u();else{for(var Hd=ob.e(),Rd=new z(Ad(Hd),u()),Bd=Rd,ae=ob.f();ae!==u();){var dd=ae.e(),od=new z(Ad(dd),u());Bd=Bd.p=od;ae=ae.f()}kd=Rd}var Ta=un(Qd,kd);if(c instanceof L){var wb=c.k;t();var $a=new L(new km(wb.re))}else $a=Kaa(b.pH(),\ne);for(var wa=zn(b.mv()),hb=null,ra=null;wa!==u();){var wc=wa.e(),ac=!1,Id=null,ud=e.ko.U(wc);a:{if(ud instanceof L){ac=!0;Id=ud;var be=Id.k;if(be instanceof mn){var re=be.Tx;t();var pe=new L(re);break a}}if(ac&&null!==Id.k)pe=t().d;else if(t().d===ud)pe=t().d;else throw new w(ud);}for(var bd=pe.m();bd.s();){var Rc=new z(bd.t(),u());null===ra?hb=Rc:ra.p=Rc;ra=Rc}wa=wa.f()}var Wc=null===hb?u():hb;if(c.b()){var Wd=b.pH(),zd=Zd=>{if(Zd instanceof Pl&&(Zd=Zd.Qb,Zd instanceof Gl)){var sf=Zd.Ra;Zd=Qm=>\n{if(null!==Qm){var Rm=Qm.j();if(null!==Rm)return Zm(a,Rm.ya,k)}throw new w(Qm);};if(sf===u())return u();var oj=sf.e(),al=oj=new z(Zd(oj),u());for(sf=sf.f();sf!==u();){var Ll=sf.e();Ll=new z(Zd(Ll),u());al=al.p=Ll;sf=sf.f()}return oj}return O().c};if(Wd===u())var Pa=u();else{for(var Db=Wd.e(),Oc=new z(zd(Db),u()),Tc=Oc,Sd=Wd.f();Sd!==u();){var Jc=Sd.e(),vd=new z(zd(Jc),u());Tc=Tc.p=vd;Sd=Sd.f()}Pa=Oc}for(var hd=Pa,de=null,ye=null;hd!==u();){for(var jf=Km(hd.e()).m();jf.s();){var af=new z(jf.t(),u());\nnull===ye?de=af:ye.p=af;ye=af}hd=hd.f()}var pf=Km(null===de?u():de),kf=t().d;Jd=pf;Dd=kf}else{var Be=Im(m,\"rest\",new L(!1),!1,t().d);t();var Kd=J(new K,[new km(\"...\"+Be.re)]),ld=Pd(u(),Kd);t();var Jd=ld,Dd=new L(Be.re)}for(var Xd=Jd,Yc=Dd,Ce=new fp,te=b.HF(),Ie=null,Jf=null;te!==u();){var df=te.e();a:{if(df instanceof bm){var vg=df,wg=vg.Vn,xg=vg.Zo;if(null!==wg){var eg=wg.x;t();var vh=new Lo(new km(\"this.#\"+eg),Zm(a,xg,m)),fg=[new Bo(vh),new qn(Im(m,eg,(t(),new L(!1)),!1,t().d).re,new km(\"this.#\"+\neg))],ih=J(new K,fg);var Ig=Pd(u(),ih);break a}}if(df instanceof Pm){var Tf=new Bo(Zm(a,df,m)),Jg=O().c;Ig=new z(Tf,Jg)}else{if(df instanceof Zn){var jh=df,yg=jh.Rb,gg=jh.Yc;if(null!==yg){var Cf=yg.x;if(gg instanceof fe){var Uf=gg.aa;if(jh.Pl){var $g=!jh.Om.b(),Ah=G(new H,$g,Cf);wp(Va,Ah);t();var Kg=[new Bo(new Lo(new km(\"this.#\"+Cf),Zm(a,Uf,m))),new qn(Im(m,Cf,(t(),new L(!1)),!1,t().d).re,new km(\"this.#\"+Cf))],Vf=J(new K,Kg);Ig=Pd(u(),Vf)}else{var hg=Cm(l,Cf);b:{if(hg instanceof L){var zg=hg.k;if(zg instanceof\nlo){var Lg=zg;break b}}throw new Yj(\"error when handling \"+Cf);}if(Lg.OP||Ub.L(Cf)){wp(Ce,Cf);t();var Mg=[new Bo(new Lo(new km(\"this.#\"+Cf),Zm(a,Uf,m))),new qn(Im(m,Cf,(t(),new L(!1)),!1,t().d).re,new km(\"this.#\"+Cf))],Wf=J(new K,Mg);Ig=Pd(u(),Wf)}else{var Ng=new qn(Im(m,Cf,(t(),new L(!1)),!1,t().d).re,Zm(a,Uf,m)),Kf=O().c;Ig=new z(Ng,Kf)}}break a}}}Ig=O().c}}for(var xf=Ig.m();xf.s();){var Og=new z(xf.t(),u());null===Jf?Ie=Og:Jf.p=Og;Jf=Og}te=te.f()}var mi=null===Ie?u():Ie,Ci=sn(m.lo);if(Ci instanceof\nL)var Xh=Ci.k,wh=O().c,Bh=new z(Xh,wh);else Bh=O().c;var ng=b.iM();if(ng instanceof L){var kh=ng.k.bx;a:{if(null!==kh){var Kh=kh.aa;if(Kh instanceof Ol){var ni=Kh.Ej,Lh=Kh.Fj;if(ni instanceof Gl){var lh=ni.Ra;if(lh instanceof z){var Ch=lh.z,Dh=lh.p;if(null!==Ch){var Yh=new L(Ch);if(!Yh.b()){var ah=Yh.k.j();if(null!==ah){var oi=ah.ya;if(oi instanceof vl){var mj=oi.x,wd=O().c;if((null===wd?null===Dh:wd.i(Dh))&&Lh instanceof Rl){var ge=Lh.Mm;if(ge instanceof Gl){var De=ge.Ra,qf=wl(Hm(h,\"unapply \"+b.Ua()),\nmj),og=new xl(qf),Xf=O().c,mh=new z(og,Xf);t();var Ag=Zd=>{if(null!==Zd){var sf=new L(Zd);if(!sf.b()&&(sf=sf.k.j(),null!==sf)){Zd=sf.ya;if(Zd instanceof Ql){var oj=Zd.Vl;sf=Zd.ml;if(oj instanceof vl&&(oj=oj.x,null!==sf))return new km(oj+\".\"+sf.x)}return Zm(a,Zd,e)}}throw new w(Zd);};if(De===u())var Bg=u();else{for(var Eh=De.e(),Pg=new z(Ag(Eh),u()),Di=Pg,Mh=De.f();Mh!==u();){var pi=Mh.e(),Xi=new z(Ag(pi),u());Di=Di.p=Xi;Mh=Mh.f()}Bg=Pg}var Qg=new vn(\"unapply\",mh,new fe(new Wo(Bg))),nh=O().c;var bh=\nnew z(Qg,nh);break a}}}}}}}}}}throw new gm(\"invalid unapply method in \"+b.Ua());}}else bh=O().c;var Mj=Ga.b()?O().c:tn(lm(m,Ga.k)),Nj=b.Ua(),ie=ic;a:for(var Ac;;)if(ie.b()){Ac=u();break}else{var Ve=ie.e(),Td=ie.f();if(!1===!!b.vy().L(Ve))ie=Td;else for(var lf=ie,Yi=Td;;){if(Yi.b())Ac=lf;else{var Jl=Yi.e();if(!1!==!!b.vy().L(Jl)){Yi=Yi.f();continue}for(var ll=Yi,Bj=new z(lf.e(),u()),$k=lf.f(),Zh=Bj;$k!==ll;){var Ei=new z($k.e(),u());Zh=Zh.p=Ei;$k=$k.f()}for(var Yd=ll.f(),bf=Yd;!Yd.b();){var rf=Yd.e();\nif(!1===!!b.vy().L(rf)){for(;bf!==Yd;){var Cg=new z(bf.e(),u());Zh=Zh.p=Cg;bf=bf.f()}bf=Yd.f()}Yd=Yd.f()}bf.b()||(Zh.p=bf);Ac=Bj}break a}}if(Ac===u())var nj=u();else{for(var Jh=Ac.e(),If=new z(G(new H,!1,Jh),u()),Hg=If,He=Ac.f();He!==u();){var lj=He.e(),Wi=new z(G(new H,!1,lj),u());Hg=Hg.p=Wi;He=He.f()}nj=If}var Oj=Va.ha(),mo=un(nj,Oj),mm=un(Ce.ha(),ic),nm=un(un(un(Mj,Bh),dc),mi),dq=x.ha();return new xp(Nj,ic,mo,mm,$a,Xd,Ub,Yc,Ta,Wc,nm,dq,!b.GF().b(),bh)}\nfunction Fo(a,b,c,d){for(var e=new fp,g=new fp,h=new fp,k=new fp,l=b;!l.b();){var m=l.e();a:{if(null!==m){var n=m.pb,r=m.gb,v=m.hg,x=m.Sg,A=m.Di,B=m.ei;if(cp()===n&&null!==r){var C=r.V,D=Rn(a,C,(x.b()?new Gl(O().c):x.o()).Ra,A,B);if(null===D)throw new w(D);var F=D.lr,I=D.mr,M=D.rt,N=D.st,P=D.tt,T=D.kv;if(v===u())var Y=u();else{for(var Z=v.e(),S=new z(Z.j().V,u()),ea=S,ia=v.f();ia!==u();){var X=ia.e(),sa=new z(X.j().V,u());ea=ea.p=sa;ia=ia.f()}Y=S}var Ja=new Hn(C,Y,F,I,M,N,T,P,c);yp(d,Ja);m.fl.b()&&\nwp(h,Ja);break a}}if(null!==m){var Xa=m.pb,Fa=m.gb,za=m.hg,Qa=m.Sg,Ma=m.Di,Ga=m.ei;if(zp()===Xa&&null!==Fa){var ab=Fa.V,Hb=Rn(a,ab,(Qa.b()?new Gl(O().c):Qa.o()).Ra,Ma,Ga);if(null===Hb)throw new w(Hb);var bc=Hb.lr,yb=Hb.mr,tb=Hb.rt,eb=Hb.st,kb=Hb.tt;if(za===u())var Rb=u();else{for(var Gb=za.e(),vb=new z(Gb.j().V,u()),Tb=vb,Nb=za.f();Nb!==u();){var ic=Nb.e(),Va=new z(ic.j().V,u());Tb=Tb.p=Va;Nb=Nb.f()}Rb=vb}var cb=new ln(ab,Rb,bc,yb,tb,eb,Ma,kb,c);yp(d,cb);m.fl.b()&&wp(k,cb);break a}}if(null!==m){var zb=\nm.pb,Ub=m.gb,jb=m.hg,db=m.Hj;if(Ap()===zb&&null!==Ub){var ub=Ub.V;if(jb===u())var Aa=u();else{for(var va=jb.e(),Ra=new z(va.j().V,u()),rb=Ra,xb=jb.f();xb!==u();){var mc=xb.e(),Ha=new z(mc.j().V,u());rb=rb.p=Ha;xb=xb.f()}Aa=Ra}Saa(d,ub,Aa,db.b()?gl():db.o());break a}}if(null!==m){var Ka=m.pb,Oa=m.gb,Na=m.hg,Da=m.Sg,ta=m.Qm,Ya=m.Di,dc=m.ei;if(Bp()===Ka&&null!==Oa){var ka=Oa.V;b:{if(ta instanceof L){var ya=ta.k;if(null!==ya){var Sa=ya.ks,xc=ya.js;if(null!==Sa){var Sb=Sa.Ra;if(null!==xc){var uc=xc.Dj;\nt();var Lb=(dd=>od=>{if(null!==od){var Ta=od.h(),wb=od.j();if(Ta instanceof L&&(Ta=Ta.k,null!==Ta&&(Ta=Ta.x,null!==wb)))return G(new H,Ta,wb.yb.Bh)}if(null!==od&&(wb=od.h(),od=od.j(),t().d===wb&&null!==od&&(wb=od.yb,od=od.ya,od instanceof vl)))return G(new H,od.x,wb.Bh);throw new gm(\"Unexpected constructor parameters in \"+dd+\".\");})(ka);if(Sb===u())var lc=u();else{for(var Xb=Sb.e(),ec=new z(Lb(Xb),u()),Ab=ec,Ob=Sb.f();Ob!==u();){var fb=Ob.e(),Wa=new z(Lb(fb),u());Ab=Ab.p=Wa;Ob=Ob.f()}lc=ec}var bb=\nnew L(lc);var Ia=uc;break b}}}}var Ua=t().d,pc=O().c;bb=Ua;Ia=pc}var sc=bb,Ba=Ia,ob=Rn(a,ka,(Da.b()?new Gl(O().c):Da.o()).Ra,Ya,dc);if(null===ob)throw new w(ob);var nc=ob.lr,Ib=ob.mr,vc=ob.rt,Vb=ob.st,fc=ob.tt,Bc=ob.kv;if(Na===u())var Pb=u();else{for(var Jb=Na.e(),gc=new z(Jb.j().V,u()),Cb=gc,cc=Na.f();cc!==u();){var yc=cc.e(),Mc=new z(yc.j().V,u());Cb=Cb.p=Mc;cc=cc.f()}Pb=gc}var qc=Cp(m);b:{if(qc instanceof L){var oc=qc.k;if(null!==oc){var Qc=oc.wd,jc=oc.Rb,sb=oc.Ch,Gc=oc.Yc;if(Gc instanceof fe){var Wb=\nGc.aa;t();var Cc=new Dp(!(Qc.b()||!Qc.o()),new Ep(ka),jc,sb,(O(),new fe(Wb)));var Fc=new L(Cc);break b}}}Fc=t().d}var qd=new jn(ka,Pb,sc,nc,Ib,Fc,vc,un(Ba,Vb),Ya,Bc,fc,c,m.Sg.b());yp(d,qd);m.fl.b()&&wp(g,qd);break a}}if(null!==m){var Yb=m.pb,Nc=m.gb,ad=m.hg,Uc=m.Sg,cd=m.Di,kc=m.ei;if(Fp()===Yb&&null!==Nc){var Vc=Nc.V,Hc=Rn(a,Vc,(Uc.b()?new Gl(O().c):Uc.o()).Ra,cd,kc);if(null===Hc)throw new w(Hc);var rc=Hc.lr,sd=Hc.mr;if(ad===u())var Kc=u();else{for(var Qd=ad.e(),Ad=new z(Qd.j().V,u()),kd=Ad,Hd=ad.f();Hd!==\nu();){var Rd=Hd.e(),Bd=new z(Rd.j().V,u());kd=kd.p=Bd;Hd=Hd.f()}Kc=Ad}var ae=Taa(d,Vc,Kc,rc,sd);m.fl.b()&&wp(e,ae);break a}}throw new w(m);}l=l.f()}return new Gp(e.ha(),g.ha(),h.ha(),k.ha())}function To(){this.kN=this.jN=null;So=this;this.jN=Hp(\"9007199254740991\");this.kN=Hp(\"-9007199254740991\")}To.prototype=new p;To.prototype.constructor=To;function Oaa(a){var b=So;return 0>=b.kN.$l(a)?0>=a.$l(b.jN):!1}To.prototype.$classData=q({nV:0},!1,\"mlscript.JSBackend$\",{nV:1,g:1});var So;\nfunction Jm(a,b){this.xH=b;if(null===a)throw null;}Jm.prototype=new p;Jm.prototype.constructor=Jm;Jm.prototype.$classData=q({uV:0},!1,\"mlscript.JSBackend$FreeVars\",{uV:1,g:1});function Do(a,b){this.yH=null;this.yV=b;if(null===a)throw null;this.yH=a}Do.prototype=new p;Do.prototype.constructor=Do;function Co(a){var b=a.yV;if(b instanceof Ol)return!0;if(b instanceof Fl){var c=b.gg;if(!1===b.bi)return Co(new Do(a.yH,c))}return b instanceof Cl?Co(new Do(a.yH,b.ai)):!1}\nDo.prototype.$classData=q({xV:0},!1,\"mlscript.JSBackend$TermOps\",{xV:1,g:1});function Ip(){}Ip.prototype=new p;Ip.prototype.constructor=Ip;function Jp(){}Jp.prototype=Ip.prototype;function Kp(){}Kp.prototype=new p;Kp.prototype.constructor=Kp;function an(a){Lp();return new hn(Mp(Np(),a))}\nfunction Op(a,b){return Pp(Hf(b).De(Qp().ye,new fn((c,d)=>{var e=G(new H,c,d);c=e.y;d=e.w;if(null!==d)return e=d.h(),d=d.Sc(),Rp(Rp(c,e instanceof El?Sp(Qp(),\"_\"+d):e.xa()),Pe(new E(d),-1+b.K()|0)?Qp().ye:Sp(Qp(),\", \"));throw new w(e);})),!0)}function Tp(a,b){return Pp(Hf(b).De(Qp().ye,new fn((c,d)=>{var e=G(new H,c,d);c=e.y;d=e.w;if(null!==d)return e=d.Sc(),Rp(Rp(c,Up(d.h(),Vp().Az)),Pe(new E(e),-1+b.K()|0)?Qp().ye:Sp(Qp(),\", \"));throw new w(e);})),!0)}\nKp.prototype.$classData=q({MV:0},!1,\"mlscript.JSExpr$\",{MV:1,g:1});var Wp;function Lp(){Wp||(Wp=new Kp);return Wp}function Xp(){this.zH=null;Yp=this;var a=new Zp;u();var b=Dk(\"^[A-Za-z$][A-Za-z0-9$]*$\");a.nG=b;this.zH=a}Xp.prototype=new p;Xp.prototype.constructor=Xp;function om(a,b,c){return new $p(b,new km(c))}function aq(a,b){return bq(new cq(a.zH.nG,nb(b)))?!eq().qF.L(b):!1}function zl(a,b){return aq(a,b)?b:Mp(Np(),b)}Xp.prototype.$classData=q({PV:0},!1,\"mlscript.JSField$\",{PV:1,g:1});var Yp;\nfunction Al(){Yp||(Yp=new Xp);return Yp}function fq(a){if(a instanceof Em){tp();a=gq(new Ep(\"int\"));var b=new Ep(\"number\");return a.bc(b)}if(a instanceof Dm)return tp(),gq(new Ep(\"string\"));if(a instanceof Fm)return tp(),gq(new Ep(\"number\"));if(a instanceof Gm)return ap();throw new w(a);}\nfunction yq(a){if(a instanceof Em){tp();a=gq(new Ep(\"Int\"));var b=new Ep(\"Num\");a=a.bc(b);b=new Ep(\"Object\");return a.bc(b)}if(a instanceof Dm)return tp(),a=gq(new Ep(\"Str\")),b=new Ep(\"Object\"),a.bc(b);if(a instanceof Fm)return tp(),a=gq(new Ep(\"Num\")),b=new Ep(\"Object\"),a.bc(b);if(a instanceof Gm)return tp(),gq(new Ep(\"Object\"));throw new w(a);}function zq(a){if(a instanceof vl)return tp(),gq(a);a=a.Vj().m();a=new xo(a,new y(b=>b.jn().m()));return Aq(Bq(),a)}\nfunction Cq(a,b){b.b()||(b=b.o(),a.fm(b.fh),a.em(b.eh),t(),a.on(new L(b.dh)));return a}\nfunction Dq(a){var b=tc();try{if(0>a.rn()){var c=Eq(a),d=new Ef(c,new y(I=>I.fh)),e=Fq(),g=Gq(d,e);if(g.b())throw Hq(new Iq,b,t().d);a.fm(g.o()|0)}if(0>a.qn()){var h=Eq(a),k=new Ef(h,new y(I=>I.eh)),l=Fq(),m=Jq(k,l);if(m.b())throw Hq(new Iq,b,t().d);a.em(m.o()|0)}var n=a.pn();if(n.b()){var r=Eq(a),v=new Ef(r,new y(I=>I.dh));Od();var x=Pd(u(),v),A=hl(x)}else{var B=n.o(),C=O().c;A=new z(B,C)}c=A;var D=c.K();if(!Pe(new E(D),1))throw new Yj(\"assertion failed: \"+c);t();var F=new Kq(a.rn(),a.qn(),c.e());\nreturn new L(F)}catch(I){if(I instanceof Iq){a=I;if(a.Qg===b)return a.Cj();throw a;}throw I;}}\nfunction Lq(a){var b=tc();try{var c=Mq(a),d=new Ef(c,new y(N=>N.fh)),e=Fq(),g=Gq(d,e);if(g.b())throw Hq(new Iq,b,t().d);var h=g.o()|0,k=Mq(a),l=new Ef(k,new y(N=>N.eh)),m=Fq(),n=Jq(l,m);if(n.b())throw Hq(new Iq,b,t().d);var r=n.o()|0,v=a.pn();if(v.b()){var x=Mq(a),A=new Ef(x,new y(N=>N.dh));Od();var B=Pd(u(),A),C=hl(B)}else{var D=v.o(),F=O().c;C=new z(D,F)}a=C;tp();var I=a.K();up(0,Pe(new E(I),1));t();var M=new Kq(h,r,a.e());return new L(M)}catch(N){if(N instanceof Iq){h=N;if(h.Qg===b)return h.Cj();\nthrow h;}throw N;}}function Eq(a){a=a.Vj().m();return new xo(a,new y(b=>b.A().m()))}function Mq(a){var b=a.Vj();return new xo(new Om(new z(a,b)),new y(c=>c.A().m()))}function Nq(a){a.fm(-1);a.em(-1);a.on(t().d)}function Oq(){}Oq.prototype=new p;Oq.prototype.constructor=Oq;function Pq(){}Pq.prototype=Oq.prototype;function Te(a){this.mN=a}Te.prototype=new p;Te.prototype.constructor=Te;\nfunction Ye(a,b){tp();var c=b.K();up(0,Pe(new E(c),-1+a.mN.Jv.K()|0));c=a.mN.Jv.Ja(new y(d=>{var e=new Ue(J(new K,[d]));d=u();e=e.Jv;Qq();if(e.K()!==(1+d.K()|0))throw Kj(\"wrong number of arguments (\"+d.K()+\") for interpolated string with \"+e.K()+\" parts\");d=e.m();e=Rq().Pa;var g=d.t(),h=new Sq;g=Tq(Qq(),g);for(h=Uq(h,g);e.s();)g=e.t(),h.ja=\"\"+h.ja+g,g=d.t(),g=Tq(Qq(),g),h.ja=\"\"+h.ja+g;return new Vq(h.ja)}));a=c.e();c=c.f();b=new Wq(b,b,c);c=new fn((d,e)=>Xq(d.fp,e));Yq();b=Zq(b,c);return new $q(b.cc(a).ha())}\nTe.prototype.$classData=q({CW:0},!1,\"mlscript.Message$MessageContext\",{CW:1,g:1});function ar(){return new Em(br())}\nfunction cr(a,b,c){if(b<a.we&&Pe(new E(hc(a.$b.a[b])),hc(46))){for(var d=1+b|0,e=d,g=O().c,h=!1,k=!1,l,m,n,r;;){if(e<a.we){var v=a.$b.a[e];if(dr(v)){var x=new z(hc(v),g);e=1+e|0;g=x;k=!1;continue}if(Pe(new E(hc(v)),hc(95))){var A=1+e|0,B=g.b();e=A;h=B;k=!0;continue}var C=er(g).m(),D=ze(C,\"\",\"\",\"\"),F=h,I=k,M=e;l=D;m=F;n=I;r=M}else{var N=er(g).m(),P=ze(N,\"\",\"\",\"\"),T=h,Y=k,Z=e;l=P;m=T;n=Y;r=Z}break}var S=l,ea=!!n,ia=r|0;if(m){var X=a.Le;fr();var sa=Ye(new Te(new Ue(J(new K,[\"Leading separator is not allowed\"]))),\nu());t();var Ja=gr(a,-1+d|0,d),Xa=G(new H,sa,new L(Ja)),Fa=O().c;X.n(hr(0,new z(Xa,Fa),!0,ir()))}if(ea){var za=a.Le;fr();var Qa=Ye(new Te(new Ue(J(new K,[\"Trailing separator is not allowed\"]))),u());t();var Ma=gr(a,-1+ia|0,ia),Ga=G(new H,Qa,new L(Ma)),ab=O().c;za.n(hr(0,new z(Ga,ab),!0,ir()))}var Hb=G(new H,\"\"===S?t().d:(t(),new L(S)),ia);var bc=Hb.y,yb=Hb.w|0;if(t().d===bc){var tb=a.Le;jr();var eb=Ye(new Te(new Ue(J(new K,[\"Expect at least one digit after the decimal point\"]))),u());t();var kb=gr(a,\n1+b|0,2+b|0),Rb=G(new H,eb,new L(kb)),Gb=O().c;tb.n(kr(0,new z(Rb,Gb),!0,ir()));var vb=\"\";var Tb=yb}else{var Nb=Hb.y,ic=Hb.w|0;if(Nb instanceof L)vb=\".\"+Nb.k,Tb=ic;else throw new w(Hb);}}else vb=\"\",Tb=b;var Va=vb,cb=Tb|0;if(cb<a.we)var zb=a.$b.a[cb],Ub=Pe(new E(hc(zb)),hc(101))||Pe(new E(hc(zb)),hc(69));else Ub=!1;if(Ub){var jb=1+cb|0;if(jb<a.we)var db=a.$b.a[jb],ub=Pe(new E(hc(db)),hc(43))||Pe(new E(hc(db)),hc(45));else ub=!1;if(ub)var Aa=a.$b.a[1+cb|0],va=2+cb|0;else{var Ra=1+cb|0;Aa=43;va=Ra}for(var rb=\nAa,xb=va,mc=xb,Ha=O().c,Ka=!1,Oa=!1,Na,Da,ta,Ya;;){if(mc<a.we){var dc=a.$b.a[mc];if(dr(dc)){var ka=new z(hc(dc),Ha);mc=1+mc|0;Ha=ka;Oa=!1;continue}if(Pe(new E(hc(dc)),hc(95))){var ya=1+mc|0,Sa=Ha.b();mc=ya;Ka=Sa;Oa=!0;continue}var xc=er(Ha).m(),Sb=ze(xc,\"\",\"\",\"\"),uc=Ka,Lb=Oa,lc=mc;Na=Sb;Da=uc;ta=Lb;Ya=lc}else{var Xb=er(Ha).m(),ec=ze(Xb,\"\",\"\",\"\"),Ab=Ka,Ob=Oa,fb=mc;Na=ec;Da=Ab;ta=Ob;Ya=fb}break}var Wa=Na,bb=!!ta,Ia=Ya|0;if(Da){var Ua=a.Le;fr();var pc=Ye(new Te(new Ue(J(new K,[\"Leading separator is not allowed\"]))),\nu());t();var sc=gr(a,-1+xb|0,xb),Ba=G(new H,pc,new L(sc)),ob=O().c;Ua.n(hr(0,new z(Ba,ob),!0,ir()))}if(bb){var nc=a.Le;fr();var Ib=Ye(new Te(new Ue(J(new K,[\"Trailing separator is not allowed\"]))),u());t();var vc=gr(a,-1+Ia|0,Ia),Vb=G(new H,Ib,new L(vc)),fc=O().c;nc.n(hr(0,new z(Vb,fc),!0,ir()))}var Bc=G(new H,\"\"===Wa?t().d:(t(),new L(Wa)),Ia);var Pb=Bc.y,Jb=Bc.w|0;if(t().d===Pb){var gc=a.Le;jr();var Cb=Ye(new Te(new Ue(J(new K,[\"Expect at least one digit after the exponent sign\"]))),u());t();var cc=\ngr(a,-1+Jb|0,Jb),yc=G(new H,Cb,new L(cc)),Mc=O().c;gc.n(kr(0,new z(yc,Mc),!0,ir()));var qc=\"\";var oc=Jb}else{var Qc=Bc.y,jc=Bc.w|0;if(Qc instanceof L)qc=\"E\"+hc(rb)+Qc.k,oc=jc;else throw new w(Bc);}}else qc=\"\",oc=cb;var sb=qc,Gc=oc|0,Wb=O();0===(1&Wb.Jt)<<24>>24&&0===(1&Wb.Jt)<<24>>24&&(Wb.tR=lr(),Wb.Jt=(1|Wb.Jt)<<24>>24);var Cc=Wb.tR;var Fc=new H,qd=\"\"+c+Va+sb,Yb=new mr;nr(Yb,or(qd),qd.length);var Nc=pr(Yb)<=Cc.xy.ds?Cc.xy:new xi(pr(Yb),Bi().OC);var ad=new tr(Yb,Nc);return G(Fc,new Fm(ad),Gc)}\nfunction Uaa(a,b,c){var d=a.Le;jr();t();a=gr(a,c,1+c|0);b=G(new H,b,new L(a));a=O().c;d.n(kr(0,new z(b,a),!0,ir()))}function Hr(a,b,c,d,e){a=G(new H,c,gr(a,d,b));return new z(a,e)}\nfunction Je(a,b,c){this.$b=this.uN=this.vN=null;this.we=0;this.HH=this.JH=this.IH=null;this.Gs=0;this.OW=a;this.Le=b;this.NW=c;a=a.Us.TM;b=Ir();c=Ir();if(b===c)a=or(a);else if(b=new Jr(a),0<=b.Xh.length)a=new Ic(b.Xh.length),b.Gc(a,0,2147483647);else{a=[];for(b=Kr(new Lr,new Mr(b.Xh));0<b.bk;)c=b.t(),a.push(Ea(c));a=new Ic(new Uint16Array(a))}this.$b=a;this.we=this.$b.a.length;this.IH=Aq(tp().Iv,J(new K,[hc(33),hc(35),hc(37),hc(38),hc(42),hc(43),hc(45),hc(47),hc(58),hc(60),hc(61),hc(62),hc(63),hc(64),\nhc(92),hc(94),hc(124),hc(126),hc(46)]));this.JH=Aq(tp().Iv,J(new K,\"\\x3d\\x3e \\x3d : ; # `\".split(\" \")));this.HH=Aq(tp().Iv,J(new K,[\"with\",\"and\",\"or\",\"is\",\"as\"]))}Je.prototype=new p;Je.prototype.constructor=Je;function Nr(a){return Or(Pr(),a)||Pe(new E(hc(a)),hc(95))?!0:Pe(new E(hc(a)),hc(39))}function Qr(a){return Nr(a)||dr(a)||Pe(new E(hc(a)),hc(39))}function dr(a){return 48<=a&&57>=a}\nfunction Rr(a,b,c,d){return d<c.length&&(b+d|0)<a.we&&Pe(new E(hc(a.$b.a[b+d|0])),hc(c.charCodeAt(d)))?Rr(a,b,c,1+d|0):d>=c.length}function Vaa(a,b,c,d){for(;b<a.we&&d.n(hc(a.$b.a[b]));)c=new z(hc(a.$b.a[b]),c),b=1+b|0;a=er(c).m();return G(new H,ze(a,\"\",\"\",\"\"),b)}\nfunction Waa(a,b){if(b<a.we)if(48===a.$b.a[b])if((1+b|0)<a.we)switch(a.$b.a[1+b|0]){case 120:for(var c=2+b|0,d=c,e=O().c,g=!1,h=!1,k,l,m,n;;){if(d<a.we){var r=a.$b.a[d];if(dr(r)||97<=r&&102>=r||65<=r&&70>=r){var v=new z(hc(r),e);d=1+d|0;e=v;h=!1;continue}if(Pe(new E(hc(r)),hc(95))){var x=1+d|0,A=e.b();d=x;g=A;h=!0;continue}var B=er(e).m(),C=ze(B,\"\",\"\",\"\"),D=g,F=h,I=d;k=C;l=D;m=F;n=I}else{var M=er(e).m(),N=ze(M,\"\",\"\",\"\"),P=g,T=h,Y=d;k=N;l=P;m=T;n=Y}break}var Z=k,S=!!m,ea=n|0;if(l){var ia=a.Le;fr();\nvar X=Ye(new Te(new Ue(J(new K,[\"Leading separator is not allowed\"]))),u());t();var sa=gr(a,-1+c|0,c),Ja=G(new H,X,new L(sa)),Xa=O().c;ia.n(hr(0,new z(Ja,Xa),!0,ir()))}if(S){var Fa=a.Le;fr();var za=Ye(new Te(new Ue(J(new K,[\"Trailing separator is not allowed\"]))),u());t();var Qa=gr(a,-1+ea|0,ea),Ma=G(new H,za,new L(Qa)),Ga=O().c;Fa.n(hr(0,new z(Ma,Ga),!0,ir()))}var ab=G(new H,\"\"===Z?t().d:(t(),new L(Z)),ea),Hb=ab.y,bc=ab.w|0;if(t().d===Hb){var yb=a.Le;jr();var tb=new Te(new Ue(J(new K,[\"Expect at least one \",\n\" digit\"]))),eb=[We(Xe(),\"hexadecimal\")],kb=Ye(tb,J(new K,eb));t();var Rb=gr(a,c,2+c|0),Gb=G(new H,kb,new L(Rb)),vb=O().c;yb.n(kr(0,new z(Gb,vb),!0,ir()));return G(new H,ar(),bc)}var Tb=ab.y,Nb=ab.w|0;if(Tb instanceof L){var ic=Tb.k;return G(new H,new Em(Sr(Tr(),ic,16)),Nb)}throw new w(ab);case 111:for(var Va=2+b|0,cb=Va,zb=O().c,Ub=!1,jb=!1,db,ub,Aa,va;;){if(cb<a.we){var Ra=a.$b.a[cb];if(48<=Ra&&55>=Ra){var rb=new z(hc(Ra),zb);cb=1+cb|0;zb=rb;jb=!1;continue}if(Pe(new E(hc(Ra)),hc(95))){var xb=1+\ncb|0,mc=zb.b();cb=xb;Ub=mc;jb=!0;continue}var Ha=er(zb).m(),Ka=ze(Ha,\"\",\"\",\"\"),Oa=Ub,Na=jb,Da=cb;db=Ka;ub=Oa;Aa=Na;va=Da}else{var ta=er(zb).m(),Ya=ze(ta,\"\",\"\",\"\"),dc=Ub,ka=jb,ya=cb;db=Ya;ub=dc;Aa=ka;va=ya}break}var Sa=db,xc=!!Aa,Sb=va|0;if(ub){var uc=a.Le;fr();var Lb=Ye(new Te(new Ue(J(new K,[\"Leading separator is not allowed\"]))),u());t();var lc=gr(a,-1+Va|0,Va),Xb=G(new H,Lb,new L(lc)),ec=O().c;uc.n(hr(0,new z(Xb,ec),!0,ir()))}if(xc){var Ab=a.Le;fr();var Ob=Ye(new Te(new Ue(J(new K,[\"Trailing separator is not allowed\"]))),\nu());t();var fb=gr(a,-1+Sb|0,Sb),Wa=G(new H,Ob,new L(fb)),bb=O().c;Ab.n(hr(0,new z(Wa,bb),!0,ir()))}var Ia=G(new H,\"\"===Sa?t().d:(t(),new L(Sa)),Sb),Ua=Ia.y,pc=Ia.w|0;if(t().d===Ua){var sc=a.Le;jr();var Ba=new Te(new Ue(J(new K,[\"Expect at least one \",\" digit\"]))),ob=[We(Xe(),\"octal\")],nc=Ye(Ba,J(new K,ob));t();var Ib=gr(a,Va,2+Va|0),vc=G(new H,nc,new L(Ib)),Vb=O().c;sc.n(kr(0,new z(vc,Vb),!0,ir()));return G(new H,ar(),pc)}var fc=Ia.y,Bc=Ia.w|0;if(fc instanceof L){var Pb=fc.k;return G(new H,new Em(Sr(Tr(),\nPb,8)),Bc)}throw new w(Ia);case 98:for(var Jb=2+b|0,gc=Jb,Cb=O().c,cc=!1,yc=!1,Mc,qc,oc,Qc;;){if(gc<a.we){var jc=a.$b.a[gc],sb=jc;if(Pe(new E(hc(sb)),hc(48))||Pe(new E(hc(sb)),hc(49))){var Gc=new z(hc(jc),Cb);gc=1+gc|0;Cb=Gc;yc=!1;continue}if(Pe(new E(hc(jc)),hc(95))){var Wb=1+gc|0,Cc=Cb.b();gc=Wb;cc=Cc;yc=!0;continue}var Fc=er(Cb).m(),qd=ze(Fc,\"\",\"\",\"\"),Yb=cc,Nc=yc,ad=gc;Mc=qd;qc=Yb;oc=Nc;Qc=ad}else{var Uc=er(Cb).m(),cd=ze(Uc,\"\",\"\",\"\"),kc=cc,Vc=yc,Hc=gc;Mc=cd;qc=kc;oc=Vc;Qc=Hc}break}var rc=Mc,sd=\n!!oc,Kc=Qc|0;if(qc){var Qd=a.Le;fr();var Ad=Ye(new Te(new Ue(J(new K,[\"Leading separator is not allowed\"]))),u());t();var kd=gr(a,-1+Jb|0,Jb),Hd=G(new H,Ad,new L(kd)),Rd=O().c;Qd.n(hr(0,new z(Hd,Rd),!0,ir()))}if(sd){var Bd=a.Le;fr();var ae=Ye(new Te(new Ue(J(new K,[\"Trailing separator is not allowed\"]))),u());t();var dd=gr(a,-1+Kc|0,Kc),od=G(new H,ae,new L(dd)),Ta=O().c;Bd.n(hr(0,new z(od,Ta),!0,ir()))}var wb=G(new H,\"\"===rc?t().d:(t(),new L(rc)),Kc),$a=wb.y,wa=wb.w|0;if(t().d===$a){var hb=a.Le;jr();\nvar ra=new Te(new Ue(J(new K,[\"Expect at least one \",\" digit\"]))),wc=[We(Xe(),\"binary\")],ac=Ye(ra,J(new K,wc));t();var Id=gr(a,Jb,2+Jb|0),ud=G(new H,ac,new L(Id)),be=O().c;hb.n(kr(0,new z(ud,be),!0,ir()));return G(new H,ar(),wa)}var re=wb.y,pe=wb.w|0;if(re instanceof L){var bd=re.k;return G(new H,new Em(Sr(Tr(),bd,2)),pe)}throw new w(wb);case 46:case 69:case 101:return cr(a,1+b|0,\"0\");default:for(var Rc=b,Wc=O().c,Wd=!1,zd=!1,Pa,Db,Oc,Tc;;){if(Rc<a.we){var Sd=a.$b.a[Rc];if(dr(Sd)){var Jc=new z(hc(Sd),\nWc);Rc=1+Rc|0;Wc=Jc;zd=!1;continue}if(Pe(new E(hc(Sd)),hc(95))){var vd=1+Rc|0,hd=Wc.b();Rc=vd;Wd=hd;zd=!0;continue}var de=er(Wc).m(),ye=ze(de,\"\",\"\",\"\"),jf=Wd,af=zd,pf=Rc;Pa=ye;Db=jf;Oc=af;Tc=pf}else{var kf=er(Wc).m(),Be=ze(kf,\"\",\"\",\"\"),Kd=Wd,ld=zd,Jd=Rc;Pa=Be;Db=Kd;Oc=ld;Tc=Jd}break}var Dd=Pa,Xd=!!Oc,Yc=Tc|0;if(Db){var Ce=a.Le;fr();var te=Ye(new Te(new Ue(J(new K,[\"Leading separator is not allowed\"]))),u());t();var Ie=gr(a,-1+b|0,b),Jf=G(new H,te,new L(Ie)),df=O().c;Ce.n(hr(0,new z(Jf,df),!0,ir()))}if(Xd){var vg=\na.Le;fr();var wg=Ye(new Te(new Ue(J(new K,[\"Trailing separator is not allowed\"]))),u());t();var xg=gr(a,-1+Yc|0,Yc),eg=G(new H,wg,new L(xg)),vh=O().c;vg.n(hr(0,new z(eg,vh),!0,ir()))}var fg=G(new H,\"\"===Dd?t().d:(t(),new L(Dd)),Yc),ih=fg.y,Ig=fg.w|0;if(t().d===ih){var Tf=a.Le;jr();var Jg=new Te(new Ue(J(new K,[\"Expect at least one \",\" digit\"]))),jh=[We(Xe(),\"decimal\")],yg=Ye(Jg,J(new K,jh));t();var gg=gr(a,b,2+b|0),Cf=G(new H,yg,new L(gg)),Uf=O().c;Tf.n(kr(0,new z(Cf,Uf),!0,ir()));return G(new H,\nar(),Ig)}var $g=fg.y,Ah=fg.w|0;if($g instanceof L){var Kg=$g.k;return G(new H,new Em(Sr(Tr(),Kg,10)),Ah)}throw new w(fg);}else return G(new H,ar(),1+b|0);else{for(var Vf=b,hg=O().c,zg=!1,Lg=!1,Mg,Wf,Ng,Kf;;){if(Vf<a.we){var xf=a.$b.a[Vf];if(dr(xf)){var Og=new z(hc(xf),hg);Vf=1+Vf|0;hg=Og;Lg=!1;continue}if(Pe(new E(hc(xf)),hc(95))){var mi=1+Vf|0,Ci=hg.b();Vf=mi;zg=Ci;Lg=!0;continue}var Xh=er(hg).m(),wh=ze(Xh,\"\",\"\",\"\"),Bh=zg,ng=Lg,kh=Vf;Mg=wh;Wf=Bh;Ng=ng;Kf=kh}else{var Kh=er(hg).m(),ni=ze(Kh,\"\",\"\",\n\"\"),Lh=zg,lh=Lg,Ch=Vf;Mg=ni;Wf=Lh;Ng=lh;Kf=Ch}break}var Dh=Mg,Yh=!!Ng,ah=Kf|0;if(Wf){var oi=a.Le;fr();var mj=Ye(new Te(new Ue(J(new K,[\"Leading separator is not allowed\"]))),u());t();var wd=gr(a,-1+b|0,b),ge=G(new H,mj,new L(wd)),De=O().c;oi.n(hr(0,new z(ge,De),!0,ir()))}if(Yh){var qf=a.Le;fr();var og=Ye(new Te(new Ue(J(new K,[\"Trailing separator is not allowed\"]))),u());t();var Xf=gr(a,-1+ah|0,ah),mh=G(new H,og,new L(Xf)),Ag=O().c;qf.n(hr(0,new z(mh,Ag),!0,ir()))}var Bg=G(new H,\"\"===Dh?t().d:(t(),\nnew L(Dh)),ah),Eh=Bg.y;if(t().d===Eh){var Pg=a.Le;jr();var Di=Ye(new Te(new Ue(J(new K,[\"Expect a numeric literal\"]))),u());t();var Mh=gr(a,b,1+b|0),pi=G(new H,Di,new L(Mh)),Xi=O().c;Pg.n(kr(0,new z(pi,Xi),!0,ir()));return G(new H,ar(),b)}var Qg=Bg.y,nh=Bg.w|0;if(Qg instanceof L){var bh=Qg.k,Mj;if(Mj=nh<a.we){var Nj=a.$b.a[nh];Mj=Pe(new E(hc(Nj)),hc(46))||Pe(new E(hc(Nj)),hc(101))||Pe(new E(hc(Nj)),hc(69))}return Mj?cr(a,nh,bh):G(new H,new Em(Hp(bh)),nh)}throw new w(Bg);}else{var ie=a.Le;jr();var Ac=\nYe(new Te(new Ue(J(new K,[\"Expect a numeric literal instead of end of input\"]))),u());t();var Ve=gr(a,b,1+b|0),Td=G(new H,Ac,new L(Ve)),lf=O().c;ie.n(kr(0,new z(Td,lf),!0,ir()));return G(new H,ar(),b)}}\nfunction Xaa(a,b,c){if(c)d=!1;else{d=Ur(tp(),a.$b);d=Vr(new Wr(d),b);var d=Pe(new E(d),new L(hc(34)))}if(d)return 1+b|0;if(c&&Rr(a,b,'\"\"\"',0))return 3+b|0;c=a.Le;jr();d=Ye(new Te(new Ue(J(new K,[\"unclosed quotation mark\"]))),u());t();a=gr(a,b,1+b|0);a=G(new H,d,new L(a));d=O().c;c.n(kr(0,new z(a,d),!0,ir()));return b}\nfunction Yaa(a,b,c,d){for(var e=!1;;)if(e)if(b<a.we)switch(e=a.$b.a[b],e){case 92:c=new z(hc(92),c);b=1+b|0;e=!1;break;case 34:c=new z(hc(34),c);b=1+b|0;e=!1;break;case 110:c=new z(hc(10),c);b=1+b|0;e=!1;break;case 116:c=new z(hc(9),c);b=1+b|0;e=!1;break;case 114:c=new z(hc(13),c);b=1+b|0;e=!1;break;case 98:c=new z(hc(8),c);b=1+b|0;e=!1;break;case 102:c=new z(hc(12),c);b=1+b|0;e=!1;break;default:var g=a.Le;fr();var h=Ye(new Te(new Ue(J(new K,[\"Found invalid escape character\"]))),u());t();var k=gr(a,\nb,1+b|0);h=G(new H,h,new L(k));k=O().c;g.n(hr(0,new z(h,k),!0,ir()));c=new z(hc(e),c);b=1+b|0;e=!1}else return d=a.Le,jr(),e=Ye(new Te(new Ue(J(new K,[\"Expect an escape character\"]))),u()),t(),a=gr(a,b,1+b|0),a=G(new H,e,new L(a)),e=O().c,d.n(kr(0,new z(a,e),!0,ir())),a=er(c).m(),G(new H,ze(a,\"\",\"\",\"\"),b);else if(d)if(b<a.we)if(e=a.$b.a[b],34===e){if(Rr(a,b,'\"\"\"',0)&&!Rr(a,1+b|0,'\"\"\"',0))return a=er(c).m(),G(new H,ze(a,\"\",\"\",\"\"),b);c=new z(hc(34),c);b=1+b|0;e=!1}else c=new z(hc(e),c),b=1+b|0,e=!1;\nelse return a=er(c).m(),G(new H,ze(a,\"\",\"\",\"\"),b);else if(b<a.we)switch(e=a.$b.a[b],e){case 92:b=1+b|0;e=!0;break;case 34:case 10:return a=er(c).m(),G(new H,ze(a,\"\",\"\",\"\"),b);default:c=new z(hc(e),c),b=1+b|0,e=!1}else return a=er(c).m(),G(new H,ze(a,\"\",\"\",\"\"),b)}function gr(a,b,c){return new Kq(b,c,a.OW)}\nfunction Zaa(a){for(var b=0,c=O().c,d=O().c,e=O().c;;){if(b>=a.we)return Km(d);var g=a.$b.a[b],h=!1,k=!1;if(32===g){for(var l=b,m=O().c;;)if(l<a.we&&Pe(new E(hc(a.$b.a[l])),hc(32))){var n=new z(hc(a.$b.a[l]),m);l=1+l|0;m=n}else break;var r=er(m).m();ze(r,\"\",\"\",\"\");var v=l,x=Hr(a,v,Se(),b,d);b=v;d=x}else if(44===g){var A=1+b|0,B=Hr(a,A,Xr(),b,d);b=A;d=B}else if(96===g){var C=1+b|0,D=Hr(a,1+b|0,Yr(),b,d);b=C;d=D}else if(99===g&&(Rr(a,b,Sk(Nk()),0)||Rr(a,b,Sk(Ok()),0))){var F=Rr(a,b,Sk(Ok()),0)?Ok():\nNk(),I=Sk(F).length,M=b+I|0,N=Hr(a,b+I|0,new Zr(F),b,d),P=new z(F,e);b=M;d=N;e=P}else{if(36===g&&(h=!0,Rr(a,b,Sk(Pk()),0))){var T=2+b|0,Y=Hr(a,2+b|0,new Zr(Pk()),b,d);b=T;d=Y;continue}if(h&&(1+b|0)<a.we&&Nr(a.$b.a[1+b|0])){for(var Z=1+b|0,S=O().c;;)if(Z<a.we&&Qr(a.$b.a[Z])){var ea=new z(hc(a.$b.a[Z]),S);Z=1+Z|0;S=ea}else break;var ia=er(S).m(),X=ze(ia,\"\",\"\",\"\"),sa=Z,Ja=Pk(),Xa=$r().GH.L(X)?new as(X):new bs(X,a.HH.L(X)),Fa=G(new H,Xa,gr(a,1+b|0,sa)),za=O().c,Qa=Hr(a,sa,new cs(Ja,new z(Fa,za),gr(a,\nb,sa)),b,d);b=sa;d=Qa}else if(59===g){var Ma=1+b|0,Ga=Hr(a,Ma,ds(),b,d);b=Ma;d=Ga}else if(34===g){var ab=e;if(ab instanceof z)var Hb=ab,bc=Hb.p,yb=Pe(new E(Hb.z),Ok()),tb=bc;else{var eb=O().c;if(null===eb?null!==ab:!eb.i(ab))throw new w(ab);var kb=O().c;yb=!1;tb=kb}var Rb=!!yb,Gb=tb;if(Rb&&Rr(a,b,Tk(Ok()),0)){var vb=Tk(Ok()).length,Tb=b+vb|0,Nb=Hr(a,b+vb|0,new es(Ok()),b,d);b=Tb;d=Nb;e=Gb}else if(Rb?0:!e.b()){var ic=1+b|0,Va=Hr(a,1+b|0,new es(Nk()),b,d);b=ic;d=Va;e=Gb}else{var cb=Rr(a,b,'\"\"\"',0),\nzb=Yaa(a,b+(cb?3:1)|0,O().c,cb);if(null===zb)throw new w(zb);var Ub=zb.h(),jb=Xaa(a,zb.Sc(),cb),db=Hr(a,jb,new fs(new Dm(Ub)),b,d);b=jb;d=db}}else{if(47===g){k=!0;var ub=Ur(tp(),a.$b);if(Vr(new Wr(ub),1+b|0).L(hc(47))){for(var Aa=2+b|0,va=O().c;;)if(Aa<a.we&&Nm(new E(hc(a.$b.a[Aa])),hc(10))){var Ra=new z(hc(a.$b.a[Aa]),va);Aa=1+Aa|0;va=Ra}else break;var rb=er(va).m(),xb=ze(rb,\"\",\"\",\"\"),mc=Aa,Ha=Hr(a,mc,new gs(xb),b,d);b=mc;d=Ha;continue}}if(k)var Ka=Ur(tp(),a.$b),Oa=Vr(new Wr(Ka),1+b|0).L(hc(42));\nelse Oa=!1;if(Oa){var Na=2+b|0,Da=0;Da=47;var ta=0;ta=42;for(var Ya=Na,dc=O().c;;){if(Ya<a.we){var ka=a.$b.a[Ya],ya=Nm(new E(hc(Da)),hc(42))?!0:Nm(new E(hc(ta)),hc(47));Da=ta;ta=ka;var Sa=ya}else Sa=!1;if(Sa){var xc=new z(hc(a.$b.a[Ya]),dc);Ya=1+Ya|0;dc=xc}else break}var Sb=er(dc).m(),uc=ze(Sb,\"\",\"\",\"\"),Lb=Ya,lc=Hr(a,Lb,new gs($aa(Q(),uc)),b,d);b=Lb;d=lc}else{var Xb=Vk(Zk(),g);if(!Xb.b()){var ec=Xb.o();if(ec instanceof fe){var Ab=1+b|0,Ob=Hr(a,1+b|0,new Zr(ec.aa),b,d);b=Ab;d=Ob;continue}}var fb=Vk(Zk(),\ng);if(!fb.b()){var Wa=fb.o();if(Wa instanceof Ud){var bb=1+b|0,Ia=Hr(a,1+b|0,new es(Wa.fa),b,d);b=bb;d=Ia;continue}}if(10===g){for(var Ua=1+b|0,pc=Ua,sc=O().c;;){if(pc<a.we)var Ba=a.$b.a[pc],ob=Pe(new E(hc(Ba)),hc(32))||Pe(new E(hc(Ba)),hc(10));else ob=!1;if(ob){var nc=new z(hc(a.$b.a[pc]),sc);pc=1+pc|0;sc=nc}else break}var Ib=er(sc).m(),vc=ze(Ib,\"\",\"\",\"\"),Vb=pc,fc=hs(new is(new js(vc),new y(kf=>Nm(new E(hc(Ea(kf))),hc(10))))),Bc=c.Jg();if((Bc.b()||(Bc.o()|0)<fc)&&0<fc){var Pb=new z(fc,c),Jb=G(new H,\nks(),gr(a,Ua,Vb)),gc=new z(Jb,d);b=Vb;c=Pb;d=gc}else{for(var Cb=c;;)if(Cb.b()?0:(Cb.e()|0)>fc)Cb=Cb.f();else break;var cc=Cb,yc=c.K()-cc.K()|0,Mc=cc.Jg(),qc=Mc.b()||(Mc.o()|0)<fc?0<fc:!1,oc=qc?new z(fc,cc):cc;if(a.NW){tp();var Qc=ls(ms(),a.$b,b),jc=ns(ms(),Qc,0,10),sb=jc.a.length,Gc=new (md(fa).Ia)(sb);if(0<sb){var Wb=0;if(jc instanceof zc)for(var Cc=jc;Wb<sb;)Gc.a[Wb]=os(Ea(Cc.a[Wb])),Wb=1+Wb|0;else if(jc instanceof Xc)for(var Fc=jc;Wb<sb;)Gc.a[Wb]=os(Ea(Fc.a[Wb])),Wb=1+Wb|0;else if(jc instanceof\ned)for(var qd=jc;Wb<sb;)Gc.a[Wb]=os(Ea(qd.a[Wb])),Wb=1+Wb|0;else if(jc instanceof Zc)for(var Yb=jc;Wb<sb;){var Nc=Yb.a[Wb];Gc.a[Wb]=os(Ea(new ma(Nc.W,Nc.Y)));Wb=1+Wb|0}else if(jc instanceof $c)for(var ad=jc;Wb<sb;)Gc.a[Wb]=os(Ea(ad.a[Wb])),Wb=1+Wb|0;else if(null!==jc)for(;Wb<sb;)Gc.a[Wb]=os(Ea(hc(jc.a[Wb]))),Wb=1+Wb|0;else if(jc instanceof Pc)for(var Uc=jc;Wb<sb;)Gc.a[Wb]=os(Ea(Uc.a[Wb])),Wb=1+Wb|0;else if(jc instanceof Sc)for(var cd=jc;Wb<sb;)Gc.a[Wb]=os(Ea(cd.a[Wb])),Wb=1+Wb|0;else if(jc instanceof\nEc)for(var kc=jc;Wb<sb;)Gc.a[Wb]=os(Ea(kc.a[Wb])),Wb=1+Wb|0;else throw new w(jc);}var Vc=ps(Gc),Hc=\"dbg: \"+ze(Vc,\"\",\"\",\"\")+\"...\";ff(gf(),Hc+\"\\n\");ff(gf(),new bo(c,fc,cc,yc,qc,oc)+\"\\n\")}if(0<yc){var rc=qc?G(new H,ks(),gr(a,Ua,Vb)):G(new H,qs(),gr(a,b,Vb));O();for(var sd=new fp,Kc=0;Kc<yc;){var Qd=G(new H,rs(),gr(a,-1+Ua|0,Vb));wp(sd,Qd);Kc=1+Kc|0}var Ad=sd.ha(),kd=dl(d,Ad),Hd=new z(rc,kd)}else{var Rd=G(new H,qs(),gr(a,b,Vb));Hd=new z(Rd,d)}b=Vb;c=oc;d=Hd}}else if(Nr(g)){for(var Bd=b,ae=O().c;;)if(Bd<\na.we&&Qr(a.$b.a[Bd])){var dd=new z(hc(a.$b.a[Bd]),ae);Bd=1+Bd|0;ae=dd}else break;var od=er(ae).m(),Ta=ze(od,\"\",\"\",\"\"),wb=Bd,$a=$r().GH.L(Ta)?new as(Ta):new bs(Ta,a.HH.L(Ta)),wa=Hr(a,wb,$a,b,d);b=wb;d=wa}else if(a.IH.L(hc(g))){var hb=Vaa(a,b,O().c,a.IH);if(null===hb)throw new w(hb);var ra=hb.h(),wc=hb.Sc();if(\".\"===ra&&wc<a.we){var ac=a.$b.a[wc];if(Nr(ac)){for(var Id=wc,ud=O().c;;)if(Id<a.we&&Qr(a.$b.a[Id])){var be=new z(hc(a.$b.a[Id]),ud);Id=1+Id|0;ud=be}else break;var re=er(ud).m(),pe=ze(re,\"\",\"\",\n\"\"),bd=Id,Rc=Hr(a,bd,new ss(pe),b,d);b=bd;d=Rc}else if(Pe(new E(hc(ac)),hc(48))&&!((1+wc|0)<a.we&&dr(a.$b.a[1+wc|0]))||48<ac&&57>=ac){for(var Wc=wc,Wd=O().c;;)if(Wc<a.we&&dr(a.$b.a[Wc])){var zd=new z(hc(a.$b.a[Wc]),Wd);Wc=1+Wc|0;Wd=zd}else break;var Pa=er(Wd).m(),Db=ze(Pa,\"\",\"\",\"\"),Oc=Wc,Tc=Hr(a,Oc,new ss(Db),b,d);b=Oc;d=Tc}else{var Sd=Hr(a,wc,a.JH.L(ra)?new as(ra):new bs(ra,!0),b,d);b=wc;d=Sd}}else{var Jc=Hr(a,wc,a.JH.L(ra)?new as(ra):new bs(ra,!0),b,d);b=wc;d=Jc}}else if(dr(g)){var vd=Waa(a,b);\nif(null===vd)throw new w(vd);var hd=vd.Sc(),de=Hr(a,hd,new fs(vd.h()),b,d);b=hd;d=de}else{var ye=new Te(new Ue(J(new K,[\"unexpected character '\",\"'\"]))),jf=[We(Xe(),os(g))];Uaa(a,Ye(ye,J(new K,jf)),b);var af=1+b|0,pf=Hr(a,1+b|0,ts(),b,d);b=af;d=pf}}}}}}\nfunction os(a){switch(a){case 8:return\"\\\\b\";case 9:return\"\\\\t\";case 10:return\"\\\\n\";case 12:return\"\\\\f\";case 13:return\"\\\\r\";case 34:return'\\\\\"';case 39:return\"\\\\'\";case 92:return\"\\\\\\\\\";default:return us(Pr(),a)?\"\\\\0\"+(+(a>>>0)).toString(8):String.fromCharCode(a)}}\nfunction qaa(a){if(0===(2&a.Gs)<<24>>24&&0===(2&a.Gs)<<24>>24){0===(1&a.Gs)<<24>>24&&0===(1&a.Gs)<<24>>24&&(a.vN=Zaa(a),a.Gs=(1|a.Gs)<<24>>24);a:for(var b=a.vN,c=!1,d=O().c,e=O().c;;){var g=!1,h=null,k=b;if(k instanceof z){g=!0;h=k;var l=h.z,m=h.p;if(null!==l){var n=l.h(),r=l.j();if(Yr()===n&&m instanceof z){var v=m,x=v.z,A=v.p;if(null!==x){var B=x.h(),C=x.j();if(B instanceof bs){var D=B,F=D.ke;if(\"\\x3c\"===D.ae&&!0===F){var I=G(new H,new bs(\"\\x3c\",!0),C),M=G(new H,Yr(),r),N=new z(I,new z(M,e));b=\nA;c=!1;e=N;continue}}}}}}if(g){var P=h.z,T=h.p;if(null!==P){var Y=P.h(),Z=P.j();if(Yr()===Y&&T instanceof z){var S=T,ea=S.z,ia=S.p;if(null!==ea){var X=ea.h(),sa=ea.j();if(X instanceof bs){var Ja=X,Xa=Ja.ke;if(\"\\x3e\"===Ja.ae&&!0===Xa){var Fa=G(new H,new bs(\"\\x3e\",!0),sa),za=G(new H,Yr(),Z),Qa=new z(Fa,new z(za,e));b=ia;c=!1;e=Qa;continue}}}}}}if(g){var Ma=h.z,Ga=h.p;if(null!==Ma){var ab=Ma.h(),Hb=Ma.j();if(ab instanceof Zr){var bc=G(new H,ab.qx,Hb),yb=G(new H,bc,e),tb=new z(yb,d),eb=O().c;b=Ga;c=!1;\nd=tb;e=eb;continue}}}if(g){var kb=h.z,Rb=h.p;if(null!==kb){var Gb=kb.h(),vb=kb.j();if(Gb instanceof es){var Tb=Gb.Iw,Nb=!1,ic=null,Va=d;if(Va instanceof z){Nb=!0;ic=Va;var cb=ic.z;if(null!==cb){var zb=cb.h();if(null!==zb){var Ub=zb.h();if(Mk()===Ub&&Nm(new E(Tb),Mk())){var jb=new es(Mk()),db=vs(vb),ub=G(new H,jb,db);b=new z(ub,b);c=!1;continue}}}}if(Nb){var Aa=ic.z,va=ic.p;if(null!==Aa){var Ra=Aa.h(),rb=Aa.j();if(null!==Ra){var xb=Ra.h();if(Mk()===xb)if(Pe(new E(Tb),Mk()))b:{for(var mc=e;!mc.b();){var Ha=\nmc.e();c:{if(null!==Ha){var Ka=Ha.h();if(Se()===Ka||qs()===Ka){var Oa=!0;break c}}Oa=!1}if(!Oa){var Na=!1;break b}mc=mc.f()}Na=!0}else Na=!1;else Na=!1;if(Na){b=Rb;c=!1;d=va;e=rb;continue}}}}if(Nb){var Da=ic.z,ta=ic.p;if(null!==Da){var Ya=Da.h(),dc=Da.j();if(null!==Ya){var ka=Ya.h(),ya=Ya.j();if(Nm(new E(ka),Tb)&&(!Pe(new E(ka),Pk())||!Pe(new E(Tb),Jk()))){var Sa=a.Le;jr();var xc=new Te(new Ue(J(new K,[\"Mistmatched closing \",\"\"]))),Sb=[We(Xe(),Tb.Ua())],uc=Ye(xc,J(new K,Sb));t();var Lb=G(new H,uc,\nnew L(vb)),lc=new Te(new Ue(J(new K,[\"does not correspond to opening \",\"\"]))),Xb=[We(Xe(),ka.Ua())],ec=Ye(lc,J(new K,Xb));t();var Ab=G(new H,ec,new L(ya)),Ob=O().c;Sa.n(kr(0,new z(Lb,new z(Ab,Ob)),!0,ws()))}var fb=Km(e),Wa=new cs(ka,fb,xs(new Kq(ya.eh,ya.eh,ya.dh),vs(vb))),bb=xs(ya,vb),Ia=G(new H,Wa,bb),Ua=new z(Ia,dc);b=Rb;c=!0;d=ta;e=Ua;continue}}}var pc=O().c;if(null===pc?null===Va:pc.i(Va)){var sc=a.Le;jr();var Ba=new Te(new Ue(J(new K,[\"Unexpected closing \",\"\"]))),ob=[We(Xe(),Tb.Ua())],nc=Ye(Ba,\nJ(new K,ob));t();var Ib=G(new H,nc,new L(vb)),vc=O().c;sc.n(kr(0,new z(Ib,vc),!0,ws()));b=Rb;c=!1;continue}throw new w(Va);}}}if(g){var Vb=h.z,fc=h.p;if(null!==Vb){var Bc=Vb.h(),Pb=Vb.j();if(ks()===Bc){var Jb=new Zr(Mk()),gc=G(new H,Jb,Pb);b=new z(gc,fc);c=!1;continue}}}if(g){var Cb=h.z,cc=h.p;if(null!==Cb){var yc=Cb.h(),Mc=Cb.j();if(rs()===yc){var qc=new es(Mk()),oc=G(new H,qc,Mc);b=new z(oc,cc);c=!1;continue}}}if(g){var Qc=h.z,jc=h.p;if(null!==Qc){var sb=Qc.h(),Gc=Qc.j();if(sb instanceof bs){var Wb=\nsb,Cc=Wb.ke;if(\"\\x3c\"===Wb.ae&&!0===Cc&&c){var Fc=new Zr(Lk()),qd=G(new H,Fc,Gc);b=new z(qd,jc);c=!1;continue}}}}if(g){var Yb=h.z,Nc=h.p;if(null!==Yb){var ad=Yb.h(),Uc=Yb.j();if(ad instanceof bs){var cd=ad,kc=cd.ke;if(\"\\x3e\"===cd.ae)if(!0===kc)if(c){var Vc=d;b:{if(Vc instanceof z){var Hc=Vc.z;if(null!==Hc){var rc=Hc.h();if(null!==rc){var sd=rc.h();if(Lk()===sd){var Kc=!0;break b}}}}Kc=!1}}else Kc=!1;else Kc=!1;else Kc=!1;if(Kc){var Qd=new es(Lk()),Ad=G(new H,Qd,Uc);b=new z(Ad,Nc);c=!1;continue}}}}if(g){var kd=\nh.z,Hd=h.p;if(null!==kd){var Rd=kd.h(),Bd=kd.j();if(Rd instanceof bs){var ae=Rd,dd=ae.ae;if(!0===ae.ke){if(c)b:{for(var od=0,Ta=dd.length;od<Ta;){if(62!==dd.charCodeAt(od)){var wb=!1;break b}od=1+od|0}wb=!0}else wb=!1;if(wb&&1<dd.length){var $a=d;b:{if($a instanceof z){var wa=$a.z;if(null!==wa){var hb=wa.h();if(null!==hb){var ra=hb.h();if(Lk()===ra){var wc=!0;break b}}}}wc=!1}}else wc=!1}else wc=!1;if(wc){var ac=new es(Lk()),Id=vs(Bd),ud=G(new H,ac,Id),be=new bs(ys(Q(),dd,1),!0),re=G(new H,be,Bd);\nb=new z(ud,new z(re,Hd));c=!1;continue}}}}if(g){var pe=h.z,bd=h.p;if(null!==pe){var Rc=pe.h(),Wc=pe.j();if(Rc instanceof bs){var Wd=Rc,zd=Wd.ke;if(\"\\x3e\"===Wd.ae&&!0===zd&&c){var Pa=a.Le;fr();var Db=Ye(new Te(new Ue(J(new K,[\"This looks like an angle bracket, but it does not close any angle bracket section\"]))),u());t();var Oc=G(new H,Db,new L(Wc)),Tc=Ye(new Te(new Ue(J(new K,[\"Add spaces around it if you intended to use `\\x3c` as an operator\"]))),u()),Sd=t().d,Jc=G(new H,Tc,Sd),vd=O().c;Pa.n(hr(0,\nnew z(Oc,new z(Jc,vd)),!0,ws()));var hd=G(new H,Wd,Wc),de=new z(hd,e);b=bd;c=!1;e=de;continue}}}}if(g){var ye=h.z,jf=h.p;if(null!==ye){var af=ye.h(),pf=ye.j();if(af&&af.$classData&&af.$classData.rb.Wm){var kf=af,Be=!(Se()===kf||qs()===kf),Kd=G(new H,kf,pf),ld=new z(Kd,e);b=jf;c=Be;e=ld;continue}}}var Jd=O().c;if(null===Jd?null===k:Jd.i(k)){var Dd=!1,Xd=null,Yc=d;if(Yc instanceof z){Dd=!0;Xd=Yc;var Ce=Xd.z;if(null!==Ce){var te=Ce.h();if(null!==te){var Ie=te.h(),Jf=te.j();if(Mk()===Ie){var df=new es(Mk()),\nvg=G(new H,df,Jf),wg=O().c;b=new z(vg,wg);c=!1;continue}}}}if(Dd){var xg=Xd.z;if(null!==xg){var eg=xg.h(),vh=xg.j();if(null!==eg){var fg=eg.h(),ih=eg.j(),Ig=a.Le;jr();var Tf=new Te(new Ue(J(new K,[\"Unmatched opening \",\"\"]))),Jg=[We(Xe(),fg.Ua())],jh=Ye(Tf,J(new K,Jg));t();var yg=G(new H,jh,new L(ih));if(Pe(new E(fg),Lk()))var gg=Ye(new Te(new Ue(J(new K,[\"Note that `\\x3c` without spaces around it is considered as an angle bracket and not as an operator\"]))),u()),Cf=t().d,Uf=G(new H,gg,Cf),$g=O().c,\nAh=new z(Uf,$g);else Ah=O().c;Ig.n(kr(0,new z(yg,Ah),!0,ws()));var Kg=Km(dl(e,vh));break a}}}var Vf=O().c;if(null===Vf?null===Yc:Vf.i(Yc)){Kg=Km(e);break a}throw new w(Yc);}throw new w(k);}a.uN=Kg;a.Gs=(2|a.Gs)<<24>>24}return a.uN}Je.prototype.$classData=q({LW:0},!1,\"mlscript.NewLexer\",{LW:1,g:1});\nfunction zs(){this.GH=null;As=this;this.GH=Aq(tp().Iv,J(new K,\"if then else case fun val var of let rec in mut set do while declare class trait mixin interface extends override super new namespace module type where forall exists in out null undefined abstract constructor virtual\".split(\" \")))}zs.prototype=new p;zs.prototype.constructor=zs;\nfunction aba(a,b){if(null!==b&&(a=b.h(),Se()===a))return\" \";if(null!==b&&(a=b.h(),Xr()===a))return\",\";if(null!==b&&(a=b.h(),ds()===a))return\";\";if(null!==b&&(a=b.h(),qs()===a))return\"\\u21b5\";if(null!==b&&(a=b.h(),ks()===a))return\"\\u2192\";if(null!==b&&(a=b.h(),rs()===a))return\"\\u2190\";if(null!==b&&(a=b.h(),ts()===a))return\"\\x3cerror\\x3e\";if(null!==b&&(a=b.h(),Yr()===a))return\"`\";if(null!==b&&(a=b.h(),a instanceof fs))return a.Cu.Dh;if(null!==b&&(a=b.h(),a instanceof as&&(a=a.Na,null!==a)))return\"#\"+\na;if(null!==b&&(a=b.h(),a instanceof bs&&(a=a.ae,null!==a)))return a;if(null!==b&&(a=b.h(),a instanceof ss&&(a=a.ux,null!==a)))return\".\"+a;if(null!==b&&(a=b.h(),a instanceof Zr))return Sk(a.qx);if(null!==b&&(a=b.h(),a instanceof es))return Tk(a.Iw);if(null!==b){var c=b.h();if(c instanceof cs&&(a=c.Cc,c=c.td,Mk()===a))return\"\"+Sk(a)+Bs(0,c)+Tk(a)}if(null!==b&&(a=b.h(),a instanceof cs))return b=a.Cc,a=a.td,\"\"+Sk(b)+Bs(0,a)+Tk(b);if(null!==b&&(a=b.h(),a instanceof gs&&(a=a.PC,null!==a)))return\"/*\"+a+\n\"*/\";throw new w(b);}function Bs(a,b){a=b.m();a=new Ef(a,new y(c=>aba($r(),c)));return ze(a,\"|\",\"|\",\"|\")}zs.prototype.$classData=q({MW:0},!1,\"mlscript.NewLexer$\",{MW:1,g:1});var As;function $r(){As||(As=new zs);return As}function Cs(a,b,c,d,e){Ds(a,new U(()=>{var h=e.fn,k=Es(b);k=Fs(k)?ze(k,\"(\",\",\",\")\"):Gs(k)?Es(b):\"(\"+Es(b)+\")\";return\"@ \"+h+k+\"    [at l.\"+d.Zl+\"]\"}));try{a.le=1+a.le|0;var g=c.n(void 0)}finally{a.le=-1+a.le|0}Ds(a,new U(()=>\"\\x3d \"+g));return g}\nfunction Hs(a){if(!a.Kz){if(!a.Kz){var b=Is(a.Lz);b.b()?b=R():(b=b.o().j(),b=new L(new Kq(b.eh,b.eh,b.dh)));a.lE=b.b()?a.kE:b;a.Kz=!0}a.Lz=null}return a.lE}function Js(a){a=a.Ol.Jg();if(a.b())return R();a=a.o();return new L(a.j())}function Ks(a,b){var c=Ye(new Te(new Ue(J(new K,[\"Expected an expression; found a 'then'/'else' clause instead\"]))),u());b=G(new H,c,b);c=O().c;Ze(a,new z(b,c));return Ls(a)}\nfunction Ms(a,b){var c=Ye(new Te(new Ue(J(new K,[\"This quote syntax is not supported yet\"]))),u());b=G(new H,c,b);c=O().c;Ze(a,new z(b,c));return Ls(a)}\nfunction Ns(a,b,c,d,e){var g=bba(a,O().c,d);if(b){var h=!1,k=null,l=Os(a);a:{if(l instanceof z){h=!0;k=l;var m=k.z,n=k.p;if(null!==m&&(m=m.h(),Yr()===m&&n instanceof z&&(n=n.z,null!==n&&(n=n.h(),n instanceof as&&\"in\"===n.Na)))){Ps(a,e,new Oe(\"body\"));Ps(a,e,new Oe(\"body\"));c=Qs(a,0,!0,O().c,c,d,e);break a}}if(h&&(n=k.z,null!==n&&(n=n.h(),qs()===n))){Ps(a,e,new Oe(\"body\"));l=Rs(a,c,d);c=r=>{if(r instanceof fe)return Ks(a,r.aa.A());if(r instanceof Ud)return r.fa;throw new w(r);};if(l===u())c=u();else{d=\nl.e();e=d=new z(c(d),u());for(l=l.f();l!==u();)h=l.e(),h=new z(c(h),u()),e=e.p=h,l=l.f();c=d}t();c=new Sl(c);c=new Ud(c);break a}if(h&&(c=k.z,null!==c)){d=c.h();c=c.j();e=new Te(new Ue(J(new K,[\"Expected '`in'; found \",\" instead\"])));d=[We(Xe(),d.jb())];d=Ye(e,J(new K,d));t();c=G(new H,d,new L(c));d=O().c;Ze(a,new z(c,d));t();c=Ls(a);c=new Ud(c);break a}c=O().c;if(null===c?null===l:c.i(l))c=Ye(new Te(new Ue(J(new K,[\"Expected '`in'; found end of input instead\"]))),u()),d=Hs(a),c=G(new H,c,d),d=O().c,\nZe(a,new z(c,d)),t(),c=Ls(a),c=new Ud(c);else throw new w(l);}}else a:{if(l=!1,h=null,k=Os(a),k instanceof z&&(l=!0,h=k,k=h.z,null!==k&&(k=k.h(),k=k instanceof as&&\"in\"===k.Na?!0:ds()===k?!0:!1,k))){Ps(a,e,new Oe(\"body\"));c=Qs(a,0,!0,O().c,c,d,e);break a}if(l&&(l=h.z,null!==l&&(l=l.h(),qs()===l))){Ps(a,e,new Oe(\"body\"));c=Qs(a,0,!0,O().c,c,d,e);break a}t();c=new Gm(!0);d=Js(a);d.b()?d=R():(d=d.o(),d=new L(vs(d)));c=Cq(c,d);c=new Ud(c)}for(g=Km(g);!g.b();){d=g.e();c=G(new H,d,c);a:{l=c.y;e=c.w;if(null!==\nl&&(d=l.h(),l=l.j(),e instanceof Ud&&(e=e.fa,b))){t();c=new em(new Rl(!1,d,new fm(l),new fm(e)));c=new Ud(c);break a}l=c.y;e=c.w;if(null!==l&&(d=l.h(),l=l.j(),e instanceof Ud)){c=e.fa;t();c=new Rl(!1,d,l,c);c=new Ud(c);break a}d=c.w;if(null!==c.y&&d instanceof fe&&(d=d.aa,b)){t();c=Ms(a,d.A());c=new Ud(c);break a}l=c.y;e=c.w;if(null!==l&&(d=l.h(),l=l.j(),e instanceof fe)){c=e.aa;t();c=new Ss(!1,d,l,c);c=new fe(c);break a}throw new w(c);}g=g.f()}return c}\nfunction Ts(a,b){for(b=Km(b);!b.b();){var c=b.e();a=new Ml(c,a);b=b.f()}return a}function Ls(a){var b=new Gm(!0);a=Hs(a);return Cq(b,a)}var dba=function cba(a,b){var d=Os(a);return d instanceof z&&(d=d.z,null!==d&&(d=d.h(),Xr()===d))?(Ps(a,new Ne(382),new Oe(\"otherParents\")),d=Us(a,Vs().ao.n(hc(44))|0,b,new Ne(383)),a=cba(a,b),new z(d,a)):O().c};\nfunction Ws(a,b){for(var c=O().c;;){var d=!1,e=null,g=Me(a,new Ne(579),new Oe(\"rec\"));if(g instanceof z&&(d=!0,e=g,g=e.z,null!==g&&(g=g.h(),Se()===g))){Ps(a,new Ne(581),new Oe(\"rec\"));continue}if(d&&(g=e.z,null!==g&&(g=g.h(),qs()===g&&b))){Ps(a,new Ne(584),new Oe(\"rec\"));continue}if(d&&(g=e.z,d=e.p,null!==g)){var h=g.h();e=g.j();if(h instanceof bs&&(g=h,h=g.ke,\"@\"===g.ae&&!0===h)){Ps(a,new Ne(587),new Oe(\"rec\"));a:{if(d instanceof z&&(g=d.z,null!==g&&(h=g.h(),g=g.j(),h instanceof bs))){var k=h.ae;\nif(!1===h.ke){d=k;e=g;break a}}d=d.Jg();d.b()?(d=\"end of input\",h=Hs(a)):(g=d.o(),t(),t(),d=g.h().jb(),h=g=it().n(g.j()));g=d;d=h;h=new Te(new Ue(J(new K,[\"Expected an identifier; found \",\" instead\"])));g=[We(Xe(),g)];g=Ye(h,J(new K,g));d=G(new H,g,d);g=O().c;Ze(a,new z(d,g));d=\"\\x3cerror\\x3e\"}Ps(a,new Ne(595),new Oe(\"rec\"));d=new vl(d);t();e=Cq(d,new L(e));c=new z(e,c);continue}}return Km(c)}}\nvar fba=function eba(a){var c=Os(a);if(c instanceof z){var d=c.z;if(null!==d&&(c=d.h(),d=d.j(),c instanceof bs)){var e=c.ae;if(!1===c.ke){Ps(a,new Ne(832),new Oe(\"getIdents\"));c=new jt((t(),new Ud(e)),t().d);t();c=Cq(c,new L(d));d=Os(a);if(d instanceof z&&(d=d.z,null!==d&&(d=d.h(),Xr()===d)))return Ps(a,new Ne(836),new Oe(\"getIdents\")),a=eba(a),new z(c,a);a=O().c;return new z(c,a)}}}return O().c};\nfunction kt(a,b,c){if(a.b())return G(new H,b,c);c instanceof fe&&no();if(c instanceof Ud){var d=c.fa;if(null!==d)return c=d.yb,d=d.ya,t(),a=new sm(c,new Sl(Km(new z(d,a)))),G(new H,b,new Ud(a))}throw new w(c);}function lt(a,b,c,d,e,g,h,k){a.mE=b;a.Lz=c;a.hx=d;a.Fu=e;a.Eu=g;a.kE=h;a.jE=k;a.fx=0;a.le=0;a.Ol=c;a.gx=mt(a).KH}function nt(){this.Lz=this.mE=this.dx=this.lE=this.ex=null;this.hx=!1;this.Fu=null;this.Eu=!1;this.jE=this.kE=null;this.le=this.fx=0;this.gx=this.Ol=null;this.Kz=!1}\nnt.prototype=new p;nt.prototype.constructor=nt;function ot(){}ot.prototype=nt.prototype;function pt(a){null===a.ex&&null===a.ex&&(a.ex=new qt(a));return a.ex}function mt(a){null===a.dx&&null===a.dx&&(a.dx=new rt(a));return a.dx}function gba(a){var b=new vl(\"_$\"+a.fx);a.fx=1+a.fx|0;return b}function st(a,b,c){tt(Vs(),c)||a.Fu.n(Es(b))}function Ze(a,b){tt(Vs(),!1)||a.Fu.n(kr(jr(),b,!0,ws()))}function Ds(a,b){a.nQ(new U(()=>\"\"+ut(Q(),\"\\u2502 \",a.le)+Es(b)))}\nfunction vt(a,b){var c=b.n(a);for(b=Me(a,new Ne(147),new Oe(\"concludeWith\"));;){if(b.b())d=!1;else if(d=b.e(),Pe(new E(d.h()),Se())||Pe(new E(d.h()),qs())){Ps(a,new Ne(147),new Oe(\"concludeWith\"));var d=!0}else d=!1;if(d)b=b.f();else break}var e=b;a:{if(e instanceof z&&(d=e.z,null!==d)){b=d.h();for(d=d.j();;){if(e.b())g=!1;else{g=e.e().h();var g=Pe(new E(g),Se())}if(g)e=e.f();else break}e=e.Jg();b=e.b()?G(new H,b,d):e.o();if(null===b)throw new w(b);d=b.h();b=b.j();e=new Te(new Ue(J(new K,[\"Unexpected \",\n\" here\"])));d=[We(Xe(),d.jb())];d=Ye(e,J(new K,d));t();b=G(new H,d,new L(b));d=O().c;Ze(a,new z(b,d));break a}b=O().c;if(null===b?null!==e:!b.i(e))throw new w(e);}Ds(a,new U(()=>\"Concluded with \"+c));return c}function wt(a,b){a.Ol=b;a.gx=mt(a).KH}function Me(a,b,c){for(a.Eu&&Ds(a,new U(()=>{var d=\"? \"+c.fn+\"\\t\\tinspects \";var e=Bs($r(),xt(a.Ol,5))+(0<a.Ol.ab(5)?\"...\":\"\");return d+e+\"    [at l.\"+b.Zl+\"]\"}));;)if(a.Ol.b()?0:a.Ol.e().h()instanceof gs)Ps(a,b,c);else break;return a.Ol}\nfunction Ps(a,b,c){a.Eu&&Ds(a,new U(()=>\"! \"+c.fn+\"\\t\\tconsumes \"+Bs($r(),xt(a.Ol,1))+\"    [at l.\"+b.Zl+\"]\"));var d=hba(new yt(a.Ol));wt(a,d.b()?O().c:d.o())}\nfunction zt(a,b,c,d,e,g){var h=tc();try{var k=new U(()=>new tl(b,c,d)),l=new Ne(188),m=new Oe(\"skip\");Ds(a,new U(()=>{var ia=m.fn,X=Es(k);X=Fs(X)?ze(X,\"(\",\",\",\")\"):Gs(X)?Es(k):\"(\"+Es(k)+\")\";return\"@ \"+ia+X+\"    [at l.\"+l.Zl+\"]\"}));try{a.le=1+a.le|0;At(tp(),!c.L(b));var n=Me(a,new Ne(190),new Oe(\"skip_res\"));a:{if(n instanceof z){var r=n.z;if(null!==r){var v=r.h(),x=r.j();if(c.L(v))throw Ps(a,new Ne(193),new Oe(\"skip_res\")),Hq(new Iq,h,zt(a,b,c,d,e,g));if(Nm(new E(v),b)){if(!tt(Vs(),g)){var A=new Te(new Ue(J(new K,\n[\"Expected \",\"; found \",\" instead\"]))),B=[We(Xe(),b.jb()),We(Xe(),v.jb())],C=Ye(A,J(new K,B));t();var D=G(new H,C,new L(x)),F=Es(e);Ze(a,new z(D,F))}var I=G(new H,!1,(t(),new L(x)))}else I=G(new H,!0,(t(),new L(x)));break a}}var M=O().c;if(null===M?null===n:M.i(n)){if(!d&&!tt(Vs(),g)){var N=new Te(new Ue(J(new K,[\"Expected \",\"; found end of input instead\"]))),P=[We(Xe(),b.jb())],T=Ye(N,J(new K,P)),Y=Hs(a),Z=G(new H,T,Y),S=Es(e);Ze(a,new z(Z,S))}I=G(new H,d,t().d)}else throw new w(n);}Ps(a,new Ne(206),\nnew Oe(\"skip\"));var ea=I}finally{a.le=-1+a.le|0}Ds(a,new U(()=>\"\\x3d \"+ea));return ea}catch(ia){if(ia instanceof Iq){a=ia;if(a.Qg===h)return a.Cj();throw a;}throw ia;}}function Bt(){tp();var a=[Se()];a=J(new K,a);return Aq(0,a)}\nfunction Le(a){var b=Rs(a,!1,!1),c=h=>{var k=!1,l=null;if(h instanceof fe)return l=h.aa,k=Ye(new Te(new Ue(J(new K,[\"Unexpected 'then'/'else' clause\"]))),u()),l=l.A(),k=G(new H,k,l),l=O().c,Ze(a,new z(k,l)),Ls(a);if(h instanceof Ud&&(k=!0,l=h,h=l.fa,h instanceof Ct)||k&&(h=l.fa,h instanceof Pm))return h;if(k&&(k=l.fa,k instanceof Po))return k;no()};if(b===u())c=u();else{var d=b.e(),e=d=new z(c(d),u());for(b=b.f();b!==u();){var g=b.e();g=new z(c(g),u());e=e.p=g;b=b.f()}c=d}return new Dt(c)}\nfunction Et(a){var b=Os(a);if(b instanceof z&&(b=b.z,null!==b)){var c=b.h();if(c instanceof cs){var d=c.Cc;b=c.td;if(Mk()===d){Ps(a,new Ne(243),new Oe(\"typingUnitMaybeIndented\"));t();d=new L(c.Mf);c=c.jb();a=new Ft(a,b,d,c);var e=Le(a);for(b=Me(a,new Ne(147),new Oe(\"concludeWith\"));;)if(b.b()?c=!1:(c=b.e(),Pe(new E(c.h()),Se())||Pe(new E(c.h()),qs())?(Ps(a,new Ne(147),new Oe(\"concludeWith\")),c=!0):c=!1),c)b=b.f();else break;d=b;a:{if(d instanceof z&&(c=d.z,null!==c)){b=c.h();for(c=c.j();;){if(d.b())g=\n!1;else{g=d.e().h();var g=Pe(new E(g),Se())}if(g)d=d.f();else break}d=d.Jg();b=d.b()?G(new H,b,c):d.o();if(null===b)throw new w(b);c=b.h();b=b.j();d=new Te(new Ue(J(new K,[\"Unexpected \",\" here\"])));c=[We(Xe(),c.jb())];c=Ye(d,J(new K,c));t();b=G(new H,c,new L(b));c=O().c;Ze(a,new z(b,c));break a}b=O().c;if(null===b?null!==d:!b.i(d))throw new w(d);}Ds(a,new U(()=>\"Concluded with \"+e));return e}}}return Le(a)}\nfunction Gt(a){var b=Os(a);if(b instanceof z&&(b=b.z,null!==b)){var c=b.h();b=b.j();if(c instanceof cs){var d=c.Cc,e=c.td;if(Jk()===d){Ps(a,new Ne(249),new Oe(\"curlyTypingUnit\"));t();t();d=new L(c.Mf);c=c.jb();a=new Ft(a,e,d,c);var g=Et(a);for(c=Me(a,new Ne(147),new Oe(\"concludeWith\"));;)if(c.b()?e=!1:(e=c.e(),Pe(new E(e.h()),Se())||Pe(new E(e.h()),qs())?(Ps(a,new Ne(147),new Oe(\"concludeWith\")),e=!0):e=!1),e)c=c.f();else break;d=c;a:{if(d instanceof z&&(e=d.z,null!==e)){c=e.h();for(e=e.j();;){if(d.b())h=\n!1;else{h=d.e().h();var h=Pe(new E(h),Se())}if(h)d=d.f();else break}d=d.Jg();c=d.b()?G(new H,c,e):d.o();if(null===c)throw new w(c);e=c.h();c=c.j();d=new Te(new Ue(J(new K,[\"Unexpected \",\" here\"])));e=[We(Xe(),e.jb())];e=Ye(d,J(new K,e));t();c=G(new H,e,new L(c));e=O().c;Ze(a,new z(c,e));break a}c=O().c;if(null===c?null!==d:!c.i(d))throw new w(d);}Ds(a,new U(()=>\"Concluded with \"+g));t();b=Cq(g,new L(b));return new L(b)}}}return t().d}function Ht(a,b,c){return It(a,Us(a,0,b,c))}\nfunction Rs(a,b,c){for(;;){var d=Ws(a,!0),e=!1,g=null,h=Me(a,new Ne(312),new Oe(\"block\")),k=O().c;if(null===k?null===h:k.i(h))return O().c;if(h instanceof z){e=!0;g=h;var l=g.z;if(null!==l){var m=l.h();if(qs()===m){Ps(a,new Ne(314),new Oe(\"block\"));continue}}}if(e){var n=g.z;if(null!==n){var r=n.h();if(Se()===r){Ps(a,new Ne(315),new Oe(\"block\"));continue}}}if(e){var v=g.z;if(null!==v){var x=v.h(),A=v.j();if(x instanceof as&&\"constructor\"===x.Na){Ps(a,new Ne(317),new Oe(\"block\"));var B=Os(a);a:{if(B instanceof\nz){var C=B.z;if(null!==C){var D=C.h(),F=C.j();if(D instanceof cs){var I=D,M=I.Cc,N=I.td;if(Ik()===M){Ps(a,new Ne(320),new Oe(\"res\"));t();var P=new L(I.Mf),T=I.jb(),Y=vt(new Ft(a,N,P,T),new y(((Yd,bf)=>rf=>Jt(rf,Yd,bf))(c,b))),Z=Gt(a),S=new U(()=>new Dt(O().c)),ea=Z.b()?Es(S):Z.o(),ia=new Gl(Y);t();var X=Cq(ia,new L(F)),sa=new Sl(ef(ea)),Ja=ea.A();var Xa=new Po(X,Cq(sa,Ja));break a}}}}var Fa=Ye(new Te(new Ue(J(new K,[\"Expect parameter list for the constructor\"]))),u());t();var za=G(new H,Fa,new L(A)),\nQa=O().c;Ze(a,new z(za,Qa));Xa=new Po(new Gl(O().c),new Sl(O().c))}t();t();var Ma=Kt(A,Dq(Xa)),Ga=Cq(Xa,new L(Ma)),ab=new Ud(Ga),Hb=Rs(a,b,c);return new z(ab,Hb)}}}a:{if(null!==h){var bc=mt(a).HC(h);if(!bc.b()){var yb=bc.k.h(),tb=bc.k.j();if(tb instanceof z){var eb=tb.z;if(null!==eb){var kb=eb.h(),Rb=eb.j();if(kb instanceof as){var Gb=kb.Na;if(\"class\"===Gb||\"infce\"===Gb||\"trait\"===Gb||\"mixin\"===Gb||\"type\"===Gb||\"module\"===Gb){Ps(a,new Ne(332),new Oe(\"t\"));var vb=Lt(yb,\"declare\");if(null!==vb)var Tb=\nG(new H,vb.h(),vb.j());else throw new w(vb);var Nb=Tb.h(),ic=Lt(Tb.j(),\"abstract\");if(null!==ic)var Va=G(new H,ic.h(),ic.j());else throw new w(ic);var cb=Va.h();Mt(Va.j());switch(Gb){case \"class\":var zb=Bp();break;case \"trait\":zb=Fp();break;case \"mixin\":zb=cp();break;case \"type\":zb=Ap();break;case \"module\":zb=zp();break;default:xm(\"Program reached and unexpected state.\")}var Ub=Os(a);b:{if(Ub instanceof z){var jb=Ub.z;if(null!==jb){var db=jb.h(),ub=jb.j();if(db instanceof bs){var Aa=db.ae;Ps(a,new Ne(346),\nnew Oe(\"x$19\"));var va=new Ep(Aa);t();var Ra=G(new H,Cq(va,new L(ub)),!0);break b}}}var rb=Ub.Jg(),xb=new U(()=>G(new H,\"end of input\",Hs(a))),mc=new y(Yd=>{t();t();Yd=G(new H,(new y(bf=>bf.jb())).n(Yd.h()),Yd.j());return G(new H,Yd.y,it().n(Yd.w))}),Ha=rb.b()?Es(xb):mc.n(rb.o());if(null!==Ha)var Ka=G(new H,Ha.h(),Ha.j());else throw new w(Ha);var Oa=Ka.h(),Na=Ka.j(),Da=new Te(new Ue(J(new K,[\"Expected a type name; found \",\" instead\"]))),ta=[We(Xe(),Oa)],Ya=Ye(Da,J(new K,ta)),dc=G(new H,Ya,Na),ka=\nO().c;Ze(a,new z(dc,ka));Ps(a,new Ne(352),new Oe(\"x$19\"));var ya=new Ep(\"\\x3cerror\\x3e\"),Sa=Js(a),xc=new y(Yd=>vs(Yd)),Sb=Sa.b()?R():new L(xc.n(Sa.o()));Ra=G(new H,Cq(ya,Sb),!1)}if(null!==Ra)var uc=G(new H,Ra.h(),Ra.cy());else throw new w(Ra);var Lb=uc.h(),lc=Os(a);b:{if(lc instanceof z){var Xb=lc.z;if(null!==Xb){var ec=Xb.h();if(ec instanceof cs){var Ab=ec,Ob=Ab.Cc,fb=Ab.td;if(Lk()===Ob||Kk()===Ob){Ps(a,new Ne(358),new Oe(\"tparams\"));t();var Wa=new L(Ab.Mf),bb=Ab.jb();var Ia=vt(new Ft(a,fb,Wa,bb),\nnew y(((Yd,bf)=>rf=>iba(rf,new fn(Cg=>Nt(Cg,Yd,bf))))(c,b)));break b}}}}Ia=O().c}var Ua=Os(a);b:{if(Ua instanceof z){var pc=Ua.z;if(null!==pc){var sc=pc.h(),Ba=pc.j();if(sc instanceof cs){var ob=sc,nc=ob.Cc,Ib=ob.td;if(Ik()===nc){Ps(a,new Ne(375),new Oe(\"params\"));t();var vc=new L(ob.Mf),Vb=ob.jb(),fc=vt(new Ft(a,Ib,vc,Vb),new y(((Yd,bf)=>rf=>Jt(rf,Yd,bf))(c,b)));t();var Bc=new Gl(fc);t();var Pb=Cq(Bc,new L(Ba));var Jb=new L(Pb);break b}}}}Jb=t().d}var gc=!1,Cb=null,cc=Os(a);b:{if(cc instanceof z){gc=\n!0;Cb=cc;var yc=Cb.z;if(null!==yc){var Mc=yc.h();if(Mc instanceof as&&\"\\x3d\"===Mc.Na&&Ot(new E(zb),Ap())){Ps(a,new Ne(388),new Oe(\"sigTrm\"));t();var qc=Us(a,0,c,new Ne(389));var oc=new L(qc);break b}}}if(gc){var Qc=Cb.z;if(null!==Qc){var jc=Qc.h();if(jc instanceof as&&\":\"===jc.Na&&!Ot(new E(zb),Ap())){Ps(a,new Ne(391),new Oe(\"sigTrm\"));t();var sb=Us(a,0,c,new Ne(392));oc=new L(sb);break b}}}oc=t().d}var Gc=Os(a);b:{if(Gc instanceof z){var Wb=Gc.z;if(null!==Wb){var Cc=Wb.h();if(Cc instanceof as&&\"extends\"===\nCc.Na){Ps(a,new Ne(400),new Oe(\"ps\"));var Fc=Us(a,Vs().ao.n(hc(44))|0,c,new Ne(401)),qd=dba(a,c);var Yb=new z(Fc,qd);break b}}}Yb=O().c}var Nc=Gt(a),ad=new U(((Yd,bf)=>()=>{var rf=Is(Yd);if(rf instanceof L){var Cg=rf.k;if(Cg instanceof cm){rf=Cg.Ys;Cg=Cg.Zs;var nj=Km(Yd).f();return new tl(bf,Km(new z(rf,nj)),Cg)}}return bf instanceof L&&(Cg=bf.k,Cg instanceof cm)?(rf=Cg.Ys,Cg=Cg.Zs,new tl((t(),new L(rf)),Yd,Cg)):new tl(bf,Yd,new Dt(O().c))})(Yb,oc)),Uc=new y(((Yd,bf)=>rf=>new tl(Yd,bf,rf))(oc,Yb)),\ncd=Nc.b()?Es(ad):Uc.n(Nc.o());if(null!==cd)var kc=new tl(cd.kc,cd.hb,cd.Rd);else throw new w(cd);var Vc=kc.kc,Hc=kc.hb,rc=kc.Rd,sd=new y(Yd=>It(a,Yd)),Kc=Vc.b()?R():new L(sd.n(Vc.o())),Qd=ef(rc),Ad=Pt(Qd,new y(Yd=>{if(Yd instanceof Po)return t(),new fe(Yd);t();return new Ud(Yd)}));if(null!==Ad)var kd=G(new H,Ad.h(),Ad.j());else throw new w(Ad);var Hd=kd.h(),Rd=new Dt(kd.j()),Bd=rc.A(),ae=Cq(Rd,Bd);if(0<Hd.ab(1)){var dd=Ye(new Te(new Ue(J(new K,[\"A class may have at most one explicit constructor\"]))),\nu());t();var od=G(new H,dd,new L(Rb)),Ta=O().c;Ze(a,new z(od,Ta));t()}var wb=Hd.Jg(),$a=new yo(zb,Lb,Ia,Jb,wb,Kc,Hc,t().d,t().d,ae,Nb,cb,d);t();t();var wa=Kt(Kt(Rb,Dq(Lb)),Dq($a));Cq($a,new L(wa));t();t();var hb=Kt(Rb,Dq($a)),ra=Cq($a,new L(hb));var wc=new Ud(ra);break a}}}}}}if(null!==h){var ac=mt(a).HC(h);if(!ac.b()){var Id=ac.k.h(),ud=ac.k.j();if(ud instanceof z){var be=ud.z;if(null!==be){var re=be.h(),pe=be.j();if(re instanceof as){var bd=re.Na;if(\"fun\"===bd||\"val\"===bd||\"let\"===bd){Ps(a,new Ne(432),\nnew Oe(\"t\"));var Rc=Lt(Id,\"declare\");if(null!==Rc)var Wc=G(new H,Rc.h(),Rc.j());else throw new w(Rc);var Wd=Wc.h(),zd=Lt(Wc.j(),\"virtual\");if(null!==zd)var Pa=G(new H,zd.h(),zd.j());else throw new w(zd);var Db=Pa.h(),Oc=Lt(Pa.j(),\"mut\");if(null!==Oc)var Tc=G(new H,Oc.h(),Oc.j());else throw new w(Oc);var Sd=Tc.h();Mt(Tc.j());var Jc=Nm(new E(bd),\"let\"),vd=Os(a);b:{if(vd instanceof z){var hd=vd.z;if(null!==hd){var de=hd.h();if(de instanceof as&&\"rec\"===de.Na&&\"let\"===bd){Ps(a,new Ne(440),new Oe(\"isLetRec\"));\nt();var ye=new L(!0);break b}}}ye=\"fun\"===bd?t().d:(t(),new L(!1))}var jf=Os(a);b:{if(jf instanceof z){var af=jf.z;if(null!==af){var pf=af.h(),kf=af.j();if(pf instanceof cs){var Be=pf,Kd=Be.Cc,ld=Be.td;if(Ik()===Kd){var Jd=!1,Dd=null;if(ld instanceof z){Jd=!0;Dd=ld;var Xd=Dd.z,Yc=Dd.p;if(null!==Xd){var Ce=Xd.h(),te=Xd.j();if(Ce instanceof bs){var Ie=Ce,Jf=Ie.ae;if(!0===Ie.ke){Ps(a,new Ne(448),new Oe(\"opStr\"));var df=jba(Yc,new y(Yd=>Pe(new E(Yd.h()),Se())));c:{var vg=O().c;if(null===vg?null!==df:\n!vg.i(df)){if(df instanceof z){var wg=df.z;if(null!==wg){var xg=wg.h(),eg=wg.j(),vh=new Te(new Ue(J(new K,[\"Unexpected \",\" after symbolic name\"]))),fg=[We(Xe(),xg.jb())],ih=Ye(vh,J(new K,fg));t();var Ig=G(new H,ih,new L(eg)),Tf=O().c;Ze(a,new z(Ig,Tf));break c}}throw new w(df);}}t();var Jg=new vl(Jf);t();var jh=Cq(Jg,new L(te));var yg=new L(jh);break b}}}}if(Jd){var gg=Dd.z;if(null!==gg){var Cf=gg.h(),Uf=gg.j();Ps(a,new Ne(456),new Oe(\"opStr\"));var $g=new Te(new Ue(J(new K,[\"Expected a symbolic name, found \",\n\" instead\"]))),Ah=[We(Xe(),Cf.jb())],Kg=Ye($g,J(new K,Ah));t();var Vf=G(new H,Kg,new L(Uf)),hg=O().c;Ze(a,new z(Vf,hg));yg=t().d;break b}}var zg=O().c;if(null===zg?null===ld:zg.i(ld)){Ps(a,new Ne(460),new Oe(\"opStr\"));var Lg=Ye(new Te(new Ue(J(new K,[\"Expected a symbolic name between brackets, found nothing\"]))),u());t();var Mg=G(new H,Lg,new L(kf)),Wf=O().c;Ze(a,new z(Mg,Wf));yg=t().d;break b}throw new w(ld);}}}}yg=t().d}var Ng=Os(a);b:{if(Ng instanceof z){var Kf=Ng.z;if(null!==Kf){var xf=Kf.h(),\nOg=Kf.j();if(xf instanceof bs){var mi=xf,Ci=mi.ae;if(!1===mi.ke){Ps(a,new Ne(468),new Oe(\"x$34\"));var Xh=new vl(Ci);t();var wh=G(new H,Cq(Xh,new L(Og)),!0);break b}}}}var Bh=Ng.Jg(),ng=new U(()=>G(new H,\"end of input\",Hs(a))),kh=new y(Yd=>{t();t();Yd=G(new H,(new y(bf=>bf.jb())).n(Yd.h()),Yd.j());return G(new H,Yd.y,it().n(Yd.w))}),Kh=Bh.b()?Es(ng):kh.n(Bh.o());if(null!==Kh)var ni=G(new H,Kh.h(),Kh.j());else throw new w(Kh);var Lh=ni.h(),lh=ni.j(),Ch=new Te(new Ue(J(new K,[\"Expected a function name; found \",\n\" instead\"]))),Dh=[We(Xe(),Lh)],Yh=Ye(Ch,J(new K,Dh)),ah=G(new H,Yh,lh),oi=O().c;Ze(a,new z(ah,oi));Ps(a,new Ne(473),new Oe(\"x$34\"));var mj=new vl(\"\\x3cerror\\x3e\"),wd=Js(a),ge=new y(Yd=>vs(Yd)),De=wd.b()?R():new L(ge.n(wd.o()));wh=G(new H,Cq(mj,De),!1)}if(null!==wh)var qf=G(new H,wh.h(),wh.cy());else throw new w(wh);var og=qf.h(),Xf=qf.cy(),mh=tt(Vs(),c)||!Xf;wc=(new y(((Yd,bf,rf,Cg,nj,Jh,If,Hg,He,lj)=>Wi=>{var Oj=!!Wi;if(\"let\"===Yd){t();var mo=u(),mm=Pd(u(),mo)}else{var nm=Os(a);a:{if(nm instanceof\nz){var dq=nm.z;if(null!==dq){var Zd=dq.h();if(Zd instanceof cs){var sf=Zd.Cc,oj=Zd.td;if(Lk()===sf||Kk()===sf){Ps(a,new Ne(480),new Oe(\"tparams\"));t();var al=new L(Zd.Mf),Ll=Zd.jb();mm=Qt(vt(new Ft(a,oj,al,Ll),new y(Ca=>Jt(Ca,Oj,Oj))),new y(Ca=>{if(null!==Ca){var Lc=Ca.h();Ca=Ca.j();if(t().d===Lc&&null!==Ca&&(Lc=Ca.yb,Ca=Ca.ya,null!==Lc)){var yd=Lc.ch;if(!1===Lc.je&&!1===yd&&Ca instanceof vl)return Lc=new Ep(Ca.x),Ca=Ca.A(),Cq(Lc,Ca)}}no()}));break a}}}}mm=O().c}}var Qm=Os(a);a:{if(Qm instanceof z){var Rm=\nQm.z,hq=Qm.p;if(null!==Rm){var Bn=Rm.h(),hp=Rm.j();if(Bn instanceof cs){var ru=Bn.Cc,qr=Bn.td;if(Ik()===ru&&null!==qr){var Xs=pt(a).HC(qr);if(!Xs.b()){var rr=Xs.k.j();if(rr instanceof z){var iq=rr.z,qo=rr.p;if(null!==iq){var qm=iq.h(),jq=iq.j();if(qm instanceof as&&\"override\"===qm.Na){var pl=new cs(Ik(),qo,Bn.Mf),ro=G(new H,pl,hp);wt(a,new z(ro,hq));var Cn=Rt(a,Oj,Oj,new Ne(492));if(Cn instanceof z){var ip=Cn.z,so=Cn.p;if(null!==ip){var Dn=ip.Ra;if(Dn instanceof z){var sr=Dn.z,kq=Dn.p;if(null!==sr){var ql=\nnew L(sr);if(!ql.b()){var Ys=ql.k.h(),Sm=ql.k.j();if(t().d===Ys&&null!==Sm){var Nl=Sm.yb,jp=Sm.ya;if(null!==Nl){var lq=Nl.ch,mq=Nl.Bh;if(!1===Nl.je)if(!1===lq){var Tm=O().c;if(null===Tm?null===kq:Tm.i(kq))var En=O().c,to=null===En?null===so:En.i(so);else to=!1}else to=!1;else to=!1;if(to){var Fn=gba(a),nq=t().d,Um=new sm(new St(!1,!1,mq),Fn),kp=G(new H,nq,Um),oq=O().c,su=new Gl(new z(kp,oq)),Gn=O().c,ur=new z(su,Gn);t();var In=G(new H,ur,new L(new y(Ca=>{Ca=new Tt(Fn,new vl(\"is\"),new Ut(jp,Ca));t();\nvar Lc=new am;t();Lc=new Ql(Cq(Lc,new L(jq)),bf);var yd=t().d,Qe=new sm(new St(!1,!1,mq),Fn);yd=G(new H,yd,Qe);Qe=O().c;Lc=new Pl(Lc,new Gl(new z(yd,Qe)));return new Xl(Ca,new L(Lc))})));break a}}}}}}}}var Zs=Ye(new Te(new Ue(J(new K,[\"Unsupported 'override' parameter list shape\"]))),u());t();var $s=G(new H,Zs,new L(Bn.Mf)),pq=O().c;Ze(a,new z($s,pq));In=G(new H,Cn,t().d);break a}}}}}}}}In=G(new H,Rt(a,Oj,Oj,new Ne(505)),t().d)}if(null!==In)var vr=G(new H,In.h(),In.j());else throw new w(In);var Vm=\nvr.h(),Jn=vr.j(),wr=Os(a);a:{if(wr instanceof z){var at=wr.z;if(null!==at){var xr=at.h();if(xr instanceof as&&\":\"===xr.Na){Ps(a,new Ne(509),new Oe(\"asc\"));t();var lp=Ht(a,Oj,new Ne(511));var Kn=new L(lp);break a}}}Kn=t().d}var qq=Os(a);if(qq instanceof z){var yr=qq.z;if(null!==yr){var rq=yr.h();if(rq instanceof as&&\"\\x3d\"===rq.Na){Ps(a,new Ne(516),new Oe(\"t\"));var sq=Us(a,0,Oj,new Ne(517)),bt=new U(()=>sq),tq=new y(Ca=>Ca.n(sq)),zr=Jn.b()?Es(bt):tq.n(Jn.o()),ct=new U(()=>zr),Ar=new y(Ca=>new Cl(zr,\nCa)),uq=Kn.b()?Es(ct):Ar.n(Kn.o()),Br=Os(a);if(Br instanceof z){var Ln=Br.z;if(null!==Ln){var vq=Ln.h(),Cr=Ln.j();if(vq instanceof as&&\"in\"===vq.Na&&\"let\"===Yd){Ps(a,new Ne(522),new Oe(\"t\"));if(!mm.b()){var tu=Ye(new Te(new Ue(J(new K,[\"Unsupported type parameters on 'let' binding\"]))),u());t();var uu=G(new H,tu,new L(Cr)),dt=O().c;Ze(a,new z(uu,dt))}var vu=Us(a,0,Oj,new Ne(524));t();var Dr=new U(()=>{xm(\"Program reached and unexpected state.\")}),uo=new Rl(!(rf.b()?!Es(Dr):!rf.o()),bf,sq,vu);t();\nvar Er=Kt(Cg,uq.A()),et=Cq(uo,new L(Er));return new Ud(et)}}}t();t();var ft=Vm.mf(uq,new fn((Ca,Lc)=>new Ol(Ca,Lc))),gt=new Zn(rf,bf,nj,mm,new fe(ft),Jh,If,Hg,t().d,t().d,He,lj);t();var Wm=Kt(Cg,uq.A()),Fr=Cq(gt,new L(Wm));return new Ud(Fr)}}}if(Kn instanceof L){var mp=Kn.k;Jn.b()||xm(\"Program reached and unexpected state.\");t();t();var wu=new Vt(O().c,Vm.mf(mp,new fn((Ca,Lc)=>{Ca=Qn(Ca);if(Ca instanceof fe){var yd=Ca.aa;st(a,new U(()=>yd),Oj);Ca=gl()}else if(Ca instanceof Ud)Ca=Ca.fa;else throw new w(Ca);\nreturn new Wt(Ca,Lc)}))),ht=new Zn(rf,bf,nj,mm,new Ud(wu),Jh,If,Hg,t().d,t().d,He,lj);t();var wq=Kt(Cg,mp.A()),xq=Cq(ht,new L(wq));return new Ud(xq)}if(t().d===Kn){var Gr=qq.Jg(),xu=new U(()=>G(new H,\"end of input\",Hs(a))),yu=new y(Ca=>{t();t();Ca=G(new H,(new y(Lc=>Lc.jb())).n(Ca.h()),Ca.j());return G(new H,Ca.y,it().n(Ca.w))}),Re=Gr.b()?Es(xu):yu.n(Gr.o());if(null!==Re)var rj=G(new H,Re.h(),Re.j());else throw new w(Re);var ai=rj.h(),rm=rj.j(),Nn=new Te(new Ue(J(new K,[\"Expected ':' or '\\x3d' followed by a function body or signature; found \",\n\" instead\"]))),zu=[We(Xe(),ai)],Au=Ye(Nn,J(new K,zu)),Av=G(new H,Au,rm),oy=O().c;Ze(a,new z(Av,oy));Ps(a,new Ne(545),new Oe(\"t\"));var Bv=Ls(a);t();var Cv=O().c;t();var py=Vm.mf(Bv,new fn((Ca,Lc)=>new Ol(Ca,Lc))),qy=new Zn(rf,bf,nj,Cv,new fe(py),Jh,If,Hg,t().d,t().d,He,lj);t();var Dv=Kt(Cg,Bv.A()),Ee=Cq(qy,new L(Dv));return new Ud(Ee)}throw new w(Kn);})(bd,og,ye,pe,yg,Wd,Db,Sd,Jc,d))).n(mh);break a}}}}}}wc=Qs(a,0,!1,d,b,c,new Ne(554))}var Ag=Os(a);a:{if(Ag instanceof z){var Bg=Ag.z;if(null!==Bg){var Eh=\nBg.h();if(Eh instanceof as&&\"\\x3d\"===Eh.Na){var Pg=!1,Di=null;if(wc instanceof Ud){Pg=!0;Di=wc;var Mh=Di.fa;if(Mh instanceof vl){var pi=Mh;Ps(a,new Ne(559),new Oe(\"finalTerm\"));t();var Xi=new bm(pi,Us(a,0,c,new Ne(560)));var Qg=new Ud(Xi);break a}}if(Pg){var nh=Di.fa;if(nh instanceof Pl){var bh=nh,Mj=bh.Za,Nj=bh.Qb;if(Mj instanceof vl){var ie=Mj;Ps(a,new Ne(562),new Oe(\"finalTerm\"));t();var Ac=new bm(ie,new Ol(Nj,Us(a,0,c,new Ne(563))));Qg=new Ud(Ac);break a}}}Qg=wc;break a}}}Qg=wc}var Ve=!1,Td=null,\nlf=Os(a);if(lf instanceof z){Ve=!0;Td=lf;var Yi=Td.z;if(null!==Yi){var Jl=Yi.h();if(ds()===Jl){Ps(a,new Ne(570),new Oe(\"block\"));var ll=Rs(a,b,c);return new z(Qg,ll)}}}if(Ve){var Bj=Td.z;if(null!==Bj){var $k=Bj.h();if(qs()===$k){Ps(a,new Ne(571),new Oe(\"block\"));var Zh=Rs(a,b,c);return new z(Qg,Zh)}}}var Ei=O().c;return new z(Qg,Ei)}}\nfunction Os(a){for(var b=Me(a,new Ne(606),new Oe(\"yeetSpaces\"));;){if(b.b())c=!1;else if(c=b.e(),Pe(new E(c.h()),Se())||c.h()instanceof gs){Ps(a,new Ne(609),new Oe(\"yeetSpaces\"));var c=!0}else c=!1;if(c)b=b.f();else break}return b}\nfunction Rt(a,b,c,d){var e=new U(()=>{}),g=new Oe(\"funParams\");Ds(a,new U(()=>{var db=g.fn,ub=Es(e);ub=Fs(ub)?ze(ub,\"(\",\",\",\")\"):Gs(ub)?Es(e):\"(\"+Es(e)+\")\";return\"@ \"+db+ub+\"    [at l.\"+d.Zl+\"]\"}));try{a.le=1+a.le|0;var h=!1,k=null,l=Os(a);a:{if(l instanceof z){h=!0;k=l;var m=k.z;if(null!==m){var n=m.h();if(n instanceof as){var r=n.Na;if(\"\\x3d\"===r||\":\"===r){var v=O().c;break a}}}}if(h){var x=k.z;if(null!==x){var A=x.h();if(A instanceof as&&\"of\"===A.Na){Ps(a,new Ne(615),new Oe(\"funParams\"));var B=\nnew Gl(Xt(a,!1,Vs().Du,c,b)),C=Rt(a,b,c,new Ne(617));v=new z(B,C);break a}}}if(h){var D=k.z;if(null!==D){var F=D.h(),I=D.j();if(F instanceof cs){var M=F.Cc,N=F.td;if(Ik()===M){Ps(a,new Ne(619),new Oe(\"funParams\"));t();for(var P=new L(F.Mf),T=F.jb(),Y=new Ft(a,N,P,T),Z=Jt(Y,c,b),S=Me(Y,new Ne(147),new Oe(\"concludeWith\"));;){if(S.b())ia=!1;else{var ea=S.e();if(Pe(new E(ea.h()),Se())||Pe(new E(ea.h()),qs())){Ps(Y,new Ne(147),new Oe(\"concludeWith\"));var ia=!0}else ia=!1}if(ia)S=S.f();else break}h=S;b:{if(h instanceof\nz){var X=h.z;if(null!==X){var sa=X.h(),Ja=X.j();for(X=h;;){if(X.b())Fa=!1;else var Xa=X.e().h(),Fa=Pe(new E(Xa),Se());if(Fa)X=X.f();else break}var za=X.Jg(),Qa=za.b()?G(new H,sa,Ja):za.o();if(null===Qa)throw new w(Qa);var Ma=Qa.h(),Ga=Qa.j(),ab=new Te(new Ue(J(new K,[\"Unexpected \",\" here\"]))),Hb=[We(Xe(),Ma.jb())],bc=Ye(ab,J(new K,Hb));t();var yb=G(new H,bc,new L(Ga)),tb=O().c;Ze(Y,new z(yb,tb));break b}}var eb=O().c;if(null===eb?null!==h:!eb.i(h))throw new w(h);}Ds(Y,new U(()=>\"Concluded with \"+\nZ));var kb=new Gl(Z);t();var Rb=Cq(kb,new L(I)),Gb=Rt(a,b,c,new Ne(621));v=new z(Rb,Gb);break a}}}}if(h){var vb=k.z;if(null!==vb){var Tb=vb.h(),Nb=vb.j(),ic=new Te(new Ue(J(new K,[\"Expected function parameter list; found \",\" instead\"]))),Va=[We(Xe(),Tb.jb())],cb=Ye(ic,J(new K,Va));t();var zb=G(new H,cb,new L(Nb)),Ub=O().c;Ze(a,new z(zb,Ub));Ps(a,new Ne(626),new Oe(\"funParams\"));v=O().c;break a}}var jb=O().c;if(null===jb?null===l:jb.i(l))v=O().c;else throw new w(l);}}finally{a.le=-1+a.le|0}Ds(a,new U(()=>\n\"\\x3d \"+v));return v}function Us(a,b,c,d){var e=new U(()=>new Yt(b,!0)),g=new Oe(\"expr\");Ds(a,new U(()=>{var m=g.fn,n=Es(e);n=Fs(n)?ze(n,\"(\",\",\",\")\"):Gs(n)?Es(e):\"(\"+Es(e)+\")\";return\"@ \"+m+n+\"    [at l.\"+d.Zl+\"]\"}));try{a.le=1+a.le|0;var h=O().c,k=Qs(a,b,!0,h,!1,c,new Ne(643));if(k instanceof Ud)var l=k.fa;else if(k instanceof fe)l=Ks(a,k.aa.A());else throw new w(k);}finally{a.le=-1+a.le|0}Ds(a,new U(()=>\"\\x3d \"+l));return l}\nfunction Zt(a,b,c,d){var e=Os(a);if(e instanceof z&&(e=e.z,null!==e&&(e=e.h(),qs()===e))){Ps(a,d,new Oe(\"exprOrBlockContinuation\"));e=Rs(a,b,c);b=h=>{if(h instanceof fe)return Ks(a,h.aa.A());if(h instanceof Ud)return h.fa;throw new w(h);};if(e===u())b=u();else{c=e.e();d=c=new z(b(c),u());for(e=e.f();e!==u();){var g=e.e();g=new z(b(g),u());d=d.p=g;e=e.f()}b=c}return new Sl(b)}return Us(a,0,c,d)}\nfunction Qs(a,b,c,d,e,g,h){var k=tc();try{return Cs(a,new U(()=>new Yt(b,c)),new y(()=>{var l=Ws(a,!1);l.b()||Os(a);var m=un(d,l),n=!1,r=null,v=Me(a,new Ne(710),new Oe(\"res\"));a:{if(v instanceof z){n=!0;r=v;var x=r.z;if(null!==x){var A=x.h();if(Se()===A&&c){Ps(a,new Ne(712),new Oe(\"res\"));var B=Qs(a,b,c,O().c,e,g,new Ne(713));break a}}}if(n){var C=r.z;if(null!==C){var D=C.h();if(D instanceof cs){var F=D.Cc,I=D.td;if(Mk()===F){var M=I.Jg();b:{if(M instanceof L){var N=M.k;if(null!==N){var P=N.h();if(P instanceof\nas){var T=P.Na;if(\"then\"===T||\"else\"===T){var Y=!1;break b}}}}Y=!0}}else Y=!1;if(Y){Ps(a,new Ne(718),new Oe(\"res\"));t();var Z=new L(D.Mf),S=D.jb(),ea=vt(new Ft(a,I,Z,S),new y(Ee=>Rs(Ee,e,g))),ia=Qt(ea,new y(Ee=>{if(Ee instanceof fe)throw t(),Ee=new $t(ea),Hq(new Iq,k,new fe(Ee));if(Ee instanceof Ud)return Ee.fa;throw new w(Ee);}));t();var X=new Sl(ia);B=new Ud(X);break a}}}}if(n){var sa=r.z;if(null!==sa){var Ja=sa.h(),Xa=sa.j();if(Yr()===Ja){Ps(a,new Ne(723),new Oe(\"res\"));var Fa=!1,za=null,Qa=Me(a,\nnew Ne(724),new Oe(\"res\"));if(Qa instanceof z){Fa=!0;za=Qa;var Ma=za.z;if(null!==Ma){var Ga=Ma.h(),ab=Ma.j();if(Ga instanceof bs){var Hb=Ga.ae;if(!1===Ga.ke){Ps(a,new Ne(726),new Oe(\"res\"));var bc=new em(new vl(Hb));t();var yb=xs(Xa,ab);B=au(a,Cq(bc,new L(yb)),b,!1,e,g,new Ne(727));break a}}}}if(Fa){var tb=za.z;if(null!==tb){var eb=tb.h(),kb=tb.j();if(eb instanceof fs){var Rb=eb.Cu;Ps(a,new Ne(729),new Oe(\"res\"));t();var Gb=new em(Cq(Rb,new L(kb)));t();var vb=xs(Xa,kb);B=au(a,Cq(Gb,new L(vb)),b,!1,\ne,g,new Ne(730));break a}}}if(Fa){var Tb=za.z;if(null!==Tb){var Nb=Tb.h(),ic=Tb.j();if(Nb instanceof as&&\"let\"===Nb.Na){Ps(a,new Ne(732),new Oe(\"res\"));var Va=Ns(a,!0,e,g,new Ne(733));if(Va instanceof Ud){var cb=Va.fa;t();t();var zb=Kt(Xa,cb.A()),Ub=Cq(cb,new L(zb));B=new Ud(Ub)}else{t();var jb=Ms(a,(t(),new L(ic)));B=new Ud(jb)}break a}}}if(Fa){var db=za.z;if(null!==db){var ub=db.h(),Aa=db.j();if(ub instanceof as&&\"if\"===ub.Na){var va=Qs(a,b,c,O().c,e,g,new Ne(738));if(va instanceof Ud){var Ra=va.fa;\nif(Ra instanceof Xl){var rb=Ra.bp,xb=Ra.zs;if(rb instanceof Ut){var mc=rb.Km,Ha=rb.Lm;t();var Ka=new Ut(new fm(mc),new fm(Ha)),Oa=new y(Ee=>new fm(Ee)),Na=new em(new Xl(Ka,xb.b()?R():new L(Oa.n(xb.o()))));t();var Da=Kt(Xa,Ra.A()),ta=Cq(Na,new L(Da));B=new Ud(ta);break a}}}t();var Ya=Ms(a,(t(),new L(Aa)));B=new Ud(Ya);break a}}}if(Fa){var dc=za.z;if(null!==dc){var ka=dc.h(),ya=dc.j();if(ka instanceof cs){var Sa=ka.Cc,xc=ka.td;if(Ik()===Sa){Ps(a,new Ne(745),new Oe(\"res\"));t();var Sb=new L(ka.Mf),uc=\nka.jb(),Lb=vt(new Ft(a,xc,Sb,uc),new y(Ee=>Jt(Ee,g,e)));b:{if(Lb instanceof z){var lc=Lb.z,Xb=Lb.p;if(null!==lc){var ec=lc.h(),Ab=lc.j();if(t().d===ec&&null!==Ab){var Ob=Ab.yb,fb=Ab.ya;if(null!==Ob){var Wa=Ob.ch;if(!1===Ob.je)if(!1===Wa)var bb=O().c,Ia=null===bb?null===Xb:bb.i(Xb);else Ia=!1;else Ia=!1;if(Ia){var Ua=new em(new Fl(!1,fb));t();var pc=Kt(ya,fb.A());var sc=Cq(Ua,new L(pc));break b}}}}}sc=Ms(a,(t(),new L(ya)))}B=au(a,sc,b,!1,e,g,new Ne(750));break a}}}}t();var Ba=Ms(a,(t(),new L(Xa)));\nB=new Ud(Ba);break a}}}if(n){var ob=r.z;if(null!==ob){var nc=ob.h(),Ib=ob.j();if(nc instanceof fs){var vc=nc.Cu;Ps(a,new Ne(754),new Oe(\"res\"));t();B=au(a,Cq(vc,new L(Ib)),b,!1,e,g,new Ne(755));break a}}}if(n){var Vb=r.z;if(null!==Vb){var fc=Vb.h(),Bc=Vb.j();if(fc instanceof as){var Pb=fc.Na;if(\"undefined\"===Pb||\"null\"===Pb){Ps(a,new Ne(757),new Oe(\"res\"));var Jb=new Gm(\"undefined\"===Pb);t();B=au(a,Cq(Jb,new L(Bc)),b,!1,e,g,new Ne(758));break a}}}}if(n){var gc=r.z;if(null!==gc){var Cb=gc.h(),cc=gc.j();\nif(Cb instanceof bs){var yc=Cb.ae;if(!1===Cb.ke){Ps(a,new Ne(760),new Oe(\"res\"));var Mc=new vl(yc);t();B=au(a,Cq(Mc,new L(cc)),b,!1,e,g,new Ne(761));break a}}}}if(n){var qc=r.z;if(null!==qc){var oc=qc.h(),Qc=qc.j();if(oc instanceof cs){var jc=oc.Cc,sb=oc.td;if(Nk()===jc||Ok()===jc){Ps(a,new Ne(763),new Oe(\"res\"));t();var Gc=new L(oc.Mf),Wb=oc.jb(),Cc=vt(new Ft(a,sb,Gc,Wb),new y(Ee=>Us(Ee,0,g,new Ne(764)))),Fc=new em(Cc);t();B=au(a,Cq(Fc,new L(Qc)),b,!1,e,g,new Ne(765));break a}}}}if(n){var qd=r.z;\nif(null!==qd){var Yb=qd.h(),Nc=qd.j();if(Yb instanceof cs){var ad=Yb.Cc,Uc=Yb.td;if(Pk()===ad){Ps(a,new Ne(767),new Oe(\"res\"));t();var cd=new L(Yb.Mf),kc=Yb.jb(),Vc=vt(new Ft(a,Uc,cd,kc),new y(Ee=>Us(Ee,0,g,new Ne(768)))),Hc=new fm(Vc);t();B=au(a,Cq(Hc,new L(Nc)),b,!1,e,g,new Ne(769));break a}}}}if(n){var rc=r.z;if(null!==rc){var sd=rc.h(),Kc=rc.j();if(sd instanceof as&&\"super\"===sd.Na){Ps(a,new Ne(771),new Oe(\"res\"));var Qd=new am;t();B=au(a,Cq(Qd,new L(Kc)),b,!1,e,g,new Ne(772));break a}}}if(n){var Ad=\nr.z;if(null!==Ad){var kd=Ad.h(),Hd=Ad.j();if(kd instanceof bs&&\"~\"===kd.ae){Ps(a,new Ne(774),new Oe(\"res\"));var Rd=Us(a,b,g,new Ne(775)),Bd=new vl(\"~\");t();var ae=new Pl(Cq(Bd,new L(Hd)),Rd);t();var dd=Kt(Hd,Rd.A());B=au(a,Cq(ae,new L(dd)),b,!1,e,g,new Ne(776));break a}}}if(n){var od=r.z;if(null!==od){var Ta=od.h();if(Ta instanceof cs){var wb=Ta.Cc,$a=Ta.td;if(Ik()===wb&&$a instanceof z){var wa=$a.z,hb=$a.p;if(null!==wa){var ra=wa.h(),wc=wa.j();if(ra instanceof bs){var ac=ra.ae;if(!0===ra.ke)var Id=\nO().c,ud=null===Id?null===hb:Id.i(hb);else ud=!1;if(ud){Ps(a,new Ne(778),new Oe(\"res\"));var be=new vl(ac);t();B=au(a,Cq(be,new L(wc)),b,!1,e,g,new Ne(779));break a}}}}}}}if(n){var re=r.z;if(null!==re){var pe=re.h(),bd=re.j();if(pe instanceof cs){var Rc=pe.Cc,Wc=pe.td;if(Ik()===Rc||Kk()===Rc||Jk()===Rc){Ps(a,new Ne(781),new Oe(\"res\"));t();var Wd=new L(pe.Mf),zd=pe.jb(),Pa=vt(new Ft(a,Wc,Wd,zd),new y(Ee=>Jt(Ee,g,e))),Db=G(new H,Rc,Pa);b:{var Oc=Db.y;if(Jk()===Oc)var Tc=new Fl(!0,new yl(Qt(Pa,new y(Ee=>\n{if(null!==Ee){var Ca=new L(Ee);if(!Ca.b()){var Lc=Ca.k.h();Ca=Ca.k.j();if(Lc instanceof L)return G(new H,Lc.k,Ca)}}if(null!==Ee&&(Ca=new L(Ee),!Ca.b()&&(Lc=Ca.k.h(),Ca=Ca.k.j(),t().d===Lc&&null!==Ca&&(Lc=Ca.ya,Lc instanceof vl))))return G(new H,Lc,Ca);if(null!==Ee&&(Lc=new L(Ee),!Lc.b()&&(Ca=Lc.k.h(),Lc=Lc.k.j(),t().d===Ca)))return Ee=Ye(new Te(new Ue(J(new K,[\"Record field should have a name\"]))),u()),Ca=Lc.ya.A(),Ee=G(new H,Ee,Ca),Ca=O().c,Ze(a,new z(Ee,Ca)),Ee=new vl(\"\\x3cerror\\x3e\"),G(new H,\nEe,Lc);throw new w(Ee);}))));else{var Sd=Db.y,Jc=Db.w;if(Ik()===Sd&&Jc instanceof z){var vd=Jc.z,hd=Jc.p;if(null!==vd){var de=vd.h(),ye=vd.j();if(t().d===de&&null!==ye){var jf=ye.yb,af=ye.ya;if(null!==jf){var pf=jf.ch;if(!1===jf.je)if(!1===pf)var kf=O().c,Be=null===kf?null===hd:kf.i(hd);else Be=!1;else Be=!1;if(Be){Tc=new Fl(!1,af);break b}}}}}var Kd=Db.y;if(Ik()===Kd){var ld=!1,Jd=null,Dd=Os(a);if(Dd instanceof z){ld=!0;Jd=Dd;var Xd=Jd.z;if(null!==Xd){var Yc=Xd.h();if(Yc instanceof as&&\"\\x3d\\x3e\"===\nYc.Na){Ps(a,new Ne(798),new Oe(\"bra\"));var Ce=Us(a,bu(\"\\x3d\\x3e\").Sc(),g,new Ne(799));Tc=new Ol(new Gl(Pa),Ce);break b}}}if(ld){var te=Jd.z,Ie=Jd.p;if(null!==te){var Jf=te.h();if(Yr()===Jf&&Ie instanceof z){var df=Ie.z;if(null!==df){var vg=df.h();if(vg instanceof as&&\"\\x3d\\x3e\"===vg.Na){var wg=au(a,new Gl(Pa),0,!0,e,g,new Ne(802));if(wg instanceof fe){Tc=Ms(a,wg.aa.A());break b}else if(wg instanceof Ud){Tc=wg.fa;break b}else throw new w(wg);}}}}}if(ld){var xg=Jd.z;if(null!==xg){var eg=xg.h();if(eg instanceof\nbs){var vh=eg.ke;if(\"-\\x3e\"===eg.ae&&!0===vh){Ps(a,new Ne(807),new Oe(\"bra\"));var fg=Us(a,bu(\"-\\x3e\").Sc(),g,new Ne(808));Tc=new Ol(new Gl(Pa),fg);break b}}}}var ih=O().c;if(null===ih?null===Pa:ih.i(Pa))Tc=new Gm(!0);else{var Ig=Qt(Pa,new y(Ee=>{if(null!==Ee){var Ca=new L(Ee);if(!Ca.b()){var Lc=Ca.k.h();Ca=Ca.k.j();if(t().d===Lc&&null!==Ca){Lc=Ca.yb;Ca=Ca.ya;var yd=tm().Cg;if(null===yd?null===Lc:yd.i(Lc))return Ca}}}if(null!==Ee&&(Ca=new L(Ee),!Ca.b()&&(Lc=Ca.k.h(),Ca=Ca.k.j(),null!==Ca)))return Ee=\nCa.ya,Ca=Ye(new Te(new Ue(J(new K,[\"Illegal position for field specification\"]))),u()),cu(),Lc=Lc.ha(),Lc=du(0,Xq(Lc,Ee)),Lc=G(new H,Ca,Lc),Ca=O().c,Ze(a,new z(Lc,Ca)),Ee;throw new w(Ee);}));Tc=kba(Ig,new fn((Ee,Ca)=>{var Lc=new vl(\",\");cu();var yd=O().c;yd=du(0,new z(Ee,new z(Ca,yd)));Lc=Cq(Lc,yd);eu();return new Pl(Lc,fu(0,J(new K,[Ee,Ca])))}))}}else Tc=new Gl(Pa)}}t();B=au(a,Cq(Tc,new L(bd)),b,!1,e,g,new Ne(827));break a}}}}if(n){var Tf=r.z;if(null!==Tf){var Jg=Tf.h();if(Jg instanceof as&&\"forall\"===\nJg.Na){Ps(a,new Ne(829),new Oe(\"res\"));var jh=fba(a),yg=Me(a,new Ne(843),new Oe(\"rest\"));b:{if(yg instanceof z){var gg=yg.z;if(null!==gg){var Cf=gg.h();if(Cf instanceof as&&\":\"===Cf.Na){Ps(a,new Ne(845),new Oe(\"rest\"));var Uf=Us(a,0,g,new Ne(846));break b}}}var $g=Ye(new Te(new Ue(J(new K,[\"Expected `:` after `forall` section\"]))),u()),Ah=Js(a),Kg=new U(()=>Hs(a)),Vf=Ah.b()?Es(Kg):Ah,hg=G(new H,$g,Vf),zg=O().c;Ze(a,new z(hg,zg));Uf=Ls(a)}t();var Lg=new Zl(jh,Uf);B=new Ud(Lg);break a}}}if(n){var Mg=\nr.z;if(null!==Mg){var Wf=Mg.h(),Ng=Mg.j();if(Wf instanceof as&&\"while\"===Wf.Na){Ps(a,new Ne(853),new Oe(\"res\"));var Kf=Us(a,0,g,new Ne(854)),xf=zt(a,new as(\"do\"),Bt(),!1,new U(()=>O().c),g);if(null===xf)throw new w(xf);var Og=Us(a,0,g,new Ne(856)),mi=new dm(Kf,Og);t();var Ci=Kt(Ng,Og.A());B=au(a,Cq(mi,new L(Ci)),b,!1,e,g,new Ne(857));break a}}}if(n){var Xh=r.z;if(null!==Xh){var wh=Xh.h(),Bh=Xh.j();if(wh instanceof as&&\"set\"===wh.Na){Ps(a,new Ne(859),new Oe(\"res\"));var ng=Us(a,0,g,new Ne(860)),kh=\nzt(a,new as(\"\\x3d\"),Bt(),!1,new U(()=>O().c),g);if(null!==kh)var Kh=kh.Rc();else throw new w(kh);var ni=tt(Vs(),g)||!Kh,Lh=Us(a,0,ni,new Ne(862)),lh=new Wl(ng,Lh);t();var Ch=Kt(Bh,Lh.A());B=au(a,Cq(lh,new L(Ch)),b,!1,e,g,new Ne(863));break a}}}if(n){var Dh=r.z;if(null!==Dh){var Yh=Dh.h();if(Yh instanceof as&&\"let\"===Yh.Na){Ps(a,new Ne(865),new Oe(\"res\"));B=Ns(a,!1,e,g,new Ne(866));break a}}}if(n){var ah=r.z;if(null!==ah){var oi=ah.h(),mj=ah.j();if(oi instanceof as&&\"new\"===oi.Na){Ps(a,new Ne(868),\nnew Oe(\"res\"));var wd=Us(a,Vs().ao.n(hc(46))|0,g,new Ne(869)),ge=new Yl(wd);t();var De=Kt(mj,wd.A());B=au(a,Cq(ge,new L(De)),b,!1,e,g,new Ne(870));break a}}}if(n){var qf=r.z;if(null!==qf){var og=qf.h(),Xf=qf.j();if(og instanceof as&&\"else\"===og.Na){Ps(a,new Ne(872),new Oe(\"res\"));var mh=Os(a);if(mh instanceof z){var Ag=mh.z;if(null!==Ag){var Bg=Ag.h();qs()===Bg&&(Ps(a,new Ne(875),new Oe(\"res\")),no())}}var Eh=Us(a,0,g,new Ne(878));t();var Pg=new gu(Eh);t();var Di=Kt(Xf,Eh.A()),Mh=Cq(Pg,new L(Di));\nB=new fe(Mh);break a}}}if(n){var pi=r.z;if(null!==pi){var Xi=pi.h(),Qg=pi.j();if(Xi instanceof as&&\"case\"===Xi.Na){Ps(a,new Ne(882),new Oe(\"res\"));var nh=O().c,bh=Qs(a,0,!0,nh,!0,g,new Ne(883));if(bh instanceof fe){var Mj=bh.aa;t();eu();var Nj=[new vl(\"case$scrut\")],ie=new Ol(fu(0,J(new K,Nj)),new Xl(new Tt(new vl(\"case$scrut\"),new vl(\"is\"),Mj),t().d));B=new Ud(ie);break a}else if(bh instanceof Ud){var Ac=bh.fa,Ve=new Te(new Ue(J(new K,[\"Expected 'then'/'else' clause after 'case'; found \",\" instead\"]))),\nTd=[We(Xe(),hu(Ac))],lf=Ye(Ve,J(new K,Td)),Yi=Ac.A(),Jl=G(new H,lf,Yi),ll=Ye(new Te(new Ue(J(new K,[\"Note: 'case' expression starts here:\"]))),u());t();var Bj=G(new H,ll,new L(Qg)),$k=O().c;Ze(a,new z(Jl,new z(Bj,$k)));t();eu();var Zh=[new vl(\"case$scrut\")],Ei=new Ol(fu(0,J(new K,Zh)),new Xl(new gu(Ac),t().d));B=new Ud(Ei);break a}else throw new w(bh);}}}if(n){var Yd=r.z;if(null!==Yd){var bf=Yd.h(),rf=Yd.j();if(bf instanceof as&&\"if\"===bf.Na){Ps(a,new Ne(893),new Oe(\"res\"));var Cg=O().c,nj=Qs(a,0,\n!0,Cg,!0,g,new Ne(894));if(nj instanceof fe){var Jh=nj.aa,If=!1,Hg=null,He=Os(a);b:{if(He instanceof z){If=!0;Hg=He;var lj=Hg.z;if(null!==lj){var Wi=lj.h();if(Wi instanceof as&&\"else\"===Wi.Na){Ps(a,new Ne(898),new Oe(\"els\"));t();var Oj=Zt(a,e,g,new Ne(899));var mo=new L(Oj);break b}}}if(If){var mm=Hg.z,nm=Hg.p;if(null!==mm){var dq=mm.h();if(qs()===dq&&nm instanceof z){var Zd=nm.z;if(null!==Zd){var sf=Zd.h();if(sf instanceof as&&\"else\"===sf.Na){Ps(a,new Ne(901),new Oe(\"els\"));Ps(a,new Ne(902),new Oe(\"els\"));\nt();var oj=Us(a,0,g,new Ne(903));mo=new L(oj);break b}}}}}if(If){var al=Hg.z;if(null!==al){var Ll=al.h();if(Ll instanceof cs){var Qm=Ll.Cc,Rm=Ll.td;if(Mk()===Qm&&Rm instanceof z){var hq=Rm.z,Bn=Rm.p;if(null!==hq){var hp=hq.h();if(hp instanceof as&&\"else\"===hp.Na){Ps(a,new Ne(905),new Oe(\"els\"));t();var ru=new L(Ll.Mf),qr=Ll.jb(),Xs=new Ft(a,Bn,ru,qr);t();var rr=vt(Xs,new y(Ee=>Us(Ee,0,g,new Ne(907))));mo=new L(rr);break b}}}}}}mo=t().d}t();var iq=new Xl(Jh,mo);B=new Ud(iq);break a}else if(nj instanceof\nUd){var qo=nj.fa,qm=Os(a);if(qm instanceof z){var jq=qm.z;if(null!==jq){var pl=jq.h();if(pl instanceof cs){var ro=pl.Cc,Cn=pl.td;if(Mk()===ro&&Cn instanceof z){var ip=Cn.z,so=Cn.p;if(null!==ip){var Dn=ip.h();if(Dn instanceof as&&\"then\"===Dn.Na){Ps(a,new Ne(914),new Oe(\"res\"));t();var sr=new L(pl.Mf),kq=pl.jb(),ql=new Ft(a,so,sr,kq),Ys=Us(ql,0,g,new Ne(916)),Sm=!1,Nl=null,jp=Os(ql);b:{if(jp instanceof z){Sm=!0;Nl=jp;var lq=Nl.z;if(null!==lq){var mq=lq.h();if(mq instanceof as&&\"else\"===mq.Na){Ps(ql,\nnew Ne(919),new Oe(\"els\"));t();var Tm=vt(ql,new y(Ee=>Us(Ee,0,g,new Ne(920))));var En=new L(Tm);break b}}}if(Sm){var to=Nl.z,Fn=Nl.p;if(null!==to){var nq=to.h();if(qs()===nq&&Fn instanceof z){var Um=Fn.z;if(null!==Um){var kp=Um.h();if(kp instanceof as&&\"else\"===kp.Na){Ps(ql,new Ne(922),new Oe(\"els\"));Ps(ql,new Ne(923),new Oe(\"els\"));t();var oq=vt(ql,new y(Ee=>Us(Ee,0,g,new Ne(925))));En=new L(oq);break b}}}}}vt(ql,new y(()=>{}));En=t().d}t();var su=new Xl(new Ut(qo,Ys),En);B=new Ud(su);break a}}}}}}b:{if(qm instanceof\nz){var Gn=qm.z;if(null!==Gn){var ur=Gn.h(),In=Gn.j(),Zs=new Te(new Ue(J(new K,[\"\",\" followed by \",\"\"]))),$s=[We(Xe(),hu(qo)),We(Xe(),ur.jb())],pq=Ye(Zs,J(new K,$s));t();var vr=iu(ju(),qo.A()).mf(In,new fn((Ee,Ca)=>xs(Ee,Ca)));var Vm=G(new H,pq,new L(vr));break b}}var Jn=O().c;if(null===Jn?null===qm:Jn.i(qm)){var wr=new Te(new Ue(J(new K,[\"\",\"\"]))),at=[We(Xe(),hu(qo))];Vm=G(new H,Ye(wr,J(new K,at)),qo.A())}else throw new w(qm);}if(null!==Vm)var xr=G(new H,Vm.h(),Vm.j());else throw new w(Vm);var lp=\nxr.j(),Kn=Ye(new Te(new Ue(J(new K,[\"Expected 'then'/'else' clause after 'if'; found \",\" instead\"]))),J(new K,[xr.h()])),qq=G(new H,Kn,lp),yr=Ye(new Te(new Ue(J(new K,[\"Note: 'if' expression starts here:\"]))),u());t();var rq=G(new H,yr,new L(rf)),sq=O().c;Ze(a,new z(qq,new z(rq,sq)));t();var bt=new Xl(new Ut(qo,Ls(a)),t().d);B=new Ud(bt);break a}else throw new w(nj);}}}var tq=O().c;if(null===tq?null===v:tq.i(v)){var zr=new Te(new Ue(J(new K,[\"Unexpected end of \",\"; an expression was expected here\"]))),\nct=[We(Xe(),a.jE)],Ar=Ye(zr,J(new K,ct)),uq=Hs(a),Br=G(new H,Ar,uq),Ln=O().c;Ze(a,new z(Br,Ln));t();var vq=Ls(a);B=new Ud(vq)}else{if(n){var Cr=r.z;if(null!==Cr){var tu=Cr.h(),uu=Cr.j();if(ds()===tu){t();var dt=new Gm(!0);t();var vu=Cq(dt,new L(uu));B=new Ud(vu);break a}}}if(n){var Dr=r.z;if(null!==Dr){var uo=Dr.h(),Er=Dr.j();if(uo instanceof bs){var et=uo.ke;if(\"-\"===uo.ae&&!0===et){Ps(a,new Ne(951),new Oe(\"res\"));var ft=new vl(\"-\");t();var gt=Cq(ft,new L(Er)),Wm=Us(a,bu(\"-\").Sc(),g,new Ne(953));\nif(Wm instanceof Em){B=au(a,new Em(lba(Wm.rq)),b,!1,e,g,new Ne(955));break a}else if(null!==Wm){if(a.hx){eu();var Fr=[new Em(br()),Wm],mp=new Pl(gt,fu(0,J(new K,Fr)))}else{eu();var wu=[new Em(br())],ht=new Pl(gt,fu(0,J(new K,wu)));eu();mp=new Pl(ht,fu(0,J(new K,[Wm])))}B=au(a,mp,b,!1,e,g,new Ne(957));break a}else throw new w(Wm);}}}}if(n){var wq=r.z;if(null!==wq){var xq=wq.h(),Gr=wq.j(),xu=new Te(new Ue(J(new K,[\"Unexpected \",\" in expression position\"]))),yu=[We(Xe(),xq.jb())],Re=Ye(xu,J(new K,yu));\nt();var rj=G(new H,Re,new L(Gr)),ai=O().c;Ze(a,new z(rj,ai));Ps(a,new Ne(964),new Oe(\"res\"));var rm=O().c;B=Qs(a,b,!0,rm,e,!0,new Ne(965));break a}}throw new w(v);}}if(m.b())return B;if(B instanceof fe){var Nn=B.aa;if(Nn instanceof Ut){var zu=Nn.Km,Au=Nn.Lm;O();var Av=new Ut(Ts(zu,m),Au);return new fe(Av)}var oy=Ye(new Te(new Ue(J(new K,[\"Unexpected annotation\"]))),u()),Bv=m.e().A(),Cv=G(new H,oy,Bv),py=O().c;Ze(a,new z(Cv,py));t();return new fe(Nn)}if(B instanceof Ud){var qy=B.fa;t();var Dv=Ts(qy,\nm);return new Ud(Dv)}throw new w(B);}),h,new Oe(\"exprOrIf\"))}catch(l){if(l instanceof Iq){h=l;if(h.Qg===k)return h.Cj();throw h;}throw l;}}\nfunction au(a,b,c,d,e,g,h){return Cs(a,new U(()=>new tl(c,\"`\"+b+\"`\",d)),new y(()=>{var k=!1,l=null,m=Me(a,new Ne(990),new Oe(\"exprCont\"));if(m instanceof z){k=!0;l=m;var n=l.z;if(null!==n){var r=n.h();if(Yr()===r){var v=!1,x=null,A=Me(a,new Ne(991),new Oe(\"exprCont\"));if(A instanceof z){v=!0;x=A;var B=x.p;if(B instanceof z){var C=B.z;if(null!==C){var D=C.h();if(D instanceof as&&\"\\x3d\\x3e\"===D.Na&&bu(\"\\x3d\\x3e\").ut()>c){Ps(a,new Ne(993),new Oe(\"exprCont\"));Ps(a,new Ne(994),new Oe(\"exprCont\"));var F=\nb instanceof Gl?b:fu(eu(),J(new K,[b]));return au(a,new em(new Ol(F,new fm(Us(a,1,g,new Ne(998))))),c,d,e,g,new Ne(995))}}}}if(v){var I=x.p;if(I instanceof z){var M=I.z;if(null!==M){var N=M.h(),P=M.j();if(N instanceof cs){var T=N.Cc,Y=N.td;if(Ik()===T){Ps(a,new Ne(1E3),new Oe(\"exprCont\"));Ps(a,new Ne(1001),new Oe(\"exprCont\"));t();var Z=new L(N.Mf),S=N.jb(),ea=Qt(vt(new Ft(a,Y,Z,S),new y(ie=>Jt(ie,g,e))),new y(ie=>{if(null!==ie){var Ac=new L(ie);if(!Ac.b()){var Ve=Ac.k.h();Ac=Ac.k.j();if(null!==Ac)return ie=\nnew sm(Ac.yb,new fm(Ac.ya)),G(new H,Ve,ie)}}throw new w(ie);})),ia=new fm(b),X=new Gl(ea);t();var sa=new Pl(ia,Cq(X,new L(P)));return au(a,new em(sa),c,d,e,g,new Ne(1006))}}}}}if(v){var Ja=x.p;if(Ja instanceof z){var Xa=Ja.z;if(null!==Xa){var Fa=Xa.h(),za=Xa.j();if(Fa instanceof bs){var Qa=Fa.ae;if(!0===Fa.ke){if(bu(Qa).ut()>c){Ps(a,new Ne(1009),new Oe(\"exprCont\"));Ps(a,new Ne(1010),new Oe(\"exprCont\"));var Ma=new vl(Qa);t();var Ga=Cq(Ma,new L(za)),ab=Os(a);if(ab instanceof z){var Hb=ab.z;if(null!==\nHb){var bc=Hb.h();qs()===bc&&Ps(a,new Ne(1013),new Oe(\"exprCont\"))}}var yb=Qs(a,bu(Qa).Sc(),!0,O().c,e,g,new Ne(1016));if(yb instanceof fe){t();var tb=Ms(a,(t(),new L(za)));return new Ud(tb)}if(yb instanceof Ud){var eb=yb.fa;if(\"with\"===Qa)var kb=Ms(a,(t(),new L(za)));else{eu();var Rb=[new fm(b),new fm(eb)];kb=new em(new Pl(Ga,fu(0,J(new K,Rb))))}return au(a,kb,c,d,e,g,new Ne(1018))}throw new w(yb);}t();return new Ud(b)}}}}}if(v){var Gb=x.p;if(Gb instanceof z){var vb=Gb.z;if(null!==vb){var Tb=vb.h();\nif(Tb instanceof as&&\"in\"===Tb.Na)return t(),new Ud(b)}}}Ps(a,new Ne(1028),new Oe(\"exprCont\"));Ms(a,b.A());t();return new Ud(b)}}}if(k){var Nb=l.z;if(null!==Nb){var ic=Nb.h(),Va=Nb.j();if(Xr()===ic&&Pe(new E(c),0)){Ps(a,new Ne(1033),new Oe(\"exprCont\"));var cb=Os(a);if(cb instanceof z){var zb=cb.z;if(null!==zb){var Ub=zb.h();qs()===Ub&&Ps(a,new Ne(1035),new Oe(\"exprCont\"))}}var jb=Us(a,c,g,new Ne(1038));t();var db=new vl(\",\");t();var ub=Cq(db,new L(Va));eu();var Aa=new Pl(ub,fu(0,J(new K,[b,jb])));\nreturn new Ud(Aa)}}}if(k){var va=l.z,Ra=l.p;if(null!==va){var rb=va.h();if(rb instanceof as&&\"\\x3d\\x3e\"===rb.Na&&Ra instanceof z){var xb=Ra.z;if(null!==xb){var mc=xb.h();if(qs()===mc&&bu(\"\\x3d\\x3e\").ut()>c){Ps(a,new Ne(1041),new Oe(\"exprCont\"));var Ha=new Sl(ef(Le(a)));t();eu();var Ka=new Ol(fu(0,J(new K,[b])),Ha);return new Ud(Ka)}}}}}if(k){var Oa=l.z;if(null!==Oa){var Na=Oa.h();if(Na instanceof as&&\"\\x3d\\x3e\"===Na.Na&&bu(\"\\x3d\\x3e\").ut()>c){Ps(a,new Ne(1045),new Oe(\"exprCont\"));var Da=Us(a,1,g,\nnew Ne(1046));eu();var ta=new Ol(fu(0,J(new K,[b])),Da);return au(a,ta,c,d,e,g,new Ne(1048))}}}if(k){var Ya=l.z,dc=l.p;if(null!==Ya){var ka=Ya.h(),ya=Ya.j();if(ka instanceof bs&&\".\"===ka.ae&&dc instanceof z){var Sa=dc.z;if(null!==Sa){var xc=Sa.h(),Sb=Sa.j();if(xc instanceof cs){var uc=xc.Cc,Lb=xc.td;if(Kk()===uc){Ps(a,new Ne(1050),new Oe(\"exprCont\"));Ps(a,new Ne(1051),new Oe(\"exprCont\"));t();var lc=new L(xc.Mf),Xb=xc.jb(),ec=vt(new Ft(a,Lb,lc,Xb),new y(ie=>Us(ie,0,g,new Ne(1053)))),Ab=new Vl(b,ec);\nt();var Ob=Kt(xs(ya,Sb),ec.A()),fb=Cq(Ab,new L(Ob));return au(a,fb,c,d,e,g,new Ne(1055))}}}}}}if(k){var Wa=l.z;if(null!==Wa){var bb=Wa.h(),Ia=Wa.j();if(bb instanceof bs){var Ua=bb.ae;if(!0===bb.ke&&bu(Ua).ut()>c){Ps(a,new Ne(1057),new Oe(\"exprCont\"));var pc=new vl(Ua);t();var sc=Cq(pc,new L(Ia)),Ba=Os(a);if(Ba instanceof z){var ob=Ba.z;if(null!==ob){var nc=ob.h();qs()===nc&&Ps(a,new Ne(1060),new Oe(\"exprCont\"))}}var Ib=Qs(a,bu(Ua).Sc(),!0,O().c,e,g,new Ne(1063));if(Ib instanceof fe){var vc=Ib.aa;\nt();var Vb=new Tt(b,sc,vc);return new fe(Vb)}if(Ib instanceof Ud){var fc=Ib.fa;if(\"with\"===Ua)a:if(fc instanceof yl)var Bc=new Tl(b,fc);else{if(fc instanceof Fl){var Pb=fc.gg;if(!0===fc.bi&&Pb instanceof yl){Bc=new Tl(b,Pb);break a}}var Jb=new Te(new Ue(J(new K,[\"record literal expected here; found \",\"\"]))),gc=[We(Xe(),hu(fc))],Cb=Ye(Jb,J(new K,gc)),cc=fc.A(),yc=G(new H,Cb,cc),Mc=O().c;Ze(a,new z(yc,Mc));Bc=b}else if(a.hx)eu(),Bc=new Pl(sc,fu(0,J(new K,[b,fc])));else{eu();var qc=new Pl(sc,fu(0,J(new K,\n[b])));eu();Bc=new Pl(qc,fu(0,J(new K,[fc])))}return au(a,Bc,c,d,e,g,new Ne(1067))}throw new w(Ib);}}}}if(k){var oc=l.z;if(null!==oc){var Qc=oc.h();if(Qc instanceof as&&\":\"===Qc.Na&&c<=(Vs().ao.n(hc(58))|0)){Ps(a,new Ne(1084),new Oe(\"exprCont\"));t();var jc=new Cl(b,Ht(a,g,new Ne(1085)));return new Ud(jc)}}}if(k){var sb=l.z;if(null!==sb){var Gc=sb.h(),Wb=sb.j();if(Gc instanceof as&&\"where\"===Gc.Na&&1>=c){Ps(a,new Ne(1087),new Oe(\"exprCont\"));var Cc=Et(a),Fc=new $l(b,ef(Cc));t();var qd=Cq(Fc,new L(Wb));\nreturn au(a,qd,c,!1,e,g,new Ne(1090))}}}if(k){var Yb=l.z;if(null!==Yb){var Nc=Yb.h();if(Se()===Nc)return Ps(a,new Ne(1092),new Oe(\"exprCont\")),au(a,b,c,d,e,g,new Ne(1093))}}if(k){var ad=l.z;if(null!==ad){var Uc=ad.h(),cd=ad.j();if(Uc instanceof ss){var kc=Uc.ux;Ps(a,new Ne(1095),new Oe(\"exprCont\"));var Vc=new vl(kc);t();return au(a,new Ql(b,Cq(Vc,new L(cd))),c,d,e,g,new Ne(1096))}}}if(k){var Hc=l.z;if(null!==Hc){var rc=Hc.h();if(rc instanceof cs){var sd=rc.Cc,Kc=rc.td;if(Mk()===sd&&Kc instanceof z){var Qd=\nKc.z,Ad=Kc.p;if(null!==Qd){var kd=Qd.h(),Hd=Qd.j();if(kd instanceof ss){var Rd=kd.ux;if(1>=c){Ps(a,new Ne(1099),new Oe(\"exprCont\"));t();var Bd=new L(rc.Mf),ae=rc.jb(),dd=vt(new Ft(a,Ad,Bd,ae),new y(ie=>{var Ac=new vl(Rd);t();return au(ie,new Ql(b,Cq(Ac,new L(Hd))),0,!0,e,g,new Ne(1100))}));if(d){if(dd instanceof fe){var od=dd.aa;t();return new fe(od)}if(dd instanceof Ud)return au(a,dd.fa,0,d,e,g,new Ne(1103));throw new w(dd);}return dd}}}}}}}if(k){var Ta=l.z;if(null!==Ta){var wb=Ta.h();if(wb instanceof\ncs){var $a=wb.Cc,wa=wb.td;if(Mk()===$a&&wa instanceof z){var hb=wa.z,ra=wa.p;if(null!==hb){var wc=hb.h(),ac=hb.j();if(wc instanceof bs){var Id=wc.ae;if(!0===wc.ke){Ps(a,new Ne(1107),new Oe(\"exprCont\"));t();var ud=new L(wb.Mf),be=wb.jb();return vt(new Ft(a,ra,ud,be),new y(ie=>ku(ie,b,Id,ac,e,g,new Ne(1108))))}}}}}}}if(k){var re=l.z;if(null!==re){var pe=re.h();if(pe instanceof as&&\"then\"===pe.Na&&Pe(new E(c),0)){Ps(a,new Ne(1111),new Oe(\"exprCont\"));t();var bd=new Ut(b,Zt(a,e,g,new Ne(1112)));return new fe(bd)}}}if(k){var Rc=\nl.z,Wc=l.p;if(null!==Rc){var Wd=Rc.h();if(qs()===Wd&&Wc instanceof z){var zd=Wc.z;if(null!==zd){var Pa=zd.h();if(Pa instanceof as&&\"then\"===Pa.Na&&Pe(new E(c),0)){Ps(a,new Ne(1114),new Oe(\"exprCont\"));Ps(a,new Ne(1115),new Oe(\"exprCont\"));t();var Db=new Ut(b,Zt(a,e,g,new Ne(1116)));return new fe(Db)}}}}}if(k){var Oc=l.z;if(null!==Oc){var Tc=Oc.h();if(qs()===Tc&&d)return Ps(a,new Ne(1118),new Oe(\"exprCont\")),au(a,b,0,d,e,g,new Ne(1119))}}if(k){var Sd=l.z;if(null!==Sd){var Jc=Sd.h(),vd=Sd.j();if(Jc instanceof\ncs){var hd=Jc.Cc,de=Jc.td;if(Jk()===hd&&c<=Vs().MH){Ps(a,new Ne(1122),new Oe(\"exprCont\"));t();var ye=new L(Jc.Mf),jf=Jc.jb(),af=vt(new Ft(a,de,ye,jf),new y(ie=>Et(ie)));t();var pf=Cq(af,new L(vd));return au(a,new cm(b,pf),c,d,e,g,new Ne(1124))}}}}if(k){var kf=l.z;if(null!==kf){var Be=kf.h();a:if(Xr()===Be)var Kd=!0;else if(ds()===Be)Kd=!0;else if(qs()===Be)Kd=!0;else{if(Be instanceof as){var ld=Be.Na;if(\"then\"===ld||\"else\"===ld||\"in\"===ld||\"\\x3d\"===ld||\"do\"===ld){Kd=!0;break a}}if(Be instanceof bs&&\n!0===Be.ke)Kd=!0;else{if(Be instanceof cs){var Jd=Be.Cc;if(Jk()===Jd){Kd=!0;break a}}Kd=!1}}if(Kd)return t(),new Ud(b)}}if(k){var Dd=l.z;if(null!==Dd){var Xd=Dd.h();if(Xd instanceof as&&\"of\"===Xd.Na&&1>=c){Ps(a,new Ne(1130),new Oe(\"exprCont\"));var Yc=Jt(a,g,e),Ce=new Pl(b,new Gl(Yc));return au(a,Ce,c,d,e,g,new Ne(1133))}}}if(k){var te=l.z;if(null!==te){var Ie=te.h();if(Ie instanceof cs){var Jf=Ie.Cc,df=Ie.td;if(Mk()===Jf&&df instanceof z){var vg=df.z,wg=df.p;if(null!==vg){var xg=vg.h();if(xg instanceof\nas&&\"of\"===xg.Na&&1>=c){Ps(a,new Ne(1135),new Oe(\"exprCont\"));t();var eg=new L(Ie.Mf),vh=Ie.jb(),fg=vt(new Ft(a,wg,eg,vh),new y(ie=>{var Ac=Jt(ie,g,e);return au(ie,new Pl(b,new Gl(Ac)),0,!0,e,g,new Ne(1143))}));if(fg instanceof fe){var ih=fg.aa;t();return new fe(ih)}if(fg instanceof Ud)return au(a,fg.fa,0,d,e,g,new Ne(1148));throw new w(fg);}}}}}}if(k){var Ig=l.z;if(null!==Ig){var Tf=Ig.h();if(Tf instanceof cs){var Jg=Tf.Cc,jh=Tf.td;if(Mk()===Jg&&jh instanceof z){var yg=jh.z;if(null!==yg){var gg=\nyg.h();if(gg instanceof as){var Cf=gg.Na;if(\"then\"===Cf||\"else\"===Cf)return t(),new Ud(b)}}}}}}if(k){var Uf=l.z;if(null!==Uf){var $g=Uf.h();if($g instanceof cs){var Ah=$g.Cc,Kg=$g.td;if(Mk()===Ah&&Kg instanceof z){var Vf=Kg.z;if(null!==Vf){var hg=Vf.h();if(hg instanceof cs){var zg=hg.Cc;if((Ik()===zg||Kk()===zg)&&1>=c){Ps(a,new Ne(1164),new Oe(\"exprCont\"));t();var Lg=new L($g.Mf),Mg=$g.jb(),Wf=vt(new Ft(a,Kg,Lg,Mg),new y(ie=>au(ie,b,0,!0,e,g,new Ne(1165))));if(Wf instanceof fe){var Ng=Wf.aa;t();return new fe(Ng)}if(Wf instanceof\nUd)return au(a,Wf.fa,0,d,e,g,new Ne(1168));throw new w(Wf);}}}}}}}if(k){var Kf=l.z;if(null!==Kf){var xf=Kf.h(),Og=Kf.j();if(xf instanceof cs){var mi=xf.Cc,Ci=xf.td;if(Lk()===mi||Kk()===mi){Ps(a,new Ne(1172),new Oe(\"exprCont\"));t();var Xh=new L(xf.Mf),wh=xf.jb(),Bh=vt(new Ft(a,Ci,Xh,wh),new y(ie=>Jt(ie,g,e))),ng=new Il(b,Qt(Bh,new y(ie=>{if(null!==ie){var Ac=ie.h();ie=ie.j();if(t().d===Ac&&null!==ie&&(Ac=ie.yb,ie=ie.ya,null!==Ac)){var Ve=Ac.ch;if(!1===Ac.je&&!1===Ve){Ac=Qn(ie);if(Ac instanceof fe){var Td=\nAc.aa;st(a,new U(()=>Td),g);return gl()}if(Ac instanceof Ud)return Ac.fa;throw new w(Ac);}}}no()}))),kh=b.A(),Kh=new U(()=>it().n(Og)),ni=new y(ie=>{ie=xs(ie,Og);return it().n(ie)}),Lh=kh.b()?Es(Kh):ni.n(kh.o()),lh=Cq(ng,Lh);return au(a,lh,c,d,e,g,new Ne(1182))}}}}if(k){var Ch=l.z;if(null!==Ch){var Dh=Ch.h(),Yh=Ch.j();if(Dh instanceof cs){var ah=Dh.Cc,oi=Dh.td;if(Ik()===ah&&c<=Vs().MH){Ps(a,new Ne(1191),new Oe(\"exprCont\"));t();var mj=new L(Dh.Mf),wd=Dh.jb(),ge=vt(new Ft(a,oi,mj,wd),new y(ie=>Jt(ie,\ng,e))),De=new Gl(ge);t();var qf=new Pl(b,Cq(De,new L(Yh)));return au(a,qf,c,d,e,g,new Ne(1194))}}}}if(k){var og=l.z;if(null!==og){var Xf=og.h();if(Xf instanceof as&&\"of\"===Xf.Na){Ps(a,new Ne(1197),new Oe(\"exprCont\"));var mh=Jt(a,g,e),Ag=new Pl(b,new Gl(mh));return au(a,Ag,c,d,e,g,new Ne(1201))}}}if(k){var Bg=l.z.h();a:{if(Bg instanceof as){var Eh=Bg.Na;if(\":\"===Eh||\"of\"===Eh||\"where\"===Eh||\"extends\"===Eh){var Pg=!0;break a}}if(ds()===Bg)Pg=!0;else{if(Bg instanceof cs){var Di=Bg.Cc;if(Ik()===Di||Kk()===\nDi){Pg=!0;break a}}if(Bg instanceof cs){var Mh=Bg.Cc,pi=Bg.td;if(Mk()===Mh&&pi instanceof z){var Xi=pi.z;if(null!==Xi){var Qg=Xi.h();b:if(Qg instanceof as&&\"of\"===Qg.Na)var nh=!0;else if(ds()===Qg)nh=!0;else{if(Qg instanceof cs){var bh=Qg.Cc;if(Ik()===bh||Kk()===bh){nh=!0;break b}}nh=Qg instanceof ss?!0:!1}if(nh){Pg=!0;break a}}}}Pg=!1}}if(!Pg){var Mj=Jt(a,g,e),Nj=new Pl(b,new Gl(Mj));st(a,new U(()=>{fr();var ie=Ye(new Te(new Ue(J(new K,[\"Paren-less applications should use the 'of' keyword\"]))),u()),\nAc=Nj.A();ie=G(new H,ie,Ac);Ac=O().c;return hr(0,new z(ie,Ac),!0,lu())}),g);return au(a,Nj,c,d,e,g,new Ne(1217))}}t();return new Ud(b)}),h,new Oe(\"exprCont\"))}\nfunction ku(a,b,c,d,e,g,h){var k=new U(()=>G(new H,\"`\"+b+\"`\",c)),l=new Oe(\"opBlock\");Ds(a,new U(()=>{var Ma=l.fn,Ga=Es(k);Ga=Fs(Ga)?ze(Ga,\"(\",\",\",\")\"):Gs(Ga)?Es(k):\"(\"+Es(k)+\")\";return\"@ \"+Ma+Ga+\"    [at l.\"+h.Zl+\"]\"}));try{a.le=1+a.le|0;var m=new vl(c);t();var n=Cq(m,new L(d)),r=Qs(a,0,!0,O().c,e,g,new Ne(1225));if(r instanceof Ud){var v=r.fa;eu();var x=new Pl(n,fu(0,J(new K,[b,v]))),A=Me(a,new Ne(1230),new Oe(\"opBlock\"));a:{if(A instanceof z){var B=A.z,C=A.p;if(null!==B){var D=B.h();if(qs()===D){Ps(a,\nnew Ne(1232),new Oe(\"opBlock\"));d=!1;m=null;if(C instanceof z){d=!0;m=C;var F=m.z;if(null!==F){var I=F.h(),M=F.j();if(I instanceof bs){var N=I.ae;if(!0===I.ke){Ps(a,new Ne(1235),new Oe(\"opBlock\"));var P=ku(a,x,N,M,e,g,new Ne(1236));break a}}}}if(d){var T=m.z;if(null!==T){var Y=T.h(),Z=T.j(),S=new Te(new Ue(J(new K,[\"Unexpected \",\" in operator block\"]))),ea=[We(Xe(),Y.jb())],ia=Ye(S,J(new K,ea));t();var X=G(new H,ia,new L(Z)),sa=O().c;Ze(a,new z(X,sa));Ps(a,new Ne(1239),new Oe(\"opBlock\"));t();P=new Ud(x);\nbreak a}}var Ja=O().c;if(null===Ja?null===C:Ja.i(C)){t();P=new Ud(x);break a}throw new w(C);}}}t();P=new Ud(x)}}else if(r instanceof fe){var Xa=r.aa;t();var Fa=G(new H,n,Xa),za=O().c,Qa=new mu(b,nu(a,new z(Fa,za),e,g));P=new fe(Qa)}else throw new w(r);}finally{a.le=-1+a.le|0}Ds(a,new U(()=>\"\\x3d \"+P));return P}\nfunction nu(a,b,c,d){var e=new U(()=>b),g=new Ne(1251),h=new Oe(\"opIfBlock\");Ds(a,new U(()=>{var N=h.fn,P=Es(e);P=Fs(P)?ze(P,\"(\",\",\",\")\"):Gs(P)?Es(e):\"(\"+Es(e)+\")\";return\"@ \"+N+P+\"    [at l.\"+g.Zl+\"]\"}));try{a.le=1+a.le|0;var k=Me(a,new Ne(1252),new Oe(\"opIfBlock\"));a:{if(k instanceof z){var l=k.z,m=k.p;if(null!==l){var n=l.h();if(qs()===n){Ps(a,new Ne(1254),new Oe(\"opIfBlock\"));if(m instanceof z){var r=m.z;if(null!==r){var v=r.h(),x=r.j();if(v instanceof bs){var A=v.ae;if(!0===v.ke){Ps(a,new Ne(1257),\nnew Oe(\"opIfBlock\"));var B=Qs(a,0,!0,O().c,c,d,new Ne(1258));if(B instanceof Ud)no();else if(B instanceof fe){var C=B.aa,D=new vl(A);t();var F=Cq(D,new L(x)),I=G(new H,F,C);var M=nu(a,new z(I,b),c,d);break a}else throw new w(B);}}}}no()}}}M=Km(b)}}finally{a.le=-1+a.le|0}Ds(a,new U(()=>\"\\x3d \"+M));return M}\nfunction Nt(a,b,c){var d=!1,e=null,g=Os(a);a:{if(g instanceof z){d=!0;e=g;g=e.z;var h=e.p;if(null!==g){var k=g.h();g=g.j();if(k instanceof as&&\"in\"===k.Na&&h instanceof z&&(k=h.z,null!==k&&(h=k.h(),k=k.j(),h instanceof as&&\"out\"===h.Na))){Ps(a,new Ne(1284),new Oe(\"vinfo\"));t();d=G(new H,ou().Yl,xs(g,k));d=new L(d);break a}}}if(d&&(h=e.z,null!==h&&(g=h.h(),h=h.j(),g instanceof as&&\"in\"===g.Na))){Ps(a,new Ne(1287),new Oe(\"vinfo\"));t();d=G(new H,ou().AA,h);d=new L(d);break a}if(d&&(e=e.z,null!==e&&(d=\ne.h(),e=e.j(),d instanceof as&&\"out\"===d.Na))){Ps(a,new Ne(1290),new Oe(\"vinfo\"));t();d=G(new H,ou().Zu,e);d=new L(d);break a}d=t().d}e=Os(a);if(e instanceof z&&(g=e.z,null!==g&&(e=g.h(),g=g.j(),e instanceof bs&&(h=e.ae,!1===e.ke)))){Ps(a,new Ne(1296),new Oe(\"typeParams\"));e=new Ep(h);t();e=Cq(e,new L(g));g=Os(a);if(g instanceof z&&(g=g.z,null!==g&&(g=g.h(),Xr()===g)))return Ps(a,new Ne(1300),new Oe(\"typeParams\")),d.b()?d=R():(d=d.o(),d=new L(d.h())),d=G(new H,d,e),a=Nt(a,b,c),new z(d,a);d.b()?a=\nR():(a=d.o(),a=new L(a.h()));a=G(new H,a,e);b=O().c;return new z(a,b)}a:{if(d instanceof L&&(b=d.k,null!==b)){b=b.j();c=Ye(new Te(new Ue(J(new K,[\"dangling variance information\"]))),u());t();b=G(new H,c,new L(b));c=O().c;Ze(a,new z(b,c));break a}if(t().d!==d)throw new w(d);}return O().c}\nfunction iba(a,b){var c=Me(a,new Ne(1317),new Oe(\"maybeIndented\"));if(c instanceof z&&(c=c.z,null!==c)){var d=c.h();if(d instanceof cs){var e=d.Cc;c=d.td;if(Mk()===e)a:{if(e=c.Jg(),e instanceof L&&(e=e.k,null!==e&&(e=e.h(),e instanceof as&&(e=e.Na,\"then\"===e||\"else\"===e)))){e=!1;break a}e=!0}else e=!1;if(e){Ps(a,new Ne(1322),new Oe(\"maybeIndented\"));t();e=new L(d.Mf);d=d.jb();a=new Ft(a,c,e,d);var g=b.ba(a,!0);for(b=Me(a,new Ne(147),new Oe(\"concludeWith\"));;)if(b.b()?c=!1:(c=b.e(),Pe(new E(c.h()),\nSe())||Pe(new E(c.h()),qs())?(Ps(a,new Ne(147),new Oe(\"concludeWith\")),c=!0):c=!1),c)b=b.f();else break;d=b;a:{if(d instanceof z&&(c=d.z,null!==c)){b=c.h();for(c=c.j();;)if(d.b()?e=!1:(e=d.e().h(),e=Pe(new E(e),Se())),e)d=d.f();else break;d=d.Jg();b=d.b()?G(new H,b,c):d.o();if(null===b)throw new w(b);c=b.h();b=b.j();d=new Te(new Ue(J(new K,[\"Unexpected \",\" here\"])));c=[We(Xe(),c.jb())];c=Ye(d,J(new K,c));t();b=G(new H,c,new L(b));c=O().c;Ze(a,new z(b,c));break a}b=O().c;if(null===b?null!==d:!b.i(d))throw new w(d);\n}Ds(a,new U(()=>\"Concluded with \"+g));return g}}}return b.ba(a,!1)}\nfunction Jt(a,b,c){var d=Me(a,new Ne(1317),new Oe(\"maybeIndented\"));a:{if(d instanceof z&&(d=d.z,null!==d)){var e=d.h();if(e instanceof cs){var g=e.Cc;d=e.td;if(Mk()===g)b:{if(g=d.Jg(),g instanceof L&&(g=g.k,null!==g&&(g=g.h(),g instanceof as&&(g=g.Na,\"then\"===g||\"else\"===g)))){g=!1;break b}g=!0}else g=!1;if(g){Ps(a,new Ne(1322),new Oe(\"maybeIndented\"));t();g=new L(e.Mf);e=e.jb();a=new Ft(a,d,g,e);var h=Xt(a,!0,Vs().Du,b,c);for(b=Me(a,new Ne(147),new Oe(\"concludeWith\"));;)if(b.b()?c=!1:(c=b.e(),Pe(new E(c.h()),\nSe())||Pe(new E(c.h()),qs())?(Ps(a,new Ne(147),new Oe(\"concludeWith\")),c=!0):c=!1),c)b=b.f();else break;d=b;b:{if(d instanceof z&&(c=d.z,null!==c)){b=c.h();for(c=c.j();;)if(d.b()?e=!1:(e=d.e().h(),e=Pe(new E(e),Se())),e)d=d.f();else break;d=d.Jg();b=d.b()?G(new H,b,c):d.o();if(null===b)throw new w(b);c=b.h();b=b.j();d=new Te(new Ue(J(new K,[\"Unexpected \",\" here\"])));c=[We(Xe(),c.jb())];c=Ye(d,J(new K,c));t();b=G(new H,c,new L(b));c=O().c;Ze(a,new z(b,c));break b}b=O().c;if(null===b?null!==d:!b.i(d))throw new w(d);\n}Ds(a,new U(()=>\"Concluded with \"+h));a=h;break a}}}a=Xt(a,!1,Vs().Du,b,c)}return a}\nfunction Xt(a,b,c,d,e){b=pu(a,O().c,O().c,b,c,d,e);for(d=c=null;b!==u();){var g=b.e();a:{if(null!==g){e=g.h();var h=g.j();if(h instanceof fe){h=h.aa;g=Ye(new Te(new Ue(J(new K,[\"Unexpected 'then'/'else' clause\"]))),u());h=h.A();g=G(new H,g,h);h=O().c;Ze(a,new z(g,h));g=new sm(tm().Cg,Ls(a));e=G(new H,e,g);g=O().c;e=new z(e,g);break a}}if(null!==g&&(e=g.h(),h=g.j(),h instanceof Ud)){e=G(new H,e,h.fa);g=O().c;e=new z(e,g);break a}throw new w(g);}for(e=new Om(e);e.s();)g=new z(e.t(),u()),null===d?c=\ng:d.p=g,d=g;b=b.f()}return null===c?u():c}\nfunction pu(a,b,c,d,e,g,h){var k=new U(()=>G(new H,b,c)),l=new Ne(1360),m=new Oe(\"argsOrIf\");Ds(a,new U(()=>{var pc=m.fn,sc=Es(k);sc=Fs(sc)?ze(sc,\"(\",\",\",\")\"):Gs(sc)?Es(k):\"(\"+Es(k)+\")\";return\"@ \"+pc+sc+\"    [at l.\"+l.Zl+\"]\"}));try{a.le=1+a.le|0;var n=!1,r=null,v=Me(a,new Ne(1362),new Oe(\"argsOrIf\"));a:{var x=O().c;if(null===x?null===v:x.i(v))if(c instanceof z){var A=c.z,B=c.p,C=t().d;t();var D=new sm(tm().Cg,new Sl(Km(new z(A,B)))),F=G(new H,C,new Ud(D));var I=Km(new z(F,b));break a}else{var M=O().c;\nif(null===M?null===c:M.i(c)){I=Km(b);break a}else throw new w(c);}if(v instanceof z){n=!0;r=v;var N=r.z;if(null!==N){var P=N.h();if(Se()===P){Ps(a,new Ne(1371),new Oe(\"argsOrIf\"));I=pu(a,b,c,d,e,g,h);break a}}}if(n){var T=r.z;if(null!==T){var Y=T.h();if(qs()===Y){up(tp(),c.b());I=Km(b);break a}}}if(n){var Z=r.z;if(null!==Z){var S=Z.h();if(S instanceof bs){var ea=S.ae;if(!0===S.ke&&Nm(new E(ea),\"-\")){up(tp(),c.b());I=Km(b);break a}}}}var ia=Os(a);b:{if(ia instanceof z){var X=ia.z;if(null!==X){var sa=\nX.h(),Ja=X.j();if(sa instanceof as&&\"val\"===sa.Na){Ps(a,new Ne(1385),new Oe(\"argVal\"));t();var Xa=new L(Ja);break b}}}Xa=t().d}var Fa=Os(a);b:{if(Fa instanceof z){var za=Fa.z;if(null!==za){var Qa=za.h(),Ma=za.j();if(Qa instanceof as&&\"mut\"===Qa.Na){Ps(a,new Ne(1391),new Oe(\"argMut\"));t();var Ga=new L(Ma);break b}}}Ga=t().d}var ab=Os(a);b:{if(ab instanceof z){var Hb=ab.z;if(null!==Hb){var bc=Hb.h(),yb=Hb.j();if(bc instanceof as&&\"#\"===bc.Na){Ps(a,new Ne(1397),new Oe(\"argSpec\"));t();var tb=new L(yb);\nbreak b}}}tb=t().d}n=!1;r=null;var eb=Os(a);b:{if(eb instanceof z){n=!0;r=eb;var kb=r.z,Rb=r.p;if(null!==kb){var Gb=kb.h(),vb=kb.j();if(Gb instanceof bs){var Tb=Gb.ae;if(!1===Gb.ke&&Rb instanceof z){var Nb=Rb.z;if(null!==Nb){var ic=Nb.h();if(ic instanceof as&&\":\"===ic.Na){Ps(a,new Ne(1403),new Oe(\"argName\"));Ps(a,new Ne(1404),new Oe(\"argName\"));t();var Va=new vl(Tb);t();var cb=Cq(Va,new L(vb));var zb=new L(cb);break b}}}}}}if(n){var Ub=r.z,jb=r.p;if(null!==Ub){var db=Ub.h(),ub=Ub.j();if(db instanceof\nfs){var Aa=db.Cu;if(Aa instanceof Em){var va=Aa.rq;if(jb instanceof z){var Ra=jb.z;if(null!==Ra){var rb=Ra.h();if(rb instanceof as&&\":\"===rb.Na){Ps(a,new Ne(1407),new Oe(\"argName\"));Ps(a,new Ne(1408),new Oe(\"argName\"));t();var xb=new vl(va.u());t();var mc=Cq(xb,new L(ub));zb=new L(mc);break b}}}}}}}zb=t().d}var Ha=Qs(a,e,!0,O().c,h,g,new Ne(1413));if(Ha instanceof Ud)var Ka=Ha.fa,Oa=new Ud(new sm(new St(!Ga.b(),!tb.b(),!Xa.b()),Ka));else Oa=Ha;e=!1;Xa=null;var Na=Me(a,new Ne(1421),new Oe(\"argsOrIf\"));\nif(Na instanceof z){e=!0;Xa=Na;var Da=Xa.z,ta=Xa.p;if(null!==Da){var Ya=Da.h();if(Xr()===Ya&&ta instanceof z){var dc=ta.z;if(null!==dc){var ka=dc.h();if(qs()===ka){Ps(a,new Ne(1423),new Oe(\"argsOrIf\"));Ps(a,new Ne(1424),new Oe(\"argsOrIf\"));var ya=kt(c,zb,Oa);I=pu(a,new z(ya,b),O().c,d,Vs().Du,g,h);break a}}}}}if(e){var Sa=Xa.z;if(null!==Sa){var xc=Sa.h();if(Xr()===xc){Ps(a,new Ne(1427),new Oe(\"argsOrIf\"));var Sb=kt(c,zb,Oa);I=pu(a,new z(Sb,b),O().c,d,Vs().Du,g,h);break a}}}if(e){var uc=Xa.z;if(null!==\nuc){var Lb=uc.h();if(qs()===Lb&&d){Ps(a,new Ne(1430),new Oe(\"argsOrIf\"));if(zb instanceof L){var lc=zb.k,Xb=Ye(new Te(new Ue(J(new K,[\"Unexpected named argument name here\"]))),u()),ec=lc.A(),Ab=G(new H,Xb,ec),Ob=O().c;Ze(a,new z(Ab,Ob))}else if(t().d!==zb)throw new w(zb);zb=!1;Oa instanceof fe&&no();if(Oa instanceof Ud){zb=!0;var fb=Oa.fa;if(null!==fb){var Wa=fb.yb,bb=fb.ya;if(null!==Wa){var Ia=Wa.ch;if(!1===Wa.je&&!1===Ia){I=pu(a,b,new z(bb,c),d,Vs().Du,g,h);break a}}}}zb&&no();throw new w(Oa);}}}var Ua=\nkt(c,zb,Oa);I=Km(new z(Ua,b))}}finally{a.le=-1+a.le|0}Ds(a,new U(()=>\"\\x3d \"+I));return I}\nfunction bba(a,b,c){for(;;){var d=!1,e=null,g=Me(a,new Ne(1450),new Oe(\"bindings\"));if(g instanceof z&&(d=!0,e=g,g=e.z,null!==g&&(g=g.h(),Se()===g))){Ps(a,new Ne(1452),new Oe(\"bindings\"));continue}if(d&&(g=e.z,null!==g&&(g=g.h(),g=qs()===g?!0:g instanceof bs&&!0===g.ke?!0:ds()===g?!0:!1,g)))return Km(b);if(d&&(d=e.z,null!==d&&(e=d.h(),d=d.j(),e instanceof bs&&(g=e.ae,!1===e.ke)))){Ps(a,new Ne(1457),new Oe(\"bindings\"));e=zt(a,new as(\"\\x3d\"),Bt(),!1,new U(()=>O().c),c);if(null===e)throw new w(e);e=\ne.Rc();e=tt(Vs(),c)||!e;e=Us(a,0,e,new Ne(1459));g=new vl(g);t();d=Cq(g,new L(d));g=Me(a,new Ne(1466),new Oe(\"bindings\"));if(g instanceof z&&(g=g.z,null!==g&&(g=g.h(),Xr()===g))){Ps(a,new Ne(1468),new Oe(\"bindings\"));d=G(new H,d,e);b=new z(d,b);continue}a=G(new H,d,e);return Km(new z(a,b))}return O().c}}function It(a,b){b=Qn(b);if(b instanceof fe)return b=b.aa,tt(Vs(),!1)||a.Fu.n(b),gl();if(b instanceof Ud)return b.fa;throw new w(b);}\nfunction qu(){this.Du=this.xN=0;this.ao=null;this.MH=0;Bu=this;this.xN=0;this.Du=1+this.xN|0;O();var a=J(new K,\";;;;;;,;\\x3d;@;:;|;/ \\\\;^;\\x26;!;\\x3c \\x3e;+ -;* %;;.\".split(\";\"));a=Pd(u(),a);a=Hf(a);for(var b=null,c=null;a!==u();){var d=a.e();if(null===d)throw new w(d);var e=d.h();d=d.Sc();for(var g=e.length,h=Cu(g),k=0;k<g;){var l=e.charCodeAt(k);Pe(new E(hc(l)),hc(32))||(l=String.fromCharCode(l),h.ja=\"\"+h.ja+l);k=1+k|0}e=g===h.K()?e:h.ja;g=e.length;h=new zc(g);for(k=0;k<g;){l=k;var m=e.charCodeAt(k);\nh.a[l]=G(new H,hc(m),1+d|0);k=1+k|0}for(d=Du(new Eu,(new Fu(h)).vn);d.s();)e=new z(d.t(),u()),null===c?b=e:c.p=e,c=e;a=a.f()}a=null===b?u():b;op();this.ao=pp(qp(),a).jM(2147483647);this.MH=-1+(this.ao.n(hc(46))|0)|0}qu.prototype=new p;qu.prototype.constructor=qu;function tt(a,b){return Pe(new E(b),!0)}\nfunction bu(a){var b=Vs();switch(a){case \"is\":return new Gu(4,4);case \"and\":return new Gu(3,3);case \"or\":return new Gu(2,2);case \"\\x3d\\x3e\":return a=b.ao.n(hc(46))|0,new Gu(a,1);case \"+.\":case \"-.\":case \"*.\":return new Gu(b.ao.n(hc(Hu(Q(),a)))|0,b.ao.n(hc(Hu(Q(),a)))|0);default:a:{for(var c=a.length,d=0;d<c;){var e=a.charCodeAt(d);if(Or(Pr(),e)){c=d;break a}d=1+d|0}c=-1}if(-1!==c)return new Gu(5,5);c=Iu(Q(),a);return new Gu(b.ao.n(hc(Hu(Q(),a)))|0,(b.ao.n(hc(c))|0)-(Pe(new E(hc(c)),hc(64))||Pe(new E(hc(c)),\nhc(47))||Pe(new E(hc(c)),hc(44))||Pe(new E(hc(c)),hc(58))?1:0)|0)}}qu.prototype.$classData=q({QW:0},!1,\"mlscript.NewParser$\",{QW:1,g:1});var Bu;function Vs(){Bu||(Bu=new qu);return Bu}function qt(a){this.LH=null;if(null===a)throw null;this.LH=a}qt.prototype=new p;qt.prototype.constructor=qt;\nqt.prototype.HC=function(a){if(a instanceof z){var b=a.z,c=a.p;if(null!==b&&(b=b.h(),Se()===b&&null!==c&&(c=pt(this.LH).HC(c),!c.b()))){var d=c.k.h();a=c.k.j();t();a=G(new H,new U(()=>{Es(d);Ps(this.LH,new Ne(96),new Oe(\"unapply\"))}),a);return new L(a)}}t();a=G(new H,new U(()=>{}),a);return new L(a)};qt.prototype.$classData=q({UW:0},!1,\"mlscript.NewParser$Spaces$\",{UW:1,g:1});\nfunction Ju(a,b){if(a instanceof Ku){var c=a.fc,d=a.vd,e=a.be,g=a.Me;a=b?Lu(e):e;c.b()?e=!0:(e=c.o(),e instanceof Mu?(e=e.pd,Q(),e=new Ep(Nu(0,e.Dh)),e=!!g.U(e).b()):e=!0);e=e?c:R();c=new Ou(g);e.b()||(g=e.o(),e=V(g.q),a=Pu(g,a,e,!1));a=Qu(c,a,new fn((h,k)=>{var l=V(h.q);return Pu(h,k,l,!1)}));if(b){ms();if(0<=d.Q())b=d.Q(),b=new (md(Ru).Ia)(b),d.Gc(b,0,2147483647),d=b;else{b=null;b=[];for(d=d.m();d.s();)c=d.t(),b.push(null===c?null:c);d=new (md(Ru).Ia)(b)}b=Su();c=op().ga;b=Tu(d,new Uu(b,c))}else if(0<=\nd.Q())b=d.Q(),b=new (md(Ru).Ia)(b),d.Gc(b,0,2147483647);else{b=null;b=[];for(d=d.m();d.s();)c=d.t(),b.push(null===c?null:c);b=new (md(Ru).Ia)(b)}d=(h,k)=>{var l=V(h.q);return Pu(h,k,l,!1)};if(null===b)throw le();if(null!==b){c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}else if(b instanceof Xc){c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}else if(b instanceof ed){c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}else if(b instanceof Zc){c=b.a.length;for(g=0;g<c;)e=b.a[g],a=d(a,new ma(e.W,\ne.Y)),g=1+g|0;d=a}else if(b instanceof $c){c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}else if(b instanceof Ic){c=b.a.length;for(g=0;g<c;)a=d(a,hc(b.a[g])),g=1+g|0;d=a}else if(b instanceof Pc){c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}else if(b instanceof Sc){c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}else if(b instanceof Ec){c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}else{if(!ph(b))throw new w(b);c=b.a.length;for(g=0;g<c;)a=d(a,b.a[g]),g=1+g|0;d=a}return d}d=Vu(a.Fa);\nif(null!==d&&d===a)return a.Fa.La;throw new w(a);}function Wu(a,b,c,d){if(null===a)throw le();if(a.Ro)return a.So;var e=Xu().X();return Yu(a,Zu(d.Nb,b,c,!0,e))}function $u(a,b,c,d){if(null===a)throw le();if(a.Ro)return a.So;b=b.ac;var e=Xu().X();return Yu(a,Zu(d,b,c,!0,e))}function av(a,b,c,d){if(null===a)throw le();if(a.Ro)return a.So;var e=Xu().X();return Yu(a,Zu(d.ac,b,c,!0,e))}\nvar nba=function mba(a,b,c,d){if(b instanceof z){var g=b.z,h=b.p;if(null!==g){b=g.Nb;var k=g.ac,l=new bv,m=new bv,n=new bv,r=c.Nb,v=Xu().X();if((r=Zu(b,r,d,!0,v))&&(n.Ro?n.So:av(n,k,d,c)))return new z(c,h);if((l.Ro?l.So:Wu(l,b,d,c))&&(m.Ro?m.So:$u(m,c,d,k)))return new z(g,h);if(r&&(l.Ro?l.So:Wu(l,b,d,c)))return a=a.Fa,c=c.ac,d=V(k.q),g=new cv(a,b,Pu(k,c,d,!1),g.Mj),new z(g,h);if((m.Ro?m.So:$u(m,c,d,k))&&(n.Ro?n.So:av(n,k,d,c)))return a=a.Fa,c=c.Nb,d=V(b.q),g=new cv(a,dv(b,c,d,!1),k,g.Mj),new z(g,\nh);h=mba(a,h,c,d);return new z(g,h)}}h=O().c;if(null===h?null===b:h.i(b))return h=O().c,new z(c,h);throw new w(b);};function fv(){this.pE=null;this.Mz=!1;this.Fa=null}fv.prototype=new p;fv.prototype.constructor=fv;function gv(){}gv.prototype=fv.prototype;\nfunction oba(a,b){var c=G(new H,a,b),d=c.y,e=c.w;if(d instanceof Ku){var g=d.fc;b=d.vd;var h=d.be;d=d.Me;if(e instanceof Ku){c=e.vd;a=e.be;var k=e.Me;e=G(new H,g,e.fc);a:{var l=e.y;g=e.w;if(l instanceof L&&(l=l.k,g instanceof L)){e=pba(l,g.k);break a}g=e.w;if(e.y instanceof L&&t().d===g)e=-1;else if(g=e.y,l=e.w,t().d===g&&l instanceof L)e=1;else if(g=e.y,l=e.w,t().d===g&&t().d===l)e=0;else throw new w(e);}if(Nm(new E(e),0))return e;e=G(new H,sp(d),sp(k));a:{l=e.y;g=e.w;if(l instanceof L&&(l=l.k,null!==\nl&&(l=l.h(),g instanceof L&&(g=g.k,null!==g)))){e=pa(l.V,g.h().V);break a}g=e.w;if(e.y instanceof L&&t().d===g)e=1;else if(g=e.y,l=e.w,t().d===g&&l instanceof L)e=-1;else if(g=e.y,l=e.w,t().d===g&&t().d===l)e=0;else throw new w(e);}if(Nm(new E(e),0))return e;e=-hv(d,k)|0;if(Nm(new E(e),0))return e;d=c.ka();e=iv(b,d);return Nm(new E(e),0)?e:e=jv(h.Ba,a.Ba)}}b=c.y;if(Vu(a.Fa)===b)return 1;b=c.w;if(Vu(a.Fa)===b)return-1;throw new w(c);}f=fv.prototype;\nf.GC=function(){var a=this.zf(!1),b=O().c;return new z(a,b)};f.zf=function(a){return a?Ju(this,!0):this.mc()};f.mc=function(){this.Mz||this.Mz||(this.pE=Ju(this,!1),this.Mz=!0);return this.pE};\nf.ub=function(a,b){if(this instanceof Ku){var c=this.vd,d=this.be,e=this.Me,g=this.fc.m();g=new Ef(g,new y(m=>m.ub(a,b)));g=kv(g,new U(()=>{var m=c.m();return new Ef(m,new y(n=>n.ub(a,b)))})).nb(new U(()=>{lv();var m=d.Ba.m();m=mv(0,m);return new Ef(m,new y(n=>n.ub(a,b)))})).nb(new U(()=>{lv();var m=e.m();m=mv(0,m);return new Ef(m,new y(n=>n.ub(a,b)))}));if(g.s()){if(!g.s())throw nv(\"empty.reduceLeft\");for(var h=!0,k=null;g.s();){var l=g.t();h?(k=l,h=!1):(k|=0,l|=0,k=k>l?k:l)}g=new L(k)}else g=R();\nreturn(g.b()?this.Fa.Gd:g.o())|0}g=Vu(this.Fa);if(null!==g&&g===this)return this.Fa.Gd;throw new w(this);};function qba(a,b,c,d,e){if(a instanceof Ku){var g=a.fc,h=a.vd,k=a.be,l=a.Me;a=a.Fa;g.b()?g=R():(g=g.o(),g=new L(g.At(b,c,d,e)));k=ov(k,b,c,d,e);l=new pv(new qv(l),new y(v=>rv(v,b,c,d,e)));var m=sv(),n=Su(),r=op().ga;return new Ku(a,g,h,k,(new tv(m,new Uu(n,r))).vc(l))}h=Vu(a.Fa);if(null!==h&&h===a)return a;throw new w(a);}\nfunction rba(a,b){var c=Vu(a.Fa);if(null!==c&&c===a){c=a.Fa;var d=t().d;uv();var e=Su(),g=op().ga;b=vv(b,new Uu(e,g));a=wv(xv(a.Fa));e=sv();g=Su();var h=op().ga;return new Ku(c,d,b,a,e.Hd(new Uu(g,h)))}if(a instanceof Ku)return c=a.be,d=a.Me,new Ku(a.Fa,a.fc,a.vd.bc(b),c,d);throw new w(a);}\nfunction yv(a,b,c,d,e){var g=G(new H,a,b),h=g.y,k=g.w;if(Vu(a.Fa)===h&&k instanceof zv){t();var l=a.Fa;t();var m=new L(k),n=uv(),r=Su(),v=op().ga,x=n.ng(new Uu(r,v)),A=Ev(e)?k.kq():wv(xv(a.Fa)),B=sv(),C=Su(),D=op().ga,F=new Ku(l,m,x,A,B.Hd(new Uu(C,D)));return new L(F)}var I=g.y,M=g.w;if(Vu(a.Fa)===I&&M instanceof Fv){t();var N=a.Fa;t();var P=new L(M),T=uv(),Y=Su(),Z=op().ga,S=T.ng(new Uu(Y,Z)),ea=wv(xv(a.Fa)),ia=sv(),X=Su(),sa=op().ga,Ja=new Ku(N,P,S,ea,ia.Hd(new Uu(X,sa)));return new L(Ja)}var Xa=\ng.y,Fa=g.w;if(Vu(a.Fa)===Xa&&Fa instanceof Gv){t();var za=a.Fa,Qa=t().d;uv();var Ma=Su(),Ga=op().ga,ab=vv(Fa,new Uu(Ma,Ga)),Hb=wv(xv(a.Fa)),bc=sv(),yb=Su(),tb=op().ga,eb=new Ku(za,Qa,ab,Hb,bc.Hd(new Uu(yb,tb)));return new L(eb)}var kb=g.y,Rb=g.w;if(kb instanceof Ku){var Gb=kb.fc,vb=kb.vd,Tb=kb.be,Nb=kb.Me;if(Rb instanceof Gv){t();var ic=new Ku(a.Fa,Gb,vb.bc(Rb),Tb,Nb);return new L(ic)}}var Va=g.y,cb=g.w;if(Va instanceof Ku){var zb=Va.fc,Ub=Va.vd,jb=Va.be,db=Va.Me;if(cb instanceof Fv){var ub=null;\nub=jb;var Aa=G(new H,zb,cb);a:{var va=Aa.y,Ra=Aa.w;if(va instanceof L){var rb=va.k;if(rb instanceof Mu&&Ra instanceof Mu){var xb=sba(rb,Ra);break a}}var mc=Aa.y,Ha=Aa.w;if(mc instanceof L){var Ka=mc.k;if(Ka instanceof cv){var Oa=Ka.Nb,Na=Ka.ac;if(Ha instanceof cv){var Da=Ha.Nb,ta=Ha.ac;if(a.Fa.UI&&!c){t();var Ya=a.Fa,dc=V(Oa.q),ka=dv(Oa,Da,dc,!1),ya=V(Na.q),Sa=new cv(Ya,ka,Pu(Na,ta,ya,!1),Ka.Mj);xb=new L(Sa);break a}}}}var xc=Aa.y;if(xc instanceof L){var Sb=xc.k;if(Sb instanceof cv){var uc=Sb.Nb;\nif(null!==uc){var Lb=Hv(Iv(a.Fa),uc,d);if(!Lb.b()){var lc=Lb.k;if(lc instanceof zv){var Xb=lc.Yb;if(Aa.w instanceof Jv||Aa.w instanceof cv)b:{for(var ec=Xb;!ec.b();){var Ab=ec.e().j().ra;if(Kv(Ab,d)){var Ob=!0;break b}ec=ec.f()}Ob=!1}else Ob=!1;if(Ob){t();xb=new L(cb);break a}}}}}}var fb=Aa.y,Wa=Aa.w;if(fb instanceof L&&fb.k instanceof Jv&&Wa instanceof cv){var bb=Wa.Nb;if(null!==bb){var Ia=Hv(Iv(a.Fa),bb,d);if(!Ia.b()){var Ua=Ia.k;if(Ua instanceof zv){b:{for(var pc=Ua.Yb;!pc.b();){var sc=pc.e().j().ra;\nif(Kv(sc,d)){var Ba=!0;break b}pc=pc.f()}Ba=!1}if(Ba){xb=fb;break a}}}}}var ob=Aa.y,nc=Aa.w;if(ob instanceof L){var Ib=ob.k;if(Ib instanceof Jv){var vc=Ib.gi;if(nc instanceof cv){t();var Vb=new Jv(a.Fa,nba(a,vc,nc,d),Ib.Mq);xb=new L(Vb);break a}}}var fc=Aa.y;if(fc instanceof L){var Bc=fc.k;if(Bc instanceof cv&&(Aa.w instanceof Jv||Aa.w instanceof cv)){var Pb=a.Fa;t();var Jb=a.Fa,gc=O().c,Cb=new Jv(Jb,new z(Bc,gc),cb.ma());return yv(new Ku(Pb,new L(Cb),Ub,jb,db),cb,c,d,e)}}var cc=Aa.y,yc=Aa.w;if(cc instanceof\nL&&cc.k instanceof Jv&&yc instanceof Jv){var Mc=yc.gi;if(Mc instanceof z){var qc=Mc.z,oc=Mc.p,Qc=O().c;if(null===Qc?null===oc:Qc.i(oc))return yv(a,qc,c,d,e);var jc=yv(a,qc,c,d,e);return jc.b()?R():yv(jc.o(),new Jv(a.Fa,oc,yc.Mq),c,d,e)}}var sb=Aa.y,Gc=Aa.w;if(sb instanceof L){var Wb=sb.k;if(Wb instanceof zv){var Cc=Wb.Yb;if(Gc instanceof zv){var Fc=Gc.Yb,qd=Cc.K();if(Pe(new E(qd),Fc.K())){if(Ev(e)){for(var Yb=a.Fa,Nc=ub.Ba,ad=Gc.kq().Ba,Uc=Su(),cd=op().ga,kc=new Uu(Uc,cd),Vc=sv(),Hc=Nc.Q()+ad.Q()|\n0,rc=Lv(Lv(Mv(8<Hc?Hc:8),Nc),ad),sd=Xu().X(),Kc=sl(rc).m();Kc.s();){var Qd=Kc.t(),Ad=Qd.h(),kd=sd.U(Ad);if(kd instanceof L)var Hd=kd.k,Rd=Nv(Hd,Qd.j(),V(Hd.Va));else{if(R()!==kd)throw new w(kd);Rd=Qd.j()}sd.bj(Ad,Rd)}var Bd=qp(),ae=Ov(Vc,(new Pv(Bd)).vc(sd),kc);Od();var dd=Pd(u(),ae);ub=new Qv(Yb,dd,V(a.Fa))}t();var od=a.Fa,Ta=Rv(Cc,Fc),wb=new zv(od,Ta,V(a.Fa));xb=new L(wb)}else xb=t().d;break a}}}var $a=Aa.y,wa=Aa.w;if($a instanceof L){var hb=$a.k;if(hb instanceof Sv){var ra=hb.Fd;if(wa instanceof\nzv){var wc=wa.Yb;if(Ev(e)){for(var ac=a.Fa,Id=ub.Ba,ud=wa.kq().Ba,be=Su(),re=op().ga,pe=new Uu(be,re),bd=sv(),Rc=Id.Q()+ud.Q()|0,Wc=Lv(Lv(Mv(8<Rc?Rc:8),Id),ud),Wd=Xu().X(),zd=sl(Wc).m();zd.s();){var Pa=zd.t(),Db=Pa.h(),Oc=Wd.U(Db);if(Oc instanceof L)var Tc=Oc.k,Sd=Nv(Tc,Pa.j(),V(Tc.Va));else{if(R()!==Oc)throw new w(Oc);Sd=Pa.j()}Wd.bj(Db,Sd)}var Jc=qp(),vd=Ov(bd,(new Pv(Jc)).vc(Wd),pe);Od();var hd=Pd(u(),vd);ub=new Qv(ac,hd,V(a.Fa))}t();var de=a.Fa,ye=Wi=>{var Oj=Wi.h();Wi=Nv(ra,Wi.j(),V(ra.Va));\nreturn G(new H,Oj,Wi)};if(wc===u())var jf=u();else{for(var af=wc.e(),pf=new z(ye(af),u()),kf=pf,Be=wc.f();Be!==u();){var Kd=Be.e(),ld=new z(ye(Kd),u());kf=kf.p=ld;Be=Be.f()}jf=pf}var Jd=new zv(de,jf,V(a.Fa));xb=new L(Jd);break a}}}var Dd=Aa.y,Xd=Aa.w;if(Dd instanceof L){var Yc=Dd.k;if(Yc instanceof zv){var Ce=Yc.Yb;if(Xd instanceof Sv){var te=Xd.Fd;t();var Ie=a.Fa,Jf=Wi=>{var Oj=Wi.h();Wi=Nv(Wi.j(),te,V(Wi.j().Va));return G(new H,Oj,Wi)};if(Ce===u())var df=u();else{for(var vg=Ce.e(),wg=new z(Jf(vg),\nu()),xg=wg,eg=Ce.f();eg!==u();){var vh=eg.e(),fg=new z(Jf(vh),u());xg=xg.p=fg;eg=eg.f()}df=wg}var ih=new zv(Ie,df,V(a.Fa));xb=new L(ih);break a}}}var Ig=Aa.y,Tf=Aa.w;if(Ig instanceof L){var Jg=Ig.k;if(Jg instanceof Sv){var jh=Jg.Fd;if(Tf instanceof Sv){var yg=Tf.Fd;t();var gg=a.Fa,Cf=Nv(jh,yg,V(jh.Va)),Uf=new Sv(gg,Cf,V(a.Fa));xb=new L(Uf);break a}}}var $g=Aa.y,Ah=Aa.w;if($g instanceof L){var Kg=$g.k;if(Kg instanceof Tv){var Vf=Kg.Ic,hg=Kg.kf;if(Ah instanceof Tv){var zg=Ah.Ic;if(Pe(new E(hg),Ah.kf)){t();\nvar Lg=a.Fa,Mg=V(Vf.q),Wf=Pu(Vf,zg,Mg,!1),Ng=new Tv(Lg,Wf,hg,Kg.vp);xb=new L(Ng);break a}}}}var Kf=Aa.y,xf=Aa.w;if(Kf instanceof L){var Og=Kf.k;if(xf instanceof Tv){t();var mi=a.Fa,Ci=V(Og.q),Xh=Pu(Og,xf,Ci,!1),wh=uv(),Bh=Su(),ng=op().ga,kh=wh.ng(new Uu(Bh,ng)),Kh=new Tv(mi,Xh,kh,V(a.Fa));xb=new L(Kh);break a}}var ni=Aa.y,Lh=Aa.w;if(ni instanceof L){var lh=ni.k;if(lh instanceof Tv){t();var Ch=a.Fa,Dh=V(lh.q),Yh=Pu(lh,Lh,Dh,!1),ah=uv(),oi=Su(),mj=op().ga,wd=ah.ng(new Uu(oi,mj)),ge=new Tv(Ch,Yh,wd,\nV(a.Fa));xb=new L(ge);break a}}var De=Aa.y;if(De instanceof L&&Uv(De.k)&&De.k.q===a.Fa&&(Aa.w instanceof cv||Aa.w instanceof Vv||Aa.w instanceof Jv))var qf=!0;else{var og=Aa.y;if(og instanceof L&&(og.k instanceof cv||og.k instanceof Vv||og.k instanceof Jv)&&Uv(Aa.w)&&Aa.w.q===a.Fa)qf=!0;else{var Xf=Aa.y;if(Xf instanceof L&&Xf.k instanceof cv&&(Aa.w instanceof Vv||Aa.w instanceof Jv))qf=!0;else{var mh=Aa.y;if(mh instanceof L&&(mh.k instanceof Vv||mh.k instanceof Jv)&&Aa.w instanceof cv)qf=!0;else{var Ag=\nAa.y;if(Ag instanceof L&&Ag.k instanceof Vv&&Aa.w instanceof Jv)qf=!0;else{var Bg=Aa.y;qf=Bg instanceof L&&Bg.k instanceof Jv&&Aa.w instanceof Vv?!0:!1}}}}}if(qf)xb=t().d;else{b:{var Eh=Aa.y;if(Eh instanceof L){var Pg=Eh.k;if(Pg instanceof Jv){var Di=Pg.gi,Mh=O().c;if(null===Mh?null===Di:Mh.i(Di)){var pi=!0;break b}}}var Xi=Aa.w;if(Aa.y instanceof L&&Xi instanceof Jv){var Qg=Xi.gi,nh=O().c;if(null===nh?null===Qg:nh.i(Qg)){pi=!0;break b}}pi=!1}pi&&xm(\"Program reached and unexpected state.\");var bh=\nAa.y;var Mj=bh instanceof L&&bh.k instanceof Wv?!0:Aa.y instanceof L&&Aa.w instanceof Wv?!0:!1;Mj&&no();var Nj=Aa.y,ie=Aa.w;if(t().d===Nj&&ie instanceof zv){if(Ev(e)){for(var Ac=a.Fa,Ve=ub.Ba,Td=ie.kq().Ba,lf=Su(),Yi=op().ga,Jl=new Uu(lf,Yi),ll=sv(),Bj=Ve.Q()+Td.Q()|0,$k=Lv(Lv(Mv(8<Bj?Bj:8),Ve),Td),Zh=Xu().X(),Ei=sl($k).m();Ei.s();){var Yd=Ei.t(),bf=Yd.h(),rf=Zh.U(bf);if(rf instanceof L)var Cg=rf.k,nj=Nv(Cg,Yd.j(),V(Cg.Va));else{if(R()!==rf)throw new w(rf);nj=Yd.j()}Zh.bj(bf,nj)}var Jh=qp(),If=Ov(ll,\n(new Pv(Jh)).vc(Zh),Jl);Od();var Hg=Pd(u(),If);ub=new Qv(Ac,Hg,V(a.Fa))}t();xb=new L(cb)}else{var He=Aa.y;if(t().d===He)t(),xb=new L(cb);else throw new w(Aa);}}}if(xb.b())return R();var lj=xb.o();return new L(new Ku(a.Fa,(t(),new L(lj)),Ub,ub,db))}}throw new w(g);}\nfunction Xv(a,b){var c=Vu(a.Fa);if(null!==c&&c===a){a=a.Fa;c=t().d;var d=uv(),e=Su(),g=op().ga;d=d.ng(new Uu(e,g));e=sv();g=Su();var h=op().ga;return new Ku(a,c,d,b,e.Hd(new Uu(g,h)))}if(a instanceof Ku)return c=a.fc,d=a.vd,e=a.Me,h=g=a.Fa,b=Yv(a.be.Ba,b.Ba),new Ku(g,c,d,new Qv(h,b,V(a.Fa)),e);throw new w(a);}\nfunction Zv(a,b,c,d,e){var g=Vu(a.Fa);if(null!==g&&g===a){t();e=a.Fa;g=t().d;var h=uv(),k=Su(),l=op().ga;h=h.ng(new Uu(k,l));k=wv(xv(a.Fa));sv();b=G(new H,b.qb,b);l=Su();var m=op().ga;b=new Ku(e,g,h,k,$v(b,new Uu(l,m)));return new L(b)}if(a instanceof Ku){g=a.fc;h=a.vd;k=a.be;l=a.Me;m=b.qb;var n=l.U(b.qb);if(n.b())n=b;else{n=n.o();var r=new aw(b.Zb);tp();var v=jv(r.rc,n.Zb);up(0,Pe(new E(v),0));t();n=bw(n,new L(!0),new fn((x,A)=>{var B=r.rc.e();r.rc=r.rc.f();var C=!1,D=null;if(x instanceof L&&(C=\n!0,D=x,!0===!!D.k))return x=V(A.q),Pu(A,B,x,!1);if(C&&!1===!!D.k)return x=V(A.q),dv(A,B,x,!1);if(t().d===x){if(c)return x=cw(a.Fa),C=V(A.q),C=dv(A,B,C,!1),D=V(A.q),dw(x,C,Pu(A,B,D,!1),ew(cw(a.Fa)),d);x=cw(a.Fa);C=V(A.q);C=Pu(A,B,C,!1);D=V(A.q);return dw(x,C,dv(A,B,D,!1),ew(cw(a.Fa)),d)}throw new w(x);}),d);n=new fw(a.Fa,b.qb,n,b.Xl)}l=l.Dm(m,n);g=new Ku(a.Fa,g,h,k,l);b=gw(b,d);b.b()?(t(),b=new L(g)):(b=b.o(),b=yv(g,b,c,d,e));return b}throw new w(a);}\nfunction hw(a,b,c,d,e){var g=tc();try{var h=G(new H,a,b),k=h.w;if(Vu(a.Fa)===k)return t(),new L(a);var l=h.y;if(Vu(a.Fa)===l)return t(),new L(b);var m=h.w;if(m instanceof Ku){var n=m.fc,r=m.be,v=m.Me,x=m.vd.m(),A=new Ou(v);if(n.b())var B=it().n(Xv(a,r));else{var C=n.o();B=yv(Xv(a,r),C,c,d,e)}for(a=B;A.Ot.s();){b=a;var D=A.t();h=D;if(b.b())throw Hq(new Iq,g,t().d);a=Zv(b.o(),h,c,d,e)}for(A=a;x.s();){D=A;var F=x.t();a=F;if(D.b())throw Hq(new Iq,g,t().d);A=yv(D.o(),a,c,d,e)}return A}throw new w(h);}catch(I){if(I instanceof\nIq){c=I;if(c.Qg===g)return c.Cj();throw c;}throw I;}}\nf.Dw=function(a,b){var c=G(new H,this,a),d=c.y,e=c.w;if(d instanceof Ku&&(d=d.be,e instanceof iw))return a=this.Fa,c=G(new H,e.me,e.Ne),e=O().c,a=new Qv(a,new z(c,e),V(this.Fa)),c=Xu().X(),Zu(d,a,b,!0,c);var g=c.y,h=c.w;if(g instanceof Ku&&(d=g.fc,h instanceof jw)){e=h.mb;c=h.Dc;a:{for(h=h.Xb;!h.b();){var k=h.e();b:{if(d instanceof L){var l=d.k;if(l instanceof Mu){k=Pe(new E(k.uo()),l.pd)?!0:(g.rE?g.qE:kw(g)).L(k.uo());break b}}k=!1}if(k){g=!0;break a}h=h.f()}g=!1}if(g)a=!0;else a:{if(g=!1,h=null,\ne instanceof L&&(g=!0,h=e,k=h.k,k instanceof Ud&&(k=k.fa,null!==k))){a=this.Dw(k,b);break a}if(g&&(k=h.k,k instanceof fe&&(k=k.aa,k instanceof cv||k instanceof Jv||k instanceof Vv||k instanceof zv))){d.b()?a=!1:(a=d.o(),d=Xu().X(),a=Zu(a,k,b,!0,d));break a}if(g&&(d=h.k,d instanceof fe&&d.aa instanceof Tv))return a=a.mc(),this.mc(),this.mc(),c=Xu().X(),d=this.mc(),Zu(d,a,b,!0,c);if(t().d===e)a=!1;else throw new w(e);}if(a)return!0;d=!1;for(a=c.m();!d&&a.s();){c=a.t();if(null===c)throw new w(c);c=c.j();\nthis.mc();this.mc();d=Xu().X();e=this.mc();d=Zu(e,c,b,!0,d)}return d}b=c.y;if(Vu(this.Fa)===b)return!1;b=c.w;if(lw(this.Fa)===b)return!1;throw new w(c);};\nfunction mw(a,b,c){var d=G(new H,a,b);b=d.w;if(Vu(a.Fa)===b)return!0;b=d.y;if(Vu(a.Fa)===b)return!1;a=d.y;var e=d.w;if(a instanceof Ku){var g=a.fc,h=a.vd;b=a.be;a=a.Me;if(e instanceof Ku){var k=e.fc,l=e.vd;d=e.be;e=e.Me;if(k.b())g=!0;else if(k=k.o(),g.b())g=!1;else{g=g.o();var m=Xu().X();g=Zu(g,k,c,!0,m)}g&&nw(l,h)?(h=Xu().X(),b=Zu(b,d,c,!0,h)):b=!1;if(b){b=new Ou(e);for(h=!0;h&&b.Ot.s();){h=b.t();d=new Ou(a);for(e=!1;!e&&d.Ot.s();)e=d.t(),l=Xu().X(),e=Zu(e,h,c,!0,l);h=e}return h}return!1}}throw new w(d);\n}function ow(a){return Vu(a.Fa)===a}\nfunction pw(a,b){if(a instanceof iw){var c=a.Aa;b=G(new H,a.me,a.Ne);var d=O().c;return new Qv(c,new z(b,d),V(a.Aa))}if(a instanceof jw){c=a.Xb;var e=a.mb;d=a.Dc;if(e.b())a=a.Aa.ib;else if(a=e.o(),a instanceof Ud)a=a.fa.zf(b);else{if(!(a instanceof fe))throw new w(a);a=a.aa}d=new Ou(d);a=Qu(d,a,new fn((g,h)=>{var k=V(g.q);return dv(g,h,k,!1)}));b&&(b=Su(),d=op().ga,c=qw(c,new Uu(b,d)));return c.De(a,new fn((g,h)=>{var k=V(g.q);return dv(g,h,k,!1)}))}c=lw(a.Aa);if(null!==c&&c===a)return a.Aa.ib;throw new w(a);\n}function rw(a,b){if(null===b)throw null;a.Aa=b}function sw(){this.Nz=null;this.jx=!1;this.Aa=null}sw.prototype=new p;sw.prototype.constructor=sw;function tw(){}tw.prototype=sw.prototype;\nfunction tba(a,b){var c=G(new H,a,b),d=c.y;b=c.w;if(d instanceof iw&&(d=d.me,b instanceof iw))return pa(d.Dh,b.me.Dh);b=c.y;var e=c.w;if(b instanceof jw&&(d=b.Xb,b=b.Dc,e instanceof jw)){c=e.Xb;a=e.Dc;e=Su();var g=op().ga;e=Gq(d,new Uu(e,g));if(e instanceof L){e=e.k;g=Su();var h=op().ga;g=Gq(c,new Uu(g,h));if(g instanceof L)c=uw(e,g.k);else{if(t().d!==g)throw new w(g);d=d.K();d=new vw(d);c=c.K();Fq();d=d.al;c=d===c?0:d<c?-1:1}}else{if(t().d!==e)throw new w(e);d=d.K();d=new vw(d);c=c.K();Fq();d=d.al;\nc=d===c?0:d<c?-1:1}if(Nm(new E(c),0))return c;c=G(new H,sp(b),sp(a));a:{e=c.y;d=c.w;if(e instanceof L&&(e=e.k,null!==e&&(e=e.h(),d instanceof L&&(d=d.k,null!==d)))){c=pa(e.V,d.h().V);break a}d=c.w;if(c.y instanceof L&&t().d===d)c=1;else if(d=c.y,e=c.w,t().d===d&&e instanceof L)c=-1;else if(d=c.y,e=c.w,t().d===d&&t().d===e)c=0;else throw new w(c);}return Nm(new E(c),0)?c:c=-hv(b,a)|0}if(c.y instanceof jw)return-1;if(c.w instanceof jw)return 1;if(c.y instanceof iw)return-1;if(c.w instanceof iw)return 1;\nb=c.y;d=c.w;if(lw(a.Aa)===b&&lw(a.Aa)===d)return 0;throw new w(c);}sw.prototype.GC=function(){var a=this.zf(!1),b=O().c;return new z(a,b)};sw.prototype.zf=function(a){return a?pw(this,!0):this.mc()};sw.prototype.mc=function(){this.jx||this.jx||(this.Nz=pw(this,!1),this.jx=!0);return this.Nz};\nfunction ww(a,b,c,d){var e=lw(a.Aa);if(null!==e&&e===a){t();e=a.Aa;var g=O().c,h=t().d;sv();b=G(new H,b.qb,b);var k=Su(),l=op().ga;b=new jw(e,g,h,$v(b,new Uu(k,l)));return new L(b)}if(a instanceof iw){e=a.me;b=a.Ne;h=!1;g=null;k=lw(a.Aa);if(null!==k&&k===a)return t(),b=new iw(a.Aa,e,b),new L(b);if(a instanceof iw&&(k=a.me,l=a.Ne,Pe(new E(k),e)))return t(),b=new iw(a.Aa,k,xw(l,b,V(l.Va))),new L(b);if(a instanceof jw){h=!0;g=a;k=g.Xb;var m=g.mb;l=g.Dc;if(t().d===m)return t(),g=a.Aa,t(),t(),b=new iw(a.Aa,\ne,b),b=new jw(g,k,new L(new Ud(b)),l),new L(b)}if(h&&(h=g.Xb,k=g.mb,g=g.Dc,k instanceof L&&(k=k.k,k instanceof Ud&&(l=k.fa,null!==l&&(k=l.me,l=l.Ne,Pe(new E(k),e))))))return t(),e=a.Aa,t(),t(),b=new iw(a.Aa,k,xw(l,b,V(l.Va))),b=new jw(e,h,new L(new Ud(b)),g),new L(b);if(a instanceof iw||a instanceof jw)return t().d;throw new w(a);}if(a instanceof jw){e=a.Xb;g=a.mb;h=a.Dc;k=b.qb;l=h.U(b.qb);if(!l.b()){l=l.o();var n=new aw(b.Zb);tp();m=jv(n.rc,l.Zb);up(0,Pe(new E(m),0));t();l=bw(l,new L(!0),new fn((r,\nv)=>{var x=n.rc.e();n.rc=n.rc.f();var A=!1,B=null;if(r instanceof L&&(A=!0,B=r,!0===!!B.k))return r=V(v.q),dv(v,x,r,!1);if(A&&!1===!!B.k)return r=V(v.q),Pu(v,x,r,!1);if(t().d===r){if(c)return r=cw(a.Aa),A=V(v.q),A=Pu(v,x,A,!1),B=V(v.q),dw(r,A,dv(v,x,B,!1),ew(cw(a.Aa)),d);r=cw(a.Aa);A=V(v.q);A=dv(v,x,A,!1);B=V(v.q);return dw(r,A,Pu(v,x,B,!1),ew(cw(a.Aa)),d)}throw new w(r);}),d);b=new fw(a.Aa,b.qb,l,b.Xl)}b=h.Dm(k,b);t();b=new jw(a.Aa,e,g,b);return new L(b)}throw new w(a);}\nfunction yw(a,b,c,d){var e=tc();try{if(b instanceof jw){for(var g=b.Xb,h=b.mb,k=new Ou(b.Dc);k.Ot.s();){var l=a,m=k.t(),n=ww(l,m,c,d);if(n.b())throw Hq(new Iq,e,t().d);a=n.o()}for(;!g.b();){c=a;var r=g.e(),v=zw(c,r);if(v.b())throw Hq(new Iq,e,t().d);a=v.o();g=g.f()}r=a;t();if(h.b())var x=r;else{var A=h.o();if(A instanceof Ud){var B=A.fa;var C=G(new H,B.me,B.Ne);var D=Aw(r,C);if(D.b())throw Hq(new Iq,e,t().d);x=D.o()}else{if(!(A instanceof fe))throw new w(A);var F=zw(r,A.aa);if(F.b())throw Hq(new Iq,\ne,t().d);x=F.o()}}return new L(x)}if(b instanceof iw){l=b.me;var I=b.Ne;h=!1;x=null;var M=lw(a.Aa);if(null!==M&&M===a){t();var N=new iw(a.Aa,l,I);return new L(N)}if(a instanceof iw){var P=a.me,T=a.Ne;if(Pe(new E(P),l)){t();var Y=new iw(a.Aa,P,xw(T,I,V(T.Va)));return new L(Y)}}if(a instanceof jw){h=!0;x=a;var Z=x.Xb,S=x.mb,ea=x.Dc;if(t().d===S){t();var ia=a.Aa;t();t();var X=new iw(a.Aa,l,I),sa=new jw(ia,Z,new L(new Ud(X)),ea);return new L(sa)}}if(h){var Ja=x.Xb,Xa=x.mb,Fa=x.Dc;if(Xa instanceof L){var za=\nXa.k;if(za instanceof Ud){var Qa=za.fa;if(null!==Qa){var Ma=Qa.me,Ga=Qa.Ne;if(Pe(new E(Ma),l)){t();var ab=a.Aa;t();t();var Hb=new iw(a.Aa,Ma,xw(Ga,I,V(Ga.Va))),bc=new jw(ab,Ja,new L(new Ud(Hb)),Fa);return new L(bc)}}}}}if(a instanceof iw||a instanceof jw)return t().d;throw new w(a);}if(lw(a.Aa)===b)return t(),new L(a);throw new w(b);}catch(yb){if(yb instanceof Iq){h=yb;if(h.Qg===e)return h.Cj();throw h;}throw yb;}}\nfunction uba(a,b,c){var d=lw(a.Aa);if(null!==d&&d===a||lw(a.Aa)===b)return t(),a=lw(a.Aa),new L(a);if(a instanceof iw){d=a.me;var e=a.Ne;if(b instanceof iw){var g=b.Ne;if(Pe(new E(d),b.me))return t(),a=new iw(a.Aa,d,Nv(e,g,V(e.Va))),new L(a)}}if(a instanceof jw&&(d=a.Xb,g=a.mb,e=a.Dc,g instanceof L&&(g=g.k,g instanceof Ud&&(g=g.fa,b instanceof jw)))){var h=b.Xb,k=b.mb,l=b.Dc;if(k instanceof L&&(k=k.k,k instanceof Ud&&(k=k.fa,Pe(new E(d),h)&&Pe(new E(e),l)&&Pe(new E(g.me),k.me))))return t(),c=a.Aa,\nt(),t(),a=new iw(a.Aa,g.me,Nv(g.Ne,k.Ne,V(g.Ne.Va))),a=new jw(c,d,new L(new Ud(a)),e),new L(a)}return a instanceof jw&&(d=a.Xb,e=a.mb,g=a.Dc,b instanceof jw&&(l=b.mb,h=b.Dc,Pe(new E(d),b.Xb)&&Pe(new E(e),l)?(b=g.AB(),b=Pe(new E(b),h.AB())):b=!1,b))?(t(),a=new jw(a.Aa,d,e,Bw(a.Aa,!1,g,h,c)),new L(a)):t().d}\nfunction vba(a,b){var c=lw(a.Aa);if(null!==c&&c===a){c=a.Aa;a=O().c;b=new z(b,a);a=t().d;var d=sv(),e=Su(),g=op().ga;return new jw(c,b,a,d.Hd(new Uu(e,g)))}if(a instanceof iw)return c=a.Aa,d=O().c,b=new z(b,d),t(),t(),a=new L(new Ud(a)),d=sv(),e=Su(),g=op().ga,new jw(c,b,a,d.Hd(new Uu(e,g)));if(a instanceof jw)return new jw(a.Aa,new z(b,a.Xb),a.mb,a.Dc);throw new w(a);}\nfunction zw(a,b){var c=G(new H,a,b),d=c.y,e=c.w;if(lw(a.Aa)===d&&Uv(e)){t();var g=a.Aa,h=O().c,k=new z(e,h),l=t().d,m=sv(),n=Su(),r=op().ga,v=new jw(g,k,l,m.Hd(new Uu(n,r)));return new L(v)}var x=c.y,A=c.w;if(lw(a.Aa)===x&&A instanceof Cw){t();var B=a.Aa,C=O().c;t();t();var D=new L(new fe(A)),F=sv(),I=Su(),M=op().ga,N=new jw(B,C,D,F.Hd(new Uu(I,M)));return new L(N)}var P=c.y,T=c.w;if(P instanceof jw){var Y=P.Xb,Z=P.mb,S=P.Dc;if(T instanceof Mu){t();var ea=new jw(a.Aa,Y.L(T)?Y:new z(T,Y),Z,S);return new L(ea)}}var ia=\nc.y,X=c.w;if(ia instanceof jw){var sa=ia.Xb,Ja=ia.mb,Xa=ia.Dc;if(t().d===Ja&&X instanceof Cw){t();var Fa=a.Aa;t();t();var za=new jw(Fa,sa,new L(new fe(X)),Xa);return new L(za)}}var Qa=c.y,Ma=c.w;if(Qa instanceof jw){var Ga=Qa.Xb,ab=Qa.mb,Hb=Qa.Dc;if(ab instanceof L){var bc=ab.k;if(bc instanceof fe){var yb=bc.aa;if(yb instanceof zv){var tb=yb.Yb;if(Ma instanceof zv){var eb=Ma.Yb,kb=tb.K();if(Nm(new E(kb),eb.K())){var Rb=a.Aa;t();t();var Gb=Dw(yb);return zw(new jw(Rb,Ga,new L(new fe(Gb)),Hb),Dw(Ma))}t();\nvar vb=a.Aa;t();t();var Tb=a.Aa,Nb=new Wq(tb,tb,eb),ic=new fn((ld,Jd)=>{ld=G(new H,ld,Jd);Jd=ld.y;var Dd=ld.w;if(null!==Jd){var Xd=Jd.h();Jd=Jd.j();if(Xd instanceof L&&(Xd=Xd.k,null!==Dd)){var Yc=Dd.h();Dd=Dd.j();if(Yc instanceof L)return ld=Pe(new E(Xd),Yc.k)?(t(),new L(Xd)):t().d,G(new H,ld,xw(Jd,Dd,V(Jd.Va)))}}Dd=ld.y;Xd=ld.w;if(null!==Dd&&(Jd=Dd.h(),Dd=Dd.j(),null!==Xd))return ld=Xd.h(),Xd=Xd.j(),ld=Jd.b()?ld:Jd,G(new H,ld,xw(Dd,Xd,V(Dd.Va)));throw new w(ld);});Yq();var Va=Ew(Nb,ic),cb=new zv(Tb,\nVa,V(a.Aa)),zb=new jw(vb,Ga,new L(new fe(cb)),Hb);return new L(zb)}}}}}var Ub=c.y,jb=c.w;if(Ub instanceof jw){var db=Ub.mb;if(db instanceof L){var ub=db.k;if(ub instanceof fe&&ub.aa instanceof Sv&&jb instanceof zv)return zw(a,Dw(jb))}}var Aa=c.y,va=c.w;if(Aa instanceof jw){var Ra=Aa.Xb,rb=Aa.mb,xb=Aa.Dc;if(rb instanceof L){var mc=rb.k;if(mc instanceof fe){var Ha=mc.aa;if(Ha instanceof zv&&va instanceof Sv){var Ka=a.Aa;t();t();var Oa=Dw(Ha);return zw(new jw(Ka,Ra,new L(new fe(Oa)),xb),va)}}}}var Na=\nc.y,Da=c.w;if(Na instanceof jw){var ta=Na.Xb,Ya=Na.mb,dc=Na.Dc;if(Ya instanceof L){var ka=Ya.k;if(ka instanceof fe){var ya=ka.aa;if(ya instanceof Sv){var Sa=ya.Fd;if(Da instanceof Sv){var xc=Da.Fd;t();var Sb=a.Aa;t();t();var uc=a.Aa,Lb=xw(Sa,xc,V(Sa.Va)),lc=new Sv(uc,Lb,V(a.Aa)),Xb=new jw(Sb,ta,new L(new fe(lc)),dc);return new L(Xb)}}}}}a:{var ec=c.y;if(ec instanceof jw){var Ab=ec.mb;if(Ab instanceof L){var Ob=Ab.k;if(Ob instanceof fe&&Ob.aa instanceof Tv){var fb=!0;break a}}}fb=c.w instanceof Tv?\n!0:!1}fb&&xm(\"Program reached and unexpected state.\");var Wa=c.y;if(Wa instanceof jw){var bb=Wa.mb;if(bb instanceof L){var Ia=bb.k;if(Ia instanceof fe&&Pe(new E(b),Ia.aa))return t(),new L(a)}}var Ua=c.y,pc=c.w;if(Ua instanceof jw){var sc=Ua.Xb,Ba=Ua.mb,ob=Ua.Dc;if(Ba instanceof L){var nc=Ba.k;if(nc instanceof fe){var Ib=nc.aa;if(Ib instanceof cv){var vc=Ib.Nb,Vb=Ib.ac;if(pc instanceof cv){var fc=pc.Nb,Bc=pc.ac;t();var Pb=a.Aa;t();t();var Jb=a.Aa,gc=V(vc.q),Cb=Pu(vc,fc,gc,!1),cc=V(Vb.q),yc=dv(Vb,Bc,\ncc,!1),Mc=new cv(Jb,Cb,yc,V(a.Aa)),qc=new jw(Pb,sc,new L(new fe(Mc)),ob);return new L(qc)}}}}}var oc=c.y,Qc=c.w;if(oc instanceof jw){var jc=oc.Xb,sb=oc.mb,Gc=oc.Dc;if(sb instanceof L){var Wb=sb.k;if(Wb instanceof fe){var Cc=Wb.aa;if(Cc instanceof Jv){var Fc=Cc.gi;if(Qc instanceof cv){var qd=Qc.Nb,Yb=Qc.ac;t();var Nc=a.Aa;t();t();var ad=a.Aa,Uc=ld=>{if(null!==ld){var Jd=ld.Nb,Dd=ld.ac,Xd=a.Aa,Yc=V(Jd.q);Jd=Pu(Jd,qd,Yc,!1);Yc=V(Dd.q);return new cv(Xd,Jd,dv(Dd,Yb,Yc,!1),ld.Mj)}throw new w(ld);};if(Fc===\nu())var cd=u();else{for(var kc=Fc.e(),Vc=new z(Uc(kc),u()),Hc=Vc,rc=Fc.f();rc!==u();){var sd=rc.e(),Kc=new z(Uc(sd),u());Hc=Hc.p=Kc;rc=rc.f()}cd=Vc}var Qd=new Jv(ad,cd,Cc.Mq),Ad=new jw(Nc,jc,new L(new fe(Qd)),Gc);return new L(Ad)}}}}}var kd=c.y,Hd=c.w;if(kd instanceof jw){var Rd=kd.Xb,Bd=kd.mb,ae=kd.Dc;if(Bd instanceof L){var dd=Bd.k;if(dd instanceof fe){var od=dd.aa;if(od instanceof cv&&Hd instanceof Jv){var Ta=a.Aa;t();t();return zw(new jw(Ta,Rd,new L(new fe(Hd)),ae),od)}}}}a:{var wb=c.y;if(wb instanceof\njw){var $a=wb.mb;if($a instanceof L){var wa=$a.k;if(wa instanceof fe&&wa.aa instanceof Jv){var hb=!0;break a}}}hb=c.w instanceof Jv?!0:!1}if(hb)return t().d;var ra=c.y,wc=c.w;if(ra instanceof jw){var ac=ra.Xb,Id=ra.mb,ud=ra.Dc;if(wc instanceof Gv){t();var be=new jw(a.Aa,ac.L(wc)?ac:new z(wc,ac),Id,ud);return new L(be)}}var re=c.y,pe=c.w;if(re instanceof iw&&Uv(pe)){t();var bd=a.Aa,Rc=O().c,Wc=new z(pe,Rc);t();t();var Wd=new L(new Ud(re)),zd=sv(),Pa=Su(),Db=op().ga,Oc=new jw(bd,Wc,Wd,zd.Hd(new Uu(Pa,\nDb)));return new L(Oc)}if(c.y instanceof iw&&(c.w instanceof cv||c.w instanceof Vv))return t().d;a:{var Tc=c.y;if(Tc instanceof jw){var Sd=Tc.mb;if(Sd instanceof L){var Jc=Sd.k;if(Jc instanceof fe&&Jc.aa instanceof cv&&c.w instanceof Vv){var vd=!0;break a}}}var hd=c.y;if(hd instanceof jw){var de=hd.mb;if(de instanceof L){var ye=de.k;if(ye instanceof fe&&ye.aa instanceof Vv&&c.w instanceof cv){vd=!0;break a}}}var jf=c.y;if(jf instanceof jw){var af=jf.mb;if(af instanceof L&&af.k instanceof Ud&&(c.w instanceof\ncv||c.w instanceof Vv)){vd=!0;break a}}vd=!1}if(vd)return t().d;a:{var pf=c.y;if(pf instanceof jw){var kf=pf.mb;if(kf instanceof L){var Be=kf.k;if(Be instanceof fe&&Be.aa instanceof Wv){var Kd=!0;break a}}}Kd=c.w instanceof Wv?!0:!1}Kd&&no();throw new w(c);}\nfunction Aw(a,b){var c=!1,d=null,e=lw(a.Aa);if(null!==e&&e===a)return t(),a=new iw(a.Aa,b.h(),b.j()),new L(a);if(a instanceof iw){e=a.me;var g=a.Ne;if(Pe(new E(e),b.h()))return t(),a=new iw(a.Aa,e,xw(g,b.j(),V(g.Va))),new L(a)}if(a instanceof jw){c=!0;d=a;e=d.Xb;var h=d.mb;g=d.Dc;if(t().d===h)return t(),d=a.Aa,t(),t(),a=new iw(a.Aa,b.h(),b.j()),a=new jw(d,e,new L(new Ud(a)),g),new L(a)}if(c&&(c=d.Xb,e=d.mb,d=d.Dc,e instanceof L&&(e=e.k,e instanceof Ud&&(g=e.fa,null!==g&&(e=g.me,h=g.Ne,Pe(new E(e),\nb.h()))))))return t(),g=a.Aa,t(),t(),a=new iw(a.Aa,e,xw(h,b.j(),V(h.Va))),a=new jw(g,c,new L(new Ud(a)),d),new L(a);if(a instanceof iw||a instanceof jw)return t().d;throw new w(a);}\nsw.prototype.Dw=function(a,b){var c=G(new H,this,a),d=c.y;a=c.w;if(d instanceof jw){var e=d.Xb,g=d.mb;d=d.Dc;if(g instanceof L&&(g=g.k,g instanceof Ud&&(g=g.fa,a instanceof iw))){if(e.b()){c=new Ou(d);for(e=!0;e&&c.Ot.s();){e=c.t();d=a.mc();var h=Xu().X();e=Zu(e,d,b,!0,h)}c=e}else c=!1;return c?g.Dw(a,b):!1}}a=c.w;if(c.y instanceof jw&&a instanceof iw)return!1;a=c.w;if(c.y instanceof iw&&a instanceof jw&&(a=a.mb,a instanceof L&&(a=a.k,a instanceof Ud)))return this.Dw(a.fa,b);a=c.w;if(c.y instanceof\niw&&a instanceof jw&&(a=a.mb,a=a instanceof L&&a.k instanceof fe?!0:t().d===a?!0:!1,a))return!1;e=c.y;a=c.w;if(e instanceof iw&&(g=e.me,e=e.Ne,a instanceof iw))return c=a.Ne,Pe(new E(g),a.me)?(a=Xu().X(),Fw(e,c,b,a)):!1;e=c.y;g=c.w;if(e instanceof jw&&(h=e.Xb,a=e.mb,e=e.Dc,g instanceof jw)){d=g.Xb;c=g.mb;g=g.Dc;a:{for(;!h.b();){var k=h.e();b:{for(var l=d;!l.b();){var m=l.e().uo();if(Pe(new E(m),k.uo())){k=!0;break b}l=l.f()}k=!1}if(!k){d=!1;break a}h=h.f()}d=!0}if(d){d=!0;for(e=e.m();d&&e.s();){d=\ne.t();if(null===d)throw new w(d);d=d.j();k=!1;for(h=g.m();!k&&h.s();){k=h.t();if(null===k)throw new w(k);k=k.j();l=Xu().X();k=Zu(d,k,b,!0,l)}d=k}g=d}else g=!1;return g?a instanceof L&&(g=a.k,g instanceof fe&&(g=g.aa,c instanceof L&&(c=c.k,c instanceof fe)))?(a=c.aa,c=Xu().X(),Zu(g,a,b,!0,c)):t().d===a?!0:!1:!1}b=c.y;if(lw(this.Aa)===b)return!0;b=c.w;if(lw(this.Aa)===b)return!1;throw new w(c);};function Gw(a){return lw(a.Aa)===a}\nfunction wba(a){var b=tf(a.cd),c=a.ne,d=a.jg,e=1+b.da|0,g=Hw(),h=Su(),k=op().ga;g=g.Hd(new Uu(h,k));e=new Iw(b.S,b.Ec,b.hc,b.Ed,e,b.Pc,b.Zc,b.Lb,b.yc,b.tb,b.$a,b.od,g);Jw(e,Kw(a));if(Pe(new E(a.LE),!0)){Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Unhandled cyclic parent specification\"]))),u()),a.Ab.A(),a.ne);var l=O().c}else try{a.LE=!0;var m=Mw(a);for(h=g=null;m!==u();){var n=m.e();a:{if(null!==n){var r=n.hv,v=n.qt,x=n.kr,A=n.iv,B=n.jv;if(null!==v){var C=v.x,D=a.J.qa,F=a.J;if(F.F){var I=ut(Q(),\"| \",F.r)+(e.da+\n\". Typing parent spec \")+r;ff(gf(),I+\"\\n\")}F.r=1+F.r|0;try{var M=x.fQ(a.ne);if(M instanceof Nw){k=M;var N=A.b()?t().d:(t(),new L(A)),P=a.ne,T=Ow(a),Y=Pw(a,k,v,N,e,P,T);if(null===Y)throw new w(Y);var Z=Y.h(),S=a.cd,ea=Qw(k,M.Ea(),!1,S,Z),ia=jv(B,ea.Tl);if(Nm(new E(ia),0)){var X=a.J,sa=new Te(new Ue(J(new K,[\"mixin \",\" expects \",\" parameter(s); got \",\"\"]))),Ja=We(Xe(),C);Xe();var Xa=ea.Tl.K(),Fa=We(0,\"\"+Xa);Xe();var za=B.K(),Qa=[Ja,Fa,We(0,\"\"+za)],Ma=Ye(sa,J(new K,Qa));cu();var Ga=op(),ab=B.Gb(Ga.ga).j();\nLw(X,Ma,du(0,new z(v,ab)),a.ne)}var Hb=ea.Tl,bc=new Wq(Hb,Hb,B),yb=new fn(((Ab,Ob)=>(fb,Wa)=>{var bb=G(new H,fb,Wa);fb=bb.y;var Ia=bb.w;if(null!==fb&&(Wa=new L(fb),!Wa.b()&&(fb=Wa.k.h(),Wa=Wa.k.j(),null!==Ia&&(Ia=new L(Ia),!Ia.b())))){var Ua=Ia.k.j();if(null!==Ua&&(Ia=Ua.yb,Ua=Ua.ya,null!==Ia)){bb=Ia.ch;var pc=Ia.Bh;if(Ia.je||bb||pc)throw new Yj(\"assertion failed: TODO\");bb=Rw(a.J,Ua,Ab,a.ne,Ow(a),!0);Ia=Wa.Oa;if(!Ia.b()){Ia=Ia.o();Ua=a.ne;pc=a.jg;var sc=Sw(a.J).ob;Tw(a.J,Ia,bb,Ua,pc,Ab,sc)}Ia=Wa.ra;\nUa=a.ne;pc=a.jg;sc=Sw(a.J).ob;Tw(a.J,bb,Ia,Ua,pc,Ab,sc);Ia=Ob.Jj.n(fb.x).Mp();Wa=Wa.Oa.b()?new Uw(a.J,Wa.Oa,bb,V(a.J)):new Uw(a.J,Wa.Oa,Wa.ra,V(a.J));return iu(ju(),Ia?new L(new Vw(a.J,fb,Wa,Ia,Ab.da)):R())}}throw new w(bb);})(e,ea));Yq();var tb=Zq(bc,yb),eb=a.J;if(eb.F){var kb=ut(Q(),\"| \",eb.r)+\"Mixin arg members \"+tb;ff(gf(),kb+\"\\n\")}t();var Rb=new Gp(ea,tb,nf(),r.A()),Gb=new L(Rb)}else if(M instanceof Ww){k=M;B.b()||Lw(a.J,Ye(new Te(new Ue(J(new K,[\"trait arguments are not yet supported\"]))),u()),\nr.A(),a.ne);var vb=A.b()?t().d:(t(),new L(A)),Tb=a.ne,Nb=Ow(a),ic=Pw(a,k,v,vb,e,Tb,Nb);if(null===ic)throw new w(ic);var Va=ic.h(),cb=ic.j(),zb=a.cd,Ub=Xw(k,M.Ea(),!1,zb,Va),jb=O().c;t();var db=new Gp(Ub,jb,cb.bf(Ub.Vm),r.A());Gb=new L(db)}else if(M instanceof Yw){k=M;var ub=A.b()?t().d:(t(),new L(A)),Aa=a.ne,va=Ow(a),Ra=Pw(a,k,v,ub,e,Aa,va);if(null===Ra)throw new w(Ra);var rb=Ra.h(),xb=Ra.j(),mc=a.cd,Ha=Zw(k,M.Ea(),!1,mc,rb),Ka=Ha.gl;if(Ka instanceof L){var Oa=Ka.k;$w(a,Oa.K(),B,C,v);var Na=new Wq(Oa,\nOa,B),Da=new fn((Ab=>(Ob,fb)=>{fb=G(new H,Ob,fb);a:{Ob=fb.y;var Wa=fb.w;if(null!==Ob&&(Ob=new L(Ob),!Ob.b()&&(Ob=Ob.k.j(),null!==Wa&&(Wa=new L(Wa),!Wa.b())))){var bb=Wa.k.j();if(null!==bb&&(Wa=bb.yb,bb=bb.ya,null!==Wa)){fb=Wa.ch;var Ia=Wa.Bh;if(Wa.je||fb||Ia)throw new Yj(\"assertion failed: TODO\");fb=Rw(a.J,bb,Ab,a.ne,Ow(a),!0);Wa=a.ne;bb=a.jg;Ia=Sw(a.J).ob;Tw(a.J,fb,Ob,Wa,bb,Ab,Ia);break a}}throw new w(fb);}})(e));Yq();Ew(Na,Da);var ta=O().c}else{if(t().d!==Ka)throw new w(Ka);var Ya=Ha.Ij;if(Ya instanceof\nL){var dc=Ya.k;$w(a,dc.K(),B,C,v);var ka=new Wq(dc,dc,B),ya=new fn(((Ab,Ob)=>(fb,Wa)=>{var bb=G(new H,fb,Wa);fb=bb.y;var Ia=bb.w;if(null!==fb&&(Wa=new L(fb),!Wa.b()&&(fb=Wa.k.h(),Wa=Wa.k.j(),null!==Ia&&(Ia=new L(Ia),!Ia.b())))){var Ua=Ia.k.j();if(null!==Ua&&(Ia=Ua.yb,Ua=Ua.ya,null!==Ia)){bb=Ia.ch;var pc=Ia.Bh;if(Ia.je||bb||pc)throw new Yj(\"assertion failed: TODO\");bb=Rw(a.J,Ua,Ab,a.ne,Ow(a),!0);Ia=Wa.Oa;if(!Ia.b()){Ia=Ia.o();Ua=a.ne;pc=a.jg;var sc=Sw(a.J).ob;Tw(a.J,Ia,bb,Ua,pc,Ab,sc)}Ia=Wa.ra;Ua=\na.ne;pc=a.jg;sc=Sw(a.J).ob;Tw(a.J,bb,Ia,Ua,pc,Ab,sc);Ia=Ob.Ei.n(fb.x).Mp();Wa=Wa.Oa.b()?new Uw(a.J,Wa.Oa,bb,V(a.J)):new Uw(a.J,Wa.Oa,Wa.ra,V(a.J));return iu(ju(),Ia?new L(new Vw(a.J,fb,Wa,Ia,Ab.da)):R())}}throw new w(bb);})(e,Ha));Yq();ta=Zq(ka,ya)}else{if(t().d!==Ya)throw new w(Ya);$w(a,0,B,C,v);ta=O().c}}var Sa=a.J;if(Sa.F){var xc=ut(Q(),\"| \",Sa.r)+\"Class arg members \"+ta;ff(gf(),xc+\"\\n\")}t();var Sb=new Gp(Ha,ta,xb.bf(Ha.Tm),r.A());Gb=new L(Sb)}else if(M instanceof ax)Lw(a.J,Ye(new Te(new Ue(J(new K,\n[\"Cannot inherit from a type alias\"]))),u()),r.A(),a.ne),Gb=t().d;else if(M instanceof Vw)Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Cannot inherit from a parameter\"]))),u()),r.A(),a.ne),Gb=t().d;else if(M instanceof bx)Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Cannot inherit from a function\"]))),u()),r.A(),a.ne),Gb=t().d;else if(M instanceof cx)Gb=t().d;else throw new w(M);}finally{F.r=-1+F.r|0}if(dx(new E(D),F.qa)&&F.F){var uc=\"\"+ut(Q(),\"| \",F.r)+D.n(Gb);ff(gf(),uc+\"\\n\")}var Lb=Gb;break a}}throw new w(n);}for(var lc=\nLb.m();lc.s();){var Xb=new z(lc.t(),u());null===h?g=Xb:h.p=Xb;h=Xb}m=m.f()}l=null===g?u():g}finally{a.LE=!1}m=e.cb;up(tp(),b.S.li||e.cb.b());if(!m.b()){n=b.S.qa;Lb=b.S;Lb.F&&(r=ut(Q(),\"| \",Lb.r)+\"UNSTASHING... (out)\",ff(gf(),r+\"\\n\"));Lb.r=1+Lb.r|0;try{m.Ca(new y(Ab=>{if(null!==Ab){var Ob=Ab.h();for(Ab=Ab.j().m();Ab.s();){var fb=Ab.t();a:{if(null!==fb){var Wa=fb.j();if(!0===fb.Rc()){fb=Sw(b.S).ob;Tw(b.S,Wa,Ob,c,d,b,fb);break a}}if(null!==fb&&(Wa=fb.j(),!1===fb.Rc())){fb=Sw(b.S).ob;Tw(b.S,Ob,Wa,c,d,\nb,fb);break a}throw new w(fb);}}}else throw new w(Ab);}));m.mg();var ec=void 0}finally{Lb.r=-1+Lb.r|0}dx(new E(n),Lb.qa)&&Lb.F&&(ec=\"\"+ut(Q(),\"| \",Lb.r)+n.n(ec),ff(gf(),ec+\"\\n\"))}return l}\nvar xba=function ex(a,b,c){var e=O().c;if(null===e?null===b:e.i(b))return c;if(b instanceof z){var g=b.z;e=b.p;if(null!==g){var h=g.qt;g=g.kr;if(null!==h){b=h.x;h=!1;var k=null;if(g instanceof fx){h=g.Qu;if(Fp()===h||Bp()===h||zp()===h)return tp(),b=gq(new Ep(b)),g=gx(g),c=b.Ce(g).Ce(c),ex(a,e,c);if(hx()===h||cp()===h||Ap()===h)return ex(a,e,c);throw new w(h);}if(g instanceof ix){h=!0;k=g;var l=k.kh;if(l instanceof Ww)return tp(),c=gq(new Ep(b)).Ce(l.Gq).Ce(c),ex(a,e,c)}if(h&&(l=k.kh,l instanceof\nYw))return tp(),c=gq(new Ep(b)).Ce(l.ip).Ce(c),ex(a,e,c);if(h&&(k.kh instanceof Vw||k.kh instanceof bx||k.kh instanceof ax||k.kh instanceof Nw||k.kh instanceof cx))return ex(a,e,c);throw new w(g);}}}throw new w(b);};\nfunction yba(a){var b=tf(a.cd),c=a.ne,d=a.jg,e=1+b.da|0,g=Hw(),h=Su(),k=op().ga;g=g.Hd(new Uu(h,k));var l=new Iw(b.S,b.Ec,b.hc,b.Ed,e,b.Pc,b.Zc,b.Lb,b.yc,b.tb,b.$a,b.od,g);e=a.Ab;if(e instanceof yo)if(k=e.hg,e=r=>{var v=r.j(),x=a.J,A=a.J,B=r.j().A();t();A=jx(new kx,A,B,\"type parameter\",new L(r.j().V),!0);B=t().d;t();var C=new L(r.j().V),D=O().c,F=O().c;return new tl(v,new lx(x,l.da,D,F,B,C,!1,A),r.h())},k===u())e=u();else{g=k.e();h=g=new z(e(g),u());for(k=k.f();k!==u();){var m=k.e();m=new z(e(m),\nu());h=h.p=m;k=k.f()}e=g}else{if(!(e instanceof Zn))throw new w(e);k=e.Ch;e=r=>{var v=a.J,x=a.J,A=r.A();t();x=jx(new kx,x,A,\"method type parameter\",new L(r.V),!0);A=t().d;t();var B=new L(r.V),C=O().c,D=O().c;return new tl(r,new lx(v,l.da,C,D,A,B,!1,x),t().d)};if(k===u())e=u();else{g=k.e();h=g=new z(e(g),u());for(k=k.f();k!==u();)m=k.e(),m=new z(e(m),u()),h=h.p=m,k=k.f();e=g}}g=l.cb;up(tp(),b.S.li||l.cb.b());if(!g.b()){h=b.S.qa;k=b.S;k.F&&(m=ut(Q(),\"| \",k.r)+\"UNSTASHING... (out)\",ff(gf(),m+\"\\n\"));\nk.r=1+k.r|0;try{g.Ca(new y(r=>{if(null!==r){var v=r.h();for(r=r.j().m();r.s();){var x=r.t();a:{if(null!==x){var A=x.j();if(!0===x.Rc()){x=Sw(b.S).ob;Tw(b.S,A,v,c,d,b,x);break a}}if(null!==x&&(A=x.j(),!1===x.Rc())){x=Sw(b.S).ob;Tw(b.S,v,A,c,d,b,x);break a}throw new w(x);}}}else throw new w(r);}));g.mg();var n=void 0}finally{k.r=-1+k.r|0}dx(new E(h),k.qa)&&k.F&&(n=\"\"+ut(Q(),\"| \",k.r)+h.n(n),ff(gf(),n+\"\\n\"))}return e}\nfunction zba(a){var b=a.Ag(),c=h=>{if(null!==h){var k=h.hb;return G(new H,h.kc.V,new mx(a.J,k,k.ji))}throw new w(h);};if(b===u())return u();var d=b.e(),e=d=new z(c(d),u());for(b=b.f();b!==u();){var g=b.e();g=new z(c(g),u());e=e.p=g;b=b.f()}return d}function Aba(a){var b=Xu();a=a.Ag().m();return b.Ib(new Ef(a,new y(c=>{var d=c.hb;c=c.Rd;c=c.b()?ou().Yl:c.o();return G(new H,d,c)})))}\nfunction Bba(a){var b=tf(a.cd),c=a.ne,d=a.jg,e=1+b.da|0,g=Hw(),h=Su(),k=op().ga;g=g.Hd(new Uu(h,k));e=new Iw(b.S,b.Ec,b.hc,b.Ed,e,b.Pc,b.Zc,b.Lb,b.yc,b.tb,b.$a,b.od,g);g=a.Ab;if(g instanceof yo)if(h=g.Sg,h.b())a=R();else{h=h.o().Ra;for(var l=k=null;h!==u();){var m=h.e();a:{if(null!==m){var n=m.h(),r=m.j();if(n instanceof L&&(n=n.k,null!==r)){var v=r.yb;r=r.ya;if(null!==v){m=v.ch;if(v.je||m)throw new Yj(\"assertion failed: TODO\");m=nx(r,a.ne);m=ox(a.J,m,e,a.ne,Ow(a),a.dt);v=a.J;r=t().d;m=new Uw(v,r,\nm,V(a.J));m=G(new H,n,m);n=O().c;m=new z(m,n);break a}}}if(null!==m&&(v=m.h(),n=m.j(),t().d===v&&null!==n&&(v=n.yb,r=n.ya,null!==v&&(n=v.je,v=v.ch,r instanceof vl)))){m=r;if(n||v)throw new Yj(\"assertion failed: TODO\");n=a.J;v=t().d;r=a.J;var x=new Te(new Ue(J(new K,[\"\",\" parameters currently need type annotations\"])));Xe();Q();var A=[We(0,Nu(0,g.pb.ld))];r=Lw(r,Ye(x,J(new K,A)),m.A(),a.ne);n=new Uw(n,v,r,V(a.J));m=G(new H,m,n);n=O().c;m=new z(m,n);break a}if(null!==m)m=m.j(),Lw(a.J,Ye(new Te(new Ue(J(new K,\n[\"Unsupported field specification\"]))),u()),m.A(),a.ne),m=O().c;else throw new w(m);}for(m=m.m();m.s();)n=new z(m.t(),u()),null===l?k=n:l.p=n,l=n;h=h.f()}a=new L(null===k?u():k)}else{if(!(g instanceof Zn))throw new w(g);a=t().d}g=e.cb;up(tp(),b.S.li||e.cb.b());if(!g.b()){e=b.S.qa;h=b.S;h.F&&(k=ut(Q(),\"| \",h.r)+\"UNSTASHING... (out)\",ff(gf(),k+\"\\n\"));h.r=1+h.r|0;try{g.Ca(new y(C=>{if(null!==C){var D=C.h();for(C=C.j().m();C.s();){var F=C.t();a:{if(null!==F){var I=F.j();if(!0===F.Rc()){F=Sw(b.S).ob;Tw(b.S,\nI,D,c,d,b,F);break a}}if(null!==F&&(I=F.j(),!1===F.Rc())){F=Sw(b.S).ob;Tw(b.S,D,I,c,d,b,F);break a}throw new w(F);}}}else throw new w(C);}));g.mg();var B=void 0}finally{h.r=-1+h.r|0}dx(new E(e),h.qa)&&h.F&&(B=\"\"+ut(Q(),\"| \",h.r)+e.n(B),ff(gf(),B+\"\\n\"))}return a}\nfunction Cba(a){var b=px(a),c=b.b()?O().c:b.o();b=h=>{var k=h.h().x;h=new qx(a.J,h.j().ra,h.h());return G(new H,k,h)};if(c===u())return u();var d=c.e(),e=d=new z(b(d),u());for(c=c.f();c!==u();){var g=c.e();g=new z(b(g),u());e=e.p=g;c=c.f()}return d}\nfunction Dba(a){var b=a.Ab;if(b instanceof yo){var c=tf(a.cd),d=a.ne,e=a.jg,g=1+c.da|0,h=Hw(),k=Su(),l=op().ga;h=h.Hd(new Uu(k,l));var m=new Iw(c.S,c.Ec,c.hc,c.Ed,g,c.Pc,c.Zc,c.Lb,c.yc,c.tb,c.$a,c.od,h);h=ef(b.ei);Od();g=new fp;Od();for(b=new fp;!h.b();){k=h.e();a:{if(k instanceof Zn){l=k;var n=l.Yc;if(n instanceof Ud&&(n=n.fa,!rx(l))){t();k=G(new H,l,n);k=new fe(k);break a}}t();k=new Ud(k)}if(k instanceof fe)wp(g,k.aa);else if(k instanceof Ud)wp(b,k.fa);else throw new w(k);h=h.f()}l=g.ha();b=Wn(b.ha(),\nnew sx(a));Jw(m,Kw(a));g=v=>{if(null!==v){var x=v.h();v=v.j();var A=a.ne,B=a.jg;Sw(m.S);var C=1+m.da|0,D=Hw(),F=Su(),I=op().ga;D=D.Hd(new Uu(F,I));var M=new Iw(m.S,m.Ec,m.hc,m.Ed,C,m.Pc,m.Zc,m.Lb,m.yc,m.tb,m.$a,m.od,D);C=Ow(a);var N=x.Ch;D=Y=>{var Z=Y.V,S=a.J,ea=a.J,ia=Y.A();t();ea=jx(new kx,ea,ia,\"method type parameter\",new L(Y.V),!0);ia=t().d;t();Y=new L(Y.V);var X=O().c,sa=O().c;S=new lx(S,M.da,X,sa,ia,Y,!1,ea);return G(new H,Z,S)};if(N===u())D=u();else{F=N.e();I=F=new z(D(F),u());for(N=N.f();N!==\nu();){var P=N.e();P=new z(D(P),u());I=I.p=P;N=N.f()}D=F}C=C.bf(D);C=ox(a.J,v,M,a.ne,C,a.dt);D=a.J;cu();v=jx(new kx,D,du(0,new z(v,new z(x.Rb,x.Ch))),\"signature of member `\"+x.Rb.x+\"`\",(tx(a.J),t().d),(tx(a.J),!1));v=ux(C.q,C,v);up(tp(),m.S.li||M.cb.b());Xu().X();C=vx(m.S);D=M.cb.m();D=new xo(D,new y(Y=>{if(null!==Y){var Z=Y.h();Y=Y.j().m();return new Ef(Y,new y(S=>{if(null!==S){var ea=S.Rc();S=S.j();up(tp(),S.Ea()>m.da);return ea?G(new H,S,Z):G(new H,Z,S)}throw new w(S);}))}throw new w(Y);}));Od();\nv=wx(C,Pd(u(),D),v);C=m.S;C.F&&(C=ut(Q(),\"| \",C.r)+(\"Inferred poly constr: \"+v+\"  \\u2014\\u2014 where \")+xx(v),ff(gf(),C+\"\\n\"));m.S.F&&Nm(new E(v),v)&&(C=m.S,C.F&&(C=ut(Q(),\"| \",C.r)+(\"Refreshed:            \"+v+\"  \\u2014\\u2014 where \")+xx(v),ff(gf(),C+\"\\n\")));v=yx(zx(m.S),m.da,v);M.cb.mg();C=M.cb;up(tp(),m.S.li||M.cb.b());if(!C.b()){D=m.S.qa;F=m.S;F.F&&(I=ut(Q(),\"| \",F.r)+\"UNSTASHING... (out)\",ff(gf(),I+\"\\n\"));F.r=1+F.r|0;try{C.Ca(new y(Y=>{if(null!==Y){var Z=Y.h();for(Y=Y.j().m();Y.s();){var S=Y.t();\na:{if(null!==S){var ea=S.j();if(!0===S.Rc()){S=Sw(m.S).ob;Tw(m.S,ea,Z,A,B,m,S);break a}}if(null!==S&&(ea=S.j(),!1===S.Rc())){S=Sw(m.S).ob;Tw(m.S,Z,ea,A,B,m,S);break a}throw new w(S);}}}else throw new w(Y);}));C.mg();var T=void 0}finally{F.r=-1+F.r|0}dx(new E(D),F.qa)&&F.F&&(T=\"\"+ut(Q(),\"| \",F.r)+D.n(T),ff(gf(),T+\"\\n\"))}return G(new H,x,v)}throw new w(v);};if(l===u())g=u();else{h=l.e();k=h=new z(g(h),u());for(l=l.f();l!==u();)n=l.e(),n=new z(g(n),u()),k=k.p=n,l=l.f();g=h}h=m.cb;up(tp(),c.S.li||m.cb.b());\nif(!h.b()){k=c.S.qa;l=c.S;l.F&&(n=ut(Q(),\"| \",l.r)+\"UNSTASHING... (out)\",ff(gf(),n+\"\\n\"));l.r=1+l.r|0;try{h.Ca(new y(v=>{if(null!==v){var x=v.h();for(v=v.j().m();v.s();){var A=v.t();a:{if(null!==A){var B=A.j();if(!0===A.Rc()){A=Sw(c.S).ob;Tw(c.S,B,x,d,e,c,A);break a}}if(null!==A&&(B=A.j(),!1===A.Rc())){A=Sw(c.S).ob;Tw(c.S,x,B,d,e,c,A);break a}throw new w(A);}}}else throw new w(v);}));h.mg();var r=void 0}finally{l.r=-1+l.r|0}dx(new E(k),l.qa)&&l.F&&(r=\"\"+ut(Q(),\"| \",l.r)+k.n(r),ff(gf(),r+\"\\n\"))}r=\ng}else{if(!(b instanceof Zn))throw new w(b);r=O().c;b=O().c}return G(new H,r,b)}function Eba(a){var b=Fba(a).m();b=new Ef(b,new y(d=>d.Rb.x));var c=Aq(Bq(),b);b=Ax(a).m();b=new Ef(b,new y(d=>{if(null!==d){var e=d.h(),g=e.Rb.x;d=new bx(a.J,1+a.Ru|0,e,d.j(),c.L(e.Rb.x));return G(new H,g,d)}throw new w(d);}));Od();return Pd(u(),b)}\nfunction Gba(a){var b=a.Ab;if(b instanceof yo)return a=Mw(a).m(),a=new xo(a,new y(c=>{c=c.kr;return c instanceof fx?Bx(c):c instanceof ix&&(c=c.kh,c instanceof Cx)?c.px:ap()})),Aq(Bq(),a);if(b instanceof Zn)return ap();throw new w(b);}\nfunction Hba(a){a=a.Ab;if(a instanceof yo)return a=(new Dx(a.Sg)).wF,a=(a.b()?O().c:a.o().Ra).m(),a=new xo(a,new y(b=>{if(null!==b){var c=b.h(),d=b.j();if(c instanceof L&&(c=c.k,null!==d))return d.yb.Bh?R():new L(c)}if(null!==b&&(c=b.h(),d=b.j(),t().d===c&&null!==d&&(c=d.yb,d=d.ya,d instanceof vl)))return c.Bh?R():new L(d);null!==b&&(d=b.h(),c=b.j(),t().d===d&&null!==c&&xm(\"Program reached and unexpected state.\"));throw new w(b);})),Aq(Bq(),a);if(a instanceof Zn)return ap();throw new w(a);}\nfunction Iba(a){var b=a.Ab;if(b instanceof yo){var c=b.Sg;c=(c.b()?new Gl(O().c):c.o()).Ra.m();c=new xo(c,new y(l=>l.h()));c=kv(c,new U(()=>{var l=ef(b.ei).m();return new Ex(l,new Fx(a))}));c=Aq(Bq(),c);var d=Gx(a);c=c.Ce(d);var e=a.Ag();d=l=>{if(null!==l){var m=l.kc;if(null!==m)return l=new vl(b.gb.V+\"#\"+m.V),m=m.A(),Cq(l,m)}throw new w(l);};if(e===u())d=u();else{var g=e.e(),h=g=new z(d(g),u());for(e=e.f();e!==u();){var k=e.e();k=new z(d(k),u());h=h.p=k;e=e.f()}d=g}return c.Ce(d)}if(b instanceof\nZn)return ap();throw new w(b);}\nfunction Jba(a){var b=px(a);b=b.b()?O().c:b.o();op();b=b.Ti();var c=Gx(a);b=b.dG(c);c=Ax(a).m();b=b.bf(new Ef(c,new y(k=>{var l=k.h().Rb;if(k.h().Om.b()){k=k.j();var m=V(a.J);k=new Uw(k.q,R(),k,m)}else m=a.J,t(),k=new Uw(m,new L(k.j()),k.j(),k.j().ma());return G(new H,l,k)})));c=Hx(a);for(var d=null,e=null;c!==u();){for(var g=c.e().oi.m();g.s();){var h=new z(g.t(),u());null===e?d=h:e.p=h;e=h}c=c.f()}c=null===d?u():d;for(e=d=null;c!==u();){h=c.e();a:{if(null!==h&&(g=h.h(),h=h.j(),h instanceof Vw)){g=\nnew vl(g);g=G(new H,g,h.ig);h=O().c;g=new z(g,h);break a}g=O().c}for(g=g.m();g.s();)h=new z(g.t(),u()),null===e?d=h:e.p=h,e=h;c=c.f()}return b.bf(null===d?u():d)}\nfunction Kba(a){var b=a.Ab;if(b instanceof Zn){var c=a.J;if(c.F){c=ut(Q(),\"| \",c.r);var d=b.Rb.x,e=Ix(b),g=a.cd.da,h=b.kx.b(),k=b.Qz;k.b()?k=!1:(k=k.o().CB(),k=dx(new E(k),cp()));ff(gf(),c+(\"Type \"+d+\" polymorphically? \"+e+\" \\x26\\x26 (\"+g+\" \\x3d\\x3d\\x3d 0 || \"+!h+\" || \")+k+\"\\n\")}if(Ix(b)){if(Pe(new E(a.cd.da),0)||!b.kx.b())return!0;a=b.Qz;if(a.b())return!1;a=a.o().CB();return dx(new E(a),cp())}return!1}xm(\"Program reached and unexpected state.\")}\nfunction Pw(a,b,c,d,e,g,h){var k=c.x;if(!d.b()){var l=d.o(),m=b.Ag(),n=l.K();m=m.ab(n);if(Nm(new E(m),0)){m=a.J;n=new Te(new Ue(J(new K,[\"\",\" \",\" expects \",\" type parameter(s); got \",\"\"])));var r=We(Xe(),b.fd().ld);k=We(Xe(),k);Xe();var v=b.Ag().K();v=We(0,\"\"+v);Xe();var x=l.K();r=[r,k,v,We(0,\"\"+x)];Lw(m,Ye(n,J(new K,r)),du(cu(),new z(c,l)),g)}}l=a.J;if(d.b())a=R();else{n=d.o();if(n===u())a=u();else{d=n.e();m=d=new z(ox(a.J,d,e,g,h,a.dt),u());for(n=n.f();n!==u();)r=n.e(),r=new z(ox(a.J,r,e,g,h,a.dt),\nu()),m=m.p=r,n=n.f();a=d}a=new L(a)}return Jx(l,b,c,a,e)}\nfunction Kx(a,b){var c=a.eo,d=new U(()=>a.ct?(Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Unhandled cyclic definition\"]))),u()),a.Ab.A(),b),new cx(a.J,a.Ab)):Lx(a.J,new U(()=>\"Completing \"+Mx(a.Ab)),new U(()=>{Nx(a.J,new U(()=>{var Ha=a.Ag();return\"Type params \"+ze(Ha,\"\",\" \",\"\")}));Nx(a.J,new U(()=>{var Ha=iu(ju(),px(a));return\"Params \"+ze(Ha,\"\",\" \",\"\")}));try{a.ct=!0;var e=a.Ab;if(e instanceof Zn){var g=!1,h=e.Yc;a:{if(h instanceof Ud){g=!0;var k=h.fa;if(k instanceof Vt){var l=k.Ws,m=k.Vs;Ox(a,e,b);var n=\nnew y(Ha=>{var Ka=Ow(a),Oa=Qt(l,new y(Na=>{if(Na instanceof fe){Na=Na.aa.V;var Da=a.J,ta=V(a.J),Ya=t().d,dc=t().d,ka=O().c,ya=O().c;Da=new lx(Da,1,ka,ya,Ya,dc,!1,ta);return G(new H,Na,Da)}xm(\"Program reached and unexpected state.\")}));op();Ka=Ka.bf(pp(qp(),Oa));Oa=nf();return ox(a.J,m,Ha,b,Ka,Oa)}),r=a.jg;Sw(a.cd.S);var v=Px(a.cd,n,b,r);var x=new bx(a.J,a.cd.da,e,new Qx(a.J,a.cd.da,v),!1);break a}}g&&xm(\"Program reached and unexpected state.\");if(h instanceof fe){var A=h.aa;e.wd.b()||Ox(a,e,b);var B=\n(Rx(a)?0:!e.wd.b())?!e.Pl:!1;if(Rx(a))var C=Sx(a.cd,new y(Ha=>{var Ka=e.Ch,Oa=Tx(a);Ka=jv(Ka,Oa);Ka=Pe(new E(Ka),0);Oa=new U(()=>G(new H,e.Ch,Tx(a)));if(!Ka)throw new Yj(\"assertion failed: \"+Es(Oa));Ka=Ow(a).bf(Tx(a));return(new y(Na=>Rw(a.J,A,Ha,b,Na,B))).n(Ka)}),b,a.jg);else if(e.Om.b())C=Rw(a.J,A,a.cd,b,Ow(a),B);else{var D=Rw(a.J,A,a.cd,b,Ow(a),B),F=Ux(a),I=a.jg,M=a.cd,N=Sw(a.J).ob;Tw(a.J,D,F,b,I,M,N);C=Ux(a)}var P=a.J,T=e.A(),Y=e.wd;if(Y instanceof L)var Z=e.Pl?\"value\":\"let binding\";else if(t().d===\nY)Z=\"method\";else throw new w(Y);var S=jx(new kx,P,T,\"definition of \"+Z+\" \"+e.Rb.x,(tx(a.J),t().d),(tx(a.J),!1));x=new bx(a.J,a.cd.da,e,ux(C.q,C,S),!0)}else throw new w(h);}Sx(a.cd,new y(Ha=>{var Ka=x.hh,Oa=Ux(a),Na=a.jg,Da=Sw(a.J).ob;Tw(a.J,Ka,Oa,b,Na,Ha,Da)}),b,a.jg);for(var ea=new y(Ha=>{Ha=Rw(a.J,Ha,a.cd,b,Ow(a),!1);var Ka=a.J.RE,Oa=a.jg,Na=a.cd,Da=Sw(a.J).ob;Tw(a.J,Ha,Ka,b,Oa,Na,Da)}),ia=e.Oz;!ia.b();)ea.n(ia.e()),ia=ia.f();var X=x}else if(e instanceof yo){if((Ot(new E(e.pb),zp())||Ot(new E(e.pb),\ncp()))&&!e.Qm.b()){g=a.J;var sa=new Te(new Ue(J(new K,[\"Explicit \",\" constructors are not supported\"]))),Ja=[We(Xe(),e.pb.ld)],Xa=Ye(sa,J(new K,Ja)),Fa=e.Qm,za=new U(()=>t().d),Qa=new y(Ha=>Ha.A());Lw(g,Xa,Fa.b()?Es(za):Qa.n(Fa.o()),b)}for(var Ma=new y(Ha=>{Ha=Rw(a.J,Ha,a.cd,b,Ow(a),!1);var Ka=a.J.RE,Oa=a.jg,Na=a.cd,Da=Sw(a.J).ob;Tw(a.J,Ha,Ka,b,Oa,Na,Da)}),Ga=e.Rz;!Ga.b();)Ma.n(Ga.e()),Ga=Ga.f();var ab=e.pb;if(Fp()===ab){var Hb=e.Sg;if(Hb instanceof L){var bc=Hb.k;Lw(a.J,Ye(new Te(new Ue(J(new K,\n[\"trait parameters are not yet supported\"]))),u()),bc.A(),b)}X=Sx(tf(a.cd),new y(Ha=>{Jw(Ha,Kw(a));Jw(Ha,Qt(Ax(a),new y(ya=>{var Sa=ya.h().Cf.x;ya=new qx(a.J,ya.j(),ya.h().Rb);return G(new H,Sa,ya)})));var Ka=new qx(a.J,Vx(a),new vl(\"this\"));Wx(Ha,G(new H,\"this\",Ka));Ka=Hx(a);var Oa=Xx(a.J,e,V(a.J),Ha),Na=O().c,Da=nf(),ta=e.Hj,Ya=new U(()=>a.J.La),dc=new y(()=>Yx(a,Ha,e,b));Ka=Lba(a,Ka,Oa,Na,Da,ta.b()?Es(Ya):dc.n(ta.o()),b,e);if(null!==Ka)Na=new Gp(Ka.Uj,Ka.oj,Ka.oi,Ka.Xi);else throw new w(Ka);Ka=\nNa.oj;Oa=Na.oi;Na=Na.Xi;ta=ef(e.ei);for(Da=new y(ya=>{if(ya instanceof Zn&&ya.Yc instanceof fe)return Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Method implementations in traits are not yet supported\"]))),u()),ya.A(),b)});!ta.b();)Da.n(ta.e()),ta=ta.f();var ka=of(a.J,e.ei,(t(),new L(e)),Ha,b,Ow(a));Da=Ka.m();Da=new Ef(Da,new y(ya=>{var Sa=ya.Ua();return G(new H,Sa,ya)}));Da=kv(Da,new U(()=>Qt(ka.xk,new y(ya=>{var Sa=ya.Ua();return G(new H,Sa,ya)})))).nb(new U(()=>Zx(a)));op();Da=pp(qp(),Da);$x(a,Qt(Zx(a),\nnew y(ya=>ya.j())),Ka,O().c,b,e);return new Ww(a.J,a.cd.da,e,a.Ag(),Da,a.J.La,Na,gx(a),Oa)}),b,a.jg)}else if(Ap()===ab){var yb=e.Sg,tb=new U(()=>new Gl(O().c));if(!(yb.b()?Es(tb):yb.o()).Ra.b()){var eb=a.J,kb=Ye(new Te(new Ue(J(new K,[\"Type alias definitions cannot have value parameters\"]))),u()),Rb=e.Sg,Gb=new U(()=>new Gl(O().c)),vb=(Rb.b()?Es(Gb):Rb.o()).A(),Tb=G(new H,kb,vb),Nb=O().c;ay(eb,new z(Tb,Nb),b)}if(!e.Di.b()){var ic=a.J,Va=Ye(new Te(new Ue(J(new K,[\"Type alias definitions cannot extend parents\"]))),\nu()),cb=du(cu(),e.Di),zb=G(new H,Va,cb),Ub=O().c;ay(ic,new z(zb,Ub),b)}var jb=e.Hj;if(jb instanceof L)var db=jb.k,ub=Sx(a.cd,new y(Ha=>ox(a.J,db,Ha,b,Ow(a),a.dt)),b,a.jg);else if(t().d===jb)ub=Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Type alias definition requires a right-hand side\"]))),u()),e.A(),b);else throw new w(jb);X=new ax(a.J,a.cd.da,e,a.Ag(),ub)}else if(Bp()===ab||zp()===ab)X=Sx(tf(a.cd),new y(Ha=>{var Ka=new $e;if(Ot(new E(e.pb),zp())&&!px(a).b()){var Oa=a.J,Na=new Te(new Ue(J(new K,[\"\",\" parameters are not supported\"])));\nXe();Q();var Da=[We(0,Nu(0,e.pb.ld))];Na=Ye(Na,J(new K,Da));Da=px(a);var ta=new U(()=>e.gb.A()),Ya=new y(Ba=>{cu();Ba=Ba.m();return du(0,new Ef(Ba,new y(ob=>ob.h())))});Lw(Oa,Na,Da.b()?Es(ta):Ya.n(Da.o()),b)}if(e.Pm.b()&&e.fl.b())if(Oa=e.Hj,Oa instanceof L)Na=Oa.k,Oa=a.J,Da=new Te(new Ue(J(new K,[\"Self-type annotations have no effects on non-abstract \",\" definitions\"]))),ta=[We(Xe(),e.pb.ld)],Da=Ye(Da,J(new K,ta)),Na=Na.A(),Na=G(new H,Da,Na),Da=Ye(new Te(new Ue(J(new K,[\"Did you mean to use `extends` and inherit from a parent class?\"]))),\nu()),ta=t().d,Da=G(new H,Da,ta),ta=O().c,by(Oa,new z(Na,new z(Da,ta)),b);else if(t().d!==Oa)throw new w(Oa);Jw(Ha,Kw(a));Jw(Ha,Qt(Ax(a),new y(Ba=>{var ob=Ba.h().Cf.x;Ba=new qx(a.J,Ba.j(),Ba.h().Rb);return G(new H,ob,Ba)})));Oa=e.Hj;Na=new U(()=>a.J.La);Da=new y(()=>Yx(a,Ha,e,b));Oa=Oa.b()?Es(Na):Da.n(Oa.o());Na=a.J;Da=a.Ab.A();Na=jx(new kx,Na,Da,cy(a.Ab),(tx(a.J),t().d),(tx(a.J),!1));Da=Vx(a);ta=Qt(a.Ag(),new y(Ba=>{if(null!==Ba){var ob=Ba.kc;Ba=Ba.hb;var nc=e.gb.V+\"#\"+ob.V,Ib=new mx(a.J,Ba,Ba.ji),\nvc=a.J;nc=new Ep(nc);ob=ob.A();return new Vw(vc,Cq(nc,ob),new Uw(a.J,(t(),new L(Ib)),Ib,Ba.ji),!0,Ha.da)}throw new w(Ba);}));var dc=Qt(ta,new y(Ba=>{var ob=Ba.ij.Zr();return G(new H,ob,Ba.ig)}));Ya=px(a);var ka=new y(Ba=>{Ba=dy(lv(),Ba);var ob=dy(lv(),dc);ob=Aq(Bq(),ob);return ey(Ba,ob)});Ya=!(!Ya.b()&&ka.n(Ya.o()));ka=new U(()=>{no()});if(!Ya)throw new Yj(\"assertion failed: \"+Es(ka));Ya=a.J;ka=O().c;var ya=a.J,Sa=du(cu(),e.Di),xc=new y(Ba=>vs(Ba));Ya=new Qv(Ya,ka,jx(new kx,ya,Sa.b()?R():new L(xc.n(Sa.o())),\n\"Object\",(tx(a.J),t().d),(tx(a.J),!1)));ka=px(a);ya=new U(()=>O().c);ka=Qt(ka.b()?Es(ya):ka.o(),new y(Ba=>new Vw(a.J,Ba.h(),Ba.j(),!fy(a).L(Ba.h()),Ha.da)));Ka=Mba(a,Hx(a),Nba(Ka.sb?Ka.vb:Oba(a,Ka),Ya,un(ta,ka),t().d,O().c,O().c,nf(),Oa),Da,Ha,b,Na,e,dc,Oa);if(null!==Ka)Da=new bo(Ka.Eq,Ka.Os,Ka.Gu,Ka.Qs,Ka.Ps,Ka.Rm);else throw new w(Ka);ta=Da.lr;var Sb=Da.mr,uc=Da.rt,Lb=Da.st;Ka=Da.tt;Da=Da.kv;Ya=new qx(a.J,Vx(a),new vl(\"this\"));Wx(Ha,G(new H,\"this\",Ya));ta=new qx(a.J,ta,new vl(\"super\"));Wx(Ha,G(new H,\n\"super\",ta));ta=of(a.J,e.ei,(t(),new L(e)),Ha,b,Ow(a));Ya=uc.BK(new y(Ba=>Ba.tr()));if(null!==Ya)Ya=G(new H,Ya.h(),Ya.j());else throw new w(Ya);var lc=Ya.h();Nx(a.J,new U(()=>\"baseClsImplemMembers \"+lc));var Xb=ta.xk,ec=Qt(Zx(a),new y(Ba=>Ba.j()));Lx(a.J,new U(()=>\"Checking `this` accesses...\"),new U(()=>{var Ba=gy(Xb,new y(Vb=>Vb.tr()),!1),ob=ef(e.ei);ob=gy(ob,new y(Vb=>!(Vb instanceof Ct)),!1);var nc=e.Qm,Ib=new U(()=>O().c),vc=new y(Vb=>Vb.js.Dj);nc=nc.b()?Es(Ib):vc.n(nc.o());Pba(a,Ba,un(ob,nc),\nuc,ec,b)}),a.J.qa);ta=Xb.m().nb(new U(()=>Sb));ta=new Ef(ta,new y(Ba=>Ba.Ua()));var Ab=Aq(Bq(),ta);ta=lc.m();ta=new hy(ta,new y(Ba=>Ba.Ua()));ta=new iy(ta,new y(Ba=>Ab.L(Ba.Ua())),!0);Od();var Ob=Pd(u(),ta);Lx(a.J,new U(()=>\"Checking base class implementations against inherited signatures...\"),new U(()=>{$x(a,Ob,Lb,O().c,b,e)}),a.J.qa);var fb=jy(a,uc,Lb,e,b);ta=Xb.m().nb(new U(()=>Sb));ta=new hy(ta,new y(Ba=>Ba.Ua()));Od();var Wa=Pd(u(),ta);Lx(a.J,new U(()=>\"Checking new implementations against inherited signatures...\"),\nnew U(()=>{var Ba=ec.m().nb(new U(()=>fb));Ba=new hy(Ba,new y(ob=>ob.Ua()));Od();$x(a,Wa,Pd(u(),Ba),ec,b,e)}),a.J.qa);ta=un(un(Xb,Sb),lc);var bb=ky(ta,new y(Ba=>Ba.Ua()));Lx(a.J,new U(()=>\"Checking new signatures against inherited signatures...\"),new U(()=>{$x(a,ec,fb,ec,b,e)}),a.J.qa);Lx(a.J,new U(()=>\"Checking signature implementations...\"),new U(()=>{var Ba=ec.m().nb(new U(()=>fb.m()));Ba=new hy(Ba,new y(ob=>ob.Ua()));Ba=new iy(Ba,new y(ob=>ob.tr()),!0);Od();ly(a,bb,Pd(u(),Ba),e,b)}),a.J.qa);ta=\nQt(un(fb,bb),new y(Ba=>{var ob=Ba.Ua();return G(new H,ob,Ba)}));op();var Ia=pp(qp(),ta).bf(Zx(a));Nx(a.J,new U(()=>\"allMembers \"+Ia));ta=e.Qm;a:{if(ta instanceof L){var Ua=ta.k;if(null!==Ua){var pc=Ua.ks,sc=Ua.js;ya=Sx(tf(a.cd),new y(Ba=>{for(var ob=Qt(pc.Ra,new y(Pb=>{if(null!==Pb){var Jb=Pb.h(),gc=Pb.j();if(Jb instanceof L&&(Jb=Jb.k,null!==gc)){var Cb=gc.yb;gc=gc.ya;if(null!==Cb){var cc=Cb.ch,yc=Cb.Bh,Mc=new U(()=>\"TODO\");if(Cb.je||cc)throw new Yj(\"assertion failed: \"+Es(Mc));yc&&my(a,Jb.A(),b);\nCb=Qn(gc);if(Cb instanceof Ud)return Pb=ox(a.J,Cb.fa,Ba,b,Ow(a),a.dt),G(new H,Jb,Pb);no()}}}if(null!==Pb&&(Cb=Pb.h(),Jb=Pb.j(),t().d===Cb&&null!==Jb&&(cc=Jb.yb,Jb=Jb.ya,null!==cc&&(Cb=cc.je,gc=cc.ch,cc=cc.Bh,Jb instanceof vl)))){Pb=new U(()=>\"TODO\");if(Cb||gc)throw new Yj(\"assertion failed: \"+Es(Pb));cc&&my(a,Jb.A(),b);Pb=a.J;Cb=ny(a.J,Jb,!1);gc=t().d;t();cc=new L(Jb.x);yc=O().c;Mc=O().c;Pb=new lx(Pb,Ba.da,yc,Mc,gc,cc,!1,Cb);return G(new H,Jb,Pb)}if(null!==Pb&&(Jb=Pb.h(),Cb=Pb.j(),t().d===Jb&&null!==\nCb))return Jb=Cb.ya,Pb=new vl(\"\\x3cerror\\x3e\"),Jb=Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Unsupported constructor parameter shape\"]))),u()),Jb.A(),b),G(new H,Pb,Jb);throw new w(Pb);})),nc=new y(Pb=>{if(null!==Pb){var Jb=Pb.h(),gc=Jb.x;Pb=new qx(a.J,Pb.j(),Jb);Wx(Ba,G(new H,gc,Pb))}else throw new w(Pb);}),Ib=ob;!Ib.b();)nc.n(Ib.e()),Ib=Ib.f();var vc=jx(new kx,a.J,Ua.A(),\"auxiliary class constructor\",(tx(a.J),t().d),(tx(a.J),!1));null!==sc?nc=sc.Dj:(nc=O().c,nc=new z(sc,nc));Ib=Xu();lv();var Vb=px(a),fc=\nnew U(()=>O().c);Vb=Vb.b()?Es(fc):Vb.o();var Bc=Ib.Ib(ry(0,Vb,it()));for(Ib=new y(Pb=>{if(Pb instanceof bm){var Jb=Pb.Vn,gc=Pb.Zo;return Bc.ou(Jb,new y(Cb=>{var cc=!1,yc=null;if(Cb instanceof L){cc=!0;yc=Cb;var Mc=yc.k;if(Mc instanceof L)return cc=Mc.k,Cb=Rw(a.J,gc,Ba,b,Ow(a),!1),cc=cc.ra,yc=Sw(a.J).ob,Tw(a.J,Cb,cc,b,vc,Ba,yc),cc=Jb.x,Cb=new qx(a.J,Cb,Jb),Wx(Ba,G(new H,cc,Cb)),t(),Cb=t().d,new L(Cb)}if(cc&&(cc=yc.k,t().d===cc))return Cb=a.J,cc=new Te(new Ue(J(new K,[\"Class parameter '\",\"' was already set\"]))),\nyc=[We(Xe(),Jb.x)],Lw(Cb,Ye(cc,J(new K,yc)),Jb.A(),b),t().d;if(t().d===Cb)return Cb=a.J,cc=new Te(new Ue(J(new K,[\"Unknown class parameter '\",\"'\"]))),yc=[We(Xe(),Jb.x)],Lw(Cb,Ye(cc,J(new K,yc)),Jb.A(),b),t().d;throw new w(Cb);}))}if(sy(Pb))return ty(a.J,Pb,!1,Ba,b,Ow(a),!1);xm(\"Program reached and unexpected state.\")});!nc.b();)Ib.n(nc.e()),nc=nc.f();t();return new L(ob)}),b,Na);break a}}if(t().d===ta)ya=t().d;else throw new w(ta);}Ia.og(new fn((Ba,ob)=>{Ba=G(new H,Ba,ob);var nc=Ba.y,Ib=Ba.w;if(Ib instanceof\nbx&&!Ib.Mb.Om.b()){var vc=uy(Ib.hh);if(!Ib.Mb.Yc.tv()&&Ib.Mb.kx.b())if(vc instanceof lx&&vc.Sb.b()){Ba=vy(vc);Ba=Qba(Ba,new fn((fc,Bc)=>{var Pb=V(fc.q);return dv(fc,Bc,Pb,!1)}));ob=new U(()=>{var fc=a.J,Bc=new Te(new Ue(J(new K,[\"Could not infer a type for unused mutable field \",\"\"]))),Pb=[We(Xe(),nc)];return Lw(fc,Ye(Bc,J(new K,Pb)),Ib.Mb.A(),b)});var Vb=Ba.b()?Es(ob):Ba.o();Nx(a.J,new U(()=>\"Setting type of \"+nc+\" based on inferred lower bounds: \"+vc+\" :\\x3d \"+Vb));wy(vc,(t(),new L(Vb)))}else xm(vc.u())}}));\nxy||(xy=new yy);Na=a.J;ta=a.cd.da;Ya=a.Ag();ka=px(a);Sa=new U(()=>{ju();var Ba=px(a).b()&&Ot(new E(e.pb),Bp())?!!e.Pm.b():!1;return zy(0,Ba,new U(()=>O().c))});ya=ya.b()?Es(Sa):ya;Oa=new Yw(Na,ta,e,Ya,ka,ya,Ia,a.J.La,e.Pm.b()?Oa:Da,gx(a),Ka);return Rba(Oa,new y(Ba=>Ay(Ba,Ha)))}),b,a.jg);else if(cp()===ab){if(!e.Di.b()){var Aa=a.J,va=Ye(new Te(new Ue(J(new K,[\"mixin definitions cannot yet extend parents\"]))),u()),Ra=du(cu(),e.Di),rb=G(new H,va,Ra),xb=O().c;ay(Aa,new z(rb,xb),b)}var mc=a.cd;X=Sx(tf(a.cd),\nnew y(Ha=>{Jw(Ha,Kw(a));Jw(Ha,Qt(Ax(a),new y(ya=>{var Sa=ya.h().Cf.x;ya=new qx(a.J,ya.j(),ya.h().Rb);return G(new H,Sa,ya)})));var Ka=px(a),Oa=new y(ya=>Qt(ya,new y(Sa=>{var xc=Sa.h().x;Sa=new Vw(a.J,Sa.h(),Sa.j(),!fy(a).L(Sa.h()),Ha.da);return G(new H,xc,Sa)})));Ka=Ka.b()?R():new L(Oa.n(Ka.o()));Oa=new U(()=>O().c);Ka=Ka.b()?Es(Oa):Ka.o();op();Ka=Ka.Ti();Oa=a.J;var Na=V(a.J),Da=t().d;t();var ta=new L(\"this\"),Ya=O().c,dc=O().c;Oa=new lx(Oa,Ha.da,Ya,dc,Da,ta,!1,Na);Na=a.J;Da=V(a.J);ta=t().d;t();Ya=\nnew L(\"super\");dc=O().c;var ka=O().c;Na=new lx(Na,Ha.da,dc,ka,ta,Ya,!1,Da);Da=new qx(a.J,Oa,new vl(\"this\"));Wx(Ha,G(new H,\"this\",Da));Da=new qx(a.J,Na,new vl(\"super\"));Wx(Ha,G(new H,\"super\",Da));Da=of(a.J,e.ei,(t(),new L(e)),Ha,b,Ow(a)).xk;ta=Qt(Zx(a),new y(ya=>ya.j()));$x(a,Da,ta,ta,b,e);ly(a,Da,ta,e,b);Da=Qt(Da,new y(ya=>{var Sa=ya.Ua();return G(new H,Sa,ya)}));op();Ka=Ka.bf(pp(qp(),Da)).bf(Zx(a));Da=a.J;ta=mc.da;Ya=a.Ag();dc=px(a);ka=new U(()=>O().c);return new Nw(Da,ta,e,Oa,Na,Ya,dc.b()?Es(ka):\ndc.o(),Ka)}),b,a.jg)}else throw new w(ab);}else throw new w(e);}finally{a.ct=!1}a.eo=(t(),new L(X));return X}),new y(e=>{var g=e.bG();var h=O().c;g=new By(g,new z(e,h),t().d);g=xx(g);return\"Completed \"+e+\" where \"+g})));return c.b()?Es(d):c.o()}\nfunction Cy(a,b,c,d){var e=a.Ab;if(e instanceof Zn){if(a.ct)return b=a.J,b.F&&(b=ut(Q(),\"| \",b.r)+\"Already computing! Using TV: \"+Ux(a),ff(gf(),b+\"\\n\")),Ux(a);a=Kx(a,d);if(a instanceof bx)return a.hh;xm(\"Program reached and unexpected state.\")}else if(e instanceof yo){if(e.Qm.b())return Dy(a.J,b,c,e,a.Ru,a.Ag(),px(a),t().d,gx(a),d);e=Kx(a,d);if(e instanceof Yw)return Dy(e.nc,b,c,e.Rf,e.Sm,e.gh,e.Ij,e.gl,0,d);if(e instanceof cx)return Ey(a.J);xm(\"Program reached and unexpected state.\")}else throw new w(e);\n}function $w(a,b,c,d,e){var g=c.ab(b);if(Nm(new E(g),0)){g=a.J;var h=new Te(new Ue(J(new K,[\"class \",\" expects \",\" parameter(s); got \",\"\"])));d=We(Xe(),d);b=We(Xe(),\"\"+b);Xe();var k=c.K();b=[d,b,We(0,\"\"+k)];h=Ye(h,J(new K,b));cu();b=op();c=c.Gb(b.ga).j();Lw(g,h,du(0,new z(e,c)),a.ne)}}function Ox(a,b,c){b.Ch.b()||Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Type parameters are not yet supported in this position\"]))),u()),b.Ch.e().A(),c)}\nfunction Fy(a,b){if(Gy(a.Mb))return!0;a=b.U(a.Ua());return a instanceof L&&(a=a.k,a instanceof bx)?!a.Mb.lx.b():!1}\nfunction Hy(a,b,c,d,e,g,h,k){var l=b.uE;if(l.b()){b=b.Uz;l=t().d;for(b=b.m();b.s();){var m=l;l=b.t();if(m.b())a:{if(m=c.U(l.h().x),m instanceof L&&(m=m.k,m instanceof bx)){if(d.b())var n=!0;else n=d.o(),n=Nm(new E(n),l.h().x);if(n&&!e.L(l.h().x)){n=l.j();if(n instanceof L&&(!g||Fy(m,h))){l=n;break a}m=Iy(m);t();l=Jy(a,m,new L(l.h().x),new z(l.h().x,e),!1,c,k,h);break a}}l=t().d}else l=m}return l}return l}\nfunction Jy(a,b,c,d,e,g,h,k){if(c.b())return Hy(a,b,g,c,d,e,k,h);var l=c.o();if(ca(h)!==da(Ky)){var m=h.U(l);if(m instanceof L)h=m.k;else{if(R()!==m)throw new w(m);a=Hy(a,b,g,c,d,e,k,h);Ly(h,l,a,!1);h=a}}else{m=My(W(),l);m^=m>>>16|0;var n=m&(-1+h.eb.a.length|0),r=h.eb.a[n];r=null===r?null:Ny(r,l,m);null!==r?h=r.Ah:(r=h.eb,a=Hy(a,b,g,c,d,e,k,h),(1+h.Xf|0)>=h.hu&&Oy(h,h.eb.a.length<<1),Py(h,l,a,!1,m,r===h.eb?n:m&(-1+h.eb.a.length|0)),h=a)}return h}\nfunction Qy(a,b,c,d,e,g){b.Uz.Ca(new y(h=>{if(h.j().b()){var k=d.U(h.h().x);if(k instanceof L){var l=k.k;if(l instanceof bx&&Fy(l,g)){k=a.J;var m=new Te(new Ue(J(new K,[\"Unqualified access to virtual member \",\"\"])));h=[We(Xe(),h.h().x)];h=Ye(m,J(new K,h));h=G(new H,h,c);m=Ye(new Te(new Ue(J(new K,[\"Declared here:\"]))),u());l=l.Mb.A();l=G(new H,m,l);m=O().c;return ay(k,new z(h,new z(l,m)),e)}}}}))}\nfunction Ry(a,b){var c=a.j(),d=b.j();if(c instanceof L&&(c=c.k,d instanceof L&&Sy(c,d.k)))return a=G(new H,a.h(),d),b=O().c,new z(a,b);d=O().c;return new z(a,new z(b,d))}\nfunction Pba(a,b,c,d,e,g){Ty();var h=u();h=Uy(h);var k=A=>{var B=A.Ua();return G(new H,B,A)};if(e===u())k=u();else{var l=e.e(),m=l=new z(k(l),u());for(e=e.f();e!==u();){var n=e.e();n=new z(k(n),u());m=m.p=n;e=e.f()}k=l}op();k=pp(qp(),k);d=d.m().nb(new U(()=>b));d=new Ef(d,new y(A=>{var B=A.Ua();return G(new H,B,A)}));op();d=k.bf(pp(qp(),d));for(l=b;!l.b();){m=l.e();if(m instanceof bx){var r=m;m=r.Mb;e=Iy(r);if(!m.wd.b()){t();n=r.Ua();n=new L(n);var v=r.Ua(),x=O().c;n=Jy(a,e,n,new z(v,x),!0,d,h,k);\nif(n instanceof L)v=n.k,n=a.J,x=new Te(new Ue(J(new K,[\"Cannot access `this` while initializing field \",\"\"]))),r=[We(Xe(),r.Ua())],r=Ye(x,J(new K,r)),x=m.A(),r=G(new H,r,x),x=Ye(new Te(new Ue(J(new K,[\"The access to `this` is here\"]))),u()),v=v.A(),ay(n,Ry(r,G(new H,x,v)),g);else if(t().d!==n)throw new w(n);}Qy(a,e,m.A(),d,g,k)}l=l.f()}for(;!c.b();){l=c.e();a:{if(l instanceof Cl&&(m=l.ai,m instanceof vl&&\"this\"===m.x))break a;m=Vy(a.J,l);e=Jy(a,m,t().d,O().c,!1,d,h,k);if(e instanceof L)n=e.k,e=a.J,\nr=Ye(new Te(new Ue(J(new K,[\"Cannot access `this` during object initialization\"]))),u()),v=l.A(),r=G(new H,r,v),v=Ye(new Te(new Ue(J(new K,[\"The access to `this` is here\"]))),u()),n=n.A(),ay(e,Ry(r,G(new H,v,n)),g);else if(t().d!==e)throw new w(e);Qy(a,m,l.A(),d,g,k)}c=c.f()}}\nfunction Wy(a,b,c,d,e){a=a.J;var g=new Te(new Ue(J(new K,[\"Member `\",\"` is declared (or its declaration is inherited) but is not implemented in `\",\"`\"]))),h=[We(Xe(),c.Ua()),We(Xe(),d.gb.V)];g=Ye(g,J(new K,h));d=d.gb.A();d=G(new H,g,d);g=Ye(new Te(new Ue(J(new K,[\"Declared here:\"]))),u());c=c.A();c=G(new H,g,c);ay(a,new z(d,new z(c,b)),e)}\nfunction ly(a,b,c,d,e){for(var g=Xu().X();!b.b();){var h=b.e();g.ou(h.Ua(),new y(((m,n,r)=>v=>{if(v instanceof L){v=a.J;var x=new Te(new Ue(J(new K,[\"Duplicated `\",\"` member definition in `\",\"`\"]))),A=[We(Xe(),m.Ua()),We(Xe(),n.Cf.x)];Lw(v,Ye(x,J(new K,A)),m.A(),r);return t().d}if(t().d===v)return t(),new L(m);throw new w(v);})(h,d,e)));b=b.f()}if(d.fl.b()&&Nm(new E(d.pb),Fp())&&d.Pm.b())for(;!c.b();){b=c.e();h=g.U(b.Ua());if(h instanceof L){if(h=h.k,!h.Mp()){var k=new Te(new Ue(J(new K,[\"Note: \",\n\" member `\",\"` is private and cannot be used as a valid implementation\"]))),l=[We(Xe(),h.fd().ld),We(Xe(),b.Ua())];k=Ye(k,J(new K,l));h=h.A();h=G(new H,k,h);k=O().c;Wy(a,new z(h,k),b,d,e)}}else if(t().d===h)Wy(a,O().c,b,d,e);else throw new w(h);c=c.f()}}\nfunction $x(a,b,c,d,e,g){var h=a.cd,k=a.jg,l=1+h.da|0,m=Hw(),n=Su(),r=op().ga;m=m.Hd(new Uu(n,r));l=new Iw(h.S,h.Ec,h.hc,h.Ed,l,h.Pc,h.Zc,h.Lb,h.yc,h.tb,h.$a,h.od,m);for(m=Xu().X();!c.b();)n=c.e(),m.ou(n.Ua(),new y((C=>D=>{if(D instanceof L)xm(\"Program reached and unexpected state.\");else{if(t().d===D)return t(),new L(C);throw new w(D);}})(n))),c=c.f();for(;!b.b();){c=b.e();n=a.J;n.F&&(n=ut(Q(),\"| \",n.r)+(\"Checking overriding for \"+c+\" against \"+m.U(c.Ua()))+\"...\",ff(gf(),n+\"\\n\"));r=G(new H,c,m.U(c.Ua()));\na:if(n=r.w,t().d!==n){n=r.y;var v=r.w;if(n&&n.$classData&&n.$classData.rb.xE&&v instanceof L&&(v=v.k)&&v.$classData&&v.$classData.rb.xE){c=v;if(!c.Mp())break a;if(c instanceof bx&&!Gy(c.Mb)&&!d.L(c)){r=a.J;v=new Te(new Ue(J(new K,[\"\",\" member '\",\"' is not virtual and cannot be overridden\"])));Xe();Q();var x=n.fd().ld;x=[We(0,Nu(0,x)),We(Xe(),n.Ua())];v=Ye(v,J(new K,x));n=n.A();n=G(new H,v,n);v=Ye(new Te(new Ue(J(new K,[\"Originally declared here:\"]))),u());c=c.A();c=G(new H,v,c);v=O().c;ay(r,new z(n,\nnew z(c,v)),e);break a}if(c instanceof Vw&&!d.L(c)){r=a.J;v=new Te(new Ue(J(new K,[\"Inherited parameter named '\",\"' is not virtual and cannot be overridden\"])));x=[We(Xe(),n.Ua())];v=Ye(v,J(new K,x));n=n.A();n=G(new H,v,n);v=Ye(new Te(new Ue(J(new K,[\"Originally declared here:\"]))),u());c=c.A();c=G(new H,v,c);v=O().c;ay(r,new z(n,new z(c,v)),e);break a}if(n instanceof bx&&rx(n.Mb)){r=a.J;v=new Te(new Ue(J(new K,[\"Cannot implement \",\" member '\",\"' with a let binding\"])));x=[We(Xe(),n.fd().ld),We(Xe(),\nn.Ua())];v=Ye(v,J(new K,x));x=n.A();v=G(new H,v,x);x=Ye(new Te(new Ue(J(new K,[\"Originally declared here:\"]))),u());var A=c.A();x=G(new H,x,A);A=O().c;ay(r,new z(v,new z(x,A)),e)}n=n.Nn();r=n.ma();c=c.Nn();v=Sw(a.J).ob;Tw(a.J,n,c,e,r,l,v);break a}n=r.w;if(n instanceof L)r=n.k,n=a.J,v=new Te(new Ue(J(new K,[\"\",\" member '\",\"' cannot override \",\" member of the same name declared in parent\"]))),Xe(),Q(),x=c.fd().ld,c=[We(0,Nu(0,x)),We(Xe(),c.Ua()),We(Xe(),r.fd().ld)],c=Ye(v,J(new K,c)),v=g.A(),c=G(new H,\nc,v),v=Ye(new Te(new Ue(J(new K,[\"Originally declared here:\"]))),u()),r=r.A(),r=G(new H,v,r),v=O().c,ay(n,new z(c,new z(r,v)),e);else throw new w(r);}b=b.f()}a=l.cb;up(tp(),h.S.li||l.cb.b());if(!a.b()){d=h.S.qa;g=h.S;g.F&&(l=ut(Q(),\"| \",g.r)+\"UNSTASHING... (out)\",ff(gf(),l+\"\\n\"));g.r=1+g.r|0;try{a.Ca(new y(C=>{if(null!==C){var D=C.h();for(C=C.j().m();C.s();){var F=C.t();a:{if(null!==F){var I=F.j();if(!0===F.Rc()){F=Sw(h.S).ob;Tw(h.S,I,D,e,k,h,F);break a}}if(null!==F&&(I=F.j(),!1===F.Rc())){F=Sw(h.S).ob;\nTw(h.S,D,I,e,k,h,F);break a}throw new w(F);}}}else throw new w(C);}));a.mg();var B=void 0}finally{g.r=-1+g.r|0}dx(new E(d),g.qa)&&g.F&&(B=\"\"+ut(Q(),\"| \",g.r)+d.n(B),ff(gf(),B+\"\\n\"))}}\nfunction Sba(a,b,c,d,e){var g=new y(B=>{var C=B.Ea();C=Pe(new E(C),b.Ea());var D=new U(()=>new Gu(b.Ea(),B.Ea()));if(!C)throw new Yj(\"assertion failed: \"+Es(D));});c.b()||g.n(c.o());g=G(new H,b,c);c=g.y;var h=g.w;if(c instanceof bx&&h instanceof L){var k=h.k;if(k instanceof bx){up(tp(),!(c.Ts&&k.Ts));d=G(new H,c.Mb.wd,k.Mb.wd);a:{e=d.y;d=d.w;if(e instanceof L&&(e=!!e.k,d instanceof L)){d=!!d.k;t();e=new L(e||d);break a}e=t().d}d=c.Mb.Rb;g=t().d;h=c.Mb.Ch;var l=c.Mb.Yc,m=c.Mb.Pz,n=c.Mb.lx,r=c.Mb.Om,\nv=t().d,x=c.Mb.Qz,A=new U(()=>k.Mb.Qz);e=new Zn(e,d,g,h,l,m,n,r,v,x.b()?Es(A):x,c.Mb.Pl,c.Mb.Oz);t();a=a.J;d=c.jp;g=c.hh;h=k.hh;l=V(c.hh.q);a=new bx(a,d,e,Pu(g,h,l,!1),c.Ts||k.Ts);return new L(a)}}c=g.y;h=g.w;if(c instanceof Vw&&h instanceof L&&(h=h.k,h instanceof Vw)){if(c.bo){if(h.bo)return t(),a=new Vw(a.J,c.ij,Nv(c.ig,h.ig,V(c.ig.Va)),!0,c.Tz),new L(a);t();return new L(c)}t();return new L(h)}c=g.y;h=g.w;if(c instanceof Vw&&h instanceof L&&(h=h.k,h instanceof bx))return t(),a=a.J,e=c.Tz,d=h.Mb,\ng=c.ig.ra,h=h.hh,c=V(c.ig.ra.q),a=new bx(a,e,d,Pu(g,h,c,!1),!0),new L(a);c=g.y;h=g.w;if(c instanceof bx&&h instanceof L&&(h=h.k,h instanceof Vw))return t(),a=a.J,e=c.jp,d=c.Mb,g=h.ig.ra,c=c.hh,h=V(h.ig.ra.q),a=new bx(a,e,d,Pu(g,c,h,!1),!0),new L(a);c=g.y;h=g.w;if(t().d===h)return t(),new L(c);h=g.y;c=g.w;if(c instanceof L)return c=c.k,a=a.J,g=new Te(new Ue(J(new K,[\"Intersection of \",\" member and \",\" members currently unsupported\"]))),l=[We(Xe(),h.fd().ld),We(Xe(),c.fd().ld)],g=Ye(g,J(new K,l)),d=\nd.A(),d=G(new H,g,d),g=new Te(new Ue(J(new K,[\"The \",\" member is defined here:\"]))),l=[We(Xe(),h.fd().ld)],g=Ye(g,J(new K,l)),h=h.A(),g=G(new H,g,h),h=new Te(new Ue(J(new K,[\"The \",\" member is defined here:\"]))),l=[We(Xe(),c.fd().ld)],h=Ye(h,J(new K,l)),c=c.A(),c=G(new H,h,c),h=O().c,ay(a,new z(d,new z(g,new z(c,h))),e),t().d;throw new w(g);}\nfunction jy(a,b,c,d,e){var g=m=>{var n=m.Ua();return G(new H,n,m)};if(c===u())g=u();else{var h=c.e(),k=h=new z(g(h),u());for(c=c.f();c!==u();){var l=c.e();l=new z(g(l),u());k=k.p=l;c=c.f()}g=h}op();for(g=pp(qp(),g);!b.b();)h=b.e(),g=g.IC(h.Ua(),new y(((m,n,r)=>v=>Sba(a,m,v,n,r))(h,d,e))),b=b.f();return g.tT().ha()}\nfunction Yx(a,b,c,d){var e=tf(b),g=a.jg,h=1+e.da|0,k=Hw(),l=Su(),m=op().ga;k=k.Hd(new Uu(l,m));h=new Iw(e.S,e.Ec,e.hc,e.Ed,h,e.Pc,e.Zc,e.Lb,e.yc,e.tb,e.$a,e.od,k);c=c.Hj;c=ox(a.J,c.b()?gl():c.o(),h,d,Ow(a),a.dt);k=Xu().X();c=c.Kc(b.da,!0,h,k);k=h.cb;up(tp(),e.S.li||h.cb.b());if(!k.b()){h=e.S.qa;l=e.S;l.F&&(m=ut(Q(),\"| \",l.r)+\"UNSTASHING... (out)\",ff(gf(),m+\"\\n\"));l.r=1+l.r|0;try{k.Ca(new y(v=>{if(null!==v){var x=v.h();for(v=v.j().m();v.s();){var A=v.t();a:{if(null!==A){var B=A.j();if(!0===A.Rc()){A=\nSw(e.S).ob;Tw(e.S,B,x,d,g,e,A);break a}}if(null!==A&&(B=A.j(),!1===A.Rc())){A=Sw(e.S).ob;Tw(e.S,x,B,d,g,e,A);break a}throw new w(A);}}}else throw new w(v);}));k.mg();var n=void 0}finally{l.r=-1+l.r|0}dx(new E(h),l.qa)&&l.F&&(n=\"\"+ut(Q(),\"| \",l.r)+h.n(n),ff(gf(),n+\"\\n\"))}n=a.J;h=V(a.J);k=t().d;l=t().d;m=O().c;var r=O().c;n=new lx(n,b.da,m,r,k,l,!1,h);h=a.jg;k=Sw(a.J).ob;Tw(a.J,c,n,d,h,b,k);b=vy(n);if(b instanceof z&&(a=b.z,b=b.p,c=O().c,null===c?null===b:c.i(b)))return a;xm(\"Program reached and unexpected state.\")}\nfunction Lba(a,b,c,d,e,g,h,k){for(;;){var l=!1,m=null,n=b;if(n instanceof z){l=!0;m=n;var r=m.z;b=m.p;if(null!==r){var v=r.Uj,x=r.oj;r=r.oi;if(v instanceof Ww){m=v;if(!x.b())throw new Yj(\"assertion failed: \"+x);n=a;l=c;x=m.uk;c=V(c.q);c=Pu(l,x,c,!1);l=new rp(m.tk);Od();d=jy(a,d,Pd(u(),l),k,h);e=e.bf(r);a=g;r=m.uk;g=V(g.q);g=Pu(a,r,g,!1);a=n;continue}}}if(l&&(b=m.z,r=m.p,null!==b)){b=b.Xi;Lw(a.J,Ye(new Te(new Ue(J(new K,[\"A trait can only inherit from other traits\"]))),u()),b,h);b=r;continue}h=O().c;\nif(null===h?null===n:h.i(n))return new Gp(c,d,e,g);throw new w(n);}}function Oba(a,b){if(null===b)throw le();return b.sb?b.vb:me(b,new Xy(a))}\nfunction Mba(a,b,c,d,e,g,h,k,l,m){for(var n=a;;){var r=b;if(r instanceof z){var v=r,x=v.z,A=v.p;if(null!==x){var B=x.Uj,C=x.oj,D=x.oi,F=x.Xi,I=n.J;if(I.F){var M=ut(Q(),\"| \",I.r)+\"\\x3d\\x3e Inheriting from \"+B;ff(gf(),M+\"\\n\")}if(B instanceof Nw){var N=B;up(tp(),Pe(new E(d.Xa),e.da));tp();var P=N.hl.Ea();up(0,Pe(new E(P),e.da));tp();var T=N.jl.Ea();up(0,Pe(new E(T),e.da));var Y=c.Eq,Z=N.hl,S=Sw(n.J).ob;Tw(n.J,Y,Z,g,h,e,S);var ea=N.jl,ia=Sw(n.J).ob;Tw(n.J,d,ea,g,h,e,ia);up(tp(),D.b());var X=N.Jj.ie(),\nsa=new iy(X,new y($a=>Yy($a)),!0),Ja=un(C,sa),Xa=n.J,Fa=c.Eq,za=n.J,Qa=Wn(Ja,new Zy(n)),Ma=new Qv(za,Qa,V(n.J)),Ga=new $y(Xa,Fa,Ma,V(n.J)),ab=n,Hb=c,bc=un(Ja,c.Os),yb=new az(Hb.Sz,Ga,bc,c.Hu,c.Gu,c.Qs,c.Ps,c.Rm);n=ab;b=A;c=yb;continue}else if(B instanceof Ww){var tb=B;if(!C.b())throw new Yj(\"assertion failed: \"+C);var eb=n,kb=n,Rb=c.Qs,Gb=tb.tk.ie(),vb=new iy(Gb,new y($a=>Yy($a)),!0);Od();var Tb=jy(kb,Rb,Pd(u(),vb),k,g),Nb=c.Ps.bf(D),ic=c.Rm,Va=tb.uk,cb=V(c.Rm.q),zb=Pu(ic,Va,cb,!1),Ub=new az(c.Sz,\nc.Eq,c.Os,c.Hu,c.Gu,Tb,Nb,zb);n=eb;b=A;c=Ub;continue}else if(B instanceof Yw){var jb=B,db=jb.Rf.gb.V,ub=c.Hu,Aa=n;if(!ub.b()){var va=ub.o(),Ra=Aa.J,rb=new Te(new Ue(J(new K,[\"Cannot inherit from more than one base class: \",\" and \",\"\"]))),xb=[We(Xe(),va),We(Xe(),db)];Lw(Ra,Ye(rb,J(new K,xb)),F,g)}var mc=jb.Ei.ie();Od();var Ha=Pd(u(),mc);if(Ha.b())var Ka=Od().jC;else{Od();var Oa=new fp;Od();for(var Na=new fp,Da=Ha.m();Da.s();){var ta=Da.t();wp(Yy(ta)?Oa:Na,ta)}var Ya=G(new H,Oa.ha(),Na.ha());var dc=\nYa.y;if(u().i(dc))Ka=G(new H,u(),Ha);else{var ka=Ya.w;Ka=u().i(ka)?G(new H,Ha,u()):Ya}}if(null===Ka)throw new w(Ka);var ya=n.J;if(ya.F){var Sa=ut(Q(),\"| \",ya.r)+\"argMembs \"+C;ff(gf(),Sa+\"\\n\")}var xc=n.J;if(xc.F){var Sb=ut(Q(),\"| \",xc.r)+\"selfSig \"+jb.sk;ff(gf(),Sb+\"\\n\")}var uc=n;t();var Lb=new L(db),lc=jb.Ei.ie(),Xb=un(C,lc),ec=c.Ps.bf(D),Ab=c.Rm,Ob=jb.sk,fb=V(c.Rm.q),Wa=Pu(Ab,Ob,fb,!1),bb=new az(c.Sz,c.Eq,c.Os,Lb,Xb,c.Qs,ec,Wa);n=uc;b=A;c=bb;continue}else if(B instanceof ax){b=A;continue}else throw new w(B);\n}}var Ia=O().c;if(null===Ia?null===r:Ia.i(r)){var Ua=n.J,pc=c;if(Ua.F){var sc=ut(Q(),\"| \",Ua.r)+\"Done inheriting: \"+pc;ff(gf(),sc+\"\\n\")}var Ba=n.J,ob=c.Eq,nc=n.J,Ib=px(n),vc=Ib.b()?O().c:Ib.o(),Vb=k.Sg,fc=Vb.b()?new Gl(O().c):Vb.o(),Bc=new Qv(nc,vc,ny(n.J,fc,!0)),Pb=new $y(Ba,ob,Bc,V(n.J)),Jb=bz(n.J,k,V(n.J),e),gc=V(Pb.q),Cb=Pu(Pb,Jb,gc,!1),cc=n.J;cu();var yc=k.hg;if(yc===u())var Mc=u();else{for(var qc=yc.e(),oc=new z(qc.j(),u()),Qc=oc,jc=yc.f();jc!==u();){var sb=jc.e(),Gc=new z(sb.j(),u());Qc=Qc.p=\nGc;jc=jc.f()}Mc=oc}var Wb=du(0,Mc);tx(n.J);var Cc=t().d,Fc=new Qv(cc,l,jx(new kx,n.J,Wb,\"type parameters\",Cc,!0)),qd=V(Cb.q),Yb=Pu(Cb,Fc,qd,!1),Nc=n,ad=n.J.qa,Uc=n.J;if(Uc.F){var cd=ut(Q(),\"| \",Uc.r)+(e.da+\". Finalizing inheritance with \"+Yb+\" \\x3c: \")+d;ff(gf(),cd+\"\\n\")}Uc.r=1+Uc.r|0;try{up(tp(),Pe(new E(d.Xa),e.da));var kc=V(Yb.q),Vc=Pu(Yb,m,kc,!1),Hc=Sw(Nc.J).ob;Tw(Nc.J,Vc,d,g,h,e,Hc);var rc=void 0}finally{Uc.r=-1+Uc.r|0}if(dx(new E(ad),Uc.qa)&&Uc.F){var sd=\"\"+ut(Q(),\"| \",Uc.r)+ad.n(rc);ff(gf(),\nsd+\"\\n\")}if(k.Pm.b()){var Kc=n,Qd=c,Ad=n.J.qa,kd=n.J;if(kd.F){var Hd=ut(Q(),\"| \",kd.r)+\"Checking self signature...\";ff(gf(),Hd+\"\\n\")}kd.r=1+kd.r|0;try{var Rd=Qd.Rm,Bd=Sw(Kc.J).ob;Tw(Kc.J,Yb,Rd,g,h,e,Bd);var ae=void 0}finally{kd.r=-1+kd.r|0}if(dx(new E(Ad),kd.qa)&&kd.F){var dd=\"\"+ut(Q(),\"| \",kd.r)+Ad.n(ae);ff(gf(),dd+\"\\n\")}}var od=c.Rm,Ta=V(c.Rm.q),wb=Pu(od,m,Ta,!1);return new az(c.Sz,Yb,c.Os,c.Hu,c.Gu,c.Qs,c.Ps,wb)}throw new w(r);}}\nfunction my(a,b,c){Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Cannot use `val` in constructor parameters\"]))),u()),b,c)}function Yy(a){return a instanceof Vw?!(a.ij instanceof Ep):!1}function cz(a,b,c){return a.yl(t().d,!1,new fn((d,e)=>b.n(e)),c)}function dz(a){return!!(a&&a.$classData&&a.$classData.rb.ZH)}function ez(){}ez.prototype=new p;ez.prototype.constructor=ez;function fz(a,b){return Wk(new gz).Ob(b,new y(()=>{t();return R()}))}ez.prototype.$classData=q({JX:0},!1,\"mlscript.OpApp$\",{JX:1,g:1});var hz;\nfunction iz(){hz||(hz=new ez);return hz}function jz(){this.ld=null}jz.prototype=new p;jz.prototype.constructor=jz;function kz(){}kz.prototype=jz.prototype;function lz(){}lz.prototype=new p;lz.prototype.constructor=lz;function fu(a,b){a=b.m();a=new Ef(a,new y(c=>G(new H,t().d,new sm(tm().Cg,c))));Od();return new Gl(Pd(u(),a))}\nfunction mz(a,b){if(b instanceof Gl){a=b.Ra;a:{for(b=a;!b.b();){var c=b.e();if(!(c.h().b()&&Pe(new E(c.j().yb.je),!1)&&Pe(new E(c.j().yb.ch),!1))){b=!1;break a}b=b.f()}b=!0}if(b){t();if(a===u())a=u();else{b=a.e();c=b=new z(b.j().ya,u());for(a=a.f();a!==u();){var d=a.e();d=new z(d.j().ya,u());c=c.p=d;a=a.f()}a=b}return new L(a)}}return t().d}lz.prototype.$classData=q({OX:0},!1,\"mlscript.PlainTup$\",{OX:1,g:1});var nz;function eu(){nz||(nz=new lz);return nz}\nfunction oz(){this.aI=this.Yz=null;Ty();var a=u();this.Yz=Uy(a);pz();a=u();this.aI=qz(a)}oz.prototype=new p;oz.prototype.constructor=oz;function ho(a,b,c){Ly(a.Yz,b,c,!1);return c}oz.prototype.$classData=q({QX:0},!1,\"mlscript.Polyfill\",{QX:1,g:1});\nfunction rz(a,b,c){a=new xl(\"x\");var d=new xl(\"y\"),e=O().c;a=new z(a,new z(d,e));d=new km(\"arguments\");d=om(Al(),d,\"length\");d=new gn(\"\\x3d\\x3d\\x3d\",d,new hn(\"2\"));e=rn(new gn(b,new km(\"x\"),new km(\"y\")));var g=O().c;e=new z(e,g);g=new xl(\"y\");var h=O().c;g=new z(g,h);t();b=rn(new oo(g,new fe(new gn(b,new km(\"x\"),new km(\"y\")))));g=O().c;b=new dp(d,e,new z(b,g));d=O().c;return new sz(c,a,new z(b,d))}\nfunction tz(a,b,c){a=J(new K,[new xl(\"x\")]);b=[rn(new $o(b,new km(\"x\")))];b=J(new K,b);return new sz(c,(Od(),Pd(u(),a)),(Od(),Pd(u(),b)))}\nfunction uz(){this.PN=this.ON=null;vz=this;var a=kl();ol(a,new wz(\"prettyPrint\",new y(b=>{var c=new km(\"value\"),d=new xl(\"value\"),e=O().c;d=new z(d,e);e=new $o(\"typeof\",c);var g=J(new K,[c]);g=rn(new cn(new km(\"String\"),(Od(),Pd(u(),g))));var h=O().c;g=new z(g,h);h=an(\"number\");var k=O().c;h=G(new H,h,k);k=an(\"boolean\");var l=om(Al(),c,\"toString\"),m=u();l=rn(new cn(l,m));m=O().c;k=G(new H,k,new z(l,m));l=an(\"function\");m=om(Al(),c,\"name\");var n=an(\"\\x3canonymous\\x3e\");m=new gn(\"??\",m,n);n=an(\"[Function: \");\nm=new gn(\"+\",n,m);n=an(\"]\");m=rn(new gn(\"+\",m,n));n=O().c;l=G(new H,l,new z(m,n));m=an(\"string\");n=an('\"');n=new gn(\"+\",n,c);var r=an('\"');n=rn(new gn(\"+\",n,r));r=O().c;m=G(new H,m,new z(n,r));n=an(\"undefined\");r=rn(an(\"undefined\"));var v=O().c;n=G(new H,n,new z(r,v));r=an(\"object\");v=new gn(\"\\x3d\\x3d\\x3d\",c,new km(\"null\"));var x=rn(an(\"null\")),A=O().c;x=new z(x,A);A=om(Al(),c,\"constructor\");A=om(Al(),A,\"name\");var B=an(\" \");A=new gn(\"+\",A,B);B=new km(\"JSON\");B=om(Al(),B,\"stringify\");var C=J(new K,\n[c,new km(\"undefined\"),new km(\"2\")]);B=new cn(B,(Od(),Pd(u(),C)));A=rn(new gn(\"+\",A,B));B=O().c;A=new z(A,B);B=new km(\"_\");c=J(new K,[c]);c=rn(new cn(new km(\"String\"),(Od(),Pd(u(),c))));C=O().c;c=new xz(A,new yz(B,new z(c,C)));A=O().c;c=new dp(v,x,new z(c,A));v=O().c;c=[h,k,l,m,n,G(new H,r,new z(c,v))];e=Tba(e,g,J(new K,c));g=O().c;return new sz(b,d,new z(e,g))})));ol(a,new wz(\"withConstruct\",new y(b=>{var c=new km(\"Object\"),d=new km(\"target\"),e=new km(\"fields\"),g=J(new K,[new xl(\"target\"),new xl(\"fields\")]),\nh=new $o(\"typeof\",d),k=an(\"string\");h=new gn(\"\\x3d\\x3d\\x3d\",h,k);k=new $o(\"typeof\",d);var l=an(\"number\");h=new gn(\"||\",h,new gn(\"\\x3d\\x3d\\x3d\",k,l));k=new $o(\"typeof\",d);l=an(\"boolean\");h=new gn(\"||\",h,new gn(\"\\x3d\\x3d\\x3d\",k,l));k=new $o(\"typeof\",d);l=an(\"bigint\");h=new gn(\"||\",h,new gn(\"\\x3d\\x3d\\x3d\",k,l));k=new $o(\"typeof\",d);l=an(\"symbol\");h=new gn(\"||\",h,new gn(\"\\x3d\\x3d\\x3d\",k,l));k=om(Al(),c,\"assign\");l=J(new K,[d,e]);k=rn(new cn(k,(Od(),Pd(u(),l))));l=O().c;h=new dp(h,new z(k,l),O().c);k=\nnew gn(\"||\",new gn(\"||\",new gn(\"||\",new gn(\"instanceof\",d,new km(\"String\")),new gn(\"instanceof\",d,new km(\"Number\"))),new gn(\"instanceof\",d,new km(\"Boolean\"))),new gn(\"instanceof\",d,new km(\"BigInt\")));l=om(Al(),c,\"assign\");var m=om(Al(),d,\"valueOf\"),n=u();m=J(new K,[new cn(m,n),d,e]);l=rn(new cn(l,(Od(),Pd(u(),m))));m=O().c;k=new dp(k,new z(l,m),O().c);l=new km(\"Array\");l=om(Al(),l,\"isArray\");m=J(new K,[d]);l=new cn(l,(Od(),Pd(u(),m)));t();m=new km(\"Array\");m=om(Al(),m,\"from\");n=J(new K,[d]);m=new cn(m,\n(Od(),Pd(u(),n)));m=new qn(\"clone\",m);n=new xl(\"key\");var r=[zz(Xo(new Yo,new km(\"clone\"),new km(\"key\")),Xo(new Yo,d,new km(\"key\")))];r=J(new K,r);n=new Az(n,d,(Od(),Pd(u(),r)));r=new xl(\"key\");var v=[zz(Xo(new Yo,new km(\"clone\"),new km(\"key\")),Xo(new Yo,e,new km(\"key\")))];v=J(new K,v);r=new Az(r,e,(Od(),Pd(u(),v)));m=[m,n,r,rn(new km(\"clone\"))];m=J(new K,m);l=new dp(l,Pd(u(),m),O().c);m=new gn(\"\\x3d\\x3d\",d,new hn(\"null\"));n=om(Al(),c,\"assign\");r=[new vo(O().c,O().c),new vo(O().c,O().c),e];r=J(new K,\nr);n=rn(new cn(n,(Od(),Pd(u(),r))));r=O().c;m=new dp(m,new z(n,r),O().c);n=om(Al(),c,\"assign\");e=[new vo(O().c,O().c),d,e];e=J(new K,e);e=new qn(\"copy\",new cn(n,(Od(),Pd(u(),e))));n=om(Al(),c,\"setPrototypeOf\");r=new km(\"copy\");c=om(Al(),c,\"getPrototypeOf\");d=J(new K,[d]);d=[r,new cn(c,(Od(),Pd(u(),d)))];d=J(new K,d);d=new cn(n,(Od(),Pd(u(),d)));d=[h,k,l,m,e,new Bo(d),rn(new km(\"copy\"))];d=J(new K,d);return new sz(b,(Od(),Pd(u(),g)),(Od(),Pd(u(),d)))})));ol(a,new Bz(\"toString\",new y(b=>{var c=J(new K,\n[new xl(\"x\")]),d=J(new K,[new km(\"x\")]);d=[rn(new cn(new km(\"String\"),(Od(),Pd(u(),d))))];d=J(new K,d);return new sz(b,(Od(),Pd(u(),c)),(Od(),Pd(u(),d)))})));ol(a,new Bz(\"id\",new y(b=>{var c=J(new K,[new xl(\"x\")]),d=[rn(new km(\"x\"))];d=J(new K,d);return new sz(b,(Od(),Pd(u(),c)),(Od(),Pd(u(),d)))})));ol(a,new Bz(\"emptyArray\",new y(b=>{var c=u(),d=[rn(new Wo(O().c))];d=J(new K,d);return new sz(b,c,(Od(),Pd(u(),d)))})));ol(a,new Bz(\"succ\",new y(b=>{var c=J(new K,[new xl(\"x\")]),d=[rn(new gn(\"+\",new km(\"x\"),\nnew hn(\"1\")))];d=J(new K,d);return new sz(b,(Od(),Pd(u(),c)),(Od(),Pd(u(),d)))})));ol(a,new Bz(\"error\",new y(b=>{var c=u(),d=new $m(new km(\"Error\")),e=[an(\"an error was thrown\")];e=J(new K,e);d=new cn(d,(Od(),Pd(u(),e)));d=J(new K,[new bn(d)]);return new sz(b,c,(Od(),Pd(u(),d)))})));ol(a,new Bz(\"length\",new y(b=>{var c=J(new K,[new xl(\"x\")]),d=new km(\"x\");d=[rn(om(Al(),d,\"length\"))];d=J(new K,d);return new sz(b,(Od(),Pd(u(),c)),(Od(),Pd(u(),d)))})));ol(a,new Bz(\"concat\",new y(b=>rz(Cz(),\"+\",b))));\nol(a,new Bz(\"join\",new y(b=>{var c=J(new K,[new xl(\"...xs\")]),d=new km(\"xs\");d=om(Al(),d,\"join\");var e=[new hn(Mp(Np(),\"\"))];e=J(new K,e);d=[rn(new cn(d,(Od(),Pd(u(),e))))];d=J(new K,d);return new sz(b,(Od(),Pd(u(),c)),(Od(),Pd(u(),d)))})));ol(a,new Bz(\"add\",new y(b=>rz(Cz(),\"+\",b))));ol(a,new Bz(\"sub\",new y(b=>rz(Cz(),\"-\",b))));ol(a,new Bz(\"mul\",new y(b=>rz(Cz(),\"*\",b))));ol(a,new Bz(\"div\",new y(b=>rz(Cz(),\"/\",b))));ol(a,new Bz(\"gt\",new y(b=>rz(Cz(),\"\\x3e\",b))));ol(a,new Bz(\"not\",new y(b=>tz(Cz(),\n\"!\",b))));ol(a,new Bz(\"negate\",new y(b=>tz(Cz(),\"-\",b))));ol(a,new Bz(\"eq\",new y(b=>rz(Cz(),\"\\x3d\\x3d\\x3d\",b))));ol(a,new Bz(\"ne\",new y(b=>rz(Cz(),\"!\\x3d\\x3d\",b))));ol(a,new Bz(\"sgt\",new y(b=>rz(Cz(),\"\\x3e\",b))));ol(a,new Bz(\"slt\",new y(b=>rz(Cz(),\"\\x3c\",b))));ol(a,new Bz(\"sge\",new y(b=>rz(Cz(),\"\\x3e\\x3d\",b))));ol(a,new Bz(\"sle\",new y(b=>rz(Cz(),\"\\x3c\\x3d\",b))));ol(a,new Bz(\"eq\",new y(b=>rz(Cz(),\"\\x3d\\x3d\\x3d\",b))));ol(a,new Bz(\"unit\",new y(b=>tz(Cz(),\"undefined\",b))));ol(a,new Bz(\"log\",new y(b=>\n{var c=J(new K,[new xl(\"x\")]),d=J(new K,[new km(\"x\")]);d=[rn(new cn(new km(\"console.info\"),(Od(),Pd(u(),d))))];d=J(new K,d);return new sz(b,(Od(),Pd(u(),c)),(Od(),Pd(u(),d)))})));ol(a,new Bz(\"discard\",new y(b=>{var c=J(new K,[new xl(\"x\")]),d=u();return new sz(b,(Od(),Pd(u(),c)),d)})));Od();this.ON=Pd(u(),a);this.PN=Dz(Ez(),Qt(this.ON,new y(b=>G(new H,b.Ua(),b))))}uz.prototype=new p;uz.prototype.constructor=uz;uz.prototype.$classData=q({RX:0},!1,\"mlscript.Polyfill$\",{RX:1,g:1});var vz;\nfunction Cz(){vz||(vz=new uz);return vz}function Fz(){}Fz.prototype=new p;Fz.prototype.constructor=Fz;function Gz(){}Gz.prototype=Fz.prototype;function Hz(a){this.$f=a}Hz.prototype=new p;Hz.prototype.constructor=Hz;function Iz(a,b){return new Hz(un(a.$f,b.$f))}\nfunction Rp(a,b){var c=b.$f;if(c instanceof z){var d=c.z;c=c.p;if(a.$f.b())return b;b=a.$f.MJ();t();a=a.$f.Mc();a=J(new K,[new Jz(\"\"+a.Kq+d.Kq,a.$s)]);a=Pd(u(),a);return new Hz(dl(dl(c,a),b))}d=O().c;if(null===d?null===c:d.i(c))return a;throw new w(c);}function Kz(a){var b=a.$f;if(b===u())a=u();else{a=b.e();var c=a=new z(Lz(a),u());for(b=b.f();b!==u();){var d=b.e();d=new z(Lz(d),u());c=c.p=d;b=b.f()}}return new Hz(a)}\nfunction Pp(a,b){if(b)switch(a.$f.K()){case 0:return Sp(Qp(),\"()\");case 1:var c=a.$f;if(c===u())b=u();else for(b=c.e(),a=b=new z(Mz(b),u()),c=c.f();c!==u();){var d=c.e();d=new z(Mz(d),u());a=a.p=d;c=c.f()}return new Hz(b);default:return c=a.$f.e(),b=a.$f.f().Bb(1),d=a.$f.Mc(),a=new Jz(\"(\"+c.Kq,c.$s),t(),c=J(new K,[new Jz(\"\"+d.Kq+\")\",d.$s)]),b=dl(Pd(u(),c),b),new Hz(new z(a,b))}else return a}\nfunction Nz(a){switch(a.$f.K()){case 0:case 1:return a;default:var b=a.$f.e(),c=a.$f.f().Bb(1);a=a.$f.Mc();b=new Jz(\"(\"+b.Kq,b.$s);t();a=J(new K,[new Jz(\"\"+a.Kq+\")\",a.$s)]);c=dl(Pd(u(),a),c);return new Hz(new z(b,c))}}function Oz(a){if(0===a.$f.K())return Sp(Qp(),\"{}\");var b=new Jz(\"{\",0),c=a.$f;if(c===u())a=u();else{a=c.e();var d=a=new z(Lz(a),u());for(c=c.f();c!==u();){var e=c.e();e=new z(Lz(e),u());d=d.p=e;c=c.f()}}t();d=J(new K,[new Jz(\"}\",0)]);a=dl(Pd(u(),d),a);return new Hz(new z(b,a))}\nHz.prototype.u=function(){return ze(this.$f,\"\",\"\\n\",\"\")};Hz.prototype.$classData=q({iY:0},!1,\"mlscript.SourceCode\",{iY:1,g:1});function Pz(){this.SN=this.ye=this.RN=this.cI=this.zx=this.bA=null;Qz=this;Sp(Qp(),\" \\x26 \");this.bA=Sp(Qp(),\" \");this.zx=Sp(Qp(),\";\");Sp(Qp(),\": \");Sp(Qp(),\" | \");this.cI=Sp(Qp(),\",\");this.RN=Sp(Qp(),\", \");this.ye=Rz(Qp(),O().c);Sp(Qp(),\"{\");Sp(Qp(),\"}\");Sp(Qp(),\"\\x3c\");Sp(Qp(),\"\\x3e\");this.SN=Sp(Qp(),\" \\x3d\\x3e \");Sp(Qp(),\" \\x3d \")}Pz.prototype=new p;\nPz.prototype.constructor=Pz;function Sp(a,b){t();a=J(new K,[new Jz(b,0)]);return new Hz(Pd(u(),a))}function Rz(a,b){if(b===u())a=u();else{a=b.e();var c=a=new z(new Jz(a,0),u());for(b=b.f();b!==u();){var d=b.e();d=new z(new Jz(d,0),u());c=c.p=d;b=b.f()}}return new Hz(a)}function Sz(a){for(var b=Qp().ye;!a.b();){var c=a.e();b=Iz(b,c);a=a.f()}return b}\nfunction Tz(a){var b=O().c;if(null===b?null===a:b.i(a))return Sp(Qp(),\"{}\");if(a instanceof z){b=a.z;var c=a.p,d=O().c;if(null===d?null===c:d.i(c))return 0<b.$f.ab(1)?Iz(Iz(Sp(Qp(),\"{\"),Kz(b)),Sp(Qp(),\"}\")):Rp(Rp(Sp(Qp(),\"{ \"),b),Sp(Qp(),\" }\"))}return Iz(Hf(a).De(Sp(Qp(),\"{\"),new fn((e,g)=>{var h=G(new H,e,g);e=h.y;g=h.w;if(null!==g)return h=g.h(),Iz(e,Kz(Pe(new E(1+g.Sc()|0),a.K())?h:Rp(h,Qp().cI)));throw new w(h);})),Sp(Qp(),\"}\"))}\nfunction Uz(a){var b=O().c;if(null===b?null===a:b.i(a))return Sp(Qp(),\"[]\");if(a instanceof z){b=a.z;var c=a.p,d=O().c;if(null===d?null===c:d.i(c))return 0<b.$f.ab(1)?Iz(Iz(Sp(Qp(),\"[\"),Kz(b)),Sp(Qp(),\"]\")):Rp(Rp(Sp(Qp(),\"[\"),b),Sp(Qp(),\"]\"))}return Iz(Hf(a).De(Sp(Qp(),\"[\"),new fn((e,g)=>{var h=G(new H,e,g);e=h.y;g=h.w;if(null!==g)return h=g.h(),Iz(e,Kz(Pe(new E(1+g.Sc()|0),a.K())?h:Rp(h,Qp().cI)));throw new w(h);})),Sp(Qp(),\"]\"))}\nfunction Uba(a,b,c){return Hf(b).De(a.ye,new fn((d,e)=>{var g=G(new H,d,e);d=g.y;e=g.w;if(null!==e)return g=e.Sc(),Rp(Rp(d,e.h()),Pe(new E(g),-1+b.K()|0)?Qp().ye:c);throw new w(g);}))}Pz.prototype.$classData=q({jY:0},!1,\"mlscript.SourceCode$\",{jY:1,g:1});var Qz;function Qp(){Qz||(Qz=new Pz);return Qz}function Jz(a,b){this.Kq=a;this.$s=b}Jz.prototype=new p;Jz.prototype.constructor=Jz;function Lz(a){return new Jz(a.Kq,1+a.$s|0)}function Mz(a){return new Jz(\"(\"+a.Kq+\")\",a.$s)}\nJz.prototype.u=function(){return\"\"+ut(Q(),\"  \",this.$s)+this.Kq};Jz.prototype.$classData=q({kY:0},!1,\"mlscript.SourceLine\",{kY:1,g:1});function Vz(){}Vz.prototype=new p;Vz.prototype.constructor=Vz;function Wz(){}Wz.prototype=Vz.prototype;\nVz.prototype.jb=function(){var a=!1,b=null;if(Se()===this)return\"space\";if(Xr()===this)return\"comma\";if(ds()===this)return\"semicolon\";if(qs()===this)return\"newline\";if(ks()===this)return\"indentation\";if(rs()===this)return\"deindentation\";if(ts()===this)return\"error\";if(Yr()===this)return\"quote\";if(this instanceof fs)return\"literal\";if(this instanceof as)return a=this.Na,b=Xz(Q(),a),b.b()?b=!1:(b=b.o(),b=Ea(b),b=Or(Pr(),b)),b?\"'\"+a+\"' keyword\":\"'\"+a+\"'\";if(this instanceof bs)return this.ke?\"operator\":\n\"identifier\";if(this instanceof ss)return\"selector\";if(this instanceof Zr)return\"opening \"+this.qx.Ua();if(this instanceof es)return\"closing \"+this.Iw.Ua();if(this instanceof cs){a=!0;b=this;var c=b.Cc;if(Mk()===c)return\"indented block\"}if(a)return b.Cc.Ua()+\" section\";if(this instanceof gs)return\"comment\";throw new w(this);};\nfunction Yz(a){a=a.Ra.m();a=new Ef(a,new y(b=>{if(null!==b){var c=b.h();b=b.j();var d=b.yb.je?\"mut \":\"\",e=b.yb.Bh?\"val \":\"\",g=b.yb.ch?\"#\":\"\";c=c.b()?\"\":c.o().x+\": \";return d+e+g+c+Zz(b.ya,!1)+\",\"}throw new w(b);}));return ze(a,\"\",\" \",\"\")}function $z(a,b){a=a.Ra.m();a=new Ef(a,new y(c=>{if(null!==c){var d=c.h();c=c.j();var e=c.yb.je?\"mut \":\"\",g=c.yb.Bh?\"val \":\"\",h=c.yb.ch?\"#\":\"\";d=d.b()?\"\":d.o().x+\": \";return e+g+h+d+aA(c.ya,!1,b)}throw new w(c);}));return ze(a,\"\",\", \",\"\")}function bA(){}\nbA.prototype=new p;bA.prototype.constructor=bA;bA.prototype.$classData=q({xY:0},!1,\"mlscript.TypeDefs$VarianceStore$\",{xY:1,g:1});function cA(a){a=a.m();a=new Ef(a,new y(b=>\"\"+dA(b.j())+b.h()));return ze(a,\"\",\", \",\"\")}function eA(a,b,c,d,e,g){c=fA(gA(a),c);c=hA(b,c,g);if(a.F){var h=ut(Q(),\"| \",a.r)+\"allVarPols: \"+cA(c);ff(gf(),h+\"\\n\")}h=Xu().X();return Vba(a,b,g,h,c,d,e,g)}\nfunction iA(a,b,c,d){var e=new $e;if(a.F){var g=ut(Q(),\"| \",a.r);if(e.sb)e=e.vb;else{if(null===e)throw le();if(e.sb)e=e.vb;else{var h=fA(gA(a),c);e=me(e,hA(b,h,d))}}g=g+\"allVarPols: \"+cA(e);ff(gf(),g+\"\\n\")}g=jA().X();return Wba(a,b,c,t().d,d,d,g)}\nfunction kA(a,b,c,d,e){var g=new $e,h=new $e,k=new lA;k=Xba(k);var l=jA().X(),m=jA().X();mA(g.sb?g.vb:Yba(a,g,e,k,l,m),fA(gA(a),d),b);a.F&&(g=ut(Q(),\"| \",a.r)+\"[inv] \"+ze(l,\"\",\", \",\"\"),ff(gf(),g+\"\\n\"));if(a.F){g=ut(Q(),\"| \",a.r);var n=k.m();n=new Ef(n,new y(B=>{t();return\"\"+dA(new L(B.h().Rc()))+B.h().j()+\" \"+B.Sc()}));g=g+\"[nums] \"+ze(n,\"\",\" ; \",\"\");ff(gf(),g+\"\\n\")}var r=Xu().X();g=jA().X();n=jA().X();nA(a,b,fA(gA(a),d),h,e,g,n,r);r.Ca(new y(B=>{up(tp(),!B.j().b())}));a.F&&(h=ut(Q(),\"| \",a.r),g=\nr.m(),g=new Ef(g,new y(B=>{t();return\"\"+dA(new L(B.h().Rc()))+B.h().j()+\" \"+ze(B.j(),\"{\",\",\",\"}\")})),h=h+\"[occs] \"+ze(g,\"\",\" ; \",\"\"),ff(gf(),h+\"\\n\"));var v=Xu().X();m=m.m();m=new Ef(m,new y(B=>B.h()));h=Su();g=op().ga;h=new Uu(h,g);m=oA(uv(),m,h);h=pA(m,v,e);var x=new aw(h);a.F&&(h=ut(Q(),\"| \",a.r)+\"[vars] \"+m,ff(gf(),h+\"\\n\"));a.F&&(h=ut(Q(),\"| \",a.r)+\"[rec] \"+x.rc,ff(gf(),h+\"\\n\"));for(h=k.m();h.s();){var A=h.t();a:{if(null!==A&&(g=A.h(),n=A.Sc(),null!==g)){A=g.Rc();g=g.j();up(tp(),0<n);Pe(new E(n),\n1)&&!k.L(G(new H,!A,g))&&(n=a,n.F&&(n=ut(Q(),\"| \",n.r)+\"0[1] \"+g,ff(gf(),n+\"\\n\")),n=R(),g=G(new H,g,n),v.$(g));break a}throw new w(A);}}m.Ca(new y(B=>{if(!x.rc.L(B)){var C=G(new H,r.U(G(new H,!0,B)),r.U(G(new H,!1,B)));var D=C.w;if(C.y instanceof L&&R()===D)D=!0;else{D=C.y;var F=C.w;D=R()===D&&F instanceof L?!0:!1}if(D)return a.F&&(C=ut(Q(),\"| \",a.r)+\"1[!] \"+B,ff(gf(),C+\"\\n\")),C=R(),B=G(new H,B,C),v.$(B);if(!Nm(new E(C),G(new H,R(),R())))throw new Yj(\"assertion failed: \"+B+\" has no occurrences...\");\n}}));m.Ca(new y(B=>{if(B.Sb.b()&&!v.L(B)){if(a.F){var C=ut(Q(),\"| \",a.r)+(\"2[v] \"+B+\" \"+r.U(G(new H,!0,B))+\" \")+r.U(G(new H,!1,B));ff(gf(),C+\"\\n\")}C=r.U(G(new H,!0,B)).m();for(C=new xo(C,new y(T=>new qA(T)));C.s();){var D=C.t();if(D instanceof Fv||D instanceof fw)if(x.rc.L(B))F=!1;else{F=r.U(G(new H,!1,B));var F=F.b()?!1:F.o().L(D)}else F=!1;if(F){F=cw(a);for(var I=rA(B),M=D;!I.b();){var N=I.e(),P=V(M.q);M=sA(M,N,P);I=I.f()}I=M;M=vy(B);N=D;for(D=M;!D.b();)M=N,N=D.e(),P=V(M.q),N=dv(M,N,P,!1),D=D.f();\nF=tA(F,I,N,V(cw(a).Vu));D=a;D.F&&(D=ut(Q(),\"| \",D.r)+(\"  [..] \"+B+\" :\\x3d \")+F,ff(gf(),D+\"\\n\"));t();F=G(new H,B,new L(F));v.$(F)}else if(D instanceof lx&&((Ot(new E(D),B)||v.L(D)||v.L(B)?0:!x.rc.L(B))?(F=r.U(G(new H,!1,B)),F=F.b()?!1:F.o().L(D)):F=!1,F)){F=cw(a);I=rA(B);for(M=D;!I.b();)N=I.e(),P=V(M.q),M=sA(M,N,P),I=I.f();I=M;M=vy(B);N=D;for(D=M;!D.b();)M=N,N=D.e(),P=V(M.q),N=dv(M,N,P,!1),D=D.f();F=tA(F,I,N,V(cw(a).Vu));D=a;D.F&&(D=ut(Q(),\"| \",D.r)+(\"  [..] \"+B+\" :\\x3d \")+F,ff(gf(),D+\"\\n\"));t();F=\nG(new H,B,new L(F));v.$(F)}}}}));m.Ca(new y(B=>{if(B.Sb.b()&&!v.L(B)){var C=a.qa;if(a.F){var D=ut(Q(),\"| \",a.r),F=iu(ju(),r.U(G(new H,!0,B)));F=ze(F,\"\",\"\",\"\");var I=iu(ju(),r.U(G(new H,!1,B)));D=D+(\"3[v] \"+B+\" +\"+F+\" -\")+ze(I,\"\",\"\",\"\");ff(gf(),D+\"\\n\")}a.r=1+a.r|0;try{uA(a,!0,r,B,v);uA(a,!1,r,B,v);var M=void 0}finally{a.r=-1+a.r|0}dx(new E(C),a.qa)&&a.F&&(B=\"\"+ut(Q(),\"| \",a.r)+C.n(M),ff(gf(),B+\"\\n\"))}}));a.F&&(h=ut(Q(),\"| \",a.r),g=v.Ja(new y(B=>B.h().u()+\" -\\x3e \"+B.j())),h=h+\"[sub] \"+ze(g,\"\",\", \",\n\"\"),ff(gf(),h+\"\\n\"));a.F&&(h=ut(Q(),\"| \",a.r)+\"[bounds] \"+xx(b),ff(gf(),h+\"\\n\"));x.rc=pA(m,v,e);a.F&&(m=ut(Q(),\"| \",a.r)+\"[rec] \"+x.rc,ff(gf(),m+\"\\n\"));m=Xu().X();h=ap();return Zba(a,b,fA(gA(a),d),h,e,v,c,m,l,x,k,r)}\nfunction vA(a,b,c,d){var e=fA(gA(a),(t(),new L(c))),g=hA(b,e,d);a.F&&(e=ut(Q(),\"| \",a.r)+\"allVarPols: \"+cA(g),ff(gf(),e+\"\\n\"));e=jA().X();g=g.m();var h=new wA(a);g=new Ex(g,h);g=new iy(g,new y(k=>{if(null!==k){var l=k.h(),m=k.j();if(null!==l)return xA(l.j(),!1).L(m)}throw new w(k);}),!1);op();g=pp(qp(),g);a.F&&(h=ut(Q(),\"| \",a.r)+\"consed: \"+g,ff(gf(),h+\"\\n\"));return $ba(a,(t(),new L(c)),b,d,e,g)}\nfunction aca(a,b,c,d){c=fA(gA(a),c);var e=hA(b,c,d);a.F&&(c=ut(Q(),\"| \",a.r)+\"allVarPols: \"+cA(e),ff(gf(),c+\"\\n\"));jA().X();var g=Xu().X();e.Ca(new y(h=>{if(null!==h){var k=h.h();h=h.j();if(h instanceof L){var l=!!h.k;a.F&&(h=ut(Q(),\"| \",a.r)+\"Consider \"+k,ff(gf(),h+\"\\n\"));h=k.Sb;if(h.b())h=R();else{h=h.o();var m=O().c;h=new L(new z(h,m))}h=h.b()?l?vy(k):rA(k):h.o();if(h instanceof z){var n=h.z;h=h.p;m=O().c;(null===m?null===h:m.i(h))&&e.Ca(new y(r=>{if(null!==r){var v=r.h();r=r.j();if(r instanceof\nL&&(r=!!r.k,Pe(new E(r),l)&&dx(new E(v),k)&&!g.L(k)&&!g.L(v))){var x=v.Sb;if(x.b())x=R();else{x=x.o();var A=O().c;x=new L(new z(x,A))}x=x.b()?r?vy(v):rA(v):x.o();if(x instanceof z&&(r=x.z,x=x.p,A=O().c,null===A?null===x:A.i(x))&&(a.F&&(x=ut(Q(),\"| \",a.r)+(\"Consider \"+k+\" ~ \")+v,ff(gf(),x+\"\\n\")),yA(a,n,r,k,v)))return a.F&&(r=ut(Q(),\"| \",a.r)+(\"Yes! \"+v+\" :\\x3d \")+k,ff(gf(),r+\"\\n\")),v=G(new H,v,k),g.$(v)}}}))}}}}));a.F&&(c=ut(Q(),\"| \",a.r)+\"[subs] \"+g,ff(gf(),c+\"\\n\"));return g.b()?b:bca(a,b,(op(),pp(qp(),\ng)),d)}function cca(a,b,c,d){return c.Hk(b,new U(()=>{if(d)return b;var e=V(a);t();var g=new L(b),h=b.kg,k=O().c,l=O().c;e=new lx(a,b.Xa,k,l,g,h,!1,e);a.F&&(g=ut(Q(),\"| \",a.r)+(\"Renewed \"+b+\" ~\\x3e \")+e,ff(gf(),g+\"\\n\"));return e}))}function Vba(a,b,c,d,e,g,h,k){if(b instanceof zA)return AA(a,b,t().d,t().d,d,e,c,g,h,k);if(b instanceof BA){CA(a);t();var l=new L(b);if(!l.b())return dca(l.k,new y(m=>AA(a,m,t().d,t().d,d,e,c,g,h,k)),c)}throw new w(b);}\nfunction DA(a,b,c,d,e,g,h,k,l){if(null===b)throw le();if(b.sb)return b.vb;var m=c.Va,n=c.Oa;n.b()?n=R():(n=n.o(),n=new L(AA(a,n,t().d,t().d,d,e,g,h,k,l)));return me(b,new Uw(m,n,AA(a,c.ra,t().d,t().d,d,e,g,h,k,l),c.Pd))}\nvar AA=function EA(a,b,c,d,e,g,h,k,l,m){var r=tc();try{var v=!1,x=null,A=!1,B=null;if(b instanceof mx){var C=b.hi;if(null!==C)return EA(a,C,c,t().d,e,g,h,k,l,m)}if(b instanceof lx){if(c.b())var D=!0;else{var F=c.o().j();D=Pe(new E(F),b)}var I=D?c:R();if(!I.b()){var M=I.o().Rc();throw Hq(new Iq,r,new FA(a,M,V(a)));}var N=new GA(!1),P=e.Hk(b,new U(()=>{N.Am=!0;return cca(a,b,e,l)}));if(N.Am){var T=b.Sb;if(T instanceof L){var Y=T.k,Z=!1,S=null,ea=HA(g,b);a:if(ea.b()||!P.Sb.b()){t();var ia=EA(a,Y,t().d,\nt().d,e,g,h,k,l,m);wy(P,new L(ia))}else{t().d===ea&&xm(\"Program reached and unexpected state.\");if(ea instanceof L&&(Z=!0,S=ea,!0===!!S.k)){t();var X=G(new H,!0,b),sa=EA(a,Y,new L(X),t().d,e,g,h,k,l,m),Ja=O().c,Xa=new z(sa,Ja);b:for(var Fa;;)if(Xa.b()){Fa=u();break}else{var za=Xa.e(),Qa=Xa.f();if(!0===!!Kv(za,h))Xa=Qa;else for(var Ma=Xa,Ga=Qa;;){if(Ga.b())Fa=Ma;else{var ab=Ga.e();if(!0!==!!Kv(ab,h)){Ga=Ga.f();continue}for(var Hb=Ga,bc=new z(Ma.e(),u()),yb=Ma.f(),tb=bc;yb!==Hb;){var eb=new z(yb.e(),\nu());tb=tb.p=eb;yb=yb.f()}for(var kb=Hb.f(),Rb=kb;!kb.b();){var Gb=kb.e();if(!0===!!Kv(Gb,h)){for(;Rb!==kb;){var vb=new z(Rb.e(),u());tb=tb.p=vb;Rb=Rb.f()}Rb=kb.f()}kb=kb.f()}Rb.b()||(tb.p=Rb);Fa=bc}break b}}IA(P,Fa);break a}if(Z&&!1===!!S.k){t();var Tb=G(new H,!1,b),Nb=EA(a,Y,new L(Tb),t().d,e,g,h,k,l,m),ic=O().c,Va=new z(Nb,ic);b:for(var cb;;)if(Va.b()){cb=u();break}else{var zb=Va.e(),Ub=Va.f();if(!0===!!JA(zb,h))Va=Ub;else for(var jb=Va,db=Ub;;){if(db.b())cb=jb;else{var ub=db.e();if(!0!==!!JA(ub,\nh)){db=db.f();continue}for(var Aa=db,va=new z(jb.e(),u()),Ra=jb.f(),rb=va;Ra!==Aa;){var xb=new z(Ra.e(),u());rb=rb.p=xb;Ra=Ra.f()}for(var mc=Aa.f(),Ha=mc;!mc.b();){var Ka=mc.e();if(!0===!!JA(Ka,h)){for(;Ha!==mc;){var Oa=new z(Ha.e(),u());rb=rb.p=Oa;Ha=Ha.f()}Ha=mc.f()}mc=mc.f()}Ha.b()||(rb.p=Ha);cb=va}break b}}KA(P,cb)}else throw new w(ea);}}else if(t().d===T){var Na=HA(g,b);if(Na.b())var Da=!0;else{var ta=!!Na.o();Da=Pe(new E(ta),!0)}if(Da){if(k)var Ya=vy(b),dc=er(Ya).m();else dc=vy(b).m();var ka=\nnew Ef(dc,new y(ng=>{t();var kh=G(new H,!0,b);return EA(a,ng,new L(kh),t().d,e,g,h,k,l,m)}));if(ka.s()){if(!ka.s())throw nv(\"empty.reduceLeft\");for(var ya=!0,Sa=null;ka.s();){var xc=ka.t();if(ya)Sa=xc,ya=!1;else{var Sb=Sa,uc=xc,Lb=V(Sb.q);Sa=dv(Sb,uc,Lb,!1)}}lc=new L(Sa)}else var lc=R();if(lc.b())var Xb=!0;else{var ec=lc.o();Xb=!Kv(ec,h)}var Ab=(Xb?lc:R()).ha()}else Ab=O().c;IA(P,Ab);var Ob=HA(g,b);if(Ob.b())var fb=!0;else{var Wa=!!Ob.o();fb=Pe(new E(Wa),!1)}if(fb){if(k)var bb=rA(b),Ia=er(bb).m();\nelse Ia=rA(b).m();var Ua=new Ef(Ia,new y(ng=>{t();var kh=G(new H,!1,b);return EA(a,ng,new L(kh),t().d,e,g,h,k,l,m)}));if(Ua.s()){if(!Ua.s())throw nv(\"empty.reduceLeft\");for(var pc=!0,sc=null;Ua.s();){var Ba=Ua.t();if(pc)sc=Ba,pc=!1;else{var ob=sc,nc=Ba,Ib=V(ob.q);sc=sA(ob,nc,Ib)}}vc=new L(sc)}else var vc=R();if(vc.b())var Vb=!0;else{var fc=vc.o();Vb=!JA(fc,h)}var Bc=(Vb?vc:R()).ha()}else Bc=O().c;KA(P,Bc)}else throw new w(T);}return P}if(b instanceof LA){v=!0;x=b;var Pb=x.ic,Jb=x.jc;if(!0===x.tc){var gc=\nEA(a,Pb,c,d,e,g,h,k,l,m),Cb=EA(a,Jb,c,d,e,g,h,k,l,m),cc=V(gc.q);return dv(gc,Cb,cc,!1)}}if(v){var yc=x.ic,Mc=x.jc;if(!1===x.tc){var qc=EA(a,yc,c,d,e,g,h,k,l,m),oc=EA(a,Mc,c,d,e,g,h,k,l,m),Qc=V(qc.q);return Pu(qc,oc,Qc,!1)}}if(b instanceof MA){var jc=b.Fc;if(c.b())var sb=R();else{var Gc=c.o();t();sb=new L(G(new H,!Gc.h(),Gc.j()))}var Wb=EA(a,jc,sb,t().d,e,g,h,k,l,m),Cc=jc.ma();return NA(Wb,Cc,!1)}if(b instanceof OA){A=!0;B=b;var Fc=B.Hi;if(l)return new OA(a,EA(a,Fc,c,d,e,g,h,k,l,m),Fc.ma())}if(A)return EA(a,\nB.Hi,c,d,e,g,h,k,l,m);if(b instanceof fw&&a.XE.L(b.qb)&&PA(b,h))return EA(a,QA(b,h),c,t().d,e,g,h,k,l,m);if(b instanceof Qv){for(var qd=b.Ba,Yb=xv(a),Nc=qd,ad=null,Uc=null;Nc!==u();){var cd=Nc.e();a:{if(null!==cd){var kc=cd.h(),Vc=cd.j();if(null!==kc){var Hc=kc.x,rc=new $e;b:{for(var sd=Hc.length,Kc=0;Kc<sd;){var Qd=Hc.charCodeAt(Kc);if(!Nm(new E(hc(Qd)),hc(35))){var Ad=Kc;break b}Kc=1+Kc|0}Ad=-1}var kd=-1===Ad?Hc:Hc.substring(0,Ad),Hd=ys(Q(),Hc,1+kd.length|0);if(\"\"===Hd||\"\"===kd){var Rd=rc.sb?rc.vb:\nDA(a,rc,Vc,e,g,h,k,l,m),Bd=G(new H,kc,Rd),ae=O().c;var dd=new z(Bd,ae);break a}else{var od=h.tb.U(kd);if(od instanceof L){var Ta=od.k,wb=Ta.Nu;if(wb.b())var $a=rc.sb?rc.vb:DA(a,rc,Vc,e,g,h,k,l,m),wa=G(new H,kc,$a),hb=O().c,ra=new z(wa,hb);else{var wc=wb.o();b:{for(var ac=Ta.Xm;!ac.b();){if(ac.e().h().V===Hd){var Id=new L(ac.e());break b}ac=ac.f()}Id=R()}Id.b()&&xm(\"Program reached and unexpected state.\");var ud=wc.n(Id.o().j());b:{if(null!==ud){var be=ud.qe;if(!0===ud.Qd&&!0===be){ra=O().c;break b}}if(null!==\nud){var re=ud.qe;if(ud.Qd){t();var pe=new Uw(a,new L(a.ib),EA(a,Vc.ra,t().d,t().d,e,g,h,k,l,m),Vc.Pd),bd=G(new H,kc,pe),Rc=O().c;ra=new z(bd,Rc)}else if(re){var Wc=Vc.Oa;if(Wc.b())var Wd=R();else{var zd=Wc.o();Wd=new L(EA(a,zd,t().d,t().d,e,g,h,k,l,m))}var Pa=new Uw(a,Wd,a.La,Vc.Pd),Db=G(new H,kc,Pa),Oc=O().c;ra=new z(Db,Oc)}else{var Tc=rc.sb?rc.vb:DA(a,rc,Vc,e,g,h,k,l,m),Sd=G(new H,kc,Tc),Jc=O().c;ra=new z(Sd,Jc)}}else throw new w(ud);}}dd=ra;break a}else{if(t().d!==od)throw new w(od);var vd=h.$a.U(kd);\nif(!(vd instanceof L))throw t().d===vd&&xm(\"'\"+kd+\"' not found\"),new w(vd);var hd=!1,de=null,ye=vd.k.eo;if(ye instanceof L){hd=!0;de=ye;var jf=de.k;if(jf instanceof Yw){var af=jf;b:{for(var pf=af.gh;!pf.b();){if(pf.e().kc.V===Hd){var kf=new L(pf.e());break b}pf=pf.f()}kf=R()}kf.b()&&xm(\"Program reached and unexpected state.\");var Be=RA(af,kf.o().hb,h);if(null!==Be){var Kd=Be.qe;if(!0===Be.Qd&&!0===Kd){dd=O().c;break a}}if(null!==Be){var ld=Be.qe;if(Be.Qd){t();var Jd=new Uw(a,new L(a.ib),EA(a,Vc.ra,\nt().d,t().d,e,g,h,k,l,m),Vc.Pd),Dd=G(new H,kc,Jd),Xd=O().c;dd=new z(Dd,Xd)}else if(ld){var Yc=Vc.Oa;if(Yc.b())var Ce=R();else{var te=Yc.o();Ce=new L(EA(a,te,t().d,t().d,e,g,h,k,l,m))}var Ie=new Uw(a,Ce,a.La,Vc.Pd),Jf=G(new H,kc,Ie),df=O().c;dd=new z(Jf,df)}else{var vg=rc.sb?rc.vb:DA(a,rc,Vc,e,g,h,k,l,m),wg=G(new H,kc,vg),xg=O().c;dd=new z(wg,xg)}break a}throw new w(Be);}}if(hd){var eg=de.k;if(eg instanceof Ww){var vh=eg.wk.m();b:{for(;vh.s();){var fg=vh.t();if(fg.kc.V===Hd){var ih=new L(fg);break b}}ih=\nR()}var Ig=ih.b()?R():ih.o().Rd,Tf=Ig.b()?ou().Yl:Ig.o();if(null!==Tf){var Jg=Tf.qe;if(!0===Tf.Qd&&!0===Jg){dd=O().c;break a}}if(null!==Tf){var jh=Tf.qe;if(Tf.Qd){t();var yg=new Uw(a,new L(a.ib),EA(a,Vc.ra,t().d,t().d,e,g,h,k,l,m),Vc.Pd),gg=G(new H,kc,yg),Cf=O().c;dd=new z(gg,Cf)}else if(jh){var Uf=Vc.Oa;if(Uf.b())var $g=R();else{var Ah=Uf.o();$g=new L(EA(a,Ah,t().d,t().d,e,g,h,k,l,m))}var Kg=new Uw(a,$g,a.La,Vc.Pd),Vf=G(new H,kc,Kg),hg=O().c;dd=new z(Vf,hg)}else{var zg=rc.sb?rc.vb:DA(a,rc,Vc,e,g,\nh,k,l,m),Lg=G(new H,kc,zg),Mg=O().c;dd=new z(Lg,Mg)}break a}throw new w(Tf);}}hd&&no();t().d===ye&&no();throw new w(ye);}}}}throw new w(cd);}for(var Wf=dd.m();Wf.s();){var Ng=new z(Wf.t(),u());null===Uc?ad=Ng:Uc.p=Ng;Uc=Ng}Nc=Nc.f()}return SA(Yb,null===ad?u():ad,b.ma())}if(b instanceof Qx){var Kf=b.de,xf=EA(a,b.Re,c,(t(),new L(Kf)),e,g,h,k,l,m);if(d instanceof L){var Og=d.k|0;if(a.Wq){var mi=new Iw(m.S,m.Ec,m.hc,m.Ed,1+Og|0,m.Pc,m.Zc,m.Lb,m.yc,m.tb,m.$a,m.od,m.cb),Ci=new Qx(a,Kf,xf);return TA(Ci,\nmi)}}return yx(zx(a),Kf,xf)}if(b instanceof cv){var Xh=b.ac;return new cv(a,EA(a,b.Nb,t().d,t().d,e,g,h,k,l,m),EA(a,Xh,t().d,d,e,g,h,k,l,m),b.Mj)}var wh=t().d;return UA(b,wh,!0,new fn((ng,kh)=>EA(a,kh,t().d,t().d,e,g,h,k,l,m)),h)}catch(ng){if(ng instanceof Iq){var Bh=ng;if(Bh.Qg===r)return Bh.Cj();throw Bh;}throw ng;}};\nfunction eca(a,b,c,d,e,g,h,k){if(null===b)throw le();if(b.sb)return b.vb;lv();var l=x=>{x=x.h().x;a:{for(var A=x.length,B=0;B<A;){var C=x.charCodeAt(B);if(!Nm(new E(hc(C)),hc(35))){A=B;break a}B=1+B|0}A=-1}return d.L(-1===A?x:x.substring(0,A))},m=c.Ba;a:for(;;)if(m.b()){l=u();break}else{var n=m.e();c=m.f();if(!0===!!l(n))m=c;else for(;;){if(c.b())l=m;else{n=c.e();if(!0!==!!l(n)){c=c.f();continue}n=c;c=new z(m.e(),u());var r=m.f();for(m=c;r!==n;){var v=new z(r.e(),u());m=m.p=v;r=r.f()}for(r=n=n.f();!n.b();){v=\nn.e();if(!0===!!l(v)){for(;r!==n;)v=new z(r.e(),u()),m=m.p=v,r=r.f();r=n.f()}n=n.f()}r.b()||(m.p=r);l=c}break a}}return me(b,ry(0,l,new y(x=>{var A=x.Va,B=x.Oa;if(B.b())B=R();else{B=B.o();if(e.b())var C=R();else C=!!e.o(),C=new L(!C);B=new L(VA(a,B,C,t().d,g,h,k))}return new Uw(A,B,VA(a,x.ra,e,t().d,g,h,k),x.Pd)})))}function WA(a,b,c,d,e,g,h,k){return b.sb?b.vb:eca(a,b,c,d,e,g,h,k)}\nfunction XA(a,b,c,d,e,g,h){Nx(a,new U(()=>\"DNF: \"+b));var k=Pt(b.xe,new y(n=>{if(null!==n){var r=n.Pf,v=n.Of,x=n.Af;if(ow(n.Nf)&&r.b()&&(!Gw(v)||!x.b()))return t(),new fe(n)}t();return new Ud(n)}));if(null!==k)k=G(new H,k.h(),k.j());else throw new w(k);var l=k.h();k=k.j();if(l.b())l=a.ib;else{l=YA(l,a.La,new fn((n,r)=>{r=r.zf(!0);var v=V(r.q);r=NA(r,v,!1);v=V(n.q);return Pu(n,r,v,!1)}));var m=new y(n=>!n);l=VA(a,l,c.b()?R():new L(m.n(c.o())),t().d,e,g,h);m=V(l.q);l=NA(l,m,!1)}m=ZA($A(a));k=Qt(qw(k,\nm),new y(n=>{n.Pf.Ca(new y(r=>{aB(a,r,h,e,g)}));n.Af.Ca(new y(r=>{aB(a,r,h,e,g)}));return fca(n,new y(r=>{if(r instanceof Ku){var v=r.fc,x=r.vd,A=r.be,B=r.Me,C=new y(Pa=>{if(null!==Pa){var Db=Pa.h(),Oc=Pa.j();if(null!==Oc)return Pa=new fw(a,Oc.qb,bw(Oc,c,new fn((Tc,Sd)=>VA(a,Sd,Tc,t().d,e,g,h)),e),Oc.Xl),G(new H,Db,Pa)}throw new w(Pa);}),D=Su(),F=op().ga,I=B.gR(C,new Uu(D,F)),M=x.m(),N=new Ex(M,new bB(a)),P=Aq(Bq(),N),T=!1,Y=null;if(v instanceof L){T=!0;Y=v;var Z=Y.k;if(Z instanceof Mu){var S=Z.pd,\nea=Z.JE;if(S instanceof vl){var ia=S.x;if(!a.cn.L(ia)&&e.tb.L(Nu(Q(),ia))&&!a.$c){var X=Nu(Q(),ia),sa=new Ep(X),Ja=e.tb.n(X),Xa=A.Ba;op();var Fa=pp(qp(),Xa),za=ry(lv(),A.Ba,new y(Pa=>cB(Pa,new y(Db=>{var Oc=new y(Tc=>!Tc);return VA(a,Db,c.b()?R():new L(Oc.n(c.o())),t().d,e,g,h)}),new y(Db=>VA(a,Db,c,t().d,e,g,h))))),Qa=new Qv(A.q,za,A.Nj);Nx(a,new U(()=>\"rcd2 \"+Qa));var Ma=dB(Ja),Ga=Ja.Wl,ab=Qt(Hf(Ja.Xm),new y(Pa=>{if(null!==Pa){var Db=Pa.h(),Oc=Pa.Sc();if(null!==Db){var Tc=Db.j(),Sd=new vl(sa.V+\n\"#\"+Db.h().V);Pa=I.U(sa);Db=new y(Jc=>{Jc=eB(Jc.Zb,Oc);return(new y(vd=>{t();return new Uw(a,new L(vd),vd,V(a))})).n(Jc)});Pa=Pa.b()?R():new L(Db.n(Pa.o()));Pa=iu(ju(),Pa);Db=Qa.Ba.m();Db=new iy(Db,new y(Jc=>Pe(new E(Jc.h()),Sd)),!1);Db=new Ef(Db,new y(Jc=>Jc.j()));Pa=Pa.tl(Db).De(G(new H,a.ib,a.La),new fn((Jc,vd)=>{var hd=G(new H,Jc,vd);Jc=hd.y;var de=hd.w;if(null!==Jc&&(vd=Jc.h(),Jc=Jc.j(),null!==de)){hd=de.Oa;de=de.ra;var ye=new U(()=>a.ib);hd=hd.b()?Es(ye):hd.o();ye=V(vd.q);vd=dv(vd,hd,ye,!1);\nhd=V(Jc.q);return G(new H,vd,Pu(Jc,de,hd,!1))}throw new w(hd);}));return(new y(Jc=>{if(null!==Jc){var vd=Jc.h();Jc=Jc.j();var hd=Ma.n(Tc);if(null!==hd){var de=hd.qe;if(!0===hd.Qd&&!0===de)return dw(cw(a),a.ib,a.La,ew(cw(a)),e)}if(null!==hd&&(de=hd.qe,!1===hd.Qd&&!1===de))return dw(cw(a),vd,Jc,ew(cw(a)),e);if(null!==hd)return hd.Qd?Jc:vd;throw new w(hd);}throw new w(Jc);})).n(Pa)}}throw new w(Pa);})),Hb=new fw(a,Ga,ab,V(a));Nx(a,new U(()=>\"typeRef \"+Hb));var bc=fB(a,gB(Hb,!0,!1,e),!0,e);Nx(a,new U(()=>\n\"clsFields \"+ze(bc,\"\",\", \",\"\")));ea.Ja(new y(Pa=>Nu(Q(),Pa.V))).bc(X).Ce(P);var yb=new Qv(a,gy(Qa.Ba,new y(Pa=>{if(null!==Pa){var Db=Pa.h(),Oc=Pa.j();Pa=bc.U(Db);var Tc=new y(Sd=>{var Jc=Xu().X();if(Fw(Sd,Oc,e,Jc))return!0;Jc=Fa.U(Db);var vd=new y(hd=>{var de=Xu().X();return Fw(Sd,hd,e,de)});return!Jc.b()&&!!vd.n(Jc.o())});return!Pa.b()&&!!Tc.n(Pa.o())}throw new w(Pa);}),!0),Qa.Nj),tb=Qa.Ba,eb=op(),kb=tb.Gb(eb.ga).h(),Rb=Aq(Bq(),kb),Gb=bc.tj(),vb=new iy(Gb,new y(Pa=>hB(ve(),Pa.x)?!0:Rb.L(Pa)),!0),\nTb=Su(),Nb=op().ga,ic=new Uu(Tb,Nb),Va=oA(uv(),vb,ic),cb=Va.b()?Hb:iB(Hb,Va);if(Qa.Ba.ul(new y(Pa=>{if(null!==Pa){var Db=Pa.h(),Oc=Pa.j();Pa=bc.U(Db);var Tc=new y(Sd=>{var Jc=Xu().X();if(Fw(Oc,Sd,e,Jc))return!0;Jc=Fa.U(Db);var vd=new y(hd=>{var de=Xu().X();return Fw(hd,Sd,e,de)});return!Jc.b()&&!!vd.n(Jc.o())});return Pa.b()||!!Tc.n(Pa.o())}throw new w(Pa);}))){var zb=Lu(yb),Ub=V(Hb.q);jb=Pu(Hb,zb,Ub,!1)}else if(yb.Ba.b())var jb=cb;else{var db=Lu(yb);jb=new $y(a,cb,db,V(a))}ms();ms();var ub=new jB(da(Ru)),\nAa=kB(x,ub),va=Su(),Ra=op().ga,rb=Tu(Aa,new Uu(va,Ra)),xb=lB(rb,jb,new fn((Pa,Db)=>{var Oc=V(Pa.q);return Pu(Pa,Db,Oc,!1)})),mc=I.xj(Ja.Wl),Ha=new Ou(mc);return mB(Ha,xb,new fn((Pa,Db)=>{var Oc=V(Pa.q);return Pu(Pa,Db,Oc,!1)}))}}}}if(T){var Ka=Y.k;if(Ka instanceof Mu){var Oa=Ka.pd,Na=Ka.JE;if(Oa instanceof vl){var Da=Oa.x;if(!a.cn.L(Da)&&e.$a.L(Da)&&!e.$a.n(Da).eo.b()){var ta=new Ep(Da),Ya=e.$a.n(Da).eo;a:{if(Ya instanceof L){var dc=Ya.k;if(dc instanceof Yw){var ka=dc;break a}}xm(\"Program reached and unexpected state.\")}var ya=\nA.Ba;op();var Sa=pp(qp(),ya),xc=ry(lv(),A.Ba,new y(Pa=>cB(Pa,new y(Db=>{var Oc=new y(Tc=>!Tc);return VA(a,Db,c.b()?R():new L(Oc.n(c.o())),t().d,e,g,h)}),new y(Db=>VA(a,Db,c,t().d,e,g,h))))),Sb=new Qv(A.q,xc,A.Nj);Nx(a,new U(()=>\"rcd2 \"+Sb));var uc=ka.Rf.gb,Lb=Qt(Hf(ka.gh),new y(Pa=>{if(null!==Pa){var Db=Pa.h(),Oc=Pa.Sc();if(null!==Db){var Tc=Db.hb,Sd=new vl(ta.V+\"#\"+Db.kc.V);Pa=I.U(ta);Db=new y(Jc=>{Jc=eB(Jc.Zb,Oc);return(new y(vd=>{t();return new Uw(a,new L(vd),vd,V(a))})).n(Jc)});Pa=Pa.b()?R():\nnew L(Db.n(Pa.o()));Pa=iu(ju(),Pa);Db=Sb.Ba.m();Db=new iy(Db,new y(Jc=>Pe(new E(Jc.h()),Sd)),!1);Db=new Ef(Db,new y(Jc=>Jc.j()));Pa=Pa.tl(Db).De(G(new H,a.ib,a.La),new fn((Jc,vd)=>{var hd=G(new H,Jc,vd);Jc=hd.y;var de=hd.w;if(null!==Jc&&(vd=Jc.h(),Jc=Jc.j(),null!==de)){hd=de.Oa;de=de.ra;var ye=new U(()=>a.ib);hd=hd.b()?Es(ye):hd.o();ye=V(vd.q);vd=dv(vd,hd,ye,!1);hd=V(Jc.q);return G(new H,vd,Pu(Jc,de,hd,!1))}throw new w(hd);}));return(new y(Jc=>{if(null!==Jc){var vd=Jc.h();Jc=Jc.j();var hd=RA(ka,Tc,\ne);if(null!==hd){var de=hd.qe;if(!0===hd.Qd&&!0===de)return dw(cw(a),a.ib,a.La,ew(cw(a)),e)}if(null!==hd&&(de=hd.qe,!1===hd.Qd&&!1===de))return dw(cw(a),vd,Jc,ew(cw(a)),e);if(null!==hd)return hd.Qd?Jc:vd;throw new w(hd);}throw new w(Jc);})).n(Pa)}}throw new w(Pa);})),lc=new fw(a,uc,Lb,V(a));Nx(a,new U(()=>\"typeRef \"+lc));var Xb=fB(a,gB(lc,!0,!1,e),!0,e);Nx(a,new U(()=>\"clsFields \"+ze(Xb,\"\",\", \",\"\")));Na.Ja(new y(Pa=>Nu(Q(),Pa.V))).bc(Da).Ce(P);var ec=new Qv(a,gy(Sb.Ba,new y(Pa=>{if(null!==Pa){var Db=\nPa.h(),Oc=Pa.j();Pa=Xb.U(Db);var Tc=new y(Sd=>{var Jc=Xu().X();if(Fw(Sd,Oc,e,Jc))return!0;Jc=Sa.U(Db);var vd=new y(hd=>{var de=Xu().X();return Fw(Sd,hd,e,de)});return!Jc.b()&&!!vd.n(Jc.o())});return!Pa.b()&&!!Tc.n(Pa.o())}throw new w(Pa);}),!0),Sb.Nj),Ab=Sb.Ba,Ob=op(),fb=Ab.Gb(Ob.ga).h();Aq(Bq(),fb);ms();ms();var Wa=new jB(da(Ru)),bb=kB(x,Wa),Ia=Su(),Ua=op().ga,pc=Tu(bb,new Uu(Ia,Ua)),sc=V(lc.q),Ba=lB(pc,Pu(lc,ec,sc,!1),new fn((Pa,Db)=>{var Oc=V(Pa.q);return Pu(Pa,Db,Oc,!1)})),ob=I.xj(ka.Rf.gb),nc=\nnew Ou(ob);return mB(nc,Ba,new fn((Pa,Db)=>{var Oc=V(Pa.q);return Pu(Pa,Db,Oc,!1)}))}}}}var Ib=new $e,vc=!1,Vb=null;a:{if(v instanceof L){vc=!0;Vb=v;var fc=Vb.k;if(fc instanceof zv){var Bc=fc.Yb,Pb=Bc.K(),Jb=gy(A.Ba,new y(Pa=>{Q();return P.L(gca(Pa.h().x,new y(Db=>Nm(new E(hc(Ea(Db))),hc(35)))))}),!0),gc=Pt(Jb,new y(Pa=>{var Db=nB(Pa.h()),Oc=new oB(0,Pb,1),Tc=new y(Sd=>pB(Oc,Sd|0));Db=Db.b()||Tc.n(Db.o())?Db:R();Tc=new y(Sd=>G(new H,Sd|0,Pa.j()));Db=Db.b()?R():new L(Tc.n(Db.o()));Tc=new U(()=>Pa);\nif(Db.b())return O(),Db=Es(Tc),new Ud(Db);O();Db=Db.o();return new fe(Db)}));if(null!==gc)var Cb=G(new H,gc.h(),gc.j());else throw new w(gc);var cc=Cb.h(),yc=Cb.j();op();var Mc=pp(qp(),cc),qc=Bc.m(),oc=new Ao(qc),Qc=new Ef(oc,new y(Pa=>{if(null!==Pa){var Db=Pa.h(),Oc=Pa.Sc();if(null!==Db)return Pa=Db.h(),Db=Db.j(),Oc=Mc.Se(Oc,new U(()=>{var Tc=a.La,Sd=V(a);return new Uw(Tc.q,R(),Tc,Sd)})),Oc=cB(Nv(Db,Oc,V(Db.Va)),new y(Tc=>{var Sd=new y(Jc=>!Jc);return VA(a,Tc,c.b()?R():new L(Sd.n(c.o())),t().d,e,\ng,h)}),new y(Tc=>VA(a,Tc,c,t().d,e,g,h))),G(new H,Pa,Oc)}throw new w(Pa);}));Od();var jc=Pd(u(),Qc);t();var sb=new zv(a,jc,fc.Nq),Gc=new L(sb),Wb=ry(lv(),yc,new y(Pa=>cB(Pa,new y(Db=>{var Oc=new y(Tc=>!Tc);return VA(a,Db,c.b()?R():new L(Oc.n(c.o())),t().d,e,g,h)}),new y(Db=>VA(a,Db,c,t().d,e,g,h)))));var Cc=G(new H,Gc,Wb);break a}}if(vc){var Fc=Vb.k;if(Fc instanceof Mu){t();var qd=new L(Fc),Yb=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,qd,Yb);break a}}if(vc){var Nc=Vb.k;if(Nc instanceof cv){var ad=Nc.Nb,Uc=\nNc.ac;t();var cd=new y(Pa=>!Pa),kc=VA(a,ad,c.b()?R():new L(cd.n(c.o())),t().d,e,g,h),Vc=new U(()=>zy(ju(),qB(b),new U(()=>b.fb))),Hc=new cv(a,kc,VA(a,Uc,c,d.b()?Es(Vc):d,e,g,h),Nc.Mj),rc=new L(Hc),sd=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,rc,sd);break a}}if(vc){var Kc=Vb.k;if(Kc instanceof Jv){t();var Qd=rB(Kc,c,new fn((Pa,Db)=>VA(a,Db,Pa,t().d,e,g,h))),Ad=new L(Qd),kd=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,Ad,kd);break a}}if(vc){var Hd=Vb.k;if(Hd instanceof Sv){var Rd=Hd.Fd;t();var Bd=new Sv(a,cB(Rd,new y(Pa=>\n{var Db=new y(Oc=>!Oc);return VA(a,Pa,c.b()?R():new L(Db.n(c.o())),t().d,e,g,h)}),new y(Pa=>VA(a,Pa,c,t().d,e,g,h))),Hd.Fx),ae=new L(Bd),dd=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,ae,dd);break a}}if(vc){var od=Vb.k;if(od instanceof Wv){t();var Ta=sB(od,new y(Pa=>VA(a,Pa,c,t().d,e,g,h)),new y(Pa=>{var Db=new y(Oc=>!Oc);return VA(a,Pa,c.b()?R():new L(Db.n(c.o())),t().d,e,g,h)}),new y(Pa=>VA(a,Pa,c,t().d,e,g,h)),od.Uu),wb=new L(Ta),$a=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,wb,$a);break a}}if(vc){var wa=Vb.k;if(wa instanceof\nTv){var hb=wa.Ic,ra=wa.kf;if(hb instanceof LA&&null!==ra&&ra.b()){t();var wc=new Tv(a,tB(hb,new y(Pa=>VA(a,Pa,c,t().d,e,g,h))),ra,wa.vp),ac=new L(wc),Id=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,ac,Id);break a}}}if(vc){var ud=Vb.k;if(ud instanceof Tv){var be=ud.Ic,re=ud.kf;t();var pe=new Tv(a,VA(a,be,c,t().d,e,g,h),re,ud.vp),bd=new L(pe),Rc=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,bd,Rc);break a}}if(t().d===v){var Wc=t().d,Wd=WA(a,Ib,A,P,c,e,g,h);Cc=G(new H,Wc,Wd)}else throw new w(v);}if(null!==Cc)var zd=G(new H,Cc.h(),\nCc.j());else throw new w(Cc);return(new Ku(a,zd.h(),x,Lu(new Qv(A.q,zd.j(),A.Nj)),I)).zf(!0)}if(Vu(a)===r)return a.La;throw new w(r);}),new y(r=>{if(lw(a)===r)return a.ib;if(r instanceof iw){var v=r.me,x=cB(r.Ne,new y(D=>{var F=new y(I=>!I);return VA(a,D,c.b()?R():new L(F.n(c.o())),t().d,e,g,h)}),new y(D=>VA(a,D,c,t().d,e,g,h)));v=G(new H,v,x);x=O().c;return new Qv(a,new z(v,x),V(a))}if(r instanceof jw){v=r.Xb;x=r.mb;r=r.Dc;var A=!1,B=null;a:{if(x instanceof L){A=!0;B=x;var C=B.k;if(C instanceof Ud&&\n(C=C.fa,null!==C)){x=(new iw(a,C.me,cB(C.Ne,new y(D=>{var F=new y(I=>!I);return VA(a,D,c.b()?R():new L(F.n(c.o())),t().d,e,g,h)}),new y(D=>VA(a,D,c,t().d,e,g,h))))).zf(!0);break a}}if(A&&(A=B.k,A instanceof fe)){x=VA(a,A.aa,c,t().d,e,g,h);break a}if(t().d===x)x=a.ib;else throw new w(x);}r=new Ou(r);r=new Ef(r,new y(D=>VA(a,D,c,t().d,e,g,h)));r=mB(r,a.ib,new fn((D,F)=>{var I=V(D.q);return dv(D,F,I,!1)}));A=Su();B=op().ga;v=qw(v,new Uu(A,B)).De(x,new fn((D,F)=>{var I=V(D.q);return dv(D,F,I,!1)}));x=\nV(r.q);return dv(r,v,x,!1)}throw new w(r);}))}));k=YA(k,a.ib,new fn((n,r)=>{var v=V(n.q);return dv(n,r,v,!1)}));k=(new y(n=>{a:{var r=uB(n,!0);n=O().c;for(r=er(r).m();r.s();){var v=r.t();b:{for(var x=n;!x.b();){var A=x.e(),B=Xu().X();if(Zu(v,A,e,!0,B)){x=!0;break b}x=x.f()}x=!1}x||(n=new z(v,n))}r=O().c;if(null===r?null===n:r.i(n))n=a.ib;else{if(n instanceof z&&(r=n.z,v=n.p,x=O().c,null===x?null===v:x.i(v))){n=r;break a}if(n===u())n=u();else{r=n.e();v=r=new z(uB(r,!1),u());for(n=n.f();n!==u();)x=\nn.e(),x=new z(uB(x,!1),u()),v=v.p=x,n=n.f();n=r}n=vB(a,n)}}return n})).n(k);m=V(k.q);k=dv(k,l,m,!1);l=Qt(b.Qf,new y(n=>{if(null!==n){var r=n.j();return G(new H,VA(a,n.h(),(t(),new L(!0)),t().d,e,g,h),VA(a,r,(t(),new L(!1)),t().d,e,g,h))}throw new w(n);}));k=wx(vx(a),l,k);return d instanceof L&&(l=d.k|0,a.Wq)?(l=new Iw(g.S,g.Ec,g.hc,g.Ed,1+l|0,g.Pc,g.Zc,g.Lb,g.yc,g.tb,g.$a,g.od,g.cb),k=new Qx(a,b.fb,k),TA(k,l)):yx(zx(a),b.fb,k)}\nfunction Wba(a,b,c,d,e,g,h){d=a.qa;if(a.F){var k=ut(Q(),\"| \",a.r)+(\"normLike[\"+dA(c)+\"] \")+b;ff(gf(),k+\"\\n\")}a.r=1+a.r|0;try{a:if(b instanceof zA)var l=VA(a,b,c,t().d,e,g,h);else{if(b instanceof BA){CA(a);t();var m=new L(b);if(!m.b()){l=wB(m.k,c,new fn((n,r)=>VA(a,r,n,t().d,e,g,h)),e);break a}}throw new w(b);}}finally{a.r=-1+a.r|0}dx(new E(d),a.qa)&&a.F&&(b=\"\"+ut(Q(),\"| \",a.r)+d.n(l),ff(gf(),b+\"\\n\"));return l}\nfunction VA(a,b,c,d,e,g,h){var k=new y(P=>\"~\\x3e \"+P);if(a.F){var l=ut(Q(),\"| \",a.r)+(\"norm[\"+dA(c)+\"] \")+b;ff(gf(),l+\"\\n\")}a.r=1+a.r|0;try{if(c instanceof L){var m=!!c.k,n=a.Df,r=O().c;xB(a);var v=ap(),x=XA(a,yB(xB(a),n,r,b,m,e,!0,!1,v),c,d,e,g,h)}else if(t().d===c){var A=a.Df,B=O().c;xB(a);var C=ap(),D=yB(xB(a),A,B,b,!1,e,!0,!1,C),F=a.Df,I=O().c;xB(a);var M=ap(),N=yB(xB(a),F,I,b,!0,e,!0,!1,M);x=dw(cw(a),XA(a,D,(t(),new L(!1)),d,e,g,h),XA(a,N,(t(),new L(!0)),d,e,g,h),ew(cw(a)),e)}else throw new w(c);\n}finally{a.r=-1+a.r|0}dx(new E(k),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+k.n(x),ff(gf(),a+\"\\n\"));return x}\nfunction aB(a,b,c,d,e){var g=new zB(c);if(!g.en.L(b))if(g.en.$(b),g=b.Sb,g instanceof L)g=g.k,t(),a=VA(a,g,t().d,t().d,d,e,c),wy(b,new L(a));else if(t().d===g){g=vy(b);if(g.b())g=R();else{g=g.m();if(!g.s())throw nv(\"empty.reduceLeft\");for(var h=!0,k=null;g.s();){var l=g.t();if(h)k=l,h=!1;else{var m=V(k.q);k=dv(k,l,m,!1)}}g=new L(k)}g.b()?(t(),g=O().c):(g=g.o(),g=VA(a,g,(t(),new L(!0)),t().d,d,e,c),h=O().c,g=new z(g,h));IA(b,g);g=rA(b);if(g.b())g=R();else{g=g.m();if(!g.s())throw nv(\"empty.reduceLeft\");\nh=!0;for(k=null;g.s();)l=g.t(),h?(k=l,h=!1):(m=V(k.q),k=Pu(k,l,m,!1));g=new L(k)}g.b()?(t(),a=O().c):(g=g.o(),a=VA(a,g,(t(),new L(!1)),t().d,d,e,c),c=O().c,a=new z(a,c));KA(b,a)}else throw new w(g);}function Yba(a,b,c,d,e,g){if(null===b)throw le();return b.sb?b.vb:me(b,new AB(a,c,d,e,g))}function nA(a,b,c,d,e,g,h,k){if(d.sb)a=d.vb;else{if(null===d)throw le();a=d.sb?d.vb:me(d,new BB(a,e,g,h,k,d))}mA(a,c,b.rT())}\nvar hca=function CB(a,b,c,d,e,g,h,k,l,m){var r=a.qa;if(a.F){var v=ut(Q(),\"| \",a.r)+(\"go \"+b+\"   (\"+ze(c,\"\",\", \",\"\"))+\")\";ff(gf(),v+\"\\n\")}a.r=1+a.r|0;try{var x=DB(b);a:if(x instanceof lx){if(EB(c,x)){var A=x.Sb;if(A instanceof L)CB(a,A.k,c,d,e,g,h,k,l,m);else if(t().d===A){var B=d.Ig(x.Xa);if(B instanceof L)for(var C=B.k?vy(x):rA(x);!C.b();){var D=C.e();CB(a,D,c,d,e,g,h,k,l,m);C=C.f()}else if(t().d===B){var F=a.qa;if(a.F){var I=ut(Q(),\"| \",a.r)+\"Analyzing invar-occ of \"+x;ff(gf(),I+\"\\n\")}a.r=1+a.r|\n0;try{nA(a,x,d,g,h,k,l,m);var M=void 0}finally{a.r=-1+a.r|0}if(dx(new E(F),a.qa)&&a.F){var N=\"\"+ut(Q(),\"| \",a.r)+F.n(M);ff(gf(),N+\"\\n\")}}else throw new w(B);}else throw new w(A);}}else{if(x instanceof LA){var P=x.ic,T=x.jc;if(Pe(new E(x.tc),e)){CB(a,P,c,d,e,g,h,k,l,m);CB(a,T,c,d,e,g,h,k,l,m);break a}}FB(c,b)}var Y=void 0}finally{a.r=-1+a.r|0}dx(new E(r),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+r.n(Y),ff(gf(),a+\"\\n\"))};\nfunction GB(a,b,c,d,e,g){Pe(new E(b),c)?c=d:(jA(),c=jA().X().$(e));a.F&&(a=ut(Q(),\"| \",a.r)+(\"\\x3e\\x3e\\x3e\\x3e occs[\"+HB(b)+e+\"] :\\x3d \"+c+\"  \\x3c~ \")+g.U(G(new H,b,e)),ff(gf(),a+\"\\n\"));a=g.U(G(new H,b,e));if(a instanceof L){if(b=a.k,e=c,!b.b()){IB();if(0<=b.Q())g=b.Q(),g=new zc(g),b.Gc(g,0,2147483647);else{g=[];for(c=b.m();c.s();)a=c.t(),g.push(null===a?null:a);g=new zc(g)}c=g.a.length;for(a=0;a<c;)d=g.a[a],e.n(d)||b.Bm(d),a=1+a|0}}else if(R()===a)g.bh(G(new H,b,e),JB(KB(),c));else throw new w(a);\n}function LB(a,b,c,d,e,g,h,k,l){var m=new MB;if(a.F){var n=ut(Q(),\"| \",a.r)+(\"\\x3e\\x3e Processing \"+b+\" at [\"+dA((t(),new L(d))))+\"]\";ff(gf(),n+\"\\n\")}hca(a,b,m,c,d,g,h,k,l,e);a.F&&(b=ut(Q(),\"| \",a.r)+\"\\x3e\\x3e Occurrences \"+m,ff(gf(),b+\"\\n\"));for(b=m.ku;null!==b;){n=b.zw;if(n instanceof lx){var r=c.Ig(n.Xa);if(r instanceof L)GB(a,!!r.k,d,m,n,e);else if(t().d===r)GB(a,!0,d,m,n,e),GB(a,!1,d,m,n,e);else throw new w(r);}b=b.Mo}for(d=m.ku;null!==d;)m=d.zw,m instanceof lx||nA(a,m,c,g,h,k,l,e),d=d.Mo}\nfunction pA(a,b,c){a=a.m();a=new iy(a,new y(d=>{var e;if(e=!b.L(d)){a:{e=d.Sb;if(e.b())e=vy(d);else{e=e.o();var g=O().c;e=new z(e,g)}for(g=d.q.ib;!e.b();){var h=e.e(),k=V(g.q);g=dv(g,h,k,!1);e=e.f()}e=g;g=gA(d.q).Pj;e=hA(e,g,c).U(d);if(e instanceof L&&(e=e.k,e=t().d===e?!0:e instanceof L&&!0===!!e.k?!0:!1,e)){e=!0;break a}e=!1}if(!e)a:{e=d.Sb;e.b()?e=rA(d):(e=e.o(),g=O().c,e=new z(e,g));for(g=d.q.La;!e.b();)h=e.e(),k=V(g.q),g=Pu(g,h,k,!1),e=e.f();e=g;g=gA(d.q).Jx;d=hA(e,g,c).U(d);if(d instanceof L&&\n(d=d.k,d=t().d===d?!0:d instanceof L&&!1===!!d.k?!0:!1,d)){e=!0;break a}e=!1}}return e}),!1);return Aq(Bq(),a)}\nfunction uA(a,b,c,d,e){var g=c.U(G(new H,b,d)).m();for(g=new xo(g,new y(Fa=>new qA(Fa)));g.s();){var h=g.t();if(h instanceof lx){var k=h;if((Ot(new E(k),d)?0:k.Sb.b())&&!e.L(k)&&(!d.kg.b()||k.kg.b()||e.L(d))&&Pe(new E(d.Xa),k.Xa)){h=a.qa;var l=a;if(l.F){var m=ut(Q(),\"| \",l.r),n=dA((t(),new L(b))),r=iu(ju(),c.U(G(new H,b,k)));m=m+(\"[w] \"+k+\" \"+n)+ze(r,\"\",\"\",\"\");ff(gf(),m+\"\\n\")}l.r=1+l.r|0;try{var v=b?rA(d):vy(d),x=b?rA(k):vy(k),A=Aq(Bq(),v);if(Nm(new E(A),Aq(Bq(),x))){if(m=a,m.F){var B=ut(Q(),\"| \",\nm.r)+(d+\" and \"+k)+\" have non-equal other bounds and won't be merged\";ff(gf(),B+\"\\n\")}}else{var C=c.U(G(new H,b,k));if(C.b()||C.o().L(d)){m=a;if(m.F){var D=ut(Q(),\"| \",m.r)+(\"  [U] \"+k+\" :\\x3d \")+d;ff(gf(),D+\"\\n\")}t();var F=G(new H,k,new L(d));e.$(F);IA(d,dl(vy(d),vy(k)));KA(d,dl(rA(d),rA(k)));var I=O().c;IA(k,new z(d,I));var M=O().c;KA(k,new z(d,M));var N=c.U(G(new H,!b,k));if(!N.b()){var P=N.o(),T=c.U(G(new H,!b,d));if(T instanceof L){var Y=T.k;if(!Y.b()){IB();if(0<=Y.ka()){var Z=Y.ka(),S=new zc(Z);\nNB(Y,S,0,2147483647);var ea=S}else{k=null;k=[];for(var ia=new qA(Y);ia.s();){var X=ia.t();k.push(null===X?null:X)}ea=new zc(k)}var sa=ea.a.length;for(k=0;k<sa;){var Ja=ea.a[k];m=Ja;Pe(new E(m),d)||P.L(m)||Y.IB(Ja);k=1+k|0}}}else if(t().d===T)c.bh(G(new H,!b,d),P);else throw new w(T);}}}var Xa=void 0}finally{l.r=-1+l.r|0}dx(new E(h),l.qa)&&l.F&&(h=\"\"+ut(Q(),\"| \",l.r)+h.n(Xa),ff(gf(),h+\"\\n\"))}}}}\nfunction OB(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B){var C=d.Sb;if(C instanceof L)C=C.k;else{if(t().d!==C)throw new w(C);C=PB(a,b,b?vy(d):rA(d))}return QB(a,C,new RB(c,d.Xa,b),e,g,h,k,l,m,n,r,v,x,A,B)}function Zba(a,b,c,d,e,g,h,k,l,m,n,r){if(b instanceof zA)return QB(a,b,c,d,t().d,d,g,h,e,k,!0,l,m,n,r);if(b instanceof BA){CA(a);t();var v=new L(b);if(!v.b())return ica(v.k,c,new fn((x,A)=>QB(a,A,x,d,t().d,d,g,h,e,k,!0,l,m,n,r)),e)}throw new w(b);}\nfunction SB(a,b,c,d,e,g,h,k,l,m,n,r,v){if(null!==b){var x=b.Oa,A=b.ra;if(x instanceof L&&Pe(new E(x.k),A))return c=QB(a,A,new TB(c),d,t().d,d,e,g,h,k,l,m,n,r,v),new Uw(a,(t(),new L(c)),c,b.Pd)}x=b.Va;A=b.Oa;A.b()?A=R():(A=A.o(),A=new L(QB(a,A,new UB(c),d,t().d,d,e,g,h,k,l,m,n,r,v)));return new Uw(x,A,QB(a,b.ra,c,d,t().d,d,e,g,h,k,l,m,n,r,v),b.Pd)}\nfunction VB(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B){var C=a.qa;a.F&&(c=ut(Q(),\"| \",a.r)+(\"Setting [\\u00b1] bounds of \"+b+\"... (failing \"+dA(c)+\", inlineBounds \"+d+\", !occursInvariantly \"+!e.L(g)+\", !recVars.contains(tv) \"+!h.rc.L(g))+\")\",ff(gf(),c+\"\\n\"));a.r=1+a.r|0;try{var D=g.Sb;if(D instanceof L){var F=D.k;t();var I=QB(a,F,new TB(k),l,m,l,r,v,x,A,d,e,h,n,B);wy(b,new L(I))}else if(t().d===D){if(n.L(G(new H,!0,g))){var M=vy(g);m=Qa=>{var Ma=new RB(k,g.Xa,!0);tp();return QB(a,Qa,Ma,gq(g),t().d,l,r,v,x,A,\nd,e,h,n,B)};if(M===u())var N=u();else{var P=M.e(),T=new z(m(P),u());P=T;for(var Y=M.f();Y!==u();){var Z=Y.e(),S=new z(m(Z),u());P=P.p=S;Y=Y.f()}N=T}IA(b,N)}if(n.L(G(new H,!1,g))){var ea=rA(g);M=Qa=>{var Ma=new RB(k,g.Xa,!1);tp();return QB(a,Qa,Ma,gq(g),t().d,l,r,v,x,A,d,e,h,n,B)};if(ea===u())var ia=u();else{var X=ea.e(),sa=new z(M(X),u());X=sa;for(var Ja=ea.f();Ja!==u();){var Xa=Ja.e(),Fa=new z(M(Xa),u());X=X.p=Fa;Ja=Ja.f()}ia=sa}KA(b,ia)}}else throw new w(D);var za=b}finally{a.r=-1+a.r|0}dx(new E(C),\na.qa)&&a.F&&(b=\"\"+ut(Q(),\"| \",a.r)+C.n(za),ff(gf(),b+\"\\n\"));return za}\nvar QB=function WB(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A){var C=new y(kc=>\"~\\x3e \"+kc);if(a.F){var D=ut(Q(),\"| \",a.r)+(\"transform[\"+dA(c.ol)+\"] \"+b+\"   (\"+ze(d,\"\",\", \",\"\")+\")  \"+c+\"  \")+e;ff(gf(),D+\"\\n\")}a.r=1+a.r|0;try{var F=!1,I=null,M=!1,N=null;a:if(b instanceof Qv){var P=b.Ba;var T=new Qv(a,ry(lv(),P,new y(kc=>SB(a,kc,c,g,h,k,l,m,n,r,v,x,A))),b.ma())}else if(b instanceof zv){var Y=b.Yb;T=new zv(a,ry(lv(),Y,new y(kc=>SB(a,kc,c,g,h,k,l,m,n,r,v,x,A))),b.ma())}else if(b instanceof Sv)T=new Sv(a,SB(a,b.Fd,\nc,g,h,k,l,m,n,r,v,x,A),b.ma());else if(b instanceof Wv){var Z=b.fo,S=kc=>{if(kc instanceof fe)return kc=kc.aa,t(),kc=WB(a,kc,c,g,t().d,g,h,k,l,m,n,r,v,x,A),new fe(kc);if(kc instanceof Ud)return kc=kc.fa,t(),kc=SB(a,kc,c,g,h,k,l,m,n,r,v,x,A),new Ud(kc);throw new w(kc);};if(Z===u())var ea=u();else{for(var ia=Z.e(),X=new z(S(ia),u()),sa=X,Ja=Z.f();Ja!==u();){var Xa=Ja.e(),Fa=new z(S(Xa),u());sa=sa.p=Fa;Ja=Ja.f()}ea=X}T=new Wv(a,ea,b.ma())}else if(b instanceof cv){var za=b.ac;T=new cv(a,WB(a,b.Nb,new UB(c),\ng,t().d,g,h,k,l,m,n,r,v,x,A),WB(a,za,c,g,e,g,h,k,l,m,n,r,v,x,A),b.ma())}else if(b instanceof Jv)T=jca(b,c,new fn((kc,Vc)=>WB(a,Vc,kc,d,e,g,h,k,l,m,n,r,v,x,A)));else if(b instanceof mx)T=WB(a,b.hi,c,d,t().d,g,h,k,l,m,n,r,v,x,A);else if(XB(b)||b instanceof YB||b instanceof FA)T=b;else{if(b instanceof lx&&(F=!0,I=b,d.L(I))){var Qa=!1,Ma=null,Ga=c.Ig(I.Xa);if(Ga instanceof L&&(Qa=!0,Ma=Ga,!0===!!Ma.k)){T=a.ib;break a}if(Qa&&!1===!!Ma.k){T=a.La;break a}if(t().d===Ga){T=WB(a,I,c,d.Ek(I),t().d,g,h,k,l,m,\nn,r,v,x,A);break a}throw new w(Ga);}if(F){var ab=!1,Hb=null,bc=h.U(I);if(bc instanceof L){ab=!0;Hb=bc;var yb=Hb.k;if(yb instanceof L){var tb=yb.k;if(a.F){var eb=ut(Q(),\"| \",a.r)+\"-\\x3e \"+tb;ff(gf(),eb+\"\\n\")}T=WB(a,tb,c,d.bc(I),e,g,h,k,l,m,n,r,v,x,A);break a}}if(ab){var kb=Hb.k;if(t().d===kb){var Rb=I;if(a.F){var Gb=ut(Q(),\"| \",a.r)+\"-\\x3e bound \"+c.Ig(Rb.Xa);ff(gf(),Gb+\"\\n\")}var vb=c.Ig(I.Xa);if(!k&&(vy(I).b()&&vb.L(!0)||rA(I).b()&&vb.L(!1)||vy(I).b()&&rA(I).b())){var Tb=new vl(\"?\"),Nb=ap();T=new Mu(a,\nTb,Nb,V(a))}else{var ic=I;vb.b()&&xm(\"Should not be replacing an invariant type variable by its bound...\");var Va=!!vb.o();T=OB(a,Va,c,ic,d.bc(ic),e,g,h,k,l,m,n,r,v,x,A)}break a}}if(t().d===bc){var cb=new GA(!0),zb=m.Hk(I,new U((kc=>()=>{cb.Am=!1;var Vc=V(a);t();var Hc=new L(kc),rc=kc.kg,sd=O().c,Kc=O().c;Vc=new lx(a,kc.Xa,sd,Kc,Hc,rc,!1,Vc);a.F&&(Hc=ut(Q(),\"| \",a.r)+(\"Renewed \"+kc+\" ~\\x3e \")+Vc,ff(gf(),Hc+\"\\n\"));return Vc})(I))),Ub=c.Ig(I.Xa);if(Ub instanceof L){var jb=!!Ub.k;if(n&&!r.L(I)&&!v.rc.L(I)){var db=\nI;if(a.F){var ub=ut(Q(),\"| \",a.r)+(\"Inlining [\"+HB(jb)+\"] bounds of \"+db+\" (~\\x3e \"+zb)+\")\";ff(gf(),ub+\"\\n\")}if(jb){var Aa=OB(a,!0,c,I,d.bc(I),e,g,h,k,l,m,n,r,v,x,A),va=V(Aa.q);T=dv(Aa,zb,va,!1)}else{var Ra=OB(a,!1,c,I,d.bc(I),e,g,h,k,l,m,n,r,v,x,A),rb=V(Ra.q);T=Pu(Ra,zb,rb,!1)}break a}}if(!cb.Am){if(Ub instanceof L){var xb=!!Ub.k;if(A.U(G(new H,!xb,I)).b()&&I.Sb.b()){var mc=xb?vy(I):rA(I);b:{for(var Ha=mc;!Ha.b();){var Ka=Ha.e();if(Ka instanceof lx)var Oa=h.U(Ka),Na=Oa.b()?!0:!Oa.o().b();else Na=\n!1;if(!Na){var Da=!1;break b}Ha=Ha.f()}Da=!0}if(Da){var ta=I;if(a.F){var Ya=ut(Q(),\"| \",a.r)+(\"NEW SUBS \"+ta)+\" -\\x3e N\";ff(gf(),Ya+\"\\n\")}var dc=I,ka=t().d,ya=G(new H,dc,ka);h.$(ya);var Sa=PB(a,xb,mc);T=WB(a,Sa,c,d.bc(I),e,g,h,k,l,m,n,r,v,x,A)}else T=VB(a,zb,Ub,n,r,I,v,c,g,e,x,h,k,l,m,A);break a}}T=VB(a,zb,Ub,n,r,I,v,c,g,e,x,h,k,l,m,A);break a}T=zb;break a}throw new w(bc);}if(b instanceof LA){M=!0;N=b;var xc=N.ic,Sb=N.jc;if(!0===N.tc){var uc=WB(a,xc,c,d,e,g,h,k,l,m,n,r,v,x,A),Lb=WB(a,Sb,c,d,e,g,h,\nk,l,m,n,r,v,x,A),lc=V(uc.q);T=dv(uc,Lb,lc,!1);break a}}if(M){var Xb=N.ic,ec=N.jc;if(!1===N.tc){var Ab=WB(a,Xb,c,d,e,g,h,k,l,m,n,r,v,x,A),Ob=WB(a,ec,c,d,e,g,h,k,l,m,n,r,v,x,A),fb=V(Ab.q);T=Pu(Ab,Ob,fb,!1);break a}}if(b instanceof MA){var Wa=WB(a,b.Fc,new UB(c),g,t().d,g,h,k,l,m,n,r,v,x,A),bb=V(Wa.q);T=NA(Wa,bb,!1)}else{if(b instanceof $y){var Ia=b.Oq,Ua=b.up;if(null!==Ua){var pc=Ua.Ba,sc=WB(a,Ia,c,g,e,g,h,k,l,m,n,r,v,x,A),Ba=ry(lv(),pc,new y(kc=>{var Vc=kc.Va,Hc=kc.Oa;Hc.b()?Hc=R():(Hc=Hc.o(),Hc=new L(WB(a,\nHc,new UB(c),g,t().d,g,h,k,l,m,n,r,v,x,A)));return new Uw(Vc,Hc,WB(a,kc.ra,c,g,t().d,g,h,k,l,m,n,r,v,x,A),kc.Pd)})),ob=new Qv(a,Ba,V(a));T=new $y(a,sc,ob,V(a));break a}}if(b instanceof ZB){$B(a);t();var nc=b.mc(),Ib=new L(nc);if(!Ib.b()){T=WB(a,Ib.k,c,d,e,g,h,k,l,m,n,r,v,x,A);break a}}if(b instanceof fw)T=new fw(a,b.qb,aC(b,c,new fn((kc,Vc)=>WB(a,Vc,kc,g,t().d,g,h,k,l,m,n,r,v,x,A)),l),b.Xl);else if(b instanceof Tv){var vc=b.Ic,Vb=b.kf;if(Vb.b())T=WB(a,vc,c,g,e,g,h,k,l,m,n,r,v,x,A);else if(Pe(new E(c.ol),\n(t(),new L(!0)))){var fc=WB(a,vc,c,g,e,g,h,k,l,m,n,r,v,x,A);T=bC(fc,Vb)}else{var Bc=WB(a,vc,c,g,e,g,h,k,l,m,n,r,v,x,A);T=iB(Bc,Vb)}}else if(b instanceof cC){var Pb=b.Fg,Jb=b.Sf,gc=c.ol;if(gc.b()){var Cb=cw(a),cc=WB(a,Pb,gA(a).Xu,d,e,g,h,k,l,m,n,r,v,x,A),yc=WB(a,Jb,gA(a).Pj,d,e,g,h,k,l,m,n,r,v,x,A);T=tA(Cb,cc,yc,V(a))}else T=gc.o()?WB(a,Jb,c,d,t().d,g,h,k,l,m,n,r,v,x,A):WB(a,Pb,c,d,t().d,g,h,k,l,m,n,r,v,x,A)}else if(b instanceof Qx){var Mc=b.de,qc=WB(a,b.Re,new dC(c,Mc),d,(t(),new L(Mc)),g,h,k,l,m,\nn,r,v,x,A);if(e instanceof L){var oc=e.k|0;if(a.Wq){var Qc=new Iw(l.S,l.Ec,l.hc,l.Ed,1+oc|0,l.Pc,l.Zc,l.Lb,l.yc,l.tb,l.$a,l.od,l.cb),jc=new Qx(a,Mc,qc);T=TA(jc,Qc);break a}}T=yx(zx(a),Mc,qc)}else if(b instanceof eC){var sb=b.Lj,Gc=b.kj,Wb=kc=>{if(null!==kc){var Vc=kc.j();return G(new H,WB(a,kc.h(),gA(a).Pj,g,t().d,g,h,k,l,m,n,r,v,x,A),WB(a,Vc,gA(a).Jx,g,t().d,g,h,k,l,m,n,r,v,x,A))}throw new w(kc);};if(sb===u())var Cc=u();else{for(var Fc=sb.e(),qd=new z(Wb(Fc),u()),Yb=qd,Nc=sb.f();Nc!==u();){var ad=\nNc.e(),Uc=new z(Wb(ad),u());Yb=Yb.p=Uc;Nc=Nc.f()}Cc=qd}T=new eC(a,Cc,WB(a,Gc,c,d,t().d,g,h,k,l,m,n,r,v,x,A))}else throw new w(b);}}}finally{a.r=-1+a.r|0}if(dx(new E(C),a.qa)&&a.F){var cd=\"\"+ut(Q(),\"| \",a.r)+C.n(T);ff(gf(),cd+\"\\n\")}return T};function fC(a,b,c,d,e,g,h,k){if(null===b)throw le();return b.sb?b.vb:me(b,UA(c,d,!0,new fn((l,m)=>gC(a,l,m,e,h,g,k)),g))}\nvar gC=function hC(a,b,c,d,e,g,h){for(;;){var l=!1,m=null,n=uy(c);if(n instanceof lx&&(l=!0,m=n,iC(a),n=m.Sb,!n.b()))return b=n.o(),d=new zB(e),c=m,l=a,a=m,d.en.L(c)||(d.en.$(c),t(),e=hC(l,t().d,b,(t(),new L(a)),e,g,h),wy(a,new L(e))),m;if(l){d=new zB(e);c=m;b=a;a=m;if(!d.en.L(c)){d.en.$(c);n=vy(a);d=((v,x,A,B,C)=>D=>hC(v,(t(),new L(!0)),D,(t(),new L(x)),A,B,C))(b,a,e,g,h);if(n===u())d=u();else{c=n.e();l=c=new z(d(c),u());for(n=n.f();n!==u();){var r=n.e();r=new z(d(r),u());l=l.p=r;n=n.f()}d=c}IA(a,\nd);d=rA(a);e=((v,x,A,B,C)=>D=>hC(v,(t(),new L(!1)),D,(t(),new L(x)),A,B,C))(b,a,e,g,h);if(d===u())e=u();else{g=d.e();h=g=new z(e(g),u());for(b=d.f();b!==u();)d=b.e(),d=new z(e(d),u()),h=h.p=d,b=b.f();e=g}KA(a,e)}return m}m=new $e;if(b instanceof L){n=!!b.k;l=h.U(G(new H,n,c));if(l instanceof L&&(l=l.k,d.b()?r=!0:(r=d.o(),r=dx(new E(r),l)),r)){m=a;m.F&&(m=ut(Q(),\"| \",m.r)+(\"!unskid-1! \"+c+\" -\\x3e \")+l,ff(gf(),m+\"\\n\"));c=l;continue}l=m.sb?m.vb:fC(a,m,c,b,d,g,e,h);l=h.U(G(new H,n,l));if(l instanceof\nL&&(l=l.k,d.b()?n=!0:(n=d.o(),n=dx(new E(n),l)),n)){r=n=a;n.F&&(m=ut(Q(),\"| \",n.r)+(\"!unskid-2! \"+(m.sb?m.vb:fC(r,m,c,b,d,g,e,h))+\" -\\x3e \")+l,ff(gf(),m+\"\\n\"));c=l;continue}return m.sb?m.vb:fC(a,m,c,b,d,g,e,h)}if(t().d===b)return m.sb?m.vb:fC(a,m,c,b,d,g,e,h);throw new w(b);}};function $ba(a,b,c,d,e,g){if(c instanceof zA)return gC(a,b,c,t().d,e,d,g);if(c instanceof BA){CA(a);t();var h=new L(c);if(!h.b())return wB(h.k,b,new fn((k,l)=>gC(a,k,l,t().d,e,d,g)),d)}throw new w(c);}\nfunction jC(a,b,c){a.F&&(a=ut(Q(),\"| \",a.r)+(\"Nope(\"+ag(ca(b))+\"): \"+b+\" ~ \")+c,ff(gf(),a+\"\\n\"));return!1}function kC(a,b,c,d,e,g,h){if(null!==b){var k=b.Oa,l=b.ra;if(k instanceof L&&(k=k.k,null!==c)){var m=c.Oa,n=c.ra;if(m instanceof L)return yA(a,k,m.k,d,e)&&yA(a,l,n,d,e)}}return null!==b&&(l=b.Oa,b=b.ra,t().d===l&&null!==c&&(l=c.Oa,c=c.ra,t().d===l))?yA(a,b,c,d,e):jC(a,g,h)}\nvar yA=function lC(a,b,c,d,e){for(;;){var h=b,k=c;if((null===d?null===h:mC(d,h))&&(null===e?null===k:mC(e,k))||(null===e?null===h:mC(e,h))&&(null===d?null===k:mC(d,k)))return!0;if(h instanceof lx){var l=h;if(k instanceof lx)return Ot(new E(l),k)||jC(a,b,c)}if(h instanceof MA){var m=h.Fc;if(k instanceof MA){var n=k.Fc;b=m;c=n;continue}}if(h instanceof Mu){var r=h.pd;if(k instanceof Mu)return Pe(new E(r),k.pd)||jC(a,b,c)}if(h instanceof Sv){var v=h.Fd;if(k instanceof Sv)return kC(a,v,k.Fd,d,e,b,c)}if(h instanceof\nzv){var x=h.Yb;if(k instanceof zv){var A=k.Yb,B=x.K();if(Pe(new E(B),A.K())||jC(a,b,c)){if(x===u())var C=u();else{for(var D=x.e(),F=new z(D.j(),u()),I=F,M=x.f();M!==u();){var N=M.e(),P=new z(N.j(),u());I=I.p=P;M=M.f()}C=F}if(A===u())var T=u();else{for(var Y=A.e(),Z=new z(Y.j(),u()),S=Z,ea=A.f();ea!==u();){var ia=ea.e(),X=new z(ia.j(),u());S=S.p=X;ea=ea.f()}T=Z}for(var sa=new Wq(C,C,T),Ja=a,Xa=b,Fa=c,za=sa.ck.m(),Qa=sa.dk.m(),Ma=!1;!Ma&&za.s()&&Qa.s();){var Ga=za.t(),ab=Qa.t();Ma=!kC(Ja,Ga,ab,d,e,\nXa,Fa)}return!Ma}return!1}}if(h instanceof cv){var Hb=h,bc=Hb.Nb,yb=Hb.ac;if(k instanceof cv){var tb=k,eb=tb.ac;if(lC(a,bc,tb.Nb,d,e)){b=yb;c=eb;continue}else return!1}}if(h instanceof Tv){var kb=h,Rb=kb.Ic,Gb=kb.kf;if(k instanceof Tv){var vb=k,Tb=vb.kf;return lC(a,Rb,vb.Ic,d,e)&&(Pe(new E(Gb),Tb)||jC(a,b,c))}}if(h instanceof nC){var Nb=h.rp;if(k instanceof nC)return Pe(new E(Nb),k.rp)||jC(a,b,c)}if(h instanceof mx){var ic=h.hi;if(k instanceof mx)return Pe(new E(ic),k.hi)||jC(a,b,c)}if(h instanceof\nFA){var Va=h.Eh;if(k instanceof FA)return Pe(new E(Va),k.Eh)||jC(a,b,c)}if(h instanceof cC){var cb=h,zb=cb.Fg,Ub=cb.Sf;if(k instanceof cC){var jb=k,db=jb.Sf;if(lC(a,zb,jb.Fg,d,e)){b=Ub;c=db;continue}else return!1}}if(h instanceof LA){var ub=h,Aa=ub.tc,va=ub.ic,Ra=ub.jc;if(k instanceof LA){var rb=k,xb=rb.ic,mc=rb.jc;if((Pe(new E(Aa),rb.tc)||jC(a,b,c))&&lC(a,va,xb,d,e)){b=Ra;c=mc;continue}else return!1}}if(h instanceof Qv){var Ha=h.Ba;if(k instanceof Qv){var Ka=k.Ba,Oa=Ha.K();if(Pe(new E(Oa),Ka.K())){for(var Na=\nnew Wq(Ha,Ha,Ka),Da=a,ta=b,Ya=c,dc=Na.ck.m(),ka=Na.dk.m(),ya=!1;!ya&&dc.s()&&ka.s();){var Sa=dc.t(),xc=ka.t(),Sb=Sa,uc=xc;ya=!((Pe(new E(Sb.h()),uc.h())||jC(Da,ta,Ya))&&kC(Da,Sb.j(),uc.j(),d,e,ta,Ya))}return!ya}return!1}}if(h instanceof $y){var Lb=h,lc=Lb.Oq,Xb=Lb.up;if(k instanceof $y){var ec=k,Ab=ec.up;if(lC(a,lc,ec.Oq,d,e)){b=Xb;c=Ab;continue}else return!1}}if(h instanceof ZB){var Ob=h;$B(a);t();var fb=Ob.mc(),Wa=new L(fb);if(!Wa.b()){b=Wa.k;continue}}if(k instanceof ZB){var bb=k;$B(a);t();var Ia=\nbb.mc(),Ua=new L(Ia);if(!Ua.b()){c=Ua.k;continue}}if(h instanceof fw){var pc=h,sc=pc.qb,Ba=pc.Zb;if(k instanceof fw){var ob=k,nc=ob.Zb;if(Pe(new E(sc),ob.qb)||jC(a,b,c)){for(var Ib=new Wq(Ba,Ba,nc),vc=a,Vb=Ib.ck.m(),fc=Ib.dk.m(),Bc=!1;!Bc&&Vb.s()&&fc.s();){var Pb=Vb.t(),Jb=fc.t();Bc=!lC(vc,Pb,Jb,d,e)}return!Bc}return!1}}return jC(a,b,c)}};function oC(){this.op=null}oC.prototype=new p;oC.prototype.constructor=oC;function pC(){}pC.prototype=oC.prototype;\nfunction saa(a,b,c,d,e){var g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\"\\u2b24 Initial: \"+b,ff(gf(),g+\"\\n\"));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\" where: \"+xx(b),ff(gf(),g+\"\\n\"));b=eA(a.op,b,c,!0,!1,e);g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\"\\u2b24 Cleaned up: \"+b,ff(gf(),g+\"\\n\"));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\" where: \"+xx(b),ff(gf(),g+\"\\n\"));c.b()||(g=!!c.o(),b=vA(a.op,b,g,e));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\"\\u2b24 Unskid: \"+b,ff(gf(),g+\"\\n\"));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\" where: \"+xx(b),ff(gf(),g+\"\\n\"));b=kA(a.op,\nb,d,c,e);g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\"\\u2b24 Type after simplification: \"+b,ff(gf(),g+\"\\n\"));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\" where: \"+xx(b),ff(gf(),g+\"\\n\"));b=iA(a.op,b,c,e);g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\"\\u2b24 Normalized: \"+b,ff(gf(),g+\"\\n\"));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\" where: \"+xx(b),ff(gf(),g+\"\\n\"));b=eA(a.op,b,c,!1,!0,e);g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\"\\u2b24 Cleaned up: \"+b,ff(gf(),g+\"\\n\"));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\" where: \"+xx(b),ff(gf(),g+\"\\n\"));c.b()||(g=!!c.o(),b=\nvA(a.op,b,g,e));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\"\\u2b24 Unskid: \"+b,ff(gf(),g+\"\\n\"));g=a.Ui;g.F&&(g=ut(Q(),\"| \",g.r)+\" where: \"+xx(b),ff(gf(),g+\"\\n\"));b=kA(a.op,b,d,c,e);d=a.Ui;d.F&&(d=ut(Q(),\"| \",d.r)+\"\\u2b24 Resim: \"+b,ff(gf(),d+\"\\n\"));d=a.Ui;d.F&&(d=ut(Q(),\"| \",d.r)+\" where: \"+xx(b),ff(gf(),d+\"\\n\"));b=aca(a.op,b,c,e);c=a.Ui;c.F&&(c=ut(Q(),\"| \",c.r)+\"\\u2b24 Factored: \"+b,ff(gf(),c+\"\\n\"));a=a.Ui;a.F&&(a=ut(Q(),\"| \",a.r)+\" where: \"+xx(b),ff(gf(),a+\"\\n\"));return b}\nfunction qC(a,b){this.aO=null;this.bO=b;if(null===a)throw null;this.aO=a}qC.prototype=new p;qC.prototype.constructor=qC;function rC(a,b){var c=a.aO;a=a.bO;b=b.m();return new qC(c,a.bf(new Ef(b,new y(d=>{if(null!==d)return G(new H,d.hb,d.kc);throw new w(d);}))))}qC.prototype.$classData=q({QY:0},!1,\"mlscript.Typer$ExpCtx$1\",{QY:1,g:1});function sC(a){this.rI=null;if(null===a)throw null;this.rI=a}sC.prototype=new p;sC.prototype.constructor=sC;\nfunction tC(a,b,c,d){if(c.yc&&kca(b)){c=(new Dx(c.Ec)).wF;c.b()?c=t().d:(c=c.o(),c=uC(c,c,b.x));c=Wk(new vC(a)).Ob(c,new y(()=>{t();return R()}));var e=new wC(a,b,d);Wk(e).Ob(c,new y(()=>{t();return R()}));return xC(yC(a.rI),b,d)}return t().d}sC.prototype.$classData=q({SY:0},!1,\"mlscript.Typer$ValidPatVar$\",{SY:1,g:1});function zC(a){this.sI=null;if(null===a)throw null;this.sI=a}zC.prototype=new p;zC.prototype.constructor=zC;\nfunction xC(a,b,c){t();a.sI.uP.L(b.x)&&Lw(a.sI,We(Xe(),\"Illegal use of reserved operator: \"+b.x),b.A(),c);return new L(b.x)}zC.prototype.$classData=q({VY:0},!1,\"mlscript.Typer$ValidVar$\",{VY:1,g:1});function AC(){}AC.prototype=new p;AC.prototype.constructor=AC;AC.prototype.$classData=q({XY:0},!1,\"mlscript.TyperDatatypes$AssignedVariable$\",{XY:1,g:1});function BC(){}BC.prototype=new p;BC.prototype.constructor=BC;BC.prototype.$classData=q({eZ:0},!1,\"mlscript.TyperDatatypes$DelayedTypeInfo$\",{eZ:1,g:1});\nfunction CC(){}CC.prototype=new p;CC.prototype.constructor=CC;CC.prototype.$classData=q({rZ:0},!1,\"mlscript.TyperDatatypes$OtherTypeLike$\",{rZ:1,g:1});function DC(){}DC.prototype=new p;DC.prototype.constructor=DC;DC.prototype.$classData=q({wZ:0},!1,\"mlscript.TyperDatatypes$ProxyType$\",{wZ:1,g:1});function EC(a){this.PO=null;if(null===a)throw null;this.PO=a}EC.prototype=new p;EC.prototype.constructor=EC;function lca(a,b,c,d){return a.PO.Wq?mca(b,b.Re,ap(),b.de,c,d):t().d}\nEC.prototype.$classData=q({BZ:0},!1,\"mlscript.TyperDatatypes$SplittablePolyFun$\",{BZ:1,g:1});function FC(a,b){if(null===b)throw null;a.J=b}function GC(){this.J=null}GC.prototype=new p;GC.prototype.constructor=GC;function HC(){}HC.prototype=GC.prototype;function IC(){}IC.prototype=new p;IC.prototype.constructor=IC;IC.prototype.$classData=q({LZ:0},!1,\"mlscript.TyperDatatypes$TypeVariable$\",{LZ:1,g:1});\nvar nca=function JC(a,b,c,d,e,g,h,k){for(;;){var m=c.U(b);if(m instanceof L){if(b=m.k,!d)return b}else{if(t().d===m){var n=!1;m=null;var r=b;if(r instanceof lx){n=!0;m=r;iC(a);var v=m.Sb;if(!v.b())return b=v.o(),e.Se(m,new U(((x,A,B,C,D,F,I,M,N)=>()=>{var P=A.ji;t();var T=new L(A),Y=A.kg,Z=O().c,S=O().c;P=new lx(x,A.Xa,Z,S,T,Y,!1,P);T=G(new H,A,P);B.$(T);t();T=JC(x,C,D,F,B,I,M,N);wy(P,new L(T));return P})(a,m,e,b,c,d,g,h,k)))}if(n&&vy(m).b()&&rA(m).b())return c=G(new H,m,m),e.$(c),m;if(n)return e.Se(m,\nnew U(((x,A,B,C,D,F,I,M)=>()=>{var N=A.ji;t();var P=new L(A),T=A.kg,Y=O().c,Z=O().c;N=new lx(x,A.Xa,Y,Z,P,T,!1,N);P=G(new H,A,N);B.$(P);Z=vy(A);P=(ea=>ia=>JC(ea,ia,C,D,B,F,I,M))(x);if(Z===u())P=u();else{T=Z.e();Y=T=new z(P(T),u());for(Z=Z.f();Z!==u();){var S=Z.e();S=new z(P(S),u());Y=Y.p=S;Z=Z.f()}P=T}IA(N,P);Z=rA(A);P=(ea=>ia=>JC(ea,ia,C,D,B,F,I,M))(x);if(Z===u())P=u();else{T=Z.e();Y=T=new z(P(T),u());for(Z=Z.f();Z!==u();)S=Z.e(),S=new z(P(S),u()),Y=Y.p=S,Z=Z.f();P=T}KA(N,P);return N})(a,m,e,c,d,\ng,h,k)));if(r instanceof Qx&&(m=r,m.de<g)){b=ap();b=KC(m,g,b,h,k);continue}return tB(b,new y(((x,A,B,C,D,F,I)=>M=>JC(x,M,A,B,C,D,F,I))(a,c,d,e,g,h,k)))}throw new w(m);}}};function LC(a,b){b=b.m();b=new Ef(b,new y(g=>{for(var h=a.La;!g.b();){var k=g.e(),l=V(h.q);h=Pu(h,k,l,!1);g=g.f()}return h}));for(var c=a.ib;b.s();){var d=b.t(),e=V(c.q);c=dv(c,d,e,!1)}return c}function oca(a){a.Ep=0;a.an=0;a.Gp=0;a.Fp=0;a.qa=new y(()=>\"\");a.r=0}\nfunction MC(){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0}MC.prototype=new p;MC.prototype.constructor=MC;function NC(){}NC.prototype=MC.prototype;function pca(a){null===a.jo&&null===a.jo&&(a.jo=new OC(a));return a.jo}function Iv(a){null===a.ho&&null===a.ho&&(a.ho=new PC(a));return a.ho}function gA(a){null===a.io&&null===a.io&&(a.io=new QC(a));return a.io}\nfunction Lx(a,b,c,d){Nx(a,b);a.r=1+a.r|0;try{var e=Es(c)}finally{a.r=-1+a.r|0}dx(new E(d),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+d.n(e),ff(gf(),a+\"\\n\"));return e}function Nx(a,b){a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+Es(b),ff(gf(),a+\"\\n\"))}function HB(a){if(!0===a)return\"+\";if(!1===a)return\"-\";throw new w(a);}function dA(a){if(a instanceof L)return HB(!!a.k);if(t().d===a)return\"\\x3d\";throw new w(a);}\nfunction Yv(a,b){var c=a.Q()+b.Q()|0;b=Lv(Lv(Mv(8<c?c:8),a),b);a=Xu().X();for(b=sl(b).m();b.s();){var d=b.t();c=d.h();var e=a.U(c);if(e instanceof L)e=e.k,d=Nv(e,d.j(),V(e.Va));else{if(R()!==e)throw new w(e);d=d.j()}a.bj(c,d)}b=qp();a=(new Pv(b)).vc(a);Od();return Pd(u(),a)}\nfunction RC(a,b){op();b=pp(qp(),b);for(var c=null,d=null;a!==u();){var e=a.e();if(null===e)throw new w(e);var g=e.h();e=e.j();var h=b.U(g);h.b()?g=R():(h=h.o(),e=xw(e,h,V(e.Va)),g=new L(G(new H,g,e)));for(g=g.m();g.s();)e=new z(g.t(),u()),null===d?c=e:d.p=e,d=e;a=a.f()}return null===c?u():c}\nfunction bca(a,b,c,d){if(b instanceof zA)return SC(a,b,c,!0,d);if(b instanceof BA){CA(a);t();var e=new L(b);if(!e.b()){b=e.k;var g=b.xk;e=m=>cz(m,new y(n=>SC(a,n,c,!0,d)),d);if(g===u())e=u();else{var h=g.e(),k=h=new z(e(h),u());for(g=g.f();g!==u();){var l=g.e();l=new z(e(l),u());k=k.p=l;g=g.f()}e=h}b=b.Ul;b.b()?b=R():(b=b.o(),b=new L(SC(a,b,c,!0,d)));return new By(a,e,b)}}throw new w(b);}\nfunction SC(a,b,c,d,e){var g=Xu().X(),h=Xu().X(),k=c.ie();k=new Ef(k,new y(r=>r.Ea()));if(k.s()){if(!k.s())throw nv(\"empty.reduceLeft\");for(var l=!0,m=null;k.s();){var n=k.t();l?(m=n,l=!1):(m|=0,n|=0,m=m>n?m:n)}k=new L(m)}else k=R();k=(k.b()?a.Gd:k.o())|0;return nca(a,b,c,d,g,k,e,h)}\nfunction Rv(a,b){tp();var c=a.K();At(0,Pe(new E(c),b.K()));a=new Wq(a,a,b);b=new fn((d,e)=>{d=G(new H,d,e);e=d.y;var g=d.w;if(null!==e){var h=e.h();e=e.j();if(h instanceof L&&(h=h.k,null!==g)){var k=g.h();g=g.j();if(k instanceof L&&Nm(new E(h),k.k))return d=t().d,G(new H,d,Nv(e,g,V(e.Va)))}}g=d.y;h=d.w;if(null!==g&&(e=g.h(),g=g.j(),null!==h))return d=h.h(),h=h.j(),d=e.b()?d:e,G(new H,d,Nv(g,h,V(g.Va)));throw new w(d);});Yq();return Ew(a,b)}\nfunction TC(a,b){tp();var c=a.K();At(0,Pe(new E(c),b.K()));a=new Wq(a,a,b);b=new fn((d,e)=>{d=G(new H,d,e);e=d.y;var g=d.w;if(null!==e){var h=e.h();e=e.j();if(h instanceof L&&(h=h.k,null!==g)){var k=g.h();g=g.j();if(k instanceof L)return d=Pe(new E(h),k.k)?new L(h):R(),G(new H,d,xw(e,g,V(e.Va)))}}e=d.y;g=d.w;if(null!==e&&(e=e.j(),null!==g))return d=g.j(),g=t().d,G(new H,g,xw(e,d,V(e.Va)));throw new w(d);});Yq();return Ew(a,b)}\nfunction vB(a,b){var c=tc();try{var d=new y(db=>\"yes: \"+db);if(a.F){var e=ut(Q(),\"| \",a.r);if(b===u())var g=u();else{var h=b.e(),k=new z(ze(h,\"\",\" \\x26 \",\"\"),u());h=k;for(var l=b.f();l!==u();){var m=l.e(),n=new z(ze(m,\"\",\" \\x26 \",\"\"),u());h=h.p=n;l=l.f()}g=k}var r=e+\"factorize? \"+ze(g,\"\",\" | \",\"\");ff(gf(),r+\"\\n\")}a.r=1+a.r|0;try{if(0>=b.ab(1))throw Hq(new Iq,c,LC(a,b));var v=new lA;for(e=b;!e.b();){for(var x=e.e();!x.b();){var A=x.e();if(A instanceof lx){g=A;var B=v.U(g);if(B instanceof L)var C=B.k;\nelse{if(R()!==B)throw new w(B);C=0}v.bh(g,1+(C|0)|0)}else if(A instanceof Gv){g=A;var D=v.U(g);if(D instanceof L)var F=D.k;else{if(R()!==D)throw new w(D);F=0}v.bh(g,1+(F|0)|0)}else if(A instanceof UC){g=A;var I=v.U(g);if(I instanceof L)var M=I.k;else{if(R()!==I)throw new w(I);M=0}v.bh(g,1+(M|0)|0)}else if(A instanceof VC){g=A;var N=v.U(g);if(N instanceof L)var P=N.k;else{if(R()!==N)throw new w(N);P=0}v.bh(g,1+(P|0)|0)}x=x.f()}e=e.f()}if(a.F){var T=ut(Q(),\"| \",a.r)+\"Factors \"+ze(v,\"\",\", \",\"\");ff(gf(),\nT+\"\\n\")}var Y=Fq();if(v.b())var Z=R();else{if(v.b())throw nv(\"empty.maxBy\");A=A=x=x=null;B=!1;B=!0;for(var S=v.Gn;null!==S;){var ea=G(new H,S.ju,S.Fn),ia=ea.w|0;if(B||0<Y.Da(ia,x))A=ea,x=ia,B=!1;S=S.zm}Z=new L(A)}a:{if(Z instanceof L){var X=Z.k;if(null!==X){var sa=X.h(),Ja=X.Sc();if(1<Ja){Od();var Xa=new fp;Od();for(var Fa=new fp;!b.b();){var za=b.e(),Qa=za.L(sa)?(t(),new fe(za)):(t(),new Ud(za));if(Qa instanceof fe)wp(Xa,Qa.aa);else if(Qa instanceof Ud)wp(Fa,Qa.fa);else throw new w(Qa);b=b.f()}var Ma=\nXa.ha(),Ga=Fa.ha();if(a.F){var ab=ut(Q(),\"| \",a.r)+(\"Factor \"+sa+\" -\\x3e \")+ze(Ma,\"\",\", \",\"\");ff(gf(),ab+\"\\n\")}var Hb=Ma.K();if(!Pe(new E(Hb),Ja))throw new Yj(\"assertion failed: \"+G(new H,Ma,Ja));Ja=db=>{var ub=db;a:for(;;)if(ub.b()){db=u();break}else{var Aa=ub.e();db=ub.f();if(!0===!!Pe(new E(Aa),sa))ub=db;else for(;;){if(db.b())db=ub;else{Aa=db.e();if(!0!==!!Pe(new E(Aa),sa)){db=db.f();continue}Aa=db;db=new z(ub.e(),u());var va=ub.f();for(ub=db;va!==Aa;){var Ra=new z(va.e(),u());ub=ub.p=Ra;va=va.f()}for(va=\nAa=Aa.f();!Aa.b();){Ra=Aa.e();if(!0===!!Pe(new E(Ra),sa)){for(;va!==Aa;)Ra=new z(va.e(),u()),ub=ub.p=Ra,va=va.f();va=Aa.f()}Aa=Aa.f()}va.b()||(ub.p=va)}break a}}return db};if(Ma===u())var bc=u();else{var yb=Ma.e(),tb=new z(Ja(yb),u());yb=tb;for(var eb=Ma.f();eb!==u();){var kb=eb.e(),Rb=new z(Ja(kb),u());yb=yb.p=Rb;eb=eb.f()}bc=tb}var Gb=vB(a,bc),vb=V(sa.q),Tb=Pu(sa,Gb,vb,!1);if(0<iv(v,1)){Ma=!1;for(var Nb=new WC(v);!Ma&&Nb.s();){var ic=Nb.gm();Ma=dx(new E(ic.h()),sa)?1<ic.Sc():!1}var Va=Ma}else Va=\n!1;var cb=Va?vB(a,Ga):LC(a,Ga),zb=V(cb.q);var Ub=dv(cb,Tb,zb,!1);break a}}}Ub=LC(a,b)}}finally{a.r=-1+a.r|0}if(dx(new E(d),a.qa)&&a.F){var jb=\"\"+ut(Q(),\"| \",a.r)+d.n(Ub);ff(gf(),jb+\"\\n\")}return Ub}catch(db){if(db instanceof Iq){a=db;if(a.Qg===c)return a.Cj();throw a;}throw db;}}function XC(a,b,c,d){lv();return new Qv(a,ry(0,b.Ba,new y(e=>{var g=e.Va,h=e.Oa;if(h.b())h=R();else{h=h.o();if(c.b())var k=R();else k=!!c.o(),k=new L(!k);h=new L(d.ba(k,h))}return new Uw(g,h,d.ba(c,e.ra),e.Pd)})),b.Nj)}\nfunction qca(a,b,c,d){var e=!1,g=null;if(b instanceof cv){g=b.Nb;e=b.ac;if(c.b())var h=R();else h=!!c.o(),h=new L(!h);return new cv(a,d.ba(h,g),d.ba(c,e),b.ma())}if(b instanceof Jv)return rB(b,c,d);if(b instanceof zv)return g=b.Yb,new zv(a,ry(lv(),g,new y(l=>{var m=l.Va,n=l.Oa;if(n.b())n=R();else{n=n.o();if(c.b())var r=R();else r=!!c.o(),r=new L(!r);n=new L(d.ba(r,n))}return new Uw(m,n,d.ba(c,l.ra),l.Pd)})),b.ma());if(b instanceof Sv){g=b.Fd;e=g.Va;h=g.Oa;if(h.b())h=R();else{h=h.o();if(c.b())var k=\nR();else k=!!c.o(),k=new L(!k);h=new L(d.ba(k,h))}return new Sv(a,new Uw(e,h,d.ba(c,g.ra),g.Pd),b.ma())}if(b instanceof Wv)return sB(b,new y(l=>d.ba(c,l)),new y(l=>{if(c.b())var m=R();else m=!!c.o(),m=new L(!m);return d.ba(m,l)}),new y(l=>d.ba(c,l)),b.Uu);if(b instanceof Tv&&(e=!0,g=b,h=g.Ic,k=g.kf,h instanceof LA&&null!==k&&k.b()))return new Tv(a,tB(h,new y(l=>d.ba(c,l))),k,g.vp);if(e)return e=g.kf,new Tv(a,d.ba(c,g.Ic),e,b.ma());if(b instanceof Mu)return b;throw new w(b);}\nfunction PB(a,b,c){if(b){for(a=a.ib;!c.b();){b=c.e();var d=V(a.q);a=dv(a,b,d,!1);c=c.f()}return a}for(a=a.La;!c.b();)b=c.e(),d=V(a.q),a=Pu(a,b,d,!1),c=c.f();return a}function YC(a,b){return Pe(new E(b),a.Df)?\"^\":5<b?\"^\"+b:ut(Q(),\"'\",b)}function PC(a){this.fP=null;if(null===a)throw null;this.fP=a}PC.prototype=new p;PC.prototype.constructor=PC;\nfunction Hv(a,b,c){a:for(var d=ap();;){var e=b;if(e instanceof fw){var g=e;if(PA(g,c)){b=QA(g,c);continue}}if(e instanceof ZB)b=e.mc();else{if(e instanceof lx&&(iC(a.fP),g=e.Sb,!g.b()&&(g=g.o(),!d.L(e)))){d=d.bc(e);b=g;continue}t();a=new L(b);break a}}return a}PC.prototype.$classData=q({QZ:0},!1,\"mlscript.TyperHelpers$AliasOf$\",{QZ:1,g:1});function ZC(a,b,c){a.ol=c;if(null===b)throw null;a.$m=b;a.gt=0}function $C(){this.ol=null;this.gt=0;this.$m=null}$C.prototype=new p;$C.prototype.constructor=$C;\nfunction aD(){}aD.prototype=$C.prototype;$C.prototype.u=function(){return this.Bw()};function QC(a){this.iP=this.jP=this.Jx=this.Xu=this.Pj=null;if(null===a)throw null;this.iP=a;t();this.Pj=new bD(this,new L(!0));t();this.Xu=new bD(this,new L(!1));this.Jx=new RB(this.Pj,a.Gd,!1);a=t().d;this.jP=new bD(this,a)}QC.prototype=new p;QC.prototype.constructor=QC;\nfunction fA(a,b){var c=!1,d=null;if(b instanceof L&&(c=!0,d=b,!0===!!d.k))return a.Pj;if(c&&!1===!!d.k)return a.Xu;if(t().d===b)return a.jP;throw new w(b);}QC.prototype.$classData=q({RZ:0},!1,\"mlscript.TyperHelpers$PolMap$\",{RZ:1,g:1});\nvar sca=function rca(a,b,c,d,e){for(;;){if(a.Yu.Wq){if(b instanceof Qx)return a=b,t(),new L(a);if(b instanceof fw){var h=b;if(!c.L(h.qb)){b=cD(h,d,e);c=h=c.bc(h.qb);continue}}if(b instanceof ZB){b=b.mc();continue}if(b instanceof lx){h=b;iC(a.Yu);var k=h.Sb;if(!k.b()&&(k=k.o(),!c.L(h))){h=c.bc(h);b=k;c=h;continue}}if(b instanceof cv){h=b.Nb;e=rca(a,b.ac,c,d,e);c=new dD(e,new y(l=>null!==l));e=c.lR;c=c.e3;e=e.b()||c.n(e.o())?e:R();if(e.b())return R();e=e.o();if(null!==e)c=e.de,k=e.Re,h.Ea()>c?(c=h.Ea(),\nk=ap(),d=eD(e,c,k,d),a=new Qx(a.Yu,d.de,new cv(a.Yu,h,d.Re,b.Mj))):a=new Qx(a.Yu,c,new cv(a.Yu,h,k,b.Mj));else throw new w(e);return new L(a)}}return t().d}};function OC(a){this.Yu=null;if(null===a)throw null;this.Yu=a}OC.prototype=new p;OC.prototype.constructor=OC;function tca(a,b,c,d){return sca(a,b,ap(),c,d)}OC.prototype.$classData=q({XZ:0},!1,\"mlscript.TyperHelpers$PolyFunction$\",{XZ:1,g:1});\nfunction TA(a,b){var c=Xu().X(),d=a.q;d.F&&(d=ut(Q(),\"| \",d.r)+(\"INST [\"+a.de+\"]   \")+a,ff(gf(),d+\"\\n\"));d=a.q;d.F&&(d=ut(Q(),\"| \",d.r)+\"  where  \"+xx(a),ff(gf(),d+\"\\n\"));c=a.Re.Kc(a.de,!1,b,c);d=a.q;d.F&&(b=ut(Q(),\"| \",d.r)+(\"TO [\"+b.da+\"] ~\\x3e  \")+c,ff(gf(),b+\"\\n\"));a=a.q;a.F&&(a=ut(Q(),\"| \",a.r)+\"  where  \"+xx(c),ff(gf(),a+\"\\n\"));return c}function uca(a,b){var c=Xu().X();return a.Re.Kc(a.de,!0,b,c)}function eD(a,b,c,d){var e=Xu().X();return KC(a,b,c,d,e)}\nfunction KC(a,b,c,d,e){At(tp(),b>=a.de);if(Pe(new E(b),a.de))return a;var g=a.q,h=a.de,k=a.Re,l=a.q.Df;d=new Iw(d.S,d.Ec,d.hc,d.Ed,1+b|0,d.Pc,d.Zc,d.Lb,d.yc,d.tb,d.$a,d.od,d.cb);return new Qx(g,b,fD(a.q,k,l,d,h,c,e,!1))}\nfunction mca(a,b,c,d,e,g){for(;;){var h=!1,k=null;if(b instanceof cv){c=b;k=c.Nb;b=c.ac;h=gD(b,d,a.q.Df);g=a.q;g.F&&(g=ut(Q(),\"| \",g.r)+\"could be distribbed: \"+h,ff(gf(),g+\"\\n\"));if(h.b())return t().d;g=gD(k,d,a.q.Df);var l=a.q;l.F&&(l=ut(Q(),\"| \",l.r)+\"cannot be distribbed: \"+g,ff(gf(),l+\"\\n\"));if(h.wy(g).b())return t().d;h=1+d|0;l=new y(n=>n.Xa);var m=Fq();l=vca(g,l,m);m=a;l=l.b()?m.q.Gd:l.o().Xa;h=h>l?h:l;b=new Qx(a.q,d,b);l=a.q;l.F&&(l=ut(Q(),\"| \",l.r)+\"inner: \"+b,ff(gf(),l+\"\\n\"));e=new cv(a.q,\nk,eD(b,h,g,e),c.Mj);c=a.q;c.F&&(c=ut(Q(),\"| \",c.r)+\"raised: \"+e,ff(gf(),c+\"\\n\"));c=a.q;c.F&&(c=ut(Q(),\"| \",c.r)+\"  where: \"+xx(e),ff(gf(),c+\"\\n\"));if(g.b())return t(),new L(e);t();d=new Qx(a.q,d,e);return new L(d)}if(b instanceof fw&&(l=b,!c.L(l.qb))){k=cD(l,e,g);c=c.bc(l.qb);b=k;continue}if(b instanceof ZB)b=k=b.mc();else{if(b instanceof lx&&(h=!0,k=b,iC(a.q),l=k.Sb,!l.b()&&(l=l.o(),!c.L(k)))){c=c.bc(k);b=l;continue}if(h&&k.Xa>d&&!c.L(k)){b=a;h=vy(k);l=a.q.ib;for(a=h;!a.b();)h=l,l=a.e(),m=V(h.q),\nl=dv(h,l,m,!1),a=a.f();h=l;c=c.bc(k);a=b;b=h}else if(b instanceof Qx)k=b,b=k.de,d=d<b?d:b,b=k.Re;else return t().d}}}function hD(a){if(a instanceof lx)return a;xm(a+\" was not a type variable\")}\nfunction mC(a,b){if(a instanceof OA)return Pe(new E(a.Hi),b);if(a instanceof lx)return b instanceof lx?Pe(new E(a.sp),b.sp):b instanceof OA&&b.q===a.q?Pe(new E(a),b.Hi):!1;if(null!==a&&Gs(a)){if(b instanceof zA&&b.q===a.q){if(b instanceof OA)return Pe(new E(a),b.Hi);if(b instanceof lx)return!1;if(null!==b&&Gs(b)){if(a.D(b)&&Pe(new E(a.G()),b.G())){a=new iD(a);for(b=new iD(b);a.s()&&b.s();){var c=a.t();if(Nm(new E(c),b.t()))return!1}return!a.s()&&!b.s()}return!1}throw new w(b);}return!1}throw new w(a);\n}function wca(a){return a instanceof lx?xca(a):tB(a,new y(b=>jD(b)))}function jD(a){Pe(new E(a.q.Im),a.pe)||(a.oe=wca(a),a.pe=a.q.Im);return a.oe}\nfunction tB(a,b){if(a instanceof cC){var c=a.Fg,d=a.Sf;return kD(cw(a.q),b.n(c),b.n(d),V(cw(a.q).Vu))}if(a instanceof cv)return c=a.ac,new cv(a.q,b.n(a.Nb),b.n(c),a.ma());if(a instanceof Jv)return rB(a,t().d,new fn((l,m)=>b.n(m)));if(a instanceof Qv)return c=a.Ba,new Qv(a.q,ry(lv(),c,new y(l=>cB(l,b,b))),a.ma());if(a instanceof zv)return c=a.Yb,new zv(a.q,ry(lv(),c,new y(l=>cB(l,b,b))),a.ma());if(a instanceof Wv)return sB(a,b,b,b,a.Uu);if(a instanceof Sv)return new Sv(a.q,cB(a.Fd,b,b),a.ma());if(a instanceof\nLA)return c=a.jc,new LA(a.q,a.tc,b.n(a.ic),b.n(c),a.ma());if(a instanceof MA)return new MA(a.q,b.n(a.Fc),a.ma());if(a instanceof Tv)return c=a.kf,new Tv(a.q,b.n(a.Ic),c,a.ma());if(a instanceof OA)return new OA(a.q,b.n(a.Hi),a.ma());if(a instanceof $y){c=a.up;d=a.q;var e=b.n(a.Oq),g=a.q;lv();return new $y(d,e,new Qv(g,ry(0,c.Ba,new y(l=>cB(l,b,b))),c.Nj),a.ma())}if(a instanceof ZB&&($B(a.q),t(),c=a.mc(),c=new L(c),!c.b()))return b.n(c.k);if(a instanceof fw){c=a.qb;var h=a.Zb;d=a.q;if(h===u())e=u();\nelse for(e=h.e(),g=e=new z(b.n(e),u()),h=h.f();h!==u();){var k=h.e();k=new z(b.n(k),u());g=g.p=k;h=h.f()}return new fw(d,c,e,a.ma())}if(a instanceof Qx)return new Qx(a.q,a.de,b.n(a.Re));if(a instanceof eC){h=a.Lj;c=a.kj;a=a.q;d=l=>{var m=b.n(l.h());l=b.n(l.j());return G(new H,m,l)};if(h===u())d=u();else{e=h.e();g=e=new z(d(e),u());for(h=h.f();h!==u();)k=h.e(),k=new z(d(k),u()),g=g.p=k,h=h.f();d=e}return new eC(a,d,b.n(c))}if(a instanceof lx||Uv(a)||a instanceof FA)return a;throw new w(a);}\nfunction UA(a,b,c,d,e){var g=!1,h=null,k=!1,l=null,m=!1,n=null;if(a instanceof cC){g=!0;h=a;var r=h.Fg,v=h.Sf;if(c&&!b.b())return b.b()&&xm(\"Program reached and unexpected state.\"),b.o()?d.ba((t(),new L(!0)),v):d.ba((t(),new L(!1)),r)}if(g)return c=h.Fg,e=h.Sf,kD(cw(a.q),d.ba((t(),new L(!1)),c),d.ba((t(),new L(!0)),e),V(cw(a.q).Vu));if(a instanceof Qv)return XC(a.q,a,b,d);if(a instanceof Tv&&(g=a.Ic,h=a.kf,c))return a=d.ba(b,g),iB(a,h);if(a instanceof Fv)return qca(a.q,a,b,d);if(a instanceof LA&&\n(k=!0,l=a,g=l.tc,r=l.ic,h=l.jc,c)){if(g)return a=d.ba(b,r),c=d.ba(b,h),e=V(a.q),dv(a,c,e,!1);a=d.ba(b,r);c=d.ba(b,h);e=V(a.q);return Pu(a,c,e,!1)}if(k)return c=l.jc,new LA(a.q,l.tc,d.ba(b,l.ic),d.ba(b,c),a.ma());if(a instanceof MA&&(m=!0,n=a,l=n.Fc,c))return b.b()?c=R():(c=!!b.o(),c=new L(!c)),c=d.ba(c,l),a=a.ma(),NA(c,a,!1);if(m)return c=n.Fc,e=a.q,b.b()?l=R():(l=!!b.o(),l=new L(!l)),new MA(e,d.ba(l,c),a.ma());if(a instanceof OA)return new OA(a.q,d.ba(b,a.Hi),a.ma());if(a instanceof $y)return c=\na.up,e=a.q,l=d.ba(b,a.Oq),m=a.q,lv(),new $y(e,l,new Qv(m,ry(0,c.Ba,new y(x=>{var A=x.Va,B=x.Oa;if(B.b())B=R();else{B=B.o();if(b.b())var C=R();else C=!!b.o(),C=new L(!C);B=new L(d.ba(C,B))}return new Uw(A,B,d.ba(b,x.ra),x.Pd)})),c.Nj),a.ma());if(a instanceof ZB&&($B(a.q),t(),l=a.mc(),l=new L(l),!l.b()))return d.ba(b,l.k);if(a instanceof fw)return new fw(a.q,a.qb,bw(a,b,d,e),a.ma());if(a instanceof Qx)return e=a.de,l=a.Re,c?yx(zx(a.q),e,d.ba(b,l)):new Qx(a.q,e,d.ba(b,l));if(a instanceof eC){n=a.Lj;\nc=a.kj;a=a.q;e=x=>{var A=d.ba((t(),new L(!0)),x.h());x=d.ba((t(),new L(!1)),x.j());return G(new H,A,x)};if(n===u())e=u();else{l=n.e();m=l=new z(e(l),u());for(n=n.f();n!==u();)k=n.e(),k=new z(e(k),u()),m=m.p=k,n=n.f();e=l}return new eC(a,e,d.ba(b,c))}if(a instanceof lx||Uv(a)||a instanceof FA)return a;throw new w(a);}function lD(a,b){return new Uw(a.q,(t(),new L(a)),a,b)}\nvar dv=function yca(a,b,c,d){var g=a.q.La;if(null===g?null===a:mC(g,a))return a;g=a.q.ib;if(null===g?null===a:mC(g,a))return b;g=a.q.La;if(null===g?null===b:mC(g,b))return b;g=a.q.ib;if(null===g?null===b:mC(g,b))return a;if(a instanceof YB&&!0===a.pA)return b;if(a instanceof YB&&!1===a.pA||a instanceof Qv&&b instanceof cv)return a.q.La;if(a instanceof Qv&&(g=a.Ba,b instanceof Qv))return new Qv(a.q,RC(g,b.Ba),c);if(a instanceof zv&&(g=a.Yb,b instanceof zv)){var h=b.Yb,k=jv(g,h);if(Pe(new E(k),0))return new zv(a.q,\nTC(g,h),a.Nq)}return d?(null===b?null===a:mC(b,a))?a:a instanceof MA&&(d=a.Fc,null===b?null===d:mC(b,d))?a.q.La:new LA(a.q,!0,b,a,c):yca(b,a,c,!0)},sA=function zca(a,b,c){if(a instanceof cv){var e=a.Nb,g=a.ac;if(b instanceof cv){var h=b.Nb,k=b.ac;if(a.q.UI)return a=a.q,b=V(e.q),e=dv(e,h,b,!1),h=V(g.q),new cv(a,e,zca(g,k,h),c)}}return Pu(a,b,c,!1)},Pu=function mD(a,b,c,d){a:{var g=a.q.La;if(null===g?null===a:mC(g,a))g=!0;else{if(a instanceof Qv){g=a.Ba;var h=O().c;if(null===h?null===g:h.i(g)){g=!0;\nbreak a}}g=!1}}if(g)return b;g=a.q.ib;if((null===g?null===a:mC(g,a))||a instanceof Mu&&b instanceof cv)return a.q.ib;if(a instanceof Qv&&(g=a.Ba,b instanceof Qv)){h=b.Ba;a=a.q;b=Su();d=op().ga;b=new Uu(b,d);d=sv();var k=g.Q()+h.Q()|0;h=Lv(Lv(Mv(8<k?k:8),g),h);g=Xu().X();for(h=sl(h).m();h.s();){var l=h.t();k=l.h();var m=g.U(k);if(m instanceof L)m=m.k,l=Nv(m,l.j(),V(m.Va));else{if(R()!==m)throw new w(m);l=l.j()}g.bj(k,l)}h=qp();b=Ov(d,(new Pv(h)).vc(g),b);Od();return new Qv(a,Pd(u(),b),c)}return a instanceof\nzv&&(g=a.Yb,b instanceof zv)?(c=b.Yb,b=jv(g,c),Nm(new E(b),0)?a.q.ib:new zv(a.q,Rv(g,c),a.Nq)):d?(null===b?null===a:mC(b,a))?a:d?a instanceof MA&&(d=a.Fc,null===b?null===d:mC(b,d))?a.q.ib:new LA(a.q,!1,b,a,c):mD(b,a,c,!0):mD(b,a,c,!0)},NA=function nD(a,b,c){var e=!1,g=null;if(a instanceof FA)return new FA(a.q,!a.Eh,V(a.q));if(a instanceof LA){e=!0;g=a;var h=g.ic,k=g.jc;if(!0===g.tc)return a=V(h.q),a=nD(h,a,!1),b=V(k.q),k=nD(k,b,!1),b=V(a.q),Pu(a,k,b,!1)}return e&&(h=g.ic,k=g.jc,!1===g.tc&&c)?(a=V(h.q),\na=nD(h,a,!1),b=V(k.q),k=nD(k,b,!1),b=V(a.q),dv(a,k,b,!1)):a instanceof MA?a.Fc:new MA(a.q,a,b)};function Aca(a,b,c){var d=Xu().X();return Zu(a,b,c,!0,d)?(d=Xu().X(),Zu(b,a,c,!0,d)):!1}\nvar Zu=function oD(a,b,c,d,e){var h=Pe(new E(d),!0)&&!a.q.ZE;a.q.Gp=1+a.q.Gp|0;if(!pD(a)&&(Ot(new E(a),b)||Pe(new E(a),b)))return!0;var k=G(new H,a,b);var l=k.w;if(l instanceof FA&&!1===l.Eh)var m=!0;else{var n=k.y;m=n instanceof FA&&!0===n.Eh?!0:!1}if(m)return!0;var r=k.y;if(r instanceof ZB){$B(a.q);t();var v=r.mc(),x=new L(v);if(!x.b())return oD(x.k,b,c,d,e)}var A=k.w;if(A instanceof ZB){$B(a.q);t();var B=A.mc(),C=new L(B);if(!C.b())return oD(a,C.k,c,d,e)}if((Uv(k.y)&&Uv(k.w)||k.y instanceof lx&&\nk.w instanceof lx)&&Pe(new E(a),b))return!0;var D=k.y,F=k.w;if(D instanceof Vv&&F instanceof Sv)return Fw(D.Zj(),F.Fd,c,e);var I=k.y,M=k.w;if(I instanceof zv){var N=I.Yb;if(M instanceof zv){var P=M.Yb,T=jv(N,P);if(Pe(new E(T),0)){for(var Y=new Wq(N,N,P),Z=Y.ck.m(),S=Y.dk.m(),ea=!1;!ea&&Z.s()&&S.s();){var ia=Z.t(),X=S.t(),sa=G(new H,ia,X);a:{var Ja=sa.y,Xa=sa.w;if(null!==Ja){var Fa=Ja.j();if(null!==Xa){var za=Fw(Fa,Xa.j(),c,e);break a}}throw new w(sa);}ea=!za}return!ea}return!1}}var Qa=k.y;if(Qa instanceof\nQv){var Ma=Qa.Ba,Ga=O().c;if(null===Ga?null===Ma:Ga.i(Ma))return oD(a.q.La,b,c,d,e)}var ab=k.w;if(ab instanceof Qv){var Hb=ab.Ba,bc=O().c;if(null===bc?null===Hb:bc.i(Hb))return oD(a,a.q.La,c,d,e)}var yb=k.y,tb=k.w;if(yb instanceof Mu){var eb=yb.pd;if(tb instanceof Mu){var kb=tb.pd;return Pe(new E(eb),kb)?!0:yb.Fv().L(kb)}}var Rb=k.y;if(Rb instanceof cC)return oD(Rb.Sf,b,c,d,e);var Gb=k.w;if(Gb instanceof cC)return oD(a,Gb.Fg,c,d,e);var vb=k.y,Tb=k.w;if(vb instanceof cv){var Nb=vb.Nb,ic=vb.ac;if(Tb instanceof\ncv){var Va=Tb.Nb,cb=Tb.ac,zb=Rd=>oD(Va,Nb,c,d,Rd)&&oD(ic,cb,c,d,Rd);if(h)var Ub=e.ry(new y(Rd=>G(new H,Rd.h(),!0))),jb=zb(Ub);else jb=zb(e);return!!jb}}var db=k.y;if(db instanceof LA){var ub=db.ic,Aa=db.jc;if(!0===db.tc)return oD(ub,b,c,d,e)&&oD(Aa,b,c,d,e)}var va=k.w;if(va instanceof LA){var Ra=va.ic,rb=va.jc;if(!1===va.tc)return oD(a,Ra,c,d,e)&&oD(a,rb,c,d,e)}var xb=k.y;if(xb instanceof LA){var mc=xb.ic,Ha=xb.jc;if(!1===xb.tc)return oD(mc,b,c,d,e)||oD(Ha,b,c,d,e)}var Ka=k.w;if(Ka instanceof LA){var Oa=\nKa.ic,Na=Ka.jc;if(!0===Ka.tc)return oD(a,Oa,c,d,e)||oD(a,Na,c,d,e)}var Da=k.y,ta=k.w;if(Da instanceof Qv){var Ya=Da.Ba;if(ta instanceof Qv){var dc=ta.Ba,ka=Rd=>{for(var Bd=dc;!Bd.b();){var ae=Bd.e();a:{for(var dd=Ya;!dd.b();){var od=dd.e().h();if(Pe(new E(od),ae.h())){dd=new L(dd.e());break a}dd=dd.f()}dd=R()}if(dd.b()||!Fw(dd.o().j(),ae.j(),c,Rd))return!1;Bd=Bd.f()}return!0};if(h)var ya=e.ry(new y(Rd=>G(new H,Rd.h(),!0))),Sa=ka(ya);else Sa=ka(e);return!!Sa}}if(k.w instanceof Tv||(k.y instanceof lx||\nk.w instanceof lx)&&!h)return!1;if((k.y instanceof lx||k.w instanceof lx)&&e.L(G(new H,a,b)))return!!e.n(G(new H,a,b));var xc=k.y;if(xc instanceof lx){e.bh(G(new H,a,b),!1);var Sb=xc.Sb;if(Sb instanceof L)var uc=oD(Sb.k,b,c,d,e);else{if(t().d!==Sb)throw new w(Sb);a:{for(var Lb=rA(xc);!Lb.b();){var lc=Lb.e();if(oD(lc,b,c,d,e)){uc=!0;break a}Lb=Lb.f()}uc=!1}}uc&&e.bh(G(new H,a,b),!0);return uc}var Xb=k.w;if(Xb instanceof lx){e.bh(G(new H,a,b),!1);var ec=Xb.Sb;if(ec instanceof L)var Ab=oD(a,ec.k,c,d,\ne);else{if(t().d!==ec)throw new w(ec);a:{for(var Ob=vy(Xb);!Ob.b();){var fb=Ob.e();if(oD(a,fb,c,d,e)){Ab=!0;break a}Ob=Ob.f()}Ab=!1}}Ab&&e.bh(G(new H,a,b),!0);return Ab}var Wa=k.y;if(Wa instanceof eC){var bb=Wa.Lj,Ia=Wa.kj,Ua=O().c;if(null===Ua?null===bb:Ua.i(bb))return oD(Ia,b,c,d,e)}var pc=k.w;if(pc instanceof eC)return oD(a,pc.kj,c,d,e);var sc=k.w;if(sc instanceof MA){var Ba=sc.Fc,ob=V(a.q),nc=Pu(a,Ba,ob,!1);return oD(nc,a.q.ib,c,d,e)}var Ib=k.y;if(Ib instanceof MA){var vc=Ib.Fc,Vb=a.q.La,fc=V(b.q),\nBc=dv(b,vc,fc,!1);return oD(Vb,Bc,c,d,e)}var Pb=k.y;if(Pb instanceof fw&&a.q.cn.L(Pb.qb.V)&&PA(Pb,c)){var Jb=QA(Pb,c);return oD(Jb,b,c,d,e)}var gc=k.w;if(gc instanceof fw&&a.q.cn.L(gc.qb.V)&&PA(gc,c)){var Cb=QA(gc,c);return oD(a,Cb,c,d,e)}var cc=k.y;if(cc instanceof fw){var yc=c.tb.U(cc.qb.V);if(yc instanceof L){var Mc=yc.k;if(b instanceof fw&&Pe(new E(b.qb),cc.qb)){for(var qc=dB(Mc),oc=Mc.Xm,Qc=op(),jc=oc.Gb(Qc.ga).j(),sb=qD(new Wq(jc,jc,cc.Zb),b.Zb),Gc=sb.jL.m(),Wb=sb.kL.m(),Cc=sb.lL.m(),Fc=!1;!Fc&&\nGc.s()&&Wb.s()&&Cc.s();){var qd=Gc.t(),Yb=Wb.t(),Nc=Cc.t(),ad=Yb,Uc=Nc,cd=qc.n(qd);Fc=!((cd.qe||oD(ad,Uc,c,d,e))&&(cd.Qd||oD(Uc,ad,c,d,e)))}return!Fc}if(Ot(new E(Mc.jj),Bp())){var kc=rD(a.q,Mc,V(a.q),c);return oD(kc,b,c,d,e)}return!1}if(t().d===yc)return!1;throw new w(yc);}if(k.w instanceof fw||k.y instanceof Qx||k.w instanceof Qx)return!1;var Vc=k.w;if(Vc instanceof Jv){for(var Hc=Vc.gi;!Hc.b();){var rc=Hc.e();if(!oD(a,rc,c,d,e))return!1;Hc=Hc.f()}return!0}var sd=k.y;if(sd instanceof Jv){for(var Kc=\nsd.gi;!Kc.b();){var Qd=Kc.e();if(oD(Qd,b,c,d,e))return!0;Kc=Kc.f()}return!1}if(k.y instanceof eC||k.y instanceof Tv||k.y instanceof Vv||k.w instanceof Vv||k.y instanceof Gv||k.w instanceof Gv||k.y instanceof cv||k.w instanceof cv||k.y instanceof Qv&&Uv(k.w)||Uv(k.y)&&k.w instanceof Qv)return!1;var Ad=k.w;if(Ad instanceof FA&&!0===Ad.Eh)var kd=!0;else{var Hd=k.y;kd=Hd instanceof FA&&!1===Hd.Eh?!0:!1}if(kd)return!1;throw new w(k);};function JA(a,b){var c=Xu().X();return Zu(a.q.La,a,b,!0,c)}\nfunction Kv(a,b){var c=a.q.ib,d=Xu().X();return Zu(a,c,b,!0,d)}function iB(a,b){return b.b()?a:a instanceof Tv?new Tv(a.q,a.Ic,a.kf.Ce(b),a.ma()):new Tv(a.q,a,b,V(a.q))}\nvar bC=function sD(a,b){if(b.b())return a;var d=!1,e=null,g=!1,h=null;if(a instanceof Tv)return new Tv(a.q,a.Ic,a.kf.Ce(b),a.ma());if(a instanceof cv)return a;if(a instanceof LA){d=!0;e=a;var k=e.ic,l=e.jc;if(!0===e.tc)return a=iB(k,b),b=iB(l,b),h=V(a.q),dv(a,b,h,!1)}if(d&&(d=e.ic,l=e.jc,!1===e.tc))return a=iB(d,b),b=iB(l,b),h=V(a.q),Pu(a,b,h,!1);if(a instanceof Qv){h=a.q;g=a.Ba;a:for(;;)if(g.b()){b=u();break}else if(l=g.e(),e=g.f(),!1===!b.L(l.h()))g=e;else for(;;){if(e.b())b=g;else{l=e.e();if(!1!==\n!b.L(l.h())){e=e.f();continue}l=e;e=new z(g.e(),u());d=g.f();for(g=e;d!==l;)k=new z(d.e(),u()),g=g.p=k,d=d.f();for(d=l=l.f();!l.b();){k=l.e();if(!1===!b.L(k.h())){for(;d!==l;)k=new z(d.e(),u()),g=g.p=k,d=d.f();d=l.f()}l=l.f()}d.b()||(g.p=d);b=e}break a}return new Qv(h,b,a.Nj)}if(a instanceof zv){var m=a.Yb;b=b.Fk(new y(n=>{var r=nB(n);n=m.K();if(r.b())return!1;r=r.o()|0;return r!==n&&!(0>r||r>n)}));if(b.b())return a;a=a.kq();e=a.Ba;a:for(;;)if(e.b()){b=u();break}else if(g=e.e(),h=e.f(),!0===!!b.L(g.h()))e=\nh;else for(;;){if(h.b())b=e;else{g=h.e();if(!0!==!!b.L(g.h())){h=h.f();continue}g=h;h=new z(e.e(),u());l=e.f();for(e=h;l!==g;)d=new z(l.e(),u()),e=e.p=d,l=l.f();for(l=g=g.f();!g.b();){d=g.e();if(!0===!!b.L(d.h())){for(;l!==g;)d=new z(l.e(),u()),e=e.p=d,l=l.f();l=g.f()}g=g.f()}l.b()||(e.p=l);b=h}break a}return new Qv(a.q,b,a.Nj)}if(a instanceof Sv)return a;a instanceof Wv&&no();if(a instanceof MA&&(g=!0,h=a,h.Fc instanceof Mu||h.Fc instanceof cv||h.Fc instanceof Qv))return h;if(g&&(e=h.Fc,e instanceof\nLA||e instanceof FA||e instanceof MA))return a=NA(e,h.rA,!0),sD(a,b);if(a instanceof FA)return a;if(a instanceof OA)return new OA(a.q,sD(a.Hi,b),a.NE);if(a instanceof ZB&&($B(a.q),t(),h=a.mc(),h=new L(h),!h.b()))return sD(h.k,b);if(Uv(a))return a;if(a instanceof cC)return sD(a.Sf,b);if(a instanceof lx||a instanceof MA||a instanceof fw)return new Tv(a.q,a,b,V(a.q));if(a instanceof Qx)return h=a.de,e=a.Re,yx(zx(a.q),h,sD(e,b));if(a instanceof Jv||a instanceof eC)return a;throw new w(a);},tD=function Bca(a,\nb){a=DB(a);return a instanceof fw&&PA(a,b)?(a=QA(a,b),Bca(a,b)):a},wD=function uD(a,b,c,d,e){var h=!1,k=null,l=vD(e)?a:tD(a,d);if(l instanceof FA)return new FA(a.q,!l.Eh,V(a.q));if(l instanceof LA){h=!0;k=l;var m=k.ic,n=k.jc;if(!0===k.tc)return a=uD(m,b,c,d,e),c=uD(n,b,c,d,e),b=V(a.q),Pu(a,c,b,!1)}return h&&(h=k.ic,n=k.jc,!1===k.tc)?(a=uD(h,b,c,d,e),c=uD(n,b,c,d,e),b=V(a.q),dv(a,c,b,!1)):l instanceof MA?(b=b.n(l.Fc),ux(b.q,b,c)):l instanceof fw&&!vD(e)&&PA(l,d)?(a=QA(l,d),uD(a,b,c,d,e)):l instanceof\nQv||l instanceof cv?a.q.ib:new MA(a.q,b.n(l),c)},Cca=function xD(a,b,c){if(a instanceof MA){var e=a.Fc,g=new y(m=>xD(m,b,c));a=a.ma();return wD(e,g,a,b,c)}if(a instanceof Tv){var h=a.Ic,k=a.kf;if(k.b())return xD(h,b,c);g=!1;e=null;h=vD(c)?DB(h):tD(h,b);k=bC(h,k);if(k instanceof Tv){g=!0;e=k;h=e.Ic;var l=e.kf;if(h instanceof LA)return e=h.jc,new LA(a.q,h.tc,bC(h.ic,l),bC(e,l),h.KE)}return g&&(g=e.Ic,e=e.kf,g instanceof MA)?(g=g.Fc,k=new y(m=>xD(m,b,c)),h=g.ma(),g=wD(g,k,h,b,c),e=bC(g,e),e instanceof\nTv&&(g=e.Ic,g instanceof MA)?(g=g.Fc,g instanceof lx||g instanceof Mu||g instanceof Qv?e:vD(c)?e:xm(a+\"  \"+e+\"  (\"+ca(g)+\")\")):e):k}return a},DB=function Dca(a){if(a instanceof ZB){$B(a.q);t();var c=a.mc();c=new L(c);if(!c.b())return Dca(c.k)}return a},uy=function Eca(a){return a instanceof OA?Eca(a.Hi):a},Fca=function yD(a){var c=DB(a);return c instanceof Tv?yD(c.Ic):c instanceof Qx?yD(c.Re):c instanceof cC?yD(c.Sf):a},uB=function zD(a,b){var d=!1,e=null;if(a instanceof FA&&b===a.Eh)return O().c;\nif(a instanceof LA){var g=a.ic,h=a.jc;if(b===a.tc)return a=zD(g,b),dl(zD(h,b),a)}if(a instanceof MA&&(d=!0,e=a,h=e.Fc,h instanceof lx&&!b))return a=new UC(a.q,h),b=O().c,new z(a,b);if(d&&(d=e.Fc,d instanceof Gv&&!b))return a=new VC(a.q,d),b=O().c,new z(a,b);if(a instanceof OA)return zD(a.Hi,b);b=O().c;return new z(a,b)};function gD(a,b,c){var d=jA().X(),e=jA().X();Gca(a,a,b,c,e,d);return Aq(Bq(),d)}function AD(a,b){t();return BD(a,new L(!0),a,b)}function CD(a,b){t();return BD(a,new L(!1),a,b)}\nfunction BD(a,b,c,d){c=SC(a.q,c,nf(),!1,d);b=iA(a.q,c,b,d);return uf(a.q,b,!0,d)}var Gca=function DD(a,b,c,d,e,g){for(;;){if(c<d&&b.Ea()>c)if(b instanceof lx){if(!e.L(b))for(e.$(b),b.Xa>c&&b.Xa<=d&&g.$(b),b=ED(b,!0);!b.b();){var k=b.e();DD(a,k,c,d,e,g);b=b.f()}}else if(b instanceof Qx){k=b.de;d=k<d?k:d;b=b.Re;continue}else for(b=ED(b,!0);!b.b();)k=b.e(),DD(a,k,c,d,e,g),b=b.f();break}};function FD(a,b,c){a.yA=c;if(null===b)throw null;a.Vq=b}function GD(){this.Vq=this.yA=null}GD.prototype=new p;\nGD.prototype.constructor=GD;function HD(){}HD.prototype=GD.prototype;function mA(a,b,c){if(c instanceof zA)a.Tb(b,c);else{if(c instanceof BA){CA(a.Vq);t();var d=new L(c);if(!d.b()){c=d.k;for(d=c.xk;!d.b();){var e=d.e();ID(a,b,e);d=d.f()}c=c.Ul;c.b()||(c=c.o(),a.Tb(b,c));return}}throw new w(c);}}\nfunction ID(a,b,c){if(c instanceof ax){var d=c.Ql;for(c=c.rk.m();c.s();){var e=c.t();a.Tb(new TB(b),e.hb)}a.Tb(b,d)}else if(c instanceof Yw){var g=c.Ij,h=c.gl,k=c.Ei;d=c.Um;e=c.sk;var l=c.Tm;for(c=c.gh.m();c.s();){var m=c.t();a.Tb(new TB(b),m.hb)}if(!g.b())for(c=g.o();!c.b();)g=c.e(),a.Kp(b,g.j()),c=c.f();if(!h.b())for(c=h.o();!c.b();)h=c.e(),a.Tb(new UB(b),h.j()),c=c.f();for(c=k.ie();c.s();)k=c.t(),ID(a,b,k);a.Tb(new UB(b),d);a.Tb(new UB(b),e);for(c=l.ie();c.s();)d=c.t(),ID(a,b,d)}else if(c instanceof\nWw){k=c.tk;d=c.co;e=c.uk;l=c.Vm;for(c=c.wk.m();c.s();)h=c.t(),a.Tb(new TB(b),h.hb);for(c=k.ie();c.s();)k=c.t(),ID(a,b,k);a.Tb(new UB(b),d);a.Tb(b,e);for(c=l.ie();c.s();)d=c.t(),ID(a,b,d)}else if(c instanceof Nw){d=c.jl;e=c.hl;k=c.Tl;l=c.Jj;for(c=c.kl.m();c.s();)h=c.t(),a.Tb(new TB(b),h.hb);for(c=k;!c.b();)k=c.e(),a.Kp(b,k.j()),c=c.f();for(c=l.ie();c.s();)l=c.t(),ID(a,b,l);a.Tb(new UB(b),d);a.Tb(new UB(b),e)}else if(c instanceof Vw)a.Kp(b,c.ig);else if(c instanceof bx)a.Tb(b,c.hh);else if(!(c instanceof\ncx))throw new w(c);}\nGD.prototype.Tb=function(a,b){var c=!1,d=null;a:{if(b instanceof lx){c=!0;d=b;iC(this.Vq);var e=d.Sb;if(!e.b()){b=e.o();this.Tb(a,b);break a}}if(c){b=a.Ig(d.Xa);if(Nm(new E(b),(t(),new L(!1))))for(e=vy(d),c=new RB(a,d.Xa,!0);!e.b();){var g=e.e();this.Tb(c,g);e=e.f()}if(Nm(new E(b),(t(),new L(!0))))for(b=rA(d),a=new RB(a,d.Xa,!1);!b.b();)d=b.e(),this.Tb(a,d),b=b.f()}else if(b instanceof cv)d=b.Nb,b=b.ac,this.Tb(new UB(a),d),this.Tb(a,b);else if(b instanceof Jv)for(b=b.gi;!b.b();)d=b.e(),this.Tb(a,\nd),b=b.f();else if(b instanceof LA)d=b.jc,this.Tb(a,b.ic),this.Tb(a,d);else if(b instanceof Qv)for(b=b.Ba,d=op(),b=b.Gb(d.ga).j();!b.b();)d=b.e(),this.Kp(a,d),b=b.f();else if(b instanceof zv)for(b=b.Yb,d=op(),b=b.Gb(d.ga).j();!b.b();)d=b.e(),this.Kp(a,d),b=b.f();else if(b instanceof Sv)this.Kp(a,b.Fd);else if(b instanceof Wv)for(b=b.fo;!b.b();){d=b.e();if(d instanceof fe)this.Tb(a,d.aa);else if(d instanceof Ud)this.Kp(a,d.fa);else throw new w(d);b=b.f()}else if(b instanceof MA)b=b.Fc,this.Tb(new UB(a),\nb);else if(!(b instanceof FA)){if(b instanceof ZB&&($B(this.Vq),t(),d=b.mc(),d=new L(d),!d.b())){this.Tb(a,d.k);break a}if(!(XB(b)||b instanceof YB))if(b instanceof mx)this.Tb(a,b.hi);else if(b instanceof fw)aC(b,a,new fn((h,k)=>{this.Tb(h,k)}),this.yA);else if(b instanceof Tv)this.Tb(a,b.Ic);else if(b instanceof cC)d=b.Fg,b=b.Sf,c=(h,k)=>{this.Tb(h,k)},Nm(new E(a.ol),(t(),new L(!0)))&&(e=gA(a.$m).Xu,c(e,d)),Nm(new E(a.ol),(t(),new L(!1)))&&(a=gA(a.$m).Pj,c(a,b));else if(b instanceof Qx)d=b.Re,this.Tb(new dC(a,\nb.de),d);else if(b instanceof eC){d=b.kj;for(b=b.Lj;!b.b();){e=b.e();if(null!==e)c=e.h(),e=e.j(),this.Tb(gA(this.Vq).Pj,c),this.Tb(gA(this.Vq).Jx,e);else throw new w(e);b=b.f()}this.Tb(a,d)}else throw new w(b);}}};GD.prototype.Kp=function(a,b){var c=b.Oa,d=new UB(a);c.b()||(c=c.o(),this.Tb(d,c));this.Tb(a,b.ra)};function JD(a,b,c){var d=c.Oa;d.b()?d=!1:(d=d.o(),d=Pe(new E(d),c.ra));d?a.Tb(new TB(b),c.ra):GD.prototype.Kp.call(a,b,c)}\nfunction KD(a,b,c){var d=!1,e=null;if(a instanceof lx){d=!0;e=a;iC(a.q);var g=e.Sb;if(!g.b()){var h=g.o(),k=G(new H,b,h),l=O().c;return new z(k,l)}}if(d){var m=b.Ig(e.Xa);if(Nm(new E(m),(t(),new L(!1)))){var n=vy(e),r=(bd=>Rc=>{var Wc=new RB(b,bd.Xa,!0);return G(new H,Wc,Rc)})(e);if(n===u())var v=u();else{for(var x=n.e(),A=new z(r(x),u()),B=A,C=n.f();C!==u();){var D=C.e(),F=new z(r(D),u());B=B.p=F;C=C.f()}v=A}}else v=O().c;if(Nm(new E(m),(t(),new L(!0)))){var I=rA(e),M=(bd=>Rc=>{var Wc=new RB(b,bd.Xa,\n!1);return G(new H,Wc,Rc)})(e);if(I===u())var N=u();else{for(var P=I.e(),T=new z(M(P),u()),Y=T,Z=I.f();Z!==u();){var S=Z.e(),ea=new z(M(S),u());Y=Y.p=ea;Z=Z.f()}N=T}}else N=O().c;return dl(N,v)}if(a instanceof cv){var ia=a.Nb,X=a.ac,sa=new UB(b),Ja=G(new H,sa,ia),Xa=G(new H,b,X),Fa=O().c;return new z(Ja,new z(Xa,Fa))}if(a instanceof Jv){var za=a.gi;if(za===u())return u();for(var Qa=za.e(),Ma=new z(G(new H,b,Qa),u()),Ga=Ma,ab=za.f();ab!==u();){var Hb=ab.e(),bc=new z(G(new H,b,Hb),u());Ga=Ga.p=bc;ab=\nab.f()}return Ma}if(a instanceof LA){var yb=a.jc,tb=G(new H,b,a.ic),eb=G(new H,b,yb),kb=O().c;return new z(tb,new z(eb,kb))}if(a instanceof Qv){for(var Rb=a.Ba,Gb=op(),vb=Rb.Gb(Gb.ga).j(),Tb=null,Nb=null;vb!==u();){for(var ic=vb.e(),Va=LD(b,ic).m();Va.s();){var cb=new z(Va.t(),u());null===Nb?Tb=cb:Nb.p=cb;Nb=cb}vb=vb.f()}return null===Tb?u():Tb}if(a instanceof zv){for(var zb=a.Yb,Ub=op(),jb=zb.Gb(Ub.ga).j(),db=null,ub=null;jb!==u();){for(var Aa=jb.e(),va=LD(b,Aa).m();va.s();){var Ra=new z(va.t(),\nu());null===ub?db=Ra:ub.p=Ra;ub=Ra}jb=jb.f()}return null===db?u():db}if(a instanceof Sv)return LD(b,a.Fd);if(a instanceof Wv){for(var rb=a.fo,xb=null,mc=null;rb!==u();){var Ha=rb.e();if(Ha instanceof fe)var Ka=G(new H,b,Ha.aa),Oa=O().c,Na=new z(Ka,Oa);else{if(!(Ha instanceof Ud))throw new w(Ha);Na=LD(b,Ha.fa)}for(var Da=Na.m();Da.s();){var ta=new z(Da.t(),u());null===mc?xb=ta:mc.p=ta;mc=ta}rb=rb.f()}return null===xb?u():xb}if(a instanceof MA){var Ya=a.Fc,dc=new UB(b),ka=G(new H,dc,Ya),ya=O().c;return new z(ka,\nya)}if(a instanceof FA)return O().c;if(a instanceof ZB){$B(a.q);t();var Sa=a.mc(),xc=new L(Sa);if(!xc.b()){var Sb=G(new H,b,xc.k),uc=O().c;return new z(Sb,uc)}}if(XB(a)||a instanceof YB)return O().c;if(a instanceof mx){var Lb=G(new H,b,a.hi),lc=O().c;return new z(Lb,lc)}if(a instanceof fw)return aC(a,b,new fn((bd,Rc)=>G(new H,bd,Rc)),c);if(a instanceof Tv){var Xb=G(new H,b,a.Ic),ec=O().c;return new z(Xb,ec)}if(a instanceof cC){var Ab=a.Fg,Ob=a.Sf,fb=gA(a.q).Xu,Wa=G(new H,fb,Ab),bb=gA(a.q).Pj,Ia=G(new H,\nbb,Ob),Ua=O().c;return new z(Wa,new z(Ia,Ua))}if(a instanceof Qx){var pc=G(new H,b,a.Re),sc=O().c;return new z(pc,sc)}if(a instanceof eC){for(var Ba=a.kj,ob=a.Lj,nc=null,Ib=null;ob!==u();){for(var vc=ob.e(),Vb=gA(a.q).Pj,fc=G(new H,Vb,vc.h()),Bc=gA(a.q).Jx,Pb=G(new H,Bc,vc.j()),Jb=O().c,gc=new Om(new z(fc,new z(Pb,Jb)));gc.s();){var Cb=new z(gc.t(),u());null===Ib?nc=Cb:Ib.p=Cb;Ib=Cb}ob=ob.f()}var cc=null===nc?u():nc,yc=G(new H,b,Ba),Mc=O().c;return dl(new z(yc,Mc),cc)}if(a instanceof BA){CA(a.q);\nt();var qc=new L(a);if(!qc.b()){for(var oc=qc.k,Qc=oc.xk,jc=null,sb=null;Qc!==u();){var Gc=Qc.e();if(Gc instanceof ax){var Wb=Gc,Cc=Wb.rk,Fc=(bd=>Rc=>{var Wc=new TB(bd);return G(new H,Wc,Rc.hb)})(b);if(Cc===u())var qd=u();else{for(var Yb=Cc.e(),Nc=new z(Fc(Yb),u()),ad=Nc,Uc=Cc.f();Uc!==u();){var cd=Uc.e(),kc=new z(Fc(cd),u());ad=ad.p=kc;Uc=Uc.f()}qd=Nc}var Vc=G(new H,b,Wb.Ql),Hc=O().c,rc=dl(new z(Vc,Hc),qd)}else if(Gc instanceof bx){var sd=Gc,Kc=gA(a.q).Pj,Qd=G(new H,Kc,sd.hh),Ad=O().c;rc=new z(Qd,\nAd)}else if(Gc instanceof Nw){var kd=Gc,Hd=kd.kl.m(),Rd=new Ef(Hd,new y((bd=>Rc=>{var Wc=new TB(bd);return G(new H,Wc,Rc.hb)})(b)));rc=kv(Rd,new U(((bd,Rc,Wc)=>()=>{var Wd=bd.Jj.ie();return new xo(Wd,new y(zd=>MD(a,zd,Rc,Wc)))})(kd,b,c))).nb(new U(((bd,Rc)=>()=>{t();var Wc=new UB(bd);Wc=G(new H,Wc,Rc.hl);return new L(Wc)})(b,kd))).nb(new U(((bd,Rc)=>()=>{t();var Wc=new UB(bd);Wc=G(new H,Wc,Rc.jl);return new L(Wc)})(b,kd)))}else if(Gc instanceof Yw){var Bd=Gc,ae=Bd.gh.m(),dd=new Ef(ae,new y((bd=>Rc=>\n{var Wc=new TB(bd);return G(new H,Wc,Rc.hb)})(b)));rc=kv(dd,new U((bd=>()=>{for(var Rc=bd.Ij.ha(),Wc=null,Wd=null;Rc!==u();){for(var zd=Rc.e(),Pa=null,Db=null;zd!==u();){var Oc=zd.e();for(Oc=LD(gA(a.q).Pj,Oc.j()).m();Oc.s();){var Tc=new z(Oc.t(),u());null===Db?Pa=Tc:Db.p=Tc;Db=Tc}zd=zd.f()}for(zd=(null===Pa?u():Pa).m();zd.s();)Pa=new z(zd.t(),u()),null===Wd?Wc=Pa:Wd.p=Pa,Wd=Pa;Rc=Rc.f()}return null===Wc?u():Wc})(Bd))).nb(new U((bd=>()=>{for(var Rc=bd.gl.ha(),Wc=null,Wd=null;Rc!==u();){var zd=Rc.e(),\nPa=Sd=>{var Jc=gA(a.q).Xu;return G(new H,Jc,Sd.j())};if(zd===u())Pa=u();else{var Db=zd.e(),Oc=Db=new z(Pa(Db),u());for(zd=zd.f();zd!==u();){var Tc=zd.e();Tc=new z(Pa(Tc),u());Oc=Oc.p=Tc;zd=zd.f()}Pa=Db}for(Pa=Pa.m();Pa.s();)Db=new z(Pa.t(),u()),null===Wd?Wc=Db:Wd.p=Db,Wd=Db;Rc=Rc.f()}return null===Wc?u():Wc})(Bd))).nb(new U(((bd,Rc,Wc)=>()=>{var Wd=bd.Ei.ie();return new xo(Wd,new y(zd=>MD(a,zd,Rc,Wc)))})(Bd,b,c))).nb(new U(((bd,Rc)=>()=>{t();var Wc=new UB(bd);Wc=G(new H,Wc,Rc.Um);return new L(Wc)})(b,\nBd))).nb(new U(((bd,Rc)=>()=>{t();var Wc=G(new H,bd,Rc.sk);return new L(Wc)})(b,Bd))).nb(new U(((bd,Rc,Wc)=>()=>{var Wd=bd.Tm.ie();return new xo(Wd,new y(zd=>MD(a,zd,Rc,Wc)))})(Bd,b,c)))}else if(Gc instanceof Ww){var od=Gc,Ta=od.wk.m(),wb=new Ef(Ta,new y((bd=>Rc=>{var Wc=new TB(bd);return G(new H,Wc,Rc.hb)})(b)));rc=kv(wb,new U(((bd,Rc,Wc)=>()=>{var Wd=bd.tk.ie();return new xo(Wd,new y(zd=>MD(a,zd,Rc,Wc)))})(od,b,c))).nb(new U(((bd,Rc)=>()=>{t();var Wc=new UB(bd);Wc=G(new H,Wc,Rc.co);return new L(Wc)})(b,\nod))).nb(new U(((bd,Rc)=>()=>{t();var Wc=G(new H,bd,Rc.uk);return new L(Wc)})(b,od))).nb(new U(((bd,Rc,Wc)=>()=>{var Wd=bd.Vm.ie();return new xo(Wd,new y(zd=>MD(a,zd,Rc,Wc)))})(od,b,c)))}else if(Gc instanceof Vw)rc=LD(b,Gc.ig);else{if(!(Gc instanceof cx))throw new w(Gc);rc=t().d}for(var $a=rc.m();$a.s();){var wa=new z($a.t(),u());null===sb?jc=wa:sb.p=wa;sb=wa}Qc=Qc.f()}var hb=null===jc?u():jc,ra=oc.Ul.ha();if(ra===u())var wc=u();else{for(var ac=ra.e(),Id=new z(G(new H,b,ac),u()),ud=Id,be=ra.f();be!==\nu();){var re=be.e(),pe=new z(G(new H,b,re),u());ud=ud.p=pe;be=be.f()}wc=Id}return dl(wc,hb)}}throw new w(a);}function hA(a,b,c){var d=Xu().X(),e=jA().X();Hca(a,b,!1,a.q.Df,a,!1,d,e,c);a=Su();b=op().ga;a=new Uu(a,b);return Ov(sv(),d,a)}\nvar Ica=function ND(a,b){if(b instanceof bx){var d=b.hh,e=O().c;return new z(d,e)}if(b instanceof ax)return d=b.rk.m(),d=new Ef(d,new y(h=>h.hb)),kv(d,new U(()=>{t();return new L(b.Ql)}));if(b instanceof Nw)return d=b.kl.m(),d=new Ef(d,new y(h=>h.hb)),kv(d,new U(()=>{var h=b.Jj.ie();return new xo(h,new y(k=>ND(a,k)))})).nb(new U(()=>{t();return new L(b.hl)})).nb(new U(()=>{t();return new L(b.jl)}));if(b instanceof Yw)return d=b.gh.m(),d=new Ef(d,new y(h=>h.hb)),kv(d,new U(()=>{for(var h=b.Ij.ha(),\nk=null,l=null;h!==u();){for(var m=h.e(),n=null,r=null;m!==u();){var v=m.e(),x=v.j().Oa.ha();v=v.j().ra;var A=O().c;for(x=dl(new z(v,A),x).m();x.s();)v=new z(x.t(),u()),null===r?n=v:r.p=v,r=v;m=m.f()}for(m=(null===n?u():n).m();m.s();)n=new z(m.t(),u()),null===l?k=n:l.p=n,l=n;h=h.f()}return null===k?u():k})).nb(new U(()=>{for(var h=b.gl.ha(),k=null,l=null;h!==u();){var m=h.e();for(m=mv(lv(),m);m.s();){var n=new z(m.t(),u());null===l?k=n:l.p=n;l=n}h=h.f()}return null===k?u():k})).nb(new U(()=>{var h=\nb.Ei.ie();return new xo(h,new y(k=>ND(a,k)))})).nb(new U(()=>{t();return new L(b.Um)})).nb(new U(()=>{t();return new L(b.sk)}));if(b instanceof Ww)return d=b.wk.m(),d=new Ef(d,new y(h=>h.hb)),kv(d,new U(()=>{var h=b.tk.ie();return new xo(h,new y(k=>ND(a,k)))})).nb(new U(()=>{t();return new L(b.co)})).nb(new U(()=>{t();return new L(b.uk)})).nb(new U(()=>{var h=b.Vm.ie();return new xo(h,new y(k=>ND(a,k)))}));if(b instanceof Vw){d=b.ig.Oa.ha();e=b.ig.ra;var g=O().c;return dl(new z(e,g),d)}if(b instanceof\ncx)return O().c;throw new w(b);};\nfunction ED(a,b){var c=!1,d=null;if(a instanceof lx){c=!0;d=a;iC(a.q);var e=d.Sb;if(!e.b())return a=e.o(),b?(b=O().c,new z(a,b)):O().c}if(c)return b?(a=vy(d),dl(rA(d),a)):O().c;if(a instanceof cv)return b=a.Nb,a=a.ac,d=O().c,new z(b,new z(a,d));if(a instanceof Jv)return a.gi;if(a instanceof LA)return b=a.ic,a=a.jc,d=O().c,new z(b,new z(a,d));if(a instanceof Qv){a=a.Ba;for(d=b=null;a!==u();){e=a.e();c=e.j().Oa.ha();e=e.j().ra;var g=O().c;for(c=dl(new z(e,g),c).m();c.s();)e=new z(c.t(),u()),null===\nd?b=e:d.p=e,d=e;a=a.f()}return null===b?u():b}if(a instanceof zv){a=a.Yb;for(d=b=null;a!==u();){e=a.e();c=e.j().Oa.ha();e=e.j().ra;g=O().c;for(c=dl(new z(e,g),c).m();c.s();)e=new z(c.t(),u()),null===d?b=e:d.p=e,d=e;a=a.f()}return null===b?u():b}if(a instanceof Sv)return b=a.Fd,a=b.Oa.ha(),b=b.ra,d=O().c,un(a,new z(b,d));if(a instanceof MA)return a=a.Fc,b=O().c,new z(a,b);if(a instanceof FA)return O().c;if(a instanceof ZB&&($B(a.q),t(),b=a.mc(),b=new L(b),!b.b()))return a=b.k,b=O().c,new z(a,b);if(XB(a)||\na instanceof YB)return O().c;if(a instanceof mx)return a=a.hi,b=O().c,new z(a,b);if(a instanceof fw)return a.Zb;if(a instanceof Tv)return a=a.Ic,b=O().c,new z(a,b);if(a instanceof cC)return b=a.Fg,a=a.Sf,d=O().c,new z(b,new z(a,d));if(a instanceof Qx)return a=a.Re,b=O().c,new z(a,b);if(a instanceof eC){b=a.kj;a=a.Lj;for(c=d=null;a!==u();){g=a.e();e=g.h();g=g.j();var h=O().c;for(e=new Om(new z(e,new z(g,h)));e.s();)g=new z(e.t(),u()),null===c?d=g:c.p=g,c=g;a=a.f()}a=null===d?u():d;d=O().c;return dl(new z(b,\nd),a)}if(a instanceof Wv){a=a.fo;for(d=b=null;a!==u();){c=a.e();if(c instanceof fe)c=c.aa,e=O().c,c=new z(c,e);else{if(!(c instanceof Ud))throw new w(c);e=c.fa;c=e.Oa.ha();e=e.ra;g=O().c;c=dl(new z(e,g),c)}for(c=c.m();c.s();)e=new z(c.t(),u()),null===d?b=e:d.p=e,d=e;a=a.f()}return null===b?u():b}if(a instanceof BA&&(CA(a.q),t(),b=new L(a),!b.b())){b=b.k;d=b.xk;for(e=c=null;d!==u();){g=d.e();for(g=Ica(a,g).m();g.s();)h=new z(g.t(),u()),null===e?c=h:e.p=h,e=h;d=d.f()}a=null===c?u():c;return dl(b.Ul.ha(),\na)}throw new w(a);}function xA(a,b){var c=jA().X(),d=O().c;Jca(new z(a,d),c,b);a=uv();O();b=new y(e=>e.sp);d=Fq();return oA(a,c,new OD(d,b))}\nfunction xx(a){var b=xA(a,!0).m();b=new iy(b,new y(c=>{if(c.Sb.b()){var d=rA(c);c=vy(c);return!un(d,c).b()}return!0}),!1);b=new Ef(b,new y(c=>{if(null!==c){iC(a.q);var d=c.Sb;if(!d.b())return d=d.o(),\"\\n\\t\\t\"+c.u()+\" :\\x3d \"+d}d=c.u();if(vy(c).b())var e=\"\";else e=vy(c),e=\" :\\x3e \"+ze(e,\"\",\" | \",\"\");rA(c).b()?c=\"\":(c=rA(c),c=\" \\x3c: \"+ze(c,\"\",\" \\x26 \",\"\"));return\"\\n\\t\\t\"+d+e+c}));return ze(b,\"\",\"\",\"\")}\nfunction LD(a,b){var c=b.Oa;if(c.b())c=R();else{c=c.o();var d=new UB(a);c=new L(G(new H,d,c))}c=c.ha();a=G(new H,a,b.ra);b=O().c;return dl(new z(a,b),c)}function MD(a,b,c,d){if(b instanceof Vw)return c=b.ig,LD(gA(a.q).Pj,c);if(b instanceof bx)return c=G(new H,c,b.hh),d=O().c,new z(c,d);if(b&&b.$classData&&b.$classData.rb.Rs){a=a.q;var e=O().c;b=new By(a,new z(b,e),t().d);return KD(b,c,d)}throw new w(b);}\nvar Hca=function PD(a,b,c,d,e,g,h,k,l){for(;;){if(e instanceof lx){if(g&&e.Xa>d){g=a.q;g.F&&(g=ut(Q(),\"| \",g.r)+\"Quantified! \"+e,ff(gf(),g+\"\\n\"));break}var n=b.Ig(e.Xa);c||h.ou(e,new y((A=>B=>{if(B instanceof L&&Nm(new E(B.k),A))return t(),B=t().d,new L(B);t();return new L(A)})(n)));if(n instanceof L){n=!!n.k;var r=G(new H,e,n);k.L(r)?n=!1:(n=G(new H,e,n),k.$(n),n=!0)}else{if(t().d!==n)throw new w(n);n=G(new H,e,!0);k.L(n)?(n=G(new H,e,!1),n=k.L(n)):n=!1;n?n=!1:(n=G(new H,e,!0),k.$(n),n=G(new H,e,\n!1),k.$(n),n=!0)}if(n)for(b=KD(e,b,l);!b.b();)e=b.e(),PD(a,e.h(),c,d,e.j(),g,h,k,l),b=b.f()}else{if(e instanceof ZB&&(n=e,$B(a.q),t(),n=n.mc(),n=new L(n),!n.b())){e=n.k;continue}if(e instanceof Jv)for(e=e.gi;!e.b();)n=e.e(),PD(a,b,c,d,n,g,h,k,l),e=e.f();else{if(e instanceof MA){e=e.Fc;b=new UB(b);continue}if(e instanceof Tv){e=e.Ic;continue}if(e instanceof cC){b=e.Fg;e=e.Sf;PD(a,gA(a.q).Xu,c,d,b,g,h,k,l);b=a;n=gA(a.q).Pj;a=b;b=n;continue}if(e instanceof eC){var v=e;e=v.kj;n=a;r=d;for(v=v.Lj;!v.b();){var x=\nv.e();PD(n,gA(n.q).Pj,!1,r,x.h(),g,h,k,l);PD(n,gA(n.q).Jx,!1,r,x.j(),g,h,k,l);v=v.f()}continue}if(e instanceof LA){n=e.jc;PD(a,b,c,d,e.ic,g,h,k,l);e=n;continue}if(e instanceof Qx){b=new dC(b,e.de);n=e.de;d=d<n?d:n;e=e.Re;continue}b=KD(e,b,l);c=a;for(a=b;!a.b();)b=a.e(),PD(c,b.h(),!1,d,b.j(),g,h,k,l),a=a.f()}}break}};\nfunction Jca(a,b,c){for(;;){var d=!1,e=null,g=a;if(g instanceof z){d=!0;e=g;var h=e.z;a=e.p;if(h instanceof lx){e=h;b.L(e)||(b.$(e),e=ED(e,c),a=dl(a,e));continue}}if(d){a=e.p;e=ED(e.z,c);a=dl(a,e);continue}b=O().c;if(null===b?null!==g:!b.i(g))throw new w(g);break}}function PA(a,b){a=b.$a.U(a.qb.V);if(a.b())return!0;a=a.o();return dz(a.Qu)?!0:!a.eo.b()}\nfunction cD(a,b,c){var d=b.$a.U(a.qb.V);if(d instanceof L){if(d=d.k,!dz(d.Qu)&&(Kx(d,c),d.eo.b()))return Ey(a.q)}else if(t().d!==d)throw new w(d);return gB(a,!0,!0,b)}function QA(a,b){At(tp(),PA(a,b));return gB(a,!0,!0,b)}\nfunction gB(a,b,c,d){var e=d.$a.U(a.qb.V);if(e.b())e=R();else{e=e.o();var g=new $e,h=!1,k=null,l=e.eo;a:{if(l instanceof L&&(h=!0,k=l,l=k.k,l instanceof ax)){tp();e=l.rk.K();up(0,Pe(new E(e),a.Zb.K()));e=a.q;g=l.Ql;c=l.rk;c=new Wq(c,c,a.Zb);l=new fn((m,n)=>{m=new mx(a.q,m.hb,V(a.q));return G(new H,m,n)});Yq();c=Ew(c,l);op();e=SC(e,g,c.Ti(),!1,d);break a}if(h&&(l=k.k,l instanceof Ww)){tp();h=l.wk.K();up(0,Pe(new E(h),a.Zb.K()));h=a.q;k=new vl(l.vk.gb.V);k=Cq(k,a.Xl.Ga);t();h=Jx(h,l,k,new L(a.Zb),d);\nif(null===h)throw new w(h);h=h.h();c=c?(Sw(a.q),l.uk.Kc(l.Hq,!1,d,h)):a.q.La;l=Xx(a.q,l.vk,V(a.q),d);h=V(c.q);c=Pu(c,l,h,!1);e=g.sb?g.vb:QD(a,g,e);g=V(c.q);e=Pu(c,e,g,!1);break a}if(h&&(l=k.k,l instanceof Yw)){tp();h=l.gh.K();up(0,Pe(new E(h),a.Zb.K()));h=a.q;k=new vl(l.Rf.gb.V);k=Cq(k,a.Xl.Ga);t();h=Jx(h,l,k,new L(a.Zb),d);if(null===h)throw new w(h);h=h.h();c=c?(Sw(a.q),l.sk.Kc(l.Sm,!1,d,h)):a.q.La;l=bz(a.q,l.Rf,V(a.q),d);h=V(l.q);c=Pu(l,c,h,!1);e=g.sb?g.vb:QD(a,g,e);g=V(c.q);e=Pu(c,e,g,!1);break a}l=\n!1;c=null;h=e.Ab;if(h instanceof yo&&(l=!0,c=h,Kca(c.pb))){tp();l=c.hg.K();up(0,Pe(new E(l),a.Zb.K()));c=bz(a.q,c,V(a.q),d);e=g.sb?g.vb:QD(a,g,e);g=V(c.q);e=Pu(c,e,g,!1);break a}l&&Ot(new E(c.pb),Fp())?(tp(),l=c.hg.K(),up(0,Pe(new E(l),a.Zb.K())),c=Xx(a.q,c,V(a.q),d),e=g.sb?g.vb:QD(a,g,e),g=V(c.q),e=Pu(c,e,g,!1)):(l&&Ot(new E(c.pb),Ap())&&xm(\"cannot expand unforced type alias\"),e=Ey(a.q))}e=new L(e)}if(e.b()){c=new $e;g=d.tb.n(a.qb.V);tp();e=a.Zb.K();At(0,Pe(new E(e),g.Xm.K()));e=a.q;l=g.jj;if(Ap()===\nl)b=g.Cx;else{if(zp()===l)throw RD(\"Namespaces are not supported yet.\");if(Bp()===l)l=rD(a.q,g,a.Xl,d),h=g.Cx,k=V(l.q),l=Pu(l,h,k,!1),b=c.sb?c.vb:SD(a,c,b,g),c=V(l.q),b=Pu(l,b,c,!1);else{if(Fp()!==l)throw cp()===l&&xm(\"mixins cannot be used as types\"),new w(l);l=TD(a.q,g,a.Xl);h=g.Cx;k=V(l.q);l=Pu(l,h,k,!1);b=c.sb?c.vb:SD(a,c,b,g);c=V(l.q);b=Pu(l,b,c,!1)}}g=g.UN;g=new UD(new Wq(g,g,a.Zb));op();d=SC(e,b,pp(qp(),g),!1,d)}else d=e.o();return d}\nfunction Lca(a,b){a=b.$a.U(a.qb.V);return a instanceof L?(a=a.k.Ab,a instanceof yo&&a.Pm.b()?!a.Hj.b():!0):!0}\nfunction gw(a,b){var c=a.MI;if(c.b()){c=!1;var d=null,e=b.tb.U(a.qb.V);a:{if(e instanceof L&&(c=!0,d=e,e=d.k,null!==e&&(Ot(new E(e.jj),Bp())||Ot(new E(e.jj),zp())))){t();b=rD(a.q,e,V(a.q),b);b=new L(b);break a}if(c&&(c=d.k,null!==c&&Ot(new E(c.jj),Fp()))){b=t().d;break a}c=b.$a.U(a.qb.V);if(c instanceof L&&(c=c.k.Ab,c instanceof yo&&(Ot(new E(c.pb),Bp())||Ot(new E(c.pb),zp())))){t();b=bz(a.q,c,V(a.q),b);b=new L(b);break a}b=t().d}a.MI=(t(),new L(b));a=b}else a=c.o();return a}\nfunction bw(a,b,c,d){var e=d.tb.U(a.qb.V);if(e instanceof L)e=e.k,d=e.Nu,e=e.Xm;else{if(t().d!==e)throw new w(e);e=d.$a.n(a.qb.V);d=t().d;var g=e.Ag();if(g===u())e=u();else{e=g.e();var h=e=new z(G(new H,e.kc,e.hb),u());for(g=g.f();g!==u();){var k=g.e();k=new z(G(new H,k.kc,k.hb),u());h=h.p=k;g=g.f()}}}if(d.b()){g=a.Zb;d=m=>c.ba(t().d,m);if(g===u())return u();e=g.e();h=e=new z(d(e),u());for(g=g.f();g!==u();)k=g.e(),k=new z(d(k),u()),h=h.p=k,g=g.f();return e}var l=d.o();tp();d=jv(e,a.Zb);up(0,Pe(new E(d),\n0));d=new Wq(e,e,a.Zb);e=new fn((m,n)=>{n=G(new H,m,n);var r=n.y;m=n.w;if(null!==r){n=l.n(r.j());if(null!==n&&(r=n.qe,!0===n.Qd&&!0===r))return m=t().d,c.ba(m,new cC(a.q,a.q.ib,a.q.La,V(a.q)));if(null!==n)return r=n.qe,n.Qd?n=b:r?b.b()?n=R():(n=!!b.o(),n=new L(!n)):n=t().d,c.ba(n,m);throw new w(n);}throw new w(n);});Yq();return Ew(d,e)}\nfunction aC(a,b,c,d){var e=tc();try{var g=d.tb.U(a.qb.V);if(g instanceof L)var h=g.k,k=h.Nu,l=h.Xm;else{if(t().d!==g)throw new w(g);var m=d.$a.Se(a.qb.V,new U(()=>{throw Hq(new Iq,e,O().c);})),n=it().n(VD(m)),r=m.Ag();if(r===u())var v=u();else{var x=r.e(),A=new z(G(new H,x.kc,x.hb),u());d=A;for(var B=r.f();B!==u();){var C=B.e(),D=new z(G(new H,C.kc,C.hb),u());d=d.p=D;B=B.f()}v=A}k=n;l=v}if(k.b()){var F=a.Zb,I=ia=>c.ba(new TB(b),ia);if(F===u())return u();var M=F.e(),N=new z(I(M),u());M=N;for(var P=\nF.f();P!==u();){var T=P.e(),Y=new z(I(T),u());M=M.p=Y;P=P.f()}return N}var Z=k.o();tp();I=jv(l,a.Zb);up(0,Pe(new E(I),0));var S=new Wq(l,l,a.Zb),ea=new fn((ia,X)=>{X=G(new H,ia,X);var sa=X.y;ia=X.w;if(null!==sa){X=Z.n(sa.j());if(null!==X&&(sa=X.qe,!0===X.Qd&&!0===sa))return ia=new TB(b),c.ba(ia,new cC(a.q,a.q.ib,a.q.La,V(a.q)));if(null!==X)return sa=X.qe,c.ba(X.Qd?b:sa?new UB(b):new TB(b),ia);throw new w(X);}throw new w(X);});Yq();return Ew(S,ea)}catch(ia){if(ia instanceof Iq){F=ia;if(F.Qg===e)return F.Cj();\nthrow F;}throw ia;}}function QD(a,b,c){if(null===b)throw le();if(b.sb)return b.vb;var d=a.q;c=c.Ag();c=new Wq(c,c,a.Zb);var e=new fn((g,h)=>{var k=G(new H,g,h);h=k.y;g=k.w;if(null!==h){k=h.kc;h=h.Rd;var l=new vl(a.qb.V+\"#\"+k.V);k=k.A();k=Cq(l,k);l=WD(a.q);h=h.b()?ou().Yl:h.o();g=XD(l,h,g,g,V(a.q));return G(new H,k,g)}throw new w(k);});Yq();c=Ew(c,e);return me(b,new Qv(d,c,V(a.q)))}\nfunction SD(a,b,c,d){if(null===b)throw le();if(b.sb)return b.vb;if(c){c=xv(a.q);var e=d.Xm,g=m=>{if(null!==m){var n=m.h();m=m.j();var r=dB(d);n=new vl(a.qb.V+\"#\"+n.V);m=new Uw(a.q,new L(r.n(m).Qd?a.q.ib:m),r.n(m).qe?a.q.La:m,a.Xl);return G(new H,n,m)}throw new w(m);};if(e===u())g=u();else{var h=e.e(),k=h=new z(g(h),u());for(e=e.f();e!==u();){var l=e.e();l=new z(g(l),u());k=k.p=l;e=e.f()}g=h}c=SA(c,g,V(a.q))}else c=a.q.La;return me(b,c)}\nfunction YD(a){var b=!1,c=Xz(Q(),a.x);if(c instanceof L&&(b=!0,48===Ea(c.k)))return Pe(new E(a.x.length),1);if(b){a=a.x;b=0;for(c=a.length;b<c;){var d=a.charCodeAt(b),e=Pr();if(!(256>d?48<=d&&57>=d:9===ZD(e,d)))return!1;b=1+b|0}return!0}if(t().d===c)return!1;throw new w(c);}function nB(a){return YD(a)?(a=a.x,$D(aE(),a)):t().d}\nfunction kca(a){var b=Hu(Q(),a.x);Or(Pr(),b)?(b=Hu(Q(),a.x),b=bE(Pr(),b)):b=!1;b?b=!0:(b=Hu(Q(),a.x),b=Pe(new E(hc(b)),hc(95)));b?b=!0:(b=Hu(Q(),a.x),b=Pe(new E(hc(b)),hc(36)));return b&&Nm(new E(a.x),\"true\")?Nm(new E(a.x),\"false\"):!1}function cE(a){a.xK(yn(a.mv()))}var Nca=function Mca(a,b){if(a.Ip.L(b))return!0;a=a.cJ;if(a.b())return!1;a=a.o();return Mca(a,b)};\nfunction dE(a,b){var c=tc();try{if(\"\"===b)return a.bJ.t();eE();var d=String.fromCharCode(39),e=String.fromCharCode(36),g=b.split(d).join(e);if(a.Ip.L(g)?0:!eq().qF.L(g))return g;for(b=1;;){d=\"\"+g+b;if(!a.Ip.L(d))throw Hq(new Iq,c,d);if(2147483647===b)break;b=1+b|0}throw new gm(\"\"===g?\"Cannot allocate a runtime name\":\"Cannot allocate a runtime name starting with '\"+g+\"'\");}catch(h){if(h instanceof Iq){a=h;if(a.Qg===c)return a.Cj();throw a;}throw h;}}\nfunction zo(a,b,c,d){var e=!1,g=null,h=a.Rx.U(b);a:{if(h instanceof L){e=!0;g=h;var k=g.k;if(k instanceof ko&&k.RP){b=new io(b,k.re,!1,c,!0);break a}}if(e)b=new io(b,g.k.zo(),!0,c,!0);else if(t().d===h)b=new io(b,dE(a,b),!1,c,!0);else throw new w(h);}vp(a,b);d.b()||(d=d.o(),vp(a,new io(d,b.nt,!1,c,!0)));return b}\nfunction fE(a,b){a.cJ=b;Ty();b=u();a.ko=Uy(b);Ty();b=u();a.Rx=Uy(b);pz();b=u();a.Ip=qz(b);Ty();b=u();a.PA=Uy(b);a.lo=new gE;a.bJ=new xo(new hE(1,1,2147483647,!1),new y(c=>{c|=0;var d=eE().QP;c=Oca(d,c);c=new Ef(c,new y(e=>{var g=ze(e,\"\",\"\",\"\");return G(new H,e,g)}));c=new iy(c,new y(e=>{if(null!==e)return!Nca(a,e.j());throw new w(e);}),!1);return new Ef(c,new y(e=>{if(null!==e)return e.j();throw new w(e);}))}));return a}function iE(){this.bJ=this.lo=this.PA=this.Ip=this.Rx=this.ko=this.cJ=null}\niE.prototype=new p;iE.prototype.constructor=iE;function yp(a,b){a.ko.bj(b.xo(),b);a.Rx.bj(b.xo(),b);a.Ip.oh(b.zo())}function vp(a,b){a.Rx.bj(b.xo(),b);a.Ip.oh(b.zo())}function Cm(a,b){var c=a.Rx.U(b);return c.b()?(a=a.cJ,a.b()?R():Cm(a.o(),b)):c}function Taa(a,b,c,d,e){var g=dE(a,b);b=new mn(b,g,c,d,e);yp(a,b);return b}function Saa(a,b,c,d){b=new nn(b,c,d);a.ko.bj(b.er,b)}\nfunction Im(a,b,c,d,e){var g=!1,h=null,k=a.Rx.U(b);a:{if(k instanceof L&&(g=!0,h=k,k=h.k,k instanceof io&&!k.RA)){g=k.nt;break a}if(g&&(k=h.k,k instanceof ko&&k.RP)){g=k.re;break a}if(g&&(g=h.k,g instanceof go&&!g.DP)){g=g.bF;break a}g=dE(a,b)}b=new ko(b,g,c,d,!1);vp(a,b);e.b()||(e=e.o(),vp(a,new ko(e,g,c,d,!1)));return b}function gp(a,b){b=dE(a,b);t();b=new ko(\"this\",b,new L(!1),!1,!1);Ly(a.PA,b.re,b,!1);vp(a,b);return b.re}\nfunction lm(a,b){var c=a.PA;a=()=>{throw new gm(\"qualifier \"+b+\" not found\");};if(ca(c)!==da(Ky))if(c=c.U(b),c instanceof L)a=c.k;else{if(R()!==c)throw new w(c);a=a()}else{var d=My(W(),b);d^=d>>>16|0;c=c.eb.a[d&(-1+c.eb.a.length|0)];c=null===c?null:Ny(c,b,d);a=null===c?a():c.Ah}return a}function Naa(a){var b=a.bJ.t();a.Ip.oh(b);return b}function Uo(a,b){b=dE(a,b);a.Ip.oh(b);return b}\nfunction wl(a,b){if(aq(Al(),b))var c=b;else if(eq().qF.L(b))c=b+\"$\";else{eE();c=String.fromCharCode(39);var d=String.fromCharCode(36);c=b.split(c).join(d)}c=dE(a,c);vp(a,new ko(b,c,new L(!1),!1,!1));return c}function Hm(a){var b=fE(new iE,(t(),new L(a)));a=a.PA;for(var c=a.eb.a.length,d=0;d<c;){var e=a.eb.a[d];if(null!==e)for(;;){var g=e.Wk,h=e.Ah;b.Ip.oh(g);Ly(b.PA,g,h,!1);if(null!==e.$d)e=e.$d;else break}d=1+d|0}return b}iE.prototype.$classData=q({w_:0},!1,\"mlscript.codegen.Scope\",{w_:1,g:1});\nfunction jE(){this.QP=null;kE=this;t();tp();var a=new Jr(\"abcdefghijklmnopqrstuvwxyz\");this.QP=Pd(u(),a)}jE.prototype=new p;jE.prototype.constructor=jE;jE.prototype.$classData=q({x_:0},!1,\"mlscript.codegen.Scope$\",{x_:1,g:1});var kE;function eE(){kE||(kE=new jE);return kE}\nfunction lE(){this.qF=null;mE=this;this.qF=Aq(tp().Iv,J(new K,\"break case catch class const continue debugger default delete do else export extends finally for function if import in instanceof new return super switch this throw try typeof var void while with yield enum abstract boolean byte char double final float goto int long native short synchronized throws transient volatile\".split(\" \")))}lE.prototype=new p;lE.prototype.constructor=lE;\nlE.prototype.$classData=q({A_:0},!1,\"mlscript.codegen.Symbol$\",{A_:1,g:1});var mE;function eq(){mE||(mE=new lE);return mE}function nE(){this.SP=\"??\"}nE.prototype=new p;nE.prototype.constructor=nE;nE.prototype.$classData=q({G_:0},!1,\"mlscript.package$\",{G_:1,g:1});var oE;function pE(){oE||(oE=new nE);return oE}function qE(a){a.lf=O().c}function rE(){this.lf=null}rE.prototype=new p;rE.prototype.constructor=rE;function sE(){}sE.prototype=rE.prototype;\nfunction tE(a){if(a.lf.b())return\"\";var b=a.lf;a=O().c;if(null===a?null===b:a.i(b))a=\"\";else{if(b===u())a=u();else{a=b.e();var c=a=new z(a.Sj.x,u());for(b=b.f();b!==u();){var d=b.e();d=new z(d.Sj.x,u());c=c.p=d;b=b.f()}}a=ze(a,\"(\",\", \",\")\")}return\" with \"+a}var Qca=function Pca(a,b,c,d){return c.L(b)?c:d.Se(b,new U(()=>u())).De(c.bc(b),new fn((g,h)=>Pca(a,h,g,d)))};function uE(){}uE.prototype=new p;uE.prototype.constructor=uE;\nfunction Rca(a,b){a=b.m();a=new xo(a,new y(e=>{if(null!==e){var g=e.h();e=e.j().m();return new Ef(e,new y(h=>G(new H,h,g)))}throw new w(e);}));for(b=nf();a.s();){var c=a.t();b=G(new H,b,c);a:{c=b.y;var d=b.w;if(null!==d&&(d=new L(d),!d.b())){b=c.IC(d.k.h(),new y((e=>g=>{if(R()===g)return g=O().c,new L(new z(e,g));if(g instanceof L)return new L(new z(e,g.k));throw new w(g);})(d.k.j())));break a}throw new w(b);}}return b}\nfunction Sca(a,b){var c=b.zr().Ja(new y(d=>{tp();var e=u();e=Qca(a,d,Aq(0,e),b).Ek(d);Od();e=Pd(u(),e);return G(new H,d,e)}));op();return c.Ti()}function vE(a,b,c,d,e){c.n(new U(()=>\"\\u2022 \"+d));b.b()?c.n(new U(()=>\"  + \\x3cEmpty\\x3e\")):b.og(new fn((g,h)=>{c.n(new U(()=>\"  + \"+g+\" \"+e+\" \"+(h.b()?\"{}\":ze(h,\"{ \",\", \",\" }\"))))}))}uE.prototype.$classData=q({R_:0},!1,\"mlscript.ucs.Desugarer$\",{R_:1,g:1});var wE;function xE(){wE||(wE=new uE);return wE}function yE(){}yE.prototype=new p;\nyE.prototype.constructor=yE;function zE(){}zE.prototype=yE.prototype;function AE(a,b){if(null===a)throw le();if(a.sb)return a.vb;b=b.ni.m();b=new Ef(b,new y(c=>{if(null!==c){var d=c.Sj,e=c.gr;if(null!==d)return\"[binding \"+d.x+\" \\x3d \"+Zz(e,!1)+\"]\"}throw new w(c);}));Od();return me(a,Pd(u(),b))}\nvar Tca=function BE(a,b,c,d){for(;;){var g=new $e,h=ut(Q(),\"  \",c),k=b;if(k instanceof CE){var l=k,m=l.hr;k=l.Dk;l=l.Fh;for(b=g.sb?g.vb:AE(g,b);!b.b();)g=b.e(),d.$(\"\"+h+g),b=b.f();b=h+(\"if \\u00ab\"+Zz(m,!1))+\"\\u00bb\";d.$(b);BE(a,k,1+c|0,d);d.$(h+\"else\");h=1+c|0;b=l;c=h}else{if(k instanceof DE){l=k;k=l.mo;m=l.mh;l=l.nj;for(b=g.sb?g.vb:AE(g,b);!b.b();)g=b.e(),d.$(\"\"+h+g),b=b.f();b=\"\"+h;var n=k;g=Zz(n.nh,!1);n=n.no;a:if(t().d===n)n=\"\";else{if(n instanceof L){var r=n.k;if(null!==r){n=\" as \"+r.x;break a}}throw new w(n);\n}d.$(b+(\"\\u00ab\"+g+\"\\u00bb\"+n)+\" match\");b=c;for(m=m.m();m.s();)a:if(n=m.t(),n instanceof EE)g=n.Jp,n=h+\"  case \"+Zz(n.ir,!1)+\" \\x3d\\x3e\",d.$(n),BE(a,g,1+b|0,d);else{if(n instanceof FE&&(g=n,r=g.Tj,g=g.pl,null!==r)){var v=new L(r);if(!v.b()&&(r=v.k.h(),v=v.k.j(),null!==r)){d.$(h+\"  case \"+r.x+\" \\x3d\\x3e\");for(n=v.m();n.s();)b:{if(v=n.t(),null!==v){r=v.h();var x=v.j();if(null!==x){v=x.x;x=GE(k);r=h+\"    [pattern \"+v+\" \\x3d \"+Zz(x,!1)+\".\"+r+\"]\";d.$(r);break b}}throw new w(v);}BE(a,g,2+b|0,d);break a}}throw new w(n);\n}l.b()||(k=l.o(),d.$(h+\"  default\"),BE(a,k,2+c|0,d))}else if(k instanceof HE){a=k.ot;for(c=g.sb?g.vb:AE(g,b);!c.b();)k=c.e(),d.$(\"\"+h+k),c=c.f();h=h+\"\\u00ab\"+Zz(a,!1)+\"\\u00bb\";d.$(h)}else if(IE()===k){for(a=g.sb?g.vb:AE(g,b);!a.b();)c=a.e(),d.$(\"\"+h+c),a=a.f();d.$(h+\"\\x3cmissing case\\x3e\")}else throw new w(k);break}}};\nfunction JE(a,b){if(null===a)throw le();if(a.sb)return a.vb;b=b.lf;if(b.b())b=Od().jC;else{Od();var c=new fp;Od();for(var d=new fp,e=b.m();e.s();){var g=e.t(),h=g;a:{if(null!==h){var k=h.fr;if(KE()===k){h=!1;break a}}if(null!==h)h=!0;else throw new w(h);}wp(h?c:d,g)}c=G(new H,c.ha(),d.ha());d=c.y;u().i(d)?b=G(new H,u(),b):(d=c.w,b=u().i(d)?G(new H,b,u()):c)}if(null===b)throw new w(b);return me(a,G(new H,b.h(),b.j()))}\nfunction LE(a,b,c){if(a.sb)a=a.vb;else{if(null===a)throw le();a=a.sb?a.vb:me(a,(b.sb?b.vb:JE(b,c)).h())}return a}function ME(a,b,c){if(a.sb)a=a.vb;else{if(null===a)throw le();a=a.sb?a.vb:me(a,(b.sb?b.vb:JE(b,c)).j())}return a}\nvar cF=function Uca(a,b,c){if(null!==b){var e=b.Wi,g=b.mj;if(e instanceof z){b=e.z;var h=new $e,k=new $e,l=new $e;c=Uca(a,new NE(e.p,g),c);if(b instanceof OE)return a=b.$x,g=b.Zx,e=PE(),l=ME(l,h,b),l=new EE(g,QE(c,l)),c=g.A(),l.pt.zc(c),l=RE(e,J(new K,[l])),l=new DE(a,l,t().d),b=LE(k,h,b),QE(l,b);if(b instanceof SE)return a=b.Wx,e=TE(PE()),t(),l=ME(l,h,b),l=QE(c,l),l=new DE(a,e,new L(l)),b=LE(k,h,b),QE(l,b);if(b instanceof UE){a=b.Yx;g=b.Xx;var m=b.WA;e=PE();m=PE().vl(m);g=G(new H,g,m);l=ME(l,h,b);\nl=[VE(new FE(g,QE(c,l)),b.Cv())];l=RE(e,J(new K,l));l=new DE(a,l,t().d);b=LE(k,h,b);return QE(l,b)}if(b instanceof WE)return a=b.ev,m=b.dv,g=b.ay,e=PE(),m=new vl(\"Tuple#\"+m),g=PE().vl(g),g=G(new H,m,g),l=ME(l,h,b),l=[VE(new FE(g,QE(c,l)),b.Cv())],l=RE(e,J(new K,l)),l=new DE(a,l,t().d),b=LE(k,h,b),QE(l,b);if(b instanceof XE)return c=new CE(b.Vx,c,IE()),k=LE(k,h,b),k=QE(c,k),b=ME(l,h,b),QE(k,b);if(b instanceof YE)return a=b.bv,e=b.cv,b.Ux?(ZE||(ZE=new $E),g=ZE):g=aF(),k=LE(k,h,b),k=QE(c,k),c=new bF(g,\n!1,a,e),a=O().c,k=QE(k,new z(c,a)),b=ME(l,h,b),QE(k,b);throw new w(b);}}if(null!==b&&(k=b.Wi,h=b.mj,l=O().c,null===l?null===k:l.i(k)))return b=new HE(c),QE(b,h);throw new w(b);};function dF(){}dF.prototype=new p;dF.prototype.constructor=dF;function eF(a,b){var c=TE(PE());Tca(a,b,0,c);return c.ha()}dF.prototype.$classData=q({X_:0},!1,\"mlscript.ucs.MutCaseOf$\",{X_:1,g:1});var fF;function gF(){fF||(fF=new dF);return fF}function hF(){this.pt=null}hF.prototype=new p;hF.prototype.constructor=hF;\nfunction iF(){}iF.prototype=hF.prototype;function VE(a,b){a.pt.zc(b);return a}function jF(){}jF.prototype=new p;jF.prototype.constructor=jF;function kF(){}kF.prototype=jF.prototype;function lF(a,b){for(b=b.m();b.s();){var c=b.t();a.fv.L(c)||(a.fv.$(c),a.ni.$(c))}}function QE(a,b){lF(a,b);return a}\nvar mF=function Vca(a,b,c,d){for(;;){var g=b;b=O().c;if(null===b?null===g:b.i(g))return d;if(g instanceof z){var h=g;b=h.z;h=h.p;if(null!==b){g=b.ZA;var k=b.Sj;b=b.gr;if(c.L(k)){b=h;continue}else return new Rl(g,k,b,Vca(a,h,c.bc(k),d))}}throw new w(g);}};function nF(){}nF.prototype=new p;nF.prototype.constructor=nF;function oF(a){var b=t().d;a=new sm(tm().Cg,a);b=G(new H,b,a);a=O().c;return new Gl(new z(b,a))}\nfunction pF(a,b,c,d,e){return e?(eu(),new Pl(c,fu(0,J(new K,[b,d])))):new Pl(new Pl(c,oF(b)),oF(d))}\nfunction qF(a,b){var c=!1,d=null;if(b instanceof Pl){c=!0;d=b;var e=d.Za,g=d.Qb;if(e instanceof Pl){var h=e.Za;e=e.Qb;if(h instanceof vl&&\"and\"===h.x&&e instanceof Gl&&(e=e.Ra,e instanceof z&&(h=e.z,e=e.p,null!==h&&(h=new L(h),!h.b()&&(h=h.k.j(),null!==h))))){h=h.ya;var k=O().c;if((null===k?null===e:k.i(e))&&g instanceof Gl&&(g=g.Ra,g instanceof z&&(e=g.z,g=g.p,null!==e&&(e=new L(e),!e.b()&&(e=e.k.j(),null!==e&&(e=e.ya,k=O().c,null===k?null===g:k.i(g)))))))return a=qF(a,h),Xq(a,e)}}}if(c&&(c=d.Za,\nd=d.Qb,c instanceof vl&&\"and\"===c.x&&null!==d&&(d=mz(eu(),d),!d.b()&&null!==d.o()&&0===d.o().ab(2))))return b=d.o(),b=eB(b,0),d=d.o(),d=eB(d,1),a=qF(a,b),Xq(a,d);a=O().c;return new z(b,a)}\nfunction rF(a,b,c){var d=!1,e=null;if(b instanceof Pl){d=!0;e=b;var g=e.Za,h=e.Qb;if(g instanceof Pl){var k=g.Za;g=g.Qb;if(k instanceof vl&&\"and\"===k.x&&g instanceof Gl){var l=g.Ra;if(l instanceof z&&(g=l.z,l=l.p,null!==g&&(g=new L(g),!g.b()&&(g=g.k.j(),null!==g)))){g=g.ya;var m=O().c;if((null===m?null===l:m.i(l))&&h instanceof Gl&&(l=h.Ra,l instanceof z&&(h=l.z,l=l.p,null!==h&&(h=new L(h),!h.b()&&(h=h.k.j(),null!==h&&(h=h.ya,m=O().c,null===m?null===l:m.i(l))))))){a=rF(a,g,c);if(null!==a&&(b=a.h(),\ne=a.j(),t().d===e))return G(new H,b,(t(),new L(h)));if(null!==a&&(b=a.h(),e=a.j(),e instanceof L))return a=e.k,t(),c=pF(0,a,k,h,c),G(new H,b,new L(c));throw new w(a);}}}}}if(d&&(k=e.Za,e=e.Qb,k instanceof vl&&\"and\"===k.x&&null!==e&&(e=mz(eu(),e),!e.b()&&null!==e.o()&&0===e.o().ab(2)))){b=e.o();d=eB(b,0);b=e.o();b=eB(b,1);a=rF(a,d,c);if(null!==a&&(e=a.h(),d=a.j(),t().d===d))return G(new H,e,(t(),new L(b)));if(null!==a&&(e=a.h(),d=a.j(),d instanceof L))return a=d.k,t(),c=pF(0,a,k,b,c),G(new H,e,new L(c));\nthrow new w(a);}return G(new H,b,t().d)}nF.prototype.$classData=q({j0:0},!1,\"mlscript.ucs.helpers$\",{j0:1,g:1});var sF;function tF(){sF||(sF=new nF);return sF}q({k0:0},!1,\"mlscript.utils.algorithms$\",{k0:1,g:1});function uF(){}uF.prototype=new p;uF.prototype.constructor=uF;\nfunction Wca(a,b,c,d){a=G(new H,b,c);c=a.y;b=a.w;if(c instanceof L&&(c=c.k,b instanceof L))return a=d.ba(c,b.k),it().n(a);d=a.y;if(d instanceof L)return d;d=a.w;if(d instanceof L)return d;d=a.y;b=a.w;if(R()===d&&R()===b)return R();throw new w(a);}function vF(){wF();throw RD(\"please add this rare case to test files\");}function xm(a){wF();var b=new xF;yF(b,\"Internal Error: \"+a,null,!0);throw b;}uF.prototype.$classData=q({m0:0},!1,\"mlscript.utils.package$\",{m0:1,g:1});var zF;\nfunction wF(){zF||(zF=new uF);return zF}function E(a){this.gv=a}E.prototype=new p;E.prototype.constructor=E;function Pe(a,b){a=a.gv;return ml(nl(),a,b)}function Nm(a,b){a=a.gv;return!ml(nl(),a,b)}function Ot(a,b){return Object.is(a.gv,b)}function dx(a,b){return!Object.is(a.gv,b)}function Lf(a,b){a=a.gv;return ml(nl(),a,b)}function Xca(a,b){return!!b.n(a.gv)}function Yca(a,b){return b.qo(new y(c=>Pe(new E(c),a.gv)))}E.prototype.$classData=q({n0:0},!1,\"mlscript.utils.package$AnyOps\",{n0:1,g:1});\nfunction AF(){}AF.prototype=new p;AF.prototype.constructor=AF;function BF(a,b){a=b.m();return a.s()?ze(a,\"[\",\", \",\"]\"):\"\"}function CF(a,b){a=b.m();a=new Ef(a,new y(c=>{ve();c=nb(c);var d=ue(ve(),c);c=new DF;for(d=sl(d).m();d.s();){var e=d.t();EF(c,\"\\t\"+e)}return\"\\n\"+ze(c.lk,\"\",\"\\n\",\"\")}));return ze(a,\"\",\"\",\"\")}AF.prototype.$classData=q({o0:0},!1,\"mlscript.utils.package$IterableOps$\",{o0:1,g:1});var FF;function GF(){FF||(FF=new AF);return FF}function yt(a){this.mJ=a}yt.prototype=new p;\nyt.prototype.constructor=yt;function HF(a){var b=Zca(),c=a.mJ;a=O().c;for(c=Km(c);!c.b();){var d=c.e();a=a.b()||!b.ba(a.e(),d)?new z(d,a):a;c=c.f()}return a}function Zca(){return new fn((a,b)=>Pe(new E(a),b))}function hba(a){if(a.mJ.b())return t().d;t();a=a.mJ.f();return new L(a)}yt.prototype.$classData=q({p0:0},!1,\"mlscript.utils.package$ListHelpers\",{p0:1,g:1});function zB(a){this.en=a}zB.prototype=new p;zB.prototype.constructor=zB;\nzB.prototype.$classData=q({q0:0},!1,\"mlscript.utils.package$MutSetHelpers\",{q0:1,g:1});function Dx(a){this.wF=a}Dx.prototype=new p;Dx.prototype.constructor=Dx;Dx.prototype.$classData=q({r0:0},!1,\"mlscript.utils.package$OptionHelpers\",{r0:1,g:1});function IF(){}IF.prototype=new p;IF.prototype.constructor=IF;function JF(a,b,c){a=$ca(lv(),b,c);Od();return Pd(u(),a)}function ry(a,b,c){a=KF(lv(),b,c);Od();return Pd(u(),a)}\nfunction $ca(a,b,c){a=b.m();return new Ef(a,new y(d=>{var e=c.n(d.h());return G(new H,e,d.j())}))}function KF(a,b,c){a=b.m();return new Ef(a,new y(d=>{var e=d.h();d=c.n(d.j());return G(new H,e,d)}))}function dy(a,b){a=b.m();return new Ef(a,new y(c=>c.h()))}function mv(a,b){a=b.m();return new Ef(a,new y(c=>c.j()))}IF.prototype.$classData=q({s0:0},!1,\"mlscript.utils.package$PairIterableOps$\",{s0:1,g:1});var LF;function lv(){LF||(LF=new IF);return LF}function gq(a){return MF(NF(new OF,a))}\nq({t0:0},!1,\"mlscript.utils.package$SetObjectHelpers\",{t0:1,g:1});function $v(a,b){return sv().Dv(b).$(a).Kb()}q({u0:0},!1,\"mlscript.utils.package$SortedMapObjectHelpers\",{u0:1,g:1});function vv(a,b){return uv().GB(b).$(a).Kb()}q({v0:0},!1,\"mlscript.utils.package$SortedSetObjectHelpers\",{v0:1,g:1});function PF(){}PF.prototype=new p;PF.prototype.constructor=PF;\nfunction ue(a,b){QF();a=[ce()];a=J(new K,a);a=RF(a);for(var c=b.length,d=0;d<c;){var e=b.charCodeAt(d);if(Pe(new E(hc(e)),hc(10))){var g=ce();ol(a,g)}else g=SF(a).yf,e=String.fromCharCode(e),g.ja=\"\"+g.ja+e;d=1+d|0}b=new DF;for(a=sl(a).m();a.s();)c=a.t().yf.ja,EF(b,c);return b.lk}\nfunction ada(a){var b=ue(ve(),a);Od();var c=Pd(u(),b);if(c instanceof z){b=c.z;var d=c.p;if(d instanceof z){if(d===u())a=u();else for(c=a=new z(\"  \"+d.z,u()),d=d.p;d!==u();){var e=d.e();e=new z(\"  \"+e,u());c=c.p=e;d=d.f()}return b+\"\\n\"+ze(a,\"\",\"\\n\",\"\")}}return a}function hB(a,b){return\"\"!==b?(a=Hu(Q(),b),TF(Pr(),a)):!1}function UF(a,b){Pe(new E(b.length),0)?a=!0:(a=b.charCodeAt(0),a=!TF(Pr(),a));if(a)return b;Q();a=b.charCodeAt(0);Pr();a=65535&bda(a);return VF(b,a)}\nfunction WF(a,b,c,d){return 1<c?b+(d?\"es\":\"s\"):b}PF.prototype.$classData=q({w0:0},!1,\"mlscript.utils.package$StringOps$\",{w0:1,g:1});var XF;function ve(){XF||(XF=new PF);return XF}function YF(){this.d=null;ZF=this;O();O();ju();$F||($F=new aG);this.d=R();O();O();O()}YF.prototype=new p;YF.prototype.constructor=YF;function it(){t();return new y(a=>new L(a))}YF.prototype.$classData=q({x0:0},!1,\"mlscript.utils.shorthands$\",{x0:1,g:1});var ZF;function t(){ZF||(ZF=new YF);return ZF}\nfunction ma(a,b){this.W=a;this.Y=b}ma.prototype=new p;ma.prototype.constructor=ma;f=ma.prototype;f.i=function(a){return a instanceof ma?this.W===a.W&&this.Y===a.Y:!1};f.B=function(){return this.W^this.Y};f.u=function(){return bG(xa(),this.W,this.Y)};f.jB=function(){return this.W<<24>>24};f.EC=function(){return this.W<<16>>16};f.Zi=function(){return this.W};f.xl=function(){return Za(this)};\nf.pv=function(){xa();var a=this.W,b=this.Y;if(0>b){var c=-a|0;a=0!==a?~b:-b|0}else c=a,a=b;c=4294967296*+(a>>>0)+ +((0===(-2097152&a)||0===(65535&c)?c:32768|-65536&c)>>>0);return Math.fround(0>b?-c:c)};f.Lp=function(){return cG(xa(),this.W,this.Y)};f.sl=function(a){return ua(xa(),this.W,this.Y,a.W,a.Y)};f.$classData=q({B0:0},!1,\"org.scalajs.linker.runtime.RuntimeLong\",{B0:1,g:1});function dG(a,b,c){return 0===(-2097152&c)?\"\"+(4294967296*c+ +(b>>>0)):eG(a,b,c,1E9,0,2)}\nfunction fG(a,b,c,d,e){return 0===(-2097152&c)?0===(-2097152&e)?(c=(4294967296*c+ +(b>>>0))/(4294967296*e+ +(d>>>0)),a.Qc=c/4294967296|0,c|0):a.Qc=0:0===e&&0===(d&(-1+d|0))?(d=31-Math.clz32(d)|0,a.Qc=c>>>d|0,b>>>d|0|c<<1<<(31-d|0)):0===d&&0===(e&(-1+e|0))?(b=31-Math.clz32(e)|0,a.Qc=0,c>>>b|0):eG(a,b,c,d,e,0)|0}\nfunction eG(a,b,c,d,e,g){var h=(0!==e?Math.clz32(e):32+Math.clz32(d)|0)-(0!==c?Math.clz32(c):32+Math.clz32(b)|0)|0,k=h,l=0===(32&k)?d<<k:0,m=0===(32&k)?(d>>>1|0)>>>(31-k|0)|0|e<<k:d<<k;k=b;var n=c;for(b=c=0;0<=h&&0!==(-2097152&n);){var r=k,v=n,x=l,A=m;if(v===A?(-2147483648^r)>=(-2147483648^x):(-2147483648^v)>=(-2147483648^A))r=n,v=m,n=k-l|0,r=(-2147483648^n)>(-2147483648^k)?-1+(r-v|0)|0:r-v|0,k=n,n=r,32>h?c|=1<<h:b|=1<<h;h=-1+h|0;r=m>>>1|0;l=l>>>1|0|m<<31;m=r}h=n;if(h===e?(-2147483648^k)>=(-2147483648^\nd):(-2147483648^h)>=(-2147483648^e))h=4294967296*n+ +(k>>>0),d=4294967296*e+ +(d>>>0),1!==g&&(m=h/d,e=m/4294967296|0,l=c,c=m=l+(m|0)|0,b=(-2147483648^m)<(-2147483648^l)?1+(b+e|0)|0:b+e|0),0!==g&&(d=h%d,k=d|0,n=d/4294967296|0);if(0===g)return a.Qc=b,c;if(1===g)return a.Qc=n,k;a=\"\"+k;return\"\"+(4294967296*b+ +(c>>>0))+\"000000000\".substring(a.length)+a}function gG(){this.Qc=0}gG.prototype=new p;gG.prototype.constructor=gG;\nfunction bG(a,b,c){return c===b>>31?\"\"+b:0>c?\"-\"+dG(a,-b|0,0!==b?~c:-c|0):dG(a,b,c)}function cG(a,b,c){return 0>c?-(4294967296*+((0!==b?~c:-c|0)>>>0)+ +((-b|0)>>>0)):4294967296*c+ +(b>>>0)}function ua(a,b,c,d,e){return c===e?b===d?0:(-2147483648^b)<(-2147483648^d)?-1:1:c<e?-1:1}\nfunction $h(a,b,c,d,e){if(0===(d|e))throw new qb(\"/ by zero\");if(c===b>>31){if(e===d>>31){if(-2147483648===b&&-1===d)return a.Qc=0,-2147483648;c=pb(b,d);a.Qc=c>>31;return c}return-2147483648===b&&-2147483648===d&&0===e?a.Qc=-1:a.Qc=0}if(0>c){var g=-b|0;b=0!==b?~c:-c|0}else g=b,b=c;if(0>e){var h=-d|0;d=0!==d?~e:-e|0}else h=d,d=e;g=fG(a,g,b,h,d);if(0<=(c^e))return g;c=a.Qc;a.Qc=0!==g?~c:-c|0;return-g|0}\nfunction Wh(a,b,c,d,e){if(0===(d|e))throw new qb(\"/ by zero\");return 0===c?0===e?(a.Qc=0,0===d?pb(0,0):+(b>>>0)/+(d>>>0)|0):a.Qc=0:fG(a,b,c,d,e)}\nfunction Ri(a,b,c,d,e){if(0===(d|e))throw new qb(\"/ by zero\");if(c===b>>31){if(e===d>>31)return-1!==d?(c=Bb(b,d),a.Qc=c>>31,c):a.Qc=0;if(-2147483648===b&&-2147483648===d&&0===e)return a.Qc=0;a.Qc=c;return b}if(0>c)var g=-b|0,h=0!==b?~c:-c|0;else g=b,h=c;0>e?(b=-d|0,d=0!==d?~e:-e|0):(b=d,d=e);0===(-2097152&h)?0===(-2097152&d)?(b=(4294967296*h+ +(g>>>0))%(4294967296*d+ +(b>>>0)),a.Qc=b/4294967296|0,b|=0):(a.Qc=h,b=g):0===d&&0===(b&(-1+b|0))?(a.Qc=0,b=g&(-1+b|0)):0===b&&0===(d&(-1+d|0))?(a.Qc=h&(-1+\nd|0),b=g):b=eG(a,g,h,b,d,1)|0;return 0>c?(c=a.Qc,a.Qc=0!==b?~c:-c|0,-b|0):b}gG.prototype.$classData=q({C0:0},!1,\"org.scalajs.linker.runtime.RuntimeLong$\",{C0:1,g:1});var hG;function xa(){hG||(hG=new gG);return hG}function iG(){this.EK=this.KB=null;jG=this;this.KB=new Xc(0);this.EK=new zc(0)}iG.prototype=new p;iG.prototype.constructor=iG;iG.prototype.$classData=q({X2:0},!1,\"scala.Array$EmptyArrays$\",{X2:1,g:1});var jG;function kG(){jG||(jG=new iG);return jG}function lG(){}lG.prototype=new p;\nlG.prototype.constructor=lG;function mG(){}mG.prototype=lG.prototype;function dD(a,b){this.lR=null;this.e3=b;if(null===a)throw null;this.lR=a}dD.prototype=new p;dD.prototype.constructor=dD;dD.prototype.$classData=q({d3:0},!1,\"scala.Option$WithFilter\",{d3:1,g:1});function nG(){this.nR=this.Hv=null;oG=this;this.Hv=new y(()=>pG().Hv);this.nR=new qG}nG.prototype=new p;nG.prototype.constructor=nG;function rG(a,b){return a.Hv===b}nG.prototype.$classData=q({f3:0},!1,\"scala.PartialFunction$\",{f3:1,g:1});\nvar oG;function pG(){oG||(oG=new nG);return oG}function sG(){}sG.prototype=new p;sG.prototype.constructor=sG;function cda(a,b){up(tp(),b);return a}sG.prototype.$classData=q({m3:0},!1,\"scala.Predef$Ensuring$\",{m3:1,g:1});var tG;function uG(a){this.oR=null;if(null===a)throw null;this.oR=a}uG.prototype=new p;uG.prototype.constructor=uG;function dda(a,b){return eda(Qq(),a.oR.Jv,b)}uG.prototype.$classData=q({t3:0},!1,\"scala.StringContext$s$\",{t3:1,g:1});function vG(){}vG.prototype=new p;\nvG.prototype.constructor=vG;\nfunction ns(a,b,c,d){a=0<c?c:0;c=wG(xG(),b);d=d<c?d:c;if(d>a){if(b instanceof zc)return Jj(Pj(),b,a,d);if(b instanceof Xc){Pj();if(a>d)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new Xc(d);b.wa(a,d,0,c);return d}if(b instanceof ed){Pj();if(a>d)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new ed(d);b.wa(a,d,0,c);return d}if(b instanceof Zc){Pj();if(a>d)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new Zc(d);b.wa(a,d,0,c);return d}if(b instanceof $c){Pj();\nif(a>d)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new $c(d);b.wa(a,d,0,c);return d}if(b instanceof Ic){Pj();if(a>d)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new Ic(d);b.wa(a,d,0,c);return d}if(b instanceof Pc){Pj();if(a>d)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new Pc(d);b.wa(a,d,0,c);return d}if(b instanceof Sc){Pj();if(a>d)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new Sc(d);b.wa(a,d,0,c);return d}if(b instanceof Ec){Pj();if(a>\nd)throw Kj(a+\" \\x3e \"+d);d=d-a|0;c=b.a.length-a|0;c=d<c?d:c;d=new Ec(d);b.wa(a,d,0,c);return d}throw new w(b);}return yG(zG(),bg(ca(b))).si(0)}function ls(a,b,c){return ns(ms(),b,c,wG(xG(),b))}\nfunction AG(a){if(a instanceof zc)return Du(new Eu,a);if(a instanceof Xc)return new BG(a);if(a instanceof ed)return new CG(a);if(a instanceof Zc)return new DG(a);if(a instanceof $c)return new EG(a);if(a instanceof Ic)return new FG(a);if(a instanceof Pc)return new GG(a);if(a instanceof Sc)return new HG(a);if(a instanceof Ec)return new IG(a);if(ph(a))return new JG(a);if(null===a)throw le();throw new w(a);}\nfunction Tu(a,b){var c=wG(xG(),a);if(1>=c)return KG(xG(),a);if(a instanceof zc)return c=zj(Pj(),a,c),hj(Pj(),c,b),c;if(a instanceof Xc){if(b===Fq())return c=Fj(Pj(),a,c),Ti(Pj(),c),c}else if(a instanceof Zc){if(b===LG())return c=Gj(Pj(),a,c),$i(Pj(),c),c}else if(a instanceof Ic){if(b===MG())return c=Hj(Pj(),a,c),dj(Pj(),c),c}else if(a instanceof Pc){if(b===NG())return c=Dj(Pj(),a,c),fj(Pj(),c),c}else if(a instanceof Sc){if(b===OG())return c=Ej(Pj(),a,c),bj(Pj(),c),c}else if(a instanceof Ec&&b===PG()){c=\nIj(Pj(),a,c);var d=QG();b=PG();RG(d,c,c.a.length,b);return c}300>c?(c=KG(xG(),a),RG(QG(),c,wG(xG(),c),b)):(SG(),TG(),Zf(da(jd),bg(ca(a)))?d=Yf(da(jd))?UG(a,c):Cj(Pj(),a,c,da(md(jd))):(d=new zc(c),VG(SG(),a,0,d,0,wG(xG(),a))),hj(Pj(),d,b),SG(),b=yG(zG(),bg(ca(a))),a=b.uh(),null!==a&&a===da(pd)?c=WG(c):Zf(a,bg(ca(d)))?Yf(a)?c=UG(d,c):(b=rh(th(),a,0),b=ca(b),c=Cj(Pj(),d,c,b)):(c=b.si(c),VG(SG(),d,0,c,0,wG(xG(),d))));return c}\nfunction lB(a,b,c){if(null===a)throw le();if(a instanceof zc){for(var d=wG(xG(),a),e=0;e<d;)b=c.ba(b,XG(xG(),a,e)),e=1+e|0;return b}if(a instanceof Xc){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}if(a instanceof ed){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}if(a instanceof Zc){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}if(a instanceof $c){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}if(a instanceof Ic){d=a.a.length;for(e=0;e<d;)b=c.ba(b,\nhc(a.a[e])),e=1+e|0;return b}if(a instanceof Pc){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}if(a instanceof Sc){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}if(a instanceof Ec){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}if(ph(a)){d=a.a.length;for(e=0;e<d;)b=c.ba(b,a.a[e]),e=1+e|0;return b}throw new w(a);}vG.prototype.$classData=q({y4:0},!1,\"scala.collection.ArrayOps$\",{y4:1,g:1});var YG;function ms(){YG||(YG=new vG);return YG}function ZG(){}\nZG.prototype=new p;ZG.prototype.constructor=ZG;function $G(a,b){a=b+~(b<<9)|0;a^=a>>>14|0;a=a+(a<<4)|0;return a^(a>>>10|0)}ZG.prototype.$classData=q({W4:0},!1,\"scala.collection.Hashing$\",{W4:1,g:1});var aH;function bH(){aH||(aH=new ZG);return aH}function cH(a,b){for(a=a.m();a.s();)b.n(a.t())}function nw(a,b){var c=!0;for(a=a.m();c&&a.s();)c=!!b.n(a.t());return c}function ey(a,b){var c=!1;for(a=a.m();!c&&a.s();)c=!!b.n(a.t());return c}\nfunction dH(a,b){for(a=a.m();a.s();){var c=a.t();if(b.n(c))return new L(c)}return R()}function mB(a,b,c){for(a=a.m();a.s();)b=c.ba(b,a.t());return b}function Qu(a,b,c){return a.ad().De(b,new fn((d,e)=>c.ba(e,d)))}function eH(a,b){a=a.m();if(!a.s())throw nv(\"empty.reduceLeft\");for(var c=!0,d=null;a.s();){var e=a.t();c?(d=e,c=!1):d=b.ba(d,e)}return d}function kba(a,b){if(!a.m().s())throw nv(\"empty.reduceRight\");return a.ad().th(new fn((c,d)=>b.ba(d,c)))}\nfunction Qba(a,b){return a.b()?R():new L(a.th(b))}function hs(a){if(0<=a.Q())return a.Q();a=a.m();for(var b=0;a.s();)b=1+b|0,a.t();return b}function NB(a,b,c,d){a=a.m();var e=c,g=wG(xG(),b)-c|0;for(d=c+(d<g?d:g)|0;e<d&&a.s();)fH(xG(),b,e,a.t()),e=1+e|0;return e-c|0}function fda(a){return a.b()?0:a.th(new fn((b,c)=>(b|0)+(c|0)|0))}function gH(a,b){if(a.b())throw nv(\"empty.min\");return a.th(new fn((c,d)=>b.Kk(c,d)))}function Gq(a,b){return a.b()?R():new L(a.aj(b))}\nfunction hH(a,b){if(a.b())throw nv(\"empty.max\");return a.th(new fn((c,d)=>b.Jk(c,d)))}function Jq(a,b){return a.b()?R():new L(a.$i(b))}function gda(a,b,c){if(a.b())throw nv(\"empty.maxBy\");var d=new aw(null),e=new aw(null),g=new GA(!0);a.Ca(new y(h=>{var k=b.n(h);if(g.Am||c.Xj(k,d.rc))e.rc=h,d.rc=k,g.Am=!1}));return e.rc}function vca(a,b,c){return a.b()?R():new L(gda(a,b,c))}function ze(a,b,c,d){return a.b()?\"\"+b+d:a.Gh(ce(),b,c,d).yf.ja}\nfunction iH(a,b,c,d,e){var g=b.yf;0!==c.length&&(g.ja=\"\"+g.ja+c);a=a.m();if(a.s())for(c=a.t(),g.ja=\"\"+g.ja+c;a.s();)g.ja=\"\"+g.ja+d,c=a.t(),g.ja=\"\"+g.ja+c;0!==e.length&&(g.ja=\"\"+g.ja+e);return b}function kB(a,b){if(0<=a.Q())return b=b.si(a.Q()),a.Gc(b,0,2147483647),b;var c=b.uh(),d=c===da(td);b=[];for(a=a.m();a.s();){var e=a.t();b.push(d?Ea(e):null===e?c.qi.jz:e)}return md((c===da(pd)?da(la):c===da(jH)||c===da(kH)?da(jd):c).qi).iz(b)}\nfunction er(a){var b=u();for(a=a.m();a.s();){var c=a.t();b=new z(c,b)}return b}function lH(a,b){this.v5=a;this.AG=b}lH.prototype=new p;lH.prototype.constructor=lH;lH.prototype.$classData=q({u5:0},!1,\"scala.collection.Iterator$ConcatIteratorCell\",{u5:1,g:1});function Wq(a,b,c){this.iL=a;this.ck=b;this.dk=c}Wq.prototype=new p;Wq.prototype.constructor=Wq;function qD(a,b){return new mH(a.iL,a.ck,a.dk,b)}function Ew(a,b){b=new nH(a,b);return a.iL.Ub().Ib(b)}\nfunction Zq(a,b){b=new oH(a,b);return a.iL.Ub().Ib(b)}function pH(a,b){var c=a.ck.m();for(a=a.dk.m();c.s()&&a.s();)b.ba(c.t(),a.t())}function qH(a){var b=a.ck.Q();if(0===b)return 0;a=a.dk.Q();return 0===a?0:b<a?b:a}Wq.prototype.u=function(){return this.ck+\".lazyZip(\"+this.dk+\")\"};Wq.prototype.$classData=q({z5:0},!1,\"scala.collection.LazyZip2\",{z5:1,g:1});function mH(a,b,c,d){this.jL=b;this.kL=c;this.lL=d}mH.prototype=new p;mH.prototype.constructor=mH;\nfunction rH(a,b){var c=a.jL.m(),d=a.kL.m();for(a=a.lL.m();c.s()&&d.s()&&a.s();){var e=c.t(),g=d.t(),h=a.t();(0,b.aM)(e,g,h)}}mH.prototype.u=function(){return this.jL+\".lazyZip(\"+this.kL+\").lazyZip(\"+this.lL+\")\"};mH.prototype.$classData=q({G5:0},!1,\"scala.collection.LazyZip3\",{G5:1,g:1});function sH(){}sH.prototype=new p;sH.prototype.constructor=sH;\nfunction VF(a,b){var c=Cu(a.length);c.ja=\"\"+c.ja+a;a=c.ja;if(0>=a.length)throw b=new tH,yF(b,\"String index out of range: 0\",null,!0),b;c.ja=\"\"+a.substring(0,0)+hc(b)+a.substring(1);return c.ja}function uH(a,b,c){return 0<=vH(b,c)}function Of(a,b,c,d){a=0<c?c:0;c=b.length;d=d<c?d:c;return a>=d?\"\":b.substring(a,d)}function ut(a,b,c){if(0>=c)return\"\";a=Cu(Math.imul(b.length,c));for(var d=0;d<c;)a.ja=\"\"+a.ja+b,d=1+d|0;return a.ja}\nfunction Nu(a,b){null===b||0===b.length?a=!0:(a=b.charCodeAt(0),a=!bE(Pr(),a));if(a)return b;Q();a=b.charCodeAt(0);Pr();a=65535&hda(a);return VF(b,a)}function zf(a){return\"\\n\"===a.substring(a.length-1|0)?a.substring(0,a.length-1|0):a}function he(a){Q();var b=Cu(a.length);for(a=new wH(a,!1);a.cj<a.Jy;){for(var c=xH(a),d=c.length,e=0;;)if(e<d&&32>=c.charCodeAt(e))e=1+e|0;else break;c=e<d&&124===c.charCodeAt(e)?c.substring(1+e|0):c;b.ja=\"\"+b.ja+c}return b.ja}\nfunction ida(a,b){a=b.Ja(new y(c=>{Q();return c instanceof yH?c.qT():c})).Bj(TG());return jda(zH(),a)}function Hu(a,b){if(\"\"===b)throw AH(\"head of empty String\");return b.charCodeAt(0)}function Xz(a,b){return\"\"===b?R():new L(hc(b.charCodeAt(0)))}function Iu(a,b){if(\"\"===b)throw AH(\"last of empty String\");return b.charCodeAt(-1+b.length|0)}function ys(a,b,c){Q();a=b.length;return Of(0,b,c<a?c:a,b.length)}function $aa(a,b){Q();a=b.length-2|0;Q();var c=b.length;return Of(0,b,0,a<c?a:c)}\nfunction kda(a,b,c){a:{Q();a=b.length;for(var d=0;d<a;){if(c.n(hc(b.charCodeAt(d)))){b=d;break a}d=1+d|0}b=-1}return-1!==b}function gca(a,b){a:{for(var c=a.length,d=0;d<c;){var e=a.charCodeAt(d);if(!b.n(hc(e))){b=d;break a}d=1+d|0}b=-1}return-1===b?a:a.substring(0,b)}sH.prototype.$classData=q({k6:0},!1,\"scala.collection.StringOps$\",{k6:1,g:1});var BH;function Q(){BH||(BH=new sH);return BH}\nfunction CH(a,b,c,d){for(var e=1;;){if(e===c)return b?-2147483648===a?R():new L(-a|0):new L(a);if(-214748364>a)return R();var g=d.charCodeAt(e);g=DH(Pr(),g,10);if(-1===g||-214748364===a&&9===g)return R();e=1+e|0;a=Math.imul(10,a)-g|0}}function EH(){}EH.prototype=new p;EH.prototype.constructor=EH;function $D(a,b){a=b.length;if(0===a)return R();var c=b.charCodeAt(0),d=DH(Pr(),c,10);return 1===a?-1<d?new L(d):R():-1<d?CH(-d|0,!0,a,b):43===c?CH(0,!0,a,b):45===c?CH(0,!1,a,b):R()}\nEH.prototype.$classData=q({p6:0},!1,\"scala.collection.StringParsers$\",{p6:1,g:1});var FH;function aE(){FH||(FH=new EH);return FH}function GH(a,b){null===a.Ok&&(a.Ok=new Xc(HH().mC<<1),a.Do=new (md(IH).Ia)(HH().mC));a.vi=1+a.vi|0;var c=a.vi<<1,d=1+(a.vi<<1)|0;a.Do.a[a.vi]=b;a.Ok.a[c]=0;a.Ok.a[d]=b.HB()}function JH(a,b){a.Nc=0;a.wn=0;a.vi=-1;b.nB()&&GH(a,b);b.jy()&&(a.wh=b,a.Nc=0,a.wn=b.uy())}function KH(){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null}KH.prototype=new p;\nKH.prototype.constructor=KH;function LH(){}LH.prototype=KH.prototype;KH.prototype.s=function(){var a;if(!(a=this.Nc<this.wn))a:{for(;0<=this.vi;){a=this.vi<<1;var b=this.Ok.a[a];if(b<this.Ok.a[1+(this.vi<<1)|0]){var c=this.Ok;c.a[a]=1+c.a[a]|0;a=this.Do.a[this.vi].mB(b);a.nB()&&GH(this,a);if(a.jy()){this.wh=a;this.Nc=0;this.wn=a.uy();a=!0;break a}}else this.vi=-1+this.vi|0}a=!1}return a};function MH(a,b){a.Pk=1+a.Pk|0;a.Xv.a[a.Pk]=b;a.Wv.a[a.Pk]=-1+b.HB()|0}\nfunction NH(a){for(;0<=a.Pk;){var b=a.Wv.a[a.Pk];a.Wv.a[a.Pk]=-1+b|0;if(0<=b)b=a.Xv.a[a.Pk].mB(b),MH(a,b);else if(b=a.Xv.a[a.Pk],a.Pk=-1+a.Pk|0,b.jy())return a.Ut=b,a.gk=-1+b.uy()|0,!0}return!1}function OH(a,b){a.gk=-1;a.Pk=-1;a.Wv=new Xc(1+HH().mC|0);a.Xv=new (md(IH).Ia)(1+HH().mC|0);MH(a,b);NH(a)}function PH(){this.gk=0;this.Ut=null;this.Pk=0;this.Xv=this.Wv=null}PH.prototype=new p;PH.prototype.constructor=PH;function QH(){}QH.prototype=PH.prototype;\nPH.prototype.s=function(){return 0<=this.gk||NH(this)};function RH(){this.lS=0;SH=this;try{var a=fh(gh(),\"scala.collection.immutable.IndexedSeq.defaultApplyPreferredMaxLength\",\"64\");var b=TH(UH(),a,10)}catch(c){throw c;}this.lS=b}RH.prototype=new p;RH.prototype.constructor=RH;RH.prototype.$classData=q({f7:0},!1,\"scala.collection.immutable.IndexedSeqDefaults$\",{f7:1,g:1});var SH;function VH(){this.HL=null}VH.prototype=new p;VH.prototype.constructor=VH;\nfunction WH(a){a=a.HL;if(null===a)throw XH(\"uninitialized\");return Es(a)}function YH(a,b){if(null!==a.HL)throw XH(\"already initialized\");a.HL=b}VH.prototype.$classData=q({k7:0},!1,\"scala.collection.immutable.LazyList$LazyBuilder$DeferredState\",{k7:1,g:1});function ZH(){this.Ty=null;$H=this;this.Ty=new aI(0,0,(IB(),new zc(0)),(rl(),new Xc(0)),0,0)}ZH.prototype=new p;ZH.prototype.constructor=ZH;ZH.prototype.$classData=q({P7:0},!1,\"scala.collection.immutable.MapNode$\",{P7:1,g:1});var $H;\nfunction bI(){$H||($H=new ZH);return $H}function cI(a,b){var c=new dI;a=b+\" is out of bounds (min 0, max \"+(-1+wG(xG(),a)|0);yF(c,a,null,!0);return c}function eI(){}eI.prototype=new p;eI.prototype.constructor=eI;function fI(){}fI.prototype=eI.prototype;function gI(a,b){if(0>b)throw cI(a,b);if(b>(-1+a.a.length|0))throw cI(a,b);var c=new Xc(-1+a.a.length|0);a.wa(0,c,0,b);a.wa(1+b|0,c,b,-1+(a.a.length-b|0)|0);return c}\nfunction hI(a,b,c){if(0>b)throw cI(a,b);if(b>a.a.length)throw cI(a,b);var d=new Xc(1+a.a.length|0);a.wa(0,d,0,b);d.a[b]=c;a.wa(b,d,1+b|0,a.a.length-b|0);return d}var IH=q({lC:0},!1,\"scala.collection.immutable.Node\",{lC:1,g:1});eI.prototype.$classData=IH;function iI(){this.mC=0;jI=this;this.mC=Eb(+Math.ceil(6.4))}iI.prototype=new p;iI.prototype.constructor=iI;function kI(a,b,c){return 31&(b>>>c|0)}function lI(a,b){return 1<<b}function mI(a,b,c){a=b&(-1+c|0);return nI(UH(),a)}\nfunction oI(a,b,c,d){return-1===b?c:mI(0,b,d)}iI.prototype.$classData=q({V7:0},!1,\"scala.collection.immutable.Node$\",{V7:1,g:1});var jI;function HH(){jI||(jI=new iI);return jI}var mda=function lda(a,b,c){for(;;)if(null!==b.sa&&lda(a,b.sa,c),c.n(G(new H,b.Wa,b.Wb)),null!==b.ta)b=b.ta;else break},oda=function nda(a,b,c){for(;;)if(null!==b.sa&&nda(a,b.sa,c),c.n(b.Wa),null!==b.ta)b=b.ta;else break},qda=function pda(a,b,c){for(;;)if(null!==b.sa&&pda(a,b.sa,c),c.ba(b.Wa,b.Wb),null!==b.ta)b=b.ta;else break};\nfunction pI(a){return null===a?null:qI(a)}function rI(a,b,c,d,e){return new sI(b,c,d,e,1+((null===d?0:2147483647&d.ea)+(null===e?0:2147483647&e.ea)|0)|0|(a?-2147483648:0))}function tI(a,b){if(a.sa===b)return a;if(0<=b.ea){var c=b.sa,d=b.ta;return null!==c&&0<=c.ea?uI(b,qI(c),vI(a,d)):null!==d&&0<=d.ea?uI(d,wI(b,d.sa),vI(a,d.ta)):xI(a,b)}return xI(a,b)}\nfunction yI(a,b){if(a.ta===b)return a;if(0<=b.ea){var c=b.sa;if(null!==c&&0<=c.ea)return uI(c,wI(a,c.sa),vI(b,c.ta));var d=b.ta;return null!==d&&0<=d.ea?uI(b,wI(a,c),qI(d)):zI(a,b)}return zI(a,b)}\nvar rda=function AI(a,b,c,d,e,g){if(null===b)return BI(c,d,null,null);if(Object.is(c,b.Wa))return e?CI(b,d):b;var k=g.Da(c,b.Wa);return 0>k?tI(b,AI(a,b.sa,c,d,e,g)):0<k?yI(b,AI(a,b.ta,c,d,e,g)):e&&!Object.is(d,b.Wb)?CI(b,d):b},sda=function DI(a,b,c,d,e){if(null===b)return BI(d,e,null,null);var h=1+EI(0,b.sa)|0;return c<h?tI(b,DI(a,b.sa,c,d,e)):c>h?yI(b,DI(a,b.ta,c-h|0,d,e)):b},GI=function tda(a,b,c){for(;;){if(null===b||0>=c)return b;if(c>=(2147483647&b.ea))return null;var e=EI(0,b.sa);if(c>e)c=-1+\n(c-e|0)|0,b=b.ta;else{if(c===e)return FI(a,null,b.Wa,b.Wb,b.ta);c=tda(a,b.sa,c);return FI(a,c,b.Wa,b.Wb,b.ta)}}},HI=function uda(a,b,c){for(;;){if(null===b||0>=c)return null;if(c>=(2147483647&b.ea))return b;var e=EI(0,b.sa);if(c<=e)b=b.sa;else return c===(1+e|0)?(a=sda(a,b.sa,c,b.Wa,b.Wb),null===a||0>a.ea||(b=a.sa,null!==b&&0<=b.ea?b=!0:(b=a.ta,b=null!==b&&0<=b.ea),a=b?qI(a):a)):a=FI(a,b.sa,b.Wa,b.Wb,uda(a,b.ta,-1+(c-e|0)|0)),a}},PI=function II(a,b,c,d){if(null===b)return null;var g=d.Da(c,b.Wa);\nif(0>g){a=II(a,b.sa,c,d);if(a===b.sa)return b;c=b.sa;null!==c&&0>c.ea?b=JI(b,a,b.ta):a===b.sa&&0<=b.ea||(c=b.ta,b=new sI(b.Wa,b.Wb,a,b.ta,1+((null===a?0:2147483647&a.ea)+(null===c?0:2147483647&c.ea)|0)|0));return b}if(0<g){a=II(a,b.ta,c,d);if(a===b.ta)return b;c=b.ta;null!==c&&0>c.ea?(c=b.sa,null!==a&&0<=a.ea?b=KI(b,c,qI(a)):null!==c&&0>c.ea?b=LI(b,MI(c),a):(null!==c&&0<=c.ea?(d=c.ta,d=null!==d&&0>d.ea):d=!1,d?b=KI(c.ta,LI(c,MI(c.sa),c.ta.sa),NI(b,c.ta.ta,a)):(OI(),b=void 0))):a===b.ta&&0<=b.ea||\n(c=b.sa,b=new sI(b.Wa,b.Wb,b.sa,a,1+((null===c?0:2147483647&c.ea)+(null===a?0:2147483647&a.ea)|0)|0));return b}return vda(a,b.sa,b.ta)};\nfunction LI(a,b,c){if(null!==b&&0<=b.ea){if(null!==c&&0<=c.ea)return KI(a,qI(b),qI(c));var d=b.sa;if(null!==d&&0<=d.ea)return uI(b,qI(b.sa),NI(a,b.ta,c));d=b.ta;return null!==d&&0<=d.ea?uI(b.ta,wI(b,b.ta.sa),NI(a,b.ta.ta,c)):NI(a,b,c)}if(null!==c&&0<=c.ea){d=c.ta;if(null!==d&&0<=d.ea)return uI(c,NI(a,b,c.sa),qI(c.ta));d=c.sa;return null!==d&&0<=d.ea?uI(c.sa,NI(a,b,c.sa.sa),NI(c,c.sa.ta,c.ta)):NI(a,b,c)}return NI(a,b,c)}\nfunction JI(a,b,c){if(null!==b&&0<=b.ea)return KI(a,qI(b),c);if(null!==c&&0>c.ea)return LI(a,b,MI(c));if(null!==c&&0<=c.ea){var d=c.sa;d=null!==d&&0>d.ea}else d=!1;if(d)return KI(c.sa,NI(a,b,c.sa.sa),LI(c,c.sa.ta,MI(c.ta)));OI()}\nvar vda=function QI(a,b,c){return null===b?c:null===c?b:0<=b.ea?0<=c.ea?(a=QI(a,b.ta,c.sa),null!==a&&0<=a.ea?uI(a,zI(b,a.sa),xI(c,a.ta)):zI(b,xI(c,a))):zI(b,QI(a,b.ta,c)):0>c.ea?(a=QI(a,b.ta,c.sa),null!==a&&0<=a.ea?uI(a,zI(b,a.sa),xI(c,a.ta)):JI(b,b.sa,xI(c,a))):xI(c,QI(a,b,c.sa))},xda=function wda(a,b,c,d,e,g,h){if((null===b?0:0>b.ea?(-1+g|0)<<1:-1+(g<<1)|0)===(h/2|0)<<1)return BI(c,d,b,e);var l=null!==b&&0>b.ea;a=wda(a,b.ta,c,d,e,l?-1+g|0:g,h);l&&null!==a&&0<=a.ea?(c=a.ta,c=null!==c&&0<=c.ea):c=\n!1;return c?BI(a.Wa,a.Wb,RI(b.Wa,b.Wb,b.sa,a.sa),qI(a.ta)):rI(l,b.Wa,b.Wb,b.sa,a)},zda=function yda(a,b,c,d,e,g,h){if((null===e?0:0>e.ea?(-1+h|0)<<1:-1+(h<<1)|0)===(g/2|0)<<1)return BI(c,d,b,e);var l=null!==e&&0>e.ea;a=yda(a,b,c,d,e.sa,g,l?-1+h|0:h);l&&null!==a&&0<=a.ea?(b=a.sa,b=null!==b&&0<=b.ea):b=!1;return b?BI(a.Wa,a.Wb,qI(a.sa),RI(e.Wa,e.Wb,a.ta,e.ta)):rI(l,e.Wa,e.Wb,a,e.ta)},TI=function SI(a,b,c,d){if(null===b)return new Gp(null,null,null,c);var g=d.Da(c,b.Wa);if(0===g)return new Gp(b.sa,b,\nb.ta,b.Wa);if(0>g){c=SI(a,b.sa,c,d);if(null===c)throw new w(c);d=c.Xi;return new Gp(c.Uj,c.oj,FI(a,c.oi,b.Wa,b.Wb,b.ta),d)}c=SI(a,b.ta,c,d);if(null===c)throw new w(c);d=c.oj;g=c.oi;var h=c.Xi;return new Gp(FI(a,b.sa,b.Wa,b.Wb,c.Uj),d,g,h)},Bda=function Ada(a,b){if(null===b.ta)return new tl(b.sa,b.Wa,b.Wb);var d=Ada(a,b.ta);if(null===d)throw new w(d);var e=d.hb,g=d.Rd;return new tl(FI(a,b.sa,b.Wa,b.Wb,d.kc),e,g)},Cda=function UI(a,b,c,d){if(null===b||b===c)return c;if(null===c)return b;var g=TI(a,\nb,c.Wa,d);if(null===g)throw new w(g);var h=g.oi;b=g.Xi;g=UI(a,g.Uj,c.sa,d);d=UI(a,h,c.ta,d);return FI(a,g,b,c.Wb,d)},XI=function VI(a,b,c,d){if(null===b||null===c)return b;if(b===c)return null;var g=TI(a,b,c.Wa,d);if(null===g)throw new w(g);b=g.oi;g=VI(a,g.Uj,c.sa,d);c=VI(a,b,c.ta,d);return WI(a,g,c)},Dda=function YI(a,b,c,d,e){switch(c){case 0:return null;case 1:return rI(b!==d||1===b,e.t(),null,null,null);default:var h=(-1+c|0)/2|0,k=YI(a,1+b|0,h,d,e),l=e.t();a=YI(a,1+b|0,(-1+c|0)-h|0,d,e);return RI(l,\nnull,k,a)}},Eda=function ZI(a,b,c,d,e){switch(c){case 0:return null;case 1:var h=d.t();if(null===h)throw new w(h);return rI(b!==e||1===b,h.h(),h.j(),null,null);default:var k=(-1+c|0)/2|0;h=ZI(a,1+b|0,k,d,e);var l=d.t();if(null===l)throw new w(l);var m=l.h();l=l.j();b=ZI(a,1+b|0,(-1+c|0)-k|0,d,e);return RI(m,l,h,b)}},Fda=function $I(a,b,c){var e=b.Wa,g=b.Wb,h=b.sa,k=b.ta,l=null===h?null:$I(a,h,c),m=!!c.ba(e,g);c=null===k?null:$I(a,k,c);return m?l===h&&c===k?b:FI(a,l,e,g,c):WI(a,l,c)};\nfunction aJ(a,b){if(null===a)throw le();return a.sb?a.vb:me(a,new bJ(b))}function cJ(a){for(var b=0;;){if(null===a)return 1+b|0;b=0>a.ea?1+b|0:b;a=a.sa}}function dJ(){this.AS=null;eJ=this;this.AS=G(new H,null,null)}dJ.prototype=new p;dJ.prototype.constructor=dJ;function fJ(a,b,c,d){for(;;){if(null===b)return null;a=d.Da(c,b.Wa);if(0>a)b=b.sa;else if(0<a)b=b.ta;else return b}}function EI(a,b){return null===b?0:2147483647&b.ea}function gJ(a,b,c,d,e,g){return pI(rda(a,b,c,d,e,g))}\nfunction hJ(a,b){if(null===b)throw AH(\"empty tree\");for(a=b;;)if(null!==a.sa)a=a.sa;else break;return a}function iJ(a,b){if(null===b)throw AH(\"empty tree\");for(a=b;;)if(null!==a.ta)a=a.ta;else break;return a}function BI(a,b,c,d){return new sI(a,b,c,d,1+((null===c?0:2147483647&c.ea)+(null===d?0:2147483647&d.ea)|0)|0)}function RI(a,b,c,d){return new sI(a,b,c,d,1+((null===c?0:2147483647&c.ea)+(null===d?0:2147483647&d.ea)|0)|-2147483648)}\nfunction jJ(a,b,c){var d=32-Math.clz32(c)|0;return Dda(a,1,c,d,b)}function kJ(a,b,c){return null===b?null:pI(Fda(a,b,c))}function Gda(a,b,c){if(null===b)return G(new H,null,null);if(null===b)return a.AS;a=new $e;lJ(a.sb?a.vb:aJ(a,c),b);return G(new H,pI((a.sb?a.vb:aJ(a,c)).$G),pI((a.sb?a.vb:aJ(a,c)).ZG))}function mJ(a,b,c,d){return pI(Cda(a,b,c,d))}\nfunction FI(a,b,c,d,e){var g=cJ(b),h=cJ(e);return g>h?(a=xda(a,b,c,d,e,g,null===e?0:0>e.ea?(-1+h|0)<<1:-1+(h<<1)|0),null!==a&&0<=a.ea?(b=a.ta,b=null!==b&&0<=b.ea):b=!1,b?qI(a):a):h>g?(a=zda(a,b,c,d,e,null===b?0:0>b.ea?(-1+g|0)<<1:-1+(g<<1)|0,h),null!==a&&0<=a.ea?(b=a.sa,b=null!==b&&0<=b.ea):b=!1,b?qI(a):a):rI(null!==b&&0<=b.ea||null!==e&&0<=e.ea,c,d,b,e)}function WI(a,b,c){if(null===b)return c;if(null===c)return b;b=Bda(a,b);if(null===b)throw new w(b);return FI(a,b.kc,b.hb,b.Rd,c)}\ndJ.prototype.$classData=q({a8:0},!1,\"scala.collection.immutable.RedBlackTree$\",{a8:1,g:1});var eJ;function nJ(){eJ||(eJ=new dJ);return eJ}function oJ(){this.Uk=null}oJ.prototype=new p;oJ.prototype.constructor=oJ;function pJ(){}pJ.prototype=oJ.prototype;function qJ(a){return null===a?a:0===(2147483647&a.ea)?rJ(sJ(a)):qI(a)}\nfunction tJ(a,b){if(0<=b.ea){var c=b.sa,d=b.ta;if(nJ(),null!==c&&0<=c.ea)return c=sJ(c),d=uJ(a,d),vJ(b,c,d);if(nJ(),null!==d&&0<=d.ea)return c=d.ta,b=wJ(b,d.sa),a=uJ(a,c),vJ(d,b,a)}a.sa===b?d=a:0===(2147483647&a.ea)?(a.sa=b,d=a):d=new sI(a.Wa,a.Wb,b,a.ta,-2147483648&a.ea);return d}\nfunction xJ(a,b){if(0<=b.ea){var c=b.sa;if(nJ(),null!==c&&0<=c.ea){var d=wJ(a,c.sa);b=uJ(b,c.ta);return vJ(c,d,b)}d=b.ta;if(nJ(),null!==d&&0<=d.ea)return c=wJ(a,c),d=sJ(d),vJ(b,c,d)}a.ta===b?b=a:0===(2147483647&a.ea)?(a.ta=b,b=a):b=new sI(a.Wa,a.Wb,a.sa,b,-2147483648&a.ea);return b}function sI(a,b,c,d,e){this.Wa=a;this.Wb=b;this.sa=c;this.ta=d;this.ea=e}sI.prototype=new p;sI.prototype.constructor=sI;\nsI.prototype.u=function(){return(0<=this.ea?\"RedTree\":\"BlackTree\")+\"(\"+this.Wa+\", \"+this.Wb+\", \"+this.sa+\", \"+this.ta+\")\"};function rJ(a){if(0===(2147483647&a.ea)){var b=1;null!==a.sa&&(rJ(a.sa),b=b+(2147483647&a.sa.ea)|0);null!==a.ta&&(rJ(a.ta),b=b+(2147483647&a.ta.ea)|0);a.ea|=b}return a}function sJ(a){return 0>a.ea?a:0===(2147483647&a.ea)?(a.ea=-2147483648,a):new sI(a.Wa,a.Wb,a.sa,a.ta,-2147483648)}\nfunction yJ(a,b){return Object.is(b,a.Wb)?a:0===(2147483647&a.ea)?(a.Wb=b,a):new sI(a.Wa,b,a.sa,a.ta,-2147483648&a.ea)}function vJ(a,b,c){return a.sa===b&&a.ta===c?a:0===(2147483647&a.ea)?(a.sa=b,a.ta=c,a):new sI(a.Wa,a.Wb,b,c,-2147483648&a.ea)}function uJ(a,b){return a.sa===b&&0>a.ea?a:0===(2147483647&a.ea)?(a.ea=-2147483648,a.sa=b,a):new sI(a.Wa,a.Wb,b,a.ta,-2147483648)}\nfunction wJ(a,b){return a.ta===b&&0>a.ea?a:0===(2147483647&a.ea)?(a.ea=-2147483648,a.ta=b,a):new sI(a.Wa,a.Wb,a.sa,b,-2147483648)}function qI(a){return 0>a.ea?a:new sI(a.Wa,a.Wb,a.sa,a.ta,-2147483648^a.ea)}function MI(a){return 0<=a.ea?a:new sI(a.Wa,a.Wb,a.sa,a.ta,-2147483648^a.ea)}function CI(a,b){return Object.is(b,a.Wb)?a:new sI(a.Wa,b,a.sa,a.ta,a.ea)}\nfunction xI(a,b){if(b===a.sa)return a;var c=a.ta;return new sI(a.Wa,a.Wb,b,a.ta,-2147483648&a.ea|1+((null===b?0:2147483647&b.ea)+(null===c?0:2147483647&c.ea)|0)|0)}function zI(a,b){if(b===a.ta)return a;var c=a.sa;return new sI(a.Wa,a.Wb,a.sa,b,-2147483648&a.ea|1+((null===c?0:2147483647&c.ea)+(null===b?0:2147483647&b.ea)|0)|0)}function vI(a,b){if(b===a.sa&&0>a.ea)return a;var c=a.ta;return new sI(a.Wa,a.Wb,b,a.ta,1+((null===b?0:2147483647&b.ea)+(null===c?0:2147483647&c.ea)|0)|-2147483648)}\nfunction wI(a,b){if(b===a.ta&&0>a.ea)return a;var c=a.sa;return new sI(a.Wa,a.Wb,a.sa,b,1+((null===c?0:2147483647&c.ea)+(null===b?0:2147483647&b.ea)|0)|-2147483648)}function uI(a,b,c){return b===a.sa&&c===a.ta?a:new sI(a.Wa,a.Wb,b,c,-2147483648&a.ea|1+((null===b?0:2147483647&b.ea)+(null===c?0:2147483647&c.ea)|0)|0)}function KI(a,b,c){return b===a.sa&&c===a.ta&&0<=a.ea?a:new sI(a.Wa,a.Wb,b,c,1+((null===b?0:2147483647&b.ea)+(null===c?0:2147483647&c.ea)|0)|0)}\nfunction NI(a,b,c){return b===a.sa&&c===a.ta&&0>a.ea?a:new sI(a.Wa,a.Wb,b,c,1+((null===b?0:2147483647&b.ea)+(null===c?0:2147483647&c.ea)|0)|-2147483648)}var zJ=q({f8:0},!1,\"scala.collection.immutable.RedBlackTree$Tree\",{f8:1,g:1});sI.prototype.$classData=zJ;function bJ(a){this.h8=a;this.ZG=this.$G=null}bJ.prototype=new p;bJ.prototype.constructor=bJ;\nfunction lJ(a,b){var c=b.Wa,d=b.Wb,e=b.sa,g=b.ta,h=null,k=null,l=null,m=null;null!==e&&(lJ(a,e),h=a.$G,k=a.ZG);var n=!!a.h8.ba(c,d);null!==g&&(lJ(a,g),l=a.$G,m=a.ZG);h=n?h===e&&l===g?b:FI(nJ(),h,c,d,l):WI(nJ(),h,l);b=n?WI(nJ(),k,m):k===e&&m===g?b:FI(nJ(),k,c,d,m);a.$G=h;a.ZG=b}bJ.prototype.$classData=q({g8:0},!1,\"scala.collection.immutable.RedBlackTree$partitioner$1$\",{g8:1,g:1});function AJ(){this.mw=null;BJ=this;this.mw=new CJ(0,0,(IB(),new zc(0)),(rl(),new Xc(0)),0,0)}AJ.prototype=new p;\nAJ.prototype.constructor=AJ;AJ.prototype.$classData=q({w8:0},!1,\"scala.collection.immutable.SetNode$\",{w8:1,g:1});var BJ;function DJ(){BJ||(BJ=new AJ);return BJ}\nvar Ida=function Hda(a,b,c,d,e){for(;;){if(1===b){b=c;var h=d,k=e;EJ(a,1,0===h&&k===b.a.length?b:Jj(Pj(),b,h,k))}else{h=Math.imul(5,-1+b|0);var l=1<<h;k=d>>>h|0;h=e>>>h|0;d&=-1+l|0;e&=-1+l|0;if(0===d)if(0===e)e=c,EJ(a,b,0===k&&h===e.a.length?e:Jj(Pj(),e,k,h));else{h>k&&(d=c,EJ(a,b,0===k&&h===d.a.length?d:Jj(Pj(),d,k,h)));h=c.a[h];b=-1+b|0;c=h;d=0;continue}else if(h===k){h=c.a[k];b=-1+b|0;c=h;continue}else if(Hda(a,-1+b|0,c.a[k],d,l),0===e)h>(1+k|0)&&(e=c,k=1+k|0,EJ(a,b,0===k&&h===e.a.length?e:Jj(Pj(),\ne,k,h)));else{h>(1+k|0)&&(d=c,k=1+k|0,EJ(a,b,0===k&&h===d.a.length?d:Jj(Pj(),d,k,h)));h=c.a[h];b=-1+b|0;c=h;d=0;continue}}break}};function EJ(a,b,c){b<=a.Vk?b=11-b|0:(a.Vk=b,b=-1+b|0);a.lb.a[b]=c}\nvar Kda=function Jda(a,b){if(null===a.lb.a[-1+b|0])if(b===a.Vk)a.lb.a[-1+b|0]=a.lb.a[11-b|0],a.lb.a[11-b|0]=null;else{Jda(a,1+b|0);var d=a.lb.a[-1+(1+b|0)|0];a.lb.a[-1+b|0]=d.a[0];if(1===d.a.length)a.lb.a[-1+(1+b|0)|0]=null,a.Vk===(1+b|0)&&null===a.lb.a[11-(1+b|0)|0]&&(a.Vk=b);else{var e=d.a.length;a.lb.a[-1+(1+b|0)|0]=Jj(Pj(),d,1,e)}}},Mda=function Lda(a,b){if(null===a.lb.a[11-b|0])if(b===a.Vk)a.lb.a[11-b|0]=a.lb.a[-1+b|0],a.lb.a[-1+b|0]=null;else{Lda(a,1+b|0);var d=a.lb.a[11-(1+b|0)|0];a.lb.a[11-\nb|0]=d.a[-1+d.a.length|0];if(1===d.a.length)a.lb.a[11-(1+b|0)|0]=null,a.Vk===(1+b|0)&&null===a.lb.a[-1+(1+b|0)|0]&&(a.Vk=b);else{var e=-1+d.a.length|0;a.lb.a[11-(1+b|0)|0]=Jj(Pj(),d,0,e)}}};function FJ(a,b){this.lb=null;this.Vk=this.az=this.Ko=0;this.KS=a;this.JS=b;this.lb=new (md(md(jd)).Ia)(11);this.Vk=this.az=this.Ko=0}FJ.prototype=new p;FJ.prototype.constructor=FJ;\nfunction GJ(a,b,c){var d=Math.imul(c.a.length,1<<Math.imul(5,-1+b|0)),e=a.KS-a.az|0;e=0<e?e:0;var g=a.JS-a.az|0;g=g<d?g:d;g>e&&(Ida(a,b,c,e,g),a.Ko=a.Ko+(g-e|0)|0);a.az=a.az+d|0}\nFJ.prototype.im=function(){if(32>=this.Ko){if(0===this.Ko)return HJ();var a=this.lb.a[0],b=this.lb.a[10];if(null!==a)if(null!==b){var c=a.a.length+b.a.length|0,d=zj(Pj(),a,c);b.wa(0,d,a.a.length,b.a.length);var e=d}else e=a;else if(null!==b)e=b;else{var g=this.lb.a[1];e=null!==g?g.a[0]:this.lb.a[9].a[0]}return new IJ(e)}Kda(this,1);Mda(this,1);var h=this.Vk;if(6>h){var k=this.lb.a[-1+this.Vk|0],l=this.lb.a[11-this.Vk|0];if(null!==k&&null!==l)if(30>=(k.a.length+l.a.length|0)){var m=this.lb,n=this.Vk,\nr=k.a.length+l.a.length|0,v=zj(Pj(),k,r);l.wa(0,v,k.a.length,l.a.length);m.a[-1+n|0]=v;this.lb.a[11-this.Vk|0]=null}else h=1+h|0;else 30<(null!==k?k:l).a.length&&(h=1+h|0)}var x=this.lb.a[0],A=this.lb.a[10],B=x.a.length,C=h;switch(C){case 2:var D=JJ().bd,F=this.lb.a[1];if(null!==F)var I=F;else{var M=this.lb.a[9];I=null!==M?M:D}var N=new KJ(x,B,I,A,this.Ko);break;case 3:var P=JJ().bd,T=this.lb.a[1],Y=null!==T?T:P,Z=JJ().eg,S=this.lb.a[2];if(null!==S)var ea=S;else{var ia=this.lb.a[8];ea=null!==ia?ia:\nZ}var X=ea,sa=JJ().bd,Ja=this.lb.a[9];N=new LJ(x,B,Y,B+(Y.a.length<<5)|0,X,null!==Ja?Ja:sa,A,this.Ko);break;case 4:var Xa=JJ().bd,Fa=this.lb.a[1],za=null!==Fa?Fa:Xa,Qa=JJ().eg,Ma=this.lb.a[2],Ga=null!==Ma?Ma:Qa,ab=JJ().jk,Hb=this.lb.a[3];if(null!==Hb)var bc=Hb;else{var yb=this.lb.a[7];bc=null!==yb?yb:ab}var tb=bc,eb=JJ().eg,kb=this.lb.a[8],Rb=null!==kb?kb:eb,Gb=JJ().bd,vb=this.lb.a[9],Tb=B+(za.a.length<<5)|0;N=new MJ(x,B,za,Tb,Ga,Tb+(Ga.a.length<<10)|0,tb,Rb,null!==vb?vb:Gb,A,this.Ko);break;case 5:var Nb=\nJJ().bd,ic=this.lb.a[1],Va=null!==ic?ic:Nb,cb=JJ().eg,zb=this.lb.a[2],Ub=null!==zb?zb:cb,jb=JJ().jk,db=this.lb.a[3],ub=null!==db?db:jb,Aa=JJ().du,va=this.lb.a[4];if(null!==va)var Ra=va;else{var rb=this.lb.a[6];Ra=null!==rb?rb:Aa}var xb=Ra,mc=JJ().jk,Ha=this.lb.a[7],Ka=null!==Ha?Ha:mc,Oa=JJ().eg,Na=this.lb.a[8],Da=null!==Na?Na:Oa,ta=JJ().bd,Ya=this.lb.a[9],dc=B+(Va.a.length<<5)|0,ka=dc+(Ub.a.length<<10)|0;N=new NJ(x,B,Va,dc,Ub,ka,ub,ka+(ub.a.length<<15)|0,xb,Ka,Da,null!==Ya?Ya:ta,A,this.Ko);break;\ncase 6:var ya=JJ().bd,Sa=this.lb.a[1],xc=null!==Sa?Sa:ya,Sb=JJ().eg,uc=this.lb.a[2],Lb=null!==uc?uc:Sb,lc=JJ().jk,Xb=this.lb.a[3],ec=null!==Xb?Xb:lc,Ab=JJ().du,Ob=this.lb.a[4],fb=null!==Ob?Ob:Ab,Wa=JJ().dH,bb=this.lb.a[5];if(null!==bb)var Ia=bb;else{var Ua=this.lb.a[5];Ia=null!==Ua?Ua:Wa}var pc=Ia,sc=JJ().du,Ba=this.lb.a[6],ob=null!==Ba?Ba:sc,nc=JJ().jk,Ib=this.lb.a[7],vc=null!==Ib?Ib:nc,Vb=JJ().eg,fc=this.lb.a[8],Bc=null!==fc?fc:Vb,Pb=JJ().bd,Jb=this.lb.a[9],gc=B+(xc.a.length<<5)|0,Cb=gc+(Lb.a.length<<\n10)|0,cc=Cb+(ec.a.length<<15)|0;N=new OJ(x,B,xc,gc,Lb,Cb,ec,cc,fb,cc+(fb.a.length<<20)|0,pc,ob,vc,Bc,null!==Jb?Jb:Pb,A,this.Ko);break;default:throw new w(C);}return N};FJ.prototype.u=function(){return\"VectorSliceBuilder(lo\\x3d\"+this.KS+\", hi\\x3d\"+this.JS+\", len\\x3d\"+this.Ko+\", pos\\x3d\"+this.az+\", maxDim\\x3d\"+this.Vk+\")\"};FJ.prototype.$classData=q({Y8:0},!1,\"scala.collection.immutable.VectorSliceBuilder\",{Y8:1,g:1});\nfunction PJ(){this.dH=this.du=this.jk=this.eg=this.bd=this.PL=null;QJ=this;this.PL=new zc(0);this.bd=new (md(md(jd)).Ia)(0);this.eg=new (md(md(md(jd))).Ia)(0);this.jk=new (md(md(md(md(jd)))).Ia)(0);this.du=new (md(md(md(md(md(jd))))).Ia)(0);this.dH=new (md(md(md(md(md(md(jd)))))).Ia)(0)}PJ.prototype=new p;PJ.prototype.constructor=PJ;function RJ(a,b,c){a=b.a.length;var d=new zc(1+a|0);b.wa(0,d,0,a);d.a[a]=c;return d}\nfunction SJ(a,b,c){a=1+b.a.length|0;b=zj(Pj(),b,a);b.a[-1+b.a.length|0]=c;return b}function TJ(a,b,c){a=new zc(1+c.a.length|0);c.wa(0,a,1,c.a.length);a.a[0]=b;return a}function UJ(a,b,c){a=bg(ca(c));var d=1+c.a.length|0;a=rh(th(),a,d);c.wa(0,a,1,c.a.length);a.a[0]=b;return a}function VJ(a,b,c,d){var e=0,g=c.a.length;if(0===b)for(;e<g;)d.n(c.a[e]),e=1+e|0;else for(b=-1+b|0;e<g;)VJ(a,b,c.a[e],d),e=1+e|0}\nfunction WJ(a,b,c){for(var d=0;d<b.a.length;){var e=b.a[d];a=c.n(e);if(!Object.is(e,a)){e=a;a=new zc(b.a.length);0<d&&b.wa(0,a,0,d);a.a[d]=e;for(d=1+d|0;d<b.a.length;)a.a[d]=c.n(b.a[d]),d=1+d|0;return a}d=1+d|0}return b}function XJ(a,b,c,d){if(1===b)return WJ(0,c,d);for(var e=0;e<c.a.length;){var g=c.a[e],h=XJ(a,-1+b|0,g,d);if(g!==h){g=bg(ca(c));var k=c.a.length;g=rh(th(),g,k);0<e&&c.wa(0,g,0,e);g.a[e]=h;for(h=1+e|0;h<c.a.length;)g.a[h]=XJ(a,-1+b|0,c.a[h],d),h=1+h|0;return g}e=1+e|0}return c}\nfunction YJ(a,b,c){if(ZJ(c))if(0>=c.$k(32-b.a.length|0))switch(a=c.ka(),a){case 0:return null;case 1:return SJ(0,b,c.e());default:return a=b.a.length+a|0,a=zj(Pj(),b,a),c.Gc(a,b.a.length,2147483647),a}else return null;else return a=c.Q(),0<a&&a<=(32-b.a.length|0)?(a=b.a.length+a|0,a=zj(Pj(),b,a),c.m().Gc(a,b.a.length,2147483647),a):null}PJ.prototype.$classData=q({Z8:0},!1,\"scala.collection.immutable.VectorStatics$\",{Z8:1,g:1});var QJ;function JJ(){QJ||(QJ=new PJ);return QJ}\nvar $J=q({VL:0},!0,\"scala.collection.mutable.HashEntry\",{VL:1,g:1});function aK(a,b,c,d){this.Wk=a;this.mk=b;this.Ah=c;this.$d=d}aK.prototype=new p;aK.prototype.constructor=aK;function Ny(a,b,c){for(;;){if(c===a.mk&&ml(nl(),b,a.Wk))return a;if(null===a.$d||a.mk>c)return null;a=a.$d}}aK.prototype.Ca=function(a){for(var b=this;;)if(a.n(G(new H,b.Wk,b.Ah)),null!==b.$d)b=b.$d;else break};aK.prototype.og=function(a){for(var b=this;;)if(a.ba(b.Wk,b.Ah),null!==b.$d)b=b.$d;else break};\naK.prototype.u=function(){return\"Node(\"+this.Wk+\", \"+this.Ah+\", \"+this.mk+\") -\\x3e \"+this.$d};var bK=q({M9:0},!1,\"scala.collection.mutable.HashMap$Node\",{M9:1,g:1});aK.prototype.$classData=bK;function cK(a,b,c){this.xm=a;this.nk=b;this.yg=c}cK.prototype=new p;cK.prototype.constructor=cK;cK.prototype.Ca=function(a){for(var b=this;;)if(a.n(b.xm),null!==b.yg)b=b.yg;else break};cK.prototype.u=function(){return\"Node(\"+this.xm+\", \"+this.nk+\") -\\x3e \"+this.yg};\nvar dK=q({T9:0},!1,\"scala.collection.mutable.HashSet$Node\",{T9:1,g:1});cK.prototype.$classData=dK;function eK(){}eK.prototype=new p;eK.prototype.constructor=eK;function fK(a,b,c){a=c>>31;var d=b>>31,e=65535&c,g=c>>>16|0,h=65535&b,k=b>>>16|0,l=Math.imul(e,h);h=Math.imul(g,h);var m=Math.imul(e,k);e=l+((h+m|0)<<16)|0;l=(l>>>16|0)+m|0;b=(((Math.imul(c,d)+Math.imul(a,b)|0)+Math.imul(g,k)|0)+(l>>>16|0)|0)+(((65535&l)+h|0)>>>16|0)|0;return $h(xa(),e,b,1E3,0)}\neK.prototype.$classData=q({V9:0},!1,\"scala.collection.mutable.HashTable$\",{V9:1,g:1});var gK;function hK(){gK||(gK=new eK);return gK}function iK(){}iK.prototype=new p;iK.prototype.constructor=iK;function jK(a,b){if(b!==a)throw new kK;}iK.prototype.$classData=q({o$:0},!1,\"scala.collection.mutable.MutationTracker$\",{o$:1,g:1});var lK;function mK(){lK||(lK=new iK)}function nK(a,b,c){for(;;){if(null===a)return null;var d=c.Da(b,a.Oo);if(0>d)a=a.Vc;else if(0<d)a=a.Bc;else return a}}\nfunction oK(a,b){if(null!==b){var c=b.Bc;b.Bc=c.Vc;null!==c.Vc&&(c.Vc.bb=b);c.bb=b.bb;null===b.bb?a.zi=c:b===b.bb.Vc?b.bb.Vc=c:b.bb.Bc=c;c.Vc=b;b.bb=c}}function pK(a,b){if(null!==b){var c=b.Vc;b.Vc=c.Bc;null!==c.Bc&&(c.Bc.bb=b);c.bb=b.bb;null===b.bb?a.zi=c:b===b.bb.Bc?b.bb.Bc=c:b.bb.Vc=c;c.Bc=b;b.bb=c}}function qK(a,b,c){null===b.bb?a.zi=c:b===b.bb.Vc?b.bb.Vc=c:b.bb.Bc=c;null!==c&&(c.bb=b.bb)}\nvar Oda=function Nda(a,b,c){for(;;)if(null!==b.Vc&&Nda(a,b.Vc,c),c.n(G(new H,b.Oo,b.Vr)),null!==b.Bc)b=b.Bc;else break},Qda=function Pda(a,b,c){for(;;){var e=b.Vc;null!==e&&Pda(a,e,c);c.ba(b.Oo,b.Vr);b=b.Bc;if(null===b)break}};function rK(){}rK.prototype=new p;rK.prototype.constructor=rK;function sK(a){return null!==a&&a.Wc}function tK(a){return null===a||!a.Wc}function uK(a){for(;;){if(null===a.Vc)return a;a=a.Vc}}\nfunction vK(a,b){if(null!==b.Bc)return uK(b.Bc);a=b;for(b=a.bb;null!==b&&a===b.Bc;)a=b,b=b.bb;return b}rK.prototype.$classData=q({t$:0},!1,\"scala.collection.mutable.RedBlackTree$\",{t$:1,g:1});var wK;function xK(){wK||(wK=new rK);return wK}function yK(a,b,c,d,e,g){this.Oo=a;this.Vr=b;this.Wc=c;this.Vc=d;this.Bc=e;this.bb=g}yK.prototype=new p;yK.prototype.constructor=yK;yK.prototype.u=function(){return\"Node(\"+this.Oo+\", \"+this.Vr+\", \"+this.Wc+\", \"+this.Vc+\", \"+this.Bc+\")\"};\nyK.prototype.$classData=q({w$:0},!1,\"scala.collection.mutable.RedBlackTree$Node\",{w$:1,g:1});function zK(a,b){this.zi=a;this.gz=b}zK.prototype=new p;zK.prototype.constructor=zK;zK.prototype.$classData=q({x$:0},!1,\"scala.collection.mutable.RedBlackTree$Tree\",{x$:1,g:1});\nfunction AK(a,b){if(b instanceof ba)return b=Ea(b),a.XJ()&&a.Zi()===b;if(Zb(b))return b|=0,a.WJ()&&a.jB()===b;if($b(b))return b|=0,a.YJ()&&a.EC()===b;if(ha(b))return b|=0,a.MF()&&a.Zi()===b;if(b instanceof ma){var c=Za(b);b=c.W;c=c.Y;a=a.xl();return a.W===b&&a.Y===c}return ja(b)?(b=Math.fround(b),a.pv()===b):\"number\"===typeof b?(b=+b,a.Lp()===b):!1}\nfunction BK(){this.wR=this.c=this.xR=this.vR=this.uR=this.tR=null;this.Jt=0;CK=this;DK();this.vR=DK();EK();xe();Rq();this.xR=Od();this.c=u();this.wR=FK();GK();Su();HK||(HK=new IK);JK||(JK=new KK);LK||(LK=new MK)}BK.prototype=new p;BK.prototype.constructor=BK;function Tr(){var a=O();0===(2&a.Jt)<<24>>24&&0===(2&a.Jt)<<24>>24&&(a.uR=NK(),a.Jt=(2|a.Jt)<<24>>24);return a.uR}BK.prototype.$classData=q({T3:0},!1,\"scala.package$\",{T3:1,g:1});var CK;function O(){CK||(CK=new BK);return CK}function OK(){}\nOK.prototype=new p;OK.prototype.constructor=OK;function ml(a,b,c){if(b===c)c=!0;else if(PK(b))a:if(PK(c))c=QK(0,b,c);else{if(c instanceof ba){if(\"number\"===typeof b){c=+b===Ea(c);break a}if(b instanceof ma){a=Za(b);b=a.Y;c=Ea(c);c=a.W===c&&b===c>>31;break a}}c=null===b?null===c:La(b,c)}else c=b instanceof ba?Rda(b,c):null===b?null===c:La(b,c);return c}\nfunction QK(a,b,c){if(\"number\"===typeof b)return a=+b,\"number\"===typeof c?a===+c:c instanceof ma?(b=Za(c),c=b.W,b=b.Y,a===cG(xa(),c,b)):c instanceof yH?c.i(a):!1;if(b instanceof ma){b=Za(b);a=b.W;b=b.Y;if(c instanceof ma){c=Za(c);var d=c.Y;return a===c.W&&b===d}return\"number\"===typeof c?(c=+c,cG(xa(),a,b)===c):c instanceof yH?c.i(new ma(a,b)):!1}return null===b?null===c:La(b,c)}\nfunction Rda(a,b){if(b instanceof ba)return Ea(a)===Ea(b);if(PK(b)){if(\"number\"===typeof b)return+b===Ea(a);if(b instanceof ma){b=Za(b);var c=b.Y;a=Ea(a);return b.W===a&&c===a>>31}return null===b?null===a:La(b,a)}return null===a&&null===b}OK.prototype.$classData=q({Y$:0},!1,\"scala.runtime.BoxesRunTime$\",{Y$:1,g:1});var RK;function nl(){RK||(RK=new OK);return RK}var jH=q({daa:0},!1,\"scala.runtime.Null$\",{daa:1,g:1});function SK(){}SK.prototype=new p;SK.prototype.constructor=SK;\nSK.prototype.$classData=q({gaa:0},!1,\"scala.runtime.RichInt$\",{gaa:1,g:1});var TK;function UK(){}UK.prototype=new p;UK.prototype.constructor=UK;function XG(a,b,c){if(b instanceof zc||b instanceof Xc||b instanceof ed||b instanceof Zc||b instanceof $c)return b.a[c];if(b instanceof Ic)return hc(b.a[c]);if(b instanceof Pc||b instanceof Sc||b instanceof Ec)return b.a[c];if(null===b)throw le();throw new w(b);}\nfunction fH(a,b,c,d){if(b instanceof zc)b.a[c]=d;else if(b instanceof Xc)b.a[c]=d|0;else if(b instanceof ed)b.a[c]=+d;else if(b instanceof Zc)b.a[c]=Za(d);else if(b instanceof $c)b.a[c]=Math.fround(d);else if(b instanceof Ic)b.a[c]=Ea(d);else if(b instanceof Pc)b.a[c]=d|0;else if(b instanceof Sc)b.a[c]=d|0;else if(b instanceof Ec)b.a[c]=!!d;else{if(null===b)throw le();throw new w(b);}}\nfunction wG(a,b){th();if(b instanceof zc||b instanceof Ec||b instanceof Ic||b instanceof Pc||b instanceof Sc||b instanceof Xc||b instanceof Zc||b instanceof $c||b instanceof ed)a=b.a.length;else throw Kj(\"argument type mismatch\");return a}function KG(a,b){if(b instanceof zc||b instanceof Xc||b instanceof ed||b instanceof Zc||b instanceof $c||b instanceof Ic||b instanceof Pc||b instanceof Sc||b instanceof Ec)return b.ia();if(null===b)throw le();throw new w(b);}\nfunction VK(a){xG();return ze(new iD(a),a.H()+\"(\",\",\",\")\")}UK.prototype.$classData=q({haa:0},!1,\"scala.runtime.ScalaRunTime$\",{haa:1,g:1});var WK;function xG(){WK||(WK=new UK);return WK}function XK(){}XK.prototype=new p;XK.prototype.constructor=XK;XK.prototype.C=function(a,b){a=this.Pp(a,b);return-430675100+Math.imul(5,a<<13|a>>>19|0)|0};XK.prototype.Pp=function(a,b){b=Math.imul(-862048943,b);b=Math.imul(461845907,b<<15|b>>>17|0);return a^b};\nXK.prototype.Ma=function(a,b){a^=b;a=Math.imul(-2048144789,a^(a>>>16|0));a=Math.imul(-1028477387,a^(a>>>13|0));return a^(a>>>16|0)};function YK(a,b){a=b.W;b=b.Y;return b===a>>31?a:a^b}function ZK(a,b){a=Eb(b);if(a===b)return a;a=xa();if(-0x7fffffffffffffff>b){a.Qc=-2147483648;var c=0}else if(0x7fffffffffffffff<=b)a.Qc=2147483647,c=-1;else{c=b|0;var d=b/4294967296|0;a.Qc=0>b&&0!==c?-1+d|0:d}a=a.Qc;return cG(xa(),c,a)===b?c^a:ig(mg(),b)}\nfunction My(a,b){return null===b?0:\"number\"===typeof b?ZK(0,+b):b instanceof ma?(a=Za(b),YK(0,new ma(a.W,a.Y))):ib(b)}function $K(a,b){throw aL(new bL,\"\"+b);}XK.prototype.$classData=q({kaa:0},!1,\"scala.runtime.Statics$\",{kaa:1,g:1});var cL;function W(){cL||(cL=new XK);return cL}function dL(){}dL.prototype=new p;dL.prototype.constructor=dL;dL.prototype.$classData=q({laa:0},!1,\"scala.runtime.Statics$PFMarker$\",{laa:1,g:1});var eL;function fL(){eL||(eL=new dL);return eL}function gL(){}gL.prototype=new p;\ngL.prototype.constructor=gL;function OI(){hL||(hL=new gL);throw iL(\"Defect: invariance violation\");}gL.prototype.$classData=q({i4:0},!1,\"scala.sys.package$\",{i4:1,g:1});var hL;function yy(){}yy.prototype=new p;yy.prototype.constructor=yy;function Rba(a,b){b.n(a);return a}yy.prototype.$classData=q({j4:0},!1,\"scala.util.ChainingOps$\",{j4:1,g:1});var xy;function jL(a){this.yR=a}jL.prototype=new p;jL.prototype.constructor=jL;jL.prototype.u=function(){return\"DynamicVariable(\"+this.yR+\")\"};\njL.prototype.$classData=q({k4:0},!1,\"scala.util.DynamicVariable\",{k4:1,g:1});function kL(){}kL.prototype=new p;kL.prototype.constructor=kL;\nfunction lL(a,b,c,d){c=c-b|0;if(!(2>c)){if(0<d.Da(XG(xG(),a,b),XG(xG(),a,1+b|0))){var e=XG(xG(),a,b);fH(xG(),a,b,XG(xG(),a,1+b|0));fH(xG(),a,1+b|0,e)}for(e=2;e<c;){var g=XG(xG(),a,b+e|0);if(0>d.Da(g,XG(xG(),a,-1+(b+e|0)|0))){for(var h=b,k=-1+(b+e|0)|0;1<(k-h|0);){var l=(h+k|0)>>>1|0;0>d.Da(g,XG(xG(),a,l))?k=l:h=l}h=h+(0>d.Da(g,XG(xG(),a,h))?0:1)|0;for(k=b+e|0;k>h;)fH(xG(),a,k,XG(xG(),a,-1+k|0)),k=-1+k|0;fH(xG(),a,h,g)}e=1+e|0}}}\nfunction mL(a,b,c,d,e,g,h){if(32>(d-c|0))lL(b,c,d,e);else{var k=(c+d|0)>>>1|0;g=null===g?h.si(k-c|0):g;mL(a,b,c,k,e,g,h);mL(a,b,k,d,e,g,h);nL(b,c,k,d,e,g)}}function nL(a,b,c,d,e,g){if(0<e.Da(XG(xG(),a,-1+c|0),XG(xG(),a,c))){for(var h=b,k=c-b|0,l=0;h<c;)fH(xG(),g,l,XG(xG(),a,h)),h=1+h|0,l=1+l|0;for(l=0;h<d&&l<k;)0>e.Da(XG(xG(),a,h),XG(xG(),g,l))?(fH(xG(),a,b,XG(xG(),a,h)),h=1+h|0):(fH(xG(),a,b,XG(xG(),g,l)),l=1+l|0),b=1+b|0;for(;l<k;)fH(xG(),a,b,XG(xG(),g,l)),l=1+l|0,b=1+b|0}}\nfunction RG(a,b,c,d){if(b instanceof zc){if(1<wG(xG(),b)&&null===d)throw oL(\"Ordering\");a=Pj();d=null===d?ij():d;var e=jj();if(0>c)throw Kj(\"fromIndex(0) \\x3e toIndex(\"+c+\")\");if(16<(c-0|0)){var g=b.a.length,h=ca(b);Vi(a,b,rh(th(),bg(h),g),0,c,d,e)}else Zi(b,0,c,d,e)}else if(b instanceof Xc)if(d===Fq())Ti(Pj(),b);else if(e=rl(),32>(c-0|0))lL(b,0,c,d);else{g=(0+c|0)>>>1|0;h=new Xc(g-0|0);if(32>(g-0|0))lL(b,0,g,d);else{var k=(0+g|0)>>>1|0;mL(a,b,0,k,d,h,e);mL(a,b,k,g,d,h,e);nL(b,0,k,g,d,h)}32>(c-g|\n0)?lL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h));nL(b,0,g,c,d,h)}else if(b instanceof ed)e=pL(),32>(c-0|0)?lL(b,0,c,d):(g=(0+c|0)>>>1|0,h=new ed(g-0|0),32>(g-0|0)?lL(b,0,g,d):(k=(0+g|0)>>>1|0,mL(a,b,0,k,d,h,e),mL(a,b,k,g,d,h,e),nL(b,0,k,g,d,h)),32>(c-g|0)?lL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h)),nL(b,0,g,c,d,h));else if(b instanceof Zc)d===LG()?$i(Pj(),b):(e=qL(),32>(c-0|0)?lL(b,0,c,d):(g=(0+c|0)>>>1|0,h=new Zc(g-0|0),32>\n(g-0|0)?lL(b,0,g,d):(k=(0+g|0)>>>1|0,mL(a,b,0,k,d,h,e),mL(a,b,k,g,d,h,e),nL(b,0,k,g,d,h)),32>(c-g|0)?lL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h)),nL(b,0,g,c,d,h)));else if(b instanceof $c)e=rL(),32>(c-0|0)?lL(b,0,c,d):(g=(0+c|0)>>>1|0,h=new $c(g-0|0),32>(g-0|0)?lL(b,0,g,d):(k=(0+g|0)>>>1|0,mL(a,b,0,k,d,h,e),mL(a,b,k,g,d,h,e),nL(b,0,k,g,d,h)),32>(c-g|0)?lL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h)),nL(b,0,g,c,d,h));else if(b instanceof\nIc)d===MG()?dj(Pj(),b):(e=Ir(),32>(c-0|0)?lL(b,0,c,d):(g=(0+c|0)>>>1|0,h=new Ic(g-0|0),32>(g-0|0)?lL(b,0,g,d):(k=(0+g|0)>>>1|0,mL(a,b,0,k,d,h,e),mL(a,b,k,g,d,h,e),nL(b,0,k,g,d,h)),32>(c-g|0)?lL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h)),nL(b,0,g,c,d,h)));else if(b instanceof Pc)d===NG()?fj(Pj(),b):(e=sL(),32>(c-0|0)?lL(b,0,c,d):(g=(0+c|0)>>>1|0,h=new Pc(g-0|0),32>(g-0|0)?lL(b,0,g,d):(k=(0+g|0)>>>1|0,mL(a,b,0,k,d,h,e),mL(a,b,k,g,d,h,e),nL(b,0,k,g,d,h)),32>(c-g|0)?\nlL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h)),nL(b,0,g,c,d,h)));else if(b instanceof Sc)d===OG()?bj(Pj(),b):(e=tL(),32>(c-0|0)?lL(b,0,c,d):(g=(0+c|0)>>>1|0,h=new Sc(g-0|0),32>(g-0|0)?lL(b,0,g,d):(k=(0+g|0)>>>1|0,mL(a,b,0,k,d,h,e),mL(a,b,k,g,d,h,e),nL(b,0,k,g,d,h)),32>(c-g|0)?lL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h)),nL(b,0,g,c,d,h)));else if(b instanceof Ec)if(d===PG()){for(d=c=0;c<b.a.length;)b.a[c]||(d=1+d|0),c=1+c|0;for(c=\n0;c<d;)b.a[c]=!1,c=1+c|0;for(;c<b.a.length;)b.a[c]=!0,c=1+c|0}else e=uL(),32>(c-0|0)?lL(b,0,c,d):(g=(0+c|0)>>>1|0,h=new Ec(g-0|0),32>(g-0|0)?lL(b,0,g,d):(k=(0+g|0)>>>1|0,mL(a,b,0,k,d,h,e),mL(a,b,k,g,d,h,e),nL(b,0,k,g,d,h)),32>(c-g|0)?lL(b,g,c,d):(k=(g+c|0)>>>1|0,mL(a,b,g,k,d,h,e),mL(a,b,k,c,d,h,e),nL(b,g,k,c,d,h)),nL(b,0,g,c,d,h));else{if(null===b)throw le();throw new w(b);}}kL.prototype.$classData=q({r4:0},!1,\"scala.util.Sorting$\",{r4:1,g:1});var vL;function QG(){vL||(vL=new kL);return vL}\nfunction wL(){}wL.prototype=new p;wL.prototype.constructor=wL;function xL(){}xL.prototype=wL.prototype;wL.prototype.C=function(a,b){a=this.Pp(a,b);return-430675100+Math.imul(5,a<<13|a>>>19|0)|0};wL.prototype.Pp=function(a,b){b=Math.imul(-862048943,b);b=Math.imul(461845907,b<<15|b>>>17|0);return a^b};wL.prototype.Ma=function(a,b){return yL(a^b)};function yL(a){a=Math.imul(-2048144789,a^(a>>>16|0));a=Math.imul(-1028477387,a^(a>>>13|0));return a^(a>>>16|0)}\nfunction zL(a,b,c){var d=a.C(-889275714,lb(\"Tuple2\"));d=a.C(d,b);d=a.C(d,c);return a.Ma(d,2)}function AL(a){var b=BL(),c=a.G();if(0===c)return lb(a.H());var d=b.C(-889275714,lb(a.H()));for(var e=0;e<c;){var g=a.I(e);d=b.C(d,My(W(),g));e=1+e|0}return b.Ma(d,c)}function CL(a,b,c){var d=0,e=0,g=0,h=1;for(b=b.m();b.s();){var k=b.t();k=My(W(),k);d=d+k|0;e^=k;h=Math.imul(h,1|k);g=1+g|0}c=a.C(c,d);c=a.C(c,e);c=a.Pp(c,h);return a.Ma(c,g)}\nfunction DL(a,b,c){var d=c;c=wG(xG(),b);switch(c){case 0:return a.Ma(d,0);case 1:return c=d,b=XG(xG(),b,0),a.Ma(a.C(c,My(W(),b)),1);default:var e=XG(xG(),b,0),g=My(W(),e);e=d=a.C(d,g);var h=XG(xG(),b,1);h=My(W(),h);var k=h-g|0;for(g=2;g<c;){d=a.C(d,h);var l=XG(xG(),b,g);l=My(W(),l);if(k!==(l-h|0)){d=a.C(d,l);for(g=1+g|0;g<c;)e=XG(xG(),b,g),d=a.C(d,My(W(),e)),g=1+g|0;return a.Ma(d,c)}h=l;g=1+g|0}return yL(a.C(a.C(e,k),h))}}\nfunction EL(a,b,c){var d=b.a.length;switch(d){case 0:return a.Ma(c,0);case 1:return a.Ma(a.C(c,b.a[0]?1231:1237),1);default:var e=b.a[0]?1231:1237,g=c=a.C(c,e),h=b.a[1]?1231:1237;e=h-e|0;for(var k=2;k<d;){c=a.C(c,h);var l=b.a[k]?1231:1237;if(e!==(l-h|0)){c=a.C(c,l);for(k=1+k|0;k<d;)c=a.C(c,b.a[k]?1231:1237),k=1+k|0;return a.Ma(c,d)}h=l;k=1+k|0}return yL(a.C(a.C(g,e),h))}}\nfunction FL(a,b,c){var d=b.a.length;switch(d){case 0:return a.Ma(c,0);case 1:return a.Ma(a.C(c,b.a[0]),1);default:var e=b.a[0],g=c=a.C(c,e),h=b.a[1];e=h-e|0;for(var k=2;k<d;){c=a.C(c,h);var l=b.a[k];if(e!==(l-h|0)){c=a.C(c,l);for(k=1+k|0;k<d;)c=a.C(c,b.a[k]),k=1+k|0;return a.Ma(c,d)}h=l;k=1+k|0}return yL(a.C(a.C(g,e),h))}}\nfunction GL(a,b,c){var d=b.a.length;switch(d){case 0:return a.Ma(c,0);case 1:return a.Ma(a.C(c,b.a[0]),1);default:var e=b.a[0],g=c=a.C(c,e),h=b.a[1];e=h-e|0;for(var k=2;k<d;){c=a.C(c,h);var l=b.a[k];if(e!==(l-h|0)){c=a.C(c,l);for(k=1+k|0;k<d;)c=a.C(c,b.a[k]),k=1+k|0;return a.Ma(c,d)}h=l;k=1+k|0}return yL(a.C(a.C(g,e),h))}}\nfunction HL(a,b,c){var d=b.a.length;switch(d){case 0:return a.Ma(c,0);case 1:return b=b.a[0],a.Ma(a.C(c,ZK(W(),b)),1);default:var e=b.a[0],g=ZK(W(),e);e=c=a.C(c,g);var h=b.a[1];h=ZK(W(),h);var k=h-g|0;for(g=2;g<d;){c=a.C(c,h);var l=b.a[g];l=ZK(W(),l);if(k!==(l-h|0)){c=a.C(c,l);for(g=1+g|0;g<d;)e=b.a[g],c=a.C(c,ZK(W(),e)),g=1+g|0;return a.Ma(c,d)}h=l;g=1+g|0}return yL(a.C(a.C(e,k),h))}}\nfunction IL(a,b,c){var d=c;c=b.a.length;switch(c){case 0:return a.Ma(d,0);case 1:return c=d,b=b.a[0],W(),a.Ma(a.C(c,ZK(0,b)),1);default:var e=b.a[0],g=ZK(W(),e);e=d=a.C(d,g);var h=b.a[1];h=ZK(W(),h);var k=h-g|0;for(g=2;g<c;){d=a.C(d,h);var l=b.a[g];l=ZK(W(),l);if(k!==(l-h|0)){d=a.C(d,l);for(g=1+g|0;g<c;)e=b.a[g],W(),d=a.C(d,ZK(0,e)),g=1+g|0;return a.Ma(d,c)}h=l;g=1+g|0}return yL(a.C(a.C(e,k),h))}}\nfunction JL(a,b,c){var d=b.a.length;switch(d){case 0:return a.Ma(c,0);case 1:return a.Ma(a.C(c,b.a[0]),1);default:var e=b.a[0],g=c=a.C(c,e),h=b.a[1];e=h-e|0;for(var k=2;k<d;){c=a.C(c,h);var l=b.a[k];if(e!==(l-h|0)){c=a.C(c,l);for(k=1+k|0;k<d;)c=a.C(c,b.a[k]),k=1+k|0;return a.Ma(c,d)}h=l;k=1+k|0}return yL(a.C(a.C(g,e),h))}}\nfunction KL(a,b,c){var d=b.a.length;switch(d){case 0:return a.Ma(c,0);case 1:return d=b.a[0],b=d.W,d=d.Y,a.Ma(a.C(c,YK(W(),new ma(b,d))),1);default:var e=b.a[0],g=e.W;e=e.Y;e=YK(W(),new ma(g,e));g=c=a.C(c,e);var h=b.a[1],k=h.W;h=h.Y;k=YK(W(),new ma(k,h));h=k-e|0;for(e=2;e<d;){c=a.C(c,k);var l=b.a[e],m=l.W;l=l.Y;m=YK(W(),new ma(m,l));if(h!==(m-k|0)){c=a.C(c,m);for(e=1+e|0;e<d;)k=b.a[e],g=k.W,k=k.Y,c=a.C(c,YK(W(),new ma(g,k))),e=1+e|0;return a.Ma(c,d)}k=m;e=1+e|0}return yL(a.C(a.C(g,h),k))}}\nfunction LL(a,b,c){var d=b.a.length;switch(d){case 0:return a.Ma(c,0);case 1:return a.Ma(a.C(c,b.a[0]),1);default:var e=b.a[0],g=c=a.C(c,e),h=b.a[1];e=h-e|0;for(var k=2;k<d;){c=a.C(c,h);var l=b.a[k];if(e!==(l-h|0)){c=a.C(c,l);for(k=1+k|0;k<d;)c=a.C(c,b.a[k]),k=1+k|0;return a.Ma(c,d)}h=l;k=1+k|0}return yL(a.C(a.C(g,e),h))}}\nfunction ML(a,b,c){b=b.a.length;switch(b){case 0:return a.Ma(c,0);case 1:return a.Ma(a.C(c,0),1);default:for(var d=c=a.C(c,0),e=0,g=e,h=2;h<b;){c=a.C(c,e);if(g!==(-e|0)){c=a.C(c,0);for(h=1+h|0;h<b;)c=a.C(c,0),h=1+h|0;return a.Ma(c,b)}e=0;h=1+h|0}return yL(a.C(a.C(d,g),e))}}function NL(){}NL.prototype=new p;NL.prototype.constructor=NL;NL.prototype.$classData=q({v4:0},!1,\"scala.util.hashing.package$\",{v4:1,g:1});var OL;function PL(){}PL.prototype=new p;PL.prototype.constructor=PL;function QL(){}\nQL.prototype=PL.prototype;function Ke(a,b){this.Lz=this.mE=this.dx=this.lE=this.ex=null;this.hx=!1;this.Fu=null;this.Eu=!1;this.jE=this.kE=null;this.le=this.fx=0;this.gx=this.Ol=null;this.Kz=!1;lt(this,a,b,!0,new y(c=>{throw c;}),!1,t().d,(Vs(),\"input\"))}Ke.prototype=new ot;Ke.prototype.constructor=Ke;Ke.prototype.nQ=function(a){this.Eu&&(a=Es(a),ff(gf(),a+\"\\n\"))};Ke.prototype.$classData=q({vT:0},!1,\"Main$$anon$1\",{vT:1,PW:1,g:1});\nfunction ne(a){this.op=null;this.Ui=a;if(null===a)throw null;this.op=a}ne.prototype=new pC;ne.prototype.constructor=ne;ne.prototype.$classData=q({wT:0},!1,\"Main$SimplifyPipeline$1$\",{wT:1,Maa:1,g:1});\nfunction ZD(a,b){0===(4&a.$j)<<24>>24&&0===(4&a.$j)<<24>>24&&(a.tQ=new Xc(new Int32Array([1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,5,1,2,5,1,3,2,1,3,2,1,3,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,\n2,1,3,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,5,2,4,27,4,27,4,27,4,27,4,27,6,1,2,1,2,4,27,1,2,0,4,2,24,0,27,1,24,1,0,1,0,1,2,1,0,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,25,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,28,6,7,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,\n1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,0,1,0,4,24,0,2,0,24,20,0,26,0,6,20,6,24,6,24,6,24,6,0,5,0,5,24,0,16,0,25,24,26,24,28,6,24,0,24,5,4,5,6,9,24,5,6,5,24,5,6,16,28,6,4,6,28,6,5,9,5,28,5,24,0,16,5,6,5,6,0,5,6,5,0,9,5,6,4,28,24,4,0,5,6,4,6,4,6,4,6,0,24,0,5,6,0,24,0,5,0,5,0,6,0,6,8,5,6,8,6,5,8,6,8,6,8,5,6,5,6,24,9,24,4,5,0,5,0,\n6,8,0,5,0,5,0,5,0,5,0,5,0,5,0,6,5,8,6,0,8,0,8,6,5,0,8,0,5,0,5,6,0,9,5,26,11,28,26,0,6,8,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,6,0,8,6,0,6,0,6,0,6,0,5,0,5,0,9,6,5,6,0,6,8,0,5,0,5,0,5,0,5,0,5,0,5,0,6,5,8,6,0,6,8,0,8,6,0,5,0,5,6,0,9,24,26,0,6,8,0,5,0,5,0,5,0,5,0,5,0,5,0,6,5,8,6,8,6,0,8,0,8,6,0,6,8,0,5,0,5,6,0,9,28,5,11,0,6,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,8,6,8,0,8,0,8,6,0,5,0,8,0,9,11,28,26,28,0,8,0,5,0,5,0,5,0,5,0,5,0,5,6,8,0,6,0,6,0,6,0,5,0,5,6,0,9,0,11,28,0,8,0,5,0,5,0,5,0,5,0,5,0,6,5,8,6,8,0,6,8,\n0,8,6,0,8,0,5,0,5,6,0,9,0,5,0,8,0,5,0,5,0,5,0,5,8,6,0,8,0,8,6,5,0,8,0,5,6,0,9,11,0,28,5,0,8,0,5,0,5,0,5,0,5,0,5,0,6,0,8,6,0,6,0,8,0,8,24,0,5,6,5,6,0,26,5,4,6,24,9,24,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,6,5,6,0,6,5,0,5,0,4,0,6,0,9,0,5,0,5,28,24,28,24,28,6,28,9,11,28,6,28,6,28,6,21,22,21,22,8,5,0,5,0,6,8,6,24,6,5,6,0,6,0,28,6,28,0,28,24,28,24,0,5,8,6,8,6,8,6,8,6,5,9,24,5,8,6,5,6,5,8,5,8,5,6,5,6,8,6,8,6,5,8,9,8,6,28,1,0,1,0,1,0,5,24,4,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,\n0,5,0,5,0,6,24,11,0,5,28,0,5,0,20,5,24,5,12,5,21,22,0,5,24,10,0,5,0,5,6,0,5,6,24,0,5,6,0,5,0,5,0,6,0,5,6,8,6,8,6,8,6,24,4,24,26,5,6,0,9,0,11,0,24,20,24,6,12,0,9,0,5,4,5,0,5,6,5,0,5,0,5,0,6,8,6,8,0,8,6,8,6,0,28,0,24,9,5,0,5,0,5,0,8,5,8,0,9,11,0,28,5,6,8,0,24,5,8,6,8,6,0,6,8,6,8,6,8,6,0,6,9,0,9,0,24,4,24,0,6,8,5,6,8,6,8,6,8,6,8,5,0,9,24,28,6,28,0,6,8,5,8,6,8,6,8,6,8,5,9,5,6,8,6,8,6,8,6,8,0,24,5,8,6,8,6,0,24,9,0,5,9,5,4,24,0,24,0,6,24,6,8,6,5,6,5,8,6,5,0,2,4,2,4,2,4,6,0,6,1,2,1,2,1,2,1,2,1,2,1,2,1,2,\n1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,0,1,0,2,1,2,1,2,0,1,0,2,0,1,0,\n1,0,1,0,1,2,1,2,0,2,3,2,3,2,3,2,0,2,1,3,27,2,27,2,0,2,1,3,27,2,0,2,1,0,27,2,1,27,0,2,0,2,1,3,27,0,12,16,20,24,29,30,21,29,30,21,29,24,13,14,16,12,24,29,30,24,23,24,25,21,22,24,25,24,23,24,12,16,0,16,11,4,0,11,25,21,22,4,11,25,21,22,0,4,0,26,0,6,7,6,7,6,0,28,1,28,1,28,2,1,2,1,2,28,1,28,25,1,28,1,28,1,28,1,28,1,28,2,1,2,5,2,28,2,1,25,1,2,28,25,28,2,28,11,10,1,2,10,11,0,25,28,25,28,25,28,25,28,25,28,25,28,25,28,25,28,25,28,25,28,25,28,25,28,21,22,28,25,28,25,28,25,28,0,28,0,28,0,11,28,11,28,25,28,25,\n28,25,28,25,28,0,28,21,22,21,22,21,22,21,22,21,22,21,22,21,22,11,28,25,21,22,25,21,22,21,22,21,22,21,22,21,22,25,28,25,21,22,21,22,21,22,21,22,21,22,21,22,21,22,21,22,21,22,21,22,21,22,25,21,22,21,22,25,21,22,25,28,25,28,25,0,28,0,1,0,2,0,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,4,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,28,1,2,1,2,6,1,2,0,24,11,24,\n2,0,2,0,2,0,5,0,4,24,0,6,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,6,24,29,30,29,30,24,29,30,24,29,30,24,20,24,20,24,29,30,24,29,30,21,22,21,22,21,22,21,22,24,4,24,20,0,28,0,28,0,28,0,28,0,12,24,28,4,5,10,21,22,21,22,21,22,21,22,21,22,28,21,22,21,22,21,22,21,22,20,21,22,28,10,6,8,20,4,28,10,4,5,24,28,0,5,0,6,27,4,5,20,5,24,4,5,0,5,0,5,0,28,11,28,5,0,28,0,5,28,0,11,28,11,28,11,28,11,28,11,28,5,0,28,5,0,5,4,5,0,28,0,5,4,24,5,4,24,5,9,5,0,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,\n1,2,1,2,1,2,1,2,1,2,1,2,5,6,7,24,6,24,4,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,0,6,5,10,6,24,0,27,4,27,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,4,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,4,27,1,2,1,2,0,1,2,1,2,0,1,2,1,2,1,2,1,2,1,2,1,0,4,2,5,6,5,6,5,6,5,8,6,8,28,0,11,28,26,28,0,5,24,0,8,5,8,6,0,24,9,0,6,5,24,5,0,9,5,6,24,5,6,8,0,24,5,0,6,8,5,6,8,6,8,6,8,24,0,4,9,0,24,0,5,6,8,6,8,6,0,5,6,5,\n6,8,0,9,0,24,5,4,5,28,5,8,0,5,6,5,6,5,6,5,6,5,6,5,0,5,4,24,5,8,6,8,24,5,4,8,6,0,5,0,5,0,5,0,5,0,5,0,5,8,6,8,6,8,24,8,6,0,9,0,5,0,5,0,5,0,19,18,5,0,5,0,2,0,2,0,5,6,5,25,5,0,5,0,5,0,5,0,5,0,5,27,0,5,21,22,0,5,0,5,0,5,26,28,0,6,24,21,22,24,0,6,0,24,20,23,21,22,21,22,21,22,21,22,21,22,21,22,21,22,21,22,24,21,22,24,23,24,0,24,20,21,22,21,22,21,22,24,25,20,25,0,24,26,24,0,5,0,5,0,16,0,24,26,24,21,22,24,25,24,20,24,9,24,25,24,1,21,24,22,27,23,27,2,21,25,22,25,21,22,24,21,22,24,5,4,5,4,5,0,5,0,5,0,5,0,5,\n0,26,25,27,28,26,0,28,25,28,0,16,28,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,24,0,11,0,28,10,11,28,11,0,28,0,28,6,0,5,0,5,0,5,0,11,0,5,10,5,10,0,5,0,24,5,0,5,24,10,0,1,2,5,0,9,0,5,0,5,0,5,0,5,0,5,0,5,0,24,11,0,5,11,0,24,5,0,24,0,5,0,5,0,5,6,0,6,0,6,5,0,5,0,5,0,6,0,6,11,0,24,0,5,11,24,0,5,0,24,5,0,11,5,0,11,0,5,0,11,0,8,6,8,5,6,24,0,11,9,0,6,8,5,8,6,8,6,24,16,24,0,5,0,9,0,6,5,6,8,6,0,9,24,0,6,8,5,8,6,8,5,24,0,9,0,5,6,8,6,8,6,8,6,0,9,0,5,0,10,0,24,0,5,0,5,0,5,0,5,8,0,6,4,0,5,0,28,0,28,0,28,8,6,28,8,16,6,28,6,\n28,6,28,0,28,6,28,0,28,0,11,0,1,2,1,2,0,2,1,2,1,0,1,0,1,0,1,0,1,0,1,2,0,2,0,2,0,2,1,2,1,0,1,0,1,0,1,0,2,1,0,1,0,1,0,1,0,1,0,2,1,2,1,2,1,2,1,2,1,2,1,2,0,1,25,2,25,2,1,25,2,25,2,1,25,2,25,2,1,25,2,25,2,1,25,2,25,2,1,2,0,9,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,5,0,25,0,28,0,28,0,28,0,28,0,28,0,28,0,11,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,0,28,\n0,28,0,28,0,28,0,5,0,5,0,5,0,5,0,16,0,16,0,6,0,18,0,18,0])),a.$j=(4|a.$j)<<24>>24);var c=a.tQ.a;if(0===(2&a.$j)<<24>>24&&0===(2&a.$j)<<24>>24){for(var d=new Xc(new Int32Array([257,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,3,2,1,1,1,2,1,3,2,4,1,2,1,3,3,2,1,2,1,1,1,1,1,2,1,1,2,1,1,2,1,3,1,1,1,2,2,1,1,\n3,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,1,2,2,1,1,4,1,1,1,1,1,1,1,1,69,1,27,18,4,12,14,5,7,1,1,1,17,112,1,1,1,1,1,1,1,1,2,1,3,1,5,2,1,1,3,1,1,1,2,1,17,1,9,35,1,2,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,1,1,1,1,2,2,51,48,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,2,1,1,1,1,1,1,\n1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,38,2,1,6,1,39,1,1,1,4,1,1,45,1,1,1,2,1,2,1,1,8,27,5,3,2,11,5,1,3,2,1,2,2,11,1,2,2,32,1,10,21,10,4,2,1,99,1,1,7,1,1,6,2,2,1,4,2,10,3,2,1,14,1,1,1,1,30,27,2,89,11,1,14,10,33,9,2,1,3,1,5,22,4,1,9,1,3,1,\n5,2,15,1,25,3,2,1,65,1,1,11,55,27,1,3,1,54,1,1,1,1,3,8,4,1,2,1,7,10,2,2,10,1,1,6,1,7,1,1,2,1,8,2,2,2,22,1,7,1,1,3,4,2,1,1,3,4,2,2,2,2,1,1,8,1,4,2,1,3,2,2,10,2,2,6,1,1,5,2,1,1,6,4,2,2,22,1,7,1,2,1,2,1,2,2,1,1,3,2,4,2,2,3,3,1,7,4,1,1,7,10,2,3,1,11,2,1,1,9,1,3,1,22,1,7,1,2,1,5,2,1,1,3,5,1,2,1,1,2,1,2,1,15,2,2,2,10,1,1,15,1,2,1,8,2,2,2,22,1,7,1,2,1,5,2,1,1,1,1,1,4,2,2,2,2,1,8,1,1,4,2,1,3,2,2,10,1,1,6,10,1,1,1,6,3,3,1,4,3,2,1,1,1,2,3,2,3,3,3,12,4,2,1,2,3,3,1,3,1,2,1,6,1,14,10,3,6,1,1,6,3,1,8,1,3,1,23,\n1,10,1,5,3,1,3,4,1,3,1,4,7,2,1,2,6,2,2,2,10,8,7,1,2,2,1,8,1,3,1,23,1,10,1,5,2,1,1,1,1,5,1,1,2,1,2,2,7,2,7,1,1,2,2,2,10,1,2,15,2,1,8,1,3,1,41,2,1,3,4,1,3,1,3,1,1,8,1,8,2,2,2,10,6,3,1,6,2,2,1,18,3,24,1,9,1,1,2,7,3,1,4,3,3,1,1,1,8,18,2,1,12,48,1,2,7,4,1,6,1,8,1,10,2,37,2,1,1,2,2,1,1,2,1,6,4,1,7,1,3,1,1,1,1,2,2,1,4,1,2,6,1,2,1,2,5,1,1,1,6,2,10,2,4,32,1,3,15,1,1,3,2,6,10,10,1,1,1,1,1,1,1,1,1,1,2,8,1,36,4,14,1,5,1,2,5,11,1,36,1,8,1,6,1,2,5,4,2,37,43,2,4,1,6,1,2,2,2,1,10,6,6,2,2,4,3,1,3,2,7,3,4,13,1,2,2,\n6,1,1,1,10,3,1,2,38,1,1,5,1,2,43,1,1,332,1,4,2,7,1,1,1,4,2,41,1,4,2,33,1,4,2,7,1,1,1,4,2,15,1,57,1,4,2,67,2,3,9,20,3,16,10,6,85,11,1,620,2,17,1,26,1,1,3,75,3,3,15,13,1,4,3,11,18,3,2,9,18,2,12,13,1,3,1,2,12,52,2,1,7,8,1,2,11,3,1,3,1,1,1,2,10,6,10,6,6,1,4,3,1,1,10,6,35,1,52,8,41,1,1,5,70,10,29,3,3,4,2,3,4,2,1,6,3,4,1,3,2,10,30,2,5,11,44,4,17,7,2,6,10,1,3,34,23,2,3,2,2,53,1,1,1,7,1,1,1,1,2,8,6,10,2,1,10,6,10,6,7,1,6,82,4,1,47,1,1,5,1,1,5,1,2,7,4,10,7,10,9,9,3,2,1,30,1,4,2,2,1,1,2,2,10,44,1,1,2,3,1,1,\n3,2,8,4,36,8,8,2,2,3,5,10,3,3,10,30,6,2,64,8,8,3,1,13,1,7,4,1,4,2,1,2,9,44,63,13,1,34,37,39,21,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,\n1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,8,6,2,6,2,8,8,8,8,6,2,6,2,8,1,1,1,1,1,1,1,1,8,8,14,2,8,8,8,8,8,8,5,1,2,4,1,1,1,3,3,1,2,4,1,3,4,2,2,4,1,3,8,5,3,2,3,1,2,4,1,2,1,11,5,6,2,1,1,1,2,1,1,1,8,1,1,5,1,9,1,1,4,2,3,1,1,1,11,1,1,1,10,1,5,5,6,1,1,2,6,3,1,1,1,10,3,1,1,1,13,3,32,16,13,4,1,3,12,15,2,1,4,1,2,1,3,2,3,1,1,1,2,1,5,6,1,1,1,1,1,1,4,1,1,4,1,4,1,2,2,2,5,1,4,1,1,2,1,1,16,35,1,1,4,1,6,5,5,2,4,1,2,1,2,1,7,1,31,2,2,1,1,1,31,268,8,4,20,2,7,1,1,81,1,\n30,25,40,6,18,12,39,25,11,21,60,78,22,183,1,9,1,54,8,111,1,144,1,103,1,1,1,1,1,1,1,1,1,1,1,1,1,1,30,44,5,1,1,31,1,1,1,1,1,1,1,1,1,1,16,256,131,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,63,1,1,1,1,32,1,1,258,48,21,2,6,3,10,166,47,1,47,1,1,1,3,2,1,1,1,1,1,1,4,1,1,2,1,6,2,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,6,1,1,1,1,3,1,1,5,4,1,2,38,1,\n1,5,1,2,56,7,1,1,14,1,23,9,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,32,2,1,1,1,1,3,1,1,1,1,1,9,1,2,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,5,1,10,2,68,26,1,89,12,214,26,12,4,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,9,4,2,1,5,2,3,1,1,1,2,1,86,2,2,2,2,1,1,90,1,3,1,5,41,3,94,1,2,4,10,27,5,36,12,16,31,1,10,30,8,1,15,32,10,39,15,320,6582,10,64,20941,51,21,1,1143,3,55,9,40,6,2,268,1,3,16,10,2,20,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,10,1,1,1,1,\n1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,70,10,2,6,8,23,9,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,12,1,1,1,1,1,1,1,1,1,1,1,77,2,1,7,1,3,1,4,1,23,2,2,1,4,4,6,2,1,1,6,52,4,8,2,50,16,1,9,2,10,6,18,6,3,1,4,10,28,8,2,23,11,2,11,1,29,3,3,1,47,1,2,4,2,1,4,13,1,1,10,4,2,32,41,6,2,2,2,2,9,3,1,8,1,1,2,10,2,4,16,1,6,3,1,1,4,48,1,1,3,2,\n2,5,2,1,1,1,24,2,1,2,11,1,2,2,2,1,2,1,1,10,6,2,6,2,6,9,7,1,7,145,35,2,1,2,1,2,1,1,1,2,10,6,11172,12,23,4,49,4,2048,6400,366,2,106,38,7,12,5,5,1,1,10,1,13,1,5,1,1,1,2,1,2,1,108,16,17,363,1,1,16,64,2,54,40,12,1,1,2,16,7,1,1,1,6,7,9,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,4,3,3,1,4,1,1,1,1,1,1,1,3,1,1,3,1,1,1,2,4,5,1,135,2,1,1,3,1,3,1,1,1,1,1,1,2,10,2,3,2,26,1,1,1,1,1,1,26,1,1,1,1,1,1,1,1,1,2,10,1,45,2,31,3,6,2,6,2,6,2,3,3,2,1,1,1,2,1,1,4,2,10,3,2,2,12,1,26,1,19,1,2,1,15,2,14,34,123,5,3,4,45,3,9,\n53,4,17,1,5,12,52,45,1,130,29,3,49,47,31,1,4,12,17,1,8,1,53,30,1,1,36,4,8,1,5,42,40,40,78,2,10,854,6,2,1,1,44,1,2,3,1,2,23,1,1,8,160,22,6,3,1,26,5,1,64,56,6,2,64,1,3,1,2,5,4,4,1,3,1,27,4,3,4,1,8,8,9,7,29,2,1,128,54,3,7,22,2,8,19,5,8,128,73,535,31,385,1,1,1,53,15,7,4,20,10,16,2,1,45,3,4,2,2,2,1,4,14,25,7,10,6,3,36,5,1,8,1,10,4,60,2,1,48,3,9,2,4,4,7,10,1190,43,1,1,1,2,6,1,1,8,10,2358,879,145,99,13,4,2956,1071,13265,569,1223,69,11,1,46,16,4,13,16480,2,8190,246,10,39,2,60,2,3,3,6,8,8,2,7,30,4,48,34,66,\n3,1,186,87,9,18,142,26,26,26,7,1,18,26,26,1,1,2,2,1,2,2,2,4,1,8,4,1,1,1,7,1,11,26,26,2,1,4,2,8,1,7,1,26,2,1,4,1,5,1,1,3,7,1,26,26,26,26,26,26,26,26,26,26,26,26,28,2,25,1,25,1,6,25,1,25,1,6,25,1,25,1,6,25,1,25,1,6,25,1,25,1,6,1,1,2,50,5632,4,1,27,1,2,1,1,2,1,1,10,1,4,1,1,1,1,6,1,4,1,1,1,1,1,1,3,1,2,1,1,2,1,1,1,1,1,1,1,1,1,1,2,1,1,2,4,1,7,1,4,1,4,1,1,1,10,1,17,5,3,1,5,1,17,52,2,270,44,4,100,12,15,2,14,2,15,1,15,32,11,5,31,1,60,4,43,75,29,13,43,5,9,7,2,174,33,15,6,1,70,3,20,12,37,1,5,21,17,15,63,1,1,\n1,182,1,4,3,62,2,4,12,24,147,70,4,11,48,70,58,116,2188,42711,41,4149,11,222,16354,542,722403,1,30,96,128,240,65040,65534,2,65534])),e=d.a[0],g=1,h=d.a.length;g!==h;)e=e+d.a[g]|0,d.a[g]=e,g=1+g|0;a.sQ=d;a.$j=(2|a.$j)<<24>>24}a=a.sQ;b=kj(Pj(),a,b);return c[0<=b?1+b|0:-1-b|0]}\nfunction RL(a){0===(32&a.$j)<<24>>24&&0===(32&a.$j)<<24>>24&&(a.vQ=new Xc(new Int32Array([1632,1776,1984,2406,2534,2662,2790,2918,3046,3174,3302,3430,3664,3792,3872,4160,4240,6112,6160,6470,6608,6784,6800,6992,7088,7232,7248,42528,43216,43264,43472,43600,44016,65296,66720,69734,69872,69942,70096,71360,120782,120792,120802,120812,120822])),a.$j=(32|a.$j)<<24>>24);return a.vQ}function SL(){this.vQ=this.tQ=this.sQ=this.uQ=null;this.$j=0}SL.prototype=new p;SL.prototype.constructor=SL;\nfunction TL(a,b){if(0<=b&&65536>b)return String.fromCharCode(b);if(0<=b&&1114111>=b)return String.fromCharCode(65535&(-64+(b>>10)|55296),65535&(56320|1023&b));throw UL();}function VL(a,b){return 0>b?0:256>b?WL(a).a[b]:ZD(a,b)}\nfunction DH(a,b,c){if(256>b)a=48<=b&&57>=b?-48+b|0:65<=b&&90>=b?-55+b|0:97<=b&&122>=b?-87+b|0:-1;else if(65313<=b&&65338>=b)a=-65303+b|0;else if(65345<=b&&65370>=b)a=-65335+b|0;else{var d=kj(Pj(),RL(a),b);d=0>d?-2-d|0:d;0>d?a=-1:(a=b-RL(a).a[d]|0,a=9<a?-1:a)}return a<c?a:-1}function us(a,b){return 0<=b&&31>=b||127<=b&&159>=b}\nfunction bE(a,b){return 256>b?170===b||186===b||2===WL(a).a[b]:688<=b&&696>=b||704<=b&&705>=b||736<=b&&740>=b||837===b||890===b||7468<=b&&7530>=b||7544===b||7579<=b&&7615>=b||8305===b||8319===b||8336<=b&&8348>=b||8560<=b&&8575>=b||9424<=b&&9449>=b||11388<=b&&11389>=b||42864===b||43E3<=b&&43001>=b||2===ZD(a,b)}function TF(a,b){return 8544<=b&&8559>=b||9398<=b&&9423>=b||1===VL(a,b)}function Or(a,b){a=VL(a,b);return 1===a||2===a||3===a||4===a||5===a}\nfunction hda(a){switch(a){case 8115:case 8131:case 8179:return 9+a|0;default:if(8064<=a&&8111>=a)return 8|a;var b=TL(0,a).toUpperCase();switch(b.length){case 1:return b.charCodeAt(0);case 2:var c=b.charCodeAt(0);b=b.charCodeAt(1);return-671032320===(-67044352&(c<<16|b))?(64+(1023&c)|0)<<10|1023&b:a;default:return a}}}\nfunction bda(a){if(304===a)return 105;var b=TL(0,a).toLowerCase();switch(b.length){case 1:return b.charCodeAt(0);case 2:var c=b.charCodeAt(0);b=b.charCodeAt(1);return-671032320===(-67044352&(c<<16|b))?(64+(1023&c)|0)<<10|1023&b:a;default:return a}}\nfunction WL(a){0===(1&a.$j)<<24>>24&&0===(1&a.$j)<<24>>24&&(a.uQ=new Xc(new Int32Array([15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12,24,24,24,26,24,24,24,21,22,24,25,24,20,24,24,9,9,9,9,9,9,9,9,9,9,24,24,25,25,25,24,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,21,24,22,27,23,27,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,21,25,22,25,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,\n15,12,24,26,26,26,26,28,24,27,28,5,29,25,16,28,27,28,25,11,11,27,2,24,24,27,11,5,30,11,11,11,24,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,25,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,25,2,2,2,2,2,2,2,2])),a.$j=(1|a.$j)<<24>>24);return a.uQ}SL.prototype.$classData=q({V0:0},!1,\"java.lang.Character$\",{V0:1,g:1,l:1});var XL;function Pr(){XL||(XL=new SL);return XL}function YL(a){throw new ZL('For input string: \"'+a+'\"');}function $L(){this.wQ=this.xQ=null;this.Ct=0}\n$L.prototype=new p;$L.prototype.constructor=$L;\nfunction aM(a,b){0===(1&a.Ct)<<24>>24&&0===(1&a.Ct)<<24>>24&&(a.xQ=RegExp(\"^[\\\\x00-\\\\x20]*([+-]?(?:NaN|Infinity|(?:\\\\d+\\\\.?\\\\d*|\\\\.\\\\d+)(?:[eE][+-]?\\\\d+)?)[fFdD]?)[\\\\x00-\\\\x20]*$\"),a.Ct=(1|a.Ct)<<24>>24);var c=a.xQ.exec(b);if(null!==c)b=+parseFloat(c[1]);else{0===(2&a.Ct)<<24>>24&&0===(2&a.Ct)<<24>>24&&(a.wQ=RegExp(\"^[\\\\x00-\\\\x20]*([+-]?)0[xX]([0-9A-Fa-f]*)\\\\.?([0-9A-Fa-f]*)[pP]([+-]?\\\\d+)[fFdD]?[\\\\x00-\\\\x20]*$\"),a.Ct=(2|a.Ct)<<24>>24);var d=a.wQ.exec(b);null===d&&YL(b);a=d[1];c=d[2];var e=d[3];d=\nd[4];\"\"===c&&\"\"===e&&YL(b);b=bM(0,c,e,d,15);b=\"-\"===a?-b:b}return b}\nfunction bM(a,b,c,d,e){a=\"\"+b+c;c=-(c.length<<2)|0;for(b=0;;)if(b!==a.length&&48===a.charCodeAt(b))b=1+b|0;else break;a=a.substring(b);if(\"\"===a)return 0;var g=a.length;if(b=g>e){for(var h=!1,k=e;!h&&k!==g;)48!==a.charCodeAt(k)&&(h=!0),k=1+k|0;g=h?\"1\":\"0\";g=a.substring(0,e)+g}else g=a;c=c+(b?(a.length-(1+e|0)|0)<<2:0)|0;e=+parseInt(g,16);d=+parseInt(d,10);c=Eb(d)+c|0;a=c/3|0;d=+Math.pow(2,a);c=+Math.pow(2,c-(a<<1)|0);return e*d*d*c}\nfunction maa(a,b,c){return b!==b?c!==c?0:1:c!==c?-1:b===c?0===b?(a=1/b,a===1/c?0:0>a?-1:1):0:b<c?-1:1}$L.prototype.$classData=q({Y0:0},!1,\"java.lang.Double$\",{Y0:1,g:1,l:1});var cM;function qa(){cM||(cM=new $L);return cM}\nfunction dM(a,b,c,d,e,g){a=eM(\"\"+a+b);b=TH(UH(),c,10)-b.length|0;var h=lg(mg(),g);c=h.W;var k=h.Y;h=k>>20;if(0===h)throw new Yj(\"parseFloatCorrection was given a subnormal mid: \"+g);g=1048575&k;g=ri(Ph(),new ma(c,1048576|g));c=-1075+h|0;0<=b?0<=c?(a=Ki(a,Qi(Ph().mq,b)),b=Oi(g,c),a=fM(a,b)):a=fM(Oi(Ki(a,Qi(Ph().mq,b)),-c|0),g):0<=c?(b=-b|0,b=Oi(Ki(g,Qi(Ph().mq,b)),c),a=fM(a,b)):(a=Oi(a,-c|0),b=-b|0,b=Ki(g,Qi(Ph().mq,b)),a=fM(a,b));return 0>a?d:0<a?e:0===(1&kg(mg(),d))?d:e}\nfunction gM(){this.zQ=null;this.aK=!1}gM.prototype=new p;gM.prototype.constructor=gM;\nfunction hM(a,b){a.aK||a.aK||(a.zQ=RegExp(\"^[\\\\x00-\\\\x20]*([+-]?)(?:(NaN)|(Infinity)|(?:((?:(\\\\d+)(?:\\\\.(\\\\d*))?|\\\\.(\\\\d+))(?:[eE]([+-]?\\\\d+))?)|(0[xX](?:([0-9A-Fa-f]+)(?:\\\\.([0-9A-Fa-f]*))?|\\\\.([0-9A-Fa-f]+))[pP]([+-]?\\\\d+)))[fFdD]?)[\\\\x00-\\\\x20]*$\"),a.aK=!0);a=a.zQ.exec(b);if(null===a)throw new ZL('For input string: \"'+b+'\"');if(void 0!==a[2])b=NaN;else if(void 0!==a[3])b=Infinity;else if(void 0!==a[4]){b=a[5];var c=a[6],d=a[7],e=a[8];b=void 0!==b?b:\"\";c=\"\"+(void 0!==c?c:\"\")+(void 0!==d?d:\"\");e=\nvoid 0!==e?e:\"0\";d=+parseFloat(a[4]);var g=Math.fround(d);if(g===d)b=g;else if(Infinity===g)b=3.4028235677973366E38===d?dM(b,c,e,3.4028234663852886E38,g,3.4028235677973366E38):g;else if(g<d){rg||(rg=new qg);if(g!==g||Infinity===g)var h=g;else-0===g?h=1.401298464324817E-45:(h=kg(mg(),g),h=0<g?1+h|0:-1+h|0,h=jg(mg(),h));var k=(g+h)/2;b=d===k?dM(b,c,e,g,h,k):g}else rg||(rg=new qg),g!==g||-Infinity===g?h=g:0===g?h=-1.401298464324817E-45:(h=kg(mg(),g),h=0<g?-1+h|0:1+h|0,h=jg(mg(),h)),k=(g+h)/2,b=d===k?\ndM(b,c,e,h,g,k):g}else b=a[10],c=a[11],e=a[12],b=void 0!==b?b:\"\",c=\"\"+(void 0!==c?c:\"\")+(void 0!==e?e:\"\"),e=a[13],b=bM(qa(),b,c,e,7),b=Math.fround(b);return\"-\"===a[1]?Math.fround(-b):b}gM.prototype.$classData=q({$0:0},!1,\"java.lang.Float$\",{$0:1,g:1,l:1});var iM;function jM(){iM||(iM=new gM);return iM}function kM(a){throw new ZL('For input string: \"'+a+'\"');}function lM(){}lM.prototype=new p;lM.prototype.constructor=lM;\nfunction TH(a,b,c){a=null===b?0:b.length;(0===a||2>c||36<c)&&kM(b);var d=b.charCodeAt(0),e=45===d,g=e?2147483648:2147483647;d=e||43===d?1:0;d>=b.length&&kM(b);for(var h=0;d!==a;){var k=DH(Pr(),b.charCodeAt(d),c);h=h*c+k;(-1===k||h>g)&&kM(b);d=1+d|0}return e?-h|0:h|0}function nI(a,b){a=b-(1431655765&b>>1)|0;a=(858993459&a)+(858993459&a>>2)|0;return Math.imul(16843009,252645135&(a+(a>>4)|0))>>24}lM.prototype.$classData=q({c1:0},!1,\"java.lang.Integer$\",{c1:1,g:1,l:1});var mM;\nfunction UH(){mM||(mM=new lM);return mM}function nM(a){if(!a.RF){for(var b=[],c=0;2>c;)b.push(null),c=1+c|0;for(;36>=c;){for(var d=pb(2147483647,c),e=c,g=1,h=\"0\";e<=d;)e=Math.imul(e,c),g=1+g|0,h+=\"0\";d=e;e=d>>31;var k=xa(),l=Wh(k,-1,-1,d,e);b.push(new pg(g,new ma(d,e),h,new ma(l,k.Qc)));c=1+c|0}a.QF=b;a.RF=!0}return a.QF}\nfunction oM(a,b,c){var d=(a.RF?a.QF:nM(a))[c],e=d.DQ;a=e.W;e=e.Y;d=d.l1;var g=-2147483648^e,h=\"\",k=b.W;for(b=b.Y;;){var l=k,m=-2147483648^b;if(m===g?(-2147483648^l)>=(-2147483648^a):m>g){l=k;m=xa();b=Wh(m,l,b,a,e);l=m.Qc;var n=65535&b;m=b>>>16|0;var r=65535&a,v=a>>>16|0,x=Math.imul(n,r);r=Math.imul(m,r);n=Math.imul(n,v);x=x+((r+n|0)<<16)|0;Math.imul(b,e);Math.imul(l,a);Math.imul(m,v);k=(k-x|0).toString(c);h=\"\"+d.substring(k.length)+k+h;k=b;b=l}else break}return\"\"+k.toString(c)+h}\nfunction pM(a){throw new ZL('For input string: \"'+a+'\"');}function qM(a,b,c){for(var d=0;a!==b;){var e=DH(Pr(),c.charCodeAt(a),10);-1===e&&pM(c);d=Math.imul(d,10)+e|0;a=1+a|0}return d}function rM(){this.QF=null;this.RF=!1}rM.prototype=new p;rM.prototype.constructor=rM;function sM(a,b,c){return 0!==c?(a=(+(c>>>0)).toString(16),b=(+(b>>>0)).toString(16),a+(\"\"+\"00000000\".substring(b.length)+b)):(+(b>>>0)).toString(16)}rM.prototype.$classData=q({h1:0},!1,\"java.lang.Long$\",{h1:1,g:1,l:1});var tM;\nfunction uM(){tM||(tM=new rM);return tM}function vM(){}vM.prototype=new p;vM.prototype.constructor=vM;function wM(){}wM.prototype=vM.prototype;function PK(a){return a instanceof vM||\"number\"===typeof a||a instanceof ma}function xM(a,b,c,d,e){this.sB=a;this.SF=b;this.tB=c;this.uB=d;this.rB=e}xM.prototype=new p;xM.prototype.constructor=xM;xM.prototype.i=function(a){return a instanceof xM?this.tB===a.tB&&this.uB===a.uB&&this.rB===a.rB&&this.sB===a.sB&&this.SF===a.SF:!1};\nxM.prototype.u=function(){var a=\"\";\"\\x3cjscode\\x3e\"!==this.sB&&(a=\"\"+a+this.sB+\".\");a=\"\"+a+this.SF;null===this.tB?a+=\"(Unknown Source)\":(a=a+\"(\"+this.tB,0<=this.uB&&(a=a+\":\"+this.uB,0<=this.rB&&(a=a+\":\"+this.rB)),a+=\")\");return a};xM.prototype.B=function(){return lb(this.sB)^lb(this.SF)^lb(this.tB)^this.uB^this.rB};var yM=q({t1:0},!1,\"java.lang.StackTraceElement\",{t1:1,g:1,l:1});xM.prototype.$classData=yM;function zM(){}zM.prototype=new p;zM.prototype.constructor=zM;\nfunction AM(a,b,c,d){a=c+d|0;if(0>c||a<c||a>b.a.length)throw b=new tH,yF(b,null,null,!0),b;for(d=\"\";c!==a;)d=\"\"+d+String.fromCharCode(b.a[c]),c=1+c|0;return d}\nfunction jda(a,b){var c=new BM,d=CM();c.wv=null;c.T1=d;c.Gt=\"\";c.gK=!1;if(c.gK)throw new DM;for(var e=0,g=0,h=6,k=0;k!==h;){var l=\"\\\\u%04X\".indexOf(\"%\",k)|0;if(0>l){EM(c,\"\\\\u%04X\".substring(k));break}EM(c,\"\\\\u%04X\".substring(k,l));var m=1+l|0,n=Tj().QQ;n.lastIndex=m;var r=n.exec(\"\\\\u%04X\");if(null===r||(r.index|0)!==m){var v=m===h?37:\"\\\\u%04X\".charCodeAt(m);FM(v)}k=n.lastIndex|0;for(var x=\"\\\\u%04X\".charCodeAt(-1+k|0),A,B=r[2],C=65<=x&&90>=x?256:0,D=B.length,F=0;F!==D;){var I=B.charCodeAt(F);switch(I){case 45:var M=\n1;break;case 35:M=2;break;case 43:M=4;break;case 32:M=8;break;case 48:M=16;break;case 44:M=32;break;case 40:M=64;break;case 60:M=128;break;default:throw new Yj(hc(I));}if(0!==(C&M))throw new GM(String.fromCharCode(I));C|=M;F=1+F|0}A=C;var N=HM(r[3]),P=HM(r[4]);if(-2===N)throw new IM(-2147483648);-2===P&&JM(-2147483648);if(110===x){-1!==P&&JM(P);if(-1!==N)throw new IM(N);0!==A&&KM(A);EM(c,\"\\n\")}else if(37===x){-1!==P&&JM(P);17!==(17&A)&&12!==(12&A)||KM(A);if(0!==(1&A)&&-1===N)throw new LM(\"%\"+r[0]);\n0!==(-2&A)&&MM(37,A,-2);NM(c,A,N,\"%\")}else{var T=0!==(256&A)?65535&(32+x|0):x,Y=Tj().PQ.a[-97+T|0];-1!==Y&&0===(256&A&Y)||FM(x);if(0!==(17&A)&&-1===N)throw new LM(\"%\"+r[0]);17!==(17&A)&&12!==(12&A)||KM(A);-1!==P&&0!==(512&Y)&&JM(P);0!==(A&Y)&&MM(T,A,Y);if(0!==(128&A))var Z=g;else{var S=HM(r[1]);if(-1===S)Z=e=1+e|0;else{if(0>=S)throw new OM(0===S?\"Illegal format argument index \\x3d 0\":\"Format argument index: (not representable as int)\");Z=S}}if(0>=Z||Z>b.a.length)throw new PM(\"%\"+r[0]);g=Z;var ea=\nb.a[-1+Z|0];if(null===ea&&98!==T&&115!==T)QM(c,CM(),A,N,P,\"null\");else{var ia=void 0,X=void 0,sa=void 0,Ja=void 0,Xa=void 0,Fa=c,za=ea,Qa=T,Ma=A,Ga=N,ab=P;switch(Qa){case 98:var Hb=!1===za||null===za?\"false\":\"true\";QM(Fa,CM(),Ma,Ga,ab,Hb);break;case 104:var bc=(+(ib(za)>>>0)).toString(16);QM(Fa,CM(),Ma,Ga,ab,bc);break;case 115:za&&za.$classData&&za.$classData.rb.Zaa?za.Xaa(Fa,(0!==(1&Ma)?1:0)|(0!==(2&Ma)?4:0)|(0!==(256&Ma)?2:0),Ga,ab):(0!==(2&Ma)&&MM(Qa,Ma,2),QM(Fa,0,Ma,Ga,ab,\"\"+za));break;case 99:if(za instanceof\nba)var yb=String.fromCharCode(Ea(za));else{ha(za)||RM(Qa,za);var tb=za|0;if(!(0<=tb&&1114111>=tb))throw new SM(tb);yb=65536>tb?String.fromCharCode(tb):String.fromCharCode(-64+(tb>>10)|55296,56320|1023&tb)}QM(Fa,0,Ma,Ga,-1,yb);break;case 100:if(ha(za))var eb=\"\"+(za|0);else if(za instanceof ma){var kb=Za(za),Rb=kb.W,Gb=kb.Y;eb=bG(xa(),Rb,Gb)}else za instanceof TM||RM(Qa,za),eb=Vh(bi(),za);UM(Fa,Ma,Ga,eb,\"\");break;case 111:case 120:var vb=111===Qa,Tb=0===(2&Ma)?\"\":vb?\"0\":0!==(256&Ma)?\"0X\":\"0x\";if(za instanceof\nTM){var Nb=vb?8:16;CM();var ic=bi(),Va=za.Ya,cb=za.wb,zb=za.Qa,Ub=2>Nb||36<Nb;if(0===Va)Xa=\"0\";else if(1===cb){var jb=zb.a[-1+cb|0],db=0;if(0>Va){var ub=jb,Aa=db;jb=-ub|0;db=0!==ub?~Aa:-Aa|0}var va=uM(),Ra=jb,rb=db;if(10===Nb||2>Nb||36<Nb)Ja=bG(xa(),Ra,rb);else{var xb=new ma(Ra,rb),mc=xb.W,Ha=xb.Y;if(mc>>31===Ha)Ja=mc.toString(Nb);else if(0>Ha){var Ka=xb.W,Oa=xb.Y;Ja=\"-\"+oM(va,new ma(-Ka|0,0!==Ka?~Oa:-Oa|0),Nb)}else Ja=oM(va,xb,Nb)}Xa=Ja}else if(10===Nb||Ub)Xa=Vh(bi(),za);else{var Na=0;Na=+Math.log(Nb)/\n+Math.log(2);var Da=0>Va?1:0,ta=VM(za),Ya=yh(Sh(),ta),dc=1+Eb(Ya/Na+Da)|0,ka=null;ka=\"\";var ya=0;ya=dc;var Sa=0;Sa=0;if(16!==Nb){var xc=new Xc(cb);zb.wa(0,xc,0,cb);var Sb=0;Sb=cb;for(var uc=ic.uH.a[Nb],Lb=ic.tH.a[-2+Nb|0];;){Sa=gi(ei(),xc,xc,Sb,Lb);for(var lc=ya;;){ya=-1+ya|0;Pr();var Xb=Bb(Sa,Nb);if(2>Nb||36<Nb||0>Xb||Xb>=Nb)var ec=0;else{var Ab=-10+Xb|0;ec=65535&(0>Ab?48+Xb|0:97+Ab|0)}ka=\"\"+String.fromCharCode(ec)+ka;Sa=pb(Sa,Nb);if(0===Sa||0===ya)break}for(var Ob=(uc-lc|0)+ya|0,fb=0;fb<Ob&&0<ya;)ya=\n-1+ya|0,ka=\"0\"+ka,fb=1+fb|0;for(fb=-1+Sb|0;0<fb&&0===xc.a[fb];)fb=-1+fb|0;Sb=1+fb|0;if(1===Sb&&0===xc.a[0])break}}else for(var Wa=0;Wa<cb;){for(var bb=Wa,Ia=0;8>Ia&&0<ya;)Sa=15&zb.a[bb]>>(Ia<<2),ya=-1+ya|0,ka=\"\"+(+(Sa>>>0)).toString(16)+ka,Ia=1+Ia|0;Wa=1+Wa|0}for(var Ua=0;;)if(48===ka.charCodeAt(Ua))Ua=1+Ua|0;else break;0!==Ua&&(ka=ka.substring(Ua));Xa=-1===Va?\"-\"+ka:ka}UM(Fa,Ma,Ga,Xa,Tb)}else{if(ha(za))var pc=za|0,sc=vb?(+(pc>>>0)).toString(8):(+(pc>>>0)).toString(16);else{za instanceof ma||RM(Qa,\nza);var Ba=Za(za),ob=Ba.W,nc=Ba.Y;if(vb){uM();var Ib=1073741823&ob,vc=1073741823&((ob>>>30|0)+(nc<<2)|0),Vb=nc>>>28|0;if(0!==Vb){var fc=(+(Vb>>>0)).toString(8),Bc=(+(vc>>>0)).toString(8),Pb=\"0000000000\".substring(Bc.length),Jb=(+(Ib>>>0)).toString(8);sa=fc+(\"\"+Pb+Bc)+(\"\"+\"0000000000\".substring(Jb.length)+Jb)}else if(0!==vc){var gc=(+(vc>>>0)).toString(8),Cb=(+(Ib>>>0)).toString(8);sa=gc+(\"\"+\"0000000000\".substring(Cb.length)+Cb)}else sa=(+(Ib>>>0)).toString(8)}else sa=sM(uM(),ob,nc);sc=sa}0!==(76&\nMa)&&MM(Qa,Ma,76);WM(Fa,CM(),Ma,Ga,Tb,XM(Ma,sc))}break;case 101:case 102:case 103:if(\"number\"===typeof za){var cc=+za;if(cc!==cc||Infinity===cc||-Infinity===cc)YM(Fa,Ma,Ga,cc);else{Tj();if(0===cc)X=new Vj(0>1/cc,\"0\",0);else{var yc=0>cc,Mc=\"\"+(yc?-cc:cc),qc=vH(Mc,101),oc=0>qc?0:parseInt(Mc.substring(1+qc|0))|0,Qc=0>qc?Mc.length:qc,jc=vH(Mc,46);if(0>jc){var sb=Mc.substring(0,Qc);X=new Vj(yc,sb,-oc|0)}else{for(var Gc=\"\"+Mc.substring(0,jc)+Mc.substring(1+jc|0,Qc),Wb=Gc.length,Cc=0;;)if(Cc<Wb&&48===Gc.charCodeAt(Cc))Cc=\n1+Cc|0;else break;var Fc=Gc.substring(Cc);X=new Vj(yc,Fc,(-oc|0)+(Qc-(1+jc|0)|0)|0)}}ZM(Fa,X,Ma,ab,Qa,Ga)}}else if(za instanceof mr){Tj();var qd=$M(za),Yb=Vh(bi(),qd);if(\"0\"===Yb)ia=new Vj(!1,\"0\",0);else{var Nc=45===Yb.charCodeAt(0),ad=Nc?Yb.substring(1):Yb;ia=new Vj(Nc,ad,za.xb)}ZM(Fa,ia,Ma,ab,Qa,Ga)}else RM(Qa,za);break;case 97:if(\"number\"===typeof za){var Uc=+za;if(Uc!==Uc||Infinity===Uc||-Infinity===Uc)YM(Fa,Ma,Ga,Uc);else{var cd=lg(mg(),Uc),kc=cd.W,Vc=cd.Y,Hc=1048575&Vc,rc=2047&(Vc>>>20|0),sd=\n0===ab?1:12<ab?-1:ab,Kc=0>Vc?\"-\":0!==(4&Ma)?\"+\":0!==(8&Ma)?\" \":\"\";if(0===rc)if(0===kc&&0===Hc)var Qd=\"0\",Ad=aa,kd=0;else if(-1===sd)Qd=\"0\",Ad=new ma(kc,Hc),kd=-1022;else{var Hd=-11+(0!==Hc?Math.clz32(Hc):32+Math.clz32(kc)|0)|0;Qd=\"1\";Ad=new ma(0===(32&Hd)?kc<<Hd:0,1048575&(0===(32&Hd)?(kc>>>1|0)>>>(31-Hd|0)|0|Hc<<Hd:kc<<Hd));kd=-1022-Hd|0}else Qd=\"1\",Ad=new ma(kc,Hc),kd=-1023+rc|0;var Rd=Qd,Bd=Za(Ad),ae=kd|0,dd=Za(new ma(Bd.W,Bd.Y)),od=dd.W,Ta=dd.Y;if(-1===sd)var wb=od,$a=Ta;else{var wa=52-(sd<<2)|\n0,hb=0===(32&wa)?1<<wa:0,ra=0===(32&wa)?0:1<<wa,wc=-1+hb|0,ac=-1!==wc?ra:-1+ra|0,Id=hb>>>1|0|ra<<31,ud=ra>>1,be=od&~wc,re=Ta&~ac,pe=od&wc,bd=Ta&ac;if(bd===ud?(-2147483648^pe)<(-2147483648^Id):bd<ud)wb=be,$a=re;else if(bd===ud?(-2147483648^pe)>(-2147483648^Id):bd>ud){var Rc=be+hb|0;wb=Rc;$a=(-2147483648^Rc)<(-2147483648^be)?1+(re+ra|0)|0:re+ra|0}else if(0===(be&hb)&&0===(re&ra))wb=be,$a=re;else{var Wc=be+hb|0;wb=Wc;$a=(-2147483648^Wc)<(-2147483648^be)?1+(re+ra|0)|0:re+ra|0}}var Wd=sM(uM(),wb,$a),zd=\n\"\"+\"0000000000000\".substring(Wd.length)+Wd;Tj();if(13!==zd.length)throw new Yj(\"padded mantissa does not have the right number of bits\");for(var Pa=1>sd?1:sd,Db=zd.length;;)if(Db>Pa&&48===zd.charCodeAt(-1+Db|0))Db=-1+Db|0;else break;var Oc=zd.substring(0,Db),Tc=Kc+(0!==(256&Ma)?\"0X\":\"0x\"),Sd=Rd+\".\"+Oc+\"p\"+ae;WM(Fa,CM(),Ma,Ga,Tc,XM(Ma,Sd))}}else RM(Qa,za);break;default:throw new Yj(\"Unknown conversion '\"+hc(Qa)+\"' was not rejected earlier\");}}}}return c.u()}\nzM.prototype.$classData=q({u1:0},!1,\"java.lang.String$\",{u1:1,g:1,l:1});var aN;function zH(){aN||(aN=new zM);return aN}\nfunction Sda(a,b){bN(a);b(a.u());if(0!==a.my.a.length)for(var c=0;c<a.my.a.length;)b(\"  at \"+a.my.a[c]),c=1+c|0;else b(\"  \\x3cno stack trace available\\x3e\");for(;;)if(a!==a.TF&&null!==a.TF){var d=bN(a);a=a.TF;c=bN(a);var e=c.a.length,g=d.a.length;b(\"Caused by: \"+a);if(0!==e){for(var h=0;;){if(h<e&&h<g){var k=c.a[-1+(e-h|0)|0],l=d.a[-1+(g-h|0)|0];k=null===k?null===l:k.i(l)}else k=!1;if(k)h=1+h|0;else break}0<h&&(h=-1+h|0);d=e-h|0;for(e=0;e<d;)b(\"  at \"+c.a[e]),e=1+e|0;0<h&&b(\"  ... \"+h+\" more\")}else b(\"  \\x3cno stack trace available\\x3e\")}else break}\nfunction yF(a,b,c,d){a.LQ=b;a.TF=c;(a.MQ=d)&&a.pQ()}function vaa(a){var b=ch().HQ;Sda(a,c=>{ff(b,null===c?\"null\":c);ff(b,\"\\n\")})}\nfunction bN(a){if(null===a.my){if(a.MQ){Ug||(Ug=new Tg);var b=Ug;var c=a.KQ;if(c)if(c.arguments&&c.stack)var d=Fg(c);else if(c.stack&&c.sourceURL)d=c.stack.replace(Rg(\"\\\\[native code\\\\]\\\\n\",\"m\"),\"\").replace(Rg(\"^(?\\x3d\\\\w+Error\\\\:).*$\\\\n\",\"m\"),\"\").replace(Rg(\"^@\",\"gm\"),\"{anonymous}()@\").split(\"\\n\");else if(c.stack&&c.number)d=c.stack.replace(Rg(\"^\\\\s*at\\\\s+(.*)$\",\"gm\"),\"$1\").replace(Rg(\"^Anonymous function\\\\s+\",\"gm\"),\"{anonymous}() \").replace(Rg(\"^([^\\\\(]+|\\\\{anonymous\\\\}\\\\(\\\\))\\\\s+\\\\((.+)\\\\)$\",\"gm\"),\n\"$1@$2\").split(\"\\n\").slice(1);else if(c.stack&&c.fileName)d=c.stack.replace(Rg(\"(?:\\\\n@:0)?\\\\s+$\",\"m\"),\"\").replace(Rg(\"^(?:\\\\((\\\\S*)\\\\))?@\",\"gm\"),\"{anonymous}($1)@\").split(\"\\n\");else if(c.message&&c[\"opera#sourceloc\"])if(c.stacktrace)if(-1<c.message.indexOf(\"\\n\")&&c.message.split(\"\\n\").length>c.stacktrace.split(\"\\n\").length)d=Sg(c);else{d=Rg(\"Line (\\\\d+).*script (?:in )?(\\\\S+)(?:: In function (\\\\S+))?$\",\"i\");c=c.stacktrace.split(\"\\n\");var e=[];for(var g=0,h=c.length|0;g<h;){var k=d.exec(c[g]);if(null!==\nk){var l=k[3];e.push((void 0!==l?l:\"{anonymous}\")+\"()@\"+k[2]+\":\"+k[1])}g=2+g|0}d=e}else d=Sg(c);else if(c.message&&c.stack&&c.stacktrace)if(0>c.stacktrace.indexOf(\"called from line\")){d=Gg(\"^(.*)@(.+):(\\\\d+)$\");c=c.stacktrace.split(\"\\n\");e=[];g=0;for(h=c.length|0;g<h;)k=d.exec(c[g]),null!==k&&(l=k[1],e.push((void 0!==l?l+\"()\":\"global code\")+\"@\"+k[2]+\":\"+k[3])),g=1+g|0;d=e}else{d=Gg(\"^.*line (\\\\d+), column (\\\\d+)(?: in (.+))? in (\\\\S+):$\");c=c.stacktrace.split(\"\\n\");e=[];g=0;for(h=c.length|0;g<h;)l=\nd.exec(c[g]),null!==l&&(k=l[4]+\":\"+l[1]+\":\"+l[2],l=l[2],l=(void 0!==l?l:\"global code\").replace(Gg(\"\\x3canonymous function: (\\\\S+)\\x3e\"),\"$1\").replace(Gg(\"\\x3canonymous function\\x3e\"),\"{anonymous}\"),e.push(l+\"@\"+k)|0),g=2+g|0;d=e}else d=c.stack&&!c.fileName?Fg(c):[];else d=[];e=d;g=Gg(\"^([^@]*)@(.*?):([0-9]+)(?::([0-9]+))?$\");d=[];for(c=0;c<(e.length|0);){k=e[c];if(\"\"!==k)if(h=g.exec(k),null!==h){k=b;l=h[1];var m=Gg(\"^(?:Object\\\\.|\\\\[object Object\\\\]\\\\.|Module\\\\.)?\\\\$(?:ps?|s|f)_((?:_[^_]|[^_])+)__([^\\\\.]+)$\"),\nn=Gg(\"^(?:Object\\\\.|\\\\[object Object\\\\]\\\\.|Module\\\\.)?\\\\$ct_((?:_[^_]|[^_])+)__([^\\\\.]*)$\"),r=Gg(\"^new (?:Object\\\\.|\\\\[object Object\\\\]\\\\.|Module\\\\.)?\\\\$c_([^\\\\.]+)$\"),v=Gg(\"^(?:Object\\\\.|\\\\[object Object\\\\]\\\\.|Module\\\\.)?\\\\$m_([^\\\\.]+)$\"),x=Gg(\"^(?:Object\\\\.|\\\\[object Object\\\\]\\\\.|Module\\\\.)?\\\\$[bc]_([^\\\\.]+)(?:\\\\.prototype)?\\\\.([^\\\\.]+)$\").exec(l);m=null!==x?x:m.exec(l);null!==m?(k=sg(k,m[1]),l=m[2],0<=l.length&&\"init___\"===l.substring(0,7)?l=\"\\x3cinit\\x3e\":(v=l.indexOf(\"__\")|0,l=0>v?l:l.substring(0,\nv)),l=[k,l]):(n=n.exec(l),r=null!==n?n:r.exec(l),null!==r?l=[sg(k,r[1]),\"\\x3cinit\\x3e\"]:(v=v.exec(l),l=null!==v?[sg(k,v[1]),\"\\x3cclinit\\x3e\"]:[\"\\x3cjscode\\x3e\",l]));k=l[0];l=l[1];v=h[2];r=parseInt(h[3]);h=h[4];h=void 0!==h?parseInt(h)|0:-1;d.push(new xM(k,l,v,r|0,h))}else d.push(new xM(\"\\x3cjscode\\x3e\",k,null,-1,-1))|0;c=1+c|0}b=d.length|0;e=new (md(yM).Ia)(b);for(c=0;c<b;)e.a[c]=d[c],c=1+c|0;b=e}else b=new (md(yM).Ia)(0);a.my=b}return a.my}\nclass Vd extends Error{constructor(){super();this.TF=this.LQ=null;this.MQ=!1;this.my=this.KQ=null}qj(){return this.LQ}pQ(){var a=this instanceof $d?this.mu:this;this.KQ=\"[object Error]\"===Object.prototype.toString.call(a)?a:void 0===Error.captureStackTrace?Error():(Error.captureStackTrace(this),this)}u(){var a=na(this),b=this.qj();return null===b?a:a+\": \"+b}B(){return gb.prototype.B.call(this)}i(a){return gb.prototype.i.call(this,a)}get message(){var a=this.qj();return null===a?\"\":a}get name(){return na(this)}toString(){return this.u()}}\nfunction cN(){this.mM=this.qH=this.lM=this.lz=this.rH=null;dN=this;eN(0,0);eN(1,0);eN(10,0);this.rH=fN(28,5);for(var a=this.rH.a.length,b=new Xc(a),c=0;c<a;){var d=c;b.a[d]=gN(hN(),hN().rH.a[d]);c=1+c|0}this.lz=fN(19,10);a=this.lz.a.length;b=new Xc(a);for(c=0;c<a;)d=c,b.a[d]=gN(hN(),hN().lz.a[d]),c=1+c|0;a=new (md(iN).Ia)(11);for(b=0;11>b;)c=b,a.a[c]=eN(c,0),b=1+b|0;this.lM=a;a=new (md(iN).Ia)(11);for(b=0;11>b;)c=b,a.a[c]=eN(0,c),b=1+b|0;this.qH=a;this.mM=\"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\"}\ncN.prototype=new p;cN.prototype.constructor=cN;function jN(a,b,c){0===c?(0<=b.Y?(c=b.Y,c=0===c?-2147483637>(-2147483648^b.W):0>c):c=!1,a=c?a.lM.a[b.W]:kN(b,0)):a=0===b.W&&0===b.Y&&0<=c&&c<a.qH.a.length?a.qH.a[c]:kN(b,c);return a}\nfunction fN(a,b){var c=new Zc(a);c.a[0]=new ma(1,0);for(var d=1;d<a;){var e=d,g=c.a[-1+e|0],h=b>>31,k=g.W,l=65535&k,m=k>>>16|0,n=65535&b,r=b>>>16|0,v=Math.imul(l,n);n=Math.imul(m,n);var x=Math.imul(l,r);l=v+((n+x|0)<<16)|0;v=(v>>>16|0)+x|0;g=(((Math.imul(k,h)+Math.imul(g.Y,b)|0)+Math.imul(m,r)|0)+(v>>>16|0)|0)+(((65535&v)+n|0)>>>16|0)|0;c.a[e]=new ma(l,g);d=1+d|0}return c}\nfunction lN(a,b,c,d){a=0>c?-c|0:c;var e=0===c?0:0>c?-1:1;if(Bi().xM===d)return e;if(Bi().sM===d)return 0;if(Bi().rM===d)return 0<e?e:0;if(Bi().tM===d)return 0>e?e:0;if(Bi().vM===d)return 5<=a?e:0;if(Bi().uM===d)return 5<a?e:0;if(Bi().OC===d)return 5<(a+b|0)?e:0;if(Bi().wM===d){if(0===c)return 0;throw new qb(\"Rounding necessary\");}throw new Yj(d);}\nfunction mN(a,b){a=b.Y;(-1===a?0>(-2147483648^b.W):-1>a)?a=!0:(a=b.Y,a=0===a?-1<(-2147483648^b.W):0<a);if(a)throw new qb(\"Out of int range: \"+b);return b.W}function gN(a,b){b=0>b.Y?new ma(~b.W,~b.Y):b;a=b.W;b=b.Y;return 64-(0!==b?Math.clz32(b):32+Math.clz32(a)|0)|0}function nN(a,b,c){return!oN(0,b,c)}function oN(a,b,c){a=c.a.length;for(var d=0;d!==a;){if(c.a[d]===b)return!0;d=1+d|0}return!1}cN.prototype.$classData=q({BT:0},!1,\"java.math.BigDecimal$\",{BT:1,g:1,l:1});var dN;\nfunction hN(){dN||(dN=new cN);return dN}function pN(){this.sH=this.pM=this.MC=this.nq=this.mq=this.Ew=null;qN=this;this.Ew=qi(1,1);this.mq=qi(1,10);this.nq=qi(0,0);this.MC=qi(-1,1);this.pM=new (md(Ji).Ia)([this.nq,this.Ew,qi(1,2),qi(1,3),qi(1,4),qi(1,5),qi(1,6),qi(1,7),qi(1,8),qi(1,9),this.mq]);for(var a=new (md(Ji).Ia)(32),b=0;32>b;){var c=b,d=Ph();a.a[c]=ri(d,new ma(0===(32&c)?1<<c:0,0===(32&c)?0:1<<c));b=1+b|0}this.sH=a}pN.prototype=new p;pN.prototype.constructor=pN;\nfunction ri(a,b){if(0>b.Y)return-1!==b.W||-1!==b.Y?(a=b.W,b=b.Y,rN(-1,new ma(-a|0,0!==a?~b:-b|0))):a.MC;var c=b.Y;return(0===c?-2147483638>=(-2147483648^b.W):0>c)?a.pM.a[b.W]:rN(1,b)}pN.prototype.$classData=q({DT:0},!1,\"java.math.BigInteger$\",{DT:1,g:1,l:1});var qN;function Ph(){qN||(qN=new pN);return qN}\nfunction sN(){this.wM=this.OC=this.uM=this.vM=this.tM=this.rM=this.sM=this.xM=null;tN=this;this.xM=new uN(\"UP\",0);this.sM=new uN(\"DOWN\",1);this.rM=new uN(\"CEILING\",2);this.tM=new uN(\"FLOOR\",3);this.vM=new uN(\"HALF_UP\",4);this.uM=new uN(\"HALF_DOWN\",5);this.OC=new uN(\"HALF_EVEN\",6);this.wM=new uN(\"UNNECESSARY\",7)}sN.prototype=new p;sN.prototype.constructor=sN;sN.prototype.$classData=q({NT:0},!1,\"java.math.RoundingMode$\",{NT:1,g:1,l:1});var tN;function Bi(){tN||(tN=new sN);return tN}function vN(){}\nvN.prototype=new p;vN.prototype.constructor=vN;function wN(){}wN.prototype=vN.prototype;vN.prototype.i=function(a){if(a===this)return!0;if(a&&a.$classData&&a.$classData.rb.SQ&&this.ka()===a.ka()){var b=this.JF().vv();a:{for(;b.s();){var c=b.t(),d=a.LF(c.so());c=c.to();if(null===d?null!==c:!La(d,c)){a=!0;break a}}a=!1}return!a}return!1};vN.prototype.B=function(){for(var a=this.JF().vv(),b=0;a.s();){var c=b;b=a.t();c|=0;b=b.B()+c|0}return b|0};\nvN.prototype.u=function(){for(var a=\"{\",b=!0,c=this.JF().vv();c.s();){var d=c.t();b?b=!1:a+=\", \";a=\"\"+a+d.so()+\"\\x3d\"+d.to()}return a+\"}\"};function xN(){}xN.prototype=new p;xN.prototype.constructor=xN;xN.prototype.Da=function(a,b){return oa(a,b)};xN.prototype.$classData=q({H1:0},!1,\"java.util.Arrays$NaturalComparator$\",{H1:1,g:1,Ji:1});var yN;function ij(){yN||(yN=new xN);return yN}function zN(){}zN.prototype=new ak;zN.prototype.constructor=zN;\nzN.prototype.$classData=q({R1:0},!1,\"java.util.Formatter$RootLocaleInfo$\",{R1:1,$aa:1,g:1});var AN;function CM(){AN||(AN=new zN);return AN}function BN(){this.vB=this.iK=0;this.hK=this.wB=null}BN.prototype=new p;BN.prototype.constructor=BN;function CN(){}CN.prototype=BN.prototype;BN.prototype.s=function(){if(null!==this.wB)return!0;for(;this.vB<this.iK;){var a=this.hK.wl.a[this.vB];this.vB=1+this.vB|0;if(null!==a)return this.wB=a,!0}return!1};\nBN.prototype.t=function(){if(!this.s())throw AH(\"next on empty iterator\");var a=this.wB;this.wB=a.xr;return a};function DN(a,b,c,d,e){this.xB=a;this.oy=b;this.xv=c;this.xr=e}DN.prototype=new p;DN.prototype.constructor=DN;f=DN.prototype;f.so=function(){return this.xB};f.to=function(){return this.xv};f.i=function(a){if(ck(a)){var b=this.xB,c=a.so();if(null===b?null===c:La(b,c))return b=this.xv,a=a.to(),null===b?null===a:La(b,a)}return!1};\nf.B=function(){var a=this.oy,b=this.xv;return a^(a>>>16|0)^(null===b?0:ib(b))};f.u=function(){return this.xB+\"\\x3d\"+this.xv};var EN=q({W1:0},!1,\"java.util.HashMap$Node\",{W1:1,g:1,TQ:1});DN.prototype.$classData=EN;function FN(a){this.kK=null;this.kK=new GN(a.yB.zv)}FN.prototype=new p;FN.prototype.constructor=FN;FN.prototype.s=function(){return this.kK.s()};FN.prototype.t=function(){return new HN(this.kK.t())};\nFN.prototype.$classData=q({$1:0},!1,\"java.util.IdentityHashMap$EntrySet$$anon$2\",{$1:1,g:1,p2:1});function HN(a){this.WF=a}HN.prototype=new p;HN.prototype.constructor=HN;f=HN.prototype;f.i=function(a){return ck(a)?Object.is(this.so(),a.so())?Object.is(this.to(),a.to()):!1:!1};f.so=function(){return this.WF.so().py};f.to=function(){return this.WF.to()};f.B=function(){var a=this.WF.to();return Qb(this.WF.so().py)^Qb(a)};f.u=function(){return this.so()+\"\\x3d\"+this.to()};\nf.$classData=q({b2:0},!1,\"java.util.IdentityHashMap$MapEntry\",{b2:1,g:1,TQ:1});function IN(){}IN.prototype=new p;IN.prototype.constructor=IN;IN.prototype.Qo=function(a,b,c){a.a[b]=c};IN.prototype.Wj=function(a,b){return a.a[b]};IN.prototype.$classData=q({C2:0},!1,\"java.util.internal.GenericArrayOps$ReusableAnyRefArrayOps$\",{C2:1,g:1,zB:1});var JN;function jj(){JN||(JN=new IN);return JN}function KN(a){if(null===a.Bv)throw XH(\"No match available\");return a.Bv}\nfunction cq(a,b){this.lK=a;this.UQ=b;this.VQ=0;this.Av=this.UQ;this.YF=0;this.Bv=null;this.qy=0}cq.prototype=new p;cq.prototype.constructor=cq;function bq(a){a.YF=0;a.Bv=null;a.qy=0;a.Bv=a.lK.fR.exec(a.Av);return null!==a.Bv}function LN(a){var b=a.lK;var c=a.Av;var d=b.sK;d.lastIndex=a.YF;c=d.exec(c);b=b.sK.lastIndex|0;a.YF=null!==c?b===(c.index|0)?1+b|0:b:1+a.Av.length|0;a.Bv=c;return null!==c}function MN(a){return(KN(a).index|0)+a.VQ|0}function NN(a){var b=MN(a);a=KN(a)[0];return b+a.length|0}\ncq.prototype.$classData=q({E2:0},!1,\"java.util.regex.Matcher\",{E2:1,g:1,bba:1});function Fk(a,b,c,d,e,g,h){this.fR=this.sK=null;this.eR=a;this.Q2=d;this.R2=e;this.O2=g;this.P2=h;this.sK=new RegExp(c,this.Q2+(this.R2?\"gy\":\"g\"));this.fR=new RegExp(\"^(?:\"+c+\")$\",d)}Fk.prototype=new p;Fk.prototype.constructor=Fk;Fk.prototype.u=function(){return this.eR};Fk.prototype.$classData=q({F2:0},!1,\"java.util.regex.Pattern\",{F2:1,g:1,l:1});\nvar Uda=function Tda(a){if(a instanceof um){var c=a.Tn;a=Tda(a.Un);return new z(c,a)}if(a instanceof ym)return c=a.dn,a=O().c,new z(c,a);if(zm()===a)return O().c;throw new w(a);},Wda=function Vda(a,b){if(a instanceof um){var d=a.Tn,e=a.Un;return(b?\"\":\"; \")+Zz(a.Xo,!1)+\" \\x3d\\x3e \"+Zz(d,!1)+Vda(e,!1)}if(a instanceof ym)return(b?\"\":\"; \")+\"_ \\x3d\\x3e \"+Zz(a.dn,!1);if(zm()===a)return\"\";throw new w(a);},Yda=function Xda(a,b){if(a instanceof um){var d=a.Xo,e=a.Tn;a=a.Un;return\"\"+ON(b)+aA(d,!1,b)+\" \\x3d\\x3e \"+\naA(e,!1,b)+Xda(a,b)}if(a instanceof ym)return d=a.dn,ON(b)+\"_ \\x3d\\x3e \"+aA(d,!1,b);if(zm()===a)return\"\";throw new w(a);};function Kca(a){return!!(a&&a.$classData&&a.$classData.rb.AM)}function PN(a){this.ob=null;if(null===a)throw null;this.ob=new QN(a,ap(),ap())}PN.prototype=new p;PN.prototype.constructor=PN;PN.prototype.$classData=q({BU:0},!1,\"mlscript.ConstraintSolver$Shadows$\",{BU:1,g:1,l:1});function RN(){this.ld=null}RN.prototype=new kz;RN.prototype.constructor=RN;function SN(){}\nSN.prototype=RN.prototype;function TN(){}TN.prototype=new p;TN.prototype.constructor=TN;function kr(a,b,c,d){return new Ff(UN(b.e().h(),c),b,d)}TN.prototype.$classData=q({PU:0},!1,\"mlscript.ErrorReport$\",{PU:1,g:1,l:1});var VN;function jr(){VN||(VN=new TN);return VN}function WN(){this.Cg=null;XN=this;this.Cg=new St(!1,!1,!1)}WN.prototype=new p;WN.prototype.constructor=WN;WN.prototype.$classData=q({UU:0},!1,\"mlscript.FldFlags$\",{UU:1,g:1,l:1});var XN;function tm(){XN||(XN=new WN);return XN}\nfunction Zda(a){if(a instanceof $t){var b=a.ap,c=k=>{if(k instanceof Ud)k=k.fa;else{if(!(k instanceof fe))throw new w(k);k=k.aa}return k};if(b===u())return u();a=b.e();var d=a=new z(c(a),u());for(b=b.f();b!==u();){var e=b.e();e=new z(c(e),u());d=d.p=e;b=b.f()}return a}if(a instanceof Ut)return c=a.Km,a=a.Lm,d=O().c,new z(c,new z(a,d));if(a instanceof gu)return c=a.ws,a=O().c,new z(c,a);if(a instanceof Ss)return c=a.xu,d=a.yu,a=a.wu,b=O().c,new z(c,new z(d,new z(a,b)));if(a instanceof Tt)return c=\na.Wn,d=a.Xn,a=a.Yn,b=O().c,new z(c,new z(d,new z(a,b)));if(a instanceof mu){c=a.xs;a=a.ys;for(b=d=null;a!==u();){var g=a.e();e=g.h();g=g.j();var h=O().c;for(e=new Om(new z(e,new z(g,h)));e.s();)g=new z(e.t(),u()),null===b?d=g:b.p=g,b=g;a=a.f()}a=null===d?u():d;return new z(c,a)}throw new w(a);}\nvar $da=function YN(a){if(a instanceof Ut){var c=a.Lm;return\"(\"+Zz(a.Km,!1)+\") then \"+Zz(c,!1)}if(a instanceof gu)return\"else \"+Zz(a.ws,!1);if(a instanceof $t)return a=a.ap.m(),a=new Ef(a,new y(e=>{if(e instanceof Ud)return e.fa.Wr();if(!(e instanceof fe))throw new w(e);return YN(e.aa)})),\"\\u2039\"+ze(a,\"\",\"; \",\"\")+\"\\u203a\";if(a instanceof Tt){c=a.Xn;var d=a.Yn;return Zz(a.Wn,!1)+\" \"+Zz(c,!1)+\" \"+YN(d)}if(a instanceof mu)return c=a.ys,a=Zz(a.xs,!1),c=c.m(),c=new Ef(c,new y(e=>{if(null!==e){var g=e.j();\nreturn\"\\u00b7 \"+Zz(e.h(),!1)+\" \"+YN(g)}throw new w(e);})),a+\" \\u2039\"+ze(c,\"\",\"; \",\"\")+\"\\u203a\";if(a instanceof Ss)return c=a.yu,d=a.wu,(a.Qw?\"rec \":\"\")+\"let \"+Zz(a.xu,!1)+\" \\x3d \"+Zz(c,!1)+\" in \"+YN(d);throw new w(a);},aea=function ZN(a,b){if(a instanceof Ut){var d=a.Km;a=a.Lm;return aA(d,!(d instanceof wm),b)+\" then \"+aA(a,!1,b)}if(a instanceof gu)return\"else \"+aA(a.ws,!1,b);if(a instanceof $t){var e=a.ap;a=k=>{if(k instanceof Ud)k=k.fa;else{if(!(k instanceof fe))throw new w(k);k=k.aa}return k};\nif(e===u())a=u();else{d=e.e();var g=d=new z(a(d),u());for(e=e.f();e!==u();){var h=e.e();h=new z(a(h),u());g=g.p=h;e=e.f()}a=d}b=ON(b);return\"\"+ze(a,\"\",b,\"\")}if(a instanceof Tt)return d=a.Xn,g=a.Yn,aA(a.Wn,!1,b)+\" \"+aA(d,!1,b)+\" \"+ZN(g,b);if(a instanceof mu)return d=a.ys,a=aA(a.xs,!1,b),d=d.m(),d=new Ef(d,new y(k=>{if(null!==k)return\"\\u00b7 \"+k.h()+\" \"+k.j();throw new w(k);})),b=ON(b),a+\" \"+ze(d,\"\",b,\"\");if(a instanceof Ss)return d=a.yu,g=a.wu,(a.Qw?\"rec \":\"\")+\"let \"+aA(a.xu,!1,b)+\" \\x3d \"+aA(d,!1,\nb)+\" in \"+ZN(g,b);throw new w(a);};function $N(){this.gD=null;aO=this;this.gD=bO().Ht()}$N.prototype=new p;$N.prototype.constructor=$N;\nfunction bO(){return Dz(Ez(),J(new K,[G(new H,\"**\",14),G(new H,\"*\",13),G(new H,\"/\",13),G(new H,\"%\",13),G(new H,\"+\",12),G(new H,\"-\",12),G(new H,\"\\x3c\\x3c\",11),G(new H,\"\\x3e\\x3e\",11),G(new H,\"\\x3e\\x3e\\x3e\",11),G(new H,\"\\x3c\",10),G(new H,\"\\x3c\\x3d\",10),G(new H,\"\\x3e\",10),G(new H,\"\\x3e\\x3d\",10),G(new H,\"in\",10),G(new H,\"instanceof\",10),G(new H,\"\\x3d\\x3d\",9),G(new H,\"!\\x3d\",9),G(new H,\"\\x3d\\x3d\\x3d\",9),G(new H,\"!\\x3d\\x3d\",9),G(new H,\"\\x26\",8),G(new H,\"^\",7),G(new H,\"|\",6),G(new H,\"\\x26\\x26\",5),G(new H,\n\"||\",4),G(new H,\"??\",4),G(new H,\",\",1)]))}$N.prototype.$classData=q({AV:0},!1,\"mlscript.JSBinary$\",{AV:1,g:1,l:1});var aO;function Lm(){aO||(aO=new $N);return aO}function cO(){this.Az=2}cO.prototype=new p;cO.prototype.constructor=cO;cO.prototype.$classData=q({JV:0},!1,\"mlscript.JSCommaExpr$\",{JV:1,g:1,l:1});var dO;function Vp(){dO||(dO=new cO);return dO}function eO(){}eO.prototype=new Jp;eO.prototype.constructor=eO;function fO(){}fO.prototype=eO.prototype;eO.prototype.VJ=function(){return!1};\nfunction rn(a){return new Io((t(),new L(a)))}function zz(a,b){return new Bo(new Lo(a,b))}function Tba(a,b,c){c=c.Ja(new y(d=>{if(null!==d)return new gO(d.h(),d.j());throw new w(d);})).ha();t();return new hO(a,c,new L(new iO(b)))}function Up(a,b){return a.sh()<b?Pp(a.xa(),!0):a.xa()}function jO(){}jO.prototype=new p;jO.prototype.constructor=jO;\nfunction Ko(a){var b=g=>{var h=t().d;return G(new H,g,h)};if(a===u())b=u();else{var c=a.e(),d=c=new z(b(c),u());for(a=a.f();a!==u();){var e=a.e();e=new z(b(e),u());d=d.p=e;a=a.f()}b=c}return new Eo(b)}jO.prototype.$classData=q({ZV:0},!1,\"mlscript.JSLetDecl$\",{ZV:1,g:1,l:1});var kO;function Jo(){kO||(kO=new jO)}function lO(){}lO.prototype=new p;lO.prototype.constructor=lO;\nfunction Mp(a,b){a=b.length;for(var c=new zc(a),d=0;d<a;){var e=d,g=b.charCodeAt(d);switch(g){case 34:g='\\\\\"';break;case 92:g=\"\\\\\\\\\";break;case 8:g=\"\\\\b\";break;case 12:g=\"\\\\f\";break;case 10:g=\"\\\\n\";break;case 13:g=\"\\\\r\";break;case 9:g=\"\\\\t\";break;default:g=0<g&&255>=g&&!us(Pr(),g)?String.fromCharCode(g):ida(Q(),J(new K,[g]))}c.a[e]=g;d=1+d|0}return ze(new Fu(c),'\"',\"\",'\"')}lO.prototype.$classData=q({aW:0},!1,\"mlscript.JSLit$\",{aW:1,g:1,l:1});var mO;function Np(){mO||(mO=new lO);return mO}\nfunction nO(){}nO.prototype=new Jp;nO.prototype.constructor=nO;function oO(){}oO.prototype=nO.prototype;function pO(){}pO.prototype=new Jp;pO.prototype.constructor=pO;function qO(){}qO.prototype=pO.prototype;\nfunction Af(){this.CH=this.DH=this.Cs=this.di=null;eE();var a=new iE;fE(a,t().d);t();var b=J(new K,\"true false NaN id emptyArray succ error length concat join add sub mul div gt not ne eq sgt slt sge sle typeof toString String negate eq unit log run Const freshName Lam Var App IntLit StrLit DecLit UnitLit Rcd Bra Sel Blk Tup Fld Let Subs With Quoted CaseOf Case Wildcard NoCases discard window\".split(\" \"));for(b=Pd(u(),b);!b.b();){var c=b.e();vp(a,new go(c,c));b=b.f()}b=new nn(\"anything\",O().c,gl());\na.ko.bj(b.er,b);b=new nn(\"nothing\",O().c,el());a.ko.bj(b.er,b);t();b=J(new K,[\"int\",\"number\",\"bool\",\"string\",\"unit\"]);for(b=Pd(u(),b);!b.b();)c=b.e(),c=new nn(c,O().c,new Ep(c)),a.ko.bj(c.er,c),b=b.f();b=new mn(\"Annotation\",\"Annotation\",O().c,new Tn(O().c),O().c);yp(a,b);this.di=a;this.Cs=(Cz(),new oz);this.DH=Uo(this.di,\"results\");this.CH=Uo(this.di,\"prettyPrint\");ho(this.Cs,\"prettyPrint\",this.CH)}Af.prototype=new eo;Af.prototype.constructor=Af;\nfunction taa(a,b){var c=b.Xz;Od();var d=new fp;Od();for(var e=new fp,g=c;!g.b();){var h=g.e();if(h&&h.$classData&&h.$classData.rb.ce){var k=h;t();var l=new Ud(k)}else if(h instanceof Zn){var m=h;t();l=new Ud(m)}else{h instanceof yo||xm(\"Program reached and unexpected state.\");var n=h;t();l=new fe(n)}if(l instanceof fe)wp(d,l.aa);else if(l instanceof Ud)wp(e,l.fa);else throw new w(l);g=g.f()}var r=d.ha(),v=e.ha(),x=a.di,A=O().c,B=dE(x,\"TypingUnit\");Od();var C=new fp;Od();for(var D=new fp,F=A;!F.b();){var I=\nF.e();a:{if(I instanceof Zn){var M=I,N=M.wd,P=M.Rb,T=M.Ch,Y=M.Yc;if(null!==P){var Z=P.x;if(Y instanceof fe){var S=Y.aa;if(N.b()||(N.b()?0:N.o())){O();var ea=new Dp(!(N.b()||!N.o()),new Ep(B),new vl(Z),T,(O(),new fe(S)));var ia=new fe(ea);break a}}}}O();ia=new Ud(I)}if(ia instanceof fe)wp(C,ia.aa);else if(ia instanceof Ud)wp(D,ia.fa);else throw new w(ia);F=F.f()}var X=C.ha(),sa=D.ha();Od();var Ja=new fp;Od();for(var Xa=new fp,Fa=sa;!Fa.b();){var za=Fa.e();a:{if(za instanceof Zn){var Qa=za,Ma=Qa.wd,\nGa=Qa.Rb,ab=Qa.Ch,Hb=Qa.Yc;if(null!==Ga){var bc=Ga.x;if(Hb instanceof Ud){var yb=Hb.fa;if(Ma.b()||(Ma.b()?0:Ma.o())){O();var tb=new Dp(!(Ma.b()||!Ma.o()),new Ep(B),new vl(bc),ab,(O(),new Ud(yb)));var eb=new fe(tb);break a}}}}O();eb=new Ud(za)}if(eb instanceof fe)wp(Ja,eb.aa);else if(eb instanceof Ud)wp(Xa,eb.fa);else throw new w(eb);Fa=Fa.f()}var kb=Ja.ha(),Rb=Xa.ha(),Gb=new ln(B,O().c,new Tn(O().c),X,kb,Rb,O().c,r,t().d);yp(x,Gb);var vb=Im(a.di,\"typing_unit\",new L(!1),!1,t().d),Tb=a.di,Nb=Go(a,Gb,\nt().d,!0,Tb),ic=new qn(vb.re,new $m(new km(Gb.lj))),Va=r;a:for(var cb;;)if(Va.b()){cb=u();break}else{var zb=Va.e(),Ub=Va.f();if(!1===!!zb.fl.b())Va=Ub;else for(var jb=Va,db=Ub;;){if(db.b())cb=jb;else{if(!1!==!!db.e().fl.b()){db=db.f();continue}for(var ub=db,Aa=new z(jb.e(),u()),va=jb.f(),Ra=Aa;va!==ub;){var rb=new z(va.e(),u());Ra=Ra.p=rb;va=va.f()}for(var xb=ub.f(),mc=xb;!xb.b();){if(!1===!!xb.e().fl.b()){for(;mc!==xb;){var Ha=new z(mc.e(),u());Ra=Ra.p=Ha;mc=mc.f()}mc=xb.f()}xb=xb.f()}mc.b()||(Ra.p=\nmc);cb=Aa}break a}}if(cb===u())var Ka=u();else{for(var Oa=cb.e(),Na=new z(bp(Oa,vb.re),u()),Da=Na,ta=cb.f();ta!==u();){var Ya=ta.e(),dc=new z(bp(Ya,vb.re),u());Da=Da.p=dc;ta=ta.f()}Ka=Na}for(var ka=new km(a.DH),ya=u(),Sa=ep(new fp,ya),xc=new qn(a.DH,new Wo(O().c)),Sb=new z(Nb,new z(ic,Ka)),uc=v,Lb=null,lc=null;uc!==u();){var Xb=uc.e(),ec=!1,Ab=null;a:{if(Xb instanceof Zn){ec=!0;Ab=Xb;var Ob=Ab.wd,fb=Ab.Rb,Wa=Ab.hj,bb=Ab.Yc;if(null!==fb){var Ia=fb.x;if(bb instanceof fe){var Ua=bb.aa,pc=!(!Ob.b()&&\n!Ob.o()),sc=Ob.b();if(Wa.b())var Ba=R();else{var ob=Wa.o();Ba=new L(ob.x)}if(pc){var nc=sc?R():new L(!0),Ib=Im(a.di,Ia,nc,Co(new Do(a,Ua)),t().d),vc=Zm(a,Ua,a.di),Vb=a.di,fc=Ib;Vb.ko.JB(fc.jJ);Vb.Ip.IB(fc.re);var Bc=sc?R():new L(!1),Pb=Im(a.di,Ia,Bc,Co(new Do(a,Ua)),Ba),Jb=vc,gc=Pb}else{var Cb=Zm(a,Ua,a.di),cc=sc?R():new L(!1),yc=Im(a.di,Ia,cc,Co(new Do(a,Ua)),Ba);Jb=Cb;gc=yc}var Mc=Jb,qc=gc,oc=qc.hJ.b()&&!qc.iJ?new oo(O().c,(t(),new fe(Mc))):Mc;wp(Sa,qc.re);var Qc=a.di.lo,jc=new qn(qc.re,oc),sb=\nom(Al(),ka,\"push\"),Gc=new km(qc.re),Wb=O().c,Cc=new Bo(new cn(sb,new z(Gc,Wb))),Fc=O().c;var qd=Qo(Qc,new z(jc,new z(Cc,Fc)));break a}}}if(ec){var Yb=Ab.Yc;if(null!==Ab.Rb&&Yb instanceof Ud){qd=O().c;break a}}if(Xb instanceof No||Xb instanceof Oo||Xb instanceof Po)throw new gm(\"Def and TypeDef are not supported in NewDef files.\");if(Xb instanceof Pm){var Nc=Xb,ad=Zm(a,Nc,a.di),Uc=Nc,cd=wf(vf(),O().c,!0,\"'\");var kc=aA(Uc,!1,cd);wp(Sa,kc);var Vc=a.di.lo,Hc=om(Al(),ka,\"push\"),rc=O().c,sd=new Bo(new cn(Hc,\nnew z(ad,rc))),Kc=O().c;qd=Qo(Vc,new z(sd,Kc))}else throw new w(Xb);}for(var Qd=qd.m();Qd.s();){var Ad=new z(Qd.t(),u());null===lc?Lb=Ad:lc.p=Ad;lc=Ad}uc=uc.f()}var kd=null===Lb?u():Lb,Hd=un(Sb,kd),Rd=new z(xc,Hd),Bd=om(Al(),ka,\"map\"),ae=J(new K,[new km(a.CH)]),dd=rn(new cn(Bd,(Od(),Pd(u(),ae)))),od=O().c,Ta=new z(dd,od),wb=t().d,$a=O().c;t();for(var wa,hb=a.Cs,ra=hb.Yz,wc=rO().Eb(),ac=ra.m();ac.s();){var Id=ac.t();if(null===Id)throw new w(Id);var ud=Id.h(),be=Id.j();if(hb.aI.L(ud))var re=t().d;else{var pe=\nCz().PN.U(ud);if(pe instanceof L){var bd=pe.k;hb.aI.oh(ud);t();var Rc=bd.dQ(be);re=new L(Rc)}else{if(t().d!==pe)throw new w(pe);re=t().d}}wc.zc(re)}wa=wc.Kb().ha();var Wc=dl(dl(Ta,Rd),wa),Wd=new H;var zd=(new dn(wb,$a,new Ud(Wc),O().c)).xa().$f;if(zd===u())var Pa=u();else{for(var Db=zd.e(),Oc=new z(Db.u(),u()),Tc=Oc,Sd=zd.f();Sd!==u();){var Jc=Sd.e(),vd=new z(Jc.u(),u());Tc=Tc.p=vd;Sd=Sd.f()}Pa=Oc}return G(Wd,Pa,Sa.ha())}Af.prototype.$classData=q({nW:0},!1,\"mlscript.JSWebBackend\",{nW:1,Baa:1,g:1});\nfunction sO(){}sO.prototype=new p;sO.prototype.constructor=sO;function du(a,b){a=b.m();t();for(b=R();a.s();){var c=b;b=a.t();c.b()?b=b.A():(b=Kt(c.o(),b.A()),b=it().n(b))}return b}sO.prototype.$classData=q({wW:0},!1,\"mlscript.Loc$\",{wW:1,g:1,l:1});var tO;function cu(){tO||(tO=new sO);return tO}function uO(){}uO.prototype=new p;uO.prototype.constructor=uO;function uaa(a){vf();a=a.m();return wf(0,new xo(a,new y(b=>Wn(b.fp,new vO(b)))),!0,\"?\")}\nfunction wO(a,b){a=new xO(b);b=O().c;return new $q(new z(a,b))}function We(a,b){a=new Vq(b);b=O().c;return new $q(new z(a,b))}uO.prototype.$classData=q({yW:0},!1,\"mlscript.Message$\",{yW:1,g:1,l:1});var yO;function Xe(){yO||(yO=new uO);return yO}function Ft(a,b,c,d){this.Lz=this.mE=this.dx=this.lE=this.ex=null;this.hx=!1;this.Fu=null;this.Eu=!1;this.jE=this.kE=null;this.le=this.fx=0;this.gx=this.Ol=null;this.Kz=!1;this.wN=null;if(null===a)throw null;this.wN=a;lt(this,a.mE,b,a.hx,a.Fu,a.Eu,c,d)}\nFt.prototype=new ot;Ft.prototype.constructor=Ft;Ft.prototype.nQ=function(a){Ds(this.wN,new U(()=>\"\\x3e \"+Es(a)))};Ft.prototype.$classData=q({RW:0},!1,\"mlscript.NewParser$$anon$1\",{RW:1,PW:1,g:1});function rt(a){this.gj=this.KH=null;if(null===a)throw null;this.gj=a;this.KH=new zO(a,nf())}rt.prototype=new p;rt.prototype.constructor=rt;\nrt.prototype.HC=function(){var a;a:for(a=this.gj.gx;;){var b=!1,c=null,d=Me(this.gj,new Ne(271),new Oe(\"go\"));if(d instanceof z){b=!0;c=d;var e=c.z;if(null!==e){var g=e.h();e=e.j();if(g instanceof as&&(g=g.Na,a.Nl.L(g))){d=this.gj;b=new Te(new Ue(J(new K,[\"Repeated modifier `\",\"`\"])));c=[We(Xe(),g)];b=Ye(b,J(new K,c));t();b=G(new H,b,new L(e));c=O().c;Ze(d,new z(b,c));Ps(this.gj,new Ne(274),new Oe(\"go\"));Os(this.gj);continue}}}if(b&&(g=c.z,null!==g&&(e=g.h(),g=g.j(),e instanceof as&&\"declare\"===e.Na))){Ps(this.gj,\nnew Ne(278),new Oe(\"go\"));Os(this.gj);d=a;a=a.Nl.Pn(G(new H,\"declare\",g));a=new zO(d.vq,a);continue}if(b&&(g=c.z,null!==g&&(e=g.h(),g=g.j(),e instanceof as&&\"virtual\"===e.Na))){Ps(this.gj,new Ne(282),new Oe(\"go\"));Os(this.gj);d=a;a=a.Nl.Pn(G(new H,\"virtual\",g));a=new zO(d.vq,a);continue}if(b&&(g=c.z,null!==g&&(e=g.h(),g=g.j(),e instanceof as&&\"mut\"===e.Na))){Ps(this.gj,new Ne(286),new Oe(\"go\"));Os(this.gj);d=a;a=a.Nl.Pn(G(new H,\"mut\",g));a=new zO(d.vq,a);continue}if(b&&(g=c.z,null!==g&&(e=g.h(),g=\ng.j(),e instanceof as&&\"abstract\"===e.Na))){Ps(this.gj,new Ne(290),new Oe(\"go\"));Os(this.gj);d=a;a=a.Nl.Pn(G(new H,\"abstract\",g));a=new zO(d.vq,a);continue}if(a.Nl.b())break a;if(b&&(e=c.z,null!==e&&(e=e.h(),e instanceof as&&(e=e.Na,\"class\"===e||\"infce\"===e||\"trait\"===e||\"mixin\"===e||\"type\"===e||\"namespace\"===e||\"module\"===e||\"fun\"===e||\"val\"===e||\"let\"===e))))break a;if(b&&(b=c.z,null!==b)){c=b.h();b=b.j();d=this.gj;e=new Te(new Ue(J(new K,[\"Unexpected \",\" token after modifier\",\"\"])));c=[We(Xe(),\nc.jb()),0<a.Nl.$k(1)?We(Xe(),\"s\"):We(Xe(),\"\")];c=Ye(e,J(new K,c));t();b=G(new H,c,new L(b));c=O().c;Ze(d,new z(b,c));break a}a=O().c;(null===a?null===d:a.i(d))&&no();throw new w(d);}this.gj.gx=a;t();a=G(new H,a,this.gj.Ol);return new L(a)};rt.prototype.$classData=q({TW:0},!1,\"mlscript.NewParser$ModifierSet$\",{TW:1,g:1,l:1});function AO(a){this.Zf=null;if(null===a)throw null;this.Zf=a}AO.prototype=new p;AO.prototype.constructor=AO;\nfunction BO(a,b){var c=a.Zf,d=a.Zf,e=uv(),g=Su(),h=op().ga;e=e.ng(new Uu(g,h));a=Vu(a.Zf);g=uv();h=Su();var k=op().ga;b=new CO(d,b,e,a,g.ng(new Uu(h,k)));d=O().c;return new DO(c,new z(b,d))}function bea(a,b){var c=a.Zf;b=b.Ba.m();b=new Ef(b,new y(d=>{var e=a.Zf;d=new iw(a.Zf,d.h(),d.j());var g=uv(),h=Su(),k=op().ga;g=g.ng(new Uu(h,k));h=Vu(a.Zf);k=uv();var l=Su(),m=op().ga;return new CO(e,d,g,h,k.ng(new Uu(l,m)))}));Od();return new DO(c,Pd(u(),b))}\nfunction EO(a,b){return b?new DO(a.Zf,O().c):BO(a,lw(a.Zf))}\nfunction FO(a,b,c,d,e,g,h,k,l){for(;;){var m=!1,n=null,r=d;if(r instanceof Fv){a:{var v=a,x=r,A=tc();try{var B=GO(v.Zf),C=zw(lw(v.Zf),x);if(C.b())throw Hq(new Iq,A,EO(GO(v.Zf),!0));var D=BO(B,C.o())}catch(Cc){if(Cc instanceof Iq){var F=Cc;if(F.Qg===A){D=F.Cj();break a}throw F;}throw Cc;}}return D}if(r instanceof Gv){var I=r,M=a.Zf,N=O().c,P=new z(I,N),T=t().d,Y=sv(),Z=Su(),S=op().ga;return BO(a,new jw(M,P,T,Y.Hd(new Uu(Z,S))))}if(r instanceof Qv)return bea(a,r);if(r instanceof FA)return EO(a,!r.Eh);\nif(r instanceof LA){var ea=r,ia=ea.jc,X=ea.tc,sa=FO(a,b,c,ea.ic,e,g,h,k,l),Ja=FO(a,b,c,ia,e,g,h,k,l);if(X){var Xa=sa,Fa=X,za=g,Qa=k,Ma=Ja.wq;if(Ma===u())var Ga=u();else{for(var ab=Ma.e(),Hb=new z(HO(Xa,ab,Fa,za,Qa),u()),bc=Hb,yb=Ma.f();yb!==u();){var tb=yb.e(),eb=new z(HO(Xa,tb,Fa,za,Qa),u());bc=bc.p=eb;yb=yb.f()}Ga=Hb}for(var kb=EO(GO(Xa.ix),!1),Rb=Ga;!Rb.b();){var Gb=kb,vb=Rb.e();kb=IO(Gb,vb);Rb=Rb.f()}var Tb=kb}else Tb=IO(sa,Ja);return Tb}if(r instanceof MA){var Nb=r.Fc,ic=a.Zf,Va=yB(xB(a.Zf),\nb,c,Nb,!e,g,h,k,l).xe;if(Va===u())var cb=u();else{for(var zb=Va.e(),Ub=new z(new CO(zb.zb,zb.Of,zb.Af,zb.Nf,zb.Pf),u()),jb=Ub,db=Va.f();db!==u();){var ub=db.e(),Aa=new z(new CO(ub.zb,ub.Of,ub.Af,ub.Nf,ub.Pf),u());jb=jb.p=Aa;db=db.f()}cb=Ub}return new DO(ic,cb)}if(r instanceof lx){m=!0;n=r;iC(a.Zf);var va=n.Sb;if(!va.b()){var Ra=va.o();if(!vD(h)&&!l.L(n)){var rb=l.bc(n),xb=b,mc=c,Ha=rb;return FO(GO(a.Zf),xb,mc,Ra,e,g,h,k,Ha)}}}if(m){uv();var Ka=n,Oa=Su(),Na=op().ga,Da=void 0,ta=void 0,Ya=vv(Ka,new Uu(Oa,\nNa)),dc=a.Zf,ka=a.Zf;null===ka.Bq&&null===ka.Bq&&(ka.Bq=new JO(ka));ta=ka.Bq;var ya=ta.oE,Sa=lw(ta.oE),xc=Vu(ta.oE),Sb=uv(),uc=Su(),Lb=op().ga;Da=new CO(ya,Sa,Ya,xc,Sb.ng(new Uu(uc,Lb)));var lc=O().c;return new DO(dc,new z(Da,lc))}if(r instanceof ZB){var Xb=r;$B(a.Zf);t();var ec=Xb.mc(),Ab=new L(ec);if(!Ab.b()){d=Ab.k;continue}}if(r instanceof fw){var Ob=r,fb=Ob.qb;if(vD(h)&&!a.Zf.cn.L(fb.V)||!PA(Ob,g)){var Wa=a.Zf,bb=a.Zf,Ia=a.Zf,Ua=O().c,pc=t().d;sv();var sc=G(new H,fb,Ob),Ba=Su(),ob=op().ga,nc=\nnew jw(Ia,Ua,pc,$v(sc,new Uu(Ba,ob))),Ib=uv(),vc=Su(),Vb=op().ga,fc=Ib.ng(new Uu(vc,Vb)),Bc=Vu(a.Zf),Pb=uv(),Jb=Su(),gc=op().ga,Cb=new CO(bb,nc,fc,Bc,Pb.ng(new Uu(Jb,gc))),cc=O().c;return new DO(Wa,new z(Cb,cc))}d=QA(Ob,g)}else if(r instanceof cC){var yc=r,Mc=yc.Fg,qc=yc.Sf;d=e?qc:Mc}else if(r instanceof Qx){var oc=r,Qc=oc.Re;b=oc.de;d=Qc}else if(r instanceof eC){var jc=r,sb=jc.kj,Gc=g.da,Wb=dl(c,jc.Lj);b=Gc;c=Wb;d=sb}else throw new w(r);}}\nAO.prototype.$classData=q({XW:0},!1,\"mlscript.NormalForms$CNF$\",{XW:1,g:1,l:1});function KO(a){this.xq=this.nE=null;if(null===a)throw null;this.xq=a}KO.prototype=new p;KO.prototype.constructor=KO;function ZA(a){null===a.nE&&null===a.nE&&(a.nE=new LO(a));return a.nE}KO.prototype.$classData=q({ZW:0},!1,\"mlscript.NormalForms$Conjunct$\",{ZW:1,g:1,l:1});\nvar dea=function cea(a,b,c,d,e,g,h){if(Pe(new E(c),d))return UA(d,b,!1,new fn((l,m)=>cea(a,l,m,d,e,g,h)),e);if(b instanceof L)return MO(a,g,h,c,!!b.k,e,!0,!1);if(t().d===b)return dw(cw(a.Bf),MO(a,g,h,c,!1,e,!0,!1),MO(a,g,h,c,!0,e,!0,!1),ew(cw(a.Bf)),e);throw new w(b);};function NO(a){this.Bf=null;if(null===a)throw null;this.Bf=a}NO.prototype=new p;NO.prototype.constructor=NO;\nfunction OO(a,b,c,d){var e=a.Bf,g=uv(),h=Su(),k=op().ga;g=g.ng(new Uu(h,k));h=lw(a.Bf);k=uv();var l=Su(),m=op().ga;d=new PO(e,d,g,h,k.ng(new Uu(l,m)));e=O().c;return QO(a,b,c,new z(d,e))}function QO(a,b,c,d){a=new RO(a.Bf,b,c,d);0===(4&a.Nm)<<24>>24&&0===(4&a.Nm)<<24>>24&&(a.zN=qB(a)?a.fb:a.Ea(),a.Nm=(4|a.Nm)<<24>>24);c=a.zN;return c<b?new RO(a.Gj,c,a.Qf,a.xe):a}function SO(a,b){return b?OO(a,a.Bf.Gd,O().c,Vu(a.Bf)):new RO(a.Bf,a.Bf.Gd,O().c,O().c)}\nfunction TO(a,b,c,d,e,g,h){return yB(a,b,c,MO(a,b,c,d,e,g,!1,!0),e,g,!1,!0,h)}function MO(a,b,c,d,e,g,h,k){if(d instanceof OA)return e=MO(a,b,c,d.Hi,e,g,h,k),h=d.ma(),ux(e.q,e,h);if(d instanceof cC){var l=d.Fg,m=d.Sf;e=MO(a,b,c,e?m:l,e,g,h,k);h=d.ma();return ux(e.q,e,h)}l=ap();h=yB(a,b,c,d,e,g,h,k,l).zf(!1);t();return UA(h,new L(e),!1,new fn((n,r)=>dea(a,n,r,d,g,b,c)),g)}\nfunction yB(a,b,c,d,e,g,h,k,l){for(;;){var m=!1,n=null,r=e?Cca(d,g,h):d;if(r instanceof Fv){var v=r,x=xB(a.Bf),A=b,B=c,C=a.Bf;t();var D=new L(v),F=uv(),I=Su(),M=op().ga,N=F.ng(new Uu(I,M)),P=Ev(k)?v.kq():wv(xv(a.Bf)),T=sv(),Y=Su(),Z=op().ga;return OO(x,A,B,new Ku(C,D,N,P,T.Hd(new Uu(Y,Z))))}if(r instanceof Gv){var S=r,ea=xB(a.Bf),ia=b,X=c,sa=a.Bf,Ja=t().d;uv();var Xa=Su(),Fa=op().ga,za=vv(S,new Uu(Xa,Fa)),Qa=wv(xv(a.Bf)),Ma=sv(),Ga=Su(),ab=op().ga;return OO(ea,ia,X,new Ku(sa,Ja,za,Qa,Ma.Hd(new Uu(Ga,\nab))))}if(r instanceof Qv){var Hb=r,bc=xB(a.Bf),yb=b,tb=c,eb=a.Bf,kb=t().d,Rb=uv(),Gb=Su(),vb=op().ga,Tb=Rb.ng(new Uu(Gb,vb)),Nb=sv(),ic=Su(),Va=op().ga;return OO(bc,yb,tb,new Ku(eb,kb,Tb,Hb,Nb.Hd(new Uu(ic,Va))))}if(r instanceof FA)return SO(a,!r.Eh);if(r instanceof LA){var cb=r,zb=cb.jc,Ub=e,jb=yB(a,b,c,cb.ic,e,g,h,k,l),db=yB(a,b,c,zb,e,g,h,k,l),ub=g,Aa=k;return cb.tc?UO(jb,db,ub,Aa):eea(jb,db,Ub,ub,Aa)}if(r instanceof MA){var va=r.Fc,Ra=xB(a.Bf),rb=b,xb=c,mc=FO(GO(a.Bf),b,O().c,va,!e,g,h,k,l).wq;\nif(mc===u())var Ha=u();else{for(var Ka=mc.e(),Oa=new z(new PO(Ka.Is,Ka.Js,Ka.Ks,Ka.Ls,Ka.Ms),u()),Na=Oa,Da=mc.f();Da!==u();){var ta=Da.e(),Ya=new z(new PO(ta.Is,ta.Js,ta.Ks,ta.Ls,ta.Ms),u());Na=Na.p=Ya;Da=Da.f()}Ha=Oa}return QO(Ra,rb,xb,Ha)}if(r instanceof lx){m=!0;n=r;iC(a.Bf);var dc=n.Sb;if(!dc.b()){var ka=dc.o();if(!vD(h)&&!l.L(n)){var ya=l.bc(n),Sa=b,xc=c,Sb=ya;return yB(xB(a.Bf),Sa,xc,ka,e,g,h,k,Sb)}}}if(m){var uc=xB(a.Bf),Lb=b,lc=c,Xb=$A(a.Bf);uv();var ec=n,Ab=Su(),Ob=op().ga,fb=Xb,Wa=vv(ec,\nnew Uu(Ab,Ob)),bb=fb.xq,Ia=Vu(fb.xq),Ua=lw(fb.xq),pc=uv(),sc=Su(),Ba=op().ga;var ob=new PO(bb,Ia,Wa,Ua,pc.ng(new Uu(sc,Ba)));var nc=O().c;return QO(uc,Lb,lc,new z(ob,nc))}if(r instanceof ZB){var Ib=r;$B(a.Bf);t();var vc=Ib.mc(),Vb=new L(vc);if(!Vb.b()){d=Vb.k;continue}}if(r instanceof fw){var fc=r,Bc=fc.qb;if(vD(h)&&!a.Bf.cn.L(Bc.V)||!PA(fc,g)){var Pb=b,Jb=c,gc=a.Bf,Cb=gw(fc,g),cc=uv(),yc=Su(),Mc=op().ga,qc=cc.ng(new Uu(yc,Mc)),oc=wv(xv(a.Bf)),Qc=sv(),jc=[G(new H,Bc,fc)],sb=J(new K,jc),Gc=Su(),Wb=\nop().ga;return OO(a,Pb,Jb,new Ku(gc,Cb,qc,oc,Qc.CF(sb,new Uu(Gc,Wb))))}d=QA(fc,g)}else if(r instanceof cC){var Cc=r,Fc=Cc.Fg,qd=Cc.Sf;d=e?qd:Fc}else if(r instanceof Qx){var Yb=r,Nc=Yb.Re;b=Yb.de;d=Nc}else if(r instanceof eC){var ad=r,Uc=ad.kj;c=dl(c,ad.Lj);d=Uc}else throw new w(r);}}NO.prototype.$classData=q({bX:0},!1,\"mlscript.NormalForms$DNF$\",{bX:1,g:1,l:1});function JO(a){this.oE=null;if(null===a)throw null;this.oE=a}JO.prototype=new p;JO.prototype.constructor=JO;\nJO.prototype.$classData=q({dX:0},!1,\"mlscript.NormalForms$Disjunct$\",{dX:1,g:1,l:1});function cy(a){if(a instanceof Zn)return\"definition\";if(a instanceof yo)return\"type declaration\";throw new w(a);}\nfunction fea(a){var b=!1,c=null;if(a instanceof Zn){b=!0;c=a;var d=c.wd,e=c.Rb,g=c.hj;if(t().d===d)return\"fun\"+(g.b()?\"\":\" (\"+g.o().x+\")\")+\" \"+e.x}if(b&&(d=c.wd,e=c.Rb,g=c.hj,d instanceof L&&!1===!!d.k))return\"let\"+(g.b()?\"\":\" \"+g.o().x+\")\")+\" \"+e.x;if(b&&(b=c.wd,d=c.Rb,c=c.hj,b instanceof L&&!0===!!b.k))return\"let rec\"+(c.b()?\"\":\" \"+c.o().x+\")\")+\" \"+d.x;if(a instanceof yo){d=a.pb;var h=a.hg;g=a.Sg;e=a.Hj;b=a.Di;c=d.ld;a=a.gb.V;if(h.b())var k=\"\";else{if(h===u())k=u();else{k=h.e();var l=k=new z(k.j().V,\nu());for(h=h.f();h!==u();){var m=h.e();m=new z(m.j().V,u());l=l.p=m;h=h.f()}}k=ze(k,\"\\u2039\",\", \",\"\\u203a\")}g.b()?g=\"\":(g=g.o(),g=\"(\"+Yz(g)+\")\");e.b()?e=\"\":(e=e.o(),e=\": \"+VO(e,!0));d=b.b()?\"\":Pe(new E(d),Ap())?\" \\x3d \":\": \";b=b.m();b=new Ef(b,new y(n=>Zz(n,!1)));return c+\" \"+a+k+g+e+d+ze(b,\"\",\", \",\"\")}throw new w(a);}\nfunction gea(a){if(a instanceof yo&&Ot(new E(a.pb),Bp())){var b=a.Sg;if(b.b())return R();var c=b.o();b=new vl(\"_\");a=new Cl(new vl(\"x\"),new Ep(a.Cf.x));var d=c.Ra;c=k=>{if(null!==k){var l=new L(k);if(!l.b()&&(l=l.k.h(),l instanceof L)){var m=l.k;k=t().d;l=tm().Cg;var n=new vl(\"x\"),r=new vl(\"#\"+m.x);m=m.A();l=new sm(l,new Ql(n,Cq(r,m)));return G(new H,k,l)}}if(null!==k&&(l=new L(k),!l.b()&&(k=l.k.h(),l=l.k.j(),t().d===k&&null!==l&&(m=l.ya,m instanceof vl))))return k=t().d,l=tm().Cg,n=new vl(\"x\"),r=\nnew vl(\"#\"+m.x),m=m.A(),l=new sm(l,new Ql(n,Cq(r,m))),G(new H,k,l);xm(\"Program reached and unexpected state.\")};if(d===u())c=u();else{var e=d.e(),g=e=new z(c(e),u());for(d=d.f();d!==u();){var h=d.e();h=new z(c(h),u());g=g.p=h;d=d.f()}c=e}g=new Rl(!1,b,a,new Gl(c));b=t().d;a=new vl(\"unapply\");c=t().d;e=O().c;t();d=t().d;h=new sm(tm().Cg,new vl(\"x\"));d=G(new H,d,h);h=O().c;g=new Ol(new Gl(new z(d,h)),g);return new L(new Zn(b,a,c,e,new fe(g),t().d,t().d,t().d,t().d,t().d,!0,O().c))}return t().d}\nfunction WO(a){this.JN=null;this.OH=!1;this.IN=null;if(null===a)throw null;this.IN=a}WO.prototype=new p;WO.prototype.constructor=WO;WO.prototype.$classData=q({yX:0},!1,\"mlscript.NuTypeDefs$RefMap$\",{yX:1,g:1,l:1});function XO(a,b,c){if(0<=a.length&&\"'\"===a.substring(0,1))var d=!0;else d=pE().SP,d=0<=a.length&&a.substring(0,d.length)===d;b=d?\"\":b;d=c.U(a);if(d instanceof L)return d=d.k|0,c.bh(a,1+d|0),\"\"+b+a+d;if(t().d===d)return c.bh(a,0),\"\"+b+a;throw new w(d);}function YO(){}YO.prototype=new p;\nYO.prototype.constructor=YO;\nfunction wf(a,b,c,d){a=b.m();Od();a=Pd(u(),a);for(var e=b=null;a!==u();){for(var g=ZO(a.e()).m();g.s();){var h=new z(g.t(),u());null===e?b=h:e.p=h;e=h}a=a.f()}a=null===b?u():b;a=hl(a);a=Pt(a,new y(n=>{var r=n.pp;if(r instanceof fe)return t(),n=G(new H,n.oA,n),new fe(n);if(r instanceof Ud)return r=r.fa,t(),n=G(new H,r,n),new Ud(n);throw new w(r);}));if(null===a)throw new w(a);g=a.h();b=a.j();Od();e=new fp;Od();for(a=new fp;!g.b();){h=g.e();a:{if(null!==h){var k=h.h(),l=h.j();if(k instanceof L){h=k.k;\nt();h=G(new H,h,l);h=new fe(h);break a}}if(null!==h&&(l=h.h(),k=h.j(),t().d===l)){t();h=new Ud(k);break a}throw new w(h);}if(h instanceof fe)wp(e,h.aa);else if(h instanceof Ud)wp(a,h.fa);else throw new w(h);g=g.f()}e=e.ha();a=a.ha();var m=Xu().X();h=un(b,e);b=n=>{if(null!==n){var r=n.h();n=n.j();Q();r=0<=r.length&&r.substring(0,d.length)===d?r.substring(d.length):r;r=XO(r,d,m);return G(new H,n,r)}throw new w(n);};if(h===u())b=u();else{e=h.e();g=e=new z(b(e),u());for(h=h.f();h!==u();)l=h.e(),l=new z(b(l),\nu()),g=g.p=l,h=h.f();b=e}e=Su();g=op().ga;e=new Uu(e,g);b=Ov(sv(),b,e);e=m.zr();O();e=new iy(new $O(0,new y(n=>{n|=0;var r=n/26|0;t();n=G(new H,String.fromCharCode(65535&(97+(n%26|0)|0))+(Pe(new E(r),0)?\"\":\"\"+r),1+n|0);return new L(n)})),e,!0);e=new Ef(e,new y(n=>XO(n,d,m)));a=Bf(a,e);return new aP(b.hy(a),!1,0,c,!1)}YO.prototype.$classData=q({gY:0},!1,\"mlscript.ShowCtx$\",{gY:1,g:1,l:1});var bP;function vf(){bP||(bP=new YO);return bP}\nfunction cP(a){var b=!1,c=null;if(a instanceof yo){b=!0;c=a;var d=c.pb;zp()===d&&no()}b&&(d=c.pb,cp()===d&&no());if(b){d=c.pb;var e=c.gb,g=c.hg,h=c.Sg,k=c.Hj,l=c.Di,m=c.Ns,n=c.ei;if(Ap()===d){if(!h.b()&&!h.o().Ra.b())throw Kj(\"requirement failed: \"+h);a=l.K();if(!Pe(new E(a),0))throw Kj(\"requirement failed: \"+l);At(tp(),!k.b());if(!m.b())throw Kj(\"requirement failed: \"+m);if(!ef(n).b())throw Kj(\"requirement failed: \"+n);a=O().c;if(g===u())c=u();else for(c=g.e(),b=c=new z(c.j(),u()),g=g.f();g!==u();)l=\ng.e(),l=new z(l.j(),u()),b=b.p=l,g=g.f();k.b()&&xm(\"Program reached and unexpected state.\");d=new Oo(d,e,c,k.o(),O().c,O().c,O().c,t().d);e=O().c;return G(new H,a,new z(d,e))}}if(b&&(d=c.pb,e=c.gb,k=c.hg,g=c.Sg,b=c.Di,Bp()===d||Fp()===d)){c=g.b()?new Gl(O().c):g.o();g=c.Ra;var r=TE(PE());a=B=>{if(null!==B){var C=B.h(),D=B.j();if(C instanceof L&&(C=C.k,null!==D)){var F=D.yb;D=D.ya;if(null!==F)return B=F.je,D=dP(D,r),B=new Sn(B?(t(),new L(D)):t().d,D),G(new H,C,B)}}if(null!==B&&(C=B.h(),B=B.j(),t().d===\nC&&null!==B&&(D=B.yb,C=B.ya,null!==D&&(B=D.je,C instanceof vl))))return B?(t(),B=el(),B=new L(B)):B=t().d,B=new Sn(B,gl()),G(new H,C,B);xm(\"Program reached and unexpected state.\")};if(g===u())l=u();else for(l=g.e(),m=l=new z(a(l),u()),n=g.f();n!==u();)h=n.e(),h=new z(a(h),u()),m=m.p=h,n=n.f();a=op();a=l.Gb(a.ga).h();if(b===u())b=u();else{m=b.e();n=m=new z(dP(m,r),u());for(b=b.f();b!==u();)h=b.e(),h=new z(dP(h,r),u()),n=n.p=h,b=b.f();b=m}b=b.mf(new Tn(l),Un());l=new vl(e.V);m=e.A();l=Cq(l,m);t();m=\nt().d;n=tm().Cg;h=B=>{if(null!==B){var C=B.h(),D=B.j();if(C instanceof L)return B=C.k,D=new sm(new St(!1,!1,D.yb.Bh),B),G(new H,B,D)}if(null!==B&&(D=B.h(),B=B.j(),t().d===D&&null!==B&&(D=B.ya,D instanceof vl)))return G(new H,D,B);xm(\"Program reached and unexpected state.\")};if(g===u())g=u();else{var v=g.e(),x=v=new z(h(v),u());for(g=g.f();g!==u();){var A=g.e();A=new z(h(A),u());x=x.p=A;g=g.f()}g=v}g=new sm(n,new yl(g));g=G(new H,m,g);m=O().c;c=new Ol(c,new Pl(l,new Gl(new z(g,m))));c=new No(!1,l,\nnew fe(c),!0);g=r.ha();if(k===u())k=u();else{l=k.e();m=l=new z(l.j(),u());for(k=k.f();k!==u();)n=k.e(),n=new z(n.j(),u()),m=m.p=n,k=k.f();k=l}d=new Oo(d,e,k,b,O().c,O().c,a,t().d);e=O().c;return G(new H,g,new z(d,new z(c,e)))}if(sy(a))return d=O().c,e=O().c,G(new H,d,new z(a,e));throw new w(a);}\nfunction eP(a){if(a instanceof Ml){var b=a.gs,c=a.Ml,d=O().c;return new z(b,new z(c,d))}if(a instanceof Fl){var e=a.gg,g=O().c;return new z(e,g)}if(a instanceof vl)return O().c;if(a instanceof Cl){var h=a.ai,k=O().c;return new z(h,k)}if(a instanceof Ol){var l=a.Ej,m=a.Fj,n=O().c;return new z(l,new z(m,n))}if(a instanceof Pl){var r=a.Za,v=a.Qb,x=O().c;return new z(r,new z(v,x))}if(a instanceof Gl){var A=a.Ra;if(A===u())return u();for(var B=A.e(),C=new z(B.j().ya,u()),D=C,F=A.f();F!==u();){var I=F.e(),\nM=new z(I.j().ya,u());D=D.p=M;F=F.f()}return C}if(a instanceof yl){var N=a.ll;if(N===u())return u();for(var P=N.e(),T=new z(P.j().ya,u()),Y=T,Z=N.f();Z!==u();){var S=Z.e(),ea=new z(S.j().ya,u());Y=Y.p=ea;Z=Z.f()}return T}if(a instanceof Ql){var ia=a.Vl,X=a.ml,sa=O().c;return new z(ia,new z(X,sa))}if(a instanceof Rl){var Ja=a.$n,Xa=a.Mm,Fa=O().c;return new z(Ja,new z(Xa,Fa))}if(a instanceof Sl)return a.Dj;if(a instanceof Dl)return O().c;if(a instanceof Tl){var za=a.br,Qa=a.ar,Ma=O().c;return new z(za,\nnew z(Qa,Ma))}if(a instanceof Ul){var Ga=a.Sn,ab=a.Hm,Hb=O().c;return new z(Ga,new z(ab,Hb))}if(a instanceof No){var bc=a.oq,yb=a.RM,tb=O().c;return new z(bc,new z(yb,tb))}if(a instanceof Oo){var eb=a.eA,kb=a.gA,Rb=a.cA,Gb=a.fA,vb=O().c,Tb=dl(dl(new z(Rb,vb),Gb),kb);return new z(eb,Tb)}if(a instanceof Vl){var Nb=a.lp,ic=a.mp,Va=O().c;return new z(Nb,new z(ic,Va))}if(a instanceof Wl){var cb=a.Gm,zb=a.Qn,Ub=O().c;return new z(cb,new z(zb,Ub))}if(a instanceof dm){var jb=a.$q,db=a.Zq,ub=O().c;return new z(jb,\nnew z(db,ub))}if(a instanceof Xl){var Aa=a.bp,va=a.zs.ha();return new z(Aa,va)}if(a instanceof Zn){var Ra=a.Rb,rb=a.Ch,xb=a.hj.ha(),mc=a.EN,Ha=O().c,Ka=dl(dl(new z(mc,Ha),rb),xb);return new z(Ra,Ka)}if(a instanceof Il)return new z(a.nl,a.np);if(a instanceof Yl){var Oa=a.hp,Na=O().c;return new z(Oa,Na)}if(a instanceof cm){var Da=a.Ys,ta=a.Zs,Ya=O().c;return new z(Da,new z(ta,Ya))}if(a instanceof $l)return new z(a.Yq,a.lt);if(a instanceof Zl){var dc=a.qq,ka=a.$o,ya=O().c;return dl(new z(ka,ya),dc)}if(a instanceof\nKl){var Sa=a.cp,xc=O().c;return new z(Sa,xc)}if(a instanceof am)return O().c;if(a instanceof Po){var Sb=a.ks,uc=a.js,Lb=O().c;return new z(Sb,new z(uc,Lb))}if(a instanceof bm){var lc=a.Vn,Xb=a.Zo,ec=O().c;return new z(lc,new z(Xb,ec))}if(a instanceof yo){var Ab=a.gb,Ob=a.hg,fb=a.Sg,Wa=a.Di,bb=a.Ns,Ia=a.ei;if(Ob===u())var Ua=u();else{for(var pc=Ob.e(),sc=new z(pc.j(),u()),Ba=sc,ob=Ob.f();ob!==u();){var nc=ob.e(),Ib=new z(nc.j(),u());Ba=Ba.p=Ib;ob=ob.f()}Ua=sc}var vc=fb.ha(),Vb=bb.ha(),fc=O().c,Bc=\ndl(dl(dl(dl(new z(Ia,fc),Vb),Wa),vc),Ua);return new z(Ab,Bc)}if(a instanceof em){var Pb=a.Iq,Jb=O().c;return new z(Pb,Jb)}if(a instanceof fm){var gc=a.jt,Cb=O().c;return new z(gc,Cb)}throw new w(a);}\nfunction Mx(a){if(a instanceof Po){var b=a.js;return\"constructor(\"+Yz(a.ks)+\") \"+Zz(b,!1)}if(a instanceof Pm)return Zz(a,!1);if(a instanceof fP){a:{var c=!1;b=null;if(a instanceof No){c=!0;b=a;var d=b.oq;if(!0===b.ls){b=\"rec def \"+Zz(d,!1);break a}}if(c&&(c=b.oq,!1===b.ls)){b=\"def \"+Zz(c,!1);break a}if(a instanceof Oo){var e=a.gA;b=a.fA;c=a.dA.ld;d=a.eA.V;if(e.b())var g=\"\";else{if(e===u())g=u();else{g=e.e();var h=g=new z(g.V,u());for(e=e.f();e!==u();){var k=e.e();k=new z(k.V,u());h=h.p=k;e=e.f()}}g=\nze(g,\"[\",\", \",\"]\")}b=c+\" \"+d+g+(b.b()?\"\":ze(b,\"(\",\", \",\")\"))}else throw new w(a);}c=a instanceof Oo&&Ot(new E(a.dA),Ap())?\" \\x3d \":\": \";b+=c;if(a instanceof No)if(a=a.vu,a instanceof Ud)a=VO(a.fa,!0);else{if(!(a instanceof fe))throw new w(a);a=Zz(a.aa,!1)}else if(a instanceof Oo)a=VO(a.cA,!0);else throw new w(a);return b+a}if(a instanceof Ct){b=fea(a);if(a instanceof Zn)c=a.Yc.TJ()?\" \\x3d \":\": \";else{if(!(a instanceof yo))throw new w(a);c=\" \"}b+=c;if(a instanceof Zn)if(a=a.Yc,a instanceof Ud)a=VO(a.fa,\n!0);else{if(!(a instanceof fe))throw new w(a);a=Zz(a.aa,!1)}else if(a instanceof yo)a=gP(a.ei);else throw new w(a);return b+a}throw new w(a);}function dP(a,b){a=Qn(a);if(a instanceof fe)return b.$(a.aa),gl();if(a instanceof Ud)return a.fa;throw new w(a);}\nfunction hea(a){if(a instanceof Tn){var b=a.Xs;if(b===u())return u();var c=b.e();a=c=new z(c.h().x,u());for(b=b.f();b!==u();){var d=b.e();d=new z(d.h().x,u());a=a.p=d;b=b.f()}return c}if(a instanceof hP)return c=a.Bs,a=yn(a.As),c=yn(c),un(a,c);if(a instanceof iP||a instanceof Wt||a instanceof jP||a instanceof kP||a instanceof lP||a instanceof mP||a instanceof nP||gl()===a||el()===a||a instanceof oP||a instanceof jt||a instanceof pP||a instanceof Ep||a instanceof qP||a instanceof rP||a instanceof sP||\na instanceof Vt||a instanceof tP)return O().c;throw new w(a);}\nfunction iea(a){if(a instanceof Ep){a=a.V;var b=O().c;return new z(a,b)}if(a instanceof pP&&(b=a.Gw,null!==b))return a=b.V,b=O().c,new z(a,b);if(a instanceof hP)return b=a.Bs,a=zn(a.As),b=zn(b),un(a,b);if(a instanceof iP||a instanceof Wt||a instanceof Tn||a instanceof jP||a instanceof kP||a instanceof lP||a instanceof mP||a instanceof nP||gl()===a||el()===a||a instanceof Vt||a instanceof oP||a instanceof jt||a instanceof qP||a instanceof rP||a instanceof sP||a instanceof tP)return O().c;throw new w(a);\n}function VO(a,b){vf();var c=O().c;b=wf(0,new z(a,c),b,\"'\");return yf(a,0,b)}function uP(a,b){return b?\"(\"+a+\")\":a}\nfunction vP(a,b){if(null!==a){var c=a.Yf,d=a.Rg;if(t().d===c)return yf(d,0,b)}if(null!==a&&(c=a.Yf,d=a.Rg,c instanceof L&&Pe(new E(c.k),d)))return yf(d,0,b);if(null!==a&&(d=a.Yf,c=a.Rg,d instanceof L&&(d=d.k,el()===d)))return\"out \"+yf(c,0,b);if(null!==a&&(d=a.Yf,c=a.Rg,d instanceof L&&(d=d.k,gl()===c)))return\"in \"+yf(d,0,b);if(null!==a&&(c=a.Yf,d=a.Rg,c instanceof L))return\"in \"+yf(c.k,0,b)+\" out \"+yf(d,0,b);throw new w(a);}\nfunction wP(a,b){var c=h=>{var k=h.j().Yf.b()?\"\":\"mut \",l=h.h();l=l.b()?\"\":l.o().x+\": \";return k+l+vP(h.j(),b)};if(a===u())return u();var d=a.e(),e=d=new z(c(d),u());for(a=a.f();a!==u();){var g=a.e();g=new z(c(g),u());e=e.p=g;a=a.f()}return d}\nvar yf=function xP(a,b,c){var e=!1,g=null,h=!1,k=null,l=!1,m=null,n=!1,r=null,v=!1,x=null;if(gl()===a)return\"anything\";if(el()===a)return\"nothing\";if(a instanceof Ep)return a.V;if(a instanceof sP)return\"#\"+a.nA;if(a instanceof jt)return HA(c.kp,a);if(a instanceof nP){var A=a.Mx;return uP(xP(a.Lx,2,c)+\" with \"+xP(A,0,c),1<b)}if(a instanceof Wt){e=!0;g=a;var B=g.ps,C=g.qs;if(B instanceof jP){var D=B.Mu;a:{var F=O().c;if(null===F?null===D:F.i(D))var I=\"()\";else{if(D instanceof z){var M=D.z,N=D.p;if(null!==\nM){var P=new L(M);if(!P.b()){var T=P.k.h(),Y=P.k.j();if(t().d===T&&null!==Y){var Z=Y.Yf,S=Y.Rg;if(t().d===Z)var ea=O().c,ia=(null===ea?null===N:ea.i(N))?!(S instanceof jP):!1;else ia=!1;if(ia){I=xP(S,31,c);break a}}}}}var X=wP(D,c);I=c.fi?ze(X,\"(\",\", \",\")\"):ze(X,\"(\",\", \",\",)\")}}return uP(I+\" -\\x3e \"+xP(C,30,c),30<b)}}if(e){var sa=g.ps,Ja=g.qs;if(c.fi)return uP(\"(...\"+xP(sa,0,c)+\") -\\x3e \"+xP(Ja,30,c),30<b)}if(e){var Xa=g.qs;return uP(xP(g.ps,31,c)+\" -\\x3e \"+xP(Xa,30,c),30<b)}if(a instanceof kP)return\"~\"+\nxP(a.cx,100,c);if(a instanceof Tn){var Fa=a.Xs,za=Ac=>{var Ve=Ac.h().x;if(hB(ve(),Ve)){Ac=Ac.j();if(null!==Ac){var Td=Ac.Yf,lf=Ac.Rg;a:if(t().d===Td)Td=!0;else{if(Td instanceof L&&(Td=Td.k,el()===Td)){Td=!0;break a}Td=!1}if(Td&&gl()===lf)return\"\"+Ve}if(null!==Ac&&(lf=Ac.Yf,Td=Ac.Rg,lf instanceof L&&Pe(new E(lf.k),Td)))return Ve+\" \\x3d \"+xP(Td,0,c);if(null!==Ac){Td=Ac.Yf;lf=Ac.Rg;a:if(t().d===Td)Td=!0;else{if(Td instanceof L&&(Td=Td.k,el()===Td)){Td=!0;break a}Td=!1}if(Td)return Ve+\" \\x3c: \"+xP(lf,\n0,c)}if(null!==Ac&&(Td=Ac.Yf,lf=Ac.Rg,Td instanceof L&&(Td=Td.k,gl()===lf)))return Ve+\" :\\x3e \"+xP(Td,0,c);if(null!==Ac&&(lf=Ac.Yf,Td=Ac.Rg,lf instanceof L))return Ve+\" :\\x3e \"+xP(lf.k,0,c)+\" \\x3c: \"+xP(Td,0,c);throw new w(Ac);}return(Ac.j().Yf.b()?\"\":\"mut \")+Ve+\": \"+vP(Ac.j(),c)};if(Fa===u())var Qa=u();else{for(var Ma=Fa.e(),Ga=new z(za(Ma),u()),ab=Ga,Hb=Fa.f();Hb!==u();){var bc=Hb.e(),yb=new z(za(bc),u());ab=ab.p=yb;Hb=Hb.f()}Qa=Ga}for(var tb=0,eb=Qa;!eb.b();){var kb=tb,Rb=eb.e();tb=(kb|0)+Rb.length|\n0;eb=eb.f()}if(80<(tb|0)){ve();var Gb=\"{\\n\"+yP(c),vb=\",\\n\"+yP(c),Tb=ze(Qa,Gb,vb,\"\");return ada(Tb)+\"\\n\"+yP(c)+\"}\"}return ze(Qa,\"{\",\", \",\"}\")}if(a instanceof rP){var Nb=a.Ax,ic=Ac=>{if(Ac instanceof fe)return\"...\"+xP(Ac.aa,0,c);if(Ac instanceof Ud)return\"\"+vP(Ac.fa,c);throw new w(Ac);};if(Nb===u())var Va=u();else{for(var cb=Nb.e(),zb=new z(ic(cb),u()),Ub=zb,jb=Nb.f();jb!==u();){var db=jb.e(),ub=new z(ic(db),u());Ub=Ub.p=ub;jb=jb.f()}Va=zb}return c.fi?ze(Va,\"[\",\", \",\"]\"):ze(Va,\"(\",\", \",\")\")}if(a instanceof\njP){var Aa=a.Mu,va=wP(Aa,c);if(c.fi)return ze(va,\"[\",\", \",\"]\");var Ra=Aa.b()?\")\":\",)\";return ze(va,\"(\",\", \",Ra)}a:{if(a instanceof iP){var rb=a.ht,xb=a.it;if(rb instanceof Ep&&\"true\"===rb.V&&xb instanceof Ep&&\"false\"===xb.V){var mc=!0;break a}}if(a instanceof iP){var Ha=a.ht,Ka=a.it;if(Ha instanceof Ep&&\"false\"===Ha.V&&Ka instanceof Ep&&\"true\"===Ka.V){mc=!0;break a}}mc=!1}if(mc){var Oa=new Ep(\"bool\");return xP(Oa,0,c)}if(a instanceof cl){var Na=a.Yo?20:25,Da=a.Yo?\" | \":\" \\x26 \",ta=a.Jw?a.Kw:zP(a),\nYa=O().c;if(null===Ya?null===ta:Ya.i(ta)){var dc=a.Yo?el():gl();return xP(dc,b,c)}if(ta instanceof z){var ka=ta.z,ya=ta.p,Sa=O().c;if(null===Sa?null===ya:Sa.i(ya))return xP(ka,b,c)}var xc=(a.Jw?a.Kw:zP(a)).m(),Sb=new Ef(xc,new y(Ac=>xP(Ac,Na,c)));if(!Sb.s())throw nv(\"empty.reduceLeft\");for(var uc=!0,Lb=null;Sb.s();){var lc=Sb.t();uc?(Lb=lc,uc=!1):Lb=Lb+Da+lc}return uP(Lb,b>Na)}if(a instanceof mP){h=!0;k=a;var Xb=k.Bi,ec=k.Ci;if(el()===Xb&&gl()===ec)return\"?\"}if(h){var Ab=k.Bi;if(Pe(new E(Ab),k.Ci))return xP(Ab,\nb,c)}if(h){var Ob=k.Bi,fb=k.Ci;if(el()===Ob)return\"out \"+xP(fb,0,c)}if(h){var Wa=k.Bi,bb=k.Ci;if(gl()===bb)return\"in \"+xP(Wa,0,c)}if(h){var Ia=k.Ci;return\"in \"+xP(k.Bi,0,c)+\" out \"+xP(Ia,0,c)}if(a instanceof pP){var Ua=a.Hw,pc=a.Gw.V;if(Ua===u())var sc=u();else{for(var Ba=Ua.e(),ob=new z(xP(Ba,0,c),u()),nc=ob,Ib=Ua.f();Ib!==u();){var vc=Ib.e(),Vb=new z(xP(vc,0,c),u());nc=nc.p=Vb;Ib=Ib.f()}sc=ob}return\"\"+pc+ze(sc,c.Jq?\"\\x3c\":\"[\",\", \",c.Jq?\"\\x3e\":\"]\")}if(a instanceof tP){var fc=a.wx;return xP(a.vx,\n100,c)+\".\"+fc.V}if(a instanceof lP){var Bc=a.Zz,Pb=xP(a.tx,90,c);if(Bc===u())var Jb=u();else{for(var gc=Bc.e(),Cb=new z(\"\\\\\"+gc.x,u()),cc=Cb,yc=Bc.f();yc!==u();){var Mc=yc.e(),qc=new z(\"\\\\\"+Mc.x,u());cc=cc.p=qc;yc=yc.f()}Jb=Cb}return\"\"+Pb+ze(Jb,\"\",\"\",\"\")}if(a instanceof oP){l=!0;m=a;var oc=m.Es;if(oc instanceof Em)return oc.rq.u()}if(l){var Qc=m.Es;if(Qc instanceof Fm)return Qc.uu.gd.u()}if(l){var jc=m.Es;if(jc instanceof Dm)return'\"'+jc.Lu+'\"'}if(l){var sb=m.Es;if(sb instanceof Gm)return sb.Xq?c.fi?\n\"()\":\"undefined\":\"null\"}if(a instanceof Vt){n=!0;r=a;var Gc=r.Ws,Wb=r.Vs,Cc=O().c;if(null===Cc?null===Gc:Cc.i(Gc))return xP(Wb,b,c)}if(n){var Fc=r.Vs,qd=r.Ws.m(),Yb=new Ef(qd,new y(Ac=>{if(Ac instanceof Ud)return xP(Ac.fa,0,c);if(!(Ac instanceof fe))throw new w(Ac);return Ac.aa.V}));return uP(ze(Yb,\"forall \",\" \",\".\")+\" \"+xP(Fc,0,c),1<b)}if(a instanceof qP){var Nc=a.Lw,ad=a.Mw,Uc=a.Nw;Q();var cd=xP(Nc,0,c),kc=zf(cd),Vc=uH(Q(),kc,10),Hc=Vc?AP(c):AP(AP(c)),rc=yP(c),sd=Ac=>{if(null!==Ac){var Ve=Ac.h(),\nTd=Ac.j();if(null!==Td){var lf=Td.Bi;Td=Td.Ci;if(el()===lf)return\"\\n\"+yP(Hc)+HA(Hc.kp,Ve)+\" \\x3c: \"+xP(Td,0,Hc)}}if(null!==Ac&&(Ve=Ac.h(),Td=Ac.j(),null!==Td&&(lf=Td.Bi,Td=Td.Ci,gl()===Td)))return\"\\n\"+yP(Hc)+HA(Hc.kp,Ve)+\" :\\x3e \"+xP(lf,0,Hc);if(null!==Ac&&(Ve=Ac.h(),lf=Ac.j(),null!==lf&&(Td=lf.Bi,Pe(new E(Td),lf.Ci))))return\"\\n\"+yP(Hc)+HA(Hc.kp,Ve)+\" :\\x3d \"+xP(Td,0,Hc);if(null!==Ac&&(Ve=Ac.h(),lf=Ac.j(),null!==lf))return Ac=lf.Bi,lf=lf.Ci,Ve=HA(Hc.kp,Ve),\"\\n\"+yP(Hc)+Ve+\" :\\x3e \"+xP(Ac,0,Hc)+(\"\\n\"+\nyP(Hc)+ut(Q(),\" \",Ve.length)+\" \\x3c: \")+xP(lf,0,Hc);throw new w(Ac);};if(ad===u())var Kc=u();else{for(var Qd=ad.e(),Ad=new z(sd(Qd),u()),kd=Ad,Hd=ad.f();Hd!==u();){var Rd=Hd.e(),Bd=new z(sd(Rd),u());kd=kd.p=Bd;Hd=Hd.f()}Kc=Ad}var ae=ze(Kc,\"\",\"\",\"\"),dd=Ac=>{if(null!==Ac){var Ve=Ac.Bi;Ac=Ac.Ci;return\"\\n\"+yP(Hc)+xP(Ve,0,Hc)+\" \\x3c: \"+xP(Ac,0,Hc)}throw new w(Ac);};if(Uc===u())var od=u();else{for(var Ta=Uc.e(),wb=new z(dd(Ta),u()),$a=wb,wa=Uc.f();wa!==u();){var hb=wa.e(),ra=new z(dd(hb),u());$a=$a.p=ra;\nwa=wa.f()}od=wb}return uP(kc+\"\\n\"+rc+(Vc?\"\":\"  \")+\"where\"+ae+ze(od,\"\",\"\",\"\"),0<b)}if(a instanceof Zn){var wc=a.wd,ac=a.Rb,Id=a.hj,ud=a.Ch,be=a.Yc,re=a.Om.b()?\"\":\"mut \",pe=!1,bd=null;a:{if(wc instanceof L&&(pe=!0,bd=wc,!1===!!bd.k)){var Rc=a.Pl?\"val\":\"let\";break a}if(pe&&!0===!!bd.k)a.Pl&&xm(\"Program reached and unexpected state.\"),Rc=\"let rec\";else if(t().d===wc)Rc=\"fun\";else throw new w(wc);}var Wc=Id.b()?\"\":\" (\"+Id.o().x+\")\",Wd=ac.x;if(ud===u())var zd=u();else{for(var Pa=ud.e(),Db=new z(xP(Pa,0,\nc),u()),Oc=Db,Tc=ud.f();Tc!==u();){var Sd=Tc.e(),Jc=new z(xP(Sd,0,c),u());Oc=Oc.p=Jc;Tc=Tc.f()}zd=Db}var vd=BF(GF(),zd);if(be instanceof fe)var hd=\" \\x3d ...\";else{if(!(be instanceof Ud))throw new w(be);hd=\": \"+xP(be.fa,0,c)}return re+Rc+Wc+\" \"+Wd+vd+hd}if(a instanceof BP){var de=a.yx,ye=a.aA,jf=Ac=>\"\"+yP(c)+xP(Ac,0,c)+\"\\n\";if(de===u())var af=u();else{for(var pf=de.e(),kf=new z(jf(pf),u()),Be=kf,Kd=de.f();Kd!==u();){var ld=Kd.e(),Jd=new z(jf(ld),u());Be=Be.p=Jd;Kd=Kd.f()}af=kf}if(ye instanceof L)var Dd=\nye.k,Xd=\"\"+yP(c)+xP(Dd,0,c)+\"\\n\",Yc=O().c,Ce=new z(Xd,Yc);else{if(t().d!==ye)throw new w(ye);Ce=O().c}var te=dl(Ce,af);return ze(te,\"\",\"\",\"\")}if(a instanceof yo){v=!0;x=a;var Ie=x.pb,Jf=x.gb,df=x.hg,vg=x.Sg,wg=x.Qm,xg=x.Hj,eg=x.Di,vh=x.mx,fg=x.Ns,ih=x.ei;if(Ap()===Ie){if(!vg.b())throw new Yj(\"assertion failed: \"+vg);if(!wg.b())throw new Yj(\"assertion failed: \"+wg);if(!eg.b())throw new Yj(\"assertion failed: \"+eg);if(!vh.b())throw new Yj(\"assertion failed: \"+vh);if(!fg.b())throw new Yj(\"assertion failed: \"+\nfg);if(!ef(ih).b())throw new Yj(\"assertion failed: \"+ih);var Ig=Jf.V;if(df===u())var Tf=u();else{for(var Jg=df.e(),jh=new z(xP(Jg.j(),0,c),u()),yg=jh,gg=df.f();gg!==u();){var Cf=gg.e(),Uf=new z(xP(Cf.j(),0,c),u());yg=yg.p=Uf;gg=gg.f()}Tf=jh}var $g=BF(GF(),Tf);xg.b()&&xm(\"Program reached and unexpected state.\");var Ah=xg.o();return\"type \"+Ig+$g+\" \\x3d \"+xP(Ah,0,c)}}if(v){var Kg=x.pb,Vf=x.gb,hg=x.hg,zg=x.Sg,Lg=x.Hj,Mg=x.Di,Wf=x.mx,Ng=x.Ns,Kf=x.ei,xf=AP(c),Og=x.fl;if(Og.b())var mi=\"\";else Og.o(),mi=\n\"declare \";var Ci=x.Pm;if(Ci.b())var Xh=\"\";else Ci.o(),Xh=\"abstract \";var wh=Kg.ld,Bh=Vf.V;if(hg===u())var ng=u();else{for(var kh=hg.e(),Kh=new z(xP(kh.j(),0,c),u()),ni=Kh,Lh=hg.f();Lh!==u();){var lh=Lh.e(),Ch=new z(xP(lh.j(),0,c),u());ni=ni.p=Ch;Lh=Lh.f()}ng=Kh}var Dh=BF(GF(),ng);a:{if(zg instanceof L){var Yh=zg.k;if(null!==Yh){var ah=Yh.Ra,oi=Ac=>{if(null!==Ac){var Ve=Ac.h(),Td=Ac.j();if(t().d===Ve&&null!==Td&&(Td=Td.ya,Td instanceof Cl&&(Ve=Td.ai,Td=Td.Fm,Ve instanceof vl)))return Ve.x+\": \"+xP(Td,\n0,c)}null!==Ac&&(Ve=Ac.h(),(t().d===Ve||Ve instanceof L)&&xm(\"ill-formed type definition parameter\"));throw new w(Ac);};if(ah===u())var mj=u();else{for(var wd=ah.e(),ge=new z(oi(wd),u()),De=ge,qf=ah.f();qf!==u();){var og=qf.e(),Xf=new z(oi(og),u());De=De.p=Xf;qf=qf.f()}mj=ge}var mh=\"(\"+ze(mj,\"\",\", \",\"\")+\")\";break a}}mh=\"\"}if(Lg.b())var Ag=\"\";else{var Bg=Lg.o();Ag=\": \"+xP(Bg,0,xf)}var Eh=O().c;if(null===Eh?null===Mg:Eh.i(Mg))var Pg=\"\";else{var Di=Mg.m(),Mh=new Ef(Di,new y(Ac=>Zz(Ac,!1)));Pg=\" extends \"+\nze(Mh,\"\",\", \",\"\")}if(ef(Kf).b()&&Wf.b()&&Ng.b())var pi=\"\";else{if(Wf.b())var Xi=\"\";else{var Qg=Wf.o();Xi=yP(xf)+\"super: \"+xP(Qg,0,xf)+\"\\n\"}if(Ng.b())var nh=\"\";else{var bh=Ng.o();nh=yP(xf)+\"this: \"+xP(bh,0,xf)+\"\\n\"}var Mj=Wn(ef(Kf),new CP(a,xf)),Nj=ze(Mj,\"\",\"\",\"\"),ie=new BP(Wn(ef(Kf),new DP(a)),t().d);pi=\" {\\n\"+Xi+nh+Nj+xP(ie,0,xf)+yP(c)+\"}\"}return mi+Xh+wh+\" \"+Bh+Dh+mh+Ag+Pg+pi}throw new w(a);};\nfunction EP(a){if(a instanceof FP)return O().c;if(a instanceof Wt){var b=a.ps,c=a.qs,d=O().c;return new z(b,new z(c,d))}if(a instanceof mP){var e=a.Bi,g=a.Ci,h=O().c;return new z(e,new z(g,h))}if(a instanceof kP){var k=a.cx,l=O().c;return new z(k,l)}if(a instanceof Tn){for(var m=a.Xs,n=null,r=null;m!==u();){for(var v=m.e(),x=v.j().Yf.ha(),A=v.j().Rg,B=O().c,C=un(x,new z(A,B)).m();C.s();){var D=new z(C.t(),u());null===r?n=D:r.p=D;r=D}m=m.f()}return null===n?u():n}if(a instanceof jP){for(var F=a.Mu,\nI=null,M=null;F!==u();){for(var N=F.e(),P=iu(ju(),N.j().Yf),T=N.j().Rg,Y=O().c,Z=P.tl(new z(T,Y)).m();Z.s();){var S=new z(Z.t(),u());null===M?I=S:M.p=S;M=S}F=F.f()}return null===I?u():I}if(a instanceof iP){var ea=a.ht,ia=a.it,X=O().c;return new z(ea,new z(ia,X))}if(a instanceof hP){var sa=a.As,Ja=a.Bs,Xa=O().c;return new z(sa,new z(Ja,Xa))}if(a instanceof pP)return a.Hw;if(a instanceof tP){var Fa=a.vx,za=a.wx,Qa=O().c;return new z(Fa,new z(za,Qa))}if(a instanceof lP){var Ma=a.tx,Ga=O().c;return new z(Ma,\nGa)}if(a instanceof nP){var ab=a.Lx,Hb=a.Mx,bc=O().c;return new z(ab,new z(Hb,bc))}if(a instanceof Vt){var yb=a.Ws,tb=a.Vs,eb=oc=>{if(oc instanceof Ud)oc=oc.fa;else{if(!(oc instanceof fe))throw new w(oc);oc=oc.aa}return oc};if(yb===u())var kb=u();else{for(var Rb=yb.e(),Gb=new z(eb(Rb),u()),vb=Gb,Tb=yb.f();Tb!==u();){var Nb=Tb.e(),ic=new z(eb(Nb),u());vb=vb.p=ic;Tb=Tb.f()}kb=Gb}return Xq(kb,tb)}if(a instanceof rP){for(var Va=a.Ax,cb=null,zb=null;Va!==u();){var Ub=Va.e();if(Ub instanceof fe)var jb=\nUb.aa,db=O().c,ub=new z(jb,db);else{if(!(Ub instanceof Ud))throw new w(Ub);var Aa=Ub.fa,va=Aa.Yf.ha(),Ra=Aa.Rg,rb=O().c;ub=un(va,new z(Ra,rb))}for(var xb=ub.m();xb.s();){var mc=new z(xb.t(),u());null===zb?cb=mc:zb.p=mc;zb=mc}Va=Va.f()}return null===cb?u():cb}if(a instanceof qP){for(var Ha=a.Lw,Ka=a.Nw,Oa=a.Mw,Na=null,Da=null;Oa!==u();){for(var ta=Oa.e(),Ya=ta.h(),dc=ta.j(),ka=O().c,ya=new Om(new z(Ya,new z(dc,ka)));ya.s();){var Sa=new z(ya.t(),u());null===Da?Na=Sa:Da.p=Sa;Da=Sa}Oa=Oa.f()}for(var xc=\nnull===Na?u():Na,Sb=Ka,uc=null,Lb=null;Sb!==u();){for(var lc=Sb.e(),Xb=lc.Bi,ec=lc.Ci,Ab=O().c,Ob=new Om(new z(Xb,new z(ec,Ab)));Ob.s();){var fb=new z(Ob.t(),u());null===Lb?uc=fb:Lb.p=fb;Lb=fb}Sb=Sb.f()}var Wa=dl(null===uc?u():uc,xc);return new z(Ha,Wa)}if(a instanceof BP){var bb=a.yx;return dl(a.aA.ha(),bb)}if(a instanceof Zn){var Ia=a.Ch;return dl(GP(a.Yc).ha(),Ia)}if(a instanceof yo){var Ua=a.hg,pc=a.Sg,sc=a.Hj,Ba=a.mx,ob=a.Ns,nc=a.ei;if(Ua===u())var Ib=u();else{for(var vc=Ua.e(),Vb=new z(vc.j(),\nu()),fc=Vb,Bc=Ua.f();Bc!==u();){var Pb=Bc.e(),Jb=new z(Pb.j(),u());fc=fc.p=Jb;Bc=Bc.f()}Ib=Vb}var gc=Wn((pc.b()?new Gl(O().c):pc.o()).Ra,new HP(a)),Cb=sc.ha(),cc=Ba.ha(),yc=ob.ha(),Mc=new BP(Wn(ef(nc),new IP(a)),t().d),qc=O().c;return dl(dl(dl(dl(dl(new z(Mc,qc),yc),cc),Cb),gc),Ib)}throw new w(a);}\nvar jea=function JP(a,b,c,d){var g=DB(b);if(g instanceof lx)return tp(),a=c.Ig(g.Xa),gq(G(new H,a,g));if(g instanceof LA){var h=g.ic;b=g.jc;if(Pe(new E(g.tc),d.tc))return g=JP(a,h,c,d),a=JP(a,b,c,d),g.Ce(a);tp();a=t().d;return gq(G(new H,a,g))}tp();g=t().d;return gq(G(new H,g,b))};function BB(a,b,c,d,e,g){this.mA=this.kA=this.lA=this.Pu=this.bt=this.Lq=this.Vq=this.yA=null;if(null===a)throw null;this.Lq=a;this.bt=c;this.Pu=d;this.lA=e;this.kA=g;this.mA=b;FD(this,a,b)}BB.prototype=new HD;\nBB.prototype.constructor=BB;\nBB.prototype.Tb=function(a,b){var c=this.Lq.qa,d=this.Lq;if(d.F){var e=ut(Q(),\"| \",d.r)+(\"analyze2[\"+a+\"] \")+b;ff(gf(),e+\"\\n\")}d.r=1+d.r|0;try{if(b instanceof lx){var g=a.Ig(b.Xa);if(g instanceof L){var h=!!g.k;this.bt.oh(G(new H,h,b))&&LB(this.Lq,b,a,h,this.lA,this.kA,this.mA,this.bt,this.Pu)}else if(t().d===g){if(this.bt.oh(G(new H,!0,b))){var k=this.Lq,l=new RB(a,b.Xa,!0);LB(k,b,l,!0,this.lA,this.kA,this.mA,this.bt,this.Pu)}if(this.bt.oh(G(new H,!1,b))){var m=this.Lq,n=new RB(a,b.Xa,!1);LB(m,b,\nn,!1,this.lA,this.kA,this.mA,this.bt,this.Pu)}}else throw new w(g);}else if(b instanceof LA){var r=jea(this,b,a,b),v=this.Lq;if(v.F){var x=ut(Q(),\"| \",v.r)+\"Components \"+r;ff(gf(),x+\"\\n\")}if(this.Pu.oh(r))LB(this.Lq,b,a,b.tc,this.lA,this.kA,this.mA,this.bt,this.Pu);else{var A=this.Lq;if(A.F){var B=ut(Q(),\"| \",A.r)+\"Found in \"+this.Pu;ff(gf(),B+\"\\n\")}}}else GD.prototype.Tb.call(this,a,b);var C=void 0}finally{d.r=-1+d.r|0}dx(new E(c),d.qa)&&d.F&&(a=\"\"+ut(Q(),\"| \",d.r)+c.n(C),ff(gf(),a+\"\\n\"))};\nBB.prototype.$classData=q({HY:0},!1,\"mlscript.TypeSimplifier$Analyze2$1$\",{HY:1,kP:1,g:1});\nfunction KP(a){this.Dx=this.Kj=null;if(null===a)throw null;this.Dx=a;var b=t().d,c=Xu(),d=a.nP.m();c=c.Ib(new Ef(d,new y(x=>{var A=x.h();x=new qx(this.Dx,x.j(),new vl(x.h()));return G(new H,A,x)})));d=Xu().X();var e=a.Gd,g=Xu().X(),h=new MB;tp();var k=a.XE;if(k===u())var l=u();else{l=k.e();var m=l=new z(G(new H,l.Wl.V,l),u());for(k=k.f();k!==u();){var n=k.e();n=new z(G(new H,n.Wl.V,n),u());m=m.p=n;k=k.f()}}l=pp(0,l);m=Xu().X();k=t().d;n=Hw();var r=Su(),v=op().ga;this.Kj=new Iw(a,b,c,d,e,g,h,!1,!1,\nl,m,k,n.Hd(new Uu(r,v)));mf(this)}KP.prototype=new p;KP.prototype.constructor=KP;\nfunction mf(a){if(a.Dx.$c){var b=Xu(),c=a.Dx.qP,d=k=>{var l=new fx(a.Dx,k,nf(),a.Kj,new y(r=>{xm(r.pq)})),m=a.Kj.hc,n=G(new H,k.gb.V,l);m.$(n);return G(new H,k.gb.V,l)};if(c===u())d=u();else{var e=c.e(),g=e=new z(d(e),u());for(c=c.f();c!==u();){var h=c.e();h=new z(d(h),u());g=g.p=h;c=c.f()}d=e}b=b.Ib(d);b=new Iw(a.Kj.S,a.Kj.Ec,a.Kj.hc,a.Kj.Ed,a.Kj.da,a.Kj.Pc,a.Kj.Zc,a.Kj.Lb,a.Kj.yc,a.Kj.tb,b,a.Kj.od,a.Kj.cb);d=new y(k=>{throw k;});for(e=b.$a.ie();e.s();)g=e.t(),h=Kx(g,d),g=b.hc,c=h.Ua(),h=new ix(a.Dx,\nh),c=G(new H,c,h),g.$(c);return b}return a.Kj}KP.prototype.$classData=q({PY:0},!1,\"mlscript.Typer$Ctx$\",{PY:1,g:1,l:1});function LP(){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0;this.zk=this.Pq=this.Uq=this.xp=this.Bp=this.Cp=this.Sq=this.zp=this.Rq=this.wp=this.Ap=this.yp=this.Qq=this.Tq=null;this.Dp=0}LP.prototype=new NC;LP.prototype.constructor=LP;function MP(){}MP.prototype=LP.prototype;function tx(a){null===a.Tq&&null===a.Tq&&(a.Tq=new NP(a))}\nfunction zx(a){null===a.yp&&null===a.yp&&(a.yp=new OP(a));return a.yp}function kea(a){null===a.Ap&&null===a.Ap&&(a.Ap=new EC(a));return a.Ap}function vx(a){null===a.wp&&null===a.wp&&(a.wp=new PP(a));return a.wp}function CA(a){null===a.Rq&&null===a.Rq&&(a.Rq=new CC(a))}function xv(a){null===a.zp&&null===a.zp&&(a.zp=new QP(a));return a.zp}function $B(a){null===a.Sq&&null===a.Sq&&(a.Sq=new DC(a))}function cw(a){null===a.Bp&&null===a.Bp&&(a.Bp=new RP(a));return a.Bp}\nfunction WD(a){null===a.xp&&null===a.xp&&(a.xp=new SP(a));return a.xp}function TP(a){null===a.Uq&&null===a.Uq&&(a.Uq=new IC(a))}function iC(a){null===a.Pq&&null===a.Pq&&(a.Pq=new AC(a))}function UP(a){a.Dp=1+a.Dp|0;return-1+a.Dp|0}function PP(a){this.gO=null;if(null===a)throw null;this.gO=a}PP.prototype=new p;PP.prototype.constructor=PP;function wx(a,b,c){return b.b()?c:new eC(a.gO,b,c)}PP.prototype.$classData=q({cZ:0},!1,\"mlscript.TyperDatatypes$ConstrainedType$\",{cZ:1,g:1,l:1});\nfunction SP(a){this.Su=null;if(null===a)throw null;this.Su=a}SP.prototype=new p;SP.prototype.constructor=SP;function XD(a,b,c,d,e){if(null!==b){var g=b.qe;if(!0===b.Qd&&!0===g)return new Uw(a.Su,t().d,a.Su.La,e)}if(null!==b&&(g=b.qe,!0===b.Qd&&!1===g))return new Uw(a.Su,t().d,d,e);if(null!==b&&(g=b.qe,!1===b.Qd&&!0===g))return new Uw(a.Su,(t(),new L(c)),a.Su.La,e);if(null!==b&&(g=b.qe,!1===b.Qd&&!1===g))return new Uw(a.Su,(t(),new L(c)),d,e);throw new w(b);}\nSP.prototype.$classData=q({lZ:0},!1,\"mlscript.TyperDatatypes$FieldType$\",{lZ:1,g:1,l:1});function VP(){this.J=null}VP.prototype=new HC;VP.prototype.constructor=VP;function WP(){}WP.prototype=VP.prototype;function OP(a){this.sA=null;if(null===a)throw null;this.sA=a}OP.prototype=new p;OP.prototype.constructor=OP;\nfunction yx(a,b,c){for(;;){At(tp(),b<=a.sA.Df);if(Pe(new E(b),a.sA.Df)||c.Ea()<=b)return c;var d=uy(c);if(d instanceof Qx)c=d.de,d=d.Re,a=zx(a.sA),b=b<c?b:c,c=d;else return new Qx(a.sA,b,c)}}OP.prototype.$classData=q({uZ:0},!1,\"mlscript.TyperDatatypes$PolymorphicType$\",{uZ:1,g:1,l:1});function QP(a){this.tA=null;if(null===a)throw null;this.tA=a}QP.prototype=new p;QP.prototype.constructor=QP;function wv(a){var b=a.tA,c=O().c;return new Qv(b,c,V(a.tA))}\nfunction SA(a,b,c){return b.b()?new FA(a.tA,!1,c):new Qv(a.tA,b,c)}QP.prototype.$classData=q({yZ:0},!1,\"mlscript.TyperDatatypes$RecordType$\",{yZ:1,g:1,l:1});function RP(a){this.Vu=null;if(null===a)throw null;this.Vu=a}RP.prototype=new p;RP.prototype.constructor=RP;function kD(a,b,c,d){for(;;){var e=b,g=c;if(e instanceof cC)b=e.Fg,c=g;else if(g instanceof cC)c=g.Sf,b=e;else return new cC(a.Vu,b,c,d)}}\nfunction dw(a,b,c,d,e){if(Ot(new E(b),c)||Pe(new E(b),c))e=!0;else{if(pD(b)||pD(c))g=!1;else{g=Xu().X();var g=Zu(b,c,e,!0,g)}g?(g=Xu().X(),e=Zu(c,b,e,!0,g)):e=!1}return e?b:kD(a,b,c,d)}function ew(a){return V(a.Vu)}function tA(a,b,c,d){return Ot(new E(b),c)||Pe(new E(b),c)?b:kD(a,b,c,d)}RP.prototype.$classData=q({GZ:0},!1,\"mlscript.TyperDatatypes$TypeBounds$\",{GZ:1,g:1,l:1});function XP(){this.q=null}XP.prototype=new p;XP.prototype.constructor=XP;function YP(){}YP.prototype=XP.prototype;\nfunction ZP(a){this.WO=null;if(null===a)throw null;this.WO=a}ZP.prototype=new p;ZP.prototype.constructor=ZP;ZP.prototype.u=function(){return\"TypeRef\"};function $P(a,b,c,d){return new fw(a.WO,b,c,d)}ZP.prototype.$classData=q({JZ:0},!1,\"mlscript.TyperDatatypes$TypeRef$\",{JZ:1,g:1,l:1});function dC(a,b){this.ol=null;this.gt=0;this.wA=this.$m=null;this.QI=0;if(null===a)throw null;this.wA=a;this.QI=b;ZC(this,a.$m,a.ol)}dC.prototype=new aD;dC.prototype.constructor=dC;\ndC.prototype.Ig=function(a){return a>this.QI?(t(),new L(!0)):this.wA.Ig(a)};dC.prototype.Ar=function(a){return a>this.QI?this:this.wA.Ar(a)};dC.prototype.Bw=function(){return this.wA+\";Q(\"+this.wA.gt+\")\"};dC.prototype.$classData=q({SZ:0},!1,\"mlscript.TyperHelpers$PolMap$$anon$1\",{SZ:1,OE:1,g:1});function TB(a){this.ol=null;this.gt=0;this.RI=this.$m=null;if(null===a)throw null;this.RI=a;ZC(this,a.$m,t().d)}TB.prototype=new aD;TB.prototype.constructor=TB;TB.prototype.Ig=function(){return t().d};\nTB.prototype.Ar=function(a){return this.RI.Ar(a)};TB.prototype.Bw=function(){return this.RI+\";\\x3d\"};TB.prototype.$classData=q({TZ:0},!1,\"mlscript.TyperHelpers$PolMap$$anon$2\",{TZ:1,OE:1,g:1});function UB(a){this.ol=null;this.gt=0;this.PE=this.$m=null;if(null===a)throw null;this.PE=a;var b=a.$m;a=a.ol;a.b()?a=R():(a=!!a.o(),a=new L(!a));ZC(this,b,a)}UB.prototype=new aD;UB.prototype.constructor=UB;UB.prototype.Ig=function(a){a=this.PE.Ig(a);if(a.b())return R();a=!!a.o();return new L(!a)};\nUB.prototype.Ar=function(a){return this.PE.Ar(a)};UB.prototype.Bw=function(){return this.PE+\";-\"};UB.prototype.$classData=q({UZ:0},!1,\"mlscript.TyperHelpers$PolMap$$anon$3\",{UZ:1,OE:1,g:1});function RB(a,b,c){this.ol=null;this.gt=0;this.QE=this.hP=this.$m=null;this.gP=0;this.xA=!1;if(null===a)throw null;this.QE=a;this.gP=b;this.xA=c;ZC(this,a.$m,a.ol);this.hP=this.Ar(b)}RB.prototype=new aD;RB.prototype.constructor=RB;\nRB.prototype.Ig=function(a){if(a>=this.gP)return t(),new L(this.xA);var b=!1,c=null;a=this.hP.Ig(a);if(a instanceof L&&(b=!0,c=a,!0===!!c.k))return t(),new L(this.xA);if(b&&!1===!!c.k)return t(),new L(!this.xA);if(t().d===a)return t().d;throw new w(a);};RB.prototype.Ar=function(a){return this.QE.Ar(a)};RB.prototype.Bw=function(){var a=this.QE;t();return a+\";@[\"+dA(new L(this.xA))+\"](\"+this.QE.gt+\")\"};RB.prototype.$classData=q({VZ:0},!1,\"mlscript.TyperHelpers$PolMap$$anon$4\",{VZ:1,OE:1,g:1});\nfunction bD(a,b){this.ol=null;this.gt=0;this.SI=this.$m=null;if(null===a)throw null;this.SI=b;ZC(this,a.iP,b)}bD.prototype=new aD;bD.prototype.constructor=bD;bD.prototype.Ig=function(){return this.SI};bD.prototype.Ar=function(){return this};bD.prototype.Bw=function(){return\"\"+dA(this.SI)};bD.prototype.$classData=q({WZ:0},!1,\"mlscript.TyperHelpers$PolMap$$anon$5\",{WZ:1,OE:1,g:1});\nfunction gP(a){a=ef(a).m();a=new Ef(a,new y(b=>{if(b instanceof Pm)return Zz(b,!1);if(b instanceof Ct||b instanceof Po)return Mx(b);xm(\"Unexpected typing unit entity: \"+b)}));return ze(a,\"{\",\"; \",\"}\")}function lea(a,b){var c=AP(b),d=ef(a);a=k=>k instanceof Pm?aA(k,!1,c):k instanceof Ct?VO(k,c.fi):b.fi?no():k.u();if(d===u())a=u();else{var e=d.e(),g=e=new z(a(e),u());for(d=d.f();d!==u();){var h=d.e();h=new z(a(h),u());g=g.p=h;d=d.f()}a=e}e=\"{\"+ON(c);g=ON(c);d=ON(b)+\"}\";return ze(a,e,g,d)}\nfunction mea(a){var b=Wn(a.Kx,new aQ(a)),c=Aq(Bq(),b),d=a.Kx;a=h=>{if(h instanceof bm){var k=h.Vn,l=h.Zo;if(c.L(k.x))return new Zn(t().d,k,t().d,O().c,(t(),new fe(l)),t().d,t().d,t().d,t().d,t().d,!0,O().c)}return h};if(d===u())return u();b=d.e();var e=b=new z(a(b),u());for(d=d.f();d!==u();){var g=d.e();g=new z(a(g),u());e=e.p=g;d=d.f()}return b}function bQ(){this.Yl=this.AA=this.Zu=this.CP=null;cQ=this;this.CP=new dQ(!0,!0);this.Zu=new dQ(!0,!1);this.AA=new dQ(!1,!0);this.Yl=new dQ(!1,!1)}\nbQ.prototype=new p;bQ.prototype.constructor=bQ;bQ.prototype.$classData=q({g_:0},!1,\"mlscript.VarianceInfo$\",{g_:1,g:1,l:1});var cQ;function ou(){cQ||(cQ=new bQ);return cQ}function eQ(){}eQ.prototype=new p;eQ.prototype.constructor=eQ;function hr(a,b,c,d){return new Gf(UN(b.e().h(),c),b,d)}eQ.prototype.$classData=q({i_:0},!1,\"mlscript.WarningReport$\",{i_:1,g:1,l:1});var fQ;function fr(){fQ||(fQ=new eQ);return fQ}function gQ(){this.lf=null}gQ.prototype=new sE;gQ.prototype.constructor=gQ;\nfunction hQ(){}hQ.prototype=gQ.prototype;function iQ(a){a.fv=jA().X();a.ni=TE(PE());O()}function jQ(){this.ni=this.fv=null}jQ.prototype=new p;jQ.prototype.constructor=jQ;function kQ(){}kQ.prototype=jQ.prototype;function lQ(a){if(a instanceof HE)return\"Consequent\";if(IE()===a)return\"MissingCase\";if(a instanceof CE)return\"IfThenElse\";if(a instanceof DE)return\"Match\";throw new w(a);}function mQ(a,b,c,d,e){a.dm(b,new y(()=>{}),c,d,e)}function nQ(){this.ga=null;oQ=this;this.ga=new pQ}nQ.prototype=new p;\nnQ.prototype.constructor=nQ;nQ.prototype.$classData=q({U2:0},!1,\"scala.$less$colon$less$\",{U2:1,g:1,l:1});var oQ;function op(){oQ||(oQ=new nQ);return oQ}function WG(a){a=new (md(la).Ia)(a);yj(Pj(),a,void 0);return a}function qQ(){}qQ.prototype=new p;qQ.prototype.constructor=qQ;\nfunction rQ(a,b,c){a=b.Q();if(-1<a){c=c.si(a);b=b.m();for(var d=0;d<a;)fH(xG(),c,d,b.t()),d=1+d|0;return c}c=c.uh();d=c===da(td);a=[];for(b=b.m();b.s();){var e=b.t();a.push(d?Ea(e):null===e?c.qi.jz:e)}return md((c===da(pd)?da(la):c===da(jH)||c===da(kH)?da(jd):c).qi).iz(a)}function VG(a,b,c,d,e,g){a=ca(b);if($f(a)&&Zf(ca(d),a))b.wa(c,d,e,g);else for(a=c,c=c+g|0;a<c;)fH(xG(),d,e,XG(xG(),b,a)),a=1+a|0,e=1+e|0}\nfunction UG(a,b){if(ph(a))return WG(b);if(a instanceof zc)return zj(Pj(),a,b);if(a instanceof Xc)return Fj(Pj(),a,b);if(a instanceof ed){Pj();if(0>b)throw new Aj;var c=a.a.length;c=b<c?b:c;b=new ed(b);a.wa(0,b,0,c);return b}if(a instanceof Zc)return Gj(Pj(),a,b);if(a instanceof $c){Pj();if(0>b)throw new Aj;c=a.a.length;c=b<c?b:c;b=new $c(b);a.wa(0,b,0,c);return b}if(a instanceof Ic)return Hj(Pj(),a,b);if(a instanceof Pc)return Dj(Pj(),a,b);if(a instanceof Sc)return Ej(Pj(),a,b);if(a instanceof Ec)return Ij(Pj(),\na,b);throw new w(a);}function sQ(a,b,c){if(b===c)return!0;if(b.a.length!==c.a.length)return!1;a=b.a.length;for(var d=0;d<a;){if(!ml(nl(),b.a[d],c.a[d]))return!1;d=1+d|0}return!0}qQ.prototype.$classData=q({W2:0},!1,\"scala.Array$\",{W2:1,g:1,l:1});var tQ;function SG(){tQ||(tQ=new qQ);return tQ}function uQ(){this.jR=null;vQ=this;this.jR=new jL(ch().IQ);ch()}uQ.prototype=new p;uQ.prototype.constructor=uQ;function gf(){vQ||(vQ=new uQ);return vQ.jR.yR}\nuQ.prototype.$classData=q({Y2:0},!1,\"scala.Console$\",{Y2:1,g:1,nba:1});var vQ;function wQ(){}wQ.prototype=new mG;wQ.prototype.constructor=wQ;function xQ(){}xQ.prototype=wQ.prototype;function ps(a){return null===a?null:0===a.a.length?(a=yQ(),TG(),a.SL):new zQ(a)}function Ur(a,b){return null!==b?new AQ(b):null}function BQ(){}BQ.prototype=new p;BQ.prototype.constructor=BQ;function iu(a,b){if(b.b())return O().vR.X();O();a=b.o();return new CQ(a)}function zy(a,b,c){return b?new L(Es(c)):R()}\nBQ.prototype.$classData=q({c3:0},!1,\"scala.Option$\",{c3:1,g:1,l:1});var DQ;function ju(){DQ||(DQ=new BQ);return DQ}function Wk(a){var b=it();return b&&b.$classData&&b.$classData.rb.za?new EQ(a,b):new FQ(a,b)}function GQ(a,b,c){return a.Lc(b)?a.n(b):c.n(b)}function Gs(a){return!!(a&&a.$classData&&a.$classData.rb.E)}function aG(){}aG.prototype=new p;aG.prototype.constructor=aG;aG.prototype.u=function(){return\"Some\"};aG.prototype.$classData=q({o3:0},!1,\"scala.Some$\",{o3:1,g:1,l:1});var $F;\nfunction HQ(){}HQ.prototype=new p;HQ.prototype.constructor=HQ;\nfunction eda(a,b,c){var d=0,e=0,g=0,h=0,k=-1+b.K()|0;rl();if(0>=k)a=new Xc(0);else{a=new Xc(k);for(var l=0;l<k;)a.a[l]=-1,l=1+l|0}rl();if(0>=k)l=new Xc(0);else{l=new Xc(k);for(var m=0;m<k;)l.a[m]=-1,m=1+m|0}m=c.length;var n=new IQ(k);b.Ca(new y(N=>{n.ve=n.ve+N.length|0}));var r=n.ve,v=new Sc(r),x=new IQ(0),A=new GA(!0);b.Ca(new y(N=>{A.Am?A.Am=!1:(v.a[x.ve]=-1,x.ve=1+x.ve|0);for(var P=N.length,T=0;T<P;){var Y=N.charCodeAt(T);v.a[x.ve]=Y<<16>>16;x.ve=1+x.ve|0;T=1+T|0}}));var B=1+r|0;rl();if(0>=B)var C=\nnew Xc(0);else{for(var D=new Xc(B),F=0;F<B;)D.a[F]=-1,F=1+F|0;C=D}var I=new IQ(0),M=new IQ(0);for(b.Ca(new y(N=>{M.ve<k&&(I.ve=I.ve+N.length|0,C.a[I.ve]=M.ve,I.ve=1+I.ve|0,M.ve=1+M.ve|0)}));d<r||e<m;)if(B=C.a[d],-1!==B&&(D=a.a[B],-1===D?D=e:(F=e,D=D<F?D:F),a.a[B]=D,D=l.a[B],-1===D?D=e:(F=e,D=D>F?D:F),l.a[B]=D),d<r?(B=v.a[d],-1===B?(g=d,h=1+e|0,d=1+d|0,B=!0):e<m&&c.charCodeAt(e)===B?(d=1+d|0,e=1+e|0,B=!0):B=!1):B=!1,!B)if(0<h&&h<=m)d=g,e=h;else return R();JQ();b=-1+b.K()|0;if(0>=b)c=new (md(fa).Ia)(0);\nelse{d=new (md(fa).Ia)(b);for(e=0;e<b;)g=e,d.a[e]=Of(Q(),c,a.a[g],l.a[g]),e=1+e|0;c=d}return new L(KQ(0,c))}\nfunction Tq(a,b){a=vH(b,92);if(-1!==a){var c=a;a=b.length;for(var d=0,e=LQ(new Sq);0<=c;){c>d&&MQ(e,b,d,c);d=1+c|0;if(d>=a)throw new NQ(b,c);switch(b.charCodeAt(d)){case 117:c=117;break;case 98:c=8;break;case 116:c=9;break;case 110:c=10;break;case 102:c=12;break;case 114:c=13;break;case 34:c=34;break;case 39:c=39;break;case 92:c=92;break;default:throw new NQ(b,c);}if(117===c)a:for(var g=c=d,h=b.length,k=b;;){if(c>=h)throw new OQ(k,-1+c|0);if(117===k.charCodeAt(c))c=1+c|0;else{b:for(var l=0,m=0;;){if(4<=\nl){c=new PQ(65535&m,(c-g|0)+l|0);break b}if((l+c|0)>=h)throw new OQ(k,c+l|0);var n=k.charCodeAt(l+c|0);n=DH(Pr(),n,36);if(0<=n&&15>=n)m=(m<<4)+n|0,l=1+l|0;else throw new OQ(k,c+l|0);}break a}}else c=new PQ(c,1);if(null===c)throw new w(c);g=c.aQ();d=d+c.Sc()|0;c=String.fromCharCode(g);e.ja=\"\"+e.ja+c;c=d;g=b;h=TL(Pr(),92);g=g.indexOf(h,d)|0;d=c;c=g}d<a&&MQ(e,b,d,a);b=e.ja}return b}HQ.prototype.$classData=q({q3:0},!1,\"scala.StringContext$\",{q3:1,g:1,l:1});var QQ;\nfunction Qq(){QQ||(QQ=new HQ);return QQ}q({R4:0},!1,\"scala.collection.BuildFromLowPriority2$$anon$11\",{R4:1,g:1,Jba:1});function RQ(a,b){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;for(JH(this,b.dc);this.s();)b=this.wh.Jb(this.Nc),SQ(a,a.Nr,this.wh.Ef(this.Nc),this.wh.Tf(this.Nc),b,$G(bH(),b),0),this.Nc=1+this.Nc|0}RQ.prototype=new LH;RQ.prototype.constructor=RQ;RQ.prototype.$classData=q({$6:0},!1,\"scala.collection.immutable.HashMapBuilder$$anon$1\",{$6:1,Vv:1,g:1});\nfunction TQ(a,b){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;for(JH(this,b.Id);this.s();)b=this.wh.Jb(this.Nc),UQ(a,a.Or,this.wh.ed(this.Nc),b,$G(bH(),b),0),this.Nc=1+this.Nc|0}TQ.prototype=new LH;TQ.prototype.constructor=TQ;TQ.prototype.$classData=q({d7:0},!1,\"scala.collection.immutable.HashSetBuilder$$anon$1\",{d7:1,Vv:1,g:1});function VQ(){}VQ.prototype=new p;VQ.prototype.constructor=VQ;VQ.prototype.u=function(){return\"\\x3cfunction1\\x3e\"};VQ.prototype.n=function(){return this};\nVQ.prototype.$classData=q({t7:0},!1,\"scala.collection.immutable.List$$anon$1\",{t7:1,g:1,la:1});function WQ(){}WQ.prototype=new fI;WQ.prototype.constructor=WQ;function XQ(){}XQ.prototype=WQ.prototype;function YQ(a){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;JH(this,a)}YQ.prototype=new LH;YQ.prototype.constructor=YQ;YQ.prototype.$classData=q({Q7:0},!1,\"scala.collection.immutable.MapNodeRemoveAllSetNodeIterator\",{Q7:1,Vv:1,g:1});function ZQ(){}ZQ.prototype=new p;\nZQ.prototype.constructor=ZQ;function $Q(a,b,c,d,e){throw Kj(b+(e?\" to \":\" until \")+c+\" by \"+d+\": seqs cannot contain more than Int.MaxValue elements.\");}function aR(a){bR();return AH(a+\" on empty Range\")}ZQ.prototype.$classData=q({X7:0},!1,\"scala.collection.immutable.Range$\",{X7:1,g:1,l:1});var cR;function bR(){cR||(cR=new ZQ);return cR}function dR(){this.Uk=null}dR.prototype=new pJ;dR.prototype.constructor=dR;function eR(){}eR.prototype=dR.prototype;\nfunction fR(a,b,c,d){if(null===b)return nJ(),new sI(c,d,null,null,0);if(Object.is(c,b.Wa))return yJ(b,d);var e=a.Uk.Da(c,b.Wa);return 0>e?tJ(b,fR(a,b.sa,c,d)):0<e?xJ(b,fR(a,b.ta,c,d)):yJ(b,d)}function gR(){this.Uk=null}gR.prototype=new pJ;gR.prototype.constructor=gR;function hR(){}hR.prototype=gR.prototype;function iR(a,b,c){if(null===b)return nJ(),new sI(c,void 0,null,null,0);if(Object.is(c,b.Wa))return b;var d=a.Uk.Da(c,b.Wa);return 0>d?tJ(b,iR(a,b.sa,c)):0<d?xJ(b,iR(a,b.ta,c)):b}\nfunction jR(){}jR.prototype=new fI;jR.prototype.constructor=jR;function kR(){}kR.prototype=jR.prototype;function lR(a,b){if(b===a)a.zc(PE().vl(b));else for(b=b.m();b.s();)a.$(b.t());return a}function mR(a,b){var c=My(W(),b);c=nR(a,c);return oR(a,b,c)}function oR(a,b,c){for(a=a.bl().a[c];;)if(null!==a?(c=a.BB(),c=!ml(nl(),c,b)):c=!1,c)a=a.Ev();else break;return a}\nfunction pR(a,b,c){b.ty(a.bl().a[c]);a.bl().a[c]=b;a.hz(1+a.nu()|0);qR(a,c);if(a.nu()>a.pT()){b=a.bl().a.length<<1;c=a.bl();a.gM(new (md($J).Ia)(b));rR(a,a.bl().a.length);for(var d=-1+c.a.length|0;0<=d;){for(var e=c.a[d];null!==e;){var g=e.BB();g=My(W(),g);g=nR(a,g);var h=e.Ev();e.ty(a.bl().a[g]);a.bl().a[g]=e;e=h;qR(a,g)}d=-1+d|0}a.hM(fK(hK(),a.sJ(),b))}}function sR(a,b,c){var d=My(W(),b);d=nR(a,d);var e=oR(a,b,d);if(null!==e)return e;b=a.CJ(b,c);pR(a,b,d);return null}\nfunction tR(a,b){var c=My(W(),b);c=nR(a,c);return uR(a,b,c)}function uR(a,b,c){var d=a.bl().a[c];if(null!==d){var e=d.BB();if(ml(nl(),e,b))return a.bl().a[c]=d.Ev(),a.hz(-1+a.nu()|0),vR(a,c),d.ty(null),d;for(e=d.Ev();;){if(null!==e){var g=e.BB();g=!ml(nl(),g,b)}else g=!1;if(g)d=e,e=e.Ev();else break}if(null!==e)return d.ty(e.Ev()),a.hz(-1+a.nu()|0),vR(a,c),e.ty(null),e}return null}function qR(a,b){null!==a.lu()&&(a=a.lu(),b>>=5,a.a[b]=1+a.a[b]|0)}\nfunction vR(a,b){null!==a.lu()&&(a=a.lu(),b>>=5,a.a[b]=-1+a.a[b]|0)}function rR(a,b){if(null!==a.lu())if(b=1+(b>>5)|0,a.lu().a.length!==b)a.$L(new Xc(b));else{a=a.lu();Pj();b=a.a.length;for(var c=0;c!==b;)a.a[c]=0,c=1+c|0}}function nR(a,b){var c=-1+a.bl().a.length|0,d=Math.clz32(c);a=a.kT();OL||(OL=new NL);b=Math.imul(-1640532531,b);UH();b=Math.imul(-1640532531,b<<24|16711680&b<<8|65280&(b>>>8|0)|b>>>24|0);return((b>>>a|0|b<<(-a|0))>>>d|0)&c}\nfunction wR(a){a.bQ(750);hK();a.gM(new (md($J).Ia)(1<<(-Math.clz32(15)|0)));a.hz(0);var b=a.sJ();hK();hK();a.hM(fK(0,b,1<<(-Math.clz32(15)|0)));a.$L(null);b=a.jT;var c=-1+a.bl().a.length|0;c=nI(UH(),c);b.call(a,c)}function xR(a,b){this.YS=null;this.ju=a;this.Fn=b;this.zm=this.ww=null}xR.prototype=new p;xR.prototype.constructor=xR;xR.prototype.BB=function(){return this.ju};xR.prototype.ty=function(a){this.YS=a};xR.prototype.Ev=function(){return this.YS};\nxR.prototype.$classData=q({e$:0},!1,\"scala.collection.mutable.LinkedHashMap$LinkedEntry\",{e$:1,g:1,VL:1});function yR(a){this.eT=null;this.zw=a;this.Mo=this.yw=null}yR.prototype=new p;yR.prototype.constructor=yR;yR.prototype.BB=function(){return this.zw};yR.prototype.ty=function(a){this.eT=a};yR.prototype.Ev=function(){return this.eT};yR.prototype.$classData=q({k$:0},!1,\"scala.collection.mutable.LinkedHashSet$Entry\",{k$:1,g:1,VL:1});function zR(){this.xy=null;AR=this;this.xy=Ai().qM}\nzR.prototype=new p;zR.prototype.constructor=zR;\nfunction BR(a,b){var c=\"\"+a;a=new mr;nr(a,or(c),c.length);c=b.ds;var d=pr(a)-c|0;if(!(CR(a)<c||0===c||0>=d))if(64>a.$h){c=hN().lz.a[d];var e=c.W,g=c.Y,h=a.xb,k=h>>31,l=d>>31;c=h-d|0;h=(-2147483648^c)>(-2147483648^h)?-1+(k-l|0)|0:k-l|0;d=a.Bg;l=d.W;var m=d.Y;k=xa();d=$h(k,l,m,e,g);k=k.Qc;var n=xa();l=Ri(n,l,m,e,g);m=n.Qc;if(0!==l||0!==m){hN();if(0>m){var r=-l|0;n=0!==l?~m:-m|0}else r=l,n=m;n=new ma(r<<1,r>>>31|0|n<<1);e=new ma(e,g);g=n.Y;r=e.Y;(g===r?(-2147483648^n.W)>(-2147483648^e.W):g>r)?e=1:(g=\nn.Y,r=e.Y,e=(g===r?(-2147483648^n.W)<(-2147483648^e.W):g<r)?-1:0);e=Math.imul(0>m?-1:0===m&&0===l?0:1,5+e|0);e=lN(hN(),1&d,e,b.Fw);g=e>>31;e=d+e|0;d=(-2147483648^e)<(-2147483648^d)?1+(k+g|0)|0:k+g|0;0>d?(k=-e|0,g=0!==e?~d:-d|0):(k=e,g=d);k=cG(xa(),k,g);+Math.log10(k)>=b.ds?(c=-1+c|0,k=-1!==c?h:-1+h|0,h=xa(),d=$h(h,e,d,10,0),c=new ma(c,k),h=new ma(d,h.Qc)):(c=new ma(c,h),h=new ma(e,d))}else c=new ma(c,h),h=new ma(d,k);c=Za(c);d=Za(h);h=Za(new ma(c.W,c.Y));c=h.W;h=h.Y;k=Za(new ma(d.W,d.Y));d=k.W;k=\nk.Y;a.xb=mN(hN(),new ma(c,h));a.cs=b.ds;a.Bg=new ma(d,k);a.$h=gN(hN(),new ma(d,k));a.bs=null}else e=Pi(fi(),new ma(d,d>>31)),h=DR($M(a),e),k=a.xb,g=k>>31,l=d>>31,d=k-d|0,k=(-2147483648^d)>(-2147483648^k)?-1+(g-l|0)|0:g-l|0,0!==h.a[1].Ya&&(g=VM(h.a[1]),0!==g.Ya&&(Sh(),l=g.wb,m=1+l|0,n=new Xc(m),Nh(0,n,g.Qa,l),g=Hh(g.Ya,m,n),Ih(g)),g=fM(g,e),e=ER(h.a[0],0)?1:0,g=Math.imul(h.a[1].Ya,5+g|0),e=lN(hN(),e,g,b.Fw),0!==e&&(e=ri(Ph(),new ma(e,e>>31)),g=h.a[0],h.a[0]=li(vi(),g,e)),e=new mr,FR(e,h.a[0],0),pr(e)>\nc&&(h.a[0]=GR(h.a[0],Ph().mq),d=e=-1+d|0,k=-1!==e?k:-1+k|0)),a.xb=mN(hN(),new ma(d,k)),a.cs=c,HR(a,h.a[0]);return new tr(a,b)}zR.prototype.$classData=q({v3:0},!1,\"scala.math.BigDecimal$\",{v3:1,g:1,l:1});var AR;function lr(){AR||(AR=new zR);return AR}function IR(a,b){var c=b-a.yy|0,d=a.KK.a[c];null===d&&(d=JR(new KR,null,new ma(b,b>>31)),a.KK.a[c]=d);return d}\nfunction LR(){this.pR=this.LK=null;this.MB=this.yy=0;this.qR=this.KK=null;MR=this;this.LK=ri(Ph(),new ma(0,-2147483648));this.pR=JR(new KR,this.LK,new ma(0,-2147483648));this.yy=-1024;this.MB=1024;this.KK=new (md(NR).Ia)(1+(this.MB-this.yy|0)|0);this.qR=ri(Ph(),new ma(-1,-1))}LR.prototype=new p;LR.prototype.constructor=LR;function br(){var a=Tr();return 0>=a.yy&&0<=a.MB?IR(a,0):OR(a,new ma(0,0))}\nfunction OR(a,b){var c=a.yy,d=c>>31,e=b.Y;(d===e?(-2147483648^c)<=(-2147483648^b.W):d<e)?(c=a.MB,d=c>>31,e=b.Y,c=e===d?(-2147483648^b.W)<=(-2147483648^c):e<d):c=!1;return c?IR(a,b.W):0===b.W&&-2147483648===b.Y?a.pR:JR(new KR,null,b)}function Hp(a){var b=Tr();return PR(b,eM(a))}function Sr(a,b,c){return PR(a,QR(new TM,b,c))}\nfunction PR(a,b){if(63>=yh(Sh(),b)){var c=b.xl(),d=c.W;c=c.Y;var e=a.yy,g=e>>31;(g===c?(-2147483648^e)<=(-2147483648^d):g<c)?(e=a.MB,g=e>>31,e=c===g?(-2147483648^d)<=(-2147483648^e):c<g):e=!1;return e?IR(a,d):JR(new KR,b,new ma(d,c))}return JR(new KR,b,new ma(0,-2147483648))}LR.prototype.$classData=q({x3:0},!1,\"scala.math.BigInt$\",{x3:1,g:1,l:1});var MR;function NK(){MR||(MR=new LR);return MR}function RR(){}RR.prototype=new p;RR.prototype.constructor=RR;\nfunction yG(a,b){b===da(xd)?a=sL():b===da(Cd)?a=tL():b===da(td)?a=Ir():b===da(Ed)?a=rl():b===da(Fd)?a=qL():b===da(Gd)?a=rL():b===da(Ld)?a=pL():b===da(rd)?a=uL():b===da(pd)?a=SR():b===da(jd)?a=TG():b===da(kH)?(TR||(TR=new UR),a=TR):b===da(jH)?(VR||(VR=new WR),a=VR):a=new jB(b);return a}RR.prototype.$classData=q({U3:0},!1,\"scala.reflect.ClassTag$\",{U3:1,g:1,l:1});var YR;function zG(){YR||(YR=new RR);return YR}function ZR(){}ZR.prototype=new p;ZR.prototype.constructor=ZR;function aS(){}\naS.prototype=ZR.prototype;ZR.prototype.u=function(){return\"\\x3cfunction0\\x3e\"};function bS(){}bS.prototype=new p;bS.prototype.constructor=bS;function cS(){}cS.prototype=bS.prototype;bS.prototype.u=function(){return\"\\x3cfunction1\\x3e\"};function dS(){}dS.prototype=new p;dS.prototype.constructor=dS;function eS(){}eS.prototype=dS.prototype;function fS(){}fS.prototype=new p;fS.prototype.constructor=fS;function gS(){}gS.prototype=fS.prototype;fS.prototype.u=function(){return\"\\x3cfunction2\\x3e\"};\nfunction hS(){}hS.prototype=new p;hS.prototype.constructor=hS;function iS(){}iS.prototype=hS.prototype;hS.prototype.u=function(){return\"\\x3cfunction3\\x3e\"};function jS(){}jS.prototype=new p;jS.prototype.constructor=jS;function kS(){}kS.prototype=jS.prototype;function lS(){}lS.prototype=new p;lS.prototype.constructor=lS;function mS(){}mS.prototype=lS.prototype;function GA(a){this.Am=a}GA.prototype=new p;GA.prototype.constructor=GA;GA.prototype.u=function(){return\"\"+this.Am};\nGA.prototype.$classData=q({X$:0},!1,\"scala.runtime.BooleanRef\",{X$:1,g:1,l:1});function IQ(a){this.ve=a}IQ.prototype=new p;IQ.prototype.constructor=IQ;IQ.prototype.u=function(){return\"\"+this.ve};IQ.prototype.$classData=q({Z$:0},!1,\"scala.runtime.IntRef\",{Z$:1,g:1,l:1});function bv(){this.So=this.Ro=!1}bv.prototype=new p;bv.prototype.constructor=bv;function Yu(a,b){a.So=b;a.Ro=!0;return b}bv.prototype.u=function(){return\"LazyBoolean \"+(this.Ro?\"of: \"+this.So:\"thunk\")};\nbv.prototype.$classData=q({$$:0},!1,\"scala.runtime.LazyBoolean\",{$$:1,g:1,l:1});function $e(){this.sb=!1;this.vb=null}$e.prototype=new p;$e.prototype.constructor=$e;function me(a,b){a.vb=b;a.sb=!0;return b}$e.prototype.u=function(){return\"LazyRef \"+(this.sb?\"of: \"+this.vb:\"thunk\")};$e.prototype.$classData=q({aaa:0},!1,\"scala.runtime.LazyRef\",{aaa:1,g:1,l:1});function aw(a){this.rc=a}aw.prototype=new p;aw.prototype.constructor=aw;aw.prototype.u=function(){return\"\"+this.rc};\naw.prototype.$classData=q({eaa:0},!1,\"scala.runtime.ObjectRef\",{eaa:1,g:1,l:1});function IK(){}IK.prototype=new p;IK.prototype.constructor=IK;IK.prototype.$classData=q({m4:0},!1,\"scala.util.Either$\",{m4:1,g:1,l:1});var HK;function KK(){}KK.prototype=new p;KK.prototype.constructor=KK;KK.prototype.u=function(){return\"Left\"};KK.prototype.$classData=q({o4:0},!1,\"scala.util.Left$\",{o4:1,g:1,l:1});var JK;function MK(){}MK.prototype=new p;MK.prototype.constructor=MK;MK.prototype.u=function(){return\"Right\"};\nMK.prototype.$classData=q({q4:0},!1,\"scala.util.Right$\",{q4:1,g:1,l:1});var LK;function nS(){this.mG=this.PB=this.Cr=this.rg=0;oS=this;this.rg=lb(\"Seq\");this.Cr=lb(\"Map\");this.PB=lb(\"Set\");this.mG=CL(this,O().c,this.Cr)}nS.prototype=new xL;nS.prototype.constructor=nS;function pS(a,b,c){return zL(a,My(W(),b),My(W(),c))}\nfunction qS(a){var b=BL();if(a&&a.$classData&&a.$classData.rb.hd)a:{var c=b.rg,d=a.K();switch(d){case 0:b=b.Ma(c,0);break a;case 1:d=c;a=a.va(0);b=b.Ma(b.C(d,My(W(),a)),1);break a;default:var e=a.va(0),g=My(W(),e);e=c=b.C(c,g);var h=a.va(1);h=My(W(),h);var k=h-g|0;for(g=2;g<d;){c=b.C(c,h);var l=a.va(g);l=My(W(),l);if(k!==(l-h|0)){c=b.C(c,l);for(g=1+g|0;g<d;)e=a.va(g),c=b.C(c,My(W(),e)),g=1+g|0;b=b.Ma(c,d);break a}h=l;g=1+g|0}b=yL(b.C(b.C(e,k),h))}}else if(a instanceof rS){d=b.rg;g=0;h=d;c=e=l=k=0;\nfor(var m=a;!m.b();){a=m.e();m=m.f();a=My(W(),a);h=b.C(h,a);switch(k){case 0:c=a;k=1;break;case 1:l=a-e|0;k=2;break;case 2:l!==(a-e|0)&&(k=3)}e=a;g=1+g|0}2===k?(a=l,b=yL(b.C(b.C(b.C(d,c),a),e))):b=b.Ma(h,g)}else a:if(d=b.rg,a=a.m(),a.s())if(c=a.t(),a.s()){e=a.t();h=My(W(),c);c=d=b.C(d,h);g=My(W(),e);h=g-h|0;for(e=2;a.s();){d=b.C(d,g);k=a.t();k=My(W(),k);if(h!==(k-g|0)){d=b.C(d,k);for(e=1+e|0;a.s();)c=a.t(),d=b.C(d,My(W(),c)),e=1+e|0;b=b.Ma(d,e);break a}g=k;e=1+e|0}b=yL(b.C(b.C(c,h),g))}else b=b.Ma(b.C(d,\nMy(W(),c)),1);else b=b.Ma(d,0);return b}nS.prototype.$classData=q({t4:0},!1,\"scala.util.hashing.MurmurHash3$\",{t4:1,Iba:1,g:1});var oS;function BL(){oS||(oS=new nS);return oS}function sS(){this.SK=this.QK=this.PK=0;this.RK=1}sS.prototype=new p;sS.prototype.constructor=sS;sS.prototype.u=function(){return\"\\x3cfunction2\\x3e\"};sS.prototype.ey=function(a,b){a=pS(BL(),a,b);this.PK=this.PK+a|0;this.QK^=a;this.RK=Math.imul(this.RK,1|a);this.SK=1+this.SK|0};sS.prototype.ba=function(a,b){this.ey(a,b)};\nsS.prototype.$classData=q({u4:0},!1,\"scala.util.hashing.MurmurHash3$accum$1\",{u4:1,g:1,kz:1});function Zp(){this.nG=null}Zp.prototype=new p;Zp.prototype.constructor=Zp;Zp.prototype.u=function(){return this.nG.eR};Zp.prototype.$classData=q({w4:0},!1,\"scala.util.matching.Regex\",{w4:1,g:1,l:1});function tS(){this.yQ=null;this.NF=0}tS.prototype=new p;tS.prototype.constructor=tS;function uS(){}uS.prototype=tS.prototype;tS.prototype.u=function(){return this.yQ};\ntS.prototype.i=function(a){return this===a};tS.prototype.B=function(){return Qb(this)};tS.prototype.sl=function(a){var b=this.NF;a=a.NF;return b===a?0:b<a?-1:1};function vS(a,b){yF(a,b,null,!0);return a}class wS extends Vd{}wS.prototype.$classData=q({OF:0},!1,\"java.lang.Error\",{OF:1,pc:1,g:1,l:1});class xF extends Vd{}xF.prototype.$classData=q({qd:0},!1,\"java.lang.Exception\",{qd:1,pc:1,g:1,l:1});function xS(){}xS.prototype=new p;xS.prototype.constructor=xS;function yS(){}yS.prototype=xS.prototype;\nxS.prototype.u=function(){for(var a=this.vv(),b=\"[\",c=!0;a.s();)c?c=!1:b+=\", \",b=\"\"+b+a.t();return b+\"]\"};function GN(a){this.vB=this.iK=0;this.hK=this.wB=null;if(null===a)throw null;this.hK=a;this.iK=a.wl.a.length}GN.prototype=new CN;GN.prototype.constructor=GN;GN.prototype.$classData=q({X1:0},!1,\"java.util.HashMap$NodeIterator\",{X1:1,aba:1,g:1,p2:1});function zS(){this.mz=null;this.oz=this.pz=0;this.qz=this.nz=null;this.Rn=0}zS.prototype=new p;zS.prototype.constructor=zS;function AS(){}\nf=AS.prototype=zS.prototype;f.Vj=function(){if(this instanceof um){var a=this.Xo;var b=this.Tn,c=this.Un,d=O().c;a=new z(a,new z(b,new z(c,d)))}else if(this instanceof ym)a=this.dn,b=O().c,a=new z(a,b);else if(zm()===this)a=O().c;else throw new w(this);return a};f.jn=function(){0===(1&this.Rn)<<24>>24&&0===(1&this.Rn)<<24>>24&&(this.mz=zq(this),this.Rn=(1|this.Rn)<<24>>24);return this.mz};f.rn=function(){return this.pz};f.fm=function(a){this.pz=a};f.qn=function(){return this.oz};\nf.em=function(a){this.oz=a};f.pn=function(){return this.nz};f.on=function(a){this.nz=a};f.A=function(){0===(2&this.Rn)<<24>>24&&0===(2&this.Rn)<<24>>24&&(this.qz=Dq(this),this.Rn=(2|this.Rn)<<24>>24);return this.qz};function BS(){this.rs=null;this.ts=this.us=0;this.vs=this.ss=null;this.dl=0}BS.prototype=new p;BS.prototype.constructor=BS;function CS(){}f=CS.prototype=BS.prototype;f.Vj=function(){return Zda(this)};\nf.jn=function(){0===(1&this.dl)<<24>>24&&0===(1&this.dl)<<24>>24&&(this.rs=zq(this),this.dl=(1|this.dl)<<24>>24);return this.rs};f.rn=function(){return this.us};f.fm=function(a){this.us=a};f.qn=function(){return this.ts};f.em=function(a){this.ts=a};f.pn=function(){return this.ss};f.on=function(a){this.ss=a};f.A=function(){0===(2&this.dl)<<24>>24&&0===(2&this.dl)<<24>>24&&(this.vs=Dq(this),this.dl=(2|this.dl)<<24>>24);return this.vs};function DS(){}DS.prototype=new qO;DS.prototype.constructor=DS;\nfunction ES(){}ES.prototype=DS.prototype;function Xo(a,b,c){a.Bu=b;a.AH=c;return a}function Yo(){this.AH=this.Bu=null}Yo.prototype=new fO;Yo.prototype.constructor=Yo;function FS(){}FS.prototype=Yo.prototype;Yo.prototype.sh=function(){return 20};Yo.prototype.xa=function(){return Rp(Rp(Rp(Pp(this.Bu.xa(),20>this.Bu.sh()||this.Bu instanceof vo||this.Bu instanceof $m),Sp(Qp(),\"[\")),this.AH.xa()),Sp(Qp(),\"]\"))};Yo.prototype.VJ=function(){return this.Bu.VJ()};\nYo.prototype.$classData=q({lN:0},!1,\"mlscript.JSMember\",{lN:1,Vi:1,Xc:1,g:1});function GS(){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0;this.zk=this.Pq=this.Uq=this.xp=this.Bp=this.Cp=this.Sq=this.zp=this.Rq=this.wp=this.Ap=this.yp=this.Qq=this.Tq=null;this.Dp=0;this.yq=this.Aq=this.Bq=this.zq=this.Dq=this.Cq=null}GS.prototype=new MP;GS.prototype.constructor=GS;function HS(){}HS.prototype=GS.prototype;\nfunction Vu(a){null===a.Cq&&null===a.Cq&&(a.Cq=new IS(a));return a.Cq}function lw(a){null===a.Dq&&null===a.Dq&&(a.Dq=new JS(a));return a.Dq}function $A(a){null===a.zq&&null===a.zq&&(a.zq=new KO(a));return a.zq}function xB(a){null===a.Aq&&null===a.Aq&&(a.Aq=new NO(a));return a.Aq}function GO(a){null===a.yq&&null===a.yq&&(a.yq=new AO(a));return a.yq}function vD(a){return Pe(new E(a),!0)}function Ev(a){return Pe(new E(a),!0)}\nfunction Bw(a,b,c,d,e){var g=Su(),h=op().ga;g=new Uu(g,h);h=sv();var k=c.Q()+d.Q()|0;d=Lv(Lv(Mv(8<k?k:8),c),d);c=Xu().X();for(d=sl(d).m();d.s();){var l=d.t();k=l.h();var m=c.U(k);if(m instanceof L){m=m.k;var n=l.j();up(tp(),Pe(new E(m.qb),n.qb));tp();l=m.Zb.K();up(0,Pe(new E(l),n.Zb.K()));l=m.qb;m=m.Zb;m=new Wq(m,m,n.Zb);n=new fn(((r,v)=>(x,A)=>{if(r){var B=cw(a),C=V(x.q);C=Pu(x,A,C,!1);var D=V(x.q);return dw(B,C,dv(x,A,D,!1),ew(cw(a)),v)}B=cw(a);C=V(x.q);C=dv(x,A,C,!1);D=V(x.q);return dw(B,C,Pu(x,\nA,D,!1),ew(cw(a)),v)})(b,e));Yq();m=Ew(m,n);l=new fw(a,l,m,V(a))}else{if(R()!==m)throw new w(m);l=l.j()}c.bj(k,l)}b=qp();return Ov(h,(new Pv(b)).vc(c),g)}class KS extends Vd{constructor(a){super();this.lX=a;yF(this,null,null,!0)}}KS.prototype.$classData=q({kX:0},!1,\"mlscript.NotAType\",{kX:1,pc:1,g:1,l:1});function LS(a,b,c,d){this.QH=this.KN=this.vE=this.Vq=this.yA=null;if(null===a)throw null;this.vE=a;this.KN=c;this.QH=d;FD(this,a.nc,b)}LS.prototype=new HD;LS.prototype.constructor=LS;\nLS.prototype.Kp=function(a,b){JD(this,a,b)};\nLS.prototype.Tb=function(a,b){var c=this.vE.nc.qa,d=this.vE.nc;if(d.F){var e=ut(Q(),\"| \",d.r)+(\"Trav(\"+a+\")(\"+b)+\")\";ff(gf(),e+\"\\n\")}d.r=1+d.r|0;try{if(b instanceof lx){var g=this.KN,h=a.Ig(b.Xa);if(g.oh(G(new H,h,b))){var k=this.QH,l=this.QH.Se(b,new U(()=>ou().CP)),m=!1,n=null,r=a.Ig(b.Xa);a:{if(r instanceof L&&(m=!0,n=r,!0===!!n.k)){var v=ou().Zu;break a}if(m&&!1===!!n.k)v=ou().AA;else if(t().d===r)v=ou().Yl;else throw new w(r);}k.bh(b,new dQ(l.Qd&&v.Qd,l.qe&&v.qe));GD.prototype.Tb.call(this,a,\nb)}}else if(b instanceof Qv){m=this.vE.nc;k=Z=>uH(Q(),Z.h().x,35);var x=b.Ba;a:for(;;)if(x.b()){n=u();break}else{var A=x.e(),B=x.f();if(!0===!!k(A))x=B;else for(l=x,r=B;;){if(r.b())n=l;else{var C=r.e();if(!0!==!!k(C)){r=r.f();continue}C=r;var D=new z(l.e(),u()),F=l.f();for(l=D;F!==C;){var I=new z(F.e(),u());l=l.p=I;F=F.f()}var M=C.f();for(F=M;!M.b();){var N=M.e();if(!0===!!k(N)){for(;F!==M;){var P=new z(F.e(),u());l=l.p=P;F=F.f()}F=M.f()}M=M.f()}F.b()||(l.p=F);n=D}break a}}var T=new Qv(m,n,b.Nj);\nGD.prototype.Tb.call(this,a,T)}else GD.prototype.Tb.call(this,a,b);var Y=void 0}finally{d.r=-1+d.r|0}dx(new E(c),d.qa)&&d.F&&(a=\"\"+ut(Q(),\"| \",d.r)+c.n(Y),ff(gf(),a+\"\\n\"))};LS.prototype.$classData=q({CX:0},!1,\"mlscript.NuTypeDefs$TypedNuCls$Trav$1$\",{CX:1,kP:1,g:1,YZ:1});function MS(a,b){if(null===b)throw null;a.nc=b;var c=a.aG().ie();c=new Ef(c,new y(e=>{e=e.Ua();return new vl(e)}));a.px=Aq(Bq(),c);c=a.Yr().A();a=cy(a.Yr());tx(b);var d=t().d;jx(new kx,b,c,a,d,!0)}\nfunction Cx(){this.nc=this.px=null}Cx.prototype=new p;Cx.prototype.constructor=Cx;function NS(){}NS.prototype=Cx.prototype;Cx.prototype.A=function(){return this.Yr().A()};Cx.prototype.bG=function(){return this.nc};function OS(a,b){a.nd=(t(),new L(b));b=b.A();return Cq(a,b)}\nvar hu=function PS(a){var c=a.nd;if(c instanceof L)return PS(c.k);if(t().d===c){var d=!1,e=null,g=!1,h=null,k=!1,l=!1,m=null;c=!1;var n=null;if(a instanceof Ml){d=!0;e=a;var r=e.Ml;if(r instanceof Ml)return PS(r.Ml)}if(d)return\"annotated \"+PS(e.Ml);if(a instanceof Fl){g=!0;h=a;d=h.gg;if(!0===h.bi)a:{if(d instanceof Gl&&(e=d.Ra,e instanceof z&&e.p instanceof z)){d=!0;break a}if(d instanceof Gl&&(e=d.Ra,e instanceof z&&(e=e.z,null!==e&&e.h()instanceof L))){d=!0;break a}d=d instanceof Sl?!0:!1}else d=\n!1;if(d)return\"record\"}if(g)return PS(h.gg);if(a instanceof Sl&&(k=!0,h=a.Dj,h instanceof z&&(g=h.z,h=h.p,g instanceof Pm&&(d=O().c,null===d?null===h:d.i(h)))))return PS(g);if(k)return\"block of statements\";if(a instanceof Em)return\"integer literal\";if(a instanceof Fm)return\"decimal literal\";if(a instanceof Dm)return\"string literal\";if(a instanceof Gm)return a.Xq?\"undefined literal\":\"null literal\";if(a instanceof vl)return\"reference\";if(a instanceof Cl)return\"type ascription\";if(a instanceof Ol)return\"lambda expression\";\nif(a instanceof Pl&&(l=!0,m=a,k=m.Za,null!==k&&(k=fz(iz(),k),!k.b()&&(k=k.o().h(),k instanceof vl&&\"|\"===k.x))))return\"type union\";if(l&&(k=m.Za,null!==k&&(k=fz(iz(),k),!k.b()&&(k=k.o().h(),k instanceof vl&&\"\\x26\"===k.x))))return\"type intersection\";if(l&&(m=m.Za,null!==m&&!fz(iz(),m).b())||null!==a&&!fz(iz(),a).b())return\"operator application\";if(l)return\"application\";if(a instanceof yl)return\"record\";if(a instanceof Ql)return\"field selection\";if(a instanceof Rl)return\"let binding\";if(a instanceof\nGl&&(c=!0,n=a,l=n.Ra,l instanceof z&&(m=l.z,l=l.p,null!==m&&(k=m.h(),m=m.j(),t().d===k&&null!==m&&(m=m.ya,k=O().c,null===k?null===l:k.i(l))))))return PS(m);if(c&&(l=n.Ra,l instanceof z&&(n=l.z,l=l.p,null!==n&&(n.h()instanceof L?(n=O().c,n=null===n?null===l:n.i(l)):n=!1,n))))return\"binding\";if(c)return\"tuple\";if(a instanceof Tl)return\"`with` extension\";if(a instanceof Ul)return\"`case` expression\";if(a instanceof Vl)return\"array access\";if(a instanceof Wl)return\"assignment\";if(a instanceof dm)return\"while loop\";\nif(a instanceof Yl)return\"new instance\";if(a instanceof cm)return\"refinement\";if(a instanceof Xl)return\"if-else block\";if(a instanceof Il)return\"type application\";if(a instanceof $l)return\"constraint clause\";if(a instanceof Zl)return\"forall clause\";if(a instanceof Kl)return\"explicit instantiation\";if(a instanceof am)return\"super\";if(a instanceof bm)return\"assign for ctor\";if(a instanceof em)return\"quasiquote\";if(a instanceof fm)return\"unquote\";throw new w(a);}throw new w(c);},Zz=function QS(a,b){var d=\n!1,e=null,g=!1,h=null,k=!1,l=null;if(a instanceof Ml)return l=a.Ml,\"\"+RS(\"@\"+QS(a.gs,!1)+\" \",b)+QS(l,!1);if(a instanceof Fl){d=!0;e=a;var m=e.gg;if(!0===e.bi)return\"'{' \"+QS(m,!1)+\" '}'\"}if(d&&(d=e.gg,!1===e.bi))return\"'(' \"+QS(d,!1)+\" ')'\";if(a instanceof Sl)return b=a.Dj.m(),b=new Ef(b,new y(n=>n.Wr())),ze(b,\"{\",\"; \",\"}\");if(a instanceof Em)return a.rq.u();if(a instanceof Fm)return a.uu.gd.u();if(a instanceof Dm)return b=a.Lu,\"\"+String.fromCharCode(34)+b+'\"';if(a instanceof Gm)return a.Xq?\"undefined\":\n\"null\";if(a instanceof vl)return b=a.x,a=a.kt,a=a.b()?\"\":\"::\"+(a.o()|0),b+a;if(a instanceof Cl)return l=a.Fm,a=QS(a.ai,!1)+\" : \"+VO(l,!0),RS(a,b);if(a instanceof Ol&&(g=!0,h=a,e=h.Ej,d=h.Fj,e instanceof Gl))return a=\"(\"+Yz(e)+\") \\x3d\\x3e \"+QS(d,!1),RS(a,b);if(g)return a=h.Fj,a=\"(...\"+QS(h.Ej,!1)+\") \\x3d\\x3e \"+QS(a,!1),RS(a,b);if(a instanceof Pl&&(k=!0,l=a,h=l.Za,g=l.Qb,g instanceof Gl))return a=QS(h,!(h instanceof Pl))+\"(\"+Yz(g)+\")\",RS(a,b);if(k)return a=l.Za,l=l.Qb,a=QS(a,!(a instanceof Pl))+\"(...\"+\nQS(l,!0)+\")\",RS(a,b);if(a instanceof yl)return b=a.ll.m(),b=new Ef(b,new y(n=>(n.j().yb.je?\"mut \":\"\")+n.h().x+\": \"+QS(n.j().ya,!1))),ze(b,\"{\",\", \",\"}\");if(a instanceof Ql)return b=a.ml,\"(\"+QS(a.Vl,!1)+\").\"+QS(b,!1);if(a instanceof Rl&&(l=a.ep,k=a.Zn,h=a.$n,g=a.Mm,null!==k))return a=\"let\"+(l?\" rec\":\"\")+\" \"+k.x+\" \\x3d \"+QS(h,!1)+\" in \"+QS(g,!1),RS(a,b);if(a instanceof Gl)return\"[\"+Yz(a)+\"]\";if(a instanceof Tl)return l=a.ar,a=QS(a.br,!1)+\" with \"+QS(l,!1),RS(a,b);if(a instanceof Ul)return l=a.Hm,a=\"case \"+\nQS(a.Sn,!1)+\" of { \"+Wda(l,!0)+\" }\",RS(a,b);if(a instanceof Vl)return b=a.mp,\"(\"+QS(a.lp,!1)+\")[\"+QS(b,!1)+\"]\";if(a instanceof Wl)return l=a.Qn,a=QS(a.Gm,!1)+\" \\x3c- \"+QS(l,!1),RS(a,b);if(a instanceof dm)return l=a.Zq,a=\"while \"+QS(a.$q,!1)+\" do \"+QS(l,!1),RS(a,b);if(a instanceof Yl)return a=\"new \"+QS(a.hp,!1),RS(a,b);if(a instanceof Xl)return l=a.zs,a=$da(a.bp),l.b()?l=\"\":(l=l.o(),l=\" else \"+QS(l,!1)),RS(\"if \"+a+l,b);if(a instanceof Il)return l=a.np,b=QS(a.nl,!1),a=l.m(),a=new Ef(a,new y(n=>VO(n,\n!0))),b+\"\\u2039\"+ze(a,\"\",\", \",\"\")+\"\\u203a\";if(a instanceof $l)return l=a.lt,b=QS(a.Yq,!1),a=l.m(),a=new Ef(a,new y(n=>n.Wr())),b+\" where {\"+ze(a,\"\",\"; \",\"\")+\"}\";if(a instanceof Zl)return b=a.$o,\"forall \"+ze(a.qq,\"\",\", \",\"\")+\". \"+QS(b,!1);if(a instanceof Kl)return QS(a.cp,!0)+\"!\";if(a instanceof am)return\"super\";if(a instanceof bm)return b=a.Zo,QS(a.Vn,!1)+\" \\x3d \"+QS(b,!1);if(a instanceof em)return'code\"'+QS(a.Iq,!1)+'\"';if(a instanceof fm)return\"${\"+QS(a.jt,!1)+\"}\";if(a instanceof cm)return b=a.Zs,\nQS(a.Ys,!1)+\" \"+gP(b);throw new w(a);},aA=function SS(a,b,c){var e=!1,g=null,h=!1,k=null,l=!1,m=null;if(a instanceof Ml)return m=a.Ml,TS(\"@\"+a.gs.u()+\" \"+SS(m,!1,c),b);if(a instanceof Fl){e=!0;g=a;var n=g.gg;if(!0===g.bi)return SS(n,!1,c)}if(e&&(e=g.gg,!1===g.bi))return\"(\"+SS(e,!1,c)+\")\";if(a instanceof Sl){l=a.Dj;var r=AP(c);b=x=>x instanceof Pm?SS(x,!1,r):x instanceof Ct?VO(x,r.fi):c.fi?no():x.u();if(l===u())b=u();else{a=l.e();m=a=new z(b(a),u());for(l=l.f();l!==u();)k=l.e(),k=new z(b(k),u()),m=\nm.p=k,l=l.f();b=a}a=\"{\"+ON(r);m=ON(r);l=yP(c)+\"\\n}\";return ze(b,a,m,l)}if(a instanceof Em)return a.rq.u();if(a instanceof Fm)return a.uu.gd.u();if(a instanceof Dm)return b=a.Lu,\"\"+String.fromCharCode(34)+b+'\"';if(a instanceof Gm)return b=a.Xq,c.fi?\"()\":b?\"undefined\":\"null\";if(a instanceof vl)return a.x;if(a instanceof Cl)return a=a.ai+\" : \"+VO(a.Fm,c.fi),TS(a,b);if(a instanceof Ol&&(h=!0,k=a,g=k.Ej,e=k.Fj,g instanceof Gl))return a=\"(\"+$z(g,c)+\") \\x3d\\x3e \"+SS(e,!1,c),TS(a,b);if(h)return a=k.Fj,a=\n\"(...\"+SS(k.Ej,!1,c)+\") \\x3d\\x3e \"+SS(a,!1,c),TS(a,b);if(a instanceof Pl&&(l=!0,m=a,k=m.Za,h=m.Qb,h instanceof Gl))return a=SS(k,!(k instanceof Pl),c)+\"(\"+$z(h,c)+\")\",TS(a,b);if(l)return a=m.Za,m=m.Qb,a=SS(a,!(a instanceof Pl),c)+\"(...\"+SS(m,!0,c)+\")\",TS(a,b);if(a instanceof yl){var v=AP(c);b=a.ll.m();b=new Ef(b,new y(x=>(x.j().yb.je?\"mut \":\"\")+x.h().x+\": \"+SS(x.j().ya,!1,v)));a=\"{\"+ON(v);m=\",\"+ON(v);l=ON(c)+\"}\";return ze(b,a,m,l)}if(a instanceof Ql)return b=a.Vl,a=a.ml,SS(b,!(b instanceof wm),c)+\n\".\"+a;if(a instanceof Rl)return m=a.$n,l=a.Mm,a=\"let\"+(a.ep?\" rec\":\"\")+\" \"+SS(a.Zn,!1,c)+\" \\x3d \"+SS(m,!1,c)+\" in \"+SS(l,!1,c),TS(a,b);if(a instanceof Gl)return\"[\"+$z(a,c)+\"]\";if(a instanceof Tl)return m=a.ar,a=SS(a.br,!1,c)+\" with \"+SS(m,!1,c),TS(a,b);if(a instanceof Ul)return m=a.Hm,a=\"case \"+SS(a.Sn,!1,c)+\" of {\"+Yda(m,AP(c))+ON(c)+\"}\",TS(a,b);if(a instanceof Vl)return b=a.mp,\"(\"+SS(a.lp,!1,c)+\")[\"+SS(b,!1,c)+\"]\";if(a instanceof Wl)return m=a.Qn,a=SS(a.Gm,!1,c)+\" \\x3c- \"+SS(m,!1,c),TS(a,b);if(a instanceof\ndm)return m=a.Zq,a=\"while \"+SS(a.$q,!1,c)+\" do \"+SS(m,!1,c),TS(a,b);if(a instanceof Yl)return a=\"new \"+SS(a.hp,!1,c),TS(a,b);if(a instanceof Xl)return m=a.zs,a=aea(a.bp,AP(c)),m.b()?m=\"\":(m=m.o(),m=\" else \"+SS(m,!1,AP(c))),TS(\"if \"+a+m,b);if(a instanceof Il){k=a.np;b=SS(a.nl,!1,c);a=c.Jq?\"\\x3c\":\"[\";if(k===u())m=u();else for(m=k.e(),l=m=new z(VO(m,c.fi),u()),k=k.f();k!==u();)h=k.e(),h=new z(VO(h,c.fi),u()),l=l.p=h,k=k.f();return\"\"+b+a+ze(m,\"\",\", \",\"\")+(c.Jq?\"\\x3e\":\"]\")}if(a instanceof $l)return b=\na.lt,a=SS(a.Yq,!1,c),b=new Sl(b),a+\" where \"+SS(b,!1,AP(c));if(a instanceof Zl){l=a.qq;b=a.$o;if(l===u())a=u();else for(a=l.e(),m=a=new z(VO(a,c.fi),u()),l=l.f();l!==u();)k=l.e(),k=new z(VO(k,c.fi),u()),m=m.p=k,l=l.f();return\"forall \"+ze(a,\"\",\", \",\"\")+\". \"+SS(b,!1,c)}if(a instanceof Kl)return SS(a.cp,!0,c)+\"!\";if(a instanceof am)return\"super\";if(a instanceof bm)return b=a.Zo,SS(a.Vn,!1,c)+\" \\x3d \"+SS(b,!1,c);if(a instanceof cm)return b=a.Zs,SS(a.Ys,!1,c)+\" { \"+lea(b,c)+\" }\";if(a instanceof em)return'code\"'+\nSS(a.Iq,!1,c)+'\"';if(a instanceof fm)return\"${\"+SS(a.jt,!1,c)+\"}\";throw new w(a);};function nx(a,b){a=Qn(a);if(a instanceof fe)return b.n(a.aa),el();if(a instanceof Ud)return a.fa;throw new w(a);}function Qn(a){try{t();var b=nea(a),c=a.A(),d=Cq(b,c);return new Ud(d)}catch(e){if(e instanceof KS)return b=e,t(),jr(),a=Ye(new Te(new Ue(J(new K,[\"Not a recognized type\"]))),u()),b=b.lX.A(),a=G(new H,a,b),b=O().c,a=kr(0,new z(a,b),!0,ws()),new fe(a);throw e;}}\nvar nea=function US(a){var c=!1,d=null,e=!1,g=null;a:{if(a instanceof vl){c=!0;d=a;var h=d.x;if(0<=h.length&&\"`\"===h.substring(0,1)){t();var k=Of(Q(),h,1,h.length);var l=new jt(new Ud(k),t().d);break a}}if(c){var m=d.x;if(0<=m.length&&\"'\"===m.substring(0,1)){l=new jt((t(),new Ud(m)),t().d);break a}}if(c)l=new Ep(d.x);else if(a instanceof Dl)l=new oP(a);else{if(a instanceof Pl){e=!0;g=a;var n=g.Za,r=g.Qb;if(n instanceof vl&&\"-\\x3e\"===n.x&&null!==r){var v=mz(eu(),r);if(!v.b()&&null!==v.o()&&0===v.o().ab(2)){var x=\nv.o(),A=eB(x,0),B=v.o(),C=eB(B,1);var D=A instanceof Gl?!0:A instanceof Fl&&!1===A.bi&&A.gg instanceof Gl?!0:!1;if(D){l=new Wt(US(A),US(C));break a}}}}if(e){var F=g.Za,I=g.Qb;if(F instanceof vl&&\"-\\x3e\"===F.x&&null!==I){var M=mz(eu(),I);if(!M.b()&&null!==M.o()&&0===M.o().ab(2)){var N=M.o(),P=eB(N,0),T=M.o(),Y=eB(T,1),Z=t().d,S=new Sn(t().d,US(P)),ea=G(new H,Z,S),ia=O().c;l=new Wt(new jP(new z(ea,ia)),US(Y));break a}}}if(e){var X=g.Za,sa=g.Qb;if(X instanceof vl&&\"|\"===X.x&&null!==sa){var Ja=mz(eu(),\nsa);if(!Ja.b()&&null!==Ja.o()&&0===Ja.o().ab(2)){var Xa=Ja.o(),Fa=eB(Xa,0),za=Ja.o(),Qa=eB(za,1);l=new iP(US(Fa),US(Qa));break a}}}if(e){var Ma=g.Za,Ga=g.Qb;if(Ma instanceof vl&&\"\\x26\"===Ma.x&&null!==Ga){var ab=mz(eu(),Ga);if(!ab.b()&&null!==ab.o()&&0===ab.o().ab(2)){var Hb=ab.o(),bc=eB(Hb,0),yb=ab.o(),tb=eB(yb,1);l=new hP(US(bc),US(tb));break a}}}if(e){var eb=g.Za,kb=g.Qb;if(eb instanceof vl&&\"\\\\\"===eb.x&&null!==kb){var Rb=mz(eu(),kb);if(!Rb.b()&&null!==Rb.o()&&0===Rb.o().ab(2)){var Gb=Rb.o(),vb=\neB(Gb,0),Tb=Rb.o(),Nb=eB(Tb,1),ic=US(vb),Va=new kP(US(Nb));cu();var cb=O().c,zb=du(0,new z(eb,new z(Nb,cb))),Ub=new hP(ic,Cq(Va,zb)),jb=Lq(g);l=Cq(Ub,jb);break a}}}if(e){var db=g.Za,ub=g.Qb;if(db instanceof vl&&\"~\"===db.x){l=new kP(US(ub));break a}}if(a instanceof Ol){var Aa=a.Fj;l=new Wt(US(a.Ej),US(Aa))}else{if(e){var va=g.Za,Ra=g.Qb;if(null!==Ra){var rb=mz(eu(),Ra);if(!rb.b()){var xb=rb.o(),mc=US(va);if(!(mc instanceof Ep))throw new KS(a);var Ha=xb.m(),Ka=new Ef(Ha,new y(Fc=>US(Fc)));Od();l=new pP(mc,\nPd(u(),Ka));break a}}}if(a instanceof Gl){var Oa=a.Ra,Na=Fc=>{var qd=Fc.h(),Yb=Fc.j();a:{if(null!==Yb){var Nc=Yb.yb;Fc=Yb.ya;if(null!==Nc){Yb=Nc.je;Fc=US(Fc);Fc=new Sn(Yb?new L(Fc):R(),Fc);break a}}throw new w(Yb);}return G(new H,qd,Fc)};if(Oa===u())var Da=u();else{for(var ta=Oa.e(),Ya=new z(Na(ta),u()),dc=Ya,ka=Oa.f();ka!==u();){var ya=ka.e(),Sa=new z(Na(ya),u());dc=dc.p=Sa;ka=ka.f()}Da=Ya}l=new jP(Da)}else if(a instanceof Fl){var xc=a.bi,Sb=a.gg;if(Sb instanceof yl){if(!xc)throw new KS(a);}else if(xc)throw new KS(a);\nl=US(Sb)}else if(a instanceof Il){var uc=a.np,Lb=US(a.nl);if(!(Lb instanceof Ep))throw new KS(a);l=new pP(Lb,uc)}else if(a instanceof yl){var lc=a.ll,Xb=Fc=>{var qd=Fc.h(),Yb=Fc.j();a:{if(null!==Yb){var Nc=Yb.yb;Fc=Yb.ya;if(null!==Nc){Yb=Nc.je;Fc=US(Fc);Fc=new Sn(Yb?new L(Fc):R(),Fc);break a}}throw new w(Yb);}return G(new H,qd,Fc)};if(lc===u())var ec=u();else{for(var Ab=lc.e(),Ob=new z(Xb(Ab),u()),fb=Ob,Wa=lc.f();Wa!==u();){var bb=Wa.e(),Ia=new z(Xb(bb),u());fb=fb.p=Ia;Wa=Wa.f()}ec=Ob}l=new Tn(ec)}else if(a instanceof\n$l){var Ua=a.lt,pc=US(a.Yq),sc=O().c,Ba=Fc=>{if(Fc instanceof Cl){var qd=Fc.Fm;return new mP(US(Fc.ai),qd)}throw new KS(Fc);};if(Ua===u())var ob=u();else{for(var nc=Ua.e(),Ib=new z(Ba(nc),u()),vc=Ib,Vb=Ua.f();Vb!==u();){var fc=Vb.e(),Bc=new z(Ba(fc),u());vc=vc.p=Bc;Vb=Vb.f()}ob=Ib}l=new qP(pc,sc,ob)}else if(a instanceof Zl){var Pb=a.qq,Jb=a.$o,gc=Fc=>{t();return new Ud(Fc)};if(Pb===u())var Cb=u();else{for(var cc=Pb.e(),yc=new z(gc(cc),u()),Mc=yc,qc=Pb.f();qc!==u();){var oc=qc.e(),Qc=new z(gc(oc),\nu());Mc=Mc.p=Qc;qc=qc.f()}Cb=yc}l=new Vt(Cb,US(Jb))}else if(a instanceof Ql){var jc=a.ml,sb=US(a.Vl),Gc=new Ep(jc.x),Wb=jc.A();l=new tP(sb,Cq(Gc,Wb))}else throw new KS(a);}}}var Cc=a.A();return Cq(l,Cc)},oea=function VS(a){if(a instanceof Ol)return!0;if(a instanceof Fl){var c=a.gg;if(!1===a.bi)return VS(c)}if(a instanceof $l)return VS(a.Yq);if(a instanceof Ul){for(a=Uda(a.Hm);!a.b();){c=a.e();if(!VS(c))return!1;a=a.f()}return!0}return!1};function RS(a,b){return b?\"(\"+a+\")\":a}\nfunction TS(a,b){return b?\"(\"+a+\")\":a}function WS(){this.ld=null}WS.prototype=new SN;WS.prototype.constructor=WS;function XS(){}XS.prototype=WS.prototype;function YS(){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0}YS.prototype=new p;YS.prototype.constructor=YS;function ZS(){}ZS.prototype=YS.prototype;\nfunction ZO(a){if(0===(1&a.sc)<<24>>24&&0===(1&a.sc)<<24>>24){if(a instanceof jt){var b=O().c;b=new z(a,b)}else{b=EP(a);for(var c=null,d=null;b!==u();){for(var e=ZO(b.e()).m();e.s();){var g=new z(e.t(),u());null===d?c=g:d.p=g;d=g}b=b.f()}b=null===c?u():c}a.jf=b;a.sc=(1|a.sc)<<24>>24}return a.jf}\nfunction $S(a){if(0===(2&a.sc)<<24>>24&&0===(2&a.sc)<<24>>24){if(a instanceof jt){tp();var b=gq(a)}else{var c=EP(a);b=ap();for(c=Km(c);!c.b();){var d=c.e();b=$S(d).Ce(b);c=c.f()}}a.cf=b;a.sc=(2|a.sc)<<24>>24}return a.cf}f=YS.prototype;f.jn=function(){0===(4&this.sc)<<24>>24&&0===(4&this.sc)<<24>>24&&(this.df=zq(this),this.sc=(4|this.sc)<<24>>24);return this.df};f.rn=function(){return this.gf};f.fm=function(a){this.gf=a};f.qn=function(){return this.ff};f.em=function(a){this.ff=a};f.pn=function(){return this.ef};\nf.on=function(a){this.ef=a};f.A=function(){0===(8&this.sc)<<24>>24&&0===(8&this.sc)<<24>>24&&(this.hf=Dq(this),this.sc=(8|this.sc)<<24>>24);return this.hf};function AB(a,b,c,d,e){this.HE=this.YN=this.Ou=this.kI=this.Vq=this.yA=null;if(null===a)throw null;this.kI=a;this.Ou=c;this.YN=d;this.HE=e;FD(this,a,b)}AB.prototype=new HD;AB.prototype.constructor=AB;AB.prototype.Kp=function(a,b){JD(this,a,b)};\nAB.prototype.Tb=function(a,b){var c=this.kI.qa,d=this.kI;if(d.F){var e=ut(Q(),\"| \",d.r)+(\"analyze1[\"+a+\"] \")+b;ff(gf(),e+\"\\n\")}d.r=1+d.r|0;try{if(b instanceof lx){var g=a.Ig(b.Xa);if(g instanceof L){var h=G(new H,!!g.k,b);this.Ou.bh(h,1+(this.Ou.n(h)|0)|0)}else if(t().d===g){this.YN.$(b);var k=G(new H,!0,b);this.Ou.bh(k,1+(this.Ou.n(k)|0)|0);var l=G(new H,!1,b);this.Ou.bh(l,1+(this.Ou.n(l)|0)|0)}else throw new w(g);var m=b.Sb;if(m instanceof L){var n=m.k,r=new zB(this.HE),v=a.Ig(b.Xa),x=v.b()?!1:\nv.o(),A=G(new H,b,x);r.en.L(A)||(r.en.$(A),this.Tb(a,n))}else if(t().d===m){var B=a.Ig(b.Xa);if(Nm(new E(B),(t(),new L(!1)))){var C=new zB(this.HE),D=G(new H,b,!0);if(!C.en.L(D)){C.en.$(D);var F=vy(b),I=new RB(a,b.Xa,!0);for(e=F;!e.b();){var M=e.e();this.Tb(I,M);e=e.f()}}}var N=a.Ig(b.Xa);if(Nm(new E(N),(t(),new L(!0)))){var P=new zB(this.HE),T=G(new H,b,!1);if(!P.en.L(T)){P.en.$(T);var Y=rA(b),Z=new RB(a,b.Xa,!1);for(a=Y;!a.b();){var S=a.e();this.Tb(Z,S);a=a.f()}}}}else throw new w(m);}else GD.prototype.Tb.call(this,\na,b);var ea=void 0}finally{d.r=-1+d.r|0}dx(new E(c),d.qa)&&d.F&&(c=\"\"+ut(Q(),\"| \",d.r)+c.n(ea),ff(gf(),c+\"\\n\"))};AB.prototype.$classData=q({GY:0},!1,\"mlscript.TypeSimplifier$Analyze1$1$\",{GY:1,kP:1,g:1,YZ:1});function aT(a){var b=GP(a.pp);return b.b()?a.oA:b}\nfunction bT(a,b){a=a.pp;if(a instanceof Ud)a=G(new H,0,a.fa);else if(a instanceof fe)a=G(new H,a.aa|0,\"\");else throw new w(a);var c=Fq(),d=cT();a=new dT(new eT(c,d),a);b=b.pp;if(b instanceof Ud)b=G(new H,0,b.fa);else if(b instanceof fe)b=G(new H,b.aa|0,\"\");else throw new w(b);return a.$l(b)}function BA(){this.q=null}BA.prototype=new YP;BA.prototype.constructor=BA;function fT(){}fT.prototype=BA.prototype;BA.prototype.rT=function(){return this};\nvar uw=function pea(a,b){a=G(new H,a,b);b=a.y;var d=a.w;if(XB(b)&&XB(d))return pa(b.rr().Dh,d.rr().Dh);d=a.y;b=a.w;if(d instanceof mx&&(d=d.hi,b instanceof mx))return gT(d,b.hi);d=a.y;b=a.w;if(d instanceof YB&&(d=d.Ym,b instanceof YB))return pea(d,b.Ym);if(XB(a.y)&&(a.w instanceof mx||a.w instanceof YB))return-1;if((a.y instanceof mx||a.y instanceof YB)&&XB(a.w))return 1;if(a.y instanceof mx&&a.w instanceof YB)return-1;if(a.y instanceof YB&&a.w instanceof mx)return 1;throw new w(a);};\nfunction Uv(a){return!!(a&&a.$classData&&a.$classData.rb.uA)}function ko(a,b,c,d,e){this.jJ=a;this.re=b;this.hJ=c;this.iJ=d;this.RP=e;this.sF=!1}ko.prototype=new p;ko.prototype.constructor=ko;ko.prototype.xo=function(){return this.jJ};ko.prototype.zo=function(){return this.re};ko.prototype.u=function(){return\"value \"+this.jJ};ko.prototype.$classData=q({F_:0},!1,\"mlscript.codegen.ValueSymbol\",{F_:1,g:1,mt:1,cr:1});function hT(a,b){a.VP=b;yF(a,null,null,!0);return a}\nfunction iT(a,b,c){b=G(new H,b,c);c=O().c;hT(a,new z(b,c));return a}class jT extends Vd{constructor(){super();this.VP=null}}jT.prototype.$classData=q({S_:0},!1,\"mlscript.ucs.DesugaringException\",{S_:1,pc:1,g:1,l:1});function kT(){}kT.prototype=new p;kT.prototype.constructor=kT;function lT(){}lT.prototype=kT.prototype;function mT(){this.Iv=this.JK=null;nT=this;O();Od();this.JK=qp();this.Iv=Bq()}mT.prototype=new xQ;mT.prototype.constructor=mT;\nfunction up(a,b){if(!b)throw new Yj(\"assertion failed\");}function At(a,b){if(!b)throw Kj(\"requirement failed\");}function no(){tp();var a=new oT;yF(a,\"an implementation is missing\",null,!0);throw a;}mT.prototype.$classData=q({l3:0},!1,\"scala.Predef$\",{l3:1,eba:1,fba:1,g:1});var nT;function tp(){nT||(nT=new mT);return nT}function qea(a,b){switch(b){case 0:return a.Uj;case 1:return a.oj;case 2:return a.oi;case 3:return a.Xi;default:throw aL(new bL,b+\" is out of bounds (min 0, max 3)\");}}\nfunction rea(a,b){switch(b){case 0:return a.hv;case 1:return a.qt;case 2:return a.kr;case 3:return a.iv;case 4:return a.jv;default:throw aL(new bL,b+\" is out of bounds (min 0, max 4)\");}}function sea(a,b){switch(b){case 0:return a.lr;case 1:return a.mr;case 2:return a.rt;case 3:return a.st;case 4:return a.tt;case 5:return a.kv;default:throw aL(new bL,b+\" is out of bounds (min 0, max 5)\");}}function pT(){qT=this}pT.prototype=new p;pT.prototype.constructor=pT;\npT.prototype.$classData=q({Q4:0},!1,\"scala.collection.BuildFrom$\",{Q4:1,g:1,Kba:1,Lba:1});var qT;function Yq(){qT||(qT=new pT)}function rT(){this.RB=null}rT.prototype=new p;rT.prototype.constructor=rT;function sT(){}sT.prototype=rT.prototype;rT.prototype.X=function(){return this.RB.ng(IB())};rT.prototype.Ib=function(a){return this.RB.pr(a,IB())};rT.prototype.Eb=function(){var a=this.RB,b=IB();return a.sy(b)};rT.prototype.Hh=function(a){var b=this.RB,c=IB();return b.pr(a,c)};\nfunction tT(){this.Mt=null}tT.prototype=new p;tT.prototype.constructor=tT;function uT(){}uT.prototype=tT.prototype;tT.prototype.ng=function(a){return this.Mt.ng(a)};tT.prototype.pr=function(a,b){return this.Mt.pr(a,b)};tT.prototype.GB=function(a){return this.Mt.GB(a)};function vT(){this.sm=null}vT.prototype=new p;vT.prototype.constructor=vT;function wT(){}wT.prototype=vT.prototype;vT.prototype.X=function(){return this.sm.X()};vT.prototype.Ib=function(a){return this.sm.Ib(a)};vT.prototype.Eb=function(){return this.sm.Eb()};\nfunction xT(a){this.c5=a}xT.prototype=new p;xT.prototype.constructor=xT;xT.prototype.vc=function(a){return this.c5.Ib(a)};xT.prototype.$classData=q({b5:0},!1,\"scala.collection.IterableFactory$ToFactory\",{b5:1,g:1,TK:1,l:1});function sp(a){a=a.m();return a.s()?new L(a.t()):R()}function yT(a){a=a.m();for(var b=a.t();a.s();)b=a.t();return b}function Is(a){return a.b()?R():new L(a.Mc())}\nfunction iv(a,b){if(0>b)return 1;var c=a.Q();if(0<=c)return c===b?0:c<b?-1:1;c=0;for(a=a.m();a.s();){if(c===b)return 1;a.t();c=1+c|0}return c-b|0}function hv(a,b){var c=b.Q();if(0<=c)return a.$k(c);c=a.Q();if(0<=c)return b=b.$k(c),-2147483648===b?1:-b|0;a=a.m();for(b=b.m();a.s()&&b.s();)a.t(),b.t();a=a.s();b=b.s();return a===b?0:a?1:-1}function zT(a,b){return a.vc(AT(new BT,a,b))}function CT(a){if(a.b())throw DT();return a.Jc(1)}\nfunction ET(a,b,c){var d=Xu().X();a.Ca(new y(h=>{var k=b.n(h);k=d.Hk(k,new U(()=>a.Ub().Eb()));h=c.n(h);return k.$(h)}));var e=nf(),g=new aw(e);d.Ca(new y(h=>{if(null!==h)g.rc=g.rc.Pn(G(new H,h.h(),h.j().Kb()));else throw new w(h);}));return g.rc}function FT(a,b){return a.Ub().Ib(GT(new HT,a,b))}function IT(a,b){var c=a.Ub();a=Fs(b)?new JT(a,b):a.m().nb(new U(()=>b.m()));return c.Ib(a)}\nfunction KT(a,b){var c=GT(new HT,a,new y(e=>b.n(e).h())),d=GT(new HT,a,new y(e=>b.n(e).j()));return G(new H,a.Ub().Ib(c),a.Ub().Ib(d))}function tea(a,b){for(var c=!1;!c&&a.s();)c=a.t(),c=ml(nl(),c,b);return c}function LT(a,b,c){var d=0<c?c:0;for(a=a.ph(c);a.s();){if(b.n(a.t()))return d;d=1+d|0}return-1}function kv(a,b){return(new MT(a)).nb(b)}function NT(a,b){return a.qk(0,0<b?b:0)}function OT(a,b,c){b=0<b?b:0;c=0>c?-1:c<=b?0:c-b|0;return 0===c?Rq().Pa:new PT(a,b,c)}\nfunction QT(){this.Pa=null;RT=this;this.Pa=new ST}QT.prototype=new p;QT.prototype.constructor=QT;QT.prototype.Eb=function(){return new TT};QT.prototype.X=function(){return this.Pa};QT.prototype.Ib=function(a){return a.m()};QT.prototype.$classData=q({d5:0},!1,\"scala.collection.Iterator$\",{d5:1,g:1,bg:1,l:1});var RT;function Rq(){RT||(RT=new QT);return RT}function uea(a){var b=qp();a.Nt=b}function UT(){this.Nt=null}UT.prototype=new p;UT.prototype.constructor=UT;function VT(){}VT.prototype=UT.prototype;\nUT.prototype.Hh=function(a){return this.Nt.Hh(a)};UT.prototype.Ib=function(a){return this.Nt.Ib(a)};UT.prototype.X=function(){return this.Nt.X()};UT.prototype.Eb=function(){return this.Nt.Eb()};function Pv(a){this.K5=a}Pv.prototype=new p;Pv.prototype.constructor=Pv;Pv.prototype.vc=function(a){return this.K5.Ib(a)};Pv.prototype.$classData=q({J5:0},!1,\"scala.collection.MapFactory$ToFactory\",{J5:1,g:1,TK:1,l:1});function WT(){this.Pt=null}WT.prototype=new p;WT.prototype.constructor=WT;\nfunction XT(){}XT.prototype=WT.prototype;WT.prototype.CF=function(a,b){return this.Pt.CF(a,b)};WT.prototype.qr=function(a,b){return this.Pt.qr(a,b)};WT.prototype.Hd=function(a){return this.Pt.Hd(a)};WT.prototype.Dv=function(a){return this.Pt.Dv(a)};function tv(a,b){this.b6=a;this.a6=b}tv.prototype=new p;tv.prototype.constructor=tv;tv.prototype.vc=function(a){return this.b6.qr(a,this.a6)};tv.prototype.$classData=q({$5:0},!1,\"scala.collection.SortedMapFactory$ToFactory\",{$5:1,g:1,TK:1,l:1});\nfunction YT(){}YT.prototype=new p;YT.prototype.constructor=YT;function ZT(a,b){if(b&&b.$classData&&b.$classData.rb.jd)return b;if(Fs(b))return new $T(new U(()=>b.m()));a=aU(FK(),b);return bU(new cU,a)}YT.prototype.Eb=function(){var a=new DF;return new dU(a,new y(b=>ZT(eU(),b)))};YT.prototype.X=function(){fU||(fU=new gU);return fU};YT.prototype.Ib=function(a){return ZT(0,a)};YT.prototype.$classData=q({r6:0},!1,\"scala.collection.View$\",{r6:1,g:1,bg:1,l:1});var hU;\nfunction eU(){hU||(hU=new YT);return hU}function aI(a,b,c,d,e,g){this.Db=a;this.qc=b;this.te=c;this.Vg=d;this.kd=e;this.ui=g}aI.prototype=new XQ;aI.prototype.constructor=aI;f=aI.prototype;f.ka=function(){return this.kd};f.uc=function(){return this.ui};f.Ef=function(a){return this.te.a[a<<1]};f.Tf=function(a){return this.te.a[1+(a<<1)|0]};f.rv=function(a){return G(new H,this.te.a[a<<1],this.te.a[1+(a<<1)|0])};f.Jb=function(a){return this.Vg.a[a]};\nf.qh=function(a){return this.te.a[(-1+this.te.a.length|0)-a|0]};f.BJ=function(a,b,c,d){var e=kI(HH(),c,d),g=lI(HH(),e);if(0!==(this.Db&g)){if(b=oI(HH(),this.Db,e,g),ml(nl(),a,this.Ef(b)))return this.Tf(b)}else if(0!==(this.qc&g))return this.qh(oI(HH(),this.qc,e,g)).BJ(a,b,c,5+d|0);throw AH(\"key not found: \"+a);};\nf.KF=function(a,b,c,d){var e=kI(HH(),c,d),g=lI(HH(),e);return 0!==(this.Db&g)?(b=oI(HH(),this.Db,e,g),c=this.Ef(b),ml(nl(),a,c)?new L(this.Tf(b)):R()):0!==(this.qc&g)?(e=oI(HH(),this.qc,e,g),this.qh(e).KF(a,b,c,5+d|0)):R()};f.KJ=function(a,b,c,d,e){var g=kI(HH(),c,d),h=lI(HH(),g);return 0!==(this.Db&h)?(b=oI(HH(),this.Db,g,h),c=this.Ef(b),ml(nl(),a,c)?this.Tf(b):Es(e)):0!==(this.qc&h)?(g=oI(HH(),this.qc,g,h),this.qh(g).KJ(a,b,c,5+d|0,e)):Es(e)};\nf.DF=function(a,b,c,d){var e=kI(HH(),c,d),g=lI(HH(),e);return 0!==(this.Db&g)?(c=oI(HH(),this.Db,e,g),this.Vg.a[c]===b&&ml(nl(),a,this.Ef(c))):0!==(this.qc&g)&&this.qh(oI(HH(),this.qc,e,g)).DF(a,b,c,5+d|0)};\nfunction iU(a,b,c,d,e,g,h){var k=kI(HH(),e,g),l=lI(HH(),k);if(0!==(a.Db&l)){var m=oI(HH(),a.Db,k,l);k=a.Ef(m);var n=a.Jb(m);if(n===d&&ml(nl(),k,b))return h?(e=a.Tf(m),Object.is(k,b)&&Object.is(e,c)||(l=a.pi(l)<<1,b=a.te,e=new zc(b.a.length),b.wa(0,e,0,b.a.length),e.a[1+l|0]=c,a=new aI(a.Db,a.qc,e,a.Vg,a.kd,a.ui)),a):a;m=a.Tf(m);h=$G(bH(),n);c=jU(a,k,m,n,h,b,c,d,e,5+g|0);e=a.pi(l);d=e<<1;g=(-2+a.te.a.length|0)-a.hm(l)|0;k=a.te;b=new zc(-1+k.a.length|0);k.wa(0,b,0,d);k.wa(2+d|0,b,d,g-d|0);b.a[g]=c;\nk.wa(2+g|0,b,1+g|0,-2+(k.a.length-g|0)|0);e=gI(a.Vg,e);return new aI(a.Db^l,a.qc|l,b,e,(-1+a.kd|0)+c.ka()|0,(a.ui-h|0)+c.uc()|0)}if(0!==(a.qc&l))return k=oI(HH(),a.qc,k,l),k=a.qh(k),c=k.KC(b,c,d,e,5+g|0,h),c===k?a:kU(a,l,k,c);g=a.pi(l);k=g<<1;n=a.te;h=new zc(2+n.a.length|0);n.wa(0,h,0,k);h.a[k]=b;h.a[1+k|0]=c;n.wa(k,h,2+k|0,n.a.length-k|0);c=hI(a.Vg,g,d);return new aI(a.Db|l,a.qc,h,c,1+a.kd|0,a.ui+e|0)}\nfunction lU(a,b,c,d,e,g,h){var k=kI(HH(),e,g),l=lI(HH(),k);if(0!==(a.Db&l)){var m=oI(HH(),a.Db,k,l);k=a.Ef(m);var n=a.Jb(m);if(n===d&&ml(nl(),k,b))return d=a.Tf(m),Object.is(k,b)&&Object.is(d,c)||(l=a.pi(l)<<1,a.te.a[1+l|0]=c),h;var r=a.Tf(m);m=$G(bH(),n);c=jU(a,k,r,n,m,b,c,d,e,5+g|0);mU(a,l,m,c);return h|l}if(0!==(a.qc&l))return k=oI(HH(),a.qc,k,l),r=a.qh(k),k=r.ka(),n=r.uc(),m=h,r instanceof aI&&0!==(l&h)?(lU(r,b,c,d,e,5+g|0,0),h=r):(h=r.KC(b,c,d,e,5+g|0,!0),h!==r&&(m|=l)),a.te.a[(-1+a.te.a.length|\n0)-a.hm(l)|0]=h,a.kd=(a.kd-k|0)+h.ka()|0,a.ui=(a.ui-n|0)+h.uc()|0,m;g=a.pi(l);k=g<<1;n=a.te;m=new zc(2+n.a.length|0);n.wa(0,m,0,k);m.a[k]=b;m.a[1+k|0]=c;n.wa(k,m,2+k|0,n.a.length-k|0);a.Db|=l;a.te=m;a.Vg=hI(a.Vg,g,d);a.kd=1+a.kd|0;a.ui=a.ui+e|0;return h}\nfunction nU(a,b,c,d,e){var g=kI(HH(),d,e),h=lI(HH(),g);if(0!==(a.Db&h)){if(g=oI(HH(),a.Db,g,h),c=a.Ef(g),ml(nl(),c,b)){b=a.Db;2===nI(UH(),b)?(b=a.qc,b=0===nI(UH(),b)):b=!1;if(b)return h=0===e?a.Db^h:lI(HH(),kI(HH(),d,0)),0===g?new aI(h,0,new zc([a.Ef(1),a.Tf(1)]),new Xc(new Int32Array([a.Vg.a[1]])),1,$G(bH(),a.Jb(1))):new aI(h,0,new zc([a.Ef(0),a.Tf(0)]),new Xc(new Int32Array([a.Vg.a[0]])),1,$G(bH(),a.Jb(0)));e=a.pi(h);b=e<<1;c=a.te;g=new zc(-2+c.a.length|0);c.wa(0,g,0,b);c.wa(2+b|0,g,b,-2+(c.a.length-\nb|0)|0);e=gI(a.Vg,e);return new aI(a.Db^h,a.qc,g,e,-1+a.kd|0,a.ui-d|0)}}else if(0!==(a.qc&h)){g=oI(HH(),a.qc,g,h);g=a.qh(g);d=g.hR(b,c,d,5+e|0);if(d===g)return a;e=d.ka();if(1===e)if(a.kd===g.ka())a=d;else{b=(-1+a.te.a.length|0)-a.hm(h)|0;c=a.pi(h);var k=c<<1,l=d.Ef(0),m=d.Tf(0),n=a.te;e=new zc(1+n.a.length|0);n.wa(0,e,0,k);e.a[k]=l;e.a[1+k|0]=m;n.wa(k,e,2+k|0,b-k|0);n.wa(1+b|0,e,2+b|0,-1+(n.a.length-b|0)|0);b=hI(a.Vg,c,d.Jb(0));a=new aI(a.Db|h,a.qc^h,e,b,1+(a.kd-g.ka()|0)|0,(a.ui-g.uc()|0)+d.uc()|\n0)}else a=1<e?kU(a,h,g,d):a;return a}return a}function jU(a,b,c,d,e,g,h,k,l,m){if(32<=m)return GK(),b=[G(new H,b,c),G(new H,g,h)],b=J(new K,b),new oU(d,e,pU(0,b));var n=kI(HH(),e,m),r=kI(HH(),l,m),v=e+l|0;if(n!==r)return e=lI(HH(),n)|lI(HH(),r),n<r?new aI(e,0,new zc([b,c,g,h]),new Xc(new Int32Array([d,k])),2,v):new aI(e,0,new zc([g,h,b,c]),new Xc(new Int32Array([k,d])),2,v);n=lI(HH(),n);d=jU(a,b,c,d,e,g,h,k,l,5+m|0);return new aI(0,n,new zc([d]),kG().KB,d.ka(),d.uc())}f.nB=function(){return 0!==this.qc};\nf.HB=function(){var a=this.qc;return nI(UH(),a)};f.jy=function(){return 0!==this.Db};f.uy=function(){var a=this.Db;return nI(UH(),a)};f.pi=function(a){a=this.Db&(-1+a|0);return nI(UH(),a)};f.hm=function(a){a=this.qc&(-1+a|0);return nI(UH(),a)};function kU(a,b,c,d){b=(-1+a.te.a.length|0)-a.hm(b)|0;var e=a.te,g=new zc(e.a.length);e.wa(0,g,0,e.a.length);g.a[b]=d;return new aI(a.Db,a.qc,g,a.Vg,(a.kd-c.ka()|0)+d.ka()|0,(a.ui-c.uc()|0)+d.uc()|0)}\nfunction mU(a,b,c,d){var e=a.pi(b),g=e<<1,h=(-2+a.te.a.length|0)-a.hm(b)|0,k=a.te,l=new zc(-1+k.a.length|0);k.wa(0,l,0,g);k.wa(2+g|0,l,g,h-g|0);l.a[h]=d;k.wa(2+h|0,l,1+h|0,-2+(k.a.length-h|0)|0);e=gI(a.Vg,e);a.Db^=b;a.qc|=b;a.te=l;a.Vg=e;a.kd=(-1+a.kd|0)+d.ka()|0;a.ui=(a.ui-c|0)+d.uc()|0}f.Ca=function(a){var b=this.Db;b=nI(UH(),b);for(var c=0;c<b;)a.n(this.rv(c)),c=1+c|0;b=this.qc;b=nI(UH(),b);for(c=0;c<b;)this.qh(c).Ca(a),c=1+c|0};\nf.og=function(a){var b=this.Db;b=nI(UH(),b);for(var c=0;c<b;)a.ba(this.Ef(c),this.Tf(c)),c=1+c|0;b=this.qc;b=nI(UH(),b);for(c=0;c<b;)this.qh(c).og(a),c=1+c|0};f.GJ=function(a){var b=0,c=this.Db;for(c=nI(UH(),c);b<c;){var d=this.Ef(b),e=this.Tf(b);(0,a.aM)(d,e,this.Jb(b));b=1+b|0}b=this.qc;b=nI(UH(),b);for(c=0;c<b;)this.qh(c).GJ(a),c=1+c|0};\nf.i=function(a){if(a instanceof aI){if(this===a)return!0;if(this.ui===a.ui&&this.qc===a.qc&&this.Db===a.Db&&this.kd===a.kd){var b=this.Vg,c=a.Vg;b=qj(Pj(),b,c)}else b=!1;if(b){b=this.te;a=a.te;c=this.te.a.length;if(b===a)return!0;for(var d=!0,e=0;d&&e<c;)d=ml(nl(),b.a[e],a.a[e]),e=1+e|0;return d}}return!1};f.B=function(){throw nv(\"Trie nodes do not support hashing.\");};\nfunction qU(a,b,c){if(b instanceof aI){if(0===a.kd)return b;if(0===b.kd||b===a)return a;if(1===b.kd){var d=b.Jb(0);return iU(a,b.Ef(0),b.Tf(0),d,$G(bH(),d),c,!0)}d=!1;var e=a.Db|b.Db|a.qc|b.qc,g=lI(HH(),0===e?32:31-Math.clz32(e&(-e|0))|0);e=lI(HH(),31-Math.clz32(e)|0);for(var h=0,k=0,l=0,m=0,n=0,r=0,v=0,x=0,A=0,B=0,C=g,D=0,F=0,I=!1;!I;){if(0!==(C&a.Db)){if(0!==(C&b.Db)){var M=a.Jb(D);M===b.Jb(F)&&ml(nl(),a.Ef(D),b.Ef(F))?A|=C:(x|=C,B|=lI(HH(),kI(HH(),$G(bH(),M),c)));F=1+F|0}else 0!==(C&b.qc)?k|=C:\nm|=C;D=1+D|0}else 0!==(C&a.qc)?0!==(C&b.Db)?(l|=C,F=1+F|0):0!==(C&b.qc)?h|=C:r|=C:0!==(C&b.Db)?(n|=C,F=1+F|0):0!==(C&b.qc)&&(v|=C);C===e?I=!0:C<<=1}C=m|n|A;B|=h|k|l|r|v;if(C===(n|A)&&B===v)return b;I=nI(UH(),C);D=(I<<1)+nI(UH(),B)|0;F=new zc(D);I=new Xc(I);var N=M=0,P=0,T=0,Y=0,Z=0;c=5+c|0;for(var S=0,ea=0,ia=!1;!ia;){if(0!==(g&h)){var X=b.qh(Z),sa=a.qh(Y).iQ(X,c);X!==sa&&(d=!0);F.a[-1+(D-ea|0)|0]=sa;ea=1+ea|0;Z=1+Z|0;Y=1+Y|0;M=M+sa.ka()|0;N=N+sa.uc()|0}else if(0!==(g&k)){X=b.qh(Z);sa=a.Ef(P);var Ja=\na.Tf(P),Xa=a.Jb(P),Fa=$G(bH(),Xa);sa=X.KC(sa,Ja,Xa,Fa,c,!1);sa!==X&&(d=!0);F.a[-1+(D-ea|0)|0]=sa;ea=1+ea|0;Z=1+Z|0;P=1+P|0;M=M+sa.ka()|0;N=N+sa.uc()|0}else 0!==(g&l)?(d=!0,X=b.Jb(T),X=a.qh(Y).KC(b.Ef(T),b.Tf(T),b.Jb(T),$G(bH(),X),c,!0),F.a[-1+(D-ea|0)|0]=X,ea=1+ea|0,Y=1+Y|0,T=1+T|0,M=M+X.ka()|0,N=N+X.uc()|0):0!==(g&m)?(d=!0,X=a.Vg.a[P],F.a[S<<1]=a.Ef(P),F.a[1+(S<<1)|0]=a.Tf(P),I.a[S]=X,S=1+S|0,P=1+P|0,M=1+M|0,N=N+$G(bH(),X)|0):0!==(g&n)?(X=b.Vg.a[T],F.a[S<<1]=b.Ef(T),F.a[1+(S<<1)|0]=b.Tf(T),I.a[S]=\nX,S=1+S|0,T=1+T|0,M=1+M|0,N=N+$G(bH(),X)|0):0!==(g&r)?(d=!0,X=a.qh(Y),F.a[-1+(D-ea|0)|0]=X,ea=1+ea|0,Y=1+Y|0,M=M+X.ka()|0,N=N+X.uc()|0):0!==(g&v)?(X=b.qh(Z),F.a[-1+(D-ea|0)|0]=X,ea=1+ea|0,Z=1+Z|0,M=M+X.ka()|0,N=N+X.uc()|0):0!==(g&x)?(d=!0,X=a.Jb(P),sa=b.Jb(T),X=jU(b,a.Ef(P),a.Tf(P),X,$G(bH(),X),b.Ef(T),b.Tf(T),sa,$G(bH(),sa),c),F.a[-1+(D-ea|0)|0]=X,ea=1+ea|0,P=1+P|0,T=1+T|0,M=M+X.ka()|0,N=N+X.uc()|0):0!==(g&A)&&(X=b.Vg.a[T],F.a[S<<1]=b.Ef(T),F.a[1+(S<<1)|0]=b.Tf(T),I.a[S]=X,S=1+S|0,T=1+T|0,M=1+M|\n0,N=N+$G(bH(),X)|0,P=1+P|0);g===e?ia=!0:g<<=1}return d?new aI(C,B,F,I,M,N):b}throw nv(\"Cannot concatenate a HashCollisionMapNode with a BitmapIndexedMapNode\");}function rU(a){var b=a.te.ia(),c=b.a.length,d=a.Db;for(d=nI(UH(),d)<<1;d<c;)b.a[d]=b.a[d].kQ(),d=1+d|0;return new aI(a.Db,a.qc,b,a.Vg.ia(),a.kd,a.ui)}\nfunction sU(a,b,c){if(0===a.kd)return a;if(1===a.kd)return!!b.n(a.rv(0))!==c?a:bI().Ty;if(0===a.qc){for(var d=a.Db,e=0===d?32:31-Math.clz32(d&(-d|0))|0,g=32-Math.clz32(a.Db)|0,h=d=0,k=0;e<g;){var l=lI(HH(),e);if(0!==(l&a.Db)){var m=a.rv(k);!!b.n(m)!==c&&(d|=l,h=h+$G(bH(),a.Jb(k))|0);k=1+k|0}e=1+e|0}if(0===d)return bI().Ty;if(d===a.Db)return a;g=d;g=nI(UH(),g);k=new zc(g<<1);e=new Xc(g);l=32-Math.clz32(d)|0;m=d;m=0===m?32:31-Math.clz32(m&(-m|0))|0;for(var n=0;m<l;){var r=lI(HH(),m);0!==(r&d)&&(r=mI(HH(),\na.Db,r),k.a[n<<1]=a.te.a[r<<1],k.a[1+(n<<1)|0]=a.te.a[1+(r<<1)|0],e.a[n]=a.Vg.a[r],n=1+n|0);m=1+m|0}return new aI(d,0,k,e,g,h)}d=a.Db|a.qc;var v=0===d?32:31-Math.clz32(d&(-d|0))|0,x=32-Math.clz32(d)|0;h=d=0;var A=null;k=g=0;e=null;for(var B=r=n=m=l=0,C=0,D=v;D<x;){var F=lI(HH(),D);if(0!==(F&a.Db)){var I=a.rv(B);!!b.n(I)!==c&&(l|=F,d|=F,n=1+n|0,r=r+$G(bH(),a.Jb(B))|0);B=1+B|0}else if(0!==(F&a.qc)){var M=a.qh(C);I=M.qQ(b,c);n=n+I.ka()|0;r=r+I.uc()|0;1<I.ka()?(m|=F,M===I?g|=F:(k|=F,null===e&&(e=new tU(16)),\nuU(e,I))):1===I.ka()&&(l|=F,h|=F,null===A&&(A=u(),A=vU(new tU(16),A)),uU(A,I));C=1+C|0}D=1+D|0}if(0===n)return bI().Ty;if(n===a.kd)return a;b=l;x=nI(UH(),b);b=m;b=(x<<1)+nI(UH(),b)|0;c=new zc(b);x=new Xc(x);B=32-Math.clz32(l|m)|0;for(I=F=D=C=0;v<B;)M=lI(HH(),v),0!==(M&d)?(c.a[F<<1]=a.Ef(C),c.a[1+(F<<1)|0]=a.Tf(C),x.a[F]=a.Jb(C),F=1+F|0,C=1+C|0):0!==(M&g)?(c.a[-1+(b-I|0)|0]=a.qh(D),I=1+I|0,D=1+D|0):0!==(M&h)?(M=wU(A),c.a[F<<1]=M.Ef(0),c.a[1+(F<<1)|0]=M.Tf(0),x.a[F]=M.Jb(0),F=1+F|0,D=1+D|0):0!==(M&\nk)?(c.a[-1+(b-I|0)|0]=wU(e),I=1+I|0,D=1+D|0):0!==(M&a.Db)?C=1+C|0:0!==(M&a.qc)&&(D=1+D|0),v=1+v|0;return new aI(l,m,c,x,n,r)}f.qQ=function(a,b){return sU(this,a,b)};f.kQ=function(){return rU(this)};f.iQ=function(a,b){return qU(this,a,b)};f.hR=function(a,b,c,d){return nU(this,a,b,c,d)};f.KC=function(a,b,c,d,e,g){return iU(this,a,b,c,d,e,g)};f.mB=function(a){return this.qh(a)};f.$classData=q({R6:0},!1,\"scala.collection.immutable.BitmapIndexedMapNode\",{R6:1,O7:1,lC:1,g:1});\nfunction xU(a,b,c,d,e,g,h,k,l,m,n,r){if(0===b)return DJ().mw;if(b===a.Fb)return a;var v=nI(UH(),c),x=v+nI(UH(),d)|0,A=new zc(x);v=new Xc(v);for(var B=32-Math.clz32(c|d)|0,C=0,D=0,F=0,I=0;e<B;){var M=lI(HH(),e);0!==(M&g)?(A.a[F]=a.ed(C),v.a[F]=a.Jb(C),F=1+F|0,C=1+C|0):0!==(M&h)?(A.a[-1+(x-I|0)|0]=a.Nh(D),I=1+I|0,D=1+D|0):0!==(M&k)?(M=wU(l),A.a[F]=M.ed(0),v.a[F]=M.Jb(0),F=1+F|0,D=1+D|0):0!==(M&m)?(A.a[-1+(x-I|0)|0]=wU(n),I=1+I|0,D=1+D|0):0!==(M&a.db)?C=1+C|0:0!==(M&a.Pb)&&(D=1+D|0);e=1+e|0}return new CJ(c,\nd,A,v,b,r)}function CJ(a,b,c,d,e,g){this.db=a;this.Pb=b;this.Uc=c;this.Ud=d;this.Fb=e;this.Ve=g}CJ.prototype=new kR;CJ.prototype.constructor=CJ;f=CJ.prototype;f.ka=function(){return this.Fb};f.uc=function(){return this.Ve};f.ed=function(a){return this.Uc.a[a]};f.Jb=function(a){return this.Ud.a[a]};f.Nh=function(a){return this.Uc.a[(-1+this.Uc.a.length|0)-a|0]};\nf.yt=function(a,b,c,d){var e=kI(HH(),c,d),g=lI(HH(),e);return 0!==(this.db&g)?(c=oI(HH(),this.db,e,g),this.Ud.a[c]===b&&ml(nl(),a,this.ed(c))):0!==(this.Pb&g)?(e=oI(HH(),this.Pb,e,g),this.Nh(e).yt(a,b,c,5+d|0)):!1};\nfunction yU(a,b,c,d,e){var g=kI(HH(),d,e),h=lI(HH(),g);if(0!==(a.db&h)){g=oI(HH(),a.db,g,h);var k=a.ed(g);if(Object.is(k,b))return a;var l=a.Jb(g);g=$G(bH(),l);if(c===l&&ml(nl(),k,b))return a;d=zU(a,k,l,g,b,c,d,5+e|0);c=a.pi(h);e=(-1+a.Uc.a.length|0)-a.hm(h)|0;k=a.Uc;b=new zc(k.a.length);k.wa(0,b,0,c);k.wa(1+c|0,b,c,e-c|0);b.a[e]=d;k.wa(1+e|0,b,1+e|0,-1+(k.a.length-e|0)|0);c=gI(a.Ud,c);return new CJ(a.db^h,a.Pb|h,b,c,(-1+a.Fb|0)+d.ka()|0,(a.Ve-g|0)+d.uc()|0)}if(0!==(a.Pb&h))return g=oI(HH(),a.Pb,\ng,h),g=a.Nh(g),d=g.JC(b,c,d,5+e|0),g===d?a:AU(a,h,g,d);e=a.pi(h);k=a.Uc;g=new zc(1+k.a.length|0);k.wa(0,g,0,e);g.a[e]=b;k.wa(e,g,1+e|0,k.a.length-e|0);b=hI(a.Ud,e,c);return new CJ(a.db|h,a.Pb,g,b,1+a.Fb|0,a.Ve+d|0)}\nfunction BU(a,b,c,d,e,g){var h=kI(HH(),d,e),k=lI(HH(),h);if(0!==(a.db&k)){var l=oI(HH(),a.db,h,k);h=a.ed(l);var m=a.Jb(l);if(m===c&&ml(nl(),h,b))return g;l=$G(bH(),m);d=zU(a,h,m,l,b,c,d,5+e|0);CU(a,k,l,d);return g|k}if(0!==(a.Pb&k)){h=oI(HH(),a.Pb,h,k);var n=a.Nh(h);h=n.ka();l=n.uc();m=g;n instanceof CJ&&0!==(k&g)?(BU(n,b,c,d,5+e|0,0),g=n):(g=n.JC(b,c,d,5+e|0),g!==n&&(m|=k));a.Uc.a[(-1+a.Uc.a.length|0)-a.hm(k)|0]=g;a.Fb=(a.Fb-h|0)+g.ka()|0;a.Ve=(a.Ve-l|0)+g.uc()|0;return m}h=a.pi(k);l=a.Uc;e=new zc(1+\nl.a.length|0);l.wa(0,e,0,h);e.a[h]=b;l.wa(h,e,1+h|0,l.a.length-h|0);b=hI(a.Ud,h,c);a.db|=k;a.Uc=e;a.Ud=b;a.Fb=1+a.Fb|0;a.Ve=a.Ve+d|0;return g}\nfunction DU(a,b,c,d,e){var g=kI(HH(),d,e),h=lI(HH(),g);if(0!==(a.db&h)){g=oI(HH(),a.db,g,h);c=a.ed(g);if(ml(nl(),c,b)){b=a.db;2===nI(UH(),b)?(b=a.Pb,b=0===nI(UH(),b)):b=!1;if(b)return h=0===e?a.db^h:lI(HH(),kI(HH(),d,0)),0===g?new CJ(h,0,new zc([a.ed(1)]),new Xc(new Int32Array([a.Ud.a[1]])),-1+a.Fb|0,$G(bH(),a.Ud.a[1])):new CJ(h,0,new zc([a.ed(0)]),new Xc(new Int32Array([a.Ud.a[0]])),-1+a.Fb|0,$G(bH(),a.Ud.a[0]));g=a.pi(h);b=a.Uc;e=new zc(-1+b.a.length|0);b.wa(0,e,0,g);b.wa(1+g|0,e,g,-1+(b.a.length-\ng|0)|0);g=gI(a.Ud,g);return new CJ(a.db^h,a.Pb,e,g,-1+a.Fb|0,a.Ve-d|0)}return a}if(0!==(a.Pb&h)){g=oI(HH(),a.Pb,g,h);g=a.Nh(g);d=g.eG(b,c,d,5+e|0);if(d===g)return a;e=d.ka();if(1===e){if(a.Fb===g.ka())a=d;else{b=(-1+a.Uc.a.length|0)-a.hm(h)|0;c=a.pi(h);var k=a.Uc;e=new zc(k.a.length);k.wa(0,e,0,c);e.a[c]=d.ed(0);k.wa(c,e,1+c|0,b-c|0);k.wa(1+b|0,e,1+b|0,-1+(k.a.length-b|0)|0);b=hI(a.Ud,c,d.Jb(0));a=new CJ(a.db|h,a.Pb^h,e,b,1+(a.Fb-g.ka()|0)|0,(a.Ve-g.uc()|0)+d.uc()|0)}return a}if(1<e)return AU(a,h,\ng,d)}return a}\nfunction EU(a,b,c,d){var e=kI(HH(),d,0),g=lI(HH(),e);if(0!==(a.db&g))e=oI(HH(),a.db,e,g),c=a.ed(e),ml(nl(),c,b)&&(b=a.db,2===nI(UH(),b)?(b=a.Pb,b=0===nI(UH(),b)):b=!1,b?(g^=a.db,0===e?(d=new zc([a.ed(1)]),e=new Xc(new Int32Array([a.Ud.a[1]])),b=$G(bH(),a.Jb(1)),a.Uc=d,a.Ud=e,a.Ve=b):(d=new zc([a.ed(0)]),e=new Xc(new Int32Array([a.Ud.a[0]])),b=$G(bH(),a.Jb(0)),a.Uc=d,a.Ud=e,a.Ve=b),a.db=g,a.Pb=0,a.Fb=1):(b=a.pi(g),c=a.Uc,e=new zc(-1+c.a.length|0),c.wa(0,e,0,b),c.wa(1+b|0,e,b,-1+(c.a.length-b|0)|0),\nb=gI(a.Ud,b),a.db^=g,a.Uc=e,a.Ud=b,a.Fb=-1+a.Fb|0,a.Ve=a.Ve-d|0));else if(0!==(a.Pb&g)&&(e=oI(HH(),a.Pb,e,g),e=a.Nh(e),d=e.eG(b,c,d,5),d!==e))if(1===d.Fb)if(b=a.db,0===nI(UH(),b)?(b=a.Pb,b=1===nI(UH(),b)):b=!1,b)a.db=d.db,a.Pb=d.Pb,a.Uc=d.Uc,a.Ud=d.Ud,a.Fb=d.Fb,a.Ve=d.Ve;else{b=(-1+a.Uc.a.length|0)-a.hm(g)|0;c=a.pi(g);var h=d.ed(0);a.Uc.wa(c,a.Uc,1+c|0,b-c|0);a.Uc.a[c]=h;b=hI(a.Ud,c,d.Jb(0));a.db|=g;a.Pb^=g;a.Ud=b;a.Fb=1+(a.Fb-e.ka()|0)|0;a.Ve=(a.Ve-e.uc()|0)+d.uc()|0}else a.Uc.a[(-1+a.Uc.a.length|\n0)-a.hm(g)|0]=d,a.Fb=-1+a.Fb|0,a.Ve=(a.Ve-e.uc()|0)+d.Ve|0}function zU(a,b,c,d,e,g,h,k){if(32<=k)return GK(),new FU(c,d,pU(0,J(new K,[b,e])));var l=kI(HH(),d,k),m=kI(HH(),h,k);if(l!==m)return a=lI(HH(),l)|lI(HH(),m),d=d+h|0,l<m?new CJ(a,0,new zc([b,e]),new Xc(new Int32Array([c,g])),2,d):new CJ(a,0,new zc([e,b]),new Xc(new Int32Array([g,c])),2,d);l=lI(HH(),l);b=zU(a,b,c,d,e,g,h,5+k|0);return new CJ(0,l,new zc([b]),kG().KB,b.ka(),b.uc())}f.jy=function(){return 0!==this.db};\nf.uy=function(){var a=this.db;return nI(UH(),a)};f.nB=function(){return 0!==this.Pb};f.HB=function(){var a=this.Pb;return nI(UH(),a)};f.pi=function(a){a=this.db&(-1+a|0);return nI(UH(),a)};f.hm=function(a){a=this.Pb&(-1+a|0);return nI(UH(),a)};function AU(a,b,c,d){b=(-1+a.Uc.a.length|0)-a.hm(b)|0;var e=a.Uc,g=new zc(e.a.length);e.wa(0,g,0,e.a.length);g.a[b]=d;return new CJ(a.db,a.Pb,g,a.Ud,(a.Fb-c.ka()|0)+d.ka()|0,(a.Ve-c.uc()|0)+d.uc()|0)}\nfunction CU(a,b,c,d){var e=a.pi(b),g=(-1+a.Uc.a.length|0)-a.hm(b)|0;a.Uc.wa(1+e|0,a.Uc,e,g-e|0);a.Uc.a[g]=d;a.db^=b;a.Pb|=b;a.Ud=gI(a.Ud,e);a.Fb=(-1+a.Fb|0)+d.ka()|0;a.Ve=(a.Ve-c|0)+d.uc()|0}f.Ca=function(a){var b=this.db;b=nI(UH(),b);for(var c=0;c<b;)a.n(this.ed(c)),c=1+c|0;b=this.Pb;b=nI(UH(),b);for(c=0;c<b;)this.Nh(c).Ca(a),c=1+c|0};\nfunction GU(a,b,c){if(0===a.Fb)return a;if(1===a.Fb)return!!b.n(a.ed(0))!==c?a:DJ().mw;if(0===a.Pb){for(var d=a.db,e=0===d?32:31-Math.clz32(d&(-d|0))|0,g=32-Math.clz32(a.db)|0,h=d=0,k=0;e<g;){var l=lI(HH(),e);if(0!==(l&a.db)){var m=a.ed(k);!!b.n(m)!==c&&(d|=l,h=h+$G(bH(),a.Jb(k))|0);k=1+k|0}e=1+e|0}if(0===d)return DJ().mw;if(d===a.db)return a;b=d;b=nI(UH(),b);c=new zc(b);g=new Xc(b);k=32-Math.clz32(d)|0;e=d;e=0===e?32:31-Math.clz32(e&(-e|0))|0;for(l=0;e<k;)m=lI(HH(),e),0!==(m&d)&&(m=mI(HH(),a.db,\nm),c.a[l]=a.Uc.a[m],g.a[l]=a.Ud.a[m],l=1+l|0),e=1+e|0;return new CJ(d,0,c,g,b,h)}h=a.db|a.Pb;d=0===h?32:31-Math.clz32(h&(-h|0))|0;h=32-Math.clz32(h)|0;k=g=0;e=null;m=l=0;for(var n=null,r=0,v=0,x=0,A=0,B=0,C=0,D=d;D<h;){var F=lI(HH(),D);if(0!==(F&a.db)){var I=a.ed(B);!!b.n(I)!==c&&(r|=F,g|=F,x=1+x|0,A=A+$G(bH(),a.Jb(B))|0);B=1+B|0}else if(0!==(F&a.Pb)){I=a.Nh(C);var M=I.EJ(b,c);x=x+M.ka()|0;A=A+M.uc()|0;1<M.ka()?(v|=F,I===M?l|=F:(m|=F,null===n&&(n=new tU(16)),uU(n,M))):1===M.ka()&&(r|=F,k|=F,null===\ne&&(e=new tU(16)),uU(e,M));C=1+C|0}D=1+D|0}return xU(a,x,r,v,d,g,l,k,e,m,n,A)}\nfunction HU(a,b,c){if(b instanceof CJ){if(0===a.Fb)return a;if(1===a.Fb){var d=a.Jb(0);return b.yt(a.ed(0),d,$G(bH(),d),c)?DJ().mw:a}var e=a.db|a.Pb;d=0===e?32:31-Math.clz32(e&(-e|0))|0;e=32-Math.clz32(e)|0;for(var g=0,h=0,k=null,l=0,m=0,n=null,r=0,v=0,x=0,A=0,B=0,C=0,D=d;D<e;){var F=lI(HH(),D);if(0!==(F&a.db)){var I=a.ed(B),M=a.Jb(B),N=$G(bH(),M);b.yt(I,M,N,c)||(r|=F,g|=F,x=1+x|0,A=A+N|0);B=1+B|0}else if(0!==(F&a.Pb)){I=a.Nh(C);if(0!==(F&b.db)){N=mI(HH(),b.db,F);M=b.ed(N);N=b.Jb(N);var P=$G(bH(),\nN);M=I.eG(M,N,P,5+c|0)}else M=0!==(F&b.Pb)?I.mQ(b.Nh(mI(HH(),b.Pb,F)),5+c|0):I;x=x+M.ka()|0;A=A+M.uc()|0;1<M.ka()?(v|=F,I===M?l|=F:(m|=F,null===n&&(n=new tU(16)),uU(n,M))):1===M.ka()&&(r|=F,h|=F,null===k&&(k=new tU(16)),uU(k,M));C=1+C|0}D=1+D|0}return xU(a,x,r,v,d,g,l,h,k,m,n,A)}if(b instanceof FU)throw iL(\"BitmapIndexedSetNode diff HashCollisionSetNode\");throw new w(b);}\nf.i=function(a){if(a instanceof CJ){if(this===a)return!0;if(this.Ve===a.Ve&&this.Pb===a.Pb&&this.db===a.db&&this.Fb===a.Fb){var b=this.Ud,c=a.Ud;b=qj(Pj(),b,c)}else b=!1;if(b){b=this.Uc;a=a.Uc;c=this.Uc.a.length;if(b===a)return!0;for(var d=!0,e=0;d&&e<c;)d=ml(nl(),b.a[e],a.a[e]),e=1+e|0;return d}}return!1};f.B=function(){throw nv(\"Trie nodes do not support hashing.\");};\nfunction IU(a){var b=a.Uc.ia(),c=b.a.length,d=a.db;for(d=nI(UH(),d);d<c;)b.a[d]=b.a[d].lQ(),d=1+d|0;return new CJ(a.db,a.Pb,b,a.Ud.ia(),a.Fb,a.Ve)}\nfunction JU(a,b,c){if(b instanceof CJ){if(0===a.Fb)return b;if(0===b.Fb||b===a)return a;if(1===b.Fb){var d=b.Jb(0);return yU(a,b.ed(0),d,$G(bH(),d),c)}d=!1;var e=a.db|b.db|a.Pb|b.Pb,g=lI(HH(),0===e?32:31-Math.clz32(e&(-e|0))|0);e=lI(HH(),31-Math.clz32(e)|0);for(var h=0,k=0,l=0,m=0,n=0,r=0,v=0,x=0,A=0,B=0,C=g,D=0,F=0,I=!1;!I;)0!==(C&a.db)?(0!==(C&b.db)?(a.Jb(D)===b.Jb(F)&&ml(nl(),a.ed(D),b.ed(F))?A|=C:(x|=C,B|=lI(HH(),kI(HH(),$G(bH(),a.Jb(D)),c))),F=1+F|0):0!==(C&b.Pb)?k|=C:m|=C,D=1+D|0):0!==(C&a.Pb)?\n0!==(C&b.db)?(l|=C,F=1+F|0):0!==(C&b.Pb)?h|=C:r|=C:0!==(C&b.db)?(n|=C,F=1+F|0):0!==(C&b.Pb)&&(v|=C),C===e?I=!0:C<<=1;C=m|n|A;B|=h|k|l|r|v;if(C===(m|A)&&B===r)return a;I=nI(UH(),C);D=I+nI(UH(),B)|0;F=new zc(D);I=new Xc(I);var M=0,N=0,P=0,T=0,Y=0,Z=0;c=5+c|0;for(var S=0,ea=0,ia=!1;!ia;){if(0!==(g&h)){var X=a.Nh(Y),sa=X.jQ(b.Nh(Z),c);X!==sa&&(d=!0);F.a[-1+(D-ea|0)|0]=sa;ea=1+ea|0;Z=1+Z|0;Y=1+Y|0;M=M+sa.ka()|0;N=N+sa.uc()|0}else if(0!==(g&k)){d=!0;X=b.Nh(Z);sa=a.ed(P);var Ja=a.Jb(P),Xa=$G(bH(),Ja);X=\nX.JC(sa,Ja,Xa,c);F.a[-1+(D-ea|0)|0]=X;ea=1+ea|0;Z=1+Z|0;P=1+P|0;M=M+X.ka()|0;N=N+X.uc()|0}else 0!==(g&l)?(sa=b.Jb(T),X=a.Nh(Y),sa=X.JC(b.ed(T),b.Jb(T),$G(bH(),sa),c),sa!==X&&(d=!0),F.a[-1+(D-ea|0)|0]=sa,ea=1+ea|0,Y=1+Y|0,T=1+T|0,M=M+sa.ka()|0,N=N+sa.uc()|0):0!==(g&m)?(X=a.Ud.a[P],F.a[S]=a.ed(P),I.a[S]=X,S=1+S|0,P=1+P|0,M=1+M|0,N=N+$G(bH(),X)|0):0!==(g&n)?(d=!0,X=b.Ud.a[T],F.a[S]=b.ed(T),I.a[S]=X,S=1+S|0,T=1+T|0,M=1+M|0,N=N+$G(bH(),X)|0):0!==(g&r)?(X=a.Nh(Y),F.a[-1+(D-ea|0)|0]=X,ea=1+ea|0,Y=1+Y|0,\nM=M+X.ka()|0,N=N+X.uc()|0):0!==(g&v)?(d=!0,X=b.Nh(Z),F.a[-1+(D-ea|0)|0]=X,ea=1+ea|0,Z=1+Z|0,M=M+X.ka()|0,N=N+X.uc()|0):0!==(g&x)?(d=!0,X=a.Jb(P),sa=b.Jb(T),X=zU(b,a.ed(P),X,$G(bH(),X),b.ed(T),sa,$G(bH(),sa),c),F.a[-1+(D-ea|0)|0]=X,ea=1+ea|0,P=1+P|0,T=1+T|0,M=M+X.ka()|0,N=N+X.uc()|0):0!==(g&A)&&(X=b.Ud.a[T],F.a[S]=b.ed(T),I.a[S]=X,S=1+S|0,T=1+T|0,M=1+M|0,N=N+$G(bH(),X)|0,P=1+P|0);g===e?ia=!0:g<<=1}return d?new CJ(C,B,F,I,M,N):a}throw nv(\"Cannot concatenate a HashCollisionSetNode with a BitmapIndexedSetNode\");\n}f.FJ=function(a){var b=this.db;b=nI(UH(),b);for(var c=0;c<b;)a.ba(this.ed(c),this.Jb(c)),c=1+c|0;b=this.Pb;b=nI(UH(),b);for(c=0;c<b;)this.Nh(c).FJ(a),c=1+c|0};f.jQ=function(a,b){return JU(this,a,b)};f.lQ=function(){return IU(this)};f.mQ=function(a,b){return HU(this,a,b)};f.EJ=function(a,b){return GU(this,a,b)};f.eG=function(a,b,c,d){return DU(this,a,b,c,d)};f.JC=function(a,b,c,d){return yU(this,a,b,c,d)};f.mB=function(a){return this.Nh(a)};\nf.$classData=q({S6:0},!1,\"scala.collection.immutable.BitmapIndexedSetNode\",{S6:1,v8:1,lC:1,g:1});function oU(a,b,c){this.Py=a;this.Eo=b;this.of=c;At(tp(),2<=this.of.K())}oU.prototype=new XQ;oU.prototype.constructor=oU;function KU(a,b){a=a.of.m();for(var c=0;a.s();){if(ml(nl(),a.t().h(),b))return c;c=1+c|0}return-1}f=oU.prototype;f.ka=function(){return this.of.K()};f.BJ=function(a,b,c,d){a=this.KF(a,b,c,d);if(a.b())throw LU();return a.o()};\nf.KF=function(a,b,c){return this.Eo===c?(a=KU(this,a),0<=a?new L(this.of.va(a).j()):R()):R()};f.KJ=function(a,b,c,d,e){return this.Eo===c?(a=KU(this,a),-1===a?Es(e):this.of.va(a).j()):Es(e)};f.DF=function(a,b,c){return this.Eo===c&&0<=KU(this,a)};f.KC=function(a,b,c,d,e,g){e=KU(this,a);return 0<=e?g?Object.is(this.of.va(e).j(),b)?this:new oU(c,d,this.of.$r(e,G(new H,a,b))):this:new oU(c,d,this.of.hn(G(new H,a,b)))};\nf.hR=function(a,b,c,d){if(this.DF(a,b,c,d)){d=MU(this.of,new y(g=>ml(nl(),g.h(),a)),!0);if(1===d.K()){var e=d.va(0);if(null===e)throw new w(e);d=e.h();e=e.j();return new aI(lI(HH(),kI(HH(),c,0)),0,new zc([d,e]),new Xc(new Int32Array([b])),1,c)}return new oU(b,c,d)}return this};f.nB=function(){return!1};f.HB=function(){return 0};f.qh=function(){throw aL(new bL,\"No sub-nodes present in hash-collision leaf node.\");};f.jy=function(){return!0};f.uy=function(){return this.of.K()};f.Ef=function(a){return this.of.va(a).h()};\nf.Tf=function(a){return this.of.va(a).j()};f.rv=function(a){return this.of.va(a)};f.Jb=function(){return this.Py};f.Ca=function(a){this.of.Ca(a)};f.og=function(a){this.of.Ca(new y(b=>{if(null!==b)return a.ba(b.h(),b.j());throw new w(b);}))};f.GJ=function(a){for(var b=this.of.m();b.s();){var c=b.t();(0,a.aM)(c.h(),c.j(),this.Py)}};\nf.i=function(a){if(a instanceof oU){if(this===a)return!0;if(this.Eo===a.Eo&&this.of.K()===a.of.K()){for(var b=this.of.m();b.s();){var c=b.t();if(null===c)throw new w(c);var d=c.j();c=KU(a,c.h());if(0>c||!ml(nl(),d,a.of.va(c).j()))return!1}return!0}}return!1};\nf.qQ=function(a,b){a=MU(this.of,a,b);b=a.K();if(0===b)return bI().Ty;if(1===b){b=a.e();if(null===b)throw new w(b);a=b.h();b=b.j();return new aI(lI(HH(),kI(HH(),this.Eo,0)),0,new zc([a,b]),new Xc(new Int32Array([this.Py])),1,this.Eo)}return b===this.of.K()?this:new oU(this.Py,this.Eo,a)};f.B=function(){throw nv(\"Trie nodes do not support hashing.\");};f.uc=function(){return Math.imul(this.of.K(),this.Eo)};f.kQ=function(){return new oU(this.Py,this.Eo,this.of)};\nf.iQ=function(a){if(a instanceof oU)if(a===this)a=this;else{for(var b=null,c=this.of.m();c.s();){var d=c.t();0>KU(a,d.h())&&(null===b&&(b=new NU,OU(b,a.of)),PU(b,d))}a=null===b?a:new oU(this.Py,this.Eo,b.im())}else{if(a instanceof aI)throw nv(\"Cannot concatenate a HashCollisionMapNode with a BitmapIndexedMapNode\");throw new w(a);}return a};f.mB=function(a){return this.qh(a)};f.$classData=q({T6:0},!1,\"scala.collection.immutable.HashCollisionMapNode\",{T6:1,O7:1,lC:1,g:1});\nfunction FU(a,b,c){this.Yv=a;this.Wp=b;this.Kg=c;At(tp(),2<=this.Kg.K())}FU.prototype=new kR;FU.prototype.constructor=FU;f=FU.prototype;f.yt=function(a,b,c){return this.Wp===c?QU(this.Kg,a):!1};f.JC=function(a,b,c,d){return this.yt(a,b,c,d)?this:new FU(b,c,this.Kg.hn(a))};f.eG=function(a,b,c,d){return this.yt(a,b,c,d)?(d=MU(this.Kg,new y(e=>ml(nl(),e,a)),!0),1===d.K()?new CJ(lI(HH(),kI(HH(),c,0)),0,new zc([d.va(0)]),new Xc(new Int32Array([b])),1,c):new FU(b,c,d)):this};f.nB=function(){return!1};\nf.HB=function(){return 0};f.Nh=function(){throw aL(new bL,\"No sub-nodes present in hash-collision leaf node.\");};f.jy=function(){return!0};f.uy=function(){return this.Kg.K()};f.ed=function(a){return this.Kg.va(a)};f.Jb=function(){return this.Yv};f.ka=function(){return this.Kg.K()};f.Ca=function(a){for(var b=this.Kg.m();b.s();)a.n(b.t())};f.uc=function(){return Math.imul(this.Kg.K(),this.Wp)};\nf.EJ=function(a,b){a=MU(this.Kg,a,b);b=a.K();return 0===b?DJ().mw:1===b?new CJ(lI(HH(),kI(HH(),this.Wp,0)),0,new zc([a.e()]),new Xc(new Int32Array([this.Yv])),1,this.Wp):a.K()===this.Kg.K()?this:new FU(this.Yv,this.Wp,a)};f.mQ=function(a,b){return this.EJ(new y(c=>a.yt(c,this.Yv,this.Wp,b)),!0)};f.i=function(a){if(a instanceof FU){if(this===a)return!0;if(this.Wp===a.Wp&&this.Kg.K()===a.Kg.K()){a=a.Kg;for(var b=!0,c=this.Kg.m();b&&c.s();)b=c.t(),b=QU(a,b);return b}}return!1};\nf.B=function(){throw nv(\"Trie nodes do not support hashing.\");};f.jQ=function(a){if(a instanceof FU){if(a===this)return this;var b=null;for(a=a.Kg.m();a.s();){var c=a.t();QU(this.Kg,c)||(null===b&&(b=new NU,OU(b,this.Kg)),PU(b,c))}return null===b?this:new FU(this.Yv,this.Wp,b.im())}if(a instanceof CJ)throw nv(\"Cannot concatenate a HashCollisionSetNode with a BitmapIndexedSetNode\");throw new w(a);};f.FJ=function(a){for(var b=this.Kg.m();b.s();){var c=b.t();a.ba(c,this.Yv)}};\nf.lQ=function(){return new FU(this.Yv,this.Wp,this.Kg)};f.mB=function(a){return this.Nh(a)};f.$classData=q({U6:0},!1,\"scala.collection.immutable.HashCollisionSetNode\",{U6:1,v8:1,lC:1,g:1});function RU(){this.Mr=null;SU=this;var a=bI();this.Mr=new TU(a.Ty)}RU.prototype=new p;RU.prototype.constructor=RU;f=RU.prototype;f.Hh=function(a){return Dz(0,a)};function Dz(a,b){return b instanceof TU?b:UU(VU(new WU,b))}f.Eb=function(){return new WU};f.Ib=function(a){return Dz(0,a)};f.X=function(){return this.Mr};\nf.$classData=q({W6:0},!1,\"scala.collection.immutable.HashMap$\",{W6:1,g:1,Ey:1,l:1});var SU;function Ez(){SU||(SU=new RU);return SU}function XU(){this.Fo=null;YU=this;var a=DJ();this.Fo=new ZU(a.mw)}XU.prototype=new p;XU.prototype.constructor=XU;function $U(a,b){return b instanceof ZU?b:0===b.Q()?a.Fo:aV(bV(new cV,b))}XU.prototype.Eb=function(){return new cV};XU.prototype.Ib=function(a){return $U(this,a)};XU.prototype.X=function(){return this.Fo};\nXU.prototype.$classData=q({b7:0},!1,\"scala.collection.immutable.HashSet$\",{b7:1,g:1,bg:1,l:1});var YU;function dV(){YU||(YU=new XU);return YU}function eV(a,b){this.o7=a;this.p7=b}eV.prototype=new p;eV.prototype.constructor=eV;eV.prototype.e=function(){return this.o7};eV.prototype.Lf=function(){return this.p7};eV.prototype.$classData=q({n7:0},!1,\"scala.collection.immutable.LazyList$State$Cons\",{n7:1,g:1,m7:1,l:1});function fV(){}fV.prototype=new p;fV.prototype.constructor=fV;\nfV.prototype.LJ=function(){throw AH(\"head of empty lazy list\");};fV.prototype.Lf=function(){throw nv(\"tail of empty lazy list\");};fV.prototype.e=function(){this.LJ()};fV.prototype.$classData=q({q7:0},!1,\"scala.collection.immutable.LazyList$State$Empty$\",{q7:1,g:1,m7:1,l:1});var gV;function hV(){gV||(gV=new fV);return gV}function iV(){}iV.prototype=new p;iV.prototype.constructor=iV;f=iV.prototype;f.Hh=function(a){return pp(0,a)};\nfunction pp(a,b){ZJ(b)&&b.b()?a=nf():jV(b)?a=b:(a=kV(new lV,b),a=a.Sy?UU(a.Wt):a.bq);return a}f.Eb=function(){return new lV};f.Ib=function(a){return pp(0,a)};f.X=function(){return nf()};f.$classData=q({u7:0},!1,\"scala.collection.immutable.Map$\",{u7:1,g:1,Ey:1,l:1});var mV;function qp(){mV||(mV=new iV);return mV}function nV(){}nV.prototype=new p;nV.prototype.constructor=nV;\nfunction Aq(a,b){return b&&b.$classData&&b.$classData.rb.OL?MF(oV(new OF,b)):0===b.Q()?ap():b&&b.$classData&&b.$classData.rb.dq?b:MF(oV(new OF,b))}nV.prototype.Eb=function(){return new OF};nV.prototype.Ib=function(a){return Aq(0,a)};nV.prototype.X=function(){return ap()};nV.prototype.$classData=q({j8:0},!1,\"scala.collection.immutable.Set$\",{j8:1,g:1,bg:1,l:1});var pV;function Bq(){pV||(pV=new nV);return pV}function qV(){}qV.prototype=new p;qV.prototype.constructor=qV;f=qV.prototype;\nf.CF=function(a,b){return rV(0,a,b)};function rV(a,b,c){if(b instanceof sV&&(a=b.We,null===c?null===a:c.i(a)))return b;if(b&&b.$classData&&b.$classData.rb.YB&&(a=b.se(),null===c?null===a:c.i(a))){a=new sV;var d=nJ(),e=b.m();b=b.ka();var g=32-Math.clz32(b)|0;b=Eda(d,1,b,e,g);return tV(a,b,c)}a=null;for(b=b.m();b.s();){e=b.t();if(null===e)throw new w(e);d=e.h();e=e.j();a=gJ(nJ(),a,d,e,!0,c)}return tV(new sV,a,c)}f.Dv=function(a){return new uV(a)};f.qr=function(a,b){return rV(0,a,b)};f.Hd=function(a){return vV(a)};\nf.$classData=q({H8:0},!1,\"scala.collection.immutable.TreeMap$\",{H8:1,g:1,xL:1,l:1});var wV;function xV(){wV||(wV=new qV);return wV}function yV(a){this.aH=this.Yy=null;if(null===a)throw null;this.aH=a;this.Yy=null}yV.prototype=new gS;yV.prototype.constructor=yV;yV.prototype.ey=function(a,b){this.Yy=fR(this.aH,this.Yy,a,b)};yV.prototype.ba=function(a,b){this.ey(a,b)};yV.prototype.$classData=q({K8:0},!1,\"scala.collection.immutable.TreeMap$TreeMapBuilder$adder$\",{K8:1,nH:1,g:1,kz:1});\nfunction zV(a){this.GS=this.cH=null;if(null===a)throw null;this.GS=a;this.cH=a.Hf}zV.prototype=new cS;zV.prototype.constructor=zV;zV.prototype.n=function(a){var b=nJ();this.cH=pI(PI(b,this.cH,a,this.GS.Xe))};zV.prototype.$classData=q({O8:0},!1,\"scala.collection.immutable.TreeSet$sub$1$\",{O8:1,dM:1,g:1,la:1});function AV(){}AV.prototype=new p;AV.prototype.constructor=AV;f=AV.prototype;f.Hh=function(a){return Uy(a)};function Uy(a){var b=a.Q();return BV(CV(new DV,0<b?Eb((1+b|0)/.75):16,.75),a)}\nf.Eb=function(){return new EV(16,.75)};f.Ib=function(a){return Uy(a)};f.X=function(){return FV()};f.$classData=q({F9:0},!1,\"scala.collection.mutable.HashMap$\",{F9:1,g:1,Ey:1,l:1});var GV;function Ty(){GV||(GV=new AV);return GV}function HV(){}HV.prototype=new p;HV.prototype.constructor=HV;function qz(a){var b=a.Q();return IV(JV(new KV,0<b?Eb((1+b|0)/.75):16,.75),a)}HV.prototype.Eb=function(){return new LV(16,.75)};HV.prototype.X=function(){return Vn()};HV.prototype.Ib=function(a){return qz(a)};\nHV.prototype.$classData=q({O9:0},!1,\"scala.collection.mutable.HashSet$\",{O9:1,g:1,bg:1,l:1});var MV;function pz(){MV||(MV=new HV);return MV}function NV(){}NV.prototype=new p;NV.prototype.constructor=NV;f=NV.prototype;f.Hh=function(a){return OV(a)};function OV(a){if(a instanceof lA)return a;var b=new lA;return lR(b,a)}f.Eb=function(){return PV(new QV,new lA)};f.Ib=function(a){return OV(a)};f.X=function(){return new lA};\nf.$classData=q({$9:0},!1,\"scala.collection.mutable.LinkedHashMap$\",{$9:1,g:1,Ey:1,l:1});var RV;function SV(a){this.SS=0;this.VS=null;this.XS=this.WS=0;this.US=null;this.TS=0;this.dz=null;if(null===a)throw null;this.dz=a;wR(this)}SV.prototype=new p;SV.prototype.constructor=SV;f=SV.prototype;f.sJ=function(){return this.SS};f.bQ=function(a){this.SS=a};f.bl=function(){return this.VS};f.gM=function(a){this.VS=a};f.nu=function(){return this.WS};f.hz=function(a){this.WS=a};f.pT=function(){return this.XS};\nf.hM=function(a){this.XS=a};f.lu=function(){return this.US};f.$L=function(a){this.US=a};f.kT=function(){return this.TS};f.jT=function(a){this.TS=a};f.CJ=function(a,b){a=new xR(a,b);null===this.dz.Gn?this.dz.Gn=a:(this.dz.xw.zm=a,a.ww=this.dz.xw);return this.dz.xw=a};f.$classData=q({a$:0},!1,\"scala.collection.mutable.LinkedHashMap$$anon$1\",{a$:1,g:1,U9:1,W9:1});function TV(){}TV.prototype=new p;TV.prototype.constructor=TV;function JB(a,b){if(b instanceof MB)return b;a=new MB;return lR(a,b)}\nTV.prototype.Eb=function(){return PV(new QV,new MB)};TV.prototype.Ib=function(a){return JB(0,a)};TV.prototype.X=function(){return new MB};TV.prototype.$classData=q({h$:0},!1,\"scala.collection.mutable.LinkedHashSet$\",{h$:1,g:1,bg:1,l:1});var UV;function KB(){UV||(UV=new TV);return UV}function VV(a){this.ZS=0;this.bT=null;this.dT=this.cT=0;this.aT=null;this.$S=0;this.ez=null;if(null===a)throw null;this.ez=a;wR(this)}VV.prototype=new p;VV.prototype.constructor=VV;f=VV.prototype;f.sJ=function(){return this.ZS};\nf.bQ=function(a){this.ZS=a};f.bl=function(){return this.bT};f.gM=function(a){this.bT=a};f.nu=function(){return this.cT};f.hz=function(a){this.cT=a};f.pT=function(){return this.dT};f.hM=function(a){this.dT=a};f.lu=function(){return this.aT};f.$L=function(a){this.aT=a};f.kT=function(){return this.$S};f.jT=function(a){this.$S=a};f.CJ=function(a){a=new yR(a);null===this.ez.ku?this.ez.ku=a:(this.ez.yC.Mo=a,a.yw=this.ez.yC);return this.ez.yC=a};\nf.$classData=q({i$:0},!1,\"scala.collection.mutable.LinkedHashSet$$anon$1\",{i$:1,g:1,U9:1,W9:1});function WV(){}WV.prototype=new p;WV.prototype.constructor=WV;f=WV.prototype;f.CF=function(a,b){return XV(0,a,b)};function XV(a,b,c){a=YV(c);return lR(a,b)}f.Dv=function(a){return PV(new QV,YV(a))};f.Hd=function(a){return YV(a)};f.qr=function(a,b){return XV(0,a,b)};f.$classData=q({K$:0},!1,\"scala.collection.mutable.TreeMap$\",{K$:1,g:1,xL:1,l:1});var ZV;function $V(){ZV||(ZV=new WV);return ZV}\nfunction dT(a,b){this.C3=a;this.D3=b}dT.prototype=new p;dT.prototype.constructor=dT;dT.prototype.sl=function(a){return this.$l(a)};dT.prototype.$l=function(a){return this.C3.Da(this.D3,a)};dT.prototype.$classData=q({B3:0},!1,\"scala.math.Ordered$$anon$1\",{B3:1,g:1,yj:1,nf:1});function aW(){}aW.prototype=new p;aW.prototype.constructor=aW;aW.prototype.$classData=q({E3:0},!1,\"scala.math.Ordering$\",{E3:1,g:1,pba:1,l:1});var bW;function Su(){bW||(bW=new aW);return bW}function yH(){}yH.prototype=new wM;\nyH.prototype.constructor=yH;function cW(){}cW.prototype=yH.prototype;function dW(){}dW.prototype=new p;dW.prototype.constructor=dW;function eW(){}eW.prototype=dW.prototype;dW.prototype.u=function(){return\"\\x3cfunction1\\x3e\"};dW.prototype.n=function(a){return this.Ob(a,pG().nR)};var kH=q({caa:0},!1,\"scala.runtime.Nothing$\",{caa:1,pc:1,g:1,l:1});function U(a){this.P$=a}U.prototype=new aS;U.prototype.constructor=U;function Es(a){return(0,a.P$)()}\nU.prototype.$classData=q({O$:0},!1,\"scala.scalajs.runtime.AnonFunction0\",{O$:1,Xba:1,g:1,naa:1});function y(a){this.R$=a}y.prototype=new cS;y.prototype.constructor=y;y.prototype.n=function(a){return(0,this.R$)(a)};y.prototype.$classData=q({Q$:0},!1,\"scala.scalajs.runtime.AnonFunction1\",{Q$:1,dM:1,g:1,la:1});function fn(a){this.T$=a}fn.prototype=new gS;fn.prototype.constructor=fn;fn.prototype.ba=function(a,b){return(0,this.T$)(a,b)};\nfn.prototype.$classData=q({S$:0},!1,\"scala.scalajs.runtime.AnonFunction2\",{S$:1,nH:1,g:1,kz:1});function fW(a){this.aM=a}fW.prototype=new iS;fW.prototype.constructor=fW;fW.prototype.$classData=q({U$:0},!1,\"scala.scalajs.runtime.AnonFunction3\",{U$:1,Zba:1,g:1,paa:1});class vea extends Vd{}function gW(){}gW.prototype=new p;gW.prototype.constructor=gW;function hW(){}hW.prototype=gW.prototype;class Yj extends wS{constructor(a){super();yF(this,\"\"+a,a instanceof Vd?a:null,!0)}}\nYj.prototype.$classData=q({Q0:0},!1,\"java.lang.AssertionError\",{Q0:1,OF:1,pc:1,g:1,l:1});var jaa=q({S0:0},!1,\"java.lang.Boolean\",{S0:1,g:1,l:1,nf:1,Et:1},a=>\"boolean\"===typeof a),laa=q({U0:0},!1,\"java.lang.Character\",{U0:1,g:1,l:1,nf:1,Et:1},a=>a instanceof ba);function iL(a){var b=new iW;yF(b,a,null,!0);return b}class iW extends xF{}iW.prototype.$classData=q({Te:0},!1,\"java.lang.RuntimeException\",{Te:1,qd:1,pc:1,g:1,l:1});function jW(){this.ly=null}jW.prototype=new p;jW.prototype.constructor=jW;\nfunction kW(a,b){a=a.ly;a.ja=\"\"+a.ja+b}function lW(a,b){a=a.ly;b=String.fromCharCode(b);a.ja=\"\"+a.ja+b}jW.prototype.eM=function(a,b){return this.ly.ja.substring(a,b)};jW.prototype.u=function(){return this.ly.ja};jW.prototype.uJ=function(a){var b=this.ly;b.ja=\"\"+b.ja+a};jW.prototype.$classData=q({v1:0},!1,\"java.lang.StringBuffer\",{v1:1,g:1,ZJ:1,rQ:1,l:1});function LQ(a){a.ja=\"\";return a}function Uq(a,b){LQ(a);if(null===b)throw le();a.ja=b;return a}\nfunction Cu(a){var b=new Sq;LQ(b);if(0>a)throw new Aj;return b}function Sq(){this.ja=null}Sq.prototype=new p;Sq.prototype.constructor=Sq;function MQ(a,b,c,d){b=null===b?\"null\":b;c=\"string\"===typeof b?b.substring(c,d):b.eM(c,d);a.ja=\"\"+a.ja+c}function mW(a,b){b=AM(zH(),b,0,b.a.length);a.ja=\"\"+a.ja+b}f=Sq.prototype;f.u=function(){return this.ja};f.K=function(){return this.ja.length};f.eM=function(a,b){return this.ja.substring(a,b)};f.uJ=function(a){this.ja=\"\"+this.ja+a};\nf.$classData=q({w1:0},!1,\"java.lang.StringBuilder\",{w1:1,g:1,ZJ:1,rQ:1,l:1});function nW(a){return 0===a.$h?(a=a.Bg,!(-1===a.W&&-1===a.Y)):!1}function oW(a,b){var c=a.xb,d=c>>31,e=-c|0;c=0!==c?~d:-d|0;var g=CR(a);d=g>>31;g=e+g|0;e=(-2147483648^g)<(-2147483648^e)?1+(c+d|0)|0:c+d|0;if(0===e?-2147483629<(-2147483648^g):0<e)throw new qb(\"Rounding necessary\");a=pW(a);if(yh(Sh(),a)<b)return a.xl();throw new qb(\"Rounding necessary\");}\nfunction CR(a){return 0<a.cs?a.cs:1+Eb(.3010299956639812*(-1+a.$h|0))|0}function HR(a,b){a.bs=b;a.$h=yh(Sh(),b);64>a.$h&&(a.Bg=b.xl())}function qW(a){a.pu=null;a.lq=0;a.$h=0;a.Bg=aa;a.xb=0;a.cs=0}function kN(a,b){var c=new mr;qW(c);c.Bg=a;c.xb=b;c.$h=gN(hN(),a);return c}function eN(a,b){var c=new mr;qW(c);c.Bg=new ma(a,a>>31);c.xb=b;hN();a=32-Math.clz32(0>a?~a:a)|0;c.$h=a;return c}\nfunction nr(a,b,c){qW(a);var d=-1+(0+c|0)|0;if(null===b)throw oL(\"in \\x3d\\x3d null\");if(d>=b.a.length||0>=c||0>d)throw new ZL(\"Bad offset/length: offset\\x3d0 len\\x3d\"+c+\" in.length\\x3d\"+b.a.length);var e=0;if(0<=d&&43===b.a[0]){if(e=1+e|0,e<d&&oN(hN(),b.a[e],new Ic(new Uint16Array([43,45]))))throw new ZL(\"For input string: \"+b.u());}else{c=e<=d&&45===b.a[e];var g=(1+e|0)<d&&oN(hN(),b.a[1+e|0],new Ic(new Uint16Array([43,45])));if(c&&g)throw new ZL(\"For input string: \"+b.u());}var h=e;for(c=!1;e<=d&&\nnN(hN(),b.a[e],new Ic(new Uint16Array([46,101,69])));)c||48===b.a[e]||(c=!0),e=1+e|0;g=e-h|0;g=AM(zH(),b,h,g);h=e-h|0;if(e<=d&&46===b.a[e]){for(var k=e=1+e|0;e<=d&&nN(hN(),b.a[e],new Ic(new Uint16Array([101,69])));)c||48===b.a[e]||(c=!0),e=1+e|0;a.xb=e-k|0;c=a.xb;zH();c=\"\"+g+AM(0,b,k,c);g=h+a.xb|0}else a.xb=0,c=g,g=h;g|=0;if(e<=d&&oN(hN(),b.a[e],new Ic(new Uint16Array([101,69])))&&(e=1+e|0,h=(1+e|0)<=d&&45!==b.a[1+e|0],e=e<=d&&43===b.a[e]&&h?1+e|0:e,d=(1+d|0)-e|0,e=AM(zH(),b,e,d),b=a.xb,d=b>>31,h=\nTH(UH(),e,10),e=h>>31,h=b-h|0,a.xb=h,k=a.xb,h!==k||((-2147483648^h)>(-2147483648^b)?-1+(d-e|0)|0:d-e|0)!==k>>31))throw new ZL(\"Scale out of range\");if(19>g){e=uM();\"\"===c&&pM(c);d=0;b=!1;switch(c.charCodeAt(0)){case 43:d=1;break;case 45:d=1,b=!0}g=c.length;if(d>=g)pM(c),e=void 0;else{h=(e.RF?e.QF:nM(e))[10];for(k=h.j1;;){if(e=d<g){e=Pr();var l=c.charCodeAt(d);e=256>l?48===l:0<=kj(Pj(),RL(e),l)}if(e)d=1+d|0;else break}(g-d|0)>Math.imul(3,k)&&pM(c);e=1+Bb(-1+(g-d|0)|0,k)|0;l=d+e|0;var m=qM(d,l,c);if(l===\ng)e=new ma(m,0);else{e=h.DQ;d=e.W;e=e.Y;k=l+k|0;var n=65535&m,r=m>>>16|0,v=65535&d,x=d>>>16|0,A=Math.imul(n,v);v=Math.imul(r,v);var B=Math.imul(n,x);n=A+((v+B|0)<<16)|0;A=(A>>>16|0)+B|0;m=((Math.imul(m,e)+Math.imul(r,x)|0)+(A>>>16|0)|0)+(((65535&A)+v|0)>>>16|0)|0;l=qM(l,k,c);l=n+l|0;m=(-2147483648^l)<(-2147483648^n)?1+m|0:m;k===g?e=new ma(l,m):(n=h.k1,h=n.W,n=n.Y,g=qM(k,g,c),(m===n?(-2147483648^l)>(-2147483648^h):m>n)&&pM(c),n=65535&l,h=l>>>16|0,x=65535&d,k=d>>>16|0,r=Math.imul(n,x),x=Math.imul(h,\nx),A=Math.imul(n,k),n=r+((x+A|0)<<16)|0,r=(r>>>16|0)+A|0,e=(((Math.imul(l,e)+Math.imul(m,d)|0)+Math.imul(h,k)|0)+(r>>>16|0)|0)+(((65535&r)+x|0)>>>16|0)|0,d=n+g|0,e=(-2147483648^d)<(-2147483648^n)?1+e|0:e,-2147483648===(-2147483648^e)&&(-2147483648^d)<(-2147483648^g)&&pM(c),e=new ma(d,e))}}d=e.W;e=e.Y;b?(b=-d|0,d=0!==d?~e:-e|0,(0===d?0!==b:0<d)&&pM(c),c=new ma(b,d)):(0>e&&pM(c),c=new ma(d,e));a.Bg=c;a.$h=gN(hN(),a.Bg)}else HR(a,eM(c))}\nfunction FR(a,b,c){qW(a);if(null===b)throw oL(\"unscaledVal \\x3d\\x3d null\");a.xb=c;HR(a,b);return a}function mr(){this.pu=null;this.lq=0;this.bs=null;this.$h=0;this.Bg=aa;this.cs=this.xb=0}mr.prototype=new wM;mr.prototype.constructor=mr;function rW(a){if(64>a.$h){if(0>a.Bg.Y)return-1;a=a.Bg;var b=a.Y;return(0===b?0!==a.W:0<b)?1:0}return $M(a).Ya}\nfunction pr(a){if(0===a.cs){if(0===a.$h)var b=1;else if(64>a.$h){var c=a.Bg;if(0===c.W&&-2147483648===c.Y)b=19;else{Pj();b=hN().lz;if(0>c.Y){var d=c.W;c=c.Y;d=new ma(-d|0,0!==d?~c:-c|0)}else d=c;b:{c=0;for(var e=b.a.length;;){if(c===e){b=-1-c|0;break b}var g=(c+e|0)>>>1|0,h=b.a[g],k=Za(new ma(h.W,h.Y));h=k.W;k=k.Y;h=ua(xa(),d.W,d.Y,h,k);if(0>h)e=g;else{if(0===h){b=g;break b}c=1+g|0}}}b=0>b?-1-b|0:1+b|0}}else b=1+Eb(.3010299956639812*(-1+a.$h|0))|0,d=$M(a),c=fi(),b=0!==GR(d,Pi(c,new ma(b,b>>31))).Ya?\n1+b|0:b;a.cs=b}return a.cs}function sW(a){if(nW(a))return a;var b=-1+fi().fs.a.length|0,c=1,d=$M(a),e=a=a.xb;for(a>>=31;;){if(ER(d,0))c=e,b=d,c=new ma(c,a);else{var g=tW(d,fi().fs.a[c]);if(0===g.oM.Ya){d=g.nM;var h=c;g=h>>31;var k=a;a=e-h|0;e=(-2147483648^a)>(-2147483648^e)?-1+(k-g|0)|0:k-g|0;c=c<b?1+c|0:c;g=e;e=a;a=g;continue}if(1!==c){c=1;continue}c=e;b=d;c=new ma(c,a)}break}c=Za(c);d=Za(new ma(c.W,c.Y));c=d.W;d=d.Y;return FR(new mr,b,mN(hN(),new ma(c,d)))}\nfunction uW(a,b){var c=rW(a),d=rW(b);if(c===d){if(a.xb===b.xb&&64>a.$h&&64>b.$h){d=a.Bg;c=b.Bg;var e=d.Y,g=c.Y;if(e===g?(-2147483648^d.W)<(-2147483648^c.W):e<g)return-1;a=a.Bg;b=b.Bg;d=a.Y;c=b.Y;return(d===c?(-2147483648^a.W)>(-2147483648^b.W):d>c)?1:0}e=a.xb;g=e>>31;d=b.xb;var h=d>>31;d=e-d|0;e=(-2147483648^d)>(-2147483648^e)?-1+(g-h|0)|0:g-h|0;g=CR(a)-CR(b)|0;h=g>>31;var k=1+d|0,l=0===k?1+e|0:e;if(h===l?(-2147483648^g)>(-2147483648^k):h>l)return c;h=g>>31;k=-1+d|0;l=-1!==k?e:-1+e|0;if(h===l?(-2147483648^\ng)<(-2147483648^k):h<l)return-c|0;a=$M(a);b=$M(b);if(0>e)c=fi(),a=Ki(a,Pi(c,new ma(-d|0,0!==d?~e:-e|0)));else if(0===e?0!==d:0<e)b=Ki(b,Pi(fi(),new ma(d,e)));return fM(a,b)}return c<d?-1:1}f=mr.prototype;f.i=function(a){if(a instanceof mr&&a.xb===this.xb){if(64>this.$h){a=a.Bg;var b=this.Bg;return a.W===b.W&&a.Y===b.Y}return this.bs.i(a.bs)}return!1};\nf.B=function(){if(0===this.lq)if(64>this.$h){this.lq=this.Bg.W;var a=this.Bg.Y;this.lq=Math.imul(33,this.lq)+a|0;this.lq=Math.imul(17,this.lq)+this.xb|0}else this.lq=Math.imul(17,this.bs.B())+this.xb|0;return this.lq};\nf.u=function(){if(null!==this.pu)return this.pu;if(32>this.$h)return this.pu=waa(bi(),this.Bg,this.xb);var a=$M(this);a=Vh(bi(),a);if(0===this.xb)return a;var b=0>$M(this).Ya?2:1,c=a.length,d=this.xb,e=d>>31,g=-d|0;e=0!==d?~e:-e|0;var h=c>>31;d=g+c|0;e=(-2147483648^d)<(-2147483648^g)?1+(e+h|0)|0:e+h|0;h=b>>31;g=d-b|0;d=(-2147483648^g)>(-2147483648^d)?-1+(e-h|0)|0:e-h|0;0<this.xb&&(-1===d?2147483642<=(-2147483648^g):-1<d)?0<=d?(hN(),b=c-this.xb|0,hN(),a=a.substring(0,b)+\".\"+a.substring(b)):(hN(),hN(),\nc=-1+b|0,hN(),a=a.substring(0,c)+\"0.\"+a.substring(c),b=1+b|0,c=hN().mM,g=-1-g|0,hN(),c=c.substring(0,g),a=\"\"+a.substring(0,b)+c+a.substring(b)):(a=(1<=(c-b|0)?(hN(),hN(),a.substring(0,b)+\".\"+a.substring(b)):a)+\"E\",a=((0===d?0!==g:0<d)?a+\"+\":a)+bG(xa(),g,d));return this.pu=a};function vW(a){if(0===a.xb||nW(a))return $M(a);if(0>a.xb){var b=$M(a),c=fi();a=a.xb;var d=a>>31;return Ki(b,Pi(c,new ma(-a|0,0!==a?~d:-d|0)))}b=$M(a);c=fi();a=a.xb;return GR(b,Pi(c,new ma(a,a>>31)))}\nfunction pW(a){if(0===a.xb||nW(a))return $M(a);if(0>a.xb){var b=$M(a),c=fi();a=a.xb;var d=a>>31;return Ki(b,Pi(c,new ma(-a|0,0!==a?~d:-d|0)))}if(a.xb>CR(a)||a.xb>wW($M(a)))throw new qb(\"Rounding necessary\");b=$M(a);c=fi();a=a.xb;a=DR(b,Pi(c,new ma(a,a>>31)));if(0!==a.a[1].Ya)throw new qb(\"Rounding necessary\");return a.a[0]}f.xl=function(){return-64>=this.xb||this.xb>CR(this)?aa:vW(this).xl()};f.Zi=function(){return-32>=this.xb||this.xb>CR(this)?0:vW(this).Zi()};\nf.pv=function(){return hM(jM(),$M(this)+\"e\"+(-this.xb|0))};f.Lp=function(){return aM(qa(),$M(this)+\"e\"+(-this.xb|0))};function $M(a){null===a.bs&&(a.bs=ri(Ph(),a.Bg));return a.bs}f.sl=function(a){return uW(this,a)};var iN=q({AT:0},!1,\"java.math.BigDecimal\",{AT:1,ur:1,g:1,l:1,nf:1});mr.prototype.$classData=iN;function xW(a){a.NC=-2;a.qu=0}\nfunction QR(a,b,c){xW(a);Ph();if(null===b)throw le();if(2>c||36<c)throw new ZL(\"Radix out of range\");if(\"\"===b)throw new ZL(\"Zero length BigInteger\");if(\"\"===b||\"+\"===b||\"-\"===b)throw new ZL(\"Zero length BigInteger\");var d=b.length;if(45===b.charCodeAt(0))var e=-1,g=1,h=-1+d|0;else 43===b.charCodeAt(0)?(g=e=1,h=-1+d|0):(e=1,g=0,h=d);e|=0;var k=g|0;g=h|0;for(h=k;h<d;){var l=b.charCodeAt(h);if(43===l||45===l)throw new ZL(\"Illegal embedded sign character\");h=1+h|0}h=bi().uH.a[c];l=pb(g,h);var m=Bb(g,\nh);0!==m&&(l=1+l|0);g=new Xc(l);l=bi().tH.a[-2+c|0];var n=0;for(m=k+(0===m?h:m)|0;k<d;){var r=TH(UH(),b.substring(k,m),c);fi();k=Fi(g,g,n,l);vi();var v=g,x=n,A=r;for(r=0;0!==A&&r<x;){var B=A;A=B+v.a[r]|0;B=(-2147483648^A)<(-2147483648^B)?1:0;v.a[r]=A;A=B;r=1+r|0}k=k+A|0;g.a[n]=k;n=1+n|0;k=m;m=k+h|0}a.Ya=e;a.wb=n;a.Qa=g;Ih(a);return a}function eM(a){var b=new TM;QR(b,a,10);return b}function qi(a,b){var c=new TM;xW(c);c.Ya=a;c.wb=1;c.Qa=new Xc(new Int32Array([b]));return c}\nfunction Hh(a,b,c){var d=new TM;xW(d);d.Ya=a;d.wb=b;d.Qa=c;return d}function rN(a,b){var c=new TM;xW(c);c.Ya=a;a=b.Y;0===a?(c.wb=1,c.Qa=new Xc(new Int32Array([b.W]))):(c.wb=2,c.Qa=new Xc(new Int32Array([b.W,a])));return c}function TM(){this.Qa=null;this.qu=this.NC=this.Ya=this.wb=0}TM.prototype=new wM;TM.prototype.constructor=TM;function VM(a){return 0>a.Ya?Hh(1,a.wb,a.Qa):a}function fM(a,b){return a.Ya>b.Ya?1:a.Ya<b.Ya?-1:a.wb>b.wb?a.Ya:a.wb<b.wb?-b.Ya|0:Math.imul(a.Ya,si(vi(),a.Qa,b.Qa,a.wb))}\nfunction GR(a,b){if(0===b.Ya)throw new qb(\"BigInteger divide by zero\");var c=b.Ya;if(1===b.wb&&1===b.Qa.a[0])return 0<b.Ya?a:ui(a);var d=a.Ya,e=a.wb,g=b.wb;if(2===(e+g|0))return a=a.Qa.a[0],b=b.Qa.a[0],e=xa(),b=$h(e,a,0,b,0),a=e.Qc,d!==c&&(c=b,d=a,b=-c|0,a=0!==c?~d:-d|0),ri(Ph(),new ma(b,a));var h=e!==g?e>g?1:-1:si(vi(),a.Qa,b.Qa,e);if(0===h)return d===c?Ph().Ew:Ph().MC;if(-1===h)return Ph().nq;h=1+(e-g|0)|0;var k=new Xc(h);c=d===c?1:-1;1===g?gi(ei(),k,a.Qa,e,b.Qa.a[0]):di(ei(),k,h,a.Qa,e,b.Qa,g);\nc=Hh(c,h,k);Ih(c);return c}function DR(a,b){a=tW(a,b);return new (md(Ji).Ia)([a.nM,a.oM])}\nfunction tW(a,b){var c=b.Ya;if(0===c)throw new qb(\"BigInteger divide by zero\");var d=b.wb;b=b.Qa;if(1===d){ei();b=b.a[0];var e=a.Qa,g=a.wb;d=a.Ya;1===g?(e=e.a[0],a=0===b?pb(0,0):+(e>>>0)/+(b>>>0)|0,g=0,b=0===b?Bb(0,0):+(e>>>0)%+(b>>>0)|0,e=0,d!==c&&(c=a,a=-c|0,g=0!==c?~g:-g|0),0>d&&(c=b,d=e,b=-c|0,e=0!==c?~d:-d|0),c=new uh(ri(Ph(),new ma(a,g)),ri(Ph(),new ma(b,e)))):(c=d===c?1:-1,a=new Xc(g),b=gi(0,a,e,g,b),b=new Xc(new Int32Array([b])),c=Hh(c,g,a),d=Hh(d,1,b),Ih(c),Ih(d),c=new uh(c,d));return c}g=\na.Qa;e=a.wb;if(0>(e!==d?e>d?1:-1:si(vi(),g,b,e)))return new uh(Ph().nq,a);a=a.Ya;var h=1+(e-d|0)|0;c=a===c?1:-1;var k=new Xc(h);b=di(ei(),k,h,g,e,b,d);c=Hh(c,h,k);d=Hh(a,d,b);Ih(c);Ih(d);return new uh(c,d)}f=TM.prototype;f.i=function(a){if(a instanceof TM){var b;if(b=this.Ya===a.Ya&&this.wb===a.wb)a:{for(b=0;b!==this.wb;){if(this.Qa.a[b]!==a.Qa.a[b]){b=!1;break a}b=1+b|0}b=!0}a=b}else a=!1;return a};\nfunction wW(a){if(0===a.Ya)return-1;var b=zh(a);a=a.Qa.a[b];return(b<<5)+(0===a?32:31-Math.clz32(a&(-a|0))|0)|0}f.B=function(){if(0===this.qu){for(var a=this.wb,b=0;b<a;){var c=b;this.qu=Math.imul(33,this.qu)+this.Qa.a[c]|0;b=1+b|0}this.qu=Math.imul(this.qu,this.Ya)}return this.qu};f.Zi=function(){return Math.imul(this.Ya,this.Qa.a[0])};\nf.xl=function(){if(1<this.wb)var a=this.Qa.a[0],b=this.Qa.a[1];else a=this.Qa.a[0],b=0;var c=this.Ya,d=c>>31,e=65535&c,g=c>>>16|0,h=65535&a,k=a>>>16|0,l=Math.imul(e,h);h=Math.imul(g,h);var m=Math.imul(e,k);e=l+((h+m|0)<<16)|0;l=(l>>>16|0)+m|0;b=(((Math.imul(c,b)+Math.imul(d,a)|0)+Math.imul(g,k)|0)+(l>>>16|0)|0)+(((65535&l)+h|0)>>>16|0)|0;return new ma(e,b)};function Ki(a,b){return 0===b.Ya||0===a.Ya?Ph().nq:Mi(fi(),a,b)}function ui(a){return 0===a.Ya?a:Hh(-a.Ya|0,a.wb,a.Qa)}\nfunction Qi(a,b){if(0>b)throw new qb(\"Negative exponent\");if(0===b)return Ph().Ew;if(1===b||a.i(Ph().Ew)||a.i(Ph().nq))return a;if(ER(a,0)){fi();for(var c=Ph().Ew,d=a;1<b;)a=0!==(1&b)?Ki(c,d):c,1===d.wb?d=Ki(d,d):(c=new Xc(d.wb<<1),c=Li(d.Qa,d.wb,c),d=new TM,xW(d),0===c.a.length?(d.Ya=0,d.wb=1,d.Qa=new Xc(new Int32Array([0]))):(d.Ya=1,d.wb=c.a.length,d.Qa=c,Ih(d))),b>>=1,c=a;return Ki(c,d)}for(c=1;!ER(a,c);)c=1+c|0;d=Ph();var e=Math.imul(c,b);if(e<d.sH.a.length)d=d.sH.a[e];else{d=e>>5;e&=31;var g=\nnew Xc(1+d|0);g.a[d]=1<<e;d=Hh(1,1+d|0,g)}return Ki(d,Qi(Ni(a,c),b))}function Oi(a,b){return 0===b||0===a.Ya?a:0<b?Fh(Sh(),a,b):Oh(Sh(),a,-b|0)}function Ni(a,b){return 0===b||0===a.Ya?a:0<b?Oh(Sh(),a,b):Fh(Sh(),a,-b|0)}function ER(a,b){var c=b>>5;if(0===b)return 0!==(1&a.Qa.a[0]);if(0>b)throw new qb(\"Negative bit address\");if(c>=a.wb)return 0>a.Ya;if(0>a.Ya&&c<zh(a))return!1;var d=a.Qa.a[c];0>a.Ya&&(d=zh(a)===c?-d|0:~d);return 0!==(d&1<<(31&b))}f.u=function(){return Vh(bi(),this)};\nfunction Ih(a){for(;;){if(0<a.wb&&(a.wb=-1+a.wb|0,0===a.Qa.a[a.wb]))continue;break}0===a.Qa.a[a.wb]&&(a.Ya=0);a.wb=1+a.wb|0}function zh(a){if(-2===a.NC){if(0===a.Ya)var b=-1;else for(b=0;0===a.Qa.a[b];)b=1+b|0;a.NC=b}return a.NC}f.sl=function(a){return fM(this,a)};var Ji=q({CT:0},!1,\"java.math.BigInteger\",{CT:1,ur:1,g:1,l:1,nf:1});TM.prototype.$classData=Ji;function uN(a,b){this.yQ=a;this.NF=b}uN.prototype=new uS;uN.prototype.constructor=uN;\nuN.prototype.$classData=q({MT:0},!1,\"java.math.RoundingMode\",{MT:1,Yaa:1,g:1,nf:1,l:1});function EM(a,b){null===a.wv?a.Gt=\"\"+a.Gt+b:yW(a,[b])}function zW(a,b,c){null===a.wv?a.Gt=\"\"+a.Gt+b+c:yW(a,[b,c])}function AW(a,b,c,d){null===a.wv?a.Gt=a.Gt+(\"\"+b+c)+d:yW(a,[b,c,d])}function yW(a,b){try{for(var c=b.length|0,d=0;d!==c;)a.wv.uJ(b[d]),d=1+d|0}catch(e){throw e;}}function HM(a){return void 0!==a?(a=+parseInt(a,10),2147483647>=a?Eb(a):-2):-1}\nfunction BW(a){return(0!==(1&a)?\"-\":\"\")+(0!==(2&a)?\"#\":\"\")+(0!==(4&a)?\"+\":\"\")+(0!==(8&a)?\" \":\"\")+(0!==(16&a)?\"0\":\"\")+(0!==(32&a)?\",\":\"\")+(0!==(64&a)?\"(\":\"\")+(0!==(128&a)?\"\\x3c\":\"\")}function CW(a,b,c){var d=Wj(a,1+b|0);a=d.Ft?\"-\":\"\";var e=d.wr,g=-1+e.length|0,h=b-g|0;b=e.substring(0,1);e=\"\"+e.substring(1)+Sj(Tj(),h);d=g-d.vr|0;g=\"\"+(0>d?-d|0:d);return a+(\"\"!==e||c?b+\".\"+e:b)+\"e\"+(0>d?\"-\":\"+\")+(1===g.length?\"0\"+g:g)}\nfunction DW(a,b,c){var d=Uj(a,(a.wr.length+b|0)-a.vr|0);Tj();if(!(\"0\"===d.wr||d.vr<=b))throw new Yj(\"roundAtPos returned a non-zero value with a scale too large\");d=\"0\"===d.wr||d.vr===b?d:new Vj(a.Ft,\"\"+d.wr+Sj(Tj(),b-d.vr|0),b);a=d.Ft?\"-\":\"\";d=d.wr;var e=d.length,g=1+b|0;d=e>=g?d:\"\"+Sj(Tj(),g-e|0)+d;e=d.length-b|0;a+=d.substring(0,e);return 0!==b||c?a+\".\"+d.substring(e):a}function QM(a,b,c,d,e,g){b=0>e||e>=g.length?g:g.substring(0,e);b=0!==(256&c)?b.toUpperCase():b;NM(a,c,d,b)}\nfunction YM(a,b,c,d){NM(a,b,c,XM(b,d!==d?\"NaN\":0<d?0!==(4&b)?\"+Infinity\":0!==(8&b)?\" Infinity\":\"Infinity\":0!==(64&b)?\"(Infinity)\":\"-Infinity\"))}\nfunction UM(a,b,c,d,e){if(d.length>=c&&0===(110&b))b=XM(b,d),EM(a,b);else if(0===(126&b))NM(a,b,c,XM(b,d));else{if(45!==d.charCodeAt(0))var g=0!==(4&b)?\"+\":0!==(8&b)?\" \":\"\";else 0!==(64&b)?(d=d.substring(1)+\")\",g=\"(\"):(d=d.substring(1),g=\"-\");e=\"\"+g+e;if(0!==(32&b)){var h=d.length;for(g=0;;){if(g!==h){var k=d.charCodeAt(g);k=48<=k&&57>=k}else k=!1;if(k)g=1+g|0;else break}g=-3+g|0;if(!(0>=g)){for(h=d.substring(g);3<g;)k=-3+g|0,h=d.substring(k,g)+\",\"+h,g=k;d=d.substring(0,g)+\",\"+h}}d=XM(b,d);WM(a,0,\nb,c,e,d)}}function XM(a,b){return 0!==(256&a)?b.toUpperCase():b}function NM(a,b,c,d){var e=d.length;e>=c?EM(a,d):0!==(1&b)?zW(a,d,EW(\" \",c-e|0)):zW(a,EW(\" \",c-e|0),d)}function WM(a,b,c,d,e,g){b=e.length+g.length|0;b>=d?zW(a,e,g):0!==(16&c)?AW(a,e,EW(\"0\",d-b|0),g):0!==(1&c)?AW(a,e,g,EW(\" \",d-b|0)):AW(a,EW(\" \",d-b|0),e,g)}function EW(a,b){for(var c=\"\",d=0;d!==b;)c=\"\"+c+a,d=1+d|0;return c}function FM(a){throw new FW(String.fromCharCode(a));}function JM(a){throw new GW(a);}\nfunction ZM(a,b,c,d,e,g){var h=0!==(2&c);d=0<=d?d:6;switch(e){case 101:h=CW(b,d,h);break;case 102:h=DW(b,d,h);break;default:e=0===d?1:d,b=Wj(b,e),d=(-1+b.wr.length|0)-b.vr|0,-4<=d&&d<e?(e=-1+(e-d|0)|0,h=DW(b,0>e?0:e,h)):h=CW(b,-1+e|0,h)}UM(a,c,g,h,\"\")}function BM(){this.Gt=this.T1=this.wv=null;this.gK=!1}BM.prototype=new p;BM.prototype.constructor=BM;BM.prototype.u=function(){if(this.gK)throw new DM;return null===this.wv?this.Gt:this.wv.u()};function KM(a){throw new HW(BW(a));}\nfunction MM(a,b,c){throw new IW(BW(b&c),a);}function RM(a,b){throw new JW(a,ca(b));}BM.prototype.$classData=q({O1:0},!1,\"java.util.Formatter\",{O1:1,g:1,yT:1,R0:1,zT:1});function KW(){}KW.prototype=new p;KW.prototype.constructor=KW;KW.prototype.Da=function(a,b){return(a|0)-(b|0)|0};KW.prototype.Qo=function(a,b,c){a.a[b]=c|0};KW.prototype.Wj=function(a,b){return a.a[b]};KW.prototype.$classData=q({y2:0},!1,\"java.util.internal.GenericArrayOps$ByteArrayOps$\",{y2:1,g:1,zB:1,XF:1,Ji:1});var LW;\nfunction gj(){LW||(LW=new KW);return LW}function MW(){}MW.prototype=new p;MW.prototype.constructor=MW;MW.prototype.Da=function(a,b){return Ea(a)-Ea(b)|0};MW.prototype.Qo=function(a,b,c){a.a[b]=Ea(c)};MW.prototype.Wj=function(a,b){return hc(a.a[b])};MW.prototype.$classData=q({z2:0},!1,\"java.util.internal.GenericArrayOps$CharArrayOps$\",{z2:1,g:1,zB:1,XF:1,Ji:1});var NW;function ej(){NW||(NW=new MW);return NW}function OW(){}OW.prototype=new p;OW.prototype.constructor=OW;\nOW.prototype.Da=function(a,b){a|=0;b|=0;return a===b?0:a<b?-1:1};OW.prototype.Qo=function(a,b,c){a.a[b]=c|0};OW.prototype.Wj=function(a,b){return a.a[b]};OW.prototype.$classData=q({A2:0},!1,\"java.util.internal.GenericArrayOps$IntArrayOps$\",{A2:1,g:1,zB:1,XF:1,Ji:1});var PW;function Ui(){PW||(PW=new OW);return PW}function QW(){}QW.prototype=new p;QW.prototype.constructor=QW;QW.prototype.Da=function(a,b){var c=Za(a);a=c.W;c=c.Y;var d=Za(b);b=d.W;d=d.Y;return ua(xa(),a,c,b,d)};\nQW.prototype.Qo=function(a,b,c){c=Za(c);a.a[b]=new ma(c.W,c.Y)};QW.prototype.Wj=function(a,b){return a.a[b]};QW.prototype.$classData=q({B2:0},!1,\"java.util.internal.GenericArrayOps$LongArrayOps$\",{B2:1,g:1,zB:1,XF:1,Ji:1});var RW;function aj(){RW||(RW=new QW);return RW}function SW(){}SW.prototype=new p;SW.prototype.constructor=SW;SW.prototype.Da=function(a,b){return(a|0)-(b|0)|0};SW.prototype.Qo=function(a,b,c){a.a[b]=c|0};SW.prototype.Wj=function(a,b){return a.a[b]};\nSW.prototype.$classData=q({D2:0},!1,\"java.util.internal.GenericArrayOps$ShortArrayOps$\",{D2:1,g:1,zB:1,XF:1,Ji:1});var TW;function cj(){TW||(TW=new SW);return TW}function wea(a,b,c){jr();var d=new Te(new Ue(J(new K,[\"\",\" `\",\"` does not contain member `\",\"`\"])));Xe();Q();var e=b.Ab.fd().ld;e=We(0,Nu(0,e));Xe();b=[e,We(0,b.Ab.Cf.x),We(Xe(),c.x)];d=Ye(d,J(new K,b));c=c.A();c=G(new H,d,c);d=O().c;return kr(0,new z(c,d),a.$c,lu())}\nvar xea=function UW(a,b,c,d,e,g,h,k,l){for(;;){if(b.Ea()<=c)return b;var n=!1,r=null,v=b;if(v instanceof cC)r=v,b=r.Fg,r=r.Sf,d?(b=r,d=!0):d=!1;else{if(v instanceof cv)return b=v,r=b.ac,new cv(a,UW(a,b.Nb,c,!d,e,g,h,k,l),UW(a,r,c,d,e,g,h,k,l),b.Mj);if(v instanceof LA)return b=v,r=b.jc,new LA(a,b.tc,UW(a,b.ic,c,d,e,g,h,k,l),UW(a,r,c,d,e,g,h,k,l),b.KE);if(v instanceof Qv)return b=v,r=b.Ba,v=a,lv(),new Qv(v,ry(0,r,new y(((C,D,F,I,M,N,P,T)=>Y=>{var Z=Y.Va,S=Y.Oa;S.b()?S=R():(S=S.o(),S=new L(UW(C,S,D,\n!F,I,M,N,P,T)));return new Uw(Z,S,UW(C,Y.ra,D,F,I,M,N,P,T),Y.Pd)})(a,c,d,e,g,h,k,l))),b.Nj);if(v instanceof zv)return b=v,r=b.Yb,v=a,lv(),new zv(v,ry(0,r,new y(((C,D,F,I,M,N,P,T)=>Y=>{var Z=Y.Va,S=Y.Oa;S.b()?S=R():(S=S.o(),S=new L(UW(C,S,D,!F,I,M,N,P,T)));return new Uw(Z,S,UW(C,Y.ra,D,F,I,M,N,P,T),Y.Pd)})(a,c,d,e,g,h,k,l))),b.Nq);if(v instanceof Sv){b=v;r=b.Fd;n=v=a;var x=d,A=r.Va,B=r.Oa;B.b()?n=R():(B=B.o(),n=new L(UW(n,B,c,!x,e,g,h,k,l)));return new Sv(v,new Uw(A,n,UW(a,r.ra,c,d,e,g,h,k,l),r.Pd),\nb.Fx)}if(v instanceof Tv)return b=v,r=b.kf,new Tv(a,UW(a,b.Ic,c,d,e,g,h,k,l),r,b.vp);if(v instanceof lx&&(n=!0,r=v,iC(a),x=r.Sb,!x.b()))return d=x.o(),b=G(new H,r,!0),h.Se(b,new U(((C,D,F,I,M,N,P,T,Y)=>()=>{var Z=D.ji;t();var S=new L(D),ea=D.kg,ia=O().c,X=O().c;Z=new lx(C,F,ia,X,S,ea,!1,Z);S=G(new H,D,!0);S=G(new H,S,Z);I.$(S);ea=UW(C,M,F,!0,N,P,I,T,Y);S=UW(C,M,F,!1,N,P,I,T,Y);Pe(new E(ea),S)?wy(Z,(t(),new L(ea))):(up(tp(),vy(Z).b()),up(tp(),rA(Z).b()),ia=O().c,IA(Z,new z(ea,ia)),ea=O().c,KA(Z,new z(S,\nea)));return Z})(a,r,c,h,d,e,g,k,l)));if(n&&r.Xa>e){d=!h.L(G(new H,r,!1));b=r;if(!d)throw new Yj(\"assertion failed: \"+G(new H,b,h));if(vy(r).b()&&rA(r).b())return r;d=G(new H,r,!0);return h.Se(d,new U(((C,D,F,I,M,N,P,T)=>()=>{var Y=D.ji;t();var Z=new L(D),S=D.kg,ea=O().c,ia=O().c;Y=new lx(C,D.Xa,ea,ia,Z,S,!1,Y);Z=G(new H,D,!0);Z=G(new H,Z,Y);F.$(Z);ia=vy(D);Z=(sa=>Ja=>UW(sa,Ja,I,!0,M,N,F,P,T))(C);if(ia===u())Z=u();else{S=ia.e();ea=S=new z(Z(S),u());for(ia=ia.f();ia!==u();){var X=ia.e();X=new z(Z(X),\nu());ea=ea.p=X;ia=ia.f()}Z=S}IA(Y,Z);ia=rA(D);Z=(sa=>Ja=>UW(sa,Ja,I,!1,M,N,F,P,T))(C);if(ia===u())Z=u();else{S=ia.e();ea=S=new z(Z(S),u());for(ia=ia.f();ia!==u();)X=ia.e(),X=new z(Z(X),u()),ea=ea.p=X,ia=ia.f();Z=S}KA(Y,Z);return Y})(a,r,h,c,e,g,k,l)))}if(v instanceof Wv)return b=v,sB(b,new y(((C,D,F,I,M,N,P,T)=>Y=>UW(C,Y,D,F,I,M,N,P,T))(a,c,d,e,g,h,k,l)),new y(((C,D,F,I,M,N,P,T)=>Y=>UW(C,Y,D,!F,I,M,N,P,T))(a,c,d,e,g,h,k,l)),new y(((C,D,F,I,M,N,P,T)=>Y=>UW(C,Y,D,F,I,M,N,P,T))(a,c,d,e,g,h,k,l)),b.Uu);\nif(n)return b=G(new H,r,d),h.Se(b,new U(((C,D,F,I,M,N,P,T,Y)=>()=>{var Z=D.ji;t();var S=new L(D),ea=D.kg,ia=O().c,X=O().c;Z=new lx(C,F,ia,X,S,ea,!1,Z);S=G(new H,D,M);S=G(new H,S,Z);I.$(S);if(M){S=rA(D);KA(D,new z(Z,S));X=vy(D);S=(Ja=>Xa=>UW(Ja,Xa,F,M,N,P,I,T,Y))(C);if(X===u())S=u();else{ea=X.e();ia=ea=new z(S(ea),u());for(X=X.f();X!==u();){var sa=X.e();sa=new z(S(sa),u());ia=ia.p=sa;X=X.f()}S=ea}IA(Z,S)}else{S=vy(D);IA(D,new z(Z,S));X=rA(D);S=(Ja=>Xa=>UW(Ja,Xa,F,M,N,P,I,T,Y))(C);if(X===u())S=u();\nelse{ea=X.e();ia=ea=new z(S(ea),u());for(X=X.f();X!==u();)sa=X.e(),sa=new z(S(sa),u()),ia=ia.p=sa,X=X.f();S=ea}KA(Z,S)}return Z})(a,r,c,h,d,e,g,k,l)));if(v instanceof MA)return b=v,new MA(a,UW(a,b.Fc,c,!d,e,g,h,k,l),b.rA);if(v instanceof FA)return v;if(v instanceof OA)return b=v,new OA(a,UW(a,b.Hi,c,d,e,g,h,k,l),b.NE);if(v instanceof ZB&&(r=v,$B(a),t(),r=r.mc(),r=new L(r),!r.b())){b=r.k;continue}if(v instanceof mx){r=v;n=r.hi;if(r.Tu>e){if(n=UW(a,n,c,d,e,g,h,k,l),n instanceof lx)return new mx(a,n,\nr.et)}else if(r.Tu>c)return new YB(a,!d,r,jx(new kx,r.et.Wu,r.et.Ga,\"extruded type variable reference\",r.et.go,r.et.Zm),l);xm(\"Program reached and unexpected state.\")}if(v instanceof Mu||v instanceof nC||v instanceof YB)return b;if(v instanceof fw)return b=v,r=b.qb,v=a,t(),new fw(v,r,bw(b,new L(d),new fn(((C,D,F,I,M,N,P)=>(T,Y)=>{T=G(new H,T,Y);Y=T.y;var Z=T.w;if(t().d===Y)return dw(cw(C),UW(C,Z,D,!1,F,I,M,N,P),UW(C,Z,D,!0,F,I,M,N,P),ew(cw(C)),I);Y=T.y;Z=T.w;if(Y instanceof L)return UW(C,Z,D,!!Y.k,\nF,I,M,N,P);throw new w(T);})(a,c,e,g,h,k,l)),g),b.Xl);if(v instanceof Qx)return b=v,r=b.de,new Qx(a,r,UW(a,b.Re,c,d,e<r?e:r,g,h,k,l));if(v instanceof eC){b=v;A=b.Lj;b=b.kj;r=a;v=((C,D,F,I,M,N,P)=>T=>{if(null!==T){var Y=T.j();T=UW(C,T.h(),D,!0,F,I,M,N,P);Y=UW(C,Y,D,!1,F,I,M,N,P);return G(new H,T,Y)}throw new w(T);})(a,c,e,g,h,k,l);if(A===u())v=u();else{n=A.e();x=n=new z(v(n),u());for(A=A.f();A!==u();)B=A.e(),B=new z(v(B),u()),x=x.p=B,A=A.f();v=n}return new eC(r,v,UW(a,b,c,d,e,g,h,k,l))}if(v instanceof\nJv)return VW(v,new y(((C,D,F,I,M,N,P,T)=>Y=>UW(C,Y,D,!F,I,M,N,P,T))(a,c,d,e,g,h,k,l)),new y(((C,D,F,I,M,N,P,T)=>Y=>UW(C,Y,D,F,I,M,N,P,T))(a,c,d,e,g,h,k,l)));throw new w(v);}}};\nfunction WW(a,b,c,d,e){var g=!1,h=null,k=b.U(c.x);if(k instanceof L&&(g=!0,h=k,b=h.k,b instanceof bx))return rx(b.Mb)&&(e=new Te(new Ue(J(new K,[\"Let binding '\",\"' cannot tbe accessed as a field\"]))),g=[We(Xe(),b.Ua())],e=Ye(e,J(new K,g)),c=c.A(),c=G(new H,e,c),e=Ye(new Te(new Ue(J(new K,[\"Use a `val` declaration to make it a field\"]))),u()),g=b.Mb.A(),e=G(new H,e,g),g=O().c,ay(a,new z(c,new z(e,g)),d)),d=b.Nn(),t(),b.Mb.Om.b()?(a=b.ma(),a=new Uw(d.q,R(),d,a)):a=new Uw(a,(t(),new L(d)),d,b.ma()),\nnew L(a);if(g&&(b=h.k,b instanceof Vw))return e||b.bo||(e=new Te(new Ue(J(new K,[\"Parameter '\",\"' cannot be accessed as a field\"]))),g=[We(Xe(),b.ij.Ua())],e=Ye(e,J(new K,g)),c=c.A(),c=G(new H,e,c),e=Ye(new Te(new Ue(J(new K,[\"Either make the parameter a `val` or access it through destructuring\"]))),u()),g=b.ij.A(),e=G(new H,e,g),g=O().c,ay(a,new z(c,new z(e,g)),d)),t(),new L(b.ig);if(g)return e=h.k,t(),b=new Te(new Ue(J(new K,[\"Access to \",\" member not yet supported\"]))),e=[We(Xe(),e.fd().ld)],d=\nLw(a,Ye(b,J(new K,e)),c.A(),d),a=V(a),a=new Uw(d.q,R(),d,a),new L(a);if(t().d===k)return t().d;throw new w(k);}function yea(a){if(0>=a.ab(15))return a;var b=xt(a,15),c=Ye(new Te(new Ue(J(new K,[\"......\"]))),u()),d=t().d;c=G(new H,c,d);d=Ye(new Te(new Ue(J(new K,[\"......\"]))),u());var e=t().d;d=G(new H,d,e);a=er(a).m().Mn(15);Od();a=Km(Pd(u(),a));return dl(new z(c,new z(d,a)),b)}\nfunction XW(a,b,c){var d=new Te(new Ue(J(new K,[\"Subtyping constraint of the form `\",\" \\x3c: \",\"`\"])));a=[wO(Xe(),AD(a,b)),wO(Xe(),CD(c,b))];return Ye(d,J(new K,a))}\nfunction YW(a,b,c,d,e,g,h,k,l,m,n){var r=(g.Ke-g.Zd|0)&(-1+g.ec.a.length|0);0<(250===r?0:250>r?-1:1)?(b=new Te(new Ue(J(new K,[\"\",\" exceeded recursion depth limit (\",\")\"]))),c=[XW(d,c,e),We(Xe(),\"250\")],b=Ye(b,J(new K,c)),h=G(new H,b,h.Ga),a.zA?a.$E?(Od(),b=Pd(u(),g),b=ZW(HF(new yt(b)),new y(v=>{if(null!==v){var x=v.h();v=v.j();var A=new Te(new Ue(J(new K,[\"while constraining:  \",\"\"]))),B=[We(Xe(),\"\"+x)];A=Ye(A,J(new K,B));x=x.ma().Ga;x=G(new H,A,x);A=new Te(new Ue(J(new K,[\"                       \\x3c!\\x3c  \",\n\"\"])));B=[We(Xe(),\"\"+v)];A=Ye(A,J(new K,B));v=v.ma().Ga;v=G(new H,A,v);A=O().c;return new z(x,new z(v,A))}throw new w(v);}))):(Od(),b=Pd(u(),g),b=yea(Qt(HF(new yt(b)),new y(v=>{var x=new Te(new Ue(J(new K,[\"while constraining:  \",\"\"])));v=[We(Xe(),v.h()+\"  \\x3c!\\x3c  \"+v.j())];x=Ye(x,J(new K,v));v=t().d;return G(new H,x,v)})))):(b=Ye(new Te(new Ue(J(new K,[\"Note: use flag `:ex` to see internal error info.\"]))),u()),g=t().d,b=G(new H,b,g),g=O().c,b=new z(b,g)),ay(a,new z(h,b),k),Es(l)):0>=m.ve?(g=\nnew Te(new Ue(J(new K,[\"\",\" took too many steps and ran out of fuel (\",\")\"]))),c=[XW(d,c,e),We(Xe(),\"\"+n)],g=Ye(g,J(new K,c)),h=G(new H,g,h.Ga),a.zA?(g=Qt(b.h(),new y(v=>{var x=new Te(new Ue(J(new K,[\" + \",\"\"]))),A=[We(Xe(),\"\"+v)];x=Ye(x,J(new K,A));v=v.ma().Ga;return G(new H,x,v)})),b=dl(Qt(b.j(),new y(v=>{var x=new Te(new Ue(J(new K,[\" - \",\"\"]))),A=[We(Xe(),\"\"+v)];x=Ye(x,J(new K,A));v=v.ma().Ga;return G(new H,x,v)})),g)):(b=Ye(new Te(new Ue(J(new K,[\"Note: use flag `:ex` to see internal error info.\"]))),\nu()),g=t().d,b=G(new H,b,g),g=O().c,b=new z(b,g)),ay(a,new z(h,b),k),Es(l)):m.ve=-1+m.ve|0}function $W(a,b,c,d){b=d+\".\"+b;a.F&&(a=ut(Q(),\"| \",a.r)+b,ff(gf(),a+\"\\n\"));c.n(b)}\nfunction aX(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A){c=c.cb;var B=a.qa;if(a.F){var C=ut(Q(),\"| \",a.r)+\"UNSTASHING...\";ff(gf(),C+\"\\n\")}a.r=1+a.r|0;try{c.Ca(new y(F=>{if(null!==F){var I=F.h();F=F.j();if(a.F){var M=ut(Q(),\"| \",a.r)+(\"where(\"+I+\") \")+xx(I);ff(gf(),M+\"\\n\")}for(F=F.m();F.s();)a:{if(M=F.t(),null!==M){var N=M.j();if(!0===M.Rc()){a.F&&(M=ut(Q(),\"| \",a.r)+(\"UNSTASH \"+N+\" \\x3c: \"+I+\" where \")+xx(N),ff(gf(),M+\"\\n\"));bX(a,N,I,!1,g,d,e,b,h,k,l,m,n,g,r,v,x,A,h);break a}}if(null!==M&&(N=M.j(),!1===M.Rc())){a.F&&\n(M=ut(Q(),\"| \",a.r)+(\"UNSTASH \"+I+\" \\x3c: \"+N+\" where \")+xx(N),ff(gf(),M+\"\\n\"));bX(a,I,N,!1,g,d,e,b,h,k,l,m,n,g,r,v,x,A,h);break a}throw new w(M);}}else throw new w(F);}));c.mg();var D=void 0}finally{a.r=-1+a.r|0}dx(new E(B),a.qa)&&a.F&&(D=\"\"+ut(Q(),\"| \",a.r)+B.n(D),ff(gf(),D+\"\\n\"))}\nfunction cX(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C){var D=a.Df,F=O().c;xB(a);xB(a);xB(a);var I=ap();b=TO(xB(a),D,F,b,!0,g,I);D=a.Df;F=O().c;xB(a);xB(a);xB(a);I=ap();var M=TO(xB(a),D,F,c,!1,g,I);if(qB(M)){c=1+g.da|0;D=Hw();F=Su();I=op().ga;D=D.Hd(new Uu(F,I));var N=new Iw(g.S,g.Ec,g.hc,g.Ed,c,g.Pc,g.Zc,g.Lb,g.yc,g.tb,g.$a,g.od,D),P=Xu().X();c=a.Df;D=JF(lv(),M.Qf,new y(S=>S.Kc(M.fb,!0,N,P)));var T=M.xe;if(T===u())F=u();else for(F=T.e(),I=F=new z(dX(F,M.fb,!0,N,P),u()),T=T.f();T!==u();){var Y=T.e();Y=new z(dX(Y,\nM.fb,!0,N,P),u());I=I.p=Y;T=T.f()}c=new RO(a,c,D,F);a.F&&(D=ut(Q(),\"| \",a.r)+(\"DNF BUMP TO LEVEL \"+N.da+\"  --\\x3e  \")+c,ff(gf(),D+\"\\n\"));eX(a,b,c,d,e,N,h,k,r,v,n,l,x,A,B,C,m);aX(a,g,N,d,e,k,m,n,r,v,l,x,A,B,C);a=N.cb;up(tp(),g.S.li||N.cb.b());if(!a.b()){d=g.S.qa;e=g.S;e.F&&(h=ut(Q(),\"| \",e.r)+\"UNSTASHING... (out)\",ff(gf(),h+\"\\n\"));e.r=1+e.r|0;try{a.Ca(new y(((S,ea)=>ia=>{if(null!==ia){var X=ia.h();for(ia=ia.j().m();ia.s();){var sa=ia.t();a:{if(null!==sa){var Ja=sa.j();if(!0===sa.Rc()){sa=Sw(S.S).ob;\nTw(S.S,Ja,X,k,l,ea,sa);break a}}if(null!==sa&&(Ja=sa.j(),!1===sa.Rc())){sa=Sw(S.S).ob;Tw(S.S,X,Ja,k,l,ea,sa);break a}throw new w(sa);}}}else throw new w(ia);})(g,g)));a.mg();var Z=void 0}finally{e.r=-1+e.r|0}dx(new E(d),e.qa)&&e.F&&(g=\"\"+ut(Q(),\"| \",e.r)+d.n(Z),ff(gf(),g+\"\\n\"))}}else eX(a,b,M,d,e,g,h,k,r,v,n,l,x,A,B,C,m)}\nfunction zea(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C,D,F,I){var M=tc();try{var N=sp(b);if(N instanceof L){var P=N.k,T=c.zf(!1),Y=(new PO(a,d,b.Ek(P),e,g)).zf(!1),Z=V(Y.q),S=NA(Y,Z,!1),ea=V(T.q);bX(a,P,dv(T,S,ea,!1),!0,h,k,l,m,n,r,v,x,A,h,B,C,D,F,I)}else if(t().d===N){var ia=g.m(),X=new Ef(ia,new y(bb=>{var Ia=a.Df,Ua=O().c;xB(a);xB(a);var pc=ap();return TO(xB(a),Ia,Ua,bb,!0,m,pc)})),sa=a.Df,Ja=O().c,Xa=e.zf(!1);xB(a);xB(a);for(var Fa=ap(),za=UO(c,TO(xB(a),sa,Ja,Xa,!1,m,Fa),m,!0);X.s();){c=za;var Qa=X.t();\nza=UO(c,Qa,m,!0)}X=za;if(a.F){var Ma=ut(Q(),\"| \",a.r)+(\"Consider \"+d+\" \\x3c: \")+X;ff(gf(),Ma+\"\\n\")}Ma=!1;za=null;if(d instanceof Ku){Ma=!0;za=d;var Ga=za.fc,ab=za.vd,Hb=za.be,bc=za.Me;if(Ga instanceof L){var yb=Ga.k;if(yb instanceof Tv){var tb=yb.Ic,eb=yb.kf;if(tb instanceof MA){var kb=tb.Fc;if(kb instanceof lx){var Rb=X.zf(!1),Gb=(new Ku(a,t().d,ab,Hb,bc)).zf(!1),vb=V(Gb.q),Tb=NA(Gb,vb,!1),Nb=V(Rb.q),ic=dv(Rb,Tb,Nb,!1),Va=iB(ic,eb),cb=V(Va.q);bX(a,NA(Va,cb,!1),kb,!0,h,k,l,m,n,r,v,x,A,h,B,C,D,F,I);\nreturn}}}}}if(Ma){var zb=za.fc,Ub=za.vd,jb=za.be,db=za.Me;if(zb instanceof L){var ub=zb.k;if(ub instanceof Tv){var Aa=ub.Ic,va=ub.kf;up(tp(),Aa instanceof lx);var Ra=X.zf(!1),rb=(new Ku(a,t().d,Ub,jb,db)).zf(!1),xb=V(rb.q),mc=NA(rb,xb,!1),Ha=V(Ra.q),Ka=dv(Ra,mc,Ha,!1);bX(a,Aa,iB(Ka,va),!0,h,k,l,m,n,r,v,x,A,h,B,C,D,F,I);return}}}Ga=bb=>{if(Ot(new E(bb.Of),lw(a))&&bb.Pf.b()&&bb.Af.b()&&mw(d,bb.Nf,m))throw a.F&&(bb=ut(Q(),\"| \",a.r)+(\"OK  \"+d+\" \\x3c: \")+bb,ff(gf(),bb+\"\\n\")),new fX(M);if(ey(b,bb.Af)?0:\n!hw(d,bb.Nf,!1,m,!1).b()){bb=bb.Of;if(d instanceof Ku){var Ia=d.vd;if(bb instanceof jw){a:{for(var Ua=bb.Xb;!Ua.b();){var pc=Ua.e();if(pc instanceof nC&&Ia.L(pc)){Ia=!0;break a}Ua=Ua.f()}Ia=!1}if(Ia)return!1}}return d instanceof Ku&&(Ia=d.fc,Ia instanceof L&&(Ia=Ia.k,Ia instanceof Mu&&bb instanceof jw))?!bb.Xb.L(Ia):!0}return!1};var Oa=X.xe;a:for(var Na;;)if(Oa.b()){Na=u();break}else{var Da=Oa.e(),ta=Oa.f();if(!1===!!Ga(Da))Oa=ta;else for(;;){if(ta.b())Na=Oa;else{var Ya=ta.e();if(!1!==!!Ga(Ya)){ta=\nta.f();continue}Ya=ta;var dc=new z(Oa.e(),u()),ka=Oa.f();for(ta=dc;ka!==Ya;){var ya=new z(ka.e(),u());ta=ta.p=ya;ka=ka.f()}var Sa=Ya.f();for(ka=Sa;!Sa.b();){var xc=Sa.e();if(!1===!!Ga(xc)){for(;ka!==Sa;){var Sb=new z(ka.e(),u());ta=ta.p=Sb;ka=ka.f()}ka=Sa.f()}Sa=Sa.f()}ka.b()||(ta.p=ka);Na=dc}break a}}if(a.F){var uc=ut(Q(),\"| \",a.r)+\"Possible: \"+Na;ff(gf(),uc+\"\\n\")}var Lb=O().c;if(Na===u())var lc=u();else{var Xb=Na.e(),ec=new z(Xb.zf(!1),u());dc=ec;for(var Ab=Na.f();Ab!==u();){var Ob=Ab.e(),fb=new z(Ob.zf(!1),\nu());dc=dc.p=fb;Ab=Ab.f()}lc=ec}var Wa=lw(a);gX(a,Lb,d,lc,Wa,k,l,n,m,\"Case\",v,x,r,A,h,B,C,D,F,I)}else throw new w(N);}catch(bb){if(bb instanceof Iq){if(h=bb,h.Qg!==M)throw h;}else throw bb;}}\nfunction eX(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C){var D=a.qa;if(a.F){var F=ut(Q(),\"| \",a.r)+(g.da+\". ARGH  \"+b+\"  \\x3c!  \")+c;ff(gf(),F+\"\\n\")}a.r=1+a.r|0;try{a.an=1+a.an|0;YW(a,d,g,l,m,n,r,k,v,x,A);At(tp(),!qB(c));c.Qf.b()||no();var I=Aea(b,g);if(null===I)throw new w(I);var M=I.h(),N=I.j(),P=a.qa;if(a.F){var T=ut(Q(),\"| \",a.r)+\"DNF DISCHARGE CONSTRAINTS\";ff(gf(),T+\"\\n\")}a.r=1+a.r|0;try{for(b=M;!b.b();){var Y=b.e();bX(a,Y.h(),Y.j(),!1,k,d,e,g,h,n,l,m,r,k,v,x,A,B,C);b=b.f()}var Z=void 0}finally{a.r=-1+\na.r|0}if(dx(new E(P),a.qa)&&a.F){var S=\"\"+ut(Q(),\"| \",a.r)+P.n(Z);ff(gf(),S+\"\\n\")}for(;!N.b();){var ea=N.e();if(null!==ea)zea(a,ea.Pf,c,ea.Nf,ea.Of,ea.Af,k,d,e,g,h,n,l,m,r,v,x,A,B,C);else throw new w(ea);N=N.f()}var ia=void 0}finally{a.r=-1+a.r|0}dx(new E(D),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+D.n(ia),ff(gf(),a+\"\\n\"))}function gX(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C,D,F,I){a.an=1+a.an|0;YW(a,g,l,n,r,v,x,A,B,C,D);Bea(a,b,c,d,e,g,h,l,k,m,A,x,v,n,r,B,C,D,F,I)}\nfunction Cea(a,b,c,d){a=a.m().nb(new U(()=>b.GC()));a=new Ef(a,new y(e=>{var g=V(e.q);return NA(e,g,!1)}));return kv(a,new U(()=>c.m())).nb(new U(()=>d.GC()))}function Dea(a,b,c,d,e){b=Cea(b,c,d,e);if(b.s()){if(!b.s())throw nv(\"empty.reduceLeft\");c=!0;for(d=null;b.s();)if(e=b.t(),c)d=e,c=!1;else{var g=V(d.q);d=dv(d,e,g,!1)}b=new L(d)}else b=R();return b.b()?a.ib:b.o()}\nfunction Eea(a,b,c,d){return a.m().nb(new U(()=>b.GC())).nb(new U(()=>{var e=c.m().nb(new U(()=>d.GC()));return new Ef(e,new y(g=>{var h=V(g.q);return NA(g,h,!1)}))}))}function Fea(a,b,c,d,e){b=Eea(c,d,b,e);if(b.s()){if(!b.s())throw nv(\"empty.reduceLeft\");c=!0;for(d=null;b.s();)if(e=b.t(),c)d=e,c=!1;else{var g=V(d.q);d=Pu(d,e,g,!1)}b=new L(d)}else b=R();return b.b()?a.La:b.o()}\nfunction Bea(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C,D,F,I){var M=tc();try{Lx(a,new U(()=>k.da+\". A  \"+c+\"  %  \"+b+\"  \\x3c!  \"+d+\"  %  \"+e),new U(()=>{var P=G(new H,b,d);a:{var T=P.y;if(T instanceof z){var Y=T.z,Z=T.p;if(Y instanceof lx){bX(a,Y,Dea(a,Z,c,d,e),ow(c)&&Z.ul(new y(Re=>JA(Re,k))),n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);break a}}var S=P.w;if(S instanceof z){var ea=S.z,ia=S.p;if(ea instanceof lx){bX(a,Fea(a,ia,b,c,e),ea,Gw(e)&&ia.ul(new y(Re=>Kv(Re,k))),n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);break a}}var X=P.y;\nif(X instanceof z){var sa=X.z,Ja=X.p;if(sa instanceof cC){gX(a,new z(sa.Sf,Ja),c,d,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var Xa=P.w;if(Xa instanceof z){var Fa=Xa.z,za=Xa.p;if(Fa instanceof cC){gX(a,b,c,new z(Fa.Fg,za),e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var Qa=P.y;if(Qa instanceof z){var Ma=Qa.z,Ga=Qa.p;if(Ma instanceof LA){var ab=Ma.ic,Hb=Ma.jc;if(!0===Ma.tc){$W(a,\"1\",new y(Re=>{gX(a,new z(ab,Ga),c,d,e,g,h,l,k,Re,x,A,v,r,n,B,C,D,F,I)}),m);$W(a,\"2\",new y(Re=>{gX(a,new z(Hb,Ga),c,d,e,g,h,\nl,k,Re,x,A,v,r,n,B,C,D,F,I)}),m);break a}}}var bc=P.w;if(bc instanceof z){var yb=bc.z,tb=bc.p;if(yb instanceof LA){var eb=yb.ic,kb=yb.jc;if(!1===yb.tc){$W(a,\"1\",new y(Re=>{gX(a,b,c,new z(eb,tb),e,g,h,l,k,Re,x,A,v,r,n,B,C,D,F,I)}),m);$W(a,\"2\",new y(Re=>{gX(a,b,c,new z(kb,tb),e,g,h,l,k,Re,x,A,v,r,n,B,C,D,F,I)}),m);break a}}}var Rb=P.w;if(Rb instanceof z){var Gb=Rb.z,vb=Rb.p;if(Gb instanceof LA){var Tb=Gb.ic,Nb=Gb.jc;if(!0===Gb.tc){gX(a,b,c,new z(Tb,new z(Nb,vb)),e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}}var ic=\nP.y;if(ic instanceof z){var Va=ic.z,cb=ic.p;if(Va instanceof LA){var zb=Va.ic,Ub=Va.jc;if(!1===Va.tc){gX(a,new z(zb,new z(Ub,cb)),c,d,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}}var jb=P.y;if(jb instanceof z){var db=jb.z,ub=jb.p;if(db instanceof ZB){$B(a);t();var Aa=db.mc(),va=new L(Aa);if(!va.b()){gX(a,new z(va.k,ub),c,d,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}}var Ra=P.w;if(Ra instanceof z){var rb=Ra.z,xb=Ra.p;if(rb instanceof ZB){$B(a);t();var mc=rb.mc(),Ha=new L(mc);if(!Ha.b()){gX(a,b,c,new z(Ha.k,\nxb),e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}}var Ka=P.y;if(Ka instanceof z){var Oa=Ka.z,Na=Ka.p;if(Oa instanceof MA){gX(a,Na,c,new z(Oa.Fc,d),e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var Da=P.w;if(Da instanceof z){var ta=Da.z,Ya=Da.p;if(ta instanceof MA){gX(a,new z(ta.Fc,b),c,Ya,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var dc=P.y;if(dc instanceof z){var ka=dc.z;if(ka instanceof FA&&!0===ka.Eh)break a}var ya=P.w;if(ya instanceof z){var Sa=ya.z;if(Sa instanceof FA&&!1===Sa.Eh)break a}var xc=P.y,\nSb=P.w;if(xc instanceof z){var uc=xc.z,Lb=xc.p;if(uc instanceof FA&&!1===uc.Eh){gX(a,Lb,c,Sb,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var lc=P.y,Xb=P.w;if(Xb instanceof z){var ec=Xb.z,Ab=Xb.p;if(ec instanceof FA&&!0===ec.Eh){gX(a,lc,c,Ab,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var Ob=P.y,fb=P.w;if(Ob instanceof z){var Wa=Ob.z,bb=Ob.p;if(Wa instanceof fw){var Ia=Zv(c,Wa,!0,k,!1),Ua=new U(()=>{throw new fX(M,(Nx(a,new U(()=>\"OK  \"+c+\" \\x26 \"+Wa+\"  \\x3d:\\x3d  \"+a.ib)),void 0));});gX(a,bb,Ia.b()?Es(Ua):\nIa.o(),fb,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var pc=P.y,sc=P.w;if(sc instanceof z){var Ba=sc.z,ob=sc.p;if(Ba instanceof fw){var nc=ww(e,Ba,!1,k),Ib=new U(()=>{throw new fX(M,(Nx(a,new U(()=>\"OK  \"+e+\" \\x26 \"+Ba+\"  \\x3d:\\x3d  \"+a.La)),void 0));});gX(a,pc,c,ob,nc.b()?Es(Ib):nc.o(),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var vc=P.y,Vb=P.w;if(vc instanceof z){var fc=vc.z,Bc=vc.p;if(fc instanceof hX){var Pb=yv(c,fc,!0,k,!0),Jb=new U(()=>{throw new fX(M,(Nx(a,new U(()=>\"OK  \"+c+\" \\x26 \"+fc+\"  \\x3d:\\x3d  \"+\na.ib)),void 0));});gX(a,Bc,Pb.b()?Es(Jb):Pb.o(),Vb,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var gc=P.y,Cb=P.w;if(Cb instanceof z){var cc=Cb.z,yc=Cb.p;if(cc instanceof hX){var Mc=zw(e,cc),qc=new U(()=>{throw new fX(M,(Nx(a,new U(()=>\"OK  \"+e+\" | \"+cc+\"  \\x3d:\\x3d  \"+a.La)),void 0));});gX(a,gc,c,yc,Mc.b()?Es(qc):Mc.o(),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var oc=P.y,Qc=P.w;if(oc instanceof z){var jc=oc.z,sb=oc.p;if(jc instanceof Qv){gX(a,sb,Xv(c,jc),Qc,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var Gc=\nP.w;if(Gc instanceof z){var Wb=Gc.z;if(Wb instanceof Qv){var Cc=Wb.Ba,Fc=O().c;if(null===Fc?null===Cc:Fc.i(Cc))break a}}var qd=P.y,Yb=P.w;if(Yb instanceof z){var Nc=Yb.z,ad=Yb.p;if(Nc instanceof Qv){var Uc=Nc.Ba;if(Uc instanceof z){var cd=Uc.z,kc=Uc.p,Vc=O().c;if(null===Vc?null===kc:Vc.i(kc)){var Hc=Aw(e,cd),rc=new U(()=>{throw new fX(M,(Nx(a,new U(()=>\"OK  \"+e+\" | \"+cd+\"  \\x3d:\\x3d  \"+a.La)),void 0));});gX(a,qd,c,ad,Hc.b()?Es(rc):Hc.o(),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}}}var sd=P.y,Kc=P.w;\nif(Kc instanceof z){var Qd=Kc.z,Ad=Kc.p;if(Qd instanceof Qv){var kd=Gea(Qd);gX(a,sd,c,new z(kd,Ad),e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break a}}var Hd=P.w;if(Hd instanceof z&&Hd.z instanceof Qx)var Rd=!0;else{var Bd=P.y;Rd=Bd instanceof z&&Bd.z instanceof Qx?!0:!1}Rd&&xm(\"Program reached and unexpected state.\");var ae=P.w;if(ae instanceof z&&ae.z instanceof eC)var dd=!0;else{var od=P.y;dd=od instanceof z&&od.z instanceof eC?!0:!1}dd&&xm(\"Program reached and unexpected state.\");var Ta=P.y,wb=P.w,$a=O().c;\nif(null===$a?null===Ta:$a.i(Ta))var wa=O().c,hb=null===wa?null===wb:wa.i(wb);else hb=!1;if(hb){var ra=G(new H,c,e);b:{var wc=ra.y,ac=ra.w;if(wc instanceof Ku){var Id=wc.fc;if(Id instanceof L){var ud=Id.k;if(ud instanceof Tv){var be=ud.Ic;if(lw(a)===ac){bX(a,be,a.ib,!0,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);break b}}}}c:{var re=ra.y;if(Vu(a)===re)var pe=!0;else{var bd=ra.y;if(bd instanceof Ku){var Rc=bd.fc,Wc=bd.vd,Wd=bd.be,zd=bd.Me;if(t().d===Rc&&null!==Wc&&Wc.b()&&null!==Wd){var Pa=Wd.Ba,Db=O().c;if((null===\nDb?null===Pa:Db.i(Pa))&&null!==zd&&zd.b()){pe=!0;break c}}}pe=!1}}if(pe)iX(a,t().d,g,k,r,n);else{var Oc=ra.y,Tc=ra.w;if(Oc instanceof Ku){var Sd=Oc.vd;if(Tc instanceof jw){var Jc=Tc.Xb;if(ey(Sd,new y(Re=>Jc.L(Re))))break b}}var vd=ra.y;if(vd instanceof Ku){var hd=vd.fc,de=vd.vd,ye=vd.be,jf=vd.Me;if(!jf.b()){var af=new Ou(jf),pf=new Ef(af,new y(Re=>cD(Re,k,n)));Od();var kf=Pd(u(),pf),Be=sv(),Kd=Su(),ld=op().ga;gX(a,kf,new Ku(a,hd,de,ye,Be.Hd(new Uu(Kd,ld))),O().c,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break b}}var Jd=\nra.w;if(Jd instanceof jw){var Dd=Jd.Xb,Xd=Jd.mb,Yc=Jd.Dc;if(!Yc.b()){var Ce=O().c,te=new Ou(Yc),Ie=new Ef(te,new y(Re=>cD(Re,k,n)));Od();var Jf=Pd(u(),Ie),df=sv(),vg=Su(),wg=op().ga;gX(a,Ce,c,Jf,new jw(a,Dd,Xd,df.Hd(new Uu(vg,wg))),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break b}}var xg=ra.w;if(xg instanceof jw){var eg=xg.Xb,vh=xg.mb,fg=xg.Dc;if(vh instanceof L){var ih=vh.k;if(ih instanceof fe){var Ig=ih.aa;if(Ig instanceof Jv){for(var Tf=new y(Re=>{var rj=O().c,ai=O().c;t();t();gX(a,rj,c,ai,new jw(a,eg,new L(new fe(Re)),\nfg),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I)}),Jg=Ig.gi;!Jg.b();)Tf.n(Jg.e()),Jg=Jg.f();break b}}}}var jh=ra.y;jh instanceof Ku&&(jh.Me.b()||xm(\"Program reached and unexpected state.\"));var yg=ra.w;yg instanceof jw&&(yg.Dc.b()||xm(\"Program reached and unexpected state.\"));c:{var gg=ra.w;if(lw(a)===gg)var Cf=!0;else{var Uf=ra.w;if(Uf instanceof jw){var $g=Uf.Xb,Ah=Uf.mb,Kg=O().c;if((null===Kg?null===$g:Kg.i($g))&&t().d===Ah){Cf=!0;break c}}Cf=!1}}if(Cf)iX(a,t().d,g,k,r,n);else{var Vf=ra.y,hg=ra.w;if(Vf instanceof\nKu){var zg=Vf.fc;if(zg instanceof L){var Lg=zg.k;if(Lg instanceof cv&&hg instanceof jw){var Mg=hg.mb;if(Mg instanceof L){var Wf=Mg.k;if(Wf instanceof fe){var Ng=Wf.aa;if(Ng instanceof cv){bX(a,Lg,Ng,!0,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);break b}}}}}}var Kf=ra.y,xf=ra.w;if(Kf instanceof Ku){var Og=Kf.fc,mi=Kf.vd,Ci=Kf.be,Xh=Kf.Me;if(Og instanceof L&&Og.k instanceof cv&&xf instanceof jw){gX(a,O().c,new Ku(a,t().d,mi,Ci,Xh),O().c,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break b}}var wh=ra.y,Bh=ra.w;if(wh instanceof\nKu){var ng=wh.fc;if(ng instanceof L&&ng.k instanceof Mu&&Bh instanceof jw&&Yca(new E(a.lP),Bh.Xb)){Nx(a,new U(()=>\"OK ~ magic Eql ~\"));break b}}var kh=ra.y,Kh=ra.w;if(kh instanceof Ku){var ni=kh.fc;if(ni instanceof L){var Lh=ni.k;if(Lh instanceof Mu){var lh=Lh.pd;if(lh instanceof Dl&&Kh instanceof jw){var Ch=Kh.mb;if(Ch instanceof L){var Dh=Ch.k;if(Dh instanceof Ud){var Yh=Dh.fa;if(null!==Yh){var ah=Yh.me,oi=Yh.Ne;if(null!==ah&&\"Eql#A\"===ah.x){if(lh instanceof Em||lh instanceof Fm){var mj=oi.Oa,wd=\nnew U(()=>a.La);bX(a,mj.b()?Es(wd):mj.o(),a.Ak,!1,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I)}else if(lh instanceof Dm){var ge=oi.Oa,De=new U(()=>a.La);bX(a,ge.b()?Es(De):ge.o(),a.Qj,!1,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I)}else if(lh instanceof Gm)iX(a,t().d,g,k,r,n);else throw new w(lh);break b}}}}}}}}var qf=ra.y,og=ra.w;if(qf instanceof Ku){var Xf=qf.fc,mh=qf.vd,Ag=qf.be;if(Xf instanceof L){var Bg=Xf.k;if(Bg instanceof Mu){var Eh=Bg.pd;if(Eh instanceof vl){var Pg=Eh.x;if(og instanceof jw){var Di=og.mb;if(Di instanceof\nL){var Mh=Di.k;if(Mh instanceof Ud){var pi=Mh.fa;if(null!==pi){var Xi=pi.me,Qg=pi.Ne;if(k.$a.L(Pg)){if(a.$c&&Nm(new E(Pg),\"Eql\")&&\"Eql#A\"===Xi.x){var nh=k.$a.n(Pg);if(px(nh).b()&&!a.cn.L(Pg)){var bh=new Te(new Ue(J(new K,[\"\",\" '\",\"' does not support equality comparison because it does not have a parameter list\"])));Xe();Q();var Mj=nh.Ab.fd().ld,Nj=We(0,Nu(0,Mj));Xe();var ie=[Nj,We(0,nh.Ab.Cf.x)];Lw(a,Ye(bh,J(new K,ie)),r.Ga,n)}for(var Ac=px(nh),Ve=new U(()=>O().c),Td=Ac.b()?Es(Ve):Ac.o(),lf=new y(Re=>\n{var rj=new U(()=>c.zf(!0));t();var ai=new L(Pg),rm=Ag.Ba;op();var Nn=pp(qp(),rm);ai=jX(a,rj,ai,new y(Au=>Nn.U(Au)),mh,Re.h(),k,n);rj=Qg.Oa;rm=new U(()=>{xm(\"Program reached and unexpected state.\")});rj=rj.b()?Es(rm):rj.o();Re=Re.h();rm=new Ep(\"Eql\");ai=ai.ra;var zu=O().c;ai=new fw(a,rm,new z(ai,zu),V(a));rm=V(a);ai=new Uw(ai.q,R(),ai,rm);Re=G(new H,Re,ai);ai=O().c;bX(a,rj,new Qv(a,new z(Re,ai),V(a)),!1,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I)}),Yi=Td;!Yi.b();)lf.n(Yi.e()),Yi=Yi.f()}else{var Jl=new U(()=>c.zf(!0));\nt();var ll=new L(Pg),Bj=Ag.Ba;op();var $k=pp(qp(),Bj),Zh=jX(a,Jl,ll,new y(Re=>$k.U(Re)),mh,Xi,k,n);bX(a,Zh.ra,Qg.ra,!1,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);kX(a,Qg,Zh,n,g,h,k,l,v,r,n,x,A,B,C,D,F,I)}break b}}}}}}}}}var Ei=ra.y,Yd=ra.w;if(Ei instanceof Ku){var bf=Ei.fc,rf=Ei.vd,Cg=Ei.be,nj=Ei.Me;if(bf instanceof L){var Jh=bf.k;if(Jh instanceof Mu&&Yd instanceof jw){var If=Yd.Xb,Hg=Yd.mb,He=Yd.Dc;Nx(a,new U(()=>\"class checking \"+Jh+\" \"+If));If.qo(new y(Re=>Pe(new E(Re.uo()),Jh.pd)?!0:(Ei.rE?Ei.qE:kw(Ei)).L(Re.uo())))?\nNx(a,new U(()=>\"OK  \"+Jh+\"  \\x3c:  \"+ze(If,\"\",\" | \",\"\"))):gX(a,O().c,new Ku(a,t().d,rf,Cg,nj),O().c,new jw(a,O().c,Hg,He),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);void 0;break b}}}var lj=ra.y,Wi=ra.w;if(lj instanceof Ku&&Wi instanceof iw){var Oj=O().c,mo=O().c,mm=O().c;t();t();var nm=new L(new Ud(Wi)),dq=sv(),Zd=Su(),sf=op().ga;gX(a,Oj,lj,mo,new jw(a,mm,nm,dq.Hd(new Uu(Zd,sf))),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I)}else{var oj=ra.y,al=ra.w;if(oj instanceof Ku){var Ll=oj.fc,Qm=oj.vd,Rm=oj.be;if(t().d===Ll&&al instanceof\njw){var hq=al.mb;if(hq instanceof L){var Bn=hq.k;if(Bn instanceof Ud){var hp=Bn.fa;if(null!==hp){var ru=hp.me,qr=hp.Ne;if(a.$c){var Xs=new U(()=>c.zf(!0)),rr=t().d,iq=Rm.Ba;op();var qo=pp(qp(),iq),qm=jX(a,Xs,rr,new y(Re=>qo.U(Re)),Qm,ru,k,n);bX(a,qm.ra,qr.ra,!1,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);kX(a,qr,qm,n,g,h,k,l,v,r,n,x,A,B,C,D,F,I);break b}}}}}}var jq=ra.y,pl=ra.w;if(jq instanceof Ku){var ro=jq.fc,Cn=jq.be;if(pl instanceof jw){var ip=pl.Xb,so=pl.mb,Dn=pl.Dc;if(so instanceof L){var sr=so.k;if(sr instanceof\nUd){var kq=sr.fa;if(null!==kq){var ql=kq.me,Ys=kq.Ne,Sm=lX(Cn.Ba,new y(Re=>Pe(new E(Re.h()),ql)));if(Sm instanceof L){var Nl=Sm.k;kX(a,Ys,Nl.j(),n,g,h,k,l,v,r,n,x,A,B,C,D,F,I);bX(a,Nl.j().ra,Ys.ra,!1,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I)}else if(t().d===Sm)c:{if(ro instanceof L){var jp=ro.k;if(jp instanceof Tv){var lq=jp.Ic;if(jp.kf.L(ql)){var mq=new jw(a,ip,t().d,Dn);bX(a,lq,mq.zf(!1),!0,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I)}else bX(a,lq,e.zf(!1),!0,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);break c}}iX(a,t().d,g,k,r,n)}else throw new w(Sm);\nbreak b}}}}}var Tm=ra.y,En=ra.w;if(Tm instanceof Ku){var to=Tm.fc,Fn=Tm.vd;if(t().d===to&&En instanceof jw){var nq=En.Xb,Um=En.mb;if(t().d===Um){Nx(a,new U(()=>\"Tag checking \"+Fn+\" \"+nq));nq.qo(new y(Re=>{var rj=Fn.m();rj=new xo(rj,new y(ai=>{if(ai instanceof nC){var rm=ai.rp;ai=ai.JI;ai=Qt((Od(),Pd(u(),ai)),new y(Nn=>new vl(Nn.V)));return new z(rm,ai)}return O().c}));return tea(rj,Re.uo())}))?Nx(a,new U(()=>\"OK \"+Fn+\" \\x3c: \"+nq)):iX(a,t().d,g,k,r,n);void 0;break b}}}var kp=ra.y,oq=ra.w;if(kp instanceof\nKu){var su=kp.fc;if(t().d===su&&oq instanceof jw){var Gn=oq.mb;if(Gn instanceof L){var ur=Gn.k;if(ur instanceof fe&&(ur.aa instanceof cv||ur.aa instanceof Vv)){iX(a,t().d,g,k,r,n);break b}}}}var In=ra.y,Zs=ra.w;if(In instanceof Ku){var $s=In.fc;if($s instanceof L){var pq=$s.k;if(pq instanceof zv&&Zs instanceof jw){var vr=Zs.mb;if(vr instanceof L){var Vm=vr.k;if(Vm instanceof fe){var Jn=Vm.aa;if(Jn instanceof zv){var wr=pq.Yb.K();if(Pe(new E(wr),Jn.Yb.K())){var at=pq.Yb,xr=op(),lp=at.Gb(xr.ga).j(),\nKn=Jn.Yb,qq=op(),yr=Kn.Gb(qq.ga).j();pH(new Wq(lp,lp,yr),new fn((Re,rj)=>{bX(a,Re.ra,rj.ra,!1,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);kX(a,rj,Re,n,g,h,k,l,v,r,n,x,A,B,C,D,F,I)}));break b}}}}}}}var rq=ra.y,sq=ra.w;if(rq instanceof Ku){var bt=rq.fc;if(bt instanceof L){var tq=bt.k;if(tq instanceof Vv&&sq instanceof jw){var zr=sq.mb;if(zr instanceof L){var ct=zr.k;if(ct instanceof fe){var Ar=ct.aa;if(Ar instanceof Sv){kX(a,Ar.Fd,tq.Zj(),n,g,h,k,l,v,r,n,x,A,B,C,D,F,I);bX(a,tq.Zj().ra,Ar.Fd.ra,!1,n,g,h,k,l,v,x,\nA,r,n,B,C,D,F,I);break b}}}}}}var uq=ra.y;if(uq instanceof Ku){var Br=uq.fc;if(Br instanceof L&&Br.k instanceof Vv){iX(a,t().d,g,k,r,n);break b}}var Ln=ra.y;if(Ln instanceof Ku){var vq=Ln.fc,Cr=Ln.vd,tu=Ln.be,uu=Ln.Me;if(vq instanceof L){var dt=vq.k;if(dt instanceof Jv){var vu=O().c;t();var Dr=mX(dt);gX(a,vu,new Ku(a,new L(Dr),Cr,tu,uu),O().c,e,g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break b}}}var uo=ra.y,Er=ra.w;if(uo instanceof Ku){var et=uo.fc;if(et instanceof L){var ft=et.k;if(ft instanceof Tv){var gt=\nft.Ic;if(Er instanceof jw){var Wm=Er.mb;var Fr=t().d===Wm?!0:Wm instanceof L&&Wm.k instanceof fe?!0:!1;if(Fr){bX(a,gt,e.zf(!1),!0,n,g,h,k,l,v,x,A,r,n,B,C,D,F,I);break b}}}}}var mp=ra.w;if(mp instanceof jw){var wu=mp.Xb,ht=mp.mb;if(ht instanceof L){var wq=ht.k;if(wq instanceof fe){var xq=wq.aa;if(xq instanceof Tv){var Gr=xq.Ic,xu=Qt(wu,new y(Re=>{var rj=V(Re.q);return NA(Re,rj,!1)})),yu=O().c;gX(a,xu,c,new z(Gr,yu),lw(a),g,h,l,k,m,x,A,v,r,n,B,C,D,F,I);break b}}}}throw new w(ra);}}}}}else throw new w(P);\n}}),a.qa)}catch(P){if(P instanceof Iq){var N=P;if(N.Qg!==M)throw N;}else throw P;}}\nfunction kX(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C,D){var F=G(new H,b.Oa,c.Oa);a:{var I=F.y,M=F.w;if(I instanceof L&&(I=I.k,M instanceof L)){bX(a,I,M.k,!1,d,e,g,h,k,l,r,v,m,n,x,A,B,C,D);break a}d=F.y;e=F.w;if(d instanceof L&&(d=d.k,R()===e)){Nx(a,new U(()=>\"RHS not mutable! in \"+b+\" \\x3c- \"+c));b.Pd.Ga.b()||c.Pd.Ga.b()?(t(),F=Ye(new Te(new Ue(J(new K,[\"cannot be reassigned\"]))),u()),F=new L(F)):(t(),F=Ye(new Te(new Ue(J(new K,[\"is not mutable\"]))),u()),F=new L(F));e=c.ra;e=ux(e.q,e,c.Pd);g=ux(d.q,d,b.Pd);\nk=O().c;e=new z(e,new z(g,k));g=V(a);d=ux(d.q,d,g);g=O().c;iX(a,F,G(new H,e,new z(d,g)),h,m,n);break a}a=F.y;h=F.w;R()===a&&h instanceof L?a=!0:(a=F.y,h=F.w,a=R()===a&&R()===h?!0:!1);if(!a)throw new w(F);}}\nfunction nX(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C,D,F,I,M){var N=xA(b,!0),P=Xu().X(),T=Hw(),Y=Su(),Z=op().ga;b=xea(a,b,c,d,e,m,P,T.Hd(new Uu(Y,Z)),g);N=xA(b,!0).wy(N);if(!N.b()){d=a.qa;a.F&&(e=ut(Q(),\"| \",a.r)+\"RECONSTRAINING TVs\",ff(gf(),e+\"\\n\"));a.r=1+a.r|0;try{N.Ca(new y(ea=>{a:{if(null!==ea&&(iC(a),!ea.Sb.b())){a.F&&(ea=ut(Q(),\"| \",a.r)+\"No need to reconstrain assigned \"+ea,ff(gf(),ea+\"\\n\"));break a}if(a.F){var ia=ut(Q(),\"| \",a.r)+\"Reconstraining \"+ea;ff(gf(),ia+\"\\n\")}if(ea.Xa>c)for(ia=vy(ea);!ia.b();){for(var X=\nia.e(),sa=rA(ea);!sa.b();){var Ja=sa.e();bX(a,X,Ja,!1,h,k,l,m,n,r,v,x,A,B,C,D,F,I,M);sa=sa.f()}ia=ia.f()}}}));var S=void 0}finally{a.r=-1+a.r|0}dx(new E(d),a.qa)&&a.F&&(S=\"\"+ut(Q(),\"| \",a.r)+d.n(S),ff(gf(),S+\"\\n\"))}return b}\nfunction bX(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C,D,F){a.Ep=1+a.Ep|0;var I=G(new H,b,c);Hea(m,I);YW(a,g,k,n,r,m,v,x,A,B,C);if(d){I=g.h().Jg();var M=new y(P=>Ot(new E(P),b));I=!I.b()&&M.n(I.o())?g.h():new z(b,g.h());M=g.j().Jg();var N=new y(P=>Ot(new E(P),c));M=!M.b()&&N.n(M.o())?g.j():new z(c,g.j());I=G(new H,I,M)}else I=O().c,I=new z(b,I),M=O().c,I=G(new H,I,new z(c,M));g=d||h.b()?h:new z(g,h);d||(d=ap(),l=new QN(l.QC,d,l.tu));Iea(a,b,c,e,I,g,k,l,D,v,m,n,r,x,A,B,C,F);wU(m)}\nfunction Iea(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C,D){var F=tc();try{Lx(a,new U(()=>h.da+\". C \"+b+\" \\x3c! \"+c+\"    (\"+k.ka()+\")\"),new U(()=>{var M=Xu().X();if(Zu(b,c,h,!1,M))Nx(a,new U(()=>\"Already a subtype by \\x3c:\\x3c\"));else{var N=G(new H,b,c);if(N.y instanceof OA||N.w instanceof OA)M=k;else{if(!a.ZE&&l.L(N))throw new fX(F,(Nx(a,new U(()=>\"Cached!\")),void 0));M=jD(b);var P=jD(c);P=G(new H,M,P);if(k.su.L(N))throw new fX(F,(Nx(a,new U(()=>\"Spurious cycle involving \"+N)),void 0));if(!a.pP&&k.tu.L(P)&&\n!k.su.L(P)){Nx(a,new U(()=>\"SHADOWING DETECTED!\"));M=new oX(a);if(!Vr(new Wr(M),N).L(!0)){M=new Te(new Ue(J(new K,[\"Cyclic-looking constraint while typing \",\"; a type annotation may be required\"])));var T=[We(Xe(),m.lh)];M=Ye(M,J(new K,T));M=G(new H,M,m.Ga);if(a.zA){T=Ye(new Te(new Ue(J(new K,[\"\\u2014\\u2014\\u2014\\u2014\\u2014\\u2014\\u2014\\u2014\\u2014 Additional debugging info: \\u2014\\u2014\\u2014\\u2014\\u2014\\u2014\\u2014\\u2014\\u2014\"]))),u());var Y=t().d;T=G(new H,T,Y);Y=new Te(new Ue(J(new K,[\"this constraint:  \",\n\"  \\x3c:  \",\"    \",\"  \",\"\"])));var Z=[We(Xe(),b.u()),We(Xe(),c.u()),We(Xe(),ag(ca(b))),We(Xe(),ag(ca(c)))];Y=Ye(Y,J(new K,Z));Z=t().d;Y=G(new H,Y,Z);Z=new Te(new Ue(J(new K,[\" ... looks like:  \",\"  \\x3c:  \",\"\"])));P=[We(Xe(),nb(P.y)),We(Xe(),nb(P.w))];P=Ye(Z,J(new K,P));Z=t().d;P=G(new H,P,Z);Z=O().c;P=new z(T,new z(Y,new z(P,Z)))}else P=Ye(new Te(new Ue(J(new K,[\"Note: use flag `:ex` to see internal error info.\"]))),u()),T=t().d,P=G(new H,P,T),T=O().c,P=new z(P,T);ay(a,new z(M,P),d)}throw new fX(F);\n}a.ZE||l.$(N);M=k.su.bc(N).bc(P);M=new QN(a,M,k.tu.bc(P))}(new y(S=>{a:{var ea=N.y;if(!(ea instanceof FA&&!0===ea.Eh)){var ia=N.w;b:if(ia instanceof FA&&!1===ia.Eh)var X=!0;else{if(ia instanceof Qv){var sa=ia.Ba,Ja=O().c;if(null===Ja?null===sa:Ja.i(sa)){X=!0;break b}}X=!1}if(!X){var Xa=N.y;if(Xa instanceof cC)bX(a,Xa.Sf,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else{var Fa=N.w;if(Fa instanceof cC)bX(a,b,Fa.Fg,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else{var za=N.y;if(za instanceof OA)bX(a,za.Hi,c,!0,d,e,g,h,\nS,n,r,v,m,x,A,B,C,l,D);else{var Qa=N.w;if(Qa instanceof OA)bX(a,b,Qa.Hi,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else if(!(Uv(N.y)&&Uv(N.w)&&Pe(new E(b),c))){var Ma=N.y,Ga=N.w;if(Ma instanceof MA){var ab=Ma.Fc;if(Ga instanceof MA){bX(a,Ga.Fc,ab,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var Hb=N.y,bc=N.w;if(Hb instanceof Mu){var yb=Hb.pd;if(yb instanceof vl){var tb=yb.x;if(bc instanceof Qv&&a.$c&&hB(ve(),tb)){h.$a.n(tb);for(var eb=new y(wd=>{a:{if(null!==wd){var ge=wd.h(),De=wd.j();if(null!==ge&&\"Eql#A\"===\nge.x){ge=G(new H,ge,De);wd=O().c;cX(a,b,new Qv(a,new z(ge,wd),V(a)),e,g,h,S,x,m,D,n,r,v,A,B,C,l);break a}}if(null!==wd){ge=wd.h();wd=wd.j();De=new U(()=>b);t();var qf=new L(tb),og=new y(()=>t().d),Xf=uv(),mh=Su(),Ag=op().ga;ge=jX(a,De,qf,og,Xf.ng(new Uu(mh,Ag)),ge,h,d);bX(a,ge.ra,wd.ra,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);kX(a,wd,ge,d,e,g,h,S,n,m,x,r,v,A,B,C,l,D)}else throw new w(wd);}}),kb=bc.Ba;!kb.b();)eb.n(kb.e()),kb=kb.f();break a}}}var Rb=N.y,Gb=N.w;if(Rb instanceof cv){var vb=Rb.Nb,Tb=Rb.ac;if(Gb instanceof\ncv){var Nb=Gb.ac;bX(a,Gb.Nb,vb,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);bX(a,Tb,Nb,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var ic=N.y,Va=N.w;if(!(ic instanceof Mu&&Uv(Va)&&ic.Fv().L(Va.uo()))){var cb=N.y,zb=N.w;if(cb instanceof lx){iC(a);var Ub=cb.Sb;if(!Ub.b()){var jb=Ub.o();bX(a,jb,zb,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var db=N.y,ub=N.w;if(ub instanceof lx){iC(a);var Aa=ub.Sb;if(!Aa.b()){var va=Aa.o();bX(a,db,va,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var Ra=N.y,rb=N.w;if(Ra instanceof lx&&\nrb.Ea()<=Ra.Xa){Nx(a,new U(()=>\"NEW \"+Ra+\" UB (\"+rb.Ea()+\")\"));var xb=e.h(),mc=dl(Km(e.j()),xb).mf(rb,new fn((wd,ge)=>{var De=wd.ma();return Ot(new E(De),V(a))?ge:ux(a,ge,wd.ma())})),Ha=rA(Ra);KA(Ra,new z(mc,Ha));for(var Ka=vy(Ra),Oa=new y(wd=>{bX(a,wd,rb,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}),Na=Ka;!Na.b();)Oa.n(Na.e()),Na=Na.f()}else{var Da=N.y,ta=N.w;if(ta instanceof lx&&Da.Ea()<=ta.Xa){Nx(a,new U(()=>\"NEW \"+ta+\" LB (\"+Da.Ea()+\")\"));var Ya=e.h(),dc=dl(Km(e.j()),Ya),ka=YA(dc,Da,new fn((wd,ge)=>{var De=\nge.ma();return Ot(new E(De),V(a))?wd:ux(a,wd,ge.ma())})),ya=vy(ta);IA(ta,new z(ka,ya));for(var Sa=rA(ta),xc=new y(wd=>{bX(a,Da,wd,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}),Sb=Sa;!Sb.b();)xc.n(Sb.e()),Sb=Sb.f()}else{var uc=N.y,Lb=N.w;if(uc instanceof lx)if(Nx(a,new U(()=>\"wrong level: \"+Lb.Ea())),a.li&&Lb.Ea()<=h.da){Nx(a,new U(()=>\"STASHING \"+uc+\" bound in extr ctx\"));var lc=pX(h.cb,uc,new U(()=>TE(PE()))),Xb=G(new H,!1,Lb);lc.$(Xb);var ec=G(new H,uc,Lb);l.Bm(ec)}else{var Ab=uc.Xa,Ob=a.Df,fb=e.h(),Wa=op(),\nbb=g.Gb(Wa.ga).h(),Ia=op(),Ua=dl(g.Gb(Ia.ga).j(),bb),pc=nX(a,Lb,Ab,!1,Ob,new z(fb,Ua),d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);Nx(a,new U(()=>\"EXTR RHS  ~\\x3e  \"+pc+\"  to \"+uc.Xa));Nx(a,new U(()=>\" where \"+xx(pc)));bX(a,uc,pc,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}else{var sc=N.y,Ba=N.w;if(Ba instanceof lx)if(Nx(a,new U(()=>\"wrong level: \"+sc.Ea())),a.li&&sc.Ea()<=h.da){Nx(a,new U(()=>\"STASHING \"+Ba+\" bound in extr ctx\"));var ob=pX(h.cb,Ba,new U(()=>TE(PE()))),nc=G(new H,!0,sc);ob.$(nc);var Ib=G(new H,sc,Ba);l.Bm(Ib)}else{var vc=\nBa.Xa,Vb=a.Df,fc=e.j(),Bc=op(),Pb=g.Gb(Bc.ga).j(),Jb=op(),gc=dl(g.Gb(Jb.ga).h(),Pb),Cb=nX(a,sc,vc,!0,Vb,new z(fc,gc),d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);Nx(a,new U(()=>\"EXTR LHS  ~\\x3e  \"+Cb+\"  to \"+Ba.Xa));Nx(a,new U(()=>\" where \"+xx(Cb)));bX(a,Cb,Ba,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}else{var cc=N.y,yc=N.w;if(cc instanceof zv){var Mc=cc.Yb;if(yc instanceof zv){var qc=yc.Yb,oc=Mc.K();if(Pe(new E(oc),qc.K())){pH(new Wq(Mc,Mc,qc),new fn((wd,ge)=>{var De=G(new H,wd,ge);a:{ge=De.y;var qf=De.w;if(null!==ge&&\n(wd=ge.h(),ge=ge.j(),null!==qf)){var og=qf.h();De=qf.j();qf=new y(Xf=>{var mh=new y(Ag=>{if(Nm(new E(Xf),Ag)){var Bg=new Te(new Ue(J(new K,[\"Wrong tuple field name: found '\",\"' instead of '\",\"'\"])));Ag=[We(Xe(),Xf.x),We(Xe(),Ag.x)];return Lw(a,Ye(Bg,J(new K,Ag)),b.ma().Ga,d)}});og.b()||mh.n(og.o())});wd.b()||qf.n(wd.o());kX(a,De,ge,d,e,g,h,S,n,m,x,r,v,A,B,C,l,D);bX(a,ge.ra,De.ra,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}throw new w(De);}}));break a}}}var Qc=N.y,jc=N.w;if(Qc instanceof Vv&&jc instanceof\nSv)kX(a,jc.Fd,Qc.Zj(),d,e,g,h,S,n,m,x,r,v,A,B,C,l,D),bX(a,Qc.Zj().ra,jc.Fd.ra,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else{var sb=N.y;if(sb instanceof LA){var Gc=sb.ic,Wb=sb.jc;if(!0===sb.tc){bX(a,Gc,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);bX(a,Wb,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var Cc=N.w;if(Cc instanceof LA){var Fc=Cc.ic,qd=Cc.jc;if(!1===Cc.tc){bX(a,b,Fc,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);bX(a,b,qd,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var Yb=N.y;if(Yb instanceof ZB){$B(a);t();var Nc=Yb.mc(),\nad=new L(Nc);if(!ad.b()){bX(a,ad.k,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var Uc=N.w;if(Uc instanceof ZB){$B(a);t();var cd=Uc.mc(),kc=new L(cd);if(!kc.b()){bX(a,b,kc.k,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var Vc=N.w;if(Vc instanceof zv){var Hc=Vc.Yb;if(Hc instanceof z){var rc=Hc.p,sd=O().c;null===sd||sd.i(rc)}}var Kc=N.y,Qd=N.w;if(Kc instanceof Mu){var Ad=Kc.pd,kd=a.Bk;if((null===kd?null===Ad:kd.i(Ad))&&Qd instanceof cv){var Hd=Qd.ac;bX(a,Qd.Nb,Kc,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);bX(a,\nKc,Hd,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var Rd=N.y,Bd=N.w;if(Rd instanceof cv){var ae=Rd.Nb,dd=Rd.ac;if(Bd instanceof Mu){var od=Bd.pd,Ta=a.Bk;if(null===Ta?null===od:Ta.i(od)){bX(a,Bd,ae,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);bX(a,dd,Bd,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}}var wb=N.y,$a=N.w;if(wb instanceof Qv){var wa=wb.Ba;if($a instanceof Qv){for(var hb=new y(wd=>{if(null!==wd){var ge=wd.h(),De=wd.j();wd=lX(wa,new y(Xf=>Pe(new E(Xf.h()),ge)));var qf=new U(()=>{iX(a,t().d,e,h,m,x)}),og=\nnew y(Xf=>{if(null!==Xf)Xf=Xf.j(),kX(a,De,Xf,d,e,g,h,S,n,m,x,r,v,A,B,C,l,D),bX(a,Xf.ra,De.ra,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else throw new w(Xf);});wd.b()?Es(qf):og.n(wd.o())}else throw new w(wd);}),ra=$a.Ba;!ra.b();)hb.n(ra.e()),ra=ra.f();break a}}var wc=N.y;if(wc instanceof zv&&N.w instanceof Qv)bX(a,wc.kq(),c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else{var ac=N.y,Id=N.w;if(ac instanceof Mu){var ud=ac.pd,be=a.Bk;if((null===be?null===ud:be.i(ud))&&Id instanceof Qv){for(var re=new y(wd=>{bX(a,ac,wd.j().ra,\n!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}),pe=Id.Ba;!pe.b();)re.n(pe.e()),pe=pe.f();break a}}if(N.w instanceof Qv)cX(a,b,c,e,g,h,S,x,m,D,n,r,v,A,B,C,l);else{var bd=N.y,Rc=N.w;if(bd instanceof Qv){var Wc=bd.Ba;if(Rc instanceof Mu){var Wd=Rc.pd,zd=a.Bk;if(null===zd?null===Wd:zd.i(Wd)){for(var Pa=new y(wd=>{bX(a,wd.j().ra,Rc,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}),Db=Wc;!Db.b();)Pa.n(Db.e()),Db=Db.f();break a}}}var Oc=N.y,Tc=N.w;if(Oc instanceof fw&&Tc instanceof fw&&Nm(new E(Oc.qb.V),\"Array\")&&Nm(new E(Tc.qb.V),\n\"Eql\"))if(Pe(new E(Oc.qb),Tc.qb)){tp();var Sd=jv(Oc.Zb,Tc.Zb);up(0,Pe(new E(Sd),0));var Jc=h.tb.U(Oc.qb.V);if(Jc instanceof L){var vd=Jc.k,hd=dB(vd),de=vd.Xm,ye=op(),jf=de.Gb(ye.ga).j();rH(qD(new Wq(jf,jf,Oc.Zb),Tc.Zb),new fW((wd,ge,De)=>{wd=hd.n(wd);wd.qe||bX(a,ge,De,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);wd.Qd||bX(a,De,ge,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}))}else if(t().d===Jc){var af=h.$a.U(Oc.qb.V);if(af instanceof L){var pf=af.k,kf=Qt(pf.Ag(),new y(wd=>wd.hb));rH(qD(new Wq(kf,kf,Oc.Zb),Tc.Zb),new fW((wd,\nge,De)=>{wd=VD(pf).U(wd);wd=wd.b()?ou().Yl:wd.o();wd.qe||bX(a,ge,De,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);wd.Qd||bX(a,De,ge,!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}))}else if(t().d===af)no();else throw new w(af);}else throw new w(Jc);}else if(Lca(Oc,h))bX(a,cD(Oc,h,d),cD(Tc,h,d),!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else{var Be=G(new H,gw(Oc,h),gw(Tc,h));b:{var Kd=Be.y,ld=Be.w;if(Kd instanceof L){var Jd=Kd.k;if(ld instanceof L){var Dd=ld.k,Xd=Xu().X();if(!Zu(Jd,Dd,h,!0,Xd)){iX(a,t().d,e,h,m,x);break b}}}bX(a,cD(Oc,\nh,d),cD(Tc,h,d),!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}}else{var Yc=N.y;if(Yc instanceof fw)bX(a,cD(Yc,h,d),c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else{var Ce=N.y,te=N.w;if(Ce instanceof Mu){var Ie=Ce.pd,Jf=a.Bk;if((null===Jf?null===Ie:Jf.i(Ie))&&te instanceof fw)break a}var df=N.w;if(df instanceof fw)bX(a,b,cD(df,h,d),!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else{var vg=N.y;if(vg instanceof Mu){var wg=vg.pd,xg=a.Bk;if(null===xg?null===wg:xg.i(wg))break a}var eg=N.w;if(eg instanceof Mu){var vh=eg.pd,fg=a.Bk;if(null===\nfg?null===vh:fg.i(vh))break a}var ih=N.w;if(ih instanceof Tv){var Ig=ih.Ic;bX(a,iB(b,ih.kf),Ig,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}else{var Tf=N.w;if(Tf instanceof MA){var Jg=Tf.Fc;if(Jg instanceof Tv){var jh=Jg.Ic;bX(a,new Tv(a,b,Jg.kf,Jg.vp),new MA(a,jh,Tf.rA),!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}var yg=N.w;if(yg instanceof Qx)Sx(h,new y(wd=>{var ge=uca(yg,wd);Nx(a,new U(()=>\"BUMP TO LEVEL \"+wd.da+\"  --\\x3e  \"+ge));Nx(a,new U(()=>\"where \"+xx(ge)));bX(a,b,ge,!0,d,e,g,wd,S,n,r,v,m,x,A,B,C,l,D);\naX(a,h,wd,e,g,x,D,n,r,v,m,A,B,C,l)}),d,m);else{var gg=N.y;if(null!==gg){var Cf=Hv(Iv(a),gg,h);if(!Cf.b()){var Uf=Cf.k;if(Uf instanceof Qx){var $g=Uf.de,Ah=Uf.Re;if(Ah.Ea()<=$g){bX(a,Ah,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}}}var Kg=N.w;if(null!==Kg){var Vf=tca(pca(a),Kg,h,d);if(!Vf.b()){var hg=Vf.o();if(a.Wq){Nx(a,new U(()=>\"DISTRIB-R  ~\\x3e  \"+hg));bX(a,b,hg,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}}var zg=N.y;if(null!==zg){var Lg=Hv(Iv(a),zg,h);if(!Lg.b()){var Mg=Lg.k;if(Mg instanceof Qx){var Wf=\nMg.de,Ng=Mg.Re;if(null!==Ng){var Kf=Hv(Iv(a),Ng,h);if(!Kf.b()){var xf=Kf.k;if(xf instanceof cv){var Og=xf.Nb,mi=xf.ac;if(a.Wq&&Og.Ea()<=Wf&&mi.Ea()>Wf){var Ci=new cv(a,Og,new Qx(a,Wf,mi),c.ma());Nx(a,new U(()=>\"DISTRIB-L  ~\\x3e  \"+Ci));bX(a,Ci,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}}}}}}var Xh=N.y;if(Xh instanceof Qx){var wh=lca(kea(a),Xh,h,d);if(!wh.b()){var Bh=wh.o();if(a.Wq){Nx(a,new U(()=>\"DISTRIB-L'  ~\\x3e  \"+Bh));bX(a,Bh,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);break a}}}var ng=N.y;if(ng instanceof\nQx){if(g.b())var kh=O().c,Kh=O().c,ni=G(new H,kh,Kh),Lh=O().c,lh=new z(ni,Lh);else lh=g;(new y(wd=>{bX(a,TA(ng,h),c,!0,d,e,wd,h,S,n,r,v,m,x,A,B,C,l,D)})).n(lh)}else{var Ch=N.y;if(Ch instanceof eC){var Dh=Ch.Lj,Yh=Ch.kj;Lx(a,new U(()=>\"DISCHARGE CONSTRAINTS\"),new U(()=>{for(var wd=new y(De=>{if(null!==De)bX(a,De.h(),De.j(),!1,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D);else throw new w(De);}),ge=Dh;!ge.b();)wd.n(ge.e()),ge=ge.f()}),a.qa);bX(a,Yh,c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D)}else{N.w instanceof eC&&no();\nvar ah=N.w;if(ah instanceof LA&&!0===ah.tc)cX(a,b,c,e,g,h,S,x,m,D,n,r,v,A,B,C,l);else{var oi=N.y;if(oi instanceof LA&&!1===oi.tc)cX(a,b,c,e,g,h,S,x,m,D,n,r,v,A,B,C,l);else{var mj=N.y;mj instanceof Jv?bX(a,mX(mj),c,!0,d,e,g,h,S,n,r,v,m,x,A,B,C,l,D):N.y instanceof MA||N.y instanceof Tv||N.w instanceof MA||N.w instanceof Tv?cX(a,b,c,e,g,h,S,x,m,D,n,r,v,A,B,C,l):(N.y instanceof Mu||N.y instanceof nC)&&N.w instanceof nC?cX(a,b,c,e,g,h,S,x,m,D,n,r,v,A,B,C,l):iX(a,t().d,e,h,m,x)}}}}}}}}}}}}}}}}}}}}}}}}})).n(M)}}),\na.qa)}catch(M){if(M instanceof Iq){var I=M;if(I.Qg!==F)throw I;}else throw M;}}function qX(a,b){var c=new Te(new Ue(J(new K,[\"does not match type `\",\"`\"])));a=[wO(Xe(),CD(a,b))];return Ye(c,J(new K,a))}function rX(a){var b=new Te(new Ue(J(new K,[\"does not have field '\",\"'\"])));a=[We(Xe(),a)];return Ye(b,J(new K,a))}function sX(a,b){if(!a.b()){var c=a.o();b.$(c)}return a}\nfunction tX(a){if(a.Zm)return Ye(new Te(new Ue(J(new K,[\"type\"]))),u());var b=new Te(new Ue(J(new K,[\"\",\" of type\"])));a=[We(Xe(),a.lh)];return Ye(b,J(new K,a))}var Kea=function Jea(a,b,c,d){if(b instanceof z){var g=b.p;b=b.z.m();b=new Ef(b,new y(h=>h.ma()));b=new Ex(b,new uX(a,c,d));Od();b=Pd(u(),b);return dl(Jea(a,g,c,d),b)}a=O().c;if(null===a?null===b:a.i(b))return O().c;throw new w(b);};\nfunction Lea(a,b){var c=jA().X(),d=jA().X(),e=k=>{k=k.j();if(k.b())return!1;k=k.o();return d.L(k)};b=Kea(a,b,c,d);a:for(;;)if(b.b()){e=u();break}else if(c=b.e(),a=b.f(),!0===!!e(c))b=a;else for(;;){if(a.b())e=b;else{c=a.e();if(!0!==!!e(c)){a=a.f();continue}c=a;a=new z(b.e(),u());var g=b.f();for(b=a;g!==c;){var h=new z(g.e(),u());b=b.p=h;g=g.f()}for(g=c=c.f();!c.b();){h=c.e();if(!0===!!e(h)){for(;g!==c;)h=new z(g.e(),u()),b=b.p=h,g=g.f();g=c.f()}c=c.f()}g.b()||(b.p=g);e=a}break a}return e}\nfunction vX(a,b,c,d,e){var g=a.Ga;if(g instanceof L&&(g=g.k,!b.Ga.L(g)&&!c.L(g))){var h=new Te(new Ue(J(new K,[\"Note: constraint arises from \",\":\"]))),k=[We(Xe(),a.lh)];h=Ye(h,J(new K,k));a=sX(a.Ga,c);a=G(new H,h,a);h=d.Ga;a:{if(h instanceof L&&(h=h.k,Nm(new E(h),g)&&!b.Ga.L(h)&&!e.Ga.L(h)&&!c.L(h))){b=new Te(new Ue(J(new K,[\"from \",\":\"])));e=[We(Xe(),d.lh)];b=Ye(b,J(new K,e));c=sX(d.Ga,c);c=G(new H,b,c);d=O().c;c=new z(c,d);break a}c=O().c}return new z(a,c)}return O().c}\nfunction iX(a,b,c,d,e,g){var h=tc();try{var k=c.h().e(),l=c.j().e();Nx(a,new U(()=>\"CONSTRAINT FAILURE: \"+k+\" \\x3c: \"+l));var m=c.h(),n=c.j(),r=m.m(),v=new iy(r,new y(ka=>ka.ma().Ix),!0),x=dH(v,new y(ka=>!ka.ma().Ga.b())),A=new y(ka=>ka.ma()),B=x.b()?R():new L(A.n(x.o())),C=new U(()=>k.ma()),D=B.b()?Es(C):B.o(),F=n.m(),I=new iy(F,new y(ka=>ka.ma().Ix),!0),M=dH(I,new y(ka=>!ka.ma().Ga.b())),N=new y(ka=>ka.ma()),P=M.b()?R():new L(N.n(M.o())),T=new U(()=>l.ma()),Y=P.b()?Es(T):P.o(),Z=er(n).m(),S=new iy(Z,\nnew y(ka=>ka.ma().Ix),!0),ea=dH(S,new y(ka=>!ka.ma().Ga.b())),ia=new y(ka=>ka.ma()),X=ea.b()?R():new L(ia.n(ea.o())),sa=new U(()=>l.ma()),Ja=X.b()?Es(sa):X.o(),Xa=Wn(m,new wX(a,D,e)).Jg(),Fa=jA().X(),za=iu(ju(),m.Jg()),Qa=Is(n),Ma=za.tl(Qa).m(),Ga=new Ef(Ma,new y(ka=>ka.ma())),ab=new Ex(Ga,new xX(a));Od();var Hb=Pd(u(),ab),bc=ky(Hb,new y(ka=>ka.j().Ga)),yb=Fca(k),tb=new U(()=>{var ka=G(new H,yb,uy(l));if(ka.y instanceof YB||ka.w instanceof YB){var ya=ka.y,Sa=ka.w;if(ya instanceof YB&&Sa instanceof\nYB){t();var xc=new L(ya);t();var Sb=new Gp(ya,xc,new L(Sa),un(ya.ME,Sa.ME))}else{var uc=ka.y;if(uc instanceof YB)Sb=new Gp(uc,(t(),new L(uc)),t().d,uc.ME);else{var Lb=ka.w;Lb instanceof YB?Sb=new Gp(Lb,t().d,(t(),new L(Lb)),Lb.ME):xm(\"Program reached and unexpected state.\")}}if(null!==Sb)var lc=new Gp(Sb.Uj,Sb.oj,Sb.oi,Sb.Xi);else throw new w(Sb);var Xb=lc.Uj,ec=lc.oj,Ab=lc.oi,Ob=Lea(a,lc.Xi),fb=sX(D.Ga,Fa),Wa=new U(()=>sX(Xb.Ym.et.Ga,Fa)),bb=fb.b()?Es(Wa):fb,Ia=new U(()=>sX(Xb.Ym.hi.ji.Ga,Fa)),Ua=\nbb.b()?Es(Ia):bb,pc=new Te(new Ue(J(new K,[\"Type error in \",\"\"]))),sc=[We(Xe(),e.lh)],Ba=Ye(pc,J(new K,sc)),ob=sX(e.Ga,Fa),nc=G(new H,Ba,ob),Ib=new Te(new Ue(J(new K,[\"type variable `\",\"` leaks out of its scope\"]))),vc=[wO(Xe(),AD(Xb.Ym,d))],Vb=Ye(Ib,J(new K,vc)),fc=G(new H,Vb,Ua);if(Ab instanceof L){var Bc=Ab.k,Pb=sX(Y.Ga,Fa),Jb=new U(()=>sX(Bc.Ym.et.Ga,Fa)),gc=Pb.b()?Es(Jb):Pb,Cb=new U(()=>sX(Bc.Ym.hi.ji.Ga,Fa)),cc=gc.b()?Es(Cb):gc;if(!ec.b()&&Nm(new E(cc),Ua))var yc=new Te(new Ue(J(new K,[\"back into type variable `\",\n\"`\"]))),Mc=[wO(Xe(),CD(Bc.Ym,d))],qc=Ye(yc,J(new K,Mc)),oc=G(new H,qc,cc),Qc=O().c,jc=new z(oc,Qc);else jc=O().c}else if(t().d===Ab){var sb=new Te(new Ue(J(new K,[\"into \",\" `\",\"`\"]))),Gc=[tX(Y),wO(Xe(),CD(l,d))],Wb=Ye(sb,J(new K,Gc)),Cc=sX(Y.Ga,Fa),Fc=G(new H,Wb,Cc),qd=O().c;jc=new z(Fc,qd)}else throw new w(Ab);if(Ob.b())Uc=O().c;else var Yb=Ye(new Te(new Ue(J(new K,[\"adding a type annotation to any of the following terms may help resolve the problem\"]))),u()),Nc=t().d,ad=G(new H,Yb,Nc),Uc=new z(ad,\nOb);var cd=Ja.Ga;a:{if(cd instanceof L){var kc=cd.k;if(!(Y.Ga.L(kc)||e.Ga.L(kc)||D.Ga.L(kc)||Fa.L(kc))){var Vc=new Te(new Ue(J(new K,[\"Note: constraint arises from \",\":\"]))),Hc=[We(Xe(),Ja.lh)],rc=Ye(Vc,J(new K,Hc)),sd=sX(Ja.Ga,Fa),Kc=G(new H,rc,sd),Qd=O().c;var Ad=new z(Kc,Qd);break a}}Ad=O().c}var kd=dl(dl(Ad,Uc),jc),Hd=new z(nc,new z(fc,kd));throw new fX(h,g.n(kr(jr(),dl(vX(Y,e,Fa,Ja,D),Hd),a.$c,lu())));}if(ka.y instanceof lx||ka.y instanceof ZB)return qX(l,d);var Rd=ka.y,Bd=ka.w;if(Rd instanceof\nQv){var ae=Rd.Ba;if(Bd instanceof Qv){var dd=Qt(Bd.Ba,new y(Yc=>Yc.h())),od=Aq(Bq(),dd),Ta=Qt(ae,new y(Yc=>Yc.h())),wb=Aq(Bq(),Ta),$a=od.wy(wb),wa=sp($a),hb=new U(()=>qX(l,d)),ra=new y(Yc=>rX(Yc.x));return wa.b()?Es(hb):ra.n(wa.o())}}var wc=ka.w;if(XB(wc)&&wc.rr()instanceof vl){var ac=new Te(new Ue(J(new K,[\"is not an instance of type `\",\"`\"])));if(a.cn.L(wc.rr().Dh))var Id=We(Xe(),wc.rr().Dh);else Xe(),Q(),Id=We(0,Nu(0,wc.rr().Dh));return Ye(ac,J(new K,[Id]))}var ud=ka.w;if(ud instanceof fw){var be=\nnew Te(new Ue(J(new K,[\"is not an instance of `\",\"`\"]))),re=[wO(Xe(),CD(ud,d))];return Ye(be,J(new K,re))}var pe=ka.y,bd=ka.w;if(bd instanceof zv){var Rc=bd.Yb;if(!(pe instanceof zv)){var Wc=new Te(new Ue(J(new K,[\"is not a \",\"-element tuple\"])));Xe();var Wd=Rc.K(),zd=[We(0,\"\"+Wd)];return Ye(Wc,J(new K,zd))}}var Pa=ka.y;if(ka.w instanceof cv&&!(Pa instanceof cv))return Ye(new Te(new Ue(J(new K,[\"is not a function\"]))),u());var Db=ka.y,Oc=ka.w;if(Oc instanceof Qv){var Tc=Oc.Ba;if(Tc instanceof z){var Sd=\nTc.z,Jc=Tc.p;if(null!==Sd){var vd=Sd.h(),hd=O().c;if((null===hd?null===Jc:hd.i(Jc))&&!(Db instanceof Qv))return rX(vd.x)}}}var de=ka.y,ye=ka.w;if(ye instanceof Qv){var jf=ye.Ba;if(jf instanceof z&&Vr(new Wr(new yX(a)),yb).L(!0)&&!(de instanceof Qv)){var af=new Te(new Ue(J(new K,[\"is not a record (expected a record with field\",\": \",\")\"]))),pf=0<jf.ab(1)?We(Xe(),\"s\"):We(Xe(),\"\");Xe();var kf=Qt(jf,new y(Yc=>Yc.h().x)),Be=[pf,We(0,ze(kf,\"\",\", \",\"\"))];return Ye(af,J(new K,Be))}}var Kd=ka.w;if(Kd instanceof\nQv){var ld=Kd.Ba;if(ld instanceof z){var Jd=new Te(new Ue(J(new K,[\"does not have all required fields \",\"\"])));Xe();var Dd=Qt(ld,new y(Yc=>\"'\"+Yc.h().x+\"'\")),Xd=[We(0,ze(Dd,\"\",\", \",\"\"))];return Ye(Jd,J(new K,Xd))}}return qX(l,d)}),eb=b.b()?Es(tb):b.o(),kb=new Te(new Ue(J(new K,[\"Type mismatch in \",\":\"]))),Rb=[We(Xe(),e.lh)],Gb=Ye(kb,J(new K,Rb)),vb=sX(e.Ga,Fa),Tb=G(new H,Gb,vb),Nb=new Te(new Ue(J(new K,[\"\",\" `\",\"` \",\"\"]))),ic=[tX(D),wO(Xe(),AD(k,d)),eb],Va=Ye(Nb,J(new K,ic)),cb=Pe(new E(D.Ga),e.Ga)?\nt().d:sX(D.Ga,Fa),zb=G(new H,Va,cb),Ub=O().c,jb=new z(Tb,new z(zb,Ub)),db=new y(ka=>{var ya=new Te(new Ue(J(new K,[\" with expected type `\",\"`\"]))),Sa=[wO(Xe(),CD(l,d))];Sa=Ye(ya,J(new K,Sa));ya=new Te(new Ue(J(new K,[\"but it flows into \",\"\",\"\"])));Sa=[We(Xe(),ka.ma().lh),Sa];ya=Ye(ya,J(new K,Sa));ka=sX(ka.ma().Ga,Fa);ka=G(new H,ya,ka);ya=O().c;return new z(ka,ya)}),ub=(Xa.b()?R():new L(db.n(Xa.o()))).ha(),Aa=op().ga,va=zX(ub,Aa),Ra=vX(Y,e,Fa,Ja,D),rb=Wn(bc,new AX(a,Fa,new GA(!0)));if(a.zA)var xb=\nYe(new Te(new Ue(J(new K,[\"\\x3d\\x3d\\x3d\\x3d\\x3d\\x3d\\x3d\\x3d\\x3d Additional explanations below \\x3d\\x3d\\x3d\\x3d\\x3d\\x3d\\x3d\\x3d\\x3d\"]))),u()),mc=t().d,Ha=G(new H,xb,mc),Ka=ZW(m,new y(ka=>{if(a.F){var ya=new Te(new Ue(J(new K,[\"[info] LHS \\x3e\\x3e \",\" : \",\"\"]))),Sa=[We(Xe(),ka.ma().u()),wO(Xe(),AD(ka,d))];ya=Ye(ya,J(new K,Sa));ka=ka.ma().Ga;ka=G(new H,ya,ka);ya=O().c;return new z(ka,ya)}ya=new Te(new Ue(J(new K,[\"[info] flowing from \",\" `\",\"`\"])));Sa=[tX(ka.ma()),wO(Xe(),AD(ka,d))];ya=Ye(ya,J(new K,\nSa));ka=ka.ma().Ga;ka=G(new H,ya,ka);ya=O().c;return new z(ka,ya)})),Oa=dl(ZW(Km(n),new y(ka=>{if(a.F){var ya=new Te(new Ue(J(new K,[\"[info] RHS \\x3c\\x3c \",\" : \",\"\"]))),Sa=[We(Xe(),ka.ma().u()),wO(Xe(),CD(ka,d))];ya=Ye(ya,J(new K,Sa));ka=ka.ma().Ga;ka=G(new H,ya,ka);ya=O().c;return new z(ka,ya)}ya=new Te(new Ue(J(new K,[\"[info] flowing into \",\" `\",\"`\"])));Sa=[tX(ka.ma()),wO(Xe(),CD(ka,d))];ya=Ye(ya,J(new K,Sa));ka=ka.ma().Ga;ka=G(new H,ya,ka);ya=O().c;return new z(ka,ya)})),Ka),Na=new z(Ha,Oa);else Na=\nO().c;t();var Da=J(new K,[jb,va,Ra,rb,Na]),ta=Pd(u(),Da),Ya=op().ga,dc=zX(ta,Ya);g.n(kr(jr(),dc,a.$c,lu()))}catch(ka){if(ka instanceof Iq){if(b=ka,b.Qg!==h)throw b;}else throw ka;}}\nvar fD=function BX(a,b,c,d,e,g,h,k){At(tp(),c>=d.da);if(b.Ea()<=e)return b;var m=!1,n=null,r=!1,v=null;if(b instanceof lx&&(m=!0,n=b,g.L(n)))return n;if(m){iC(a);var x=n.Sb;if(!x.b()){var A=x.o();return h.Se(n,new U((ra=>()=>{var wc=ra.ji;t();var ac=new L(ra),Id=ra.kg,ud=O().c,be=O().c;wc=new lx(a,ra.Xa>c?ra.Xa:d.da,ud,be,ac,Id,!1,wc);ac=G(new H,ra,wc);h.$(ac);ac=BX(a,A,c,d,e,g,h,k);wy(wc,(t(),new L(ac)));return wc})(n)))}}if(m){var B=!1,C=h.U(n);if(C instanceof L)return C.k;if(R()===C&&(B=!0,k&&\nn.Xa<=c)){var D=V(a);t();var F=new L(n),I=n.kg,M=O().c,N=O().c,P=new mx(a,new lx(a,d.da,M,N,F,I,!1,D),n.ji),T=n;if(a.F){var Y=ut(Q(),\"| \",a.r)+(\"New skolem: \"+T+\" ~\\x3e \")+P;ff(gf(),Y+\"\\n\")}if(vy(n).b()?!rA(n).b():1){var Z=n.ji;t();var S=new L(n),ea=n.kg,ia=O().c,X=O().c,sa=new lx(a,d.da,ia,X,S,ea,!1,Z),Ja=G(new H,n,sa);h.$(Ja);var Xa=vy(sa),Fa=rA(n);if(Fa===u())var za=u();else{for(var Qa=Fa.e(),Ma=new z(BX(a,Qa,c,d,e,g,h,k),u()),Ga=Ma,ab=Fa.f();ab!==u();){var Hb=ab.e(),bc=new z(BX(a,Hb,c,d,e,g,h,\nk),u());Ga=Ga.p=bc;ab=ab.f()}za=Ma}for(var yb=P,tb=za;!tb.b();){var eb=yb,kb=tb.e(),Rb=eb,Gb=kb,vb=V(Rb.q);yb=Pu(Rb,Gb,vb,!1);tb=tb.f()}IA(sa,new z(yb,Xa));if(a.F){var Tb=ut(Q(),\"| \",a.r)+(sa+\" :\\x3e \")+vy(sa);ff(gf(),Tb+\"\\n\")}var Nb=rA(sa),ic=vy(n);if(ic===u())var Va=u();else{for(var cb=ic.e(),zb=new z(BX(a,cb,c,d,e,g,h,k),u()),Ub=zb,jb=ic.f();jb!==u();){var db=jb.e(),ub=new z(BX(a,db,c,d,e,g,h,k),u());Ub=Ub.p=ub;jb=jb.f()}Va=zb}for(var Aa=P,va=Va;!va.b();){var Ra=Aa,rb=va.e(),xb=Ra,mc=rb,Ha=V(xb.q);\nAa=dv(xb,mc,Ha,!1);va=va.f()}KA(sa,new z(Aa,Nb));if(a.F){var Ka=ut(Q(),\"| \",a.r)+(sa+\" \\x3c: \")+rA(sa);ff(gf(),Ka+\"\\n\")}return sa}var Oa=G(new H,n,P);h.$(Oa);return P}if(B){var Na=n.ji;t();var Da=new L(n),ta=n.kg,Ya=O().c,dc=O().c;if(n.Xa>c)var ka=n.Xa;else{if(!(d.da<=c))throw new Yj(\"assertion failed: this condition should be false for the result to be correct\");ka=d.da}var ya=new lx(a,ka,Ya,dc,Da,ta,!1,Na),Sa=G(new H,n,ya);h.$(Sa);for(var xc=vy(n),Sb=null,uc=null,Lb=xc,lc=xc,Xb;;)if(lc.b()){null===\nSb?Xb=Lb:(uc.p=Lb,Xb=Sb);break}else{var ec=lc.e(),Ab=BX(a,ec,c,d,e,g,h,k);if(Ab===ec)lc=lc.f();else{for(var Ob=Lb,fb=Sb,Wa=uc;Ob!==lc;){var bb=new z(Ob.e(),u());null===fb&&(fb=bb);null!==Wa&&(Wa.p=bb);Wa=bb;Ob=Ob.f()}var Ia=new z(Ab,u());null===fb&&(fb=Ia);null!==Wa&&(Wa.p=Ia);Wa=Ia;var Ua=lc.f(),pc=Wa;Sb=fb;uc=pc;lc=Lb=Ua}}IA(ya,Xb);for(var sc=rA(n),Ba=null,ob=null,nc=sc,Ib=sc,vc;;)if(Ib.b()){null===Ba?vc=nc:(ob.p=nc,vc=Ba);break}else{var Vb=Ib.e(),fc=BX(a,Vb,c,d,e,g,h,k);if(fc===Vb)Ib=Ib.f();else{for(var Bc=\nnc,Pb=Ba,Jb=ob;Bc!==Ib;){var gc=new z(Bc.e(),u());null===Pb&&(Pb=gc);null!==Jb&&(Jb.p=gc);Jb=gc;Bc=Bc.f()}var Cb=new z(fc,u());null===Pb&&(Pb=Cb);null!==Jb&&(Jb.p=Cb);Jb=Cb;var cc=Ib.f(),yc=Jb;Ba=Pb;ob=yc;Ib=nc=cc}}KA(ya,vc);return ya}throw new w(C);}if(b instanceof cC){var Mc=b.Sf;return new cC(a,BX(a,b.Fg,c,d,e,g,h,k),BX(a,Mc,c,d,e,g,h,k),b.TO)}if(b instanceof cv){var qc=b.ac;return new cv(a,BX(a,b.Nb,c,d,e,g,h,k),BX(a,qc,c,d,e,g,h,k),b.Mj)}if(b instanceof LA){var oc=b.jc;return new LA(a,b.tc,BX(a,\nb.ic,c,d,e,g,h,k),BX(a,oc,c,d,e,g,h,k),b.KE)}if(b instanceof Qv){var Qc=b.Ba;return new Qv(a,ry(lv(),Qc,new y(ra=>{var wc=ra.Va,ac=ra.Oa;ac.b()?ac=R():(ac=ac.o(),ac=new L(BX(a,ac,c,d,e,g,h,k)));return new Uw(wc,ac,BX(a,ra.ra,c,d,e,g,h,k),ra.Pd)})),b.Nj)}if(b instanceof zv){var jc=b.Yb;return new zv(a,ry(lv(),jc,new y(ra=>{var wc=ra.Va,ac=ra.Oa;ac.b()?ac=R():(ac=ac.o(),ac=new L(BX(a,ac,c,d,e,g,h,k)));return new Uw(wc,ac,BX(a,ra.ra,c,d,e,g,h,k),ra.Pd)})),b.Nq)}if(b instanceof Sv){var sb=b.Fd,Gc=sb.Va,\nWb=sb.Oa;if(Wb.b())var Cc=R();else{var Fc=Wb.o();Cc=new L(BX(a,Fc,c,d,e,g,h,k))}return new Sv(a,new Uw(Gc,Cc,BX(a,sb.ra,c,d,e,g,h,k),sb.Pd),b.Fx)}if(b instanceof Wv)return sB(b,new y(ra=>BX(a,ra,c,d,e,g,h,k)),new y(ra=>BX(a,ra,c,d,e,g,h,k)),new y(ra=>BX(a,ra,c,d,e,g,h,k)),b.Uu);if(b instanceof MA)return new MA(a,BX(a,b.Fc,c,d,e,g,h,k),b.rA);if(b instanceof FA)return b;if(b instanceof OA)return new OA(a,BX(a,b.Hi,c,d,e,g,h,k),b.NE);if(b instanceof ZB){$B(a);t();var qd=b.mc(),Yb=new L(qd);if(!Yb.b())return BX(a,\nYb.k,c,d,e,g,h,k)}if(b instanceof mx){var Nc=b.hi;if(b.Tu>e&&b.Tu<=c)return BX(a,Nc,c,d,e,g,h,k)}if(b instanceof Mu||b instanceof nC||b instanceof mx||b instanceof YB)return b;if(b instanceof Tv){var ad=b.kf;return new Tv(a,BX(a,b.Ic,c,d,e,g,h,k),ad,b.vp)}if(b instanceof fw){var Uc=b.qb,cd=b.Zb;if(cd===u())var kc=u();else{for(var Vc=cd.e(),Hc=new z(BX(a,Vc,c,d,e,g,h,k),u()),rc=Hc,sd=cd.f();sd!==u();){var Kc=sd.e(),Qd=new z(BX(a,Kc,c,d,e,g,h,k),u());rc=rc.p=Qd;sd=sd.f()}kc=Hc}return new fw(a,Uc,kc,\nb.Xl)}if(b instanceof Qx&&(r=!0,v=b,v.Ea()<=e))return v;if(r){var Ad=v.de,kd=v.Re;if(d.da>Ad){var Hd=KC(v,d.da,g,d,h);return BX(a,Hd,c,d,e,g,h,k)}return new Qx(a,Ad,BX(a,kd,c<Ad?c:Ad,d,e,g,h,k))}if(b instanceof eC){var Rd=b.Lj,Bd=b.kj,ae=ra=>{var wc=BX(a,ra.h(),c,d,e,g,h,k);ra=BX(a,ra.j(),c,d,e,g,h,k);return G(new H,wc,ra)};if(Rd===u())var dd=u();else{for(var od=Rd.e(),Ta=new z(ae(od),u()),wb=Ta,$a=Rd.f();$a!==u();){var wa=$a.e(),hb=new z(ae(wa),u());wb=wb.p=hb;$a=$a.f()}dd=Ta}return new eC(a,dd,\nBX(a,Bd,c,d,e,g,h,k))}if(b instanceof Jv)return VW(b,new y(ra=>BX(a,ra,c,d,e,g,h,k)),new y(ra=>BX(a,ra,c,d,e,g,h,k)));throw new w(b);};function CX(){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0;this.zk=this.Pq=this.Uq=this.xp=this.Bp=this.Cp=this.Sq=this.zp=this.Rq=this.wp=this.Ap=this.yp=this.Qq=this.Tq=null;this.Dp=0;this.hs=this.yq=this.Aq=this.Bq=this.zq=this.Dq=this.Cq=null;this.Im=this.Pw=0}CX.prototype=new HS;CX.prototype.constructor=CX;\nfunction DX(){}DX.prototype=CX.prototype;function Sw(a){null===a.hs&&null===a.hs&&(a.hs=new PN(a));return a.hs}function Mea(a,b,c,d,e){b=d.$a.Se(b,new U(()=>{no()}));if(!b.ct&&(e=Kx(b,e),e instanceof Yw)){e=e.Ei.U(c.x);if(e instanceof L)return a=e.k,t(),new Ud(a);if(t().d===e)return t(),a=wea(a,b,c),new fe(a);throw new w(e);}no()}\nfunction jX(a,b,c,d,e,g,h,k){var l=a.qa;if(a.F){var m=ut(Q(),\"| \",a.r)+(\"Looking up field \"+g.x+\" in \"+c+\" \\x26 \"+e)+\" \\x26 {...}\";ff(gf(),m+\"\\n\")}a.r=1+a.r|0;try{var n=g.x;if(0<=n.length&&\"#\"===n.substring(0,1))var r=g.x,v=new vl(Of(Q(),r,1,r.length)),x=g.A(),A=Cq(v,x),B=!0;else A=g,B=!1;g=A;B=!!B;var C=d.n(g),D=t().d,F=new aw(D);if(c.b())var I=R();else{var M=c.o();I=EX(a,h.$a.n(M),g,B,k,F,d,h)}var N=Wn((Od(),Pd(u(),e)),new FX(a,h,g,B,k,F,d)),P=op().ga,T=zX(N,P),Y=C.ha(),Z=I.ha(),S=dl(dl(T,Z),Y);\nif(a.F){var ea=ut(Q(),\"| \",a.r)+(\"  \\x26 \"+C)+\"  (from refinement)\";ff(gf(),ea+\"\\n\")}if(S instanceof z){for(var ia=S.z,X=Km(S.p);!X.b();){var sa=X.e();ia=Nv(sa,ia,V(sa.Va));X=X.f()}var Ja=ia}else{var Xa=O().c;if(null===Xa?null===S:Xa.i(S)){var Fa=F.rc;if(Fa instanceof L){var za=GX(a,Fa.k,k),Qa=V(a);Ja=lD(za,Qa)}else if(t().d===Fa){var Ma=new Te(new Ue(J(new K,[\"Type `\",\"` does not contain member `\",\"`\"])));Xe();var Ga=Es(b),ab=[wO(0,AD(Ga,h)),We(Xe(),g.x)],Hb=Ye(Ma,J(new K,ab)),bc=g.A(),yb=G(new H,\nHb,bc),tb=O().c,eb=ay(a,new z(yb,tb),k),kb=V(a);Ja=lD(eb,kb)}else throw new w(Fa);}else throw new w(S);}}finally{a.r=-1+a.r|0}dx(new E(l),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+l.n(Ja),ff(gf(),a+\"\\n\"));return Ja}function Tw(a,b,c,d,e,g,h){var k=tc();try{a.Im=1+a.Im|0,HX(a,b,c,d,e,g,h)}catch(l){if(l instanceof Iq){if(a=l,a.Qg!==k)throw a;}else throw l;}}\nfunction HX(a,b,c,d,e,g,h){var k=tc();try{var l=jA().X(),m=a.Pw,n=new IQ(m),r=new IX(16);Nx(a,new U(()=>\"CONSTRAIN \"+b+\" \\x3c! \"+c));Nx(a,new U(()=>{var B=new cv(a,b,c,V(a));return\"  where \"+xx(B)}));var v=new U(()=>{throw new fX(k);}),x=O().c,A=O().c;bX(a,b,c,!0,d,G(new H,x,A),O().c,g,h,r,b,c,e,d,v,n,m,l,h)}catch(B){if(B instanceof Iq){if(d=B,d.Qg!==k)throw d;}else throw B;}}\nfunction Nea(a,b,c,d,e,g){var h=tc();try{Nx(a,new U(()=>\"CHECKING SUBSUMPTION...\"));var k=new IQ(0);Tw(a,b,c,new y(l=>{k.ve=1+k.ve|0;if(3<k.ve)throw new fX(h);Pe(new E(k.ve),1)&&e.n(l)}),g,d,Sw(a).ob)}catch(l){if(l instanceof Iq){if(a=l,a.Qg!==h)throw a;}else throw l;}}function Lw(a,b,c,d){b=G(new H,b,c);c=O().c;return ay(a,new z(b,c),d)}function ay(a,b,c){return GX(a,kr(jr(),b,a.$c,lu()),c)}function GX(a,b,c){c.n(b);return Ey(a)}function Ey(a){var b=a.Bk,c=ap();return new Mu(a,b,c,V(a))}\nfunction JX(a,b,c,d){b=G(new H,b,c);c=O().c;by(a,new z(b,c),d)}function by(a,b,c){c.n(hr(fr(),b,a.$c,lu()))}\nfunction KX(a,b,c,d,e,g,h){var k=a.qa;if(a.F){var l=ut(Q(),\"| \",a.r)+(g.da+\". U \"+b+\" \\x3d! \")+c;ff(gf(),l+\"\\n\")}a.r=1+a.r|0;try{l=c;for(var m=!1;;){if(pD(b)||!Pe(new E(b),l)){var n=b;c=l;if(n instanceof lx&&c.Ea()<=n.Xa){var r=n.Sb;if(r instanceof L)KX(a,r.k,c,d,e,g,h);else if(t().d===r){r=a;if(r.F){var v=ut(Q(),\"| \",r.r)+(n+\" :\\x3d \")+c;ff(gf(),v+\"\\n\")}var x=vy(n),A=rA(n);wy(n,(t(),new L(c)));for(v=a;!x.b();){var B=x.e();HX(v,B,c,d,e,g,h);x=x.f()}for(B=a;!A.b();){var C=A.e();HX(B,c,C,d,e,g,h);A=\nA.f()}}else throw new w(r);}else if(m)Tw(a,b,l,d,e,g,h),Tw(a,l,b,d,e,g,h);else{c=b;b=l;l=c;m=!0;continue}}break}var D=void 0}finally{a.r=-1+a.r|0}dx(new E(k),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+k.n(D),ff(gf(),a+\"\\n\"))}\nfunction EX(a,b,c,d,e,g,h,k){var l=!1;if(b.eo.b()){0===(65536&b.Ha)&&0===(65536&b.Ha)&&(b.yO=Jba(b),b.Ha|=65536);var m=b.yO.U(c)}else m=t().d;a:if(m instanceof L)g=m.k,fy(b).L(c)&&!d&&(d=new Te(new Ue(J(new K,[\"Parameter '\",\"' cannot be accessed as a field\"]))),l=[We(Xe(),c.x)],d=Ye(d,J(new K,l)),l=c.A(),d=G(new H,d,l),l=O().c,ay(a,new z(d,l),e)),t(),e=new L(g);else{if(t().d===m&&(l=!0,b.ct)){Bx(b).L(c)&&(t(),jr(),e=Ye(new Te(new Ue(J(new K,[\"Indirectly-recursive member should have a type signature\"]))),\nu()),d=c.A(),e=G(new H,e,d),d=O().c,e=kr(0,new z(e,d),a.$c,lu()),g.rc=new L(e));e=t().d;break a}if(l)g=Kx(b,e),g instanceof Yw?e=WW(a,g.LC(),c,e,d):g instanceof Ww?e=WW(a,g.LC(),c,e,d):g instanceof Nw?e=WW(a,g.LC(),c,e,d):(g instanceof cx||no(),e=t().d);else throw new w(m);}a.F&&(g=ut(Q(),\"| \",a.r),d=b.Ab.Cf.x,l=c.x,e.b()?m=\"\":(m=e.o().ra,m=xx(m)),ff(gf(),g+(\"Lookup \"+d+\".\"+l+\" : \"+e+\" where \")+m+\"\\n\"));if(e.b())h=R();else{e=e.o();g=Xu().X();Sw(a);for(d=b.Ag();!d.b();){var n=d.e();if(null!==n){l=\nn.hb;var r=n.Rd;m=!1;var v=null;n=h.n(new vl(b.Ab.Cf.x+\"#\"+n.kc.V));a:{if(n instanceof L){m=!0;v=n;var x=v.k,A=new E(r);t();var B=ou().Zu;if(Pe(A,new L(B))){m=x.ra;break a}}if(m&&(x=v.k,r=new E(r),t(),A=ou().AA,Pe(r,new L(A)))){m=x.Oa;m=m.b()?a.ib:m.o();break a}if(m)m=v.k,v=cw(a),n=m.Oa,m=dw(v,n.b()?a.ib:n.o(),m.ra,ew(cw(a)),k);else if(t().d===n){m=vy(l);v=new mx(a,l,V(a));for(v=new YB(a,!0,v,V(a),O().c);!m.b();)n=m.e(),r=V(v.q),v=dv(v,n,r,!1),m=m.f();m=v;v=rA(l);n=new mx(a,l,V(a));for(n=new YB(a,\n!1,n,V(a),O().c);!v.b();)r=v.e(),x=V(n.q),n=Pu(n,r,x,!1),v=v.f();m=new cC(a,m,n,l.ji)}else throw new w(n);}l=G(new H,l,m);g.$(l)}else throw new w(n);d=d.f()}h=new L(LX(e,b.Ru,!1,k,g))}a.F&&(a=ut(Q(),\"| \",a.r),k=b.Ru,b=b.Ab.Cf.x,c=c.x,h.b()?e=R():(e=h.o().ra,e=new L(xx(e))),ff(gf(),a+(\"Fresh[\"+k+\"] \"+b+\".\"+c+\" : \"+h+\" where \")+e+\"\\n\"));return h}function QN(a,b,c){this.QC=null;this.su=b;this.tu=c;if(null===a)throw null;this.QC=a}QN.prototype=new p;QN.prototype.constructor=QN;f=QN.prototype;\nf.ka=function(){return this.su.ka()+this.tu.ka()|0};f.H=function(){return\"Shadows\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.su;case 1:return this.tu;default:return $K(W(),a)}};f.D=function(a){return a instanceof QN};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof QN&&a.QC===this.QC){var b=this.su,c=a.su;if(null===b?null===c:b.i(c))return b=this.tu,a=a.tu,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({AU:0},!1,\"mlscript.ConstraintSolver$Shadows\",{AU:1,g:1,E:1,v:1,l:1});class Df extends xF{constructor(){super();this.pq=null}}function MX(){}MX.prototype=new gS;MX.prototype.constructor=MX;MX.prototype.u=function(){return\"Inter\"};MX.prototype.ba=function(a,b){return new hP(a,b)};MX.prototype.$classData=q({iV:0},!1,\"mlscript.Inter$\",{iV:1,nH:1,g:1,kz:1,l:1});var NX;function Un(){NX||(NX=new MX);return NX}function np(a,b,c){this.zu=b;this.dp=c;if(null===a)throw null;}np.prototype=new p;\nnp.prototype.constructor=np;f=np.prototype;f.H=function(){return\"QualifierPack\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.zu;case 1:return this.dp;default:return $K(W(),a)}};f.D=function(a){return a instanceof np};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof np?this.zu===a.zu?this.dp===a.dp:!1:!1};f.$classData=q({vV:0},!1,\"mlscript.JSBackend$QualifierPack$1\",{vV:1,g:1,E:1,v:1,l:1});\nfunction On(a){this.fD=null;if(null===a)throw null;this.fD=a}On.prototype=new gS;On.prototype.constructor=On;On.prototype.u=function(){return\"QualifierPack\"};On.prototype.ba=function(a,b){return new np(this.fD,a,b)};On.prototype.$classData=q({wV:0},!1,\"mlscript.JSBackend$QualifierPack$2$\",{wV:1,nH:1,g:1,kz:1,l:1});function iO(a){this.tD=a}iO.prototype=new p;iO.prototype.constructor=iO;f=iO.prototype;\nf.xa=function(){for(var a=Sp(Qp(),\"default:\"),b=this.tD,c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,Kz(d.xa()));b=b.f()}return Iz(a,c)};f.H=function(){return\"JSDefaultCase\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.tD:$K(W(),a)};f.D=function(a){return a instanceof iO};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof iO){var b=this.tD;a=a.tD;return null===b?null===a:b.i(a)}return!1};\nf.$classData=q({LV:0},!1,\"mlscript.JSDefaultCase\",{LV:1,g:1,E:1,v:1,l:1});function $p(a,b){this.AH=this.Bu=null;this.uD=a;this.vD=b;Xo(this,a,b)}$p.prototype=new FS;$p.prototype.constructor=$p;\n$p.prototype.xa=function(){var a=Pp(this.uD.xa(),20>this.uD.sh()||this.uD instanceof vo||this.uD instanceof $m);Qp();var b=Al().zH;if(bq(new cq(b.nG,nb(this.vD.tq))))b=\".\"+this.vD.tq;else if(b=this.vD.tq,b=$D(aE(),b),b instanceof L)b=\"[\"+(b.k|0)+\"]\";else{if(t().d!==b)throw new w(b);b=\"[\"+Mp(Np(),this.vD.tq)+\"]\"}return Rp(a,Sp(0,b))};$p.prototype.$classData=q({OV:0},!1,\"mlscript.JSField\",{OV:1,lN:1,Vi:1,Xc:1,g:1});function gO(a,b){this.UD=a;this.TD=b}gO.prototype=new p;gO.prototype.constructor=gO;\nf=gO.prototype;f.xa=function(){for(var a=Rp(Rp(Sp(Qp(),\"case \"),this.UD.xa()),Sp(Qp(),\": \")),b=this.TD,c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,Kz(d.xa()));b=b.f()}return Iz(a,c)};f.H=function(){return\"JSSwitchCase\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.UD;case 1:return this.TD;default:return $K(W(),a)}};f.D=function(a){return a instanceof gO};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof gO){var b=this.UD,c=a.UD;if(null===b?null===c:b.i(c))return b=this.TD,a=a.TD,null===b?null===a:b.i(a)}return!1};f.$classData=q({hW:0},!1,\"mlscript.JSSwitchCase\",{hW:1,g:1,E:1,v:1,l:1});function Kq(a,b,c){this.fh=a;this.eh=b;this.dh=c;up(tp(),0<=a);up(tp(),b>=a)}Kq.prototype=new p;Kq.prototype.constructor=Kq;function Sy(a,b){return Pe(new E(b.dh),a.dh)?b.fh>=a.fh&&b.eh<=a.eh:!1}\nfunction OX(a,b){return Pe(new E(b.dh),a.dh)?b.fh>=a.fh&&b.fh<=a.eh||b.eh<=a.eh&&b.eh>=a.fh:!1}function xs(a,b){At(tp(),Ot(new E(a.dh),b.dh));var c=a.fh,d=b.fh,e=a.eh;b=b.eh;return new Kq(c<d?c:d,e>b?e:b,a.dh)}function Kt(a,b){if(b.b())return a;b=b.o();return xs(a,b)}function vs(a){return new Kq(a.fh,a.fh,a.dh)}f=Kq.prototype;f.H=function(){return\"Loc\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.fh;case 1:return this.eh;case 2:return this.dh;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof Kq};f.B=function(){var a=lb(\"Loc\");a=W().C(-889275714,a);var b=this.fh;a=W().C(a,b);b=this.eh;a=W().C(a,b);b=this.dh;b=My(W(),b);a=W().C(a,b);return W().Ma(a,3)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Kq&&this.fh===a.fh&&this.eh===a.eh){var b=this.dh;a=a.dh;return null===b?null===a:b.i(a)}return!1};f.$classData=q({vW:0},!1,\"mlscript.Loc\",{vW:1,g:1,E:1,v:1,l:1});function $q(a){this.fp=a}$q.prototype=new p;\n$q.prototype.constructor=$q;function UN(a,b){b=wf(vf(),Wn(a.fp,new vO(a)),b,\"'\");return Mf(a,b)}function Mf(a,b){var c=a.fp;a=h=>{if(h instanceof xO)return yf(h.ax,0,b);if(h instanceof Vq)return h.Jz;throw new w(h);};if(c===u())a=u();else{var d=c.e(),e=d=new z(a(d),u());for(c=c.f();c!==u();){var g=c.e();g=new z(a(g),u());e=e.p=g;c=c.f()}a=d}return ze(a,\"\",\"\",\"\")}f=$q.prototype;\nf.Wr=function(){var a=this.fp.m();a=new Ef(a,new y(b=>{if(b instanceof xO)return\"\"+b.ax;if(b instanceof Vq)return b.Jz;throw new w(b);}));return ze(a,\"\",\"\",\"\")};function PX(a,b){return new $q(un(a.fp,b.fp))}f.H=function(){return\"Message\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.fp:$K(W(),a)};f.D=function(a){return a instanceof $q};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof $q){var b=this.fp;a=a.fp;return null===b?null===a:b.i(a)}return!1};f.$classData=q({xW:0},!1,\"mlscript.Message\",{xW:1,g:1,E:1,v:1,l:1});function zO(a,b){this.vq=null;this.Nl=b;if(null===a)throw null;this.vq=a}zO.prototype=new p;zO.prototype.constructor=zO;function Lt(a,b){var c=a.Nl.U(b);b=a.Nl.xj(b);a=new zO(a.vq,b);return G(new H,c,a)}\nfunction Mt(a){a.Nl.og(new fn((b,c)=>{var d=a.vq,e=new Te(new Ue(J(new K,[\"Unrecognized modifier `\",\"` in this position\"])));b=[We(Xe(),b)];e=Ye(e,J(new K,b));t();c=G(new H,e,new L(c));e=O().c;Ze(d,new z(c,e))}))}f=zO.prototype;f.H=function(){return\"ModifierSet\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Nl:$K(W(),a)};f.D=function(a){return a instanceof zO};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof zO&&a.vq===this.vq){var b=this.Nl;a=a.Nl;return null===b?null===a:b.i(a)}return!1};f.$classData=q({SW:0},!1,\"mlscript.NewParser$ModifierSet\",{SW:1,g:1,E:1,v:1,l:1});function DO(a,b){this.ix=null;this.wq=b;if(null===a)throw null;this.ix=a}DO.prototype=new p;DO.prototype.constructor=DO;function IO(a,b){for(b=b.wq;!b.b();){var c=b.e();a=new DO(a.ix,new z(c,a.wq));b=b.f()}return a}\nfunction HO(a,b,c,d,e){var g=a.ix;a=a.wq;for(var h=null,k=null;a!==u();){a:{var l=a.e(),m=b,n=c,r=d,v=e,x=tc();try{t();var A=l.Is,B=yw(l.Ls,m.Ls,n,r);if(B.b())throw Hq(new Iq,x,t().d);var C=B.o(),D=l.Ms.Ce(m.Ms),F=hw(l.Js,m.Js,n,r,v);if(F.b())throw Hq(new Iq,x,t().d);var I=F.o(),M=new CO(A,C,D,I,l.Ks.Ce(m.Ks));var N=new L(M)}catch(P){if(P instanceof Iq){N=P;if(N.Qg===x){N=N.Cj();break a}throw N;}throw P;}}for(x=N.m();x.s();)l=new z(x.t(),u()),null===k?h=l:k.p=l,k=l;a=a.f()}return new DO(g,null===\nh?u():h)}f=DO.prototype;f.u=function(){return\"CNF(\"+ze(this.wq,\"\",\" \\x26 \",\"\")+\")\"};f.H=function(){return\"CNF\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.wq:$K(W(),a)};f.D=function(a){return a instanceof DO};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof DO&&a.ix===this.ix){var b=this.wq;a=a.wq;return null===b?null===a:b.i(a)}return!1};f.$classData=q({WW:0},!1,\"mlscript.NormalForms$CNF\",{WW:1,g:1,E:1,v:1,l:1});\nfunction Oea(a){if(0===(2&a.Hs)<<24>>24){O();var b=new QX(J(new K,[a.Nf]));b=Kr(new Lr,b);b=new iy(b,new y(c=>Nm(new E(c),Vu(a.zb))),!1);b=kv(b,new U(()=>a.Pf)).nb(new U(()=>{O();var c=new QX(J(new K,[a.Of]));c=Kr(new Lr,c);c=new iy(c,new y(d=>Nm(new E(d),lw(a.zb))),!1);c=kv(c,new U(()=>a.Af));return new Ef(c,new y(d=>\"~(\"+d+\")\"))}));a.NH=ze(b,\"\",\"\\u2227\",\"\");a.Hs=(2|a.Hs)<<24>>24}return a.NH}\nfunction PO(a,b,c,d,e){this.yN=0;this.NH=null;this.Hs=0;this.zb=null;this.Nf=b;this.Pf=c;this.Of=d;this.Af=e;if(null===a)throw null;this.zb=a}PO.prototype=new p;PO.prototype.constructor=PO;function Pea(a,b){var c=oba(a.Nf,b.Nf);if(Nm(new E(c),0))return c;c=tba(a.Of,b.Of);if(Nm(new E(c),0))return c;c=-hv(a.Pf,b.Pf)|0;return Nm(new E(c),0)?c:c=-hv(a.Af,b.Af)|0}f=PO.prototype;\nf.zf=function(a){var b=new y(h=>h.zf(a));if(a){ms();ms();var c=this.Pf;if(0<=c.Q()){var d=c.Q();d=new (md(RX).Ia)(d);c.Gc(d,0,2147483647);c=d}else{d=null;d=[];for(c=c.m();c.s();){var e=c.t();d.push(null===e?null:e)}c=new (md(RX).Ia)(d)}d=Su();e=op().ga;c=Tu(c,new Uu(d,e));c=AG(c)}else c=this.Pf.m();c=c.nb(new U(()=>{O();var h=b.n(this.Of),k=V(h.q);h=[NA(h,k,!1)];h=J(new K,h);h=new QX(h);return Kr(new Lr,h)})).nb(new U(()=>{if(a){ms();ms();var h=this.Af;if(0<=h.Q()){var k=h.Q();k=new (md(RX).Ia)(k);\nh.Gc(k,0,2147483647);h=k}else{k=null;k=[];for(h=h.m();h.s();){var l=h.t();k.push(null===l?null:l)}h=new (md(RX).Ia)(k)}k=Su();l=op().ga;h=Tu(h,new Uu(k,l));h=AG(h)}else h=this.Af;return h.Ja(new y(m=>{var n=V(m.q);return NA(m,n,!1)}))}));for(d=this.Nf.zf(a);c.s();){e=c.t();var g=V(d.q);d=Pu(d,e,g,!1)}return d};\nfunction fca(a,b,c){ms();ms();var d=a.Pf;if(0<=d.Q()){var e=d.Q();e=new (md(RX).Ia)(e);d.Gc(e,0,2147483647);d=e}else{e=null;e=[];for(d=d.m();d.s();){var g=d.t();e.push(null===g?null:g)}d=new (md(RX).Ia)(e)}e=Su();g=op().ga;d=Tu(d,new Uu(e,g));d=AG(d).nb(new U(()=>{O();var h=c.n(a.Of),k=V(h.q);h=[NA(h,k,!1)];h=J(new K,h);h=new QX(h);return Kr(new Lr,h)})).nb(new U(()=>{ms();ms();var h=a.Af;if(0<=h.Q()){var k=h.Q();k=new (md(RX).Ia)(k);h.Gc(k,0,2147483647);h=k}else{k=null;k=[];for(h=h.m();h.s();){var l=\nh.t();k.push(null===l?null:l)}h=new (md(RX).Ia)(k)}k=Su();l=op().ga;h=Tu(h,new Uu(k,l));return AG(h).Ja(new y(m=>{var n=V(m.q);return NA(m,n,!1)}))}));for(b=b.n(a.Nf);d.s();)e=d.t(),g=V(b.q),b=Pu(b,e,g,!1);return b}f.Ea=function(){0===(1&this.Hs)<<24>>24&&0===(1&this.Hs)<<24>>24&&(this.yN=this.ub(this.zb.Df,jA().X()),this.Hs=(1|this.Hs)<<24>>24);return this.yN};\nf.ub=function(a,b){var c=this.Pf.m().nb(new U(()=>this.Af));c=new Ef(c,new y(e=>e.ub(a,b)));c=kv(c,new U(()=>{O();var e=[this.Nf.ub(a,b),this.Of.mc().ub(a,b)];e=J(new K,e);e=new QX(e);return Kr(new Lr,e)}));var d=Fq();return hH(c,d)|0};\nfunction dX(a,b,c,d,e){var g=a.Pf;g=PE().vl(g);g=Pt(g,new y(v=>{v=v.Kc(b,c,d,e);if(v instanceof lx)return t(),new fe(v);if(v instanceof Gv)return t(),new Ud(v);xm(\"Program reached and unexpected state.\")}));if(null===g)throw new w(g);var h=g.h(),k=g.j();g=a.Af;g=PE().vl(g);var l=Pt(g,new y(v=>{v=v.Kc(b,c,d,e);if(v instanceof lx)return t(),new fe(v);if(v instanceof Gv)return t(),new Ud(v);xm(\"Program reached and unexpected state.\")}));if(null===l)throw new w(l);g=l.h();var m=l.j();l=a.zb;var n=qba(a.Nf,\nb,c,d,e);for(k=k.m();k.s();){var r=k.t();n=rba(n,r)}k=n;n=Su();r=op().ga;n=new Uu(n,r);h=oA(uv(),h,n);n=a.Of.HJ(b,c,d,e);for(a=m.m();a.s();)m=n,n=a.t(),n=vba(m,n);a=n;m=Su();n=op().ga;m=new Uu(m,n);return new PO(l,k,h,a,oA(uv(),g,m))}function SX(a,b,c){return nw(b.Pf,a.Pf)&&mw(a.Nf,b.Nf,c)&&b.Of.Dw(a.Of,c)?nw(b.Af,a.Af):!1}\nfunction Qea(a,b,c,d){var e=tc();try{if(SX(a,b,c))return t(),new L(b);if(SX(b,a,c))return t(),new L(a);var g=a.Nf,h=a.Pf,k=a.Of,l=a.Af;if(Vu(a.zb)===g&&null!==b){var m=b.Nf,n=b.Pf,r=b.Of,v=b.Af;if(Vu(a.zb)===m&&Pe(new E(h),n)&&Pe(new E(l),v)){t();var x=a.zb,A=Vu(a.zb),B=uba(k,r,c);if(B.b())throw Hq(new Iq,e,t().d);var C=new PO(x,A,h,B.o(),l);return new L(C)}}var D=a.Nf,F=a.Pf,I=a.Of,M=a.Af;if(D instanceof Ku){var N=D.fc,P=D.vd,T=D.be,Y=D.Me;if(null!==b){var Z=b.Nf,S=b.Pf,ea=b.Of,ia=b.Af;if(Z instanceof\nKu){var X=Z.vd,sa=Z.be,Ja=Z.Me;if(Pe(new E(N),Z.fc)&&Pe(new E(P),X)&&Pe(new E(F),S)&&Pe(new E(I),ea)&&Pe(new E(M),ia))var Xa=Y.AB(),Fa=Pe(new E(Xa),Ja.AB());else Fa=!1;if(Fa){var za=Bw(a.zb,!0,Y,Ja,c),Qa=a.zb,Ma=RC(T.Ba,sa.Ba),Ga=new Qv(Qa,Ma,V(a.zb));t();var ab=new PO(a.zb,new Ku(a.zb,N,P,Ga,za),F,I,M);return new L(ab)}}}}var Hb=a.Nf,bc=a.Pf,yb=a.Of,tb=a.Af;if(Hb instanceof Ku){var eb=Hb.fc,kb=Hb.vd,Rb=Hb.be,Gb=Hb.Me;if(null!==b){var vb=b.Nf,Tb=b.Pf,Nb=b.Of,ic=b.Af;if(vb instanceof Ku){var Va=vb.fc,\ncb=vb.be,zb=vb.Me;if(Pe(new E(kb),vb.vd)&&Pe(new E(bc),Tb)&&Pe(new E(yb),Nb)&&Pe(new E(tb),ic)&&Pe(new E(Gb),zb)){var Ub=a.zb;if(Ev(d))var jb=Rb.Ba;else{if(eb.b())var db=R();else{var ub=eb.o();db=new L(ub.kq().Ba)}if(db.b())jb=Rb.Ba;else{var Aa=db.o();jb=Yv(Rb.Ba,Aa)}}if(Ev(d))var va=cb.Ba;else{if(Va.b())var Ra=R();else{var rb=Va.o();Ra=new L(rb.kq().Ba)}if(Ra.b())va=cb.Ba;else{var xb=Ra.o();va=Yv(cb.Ba,xb)}}var mc=RC(jb,va),Ha=new Qv(Ub,mc,V(a.zb));if(eb instanceof L){var Ka=eb.k;if(Ka instanceof\ncv){var Oa=Ka.Nb,Na=Ka.ac;if(Va instanceof L){var Da=Va.k;if(Da instanceof cv){var ta=Da.Nb,Ya=Da.ac;t();var dc=a.zb,ka=a.zb;t();var ya=a.zb,Sa=V(Oa.q),xc=Pu(Oa,ta,Sa,!1),Sb=V(Na.q),uc=dv(Na,Ya,Sb,!1),Lb=new cv(ya,xc,uc,V(a.zb)),lc=new PO(dc,new Ku(ka,new L(Lb),kb,Ha,Gb),bc,lw(a.zb),tb);return new L(lc)}}}}if(eb instanceof L){var Xb=eb.k;if(Xb instanceof zv){var ec=Xb.Yb;if(Va instanceof L){var Ab=Va.k;if(Ab instanceof zv){var Ob=Ab.Yb,fb=ec.K();if(Nm(new E(fb),Ob.K())){t();var Wa=a.zb,bb=a.zb;t();\nvar Ia=a.zb,Ua=Xb.Zj(),pc=Ab.Zj(),sc=Xb.Zj().Va,Ba=xw(Ua,pc,V(sc)),ob=new Sv(Ia,Ba,V(a.zb)),nc=new PO(Wa,new Ku(bb,new L(ob),kb,Ha,Gb),bc,lw(a.zb),tb);return new L(nc)}t();var Ib=a.zb,vc=a.zb;t();var Vb=a.zb,fc=TC(ec,Ob),Bc=new zv(Vb,fc,V(a.zb)),Pb=new PO(Ib,new Ku(vc,new L(Bc),kb,Ha,Gb),bc,lw(a.zb),tb);return new L(Pb)}}}}if(eb instanceof L){var Jb=eb.k;if(Jb instanceof zv&&Va instanceof L){var gc=Va.k;if(gc instanceof Sv){var Cb=gc.Fd;t();var cc=a.zb,yc=a.zb;t();var Mc=a.zb,qc=Jb.Zj(),oc=Jb.Zj().Va,\nQc=xw(qc,Cb,V(oc)),jc=new Sv(Mc,Qc,V(a.zb)),sb=new PO(cc,new Ku(yc,new L(jc),kb,Ha,Gb),bc,lw(a.zb),tb);return new L(sb)}}}if(eb instanceof L){var Gc=eb.k;if(Gc instanceof Sv){var Wb=Gc.Fd;if(Va instanceof L){var Cc=Va.k;if(Cc instanceof zv){t();var Fc=a.zb,qd=a.zb;t();var Yb=a.zb,Nc=Cc.Zj(),ad=Cc.Zj().Va,Uc=xw(Nc,Wb,V(ad)),cd=new Sv(Yb,Uc,V(a.zb)),kc=new PO(Fc,new Ku(qd,new L(cd),kb,Ha,Gb),bc,lw(a.zb),tb);return new L(kc)}}}}if(eb instanceof L){var Vc=eb.k;if(Vc instanceof Sv){var Hc=Vc.Fd;if(Va instanceof\nL){var rc=Va.k;if(rc instanceof Sv){var sd=rc.Fd;t();var Kc=a.zb,Qd=a.zb;t();var Ad=a.zb,kd=xw(Hc,sd,V(Hc.Va)),Hd=new Sv(Ad,kd,V(a.zb)),Rd=new PO(Kc,new Ku(Qd,new L(Hd),kb,Ha,Gb),bc,lw(a.zb),tb);return new L(Rd)}}}}var Bd=t().d===eb&&t().d===Va?!0:eb instanceof L&&eb.k instanceof cv&&Va instanceof L&&Va.k instanceof Vv?!0:eb instanceof L&&eb.k instanceof Vv&&Va instanceof L&&Va.k instanceof cv?!0:!1;if(Bd){t();var ae=new PO(a.zb,new Ku(a.zb,t().d,kb,Ha,Gb),bc,lw(a.zb),tb);return new L(ae)}}}}}return t().d}catch(od){if(od instanceof\nIq){var dd=od;if(dd.Qg===e)return dd.Cj();throw dd;}throw od;}}f.u=function(){return 0===(2&this.Hs)<<24>>24?Oea(this):this.NH};f.H=function(){return\"Conjunct\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.Nf;case 1:return this.Pf;case 2:return this.Of;case 3:return this.Af;default:return $K(W(),a)}};f.D=function(a){return a instanceof PO};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof PO&&a.zb===this.zb){var b=this.Nf,c=a.Nf;(null===b?null===c:b.i(c))?(b=this.Pf,c=a.Pf,b=null===b?null===c:b.i(c)):b=!1;if(b&&(b=this.Of,c=a.Of,null===b?null===c:b.i(c)))return b=this.Af,a=a.Af,null===b?null===a:b.i(a)}return!1};f.$classData=q({YW:0},!1,\"mlscript.NormalForms$Conjunct\",{YW:1,g:1,E:1,v:1,l:1});function TX(a,b){var c=a.xe.m();c=new Ef(c,new y(e=>e.ub(b,jA().X())));var d=Fq();c=Jq(c,d);return(c.b()?a.Gj.Gd:c.o())|0}\nfunction UX(a,b,c){var d=Xu().X();if(VX(a)<=b.fb&&VX(b)<=a.fb){c=a.fb;var e=b.fb;return new WX(c<e?c:e,a.xe,b.xe,a.Qf,b.Qf)}if(TX(a,b.fb)<=a.fb&&VX(a)<=b.fb)return new WX(b.fb,a.xe,b.xe,a.Qf,b.Qf);if(TX(b,a.fb)<=b.fb&&VX(b)<=a.fb)return new WX(a.fb,a.xe,b.xe,a.Qf,b.Qf);if(b.fb>a.fb){var g=new Iw(c.S,c.Ec,c.hc,c.Ed,1+b.fb|0,c.Pc,c.Zc,c.Lb,c.yc,c.tb,c.$a,c.od,c.cb);tp();c=a.fb;e=b.fb;up(0,Pe(new E(c>e?c:e),b.fb));c=a.fb;e=b.fb;var h=a.xe;if(h===u())var k=u();else{k=h.e();var l=k=new z(dX(k,a.fb,!1,\ng,d),u());for(h=h.f();h!==u();){var m=h.e();m=new z(dX(m,a.fb,!1,g,d),u());l=l.p=m;h=h.f()}}l=b.xe;lv();h=JF(lv(),a.Qf,new y(v=>v.Kc(a.fb,!1,g,d)));return new WX(c>e?c:e,k,l,ry(0,h,new y(v=>v.Kc(a.fb,!1,g,d))),b.Qf)}if(a.fb>b.fb){var n=new Iw(c.S,c.Ec,c.hc,c.Ed,1+a.fb|0,c.Pc,c.Zc,c.Lb,c.yc,c.tb,c.$a,c.od,c.cb);tp();c=a.fb;e=b.fb;up(0,Pe(new E(c>e?c:e),a.fb));c=a.fb;e=b.fb;k=a.xe;m=b.xe;if(m===u())l=u();else for(l=m.e(),h=l=new z(dX(l,b.fb,!1,n,d),u()),m=m.f();m!==u();){var r=m.e();r=new z(dX(r,b.fb,\n!1,n,d),u());h=h.p=r;m=m.f()}h=a.Qf;lv();b=JF(lv(),b.Qf,new y(v=>v.Kc(a.fb,!1,n,d)));return new WX(c>e?c:e,k,l,h,ry(0,b,new y(v=>v.Kc(a.fb,!1,n,d))))}tG||(tG=new sG);return cda(new WX(a.fb,a.xe,b.xe,a.Qf,b.Qf),Pe(new E(b.fb),a.fb))}function RO(a,b,c,d){this.Nm=this.zN=this.AN=this.BN=0;this.Gj=null;this.fb=b;this.Qf=c;this.xe=d;if(null===a)throw null;this.Gj=a;if(!(b<=a.Df))throw new Yj(\"assertion failed: \"+this.fb);}RO.prototype=new p;RO.prototype.constructor=RO;\nfunction VX(a){0===(1&a.Nm)<<24>>24&&0===(1&a.Nm)<<24>>24&&(a.BN=TX(a,a.fb),a.Nm=(1|a.Nm)<<24>>24);return a.BN}f=RO.prototype;\nf.zf=function(a){var b=vx(this.Gj),c=this.Qf;if(this.xe.b())var d=this.Gj.ib;else{if(a){d=this.xe;var e=ZA($A(this.Gj)),g=qw(d,e)}else g=this.xe;d=zx(this.Gj);e=this.fb;if(g===u())a=u();else{var h=g.e(),k=h=new z(h.zf(a),u());for(g=g.f();g!==u();){var l=g.e();l=new z(l.zf(a),u());k=k.p=l;g=g.f()}a=h}for(h=this.Gj.ib;!a.b();)k=a.e(),g=V(h.q),h=dv(h,k,g,!1),a=a.f();d=yx(d,e,h)}return wx(b,c,d)};\nf.Ea=function(){if(0===(2&this.Nm)<<24>>24&&0===(2&this.Nm)<<24>>24){var a=this.xe,b=Fq();if(a.b())b=R();else{if(a.b())throw nv(\"empty.maxBy\");var c=null;var d=null;var e;for(e=!0;!a.b();){var g=a.e(),h=g.Ea();if(e||0<b.Da(h,c))d=g,c=h,e=!1;a=a.f()}b=new L(d)}this.AN=b.b()?this.Gj.Gd:b.o().Ea();this.Nm=(2|this.Nm)<<24>>24}return this.AN};function qB(a){return a.Ea()>a.fb}\nfunction Aea(a,b){if(qB(a)){var c=Xu().X(),d=a.Qf,e=l=>{if(null!==l){var m=l.j();return G(new H,l.h().Kc(a.fb,!1,b,c),m.Kc(a.fb,!1,b,c))}throw new w(l);};if(d===u())e=u();else{var g=d.e(),h=g=new z(e(g),u());for(d=d.f();d!==u();){var k=d.e();k=new z(e(k),u());h=h.p=k;d=d.f()}e=g}d=a.xe;if(d===u())g=u();else for(g=d.e(),h=g=new z(dX(g,a.fb,!1,b,c),u()),d=d.f();d!==u();)k=d.e(),k=new z(dX(k,a.fb,!1,b,c),u()),h=h.p=k,d=d.f();return G(new H,e,g)}return G(new H,a.Qf,a.xe)}\nfunction eea(a,b,c,d,e){b=UX(a,b,d);if(null===b)throw new w(b);var g=b.hv|0,h=b.qt,k=b.kr,l=b.iv,m=b.jv;b=x=>{var A=new RO(a.Gj,g,dl(m,l),h),B=A.Gj,C=A.fb,D=A.Qf;A=A.xe;for(var F=null,I=null;A!==u();){a:{var M=A.e(),N=x,P=c,T=d,Y=e,Z=tc();try{if(M.Nf.Dw(N.Of,T))var S=t().d;else{t();var ea=$A(M.zb),ia=hw(M.Nf,N.Nf,P,T,Y);if(ia.b())throw Hq(new Iq,Z,t().d);var X=ia.o(),sa=M.Pf.Ce(N.Pf),Ja=yw(M.Of,N.Of,P,T);if(Ja.b())throw Hq(new Iq,Z,t().d);var Xa=Ja.o(),Fa=void 0,za=ea,Qa=X,Ma=sa,Ga=Xa,ab=M.Af.Ce(N.Af);\nM=P;var Hb=za.xq;if(Ga instanceof iw)var bc=new iw(za.xq,Ga.me,Ga.Ne);else if(Ga instanceof jw){var yb=Ga.mb,tb=Ga.Dc,eb=za.xq,kb=Ga.Xb;b:for(;;)if(kb.b()){Fa=u();break}else{var Rb=kb.e(),Gb=kb.f();if(!1===!yv(Qa,Rb,M,T,Y).b())kb=Gb;else for(za=kb,Ga=Gb;;){if(Ga.b())Fa=za;else{var vb=Ga.e();if(!1!==!yv(Qa,vb,M,T,Y).b()){Ga=Ga.f();continue}var Tb=new z(za.e(),u()),Nb=za.f();for(za=Tb;Nb!==Ga;){var ic=new z(Nb.e(),u());za=za.p=ic;Nb=Nb.f()}var Va=Ga.f();for(Ga=Va;!Va.b();){var cb=Va.e();if(!1===!yv(Qa,\ncb,M,T,Y).b()){for(;Ga!==Va;){var zb=new z(Ga.e(),u());za=za.p=zb;Ga=Ga.f()}Ga=Va.f()}Va=Va.f()}Ga.b()||(za.p=Ga);Fa=Tb}break b}}if(yb.b())var Ub=!0;else{var jb=yb.o();if(jb instanceof fe)Ub=!yv(Qa,jb.aa,M,T,Y).b();else{if(!(jb instanceof Ud))throw new w(jb);Ub=!0}}bc=new jw(eb,Fa,Ub?yb:R(),tb)}else if(lw(za.xq)===Ga)bc=lw(za.xq);else throw new w(Ga);var db=new PO(Hb,Qa,Ma,bc,ab);S=new L(db)}}catch(ub){if(ub instanceof Iq){S=ub;if(S.Qg===Z){S=S.Cj();break a}throw S;}throw ub;}}for(Z=S.m();Z.s();)Fa=\nnew z(Z.t(),u()),null===I?F=Fa:I.p=Fa,I=Fa;A=A.f()}return new RO(B,C,D,null===F?u():F)};if(k===u())b=u();else{var n=k.e(),r=n=new z(b(n),u());for(k=k.f();k!==u();){var v=k.e();v=new z(b(v),u());r=r.p=v;k=k.f()}b=n}for(n=SO(xB(a.Gj),!1);!b.b();)r=b.e(),n=UO(n,r,d,e),b=b.f();return n}\nfunction UO(a,b,c,d){var e=UX(a,b,c);if(null===e)throw new w(e);var g=e.qt;b=e.kr;e=new RO(a.Gj,e.hv|0,dl(e.jv,e.iv),g);for(a=b;!a.b();){var h=e,k=a.e(),l=c,m=d;b=h.Gj;e=h.fb;g=h.Qf;a:{var n=h.xe;for(h=O().c;;)if(n instanceof z){var r=n.z;n=n.p;if(SX(r,k,l)){h=Km(h);h=dl(new z(k,n),h);break a}if(SX(k,r,l)){h=Km(h);h=dl(new z(r,n),h);break a}var v=Qea(r,k,l,m);if(v instanceof L){k=v.k;h=Km(h);h=dl(new z(k,n),h);break a}if(R()===v)h=new z(r,h);else throw new w(v);}else{l=O().c;if(null===l?null===n:\nl.i(n)){h=Km(new z(k,h));break a}throw new w(n);}}e=new RO(b,e,g,h);a=a.f()}return e}f.u=function(){var a=this.fb,b=ze(this.xe,\"\",\" | \",\"\"),c=this.Qf.b()?\"\":\"{\"+ze(this.Qf,\"\",\", \",\"\")+\"}\";return\"DNF(\"+a+\", \"+b+\")\"+c};f.H=function(){return\"DNF\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.fb;case 1:return this.Qf;case 2:return this.xe;default:return $K(W(),a)}};f.D=function(a){return a instanceof RO};\nf.B=function(){var a=lb(\"DNF\");a=W().C(-889275714,a);var b=this.fb;a=W().C(a,b);b=this.Qf;b=My(W(),b);a=W().C(a,b);b=this.xe;b=My(W(),b);a=W().C(a,b);return W().Ma(a,3)};f.i=function(a){if(this===a)return!0;if(a instanceof RO&&a.Gj===this.Gj){if(this.fb===a.fb){var b=this.Qf,c=a.Qf;b=null===b?null===c:b.i(c)}else b=!1;if(b)return b=this.xe,a=a.xe,null===b?null===a:b.i(a)}return!1};f.$classData=q({aX:0},!1,\"mlscript.NormalForms$DNF\",{aX:1,g:1,E:1,v:1,l:1});\nfunction CO(a,b,c,d,e){this.Is=null;this.Ls=b;this.Ms=c;this.Js=d;this.Ks=e;if(null===a)throw null;this.Is=a}CO.prototype=new p;CO.prototype.constructor=CO;f=CO.prototype;\nf.u=function(){O();var a=new QX(J(new K,[this.Ls]));a=Kr(new Lr,a);a=new iy(a,new y(b=>Nm(new E(b),lw(this.Is))),!1);a=kv(a,new U(()=>this.Ms)).nb(new U(()=>{O();var b=new QX(J(new K,[this.Js]));b=Kr(new Lr,b);b=new iy(b,new y(c=>Nm(new E(c),Vu(this.Is))),!1);b=kv(b,new U(()=>this.Ks));return new Ef(b,new y(c=>\"~\"+c))}));return ze(a,\"\",\"\\u2228\",\"\")};f.H=function(){return\"Disjunct\"};f.G=function(){return 4};\nf.I=function(a){switch(a){case 0:return this.Ls;case 1:return this.Ms;case 2:return this.Js;case 3:return this.Ks;default:return $K(W(),a)}};f.D=function(a){return a instanceof CO};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof CO&&a.Is===this.Is){var b=this.Ls,c=a.Ls;(null===b?null===c:b.i(c))?(b=this.Ms,c=a.Ms,b=null===b?null===c:b.i(c)):b=!1;if(b&&(b=this.Js,c=a.Js,null===b?null===c:b.i(c)))return b=this.Ks,a=a.Ks,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({cX:0},!1,\"mlscript.NormalForms$Disjunct\",{cX:1,g:1,E:1,v:1,l:1});function az(a,b,c,d,e,g,h,k){this.Sz=null;this.Eq=b;this.Os=c;this.Hu=d;this.Gu=e;this.Qs=g;this.Ps=h;this.Rm=k;if(null===a)throw null;this.Sz=a}az.prototype=new p;az.prototype.constructor=az;f=az.prototype;f.H=function(){return\"Pack\"};f.G=function(){return 7};\nf.I=function(a){switch(a){case 0:return this.Eq;case 1:return this.Os;case 2:return this.Hu;case 3:return this.Gu;case 4:return this.Qs;case 5:return this.Ps;case 6:return this.Rm;default:return $K(W(),a)}};f.D=function(a){return a instanceof az};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof az){var b=this.Eq,c=a.Eq;(null===b?null===c:mC(b,c))?(b=this.Os,c=a.Os,b=null===b?null===c:b.i(c)):b=!1;b?(b=this.Hu,c=a.Hu,(null===b?null===c:b.i(c))?(b=this.Gu,c=a.Gu,b=null===b?null===c:b.i(c)):b=!1):b=!1;if(b&&(b=this.Qs,c=a.Qs,(null===b?null===c:b.i(c))?(b=this.Ps,c=a.Ps,b=null===b?null===c:b.i(c)):b=!1,b))return b=this.Rm,a=a.Rm,null===b?null===a:mC(b,a)}return!1};\nf.$classData=q({uX:0},!1,\"mlscript.NuTypeDefs$DelayedTypeInfoImpl$Pack$1\",{uX:1,g:1,E:1,v:1,l:1});function Xy(a){this.GN=null;if(null===a)throw null;this.GN=a}Xy.prototype=new mS;Xy.prototype.constructor=Xy;Xy.prototype.u=function(){return\"Pack\"};function Nba(a,b,c,d,e,g,h,k){return new az(a.GN,b,c,d,e,g,h,k)}Xy.prototype.$classData=q({vX:0},!1,\"mlscript.NuTypeDefs$DelayedTypeInfoImpl$Pack$2$\",{vX:1,aca:1,g:1,raa:1,l:1});\nfunction XX(a,b,c){this.PH=null;this.uE=b;this.Uz=c;if(null===a)throw null;this.PH=a}XX.prototype=new p;XX.prototype.constructor=XX;f=XX.prototype;f.H=function(){return\"RefMap\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.uE;case 1:return this.Uz;default:return $K(W(),a)}};f.D=function(a){return a instanceof XX};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof XX&&a.PH===this.PH){var b=this.uE,c=a.uE;if(null===b?null===c:b.i(c))return b=this.Uz,a=a.Uz,null===b?null===a:b.i(a)}return!1};f.$classData=q({xX:0},!1,\"mlscript.NuTypeDefs$RefMap\",{xX:1,g:1,E:1,v:1,l:1});function Ge(a,b,c){this.Wz=a;this.rx=b;this.Us=c}Ge.prototype=new p;Ge.prototype.constructor=Ge;f=Ge.prototype;f.u=function(){return this.Wz+\":+\"+this.rx};f.H=function(){return\"Origin\"};f.G=function(){return 3};\nf.I=function(a){switch(a){case 0:return this.Wz;case 1:return this.rx;case 2:return this.Us;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ge};f.B=function(){var a=lb(\"Origin\");a=W().C(-889275714,a);var b=this.Wz;b=My(W(),b);a=W().C(a,b);b=this.rx;a=W().C(a,b);b=this.Us;b=My(W(),b);a=W().C(a,b);return W().Ma(a,3)};f.i=function(a){return this===a?!0:a instanceof Ge?this.rx===a.rx?this.Wz===a.Wz?this.Us===a.Us:!1:!1:!1};f.$classData=q({LX:0},!1,\"mlscript.Origin\",{LX:1,g:1,E:1,v:1,l:1});\nfunction aP(a,b,c,d,e){this.QN=null;this.bI=!1;this.kp=a;this.$z=b;this.xx=c;this.fi=d;this.Jq=e}aP.prototype=new p;aP.prototype.constructor=aP;function yP(a){a.bI||a.bI||(a.QN=ut(Q(),\"  \",a.xx),a.bI=!0);return a.QN}function ON(a){return\"\\n\"+yP(a)}function AP(a){return new aP(a.kp,a.$z,1+a.xx|0,a.fi,a.Jq)}f=aP.prototype;f.H=function(){return\"ShowCtx\"};f.G=function(){return 5};\nf.I=function(a){switch(a){case 0:return this.kp;case 1:return this.$z;case 2:return this.xx;case 3:return this.fi;case 4:return this.Jq;default:return $K(W(),a)}};f.D=function(a){return a instanceof aP};f.B=function(){var a=lb(\"ShowCtx\");a=W().C(-889275714,a);var b=this.kp;b=My(W(),b);a=W().C(a,b);b=this.$z?1231:1237;a=W().C(a,b);b=this.xx;a=W().C(a,b);b=this.fi?1231:1237;a=W().C(a,b);b=this.Jq?1231:1237;a=W().C(a,b);return W().Ma(a,5)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof aP&&this.$z===a.$z&&this.xx===a.xx&&this.fi===a.fi&&this.Jq===a.Jq){var b=this.kp;a=a.kp;return null===b?null===a:b.i(a)}return!1};f.$classData=q({fY:0},!1,\"mlscript.ShowCtx\",{fY:1,g:1,E:1,v:1,l:1});\nfunction YX(a,b,c,d,e,g,h,k,l,m,n){this.FE=this.Nu=this.UN=this.VN=null;this.jj=b;this.Wl=c;this.Xm=d;this.Cx=e;this.hI=g;this.iI=h;this.Bx=k;this.GE=l;this.at=m;this.gI=n;if(null===a)throw null;this.FE=a;a=op();d=d.Gb(a.ga);a:{if(null!==d&&(a=d.h(),b=d.j(),null!==a&&null!==b)){d=G(new H,a,b);break a}throw new w(d);}this.VN=d;this.UN=this.VN.j();this.Nu=t().d}YX.prototype=new p;YX.prototype.constructor=YX;\nfunction ZX(a,b,c){var d=a.Bx.Ja(new y(e=>new Ep(e.V)));a=a.Bx.m();a=new iy(a,c,!0);a=new xo(a,new y(e=>{var g=b.tb.U(e.V);return g.b()?ap():ZX(g.o(),b,c.bc(e))}));return d.Ce(a)}function dB(a){a=a.Nu;if(a.b()){a=nf();var b=ou().Yl;a=$X(a,b)}else a=a.o();return a}f=YX.prototype;f.H=function(){return\"TypeDef\"};f.G=function(){return 10};\nf.I=function(a){switch(a){case 0:return this.jj;case 1:return this.Wl;case 2:return this.Xm;case 3:return this.Cx;case 4:return this.hI;case 5:return this.iI;case 6:return this.Bx;case 7:return this.GE;case 8:return this.at;case 9:return this.gI;default:return $K(W(),a)}};f.D=function(a){return a instanceof YX};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof YX&&a.FE===this.FE){if(this.jj===a.jj){var b=this.Wl,c=a.Wl;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.Xm,c=a.Xm,(null===b?null===c:b.i(c))?(b=this.Cx,c=a.Cx,(null===b?null===c:mC(b,c))?(b=this.hI,c=a.hI,b=null===b?null===c:b.i(c)):b=!1):b=!1):b=!1;if(b&&(b=this.iI,c=a.iI,(null===b?null===c:b.i(c))?(b=this.Bx,c=a.Bx,(null===b?null===c:b.i(c))?(b=this.GE,c=a.GE,b=null===b?null===c:b.i(c)):b=!1):b=!1,b&&(b=this.at,c=a.at,null===b?null===c:b.i(c))))return b=\nthis.gI,a=a.gI,null===b?null===a:b.i(a)}return!1};f.$classData=q({vY:0},!1,\"mlscript.TypeDefs$TypeDef\",{vY:1,g:1,E:1,v:1,l:1});function aY(a){if(null===a)throw null;}aY.prototype=new eS;aY.prototype.constructor=aY;aY.prototype.u=function(){return\"TypeDef\"};aY.prototype.$classData=q({wY:0},!1,\"mlscript.TypeDefs$TypeDef$\",{wY:1,Yba:1,g:1,oaa:1,l:1});function bY(){}bY.prototype=new cS;bY.prototype.constructor=bY;bY.prototype.u=function(){return\"TypeName\"};bY.prototype.n=function(a){return new Ep(a)};\nbY.prototype.$classData=q({DY:0},!1,\"mlscript.TypeName$\",{DY:1,dM:1,g:1,la:1,l:1});\nvar cY,Sea=function Rea(a,b){var d=a.Ed.U(b);return d.b()?(a=(new Dx(a.Ec)).wF,a.b()?b=t().d:(a=a.o(),b=Rea(a,b)),b):d},uC=function dY(a,b,c){for(;;){if(Pe(new E(a.Lb),b.Lb)){var e=b.hc.U(c);if(e.b()){e=b.Ec;if(e.b())return R();e=e.o();return dY(a,e,c)}return e}if(a.Lb)if(e=b.Ec,e instanceof L)b=e.k;else return b.hc.U(c);else{e=b.hc.U(c);if(e instanceof L&&(e=e.k,e instanceof qx)){e=e.tp;var g=eY(b,c);if(g instanceof L){b=g.k;t();var h=g=a.S,k=new Ep(\"Var\"),l=O().c;a=new qx(g,new fw(h,k,new z(e,new z(b,\nl)),V(a.S)),new vl(c));return new L(a)}e=b.Ec;if(e.b())return R();e=e.o();return dY(a,e,c)}e=b.Ec;if(e.b())return R();e=e.o();return dY(a,e,c)}}};function Iw(a,b,c,d,e,g,h,k,l,m,n,r,v){this.S=this.$N=null;this.Ec=b;this.hc=c;this.Ed=d;this.da=e;this.Pc=g;this.Zc=h;this.Lb=k;this.yc=l;this.tb=m;this.$a=n;this.od=r;this.cb=v;if(null===a)throw null;this.S=a;this.$N=Xu().X()}Iw.prototype=new p;Iw.prototype.constructor=Iw;\nfunction Wx(a,b){a.hc.$(b);if(a.Lb){var c=a.S,d=a.S,e=V(a.S),g=t().d;t();var h=new L(b.h()),k=O().c,l=O().c;c=new mx(c,new lx(d,a.da,k,l,g,h,!1,e),V(a.S));d=a.S;d.F&&(d=ut(Q(),\"| \",d.r)+(\"Create skolem tag \"+c+\" for \"+b.j())+\" in quasiquote.\",ff(gf(),d+\"\\n\"));a=a.Pc;b=G(new H,b.h(),c);a.$(b)}}function Jw(a,b){for(b=b.m();b.s();){var c=b.t();Wx(a,c)}}function eY(a,b){var c=a.Pc.U(b);return c.b()?(a=(new Dx(a.Ec)).wF,a.b()?t().d:eY(a.o(),b)):c}\nfunction Tea(a,b){for(a=a.Pc.m();a.s();){var c=a.t(),d=c;c=d.j();d=V(d.j().q);b=dv(c,b,d,!1)}return b}function fY(a){var b=a.S.ib;for(a=new qA(a.Zc);a.s();){var c=a.t(),d=V(b.q);b=dv(b,c,d,!1)}return b}function gY(a,b){var c=a.S;c.F&&(c=ut(Q(),\"| \",c.r)+\"Capture free variable type \"+b,ff(gf(),c+\"\\n\"));FB(a.Zc,b)}function hY(a,b,c){t();b=G(new H,b,c);return Sea(a,new Ud(b))}\nfunction tf(a){up(tp(),!a.Lb);var b=new L(a),c=Xu().X(),d=Xu().X();return new Iw(a.S,b,c,d,a.da,a.Pc,a.Zc,a.Lb,a.yc,a.tb,a.$a,a.od,a.cb)}function iY(a){var b=new L(a),c=Xu().X(),d=Xu().X(),e=1+a.da|0,g=Xu().X(),h=new MB;return new Iw(a.S,b,c,d,e,g,h,!0,a.yc,a.tb,a.$a,a.od,a.cb)}function Uea(a){var b=new L(a),c=Xu().X(),d=Xu().X();return new Iw(a.S,b,c,d,a.da,a.Pc,a.Zc,!1,a.yc,a.tb,a.$a,a.od,a.cb)}\nfunction Sx(a,b,c,d){var e=1+a.da|0,g=Hw(),h=Su(),k=op().ga;g=g.Hd(new Uu(h,k));g=new Iw(a.S,a.Ec,a.hc,a.Ed,e,a.Pc,a.Zc,a.Lb,a.yc,a.tb,a.$a,a.od,g);b=b.n(g);e=g.cb;up(tp(),a.S.li||g.cb.b());if(!e.b()){g=a.S.qa;h=a.S;h.F&&(k=ut(Q(),\"| \",h.r)+\"UNSTASHING... (out)\",ff(gf(),k+\"\\n\"));h.r=1+h.r|0;try{e.Ca(new y(m=>{if(null!==m){var n=m.h();for(m=m.j().m();m.s();){var r=m.t();a:{if(null!==r){var v=r.j();if(!0===r.Rc()){r=Sw(a.S).ob;Tw(a.S,v,n,c,d,a,r);break a}}if(null!==r&&(v=r.j(),!1===r.Rc())){r=Sw(a.S).ob;\nTw(a.S,n,v,c,d,a,r);break a}throw new w(r);}}}else throw new w(m);}));e.mg();var l=void 0}finally{h.r=-1+h.r|0}dx(new E(g),h.qa)&&h.F&&(l=\"\"+ut(Q(),\"| \",h.r)+g.n(l),ff(gf(),l+\"\\n\"))}return b}\nfunction Px(a,b,c,d){var e=1+a.da|0,g=Hw(),h=Su(),k=op().ga;g=g.Hd(new Uu(h,k));e=new Iw(a.S,a.Ec,a.hc,a.Ed,e,a.Pc,a.Zc,a.Lb,a.yc,a.tb,a.$a,a.od,g);b=b.n(e);up(tp(),a.S.li||e.cb.b());Xu().X();g=vx(a.S);h=e.cb.m();h=new xo(h,new y(m=>{if(null!==m){var n=m.h();m=m.j().m();return new Ef(m,new y(r=>{if(null!==r){var v=r.Rc();r=r.j();up(tp(),r.Ea()>a.da);return v?G(new H,r,n):G(new H,n,r)}throw new w(r);}))}throw new w(m);}));Od();b=wx(g,Pd(u(),h),b);g=a.S;g.F&&(g=ut(Q(),\"| \",g.r)+(\"Inferred poly constr: \"+\nb+\"  \\u2014\\u2014 where \")+xx(b),ff(gf(),g+\"\\n\"));a.S.F&&Nm(new E(b),b)&&(g=a.S,g.F&&(g=ut(Q(),\"| \",g.r)+(\"Refreshed:            \"+b+\"  \\u2014\\u2014 where \")+xx(b),ff(gf(),g+\"\\n\")));b=yx(zx(a.S),a.da,b);e.cb.mg();g=e.cb;up(tp(),a.S.li||e.cb.b());if(!g.b()){e=a.S.qa;h=a.S;h.F&&(k=ut(Q(),\"| \",h.r)+\"UNSTASHING... (out)\",ff(gf(),k+\"\\n\"));h.r=1+h.r|0;try{g.Ca(new y(m=>{if(null!==m){var n=m.h();for(m=m.j().m();m.s();){var r=m.t();a:{if(null!==r){var v=r.j();if(!0===r.Rc()){r=Sw(a.S).ob;Tw(a.S,v,n,c,d,a,\nr);break a}}if(null!==r&&(v=r.j(),!1===r.Rc())){r=Sw(a.S).ob;Tw(a.S,n,v,c,d,a,r);break a}throw new w(r);}}}else throw new w(m);}));g.mg();var l=void 0}finally{h.r=-1+h.r|0}dx(new E(e),h.qa)&&h.F&&(l=\"\"+ut(Q(),\"| \",h.r)+e.n(l),ff(gf(),l+\"\\n\"))}return b}function jY(a,b){return a.$N.Hk(b,new U(()=>{var c=a.tb.U(b);return c.b()?ap():ZX(c.o(),a,ap())}))}f=Iw.prototype;f.H=function(){return\"Ctx\"};f.G=function(){return 12};\nf.I=function(a){switch(a){case 0:return this.Ec;case 1:return this.hc;case 2:return this.Ed;case 3:return this.da;case 4:return this.Pc;case 5:return this.Zc;case 6:return this.Lb;case 7:return this.yc;case 8:return this.tb;case 9:return this.$a;case 10:return this.od;case 11:return this.cb;default:return $K(W(),a)}};f.D=function(a){return a instanceof Iw};\nf.B=function(){var a=lb(\"Ctx\");a=W().C(-889275714,a);var b=this.Ec;b=My(W(),b);a=W().C(a,b);b=this.hc;b=My(W(),b);a=W().C(a,b);b=this.Ed;b=My(W(),b);a=W().C(a,b);b=this.da;a=W().C(a,b);b=this.Pc;b=My(W(),b);a=W().C(a,b);b=this.Zc;b=My(W(),b);a=W().C(a,b);b=this.Lb?1231:1237;a=W().C(a,b);b=this.yc?1231:1237;a=W().C(a,b);b=this.tb;b=My(W(),b);a=W().C(a,b);b=this.$a;b=My(W(),b);a=W().C(a,b);b=this.od;b=My(W(),b);a=W().C(a,b);b=this.cb;b=My(W(),b);a=W().C(a,b);return W().Ma(a,12)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Iw&&a.S===this.S){if(this.da===a.da&&this.Lb===a.Lb&&this.yc===a.yc){var b=this.Ec,c=a.Ec;(null===b?null===c:b.i(c))?(b=this.hc,c=a.hc,(null===b?null===c:b.i(c))?(b=this.Ed,c=a.Ed,b=null===b?null===c:b.i(c)):b=!1):b=!1}else b=!1;if(b&&(b=this.Pc,c=a.Pc,(null===b?null===c:b.i(c))?(b=this.Zc,c=a.Zc,(null===b?null===c:kY(b,c))?(b=this.tb,c=a.tb,b=null===b?null===c:b.i(c)):b=!1):b=!1,b&&(b=this.$a,c=a.$a,(null===b?null===c:b.i(c))?(b=this.od,c=a.od,\nb=null===b?null===c:b.i(c)):b=!1,b)))return b=this.cb,a=a.cb,null===b?null===a:lY(b,a)}return!1};f.$classData=q({OY:0},!1,\"mlscript.Typer$Ctx\",{OY:1,g:1,E:1,v:1,l:1});\nfunction fx(a,b,c,d,e){this.J=null;this.ct=!1;this.eo=null;this.Ru=0;this.uO=this.dt=this.jg=this.sO=this.Qu=null;this.LE=!1;this.AO=null;this.wI=!1;this.yO=this.iO=this.vO=this.lO=this.BO=this.kO=this.CO=this.qO=this.tO=this.zO=this.pO=this.jO=this.xO=this.wO=this.mO=null;this.nO=!1;this.oO=this.rO=null;this.Ha=0;this.Ab=b;this.fZ=c;this.cd=d;this.ne=e;FC(this,a);this.ct=!1;this.eo=t().d;this.Ru=this.cd.da;this.Qu=this.Ab.fd();this.sO=this.Ab.Cf.x;a=this.J;b=this.Ab.A();this.jg=jx(new kx,a,b,cy(this.Ab),\n(tx(this.J),t().d),(tx(this.J),!1));this.dt=nf();a=this.J;a.F&&(a=ut(Q(),\"| \",a.r)+(this.cd.da+\". Created lazy type info for \")+this.Ab,ff(gf(),a+\"\\n\"));this.wI=this.LE=!1}fx.prototype=new WP;fx.prototype.constructor=fx;f=fx.prototype;f.u=function(){var a=this.Ab.Cf.x;if(this.ct)var b=\"\\x3ccomputing\\x3e\";else b=this.eo,b=b.b()?\"\\x3cuncomputed\\x3e\":b.o().u();return a+\" ~\\x3e \"+b};f.fd=function(){return this.Qu};\nfunction Mw(a){if(0===(1&a.Ha)&&0===(1&a.Ha)){var b=a.Ab;if(b instanceof yo){b=b.Di;for(var c=null,d=null;b!==u();){var e=b.e(),g=!1,h=null;b:if(e instanceof vl)h=e,t(),h=new Gp(h,h,O().c,O().c),h=new L(h);else{if(e instanceof Pl){g=!0;h=e;var k=h.Za,l=h.Qb;if(k instanceof vl&&l instanceof Gl){e=l.Ra;t();h=new Gp(h,k,O().c,e);h=new L(h);break b}}if(e instanceof Il&&(k=e,l=k.nl,k=k.np,l instanceof vl)){h=l;t();h=new Gp(h,h,k,O().c);h=new L(h);break b}if(g&&(l=h.Za,g=h.Qb,l instanceof Il&&(k=l.nl,l=\nl.np,k instanceof vl&&g instanceof Gl))){e=g.Ra;t();h=new L(new Gp(h,k,l,e));break b}Lw(a.J,Ye(new Te(new Ue(J(new K,[\"Unsupported parent specification\"]))),u()),e.A(),a.ne);h=t().d}for(h=h.m();h.s();)e=new z(h.t(),u()),null===d?c=e:d.p=e,d=e;b=b.f()}b=null===c?u():c;for(d=c=null;b!==u();){k=b.e();b:{if(null!==k&&(h=k.Uj,e=k.oj,g=k.oi,l=k.Xi,null!==e)){k=e.x;var m=!1,n=a.cd;n=uC(n,n,k);if(n instanceof L){m=!0;var r=n;r=r.k;if(r instanceof VP){k=r;t();h=new L(new WX(h,e,k,g,l));break b}}if(m){Lw(a.J,\nYe(new Te(new Ue(J(new K,[\"Cannot inherit from this\"]))),u()),h.A(),a.ne);h=t().d;break b}if(t().d===n){e=a.J;g=new Te(new Ue(J(new K,[\"Could not find definition `\",\"`\"])));l=[We(Xe(),k)];Lw(e,Ye(g,J(new K,l)),h.A(),a.ne);h=t().d;break b}throw new w(n);}throw new w(k);}for(h=h.m();h.s();)e=new z(h.t(),u()),null===d?c=e:d.p=e,d=e;b=b.f()}b=null===c?u():c}else b=O().c;a.uO=b;a.Ha|=1}return a.uO}function Hx(a){0===(2&a.Ha)&&0===(2&a.Ha)&&(a.AO=wba(a),a.Ha|=2);return a.AO}\nfunction gx(a){if(0===(4&a.Ha)&&0===(4&a.Ha)){if(a.wI)var b=ap();else{a.wI=!0;b=Mw(a);var c=ap();b=xba(a,b,c)}a.mO=b;a.Ha|=4}return a.mO}f.Ag=function(){0===(8&this.Ha)&&0===(8&this.Ha)&&(this.wO=yba(this),this.Ha|=8);return this.wO};function Tx(a){0===(16&a.Ha)&&0===(16&a.Ha)&&(a.xO=zba(a),a.Ha|=16);return a.xO}function VD(a){0===(32&a.Ha)&&0===(32&a.Ha)&&(a.jO=Aba(a),a.Ha|=32);return a.jO}function Ow(a){0===(64&a.Ha)&&0===(64&a.Ha)&&(a.pO=a.fZ.bf(Tx(a)),a.Ha|=64);return a.pO}\nfunction px(a){0===(128&a.Ha)&&0===(128&a.Ha)&&(a.zO=Bba(a),a.Ha|=128);return a.zO}function Kw(a){0===(256&a.Ha)&&0===(256&a.Ha)&&(a.tO=Cba(a),a.Ha|=256);return a.tO}function mY(a){0===(512&a.Ha)&&0===(512&a.Ha)&&(a.qO=Dba(a),a.Ha|=512);return a.qO}function Ax(a){0===(1024&a.Ha)&&0===(1024&a.Ha)&&(a.CO=mY(a).h(),a.Ha|=1024);return a.CO}function Fba(a){0===(2048&a.Ha)&&0===(2048&a.Ha)&&(a.kO=mY(a).j(),a.Ha|=2048);return a.kO}\nfunction Zx(a){0===(4096&a.Ha)&&0===(4096&a.Ha)&&(a.BO=Eba(a),a.Ha|=4096);return a.BO}function Gx(a){0===(8192&a.Ha)&&0===(8192&a.Ha)&&(a.lO=Gba(a),a.Ha|=8192);return a.lO}function fy(a){0===(16384&a.Ha)&&0===(16384&a.Ha)&&(a.vO=Hba(a),a.Ha|=16384);return a.vO}function Bx(a){0===(32768&a.Ha)&&0===(32768&a.Ha)&&(a.iO=Iba(a),a.Ha|=32768);return a.iO}function Rx(a){0===(131072&a.Ha)&&0===(131072&a.Ha)&&(a.nO=Kba(a),a.Ha|=131072);return a.nO}\nfunction Ux(a){if(0===(262144&a.Ha)&&0===(262144&a.Ha)){var b;if(a.Ab instanceof Zn){var c=b=a.J,d=a.Ab.A(),e=cy(a.Ab);t();c=jx(new kx,c,d,e,new L(a.Ab.Cf.x),a.Ab instanceof yo);d=t().d;t();e=new L(a.Ab.Cf.x);var g=O().c,h=O().c,k=Rx(a)?1+a.Ru|0:a.Ru;b=new lx(b,k,g,h,d,e,!1,c)}else xm(\"Not supposed to use mutRecTV for \"+a.Ab.fd()),b=void 0;a.rO=b;a.Ha|=262144}return a.rO}\nfunction Vx(a){if(0===(524288&a.Ha)&&0===(524288&a.Ha)){var b=a.J;var c=V(a.J),d=t().d;t();var e=UF(ve(),a.Ab.Cf.x);e=new L(e);var g=O().c,h=O().c;b=new lx(b,1+a.cd.da|0,g,h,d,e,!1,c);a.oO=b;a.Ha|=524288}return a.oO}f.fQ=function(a){return Kx(this,a)};f.$classData=q({dZ:0},!1,\"mlscript.TyperDatatypes$DelayedTypeInfo\",{dZ:1,nZ:1,UO:1,g:1,Eaa:1});function Uw(a,b,c,d){this.Va=null;this.Oa=b;this.ra=c;this.Pd=d;if(null===a)throw null;this.Va=a}Uw.prototype=new p;Uw.prototype.constructor=Uw;f=Uw.prototype;\nf.Ea=function(){var a=this.Oa;a.b()?a=R():(a=a.o(),a=new L(a.Ea()));a=(a.b()?this.ra.Ea():a.o())|0;var b=this.ra.Ea();return a>b?a:b};f.ub=function(a,b){var c=this.Oa;c=c.b()?this.Va.Gd:c.o().ub(a,b);a=this.ra.ub(a,b);return c>a?c:a};function Fw(a,b,c,d){var e=b.Oa;e=e.b()?a.Va.ib:e.o();var g=a.Oa;g=g.b()?a.Va.ib:g.o();return Zu(e,g,c,!0,d)?Zu(a.ra,b.ra,c,!0,d):!1}\nfunction Nv(a,b,c){var d=a.Va,e=a.Oa;if(e.b())e=b.Oa;else{e=e.o();var g=b.Oa;if(!g.b()){g=g.o();var h=V(e.q);e=dv(e,g,h,!1)}e=new L(e)}g=a.ra;b=b.ra;a=V(a.ra.q);return new Uw(d,e,Pu(g,b,a,!1),c)}function xw(a,b,c){var d=a.Va,e=a.Oa;if(e.b())e=R();else{e=e.o();var g=b.Oa;if(g.b())e=R();else{g=g.o();var h=V(e.q);e=new L(Pu(e,g,h,!1))}}g=a.ra;b=b.ra;a=V(a.ra.q);return new Uw(d,e,dv(g,b,a,!1),c)}function cB(a,b,c){var d=a.Oa;return new Uw(a.Va,d.b()?R():new L(b.n(d.o())),c.n(a.ra),a.Pd)}\nfunction LX(a,b,c,d,e){var g=a.Va,h=a.Oa;h.b()?h=R():(h=h.o(),h=new L(h.Kc(b,c,d,e)));return new Uw(g,h,a.ra.Kc(b,c,d,e),a.Pd)}f.u=function(){var a=this.Oa;if(a.b())return\"\"+this.ra;a=a.o();return\"mut \"+(Pe(new E(a),this.Va.ib)?\"\":a)+\"..\"+this.ra};f.H=function(){return\"FieldType\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Oa;case 1:return this.ra;default:return $K(W(),a)}};f.D=function(a){return a instanceof Uw};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Uw&&a.Va===this.Va){var b=this.Oa,c=a.Oa;if(null===b?null===c:b.i(c))return b=this.ra,a=a.ra,null===b?null===a:mC(b,a)}return!1};f.$classData=q({kZ:0},!1,\"mlscript.TyperDatatypes$FieldType\",{kZ:1,g:1,E:1,v:1,l:1});function nY(a){a=a.AK().m();a=new Ef(a,new y(b=>new vl(b.V)));return Aq(Bq(),a)}function oY(a){var b=a.rr().Dh;a=a.AK().Ja(new y(c=>c.V));return\"#\"+(b+(\"\\x3c\"+ze(a,\"\",\",\",\"\"))+\"\\x3e\")}\nfunction XB(a){return!!(a&&a.$classData&&a.$classData.rb.KO)}function pY(a,b){if(null===b)throw null;a.q=b;a.Be=a.q.Im;a.pe=-1+a.Be|0;a.oe=a;b.Fp=1+b.Fp|0}function zA(){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0}zA.prototype=new YP;zA.prototype.constructor=zA;function qY(){}qY.prototype=zA.prototype;zA.prototype.i=function(a){return mC(this,a)};\nzA.prototype.B=function(){if(0===(1&this.dd)<<24>>24&&0===(1&this.dd)<<24>>24){if(this instanceof lx)var a=this.sp;else if(this instanceof OA)a=this.Hi.B();else if(null!==this&&Gs(this))a=AL(this);else throw new w(this);this.ze=a;this.dd=(1|this.dd)<<24>>24}return this.ze};function pD(a){if(0===(2&a.dd)<<24>>24&&0===(2&a.dd)<<24>>24){a:if(a instanceof cC)var b=!0;else{for(b=ED(a,!1);!b.b();){if(pD(b.e())){b=!0;break a}b=b.f()}b=!1}a.Ae=b;a.dd=(2|a.dd)<<24>>24}return a.Ae}\nzA.prototype.Kc=function(a,b,c,d){var e=this.q,g=this.q.Df,h=ap();return fD(e,this,g,c,a,h,d,b)};zA.prototype.rT=function(){return uy(this)};function jx(a,b,c,d,e,g){a.Ga=c;a.lh=d;a.go=e;a.Zm=g;if(null===b)throw null;a.Wu=b;a.Ix=!e.b();return a}function kx(){this.go=this.lh=this.Ga=null;this.Ix=this.Zm=!1;this.Wu=null}kx.prototype=new p;kx.prototype.constructor=kx;function rY(){}f=rY.prototype=kx.prototype;\nf.u=function(){var a=this.Ix?\"o: \":\"\",b=this.Ga;b.b()?b=this.lh:(b=b.o(),b=this.lh+\":\"+b);return a+\"\\u2039\"+b+\"\\u203a\"};f.H=function(){return\"TypeProvenance\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.Ga;case 1:return this.lh;case 2:return this.go;case 3:return this.Zm;default:return $K(W(),a)}};f.D=function(a){return a instanceof kx};\nf.B=function(){var a=lb(\"TypeProvenance\");a=W().C(-889275714,a);var b=this.Ga;b=My(W(),b);a=W().C(a,b);b=this.lh;b=My(W(),b);a=W().C(a,b);b=this.go;b=My(W(),b);a=W().C(a,b);b=this.Zm?1231:1237;a=W().C(a,b);return W().Ma(a,4)};f.i=function(a){if(this===a)return!0;if(a instanceof kx&&a.Wu===this.Wu){if(this.Zm===a.Zm){var b=this.Ga,c=a.Ga;b=null===b?null===c:b.i(c)}else b=!1;if(b&&this.lh===a.lh)return b=this.go,a=a.go,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({VO:0},!1,\"mlscript.TyperDatatypes$TypeProvenance\",{VO:1,g:1,E:1,v:1,l:1});function NP(a){if(null===a)throw null;}NP.prototype=new kS;NP.prototype.constructor=NP;NP.prototype.u=function(){return\"TypeProvenance\"};NP.prototype.$classData=q({HZ:0},!1,\"mlscript.TyperDatatypes$TypeProvenance$\",{HZ:1,$ba:1,g:1,qaa:1,l:1});function dQ(a,b){this.Qd=a;this.qe=b}dQ.prototype=new p;dQ.prototype.constructor=dQ;f=dQ.prototype;f.u=function(){return this.Bw()};\nf.Bw=function(){var a=this.qe;if(!0===this.Qd&&!0===a)return\"\\u00b1\";a=this.qe;if(!1===this.Qd&&!0===a)return\"-\";a=this.qe;if(!0===this.Qd&&!1===a)return\"+\";a=this.qe;if(!1===this.Qd&&!1===a)return\"\\x3d\";throw new w(this);};f.H=function(){return\"VarianceInfo\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Qd;case 1:return this.qe;default:return $K(W(),a)}};f.D=function(a){return a instanceof dQ};\nf.B=function(){var a=lb(\"VarianceInfo\");a=W().C(-889275714,a);var b=this.Qd?1231:1237;a=W().C(a,b);b=this.qe?1231:1237;a=W().C(a,b);return W().Ma(a,2)};f.i=function(a){return this===a?!0:a instanceof dQ?this.Qd===a.Qd&&this.qe===a.qe:!1};f.$classData=q({f_:0},!1,\"mlscript.VarianceInfo\",{f_:1,g:1,E:1,v:1,l:1});function gE(){this.SA=null;pz();var a=u();this.SA=qz(a)}gE.prototype=new p;gE.prototype.constructor=gE;\nfunction sn(a){if(a.SA.b())return t().d;Jo();var b=a.SA;Od();b=Ko(Pd(u(),b));a.SA.mg();t();return new L(b)}function Qo(a,b){a=sn(a);if(a instanceof L)return new z(a.k,b);if(t().d===a)return b;throw new w(a);}function po(a,b){a=sn(a);if(a instanceof L){a=a.k;t();b=rn(b);var c=O().c;return new Ud(new z(a,new z(b,c)))}if(t().d===a)return t(),new fe(b);throw new w(a);}f=gE.prototype;f.H=function(){return\"TemporaryVariableEmitter\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};\nf.D=function(a){return a instanceof gE};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return a instanceof gE};f.$classData=q({B_:0},!1,\"mlscript.codegen.TemporaryVariableEmitter\",{B_:1,g:1,E:1,v:1,l:1});function NE(a,b){this.Wi=a;this.mj=b}NE.prototype=new p;NE.prototype.constructor=NE;f=NE.prototype;\nf.u=function(){var a=ze(this.Wi,\"\",\" and \",\"\"),b=this.mj.b()?\"\":\" \",c=this.mj,d=O().c;if(null===d?null===c:d.i(c))d=\"\";else{if(c===u())d=u();else{d=c.e();var e=d=new z(d.Sj.x,u());for(c=c.f();c!==u();){var g=c.e();g=new z(g.Sj.x,u());e=e.p=g;c=c.f()}}d=ze(d,\"(\",\", \",\")\")}return a+b+d};\nfunction sY(a,b){var c=a.Wi;a=a.mj;if(null===b)throw new w(b);var d=b.Wi;b=b.mj;var e=O().c;if(null===e?null===d:e.i(d))return new NE(c,dl(b,a));if(d instanceof z)return e=d.z,e.lf=dl(e.lf,a),new NE(dl(d,c),b);throw new w(d);}function tY(a,b){var c=O().c;if(null===c?null===b:c.i(b))return a;if(b instanceof z)return c=b.z,c.lf=dl(c.lf,a.mj),new NE(dl(b,a.Wi),O().c);throw new w(b);}\nfunction Vea(a,b){a:for(var c=O().c,d=a.Wi,e=R();;){var g=!1,h=null,k=O().c;if(null===k?null===d:k.i(d)){b=e;break a}if(d instanceof z){g=!0;h=d;var l=h.z;k=h.p;if(l instanceof OE){h=l;if(Pe(new E(h.$x),b)){t();b=new L(new tl(c,h,k));break a}c=Xq(c,h);d=k;continue}}if(g&&(l=h.z,k=h.p,l instanceof UE)){h=l;if(Pe(new E(h.Yx),b)){t();b=new L(new tl(c,h,k));break a}c=Xq(c,h);d=k;continue}if(g&&(l=h.z,k=h.p,l instanceof SE)){h=l;Pe(new E(h.Wx),b)?(g=c,e.b()&&(t(),e=new L(new tl(g,h,k))),d=k):(c=Xq(c,h),\nd=k);continue}if(g)g=h.p,c=Xq(c,h.z),d=g;else throw new w(d);}if(b.b())return R();b=b.o();if(null!==b)a=G(new H,b.hb,new NE(dl(b.Rd,b.kc),a.mj));else throw new w(b);return new L(a)}function uY(a,b){var c=a.Wi,d=O().c;if(null===d?null===c:d.i(c))return c=O().c,b=b.ha(),new NE(c,dl(a.mj,b));if(c instanceof z)return c=c.z,d=c.lf,c.lf=dl(b.ha(),d),a;throw new w(c);}f.H=function(){return\"Conjunction\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.Wi;case 1:return this.mj;default:return $K(W(),a)}};f.D=function(a){return a instanceof NE};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof NE){var b=this.Wi,c=a.Wi;if(null===b?null===c:b.i(c))return b=this.mj,a=a.mj,null===b?null===a:b.i(a)}return!1};f.$classData=q({Q_:0},!1,\"mlscript.ucs.Conjunction\",{Q_:1,g:1,E:1,v:1,l:1});function bF(a,b,c,d){this.fr=a;this.ZA=b;this.Sj=c;this.gr=d}bF.prototype=new p;\nbF.prototype.constructor=bF;f=bF.prototype;f.H=function(){return\"LetBinding\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.fr;case 1:return this.ZA;case 2:return this.Sj;case 3:return this.gr;default:return $K(W(),a)}};f.D=function(a){return a instanceof bF};\nf.B=function(){var a=lb(\"LetBinding\");a=W().C(-889275714,a);var b=this.fr;b=My(W(),b);a=W().C(a,b);b=this.ZA?1231:1237;a=W().C(a,b);b=this.Sj;b=My(W(),b);a=W().C(a,b);b=this.gr;b=My(W(),b);a=W().C(a,b);return W().Ma(a,4)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof bF&&this.ZA===a.ZA&&this.fr===a.fr){var b=this.Sj,c=a.Sj;if(null===b?null===c:b.i(c))return b=this.gr,a=a.gr,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({T_:0},!1,\"mlscript.ucs.LetBinding\",{T_:1,g:1,E:1,v:1,l:1});class vY extends wS{constructor(a){super();yF(this,a,null,!0)}}vY.prototype.$classData=q({h0:0},!1,\"mlscript.ucs.PartialTermError\",{h0:1,OF:1,pc:1,g:1,l:1});function wY(a,b,c){this.no=a;this.nh=b;this.ZP=c}wY.prototype=new p;wY.prototype.constructor=wY;function GE(a){var b=a.no;b.b()?(a=a.nh,a instanceof wm||xm(\"`term` must be a `SimpleTerm` when `local` is empty\")):a=b.o();return a}\nfunction xY(a){var b=a.no;if(b.b())return R();b=b.o();return new L(new bF(aF(),!1,b,a.nh))}f=wY.prototype;f.u=function(){var a=this.no;a:if(t().d===a)a=\"\";else{if(a instanceof L){var b=a.k;if(null!==b){a=b.x+\" @ \";break a}}throw new w(a);}return a+\"\"+Zz(this.nh,!1)};f.H=function(){return\"Scrutinee\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.no;case 1:return this.nh;default:return $K(W(),a)}};f.D=function(a){return a instanceof wY};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof wY){var b=this.no,c=a.no;if(null===b?null===c:b.i(c))return b=this.nh,a=a.nh,null===b?null===a:b.i(a)}return!1};f.$classData=q({i0:0},!1,\"mlscript.ucs.Scrutinee\",{i0:1,g:1,E:1,v:1,l:1});q({l0:0},!1,\"mlscript.utils.algorithms$CyclicGraphError\",{l0:1,qd:1,pc:1,g:1,l:1});function yY(){}yY.prototype=new lT;yY.prototype.constructor=yY;function zY(){}zY.prototype=yY.prototype;function RD(a){var b=new oT;yF(b,a,null,!0);return b}class oT extends wS{}\noT.prototype.$classData=q({a3:0},!1,\"scala.NotImplementedError\",{a3:1,OF:1,pc:1,g:1,l:1});function qG(){}qG.prototype=new p;qG.prototype.constructor=qG;f=qG.prototype;f.Ob=function(a,b){return GQ(this,a,b)};f.u=function(){return\"\\x3cfunction1\\x3e\"};f.Lc=function(){return!1};f.AJ=function(a){throw new w(a);};f.n=function(a){this.AJ(a)};f.$classData=q({g3:0},!1,\"scala.PartialFunction$$anon$1\",{g3:1,g:1,za:1,la:1,l:1});function FQ(a,b){this.GK=a;this.mR=b}FQ.prototype=new p;\nFQ.prototype.constructor=FQ;f=FQ.prototype;f.u=function(){return\"\\x3cfunction1\\x3e\"};f.Lc=function(a){return this.GK.Lc(a)};f.n=function(a){return this.mR.n(this.GK.n(a))};f.Ob=function(a,b){var c=this.GK.Ob(a,pG().Hv);return rG(pG(),c)?b.n(a):this.mR.n(c)};f.$classData=q({h3:0},!1,\"scala.PartialFunction$AndThen\",{h3:1,g:1,za:1,la:1,l:1});function EQ(a,b){this.IK=a;this.HK=b}EQ.prototype=new p;EQ.prototype.constructor=EQ;f=EQ.prototype;f.u=function(){return\"\\x3cfunction1\\x3e\"};\nf.Lc=function(a){a=this.IK.Ob(a,pG().Hv);return!rG(pG(),a)&&this.HK.Lc(a)};f.n=function(a){return this.HK.n(this.IK.n(a))};f.Ob=function(a,b){var c=this.IK.Ob(a,pG().Hv);return rG(pG(),c)?b.n(a):this.HK.Ob(c,new y(()=>b.n(a)))};f.$classData=q({i3:0},!1,\"scala.PartialFunction$Combined\",{i3:1,g:1,za:1,la:1,l:1});function Wr(a){this.k3=a}Wr.prototype=new cS;Wr.prototype.constructor=Wr;function Vr(a,b){a=a.k3.Ob(b,pG().Hv);return rG(pG(),a)?R():new L(a)}Wr.prototype.n=function(a){return Vr(this,a)};\nWr.prototype.$classData=q({j3:0},!1,\"scala.PartialFunction$Lifted\",{j3:1,dM:1,g:1,la:1,l:1});function Ue(a){this.gG=null;this.Jv=a}Ue.prototype=new p;Ue.prototype.constructor=Ue;function Wea(){var a=new Ue(J(new K,[\"\",\".\",\"\"]));null===a.gG&&null===a.gG&&(a.gG=new uG(a));return a.gG}f=Ue.prototype;f.H=function(){return\"StringContext\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Jv:$K(W(),a)};f.D=function(a){return a instanceof Ue};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Ue){var b=this.Jv;a=a.Jv;return null===b?null===a:b.i(a)}return!1};f.$classData=q({p3:0},!1,\"scala.StringContext\",{p3:1,g:1,E:1,v:1,l:1});function AY(){}AY.prototype=new p;AY.prototype.constructor=AY;function BY(){}f=BY.prototype=AY.prototype;f.m=function(){return this};f.b=function(){return!this.s()};f.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return this.qk(a,-1)};\nf.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};\nf.Q=function(){return-1};f.Ja=function(a){return new Ef(this,a)};function CY(){this.sm=null;this.sm=DY()}CY.prototype=new wT;CY.prototype.constructor=CY;CY.prototype.$classData=q({$4:0},!1,\"scala.collection.Iterable$\",{$4:1,pG:1,g:1,bg:1,l:1});var EY;function DK(){EY||(EY=new CY);return EY}function FY(){this.VR=this.UR=this.Nt=null;uea(this);GY=this;this.UR=tc();this.VR=new U(()=>HY().UR)}FY.prototype=new VT;FY.prototype.constructor=FY;\nFY.prototype.$classData=q({H5:0},!1,\"scala.collection.Map$\",{H5:1,I5:1,g:1,Ey:1,l:1});var GY;function HY(){GY||(GY=new FY);return GY}function IY(){this.YR=null;JY=this;this.YR=new KY}IY.prototype=new p;IY.prototype.constructor=IY;f=IY.prototype;f.Eb=function(){var a=new EV(16,.75);return new dU(a,new y(b=>new qv(b)))};f.Hh=function(a){return(a=(op(),pp(qp(),a)))&&a.$classData&&a.$classData.rb.oL?a:new qv(a)};f.Ib=function(a){return ZT(eU(),a)};f.X=function(){return this.YR};\nf.$classData=q({O5:0},!1,\"scala.collection.MapView$\",{O5:1,g:1,Nba:1,Ey:1,l:1});var JY;function LY(){this.Bl=null}LY.prototype=new p;LY.prototype.constructor=LY;function MY(){}MY.prototype=LY.prototype;function RE(a,b){return a.Bl.Hh(b)}function TE(a){return a.Bl.X()}f=LY.prototype;f.vl=function(a){return this.Bl.Ib(a)};f.Eb=function(){return this.Bl.Eb()};f.Ib=function(a){return this.vl(a)};f.X=function(){return TE(this)};f.Hh=function(a){return RE(this,a)};\nfunction hl(a){return a.Ii(new y(b=>b))}function NY(a,b){return a.vc(new OY(a,b))}function Xea(a,b){return a.wo(new y(c=>ml(nl(),b,c)),0)}function QU(a,b){return a.qo(new y(c=>ml(nl(),c,b)))}function Oca(a,b){return 0>b||b>a.K()?Rq().Pa:new PY(a,b)}function qw(a,b){var c=a.K(),d=a.ti();if(1===c)c=a.e(),d.$(c);else if(1<c){d.he(c);var e=new zc(c);a.Gc(e,0,2147483647);hj(Pj(),e,b);for(a=0;a<c;)d.$(e.a[a]),a=1+a|0}return d.Kb()}function QY(a,b,c){return a.Zh(new RY(c,b))}\nfunction SY(a){return 0===a.ab(0)}function TY(a,b){var c=a.Q();if(-1!==c){var d=b.Q();c=-1!==d&&c!==d}else c=!1;if(c)return!1;a:{a=a.m();for(b=b.m();a.s()&&b.s();)if(!ml(nl(),a.t(),b.t())){b=!1;break a}b=a.s()===b.s()}return b}function UY(){this.sm=null;this.sm=Bq()}UY.prototype=new wT;UY.prototype.constructor=UY;UY.prototype.$classData=q({X5:0},!1,\"scala.collection.Set$\",{X5:1,pG:1,g:1,bg:1,l:1});var VY;function WY(){VY||(VY=new UY);return VY}\nfunction XY(a,b){var c=a.Ub().Eb(),d=a.Ub().Eb();a.Ca(new y(e=>{e=b.n(e);c.$(e.h());return d.$(e.j())}));return G(new H,c.Kb(),d.Kb())}function YY(a,b){var c=a.Ub().Eb();for(a=a.m();a.s();){var d=b.n(a.t());c.$(d)}return c.Kb()}function zX(a,b){var c=a.Ub().Eb();for(a=a.m();a.s();){var d=b.n(a.t());c.zc(d)}return c.Kb()}function Bf(a,b){var c=a.Ub().Eb();a=a.m();for(b=b.m();a.s()&&b.s();){var d=G(new H,a.t(),b.t());c.$(d)}return c.Kb()}\nfunction Hf(a){var b=a.Ub().Eb(),c=0;for(a=a.m();a.s();){var d=G(new H,a.t(),c);b.$(d);c=1+c|0}return b.Kb()}function ZY(a,b){var c=a.ti();for(a=a.m();a.s();){var d=a.t();!1!==!!b.n(d)&&c.$(d)}return c.Kb()}function Pt(a,b){var c=a.Ub().Eb(),d=a.Ub().Eb();a.Ca(new y(e=>{e=b.n(e);if(e instanceof fe)return c.$(e.aa);if(e instanceof Ud)return d.$(e.fa);throw new w(e);}));return G(new H,c.Kb(),d.Kb())}\nfunction $Y(a,b){var c=a.ti();if(0<=b){var d=-b|0,e=a.Q();-1!==e&&c.he(e+d|0)}b=a.m().ph(b);for(a=a.m();b.s();)d=a.t(),c.$(d),b.t();return c.Kb()}function Yea(a,b,c){a=a.Eb();a.he(b);for(var d=0;d<b;){var e=Es(c);a.$(e);d=1+d|0}return a.Kb()}function aZ(a){this.GL=!1;this.XG=0;this.kS=this.Zv=null;if(null===a)throw null;this.kS=a;this.GL=!1;this.XG=0;this.Zv=a.dc}aZ.prototype=new gS;aZ.prototype.constructor=aZ;f=aZ.prototype;f.u=function(){return\"\\x3cfunction1\\x3e\"};\nf.ey=function(a,b){var c=My(W(),a),d=$G(bH(),c);this.GL?this.XG=lU(this.Zv,a,b,c,d,0,this.XG):(this.Zv=iU(this.Zv,a,b,c,d,0,!0),this.Zv!==this.kS.dc&&(this.GL=!0,this.XG=lI(HH(),kI(HH(),d,0))))};f.ba=function(a,b){this.ey(a,b)};f.n=function(a){this.ey(a.h(),a.j())};f.$classData=q({Y6:0},!1,\"scala.collection.immutable.HashMap$accum$1\",{Y6:1,nH:1,g:1,kz:1,la:1});function bZ(){this.sm=null;this.sm=Od()}bZ.prototype=new wT;bZ.prototype.constructor=bZ;\nbZ.prototype.Ib=function(a){return ZJ(a)?a:vT.prototype.Ib.call(this,a)};bZ.prototype.$classData=q({g7:0},!1,\"scala.collection.immutable.Iterable$\",{g7:1,pG:1,g:1,bg:1,l:1});var cZ;function DY(){cZ||(cZ=new bZ);return cZ}function dZ(){this.Ry=null;eZ=this;this.Ry=fZ(new gZ(new U(()=>hV())))}dZ.prototype=new p;dZ.prototype.constructor=dZ;f=dZ.prototype;f.Hh=function(a){return aU(this,a)};\nfunction Zea(a,b,c){var d=new aw(b),e=new IQ(c);return new gZ(new U(()=>{for(var g=d.rc,h=e.ve;0<h&&!g.b();)g=hZ(g).Lf(),d.rc=g,h=-1+h|0,e.ve=h;return hZ(g)}))}function aU(a,b){return b instanceof gZ?b:0===b.Q()?a.Ry:new gZ(new U(()=>iZ(FK(),b.m())))}function jZ(a,b,c){return b.s()?(a=b.t(),new eV(a,new gZ(new U(()=>jZ(FK(),b,c))))):Es(c)}function iZ(a,b){return b.s()?(a=b.t(),new eV(a,new gZ(new U(()=>iZ(FK(),b))))):hV()}\nfunction kZ(a,b,c){return new gZ(new U(()=>{FK();var d=kZ(FK(),b+c|0,c);return new eV(b,d)}))}f.Eb=function(){return new lZ};f.X=function(){return this.Ry};f.Ib=function(a){return aU(this,a)};f.$classData=q({i7:0},!1,\"scala.collection.immutable.LazyList$\",{i7:1,g:1,Nk:1,bg:1,l:1});var eZ;function FK(){eZ||(eZ=new dZ);return eZ}function mZ(){this.Pt=null;this.Pt=xV()}mZ.prototype=new XT;mZ.prototype.constructor=mZ;\nfunction Ov(a,b,c){if(b&&b.$classData&&b.$classData.rb.FS){O();var d=b.se();if(null===c?null===d:c.i(d))return b}return WT.prototype.qr.call(a,b,c)}mZ.prototype.qr=function(a,b){return Ov(this,a,b)};mZ.prototype.$classData=q({y8:0},!1,\"scala.collection.immutable.SortedMap$\",{y8:1,Z5:1,g:1,xL:1,l:1});var nZ;function sv(){nZ||(nZ=new mZ);return nZ}function oZ(a){this.Uk=a.We;this.bu=a.Jd}oZ.prototype=new eR;oZ.prototype.constructor=oZ;oZ.prototype.u=function(){return\"\\x3cfunction1\\x3e\"};\noZ.prototype.n=function(a){this.bu=fR(this,this.bu,a.h(),a.j())};oZ.prototype.$classData=q({I8:0},!1,\"scala.collection.immutable.TreeMap$Adder\",{I8:1,e8:1,yS:1,g:1,la:1});function pZ(){}pZ.prototype=new p;pZ.prototype.constructor=pZ;\nfunction qZ(a,b,c){if(b instanceof rZ&&(a=b.Xe,null===c?null===a:c.i(a)))return b;if(b&&b.$classData&&b.$classData.rb.PG&&(a=b.se(),null===c?null===a:c.i(a)))return sZ(new rZ,jJ(nJ(),b.m(),b.ka()),c);if(b instanceof tZ&&(c===Fq()?a=!0:(a=Fq(),a=c===a.NB),a))return c===Fq()===0<b.lc?a=b.m():(a=new QX(b),a=uZ(new vZ,a)),b=jJ(nJ(),a,b.K()),sZ(new rZ,b,c);a=null;for(b=b.m();b.s();)a=gJ(nJ(),a,b.t(),null,!1,c);return sZ(new rZ,a,c)}pZ.prototype.GB=function(a){return new wZ(a)};\npZ.prototype.pr=function(a,b){return qZ(0,a,b)};pZ.prototype.ng=function(a){return xZ(a)};pZ.prototype.$classData=q({M8:0},!1,\"scala.collection.immutable.TreeSet$\",{M8:1,g:1,dS:1,oG:1,l:1});var yZ;function zZ(){yZ||(yZ=new pZ);return yZ}function AZ(){BZ=this}AZ.prototype=new p;AZ.prototype.constructor=AZ;function CZ(a,b){a=a.Eb();var c=b.Q();0<=c&&a.he(c);a.zc(b);return a.Kb()}AZ.prototype.Eb=function(){var a=ce();return new dU(a,new y(b=>new Jr(b)))};AZ.prototype.vc=function(a){return CZ(this,a)};\nAZ.prototype.$classData=q({a9:0},!1,\"scala.collection.immutable.WrappedString$\",{a9:1,g:1,Pba:1,TK:1,l:1});var BZ;function DZ(){BZ||(BZ=new AZ);return BZ}function dU(a,b){this.OS=this.sC=null;if(null===a)throw null;this.sC=a;this.OS=b}dU.prototype=new p;dU.prototype.constructor=dU;f=dU.prototype;f.he=function(a){this.sC.he(a)};f.Kb=function(){return this.OS.n(this.sC.Kb())};f.zc=function(a){this.sC.zc(a);return this};f.$=function(a){this.sC.$(a);return this};\nf.$classData=q({v9:0},!1,\"scala.collection.mutable.Builder$$anon$1\",{v9:1,g:1,xg:1,xf:1,wf:1});function PV(a,b){a.lk=b;return a}function QV(){this.lk=null}QV.prototype=new p;QV.prototype.constructor=QV;function EZ(){}f=EZ.prototype=QV.prototype;f.he=function(){};function EF(a,b){a.lk.$(b);return a}function FZ(a,b){a.lk.zc(b);return a}f.zc=function(a){return FZ(this,a)};f.$=function(a){return EF(this,a)};f.Kb=function(){return this.lk};\nf.$classData=q({tC:0},!1,\"scala.collection.mutable.GrowableBuilder\",{tC:1,g:1,xg:1,xf:1,wf:1});function GZ(){this.sm=null;this.sm=QF()}GZ.prototype=new wT;GZ.prototype.constructor=GZ;GZ.prototype.$classData=q({Y9:0},!1,\"scala.collection.mutable.Iterable$\",{Y9:1,pG:1,g:1,bg:1,l:1});var HZ;function rO(){HZ||(HZ=new GZ);return HZ}function IZ(){this.Nt=null;this.Nt=Ty()}IZ.prototype=new VT;IZ.prototype.constructor=IZ;\nIZ.prototype.$classData=q({n$:0},!1,\"scala.collection.mutable.Map$\",{n$:1,I5:1,g:1,Ey:1,l:1});var JZ;function Xu(){JZ||(JZ=new IZ);return JZ}function KZ(){this.sm=null;this.sm=pz()}KZ.prototype=new wT;KZ.prototype.constructor=KZ;KZ.prototype.$classData=q({A$:0},!1,\"scala.collection.mutable.Set$\",{A$:1,pG:1,g:1,bg:1,l:1});var LZ;function jA(){LZ||(LZ=new KZ);return LZ}function MZ(){this.Pt=null;this.Pt=$V()}MZ.prototype=new XT;MZ.prototype.constructor=MZ;\nMZ.prototype.$classData=q({D$:0},!1,\"scala.collection.mutable.SortedMap$\",{D$:1,Z5:1,g:1,xL:1,l:1});var NZ;function Hw(){NZ||(NZ=new MZ);return NZ}function Hq(a,b,c){a.Qg=b;a.mT=c;yF(a,null,null,!1);return a}class Iq extends vea{constructor(){super();this.mT=this.Qg=null}Cj(){return this.mT}pQ(){}}Iq.prototype.$classData=q({lT:0},!1,\"scala.runtime.NonLocalReturnControl\",{lT:1,s4:1,pc:1,g:1,l:1});function OZ(){}OZ.prototype=new p;OZ.prototype.constructor=OZ;function PZ(){}PZ.prototype=OZ.prototype;\nfunction GP(a){return a instanceof Ud?new L(a.fa):R()}function QZ(){}QZ.prototype=new hW;QZ.prototype.constructor=QZ;function RZ(){}RZ.prototype=QZ.prototype;class qb extends iW{constructor(a){super();yF(this,a,null,!0)}}qb.prototype.$classData=q({O0:0},!1,\"java.lang.ArithmeticException\",{O0:1,Te:1,qd:1,pc:1,g:1,l:1});var eaa=q({T0:0},!1,\"java.lang.Byte\",{T0:1,ur:1,g:1,l:1,nf:1,Et:1},a=>Zb(a));function Kj(a){var b=new SZ;yF(b,a,null,!0);return b}\nfunction UL(){var a=new SZ;yF(a,null,null,!0);return a}class SZ extends iW{}SZ.prototype.$classData=q({ak:0},!1,\"java.lang.IllegalArgumentException\",{ak:1,Te:1,qd:1,pc:1,g:1,l:1});function XH(a){var b=new TZ;yF(b,a,null,!0);return b}class TZ extends iW{}TZ.prototype.$classData=q({CQ:0},!1,\"java.lang.IllegalStateException\",{CQ:1,Te:1,qd:1,pc:1,g:1,l:1});function aL(a,b){yF(a,b,null,!0);return a}class bL extends iW{}\nbL.prototype.$classData=q({eK:0},!1,\"java.lang.IndexOutOfBoundsException\",{eK:1,Te:1,qd:1,pc:1,g:1,l:1});class Aj extends iW{constructor(){super();yF(this,null,null,!0)}}Aj.prototype.$classData=q({n1:0},!1,\"java.lang.NegativeArraySizeException\",{n1:1,Te:1,qd:1,pc:1,g:1,l:1});function oL(a){var b=new UZ;yF(b,a,null,!0);return b}function le(){var a=new UZ;yF(a,null,null,!0);return a}class UZ extends iW{}UZ.prototype.$classData=q({o1:0},!1,\"java.lang.NullPointerException\",{o1:1,Te:1,qd:1,pc:1,g:1,l:1});\nvar faa=q({q1:0},!1,\"java.lang.Short\",{q1:1,ur:1,g:1,l:1,nf:1,Et:1},a=>$b(a));function DT(){var a=new VZ;yF(a,null,null,!0);return a}function nv(a){var b=new VZ;yF(b,a,null,!0);return b}class VZ extends iW{}VZ.prototype.$classData=q({A1:0},!1,\"java.lang.UnsupportedOperationException\",{A1:1,Te:1,qd:1,pc:1,g:1,l:1});function WZ(){}WZ.prototype=new yS;WZ.prototype.constructor=WZ;function XZ(){}XZ.prototype=WZ.prototype;\nWZ.prototype.i=function(a){if(a===this)a=!0;else if(a&&a.$classData&&a.$classData.rb.OQ){var b;if(b=a.ka()===this.ka()){a=a.vv();a:{for(;a.s();)if(b=a.t(),!this.L(b)){a=!0;break a}a=!1}b=!a}a=b}else a=!1;return a};WZ.prototype.B=function(){for(var a=this.vv(),b=0;a.s();){var c=b;b=a.t();c|=0;b=ib(b)+c|0}return b|0};class kK extends iW{constructor(){super();yF(this,\"mutation occurred during iteration\",null,!0)}}\nkK.prototype.$classData=q({I1:0},!1,\"java.util.ConcurrentModificationException\",{I1:1,Te:1,qd:1,pc:1,g:1,l:1});function YZ(a,b){if(null===b)var c=0;else c=ib(b),c^=c>>>16|0;a=ZZ(a,b,c,c&(-1+a.wl.a.length|0));return null===a?null:a.xv}\nfunction $Z(a,b){this.wl=null;this.yv=this.jK=0;this.RQ=b;if(0>a)throw Kj(\"initialCapacity \\x3c 0\");if(0>=b)throw Kj(\"loadFactor \\x3c\\x3d 0.0\");a=-1+a|0;a=4<a?a:4;a=(-2147483648>>Math.clz32(a)&a)<<1;this.wl=new (md(EN).Ia)(1073741824>a?a:1073741824);this.jK=Eb(this.wl.a.length*this.RQ);this.yv=0}$Z.prototype=new wN;$Z.prototype.constructor=$Z;f=$Z.prototype;f.ka=function(){return this.yv};f.LF=function(a){return YZ(this,a)};\nf.EF=function(a){if(null===a)var b=0;else b=ib(a),b^=b>>>16|0;return null!==ZZ(this,a,b,b&(-1+this.wl.a.length|0))};f.JF=function(){return new a_(this)};function ZZ(a,b,c,d){for(a=a.wl.a[d];;){if(null===a)return null;c===a.oy?(d=a.xB,d=null===b?null===d:La(b,d)):d=!1;if(d)return a;if(c<a.oy)return null;a=a.xr}}f.$classData=q({U1:0},!1,\"java.util.HashMap\",{U1:1,E1:1,g:1,SQ:1,l:1,Ff:1});function $ea(){var a=new b_,b=new $Z(16,.75);a.zv=b;return a}function b_(){this.zv=null}b_.prototype=new wN;\nb_.prototype.constructor=b_;f=b_.prototype;f.EF=function(a){return this.zv.EF(new bk(a))};f.LF=function(a){return YZ(this.zv,new bk(a))};f.ka=function(){return this.zv.yv};f.JF=function(){return new c_(this)};f.$classData=q({Y1:0},!1,\"java.util.IdentityHashMap\",{Y1:1,E1:1,g:1,SQ:1,l:1,Ff:1});function AH(a){var b=new d_;yF(b,a,null,!0);return b}function LU(){var a=new d_;yF(a,null,null,!0);return a}class d_ extends iW{}\nd_.prototype.$classData=q({u2:0},!1,\"java.util.NoSuchElementException\",{u2:1,Te:1,qd:1,pc:1,g:1,l:1});function e_(){this.ld=\"block\"}e_.prototype=new kz;e_.prototype.constructor=e_;f=e_.prototype;f.H=function(){return\"Block\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof e_};f.B=function(){return 64279661};f.u=function(){return\"Block\"};f.$classData=q({WT:0},!1,\"mlscript.Block$\",{WT:1,sx:1,g:1,E:1,v:1,l:1});var f_;\nfunction g_(){f_||(f_=new e_);return f_}function Xk(){}Xk.prototype=new eW;Xk.prototype.constructor=Xk;function afa(a,b){switch(a){case 40:return O(),a=Ik(),new fe(a);case 41:return O(),a=Ik(),new Ud(a);case 123:return O(),a=Jk(),new fe(a);case 125:return O(),a=Jk(),new Ud(a);case 91:return O(),a=Kk(),new fe(a);case 93:return O(),a=Kk(),new Ud(a);case 8249:return O(),a=Lk(),new fe(a);case 8250:return O(),a=Lk(),new Ud(a);default:return b.n(hc(a))}}\nfunction bfa(a){switch(a){case 40:return!0;case 41:return!0;case 123:return!0;case 125:return!0;case 91:return!0;case 93:return!0;case 8249:return!0;case 8250:return!0;default:return!1}}Xk.prototype.Lc=function(a){return bfa(Ea(a))};Xk.prototype.Ob=function(a,b){return afa(Ea(a),b)};Xk.prototype.$classData=q({aU:0},!1,\"mlscript.BracketKind$$anonfun$unapply$1\",{aU:1,Kf:1,g:1,la:1,za:1,l:1});function h_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}h_.prototype=new Rk;h_.prototype.constructor=h_;f=h_.prototype;\nf.H=function(){return\"Angle\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof h_};f.B=function(){return 63408307};f.u=function(){return\"Angle\"};f.$classData=q({bU:0},!1,\"mlscript.BracketKind$Angle$\",{bU:1,ru:1,g:1,E:1,v:1,l:1});var i_;function Lk(){i_||(i_=new h_);return i_}function j_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}j_.prototype=new Rk;j_.prototype.constructor=j_;f=j_.prototype;f.H=function(){return\"Curly\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof j_};f.B=function(){return 65474477};f.u=function(){return\"Curly\"};f.$classData=q({cU:0},!1,\"mlscript.BracketKind$Curly$\",{cU:1,ru:1,g:1,E:1,v:1,l:1});var k_;function Jk(){k_||(k_=new j_);return k_}function l_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}l_.prototype=new Rk;l_.prototype.constructor=l_;f=l_.prototype;f.H=function(){return\"Indent\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};\nf.D=function(a){return a instanceof l_};f.B=function(){return-2100372276};f.u=function(){return\"Indent\"};f.$classData=q({dU:0},!1,\"mlscript.BracketKind$Indent$\",{dU:1,ru:1,g:1,E:1,v:1,l:1});var m_;function Mk(){m_||(m_=new l_);return m_}function n_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}n_.prototype=new Rk;n_.prototype.constructor=n_;f=n_.prototype;f.H=function(){return\"Quasiquote\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof n_};f.B=function(){return-404865879};\nf.u=function(){return\"Quasiquote\"};f.$classData=q({eU:0},!1,\"mlscript.BracketKind$Quasiquote$\",{eU:1,ru:1,g:1,E:1,v:1,l:1});var o_;function Nk(){o_||(o_=new n_);return o_}function p_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}p_.prototype=new Rk;p_.prototype.constructor=p_;f=p_.prototype;f.H=function(){return\"QuasiquoteTriple\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof p_};f.B=function(){return-2129833369};f.u=function(){return\"QuasiquoteTriple\"};\nf.$classData=q({fU:0},!1,\"mlscript.BracketKind$QuasiquoteTriple$\",{fU:1,ru:1,g:1,E:1,v:1,l:1});var q_;function Ok(){q_||(q_=new p_);return q_}function r_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}r_.prototype=new Rk;r_.prototype.constructor=r_;f=r_.prototype;f.H=function(){return\"Round\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof r_};f.B=function(){return 79151470};f.u=function(){return\"Round\"};\nf.$classData=q({gU:0},!1,\"mlscript.BracketKind$Round$\",{gU:1,ru:1,g:1,E:1,v:1,l:1});var s_;function Ik(){s_||(s_=new r_);return s_}function t_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}t_.prototype=new Rk;t_.prototype.constructor=t_;f=t_.prototype;f.H=function(){return\"Square\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof t_};f.B=function(){return-1810807491};f.u=function(){return\"Square\"};\nf.$classData=q({hU:0},!1,\"mlscript.BracketKind$Square$\",{hU:1,ru:1,g:1,E:1,v:1,l:1});var u_;function Kk(){u_||(u_=new t_);return u_}function v_(){this.Vo=this.Uo=this.Wo=null;this.ci=0}v_.prototype=new Rk;v_.prototype.constructor=v_;f=v_.prototype;f.H=function(){return\"Unquote\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof v_};f.B=function(){return 1385561955};f.u=function(){return\"Unquote\"};\nf.$classData=q({iU:0},!1,\"mlscript.BracketKind$Unquote$\",{iU:1,ru:1,g:1,E:1,v:1,l:1});var w_;function Pk(){w_||(w_=new v_);return w_}function es(a){this.Iw=a}es.prototype=new Wz;es.prototype.constructor=es;f=es.prototype;f.H=function(){return\"CLOSE_BRACKET\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Iw:$K(W(),a)};f.D=function(a){return a instanceof es};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof es?this.Iw===a.Iw:!1};f.$classData=q({jU:0},!1,\"mlscript.CLOSE_BRACKET\",{jU:1,yk:1,g:1,E:1,v:1,l:1});function oX(a){this.rz=null;if(null===a)throw null;this.rz=a}oX.prototype=new eW;oX.prototype.constructor=oX;f=oX.prototype;\nf.nr=function(a,b){a:{if(null!==a){var c=a.h();if(c instanceof Mu){c=c.pd;var d=this.rz.Bk;if(null===d?null===c:d.i(c)){c=!0;break a}}}if(null!==a&&(c=a.j(),c instanceof Mu&&(c=c.pd,d=this.rz.Bk,null===d?null===c:d.i(c)))){c=!0;break a}c=!1}return c?!0:b.n(a)};f.sr=function(a){if(null!==a){var b=a.h();if(b instanceof Mu){b=b.pd;var c=this.rz.Bk;if(null===c?null===b:c.i(b))return!0}}return null!==a&&(a=a.j(),a instanceof Mu&&(a=a.pd,b=this.rz.Bk,null===b?null===a:b.i(a)))?!0:!1};f.Lc=function(a){return this.sr(a)};\nf.Ob=function(a,b){return this.nr(a,b)};f.$classData=q({sU:0},!1,\"mlscript.ConstraintSolver$$anonfun$$nestedInanonfun$constrainImpl$103$1\",{sU:1,Kf:1,g:1,la:1,za:1,l:1});function FX(a,b,c,d,e,g,h){this.DM=this.vH=this.BM=null;this.CM=!1;this.GM=this.EM=this.FM=null;if(null===a)throw null;this.BM=a;this.vH=b;this.DM=c;this.CM=d;this.FM=e;this.EM=g;this.GM=h}FX.prototype=new eW;FX.prototype.constructor=FX;f=FX.prototype;\nf.wJ=function(a,b){return a instanceof nC?EX(this.BM,this.vH.$a.n(a.rp.x),this.DM,this.CM,this.FM,this.EM,this.GM,this.vH):b.n(a)};f.PJ=function(a){return a instanceof nC};f.Lc=function(a){return this.PJ(a)};f.Ob=function(a,b){return this.wJ(a,b)};f.$classData=q({tU:0},!1,\"mlscript.ConstraintSolver$$anonfun$1\",{tU:1,Kf:1,g:1,la:1,za:1,l:1});function wX(a,b,c){this.HM=b;this.IM=c}wX.prototype=new eW;wX.prototype.constructor=wX;f=wX.prototype;\nf.xJ=function(a,b){var c=a.ma().Ga;if(Nm(new E(c),this.HM.Ga))if(c=a.ma().Ga,c.b())c=!1;else{c=c.o();var d=this.IM.Ga;d.b()?c=!0:(d=d.o(),c=OX(c,d)||Sy(d,c))}else c=!1;return c?a:b.n(a)};f.QJ=function(a){var b=a.ma().Ga;if(Nm(new E(b),this.HM.Ga)){a=a.ma().Ga;if(a.b())return!1;a=a.o();b=this.IM.Ga;if(b.b())return!0;b=b.o();return OX(a,b)||Sy(b,a)}return!1};f.Lc=function(a){return this.QJ(a)};f.Ob=function(a,b){return this.xJ(a,b)};\nf.$classData=q({uU:0},!1,\"mlscript.ConstraintSolver$$anonfun$2\",{uU:1,Kf:1,g:1,la:1,za:1,l:1});function xX(){}xX.prototype=new eW;xX.prototype.constructor=xX;f=xX.prototype;f.yJ=function(a,b){if(null!==a){var c=a.Ga,d=a.go;if(d instanceof L&&(d=d.k,!c.b()))return G(new H,d,a)}return b.n(a)};f.RJ=function(a){if(null!==a){var b=a.Ga;if(a.go instanceof L&&!b.b())return!0}return!1};f.Lc=function(a){return this.RJ(a)};f.Ob=function(a,b){return this.yJ(a,b)};\nf.$classData=q({vU:0},!1,\"mlscript.ConstraintSolver$$anonfun$3\",{vU:1,Kf:1,g:1,la:1,za:1,l:1});function uX(a,b,c){this.Ow=b;this.xU=c}uX.prototype=new eW;uX.prototype.constructor=uX;f=uX.prototype;\nf.yJ=function(a,b){if(null!==a){var c=a.Ga,d=a.lh;if(c instanceof L){var e=c.k;if(this.Ow.L(e)||a.Zm)h=!1;else{var g=!1;for(h=this.Ow.m();!g&&h.s();)g=h.t(),g=Sy(e,g);var h=!g}if(h)return this.Ow.Ca(new y(k=>{if(Sy(k,e))return this.xU.$(k)})),this.Ow.oh(e),a=new Te(new Ue(J(new K,[\"\\u2022 this \",\":\"]))),d=[We(Xe(),d)],d=Ye(a,J(new K,d)),G(new H,d,c)}}return b.n(a)};\nf.RJ=function(a){if(null!==a){var b=a.Ga;if(b instanceof L){b=b.k;if(this.Ow.L(b)||a.Zm)b=!1;else{var c=!1;for(a=this.Ow.m();!c&&a.s();)c=a.t(),c=Sy(b,c);b=!c}if(b)return!0}}return!1};f.Lc=function(a){return this.RJ(a)};f.Ob=function(a,b){return this.yJ(a,b)};f.$classData=q({wU:0},!1,\"mlscript.ConstraintSolver$$anonfun$4\",{wU:1,Kf:1,g:1,la:1,za:1,l:1});function AX(a,b,c){this.KM=b;this.JM=c}AX.prototype=new eW;AX.prototype.constructor=AX;f=AX.prototype;\nf.nr=function(a,b){if(null!==a){var c=a.h(),d=a.j(),e=d.Ga;e.b()?e=!1:(e=e.o(),e=!this.KM.L(e));if(e)return this.JM.Am?(a=new Te(new Ue(J(new K,[\"Note: \",\" \",\"\"]))),c=[We(Xe(),d.lh),We(Xe(),c)],c=Ye(a,J(new K,c))):(a=new Te(new Ue(J(new K,[\"      \",\" \",\"\"]))),c=[We(Xe(),d.lh),We(Xe(),c)],c=Ye(a,J(new K,c))),this.JM.Am=!1,c=Ye(new Te(new Ue(J(new K,[\"\",\" is defined at:\"]))),J(new K,[c])),G(new H,c,d.Ga)}return b.n(a)};\nf.sr=function(a){return null!==a&&(a=a.j().Ga,a.b()?a=!1:(a=a.o(),a=!this.KM.L(a)),a)?!0:!1};f.Lc=function(a){return this.sr(a)};f.Ob=function(a,b){return this.nr(a,b)};f.$classData=q({yU:0},!1,\"mlscript.ConstraintSolver$$anonfun$5\",{yU:1,Kf:1,g:1,la:1,za:1,l:1});function yX(){}yX.prototype=new eW;yX.prototype.constructor=yX;f=yX.prototype;f.xJ=function(a,b){return a instanceof cv||a instanceof Qv||Uv(a)||a instanceof zv||a instanceof fw||a instanceof FA||b.n(a)};\nf.QJ=function(a){return a instanceof cv||a instanceof Qv||Uv(a)||a instanceof zv||a instanceof fw||a instanceof FA};f.Lc=function(a){return this.QJ(a)};f.Ob=function(a,b){return this.xJ(a,b)};f.$classData=q({zU:0},!1,\"mlscript.ConstraintSolver$$anonfun$lhsIsPlain$1$1\",{zU:1,Kf:1,g:1,la:1,za:1,l:1});function x_(){}x_.prototype=new Wz;x_.prototype.constructor=x_;f=x_.prototype;f.H=function(){return\"DEINDENT\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};\nf.D=function(a){return a instanceof x_};f.B=function(){return 1524287597};f.u=function(){return\"DEINDENT\"};f.$classData=q({DU:0},!1,\"mlscript.DEINDENT$\",{DU:1,yk:1,g:1,E:1,v:1,l:1});var y_;function rs(){y_||(y_=new x_);return y_}function sy(a){return!!(a&&a.$classData&&a.$classData.rb.ud)}function z_(){}z_.prototype=new jl;z_.prototype.constructor=z_;f=z_.prototype;f.H=function(){return\"Lexing\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof z_};\nf.B=function(){return-2022196861};f.u=function(){return\"Lexing\"};f.$classData=q({JU:0},!1,\"mlscript.Diagnostic$Lexing$\",{JU:1,SM:1,g:1,E:1,v:1,l:1});var A_;function ir(){A_||(A_=new z_);return A_}function B_(){}B_.prototype=new jl;B_.prototype.constructor=B_;f=B_.prototype;f.H=function(){return\"Parsing\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof B_};f.B=function(){return 871689872};f.u=function(){return\"Parsing\"};\nf.$classData=q({KU:0},!1,\"mlscript.Diagnostic$Parsing$\",{KU:1,SM:1,g:1,E:1,v:1,l:1});var C_;function ws(){C_||(C_=new B_);return C_}function D_(){}D_.prototype=new jl;D_.prototype.constructor=D_;f=D_.prototype;f.H=function(){return\"Typing\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof D_};f.B=function(){return-1774931561};f.u=function(){return\"Typing\"};f.$classData=q({LU:0},!1,\"mlscript.Diagnostic$Typing$\",{LU:1,SM:1,g:1,E:1,v:1,l:1});var E_;\nfunction lu(){E_||(E_=new D_);return E_}function F_(){}F_.prototype=new Wz;F_.prototype.constructor=F_;f=F_.prototype;f.H=function(){return\"INDENT\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof F_};f.B=function(){return-2130910036};f.u=function(){return\"INDENT\"};f.$classData=q({YU:0},!1,\"mlscript.INDENT$\",{YU:1,yk:1,g:1,E:1,v:1,l:1});var G_;function ks(){G_||(G_=new F_);return G_}function Xn(a,b,c){this.pV=b;this.qV=c}Xn.prototype=new eW;\nXn.prototype.constructor=Xn;f=Xn.prototype;f.pj=function(a,b){if(a instanceof Zn){var c=a.wd,d=a.Rb,e=a.Ch,g=a.Yc;if(g instanceof fe&&(g=g.aa,c.b()||(c.b()?0:c.o())))return this.pV.oh(d.x),new Dp(!(c.b()||!c.o()),new Ep(this.qV),d,e,(O(),new fe(g)))}return b.n(a)};f.rj=function(a){if(a instanceof Zn){var b=a.wd;if(a.Yc instanceof fe&&(b.b()||(b.b()?0:b.o())))return!0}return!1};f.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};\nf.$classData=q({oV:0},!1,\"mlscript.JSBackend$$anonfun$1\",{oV:1,Kf:1,g:1,la:1,za:1,l:1});function Yn(a,b,c){this.iN=b;this.sV=c}Yn.prototype=new eW;Yn.prototype.constructor=Yn;f=Yn.prototype;f.pj=function(a,b){if(a instanceof Zn){var c=a.wd,d=a.Rb,e=a.Ch,g=a.Yc;if(g instanceof Ud&&(g=g.fa,a.Pl&&!this.iN.L(d.x)))return new Dp(!(c.b()||!c.o()),new Ep(this.sV),d,e,(O(),new Ud(g)))}return b.n(a)};f.rj=function(a){if(a instanceof Zn){var b=a.Rb;if(a.Yc instanceof Ud&&a.Pl&&!this.iN.L(b.x))return!0}return!1};\nf.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};f.$classData=q({rV:0},!1,\"mlscript.JSBackend$$anonfun$2\",{rV:1,Kf:1,g:1,la:1,za:1,l:1});function ao(){}ao.prototype=new eW;ao.prototype.constructor=ao;f=ao.prototype;f.pj=function(a,b){return a instanceof yo?a:b.n(a)};f.rj=function(a){return a instanceof yo};f.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};f.$classData=q({tV:0},!1,\"mlscript.JSBackend$$anonfun$3\",{tV:1,Kf:1,g:1,la:1,za:1,l:1});\nfunction yz(a,b){this.kD=a;this.jD=b}yz.prototype=new Jp;yz.prototype.constructor=yz;f=yz.prototype;f.xa=function(){for(var a=Sp(Qp(),\" catch (\"+this.kD.tq+\") \"),b=this.jD,c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,d.xa());b=b.f()}return Rp(a,Oz(c))};f.H=function(){return\"JSCatchClause\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.kD;case 1:return this.jD;default:return $K(W(),a)}};f.D=function(a){return a instanceof yz};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof yz){var b=this.kD,c=a.kD;if(null===b?null===c:b.i(c))return b=this.jD,a=a.jD,null===b?null===a:b.i(a)}return!1};f.$classData=q({BV:0},!1,\"mlscript.JSCatchClause\",{BV:1,Xc:1,g:1,E:1,v:1,l:1});function vO(){}vO.prototype=new eW;vO.prototype.constructor=vO;vO.prototype.Lc=function(a){return a instanceof xO};vO.prototype.Ob=function(a,b){return a instanceof xO?a.ax:b.n(a)};\nvO.prototype.$classData=q({zW:0},!1,\"mlscript.Message$$anonfun$typeBits$1\",{zW:1,Kf:1,g:1,la:1,za:1,l:1});function xO(a){this.ax=a}xO.prototype=new Pq;xO.prototype.constructor=xO;f=xO.prototype;f.H=function(){return\"Code\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.ax:$K(W(),a)};f.D=function(a){return a instanceof xO};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof xO){var b=this.ax;a=a.ax;return null===b?null===a:b.i(a)}return!1};f.$classData=q({BW:0},!1,\"mlscript.Message$Code\",{BW:1,AW:1,g:1,E:1,v:1,l:1});function Vq(a){this.Jz=a}Vq.prototype=new Pq;Vq.prototype.constructor=Vq;f=Vq.prototype;f.H=function(){return\"Text\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Jz:$K(W(),a)};f.D=function(a){return a instanceof Vq};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof Vq?this.Jz===a.Jz:!1};f.$classData=q({DW:0},!1,\"mlscript.Message$Text\",{DW:1,AW:1,g:1,E:1,v:1,l:1});function Dp(a,b,c,d,e){this.pN=this.oN=this.nN=null;this.rN=this.sN=0;this.tN=this.qN=null;this.Fs=0;this.hE=a;this.gE=b;this.uq=c;this.iE=d;this.bx=e;Nq(this);if(e instanceof Ud)a=e.fa;else{if(!(e instanceof fe))throw new w(e);a=e.aa}a=this.nN=a;b=O().c;this.oN=new z(c,new z(a,b))}Dp.prototype=new p;Dp.prototype.constructor=Dp;f=Dp.prototype;\nf.jn=function(){0===(1&this.Fs)<<24>>24&&0===(1&this.Fs)<<24>>24&&(this.pN=zq(this),this.Fs=(1|this.Fs)<<24>>24);return this.pN};f.rn=function(){return this.sN};f.fm=function(a){this.sN=a};f.qn=function(){return this.rN};f.em=function(a){this.rN=a};f.pn=function(){return this.qN};f.on=function(a){this.qN=a};f.A=function(){0===(2&this.Fs)<<24>>24&&0===(2&this.Fs)<<24>>24&&(this.tN=Dq(this),this.Fs=(2|this.Fs)<<24>>24);return this.tN};f.Vj=function(){return this.oN};f.H=function(){return\"MethodDef\"};\nf.G=function(){return 5};f.I=function(a){switch(a){case 0:return this.hE;case 1:return this.gE;case 2:return this.uq;case 3:return this.iE;case 4:return this.bx;default:return $K(W(),a)}};f.D=function(a){return a instanceof Dp};f.B=function(){var a=lb(\"MethodDef\");a=W().C(-889275714,a);var b=this.hE?1231:1237;a=W().C(a,b);b=this.gE;b=My(W(),b);a=W().C(a,b);b=this.uq;b=My(W(),b);a=W().C(a,b);b=this.iE;b=My(W(),b);a=W().C(a,b);b=this.bx;b=My(W(),b);a=W().C(a,b);return W().Ma(a,5)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Dp){if(this.hE===a.hE){var b=this.gE,c=a.gE;b=null===b?null===c:b.i(c)}else b=!1;if(b&&(b=this.uq,c=a.uq,null===b?null===c:b.i(c))&&(b=this.iE,c=a.iE,null===b?null===c:b.i(c)))return b=this.bx,a=a.bx,null===b?null===a:b.i(a)}return!1};f.$classData=q({EW:0},!1,\"mlscript.MethodDef\",{EW:1,g:1,Ta:1,E:1,v:1,l:1});\nfunction kw(a){if(!a.rE){var b=a.vd.m(),c=a.fc;a:{if(c instanceof L&&(c=c.k,c instanceof Mu)){c=c.Fv().bc(c.pd);break a}c=ap()}for(;b.s();){var d=b.t();if(d instanceof nC){var e=d.Fv();c=c.Ce(e).bc(d.rp)}}a.qE=c;a.rE=!0}return a.qE}function Ku(a,b,c,d,e){this.pE=null;this.Mz=!1;this.qE=this.Fa=null;this.rE=!1;this.fc=b;this.vd=c;this.be=d;this.Me=e;if(null===a)throw null;this.Fa=a}Ku.prototype=new gv;Ku.prototype.constructor=Ku;f=Ku.prototype;\nf.u=function(){var a=this.fc;a=a.b()?\"\":a.o();var b=this.be,c=this.vd.m().nb(new U(()=>new Ou(this.Me)));c=new Ef(c,new y(d=>\"\\u2227\"+d));return\"\"+a+b+ze(c,\"\",\"\",\"\")};f.H=function(){return\"LhsRefined\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.fc;case 1:return this.vd;case 2:return this.be;case 3:return this.Me;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ku};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Ku&&a.Fa===this.Fa){var b=this.fc,c=a.fc;(null===b?null===c:b.i(c))?(b=this.vd,c=a.vd,b=null===b?null===c:b.i(c)):b=!1;if(b&&(b=this.be,c=a.be,null===b?null===c:mC(b,c)))return b=this.Me,a=a.Me,null===b?null===a:b.i(a)}return!1};f.$classData=q({fX:0},!1,\"mlscript.NormalForms$LhsRefined\",{fX:1,eX:1,g:1,E:1,v:1,l:1});function IS(a){this.pE=null;this.Mz=!1;this.Fa=null;if(null===a)throw null;this.Fa=a}IS.prototype=new gv;IS.prototype.constructor=IS;\nf=IS.prototype;f.u=function(){return\"\\u22a4\"};f.H=function(){return\"LhsTop\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof IS};f.B=function(){return-2019595394};f.$classData=q({gX:0},!1,\"mlscript.NormalForms$LhsTop$\",{gX:1,eX:1,g:1,E:1,v:1,l:1});function jw(a,b,c,d){this.Nz=null;this.jx=!1;this.Aa=null;this.Xb=b;this.mb=c;this.Dc=d;rw(this,a)}jw.prototype=new tw;jw.prototype.constructor=jw;\nfunction cfa(a,b,c,d,e){var g=a.Aa,h=a.Xb,k=a.mb;if(k.b())k=R();else{k=k.o();if(k instanceof fe)k=k.aa,t(),k=k.qv(b,c,d,e),k=new fe(k);else if(k instanceof Ud)k=k.fa,t(),k=H_(k,b,c,d,e),k=new Ud(k);else throw new w(k);k=new L(k)}a=new pv(new qv(a.Dc),new y(r=>rv(r,b,c,d,e)));var l=sv(),m=Su(),n=op().ga;return new jw(g,h,k,(new tv(l,new Uu(m,n))).vc(a))}f=jw.prototype;\nf.u=function(){var a=ze(this.Xb,\"\",\"|\",\"\"),b=this.mb;if(b.b())b=\"\";else{b=b.o();if(b instanceof Ud)b=\"\"+b.fa;else{if(!(b instanceof fe))throw new w(b);b=\"\"+b.aa}b=\"|\"+b}var c=new Ou(this.Dc);c=new Ef(c,new y(d=>\"|\"+d));return a+b+ze(c,\"\",\"\",\"\")};f.H=function(){return\"RhsBases\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.Xb;case 1:return this.mb;case 2:return this.Dc;default:return $K(W(),a)}};f.D=function(a){return a instanceof jw};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof jw&&a.Aa===this.Aa){var b=this.Xb,c=a.Xb;(null===b?null===c:b.i(c))?(b=this.mb,c=a.mb,b=null===b?null===c:b.i(c)):b=!1;if(b)return b=this.Dc,a=a.Dc,null===b?null===a:b.i(a)}return!1};f.HJ=function(a,b,c,d){return cfa(this,a,b,c,d)};f.$classData=q({hX:0},!1,\"mlscript.NormalForms$RhsBases\",{hX:1,CN:1,g:1,E:1,v:1,l:1});function JS(a){this.Nz=null;this.jx=!1;this.Aa=null;rw(this,a)}JS.prototype=new tw;JS.prototype.constructor=JS;f=JS.prototype;\nf.u=function(){return\"\\u22a5\"};f.H=function(){return\"RhsBot\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof JS};f.B=function(){return-1847837782};f.HJ=function(){return this};f.$classData=q({iX:0},!1,\"mlscript.NormalForms$RhsBot$\",{iX:1,CN:1,g:1,E:1,v:1,l:1});function iw(a,b,c){this.Nz=null;this.jx=!1;this.Aa=null;this.me=b;this.Ne=c;rw(this,a)}iw.prototype=new tw;iw.prototype.constructor=iw;\nfunction H_(a,b,c,d,e){var g=a.Aa,h=a.me,k=a.Ne,l=k.Va,m=k.Oa;if(m.b())m=R();else{m=m.o();var n=a.Aa,r=a.Aa.Df,v=ap();m=new L(fD(n,m,r,d,b,v,e,c))}n=k.ra;r=a.Aa;a=a.Aa.Df;v=ap();return new iw(g,h,new Uw(l,m,fD(r,n,a,d,b,v,e,c),k.Pd))}f=iw.prototype;f.u=function(){return\"{\"+this.me.x+\":\"+this.Ne+\"}\"};f.H=function(){return\"RhsField\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.me;case 1:return this.Ne;default:return $K(W(),a)}};f.D=function(a){return a instanceof iw};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof iw&&a.Aa===this.Aa){var b=this.me,c=a.me;if(null===b?null===c:b.i(c))return b=this.Ne,a=a.Ne,null===b?null===a:b.i(a)}return!1};f.HJ=function(a,b,c,d){return H_(this,a,b,c,d)};f.$classData=q({jX:0},!1,\"mlscript.NormalForms$RhsField\",{jX:1,CN:1,g:1,E:1,v:1,l:1});\nvar efa=function dfa(a,b,c){if(b instanceof Ql){var e=b.Vl,g=b.ml;if(e instanceof vl&&\"this\"===e.x)return c.oh(G(new H,g,(t(),new L(e)))),t().d}if(b instanceof vl)return\"this\"===b.x?(t(),new L(b)):(c.oh(G(new H,b,t().d)),t().d);if(b instanceof I_)return t().d;if(b instanceof Pm||b&&b.$classData&&b.$classData.rb.md||b instanceof Ct||b instanceof BS||b instanceof zS||b instanceof Dt){b=b.Vj();for(e=t().d;!b.b();)g=e,e=b.e(),e=g.b()?dfa(a,e,c):g,b=b.f();return e}throw new w(b);};\nfunction ffa(a,b,c,d,e,g,h){for(;;)if(b instanceof z){var k=b.z;b=b.p;if(k instanceof Ct)var l=t().d;else if(k instanceof Pm){var m=k;l=Rw(a,m,c,d,e,!0);if(!(g||b.b()&&h))if(m instanceof Dl||m instanceof Ol)JX(a,We(Xe(),\"Pure expression does nothing in statement position.\"),m.A(),d);else{k=ux(a,l,jx(new kx,a,Lq(m),\"expression in statement position\",(tx(a),t().d),(tx(a),!1)));var n=a.Ck,r=new y(((x,A)=>B=>{fr();var C=Ye(new Te(new Ue(J(new K,[\"Expression in statement position should have type `()`.\"]))),\nu()),D=t().d;C=G(new H,C,D);D=Ye(new Te(new Ue(J(new K,[\"Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\"]))),u());var F=t().d;D=G(new H,D,F);A.n(hr(0,new z(C,new z(D,B.vt())),x.$c,lu()))})(a,d));m=jx(new kx,a,m.A(),hu(m),(tx(a),t().d),(tx(a),!1));var v=Sw(a).ob;Tw(a,k,n,r,m,c,v)}t();l=new L(l)}else sy(k)?(l=k,k=a,n=new Te(new Ue(J(new K,[\"Illegal position for this \",\" statement.\"]))),r=[We(Xe(),l.jb())],Lw(k,Ye(n,J(new K,r)),l.A(),d),l=t().d):\nxm(\"Program reached and unexpected state.\");k=O().c;if(null===k?null===b:k.i(b))return l}else{a=O().c;if(null===a?null===b:a.i(b))return t().d;throw new w(b);}}function J_(){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0;this.zk=this.Pq=this.Uq=this.xp=this.Bp=this.Cp=this.Sq=this.zp=this.Rq=this.wp=this.Ap=this.yp=this.Qq=this.Tq=null;this.Dp=0;this.hs=this.yq=this.Aq=this.Bq=this.zq=this.Dq=this.Cq=null;this.Im=this.Pw=0;this.Ku=null}J_.prototype=new DX;\nJ_.prototype.constructor=J_;function K_(){}K_.prototype=J_.prototype;\nfunction Dy(a,b,c,d,e,g,h,k,l,m){if(Ot(new E(d.pb),zp())&&h.b()){if(g.b())return e=d.gb,g=O().c,new fw(a,e,g,V(a));c=zx(a);d=d.gb;if(g===u())g=u();else{m=g.e();h=m=new z(m.hb,u());for(g=g.f();g!==u();)k=g.e(),k=new z(k.hb,u()),h=h.p=k,g=g.f();g=m}return yx(c,e,new fw(a,d,g,V(a)))}if(Ot(new E(d.pb),Bp())||Ot(new E(d.pb),zp())){Ot(new E(d.pb),zp())&&Lw(a,Ye(new Te(new Ue(J(new K,[\"Parameterized modules are not yet supported\"]))),u()),c,m);a.F&&(l=ut(Q(),\"| \",a.r)+(\"params: \"+h+\" \")+k,ff(gf(),l+\"\\n\"));\nif(!b)if(h.b()){if(k.b())return e=new Te(new Ue(J(new K,[\"Class \",\" cannot be instantiated as it exposes no constructor\"]))),g=[We(Xe(),d.gb.V)],Lw(a,Ye(e,J(new K,g)),c,m);b=new Te(new Ue(J(new K,[\"Construction of unparameterized class \",\" should use the `new` keyword\"])));l=[We(Xe(),d.gb.V)];Lw(a,Ye(b,J(new K,l)),c,m)}else k.b()||Lw(a,Ye(new Te(new Ue(J(new K,[\"Construction of class with auxiliary constructor should use the `new` keyword\"]))),u()),c,m);if(k instanceof L)c=k.k,m=ry(lv(),c,new y(n=>\n{var r=V(a);return new Uw(n.q,R(),n,r)}));else{if(t().d!==k)throw new w(k);m=h.b()?O().c:h.o()}c=zx(a);m=JF(lv(),m,it());m=new zv(a,m,V(a));d=d.gb;if(g===u())g=u();else{h=g.e();k=h=new z(h.hb,u());for(g=g.f();g!==u();)b=g.e(),b=new z(b.hb,u()),k=k.p=b,g=g.f();g=h}g=new fw(a,d,g,V(a));return yx(c,e,new cv(a,m,g,V(a)))}return Ey(a)}function Vy(a,b){pz();var c=u();c=qz(c);return new XX(a,efa(a,b,c),Aq(Bq(),c))}\nfunction of(a,b,c,d,e,g){var h=a.qa;if(a.F){var k=ut(Q(),\"| \",a.r)+(d.da+\". Typing \")+b;ff(gf(),k+\"\\n\")}a.r=1+a.r|0;try{for(var l=c.b(),m=ef(b);!m.b();){var n=m.e();if(n instanceof Zn){k=n;if(k.wd.b())if(c.b())v=!1;else var r=c.o().CB(),v=Ot(new E(r),g_());else v=!1;v&&Lw(a,Ye(new Te(new Ue(J(new K,[\"Cannot use `val` or `fun` in local block; use `let` instead.\"]))),u()),k.A(),e)}m=m.f()}var x=Xu().X(),A=ef(b);Od();var B=new fp;Od();var C=new fp;for(b=A;!b.b();){var D=b.e();if(D instanceof Ct){m=D;\nt();var F=new fe(m)}else t(),F=new Ud(D);if(F instanceof fe)wp(B,F.aa);else if(F instanceof Ud)wp(C,F.fa);else throw new w(F);b=b.f()}var I=B.ha(),M=C.ha(),N=Xu().X();B=va=>{if(va instanceof Zn){var Ra=va.Rb;if(va.Yc instanceof Ud)return rx(va)&&Lw(a,We(Xe(),\"`let` bindings must have a right-hand side\"),va.A(),e),N.ou(Ra.x,new y(rb=>{if(rb instanceof L)return rb=rb.k,Lw(a,We(Xe(),\"A type signature for '\"+Ra.x+\"' was already given\"),va.A(),e),t(),new L(rb);if(t().d===rb)return t(),new L(va);throw new w(rb);\n})),!1}return!0};a:for(var P;;)if(I.b()){P=u();break}else{var T=I.e(),Y=I.f();if(!1===!!B(T))I=Y;else for(T=I;;){if(Y.b())P=T;else{var Z=Y.e();if(!1!==!!B(Z)){Y=Y.f();continue}Z=Y;var S=new z(T.e(),u()),ea=T.f();for(Y=S;ea!==Z;){var ia=new z(ea.e(),u());Y=Y.p=ia;ea=ea.f()}var X=Z.f();for(ea=X;!X.b();){var sa=X.e();if(!1===!!B(sa)){for(;ea!==X;){var Ja=new z(ea.e(),u());Y=Y.p=Ja;ea=ea.f()}ea=X.f()}X=X.f()}ea.b()||(Y.p=ea);P=S}break a}}var Xa=l?N.ry(new y(va=>{if(null!==va){va=va.j();var Ra=new fx(a,\nva,g,d,e),rb=va.hj;rb.b()||(rb=rb.o().x,Wx(d,G(new H,rb,Ra)));return G(new H,va.Cf.x,Ra)}throw new w(va);})):O().c;S=va=>{if(null!==va){if(va instanceof Zn){up(tp(),va.kx.b());var Ra=N.U(va.Rb.x);if(Ra instanceof L){Ra=Ra.k;var rb=va.wd,xb=va.Rb,mc=va.hj,Ha=va.Ch,Ka=va.Yc,Oa=va.Pz,Na=va.lx,Da=va.Om;t();var ta=new Zn(rb,xb,mc,Ha,Ka,Oa,Na,Da,new L(Ra),c,va.Pl,va.Oz)}else ta=new Zn(va.wd,va.Rb,va.hj,va.Ch,va.Yc,va.Pz,va.lx,va.Om,va.kx,c,va.Pl,va.Oz)}else{if(!(va instanceof yo))throw new w(va);Xca(new E(va.gb.V),\na.tP)&&(Ra=new Te(new Ue(J(new K,[\"Type name '\",\"' is reserved\"]))),rb=[We(Xe(),va.gb.V)],Lw(a,Ye(Ra,J(new K,rb)),va.A(),e));ta=va}var Ya=new fx(a,ta,g,d,e);if(ta instanceof yo)va=d.$a,Ra=G(new H,ta.gb.V,Ya),va.$(Ra);else if(ta instanceof Zn)va=ta.hj,va.b()||(va=va.o().x,Wx(d,G(new H,va,Ya)));else throw new w(ta);x.ou(ta.Cf.x,new y(dc=>{if(dc instanceof L){if(!(ta instanceof Zn&&ta.wd instanceof L)){dc=new Te(new Ue(J(new K,[\"Redefinition of '\",\"'\"])));var ka=[We(Xe(),ta.Cf.x)];Lw(a,Ye(dc,J(new K,\nka)),ta.A(),e)}t();return new L(Ya)}if(t().d===dc)return t(),new L(Ya);throw new w(dc);}));return G(new H,ta.Cf.x,Ya)}throw new w(va);};if(P===u())var Fa=u();else{var za=P.e(),Qa=new z(S(za),u());za=Qa;for(var Ma=P.f();Ma!==u();){var Ga=Ma.e(),ab=new z(S(Ga),u());za=za.p=ab;Ma=Ma.f()}Fa=Qa}Jw(d,Fa);Jw(d,Xa);var Hb=ry(lv(),Xa,new y(va=>{var Ra=!1,rb=null;va=Kx(va,e);if(va instanceof bx&&(Ra=!0,rb=va,!rb.Mb.Pz.b()))return a.La;if(Ra)return rb.Nn();xm(\"Program reached and unexpected state.\")}));op();\nvar bc=pp(qp(),Hb);lv();var yb=un(Fa,Xa),tb=ry(0,yb,new y(va=>{va=Kx(va,e);if(va instanceof bx){var Ra=bc.U(va.Ua());if(Ra instanceof L){Ra=Ra.k;var rb=va.Mb.A();rb=jx(new kx,a,rb,cy(va.Mb),(tx(a),t().d),(tx(a),!1));Nea(a,va.Nn(),Ra,d,e,rb)}else Ra=va.Ua(),rb=new qx(a,va.Nn(),va.Mb.Rb),Wx(d,G(new H,Ra,rb)),Ra=va.Mb.hj,Ra.b()?Ra=R():(Ra=Ra.o(),Ra=new L(Ra.x)),Ra.b()||(Ra=Ra.o(),rb=new qx(a,va.Nn(),va.Mb.Rb),Wx(d,G(new H,Ra,rb)))}return new ix(a,va)}));Jw(d,tb);if(c.b())var eb=R();else{var kb=c.o();\neb=new L(kb.CB())}b:if(t().d===eb)var Rb=!0;else{if(eb instanceof L){var Gb=eb.k;if(g_()===Gb||hx()===Gb){Rb=!0;break b}}Rb=!1}if(Rb)var vb=!0;else if(eb instanceof L&&eb.k instanceof WS)vb=!1;else throw new w(eb);var Tb=new y(va=>\": \"+va);if(a.F){var Nb=ut(Q(),\"| \",a.r)+\"Typing unit statements\";ff(gf(),Nb+\"\\n\")}a.r=1+a.r|0;try{var ic=ffa(a,M,d,e,g,l,vb)}finally{a.r=-1+a.r|0}if(dx(new E(Tb),a.qa)&&a.F){var Va=\"\"+ut(Q(),\"| \",a.r)+Tb.n(ic);ff(gf(),Va+\"\\n\")}if(tb===u())var cb=u();else{var zb=tb.e(),\nUb=new z(zb.j().kh,u());l=Ub;for(var jb=tb.f();jb!==u();){var db=jb.e(),ub=new z(db.j().kh,u());l=l.p=ub;jb=jb.f()}cb=Ub}var Aa=new By(a,cb,ic)}finally{a.r=-1+a.r|0}dx(new E(h),a.qa)&&a.F&&(h=\"\"+ut(Q(),\"| \",a.r)+h.n(Aa),ff(gf(),h+\"\\n\"));return Aa}\nfunction Jx(a,b,c,d,e){var g=Xu().X(),h=c.x;c=b.Ag();if(d.b()){var k=b.Ag();b=n=>{if(null!==n){n=n.hb;var r=n.ji;t();var v=new L(n),x=n.kg,A=O().c,B=O().c;return new lx(a,n.Xa,A,B,v,x,!1,r)}throw new w(n);};if(k===u())b=u();else{d=k.e();var l=d=new z(b(d),u());for(k=k.f();k!==u();){var m=k.e();m=new z(b(m),u());l=l.p=m;k=k.f()}b=d}}else b=d.o();c=new Wq(c,c,b);b=new fn((n,r)=>{n=G(new H,n,r);var v=n.y;r=n.w;if(null!==v){n=v.kc;v=v.hb;if(r instanceof lx){if(a.F){var x=ut(Q(),\"| \",a.r)+(\"Passing \"+\nn.V+\" :: \"+v+\" \\x3c\\x3d\\x3c \")+r;ff(gf(),x+\"\\n\")}}else{a.F&&(x=ut(Q(),\"| \",a.r)+(\"Assigning \"+n.V+\" :: \"+v+\" :\\x3d \"+r+\" where \")+xx(r),ff(gf(),x+\"\\n\"));x=v.ji;t();var A=new L(v),B=v.kg,C=vy(v),D=rA(v),F=r.Ea();x=new lx(a,F,C,D,A,B,!1,x);a.F&&(A=ut(Q(),\"| \",a.r)+(\"Set \"+x+\" ~\\x3e \")+v,ff(gf(),A+\"\\n\"));up(tp(),x.Sb.b());if(!vy(x).b())throw new Yj(\"assertion failed: \"+vy(x));if(!rA(x).b())throw new Yj(\"assertion failed: \"+rA(x));wy(x,(t(),new L(r)));r=x}v=G(new H,v,r);g.$(v);v=h+\"#\"+n.V;t();n=new Vw(a,\nn,new Uw(a,new L(r),r,V(a)),!0,e.da);return G(new H,v,n)}throw new w(n);});Yq();c=Ew(c,b);op();c=pp(qp(),c);return G(new H,g,c)}function Fx(){}Fx.prototype=new eW;Fx.prototype.constructor=Fx;f=Fx.prototype;f.pj=function(a,b){return a instanceof Zn&&!rx(a)?a.Rb:b.n(a)};f.rj=function(a){return a instanceof Zn&&!rx(a)?!0:!1};f.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};\nf.$classData=q({rX:0},!1,\"mlscript.NuTypeDefs$DelayedTypeInfoImpl$$anonfun$$nestedInanonfun$allFields$4$1\",{rX:1,Kf:1,g:1,la:1,za:1,l:1});function sx(){}sx.prototype=new eW;sx.prototype.constructor=sx;f=sx.prototype;f.pj=function(a,b){if(a instanceof Zn){var c=a.wd,d=a.Yc;c=t().d===c?!0:c instanceof L&&!1===!!c.k?!0:!1;if(c&&d instanceof fe)return a}return b.n(a)};f.rj=function(a){if(a instanceof Zn){var b=a.wd;a=a.Yc;b=t().d===b?!0:b instanceof L&&!1===!!b.k?!0:!1;if(b&&a instanceof fe)return!0}return!1};\nf.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};f.$classData=q({sX:0},!1,\"mlscript.NuTypeDefs$DelayedTypeInfoImpl$$anonfun$2\",{sX:1,Kf:1,g:1,la:1,za:1,l:1});function Zy(a){this.FN=null;if(null===a)throw null;this.FN=a}Zy.prototype=new eW;Zy.prototype.constructor=Zy;Zy.prototype.Lc=function(a){return a instanceof Vw||a instanceof bx};\nZy.prototype.Ob=function(a,b){if(a instanceof Vw)b=a.ij.Zr(),a=G(new H,b,a.ig);else if(a instanceof bx){b=a.hh;a=a.Mb.Rb;var c=V(this.FN.J);b=new Uw(b.q,R(),b,c);a=G(new H,a,b)}else a=b.n(a);return a};Zy.prototype.$classData=q({tX:0},!1,\"mlscript.NuTypeDefs$DelayedTypeInfoImpl$$anonfun$3\",{tX:1,Kf:1,g:1,la:1,za:1,l:1});function L_(){}L_.prototype=new eW;L_.prototype.constructor=L_;L_.prototype.Lc=function(a){return null!==a&&a.Rd instanceof L?!0:!1};\nL_.prototype.Ob=function(a,b){a:{if(null!==a){var c=a.hb,d=a.Rd;if(d instanceof L){a=G(new H,c,d.k);break a}}a=b.n(a)}return a};L_.prototype.$classData=q({BX:0},!1,\"mlscript.NuTypeDefs$TypedNuCls$$anonfun$1\",{BX:1,Kf:1,g:1,la:1,za:1,l:1});function Zr(a){this.qx=a}Zr.prototype=new Wz;Zr.prototype.constructor=Zr;f=Zr.prototype;f.H=function(){return\"OPEN_BRACKET\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.qx:$K(W(),a)};f.D=function(a){return a instanceof Zr};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof Zr?this.qx===a.qx:!1};f.$classData=q({IX:0},!1,\"mlscript.OPEN_BRACKET\",{IX:1,yk:1,g:1,E:1,v:1,l:1});function gz(){}gz.prototype=new eW;gz.prototype.constructor=gz;f=gz.prototype;f.vJ=function(a,b){if(a instanceof Pl){var c=a.Za,d=a.Qb,e=c.A();if(e.b())e=!1;else{e=e.o();var g=d.A();g.b()?e=!1:(g=g.o(),e=e.fh>g.fh)}if(e)return G(new H,c,d)}return b.n(a)};\nf.OJ=function(a){if(a instanceof Pl){var b=a.Qb;a=a.Za.A();a.b()?b=!1:(a=a.o(),b=b.A(),b.b()?b=!1:(b=b.o(),b=a.fh>b.fh));if(b)return!0}return!1};f.Lc=function(a){return this.OJ(a)};f.Ob=function(a,b){return this.vJ(a,b)};f.$classData=q({KX:0},!1,\"mlscript.OpApp$$anonfun$unapply$1\",{KX:1,Kf:1,g:1,la:1,za:1,l:1});function cf(a){this.NN=null;this.$H=!1;this.Xz=a}cf.prototype=new p;cf.prototype.constructor=cf;f=cf.prototype;\nf.nv=function(){if(!this.$H&&!this.$H){for(var a=TE(PE()),b=this.Xz,c=null,d=null;b!==u();){var e=b.e().nv();if(null===e)throw new w(e);var g=e.j();a.zc(e.h());for(e=g.m();e.s();)g=new z(e.t(),u()),null===d?c=g:d.p=g,d=g;b=b.f()}d=null===c?u():c;Od();b=new fp;Od();for(c=new fp;!d.b();){e=d.e();if(e instanceof Oo)t(),e=new fe(e);else if(e&&e.$classData&&e.$classData.rb.ce)t(),e=new Ud(e);else{if(!(e instanceof Zn))throw e instanceof Po&&xm(\"Program reached and unexpected state.\"),new w(e);var h=e;\ne=h.wd;g=h.Rb;h=h.Yc;t();e=new No(!(!e.b()&&!e.o()),g,h,e.b());e=new Ud(e)}if(e instanceof fe)wp(b,e.aa);else if(e instanceof Ud)wp(c,e.fa);else throw new w(e);d=d.f()}b=G(new H,b.ha(),c.ha());a=a.ha();this.NN=G(new H,a,b);this.$H=!0}return this.NN};f.H=function(){return\"Pgrm\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Xz:$K(W(),a)};f.D=function(a){return a instanceof cf};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof cf){var b=this.Xz;a=a.Xz;return null===b?null===a:b.i(a)}return!1};f.$classData=q({NX:0},!1,\"mlscript.Pgrm\",{NX:1,g:1,Faa:1,E:1,v:1,l:1});function Bz(a,b){this.zE=a;this.yE=b}Bz.prototype=new Gz;Bz.prototype.constructor=Bz;f=Bz.prototype;f.Ua=function(){return this.zE};f.dQ=function(a){return this.yE.n(a)};f.H=function(){return\"BuiltinFunc\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.zE;case 1:return this.yE;default:return $K(W(),a)}};f.D=function(a){return a instanceof Bz};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Bz&&this.zE===a.zE){var b=this.yE;a=a.yE;return null===b?null===a:b.i(a)}return!1};f.$classData=q({SX:0},!1,\"mlscript.Polyfill$BuiltinFunc\",{SX:1,TX:1,g:1,E:1,v:1,l:1});function wz(a,b){this.BE=a;this.AE=b}wz.prototype=new Gz;\nwz.prototype.constructor=wz;f=wz.prototype;f.Ua=function(){return this.BE};f.dQ=function(a){return this.AE.n(a)};f.H=function(){return\"RuntimeHelper\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.BE;case 1:return this.AE;default:return $K(W(),a)}};f.D=function(a){return a instanceof wz};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof wz&&this.BE===a.BE){var b=this.AE;a=a.AE;return null===b?null===a:b.i(a)}return!1};\nf.$classData=q({UX:0},!1,\"mlscript.Polyfill$RuntimeHelper\",{UX:1,TX:1,g:1,E:1,v:1,l:1});function I_(){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0}I_.prototype=new ZS;I_.prototype.constructor=I_;function M_(){}M_.prototype=I_.prototype;I_.prototype.Vj=function(){return EP(this)};function yn(a){0===(1&a.Qe)<<24>>24&&0===(1&a.Qe)<<24>>24&&(a.Dg=hea(a),a.Qe=(1|a.Qe)<<24>>24);return a.Dg}\nfunction zn(a){0===(2&a.Qe)<<24>>24&&0===(2&a.Qe)<<24>>24&&(a.Eg=iea(a),a.Qe=(2|a.Qe)<<24>>24);return a.Eg}function HP(){}HP.prototype=new eW;HP.prototype.constructor=HP;f=HP.prototype;f.nr=function(a,b){if(null!==a){var c=a.j();if(null!==c&&(c=c.ya,c instanceof Cl))return c.Fm}return b.n(a)};f.sr=function(a){return null!==a&&(a=a.j(),null!==a&&a.ya instanceof Cl)?!0:!1};f.Lc=function(a){return this.sr(a)};f.Ob=function(a,b){return this.nr(a,b)};\nf.$classData=q({yY:0},!1,\"mlscript.TypeLikeImpl$$anonfun$1\",{yY:1,Kf:1,g:1,la:1,za:1,l:1});function IP(){}IP.prototype=new eW;IP.prototype.constructor=IP;f=IP.prototype;f.pj=function(a,b){return a instanceof Ct?a:b.n(a)};f.rj=function(a){return a instanceof Ct};f.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};f.$classData=q({zY:0},!1,\"mlscript.TypeLikeImpl$$anonfun$2\",{zY:1,Kf:1,g:1,la:1,za:1,l:1});function CP(a,b){this.WN=b}CP.prototype=new eW;\nCP.prototype.constructor=CP;f=CP.prototype;\nf.pj=function(a,b){if(a instanceof Po){b=a.ks;a=yP(this.WN);var c=b.Ra;b=h=>{if(null!==h){var k=new L(h);if(!k.b()&&(h=k.k.h(),k=k.k.j(),t().d===h&&null!==k)){h=k.yb;k=k.ya;var l=tm().Cg;if((null===l?null===h:l.i(h))&&k instanceof Cl&&(h=k.ai,k=k.Fm,h instanceof vl))return h.x+\": \"+yf(k,0,this.WN)}}xm(\"ill-formed constructor parameter\")};if(c===u())b=u();else{var d=c.e(),e=d=new z(b(d),u());for(c=c.f();c!==u();){var g=c.e();g=new z(b(g),u());e=e.p=g;c=c.f()}b=d}return a+\"constructor(\"+ze(b,\"\",\", \",\n\"\")+\")\\n\"}return b.n(a)};f.rj=function(a){return a instanceof Po};f.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};f.$classData=q({AY:0},!1,\"mlscript.TypeLikeImpl$$anonfun$showIn$38\",{AY:1,Kf:1,g:1,la:1,za:1,l:1});function DP(){}DP.prototype=new eW;DP.prototype.constructor=DP;f=DP.prototype;f.pj=function(a,b){return a instanceof Ct?a:b.n(a)};f.rj=function(a){return a instanceof Ct};f.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};\nf.$classData=q({BY:0},!1,\"mlscript.TypeLikeImpl$$anonfun$showIn$39\",{BY:1,Kf:1,g:1,la:1,za:1,l:1});function bB(){}bB.prototype=new eW;bB.prototype.constructor=bB;f=bB.prototype;f.wJ=function(a,b){if(a instanceof nC){var c=a.rp;if(null!==c)return a=c.x,Nu(Q(),a)}return b.n(a)};f.PJ=function(a){return a instanceof nC&&null!==a.rp?!0:!1};f.Lc=function(a){return this.PJ(a)};f.Ob=function(a,b){return this.wJ(a,b)};f.$classData=q({EY:0},!1,\"mlscript.TypeSimplifier$$anonfun$1\",{EY:1,Kf:1,g:1,la:1,za:1,l:1});\nfunction wA(a){this.jA=null;if(null===a)throw null;this.jA=a}wA.prototype=new eW;wA.prototype.constructor=wA;f=wA.prototype;\nf.nr=function(a,b){if(null!==a){var c=a.h(),d=a.j();if(null!==c){iC(this.jA);var e=c.Sb;if(!e.b()&&(e=e.o(),d instanceof L)){if(d.k)return a=G(new H,!0,e),G(new H,a,c);a=G(new H,!1,e);return G(new H,a,c)}}}if(null!==a&&(c=a.h(),d=a.j(),d instanceof L)){if(d.k){a=vy(c);for(b=this.jA.ib;!a.b();)d=a.e(),e=V(b.q),b=dv(b,d,e,!1),a=a.f();a=G(new H,!0,b);return G(new H,a,c)}a=rA(c);for(b=this.jA.La;!a.b();)d=a.e(),e=V(b.q),b=sA(b,d,e),a=a.f();a=G(new H,!1,b);return G(new H,a,c)}return b.n(a)};\nf.sr=function(a){if(null!==a){var b=a.h(),c=a.j();if(null!==b&&(iC(this.jA),!b.Sb.b()&&c instanceof L))return!0}return null!==a&&a.j()instanceof L?!0:!1};f.Lc=function(a){return this.sr(a)};f.Ob=function(a,b){return this.nr(a,b)};f.$classData=q({FY:0},!1,\"mlscript.TypeSimplifier$$anonfun$2\",{FY:1,Kf:1,g:1,la:1,za:1,l:1});function N_(a,b){this.ZN=b}N_.prototype=new eW;N_.prototype.constructor=N_;N_.prototype.Lc=function(a){return a instanceof qx};\nN_.prototype.Ob=function(a,b){a instanceof qx?(b=a.tp,a=a.vA,up(tp(),!this.ZN.kt.b()),this.ZN.kt=a.kt,a=b):a=b.n(a);return a};N_.prototype.$classData=q({LY:0},!1,\"mlscript.Typer$$anonfun$$nestedInanonfun$typeTerm$2$1\",{LY:1,Kf:1,g:1,la:1,za:1,l:1});function O_(){}O_.prototype=new eW;O_.prototype.constructor=O_;f=O_.prototype;f.vJ=function(a,b){if(a instanceof vl)return a;if(a instanceof Cl){var c=a.ai;if(c instanceof vl)return c}return b.n(a)};\nf.OJ=function(a){return a instanceof vl||a instanceof Cl&&a.ai instanceof vl?!0:!1};f.Lc=function(a){return this.OJ(a)};f.Ob=function(a,b){return this.vJ(a,b)};f.$classData=q({MY:0},!1,\"mlscript.Typer$$anonfun$1\",{MY:1,Kf:1,g:1,la:1,za:1,l:1});function P_(a,b,c,d,e,g){this.nI=this.oI=this.lI=null;this.qI=!1;this.mI=this.pI=null;if(null===a)throw null;this.lI=a;this.oI=b;this.nI=c;this.qI=d;this.pI=e;this.mI=g}P_.prototype=new eW;P_.prototype.constructor=P_;f=P_.prototype;\nf.nr=function(a,b){if(null!==a){var c=a.j();if(c instanceof bx)return Q_(this.lI,c,this.oI,this.nI,this.qI,this.pI,this.mI)}return null!==a&&(c=a.j(),c instanceof Cx)?Q_(this.lI,c,this.oI,this.nI,this.qI,this.pI,this.mI):b.n(a)};f.sr=function(a){return null!==a&&a.j()instanceof bx||null!==a&&a.j()instanceof Cx?!0:!1};f.Lc=function(a){return this.sr(a)};f.Ob=function(a,b){return this.nr(a,b)};f.$classData=q({NY:0},!1,\"mlscript.Typer$$anonfun$mkTypingUnit$1$1\",{NY:1,Kf:1,g:1,la:1,za:1,l:1});\nfunction R_(a){this.go=this.lh=this.Ga=null;this.Ix=this.Zm=!1;this.Wu=null;jx(this,a,t().d,\"expression\",(tx(a),t().d),(tx(a),!1))}R_.prototype=new rY;R_.prototype.constructor=R_;R_.prototype.u=function(){return\"[NO PROV]\"};R_.prototype.$classData=q({RY:0},!1,\"mlscript.Typer$NoProv$\",{RY:1,VO:1,g:1,E:1,v:1,l:1});function vC(){}vC.prototype=new eW;vC.prototype.constructor=vC;f=vC.prototype;f.zJ=function(a,b){if(a instanceof L){var c=a.k;if(c instanceof qx&&(c=c.tp,null!==c))return DB(c)}return b.n(a)};\nf.SJ=function(a){return a instanceof L&&(a=a.k,a instanceof qx&&null!==a.tp)?!0:!1};f.Lc=function(a){return this.SJ(a)};f.Ob=function(a,b){return this.zJ(a,b)};f.$classData=q({TY:0},!1,\"mlscript.Typer$ValidPatVar$$anonfun$unapply$3\",{TY:1,Kf:1,g:1,la:1,za:1,l:1});function wC(a,b,c){this.dO=this.Ex=this.cO=null;if(null===a)throw null;this.cO=a;this.Ex=b;this.dO=c}wC.prototype=new eW;wC.prototype.constructor=wC;f=wC.prototype;\nf.zJ=function(a,b){if(a instanceof L){var c=a.k;if(c instanceof Mu&&(c=c.pd,c instanceof vl&&this.Ex.x===c.x)){a=this.cO.rI;b=new Te(new Ue(J(new K,[\"Variable name '\",\"' already names a symbol in scope. \"])));c=[We(Xe(),this.Ex.x)];JX(a,PX(PX(Ye(b,J(new K,c)),We(Xe(),\"If you want to refer to that symbol, you can use `scope.\"+this.Ex.x+\"`; \")),We(Xe(),\"if not, give your future readers a break and use another name :^)\")),this.Ex.A(),this.dO);return}}return b.n(a)};\nf.SJ=function(a){return a instanceof L&&(a=a.k,a instanceof Mu&&(a=a.pd,a instanceof vl&&this.Ex.x===a.x))?!0:!1};f.Lc=function(a){return this.SJ(a)};f.Ob=function(a,b){return this.zJ(a,b)};f.$classData=q({UY:0},!1,\"mlscript.Typer$ValidPatVar$$anonfun$unapply$4\",{UY:1,Kf:1,g:1,la:1,za:1,l:1});function hX(){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0}hX.prototype=new qY;hX.prototype.constructor=hX;function S_(){}S_.prototype=hX.prototype;\nfunction ZB(){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0}ZB.prototype=new qY;ZB.prototype.constructor=ZB;function T_(){}T_.prototype=ZB.prototype;ZB.prototype.Ea=function(){return this.mc().Ea()};ZB.prototype.ub=function(a,b){return this.mc().ub(a,b)};ZB.prototype.u=function(){return\"[\"+this.mc()+\"]\"};function qx(a,b,c){this.J=null;this.tp=b;this.vA=c;FC(this,a)}qx.prototype=new HC;qx.prototype.constructor=qx;f=qx.prototype;f.H=function(){return\"VarSymbol\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.tp;case 1:return this.vA;default:return $K(W(),a)}};f.D=function(a){return a instanceof qx};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof qx&&a.J===this.J){var b=this.tp,c=a.tp;if(null===b?null===c:mC(b,c))return b=this.vA,a=a.vA,null===b?null===a:b.i(a)}return!1};f.$classData=q({MZ:0},!1,\"mlscript.TyperDatatypes$VarSymbol\",{MZ:1,UO:1,g:1,E:1,v:1,l:1});function aQ(){}aQ.prototype=new eW;\naQ.prototype.constructor=aQ;f=aQ.prototype;f.pj=function(a,b){return a instanceof Zn&&a.Yc.tv()?a.Rb.x:b.n(a)};f.rj=function(a){return a instanceof Zn&&a.Yc.tv()?!0:!1};f.Lc=function(a){return this.rj(a)};f.Ob=function(a,b){return this.pj(a,b)};f.$classData=q({$Z:0},!1,\"mlscript.TypingUnitImpl$$anonfun$3\",{$Z:1,Kf:1,g:1,la:1,za:1,l:1});function YE(a,b,c,d){this.lf=null;this.bv=a;this.cv=b;this.Ux=c;this.I_=d;qE(this)}YE.prototype=new sE;YE.prototype.constructor=YE;f=YE.prototype;f.Cv=function(){return this.I_};\nf.u=function(){return\"\\u00ab\"+this.bv+\" \\x3d \"+this.cv+\"\\u00bb\"+tE(this)};f.H=function(){return\"Binding\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.bv;case 1:return this.cv;case 2:return this.Ux;default:return $K(W(),a)}};f.D=function(a){return a instanceof YE};f.B=function(){var a=lb(\"Binding\");a=W().C(-889275714,a);var b=this.bv;b=My(W(),b);a=W().C(a,b);b=this.cv;b=My(W(),b);a=W().C(a,b);b=this.Ux?1231:1237;a=W().C(a,b);return W().Ma(a,3)};\nf.i=function(a){if(this===a)return!0;if(a instanceof YE&&this.Ux===a.Ux){var b=this.bv,c=a.bv;if(null===b?null===c:b.i(c))return b=this.cv,a=a.cv,null===b?null===a:b.i(a)}return!1};f.$classData=q({H_:0},!1,\"mlscript.ucs.Clause$Binding\",{H_:1,VA:1,g:1,E:1,v:1,l:1});function XE(a,b){this.lf=null;this.Vx=a;this.K_=b;qE(this)}XE.prototype=new sE;XE.prototype.constructor=XE;f=XE.prototype;f.Cv=function(){return this.K_};f.u=function(){return\"\\u00ab\"+this.Vx+\"\\u00bb\"+tE(this)};f.H=function(){return\"BooleanTest\"};\nf.G=function(){return 1};f.I=function(a){return 0===a?this.Vx:$K(W(),a)};f.D=function(a){return a instanceof XE};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof XE){var b=this.Vx;a=a.Vx;return null===b?null===a:b.i(a)}return!1};f.$classData=q({J_:0},!1,\"mlscript.ucs.Clause$BooleanTest\",{J_:1,VA:1,g:1,E:1,v:1,l:1});function WE(a,b,c,d){this.lf=null;this.ev=a;this.dv=b;this.ay=c;this.UP=d;qE(this)}WE.prototype=new sE;WE.prototype.constructor=WE;f=WE.prototype;\nf.Cv=function(){return this.UP};f.u=function(){return\"\\u00ab\"+this.ev+\" is Tuple#\"+this.dv+\"\\u00bb\"+tE(this)};f.H=function(){return\"MatchTuple\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.ev;case 1:return this.dv;case 2:return this.ay;default:return $K(W(),a)}};f.D=function(a){return a instanceof WE};\nf.B=function(){var a=lb(\"MatchTuple\");a=W().C(-889275714,a);var b=this.ev;b=My(W(),b);a=W().C(a,b);b=this.dv;a=W().C(a,b);b=this.ay;b=My(W(),b);a=W().C(a,b);return W().Ma(a,3)};f.i=function(a){if(this===a)return!0;if(a instanceof WE&&this.dv===a.dv){var b=this.ev,c=a.ev;if(null===b?null===c:b.i(c))return b=this.ay,a=a.ay,null===b?null===a:b.i(a)}return!1};f.$classData=q({P_:0},!1,\"mlscript.ucs.Clause$MatchTuple\",{P_:1,VA:1,g:1,E:1,v:1,l:1});function $E(){}$E.prototype=new zE;\n$E.prototype.constructor=$E;f=$E.prototype;f.u=function(){return\"pattern destruction\"};f.H=function(){return\"FieldExtraction\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof $E};f.B=function(){return 1536009313};f.$classData=q({U_:0},!1,\"mlscript.ucs.LetBinding$Kind$FieldExtraction$\",{U_:1,WP:1,g:1,E:1,v:1,l:1});var ZE;function U_(){}U_.prototype=new zE;U_.prototype.constructor=U_;f=U_.prototype;f.u=function(){return\"interleaved let\"};f.H=function(){return\"InterleavedLet\"};\nf.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof U_};f.B=function(){return 1258608914};f.$classData=q({V_:0},!1,\"mlscript.ucs.LetBinding$Kind$InterleavedLet$\",{V_:1,WP:1,g:1,E:1,v:1,l:1});var V_;function KE(){V_||(V_=new U_);return V_}function W_(){}W_.prototype=new zE;W_.prototype.constructor=W_;f=W_.prototype;f.u=function(){return\"scrutinee alias\"};f.H=function(){return\"ScrutineeAlias\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};\nf.D=function(a){return a instanceof W_};f.B=function(){return-1538996278};f.$classData=q({W_:0},!1,\"mlscript.ucs.LetBinding$Kind$ScrutineeAlias$\",{W_:1,WP:1,g:1,E:1,v:1,l:1});var X_;function aF(){X_||(X_=new W_);return X_}function FE(a,b){this.pt=null;this.Tj=a;this.pl=b;this.pt=jA().X()}FE.prototype=new iF;FE.prototype.constructor=FE;f=FE.prototype;f.xt=function(){return this.pl};f.oQ=function(){var a=this.Tj.j().ia();return VE(new FE(G(new H,this.Tj.iy(),a),this.pl.or()),this.pt)};\nf.FF=function(a,b){var c=!1,d=null;if(a instanceof Dl)return!1;if(a instanceof vl){c=!0;d=a;var e=d.x;if(\"true\"===e||\"false\"===e)return!1}if(c&&d.x===this.Tj.h().x)return!0;if(c){a=b.U(d.x);if(a instanceof L)return a.k.L(this.Tj.h().x);if(R()===a)return!1;throw new w(a);}throw new w(a);};function Y_(a,b){var c=a.Tj.j();b=b.m();b=new iy(b,new y(d=>!a.Tj.j().L(d)),!1);c.zc(b)}f.H=function(){return\"Constructor\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.Tj;case 1:return this.pl;default:return $K(W(),a)}};f.D=function(a){return a instanceof FE};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof FE){var b=this.Tj,c=a.Tj;if(null===b?null===c:b.i(c))return b=this.pl,a=a.pl,null===b?null===a:b.i(a)}return!1};f.$classData=q({c0:0},!1,\"mlscript.ucs.MutCaseOf$MutCase$Constructor\",{c0:1,b0:1,g:1,E:1,v:1,l:1});\nfunction EE(a,b){this.pt=null;this.ir=a;this.Jp=b;this.pt=jA().X()}EE.prototype=new iF;EE.prototype.constructor=EE;f=EE.prototype;f.xt=function(){return this.Jp};f.oQ=function(){return VE(new EE(this.ir,this.Jp.or()),this.pt)};f.FF=function(a){var b=a instanceof Dl?!0:a instanceof vl&&\"true\"===a.x?!0:a instanceof vl&&\"false\"===a.x?!0:!1;if(b)return Pe(new E(a),this.ir);if(a instanceof vl)return!1;throw new w(a);};f.H=function(){return\"Literal\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.ir;case 1:return this.Jp;default:return $K(W(),a)}};f.D=function(a){return a instanceof EE};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof EE){var b=this.ir,c=a.ir;if(null===b?null===c:b.i(c))return b=this.Jp,a=a.Jp,null===b?null===a:b.i(a)}return!1};f.$classData=q({d0:0},!1,\"mlscript.ucs.MutCaseOf$MutCase$Literal\",{d0:1,b0:1,g:1,E:1,v:1,l:1});function Z_(){$_=this;O()}Z_.prototype=new kF;\nZ_.prototype.constructor=Z_;f=Z_.prototype;f.oo=function(a){var b=O().c;return new a0(a,new z(a,b))};f.H=function(){return\"Empty\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof Z_};f.B=function(){return 67081517};f.u=function(){return\"Empty\"};f.$classData=q({e0:0},!1,\"mlscript.ucs.PartialTerm$Empty$\",{e0:1,YP:1,g:1,E:1,v:1,l:1});var $_;function b0(){$_||($_=new Z_);return $_}function c0(a,b,c){this.uF=a;this.vF=b;this.$A=c}c0.prototype=new kF;\nc0.prototype.constructor=c0;f=c0.prototype;f.oo=function(a,b){var c=rF(tF(),a,b);if(null===c)throw new w(c);a=c.h();c=c.j();a=pF(tF(),this.uF,this.vF,a,b);if(t().d===c)return new a0(a,this.$A);if(c instanceof L)return c=c.k,b=pF(tF(),a,new vl(\"and\"),c,b),new a0(b,new z(c,this.$A));throw new w(c);};f.H=function(){return\"Half\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.uF;case 1:return this.vF;case 2:return this.$A;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof c0};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof c0){var b=this.uF,c=a.uF;if(null===b?null===c:b.i(c))if(b=this.vF,c=a.vF,null===b?null===c:b.i(c))return b=this.$A,a=a.$A,null===b?null===a:b.i(a)}return!1};f.$classData=q({f0:0},!1,\"mlscript.ucs.PartialTerm$Half\",{f0:1,YP:1,g:1,E:1,v:1,l:1});function a0(a,b){this.jr=a;this.aB=b}a0.prototype=new kF;a0.prototype.constructor=a0;f=a0.prototype;\nf.oo=function(a){throw new vY(\"expect an operator but term \"+a+\" was given\");};function d0(a,b){return new c0(a.jr,b,new z(b,a.aB))}f.H=function(){return\"Total\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.jr;case 1:return this.aB;default:return $K(W(),a)}};f.D=function(a){return a instanceof a0};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof a0){var b=this.jr,c=a.jr;if(null===b?null===c:b.i(c))return b=this.aB,a=a.aB,null===b?null===a:b.i(a)}return!1};f.$classData=q({g0:0},!1,\"mlscript.ucs.PartialTerm$Total\",{g0:1,YP:1,g:1,E:1,v:1,l:1});function pQ(){}pQ.prototype=new zY;pQ.prototype.constructor=pQ;pQ.prototype.n=function(a){return a};pQ.prototype.u=function(){return\"generalized constraint\"};\npQ.prototype.$classData=q({V2:0},!1,\"scala.$less$colon$less$$anon$1\",{V2:1,cba:1,dba:1,g:1,la:1,l:1});class w extends iW{constructor(a){super();this.kR=null;this.FK=!1;this.fG=a;yF(this,null,null,!0)}qj(){if(!this.FK&&!this.FK){if(null===this.fG)var a=\"null\";else try{a=nb(this.fG)+\" (of class \"+na(this.fG)+\")\"}catch(b){a=\"an instance of class \"+na(this.fG)}this.kR=a;this.FK=!0}return this.kR}}w.prototype.$classData=q({Z2:0},!1,\"scala.MatchError\",{Z2:1,Te:1,qd:1,pc:1,g:1,l:1});function e0(){}\ne0.prototype=new p;e0.prototype.constructor=e0;function f0(){}f=f0.prototype=e0.prototype;f.b=function(){return this===R()};f.Q=function(){return this.b()?0:1};f.L=function(a){return!this.b()&&ml(nl(),this.o(),a)};f.m=function(){if(this.b())return Rq().Pa;Rq();var a=this.o();return new g0(a)};f.ha=function(){if(this.b()){O();var a=u();return Pd(u(),a)}return new z(this.o(),O().c)};function G(a,b,c){a.y=b;a.w=c;return a}function H(){this.w=this.y=null}H.prototype=new p;H.prototype.constructor=H;\nfunction h0(){}f=h0.prototype=H.prototype;f.G=function(){return 2};f.I=function(a){a:switch(a){case 0:a=this.h();break a;case 1:a=this.j();break a;default:throw aL(new bL,a+\" is out of bounds (min 0, max 1)\");}return a};f.h=function(){return this.y};f.j=function(){return this.w};f.u=function(){return\"(\"+this.h()+\",\"+this.j()+\")\"};f.Cw=function(){return G(new H,this.j(),this.h())};f.iy=function(){return this.h()};f.H=function(){return\"Tuple2\"};f.D=function(a){return a instanceof H};f.B=function(){return AL(this)};\nf.i=function(a){return this===a?!0:a instanceof H?ml(nl(),this.h(),a.h())&&ml(nl(),this.j(),a.j()):!1};f.Rc=function(){return!!this.h()};f.aQ=function(){return Ea(this.h())};f.ut=function(){return this.h()|0};f.cy=function(){return!!this.j()};f.Sc=function(){return this.j()|0};f.$classData=q({by:0},!1,\"scala.Tuple2\",{by:1,g:1,LB:1,E:1,v:1,l:1});function tl(a,b,c){this.kc=a;this.hb=b;this.Rd=c}tl.prototype=new p;tl.prototype.constructor=tl;f=tl.prototype;f.G=function(){return 3};\nf.I=function(a){a:switch(a){case 0:a=this.kc;break a;case 1:a=this.hb;break a;case 2:a=this.Rd;break a;default:throw aL(new bL,a+\" is out of bounds (min 0, max 2)\");}return a};f.u=function(){return\"(\"+this.kc+\",\"+this.hb+\",\"+this.Rd+\")\"};f.H=function(){return\"Tuple3\"};f.D=function(a){return a instanceof tl};f.B=function(){return AL(this)};f.i=function(a){return this===a?!0:a instanceof tl?ml(nl(),this.kc,a.kc)&&ml(nl(),this.hb,a.hb)&&ml(nl(),this.Rd,a.Rd):!1};\nf.$classData=q({J0:0},!1,\"scala.Tuple3\",{J0:1,g:1,hba:1,E:1,v:1,l:1});function Gp(a,b,c,d){this.Uj=a;this.oj=b;this.oi=c;this.Xi=d}Gp.prototype=new p;Gp.prototype.constructor=Gp;f=Gp.prototype;f.G=function(){return 4};f.I=function(a){return qea(this,a)};f.u=function(){return\"(\"+this.Uj+\",\"+this.oj+\",\"+this.oi+\",\"+this.Xi+\")\"};f.H=function(){return\"Tuple4\"};f.D=function(a){return a instanceof Gp};f.B=function(){return AL(this)};\nf.i=function(a){return this===a?!0:a instanceof Gp?ml(nl(),this.Uj,a.Uj)&&ml(nl(),this.oj,a.oj)&&ml(nl(),this.oi,a.oi)&&ml(nl(),this.Xi,a.Xi):!1};f.$classData=q({K0:0},!1,\"scala.Tuple4\",{K0:1,g:1,iba:1,E:1,v:1,l:1});function WX(a,b,c,d,e){this.hv=a;this.qt=b;this.kr=c;this.iv=d;this.jv=e}WX.prototype=new p;WX.prototype.constructor=WX;f=WX.prototype;f.G=function(){return 5};f.I=function(a){return rea(this,a)};f.u=function(){return\"(\"+this.hv+\",\"+this.qt+\",\"+this.kr+\",\"+this.iv+\",\"+this.jv+\")\"};\nf.H=function(){return\"Tuple5\"};f.D=function(a){return a instanceof WX};f.B=function(){return AL(this)};f.i=function(a){return this===a?!0:a instanceof WX?ml(nl(),this.hv,a.hv)&&ml(nl(),this.qt,a.qt)&&ml(nl(),this.kr,a.kr)&&ml(nl(),this.iv,a.iv)&&ml(nl(),this.jv,a.jv):!1};f.$classData=q({L0:0},!1,\"scala.Tuple5\",{L0:1,g:1,jba:1,E:1,v:1,l:1});function bo(a,b,c,d,e,g){this.lr=a;this.mr=b;this.rt=c;this.st=d;this.tt=e;this.kv=g}bo.prototype=new p;bo.prototype.constructor=bo;f=bo.prototype;f.G=function(){return 6};\nf.I=function(a){return sea(this,a)};f.u=function(){return\"(\"+this.lr+\",\"+this.mr+\",\"+this.rt+\",\"+this.st+\",\"+this.tt+\",\"+this.kv+\")\"};f.H=function(){return\"Tuple6\"};f.D=function(a){return a instanceof bo};f.B=function(){return AL(this)};f.i=function(a){return this===a?!0:a instanceof bo?ml(nl(),this.lr,a.lr)&&ml(nl(),this.mr,a.mr)&&ml(nl(),this.rt,a.rt)&&ml(nl(),this.st,a.st)&&ml(nl(),this.tt,a.tt)&&ml(nl(),this.kv,a.kv):!1};f.$classData=q({M0:0},!1,\"scala.Tuple6\",{M0:1,g:1,kba:1,E:1,v:1,l:1});\nfunction i0(a){this.RB=a}i0.prototype=new sT;i0.prototype.constructor=i0;i0.prototype.$classData=q({U4:0},!1,\"scala.collection.ClassTagSeqFactory$AnySeqDelegate\",{U4:1,Mba:1,g:1,bg:1,l:1,Nk:1});function j0(){this.Bl=null;this.Bl=xe()}j0.prototype=new MY;j0.prototype.constructor=j0;j0.prototype.$classData=q({X4:0},!1,\"scala.collection.IndexedSeq$\",{X4:1,FG:1,g:1,Nk:1,bg:1,l:1});var k0;function l0(a,b,c){for(a=a.Sd();a.s();)b=c.ba(a.t(),b);return b}\nfunction n0(a,b){return a.Ub().Ib(o0(new p0,b,a))}function q0(a,b){return a.vc(r0(new s0,a,b))}function t0(a,b){return a.Ub().Ib(u0(new v0,a,b))}function SF(a){return a.va(-1+a.K()|0)}function w0(a){return ze(a,a.Ih()+\"(\",\", \",\")\")}function Fs(a){return!!(a&&a.$classData&&a.$classData.rb.na)}function xo(a,b){this.zy=null;this.Lv=0;this.GR=this.XK=null;if(null===a)throw null;this.XK=a;this.GR=b;this.zy=Rq().Pa;this.Lv=-1}xo.prototype=new BY;xo.prototype.constructor=xo;\nxo.prototype.s=function(){if(-1===this.Lv){for(;!this.zy.s();){if(!this.XK.s())return this.Lv=0,this.zy=Rq().Pa,!1;this.zy=null;this.zy=this.GR.n(this.XK.t()).m();this.Lv=-1}this.Lv=1;return!0}return 1===this.Lv};xo.prototype.t=function(){this.s()&&(this.Lv=-1);return this.zy.t()};xo.prototype.$classData=q({e5:0},!1,\"scala.collection.Iterator$$anon$10\",{e5:1,Sa:1,g:1,Ka:1,M:1,N:1});function is(a,b){this.YK=null;this.g5=b;this.qG=!1;this.ZK=a}is.prototype=new BY;is.prototype.constructor=is;\nis.prototype.s=function(){return this.qG?!0:this.ZK.s()?(this.YK=this.ZK.t(),this.g5.n(this.YK)?this.qG=!0:this.ZK=Rq().Pa,this.qG):!1};is.prototype.t=function(){return this.s()?(this.qG=!1,this.YK):Rq().Pa.t()};is.prototype.$classData=q({f5:0},!1,\"scala.collection.Iterator$$anon$11\",{f5:1,Sa:1,g:1,Ka:1,M:1,N:1});function x0(a,b){this.rG=this.sG=null;if(null===a)throw null;this.rG=a;this.sG=b.m()}x0.prototype=new BY;x0.prototype.constructor=x0;f=x0.prototype;\nf.Q=function(){var a=this.rG.Q(),b=this.sG.Q();return a<b?a:b};f.s=function(){return this.rG.s()&&this.sG.s()};f.gm=function(){return G(new H,this.rG.t(),this.sG.t())};f.t=function(){return this.gm()};f.$classData=q({h5:0},!1,\"scala.collection.Iterator$$anon$14\",{h5:1,Sa:1,g:1,Ka:1,M:1,N:1});function Ao(a){this.uG=0;this.tG=null;if(null===a)throw null;this.tG=a;this.uG=0}Ao.prototype=new BY;Ao.prototype.constructor=Ao;f=Ao.prototype;f.Q=function(){return this.tG.Q()};f.s=function(){return this.tG.s()};\nf.gm=function(){var a=G(new H,this.tG.t(),this.uG);this.uG=1+this.uG|0;return a};f.t=function(){return this.gm()};f.$classData=q({i5:0},!1,\"scala.collection.Iterator$$anon$16\",{i5:1,Sa:1,g:1,Ka:1,M:1,N:1});function ST(){}ST.prototype=new BY;ST.prototype.constructor=ST;f=ST.prototype;f.s=function(){return!1};f.Q=function(){return 0};f.qk=function(){return this};f.t=function(){throw AH(\"next on empty iterator\");};\nf.$classData=q({j5:0},!1,\"scala.collection.Iterator$$anon$19\",{j5:1,Sa:1,g:1,Ka:1,M:1,N:1});function g0(a){this.l5=a;this.vG=!1}g0.prototype=new BY;g0.prototype.constructor=g0;g0.prototype.s=function(){return!this.vG};g0.prototype.t=function(){if(this.vG)return Rq().Pa.t();this.vG=!0;return this.l5};g0.prototype.qk=function(a,b){return this.vG||0<a||0===b?Rq().Pa:this};g0.prototype.$classData=q({k5:0},!1,\"scala.collection.Iterator$$anon$20\",{k5:1,Sa:1,g:1,Ka:1,M:1,N:1});function y0(a){this.o5=a}\ny0.prototype=new BY;y0.prototype.constructor=y0;y0.prototype.s=function(){return!0};y0.prototype.t=function(){return Es(this.o5)};y0.prototype.$classData=q({n5:0},!1,\"scala.collection.Iterator$$anon$27\",{n5:1,Sa:1,g:1,Ka:1,M:1,N:1});function iy(a,b,c){this.wG=null;this.xG=!1;this.IR=this.SB=null;this.HR=!1;if(null===a)throw null;this.SB=a;this.IR=b;this.HR=c;this.xG=!1}iy.prototype=new BY;iy.prototype.constructor=iy;\niy.prototype.s=function(){if(!this.xG){if(!this.SB.s())return!1;for(this.wG=this.SB.t();!!this.IR.n(this.wG)===this.HR;){if(!this.SB.s())return!1;this.wG=this.SB.t()}this.xG=!0}return!0};iy.prototype.t=function(){return this.s()?(this.xG=!1,this.wG):Rq().Pa.t()};iy.prototype.$classData=q({p5:0},!1,\"scala.collection.Iterator$$anon$6\",{p5:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction hy(a,b){this.NR=null;this.yG=!1;this.LR=this.aL=this.MR=null;if(null===a)throw null;this.aL=a;this.LR=b;this.NR=Vn();this.yG=!1}hy.prototype=new BY;hy.prototype.constructor=hy;hy.prototype.s=function(){for(;;){if(this.yG)return!0;if(this.aL.s()){var a=this.aL.t();if(this.NR.oh(this.LR.n(a)))return this.MR=a,this.yG=!0}else return!1}};hy.prototype.t=function(){return this.s()?(this.yG=!1,this.MR):Rq().Pa.t()};\nhy.prototype.$classData=q({r5:0},!1,\"scala.collection.Iterator$$anon$8\",{r5:1,Sa:1,g:1,Ka:1,M:1,N:1});function Ef(a,b){this.OR=this.zG=null;if(null===a)throw null;this.zG=a;this.OR=b}Ef.prototype=new BY;Ef.prototype.constructor=Ef;Ef.prototype.Q=function(){return this.zG.Q()};Ef.prototype.s=function(){return this.zG.s()};Ef.prototype.t=function(){return this.OR.n(this.zG.t())};Ef.prototype.$classData=q({s5:0},!1,\"scala.collection.Iterator$$anon$9\",{s5:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction MT(a){this.tm=a;this.Rp=this.Bo=null;this.Mv=!1}MT.prototype=new BY;MT.prototype.constructor=MT;\nMT.prototype.s=function(){if(this.Mv)return!0;if(null!==this.tm){if(this.tm.s())return this.Mv=!0;a:for(;;){if(null===this.Bo){this.Rp=this.tm=null;var a=!1;break a}this.tm=Es(this.Bo.v5).m();this.Rp===this.Bo&&(this.Rp=this.Rp.AG);for(this.Bo=this.Bo.AG;this.tm instanceof MT;)a=this.tm,this.tm=a.tm,this.Mv=a.Mv,null!==a.Bo&&(null===this.Rp&&(this.Rp=a.Rp),a.Rp.AG=this.Bo,this.Bo=a.Bo);if(this.Mv){a=!0;break a}if(null!==this.tm&&this.tm.s()){a=this.Mv=!0;break a}}return a}return!1};\nMT.prototype.t=function(){return this.s()?(this.Mv=!1,this.tm.t()):Rq().Pa.t()};MT.prototype.nb=function(a){a=new lH(a,null);null===this.Bo?this.Bo=a:this.Rp.AG=a;this.Rp=a;null===this.tm&&(this.tm=Rq().Pa);return this};MT.prototype.$classData=q({t5:0},!1,\"scala.collection.Iterator$ConcatIterator\",{t5:1,Sa:1,g:1,Ka:1,M:1,N:1});function z0(a){for(;0<a.Nv;)a.By.s()?(a.By.t(),a.Nv=-1+a.Nv|0):a.Nv=0}function A0(a,b){if(0>a.Co)return-1;a=a.Co-b|0;return 0>a?0:a}\nfunction PT(a,b,c){this.By=a;this.Co=c;this.Nv=b}PT.prototype=new BY;PT.prototype.constructor=PT;f=PT.prototype;f.Q=function(){var a=this.By.Q();if(0>a)return-1;a=a-this.Nv|0;a=0>a?0:a;if(0>this.Co)return a;var b=this.Co;return b<a?b:a};f.s=function(){z0(this);return 0!==this.Co&&this.By.s()};f.t=function(){z0(this);return 0<this.Co?(this.Co=-1+this.Co|0,this.By.t()):0>this.Co?this.By.t():Rq().Pa.t()};\nf.qk=function(a,b){a=0<a?a:0;if(0>b)b=A0(this,a);else if(b<=a)b=0;else if(0>this.Co)b=b-a|0;else{var c=A0(this,a);b=b-a|0;b=c<b?c:b}if(0===b)return Rq().Pa;this.Nv=this.Nv+a|0;this.Co=b;return this};f.$classData=q({w5:0},!1,\"scala.collection.Iterator$SliceIterator\",{w5:1,Sa:1,g:1,Ka:1,M:1,N:1});function $O(a,b){this.y5=b;this.bL=a;this.TB=null}$O.prototype=new BY;$O.prototype.constructor=$O;\n$O.prototype.s=function(){if(null===this.TB){var a=this.y5.n(this.bL);if(null===a)throw oL(\"null during unfold\");this.TB=a;this.bL=null}return!this.TB.b()};$O.prototype.t=function(){if(this.s()){var a=this.TB.o();if(null===a)throw new w(a);var b=a.h();this.bL=a.j();this.TB=null;return b}return Rq().Pa.t()};$O.prototype.$classData=q({x5:0},!1,\"scala.collection.Iterator$UnfoldIterator\",{x5:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction B0(a){this.PR=this.dL=this.cL=null;if(null===a)throw null;this.PR=a;this.cL=a.Cy.ck.m();this.dL=a.Cy.dk.m()}B0.prototype=new BY;B0.prototype.constructor=B0;B0.prototype.s=function(){return this.cL.s()&&this.dL.s()};B0.prototype.t=function(){return this.PR.QR.ba(this.cL.t(),this.dL.t())};B0.prototype.$classData=q({B5:0},!1,\"scala.collection.LazyZip2$$anon$1$$anon$2\",{B5:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction C0(a){for(;!a.BG.s()&&a.eL.s()&&a.fL.s();)a.BG=a.RR.SR.ba(a.eL.t(),a.fL.t()).m();return a.BG}function D0(a){this.RR=this.BG=this.fL=this.eL=null;if(null===a)throw null;this.RR=a;this.eL=a.Ov.ck.m();this.fL=a.Ov.dk.m();this.BG=Rq().Pa}D0.prototype=new BY;D0.prototype.constructor=D0;D0.prototype.s=function(){return C0(this).s()};D0.prototype.t=function(){return C0(this).t()};D0.prototype.$classData=q({D5:0},!1,\"scala.collection.LazyZip2$$anon$3$$anon$4\",{D5:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction E0(a){this.hL=this.gL=null;this.gL=a.Dy.ck.m();this.hL=a.Dy.dk.m()}E0.prototype=new BY;E0.prototype.constructor=E0;E0.prototype.s=function(){return this.gL.s()&&this.hL.s()};E0.prototype.gm=function(){return G(new H,this.gL.t(),this.hL.t())};E0.prototype.t=function(){return this.gm()};E0.prototype.$classData=q({F5:0},!1,\"scala.collection.LazyZip2$$anon$7$$anon$8\",{F5:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction jv(a,b){var c=b.Q();if(0<=c)return a.ab(c);if(b&&b.$classData&&b.$classData.rb.CG){for(;;)if(a.b()?0:!b.b())a=a.f(),b=b.f();else break;a=!a.b();b=!b.b();return a===b?0:a?1:-1}for(b=b.m();;)if(!a.b()&&b.s())a=a.f(),b.t();else break;a=!a.b();b=b.s();return a===b?0:a?1:-1}function F0(a,b){return 0<=b&&0<a.ab(b)}function eB(a,b){if(0>b)throw aL(new bL,\"\"+b);a=a.Jc(b);if(a.b())throw aL(new bL,\"\"+b);return a.e()}function YA(a,b,c){for(;!a.b();)b=c.ba(b,a.e()),a=a.f();return b}\nfunction G0(a,b){if(b&&b.$classData&&b.$classData.rb.CG)a:for(;;){if(a===b){a=!0;break a}if((a.b()?0:!b.b())&&ml(nl(),a.e(),b.e()))a=a.f(),b=b.f();else{a=a.b()&&b.b();break a}}else a=TY(a,b);return a}function H0(a,b,c){var d=0<c?c:0;for(a=a.Jc(c);!a.b();){if(b.n(a.e()))return d;d=1+d|0;a=a.f()}return-1}function I0(a){this.nL=null;this.nL=a.m()}I0.prototype=new BY;I0.prototype.constructor=I0;I0.prototype.s=function(){return this.nL.s()};I0.prototype.t=function(){return this.nL.t().h()};\nI0.prototype.$classData=q({M5:0},!1,\"scala.collection.MapOps$$anon$2\",{M5:1,Sa:1,g:1,Ka:1,M:1,N:1});function Ou(a){this.Ot=null;this.Ot=a.m()}Ou.prototype=new BY;Ou.prototype.constructor=Ou;Ou.prototype.s=function(){return this.Ot.s()};Ou.prototype.t=function(){return this.Ot.t().j()};Ou.prototype.$classData=q({N5:0},!1,\"scala.collection.MapOps$$anon$3\",{N5:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction gfa(a){Ty();var b=u(),c=Uy(b);b=a.qL;b=(b&&b.$classData&&b.$classData.rb.Ac?b:b.FC()).Ja(new y(n=>{if(ca(c)!==da(Ky)){var r=c.U(n);if(r instanceof L)r=r.k;else if(R()===r)r=c.Xf,Ly(c,n,r,!1);else throw new w(r);}else{r=My(W(),n);r^=r>>>16|0;var v=r&(-1+c.eb.a.length|0),x=c.eb.a[v];x=null===x?null:Ny(x,n,r);if(null!==x)r=x.Ah;else{x=c.eb;var A=c.Xf;(1+c.Xf|0)>=c.hu&&Oy(c,c.eb.a.length<<1);Py(c,n,A,!1,r,x===c.eb?v:r&(-1+c.eb.a.length|0));r=A}}return G(new H,n,r)}));var d=new y(n=>n.Sc()),e=\nFq();b=QY(b,d,e);d=op();d=b.Gb(d.ga);if(null===d)throw new w(d);b=d.h();d=d.j();var g=new Xc(c.Xf);d.Ca(new y(n=>{n|=0;g.a[n]=1+g.a[n]|0}));d=new Xc(g.a.length);e=0;e=a.U5;var h=d.a.length;a=-1+h|0;if(!(0>=h))for(h=0;;){var k=h,l=e,m=g.a[k];d.a[k]=l<m?l:m;e=e-d.a[k]|0;if(h===a)break;h=1+h|0}k0||(k0=new j0);return new tl((new xT(k0)).vc(b),g,d)}\nfunction PY(a,b){this.$R=this.vm=this.HG=this.ZR=this.IG=null;this.GG=!1;this.qL=null;this.U5=b;if(null===a)throw null;this.qL=a;a=gfa(this);if(null===a)throw new w(a);this.IG=new tl(a.kc,a.hb,a.Rd);this.ZR=this.IG.kc;this.HG=this.IG.hb;this.vm=this.IG.Rd;a=this.HG;rl();for(var c=b=0,d=new Xc(1+a.a.length|0);c<a.a.length;)d.a[c]=b|0,b=(b|0)+a.a[c]|0,c=1+c|0;d.a[c]=b|0;this.$R=d;this.GG=!0}PY.prototype=new BY;PY.prototype.constructor=PY;PY.prototype.s=function(){return this.GG};\nPY.prototype.t=function(){this.GG||Rq().Pa.t();var a=this.qL.ti(),b=this.vm.a.length,c=-1+b|0;if(!(0>=b))for(b=0;;){var d=b,e=this.vm.a[d],g=-1+e|0;if(!(0>=e))for(e=0;;){var h=this.ZR.va(this.$R.a[d]+e|0);a.$(h);if(e===g)break;e=1+e|0}if(b===c)break;b=1+b|0}a=a.Kb();for(b=-1+this.vm.a.length|0;0<=b&&this.vm.a[b]===this.HG.a[b];)b=-1+b|0;c=this.vm;b=-1+b|0;a:{d=-1+c.a.length|0;for(b=b<d?b:d;0<=b;){if(0<c.a[b])break a;b=-1+b|0}b=-1}if(0>b)this.GG=!1;else{c=1;for(d=1+b|0;d<this.vm.a.length;)c=c+this.vm.a[d]|\n0,d=1+d|0;d=b;this.vm.a[d]=-1+this.vm.a[d]|0;d=1+b|0;g=this.vm.a.length;b=-1+g|0;if(!(d>=g))for(;;){g=d;e=c;h=this.HG.a[g];this.vm.a[g]=e<h?e:h;c=c-this.vm.a[g]|0;if(d===b)break;d=1+d|0}}return a};PY.prototype.$classData=q({T5:0},!1,\"scala.collection.SeqOps$CombinationsItr\",{T5:1,Sa:1,g:1,Ka:1,M:1,N:1});function J0(a,b){var c=Fs(b)?new JT(a,b):a.m().nb(new U(()=>b.m()));return a.vc(c)}function K0(){this.Mt=null}K0.prototype=new uT;K0.prototype.constructor=K0;function L0(){}L0.prototype=K0.prototype;\nfunction Om(a){this.QG=a}Om.prototype=new BY;Om.prototype.constructor=Om;Om.prototype.s=function(){return!this.QG.b()};Om.prototype.t=function(){var a=this.QG.e();this.QG=this.QG.f();return a};Om.prototype.$classData=q({h6:0},!1,\"scala.collection.StrictOptimizedLinearSeqOps$$anon$1\",{h6:1,Sa:1,g:1,Ka:1,M:1,N:1});function wH(a,b){this.SG=a;this.m6=b;this.Jy=a.length;this.cj=0}wH.prototype=new BY;wH.prototype.constructor=wH;wH.prototype.s=function(){return this.cj<this.Jy};\nfunction xH(a){if(a.cj>=a.Jy)a=Rq().Pa.t();else{for(var b=a.cj;;){if(a.cj<a.Jy){var c=a.SG.charCodeAt(a.cj);c=!(13===c||10===c)}else c=!1;if(c)a.cj=1+a.cj|0;else break}c=a.cj;if(a.cj<a.Jy){var d=a.SG.charCodeAt(a.cj);a.cj=1+a.cj|0;if(a.cj<a.Jy){var e=a.SG.charCodeAt(a.cj);d=13===d&&10===e}else d=!1;d&&(a.cj=1+a.cj|0);a.m6||(c=a.cj)}a=a.SG.substring(b,c)}return a}wH.prototype.t=function(){return xH(this)};\nwH.prototype.$classData=q({l6:0},!1,\"scala.collection.StringOps$$anon$1\",{l6:1,Sa:1,g:1,Ka:1,M:1,N:1});function js(a){this.o6=a;this.TG=-1+a.length|0}js.prototype=new BY;js.prototype.constructor=js;js.prototype.s=function(){return 0<=this.TG};js.prototype.t=function(){try{var a=this.o6.charCodeAt(this.TG);this.TG=-1+this.TG|0;var b=a}catch(c){if(c instanceof bL)b=Ea(Rq().Pa.t());else throw c;}return hc(b)};\njs.prototype.$classData=q({n6:0},!1,\"scala.collection.StringOps$ReverseIterator\",{n6:1,Sa:1,g:1,Ka:1,M:1,N:1});function M0(a,b){this.ZB=null;this.$B=a;this.DL=b;this.Sv=-1;this.Up=0}M0.prototype=new BY;M0.prototype.constructor=M0;M0.prototype.Q=function(){return this.Sv};M0.prototype.s=function(){if(null===this.ZB){var a=this.DL;for(this.ZB=Mv(256>a?a:256);this.Up<this.DL&&this.$B.s();)ol(this.ZB,this.$B.t()),this.Up=1+this.Up|0;this.$B.s()||(this.Sv=0);this.Up=0}return 0!==this.Sv};\nM0.prototype.t=function(){if(this.s()){var a=this.ZB.va(this.Up);-1===this.Sv?(N0(this.ZB,this.Up,this.$B.t()),this.$B.s()||(this.Sv=0)):this.Sv=-1+this.Sv|0;this.Up=1+this.Up|0;this.Up===this.DL&&(this.Up=0);return a}return Rq().Pa.t()};M0.prototype.$classData=q({x6:0},!1,\"scala.collection.View$DropRightIterator\",{x6:1,Sa:1,g:1,Ka:1,M:1,N:1});function O0(a){null!==a.gC&&(a.Nr=rU(a.Nr));a.gC=null}function WU(){this.Nr=this.gC=null;this.Nr=new aI(0,0,kG().EK,kG().KB,0,0)}WU.prototype=new p;\nWU.prototype.constructor=WU;f=WU.prototype;f.he=function(){};\nfunction SQ(a,b,c,d,e,g,h){if(b instanceof aI){var k=kI(HH(),g,h),l=lI(HH(),k);if(0!==(b.Db&l)){var m=oI(HH(),b.Db,k,l);a=b.Ef(m);k=b.Jb(m);if(k===e&&ml(nl(),a,c))b.te.a[1+(m<<1)|0]=d;else{var n=b.Tf(m);m=$G(bH(),k);e=jU(b,a,n,k,m,c,d,e,g,5+h|0);mU(b,l,m,e)}}else if(0!==(b.qc&l))l=oI(HH(),b.qc,k,l),l=b.qh(l),k=l.ka(),m=l.uc(),SQ(a,l,c,d,e,g,5+h|0),b.kd=b.kd+(l.ka()-k|0)|0,b.ui=b.ui+(l.uc()-m|0)|0;else{h=b.pi(l);k=h<<1;m=b.te;a=new zc(2+m.a.length|0);m.wa(0,a,0,k);a.a[k]=c;a.a[1+k|0]=d;m.wa(k,a,2+\nk|0,m.a.length-k|0);c=b.Vg;if(0>h)throw P0();if(h>c.a.length)throw P0();d=new Xc(1+c.a.length|0);c.wa(0,d,0,h);d.a[h]=e;c.wa(h,d,1+h|0,c.a.length-h|0);b.Db|=l;b.te=a;b.Vg=d;b.kd=1+b.kd|0;b.ui=b.ui+g|0}}else if(b instanceof oU)e=KU(b,c),b.of=0>e?b.of.hn(G(new H,c,d)):b.of.$r(e,G(new H,c,d));else throw new w(b);}function UU(a){if(0===a.Nr.kd)return Ez().Mr;null===a.gC&&(a.gC=new TU(a.Nr));return a.gC}\nfunction Q0(a,b){O0(a);var c=b.h();c=My(W(),c);var d=$G(bH(),c);SQ(a,a.Nr,b.h(),b.j(),c,d,0);return a}function R0(a,b,c){O0(a);var d=My(W(),b);SQ(a,a.Nr,b,c,d,$G(bH(),d),0);return a}function VU(a,b){O0(a);if(b instanceof TU)new RQ(a,b);else if(b instanceof DV)for(b=S0(b);b.s();){var c=b.t(),d=c.mk;d^=d>>>16|0;var e=$G(bH(),d);SQ(a,a.Nr,c.Wk,c.Ah,d,e,0)}else if(jV(b))b.og(new fn((g,h)=>R0(a,g,h)));else for(b=b.m();b.s();)Q0(a,b.t());return a}f.zc=function(a){return VU(this,a)};\nf.$=function(a){return Q0(this,a)};f.Kb=function(){return UU(this)};f.$classData=q({Z6:0},!1,\"scala.collection.immutable.HashMapBuilder\",{Z6:1,g:1,Po:1,xg:1,xf:1,wf:1});function cV(){this.Or=this.$v=null;this.Or=new CJ(0,0,kG().EK,kG().KB,0,0)}cV.prototype=new p;cV.prototype.constructor=cV;f=cV.prototype;f.he=function(){};\nfunction UQ(a,b,c,d,e,g){if(b instanceof CJ){var h=kI(HH(),e,g),k=lI(HH(),h);if(0!==(b.db&k)){h=oI(HH(),b.db,h,k);a=b.ed(h);var l=b.Jb(h);l===d&&ml(nl(),a,c)?(d=b.pi(k),b.Uc.a[d]=a):(h=$G(bH(),l),d=zU(b,a,l,h,c,d,e,5+g|0),CU(b,k,h,d))}else if(0!==(b.Pb&k))k=oI(HH(),b.Pb,h,k),k=b.Nh(k),h=k.ka(),l=k.uc(),UQ(a,k,c,d,e,5+g|0),b.Fb=b.Fb+(k.ka()-h|0)|0,b.Ve=b.Ve+(k.uc()-l|0)|0;else{g=b.pi(k);h=b.Uc;a=new zc(1+h.a.length|0);h.wa(0,a,0,g);a.a[g]=c;h.wa(g,a,1+g|0,h.a.length-g|0);c=b.Ud;if(0>g)throw P0();if(g>\nc.a.length)throw P0();h=new Xc(1+c.a.length|0);c.wa(0,h,0,g);h.a[g]=d;c.wa(g,h,1+g|0,c.a.length-g|0);b.db|=k;b.Uc=a;b.Ud=h;b.Fb=1+b.Fb|0;b.Ve=b.Ve+e|0}}else if(b instanceof FU)d=Xea(b.Kg,c),b.Kg=0>d?b.Kg.hn(c):b.Kg.$r(d,c);else throw new w(b);}function aV(a){if(0===a.Or.Fb)return dV().Fo;null===a.$v&&(a.$v=new ZU(a.Or));return a.$v}function T0(a,b){null!==a.$v&&(a.Or=IU(a.Or));a.$v=null;var c=My(W(),b),d=$G(bH(),c);UQ(a,a.Or,b,c,d,0);return a}\nfunction bV(a,b){null!==a.$v&&(a.Or=IU(a.Or));a.$v=null;if(b instanceof ZU)new TQ(a,b);else for(b=b.m();b.s();)T0(a,b.t());return a}f.zc=function(a){return bV(this,a)};f.$=function(a){return T0(this,a)};f.Kb=function(){return aV(this)};f.$classData=q({c7:0},!1,\"scala.collection.immutable.HashSetBuilder\",{c7:1,g:1,Po:1,xg:1,xf:1,wf:1});function U0(){this.Bl=null;this.Bl=GK()}U0.prototype=new MY;U0.prototype.constructor=U0;function we(a,b){return V0(b)?b:LY.prototype.vl.call(a,b)}\nU0.prototype.Ib=function(a){return we(this,a)};U0.prototype.vl=function(a){return we(this,a)};U0.prototype.$classData=q({e7:0},!1,\"scala.collection.immutable.IndexedSeq$\",{e7:1,FG:1,g:1,Nk:1,bg:1,l:1});var W0;function xe(){W0||(W0=new U0);return W0}function lZ(){this.mS=this.Qy=null;this.mg()}lZ.prototype=new p;lZ.prototype.constructor=lZ;f=lZ.prototype;f.he=function(){};f.mg=function(){var a=new VH;FK();this.mS=new gZ(new U(()=>WH(a)));this.Qy=a};\nfunction hfa(a){YH(a.Qy,new U(()=>hV()));return a.mS}function ifa(a,b){var c=new VH;YH(a.Qy,new U(()=>{FK();FK();return new eV(b,new gZ(new U(()=>WH(c))))}));a.Qy=c;return a}function jfa(a,b){if(0!==b.Q()){var c=new VH;YH(a.Qy,new U(()=>jZ(FK(),b.m(),new U(()=>WH(c)))));a.Qy=c}return a}f.zc=function(a){return jfa(this,a)};f.$=function(a){return ifa(this,a)};f.Kb=function(){return hfa(this)};f.$classData=q({j7:0},!1,\"scala.collection.immutable.LazyList$LazyBuilder\",{j7:1,g:1,Po:1,xg:1,xf:1,wf:1});\nfunction X0(a){this.hC=a}X0.prototype=new BY;X0.prototype.constructor=X0;X0.prototype.s=function(){return!this.hC.b()};X0.prototype.t=function(){if(this.hC.b())return Rq().Pa.t();var a=hZ(this.hC).e();this.hC=hZ(this.hC).Lf();return a};X0.prototype.$classData=q({l7:0},!1,\"scala.collection.immutable.LazyList$LazyIterator\",{l7:1,Sa:1,g:1,Ka:1,M:1,N:1});function Y0(){this.iC=this.jC=null;Z0=this;this.jC=G(new H,u(),u());this.iC=new VQ}Y0.prototype=new p;Y0.prototype.constructor=Y0;f=Y0.prototype;\nf.Hh=function(a){return Pd(u(),a)};f.Eb=function(){return new fp};f.X=function(){return u()};f.Ib=function(a){return Pd(u(),a)};f.$classData=q({s7:0},!1,\"scala.collection.immutable.List$\",{s7:1,g:1,Qt:1,Nk:1,bg:1,l:1});var Z0;function Od(){Z0||(Z0=new Y0);return Z0}function $0(a,b){if(null===b)throw null;a.Vt=b;a.Yp=0}function a1(){this.Yp=0;this.Vt=null}a1.prototype=new BY;a1.prototype.constructor=a1;function b1(){}b1.prototype=a1.prototype;a1.prototype.s=function(){return 2>this.Yp};\na1.prototype.t=function(){switch(this.Yp){case 0:var a=this.wj(this.Vt.hk,this.Vt.xn);break;case 1:a=this.wj(this.Vt.ik,this.Vt.yn);break;default:a=Rq().Pa.t()}this.Yp=1+this.Yp|0;return a};a1.prototype.ph=function(a){this.Yp=this.Yp+a|0;return this};function c1(a,b){if(null===b)throw null;a.Zp=b;a.$p=0}function d1(){this.$p=0;this.Zp=null}d1.prototype=new BY;d1.prototype.constructor=d1;function e1(){}e1.prototype=d1.prototype;d1.prototype.s=function(){return 3>this.$p};\nd1.prototype.t=function(){switch(this.$p){case 0:var a=this.wj(this.Zp.dj,this.Zp.Fl);break;case 1:a=this.wj(this.Zp.Mi,this.Zp.Qk);break;case 2:a=this.wj(this.Zp.Ni,this.Zp.Rk);break;default:a=Rq().Pa.t()}this.$p=1+this.$p|0;return a};d1.prototype.ph=function(a){this.$p=this.$p+a|0;return this};function f1(a,b){if(null===b)throw null;a.zn=b;a.aq=0}function g1(){this.aq=0;this.zn=null}g1.prototype=new BY;g1.prototype.constructor=g1;function h1(){}h1.prototype=g1.prototype;\ng1.prototype.s=function(){return 4>this.aq};g1.prototype.t=function(){switch(this.aq){case 0:var a=this.wj(this.zn.Th,this.zn.Aj);break;case 1:a=this.wj(this.zn.xh,this.zn.ej);break;case 2:a=this.wj(this.zn.Wg,this.zn.Oi);break;case 3:a=this.wj(this.zn.Xg,this.zn.Pi);break;default:a=Rq().Pa.t()}this.aq=1+this.aq|0;return a};g1.prototype.ph=function(a){this.aq=this.aq+a|0;return this};function lV(){this.bq=null;this.Sy=!1;this.Wt=null;this.bq=nf();this.Sy=!1}lV.prototype=new p;\nlV.prototype.constructor=lV;f=lV.prototype;f.he=function(){};function kV(a,b){return a.Sy?(VU(a.Wt,b),a):lR(a,b)}f.zc=function(a){return kV(this,a)};f.$=function(a){var b=a.h();a=a.j();if(this.Sy)R0(this.Wt,b,a);else if(4>this.bq.ka())this.bq=this.bq.Em(b,a);else if(this.bq.L(b))this.bq=this.bq.Em(b,a);else{this.Sy=!0;null===this.Wt&&(this.Wt=new WU);var c=this.bq;R0(R0(R0(R0(this.Wt,c.Th,c.Aj),c.xh,c.ej),c.Wg,c.Oi),c.Xg,c.Pi);R0(this.Wt,b,a)}return this};\nf.Kb=function(){return this.Sy?UU(this.Wt):this.bq};f.$classData=q({J7:0},!1,\"scala.collection.immutable.MapBuilderImpl\",{J7:1,g:1,Po:1,xg:1,xf:1,wf:1});function i1(a){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;JH(this,a)}i1.prototype=new LH;i1.prototype.constructor=i1;f=i1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};f.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};\nf.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};\nf.Q=function(){return-1};f.t=function(){if(!this.s())throw LU();var a=this.wh.Ef(this.Nc);this.Nc=1+this.Nc|0;return a};f.Ja=function(a){return new Ef(this,a)};f.$classData=q({K7:0},!1,\"scala.collection.immutable.MapKeyIterator\",{K7:1,Vv:1,g:1,Ka:1,M:1,N:1});function j1(a){this.gk=0;this.Ut=null;this.Pk=0;this.Xv=this.Wv=null;this.LL=0;this.uS=null;OH(this,a);this.LL=0}j1.prototype=new QH;j1.prototype.constructor=j1;f=j1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};\nf.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};f.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};\nf.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return-1};f.B=function(){var a=BL(),b=this.uS;return zL(a,this.LL,My(W(),b))};f.Ja=function(a){return new Ef(this,a)};f.t=function(){if(!this.s())throw LU();this.LL=this.Ut.Jb(this.gk);this.uS=this.Ut.Tf(this.gk);this.gk=-1+this.gk|0;return this};f.$classData=q({L7:0},!1,\"scala.collection.immutable.MapKeyValueTupleHashIterator\",{L7:1,jS:1,g:1,Ka:1,M:1,N:1});\nfunction k1(a){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;JH(this,a)}k1.prototype=new LH;k1.prototype.constructor=k1;f=k1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};f.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};f.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};\nf.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return-1};f.gm=function(){if(!this.s())throw LU();var a=this.wh.rv(this.Nc);this.Nc=1+this.Nc|0;return a};\nf.Ja=function(a){return new Ef(this,a)};f.t=function(){return this.gm()};f.$classData=q({M7:0},!1,\"scala.collection.immutable.MapKeyValueTupleIterator\",{M7:1,Vv:1,g:1,Ka:1,M:1,N:1});function l1(a){this.gk=0;this.Ut=null;this.Pk=0;this.Xv=this.Wv=null;OH(this,a)}l1.prototype=new QH;l1.prototype.constructor=l1;f=l1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};f.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};\nf.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};\nf.Q=function(){return-1};f.gm=function(){if(!this.s())throw LU();var a=this.Ut.rv(this.gk);this.gk=-1+this.gk|0;return a};f.Ja=function(a){return new Ef(this,a)};f.t=function(){return this.gm()};f.$classData=q({N7:0},!1,\"scala.collection.immutable.MapKeyValueTupleReverseIterator\",{N7:1,jS:1,g:1,Ka:1,M:1,N:1});function m1(a){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;JH(this,a)}m1.prototype=new LH;m1.prototype.constructor=m1;f=m1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};\nf.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};f.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};\nf.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return-1};f.t=function(){if(!this.s())throw LU();var a=this.wh.Tf(this.Nc);this.Nc=1+this.Nc|0;return a};f.Ja=function(a){return new Ef(this,a)};f.$classData=q({R7:0},!1,\"scala.collection.immutable.MapValueIterator\",{R7:1,Vv:1,g:1,Ka:1,M:1,N:1});\nfunction n1(a){a.xi<=a.Lg&&Rq().Pa.t();a.ew=1+a.ew|0;for(var b=a.wS.To(a.ew);0===b.a.length;)a.ew=1+a.ew|0,b=a.wS.To(a.ew);a.YG=a.Yt;var c=a.T7/2|0,d=a.ew-c|0;a.dw=(1+c|0)-(0>d?-d|0:d)|0;c=a.dw;switch(c){case 1:a.Go=b;break;case 2:a.aw=b;break;case 3:a.bw=b;break;case 4:a.cw=b;break;case 5:a.Uy=b;break;case 6:a.ML=b;break;default:throw new w(c);}a.Yt=a.YG+Math.imul(b.a.length,1<<Math.imul(5,-1+a.dw|0))|0;a.Yt>a.Bn&&(a.Yt=a.Bn);1<a.dw&&(a.kC=-1+(1<<Math.imul(5,a.dw))|0)}\nfunction o1(a){var b=(a.Lg-a.xi|0)+a.Bn|0;b===a.Yt&&n1(a);if(1<a.dw){b=b-a.YG|0;var c=a.kC^b;1024>c?a.Go=a.aw.a[31&(b>>>5|0)]:(32768>c?a.aw=a.bw.a[31&(b>>>10|0)]:(1048576>c?a.bw=a.cw.a[31&(b>>>15|0)]:(33554432>c?a.cw=a.Uy.a[31&(b>>>20|0)]:(a.Uy=a.ML.a[b>>>25|0],a.cw=a.Uy.a[0]),a.bw=a.cw.a[0]),a.aw=a.bw.a[0]),a.Go=a.aw.a[0]);a.kC=b}a.xi=a.xi-a.Lg|0;b=a.Go.a.length;c=a.xi;a.cq=b<c?b:c;a.Lg=0}\nfunction p1(a,b,c){this.ML=this.Uy=this.cw=this.bw=this.aw=null;this.wS=a;this.Bn=b;this.T7=c;this.Go=a.R;this.cq=this.Go.a.length;this.kC=this.Lg=0;this.xi=this.Bn;this.ew=0;this.dw=1;this.YG=0;this.Yt=this.cq}p1.prototype=new p;p1.prototype.constructor=p1;f=p1.prototype;f.m=function(){return this};f.b=function(){return this.xi<=this.Lg};f.nb=function(a){return kv(this,a)};f.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};\nf.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return this.xi-this.Lg|0};f.s=function(){return this.xi>this.Lg};\nf.t=function(){this.Lg===this.cq&&o1(this);var a=this.Go.a[this.Lg];this.Lg=1+this.Lg|0;return a};\nf.ph=function(a){if(0<a){a=((this.Lg-this.xi|0)+this.Bn|0)+a|0;var b=this.Bn;a=a<b?a:b;if(a===this.Bn)this.cq=this.xi=this.Lg=0;else{for(;a>=this.Yt;)n1(this);b=a-this.YG|0;if(1<this.dw){var c=this.kC^b;1024>c||(32768>c||(1048576>c||(33554432>c||(this.Uy=this.ML.a[b>>>25|0]),this.cw=this.Uy.a[31&(b>>>20|0)]),this.bw=this.cw.a[31&(b>>>15|0)]),this.aw=this.bw.a[31&(b>>>10|0)]);this.Go=this.aw.a[31&(b>>>5|0)];this.kC=b}this.cq=this.Go.a.length;this.Lg=31&b;this.xi=this.Lg+(this.Bn-a|0)|0;this.cq>this.xi&&\n(this.cq=this.xi)}}return this};f.Mn=function(a){a<(this.xi-this.Lg|0)&&(a=(this.xi-this.Lg|0)-(0>a?0:a)|0,this.Bn=this.Bn-a|0,this.xi=this.xi-a|0,this.xi<this.cq&&(this.cq=this.xi),this.Bn<this.Yt&&(this.Yt=this.Bn));return this};\nf.Gc=function(a,b,c){var d=wG(xG(),a),e=this.xi-this.Lg|0;c=c<e?c:e;d=d-b|0;d=c<d?c:d;d=0<d?d:0;c=0;for(e=a instanceof zc;c<d;){this.Lg===this.cq&&o1(this);var g=d-c|0,h=this.Go.a.length-this.Lg|0;g=g<h?g:h;e?this.Go.wa(this.Lg,a,b+c|0,g):VG(SG(),this.Go,this.Lg,a,b+c|0,g);this.Lg=this.Lg+g|0;c=c+g|0}return d};f.Ja=function(a){return new Ef(this,a)};f.$classData=q({S7:0},!1,\"scala.collection.immutable.NewVectorIterator\",{S7:1,g:1,Ka:1,M:1,N:1,Ff:1});\nfunction q1(a,b,c,d){a.Xy=b;a.hw=d;null===b?d=null:(d=-2+((32-Math.clz32(1+(2147483647&b.ea)|0)|0)<<1)|0,d=new (md(zJ).Ia)(d));a.Cn=d;a.Wd=0;if(c.b())b=r1(a,b);else if(b=c.o(),null===a.Xy)b=null;else a:for(c=a.Xy;;){if(null===c){if(0===a.Wd){b=null;break a}a.Wd=-1+a.Wd|0;b=a.Cn.a[a.Wd];break a}a.hw.uj(b,c.Wa)?(a.Cn.a[a.Wd]=c,a.Wd=1+a.Wd|0,c=c.sa):c=c.ta}a.Hc=b}function s1(){this.Cn=this.hw=this.Xy=null;this.Wd=0;this.Hc=null}s1.prototype=new BY;s1.prototype.constructor=s1;function t1(){}\nt1.prototype=s1.prototype;s1.prototype.s=function(){return null!==this.Hc};s1.prototype.t=function(){var a=this.Hc;return null!==a?(this.Hc=r1(this,a.ta),this.yK(a)):Rq().Pa.t()};function r1(a,b){for(;;){if(null===b){if(0===a.Wd)return null;a.Wd=-1+a.Wd|0;return a.Cn.a[a.Wd]}if(null===b.sa)return b;a.Cn.a[a.Wd]=b;a.Wd=1+a.Wd|0;b=b.sa}}function u1(){this.Bl=null;this.Bl=Od()}u1.prototype=new MY;u1.prototype.constructor=u1;\nfunction v1(a,b){return b&&b.$classData&&b.$classData.rb.Mg?b:LY.prototype.vl.call(a,b)}u1.prototype.Ib=function(a){return v1(this,a)};u1.prototype.vl=function(a){return v1(this,a)};u1.prototype.$classData=q({i8:0},!1,\"scala.collection.immutable.Seq$\",{i8:1,FG:1,g:1,Nk:1,bg:1,l:1});var w1;function EK(){w1||(w1=new u1);return w1}function OF(){this.kw=null;this.oC=!1;this.lw=null;this.kw=ap();this.oC=!1}OF.prototype=new p;OF.prototype.constructor=OF;f=OF.prototype;f.he=function(){};\nfunction MF(a){return a.oC?aV(a.lw):a.kw}function NF(a,b){if(a.oC)T0(a.lw,b);else if(4>a.kw.ka())a.kw=a.kw.bc(b);else if(!a.kw.L(b)){a.oC=!0;null===a.lw&&(a.lw=new cV);var c=a.kw;a.lw.$(c.Ho).$(c.eq).$(c.fq).$(c.gq);T0(a.lw,b)}return a}function oV(a,b){return a.oC?(bV(a.lw,b),a):lR(a,b)}f.zc=function(a){return oV(this,a)};f.$=function(a){return NF(this,a)};f.Kb=function(){return MF(this)};f.$classData=q({s8:0},!1,\"scala.collection.immutable.SetBuilderImpl\",{s8:1,g:1,Po:1,xg:1,xf:1,wf:1});\nfunction x1(a){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;this.NL=0;JH(this,a);this.NL=0}x1.prototype=new LH;x1.prototype.constructor=x1;f=x1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};f.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};f.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};\nf.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return-1};f.B=function(){return this.NL};f.t=function(){if(!this.s())throw LU();this.NL=this.wh.Jb(this.Nc);this.Nc=1+this.Nc|0;return this};\nf.Ja=function(a){return new Ef(this,a)};f.$classData=q({t8:0},!1,\"scala.collection.immutable.SetHashIterator\",{t8:1,Vv:1,g:1,Ka:1,M:1,N:1});function y1(a){this.wn=this.Nc=0;this.wh=null;this.vi=0;this.Do=this.Ok=null;JH(this,a)}y1.prototype=new LH;y1.prototype.constructor=y1;f=y1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};f.nb=function(a){return kv(this,a)};f.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};f.qk=function(a,b){return OT(this,a,b)};\nf.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return-1};\nf.t=function(){if(!this.s())throw LU();var a=this.wh.ed(this.Nc);this.Nc=1+this.Nc|0;return a};f.Ja=function(a){return new Ef(this,a)};f.$classData=q({u8:0},!1,\"scala.collection.immutable.SetIterator\",{u8:1,Vv:1,g:1,Ka:1,M:1,N:1});function z1(a){this.gk=0;this.Ut=null;this.Pk=0;this.Xv=this.Wv=null;OH(this,a)}z1.prototype=new QH;z1.prototype.constructor=z1;f=z1.prototype;f.m=function(){return this};f.b=function(){return!this.s()};f.nb=function(a){return kv(this,a)};\nf.Mn=function(a){return NT(this,a)};f.ph=function(a){return OT(this,a,-1)};f.qk=function(a,b){return OT(this,a,b)};f.u=function(){return\"\\x3citerator\\x3e\"};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};\nf.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return-1};f.t=function(){if(!this.s())throw LU();var a=this.Ut.ed(this.gk);this.gk=-1+this.gk|0;return a};f.Ja=function(a){return new Ef(this,a)};f.$classData=q({x8:0},!1,\"scala.collection.immutable.SetReverseIterator\",{x8:1,jS:1,g:1,Ka:1,M:1,N:1});\nfunction A1(){this.HS=0;this.IS=null;B1=this;try{var a=fh(gh(),\"scala.collection.immutable.Vector.defaultApplyPreferredMaxLength\",\"250\");var b=TH(UH(),a,10)}catch(c){throw c;}this.HS=b;this.IS=new p1(HJ(),0,0)}A1.prototype=new p;A1.prototype.constructor=A1;f=A1.prototype;f.Hh=function(a){return pU(0,a)};\nfunction pU(a,b){if(b instanceof C1)return b;a=b.Q();if(0===a)return HJ();if(0<a&&32>=a){a:{if(b instanceof Fu){var c=b.ag().uh();if(null!==c&&c===da(jd)){b=b.vn;break a}}ZJ(b)?(a=new zc(a),b.Gc(a,0,2147483647),b=a):(a=new zc(a),b.m().Gc(a,0,2147483647),b=a)}return new IJ(b)}return OU(new NU,b).im()}f.Eb=function(){return new NU};f.Ib=function(a){return pU(0,a)};f.X=function(){return HJ()};f.$classData=q({P8:0},!1,\"scala.collection.immutable.Vector$\",{P8:1,g:1,Qt:1,Nk:1,bg:1,l:1});var B1;\nfunction GK(){B1||(B1=new A1);return B1}function D1(a,b){var c=b.a.length;if(0<c){32===a.Yd&&E1(a);var d=32-a.Yd|0;d=d<c?d:c;c=c-d|0;b.wa(0,a.af,a.Yd,d);a.Yd=a.Yd+d|0;0<c&&(E1(a),b.wa(d,a.af,0,c),a.Yd=a.Yd+c|0)}}function kfa(a,b){for(var c=b.On(),d=0;d<c;){var e=b.To(d),g=c/2|0,h=d-g|0;g=(1+g|0)-(0>h?-h|0:h)|0;1===g?D1(a,e):VJ(JJ(),-2+g|0,e,new y(k=>{D1(a,k)}));d=1+d|0}return a}\nfunction E1(a){var b=32+a.yi|0,c=b^a.yi;a.yi=b;a.Yd=0;if(1024>c)1===a.wg&&(a.sd=new (md(md(jd)).Ia)(32),a.sd.a[0]=a.af,a.wg=1+a.wg|0),a.af=new zc(32),a.sd.a[31&(b>>>5|0)]=a.af;else if(32768>c)2===a.wg&&(a.ue=new (md(md(md(jd))).Ia)(32),a.ue.a[0]=a.sd,a.wg=1+a.wg|0),a.af=new zc(32),a.sd=new (md(md(jd)).Ia)(32),a.sd.a[31&(b>>>5|0)]=a.af,a.ue.a[31&(b>>>10|0)]=a.sd;else if(1048576>c)3===a.wg&&(a.Jf=new (md(md(md(md(jd)))).Ia)(32),a.Jf.a[0]=a.ue,a.wg=1+a.wg|0),a.af=new zc(32),a.sd=new (md(md(jd)).Ia)(32),\na.ue=new (md(md(md(jd))).Ia)(32),a.sd.a[31&(b>>>5|0)]=a.af,a.ue.a[31&(b>>>10|0)]=a.sd,a.Jf.a[31&(b>>>15|0)]=a.ue;else if(33554432>c)4===a.wg&&(a.Pg=new (md(md(md(md(md(jd))))).Ia)(32),a.Pg.a[0]=a.Jf,a.wg=1+a.wg|0),a.af=new zc(32),a.sd=new (md(md(jd)).Ia)(32),a.ue=new (md(md(md(jd))).Ia)(32),a.Jf=new (md(md(md(md(jd)))).Ia)(32),a.sd.a[31&(b>>>5|0)]=a.af,a.ue.a[31&(b>>>10|0)]=a.sd,a.Jf.a[31&(b>>>15|0)]=a.ue,a.Pg.a[31&(b>>>20|0)]=a.Jf;else if(1073741824>c)5===a.wg&&(a.Si=new (md(md(md(md(md(md(jd)))))).Ia)(64),\na.Si.a[0]=a.Pg,a.wg=1+a.wg|0),a.af=new zc(32),a.sd=new (md(md(jd)).Ia)(32),a.ue=new (md(md(md(jd))).Ia)(32),a.Jf=new (md(md(md(md(jd)))).Ia)(32),a.Pg=new (md(md(md(md(md(jd))))).Ia)(32),a.sd.a[31&(b>>>5|0)]=a.af,a.ue.a[31&(b>>>10|0)]=a.sd,a.Jf.a[31&(b>>>15|0)]=a.ue,a.Pg.a[31&(b>>>20|0)]=a.Jf,a.Si.a[31&(b>>>25|0)]=a.Pg;else throw Kj(\"advance1(\"+b+\", \"+c+\"): a1\\x3d\"+a.af+\", a2\\x3d\"+a.sd+\", a3\\x3d\"+a.ue+\", a4\\x3d\"+a.Jf+\", a5\\x3d\"+a.Pg+\", a6\\x3d\"+a.Si+\", depth\\x3d\"+a.wg);}\nfunction NU(){this.af=this.sd=this.ue=this.Jf=this.Pg=this.Si=null;this.wg=this.Gl=this.yi=this.Yd=0;this.af=new zc(32);this.Gl=this.yi=this.Yd=0;this.wg=1}NU.prototype=new p;NU.prototype.constructor=NU;f=NU.prototype;f.he=function(){};function lfa(a,b){a.wg=1;var c=b.a.length;a.Yd=31&c;a.yi=c-a.Yd|0;a.af=32===b.a.length?b:Jj(Pj(),b,0,32);0===a.Yd&&0<a.yi&&(a.Yd=32,a.yi=-32+a.yi|0)}\nfunction F1(a,b){var c=b.On();switch(c){case 0:break;case 1:a.wg=1;c=b.R.a.length;a.Yd=31&c;a.yi=c-a.Yd|0;b=b.R;a.af=32===b.a.length?b:Jj(Pj(),b,0,32);break;case 3:c=b.yh;var d=b.Z;a.af=32===d.a.length?d:Jj(Pj(),d,0,32);a.wg=2;a.Gl=32-b.Ri|0;d=b.ca+a.Gl|0;a.Yd=31&d;a.yi=d-a.Yd|0;a.sd=new (md(md(jd)).Ia)(32);a.sd.a[0]=b.R;c.wa(0,a.sd,1,c.a.length);a.sd.a[1+c.a.length|0]=a.af;break;case 5:c=b.cg;d=b.tg;var e=b.Z;a.af=32===e.a.length?e:Jj(Pj(),e,0,32);a.wg=3;a.Gl=1024-b.zh|0;e=b.ca+a.Gl|0;a.Yd=31&e;\na.yi=e-a.Yd|0;a.ue=new (md(md(md(jd))).Ia)(32);a.ue.a[0]=UJ(JJ(),b.R,b.Wh);c.wa(0,a.ue,1,c.a.length);a.sd=zj(Pj(),d,32);a.ue.a[1+c.a.length|0]=a.sd;a.sd.a[d.a.length]=a.af;break;case 7:c=b.Ye;d=b.qf;e=b.pf;var g=b.Z;a.af=32===g.a.length?g:Jj(Pj(),g,0,32);a.wg=4;a.Gl=32768-b.dg|0;g=b.ca+a.Gl|0;a.Yd=31&g;a.yi=g-a.Yd|0;a.Jf=new (md(md(md(md(jd)))).Ia)(32);a.Jf.a[0]=UJ(JJ(),UJ(JJ(),b.R,b.ug),b.vg);c.wa(0,a.Jf,1,c.a.length);a.ue=zj(Pj(),d,32);a.sd=zj(Pj(),e,32);a.Jf.a[1+c.a.length|0]=a.ue;a.ue.a[d.a.length]=\na.sd;a.sd.a[e.a.length]=a.af;break;case 9:c=b.Xd;d=b.ge;e=b.fe;g=b.ee;var h=b.Z;a.af=32===h.a.length?h:Jj(Pj(),h,0,32);a.wg=5;a.Gl=1048576-b.Ze|0;h=b.ca+a.Gl|0;a.Yd=31&h;a.yi=h-a.Yd|0;a.Pg=new (md(md(md(md(md(jd))))).Ia)(32);a.Pg.a[0]=UJ(JJ(),UJ(JJ(),UJ(JJ(),b.R,b.rf),b.sf),b.tf);c.wa(0,a.Pg,1,c.a.length);a.Jf=zj(Pj(),d,32);a.ue=zj(Pj(),e,32);a.sd=zj(Pj(),g,32);a.Pg.a[1+c.a.length|0]=a.Jf;a.Jf.a[d.a.length]=a.ue;a.ue.a[e.a.length]=a.sd;a.sd.a[g.a.length]=a.af;break;case 11:c=b.rd;d=b.Nd;e=b.Md;g=\nb.Ld;h=b.Kd;var k=b.Z;a.af=32===k.a.length?k:Jj(Pj(),k,0,32);a.wg=6;a.Gl=33554432-b.Fe|0;k=b.ca+a.Gl|0;a.Yd=31&k;a.yi=k-a.Yd|0;a.Si=new (md(md(md(md(md(md(jd)))))).Ia)(32);a.Si.a[0]=UJ(JJ(),UJ(JJ(),UJ(JJ(),UJ(JJ(),b.R,b.Ge),b.He),b.Ie),b.Je);c.wa(0,a.Si,1,c.a.length);a.Pg=zj(Pj(),d,32);a.Jf=zj(Pj(),e,32);a.ue=zj(Pj(),g,32);a.sd=zj(Pj(),h,32);a.Si.a[1+c.a.length|0]=a.Pg;a.Pg.a[d.a.length]=a.Jf;a.Jf.a[e.a.length]=a.ue;a.ue.a[g.a.length]=a.sd;a.sd.a[h.a.length]=a.af;break;default:throw new w(c);}0===\na.Yd&&0<a.yi&&(a.Yd=32,a.yi=-32+a.yi|0);return a}function PU(a,b){32===a.Yd&&E1(a);a.af.a[a.Yd]=b;a.Yd=1+a.Yd|0;return a}function OU(a,b){return b instanceof C1?0===a.Yd&&0===a.yi?F1(a,b):kfa(a,b):lR(a,b)}\nf.im=function(){var a=this.Yd+this.yi|0,b=a-this.Gl|0;if(0===b)return GK(),HJ();if(32>=a){if(32===b)return new IJ(this.af);var c=this.af;return new IJ(zj(Pj(),c,b))}if(1024>=a){var d=31&(-1+a|0),e=(-1+a|0)>>>5|0,g=this.sd,h=Jj(Pj(),g,1,e),k=this.sd.a[0],l=this.sd.a[e],m=1+d|0,n=l.a.length===m?l:zj(Pj(),l,m);return new KJ(k,32-this.Gl|0,h,n,b)}if(32768>=a){var r=31&(-1+a|0),v=31&((-1+a|0)>>>5|0),x=(-1+a|0)>>>10|0,A=this.ue,B=Jj(Pj(),A,1,x),C=this.ue.a[0],D=C.a.length,F=Jj(Pj(),C,1,D),I=this.ue.a[0].a[0],\nM=this.ue.a[x],N=zj(Pj(),M,v),P=this.ue.a[x].a[v],T=1+r|0,Y=P.a.length===T?P:zj(Pj(),P,T),Z=I.a.length;return new LJ(I,Z,F,Z+(F.a.length<<5)|0,B,N,Y,b)}if(1048576>=a){var S=31&(-1+a|0),ea=31&((-1+a|0)>>>5|0),ia=31&((-1+a|0)>>>10|0),X=(-1+a|0)>>>15|0,sa=this.Jf,Ja=Jj(Pj(),sa,1,X),Xa=this.Jf.a[0],Fa=Xa.a.length,za=Jj(Pj(),Xa,1,Fa),Qa=this.Jf.a[0].a[0],Ma=Qa.a.length,Ga=Jj(Pj(),Qa,1,Ma),ab=this.Jf.a[0].a[0].a[0],Hb=this.Jf.a[X],bc=zj(Pj(),Hb,ia),yb=this.Jf.a[X].a[ia],tb=zj(Pj(),yb,ea),eb=this.Jf.a[X].a[ia].a[ea],\nkb=1+S|0,Rb=eb.a.length===kb?eb:zj(Pj(),eb,kb),Gb=ab.a.length,vb=Gb+(Ga.a.length<<5)|0;return new MJ(ab,Gb,Ga,vb,za,vb+(za.a.length<<10)|0,Ja,bc,tb,Rb,b)}if(33554432>=a){var Tb=31&(-1+a|0),Nb=31&((-1+a|0)>>>5|0),ic=31&((-1+a|0)>>>10|0),Va=31&((-1+a|0)>>>15|0),cb=(-1+a|0)>>>20|0,zb=this.Pg,Ub=Jj(Pj(),zb,1,cb),jb=this.Pg.a[0],db=jb.a.length,ub=Jj(Pj(),jb,1,db),Aa=this.Pg.a[0].a[0],va=Aa.a.length,Ra=Jj(Pj(),Aa,1,va),rb=this.Pg.a[0].a[0].a[0],xb=rb.a.length,mc=Jj(Pj(),rb,1,xb),Ha=this.Pg.a[0].a[0].a[0].a[0],\nKa=this.Pg.a[cb],Oa=zj(Pj(),Ka,Va),Na=this.Pg.a[cb].a[Va],Da=zj(Pj(),Na,ic),ta=this.Pg.a[cb].a[Va].a[ic],Ya=zj(Pj(),ta,Nb),dc=this.Pg.a[cb].a[Va].a[ic].a[Nb],ka=1+Tb|0,ya=dc.a.length===ka?dc:zj(Pj(),dc,ka),Sa=Ha.a.length,xc=Sa+(mc.a.length<<5)|0,Sb=xc+(Ra.a.length<<10)|0;return new NJ(Ha,Sa,mc,xc,Ra,Sb,ub,Sb+(ub.a.length<<15)|0,Ub,Oa,Da,Ya,ya,b)}var uc=31&(-1+a|0),Lb=31&((-1+a|0)>>>5|0),lc=31&((-1+a|0)>>>10|0),Xb=31&((-1+a|0)>>>15|0),ec=31&((-1+a|0)>>>20|0),Ab=(-1+a|0)>>>25|0,Ob=this.Si,fb=Jj(Pj(),\nOb,1,Ab),Wa=this.Si.a[0],bb=Wa.a.length,Ia=Jj(Pj(),Wa,1,bb),Ua=this.Si.a[0].a[0],pc=Ua.a.length,sc=Jj(Pj(),Ua,1,pc),Ba=this.Si.a[0].a[0].a[0],ob=Ba.a.length,nc=Jj(Pj(),Ba,1,ob),Ib=this.Si.a[0].a[0].a[0].a[0],vc=Ib.a.length,Vb=Jj(Pj(),Ib,1,vc),fc=this.Si.a[0].a[0].a[0].a[0].a[0],Bc=this.Si.a[Ab],Pb=zj(Pj(),Bc,ec),Jb=this.Si.a[Ab].a[ec],gc=zj(Pj(),Jb,Xb),Cb=this.Si.a[Ab].a[ec].a[Xb],cc=zj(Pj(),Cb,lc),yc=this.Si.a[Ab].a[ec].a[Xb].a[lc],Mc=zj(Pj(),yc,Lb),qc=this.Si.a[Ab].a[ec].a[Xb].a[lc].a[Lb],oc=1+\nuc|0,Qc=qc.a.length===oc?qc:zj(Pj(),qc,oc),jc=fc.a.length,sb=jc+(Vb.a.length<<5)|0,Gc=sb+(nc.a.length<<10)|0,Wb=Gc+(sc.a.length<<15)|0;return new OJ(fc,jc,Vb,sb,nc,Gc,sc,Wb,Ia,Wb+(Ia.a.length<<20)|0,fb,Pb,gc,cc,Mc,Qc,b)};f.u=function(){return\"VectorBuilder(len1\\x3d\"+this.Yd+\", lenRest\\x3d\"+this.yi+\", offset\\x3d\"+this.Gl+\", depth\\x3d\"+this.wg+\")\"};f.Kb=function(){return this.im()};f.zc=function(a){return OU(this,a)};f.$=function(a){return PU(this,a)};\nf.$classData=q({X8:0},!1,\"scala.collection.immutable.VectorBuilder\",{X8:1,g:1,Po:1,xg:1,xf:1,wf:1});function G1(){}G1.prototype=new p;G1.prototype.constructor=G1;f=G1.prototype;f.Hh=function(a){return RF(a)};function RF(a){var b=a.Q();if(0<=b){var c=new zc(16<b?b:16);Fs(a)?a.Gc(c,0,2147483647):a.m().Gc(c,0,2147483647);return H1(new I1,c,b)}return Lv(kl(),a)}f.Eb=function(){return new DF};f.X=function(){return kl()};f.Ib=function(a){return RF(a)};\nf.$classData=q({d9:0},!1,\"scala.collection.mutable.ArrayBuffer$\",{d9:1,g:1,Qt:1,Nk:1,bg:1,l:1});var J1;function QF(){J1||(J1=new G1);return J1}function DF(){this.lk=null;PV(this,kl())}DF.prototype=new EZ;DF.prototype.constructor=DF;DF.prototype.he=function(a){K1(this.lk,a)};DF.prototype.$classData=q({e9:0},!1,\"scala.collection.mutable.ArrayBuffer$$anon$1\",{e9:1,tC:1,g:1,xg:1,xf:1,wf:1});function L1(){}L1.prototype=new p;L1.prototype.constructor=L1;f=L1.prototype;f.Hh=function(a){return M1(a)};\nfunction M1(a){var b=a.Q();if(0<=b){var c=N1(0,b);Fs(a)?a.Gc(c,0,2147483647):a.m().Gc(c,0,2147483647);return O1(new P1,c,0,b)}return vU(Q1(),a)}f.Eb=function(){return new R1};function N1(a,b){if(!(0<=b))throw Kj(\"requirement failed: Non-negative array size required\");a=(-2147483648>>>Math.clz32(b)|0)<<1;if(!(0<=a))throw Kj(\"requirement failed: ArrayDeque too big - cannot allocate ArrayDeque of length \"+b);return new zc(16<a?a:16)}f.X=function(){return Q1()};f.Ib=function(a){return M1(a)};\nf.$classData=q({h9:0},!1,\"scala.collection.mutable.ArrayDeque$\",{h9:1,g:1,Qt:1,Nk:1,bg:1,l:1});var S1;function T1(){S1||(S1=new L1);return S1}function R1(){this.lk=null;PV(this,Q1())}R1.prototype=new EZ;R1.prototype.constructor=R1;R1.prototype.he=function(a){var b=this.lk;a>((b.Ke-b.Zd|0)&(-1+b.ec.a.length|0))&&a>=b.ec.a.length&&U1(b,a)};R1.prototype.$classData=q({i9:0},!1,\"scala.collection.mutable.ArrayDeque$$anon$1\",{i9:1,tC:1,g:1,xg:1,xf:1,wf:1});function V1(){this.Bl=null;this.Bl=W1()}\nV1.prototype=new MY;V1.prototype.constructor=V1;V1.prototype.$classData=q({u9:0},!1,\"scala.collection.mutable.Buffer$\",{u9:1,FG:1,g:1,Nk:1,bg:1,l:1});var X1;function PE(){X1||(X1=new V1);return X1}function EV(a,b){this.lk=null;PV(this,CV(new DV,a,b))}EV.prototype=new EZ;EV.prototype.constructor=EV;EV.prototype.he=function(a){this.lk.he(a)};EV.prototype.$classData=q({L9:0},!1,\"scala.collection.mutable.HashMap$$anon$6\",{L9:1,tC:1,g:1,xg:1,xf:1,wf:1});\nfunction Y1(a,b){if(null===b)throw null;a.uw=b;a.hq=0;a.Lo=null;a.vw=b.eb.a.length}function Z1(){this.hq=0;this.Lo=null;this.vw=0;this.uw=null}Z1.prototype=new BY;Z1.prototype.constructor=Z1;function $1(){}$1.prototype=Z1.prototype;Z1.prototype.s=function(){if(null!==this.Lo)return!0;for(;this.hq<this.vw;){var a=this.uw.eb.a[this.hq];this.hq=1+this.hq|0;if(null!==a)return this.Lo=a,!0}return!1};Z1.prototype.t=function(){if(this.s()){var a=this.lB(this.Lo);this.Lo=this.Lo.$d;return a}return Rq().Pa.t()};\nfunction LV(a,b){this.lk=null;PV(this,JV(new KV,a,b))}LV.prototype=new EZ;LV.prototype.constructor=LV;LV.prototype.he=function(a){this.lk.he(a)};LV.prototype.$classData=q({S9:0},!1,\"scala.collection.mutable.HashSet$$anon$4\",{S9:1,tC:1,g:1,xg:1,xf:1,wf:1});function a2(a,b){if(null===b)throw null;a.uC=b;a.iu=0;a.Ur=null;a.vC=b.zg.a.length}function b2(){this.iu=0;this.Ur=null;this.vC=0;this.uC=null}b2.prototype=new BY;b2.prototype.constructor=b2;function c2(){}c2.prototype=b2.prototype;\nb2.prototype.s=function(){if(null!==this.Ur)return!0;for(;this.iu<this.vC;){var a=this.uC.zg.a[this.iu];this.iu=1+this.iu|0;if(null!==a)return this.Ur=a,!0}return!1};b2.prototype.t=function(){if(this.s()){var a=this.DJ(this.Ur);this.Ur=this.Ur.yg;return a}return Rq().Pa.t()};function d2(){this.wC=null}d2.prototype=new p;d2.prototype.constructor=d2;function e2(){}e2.prototype=d2.prototype;d2.prototype.he=function(){};d2.prototype.zc=function(a){return lR(this,a)};d2.prototype.Kb=function(){return this.wC};\nfunction f2(){this.Bl=null;this.Bl=QF()}f2.prototype=new MY;f2.prototype.constructor=f2;f2.prototype.$classData=q({X9:0},!1,\"scala.collection.mutable.IndexedSeq$\",{X9:1,FG:1,g:1,Nk:1,bg:1,l:1});var g2;function WC(a){this.xC=a.Gn}WC.prototype=new BY;WC.prototype.constructor=WC;WC.prototype.s=function(){return null!==this.xC};WC.prototype.gm=function(){if(this.s()){var a=G(new H,this.xC.ju,this.xC.Fn);this.xC=this.xC.zm;return a}return Rq().Pa.t()};WC.prototype.t=function(){return this.gm()};\nWC.prototype.$classData=q({b$:0},!1,\"scala.collection.mutable.LinkedHashMap$$anon$2\",{b$:1,Sa:1,g:1,Ka:1,M:1,N:1});function h2(a){this.jH=a.Gn}h2.prototype=new BY;h2.prototype.constructor=h2;h2.prototype.s=function(){return null!==this.jH};h2.prototype.t=function(){if(this.s()){var a=this.jH.ju;this.jH=this.jH.zm;return a}return Rq().Pa.t()};h2.prototype.$classData=q({c$:0},!1,\"scala.collection.mutable.LinkedHashMap$$anon$3\",{c$:1,Sa:1,g:1,Ka:1,M:1,N:1});function i2(a){this.kH=a.Gn}i2.prototype=new BY;\ni2.prototype.constructor=i2;i2.prototype.s=function(){return null!==this.kH};i2.prototype.t=function(){if(this.s()){var a=this.kH.Fn;this.kH=this.kH.zm;return a}return Rq().Pa.t()};i2.prototype.$classData=q({d$:0},!1,\"scala.collection.mutable.LinkedHashMap$$anon$4\",{d$:1,Sa:1,g:1,Ka:1,M:1,N:1});function qA(a){this.lH=a.ku}qA.prototype=new BY;qA.prototype.constructor=qA;qA.prototype.s=function(){return null!==this.lH};qA.prototype.t=function(){if(this.s()){var a=this.lH.zw;this.lH=this.lH.Mo;return a}return Rq().Pa.t()};\nqA.prototype.$classData=q({j$:0},!1,\"scala.collection.mutable.LinkedHashSet$$anon$2\",{j$:1,Sa:1,g:1,Ka:1,M:1,N:1});function j2(){}j2.prototype=new p;j2.prototype.constructor=j2;f=j2.prototype;f.Hh=function(a){return ep(new fp,a)};f.Eb=function(){return PV(new QV,new fp)};f.X=function(){return new fp};f.Ib=function(a){return ep(new fp,a)};f.$classData=q({m$:0},!1,\"scala.collection.mutable.ListBuffer$\",{m$:1,g:1,Qt:1,Nk:1,bg:1,l:1});var k2;function l2(){k2||(k2=new j2);return k2}\nfunction m2(a,b){this.gT=0;this.hT=a;this.q$=b;this.gT=Es(b)|0}m2.prototype=new BY;m2.prototype.constructor=m2;m2.prototype.s=function(){mK();var a=this.gT,b=Es(this.q$)|0;jK(a,b);return this.hT.s()};m2.prototype.t=function(){return this.hT.t()};m2.prototype.$classData=q({p$:0},!1,\"scala.collection.mutable.MutationTracker$CheckedIterator\",{p$:1,Sa:1,g:1,Ka:1,M:1,N:1});function n2(){}n2.prototype=new p;n2.prototype.constructor=n2;f=n2.prototype;f.Hh=function(a){return vU(new tU(16),a)};\nf.Eb=function(){return PV(new QV,new tU(16))};f.X=function(){return new tU(16)};f.Ib=function(a){return vU(new tU(16),a)};f.$classData=q({s$:0},!1,\"scala.collection.mutable.Queue$\",{s$:1,g:1,Qt:1,Nk:1,bg:1,l:1});var o2;function p2(){o2||(o2=new n2);return o2}function q2(a){!a.fz.b()&&null!==a.iq&&0<=a.DC.Da(a.iq.Oo,a.fz.o())&&(a.iq=null)}\nfunction r2(a,b,c,d,e){a.fz=d;a.DC=e;if(R()===c)xK(),e=b.zi,e=null===e?null:uK(e);else{if(!(c instanceof L))throw new w(c);c=c.k;xK();d=b.zi;if(null===d)e=null;else{b=null;for(var g=1;null!==d&&0!==g;)b=d,g=e.Da(c,d.Oo),d=0>g?d.Vc:d.Bc;e=0>=g?b:vK(0,b)}}a.iq=e;q2(a)}function s2(){this.iq=this.DC=this.fz=null}s2.prototype=new BY;s2.prototype.constructor=s2;function t2(){}t2.prototype=s2.prototype;s2.prototype.s=function(){return null!==this.iq};\ns2.prototype.t=function(){var a=this.iq;if(null===a)throw AH(\"next on empty iterator\");this.iq=vK(xK(),a);q2(this);return this.zK(a)};function u2(){}u2.prototype=new p;u2.prototype.constructor=u2;f=u2.prototype;f.Hh=function(a){return vU(new IX(16),a)};f.Eb=function(){return PV(new QV,new IX(16))};f.X=function(){return new IX(16)};f.Ib=function(a){return vU(new IX(16),a)};f.$classData=q({H$:0},!1,\"scala.collection.mutable.Stack$\",{H$:1,g:1,Qt:1,Nk:1,bg:1,l:1});var v2;\nfunction w2(){v2||(v2=new u2);return v2}function x2(a,b,c){return 0===a.Da(b,c)}function y2(a,b,c){return a.Yj(b,c)?b:c}function z2(a,b,c){return a.uj(b,c)?b:c}function A2(a,b){return b instanceof B2?(b=b.sn,null!==b&&b.i(a)):!1}var nfa=function mfa(a,b){return $f(b)?\"Array[\"+mfa(a,bg(b))+\"]\":b.qi.name};class fX extends Iq{constructor(a){super();Hq(this,a,void 0)}Cj(){}}fX.prototype.$classData=q({baa:0},!1,\"scala.runtime.NonLocalReturnControl$mcV$sp\",{baa:1,lT:1,s4:1,pc:1,g:1,l:1});\nfunction iD(a){this.nT=0;this.jaa=a;this.oH=0;this.nT=a.G()}iD.prototype=new BY;iD.prototype.constructor=iD;iD.prototype.s=function(){return this.oH<this.nT};iD.prototype.t=function(){var a=this.jaa.I(this.oH);this.oH=1+this.oH|0;return a};iD.prototype.$classData=q({iaa:0},!1,\"scala.runtime.ScalaRunTime$$anon$1\",{iaa:1,Sa:1,g:1,Ka:1,M:1,N:1});function C2(){}C2.prototype=new p;C2.prototype.constructor=C2;f=C2.prototype;f.Hh=function(a){return D2(a)};f.Eb=function(){return E2()};\nfunction D2(a){var b=E2();return lR(b,a).Kb()}f.Ib=function(a){return D2(a)};f.X=function(){return E2()};f.$classData=q({N$:0},!1,\"scala.scalajs.js.WrappedArray$\",{N$:1,g:1,Qt:1,Nk:1,bg:1,l:1});var F2;function W1(){F2||(F2=new C2);return F2}function G2(){}G2.prototype=new p;G2.prototype.constructor=G2;f=G2.prototype;f.Hh=function(a){return H2(this,a)};function H2(a,b){return a.Eb().zc(b).Kb()}f.Eb=function(){return new dU(Md(new Nd,[]),new y(a=>J(new K,a.Xr)))};f.Ib=function(a){return H2(this,a)};\nf.X=function(){var a=new K;J(a,[]);return a};f.$classData=q({W$:0},!1,\"scala.scalajs.runtime.WrappedVarArgs$\",{W$:1,g:1,Qt:1,Nk:1,bg:1,l:1});var I2;function J2(){I2||(I2=new G2);return I2}function fe(a){this.aa=a}fe.prototype=new PZ;fe.prototype.constructor=fe;f=fe.prototype;f.TJ=function(){return!0};f.tv=function(){return!1};f.H=function(){return\"Left\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.aa:$K(W(),a)};f.D=function(a){return a instanceof fe};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof fe?ml(nl(),this.aa,a.aa):!1};f.$classData=q({n4:0},!1,\"scala.util.Left\",{n4:1,l4:1,g:1,E:1,v:1,l:1});function Ud(a){this.fa=a}Ud.prototype=new PZ;Ud.prototype.constructor=Ud;f=Ud.prototype;f.TJ=function(){return!1};f.tv=function(){return!0};f.H=function(){return\"Right\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.fa:$K(W(),a)};f.D=function(a){return a instanceof Ud};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof Ud?ml(nl(),this.fa,a.fa):!1};var K2=q({p4:0},!1,\"scala.util.Right\",{p4:1,l4:1,g:1,E:1,v:1,l:1});Ud.prototype.$classData=K2;function Ne(a){this.Zl=a}Ne.prototype=new QL;Ne.prototype.constructor=Ne;f=Ne.prototype;f.H=function(){return\"Line\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Zl:$K(W(),a)};f.D=function(a){return a instanceof Ne};f.B=function(){var a=lb(\"Line\");a=W().C(-889275714,a);var b=this.Zl;a=W().C(a,b);return W().Ma(a,1)};\nf.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof Ne?this.Zl===a.Zl:!1};f.$classData=q({y0:0},!1,\"sourcecode.Line\",{y0:1,A0:1,g:1,E:1,v:1,l:1});function Oe(a){this.fn=a}Oe.prototype=new QL;Oe.prototype.constructor=Oe;f=Oe.prototype;f.H=function(){return\"Name\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.fn:$K(W(),a)};f.D=function(a){return a instanceof Oe};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof Oe?this.fn===a.fn:!1};f.$classData=q({z0:0},!1,\"sourcecode.Name\",{z0:1,A0:1,g:1,E:1,v:1,l:1});function P0(){var a=new dI;yF(a,null,null,!0);return a}class dI extends bL{}dI.prototype.$classData=q({P0:0},!1,\"java.lang.ArrayIndexOutOfBoundsException\",{P0:1,eK:1,Te:1,qd:1,pc:1,g:1,l:1});function mb(a){return ig(mg(),a)}\nvar iaa=q({X0:0},!1,\"java.lang.Double\",{X0:1,ur:1,g:1,l:1,nf:1,Et:1,UF:1},a=>\"number\"===typeof a),haa=q({Z0:0},!1,\"java.lang.Float\",{Z0:1,ur:1,g:1,l:1,nf:1,Et:1,UF:1},a=>ja(a)),gaa=q({b1:0},!1,\"java.lang.Integer\",{b1:1,ur:1,g:1,l:1,nf:1,Et:1,UF:1},a=>ha(a)),kaa=q({g1:0},!1,\"java.lang.Long\",{g1:1,ur:1,g:1,l:1,nf:1,Et:1,UF:1},a=>a instanceof ma);class ZL extends SZ{constructor(a){super();yF(this,a,null,!0)}}\nZL.prototype.$classData=q({p1:0},!1,\"java.lang.NumberFormatException\",{p1:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});function gk(a,b){return a.codePointAt(b)|0}function lb(a){for(var b=0,c=1,d=-1+a.length|0;0<=d;)b=b+Math.imul(a.charCodeAt(d),c)|0,c=Math.imul(31,c),d=-1+d|0;return b}function pa(a,b){for(var c=a.length,d=b.length,e=c<d?c:d,g=0;g!==e;){var h=g;h=a.charCodeAt(g)-b.charCodeAt(h)|0;if(0!==h)return h;g=1+g|0}return c-d|0}\nfunction L2(a,b,c,d){if(b>a.length||0>b||0>b)throw a=new tH,yF(a,\"Index out of Bound\",null,!0),a;d=d-0|0;for(var e=0;e<b;)c.a[e+d|0]=a.charCodeAt(e),e=1+e|0}function vH(a,b){b=TL(Pr(),b);return a.indexOf(b)|0}\nfunction je(a,b,c){b=Dk(b);a=new cq(b,a);a.VQ=0;a.Av=a.UQ;a.YF=0;a.Bv=null;a.qy=0;b=new jW;for(b.ly=LQ(new Sq);LN(a);){var d=a,e=b,g=c,h=d.Av,k=d.qy,l=MN(d);kW(e,h.substring(k,l));h=g.length;for(k=0;k<h;)switch(l=g.charCodeAt(k),l){case 36:for(l=k=1+k|0;;){if(k<h){var m=g.charCodeAt(k);m=48<=m&&57>=m}else m=!1;if(m)k=1+k|0;else break}UH();l=g.substring(l,k);m=TH(0,l,10);l=d;var n=KN(l);l=l.lK;if(0>m||m>l.O2)throw aL(new bL,\"\"+m);l=n[l.P2[m]|0];l=void 0!==l?l:null;null!==l&&kW(e,l);break;case 92:k=\n1+k|0;k<h&&lW(e,g.charCodeAt(k));k=1+k|0;break;default:lW(e,l),k=1+k|0}d.qy=NN(d)}kW(b,a.Av.substring(a.qy));a.qy=a.Av.length;return b.u()}\nfunction M2(a,b){b=Dk(b);if(\"\"===a)b=new (md(fa).Ia)([\"\"]);else{var c=new cq(b,a);b=[];for(var d=0;2147483646>(b.length|0)&&LN(c);){if(0!==NN(c)){var e=MN(c);b.push(a.substring(d,e))}d=NN(c)}b.push(a.substring(d));for(c=b.length|0;;)if(0!==c?(a=b[-1+c|0],a=null!==a&&La(a,\"\")):a=!1,a)c=-1+c|0;else break;a=new (md(fa).Ia)(c);for(d=0;d<c;)e=d,a.a[e]=b[e],d=1+d|0;b=a}return b}function or(a){for(var b=a.length,c=new Ic(b),d=0;d<b;)c.a[d]=a.charCodeAt(d),d=1+d|0;return c}\nvar fa=q({D0:0},!1,\"java.lang.String\",{D0:1,g:1,l:1,nf:1,ZJ:1,Et:1,UF:1},a=>\"string\"===typeof a);class tH extends bL{}tH.prototype.$classData=q({x1:0},!1,\"java.lang.StringIndexOutOfBoundsException\",{x1:1,eK:1,Te:1,qd:1,pc:1,g:1,l:1});class DM extends TZ{constructor(){super();yF(this,null,null,!0)}}DM.prototype.$classData=q({S1:0},!1,\"java.util.FormatterClosedException\",{S1:1,CQ:1,Te:1,qd:1,pc:1,g:1,l:1});function a_(a){this.VF=null;if(null===a)throw null;this.VF=a}a_.prototype=new XZ;\na_.prototype.constructor=a_;a_.prototype.vv=function(){return new GN(this.VF)};a_.prototype.ka=function(){return this.VF.yv};a_.prototype.L=function(a){if(ck(a)){var b=this.VF,c=a.so();if(null===c)var d=0;else d=ib(c),d^=d>>>16|0;b=ZZ(b,c,d,d&(-1+b.wl.a.length|0));if(null!==b)return b=b.xv,a=a.to(),null===b?null===a:La(b,a)}return!1};a_.prototype.$classData=q({V1:0},!1,\"java.util.HashMap$EntrySet\",{V1:1,F1:1,D1:1,g:1,OQ:1,d1:1,v2:1});function c_(a){this.yB=null;if(null===a)throw null;this.yB=a}\nc_.prototype=new XZ;c_.prototype.constructor=c_;c_.prototype.vv=function(){return new FN(this)};c_.prototype.ka=function(){return this.yB.zv.yv};c_.prototype.L=function(a){if(ck(a)){var b=a.so();if(this.yB.EF(b))return b=this.yB.LF(b),Object.is(b,a.to())}return!1};c_.prototype.$classData=q({Z1:0},!1,\"java.util.IdentityHashMap$EntrySet\",{Z1:1,F1:1,D1:1,g:1,OQ:1,d1:1,v2:1});class N2 extends SZ{}\nclass ek extends SZ{constructor(a,b,c){super();this.L2=a;this.N2=b;this.M2=c;yF(this,null,null,!0)}qj(){var a=this.M2,b=this.N2,c=this.L2+(0>a?\"\":\" near index \"+a)+\"\\n\"+b;if(0<=a&&null!==b&&a<b.length){if(0>a)throw UL();a=\" \".repeat(a);c=c+\"\\n\"+a+\"^\"}return c}}ek.prototype.$classData=q({K2:0},!1,\"java.util.regex.PatternSyntaxException\",{K2:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});function cs(a,b,c){this.Cc=a;this.td=b;this.Mf=c}cs.prototype=new Wz;cs.prototype.constructor=cs;f=cs.prototype;f.H=function(){return\"BRACKETS\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Cc;case 1:return this.td;default:return $K(W(),a)}};f.D=function(a){return a instanceof cs};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof cs&&this.Cc===a.Cc){var b=this.td;a=a.td;return null===b?null===a:b.i(a)}return!1};f.$classData=q({UT:0},!1,\"mlscript.BRACKETS\",{UT:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});function O2(){}O2.prototype=new Wz;\nO2.prototype.constructor=O2;f=O2.prototype;f.H=function(){return\"COMMA\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof O2};f.B=function(){return 64305845};f.u=function(){return\"COMMA\"};f.$classData=q({kU:0},!1,\"mlscript.COMMA$\",{kU:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});var P2;function Xr(){P2||(P2=new O2);return P2}function gs(a){this.PC=a}gs.prototype=new Wz;gs.prototype.constructor=gs;f=gs.prototype;f.H=function(){return\"COMMENT\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.PC:$K(W(),a)};f.D=function(a){return a instanceof gs};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof gs?this.PC===a.PC:!1};f.$classData=q({lU:0},!1,\"mlscript.COMMENT\",{lU:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});function Q2(){}Q2.prototype=new Wz;Q2.prototype.constructor=Q2;f=Q2.prototype;f.H=function(){return\"ERROR\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};\nf.D=function(a){return a instanceof Q2};f.B=function(){return 66247144};f.u=function(){return\"ERROR\"};f.$classData=q({MU:0},!1,\"mlscript.ERROR$\",{MU:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});var R2;function ts(){R2||(R2=new Q2);return R2}function Sn(a,b){this.UM=null;this.WM=this.XM=0;this.YM=this.VM=null;this.ms=0;this.Yf=a;this.Rg=b;Nq(this)}Sn.prototype=new p;Sn.prototype.constructor=Sn;f=Sn.prototype;f.Vj=function(){var a=this.Yf.ha(),b=this.Rg,c=O().c;return dl(new z(b,c),a)};\nf.jn=function(){0===(1&this.ms)<<24>>24&&0===(1&this.ms)<<24>>24&&(this.UM=zq(this),this.ms=(1|this.ms)<<24>>24);return this.UM};f.rn=function(){return this.XM};f.fm=function(a){this.XM=a};f.qn=function(){return this.WM};f.em=function(a){this.WM=a};f.pn=function(){return this.VM};f.on=function(a){this.VM=a};f.A=function(){0===(2&this.ms)<<24>>24&&0===(2&this.ms)<<24>>24&&(this.YM=Dq(this),this.ms=(2|this.ms)<<24>>24);return this.YM};f.H=function(){return\"Field\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.Yf;case 1:return this.Rg;default:return $K(W(),a)}};f.D=function(a){return a instanceof Sn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Sn){var b=this.Yf,c=a.Yf;if(null===b?null===c:b.i(c))return b=this.Rg,a=a.Rg,null===b?null===a:b.i(a)}return!1};f.$classData=q({RU:0},!1,\"mlscript.Field\",{RU:1,g:1,yaa:1,Ta:1,E:1,v:1,l:1});\nfunction sm(a,b){this.dN=null;this.fN=this.gN=0;this.hN=this.eN=null;this.os=0;this.yb=a;this.ya=b;Nq(this)}sm.prototype=new p;sm.prototype.constructor=sm;f=sm.prototype;f.Vj=function(){var a=this.ya,b=O().c;return new z(a,b)};f.jn=function(){0===(1&this.os)<<24>>24&&0===(1&this.os)<<24>>24&&(this.dN=zq(this),this.os=(1|this.os)<<24>>24);return this.dN};f.rn=function(){return this.gN};f.fm=function(a){this.gN=a};f.qn=function(){return this.fN};f.em=function(a){this.fN=a};f.pn=function(){return this.eN};\nf.on=function(a){this.eN=a};f.A=function(){0===(2&this.os)<<24>>24&&0===(2&this.os)<<24>>24&&(this.hN=Dq(this),this.os=(2|this.os)<<24>>24);return this.hN};f.H=function(){return\"Fld\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.yb;case 1:return this.ya;default:return $K(W(),a)}};f.D=function(a){return a instanceof sm};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof sm){var b=this.yb,c=a.yb;if(null===b?null===c:b.i(c))return b=this.ya,a=a.ya,null===b?null===a:b.i(a)}return!1};f.$classData=q({SU:0},!1,\"mlscript.Fld\",{SU:1,g:1,Aaa:1,Ta:1,E:1,v:1,l:1});function St(a,b,c){this.ZM=null;this.aN=this.bN=0;this.cN=this.$M=null;this.ns=0;this.je=a;this.ch=b;this.Bh=c;Nq(this)}St.prototype=new p;St.prototype.constructor=St;f=St.prototype;f.Vj=function(){return O().c};\nf.u=function(){if(null===this)throw new w(this);var a=(this.je?\"m\":\"\")+(this.ch?\"s\":\"\")+(this.Bh?\"g\":\"\");return\"\"===a?\"_\":a};f.jn=function(){0===(1&this.ns)<<24>>24&&0===(1&this.ns)<<24>>24&&(this.ZM=zq(this),this.ns=(1|this.ns)<<24>>24);return this.ZM};f.rn=function(){return this.bN};f.fm=function(a){this.bN=a};f.qn=function(){return this.aN};f.em=function(a){this.aN=a};f.pn=function(){return this.$M};f.on=function(a){this.$M=a};\nf.A=function(){0===(2&this.ns)<<24>>24&&0===(2&this.ns)<<24>>24&&(this.cN=Dq(this),this.ns=(2|this.ns)<<24>>24);return this.cN};f.H=function(){return\"FldFlags\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.je;case 1:return this.ch;case 2:return this.Bh;default:return $K(W(),a)}};f.D=function(a){return a instanceof St};\nf.B=function(){var a=lb(\"FldFlags\");a=W().C(-889275714,a);var b=this.je?1231:1237;a=W().C(a,b);b=this.ch?1231:1237;a=W().C(a,b);b=this.Bh?1231:1237;a=W().C(a,b);return W().Ma(a,3)};f.i=function(a){return this===a?!0:a instanceof St?this.je===a.je&&this.ch===a.ch&&this.Bh===a.Bh:!1};f.$classData=q({TU:0},!1,\"mlscript.FldFlags\",{TU:1,g:1,zaa:1,Ta:1,E:1,v:1,l:1});function bs(a,b){this.ae=a;this.ke=b}bs.prototype=new Wz;bs.prototype.constructor=bs;f=bs.prototype;f.H=function(){return\"IDENT\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.ae;case 1:return this.ke;default:return $K(W(),a)}};f.D=function(a){return a instanceof bs};f.B=function(){var a=lb(\"IDENT\");a=W().C(-889275714,a);var b=this.ae;b=My(W(),b);a=W().C(a,b);b=this.ke?1231:1237;a=W().C(a,b);return W().Ma(a,2)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof bs?this.ke===a.ke&&this.ae===a.ae:!1};f.$classData=q({XU:0},!1,\"mlscript.IDENT\",{XU:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});\nfunction Wo(a){this.bD=a}Wo.prototype=new fO;Wo.prototype.constructor=Wo;f=Wo.prototype;f.sh=function(){return 22};f.xa=function(){Qp();var a=this.bD;if(a===u())var b=u();else{b=a.e();var c=b=new z(Up(b,Vp().Az),u());for(a=a.f();a!==u();){var d=a.e();d=new z(Up(d,Vp().Az),u());c=c.p=d;a=a.f()}}return Uz(b)};f.H=function(){return\"JSArray\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.bD:$K(W(),a)};f.D=function(a){return a instanceof Wo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Wo){var b=this.bD;a=a.bD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({jV:0},!1,\"mlscript.JSArray\",{jV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function Hl(a){this.aD=a}Hl.prototype=new oO;Hl.prototype.constructor=Hl;f=Hl.prototype;f.xa=function(){Qp();var a=this.aD;if(a===u())var b=u();else{b=a.e();var c=b=new z(b.xa(),u());for(a=a.f();a!==u();){var d=a.e();d=new z(d.xa(),u());c=c.p=d;a=a.f()}}return Uz(b)};f.H=function(){return\"JSArrayPattern\"};\nf.G=function(){return 1};f.I=function(a){return 0===a?this.aD:$K(W(),a)};f.D=function(a){return a instanceof Hl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Hl){var b=this.aD;a=a.aD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({kV:0},!1,\"mlscript.JSArrayPattern\",{kV:1,BH:1,Xc:1,g:1,E:1,v:1,l:1});function oo(a,b){this.wz=a;this.cD=b}oo.prototype=new fO;oo.prototype.constructor=oo;f=oo.prototype;f.sh=function(){return 2};\nf.xa=function(){var a=Rp(Pp(Hf(this.wz).De(Qp().ye,new fn((g,h)=>{var k=G(new H,g,h);g=k.y;h=k.w;if(null!==h)return k=h.h(),h=h.Sc(),Rp(Rp(g,k instanceof El?Sp(Qp(),\"_\"+h):k.xa()),Pe(new E(h),-1+this.wz.K()|0)?Qp().ye:Sp(Qp(),\", \"));throw new w(k);})),!0),Qp().SN),b=!1,c=null,d=this.cD;a:{if(d instanceof fe){b=!0;c=d;var e=c.aa;if(e instanceof vo){b=Pp(e.xa(),!0);break a}}if(b)b=Up(c.aa,2);else if(d instanceof Ud){d=d.fa;Qp();if(d===u())b=u();else for(b=d.e(),c=b=new z(b.xa(),u()),d=d.f();d!==u();)e=\nd.e(),e=new z(e.xa(),u()),c=c.p=e,d=d.f();b=Oz(Sz(b))}else throw new w(d);}return Rp(a,b)};f.H=function(){return\"JSArrowFn\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.wz;case 1:return this.cD;default:return $K(W(),a)}};f.D=function(a){return a instanceof oo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof oo){var b=this.wz,c=a.wz;if(null===b?null===c:b.i(c))return b=this.cD,a=a.cD,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({lV:0},!1,\"mlscript.JSArrowFn\",{lV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function Lo(a,b){this.dD=a;this.eD=b}Lo.prototype=new fO;Lo.prototype.constructor=Lo;f=Lo.prototype;f.sh=function(){return 3};f.xa=function(){return Rp(Rp(Up(this.dD,3),Sp(Qp(),\" \\x3d \")),Up(this.eD,3))};f.H=function(){return\"JSAssignExpr\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.dD;case 1:return this.eD;default:return $K(W(),a)}};f.D=function(a){return a instanceof Lo};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Lo){var b=this.dD,c=a.dD;if(null===b?null===c:b.i(c))return b=this.eD,a=a.eD,null===b?null===a:b.i(a)}return!1};f.$classData=q({mV:0},!1,\"mlscript.JSAssignExpr\",{mV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function gn(a,b,c){this.Rw=a;this.hD=b;this.iD=c}gn.prototype=new fO;gn.prototype.constructor=gn;f=gn.prototype;\nf.sh=function(){var a=bO(Lm()).U(this.Rw);if(a instanceof L)return a.k|0;if(R()===a)throw vS(new wS,\"Unknown binary operator: \"+this.Rw);throw new w(a);};f.xa=function(){return Rp(Rp(Up(this.hD,this.sh()),Sp(Qp(),\" \"+this.Rw+\" \")),Up(this.iD,this.sh()))};f.H=function(){return\"JSBinary\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.Rw;case 1:return this.hD;case 2:return this.iD;default:return $K(W(),a)}};f.D=function(a){return a instanceof gn};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof gn&&this.Rw===a.Rw){var b=this.hD,c=a.hD;if(null===b?null===c:b.i(c))return b=this.iD,a=a.iD,null===b?null===a:b.i(a)}return!1};f.$classData=q({zV:0},!1,\"mlscript.JSBinary\",{zV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});q({CV:0},!1,\"mlscript.JSClassDecl\",{CV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function Mo(a){this.lD=a}Mo.prototype=new fO;Mo.prototype.constructor=Mo;f=Mo.prototype;f.sh=function(){return 22};f.xa=function(){return this.lD.xa()};\nf.H=function(){return\"JSClassExpr\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.lD:$K(W(),a)};f.D=function(a){return a instanceof Mo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Mo){var b=this.lD;a=a.lD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({DV:0},!1,\"mlscript.JSClassExpr\",{DV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});\nfunction xp(a,b,c,d,e,g,h,k,l,m,n,r,v,x){this.Ds=a;this.Au=b;this.Sw=c;this.Xw=d;this.Tw=e;this.Zw=g;this.sq=h;this.zz=k;this.Ww=l;this.Uw=m;this.Vw=n;this.yz=r;this.xz=v;this.Yw=x;$U(dV(),b)}xp.prototype=new qO;xp.prototype.constructor=xp;f=xp.prototype;\nf.xa=function(){var a=new fp,b=this.sq.m();b=new Ao(b);var c=this.zz;b=Qu(b,c instanceof L?\"...\"+c.k:\"\",new fn((k,l)=>\"\"===l?\"\"+k.h():k.h()+\", \"+l));for(c=this.yz;!c.b();){var d=\"  #\"+c.e()+\";\";wp(a,d);c=c.f()}for(c=hl(this.Xw);!c.b();)d=\"  #\"+c.e()+\";\",wp(a,d),c=c.f();for(c=hl(this.Sw);!c.b();){var e=c.e();if(null!==e)d=e.Rc(),e=e.j(),this.Xw.L(e)||wp(a,\"  #\"+e+\";\"),wp(a,\"  get \"+e+\"() { return this.#\"+e+\"; }\"),d&&wp(a,\"  set \"+e+\"($value) { return this.#\"+e+\" \\x3d $value; }\");else throw new w(e);\nc=c.f()}wp(a,\"  constructor(\"+b+\") {\");if(!this.Tw.b()){b=this.Zw.m();b=new Ao(b);for(c=\"\";b.s();)d=c,c=b.gm(),c=Pe(new E(c.Sc()),-1+this.Zw.K()|0)?\"\"+d+c.h().xa():\"\"+d+c.h().xa()+\", \";wp(a,\"    super(\"+c+\");\")}for(b=this.Uw;!b.b();)c=\"    \"+b.e()+\".implement(this);\",wp(a,c),b=b.f();if(!this.xz){b=this.Au.K();if(!Pe(new E(b),this.sq.K()))throw new Yj(\"assertion failed: fields and ctorParams have different size in class \"+this.Ds+\".\");b=this.Au;c=new Wq(b,b,this.sq);b=c.ck.m();for(c=c.dk.m();b.s()&&\nc.s();)d=b.t(),e=c.t(),wp(a,\"    this.#\"+d+\" \\x3d \"+e+\";\")}for(b=this.Vw;!b.b();){c=Kz(Kz(b.e().xa())).$f;c=ze(c,\"\",\"\\n\",\"\");var g=M2(c,\"\\n\");c=(k=>l=>wp(k,l))(a);d=g.a.length;e=0;if(null!==g)for(;e<d;)c(g.a[e]),e=1+e|0;else if(g instanceof Xc)for(;e<d;)c(g.a[e]),e=1+e|0;else if(g instanceof ed)for(;e<d;)c(g.a[e]),e=1+e|0;else if(g instanceof Zc)for(;e<d;){var h=g.a[e];c(new ma(h.W,h.Y));e=1+e|0}else if(g instanceof $c)for(;e<d;)c(g.a[e]),e=1+e|0;else if(g instanceof Ic)for(;e<d;)c(hc(g.a[e])),e=\n1+e|0;else if(g instanceof Pc)for(;e<d;)c(g.a[e]),e=1+e|0;else if(g instanceof Sc)for(;e<d;)c(g.a[e]),e=1+e|0;else if(g instanceof Ec)for(;e<d;)c(g.a[e]),e=1+e|0;else throw new w(g);b=b.f()}wp(a,\"  }\");a=Rz(Qp(),a.ha());b=this.Ww;for(c=Qp().ye;!b.b();)d=b.e(),c=Iz(c,Kz(d.xa())),b=b.f();b=c;c=this.Yw;for(d=Qp().ye;!c.b();)e=c.e(),d=Iz(Iz(d,Sp(Qp(),\"static\")),Kz(e.xa())),c=c.f();c=d;d=Sp(Qp(),\"}\");e=this.Tw;if(e instanceof L)return e=e.k,Iz(Iz(Iz(Iz(Rp(Rp(Sp(Qp(),\"class \"+this.Ds+\" extends \"),e.xa()),\nSp(Qp(),\" {\")),a),b),c),d);if(R()===e){if(this.Au.b()&&this.Ww.b()&&this.Uw.b()&&this.Sw.b()&&this.Vw.b()&&this.Yw.b())return Sp(Qp(),\"class \"+this.Ds+\" {}\");Qp();e=\"class \"+this.Ds+\" {\";g=O().c;return Iz(Iz(Iz(Iz(Rz(0,new z(e,g)),a),b),c),d)}throw new w(e);};f.H=function(){return\"JSClassNewDecl\"};f.G=function(){return 14};\nf.I=function(a){switch(a){case 0:return this.Ds;case 1:return this.Au;case 2:return this.Sw;case 3:return this.Xw;case 4:return this.Tw;case 5:return this.Zw;case 6:return this.sq;case 7:return this.zz;case 8:return this.Ww;case 9:return this.Uw;case 10:return this.Vw;case 11:return this.yz;case 12:return this.xz;case 13:return this.Yw;default:return $K(W(),a)}};f.D=function(a){return a instanceof xp};\nf.B=function(){var a=lb(\"JSClassNewDecl\");a=W().C(-889275714,a);var b=this.Ds;b=My(W(),b);a=W().C(a,b);b=this.Au;b=My(W(),b);a=W().C(a,b);b=this.Sw;b=My(W(),b);a=W().C(a,b);b=this.Xw;b=My(W(),b);a=W().C(a,b);b=this.Tw;b=My(W(),b);a=W().C(a,b);b=this.Zw;b=My(W(),b);a=W().C(a,b);b=this.sq;b=My(W(),b);a=W().C(a,b);b=this.zz;b=My(W(),b);a=W().C(a,b);b=this.Ww;b=My(W(),b);a=W().C(a,b);b=this.Uw;b=My(W(),b);a=W().C(a,b);b=this.Vw;b=My(W(),b);a=W().C(a,b);b=this.yz;b=My(W(),b);a=W().C(a,b);b=this.xz?1231:\n1237;a=W().C(a,b);b=this.Yw;b=My(W(),b);a=W().C(a,b);return W().Ma(a,14)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof xp){if(this.xz===a.xz)if(this.Ds===a.Ds){var b=this.Au,c=a.Au;b=null===b?null===c:b.i(c)}else b=!1;else b=!1;b?(b=this.Sw,c=a.Sw,(null===b?null===c:b.i(c))?(b=this.Xw,c=a.Xw,b=null===b?null===c:b.i(c)):b=!1,b?(b=this.Tw,c=a.Tw,(null===b?null===c:b.i(c))?(b=this.Zw,c=a.Zw,b=null===b?null===c:b.i(c)):b=!1):b=!1):b=!1;if(b&&(b=this.sq,c=a.sq,(null===b?null===c:b.i(c))?(b=this.zz,c=a.zz,(null===b?null===c:b.i(c))?(b=this.Ww,c=a.Ww,b=null===b?null===\nc:b.i(c)):b=!1):b=!1,b&&(b=this.Uw,c=a.Uw,(null===b?null===c:b.i(c))?(b=this.Vw,c=a.Vw,b=null===b?null===c:b.i(c)):b=!1,b&&(b=this.yz,c=a.yz,null===b?null===c:b.i(c)))))return b=this.Yw,a=a.Yw,null===b?null===a:b.i(a)}return!1};f.$classData=q({HV:0},!1,\"mlscript.JSClassNewDecl\",{HV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function Ro(a){this.rD=a}Ro.prototype=new fO;Ro.prototype.constructor=Ro;f=Ro.prototype;f.sh=function(){return 1};\nf.xa=function(){var a=Qp(),b=this.rD;if(b===u())var c=u();else{c=b.e();var d=c=new z(c.xa(),u());for(b=b.f();b!==u();){var e=b.e();e=new z(e.xa(),u());d=d.p=e;b=b.f()}}d=Qp();return Uba(a,c,d.RN)};f.H=function(){return\"JSCommaExpr\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.rD:$K(W(),a)};f.D=function(a){return a instanceof Ro};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Ro){var b=this.rD;a=a.rD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({IV:0},!1,\"mlscript.JSCommaExpr\",{IV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function qn(a,b){this.sD=a;this.$w=b}qn.prototype=new qO;qn.prototype.constructor=qn;f=qn.prototype;f.xa=function(){var a=Sp(Qp(),\"const \"+this.sD+\" \\x3d \"),b=this.$w instanceof Ro?Pp(this.$w.xa(),!0):this.$w.xa();return Rp(Rp(a,b),Qp().zx)};f.H=function(){return\"JSConstDecl\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.sD;case 1:return this.$w;default:return $K(W(),a)}};f.D=function(a){return a instanceof qn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof qn&&this.sD===a.sD){var b=this.$w;a=a.$w;return null===b?null===a:b.i(a)}return!1};f.$classData=q({KV:0},!1,\"mlscript.JSConstDecl\",{KV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function Bo(a){this.Bz=a}Bo.prototype=new qO;Bo.prototype.constructor=Bo;f=Bo.prototype;\nf.xa=function(){return Rp(Pp(this.Bz.xa(),this.Bz instanceof vo),Qp().zx)};f.H=function(){return\"JSExprStmt\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Bz:$K(W(),a)};f.D=function(a){return a instanceof Bo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Bo){var b=this.Bz;a=a.Bz;return null===b?null===a:b.i(a)}return!1};f.$classData=q({NV:0},!1,\"mlscript.JSExprStmt\",{NV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});\nfunction Az(a,b,c){this.yD=a;this.xD=b;this.wD=c}Az.prototype=new qO;Az.prototype.constructor=Az;f=Az.prototype;f.xa=function(){for(var a=Rp(Rp(Rp(Rp(Sp(Qp(),\"for (const \"),this.yD.xa()),Sp(Qp(),\" in \")),this.xD.xa()),Sp(Qp(),\")\")),b=this.wD,c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,d.xa());b=b.f()}return Rp(a,Oz(c))};f.H=function(){return\"JSForInStmt\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.yD;case 1:return this.xD;case 2:return this.wD;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof Az};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Az){var b=this.yD,c=a.yD;if(null===b?null===c:b.i(c))if(b=this.xD,c=a.xD,null===b?null===c:b.i(c))return b=this.wD,a=a.wD,null===b?null===a:b.i(a)}return!1};f.$classData=q({QV:0},!1,\"mlscript.JSForInStmt\",{QV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function sz(a,b,c){this.AD=a;this.BD=b;this.zD=c}sz.prototype=new qO;sz.prototype.constructor=sz;f=sz.prototype;\nf.xa=function(){for(var a=Rp(Rp(Sp(Qp(),\"function \"+this.AD),Op(Lp(),this.BD)),Qp().bA),b=this.zD,c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,d.xa());b=b.f()}return Rp(a,Oz(c))};f.H=function(){return\"JSFuncDecl\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.AD;case 1:return this.BD;case 2:return this.zD;default:return $K(W(),a)}};f.D=function(a){return a instanceof sz};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof sz&&this.AD===a.AD){var b=this.BD,c=a.BD;if(null===b?null===c:b.i(c))return b=this.zD,a=a.zD,null===b?null===a:b.i(a)}return!1};f.$classData=q({RV:0},!1,\"mlscript.JSFuncDecl\",{RV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function wo(a,b,c){this.DD=a;this.ED=b;this.CD=c}wo.prototype=new fO;wo.prototype.constructor=wo;f=wo.prototype;f.sh=function(){return 22};\nf.xa=function(){Qp();var a=this.DD;a=Rp(Rp(Sp(0,\"function \"+(a.b()?\"\":a.o())),Op(Lp(),this.ED)),Qp().bA);Qp();var b=this.CD;if(b===u())var c=u();else{c=b.e();var d=c=new z(c.xa(),u());for(b=b.f();b!==u();){var e=b.e();e=new z(e.xa(),u());d=d.p=e;b=b.f()}}return Rp(a,Oz(Sz(c)))};f.H=function(){return\"JSFuncExpr\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.DD;case 1:return this.ED;case 2:return this.CD;default:return $K(W(),a)}};f.D=function(a){return a instanceof wo};\nf.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof wo){var b=this.DD,c=a.DD;if(null===b?null===c:b.i(c))if(b=this.ED,c=a.ED,null===b?null===c:b.i(c))return b=this.CD,a=a.CD,null===b?null===a:b.i(a)}return!1};f.$classData=q({SV:0},!1,\"mlscript.JSFuncExpr\",{SV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function km(a){this.tq=a}km.prototype=new fO;km.prototype.constructor=km;f=km.prototype;f.sh=function(){return 22};\nf.xa=function(){return Sp(Qp(),this.tq)};f.H=function(){return\"JSIdent\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.tq:$K(W(),a)};f.D=function(a){return a instanceof km};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof km?this.tq===a.tq:!1};f.$classData=q({TV:0},!1,\"mlscript.JSIdent\",{TV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function dp(a,b,c){this.GD=a;this.FD=b;this.Cz=c}dp.prototype=new qO;dp.prototype.constructor=dp;f=dp.prototype;\nf.xa=function(){var a=Sp(Qp(),\"if \");a:{var b=this.GD.xa();switch(b.$f.K()){case 0:var c=b;break a;case 1:var d=b.$f;if(d===u())c=u();else for(c=d.e(),b=c=new z(Mz(c),u()),d=d.f();d!==u();){var e=d.e();e=new z(Mz(e),u());b=b.p=e;d=d.f()}c=new Hz(c);break a;default:c=new Jz(\"(\",0);e=b.$f;if(e===u())b=u();else for(b=e.e(),d=b=new z(Lz(b),u()),e=e.f();e!==u();){var g=e.e();g=new z(Lz(g),u());d=d.p=g;e=e.f()}t();d=J(new K,[new Jz(\")\",0)]);b=dl(Pd(u(),d),b);c=new Hz(new z(c,b))}}a=Rp(Rp(a,c),Qp().bA);\nc=this.FD;for(b=Qp().ye;!c.b();)d=c.e(),b=Iz(b,d.xa()),c=c.f();a=Rp(a,Oz(b));c=this.Cz;b=O().c;if(null===b?null===c:b.i(c))c=Qp().ye;else{c=Sp(Qp(),\" else \");b=this.Cz;for(d=Qp().ye;!b.b();)e=b.e(),d=Iz(d,e.xa()),b=b.f();c=Rp(c,Oz(d))}return Rp(a,c)};f.H=function(){return\"JSIfStmt\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.GD;case 1:return this.FD;case 2:return this.Cz;default:return $K(W(),a)}};f.D=function(a){return a instanceof dp};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof dp){var b=this.GD,c=a.GD;if(null===b?null===c:b.i(c))if(b=this.FD,c=a.FD,null===b?null===c:b.i(c))return b=this.Cz,a=a.Cz,null===b?null===a:b.i(a)}return!1};f.$classData=q({UV:0},!1,\"mlscript.JSIfStmt\",{UV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function dn(a,b,c,d){this.HD=a;this.Fz=b;this.Ez=c;this.Dz=d}dn.prototype=new fO;dn.prototype.constructor=dn;f=dn.prototype;f.sh=function(){return 22};\nf.xa=function(){var a=this.HD;if(R()===a){a=Sp(Qp(),Op(Lp(),this.Fz)+\" \\x3d\\x3e \");var b=!1,c=null,d=this.Ez;a:{if(d instanceof fe){b=!0;c=d;var e=c.aa;if(e instanceof vo){b=Pp(e.xa(),!0);break a}}if(b)b=Up(c.aa,2);else if(d instanceof Ud){b=d.fa;for(c=Qp().ye;!b.b();)d=b.e(),c=Iz(c,d.xa()),b=b.f();b=Oz(c)}else throw new w(d);}return Rp(Pp(Rp(a,b),!0),Tp(Lp(),this.Dz))}if(a instanceof L){a=a.k;a=Sp(Qp(),\"function \"+a+Op(Lp(),this.Fz)+\" \");b=this.Ez;if(b instanceof fe)b=rn(b.aa).xa();else{if(!(b instanceof\nUd))throw new w(b);b=b.fa;for(c=Qp().ye;!b.b();)d=b.e(),c=Iz(c,d.xa()),b=b.f();b=c}return Rp(Pp(Rp(a,Oz(b)),!0),Tp(Lp(),this.Dz))}throw new w(a);};f.H=function(){return\"JSImmEvalFn\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.HD;case 1:return this.Fz;case 2:return this.Ez;case 3:return this.Dz;default:return $K(W(),a)}};f.D=function(a){return a instanceof dn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof dn){var b=this.HD,c=a.HD;(null===b?null===c:b.i(c))?(b=this.Fz,c=a.Fz,b=null===b?null===c:b.i(c)):b=!1;if(b&&(b=this.Ez,c=a.Ez,null===b?null===c:b.i(c)))return b=this.Dz,a=a.Dz,null===b?null===a:b.i(a)}return!1};f.$classData=q({VV:0},!1,\"mlscript.JSImmEvalFn\",{VV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function kn(a,b){this.ID=a;this.JD=b}kn.prototype=new fO;kn.prototype.constructor=kn;f=kn.prototype;f.sh=function(){return 12};\nf.xa=function(){return Rp(Rp(this.ID.xa(),Sp(Qp(),\" instanceof \")),this.JD.xa())};f.H=function(){return\"JSInstanceOf\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.ID;case 1:return this.JD;default:return $K(W(),a)}};f.D=function(a){return a instanceof kn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof kn){var b=this.ID,c=a.ID;if(null===b?null===c:b.i(c))return b=this.JD,a=a.JD,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({WV:0},!1,\"mlscript.JSInstanceOf\",{WV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function cn(a,b){this.KD=a;this.Gz=b}cn.prototype=new fO;cn.prototype.constructor=cn;f=cn.prototype;f.sh=function(){return 20};f.xa=function(){var a=Up(this.KD,20),b=Hf(this.Gz).De(Qp().ye,new fn((c,d)=>{var e=G(new H,c,d);c=e.y;d=e.w;if(null!==d)return e=d.Sc(),Rp(Rp(c,Up(d.h(),Vp().Az)),Pe(new E(e),-1+this.Gz.K()|0)?Qp().ye:Sp(Qp(),\", \"));throw new w(e);}));return Rp(a,Pp(b,!0))};f.H=function(){return\"JSInvoke\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.KD;case 1:return this.Gz;default:return $K(W(),a)}};f.D=function(a){return a instanceof cn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof cn){var b=this.KD,c=a.KD;if(null===b?null===c:b.i(c))return b=this.Gz,a=a.Gz,null===b?null===a:b.i(a)}return!1};f.$classData=q({XV:0},!1,\"mlscript.JSInvoke\",{XV:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function Eo(a){this.Hz=a}\nEo.prototype=new qO;Eo.prototype.constructor=Eo;f=Eo.prototype;f.xa=function(){return Rp(Rp(Sp(Qp(),\"let \"),Hf(this.Hz).De(Qp().ye,new fn((a,b)=>{var c=G(new H,a,b);a=c.y;b=c.w;if(null!==b){c=b.h();b=b.Sc();a:{if(null!==c){var d=c.h(),e=c.j();if(t().d===e){c=Sp(Qp(),d);break a}}if(null!==c&&(d=c.h(),e=c.j(),e instanceof L)){c=e.k;c=Rp(Rp(Sp(Qp(),d),Sp(Qp(),\" \\x3d \")),c.xa());break a}throw new w(c);}return Rp(Rp(a,c),Pe(new E(b),-1+this.Hz.K()|0)?Qp().ye:Sp(Qp(),\", \"))}throw new w(c);}))),Qp().zx)};\nf.H=function(){return\"JSLetDecl\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Hz:$K(W(),a)};f.D=function(a){return a instanceof Eo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Eo){var b=this.Hz;a=a.Hz;return null===b?null===a:b.i(a)}return!1};f.$classData=q({YV:0},!1,\"mlscript.JSLetDecl\",{YV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function hn(a){this.LD=a}hn.prototype=new fO;hn.prototype.constructor=hn;f=hn.prototype;\nf.sh=function(){return 22};f.xa=function(){return Sp(Qp(),this.LD)};f.H=function(){return\"JSLit\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.LD:$K(W(),a)};f.D=function(a){return a instanceof hn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof hn?this.LD===a.LD:!1};f.$classData=q({$V:0},!1,\"mlscript.JSLit\",{$V:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function xl(a){this.MD=a}xl.prototype=new oO;xl.prototype.constructor=xl;f=xl.prototype;\nf.xa=function(){return Sp(Qp(),this.MD)};f.H=function(){return\"JSNamePattern\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.MD:$K(W(),a)};f.D=function(a){return a instanceof xl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof xl?this.MD===a.MD:!1};f.$classData=q({bW:0},!1,\"mlscript.JSNamePattern\",{bW:1,BH:1,Xc:1,g:1,E:1,v:1,l:1});function $m(a){this.ND=a}$m.prototype=new fO;$m.prototype.constructor=$m;f=$m.prototype;\nf.sh=function(){return 21};f.xa=function(){return Rp(Sp(Qp(),\"new \"),this.ND.xa())};f.H=function(){return\"JSNew\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.ND:$K(W(),a)};f.D=function(a){return a instanceof $m};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof $m){var b=this.ND;a=a.ND;return null===b?null===a:b.i(a)}return!1};f.$classData=q({cW:0},!1,\"mlscript.JSNew\",{cW:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});\nfunction Bl(a){this.OD=a}Bl.prototype=new oO;Bl.prototype.constructor=Bl;f=Bl.prototype;\nf.xa=function(){Qp();var a=this.OD,b=g=>{if(null!==g){var h=new L(g);if(!h.b()){var k=h.k.h();h=h.k.j();if(h instanceof L&&h.k instanceof El)return Sp(Qp(),k)}}if(null!==g&&(h=new L(g),!h.b()&&(k=h.k.h(),h=h.k.j(),h instanceof L)))return g=h.k,Rp(Sp(Qp(),k+\": \"),g.xa());if(null!==g&&(h=new L(g),!h.b()&&(k=h.k.h(),h=h.k.j(),t().d===h)))return Sp(Qp(),k);throw new w(g);};if(a===u())b=u();else{var c=a.e(),d=c=new z(b(c),u());for(a=a.f();a!==u();){var e=a.e();e=new z(b(e),u());d=d.p=e;a=a.f()}b=c}return Tz(b)};\nf.H=function(){return\"JSObjectPattern\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.OD:$K(W(),a)};f.D=function(a){return a instanceof Bl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Bl){var b=this.OD;a=a.OD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({dW:0},!1,\"mlscript.JSObjectPattern\",{dW:1,BH:1,Xc:1,g:1,E:1,v:1,l:1});function Vo(a){this.PD=a}Vo.prototype=new fO;Vo.prototype.constructor=Vo;f=Vo.prototype;\nf.sh=function(){return 0};f.xa=function(){return Up(this.PD,0)};f.H=function(){return\"JSParenthesis\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.PD:$K(W(),a)};f.D=function(a){return a instanceof Vo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Vo){var b=this.PD;a=a.PD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({eW:0},!1,\"mlscript.JSParenthesis\",{eW:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});\nfunction vo(a,b){this.QD=a;this.RD=b}vo.prototype=new fO;vo.prototype.constructor=vo;f=vo.prototype;f.sh=function(){return 22};\nf.xa=function(){Qp();var a=this.QD,b=g=>{if(null!==g){var h=g.h();g=g.j();return Rp(Sp(Qp(),zl(Al(),h)+\": \"),Up(g,Vp().Az))}throw new w(g);};if(a===u())b=u();else{var c=a.e(),d=c=new z(b(c),u());for(a=a.f();a!==u();){var e=a.e();e=new z(b(e),u());d=d.p=e;a=a.f()}b=c}a=this.RD;if(a===u())c=u();else for(c=a.e(),d=c=new z(c.xa(),u()),a=a.f();a!==u();)e=a.e(),e=new z(e.xa(),u()),d=d.p=e,a=a.f();return Tz(un(b,c))};f.H=function(){return\"JSRecord\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.QD;case 1:return this.RD;default:return $K(W(),a)}};f.D=function(a){return a instanceof vo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof vo){var b=this.QD,c=a.QD;if(null===b?null===c:b.i(c))return b=this.RD,a=a.RD,null===b?null===a:b.i(a)}return!1};f.$classData=q({fW:0},!1,\"mlscript.JSRecord\",{fW:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function Io(a){this.SD=a}Io.prototype=new qO;\nIo.prototype.constructor=Io;f=Io.prototype;f.xa=function(){var a=this.SD;if(a instanceof L)a=a.k,a=Rp(Sp(Qp(),\"return \"),Nz(a.xa()));else{if(R()!==a)throw new w(a);a=Sp(Qp(),\"return\")}return Rp(a,Qp().zx)};f.H=function(){return\"JSReturnStmt\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.SD:$K(W(),a)};f.D=function(a){return a instanceof Io};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Io){var b=this.SD;a=a.SD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({gW:0},!1,\"mlscript.JSReturnStmt\",{gW:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function hO(a,b,c){this.XD=a;this.VD=b;this.WD=c}hO.prototype=new qO;hO.prototype.constructor=hO;f=hO.prototype;\nf.xa=function(){for(var a=Rp(Rp(Sp(Qp(),\"switch (\"),this.XD.xa()),Sp(Qp(),\") {\")),b=this.VD,c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,Kz(d.xa()));b=b.f()}a=Iz(a,c);b=this.WD;if(b instanceof L)b=Iz(Kz(b.k.xa()),Sp(Qp(),\"}\"));else{if(t().d!==b)throw new w(b);b=Sp(Qp(),\"}\")}return Iz(a,b)};f.H=function(){return\"JSSwitchStmt\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.XD;case 1:return this.VD;case 2:return this.WD;default:return $K(W(),a)}};f.D=function(a){return a instanceof hO};\nf.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof hO){var b=this.XD,c=a.XD;if(null===b?null===c:b.i(c))if(b=this.VD,c=a.VD,null===b?null===c:b.i(c))return b=this.WD,a=a.WD,null===b?null===a:b.i(a)}return!1};f.$classData=q({iW:0},!1,\"mlscript.JSSwitchStmt\",{iW:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function on(a,b,c){this.$D=a;this.ZD=b;this.YD=c}on.prototype=new fO;on.prototype.constructor=on;f=on.prototype;f.sh=function(){return 4};\nf.xa=function(){return Rp(Rp(Rp(Rp(Up(this.$D,4),Sp(Qp(),\" ? \")),Up(this.ZD,4)),Sp(Qp(),\" : \")),Up(this.YD,4))};f.H=function(){return\"JSTenary\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.$D;case 1:return this.ZD;case 2:return this.YD;default:return $K(W(),a)}};f.D=function(a){return a instanceof on};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof on){var b=this.$D,c=a.$D;if(null===b?null===c:b.i(c))if(b=this.ZD,c=a.ZD,null===b?null===c:b.i(c))return b=this.YD,a=a.YD,null===b?null===a:b.i(a)}return!1};f.$classData=q({jW:0},!1,\"mlscript.JSTenary\",{jW:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function bn(a){this.aE=a}bn.prototype=new qO;bn.prototype.constructor=bn;f=bn.prototype;f.xa=function(){return Rp(Rp(Sp(Qp(),\"throw \"),Nz(this.aE.xa())),Qp().zx)};f.H=function(){return\"JSThrowStmt\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.aE:$K(W(),a)};f.D=function(a){return a instanceof bn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof bn){var b=this.aE;a=a.aE;return null===b?null===a:b.i(a)}return!1};f.$classData=q({kW:0},!1,\"mlscript.JSThrowStmt\",{kW:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function xz(a,b){this.bE=a;this.cE=b}xz.prototype=new qO;xz.prototype.constructor=xz;f=xz.prototype;\nf.xa=function(){for(var a=Sp(Qp(),\"try \"),b=this.bE,c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,d.xa());b=b.f()}return Rp(Rp(a,Oz(c)),this.cE.xa())};f.H=function(){return\"JSTryStmt\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.bE;case 1:return this.cE;default:return $K(W(),a)}};f.D=function(a){return a instanceof xz};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof xz){var b=this.bE,c=a.bE;if(null===b?null===c:b.i(c))return b=this.cE,a=a.cE,null===b?null===a:b.i(a)}return!1};f.$classData=q({lW:0},!1,\"mlscript.JSTryStmt\",{lW:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function $o(a,b){this.Iz=a;this.dE=b}$o.prototype=new fO;$o.prototype.constructor=$o;f=$o.prototype;f.sh=function(){return 15};f.xa=function(){return Rp(\"typeof\"===this.Iz?Sp(Qp(),\"typeof \"):Sp(Qp(),this.Iz),Up(this.dE,15))};f.H=function(){return\"JSUnary\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Iz;case 1:return this.dE;default:return $K(W(),a)}};f.D=function(a){return a instanceof $o};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof $o&&this.Iz===a.Iz){var b=this.dE;a=a.dE;return null===b?null===a:b.i(a)}return!1};f.$classData=q({mW:0},!1,\"mlscript.JSUnary\",{mW:1,Vi:1,Xc:1,g:1,E:1,v:1,l:1});function Zo(a,b){this.fE=a;this.eE=b}Zo.prototype=new qO;\nZo.prototype.constructor=Zo;f=Zo.prototype;f.xa=function(){return Rp(Rp(Rp(Sp(Qp(),\"while (\"),this.fE.xa()),Sp(Qp(),\") \")),Oz(this.eE.xa()))};f.H=function(){return\"JSWhileStmt\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.fE;case 1:return this.eE;default:return $K(W(),a)}};f.D=function(a){return a instanceof Zo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Zo){var b=this.fE,c=a.fE;if(null===b?null===c:b.i(c))return b=this.eE,a=a.eE,null===b?null===a:b.i(a)}return!1};f.$classData=q({oW:0},!1,\"mlscript.JSWhileStmt\",{oW:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function El(){}El.prototype=new oO;El.prototype.constructor=El;f=El.prototype;f.xa=function(){return Qp().ye};f.H=function(){return\"JSWildcardPattern\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof El};\nf.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return a instanceof El};f.$classData=q({pW:0},!1,\"mlscript.JSWildcardPattern\",{pW:1,BH:1,Xc:1,g:1,E:1,v:1,l:1});function as(a){this.Na=a}as.prototype=new Wz;as.prototype.constructor=as;f=as.prototype;f.H=function(){return\"KEYWORD\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Na:$K(W(),a)};f.D=function(a){return a instanceof as};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof as?this.Na===a.Na:!1};f.$classData=q({qW:0},!1,\"mlscript.KEYWORD\",{qW:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});function fs(a){this.Cu=a}fs.prototype=new Wz;fs.prototype.constructor=fs;f=fs.prototype;f.H=function(){return\"LITVAL\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Cu:$K(W(),a)};f.D=function(a){return a instanceof fs};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof fs){var b=this.Cu;a=a.Cu;return null===b?null===a:b.i(a)}return!1};f.$classData=q({rW:0},!1,\"mlscript.LITVAL\",{rW:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});function S2(){}S2.prototype=new Wz;S2.prototype.constructor=S2;f=S2.prototype;f.H=function(){return\"NEWLINE\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof S2};f.B=function(){return-1731062412};f.u=function(){return\"NEWLINE\"};\nf.$classData=q({HW:0},!1,\"mlscript.NEWLINE$\",{HW:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});var T2;function qs(){T2||(T2=new S2);return T2}function LO(){}LO.prototype=new p;LO.prototype.constructor=LO;f=LO.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};\nf.Da=function(a,b){return Pea(a,b)};f.$classData=q({$W:0},!1,\"mlscript.NormalForms$Conjunct$Ordering$\",{$W:1,g:1,lm:1,Ji:1,mm:1,km:1,l:1});function FP(){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0}FP.prototype=new M_;FP.prototype.constructor=FP;function U2(){}U2.prototype=FP.prototype;function V2(){}V2.prototype=new Wz;V2.prototype.constructor=V2;f=V2.prototype;f.H=function(){return\"QUOTE\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof V2};f.B=function(){return 77416028};f.u=function(){return\"QUOTE\"};f.$classData=q({VX:0},!1,\"mlscript.QUOTE$\",{VX:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});var W2;function Yr(){W2||(W2=new V2);return W2}function ss(a){this.ux=a}ss.prototype=new Wz;ss.prototype.constructor=ss;f=ss.prototype;f.H=function(){return\"SELECT\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.ux:$K(W(),a)};f.D=function(a){return a instanceof ss};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof ss?this.ux===a.ux:!1};f.$classData=q({aY:0},!1,\"mlscript.SELECT\",{aY:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});function X2(){}X2.prototype=new Wz;X2.prototype.constructor=X2;f=X2.prototype;f.H=function(){return\"SEMI\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof X2};f.B=function(){return 2541422};f.u=function(){return\"SEMI\"};\nf.$classData=q({bY:0},!1,\"mlscript.SEMI$\",{bY:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});var Y2;function ds(){Y2||(Y2=new X2);return Y2}function Z2(){}Z2.prototype=new Wz;Z2.prototype.constructor=Z2;f=Z2.prototype;f.H=function(){return\"SPACE\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof Z2};f.B=function(){return 79100134};f.u=function(){return\"SPACE\"};f.$classData=q({cY:0},!1,\"mlscript.SPACE$\",{cY:1,yk:1,g:1,Wm:1,E:1,v:1,l:1});var $2;\nfunction Se(){$2||($2=new Z2);return $2}function a3(){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0;this.zk=this.Pq=this.Uq=this.xp=this.Bp=this.Cp=this.Sq=this.zp=this.Rq=this.wp=this.Ap=this.yp=this.Qq=this.Tq=null;this.Dp=0;this.hs=this.yq=this.Aq=this.Bq=this.zq=this.Dq=this.Cq=null;this.Im=this.Pw=0;this.iA=this.hA=this.Ku=null}a3.prototype=new K_;a3.prototype.constructor=a3;function b3(){}b3.prototype=a3.prototype;\nfunction c3(a){null===a.hA&&null===a.hA&&(a.hA=new aY(a))}function ofa(a){null===a.iA&&null===a.iA&&(a.iA=new bA(a))}function bz(a,b,c,d){if(!Ot(new E(b.pb),Bp())&&!Ot(new E(b.pb),zp()))throw Kj(\"requirement failed: \"+b.pb);var e=new vl(b.gb.V);if(a.$c&&Nm(new E(b.gb.V),\"Object\")){tp();var g=gq(new Ep(\"Object\"));b=d.$a.U(b.gb.V);b.b()?b=R():(b=b.o(),b=new L(gx(b)));b=b.b()?ap():b.o();g=g.Ce(b)}else g=jY(d,b.gb.V);return new Mu(a,e,g,c)}\nfunction rD(a,b,c,d){if(!Ot(new E(b.jj),Bp())&&!Ot(new E(b.jj),zp()))throw Kj(\"requirement failed: \"+b.jj);return new Mu(a,new vl(b.Wl.V),jY(d,b.Wl.V),c)}function TD(a,b,c){At(tp(),Ot(new E(b.jj),Fp()));return new nC(a,new vl(b.Wl.V),ap(),c)}function Xx(a,b,c,d){At(tp(),Ot(new E(b.pb),Fp()));var e=new vl(b.gb.V);b=d.$a.U(b.gb.V);b.b()?b=R():(b=b.o(),b=new L(gx(b)));return new nC(a,e,b.b()?ap():b.o(),c)}\nfunction fB(a,b,c,d){if(b instanceof fw)return fB(a,gB(b,c,!1,d),c,d);if(b instanceof LA){var e=b.ic,g=b.jc;if(!1===b.tc){b=fB(a,e,c,d);a=fB(a,g,c,d);c=b.Q()+a.Q()|0;c=Lv(Lv(Mv(8<c?c:8),b),a);a=Xu().X();for(c=sl(c).m();c.s();){g=c.t();d=g.h();b=a.U(d);if(b instanceof L)b=b.k,g=Nv(b,g.j(),V(b.Va));else{if(R()!==b)throw new w(b);g=g.j()}a.bj(d,g)}c=qp();return(new Pv(c)).vc(a)}}if(b instanceof Qv)return a=b.Ba,op(),pp(qp(),a);if(b instanceof ZB)return fB(a,b.mc(),c,d);if(b instanceof Tv){var h=b.kf;\nreturn fB(a,b.Ic,c,d).Fk(new y(k=>h.L(k.h())))}if(b instanceof cC)return fB(a,b.Sf,c,d);if(Uv(b)||b instanceof cv||b instanceof Vv||b instanceof lx||b instanceof MA||b instanceof FA||b instanceof LA||b instanceof Wv||b instanceof eC||b instanceof Qx||b instanceof Jv)return nf();throw new w(b);}function Fv(){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0}Fv.prototype=new S_;Fv.prototype.constructor=Fv;function d3(){}d3.prototype=Fv.prototype;\nfunction pba(a,b){b=G(new H,a,b);var c=b.y,d=b.w;if(Uv(c)&&c.q===a.q&&Uv(d)&&d.q===a.q)return uw(c,d);c=b.y;if(Uv(c)&&c.q===a.q)return-1;c=b.w;if(Uv(c)&&c.q===a.q)return 1;if(b.y instanceof cv&&b.w instanceof cv)return 0;if(b.y instanceof cv)return-1;if(b.w instanceof cv)return 1;if(b.y instanceof Sv&&b.w instanceof Sv)return 0;if(b.y instanceof Sv)return-1;if(b.w instanceof Sv)return 1;if(b.y instanceof zv&&b.w instanceof zv)return 0;if(b.y instanceof zv)return-1;if(b.w instanceof zv)return 1;if(b.y instanceof\nTv&&b.w instanceof Tv)return 0;if(b.y instanceof Tv)return-1;if(b.w instanceof Tv)return 1;if(b.y instanceof Jv&&b.w instanceof Jv)return 0;if(b.y instanceof Jv)return-1;if(b.w instanceof Jv)return 1;if(b.y instanceof Wv&&b.w instanceof Wv)return 0;throw new w(b);}Fv.prototype.kq=function(){return wv(xv(this.q))};Fv.prototype.Kc=function(a,b,c,d){return this.At(a,b,c,d)};function ix(a,b){this.J=null;this.kh=b;FC(this,a);b.Ua()}ix.prototype=new WP;ix.prototype.constructor=ix;f=ix.prototype;f.fQ=function(){return this.kh};\nf.fd=function(){return this.kh.fd()};f.H=function(){return\"CompletedTypeInfo\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.kh:$K(W(),a)};f.D=function(a){return a instanceof ix};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof ix&&a.J===this.J){var b=this.kh;a=a.kh;return null===b?null===a:b.i(a)}return!1};f.$classData=q({$Y:0},!1,\"mlscript.TyperDatatypes$CompletedTypeInfo\",{$Y:1,nZ:1,UO:1,g:1,E:1,v:1,l:1});\nfunction Dt(a){this.xP=this.wP=this.vP=null;this.zP=this.AP=0;this.BP=this.yP=null;this.Rj=0;this.Kx=a;Nq(this)}Dt.prototype=new p;Dt.prototype.constructor=Dt;f=Dt.prototype;f.Vj=function(){0===(1&this.Rj)<<24>>24&&0===(1&this.Rj)<<24>>24&&(this.vP=this.Kx,this.Rj=(1|this.Rj)<<24>>24);return this.vP};function ef(a){0===(2&a.Rj)<<24>>24&&0===(2&a.Rj)<<24>>24&&(a.wP=mea(a),a.Rj=(2|a.Rj)<<24>>24);return a.wP}\nf.jn=function(){0===(4&this.Rj)<<24>>24&&0===(4&this.Rj)<<24>>24&&(this.xP=zq(this),this.Rj=(4|this.Rj)<<24>>24);return this.xP};f.rn=function(){return this.AP};f.fm=function(a){this.AP=a};f.qn=function(){return this.zP};f.em=function(a){this.zP=a};f.pn=function(){return this.yP};f.on=function(a){this.yP=a};f.A=function(){0===(8&this.Rj)<<24>>24&&0===(8&this.Rj)<<24>>24&&(this.BP=Dq(this),this.Rj=(8|this.Rj)<<24>>24);return this.BP};f.H=function(){return\"TypingUnit\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.Kx:$K(W(),a)};f.D=function(a){return a instanceof Dt};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Dt){var b=this.Kx;a=a.Kx;return null===b?null===a:b.i(a)}return!1};f.$classData=q({ZZ:0},!1,\"mlscript.TypingUnit\",{ZZ:1,g:1,Taa:1,Ta:1,E:1,v:1,l:1});function e3(){this.ld=\"value\"}e3.prototype=new SN;e3.prototype.constructor=e3;f=e3.prototype;f.H=function(){return\"Val\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof e3};f.B=function(){return 85761};f.u=function(){return\"Val\"};f.$classData=q({d_:0},!1,\"mlscript.Val$\",{d_:1,sz:1,sx:1,g:1,E:1,v:1,l:1});var f3;function hx(){f3||(f3=new e3);return f3}function go(a,b){this.BA=a;this.Nx=b;this.bF=a;this.DP=!1}go.prototype=new p;go.prototype.constructor=go;f=go.prototype;f.xo=function(){return this.BA};f.zo=function(){return this.bF};f.u=function(){return\"function \"+this.BA};f.H=function(){return\"BuiltinSymbol\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.BA;case 1:return this.Nx;default:return $K(W(),a)}};f.D=function(a){return a instanceof go};f.B=function(){return AL(this)};f.i=function(a){return this===a?!0:a instanceof go?this.BA===a.BA&&this.Nx===a.Nx:!1};f.$classData=q({o_:0},!1,\"mlscript.codegen.BuiltinSymbol\",{o_:1,g:1,mt:1,cr:1,E:1,v:1,l:1});\nclass gm extends xF{constructor(a){super();this.ZI=a;yF(this,a,null,!0)}H(){return\"CodeGenError\"}G(){return 1}I(a){return 0===a?this.ZI:$K(W(),a)}D(a){return a instanceof gm}B(){return AL(this)}i(a){return this===a?!0:a instanceof gm?this.ZI===a.ZI:!1}}gm.prototype.$classData=q({q_:0},!1,\"mlscript.codegen.CodeGenError\",{q_:1,qd:1,pc:1,g:1,l:1,E:1,v:1});function lo(a,b,c,d,e){this.dr=a;this.Ox=b;this.Px=c;this.EA=d;this.FA=e;this.OP=!1}lo.prototype=new p;lo.prototype.constructor=lo;f=lo.prototype;\nf.u=function(){return\"new class member \"+this.dr};f.xo=function(){return this.dr};f.zo=function(){return this.dr};f.H=function(){return\"NewClassMemberSymbol\"};f.G=function(){return 5};f.I=function(a){switch(a){case 0:return this.dr;case 1:return this.Ox;case 2:return this.Px;case 3:return this.EA;case 4:return this.FA;default:return $K(W(),a)}};f.D=function(a){return a instanceof lo};\nf.B=function(){var a=lb(\"NewClassMemberSymbol\");a=W().C(-889275714,a);var b=this.dr;b=My(W(),b);a=W().C(a,b);b=this.Ox;b=My(W(),b);a=W().C(a,b);b=this.Px?1231:1237;a=W().C(a,b);b=this.EA?1231:1237;a=W().C(a,b);b=this.FA;b=My(W(),b);a=W().C(a,b);return W().Ma(a,5)};f.i=function(a){if(this===a)return!0;if(a instanceof lo&&this.Px===a.Px&&this.EA===a.EA&&this.dr===a.dr){var b=this.Ox,c=a.Ox;if(null===b?null===c:b.i(c))return b=this.FA,a=a.FA,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({u_:0},!1,\"mlscript.codegen.NewClassMemberSymbol\",{u_:1,g:1,mt:1,cr:1,E:1,v:1,l:1});function io(a,b,c,d,e){this.av=a;this.nt=b;this.RA=c;this.QA=d;this.z_=e}io.prototype=new p;io.prototype.constructor=io;f=io.prototype;f.xo=function(){return this.av};f.zo=function(){return this.nt};f.u=function(){return\"value \"+this.av};f.H=function(){return\"StubValueSymbol\"};f.G=function(){return 4};\nf.I=function(a){switch(a){case 0:return this.av;case 1:return this.nt;case 2:return this.RA;case 3:return this.QA;default:return $K(W(),a)}};f.D=function(a){return a instanceof io};f.B=function(){var a=lb(\"StubValueSymbol\");a=W().C(-889275714,a);var b=this.av;b=My(W(),b);a=W().C(a,b);b=this.nt;b=My(W(),b);a=W().C(a,b);b=this.RA?1231:1237;a=W().C(a,b);b=this.QA;b=My(W(),b);a=W().C(a,b);return W().Ma(a,4)};\nf.i=function(a){if(this===a)return!0;if(a instanceof io&&this.RA===a.RA&&this.av===a.av&&this.nt===a.nt){var b=this.QA;a=a.QA;return null===b?null===a:b.i(a)}return!1};f.$classData=q({y_:0},!1,\"mlscript.codegen.StubValueSymbol\",{y_:1,g:1,mt:1,cr:1,E:1,v:1,l:1});function nn(a,b,c){this.er=a;this.fJ=b;this.rF=c}nn.prototype=new p;nn.prototype.constructor=nn;f=nn.prototype;f.xo=function(){return this.er};f.mv=function(){return this.rF};f.u=function(){return\"type \"+this.er};f.H=function(){return\"TypeAliasSymbol\"};\nf.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.er;case 1:return this.fJ;case 2:return this.rF;default:return $K(W(),a)}};f.D=function(a){return a instanceof nn};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof nn){if(this.er===a.er){var b=this.fJ,c=a.fJ;b=null===b?null===c:b.i(c)}else b=!1;if(b)return b=this.rF,a=a.rF,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({D_:0},!1,\"mlscript.codegen.TypeAliasSymbol\",{D_:1,g:1,UA:1,cr:1,E:1,v:1,l:1});\nclass jo extends xF{constructor(a){super();this.gJ=a;var b=kl();for(a=new L(a);;){var c=a;if(c instanceof L)a=c.k,ol(b,a.av),a=a.QA,c=!0;else if(R()===c)c=!1;else throw new w(c);if(!c)break}a=ze(b,\"\",\", \",\"\");c=a.lastIndexOf(\", \")|0;a=-1<c?a.substring(0,c)+\" and \"+a.substring(2+c|0):a;b=b.Zg;yF(this,a+\" \"+(0<(1===b?0:1>b?-1:1)?\"are\":\"is\")+\" not implemented\",null,!0)}H(){return\"UnimplementedError\"}G(){return 1}I(a){return 0===a?this.gJ:$K(W(),a)}D(a){return a instanceof jo}B(){return AL(this)}i(a){if(this===\na)return!0;if(a instanceof jo){var b=this.gJ;a=a.gJ;return null===b?null===a:b.i(a)}return!1}}jo.prototype.$classData=q({E_:0},!1,\"mlscript.codegen.UnimplementedError\",{E_:1,qd:1,pc:1,g:1,l:1,E:1,v:1});function SE(a,b){this.lf=null;this.Wx=a;this.M_=b;qE(this)}SE.prototype=new hQ;SE.prototype.constructor=SE;f=SE.prototype;f.Cv=function(){return this.M_};f.u=function(){return\"\\u00ab\"+this.Wx+\" is any\"+tE(this)};f.H=function(){return\"MatchAny\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.Wx:$K(W(),a)};f.D=function(a){return a instanceof SE};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof SE){var b=this.Wx;a=a.Wx;return null===b?null===a:b.i(a)}return!1};f.$classData=q({L_:0},!1,\"mlscript.ucs.Clause$MatchAny\",{L_:1,XP:1,VA:1,g:1,E:1,v:1,l:1});function UE(a,b,c,d){this.lf=null;this.Yx=a;this.Xx=b;this.WA=c;this.tF=d;qE(this)}UE.prototype=new hQ;UE.prototype.constructor=UE;f=UE.prototype;f.Cv=function(){return this.tF};\nf.u=function(){return\"\\u00ab\"+this.Yx+\" is \"+this.Xx+\"\\u00bb\"+tE(this)};f.H=function(){return\"MatchClass\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.Yx;case 1:return this.Xx;case 2:return this.WA;default:return $K(W(),a)}};f.D=function(a){return a instanceof UE};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof UE){var b=this.Yx,c=a.Yx;if(null===b?null===c:b.i(c))if(b=this.Xx,c=a.Xx,null===b?null===c:b.i(c))return b=this.WA,a=a.WA,null===b?null===a:b.i(a)}return!1};f.$classData=q({N_:0},!1,\"mlscript.ucs.Clause$MatchClass\",{N_:1,XP:1,VA:1,g:1,E:1,v:1,l:1});function OE(a,b,c){this.lf=null;this.$x=a;this.Zx=b;this.TP=c;qE(this)}OE.prototype=new hQ;OE.prototype.constructor=OE;f=OE.prototype;f.Cv=function(){return this.TP};\nf.u=function(){return\"\\u00ab\"+this.$x+\" is \"+this.Zx+tE(this)};f.H=function(){return\"MatchLiteral\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.$x;case 1:return this.Zx;default:return $K(W(),a)}};f.D=function(a){return a instanceof OE};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof OE){var b=this.$x,c=a.$x;if(null===b?null===c:b.i(c))return b=this.Zx,a=a.Zx,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({O_:0},!1,\"mlscript.ucs.Clause$MatchLiteral\",{O_:1,XP:1,VA:1,g:1,E:1,v:1,l:1});function HE(a){this.ni=this.fv=null;this.ot=a;iQ(this)}HE.prototype=new kQ;HE.prototype.constructor=HE;f=HE.prototype;f.jb=function(){return\"Consequent(\"+Zz(this.ot,!1)+\")\"};f.zt=function(){};f.or=function(){var a=new HE(this.ot);return QE(a,this.ni)};f.Bt=function(){return!0};f.ky=function(){return!0};\nf.dm=function(a,b){var c=new fp,d=We(Xe(),\"Found a duplicated branch\"),e=t().d;d=G(new H,d,e);wp(c,d);d=We(Xe(),\"This branch\");a:{if(null!==a&&(e=new L(a),!e.b())){var g=e.k.j();if(null!==e.k.h())break a}throw new w(a);}a=g.A();a=G(new H,d,a);wp(c,a);a=We(Xe(),\"is subsumed by the branch here.\");d=this.ot.A();a=G(new H,a,d);wp(c,a);b.n(hr(fr(),c.ha(),!0,lu()))};f.Op=function(){return 0};f.H=function(){return\"Consequent\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.ot:$K(W(),a)};\nf.D=function(a){return a instanceof HE};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof HE){var b=this.ot;a=a.ot;return null===b?null===a:b.i(a)}return!1};f.$classData=q({Y_:0},!1,\"mlscript.ucs.MutCaseOf$Consequent\",{Y_:1,kJ:1,g:1,lJ:1,E:1,v:1,l:1});function CE(a,b,c){this.ni=this.fv=null;this.hr=a;this.Dk=b;this.Fh=c;iQ(this)}CE.prototype=new kQ;CE.prototype.constructor=CE;f=CE.prototype;\nf.jb=function(){return\"IfThenElse(\"+Zz(this.hr,!1)+\", whenTrue \\x3d \"+lQ(this.Dk)+\", whenFalse \\x3d \"+lQ(this.Fh)+\")\"};f.or=function(){var a=new CE(this.hr,this.Dk.or(),this.Fh.or());return QE(a,this.ni)};f.zt=function(a){this.Dk.zt(a);Pe(new E(this.Fh),IE())?this.Fh=a:this.Fh.zt(a)};f.Bt=function(){return this.Dk.Bt()&&this.Fh.Bt()};f.ky=function(a,b){return this.Dk.ky(a,b)&&this.Fh.ky(a,b)};\nf.dm=function(a,b,c,d,e){if(null!==a){var g=new L(a);if(!g.b()){var h=g.k.h();g=g.k.j();if(null!==h){var k=h.Wi;h=h.mj;var l=O().c;if(null===l?null===k:l.i(k)){a=this.Op(h,g,b,c,d,e);Pe(new E(a),0)&&(fr(),a=Ye(new Te(new Ue(J(new K,[\"Found a redundant else branch\"]))),u()),c=g.A(),a=G(new H,a,c),c=O().c,b.n(hr(0,new z(a,c),!0,lu())));return}}}}if(null!==a&&(g=new L(a),!g.b()&&(h=g.k.h(),g=g.k.j(),null!==h&&(k=h.Wi,h=h.mj,k instanceof z&&(l=k.z,k=k.p,l instanceof XE&&Pe(new E(l.Vx),this.hr)))))){lF(this.Dk,\nl.lf);this.Dk.dm(G(new H,new NE(k,h),g),b,c,d,e);return}if(null!==a&&(g=new L(a),!g.b()&&(g=g.k.h(),null!==g&&(g=g.Wi,g instanceof z)))){g=g.z;mQ(this.Dk,a,c,d,e);k=this.Fh;k instanceof HE?(fr(),a=We(Xe(),\"duplicated else in the if-then-else\"),c=t().d,a=G(new H,a,c),c=O().c,b.n(hr(0,new z(a,c),!0,lu()))):IE()===k?(b=gF(),this.Fh=cF(b,a.h(),a.j()),lF(this.Fh,g.lf)):this.Fh.dm(a,b,c,d,e);return}throw new w(a);};\nf.Op=function(a,b,c,d,e,g){var h=this.Dk.Op(a,b,c,d,e,g),k=this.Fh;if(k instanceof HE)a=0;else if(IE()===k)b=new HE(b),this.Fh=QE(b,a),a=1;else{if(!(k instanceof CE||k instanceof DE))throw new w(k);a=this.Fh.Op(a,b,c,d,e,g)}return h+a|0};f.H=function(){return\"IfThenElse\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.hr;case 1:return this.Dk;case 2:return this.Fh;default:return $K(W(),a)}};f.D=function(a){return a instanceof CE};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof CE){var b=this.hr,c=a.hr;if(null===b?null===c:b.i(c))if(b=this.Dk,c=a.Dk,null===b?null===c:b.i(c))return b=this.Fh,a=a.Fh,null===b?null===a:b.i(a)}return!1};f.$classData=q({Z_:0},!1,\"mlscript.ucs.MutCaseOf$IfThenElse\",{Z_:1,kJ:1,g:1,lJ:1,E:1,v:1,l:1});function DE(a,b,c){this.ni=this.fv=null;this.mo=a;this.mh=b;this.nj=c;iQ(this)}DE.prototype=new kQ;DE.prototype.constructor=DE;f=DE.prototype;\nf.jb=function(){var a=this.mh.K(),b=this.mo,c=WF(ve(),\"branch\",a,!0),d=this.nj;d=d.b()?\"no wildcard\":\"wildcard \\x3d \"+lQ(d.o());return\"Match(\"+b+\", \"+a+\" \"+c+\", \"+d+\")\"};f.or=function(){var a=this.mo,b=this.mh.Ja(new y(d=>d.oQ())),c=this.nj;c.b()?c=R():(c=c.o(),c=new L(c.or()));a=new DE(a,b,c);return QE(a,this.ni)};f.zt=function(a){for(var b=this.mh.m();b.s();)b.t().xt().zt(a);b=this.nj;b.b()||b.o().zt(a)};\nf.Bt=function(){for(var a=!0,b=this.mh.m();a&&b.s();)a=b.t().xt().Bt();return a?(a=this.nj,a.b()?!0:a.o().Bt()):!1};\nf.ky=function(a,b){a=b.U(a.n(this.mo));if(R()===a)no();else{if(a instanceof L)return a=a.k.tj(),!(new iy(a,new y(c=>{if(c instanceof fe){c=c.aa|0;for(var d=this.mh.m(),e=!1;!e&&d.s();)a:if(e=d.t(),e instanceof EE)e=!1;else{if(e instanceof FE){var g=e.Tj;if(null!==g&&(g=new L(g),!g.b()&&(g=g.k.h(),null!==g))){e=g.x===\"Tuple#\"+c;break a}}throw new w(e);}return e}if(c instanceof Ud){c=c.fa;d=this.mh.m();for(e=!1;!e&&d.s();)a:if(e=d.t(),e instanceof EE)e=Pe(new E(c),e.ir);else{if(e instanceof FE&&(g=\ne.Tj,null!==g&&(g=new L(g),!g.b()))){e=Pe(new E(c),g.k.h());break a}throw new w(e);}return e}throw new w(c);}),!0)).s();throw new w(a);}};\nf.dm=function(a,b,c,d,e){var g=Cc=>{if(Cc instanceof YE){var Fc=Cc.bv,qd=Cc.cv;if(!1===Cc.Ux){var Yb=!1;for(Cc=this.ni.m();!Yb&&Cc.s();){var Nc=Cc.t();a:{if(null!==Nc){Yb=Nc.fr;var ad=Nc.Sj;Nc=Nc.gr;if(aF()===Yb){Yb=Pe(new E(ad),Fc)&&Pe(new E(Nc),qd);break a}}Yb=!1}}Fc=Yb}else Fc=!1;if(Fc)return!1}return!0},h=a.h().Wi;a:for(var k;;)if(h.b()){k=u();break}else{var l=h.e(),m=h.f();if(!1===!!g(l))h=m;else for(var n=h,r=m;;){if(r.b())k=n;else{var v=r.e();if(!1!==!!g(v)){r=r.f();continue}for(var x=r,A=\nnew z(n.e(),u()),B=n.f(),C=A;B!==x;){var D=new z(B.e(),u());C=C.p=D;B=B.f()}for(var F=x.f(),I=F;!F.b();){var M=F.e();if(!1===!!g(M)){for(;I!==F;){var N=new z(I.e(),u());C=C.p=N;I=I.f()}I=F.f()}F=F.f()}I.b()||(C.p=I);k=A}break a}}var P=G(new H,new NE(k,a.h().mj),a.j()),T=!1,Y=null,Z=Vea(P.y,this.mo);a:if(t().d===Z)b:{var S=new L(P);if(!S.b()){var ea=S.k.h(),ia=S.k.j();if(null!==ea){var X=ea.Wi,sa=ea.mj;if(X instanceof z){var Ja=X.z,Xa=X.p;if(Ja instanceof WE){var Fa=Ja.dv,za=Ja.ay;if(Pe(new E(Ja.ev),\nthis.mo)){var Qa=new vl(\"Tuple#\"+Fa);c:{for(var Ma=this.mh.m();Ma.s();){var Ga=Ma.t();if(Ga.FF(Qa,e)){var ab=new L(Ga);break c}}ab=R()}c:{var Hb=t().d;var bc=null!==Hb&&Hb===ab?!0:ab instanceof L&&ab.k instanceof EE?!0:!1;if(bc){var yb=gF(),tb=cF(yb,new NE(Xa,sa),ia);lF(tb,Ja.lf);var eb=this.mh,kb=PE().vl(za),Rb=VE(new FE(G(new H,Qa,kb),tb),Ja.UP);eb.$(Rb)}else{if(ab instanceof L){var Gb=ab.k;if(Gb instanceof FE){lF(Gb.pl,Ja.lf);Y_(Gb,za);Gb.pl.dm(G(new H,new NE(Xa,sa),ia),b,c,d,e);break c}}throw new w(ab);\n}}break b}}}}}var vb=new L(P);if(!vb.b()){var Tb=vb.k.h(),Nb=vb.k.j();if(null!==Tb){var ic=Tb.Wi,Va=Tb.mj,cb=O().c;if(null===cb?null===ic:cb.i(ic)){var zb=this.Op(Va,Nb,b,c,d,e);if(Pe(new E(zb),0)){fr();var Ub=Ye(new Te(new Ue(J(new K,[\"Found a redundant else branch\"]))),u()),jb=Nb.A(),db=G(new H,Ub,jb),ub=O().c;b.n(hr(0,new z(db,ub),!0,lu()))}break b}}}var Aa=new L(P);if(Aa.b())throw new w(P);for(var va=Aa.k.h(),Ra=Aa.k.j(),rb=this.mh.m();rb.s();)mQ(rb.t().xt(),G(new H,va,Ra),c,d,e);var xb=this.nj;\nif(t().d===xb){t();var mc=gF(),Ha=cF(mc,va,Ra);this.nj=new L(Ha)}else if(xb instanceof L)xb.k.dm(G(new H,va,Ra),b,c,d,e);else throw new w(xb);}else{if(Z instanceof L){T=!0;Y=Z;var Ka=Y.k;if(null!==Ka){var Oa=new L(Ka);if(!Oa.b()){var Na=Oa.k.h(),Da=Oa.k.j();if(Na instanceof UE){var ta=Na.Xx,Ya=Na.WA,dc=this.mh.m(),ka=new iy(dc,new y(Cc=>Cc.FF(ta,e)),!1);if(ka.s())for(;ka.s();){var ya=ka.t();b:if(!(ya instanceof EE)){if(ya instanceof FE){var Sa=ya,xc=Sa.Tj;if(null!==xc){var Sb=new L(xc);if(!Sb.b()){var uc=\nSb.k.h();if(null!==uc){uc.x===ta.x?(lF(Sa.pl,Na.lf),Y_(Sa,Ya),Sa.pl.dm(G(new H,Da,P.w),b,c,d,e)):(lF(Sa.pl,Na.lf),Y_(Sa,Ya),Sa.pl.dm(P,b,c,d,e));break b}}}}throw new w(ya);}}else{var Lb=this.nj;b:{if(Lb instanceof L){var lc=Lb.k;if(!lc.Bt()){var Xb=lc.or(),ec=gF();Xb.zt(cF(ec,Da,P.w));lF(Xb,Na.lf);var Ab=this.mh,Ob=PE().vl(Ya),fb=VE(new FE(G(new H,ta,Ob),Xb),Na.tF);Ab.$(fb);break b}}if(Lb instanceof L||R()===Lb){var Wa=gF(),bb=cF(Wa,Da,P.w);lF(bb,Na.lf);var Ia=this.mh,Ua=PE().vl(Ya),pc=VE(new FE(G(new H,\nta,Ua),bb),Na.tF);Ia.$(pc)}else throw new w(Lb);}}break a}}}}if(T){var sc=Y.k;if(null!==sc){var Ba=new L(sc);if(!Ba.b()){var ob=Ba.k.h(),nc=Ba.k.j();if(ob instanceof OE){var Ib=ob.Zx;b:{for(var vc=this.mh.m();vc.s();){var Vb=vc.t();if(Vb.FF(Ib,e)){var fc=new L(Vb);break b}}fc=R()}b:{var Bc=t().d;var Pb=null!==Bc&&Bc===fc?!0:fc instanceof L&&fc.k instanceof FE?!0:!1;if(Pb){var Jb=gF(),gc=cF(Jb,nc,P.w);lF(gc,ob.lf);var Cb=this.mh,cc=VE(new EE(Ib,gc),ob.TP);Cb.$(cc)}else{if(fc instanceof L){var yc=fc.k;\nif(yc instanceof EE){lF(yc.Jp,ob.lf);yc.Jp.dm(G(new H,nc,P.w),b,c,d,e);break b}}throw new w(fc);}}break a}}}}if(T){var Mc=Y.k;if(null!==Mc){var qc=new L(Mc);if(!qc.b()){var oc=qc.k.j();if(qc.k.h()instanceof SE){for(var Qc=this.mh.m(),jc=new iy(Qc,new y(Cc=>Cc.xt().ky(c,d)),!0);jc.s();)mQ(jc.t().xt(),G(new H,oc,P.w),c,d,e);var sb=this.nj;if(t().d===sb){t();var Gc=gF(),Wb=cF(Gc,oc,P.w);this.nj=new L(Wb)}else if(sb instanceof L)sb.k.dm(G(new H,oc,P.w),b,c,d,e);else throw new w(sb);break a}}}}throw new w(Z);\n}};f.Op=function(a,b,c,d,e,g){var h=this.mh.m();h=new Ef(h,new y(l=>{if(l instanceof FE)return l.pl.Op(a,b,c,d,e,g);if(l instanceof EE)return l.Jp.Op(a,b,c,d,e,g);throw new w(l);}));g3||(g3=new h3);h=fda(h);var k=this.nj;if(t().d===k)t(),k=new HE(b),k=QE(k,a),this.nj=new L(k),k=1;else{if(!(k instanceof L))throw new w(k);k=k.k.Op(a,b,c,d,e,g)}return(h|0)+k|0};f.H=function(){return\"Match\"};f.G=function(){return 3};\nf.I=function(a){switch(a){case 0:return this.mo;case 1:return this.mh;case 2:return this.nj;default:return $K(W(),a)}};f.D=function(a){return a instanceof DE};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof DE){var b=this.mo,c=a.mo;if(null===b?null===c:b.i(c))if(b=this.mh,c=a.mh,null===b?null===c:i3(b,c))return b=this.nj,a=a.nj,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({$_:0},!1,\"mlscript.ucs.MutCaseOf$Match\",{$_:1,kJ:1,g:1,lJ:1,E:1,v:1,l:1});function j3(){this.ni=this.fv=null;iQ(this)}j3.prototype=new kQ;j3.prototype.constructor=j3;f=j3.prototype;f.jb=function(){return\"MissingCase\"};f.zt=function(){};f.Bt=function(){return!1};f.ky=function(){return!1};f.dm=function(){xm(\"`MissingCase` is a placeholder and cannot be merged\")};f.Op=function(){return 0};f.H=function(){return\"MissingCase\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};\nf.D=function(a){return a instanceof j3};f.B=function(){return-1279461994};f.u=function(){return\"MissingCase\"};f.or=function(){return IE()};f.$classData=q({a0:0},!1,\"mlscript.ucs.MutCaseOf$MissingCase$\",{a0:1,kJ:1,g:1,lJ:1,E:1,v:1,l:1});var k3;function IE(){k3||(k3=new j3);return k3}function l3(){}l3.prototype=new f0;l3.prototype.constructor=l3;f=l3.prototype;f.H=function(){return\"None\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof l3};f.B=function(){return 2433880};\nf.u=function(){return\"None\"};f.o=function(){throw AH(\"None.get\");};f.$classData=q({$2:0},!1,\"scala.None$\",{$2:1,b3:1,g:1,M:1,E:1,v:1,l:1});var m3;function R(){m3||(m3=new l3);return m3}function L(a){this.k=a}L.prototype=new f0;L.prototype.constructor=L;f=L.prototype;f.o=function(){return this.k};f.H=function(){return\"Some\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.k:$K(W(),a)};f.D=function(a){return a instanceof L};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof L?ml(nl(),this.k,a.k):!1};f.$classData=q({n3:0},!1,\"scala.Some\",{n3:1,b3:1,g:1,M:1,E:1,v:1,l:1});class NQ extends SZ{constructor(a,b){super();At(tp(),0<=b&&b<a.length);var c=b===(-1+a.length|0)?\"at terminal\":\"'\\\\\"+hc(a.charCodeAt(1+b|0))+\"' not one of [\\\\b, \\\\t, \\\\n, \\\\f, \\\\r, \\\\\\\\, \\\\\\\", \\\\', \\\\uxxxx] at\";yF(this,\"invalid escape \"+c+\" index \"+b+' in \"'+a+'\". Use \\\\\\\\ for literal \\\\.',null,!0)}}\nNQ.prototype.$classData=q({r3:0},!1,\"scala.StringContext$InvalidEscapeException\",{r3:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class OQ extends SZ{constructor(a,b){super();yF(this,\"invalid unicode escape at index \"+b+\" of \"+a,null,!0)}}OQ.prototype.$classData=q({s3:0},!1,\"scala.StringContext$InvalidUnicodeEscapeException\",{s3:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});function PQ(a,b){this.w=this.y=null;this.xF=a;this.nJ=b;G(this,null,null)}PQ.prototype=new h0;PQ.prototype.constructor=PQ;f=PQ.prototype;f.aQ=function(){return this.xF};\nf.Sc=function(){return this.nJ};f.Cw=function(){return new n3(this.nJ,this.xF)};f.iy=function(){return hc(this.xF)};f.j=function(){return this.nJ};f.h=function(){return hc(this.xF)};f.$classData=q({E0:0},!1,\"scala.Tuple2$mcCI$sp\",{E0:1,by:1,g:1,LB:1,E:1,v:1,l:1});function n3(a,b){this.w=this.y=null;this.yF=a;this.$P=b;G(this,null,null)}n3.prototype=new h0;n3.prototype.constructor=n3;f=n3.prototype;f.ut=function(){return this.yF};f.Cw=function(){return new PQ(this.$P,this.yF)};f.iy=function(){return this.yF};\nf.j=function(){return hc(this.$P)};f.h=function(){return this.yF};f.$classData=q({F0:0},!1,\"scala.Tuple2$mcIC$sp\",{F0:1,by:1,g:1,LB:1,E:1,v:1,l:1});function Yt(a,b){this.w=this.y=null;this.AF=a;this.pJ=b;G(this,null,null)}Yt.prototype=new h0;Yt.prototype.constructor=Yt;f=Yt.prototype;f.ut=function(){return this.AF};f.cy=function(){return this.pJ};f.Cw=function(){return new o3(this.pJ,this.AF)};f.iy=function(){return this.AF};f.j=function(){return this.pJ};f.h=function(){return this.AF};\nf.$classData=q({H0:0},!1,\"scala.Tuple2$mcIZ$sp\",{H0:1,by:1,g:1,LB:1,E:1,v:1,l:1});function o3(a,b){this.w=this.y=null;this.BF=a;this.qJ=b;G(this,null,null)}o3.prototype=new h0;o3.prototype.constructor=o3;f=o3.prototype;f.Rc=function(){return this.BF};f.Sc=function(){return this.qJ};f.Cw=function(){return new Yt(this.qJ,this.BF)};f.iy=function(){return this.BF};f.j=function(){return this.qJ};f.h=function(){return this.BF};\nf.$classData=q({I0:0},!1,\"scala.Tuple2$mcZI$sp\",{I0:1,by:1,g:1,LB:1,E:1,v:1,l:1});function p3(){}p3.prototype=new p;p3.prototype.constructor=p3;function q3(){}f=q3.prototype=p3.prototype;f.Ub=function(){return DK()};f.Ih=function(){return this.Oc()};f.Oc=function(){return\"Iterable\"};f.u=function(){return w0(this)};f.Gk=function(a){return this.Ub().Ib(a)};f.ti=function(){return this.Ub().Eb()};f.e=function(){return this.m().t()};f.Mc=function(){return yT(this)};f.$k=function(a){return iv(this,a)};\nf.Fk=function(a){return this.vc(new r3(this,a,!1))};f.BK=function(a){var b=new r3(this,a,!0);return G(new H,this.vc(new r3(this,a,!1)),this.vc(b))};f.Jc=function(a){return zT(this,a)};f.Bb=function(a){return this.vc(s3(new t3,this,a))};f.f=function(){return CT(this)};f.MJ=function(){if(this.b())throw DT();return this.Bb(1)};f.Ja=function(a){return FT(this,a)};f.tl=function(a){return IT(this,a)};f.Gb=function(a){return KT(this,a)};f.Ca=function(a){cH(this,a)};f.ul=function(a){return nw(this,a)};\nf.qo=function(a){return ey(this,a)};f.De=function(a,b){return mB(this,a,b)};f.mf=function(a,b){return Qu(this,a,b)};f.th=function(a){return eH(this,a)};f.b=function(){return!this.m().s()};f.ka=function(){return hs(this)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.FC=function(){return v1(EK(),this)};\nf.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.Q=function(){return-1};f.vc=function(a){return this.Gk(a)};function Du(a,b){a.tn=b;a.wc=0;a.Al=wG(xG(),a.tn);return a}function Eu(){this.tn=null;this.Al=this.wc=0}Eu.prototype=new BY;Eu.prototype.constructor=Eu;function u3(){}f=u3.prototype=Eu.prototype;f.Q=function(){return this.Al-this.wc|0};f.s=function(){return this.wc<this.Al};\nf.t=function(){try{var a=XG(xG(),this.tn,this.wc);this.wc=1+this.wc|0;return a}catch(b){if(b instanceof dI)return Rq().Pa.t();throw b;}};f.ph=function(a){if(0<a){a=this.wc+a|0;if(0>a)a=this.Al;else{var b=this.Al;a=b<a?b:a}this.wc=a}return this};f.$classData=q({Qp:0},!1,\"scala.collection.ArrayOps$ArrayIterator\",{Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function Kr(a,b){a.UK=b;a.Er=0;a.bk=b.K();return a}function Lr(){this.UK=null;this.bk=this.Er=0}Lr.prototype=new BY;Lr.prototype.constructor=Lr;\nfunction v3(){}f=v3.prototype=Lr.prototype;f.Q=function(){return this.bk};f.s=function(){return 0<this.bk};f.t=function(){if(0<this.bk){var a=this.UK.va(this.Er);this.Er=1+this.Er|0;this.bk=-1+this.bk|0;return a}return Rq().Pa.t()};f.ph=function(a){0<a&&(this.Er=this.Er+a|0,a=this.bk-a|0,this.bk=0>a?0:a);return this};f.qk=function(a,b){a=0>a?0:a>this.bk?this.bk:a;b=(0>b?0:b>this.bk?this.bk:b)-a|0;this.bk=0>b?0:b;this.Er=this.Er+a|0;return this};\nf.$classData=q({CR:0},!1,\"scala.collection.IndexedSeqView$IndexedSeqViewIterator\",{CR:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function uZ(a,b){a.VK=b;a.zj=b.K();a.Kv=-1+a.zj|0;return a}function vZ(){this.VK=null;this.Kv=this.zj=0}vZ.prototype=new BY;vZ.prototype.constructor=vZ;function w3(){}w3.prototype=vZ.prototype;vZ.prototype.s=function(){return 0<this.zj};vZ.prototype.t=function(){if(0<this.zj){var a=this.VK.va(this.Kv);this.Kv=-1+this.Kv|0;this.zj=-1+this.zj|0;return a}return Rq().Pa.t()};\nvZ.prototype.qk=function(a,b){0<this.zj&&(this.zj<=a?this.zj=0:0>=a?0<=b&&b<this.zj&&(this.zj=b):(this.Kv=this.Kv-a|0,this.zj=0<=b&&b<this.zj?b<=a?0:b-a|0:this.zj-a|0));return this};vZ.prototype.$classData=q({DR:0},!1,\"scala.collection.IndexedSeqView$IndexedSeqViewReverseIterator\",{DR:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function TT(){this.wC=null;this.wC=Rq().Pa}TT.prototype=new e2;TT.prototype.constructor=TT;function pfa(a,b){a.wC=a.wC.nb(new U(()=>{Rq();return new g0(b)}));return a}\nTT.prototype.$=function(a){return pfa(this,a)};TT.prototype.$classData=q({m5:0},!1,\"scala.collection.Iterator$$anon$21\",{m5:1,Vba:1,g:1,Po:1,xg:1,xf:1,wf:1});function Ex(a,b){this.JR=null;this.Ay=0;this.KR=this.$K=null;if(null===a)throw null;this.$K=a;this.KR=b;this.Ay=0}Ex.prototype=new BY;Ex.prototype.constructor=Ex;f=Ex.prototype;f.u=function(){return\"\\x3cfunction1\\x3e\"};f.n=function(){return fL()};\nf.s=function(){for(var a=fL();0===this.Ay;)if(this.$K.s()){var b=this.$K.t();b=this.KR.Ob(b,this);a!==b&&(this.JR=b,this.Ay=1)}else this.Ay=-1;return 1===this.Ay};f.t=function(){return this.s()?(this.Ay=0,this.JR):Rq().Pa.t()};f.$classData=q({q5:0},!1,\"scala.collection.Iterator$$anon$7\",{q5:1,Sa:1,g:1,Ka:1,M:1,N:1,la:1});function x3(a,b,c){a=a.U(b);if(a instanceof L)return a.k;if(R()===a)return Es(c);throw new w(a);}\nfunction HA(a,b){var c=a.U(b);if(R()===c)return a.IF(b);if(c instanceof L)return c.k;throw new w(c);}function y3(a,b,c){return a.Se(b,new U(()=>c.n(b)))}function z3(a){throw AH(\"key not found: \"+a);}function A3(a,b){var c=a.vj();a=Fs(b)?new JT(a,b):a.m().nb(new U(()=>b.m()));return c.Ib(a)}function B3(a,b,c,d,e){a=a.m();a=new Ef(a,new y(g=>{if(null!==g)return g.h()+\" -\\x3e \"+g.j();throw new w(g);}));return iH(a,b,c,d,e)}function C3(){this.Mt=null;this.Mt=uv()}C3.prototype=new L0;\nC3.prototype.constructor=C3;C3.prototype.$classData=q({e6:0},!1,\"scala.collection.SortedSet$\",{e6:1,Y5:1,V4:1,g:1,oG:1,l:1,dS:1});var D3;function E3(a,b){var c=a.ti(),d=Vn();for(a=a.m();a.s();){var e=a.t();d.oh(b.n(e))&&c.$(e)}return c.Kb()}function F3(a,b){var c=a.Ik().Eb();0<=a.Q()&&c.he(1+a.K()|0);c.$(b);c.zc(a);return c.Kb()}function Xq(a,b){var c=a.Ik().Eb();0<=a.Q()&&c.he(1+a.K()|0);c.zc(a);c.$(b);return c.Kb()}function G3(a,b){var c=a.Ik().Eb();c.zc(a);c.zc(b);return c.Kb()}\nfunction H3(){this.FL=this.iS=null;this.EL=!1;I3=this;this.FL=new i0(this)}H3.prototype=new p;H3.prototype.constructor=H3;function J3(a,b){return a instanceof K3?a:KQ(0,rQ(SG(),a,b))}f=H3.prototype;f.sy=function(a){var b=new DF;return new dU(b,new y(c=>KQ(JQ(),kB(c,a))))};\nfunction KQ(a,b){if(null===b)return null;if(b instanceof zc)return new Fu(b);if(b instanceof Xc)return new L3(b);if(b instanceof ed)return new M3(b);if(b instanceof Zc)return new N3(b);if(b instanceof $c)return new O3(b);if(b instanceof Ic)return new P3(b);if(b instanceof Pc)return new Q3(b);if(b instanceof Sc)return new R3(b);if(b instanceof Ec)return new S3(b);if(ph(b))return new T3(b);throw new w(b);}f.GB=function(a){return this.sy(a)};f.pr=function(a,b){return J3(a,b)};\nf.ng=function(){this.EL||this.EL||(this.iS=new Fu(new zc(0)),this.EL=!0);return this.iS};f.$classData=q({G6:0},!1,\"scala.collection.immutable.ArraySeq$\",{G6:1,g:1,f6:1,T4:1,S4:1,oG:1,l:1});var I3;function JQ(){I3||(I3=new H3);return I3}function ZJ(a){return!!(a&&a.$classData&&a.$classData.rb.xc)}function U3(a){this.Yp=0;this.Vt=null;$0(this,a)}U3.prototype=new b1;U3.prototype.constructor=U3;U3.prototype.wj=function(a,b){return G(new H,a,b)};\nU3.prototype.$classData=q({y7:0},!1,\"scala.collection.immutable.Map$Map2$$anon$1\",{y7:1,qS:1,Sa:1,g:1,Ka:1,M:1,N:1});function V3(a){this.Yp=0;this.Vt=null;$0(this,a)}V3.prototype=new b1;V3.prototype.constructor=V3;V3.prototype.wj=function(a){return a};V3.prototype.$classData=q({z7:0},!1,\"scala.collection.immutable.Map$Map2$$anon$2\",{z7:1,qS:1,Sa:1,g:1,Ka:1,M:1,N:1});function W3(a){this.Yp=0;this.Vt=null;$0(this,a)}W3.prototype=new b1;W3.prototype.constructor=W3;W3.prototype.wj=function(a,b){return b};\nW3.prototype.$classData=q({A7:0},!1,\"scala.collection.immutable.Map$Map2$$anon$3\",{A7:1,qS:1,Sa:1,g:1,Ka:1,M:1,N:1});function X3(a){this.$p=0;this.Zp=null;c1(this,a)}X3.prototype=new e1;X3.prototype.constructor=X3;X3.prototype.wj=function(a,b){return G(new H,a,b)};X3.prototype.$classData=q({C7:0},!1,\"scala.collection.immutable.Map$Map3$$anon$4\",{C7:1,rS:1,Sa:1,g:1,Ka:1,M:1,N:1});function Y3(a){this.$p=0;this.Zp=null;c1(this,a)}Y3.prototype=new e1;Y3.prototype.constructor=Y3;Y3.prototype.wj=function(a){return a};\nY3.prototype.$classData=q({D7:0},!1,\"scala.collection.immutable.Map$Map3$$anon$5\",{D7:1,rS:1,Sa:1,g:1,Ka:1,M:1,N:1});function Z3(a){this.$p=0;this.Zp=null;c1(this,a)}Z3.prototype=new e1;Z3.prototype.constructor=Z3;Z3.prototype.wj=function(a,b){return b};Z3.prototype.$classData=q({E7:0},!1,\"scala.collection.immutable.Map$Map3$$anon$6\",{E7:1,rS:1,Sa:1,g:1,Ka:1,M:1,N:1});function $3(a){this.aq=0;this.zn=null;f1(this,a)}$3.prototype=new h1;$3.prototype.constructor=$3;\n$3.prototype.wj=function(a,b){return G(new H,a,b)};$3.prototype.$classData=q({G7:0},!1,\"scala.collection.immutable.Map$Map4$$anon$7\",{G7:1,sS:1,Sa:1,g:1,Ka:1,M:1,N:1});function a4(a){this.aq=0;this.zn=null;f1(this,a)}a4.prototype=new h1;a4.prototype.constructor=a4;a4.prototype.wj=function(a){return a};a4.prototype.$classData=q({H7:0},!1,\"scala.collection.immutable.Map$Map4$$anon$8\",{H7:1,sS:1,Sa:1,g:1,Ka:1,M:1,N:1});function b4(a){this.aq=0;this.zn=null;f1(this,a)}b4.prototype=new h1;\nb4.prototype.constructor=b4;b4.prototype.wj=function(a,b){return b};b4.prototype.$classData=q({I7:0},!1,\"scala.collection.immutable.Map$Map4$$anon$9\",{I7:1,sS:1,Sa:1,g:1,Ka:1,M:1,N:1});function hE(a,b,c,d){this.nC=b;this.Wy=c;this.fw=!d;this.Vy=a}hE.prototype=new BY;hE.prototype.constructor=hE;f=hE.prototype;f.Q=function(){return this.fw?1+pb(this.Wy-this.Vy|0,this.nC)|0:0};f.s=function(){return this.fw};function c4(a){a.fw||Rq().Pa.t();var b=a.Vy;a.fw=b!==a.Wy;a.Vy=b+a.nC|0;return b}\nf.ph=function(a){if(0<a){var b=this.Vy,c=b>>31;a=Math.imul(this.nC,a);var d=a>>31;a=b+a|0;b=(-2147483648^a)<(-2147483648^b)?1+(c+d|0)|0:c+d|0;0<this.nC?(c=this.Wy,d=c>>31,this.Vy=(d===b?(-2147483648^c)<(-2147483648^a):d<b)?c:a,c=this.Wy,d=c>>31,this.fw=b===d?(-2147483648^a)<=(-2147483648^c):b<d):0>this.nC&&(c=this.Wy,d=c>>31,this.Vy=(d===b?(-2147483648^c)>(-2147483648^a):d>b)?c:a,c=this.Wy,d=c>>31,this.fw=b===d?(-2147483648^a)>=(-2147483648^c):b>d)}return this};f.t=function(){return c4(this)};\nf.$classData=q({$7:0},!1,\"scala.collection.immutable.RangeIterator\",{$7:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function d4(a,b,c){this.Cn=this.hw=this.Xy=null;this.Wd=0;this.Hc=null;q1(this,a,b,c)}d4.prototype=new t1;d4.prototype.constructor=d4;d4.prototype.yK=function(a){return G(new H,a.Wa,a.Wb)};d4.prototype.$classData=q({b8:0},!1,\"scala.collection.immutable.RedBlackTree$EntriesIterator\",{b8:1,zS:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction e4(a,b){this.Cn=this.hw=this.Xy=null;this.Wd=0;this.Hc=null;q1(this,a,R(),b)}e4.prototype=new t1;e4.prototype.constructor=e4;e4.prototype.yK=function(){no()};e4.prototype.$classData=q({c8:0},!1,\"scala.collection.immutable.RedBlackTree$EqualsIterator\",{c8:1,zS:1,Sa:1,g:1,Ka:1,M:1,N:1});function f4(a,b,c){this.Cn=this.hw=this.Xy=null;this.Wd=0;this.Hc=null;q1(this,a,b,c)}f4.prototype=new t1;f4.prototype.constructor=f4;f4.prototype.yK=function(a){return a.Wa};\nf4.prototype.$classData=q({d8:0},!1,\"scala.collection.immutable.RedBlackTree$KeysIterator\",{d8:1,zS:1,Sa:1,g:1,Ka:1,M:1,N:1});function g4(){this.Dn=this.Io=0}g4.prototype=new BY;g4.prototype.constructor=g4;function h4(){}h4.prototype=g4.prototype;g4.prototype.Q=function(){return this.Dn};g4.prototype.s=function(){return 0<this.Dn};g4.prototype.t=function(){if(this.s()){var a=this.va(this.Io);this.Io=1+this.Io|0;this.Dn=-1+this.Dn|0;return a}return Rq().Pa.t()};\ng4.prototype.ph=function(a){0<a&&(this.Io=this.Io+a|0,a=this.Dn-a|0,this.Dn=0>a?0:a);return this};function i4(){this.Mt=null;this.Mt=zZ()}i4.prototype=new L0;i4.prototype.constructor=i4;function oA(a,b,c){if(b&&b.$classData&&b.$classData.rb.OL){O();var d=b.se();if(null===c?null===d:c.i(d))return b}return tT.prototype.pr.call(a,b,c)}i4.prototype.pr=function(a,b){return oA(this,a,b)};i4.prototype.$classData=q({C8:0},!1,\"scala.collection.immutable.SortedSet$\",{C8:1,Y5:1,V4:1,g:1,oG:1,l:1,dS:1});var j4;\nfunction uv(){j4||(j4=new i4);return j4}function k4(){}k4.prototype=new p;k4.prototype.constructor=k4;function l4(){}l4.prototype=k4.prototype;k4.prototype.he=function(){};function m4(){this.SL=this.TL=null;n4=this;this.TL=new i0(this);this.SL=new zQ(new zc(0))}m4.prototype=new p;m4.prototype.constructor=m4;f=m4.prototype;f.sy=function(a){a=new o4(a.uh());return new dU(a,new y(b=>p4(yQ(),b)))};\nfunction p4(a,b){if(null===b)return null;if(b instanceof zc)return new zQ(b);if(b instanceof Xc)return new q4(b);if(b instanceof ed)return new r4(b);if(b instanceof Zc)return new s4(b);if(b instanceof $c)return new t4(b);if(b instanceof Ic)return new AQ(b);if(b instanceof Pc)return new u4(b);if(b instanceof Sc)return new v4(b);if(b instanceof Ec)return new w4(b);if(ph(b))return new x4(b);throw new w(b);}f.GB=function(a){return this.sy(a)};f.pr=function(a,b){return p4(0,rQ(SG(),a,b))};f.ng=function(){return this.SL};\nf.$classData=q({j9:0},!1,\"scala.collection.mutable.ArraySeq$\",{j9:1,g:1,f6:1,T4:1,S4:1,oG:1,l:1});var n4;function yQ(){n4||(n4=new m4);return n4}function y4(a){this.hq=0;this.Lo=null;this.vw=0;this.uw=null;Y1(this,a)}y4.prototype=new $1;y4.prototype.constructor=y4;y4.prototype.lB=function(a){return G(new H,a.Wk,a.Ah)};y4.prototype.$classData=q({G9:0},!1,\"scala.collection.mutable.HashMap$$anon$1\",{G9:1,fH:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction z4(a){this.hq=0;this.Lo=null;this.vw=0;this.uw=null;Y1(this,a)}z4.prototype=new $1;z4.prototype.constructor=z4;z4.prototype.lB=function(a){return a.Wk};z4.prototype.$classData=q({H9:0},!1,\"scala.collection.mutable.HashMap$$anon$2\",{H9:1,fH:1,Sa:1,g:1,Ka:1,M:1,N:1});function A4(a){this.hq=0;this.Lo=null;this.vw=0;this.uw=null;Y1(this,a)}A4.prototype=new $1;A4.prototype.constructor=A4;A4.prototype.lB=function(a){return a.Ah};\nA4.prototype.$classData=q({I9:0},!1,\"scala.collection.mutable.HashMap$$anon$3\",{I9:1,fH:1,Sa:1,g:1,Ka:1,M:1,N:1});function B4(a){this.hq=0;this.Lo=null;this.vw=0;this.uw=null;Y1(this,a)}B4.prototype=new $1;B4.prototype.constructor=B4;B4.prototype.lB=function(a){return a};B4.prototype.$classData=q({J9:0},!1,\"scala.collection.mutable.HashMap$$anon$4\",{J9:1,fH:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction C4(a){this.hq=0;this.Lo=null;this.vw=0;this.uw=null;this.WL=0;if(null===a)throw null;Y1(this,a);this.WL=0}C4.prototype=new $1;C4.prototype.constructor=C4;C4.prototype.B=function(){return this.WL};C4.prototype.lB=function(a){var b=BL(),c=a.mk;a=a.Ah;this.WL=pS(b,c^(c>>>16|0),My(W(),a));return this};C4.prototype.$classData=q({K9:0},!1,\"scala.collection.mutable.HashMap$$anon$5\",{K9:1,fH:1,Sa:1,g:1,Ka:1,M:1,N:1});function D4(a){this.iu=0;this.Ur=null;this.vC=0;this.uC=null;a2(this,a)}\nD4.prototype=new c2;D4.prototype.constructor=D4;D4.prototype.DJ=function(a){return a.xm};D4.prototype.$classData=q({P9:0},!1,\"scala.collection.mutable.HashSet$$anon$1\",{P9:1,RS:1,Sa:1,g:1,Ka:1,M:1,N:1});function E4(a){this.iu=0;this.Ur=null;this.vC=0;this.uC=null;a2(this,a)}E4.prototype=new c2;E4.prototype.constructor=E4;E4.prototype.DJ=function(a){return a};E4.prototype.$classData=q({Q9:0},!1,\"scala.collection.mutable.HashSet$$anon$2\",{Q9:1,RS:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction F4(a){this.iu=0;this.Ur=null;this.vC=0;this.uC=null;this.XL=0;if(null===a)throw null;a2(this,a);this.XL=0}F4.prototype=new c2;F4.prototype.constructor=F4;F4.prototype.B=function(){return this.XL};F4.prototype.DJ=function(a){this.XL=G4(a.nk);return this};F4.prototype.$classData=q({R9:0},!1,\"scala.collection.mutable.HashSet$$anon$3\",{R9:1,RS:1,Sa:1,g:1,Ka:1,M:1,N:1});function H4(a,b,c,d){this.iq=this.DC=this.fz=null;r2(this,a,b,c,d)}H4.prototype=new t2;H4.prototype.constructor=H4;\nH4.prototype.zK=function(a){return G(new H,a.Oo,a.Vr)};H4.prototype.$classData=q({u$:0},!1,\"scala.collection.mutable.RedBlackTree$EntriesIterator\",{u$:1,iT:1,Sa:1,g:1,Ka:1,M:1,N:1});function I4(a,b,c,d){this.iq=this.DC=this.fz=null;r2(this,a,b,c,d)}I4.prototype=new t2;I4.prototype.constructor=I4;I4.prototype.zK=function(a){return a.Oo};I4.prototype.$classData=q({v$:0},!1,\"scala.collection.mutable.RedBlackTree$KeysIterator\",{v$:1,iT:1,Sa:1,g:1,Ka:1,M:1,N:1});\nfunction J4(a,b,c,d){this.iq=this.DC=this.fz=null;r2(this,a,b,c,d)}J4.prototype=new t2;J4.prototype.constructor=J4;J4.prototype.zK=function(a){return a.Vr};J4.prototype.$classData=q({y$:0},!1,\"scala.collection.mutable.RedBlackTree$ValuesIterator\",{y$:1,iT:1,Sa:1,g:1,Ka:1,M:1,N:1});function Uu(a,b){this.z3=b}Uu.prototype=new p;Uu.prototype.constructor=Uu;f=Uu.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};\nf.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){return oa(this.z3.n(a),b)};f.$classData=q({y3:0},!1,\"scala.math.LowPriorityOrderingImplicits$$anon$2\",{y3:1,g:1,lm:1,Ji:1,mm:1,km:1,l:1});function RY(a,b){this.MK=this.rR=null;if(null===a)throw null;this.rR=a;this.MK=b}RY.prototype=new p;RY.prototype.constructor=RY;f=RY.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};\nf.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){return this.rR.Da(this.MK.n(a),this.MK.n(b))};f.$classData=q({F3:0},!1,\"scala.math.Ordering$$anon$1\",{F3:1,g:1,lm:1,Ji:1,mm:1,km:1,l:1});function OD(a,b){this.iG=a;this.It=b}OD.prototype=new p;OD.prototype.constructor=OD;f=OD.prototype;\nf.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){return this.iG.Da(this.It.n(a),this.It.n(b))};f.Xj=function(a,b){return this.iG.Xj(this.It.n(a),this.It.n(b))};f.Yj=function(a,b){return this.iG.Yj(this.It.n(a),this.It.n(b))};f.uj=function(a,b){return this.iG.uj(this.It.n(a),this.It.n(b))};\nf.$classData=q({G3:0},!1,\"scala.math.Ordering$$anon$5\",{G3:1,g:1,lm:1,Ji:1,mm:1,km:1,l:1});function B2(a){this.sn=a}B2.prototype=new p;B2.prototype.constructor=B2;f=B2.prototype;f.sj=function(a){var b=this.sn;return null===a?null===b:a.i(b)};f.Da=function(a,b){return this.sn.Da(b,a)};f.uj=function(a,b){return this.sn.uj(b,a)};f.Yj=function(a,b){return this.sn.Yj(b,a)};f.Xj=function(a,b){return this.sn.Xj(b,a)};f.Yi=function(a,b){return this.sn.Yi(b,a)};f.Jk=function(a,b){return this.sn.Kk(a,b)};\nf.Kk=function(a,b){return this.sn.Jk(a,b)};f.i=function(a){if(null!==a&&this===a)return!0;if(a instanceof B2){var b=this.sn;a=a.sn;return null===b?null===a:b.i(a)}return!1};f.B=function(){return Math.imul(41,this.sn.B())};f.$classData=q({N3:0},!1,\"scala.math.Ordering$Reverse\",{N3:1,g:1,lm:1,Ji:1,mm:1,km:1,l:1});function eT(a,b){this.jG=a;this.kG=b}eT.prototype=new p;eT.prototype.constructor=eT;f=eT.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};\nf.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.i=function(a){if(null!==a&&this===a)return!0;if(a instanceof eT){var b=this.jG,c=a.jG;if(null===b?null===c:b.i(c))return b=this.kG,a=a.kG,null===b?null===a:b.i(a)}return!1};\nf.B=function(){var a=this.jG,b=this.kG,c=BL();var d=c.C(-889275714,lb(\"Tuple2\"));for(var e=0;2>e;){var g=e;switch(g){case 0:g=a;break;case 1:g=b;break;default:throw aL(new bL,g+\" is out of bounds (min 0, max 1)\");}d=c.C(d,My(W(),g));e=1+e|0}return c.Ma(d,2)};f.Da=function(a,b){var c=this.jG.Da(a.h(),b.h());return 0!==c?c:this.kG.Da(a.j(),b.j())};f.$classData=q({Q3:0},!1,\"scala.math.Ordering$Tuple2Ordering\",{Q3:1,g:1,lm:1,Ji:1,mm:1,km:1,l:1});function jB(a){this.lG=a}jB.prototype=new p;\njB.prototype.constructor=jB;f=jB.prototype;f.D=function(a){return!!(a&&a.$classData&&a.$classData.rb.Lk)};f.i=function(a){if(a&&a.$classData&&a.$classData.rb.Lk){var b=this.uh();a=a.uh();b=b===a}else b=!1;return b};f.B=function(){var a=this.lG;return My(W(),a)};f.u=function(){return nfa(this,this.lG)};f.uh=function(){return this.lG};f.si=function(a){var b=this.lG;return rh(th(),b,a)};f.$classData=q({V3:0},!1,\"scala.reflect.ClassTag$GenericClassTag\",{V3:1,g:1,Lk:1,nm:1,pm:1,l:1,v:1});\nfunction K4(){}K4.prototype=new RZ;K4.prototype.constructor=K4;function L4(){}L4.prototype=K4.prototype;K4.prototype.uJ=function(a){a=null===a?\"null\":nb(a);ff(this,null===a?\"null\":a)};class GM extends N2{constructor(a){super();this.K1=a;yF(this,null,null,!0);if(null===a)throw le();}qj(){return\"Flags \\x3d '\"+this.K1+\"'\"}}GM.prototype.$classData=q({J1:0},!1,\"java.util.DuplicateFormatFlagsException\",{J1:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});\nclass IW extends N2{constructor(a,b){super();this.N1=a;this.M1=b;yF(this,null,null,!0);if(null===a)throw le();}qj(){return\"Conversion \\x3d \"+hc(this.M1)+\", Flags \\x3d \"+this.N1}}IW.prototype.$classData=q({L1:0},!1,\"java.util.FormatFlagsConversionMismatchException\",{L1:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class OM extends N2{constructor(a){super();this.d2=a;yF(this,null,null,!0)}qj(){return this.d2}}\nOM.prototype.$classData=q({c2:0},!1,\"java.util.IllegalFormatArgumentIndexException\",{c2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class SM extends N2{constructor(a){super();this.f2=a;yF(this,null,null,!0)}qj(){return\"Code point \\x3d 0x\"+(+(this.f2>>>0)).toString(16)}}SM.prototype.$classData=q({e2:0},!1,\"java.util.IllegalFormatCodePointException\",{e2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});\nclass JW extends N2{constructor(a,b){super();this.i2=a;this.h2=b;yF(this,null,null,!0);if(null===b)throw le();}qj(){return String.fromCharCode(this.i2)+\" !\\x3d \"+this.h2.qi.name}}JW.prototype.$classData=q({g2:0},!1,\"java.util.IllegalFormatConversionException\",{g2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class HW extends N2{constructor(a){super();this.k2=a;yF(this,null,null,!0);if(null===a)throw le();}qj(){return\"Flags \\x3d '\"+this.k2+\"'\"}}\nHW.prototype.$classData=q({j2:0},!1,\"java.util.IllegalFormatFlagsException\",{j2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class GW extends N2{constructor(a){super();this.m2=a;yF(this,null,null,!0)}qj(){return\"\"+this.m2}}GW.prototype.$classData=q({l2:0},!1,\"java.util.IllegalFormatPrecisionException\",{l2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class IM extends N2{constructor(a){super();this.o2=a;yF(this,null,null,!0)}qj(){return\"\"+this.o2}}\nIM.prototype.$classData=q({n2:0},!1,\"java.util.IllegalFormatWidthException\",{n2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class PM extends N2{constructor(a){super();this.r2=a;yF(this,null,null,!0);if(null===a)throw le();}qj(){return\"Format specifier '\"+this.r2+\"'\"}}PM.prototype.$classData=q({q2:0},!1,\"java.util.MissingFormatArgumentException\",{q2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});\nclass LM extends N2{constructor(a){super();this.t2=a;yF(this,null,null,!0);if(null===a)throw le();}qj(){return this.t2}}LM.prototype.$classData=q({s2:0},!1,\"java.util.MissingFormatWidthException\",{s2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});class FW extends N2{constructor(a){super();this.x2=a;yF(this,null,null,!0);if(null===a)throw le();}qj(){return\"Conversion \\x3d '\"+this.x2+\"'\"}}FW.prototype.$classData=q({w2:0},!1,\"java.util.UnknownFormatConversionException\",{w2:1,Np:1,ak:1,Te:1,qd:1,pc:1,g:1,l:1});\nfunction M4(){this.ld=\"type alias\"}M4.prototype=new XS;M4.prototype.constructor=M4;f=M4.prototype;f.H=function(){return\"Als\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof M4};f.B=function(){return 65928};f.u=function(){return\"Als\"};f.$classData=q({OT:0},!1,\"mlscript.Als$\",{OT:1,EE:1,sz:1,sx:1,g:1,E:1,v:1,l:1});var N4;function Ap(){N4||(N4=new M4);return N4}\nfunction um(a,b,c){this.mz=null;this.oz=this.pz=0;this.qz=this.nz=null;this.Rn=0;this.Xo=a;this.Tn=b;this.Un=c;Nq(this)}um.prototype=new AS;um.prototype.constructor=um;f=um.prototype;f.H=function(){return\"Case\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.Xo;case 1:return this.Tn;case 2:return this.Un;default:return $K(W(),a)}};f.D=function(a){return a instanceof um};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof um){var b=this.Xo,c=a.Xo;if(null===b?null===c:b.i(c))if(b=this.Tn,c=a.Tn,null===b?null===c:b.i(c))return b=this.Un,a=a.Un,null===b?null===a:b.i(a)}return!1};f.$classData=q({mU:0},!1,\"mlscript.Case\",{mU:1,yM:1,g:1,zM:1,Ta:1,E:1,v:1,l:1});function zP(a){a.Jw||(a.Kw=Faa(a),a.Jw=!0);return a.Kw}\nfunction cl(){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Yo=!1;this.Kw=null;this.Jw=!1}cl.prototype=new M_;cl.prototype.constructor=cl;function O4(){}O4.prototype=cl.prototype;function fP(){this.SC=this.RC=null;this.UC=this.VC=0;this.WC=this.TC=null;this.cl=0}fP.prototype=new p;fP.prototype.constructor=fP;function P4(){}f=P4.prototype=fP.prototype;\nf.jb=function(){if(this instanceof No)var a=\"definition\";else if(this instanceof Oo)a=\"type declaration\";else throw new w(this);return a};f.Vj=function(){return eP(this)};f.Wr=function(){return Mx(this)};f.nv=function(){0===(1&this.cl)<<24>>24&&0===(1&this.cl)<<24>>24&&(this.RC=cP(this),this.cl=(1|this.cl)<<24>>24);return this.RC};f.jn=function(){0===(2&this.cl)<<24>>24&&0===(2&this.cl)<<24>>24&&(this.SC=zq(this),this.cl=(2|this.cl)<<24>>24);return this.SC};f.rn=function(){return this.VC};\nf.fm=function(a){this.VC=a};f.qn=function(){return this.UC};f.em=function(a){this.UC=a};f.pn=function(){return this.TC};f.on=function(a){this.TC=a};f.A=function(){0===(4&this.cl)<<24>>24&&0===(4&this.cl)<<24>>24&&(this.WC=Dq(this),this.cl=(4|this.cl)<<24>>24);return this.WC};\nclass Ff extends Df{constructor(a,b,c){super();this.YC=b;this.wH=c;this.pq=a;yF(this,a,null,!0)}vt(){return this.YC}H(){return\"ErrorReport\"}G(){return 3}I(a){switch(a){case 0:return this.pq;case 1:return this.YC;case 2:return this.wH;default:return $K(W(),a)}}D(a){return a instanceof Ff}B(){return AL(this)}i(a){if(this===a)return!0;if(a instanceof Ff&&this.pq===a.pq){var b=this.YC,c=a.YC;return(null===b?null===c:b.i(c))?this.wH===a.wH:!1}return!1}}\nFf.prototype.$classData=q({OU:0},!1,\"mlscript.ErrorReport\",{OU:1,IU:1,qd:1,pc:1,g:1,l:1,E:1,v:1});function $t(a){this.rs=null;this.ts=this.us=0;this.vs=this.ss=null;this.dl=0;this.ap=a;Nq(this)}$t.prototype=new CS;$t.prototype.constructor=$t;f=$t.prototype;f.H=function(){return\"IfBlock\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.ap:$K(W(),a)};f.D=function(a){return a instanceof $t};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof $t){var b=this.ap;a=a.ap;return null===b?null===a:b.i(a)}return!1};f.$classData=q({$U:0},!1,\"mlscript.IfBlock\",{$U:1,uz:1,g:1,vz:1,Ta:1,E:1,v:1,l:1});function gu(a){this.rs=null;this.ts=this.us=0;this.vs=this.ss=null;this.dl=0;this.ws=a;Nq(this)}gu.prototype=new CS;gu.prototype.constructor=gu;f=gu.prototype;f.H=function(){return\"IfElse\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.ws:$K(W(),a)};\nf.D=function(a){return a instanceof gu};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof gu){var b=this.ws;a=a.ws;return null===b?null===a:b.i(a)}return!1};f.$classData=q({aV:0},!1,\"mlscript.IfElse\",{aV:1,uz:1,g:1,vz:1,Ta:1,E:1,v:1,l:1});function Ss(a,b,c,d){this.rs=null;this.ts=this.us=0;this.vs=this.ss=null;this.dl=0;this.Qw=a;this.xu=b;this.yu=c;this.wu=d;Nq(this)}Ss.prototype=new CS;Ss.prototype.constructor=Ss;f=Ss.prototype;\nf.H=function(){return\"IfLet\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.Qw;case 1:return this.xu;case 2:return this.yu;case 3:return this.wu;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ss};f.B=function(){var a=lb(\"IfLet\");a=W().C(-889275714,a);var b=this.Qw?1231:1237;a=W().C(a,b);b=this.xu;b=My(W(),b);a=W().C(a,b);b=this.yu;b=My(W(),b);a=W().C(a,b);b=this.wu;b=My(W(),b);a=W().C(a,b);return W().Ma(a,4)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Ss){if(this.Qw===a.Qw){var b=this.xu,c=a.xu;b=null===b?null===c:b.i(c)}else b=!1;if(b&&(b=this.yu,c=a.yu,null===b?null===c:b.i(c)))return b=this.wu,a=a.wu,null===b?null===a:b.i(a)}return!1};f.$classData=q({bV:0},!1,\"mlscript.IfLet\",{bV:1,uz:1,g:1,vz:1,Ta:1,E:1,v:1,l:1});function Tt(a,b,c){this.rs=null;this.ts=this.us=0;this.vs=this.ss=null;this.dl=0;this.Wn=a;this.Xn=b;this.Yn=c;Nq(this)}Tt.prototype=new CS;Tt.prototype.constructor=Tt;f=Tt.prototype;\nf.H=function(){return\"IfOpApp\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.Wn;case 1:return this.Xn;case 2:return this.Yn;default:return $K(W(),a)}};f.D=function(a){return a instanceof Tt};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Tt){var b=this.Wn,c=a.Wn;if(null===b?null===c:b.i(c))if(b=this.Xn,c=a.Xn,null===b?null===c:b.i(c))return b=this.Yn,a=a.Yn,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({cV:0},!1,\"mlscript.IfOpApp\",{cV:1,uz:1,g:1,vz:1,Ta:1,E:1,v:1,l:1});function mu(a,b){this.rs=null;this.ts=this.us=0;this.vs=this.ss=null;this.dl=0;this.xs=a;this.ys=b;Nq(this)}mu.prototype=new CS;mu.prototype.constructor=mu;f=mu.prototype;f.H=function(){return\"IfOpsApp\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.xs;case 1:return this.ys;default:return $K(W(),a)}};f.D=function(a){return a instanceof mu};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof mu){var b=this.xs,c=a.xs;if(null===b?null===c:b.i(c))return b=this.ys,a=a.ys,null===b?null===a:b.i(a)}return!1};f.$classData=q({dV:0},!1,\"mlscript.IfOpsApp\",{dV:1,uz:1,g:1,vz:1,Ta:1,E:1,v:1,l:1});function Ut(a,b){this.rs=null;this.ts=this.us=0;this.vs=this.ss=null;this.dl=0;this.Km=a;this.Lm=b;Nq(this)}Ut.prototype=new CS;Ut.prototype.constructor=Ut;f=Ut.prototype;f.H=function(){return\"IfThen\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.Km;case 1:return this.Lm;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ut};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Ut){var b=this.Km,c=a.Km;if(null===b?null===c:b.i(c))return b=this.Lm,a=a.Lm,null===b?null===a:b.i(a)}return!1};f.$classData=q({eV:0},!1,\"mlscript.IfThen\",{eV:1,uz:1,g:1,vz:1,Ta:1,E:1,v:1,l:1});function wn(a,b){this.nD=a;this.mD=b}wn.prototype=new ES;\nwn.prototype.constructor=wn;f=wn.prototype;f.xa=function(){var a=Sp(Qp(),\"get \"+zl(Al(),this.nD)+\"() \"),b=this.mD;if(b instanceof fe)b=b.aa,b=(new Io((t(),new L(b)))).xa();else{if(!(b instanceof Ud))throw new w(b);b=b.fa;for(var c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,d.xa());b=b.f()}b=c}return Rp(a,Oz(b))};f.H=function(){return\"JSClassGetter\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.nD;case 1:return this.mD;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof wn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof wn&&this.nD===a.nD){var b=this.mD;a=a.mD;return null===b?null===a:b.i(a)}return!1};f.$classData=q({EV:0},!1,\"mlscript.JSClassGetter\",{EV:1,FV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function vn(a,b,c){this.pD=a;this.qD=b;this.oD=c}vn.prototype=new ES;vn.prototype.constructor=vn;f=vn.prototype;\nf.xa=function(){var a=Rp(Rp(Sp(Qp(),zl(Al(),this.pD)),Op(Lp(),this.qD)),Qp().bA),b=this.oD;if(b instanceof fe)b=b.aa,b=(new Io((t(),new L(b)))).xa();else{if(!(b instanceof Ud))throw new w(b);b=b.fa;for(var c=Qp().ye;!b.b();){var d=b.e();c=Iz(c,d.xa());b=b.f()}b=c}return Rp(a,Oz(b))};f.H=function(){return\"JSClassMethod\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.pD;case 1:return this.qD;case 2:return this.oD;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof vn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof vn&&this.pD===a.pD){var b=this.qD,c=a.qD;if(null===b?null===c:b.i(c))return b=this.oD,a=a.oD,null===b?null===a:b.i(a)}return!1};f.$classData=q({GV:0},!1,\"mlscript.JSClassMethod\",{GV:1,FV:1,el:1,Xc:1,g:1,E:1,v:1,l:1});function Q4(){this.ld=\"mixin\"}Q4.prototype=new XS;Q4.prototype.constructor=Q4;f=Q4.prototype;f.H=function(){return\"Mxn\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof Q4};f.B=function(){return 77827};f.u=function(){return\"Mxn\"};f.$classData=q({GW:0},!1,\"mlscript.Mxn$\",{GW:1,EE:1,sz:1,sx:1,g:1,E:1,v:1,l:1});var R4;function cp(){R4||(R4=new Q4);return R4}function S4(){this.mz=null;this.oz=this.pz=0;this.qz=this.nz=null;this.Rn=0;Nq(this)}S4.prototype=new AS;S4.prototype.constructor=S4;f=S4.prototype;f.H=function(){return\"NoCases\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};\nf.D=function(a){return a instanceof S4};f.B=function(){return-546441758};f.u=function(){return\"NoCases\"};f.$classData=q({VW:0},!1,\"mlscript.NoCases$\",{VW:1,yM:1,g:1,zM:1,Ta:1,E:1,v:1,l:1});var T4;function zm(){T4||(T4=new S4);return T4}function U4(a){Nq(a);if(a instanceof yo)var b=a.gb.Zr();else{if(!(a instanceof Zn))throw new w(a);b=a.Rb}a.Cf=b}function Ct(){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.sE=this.tE=this.Cf=null;this.gp=0}Ct.prototype=new ZS;\nCt.prototype.constructor=Ct;function V4(){}V4.prototype=Ct.prototype;Ct.prototype.jb=function(){return cy(this)};Ct.prototype.Vj=function(){return eP(this)};Ct.prototype.Wr=function(){return Mx(this)};function Cp(a){0===(1&a.gp)<<24>>24&&0===(1&a.gp)<<24>>24&&(a.tE=gea(a),a.gp=(1|a.gp)<<24>>24);return a.tE}Ct.prototype.nv=function(){0===(2&this.gp)<<24>>24&&0===(2&this.gp)<<24>>24&&(this.sE=cP(this),this.gp=(2|this.gp)<<24>>24);return this.sE};\nfunction ax(a,b,c,d,e){this.nc=this.px=null;this.Ju=b;this.Rl=c;this.rk=d;this.Ql=e;MS(this,a,Ap())}ax.prototype=new NS;ax.prototype.constructor=ax;f=ax.prototype;f.Ea=function(){return this.Ju};f.Yr=function(){return this.Rl};f.Ag=function(){return this.rk};f.fd=function(){return this.Rl.pb};f.Ua=function(){return this.Rl.gb.V};f.cG=function(){return this.Rl.gb};f.aG=function(){return nf()};f.tr=function(){return!this.Rl.Hj.b()};f.Mp=function(){return!0};\nfunction qfa(a,b,c,d,e){var g=new Iw(d.S,d.Ec,d.hc,d.Ed,1+d.da|0,d.Pc,d.Zc,d.Lb,d.yc,d.tb,d.$a,d.od,d.cb),h=a.nc;d=d.da;var k=a.Rl,l=a.rk,m=x=>{var A=x.kc,B=x.hb.Kc(b,c,g,e);return new tl(A,hD(B),x.Rd)};if(l===u())m=u();else{var n=l.e(),r=n=new z(m(n),u());for(l=l.f();l!==u();){var v=l.e();v=new z(m(v),u());r=r.p=v;l=l.f()}m=n}return new ax(h,d,k,m,a.Ql.Kc(b,c,g,e))}\nfunction rfa(a,b,c){var d=a.nc,e=a.Ju,g=a.Rl,h=a.rk,k=r=>{var v=r.kc,x=c.ba(t().d,r.hb);return new tl(v,hD(x),r.Rd)};if(h===u())k=u();else{var l=h.e(),m=l=new z(k(l),u());for(h=h.f();h!==u();){var n=h.e();n=new z(k(n),u());m=m.p=n;h=h.f()}k=l}return new ax(d,e,g,k,c.ba(b,a.Ql))}\nfunction sfa(a,b,c){var d=a.nc,e=a.Ju,g=a.Rl,h=a.rk,k=r=>{var v=r.kc,x=c.ba(new TB(b),r.hb);return new tl(v,hD(x),r.Rd)};if(h===u())k=u();else{var l=h.e(),m=l=new z(k(l),u());for(h=h.f();h!==u();){var n=h.e();n=new z(k(n),u());m=m.p=n;h=h.f()}k=l}return new ax(d,e,g,k,c.ba(b,a.Ql))}f.H=function(){return\"TypedNuAls\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.Ju;case 1:return this.Rl;case 2:return this.rk;case 3:return this.Ql;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof ax};f.B=function(){var a=lb(\"TypedNuAls\");a=W().C(-889275714,a);var b=this.Ju;a=W().C(a,b);b=this.Rl;b=My(W(),b);a=W().C(a,b);b=this.rk;b=My(W(),b);a=W().C(a,b);b=this.Ql;b=My(W(),b);a=W().C(a,b);return W().Ma(a,4)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof ax&&a.nc===this.nc){if(this.Ju===a.Ju){var b=this.Rl,c=a.Rl;b=null===b?null===c:b.i(c)}else b=!1;if(b&&(b=this.rk,c=a.rk,null===b?null===c:b.i(c)))return b=this.Ql,a=a.Ql,null===b?null===a:mC(b,a)}return!1};f.cm=function(a,b){return sfa(this,a,b)};f.yl=function(a,b,c){return rfa(this,a,c)};f.ro=function(a,b,c,d){return qfa(this,a,b,c,d)};f.$classData=q({zX:0},!1,\"mlscript.NuTypeDefs$TypedNuAls\",{zX:1,YH:1,g:1,Rs:1,nx:1,E:1,v:1,l:1});\nfunction By(a,b,c){this.q=null;this.xk=b;this.Ul=c;if(null===a)throw null;this.q=a}By.prototype=new fT;By.prototype.constructor=By;function dca(a,b,c){var d=a.q,e=a.xk;if(e===u())c=u();else{var g=e.e(),h=g=new z(cz(g,b,c),u());for(e=e.f();e!==u();){var k=e.e();k=new z(cz(k,b,c),u());h=h.p=k;e=e.f()}c=g}a=a.Ul;return new By(d,c,a.b()?R():new L(b.n(a.o())))}\nfunction wB(a,b,c,d){var e=a.q,g=a.xk;if(g===u())d=u();else{var h=g.e(),k=h=new z(h.yl(b,!0,c,d),u());for(g=g.f();g!==u();){var l=g.e();l=new z(l.yl(b,!0,c,d),u());k=k.p=l;g=g.f()}d=h}a=a.Ul;a.b()?b=R():(a=a.o(),b=new L(c.ba(b,a)));return new By(e,d,b)}\nfunction ica(a,b,c,d){var e=a.q,g=a.xk;if(g===u())d=u();else{var h=g.e(),k=h=new z(h.cm(b,c,d),u());for(g=g.f();g!==u();){var l=g.e();l=new z(l.cm(b,c,d),u());k=k.p=l;g=g.f()}d=h}a=a.Ul;a.b()?b=R():(a=a.o(),b=new L(c.ba(b,a)));return new By(e,d,b)}f=By.prototype;f.u=function(){var a=Xq(this.xk,this.Ul);return\"TypedTypingUnit(\"+CF(GF(),a)+\")\"};f.H=function(){return\"TypedTypingUnit\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.xk;case 1:return this.Ul;default:return $K(W(),a)}};f.D=function(a){return a instanceof By};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof By&&a.q===this.q){var b=this.xk,c=a.xk;if(null===b?null===c:b.i(c))return b=this.Ul,a=a.Ul,null===b?null===a:b.i(a)}return!1};f.$classData=q({HX:0},!1,\"mlscript.NuTypeDefs$TypedTypingUnit\",{HX:1,Paa:1,Gg:1,g:1,Hg:1,E:1,v:1,l:1});\nfunction Cw(){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0}Cw.prototype=new d3;Cw.prototype.constructor=Cw;function W4(){}W4.prototype=Cw.prototype;\nclass Gf extends Df{constructor(a,b,c){super();this.aF=b;this.YI=c;this.pq=a;yF(this,a,null,!0)}vt(){return this.aF}H(){return\"WarningReport\"}G(){return 3}I(a){switch(a){case 0:return this.pq;case 1:return this.aF;case 2:return this.YI;default:return $K(W(),a)}}D(a){return a instanceof Gf}B(){return AL(this)}i(a){if(this===a)return!0;if(a instanceof Gf&&this.pq===a.pq){var b=this.aF,c=a.aF;return(null===b?null===c:b.i(c))?this.YI===a.YI:!1}return!1}}\nGf.prototype.$classData=q({h_:0},!1,\"mlscript.WarningReport\",{h_:1,IU:1,qd:1,pc:1,g:1,l:1,E:1,v:1});function ym(a){this.mz=null;this.oz=this.pz=0;this.qz=this.nz=null;this.Rn=0;this.dn=a;Nq(this)}ym.prototype=new AS;ym.prototype.constructor=ym;f=ym.prototype;f.H=function(){return\"Wildcard\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.dn:$K(W(),a)};f.D=function(a){return a instanceof ym};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof ym){var b=this.dn;a=a.dn;return null===b?null===a:b.i(a)}return!1};f.$classData=q({l_:0},!1,\"mlscript.Wildcard\",{l_:1,yM:1,g:1,zM:1,Ta:1,E:1,v:1,l:1});function mn(a,b,c,d,e){this.TA=a;this.Tx=b;this.eJ=c;this.Sx=d;this.dJ=e}mn.prototype=new p;mn.prototype.constructor=mn;f=mn.prototype;f.xo=function(){return this.TA};f.zo=function(){return this.Tx};f.mv=function(){return this.Sx};f.u=function(){return\"trait \"+this.TA};f.H=function(){return\"TraitSymbol\"};\nf.G=function(){return 5};f.I=function(a){switch(a){case 0:return this.TA;case 1:return this.Tx;case 2:return this.eJ;case 3:return this.Sx;case 4:return this.dJ;default:return $K(W(),a)}};f.D=function(a){return a instanceof mn};f.B=function(){return AL(this)};f.i=function(a){if(this===a)return!0;if(a instanceof mn&&this.TA===a.TA&&this.Tx===a.Tx){var b=this.eJ,c=a.eJ;if(null===b?null===c:b.i(c))if(b=this.Sx,c=a.Sx,null===b?null===c:b.i(c))return b=this.dJ,a=a.dJ,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({C_:0},!1,\"mlscript.codegen.TraitSymbol\",{C_:1,g:1,UA:1,cr:1,mt:1,E:1,v:1,l:1});function X4(a,b){a.Hb&&Nx(a,b)}function tfa(a,b,c,d){a.Hb?Lx(a,b,c,d):Es(c)}function Y4(a){var b=\"tmp\"+a.XA;a.XA=1+a.XA|0;return b}function Z4(a,b){for(var c=Y4(a);b.hc.L(c);)c=Y4(a);return c}function $4(a,b,c,d,e){e.Hk(a5(a,b,d),new U(()=>Xu().X()))}function ufa(a,b,c,d,e,g){g.Hk(a5(a,b,e),new U(()=>Xu().X())).Hk((t(),new fe(c)),new U(()=>TE(PE()))).zc(d)}\nfunction b5(a,b,c,d,e,g){g.Hk(a5(a,b,e),new U(()=>Xu().X())).Hk((t(),new Ud(c)),new U(()=>TE(PE()))).zc(d)}\nfunction c5(a,b,c,d,e,g){var h=TE(PE());c=c.m();d=new x0(c,d);d=new xo(d,new y(k=>{if(null!==k){var l=k.h(),m=k.j();if(l instanceof vl&&\"_\"===l.x)return t(),k=new vl(\"_\"),k=G(new H,m,k),new L(k)}if(null!==k&&(m=k.h(),l=k.j(),m instanceof vl)){var n=m.x;n=Xz(Q(),n);n.b()?n=!1:(n=n.o(),n=Ea(n),n=bE(Pr(),n));if(n)return t(),k=G(new H,l,m),new L(k)}if(null!==k){var r=k.h();m=k.j();if(null!==r)return k=g.Hk(GE(b),new U(()=>Xu().X())).Hk(m,new U(()=>{var v=new vl(Z4(a,e));return OS(v,r)})),l=G(new H,k,\nr),h.$(l),t(),k=G(new H,m,k),new L(k)}throw new w(k);}));Od();d=Pd(u(),d);return G(new H,h.ha(),d)}function d5(a,b,c,d,e,g,h){c=c.m();c=new xo(c,new y(k=>{if(null!==k){var l=k.j();k=e5(a,k.h(),b.ZP,d);var m=O().c;return f5(a,k,l,!1,d,e,g,h,m)}throw new w(k);}));Od();return Pd(u(),c)}\nfunction e5(a,b,c,d){var e=()=>{if(b instanceof vl){if(a.Hb&&a.F){var l=ut(Q(),\"| \",a.r)+\"The scrutinee does not need an alias.\";ff(gf(),l+\"\\n\")}return new wY(t().d,b,c)}if(a.YA.EF(b))l=a.YA.LF(b);else{l=new vl(Z4(a,d));l=OS(l,b);var m=a.YA.zv,n=new bk(b),r=Qb(n.py);b:{var v=r^(r>>>16|0);r=1+m.yv|0;if(r>=m.jK){var x=m.wl,A=x.a.length,B=A<<1,C=new (md(EN).Ia)(B);m.wl=C;m.jK=Eb(B*m.RQ);for(B=0;B<A;){for(var D=null,F=null,I=x.a[B];null!==I;)0===(I.oy&A)?(null===D?C.a[B]=I:D.xr=I,D=I):(null===F?C.a[A+\nB|0]=I:F.xr=I,F=I),I=I.xr;null!==D&&(D.xr=null);null!==F&&(F.xr=null);B=1+B|0}}x=v&(-1+m.wl.a.length|0);A=m.wl.a[x];if(null===A)m.wl.a[x]=new DN(n,v,l,null,null);else{for(C=null;null!==A&&A.oy<=v;){A.oy===v?(C=A.xB,C=null===n?null===C:La(n,C)):C=!1;if(C){A.xv=l;break b}C=A;A=A.xr}n=new DN(n,v,l,C,A);null===C?m.wl.a[x]=n:C.xr=n;null!==A}m.yv=r}}a.Hb&&a.F&&(m=ut(Q(),\"| \",a.r)+\"The scrutinee needs an alias: \"+l,ff(gf(),m+\"\\n\"));return new wY((t(),new L(l)),b,c)},g=a.qa;if(a.Hb){if(a.F){var h=ut(Q(),\n\"| \",a.r)+(\"Making a scrutinee for `\"+b)+\"`\";ff(gf(),h+\"\\n\")}a.r=1+a.r|0;try{var k=e()}finally{a.r=-1+a.r|0}dx(new E(g),a.qa)&&a.F&&(e=\"\"+ut(Q(),\"| \",a.r)+g.n(k),ff(gf(),e+\"\\n\"))}else k=e();return k}\nvar f5=function vfa(a,b,c,d,e,g,h,k,l){return Lx(a,new U(()=>\"[Desugarer.destructPattern] scrutinee \\x3d \"+b.nh+\"; pattern \\x3d \"+c),new U(()=>{var n=!1,r=null,v=!1,x=null,A=!1,B=null;if(c instanceof vl&&(n=!0,r=c,\"_\"===r.x&&d)){$4(a,b,iu(ju(),r.A()),e,h);var C=new SE(b,r.A().ha()),D=O().c;return new z(C,D)}if(n&&\"_\"===r.x)return O().c;if(n&&(\"true\"===r.x||\"false\"===r.x)){b5(a,b,r,iu(ju(),r.A()),e,h);var F=r,I=b.nh.A().ha(),M=new OE(b,F,dl(r.A().ha(),I));M.lf=xY(b).ha();X4(a,new U(()=>\"Add bindings to the clause: \"+\nxY(b)));var N=O().c;return new z(M,N)}if(c instanceof Dl){b5(a,b,c,iu(ju(),c.A()),e,h);var P=b.nh.A().ha(),T=new OE(b,c,dl(c.A().ha(),P));T.lf=xY(b).ha();X4(a,new U(()=>\"Add bindings to the clause: \"+xY(b)));var Y=O().c;return new z(T,Y)}if(n){var Z=r.x,S=Xz(Q(),Z),ea=new y(rc=>{rc=Ea(rc);return bE(Pr(),rc)});if(!S.b()&&ea.n(S.o())){var ia=b.nh.A().ha(),X=dl(r.A().ha(),ia);if(d){$4(a,b,iu(ju(),r.A()),e,h);var sa=new SE(b,X),Ja=new YE(r,GE(b),!d,X),Xa=O().c;return new z(sa,new z(Ja,Xa))}var Fa=new YE(r,\nb.nh,!d,X),za=O().c;return new z(Fa,za)}}if(n){var Qa=r.x,Ma=!1,Ga=null,ab=e.tb.U(Qa),Hb=new U(()=>uC(e,e,Qa)),bc=ab.b()?Es(Hb):ab;a:{if(bc instanceof L){Ma=!0;Ga=bc;var yb=Ga.k;if(yb instanceof VP&&yb.J===a){var tb=yb.fd();if(Ot(new E(tb),Bp()))var eb=!0;else{var kb=yb.fd();eb=Ot(new E(kb),zp())}if(eb)break a}}if(Ma){var Rb=Ga.k;if(Rb instanceof VP&&Rb.J===a){var Gb=Rb.fd();if(Ot(new E(Gb),Fp())){var vb=new Te(new Ue(J(new K,[\"Cannot match on trait `\",\"`\"]))),Tb=[We(Xe(),Qa)];throw iT(new jT,Ye(vb,\nJ(new K,Tb)),r.A());}}}if(!(Ma&&Ga.k instanceof YX&&Ga.k.FE===a)){var Nb=new Te(new Ue(J(new K,[\"Cannot find constructor `\",\"` in scope\"]))),ic=[We(Xe(),Qa)];throw iT(new jT,Ye(Nb,J(new K,ic)),r.A());}}X4(a,new U((rc=>()=>\"Build a Clause.MatchClass from \"+b+\" where pattern is \"+rc)(r)));b5(a,b,r,iu(ju(),r.A()),e,h);var Va=new UE(b,r,O().c,g5()),cb=O().c;return new z(Va,cb)}if(c instanceof Pl){v=!0;x=c;var zb=x.Za,Ub=x.Qb;if(zb instanceof vl){var jb=zb.x;if(Ub instanceof Gl){var db=Ub.Ra,ub=e.tb.U(jb),\nAa=new y(rc=>G(new H,rc.jj,rc.at)),va=ub.b()?R():new L(Aa.n(ub.o())),Ra=new U(()=>{var rc=!1,sd=null,Kc=uC(e,e,jb);if(Kc instanceof L&&(rc=!0,sd=Kc,Kc=sd.k,Kc instanceof fx)){var Qd=Kc.Ab.fd();if(Ot(new E(Qd),Bp()))return t(),rc=Kc.Ab.fd(),sd=px(Kc),Kc=new U(()=>O().c),rc=G(new H,rc,Qt(sd.b()?Es(Kc):sd.o(),new y(Ad=>Ad.h().x))),new L(rc)}if(rc&&(rc=sd.k,rc instanceof ix&&(rc=rc.kh,rc instanceof Yw)))return t(),sd=rc.Ij,Kc=new U(()=>O().c),rc=G(new H,rc.Rf.pb,Qt(sd.b()?Es(Kc):sd.o(),new y(Ad=>Ad.h().x))),\nnew L(rc);rc=new Te(new Ue(J(new K,[\"Illegal pattern `\",\"`\"])));sd=[We(Xe(),jb)];throw iT(new jT,Ye(rc,J(new K,sd)),zb.A());}),rb=va.b()?Es(Ra):va;if(t().d===rb){var xb=new Te(new Ue(J(new K,[\"Cannot find class `\",\"` in scope\"]))),mc=[We(Xe(),jb)];throw iT(new jT,Ye(xb,J(new K,mc)),zb.A());}if(rb instanceof L){var Ha=rb.k;if(null!==Ha){var Ka=Ha.h(),Oa=Ha.j(),Na=db.K();if(Pe(new E(Na),Oa.K())){var Da=db.m(),ta=c5(a,b,new Ef(Da,new y(rc=>rc.j().ya)),Oa,e,k);if(null!==ta)var Ya=G(new H,ta.h(),ta.j());\nelse throw new w(ta);var dc=Ya.h(),ka=Ya.j();b5(a,b,zb,iu(ju(),x.A()),e,h);var ya=c.A().ha(),Sa=new UE(b,zb,ka,dl(g5(),ya));X4(a,new U(()=>\"Build a Clause.MatchClass from \"+b+\" where pattern is \"+c));X4(a,new U(()=>\"Fragments: \"+l));X4(a,new U(()=>\"The locations of the clause: \"+Sa.tF));var xc=d5(a,b,dc,e,g,h,k);return new z(Sa,xc)}var Sb=Oa.K();db.K();var uc=new Te(new Ue(J(new K,\"; ; expects ; ; but found ; ;\".split(\";\")))),Lb=We(Xe(),Ka.ld),lc=We(Xe(),jb),Xb=We(Xe(),\"\"+Sb),ec=We(Xe(),WF(ve(),\"parameter\",\nSb,!1));Xe();var Ab=db.K(),Ob=[Lb,lc,Xb,ec,We(0,\"\"+Ab),We(Xe(),WF(ve(),\"parameter\",Sb,!1))];throw iT(new jT,Ye(uc,J(new K,Ob)),x.A());}}throw new w(rb);}}}if(v){var fb=x.Za,Wa=x.Qb;if(fb instanceof Pl){var bb=fb.Za,Ia=fb.Qb;if(bb instanceof vl){var Ua=bb.x;if(Ia instanceof Gl){var pc=Ia.Ra;if(pc instanceof z){var sc=pc.z,Ba=pc.p;if(null!==sc){var ob=new L(sc);if(!ob.b()){var nc=ob.k.j();if(null!==nc){var Ib=nc.ya,vc=O().c;if((null===vc?null===Ba:vc.i(Ba))&&Wa instanceof Gl){var Vb=Wa.Ra;if(Vb instanceof\nz){var fc=Vb.z,Bc=Vb.p;if(null!==fc){var Pb=new L(fc);if(!Pb.b()){var Jb=Pb.k.j();if(null!==Jb){var gc=Jb.ya,Cb=O().c;if(null===Cb?null===Bc:Cb.i(Bc)){var cc=!1,yc=null,Mc=e.tb.U(Ua);if(t().d===Mc){var qc=new Te(new Ue(J(new K,[\"Cannot find operator `\",\"` in the context\"]))),oc=[We(Xe(),Ua)];throw iT(new jT,Ye(qc,J(new K,oc)),bb.A());}if(Mc instanceof L){cc=!0;yc=Mc;var Qc=yc.k,jc=Qc.at.K();if(Pe(new E(jc),2)){var sb=O().c,Gc=c5(a,b,new z(Ib,new z(gc,sb)),Qc.at,e,k);if(null!==Gc)var Wb=G(new H,Gc.h(),\nGc.j());else throw new w(Gc);var Cc=Wb.h(),Fc=Wb.j();b5(a,b,bb,iu(ju(),x.A()),e,h);var qd=new UE(b,bb,Fc,g5());X4(a,new U(()=>\"Build a Clause.MatchClass from \"+b+\" where operator is \"+bb));var Yb=d5(a,b,Cc,e,g,h,k);return new z(qd,Yb)}}if(cc){var Nc=yc.k;Nc.at.K();var ad=Nc.at.K(),Uc=new Te(new Ue(J(new K,[\"\",\" `\",\"` expects \",\" \",\" but found two parameters\"]))),cd=[We(Xe(),Nc.jj.ld),We(Xe(),Ua),We(Xe(),\"\"+ad),We(Xe(),WF(ve(),\"parameter\",ad,!1))];throw iT(new jT,Ye(Uc,J(new K,cd)),x.A());}throw new w(Mc);\n}}}}}}}}}}}}}}if(c instanceof Fl){A=!0;B=c;var kc=B.gg;if(!1===B.bi&&kc instanceof Gl)return h5(a,kc,b,e,k,g,h)}if(c instanceof Gl)return h5(a,c,b,e,k,g,h);if(A){var Vc=B.gg;if(!1===B.bi)return vfa(a,b,Vc,d,e,g,h,k,l)}var Hc=new Ue(J(new K,[\"illegal pattern\"]));throw iT(new jT,Ye(new Te(Hc),u()),c.A());}),new y(n=>\"[Desugarer.destructPattern] Result: \"+ze(n,\"\",\", \",\"\")))};function g5(){return TE(PE()).ha()}\nvar xfa=function wfa(a,b,c){var e=()=>{var l=b.zs;if(l instanceof L){var m=l.k;if(m instanceof Xl)return wfa(a,m,new z(b.bp,c))}if(c.b())return G(new H,b.bp,l);m=er(new z(b.bp,c)).m();m=new xo(m,new y(n=>{if(n instanceof $t)return n.ap;O();t();return new CQ(new fe(n))}));Od();m=Pd(u(),m);return G(new H,new $t(m),l)},g=new y(l=>\"[unfoldNestedIf] (\"+ag(ca(l.h()))+\", \"+l.j()+\")\");if(a.Hb){if(a.F){var h=ut(Q(),\"| \",a.r)+\"[unfoldNestedIf]\";ff(gf(),h+\"\\n\")}a.r=1+a.r|0;try{var k=e()}finally{a.r=-1+a.r|0}dx(new E(g),\na.qa)&&a.F&&(e=\"\"+ut(Q(),\"| \",a.r)+g.n(k),ff(gf(),e+\"\\n\"))}else k=e();return k};\nfunction yfa(a,b,c,d,e,g){var h=()=>{var n=Xu().X(),r=TE(PE()),v=TE(PE());i5(a,b,b0(),new NE(O().c,O().c),v,r,d,e,g,n);c.b()||(n=c.o(),v=new NE(O().c,O().c),n=G(new H,v,n),r.$(n));a.Hb&&a.F&&(n=ut(Q(),\"| \",a.r)+\"Decision paths:\",ff(gf(),n+\"\\n\"));for(n=r.m();n.s();){var x=n.t();a:{if(null!==x&&(v=new L(x),!v.b())){x=v.k.h();v=v.k.j();a.Hb&&a.F&&(v=ut(Q(),\"| \",a.r)+(\"+ \"+x+\" \\x3d\\x3e \")+v,ff(gf(),v+\"\\n\"));break a}throw new w(x);}}return r.ha()},k=new y(n=>{var r=n.K();n=n.K();return\"[desugarIf] produces \"+\nr+\" \"+WF(ve(),\"path\",n,!1)});if(a.Hb){if(a.F){var l=ut(Q(),\"| \",a.r)+\"[desugarIf] with fallback \"+c;ff(gf(),l+\"\\n\")}a.r=1+a.r|0;try{var m=h()}finally{a.r=-1+a.r|0}dx(new E(k),a.qa)&&a.F&&(h=\"\"+ut(Q(),\"| \",a.r)+k.n(m),ff(gf(),h+\"\\n\"))}else m=h();return m}\nfunction a5(a,b,c){var d=()=>{var k=b.nh;if(k instanceof vl){var l=k.x;if(a.Hb&&a.F){var m=ut(Q(),\"| \",a.r)+\"The original scrutinee is an reference.\";ff(gf(),m+\"\\n\")}l=c.hc.U(l);if(l instanceof L&&(m=l.k,m instanceof qx))return l=m.vA.kt,l.b()?(t(),k=new fe(k.x)):(k=l.o()|0,t(),k=new Ud(k)),k;if(l instanceof L||t().d===l)return t(),new fe(k.x);throw new w(l);}a.Hb&&a.F&&(k=ut(Q(),\"| \",a.r)+\"The scrutinee was localized because it might be effectful.\",ff(gf(),k+\"\\n\"));k=b.no;if(t().d===k)throw vS(new wS,\n\"check your `makeScrutinee`\");if(k instanceof L)return k=k.k,t(),new fe(k.x);throw new w(k);},e=a.qa;if(a.Hb){if(a.F){var g=ut(Q(),\"| \",a.r)+\"[getScrutineeKey] \"+b;ff(gf(),g+\"\\n\")}a.r=1+a.r|0;try{var h=d()}finally{a.r=-1+a.r|0}dx(new E(e),a.qa)&&a.F&&(d=\"\"+ut(Q(),\"| \",a.r)+e.n(h),ff(gf(),d+\"\\n\"))}else h=d();return h}\nvar zfa=function j5(a,b,c,d,e,g,h){tfa(a,new U(()=>\"[checkExhaustive] \"+b.jb()),new U(()=>{if(!(b instanceof HE)){if(IE()===b){var l=!1,m=null;if(c instanceof L){l=!0;m=c;var n=m.k;if(n instanceof CE){var r=n.hr;if(Pe(new E(n.Fh),b))throw l=new Te(new Ue(J(new K,[\"The case when this is false is not handled: \",\"\"]))),m=[We(Xe(),Zz(r,!1))],iT(new jT,Ye(l,J(new K,m)),r.A());xm(\"`MissingCase` are not supposed to be the true branch of `IfThenElse`\")}}l&&m.k instanceof DE&&xm(\"`MissingCase` are not supposed to be a case of `Match`\");\na:if(c instanceof L&&c.k instanceof HE)r=!0;else{if(c instanceof L&&(r=c.k,IE()===r)){r=!0;break a}r=t().d===c?!0:!1}r&&xm(\"Program reached and unexpected state.\");throw new w(c);}if(b instanceof CE)r=b.Dk,j5(a,b.Fh,(t(),new L(b)),d,e,g,h),j5(a,r,(t(),new L(b)),d,e,g,h);else if(b instanceof DE){var v=b.mo;r=b.mh;l=b.nj;m=!1;n=null;var x=g.U(a5(a,v,d));a:{t().d===x&&xm(\"unreachable case: unknown scrutinee \"+v.nh);if(x instanceof L&&(m=!0,n=x,!l.b())){X4(a,new U(()=>\"The match has a default branch. So, it is always safe.\"));\nbreak a}if(m){m=n.k;X4(a,new U(()=>\"The exhaustiveness map is\"));g.og(new fn((C,D)=>{X4(a,new U(()=>{var F=D.tj();return\"- \"+C+\" -\\x3e \"+ze(F,\"\",\", \",\"\")}))}));X4(a,new U(()=>\"The scrutinee key is \"+a5(a,v,d)));X4(a,new U(()=>\"Pattern map of the scrutinee:\"));m.b()?X4(a,new U(()=>\"\\x3cEmpty\\x3e\")):m.og(new fn((C,D)=>{X4(a,new U(()=>\"- \"+C+\" \\x3d\\x3e \"+D))}));tp();n=r.m();var A=Aq(0,new xo(n,new y(C=>{if(C instanceof EE)return O().c;if(C instanceof FE){var D=C.Tj;if(null!==D&&(D=new L(D),!D.b()&&(D=\nD.k.h(),null!==D))){C=h.U(D.x);D=new U(()=>O().c);var F=new y(I=>I);return C.b()?Es(D):F.n(C.o())}}throw new w(C);})));X4(a,new U(()=>\"The match can cover following classes\"));X4(a,new U(()=>ze(A,\"{\",\", \",\"}\")));n=r.m();m=m.dG(new Ef(n,new y(C=>{if(C instanceof EE)return C=C.ir,t(),new Ud(C);if(C instanceof FE){var D=C.Tj;if(null!==D&&(D=new L(D),!D.b())){C=D.k.h();tp();Q();D=C.x;Q();D=M2(D,\"\\\\\"+hc(35));D=ps(D);Od();D=Pd(u(),D);if(D instanceof z){var F=D.p;if(\"Tuple\"===D.z&&F instanceof z){D=F.z;\nF=F.p;var I=O().c;if(null===I?null===F:I.i(F)){D=$D(aE(),D);if(t().d===D)return t(),new Ud(C);if(D instanceof L)return C=D.k|0,t(),new fe(C);throw new w(D);}}}t();return new Ud(C)}}throw new w(C);}))).Fk(new y(C=>{if(null!==C){var D=new L(C);if(!D.b()&&(D=D.k.h(),D instanceof Ud&&(D=D.fa,D instanceof vl)))return!A.L(D.x)}if(null!==C&&(D=new L(C),!D.b()&&D.k.h()instanceof fe)||null!==C&&(D=new L(C),!D.b()&&D.k.h()instanceof Ud))return!0;throw new w(C);}));X4(a,new U(()=>\"Missing cases\"));m.og(new fn((C,\nD)=>{X4(a,new U(()=>\"- \"+C+\" -\\x3e \"+D))}));if(m.b())break a;else{var B=m.ka();r=Ye(new Te(new Ue(J(new K,[\"The match is not exhaustive.\"]))),u());r=G(new H,r,v.ZP);l=new Te(new Ue(J(new K,[\"The scrutinee at this position misses \",\" \",\".\"])));n=[We(Xe(),\"\"+B),We(Xe(),WF(ve(),\"case\",B,!1))];l=Ye(l,J(new K,n));n=v.nh.A();l=G(new H,l,n);m=m.m();m=new Ao(m);m=new xo(m,new y(C=>{if(null!==C){var D=C.h(),F=C.Sc();if(null!==D){C=D.h();D=D.j();if(C instanceof fe)C=(C.aa|0)+\"-ary tuple\";else if(C instanceof\nUd)C=Zz(C.fa,!1);else throw new w(C);var I=\"[Missing Case \"+(1+F|0)+\"/\"+B+\"]\";F=new Te(new Ue(J(new K,[\"\",\" `\",\"`\"])));C=[We(Xe(),I),We(Xe(),C)];F=Ye(F,J(new K,C));C=t().d;F=G(new H,F,C);D=D.m();D=new Ao(D);D=new Ef(D,new y(M=>{if(null!==M){var N=M.h();M=Pe(new E(M.Sc()),0)?Ye(new Te(new Ue(J(new K,[\"It first appears here.\"]))),u()):Ye(new Te(new Ue(J(new K,[\"And here.\"]))),u());t();return G(new H,M,new L(N))}throw new w(M);}));Od();D=Pd(u(),D);return new z(F,D)}}throw new w(C);}));Od();m=Pd(u(),\nm);l=new z(l,m);throw hT(new jT,new z(r,l));}}throw new w(x);}m=new y(C=>{j5(a,C,(t(),new L(b)),d,e,g,h)});l.b()||m.n(l.o());cH(r,new y(C=>{j5(a,C.xt(),(t(),new L(b)),d,e,g,h)}))}else throw new w(b);}}),new y(()=>\"[checkExhaustive] \"+b.jb()))};\nfunction Afa(a,b,c){var d=()=>{tp();var k=b.ni.m();k=k5(a,b,Aq(0,new Ef(k,new y(r=>r.Sj))),c);var l=tF(),m=b.ni.ha(),n=ap();return mF(l,m,n,k)},e=new y(()=>\"[constructTerm]\");if(a.Hb){if(a.F){var g=ut(Q(),\"| \",a.r)+\"[constructTerm]\";ff(gf(),g+\"\\n\")}a.r=1+a.r|0;try{var h=d()}finally{a.r=-1+a.r|0}dx(new E(e),a.qa)&&a.F&&(d=\"\"+ut(Q(),\"| \",a.r)+e.n(h),ff(gf(),d+\"\\n\"))}else h=d();return h}\nfunction Bfa(a,b,c,d,e,g){var h=()=>{var n=O().c;if(null===n?null===b:n.i(b))return IE();if(b instanceof z){var r=b.z;n=b.p;if(null!==r){var v=new L(r);if(!v.b()){r=v.k.h();v=v.k.j();var x=gF(),A=cF(x,r,v);r=()=>{for(var D=eF(gF(),A);!D.b();){var F=D.e();a.Hb&&a.F&&(F=\"\"+ut(Q(),\"| \",a.r)+F,ff(gf(),F+\"\\n\"));D=D.f()}};v=a.qa;if(a.Hb){a.F&&(x=ut(Q(),\"| \",a.r)+\"*** Initial tree ***\",ff(gf(),x+\"\\n\"));a.r=1+a.r|0;try{var B=r()}finally{a.r=-1+a.r|0}dx(new E(v),a.qa)&&a.F&&(B=\"\"+ut(Q(),\"| \",a.r)+v.n(B),ff(gf(),\nB+\"\\n\"))}else r();for(;!n.b();){B=n.e();A.dm(B,c,d,e,g);a.Hb&&a.F&&(B=ut(Q(),\"| \",a.r)+(\"*** Merging `\"+B.h()+\" \\x3d\\x3e \"+B.j())+\"` ***\",ff(gf(),B+\"\\n\"));B=(D=>()=>{for(var F=eF(gF(),D);!F.b();){var I=F.e();a.Hb&&a.F&&(I=\"\"+ut(Q(),\"| \",a.r)+I,ff(gf(),I+\"\\n\"));F=F.f()}})(A);r=a.qa;if(a.Hb){a.F&&(v=ut(Q(),\"| \",a.r)+\"*** Updated tree ***\",ff(gf(),v+\"\\n\"));a.r=1+a.r|0;try{var C=B()}finally{a.r=-1+a.r|0}dx(new E(r),a.qa)&&a.F&&(B=\"\"+ut(Q(),\"| \",a.r)+r.n(C),ff(gf(),B+\"\\n\"))}else B();n=n.f()}return A}}}throw new w(b);\n},k=new y(()=>\"[buildCaseTree]\");if(a.Hb){if(a.F){var l=ut(Q(),\"| \",a.r)+\"[buildCaseTree]\";ff(gf(),l+\"\\n\")}a.r=1+a.r|0;try{var m=h()}finally{a.r=-1+a.r|0}dx(new E(k),a.qa)&&a.F&&(h=\"\"+ut(Q(),\"| \",a.r)+k.n(m),ff(gf(),h+\"\\n\"))}else m=h();return m}\nfunction Cfa(a,b){var c=()=>{var h=b.tb.m();h=new iy(h,new y(k=>!k.j().GE.b()),!1);h=new Ef(h,new y(k=>{if(null!==k){var l=k.h();k=k.j().Bx.m();k=new Ef(k,new y(m=>m.V));Od();k=Pd(u(),k);return G(new H,l,k)}throw new w(k);}));h=pp(tp().JK,h);return Sca(xE(),h)},d=new y(()=>\"[getClassHierarchy]\");if(a.Hb){if(a.F){var e=ut(Q(),\"| \",a.r)+\"[getClassHierarchy]\";ff(gf(),e+\"\\n\")}a.r=1+a.r|0;try{var g=c()}finally{a.r=-1+a.r|0}dx(new E(d),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+d.n(g),ff(gf(),a+\"\\n\"))}else g=c();\nreturn g}function h5(a,b,c,d,e,g,h){var k=b.Ra.m();k=new Ef(k,new y(v=>v.j().ya));var l=b.Ra.K(),m=1>l;if(m)var n=0;else{var r=l>>31;n=-1+l|0;r=-1!==n?r:-1+r|0;n=1+n|0;r=0===n?1+r|0:r;n=(0===r?-1<(-2147483648^n):0<r)?-1:n}0>n&&$Q(bR(),1,l,1,!0);n=xe().Eb();for(l=new hE(1,1,l,m);l.fw;)m=\"_\"+c4(l),n.$(m);l=n.Kb();Od();l=c5(a,c,k,Pd(u(),l),d,e);if(null===l)throw new w(l);k=l.h();l=l.j();ufa(a,c,b.Ra.K(),iu(ju(),b.A()),d,h);b=new WE(c,b.Ra.K(),l,g5());a=d5(a,c,k,d,g,h,e);return new z(b,a)}\nfunction l5(a,b,c,d,e,g){for(var h=null,k=null;b!==u();){var l=b.e(),m=!1,n=null;a:{if(l instanceof Pl){m=!0;n=l;var r=n.Za,v=n.Qb;if(r instanceof Pl){var x=r;r=x.Za;x=x.Qb;if(r instanceof vl&&\"is\"===r.x&&x instanceof Gl&&(r=x.Ra,r instanceof z&&(x=r,r=x.z,x=x.p,null!==r&&(r=new L(r),!r.b()&&(r=r.k.j(),null!==r))))){r=r.ya;var A=O().c;if((null===A?null===x:A.i(x))&&v instanceof Gl&&(v=v.Ra,v instanceof z&&(x=v.z,v=v.p,null!==x&&(x=new L(x),!x.b()&&(x=x.k.j(),null!==x&&(x=x.ya,A=O().c,(null===A?null===\nv:A.i(v))&&!a.$c)))))){n=n.A();n=e5(a,r,n,c);l=O().c;n=f5(a,n,x,!0,c,d,e,g,l);break a}}}}if(m&&(m=n.Za,v=n.Qb,m instanceof vl&&\"is\"===m.x&&null!==v&&(m=mz(eu(),v),!m.b()&&null!==m.o()&&0===m.o().ab(2)))){l=m.o();l=eB(l,0);m=m.o();m=eB(m,1);n=n.A();n=e5(a,l,n,c);l=O().c;n=f5(a,n,m,!0,c,d,e,g,l);break a}n=new XE(l,g5());O();n=new CQ(n)}for(n=n.m();n.s();)l=new z(n.t(),u()),null===k?h=l:k.p=l,k=l;b=b.f()}return null===h?u():h}\nvar Dfa=function m5(a,b,c,d,e,g,h,k,l,m,n){var v=()=>{var C=!1,D=null,F=!1,I=null;a:{if(c instanceof fe){C=!0;D=c;var M=D.aa;if(M instanceof gu){F=G(new H,e,M.ws);h.$(F);break a}}if(C){var N=D.aa;if(N instanceof Ut&&(M=N.Km,N=N.Lm,M instanceof vl&&\"_\"===M.x)){F=G(new H,e,N);h.$(F);break a}}if(C&&(M=D.aa,M instanceof Ut)){I=M.Km;F=M.Lm;C=rF(tF(),I,a.$c);if(null===C)throw new w(C);I=C.j();C=d.oo(C.h(),a.$c).jr;D=O().c;C=f5(a,b,C,!0,k,l,m,n,D);C=sY(e,uY(new NE(C,O().c),g));a.Hb&&a.F&&(D=ut(Q(),\"| \",\na.r)+\"Result: \"+ze(C.Wi,\"\",\", \",\"\"),ff(gf(),D+\"\\n\"));if(t().d===I)F=G(new H,C,F),h.$(F);else if(I instanceof L)i5(a,new Ut(I.k,F),b0(),C,g,h,k,l,m,n);else throw new w(I);break a}if(C&&(M=D.aa,M instanceof Tt)){N=M.Wn;var P=M.Xn;M=M.Yn;if(null!==P&&\"and\"===P.x){I=rF(tF(),N,a.$c);if(null===I)throw new w(I);F=I.h();I=I.j();C=O().c;F=f5(a,b,F,!0,k,l,m,n,C);I.b()?I=O().c:(I=I.o(),I=qF(tF(),I),O(),I=l5(a,I,k,l,m,n));F=sY(e,uY(new NE(dl(I,F),O().c),g));i5(a,M,b0(),F,g,h,k,l,m,n);break a}}if(C&&(M=D.aa,M instanceof\nTt)){C=M.Wn;I=M.Xn;F=M.Yn;C=rF(tF(),C,a.$c);b:{if(null!==C&&(D=C.h(),M=C.j(),M instanceof L)){I=M.k;C=O().c;C=f5(a,b,D,!0,k,l,m,n,C);I=qF(tF(),I);O();I=l5(a,I,k,l,m,n);I=sY(e,uY(new NE(dl(I,C),O().c),g));i5(a,F,b0(),I,g,h,k,l,m,n);break b}if(null!==C&&(D=C.h(),M=C.j(),t().d===M)){F=(t(),new fe(F));I=d0(d.oo(D,a.$c),I);m5(a,b,F,I,e,g,h,k,l,m,n);break b}throw new w(C);}break a}if(C&&(M=D.aa,M instanceof mu)){I=M.xs;F=M.ys;I=rF(tF(),I,a.$c);b:{if(null!==I&&(C=I.h(),D=I.j(),t().d===D)){for(I=d.oo(C,a.$c);!F.b();){D=\nF.e();c:{if(null!==D&&(C=new L(D),!C.b())){D=C.k.h();C=C.k.j();m5(a,b,(t(),new fe(C)),d0(I,D),e,g,h,k,l,m,n);break c}throw new w(D);}F=F.f()}break b}if(null!==I&&(C=I.h(),D=I.j(),D instanceof L)){I=D.k;C=d.oo(C,a.$c).jr;D=O().c;C=f5(a,b,C,!0,k,l,m,n,D);I=qF(tF(),I);D=I.MJ();O();D=l5(a,D,k,l,m,n);for(C=sY(e,uY(new NE(dl(D,C),O().c),g));!F.b();){D=F.e();c:{if(null!==D&&(M=new L(D),!M.b())){D=M.k.j();M=I.Mc();N=O().c;i5(a,D,new a0(M,new z(M,N)),C,g,h,k,l,m,n);break c}throw new w(D);}F=F.f()}break b}throw new w(I);\n}break a}if(C&&(M=D.aa,M instanceof $t)){for(F=M.ap;!F.b();)I=F.e(),m5(a,b,I,d,e,g,h,k,l,m,n),F=F.f();break a}C&&D.aa instanceof Ss&&vF();if(c instanceof Ud&&(F=!0,I=c,M=I.fa,M instanceof Zn&&(D=M.wd,C=M.Rb,M=M.Yc,D instanceof L&&(D=!!D.k,M instanceof fe)))){F=M.aa;F=new bF(KE(),D,C,F);g.$(F);break a}if(F)throw F=I.fa,I=new Te(new Ue(J(new K,[\"Illegal interleaved statement \",\"\"]))),C=[We(Xe(),F.u())],iT(new jT,Ye(I,J(new K,C)),F.A());throw new w(c);}},x=new y(()=>\"[desugarMatchBranch]\");if(a.Hb){if(a.F){var A=\nut(Q(),\"| \",a.r)+\"[desugarMatchBranch]\";ff(gf(),A+\"\\n\")}a.r=1+a.r|0;try{var B=v()}finally{a.r=-1+a.r|0}dx(new E(x),a.qa)&&a.F&&(v=\"\"+ut(Q(),\"| \",a.r)+x.n(B),ff(gf(),v+\"\\n\"))}else v()},i5=function n5(a,b,c,d,e,g,h,k,l,m){var r=()=>{var B=!1,C=null,D=!1,F=null;a:if(b instanceof mu)for(D=b.ys,F=c.oo(b.xs,a.$c);!D.b();){C=D.e();b:{if(null!==C&&(B=new L(C),!B.b())){n5(a,B.k.j(),d0(F,B.k.h()),d,e,g,h,k,l,m);break b}throw new w(C);}D=D.f()}else{if(b instanceof Ut){B=!0;C=b;var I=C.Km,M=C.Lm;if(I instanceof\nvl&&\"_\"===I.x){F=G(new H,d,M);g.$(F);break a}}if(B)F=C.Lm,D=c.oo(C.Km,a.$c),C=qF(tF(),D.jr),dl(D.aB,C),D=l5(a,C,h,k,l,m),D=uY(tY(d,D),e),F=G(new H,D,F),g.$(F);else{if(b instanceof Tt&&(D=!0,F=b,B=F.Wn,C=F.Xn,I=F.Yn,null!==C&&\"is\"===C.x&&I instanceof $t)){F=I.ap;D=c.oo(B,a.$c).jr;B=D.A();C=C.A();b:{if(B instanceof L&&(B=B.k,C instanceof L)){C=C.k;t();C=xs(B,C);C=new L(C);break b}C=t().d}D=e5(a,D,C,h);C=D.no;if(C instanceof L)C=d;else{if(t().d!==C)throw new w(C);C=d}for(B=e.ia();!F.b();)I=F.e(),Dfa(a,\nD,I,b0(),C,B,g,h,k,l,m),F=F.f();break a}if(D&&(B=F.Wn,I=F.Xn,C=F.Yn,null!==I&&\"and\"===I.x)){F=c.oo(B,a.$c).jr;D=O().c;F=new z(F,D);O();F=tY(d,l5(a,F,h,k,l,m));n5(a,C,b0(),F,e,g,h,k,l,m);break a}if(D)D=F.Yn,C=F.Xn,F=d0(c.oo(F.Wn,a.$c),C),n5(a,D,F,d,e,g,h,k,l,m);else if(b instanceof Ss&&vF(),b instanceof gu)F=b.ws,D=uY(d,e),F=G(new H,D,F),g.$(F);else if(b instanceof $t)for(F=b.ap;!F.b();){D=F.e();C=!1;b:if(D instanceof fe)n5(a,D.aa,c,d,e,g,h,k,l,m);else{if(D instanceof Ud&&(C=!0,B=D,B=B.fa,B instanceof\nZn&&(M=B,I=M.wd,B=M.Rb,M=M.Yc,I instanceof L&&(I=!!I.k,M instanceof fe)))){D=M.aa;a.Hb&&a.F&&(C=ut(Q(),\"| \",a.r)+\"Found interleaved binding \"+B.x,ff(gf(),C+\"\\n\"));D=new bF(KE(),I,B,D);e.$(D);break b}if(C)throw vS(new wS,\"unexpected statements at desugarIfBody\");throw new w(D);}F=F.f()}else throw new w(b);}}},v=new y(()=>\"[desugarIfBody]\");if(a.Hb){if(a.F){var x=ut(Q(),\"| \",a.r)+\"[desugarIfBody]\";ff(gf(),x+\"\\n\")}a.r=1+a.r|0;try{var A=r()}finally{a.r=-1+a.r|0}dx(new E(v),a.qa)&&a.F&&(r=\"\"+ut(Q(),\"| \",\na.r)+v.n(A),ff(gf(),r+\"\\n\"))}else r()},p5=function o5(a,b,c,d,e,g){var k=!1,l=null;if(b instanceof z){k=!0;l=b;var m=l.z,n=l.p;if(m instanceof FE){var r=m.Tj;m=m.pl;if(null!==r&&(r=new L(r),!r.b())){b=r.k.h();l=r.k.j();a.Hb&&a.F&&(k=ut(Q(),\"| \",a.r),r=l.m(),r=new Ef(r,new y(D=>D.h()+\" -\\x3e \"+D.j())),k=k+(\"\\u2022 Constructor pattern: \"+b+\"(\"+ze(r,\"\",\", \",\"\"))+\")\",ff(gf(),k+\"\\n\"));k=l.m();k=new Ef(k,new y(D=>D.j()));m=k5(a,m,c.Ce(k),g);r=!1;var v=null;k=uC(g,g,b.x);a:{if(k instanceof L){r=!0;v=k;var x=\nv.k;if(x instanceof ix&&(x=x.kh,x instanceof Cx)){k=Cp(x.Yr());break a}}if(r&&(r=v.k,r instanceof fx)){k=Cp(r.Ab);break a}r=k instanceof L&&k.k instanceof VP?!0:k instanceof L&&k.k instanceof qx?!0:t().d===k?!0:!1;if(r)k=t().d;else throw new w(k);}a:{if(GE(d)instanceof vl&&k instanceof L&&(k=k.k,!l.b())){v=FV();r=new fp;for(x=l.m();x.s();){var A=x.t();b:{if(null!==A){var B=new L(A);if(!B.b()){var C=B.k.h();B=B.k.j();if(null!==B){A=B.x;B=v.U(C);B instanceof L?wp(r,G(new H,B.k,A)):v.bj(C,A);break b}}}throw new w(A);\n}}v=t().d;l=new sm(tm().Cg,new Gl(l.Ii(new y(D=>D.h())).Ja(new y(D=>{if(null!==D){var F=new L(D);if(!F.b()&&(F=F.k.j(),null!==F)){F=F.x;if(\"_\"===F)return D=t().d,F=new sm(tm().Cg,new vl(Z4(a,g))),G(new H,D,F);D=t().d;F=new sm(tm().Cg,new vl(F));return G(new H,D,F)}}throw new w(D);})).ha()));l=G(new H,v,l);v=O().c;l=new Gl(new z(l,v));r=r.ha();for(r=Km(r);!r.b();)v=r.e(),m=new Rl(!1,new vl(v.j()),new vl(v.h()),m),r=r.f();l=new Ol(l,m);m=t().d;r=tm().Cg;k=new Ql(b,new vl(k.Cf.x));v=t().d;x=new sm(tm().Cg,\nGE(d));v=G(new H,v,x);x=O().c;k=new sm(r,new Pl(k,new Gl(new z(v,x))));m=G(new H,m,k);k=O().c;l=new Pl(l,new Gl(new z(m,k)));break a}l=l.Fk(new y(D=>Nm(new E(D.j().x),\"_\"))).ha();l=Efa(a,GE(d),l,m,d,g)}return new um(b,l,o5(a,n,c,d,e,g))}}}if(k&&(m=l.z,n=l.p,m instanceof EE))return b=m.ir,l=m.Jp,a.Hb&&a.F&&(m=ut(Q(),\"| \",a.r)+\"\\u2022 Literal pattern: \"+b,ff(gf(),m+\"\\n\")),new um(b,k5(a,l,c,g),o5(a,n,c,d,e,g));d=O().c;if(null===d?null===b:d.i(b)){if(R()===e)return a.Hb&&a.F&&(c=ut(Q(),\"| \",a.r)+\"\\u2022 No wildcard branch\",\nff(gf(),c+\"\\n\")),zm();if(e instanceof L)return e=e.k,a.Hb&&a.F&&(d=ut(Q(),\"| \",a.r)+\"\\u2022 Wildcard branch\",ff(gf(),d+\"\\n\")),new ym(k5(a,e,c,g));throw new w(e);}throw new w(b);},k5=function q5(a,b,c,d){var g=()=>{if(b instanceof HE){var m=b.ot,n=tF(),r=b.ni.ha();return mF(n,r,c,m)}if(b instanceof DE){m=b.mo;var v=b.mh,x=b.nj;a.Hb&&a.F&&(n=ut(Q(),\"| \",a.r)+\"\\u2022 Owned let bindings\",ff(gf(),n+\"\\n\"));n=b.ni.m();n=new iy(n,new y(F=>Pe(new E(F.fr),KE())),!0);Od();n=Pd(u(),n);if(n.b()){if(a.Hb&&a.F){var A=\nut(Q(),\"| \",a.r)+\"  * \\x3cNo bindings\\x3e\";ff(gf(),A+\"\\n\")}}else for(A=n;!A.b();){var B=A.e();if(null!==B){var C=B.fr,D=B.Sj;B=B.gr;a.Hb&&a.F&&(C=ut(Q(),\"| \",a.r)+(\"  * (\"+C+\") \"+D+\" \\x3d \")+B,ff(gf(),C+\"\\n\"))}else throw new w(B);A=A.f()}A=v.m();A=new Ef(A,new y(F=>F.xt()));A=kv(A,new U(()=>x));A=new xo(A,new y(F=>F.ni));A=new iy(A,new y(F=>Pe(new E(F.fr),KE())),!1);Od();A=Pd(u(),A);a.Hb&&a.F&&(C=ut(Q(),\"| \",a.r)+\"\\u2022 Collect interleaved let bindings from case branches\",ff(gf(),C+\"\\n\"));if(A.b())a.Hb&&\na.F&&(C=ut(Q(),\"| \",a.r)+\"  * \\x3cNo interleaved bindings\\x3e\",ff(gf(),C+\"\\n\"));else for(C=A;!C.b();){B=C.e();if(null!==B)D=B.Sj,B=B.gr,a.Hb&&a.F&&(D=ut(Q(),\"| \",a.r)+(\"  * \"+D+\" \\x3d \")+B,ff(gf(),D+\"\\n\"));else throw new w(B);C=C.f()}if(v.b()){if(R()===x)throw a.Hb&&a.F&&(n=ut(Q(),\"| \",a.r)+\"\\u2022 The match has neither branches nor default case\",ff(gf(),n+\"\\n\")),n=new Ue(J(new K,[\"found an empty match\"])),iT(new jT,Ye(new Te(n),u()),m.nh.A());if(!(x instanceof L))throw new w(x);r=x.k;a.Hb&&a.F&&\n(v=ut(Q(),\"| \",a.r)+\"\\u2022 Degenerated case: the match only has a wildcard\",ff(gf(),v+\"\\n\"));r=q5(a,r,c,d);v=m.no;if(t().d!==v){if(!(v instanceof L))throw new w(v);r=new Rl(!1,v.k,m.nh,r)}}else{a.Hb&&a.F&&(C=ut(Q(),\"| \",a.r)+\"\\u2022 The match has some case branches\",ff(gf(),C+\"\\n\"));C=new y(()=>\"\\u2022 End for each\");if(a.Hb){a.F&&(D=ut(Q(),\"| \",a.r)+\"\\u2022 For each case branch\",ff(gf(),D+\"\\n\"));a.r=1+a.r|0;try{r=p5(a,v.ha(),c,m,x,d)}finally{a.r=-1+a.r|0}dx(new E(C),a.qa)&&a.F&&(v=\"\"+ut(Q(),\"| \",\na.r)+C.n(r),ff(gf(),v+\"\\n\"))}else r=p5(a,v.ha(),c,m,x,d);v=m.no;if(t().d===v)r=new Ul(m.nh,r);else{if(!(v instanceof L))throw new w(v);v=v.k;r=new Rl(!1,v,m.nh,new Ul(v,r))}}m=tF();v=tF();r=mF(v,A,c,r);return mF(m,n,c,r)}if(IE()===b)throw m=new Ue(J(new K,[\"missing a default branch\"])),iT(new jT,Ye(new Te(m),u()),t().d);if(b instanceof CE)return m=b.hr,n=b.Dk,A=b.Fh,r=tF(),v=A.ni.ha(),C=A.ni.m(),C=new Ef(C,new y(F=>F.Sj)),A=q5(a,A,c.Ce(C),d),r=mF(r,v,c,A),v=tF(),A=n.ni.ha(),C=n.ni.m(),C=new Ef(C,\nnew y(F=>F.Sj)),n=q5(a,n,c.Ce(C),d),n=mF(v,A,c,n),r=new ym(r),n=new um(new vl(\"true\"),n,r),new Ul(m,n);throw new w(b);},h=a.qa;if(a.Hb){if(a.F){var k=ut(Q(),\"| \",a.r)+(\"[rec] \"+b.jb()+\" -| {\"+ze(c,\"\",\", \",\"\"))+\"}\";ff(gf(),k+\"\\n\")}a.r=1+a.r|0;try{var l=g()}finally{a.r=-1+a.r|0}dx(new E(h),a.qa)&&a.F&&(g=\"\"+ut(Q(),\"| \",a.r)+h.n(l),ff(gf(),g+\"\\n\"))}else l=g();return l},Efa=function r5(a,b,c,d,e,g){var k=O().c;if(null===k?null===c:k.i(c))return d;if(c instanceof z){var l=c.z;k=c.p;if(null!==l&&(l=new L(l),\n!l.b())){var m=l.k.h();l=l.k.j();if(null!==l){c=l.x;var n=e.nh;if(n instanceof vl&&c===n.x)return b=new vl(Z4(a,g)),c=GE(e),m=new Ql(b,new vl(m)),new Rl(!1,b,c,new Rl(!1,l,OS(m,e.nh),r5(a,b,k,d,e,g)));m=new Ql(b,new vl(m));return new Rl(!1,l,OS(m,e.nh),r5(a,b,k,d,e,g))}}}throw new w(c);};\nfunction s5(){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0;this.zk=this.Pq=this.Uq=this.xp=this.Bp=this.Cp=this.Sq=this.zp=this.Rq=this.wp=this.Ap=this.yp=this.Qq=this.Tq=null;this.Dp=0;this.hs=this.yq=this.Aq=this.Bq=this.zq=this.Dq=this.Cq=null;this.Im=this.Pw=0;this.iA=this.hA=this.Ku=null;this.Hb=!1;this.XA=0;this.YA=null}s5.prototype=new b3;s5.prototype.constructor=s5;function t5(){}t5.prototype=s5.prototype;\nfunction Ffa(a,b,c,d){var e=()=>{var l=Cfa(a,c);vE(xE(),l,new y(A=>{X4(a,A)}),\"Super-class map\",\"\\x3c:\");var m=Rca(xE(),l);vE(xE(),m,new y(A=>{X4(a,A)}),\"Sub-class map\",\":\\x3e\");var n=xfa(a,b,O().c);if(null===n)throw new w(n);var r=n.h(),v=n.j();n=Xu().X();if(a.Hb&&a.F){var x=ut(Q(),\"| \",a.r)+\"### Desugar the UCS to decision paths ###\";ff(gf(),x+\"\\n\")}r=yfa(a,r,v,c,d,n);a.Hb&&a.F&&(v=ut(Q(),\"| \",a.r)+\"Exhaustiveness map\",ff(gf(),v+\"\\n\"));n.b()?a.Hb&&a.F&&(v=ut(Q(),\"| \",a.r)+\"  * \\x3cNo entries\\x3e\",\nff(gf(),v+\"\\n\")):n.og(new fn((A,B)=>{a.Hb&&a.F&&(A=ut(Q(),\"| \",a.r)+\"  * Patterns of \"+A,ff(gf(),A+\"\\n\"));B.b()?a.Hb&&a.F&&(B=ut(Q(),\"| \",a.r)+\"    + \\x3cNo patterns\\x3e\",ff(gf(),B+\"\\n\")):B.og(new fn((C,D)=>{if(C instanceof fe)C=\"()^\"+(C.aa|0);else{if(!(C instanceof Ud))throw new w(C);C=Zz(C.fa,!1)}D=ze(D,\"[\",\", \",\"]\");a.Hb&&a.F&&(D=ut(Q(),\"| \",a.r)+(\"    + \"+C+\" -\\x3e \")+D,ff(gf(),D+\"\\n\"))}))}));a.Hb&&a.F&&(v=ut(Q(),\"| \",a.r)+\"### Build a case tree from decision paths ###\",ff(gf(),v+\"\\n\"));tp();\nn=n.m();n=pp(0,new Ef(n,new y(A=>{if(null!==A){var B=A.h();A=A.j();A=pp(tp().JK,A);return G(new H,B,A)}throw new w(A);})));l=Bfa(a,r,d,new y(A=>a5(a,A,c)),n,l);a.Hb&&a.F&&(r=ut(Q(),\"| \",a.r)+\"### Checking exhaustiveness of the case tree ###\",ff(gf(),r+\"\\n\"));zfa(a,l,t().d,c,d,n,m);a.Hb&&a.F&&(m=ut(Q(),\"| \",a.r)+\"### Construct a term from the case tree ###\",ff(gf(),m+\"\\n\"));m=Afa(a,l,c);a.F&&(l=ut(Q(),\"| \",a.r)+\"Desugared term: \"+Zz(m,!1),ff(gf(),l+\"\\n\"));b.oc=(t(),new L(m));return m},g=a.qa;if(a.Hb){if(a.F){var h=\nut(Q(),\"| \",a.r)+\"[desugarIf]\";ff(gf(),h+\"\\n\")}a.r=1+a.r|0;try{var k=e()}finally{a.r=-1+a.r|0}dx(new E(g),a.qa)&&a.F&&(e=\"\"+ut(Q(),\"| \",a.r)+g.n(k),ff(gf(),e+\"\\n\"))}else k=e();return k}function Gu(a,b){this.w=this.y=null;this.zF=a;this.oJ=b;G(this,null,null)}Gu.prototype=new h0;Gu.prototype.constructor=Gu;f=Gu.prototype;f.ut=function(){return this.zF};f.Sc=function(){return this.oJ};f.Cw=function(){return new Gu(this.oJ,this.zF)};f.iy=function(){return this.zF};f.j=function(){return this.oJ};\nf.h=function(){return this.zF};f.$classData=q({G0:0},!1,\"scala.Tuple2$mcII$sp\",{G0:1,by:1,g:1,LB:1,E:1,v:1,l:1,gba:1});function GG(a){this.tn=null;this.Al=this.wc=0;this.A4=a;Du(this,a)}GG.prototype=new u3;GG.prototype.constructor=GG;GG.prototype.t=function(){try{var a=this.A4.a[this.wc];this.wc=1+this.wc|0;var b=a}catch(c){if(c instanceof dI)b=Rq().Pa.t()|0;else throw c;}return b};\nGG.prototype.$classData=q({z4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcB$sp\",{z4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function FG(a){this.tn=null;this.Al=this.wc=0;this.C4=a;Du(this,a)}FG.prototype=new u3;FG.prototype.constructor=FG;FG.prototype.t=function(){try{var a=this.C4.a[this.wc];this.wc=1+this.wc|0;var b=a}catch(c){if(c instanceof dI)b=Ea(Rq().Pa.t());else throw c;}return hc(b)};\nFG.prototype.$classData=q({B4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcC$sp\",{B4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function CG(a){this.tn=null;this.Al=this.wc=0;this.E4=a;Du(this,a)}CG.prototype=new u3;CG.prototype.constructor=CG;CG.prototype.t=function(){try{var a=this.E4.a[this.wc];this.wc=1+this.wc|0;var b=a}catch(c){if(c instanceof dI)b=+Rq().Pa.t();else throw c;}return b};\nCG.prototype.$classData=q({D4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcD$sp\",{D4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function EG(a){this.tn=null;this.Al=this.wc=0;this.G4=a;Du(this,a)}EG.prototype=new u3;EG.prototype.constructor=EG;EG.prototype.t=function(){try{var a=this.G4.a[this.wc];this.wc=1+this.wc|0;var b=a}catch(c){if(c instanceof dI)b=Math.fround(Rq().Pa.t());else throw c;}return b};\nEG.prototype.$classData=q({F4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcF$sp\",{F4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function BG(a){this.tn=null;this.Al=this.wc=0;this.I4=a;Du(this,a)}BG.prototype=new u3;BG.prototype.constructor=BG;BG.prototype.t=function(){try{var a=this.I4.a[this.wc];this.wc=1+this.wc|0;var b=a}catch(c){if(c instanceof dI)b=Rq().Pa.t()|0;else throw c;}return b};\nBG.prototype.$classData=q({H4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcI$sp\",{H4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function DG(a){this.tn=null;this.Al=this.wc=0;this.K4=a;Du(this,a)}DG.prototype=new u3;DG.prototype.constructor=DG;DG.prototype.t=function(){try{var a=this.K4.a[this.wc],b=a.W,c=a.Y;this.wc=1+this.wc|0;var d=new ma(b,c)}catch(e){if(e instanceof dI)d=Za(Rq().Pa.t());else throw e;}return d};\nDG.prototype.$classData=q({J4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcJ$sp\",{J4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function HG(a){this.tn=null;this.Al=this.wc=0;this.M4=a;Du(this,a)}HG.prototype=new u3;HG.prototype.constructor=HG;HG.prototype.t=function(){try{var a=this.M4.a[this.wc];this.wc=1+this.wc|0;var b=a}catch(c){if(c instanceof dI)b=Rq().Pa.t()|0;else throw c;}return b};\nHG.prototype.$classData=q({L4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcS$sp\",{L4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function JG(a){this.tn=null;this.Al=this.wc=0;Du(this,a)}JG.prototype=new u3;JG.prototype.constructor=JG;JG.prototype.t=function(){try{this.wc=1+this.wc|0}catch(a){if(a instanceof dI)Rq().Pa.t();else throw a;}};JG.prototype.$classData=q({N4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcV$sp\",{N4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});\nfunction IG(a){this.tn=null;this.Al=this.wc=0;this.P4=a;Du(this,a)}IG.prototype=new u3;IG.prototype.constructor=IG;IG.prototype.t=function(){try{var a=this.P4.a[this.wc];this.wc=1+this.wc|0;var b=a}catch(c){if(c instanceof dI)b=!!Rq().Pa.t();else throw c;}return b};IG.prototype.$classData=q({O4:0},!1,\"scala.collection.ArrayOps$ArrayIterator$mcZ$sp\",{O4:1,Qp:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function CQ(a){this.WK=a}CQ.prototype=new q3;CQ.prototype.constructor=CQ;f=CQ.prototype;f.m=function(){Rq();return new g0(this.WK)};\nf.Q=function(){return 1};f.e=function(){return this.WK};f.Mc=function(){return this.WK};f.Bb=function(a){return 0<a?DK().X():this};f.Jc=function(a){return 0<a?DK().X():this};f.$classData=q({a5:0},!1,\"scala.collection.Iterable$$anon$1\",{a5:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1});function u5(a,b){if(a.b())throw nv(\"empty.min\");var c=a.se();return(null===b?null===c:b.i(c))?a.e():b.sj(a.se())?a.Mc():gH(a,b)}\nfunction v5(a,b){if(a.b())throw nv(\"empty.max\");var c=a.se();return(null===b?null===c:b.i(c))?a.Mc():b.sj(a.se())?a.e():hH(a,b)}function w5(a){return a.Ih()+\"(\\x3cnot computed\\x3e)\"}function x5(a,b){for(b=b.m();b.s();){var c=b.t();a=a.xj(c)}return a}function y5(a,b,c){var d=a.U(b);c=c.n(d);d=G(new H,d,c);c=d.y;var e=d.w;if(R()===c&&R()===e)return a;c=d.w;if(d.y instanceof L&&R()===c)return a.xj(b);c=d.w;if(c instanceof L)return a.Em(b,c.k);throw new w(d);}\nfunction z5(a){this.Dn=this.Io=0;this.BS=null;if(null===a)throw null;this.BS=a;this.Io=0;this.Dn=2}z5.prototype=new h4;z5.prototype.constructor=z5;z5.prototype.va=function(a){a:{var b=this.BS;switch(a){case 0:a=b.Zt;break a;case 1:a=b.jw;break a;default:throw new w(a);}}return a};z5.prototype.$classData=q({n8:0},!1,\"scala.collection.immutable.Set$Set2$$anon$1\",{n8:1,ES:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});\nfunction A5(a){this.Dn=this.Io=0;this.CS=null;if(null===a)throw null;this.CS=a;this.Io=0;this.Dn=3}A5.prototype=new h4;A5.prototype.constructor=A5;A5.prototype.va=function(a){a:{var b=this.CS;switch(a){case 0:a=b.Qr;break a;case 1:a=b.$t;break a;case 2:a=b.au;break a;default:throw new w(a);}}return a};A5.prototype.$classData=q({p8:0},!1,\"scala.collection.immutable.Set$Set3$$anon$2\",{p8:1,ES:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});\nfunction B5(a){this.Dn=this.Io=0;this.DS=null;if(null===a)throw null;this.DS=a;this.Io=0;this.Dn=4}B5.prototype=new h4;B5.prototype.constructor=B5;B5.prototype.va=function(a){return Gfa(this.DS,a)};B5.prototype.$classData=q({r8:0},!1,\"scala.collection.immutable.Set$Set4$$anon$3\",{r8:1,ES:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function uV(a){this.bH=null;this.Uk=a;this.cu=null}uV.prototype=new eR;uV.prototype.constructor=uV;f=uV.prototype;f.he=function(){};f.Kb=function(){return tV(new sV,qJ(this.cu),this.Uk)};\nf.zc=function(a){a:{if(a instanceof sV){var b=a.We,c=this.Uk;if(null===b?null===c:b.i(c)){this.cu=null===this.cu?a.Jd:mJ(nJ(),qJ(this.cu),a.Jd,this.Uk);break a}}a&&a.$classData&&a.$classData.rb.Mk?(null===this.bH&&null===this.bH&&(this.bH=new yV(this)),b=this.bH,b.Yy=b.aH.cu,a.og(b),b.aH.cu=b.Yy,b.Yy=null):lR(this,a)}return this};f.$=function(a){this.cu=fR(this,this.cu,a.h(),a.j());return this};\nf.$classData=q({J8:0},!1,\"scala.collection.immutable.TreeMap$TreeMapBuilder\",{J8:1,e8:1,yS:1,g:1,Po:1,xg:1,xf:1,wf:1});function wZ(a){this.Uk=a;this.Sr=null}wZ.prototype=new hR;wZ.prototype.constructor=wZ;f=wZ.prototype;f.he=function(){};f.Kb=function(){return sZ(new rZ,qJ(this.Sr),this.Uk)};\nf.zc=function(a){a:{if(a instanceof rZ){var b=a.Xe,c=this.Uk;if(null===b?null===c:b.i(c)){this.Sr=null===this.Sr?a.Hf:mJ(nJ(),qJ(this.Sr),a.Hf,this.Uk);break a}}if(a instanceof sV&&(b=a.We,c=this.Uk,null===b?null===c:b.i(c))){this.Sr=null===this.Sr?a.Jd:mJ(nJ(),qJ(this.Sr),a.Jd,this.Uk);break a}lR(this,a)}return this};f.$=function(a){this.Sr=iR(this,this.Sr,a);return this};f.$classData=q({N8:0},!1,\"scala.collection.immutable.TreeSet$TreeSetBuilder\",{N8:1,Rba:1,yS:1,g:1,Po:1,xg:1,xf:1,wf:1});\nfunction o4(a){this.MS=!1;this.QL=null;this.qC=a;this.MS=a===da(td);this.QL=[]}o4.prototype=new l4;o4.prototype.constructor=o4;function C5(a,b){a.QL.push(a.MS?Ea(b):null===b?a.qC.qi.jz:b);return a}f=o4.prototype;f.Kb=function(){return md((this.qC===da(pd)?da(la):this.qC===da(jH)||this.qC===da(kH)?da(jd):this.qC).qi).iz(this.QL)};f.u=function(){return\"ArrayBuilder.generic\"};f.zc=function(a){for(a=a.m();a.s();){var b=a.t();C5(this,b)}return this};f.$=function(a){return C5(this,a)};\nf.$classData=q({g9:0},!1,\"scala.collection.mutable.ArrayBuilder$generic\",{g9:1,Uba:1,g:1,Po:1,xg:1,xf:1,wf:1,l:1});\nfunction D5(a,b,c,d){var e=1+wG(xG(),b)|0;if(0>c||c>=e)throw aL(new bL,c+\" is out of bounds (min 0, max \"+(-1+e|0)+\")\");e=(a.Ke-a.Zd|0)&(-1+a.ec.a.length|0)|0;var g=wG(xG(),b)-c|0;e=e<g?e:g;d=d<e?d:e;if(0<d){e=(a.Ke-a.Zd|0)&(-1+a.ec.a.length|0);if(0>=e)throw aL(new bL,\"0 is out of bounds (min 0, max \"+(-1+e|0)+\")\");e=(a.Zd+0|0)&(-1+a.ec.a.length|0);g=a.ec.a.length-e|0;g=d<g?d:g;VG(SG(),a.ec,e,b,c,g);d=d-g|0;0<d&&VG(SG(),a.ec,0,b,c+g|0,d)}return b}\nfunction E5(a,b){this.UK=null;this.PS=this.bk=this.Er=0;this.x9=b;Kr(this,a);this.PS=Es(b)|0}E5.prototype=new v3;E5.prototype.constructor=E5;E5.prototype.s=function(){mK();var a=this.PS,b=Es(this.x9)|0;jK(a,b);return 0<this.bk};E5.prototype.$classData=q({w9:0},!1,\"scala.collection.mutable.CheckedIndexedSeqView$CheckedIterator\",{w9:1,CR:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function F5(a,b){this.VK=null;this.QS=this.Kv=this.zj=0;this.z9=b;uZ(this,a);this.QS=Es(b)|0}F5.prototype=new w3;\nF5.prototype.constructor=F5;F5.prototype.s=function(){mK();var a=this.QS,b=Es(this.z9)|0;jK(a,b);return 0<this.zj};F5.prototype.$classData=q({y9:0},!1,\"scala.collection.mutable.CheckedIndexedSeqView$CheckedReverseIterator\",{y9:1,DR:1,Sa:1,g:1,Ka:1,M:1,N:1,l:1});function G5(){}G5.prototype=new p;G5.prototype.constructor=G5;f=G5.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};\nf.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){a=!!a;return a===!!b?0:a?1:-1};f.$classData=q({H3:0},!1,\"scala.math.Ordering$Boolean$\",{H3:1,g:1,sba:1,lm:1,Ji:1,mm:1,km:1,l:1});var H5;function PG(){H5||(H5=new G5);return H5}function I5(){}I5.prototype=new p;I5.prototype.constructor=I5;f=I5.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};\nf.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){return(a|0)-(b|0)|0};f.$classData=q({I3:0},!1,\"scala.math.Ordering$Byte$\",{I3:1,g:1,tba:1,lm:1,Ji:1,mm:1,km:1,l:1});var J5;function NG(){J5||(J5=new I5);return J5}function K5(){}K5.prototype=new p;K5.prototype.constructor=K5;f=K5.prototype;\nf.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){return Ea(a)-Ea(b)|0};f.$classData=q({J3:0},!1,\"scala.math.Ordering$Char$\",{J3:1,g:1,vba:1,lm:1,Ji:1,mm:1,km:1,l:1});var L5;function MG(){L5||(L5=new K5);return L5}function M5(){}M5.prototype=new p;\nM5.prototype.constructor=M5;f=M5.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){var c=Za(a);a=c.W;c=c.Y;var d=Za(b);b=d.W;d=d.Y;return ua(xa(),a,c,b,d)};\nf.$classData=q({M3:0},!1,\"scala.math.Ordering$Long$\",{M3:1,g:1,wba:1,lm:1,Ji:1,mm:1,km:1,l:1});var N5;function LG(){N5||(N5=new M5);return N5}function O5(){}O5.prototype=new p;O5.prototype.constructor=O5;f=O5.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};f.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};\nf.Da=function(a,b){return(a|0)-(b|0)|0};f.$classData=q({O3:0},!1,\"scala.math.Ordering$Short$\",{O3:1,g:1,xba:1,lm:1,Ji:1,mm:1,km:1,l:1});var P5;function OG(){P5||(P5=new O5);return P5}function Q5(){}Q5.prototype=new p;Q5.prototype.constructor=Q5;f=Q5.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};\nf.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){return pa(a,b)};f.$classData=q({P3:0},!1,\"scala.math.Ordering$String$\",{P3:1,g:1,yba:1,lm:1,Ji:1,mm:1,km:1,l:1});var R5;function cT(){R5||(R5=new Q5);return R5}function S5(){this.Ki=null;this.Gf=0}S5.prototype=new p;S5.prototype.constructor=S5;function T5(){}T5.prototype=S5.prototype;S5.prototype.u=function(){return this.Ki};S5.prototype.D=function(a){return a instanceof S5};\nS5.prototype.i=function(a){return this===a};S5.prototype.B=function(){return this.Gf};function U5(){}U5.prototype=new p;U5.prototype.constructor=U5;function V5(){}V5.prototype=U5.prototype;U5.prototype.D=function(a){return!!(a&&a.$classData&&a.$classData.rb.om)};\nclass $d extends iW{constructor(a){super();this.mu=a;yF(this,null,null,!0)}qj(){return nb(this.mu)}H(){return\"JavaScriptException\"}G(){return 1}I(a){return 0===a?this.mu:$K(W(),a)}D(a){return a instanceof $d}B(){return AL(this)}i(a){if(this===a)return!0;if(a instanceof $d){var b=this.mu;a=a.mu;return ml(nl(),b,a)}return!1}}$d.prototype.$classData=q({L$:0},!1,\"scala.scalajs.js.JavaScriptException\",{L$:1,Te:1,qd:1,pc:1,g:1,l:1,E:1,v:1});function Zg(a){this.f1=a;this.PF=\"\"}Zg.prototype=new L4;\nZg.prototype.constructor=Zg;function ff(a,b){for(;\"\"!==b;){var c=b.indexOf(\"\\n\")|0;if(0>c)a.PF=\"\"+a.PF+b,b=\"\";else{var d=\"\"+a.PF+b.substring(0,c);\"undefined\"!==typeof console&&(a.f1&&console.error?console.error(d):console.log(d));a.PF=\"\";b=b.substring(1+c|0)}}}Zg.prototype.$classData=q({e1:0},!1,\"java.lang.JSConsoleBasedPrintStream\",{e1:1,uaa:1,saa:1,taa:1,g:1,yT:1,R0:1,zT:1,rQ:1});function Vw(a,b,c,d,e){this.Iu=null;this.ij=b;this.ig=c;this.bo=d;this.Tz=e;if(null===a)throw null;this.Iu=a}\nVw.prototype=new p;Vw.prototype.constructor=Vw;f=Vw.prototype;f.Mp=function(){return this.bo};f.Ea=function(){return this.Tz};f.Ua=function(){return this.ij.Ua()};f.fd=function(){return this.ij instanceof Ep?Ap():hx()};f.A=function(){return this.ij.A()};f.tr=function(){return!0};f.Nn=function(){return this.ig.ra};f.H=function(){return\"NuParam\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.ij;case 1:return this.ig;case 2:return this.bo;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof Vw};f.B=function(){var a=lb(\"NuParam\");a=W().C(-889275714,a);var b=this.ij;b=My(W(),b);a=W().C(a,b);b=this.ig;b=My(W(),b);a=W().C(a,b);b=this.bo?1231:1237;a=W().C(a,b);return W().Ma(a,3)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Vw&&a.Iu===this.Iu){if(this.bo===a.bo){var b=this.ij,c=a.ij;b=null===b?null===c:b.i(c)}else b=!1;if(b)return b=this.ig,a=a.ig,null===b?null===a:b.i(a)}return!1};f.bG=function(){return this.Iu};\nf.cm=function(a,b){var c=this.Iu,d=this.ij,e=this.ig,g=e.Va,h=e.Oa;h.b()?h=R():(h=h.o(),h=new L(b.ba(new UB(a),h)));return new Vw(c,d,new Uw(g,h,b.ba(a,e.ra),e.Pd),this.bo,this.Tz)};f.yl=function(a,b,c){b=this.Iu;var d=this.ij,e=this.ig,g=e.Va,h=e.Oa;if(h.b())h=R();else{h=h.o();if(a.b())var k=R();else k=!!a.o(),k=new L(!k);h=new L(c.ba(k,h))}return new Vw(b,d,new Uw(g,h,c.ba(a,e.ra),e.Pd),this.bo,this.Tz)};f.ro=function(a,b,c,d){return new Vw(this.Iu,this.ij,LX(this.ig,a,b,c,d),this.bo,c.da)};\nf.$classData=q({wX:0},!1,\"mlscript.NuTypeDefs$NuParam\",{wX:1,g:1,nx:1,xE:1,Rs:1,TN:1,E:1,v:1,l:1});function Hfa(a){if(!a.SH){var b=a.Ei,c=a.gh,d=k=>{if(null!==k){var l=k.kc,m=k.hb;if(null!==l){k=a.Rf.gb.V+\"#\"+l.V;var n=a.nc,r=a.nc;t();l=new Vw(n,l,new Uw(r,new L(m),m,V(a.nc)),!0,a.Sm);return G(new H,k,l)}}throw new w(k);};if(c===u())d=u();else{var e=c.e(),g=e=new z(d(e),u());for(c=c.f();c!==u();){var h=c.e();h=new z(d(h),u());g=g.p=h;c=c.f()}d=e}a.TH=b.bf(d).bf(a.Tm);a.SH=!0}return a.TH}\nfunction Yw(a,b,c,d,e,g,h,k,l,m,n){this.RH=this.TH=this.nc=this.px=null;this.SH=!1;this.Sm=b;this.Rf=c;this.gh=d;this.Ij=e;this.gl=g;this.Ei=h;this.Um=k;this.sk=l;this.ip=m;this.Tm=n;MS(this,a,Bp());this.RH=t().d}Yw.prototype=new NS;Yw.prototype.constructor=Yw;f=Yw.prototype;f.Ea=function(){return this.Sm};f.Yr=function(){return this.Rf};f.Ag=function(){return this.gh};f.aG=function(){return this.Ei};f.fd=function(){return this.Rf.pb};f.cG=function(){return this.Rf.gb};f.Ua=function(){return this.Rf.gb.V};\nf.tr=function(){return!0};f.Mp=function(){return!0};f.LC=function(){return this.SH?this.TH:Hfa(this)};\nfunction Ay(a,b){var c=a.RH;if(c instanceof L)return c.k;if(t().d===c){c=a.nc;var d=new y(r=>\"\\x3d \"+r);if(c.F){var e=ut(Q(),\"| \",c.r)+\"Computing variances of \"+a.Rf.gb.V;ff(gf(),e+\"\\n\")}c.r=1+c.r|0;try{var g=new $e;ofa(a.nc);var h=Xu().X(),k=jA().X();a.Ei.og(new fn((r,v)=>{if(!(v instanceof Vw&&v.ij instanceof Ep)){r=ID;if(g.sb)var x=g.vb;else{if(null===g)throw le();x=g.sb?g.vb:me(g,new LS(a,b,k,h))}r(x,gA(a.nc).Pj,v)}}));var l=a.gh.m(),m=h.bf(new Ex(l,new L_(a)));a.RH=(t(),new L(m));var n=m}finally{c.r=\n-1+c.r|0}dx(new E(d),c.qa)&&c.F&&(l=\"\"+ut(Q(),\"| \",c.r)+d.n(n),ff(gf(),l+\"\\n\"));return n}throw new w(c);}function RA(a,b,c){return Ay(a,c).Se(b,new U(()=>ou().Yl))}\nfunction Zw(a,b,c,d,e){var g=new Iw(d.S,d.Ec,d.hc,d.Ed,1+d.da|0,d.Pc,d.Zc,d.Lb,d.yc,d.tb,d.$a,d.od,d.cb),h=a.nc;d=d.da;var k=a.Rf,l=a.gh,m=B=>{var C=B.kc,D=B.hb.Kc(b,c,g,e);return new tl(C,hD(D),B.Rd)};if(l===u())m=u();else{var n=l.e(),r=n=new z(m(n),u());for(l=l.f();l!==u();){var v=l.e();v=new z(m(v),u());r=r.p=v;l=l.f()}m=n}n=a.Ij;n.b()?n=R():(n=n.o(),n=new L(ry(lv(),n,new y(B=>LX(B,b,c,g,e)))));r=a.gl;r.b()?r=R():(r=r.o(),r=new L(ry(lv(),r,new y(B=>B.Kc(b,c,g,e)))));l=KF(lv(),a.Ei,new y(B=>B.ro(b,\nc,g,e)));op();l=pp(qp(),l);v=a.Um.Kc(b,c,g,e);var x=a.sk.Kc(b,c,g,e),A=a.ip;a=KF(lv(),a.Tm,new y(B=>B.ro(b,c,g,e)));op();return new Yw(h,d,k,m,n,r,l,v,x,A,pp(qp(),a))}\nfunction Ifa(a,b,c,d,e){var g=a.nc,h=a.Sm,k=a.Rf,l=a.gh,m=B=>{var C=B.kc,D=d.ba(t().d,B.hb);return new tl(C,hD(D),B.Rd)};if(l===u())m=u();else{var n=l.e(),r=n=new z(m(n),u());for(l=l.f();l!==u();){var v=l.e();v=new z(m(v),u());r=r.p=v;l=l.f()}m=n}n=a.Ij;n.b()?n=R():(n=n.o(),n=new L(ry(lv(),n,new y(B=>{var C=B.Va,D=B.Oa;if(D.b())D=R();else{D=D.o();if(b.b())var F=R();else F=!!b.o(),F=new L(!F);D=new L(d.ba(F,D))}return new Uw(C,D,d.ba(b,B.ra),B.Pd)}))));r=a.gl;r.b()?r=R():(r=r.o(),r=new L(ry(lv(),r,\nnew y(B=>{if(b.b())var C=R();else C=!!b.o(),C=new L(!C);return d.ba(C,B)}))));l=KF(lv(),a.Ei,new y(B=>B.yl(b,c,d,e)));op();l=pp(qp(),l);b.b()?v=R():(v=!!b.o(),v=new L(!v));v=d.ba(v,a.Um);var x=d.ba(b,a.sk),A=a.ip;a=KF(lv(),a.Tm,new y(B=>B.yl(b,c,d,e)));op();return new Yw(g,h,k,m,n,r,l,v,x,A,pp(qp(),a))}\nfunction Jfa(a,b,c,d){var e=a.nc,g=a.Sm,h=a.Rf,k=a.gh,l=A=>{var B=A.kc,C=c.ba(new TB(b),A.hb);return new tl(B,hD(C),A.Rd)};if(k===u())l=u();else{var m=k.e(),n=m=new z(l(m),u());for(k=k.f();k!==u();){var r=k.e();r=new z(l(r),u());n=n.p=r;k=k.f()}l=m}m=a.Ij;m.b()?m=R():(m=m.o(),m=new L(ry(lv(),m,new y(A=>{var B=A.Va,C=A.Oa;C.b()?C=R():(C=C.o(),C=new L(c.ba(new UB(b),C)));return new Uw(B,C,c.ba(b,A.ra),A.Pd)}))));n=a.gl;n.b()?n=R():(n=n.o(),n=new L(ry(lv(),n,new y(A=>c.ba(new UB(b),A)))));k=KF(lv(),\na.Ei,new y(A=>A.cm(b,c,d)));op();k=pp(qp(),k);r=c.ba(new UB(b),a.Um);var v=c.ba(b,a.sk),x=a.ip;a=KF(lv(),a.Tm,new y(A=>A.cm(b,c,d)));op();return new Yw(e,g,h,l,m,n,k,r,v,x,pp(qp(),a))}f.u=function(){var a=this.Ei;return\"TypedNuCls(\"+this.Sm+\", \"+this.Rf.gb+\",\\n\\t\"+this.gh+\",\\n\\t\"+this.Ij+\",\\n\\tthis: \"+this.Um+\", \"+CF(GF(),a)+\",\\n\\t: \"+this.sk+\", \"+this.ip+\", \"+this.Tm+\")\"};f.H=function(){return\"TypedNuCls\"};f.G=function(){return 10};\nf.I=function(a){switch(a){case 0:return this.Sm;case 1:return this.Rf;case 2:return this.gh;case 3:return this.Ij;case 4:return this.gl;case 5:return this.Ei;case 6:return this.Um;case 7:return this.sk;case 8:return this.ip;case 9:return this.Tm;default:return $K(W(),a)}};f.D=function(a){return a instanceof Yw};\nf.B=function(){var a=lb(\"TypedNuCls\");a=W().C(-889275714,a);var b=this.Sm;a=W().C(a,b);b=this.Rf;b=My(W(),b);a=W().C(a,b);b=this.gh;b=My(W(),b);a=W().C(a,b);b=this.Ij;b=My(W(),b);a=W().C(a,b);b=this.gl;b=My(W(),b);a=W().C(a,b);b=this.Ei;b=My(W(),b);a=W().C(a,b);b=this.Um;b=My(W(),b);a=W().C(a,b);b=this.sk;b=My(W(),b);a=W().C(a,b);b=this.ip;b=My(W(),b);a=W().C(a,b);b=this.Tm;b=My(W(),b);a=W().C(a,b);return W().Ma(a,10)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Yw&&a.nc===this.nc){if(this.Sm===a.Sm){var b=this.Rf,c=a.Rf;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.gh,c=a.gh,(null===b?null===c:b.i(c))?(b=this.Ij,c=a.Ij,(null===b?null===c:b.i(c))?(b=this.gl,c=a.gl,b=null===b?null===c:b.i(c)):b=!1):b=!1):b=!1;if(b&&(b=this.Ei,c=a.Ei,(null===b?null===c:b.i(c))?(b=this.Um,c=a.Um,(null===b?null===c:mC(b,c))?(b=this.sk,c=a.sk,b=null===b?null===c:mC(b,c)):b=!1):b=!1,b&&(b=this.ip,c=a.ip,null===b?null===c:b.i(c))))return b=\nthis.Tm,a=a.Tm,null===b?null===a:b.i(a)}return!1};f.cm=function(a,b,c){return Jfa(this,a,b,c)};f.yl=function(a,b,c,d){return Ifa(this,a,b,c,d)};f.ro=function(a,b,c,d){return Zw(this,a,b,c,d)};f.$classData=q({AX:0},!1,\"mlscript.NuTypeDefs$TypedNuCls\",{AX:1,YH:1,g:1,Rs:1,nx:1,HN:1,E:1,v:1,l:1});function cx(a,b){this.ox=null;this.wE=b;if(null===a)throw null;this.ox=a}cx.prototype=new p;cx.prototype.constructor=cx;f=cx.prototype;f.Ea=function(){return this.ox.Gd};f.fd=function(){return hx()};f.A=function(){return t().d};\nf.Ua=function(){return this.wE.Cf.x};f.tr=function(){return!0};f.Mp=function(){return!0};f.Nn=function(){return Ey(this.ox)};f.H=function(){return\"TypedNuDummy\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.wE:$K(W(),a)};f.D=function(a){return a instanceof cx};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof cx&&a.ox===this.ox){var b=this.wE;a=a.wE;return null===b?null===a:b.i(a)}return!1};f.bG=function(){return this.ox};\nf.cm=function(){return this};f.yl=function(){return this};f.ro=function(){return this};f.$classData=q({DX:0},!1,\"mlscript.NuTypeDefs$TypedNuDummy\",{DX:1,g:1,Rs:1,nx:1,xE:1,TN:1,E:1,v:1,l:1});function bx(a,b,c,d,e){this.MN=this.LN=null;this.Ss=0;this.Sl=null;this.jp=b;this.Mb=c;this.hh=d;this.Ts=e;if(null===a)throw null;this.Sl=a}bx.prototype=new p;bx.prototype.constructor=bx;f=bx.prototype;f.Ea=function(){return this.jp};f.tr=function(){return this.Ts};f.fd=function(){return hx()};f.Ua=function(){return this.Mb.Rb.x};\nf.A=function(){return this.Mb.A()};f.ma=function(){0===(1&this.Ss)<<24>>24&&0===(1&this.Ss)<<24>>24&&(this.LN=jx(new kx,this.Sl,this.Mb.A(),\"member\",(tx(this.Sl),t().d),(tx(this.Sl),!1)),this.Ss=(1|this.Ss)<<24>>24);return this.LN};f.Mp=function(){return!rx(this.Mb)};f.Nn=function(){0===(2&this.Ss)<<24>>24&&0===(2&this.Ss)<<24>>24&&(this.MN=this.Mb.Om.b()?yx(zx(this.Sl),this.jp,this.hh):this.hh,this.Ss=(2|this.Ss)<<24>>24);return this.MN};\nfunction Iy(a){var b=a.Mb.Yc;b instanceof fe?a=Vy(a.Sl,b.aa):(a=a.Sl,null===a.Ku&&null===a.Ku&&(a.Ku=new WO(a)),a=a.Ku,a.OH||a.OH||(a.JN=new XX(a.IN,t().d,ap()),a.OH=!0),a=a.JN);return a}f.H=function(){return\"TypedNuFun\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.jp;case 1:return this.Mb;case 2:return this.hh;default:return $K(W(),a)}};f.D=function(a){return a instanceof bx};\nf.B=function(){var a=lb(\"TypedNuFun\");a=W().C(-889275714,a);var b=this.jp;a=W().C(a,b);b=this.Mb;b=My(W(),b);a=W().C(a,b);b=this.hh;b=My(W(),b);a=W().C(a,b);return W().Ma(a,3)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof bx&&a.Sl===this.Sl){if(this.jp===a.jp){var b=this.Mb,c=a.Mb;b=null===b?null===c:b.i(c)}else b=!1;if(b)return b=this.hh,a=a.hh,null===b?null===a:mC(b,a)}return!1};f.bG=function(){return this.Sl};\nf.cm=function(a,b){return new bx(this.Sl,this.jp,this.Mb,b.ba(a,this.hh),this.Ts)};f.yl=function(a,b,c){return new bx(this.Sl,this.jp,this.Mb,c.ba(a,this.hh),this.Ts)};f.ro=function(a,b,c,d){var e=new Iw(c.S,c.Ec,c.hc,c.Ed,1+c.da|0,c.Pc,c.Zc,c.Lb,c.yc,c.tb,c.$a,c.od,c.cb);return new bx(this.Sl,c.da,this.Mb,this.hh.Kc(a,b,e,d),this.Ts)};f.$classData=q({EX:0},!1,\"mlscript.NuTypeDefs$TypedNuFun\",{EX:1,g:1,Rs:1,nx:1,xE:1,TN:1,E:1,v:1,l:1});\nfunction Kfa(a){if(!a.UH){var b=a.Jj,c=a.kl,d=k=>{if(null!==k){var l=k.kc,m=k.hb;if(null!==l){k=a.il.gb.V+\"#\"+l.V;var n=a.nc,r=a.nc;t();l=new Vw(n,l,new Uw(r,new L(m),m,V(a.nc)),!1,a.Fq);return G(new H,k,l)}}throw new w(k);};if(c===u())d=u();else{var e=c.e(),g=e=new z(d(e),u());for(c=c.f();c!==u();){var h=c.e();h=new z(d(h),u());g=g.p=h;c=c.f()}d=e}a.VH=b.bf(d);a.UH=!0}return a.VH}\nfunction Nw(a,b,c,d,e,g,h,k){this.VH=this.nc=this.px=null;this.UH=!1;this.Fq=b;this.il=c;this.jl=d;this.hl=e;this.kl=g;this.Tl=h;this.Jj=k;MS(this,a,cp())}Nw.prototype=new NS;Nw.prototype.constructor=Nw;f=Nw.prototype;f.Ea=function(){return this.Fq};f.Yr=function(){return this.il};f.Ag=function(){return this.kl};f.aG=function(){return this.Jj};f.fd=function(){return this.il.pb};f.cG=function(){return this.il.gb};f.Ua=function(){return this.il.gb.V};f.tr=function(){return!0};f.Mp=function(){return!0};\nf.LC=function(){return this.UH?this.VH:Kfa(this)};\nfunction Qw(a,b,c,d,e){var g=new Iw(d.S,d.Ec,d.hc,d.Ed,1+d.da|0,d.Pc,d.Zc,d.Lb,d.yc,d.tb,d.$a,d.od,d.cb),h=a.nc;d=d.da;var k=a.il,l=a.jl.Kc(b,c,g,e),m=a.hl.Kc(b,c,g,e),n=a.kl,r=B=>{var C=B.kc,D=B.hb.Kc(b,c,g,e);return new tl(C,hD(D),B.Rd)};if(n===u())r=u();else{var v=n.e(),x=v=new z(r(v),u());for(n=n.f();n!==u();){var A=n.e();A=new z(r(A),u());x=x.p=A;n=n.f()}r=v}v=ry(lv(),a.Tl,new y(B=>LX(B,b,c,g,e)));a=KF(lv(),a.Jj,new y(B=>B.ro(b,c,g,e)));op();return new Nw(h,d,k,l,m,r,v,pp(qp(),a))}\nfunction Lfa(a,b,c,d,e){var g=a.nc,h=a.Fq,k=a.il;if(b.b())var l=R();else l=!!b.o(),l=new L(!l);l=d.ba(l,a.jl);if(b.b())var m=R();else m=!!b.o(),m=new L(!m);m=d.ba(m,a.hl);var n=a.kl,r=B=>{var C=B.kc,D=d.ba(t().d,B.hb);return new tl(C,hD(D),B.Rd)};if(n===u())r=u();else{var v=n.e(),x=v=new z(r(v),u());for(n=n.f();n!==u();){var A=n.e();A=new z(r(A),u());x=x.p=A;n=n.f()}r=v}v=ry(lv(),a.Tl,new y(B=>{var C=B.Va,D=B.Oa;if(D.b())D=R();else{D=D.o();if(b.b())var F=R();else F=!!b.o(),F=new L(!F);D=new L(d.ba(F,\nD))}return new Uw(C,D,d.ba(b,B.ra),B.Pd)}));a=KF(lv(),a.Jj,new y(B=>B.yl(b,c,d,e)));op();return new Nw(g,h,k,l,m,r,v,pp(qp(),a))}\nfunction Mfa(a,b,c,d){var e=a.nc,g=a.Fq,h=a.il,k=c.ba(new UB(b),a.jl),l=c.ba(new UB(b),a.hl),m=a.kl,n=A=>{var B=A.kc,C=c.ba(new TB(b),A.hb);return new tl(B,hD(C),A.Rd)};if(m===u())n=u();else{var r=m.e(),v=r=new z(n(r),u());for(m=m.f();m!==u();){var x=m.e();x=new z(n(x),u());v=v.p=x;m=m.f()}n=r}r=ry(lv(),a.Tl,new y(A=>{var B=A.Va,C=A.Oa;C.b()?C=R():(C=C.o(),C=new L(c.ba(new UB(b),C)));return new Uw(B,C,c.ba(b,A.ra),A.Pd)}));a=KF(lv(),a.Jj,new y(A=>A.cm(b,c,d)));op();return new Nw(e,g,h,k,l,n,r,pp(qp(),\na))}f.u=function(){var a=this.Jj;return\"TypedNuMxn(\"+this.Fq+\", \"+this.il.gb+\",\\n\\tthis: \"+this.jl+\",\\n\\tsuper: \"+this.hl+\",\\n\\ttparams: \"+this.kl+\",\\n\\tparams: \"+this.Tl+\",\\n\\tmembers: \"+CF(GF(),a)+\"\\n)\"};f.H=function(){return\"TypedNuMxn\"};f.G=function(){return 7};f.I=function(a){switch(a){case 0:return this.Fq;case 1:return this.il;case 2:return this.jl;case 3:return this.hl;case 4:return this.kl;case 5:return this.Tl;case 6:return this.Jj;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof Nw};f.B=function(){var a=lb(\"TypedNuMxn\");a=W().C(-889275714,a);var b=this.Fq;a=W().C(a,b);b=this.il;b=My(W(),b);a=W().C(a,b);b=this.jl;b=My(W(),b);a=W().C(a,b);b=this.hl;b=My(W(),b);a=W().C(a,b);b=this.kl;b=My(W(),b);a=W().C(a,b);b=this.Tl;b=My(W(),b);a=W().C(a,b);b=this.Jj;b=My(W(),b);a=W().C(a,b);return W().Ma(a,7)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Nw&&a.nc===this.nc){if(this.Fq===a.Fq){var b=this.il,c=a.il;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.jl,c=a.jl,(null===b?null===c:mC(b,c))?(b=this.hl,c=a.hl,b=null===b?null===c:mC(b,c)):b=!1):b=!1;if(b&&(b=this.kl,c=a.kl,(null===b?null===c:b.i(c))?(b=this.Tl,c=a.Tl,b=null===b?null===c:b.i(c)):b=!1,b))return b=this.Jj,a=a.Jj,null===b?null===a:b.i(a)}return!1};f.cm=function(a,b,c){return Mfa(this,a,b,c)};\nf.yl=function(a,b,c,d){return Lfa(this,a,b,c,d)};f.ro=function(a,b,c,d){return Qw(this,a,b,c,d)};f.$classData=q({FX:0},!1,\"mlscript.NuTypeDefs$TypedNuMxn\",{FX:1,YH:1,g:1,Rs:1,nx:1,HN:1,E:1,v:1,l:1});\nfunction Nfa(a){if(!a.WH){var b=a.tk,c=a.wk,d=k=>{if(null!==k){var l=k.kc,m=k.hb;if(null!==l){k=a.vk.gb.V+\"#\"+l.V;var n=a.nc,r=a.nc;t();l=new Vw(n,l,new Uw(r,new L(m),m,V(a.nc)),!0,a.Hq);return G(new H,k,l)}}throw new w(k);};if(c===u())d=u();else{var e=c.e(),g=e=new z(d(e),u());for(c=c.f();c!==u();){var h=c.e();h=new z(d(h),u());g=g.p=h;c=c.f()}d=e}a.XH=b.bf(d).bf(a.Vm);a.WH=!0}return a.XH}\nfunction Ww(a,b,c,d,e,g,h,k,l){this.XH=this.nc=this.px=null;this.WH=!1;this.Hq=b;this.vk=c;this.wk=d;this.tk=e;this.co=g;this.uk=h;this.Gq=k;this.Vm=l;MS(this,a,Fp())}Ww.prototype=new NS;Ww.prototype.constructor=Ww;f=Ww.prototype;f.Ea=function(){return this.Hq};f.Yr=function(){return this.vk};f.Ag=function(){return this.wk};f.aG=function(){return this.tk};f.fd=function(){return this.vk.pb};f.cG=function(){return this.vk.gb};f.Ua=function(){return this.vk.gb.V};f.tr=function(){return!0};f.Mp=function(){return!0};\nf.LC=function(){return this.WH?this.XH:Nfa(this)};\nfunction Xw(a,b,c,d,e){var g=new Iw(d.S,d.Ec,d.hc,d.Ed,1+d.da|0,d.Pc,d.Zc,d.Lb,d.yc,d.tb,d.$a,d.od,d.cb),h=a.nc;d=d.da;var k=a.vk,l=a.wk,m=x=>{var A=x.kc,B=x.hb.Kc(b,c,g,e);return new tl(A,hD(B),x.Rd)};if(l===u())m=u();else{var n=l.e(),r=n=new z(m(n),u());for(l=l.f();l!==u();){var v=l.e();v=new z(m(v),u());r=r.p=v;l=l.f()}m=n}n=KF(lv(),a.tk,new y(x=>x.ro(b,c,g,e)));op();n=pp(qp(),n);r=a.co.Kc(b,c,g,e);l=a.uk.Kc(b,c,g,e);v=a.Gq;a=KF(lv(),a.Vm,new y(x=>x.ro(b,c,g,e)));op();return new Ww(h,d,k,m,n,r,\nl,v,pp(qp(),a))}function Ofa(a,b,c,d,e){var g=a.nc,h=a.Hq,k=a.vk,l=a.wk,m=x=>{var A=x.kc,B=d.ba(t().d,x.hb);return new tl(A,hD(B),x.Rd)};if(l===u())m=u();else{var n=l.e(),r=n=new z(m(n),u());for(l=l.f();l!==u();){var v=l.e();v=new z(m(v),u());r=r.p=v;l=l.f()}m=n}n=KF(lv(),a.tk,new y(x=>x.yl(b,c,d,e)));op();n=pp(qp(),n);b.b()?r=R():(r=!!b.o(),r=new L(!r));r=d.ba(r,a.co);l=d.ba(b,a.uk);v=a.Gq;a=KF(lv(),a.Vm,new y(x=>x.yl(b,c,d,e)));op();return new Ww(g,h,k,m,n,r,l,v,pp(qp(),a))}\nfunction Pfa(a,b,c,d){var e=a.nc,g=a.Hq,h=a.vk,k=a.wk,l=v=>{var x=v.kc,A=c.ba(new TB(b),v.hb);return new tl(x,hD(A),v.Rd)};if(k===u())l=u();else{var m=k.e(),n=m=new z(l(m),u());for(k=k.f();k!==u();){var r=k.e();r=new z(l(r),u());n=n.p=r;k=k.f()}l=m}m=KF(lv(),a.tk,new y(v=>v.cm(b,c,d)));op();m=pp(qp(),m);n=c.ba(new UB(b),a.co);k=c.ba(b,a.uk);r=a.Gq;a=KF(lv(),a.Vm,new y(v=>v.cm(b,c,d)));op();return new Ww(e,g,h,l,m,n,k,r,pp(qp(),a))}f.H=function(){return\"TypedNuTrt\"};f.G=function(){return 8};\nf.I=function(a){switch(a){case 0:return this.Hq;case 1:return this.vk;case 2:return this.wk;case 3:return this.tk;case 4:return this.co;case 5:return this.uk;case 6:return this.Gq;case 7:return this.Vm;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ww};\nf.B=function(){var a=lb(\"TypedNuTrt\");a=W().C(-889275714,a);var b=this.Hq;a=W().C(a,b);b=this.vk;b=My(W(),b);a=W().C(a,b);b=this.wk;b=My(W(),b);a=W().C(a,b);b=this.tk;b=My(W(),b);a=W().C(a,b);b=this.co;b=My(W(),b);a=W().C(a,b);b=this.uk;b=My(W(),b);a=W().C(a,b);b=this.Gq;b=My(W(),b);a=W().C(a,b);b=this.Vm;b=My(W(),b);a=W().C(a,b);return W().Ma(a,8)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Ww&&a.nc===this.nc){if(this.Hq===a.Hq){var b=this.vk,c=a.vk;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.wk,c=a.wk,(null===b?null===c:b.i(c))?(b=this.tk,c=a.tk,b=null===b?null===c:b.i(c)):b=!1):b=!1;if(b&&(b=this.co,c=a.co,(null===b?null===c:mC(b,c))?(b=this.uk,c=a.uk,b=null===b?null===c:mC(b,c)):b=!1,b&&(b=this.Gq,c=a.Gq,null===b?null===c:b.i(c))))return b=this.Vm,a=a.Vm,null===b?null===a:b.i(a)}return!1};\nf.cm=function(a,b,c){return Pfa(this,a,b,c)};f.yl=function(a,b,c,d){return Ofa(this,a,b,c,d)};f.ro=function(a,b,c,d){return Xw(this,a,b,c,d)};f.$classData=q({GX:0},!1,\"mlscript.NuTypeDefs$TypedNuTrt\",{GX:1,YH:1,g:1,Rs:1,nx:1,HN:1,E:1,v:1,l:1});function BP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.yx=a;this.aA=b;Nq(this)}BP.prototype=new ZS;BP.prototype.constructor=BP;f=BP.prototype;f.Vj=function(){return this.yx};f.H=function(){return\"Signature\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.yx;case 1:return this.aA;default:return $K(W(),a)}};f.D=function(a){return a instanceof BP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof BP){var b=this.yx,c=a.yx;if(null===b?null===c:b.i(c))return b=this.aA,a=a.aA,null===b?null===a:b.i(a)}return!1};f.$classData=q({hY:0},!1,\"mlscript.Signature\",{hY:1,ih:1,g:1,jh:1,Ta:1,Haa:1,E:1,v:1,l:1});\nfunction W5(a){Nq(a);a.oc=t().d;a.nd=t().d}function Pm(){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0}Pm.prototype=new p;Pm.prototype.constructor=Pm;function X5(){}f=X5.prototype=Pm.prototype;f.jb=function(){return hu(this)};f.Wr=function(){return Zz(this,!1)};f.Vj=function(){return eP(this)};f.nv=function(){0===(1&this.gc)<<24>>24&&0===(1&this.gc)<<24>>24&&(this.yd=cP(this),this.gc=(1|this.gc)<<24>>24);return this.yd};\nf.jn=function(){0===(2&this.gc)<<24>>24&&0===(2&this.gc)<<24>>24&&(this.zd=zq(this),this.gc=(2|this.gc)<<24>>24);return this.zd};f.rn=function(){return this.Cd};f.fm=function(a){this.Cd=a};f.qn=function(){return this.Bd};f.em=function(a){this.Bd=a};f.pn=function(){return this.Ad};f.on=function(a){this.Ad=a};f.A=function(){0===(4&this.gc)<<24>>24&&0===(4&this.gc)<<24>>24&&(this.Dd=Dq(this),this.gc=(4|this.gc)<<24>>24);return this.Dd};function Y5(){this.ld=\"trait\"}Y5.prototype=new XS;\nY5.prototype.constructor=Y5;f=Y5.prototype;f.H=function(){return\"Trt\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof Y5};f.B=function(){return 84374};f.u=function(){return\"Trt\"};f.$classData=q({qY:0},!1,\"mlscript.Trt$\",{qY:1,EE:1,sz:1,sx:1,g:1,ZH:1,E:1,v:1,l:1});var Z5;function Fp(){Z5||(Z5=new Y5);return Z5}function Vv(){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0}Vv.prototype=new W4;Vv.prototype.constructor=Vv;\nfunction $5(){}$5.prototype=Vv.prototype;function LA(a,b,c,d,e){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.tc=b;this.ic=c;this.jc=d;this.KE=e;pY(this,a)}LA.prototype=new qY;LA.prototype.constructor=LA;f=LA.prototype;f.ma=function(){return this.KE};f.Ea=function(){var a=this.ic.Ea(),b=this.jc.Ea();return a>b?a:b};f.ub=function(a,b){var c=this.ic.ub(a,b);a=this.jc.ub(a,b);return c>a?c:a};f.u=function(){return\"(\"+this.ic+\" \"+(this.tc?\"|\":\"\\x26\")+\" \"+this.jc+\")\"};\nf.H=function(){return\"ComposedType\"};f.G=function(){return 3};f.I=function(a){switch(a){case 0:return this.tc;case 1:return this.ic;case 2:return this.jc;default:return $K(W(),a)}};f.D=function(a){return a instanceof LA};f.$classData=q({aZ:0},!1,\"mlscript.TyperDatatypes$ComposedType\",{aZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function Qfa(a){if(!a.uI){var b=ED(a,!1).m();b=new Ef(b,new y(d=>d.Ea()));var c=Fq();a.vI=hH(b,c)|0;a.uI=!0}return a.vI}\nfunction eC(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.vI=this.dd=0;this.hO=null;this.uI=!1;this.Lj=b;this.kj=c;pY(this,a);this.hO=c.ma()}eC.prototype=new qY;eC.prototype.constructor=eC;f=eC.prototype;f.ma=function(){return this.hO};f.Ea=function(){return this.uI?this.vI:Qfa(this)};f.ub=function(a,b){var c=ED(this,!1).m();c=new Ef(c,new y(e=>e.ub(a,b)));var d=Fq();return hH(c,d)|0};\nf.u=function(){var a=this.kj,b=this.Lj,c=h=>{if(null!==h)return h.h()+\" \\x3c: \"+h.j();throw new w(h);};if(b===u())c=u();else{var d=b.e(),e=d=new z(c(d),u());for(b=b.f();b!==u();){var g=b.e();g=new z(c(g),u());e=e.p=g;b=b.f()}c=d}return\"{\"+a+\" where: \"+ze(c,\"\",\", \",\"\")+\"}\"};f.H=function(){return\"ConstrainedType\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Lj;case 1:return this.kj;default:return $K(W(),a)}};f.D=function(a){return a instanceof eC};\nf.$classData=q({bZ:0},!1,\"mlscript.TyperDatatypes$ConstrainedType\",{bZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function FA(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.Eh=b;this.hZ=c;pY(this,a)}FA.prototype=new qY;FA.prototype.constructor=FA;f=FA.prototype;f.ma=function(){return this.hZ};f.Ea=function(){return this.q.Gd};f.ub=function(){return this.q.Gd};f.u=function(){return this.Eh?\"\\u22a5\":\"\\u22a4\"};f.H=function(){return\"ExtrType\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.Eh:$K(W(),a)};f.D=function(a){return a instanceof FA};f.$classData=q({gZ:0},!1,\"mlscript.TyperDatatypes$ExtrType\",{gZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function MA(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.Fc=b;this.rA=c;pY(this,a)}MA.prototype=new qY;MA.prototype.constructor=MA;f=MA.prototype;f.ma=function(){return this.rA};f.Ea=function(){return this.Fc.Ea()};f.ub=function(a,b){return this.Fc.ub(a,b)};\nf.u=function(){return\"~(\"+this.Fc+\")\"};f.H=function(){return\"NegType\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Fc:$K(W(),a)};f.D=function(a){return a instanceof MA};f.$classData=q({pZ:0},!1,\"mlscript.TyperDatatypes$NegType\",{pZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function Qv(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.OO=this.dd=0;this.FI=!1;this.Ba=b;this.Nj=c;pY(this,a)}Qv.prototype=new qY;Qv.prototype.constructor=Qv;f=Qv.prototype;f.ma=function(){return this.Nj};\nf.Ea=function(){this.FI||this.FI||(this.OO=this.ub(this.q.Df,jA().X()),this.FI=!0);return this.OO};f.ub=function(a,b){var c=this.Ba.m();c=new Ef(c,new y(e=>e.j().ub(a,b)));var d=Fq();c=Jq(c,d);return(c.b()?this.q.Gd:c.o())|0};function ov(a,b,c,d,e){return XC(a.q,a,t().d,new fn((g,h)=>h.Kc(b,c,d,e)))}\nfunction Gea(a){var b=a.Ba,c=h=>{var k=a.q,l=O().c;return new Qv(k,new z(h,l),a.Nj)};if(b===u())c=u();else{var d=b.e(),e=d=new z(c(d),u());for(b=b.f();b!==u();){var g=b.e();g=new z(c(g),u());e=e.p=g;b=b.f()}c=d}for(d=a.q.La;!c.b();)e=c.e(),d=new LA(a.q,!1,d,e,V(a.q)),c=c.f();return d}function Lu(a){var b=a.q,c=a.Ba,d=new y(h=>h.h()),e=Su(),g=op().ga;return new Qv(b,QY(c,d,new Uu(e,g)),a.Nj)}\nf.u=function(){var a=this.Ba;if(a===u())var b=u();else{b=a.e();var c=b=new z(b.h().x+\": \"+b.j(),u());for(a=a.f();a!==u();){var d=a.e();d=new z(d.h().x+\": \"+d.j(),u());c=c.p=d;a=a.f()}}return\"{\"+ze(b,\"\",\", \",\"\")+\"}\"};f.H=function(){return\"RecordType\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Ba:$K(W(),a)};f.D=function(a){return a instanceof Qv};f.Kc=function(a,b,c,d){return ov(this,a,b,c,d)};\nf.$classData=q({xZ:0},!1,\"mlscript.TyperDatatypes$RecordType\",{xZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function cC(a,b,c,d){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.Fg=b;this.Sf=c;this.TO=d;pY(this,a)}cC.prototype=new qY;cC.prototype.constructor=cC;f=cC.prototype;f.ma=function(){return this.TO};f.Ea=function(){var a=this.Fg.Ea(),b=this.Sf.Ea();return a>b?a:b};f.ub=function(a,b){var c=this.Fg.ub(a,b);a=this.Sf.ub(a,b);return c>a?c:a};\nf.u=function(){return this.Fg+\"..\"+this.Sf};f.H=function(){return\"TypeBounds\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Fg;case 1:return this.Sf;default:return $K(W(),a)}};f.D=function(a){return a instanceof cC};f.$classData=q({FZ:0},!1,\"mlscript.TyperDatatypes$TypeBounds\",{FZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});\nfunction Hn(a,b,c,d,e,g,h,k,l){this.HP=null;this.FP=!1;this.GP=this.IP=this.EP=null;this.Hp=a;this.$I=b;this.cF=c;this.eF=d;this.hF=e;this.dF=g;this.gF=h;this.fF=k;this.CA=l;cE(this);this.HP=O().c;this.FP=!0;this.EP=t().d;this.IP=t().d}Hn.prototype=new p;Hn.prototype.constructor=Hn;f=Hn.prototype;f.wK=function(){return this.GP};f.xK=function(a){this.GP=a};f.Ua=function(){return this.Hp};f.mv=function(){return this.cF};f.EB=function(){return this.eF};f.ZL=function(){return this.hF};f.HF=function(){return this.dF};\nf.vy=function(){return this.gF};f.FB=function(){return this.fF};f.CK=function(){return this.CA};f.u=function(){return\"mixin \"+this.Hp};f.xo=function(){return this.Hp};f.zo=function(){return this.Hp};f.pH=function(){return this.HP};f.UJ=function(){return this.FP};f.GF=function(){return this.EP};f.iM=function(){return this.IP};f.H=function(){return\"MixinSymbol\"};f.G=function(){return 9};\nf.I=function(a){switch(a){case 0:return this.Hp;case 1:return this.$I;case 2:return this.cF;case 3:return this.eF;case 4:return this.hF;case 5:return this.dF;case 6:return this.gF;case 7:return this.fF;case 8:return this.CA;default:return $K(W(),a)}};f.D=function(a){return a instanceof Hn};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Hn){if(this.Hp===a.Hp){var b=this.$I,c=a.$I;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.cF,c=a.cF,(null===b?null===c:b.i(c))?(b=this.eF,c=a.eF,b=null===b?null===c:b.i(c)):b=!1):b=!1;if(b&&(b=this.hF,c=a.hF,(null===b?null===c:b.i(c))?(b=this.dF,c=a.dF,b=null===b?null===c:b.i(c)):b=!1,b&&(b=this.gF,c=a.gF,null===b?null===c:b.i(c)))&&(b=this.fF,c=a.fF,null===b?null===c:b.i(c)))return b=this.CA,a=a.CA,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({r_:0},!1,\"mlscript.codegen.MixinSymbol\",{r_:1,g:1,UA:1,cr:1,mt:1,pF:1,E:1,v:1,l:1});function ln(a,b,c,d,e,g,h,k,l){this.KP=!1;this.LP=this.NP=this.MP=this.JP=null;this.lj=a;this.aJ=b;this.iF=c;this.kF=d;this.mF=e;this.jF=g;this.nF=h;this.lF=k;this.DA=l;cE(this);this.KP=!1;this.JP=t().d;this.MP=O().c;this.NP=t().d}ln.prototype=new p;ln.prototype.constructor=ln;f=ln.prototype;f.wK=function(){return this.LP};f.xK=function(a){this.LP=a};f.Ua=function(){return this.lj};f.mv=function(){return this.iF};\nf.EB=function(){return this.kF};f.ZL=function(){return this.mF};f.HF=function(){return this.jF};f.pH=function(){return this.nF};f.FB=function(){return this.lF};f.CK=function(){return this.DA};f.u=function(){return\"module \"+this.lj};f.xo=function(){return this.lj};f.zo=function(){return this.lj};f.UJ=function(){return this.KP};f.GF=function(){return this.JP};f.vy=function(){return this.MP};f.iM=function(){return this.NP};f.H=function(){return\"ModuleSymbol\"};f.G=function(){return 9};\nf.I=function(a){switch(a){case 0:return this.lj;case 1:return this.aJ;case 2:return this.iF;case 3:return this.kF;case 4:return this.mF;case 5:return this.jF;case 6:return this.nF;case 7:return this.lF;case 8:return this.DA;default:return $K(W(),a)}};f.D=function(a){return a instanceof ln};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof ln){if(this.lj===a.lj){var b=this.aJ,c=a.aJ;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.iF,c=a.iF,(null===b?null===c:b.i(c))?(b=this.kF,c=a.kF,b=null===b?null===c:b.i(c)):b=!1):b=!1;if(b&&(b=this.mF,c=a.mF,(null===b?null===c:b.i(c))?(b=this.jF,c=a.jF,b=null===b?null===c:b.i(c)):b=!1,b&&(b=this.nF,c=a.nF,null===b?null===c:b.i(c)))&&(b=this.lF,c=a.lF,null===b?null===c:b.i(c)))return b=this.DA,a=a.DA,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({t_:0},!1,\"mlscript.codegen.ModuleSymbol\",{t_:1,g:1,UA:1,cr:1,mt:1,pF:1,E:1,v:1,l:1});function jn(a,b,c,d,e,g,h,k,l,m,n,r,v){this.PP=null;this.mi=a;this.oF=b;this.IA=c;this.GA=d;this.JA=e;this.OA=g;this.MA=h;this.HA=k;this.NA=l;this.LA=m;this.KA=n;this.Qx=r;this.$u=v;cE(this)}jn.prototype=new p;jn.prototype.constructor=jn;f=jn.prototype;f.wK=function(){return this.PP};f.xK=function(a){this.PP=a};f.Ua=function(){return this.mi};f.GF=function(){return this.IA};f.mv=function(){return this.GA};\nf.EB=function(){return this.JA};f.iM=function(){return this.OA};f.ZL=function(){return this.MA};f.HF=function(){return this.HA};f.pH=function(){return this.NA};f.vy=function(){return this.LA};f.FB=function(){return this.KA};f.CK=function(){return this.Qx};f.UJ=function(){return this.$u};f.u=function(){return\"new class \"+this.mi};f.xo=function(){return this.mi};f.zo=function(){return this.mi};f.H=function(){return\"NewClassSymbol\"};f.G=function(){return 13};\nf.I=function(a){switch(a){case 0:return this.mi;case 1:return this.oF;case 2:return this.IA;case 3:return this.GA;case 4:return this.JA;case 5:return this.OA;case 6:return this.MA;case 7:return this.HA;case 8:return this.NA;case 9:return this.LA;case 10:return this.KA;case 11:return this.Qx;case 12:return this.$u;default:return $K(W(),a)}};f.D=function(a){return a instanceof jn};\nf.B=function(){var a=lb(\"NewClassSymbol\");a=W().C(-889275714,a);var b=this.mi;b=My(W(),b);a=W().C(a,b);b=this.oF;b=My(W(),b);a=W().C(a,b);b=this.IA;b=My(W(),b);a=W().C(a,b);b=this.GA;b=My(W(),b);a=W().C(a,b);b=this.JA;b=My(W(),b);a=W().C(a,b);b=this.OA;b=My(W(),b);a=W().C(a,b);b=this.MA;b=My(W(),b);a=W().C(a,b);b=this.HA;b=My(W(),b);a=W().C(a,b);b=this.NA;b=My(W(),b);a=W().C(a,b);b=this.LA;b=My(W(),b);a=W().C(a,b);b=this.KA;b=My(W(),b);a=W().C(a,b);b=this.Qx;b=My(W(),b);a=W().C(a,b);b=this.$u?1231:\n1237;a=W().C(a,b);return W().Ma(a,13)};\nf.i=function(a){if(this===a)return!0;if(a instanceof jn){if(this.$u===a.$u)if(this.mi===a.mi){var b=this.oF,c=a.oF;b=null===b?null===c:b.i(c)}else b=!1;else b=!1;b?(b=this.IA,c=a.IA,(null===b?null===c:b.i(c))?(b=this.GA,c=a.GA,(null===b?null===c:b.i(c))?(b=this.JA,c=a.JA,b=null===b?null===c:b.i(c)):b=!1):b=!1):b=!1;if(b&&(b=this.OA,c=a.OA,(null===b?null===c:b.i(c))?(b=this.MA,c=a.MA,(null===b?null===c:b.i(c))?(b=this.HA,c=a.HA,b=null===b?null===c:b.i(c)):b=!1):b=!1,b&&(b=this.NA,c=a.NA,(null===b?\nnull===c:b.i(c))?(b=this.LA,c=a.LA,b=null===b?null===c:b.i(c)):b=!1,b&&(b=this.KA,c=a.KA,null===b?null===c:b.i(c)))))return b=this.Qx,a=a.Qx,null===b?null===a:b.i(a)}return!1};f.$classData=q({v_:0},!1,\"mlscript.codegen.NewClassSymbol\",{v_:1,g:1,UA:1,cr:1,mt:1,pF:1,E:1,v:1,l:1});function a6(a,b){for(;;){if(0>=a||b.b())return b;a=-1+a|0;b=b.f()}}function jba(a,b){for(;;)if(!a.b()&&b.n(a.e()))a=a.f();else break;return a}\nfunction b6(a,b){var c=a.vj().Eb();for(a=a.m();a.s();){var d=b.n(a.t());c.$(d)}return c.Kb()}function c6(a,b){var c=a.vj().Eb();c.zc(a);c.zc(b);return c.Kb()}function ky(a,b){if(0>=a.ab(1))return a;for(var c=a.ti(),d=Vn(),e=a.m(),g=!1;e.s();){var h=e.t();d.oh(b.n(h))?c.$(h):g=!0}return g?c.Kb():a}function tr(a,b){this.hG=0;this.gd=a;if(null===a)throw Kj(\"null value for BigDecimal\");if(null===b)throw Kj(\"null MathContext for BigDecimal\");this.hG=1565550863}tr.prototype=new cW;\ntr.prototype.constructor=tr;f=tr.prototype;f.sl=function(a){return uW(this.gd,a.gd)};\nf.B=function(){if(1565550863===this.hG){if(this.uv()&&4934>(pr(this.gd)-this.gd.xb|0))var a=d6(new KR,vW(this.gd)).B();else{a=this.gd.Lp();if(Infinity!==a&&-Infinity!==a){var b=lr();a=e6(this,BR(a,b.xy))}else a=!1;if(a)a=this.gd.Lp(),a=ZK(W(),a);else{a=sW(this.gd);b=BL();var c=b.Pp,d;var e=d=a.xb,g=e>>31,h=d>>31;d=e-d|0;g=(-2147483648^d)>(-2147483648^e)?-1+(g-h|0)|0:g-h|0;64>a.$h?(e=a.Bg,0===e.W&&0===e.Y?(e=hN(),d=new ma(d,g),g=d.W,d=d.W===g&&d.Y===g>>31?jN(e,aa,d.W):0<=d.Y?eN(0,2147483647):eN(0,\n-2147483648)):d=jN(hN(),a.Bg,mN(hN(),new ma(d,g)))):d=FR(new mr,$M(a),mN(hN(),new ma(d,g)));a=c.call(b,vW(d).B(),a.xb)}}this.hG=a}return this.hG};\nf.i=function(a){if(a instanceof tr)return e6(this,a);if(a instanceof KR){var b=f6(a),c=pr(this.gd);if(b>3.3219280948873626*(-2+(c-this.gd.xb|0)|0)){if(this.uv())try{var d=new L(d6(new KR,pW(this.gd)))}catch(e){if(e instanceof qb)d=R();else throw e;}else d=R();if(d.b())return!1;b=d.o();return g6(a,b)}return!1}return\"number\"===typeof a?(b=+a,Infinity!==b&&-Infinity!==b&&(a=this.gd.Lp(),Infinity!==a&&-Infinity!==a&&a===b)?(b=lr(),e6(this,BR(a,b.xy))):!1):ja(a)?(b=Math.fround(a),Infinity!==b&&-Infinity!==\nb&&(a=this.gd.pv(),Infinity!==a&&-Infinity!==a&&a===b)?(b=lr(),e6(this,BR(a,b.xy))):!1):this.pB()&&AK(this,a)};f.WJ=function(){try{return oW(this.gd,8),!0}catch(a){if(a instanceof qb)return!1;throw a;}};f.YJ=function(){try{return oW(this.gd,16),!0}catch(a){if(a instanceof qb)return!1;throw a;}};f.XJ=function(){return this.MF()&&0<=oW(this.gd,32).W&&65535>=oW(this.gd,32).W};f.MF=function(){try{return oW(this.gd,32),!0}catch(a){if(a instanceof qb)return!1;throw a;}};\nf.pB=function(){try{return oW(this.gd,64),!0}catch(a){if(a instanceof qb)return!1;throw a;}};f.uv=function(){return 0>=this.gd.xb?!0:0>=sW(this.gd).xb};function e6(a,b){return 0===uW(a.gd,b.gd)}f.jB=function(){return this.gd.Zi()<<24>>24};f.EC=function(){return this.gd.Zi()<<16>>16};f.Zi=function(){return this.gd.Zi()};f.xl=function(){return this.gd.xl()};f.pv=function(){return this.gd.pv()};f.Lp=function(){return this.gd.Lp()};f.u=function(){return this.gd.u()};\nf.$l=function(a){return uW(this.gd,a.gd)};f.qT=function(){return this.gd};f.$classData=q({u3:0},!1,\"scala.math.BigDecimal\",{u3:1,R3:1,ur:1,g:1,l:1,S3:1,sR:1,yj:1,nf:1});function h6(a){a=a.Uf;return!(0===a.W&&-2147483648===a.Y)}function i6(a){a=Ni(j6(a),2147483647);return 0!==a.Ya&&!a.i(NK().qR)}function JR(a,b,c){a.jm=b;a.Uf=c;return a}function d6(a,b){JR(a,b,63>=yh(Sh(),b)?b.xl():new ma(0,-2147483648));return a}function KR(){this.jm=null;this.Uf=aa}KR.prototype=new cW;KR.prototype.constructor=KR;\nf=KR.prototype;f.sl=function(a){return k6(this,a)};function j6(a){var b=a.jm;if(null!==b)return b;var c=a.Uf;b=c.W;c=c.Y;b=ri(Ph(),new ma(b,c));return a.jm=b}f.B=function(){if(this.pB()){var a=this.xl(),b=a.W;a=a.Y;return(-1===a?0<=(-2147483648^b):-1<a)&&(0===a?-1>=(-2147483648^b):0>a)?b:YK(W(),new ma(b,a))}b=j6(this);return My(W(),b)};\nf.i=function(a){if(a instanceof KR)return g6(this,a);if(a instanceof tr)return a.i(this);if(\"number\"===typeof a){a=+a;var b=f6(this);if(53>=b)b=!0;else{var c=l6(this);b=1024>=b&&c>=(-53+b|0)&&1024>c}return(b?!i6(this):!1)&&this.Lp()===a}return ja(a)?(a=Math.fround(a),b=f6(this),24>=b?b=!0:(c=l6(this),b=128>=b&&c>=(-24+b|0)&&128>c),b&&!i6(this)?(b=j6(this),hM(jM(),Vh(bi(),b))===a):!1):this.pB()&&AK(this,a)};\nf.WJ=function(){var a=this.Uf,b=a.Y;return(-1===b?2147483520<=(-2147483648^a.W):-1<b)?(a=this.Uf,b=a.Y,0===b?-2147483521>=(-2147483648^a.W):0>b):!1};f.YJ=function(){var a=this.Uf,b=a.Y;return(-1===b?2147450880<=(-2147483648^a.W):-1<b)?(a=this.Uf,b=a.Y,0===b?-2147450881>=(-2147483648^a.W):0>b):!1};f.XJ=function(){if(0<=this.Uf.Y){var a=this.Uf,b=a.Y;return 0===b?-2147418113>=(-2147483648^a.W):0>b}return!1};\nf.MF=function(){var a=this.Uf,b=a.Y;return(-1===b?0<=(-2147483648^a.W):-1<b)?(a=this.Uf,b=a.Y,0===b?-1>=(-2147483648^a.W):0>b):!1};f.pB=function(){return h6(this)||QK(nl(),this.jm,NK().LK)};f.uv=function(){return!0};function g6(a,b){return h6(a)?h6(b)?(a=a.Uf,b=b.Uf,a.W===b.W&&a.Y===b.Y):!1:!h6(b)&&QK(nl(),a.jm,b.jm)}function k6(a,b){if(h6(a)){if(h6(b)){var c=a.Uf;a=c.W;c=c.Y;var d=b.Uf;b=d.W;d=d.Y;return ua(xa(),a,c,b,d)}return-b.jm.Ya|0}return h6(b)?a.jm.Ya:fM(a.jm,b.jm)}\nfunction lba(a){if(h6(a)){var b=NK(),c=a.Uf;a=c.W;c=c.Y;return OR(b,new ma(-a|0,0!==a?~c:-c|0))}return PR(NK(),ui(j6(a)))}function l6(a){if(h6(a)){var b=a.Uf;if(0===b.W&&0===b.Y)return-1;b=a.Uf;a=b.W;b=b.Y;return 0!==a?0===a?32:31-Math.clz32(a&(-a|0))|0:32+(0===b?32:31-Math.clz32(b&(-b|0))|0)|0}return wW(j6(a))}\nfunction f6(a){if(h6(a)){if(0>a.Uf.Y){a=a.Uf;var b=a.Y;a=1+a.W|0;var c=0===a?1+b|0:b;b=-a|0;a=0!==a?~c:-c|0;return 64-(0!==a?Math.clz32(a):32+Math.clz32(b)|0)|0}b=a.Uf;a=b.W;b=b.Y;return 64-(0!==b?Math.clz32(b):32+Math.clz32(a)|0)|0}a=a.jm;return yh(Sh(),a)}f.jB=function(){return this.Zi()<<24>>24};f.EC=function(){return this.Zi()<<16>>16};f.Zi=function(){return h6(this)?this.Uf.W:j6(this).Zi()};f.xl=function(){return h6(this)?this.Uf:this.jm.xl()};\nf.pv=function(){var a=j6(this);return hM(jM(),Vh(bi(),a))};f.Lp=function(){if(this.pB())if(-2097152<=this.Uf.Y){var a=this.Uf,b=a.Y;a=2097152===b?0===a.W:2097152>b}else a=!1;else a=!1;if(a)return a=this.Uf,cG(xa(),a.W,a.Y);a=j6(this);return aM(qa(),Vh(bi(),a))};f.u=function(){if(h6(this)){var a=this.Uf;return bG(xa(),a.W,a.Y)}a=this.jm;return Vh(bi(),a)};f.$l=function(a){return k6(this,a)};f.qT=function(){return j6(this)};\nvar NR=q({w3:0},!1,\"scala.math.BigInt\",{w3:1,R3:1,ur:1,g:1,l:1,S3:1,sR:1,yj:1,nf:1});KR.prototype.$classData=NR;function m6(){this.NB=null;n6=this;this.NB=new B2(this)}m6.prototype=new p;m6.prototype.constructor=m6;f=m6.prototype;f.sj=function(a){return a===this.NB};f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};\nf.Kk=function(a,b){return z2(this,a,b)};f.Da=function(a,b){a|=0;b|=0;return a===b?0:a<b?-1:1};f.$classData=q({K3:0},!1,\"scala.math.Ordering$Int$\",{K3:1,g:1,L3:1,lm:1,Ji:1,mm:1,km:1,l:1,uba:1});var n6;function Fq(){n6||(n6=new m6);return n6}function o6(){this.Ki=null;this.Gf=0}o6.prototype=new T5;o6.prototype.constructor=o6;function p6(){}p6.prototype=o6.prototype;o6.prototype.uh=function(){return da(rd)};o6.prototype.si=function(a){return new Ec(a)};function q6(){this.Ki=null;this.Gf=0}\nq6.prototype=new T5;q6.prototype.constructor=q6;function r6(){}r6.prototype=q6.prototype;q6.prototype.uh=function(){return da(xd)};q6.prototype.si=function(a){return new Pc(a)};function s6(){this.Ki=null;this.Gf=0}s6.prototype=new T5;s6.prototype.constructor=s6;function t6(){}t6.prototype=s6.prototype;s6.prototype.uh=function(){return da(td)};s6.prototype.si=function(a){return new Ic(a)};function u6(){this.Ki=null;this.Gf=0}u6.prototype=new T5;u6.prototype.constructor=u6;function v6(){}\nv6.prototype=u6.prototype;u6.prototype.uh=function(){return da(Ld)};u6.prototype.si=function(a){return new ed(a)};function w6(){this.Ki=null;this.Gf=0}w6.prototype=new T5;w6.prototype.constructor=w6;function x6(){}x6.prototype=w6.prototype;w6.prototype.uh=function(){return da(Gd)};w6.prototype.si=function(a){return new $c(a)};function y6(){this.Ki=null;this.Gf=0}y6.prototype=new T5;y6.prototype.constructor=y6;function z6(){}z6.prototype=y6.prototype;y6.prototype.uh=function(){return da(Ed)};\ny6.prototype.si=function(a){return new Xc(a)};function A6(){this.Ki=null;this.Gf=0}A6.prototype=new T5;A6.prototype.constructor=A6;function B6(){}B6.prototype=A6.prototype;A6.prototype.uh=function(){return da(Fd)};A6.prototype.si=function(a){return new Zc(a)};function C6(){this.OB=null;this.Br=0}C6.prototype=new V5;C6.prototype.constructor=C6;function D6(){}D6.prototype=C6.prototype;C6.prototype.u=function(){return this.OB};C6.prototype.i=function(a){return this===a};C6.prototype.B=function(){return this.Br};\nfunction E6(){this.Ki=null;this.Gf=0}E6.prototype=new T5;E6.prototype.constructor=E6;function F6(){}F6.prototype=E6.prototype;E6.prototype.uh=function(){return da(Cd)};E6.prototype.si=function(a){return new Sc(a)};function G6(){this.Ki=null;this.Gf=0}G6.prototype=new T5;G6.prototype.constructor=G6;function H6(){}H6.prototype=G6.prototype;G6.prototype.uh=function(){return da(pd)};G6.prototype.si=function(a){return new (md(la).Ia)(a)};\nfunction mP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Bi=a;this.Ci=b;Nq(this)}mP.prototype=new M_;mP.prototype.constructor=mP;f=mP.prototype;f.H=function(){return\"Bounds\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Bi;case 1:return this.Ci;default:return $K(W(),a)}};f.D=function(a){return a instanceof mP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof mP){var b=this.Bi,c=a.Bi;if(null===b?null===c:b.i(c))return b=this.Ci,a=a.Ci,null===b?null===a:b.i(a)}return!1};f.$classData=q({YT:0},!1,\"mlscript.Bounds\",{YT:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});function I6(){this.ld=\"class\"}I6.prototype=new XS;I6.prototype.constructor=I6;f=I6.prototype;f.H=function(){return\"Cls\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof I6};f.B=function(){return 67850};\nf.u=function(){return\"Cls\"};f.$classData=q({oU:0},!1,\"mlscript.Cls$\",{oU:1,EE:1,sz:1,sx:1,g:1,AM:1,ZH:1,E:1,v:1,l:1});var J6;function Bp(){J6||(J6=new I6);return J6}function qP(a,b,c){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Lw=a;this.Mw=b;this.Nw=c;Nq(this)}qP.prototype=new M_;qP.prototype.constructor=qP;f=qP.prototype;f.H=function(){return\"Constrained\"};f.G=function(){return 3};\nf.I=function(a){switch(a){case 0:return this.Lw;case 1:return this.Mw;case 2:return this.Nw;default:return $K(W(),a)}};f.D=function(a){return a instanceof qP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof qP){var b=this.Lw,c=a.Lw;if(null===b?null===c:b.i(c))if(b=this.Mw,c=a.Mw,null===b?null===c:b.i(c))return b=this.Nw,a=a.Nw,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({rU:0},!1,\"mlscript.Constrained\",{rU:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});function Wt(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.ps=a;this.qs=b;Nq(this)}Wt.prototype=new M_;Wt.prototype.constructor=Wt;f=Wt.prototype;f.H=function(){return\"Function\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.ps;case 1:return this.qs;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof Wt};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Wt){var b=this.ps,c=a.ps;if(null===b?null===c:b.i(c))return b=this.qs,a=a.qs,null===b?null===a:b.i(a)}return!1};f.$classData=q({WU:0},!1,\"mlscript.Function\",{WU:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});function K6(){this.ld=\"module\"}K6.prototype=new XS;K6.prototype.constructor=K6;f=K6.prototype;f.H=function(){return\"Mod\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof K6};f.B=function(){return 77538};f.u=function(){return\"Mod\"};f.$classData=q({FW:0},!1,\"mlscript.Mod$\",{FW:1,EE:1,sz:1,sx:1,g:1,AM:1,ZH:1,E:1,v:1,l:1});var L6;function zp(){L6||(L6=new K6);return L6}function kP(a){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.cx=a;Nq(this)}kP.prototype=new M_;kP.prototype.constructor=kP;f=kP.prototype;f.H=function(){return\"Neg\"};\nf.G=function(){return 1};f.I=function(a){return 0===a?this.cx:$K(W(),a)};f.D=function(a){return a instanceof kP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof kP){var b=this.cx;a=a.cx;return null===b?null===a:b.i(a)}return!1};f.$classData=q({KW:0},!1,\"mlscript.Neg\",{KW:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});\nfunction Tn(a){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Xs=a;Nq(this)}Tn.prototype=new M_;Tn.prototype.constructor=Tn;f=Tn.prototype;f.H=function(){return\"Record\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Xs:$K(W(),a)};f.D=function(a){return a instanceof Tn};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Tn){var b=this.Xs;a=a.Xs;return null===b?null===a:b.i(a)}return!1};f.$classData=q({YX:0},!1,\"mlscript.Record\",{YX:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});function lP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.tx=a;this.Zz=b;Nq(this)}lP.prototype=new M_;lP.prototype.constructor=lP;f=lP.prototype;f.H=function(){return\"Rem\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.tx;case 1:return this.Zz;default:return $K(W(),a)}};f.D=function(a){return a instanceof lP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof lP){var b=this.tx,c=a.tx;if(null===b?null===c:b.i(c))return b=this.Zz,a=a.Zz,null===b?null===a:b.i(a)}return!1};f.$classData=q({ZX:0},!1,\"mlscript.Rem\",{ZX:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});\nfunction tP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.vx=a;this.wx=b;Nq(this)}tP.prototype=new M_;tP.prototype.constructor=tP;f=tP.prototype;f.H=function(){return\"Selection\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.vx;case 1:return this.wx;default:return $K(W(),a)}};f.D=function(a){return a instanceof tP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof tP){var b=this.vx,c=a.vx;if(null===b?null===c:b.i(c))return b=this.wx,a=a.wx,null===b?null===a:b.i(a)}return!1};f.$classData=q({eY:0},!1,\"mlscript.Selection\",{eY:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});function rP(a){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Ax=a;Nq(this)}rP.prototype=new M_;rP.prototype.constructor=rP;f=rP.prototype;f.H=function(){return\"Splice\"};\nf.G=function(){return 1};f.I=function(a){return 0===a?this.Ax:$K(W(),a)};f.D=function(a){return a instanceof rP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof rP){var b=this.Ax;a=a.Ax;return null===b?null===a:b.i(a)}return!1};f.$classData=q({lY:0},!1,\"mlscript.Splice\",{lY:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});\nfunction jP(a){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Mu=a;Nq(this)}jP.prototype=new M_;jP.prototype.constructor=jP;f=jP.prototype;f.H=function(){return\"Tuple\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Mu:$K(W(),a)};f.D=function(a){return a instanceof jP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof jP){var b=this.Mu;a=a.Mu;return null===b?null===a:b.i(a)}return!1};f.$classData=q({sY:0},!1,\"mlscript.Tuple\",{sY:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});function M6(a){tp();return gq(a)}function N6(a,b,c,d,e){if(Bp()!==b&&zp()!==b&&Ap()!==b&&Fp()!==b){var g=new Te(new Ue(J(new K,[\"\",\" \",\" cannot be used as a type\"])));b=[We(Xe(),b.ld),We(Xe(),c)];Lw(a,Ye(g,J(new K,b)),d,e)}}\nfunction O6(a,b,c,d,e,g){d=d.U(c);d.b()&&(d=e.tb.U(c),d.b()?d=R():(d=d.o(),d=new L(G(new H,d.jj,d.Xm.K()))));if(d.b())if(e=uC(e,e,c),e.b())e=R();else a:{if(d=e.o(),d instanceof ix&&(e=d.kh,e instanceof Cx)){N6(a,e.Yr().pb,e.cG().V,b,g);t();d=e.Yr().pb;e=e.Ag();e=G(new H,d,e.K());e=new L(e);break a}if(d instanceof fx){e=d.Ab.fd();N6(a,e,d.Ab.Cf.x,b,g);var h=!1;e=null;d=d.Ab;if(d instanceof yo){h=!0;e=d;var k=e.pb,l=e.hg;if(Bp()===k||zp()===k||Ap()===k||Fp()===k){t();e=G(new H,k,l.K());e=new L(e);break a}}if(h&&\n(h=e.pb,e=e.hg,cp()===h)){t();e=G(new H,h,e.K());e=new L(e);break a}if(d instanceof Zn){e=t().d;break a}throw new w(d);}e=t().d}else e=d;if(e.b())return O(),new fe(new U(()=>Lw(a,We(Xe(),\"type identifier not found: \"+c),b,g)));O();e=e.o();return new Ud(e)}\nfunction Rfa(a,b,c,d,e,g,h){var k=tD(b,c);k instanceof fw&&xm(\"Program reached and unexpected state.\");if(k instanceof Mu&&(k=k.pd,k instanceof vl)){h=!1;b=null;k=Mea(a,k.x,d.Zr(),c,e);if(k instanceof Ud){h=!0;b=k;var l=b.fa;if(l instanceof Yw)return l.gh.b()||no(),e=l.Rf,d=g.A(),tx(a),g=t().d,bz(a,e,jx(new kx,a,d,\"type selection\",g,!0),c)}if(h&&(c=b.fa,c instanceof ax))return c.rk.b()||no(),c.Ql;if(h)return g=b.fa,c=new Te(new Ue(J(new K,[\"Illegal selection of \",\" member in type position\"]))),g=\n[We(Xe(),g.fd().ld)],Lw(a,Ye(c,J(new K,g)),d.A(),e);if(k instanceof fe)return GX(a,k.aa,e);throw new w(k);}d=new Te(new Ue(J(new K,[\"Illegal prefix of type selection: \",\"\"])));c=[wO(Xe(),AD(b,c))];return Lw(a,Ye(d,J(new K,c)),h.A(),e)}\nvar Sfa=function P6(a,b,c,d,e,g,h,k,l,m,n){return Lx(a,new U(()=>c.da+\". type \"+wO(Xe(),b).Wr()),new U(()=>{var v=!1,x=null,A=!1,B=null;if(gl()===b){var C=b.A(),D=t().d;return new FA(a,!1,jx(new kx,a,C,\"top type\",D,!0))}if(el()===b){var F=b.A(),I=t().d;return new FA(a,!0,jx(new kx,a,F,\"bottom type\",I,!0))}if(b instanceof mP){v=!0;x=b;var M=x.Bi,N=x.Ci;if(el()===M&&gl()===N){var P=b.A(),T=t().d,Y=jx(new kx,a,P,\"type wildcard\",T,!0);return new cC(a,new FA(a,!0,Y),new FA(a,!1,Y),Y)}}if(v){var Z=x.Ci,\nS=P6(a,x.Bi,c,d,e,g,h,k,l,m,n),ea=P6(a,Z,c,d,e,g,h,k,l,m,n),ia=b.A(),X=t().d,sa=jx(new kx,a,ia,\"type bounds\",X,!0),Ja=Sw(a).ob;Tw(a,S,ea,e,sa,c,Ja);return new cC(a,S,ea,sa)}if(b instanceof jP){var Xa=b.Mu,Fa=ry(lv(),Xa,new y(Ta=>{var wb=Ta.Yf,$a=new y(wa=>P6(a,wa,c,d,e,g,h,k,l,m,n));return new Uw(a,wb.b()?R():new L($a.n(wb.o())),P6(a,Ta.Rg,c,d,e,g,h,k,l,m,n),jx(new kx,a,Ta.A(),\"tuple field\",(tx(a),t().d),(tx(a),!1)))})),za=b.A(),Qa=t().d;return new zv(a,Fa,jx(new kx,a,za,\"tuple type\",Qa,!0))}if(b instanceof\nrP){var Ma=Qt(b.Ax,new y(Ta=>{if(Ta instanceof fe){Ta=P6(a,Ta.aa,c,d,e,g,h,k,l,m,n);var wb=Ta.ma(),$a=t().d,wa=t().d,hb=O().c,ra=O().c;wb=new lx(a,c.da,hb,ra,$a,wa,!1,wb);$a=Ta.ma();wb=new Sv(a,new Uw(wb.q,R(),wb,$a),Ta.ma());$a=Ta.ma();wa=Sw(a).ob;Tw(a,Ta,wb,e,$a,c,wa);t();return new fe(Ta)}if(Ta instanceof Ud)return Ta=Ta.fa,t(),wb=Ta.Yf,$a=new y(wc=>P6(a,wc,c,d,e,g,h,k,l,m,n)),Ta=new Uw(a,wb.b()?R():new L($a.n(wb.o())),P6(a,Ta.Rg,c,d,e,g,h,k,l,m,n),jx(new kx,a,Ta.A(),\"splice field\",(tx(a),t().d),\n(tx(a),!1))),new Ud(Ta);throw new w(Ta);})),Ga=b.A(),ab=t().d;return new Wv(a,Ma,jx(new kx,a,Ga,\"splice type\",ab,!0))}if(b instanceof hP){var Hb=b.As,bc=b.Bs;if(g)var yb=new y(Ta=>{var wb=P6(a,Hb,c,d,e,g,h,k,l,m,n),$a=P6(a,bc,c,d,e,g,h,k,l,m,n);return Pu(wb,$a,Ta,!1)});else{var tb=P6(a,Hb,c,d,e,g,h,k,l,m,n),eb=P6(a,bc,c,d,e,g,h,k,l,m,n);yb=new y(Ta=>new LA(a,!1,tb,eb,Ta))}var kb=b.A(),Rb=t().d;return yb.n(jx(new kx,a,kb,\"intersection type\",Rb,!0))}if(b instanceof iP){var Gb=b.ht,vb=b.it;if(g)var Tb=\nnew y(Ta=>{var wb=P6(a,Gb,c,d,e,g,h,k,l,m,n),$a=P6(a,vb,c,d,e,g,h,k,l,m,n);return dv(wb,$a,Ta,!1)});else{var Nb=P6(a,Gb,c,d,e,g,h,k,l,m,n),ic=P6(a,vb,c,d,e,g,h,k,l,m,n);Tb=new y(Ta=>new LA(a,!0,Nb,ic,Ta))}var Va=b.A(),cb=t().d;return Tb.n(jx(new kx,a,Va,\"union type\",cb,!0))}if(b instanceof kP){var zb=P6(a,b.cx,c,d,e,g,h,k,l,m,n),Ub=b.A(),jb=t().d;return new MA(a,zb,jx(new kx,a,Ub,\"type negation\",jb,!0))}if(b instanceof Tn){var db=b.Xs,ub=b.A(),Aa=t().d,va=jx(new kx,a,ub,\"record type\",Aa,!0);ET(db,\nnew y(Ta=>Ta.h().x),new y(Ta=>Ta.h())).Ca(new y(Ta=>{if(null!==Ta&&(Ta=new L(Ta),!Ta.b())){var wb=Ta.k.h();Ta=Ta.k.j();if(0<Ta.ab(1)){var $a=new Te(new Ue(J(new K,[\"Multiple declarations of field name \",\" in \",\"\"])));wb=[We(Xe(),wb),We(Xe(),va.lh)];wb=Ye($a,J(new K,wb));$a=b.A();wb=G(new H,wb,$a);Ta=Qt(Ta,new y(wa=>{var hb=Ye(new Te(new Ue(J(new K,[\"Declared at\"]))),u());wa=wa.A();return G(new H,hb,wa)}));return ay(a,new z(wb,Ta),e)}}}));return SA(xv(a),Qt(db,new y(Ta=>{hB(ve(),Ta.h().x)&&Lw(a,Ye(new Te(new Ue(J(new K,\n[\"Field identifiers must start with a small letter\"]))),u()),Ta.h().A(),e);var wb=Ta.h(),$a=Ta.j().Yf,wa=new y(ac=>P6(a,ac,c,d,e,g,h,k,l,m,n));$a=$a.b()?R():new L(wa.n($a.o()));wa=P6(a,Ta.j().Rg,c,d,e,g,h,k,l,m,n);var hb=Ta.h(),ra=new vl(\"\"),wc=Ta.j().A();hb=new Pl(hb,Cq(ra,wc));hb=Lq(hb);Ta=new Uw(a,$a,wa,jx(new kx,a,hb,(Ta.j().Yf.b()?\"\":\"mutable \")+\"record field\",(tx(a),t().d),(tx(a),!1)));return G(new H,wb,Ta)})),va)}if(b instanceof Wt){var Ra=b.qs,rb=P6(a,b.ps,c,d,e,g,h,k,l,m,n),xb=P6(a,Ra,c,\nd,e,g,h,k,l,m,n),mc=b.A(),Ha=t().d;return new cv(a,rb,xb,jx(new kx,a,mc,\"function type\",Ha,!0))}if(b instanceof nP){var Ka=b.Mx,Oa=P6(a,b.Lx,c,d,e,g,h,k,l,m,n),Na=Qt(Ka.Xs,new y(Ta=>{if(null!==Ta){var wb=Ta.h(),$a=Ta.j();Ta=$a.Yf;var wa=new y(ra=>P6(a,ra,c,d,e,g,h,k,l,m,n));Ta=Ta.b()?R():new L(wa.n(Ta.o()));wa=P6(a,$a.Rg,c,d,e,g,h,k,l,m,n);var hb=new vl(\"\");$a=$a.A();$a=new Pl(wb,Cq(hb,$a));$a=Lq($a);hb=t().d;Ta=new Uw(a,Ta,wa,jx(new kx,a,$a,\"extension field\",hb,!0));return G(new H,wb,Ta)}throw new w(Ta);\n})),Da=Ka.A(),ta=t().d,Ya=new Qv(a,Na,jx(new kx,a,Da,\"extension record\",ta,!0)),dc=b.A(),ka=t().d;return new $y(a,Oa,Ya,jx(new kx,a,dc,\"extension type\",ka,!0))}if(b instanceof oP){var ya=b.Es,Sa=a.$c?yq(ya):fq(ya),xc=b.A(),Sb=t().d;return new Mu(a,ya,Sa,jx(new kx,a,xc,\"literal type\",Sb,!0))}if(b instanceof Ep&&(A=!0,B=b,\"this\"===B.V)){var uc=!1,Lb=null,lc=c.hc.U(\"this\");lc instanceof L&&(uc=!0,Lb=lc,Lb.k instanceof VP&&xm(\"Program reached and unexpected state.\"));if(uc){var Xb=Lb.k;if(Xb instanceof\nqx){var ec=Xb.tp;if(null!==ec)return ec}}if(t().d===lc){var Ab=Ye(new Te(new Ue(J(new K,[\"undeclared `this`\"]))),u()),Ob=b.A(),fb=G(new H,Ab,Ob),Wa=O().c;return ay(a,new z(fb,Wa),e)}throw new w(lc);}if(b instanceof sP){var bb=b.nA;return P6(a,new Ep(UF(ve(),bb)),c,d,e,g,h,k,l,m,n)}if(A){var Ia=B.V,Ua=b.A(),pc=t().d,sc=jx(new kx,a,Ua,\"type reference\",pc,!0);return h.Se(Ia,new U((Ta=>()=>{var wb=O6(a,Ua,Ia,m,n,e);if(wb instanceof Ud){var $a=wb.fa;if(null!==$a){$a=$a.Sc();if(Pe(new E($a),0))return new fw(a,\nTa,O().c,sc);var wa=c.$a.U(Ia);if(wa instanceof L){var hb=!1,ra=null;wa=wa.k.Ab;if(wa instanceof yo&&(hb=!0,ra=wa,wa=ra.pb,Bp()===wa||zp()===wa))return wb=c.$a.n(Ia).Ab,$a=t().d,bz(a,wb,jx(new kx,a,Ua,\"class tag\",$a,!0),c);if(hb&&(wa=ra.pb,Fp()===wa))return wb=c.$a.n(Ia).Ab,$a=t().d,Xx(a,wb,jx(new kx,a,Ua,\"class tag\",$a,!0),c);if(hb&&(hb=ra.pb,Ap()===hb))return wb=O().xR,new fw(a,Ta,Yea(wb,$a,new U(()=>{var wc=V(a),ac=t().d,Id=t().d,ud=O().c,be=O().c;return new lx(a,c.da,ud,be,ac,Id,!1,wc)})),sc);\nxm(\"Program reached and unexpected state.\")}else return wb=new Te(new Ue(J(new K,[\"Type \",\" takes parameters\"]))),$a=[We(Xe(),Ia)],Lw(a,Ye(wb,J(new K,$a)),Ua,e)}}if(wb instanceof fe){wb=wb.aa;\"\"===Ia?$a=!0:($a=Hu(Q(),Ia),$a=!bE(Pr(),$a));if(!$a&&($a=G(new H,O6(a,Ua,Nu(Q(),Ia),m,n,e),c.tb.U(Nu(Q(),Ia))),hb=$a.y,$a=$a.w,hb instanceof Ud&&(hb=hb.fa,null!==hb&&(hb=hb.h(),$a instanceof L)))){wb=$a.k;if(Bp()===hb)return $a=t().d,rD(a,wb,jx(new kx,a,Ua,\"class tag\",$a,!0),c);if(Fp()===hb)return $a=t().d,\nTD(a,wb,jx(new kx,a,Ua,\"trait tag\",$a,!0));if(Ap()===hb)return wb=new Te(new Ue(J(new K,[\"Type alias \",\" cannot be used as a type tag\"]))),$a=[We(Xe(),Nu(Q(),Ia))],Lw(a,Ye(wb,J(new K,$a)),Ua,e);if(zp()===hb)return wb=new Te(new Ue(J(new K,[\"Module \",\" cannot be used as a type tag\"]))),$a=[We(Xe(),Nu(Q(),Ia))],Lw(a,Ye(wb,J(new K,$a)),Ua,e);if(cp()===hb)return wb=new Te(new Ue(J(new K,[\"Mixin \",\" cannot be used as a type tag\"]))),$a=[We(Xe(),Nu(Q(),Ia))],Lw(a,Ye(wb,J(new K,$a)),Ua,e);throw new w(hb);\n}return Es(wb)}throw new w(wb);})(B)))}if(b instanceof jt){var Ba=GP(b.pp),ob=new y(Ta=>h.U(Ta)),nc=Ba.b()?R():ob.n(Ba.o()),Ib=new U(()=>{var Ta=d.Se(b,new U(()=>k.Hk(b,new U(()=>{var wa=V(a),hb=t().d,ra=aT(b),wc=new y(Id=>kda(Q(),Id,new y(ud=>Nm(new E(hc(Ea(ud))),hc(39)))));ra=ra.b()||wc.n(ra.o())?ra:R();wc=O().c;var ac=O().c;return new lx(a,l,wc,ac,hb,ra,!1,wa)})))),wb=b.A(),$a=t().d;wb=jx(new kx,a,wb,\"type variable\",$a,!0);return ux(Ta.q,Ta,wb)});return nc.b()?Es(Ib):nc.o()}if(b instanceof pP){var vc=\nb.Gw,Vb=b.Hw,fc=b.A(),Bc=t().d,Pb=jx(new kx,a,fc,\"applied type reference\",Bc,!0),Jb=O6(a,b.A(),vc.V,m,n,e);if(Jb instanceof Ud){var gc=Jb.fa;if(null!==gc){var Cb=gc.Sc(),cc=Vb.K();if(Pe(new E(cc),Cb))var yc=Qt(Vb,new y(Ta=>P6(a,Ta,c,d,e,g,h,k,l,m,n)));else{var Mc=new Te(new Ue(J(new K,[\"Wrong number of type arguments \\u2013 expected \",\", found \",\"\"]))),qc=We(Xe(),\"\"+Cb);Xe();var oc=Vb.K(),Qc=[qc,We(0,\"\"+oc)];Lw(a,Ye(Mc,J(new K,Qc)),b.A(),e);var jc=Vb.m(),sb=new Ef(jc,new y(Ta=>P6(a,Ta,c,d,e,g,h,k,\nl,m,n))),Gc=kv(sb,new U(()=>{O();return new y0(new U(()=>{var Ta=V(a),wb=t().d,$a=t().d,wa=O().c,hb=O().c;return new lx(a,c.da,wa,hb,wb,$a,!1,Ta)}))})).Mn(Cb);Od();yc=Pd(u(),Gc)}return new fw(a,vc,yc,Pb)}}if(Jb instanceof fe)return Es(Jb.aa);throw new w(Jb);}if(b instanceof tP){var Wb=b.vx,Cc=b.wx,Fc=P6(a,Wb,c,d,e,g,h,k,l,m,n);return Rfa(a,Fc,c,Cc,e,b,Wb)}if(b instanceof lP){var qd=b.Zz,Yb=P6(a,b.tx,c,d,e,g,h,k,l,m,n),Nc=Su(),ad=op().ga,Uc=new Uu(Nc,ad),cd=oA(uv(),qd,Uc),kc=b.A(),Vc=t().d;return new Tv(a,\nYb,cd,jx(new kx,a,kc,\"field removal type\",Vc,!0))}if(b instanceof qP){var Hc=b.Lw,rc=b.Mw,sd=b.Nw;if(Hc instanceof I_)var Kc=Hc;else xm(\"Program reached and unexpected state.\");for(var Qd=P6(a,Kc,c,d,e,g,h,k,l,m,n),Ad=new y(Ta=>{a:{if(null!==Ta){var wb=Ta.h(),$a=Ta.j();if(null!==$a){var wa=$a.Bi;$a=$a.Ci;Ta=P6(a,wa,c,d,e,g,h,k,l,m,n);var hb=d.n(wb);wa=jx(new kx,a,wa.A(),\"lower bound specifiation\",(tx(a),t().d),(tx(a),!1));var ra=Sw(a).ob;Tw(a,Ta,hb,e,wa,c,ra);wb=d.n(wb);Ta=P6(a,$a,c,d,e,g,h,k,l,m,\nn);$a=jx(new kx,a,$a.A(),\"upper bound specifiation\",(tx(a),t().d),(tx(a),!1));hb=Sw(a).ob;Tw(a,wb,Ta,e,$a,c,hb);break a}}throw new w(Ta);}}),kd=rc;!kd.b();)Ad.n(kd.e()),kd=kd.f();for(var Hd=new y(Ta=>{if(null!==Ta){var wb=Ta.Bi,$a=Ta.Ci;Ta=P6(a,wb,c,d,e,g,h,k,l,m,n);var wa=P6(a,$a,c,d,e,g,h,k,l,m,n);wb=jx(new kx,a,Wca(wF(),wb.A(),$a.A(),new fn((hb,ra)=>xs(hb,ra))),\"constraint specifiation\",(tx(a),t().d),(tx(a),!1));$a=Sw(a).ob;Tw(a,Ta,wa,e,wb,c,$a)}else throw new w(Ta);}),Rd=sd;!Rd.b();)Hd.n(Rd.e()),\nRd=Rd.f();return Qd}if(b instanceof Vt){var Bd=b.Ws,ae=b.Vs,dd=jx(new kx,a,ae.A(),\"polymorphic type\",(tx(a),t().d),(tx(a),!1)),od=new y(Ta=>{var wb=new aw(d);Qt(Bd,new y($a=>{if($a instanceof fe)xm(\"Program reached and unexpected state.\");else{if($a instanceof Ud){$a=$a.fa;var wa=$a.A(),hb=aT($a);wa=jx(new kx,a,wa,\"quantified type variable\",hb,!0);hb=t().d;var ra=aT($a),wc=O().c,ac=O().c;wa=new lx(a,Ta.da,wc,ac,hb,ra,!1,wa);wb.rc=wb.rc.Pn(G(new H,$a,wa));return wa}throw new w($a);}}));return P6(a,\nae,Ta,wb.rc,e,g,h,k,l,m,n)});Sw(c.S);return Px(c,od,e,dd)}throw new w(b);}),new y(v=>\"\\x3d\\x3e \"+v))};function Q6(a,b,c,d,e,g,h){var k=tc();try{var l=new IQ(0),m=new y(r=>{if(r instanceof Ff){if(Pe(new E(l.ve),0)){var v=Ey(a),x=new y(()=>{}),A=V(a),B=Sw(a).ob;Tw(a,v,d,x,A,e,B);g.n(r)}else if(3<=l.ve)throw Hq(new Iq,k,d);l.ve=1+l.ve|0}else g.n(r)}),n=Sw(a).ob;Tw(a,b,c,m,h,e,n);return d}catch(r){if(r instanceof Iq){b=r;if(b.Qg===k)return b.Cj();throw b;}throw r;}}\nfunction R6(a,b,c,d){if(!b.tJ().b()){var e=new Te(new Ue(J(new K,[\"Class \",\" is abstract and cannot be instantiated\"])));b=[We(Xe(),b.Cf.x)];Lw(a,Ye(e,J(new K,b)),c.A(),d)}}function S6(a,b,c,d){if(b.Om.b()){var e=new Te(new Ue(J(new K,[\"\",\" `\",\"` is not mutable and cannot be reassigned\"])));b=[We(Xe(),cy(b)),We(Xe(),b.Rb.x)];Lw(a,Ye(e,J(new K,b)),c.Ga,d)}}\nfunction T6(a,b,c,d,e,g){if(a.F){var h=\"\"+ut(Q(),\"| \",a.r)+G(new H,b,c.$a.U(b));ff(gf(),h+\"\\n\")}c=c.$a.U(b);if(t().d===c)return g=new Te(new Ue(J(new K,[\"Type `\",\"` cannot be used in `new` expression\"]))),b=[We(Xe(),b)],Lw(a,Ye(g,J(new K,b)),d.A(),e);if(c instanceof L){b=c.k;if(null!==b&&!Ot(new E(b.Qu),Bp()))return d=new Te(new Ue(J(new K,[\"\",\" \",\" cannot be used in `new` expression\"]))),Xe(),Q(),b=[We(0,Nu(0,b.Qu.ld)),We(Xe(),b.sO)],Lw(a,Ye(d,J(new K,b)),g.Ga,e);if(null!==b)return h=b.Ab,h.tJ().b()||\n(c=new Te(new Ue(J(new K,[\"Class \",\" is abstract and cannot be instantiated\"]))),h=[We(Xe(),h.Cf.x)],Lw(a,Ye(c,J(new K,h)),d.A(),e)),Cy(b,!0,g.Ga,e);throw new w(b);}throw new w(c);}\nvar Tfa=function U6(a,b,c){b=uy(b);if(b instanceof Qx){var e=b.Re;if(null!==e&&(e=Hv(Iv(a),e,c),!e.b()&&(e=e.k,e instanceof cv)))return O(),a=J(new K,[e]),Pd(u(),a)}if(b instanceof cv)return O(),a=J(new K,[b]),Pd(u(),a);if(b instanceof lx){var g=vy(b);if(g===u())a=u();else{b=g.e();e=b=new z(U6(a,b,c),u());for(g=g.f();g!==u();){var h=g.e();h=new z(U6(a,h,c),u());e=e.p=h;g=g.f()}a=b}c=op().ga;return zX(a,c)}return b instanceof LA&&(g=b.ic,e=b.jc,Pe(new E(b.tc),!1))?(b=U6(a,g,c),a=U6(a,e,c),un(b,a)):\nO().c};\nfunction V6(a,b,c,d,e,g){if(a.oP){Sw(c.S);var h=1+c.da|0,k=Hw(),l=Su(),m=op().ga;k=k.Hd(new Uu(l,m));h=new Iw(c.S,c.Ec,c.hc,c.Ed,h,c.Pc,c.Zc,c.Lb,c.yc,c.tb,c.$a,c.od,k);a=Rw(a,b,h,d,e,!0);up(tp(),c.S.li||h.cb.b());Xu().X();b=vx(c.S);e=h.cb.m();e=new xo(e,new y((r=>v=>{if(null!==v){var x=v.h();v=v.j().m();return new Ef(v,new y(A=>{if(null!==A){var B=A.Rc();A=A.j();up(tp(),A.Ea()>r.da);return B?G(new H,A,x):G(new H,x,A)}throw new w(A);}))}throw new w(v);})(c)));Od();a=wx(b,Pd(u(),e),a);b=c.S;b.F&&(b=\nut(Q(),\"| \",b.r)+(\"Inferred poly constr: \"+a+\"  \\u2014\\u2014 where \")+xx(a),ff(gf(),b+\"\\n\"));c.S.F&&Nm(new E(a),a)&&(b=c.S,b.F&&(b=ut(Q(),\"| \",b.r)+(\"Refreshed:            \"+a+\"  \\u2014\\u2014 where \")+xx(a),ff(gf(),b+\"\\n\")));a=yx(zx(c.S),c.da,a);h.cb.mg();b=h.cb;up(tp(),c.S.li||h.cb.b());if(!b.b()){h=c.S.qa;e=c.S;e.F&&(k=ut(Q(),\"| \",e.r)+\"UNSTASHING... (out)\",ff(gf(),k+\"\\n\"));e.r=1+e.r|0;try{b.Ca(new y(((r,v)=>x=>{if(null!==x){var A=x.h();for(x=x.j().m();x.s();){var B=x.t();a:{if(null!==B){var C=\nB.j();if(!0===B.Rc()){B=Sw(r.S).ob;Tw(r.S,C,A,d,g,v,B);break a}}if(null!==B&&(C=B.j(),!1===B.Rc())){B=Sw(r.S).ob;Tw(r.S,A,C,d,g,v,B);break a}throw new w(B);}}}else throw new w(x);})(c,c)));b.mg();var n=void 0}finally{e.r=-1+e.r|0}dx(new E(h),e.qa)&&e.F&&(c=\"\"+ut(Q(),\"| \",e.r)+h.n(n),ff(gf(),c+\"\\n\"))}return a}return Rw(a,b,c,d,e,!0)}\nfunction Ufa(a,b,c,d,e,g,h){var k=W6(a,b,d,e,g);g=t().d;t();var l=c.x;l=(0<=l.length&&\"_\"===l.substring(0,1)?0:!YD(c))?new L(c.x):R();var m=O().c,n=O().c;g=new lx(a,d.da,m,n,g,l,!1,h);b=ux(a,k,jx(new kx,a,Lq(b),\"receiver\",(tx(a),t().d),(tx(a),!1)));k=xv(a);l=jx(new kx,a,c.A(),\"field selector\",(tx(a),t().d),(tx(a),!1));l=new Uw(g.q,R(),g,l);c=G(new H,c,l);l=O().c;c=SA(k,new z(c,l),h);return Q6(a,b,c,g,d,e,h)}\nfunction X6(a,b,c,d,e,g,h,k){if(a.$c)var l=t().d;else{var m=c.x;a:{if(null!==m&&(l=dda(Wea(),m),!l.b()&&null!==l.o()&&0===l.o().ab(2))){m=l.o().va(0);l=l.o().va(1);l=hY(d,(t(),new L(m)),l);break a}l=hY(d,t().d,m)}}if(l instanceof L){l=l.k;if(l.Waa().b()){if(!(0<l.T2().ab(1)))throw new Yj(\"assertion failed: \"+l);m=new Te(new Ue(J(new K,[\"Implicit call to method \",\" is forbidden because it is ambiguous.\"])));var n=[We(Xe(),c.x)];m=Ye(m,J(new K,n));e=e.A();e=G(new H,m,e);m=new Te(new Ue(J(new K,[\"Unrelated methods named \",\n\" are defined by:\"])));c=[We(Xe(),c.x)];c=Ye(m,J(new K,c));m=t().d;c=G(new H,c,m);var r=l.T2();m=A=>{A=d.tb.n(A.V);var B=new Te(new Ue(J(new K,[\"\\u2022 \",\" \",\"\"]))),C=[We(Xe(),A.jj.ld),wO(Xe(),A.Wl)];B=Ye(B,J(new K,C));A=A.Wl.A();return G(new H,B,A)};if(r===u())m=u();else{n=r.e();var v=n=new z(m(n),u());for(r=r.f();r!==u();){var x=r.e();x=new z(m(x),u());v=v.p=x;r=r.f()}m=n}ay(a,new z(e,new z(c,m)),g)}h=W6(a,b,d,g,h);b=t().d;c=t().d;e=O().c;m=O().c;b=new lx(a,d.da,e,m,b,c,!1,k);l=l.maa();return Q6(a,\nTA(l,d),new cv(a,Y6(a,h),b,k),b,d,g,k)}if(t().d===l){if(a.$c?0:hB(ve(),c.x))return k=new Te(new Ue(J(new K,[\"Method \",\" not found\"]))),h=[We(Xe(),c.x)],Lw(a,Ye(k,J(new K,h)),e.A(),g);b instanceof am&&(l=new vl(\"super\"),b=b.A(),b=Cq(l,b));return Ufa(a,b,c,d,g,h,k)}throw new w(l);}function Vfa(a,b,c){for(;;){var d=tD(a,b);if(d instanceof Qx)a=d,c.Am=!0,a=TA(a,b);else return a}}\nvar Yfa=function Wfa(a,b,c,d,e,g,h){for(;;){var l=b;if(l instanceof z){b=l;var m=b.z;b=b.p;if(null!==m){var n=m.h();m=m.cy();if(null!==n)if(l=n.h(),n=n.j(),m)if(m=n.ya,m instanceof Dl||m instanceof vl){t();c=c.Pn(G(new H,l,new Ud(n.ya)));continue}else return m=new vl(Xfa(l,d.jn())),n=n.ya,t(),new Rl(!1,m,n,Wfa(a,b,c.Pn(G(new H,l,new fe(m))),d,e,g,h));else{t();c=c.Pn(G(new H,l,new Ud(n.ya)));continue}}}b=O().c;if(null===b?null===l:b.i(l)){d=((r,v,x)=>A=>{var B=!1,C=null,D=r.U(A.x);if(D instanceof L){B=\n!0;C=D;var F=C.k;if(F instanceof fe)return A=F.aa,G(new H,R(),new sm(tm().Cg,A))}if(B&&(B=C.k,B instanceof Ud))return A=B.fa,G(new H,R(),new sm(tm().Cg,A));if(R()===D)return D=new Te(new Ue(J(new K,[\"Argument named '\",\"' is missing from this function call\"]))),A=[We(Xe(),A.x)],Lw(a,Ye(D,J(new K,A)),v.A(),x),G(new H,R(),new sm(tm().Cg,new vl(\"error\")));throw new w(D);})(c,d,g);if(e===u())e=u();else{g=e.e();b=g=new z(d(g),u());for(e=e.f();e!==u();)c=e.e(),c=new z(d(c),u()),b=b.p=c,e=e.f();e=g}e=new Gl(e);\nreturn new Pl(h,e)}throw new w(l);}};function Z6(a,b,c,d,e,g,h){if(null!==b){var k=b.Oa,l=b.ra;if(k instanceof L&&(k=k.k,k instanceof lx&&l instanceof lx&&Pe(new E(k),l)))return a=$6(a,l,c,d,e,g,h),new Sn((t(),new L(a)),a)}l=b.Oa;l.b()?l=R():(l=l.o(),l=new L($6(a,l,c,d,e,g,h)));return new Sn(l,$6(a,b.ra,c,d,e,g,h))}function a7(a,b,c,d,e,g,h){Od();b=Pd(u(),b);var k=new y(m=>m.h()),l=cT();b=QY(b,k,l);return new Dt(Wn(b,new P_(a,c,d,e,g,h)))}\nvar $6=function b7(a,b,c,d,e,g,h){for(;;){var l=!1,m=null,n=!1,r=null,v=!1,x=null,A=!1,B=null,C=!1,D=null,F=uy(b);if(F instanceof lx&&(l=!0,m=F,d))return c7(m);if(l)return c.bO.Se(m,new U(((Kd,ld,Jd,Dd,Xd,Yc)=>()=>{var Ce=c7(Kd);if(ld.oh(Kd)){var te=Kd.Sb;if(te instanceof L){var Ie=b7(a,te.k,Jd,Xd,ld,Dd,Yc);te=Dd.rc;Ie=new mP(Ie,Ie);Ie=G(new H,Ce,Ie);Dd.rc=new z(Ie,te)}else if(t().d===te){te=vy(Kd);for(Ie=a.ib;!te.b();){var Jf=te.e(),df=V(Ie.q);Ie=dv(Ie,Jf,df,!1);te=te.f()}te=b7(a,Ie,Jd,Xd,ld,Dd,\nYc);Ie=rA(Kd);for(Jf=a.La;!Ie.b();){df=Ie.e();var vg=V(Jf.q);Jf=sA(Jf,df,vg);Ie=Ie.f()}Jf=b7(a,Jf,Jd,Xd,ld,Dd,Yc);if(Nm(new E(te),el())||Nm(new E(Jf),gl()))Ie=Dd.rc,te=new mP(te,Jf),te=G(new H,Ce,te),Dd.rc=new z(te,Ie)}else throw new w(te);}return Ce})(m,e,c,g,d,h)));if(F instanceof cv){var I=F,M=I.ac;return new Wt(b7(a,I.Nb,c,d,e,g,h),b7(a,M,c,d,e,g,h))}if(F instanceof LA){n=!0;r=F;var N=r.ic,P=r.jc;if(!0===r.tc){var T=a.UE,Y=a.TI,Z=V(a.UE.q),S=dv(T,Y,Z,!1);return Aca(r,S,h)?new Ep(\"Bool\"):new iP(b7(a,\nN,c,d,e,g,h),b7(a,P,c,d,e,g,h))}}if(n){var ea=r.ic,ia=r.jc;if(!1===r.tc)return new hP(b7(a,ea,c,d,e,g,h),b7(a,ia,c,d,e,g,h))}if(F instanceof Qv){var X=F.Ba;return new Tn(ry(lv(),X,new y(((Kd,ld,Jd,Dd,Xd)=>Yc=>Z6(a,Yc,Kd,ld,Jd,Dd,Xd))(c,d,e,g,h))))}if(F instanceof zv){var sa=F.Yb;return new jP(ry(lv(),sa,new y(((Kd,ld,Jd,Dd,Xd)=>Yc=>Z6(a,Yc,Kd,ld,Jd,Dd,Xd))(c,d,e,g,h))))}if(F instanceof Sv){v=!0;x=F;var Ja=x.Fd;if(null!==Ja){var Xa=Ja.Oa,Fa=Ja.ra;if(R()===Xa){var za=new Ep(\"Array\"),Qa=b7(a,Fa,c,d,\ne,g,h),Ma=O().c;return new pP(za,new z(Qa,Ma))}}}if(v){var Ga=Z6(a,x.Fd,c,d,e,g,h),ab=new Ep(\"MutArray\"),Hb=Ga.Yf,bc=new mP(Hb.b()?el():Hb.o(),Ga.Rg),yb=O().c;return new pP(ab,new z(bc,yb))}if(F instanceof Wv){var tb=F.fo,eb=((Kd,ld,Jd,Dd,Xd)=>Yc=>{if(Yc instanceof fe)return Yc=Yc.aa,t(),Yc=b7(a,Yc,Kd,ld,Jd,Dd,Xd),new fe(Yc);if(Yc instanceof Ud){Yc=Yc.fa;t();var Ce=Yc.Oa;Ce.b()?Ce=R():(Ce=Ce.o(),Ce=new L(b7(a,Ce,Kd,ld,Jd,Dd,Xd)));Yc=new Sn(Ce,b7(a,Yc.ra,Kd,ld,Jd,Dd,Xd));return new Ud(Yc)}throw new w(Yc);\n})(c,d,e,g,h);if(tb===u())var kb=u();else{for(var Rb=tb.e(),Gb=new z(eb(Rb),u()),vb=Gb,Tb=tb.f();Tb!==u();){var Nb=Tb.e(),ic=new z(eb(Nb),u());vb=vb.p=ic;Tb=Tb.f()}kb=Gb}return new rP(kb)}if(F instanceof MA)return new kP(b7(a,F.Fc,c,d,e,g,h));if(F instanceof FA&&(A=!0,B=F,!0===B.Eh))return el();if(A&&!1===B.Eh)return gl();if(F instanceof $y){var Va=F,cb=Va.up,zb=b7(a,Va.Oq,c,d,e,g,h);lv();return new nP(zb,new Tn(ry(0,cb.Ba,new y(((Kd,ld,Jd,Dd,Xd)=>Yc=>Z6(a,Yc,Kd,ld,Jd,Dd,Xd))(c,d,e,g,h)))))}if(F instanceof\nZB){var Ub=F;$B(a);t();var jb=Ub.mc(),db=new L(jb);if(!db.b()){b=db.k;continue}}if(XB(F)){var ub=F.rr();if(ub instanceof vl){var Aa=ub.x;return a.cn.L(Aa)||\"this\"===Aa?new Ep(Aa):new sP(Nu(Q(),Aa))}if(ub instanceof Dl)return new oP(ub);throw new w(ub);}if(F instanceof mx){var va=F.hi,Ra=va.kg;if(Ra instanceof L){var rb=Ra.k;if(hB(ve(),rb))return new Ep(rb)}b=va}else{if(F instanceof YB){var xb=F,mc=xb.pA,Ha=xb.Ym;if(null!==Ha){var Ka=Ha.hi;return mc?Zfa(Ka):$fa(Ka)}}if(F instanceof fw){C=!0;D=F;var Oa=\nD.qb,Na=D.Zb,Da=O().c;if(null===Da?null===Na:Da.i(Na))return Oa}if(C){var ta=D.qb,Ya=D;t();return new pP(ta,bw(Ya,new L(!0),new fn(((Kd,ld,Jd,Dd,Xd)=>(Yc,Ce)=>{a:{if(Yc instanceof L){if(!0===!!Yc.k){var te=a.La;te=null===te?null===Ce:mC(te,Ce)}else te=!1;if(te){Yc=!0;break a}}if(Yc instanceof L&&(!1===!!Yc.k?(Yc=a.ib,Yc=null===Yc?null===Ce:mC(Yc,Ce)):Yc=!1,Yc)){Yc=!0;break a}Yc=!1}return Yc?new mP(el(),gl()):b7(a,Ce,Kd,ld,Jd,Dd,Xd)})(c,d,e,g,h)),h))}if(F instanceof cC){var dc=F,ka=dc.Sf;return new mP(b7(a,\ndc.Fg,c,d,e,g,h),b7(a,ka,c,d,e,g,h))}if(F instanceof Tv){var ya=F,Sa=ya.kf;return new lP(b7(a,ya.Ic,c,d,e,g,h),(Od(),Pd(u(),Sa)))}if(F instanceof Jv){var xc=F.gi,Sb=((Kd,ld,Jd,Dd,Xd)=>Yc=>b7(a,Yc,Kd,ld,Jd,Dd,Xd))(c,d,e,g,h);if(xc===u())var uc=u();else{for(var Lb=xc.e(),lc=new z(Sb(Lb),u()),Xb=lc,ec=xc.f();ec!==u();){var Ab=ec.e(),Ob=new z(Sb(Ab),u());Xb=Xb.p=Ob;ec=ec.f()}uc=lc}var fb=Un();return eH(uc,fb)}if(F instanceof Qx){var Wa=F,bb=Wa.de,Ia=Wa.Re,Ua=g.rc.K(),pc=b7(a,Ia,c,d,e,g,h),sc=er(g.rc).m().ph(Ua),\nBa=PE().vl(sc),ob=gD(Ia,bb,a.Df).m(),nc=$S(pc),Ib=Ba.m(),vc=new Ef(Ib,new y(Kd=>Kd.h())),Vb=nc.Ce(vc),fc=Ba.m(),Bc=new xo(fc,new y(Kd=>$S(Kd.j()))),Pb=Vb.Ce(Bc),Jb=new iy(ob,new y((Kd=>ld=>Kd.L(c7(ld)))(Pb)),!1);if(Jb.s()){tp();ms();var gc=null;for(gc=[];Jb.s();){var Cb=Jb.t();gc.push(null===Cb?null:Cb)}var cc=new (md(RX).Ia)(gc),yc=Su(),Mc=op().ga,qc=Tu(cc,new Uu(yc,Mc)),oc=Kd=>{Kd=c7(Kd);t();return new Ud(Kd)},Qc=qc.a.length,jc=new (md(K2).Ia)(Qc);if(0<Qc){var sb=0;if(null!==qc)for(;sb<Qc;)jc.a[sb]=\noc(qc.a[sb]),sb=1+sb|0;else if(qc instanceof Xc)for(var Gc=qc;sb<Qc;)jc.a[sb]=oc(Gc.a[sb]),sb=1+sb|0;else if(qc instanceof ed)for(var Wb=qc;sb<Qc;)jc.a[sb]=oc(Wb.a[sb]),sb=1+sb|0;else if(qc instanceof Zc)for(var Cc=qc;sb<Qc;){var Fc=Cc.a[sb];jc.a[sb]=oc(new ma(Fc.W,Fc.Y));sb=1+sb|0}else if(qc instanceof $c)for(var qd=qc;sb<Qc;)jc.a[sb]=oc(qd.a[sb]),sb=1+sb|0;else if(qc instanceof Ic)for(var Yb=qc;sb<Qc;)jc.a[sb]=oc(hc(Yb.a[sb])),sb=1+sb|0;else if(qc instanceof Pc)for(var Nc=qc;sb<Qc;)jc.a[sb]=oc(Nc.a[sb]),\nsb=1+sb|0;else if(qc instanceof Sc)for(var ad=qc;sb<Qc;)jc.a[sb]=oc(ad.a[sb]),sb=1+sb|0;else if(qc instanceof Ec)for(var Uc=qc;sb<Qc;)jc.a[sb]=oc(Uc.a[sb]),sb=1+sb|0;else throw new w(qc);}var cd=ps(jc);Od();return new Vt(Pd(u(),cd),pc)}return pc}if(F instanceof eC){for(var kc=F,Vc=kc.Lj,Hc=kc.kj,rc=new lA,sd=new lA,Kc=Vc;!Kc.b();){var Qd=Kc.e();if(null!==Qd){var Ad=Qd.h(),kd=Qd.j(),Hd=rc.U(Ad);if(Hd instanceof L)var Rd=Hd.k;else{if(R()!==Hd)throw new w(Hd);var Bd=TE(PE());rc.bh(Ad,Bd);Rd=Bd}Rd.$(kd)}else throw new w(Qd);\nKc=Kc.f()}Od();var ae=Pd(u(),rc);if(ae.b())var dd=Od().jC;else{Od();var od=new fp;Od();for(var Ta=new fp,wb=ae.m();wb.s();){var $a=wb.t();wp(0<$a.j().$k(1)?od:Ta,$a)}var wa=G(new H,od.ha(),Ta.ha());var hb=wa.y;if(u().i(hb))dd=G(new H,u(),ae);else{var ra=wa.w;dd=u().i(ra)?G(new H,ae,u()):wa}}if(null===dd)throw new w(dd);for(var wc=dd.h(),ac=dd.j();!ac.b();){var Id=ac.e();if(null!==Id){var ud=Id.h(),be=Id.j().e(),re=sd.U(be);if(re instanceof L)var pe=re.k;else{if(R()!==re)throw new w(re);var bd=TE(PE());\nsd.bh(be,bd);pe=bd}pe.$(ud)}else throw new w(Id);ac=ac.f()}Od();var Rc=Pd(u(),sd),Wc=ry(lv(),wc,new y(Kd=>Kd.th(new fn((ld,Jd)=>{var Dd=V(ld.q);return sA(ld,Jd,Dd)})))),Wd=ry(lv(),Rc,new y(Kd=>Kd.th(new fn((ld,Jd)=>{var Dd=V(ld.q);return dv(ld,Jd,Dd,!1)}))));if(Wd===u())var zd=u();else{for(var Pa=Wd.e(),Db=new z(Pa.Cw(),u()),Oc=Db,Tc=Wd.f();Tc!==u();){var Sd=Tc.e(),Jc=new z(Sd.Cw(),u());Oc=Oc.p=Jc;Tc=Tc.f()}zd=Db}var vd=un(Wc,zd),hd=((Kd,ld,Jd,Dd,Xd)=>Yc=>{if(null!==Yc){var Ce=Yc.j();return new mP(b7(a,\nYc.h(),Kd,ld,Jd,Dd,Xd),b7(a,Ce,Kd,ld,Jd,Dd,Xd))}throw new w(Yc);})(c,d,e,g,h);if(vd===u())var de=u();else{for(var ye=vd.e(),jf=new z(hd(ye),u()),af=jf,pf=vd.f();pf!==u();){var kf=pf.e(),Be=new z(hd(kf),u());af=af.p=Be;pf=pf.f()}de=jf}return new qP(b7(a,Hc,c,d,e,g,h),O().c,de)}throw new w(F);}}};\nfunction hf(a,b,c,d){this.io=this.ho=this.jo=null;this.Fp=this.Gp=this.an=this.Ep=0;this.qa=null;this.r=0;this.zk=this.Pq=this.Uq=this.xp=this.Bp=this.Cp=this.Sq=this.zp=this.Rq=this.wp=this.Ap=this.yp=this.Qq=this.Tq=null;this.Dp=0;this.hs=this.yq=this.Aq=this.Bq=this.zq=this.Dq=this.Cq=null;this.Im=this.Pw=0;this.iA=this.hA=this.Ku=null;this.Hb=!1;this.XA=0;this.VE=this.WE=this.TE=this.SE=this.YA=null;this.sP=this.li=this.ZE=this.pP=this.oP=this.Wq=this.rP=this.UI=this.VI=this.$c=this.zA=this.$E=\nthis.F=!1;this.Df=this.Gd=0;this.uP=this.nP=this.XI=this.tP=this.cn=this.XE=this.qP=this.bn=this.WI=this.Bk=this.lP=this.RE=this.TI=this.UE=this.Qj=this.Ak=this.ki=this.mP=this.lg=this.Ck=this.ib=this.La=null;this.YE=0;this.F=a;this.$E=b;this.zA=c;this.$c=d;oca(this);cY||(cY=new bY);null===this.Cp&&null===this.Cp&&(this.Cp=new ZP(this));this.zk=this.Cp;TE(PE());this.Dp=0;this.Pw=1E4;this.Im=0;this.Hb=!1;this.XA=0;this.YA=$ea();this.li=this.ZE=this.pP=this.oP=this.Wq=this.rP=this.UI=this.VI=!1;this.sP=\n!0;this.Gd=0;this.Df=1024;this.La=new FA(this,!1,d7(this));this.ib=new FA(this,!0,d7(this));this.Ck=d?new Mu(this,new Gm(!0),ap(),d7(this)):new Mu(this,new vl(\"unit\"),ap(),d7(this));this.lg=d?$P(this.zk,new Ep(\"Bool\"),O().c,d7(this)):new Mu(this,new vl(\"bool\"),ap(),d7(this));new Mu(this,new vl(\"Object\"),ap(),d7(this));this.mP=d?$P(this.zk,new Ep(\"Object\"),O().c,d7(this)):this.La;this.ki=d?$P(this.zk,new Ep(\"Int\"),O().c,d7(this)):new Mu(this,new vl(\"int\"),M6(new Ep(\"number\")),d7(this));this.Ak=d?$P(this.zk,\nnew Ep(\"Num\"),O().c,d7(this)):new Mu(this,new vl(\"number\"),ap(),d7(this));this.Qj=d?$P(this.zk,new Ep(\"Str\"),O().c,d7(this)):new Mu(this,new vl(\"string\"),ap(),d7(this));this.UE=d?$P(this.zk,new Ep(\"true\"),O().c,d7(this)):new Mu(this,new vl(\"true\"),M6(new Ep(\"bool\")),d7(this));this.TI=d?$P(this.zk,new Ep(\"false\"),O().c,d7(this)):new Mu(this,new vl(\"false\"),M6(new Ep(\"bool\")),d7(this));this.RE=$P(this.zk,new Ep(\"Annotation\"),O().c,d7(this));this.lP=new nC(this,new vl(\"Eql\"),ap(),V(this));this.Bk=new vl(\"error\");\nO();var e=G(new H,\"unit\",this.Ck),g=G(new H,\"bool\",this.lg),h=G(new H,\"int\",this.ki),k=G(new H,\"number\",this.Ak),l=G(new H,\"string\",this.Qj),m=G(new H,\"anything\",this.La),n=[e,g,h,k,l,m,G(new H,\"nothing\",this.ib)],r=J(new K,n);this.WI=Pd(u(),r);this.bn=new Kq(0,0,new Ge(\"\\x3cprelude\\x3e\",0,Gaa()));t();var v=Bp(),x=new Ep(\"Object\"),A=O().c,B=t().d,C=t().d,D=t().d,F=O().c,I=t().d,M=t().d,N=new Dt(O().c),P=t().d;t();var T=new yo(v,x,A,B,C,D,F,I,M,N,P,new L(this.bn),O().c),Y=Fp(),Z=new Ep(\"Eql\");t();\nvar S=ou().AA,ea=G(new H,new L(S),new Ep(\"A\")),ia=O().c,X=new z(ea,ia),sa=t().d,Ja=t().d,Xa=t().d,Fa=O().c,za=t().d,Qa=t().d,Ma=new Dt(O().c),Ga=t().d;t();var ab=new yo(Y,Z,X,sa,Ja,Xa,Fa,za,Qa,Ma,Ga,new L(this.bn),O().c),Hb=Bp(),bc=new Ep(\"Num\"),yb=O().c,tb=t().d,eb=t().d,kb=t().d,Rb=O().c,Gb=t().d,vb=t().d,Tb=new Dt(O().c),Nb=t().d;t();var ic=new yo(Hb,bc,yb,tb,eb,kb,Rb,Gb,vb,Tb,Nb,new L(this.bn),O().c),Va=Bp(),cb=new Ep(\"Int\"),zb=O().c,Ub=t().d,jb=t().d,db=t().d,ub=new vl(\"Num\"),Aa=O().c,va=new z(ub,\nAa),Ra=t().d,rb=t().d,xb=new Dt(O().c),mc=t().d;t();var Ha=new yo(Va,cb,zb,Ub,jb,db,va,Ra,rb,xb,mc,new L(this.bn),O().c),Ka=Bp(),Oa=new Ep(\"Bool\"),Na=O().c,Da=t().d,ta=t().d;t();var Ya=new iP(new Ep(\"true\"),new Ep(\"false\")),dc=new L(Ya),ka=O().c,ya=t().d,Sa=t().d,xc=new Dt(O().c),Sb=t().d;t();var uc=new yo(Ka,Oa,Na,Da,ta,dc,ka,ya,Sa,xc,Sb,new L(this.bn),O().c),Lb=zp(),lc=new Ep(\"true\"),Xb=O().c,ec=t().d,Ab=t().d,Ob=t().d,fb=new vl(\"Bool\"),Wa=O().c,bb=new yo(Lb,lc,Xb,ec,Ab,Ob,new z(fb,Wa),t().d,t().d,\nnew Dt(O().c),t().d,t().d,O().c),Ia=zp(),Ua=new Ep(\"false\"),pc=O().c,sc=t().d,Ba=t().d,ob=t().d,nc=new vl(\"Bool\"),Ib=O().c,vc=new yo(Ia,Ua,pc,sc,Ba,ob,new z(nc,Ib),t().d,t().d,new Dt(O().c),t().d,t().d,O().c),Vb=Bp(),fc=new Ep(\"Str\"),Bc=O().c,Pb=t().d,Jb=t().d,gc=t().d,Cb=O().c,cc=t().d,yc=t().d,Mc=new Dt(O().c),qc=t().d;t();var oc=new yo(Vb,fc,Bc,Pb,Jb,gc,Cb,cc,yc,Mc,qc,new L(this.bn),O().c),Qc=Ap(),jc=new Ep(\"undefined\"),sb=O().c,Gc=t().d,Wb=t().d;t();var Cc=new oP(new Gm(!0)),Fc=new L(Cc),qd=O().c,\nYb=t().d,Nc=t().d,ad=new Dt(O().c),Uc=t().d;t();var cd=new yo(Qc,jc,sb,Gc,Wb,Fc,qd,Yb,Nc,ad,Uc,new L(this.bn),O().c),kc=Ap(),Vc=new Ep(\"null\"),Hc=O().c,rc=t().d,sd=t().d;t();var Kc=new oP(new Gm(!1)),Qd=new L(Kc),Ad=O().c,kd=t().d,Hd=t().d,Rd=new Dt(O().c),Bd=t().d;t();var ae=new yo(kc,Vc,Hc,rc,sd,Qd,Ad,kd,Hd,Rd,Bd,new L(this.bn),O().c),dd=Bp(),od=new Ep(\"Annotation\"),Ta=O().c,wb=t().d,$a=t().d,wa=t().d,hb=O().c,ra=t().d,wc=t().d,ac=new Dt(O().c),Id=t().d;t();var ud=new yo(dd,od,Ta,wb,$a,wa,hb,ra,\nwc,ac,Id,new L(this.bn),O().c),be=Bp(),re=new Ep(\"Code\");t();var pe=ou().Zu,bd=new L(pe),Rc=new Ep(\"T\"),Wc=G(new H,bd,Rc);t();var Wd=ou().Zu,zd=new L(Wd),Pa=new Ep(\"C\"),Db=G(new H,zd,Pa),Oc=O().c,Tc=new z(Wc,new z(Db,Oc)),Sd=t().d,Jc=t().d,vd=t().d,hd=O().c,de=t().d,ye=t().d,jf=new Dt(O().c),af=t().d;t();var pf=new yo(be,re,Tc,Sd,Jc,vd,hd,de,ye,jf,af,new L(this.bn),O().c),kf=Bp(),Be=new Ep(\"Var\");t();var Kd=ou().Yl,ld=new L(Kd),Jd=new Ep(\"T\"),Dd=G(new H,ld,Jd);t();var Xd=ou().Yl,Yc=new L(Xd),Ce=new Ep(\"C\"),\nte=G(new H,Yc,Ce),Ie=O().c,Jf=new z(Dd,new z(te,Ie)),df=t().d,vg=t().d,wg=t().d,xg=new vl(\"Code\"),eg=new Ep(\"T\"),vh=new Ep(\"C\"),fg=O().c,ih=new Il(xg,new z(eg,new z(vh,fg))),Ig=O().c,Tf=new z(ih,Ig),Jg=t().d,jh=t().d,yg=new Dt(O().c),gg=t().d;t();var Cf=[T,ab,ic,Ha,uc,bb,vc,oc,cd,ae,ud,pf,new yo(kf,Be,Jf,df,vg,wg,Tf,Jg,jh,yg,gg,new L(this.bn),O().c)],Uf=J(new K,Cf);this.qP=Pd(u(),Uf);var $g=new YX(this,Bp(),new Ep(\"?\"),O().c,this.La,O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),Ah=new YX(this,Bp(),\nnew Ep(\"int\"),O().c,this.La,O().c,O().c,M6(new Ep(\"number\")),t().d,O().c,(c3(this),t().d)),Kg=new YX(this,Bp(),new Ep(\"number\"),O().c,this.La,O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),Vf=new YX(this,Bp(),new Ep(\"bool\"),O().c,this.La,O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),hg=new YX(this,Bp(),new Ep(\"true\"),O().c,this.La,O().c,O().c,M6(new Ep(\"bool\")),t().d,O().c,(c3(this),t().d)),zg=new YX(this,Bp(),new Ep(\"false\"),O().c,this.La,O().c,O().c,M6(new Ep(\"bool\")),t().d,O().c,(c3(this),t().d)),\nLg=new YX(this,Bp(),new Ep(\"string\"),O().c,this.La,O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),Mg=new YX(this,Ap(),new Ep(\"undefined\"),O().c,new Mu(this,new Gm(!0),ap(),V(this)),O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),Wf=new YX(this,Ap(),new Ep(\"null\"),O().c,new Mu(this,new Gm(!1),ap(),V(this)),O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),Ng=new YX(this,Ap(),new Ep(\"anything\"),O().c,this.La,O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),Kf=new YX(this,Ap(),new Ep(\"nothing\"),O().c,this.ib,\nO().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),xf=new YX(this,Bp(),new Ep(\"error\"),O().c,this.La,O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),Og=new YX(this,Bp(),new Ep(\"unit\"),O().c,this.La,O().c,O().c,ap(),t().d,O().c,(c3(this),t().d)),mi=d7(this),Ci=t().d,Xh=t().d,wh=O().c,Bh=O().c,ng=new lx(this,1,wh,Bh,Ci,Xh,!1,mi),kh=Ap(),Kh=new Ep(\"Array\");O();var ni=new Ep(\"A\"),Lh=[G(new H,ni,ng)],lh=J(new K,Lh),Ch=new YX(this,kh,Kh,Pd(u(),lh),new Sv(this,new Uw(this,R(),ng,d7(this)),d7(this)),O().c,O().c,\nap(),t().d,O().c,(c3(this),t().d));t();var Dh=Xu(),Yh=ou().Zu,ah=[G(new H,ng,Yh)],oi=Dh.Hh(J(new K,ah));Ch.Nu=new L(oi);var mj=d7(this),wd=t().d,ge=t().d,De=O().c,qf=O().c,og=new lx(this,1,De,qf,wd,ge,!1,mj),Xf=Ap(),mh=new Ep(\"MutArray\");O();var Ag=new Ep(\"A\"),Bg=[G(new H,Ag,og)],Eh=J(new K,Bg),Pg=new YX(this,Xf,mh,Pd(u(),Eh),new Sv(this,new Uw(this,new L(og),og,d7(this)),d7(this)),O().c,O().c,ap(),t().d,O().c,(c3(this),t().d));t();var Di=Xu(),Mh=ou().Yl,pi=[G(new H,og,Mh)],Xi=Di.Hh(J(new K,pi));\nPg.Nu=new L(Xi);var Qg=O().c;this.XE=new z($g,new z(Ah,new z(Kg,new z(Vf,new z(hg,new z(zg,new z(Lg,new z(Mg,new z(Wf,new z(Ng,new z(Kf,new z(xf,new z(Og,new z(Ch,new z(Pg,Qg)))))))))))))));var nh=this.XE.m(),bh=new Ef(nh,new y(ev=>ev.Wl.V)),Mj=new xo(bh,new y(ev=>{var m0=UF(ve(),ev);ev=Nu(Q(),ev);var iga=O().c;return new z(m0,new z(ev,iga))}));this.cn=Aq(Bq(),Mj).bc(\"Object\").bc(\"Num\").bc(\"Str\");this.tP=this.cn.bc(\"Eql\");var Nj=V(this),ie=t().d,Ac=t().d,Ve=O().c,Td=O().c;this.XI=new lx(this,1,Ve,\nTd,ie,Ac,!1,Nj);var lf=V(this),Yi=t().d,Jl=t().d,ll=O().c,Bj=O().c,$k=new lx(this,1,ll,Bj,Yi,Jl,!1,lf),Zh=d?new Gp(new cv(this,e7(this,this.ki,this.ki),this.ki,V(this)),new cv(this,e7(this,this.Ak,this.Ak),this.Ak,V(this)),new cv(this,e7(this,this.Ak,this.Ak),this.lg,V(this)),new cv(this,e7(this,this.Qj,this.Qj),this.lg,V(this))):new Gp(new cv(this,Y6(this,this.ki),new cv(this,Y6(this,this.ki),this.ki,V(this)),V(this)),new cv(this,Y6(this,this.Ak),new cv(this,Y6(this,this.Ak),this.Ak,V(this)),V(this)),\nnew cv(this,Y6(this,this.Ak),new cv(this,Y6(this,this.Ak),this.lg,V(this)),V(this)),new cv(this,Y6(this,this.Qj),new cv(this,Y6(this,this.Qj),this.lg,V(this)),V(this)));if(null!==Zh)var Ei=new Gp(Zh.Uj,Zh.oj,Zh.oi,Zh.Xi);else throw new w(Zh);var Yd=Ei.Uj,bf=Ei.oj,rf=Ei.oi,Cg=Ei.Xi;tp();var nj=G(new H,\"true\",this.UE),Jh=G(new H,\"false\",this.TI),If=new fw(this,new Ep(\"True\"),O().c,V(this)),Hg=G(new H,\"True\",If),He=new fw(this,new Ep(\"False\"),O().c,V(this)),lj=G(new H,\"False\",He),Wi=G(new H,\"NaN\",this.Ak),\nOj=G(new H,\"document\",this.ib),mo=G(new H,\"window\",this.ib),mm=new cv(this,Y6(this,this.La),this.Qj,V(this)),nm=G(new H,\"typeof\",mm),dq=new cv(this,Y6(this,this.La),this.Qj,V(this)),Zd=G(new H,\"toString\",dq),sf=new cv(this,Y6(this,this.La),this.Qj,V(this)),oj=G(new H,\"String\",sf),al=new cv(this,Y6(this,this.lg),this.lg,V(this)),Ll=G(new H,\"not\",al),Qm=new cv(this,Y6(this,this.ki),this.ki,V(this)),Rm=G(new H,\"succ\",Qm),hq=new Qx(this,this.Gd,new cv(this,Y6(this,$k),this.Ck,V(this))),Bn=G(new H,\"log\",\nhq),hp=new Qx(this,this.Gd,new cv(this,Y6(this,$k),this.Ck,V(this))),ru=G(new H,\"discard\",hp),qr=new cv(this,Y6(this,this.ki),this.ki,V(this)),Xs=G(new H,\"negate\",qr),rr=new cv(this,Y6(this,this.Ak),this.ki,V(this)),iq=G(new H,\"round\",rr),qo=G(new H,\"add\",Yd),qm=G(new H,\"sub\",Yd),jq=G(new H,\"mul\",Yd),pl=G(new H,\"div\",Yd),ro=new cv(this,Y6(this,this.ki),this.ki,V(this)),Cn=G(new H,\"sqrt\",ro),ip=G(new H,\"lt\",rf),so=G(new H,\"le\",rf),Dn=G(new H,\"gt\",rf),sr=G(new H,\"ge\",rf),kq=G(new H,\"slt\",Cg),ql=G(new H,\n\"sle\",Cg),Ys=G(new H,\"sgt\",Cg),Sm=G(new H,\"sge\",Cg),Nl=new cv(this,Y6(this,this.Qj),this.ki,V(this)),jp=G(new H,\"length\",Nl),lq=new cv(this,Y6(this,this.Qj),new cv(this,Y6(this,this.Qj),this.Qj,V(this)),V(this)),mq=G(new H,\"concat\",lq),Tm=this.Qj,En=V(this),to=new cv(this,new Sv(this,new Uw(Tm.q,R(),Tm,En),V(this)),this.Qj,V(this)),Fn=G(new H,\"join\",to),nq=V(this),Um=t().d,kp=t().d,oq=O().c,su=O().c,Gn=new lx(this,1,oq,su,Um,kp,!1,nq),ur=new Qx(this,this.Gd,new cv(this,Y6(this,Gn),new cv(this,Y6(this,\nGn),this.lg,V(this)),V(this))),In=G(new H,\"eq\",ur),Zs=V(this),$s=t().d,pq=t().d,vr=O().c,Vm=O().c,Jn=new lx(this,1,vr,Vm,$s,pq,!1,Zs),wr=new Qx(this,this.Gd,new cv(this,Y6(this,Jn),new cv(this,Y6(this,Jn),this.lg,V(this)),V(this))),at=G(new H,\"ne\",wr),xr=G(new H,\"error\",this.ib),lp=this.XI,Kn=this.Gd,qq=t().d,yr=this.La,rq=V(this),sq=new Uw(yr.q,R(),yr,rq),bt=G(new H,qq,sq),tq=t().d,zr=V(this),ct=new Uw(lp.q,R(),lp,zr),Ar=G(new H,tq,ct),uq=O().c,Br=new Qx(this,Kn,new cv(this,new zv(this,new z(bt,\nnew z(Ar,uq)),V(this)),lp,V(this))),Ln=G(new H,\",\",Br),vq=G(new H,\"+\",Yd),Cr=G(new H,\"-\",Yd),tu=G(new H,\"*\",Yd),uu=G(new H,\"+.\",bf),dt=G(new H,\"-.\",bf),vu=G(new H,\"*.\",bf),Dr=G(new H,\"%\",Yd),uo=G(new H,\"/\",bf),Er=G(new H,\"\\x3c\",rf),et=G(new H,\"\\x3e\",rf),ft=G(new H,\"\\x3c\\x3d\",rf),gt=G(new H,\"\\x3e\\x3d\",rf),Wm=G(new H,\"\\x3d\\x3d\",rf),Fr=this.XI,mp=new Ep(\"Eql\"),wu=O().c,ht=new fw(this,mp,new z(Fr,wu),V(this)),wq=new Qx(this,this.Gd,new cv(this,e7(this,ht,Fr),this.lg,V(this))),xq=G(new H,\"\\x3d\\x3d\\x3d\",\nwq),Gr=G(new H,\"\\x3c\\x3e\",rf),xu=d?new cv(this,e7(this,this.lg,this.lg),this.lg,V(this)):new cv(this,Y6(this,this.lg),new cv(this,Y6(this,this.lg),this.lg,V(this)),V(this)),yu=G(new H,\"\\x26\\x26\",xu),Re=d?new cv(this,e7(this,this.lg,this.lg),this.lg,V(this)):new cv(this,Y6(this,this.lg),new cv(this,Y6(this,this.lg),this.lg,V(this)),V(this)),rj=G(new H,\"||\",Re),ai=V(this),rm=t().d,Nn=t().d,zu=O().c,Au=O().c,Av=new lx(this,1,zu,Au,rm,Nn,!1,ai),oy=new Qx(this,this.Gd,new cv(this,Y6(this,Av),Av,V(this))),\nBv=G(new H,\"id\",oy),Cv=V(this),py=t().d,qy=t().d,Dv=O().c,Ee=O().c,Ca=new lx(this,1,Dv,Ee,py,qy,!1,Cv),Lc=new Qx(this,this.Gd,new cv(this,Y6(this,this.lg),new cv(this,Y6(this,Ca),new cv(this,Y6(this,Ca),Ca,V(this)),V(this)),V(this))),yd=G(new H,\"if\",Lc),Qe=V(this),Xj=t().d,fl=t().d,Gk=O().c,$n=O().c,$R=new lx(this,1,Gk,$n,Xj,fl,!1,Qe),jga=new Qx(this,0,new Sv(this,new Uw(this,(t(),new L($R)),$R,V(this)),V(this))),kga=G(new H,\"emptyArray\",jga),lga=V(this),mga=t().d,nga=t().d,oga=O().c,pga=O().c,a$=\nnew lx(this,1,oga,pga,mga,nga,!1,lga),qga=new Ep(\"Code\"),rga=this.ib,sga=O().c,tga=new Qx(this,0,new cv(this,Y6(this,new fw(this,qga,new z(a$,new z(rga,sga)),V(this))),a$,V(this))),uga=G(new H,\"run\",tga),vga=Y6(this,this.ki),wga=new Ep(\"Code\"),xga=this.ki,yga=this.ib,zga=O().c,Aga=new cv(this,vga,new fw(this,wga,new z(xga,new z(yga,zga)),V(this)),V(this)),Bga=[nj,Jh,Hg,lj,Wi,Oj,mo,nm,Zd,oj,Ll,Rm,Bn,ru,Xs,iq,qo,qm,jq,pl,Cn,ip,so,Dn,sr,kq,ql,Ys,Sm,jp,mq,Fn,In,at,xr,Ln,vq,Cr,tu,uu,dt,vu,Dr,uo,Er,et,\nft,gt,Wm,xq,Gr,yu,rj,Bv,yd,kga,uga,G(new H,\"Const\",Aga)],Cga=J(new K,Bga),Dga=pp(0,Cga);if(d)b$=O().c;else var Ega=this.WI,Fga=Qt(this.WI,new y(ev=>{var m0=Nu(Q(),ev.h());return G(new H,m0,ev.j())})),b$=un(Ega,Fga);this.nP=Dga.bf(b$);this.uP=Aq(tp().Iv,J(new K,\"| \\x26 ~ neg and or is\".split(\" \")));this.YE=0}hf.prototype=new t5;hf.prototype.constructor=hf;function raa(a){null===a.SE&&null===a.SE&&(a.SE=new KP(a));return a.SE}function V(a){null===a.TE&&null===a.TE&&(a.TE=new R_(a));return a.TE}\nfunction yC(a){null===a.WE&&null===a.WE&&(a.WE=new zC(a));return a.WE}function f7(a){null===a.VE&&null===a.VE&&(a.VE=new sC(a));return a.VE}function ny(a,b,c){var d=b.A();b=hu(b);tx(a);var e=t().d;return jx(new kx,a,d,b,e,c)}function d7(a){var b=t().d;tx(a);var c=t().d;return jx(new kx,a,b,\"type\",c,!0)}function Y6(a,b){var c=t().d,d=b.ma();b=G(new H,c,new Uw(b.q,R(),b,d));c=O().c;return new zv(a,new z(b,c),V(a))}\nfunction e7(a,b,c){var d=t().d,e=b.ma();b=new Uw(b.q,R(),b,e);d=G(new H,d,b);b=t().d;e=c.ma();c=new Uw(c.q,R(),c,e);c=G(new H,b,c);b=O().c;return new zv(a,new z(d,new z(c,b)),V(a))}function ox(a,b,c,d,e,g){return aga(a,b,c,d,e,g).h()}\nfunction aga(a,b,c,d,e,g){var h=new y(v=>\"\\x3d\\x3e \"+v.h()+\" \\u2014\\u2014\\u2014 \"+ze(v.j(),\"\",\", \",\"\"));if(a.F){var k=ut(Q(),\"| \",a.r)+\"Typing type \"+wO(Xe(),b).Wr();ff(gf(),k+\"\\n\")}a.r=1+a.r|0;try{if(a.F){var l=ut(Q(),\"| \",a.r)+(\"vars\\x3d\"+e+\" newDefsInfo\\x3d\")+g;ff(gf(),l+\"\\n\")}var m=c.da,n=Xu().X(),r=G(new H,Sfa(a,b,c,nf(),d,!0,e,n,m,g,c),new rp(n))}finally{a.r=-1+a.r|0}dx(new E(h),a.qa)&&a.F&&(a=\"\"+ut(Q(),\"| \",a.r)+h.n(r),ff(gf(),a+\"\\n\"));return r}\nfunction g7(a,b,c,d,e){return Rw(a,b,new Iw(c.S,c.Ec,c.hc,c.Ed,c.da,c.Pc,c.Zc,c.Lb,!0,c.tb,c.$a,c.od,c.cb),d,e,!1)}\nfunction ty(a,b,c,d,e,g,h){var k=!1,l=null;if(b instanceof No){k=!0;l=b;var m=l.oq,n=l.vu;if(!1===l.ls&&null!==m&&\"_\"===m.x&&n instanceof fe)return ty(a,n.aa,c,d,e,g,h)}if(k&&(m=l.ls,k=l.oq,l=l.vu,l instanceof fe))return b=l.aa,\"_\"===k.x&&(h=new Te(new Ue(J(new K,[\"Illegal definition name: \",\"\"]))),c=[We(Xe(),k.x)],Lw(a,Ye(h,J(new K,c)),k.A(),e)),b=h7(a,m,k.x,b,d,e,g),t(),g=i7(a),k.kt=new L(g),g=k.x,h=new qx(a,b,k),Wx(d,G(new H,g,h)),t(),t(),d=G(new H,k.x,b),new Ud(new L(d));if(b instanceof Gl&&(k=\nb.Ra,!c)){a:{if(k instanceof z&&(m=k.z,c=k.p,null!==m&&(m.h()instanceof L?(m=O().c,c=null===m?null===c:m.i(c)):c=!1,c))){k=\"field\";break a}c=O().c;k=(null===c?null===k:c.i(k))?\"empty tuple\":\"tuple\"}JX(a,We(Xe(),\"Useless \"+k+\" in statement position.\"),b.A(),e);t();d=new Qx(a,a.Gd,Rw(a,b,d,e,g,h));return new fe(d)}if(b instanceof Pm)return g=Rw(a,b,d,e,g,h),c||(b instanceof vl||b instanceof Dl?JX(a,We(Xe(),\"Pure expression does nothing in statement position.\"),b.A(),e):(h=ux(a,g,jx(new kx,a,Lq(b),\"expression in statement position\",\n(tx(a),t().d),(tx(a),!1))),k=a.Ck,c=new y(r=>{fr();var v=Ye(new Te(new Ue(J(new K,[\"Expression in statement position should have type `unit`.\"]))),u()),x=t().d;v=G(new H,v,x);x=Ye(new Te(new Ue(J(new K,[\"Use the `discard` function to discard non-unit values, making the intent clearer.\"]))),u());var A=t().d;x=G(new H,x,A);e.n(hr(0,new z(v,new z(x,r.vt())),a.$c,lu()))}),b=jx(new kx,a,b.A(),hu(b),(tx(a),t().d),(tx(a),!1)),m=Sw(a).ob,Tw(a,h,k,c,b,d,m))),t(),new fe(g);d=new Te(new Ue(J(new K,[\"Illegal position for this \",\n\" statement.\"])));g=[We(Xe(),b.jb())];Lw(a,Ye(d,J(new K,g)),b.A(),e);t();d=t().d;return new Ud(d)}\nfunction h7(a,b,c,d,e,g,h){var k=jx(new kx,a,d.A(),\"binding of \"+hu(d),(tx(a),t().d),(tx(a),!1));if(b){var l=V(a);b=t().d;t();var m=new L(c),n=O().c,r=O().c;l=new lx(a,1+e.da|0,n,r,b,m,!0,l);b=new qx(a,l,new vl(c));Wx(e,G(new H,c,b));t();c=new vl(c);var v=new Iw(e.S,e.Ec,e.hc,e.Ed,e.da,e.Pc,e.Zc,e.Lb,e.yc,e.tb,e.$a,new L(c),e.cb);c=1+v.da|0;b=Hw();m=Su();n=op().ga;b=b.Hd(new Uu(m,n));c=new Iw(v.S,v.Ec,v.hc,v.Ed,c,v.Pc,v.Zc,v.Lb,v.yc,v.tb,v.$a,v.od,b);t();d=Rw(a,d,c,g,h,a.rP);h=Sw(a).ob;Tw(a,d,l,g,\nk,c,h);wy(l,(t(),new L(d)));d=c.cb;up(tp(),v.S.li||c.cb.b());if(!d.b()){h=v.S.qa;c=v.S;c.F&&(b=ut(Q(),\"| \",c.r)+\"UNSTASHING... (out)\",ff(gf(),b+\"\\n\"));c.r=1+c.r|0;try{d.Ca(new y(A=>{if(null!==A){var B=A.h();for(A=A.j().m();A.s();){var C=A.t();a:{if(null!==C){var D=C.j();if(!0===C.Rc()){C=Sw(v.S).ob;Tw(v.S,D,B,g,k,v,C);break a}}if(null!==C&&(D=C.j(),!1===C.Rc())){C=Sw(v.S).ob;Tw(v.S,B,D,g,k,v,C);break a}throw new w(C);}}}else throw new w(A);}));d.mg();var x=void 0}finally{c.r=-1+c.r|0}dx(new E(h),\nc.qa)&&c.F&&(d=\"\"+ut(Q(),\"| \",c.r)+h.n(x),ff(gf(),d+\"\\n\"))}d=l}else if(x=1+e.da|0,c=Hw(),b=Su(),m=op().ga,c=c.Hd(new Uu(b,m)),x=new Iw(e.S,e.Ec,e.hc,e.Ed,x,e.Pc,e.Zc,e.Lb,e.yc,e.tb,e.$a,e.od,c),d=Rw(a,d,x,g,h,!0),h=x.cb,up(tp(),e.S.li||x.cb.b()),!h.b()){x=e.S.qa;c=e.S;c.F&&(b=ut(Q(),\"| \",c.r)+\"UNSTASHING... (out)\",ff(gf(),b+\"\\n\"));c.r=1+c.r|0;try{h.Ca(new y(((A,B)=>C=>{if(null!==C){var D=C.h();for(C=C.j().m();C.s();){var F=C.t();a:{if(null!==F){var I=F.j();if(!0===F.Rc()){F=Sw(A.S).ob;Tw(A.S,I,D,\ng,k,B,F);break a}}if(null!==F&&(I=F.j(),!1===F.Rc())){F=Sw(A.S).ob;Tw(A.S,D,I,g,k,B,F);break a}throw new w(F);}}}else throw new w(C);})(e,e))),h.mg(),l=void 0}finally{c.r=-1+c.r|0}dx(new E(x),c.qa)&&c.F&&(h=\"\"+ut(Q(),\"| \",c.r)+x.n(l),ff(gf(),h+\"\\n\"))}return new Qx(a,e.da,d)}function ux(a,b,c){if(a.sP){var d=b.ma();return Ot(new E(d),c)?b:new OA(a,b,c)}return b}function W6(a,b,c,d,e){return Rw(a,b,c,d,e,!1)}\nfunction j7(a,b,c,d){if(b.Lb){var e=d7(a),g=t().d,h=t().d,k=O().c,l=O().c,m=new lx(a,b.da,k,l,g,h,!1,e);e=fY(c);c=Tea(c,m);g=new y(n=>{if(n instanceof Ff){var r=Ey(a),v=new y(()=>{}),x=V(a),A=Sw(a).ob;Tw(a,r,m,v,x,b,A)}d.n(n)});h=V(a);k=Sw(a).ob;Tw(a,e,c,g,h,b,k);gY(b,m)}}\nfunction Rw(a,b,c,d,e,g){return Lx(a,new U(()=>c.da+\". Typing \"+(c.yc?\"pattern\":\"term\")+\" \"+b),new U(()=>{var h=ny(a,b,!1),k=!1,l=null,m=!1,n=null,r=!1,v=null,x=!1,A=null,B=!1,C=null,D=!1,F=null,I=!1,M=null,N=!1,P=null;if(b instanceof vl&&(k=!0,l=b,\"_\"===l.x)){if(c.yc){var T=jx(new kx,a,l.A(),\"wildcard\",(tx(a),t().d),(tx(a),!1)),Y=t().d,Z=t().d,S=O().c,ea=O().c;return new lx(a,c.da,S,ea,Y,Z,!1,T)}return Lw(a,Ye(new Te(new Ue(J(new K,[\"Widlcard in expression position.\"]))),u()),l.A(),d)}if(b instanceof\nMl){var ia=b.Ml,X=Rw(a,b.gs,c,d,e,g);Q6(a,X,a.RE,a.Ck,c,d,h);return Rw(a,ia,c,d,e,g)}if(b instanceof Cl){m=!0;n=b;var sa=n.ai,Ja=n.Fm;if(sa instanceof vl){var Xa=tC(f7(a),sa,c,d);if(!Xa.b()){var Fa=Xa.o(),za=new Iw(c.S,c.Ec,c.hc,c.Ed,c.da,c.Pc,c.Zc,c.Lb,!1,c.tb,c.$a,c.od,c.cb),Qa=nf(),Ma=ox(a,Ja,za,d,e,Qa);jx(new kx,a,a.$E?sa.A():t().d,\"variable\",(tx(a),t().d),(tx(a),!1));var Ga=c.hc.U(Fa);if(Ga instanceof L)return Lw(a,We(Xe(),\"Duplicate use of annotated pattern variable \"+Fa),sa.A(),d);if(t().d===\nGa){var ab=new qx(a,Ma,sa);Wx(c,G(new H,Fa,ab));return Ma}throw new w(Ga);}}}if(m){var Hb=n.Fm,bc=Rw(a,n.ai,c,d,e,!0),yb=new Iw(c.S,c.Ec,c.hc,c.Ed,c.da,c.Pc,c.Zc,c.Lb,!1,c.tb,c.$a,c.od,c.cb),tb=nf(),eb=ox(a,Hb,yb,d,e,tb);if(c.yc){var kb=Sw(a).ob;KX(a,bc,eb,d,h,c,kb);return eb}return Q6(a,bc,eb,eb,c,d,h)}if(k){var Rb=tC(f7(a),l,c,d);if(!Rb.b()){var Gb=Rb.o(),vb=jx(new kx,a,a.$E?l.A():t().d,\"variable\",(tx(a),t().d),(tx(a),!1)),Tb=c.hc.U(Gb),Nb=new N_(a,l);if(Tb.b())cb=R();else var ic=new Wr(Nb),Va=\nTb.o(),cb=Vr(ic,Va);var zb=new U((Ca=>()=>{var Lc=new lx(a,c.da,O().c,O().c,t().d,zy(ju(),a.F,new U(()=>Gb)),(TP(a),!1),vb);t();var yd=i7(a);Ca.kt=new L(yd);yd=new qx(a,Lc,Ca);Wx(c,G(new H,Gb,yd));return Lc})(l));return cb.b()?Es(zb):cb.o()}}if(k){var Ub=xC(yC(a),l,d);if(!Ub.b()){var jb=Ub.k,db=uC(c,c,jb),ub=new U(()=>Lw(a,We(Xe(),\"identifier not found: \"+jb),b.A(),d)),Aa=new y(Ca=>{if(Ca instanceof qx){Ca=Ca.tp;if(c.Lb){var Lc=eY(c,jb),yd=new y(Qe=>{gY(c,Qe)});Lc.b()||yd.n(Lc.o())}return Ca}if(Ca instanceof\nVP){if(Ca instanceof ix){Lc=Ca.kh;if(Lc instanceof bx)return Lc.Nn();if(Lc instanceof Vw)return Lc.ig.ra;if(Lc instanceof Yw)return R6(a,Lc.Rf,b,d),Dy(Lc.nc,!1,h.Ga,Lc.Rf,Lc.Sm,Lc.gh,Lc.Ij,Lc.gl,0,d);if(Lc&&Lc.$classData&&Lc.$classData.rb.Rs)return Ca=new Te(new Ue(J(new K,[\"\",\" \",\" cannot be used in term position\"]))),Lc=[We(Xe(),Lc.fd().ld),We(Xe(),Lc.Ua())],Lw(a,Ye(Ca,J(new K,Lc)),h.Ga,d);throw new w(Lc);}if(Ca instanceof fx)return R6(a,Ca.Ab,b,d),Cy(Ca,!1,h.Ga,d)}throw new w(Ca);}),va=db.b()?\nEs(ub):Aa.n(db.o());return ux(a,va,h)}}if(b instanceof Dl)return new Mu(a,b,a.$c?yq(b):fq(b),h);if(b instanceof am){Lw(a,We(Xe(),\"Illegal use of `super`\"),b.A(),d);var Ra=new vl(\"super\"),rb=b.A();return Rw(a,Cq(Ra,rb),c,d,e,g)}if(b instanceof Pl){r=!0;v=b;var xb=v.Za;if(xb instanceof vl){var mc=xb.x;\"neg\"!==mc&&\"~\"===mc}}if(r){var Ha=v.Za;if(Ha instanceof Pl){var Ka=Ha.Za;Ka instanceof vl&&\"|\"===Ka.x}}if(r){var Oa=v.Za;if(Oa instanceof Pl){var Na=Oa.Za;Na instanceof vl&&\"\\x26\"===Na.x}}if(b instanceof\nyl){var Da=b.ll,ta=jx(new kx,a,b.A(),\"record literal\",(tx(a),t().d),(tx(a),!1));ET(Da,new y(Ca=>Ca.h().x),new y(Ca=>Ca.h())).Ca(new y(Ca=>{if(null!==Ca&&(Ca=new L(Ca),!Ca.b())){var Lc=Ca.k.h();Ca=Ca.k.j();if(0<Ca.ab(1)){var yd=new Te(new Ue(J(new K,[\"Multiple declarations of field name \",\" in \",\"\"])));Lc=[We(Xe(),Lc),We(Xe(),ta.lh)];Lc=Ye(yd,J(new K,Lc));yd=b.A();Lc=G(new H,Lc,yd);Ca=Qt(Ca,new y(Qe=>{var Xj=Ye(new Te(new Ue(J(new K,[\"Declared at\"]))),u());Qe=Qe.A();return G(new H,Xj,Qe)}));return ay(a,\nnew z(Lc,Ca),d)}}}));return SA(xv(a),Qt(Da,new y(Ca=>{if(null!==Ca){var Lc=Ca.h(),yd=Ca.j();if(null!==yd){var Qe=yd.yb;yd=yd.ya;if(null!==Qe){Qe=Qe.je;hB(ve(),Lc.x)&&Lw(a,Ye(new Te(new Ue(J(new K,[\"Field identifiers must start with a small letter\"]))),u()),b.A(),d);Ca=Rw(a,yd,c,d,e,!0);yd=jx(new kx,a,(new Pl(Lc,yd)).A(),(Qe?\"mutable \":\"\")+\"record field\",(tx(a),t().d),(tx(a),!1));if(Qe){Qe=t().d;t();var Xj=new L(Lc.x),fl=O().c,Gk=O().c;Qe=new lx(a,c.da,fl,Gk,Qe,Xj,!1,yd);Ca=Q6(a,Ca,Qe,Qe,c,d,h);return G(new H,\nLc,new Uw(a,new L(Ca),Ca,yd))}return G(new H,Lc,new Uw(Ca.q,R(),Ca,yd))}}}throw new w(Ca);})),ta)}b instanceof Gl&&(x=!0,A=b);if(x){var Ya=A.Ra,dc=Qt(bga(Ya,Ya,new y(Ca=>{if(null!==Ca){var Lc=Ca.h(),yd=Ca.j();if(null!==yd){var Qe=yd.yb,Xj=yd.ya;if(Lc instanceof L&&(yd=Lc.k,c.yc)){Ca=new Cl(yd,nx(Xj,d));yd=yd.A();var fl=new U(()=>Xj.A()),Gk=new y($n=>{$n=Kt($n,Xj.A());return it().n($n)});yd=yd.b()?Es(fl):Gk.n(yd.o());return G(new H,Lc,new sm(Qe,Cq(Ca,yd)))}return Ca}}throw new w(Ca);})),new y(Ca=>\n{if(null!==Ca){var Lc=Ca.h(),yd=Ca.j();if(null!==yd){var Qe=yd.yb;yd=yd.ya;if(null!==Qe){Ca=Qe.je;if(Qe.Bh){Qe=Ye(new Te(new Ue(J(new K,[\"Cannot use `val` in this position\"]))),u());cu();var Xj=Lc.ha();Lw(a,Qe,du(0,new z(yd,Xj)),d)}Qe=Rw(a,yd,c,d,e,!0);yd=jx(new kx,a,yd.A(),(Ca?\"mutable \":\"\")+\"tuple field\",(tx(a),t().d),(tx(a),!1));if(Ca){Ca=t().d;Xj=new y($n=>$n.x);Xj=Lc.b()?R():new L(Xj.n(Lc.o()));var fl=O().c,Gk=O().c;Ca=new lx(a,c.da,fl,Gk,Ca,Xj,!1,yd);Qe=Q6(a,Qe,Ca,Ca,c,d,h);return G(new H,Lc,\nnew Uw(a,new L(Qe),Qe,yd))}return G(new H,Lc,new Uw(Qe.q,R(),Qe,yd))}}}throw new w(Ca);}));a:{var ka=O().c;if(null===ka?null===Ya:ka.i(Ya))var ya=!0;else{if(Ya instanceof z){var Sa=Ya.z,xc=Ya.p;if(null!==Sa){var Sb=Sa.h();if(t().d===Sb)var uc=O().c,Lb=null===uc?null===xc:uc.i(xc);else Lb=!1;if(Lb){ya=!0;break a}}}ya=!1}}return new zv(a,dc,ya?V(a):jx(new kx,a,b.A(),\"tuple literal\",(tx(a),t().d),(tx(a),!1)))}if(b instanceof Vl){var lc=b.mp,Xb=W6(a,b.lp,c,d,e),ec=W6(a,lc,c,d,e);Q6(a,ec,a.ki,a.La,c,d,\nh);var Ab=t().d,Ob=t().d,fb=O().c,Wa=O().c,bb=new lx(a,c.da,fb,Wa,Ab,Ob,!1,h),Ia=rA(bb),Ua=new fw(a,new Ep(\"undefined\"),O().c,V(a)),pc=jx(new kx,h.Wu,h.Ga,\"prohibited undefined element\",h.go,h.Zm),sc=NA(Ua,pc,!1);KA(bb,new z(sc,Ia));var Ba=jx(new kx,a,lc.A(),\"array element\",(tx(a),t().d),(tx(a),!1)),ob=Q6(a,Xb,new Sv(a,new Uw(bb.q,R(),bb,Ba),h),bb,c,d,h),nc=new Ep(\"undefined\"),Ib=O().c,vc=new fw(a,nc,Ib,jx(new kx,h.Wu,h.Ga,\"possibly-undefined array access\",h.go,h.Zm)),Vb=V(ob.q);return dv(ob,vc,Vb,\n!1)}if(b instanceof dm){var fc=b.Zq,Bc=W6(a,b.$q,c,d,e);Q6(a,Bc,a.lg,a.Ck,c,d,h);var Pb=new Gm(!0),Jb=O().c;return Rw(a,new Sl(new z(fc,new z(Pb,Jb))),c,d,e,g)}if(b instanceof Wl){B=!0;C=b;var gc=C.Gm,Cb=C.Qn;if(gc instanceof Ql){var cc=gc.Vl,yc=gc.ml,Mc=W6(a,cc,c,d,e),qc=jx(new kx,a,gc.A(),\"assigned selection\",(tx(a),t().d),(tx(a),!1)),oc=t().d;t();var Qc=yc.x,jc=zy(0,!(0<=Qc.length&&\"_\"===Qc.substring(0,1)),new U(()=>yc.x)),sb=O().c,Gc=O().c,Wb=new lx(a,c.da,sb,Gc,oc,jc,!1,qc),Cc=ux(a,Mc,jx(new kx,\na,Lq(cc),\"receiver\",(tx(a),t().d),(tx(a),!1))),Fc=xv(a),qd=G(new H,yc,new Uw(a,new L(Wb),a.La,jx(new kx,a,yc.A(),\"assigned field\",(tx(a),t().d),(tx(a),!1)))),Yb=O().c;Q6(a,Cc,SA(Fc,new z(qd,Yb),qc),Wb,c,d,h);var Nc=W6(a,Cb,c,d,e),ad=a.Ck;return Q6(a,Nc,Wb,ux(ad.q,ad,h),c,d,h)}}if(B){var Uc=C.Gm,cd=C.Qn;if(Uc instanceof Vl){var kc=Uc.lp,Vc=Uc.mp,Hc=W6(a,kc,c,d,e),rc=jx(new kx,a,Uc.A(),\"assigned array element\",(tx(a),t().d),(tx(a),!1)),sd=t().d,Kc=t().d,Qd=O().c,Ad=O().c,kd=new lx(a,c.da,Qd,Ad,sd,Kc,\n!1,rc),Hd=ux(a,Hc,jx(new kx,a,Lq(kc),\"receiver\",(tx(a),t().d),(tx(a),!1)));Q6(a,Hd,new Sv(a,new Uw(a,new L(kd),kd,rc),h),a.La,c,d,h);var Rd=W6(a,Vc,c,d,e);Q6(a,Rd,a.ki,a.La,c,d,h);var Bd=W6(a,cd,c,d,e),ae=a.Ck;return Q6(a,Bd,kd,ux(ae.q,ae,h),c,d,h)}}if(B){var dd=C.Gm,od=C.Qn;if(dd instanceof vl){var Ta=Rw(a,od,c,d,e,g),wb=!1,$a=null,wa=uC(c,c,dd.x);if(wa instanceof L){wb=!0;$a=wa;var hb=$a.k;if(hb instanceof qx){var ra=a.Ck;return Q6(a,Ta,hb.tp,ux(ra.q,ra,h),c,d,h)}}if(wb){var wc=$a.k;if(wc instanceof\nix){var ac=wc.kh;if(ac instanceof bx){S6(a,ac.Mb,h,d);var Id=ac.Nn(),ud=a.Ck;return Q6(a,Ta,Id,ux(ud.q,ud,h),c,d,h)}}}if(wb){var be=$a.k;if(be instanceof fx){null===a.Qq&&null===a.Qq&&(a.Qq=new BC(a));t();var re=new L(be.Ab);if(!re.b()){var pe=re.k;if(pe instanceof Zn){S6(a,pe,h,d);var bd=Ux(be),Rc=a.Ck;return Q6(a,Ta,bd,ux(Rc.q,Rc,h),c,d,h)}}}}var Wc=Ye(new Te(new Ue(J(new K,[\"Illegal assignment\"]))),u()),Wd=G(new H,Wc,h.Ga),zd=new Te(new Ue(J(new K,[\"cannot assign to \",\"\"]))),Pa=[We(Xe(),hu(dd))],\nDb=Ye(zd,J(new K,Pa)),Oc=dd.A(),Tc=G(new H,Db,Oc),Sd=O().c;return ay(a,new z(Wd,new z(Tc,Sd)),d)}}if(B){var Jc=C.Gm,vd=Ye(new Te(new Ue(J(new K,[\"Illegal assignment\"]))),u()),hd=G(new H,vd,h.Ga),de=new Te(new Ue(J(new K,[\"cannot assign to \",\"\"]))),ye=[We(Xe(),hu(Jc))],jf=Ye(de,J(new K,ye)),af=Jc.A(),pf=G(new H,jf,af),kf=O().c;return ay(a,new z(hd,new z(pf,kf)),d)}if(b instanceof Fl){D=!0;F=b;var Be=F.gg;if(!1===F.bi&&Be instanceof Sl)return Rw(a,Be,c,d,e,g)}if(D)return Rw(a,F.gg,c,d,e,g);if(b instanceof\nSl){I=!0;M=b;var Kd=M.Dj;if(Kd instanceof z){var ld=Kd.z,Jd=Kd.p;if(ld instanceof Pm){var Dd=O().c;if(null===Dd?null===Jd:Dd.i(Jd))return Rw(a,ld,c,d,e,g)}}}if(I){var Xd=M.Dj,Yc=O().c;if(null===Yc?null===Xd:Yc.i(Xd)){var Ce=a.Ck;return ux(Ce.q,Ce,h)}}if(c.yc){var te=new Te(new Ue(J(new K,[\"Unsupported pattern shape\",\":\"]))),Ie=[a.F?We(Xe(),\" (\"+ca(b).u()+\")\"):We(Xe(),\"\")];return Lw(a,Ye(te,J(new K,Ie)),b.A(),d)}if(b instanceof Ol){N=!0;P=b;var Jf=P.Ej,df=P.Fj;if(Pe(new E(g),!0)){Nx(a,new U(()=>\"TYPING POLY LAM\"));\nvar vg=c.Lb?iY(c):tf(c),wg=new y(Ca=>{var Lc=g7(a,Jf,Ca,d,e),yd=Rw(a,df,Ca,d,e,a.VI||Pe(new E(g),!0)&&a.li);j7(a,c,Ca,d);return new cv(a,Lc,yd,jx(new kx,a,b.A(),\"function\",(tx(a),t().d),(tx(a),!1)))});Sw(vg.S);return Px(vg,wg,d,h)}}if(N){var xg=P.Ej,eg=P.Fj,vh=c.Lb?iY(c):tf(c),fg=g7(a,xg,vh,d,e);up(tp(),!Pe(new E(g),!0));var ih=Rw(a,eg,vh,d,e,a.VI||Pe(new E(g),!0));j7(a,c,vh,d);return new cv(a,fg,ih,jx(new kx,a,b.A(),\"function\",(tx(a),t().d),(tx(a),!1)))}if(b instanceof Yl){var Ig=new Yl(b.hp),Tf=\nnew Gl(O().c),Jg=b.A(),jh=new y(Ca=>new Kq(Ca.eh,Ca.eh,Ca.dh)),yg=Jg.b()?R():new L(jh.n(Jg.o()));return W6(a,new Pl(Ig,Cq(Tf,yg)),c,d,e)}if(r){var gg=v.Za,Cf=v.Qb;if(gg instanceof Yl){var Uf=gg.hp;Uf instanceof Il&&Lw(a,Ye(new Te(new Ue(J(new K,[\"Type arguments in `new` expressions are not yet supported\"]))),u()),h.Ga,d);var $g=nx(Uf,d),Ah=nf(),Kg=ox(a,$g,c,d,e,Ah),Vf=!1,hg=null,zg=DB(Kg);a:if(zg instanceof fw)var Lg=T6(a,zg.qb.V,c,b,d,h);else{if(zg instanceof Mu){Vf=!0;hg=zg;var Mg=hg.pd,Wf=a.Bk;\nif(null===Wf?null===Mg:Wf.i(Mg)){Lg=hg;break a}}if(Vf){var Ng=hg.pd;if(Ng instanceof vl){Lg=T6(a,Ng.x,c,b,d,h);break a}}var Kf=new Te(new Ue(J(new K,[\"Unexpected type `\",\"` after `new` keyword\"]))),xf=[wO(Xe(),AD(Kg,c))],Og=Ye(Kf,J(new K,xf)),mi=Uf.A(),Ci=G(new H,Og,mi),Xh=O().c;Lg=ay(a,new z(Ci,Xh),d)}var wh=t().d,Bh=t().d,ng=O().c,kh=O().c,Kh=new lx(a,c.da,ng,kh,wh,Bh,!1,h),ni=jx(new kx,a,Cf.A(),\"argument list\",(tx(a),t().d),(tx(a),!1)),Lh=Rw(a,Cf,c,d,e,g);return Q6(a,Lg,new cv(a,ux(Lh.q,Lh,ni),\nKh,V(a)),Kh,c,d,h)}}if(r){var lh=v.Za;if(lh instanceof Pl){var Ch=lh.Za;if(Ch instanceof vl&&\"is\"===Ch.x){var Dh=new Ut(b,new vl(\"true\"));t();var Yh=new vl(\"false\"),ah=new Xl(Dh,new L(Yh));b.oc=(t(),new L(ah));return Rw(a,ah,c,d,e,g)}}}if(r){var oi=v.Za;if(oi instanceof vl&&\"is\"===oi.x){var mj=new Ut(b,new vl(\"true\"));t();var wd=new vl(\"false\"),ge=new Xl(mj,new L(wd));b.oc=(t(),new L(ge));return Rw(a,ge,c,d,e,g)}}if(r){var De=v.Za,qf=v.Qb;if(De instanceof Pl){var og=De.Za,Xf=De.Qb;if(og instanceof\nvl&&\"and\"===og.x&&null!==Xf){var mh=mz(eu(),Xf);if(!mh.b()&&null!==mh.o()&&0===mh.o().ab(1)){var Ag=mh.o(),Bg=eB(Ag,0);if(null!==qf){var Eh=mz(eu(),qf);if(!Eh.b()&&null!==Eh.o()&&0===Eh.o().ab(1)){var Pg=Eh.o(),Di=eB(Pg,0),Mh=new Ut(Bg,Di);t();var pi=new vl(\"false\"),Xi=new Xl(Mh,new L(pi));b.oc=(t(),new L(Xi));return Rw(a,Xi,c,d,e,g)}}}}}}if(r){var Qg=v.Za,nh=v.Qb;if(Qg instanceof vl&&\"and\"===Qg.x&&null!==nh){var bh=mz(eu(),nh);if(!bh.b()&&null!==bh.o()&&0===bh.o().ab(2)){var Mj=bh.o(),Nj=eB(Mj,0),\nie=bh.o(),Ac=eB(ie,1),Ve=new Ut(Nj,Ac);t();var Td=new vl(\"false\"),lf=new Xl(Ve,new L(Td));b.oc=(t(),new L(lf));return Rw(a,lf,c,d,e,g)}}}if(r){var Yi=v.Za,Jl=v.Qb;if(null!==Yi&&Jl instanceof Gl&&Jl.Ra.qo(new y(Ca=>!Ca.h().b()))){var ll=Rw(a,Yi,c,d,e,g),Bj=Tfa(a,ll,c),$k=!1,Zh=null;if(Bj instanceof z){$k=!0;Zh=Bj;var Ei=Zh.z,Yd=Zh.p;if(null!==Ei){var bf=Ei.Nb;if(bf instanceof zv){var rf=bf.Yb,Cg=O().c;if(null===Cg?null===Yd:Cg.i(Yd)){if(rf.qo(new y(Ca=>Ca.h().b())))return Lw(a,We(Xe(),\"Cannot use named arguments as the function type has untyped arguments\"),\nJl.A(),d);var nj=Qt(rf,new y(Ca=>{Ca=Ca.h();if(Ca instanceof L)return Ca.k;if(t().d===Ca)xm(\"Program reached and unexpected state.\");else throw new w(Ca);}));return cga(a,b,Yi,Jl,nj,ll,c,d,e)}}}}if($k&&Zh.p instanceof z){var Jh=new Te(new Ue(J(new K,[\"More than one function signature found in type `\",\"` for function call with named arguments\"]))),If=[wO(Xe(),AD(ll,c))];return Lw(a,Ye(Jh,J(new K,If)),Yi.A(),d)}a:{var Hg=O().c;if(null===Hg?null===Bj:Hg.i(Bj))var He=!0;else{if(Bj instanceof z){var lj=\nBj.p,Wi=O().c;if(null===Wi?null===lj:Wi.i(lj)){He=!0;break a}}He=!1}}if(He){var Oj=new Te(new Ue(J(new K,[\"Cannot retrieve appropriate function signature from type `\",\"` for applying named arguments\"]))),mo=[wO(Xe(),AD(ll,c))];return Lw(a,Ye(Oj,J(new K,mo)),Yi.A(),d)}throw new w(Bj);}}if(r){var mm=v.Za,nm=v.Qb,dq=W6(a,mm,c,d,e);if(nm instanceof Gl){var Zd=nm.Ra,sf=Qt(Zd,new y(Ca=>{if(null!==Ca){var Lc=Ca.h(),yd=Ca.j();if(null!==yd){var Qe=yd.ya;if(null!==yd.yb)return Ca=jx(new kx,a,Qe.A(),\"argument\",\n(tx(a),t().d),(tx(a),!1)),Qe=V6(a,Qe,c,d,e,h),G(new H,Lc,new Uw(Qe.q,R(),Qe,Ca))}}throw new w(Ca);}));a:{var oj=O().c;if(null===oj?null===Zd:oj.i(Zd))var al=!0;else{if(Zd instanceof z){var Ll=Zd.z,Qm=Zd.p;if(null!==Ll){var Rm=Ll.h();if(t().d===Rm)var hq=O().c,Bn=null===hq?null===Qm:hq.i(Qm);else Bn=!1;if(Bn){al=!0;break a}}}al=!1}}var hp=new zv(a,sf,al?V(a):jx(new kx,a,nm.A(),\"argument list\",(tx(a),t().d),(tx(a),!1)))}else hp=V6(a,nm,c,d,e,h);var ru=t().d,qr=t().d,Xs=O().c,rr=O().c,iq=new lx(a,c.da,\nXs,rr,ru,qr,!1,h),qo=ux(a,hp,jx(new kx,a,Lq(nm),\"argument\",(tx(a),t().d),(tx(a),!1))),qm=jx(new kx,a,Lq(mm),\"applied expression\",(tx(a),t().d),(tx(a),!1)),jq=ux(a,dq,qm);return Q6(a,jq,new cv(a,qo,iq,h),iq,c,d,h)}if(b instanceof Ql){var pl=b.Vl,ro=b.ml,Cn=!1,ip=null;if(pl instanceof vl){Cn=!0;ip=pl;var so=ip.x;if(hB(ve(),so)&&c.tb.L(so)){var Dn=hY(c,(t(),new L(so)),ro.x);if(Dn instanceof L){var sr=Dn.k.maa();return TA(sr,c)}if(t().d===Dn){var kq=new Te(new Ue(J(new K,[\"Class \",\" has no method \",\"\"]))),\nql=[We(Xe(),so),We(Xe(),ro.x)];Lw(a,Ye(kq,J(new K,ql)),b.A(),d);return X6(a,pl,ro,c,b,d,e,h)}throw new w(Dn);}}if(Cn){var Ys=ip.x;if(\"unapply\"===ro.x){var Sm=!1,Nl=null,jp=uC(c,c,Ys);a:{if(jp instanceof L){Sm=!0;Nl=jp;var lq=Nl.k;if(lq instanceof ix){var mq=lq.kh;if(mq instanceof Yw){var Tm=Cp(mq.Rf);break a}}}if(Sm){var En=Nl.k;if(En instanceof fx){Tm=Cp(En.Ab);break a}}Tm=t().d}if(Tm instanceof L){var to=Tm.k;if(null!==to){var Fn=to.Yc;if(Fn instanceof fe)return Rw(a,Fn.aa,c,d,e,!0)}}}}return X6(a,\npl,ro,c,b,d,e,h)}if(b instanceof Rl){var nq=b.ep,Um=b.Zn,kp=b.$n,oq=b.Mm;if(c.Lb){var su=Rw(a,kp,c,d,e,g),Gn=iY(c),ur=Um.x,In=new qx(a,su,Um);Wx(Gn,G(new H,ur,In));var Zs=Rw(a,oq,Gn,d,e,g);j7(a,c,Gn,d);return Zs}if(a.$c&&!nq){var $s=Rw(a,kp,c,d,e,g),pq=tf(c),vr=Um.x,Vm=new qx(a,$s,Um);Wx(pq,G(new H,vr,Vm));return Rw(a,oq,pq,d,e,g)}var Jn=h7(a,nq,Um.x,kp,c,d,e),wr=tf(c),at=Um.x,xr=new qx(a,Jn,Um);Wx(wr,G(new H,at,xr));return Rw(a,oq,wr,d,e,g)}if(I){var lp=M.Dj;if(a.$c){var Kn=new Dt(lp);t();var qq=\nof(a,Kn,new L(M),c,d,e).Ul,yr=new U(()=>a.Ck);return qq.b()?Es(yr):qq.o()}return k7(a,lp,!1,O().c,!1,tf(c),d,h,e,g)}if(b instanceof Tl){var rq=b.ar,sq=W6(a,b.br,c,d,e),bt=W6(a,rq,c,d,e),tq=rq.ll.m(),zr=new Ef(tq,new y(Ca=>Ca.h())),ct=Su(),Ar=op().ga,uq=new Uu(ct,Ar),Br=oA(uv(),zr,uq),Ln=iB(sq,Br);return Pu(Ln,bt,h,!1)}if(b instanceof Ul){var vq=b.Sn,Cr=b.Hm,tu=c.Lb?iY(c):c;return(new y(Ca=>{var Lc=W6(a,vq,Ca,d,e);if(a.$c){var yd=a.mP;Q6(a,Lc,ux(yd.q,yd,h),a.La,Ca,d,h)}yd=l7(a,Wk(new O_(a)).Ob(vq,\nnew y(()=>{t();return R()})),Cr,Ca,d,e,g);if(null!==yd)var Qe=G(new H,yd.h(),yd.j());else throw new w(yd);yd=Qe.h();Qe=Qe.j();j7(a,c,Ca,d);yd=yd.mf(a.ib,new fn((Xj,fl)=>{var Gk=G(new H,Xj,fl);fl=Gk.y;Xj=Gk.w;if(null!==fl){Gk=fl.h();fl=fl.j();var $n=V(Gk.q);fl=Pu(Gk,fl,$n,!1);$n=V(Gk.q);Gk=NA(Gk,$n,!1);$n=V(Xj.q);Xj=Pu(Xj,Gk,$n,!1);Gk=V(fl.q);return dv(fl,Xj,Gk,!1)}throw new w(Gk);}));return Q6(a,Lc,yd,Qe,Ca,d,h)})).n(tu)}if(b instanceof Xl)try{return Rw(a,Ffa(a,b,c,d),c,d,e,g)}catch(Ca){if(Ca instanceof\njT)return ay(a,Ca.VP,d);throw Ca;}if(b instanceof Il){var uu=b.nl;Lw(a,Ye(new Te(new Ue(J(new K,[\"Type application syntax is not yet supported\"]))),u()),b.A(),d);return Rw(a,uu,c,d,e,g)}if(b instanceof $l)return k7(a,Xq(b.lt,b.Yq),!1,O().c,!0,c,d,h,e,g);if(b instanceof Zl){var dt=b.qq,vu=b.$o,Dr=new y(Ca=>{var Lc=Qt(dt,new y(yd=>{if(null!==yd){var Qe=yd.pp;if(Qe instanceof Ud){Qe=Qe.fa;var Xj=jx(new kx,a,yd.A(),\"quantified type variable\",(tx(a),t().d),(tx(a),!1)),fl=t().d;t();var Gk=new L(Qe),$n=\nO().c,$R=O().c;yd=new mx(a,new lx(a,Ca.da,$n,$R,fl,Gk,!1,Xj),jx(new kx,a,yd.A(),\"rigid type variable\",(tx(a),t().d),(tx(a),!1)));return G(new H,Qe,yd)}}xm(\"Program reached and unexpected state.\")}));Lc=e.bf(Lc);return(new y(yd=>W6(a,vu,Ca,d,yd))).n(Lc)});Sw(c.S);return Px(c,Dr,d,h)}if(b instanceof Kl){var uo=Rw(a,b.cp,c,d,e,!0),Er=new GA(!1),et=Vfa(uo,c,Er);if(!Er.Am){var ft=new Te(new Ue(J(new K,[\"Inferred type `\",\"` of this \",\" cannot be instantiated\"]))),gt=[wO(Xe(),AD(uo,c)),We(Xe(),uo.ma().lh)];\nJX(a,Ye(ft,J(new K,gt)),h.Ga,d)}return et}if(b instanceof bm)return Lw(a,Ye(new Te(new Ue(J(new K,[\"Unexpected equation in this position\"]))),u()),b.A(),d);if(b instanceof em){var Wm=b.Iq;if(c.Lb)return Lw(a,Ye(new Te(new Ue(J(new K,[\"Nested quotation is not allowed.\"]))),u()),b.A(),d);var Fr=iY(c),mp=Rw(a,Wm,Fr,d,e,g),wu=new Ep(\"Code\"),ht=fY(Fr),wq=O().c;return new fw(a,wu,new z(mp,new z(ht,wq)),jx(new kx,a,b.A(),\"code fragment\",(tx(a),t().d),(tx(a),!1)))}if(b instanceof fm){var xq=b.jt;if(c.Lb){var Gr=\nUea(c),xu=Rw(a,xq,Gr,d,e,g),yu=jx(new kx,a,b.A(),\"code fragment body type\",(tx(a),t().d),(tx(a),!1)),Re=t().d,rj=t().d,ai=O().c,rm=O().c,Nn=new lx(a,c.da,ai,rm,Re,rj,!1,yu),zu=jx(new kx,a,xq.A(),\"code fragment context type\",(tx(a),t().d),(tx(a),!1)),Au=t().d,Av=t().d,oy=O().c,Bv=O().c,Cv=new lx(a,c.da,oy,Bv,Au,Av,!1,zu),py=new Ep(\"Code\"),qy=O().c,Dv=Q6(a,xu,new fw(a,py,new z(Nn,new z(Cv,qy)),jx(new kx,a,xq.A(),\"unquote body\",(tx(a),t().d),(tx(a),!1))),Nn,Gr,d,h);gY(c,Cv);var Ee=jx(new kx,a,b.A(),\n\"unquote\",(tx(a),t().d),(tx(a),!1));return ux(Dv.q,Dv,Ee)}return Lw(a,We(Xe(),\"Unquotes should be enclosed with a quasiquote.\"),b.A(),d)}if(b instanceof cm)return Lw(a,Ye(new Te(new Ue(J(new K,[\"Refinement terms are not yet supported\"]))),u()),b.A(),d);throw new w(b);}),new y(h=>c.da+\". : \"+h))}\nfunction l7(a,b,c,d,e,g,h){var k=tc();try{if(zm()===c){var l=O().c;return G(new H,l,a.ib)}if(c instanceof ym){var m=c.dn,n=jx(new kx,a,c.A(),\"wildcard pattern\",(tx(a),t().d),(tx(a),!1)),r=t().d,v=t().d,x=O().c,A=O().c,B=new lx(a,d.da,x,A,r,v,!1,n),C=d.Lb?iY(d):tf(d);if(b instanceof L){var D=b.k,F=D.x,I=new qx(a,B,D);Wx(C,G(new H,F,I));var M=Rw(a,m,C,e,g,h),N=G(new H,B,a.La),P=O().c,T=G(new H,new z(N,P),M)}else{var Y=G(new H,B,a.La),Z=O().c,S=new z(Y,Z),ea=Rw(a,m,d,e,g,h);T=G(new H,S,ea)}j7(a,d,C,\ne);return T}if(c instanceof um){var ia=c.Xo,X=c.Tn,sa=c.Un;if(ia instanceof Dl)var Ja=new Mu(a,ia,a.$c?yq(ia):fq(ia),jx(new kx,a,ia.A(),\"literal pattern\",(tx(a),t().d),(tx(a),!1))),Xa=G(new H,Ja,Ja);else{if(!(ia instanceof vl))throw new w(ia);var Fa=ia.x,za=jx(new kx,a,ia.A(),\"type pattern\",(tx(a),t().d),(tx(a),!1)),Qa=d.tb.U(Fa);if(R()===Qa){var Ma=()=>{var Yb=new Mu(a,a.Bk,ap(),za),Nc=G(new H,Yb,Yb),ad=O().c;Nc=new z(Nc,ad);throw Hq(new Iq,k,G(new H,Nc,Yb));},Ga=uC(d,d,Fa);a:{if(Ga instanceof L){var ab=\nGa.k;if(ab instanceof VP){var Hb=ab.fd();if(dx(new E(Hb),Bp()))var bc=ab.fd(),yb=dx(new E(bc),zp());else yb=!1;if(yb)var tb=ab.fd(),eb=dx(new E(tb),Fp());else eb=!1;eb&&Lw(a,Ye(new Te(new Ue(J(new K,[\"can only match on classes and traits\"]))),u()),ia.A(),e);var kb=jx(new kx,a,ia.A(),\"class pattern\",(tx(a),t().d),(tx(a),!1)),Rb=!1,Gb=null;if(ab instanceof fx){var vb=ab.Ab;vb instanceof yo||xm(\"Program reached and unexpected state.\");var Tb=bz(a,vb,kb,d),Nb=xv(a),ic=ab.Ag(),Va=Yb=>{if(null!==Yb){var Nc=\nYb.kc,ad=Yb.hb;Yb=Yb.Rd;var Uc=ad.ji;t();var cd=new L(ad);ad=ad.kg;var kc=O().c,Vc=O().c;Uc=new lx(a,d.da,kc,Vc,cd,ad,!1,Uc);cd=new vl(Fa+\"#\"+Nc.V);Nc=Nc.A();return G(new H,Cq(cd,Nc),XD(WD(a),Yb.b()?ou().Yl:Yb.o(),Uc,Uc,V(a)))}throw new w(Yb);};if(ic===u())var cb=u();else{for(var zb=ic.e(),Ub=new z(Va(zb),u()),jb=Ub,db=ic.f();db!==u();){var ub=db.e(),Aa=new z(Va(ub),u());jb=jb.p=Aa;db=db.f()}cb=Ub}var va=SA(Nb,cb,V(a));if(a.F){var Ra=ut(Q(),\"| \",a.r)+(\"Match arm \"+Fa+\": \"+Tb+\" \\x26 \")+va;ff(gf(),\nRa+\"\\n\")}Xa=G(new H,Tb,va);break a}if(ab instanceof ix){Rb=!0;Gb=ab;var rb=Gb.kh;if(rb instanceof Yw){var xb=bz(a,rb.Rf,kb,d),mc=xv(a),Ha=rb.gh,Ka=Yb=>{if(null!==Yb){var Nc=Yb.kc,ad=Yb.hb;Yb=Yb.Rd;var Uc=ad.ji;t();var cd=new L(ad),kc=ad.kg,Vc=O().c,Hc=O().c;Uc=new lx(a,d.da,Vc,Hc,cd,kc,!1,Uc);cd=new vl(Fa+\"#\"+Nc.V);Nc=Nc.A();return G(new H,Cq(cd,Nc),XD(WD(a),Yb.b()?RA(rb,ad,d):Yb.o(),Uc,Uc,V(a)))}throw new w(Yb);};if(Ha===u())var Oa=u();else{for(var Na=Ha.e(),Da=new z(Ka(Na),u()),ta=Da,Ya=Ha.f();Ya!==\nu();){var dc=Ya.e(),ka=new z(Ka(dc),u());ta=ta.p=ka;Ya=Ya.f()}Oa=Da}var ya=SA(mc,Oa,V(a));if(a.F){var Sa=ut(Q(),\"| \",a.r)+(\"Match arm \"+Fa+\": \"+xb+\" \\x26 \")+ya;ff(gf(),Sa+\"\\n\")}Xa=G(new H,xb,ya);break a}}if(Rb){Xa=Ma();break a}throw new w(ab);}}Lw(a,We(Xe(),\"type identifier not found: \"+Fa),ia.A(),e);Xa=Ma()}}else{if(!(Qa instanceof L))throw new w(Qa);var xc=Qa.k,Sb=xc.jj;if(Ap()===Sb||zp()===Sb||cp()===Sb){var uc=Lw(a,Ye(new Te(new Ue(J(new K,[\"can only match on classes and traits\"]))),u()),ia.A(),\ne);Xa=G(new H,uc,uc)}else if(Bp()===Sb){var Lb=rD(a,xc,jx(new kx,a,ia.A(),\"class pattern\",(tx(a),t().d),(tx(a),!1)),d);Xa=G(new H,Lb,Lb)}else if(Fp()===Sb){var lc=TD(a,xc,jx(new kx,a,ia.A(),\"trait pattern\",(tx(a),t().d),(tx(a),!1)));Xa=G(new H,lc,lc)}else throw new w(Sb);}}if(null===Xa)throw new w(Xa);var Xb=Xa.h(),ec=Xa.j(),Ab=d.Lb?iY(d):tf(d);if(b instanceof L){var Ob=b.k;if(a.$c){var fb=Ob.x,Wa=V(Xb.q),bb=new qx(a,Pu(Xb,ec,Wa,!1),Ob);Wx(Ab,G(new H,fb,bb));var Ia=Rw(a,X,Ab,e,g,h),Ua=new tl(G(new H,\nXb,ec),Ia,l7(a,b,sa,d,e,g,h))}else{var pc=jx(new kx,a,Ob.A(),\"refined scrutinee\",(tx(a),t().d),(tx(a),!1)),sc=t().d,Ba=t().d,ob=O().c,nc=O().c,Ib=new lx(a,d.da,ob,nc,sc,Ba,!1,pc),vc=Ob.x,Vb=new qx(a,Ib,Ob);Wx(Ab,G(new H,vc,Vb));var fc=Rw(a,X,Ab,e,g,h);Ua=new tl(G(new H,ec,Ib),fc,l7(a,b,sa,d,e,g,h))}}else if(t().d===b){var Bc=Rw(a,X,Ab,e,g,h);Ua=new tl(G(new H,Xb,a.La),Bc,l7(a,b,sa,d,e,g,h))}else throw new w(b);a:{if(null!==Ua){var Pb=Ua.kc,Jb=Ua.hb,gc=Ua.Rd;if(null!==gc){var Cb=gc.h(),cc=gc.j();var yc=\nPb;var Mc=Jb;var qc=Cb;var oc=cc;break a}}throw new w(Ua);}var Qc=yc,jc=Mc,sb=qc,Gc=oc;j7(a,d,Ab,e);var Wb=new z(Qc,sb),Cc=V(jc.q),Fc=dv(jc,Gc,Cc,!1);return G(new H,Wb,Fc)}throw new w(c);}catch(Yb){if(Yb instanceof Iq){var qd=Yb;if(qd.Qg===k)return qd.Cj();throw qd;}throw Yb;}}\nfunction k7(a,b,c,d,e,g,h,k,l,m){var n=!1,r=null;if(b instanceof z){n=!0;r=b;var v=r.z,x=r.p;if(v instanceof vl&&c)return t(),e=new L(v),v=new sm(tm().Cg,v),e=G(new H,e,v),v=O().c,e=new Gl(new z(e,v)),k7(a,new z(e,x),c,d,!1,g,h,k,l,m)}if(n&&(x=r.z,v=r.p,x instanceof Sl))return k7(a,dl(v,x.Dj),c,d,!1,g,h,k,l,m);if(n&&(v=r.z,x=r.p,v instanceof Gl)){v=v.Ra;var A=O().c;if(null===A?null===v:A.i(v))return k7(a,x,c,d,!1,g,h,k,l,m)}if(n&&(v=r.z,x=r.p,v instanceof Gl&&(v=v.Ra,v instanceof z))){var B=v.z;A=\nv.p;if(null!==B){v=B.h();var C=B.j();if(null!==C&&(B=C.ya,null!==C.yb)){a:{if(B instanceof Fl&&(e=B.gg,!1===B.bi&&g.yc)){e=g7(a,e,g,h,l);break a}e=g.yc&&v.b();e=new Iw(g.S,g.Ec,g.hc,g.Ed,g.da,g.Pc,g.Zc,g.Lb,e,g.tb,g.$a,g.od,g.cb);e=A.b()?Rw(a,new Fl(c,B),e,h,l,m):Rw(a,B,e,h,l,m)}r=!1;n=null;a:{if(v instanceof L&&(r=!0,n=v,b=n.k,g.yc)){n=jx(new kx,a,B.A(),\"parameter type\",(tx(a),t().d),(tx(a),!1));r=new lx(a,g.da,O().c,O().c,t().d,(TP(a),t().d),(TP(a),!1),n);B=Sw(a).ob;Tw(a,r,e,h,n,g,B);e=b.x;b=new qx(a,\nr,b);Wx(g,G(new H,e,b));e=r;break a}r&&(r=n.k,b=r.x,r=new qx(a,e,r),Wx(g,G(new H,b,r)))}A=new Gl(A);x=new z(A,x);e=G(new H,v,e);return k7(a,x,c,new z(e,d),!1,g,h,k,l,m)}}}if(n&&(x=r.z,v=r.p,x instanceof Pm&&(A=O().c,null===A?null===v:A.i(v))))return d.b()||JX(a,We(Xe(),\"Previous field definitions are discarded by this returned expression.\"),x.A(),h),Rw(a,x,g,h,l,m);if(n){x=r.p;A=r.z.nv();if(null===A)throw new w(A);v=A.j();for(A=A.h();!A.b();)h.n(A.e()),A=A.f();for(b=A=null;v!==u();){r=v.e();for(r=\nGP(ty(a,r,e,g,h,l,m)).m();r.s();)n=new z(r.t(),u()),null===b?A=n:b.p=n,b=n;v=v.f()}e=(null===A?u():A).m();v=op().ga;e=new xo(e,v);Jw(g,new Ef(e,new y(D=>{var F=D.h();D=new qx(a,D.j(),new vl(D.h()));return G(new H,F,D)})));return k7(a,x,c,d,!1,g,h,k,l,m)}g=O().c;if(null===g?null===b:g.i(b)){if(c)return c=er(d).m(),c=new Ao(c),c=new Ef(c,new y(D=>{if(null!==D){var F=D.h();if(null!==F){var I=F.h();F=F.j();if(I instanceof L)return D=I.k,I=V(a),F=new Uw(F.q,R(),F,I),G(new H,D,F)}}if(null!==D&&(F=D.h(),\nI=D.Sc(),null!==F)){var M=F.h();F=F.j();if(t().d===M)return JX(a,We(Xe(),\"Missing name for record field\"),F.ma().Ga,h),D=new vl(\"_\"+(1+I|0)),I=V(a),G(new H,D,new Uw(F.q,R(),F,I))}throw new w(D);})),Od(),c=Pd(u(),c),SA(xv(a),c,k);lv();c=er(d).m();return new zv(a,ry(0,c,new y(D=>{var F=V(a);return new Uw(D.q,R(),D,F)})),k)}throw new w(b);}\nfunction Xfa(a,b){for(var c=kZ(O().wR,1,1);;){if(c.b())b=R();else{var d=hZ(c).e();if(b.L(new vl(a+\"_\"+(d|0)))){c=hZ(c).Lf();continue}b=new L(d)}break}b.b()&&xm(\"Program reached and unexpected state.\");return a+\"_\"+b.o()}\nfunction cga(a,b,c,d,e,g,h,k,l){a:{for(var m=d.Ra;!m.b();){if(!m.e().h().b()){m=!0;break a}m=m.f()}m=!1}a:{for(var n=d.Ra;!n.b();){if(n.e().h().b()){n=!0;break a}n=n.f()}n=!1}a:{for(var r=0,v=a6(0,d.Ra);!v.b();){if(!v.e().h().b())break a;r=1+r|0;v=v.f()}r=-1}v=0;for(var x=d.Ra,A=-1;!x.b();)x.e().h().b()&&(A=v),x=x.f(),v=1+v|0;if(m&&n&&r<A)return Lw(a,Ye(new Te(new Ue(J(new K,[\"Unnamed arguments should appear first when using named arguments\"]))),u()),d.A(),k);if(0===jv(d.Ra,e)){r=Hf(d.Ra);g=B=>{if(null!==\nB){var C=B.h();B=B.Sc();var D=C.h();if(D instanceof L)return G(new H,G(new H,D.k.x,C.j()),!0);if(t().d===D)return G(new H,G(new H,eB(e,B).x,C.j()),!1);throw new w(D);}throw new w(B);};if(r===u())g=u();else{m=r.e();n=m=new z(g(m),u());for(r=r.f();r!==u();)v=r.e(),v=new z(g(v),u()),n=n.p=v,r=r.f();g=m}m=Xu().X();for(n=g.m();n.s();)r=n.t(),m.Hk(r.h().h(),new U(()=>{Od();return new fp})).$(r);n=Ez().Mr;for(m=m.m();m.s();){r=m.t();if(null===r)throw new w(r);n=m7(n,r.h(),r.j().Kb())}m=n;0>hv(m,e)&&m.dc.Ca(new y(B=>\n{var C=B.j();if(C instanceof z&&C.p instanceof z)return C=new Te(new Ue(J(new K,[\"Argument for parameter '\",\"' is duplicated\"]))),B=[We(Xe(),B.h())],Lw(a,Ye(C,J(new K,B)),d.A(),k)}));tp();m=u();c=Yfa(a,g,pp(0,m),d,e,k,c);a.F&&(g=ut(Q(),\"| \",a.r)+\"Desugared is here \\x3d\\x3e \"+c,ff(gf(),g+\"\\n\"));b.oc=(t(),new L(c));return Rw(a,c,h,k,l,!1)}b=new Te(new Ue(J(new K,[\"Number of arguments doesn't match function signature `\",\"`\"])));h=[wO(Xe(),AD(g,h))];return Lw(a,Ye(b,J(new K,h)),d.A(),k)}\nfunction uf(a,b,c,d){var e=O().c;e=new aw(e);var g=jA().X();a:{var h=new qC(a,nf());if(b instanceof zA)a=$6(a,b,h,c,g,e,d);else{if(b instanceof BA){CA(a);t();var k=new L(b);if(!k.b()){b=k.k;var l=b.xk;if(l===u())k=u();else{k=l.e();var m=k=new z(Q_(a,k,h,d,c,g,e),u());for(l=l.f();l!==u();){var n=l.e();n=new z(Q_(a,n,h,d,c,g,e),u());m=m.p=n;l=l.f()}}b=b.Ul;b.b()?a=R():(b=b.o(),a=new L($6(a,b,h,c,g,e,d)));a=new BP(k,a);break a}}throw new w(b);}}return e.rc.b()?a:new qP(a,e.rc,O().c)}\nfunction i7(a){var b=a.YE;a.YE=1+a.YE|0;return b}\nfunction Q_(a,b,c,d,e,g,h){if(b instanceof ax){var k=b.Rl,l=b.Ql,m=rC(c,b.rk),n=k.pb,r=k.gb,v=k.hg,x=t().d,A=t().d;t();var B=$6(a,l,m,e,g,h,d);return new yo(n,r,v,x,A,new L(B),O().c,t().d,t().d,new Dt(O().c),k.fl,k.Pm,k.Rz)}if(b instanceof Nw){var C=b.il,D=b.jl,F=b.hl,I=b.Tl,M=b.Jj,N=rC(c,b.kl),P=C.pb,T=C.gb,Y=C.hg;t();var Z=Kc=>{var Qd=t().d;Kc=new sm(tm().Cg,new Cl(Kc.h(),$6(a,Kc.j().ra,N,e,g,h,d)));return G(new H,Qd,Kc)};if(I===u())var S=u();else{for(var ea=I.e(),ia=new z(Z(ea),u()),X=ia,sa=I.f();sa!==\nu();){var Ja=sa.e(),Xa=new z(Z(Ja),u());X=X.p=Xa;sa=sa.f()}S=ia}var Fa=new Gl(S),za=new L(Fa),Qa=t().d,Ma=t().d,Ga=O().c,ab=Xu().X(),Hb=Zu(a.La,F,d,!0,ab)?R():new L($6(a,F,N,e,g,h,d)),bc=Xu().X(),yb=!Zu(a.La,D,d,!0,bc);return new yo(P,T,Y,za,Qa,Ma,Ga,Hb,yb?new L($6(a,D,N,e,g,h,d)):R(),a7(a,M,N,d,e,g,h),C.fl,C.Pm,C.Rz)}if(b instanceof Yw){var tb=b.Rf,eb=b.Ij,kb=b.gl,Rb=b.Ei,Gb=b.Um,vb=b.sk,Tb=b.ip,Nb=rC(c,b.gh),ic=tb.pb,Va=tb.gb,cb=tb.hg;if(eb.b())var zb=R();else{var Ub=eb.o(),jb=Kc=>{var Qd=t().d;\nKc=new sm(tm().Cg,new Cl(Kc.h(),$6(a,Kc.j().ra,Nb,e,g,h,d)));return G(new H,Qd,Kc)};if(Ub===u())var db=u();else{for(var ub=Ub.e(),Aa=new z(jb(ub),u()),va=Aa,Ra=Ub.f();Ra!==u();){var rb=Ra.e(),xb=new z(jb(rb),u());va=va.p=xb;Ra=Ra.f()}db=Aa}zb=new L(new Gl(db))}var mc=tb.Qm,Ha=Xu().X(),Ka=Zu(a.La,vb,d,!0,Ha)?R():new L($6(a,vb,Nb,e,g,h,d));Od();var Oa=Pd(u(),Tb),Na=Su(),Da=op().ga,ta=qw(Oa,new Uu(Na,Da));if(ta===u())var Ya=u();else{for(var dc=ta.e(),ka=new z(dc.Zr(),u()),ya=ka,Sa=ta.f();Sa!==u();){var xc=\nSa.e(),Sb=new z(xc.Zr(),u());ya=ya.p=Sb;Sa=Sa.f()}Ya=ka}var uc=t().d,Lb=Xu().X(),lc=Zu(a.La,Gb,d,!0,Lb)?R():new L($6(a,Gb,Nb,e,g,h,d)),Xb=a7(a,Rb,Nb,d,e,g,h);if(kb instanceof L){var ec=kb.k,Ab=Kc=>{var Qd=t().d;Kc=new sm(tm().Cg,new Cl(Kc.h(),$6(a,Kc.j(),Nb,e,g,h,d)));return G(new H,Qd,Kc)};if(ec===u())var Ob=u();else{for(var fb=ec.e(),Wa=new z(Ab(fb),u()),bb=Wa,Ia=ec.f();Ia!==u();){var Ua=Ia.e(),pc=new z(Ab(Ua),u());bb=bb.p=pc;Ia=Ia.f()}Ob=Wa}var sc=new Po(new Gl(Ob),new Sl(O().c)),Ba=ef(Xb),ob=\nnew Dt(new z(sc,Ba))}else{if(t().d!==kb)throw new w(kb);ob=Xb}return new yo(ic,Va,cb,zb,mc,Ka,Ya,uc,lc,ob,tb.fl,tb.Pm,tb.Rz)}if(b instanceof Ww){var nc=b.vk,Ib=b.tk,vc=b.co,Vb=b.uk,fc=b.Gq,Bc=rC(c,b.wk),Pb=nc.pb,Jb=nc.gb,gc=nc.hg,Cb=t().d,cc=nc.Qm,yc=Xu().X(),Mc=Zu(a.La,Vb,d,!0,yc)?R():new L($6(a,Vb,Bc,e,g,h,d));Od();var qc=Pd(u(),fc),oc=Su(),Qc=op().ga,jc=qw(qc,new Uu(oc,Qc));if(jc===u())var sb=u();else{for(var Gc=jc.e(),Wb=new z(Gc.Zr(),u()),Cc=Wb,Fc=jc.f();Fc!==u();){var qd=Fc.e(),Yb=new z(qd.Zr(),\nu());Cc=Cc.p=Yb;Fc=Fc.f()}sb=Wb}var Nc=t().d,ad=Xu().X(),Uc=!Zu(a.La,vc,d,!0,ad);return new yo(Pb,Jb,gc,Cb,cc,Mc,sb,Nc,Uc?new L($6(a,vc,Bc,e,g,h,d)):R(),a7(a,Ib,Bc,d,e,g,h),nc.fl,nc.Pm,nc.Rz)}if(b instanceof bx){var cd=b.Mb,kc=cd.wd,Vc=cd.Rb,Hc=cd.hj,rc=O().c;t();var sd=$6(a,b.Nn(),c,e,g,h,d);return new Zn(kc,Vc,Hc,rc,new Ud(sd),cd.Pz,cd.lx,cd.Om,cd.kx,cd.Qz,cd.Pl,cd.Oz)}if(b instanceof Vw)no();else if(b instanceof cx)no();else throw new w(b);}\nhf.prototype.$classData=q({KY:0},!1,\"mlscript.Typer\",{KY:1,Vaa:1,Jaa:1,Daa:1,waa:1,Caa:1,Oaa:1,Qaa:1,g:1,Laa:1});function Qx(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.MO=this.dd=0;this.NO=null;this.DI=!1;this.de=b;this.Re=c;pY(this,a);if(!(b<a.Df))throw Kj(\"requirement failed: \"+this.de);this.NO=c.ma()}Qx.prototype=new qY;Qx.prototype.constructor=Qx;f=Qx.prototype;f.ma=function(){return this.NO};\nf.Ea=function(){this.DI||this.DI||(this.MO=this.ub(this.de,jA().X()),this.DI=!0);return this.MO};f.ub=function(a,b){var c=this.de;return this.Re.ub(a<c?a:c,b)};f.u=function(){return\"\\u2039\\u2200 \"+this.de+\". \"+this.Re+\"\\u203a\"};f.H=function(){return\"PolymorphicType\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.de;case 1:return this.Re;default:return $K(W(),a)}};f.D=function(a){return a instanceof Qx};\nf.$classData=q({tZ:0},!1,\"mlscript.TyperDatatypes$PolymorphicType\",{tZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,Raa:1,E:1,v:1,l:1});function OA(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.Hi=b;this.NE=c;pY(this,a)}OA.prototype=new T_;OA.prototype.constructor=OA;f=OA.prototype;f.mc=function(){return this.Hi};f.ma=function(){return this.NE};f.u=function(){return\"\"+this.Hi};f.H=function(){return\"ProvType\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.Hi:$K(W(),a)};f.D=function(a){return a instanceof OA};f.$classData=q({vZ:0},!1,\"mlscript.TyperDatatypes$ProvType\",{vZ:1,EI:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function fw(a,b,c,d){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.MI=null;this.qb=b;this.Zb=c;this.Xl=d;pY(this,a);this.MI=t().d}fw.prototype=new qY;fw.prototype.constructor=fw;f=fw.prototype;f.ma=function(){return this.Xl};\nf.Ea=function(){var a=this.Zb.m();a=new Ef(a,new y(c=>c.Ea()));var b=Fq();a=Jq(a,b);return(a.b()?this.q.Gd:a.o())|0};f.ub=function(a,b){var c=this.Zb.m();c=new Ef(c,new y(e=>e.ub(a,b)));var d=Fq();c=Jq(c,d);return(c.b()?this.q.Gd:c.o())|0};function rv(a,b,c,d,e){var g=a.q,h=a.qb,k=a.Zb;if(k===u())b=u();else{var l=k.e(),m=l=new z(l.Kc(b,c,d,e),u());for(k=k.f();k!==u();){var n=k.e();n=new z(n.Kc(b,c,d,e),u());m=m.p=n;k=k.f()}b=l}return new fw(g,h,b,a.Xl)}\nf.u=function(){var a=this.q.cn.L(this.qb.V)?Nu(Q(),this.qb.V):this.qb.V;return this.Zb.b()?a:a+\"[\"+ze(this.Zb,\"\",\",\",\"\")+\"]\"};f.H=function(){return\"TypeRef\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.qb;case 1:return this.Zb;default:return $K(W(),a)}};f.D=function(a){return a instanceof fw};f.Kc=function(a,b,c,d){return rv(this,a,b,c,d)};f.$classData=q({IZ:0},!1,\"mlscript.TyperDatatypes$TypeRef\",{IZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,Saa:1,E:1,v:1,l:1});\nfunction dga(a){if(!a.OI){var b=a.Oq,c=a.up.Ba.m();c=new Ef(c,new y(g=>g.h()));var d=Su(),e=op().ga;d=new Uu(d,e);c=oA(uv(),c,d);b=iB(b,c);c=a.up;d=V(b.q);a.PI=Pu(b,c,d,!1);a.OI=!0}return a.PI}function $y(a,b,c,d){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.PI=null;this.OI=!1;this.Oq=b;this.up=c;this.OZ=d;pY(this,a)}$y.prototype=new T_;$y.prototype.constructor=$y;f=$y.prototype;f.ma=function(){return this.OZ};f.mc=function(){return this.OI?this.PI:dga(this)};\nf.u=function(){return this.Oq+\" w/ \"+this.up};f.H=function(){return\"WithType\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Oq;case 1:return this.up;default:return $K(W(),a)}};f.D=function(a){return a instanceof $y};f.$classData=q({NZ:0},!1,\"mlscript.TyperDatatypes$WithType\",{NZ:1,EI:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});\nfunction nP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Lx=a;this.Mx=b;Nq(this)}nP.prototype=new M_;nP.prototype.constructor=nP;f=nP.prototype;f.H=function(){return\"WithExtension\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Lx;case 1:return this.Mx;default:return $K(W(),a)}};f.D=function(a){return a instanceof nP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof nP){var b=this.Lx,c=a.Lx;if(null===b?null===c:b.i(c))return b=this.Mx,a=a.Mx,null===b?null===a:b.i(a)}return!1};f.$classData=q({n_:0},!1,\"mlscript.WithExtension\",{n_:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});q({p_:0},!1,\"mlscript.codegen.ClassSymbol\",{p_:1,g:1,UA:1,cr:1,mt:1,yj:1,nf:1,E:1,v:1,l:1});function n7(){}n7.prototype=new q3;n7.prototype.constructor=n7;function o7(){}o7.prototype=n7.prototype;n7.prototype.Ub=function(){return eU()};\nn7.prototype.u=function(){return w5(this)};n7.prototype.Oc=function(){return\"View\"};function rp(a){this.mL=null;if(null===a)throw null;this.mL=a}rp.prototype=new q3;rp.prototype.constructor=rp;rp.prototype.Q=function(){return this.mL.Q()};rp.prototype.m=function(){return this.mL.ie()};rp.prototype.$classData=q({L5:0},!1,\"scala.collection.MapOps$$anon$1\",{L5:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,sg:1,l:1});\nfunction kY(a,b){if(a===b)return!0;if(b&&b.$classData&&b.$classData.rb.fk)if(a.ka()===b.ka())try{return a.fM(b)}catch(c){throw c;}else return!1;else return!1}function p7(){this.Br=0;this.OB=\"Any\";O();this.Br=Qb(this)}p7.prototype=new D6;p7.prototype.constructor=p7;p7.prototype.uh=function(){return da(jd)};p7.prototype.si=function(a){return new zc(a)};p7.prototype.$classData=q({W3:0},!1,\"scala.reflect.ManifestFactory$AnyManifest$\",{W3:1,OK:1,NK:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var q7;\nfunction IB(){q7||(q7=new p7);return q7}function r7(){this.Gf=0;this.Ki=\"Boolean\";this.Gf=Qb(this)}r7.prototype=new p6;r7.prototype.constructor=r7;r7.prototype.$classData=q({X3:0},!1,\"scala.reflect.ManifestFactory$BooleanManifest$\",{X3:1,zba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var s7;function uL(){s7||(s7=new r7);return s7}function t7(){this.Gf=0;this.Ki=\"Byte\";this.Gf=Qb(this)}t7.prototype=new r6;t7.prototype.constructor=t7;\nt7.prototype.$classData=q({Y3:0},!1,\"scala.reflect.ManifestFactory$ByteManifest$\",{Y3:1,Aba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var u7;function sL(){u7||(u7=new t7);return u7}function v7(){this.Gf=0;this.Ki=\"Char\";this.Gf=Qb(this)}v7.prototype=new t6;v7.prototype.constructor=v7;v7.prototype.$classData=q({Z3:0},!1,\"scala.reflect.ManifestFactory$CharManifest$\",{Z3:1,Bba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var w7;function Ir(){w7||(w7=new v7);return w7}\nfunction x7(){this.Gf=0;this.Ki=\"Double\";this.Gf=Qb(this)}x7.prototype=new v6;x7.prototype.constructor=x7;x7.prototype.$classData=q({$3:0},!1,\"scala.reflect.ManifestFactory$DoubleManifest$\",{$3:1,Cba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var y7;function pL(){y7||(y7=new x7);return y7}function z7(){this.Gf=0;this.Ki=\"Float\";this.Gf=Qb(this)}z7.prototype=new x6;z7.prototype.constructor=z7;\nz7.prototype.$classData=q({a4:0},!1,\"scala.reflect.ManifestFactory$FloatManifest$\",{a4:1,Dba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var A7;function rL(){A7||(A7=new z7);return A7}function B7(){this.Gf=0;this.Ki=\"Int\";this.Gf=Qb(this)}B7.prototype=new z6;B7.prototype.constructor=B7;B7.prototype.$classData=q({b4:0},!1,\"scala.reflect.ManifestFactory$IntManifest$\",{b4:1,Eba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var C7;function rl(){C7||(C7=new B7);return C7}\nfunction D7(){this.Gf=0;this.Ki=\"Long\";this.Gf=Qb(this)}D7.prototype=new B6;D7.prototype.constructor=D7;D7.prototype.$classData=q({c4:0},!1,\"scala.reflect.ManifestFactory$LongManifest$\",{c4:1,Fba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var E7;function qL(){E7||(E7=new D7);return E7}function UR(){this.Br=0;this.OB=\"Nothing\";O();this.Br=Qb(this)}UR.prototype=new D6;UR.prototype.constructor=UR;UR.prototype.uh=function(){return da(kH)};UR.prototype.si=function(a){return new zc(a)};\nUR.prototype.$classData=q({d4:0},!1,\"scala.reflect.ManifestFactory$NothingManifest$\",{d4:1,OK:1,NK:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var TR;function WR(){this.Br=0;this.OB=\"Null\";O();this.Br=Qb(this)}WR.prototype=new D6;WR.prototype.constructor=WR;WR.prototype.uh=function(){return da(jH)};WR.prototype.si=function(a){return new zc(a)};WR.prototype.$classData=q({e4:0},!1,\"scala.reflect.ManifestFactory$NullManifest$\",{e4:1,OK:1,NK:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var VR;\nfunction F7(){this.Br=0;this.OB=\"Object\";O();this.Br=Qb(this)}F7.prototype=new D6;F7.prototype.constructor=F7;F7.prototype.uh=function(){return da(jd)};F7.prototype.si=function(a){return new zc(a)};F7.prototype.$classData=q({f4:0},!1,\"scala.reflect.ManifestFactory$ObjectManifest$\",{f4:1,OK:1,NK:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var G7;function TG(){G7||(G7=new F7);return G7}function H7(){this.Gf=0;this.Ki=\"Short\";this.Gf=Qb(this)}H7.prototype=new F6;H7.prototype.constructor=H7;\nH7.prototype.$classData=q({g4:0},!1,\"scala.reflect.ManifestFactory$ShortManifest$\",{g4:1,Gba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var I7;function tL(){I7||(I7=new H7);return I7}function J7(){this.Gf=0;this.Ki=\"Unit\";this.Gf=Qb(this)}J7.prototype=new H6;J7.prototype.constructor=J7;J7.prototype.$classData=q({h4:0},!1,\"scala.reflect.ManifestFactory$UnitManifest$\",{h4:1,Hba:1,Kt:1,g:1,om:1,Lk:1,nm:1,pm:1,l:1,v:1});var K7;function SR(){K7||(K7=new J7);return K7}function vw(a){this.al=a}\nvw.prototype=new p;vw.prototype.constructor=vw;f=vw.prototype;f.$l=function(a){Fq();var b=this.al;a|=0;return b===a?0:b<a?-1:1};f.sl=function(a){Fq();var b=this.al;a|=0;return b===a?0:b<a?-1:1};f.u=function(){return\"\"+this.al};f.WJ=function(){return this.uv()&&this.Zi()===this.jB()};f.YJ=function(){return this.uv()&&this.Zi()===this.EC()};f.XJ=function(){return this.uv()&&0<=this.Zi()&&65535>=this.Zi()};f.Lp=function(){return this.al};f.pv=function(){return Math.fround(this.al)};\nf.xl=function(){var a=this.al;return new ma(a,a>>31)};f.Zi=function(){return this.al};f.jB=function(){return this.al<<24>>24};f.EC=function(){return this.al<<16>>16};f.uv=function(){return!0};f.MF=function(){return!0};f.B=function(){return this.al};f.i=function(a){TK||(TK=new SK);return a instanceof vw?this.al===a.al:!1};f.$classData=q({faa:0},!1,\"scala.runtime.RichInt\",{faa:1,g:1,dca:1,sR:1,mba:1,lba:1,bca:1,yj:1,nf:1,cca:1});\nfunction pP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Gw=a;this.Hw=b;Nq(this)}pP.prototype=new M_;pP.prototype.constructor=pP;f=pP.prototype;f.H=function(){return\"AppliedType\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Gw;case 1:return this.Hw;default:return $K(W(),a)}};f.D=function(a){return a instanceof pP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof pP){var b=this.Gw,c=a.Gw;if(null===b?null===c:b.i(c))return b=this.Hw,a=a.Hw,null===b?null===a:b.i(a)}return!1};f.$classData=q({RT:0},!1,\"mlscript.AppliedType\",{RT:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,JW:1,E:1,v:1,l:1});function L7(){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;Nq(this)}L7.prototype=new U2;L7.prototype.constructor=L7;f=L7.prototype;f.H=function(){return\"Bot\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof L7};f.B=function(){return 66983};f.u=function(){return\"Bot\"};f.$classData=q({XT:0},!1,\"mlscript.Bot$\",{XT:1,Vz:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});var M7;function el(){M7||(M7=new L7);return M7}function Po(a,b){this.MM=this.LM=null;this.OM=this.PM=0;this.QM=this.NM=null;this.Jm=0;this.ks=a;this.js=b;Nq(this)}Po.prototype=new p;Po.prototype.constructor=Po;f=Po.prototype;f.jb=function(){return\"constructor\"};f.Vj=function(){return eP(this)};\nf.Wr=function(){return Mx(this)};f.nv=function(){0===(1&this.Jm)<<24>>24&&0===(1&this.Jm)<<24>>24&&(this.LM=cP(this),this.Jm=(1|this.Jm)<<24>>24);return this.LM};f.jn=function(){0===(2&this.Jm)<<24>>24&&0===(2&this.Jm)<<24>>24&&(this.MM=zq(this),this.Jm=(2|this.Jm)<<24>>24);return this.MM};f.rn=function(){return this.PM};f.fm=function(a){this.PM=a};f.qn=function(){return this.OM};f.em=function(a){this.OM=a};f.pn=function(){return this.NM};f.on=function(a){this.NM=a};\nf.A=function(){0===(4&this.Jm)<<24>>24&&0===(4&this.Jm)<<24>>24&&(this.QM=Dq(this),this.Jm=(4|this.Jm)<<24>>24);return this.QM};f.H=function(){return\"Constructor\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.ks;case 1:return this.js;default:return $K(W(),a)}};f.D=function(a){return a instanceof Po};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Po){var b=this.ks,c=a.ks;if(null===b?null===c:b.i(c))return b=this.js,a=a.js,null===b?null===a:b.i(a)}return!1};f.$classData=q({CU:0},!1,\"mlscript.Constructor\",{CU:1,g:1,ud:1,md:1,xd:1,Ta:1,Od:1,xaa:1,E:1,v:1,l:1});function oP(a){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Es=a;Nq(this)}oP.prototype=new U2;oP.prototype.constructor=oP;f=oP.prototype;f.H=function(){return\"Literal\"};\nf.G=function(){return 1};f.I=function(a){return 0===a?this.Es:$K(W(),a)};f.D=function(a){return a instanceof oP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof oP){var b=this.Es;a=a.Es;return null===b?null===a:b.i(a)}return!1};f.$classData=q({uW:0},!1,\"mlscript.Literal\",{uW:1,Vz:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});\nfunction Vt(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Ws=a;this.Vs=b;Nq(this)}Vt.prototype=new M_;Vt.prototype.constructor=Vt;f=Vt.prototype;f.H=function(){return\"PolyType\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Ws;case 1:return this.Vs;default:return $K(W(),a)}};f.D=function(a){return a instanceof Vt};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Vt){var b=this.Ws,c=a.Ws;if(null===b?null===c:b.i(c))return b=this.Vs,a=a.Vs,null===b?null===a:b.i(a)}return!1};f.$classData=q({PX:0},!1,\"mlscript.PolyType\",{PX:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,Gaa:1,E:1,v:1,l:1});function N7(){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;Nq(this)}N7.prototype=new U2;N7.prototype.constructor=N7;f=N7.prototype;f.H=function(){return\"Top\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof N7};f.B=function(){return 84277};f.u=function(){return\"Top\"};f.$classData=q({pY:0},!1,\"mlscript.Top$\",{pY:1,Vz:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});var O7;function gl(){O7||(O7=new N7);return O7}function sP(a){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.nA=a;Nq(this)}sP.prototype=new U2;sP.prototype.constructor=sP;f=sP.prototype;f.H=function(){return\"TypeTag\"};\nf.G=function(){return 1};f.I=function(a){return 0===a?this.nA:$K(W(),a)};f.D=function(a){return a instanceof sP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof sP?this.nA===a.nA:!1};f.$classData=q({IY:0},!1,\"mlscript.TypeTag\",{IY:1,Vz:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,E:1,v:1,l:1});function Gv(){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0}Gv.prototype=new S_;Gv.prototype.constructor=Gv;function P7(){}\nP7.prototype=Gv.prototype;Gv.prototype.sl=function(a){return uw(this,a)};Gv.prototype.$l=function(a){return uw(this,a)};var Ru=q({IE:0},!1,\"mlscript.TyperDatatypes$AbstractTag\",{IE:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,uA:1,yj:1,nf:1,Hx:1});Gv.prototype.$classData=Ru;function VC(a,b){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.GO=this.HO=null;this.yI=!1;this.zI=b;pY(this,a);this.GO=V(a)}VC.prototype=new T_;VC.prototype.constructor=VC;f=VC.prototype;\nf.mc=function(){if(!this.yI&&!this.yI){var a=this.zI,b=V(this.zI.q);this.HO=NA(a,b,!1);this.yI=!0}return this.HO};f.ma=function(){return this.GO};f.H=function(){return\"NegAbsTag\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.zI:$K(W(),a)};f.D=function(a){return a instanceof VC};f.$classData=q({oZ:0},!1,\"mlscript.TyperDatatypes$NegAbsTag\",{oZ:1,EI:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,Hx:1,E:1,v:1,l:1});\nfunction UC(a,b){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.IO=this.JO=null;this.AI=!1;this.BI=b;pY(this,a);this.IO=V(a)}UC.prototype=new T_;UC.prototype.constructor=UC;f=UC.prototype;f.mc=function(){if(!this.AI&&!this.AI){var a=this.BI,b=V(this.BI.q);this.JO=NA(a,b,!1);this.AI=!0}return this.JO};f.ma=function(){return this.IO};f.H=function(){return\"NegVar\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.BI:$K(W(),a)};\nf.D=function(a){return a instanceof UC};f.$classData=q({qZ:0},!1,\"mlscript.TyperDatatypes$NegVar\",{qZ:1,EI:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,Hx:1,E:1,v:1,l:1});function Q7(a){if(0===(1&a.ii)<<24>>24&&0===(1&a.ii)<<24>>24){var b=a.NI;b.b()?b=R():(b=b.o(),b=Q7(b),b=b.b()?a.NI:b);a.dP=b;a.ii=(1|a.ii)<<24>>24}return a.dP}\nfunction R7(a){if(0===(4&a.ii)<<24>>24&&0===(4&a.ii)<<24>>24){t();var b=pE().SP,c=a.kg;c=c.b()?\"_\":c.o();a:{for(var d=c.length,e=0;e<d;){var g=c.charCodeAt(e);if(!Pe(new E(hc(g)),hc(39))){d=e;break a}e=1+e|0}d=-1}b=\"\"+b+(-1===d?\"\":c.substring(d));b=new L(b);t();c=UP(a.q);c=new jt(new fe(c),b);t();d=UP(a.q);b=new jt(new fe(d),b);a.eP=G(new H,c,b);a.ii=(4|a.ii)<<24>>24}return a.eP}\nfunction lx(a,b,c,d,e,g,h,k){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.Sb=this.$O=this.aP=this.eP=this.bP=this.dP=null;this.ii=this.sp=this.cP=0;this.Xa=b;this.YO=c;this.ZO=d;this.NI=e;this.kg=g;this.ji=k;pY(this,a);At(tp(),b<=a.Df);this.Sb=t().d;this.cP=a.Im;this.sp=UP(a)}lx.prototype=new qY;lx.prototype.constructor=lx;f=lx.prototype;f.sl=function(a){return gT(this,a)};f.Ea=function(){return this.Xa};f.ma=function(){return this.ji};\nfunction wy(a,b){tp();var c=b.b()?!0:b.o().Ea()<=a.Xa;At(0,c);a.Sb=b}function vy(a){if(!a.Sb.b())throw Kj(\"requirement failed: \"+a);return a.YO}function rA(a){if(!a.Sb.b())throw Kj(\"requirement failed: \"+a);return a.ZO}function IA(a,b){if(!a.Sb.b())throw Kj(\"requirement failed: \"+a);a.YO=b}function KA(a,b){if(!a.Sb.b())throw Kj(\"requirement failed: \"+a);a.ZO=b}function xca(a){if(Pe(new E(a.q.Im),a.cP)){var b=a.NI;return b.b()?a:b.o()}return a}\nf.ub=function(a,b){if(this.Xa<=a)return this.Xa;if(b.L(this))return this.q.Gd;b.$(this);var c=this.Sb;if(c instanceof L)return c.k.ub(a,b);if(t().d===c){c=vy(this).m().nb(new U(()=>rA(this).m()));c=new Ef(c,new y(e=>e.ub(a,b)));var d=Fq();c=Jq(c,d);return(c.b()?this.q.Gd:c.o())|0}throw new w(c);};function c7(a){0===(2&a.ii)<<24>>24&&0===(2&a.ii)<<24>>24&&(t(),a.bP=new jt(new fe(a.sp),a.kg),a.ii=(2|a.ii)<<24>>24);return a.bP}\nfunction Zfa(a){0===(8&a.ii)<<24>>24&&0===(8&a.ii)<<24>>24&&(a.aP=R7(a).h(),a.ii=(8|a.ii)<<24>>24);return a.aP}function $fa(a){0===(16&a.ii)<<24>>24&&0===(16&a.ii)<<24>>24&&(a.$O=R7(a).j(),a.ii=(16|a.ii)<<24>>24);return a.$O}function gT(a,b){a=new vw(a.sp);b=b.sp;Fq();a=a.al;return a===b?0:a<b?-1:1}\nf.u=function(){var a=Q7(this);if(a instanceof L){a=a.k;if(!Pe(new E(a.kg),this.kg))throw new Yj(\"assertion failed: \"+G(new H,a.kg,this.kg));a=S7(a)+\"_\"+this.sp+YC(this.q,this.Xa)}else{if(t().d!==a)throw new w(a);a=\"\"+S7(this)+YC(this.q,this.Xa)}return a+(this.Sb.b()?\"\":\"#\")};function S7(a){var b=a.kg;return\"\"+(b.b()?\"\\u03b1\":b.o())+a.sp}f.$l=function(a){return gT(this,a)};var RX=q({KZ:0},!1,\"mlscript.TyperDatatypes$TypeVariable\",{KZ:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,XO:1,yj:1,nf:1,Hx:1,tz:1});\nlx.prototype.$classData=RX;function nH(a,b){this.QR=this.Cy=null;if(null===a)throw null;this.Cy=a;this.QR=b}nH.prototype=new o7;nH.prototype.constructor=nH;nH.prototype.Q=function(){return qH(this.Cy)};nH.prototype.b=function(){return this.Cy.ck.b()||this.Cy.dk.b()};nH.prototype.m=function(){return new B0(this)};nH.prototype.$classData=q({A5:0},!1,\"scala.collection.LazyZip2$$anon$1\",{A5:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});\nfunction oH(a,b){this.SR=this.Ov=null;if(null===a)throw null;this.Ov=a;this.SR=b}oH.prototype=new o7;oH.prototype.constructor=oH;oH.prototype.Q=function(){return 0===this.Ov.ck.Q()||0===this.Ov.dk.Q()?0:-1};oH.prototype.b=function(){return this.Ov.ck.b()||this.Ov.dk.b()};oH.prototype.m=function(){return new D0(this)};oH.prototype.$classData=q({C5:0},!1,\"scala.collection.LazyZip2$$anon$3\",{C5:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});\nfunction UD(a){this.Dy=null;if(null===a)throw null;this.Dy=a}UD.prototype=new o7;UD.prototype.constructor=UD;UD.prototype.Q=function(){return qH(this.Dy)};UD.prototype.b=function(){return this.Dy.ck.b()||this.Dy.dk.b()};UD.prototype.m=function(){return new E0(this)};UD.prototype.$classData=q({E5:0},!1,\"scala.collection.LazyZip2$$anon$7\",{E5:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function T7(a){this.pL=a}T7.prototype=new o7;T7.prototype.constructor=T7;T7.prototype.m=function(){return this.pL.ie()};\nT7.prototype.Q=function(){return this.pL.Q()};T7.prototype.b=function(){return this.pL.b()};T7.prototype.$classData=q({S5:0},!1,\"scala.collection.MapView$Values\",{S5:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function i3(a,b){return a===b?!0:b&&b.$classData&&b.$classData.rb.Ac&&b.D(a)?a.Lt(b):!1}function U7(a,b,c,d){a.XB=b;a.Sp=c;a.Hy=d;a.wL=!1;return a}function V7(a,b){var c=new W7;U7(c,a,a.K(),b);return c}function W7(){this.XB=this.cS=null;this.Sp=0;this.Hy=null;this.vL=this.wL=!1}\nW7.prototype=new p;W7.prototype.constructor=W7;f=W7.prototype;f.Ub=function(){return eU()};f.u=function(){return w5(this)};f.Ih=function(){return\"SeqView\"};f.ti=function(){return eU().Eb()};f.tl=function(a){return IT(this,a)};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return(new X7(this)).m()};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};f.L=function(a){return QU(this,a)};f.$k=function(a){return iv(this,a)};f.ab=function(a){return iv(this,a)};f.e=function(){return this.m().t()};\nf.Mc=function(){return yT(this)};f.Gb=function(a){return KT(this,a)};f.Ca=function(a){cH(this,a)};f.qo=function(a){return ey(this,a)};f.De=function(a,b){return mB(this,a,b)};f.mf=function(a,b){return Qu(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};\nf.FC=function(){return v1(EK(),this)};f.Bj=function(a){return kB(this,a)};function Y7(a){if(!a.vL&&!a.vL){var b=a.Sp;if(0===b)b=O().c;else if(1===b)O(),b=[a.XB.e()],b=J(new K,b),b=Pd(u(),b);else{b=new zc(b);a.XB.Gc(b,0,2147483647);var c=a.Hy;hj(Pj(),b,c);b=KQ(JQ(),b)}a.wL=!0;a.XB=null;a.cS=b;a.vL=!0}return a.cS}function Z7(a){var b=a.XB;return a.wL?Y7(a):b}f.va=function(a){return Y7(this).va(a)};f.K=function(){return this.Sp};f.m=function(){return Rq().Pa.nb(new U(()=>Y7(this).m()))};f.Q=function(){return this.Sp};\nf.b=function(){return 0===this.Sp};f.ad=function(){return new X7(this)};f.cM=function(a){var b=this.Hy;return(null===a?null===b:a.i(b))?this:a.sj(this.Hy)?new X7(this):U7(new W7,Z7(this),this.Sp,a)};f.vc=function(a){return ZT(eU(),a)};f.Bb=function(a){return $7(new a8,this,a)};f.Jc=function(a){return b8(new c8,this,a)};f.cc=function(a){return d8(new e8,a,this)};f.Ja=function(a){return f8(new g8,this,a)};f.Zh=function(a){return this.cM(a)};\nf.$classData=q({V5:0},!1,\"scala.collection.SeqView$Sorted\",{V5:1,g:1,Li:1,kb:1,pa:1,M:1,N:1,jd:1,na:1,oa:1,l:1});function h8(a){if(!a.OG){var b=new i8,c=Y7(a.un);b.Rv=c;a.NG=b;a.OG=!0}return a.NG}function X7(a){this.NG=null;this.OG=!1;this.un=null;if(null===a)throw null;this.un=a}X7.prototype=new p;X7.prototype.constructor=X7;f=X7.prototype;f.Ub=function(){return eU()};f.u=function(){return w5(this)};f.Ih=function(){return\"SeqView\"};f.ti=function(){return eU().Eb()};\nf.tl=function(a){return IT(this,a)};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return this.un.m()};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};f.L=function(a){return QU(this,a)};f.$k=function(a){return iv(this,a)};f.ab=function(a){return iv(this,a)};f.e=function(){return this.m().t()};f.Mc=function(){return yT(this)};f.Gb=function(a){return KT(this,a)};f.Ca=function(a){cH(this,a)};f.qo=function(a){return ey(this,a)};f.De=function(a,b){return mB(this,a,b)};\nf.mf=function(a,b){return Qu(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.FC=function(){return v1(EK(),this)};f.Bj=function(a){return kB(this,a)};f.va=function(a){return(this.OG?this.NG:h8(this)).va(a)};f.K=function(){return this.un.Sp};\nf.m=function(){return Rq().Pa.nb(new U(()=>(this.OG?this.NG:h8(this)).m()))};f.Q=function(){return this.un.Sp};f.b=function(){return 0===this.un.Sp};f.ad=function(){return this.un};f.cM=function(a){var b=this.un.Hy;return(null===a?null===b:a.i(b))?this.un:a.sj(this.un.Hy)?this:U7(new W7,Z7(this.un),this.un.Sp,a)};f.vc=function(a){return ZT(eU(),a)};f.Bb=function(a){return $7(new a8,this,a)};f.Jc=function(a){return b8(new c8,this,a)};f.cc=function(a){return d8(new e8,a,this)};\nf.Ja=function(a){return f8(new g8,this,a)};f.Zh=function(a){return this.cM(a)};f.$classData=q({W5:0},!1,\"scala.collection.SeqView$Sorted$ReverseSorted\",{W5:1,g:1,Li:1,kb:1,pa:1,M:1,N:1,jd:1,na:1,oa:1,l:1});function $T(a){this.t6=a}$T.prototype=new o7;$T.prototype.constructor=$T;$T.prototype.m=function(){return Es(this.t6)};$T.prototype.$classData=q({s6:0},!1,\"scala.collection.View$$anon$1\",{s6:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function JT(a,b){this.AL=a;this.BL=b}JT.prototype=new o7;\nJT.prototype.constructor=JT;JT.prototype.m=function(){return this.AL.m().nb(new U(()=>this.BL.m()))};JT.prototype.Q=function(){var a=this.AL.Q();if(0<=a){var b=this.BL.Q();return 0<=b?a+b|0:-1}return-1};JT.prototype.b=function(){return this.AL.b()&&this.BL.b()};JT.prototype.$classData=q({u6:0},!1,\"scala.collection.View$Concat\",{u6:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function OY(a,b){this.CL=a;this.w6=b}OY.prototype=new o7;OY.prototype.constructor=OY;\nOY.prototype.m=function(){var a=this.CL.m();return new hy(a,this.w6)};OY.prototype.Q=function(){return 0===this.CL.Q()?0:-1};OY.prototype.b=function(){return this.CL.b()};OY.prototype.$classData=q({v6:0},!1,\"scala.collection.View$DistinctBy\",{v6:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function AT(a,b,c){a.My=b;a.cC=c;a.Tv=0<c?c:0;return a}function BT(){this.My=null;this.Tv=this.cC=0}BT.prototype=new o7;BT.prototype.constructor=BT;function j8(){}j8.prototype=BT.prototype;BT.prototype.m=function(){return this.My.m().ph(this.cC)};\nBT.prototype.Q=function(){var a=this.My.Q();return 0<=a?(a=a-this.Tv|0,0<a?a:0):-1};BT.prototype.b=function(){return!this.m().s()};BT.prototype.$classData=q({UG:0},!1,\"scala.collection.View$Drop\",{UG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function s3(a,b,c){a.Ly=b;a.aC=c;a.bC=0<c?c:0;return a}function t3(){this.Ly=null;this.bC=this.aC=0}t3.prototype=new o7;t3.prototype.constructor=t3;function k8(){}k8.prototype=t3.prototype;\nt3.prototype.m=function(){eU();var a=this.Ly.m();var b=this.aC;if(!(0>=b)){var c=a.Q();a=0<=c?a.Mn(c-b|0):new M0(a,b)}return a};t3.prototype.Q=function(){var a=this.Ly.Q();return 0<=a?(a=a-this.bC|0,0<a?a:0):-1};t3.prototype.b=function(){return 0<=this.Q()?0===this.Q():!this.m().s()};t3.prototype.$classData=q({VG:0},!1,\"scala.collection.View$DropRight\",{VG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function r3(a,b,c){this.gS=a;this.B6=b;this.A6=c}r3.prototype=new o7;\nr3.prototype.constructor=r3;r3.prototype.m=function(){var a=this.gS.m();return new iy(a,this.B6,this.A6)};r3.prototype.Q=function(){return 0===this.gS.Q()?0:-1};r3.prototype.b=function(){return!this.m().s()};r3.prototype.$classData=q({z6:0},!1,\"scala.collection.View$Filter\",{z6:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});q({C6:0},!1,\"scala.collection.View$FlatMap\",{C6:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function GT(a,b,c){a.Uv=b;a.dC=c;return a}\nfunction HT(){this.dC=this.Uv=null}HT.prototype=new o7;HT.prototype.constructor=HT;function l8(){}l8.prototype=HT.prototype;HT.prototype.m=function(){var a=this.Uv.m();return new Ef(a,this.dC)};HT.prototype.Q=function(){return this.Uv.Q()};HT.prototype.b=function(){return this.Uv.b()};HT.prototype.$classData=q({WG:0},!1,\"scala.collection.View$Map\",{WG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});function m8(){this.Ny=this.eC=null}m8.prototype=new o7;m8.prototype.constructor=m8;\nfunction n8(){}n8.prototype=m8.prototype;m8.prototype.m=function(){return(new JT(new o8(this.eC),this.Ny)).m()};m8.prototype.Q=function(){var a=this.Ny.Q();return 0<=a?1+a|0:-1};function o8(a){this.E6=a}o8.prototype=new o7;o8.prototype.constructor=o8;o8.prototype.m=function(){Rq();return new g0(this.E6)};o8.prototype.Q=function(){return 1};o8.prototype.b=function(){return!1};o8.prototype.$classData=q({D6:0},!1,\"scala.collection.View$Single\",{D6:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1});\nfunction p8(a,b,c){var d=a.U(b);c=c.n(d);d=G(new H,d,c);c=d.y;var e=d.w;if(R()===c&&R()===e)return a;c=d.w;if(d.y instanceof L&&R()===c)return a.xj(b);c=d.w;if(c instanceof L)return a.Dm(b,c.k);throw new w(d);}function h3(){}h3.prototype=new p;h3.prototype.constructor=h3;f=h3.prototype;f.uj=function(a,b){return 0>=this.Da(a,b)};f.Yj=function(a,b){return 0<=this.Da(a,b)};f.Xj=function(a,b){return 0<this.Da(a,b)};f.Yi=function(a,b){return x2(this,a,b)};f.Jk=function(a,b){return y2(this,a,b)};\nf.Kk=function(a,b){return z2(this,a,b)};f.sj=function(a){return A2(this,a)};f.Da=function(a,b){a|=0;b|=0;return a===b?0:a<b?-1:1};f.$classData=q({A3:0},!1,\"scala.math.Numeric$IntIsIntegral$\",{A3:1,g:1,rba:1,oba:1,qba:1,lm:1,Ji:1,mm:1,km:1,l:1,L3:1});var g3;function hP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Kw=null;this.Jw=!1;this.As=a;this.Bs=b;this.Yo=!1;Nq(this)}hP.prototype=new O4;hP.prototype.constructor=hP;f=hP.prototype;\nf.vK=function(){return this.As};f.DK=function(){return this.Bs};f.H=function(){return\"Inter\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.As;case 1:return this.Bs;default:return $K(W(),a)}};f.D=function(a){return a instanceof hP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof hP){var b=this.As,c=a.As;if(null===b?null===c:b.i(c))return b=this.Bs,a=a.Bs,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({hV:0},!1,\"mlscript.Inter\",{hV:1,pU:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,qU:1,E:1,v:1,l:1});function Oo(a,b,c,d,e,g,h,k){this.SC=this.RC=null;this.UC=this.VC=0;this.WC=this.TC=null;this.cl=0;this.dA=a;this.eA=b;this.gA=c;this.cA=d;this.eI=e;this.fI=g;this.fA=h;this.dI=k;Nq(this)}Oo.prototype=new P4;Oo.prototype.constructor=Oo;f=Oo.prototype;f.H=function(){return\"TypeDef\"};f.G=function(){return 8};\nf.I=function(a){switch(a){case 0:return this.dA;case 1:return this.eA;case 2:return this.gA;case 3:return this.cA;case 4:return this.eI;case 5:return this.fI;case 6:return this.fA;case 7:return this.dI;default:return $K(W(),a)}};f.D=function(a){return a instanceof Oo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Oo){if(this.dA===a.dA){var b=this.eA,c=a.eA;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.gA,c=a.gA,(null===b?null===c:b.i(c))?(b=this.cA,c=a.cA,b=null===b?null===c:b.i(c)):b=!1):b=!1;if(b&&(b=this.eI,c=a.eI,(null===b?null===c:b.i(c))?(b=this.fI,c=a.fI,b=null===b?null===c:b.i(c)):b=!1,b&&(b=this.fA,c=a.fA,null===b?null===c:b.i(c))))return b=this.dI,a=a.dI,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({uY:0},!1,\"mlscript.TypeDef\",{uY:1,FU:1,g:1,ud:1,md:1,xd:1,Ta:1,Od:1,GU:1,E:1,v:1,l:1});function cv(a,b,c,d){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.FO=this.dd=0;this.xI=!1;this.Nb=b;this.ac=c;this.Mj=d;pY(this,a)}cv.prototype=new W4;cv.prototype.constructor=cv;f=cv.prototype;f.ma=function(){return this.Mj};f.Ea=function(){if(!this.xI&&!this.xI){var a=this.Nb.Ea(),b=this.ac.Ea();this.FO=a>b?a:b;this.xI=!0}return this.FO};\nf.ub=function(a,b){var c=this.Nb.ub(a,b);a=this.ac.ub(a,b);return c>a?c:a};function q8(a,b,c,d,e){return new cv(a.q,a.Nb.Kc(b,c,d,e),a.ac.Kc(b,c,d,e),a.Mj)}\nf.u=function(){var a=!1,b=null,c=this.Nb;a:{if(c instanceof zv){a=!0;b=c;var d=b.Yb;if(d instanceof z){var e=d.z;d=d.p;if(null!==e){var g=e.h();e=e.j();if(t().d===g&&null!==e&&(g=e.Oa,e=e.ra,t().d===g&&e instanceof zv&&(g=O().c,null===g?null===d:g.i(d)))){c=\"[\"+r8(e)+\"]\";break a}}}}a&&(a=b.Yb,a instanceof z&&(b=a.z,a=a.p,null!==b&&(d=b.h(),b=b.j(),t().d===d?(d=O().c,a=null===d?null===a:d.i(a)):a=!1,a&&(c=b.u()))))}return\"(\"+c+\" -\\x3e \"+this.ac+\")\"};f.H=function(){return\"FunctionType\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.Nb;case 1:return this.ac;default:return $K(W(),a)}};f.D=function(a){return a instanceof cv};f.At=function(a,b,c,d){return q8(this,a,b,c,d)};f.qv=function(a,b,c,d){return q8(this,a,b,c,d)};f.$classData=q({mZ:0},!1,\"mlscript.TyperDatatypes$FunctionType\",{mZ:1,qA:1,Gx:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});\nfunction Jv(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.LO=this.dd=0;this.CI=!1;this.gi=b;this.Mq=c;pY(this,a);At(tp(),0<b.ab(0))}Jv.prototype=new W4;Jv.prototype.constructor=Jv;f=Jv.prototype;f.ma=function(){return this.Mq};function VW(a,b,c){var d=a.q,e=a.gi,g=m=>new cv(a.q,b.n(m.Nb),c.n(m.ac),m.Mj);if(e===u())g=u();else{var h=e.e(),k=h=new z(g(h),u());for(e=e.f();e!==u();){var l=e.e();l=new z(g(l),u());k=k.p=l;e=e.f()}g=h}return new Jv(d,g,a.Mq)}\nfunction rB(a,b,c){var d=a.q,e=a.gi,g=m=>{var n=a.q;if(b.b())var r=R();else r=!!b.o(),r=new L(!r);return new cv(n,c.ba(r,m.Nb),c.ba(b,m.ac),m.Mj)};if(e===u())g=u();else{var h=e.e(),k=h=new z(g(h),u());for(e=e.f();e!==u();){var l=e.e();l=new z(g(l),u());k=k.p=l;e=e.f()}g=h}return new Jv(d,g,a.Mq)}\nfunction jca(a,b,c){var d=a.q,e=a.gi,g=m=>new cv(a.q,c.ba(new UB(b),m.Nb),c.ba(b,m.ac),m.Mj);if(e===u())g=u();else{var h=e.e(),k=h=new z(g(h),u());for(e=e.f();e!==u();){var l=e.e();l=new z(g(l),u());k=k.p=l;e=e.f()}g=h}return new Jv(d,g,a.Mq)}\nfunction mX(a){var b=a.gi;if(b===u())var c=u();else{c=b.e();var d=c=new z(G(new H,c.Nb,c.ac),u());for(b=b.f();b!==u();){var e=b.e();e=new z(G(new H,e.Nb,e.ac),u());d=d.p=e;b=b.f()}}d=op();b=c.Gb(d.ga);if(null===b)throw new w(b);d=b.j();c=a.q;b=b.h().m();if(!b.s())throw nv(\"empty.reduceLeft\");e=!0;for(var g=null;b.s();){var h=b.t();if(e)g=h,e=!1;else{var k=V(g.q);g=dv(g,h,k,!1)}}b=g;d=d.m();if(!d.s())throw nv(\"empty.reduceLeft\");e=!0;for(g=null;d.s();)h=d.t(),e?(g=h,e=!1):(k=V(g.q),g=dv(g,h,k,!1));\nreturn new cv(c,b,g,a.Mq)}f.Ea=function(){this.CI||this.CI||(this.LO=this.ub(this.q.Df,jA().X()),this.CI=!0);return this.LO};f.ub=function(a,b){var c=this.gi.m();c=new Ef(c,new y(e=>e.ub(a,b)));var d=Fq();return hH(c,d)|0};function s8(a,b,c,d,e){var g=a.q,h=a.gi;if(h===u())b=u();else{var k=h.e(),l=k=new z(q8(k,b,c,d,e),u());for(h=h.f();h!==u();){var m=h.e();m=new z(q8(m,b,c,d,e),u());l=l.p=m;h=h.f()}b=k}return new Jv(g,b,a.Mq)}f.H=function(){return\"Overload\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.gi:$K(W(),a)};f.D=function(a){return a instanceof Jv};f.u=function(){return VK(this)};f.At=function(a,b,c,d){return s8(this,a,b,c,d)};f.qv=function(a,b,c,d){return s8(this,a,b,c,d)};f.$classData=q({sZ:0},!1,\"mlscript.TyperDatatypes$Overload\",{sZ:1,qA:1,Gx:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function Tv(a,b,c,d){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.Ic=b;this.kf=c;this.vp=d;pY(this,a)}Tv.prototype=new W4;\nTv.prototype.constructor=Tv;f=Tv.prototype;f.ma=function(){return this.vp};f.Ea=function(){return this.Ic.Ea()};f.ub=function(a,b){return this.Ic.ub(a,b)};f.u=function(){return this.Ic+\"\\\\\"+ze(this.kf,\"\",\"-\",\"\")};f.H=function(){return\"Without\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Ic;case 1:return this.kf;default:return $K(W(),a)}};f.D=function(a){return a instanceof Tv};f.At=function(a,b,c,d){return new Tv(this.q,this.Ic.Kc(a,b,c,d),this.kf,this.vp)};\nf.qv=function(a,b,c,d){return new Tv(this.q,this.Ic.Kc(a,b,c,d),this.kf,this.vp)};f.$classData=q({PZ:0},!1,\"mlscript.TyperDatatypes$Without\",{PZ:1,qA:1,Gx:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function iP(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.Kw=null;this.Jw=!1;this.ht=a;this.it=b;this.Yo=!0;Nq(this)}iP.prototype=new O4;iP.prototype.constructor=iP;f=iP.prototype;f.vK=function(){return this.ht};f.DK=function(){return this.it};\nf.H=function(){return\"Union\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.ht;case 1:return this.it;default:return $K(W(),a)}};f.D=function(a){return a instanceof iP};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof iP){var b=this.ht,c=a.ht;if(null===b?null===c:b.i(c))return b=this.it,a=a.it,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({a_:0},!1,\"mlscript.Union\",{a_:1,pU:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,qU:1,E:1,v:1,l:1});function t8(){}t8.prototype=new q3;t8.prototype.constructor=t8;function u8(){}f=u8.prototype=t8.prototype;f.D=function(){return!0};f.i=function(a){return kY(this,a)};f.B=function(){var a=BL();return CL(a,this,a.PB)};f.Ub=function(){return WY()};f.Oc=function(){return\"Set\"};f.u=function(){return w0(this)};f.fM=function(a){return this.ul(a)};f.Ce=function(a){return J0(this,a)};f.n=function(a){return this.L(a)};\nfunction v8(a,b){if(a===b)return!0;if(b&&b.$classData&&b.$classData.rb.Mk)if(a.ka()===b.ka())try{return a.ul(new y(c=>ml(nl(),b.Se(c.h(),HY().VR),c.j())))}catch(c){throw c;}else return!1;else return!1}function w8(a,b){var c=a.jq().Dv(a.se());c.zc(a);c.zc(b);return c.Kb()}function Ml(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.gs=a;this.Ml=b;W5(this)}Ml.prototype=new X5;Ml.prototype.constructor=Ml;f=Ml.prototype;f.H=function(){return\"Ann\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.gs;case 1:return this.Ml;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ml};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Ml){var b=this.gs,c=a.gs;if(null===b?null===c:b.i(c))return b=this.Ml,a=a.Ml,null===b?null===a:b.i(a)}return!1};f.$classData=q({PT:0},!1,\"mlscript.Ann\",{PT:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction Pl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Za=a;this.Qb=b;W5(this)}Pl.prototype=new X5;Pl.prototype.constructor=Pl;f=Pl.prototype;f.H=function(){return\"App\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Za;case 1:return this.Qb;default:return $K(W(),a)}};f.D=function(a){return a instanceof Pl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Pl){var b=this.Za,c=a.Za;if(null===b?null===c:b.i(c))return b=this.Qb,a=a.Qb,null===b?null===a:b.i(a)}return!1};f.$classData=q({QT:0},!1,\"mlscript.App\",{QT:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Cl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.ai=a;this.Fm=b;W5(this)}Cl.prototype=new X5;Cl.prototype.constructor=Cl;f=Cl.prototype;f.H=function(){return\"Asc\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.ai;case 1:return this.Fm;default:return $K(W(),a)}};f.D=function(a){return a instanceof Cl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Cl){var b=this.ai,c=a.ai;if(null===b?null===c:b.i(c))return b=this.Fm,a=a.Fm,null===b?null===a:b.i(a)}return!1};f.$classData=q({ST:0},!1,\"mlscript.Asc\",{ST:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction Wl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Gm=a;this.Qn=b;W5(this)}Wl.prototype=new X5;Wl.prototype.constructor=Wl;f=Wl.prototype;f.H=function(){return\"Assign\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Gm;case 1:return this.Qn;default:return $K(W(),a)}};f.D=function(a){return a instanceof Wl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Wl){var b=this.Gm,c=a.Gm;if(null===b?null===c:b.i(c))return b=this.Qn,a=a.Qn,null===b?null===a:b.i(a)}return!1};f.$classData=q({TT:0},!1,\"mlscript.Assign\",{TT:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Fl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.bi=a;this.gg=b;W5(this)}Fl.prototype=new X5;Fl.prototype.constructor=Fl;f=Fl.prototype;f.H=function(){return\"Bra\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.bi;case 1:return this.gg;default:return $K(W(),a)}};f.D=function(a){return a instanceof Fl};f.B=function(){var a=lb(\"Bra\");a=W().C(-889275714,a);var b=this.bi?1231:1237;a=W().C(a,b);b=this.gg;b=My(W(),b);a=W().C(a,b);return W().Ma(a,2)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Fl&&this.bi===a.bi){var b=this.gg;a=a.gg;return null===b?null===a:b.i(a)}return!1};\nf.$classData=q({ZT:0},!1,\"mlscript.Bra\",{ZT:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Ul(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Sn=a;this.Hm=b;W5(this)}Ul.prototype=new X5;Ul.prototype.constructor=Ul;f=Ul.prototype;f.H=function(){return\"CaseOf\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Sn;case 1:return this.Hm;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ul};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Ul){var b=this.Sn,c=a.Sn;if(null===b?null===c:b.i(c))return b=this.Hm,a=a.Hm,null===b?null===a:b.i(a)}return!1};f.$classData=q({nU:0},!1,\"mlscript.CaseOf\",{nU:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction No(a,b,c,d){this.SC=this.RC=null;this.UC=this.VC=0;this.WC=this.TC=null;this.cl=0;this.RM=null;this.ls=a;this.oq=b;this.vu=c;this.XC=d;Nq(this);if(c instanceof Ud)a=c.fa;else{if(!(c instanceof fe))throw new w(c);a=c.aa}this.RM=a}No.prototype=new P4;No.prototype.constructor=No;f=No.prototype;f.H=function(){return\"Def\"};f.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.ls;case 1:return this.oq;case 2:return this.vu;case 3:return this.XC;default:return $K(W(),a)}};\nf.D=function(a){return a instanceof No};f.B=function(){var a=lb(\"Def\");a=W().C(-889275714,a);var b=this.ls?1231:1237;a=W().C(a,b);b=this.oq;b=My(W(),b);a=W().C(a,b);b=this.vu;b=My(W(),b);a=W().C(a,b);b=this.XC?1231:1237;a=W().C(a,b);return W().Ma(a,4)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof No&&this.ls===a.ls&&this.XC===a.XC){var b=this.oq,c=a.oq;if(null===b?null===c:b.i(c))return b=this.vu,a=a.vu,null===b?null===a:b.i(a)}return!1};\nf.$classData=q({HU:0},!1,\"mlscript.Def\",{HU:1,FU:1,g:1,ud:1,md:1,xd:1,Ta:1,Od:1,GU:1,ce:1,E:1,v:1,l:1});function bm(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Vn=a;this.Zo=b;W5(this)}bm.prototype=new X5;bm.prototype.constructor=bm;f=bm.prototype;f.H=function(){return\"Eqn\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Vn;case 1:return this.Zo;default:return $K(W(),a)}};f.D=function(a){return a instanceof bm};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof bm){var b=this.Vn,c=a.Vn;if(null===b?null===c:b.i(c))return b=this.Zo,a=a.Zo,null===b?null===a:b.i(a)}return!1};f.$classData=q({NU:0},!1,\"mlscript.Eqn\",{NU:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Zl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.qq=a;this.$o=b;W5(this)}Zl.prototype=new X5;Zl.prototype.constructor=Zl;f=Zl.prototype;f.H=function(){return\"Forall\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.qq;case 1:return this.$o;default:return $K(W(),a)}};f.D=function(a){return a instanceof Zl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Zl){var b=this.qq,c=a.qq;if(null===b?null===c:b.i(c))return b=this.$o,a=a.$o,null===b?null===a:b.i(a)}return!1};f.$classData=q({VU:0},!1,\"mlscript.Forall\",{VU:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction Xl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.bp=a;this.zs=b;W5(this)}Xl.prototype=new X5;Xl.prototype.constructor=Xl;f=Xl.prototype;f.H=function(){return\"If\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.bp;case 1:return this.zs;default:return $K(W(),a)}};f.D=function(a){return a instanceof Xl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Xl){var b=this.bp,c=a.bp;if(null===b?null===c:b.i(c))return b=this.zs,a=a.zs,null===b?null===a:b.i(a)}return!1};f.$classData=q({ZU:0},!1,\"mlscript.If\",{ZU:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Kl(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.cp=a;W5(this)}Kl.prototype=new X5;Kl.prototype.constructor=Kl;f=Kl.prototype;f.H=function(){return\"Inst\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.cp:$K(W(),a)};f.D=function(a){return a instanceof Kl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Kl){var b=this.cp;a=a.cp;return null===b?null===a:b.i(a)}return!1};f.$classData=q({fV:0},!1,\"mlscript.Inst\",{fV:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction Ol(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Ej=a;this.Fj=b;W5(this)}Ol.prototype=new X5;Ol.prototype.constructor=Ol;f=Ol.prototype;f.H=function(){return\"Lam\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Ej;case 1:return this.Fj;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ol};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Ol){var b=this.Ej,c=a.Ej;if(null===b?null===c:b.i(c))return b=this.Fj,a=a.Fj,null===b?null===a:b.i(a)}return!1};f.$classData=q({sW:0},!1,\"mlscript.Lam\",{sW:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Rl(a,b,c,d){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.ep=a;this.Zn=b;this.$n=c;this.Mm=d;W5(this)}Rl.prototype=new X5;Rl.prototype.constructor=Rl;f=Rl.prototype;f.H=function(){return\"Let\"};\nf.G=function(){return 4};f.I=function(a){switch(a){case 0:return this.ep;case 1:return this.Zn;case 2:return this.$n;case 3:return this.Mm;default:return $K(W(),a)}};f.D=function(a){return a instanceof Rl};f.B=function(){var a=lb(\"Let\");a=W().C(-889275714,a);var b=this.ep?1231:1237;a=W().C(a,b);b=this.Zn;b=My(W(),b);a=W().C(a,b);b=this.$n;b=My(W(),b);a=W().C(a,b);b=this.Mm;b=My(W(),b);a=W().C(a,b);return W().Ma(a,4)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Rl){if(this.ep===a.ep){var b=this.Zn,c=a.Zn;b=null===b?null===c:b.i(c)}else b=!1;if(b&&(b=this.$n,c=a.$n,null===b?null===c:b.i(c)))return b=this.Mm,a=a.Mm,null===b?null===a:b.i(a)}return!1};f.$classData=q({tW:0},!1,\"mlscript.Let\",{tW:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Yl(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.hp=a;W5(this)}Yl.prototype=new X5;\nYl.prototype.constructor=Yl;f=Yl.prototype;f.H=function(){return\"NuNew\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.hp:$K(W(),a)};f.D=function(a){return a instanceof Yl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Yl){var b=this.hp;a=a.hp;return null===b?null===a:b.i(a)}return!1};f.$classData=q({pX:0},!1,\"mlscript.NuNew\",{pX:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction yo(a,b,c,d,e,g,h,k,l,m,n,r,v){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.sE=this.tE=this.Cf=null;this.gp=0;this.pb=a;this.gb=b;this.hg=c;this.Sg=d;this.Qm=e;this.Hj=g;this.Di=h;this.mx=k;this.Ns=l;this.ei=m;this.fl=n;this.Pm=r;this.Rz=v;U4(this)}yo.prototype=new V4;yo.prototype.constructor=yo;f=yo.prototype;f.tJ=function(){return this.Pm};f.H=function(){return\"NuTypeDef\"};f.G=function(){return 10};\nf.I=function(a){switch(a){case 0:return this.pb;case 1:return this.gb;case 2:return this.hg;case 3:return this.Sg;case 4:return this.Qm;case 5:return this.Hj;case 6:return this.Di;case 7:return this.mx;case 8:return this.Ns;case 9:return this.ei;default:return $K(W(),a)}};f.D=function(a){return a instanceof yo};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof yo){if(this.pb===a.pb){var b=this.gb,c=a.gb;b=null===b?null===c:b.i(c)}else b=!1;b?(b=this.hg,c=a.hg,(null===b?null===c:b.i(c))?(b=this.Sg,c=a.Sg,(null===b?null===c:b.i(c))?(b=this.Qm,c=a.Qm,b=null===b?null===c:b.i(c)):b=!1):b=!1):b=!1;if(b&&(b=this.Hj,c=a.Hj,(null===b?null===c:b.i(c))?(b=this.Di,c=a.Di,b=null===b?null===c:b.i(c)):b=!1,b&&(b=this.mx,c=a.mx,null===b?null===c:b.i(c)))&&(b=this.Ns,c=a.Ns,null===b?null===c:b.i(c)))return b=this.ei,\na=a.ei,null===b?null===a:b.i(a)}return!1};f.fd=function(){return this.pb};f.CB=function(){return this.pb};f.$classData=q({qX:0},!1,\"mlscript.NuTypeDef\",{qX:1,mX:1,ih:1,g:1,jh:1,Ta:1,md:1,xd:1,nX:1,MX:1,E:1,v:1,l:1});function em(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Iq=a;W5(this)}em.prototype=new X5;em.prototype.constructor=em;f=em.prototype;f.H=function(){return\"Quoted\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Iq:$K(W(),a)};\nf.D=function(a){return a instanceof em};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof em){var b=this.Iq;a=a.Iq;return null===b?null===a:b.i(a)}return!1};f.$classData=q({WX:0},!1,\"mlscript.Quoted\",{WX:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function yl(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.ll=a;W5(this)}yl.prototype=new X5;yl.prototype.constructor=yl;\nf=yl.prototype;f.H=function(){return\"Rcd\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.ll:$K(W(),a)};f.D=function(a){return a instanceof yl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof yl){var b=this.ll;a=a.ll;return null===b?null===a:b.i(a)}return!1};f.$classData=q({XX:0},!1,\"mlscript.Rcd\",{XX:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction cm(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Ys=a;this.Zs=b;W5(this)}cm.prototype=new X5;cm.prototype.constructor=cm;f=cm.prototype;f.H=function(){return\"Rft\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Ys;case 1:return this.Zs;default:return $K(W(),a)}};f.D=function(a){return a instanceof cm};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof cm){var b=this.Ys,c=a.Ys;if(null===b?null===c:b.i(c))return b=this.Zs,a=a.Zs,null===b?null===a:b.i(a)}return!1};f.$classData=q({$X:0},!1,\"mlscript.Rft\",{$X:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Ql(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Vl=a;this.ml=b;W5(this)}Ql.prototype=new X5;Ql.prototype.constructor=Ql;f=Ql.prototype;f.H=function(){return\"Sel\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.Vl;case 1:return this.ml;default:return $K(W(),a)}};f.D=function(a){return a instanceof Ql};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Ql){var b=this.Vl,c=a.Vl;if(null===b?null===c:b.i(c))return b=this.ml,a=a.ml,null===b?null===a:b.i(a)}return!1};f.$classData=q({dY:0},!1,\"mlscript.Sel\",{dY:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction Vl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.lp=a;this.mp=b;W5(this)}Vl.prototype=new X5;Vl.prototype.constructor=Vl;f=Vl.prototype;f.H=function(){return\"Subs\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.lp;case 1:return this.mp;default:return $K(W(),a)}};f.D=function(a){return a instanceof Vl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Vl){var b=this.lp,c=a.lp;if(null===b?null===c:b.i(c))return b=this.mp,a=a.mp,null===b?null===a:b.i(a)}return!1};f.$classData=q({nY:0},!1,\"mlscript.Subs\",{nY:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function am(){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;W5(this)}am.prototype=new X5;am.prototype.constructor=am;f=am.prototype;f.H=function(){return\"Super\"};f.G=function(){return 0};\nf.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof am};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return a instanceof am};f.$classData=q({oY:0},!1,\"mlscript.Super\",{oY:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Il(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.nl=a;this.np=b;W5(this)}Il.prototype=new X5;Il.prototype.constructor=Il;f=Il.prototype;f.H=function(){return\"TyApp\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.nl;case 1:return this.np;default:return $K(W(),a)}};f.D=function(a){return a instanceof Il};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Il){var b=this.nl,c=a.nl;if(null===b?null===c:b.i(c))return b=this.np,a=a.np,null===b?null===a:b.i(a)}return!1};f.$classData=q({tY:0},!1,\"mlscript.TyApp\",{tY:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction Sv(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.Fd=b;this.Fx=c;pY(this,a)}Sv.prototype=new $5;Sv.prototype.constructor=Sv;f=Sv.prototype;f.Zj=function(){return this.Fd};f.ma=function(){return this.Fx};f.Ea=function(){return this.Fd.Ea()};f.ub=function(a,b){return this.Fd.ub(a,b)};f.u=function(){return\"Array\\u2039\"+this.Fd+\"\\u203a\"};f.H=function(){return\"ArrayType\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Fd:$K(W(),a)};\nf.D=function(a){return a instanceof Sv};f.At=function(a,b,c,d){return new Sv(this.q,LX(this.Fd,a,b,c,d),this.Fx)};f.qv=function(a,b,c,d){return new Sv(this.q,LX(this.Fd,a,b,c,d),this.Fx)};f.$classData=q({WY:0},!1,\"mlscript.TyperDatatypes$ArrayType\",{WY:1,eO:1,qA:1,Gx:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});\nfunction ega(a){if(0===(1&a.ft)<<24>>24){var b=a.fo,c=h=>{if(h instanceof fe)return h.aa.Ea();if(h instanceof Ud)return h.fa.Ea();throw new w(h);};if(b===u())c=u();else{var d=b.e(),e=d=new z(c(d),u());for(b=b.f();b!==u();){var g=b.e();g=new z(c(g),u());e=e.p=g;b=b.f()}c=d}d=Fq();a.HI=hH(c,d)|0;a.ft=(1|a.ft)<<24>>24}return a.HI}\nfunction fga(a){if(0===(2&a.ft)<<24>>24){var b=a.fo,c=h=>{if(h instanceof fe){h=h.aa;if(h instanceof Vv)return h.Zj();no()}else{if(h instanceof Ud)return h.fa;throw new w(h);}};if(b===u())c=u();else{var d=b.e(),e=d=new z(c(d),u());for(b=b.f();b!==u();){var g=b.e();g=new z(c(g),u());e=e.p=g;b=b.f()}c=d}c=c.m();if(!c.s())throw nv(\"empty.reduceLeft\");d=!0;for(b=null;c.s();)e=c.t(),d?(b=e,d=!1):b=xw(b,e,V(b.Va));a.GI=b;a.ft=(2|a.ft)<<24>>24}return a.GI}\nfunction Wv(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.HI=this.dd=0;this.GI=null;this.ft=0;this.fo=b;this.Uu=c;pY(this,a);At(tp(),!b.b())}Wv.prototype=new $5;Wv.prototype.constructor=Wv;f=Wv.prototype;f.ma=function(){return this.Uu};f.Ea=function(){return 0===(1&this.ft)<<24>>24?ega(this):this.HI};\nf.qv=function(a,b,c,d){var e=this.q,g=this.fo,h=n=>{if(n instanceof fe)return n=n.aa,t(),n=n.Kc(a,b,c,d),new fe(n);if(n instanceof Ud)return n=n.fa,t(),n=LX(n,a,b,c,d),new Ud(n);throw new w(n);};if(g===u())h=u();else{var k=g.e(),l=k=new z(h(k),u());for(g=g.f();g!==u();){var m=g.e();m=new z(h(m),u());l=l.p=m;g=g.f()}h=k}return new Wv(e,h,this.Uu)};\nf.ub=function(a,b){var c=this.fo,d=k=>{if(k instanceof fe)return k.aa.ub(a,b);if(k instanceof Ud)return k.fa.ub(a,b);throw new w(k);};if(c===u())d=u();else{var e=c.e(),g=e=new z(d(e),u());for(c=c.f();c!==u();){var h=c.e();h=new z(d(h),u());g=g.p=h;c=c.f()}d=e}e=Fq();return hH(d,e)|0};f.Zj=function(){return 0===(2&this.ft)<<24>>24?fga(this):this.GI};\nfunction sB(a,b,c,d,e){var g=a.q,h=a.fo;a=n=>{if(n instanceof fe)return n=n.aa,t(),n=b.n(n),new fe(n);if(n instanceof Ud)return n=n.fa,t(),n=cB(n,c,d),new Ud(n);throw new w(n);};if(h===u())a=u();else{var k=h.e(),l=k=new z(a(k),u());for(h=h.f();h!==u();){var m=h.e();m=new z(a(m),u());l=l.p=m;h=h.f()}a=k}return new Wv(g,a,e)}f.H=function(){return\"SpliceType\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.fo:$K(W(),a)};f.D=function(a){return a instanceof Wv};f.u=function(){return VK(this)};\nf.At=function(a,b,c,d){return this.qv(a,b,c,d)};f.$classData=q({AZ:0},!1,\"mlscript.TyperDatatypes$SpliceType\",{AZ:1,eO:1,qA:1,Gx:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function gga(a){if(0===(2&a.Oj)<<24>>24){var b=a.Yb.m();b=new Ef(b,new y(d=>d.j().Ea()));var c=Fq();b=Jq(b,c);a.KI=(b.b()?0:b.o())|0;a.Oj=(2|a.Oj)<<24>>24}return a.KI}\nfunction hga(a){if(0===(8&a.Oj)<<24>>24){var b=a.q,c=Hf(a.Yb),d=k=>{if(null!==k){var l=k.h(),m=k.Sc();if(null!==l)return k=l.j(),G(new H,new vl(\"\"+m),k)}throw new w(k);};if(c===u())d=u();else{var e=c.e(),g=e=new z(d(e),u());for(c=c.f();c!==u();){var h=c.e();h=new z(d(h),u());g=g.p=h;c=c.f()}d=e}a.LI=new Qv(b,d,a.Nq);a.Oj=(8|a.Oj)<<24>>24}return a.LI}\nfunction zv(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.RO=null;this.KI=0;this.LI=this.SO=null;this.Oj=0;this.Yb=b;this.Nq=c;pY(this,a)}zv.prototype=new $5;zv.prototype.constructor=zv;f=zv.prototype;f.ma=function(){return this.Nq};\nf.Zj=function(){if(0===(1&this.Oj)<<24>>24&&0===(1&this.Oj)<<24>>24){var a=this.Yb;if(a===u())var b=u();else{b=a.e();var c=b=new z(b.j(),u());for(a=a.f();a!==u();){var d=a.e();d=new z(d.j(),u());c=c.p=d;a=a.f()}}if(b.b())b=R();else{b=b.m();if(!b.s())throw nv(\"empty.reduceLeft\");c=!0;for(d=null;b.s();)a=b.t(),c?(d=a,c=!1):d=xw(d,a,V(d.Va));b=new L(d)}b.b()?(b=this.q.ib,c=V(this.q),b=new Uw(b.q,R(),b,c)):b=b.o();this.RO=b;this.Oj=(1|this.Oj)<<24>>24}return this.RO};\nf.Ea=function(){return 0===(2&this.Oj)<<24>>24?gga(this):this.KI};f.ub=function(a,b){var c=this.Yb.m();c=new Ef(c,new y(e=>e.j().ub(a,b)));var d=Fq();c=Jq(c,d);return(c.b()?this.q.Gd:c.o())|0};function x8(a,b,c,d,e){var g=a.q;lv();return new zv(g,ry(0,a.Yb,new y(h=>LX(h,b,c,d,e))),a.Nq)}function Dw(a){0===(4&a.Oj)<<24>>24&&0===(4&a.Oj)<<24>>24&&(a.SO=new Sv(a.q,a.Zj(),a.Nq),a.Oj=(4|a.Oj)<<24>>24);return a.SO}f.kq=function(){return 0===(8&this.Oj)<<24>>24?hga(this):this.LI};\nfunction r8(a){var b=a.Yb;a=g=>{var h=g.h();return(h.b()?\"\":h.o().x+\": \")+g.j()+\",\"};if(b===u())a=u();else{var c=b.e(),d=c=new z(a(c),u());for(b=b.f();b!==u();){var e=b.e();e=new z(a(e),u());d=d.p=e;b=b.f()}a=c}return ze(a,\"\",\" \",\"\")}f.u=function(){return\"(\"+r8(this)+\")\"};f.H=function(){return\"TupleType\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Yb:$K(W(),a)};f.D=function(a){return a instanceof zv};f.At=function(a,b,c,d){return x8(this,a,b,c,d)};\nf.qv=function(a,b,c,d){return x8(this,a,b,c,d)};f.$classData=q({EZ:0},!1,\"mlscript.TyperDatatypes$TupleType\",{EZ:1,eO:1,qA:1,Gx:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,E:1,v:1,l:1});function fm(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.jt=a;W5(this)}fm.prototype=new X5;fm.prototype.constructor=fm;f=fm.prototype;f.H=function(){return\"Unquoted\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.jt:$K(W(),a)};f.D=function(a){return a instanceof fm};\nf.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof fm){var b=this.jt;a=a.jt;return null===b?null===a:b.i(a)}return!1};f.$classData=q({c_:0},!1,\"mlscript.Unquoted\",{c_:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function $l(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Yq=a;this.lt=b;W5(this)}$l.prototype=new X5;$l.prototype.constructor=$l;f=$l.prototype;f.H=function(){return\"Where\"};\nf.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.Yq;case 1:return this.lt;default:return $K(W(),a)}};f.D=function(a){return a instanceof $l};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof $l){var b=this.Yq,c=a.Yq;if(null===b?null===c:b.i(c))return b=this.lt,a=a.lt,null===b?null===a:b.i(a)}return!1};f.$classData=q({j_:0},!1,\"mlscript.Where\",{j_:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});\nfunction dm(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.$q=a;this.Zq=b;W5(this)}dm.prototype=new X5;dm.prototype.constructor=dm;f=dm.prototype;f.H=function(){return\"While\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.$q;case 1:return this.Zq;default:return $K(W(),a)}};f.D=function(a){return a instanceof dm};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof dm){var b=this.$q,c=a.$q;if(null===b?null===c:b.i(c))return b=this.Zq,a=a.Zq,null===b?null===a:b.i(a)}return!1};f.$classData=q({k_:0},!1,\"mlscript.While\",{k_:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function Tl(a,b){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.br=a;this.ar=b;W5(this)}Tl.prototype=new X5;Tl.prototype.constructor=Tl;f=Tl.prototype;f.H=function(){return\"With\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.br;case 1:return this.ar;default:return $K(W(),a)}};f.D=function(a){return a instanceof Tl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Tl){var b=this.br,c=a.br;if(null===b?null===c:b.i(c))return b=this.ar,a=a.ar,null===b?null===a:b.i(a)}return!1};f.$classData=q({m_:0},!1,\"mlscript.With\",{m_:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,E:1,v:1,l:1});function y8(){}y8.prototype=new q3;\ny8.prototype.constructor=y8;function z8(){}f=z8.prototype=y8.prototype;f.D=function(){return!0};f.i=function(a){return i3(this,a)};f.B=function(){return qS(this)};f.u=function(){return w0(this)};f.gn=function(a){return IT(this,a)};f.tl=function(a){return this.gn(a)};f.ka=function(){return this.K()};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return this.ad().m()};f.NJ=function(a){return 0<=a&&0<this.ab(a)};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};\nf.L=function(a){return QU(this,a)};f.Zh=function(a){return qw(this,a)};f.$k=function(a){return this.ab(a)};f.ab=function(a){return iv(this,a)};f.b=function(){return SY(this)};f.Lt=function(a){return TY(this,a)};f.Ob=function(a,b){return GQ(this,a,b)};f.Lc=function(a){return this.NJ(a|0)};function A8(){}A8.prototype=new o7;A8.prototype.constructor=A8;function B8(){}f=B8.prototype=A8.prototype;f.Ph=function(a){return f8(new g8,this,a)};f.Rh=function(a){return d8(new e8,a,this)};\nf.Mh=function(a){return b8(new c8,this,a)};f.Kh=function(a){return $7(new a8,this,a)};f.Oc=function(){return\"SeqView\"};f.tl=function(a){return IT(this,a)};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return this.ad().m()};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};f.L=function(a){return QU(this,a)};f.$k=function(a){return this.ab(a)};f.ab=function(a){return iv(this,a)};f.b=function(){return SY(this)};f.Zh=function(a){return V7(this,a)};f.Bb=function(a){return this.Kh(a)};f.Jc=function(a){return this.Mh(a)};\nf.cc=function(a){return this.Rh(a)};f.Ja=function(a){return this.Ph(a)};function gU(){}gU.prototype=new o7;gU.prototype.constructor=gU;f=gU.prototype;f.m=function(){return Rq().Pa};f.Q=function(){return 0};f.b=function(){return!0};f.H=function(){return\"Empty\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.D=function(a){return a instanceof gU};f.B=function(){return 67081517};\nf.$classData=q({y6:0},!1,\"scala.collection.View$Empty$\",{y6:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,E:1,v:1});var fU;function EB(a,b){if(a.L(b))return!1;a.$(b);return!0}\nfunction Zn(a,b,c,d,e,g,h,k,l,m,n,r){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.sE=this.tE=this.Cf=null;this.gp=0;this.DN=this.EN=null;this.wd=a;this.Rb=b;this.hj=c;this.Ch=d;this.Yc=e;this.Pz=g;this.lx=h;this.Om=k;this.kx=l;this.Qz=m;this.Pl=n;this.Oz=r;U4(this);if(e instanceof Ud)a=e.fa;else{if(!(e instanceof fe))throw new w(e);a=e.aa}this.EN=a;this.DN=R()}Zn.prototype=new V4;Zn.prototype.constructor=Zn;f=Zn.prototype;f.fd=function(){return hx()};f.tJ=function(){return this.DN};\nfunction rx(a){return a.wd.b()?!1:!a.Pl}function Gy(a){return a.lx.b()?a.Yc.tv():!0}function Ix(a){if(a.wd.b())return!0;a=a.Yc;if(a instanceof fe)return oea(a.aa);if(a instanceof Ud)return!1;throw new w(a);}f.H=function(){return\"NuFunDef\"};f.G=function(){return 5};f.I=function(a){switch(a){case 0:return this.wd;case 1:return this.Rb;case 2:return this.hj;case 3:return this.Ch;case 4:return this.Yc;default:return $K(W(),a)}};f.D=function(a){return a instanceof Zn};f.B=function(){return AL(this)};\nf.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Zn){var b=this.wd,c=a.wd;(null===b?null===c:b.i(c))?(b=this.Rb,c=a.Rb,b=null===b?null===c:b.i(c)):b=!1;if(b&&(b=this.hj,c=a.hj,null===b?null===c:b.i(c))&&(b=this.Ch,c=a.Ch,null===b?null===c:b.i(c)))return b=this.Yc,a=a.Yc,null===b?null===a:b.i(a)}return!1};f.$classData=q({oX:0},!1,\"mlscript.NuFunDef\",{oX:1,mX:1,ih:1,g:1,jh:1,Ta:1,md:1,xd:1,nX:1,ud:1,Od:1,E:1,v:1,l:1});\nfunction C8(a){W5(a);if(a instanceof vl)var b=a.x;else{if(!(a instanceof Dl))throw new w(a);b=Zz(a,!1)}a.Dh=b}function wm(){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Dh=null}wm.prototype=new X5;wm.prototype.constructor=wm;function D8(){}D8.prototype=wm.prototype;wm.prototype.sl=function(a){return pa(this.Dh,a.Dh)};wm.prototype.$l=function(a){return pa(this.Dh,a.Dh)};\nfunction Gl(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Ra=a;W5(this)}Gl.prototype=new X5;Gl.prototype.constructor=Gl;f=Gl.prototype;f.H=function(){return\"Tup\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Ra:$K(W(),a)};f.D=function(a){return a instanceof Gl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Gl){var b=this.Ra;a=a.Ra;return null===b?null===a:b.i(a)}return!1};\nf.$classData=q({rY:0},!1,\"mlscript.Tup\",{rY:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,Iaa:1,E:1,v:1,l:1});function jt(a,b){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.pp=a;this.oA=b;Nq(this);At(tp(),b.b()||a.TJ())}jt.prototype=new U2;jt.prototype.constructor=jt;f=jt.prototype;f.sl=function(a){return bT(this,a)};\nf.u=function(){var a=this.pp;if(a instanceof Ud)a=a.fa;else{if(!(a instanceof fe))throw new w(a);a=\"\\u03b1\"+(a.aa|0)}return a};f.H=function(){return\"TypeVar\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.pp;case 1:return this.oA;default:return $K(W(),a)}};f.D=function(a){return a instanceof jt};f.B=function(){return AL(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof jt){var b=this.pp,c=a.pp;if(null===b?null===c:b.i(c))return b=this.oA,a=a.oA,null===b?null===a:b.i(a)}return!1};f.$l=function(a){return bT(this,a)};f.$classData=q({JY:0},!1,\"mlscript.TypeVar\",{JY:1,Vz:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,Naa:1,yj:1,nf:1,E:1,v:1,l:1});function E8(){}E8.prototype=new q3;E8.prototype.constructor=E8;function F8(){}f=F8.prototype=E8.prototype;f.D=function(){return!0};f.i=function(a){return v8(this,a)};\nf.B=function(){var a=BL();if(this.b())a=a.mG;else{var b=new sS,c=a.Cr;this.og(b);c=a.C(c,b.PK);c=a.C(c,b.QK);c=a.Pp(c,b.RK);a=a.Ma(c,b.SK)}return a};f.Oc=function(){return\"Map\"};f.u=function(){return w0(this)};f.Gk=function(a){return this.vj().Ib(a)};f.ti=function(){return this.vj().Eb()};f.Se=function(a,b){return x3(this,a,b)};f.n=function(a){return HA(this,a)};f.Ob=function(a,b){return y3(this,a,b)};f.zr=function(){return G8(new H8,this)};f.tT=function(){return new rp(this)};f.tj=function(){return new I0(this)};\nf.ie=function(){return new Ou(this)};f.og=function(a){for(var b=this.m();b.s();){var c=b.t();a.ba(c.h(),c.j())}};f.IF=function(a){return z3(a)};f.L=function(a){return!this.U(a).b()};f.Lc=function(a){return this.L(a)};f.ry=function(a){return this.vj().Ib(GT(new HT,this,a))};f.am=function(a){return A3(this,a)};f.bf=function(a){return this.am(a)};f.Gh=function(a,b,c,d){return B3(this,a,b,c,d)};f.vc=function(a){return this.Gk(a)};function b8(a,b,c){a.Gy=b;a.KG=c;AT(a,b,c);return a}\nfunction c8(){this.My=null;this.Tv=this.cC=0;this.Gy=null;this.KG=0}c8.prototype=new j8;c8.prototype.constructor=c8;function I8(){}f=I8.prototype=c8.prototype;f.Ph=function(a){return f8(new g8,this,a)};f.Rh=function(a){return d8(new e8,a,this)};f.Kh=function(a){return $7(new a8,this,a)};f.Oc=function(){return\"SeqView\"};f.tl=function(a){return IT(this,a)};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return this.ad().m()};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};\nf.L=function(a){return QU(this,a)};f.$k=function(a){return this.ab(a)};f.ab=function(a){return iv(this,a)};f.b=function(){return SY(this)};f.K=function(){var a=this.Gy.K()-this.Tv|0;return 0<a?a:0};f.va=function(a){return this.Gy.va(a+this.Tv|0)};f.Mh=function(a){return b8(new c8,this.Gy,this.KG+a|0)};f.Zh=function(a){return V7(this,a)};f.Bb=function(a){return this.Kh(a)};f.cc=function(a){return this.Rh(a)};f.Ja=function(a){return this.Ph(a)};f.Jc=function(a){return this.Mh(a)};\nf.$classData=q({rL:0},!1,\"scala.collection.SeqView$Drop\",{rL:1,UG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1});function $7(a,b,c){a.JG=b;s3(a,b,c);b=b.K()-(0<c?c:0)|0;a.Fy=0<b?b:0;return a}function a8(){this.Ly=null;this.bC=this.aC=0;this.JG=null;this.Fy=0}a8.prototype=new k8;a8.prototype.constructor=a8;function J8(){}f=J8.prototype=a8.prototype;f.Ph=function(a){return f8(new g8,this,a)};f.Rh=function(a){return d8(new e8,a,this)};f.Mh=function(a){return b8(new c8,this,a)};\nf.Kh=function(a){return $7(new a8,this,a)};f.Oc=function(){return\"SeqView\"};f.tl=function(a){return IT(this,a)};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return this.ad().m()};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};f.L=function(a){return QU(this,a)};f.$k=function(a){return this.ab(a)};f.ab=function(a){return iv(this,a)};f.b=function(){return SY(this)};f.K=function(){return this.Fy};f.va=function(a){return this.JG.va(a)};f.Zh=function(a){return V7(this,a)};f.Bb=function(a){return this.Kh(a)};\nf.Jc=function(a){return this.Mh(a)};f.cc=function(a){return this.Rh(a)};f.Ja=function(a){return this.Ph(a)};f.$classData=q({sL:0},!1,\"scala.collection.SeqView$DropRight\",{sL:1,VG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1});function bU(a,b){a.Qv=b;return a}function cU(){this.Qv=null}cU.prototype=new B8;cU.prototype.constructor=cU;function K8(){}f=K8.prototype=cU.prototype;f.va=function(a){return this.Qv.va(a)};f.K=function(){return this.Qv.K()};f.m=function(){return this.Qv.m()};\nf.Q=function(){return this.Qv.Q()};f.b=function(){return this.Qv.b()};f.$classData=q({aS:0},!1,\"scala.collection.SeqView$Id\",{aS:1,QB:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1});function f8(a,b,c){a.VB=b;a.LG=c;GT(a,b,c);return a}function g8(){this.LG=this.VB=this.dC=this.Uv=null}g8.prototype=new l8;g8.prototype.constructor=g8;function L8(){}f=L8.prototype=g8.prototype;f.Ph=function(a){return f8(new g8,this,a)};f.Rh=function(a){return d8(new e8,a,this)};\nf.Mh=function(a){return b8(new c8,this,a)};f.Kh=function(a){return $7(new a8,this,a)};f.Oc=function(){return\"SeqView\"};f.tl=function(a){return IT(this,a)};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return this.ad().m()};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};f.L=function(a){return QU(this,a)};f.$k=function(a){return this.ab(a)};f.ab=function(a){return iv(this,a)};f.b=function(){return SY(this)};f.va=function(a){return this.LG.n(this.VB.va(a))};f.K=function(){return this.VB.K()};\nf.Zh=function(a){return V7(this,a)};f.Bb=function(a){return this.Kh(a)};f.Jc=function(a){return this.Mh(a)};f.cc=function(a){return this.Rh(a)};f.Ja=function(a){return this.Ph(a)};f.$classData=q({tL:0},!1,\"scala.collection.SeqView$Map\",{tL:1,WG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1});function d8(a,b,c){a.MG=b;a.WB=c;a.eC=b;a.Ny=c;return a}function e8(){this.WB=this.MG=this.Ny=this.eC=null}e8.prototype=new n8;e8.prototype.constructor=e8;function M8(){}f=M8.prototype=e8.prototype;\nf.Ph=function(a){return f8(new g8,this,a)};f.Rh=function(a){return d8(new e8,a,this)};f.Mh=function(a){return b8(new c8,this,a)};f.Kh=function(a){return $7(new a8,this,a)};f.Oc=function(){return\"SeqView\"};f.tl=function(a){return IT(this,a)};f.Ii=function(a){return NY(this,a)};f.Sd=function(){return this.ad().m()};f.wo=function(a,b){var c=this.m();return LT(c,a,b)};f.L=function(a){return QU(this,a)};f.$k=function(a){return this.ab(a)};f.ab=function(a){return iv(this,a)};f.b=function(){return SY(this)};\nf.va=function(a){return 0===a?this.MG:this.WB.va(-1+a|0)};f.K=function(){return 1+this.WB.K()|0};f.Zh=function(a){return V7(this,a)};f.Bb=function(a){return this.Kh(a)};f.Jc=function(a){return this.Mh(a)};f.cc=function(a){return this.Rh(a)};f.Ja=function(a){return this.Ph(a)};f.$classData=q({uL:0},!1,\"scala.collection.SeqView$Prepended\",{uL:1,hS:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1});function i8(){this.Rv=null}i8.prototype=new B8;i8.prototype.constructor=i8;function N8(){}\nf=N8.prototype=i8.prototype;f.va=function(a){return this.Rv.va((-1+this.K()|0)-a|0)};f.K=function(){return this.Rv.K()};f.m=function(){return this.Rv.Sd()};f.Q=function(){return this.Rv.Q()};f.b=function(){return this.Rv.b()};f.$classData=q({bS:0},!1,\"scala.collection.SeqView$Reverse\",{bS:1,QB:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1});\nfunction O8(a,b){if(a===b)return!0;if(b&&b.$classData&&b.$classData.rb.PG){var c=b.se(),d=a.se();if(null===c?null===d:c.i(d)){if(a.ka()===b.ka()){c=a.m();b=b.m();for(d=!0;d&&c.s();)d=a.se().Yi(c.t(),b.t());return d}return!1}}return kY(a,b)}function P8(a,b,c){var d=a.U(b);c=c.n(d);d=G(new H,d,c);var e=d.y,g=d.w;if(R()!==e||R()!==g)if(e=d.w,d.y instanceof L&&R()===e)a.JB(b);else if(e=d.w,e instanceof L)a.bh(b,e.k);else throw new w(d);return c}\nfunction pX(a,b,c){var d=a.U(b);if(d instanceof L)return d.k;if(R()===d)return c=Es(c),a.bh(b,c),c;throw new w(d);}function Sl(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Dj=a;W5(this)}Sl.prototype=new X5;Sl.prototype.constructor=Sl;f=Sl.prototype;f.H=function(){return\"Blk\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Dj:$K(W(),a)};f.D=function(a){return a instanceof Sl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Sl){var b=this.Dj;a=a.Dj;return null===b?null===a:b.i(a)}return!1};f.CB=function(){return g_()};f.$classData=q({VT:0},!1,\"mlscript.Blk\",{VT:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,vaa:1,MX:1,E:1,v:1,l:1});function Mu(a,b,c,d){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.fO=null;this.tI=!1;this.pd=b;this.JE=c;this.ZY=d;pY(this,a)}Mu.prototype=new d3;Mu.prototype.constructor=Mu;f=Mu.prototype;f.u=function(){return oY(this)};\nf.sl=function(a){return uw(this,a)};f.Fv=function(){this.tI||this.tI||(this.fO=nY(this),this.tI=!0);return this.fO};f.rr=function(){return this.pd};f.AK=function(){return this.JE};f.ma=function(){return this.ZY};function sba(a,b){return Pe(new E(b.pd),a.pd)?(t(),new L(a)):b.Fv().L(a.pd)?(t(),new L(b)):a.Fv().L(b.pd)?(t(),new L(a)):t().d}f.Ea=function(){return this.q.Gd};f.ub=function(){return this.q.Gd};f.H=function(){return\"ClassTag\"};f.G=function(){return 2};\nf.I=function(a){switch(a){case 0:return this.pd;case 1:return this.JE;default:return $K(W(),a)}};f.D=function(a){return a instanceof Mu};f.$l=function(a){return uw(this,a)};f.At=function(){return this};f.uo=function(){return this.pd};f.$classData=q({YY:0},!1,\"mlscript.TyperDatatypes$ClassTag\",{YY:1,Gx:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,uA:1,yj:1,nf:1,KO:1,E:1,v:1,l:1});function Q8(){}Q8.prototype=new o7;Q8.prototype.constructor=Q8;function R8(){}f=R8.prototype=Q8.prototype;f.tT=function(){return new T7(this)};\nf.u=function(){return w5(this)};f.Oc=function(){return\"MapView\"};f.Se=function(a,b){return x3(this,a,b)};f.n=function(a){return HA(this,a)};f.Ob=function(a,b){return y3(this,a,b)};f.tj=function(){return new I0(this)};f.ie=function(){return new Ou(this)};f.IF=function(a){return z3(a)};f.L=function(a){return!this.U(a).b()};f.Lc=function(a){return!this.U(a).b()};f.bf=function(a){return A3(this,a)};f.Gh=function(a,b,c,d){return B3(this,a,b,c,d)};f.vj=function(){JY||(JY=new IY);return JY};\nfunction $X(a,b){return S8(new T8,a,new y(()=>b))}function jV(a){return!!(a&&a.$classData&&a.$classData.rb.Pr)}function Dl(){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Dh=null}Dl.prototype=new D8;Dl.prototype.constructor=Dl;function U8(){}U8.prototype=Dl.prototype;function Ep(a){this.df=this.cf=this.jf=null;this.ff=this.gf=0;this.hf=this.ef=null;this.sc=0;this.Eg=this.Dg=null;this.Qe=0;this.XN=null;this.jI=!1;this.V=a;Nq(this)}Ep.prototype=new U2;\nEp.prototype.constructor=Ep;f=Ep.prototype;f.sl=function(a){return pa(this.V,a.V)};f.Zr=function(){if(!this.jI&&!this.jI){var a=new vl(this.V),b=this.A();this.XN=Cq(a,b);this.jI=!0}return this.XN};f.Ua=function(){return this.V};f.H=function(){return\"TypeName\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.V:$K(W(),a)};f.D=function(a){return a instanceof Ep};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof Ep?this.V===a.V:!1};f.$l=function(a){return pa(this.V,a.V)};f.$classData=q({CY:0},!1,\"mlscript.TypeName\",{CY:1,Vz:1,Fi:1,ih:1,g:1,jh:1,Ta:1,Gi:1,JW:1,Kaa:1,yj:1,nf:1,IW:1,E:1,v:1,l:1});function YB(a,b,c,d,e){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.EO=this.dd=0;this.DO=null;this.pA=b;this.Ym=c;this.jZ=d;this.ME=e;pY(this,a);this.EO=a.Gd;this.DO=c.hi}YB.prototype=new P7;YB.prototype.constructor=YB;f=YB.prototype;f.ma=function(){return this.jZ};\nf.Ea=function(){return this.EO};f.ub=function(){return 0};f.u=function(){return this.pA?\"\\u22a5(\"+this.Ym+\")\":\"\\u22a4(\"+this.Ym+\")\"};f.H=function(){return\"Extruded\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.pA;case 1:return this.Ym;default:return $K(W(),a)}};f.D=function(a){return a instanceof YB};f.uo=function(){return this.DO};f.$classData=q({iZ:0},!1,\"mlscript.TyperDatatypes$Extruded\",{iZ:1,IE:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,uA:1,yj:1,nf:1,Hx:1,XO:1,E:1,v:1,l:1});\nfunction mx(a,b,c){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.Tu=this.dd=0;this.hi=b;this.et=c;pY(this,a);this.Tu=b.Xa}mx.prototype=new P7;mx.prototype.constructor=mx;f=mx.prototype;f.ma=function(){return this.et};f.ub=function(a,b){return this.hi.ub(a,b)};f.Ea=function(){return this.Tu};f.u=function(){var a=S7(this.hi),b=0<=a.length&&\"'\"===a.substring(0,1)?Of(Q(),a,1,a.length):a;a=Iu(Q(),a);return\"\\u2018\"+b+(Pe(new E(hc(a)),hc(39))?\"_\":\"\")+YC(this.q,this.Tu)};f.H=function(){return\"SkolemTag\"};\nf.G=function(){return 1};f.I=function(a){return 0===a?this.hi:$K(W(),a)};f.D=function(a){return a instanceof mx};f.uo=function(){return this.hi};f.$classData=q({zZ:0},!1,\"mlscript.TyperDatatypes$SkolemTag\",{zZ:1,IE:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,uA:1,yj:1,nf:1,Hx:1,XO:1,E:1,v:1,l:1});function nC(a,b,c,d){this.q=null;this.pe=this.Be=this.ze=0;this.oe=null;this.Ae=!1;this.dd=0;this.QO=null;this.II=!1;this.rp=b;this.JI=c;this.DZ=d;pY(this,a)}nC.prototype=new P7;nC.prototype.constructor=nC;f=nC.prototype;\nf.u=function(){return oY(this)};f.Fv=function(){this.II||this.II||(this.QO=nY(this),this.II=!0);return this.QO};f.AK=function(){return this.JI};f.ma=function(){return this.DZ};f.ub=function(){return this.q.Gd};f.Ea=function(){return this.q.Gd};f.H=function(){return\"TraitTag\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.rp;case 1:return this.JI;default:return $K(W(),a)}};f.D=function(a){return a instanceof nC};f.uo=function(){return this.rp};f.rr=function(){return this.rp};\nf.$classData=q({CZ:0},!1,\"mlscript.TyperDatatypes$TraitTag\",{CZ:1,IE:1,qp:1,Tg:1,Gg:1,g:1,Hg:1,Ug:1,uA:1,yj:1,nf:1,Hx:1,KO:1,E:1,v:1,l:1});function V8(){}V8.prototype=new B8;V8.prototype.constructor=V8;function W8(){}f=W8.prototype=V8.prototype;f.m=function(){return Kr(new Lr,this)};f.Sd=function(){return uZ(new vZ,this)};f.Qh=function(a){return o0(new p0,a,this)};f.Lh=function(a){return r0(new s0,this,a)};f.Jh=function(a){return X8(new Y8,this,a)};f.Oh=function(a){return u0(new v0,this,a)};\nf.Oc=function(){return\"IndexedSeqView\"};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ph=function(a){return this.Oh(a)};f.Ja=function(a){return this.Oh(a)};f.Kh=function(a){return this.Jh(a)};f.Bb=function(a){return this.Jh(a)};f.Mh=function(a){return this.Lh(a)};f.Jc=function(a){return this.Lh(a)};f.Rh=function(a){return this.Qh(a)};\nf.cc=function(a){return this.Qh(a)};function G8(a,b){if(null===b)throw null;a.Pv=b;return a}function H8(){this.Pv=null}H8.prototype=new u8;H8.prototype.constructor=H8;function $8(){}f=$8.prototype=H8.prototype;f.m=function(){return this.Pv.tj()};f.L=function(a){return this.Pv.L(a)};f.ka=function(){return this.Pv.ka()};f.Q=function(){return this.Pv.Q()};f.b=function(){return this.Pv.b()};\nf.$classData=q({WR:0},!1,\"scala.collection.MapOps$KeySet\",{WR:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,UB:1,sg:1,l:1});function KY(){}KY.prototype=new R8;KY.prototype.constructor=KY;f=KY.prototype;f.U=function(){return R()};f.m=function(){return Rq().Pa};f.Q=function(){return 0};f.b=function(){return!0};f.$classData=q({P5:0},!1,\"scala.collection.MapView$$anon$1\",{P5:1,zR:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,oL:1,ek:1,za:1,la:1});function qv(a){this.DG=a}qv.prototype=new R8;\nqv.prototype.constructor=qv;f=qv.prototype;f.U=function(a){return this.DG.U(a)};f.m=function(){return this.DG.m()};f.Q=function(){return this.DG.Q()};f.b=function(){return this.DG.b()};f.$classData=q({Q5:0},!1,\"scala.collection.MapView$Id\",{Q5:1,zR:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,oL:1,ek:1,za:1,la:1});function pv(a,b){this.EG=a;this.XR=b}pv.prototype=new R8;pv.prototype.constructor=pv;f=pv.prototype;f.m=function(){var a=this.EG.m();return new Ef(a,new y(b=>G(new H,b.h(),this.XR.n(b.j()))))};\nf.U=function(a){a=this.EG.U(a);var b=this.XR;return a.b()?R():new L(b.n(a.o()))};f.Q=function(){return this.EG.Q()};f.b=function(){return this.EG.b()};f.$classData=q({R5:0},!1,\"scala.collection.MapView$MapValues\",{R5:1,zR:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,oL:1,ek:1,za:1,la:1});\nfunction lY(a,b){if(a===b)return!0;if(b&&b.$classData&&b.$classData.rb.YB){var c=b.se(),d=a.se();if(null===c?null===d:c.i(d)){if(a.ka()===b.ka()){c=a.m();b=b.m();for(d=!0;d&&c.s();){d=c.t();var e=b.t();d=a.se().Yi(d.h(),e.h())&&ml(nl(),d.j(),e.j())}return d}return!1}}return v8(a,b)}function a9(){}a9.prototype=new u8;a9.prototype.constructor=a9;function b9(){}b9.prototype=a9.prototype;a9.prototype.Ub=function(){return Bq()};a9.prototype.wy=function(a){a=a.m();for(var b=this;a.s();){var c=a.t();b=b.Ek(c)}return b};\nfunction r0(a,b,c){b8(a,b,c);return a}function s0(){this.My=null;this.Tv=this.cC=0;this.Gy=null;this.KG=0}s0.prototype=new I8;s0.prototype.constructor=s0;function c9(){}f=c9.prototype=s0.prototype;f.m=function(){return Kr(new Lr,this)};f.Sd=function(){return uZ(new vZ,this)};f.Qh=function(a){return o0(new p0,a,this)};f.Lh=function(a){return r0(new s0,this,a)};f.Jh=function(a){return X8(new Y8,this,a)};f.Oh=function(a){return u0(new v0,this,a)};f.Oc=function(){return\"IndexedSeqView\"};\nf.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ph=function(a){return this.Oh(a)};f.Ja=function(a){return this.Oh(a)};f.Kh=function(a){return this.Jh(a)};f.Bb=function(a){return this.Jh(a)};f.Mh=function(a){return this.Lh(a)};f.Jc=function(a){return this.Lh(a)};f.Rh=function(a){return this.Qh(a)};f.cc=function(a){return this.Qh(a)};\nf.$classData=q({AR:0},!1,\"scala.collection.IndexedSeqView$Drop\",{AR:1,rL:1,UG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1});function X8(a,b,c){$7(a,b,c);return a}function Y8(){this.Ly=null;this.bC=this.aC=0;this.JG=null;this.Fy=0}Y8.prototype=new J8;Y8.prototype.constructor=Y8;function d9(){}f=d9.prototype=Y8.prototype;f.m=function(){return Kr(new Lr,this)};f.Sd=function(){return uZ(new vZ,this)};f.Qh=function(a){return o0(new p0,a,this)};\nf.Lh=function(a){return r0(new s0,this,a)};f.Jh=function(a){return X8(new Y8,this,a)};f.Oh=function(a){return u0(new v0,this,a)};f.Oc=function(){return\"IndexedSeqView\"};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.Fy;return b===a?0:b<a?-1:1};f.Q=function(){return this.Fy};f.Ph=function(a){return this.Oh(a)};f.Ja=function(a){return this.Oh(a)};f.Kh=function(a){return this.Jh(a)};\nf.Bb=function(a){return this.Jh(a)};f.Mh=function(a){return this.Lh(a)};f.Jc=function(a){return this.Lh(a)};f.Rh=function(a){return this.Qh(a)};f.cc=function(a){return this.Qh(a)};f.$classData=q({BR:0},!1,\"scala.collection.IndexedSeqView$DropRight\",{BR:1,sL:1,VG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1});function QX(a){this.Qv=null;bU(this,a)}QX.prototype=new K8;QX.prototype.constructor=QX;f=QX.prototype;f.m=function(){return Kr(new Lr,this)};\nf.Sd=function(){return uZ(new vZ,this)};f.Oc=function(){return\"IndexedSeqView\"};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ph=function(a){return u0(new v0,this,a)};f.Ja=function(a){return u0(new v0,this,a)};f.Kh=function(a){return X8(new Y8,this,a)};f.Bb=function(a){return X8(new Y8,this,a)};\nf.Mh=function(a){return r0(new s0,this,a)};f.Jc=function(a){return r0(new s0,this,a)};f.Rh=function(a){return o0(new p0,a,this)};f.cc=function(a){return o0(new p0,a,this)};f.$classData=q({Y4:0},!1,\"scala.collection.IndexedSeqView$Id\",{Y4:1,aS:1,QB:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1});function u0(a,b,c){f8(a,b,c);return a}function v0(){this.LG=this.VB=this.dC=this.Uv=null}v0.prototype=new L8;v0.prototype.constructor=v0;function e9(){}f=e9.prototype=v0.prototype;\nf.m=function(){return Kr(new Lr,this)};f.Sd=function(){return uZ(new vZ,this)};f.Qh=function(a){return o0(new p0,a,this)};f.Lh=function(a){return r0(new s0,this,a)};f.Jh=function(a){return X8(new Y8,this,a)};f.Oh=function(a){return u0(new v0,this,a)};f.Oc=function(){return\"IndexedSeqView\"};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};\nf.Ph=function(a){return this.Oh(a)};f.Ja=function(a){return this.Oh(a)};f.Kh=function(a){return this.Jh(a)};f.Bb=function(a){return this.Jh(a)};f.Mh=function(a){return this.Lh(a)};f.Jc=function(a){return this.Lh(a)};f.Rh=function(a){return this.Qh(a)};f.cc=function(a){return this.Qh(a)};f.$classData=q({ER:0},!1,\"scala.collection.IndexedSeqView$Map\",{ER:1,tL:1,WG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1});function o0(a,b,c){d8(a,b,c);return a}\nfunction p0(){this.WB=this.MG=this.Ny=this.eC=null}p0.prototype=new M8;p0.prototype.constructor=p0;function f9(){}f=f9.prototype=p0.prototype;f.m=function(){return Kr(new Lr,this)};f.Sd=function(){return uZ(new vZ,this)};f.Qh=function(a){return o0(new p0,a,this)};f.Lh=function(a){return r0(new s0,this,a)};f.Jh=function(a){return X8(new Y8,this,a)};f.Oh=function(a){return u0(new v0,this,a)};f.Oc=function(){return\"IndexedSeqView\"};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};\nf.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ph=function(a){return this.Oh(a)};f.Ja=function(a){return this.Oh(a)};f.Kh=function(a){return this.Jh(a)};f.Bb=function(a){return this.Jh(a)};f.Mh=function(a){return this.Lh(a)};f.Jc=function(a){return this.Lh(a)};f.Rh=function(a){return this.Qh(a)};f.cc=function(a){return this.Qh(a)};\nf.$classData=q({FR:0},!1,\"scala.collection.IndexedSeqView$Prepended\",{FR:1,uL:1,hS:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1});function Z8(a){this.Rv=a}Z8.prototype=new N8;Z8.prototype.constructor=Z8;f=Z8.prototype;f.m=function(){return Kr(new Lr,this)};f.Sd=function(){return uZ(new vZ,this)};f.Oc=function(){return\"IndexedSeqView\"};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};\nf.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ph=function(a){return u0(new v0,this,a)};f.Ja=function(a){return u0(new v0,this,a)};f.Kh=function(a){return X8(new Y8,this,a)};f.Bb=function(a){return X8(new Y8,this,a)};f.Mh=function(a){return r0(new s0,this,a)};f.Jc=function(a){return r0(new s0,this,a)};f.Rh=function(a){return o0(new p0,a,this)};f.cc=function(a){return o0(new p0,a,this)};\nf.$classData=q({Z4:0},!1,\"scala.collection.IndexedSeqView$Reverse\",{Z4:1,bS:1,QB:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1});function g9(a){this.Tp=null;if(null===a)throw null;this.Tp=a}g9.prototype=new p;g9.prototype.constructor=g9;f=g9.prototype;f.se=function(){return this.Tp.se()};f.m=function(){return this.Tp.tj()};f.L=function(a){return this.Tp.L(a)};f.ka=function(){return this.Tp.ka()};f.Q=function(){return this.Tp.Q()};f.b=function(){return this.Tp.b()};\nf.i=function(a){return O8(this,a)};f.aj=function(a){return u5(this,a)};f.$i=function(a){return v5(this,a)};f.D=function(){return!0};f.B=function(){var a=BL();return CL(a,this,a.PB)};f.Ub=function(){return WY()};f.u=function(){return w0(this)};f.fM=function(a){return nw(this,a)};f.Ce=function(a){return J0(this,a)};f.Ih=function(){return\"SortedSet\"};f.e=function(){return this.Tp.tj().t()};f.Mc=function(){return yT(this)};f.$k=function(a){return iv(this,a)};f.Jc=function(a){return zT(this,a)};\nf.Bb=function(a){return this.vc(s3(new t3,this,a))};f.Ja=function(a){return FT(this,a)};f.tl=function(a){return IT(this,a)};f.Gb=function(a){return KT(this,a)};f.Ca=function(a){cH(this,a)};f.De=function(a,b){return mB(this,a,b)};f.mf=function(a,b){return Qu(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};f.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};\nf.Bj=function(a){return kB(this,a)};f.ad=function(){return er(this)};f.n=function(a){return this.Tp.L(a)};f.vc=function(a){D3||(D3=new C3);return D3.pr(a,this.Tp.se())};f.$classData=q({d6:0},!1,\"scala.collection.SortedMapOps$KeySortedSet\",{d6:1,g:1,PG:1,fk:1,na:1,M:1,pa:1,N:1,oa:1,Cl:1,la:1,v:1,fS:1,Iy:1,eS:1,UB:1,c6:1});function h9(){}h9.prototype=new z8;h9.prototype.constructor=h9;function i9(){}i9.prototype=h9.prototype;h9.prototype.FC=function(){return this};\nfunction j9(a,b){this.LS=a;this.bz=b}j9.prototype=new W8;j9.prototype.constructor=j9;f=j9.prototype;f.va=function(a){return this.LS.va(a)};f.K=function(){return this.LS.Zg};f.Ih=function(){return\"ArrayBufferView\"};f.m=function(){return new E5(this,this.bz)};f.Sd=function(){return new F5(this,this.bz)};f.Qh=function(a){return new k9(a,this,this.bz)};f.Lh=function(a){return new l9(this,a,this.bz)};f.Jh=function(a){return new m9(this,a,this.bz)};f.Oh=function(a){return new n9(this,a,this.bz)};f.Ph=function(a){return this.Oh(a)};\nf.Ja=function(a){return this.Oh(a)};f.Kh=function(a){return this.Jh(a)};f.Bb=function(a){return this.Jh(a)};f.Mh=function(a){return this.Lh(a)};f.Jc=function(a){return this.Lh(a)};f.Rh=function(a){return this.Qh(a)};f.cc=function(a){return this.Qh(a)};f.$classData=q({f9:0},!1,\"scala.collection.mutable.ArrayBufferView\",{f9:1,x4:1,QB:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1});function o9(a){this.Pv=null;G8(this,a)}o9.prototype=new $8;o9.prototype.constructor=o9;\no9.prototype.Ub=function(){return KB()};o9.prototype.$classData=q({f$:0},!1,\"scala.collection.mutable.LinkedHashMap$LinkedKeySet\",{f$:1,WR:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,UB:1,sg:1,l:1});function p9(){}p9.prototype=new F8;p9.prototype.constructor=p9;function q9(){}f=q9.prototype=p9.prototype;f.vj=function(){return qp()};f.Ti=function(){return this};f.jM=function(a){return $X(this,a)};f.dG=function(a){return x5(this,a)};f.IC=function(a,b){return y5(this,a,b)};\nf.Pn=function(a){return this.Em(a.h(),a.j())};f.Ht=function(){return r9(new s9,this)};f.Ub=function(){return DY()};f.zr=function(){return this.Ht()};function t9(a,b){return V0(b)?a.K()===b.K():!0}\nfunction u9(a,b){if(V0(b)){if(a===b)return!0;var c=a.K(),d=c===b.K();if(d){var e=0,g=a.dy(),h=b.dy();g=g<h?g:h;h=c>>31;var k=g>>>31|0|g>>31<<1;for(g=(h===k?(-2147483648^c)>(-2147483648^g<<1):h>k)?g:c;e<g&&d;)d=ml(nl(),a.va(e),b.va(e)),e=1+e|0;if(e<c&&d)for(a=a.m().ph(e),b=b.m().ph(e);d&&a.s();)d=ml(nl(),a.t(),b.t())}return d}return TY(a,b)}function V0(a){return!!(a&&a.$classData&&a.$classData.rb.Sh)}function v9(){}v9.prototype=new b9;v9.prototype.constructor=v9;f=v9.prototype;f.ka=function(){return 0};\nf.b=function(){return!0};f.Q=function(){return 0};f.fM=function(){return!0};f.L=function(){return!1};f.m=function(){return Rq().Pa};f.Ca=function(){};f.Ek=function(){return this};f.bc=function(a){return new w9(a)};f.wy=function(){return this};f.$classData=q({k8:0},!1,\"scala.collection.immutable.Set$EmptySet$\",{k8:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,l:1});var x9;function ap(){x9||(x9=new v9);return x9}function Mr(a){this.Ky=a}Mr.prototype=new W8;\nMr.prototype.constructor=Mr;f=Mr.prototype;f.K=function(){return this.Ky.length};f.u=function(){return\"StringView(\"+this.Ky+\")\"};f.H=function(){return\"StringView\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Ky:$K(W(),a)};f.D=function(a){return a instanceof Mr};f.B=function(){return AL(this)};f.i=function(a){return this===a?!0:a instanceof Mr?this.Ky===a.Ky:!1};f.va=function(a){return hc(this.Ky.charCodeAt(a))};\nf.$classData=q({q6:0},!1,\"scala.collection.StringView\",{q6:1,x4:1,QB:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1,E:1,v:1});function w9(a){this.iw=a}w9.prototype=new b9;w9.prototype.constructor=w9;f=w9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 1};f.b=function(){return!1};f.Q=function(){return 1};f.L=function(a){return ml(nl(),a,this.iw)};\nf.vo=function(a){return this.L(a)?this:new y9(this.iw,a)};f.po=function(a){return ml(nl(),a,this.iw)?ap():this};f.m=function(){Rq();return new g0(this.iw)};f.Ca=function(a){a.n(this.iw)};f.ul=function(a){return!!a.n(this.iw)};f.e=function(){return this.iw};f.Ek=function(a){return this.po(a)};f.bc=function(a){return this.vo(a)};f.$classData=q({l8:0},!1,\"scala.collection.immutable.Set$Set1\",{l8:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,Cb:1,l:1});\nfunction y9(a,b){this.Zt=a;this.jw=b}y9.prototype=new b9;y9.prototype.constructor=y9;f=y9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 2};f.b=function(){return!1};f.Q=function(){return 2};f.L=function(a){return ml(nl(),a,this.Zt)||ml(nl(),a,this.jw)};f.vo=function(a){return this.L(a)?this:new z9(this.Zt,this.jw,a)};\nf.po=function(a){return ml(nl(),a,this.Zt)?new w9(this.jw):ml(nl(),a,this.jw)?new w9(this.Zt):this};f.m=function(){return new z5(this)};f.Ca=function(a){a.n(this.Zt);a.n(this.jw)};f.ul=function(a){return!!a.n(this.Zt)&&!!a.n(this.jw)};f.e=function(){return this.Zt};f.Ek=function(a){return this.po(a)};f.bc=function(a){return this.vo(a)};f.$classData=q({m8:0},!1,\"scala.collection.immutable.Set$Set2\",{m8:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,Cb:1,l:1});\nfunction z9(a,b,c){this.Qr=a;this.$t=b;this.au=c}z9.prototype=new b9;z9.prototype.constructor=z9;f=z9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 3};f.b=function(){return!1};f.Q=function(){return 3};f.L=function(a){return ml(nl(),a,this.Qr)||ml(nl(),a,this.$t)||ml(nl(),a,this.au)};f.vo=function(a){return this.L(a)?this:new A9(this.Qr,this.$t,this.au,a)};\nf.po=function(a){return ml(nl(),a,this.Qr)?new y9(this.$t,this.au):ml(nl(),a,this.$t)?new y9(this.Qr,this.au):ml(nl(),a,this.au)?new y9(this.Qr,this.$t):this};f.m=function(){return new A5(this)};f.Ca=function(a){a.n(this.Qr);a.n(this.$t);a.n(this.au)};f.ul=function(a){return!!a.n(this.Qr)&&!!a.n(this.$t)&&!!a.n(this.au)};f.e=function(){return this.Qr};f.Ek=function(a){return this.po(a)};f.bc=function(a){return this.vo(a)};\nf.$classData=q({o8:0},!1,\"scala.collection.immutable.Set$Set3\",{o8:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,Cb:1,l:1});function A9(a,b,c,d){this.Ho=a;this.eq=b;this.fq=c;this.gq=d}A9.prototype=new b9;A9.prototype.constructor=A9;f=A9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 4};f.b=function(){return!1};f.Q=function(){return 4};\nf.L=function(a){return ml(nl(),a,this.Ho)||ml(nl(),a,this.eq)||ml(nl(),a,this.fq)||ml(nl(),a,this.gq)};f.vo=function(a){return this.L(a)?this:B9(B9(B9(B9(B9(dV().Fo,this.Ho),this.eq),this.fq),this.gq),a)};f.po=function(a){return ml(nl(),a,this.Ho)?new z9(this.eq,this.fq,this.gq):ml(nl(),a,this.eq)?new z9(this.Ho,this.fq,this.gq):ml(nl(),a,this.fq)?new z9(this.Ho,this.eq,this.gq):ml(nl(),a,this.gq)?new z9(this.Ho,this.eq,this.fq):this};f.m=function(){return new B5(this)};\nfunction Gfa(a,b){switch(b){case 0:return a.Ho;case 1:return a.eq;case 2:return a.fq;case 3:return a.gq;default:throw new w(b);}}f.Ca=function(a){a.n(this.Ho);a.n(this.eq);a.n(this.fq);a.n(this.gq)};f.ul=function(a){return!!a.n(this.Ho)&&!!a.n(this.eq)&&!!a.n(this.fq)&&!!a.n(this.gq)};f.e=function(){return this.Ho};f.Ek=function(a){return this.po(a)};f.bc=function(a){return this.vo(a)};\nf.$classData=q({q8:0},!1,\"scala.collection.immutable.Set$Set4\",{q8:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,Cb:1,l:1});function C9(){}C9.prototype=new z8;C9.prototype.constructor=C9;function D9(){}D9.prototype=C9.prototype;C9.prototype.ia=function(){var a=this.ti();a.zc(this);return a.Kb()};function l9(a,b,c){this.My=null;this.Tv=this.cC=0;this.Gy=null;this.KG=0;this.Il=c;r0(this,a,b)}l9.prototype=new c9;l9.prototype.constructor=l9;f=l9.prototype;\nf.m=function(){return new E5(this,this.Il)};f.Sd=function(){return new F5(this,this.Il)};f.Qh=function(a){return new k9(a,this,this.Il)};f.Lh=function(a){return new l9(this,a,this.Il)};f.Jh=function(a){return new m9(this,a,this.Il)};f.Oh=function(a){return new n9(this,a,this.Il)};f.Ph=function(a){return new n9(this,a,this.Il)};f.Ja=function(a){return new n9(this,a,this.Il)};f.Kh=function(a){return new m9(this,a,this.Il)};f.Bb=function(a){return new m9(this,a,this.Il)};\nf.Mh=function(a){return new l9(this,a,this.Il)};f.Jc=function(a){return new l9(this,a,this.Il)};f.Rh=function(a){return new k9(a,this,this.Il)};f.cc=function(a){return new k9(a,this,this.Il)};f.$classData=q({A9:0},!1,\"scala.collection.mutable.CheckedIndexedSeqView$Drop\",{A9:1,AR:1,rL:1,UG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1,UL:1});function m9(a,b,c){this.Ly=null;this.bC=this.aC=0;this.JG=null;this.Fy=0;this.Hl=c;X8(this,a,b)}m9.prototype=new d9;\nm9.prototype.constructor=m9;f=m9.prototype;f.m=function(){return new E5(this,this.Hl)};f.Sd=function(){return new F5(this,this.Hl)};f.Qh=function(a){return new k9(a,this,this.Hl)};f.Lh=function(a){return new l9(this,a,this.Hl)};f.Jh=function(a){return new m9(this,a,this.Hl)};f.Oh=function(a){return new n9(this,a,this.Hl)};f.Ph=function(a){return new n9(this,a,this.Hl)};f.Ja=function(a){return new n9(this,a,this.Hl)};f.Kh=function(a){return new m9(this,a,this.Hl)};\nf.Bb=function(a){return new m9(this,a,this.Hl)};f.Mh=function(a){return new l9(this,a,this.Hl)};f.Jc=function(a){return new l9(this,a,this.Hl)};f.Rh=function(a){return new k9(a,this,this.Hl)};f.cc=function(a){return new k9(a,this,this.Hl)};f.$classData=q({B9:0},!1,\"scala.collection.mutable.CheckedIndexedSeqView$DropRight\",{B9:1,BR:1,sL:1,VG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1,UL:1});function n9(a,b,c){this.LG=this.VB=this.dC=this.Uv=null;this.Jl=c;u0(this,a,b)}\nn9.prototype=new e9;n9.prototype.constructor=n9;f=n9.prototype;f.m=function(){return new E5(this,this.Jl)};f.Sd=function(){return new F5(this,this.Jl)};f.Qh=function(a){return new k9(a,this,this.Jl)};f.Lh=function(a){return new l9(this,a,this.Jl)};f.Jh=function(a){return new m9(this,a,this.Jl)};f.Oh=function(a){return new n9(this,a,this.Jl)};f.Ph=function(a){return new n9(this,a,this.Jl)};f.Ja=function(a){return new n9(this,a,this.Jl)};f.Kh=function(a){return new m9(this,a,this.Jl)};\nf.Bb=function(a){return new m9(this,a,this.Jl)};f.Mh=function(a){return new l9(this,a,this.Jl)};f.Jc=function(a){return new l9(this,a,this.Jl)};f.Rh=function(a){return new k9(a,this,this.Jl)};f.cc=function(a){return new k9(a,this,this.Jl)};f.$classData=q({C9:0},!1,\"scala.collection.mutable.CheckedIndexedSeqView$Map\",{C9:1,ER:1,tL:1,WG:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1,UL:1});function k9(a,b,c){this.WB=this.MG=this.Ny=this.eC=null;this.Kl=c;o0(this,a,b)}\nk9.prototype=new f9;k9.prototype.constructor=k9;f=k9.prototype;f.m=function(){return new E5(this,this.Kl)};f.Sd=function(){return new F5(this,this.Kl)};f.Qh=function(a){return new k9(a,this,this.Kl)};f.Lh=function(a){return new l9(this,a,this.Kl)};f.Jh=function(a){return new m9(this,a,this.Kl)};f.Oh=function(a){return new n9(this,a,this.Kl)};f.Ph=function(a){return new n9(this,a,this.Kl)};f.Ja=function(a){return new n9(this,a,this.Kl)};f.Kh=function(a){return new m9(this,a,this.Kl)};\nf.Bb=function(a){return new m9(this,a,this.Kl)};f.Mh=function(a){return new l9(this,a,this.Kl)};f.Jc=function(a){return new l9(this,a,this.Kl)};f.Rh=function(a){return new k9(a,this,this.Kl)};f.cc=function(a){return new k9(a,this,this.Kl)};f.$classData=q({D9:0},!1,\"scala.collection.mutable.CheckedIndexedSeqView$Prepended\",{D9:1,FR:1,uL:1,hS:1,Td:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,jd:1,l:1,Li:1,kb:1,Ao:1,Vb:1,UL:1});\nfunction Fm(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Dh=null;this.uu=a;C8(this)}Fm.prototype=new U8;Fm.prototype.constructor=Fm;f=Fm.prototype;f.H=function(){return\"DecLit\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.uu:$K(W(),a)};f.D=function(a){return a instanceof Fm};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){if(this===a)return!0;if(a instanceof Fm){var b=this.uu;a=a.uu;return null===b?null===a:b.i(a)}return!1};f.$classData=q({EU:0},!1,\"mlscript.DecLit\",{EU:1,EH:1,CE:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,tz:1,DE:1,yj:1,nf:1,FH:1,E:1,v:1,l:1});function Em(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Dh=null;this.rq=a;C8(this)}Em.prototype=new U8;Em.prototype.constructor=Em;f=Em.prototype;f.H=function(){return\"IntLit\"};f.G=function(){return 1};\nf.I=function(a){return 0===a?this.rq:$K(W(),a)};f.D=function(a){return a instanceof Em};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){if(this===a)return!0;if(a instanceof Em){var b=this.rq;a=a.rq;return null===b?null===a:b.i(a)}return!1};f.$classData=q({gV:0},!1,\"mlscript.IntLit\",{gV:1,EH:1,CE:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,tz:1,DE:1,yj:1,nf:1,FH:1,E:1,v:1,l:1});\nfunction Dm(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Dh=null;this.Lu=a;C8(this)}Dm.prototype=new U8;Dm.prototype.constructor=Dm;f=Dm.prototype;f.H=function(){return\"StrLit\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Lu:$K(W(),a)};f.D=function(a){return a instanceof Dm};f.B=function(){return AL(this)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof Dm?this.Lu===a.Lu:!1};\nf.$classData=q({mY:0},!1,\"mlscript.StrLit\",{mY:1,EH:1,CE:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,tz:1,DE:1,yj:1,nf:1,FH:1,E:1,v:1,l:1});function Gm(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.Dh=null;this.Xq=a;C8(this)}Gm.prototype=new U8;Gm.prototype.constructor=Gm;f=Gm.prototype;f.H=function(){return\"UnitLit\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.Xq:$K(W(),a)};f.D=function(a){return a instanceof Gm};\nf.B=function(){var a=lb(\"UnitLit\");a=W().C(-889275714,a);var b=this.Xq?1231:1237;a=W().C(a,b);return W().Ma(a,1)};f.u=function(){return VK(this)};f.i=function(a){return this===a?!0:a instanceof Gm?this.Xq===a.Xq:!1};f.$classData=q({b_:0},!1,\"mlscript.UnitLit\",{b_:1,EH:1,CE:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,tz:1,DE:1,yj:1,nf:1,FH:1,E:1,v:1,l:1});\nfunction vl(a){this.zd=this.yd=this.nd=this.oc=null;this.Bd=this.Cd=0;this.Dd=this.Ad=null;this.gc=0;this.kt=this.Dh=null;this.x=a;C8(this);this.kt=t().d}vl.prototype=new D8;vl.prototype.constructor=vl;f=vl.prototype;f.Zr=function(){return this};f.Ua=function(){return this.x};f.H=function(){return\"Var\"};f.G=function(){return 1};f.I=function(a){return 0===a?this.x:$K(W(),a)};f.D=function(a){return a instanceof vl};f.B=function(){return AL(this)};f.u=function(){return VK(this)};\nf.i=function(a){return this===a?!0:a instanceof vl?this.x===a.x:!1};f.$classData=q({e_:0},!1,\"mlscript.Var\",{e_:1,CE:1,Oe:1,g:1,ce:1,ud:1,md:1,xd:1,Ta:1,Od:1,Pe:1,tz:1,DE:1,yj:1,nf:1,Uaa:1,IW:1,E:1,v:1,l:1});function E9(){}E9.prototype=new q9;E9.prototype.constructor=E9;f=E9.prototype;f.ka=function(){return 0};f.Q=function(){return 0};f.b=function(){return!0};f.AJ=function(a){throw AH(\"key not found: \"+a);};f.L=function(){return!1};f.U=function(){return R()};f.Se=function(a,b){return Es(b)};f.m=function(){return Rq().Pa};\nf.tj=function(){return Rq().Pa};f.ie=function(){return Rq().Pa};f.am=function(a){return jV(a)?a:A3(this,a)};f.xj=function(){return this};f.Em=function(a,b){return new F9(a,b)};f.n=function(a){this.AJ(a)};f.$classData=q({v7:0},!1,\"scala.collection.immutable.Map$EmptyMap$\",{v7:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,l:1});var G9;function nf(){G9||(G9=new E9);return G9}function S8(a,b,c){a.Qi=b;a.An=c;return a}function T8(){this.An=this.Qi=null}\nT8.prototype=new q9;T8.prototype.constructor=T8;function H9(){}f=H9.prototype=T8.prototype;f.U=function(a){return this.Qi.U(a)};f.IF=function(a){return this.An.n(a)};f.Ub=function(){return this.Qi.Ub()};f.m=function(){return this.Qi.m()};f.b=function(){return this.Qi.b()};f.vj=function(){return this.Qi.vj()};f.gQ=function(a){return S8(new T8,this.Qi.am(a),this.An)};f.iR=function(a){return S8(new T8,this.Qi.xj(a),this.An)};f.sT=function(a,b){return S8(new T8,this.Qi.Em(a,b),this.An)};\nf.IJ=function(a){return S8(new T8,this.Qi.vj().Ib(a),this.An)};f.vc=function(a){return this.IJ(a)};f.Gk=function(a){return this.IJ(a)};f.Em=function(a,b){return this.sT(a,b)};f.xj=function(a){return this.iR(a)};f.am=function(a){return this.gQ(a)};f.$classData=q({tS:0},!1,\"scala.collection.immutable.Map$WithDefault\",{tS:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,l:1});function r9(a,b){if(null===b)throw null;a.wm=b;return a}function s9(){this.wm=null}\ns9.prototype=new b9;s9.prototype.constructor=s9;function I9(){}f=I9.prototype=s9.prototype;f.m=function(){return this.wm.tj()};f.L=function(a){return this.wm.L(a)};f.ka=function(){return this.wm.ka()};f.Q=function(){return this.wm.Q()};f.b=function(){return this.wm.b()};f.vo=function(a){if(this.wm.L(a))return this;var b=ap();return J0(b,this).bc(a)};f.po=function(a){if(this.wm.L(a)){var b=ap();return J0(b,this).Ek(a)}return this};f.Ek=function(a){return this.po(a)};f.bc=function(a){return this.vo(a)};\nf.$classData=q({vS:0},!1,\"scala.collection.immutable.MapOps$ImmutableKeySet\",{vS:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,UB:1,sg:1,l:1});function J9(a){this.wm=null;r9(this,a)}J9.prototype=new I9;J9.prototype.constructor=J9;f=J9.prototype;f.vo=function(a){var b=My(W(),a),c=$G(bH(),b);a=iU(this.wm.dc,a,null,b,c,0,!1);return a===this.wm.dc?this:(new TU(a)).Ht()};f.po=function(a){a=K9(this.wm,a);return a===this.wm?this:a.Ht()};f.Ek=function(a){return this.po(a)};\nf.bc=function(a){return this.vo(a)};f.$classData=q({X6:0},!1,\"scala.collection.immutable.HashMap$HashKeySet\",{X6:1,vS:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,UB:1,sg:1,l:1});function F9(a,b){this.El=a;this.Xp=b}F9.prototype=new q9;F9.prototype.constructor=F9;f=F9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){return this.ov(a,!1)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 1};f.Q=function(){return 1};\nf.b=function(){return!1};f.n=function(a){if(ml(nl(),a,this.El))return this.Xp;throw AH(\"key not found: \"+a);};f.L=function(a){return ml(nl(),a,this.El)};f.U=function(a){return ml(nl(),a,this.El)?new L(this.Xp):R()};f.Se=function(a,b){return ml(nl(),a,this.El)?this.Xp:Es(b)};f.m=function(){Rq();var a=G(new H,this.El,this.Xp);return new g0(a)};f.tj=function(){Rq();return new g0(this.El)};f.ie=function(){Rq();return new g0(this.Xp)};\nf.Dm=function(a,b){return ml(nl(),a,this.El)?new F9(this.El,b):new L9(this.El,this.Xp,a,b)};f.Gv=function(a){return ml(nl(),a,this.El)?nf():this};f.Ca=function(a){a.n(G(new H,this.El,this.Xp))};f.ul=function(a){return!!a.n(G(new H,this.El,this.Xp))};f.ov=function(a,b){return!!a.n(G(new H,this.El,this.Xp))!==b?this:nf()};f.B=function(){var a=0,b=0,c=1,d=pS(BL(),this.El,this.Xp);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=BL().Cr;d=BL().C(d,a);d=BL().C(d,b);d=BL().Pp(d,c);return BL().Ma(d,1)};f.xj=function(a){return this.Gv(a)};\nf.Em=function(a,b){return this.Dm(a,b)};f.$classData=q({w7:0},!1,\"scala.collection.immutable.Map$Map1\",{w7:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,Cb:1,l:1});function L9(a,b,c,d){this.hk=a;this.xn=b;this.ik=c;this.yn=d}L9.prototype=new q9;L9.prototype.constructor=L9;f=L9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){return this.ov(a,!1)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 2};\nf.Q=function(){return 2};f.b=function(){return!1};f.n=function(a){if(ml(nl(),a,this.hk))return this.xn;if(ml(nl(),a,this.ik))return this.yn;throw AH(\"key not found: \"+a);};f.L=function(a){return ml(nl(),a,this.hk)||ml(nl(),a,this.ik)};f.U=function(a){return ml(nl(),a,this.hk)?new L(this.xn):ml(nl(),a,this.ik)?new L(this.yn):R()};f.Se=function(a,b){return ml(nl(),a,this.hk)?this.xn:ml(nl(),a,this.ik)?this.yn:Es(b)};f.m=function(){return new U3(this)};f.tj=function(){return new V3(this)};f.ie=function(){return new W3(this)};\nf.Dm=function(a,b){return ml(nl(),a,this.hk)?new L9(this.hk,b,this.ik,this.yn):ml(nl(),a,this.ik)?new L9(this.hk,this.xn,this.ik,b):new M9(this.hk,this.xn,this.ik,this.yn,a,b)};f.Gv=function(a){return ml(nl(),a,this.hk)?new F9(this.ik,this.yn):ml(nl(),a,this.ik)?new F9(this.hk,this.xn):this};f.Ca=function(a){a.n(G(new H,this.hk,this.xn));a.n(G(new H,this.ik,this.yn))};f.ul=function(a){return!!a.n(G(new H,this.hk,this.xn))&&!!a.n(G(new H,this.ik,this.yn))};\nf.ov=function(a,b){var c=null,d=null,e=0;!!a.n(G(new H,this.hk,this.xn))!==b&&(c=this.hk,d=this.xn,e=1+e|0);!!a.n(G(new H,this.ik,this.yn))!==b&&(0===e&&(c=this.ik,d=this.yn),e=1+e|0);a=e;switch(a){case 0:return nf();case 1:return new F9(c,d);case 2:return this;default:throw new w(a);}};\nf.B=function(){var a=0,b=0,c=1,d=pS(BL(),this.hk,this.xn);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=pS(BL(),this.ik,this.yn);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=BL().Cr;d=BL().C(d,a);d=BL().C(d,b);d=BL().Pp(d,c);return BL().Ma(d,2)};f.xj=function(a){return this.Gv(a)};f.Em=function(a,b){return this.Dm(a,b)};f.$classData=q({x7:0},!1,\"scala.collection.immutable.Map$Map2\",{x7:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,Cb:1,l:1});\nfunction M9(a,b,c,d,e,g){this.dj=a;this.Fl=b;this.Mi=c;this.Qk=d;this.Ni=e;this.Rk=g}M9.prototype=new q9;M9.prototype.constructor=M9;f=M9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){return this.ov(a,!1)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 3};f.Q=function(){return 3};f.b=function(){return!1};\nf.n=function(a){if(ml(nl(),a,this.dj))return this.Fl;if(ml(nl(),a,this.Mi))return this.Qk;if(ml(nl(),a,this.Ni))return this.Rk;throw AH(\"key not found: \"+a);};f.L=function(a){return ml(nl(),a,this.dj)||ml(nl(),a,this.Mi)||ml(nl(),a,this.Ni)};f.U=function(a){return ml(nl(),a,this.dj)?new L(this.Fl):ml(nl(),a,this.Mi)?new L(this.Qk):ml(nl(),a,this.Ni)?new L(this.Rk):R()};f.Se=function(a,b){return ml(nl(),a,this.dj)?this.Fl:ml(nl(),a,this.Mi)?this.Qk:ml(nl(),a,this.Ni)?this.Rk:Es(b)};f.m=function(){return new X3(this)};\nf.tj=function(){return new Y3(this)};f.ie=function(){return new Z3(this)};f.Dm=function(a,b){return ml(nl(),a,this.dj)?new M9(this.dj,b,this.Mi,this.Qk,this.Ni,this.Rk):ml(nl(),a,this.Mi)?new M9(this.dj,this.Fl,this.Mi,b,this.Ni,this.Rk):ml(nl(),a,this.Ni)?new M9(this.dj,this.Fl,this.Mi,this.Qk,this.Ni,b):new N9(this.dj,this.Fl,this.Mi,this.Qk,this.Ni,this.Rk,a,b)};\nf.Gv=function(a){return ml(nl(),a,this.dj)?new L9(this.Mi,this.Qk,this.Ni,this.Rk):ml(nl(),a,this.Mi)?new L9(this.dj,this.Fl,this.Ni,this.Rk):ml(nl(),a,this.Ni)?new L9(this.dj,this.Fl,this.Mi,this.Qk):this};f.Ca=function(a){a.n(G(new H,this.dj,this.Fl));a.n(G(new H,this.Mi,this.Qk));a.n(G(new H,this.Ni,this.Rk))};f.ul=function(a){return!!a.n(G(new H,this.dj,this.Fl))&&!!a.n(G(new H,this.Mi,this.Qk))&&!!a.n(G(new H,this.Ni,this.Rk))};\nf.ov=function(a,b){var c=null,d=null,e=null,g=null,h=0;!!a.n(G(new H,this.dj,this.Fl))!==b&&(c=this.dj,e=this.Fl,h=1+h|0);!!a.n(G(new H,this.Mi,this.Qk))!==b&&(0===h?(c=this.Mi,e=this.Qk):(d=this.Mi,g=this.Qk),h=1+h|0);!!a.n(G(new H,this.Ni,this.Rk))!==b&&(0===h?(c=this.Ni,e=this.Rk):1===h&&(d=this.Ni,g=this.Rk),h=1+h|0);a=h;switch(a){case 0:return nf();case 1:return new F9(c,e);case 2:return new L9(c,e,d,g);case 3:return this;default:throw new w(a);}};\nf.B=function(){var a=0,b=0,c=1,d=pS(BL(),this.dj,this.Fl);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=pS(BL(),this.Mi,this.Qk);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=pS(BL(),this.Ni,this.Rk);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=BL().Cr;d=BL().C(d,a);d=BL().C(d,b);d=BL().Pp(d,c);return BL().Ma(d,3)};f.xj=function(a){return this.Gv(a)};f.Em=function(a,b){return this.Dm(a,b)};\nf.$classData=q({B7:0},!1,\"scala.collection.immutable.Map$Map3\",{B7:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,Cb:1,l:1});function N9(a,b,c,d,e,g,h,k){this.Th=a;this.Aj=b;this.xh=c;this.ej=d;this.Wg=e;this.Oi=g;this.Xg=h;this.Pi=k}N9.prototype=new q9;N9.prototype.constructor=N9;f=N9.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){return this.ov(a,!1)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return 4};\nf.Q=function(){return 4};f.b=function(){return!1};f.n=function(a){if(ml(nl(),a,this.Th))return this.Aj;if(ml(nl(),a,this.xh))return this.ej;if(ml(nl(),a,this.Wg))return this.Oi;if(ml(nl(),a,this.Xg))return this.Pi;throw AH(\"key not found: \"+a);};f.L=function(a){return ml(nl(),a,this.Th)||ml(nl(),a,this.xh)||ml(nl(),a,this.Wg)||ml(nl(),a,this.Xg)};\nf.U=function(a){return ml(nl(),a,this.Th)?new L(this.Aj):ml(nl(),a,this.xh)?new L(this.ej):ml(nl(),a,this.Wg)?new L(this.Oi):ml(nl(),a,this.Xg)?new L(this.Pi):R()};f.Se=function(a,b){return ml(nl(),a,this.Th)?this.Aj:ml(nl(),a,this.xh)?this.ej:ml(nl(),a,this.Wg)?this.Oi:ml(nl(),a,this.Xg)?this.Pi:Es(b)};f.m=function(){return new $3(this)};f.tj=function(){return new a4(this)};f.ie=function(){return new b4(this)};\nf.Dm=function(a,b){return ml(nl(),a,this.Th)?new N9(this.Th,b,this.xh,this.ej,this.Wg,this.Oi,this.Xg,this.Pi):ml(nl(),a,this.xh)?new N9(this.Th,this.Aj,this.xh,b,this.Wg,this.Oi,this.Xg,this.Pi):ml(nl(),a,this.Wg)?new N9(this.Th,this.Aj,this.xh,this.ej,this.Wg,b,this.Xg,this.Pi):ml(nl(),a,this.Xg)?new N9(this.Th,this.Aj,this.xh,this.ej,this.Wg,this.Oi,this.Xg,b):m7(m7(m7(m7(m7(Ez().Mr,this.Th,this.Aj),this.xh,this.ej),this.Wg,this.Oi),this.Xg,this.Pi),a,b)};\nf.Gv=function(a){return ml(nl(),a,this.Th)?new M9(this.xh,this.ej,this.Wg,this.Oi,this.Xg,this.Pi):ml(nl(),a,this.xh)?new M9(this.Th,this.Aj,this.Wg,this.Oi,this.Xg,this.Pi):ml(nl(),a,this.Wg)?new M9(this.Th,this.Aj,this.xh,this.ej,this.Xg,this.Pi):ml(nl(),a,this.Xg)?new M9(this.Th,this.Aj,this.xh,this.ej,this.Wg,this.Oi):this};f.Ca=function(a){a.n(G(new H,this.Th,this.Aj));a.n(G(new H,this.xh,this.ej));a.n(G(new H,this.Wg,this.Oi));a.n(G(new H,this.Xg,this.Pi))};\nf.ul=function(a){return!!a.n(G(new H,this.Th,this.Aj))&&!!a.n(G(new H,this.xh,this.ej))&&!!a.n(G(new H,this.Wg,this.Oi))&&!!a.n(G(new H,this.Xg,this.Pi))};\nf.ov=function(a,b){var c=null,d=null,e=null,g=null,h=null,k=null,l=0;!!a.n(G(new H,this.Th,this.Aj))!==b&&(c=this.Th,g=this.Aj,l=1+l|0);!!a.n(G(new H,this.xh,this.ej))!==b&&(0===l?(c=this.xh,g=this.ej):(d=this.xh,h=this.ej),l=1+l|0);!!a.n(G(new H,this.Wg,this.Oi))!==b&&(0===l?(c=this.Wg,g=this.Oi):1===l?(d=this.Wg,h=this.Oi):(e=this.Wg,k=this.Oi),l=1+l|0);!!a.n(G(new H,this.Xg,this.Pi))!==b&&(0===l?(c=this.Xg,g=this.Pi):1===l?(d=this.Xg,h=this.Pi):2===l&&(e=this.Xg,k=this.Pi),l=1+l|0);a=l;switch(a){case 0:return nf();\ncase 1:return new F9(c,g);case 2:return new L9(c,g,d,h);case 3:return new M9(c,g,d,h,e,k);case 4:return this;default:throw new w(a);}};f.B=function(){var a=0,b=0,c=1,d=pS(BL(),this.Th,this.Aj);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=pS(BL(),this.xh,this.ej);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=pS(BL(),this.Wg,this.Oi);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=pS(BL(),this.Xg,this.Pi);a=a+d|0;b^=d;c=Math.imul(c,1|d);d=BL().Cr;d=BL().C(d,a);d=BL().C(d,b);d=BL().Pp(d,c);return BL().Ma(d,4)};f.xj=function(a){return this.Gv(a)};\nf.Em=function(a,b){return this.Dm(a,b)};f.$classData=q({F7:0},!1,\"scala.collection.immutable.Map$Map4\",{F7:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,Cb:1,l:1});function O9(a,b){return new P9(a,new y(()=>b))}function Xba(a){return Q9(new R9,a,new y(()=>0))}function S9(a,b){return a.Id===b?a:new ZU(b)}\nfunction T9(a,b){b=b.m();for(var c=a.Id;b.s();){var d=b.t(),e=My(W(),d),g=$G(bH(),e);c=DU(c,d,e,g,0);if(c!==a.Id){if(0===c.Fb)return dV().Fo;for(;b.s();)if(a=b.t(),d=My(W(),a),e=$G(bH(),d),EU(c,a,d,e),0===c.Fb)return dV().Fo;return new ZU(c)}}return a}function ZU(a){this.Id=a}ZU.prototype=new b9;ZU.prototype.constructor=ZU;f=ZU.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Ub=function(){return dV()};f.Q=function(){return this.Id.Fb};f.ka=function(){return this.Id.Fb};\nf.b=function(){return 0===this.Id.Fb};f.m=function(){return this.b()?Rq().Pa:new y1(this.Id)};f.L=function(a){var b=My(W(),a),c=$G(bH(),b);return this.Id.yt(a,b,c,0)};function B9(a,b){var c=My(W(),b),d=$G(bH(),c);b=yU(a.Id,b,c,d,0);return S9(a,b)}\nfunction Gga(a,b){if(b instanceof ZU){if(a.b())return b;var c=JU(a.Id,b.Id,0);return c===b.Id?b:S9(a,c)}if(b instanceof KV)for(b=new E4(b),c=a.Id;b.s();){var d=b.t(),e=G4(d.nk),g=$G(bH(),e);c=yU(c,d.xm,e,g,0);if(c!==a.Id){for(a=lI(HH(),kI(HH(),g,0));b.s();)d=b.t(),e=G4(d.nk),g=$G(bH(),e),a=BU(c,d.xm,e,g,0,a);return new ZU(c)}}else for(b=b.m(),c=a.Id;b.s();)if(d=b.t(),e=My(W(),d),g=$G(bH(),e),c=yU(c,d,e,g,0),c!==a.Id){for(a=lI(HH(),kI(HH(),g,0));b.s();)d=b.t(),e=My(W(),d),g=$G(bH(),e),a=BU(c,d,e,g,\n0,a);return new ZU(c)}return a}f.e=function(){return this.m().t()};f.Mc=function(){return(new z1(this.Id)).t()};f.Ca=function(a){this.Id.Ca(a)};f.i=function(a){if(a instanceof ZU){if(this===a)return!0;var b=this.Id;a=a.Id;return null===b?null===a:b.i(a)}return kY(this,a)};f.Ih=function(){return\"HashSet\"};f.B=function(){var a=new x1(this.Id);return CL(BL(),a,BL().PB)};\nfunction Hga(a,b){if(a.b())return a;if(b instanceof ZU)return b.b()?a:0===HU(a.Id,b.Id,0).Fb?dV().Fo:S9(a,HU(a.Id,b.Id,0));if(b instanceof KV){for(var c=new E4(b),d=a.Id;c.s();){var e=c.t(),g=G4(e.nk),h=$G(bH(),g);d=DU(d,e.xm,g,h,0);if(d!==a.Id){if(0===d.Fb)return dV().Fo;for(;c.s();)if(a=c.t(),e=G4(a.nk),g=$G(bH(),e),EU(d,a.xm,e,g),0===d.Fb)return dV().Fo;return new ZU(d)}}return a}c=b.Q();return 0===c?a:c<=a.Id.Fb?T9(a,b):U9(a,new y(k=>b.L(k)),!0)}\nfunction Iga(a,b){return b&&b.$classData&&b.$classData.rb.fk?Hga(a,b):b instanceof tZ&&b.K()>a.Id.Fb?U9(a,new y(c=>ha(c)?!pB(b,c|0):!0),!1):T9(a,b)}function U9(a,b,c){b=GU(a.Id,b,c);return b===a.Id?a:0===b.Fb?dV().Fo:new ZU(b)}f.Bb=function(a){return $Y(this,a)};f.Jc=function(a){return zT(this,a)};f.wy=function(a){return Iga(this,a)};f.Ce=function(a){return Gga(this,a)};f.Ek=function(a){var b=My(W(),a),c=$G(bH(),b);a=DU(this.Id,a,b,c,0);return S9(this,a)};f.bc=function(a){return B9(this,a)};\nf.$classData=q({a7:0},!1,\"scala.collection.immutable.HashSet\",{a7:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,F8:1,i6:1,Cb:1,sg:1,l:1});function V9(){}V9.prototype=new u8;V9.prototype.constructor=V9;function W9(){}W9.prototype=V9.prototype;V9.prototype.oh=function(a){return EB(this,a)};V9.prototype.he=function(){};V9.prototype.zc=function(a){return lR(this,a)};V9.prototype.Kb=function(){return this};\nvar Kga=function Jga(a,b){FK();return new gZ(new U(()=>{if(a.b())return hV();FK();var d=b.n(hZ(a).e()),e=Jga(hZ(a).Lf(),b);return new eV(d,e)}))},Mga=function Lga(a,b){if(b.b())return hV();FK();var d=hZ(a).e();FK();return new eV(d,new gZ(new U(()=>Lga(hZ(a).Lf(),hZ(b).Lf()))))};\nfunction X9(a,b,c,d,e){b.ja=\"\"+b.ja+c;if(!a.Dl)b.ja+=\"\\x3cnot computed\\x3e\";else if(!a.b()){c=hZ(a).e();b.ja=\"\"+b.ja+c;c=a;var g=hZ(a).Lf();if(c!==g&&(!g.Dl||hZ(c)!==hZ(g))&&(c=g,g.Dl&&!g.b()))for(g=hZ(g).Lf();c!==g&&g.Dl&&!g.b()&&hZ(c)!==hZ(g);){b.ja=\"\"+b.ja+d;var h=hZ(c).e();b.ja=\"\"+b.ja+h;c=hZ(c).Lf();g=hZ(g).Lf();g.Dl&&!g.b()&&(g=hZ(g).Lf())}if(!g.Dl||g.b()){for(;c!==g;)b.ja=\"\"+b.ja+d,a=hZ(c).e(),b.ja=\"\"+b.ja+a,c=hZ(c).Lf();c.Dl||(b.ja=\"\"+b.ja+d,b.ja+=\"\\x3cnot computed\\x3e\")}else{h=a;for(a=0;;){var k=\nh,l=g;if(k!==l&&hZ(k)!==hZ(l))h=hZ(h).Lf(),g=hZ(g).Lf(),a=1+a|0;else break}h=c;k=g;(h===k||hZ(h)===hZ(k))&&0<a&&(b.ja=\"\"+b.ja+d,a=hZ(c).e(),b.ja=\"\"+b.ja+a,c=hZ(c).Lf());for(;;)if(a=c,h=g,a!==h&&hZ(a)!==hZ(h))b.ja=\"\"+b.ja+d,a=hZ(c).e(),b.ja=\"\"+b.ja+a,c=hZ(c).Lf();else break;b.ja=\"\"+b.ja+d;b.ja+=\"\\x3ccycle\\x3e\"}}b.ja=\"\"+b.ja+e;return b}function gZ(a){this.oS=null;this.IL=!1;this.nS=a;this.JL=this.Dl=!1}gZ.prototype=new i9;gZ.prototype.constructor=gZ;f=gZ.prototype;f.Oc=function(){return\"LinearSeq\"};\nf.Jg=function(){return this.b()?R():new L(this.e())};f.K=function(){for(var a=this,b=0;!a.b();)b=1+b|0,a=a.f();return b};f.Mc=function(){if(this.b())throw AH(\"LinearSeq.last\");for(var a=this,b=this.f();!b.b();)a=b,b=b.f();return a.e()};f.ab=function(a){if(0>a)a=1;else a:for(var b=this,c=0;;){if(c===a){a=b.b()?0:1;break a}if(b.b()){a=-1;break a}c=1+c|0;b=b.f()}return a};f.NJ=function(a){return F0(this,a)};f.va=function(a){return eB(this,a)};\nf.qo=function(a){a:{for(var b=this;!b.b();){if(a.n(b.e())){a=!0;break a}b=b.f()}a=!1}return a};f.L=function(a){a:{for(var b=this;!b.b();){if(ml(nl(),b.e(),a)){a=!0;break a}b=b.f()}a=!1}return a};f.Lt=function(a){return G0(this,a)};f.wo=function(a,b){return H0(this,a,b)};function hZ(a){if(!a.IL&&!a.IL){if(a.JL)throw iL(\"self-referential LazyList or a derivation thereof has no more elements\");a.JL=!0;try{var b=Es(a.nS)}finally{a.JL=!1}a.Dl=!0;a.nS=null;a.oS=b;a.IL=!0}return a.oS}\nf.b=function(){return hZ(this)===hV()};f.Q=function(){return this.Dl&&this.b()?0:-1};f.e=function(){return hZ(this).e()};function fZ(a){var b=a,c=a;for(b.b()||(b=hZ(b).Lf());c!==b&&!b.b();){b=hZ(b).Lf();if(b.b())break;b=hZ(b).Lf();if(b===c)break;c=hZ(c).Lf()}return a}f.m=function(){return this.Dl&&this.b()?Rq().Pa:new X0(this)};f.Ca=function(a){for(var b=this;!b.b();)a.n(hZ(b).e()),b=hZ(b).Lf()};f.De=function(a,b){for(var c=this;;){if(c.b())return a;var d=hZ(c).Lf();a=b.ba(a,hZ(c).e());c=d}};\nf.Ih=function(){return\"LazyList\"};function Y9(a,b){FK();return new gZ(new U(()=>{if(a.b()){var c=Es(b);return c instanceof gZ?hZ(c):0===c.Q()?hV():iZ(FK(),c.m())}FK();c=hZ(a).e();var d=Y9(hZ(a).Lf(),b);return new eV(c,d)}))}function Nga(a,b){return a.Dl&&a.b()?aU(FK(),b):Y9(a,new U(()=>b))}f.th=function(a){if(this.b())throw nv(\"empty.reduceLeft\");for(var b=hZ(this).e(),c=hZ(this).Lf();!c.b();)b=a.ba(b,hZ(c).e()),c=hZ(c).Lf();return b};\nfunction Oga(a,b){FK();return new gZ(new U(()=>{FK();return new eV(b,a)}))}function Z9(a,b){return a.Dl&&a.b()?FK().Ry:Kga(a,b)}f.Gb=function(a){return G(new H,Z9(this,new y(b=>a.n(b).h())),Z9(this,new y(b=>a.n(b).j())))};function Pga(a,b){if(0>=b)return a;if(a.Dl&&a.b())return FK().Ry;FK();return new gZ(new U(()=>{for(var c=a,d=b;0<d&&!c.b();)d=-1+d|0,c=hZ(c).Lf();return Mga(a,c)}))}f.Gh=function(a,b,c,d){fZ(this);X9(this,a.yf,b,c,d);return a};\nf.u=function(){return X9(this,Uq(new Sq,\"LazyList\"),\"(\",\", \",\")\").ja};f.n=function(a){return eB(this,a|0)};f.Lc=function(a){return F0(this,a|0)};f.Bb=function(a){return Pga(this,a)};f.Jc=function(a){return 0>=a?this:this.Dl&&this.b()?FK().Ry:Zea(FK(),this,a)};f.Ja=function(a){return Z9(this,a)};f.cc=function(a){return Oga(this,a)};f.gn=function(a){return Nga(this,a)};f.f=function(){return hZ(this).Lf()};f.Ub=function(){return FK()};\nf.$classData=q({h7:0},!1,\"scala.collection.immutable.LazyList\",{h7:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,KL:1,CG:1,TR:1,pS:1,l:1});function Jr(a){this.Xh=a}Jr.prototype=new i9;Jr.prototype.constructor=Jr;f=Jr.prototype;f.D=function(a){return t9(this,a)};f.Oc=function(){return\"IndexedSeq\"};f.m=function(){return Kr(new Lr,new Mr(this.Xh))};f.Sd=function(){return uZ(new vZ,new Mr(this.Xh))};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};\nf.cc=function(a){return n0(this,a)};f.Jc=function(a){return q0(this,a)};f.Bb=function(a){return this.vc(X8(new Y8,this,a))};f.Ja=function(a){return t0(this,a)};f.e=function(){return hc(this.Xh.charCodeAt(0))};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.Xh.length;return b===a?0:b<a?-1:1};f.Q=function(){return this.Xh.length};f.ti=function(){return DZ().Eb()};f.K=function(){return this.Xh.length};f.u=function(){return this.Xh};\nf.Gc=function(a,b,c){if(a instanceof Ic){var d=this.Xh.length;c=c<d?c:d;d=a.a.length-b|0;c=c<d?c:d;c=0<c?c:0;L2(this.Xh,c,a,b);return c}return NB(this,a,b,c)};f.Lt=function(a){return a instanceof Jr?this.Xh===a.Xh:u9(this,a)};f.Ih=function(){return\"WrappedString\"};f.dy=function(){return 2147483647};f.i=function(a){return a instanceof Jr?this.Xh===a.Xh:i3(this,a)};f.Ub=function(){return xe()};f.gn=function(a){return a instanceof Jr?new Jr(this.Xh+a.Xh):IT(this,a)};f.vc=function(a){return CZ(DZ(),a)};\nf.Gk=function(a){return CZ(DZ(),a)};f.n=function(a){return hc(this.Xh.charCodeAt(a|0))};f.va=function(a){return hc(this.Xh.charCodeAt(a))};f.$classData=q({$8:0},!1,\"scala.collection.immutable.WrappedString\",{$8:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,l:1});function J(a,b){a.bM=b;return a}function K(){this.bM=null}K.prototype=new p;K.prototype.constructor=K;f=K.prototype;f.Ii=function(a){return ky(this,a)};\nf.Zh=function(a){return qw(this,a)};f.cc=function(a){return F3(this,a)};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.D=function(a){return t9(this,a)};f.Lt=function(a){return u9(this,a)};f.dy=function(){SH||(SH=new RH);return SH.lS};f.m=function(){var a=new QX(this);return Kr(new Lr,a)};f.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};\nf.Jc=function(a){return q0(this,a)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.FC=function(){return this};f.i=function(a){return i3(this,a)};f.B=function(){return qS(this)};f.u=function(){return w0(this)};f.tl=function(a){return G3(this,a)};f.ka=function(){return this.K()};f.wo=function(a,b){var c=new QX(this);c=Kr(new Lr,c);return LT(c,a,b)};f.L=function(a){return QU(this,a)};\nf.$k=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.b=function(){return SY(this)};f.Ob=function(a,b){return GQ(this,a,b)};f.ti=function(){return J2().Eb()};f.f=function(){return CT(this)};f.Ca=function(a){cH(this,a)};f.qo=function(a){return ey(this,a)};f.De=function(a,b){return mB(this,a,b)};f.th=function(a){return eH(this,a)};f.Gc=function(a,b,c){return NB(this,a,b,c)};f.aj=function(a){return gH(this,a)};f.$i=function(a){return hH(this,a)};f.Gh=function(a,b,c,d){return iH(this,a,b,c,d)};\nf.ha=function(){Od();return Pd(u(),this)};f.Ti=function(){return pp(qp(),this)};f.Bj=function(a){return kB(this,a)};f.Ik=function(){return J2()};f.K=function(){return this.bM.length|0};f.va=function(a){return this.bM[a]};f.Ih=function(){return\"WrappedVarArgs\"};f.vc=function(a){return H2(J2(),a)};f.Lc=function(a){a|=0;return 0<=a&&0<this.ab(a)};f.n=function(a){return this.va(a|0)};f.Ub=function(){return J2()};\nf.$classData=q({V$:0},!1,\"scala.scalajs.runtime.WrappedVarArgs\",{V$:1,g:1,Sh:1,Mg:1,xc:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Yg:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,l:1});function TU(a){this.dc=a}TU.prototype=new q9;TU.prototype.constructor=TU;f=TU.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){a=sU(this.dc,a,!1);return a===this.dc?this:0===a.kd?Ez().Mr:new TU(a)};f.vj=function(){return Ez()};f.Q=function(){return this.dc.kd};f.ka=function(){return this.dc.kd};\nf.b=function(){return 0===this.dc.kd};f.Ht=function(){return 0===this.dc.kd?ap():new J9(this)};f.m=function(){return this.b()?Rq().Pa:new k1(this.dc)};f.tj=function(){return this.b()?Rq().Pa:new i1(this.dc)};f.ie=function(){return this.b()?Rq().Pa:new m1(this.dc)};f.Sd=function(){return this.b()?Rq().Pa:new l1(this.dc)};f.L=function(a){var b=My(W(),a),c=$G(bH(),b);return this.dc.DF(a,b,c,0)};f.n=function(a){var b=My(W(),a),c=$G(bH(),b);return this.dc.BJ(a,b,c,0)};\nf.U=function(a){var b=My(W(),a),c=$G(bH(),b);return this.dc.KF(a,b,c,0)};f.Se=function(a,b){var c=My(W(),a),d=$G(bH(),c);return this.dc.KJ(a,c,d,0,b)};function m7(a,b,c){var d=My(W(),b);b=iU(a.dc,b,c,d,$G(bH(),d),0,!0);return b===a.dc?a:new TU(b)}function K9(a,b){var c=My(W(),b);b=nU(a.dc,b,c,$G(bH(),c),0);return b===a.dc?a:new TU(b)}\nfunction Qga(a,b){if(b instanceof TU){if(a.b()||qU(a.dc,b.dc,0)===b.dc)return b;b=qU(a.dc,b.dc,0);return b===a.dc?a:new TU(b)}if(b instanceof DV){b=S0(b);for(var c=a.dc;b.s();){var d=b.t(),e=d.mk;e^=e>>>16|0;var g=$G(bH(),e);c=iU(c,d.Wk,d.Ah,e,g,0,!0);if(c!==a.dc){for(a=lI(HH(),kI(HH(),g,0));b.s();)d=b.t(),e=d.mk,e^=e>>>16|0,a=lU(c,d.Wk,d.Ah,e,$G(bH(),e),0,a);return new TU(c)}}return a}if(jV(b)){if(b.b())return a;c=new aZ(a);b.og(c);b=c.Zv;return b===a.dc?a:new TU(b)}b=b.m();return b.s()?(c=new aZ(a),\ncH(b,c),b=c.Zv,b===a.dc?a:new TU(b)):a}f.Ca=function(a){this.dc.Ca(a)};f.og=function(a){this.dc.og(a)};f.i=function(a){if(a instanceof TU){if(this===a)return!0;var b=this.dc;a=a.dc;return null===b?null===a:b.i(a)}return v8(this,a)};f.B=function(){if(this.b())return BL().mG;var a=new j1(this.dc);return CL(BL(),a,BL().Cr)};f.Ih=function(){return\"HashMap\"};\nfunction Rga(a,b){if(a.b())return a;if(b instanceof ZU){if(b.b())return a;b=new YQ(b.Id);for(var c=a.dc;0<c.kd&&b.s();){var d=b.wh.Jb(b.Nc),e=b.wh.ed(b.Nc),g=$G(bH(),d);c=nU(c,e,d,g,0);b.Nc=1+b.Nc|0}b=c;return b===a.dc?a:0>=b.kd?Ez().Mr:new TU(b)}if(b instanceof KV){if(b.b())return a;b=new E4(b);for(d=a.dc;b.s();)if(c=b.t(),e=G4(c.nk),g=$G(bH(),e),d=nU(d,c.xm,e,g,0),0===d.kd)return Ez().Mr;b=d;return b===a.dc?a:new TU(b)}b=b.m();for(d=a.dc;b.s();)if(c=b.t(),e=My(W(),c),g=$G(bH(),e),d=nU(d,c,e,g,0),\n0===d.kd)return Ez().Mr;b=d;return b===a.dc?a:new TU(b)}f.Jc=function(a){return zT(this,a)};f.Bb=function(a){return $Y(this,a)};f.dG=function(a){return Rga(this,a)};f.Mc=function(){return this.Sd().t()};f.e=function(){return this.m().t()};f.am=function(a){return Qga(this,a)};f.xj=function(a){return K9(this,a)};f.IC=function(a,b){return y5(this,a,b)};f.Em=function(a,b){return m7(this,a,b)};f.zr=function(){return this.Ht()};\nf.$classData=q({V6:0},!1,\"scala.collection.immutable.HashMap\",{V6:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,E8:1,RG:1,Cb:1,sg:1,l:1});function $9(){}$9.prototype=new D9;$9.prototype.constructor=$9;function c$(){}c$.prototype=$9.prototype;$9.prototype.zc=function(a){return lR(this,a)};function d$(){}d$.prototype=new F8;d$.prototype.constructor=d$;function e$(){}f=e$.prototype=d$.prototype;f.vj=function(){return Xu()};\nf.kM=function(a){return Q9(new R9,this,a)};f.bj=function(a,b){this.U(a);this.bh(a,b)};f.bh=function(a,b){a=G(new H,a,b);this.$(a)};f.ou=function(a,b){return P8(this,a,b)};f.Hk=function(a,b){return pX(this,a,b)};f.JB=function(a){this.U(a).b()||this.Bm(a)};f.he=function(){};f.zc=function(a){return lR(this,a)};f.Ub=function(){return rO()};f.Kb=function(){return this};function f$(a){this.Jo=null;if(null===a)throw null;this.Jo=a}f$.prototype=new b9;f$.prototype.constructor=f$;f=f$.prototype;f.se=function(){return this.Jo.se()};\nf.m=function(){return new I0(this.Jo)};f.L=function(a){return!this.Jo.U(a).b()};f.ka=function(){return this.Jo.ka()};f.Q=function(){return this.Jo.Q()};f.b=function(){return this.Jo.b()};f.Oc=function(){return\"SortedSet\"};f.i=function(a){return O8(this,a)};f.aj=function(a){return u5(this,a)};f.$i=function(a){return v5(this,a)};f.vc=function(a){return oA(uv(),a,this.Jo.se())};f.Gk=function(a){return oA(uv(),a,this.Jo.se())};f.Ek=function(a){return oA(uv(),this,this.Jo.se()).Ek(a)};\nf.bc=function(a){return oA(uv(),this,this.Jo.se()).bc(a)};f.$classData=q({B8:0},!1,\"scala.collection.immutable.SortedMapOps$ImmutableKeySortedSet\",{B8:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,OL:1,PG:1,fS:1,Iy:1,eS:1,D8:1,UB:1,c6:1});\nfunction g$(a,b,c){var d=c&(-1+a.zg.a.length|0),e=a.zg.a[d];if(null===e)a.zg.a[d]=new cK(b,c,null);else{for(var g=null,h=e;null!==h&&h.nk<=c;){if(h.nk===c&&ml(nl(),b,h.xm))return!1;g=h;h=h.yg}null===g?a.zg.a[d]=new cK(b,c,e):g.yg=new cK(b,c,g.yg)}a.ym=1+a.ym|0;return!0}\nfunction h$(a,b){var c=a.zg.a.length;a.YL=Eb(b*a.hH);if(0===a.ym)a.zg=new (md(dK).Ia)(b);else{var d=a.zg;a.zg=zj(Pj(),d,b);d=new cK(null,0,null);for(var e=new cK(null,0,null);c<b;){for(var g=0;g<c;){var h=a.zg.a[g];if(null!==h){d.yg=null;e.yg=null;for(var k=d,l=e,m=h;null!==m;){var n=m.yg;0===(m.nk&c)?k=k.yg=m:l=l.yg=m;m=n}k.yg=null;h!==d.yg&&(a.zg.a[g]=d.yg);null!==e.yg&&(a.zg.a[g+c|0]=e.yg,l.yg=null)}g=1+g|0}c<<=1}}}\nfunction i$(a){a=-1+a|0;a=4<a?a:4;a=(-2147483648>>Math.clz32(a)&a)<<1;return 1073741824>a?a:1073741824}function JV(a,b,c){a.hH=c;a.zg=new (md(dK).Ia)(i$(b));a.YL=Eb(a.zg.a.length*a.hH);a.ym=0;return a}function Vn(){var a=new KV;JV(a,16,.75);return a}function KV(){this.hH=0;this.zg=null;this.ym=this.YL=0}KV.prototype=new W9;KV.prototype.constructor=KV;f=KV.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return this.ym};\nfunction G4(a){return a^(a>>>16|0)}f.L=function(a){var b=G4(My(W(),a)),c=this.zg.a[b&(-1+this.zg.a.length|0)];if(null===c)a=null;else a:for(;;){if(b===c.nk&&ml(nl(),a,c.xm)){a=c;break a}if(null===c.yg||c.nk>b){a=null;break a}c=c.yg}return null!==a};f.he=function(a){a=i$(Eb((1+a|0)/this.hH));a>this.zg.a.length&&h$(this,a)};f.oh=function(a){(1+this.ym|0)>=this.YL&&h$(this,this.zg.a.length<<1);return g$(this,a,G4(My(W(),a)))};\nfunction IV(a,b){a.he(b.Q());if(b instanceof ZU)return b.Id.FJ(new fn((d,e)=>{g$(a,d,G4(e|0))})),a;if(b instanceof KV){for(b=new E4(b);b.s();){var c=b.t();g$(a,c.xm,c.nk)}return a}return lR(a,b)}f.IB=function(a){a:{var b=G4(My(W(),a)),c=b&(-1+this.zg.a.length|0),d=this.zg.a[c];if(null!==d)if(d.nk===b&&ml(nl(),d.xm,a))this.zg.a[c]=d.yg,this.ym=-1+this.ym|0;else for(c=d,d=d.yg;null!==d&&d.nk<=b;){if(d.nk===b&&ml(nl(),d.xm,a)){c.yg=d.yg;this.ym=-1+this.ym|0;break a}c=d;d=d.yg}}};f.m=function(){return new D4(this)};\nf.mg=function(){var a=this.zg;yj(Pj(),a,null);this.ym=0};f.Ub=function(){return pz()};f.Q=function(){return this.ym};f.b=function(){return 0===this.ym};f.Ca=function(a){for(var b=this.zg.a.length,c=0;c<b;){var d=this.zg.a[c];null!==d&&d.Ca(a);c=1+c|0}};f.Ih=function(){return\"HashSet\"};f.B=function(){var a=new D4(this);a=a.s()?new F4(this):a;return CL(BL(),a,BL().PB)};f.Bm=function(a){this.IB(a)};f.$=function(a){this.oh(a);return this};f.zc=function(a){return IV(this,a)};\nf.$classData=q({N9:0},!1,\"scala.collection.mutable.HashSet\",{N9:1,b9:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,z$:1,ah:1,B$:1,$g:1,Ff:1,xg:1,xf:1,wf:1,Jn:1,Cb:1,l:1});function j$(a){var b=a.Sk,c=b>>31,d=a.Vd;a=d>>31;d=b-d|0;return new ma(d,(-2147483648^d)>(-2147483648^b)?-1+(c-a|0)|0:c-a|0)}function k$(a){var b=j$(a),c=a.lc,d=c>>31;a=xa();b=Ri(a,b.W,b.Y,c,d);a=a.Qc;return 0===b&&0===a}\nfunction l$(a,b,c,d){a.Vd=b;a.Sk=c;a.lc=d;a.fj=b>c&&0<d||b<c&&0>d||b===c&&!a.kn();if(0===d)throw Kj(\"step cannot be 0.\");if(a.fj)b=0;else{b=j$(a);var e=a.lc,g=e>>31;var h=xa();b=$h(h,b.W,b.Y,e,g);h=h.Qc;g=a.kn()||!k$(a)?1:0;e=g>>31;g=b+g|0;h=new ma(g,(-2147483648^g)<(-2147483648^b)?1+(h+e|0)|0:h+e|0);b=h.W;h=h.Y;b=(0===h?-1<(-2147483648^b):0<h)?-1:b}a.Tk=b;switch(d){case 1:c=a.kn()?c:-1+c|0;break;case -1:c=a.kn()?c:1+c|0;break;default:b=j$(a),h=d>>31,b=Ri(xa(),b.W,b.Y,d,h),c=0!==b?c-b|0:a.kn()?c:\nc-d|0}a.gw=c}function tZ(){this.lc=this.Sk=this.Vd=0;this.fj=!1;this.gw=this.Tk=0}tZ.prototype=new i9;tZ.prototype.constructor=tZ;function m$(){}f=m$.prototype=tZ.prototype;f.Ii=function(a){return ky(this,a)};f.cc=function(a){return F3(this,a)};f.gn=function(a){return G3(this,a)};f.Gb=function(a){return XY(this,a)};f.D=function(a){return t9(this,a)};f.Ik=function(){return xe()};f.Oc=function(){return\"IndexedSeq\"};f.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};\nf.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.m=function(){return new hE(this.Vd,this.lc,this.gw,this.fj)};f.b=function(){return this.fj};f.K=function(){return 0>this.Tk?$Q(bR(),this.Vd,this.Sk,this.lc,this.kn()):this.Tk};function n$(a){if(a.fj)throw a=aR(\"last\"),a instanceof $d?a.mu:a;return a.gw}function o$(a){if(a.fj)throw a=aR(\"head\"),a instanceof $d?a.mu:a;return a.Vd}\nfunction p$(a){0>a.Tk&&$Q(bR(),a.Vd,a.Sk,a.lc,a.kn())}f.Ca=function(a){if(!this.fj)for(var b=this.Vd;;){a.n(b);if(b===this.gw)break;b=b+this.lc|0}};f.Lt=function(a){if(a instanceof tZ){var b=this.K();switch(b){case 0:return a.fj;case 1:return 1===a.K()&&this.Vd===a.Vd;default:return a.K()===b&&this.Vd===a.Vd&&this.lc===a.lc}}else return u9(this,a)};\nfunction Sga(a,b){if(0>=b)return a;if(0<=a.Tk)return b=a.Tk-b|0,0>=b||a.fj?(b=a.Vd,a=new oB(b,b,a.lc)):a=b>=a.Tk&&0<=a.Tk?a:new q$(a.Vd,a.Vd+Math.imul(a.lc,-1+b|0)|0,a.lc),a;b=n$(a)-Math.imul(a.lc,b)|0;return 0<a.lc&&b<a.Vd||0>a.lc&&b>a.Vd?(b=a.Vd,new oB(b,b,a.lc)):new q$(a.Vd,b,a.lc)}function pB(a,b){return!(b===a.Sk&&!a.kn())&&(0<a.lc?!(b<a.Vd||b>a.Sk)&&(1===a.lc||0===Bb(b-a.Vd|0,a.lc)):!(b<a.Sk||b>a.Vd)&&(-1===a.lc||0===Bb(b-a.Vd|0,a.lc)))}f.L=function(a){return ha(a)?pB(this,a|0):QU(this,a)};\nf.dy=function(){return 2147483647};f.i=function(a){if(a instanceof tZ){if(this.fj)return a.fj;if(a.fj||this.Vd!==a.Vd)return!1;var b=n$(this);return b===n$(a)&&(this.Vd===b||this.lc===a.lc)}return i3(this,a)};f.B=function(){if(2<=this.K()){var a=BL(),b=this.lc,c=this.gw;return yL(a.C(a.C(a.C(a.rg,this.Vd),b),c))}return qS(this)};f.u=function(){var a=this.kn()?\"to\":\"until\",b=1===this.lc?\"\":\" by \"+this.lc;return(this.fj?\"empty \":k$(this)?\"\":\"inexact \")+\"Range \"+this.Vd+\" \"+a+\" \"+this.Sk+b};f.Ih=function(){return\"Range\"};\nf.wt=function(a){p$(this);if(0>a||a>=this.Tk)throw aL(new bL,a+\" is out of bounds (min 0, max \"+(-1+this.Tk|0)+\")\");return this.Vd+Math.imul(this.lc,a)|0};f.Ub=function(){return xe()};f.Zh=function(a){return a===Fq()?0<this.lc?this:this.fj?this:new q$(n$(this),this.Vd,-this.lc|0):qw(this,a)};f.$i=function(a){if(a===Fq())a=0<this.lc?n$(this):o$(this);else{var b=Fq();a=a===b.NB?0<this.lc?o$(this):n$(this):hH(this,a)|0}return a};\nf.aj=function(a){if(a===Fq())a=0<this.lc?o$(this):n$(this);else{var b=Fq();a=a===b.NB?0<this.lc?n$(this):o$(this):gH(this,a)|0}return a};f.Bb=function(a){return Sga(this,a)};f.Jc=function(a){if(0>=a||this.fj)a=this;else if(a>=this.Tk&&0<=this.Tk)a=this.Sk,a=new oB(a,a,this.lc);else{a=this.Vd+Math.imul(this.lc,a)|0;var b=this.Sk,c=this.lc;a=this.kn()?new q$(a,b,c):new oB(a,b,c)}return a};f.n=function(a){return this.wt(a|0)};f.va=function(a){return this.wt(a)};\nf.Ja=function(a){p$(this);return YY(this,a)};f.f=function(){if(this.fj){var a=aR(\"tail\");throw a instanceof $d?a.mu:a;}1===this.Tk?(a=this.Sk,a=new oB(a,a,this.lc)):a=this.kn()?new q$(this.Vd+this.lc|0,this.Sk,this.lc):new oB(this.Vd+this.lc|0,this.Sk,this.lc);return a};f.e=function(){return o$(this)};f.Mc=function(){return n$(this)};function MB(){this.yC=this.ku=this.zC=null;this.zC=new VV(this)}MB.prototype=new W9;MB.prototype.constructor=MB;f=MB.prototype;f.Gb=function(a){return XY(this,a)};\nf.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.Ub=function(){return KB()};f.Mc=function(){if(0<this.ka())return this.yC.zw;throw AH(\"Cannot call .last on empty LinkedHashSet\");};f.e=function(){if(0<this.ka())return this.ku.zw;throw AH(\"Cannot call .head on empty LinkedHashSet\");};f.ka=function(){return this.zC.nu()};f.Q=function(){return this.ka()};f.b=function(){return 0===this.ka()};f.L=function(a){return null!==mR(this.zC,a)};\nfunction FB(a,b){sR(a.zC,b,null);return a}f.IB=function(a){a=tR(this.zC,a);null!==a&&(null===a.yw?this.ku=a.Mo:a.yw.Mo=a.Mo,null===a.Mo?this.yC=a.yw:a.Mo.yw=a.yw,a.yw=null,a.Mo=null)};f.m=function(){return new qA(this)};f.Ca=function(a){for(var b=this.ku;null!==b;)a.n(b.zw),b=b.Mo};f.Oc=function(){return\"LinkedHashSet\"};f.Bm=function(a){this.IB(a)};f.$=function(a){return FB(this,a)};\nf.$classData=q({g$:0},!1,\"scala.collection.mutable.LinkedHashSet\",{g$:1,b9:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,z$:1,ah:1,B$:1,$g:1,Ff:1,xg:1,xf:1,wf:1,Jn:1,Cb:1,sg:1,l:1});function Q9(a,b,c){a.Yh=b;a.Aw=c;return a}function R9(){this.Aw=this.Yh=null}R9.prototype=new e$;R9.prototype.constructor=R9;function r$(){}f=r$.prototype=R9.prototype;f.IF=function(a){return this.Aw.n(a)};f.m=function(){return this.Yh.m()};f.b=function(){return this.Yh.b()};f.Q=function(){return this.Yh.Q()};\nf.vj=function(){return this.Yh.vj()};f.mg=function(){this.Yh.mg()};f.U=function(a){return this.Yh.U(a)};f.oT=function(a){this.Yh.Bm(a)};f.cQ=function(a){this.Yh.$(a);return this};f.hQ=function(a){return this.Yh.am(a).kM(this.Aw)};f.JJ=function(a){return Q9(new R9,this.Yh.vj().Ib(a),this.Aw)};f.vc=function(a){return this.JJ(a)};f.Gk=function(a){return this.JJ(a)};f.am=function(a){return this.hQ(a)};f.$=function(a){return this.cQ(a)};f.Bm=function(a){this.oT(a)};\nf.$classData=q({fT:0},!1,\"scala.collection.mutable.Map$WithDefault\",{fT:1,eH:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,CC:1,ah:1,mH:1,$g:1,Ff:1,xg:1,xf:1,wf:1,Jn:1,l:1});\nfunction Tga(a,b){if(SY(a))return b;if(SY(b))return a;var c=a.fg()instanceof zc;if(c!==b.fg()instanceof zc)return null;if(c){c=a.fg();b=b.fg();a=wG(xG(),c)+wG(xG(),b)|0;a=new zc(a);var d=wG(xG(),c);c.wa(0,a,0,d);c=wG(xG(),c);d=wG(xG(),b);b.wa(0,a,c,d);return KQ(JQ(),a)}c=a.fg();b=b.fg();d=wG(xG(),c)+wG(xG(),b)|0;a=a.ag().si(d);d=wG(xG(),c);c.wa(0,a,0,d);c=wG(xG(),c);d=wG(xG(),b);b.wa(0,a,c,d);return KQ(JQ(),a)}\nfunction s$(a,b){var c=b.Q();if(0===c)return a;IB();var d=[];0<=c&&wG(xG(),a.fg());a=a.fg();c=wG(xG(),a);for(var e=0;e<c;){var g=XG(xG(),a,e);d.push(null===g?null:g);e=1+e|0}for(b=b.m();b.s();)a=b.t(),d.push(null===a?null:a);return KQ(JQ(),new zc(d))}function K3(){}K3.prototype=new i9;K3.prototype.constructor=K3;function t$(){}f=t$.prototype=K3.prototype;f.Gk=function(a){JQ();var b=this.ag();return J3(a,b)};f.ti=function(){var a=JQ(),b=this.ag();return a.sy(b)};f.Ii=function(a){return ky(this,a)};\nf.Gb=function(a){return XY(this,a)};f.D=function(a){return t9(this,a)};f.Lt=function(a){return u9(this,a)};f.Oc=function(){return\"IndexedSeq\"};f.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};f.ad=function(){return new Z8(this)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ik=function(){return JQ().FL};\nf.qg=function(a){JQ();var b=this.fg();IB();var c=1+wG(xG(),b)|0;c=new zc(c);c.a[0]=a;VG(SG(),b,0,c,1,wG(xG(),b));return KQ(0,c)};f.De=function(a,b){for(var c=this.fg(),d=0;d<wG(xG(),c);){var e=XG(xG(),c,d);a=b.ba(a,e);d=1+d|0}return a};f.mf=function(a,b){for(var c=this.fg(),d=wG(xG(),c);0<d;){d=-1+d|0;var e=XG(xG(),c,d);a=b.ba(e,a)}return a};f.Ih=function(){return\"ArraySeq\"};f.Gc=function(a,b,c){var d=this.K(),e=wG(xG(),a);c=c<d?c:d;e=e-b|0;e=c<e?c:e;e=0<e?e:0;0<e&&VG(SG(),this.fg(),0,a,b,e);return e};\nf.dy=function(){return 2147483647};f.Ai=function(a){if(1>=wG(xG(),this.fg()))return this;SG();var b=this.fg(),c=this.K();TG();Zf(da(jd),bg(ca(b)))?b=Yf(da(jd))?UG(b,c):Cj(Pj(),b,c,da(md(jd))):(c=new zc(c),VG(SG(),b,0,c,0,wG(xG(),b)),b=c);hj(Pj(),b,a);return new Fu(b)};f.vc=function(a){JQ();var b=this.ag();return J3(a,b)};f.Zh=function(a){return this.Ai(a)};f.f=function(){JQ();ms();var a=this.fg();if(0===wG(xG(),a))throw nv(\"tail of empty array\");a=ns(ms(),a,1,wG(xG(),a));return KQ(0,a)};\nf.Bb=function(a){if(0>=a)var b=this;else JQ(),ms(),b=this.fg(),a=wG(xG(),b)-(0<a?a:0)|0,b=ns(ms(),b,0,a),b=KQ(0,b);return b};f.Jc=function(a){return 0>=a?this:KQ(JQ(),ls(ms(),this.fg(),a))};f.gn=function(a){if(a instanceof K3){var b=Tga(this,a);a=null===b?s$(this,a):b}else a=s$(this,a);return a};f.cc=function(a){return this.qg(a)};f.Ja=function(a){for(var b=new zc(this.K()),c=0;c<b.a.length;)b.a[c]=a.n(this.va(c)),c=1+c|0;return KQ(JQ(),b)};f.Ub=function(){return JQ().FL};\nfunction oB(a,b,c){this.lc=this.Sk=this.Vd=0;this.fj=!1;this.gw=this.Tk=0;l$(this,a,b,c)}oB.prototype=new m$;oB.prototype.constructor=oB;oB.prototype.kn=function(){return!1};oB.prototype.$classData=q({Y7:0},!1,\"scala.collection.immutable.Range$Exclusive\",{Y7:1,W7:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,l:1});function q$(a,b,c){this.lc=this.Sk=this.Vd=0;this.fj=!1;this.gw=this.Tk=0;l$(this,a,b,c)}q$.prototype=new m$;\nq$.prototype.constructor=q$;q$.prototype.kn=function(){return!0};q$.prototype.$classData=q({Z7:0},!1,\"scala.collection.immutable.Range$Inclusive\",{Z7:1,W7:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,l:1});function P9(a,b){this.An=this.Qi=null;S8(this,a,b)}P9.prototype=new H9;P9.prototype.constructor=P9;f=P9.prototype;f.AB=function(){return new f$(this)};f.Oc=function(){return\"SortedMap\"};f.i=function(a){return lY(this,a)};\nf.gR=function(a,b){return this.jq().qr(GT(new HT,this,a),b)};f.se=function(){return this.Qi.se()};f.jq=function(){return this.Qi.jq()};function u$(a,b,c){return new P9(a.Qi.Dm(b,c),a.An)}function v$(a,b){return new P9(a.Qi.hy(b),a.An)}function w$(a,b){return new P9(a.Qi.jq().qr(b,a.Qi.se()),a.An)}f.bf=function(a){return v$(this,a)};f.IC=function(a,b){return p8(this,a,b)};f.Pn=function(a){return u$(this,a.h(),a.j())};f.zr=function(){return new f$(this)};f.Ht=function(){return new f$(this)};\nf.jM=function(a){return O9(this,a)};f.vc=function(a){return w$(this,a)};f.Gk=function(a){return w$(this,a)};f.IJ=function(a){return w$(this,a)};f.xj=function(a){return new P9(this.Qi.xj(a),this.An)};f.iR=function(a){return new P9(this.Qi.xj(a),this.An)};f.am=function(a){return v$(this,a)};f.gQ=function(a){return v$(this,a)};f.hy=function(a){return v$(this,a)};f.Em=function(a,b){return u$(this,a,b)};f.Dm=function(a,b){return u$(this,a,b)};f.sT=function(a,b){return u$(this,a,b)};\nf.$classData=q({z8:0},!1,\"scala.collection.immutable.SortedMap$WithDefault\",{z8:1,tS:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,l:1,FS:1,YB:1,zL:1,Iy:1,yL:1,A8:1});function C1(){this.R=null}C1.prototype=new i9;C1.prototype.constructor=C1;function x$(){}f=x$.prototype=C1.prototype;f.Ii=function(a){return ky(this,a)};f.Zh=function(a){return qw(this,a)};f.Gb=function(a){return XY(this,a)};f.D=function(a){return t9(this,a)};\nf.Lt=function(a){return u9(this,a)};f.Oc=function(){return\"IndexedSeq\"};f.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ik=function(){return GK()};f.K=function(){return this instanceof y$?this.ca:this.R.a.length};f.m=function(){return HJ()===this?GK().IS:new p1(this,this.K(),this.On())};\nfunction MU(a,b,c){for(var d=0,e=a.R.a.length;d!==e;){if(!!b.n(a.R.a[d])===c){for(var g=0,h=1+d|0;h<e;)!!b.n(a.R.a[h])!==c&&(g|=1<<h),h=1+h|0;e=g;e=d+nI(UH(),e)|0;if(a instanceof y$){h=new NU;for(var k=0;k<d;)PU(h,a.R.a[k]),k=1+k|0;for(k=1+d|0;d!==e;)0!==(1<<k&g)&&(PU(h,a.R.a[k]),d=1+d|0),k=1+k|0;z$(a,new y(((m,n,r)=>v=>!!m.n(v)!==n?PU(r,v):void 0)(b,c,h)));return h.im()}if(0===e)return HJ();h=new zc(e);a.R.wa(0,h,0,d);for(k=1+d|0;d!==e;)0!==(1<<k&g)&&(h.a[d]=a.R.a[k],d=1+d|0),k=1+k|0;return new IJ(h)}d=\n1+d|0}if(a instanceof y$){var l=new NU;lfa(l,a.R);z$(a,new y(m=>!!b.n(m)!==c?PU(l,m):void 0));return l.im()}return a}f.ql=function(a,b){var c=4+this.On()|0;if(0<b&&b<c){var d=new aw(this);if(ZJ(a))a.Ca(new y(e=>{d.rc=d.rc.hn(e)}));else for(a=a.m();a.s();)b=a.t(),d.rc=d.rc.hn(b);return d.rc}if(this.K()<(b>>>5|0)&&a instanceof C1){b=new QX(this);for(b=uZ(new vZ,b);0<b.zj;)a=a.zl(b.t());return a}return OU(F1(new NU,this),a).im()};f.Ih=function(){return\"Vector\"};\nf.Gc=function(a,b,c){return this.m().Gc(a,b,c)};f.dy=function(){return GK().HS};f.rh=function(a){return aL(new bL,a+\" is out of bounds (min 0, max \"+(-1+this.K()|0)+\")\")};f.e=function(){if(0===this.R.a.length)throw AH(\"empty.head\");return this.R.a[0]};f.Mc=function(){if(this instanceof y$){var a=this.Z;if(0===a.a.length)throw AH(\"empty.tail\");return a.a[-1+a.a.length|0]}return this.R.a[-1+this.R.a.length|0]};\nf.Ca=function(a){for(var b=this.On(),c=0;c<b;){var d=JJ(),e=b/2|0,g=c-e|0;VJ(d,-1+((1+e|0)-(0>g?-g|0:g)|0)|0,this.To(c),a);c=1+c|0}};f.Bb=function(a){a=this.K()-(0<a?a:0)|0;return A$(this,0,a)};f.Jc=function(a){var b=this.K();return A$(this,a,b)};f.gn=function(a){var b=a.Q();return 0===b?this:this.ql(a,b)};f.Ub=function(){return GK()};function B$(){}B$.prototype=new D9;B$.prototype.constructor=B$;function C$(){}f=C$.prototype=B$.prototype;f.Ii=function(a){return E3(this,a)};\nf.cc=function(a){return F3(this,a)};f.gn=function(a){return G3(this,a)};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.Oc=function(){return\"IndexedSeq\"};f.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.Jc=function(a){return q0(this,a)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};\nf.ab=function(a){var b=this.K();return b===a?0:b<a?-1:1};f.Q=function(){return this.K()};f.Ik=function(){return yQ().TL};function D$(a,b){var c=a.ag().uh(),d=c===da(td);a=[];b.Q();for(b=b.m();b.s();){var e=b.t();a.push(d?Ea(e):null===e?c.qi.jz:e)}yQ();c=c===da(pd)?da(la):c===da(jH)||c===da(kH)?da(jd):c;return p4(0,md(c.qi).iz(a))}f.ti=function(){return yQ().sy(this.ag())};f.Ih=function(){return\"ArraySeq\"};\nf.Gc=function(a,b,c){var d=this.K(),e=wG(xG(),a);c=c<d?c:d;e=e-b|0;e=c<e?c:e;e=0<e?e:0;0<e&&VG(SG(),this.rl(),0,a,b,e);return e};f.i=function(a){return a instanceof B$&&wG(xG(),this.rl())!==wG(xG(),a.rl())?!1:i3(this,a)};f.Zh=function(a){yQ();ms();return p4(0,Tu(this.rl(),a))};f.ia=function(){return p4(yQ(),KG(xG(),this.rl()))};f.vc=function(a){return D$(this,a)};f.Gk=function(a){return D$(this,a)};f.Ub=function(){return yQ().TL};function S3(a){this.Hr=a}S3.prototype=new t$;\nS3.prototype.constructor=S3;f=S3.prototype;f.K=function(){return this.Hr.a.length};f.B=function(){var a=BL();return EL(a,this.Hr,a.rg)};f.i=function(a){if(a instanceof S3){var b=this.Hr;a=a.Hr;return vj(Pj(),b,a)}return i3(this,a)};f.Ai=function(a){if(1>=this.K())return this;if(a===PG()){a=this.Hr.ia();var b=QG(),c=PG();RG(b,a,a.a.length,c);return new S3(a)}return K3.prototype.Ai.call(this,a)};f.m=function(){return new IG(this.Hr)};\nf.qg=function(a){if(\"boolean\"===typeof a){a=!!a;var b=this.Hr;uL();var c=new Ec(1+b.a.length|0);c.a[0]=a;VG(SG(),b,0,c,1,b.a.length);return new S3(c)}return K3.prototype.qg.call(this,a)};f.fB=function(a){return this.Hr.a[a]};f.cc=function(a){return this.qg(a)};f.Zh=function(a){return this.Ai(a)};f.n=function(a){return this.fB(a|0)};f.va=function(a){return this.fB(a)};f.ag=function(){return uL()};f.fg=function(){return this.Hr};\nf.$classData=q({H6:0},!1,\"scala.collection.immutable.ArraySeq$ofBoolean\",{H6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function Q3(a){this.Ir=a}Q3.prototype=new t$;Q3.prototype.constructor=Q3;f=Q3.prototype;f.K=function(){return this.Ir.a.length};f.gB=function(a){return this.Ir.a[a]};f.B=function(){var a=BL();return FL(a,this.Ir,a.rg)};\nf.i=function(a){if(a instanceof Q3){var b=this.Ir;a=a.Ir;return uj(Pj(),b,a)}return i3(this,a)};f.Ai=function(a){return 1>=this.K()?this:a===NG()?(a=this.Ir.ia(),fj(Pj(),a),new Q3(a)):K3.prototype.Ai.call(this,a)};f.m=function(){return new GG(this.Ir)};f.qg=function(a){if(Zb(a)){a|=0;var b=this.Ir;sL();var c=new Pc(1+b.a.length|0);c.a[0]=a;VG(SG(),b,0,c,1,b.a.length);return new Q3(c)}return K3.prototype.qg.call(this,a)};f.cc=function(a){return this.qg(a)};f.Zh=function(a){return this.Ai(a)};\nf.n=function(a){return this.gB(a|0)};f.va=function(a){return this.gB(a)};f.ag=function(){return sL()};f.fg=function(){return this.Ir};f.$classData=q({I6:0},!1,\"scala.collection.immutable.ArraySeq$ofByte\",{I6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function P3(a){this.Vp=a}P3.prototype=new t$;P3.prototype.constructor=P3;f=P3.prototype;f.K=function(){return this.Vp.a.length};f.hB=function(a){return this.Vp.a[a]};\nf.B=function(){var a=BL();return GL(a,this.Vp,a.rg)};f.i=function(a){if(a instanceof P3){var b=this.Vp;a=a.Vp;return tj(Pj(),b,a)}return i3(this,a)};f.Ai=function(a){return 1>=this.K()?this:a===MG()?(a=this.Vp.ia(),dj(Pj(),a),new P3(a)):K3.prototype.Ai.call(this,a)};f.m=function(){return new FG(this.Vp)};f.qg=function(a){if(a instanceof ba){a=Ea(a);var b=this.Vp;Ir();var c=new Ic(1+b.a.length|0);c.a[0]=a;VG(SG(),b,0,c,1,b.a.length);return new P3(c)}return K3.prototype.qg.call(this,a)};\nf.Gh=function(a,b,c,d){return(new AQ(this.Vp)).Gh(a,b,c,d)};f.cc=function(a){return this.qg(a)};f.Zh=function(a){return this.Ai(a)};f.n=function(a){return hc(this.hB(a|0))};f.va=function(a){return hc(this.hB(a))};f.ag=function(){return Ir()};f.fg=function(){return this.Vp};f.$classData=q({J6:0},!1,\"scala.collection.immutable.ArraySeq$ofChar\",{J6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});\nfunction M3(a){this.St=a}M3.prototype=new t$;M3.prototype.constructor=M3;f=M3.prototype;f.K=function(){return this.St.a.length};f.B=function(){var a=BL();return HL(a,this.St,a.rg)};f.i=function(a){if(a instanceof M3){var b=this.St;a=a.St;return wj(Pj(),b,a)}return i3(this,a)};f.m=function(){return new CG(this.St)};f.qg=function(a){if(\"number\"===typeof a){a=+a;var b=this.St;pL();var c=new ed(1+b.a.length|0);c.a[0]=a;VG(SG(),b,0,c,1,b.a.length);return new M3(c)}return K3.prototype.qg.call(this,a)};\nf.cB=function(a){return this.St.a[a]};f.cc=function(a){return this.qg(a)};f.n=function(a){return this.cB(a|0)};f.va=function(a){return this.cB(a)};f.ag=function(){return pL()};f.fg=function(){return this.St};f.$classData=q({K6:0},!1,\"scala.collection.immutable.ArraySeq$ofDouble\",{K6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function O3(a){this.Tt=a}O3.prototype=new t$;O3.prototype.constructor=O3;f=O3.prototype;\nf.K=function(){return this.Tt.a.length};f.B=function(){var a=BL();return IL(a,this.Tt,a.rg)};f.i=function(a){if(a instanceof O3){var b=this.Tt;a=a.Tt;return xj(Pj(),b,a)}return i3(this,a)};f.m=function(){return new EG(this.Tt)};f.qg=function(a){if(ja(a)){a=Math.fround(a);var b=this.Tt;rL();var c=new $c(1+b.a.length|0);c.a[0]=a;VG(SG(),b,0,c,1,b.a.length);return new O3(c)}return K3.prototype.qg.call(this,a)};f.dB=function(a){return this.Tt.a[a]};f.cc=function(a){return this.qg(a)};\nf.n=function(a){return this.dB(a|0)};f.va=function(a){return this.dB(a)};f.ag=function(){return rL()};f.fg=function(){return this.Tt};f.$classData=q({L6:0},!1,\"scala.collection.immutable.ArraySeq$ofFloat\",{L6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function L3(a){this.Jr=a}L3.prototype=new t$;L3.prototype.constructor=L3;f=L3.prototype;f.K=function(){return this.Jr.a.length};\nf.B=function(){var a=BL();return JL(a,this.Jr,a.rg)};f.i=function(a){if(a instanceof L3){var b=this.Jr;a=a.Jr;return qj(Pj(),b,a)}return i3(this,a)};f.Ai=function(a){return 1>=this.K()?this:a===Fq()?(a=this.Jr.ia(),Ti(Pj(),a),new L3(a)):K3.prototype.Ai.call(this,a)};f.m=function(){return new BG(this.Jr)};f.qg=function(a){if(ha(a)){a|=0;var b=this.Jr;rl();var c=new Xc(1+b.a.length|0);c.a[0]=a;VG(SG(),b,0,c,1,b.a.length);return new L3(c)}return K3.prototype.qg.call(this,a)};f.wt=function(a){return this.Jr.a[a]};\nf.cc=function(a){return this.qg(a)};f.Zh=function(a){return this.Ai(a)};f.n=function(a){return this.wt(a|0)};f.va=function(a){return this.wt(a)};f.ag=function(){return rl()};f.fg=function(){return this.Jr};f.$classData=q({M6:0},!1,\"scala.collection.immutable.ArraySeq$ofInt\",{M6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function N3(a){this.Kr=a}N3.prototype=new t$;N3.prototype.constructor=N3;f=N3.prototype;\nf.K=function(){return this.Kr.a.length};f.B=function(){var a=BL();return KL(a,this.Kr,a.rg)};f.i=function(a){if(a instanceof N3){var b=this.Kr;a=a.Kr;return pj(Pj(),b,a)}return i3(this,a)};f.Ai=function(a){return 1>=this.K()?this:a===LG()?(a=this.Kr.ia(),$i(Pj(),a),new N3(a)):K3.prototype.Ai.call(this,a)};f.m=function(){return new DG(this.Kr)};\nf.qg=function(a){if(a instanceof ma){var b=Za(a);a=b.W;b=b.Y;var c=this.Kr;qL();var d=new Zc(1+c.a.length|0);d.a[0]=Za(new ma(a,b));VG(SG(),c,0,d,1,c.a.length);return new N3(d)}return K3.prototype.qg.call(this,a)};f.eB=function(a){return this.Kr.a[a]};f.cc=function(a){return this.qg(a)};f.Zh=function(a){return this.Ai(a)};f.n=function(a){return this.eB(a|0)};f.va=function(a){return this.eB(a)};f.ag=function(){return qL()};f.fg=function(){return this.Kr};\nf.$classData=q({N6:0},!1,\"scala.collection.immutable.ArraySeq$ofLong\",{N6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function Fu(a){this.vn=a}Fu.prototype=new t$;Fu.prototype.constructor=Fu;f=Fu.prototype;f.ag=function(){return yG(zG(),bg(ca(this.vn)))};f.K=function(){return this.vn.a.length};f.va=function(a){return this.vn.a[a]};f.B=function(){var a=BL();return DL(a,this.vn,a.rg)};\nf.i=function(a){return a instanceof Fu?sQ(SG(),this.vn,a.vn):i3(this,a)};function E$(a,b){if(1>=a.vn.a.length)return a;a=a.vn.ia();hj(Pj(),a,b);return new Fu(a)}f.m=function(){return Du(new Eu,this.vn)};f.Zh=function(a){return E$(this,a)};f.Ai=function(a){return E$(this,a)};f.n=function(a){return this.va(a|0)};f.fg=function(){return this.vn};\nf.$classData=q({O6:0},!1,\"scala.collection.immutable.ArraySeq$ofRef\",{O6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function R3(a){this.Lr=a}R3.prototype=new t$;R3.prototype.constructor=R3;f=R3.prototype;f.K=function(){return this.Lr.a.length};f.iB=function(a){return this.Lr.a[a]};f.B=function(){var a=BL();return LL(a,this.Lr,a.rg)};\nf.i=function(a){if(a instanceof R3){var b=this.Lr;a=a.Lr;return sj(Pj(),b,a)}return i3(this,a)};f.Ai=function(a){return 1>=this.K()?this:a===OG()?(a=this.Lr.ia(),bj(Pj(),a),new R3(a)):K3.prototype.Ai.call(this,a)};f.m=function(){return new HG(this.Lr)};f.qg=function(a){if($b(a)){a|=0;var b=this.Lr;tL();var c=new Sc(1+b.a.length|0);c.a[0]=a;VG(SG(),b,0,c,1,b.a.length);return new R3(c)}return K3.prototype.qg.call(this,a)};f.cc=function(a){return this.qg(a)};f.Zh=function(a){return this.Ai(a)};\nf.n=function(a){return this.iB(a|0)};f.va=function(a){return this.iB(a)};f.ag=function(){return tL()};f.fg=function(){return this.Lr};f.$classData=q({P6:0},!1,\"scala.collection.immutable.ArraySeq$ofShort\",{P6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});function T3(a){this.Oy=a}T3.prototype=new t$;T3.prototype.constructor=T3;f=T3.prototype;f.K=function(){return this.Oy.a.length};\nf.B=function(){var a=BL();return ML(a,this.Oy,a.rg)};f.i=function(a){return a instanceof T3?this.Oy.a.length===a.Oy.a.length:i3(this,a)};f.m=function(){return new JG(this.Oy)};f.n=function(){};f.va=function(){};f.ag=function(){return SR()};f.fg=function(){return this.Oy};f.$classData=q({Q6:0},!1,\"scala.collection.immutable.ArraySeq$ofUnit\",{Q6:1,Gr:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,Dr:1,l:1});\nfunction gy(a,b,c){a:for(;;){if(a.b()){c=u();break a}var d=a.e(),e=a.f();if(!!b.n(d)!==c){b:for(var g=c;;){if(e.b()){c=a;break b}c=e.e();if(!!b.n(c)!==g)e=e.f();else{var h=a;d=e;c=b;b=g;a=new z(h.e(),u());g=h.f();for(e=a;g!==d;)h=new z(g.e(),u()),e=e.p=h,g=g.f();for(g=d=d.f();!d.b();){h=d.e();if(!!c.n(h)===b){for(;g!==d;)h=new z(g.e(),u()),e=e.p=h,g=g.f();g=d.f()}d=d.f()}g.b()||(e.p=g);c=a;break b}}break a}a=e}return c}\nfunction bga(a,b,c){for(var d=null,e=null;;){if(b.b()){if(null===d)return a;e.p=a;return d}var g=b.e(),h=c.n(g);if(Object.is(h,g))b=b.f();else{for(;a!==b;)g=new z(a.e(),u()),null===d&&(d=g),null!==e&&(e.p=g),e=g,a=a.f();h=new z(h,u());null===d&&(d=h);null!==e&&(e.p=h);e=h;b=b.f();e=h=e;a=b}}}function rS(){}rS.prototype=new i9;rS.prototype.constructor=rS;function F$(){}f=F$.prototype=rS.prototype;f.Ii=function(a){return ky(this,a)};f.Zh=function(a){return qw(this,a)};f.m=function(){return new Om(this)};\nf.Gb=function(a){return XY(this,a)};f.Bb=function(a){return $Y(this,a)};f.Oc=function(){return\"LinearSeq\"};f.NJ=function(a){return F0(this,a)};f.va=function(a){return eB(this,a)};f.De=function(a,b){return YA(this,a,b)};f.Lt=function(a){return G0(this,a)};f.wo=function(a,b){return H0(this,a,b)};f.Ik=function(){return Od()};function dl(a,b){if(a.b())return b;if(b.b())return a;var c=new z(b.e(),a),d=c;for(b=b.f();!b.b();){var e=new z(b.e(),a);d=d.p=e;b=b.f()}return c}f.b=function(){return this===u()};\nfunction Pd(a,b){if(b instanceof rS)return dl(a,b);if(0===b.Q())return a;if(b instanceof fp&&a.b())return b.ha();b=b.m();if(b.s()){for(var c=new z(b.t(),a),d=c;b.s();){var e=new z(b.t(),a);d=d.p=e}return c}return a}function un(a,b){return b instanceof rS?dl(b,a):G3(a,b)}function xt(a,b){if(a.b()||0>=b)return u();for(var c=new z(a.e(),u()),d=c,e=a.f(),g=1;;){if(e.b())return a;if(g<b){g=1+g|0;var h=new z(e.e(),u());d=d.p=h;e=e.f()}else break}return c}\nfunction Qt(a,b){if(a===u())return u();var c=new z(b.n(a.e()),u()),d=c;for(a=a.f();a!==u();){var e=new z(b.n(a.e()),u());d=d.p=e;a=a.f()}return c}function Wn(a,b){if(a===u())return u();for(var c=null,d;null===c;)if(d=b.Ob(a.e(),Od().iC),d!==Od().iC&&(c=new z(d,u())),a=a.f(),a===u())return null===c?u():c;for(var e=c;a!==u();)d=b.Ob(a.e(),Od().iC),d!==Od().iC&&(d=new z(d,u()),e=e.p=d),a=a.f();return c}\nfunction ZW(a,b){for(var c=null,d=null;a!==u();){for(var e=b.n(a.e()).m();e.s();){var g=new z(e.t(),u());null===d?c=g:d.p=g;d=g}a=a.f()}return null===c?u():c}f.Ca=function(a){for(var b=this;!b.b();)a.n(b.e()),b=b.f()};function Km(a){for(var b=u();!a.b();){var c=a.e();b=new z(c,b);a=a.f()}return b}f.mf=function(a,b){for(var c=Km(this);!c.b();)a=b.ba(c.e(),a),c=c.f();return a};f.K=function(){for(var a=this,b=0;!a.b();)b=1+b|0,a=a.f();return b};\nf.ab=function(a){if(0>a)a=1;else a:for(var b=this,c=0;;){if(c===a){a=b.b()?0:1;break a}if(b.b()){a=-1;break a}c=1+c|0;b=b.f()}return a};f.ul=function(a){for(var b=this;!b.b();){if(!a.n(b.e()))return!1;b=b.f()}return!0};f.qo=function(a){for(var b=this;!b.b();){if(a.n(b.e()))return!0;b=b.f()}return!1};f.L=function(a){for(var b=this;!b.b();){if(ml(nl(),b.e(),a))return!0;b=b.f()}return!1};function lX(a,b){for(;!a.b();){if(b.n(a.e()))return new L(a.e());a=a.f()}return R()}\nf.Mc=function(){if(this.b())throw AH(\"List.last\");for(var a=this,b=this.f();!b.b();)a=b,b=b.f();return a.e()};f.Ih=function(){return\"List\"};f.BK=function(a){if(this.b())return Od().jC;for(var b=this.ti(),c=this.ti(),d=this.m();d.s();){var e=d.t();(a.n(e)?b:c).$(e)}a=G(new H,b.Kb(),c.Kb());return null!==a&&(b=a.h(),u().i(b))?G(new H,u(),this):null!==a&&(b=a.j(),u().i(b))?G(new H,this,u()):a};f.ha=function(){return this};\nf.i=function(a){var b;if(a instanceof rS)a:for(b=this;;){if(b===a){b=!0;break a}var c=b.b(),d=a.b();if(c||d||!ml(nl(),b.e(),a.e())){b=c&&d;break a}b=b.f();a=a.f()}else b=i3(this,a);return b};f.n=function(a){return eB(this,a|0)};f.Lc=function(a){return F0(this,a|0)};f.Jc=function(a){return a6(a,this)};f.Ja=function(a){return Qt(this,a)};f.gn=function(a){return un(this,a)};f.cc=function(a){return new z(a,this)};f.Ub=function(){return Od()};function G$(){this.R=null}G$.prototype=new x$;\nG$.prototype.constructor=G$;function H$(){}H$.prototype=G$.prototype;function A$(a,b,c){b=0<b?b:0;var d=a.K();c=c<d?c:d;return(c-b|0)===a.K()?a:c<=b?HJ():a.Ln(b,c)}function w4(a){this.nw=a}w4.prototype=new C$;w4.prototype.constructor=w4;f=w4.prototype;f.K=function(){return this.nw.a.length};f.B=function(){var a=BL();return EL(a,this.nw,a.rg)};f.i=function(a){if(a instanceof w4){var b=this.nw;a=a.nw;return vj(Pj(),b,a)}return B$.prototype.i.call(this,a)};f.m=function(){return new IG(this.nw)};\nf.fB=function(a){return this.nw.a[a]};f.n=function(a){return this.fB(a|0)};f.va=function(a){return this.fB(a)};f.ag=function(){return uL()};f.rl=function(){return this.nw};f.$classData=q({k9:0},!1,\"scala.collection.mutable.ArraySeq$ofBoolean\",{k9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function u4(a){this.ow=a}u4.prototype=new C$;u4.prototype.constructor=u4;f=u4.prototype;f.K=function(){return this.ow.a.length};\nf.gB=function(a){return this.ow.a[a]};f.B=function(){var a=BL();return FL(a,this.ow,a.rg)};f.i=function(a){if(a instanceof u4){var b=this.ow;a=a.ow;return uj(Pj(),b,a)}return B$.prototype.i.call(this,a)};f.m=function(){return new GG(this.ow)};f.n=function(a){return this.gB(a|0)};f.va=function(a){return this.gB(a)};f.ag=function(){return sL()};f.rl=function(){return this.ow};\nf.$classData=q({l9:0},!1,\"scala.collection.mutable.ArraySeq$ofByte\",{l9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function AQ(a){this.En=a}AQ.prototype=new C$;AQ.prototype.constructor=AQ;f=AQ.prototype;f.K=function(){return this.En.a.length};f.hB=function(a){return this.En.a[a]};f.B=function(){var a=BL();return GL(a,this.En,a.rg)};\nf.i=function(a){if(a instanceof AQ){var b=this.En;a=a.En;return tj(Pj(),b,a)}return B$.prototype.i.call(this,a)};f.m=function(){return new FG(this.En)};f.Gh=function(a,b,c,d){var e=a.yf;0!==b.length&&(e.ja=\"\"+e.ja+b);b=this.En.a.length;if(0!==b)if(\"\"===c)mW(e,this.En);else{e.K();var g=String.fromCharCode(this.En.a[0]);e.ja=\"\"+e.ja+g;for(g=1;g<b;){e.ja=\"\"+e.ja+c;var h=String.fromCharCode(this.En.a[g]);e.ja=\"\"+e.ja+h;g=1+g|0}}0!==d.length&&(e.ja=\"\"+e.ja+d);return a};\nf.n=function(a){return hc(this.hB(a|0))};f.va=function(a){return hc(this.hB(a))};f.ag=function(){return Ir()};f.rl=function(){return this.En};f.$classData=q({m9:0},!1,\"scala.collection.mutable.ArraySeq$ofChar\",{m9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function r4(a){this.pw=a}r4.prototype=new C$;r4.prototype.constructor=r4;f=r4.prototype;f.K=function(){return this.pw.a.length};\nf.B=function(){var a=BL();return HL(a,this.pw,a.rg)};f.i=function(a){if(a instanceof r4){var b=this.pw;a=a.pw;return wj(Pj(),b,a)}return B$.prototype.i.call(this,a)};f.m=function(){return new CG(this.pw)};f.cB=function(a){return this.pw.a[a]};f.n=function(a){return this.cB(a|0)};f.va=function(a){return this.cB(a)};f.ag=function(){return pL()};f.rl=function(){return this.pw};\nf.$classData=q({n9:0},!1,\"scala.collection.mutable.ArraySeq$ofDouble\",{n9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function t4(a){this.qw=a}t4.prototype=new C$;t4.prototype.constructor=t4;f=t4.prototype;f.K=function(){return this.qw.a.length};f.B=function(){var a=BL();return IL(a,this.qw,a.rg)};f.i=function(a){if(a instanceof t4){var b=this.qw;a=a.qw;return xj(Pj(),b,a)}return B$.prototype.i.call(this,a)};\nf.m=function(){return new EG(this.qw)};f.dB=function(a){return this.qw.a[a]};f.n=function(a){return this.dB(a|0)};f.va=function(a){return this.dB(a)};f.ag=function(){return rL()};f.rl=function(){return this.qw};f.$classData=q({o9:0},!1,\"scala.collection.mutable.ArraySeq$ofFloat\",{o9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function q4(a){this.rw=a}q4.prototype=new C$;q4.prototype.constructor=q4;f=q4.prototype;\nf.K=function(){return this.rw.a.length};f.B=function(){var a=BL();return JL(a,this.rw,a.rg)};f.i=function(a){if(a instanceof q4){var b=this.rw;a=a.rw;return qj(Pj(),b,a)}return B$.prototype.i.call(this,a)};f.m=function(){return new BG(this.rw)};f.wt=function(a){return this.rw.a[a]};f.n=function(a){return this.wt(a|0)};f.va=function(a){return this.wt(a)};f.ag=function(){return rl()};f.rl=function(){return this.rw};\nf.$classData=q({p9:0},!1,\"scala.collection.mutable.ArraySeq$ofInt\",{p9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function s4(a){this.sw=a}s4.prototype=new C$;s4.prototype.constructor=s4;f=s4.prototype;f.K=function(){return this.sw.a.length};f.B=function(){var a=BL();return KL(a,this.sw,a.rg)};f.i=function(a){if(a instanceof s4){var b=this.sw;a=a.sw;return pj(Pj(),b,a)}return B$.prototype.i.call(this,a)};\nf.m=function(){return new DG(this.sw)};f.eB=function(a){return this.sw.a[a]};f.n=function(a){return this.eB(a|0)};f.va=function(a){return this.eB(a)};f.ag=function(){return qL()};f.rl=function(){return this.sw};f.$classData=q({q9:0},!1,\"scala.collection.mutable.ArraySeq$ofLong\",{q9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function zQ(a){this.gu=a}zQ.prototype=new C$;zQ.prototype.constructor=zQ;f=zQ.prototype;\nf.ag=function(){return yG(zG(),bg(ca(this.gu)))};f.K=function(){return this.gu.a.length};f.va=function(a){return this.gu.a[a]};f.B=function(){var a=BL();return DL(a,this.gu,a.rg)};f.i=function(a){return a instanceof zQ?sQ(SG(),this.gu,a.gu):B$.prototype.i.call(this,a)};f.m=function(){return Du(new Eu,this.gu)};f.n=function(a){return this.va(a|0)};f.rl=function(){return this.gu};\nf.$classData=q({r9:0},!1,\"scala.collection.mutable.ArraySeq$ofRef\",{r9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function v4(a){this.tw=a}v4.prototype=new C$;v4.prototype.constructor=v4;f=v4.prototype;f.K=function(){return this.tw.a.length};f.iB=function(a){return this.tw.a[a]};f.B=function(){var a=BL();return LL(a,this.tw,a.rg)};\nf.i=function(a){if(a instanceof v4){var b=this.tw;a=a.tw;return sj(Pj(),b,a)}return B$.prototype.i.call(this,a)};f.m=function(){return new HG(this.tw)};f.n=function(a){return this.iB(a|0)};f.va=function(a){return this.iB(a)};f.ag=function(){return tL()};f.rl=function(){return this.tw};f.$classData=q({s9:0},!1,\"scala.collection.mutable.ArraySeq$ofShort\",{s9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});\nfunction x4(a){this.cz=a}x4.prototype=new C$;x4.prototype.constructor=x4;f=x4.prototype;f.K=function(){return this.cz.a.length};f.B=function(){var a=BL();return ML(a,this.cz,a.rg)};f.i=function(a){return a instanceof x4?this.cz.a.length===a.cz.a.length:B$.prototype.i.call(this,a)};f.m=function(){return new JG(this.cz)};f.n=function(){};f.va=function(){};f.ag=function(){return SR()};f.rl=function(){return this.cz};\nf.$classData=q({t9:0},!1,\"scala.collection.mutable.ArraySeq$ofUnit\",{t9:1,Tr:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,l:1});function I$(a,b,c,d){(1+a.Xf|0)>=a.hu&&Oy(a,a.eb.a.length<<1);return Py(a,b,c,!1,d,d&(-1+a.eb.a.length|0))}function Ly(a,b,c,d){(1+a.Xf|0)>=a.hu&&Oy(a,a.eb.a.length<<1);var e=My(W(),b);e^=e>>>16|0;return Py(a,b,c,d,e,e&(-1+a.eb.a.length|0))}\nfunction Py(a,b,c,d,e,g){var h=a.eb.a[g];if(null===h)a.eb.a[g]=new aK(b,e,c,null);else{for(var k=null,l=h;null!==l&&l.mk<=e;){if(l.mk===e&&ml(nl(),b,l.Wk))return a=l.Ah,l.Ah=c,d?new L(a):null;k=l;l=l.$d}null===k?a.eb.a[g]=new aK(b,e,c,h):k.$d=new aK(b,e,c,k.$d)}a.Xf=1+a.Xf|0;return null}\nfunction J$(a,b){var c=My(W(),b);a:{c^=c>>>16|0;var d=c&(-1+a.eb.a.length|0),e=a.eb.a[d];if(null===e)a=null;else if(e.mk===c&&ml(nl(),e.Wk,b))a.eb.a[d]=e.$d,a.Xf=-1+a.Xf|0,a=e;else{d=e;for(e=e.$d;null!==e&&e.mk<=c;){if(e.mk===c&&ml(nl(),e.Wk,b)){d.$d=e.$d;a.Xf=-1+a.Xf|0;a=e;break a}d=e;e=e.$d}a=null}}return a}\nfunction Oy(a,b){if(0>b)throw iL(\"new HashMap table size \"+b+\" exceeds maximum\");var c=a.eb.a.length;a.hu=Eb(b*a.gH);if(0===a.Xf)a.eb=new (md(bK).Ia)(b);else{var d=a.eb;a.eb=zj(Pj(),d,b);d=new aK(null,0,null,null);for(var e=new aK(null,0,null,null);c<b;){for(var g=0;g<c;){var h=a.eb.a[g];if(null!==h){d.$d=null;e.$d=null;for(var k=d,l=e,m=h;null!==m;){var n=m.$d;0===(m.mk&c)?k=k.$d=m:l=l.$d=m;m=n}k.$d=null;h!==d.$d&&(a.eb.a[g]=d.$d);null!==e.$d&&(a.eb.a[g+c|0]=e.$d,l.$d=null)}g=1+g|0}c<<=1}}}\nfunction K$(a){a=-1+a|0;a=4<a?a:4;a=(-2147483648>>Math.clz32(a)&a)<<1;return 1073741824>a?a:1073741824}function CV(a,b,c){a.gH=c;a.eb=new (md(bK).Ia)(K$(b));a.hu=Eb(a.eb.a.length*a.gH);a.Xf=0;return a}function FV(){var a=new DV;CV(a,16,.75);return a}function DV(){this.gH=0;this.eb=null;this.Xf=this.hu=0}DV.prototype=new e$;DV.prototype.constructor=DV;f=DV.prototype;f.ry=function(a){return b6(this,a)};f.am=function(a){return c6(this,a)};f.Gb=function(a){return XY(this,a)};\nf.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.ka=function(){return this.Xf};f.L=function(a){var b=My(W(),a);b^=b>>>16|0;var c=this.eb.a[b&(-1+this.eb.a.length|0)];return null!==(null===c?null:Ny(c,a,b))};f.he=function(a){a=K$(Eb((1+a|0)/this.gH));a>this.eb.a.length&&Oy(this,a)};\nfunction BV(a,b){a.he(b.Q());if(b instanceof TU)return b.dc.GJ(new fW((d,e,g)=>{g|=0;I$(a,d,e,g^(g>>>16|0))})),a;if(b instanceof DV){for(b=S0(b);b.s();){var c=b.t();I$(a,c.Wk,c.Ah,c.mk)}return a}return b&&b.$classData&&b.$classData.rb.CC?(b.og(new fn((d,e)=>{var g=My(W(),d);return I$(a,d,e,g^(g>>>16|0))})),a):lR(a,b)}\nf.ou=function(a,b){if(ca(this)!==da(Ky))return P8(this,a,b);var c=My(W(),a);c^=c>>>16|0;var d=c&(-1+this.eb.a.length|0);var e=null;var g=null;var h=this.eb.a[d];if(null!==h)for(var k=null;;){if(c===h.mk&&ml(nl(),a,h.Wk))g=k,e=h;else if(!(null===h.$d||h.mk>c)){var l=h.$d;k=h;h=l;continue}break}k=e;k=null===k?R():new L(k.Ah);b=b.n(k);k=G(new H,k,b);h=k.y;l=k.w;if(R()!==h||R()!==l)if(h=k.w,k.y instanceof L&&R()===h)null!==g?g.$d=e.$d:this.eb.a[d]=e.$d,this.Xf=-1+this.Xf|0;else if(g=k.y,h=k.w,R()===g&&\nh instanceof L)e=h.k,d=(1+this.Xf|0)>=this.hu?(Oy(this,this.eb.a.length<<1),c&(-1+this.eb.a.length|0)):d,Py(this,a,e,!1,c,d);else if(a=k.w,k.y instanceof L&&a instanceof L)e.Ah=a.k;else throw new w(k);return b};f.m=function(){return 0===this.Xf?Rq().Pa:new y4(this)};f.tj=function(){return 0===this.Xf?Rq().Pa:new z4(this)};f.ie=function(){return 0===this.Xf?Rq().Pa:new A4(this)};function S0(a){return 0===a.Xf?Rq().Pa:new B4(a)}f.mg=function(){var a=this.eb;yj(Pj(),a,null);this.Xf=0};\nf.U=function(a){var b=My(W(),a);b^=b>>>16|0;var c=this.eb.a[b&(-1+this.eb.a.length|0)];a=null===c?null:Ny(c,a,b);return null===a?R():new L(a.Ah)};f.n=function(a){var b=My(W(),a);b^=b>>>16|0;var c=this.eb.a[b&(-1+this.eb.a.length|0)];b=null===c?null:Ny(c,a,b);return null===b?z3(a):b.Ah};f.Se=function(a,b){if(ca(this)!==da(Ky))return x3(this,a,b);var c=My(W(),a);c^=c>>>16|0;var d=this.eb.a[c&(-1+this.eb.a.length|0)];a=null===d?null:Ny(d,a,c);return null===a?Es(b):a.Ah};\nf.Hk=function(a,b){if(ca(this)!==da(Ky))return pX(this,a,b);var c=My(W(),a);c^=c>>>16|0;var d=c&(-1+this.eb.a.length|0),e=this.eb.a[d];e=null===e?null:Ny(e,a,c);if(null!==e)return e.Ah;e=this.eb;b=Es(b);(1+this.Xf|0)>=this.hu&&Oy(this,this.eb.a.length<<1);Py(this,a,b,!1,c,e===this.eb?d:c&(-1+this.eb.a.length|0));return b};f.bj=function(a,b){null===Ly(this,a,b,!0)&&R()};f.JB=function(a){null===J$(this,a)&&R()};f.bh=function(a,b){Ly(this,a,b,!1)};f.Q=function(){return this.Xf};\nf.b=function(){return 0===this.Xf};f.Ca=function(a){for(var b=this.eb.a.length,c=0;c<b;){var d=this.eb.a[c];null!==d&&d.Ca(a);c=1+c|0}};f.og=function(a){for(var b=this.eb.a.length,c=0;c<b;){var d=this.eb.a[c];null!==d&&d.og(a);c=1+c|0}};f.vj=function(){return Ty()};f.Oc=function(){return\"HashMap\"};f.B=function(){if(this.b())return BL().mG;var a=new C4(this);return CL(BL(),a,BL().Cr)};f.Bm=function(a){J$(this,a)};f.$=function(a){Ly(this,a.h(),a.j(),!1);return this};\nf.zc=function(a){return BV(this,a)};var Ky=q({E9:0},!1,\"scala.collection.mutable.HashMap\",{E9:1,eH:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,CC:1,ah:1,mH:1,$g:1,Ff:1,xg:1,xf:1,wf:1,Jn:1,Cb:1,RG:1,l:1});DV.prototype.$classData=Ky;function L$(a,b,c,d){a.Z=c;a.ca=d;a.R=b}function y$(){this.Z=this.R=null;this.ca=0}y$.prototype=new H$;y$.prototype.constructor=y$;function M$(){}M$.prototype=y$.prototype;\nfunction z$(a,b){for(var c=a.On(),d=1;d<c;){var e=JJ(),g=c/2|0,h=d-g|0;VJ(e,-1+((1+g|0)-(0>h?-h|0:h)|0)|0,a.To(d),b);d=1+d|0}}function IJ(a){this.R=a}IJ.prototype=new H$;IJ.prototype.constructor=IJ;f=IJ.prototype;f.va=function(a){if(0<=a&&a<this.R.a.length)return this.R.a[a];throw this.rh(a);};f.$r=function(a,b){if(0<=a&&a<this.R.a.length){var c=this.R.ia();c.a[a]=b;return new IJ(c)}throw this.rh(a);};\nf.hn=function(a){if(32>this.R.a.length)return new IJ(RJ(JJ(),this.R,a));var b=this.R,c=JJ().bd,d=new zc(1);d.a[0]=a;return new KJ(b,32,c,d,33)};f.zl=function(a){var b=this.R.a.length;if(32>b)return new IJ(TJ(JJ(),a,this.R));var c=new zc(1);c.a[0]=a;return new KJ(c,1,JJ().bd,this.R,1+b|0)};f.yo=function(a){return new IJ(WJ(JJ(),this.R,a))};f.Ln=function(a,b){var c=this.R;return new IJ(Jj(Pj(),c,a,b))};\nf.Cm=function(){if(1===this.R.a.length)return HJ();var a=this.R,b=a.a.length;return new IJ(Jj(Pj(),a,1,b))};f.On=function(){return 1};f.To=function(){return this.R};f.ql=function(a,b){var c=YJ(JJ(),this.R,a);return null!==c?new IJ(c):C1.prototype.ql.call(this,a,b)};f.f=function(){return this.Cm()};f.Ja=function(a){return this.yo(a)};f.cc=function(a){return this.zl(a)};f.n=function(a){a|=0;if(0<=a&&a<this.R.a.length)return this.R.a[a];throw this.rh(a);};\nf.$classData=q({R8:0},!1,\"scala.collection.immutable.Vector1\",{R8:1,$y:1,Zy:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,sg:1,l:1});function z(a,b){this.z=a;this.p=b}z.prototype=new F$;z.prototype.constructor=z;f=z.prototype;f.e=function(){return this.z};f.H=function(){return\"::\"};f.G=function(){return 2};f.I=function(a){switch(a){case 0:return this.z;case 1:return this.p;default:return $K(W(),a)}};f.f=function(){return this.p};\nf.Jg=function(){return new L(this.z)};f.$classData=q({F6:0},!1,\"scala.collection.immutable.$colon$colon\",{F6:1,r7:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,KL:1,CG:1,TR:1,pS:1,g6:1,id:1,Cb:1,Uh:1,sg:1,l:1,E:1});function N$(){this.xS=null;O$=this;this.xS=G(new H,u(),u())}N$.prototype=new F$;N$.prototype.constructor=N$;f=N$.prototype;f.LJ=function(){throw AH(\"head of empty list\");};f.Q=function(){return 0};f.m=function(){return Rq().Pa};f.Gb=function(){return this.xS};\nf.H=function(){return\"Nil\"};f.G=function(){return 0};f.I=function(a){return $K(W(),a)};f.MJ=function(){throw nv(\"init of empty list\");};f.Mc=function(){throw AH(\"last of empty list\");};f.f=function(){throw nv(\"tail of empty list\");};f.Jg=function(){return R()};f.e=function(){this.LJ()};f.$classData=q({U7:0},!1,\"scala.collection.immutable.Nil$\",{U7:1,r7:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,KL:1,CG:1,TR:1,pS:1,g6:1,id:1,Cb:1,Uh:1,sg:1,l:1,E:1});var O$;\nfunction u(){O$||(O$=new N$);return O$}function P$(a,b){return b===a.Hf?a:sZ(new rZ,b,a.Xe)}function Uga(a,b){if(null===b)throw le();return b.sb?b.vb:me(b,new zV(a))}function sZ(a,b,c){a.Hf=b;a.Xe=c;if(null===c)throw oL(\"ordering must not be null\");return a}function xZ(a){var b=new rZ;sZ(b,null,a);return b}function rZ(){this.Xe=this.Hf=null}rZ.prototype=new b9;rZ.prototype.constructor=rZ;f=rZ.prototype;f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Oc=function(){return\"SortedSet\"};\nf.ti=function(){return new wZ(this.Xe)};f.se=function(){return this.Xe};f.ka=function(){return EI(nJ(),this.Hf)};f.b=function(){return 0===EI(nJ(),this.Hf)};f.e=function(){return hJ(nJ(),this.Hf).Wa};f.Mc=function(){return iJ(nJ(),this.Hf).Wa};f.aj=function(a){return a!==this.Xe||this.b()?u5(this,a):this.e()};f.$i=function(a){return a!==this.Xe||this.b()?v5(this,a):this.Mc()};f.Ca=function(a){var b=nJ(),c=this.Hf;null!==c&&oda(b,c,a)};\nf.m=function(){nJ();var a=this.Hf;nJ();var b=R();return new f4(a,b,this.Xe)};f.L=function(a){nJ();return null!==fJ(0,this.Hf,a,this.Xe)};function Vga(a,b){return P$(a,kJ(nJ(),a.Hf,new fn(c=>!!b.n(c))))}\nf.i=function(a){if(a instanceof rZ){var b=this.Xe,c=a.Xe;if(null===b?null===c:b.i(c)){nJ();b=this.Hf;a=a.Hf;c=this.Xe;var d;if(!(d=b===a)&&(d=null!==b)&&(d=null!==a)&&(d=(2147483647&b.ea)===(2147483647&a.ea))){b=new e4(b,c);a=new e4(a,c);for(c=!0;c&&null!==b.Hc&&null!==a.Hc;)b.Hc===a.Hc?(0===b.Wd?d=null:(b.Wd=-1+b.Wd|0,d=b.Cn.a[b.Wd]),b.Hc=d,0===a.Wd?d=null:(a.Wd=-1+a.Wd|0,d=a.Cn.a[a.Wd]),a.Hc=d):(c=Object.is(b.Hc.Wa,a.Hc.Wa)?!0:b.hw.Yi(b.Hc.Wa,a.Hc.Wa),b.Hc=r1(b,b.Hc.ta),a.Hc=r1(a,a.Hc.ta));d=c&&\nnull===b.Hc&&null===a.Hc}return d}}return O8(this,a)};f.Ih=function(){return\"TreeSet\"};f.vc=function(a){return qZ(zZ(),a,this.Xe)};f.Gk=function(a){return qZ(zZ(),a,this.Xe)};f.Fk=function(a){return Vga(this,a)};f.wy=function(a){a:{if(a instanceof rZ){var b=this.Xe,c=a.Xe;if(null===b?null===c:b.i(c)){b=nJ();a=pI(XI(b,this.Hf,a.Hf,this.Xe));a=P$(this,a);break a}}b=new $e;a=a.m();c=b.sb?b.vb:Uga(this,b);cH(a,c);a=P$(this,(b.sb?b.vb:Uga(this,b)).cH)}return a};\nf.Ce=function(a){a:{if(a instanceof rZ){var b=this.Xe,c=a.Xe;if(null===b?null===c:b.i(c)){a=mJ(nJ(),this.Hf,a.Hf,this.Xe);break a}}a=a.m();for(b=this.Hf;a.s();)b=gJ(nJ(),b,a.t(),null,!1,this.Xe);a=b}return P$(this,a)};f.Ek=function(a){var b=nJ();a=pI(PI(b,this.Hf,a,this.Xe));return P$(this,a)};f.bc=function(a){return P$(this,gJ(nJ(),this.Hf,a,null,!1,this.Xe))};\nf.Bb=function(a){var b=EI(nJ(),this.Hf)-(0<a?a:0)|0;if(0>=b)a=xZ(this.Xe);else if(b>=EI(nJ(),this.Hf))a=this;else{a=new rZ;var c=nJ();b=pI(HI(c,this.Hf,b));a=sZ(a,b,this.Xe)}return a};f.Jc=function(a){if(0>=a)var b=this;else if(a>=EI(nJ(),this.Hf))b=xZ(this.Xe);else{b=new rZ;var c=nJ();a=pI(GI(c,this.Hf,a));b=sZ(b,a,this.Xe)}return b};\nf.$classData=q({L8:0},!1,\"scala.collection.immutable.TreeSet\",{L8:1,Fr:1,rm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,fk:1,Cl:1,la:1,v:1,dq:1,xc:1,Rr:1,OL:1,PG:1,fS:1,Iy:1,eS:1,D8:1,Tba:1,Qba:1,i6:1,Cb:1,F8:1,sg:1,l:1});function Q$(){this.Z=this.R=null;this.ca=0;L$(this,JJ().PL,JJ().PL,0)}Q$.prototype=new M$;Q$.prototype.constructor=Q$;f=Q$.prototype;f.$r=function(a){throw this.rh(a);};f.hn=function(a){var b=new zc(1);b.a[0]=a;return new IJ(b)};f.zl=function(a){var b=new zc(1);b.a[0]=a;return new IJ(b)};\nf.Cm=function(){throw nv(\"empty.tail\");};f.Ln=function(){return this};f.On=function(){return 0};f.To=function(){return null};f.i=function(a){return this===a||!(a instanceof C1)&&i3(this,a)};f.ql=function(a){return pU(GK(),a)};f.rh=function(a){return aL(new bL,a+\" is out of bounds (empty vector)\")};f.f=function(){return this.Cm()};f.Ja=function(){return this};f.cc=function(a){return this.zl(a)};f.n=function(a){throw this.rh(a|0);};f.va=function(a){throw this.rh(a);};\nf.$classData=q({Q8:0},!1,\"scala.collection.immutable.Vector0$\",{Q8:1,fC:1,$y:1,Zy:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,sg:1,l:1});var R$;function HJ(){R$||(R$=new Q$);return R$}function KJ(a,b,c,d,e){this.Z=this.R=null;this.ca=0;this.Ri=b;this.yh=c;L$(this,a,d,e)}KJ.prototype=new M$;KJ.prototype.constructor=KJ;f=KJ.prototype;\nf.va=function(a){if(0<=a&&a<this.ca){var b=a-this.Ri|0;return 0<=b?(a=b>>>5|0,a<this.yh.a.length?this.yh.a[a].a[31&b]:this.Z.a[31&b]):this.R.a[a]}throw this.rh(a);};\nf.$r=function(a,b){if(0<=a&&a<this.ca){if(a>=this.Ri){var c=a-this.Ri|0;a=c>>>5|0;c&=31;if(a<this.yh.a.length){var d=this.yh.ia(),e=d.a[a].ia();e.a[c]=b;d.a[a]=e;return new KJ(this.R,this.Ri,d,this.Z,this.ca)}a=this.Z.ia();a.a[c]=b;return new KJ(this.R,this.Ri,this.yh,a,this.ca)}c=this.R.ia();c.a[a]=b;return new KJ(c,this.Ri,this.yh,this.Z,this.ca)}throw this.rh(a);};\nf.hn=function(a){if(32>this.Z.a.length)return a=RJ(JJ(),this.Z,a),new KJ(this.R,this.Ri,this.yh,a,1+this.ca|0);if(30>this.yh.a.length){var b=SJ(JJ(),this.yh,this.Z),c=new zc(1);c.a[0]=a;return new KJ(this.R,this.Ri,b,c,1+this.ca|0)}b=this.R;c=this.Ri;var d=this.yh,e=this.Ri,g=JJ().eg,h=this.Z,k=new (md(md(jd)).Ia)(1);k.a[0]=h;h=new zc(1);h.a[0]=a;return new LJ(b,c,d,960+e|0,g,k,h,1+this.ca|0)};\nf.zl=function(a){if(32>this.Ri){var b=TJ(JJ(),a,this.R);return new KJ(b,1+this.Ri|0,this.yh,this.Z,1+this.ca|0)}if(30>this.yh.a.length)return b=new zc(1),b.a[0]=a,a=UJ(JJ(),this.R,this.yh),new KJ(b,1,a,this.Z,1+this.ca|0);b=new zc(1);b.a[0]=a;a=this.R;var c=new (md(md(jd)).Ia)(1);c.a[0]=a;return new LJ(b,1,c,1+this.Ri|0,JJ().eg,this.yh,this.Z,1+this.ca|0)};f.yo=function(a){var b=WJ(JJ(),this.R,a),c=XJ(JJ(),2,this.yh,a);a=WJ(JJ(),this.Z,a);return new KJ(b,this.Ri,c,a,this.ca)};\nf.Ln=function(a,b){a=new FJ(a,b);GJ(a,1,this.R);GJ(a,2,this.yh);GJ(a,1,this.Z);return a.im()};f.Cm=function(){if(1<this.Ri){var a=this.R,b=a.a.length;a=Jj(Pj(),a,1,b);return new KJ(a,-1+this.Ri|0,this.yh,this.Z,-1+this.ca|0)}return this.Ln(1,this.ca)};f.On=function(){return 3};f.To=function(a){switch(a){case 0:return this.R;case 1:return this.yh;case 2:return this.Z;default:throw new w(a);}};\nf.ql=function(a,b){var c=YJ(JJ(),this.Z,a);return null!==c?new KJ(this.R,this.Ri,this.yh,c,(this.ca-this.Z.a.length|0)+c.a.length|0):C1.prototype.ql.call(this,a,b)};f.f=function(){return this.Cm()};f.Ja=function(a){return this.yo(a)};f.cc=function(a){return this.zl(a)};f.n=function(a){var b=a|0;if(0<=b&&b<this.ca)return a=b-this.Ri|0,0<=a?(b=a>>>5|0,b<this.yh.a.length?this.yh.a[b].a[31&a]:this.Z.a[31&a]):this.R.a[b];throw this.rh(b);};\nf.$classData=q({S8:0},!1,\"scala.collection.immutable.Vector2\",{S8:1,fC:1,$y:1,Zy:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,sg:1,l:1});function LJ(a,b,c,d,e,g,h,k){this.Z=this.R=null;this.ca=0;this.Vh=b;this.Wh=c;this.zh=d;this.cg=e;this.tg=g;L$(this,a,h,k)}LJ.prototype=new M$;LJ.prototype.constructor=LJ;f=LJ.prototype;\nf.va=function(a){if(0<=a&&a<this.ca){var b=a-this.zh|0;if(0<=b){a=b>>>10|0;var c=31&(b>>>5|0);b&=31;return a<this.cg.a.length?this.cg.a[a].a[c].a[b]:c<this.tg.a.length?this.tg.a[c].a[b]:this.Z.a[b]}return a>=this.Vh?(b=a-this.Vh|0,this.Wh.a[b>>>5|0].a[31&b]):this.R.a[a]}throw this.rh(a);};\nf.$r=function(a,b){if(0<=a&&a<this.ca){if(a>=this.zh){var c=a-this.zh|0,d=c>>>10|0;a=31&(c>>>5|0);c&=31;if(d<this.cg.a.length){var e=this.cg.ia(),g=e.a[d].ia(),h=g.a[a].ia();h.a[c]=b;g.a[a]=h;e.a[d]=g;return new LJ(this.R,this.Vh,this.Wh,this.zh,e,this.tg,this.Z,this.ca)}if(a<this.tg.a.length)return d=this.tg.ia(),e=d.a[a].ia(),e.a[c]=b,d.a[a]=e,new LJ(this.R,this.Vh,this.Wh,this.zh,this.cg,d,this.Z,this.ca);a=this.Z.ia();a.a[c]=b;return new LJ(this.R,this.Vh,this.Wh,this.zh,this.cg,this.tg,a,this.ca)}if(a>=\nthis.Vh)return c=a-this.Vh|0,a=c>>>5|0,c&=31,d=this.Wh.ia(),e=d.a[a].ia(),e.a[c]=b,d.a[a]=e,new LJ(this.R,this.Vh,d,this.zh,this.cg,this.tg,this.Z,this.ca);c=this.R.ia();c.a[a]=b;return new LJ(c,this.Vh,this.Wh,this.zh,this.cg,this.tg,this.Z,this.ca)}throw this.rh(a);};\nf.hn=function(a){if(32>this.Z.a.length)return a=RJ(JJ(),this.Z,a),new LJ(this.R,this.Vh,this.Wh,this.zh,this.cg,this.tg,a,1+this.ca|0);if(31>this.tg.a.length){var b=SJ(JJ(),this.tg,this.Z),c=new zc(1);c.a[0]=a;return new LJ(this.R,this.Vh,this.Wh,this.zh,this.cg,b,c,1+this.ca|0)}if(30>this.cg.a.length){b=SJ(JJ(),this.cg,SJ(JJ(),this.tg,this.Z));c=JJ().bd;var d=new zc(1);d.a[0]=a;return new LJ(this.R,this.Vh,this.Wh,this.zh,b,c,d,1+this.ca|0)}b=this.R;c=this.Vh;d=this.Wh;var e=this.zh,g=this.cg,h=\nthis.zh,k=JJ().jk,l=SJ(JJ(),this.tg,this.Z),m=new (md(md(md(jd))).Ia)(1);m.a[0]=l;l=JJ().bd;var n=new zc(1);n.a[0]=a;return new MJ(b,c,d,e,g,30720+h|0,k,m,l,n,1+this.ca|0)};\nf.zl=function(a){if(32>this.Vh){var b=TJ(JJ(),a,this.R);return new LJ(b,1+this.Vh|0,this.Wh,1+this.zh|0,this.cg,this.tg,this.Z,1+this.ca|0)}if(1024>this.zh)return b=new zc(1),b.a[0]=a,a=UJ(JJ(),this.R,this.Wh),new LJ(b,1,a,1+this.zh|0,this.cg,this.tg,this.Z,1+this.ca|0);if(30>this.cg.a.length){b=new zc(1);b.a[0]=a;a=JJ().bd;var c=UJ(JJ(),UJ(JJ(),this.R,this.Wh),this.cg);return new LJ(b,1,a,1,c,this.tg,this.Z,1+this.ca|0)}b=new zc(1);b.a[0]=a;a=JJ().bd;c=UJ(JJ(),this.R,this.Wh);var d=new (md(md(md(jd))).Ia)(1);\nd.a[0]=c;return new MJ(b,1,a,1,d,1+this.zh|0,JJ().jk,this.cg,this.tg,this.Z,1+this.ca|0)};f.yo=function(a){var b=WJ(JJ(),this.R,a),c=XJ(JJ(),2,this.Wh,a),d=XJ(JJ(),3,this.cg,a),e=XJ(JJ(),2,this.tg,a);a=WJ(JJ(),this.Z,a);return new LJ(b,this.Vh,c,this.zh,d,e,a,this.ca)};f.Ln=function(a,b){a=new FJ(a,b);GJ(a,1,this.R);GJ(a,2,this.Wh);GJ(a,3,this.cg);GJ(a,2,this.tg);GJ(a,1,this.Z);return a.im()};\nf.Cm=function(){if(1<this.Vh){var a=this.R,b=a.a.length;a=Jj(Pj(),a,1,b);return new LJ(a,-1+this.Vh|0,this.Wh,-1+this.zh|0,this.cg,this.tg,this.Z,-1+this.ca|0)}return this.Ln(1,this.ca)};f.On=function(){return 5};f.To=function(a){switch(a){case 0:return this.R;case 1:return this.Wh;case 2:return this.cg;case 3:return this.tg;case 4:return this.Z;default:throw new w(a);}};\nf.ql=function(a,b){var c=YJ(JJ(),this.Z,a);return null!==c?new LJ(this.R,this.Vh,this.Wh,this.zh,this.cg,this.tg,c,(this.ca-this.Z.a.length|0)+c.a.length|0):C1.prototype.ql.call(this,a,b)};f.f=function(){return this.Cm()};f.Ja=function(a){return this.yo(a)};f.cc=function(a){return this.zl(a)};\nf.n=function(a){var b=a|0;if(0<=b&&b<this.ca){a=b-this.zh|0;if(0<=a){b=a>>>10|0;var c=31&(a>>>5|0);a&=31;return b<this.cg.a.length?this.cg.a[b].a[c].a[a]:c<this.tg.a.length?this.tg.a[c].a[a]:this.Z.a[a]}return b>=this.Vh?(a=b-this.Vh|0,this.Wh.a[a>>>5|0].a[31&a]):this.R.a[b]}throw this.rh(b);};f.$classData=q({T8:0},!1,\"scala.collection.immutable.Vector3\",{T8:1,fC:1,$y:1,Zy:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,sg:1,l:1});\nfunction MJ(a,b,c,d,e,g,h,k,l,m,n){this.Z=this.R=null;this.ca=0;this.Ng=b;this.ug=c;this.Og=d;this.vg=e;this.dg=g;this.Ye=h;this.qf=k;this.pf=l;L$(this,a,m,n)}MJ.prototype=new M$;MJ.prototype.constructor=MJ;f=MJ.prototype;\nf.va=function(a){if(0<=a&&a<this.ca){var b=a-this.dg|0;if(0<=b){a=b>>>15|0;var c=31&(b>>>10|0),d=31&(b>>>5|0);b&=31;return a<this.Ye.a.length?this.Ye.a[a].a[c].a[d].a[b]:c<this.qf.a.length?this.qf.a[c].a[d].a[b]:d<this.pf.a.length?this.pf.a[d].a[b]:this.Z.a[b]}return a>=this.Og?(b=a-this.Og|0,this.vg.a[b>>>10|0].a[31&(b>>>5|0)].a[31&b]):a>=this.Ng?(b=a-this.Ng|0,this.ug.a[b>>>5|0].a[31&b]):this.R.a[a]}throw this.rh(a);};\nf.$r=function(a,b){if(0<=a&&a<this.ca){if(a>=this.dg){var c=a-this.dg|0,d=c>>>15|0,e=31&(c>>>10|0);a=31&(c>>>5|0);c&=31;if(d<this.Ye.a.length){var g=this.Ye.ia(),h=g.a[d].ia(),k=h.a[e].ia(),l=k.a[a].ia();l.a[c]=b;k.a[a]=l;h.a[e]=k;g.a[d]=h;return new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,g,this.qf,this.pf,this.Z,this.ca)}if(e<this.qf.a.length)return d=this.qf.ia(),g=d.a[e].ia(),h=g.a[a].ia(),h.a[c]=b,g.a[a]=h,d.a[e]=g,new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,d,this.pf,\nthis.Z,this.ca);if(a<this.pf.a.length)return e=this.pf.ia(),d=e.a[a].ia(),d.a[c]=b,e.a[a]=d,new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,this.qf,e,this.Z,this.ca);a=this.Z.ia();a.a[c]=b;return new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,this.qf,this.pf,a,this.ca)}if(a>=this.Og)return e=a-this.Og|0,a=e>>>10|0,c=31&(e>>>5|0),e&=31,d=this.vg.ia(),g=d.a[a].ia(),h=g.a[c].ia(),h.a[e]=b,g.a[c]=h,d.a[a]=g,new MJ(this.R,this.Ng,this.ug,this.Og,d,this.dg,this.Ye,this.qf,this.pf,\nthis.Z,this.ca);if(a>=this.Ng)return c=a-this.Ng|0,a=c>>>5|0,c&=31,e=this.ug.ia(),d=e.a[a].ia(),d.a[c]=b,e.a[a]=d,new MJ(this.R,this.Ng,e,this.Og,this.vg,this.dg,this.Ye,this.qf,this.pf,this.Z,this.ca);c=this.R.ia();c.a[a]=b;return new MJ(c,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,this.qf,this.pf,this.Z,this.ca)}throw this.rh(a);};\nf.hn=function(a){if(32>this.Z.a.length)return a=RJ(JJ(),this.Z,a),new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,this.qf,this.pf,a,1+this.ca|0);if(31>this.pf.a.length){var b=SJ(JJ(),this.pf,this.Z),c=new zc(1);c.a[0]=a;return new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,this.qf,b,c,1+this.ca|0)}if(31>this.qf.a.length){b=SJ(JJ(),this.qf,SJ(JJ(),this.pf,this.Z));c=JJ().bd;var d=new zc(1);d.a[0]=a;return new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,b,\nc,d,1+this.ca|0)}if(30>this.Ye.a.length){b=SJ(JJ(),this.Ye,SJ(JJ(),this.qf,SJ(JJ(),this.pf,this.Z)));c=JJ().eg;d=JJ().bd;var e=new zc(1);e.a[0]=a;return new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,b,c,d,e,1+this.ca|0)}b=this.R;c=this.Ng;d=this.ug;e=this.Og;var g=this.vg,h=this.dg,k=this.Ye,l=this.dg,m=JJ().du,n=SJ(JJ(),this.qf,SJ(JJ(),this.pf,this.Z)),r=new (md(md(md(md(jd)))).Ia)(1);r.a[0]=n;n=JJ().eg;var v=JJ().bd,x=new zc(1);x.a[0]=a;return new NJ(b,c,d,e,g,h,k,983040+l|0,m,r,n,v,x,1+\nthis.ca|0)};\nf.zl=function(a){if(32>this.Ng){var b=TJ(JJ(),a,this.R);return new MJ(b,1+this.Ng|0,this.ug,1+this.Og|0,this.vg,1+this.dg|0,this.Ye,this.qf,this.pf,this.Z,1+this.ca|0)}if(1024>this.Og)return b=new zc(1),b.a[0]=a,a=UJ(JJ(),this.R,this.ug),new MJ(b,1,a,1+this.Og|0,this.vg,1+this.dg|0,this.Ye,this.qf,this.pf,this.Z,1+this.ca|0);if(32768>this.dg){b=new zc(1);b.a[0]=a;a=JJ().bd;var c=UJ(JJ(),UJ(JJ(),this.R,this.ug),this.vg);return new MJ(b,1,a,1,c,1+this.dg|0,this.Ye,this.qf,this.pf,this.Z,1+this.ca|0)}if(30>\nthis.Ye.a.length){b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;var d=UJ(JJ(),UJ(JJ(),UJ(JJ(),this.R,this.ug),this.vg),this.Ye);return new MJ(b,1,a,1,c,1,d,this.qf,this.pf,this.Z,1+this.ca|0)}b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;d=UJ(JJ(),UJ(JJ(),this.R,this.ug),this.vg);var e=new (md(md(md(md(jd)))).Ia)(1);e.a[0]=d;return new NJ(b,1,a,1,c,1,e,1+this.dg|0,JJ().du,this.Ye,this.qf,this.pf,this.Z,1+this.ca|0)};\nf.yo=function(a){var b=WJ(JJ(),this.R,a),c=XJ(JJ(),2,this.ug,a),d=XJ(JJ(),3,this.vg,a),e=XJ(JJ(),4,this.Ye,a),g=XJ(JJ(),3,this.qf,a),h=XJ(JJ(),2,this.pf,a);a=WJ(JJ(),this.Z,a);return new MJ(b,this.Ng,c,this.Og,d,this.dg,e,g,h,a,this.ca)};f.Ln=function(a,b){a=new FJ(a,b);GJ(a,1,this.R);GJ(a,2,this.ug);GJ(a,3,this.vg);GJ(a,4,this.Ye);GJ(a,3,this.qf);GJ(a,2,this.pf);GJ(a,1,this.Z);return a.im()};\nf.Cm=function(){if(1<this.Ng){var a=this.R,b=a.a.length;a=Jj(Pj(),a,1,b);return new MJ(a,-1+this.Ng|0,this.ug,-1+this.Og|0,this.vg,-1+this.dg|0,this.Ye,this.qf,this.pf,this.Z,-1+this.ca|0)}return this.Ln(1,this.ca)};f.On=function(){return 7};f.To=function(a){switch(a){case 0:return this.R;case 1:return this.ug;case 2:return this.vg;case 3:return this.Ye;case 4:return this.qf;case 5:return this.pf;case 6:return this.Z;default:throw new w(a);}};\nf.ql=function(a,b){var c=YJ(JJ(),this.Z,a);return null!==c?new MJ(this.R,this.Ng,this.ug,this.Og,this.vg,this.dg,this.Ye,this.qf,this.pf,c,(this.ca-this.Z.a.length|0)+c.a.length|0):C1.prototype.ql.call(this,a,b)};f.f=function(){return this.Cm()};f.Ja=function(a){return this.yo(a)};f.cc=function(a){return this.zl(a)};\nf.n=function(a){var b=a|0;if(0<=b&&b<this.ca){a=b-this.dg|0;if(0<=a){b=a>>>15|0;var c=31&(a>>>10|0),d=31&(a>>>5|0);a&=31;return b<this.Ye.a.length?this.Ye.a[b].a[c].a[d].a[a]:c<this.qf.a.length?this.qf.a[c].a[d].a[a]:d<this.pf.a.length?this.pf.a[d].a[a]:this.Z.a[a]}return b>=this.Og?(a=b-this.Og|0,this.vg.a[a>>>10|0].a[31&(a>>>5|0)].a[31&a]):b>=this.Ng?(a=b-this.Ng|0,this.ug.a[a>>>5|0].a[31&a]):this.R.a[b]}throw this.rh(b);};\nf.$classData=q({U8:0},!1,\"scala.collection.immutable.Vector4\",{U8:1,fC:1,$y:1,Zy:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,sg:1,l:1});function NJ(a,b,c,d,e,g,h,k,l,m,n,r,v,x){this.Z=this.R=null;this.ca=0;this.Vf=b;this.rf=c;this.Wf=d;this.sf=e;this.If=g;this.tf=h;this.Ze=k;this.Xd=l;this.ge=m;this.fe=n;this.ee=r;L$(this,a,v,x)}NJ.prototype=new M$;NJ.prototype.constructor=NJ;f=NJ.prototype;\nf.va=function(a){if(0<=a&&a<this.ca){var b=a-this.Ze|0;if(0<=b){a=b>>>20|0;var c=31&(b>>>15|0),d=31&(b>>>10|0),e=31&(b>>>5|0);b&=31;return a<this.Xd.a.length?this.Xd.a[a].a[c].a[d].a[e].a[b]:c<this.ge.a.length?this.ge.a[c].a[d].a[e].a[b]:d<this.fe.a.length?this.fe.a[d].a[e].a[b]:e<this.ee.a.length?this.ee.a[e].a[b]:this.Z.a[b]}return a>=this.If?(b=a-this.If|0,this.tf.a[b>>>15|0].a[31&(b>>>10|0)].a[31&(b>>>5|0)].a[31&b]):a>=this.Wf?(b=a-this.Wf|0,this.sf.a[b>>>10|0].a[31&(b>>>5|0)].a[31&b]):a>=this.Vf?\n(b=a-this.Vf|0,this.rf.a[b>>>5|0].a[31&b]):this.R.a[a]}throw this.rh(a);};\nf.$r=function(a,b){if(0<=a&&a<this.ca){if(a>=this.Ze){var c=a-this.Ze|0,d=c>>>20|0,e=31&(c>>>15|0),g=31&(c>>>10|0);a=31&(c>>>5|0);c&=31;if(d<this.Xd.a.length){var h=this.Xd.ia(),k=h.a[d].ia(),l=k.a[e].ia(),m=l.a[g].ia(),n=m.a[a].ia();n.a[c]=b;m.a[a]=n;l.a[g]=m;k.a[e]=l;h.a[d]=k;return new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,h,this.ge,this.fe,this.ee,this.Z,this.ca)}if(e<this.ge.a.length)return d=this.ge.ia(),h=d.a[e].ia(),k=h.a[g].ia(),l=k.a[a].ia(),l.a[c]=b,k.a[a]=l,\nh.a[g]=k,d.a[e]=h,new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,d,this.fe,this.ee,this.Z,this.ca);if(g<this.fe.a.length)return e=this.fe.ia(),d=e.a[g].ia(),h=d.a[a].ia(),h.a[c]=b,d.a[a]=h,e.a[g]=d,new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,e,this.ee,this.Z,this.ca);if(a<this.ee.a.length)return g=this.ee.ia(),e=g.a[a].ia(),e.a[c]=b,g.a[a]=e,new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,\nthis.fe,g,this.Z,this.ca);a=this.Z.ia();a.a[c]=b;return new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,this.fe,this.ee,a,this.ca)}if(a>=this.If)return e=a-this.If|0,a=e>>>15|0,c=31&(e>>>10|0),g=31&(e>>>5|0),e&=31,d=this.tf.ia(),h=d.a[a].ia(),k=h.a[c].ia(),l=k.a[g].ia(),l.a[e]=b,k.a[g]=l,h.a[c]=k,d.a[a]=h,new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,d,this.Ze,this.Xd,this.ge,this.fe,this.ee,this.Z,this.ca);if(a>=this.Wf)return g=a-this.Wf|0,a=g>>>10|\n0,c=31&(g>>>5|0),g&=31,e=this.sf.ia(),d=e.a[a].ia(),h=d.a[c].ia(),h.a[g]=b,d.a[c]=h,e.a[a]=d,new NJ(this.R,this.Vf,this.rf,this.Wf,e,this.If,this.tf,this.Ze,this.Xd,this.ge,this.fe,this.ee,this.Z,this.ca);if(a>=this.Vf)return c=a-this.Vf|0,a=c>>>5|0,c&=31,g=this.rf.ia(),e=g.a[a].ia(),e.a[c]=b,g.a[a]=e,new NJ(this.R,this.Vf,g,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,this.fe,this.ee,this.Z,this.ca);c=this.R.ia();c.a[a]=b;return new NJ(c,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,\nthis.Ze,this.Xd,this.ge,this.fe,this.ee,this.Z,this.ca)}throw this.rh(a);};\nf.hn=function(a){if(32>this.Z.a.length)return a=RJ(JJ(),this.Z,a),new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,this.fe,this.ee,a,1+this.ca|0);if(31>this.ee.a.length){var b=SJ(JJ(),this.ee,this.Z),c=new zc(1);c.a[0]=a;return new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,this.fe,b,c,1+this.ca|0)}if(31>this.fe.a.length){b=SJ(JJ(),this.fe,SJ(JJ(),this.ee,this.Z));c=JJ().bd;var d=new zc(1);d.a[0]=a;return new NJ(this.R,this.Vf,\nthis.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,b,c,d,1+this.ca|0)}if(31>this.ge.a.length){b=SJ(JJ(),this.ge,SJ(JJ(),this.fe,SJ(JJ(),this.ee,this.Z)));c=JJ().eg;d=JJ().bd;var e=new zc(1);e.a[0]=a;return new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,b,c,d,e,1+this.ca|0)}if(30>this.Xd.a.length){b=SJ(JJ(),this.Xd,SJ(JJ(),this.ge,SJ(JJ(),this.fe,SJ(JJ(),this.ee,this.Z))));c=JJ().jk;d=JJ().eg;e=JJ().bd;var g=new zc(1);g.a[0]=a;return new NJ(this.R,this.Vf,\nthis.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,b,c,d,e,g,1+this.ca|0)}b=this.R;c=this.Vf;d=this.rf;e=this.Wf;g=this.sf;var h=this.If,k=this.tf,l=this.Ze,m=this.Xd,n=this.Ze,r=JJ().dH,v=SJ(JJ(),this.ge,SJ(JJ(),this.fe,SJ(JJ(),this.ee,this.Z))),x=new (md(md(md(md(md(jd))))).Ia)(1);x.a[0]=v;v=JJ().jk;var A=JJ().eg,B=JJ().bd,C=new zc(1);C.a[0]=a;return new OJ(b,c,d,e,g,h,k,l,m,31457280+n|0,r,x,v,A,B,C,1+this.ca|0)};\nf.zl=function(a){if(32>this.Vf){var b=TJ(JJ(),a,this.R);return new NJ(b,1+this.Vf|0,this.rf,1+this.Wf|0,this.sf,1+this.If|0,this.tf,1+this.Ze|0,this.Xd,this.ge,this.fe,this.ee,this.Z,1+this.ca|0)}if(1024>this.Wf)return b=new zc(1),b.a[0]=a,a=UJ(JJ(),this.R,this.rf),new NJ(b,1,a,1+this.Wf|0,this.sf,1+this.If|0,this.tf,1+this.Ze|0,this.Xd,this.ge,this.fe,this.ee,this.Z,1+this.ca|0);if(32768>this.If){b=new zc(1);b.a[0]=a;a=JJ().bd;var c=UJ(JJ(),UJ(JJ(),this.R,this.rf),this.sf);return new NJ(b,1,a,1,\nc,1+this.If|0,this.tf,1+this.Ze|0,this.Xd,this.ge,this.fe,this.ee,this.Z,1+this.ca|0)}if(1048576>this.Ze){b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;var d=UJ(JJ(),UJ(JJ(),UJ(JJ(),this.R,this.rf),this.sf),this.tf);return new NJ(b,1,a,1,c,1,d,1+this.Ze|0,this.Xd,this.ge,this.fe,this.ee,this.Z,1+this.ca|0)}if(30>this.Xd.a.length){b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;d=JJ().jk;var e=UJ(JJ(),UJ(JJ(),UJ(JJ(),UJ(JJ(),this.R,this.rf),this.sf),this.tf),this.Xd);return new NJ(b,1,a,1,c,1,d,1,e,this.ge,this.fe,\nthis.ee,this.Z,1+this.ca|0)}b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;d=JJ().jk;e=UJ(JJ(),UJ(JJ(),UJ(JJ(),this.R,this.rf),this.sf),this.tf);var g=new (md(md(md(md(md(jd))))).Ia)(1);g.a[0]=e;return new OJ(b,1,a,1,c,1,d,1,g,1+this.Ze|0,JJ().dH,this.Xd,this.ge,this.fe,this.ee,this.Z,1+this.ca|0)};\nf.yo=function(a){var b=WJ(JJ(),this.R,a),c=XJ(JJ(),2,this.rf,a),d=XJ(JJ(),3,this.sf,a),e=XJ(JJ(),4,this.tf,a),g=XJ(JJ(),5,this.Xd,a),h=XJ(JJ(),4,this.ge,a),k=XJ(JJ(),3,this.fe,a),l=XJ(JJ(),2,this.ee,a);a=WJ(JJ(),this.Z,a);return new NJ(b,this.Vf,c,this.Wf,d,this.If,e,this.Ze,g,h,k,l,a,this.ca)};f.Ln=function(a,b){a=new FJ(a,b);GJ(a,1,this.R);GJ(a,2,this.rf);GJ(a,3,this.sf);GJ(a,4,this.tf);GJ(a,5,this.Xd);GJ(a,4,this.ge);GJ(a,3,this.fe);GJ(a,2,this.ee);GJ(a,1,this.Z);return a.im()};\nf.Cm=function(){if(1<this.Vf){var a=this.R,b=a.a.length;a=Jj(Pj(),a,1,b);return new NJ(a,-1+this.Vf|0,this.rf,-1+this.Wf|0,this.sf,-1+this.If|0,this.tf,-1+this.Ze|0,this.Xd,this.ge,this.fe,this.ee,this.Z,-1+this.ca|0)}return this.Ln(1,this.ca)};f.On=function(){return 9};\nf.To=function(a){switch(a){case 0:return this.R;case 1:return this.rf;case 2:return this.sf;case 3:return this.tf;case 4:return this.Xd;case 5:return this.ge;case 6:return this.fe;case 7:return this.ee;case 8:return this.Z;default:throw new w(a);}};f.ql=function(a,b){var c=YJ(JJ(),this.Z,a);return null!==c?new NJ(this.R,this.Vf,this.rf,this.Wf,this.sf,this.If,this.tf,this.Ze,this.Xd,this.ge,this.fe,this.ee,c,(this.ca-this.Z.a.length|0)+c.a.length|0):C1.prototype.ql.call(this,a,b)};f.f=function(){return this.Cm()};\nf.Ja=function(a){return this.yo(a)};f.cc=function(a){return this.zl(a)};\nf.n=function(a){var b=a|0;if(0<=b&&b<this.ca){a=b-this.Ze|0;if(0<=a){b=a>>>20|0;var c=31&(a>>>15|0),d=31&(a>>>10|0),e=31&(a>>>5|0);a&=31;return b<this.Xd.a.length?this.Xd.a[b].a[c].a[d].a[e].a[a]:c<this.ge.a.length?this.ge.a[c].a[d].a[e].a[a]:d<this.fe.a.length?this.fe.a[d].a[e].a[a]:e<this.ee.a.length?this.ee.a[e].a[a]:this.Z.a[a]}return b>=this.If?(a=b-this.If|0,this.tf.a[a>>>15|0].a[31&(a>>>10|0)].a[31&(a>>>5|0)].a[31&a]):b>=this.Wf?(a=b-this.Wf|0,this.sf.a[a>>>10|0].a[31&(a>>>5|0)].a[31&a]):b>=\nthis.Vf?(a=b-this.Vf|0,this.rf.a[a>>>5|0].a[31&a]):this.R.a[b]}throw this.rh(b);};f.$classData=q({V8:0},!1,\"scala.collection.immutable.Vector5\",{V8:1,fC:1,$y:1,Zy:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,sg:1,l:1});\nfunction OJ(a,b,c,d,e,g,h,k,l,m,n,r,v,x,A,B,C){this.Z=this.R=null;this.ca=0;this.uf=b;this.Ge=c;this.vf=d;this.He=e;this.$e=g;this.Ie=h;this.Ee=k;this.Je=l;this.Fe=m;this.rd=n;this.Nd=r;this.Md=v;this.Ld=x;this.Kd=A;L$(this,a,B,C)}OJ.prototype=new M$;OJ.prototype.constructor=OJ;f=OJ.prototype;\nf.va=function(a){if(0<=a&&a<this.ca){var b=a-this.Fe|0;if(0<=b){a=b>>>25|0;var c=31&(b>>>20|0),d=31&(b>>>15|0),e=31&(b>>>10|0),g=31&(b>>>5|0);b&=31;return a<this.rd.a.length?this.rd.a[a].a[c].a[d].a[e].a[g].a[b]:c<this.Nd.a.length?this.Nd.a[c].a[d].a[e].a[g].a[b]:d<this.Md.a.length?this.Md.a[d].a[e].a[g].a[b]:e<this.Ld.a.length?this.Ld.a[e].a[g].a[b]:g<this.Kd.a.length?this.Kd.a[g].a[b]:this.Z.a[b]}return a>=this.Ee?(b=a-this.Ee|0,this.Je.a[b>>>20|0].a[31&(b>>>15|0)].a[31&(b>>>10|0)].a[31&(b>>>5|\n0)].a[31&b]):a>=this.$e?(b=a-this.$e|0,this.Ie.a[b>>>15|0].a[31&(b>>>10|0)].a[31&(b>>>5|0)].a[31&b]):a>=this.vf?(b=a-this.vf|0,this.He.a[b>>>10|0].a[31&(b>>>5|0)].a[31&b]):a>=this.uf?(b=a-this.uf|0,this.Ge.a[b>>>5|0].a[31&b]):this.R.a[a]}throw this.rh(a);};\nf.$r=function(a,b){if(0<=a&&a<this.ca){if(a>=this.Fe){var c=a-this.Fe|0,d=c>>>25|0,e=31&(c>>>20|0),g=31&(c>>>15|0),h=31&(c>>>10|0);a=31&(c>>>5|0);c&=31;if(d<this.rd.a.length){var k=this.rd.ia(),l=k.a[d].ia(),m=l.a[e].ia(),n=m.a[g].ia(),r=n.a[h].ia(),v=r.a[a].ia();v.a[c]=b;r.a[a]=v;n.a[h]=r;m.a[g]=n;l.a[e]=m;k.a[d]=l;return new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,k,this.Nd,this.Md,this.Ld,this.Kd,this.Z,this.ca)}if(e<this.Nd.a.length)return d=this.Nd.ia(),\nk=d.a[e].ia(),l=k.a[g].ia(),m=l.a[h].ia(),n=m.a[a].ia(),n.a[c]=b,m.a[a]=n,l.a[h]=m,k.a[g]=l,d.a[e]=k,new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,d,this.Md,this.Ld,this.Kd,this.Z,this.ca);if(g<this.Md.a.length)return e=this.Md.ia(),d=e.a[g].ia(),k=d.a[h].ia(),l=k.a[a].ia(),l.a[c]=b,k.a[a]=l,d.a[h]=k,e.a[g]=d,new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,e,this.Ld,this.Kd,this.Z,this.ca);if(h<this.Ld.a.length)return g=\nthis.Ld.ia(),e=g.a[h].ia(),d=e.a[a].ia(),d.a[c]=b,e.a[a]=d,g.a[h]=e,new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,g,this.Kd,this.Z,this.ca);if(a<this.Kd.a.length)return h=this.Kd.ia(),g=h.a[a].ia(),g.a[c]=b,h.a[a]=g,new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,h,this.Z,this.ca);a=this.Z.ia();a.a[c]=b;return new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,\nthis.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,a,this.ca)}if(a>=this.Ee)return e=a-this.Ee|0,a=e>>>20|0,c=31&(e>>>15|0),h=31&(e>>>10|0),g=31&(e>>>5|0),e&=31,d=this.Je.ia(),k=d.a[a].ia(),l=k.a[c].ia(),m=l.a[h].ia(),n=m.a[g].ia(),n.a[e]=b,m.a[g]=n,l.a[h]=m,k.a[c]=l,d.a[a]=k,new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,d,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,this.ca);if(a>=this.$e)return g=a-this.$e|0,a=g>>>15|0,c=31&(g>>>10|0),h=31&(g>>>5|0),\ng&=31,e=this.Ie.ia(),d=e.a[a].ia(),k=d.a[c].ia(),l=k.a[h].ia(),l.a[g]=b,k.a[h]=l,d.a[c]=k,e.a[a]=d,new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,e,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,this.ca);if(a>=this.vf)return h=a-this.vf|0,a=h>>>10|0,c=31&(h>>>5|0),h&=31,g=this.He.ia(),e=g.a[a].ia(),d=e.a[c].ia(),d.a[h]=b,e.a[c]=d,g.a[a]=e,new OJ(this.R,this.uf,this.Ge,this.vf,g,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,this.ca);\nif(a>=this.uf)return c=a-this.uf|0,a=c>>>5|0,c&=31,h=this.Ge.ia(),g=h.a[a].ia(),g.a[c]=b,h.a[a]=g,new OJ(this.R,this.uf,h,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,this.ca);c=this.R.ia();c.a[a]=b;return new OJ(c,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,this.ca)}throw this.rh(a);};\nf.hn=function(a){if(32>this.Z.a.length)return a=RJ(JJ(),this.Z,a),new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,a,1+this.ca|0);if(31>this.Kd.a.length){var b=SJ(JJ(),this.Kd,this.Z),c=new zc(1);c.a[0]=a;return new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,b,c,1+this.ca|0)}if(31>this.Ld.a.length){b=SJ(JJ(),this.Ld,SJ(JJ(),this.Kd,this.Z));c=JJ().bd;\nvar d=new zc(1);d.a[0]=a;return new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,b,c,d,1+this.ca|0)}if(31>this.Md.a.length){b=SJ(JJ(),this.Md,SJ(JJ(),this.Ld,SJ(JJ(),this.Kd,this.Z)));c=JJ().eg;d=JJ().bd;var e=new zc(1);e.a[0]=a;return new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,b,c,d,e,1+this.ca|0)}if(31>this.Nd.a.length){b=SJ(JJ(),this.Nd,SJ(JJ(),this.Md,SJ(JJ(),this.Ld,SJ(JJ(),\nthis.Kd,this.Z))));c=JJ().jk;d=JJ().eg;e=JJ().bd;var g=new zc(1);g.a[0]=a;return new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,b,c,d,e,g,1+this.ca|0)}if(62>this.rd.a.length){b=SJ(JJ(),this.rd,SJ(JJ(),this.Nd,SJ(JJ(),this.Md,SJ(JJ(),this.Ld,SJ(JJ(),this.Kd,this.Z)))));c=JJ().du;d=JJ().jk;e=JJ().eg;g=JJ().bd;var h=new zc(1);h.a[0]=a;return new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,b,c,d,e,g,h,1+this.ca|0)}throw UL();\n};\nf.zl=function(a){if(32>this.uf){var b=TJ(JJ(),a,this.R);return new OJ(b,1+this.uf|0,this.Ge,1+this.vf|0,this.He,1+this.$e|0,this.Ie,1+this.Ee|0,this.Je,1+this.Fe|0,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,1+this.ca|0)}if(1024>this.vf)return b=new zc(1),b.a[0]=a,a=UJ(JJ(),this.R,this.Ge),new OJ(b,1,a,1+this.vf|0,this.He,1+this.$e|0,this.Ie,1+this.Ee|0,this.Je,1+this.Fe|0,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,1+this.ca|0);if(32768>this.$e){b=new zc(1);b.a[0]=a;a=JJ().bd;var c=UJ(JJ(),UJ(JJ(),\nthis.R,this.Ge),this.He);return new OJ(b,1,a,1,c,1+this.$e|0,this.Ie,1+this.Ee|0,this.Je,1+this.Fe|0,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,1+this.ca|0)}if(1048576>this.Ee){b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;var d=UJ(JJ(),UJ(JJ(),UJ(JJ(),this.R,this.Ge),this.He),this.Ie);return new OJ(b,1,a,1,c,1,d,1+this.Ee|0,this.Je,1+this.Fe|0,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,1+this.ca|0)}if(33554432>this.Fe){b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;d=JJ().jk;var e=UJ(JJ(),UJ(JJ(),UJ(JJ(),\nUJ(JJ(),this.R,this.Ge),this.He),this.Ie),this.Je);return new OJ(b,1,a,1,c,1,d,1,e,1+this.Fe|0,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,1+this.ca|0)}if(62>this.rd.a.length){b=new zc(1);b.a[0]=a;a=JJ().bd;c=JJ().eg;d=JJ().jk;e=JJ().du;var g=UJ(JJ(),UJ(JJ(),UJ(JJ(),UJ(JJ(),UJ(JJ(),this.R,this.Ge),this.He),this.Ie),this.Je),this.rd);return new OJ(b,1,a,1,c,1,d,1,e,1,g,this.Nd,this.Md,this.Ld,this.Kd,this.Z,1+this.ca|0)}throw UL();};\nf.yo=function(a){var b=WJ(JJ(),this.R,a),c=XJ(JJ(),2,this.Ge,a),d=XJ(JJ(),3,this.He,a),e=XJ(JJ(),4,this.Ie,a),g=XJ(JJ(),5,this.Je,a),h=XJ(JJ(),6,this.rd,a),k=XJ(JJ(),5,this.Nd,a),l=XJ(JJ(),4,this.Md,a),m=XJ(JJ(),3,this.Ld,a),n=XJ(JJ(),2,this.Kd,a);a=WJ(JJ(),this.Z,a);return new OJ(b,this.uf,c,this.vf,d,this.$e,e,this.Ee,g,this.Fe,h,k,l,m,n,a,this.ca)};\nf.Ln=function(a,b){a=new FJ(a,b);GJ(a,1,this.R);GJ(a,2,this.Ge);GJ(a,3,this.He);GJ(a,4,this.Ie);GJ(a,5,this.Je);GJ(a,6,this.rd);GJ(a,5,this.Nd);GJ(a,4,this.Md);GJ(a,3,this.Ld);GJ(a,2,this.Kd);GJ(a,1,this.Z);return a.im()};f.Cm=function(){if(1<this.uf){var a=this.R,b=a.a.length;a=Jj(Pj(),a,1,b);return new OJ(a,-1+this.uf|0,this.Ge,-1+this.vf|0,this.He,-1+this.$e|0,this.Ie,-1+this.Ee|0,this.Je,-1+this.Fe|0,this.rd,this.Nd,this.Md,this.Ld,this.Kd,this.Z,-1+this.ca|0)}return this.Ln(1,this.ca)};\nf.On=function(){return 11};f.To=function(a){switch(a){case 0:return this.R;case 1:return this.Ge;case 2:return this.He;case 3:return this.Ie;case 4:return this.Je;case 5:return this.rd;case 6:return this.Nd;case 7:return this.Md;case 8:return this.Ld;case 9:return this.Kd;case 10:return this.Z;default:throw new w(a);}};\nf.ql=function(a,b){var c=YJ(JJ(),this.Z,a);return null!==c?new OJ(this.R,this.uf,this.Ge,this.vf,this.He,this.$e,this.Ie,this.Ee,this.Je,this.Fe,this.rd,this.Nd,this.Md,this.Ld,this.Kd,c,(this.ca-this.Z.a.length|0)+c.a.length|0):C1.prototype.ql.call(this,a,b)};f.f=function(){return this.Cm()};f.Ja=function(a){return this.yo(a)};f.cc=function(a){return this.zl(a)};\nf.n=function(a){var b=a|0;if(0<=b&&b<this.ca){a=b-this.Fe|0;if(0<=a){b=a>>>25|0;var c=31&(a>>>20|0),d=31&(a>>>15|0),e=31&(a>>>10|0),g=31&(a>>>5|0);a&=31;return b<this.rd.a.length?this.rd.a[b].a[c].a[d].a[e].a[g].a[a]:c<this.Nd.a.length?this.Nd.a[c].a[d].a[e].a[g].a[a]:d<this.Md.a.length?this.Md.a[d].a[e].a[g].a[a]:e<this.Ld.a.length?this.Ld.a[e].a[g].a[a]:g<this.Kd.a.length?this.Kd.a[g].a[a]:this.Z.a[a]}return b>=this.Ee?(a=b-this.Ee|0,this.Je.a[a>>>20|0].a[31&(a>>>15|0)].a[31&(a>>>10|0)].a[31&(a>>>\n5|0)].a[31&a]):b>=this.$e?(a=b-this.$e|0,this.Ie.a[a>>>15|0].a[31&(a>>>10|0)].a[31&(a>>>5|0)].a[31&a]):b>=this.vf?(a=b-this.vf|0,this.He.a[a>>>10|0].a[31&(a>>>5|0)].a[31&a]):b>=this.uf?(a=b-this.uf|0,this.Ge.a[a>>>5|0].a[31&a]):this.R.a[b]}throw this.rh(b);};f.$classData=q({W8:0},!1,\"scala.collection.immutable.Vector6\",{W8:1,fC:1,$y:1,Zy:1,vh:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,Mg:1,xc:1,Yg:1,Sh:1,hd:1,Vb:1,wi:1,Uh:1,id:1,Cb:1,sg:1,l:1});\nfunction ce(){var a=new S$;a.yf=LQ(new Sq);return a}function S$(){this.yf=null}S$.prototype=new D9;S$.prototype.constructor=S$;f=S$.prototype;f.Oc=function(){return\"IndexedSeq\"};f.m=function(){var a=new QX(this);return Kr(new Lr,a)};f.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.cc=function(a){return n0(this,a)};f.Jc=function(a){return q0(this,a)};f.Bb=function(a){return this.vc(X8(new Y8,this,a))};\nf.Ja=function(a){return t0(this,a)};f.e=function(){return hc(this.yf.ja.charCodeAt(0))};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.yf.K();return b===a?0:b<a?-1:1};f.he=function(){};f.zc=function(a){return lR(this,a)};f.ti=function(){return PV(new QV,ce())};f.K=function(){return this.yf.K()};f.Q=function(){return this.yf.K()};function ee(a,b){a=a.yf;a.ja=\"\"+a.ja+b}f.u=function(){return this.yf.ja};\nf.Bj=function(a){if(a.uh()===da(td)){a=this.yf.K();var b=new Ic(a);L2(this.yf.ja,a,b,0);a=b}else a=kB(this,a);return a};function Wga(a,b){if(b instanceof Jr){var c=a.yf;DZ();c.ja=\"\"+c.ja+b.Xh}else if(b instanceof AQ)mW(a.yf,b.En);else if(b instanceof S$)c=a.yf,c.ja=\"\"+c.ja+b.yf;else{var d=b.Q();if(0!==d)for(c=a.yf,0<d&&c.K(),b=b.m();b.s();)d=Ea(b.t()),d=String.fromCharCode(d),c.ja=\"\"+c.ja+d}return a}f.eM=function(a,b){return this.yf.ja.substring(a,b)};f.b=function(){return 0===this.yf.K()};\nf.Ub=function(){g2||(g2=new f2);return g2};f.Kb=function(){return this.yf.ja};f.$=function(a){var b=this.yf;a=String.fromCharCode(Ea(a));b.ja=\"\"+b.ja+a;return this};f.vc=function(a){return Wga(ce(),a)};f.Gk=function(a){return Wga(ce(),a)};f.n=function(a){return hc(this.yf.ja.charCodeAt(a|0))};f.va=function(a){return hc(this.yf.ja.charCodeAt(a))};\nf.$classData=q({I$:0},!1,\"scala.collection.mutable.StringBuilder\",{I$:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,Po:1,xg:1,xf:1,wf:1,Xk:1,hd:1,Vb:1,Yk:1,ZJ:1,l:1});function Xga(a,b){null===b.ww?a.Gn=b.zm:b.ww.zm=b.zm;null===b.zm?a.xw=b.ww:b.zm.ww=b.ww;b.ww=null;b.zm=null}function lA(){this.xw=this.Gn=this.Ll=null;this.Ll=new SV(this)}lA.prototype=new e$;lA.prototype.constructor=lA;f=lA.prototype;f.ry=function(a){return b6(this,a)};\nf.am=function(a){return c6(this,a)};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.vj=function(){RV||(RV=new NV);return RV};f.DB=function(){if(0<this.ka())return G(new H,this.xw.ju,this.xw.Fn);throw AH(\"Cannot call .last on empty LinkedHashMap\");};f.oB=function(){if(0<this.ka())return G(new H,this.Gn.ju,this.Gn.Fn);throw AH(\"Cannot call .head on empty LinkedHashMap\");};f.ka=function(){return this.Ll.nu()};f.Q=function(){return this.ka()};\nf.b=function(){return 0===this.Ll.nu()};f.U=function(a){a=mR(this.Ll,a);return null===a?R():new L(a.Fn)};f.L=function(a){return ca(this)===da(Yga)?null!==mR(this.Ll,a):!this.U(a).b()};f.bj=function(a,b){a=sR(this.Ll,a,b);null===a?R():a.Fn=b};f.bh=function(a,b){a=sR(this.Ll,a,b);null!==a&&(a.Fn=b)};f.JB=function(a){a=tR(this.Ll,a);null===a?R():Xga(this,a)};f.m=function(){return new WC(this)};f.zr=function(){return new o9(this)};f.tj=function(){return new h2(this)};\nf.ou=function(a,b){var c=this.Ll,d=My(W(),a);c=nR(c,d);d=oR(this.Ll,a,c);var e=null===d?R():new L(d.Fn);b=b.n(e);e=G(new H,e,b);var g=e.y,h=e.w;if(R()!==g||R()!==h)if(g=e.w,e.y instanceof L&&R()===g)Xga(this,d),uR(this.Ll,a,c);else if(h=e.y,g=e.w,R()===h&&g instanceof L)d=this.Ll,a=this.Ll.CJ(a,g.k),pR(d,a,c);else if(a=e.w,e.y instanceof L&&a instanceof L)d.Fn=a.k;else throw new w(e);return b};f.ie=function(){return new i2(this)};\nf.Ca=function(a){for(var b=this.Gn;null!==b;)a.n(G(new H,b.ju,b.Fn)),b=b.zm};f.og=function(a){for(var b=this.Gn;null!==b;)a.ba(b.ju,b.Fn),b=b.zm};f.mg=function(){for(var a=this.Ll,b=-1+a.bl().a.length|0;0<=b;)a.bl().a[b]=null,b=-1+b|0;a.hz(0);rR(a,0);this.xw=this.Gn=null};f.Oc=function(){return\"LinkedHashMap\"};f.Bm=function(a){this.JB(a)};f.$=function(a){this.bj(a.h(),a.j());return this};f.e=function(){return this.oB()};f.Mc=function(){return this.DB()};\nvar Yga=q({Z9:0},!1,\"scala.collection.mutable.LinkedHashMap\",{Z9:1,eH:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,CC:1,ah:1,mH:1,$g:1,Ff:1,xg:1,xf:1,wf:1,Jn:1,Wba:1,Oba:1,Cb:1,RG:1,sg:1,l:1});lA.prototype.$classData=Yga;function Zga(a){var b=ep(new fp,a);a.Hn=b.Hn;a.No=b.No;a.AC=!1}function fp(){this.No=this.Hn=null;this.AC=!1;this.BC=this.In=0;this.Hn=u();this.No=null;this.AC=!1;this.In=0}fp.prototype=new c$;fp.prototype.constructor=fp;f=fp.prototype;f.he=function(){};\nf.Ii=function(a){return E3(this,a)};f.cc=function(a){return F3(this,a)};f.gn=function(a){return G3(this,a)};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){return ZY(this,a)};f.Bb=function(a){return $Y(this,a)};f.m=function(){return new m2(this.Hn.m(),new U(()=>this.BC))};f.Ik=function(){return l2()};f.va=function(a){return eB(this.Hn,a)};f.K=function(){return this.In};f.Q=function(){return this.In};f.b=function(){return 0===this.In};\nf.ha=function(){this.AC=!this.b();return this.Hn};function wp(a,b){a.BC=1+a.BC|0;a.AC&&Zga(a);b=new z(b,u());0===a.In?a.Hn=b:a.No.p=b;a.No=b;a.In=1+a.In|0;return a}function ep(a,b){b=b.m();if(b.s()){var c=1,d=new z(b.t(),u());for(a.Hn=d;b.s();){var e=new z(b.t(),u());d=d.p=e;c=1+c|0}a.In=c;a.No=d}return a}f.Mc=function(){if(null===this.No)throw AH(\"last of empty ListBuffer\");return this.No.z};f.Oc=function(){return\"ListBuffer\"};\nf.zc=function(a){a=a.m();a.s()&&(a=ep(new fp,a),this.BC=1+this.BC|0,this.AC&&Zga(this),0===this.In?this.Hn=a.Hn:this.No.p=a.Hn,this.No=a.No,this.In=this.In+a.In|0);return this};f.$=function(a){return wp(this,a)};f.Kb=function(){return this.ha()};f.n=function(a){return eB(this.Hn,a|0)};f.Ub=function(){return l2()};\nf.$classData=q({l$:0},!1,\"scala.collection.mutable.ListBuffer\",{l$:1,pC:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,rC:1,xf:1,wf:1,Jn:1,id:1,Cb:1,Po:1,xg:1,sg:1,l:1});function T$(a,b){return b===a.Jd?a:tV(new sV,b,a.We)}function tV(a,b,c){a.Jd=b;a.We=c;return a}function vV(a){var b=new sV;tV(b,null,a);return b}function sV(){this.We=this.Jd=null}sV.prototype=new q9;sV.prototype.constructor=sV;f=sV.prototype;\nf.gR=function(a,b){b=this.jq().Dv(b);for(var c=this.m();c.s();){var d=a.n(c.t());b.$(d)}return b.Kb()};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Oc=function(){return\"SortedMap\"};f.ti=function(){return new uV(this.We)};f.se=function(){return this.We};f.jq=function(){return xV()};f.m=function(){nJ();var a=this.Jd;nJ();var b=R();return new d4(a,b,this.We)};f.U=function(a){nJ();a=fJ(0,this.Jd,a,this.We);return null===a?R():new L(a.Wb)};\nf.Se=function(a,b){a=fJ(nJ(),this.Jd,a,this.We);return null===a?Es(b):a.Wb};function U$(a,b,c){return T$(a,gJ(nJ(),a.Jd,b,c,!0,a.We))}function V$(a,b){a:{if(b instanceof sV){var c=a.We,d=b.We;if(null===c?null===d:c.i(d)){b=mJ(nJ(),a.Jd,b.Jd,a.We);break a}}if(b&&b.$classData&&b.$classData.rb.KL)if(b.b())b=a.Jd;else{for(c=new oZ(a);!b.b();)d=b.e(),c.bu=fR(c,c.bu,d.h(),d.j()),b=b.f();b=qJ(c.bu)}else{c=new oZ(a);for(b=b.m();b.s();)d=b.t(),c.bu=fR(c,c.bu,d.h(),d.j());b=qJ(c.bu)}}return T$(a,b)}\nf.Ca=function(a){var b=nJ(),c=this.Jd;null!==c&&mda(b,c,a)};f.og=function(a){var b=nJ(),c=this.Jd;null!==c&&qda(b,c,a)};f.ka=function(){return EI(nJ(),this.Jd)};f.Q=function(){return EI(nJ(),this.Jd)};f.b=function(){return 0===EI(nJ(),this.Jd)};f.oB=function(){var a=hJ(nJ(),this.Jd);return G(new H,a.Wa,a.Wb)};f.DB=function(){var a=iJ(nJ(),this.Jd);return G(new H,a.Wa,a.Wb)};function $ga(a,b){return T$(a,kJ(nJ(),a.Jd,new fn((c,d)=>!!b.n(G(new H,c,d)))))}\nf.BK=function(a){var b=Gda(nJ(),this.Jd,new fn((d,e)=>!!a.n(G(new H,d,e))));if(null===b)throw new w(b);var c=b.j();return G(new H,T$(this,b.h()),T$(this,c))};\nf.i=function(a){if(a instanceof sV){var b=this.We,c=a.We;if(null===b?null===c:b.i(c)){nJ();b=this.Jd;a=a.Jd;c=this.We;var d;if(!(d=b===a)&&(d=null!==b)&&(d=null!==a)&&(d=(2147483647&b.ea)===(2147483647&a.ea))){b=new e4(b,c);a=new e4(a,c);for(c=!0;c&&null!==b.Hc&&null!==a.Hc;)b.Hc===a.Hc?(0===b.Wd?d=null:(b.Wd=-1+b.Wd|0,d=b.Cn.a[b.Wd]),b.Hc=d,0===a.Wd?d=null:(a.Wd=-1+a.Wd|0,d=a.Cn.a[a.Wd]),a.Hc=d):(c=Object.is(b.Hc.Wa,a.Hc.Wa)||b.hw.Yi(b.Hc.Wa,a.Hc.Wa)?ml(nl(),b.Hc.Wb,a.Hc.Wb):!1,b.Hc=r1(b,b.Hc.ta),\na.Hc=r1(a,a.Hc.ta));d=c&&null===b.Hc&&null===a.Hc}return d}}return lY(this,a)};f.Ih=function(){return\"TreeMap\"};f.bf=function(a){return V$(this,a)};f.vc=function(a){return rV(xV(),a,this.We)};f.Gk=function(a){return rV(xV(),a,this.We)};f.IC=function(a,b){return p8(this,a,b)};f.Pn=function(a){return U$(this,a.h(),a.j())};f.jM=function(a){return O9(this,a)};f.Fk=function(a){return $ga(this,a)};\nf.Bb=function(a){var b=EI(nJ(),this.Jd)-(0<a?a:0)|0;if(0>=b)a=vV(this.We);else if(b>=EI(nJ(),this.Jd))a=this;else{a=new sV;var c=nJ();b=pI(HI(c,this.Jd,b));a=tV(a,b,this.We)}return a};f.Jc=function(a){if(0>=a)var b=this;else if(a>=EI(nJ(),this.Jd))b=vV(this.We);else{b=new sV;var c=nJ();a=pI(GI(c,this.Jd,a));b=tV(b,a,this.We)}return b};f.Mc=function(){return this.DB()};f.e=function(){return this.oB()};\nf.dG=function(a){a:{if(a instanceof rZ){var b=this.We,c=a.Xe;if(null===b?null===c:b.i(c)){b=nJ();a=pI(XI(b,this.Jd,a.Hf,this.We));a=T$(this,a);break a}}a=x5(this,a)}return a};f.am=function(a){return V$(this,a)};f.hy=function(a){return V$(this,a)};f.Em=function(a,b){return U$(this,a,b)};f.Dm=function(a,b){return U$(this,a,b)};f.xj=function(a){var b=nJ();a=pI(PI(b,this.Jd,a,this.We));return T$(this,a)};f.zr=function(){return sZ(new rZ,this.Jd,this.We)};f.Ht=function(){return sZ(new rZ,this.Jd,this.We)};\nf.AB=function(){return sZ(new rZ,this.Jd,this.We)};f.$classData=q({G8:0},!1,\"scala.collection.immutable.TreeMap\",{G8:1,Rt:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,Pr:1,xc:1,Xt:1,FS:1,YB:1,zL:1,Iy:1,yL:1,A8:1,Sba:1,j6:1,RG:1,Cb:1,E8:1,sg:1,l:1});function W$(a,b){this.Aw=this.Yh=null;Q9(this,a,b)}W$.prototype=new r$;W$.prototype.constructor=W$;f=W$.prototype;f.Oc=function(){return\"SortedMap\"};f.i=function(a){return lY(this,a)};f.jq=function(){return this.Yh.jq()};f.se=function(){return this.Yh.se()};\nfunction X$(a,b){b=a.Yh.hy(b);return new W$(b,a.Aw)}function Y$(a,b){return new W$(a.Yh.jq().qr(b,a.Yh.se()),a.Aw)}f.bf=function(a){return X$(this,a)};f.zr=function(){return new g9(this)};f.kM=function(a){return new W$(this,a)};f.vc=function(a){return Y$(this,a)};f.Gk=function(a){return Y$(this,a)};f.JJ=function(a){return Y$(this,a)};f.am=function(a){return X$(this,a)};f.hQ=function(a){return X$(this,a)};f.hy=function(a){return X$(this,a)};f.$=function(a){this.Yh.$(a);return this};\nf.cQ=function(a){this.Yh.$(a);return this};f.Bm=function(a){this.Yh.Bm(a)};f.oT=function(a){this.Yh.Bm(a)};f.$classData=q({E$:0},!1,\"scala.collection.mutable.SortedMap$WithDefault\",{E$:1,fT:1,eH:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,CC:1,ah:1,mH:1,$g:1,Ff:1,xg:1,xf:1,wf:1,Jn:1,l:1,C$:1,YB:1,zL:1,Iy:1,yL:1,F$:1});function H1(a,b,c){a.fu=0;a.eu=b;a.Zg=c;return a}function kl(){var a=new I1;H1(a,new zc(16),0);return a}\nfunction Mv(a){var b=new I1;H1(b,new zc(1<a?a:1),0);return b}function I1(){this.fu=0;this.eu=null;this.Zg=0}I1.prototype=new c$;I1.prototype.constructor=I1;f=I1.prototype;f.Ii=function(a){return E3(this,a)};f.cc=function(a){return F3(this,a)};f.gn=function(a){return G3(this,a)};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){return ZY(this,a)};f.Bb=function(a){return $Y(this,a)};f.m=function(){return sl(this).m()};f.Sd=function(){return sl(this).Sd()};\nf.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.Jc=function(a){return q0(this,a)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=this.Zg;return b===a?0:b<a?-1:1};f.Q=function(){return this.Zg};\nfunction K1(a,b){QF();var c=a.eu;var d=a.Zg;if(!(b<=c.a.length)){var e=c.a.length;var g=e<<1;e=e>>>31|0|e>>31<<1;g=(0===e?-2147483632<(-2147483648^g):0<e)?new ma(g,e):new ma(16,0);e=g.Y;for(g=g.W;;){var h=g,k=b>>31,l=e;if(l===k?(-2147483648^h)<(-2147483648^b):l<k)e=g>>>31|0|e<<1,g<<=1;else break}b=e;if(0===b?-1>=(-2147483648^g):0>b)b=g;else{if(2147483647===d)throw a=new xF,yF(a,\"Collections can not have more than 2147483647 elements\",null,!0),a;b=2147483647}b=new zc(b);VG(SG(),c,0,b,0,d);c=b}a.eu=\nc}f.va=function(a){var b=1+a|0;if(0>a)throw aL(new bL,a+\" is out of bounds (min 0, max \"+(-1+this.Zg|0)+\")\");if(b>this.Zg)throw aL(new bL,(-1+b|0)+\" is out of bounds (min 0, max \"+(-1+this.Zg|0)+\")\");return this.eu.a[a]};function N0(a,b,c){var d=1+b|0;if(0>b)throw aL(new bL,b+\" is out of bounds (min 0, max \"+(-1+a.Zg|0)+\")\");if(d>a.Zg)throw aL(new bL,(-1+d|0)+\" is out of bounds (min 0, max \"+(-1+a.Zg|0)+\")\");a.fu=1+a.fu|0;a.eu.a[b]=c}f.K=function(){return this.Zg};\nfunction sl(a){return new j9(a,new U(()=>a.fu))}f.Ik=function(){return QF()};function ol(a,b){a.fu=1+a.fu|0;var c=a.Zg;K1(a,1+c|0);a.Zg=1+c|0;N0(a,c,b);return a}function Lv(a,b){if(b instanceof I1){var c=b.Zg;0<c&&(a.fu=1+a.fu|0,K1(a,a.Zg+c|0),VG(SG(),b.eu,0,a.eu,a.Zg,c),a.Zg=a.Zg+c|0)}else lR(a,b);return a}f.Oc=function(){return\"ArrayBuffer\"};f.Gc=function(a,b,c){var d=this.Zg,e=wG(xG(),a);c=c<d?c:d;e=e-b|0;e=c<e?c:e;e=0<e?e:0;0<e&&VG(SG(),this.eu,0,a,b,e);return e};\nf.zc=function(a){return Lv(this,a)};f.$=function(a){return ol(this,a)};f.Ub=function(){return QF()};f.n=function(a){return this.va(a|0)};f.$classData=q({c9:0},!1,\"scala.collection.mutable.ArrayBuffer\",{c9:1,pC:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,rC:1,xf:1,wf:1,Jn:1,iH:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,sg:1,l:1});function Md(a,b){a.Xr=b;return a}function E2(){var a=new Nd;Md(a,[]);return a}function Nd(){this.Xr=null}Nd.prototype=new c$;\nNd.prototype.constructor=Nd;f=Nd.prototype;f.he=function(){};f.Oc=function(){return\"IndexedSeq\"};f.m=function(){var a=new QX(this);return Kr(new Lr,a)};f.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.cc=function(a){return n0(this,a)};f.Jc=function(a){return q0(this,a)};f.Bb=function(a){return this.vc(X8(new Y8,this,a))};f.Ja=function(a){return t0(this,a)};f.e=function(){return this.Xr[0]};f.Mc=function(){return SF(this)};\nf.ab=function(a){var b=this.Xr.length|0;return b===a?0:b<a?-1:1};f.Ii=function(a){return E3(this,a)};f.gn=function(a){return G3(this,a)};f.Gb=function(a){return XY(this,a)};f.Fk=function(a){return ZY(this,a)};f.Ik=function(){return W1()};f.va=function(a){return this.Xr[a]};f.K=function(){return this.Xr.length|0};f.Q=function(){return this.Xr.length|0};f.Ih=function(){return\"WrappedArray\"};f.Kb=function(){return this};f.$=function(a){this.Xr.push(a);return this};f.n=function(a){return this.Xr[a|0]};\nf.Ub=function(){return W1()};f.$classData=q({M$:0},!1,\"scala.scalajs.js.WrappedArray\",{M$:1,pC:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,rC:1,xf:1,wf:1,Jn:1,id:1,Cb:1,Xk:1,hd:1,Vb:1,Yk:1,iH:1,xg:1,l:1});\nfunction aha(a,b,c,d){if(0!==(b.a.length&(-1+b.a.length|0)))throw new Yj(\"assertion failed: Array.length must be power of 2\");var e=b.a.length;if(0>c||c>=e)throw aL(new bL,c+\" is out of bounds (min 0, max \"+(-1+e|0)+\")\");e=b.a.length;if(0>d||d>=e)throw aL(new bL,d+\" is out of bounds (min 0, max \"+(-1+e|0)+\")\");a.ec=b;a.Zd=c;a.Ke=d}function O1(a,b,c,d){a.ec=b;a.Zd=c;a.Ke=d;aha(a,a.ec,a.Zd,a.Ke);return a}function Q1(){var a=new P1;O1(a,N1(T1(),16),0,0);return a}\nfunction P1(){this.ec=null;this.Ke=this.Zd=0}P1.prototype=new c$;P1.prototype.constructor=P1;function Z$(){}f=Z$.prototype=P1.prototype;f.ia=function(){return this.tK()};f.Ii=function(a){return E3(this,a)};f.cc=function(a){return F3(this,a)};f.gn=function(a){return G3(this,a)};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Fk=function(a){return ZY(this,a)};f.Bb=function(a){return $Y(this,a)};f.m=function(){var a=new QX(this);return Kr(new Lr,a)};\nf.Sd=function(){var a=new QX(this);return uZ(new vZ,a)};f.mf=function(a,b){return l0(this,a,b)};f.ad=function(){return new Z8(this)};f.Jc=function(a){return q0(this,a)};f.e=function(){return this.va(0)};f.Mc=function(){return SF(this)};f.ab=function(a){var b=(this.Ke-this.Zd|0)&(-1+this.ec.a.length|0);return b===a?0:b<a?-1:1};f.Q=function(){return(this.Ke-this.Zd|0)&(-1+this.ec.a.length|0)};\nf.va=function(a){var b=(this.Ke-this.Zd|0)&(-1+this.ec.a.length|0);if(0>a||a>=b)throw aL(new bL,a+\" is out of bounds (min 0, max \"+(-1+b|0)+\")\");return this.ec.a[(this.Zd+a|0)&(-1+this.ec.a.length|0)]};function uU(a,b){var c=1+((a.Ke-a.Zd|0)&(-1+a.ec.a.length|0))|0;c>((a.Ke-a.Zd|0)&(-1+a.ec.a.length|0))&&c>=a.ec.a.length&&U1(a,c);a.ec.a[a.Ke]=b;a.Ke=(1+a.Ke|0)&(-1+a.ec.a.length|0);return a}\nfunction Hea(a,b){var c=1+((a.Ke-a.Zd|0)&(-1+a.ec.a.length|0))|0;c>((a.Ke-a.Zd|0)&(-1+a.ec.a.length|0))&&c>=a.ec.a.length&&U1(a,c);a.Zd=(-1+a.Zd|0)&(-1+a.ec.a.length|0);a.ec.a[a.Zd]=b}function vU(a,b){var c=b.Q();if(0<c)for(c=c+((a.Ke-a.Zd|0)&(-1+a.ec.a.length|0))|0,c>((a.Ke-a.Zd|0)&(-1+a.ec.a.length|0))&&c>=a.ec.a.length&&U1(a,c),b=b.m();b.s();)c=b.t(),a.ec.a[a.Ke]=c,a.Ke=(1+a.Ke|0)&(-1+a.ec.a.length|0);else for(b=b.m();b.s();)c=b.t(),uU(a,c);return a}\nfunction wU(a){if(a.b())throw AH(\"empty collection\");var b=a.ec.a[a.Zd];a.ec.a[a.Zd]=null;a.Zd=(1+a.Zd|0)&(-1+a.ec.a.length|0);return b}f.K=function(){return(this.Ke-this.Zd|0)&(-1+this.ec.a.length|0)};f.b=function(){return this.Zd===this.Ke};f.uK=function(){return O1(new P1,this.ec.ia(),this.Zd,this.Ke)};f.Ik=function(){return T1()};f.Gc=function(a,b,c){var d=(this.Ke-this.Zd|0)&(-1+this.ec.a.length|0),e=wG(xG(),a);d=c<d?c:d;e=e-b|0;e=d<e?d:e;e=0<e?e:0;0<e&&D5(this,a,b,c);return e};\nf.Bj=function(a){a=a.si((this.Ke-this.Zd|0)&(-1+this.ec.a.length|0));return D5(this,a,0,(this.Ke-this.Zd|0)&(-1+this.ec.a.length|0))};function U1(a,b){if(b>=a.ec.a.length||16<a.ec.a.length&&(a.ec.a.length-b|0)>b){var c=(a.Ke-a.Zd|0)&(-1+a.ec.a.length|0);b=N1(T1(),b);b=D5(a,b,0,c);aha(a,b,0,c)}}f.Oc=function(){return\"ArrayDeque\"};f.Ub=function(){return this.Ik()};f.tK=function(){return this.uK()};f.zc=function(a){return vU(this,a)};f.$=function(a){return uU(this,a)};\nf.n=function(a){return this.va(a|0)};f.$classData=q({RL:0},!1,\"scala.collection.mutable.ArrayDeque\",{RL:1,pC:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,rC:1,xf:1,wf:1,Jn:1,iH:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,NS:1,sg:1,l:1});function tU(a){this.ec=null;this.Ke=this.Zd=0;a=N1(T1(),a);O1(this,a,0,0)}tU.prototype=new Z$;tU.prototype.constructor=tU;f=tU.prototype;f.Ik=function(){return p2()};f.Oc=function(){return\"Queue\"};\nfunction bha(a){var b=PV(new QV,new tU(16));FZ(b,a);return b.lk}f.tK=function(){return bha(this)};f.uK=function(){return bha(this)};f.Ub=function(){return p2()};f.$classData=q({r$:0},!1,\"scala.collection.mutable.Queue\",{r$:1,RL:1,pC:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,rC:1,xf:1,wf:1,Jn:1,iH:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,NS:1,sg:1,l:1});function IX(a){this.ec=null;this.Ke=this.Zd=0;a=N1(T1(),a);O1(this,a,0,0)}IX.prototype=new Z$;\nIX.prototype.constructor=IX;f=IX.prototype;f.Ik=function(){return w2()};f.Oc=function(){return\"Stack\"};function cha(a){var b=PV(new QV,new IX(16));FZ(b,a);return b.lk}f.tK=function(){return cha(this)};f.uK=function(){return cha(this)};f.Ub=function(){return w2()};f.$classData=q({G$:0},!1,\"scala.collection.mutable.Stack\",{G$:1,RL:1,pC:1,kk:1,Tc:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Ac:1,za:1,la:1,kb:1,v:1,ok:1,ah:1,pk:1,$g:1,Ff:1,rC:1,xf:1,wf:1,Jn:1,iH:1,Xk:1,hd:1,Vb:1,Yk:1,id:1,Cb:1,NS:1,sg:1,l:1});\nfunction YV(a){var b=new $$;b.Zk=new zK(null,0);b.Kn=a;return b}function $$(){this.Kn=this.Zk=null}$$.prototype=new e$;$$.prototype.constructor=$$;f=$$.prototype;f.hy=function(a){return w8(this,a)};f.ry=function(a){return b6(this,a)};f.Gb=function(a){return XY(this,a)};f.Ja=function(a){return YY(this,a)};f.Bb=function(a){return $Y(this,a)};f.Oc=function(){return\"SortedMap\"};f.i=function(a){return lY(this,a)};f.ti=function(){return $V().Dv(this.Kn)};f.se=function(){return this.Kn};\nf.m=function(){if(this.b())return Rq().Pa;var a=this.Zk,b=R(),c=R();return new H4(a,b,c,this.Kn)};f.tj=function(){if(this.b())return Rq().Pa;var a=this.Zk,b=R(),c=R();return new I4(a,b,c,this.Kn)};f.ie=function(){if(this.b())return Rq().Pa;var a=this.Zk,b=R(),c=R();return new J4(a,b,c,this.Kn)};f.mg=function(){xK();var a=this.Zk;a.zi=null;a.gz=0};f.U=function(a){xK();a=nK(this.Zk.zi,a,this.Kn);return null===a?R():new L(a.Vr)};f.Ca=function(a){var b=xK(),c=this.Zk.zi;null!==c&&Oda(b,c,a)};\nf.og=function(a){var b=xK(),c=this.Zk.zi;null!==c&&Qda(b,c,a)};f.ka=function(){return this.Zk.gz};f.Q=function(){return this.ka()};f.b=function(){xK();return null===this.Zk.zi};f.L=function(a){xK();return null!==nK(this.Zk.zi,a,this.Kn)};f.oB=function(){xK();var a=this.Zk.zi;a=null===a?null:uK(a);return(null===a?R():new L(G(new H,a.Oo,a.Vr))).o()};f.DB=function(){xK();var a=this.Zk.zi;if(null===a)a=null;else a:for(;;){if(null===a.Bc)break a;a=a.Bc}return(null===a?R():new L(G(new H,a.Oo,a.Vr))).o()};\nf.Ih=function(){return\"TreeMap\"};f.bf=function(a){return w8(this,a)};f.zr=function(){return new g9(this)};f.vc=function(a){return XV($V(),a,this.Kn)};f.Gk=function(a){return XV($V(),a,this.Kn)};f.kM=function(a){return new W$(this,a)};f.am=function(a){return w8(this,a)};f.Mc=function(){return this.DB()};f.e=function(){return this.oB()};\nf.Bm=function(a){xK();var b=this.Zk,c=nK(b.zi,a,this.Kn);if(null!==c){var d=c.Wc;if(null===c.Vc){var e=c.Bc;qK(b,c,c.Bc);a=c.bb}else if(null===c.Bc)e=c.Vc,qK(b,c,c.Vc),a=c.bb;else{var g=uK(c.Bc);d=g.Wc;e=g.Bc;g.bb===c?a=g:(a=g.bb,qK(b,g,g.Bc),g.Bc=c.Bc,g.Bc.bb=g);qK(b,c,g);g.Vc=c.Vc;g.Vc.bb=g;g.Wc=c.Wc}if(!d){for(c=e;c!==b.zi&&tK(c);)c===a.Vc?(c=a.Bc,c.Wc&&(c.Wc=!1,a.Wc=!0,oK(b,a),c=a.Bc),tK(c.Vc)&&tK(c.Bc)?(c.Wc=!0,c=a):(tK(c.Bc)&&(c.Vc.Wc=!1,c.Wc=!0,pK(b,c),c=a.Bc),c.Wc=a.Wc,a.Wc=!1,c.Bc.Wc=!1,\noK(b,a),c=b.zi)):(c=a.Vc,c.Wc&&(c.Wc=!1,a.Wc=!0,pK(b,a),c=a.Vc),tK(c.Bc)&&tK(c.Vc)?(c.Wc=!0,c=a):(tK(c.Vc)&&(c.Bc.Wc=!1,c.Wc=!0,oK(b,c),c=a.Vc),c.Wc=a.Wc,a.Wc=!1,c.Vc.Wc=!1,pK(b,a),c=b.zi)),a=c.bb;null!==c&&(c.Wc=!1)}b.gz=-1+b.gz|0}};\nf.$=function(a){xK();var b=this.Zk,c=a.h(),d=a.j(),e=this.Kn;a=null;for(var g=b.zi,h=1;null!==g&&0!==h;)a=g,h=e.Da(c,g.Oo),g=0>h?g.Vc:g.Bc;if(0===h)a.Vr=d;else{c=new yK(c,d,!0,null,null,a);for(null===a?b.zi=c:0>h?a.Vc=c:a.Bc=c;sK(c.bb);)c.bb===c.bb.bb.Vc?(a=c.bb.bb.Bc,sK(a)?(c.bb.Wc=!1,a.Wc=!1,c.bb.bb.Wc=!0,c=c.bb.bb):(c===c.bb.Bc&&(c=c.bb,oK(b,c)),c.bb.Wc=!1,c.bb.bb.Wc=!0,pK(b,c.bb.bb))):(a=c.bb.bb.Vc,sK(a)?(c.bb.Wc=!1,a.Wc=!1,c.bb.bb.Wc=!0,c=c.bb.bb):(c===c.bb.Vc&&(c=c.bb,pK(b,c)),c.bb.Wc=!1,c.bb.bb.Wc=\n!0,oK(b,c.bb.bb)));b.zi.Wc=!1;b.gz=1+b.gz|0}return this};f.jq=function(){return $V()};f.$classData=q({J$:0},!1,\"scala.collection.mutable.TreeMap\",{J$:1,eH:1,qm:1,ua:1,g:1,na:1,M:1,pa:1,N:1,oa:1,Mk:1,ek:1,za:1,la:1,um:1,v:1,CC:1,ah:1,mH:1,$g:1,Ff:1,xg:1,xf:1,wf:1,Jn:1,C$:1,YB:1,zL:1,Iy:1,yL:1,F$:1,Cb:1,RG:1,j6:1,sg:1,l:1});aa=new ma(0,0);Fd.jz=aa;typecheck=function(a){qe(Qf(),a)};new (md(fa).Ia)([]);\n(function(a){var b=document.querySelector(\"#mlscript-input\");se(a,b.textContent);b.addEventListener(\"input\",c=>{qe(Qf(),c)})})(Qf());\n}).call(this);\n//# sourceMappingURL=mlscript-opt.js.map\n"
  },
  {
    "path": "build.sbt",
    "content": "import Wart._\nimport org.scalajs.linker.interface.OutputPatterns\n\nenablePlugins(ScalaJSPlugin)\n\nval scala3Version = \"3.8.3\"\nval directoryWatcherVersion = \"0.18.0\"\nval scalaTestVersion = \"3.2.19\"\n\nThisBuild / scalaVersion     := \"2.13.18\"\nThisBuild / version          := \"0.1.0-SNAPSHOT\"\nThisBuild / organization     := \"hkust-taco.github.io\"\nThisBuild / organizationName := \"HKUST-TACO\"\nThisBuild / scalacOptions ++= Seq(\n  \"-deprecation\",\n  \"-feature\",\n  \"-unchecked\",\n  \"-language:higherKinds\",\n  \"-language:implicitConversions\",\n  if (insideCI.value) \"-Wconf:any:error\"\n  else                \"-Wconf:any:warning\",\n)\n\nlazy val root = project.in(file(\".\"))\n  .aggregate(mlscriptJS, mlscriptJVM, ts2mlsTest, compilerJVM, hkmc2AllTests, coreJS, coreJVM)\n  .settings(\n    publish := {},\n    publishLocal := {},\n  )\n\nlazy val hkmc2 = crossProject(JSPlatform, JVMPlatform).in(file(\"hkmc2\"))\n  .settings(\n    scalaVersion := scala3Version,\n    watchSources += WatchSource(\n      baseDirectory.value.getParentFile()/\"shared\"/\"src\"/\"test\"/\"diff\", \"*.mls\", NothingFilter),\n    \n    // TODO remove when codebase becomes production-ready\n    scalacOptions -= \"-Wconf:any:error\",\n    \n    // scalacOptions ++= Seq(\"-indent\", \"-rewrite\"),\n    scalacOptions ++= Seq(\"-new-syntax\", \"-rewrite\"),\n    // scalacOptions ++= Seq(\"-language:experimental.modularity\"), // https://docs.scala-lang.org/scala3/reference/experimental/modularity.html\n    \n    libraryDependencies += \"io.methvin\" % \"directory-watcher\" % directoryWatcherVersion,\n    libraryDependencies += \"io.methvin\" %% \"directory-watcher-better-files\" % directoryWatcherVersion,\n    libraryDependencies += \"com.lihaoyi\" %%% \"fansi\" % \"0.5.0\", // Scala.js or Scala-Native\n    libraryDependencies += \"com.lihaoyi\" %%% \"sourcecode\" % \"0.4.2\", // Scala.js / Scala Native\n    libraryDependencies += \"com.lihaoyi\" %% \"os-lib\" % \"0.9.3\",\n    \n    libraryDependencies += \"org.scalactic\" %%% \"scalactic\" % scalaTestVersion,\n    libraryDependencies += \"org.scalatest\" %%% \"scalatest\" % scalaTestVersion % \"test\",\n    \n    watchSources += WatchSource(\n      baseDirectory.value.getParentFile()/\"shared\"/\"src\"/\"test\"/\"mlscript\", \"*.mls\", NothingFilter),\n    watchSources += WatchSource(\n      baseDirectory.value.getParentFile()/\"shared\"/\"src\"/\"test\"/\"mlscript-compile\", \"*.mls\", NothingFilter),\n    watchSources += WatchSource(\n      baseDirectory.value.getParentFile()/\"shared\"/\"src\"/\"test\"/\"mlscript\", \"*.cmd\", NothingFilter),\n  )\n  .jvmSettings(\n  )\n  .jsSettings(\n    scalaJSLinkerConfig ~= {\n      _.withModuleKind(ModuleKind.ESModule)\n        .withOutputPatterns(OutputPatterns.fromJSFile(\"MLscript.mjs\"))\n    },\n    libraryDependencies += \"org.scala-js\" %%% \"scalajs-dom\" % \"2.2.0\",\n  )\n  .dependsOn(core)\n\nlazy val hkmc2JVM = hkmc2.jvm\nlazy val hkmc2JS = hkmc2.js\n\nlazy val hkmc2DiffTests = project.in(file(\"hkmc2DiffTests\"))\n  .dependsOn(hkmc2JVM % \"compile->compile;test->test\")\n  .settings(\n    scalaVersion := scala3Version,\n    \n    libraryDependencies += \"org.scalactic\" %%% \"scalactic\" % scalaTestVersion,\n    libraryDependencies += \"org.scalatest\" %%% \"scalatest\" % scalaTestVersion % \"test\",\n    \n    Test/run/fork := true, // so that CTRL+C actually terminates the watcher\n  )\n\n/** Helper to create test subprojects that compile `.mls` files then run diff tests.\n  * Each subproject depends on `hkmc2JVM` and `hkmc2DiffTests` for shared test infrastructure,\n  * and uses `Def.sequential` to guarantee compile tests complete before diff tests start. */\ndef hkmc2TestSubproject(dirName: String, compileRunner: String, diffRunner: String): Project =\n  Project(dirName, file(dirName))\n    .dependsOn(hkmc2JVM % \"compile->compile;test->test\")\n    .dependsOn(hkmc2DiffTests % \"compile->compile;test->test\")\n    .settings(\n      scalaVersion := scala3Version,\n      \n      libraryDependencies += \"org.scalactic\" %%% \"scalactic\" % scalaTestVersion,\n      libraryDependencies += \"org.scalatest\" %%% \"scalatest\" % scalaTestVersion % \"test\",\n      \n      Test / test := Def.sequential(\n        (Test / testOnly).toTask(s\" hkmc2.$compileRunner\"),\n        (Test / testOnly).toTask(s\" hkmc2.$diffRunner\"),\n      ).value,\n      \n      Test/run/fork := true, // so that CTRL+C actually terminates the watcher\n    )\n\nlazy val hkmc2NofibTests = hkmc2TestSubproject(\"hkmc2NofibTests\", \"NofibCompileTestRunner\", \"NofibDiffTestRunner\")\nlazy val hkmc2AppsTests = hkmc2TestSubproject(\"hkmc2AppsTests\", \"AppsCompileTestRunner\", \"AppsDiffTestRunner\")\nlazy val hkmc2WasmTests = hkmc2TestSubproject(\"hkmc2WasmTests\", \"WasmCompileTestRunner\", \"WasmDiffTestRunner\")\n\nlazy val hkmc2MainTests = project.in(file(\"hkmc2MainTests\"))\n  .settings(\n    Test / test := (\n      (hkmc2DiffTests / Test / test)\n        .dependsOn(hkmc2JVM / Test / test)\n    ).value\n  )\n\nlazy val hkmc2MostTests = project.in(file(\"hkmc2MostTests\"))\n  .settings(\n    Test / test := (\n      (hkmc2DiffTests / Test / test)\n        .dependsOn(hkmc2NofibTests / Test / test)\n        .dependsOn(hkmc2AppsTests / Test / test)\n        .dependsOn(hkmc2WasmTests / Test / test)\n        .dependsOn(hkmc2JVM / Test / test)\n    ).value\n  )\n\nlazy val hkmc2AllTests = project.in(file(\"hkmc2AllTests\"))\n  .settings(\n    Test / test := (\n      (hkmc2DiffTests / Test / test)\n        .dependsOn(hkmc2NofibTests / Test / test)\n        .dependsOn(hkmc2AppsTests / Test / test)\n        .dependsOn(hkmc2WasmTests / Test / test)\n        .dependsOn(hkmc2JVM / Test / test)\n        .dependsOn(hkmc2JS / Test / test)\n        .dependsOn(hkmc2Benchmarks / Test / compile)\n    ).value\n  )\n\nlazy val core = crossProject(JSPlatform, JVMPlatform).in(file(\"core\"))\n  .settings(\n    sourceDirectory := baseDirectory.value.getParentFile()/\"shared\",\n  )\n\nlazy val coreJVM = core.jvm\nlazy val coreJS = core.js\n\nlazy val mlscript = crossProject(JSPlatform, JVMPlatform).in(file(\".\"))\n  .settings(\n    name := \"mlscript\",\n    scalacOptions ++= Seq(\n      \"-Ywarn-value-discard\",\n      \"-Ypatmat-exhaust-depth:160\",\n    ),\n    wartremoverWarnings ++= Warts.allBut(\n      Recursion, Throw, Nothing, Return, While, IsInstanceOf,\n      Var, MutableDataStructures, NonUnitStatements,\n      DefaultArguments, ImplicitParameter, ImplicitConversion,\n      StringPlusAny, Any, ToString,\n      JavaSerializable, Serializable, Product, ToString,\n      LeakingSealed, Overloading,\n      Option2Iterable, IterableOps, ListAppend, SeqApply,\n      TripleQuestionMark, PartialFunctionApply,\n    ),\n    libraryDependencies += \"org.scalatest\" %% \"scalatest\" % \"3.2.12\" % Test,\n    libraryDependencies += \"com.lihaoyi\" %%% \"sourcecode\" % \"0.3.1\",\n    libraryDependencies += \"com.lihaoyi\" %%% \"fastparse\" % \"2.3.3\",\n    libraryDependencies += \"com.lihaoyi\" %% \"os-lib\" % \"0.8.0\",\n    // \n    watchSources += WatchSource(\n      sourceDirectory.value.getParentFile().getParentFile()/\"shared/src/test/diff\", \"*.fun\", NothingFilter),\n    watchSources += WatchSource(\n      sourceDirectory.value.getParentFile().getParentFile()/\"shared/src/test/diff\", \"*.mls\", NothingFilter),\n    Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, \"-oC\"),\n  )\n  .jsSettings(\n    scalaJSUseMainModuleInitializer := true,\n    libraryDependencies += \"org.scala-js\" %%% \"scalajs-dom\" % \"2.2.0\",\n  )\n  .dependsOn(core)\n\nlazy val mlscriptJVM = mlscript.jvm\nlazy val mlscriptJS = mlscript.js\n\nlazy val ts2mls = crossProject(JSPlatform, JVMPlatform).in(file(\"ts2mls\"))\n  .settings(\n    name := \"ts2mls\",\n  )\n  .jvmSettings()\n  .jsSettings(\n    libraryDependencies += \"org.scalatest\" %%% \"scalatest\" % \"3.2.12\" % \"test\"\n  )\n  .dependsOn(mlscript % \"compile->compile;test->test\")\n\nlazy val ts2mlsJS = ts2mls.js\nlazy val ts2mlsJVM = ts2mls.jvm\n\nlazy val ts2mlsTest = project.in(file(\"ts2mls\"))\n  .settings(\n    Test / test := ((ts2mlsJVM / Test / test) dependsOn (ts2mlsJS / Test / test)).value\n  )\n\nlazy val compiler = crossProject(JSPlatform, JVMPlatform).in(file(\"compiler\"))\n  .settings(\n    name := \"mlscript-compiler\",\n    scalaVersion := scala3Version,\n    sourceDirectory := baseDirectory.value.getParentFile()/\"shared\",\n    watchSources += WatchSource(\n      baseDirectory.value.getParentFile()/\"shared\"/\"test\"/\"diff\", \"*.mls\", NothingFilter),\n    watchSources += WatchSource(\n      baseDirectory.value.getParentFile()/\"shared\"/\"test\"/\"diff-ir\", \"*.mls\", NothingFilter),\n  )\n  .dependsOn(mlscript % \"compile->compile;test->test\")\n\nlazy val compilerJVM = compiler.jvm\nlazy val compilerJS = compiler.js\n\nlazy val hkmc2Benchmarks = project.in(file(\"hkmc2Benchmarks\"))\n  .settings(\n    name := \"benchmark\",\n    scalaVersion := scala3Version,\n    sourceDirectory := baseDirectory.value/\"src\",\n    libraryDependencies += \"org.scalatest\" %%% \"scalatest\" % scalaTestVersion % \"test\",\n    watchSources += WatchSource(\n      baseDirectory.value/\"src\"/\"test\"/\"bench\", \"*.mls\", NothingFilter),\n\n    Test/run/fork := true, // so that CTRL+C actually terminates the watcher\n  )\n  .dependsOn(hkmc2JVM)\n  .dependsOn(hkmc2DiffTests % \"compile->compile;test->test\")\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala",
    "content": "package mlscript\npackage compiler\n\nimport mlscript.utils.*\nimport mlscript.utils.shorthands.*\nimport scala.collection.mutable.StringBuilder as StringBuilder\nimport scala.collection.mutable.Map as MutMap\nimport scala.collection.mutable.Set as MutSet\nimport scala.collection.mutable.ArrayBuffer as ArrayBuffer\nimport mlscript.codegen.CodeGenError\n\nclass CompilerError(error: String) extends Error(error)\n\nclass ClassLifter(logDebugMsg: Boolean = false) {\n  type ClassName = String\n  type FieldName = String\n  case class LocalContext(vSet: Set[Var], tSet: Set[TypeName]){\n    def ++(rst: LocalContext) = LocalContext(vSet ++ rst.vSet, tSet ++ rst.tSet)\n    def -+(rst: LocalContext) = LocalContext(vSet -- rst.vSet, tSet ++ rst.tSet)\n    def addV(rst: IterableOnce[Var]) = LocalContext(vSet ++ rst, tSet)\n    def addV(nV: Var) = LocalContext(vSet + nV, tSet)\n    def extV(rst: IterableOnce[Var]) = LocalContext(vSet -- rst, tSet)\n    def extV(nV: Var) = LocalContext(vSet - nV, tSet)\n    def addT(rst: IterableOnce[TypeName]) = LocalContext(vSet, tSet ++ rst)\n    def addT(nT: TypeName) = LocalContext(vSet, tSet + nT)\n    def extT(rst: IterableOnce[TypeName]) = LocalContext(vSet, tSet -- rst)\n    def vSet2tSet = LocalContext(Set(), vSet.map(t => TypeName(t.name)))\n    def moveT2V(ts: Set[TypeName]) = {\n      val inters = tSet.intersect(ts)\n      LocalContext(vSet ++ inters.map(x => Var(x.name)), tSet -- inters)\n    }\n    def intersect(rst: LocalContext) = LocalContext(vSet intersect rst.vSet, tSet intersect rst.tSet)\n    def intersectV(rst: Set[Var]) = LocalContext(vSet.intersect(rst), tSet)\n    def contains(v: Var) = vSet.contains(v) || tSet.contains(TypeName(v.name))\n    def contains(tv: TypeName) = vSet.contains(Var(tv.name)) || tSet.contains(tv)\n    override def toString(): String = \"(\" ++ vSet.mkString(\", \") ++ \"; \" ++ tSet.mkString(\", \") ++ \")\"\n  }\n  private def asContext(v: Var) = LocalContext(Set(v), Set())\n  private def asContextV(vS: IterableOnce[Var]) = LocalContext(vS.iterator.toSet, Set())\n  private def asContext(t: TypeName) = LocalContext(Set(), Set(t))\n  private def asContextT(tS: IterableOnce[TypeName]) = LocalContext(Set(), tS.iterator.toSet)\n  private def emptyCtx = LocalContext(Set(), Set())\n  private def emptyCtxObj = LocalContext(Set(Var(\"this\")), Set())\n\n  case class ClassInfoCache(\n    originNm: TypeName, \n    liftedNm: TypeName, \n    var capturedParams: LocalContext, \n    fields: MutSet[Var], \n    innerClses: MutMap[TypeName, ClassInfoCache], \n    supClses: Set[TypeName],\n    outerCls: Option[ClassInfoCache],\n    body: NuTypeDef, \n    depth: Int\n  ){\n    override def toString(): String = liftedNm.name ++ \"@\" ++ capturedParams.toString() ++ \"^\" ++ outerCls.map(_.liftedNm.toString()).getOrElse(\"_\")\n  }\n  type ClassCache = Map[TypeName, ClassInfoCache]\n  type NamePath = List[String]\n\n  var retSeq: List[NuTypeDef] = Nil\n  val globalFunctions: ArrayBuffer[NuFunDef] = ArrayBuffer()\n  var anonymCnt: Int = 0\n  var clsCnt: Int = 0\n  val logOutput: StringBuilder = new StringBuilder\n  val primiTypes = new mlscript.Typer(false, false, false, true).primitiveTypes\n\n  private def log(str: String): Unit = {\n    logOutput.append(str+\"\\n\")\n    if(logDebugMsg){\n      println(str)\n    }\n  }\n  def getLog: String = logOutput.toString()\n\n  private def genAnoName(textNm: String = \"Ano\"): String = {\n    anonymCnt = anonymCnt + 1\n    textNm ++ \"$\" ++ anonymCnt.toString()\n  }\n\n  private def genParName(clsNm: String): String = \"par$\" ++ clsNm\n  \n  private def genInnerName(outerClsNm: TypeName, innerNm: String) = {\n    clsCnt = clsCnt+1\n    outerClsNm.name ++ \"_\" ++ innerNm ++ \"$\" ++ clsCnt.toString()\n  }\n\n  private def tupleEntityToVar(fld: (Option[Var], Fld)): Option[Var] = fld match{\n    case (None, Fld(_, v: Var)) => Some(v)\n    case (Some(v: Var), _) => Some(v)\n    case _ => None\n  }\n\n  private def getFields(etts: List[Statement]): Set[Var] = {\n    etts.flatMap{\n      case NuFunDef(_, nm, _, _, _) => Some(nm)\n      case nuty: NuTypeDef => Some(Var(nuty.name))\n      case Let(_, name, _, _) => Some(name)\n      case _ => None \n    }.toSet\n  }\n\n  private def selPath2Term(path: List[String], varNm: Var): Term = path match {\n    case Nil => varNm\n    case (head :: tail) => Sel(selPath2Term(tail, Var(head)), varNm)\n  }\n\n  private def buildPathToVar(v: Var)(using outer: Option[ClassInfoCache]): Option[Term] = {\n    def findField(ot: Option[ClassInfoCache]): Option[List[TypeName]] = {\n      ot match{\n        case None => None\n        case Some(info) =>\n          if(info.fields.contains(v) || info.capturedParams.vSet.contains(v))\n            Some(List(info.liftedNm))\n          else findField(info.outerCls).map(l => info.liftedNm :: l)\n      }\n    }\n    val tmp = findField(outer)\n    tmp.map(l => {\n      selPath2Term(l.map(x => genParName(x.name)).updated(0, \"this\").reverse, v)\n    })\n  }\n  private def toFldsEle(trm: Term): (Option[Var], Fld) = (None, Fld(FldFlags(false, false, false), trm))\n\n  def getSupClsInfoByTerm(parentTerm: Term): (List[TypeName], List[(Var, Fld)]) = parentTerm match{\n    case Var(nm) => List(TypeName(nm)) -> Nil\n    case App(Var(nm), _: Tup) => List(TypeName(nm)) -> Nil\n    case App(App(Var(\"&\"), t1), t2) =>\n      val ret1 = getSupClsInfoByTerm(t1)\n      val ret2 = getSupClsInfoByTerm(t2)\n      (ret1._1 ++ ret2._1) -> (ret1._2 ++ ret2._2)\n    case TyApp(trm, targs) => getSupClsInfoByTerm(trm)\n    //SPECIAL CARE: Tup related issue\n    case Tup(flds) =>\n      val ret = flds.filter(_._1.isEmpty).map(fld => getSupClsInfoByTerm(fld._2.value)).unzip\n      ret._1.flatten -> ret._2.fold(Nil)(_ ++ _)\n    case Bra(rcd, trm) => getSupClsInfoByTerm(trm)\n    case Rcd(fields) => (Nil, fields)\n    case _ => (Nil, Nil)\n  }\n  \n  private def splitEntities(etts: List[Statement]) = {\n    val tmp = etts.map{\n      case cls: NuTypeDef => (Some(cls), None, None)\n      case func: NuFunDef => (None, Some(func), None)\n      case trm: Term => (None, None, Some(trm))\n      case others => throw CodeGenError(s\"Not supported entity type: $others\")\n    }.unzip3\n    (tmp._1.flatten, tmp._2.flatten, tmp._3.flatten)\n  }\n\n  private def genClassNm(orgNm: String)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): TypeName = {\n    TypeName(outer match{\n      case None =>\n        clsCnt = clsCnt+1\n        orgNm ++ \"$\" ++ clsCnt.toString()\n      case Some(value) => genInnerName(value.liftedNm, orgNm)\n    })\n  }\n\n  private def getFreeVars(stmt: Located)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): LocalContext = stmt match{\n    case v:Var => \n      val caseEmpty = ctx.vSet.contains(v) || cache.contains(TypeName(v.name)) || globFuncs.contains(v) || primiTypes.contains(v.name)\n      val caseThis = buildPathToVar(v).isDefined && !ctx.vSet.contains(Var(\"this\"))\n      log(s\"get free var find $v: $caseEmpty/$caseThis\")\n      if(caseEmpty) then emptyCtx\n      else if(caseThis) asContext(Var(\"this\"))\n      else asContext(v)\n    case t: NamedType => \n      log(s\"get type $t under $ctx, $cache, $outer\")\n      asContextT(t.collectTypeNames.map(TypeName(_)).filterNot(x => ctx.contains(x) || cache.contains(x) || primiTypes.contains(x.name)))\n    case Lam(lhs, rhs) =>\n      val lhsVs = getFreeVars(lhs)\n      getFreeVars(rhs)(using ctx ++ lhsVs) -+ lhsVs\n    case NuFunDef(_, vm, _, tps, Left(trm)) =>\n      getFreeVars(trm).extV(vm).extT(tps)\n    case OpApp(_, trm) => getFreeVars(trm)\n    case Sel(trm, _) => getFreeVars(trm)\n    case Asc(trm, tp) =>\n      getFreeVars(trm) ++ getFreeVars(tp)\n    case Tup(tupLst) =>\n      tupLst.map{\n        case (Some(v), Fld(_, trm)) => getFreeVars(trm).vSet2tSet.addV(v)\n        case (_, Fld(_, rhs)) => getFreeVars(rhs)\n      }.fold(emptyCtx)(_ ++ _)\n    case Rcd(fields) =>\n      fields.map{\n        case (v, Fld(_, trm)) => getFreeVars(trm).vSet2tSet\n      }.fold(emptyCtx)(_ ++ _)\n    case TyApp(trm, tpLst) =>\n      getFreeVars(trm).addT(tpLst.flatMap(_.collectTypeNames.map(TypeName(_))))\n    case NuTypeDef(_, nm, tps, param, _, _, pars, _, _, body) =>\n      val prmVs = param.map(getFreeVars(_)(using emptyCtx, Map(), globFuncs, None)).getOrElse(emptyCtx)\n      val newVs = prmVs.vSet ++ getFields(body.entities) + Var(nm.name)\n      val nCtx = ctx.addV(newVs).addT(nm).addT(tps.map(_._2))\n      val parVs = pars.map(getFreeVars(_)(using nCtx)).fold(emptyCtx)(_ ++ _)\n      val bodyVs = body.entities.map(getFreeVars(_)(using nCtx)).fold(emptyCtx)(_ ++ _)\n      (bodyVs ++ parVs -+ prmVs).extT(tps.map(_._2))\n    case Blk(stmts) =>\n      val newVs = getFields(stmts)\n      stmts.map(getFreeVars(_)(using ctx.addV(newVs))).fold(emptyCtx)(_ ++ _)\n    case Let(isRec, name, rhs, body) =>\n      getFreeVars(rhs)(using ctx.addV(name)) ++ getFreeVars(body)(using ctx.addV(name))\n    case others =>\n      others.children.map(getFreeVars).fold(emptyCtx)(_ ++ _)\n  }\n\n  private def collectClassInfo(cls: NuTypeDef, preClss: Set[TypeName])(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): ClassInfoCache = {\n    val NuTypeDef(_, nm, tps, param, _, _, pars, _, _, body) = cls\n    log(s\"grep context of ${cls.nme.name} under $ctx # $cache # $globFuncs # $outer \")\n    val (clses, funcs, trms) = splitEntities(cls.body.entities)\n    val (supNms, rcdFlds) = pars.map(getSupClsInfoByTerm).unzip\n    val flds = rcdFlds.flatten.map{\n      case (v, Fld(_, trm)) => \n        val tmp = getFreeVars(trm)(using emptyCtxObj)\n        val ret = tmp.tSet ++ tmp.vSet.map(x => TypeName(x.name))\n        (v, ret)\n    }.unzip\n    log(s\"par record: ${flds._2.flatten}\")\n    val fields = (param.fold(Nil)(t => t.fields).flatMap(tupleEntityToVar) ++ funcs.map(_.nme) ++ clses.map(x => Var(x.nme.name)) ++ trms.flatMap(grepFieldsInTrm) ++ flds._1).toSet\n    val nCtx = ctx.addV(fields).addV(flds._1).extT(tps.map(_._2)).addV(Var(\"this\"))\n    val tmpCtx = ((body.entities.map(getFreeVars(_)(using nCtx)) ++ pars.map(getFreeVars(_)(using nCtx))).fold(emptyCtx)(_ ++ _).moveT2V(preClss)\n                  ).addT(flds._2.flatten.toSet).extV(supNms.flatten.map(x => Var(x.name)))\n\n    log(s\"ret ctx for ${cls.nme.name}: $tmpCtx\")\n    val ret = ClassInfoCache(nm, genClassNm(nm.name), tmpCtx, MutSet(fields.toSeq*), MutMap(), supNms.flatten.toSet, outer, cls, outer.map(_.depth).getOrElse(0)+1)\n    ret\n  }\n\n  private def liftCaseBranch(brn: CaseBranches)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (CaseBranches, LocalContext) = brn match{\n    case k @ Case(v: Var, body, rest) => \n      val nTrm = liftTerm(body)(using ctx.addV(v))\n      val nRest = liftCaseBranch(rest)\n      (Case(v, nTrm._1, nRest._1)(k.refined), nTrm._2 ++ nRest._2)\n    case k @ Case(pat, body, rest) =>\n      val nTrm = liftTerm(body)\n      val nRest = liftCaseBranch(rest)\n      (Case(pat, nTrm._1, nRest._1)(k.refined), nTrm._2 ++ nRest._2)\n    case Wildcard(body) =>\n      val nTrm = liftTerm(body)\n      (Wildcard(nTrm._1), nTrm._2)\n    case NoCases => (brn, emptyCtx)\n  }\n\n  private def liftIf(body: IfBody)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (IfBody, LocalContext) = body match{\n    case IfElse(expr) => \n      val ret = liftTerm(expr)\n      (IfElse(ret._1), ret._2)\n    case IfThen(expr, rhs) =>\n      val nE = liftTerm(expr)\n      val nR = liftTerm(rhs)\n      (IfThen(nE._1, nR._1), nE._2 ++ nR._2)\n    case _ => throw CompilerError(s\"Unknown IfBody: ${body}\")\n  }\n\n  private def liftTuple(tup: Tup)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Tup, LocalContext) = {\n    val ret = tup.fields.map{\n        case (None, Fld(flags, trm)) =>\n          val tmp = liftTerm(trm)\n          ((None, Fld(flags, tmp._1)), tmp._2)\n        case (Some(v), Fld(flags, trm)) =>\n          val nTrm = liftTermAsType(trm)\n          ((Some(v), Fld(flags, nTrm._1)), nTrm._2)\n      }.unzip\n    (Tup(ret._1), ret._2.fold(emptyCtx)(_ ++ _))\n  }\n\n  private def liftConstr(tp: TypeName, prm: Tup)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (TypeName, Tup, LocalContext) = {\n    def findAncestor(crt: ClassInfoCache, target: Option[ClassInfoCache]): Option[(List[String], Option[String])] = {\n      (crt.outerCls, target) match{\n        case (None, None) =>  None\n        case (Some(c1), Some(c2)) if c1.depth == c2.depth => Some((crt.liftedNm.name :: Nil, Some(genParName(c1.liftedNm.name))))\n        case (Some(c1), _) => findAncestor(c1, target).map(l => (crt.liftedNm.name :: l._1, l._2))\n        case (None, _) => Some(Nil, None)\n      }\n    }\n    log(s\"lift constr for $tp$prm under $ctx, $cache, $outer\")\n    if(!cache.contains(tp)){\n      throw new CodeGenError(s\"Cannot find type ${tp.name}. Class values are not supported in lifter. \")\n    }\n    else {\n      val cls@ClassInfoCache(_, nm, capParams, _, _, _, out, _, _) = cache.get(tp).get\n      val nParams = liftTuple(Tup(prm.fields ++ capParams.vSet.toList.map(toFldsEle(_))))\n      if(outer.isDefined){\n        log(\"find ancestor \" + outer.get + \" & \" + cls)\n        findAncestor(outer.get, out) match{\n          case None =>\n            log(\"case 1\")\n            (nm, nParams._1, nParams._2)\n          case Some((selPt, Some(varNm))) =>\n            log(\"case 2\")\n            (nm, Tup(toFldsEle(selPath2Term(selPt.map(genParName).updated(0, \"this\").reverse, Var(varNm))) :: nParams._1.fields), nParams._2) \n          case Some((_, None)) =>\n            log(\"case 3\")\n            (nm, Tup(toFldsEle(Var(\"this\")) :: nParams._1.fields), nParams._2) \n        }\n      }\n      else (nm, nParams._1, nParams._2)\n    }\n  }\n\n  private def newLambObj(lhs: Term, rhs: Term) = \n    New(None, TypingUnit(List(NuFunDef(None, Var(\"apply\"), None, Nil, Left(Lam(lhs, rhs)))(N, N, N, N, N, false, Nil)))) \n\n  private def liftTerm(target: Term)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Term, LocalContext) = \n    log(s\"liftTermNew $target in $ctx, $cache, $globFuncs, $outer\")\n    target match {\n    case v: Var => \n      if(globFuncs.contains(v)) {\n        (globFuncs.get(v).get)\n      }\n      else if(cache.contains(TypeName(v.name))){\n        val cls@ClassInfoCache(_, nm, capParams, _, _, _, out, _, _) = cache.get(TypeName(v.name)).get\n        (Var(nm.name), emptyCtx)\n      }\n      else if(ctx.contains(v) || v.name.equals(\"this\") || primiTypes.contains(v.name))   (v, emptyCtx)\n      else {\n        buildPathToVar(v) match{\n          case Some(value) => (value, emptyCtx)\n          case None => (v, asContext(v))\n        }\n      }\n    case Lam(lhs, rhs) => \n      val prmCnt = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None).vSet.size\n      val nTpNm = TypeName(genAnoName(\"Lambda\"+prmCnt))\n      val anoCls = NuTypeDef(\n        Cls, nTpNm, Nil, S(Tup(Nil)), N, N, Nil, N, N, \n        TypingUnit(List(NuFunDef(None, Var(\"apply\"), N, Nil, Left(Lam(lhs, rhs)))(N, N, N, N, N, false, Nil))))(N, N, Nil)\n      val nSta = App(Var(nTpNm.name),Tup(Nil))\n      val ret = liftEntities(List(anoCls, nSta))\n      (Blk(ret._1), ret._2)\n    case t: Tup => \n      liftTuple(t)\n    case Rcd(fields) =>\n      val ret = fields.map{\n        case (v, Fld(flags, trm)) =>\n          val tmp = liftTermAsType(trm)\n          ((v, Fld(flags, tmp._1)), tmp._2)\n      }.unzip\n      (Rcd(ret._1), ret._2.fold(emptyCtx)(_ ++ _))\n    case Asc(trm, ty) =>\n      val ret = liftTerm(trm)\n      val nTy = liftType(ty)\n      (Asc(ret._1, nTy._1), ret._2 ++ nTy._2)\n    case NuNew(cls) =>\n      liftTerm(App(NuNew(cls), Tup(Nil)))\n    case App(NuNew(cls), args) =>\n      (cls, args) match {\n        case (v: Var, args: Tup) =>\n          val ret = liftConstr(TypeName(v.name), args)\n          (App(NuNew(Var(ret._1.name)), ret._2), ret._3)\n        case _ => ???\n      }\n    case Rft(NuNew(cls), tu) =>\n      liftTerm(Rft(App(NuNew(cls), Tup(Nil)), TypingUnit(Nil)))\n    case Rft(App(NuNew(cls), args), tu) =>\n      (cls, args) match {\n        case (v: Var, args: Tup) =>\n          liftTerm(New(Some((TypeName(v.name), args)), tu))\n        case _ => ???\n      }\n    case App(v: Var, prm: Tup) if cache.contains(TypeName(v.name)) =>\n      val ret = liftConstr(TypeName(v.name), prm)\n      (App(Var(ret._1.name), ret._2), ret._3)\n    case App(v: Var, prm: Tup) if globFuncs.contains(v) => \n      val (nFuncName, nCtxs) = globFuncs.get(v).get\n      val addiArgs = nCtxs.vSet.toList.map(toFldsEle(_))\n      val nPrm = liftTuple(prm)\n      (App(nFuncName, Tup(nPrm._1.fields ++ addiArgs)), nPrm._2)\n    case App(lhs, rhs) => \n      val (ltrm, lctx) = liftTerm(lhs)\n      val (rtrm, rctx) = liftTerm(rhs)\n      (App(ltrm, rtrm), lctx ++ rctx)\n    case Assign(lhs, rhs) =>\n      val (ltrm, lctx) = liftTerm(lhs)\n      val (rtrm, rctx) = liftTerm(rhs)\n      (Assign(ltrm, rtrm), lctx ++ rctx)\n    case Bind(lhs, rhs) =>\n      val (ltrm, lctx) = liftTerm(lhs)\n      val (rtrm, rctx) = liftTermAsType(rhs)\n      (Bind(ltrm, rtrm), lctx ++ rctx)\n    case Bra(rcd, trm) =>\n      val ret = liftTerm(trm)\n      (Bra(rcd, ret._1), ret._2)\n    case CaseOf(trm, cases) =>\n      val nTrm = liftTerm(trm)\n      val nCases = liftCaseBranch(cases)\n      (CaseOf(nTrm._1, nCases._1), nTrm._2 ++ nCases._2)\n    case If(body, None) =>\n      val ret = liftIf(body)\n      (If(ret._1, None), ret._2)\n    case If(body, Some(trm)) =>\n      val ret = liftIf(body)\n      val nTrm = liftTerm(trm)\n      (If(ret._1, Some(nTrm._1)), ret._2 ++ nTrm._2)\n    case Let(isRec, name, rhs, body) =>\n      val nRhs = if(isRec) liftTerm(rhs)(using ctx.addV(name), cache, globFuncs.-(name)) else liftTerm(rhs)\n      val nBody = liftTerm(body)(using ctx.addV(name), cache, globFuncs.-(name))\n      (Let(isRec, name, nRhs._1, nBody._1), nRhs._2 ++ nBody._2)\n    case Sel(receiver, fieldName) =>\n      val nRec = liftTerm(receiver)\n      (Sel(nRec._1, fieldName), nRec._2)\n    case Splc(fields) => throw CompilerError(s\"Unimplemented liftTerm: ${target}\")\n    case Subs(arr, idx) =>\n      val (ltrm, lctx) = liftTerm(arr)\n      val (rtrm, rctx) = liftTerm(idx)\n      (Subs(ltrm, rtrm), lctx ++ rctx)\n    case Test(trm, ty) =>\n      val (ltrm, lctx) = liftTerm(trm)\n      val (rtrm, rctx) = liftTermAsType(ty)\n      (Test(ltrm, rtrm), lctx ++ rctx)\n    case TyApp(lhs, targs) =>\n      val ret = liftTerm(lhs)\n      val nTs = targs.map(liftType).unzip\n      (TyApp(ret._1, nTs._1), nTs._2.fold(ret._2)(_ ++ _))\n    case With(trm, fields) => throw CompilerError(s\"Unimplemented liftTerm: ${target}\")\n    case New(Some((t: TypeName, prm: Tup)), TypingUnit(Nil)) =>\n      val ret = liftConstr(t, prm)\n      (New(Some((ret._1, ret._2)), TypingUnit(Nil)), ret._3)\n    case New(Some((t: TypeName, prm: Tup)), tu) =>\n      log(s\"new $t in ctx $ctx, $cache, $outer\")\n      val nTpNm = TypeName(genAnoName(t.name))\n      val cls = cache.get(t).get\n      val supArgs = Tup(cls.body.params.fold(Nil)(t => t.fields).flatMap(tupleEntityToVar).map(toFldsEle))\n      val anoCls = NuTypeDef(Cls, nTpNm, Nil, cls.body.params, None, None,\n                    List(App(Var(t.name), supArgs)), None, None, tu)(None, None, Nil)\n      val nSta = New(Some((nTpNm, prm)), TypingUnit(Nil))\n      val ret = liftEntities(List(anoCls, nSta))\n      (Blk(ret._1), ret._2)\n    case New(None, tu) =>\n      val nTpNm = TypeName(genAnoName())\n      val anoCls = NuTypeDef(Cls, nTpNm, Nil, None, None, None, Nil, None, None, tu)(None, None, Nil)\n      val nSta = New(Some((nTpNm, Tup(Nil))), TypingUnit(Nil))\n      val ret = liftEntities(List(anoCls, nSta))\n      (Blk(ret._1), ret._2)\n    case New(head, body) => throw CompilerError(s\"Unimplemented liftTerm: ${target}\")\n    case Blk(stmts) =>\n      val ret = liftEntities(stmts)\n      (Blk(ret._1), ret._2)\n    case lit: Lit => (lit, emptyCtx)\n    case Inst(bod) =>\n      val (trm, ctx) = liftTerm(bod)\n      (Inst(trm), ctx)\n    case Forall(ps, bod) =>\n      val (trm, ctx) = liftTerm(bod)\n      (Forall(ps, trm), ctx)\n    case Where(bod, sts) =>\n      val (bod2, ctx) = liftTerm(bod)\n      val (sts2, ctx2) = liftEntities(sts)\n      (Where(bod2, sts2), ctx2)\n    case _: Eqn | _: Super | _: Rft | _: While | _: Quoted | _: Unquoted | _: Ann => throw CompilerError(s\"Unimplemented liftTerm: ${target}\") // TODO\n    case patmat: AdtMatchWith => lastWords(s\"Cannot liftTermNew ${patmat}\")\n  }\n\n  //serves for lifting Tup(Some(_), Fld(_, _, trm)), where trm refers to a type\n  private def liftTermAsType(target: Term)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Term, LocalContext) = \n    log(s\"liftTermAsType $target in $ctx, $cache\")\n    target match{\n    case v: Var =>\n      if (!ctx.contains(v) && !primiTypes.contains(v.name))\n        cache.get(TypeName(v.name)).map(x => Var(x.liftedNm.name) -> emptyCtx).getOrElse(v -> asContext(TypeName(v.name)))\n      else (v -> emptyCtx)\n    case Lam(lhs, rhs) =>\n      val lret = liftTermAsType(lhs)\n      val rret = liftTermAsType(rhs)\n      Lam(lret._1, rret._1) -> (lret._2 ++ rret._2)\n    case TyApp(lhs, targs) =>\n      val lret = liftTermAsType(lhs)\n      val tRets = targs.map(liftType).unzip\n      TyApp(lret._1, tRets._1) -> (tRets._2.fold(lret._2)(_ ++ _))\n    case Tup(fields) =>\n      val ret = fields.map{\n        case (oV, Fld(flags, trm)) =>\n          val tmp = liftTermAsType(trm)\n          (oV, Fld(flags, tmp._1)) -> tmp._2\n      }.unzip\n      Tup(ret._1) -> ret._2.fold(emptyCtx)(_ ++ _)\n    case Bra(rcd, trm) =>\n      val ret = liftTermAsType(trm)\n      Bra(rcd, ret._1) -> ret._2\n    case Rcd(fields) =>\n      val ret = fields.map{\n        case (v, Fld(flags, trm)) =>\n          val tmp = liftTermAsType(trm)\n          ((v, Fld(flags, tmp._1)), tmp._2)\n      }.unzip\n      (Rcd(ret._1), ret._2.fold(emptyCtx)(_ ++ _))\n    case _ => throw CompilerError(s\"Unimplemented liftTermAsType: ${target}\")\n  }\n\n  private def liftTypeName(target: TypeName)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (TypeName, LocalContext) = {\n    if(ctx.contains(target) || primiTypes.contains(target.name)) { target -> emptyCtx }\n    else {\n      cache.get(target).map(x => (x.liftedNm -> emptyCtx)).getOrElse(target -> asContext(target)) \n    }\n  }\n\n  private def liftTypeField(target: Field)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Field, LocalContext) = {\n    val (inT, iCtx) = target.in.map(liftType).unzip\n    val (outT, oCtx) = liftType(target.out)\n    Field(inT, outT) -> (iCtx.getOrElse(emptyCtx) ++ oCtx)\n  }\n\n  private def liftType(target: Type)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (Type, LocalContext) = target match{\n    case AppliedType(base, targs) => \n      val (nTargs, nCtx) = targs.map(liftType).unzip\n      val (nBase, bCtx) = liftTypeName(base)\n      AppliedType(nBase, nTargs) -> (nCtx.fold(emptyCtx)(_ ++ _) ++ bCtx)\n    case Bounds(lb, ub) =>\n      val nlhs = liftType(lb)\n      val nrhs = liftType(ub)\n      Bounds(nlhs._1, nrhs._1) -> (nlhs._2 ++ nrhs._2)\n    case Constrained(base: Type, bounds, where, tscs) =>\n      val (nTargs, nCtx) = bounds.map { case (tv, Bounds(lb, ub)) =>\n        val nlhs = liftType(lb)\n        val nrhs = liftType(ub)\n        (tv, Bounds(nlhs._1, nrhs._1)) -> (nlhs._2 ++ nrhs._2)\n      }.unzip\n      val (bounds2, nCtx2) = where.map { case Bounds(lb, ub) =>\n        val nlhs = liftType(lb)\n        val nrhs = liftType(ub)\n        Bounds(nlhs._1, nrhs._1) -> (nlhs._2 ++ nrhs._2)\n      }.unzip\n      val (tscs0, nCtx3) = tscs.map { case (tvs, cs) =>\n        val (ntvs,c0) = tvs.map { case (p,v) =>\n          val (nv, c) = liftType(v)\n          (p,nv) -> c\n        }.unzip\n        val (ncs,c1) = cs.map(_.map(liftType).unzip).unzip\n        (ntvs,ncs) -> (c0 ++ c1.flatten)\n      }.unzip\n      val (nBase, bCtx) = liftType(base)\n      Constrained(nBase, nTargs, bounds2, tscs0) ->\n        ((nCtx ++ nCtx2 ++ nCtx3.flatten).fold(emptyCtx)(_ ++ _) ++ bCtx)\n    case Constrained(_, _, _, _) => die\n    case Function(lhs, rhs) =>\n      val nlhs = liftType(lhs)\n      val nrhs = liftType(rhs)\n      Function(nlhs._1, nrhs._1) -> (nlhs._2 ++ nrhs._2)\n    case Neg(base) =>\n      val ret = liftType(base)\n      Neg(ret._1) -> ret._2\n    case Record(fields) =>\n      val ret = fields.map(x =>\n        val (nX, nXCtx) = liftTypeName(TypeName(x._1.name))\n        val (nFld, nFldCtx) = liftTypeField(x._2)\n        (Var(nX.name) -> nFld) -> (nXCtx ++ nFldCtx)\n      ).unzip\n      Record(ret._1) -> ret._2.fold(emptyCtx)(_ ++ _)\n    case Recursive(uv, body) =>\n      val ret = liftType(body)\n      Recursive(uv, ret._1) -> ret._2\n    case Rem(base, names) =>\n      val ret = liftType(base)\n      Rem(ret._1, names) -> ret._2\n    case Splice(fields) =>\n      val ret = fields.map{\n          case Left(tp) =>\n            val tmp = liftType(tp)\n            Left(tmp._1) -> tmp._2\n          case Right(fld) =>\n            val tmp = liftTypeField(fld)\n            Right(tmp._1) -> tmp._2\n      }.unzip\n      Splice(ret._1) -> ret._2.fold(emptyCtx)(_ ++ _)\n    case Tuple(fields) =>\n      val ret = fields.map(x =>\n        val (nFld, nFldCtx) = liftTypeField(x._2)\n        (x._1 -> nFld) -> nFldCtx\n      ).unzip\n      Tuple(ret._1) -> ret._2.fold(emptyCtx)(_ ++ _)\n    case WithExtension(base, rcd) =>\n      val nBase = liftType(base)\n      val nRcd = liftType(rcd)\n      WithExtension(nBase._1, nRcd._1.asInstanceOf[Record]) -> (nBase._2 ++ nRcd._2)\n    case Inter(lhs, rhs) =>\n      val nlhs = liftType(lhs)\n      val nrhs = liftType(rhs)\n      Inter(nlhs._1, nrhs._1) -> (nlhs._2 ++ nrhs._2)\n    case Union(lhs, rhs) =>\n      val nlhs = liftType(lhs)\n      val nrhs = liftType(rhs)\n      Union(nlhs._1, nrhs._1) -> (nlhs._2 ++ nrhs._2)\n    case x : TypeName =>\n      liftTypeName(x)\n    case PolyType(targs, body) =>\n      val (body2, ctx) = liftType(body)\n      PolyType(targs, body2) -> ctx\n    case Top | Bot | _: Literal | _: TypeTag | _: TypeVar => target.asInstanceOf[Type] -> emptyCtx\n    case _: Selection => throw CompilerError(s\"Unimplemented liftType: ${target}\") // TODO\n  }\n  \n\n  private def liftMemberFunc(func: NuFunDef)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (NuFunDef, LocalContext) = {\n    log(s\"liftMemberFunc $func under $ctx # $cache # $globFuncs # $outer\")\n    val NuFunDef(rec, nm, sn, tpVs, body) = func\n    body match{\n      case Left(Lam(lhs@Tup(etts), rhs)) =>\n        val lctx = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None)\n        val lret = liftTuple(lhs)(using ctx.addV(lctx.vSet))\n        val ret = liftTerm(rhs)(using ctx.addV(lctx.vSet).addT(tpVs))\n        (func.copy(rhs = Left(Lam(lret._1, ret._1)))(func.declareLoc, func.virtualLoc, func.mutLoc, func.signature, func.outer, func.genField, func.annotations), ret._2 -+ lret._2) \n      case Left(value) => \n        val ret = liftTerm(value)(using ctx.addT(tpVs))\n        (func.copy(rhs = Left(ret._1))(func.declareLoc, func.virtualLoc, func.mutLoc, func.signature, func.outer, func.genField, func.annotations), ret._2) \n      case Right(PolyType(targs, body)) => \n        val nBody = liftType(body)(using ctx.addT(tpVs))\n        val nTargs = targs.map {\n          case L(tp) => liftTypeName(tp)(using ctx.addT(tpVs)).mapFirst(Left.apply)\n          case R(tv) => R(tv) -> emptyCtx\n        }.unzip\n        (func.copy(rhs = Right(PolyType(nTargs._1, nBody._1)))(func.declareLoc, func.virtualLoc, func.mutLoc, func.signature, func.outer, func.genField, func.annotations),\n          nTargs._2.fold(nBody._2)(_ ++ _))\n      case _ => throw CompilerError(s\"Unimplemented liftMemberFunc: ${func}\") // TODO\n    }\n  }\n\n  private def liftGlobalFunc(func: NuFunDef)(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): Unit = {\n    log(s\"liftGlobalFunc $func under $ctx # $cache # $globFuncs # $outer\")\n    val NuFunDef(rec, nm, _, tpVs, body) = func\n    val nTpVs = tpVs ++ globFuncs.get(nm).get._2.tSet.toList\n    globalFunctions.addOne(body match{\n      case Left(Lam(lhs@Tup(etts), rhs)) =>\n        val tmp = globFuncs.get(nm).get._2.vSet.toList.map(toFldsEle)\n        val lctx = getFreeVars(lhs)(using emptyCtx, cache, globFuncs, None)\n        val lret = liftTuple(lhs)(using ctx.addV(lctx.vSet) ++ globFuncs.get(nm).get._2, cache, globFuncs)\n        val ret = liftTerm(rhs)(using ctx.addV(lctx.vSet) ++ globFuncs.get(nm).get._2, cache, globFuncs)\n        NuFunDef(rec, globFuncs.get(nm).get._1, N, nTpVs, Left(Lam(Tup(lret._1.fields ++ tmp), ret._1)))(N, N, N, N, N, true, Nil) \n      case Left(rhs) => \n        val tmp = globFuncs.get(nm).get._2.vSet.toList.map(toFldsEle)\n        val ret = liftTerm(rhs)(using ctx ++ globFuncs.get(nm).get._2, cache, globFuncs)\n        NuFunDef(rec, globFuncs.get(nm).get._1, N, nTpVs, Left(ret._1))(N, N, N, N, N, true, Nil) \n      case Right(PolyType(targs, body)) => \n        val nBody = liftType(body)(using ctx ++ globFuncs.get(nm).get._2, cache, globFuncs, None)\n        val nTargs = targs.map({\n          case L(tn) => \n            liftTypeName(tn)(using ctx.addT(nTpVs), cache, globFuncs, None) match\n              case (tn, ctx) => (L(tn), ctx)\n          case R(tv) => R(tv) -> emptyCtx}).unzip\n        NuFunDef(rec, globFuncs.get(nm).get._1, N, nTpVs, Right(PolyType(nTargs._1, nBody._1)))(N, N, N, N, N, true, Nil) \n      case _ => throw CompilerError(s\"Unimplemented liftGlobalFunc: ${func}\")\n    })\n  }\n  \n\n  private def grepFieldsInTrm(trm: Term): Option[Var] = trm match{\n    case Let(isRec, name, rhs, body) => Some(name)\n    case _ => None\n  }\n\n  private def mixClsInfos(clsInfos: Map[String, ClassInfoCache], funcInfos: Map[String, LocalContext])(using cache: ClassCache): (Map[String, ClassInfoCache], Map[String, LocalContext]) = {\n    val nameInfoMap: MutMap[String, ClassInfoCache] = MutMap(clsInfos.toSeq*)\n    val nameFuncMap: MutMap[String, LocalContext] = MutMap(funcInfos.toSeq*)\n    log(s\"mix cls infos $nameInfoMap, $nameFuncMap\")\n    val clsNmsAsTypeNm = clsInfos.keySet.map(x => TypeName(x))\n    val len = clsInfos.size + nameFuncMap.size\n    for(_ <- 0 to len){\n      nameInfoMap.toList.foreach{case (nmOfCls, infoOfCls@ClassInfoCache(_, _, ctx, flds, inners, sups, _, _, _)) => {\n        val usedClsNmList = ctx.vSet.map(_.name).intersect(clsInfos.keySet)\n        val newCtxForCls_tmp = usedClsNmList.foldLeft(ctx)((c1, c2) => c1 ++ nameInfoMap.get(c2).get.capturedParams)\n\n        val usedFuncNmList = ctx.vSet.map(_.name).intersect(funcInfos.keySet)\n        val newCtxForCls = usedFuncNmList.foldLeft(newCtxForCls_tmp)((c, x) => c ++ nameFuncMap.get(x).get)\n\n        val supClsNmList = infoOfCls.supClses\n        supClsNmList.foreach(c2 => flds.addAll(\n          nameInfoMap.get(c2.name).map(_.fields).getOrElse(cache.get(c2).map(_.fields).getOrElse(Nil))\n          ))\n        supClsNmList.foreach(c2 => inners.addAll(\n          nameInfoMap.get(c2.name).map(_.innerClses).getOrElse(cache.get(c2).map(_.innerClses).getOrElse(Nil))\n          ))\n        val newCtxFromSup = supClsNmList.map(c2 => \n          nameInfoMap.get(c2.name).map(_.capturedParams).getOrElse(cache.get(c2).map(_.capturedParams).getOrElse(emptyCtx))\n          ).fold(emptyCtx)(_ ++ _)\n        infoOfCls.capturedParams = newCtxForCls ++ newCtxFromSup\n      }}\n      nameFuncMap.toList.foreach((nm, ctx) => {\n        val usedClsNmList = ctx.vSet.map(_.name).intersect(clsInfos.keySet)\n        val usedFuncNmList = ctx.vSet.map(_.name).intersect(funcInfos.keySet)\n        val nCtx = (usedClsNmList.map(x => nameInfoMap.get(x).get.capturedParams) ++ usedFuncNmList.map(x => nameFuncMap.get(x).get)).foldLeft(ctx)(_ ++ _)\n        nameFuncMap.update(nm, nCtx)\n      })\n    }\n    nameInfoMap.foreach((x1, x2) => x2.capturedParams = (x2.capturedParams.extV(clsInfos.keySet.map(Var(_)))).extV(funcInfos.keySet.map(Var(_))).extT(x2.innerClses.keySet))\n    nameFuncMap.toList.foreach((x, c) => nameFuncMap.update(x, c.extV(clsInfos.keySet.map(Var(_))).extV(funcInfos.keySet.map(Var(_)))))\n    log(s\"mix result: $nameInfoMap, $nameFuncMap\")\n    nameInfoMap.toMap -> nameFuncMap.toMap\n  }\n  \n\n  private def liftEntities(etts: List[Statement])(using ctx: LocalContext, cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): (List[Statement], LocalContext) = {\n    log(\"liftEntities: \" ++ etts.headOption.map(_.toString()).getOrElse(\"\"))\n    val (newCls, newFuncs, rstTrms) = splitEntities(etts)\n    val newClsNms = newCls.map(x => Var(x.nme.name)).toSet\n    val newFuncNms = newFuncs.map(_.nme)\n    val nmsInTrm = rstTrms.flatMap(grepFieldsInTrm)\n    val clsInfos = newCls.map(x => {\n      val infos = collectClassInfo(x, newCls.map(_.nme).toSet)(using emptyCtx)\n      infos.capturedParams = infos.capturedParams.intersect(ctx.addT(infos.capturedParams.tSet).addV(newClsNms ++ newFuncNms ++ nmsInTrm -- globFuncs.keySet ++ outer.map(_ => Var(\"this\"))))\n      x.nme.name -> infos}).toMap\n    val funcInfos = \n      newFuncs.map(x => x.nme.name -> (x.rhs match {\n        case Left(trm) => getFreeVars(trm)(using emptyCtx)\n                            .intersect(ctx.addV(newClsNms ++ newFuncNms ++ nmsInTrm -- globFuncs.keySet ++ outer.map(_ => Var(\"this\"))))\n                            .extT(x.tparams) \n        case _ => emptyCtx})\n      ).toMap\n    log(\"captured cls infos: \\n\" ++ clsInfos.toString())\n    log(\"captured func infos: \\n\" ++ funcInfos.toString())\n    val (refinedClsInfo, refinedFuncInfo) = mixClsInfos(clsInfos, funcInfos)\n    val newCache = cache ++ refinedClsInfo.map(x => (TypeName(x._1) -> x._2))\n    refinedClsInfo.foreach((_, clsi) => completeClsInfo(clsi)(using newCache))\n    val newGlobalFuncs = refinedFuncInfo.map((nm, vs) => (Var(nm) -> (Var(genAnoName(nm)), vs)))\n\n    newCls.foreach(x => liftTypeDef(x)(using newCache, globFuncs ++ newGlobalFuncs))\n    (newFuncs zip refinedFuncInfo).foreach((f, c) => liftGlobalFunc(f)(using ctx, newCache, globFuncs ++ newGlobalFuncs))\n    val (liftedTerms, termVs) = rstTrms.map(liftTerm(_)(using ctx.addV(newFuncNms), newCache, globFuncs ++ newGlobalFuncs)).unzip\n    (liftedTerms, (termVs).fold(emptyCtx)(_ ++ _))\n  }\n\n  private def completeClsInfo(clsInfo: ClassInfoCache)(using cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)]): Unit = {\n    val ClassInfoCache(_, nName, freeVs, flds, inners, _, _, cls, _) = clsInfo\n    val (clsList, _, _) = splitEntities(cls.body.entities)\n    val innerClsNmSet = clsList.map(_.nme).toSet\n    val innerClsInfos = clsList.map(x => x.nme.name -> collectClassInfo(x, innerClsNmSet)(using asContextV(freeVs.vSet ++ flds), cache, globFuncs, Some(clsInfo))).toMap\n    val refinedInfos = mixClsInfos(innerClsInfos, Map())._1.map(x => (TypeName(x._1) -> x._2))\n    refinedInfos.foreach((_, info) => completeClsInfo(info)(using cache ++ refinedInfos))\n    inners.addAll(refinedInfos)\n  }\n\n  private def liftTypeDef(target: NuTypeDef)(using cache: ClassCache, globFuncs: Map[Var, (Var, LocalContext)], outer: Option[ClassInfoCache]): Unit = {\n    def getAllInners(sups: Set[TypeName]): ClassCache = {\n      sups.flatMap(\n        t => cache.get(t).map(x => getAllInners(x.supClses) ++ x.innerClses)\n      ).flatten.toMap\n    }\n    log(\"lift type \" + target.toString() + \" with cache \" + cache.toString())\n    val NuTypeDef(kind, nme, tps, params, _, sig, pars, supAnn, thisAnn, body) = target\n    val nOuter = cache.get(nme)\n    val ClassInfoCache(_, nName, freeVs, flds, inners, sups, _, _, _) = nOuter.get\n    val (clsList, funcList, termList) = splitEntities(body.entities)\n    val innerNmsSet = clsList.map(_.nme).toSet\n\n    val nCache = cache ++ inners ++ getAllInners(sups)\n    val nTps = (tps.map(_._2) ++ (freeVs.tSet -- nCache.keySet).toList).distinct\n    val nCtx = freeVs.addT(nTps)\n    val nParams = \n      outer.map(x => List(toFldsEle(Var(genParName(x.liftedNm.name))))).getOrElse(Nil)\n      ++ params.fold(Nil)(t => t.fields.map{\n        case (Some(nm), Fld(flags, term)) => (Some(nm), Fld(flags, liftTerm(term)(using emptyCtx, nCache, globFuncs, nOuter)._1))\n        case other => other\n      })\n      ++ freeVs.vSet.map(toFldsEle) \n    val nPars = pars.map(liftTerm(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip\n    val nFuncs = funcList.map(liftMemberFunc(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip\n    val nTerms = termList.map(liftTerm(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip\n    clsList.foreach(x => liftTypeDef(x)(using nCache, globFuncs, nOuter))\n    retSeq = retSeq.appended(NuTypeDef(\n      kind, nName, nTps.map((None, _)), kind match \n        case Mod => None\n        case _ => S(Tup(nParams))\n      , None, None, nPars._1, None, None, TypingUnit(nFuncs._1 ++ nTerms._1))(None, None, Nil))\n  }\n\n  def liftTypingUnit(rawUnit: TypingUnit): TypingUnit = {\n    log(\"=========================\\n\")\n    log(s\"lifting: \\n$rawUnit\\n\")\n    retSeq = Nil\n    globalFunctions.clear()\n    val re = liftEntities(rawUnit.entities)(using emptyCtx, Map(), Map(), None)\n    log(s\"freeVars: ${re._2}\")\n    TypingUnit(retSeq.toList ++ globalFunctions.toList ++ re._1)\n  }\n}\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/Document.scala",
    "content": "package mlscript.compiler.utils\n\nenum Document:\n  case Indented(content: Document)\n  case Unindented(content: Document)\n  case Stacked(docs: List[Document], emptyLines: Boolean = false)\n  case Lined(docs: List[Document], separator: Document)\n  case Raw(s: String)\n\n  def <:>(other: Document) = line(List(this, other))\n  def <#>(other: Document) = line(List(this, other), sep = \"\")\n\n  override def toString: String = print\n\n  def print: String = {\n    val sb = StringBuffer()\n\n    def rec(d: Document)(implicit ind: Int, first: Boolean): Unit = d match {\n      case Raw(s) =>\n        if (first && s.nonEmpty) sb.append(\"  \" * ind)\n        sb.append(s)\n      case Indented(doc) =>\n        rec(doc)(using ind + 1, first)\n      case Unindented(doc) =>\n        assume(ind > 0)\n        rec(doc)(using ind - 1, first)\n      case Lined(Nil, _) => // skip\n      case Lined(docs, sep) =>\n        rec(docs.head)\n        docs.tail foreach { doc =>\n          rec(sep)(using ind, false)\n          rec(doc)(using ind, false)\n        }\n      case Stacked(Nil, _) => // skip\n      case Stacked(docs, emptyLines) =>\n        rec(docs.head)\n        docs.tail foreach { doc =>\n          sb.append(\"\\n\")\n          if (emptyLines) sb.append(\"\\n\")\n          rec(doc)(using ind, true)\n        }\n    }\n\n    rec(this)(using 0, true)\n    sb.toString\n  }\n\ndef stack(docs: Document*) = Document.Stacked(docs.toList)\ndef stack_list(docs: List[Document]) = Document.Stacked(docs)\ndef line(docs: List[Document], sep: String = \" \") = Document.Lined(docs, Document.Raw(sep))\ndef raw(s: String) = Document.Raw(s)\ndef indent(doc: Document) = Document.Indented(doc)\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/PrettyPrinter.scala",
    "content": "package mlscript.compiler\n\nimport mlscript.{TypingUnit, NuFunDef, NuTypeDef, Term, Tup}\nimport mlscript.compiler.DebugOutput\n\n// For pretty printing terms in debug output.\nobject PrettyPrinter:\n  def show(term: Term): DebugOutput = DebugOutput.Code(term.showDbg.linesIterator.toList)\n  def show(unit: TypingUnit): DebugOutput = DebugOutput.Code(showTypingUnit(unit, 0).linesIterator.toList)\n  def show(funDef: NuFunDef): DebugOutput = DebugOutput.Code(showFunDef(funDef).linesIterator.toList)\n  def show(tyDef: NuTypeDef): DebugOutput = DebugOutput.Code(showTypeDef(tyDef, 0).linesIterator.toList)\n\n  def showTypingUnit(unit: TypingUnit, indent: Int = 0): String =\n    val head = if indent == 0 then \"TypingUnit \" else \" \"\n    val singleLine = head + unit.entities.iterator.map {\n      case term: Term => show(term)\n      case tyDef: NuTypeDef => showTypeDef(tyDef)\n      case funDef: NuFunDef => showFunDef(funDef)\n      case others => others.showDbg\n    }.mkString(\"{\", \"; \", \"}\")\n    if (singleLine.length < 60)\n      singleLine\n    else\n      val indentStr = \" \" * (indent * 2)\n      head + unit.entities.iterator.map {\n        case term: Term => show(term)\n        case tyDef: NuTypeDef => showTypeDef(tyDef)\n        case funDef: NuFunDef => showFunDef(funDef)\n        case others => others.showDbg\n      }.map(indentStr + \"  \" + _).mkString(\"{\\n\", \"\\n\", s\"\\n$indentStr}\")\n  \n  def showFunDef(funDef: NuFunDef): String =\n    val st = (funDef.isLetRec) match {\n      case None => \"fun\"\n      case Some(false) => \"let\"\n      case Some(true) => \"let'\"\n    }\n    s\"$st ${funDef.nme.name}\"\n      + (if funDef.tparams.isEmpty\n         then \"\"\n         else funDef.tparams.map(_.name).mkString(\"[\", \", \", \"]\"))\n      + \" = \"\n      + funDef.rhs.fold(_.showDbg, _.show(newDefs = true))\n\n  def showTypeDef(tyDef: NuTypeDef, indent: Int = 0): String =\n    s\"${tyDef.kind.str} ${tyDef.nme.name}\"\n      + (if tyDef.tparams.isEmpty\n         then \"\"\n         else tyDef.tparams.map(_._2.name).mkString(\"[\", \",\", \"]\"))\n      + tyDef.params.fold(\"\")(params => s\"(${params.showDbg})\")\n      + (if tyDef.parents.isEmpty\n         then \"\"\n         else \": \" + tyDef.parents.map(_.showDbg).mkString(\", \"))\n      + showTypingUnit(tyDef.body, indent + 1)\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/codegen/CppAst.scala",
    "content": "package mlscript.compiler.codegen.cpp\n\nimport mlscript._\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\nimport mlscript.compiler.utils._\n\nimport scala.language.implicitConversions\n\ngiven Conversion[String, Document] = raw\n\nenum Specifier:\n  case Extern\n  case Static\n  case Inline\n\n  def toDocument = raw:\n    this match\n    case Extern => \"extern\"\n    case Static => \"static\"\n    case Inline => \"inline\"\n\n  override def toString: Str = toDocument.print\n\nobject Type:\n  def toDocuments(args: Ls[Type], sep: Document, extraTypename: Bool = false): Document =\n    args.iterator.zipWithIndex.map {\n      case (x, 0) =>\n        x.toDocument(extraTypename)\n      case (x, _) =>\n        sep <#> x.toDocument(extraTypename)\n    }.fold(raw(\"\"))(_ <#> _)\n\n  def toDocuments(args: Ls[(Str, Type)], sep: Document): Document =\n    args.iterator.zipWithIndex.map {\n      case (x, 0) =>\n        x._2.toDocument() <:> raw(x._1)\n      case (x, _) =>\n        sep <#> x._2.toDocument() <:> raw(x._1)\n    }.fold(raw(\"\"))(_ <#> _)\n\nenum Type:\n  case Prim(name: Str)\n  case Ptr(inner: Type)\n  case Ref(inner: Type)\n  case Array(inner: Type, size: Opt[Int])\n  case FuncPtr(ret: Type, args: List[Type])\n  case Struct(name: Str)\n  case Enum(name: Str)\n  case Template(name: Str, args: List[Type])\n  case Var(name: Str)\n  case Qualifier(inner: Type, qual: Str)\n\n  def toDocument(extraTypename: Bool = false): Document =\n    def aux(x: Type): Document = x match\n      case Prim(name) => name\n      case Ptr(inner) => aux(inner) <#> \"*\" \n      case Ref(inner) => aux(inner) <#> \"&\"\n      case Array(inner, size) => aux(inner) <#> \"[\" <#> size.fold(raw(\"\"))(x => x.toString) <#> \"]\"\n      case FuncPtr(ret, args) => aux(ret) <#> \"(\" <#> Type.toDocuments(args, sep = \", \") <#> \")\"\n      case Struct(name) => s\"struct $name\"\n      case Enum(name) => s\"enum $name\"\n      case Template(name, args) => s\"$name\" <#> \"<\" <#> Type.toDocuments(args, sep = \", \") <#> \">\"\n      case Var(name) => name\n      case Qualifier(inner, qual) => aux(inner) <:> qual\n    aux(this)\n\n  override def toString: Str = toDocument().print\n\nobject Stmt:\n  def toDocuments(decl: Ls[Decl], stmts: Ls[Stmt]): Document =\n    stack_list(decl.map(_.toDocument) ++ stmts.map(_.toDocument))\n\nenum Stmt:\n  case AutoBind(lhs: Ls[Str], rhs: Expr)\n  case Assign(lhs: Str, rhs: Expr)\n  case Return(expr: Expr)\n  case If(cond: Expr, thenStmt: Stmt, elseStmt: Opt[Stmt])\n  case While(cond: Expr, body: Stmt)\n  case For(init: Stmt, cond: Expr, update: Stmt, body: Stmt)\n  case ExprStmt(expr: Expr)\n  case Break\n  case Continue\n  case Block(decl: Ls[Decl], stmts: Ls[Stmt])\n  case Switch(expr: Expr, cases: Ls[(Expr, Stmt)])\n  case Raw(stmt: Str)\n\n  def toDocument: Document =\n    def aux(x: Stmt): Document = x match\n      case AutoBind(lhs, rhs) =>\n        lhs match\n          case Nil => rhs.toDocument\n          case x :: Nil => \"auto\" <:> x <:> \"=\" <:> rhs.toDocument <#> \";\"\n          case _ => \"auto\" <:> lhs.mkString(\"[\", \",\", \"]\") <:> \"=\" <:> rhs.toDocument <#> \";\"\n      case Assign(lhs, rhs) => lhs <#> \" = \" <#> rhs.toDocument <#> \";\"\n      case Return(expr) => \"return \" <#> expr.toDocument <#> \";\"\n      case If(cond, thenStmt, elseStmt) =>\n        \"if (\" <#> cond.toDocument <#> \")\" <#> thenStmt.toDocument <:> elseStmt.fold(raw(\"\"))(x => \"else\" <:> x.toDocument)\n      case While(cond, body) =>\n        \"while (\" <#> cond.toDocument <#> \")\" <#> body.toDocument\n      case For(init, cond, update, body) =>\n        \"for (\" <#> init.toDocument <#> \"; \" <#> cond.toDocument <#> \"; \" <#> update.toDocument <#> \")\" <#> body.toDocument\n      case ExprStmt(expr) => expr.toDocument <#> \";\"\n      case Break => \"break;\"\n      case Continue => \"continue;\"\n      case Block(decl, stmts) => \n        stack(\n          \"{\",\n          Stmt.toDocuments(decl, stmts) |> indent,\n          \"}\")\n      case Switch(expr, cases) =>\n        \"switch (\" <#> expr.toDocument <#> \")\" <#> \"{\" <#> stack_list(cases.map {\n          case (cond, stmt) => \"case \" <#> cond.toDocument <#> \":\" <#> stmt.toDocument\n        }) <#> \"}\"\n      case Raw(stmt) => stmt\n    aux(this)\n\nobject Expr:\n  def toDocuments(args: Ls[Expr], sep: Document): Document =\n    args.zipWithIndex.map {\n      case (x, i) =>\n        if i == 0 then x.toDocument\n        else sep <#> x.toDocument\n    }.fold(raw(\"\"))(_ <#> _)\n  \nenum Expr:\n  case Var(name: Str)\n  case IntLit(value: BigInt)\n  case DoubleLit(value: Double)\n  case StrLit(value: Str)\n  case CharLit(value: Char)\n  case Call(func: Expr, args: Ls[Expr])\n  case Member(expr: Expr, member: Str)\n  case Index(expr: Expr, index: Expr)\n  case Unary(op: Str, expr: Expr)\n  case Binary(op: Str, lhs: Expr, rhs: Expr)\n  case Initializer(exprs: Ls[Expr])\n  case Constructor(name: Str, init: Expr)\n\n  def toDocument: Document =\n    def aux(x: Expr): Document = x match\n      case Var(name) => name\n      case IntLit(value) => value.toString\n      case DoubleLit(value) => value.toString\n      case StrLit(value) => s\"\\\"$value\\\"\" // need more reliable escape utils\n      case CharLit(value) => value.toInt.toString\n      case Call(func, args) => aux(func) <#> \"(\" <#> Expr.toDocuments(args, sep = \", \") <#> \")\"\n      case Member(expr, member) => aux(expr) <#> \"->\" <#> member\n      case Index(expr, index) => aux(expr) <#> \"[\" <#> aux(index) <#> \"]\"\n      case Unary(op, expr) => \"(\" <#> op <#> aux(expr) <#> \")\"\n      case Binary(op, lhs, rhs) => \"(\" <#> aux(lhs) <#> op <#> aux(rhs) <#> \")\"\n      case Initializer(exprs) => \"{\" <#> Expr.toDocuments(exprs, sep = \", \") <#> \"}\"\n      case Constructor(name, init) => name <#> init.toDocument\n    aux(this)\n\ncase class CompilationUnit(includes: Ls[Str], decls: Ls[Decl], defs: Ls[Def]):\n  def toDocument: Document =\n    stack_list(includes.map(x => raw(x)) ++ decls.map(_.toDocument) ++ defs.map(_.toDocument))\n  def toDocumentWithoutHidden: Document =\n    val hiddenNames = Set(\n      \"HiddenTheseEntities\", \"True\", \"False\", \"Callable\", \"List\", \"Cons\", \"Nil\", \"Option\", \"Some\", \"None\", \"Pair\", \"Tuple2\", \"Tuple3\", \"Nat\", \"S\", \"O\"\n    )\n    stack_list(defs.filterNot { \n      case d: Def.StructDef => hiddenNames.contains(d.name.stripPrefix(\"_mls_\"))\n      case _ => false\n    }.map(_.toDocument))\n\nenum Decl:\n  case StructDecl(name: Str)\n  case EnumDecl(name: Str)\n  case FuncDecl(ret: Type, name: Str, args: Ls[Type])\n  case VarDecl(name: Str, typ: Type)\n\n  def toDocument: Document =\n    def aux(x: Decl): Document = x match\n      case StructDecl(name) => s\"struct $name;\"\n      case EnumDecl(name) => s\"enum $name;\"\n      case FuncDecl(ret, name, args) => ret.toDocument() <#> s\" $name(\" <#> Type.toDocuments(args, sep = \", \")  <#> \");\"\n      case VarDecl(name, typ) => typ.toDocument() <#> s\" $name;\"\n    aux(this)\n\nenum Def:\n  case StructDef(name: Str, fields: Ls[(Str, Type)], inherit: Opt[Ls[Str]], methods: Ls[Def] = Ls.empty)\n  case EnumDef(name: Str, fields: Ls[(Str, Opt[Int])])\n  case FuncDef(specret: Type, name: Str, args: Ls[(Str, Type)], body: Stmt.Block, or: Bool = false, virt: Bool = false)\n  case VarDef(typ: Type, name: Str, init: Opt[Expr])\n  case RawDef(raw: Str)\n\n  def toDocument: Document =\n    def aux(x: Def): Document = x match\n      case StructDef(name, fields, inherit, defs) =>\n        stack(\n          s\"struct $name\" <#> (if inherit.nonEmpty then \": public\" <:> inherit.get.mkString(\", \") else \"\" ) <:> \"{\",\n            stack_list(fields.map {\n                case (name, typ) => typ.toDocument() <#> \" \" <#> name <#> \";\"\n            }) |> indent,\n            stack_list(defs.map(_.toDocument)) |> indent,\n          \"};\"\n        )\n      case EnumDef(name, fields) =>\n        s\"enum $name\" <:> \"{\" <#> stack_list(fields.map {\n          case (name, value) => value.fold(s\"$name\")(x => s\"$name = $x\")\n        }) <#> \"};\"\n      case FuncDef(specret, name, args, body, or, virt) =>\n        (if virt then \"virtual \" else \"\") \n        <#> specret.toDocument() <#> s\" $name(\" <#> Type.toDocuments(args, sep = \", \") <#> \")\" <#> (if or then \" override\" else \"\") <#> body.toDocument\n      case VarDef(typ, name, init) =>\n        typ.toDocument() <#> s\" $name\" <#> init.fold(raw(\"\"))(x => \" = \" <#> x.toDocument) <#> raw(\";\")\n      case RawDef(x) => x\n    aux(this)"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/codegen/CppCodeGen.scala",
    "content": "package mlscript.compiler.codegen.cpp\n\nimport mlscript.compiler.ir.{Expr => IExpr, _}\nimport mlscript.compiler.utils._\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\nimport scala.collection.mutable.ListBuffer\n\ndef codegen(prog: Program): CompilationUnit =\n  val codegen = CppCodeGen()\n  codegen.codegen(prog)\n\nprivate class CppCodeGen:\n  def mapName(name: Name): Str = \"_mls_\" + name.str.replace('$', '_').replace('\\'', '_')\n  def mapName(name: Str): Str = \"_mls_\" + name.replace('$', '_').replace('\\'', '_')\n  val freshName = Fresh(div = '_');\n  val mlsValType = Type.Prim(\"_mlsValue\")\n  val mlsUnitValue = Expr.Call(Expr.Var(\"_mlsValue::create<_mls_Unit>\"), Ls());\n  val mlsRetValue  = \"_mls_retval\"\n  val mlsRetValueDecl = Decl.VarDecl(mlsRetValue, mlsValType)\n  val mlsMainName = \"_mlsMain\"\n  val mlsPrelude = \"#include \\\"mlsprelude.h\\\"\"\n  val mlsPreludeImpl = \"#include \\\"mlsprelude.cpp\\\"\"\n  val mlsInternalClass = Set(\"True\", \"False\", \"Boolean\", \"Callable\")\n  val mlsObject = \"_mlsObject\"\n  val mlsBuiltin = \"builtin\"\n  val mlsEntryPoint = s\"int main() { return _mlsLargeStack(_mlsMainWrapper); }\";\n  def mlsIntLit(x: BigInt) = Expr.Call(Expr.Var(\"_mlsValue::fromIntLit\"), Ls(Expr.IntLit(x)))\n  def mlsStrLit(x: Str) = Expr.Call(Expr.Var(\"_mlsValue::fromStrLit\"), Ls(Expr.StrLit(x)))\n  def mlsCharLit(x: Char) = Expr.Call(Expr.Var(\"_mlsValue::fromIntLit\"), Ls(Expr.CharLit(x)))\n  def mlsNewValue(cls: Str, args: Ls[Expr]) = Expr.Call(Expr.Var(s\"_mlsValue::create<$cls>\"), args)\n  def mlsIsValueOf(cls: Str, scrut: Expr) = Expr.Call(Expr.Var(s\"_mlsValue::isValueOf<$cls>\"), Ls(scrut))\n  def mlsIsIntLit(scrut: Expr, lit: mlscript.IntLit) = Expr.Call(Expr.Var(\"_mlsValue::isIntLit\"), Ls(scrut, Expr.IntLit(lit.value)))\n  def mlsDebugPrint(x: Expr) = Expr.Call(Expr.Var(\"_mlsValue::print\"), Ls(x))\n  def mlsTupleValue(init: Expr) = Expr.Constructor(\"_mlsValue::tuple\", init)\n  def mlsAs(name: Str, cls: Str) = Expr.Var(s\"_mlsValue::as<$cls>($name)\")\n  def mlsAsUnchecked(name: Str, cls: Str) = Expr.Var(s\"_mlsValue::cast<$cls>($name)\")\n  def mlsObjectNameMethod(name: Str) = s\"constexpr static inline const char *typeName = \\\"${name}\\\";\"\n  def mlsTypeTag() = s\"constexpr static inline uint32_t typeTag = nextTypeTag();\"\n  def mlsTypeTag(n: Int) = s\"constexpr static inline uint32_t typeTag = $n;\"\n  def mlsCommonCreateMethod(cls: Str, fields: Ls[Str], id: Int) =\n    val parameters = fields.map{x => s\"_mlsValue $x\"}.mkString(\", \")\n    val fieldsAssignment = fields.map{x => s\"_mlsVal->$x = $x; \"}.mkString\n    s\"static _mlsValue create($parameters) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) $cls; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; $fieldsAssignment return _mlsValue(_mlsVal); }\"\n  def mlsCommonPrintMethod(fields: Ls[Str]) =\n    if fields.isEmpty then s\"virtual void print() const override { std::printf(\\\"%s\\\", typeName); }\"\n    else\n      val fieldsPrint = fields.map{x => s\"this->$x.print(); \"}.mkString(\"std::printf(\\\", \\\"); \")\n      s\"virtual void print() const override { std::printf(\\\"%s\\\", typeName); std::printf(\\\"(\\\"); $fieldsPrint std::printf(\\\")\\\"); }\"\n  def mlsCommonDestructorMethod(cls: Str, fields: Ls[Str]) = \n    val fieldsDeletion = fields.map{x => s\"_mlsValue::destroy(this->$x); \"}.mkString\n    s\"virtual void destroy() override { $fieldsDeletion operator delete (this, std::align_val_t(_mlsAlignment)); }\"\n  def mlsThrowNonExhaustiveMatch = Stmt.Raw(\"_mlsNonExhaustiveMatch();\");\n  def mlsCall(fn: Str, args: Ls[Expr]) = Expr.Call(Expr.Var(\"_mlsCall\"), Expr.Var(fn) :: args)\n  def mlsMethodCall(cls: ClassRef, method: Str, args: Ls[Expr]) =\n    Expr.Call(Expr.Member(Expr.Call(Expr.Var(s\"_mlsMethodCall<${cls.name |> mapName}>\"), Ls(args.head)), method), args.tail)\n  def mlsFnWrapperName(fn: Str) = s\"_mlsFn_$fn\"\n  def mlsFnCreateMethod(fn: Str) = s\"static _mlsValue create() { static _mlsFn_$fn mlsFn alignas(_mlsAlignment); mlsFn.refCount = stickyRefCount; mlsFn.tag = typeTag; return _mlsValue(&mlsFn); }\"\n  def mlsNeverValue(n: Int) = if (n <= 1) then Expr.Call(Expr.Var(s\"_mlsValue::never\"), Ls()) else Expr.Call(Expr.Var(s\"_mlsValue::never<$n>\"), Ls())\n\n  case class Ctx(\n    defnCtx: Set[Str],\n  )\n\n  def codegenClassInfo(using ctx: Ctx)(cls: ClassInfo): (Opt[Def], Decl) =\n    val fields = cls.fields.map{x => (x |> mapName, mlsValType)}\n    val parents = if cls.parents.nonEmpty then cls.parents.toList.map(mapName) else mlsObject :: Nil\n    val decl = Decl.StructDecl(cls.name |> mapName)\n    if mlsInternalClass.contains(cls.name) then return (None, decl)\n    val theDef = Def.StructDef(\n      cls.name |> mapName, fields,\n      if parents.nonEmpty then Some(parents) else None,\n      Ls(Def.RawDef(mlsObjectNameMethod(cls.name)),\n         Def.RawDef(mlsTypeTag()),\n         Def.RawDef(mlsCommonPrintMethod(cls.fields.map(mapName))),\n         Def.RawDef(mlsCommonDestructorMethod(cls.name |> mapName, cls.fields.map(mapName))),\n         Def.RawDef(mlsCommonCreateMethod(cls.name |> mapName, cls.fields.map(mapName), cls.id)))\n      ++ cls.methods.map{case (name, defn) => {\n        val (theDef, decl) = codegenDefn(using Ctx(ctx.defnCtx + cls.name))(defn)\n        theDef match\n          case x @ Def.FuncDef(_, name, _, _, _, _) => x.copy(virt = true)\n          case _ => theDef\n      }}\n    )\n    (S(theDef), decl)\n  \n  def toExpr(texpr: TrivialExpr, reifyUnit: Bool = false)(using ctx: Ctx): Opt[Expr] = texpr match\n    case IExpr.Ref(name) => S(Expr.Var(name |> mapName))\n    case IExpr.Literal(mlscript.IntLit(x)) => S(mlsIntLit(x))\n    case IExpr.Literal(mlscript.DecLit(x)) => S(mlsIntLit(x.toBigInt))\n    case IExpr.Literal(mlscript.StrLit(x)) => S(mlsStrLit(x))\n    case IExpr.Literal(mlscript.UnitLit(_)) => if reifyUnit then S(mlsUnitValue) else None\n  \n  def toExpr(texpr: TrivialExpr)(using ctx: Ctx): Expr = texpr match\n    case IExpr.Ref(name) => Expr.Var(name |> mapName)\n    case IExpr.Literal(mlscript.IntLit(x)) => mlsIntLit(x)\n    case IExpr.Literal(mlscript.DecLit(x)) => mlsIntLit(x.toBigInt)\n    case IExpr.Literal(mlscript.StrLit(x)) => mlsStrLit(x)\n    case IExpr.Literal(mlscript.UnitLit(_)) => mlsUnitValue\n  \n\n  def wrapMultiValues(exprs: Ls[TrivialExpr])(using ctx: Ctx): Expr = exprs match\n    case x :: Nil => toExpr(x, reifyUnit = true).get\n    case _ => \n      val init = Expr.Initializer(exprs.map{x => toExpr(x)})\n      mlsTupleValue(init)\n  \n  def codegenCaseWithIfs(scrut: Name, cases: Ls[(Pat, Node)], default: Opt[Node], storeInto: Str)(using decls: Ls[Decl], stmts: Ls[Stmt])(using ctx: Ctx): (Ls[Decl], Ls[Stmt]) =\n    val scrutName = mapName(scrut)\n    val init: Stmt = \n      default.fold(mlsThrowNonExhaustiveMatch)(x => {\n        val (decls2, stmts2) = codegen(x, storeInto)(using Ls.empty, Ls.empty[Stmt])\n        Stmt.Block(decls2, stmts2)\n      })\n    val stmt = cases.foldRight(S(init)) {\n      case ((Pat.Class(cls), arm), nextarm) =>\n        val (decls2, stmts2) = codegen(arm, storeInto)(using Ls.empty, Ls.empty[Stmt])\n        val stmt = Stmt.If(mlsIsValueOf(cls.name |> mapName, Expr.Var(scrutName)), Stmt.Block(decls2, stmts2), nextarm)\n        S(stmt)\n      case ((Pat.Lit(i @ mlscript.IntLit(_)), arm), nextarm) =>\n        val (decls2, stmts2) = codegen(arm, storeInto)(using Ls.empty, Ls.empty[Stmt])\n        val stmt = Stmt.If(mlsIsIntLit(Expr.Var(scrutName), i), Stmt.Block(decls2, stmts2), nextarm)\n        S(stmt)\n      case _ => ???\n    }\n    (decls, stmt.fold(stmts)(x => stmts :+ x))\n\n  def codegenJumpWithCall(defn: DefnRef, args: Ls[TrivialExpr], storeInto: Opt[Str])(using decls: Ls[Decl], stmts: Ls[Stmt])(using ctx: Ctx): (Ls[Decl], Ls[Stmt]) =\n    val call = Expr.Call(Expr.Var(defn.name |> mapName), args.map(toExpr))\n    val stmts2 = stmts ++ Ls(storeInto.fold(Stmt.Return(call))(x => Stmt.Assign(x, call)))\n    (decls, stmts2)\n\n  def codegenOps(op: Str, args: Ls[TrivialExpr])(using ctx: Ctx) = op match\n    case \"+\" => Expr.Binary(\"+\", toExpr(args(0)), toExpr(args(1)))\n    case \"-\" => Expr.Binary(\"-\", toExpr(args(0)), toExpr(args(1)))\n    case \"*\" => Expr.Binary(\"*\", toExpr(args(0)), toExpr(args(1)))\n    case \"/\" => Expr.Binary(\"/\", toExpr(args(0)), toExpr(args(1)))\n    case \"%\" => Expr.Binary(\"%\", toExpr(args(0)), toExpr(args(1)))\n    case \"==\" => Expr.Binary(\"==\", toExpr(args(0)), toExpr(args(1)))\n    case \"!=\" => Expr.Binary(\"!=\", toExpr(args(0)), toExpr(args(1)))\n    case \"<\" => Expr.Binary(\"<\", toExpr(args(0)), toExpr(args(1)))\n    case \"<=\" => Expr.Binary(\"<=\", toExpr(args(0)), toExpr(args(1)))\n    case \">\" => Expr.Binary(\">\", toExpr(args(0)), toExpr(args(1)))\n    case \">=\" => Expr.Binary(\">=\", toExpr(args(0)), toExpr(args(1)))\n    case \"&&\" => Expr.Binary(\"&&\", toExpr(args(0)), toExpr(args(1)))\n    case \"||\" => Expr.Binary(\"||\", toExpr(args(0)), toExpr(args(1)))\n    case \"!\" => Expr.Unary(\"!\", toExpr(args(0)))\n    case _ => mlscript.utils.TODO(\"codegenOps\")\n\n\n  def codegen(expr: IExpr)(using ctx: Ctx): Expr = expr match\n    case x @ (IExpr.Ref(_) | IExpr.Literal(_)) => toExpr(x, reifyUnit = true).get\n    case IExpr.CtorApp(cls, args) => mlsNewValue(cls.name |> mapName, args.map(toExpr))\n    case IExpr.Select(name, cls, field) => Expr.Member(mlsAsUnchecked(name |> mapName, cls.name |> mapName), field |> mapName)\n    case IExpr.BasicOp(name, args) => codegenOps(name, args)\n    case IExpr.AssignField(assignee, cls, field, value) => mlscript.utils.TODO(\"Assign field in the backend\")\n\n  def codegenBuiltin(names: Ls[Name], builtin: Str, args: Ls[TrivialExpr])(using ctx: Ctx): Ls[Stmt] = builtin match\n    case \"error\" => Ls(Stmt.Raw(\"throw std::runtime_error(\\\"Error\\\");\"), Stmt.AutoBind(names.map(mapName), mlsNeverValue(names.size)))\n    case _ => Ls(Stmt.AutoBind(names.map(mapName), Expr.Call(Expr.Var(\"_mls_builtin_\" + builtin), args.map(toExpr))))\n\n  def codegen(body: Node, storeInto: Str)(using decls: Ls[Decl], stmts: Ls[Stmt])(using ctx: Ctx): (Ls[Decl], Ls[Stmt]) = body match\n    case Node.Result(res) => \n      val expr = wrapMultiValues(res)\n      val stmts2 = stmts ++ Ls(Stmt.Assign(storeInto, expr))\n      (decls, stmts2)\n    case Node.Jump(defn, args) =>\n      codegenJumpWithCall(defn, args, S(storeInto))\n    case Node.LetExpr(name, expr, body) =>\n      val stmts2 = stmts ++ Ls(Stmt.AutoBind(Ls(name |> mapName), codegen(expr)))\n      codegen(body, storeInto)(using decls, stmts2)\n    case Node.LetMethodCall(names, cls, method, IExpr.Ref(Name(\"builtin\")) :: args, body) =>\n      val stmts2 = stmts ++ codegenBuiltin(names, args.head.toString.replace(\"\\\"\", \"\"), args.tail)\n      codegen(body, storeInto)(using decls, stmts2)\n    case Node.LetMethodCall(names, cls, method, args, body) =>\n      val call = mlsMethodCall(cls, method.str |> mapName, args.map(toExpr))\n      val stmts2 = stmts ++ Ls(Stmt.AutoBind(names.map(mapName), call))\n      codegen(body, storeInto)(using decls, stmts2)\n    case Node.LetCall(names, defn, args, _, body) =>\n      val call = Expr.Call(Expr.Var(defn.name |> mapName), args.map(toExpr))\n      val stmts2 = stmts ++ Ls(Stmt.AutoBind(names.map(mapName), call))\n      codegen(body, storeInto)(using decls, stmts2)\n    case Node.Case(scrut, cases, default) =>\n      codegenCaseWithIfs(scrut, cases, default, storeInto)\n    \n  private def codegenDefn(using ctx: Ctx)(defn: Defn): (Def, Decl) = defn match\n    case Defn(id, name, params, resultNum, body, _, _) =>\n      val decls = Ls(mlsRetValueDecl)\n      val stmts = Ls.empty[Stmt]\n      val (decls2, stmts2) = codegen(body, mlsRetValue)(using decls, stmts)\n      val stmtsWithReturn = stmts2 :+ Stmt.Return(Expr.Var(mlsRetValue))\n      val theDef = Def.FuncDef(mlsValType, name |> mapName, params.map(x => (x |> mapName, mlsValType)), Stmt.Block(decls2, stmtsWithReturn))\n      val decl = Decl.FuncDecl(mlsValType, name |> mapName, params.map(x => mlsValType))\n      (theDef, decl)\n\n  def codegenTopNode(node: Node)(using ctx: Ctx): (Def, Decl) =\n    val decls = Ls(mlsRetValueDecl)\n    val stmts = Ls.empty[Stmt]\n    val (decls2, stmts2) = codegen(node, mlsRetValue)(using decls, stmts)\n    val stmtsWithReturn = stmts2 :+ Stmt.Return(Expr.Var(mlsRetValue))\n    val theDef = Def.FuncDef(mlsValType, mlsMainName, Ls(), Stmt.Block(decls2, stmtsWithReturn))\n    val decl = Decl.FuncDecl(mlsValType, mlsMainName, Ls())\n    (theDef, decl)\n\n  // Topological sort of classes based on inheritance relationships\n  def sortClasses(prog: Program): Ls[ClassInfo] =\n    var depgraph = prog.classes.map(x => (x.name, x.parents)).toMap\n    var degree = depgraph.view.mapValues(_.size).toMap\n    def removeNode(node: Str) =\n      degree -= node\n      depgraph -= node\n      depgraph = depgraph.view.mapValues(_.filter(_ != node)).toMap\n      degree = depgraph.view.mapValues(_.size).toMap\n    val sorted = ListBuffer.empty[ClassInfo]\n    var work = degree.filter(_._2 == 0).keys.toSet\n    while work.nonEmpty do\n      val node = work.head\n      work -= node\n      sorted.addOne(prog.classes.find(_.name == node).get)\n      removeNode(node)\n      val next = degree.filter(_._2 == 0).keys\n      work ++= next\n    if depgraph.nonEmpty then\n      val cycle = depgraph.keys.mkString(\", \")\n      throw new Exception(s\"Cycle detected in class hierarchy: $cycle\")\n    sorted.toList\n\n  def codegen(prog: Program): CompilationUnit =\n    val sortedClasses = sortClasses(prog)\n    val defnCtx = prog.defs.map(_.name)\n    val (defs, decls) = sortedClasses.map(codegenClassInfo(using Ctx(defnCtx))).unzip\n    val (defs2, decls2) = prog.defs.map(codegenDefn(using Ctx(defnCtx))).unzip\n    val (defMain, declMain) = codegenTopNode(prog.main)(using Ctx(defnCtx))\n    CompilationUnit(Ls(mlsPrelude), decls ++ decls2 :+ declMain, defs.flatten ++ defs2 :+ defMain :+ Def.RawDef(mlsEntryPoint))\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/codegen/CppCompilerHost.scala",
    "content": "package mlscript.compiler.codegen.cpp\n\nimport mlscript._\nimport mlscript.utils.shorthands._\nimport scala.collection.mutable.ListBuffer\n\nfinal class CppCompilerHost(val auxPath: Str):\n  import scala.sys.process._\n  private def ifAnyCppCompilerExists(): Boolean =\n    Seq(\"g++\", \"--version\").! == 0 || Seq(\"clang++\", \"--version\").! == 0\n\n  private def isMakeExists(): Boolean =\n    import scala.sys.process._\n    Seq(\"make\", \"--version\").! == 0\n\n  val ready = ifAnyCppCompilerExists() && isMakeExists()\n  \n  def compileAndRun(src: Str, output: Str => Unit): Unit =\n    if !ready then\n      return\n    val srcPath = os.temp(contents = src, suffix = \".cpp\")\n    val binPath = os.temp(suffix = \".mls.out\")\n    var stdout = ListBuffer[Str]()\n    var stderr = ListBuffer[Str]()\n    val buildLogger = ProcessLogger(stdout :+= _, stderr :+= _)\n    val buildResult = Seq(\"make\", \"-B\", \"-C\", auxPath, \"auto\", s\"SRC=$srcPath\", s\"DST=$binPath\") ! buildLogger\n    if buildResult != 0 then\n      output(\"Compilation failed: \")\n      for line <- stdout do output(line)\n      for line <- stderr do output(line)\n      return\n  \n    stdout.clear()\n    stderr.clear()\n    val runCmd = Seq(binPath.toString)\n    val runResult = runCmd ! buildLogger\n    if runResult != 0 then\n      output(\"Execution failed: \")\n      for line <- stdout do output(line)\n      for line <- stderr do output(line)\n      return\n\n    output(\"Execution succeeded: \")\n    for line <- stdout do output(line)\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/debug/Debug.scala",
    "content": "package mlscript.compiler\n\nabstract class Debug:\n  def trace[T](name: String, pre: Any*)\n              (thunk: => T)\n              (post: T => Any = Debug.noPostTrace): T\n  def log(msg: => String): Unit\n  def writeLine(line: String): Unit\n  def indent(): Unit\n  def outdent(): Unit\n\nobject Debug:\n  val noPostTrace: Any => Any = _ => \"\"\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/debug/DebutOutput.scala",
    "content": "package mlscript.compiler\n\nimport scala.collection.mutable.ArrayBuffer\nimport RainbowDebug.black\n\nenum DebugOutput extends Printable:\n  case Code(lines: List[String])\n  case Map(entries: List[(String, String)])\n  case Plain(content: String)\n\n  def getDebugOutput: DebugOutput = this\n\n  import DebugOutput._\n\n  def toLines(using color: Boolean): List[String] = this match\n    case Code(lines) => if lines.length == 1 then lines else box(lines)\n    case Map(entries) =>\n      if entries.length <= 3 then\n        entries.iterator.map { (key, value) =>\n          s\"$key: $value\"\n        }.mkString(\"{ \", \", \", \" }\") :: Nil\n      else\n        boxMap(entries)\n    case Plain(content) => content.linesIterator.toList\n\nobject DebugOutput:\n  def box(lines: List[String])(using color: Boolean = true): List[String] =\n    val maxWidth = lines.iterator.map(_.length).max\n    val gutterWidth = if lines.length == 1 then 1 else scala.math.log10(lines.length).ceil.toInt\n    val newLines = ArrayBuffer[String]()\n    newLines += \"┌\" + \"─\" * (gutterWidth + 2) + \"┬\" + \"─\" * (maxWidth + 2) + \"┐\"\n    lines.iterator.zipWithIndex.foreach { (line, index) =>\n      newLines += (\"│ \" + (index + 1).toString + \" │ \" + (if color then black else identity)(line.padTo(maxWidth, ' ')) + \" │\")\n    }\n    newLines += \"└\" + \"─\" * (gutterWidth + 2) + \"┴\" + \"─\" * (maxWidth + 2) + \"┘\"\n    newLines.toList\n\n  private val KEY_TEXT = \"(key)\"\n  private val VALUE_TEXT = \"(value)\"\n\n  def boxMap(entries: List[(String, String)])(using color: Boolean = true): List[String] =\n    val keyMaxWidth = entries.iterator.map(_._1.length).max.max(KEY_TEXT.length)\n    val valueMaxWidth = entries.iterator.map(_._2.length).max.max(VALUE_TEXT.length)\n    val newLines = ArrayBuffer[String]()\n    newLines += \"┌\" + \"─\" * (keyMaxWidth + 2) + \"┬\" + \"─\" * (valueMaxWidth + 2) + \"┐\"\n    newLines += (\"│ \" + KEY_TEXT.padTo(keyMaxWidth, ' ') + \" │ \" + VALUE_TEXT.padTo(valueMaxWidth, ' ') + \" │\")\n    newLines += \"├\" + \"─\" * (keyMaxWidth + 2) + \"┼\" + \"─\" * (valueMaxWidth + 2) + \"┤\"\n    entries.foreach { (key, value) =>\n      val reprKey = key.padTo(keyMaxWidth, ' ')\n      val reprValue = (if color then black else identity)(value.padTo(valueMaxWidth, ' '))\n      newLines += (\"│ \" + reprKey + \" │ \" + reprValue + \" │\")\n    }\n    newLines += \"└\" + \"─\" * (keyMaxWidth + 2) + \"┴\" + \"─\" * (valueMaxWidth + 2) + \"┘\"\n    newLines.toList"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/debug/DummyDebug.scala",
    "content": "package mlscript.compiler\n\nobject DummyDebug extends Debug:\n  def trace[T](name: String, pre: Any*)\n              (thunk: => T)\n              (post: T => Any = Debug.noPostTrace): T = thunk\n  inline def log(msg: => String): Unit = ()\n  def writeLine(line: String): Unit = ()\n  def indent(): Unit = ()\n  def outdent(): Unit = ()\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/debug/Printable.scala",
    "content": "package mlscript.compiler\n\ntrait Printable:\n  def getDebugOutput: DebugOutput\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/debug/RainbowDebug.scala",
    "content": "package mlscript.compiler\n\nimport scala.collection.mutable.ArrayBuffer\nimport scala.collection.immutable.StringOps\n\nclass RainbowDebug(color: Boolean = true) extends Debug:\n  import RainbowDebug._\n\n  private inline def currentColor =\n    if color then colors(privIndent % colors.size) else identity[String]\n  private inline def beginMark = currentColor(\"┌\")\n  private inline def endMark = currentColor(\"└\")\n  private var privIndent = 0\n  def indent(): Unit = ()\n  def outdent(): Unit = ()\n\n  def trace[T](name: String, pre: Any*)\n              (thunk: => T)\n              (post: T => Any): T = {\n    printPrologue(name, pre.map(toLines(_)(using color)))\n    privIndent += 1\n    val res =\n      try thunk\n      finally privIndent -= 1\n    if (post eq Debug.noPostTrace) {\n      log(s\"$endMark $name\")\n    } else {\n      val result = post(res)\n      printEpilogue(name, toLines(result)(using color))\n    }\n    res\n  }\n\n  private def printPrologue(name: String, things: Iterable[List[String]]): Unit =\n    val leadingLength = name.length + 1\n    val leadingSpaces = \" \" * leadingLength\n    things.headOption.foreach {\n      case Nil => ()\n      case head :: Nil =>\n        log(s\"$beginMark ${name} ${if color then black(head) else head}\")\n      case list =>\n        log(s\"$beginMark ${name}\")\n        privIndent += 1\n        list.foreach { line => log(line) }\n        privIndent -= 1\n    }\n    privIndent += 1\n    things.tail.foreach { _.foreach { log(_) } }\n    privIndent -= 1\n\n  private def printEpilogue(name: String, lines: List[String]): Unit =\n    val leadingLength = name.length + 3\n    val leadingSpaces = \" \" * leadingLength\n    lines match {\n      case Nil => ()\n      case head :: Nil =>\n        log(s\"$endMark $name ${if color then black(head) else head}\")\n      case items =>\n        log(s\"$endMark $name\")\n        items.foreach { line => log(s\"  $line\") }\n    }\n\n  inline def log(msg: => String): Unit =\n    import scala.collection.mutable.StringBuilder\n    val indentBuilder = StringBuilder()\n    for i <- 0 until privIndent do\n      indentBuilder ++= (if color then colors(i % colors.size) else identity[String])(\"│ \")\n    writeLine(\"[mono] \" + indentBuilder.toString + msg)\n\n  def writeLine(line: String): Unit = println(line)\n\nobject RainbowDebug:\n  def toLines(thingy: Any)(using color: Boolean): List[String] =\n    thingy match\n      case printable: Printable => printable.getDebugOutput.toLines\n      case _ => thingy.toString.linesIterator.toList\n\n  val colors = ArrayBuffer(red, yellow, green, cyan, blue, magenta)\n\n  def red(content: String): String =\n    Console.RED + content + Console.RESET\n  def yellow(content: String): String =\n    Console.YELLOW + content + Console.RESET\n  def green(content: String): String =\n    Console.GREEN + content + Console.RESET\n  def cyan(content: String): String =\n    Console.CYAN + content + Console.RESET\n  def blue(content: String): String =\n    Console.BLUE + content + Console.RESET\n  def magenta(content: String): String =\n    Console.MAGENTA + content + Console.RESET\n\n  def black(content: String): String =\n    Console.BLACK + content + Console.RESET\n\n  def underline(content: String): String =\n    Console.UNDERLINED + content + Console.RESET\n  def bold(content: String): String =\n    Console.BOLD + content + Console.RESET\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/debug/TreeDebug.scala",
    "content": "package mlscript.compiler\n\nimport scala.collection.mutable.ArrayBuffer\n\nclass TreeDebug(output: String => Unit) extends RainbowDebug(false):\n  private val lines = ArrayBuffer[String]()\n  private var indentation: Int = 0 \n\n  override inline def writeLine(line: String): Unit = \n    output(\"║\"*indentation ++ line)\n    lines += line\n  \n  override def indent(): Unit = \n    indentation += 1\n  override def outdent(): Unit = \n    indentation -= 1\n\n  def getLines: List[String] = lines.toList\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/ir/Builder.scala",
    "content": "package mlscript.compiler.ir\n\nimport mlscript.compiler.optimizer.FreeVarAnalysis\nimport mlscript.utils.shorthands._\nimport mlscript.utils._\nimport mlscript._\nimport mlscript.Message.MessageContext\nimport scala.collection.mutable.ListBuffer\n\nfinal val ops = Set(\"+\", \"-\", \"*\", \"/\", \">\", \"<\", \">=\", \"<=\", \"!=\", \"==\")\nfinal val builtin = Set(\"builtin\")\n\nfinal class Builder(fresh: Fresh, fnUid: FreshInt, classUid: FreshInt, tag: FreshInt, raise: Diagnostic => Unit, verbose: Boolean = false):\n  import Node._\n  import Expr._\n  \n  private def log(x: Any) = if verbose then println(x)\n\n  private final case class ClassInfoPartial(name: Str, fields: Ls[Str], methods: Set[Str]):\n    var freeVars = Ls.empty[Str]\n    var ctx = ctxEmpty\n\n  private final case class DefnInfoPartial(name: Str, params: Ls[Str]):\n    var freeVars = Ls.empty[Str]\n    var ctx = ctxEmpty\n\n  private type NameCtx = Map[Str, Name] // name -> new name\n  private type ClassCtx = Map[Str, ClassInfoPartial] // class name -> partial class info\n  private type FnCtx = Map[Str, DefnInfoPartial]    // fn name -> partial defn info\n  private type OpCtx = Set[Str]         // op names\n  \n  private final case class Ctx(\n    nameCtx: NameCtx = Map.empty,\n    tyNameCtx: NameCtx = Map.empty,\n    classCtx: ClassCtx = Map.empty,\n    fnCtx: FnCtx = Map.empty,\n    opCtx: OpCtx = Set.empty,\n    jpAcc: ListBuffer[Defn],\n    defAcc: ListBuffer[NuFunDef],\n    lcAcc: ListBuffer[NuTypeDef],\n  ):\n    def hasClassLifted = lcAcc.nonEmpty\n    def hasLifted = jpAcc.nonEmpty || defAcc.nonEmpty || lcAcc.nonEmpty\n\n  private def ctxEmpty = Ctx(\n      nameCtx = Map.empty,\n      tyNameCtx = Map.empty,\n      classCtx = Map.empty,\n      fnCtx = Map.empty,\n      opCtx = ops,\n      jpAcc = ListBuffer.empty,\n      defAcc = ListBuffer.empty,\n      lcAcc = ListBuffer.empty,\n  )\n\n  private def ctxJoin(c1: Ctx, c2: Ctx) =\n    Ctx(\n      nameCtx = c1.nameCtx ++ c2.nameCtx,\n      tyNameCtx = c1.tyNameCtx ++ c2.tyNameCtx,\n      classCtx = c1.classCtx ++ c2.classCtx,\n      fnCtx = c1.fnCtx ++ c2.fnCtx,\n      opCtx = c1.opCtx ++ c2.opCtx,\n      jpAcc = c1.jpAcc,\n      defAcc = c1.defAcc,\n      lcAcc = c1.lcAcc,\n    )\n\n  private def ref(x: Name) = Ref(x)\n  private def result(x: Ls[TrivialExpr]) = Result(x).attachTag(tag)\n  private def sresult(x: TrivialExpr) = Result(Ls(x)).attachTag(tag)\n  private def unexpectedNode(x: Node) = throw IRError(s\"unsupported node $x\")\n  private def unexpectedTerm(x: Statement) = throw IRError(s\"unsupported term $x\")\n\n  private def buildBinding(using ctx: Ctx)(name: Str, e: Term, body: Term)(k: Node => Node): Node =\n    buildResultFromTerm(e) {\n      case Result((r: Ref) :: Nil) =>\n        given Ctx = ctx.copy(nameCtx = ctx.nameCtx + (name -> r.name))\n        buildResultFromTerm(body)(k)\n      case Result((lit: Literal) :: Nil) =>\n        val v = fresh.make\n        given Ctx = ctx.copy(nameCtx = ctx.nameCtx + (name -> v))\n        LetExpr(v,\n          lit,\n          buildResultFromTerm(body)(k)).attachTag(tag)\n      case node @ _ => node |> unexpectedNode\n    }\n  \n  private def buildResultFromTup(using ctx: Ctx)(tup: Tup)(k: Node => Node): Node =\n    tup match\n      case Tup(N -> Fld(FldFlags.empty, x) :: xs) => buildResultFromTerm(x) {\n        case Result(x :: Nil) =>\n          buildResultFromTup(Tup(xs)) {\n            case Result(xs) => x :: xs |> result |> k\n            case node @ _ => node |> unexpectedNode\n          }\n        case node @ _ => node |> unexpectedNode\n      }\n      case Tup(Nil) => Nil |> result |> k\n      case _ => ???\n      \n  private def bindingPatternVariables(scrut: Str, tup: Tup, cls: ClassInfoPartial, rhs: Term): Term =\n    val params = tup |> getTupleFields\n    val fields = cls.fields\n    val tm = params.zip(fields).foldLeft(rhs) {\n      case (tm, (param, field)) => \n        Let(false, Var(param), App(Sel(Var(cls.name), Var(field)), Tup(Ls(N -> Fld(FldFlags.empty, Var(scrut))))), tm)\n    }\n    tm\n\n  private def freeVariablesIf(ucs: If): Set[Str] =\n    val ifbody: IfBody = ucs.body\n    val els: Opt[Term] = ucs.els\n\n    def f(ifbody: IfBody): Set[Str] = ifbody match\n      case IfBlock(lines) => lines.foldLeft(Set.empty[Str]) {\n        case (acc, Left(ifbody2)) => acc ++ f(ifbody2)\n        case (acc, Right(rhs)) => acc ++ freeVariables(rhs)._2\n      }\n      case IfElse(expr) => freeVariables(expr)\n      case IfLet(isRec, name, rhs, body) =>\n        if isRec then\n          (freeVariables(rhs) -- freeVariables(name)) ++ (f(body) -- freeVariables(name))\n        else\n          freeVariables(rhs) ++ (f(body) -- freeVariables(name))\n      case IfOpApp(lhs, op, rhs) => freeVariables(lhs) ++ f(rhs)\n      case IfOpsApp(lhs, opsRhss) => freeVariables(lhs) ++ opsRhss.foldLeft(Set.empty[Str]) {\n        case (acc, (op, rhs)) => acc ++ f(rhs)\n      }\n      case IfThen(expr, rhs) => freeVariables(rhs) -- freeVariables(expr)\n\n    val fvs1 = f(ifbody)\n    val fvs2 = els.fold(Set.empty[Str]) { freeVariables }\n\n    fvs1 ++ fvs2\n\n  private def freeVariables(tu: TypingUnit): Set[Str] =\n    var all_defined = tu.rawEntities.foldLeft(Set.empty[Str]) {\n      case (defined, stmt) => defined ++ freeVariables(stmt)._1\n    }\n    tu.rawEntities.foldLeft(Set.empty[Str]) {\n      case (acc, stmt) => acc ++ (freeVariables(stmt)._2 -- all_defined)\n    }\n\n    // for this fv analysis, we also need to return the variables that are defined in this statement\n  private def freeVariables(stmt: Statement): (Set[Str], Set[Str]) = stmt match\n    case DataDefn(body) => throw IRError(\"unsupported DataDefn\")\n    case DatatypeDefn(head, body) => throw IRError(\"unsupported DatatypeDefn\")\n    case LetS(isRec, pat, rhs) => throw IRError(\"unsupported LetS\")\n    case ntd: NuTypeDef => \n      val fvs = freeVariables(ntd.body) -- ntd.params.fold(Set.empty)(freeVariables)\n      (Set(ntd.nme.name), fvs)\n    case Constructor(params, body) => throw IRError(\"unsupported Constructor\")\n    case nfd: NuFunDef =>\n      val fvs = nfd.isLetRec match\n        case None | Some(true) => nfd.rhs.fold(tm => freeVariables(tm) -- freeVariables(nfd.nme), ty => Set.empty)\n        case Some(false) => nfd.rhs.fold(tm => freeVariables(tm), ty => Set.empty)\n      (freeVariables(nfd.nme), fvs)\n    case Def(rec, nme, rhs, isByname) => throw IRError(\"unsupported Def\")\n    case TypeDef(kind, nme, tparams, body, mthDecls, mthDefs, positionals, adtInfo) => throw IRError(\"unsupported TypeDef\")\n    case x: Term =>\n      val fvs = freeVariables(x)\n      (Set.empty, fvs)\n\n  private def freeVariables(tm: Term): Set[Str] = tm match\n    case AdtMatchWith(cond, arms) =>\n      val inner: Set[Str] = arms.foldLeft(Set.empty){\n        case (acc, AdtMatchPat(pat, body)) => acc ++ freeVariables(body) -- freeVariables(pat)\n      }\n      freeVariables(cond) ++ inner\n    case Ann(ann, receiver) => freeVariables(receiver)\n    case App(lhs, rhs) => freeVariables(lhs) ++ freeVariables(rhs)\n    case Asc(trm, ty) => freeVariables(trm)\n    case Assign(lhs, rhs) => freeVariables(lhs) ++ freeVariables(rhs)\n    case Bind(lhs, rhs) => freeVariables(lhs)\n    case Blk(stmts) => \n      var fvs = Set.empty[Str]\n      var defined = Set.empty[Str]\n      stmts.foreach {\n        stmt => {\n          val stmt_fvs = freeVariables(stmt)\n          fvs ++= stmt_fvs._2\n          fvs --= defined\n          defined ++= stmt_fvs._1\n        }\n      }\n      fvs\n    case Bra(rcd, trm) => freeVariables(trm)\n    case CaseOf(trm, cases) =>\n      import mlscript.{Case => CCase}\n      def f(pat: CaseBranches): Set[Str] =\n        pat match\n          case CCase(pat, body, rest) => freeVariables(body) -- freeVariables(pat) ++ f(rest)\n          case NoCases => Set.empty\n          case Wildcard(body) => freeVariables(body)\n      freeVariables(trm) ++ f(cases)\n    case Eqn(lhs, rhs) => freeVariables(rhs)\n    case Forall(params, body) => freeVariables(body)\n    case x: If => freeVariablesIf(x)\n    case Inst(body) => freeVariables(body)\n    case Lam(lhs, rhs) => \n      freeVariables(rhs) -- freeVariables(lhs)\n    case Let(isRec, name, rhs, body) => \n      if isRec then\n        (freeVariables(rhs) -- freeVariables(name)) ++ (freeVariables(body) -- freeVariables(name))\n      else\n        freeVariables(rhs) ++ (freeVariables(body) -- freeVariables(name))\n    case New(head, body) => throw IRError(\"unsupported New\")\n    case NuNew(cls) => freeVariables(cls)\n    case Quoted(body) => throw IRError(\"unsupported Quoted\")\n    case Rcd(fields) => fields.foldLeft(Set.empty[Str]) {\n      case (acc, (_, Fld(_, trm))) => acc ++ freeVariables(trm)\n    }\n    case Rft(base, decls) => throw IRError(\"unsupported Rft\")\n    case Sel(receiver, fieldName) => freeVariables(receiver)\n    case Splc(fields) => fields.foldLeft(Set.empty[Str]) {\n      case (acc, Left(trm)) => acc ++ freeVariables(trm) \n      case (acc, Right(Fld(_, trm))) => acc ++ freeVariables(trm)\n    }\n    case Subs(arr, idx) => freeVariables(arr) ++ freeVariables(idx)\n    case Super() => Set.empty\n    case Test(trm, ty) => freeVariables(trm)\n    case Tup(fields) => fields.foldLeft(Set.empty[Str]) {\n      case (acc, (_, Fld(_, trm))) => acc ++ freeVariables(trm)\n    }\n    case TyApp(lhs, targs) => freeVariables(lhs)\n    case Unquoted(body) => throw IRError(\"unsupported Unquoted\")\n    case Where(body, where) => throw IRError(\"unsupported Where\")\n    case While(cond, body) => freeVariables(cond) ++ freeVariables(body)\n    case With(trm, fields) => freeVariables(trm) ++ freeVariables(fields: Term)\n    case Var(name) => Set(name)\n    case DecLit(value) => Set.empty\n    case IntLit(value) => Set.empty\n    case StrLit(value) => Set.empty\n    case UnitLit(undefinedOrNull) => Set.empty\n\n    private def buildLetCall(using ctx: Ctx)(f: Var, xs: Tup, ann: Option[Term])(k: Node => Node) =        \n      buildResultFromTup(xs) {\n        case Result(args) =>\n          val v = fresh.make\n          ctx.nameCtx.get(f.name) match\n            case None => throw IRError(s\"unknown name $f in $ctx\")\n            case Some(f2) =>\n              ctx.fnCtx.get(f2.str) match\n                case None => throw IRError(s\"unknown function $f2 in $ctx\")\n                case Some(dInfo) =>\n                  val args2 = \n                    if args.size != dInfo.params.size then\n                      args ++ dInfo.freeVars.map(x => Ref(ctx.nameCtx(x))) // it's possible that the free vars as parameters have been filled when do eta expansion\n                    else\n                      args\n                  ann match\n                    case Some(ann @ Var(nme)) =>\n                      if nme === \"tailcall\" then \n                        LetCall(List(v), DefnRef(Right(f2.str)), args2, true, v |> ref |> sresult |> k)(f.toLoc).attachTag(tag)\n                      else\n                        if nme === \"tailrec\" then\n                          raise(ErrorReport(List(msg\"@tailrec is for annotating functions; try @tailcall instead\" -> ann.toLoc), true, Diagnostic.Compilation))\n                        LetCall(List(v), DefnRef(Right(f2.str)), args2, false, v |> ref |> sresult |> k)(f.toLoc).attachTag(tag) \n                    case Some(_) => throw IRError(\"unsupported annotation\")\n                    case None => LetCall(List(v), DefnRef(Right(f2.str)), args2, false, v |> ref |> sresult |> k)(f.toLoc).attachTag(tag)\n        case node @ _ => node |> unexpectedNode\n      }\n  private def buildResultFromTerm(using ctx: Ctx)(tm: Statement)(k: Node => Node): Node =\n    val res = tm match\n      case lit: Lit => Literal(lit) |> sresult |> k\n      case v @ Var(name) =>\n        if (name.isCapitalized)\n          ctx.tyNameCtx.get(name) match\n            case Some(x) => \n              val v = fresh.make\n              ctx.classCtx.get(x.str) match\n                case Some(clsinfo) =>\n                  val args = (if clsinfo.freeVars.isEmpty then Nil else clsinfo.freeVars.map(x => Ref(ctx.nameCtx(x))))\n                  LetExpr(v,\n                    CtorApp(ClassRef(Right(x.str)), args),\n                    v |> ref |> sresult |> k).attachTag(tag)\n                case None => throw IRError(s\"unknown class $name in $ctx\")\n            case None => throw IRError(s\"unknown type name $name in $ctx\")\n        else\n          ctx.nameCtx.get(name) match {\n            case Some(x) =>\n              if (ctx.fnCtx.contains(x.str))\n                val info = ctx.fnCtx(x.str)\n                val arity = info.params.size - info.freeVars.size\n                val range = 0 until arity\n                val xs = range.map(_ => fresh.make.str).toList\n                val params = Tup(xs.map(x => N -> Fld(FldFlags.empty, Var(x))))\n                val args = Tup(params.fields ++ info.freeVars.map(x => N -> Fld(FldFlags.empty, Var(x))))\n                val lam = Lam(params, App(Var(x.str), args))\n                buildResultFromTerm(lam)(k)\n              else\n                x |> ref |> sresult |> k\n            case None => throw IRError(s\"unknown name $name in $ctx\")\n          }\n      case lam @ Lam(Tup(fields), body) =>\n        val tmp = fresh.make\n        val lambdaName = fresh.make(\"Lambda\")\n        val result = Var(lambdaName.str)\n        val localCls = Blk(\n          NuTypeDef(Cls, TypeName(lambdaName.str), Nil, N, N, N, Ls(Var(\"Callable\")), N, N, TypingUnit(\n            NuFunDef(N, Var(s\"apply${fields.size}\"), None, Nil, L(Lam(Tup(fields), body)))(tm.getLoc, N, N, N, N, false, Nil) :: Nil\n          ))(tm.getLoc, tm.getLoc, Nil) :: result :: Nil)\n        buildResultFromTerm(localCls)(k)\n\n      case App(\n        App(Var(name), Tup((_ -> Fld(_, e1)) :: Nil)),\n        Tup((_ -> Fld(_, e2)) :: Nil)) if ctx.opCtx.contains(name) =>\n        buildResultFromTerm(e1) {\n          case Result(v1 :: Nil) =>\n            buildResultFromTerm(e2) {\n              case Result(v2 :: Nil) =>\n                val v = fresh.make\n                LetExpr(v,\n                  BasicOp(name, List(v1, v2)),\n                  v |> ref |> sresult |> k).attachTag(tag)\n              case node @ _ => node |> unexpectedNode\n            }\n          case node @ _ => node |> unexpectedNode\n        }\n      case x @ App(Var(name), xs @ Tup(_)) if name.isCapitalized || ctx.opCtx.contains(name) =>\n        if name.isCapitalized then\n          buildResultFromTerm(xs) {\n            case Result(args) => \n              ctx.tyNameCtx.get(name) match\n                case Some(x) =>\n                  val v = fresh.make\n                  ctx.classCtx.get(x.str) match\n                    case Some(clsinfo) =>\n                      val args2 = args ++ clsinfo.freeVars.map(x => Ref(ctx.nameCtx(x)))\n                      LetExpr(v,\n                        CtorApp(ClassRef(Right(x.str)), args2),\n                        v |> ref |> sresult |> k).attachTag(tag)\n                    case None => throw IRError(s\"unknown class $name in $ctx\")\n                case None => throw IRError(s\"unknown type name $name in $ctx\")\n            case node @ _ => node |> unexpectedNode\n          }\n        else\n          buildResultFromTerm(xs) {\n            case Result(args) =>\n              val v = fresh.make\n              LetExpr(v,\n                BasicOp(name, args),\n                v |> ref |> sresult |> k).attachTag(tag)\n            case node @ _ => node |> unexpectedNode\n          }\n      case App(\n        member @ Sel(Var(clsName), Var(fld)), \n        xs @ Tup((_ -> Fld(_, Var(s))) :: _)) if clsName.isCapitalized =>\n        buildResultFromTup(xs) {\n          case Result(xs @ (Ref(name) :: args)) =>\n            ctx.tyNameCtx.get(clsName) match\n              case Some(x) => \n                val v = fresh.make\n                val cls = ctx.classCtx(x.str)\n                val isField = cls.fields.contains(fld)\n                if isField then\n                  LetExpr(v, Select(name, ClassRef(Right(x.str)), fld),\n                    v |> ref |> sresult |> k).attachTag(tag)\n                else\n                  if cls.methods.contains(fld) then\n                    LetMethodCall(Ls(v), ClassRef(Right(x.str)), Name(fld), xs, v |> ref |> sresult |> k).attachTag(tag)\n                  else\n                    throw IRError(s\"unknown field or method $fld in $cls\")\n              case None => throw IRError(s\"unknown type name $clsName in $ctx\")\n          case node @ _ => node |> unexpectedNode\n        }\n      case App(vf @ Var(f), xs @ Tup(_)) if ctx.fnCtx.contains(f) || ctx.nameCtx.get(f).fold(false)(x => ctx.fnCtx.contains(x.str)) => \n        buildLetCall(vf, xs, None)(k)\n      case Ann(ann, App(vf @ Var(f), xs @ Tup(_))) if ctx.fnCtx.contains(f) || ctx.nameCtx.get(f).fold(false)(x => ctx.fnCtx.contains(x.str)) =>\n        buildLetCall(vf, xs, Some(ann))(k)\n      case App(f, xs @ Tup(_)) =>\n        buildResultFromTerm(f) {\n          case Result(Ref(f) :: Nil) => buildResultFromTerm(xs) {\n            case Result(args) =>\n              val v = fresh.make\n              // LetApply(List(v), f, args, v |> ref |> sresult |> k).attachTag(tag)\n              LetMethodCall(List(v), ClassRef(R(\"Callable\")), Name(\"apply\" + args.length), (Ref(f): TrivialExpr) :: args, v |> ref |> sresult |> k).attachTag(tag)\n            case node @ _ => node |> unexpectedNode\n          }\n          case node @ _ => node |> unexpectedNode\n      }\n\n      case Ann(ann @ Var(name), recv) =>\n        if name === \"tailcall\" then\n          raise(ErrorReport(List(msg\"@tailcall may only be used to annotate function calls\" -> ann.toLoc), true, Diagnostic.Compilation))\n        else if name === \"tailrec\" then\n          raise(ErrorReport(List(msg\"@tailrec may only be used to annotate functions\" -> ann.toLoc), true, Diagnostic.Compilation))\n\n        buildResultFromTerm(recv)(k)\n      case Let(false, Var(name), rhs, body) => \n        buildBinding(name, rhs, body)(k)\n\n      case If(IfThen(cond, tru), Some(fls)) => \n        buildResultFromTerm(cond) {\n          case Result(Ref(cond) :: Nil) => \n            if (!ctx.classCtx.contains(\"True\") || !ctx.classCtx.contains(\"False\"))\n              throw IRError(\"True or False class not found, unable to use 'if then else'\")\n            val jp = fresh.make(\"j\")\n            val res = fresh.make\n            val jpbody = res |> ref |> sresult |> k\n            val fvs = FreeVarAnalysis(extended_scope = false).run_with(jpbody, Set(res.str)).toList\n            val jpdef = Defn(\n              fnUid.make,\n              jp.str,\n              params = res :: fvs.map(x => Name(x)),\n              resultNum = 1,\n              jpbody,\n              false,\n              None\n            )\n            ctx.jpAcc.addOne(jpdef)\n            val tru2 = buildResultFromTerm(tru) {\n              case Result(xs) => Jump(DefnRef(Right(jp.str)), xs ++ fvs.map(x => Ref(Name(x)))).attachTag(tag)\n              case node @ _ => node |> unexpectedNode\n            }\n            val fls2 = buildResultFromTerm(fls) {\n              case Result(xs) => Jump(DefnRef(Right(jp.str)), xs ++ fvs.map(x => Ref(Name(x)))).attachTag(tag)\n              case node @ _ => node |> unexpectedNode\n            }\n            Case(cond, Ls(\n              (Pat.Class(ClassRef(Right(\"True\"))), tru2),\n              (Pat.Class(ClassRef(Right(\"False\"))), fls2)), None).attachTag(tag)\n          case node @ _ => node |> unexpectedNode\n        }\n        \n      case If(IfOpApp(lhs, Var(\"is\"), IfBlock(lines)), N)\n        => buildResultFromTerm(lhs) {\n          case Result(Ref(scrut) :: Nil) =>\n            val jp = fresh.make(\"j\")\n            val res = fresh.make\n            val jpbody = res |> ref |> sresult |> k\n            val fvs = FreeVarAnalysis(extended_scope = false).run_with(jpbody, Set(res.str)).toList\n            val jpdef = Defn(\n              fnUid.make,\n              jp.str,\n              params = res :: fvs.map(x => Name(x)),\n              resultNum = 1,\n              jpbody,\n              false,\n              None,\n            )\n            ctx.jpAcc.addOne(jpdef)\n            var defaultCase: Opt[Node] = None\n            val cases: Ls[(Pat, Node)] = lines flatMap {\n              case L(IfThen(App(Var(ctor), params: Tup), rhs)) =>\n                S(Pat.Class(ClassRef(Right(ctor))) -> {\n                  // need this because we have built terms (selections in case arms) containing names that are not in the original term\n                  given Ctx = ctx.copy(nameCtx = ctx.nameCtx + (scrut.str -> scrut))\n                  buildResultFromTerm(\n                    bindingPatternVariables(scrut.str, params, ctx.classCtx(ctor), rhs)) {\n                      case Result(xs) => Jump(DefnRef(Right(jp.str)), xs ++ fvs.map(x => Ref(Name(x)))).attachTag(tag)\n                      case node @ _ => node |> unexpectedNode\n                    }\n                })\n              case L(IfThen(lit @ IntLit(_), rhs)) =>\n                S(Pat.Lit(lit) -> buildResultFromTerm(rhs) {\n                  case Result(xs) => Jump(DefnRef(Right(jp.str)), xs ++ fvs.map(x => Ref(Name(x)))).attachTag(tag)\n                  case node @ _ => node |> unexpectedNode\n                })\n              case L(IfThen(Var(\"_\"), rhs)) =>\n                defaultCase = Some(buildResultFromTerm(rhs) {\n                  case Result(xs) => Jump(DefnRef(Right(jp.str)), xs ++ fvs.map(x => Ref(Name(x)))).attachTag(tag)\n                  case node @ _ => node |> unexpectedNode\n                })\n                N\n              case L(IfThen(Var(ctor), rhs)) =>\n                S(Pat.Class(ClassRef(Right(ctor))) -> buildResultFromTerm(rhs) {\n                  case Result(xs) => Jump(DefnRef(Right(jp.str)), xs ++ fvs.map(x => Ref(Name(x)))).attachTag(tag)\n                  case node @ _ => node |> unexpectedNode\n                })\n              case _ => throw IRError(s\"not supported UCS\")\n            }\n            Case(scrut, cases, defaultCase).attachTag(tag)\n          case node @ _ => node |> unexpectedNode\n        }\n\n      case Bra(false, tm) => buildResultFromTerm(tm)(k)\n\n      case Blk(stmts) =>\n        val (nfds, ntds, terms) = collectInfo(stmts)\n        val (ctx2, nfds2, ntds2) = renameToBeLifted(nfds, ntds)\n        val ctx3 = initContextForStatementsFrom(\n          nfds2, ntds2, terms, scanNamesInThisScope(stmts)\n        )(using ctx2)\n\n        ctx.lcAcc.addAll(ntds2)\n        ctx.defAcc.addAll(nfds2)\n\n        buildResultFromTerms(using ctx3)(terms)(k)\n\n      case tup: Tup => buildResultFromTup(tup)(k)\n\n      case term => term |> unexpectedTerm\n    \n    res\n\n  private def buildResultFromTerms(using ctx: Ctx)(tms: Ls[Statement])(k: Node => Node): Node =\n    tms match\n      case Nil => throw IRError(\"empty term list\")\n      case NuFunDef(S(false), Var(name), _, _, Left(tm)) :: xs =>\n        xs match\n          case Nil => throw IRError(\"unsupported NuFunDef at tail position\")\n          case _ => buildResultFromTerm(tm) {\n            case Result((r: Ref) :: Nil) =>\n              given Ctx = ctx.copy(nameCtx = ctx.nameCtx + (name -> r.name))\n              buildResultFromTerms(xs)(k)\n            case Result((lit: Literal) :: Nil) =>\n              val v = fresh.make\n              given Ctx = ctx.copy(nameCtx = ctx.nameCtx + (name -> v))\n              LetExpr(v,\n                lit,\n                buildResultFromTerms(xs)(k)).attachTag(tag)\n            case node @ _ => node |> unexpectedNode\n          }\n      case x :: Nil => buildResultFromTerm(x)(k)\n      case x :: xs => buildResultFromTerm(x) {\n        case _ => buildResultFromTerms(xs)(k)\n      }\n\n  private def getTupleFields(tup: Tup) = tup.fields.map {\n    case N -> Fld(FldFlags.empty, Var(name)) => name\n    case S(Var(name)) -> Fld(_, ty) => name\n    case _ => throw IRError(\"unsupported field\")\n  }\n\n  private def buildDefFromMethod(using ctx: Ctx)(fields: List[Str], nfd: Statement): Defn = nfd match\n    case nfd @ NuFunDef(_, Var(name), None, Nil, L(Lam(xs @ Tup(_), body))) =>\n      val defnInfoPartial = getDefnInfoPartial(ctx.fnCtx.keySet ++ ctx.classCtx.keySet ++ fields, ctx)(nfd).get\n      val params = defnInfoPartial.params\n      val names = params map (fresh.make(_))\n      val ctx2 =  ctxJoin(ctx, defnInfoPartial.ctx)\n      given Ctx = ctx2.copy(nameCtx = ctx2.nameCtx ++ (params zip names))\n      Defn(\n        fnUid.make,\n        name,\n        params = names,\n        resultNum = 1,\n        body = buildResultFromTerm(body) { x => x },\n        isTailRec = false,\n        loc = nfd.getLoc,\n      )\n    case fd @ _ => throw IRError(\"unsupported NuFunDef \" + fd.toString)\n\n  private def buildDefFromNuFunDef(using ctx: Ctx)(nfd: Statement): Defn = nfd match\n    case nfd @ NuFunDef(_, Var(name), None, Nil, L(Lam(xs @ Tup(_), body))) =>\n      val defnInfoPartial = getDefnInfoPartial(ctx.fnCtx.keySet ++ ctx.classCtx.keySet, ctx)(nfd).get\n      val params = defnInfoPartial.params\n      val names = params map (fresh.make(_))\n      val ctx2 =  ctxJoin(ctx, defnInfoPartial.ctx)\n      given Ctx = ctx2.copy(nameCtx = ctx2.nameCtx ++ (params zip names))\n      val trAnn = nfd.annotations.find { \n        case Var(\"tailrec\") => true\n        case ann @ Var(\"tailcall\") =>\n          raise(ErrorReport(List(msg\"@tailcall is for annotating function calls; try @tailrec instead\" -> ann.toLoc), true, Diagnostic.Compilation))\n          false\n        case _ => false }\n      Defn(\n        fnUid.make,\n        name,\n        params = names,\n        resultNum = 1,\n        buildResultFromTerm(body) { x => x },\n        trAnn.isDefined,\n        trAnn.flatMap(_.toLoc)\n      )\n    case fd @ _ => throw IRError(\"unsupported NuFunDef \" + fd.toString)\n\n  private def buildClassInfo(using ctx: Ctx)(ntd: Statement): ClassInfo = ntd match\n    case ntd @ NuTypeDef(Cls | Mod, TypeName(name), _, params, N, _, parents, N, N, TypingUnit(methods)) =>\n      val clsInfoPartial = getClassInfoPartial(ctx.classCtx.keySet ++ ctx.fnCtx.keySet, ctx)(ntd)\n      val cls = ClassInfo(classUid.make, name, clsInfoPartial.fields)\n      val ctx2 = ctxJoin(ctx, clsInfoPartial.ctx)\n      given Ctx = ctx2.copy(\n        nameCtx = ctx2.nameCtx ++ clsInfoPartial.fields.map(x => x -> Name(x)),\n        classCtx = ctx2.classCtx + (name -> clsInfoPartial)\n      )\n      def resolveParentName(parent: Term): String = parent match {\n        case Var(name) if name.isCapitalized => name\n        case TyApp(lhs, _) => resolveParentName(lhs)\n        case App(lhs, _) => resolveParentName(lhs)\n        case _ => throw IRError(\"unsupported parent\")\n      }\n      cls.parents = parents.map(resolveParentName).toSet\n      cls.methods = methods.map {\n        case x: NuFunDef => x.name -> buildDefFromMethod(clsInfoPartial.fields, x)\n        case x @ _ => throw IRError(f\"unsupported method $x\")\n      }.toMap\n      cls\n    case x @ _ => throw IRError(f\"unsupported NuTypeDef $x\")\n\n\n  private def getDefnInfoPartial(names: Set[Str], ctx: Ctx)(nfd: NuFunDef): Opt[DefnInfoPartial] = nfd match\n    case NuFunDef(_, Var(name), _, _, Left(Lam(Var(x), _))) => \n      val originalFvs = freeVariables(nfd)._2\n      val fvs = (originalFvs -- builtin -- ops -- names).toList\n      val params = x :: fvs\n      val dip = DefnInfoPartial(name, params)\n      dip.freeVars = fvs\n      dip.ctx = ctx\n      S(dip)\n    case NuFunDef(_, Var(name), _, _, Left(Lam(tp @ Tup(fields), _))) =>\n      val originalFvs = freeVariables(nfd)._2\n      val fvs = (originalFvs -- builtin -- ops -- names).toList\n      val params = getTupleFields(tp) ++ fvs\n      val dip = DefnInfoPartial(name, params)\n      dip.freeVars = fvs\n      dip.ctx = ctx\n      S(dip)\n    case NuFunDef(_, Var(name), _, _, _) => N\n\n\n  private def getClassInfoPartial(names: Set[Str], ctx: Ctx)(ntd: NuTypeDef): ClassInfoPartial = ntd match\n    case ntd @ NuTypeDef(Cls | Mod, TypeName(name), _, params, N, _, parents, N, N, TypingUnit(other)) =>\n      val originalFvs = freeVariables(ntd)._2\n      log(s\"getClassInfoPartial $name\")\n      log(originalFvs)\n      log(names)\n      val fvs = (originalFvs -- builtin -- ops -- names).toList\n      val fields = params.fold(fvs)(xs => getTupleFields(xs) ++ fvs)\n      val methods = other.map {\n        case x: NuFunDef => x.name\n        case x @ _ => throw IRError(f\"unsupported method $x\")\n      }\n      val cls = ClassInfoPartial(name, fields, methods.toSet)\n      cls.freeVars = fvs\n      cls.ctx = ctx\n      cls\n    case x @ _ => throw IRError(f\"unsupported NuTypeDef $x\")\n  \n  private def collectInfo(stmts: Ls[Statement]): (Ls[NuFunDef], Ls[NuTypeDef], Ls[Statement]) =\n    var nfds = ListBuffer.empty[NuFunDef]\n    var ntds = ListBuffer.empty[NuTypeDef]\n    var terms = ListBuffer.empty[Statement]\n    stmts.foreach {\n      case tm @ NuFunDef(S(false), Var(_), _, _, Left(_)) =>\n        terms.addOne(tm)\n      case nfd: NuFunDef => nfds.addOne(nfd)\n      case ntd: NuTypeDef => ntds.addOne(ntd)\n      case tm: Term => terms.addOne(tm)\n      case _ => throw IRError(\"unsupported statement\")\n    }\n    (nfds.toList, ntds.toList, terms.toList)\n\n  private def makeNameMap(str: IterableOnce[Str]) = str.iterator.map(x => (x, Name(x))).toMap\n\n  private def scanNamesInThisScope(stmt: Ls[Statement]): Set[Str] =\n    val names = stmt flatMap {\n      case NuTypeDef(_, TypeName(name), _, _, _, _, _, _, _, _) => S(name)\n      case NuFunDef(_, Var(name), _, _, _) => S(name)\n      case _ => Nil\n    }\n    names.toSet\n  \n  private def renameToBeLifted(nfds: Ls[NuFunDef], ntds: Ls[NuTypeDef])(using ctx: Ctx): (Ctx, Ls[NuFunDef], Ls[NuTypeDef]) =\n    val oldFnNames = scanNamesInThisScope(nfds).toList\n    val oldTyNames = scanNamesInThisScope(ntds).toList\n    // TODO: currently, rename cause bugs\n    //val newFnNames = oldFnNames.map(x => fresh.make(x))\n    //val newTyNames = oldTyNames.map(x => if x.startsWith(\"Lambda$\") then Name(x) else fresh.make(x))\n    val newFnNames = oldFnNames.map(Name(_))\n    val newTyNames = oldTyNames.map(Name(_))\n    val nameCtx = oldFnNames.zip(newFnNames).toMap\n    val tyNameCtx = oldTyNames.zip(newTyNames).toMap\n    val nfds2 = nfds.map(x => x.copy(nme = Var(nameCtx(x.name).str))(x.declareLoc, x.virtualLoc, x.mutLoc, x.signature, x.outer, x.genField, x.annotations))\n    val ntds2 = ntds.map(x => x.copy(nme = TypeName(tyNameCtx(x.name).str))(x.declareLoc, x.abstractLoc, x.annotations))\n\n    (ctx.copy(nameCtx = ctx.nameCtx ++ nameCtx, tyNameCtx = ctx.tyNameCtx ++ tyNameCtx), nfds2, ntds2)\n\n  private def initContextForStatementsFrom(nfds: Ls[NuFunDef], ntds: Ls[NuTypeDef], terms: Ls[Statement], excluded: Set[Str])(using ctx: Ctx): Ctx =\n    // they are in the same mutual group or higher group, mustn't capture them\n    val excludedNames = excluded ++ scanNamesInThisScope(nfds) ++ scanNamesInThisScope(ntds) ++ ctx.fnCtx.keySet ++ ctx.classCtx.keySet\n    val partialDefnInfo = nfds flatMap getDefnInfoPartial(excludedNames, ctx)\n    val partialClassInfo = ntds map getClassInfoPartial(excludedNames, ctx)\n    val fnNames = partialDefnInfo.map(_.name)\n    val fnCtx = fnNames.zip(partialDefnInfo).toMap\n    val nameCtx = makeNameMap(builtin) ++ makeNameMap(fnNames) ++ makeNameMap(ops)\n    val tyNames = partialClassInfo.map(_.name)\n    val tyNameCtx = makeNameMap(tyNames)\n    val classCtx = tyNames.zip(partialClassInfo).toMap\n\n    ctx.copy(\n      tyNameCtx = ctx.tyNameCtx ++ tyNameCtx,\n      nameCtx = ctx.nameCtx ++ nameCtx,\n      classCtx = ctx.classCtx ++ classCtx,\n      fnCtx = ctx.fnCtx ++ fnCtx,\n    )\n\n  private def initContextForStatements(nfds: Ls[NuFunDef], ntds: Ls[NuTypeDef], terms: Ls[Statement]): Ctx =\n    val ctx = Ctx(\n      nameCtx = Map.empty,\n      tyNameCtx = Map.empty,\n      classCtx = Map.empty,\n      fnCtx = Map.empty,\n      opCtx = ops,\n      jpAcc = ListBuffer.empty,\n      defAcc = ListBuffer.empty,\n      lcAcc = ListBuffer.empty,\n    )\n    initContextForStatementsFrom(nfds, ntds, terms, Set.empty)(using ctx)\n\n  def getHiddenNames(prelude: TypingUnit): Set[Str] =\n    def resolveTypeName(x: Term): Str = x match\n      case Var(name) => name\n      case TyApp(lhs, _) => resolveTypeName(lhs)\n      case App(lhs, _) => resolveTypeName(lhs)\n      case _ => throw IRError(\"unsupported type name\")\n    val hidden = prelude.rawEntities.flatMap {\n      case NuFunDef(_, Var(name), _, _, _) => Nil\n      case NuTypeDef(_, TypeName(name), _, params, _, _, _, _, _, _) if name == \"HiddenTheseEntities\" =>\n        params.fold{Nil}{\n          x => x.fields.flatMap {\n            case S(Var(name)) -> Fld(FldFlags.empty, ty) => resolveTypeName(ty) :: Nil\n            case _ => Nil\n          }\n        }\n      case NuTypeDef(_, TypeName(name), _, _, _, _, _, _, _, _) => Nil\n      case _ => Nil\n    }\n    hidden.toSet\n\n  def buildGraph(unit: TypingUnit, prelude: TypingUnit, addPrelude: Boolean = true): Program =\n    val unit2 = if addPrelude then TypingUnit(prelude.rawEntities ++ unit.rawEntities) else unit\n    val hiddenNames = getHiddenNames(unit2)\n    val (nfds, ntds, terms) = collectInfo(unit2.rawEntities)\n    var ctx = initContextForStatements(nfds, ntds, terms)\n\n    val definitions = ListBuffer.empty[Defn]\n    val classes = ListBuffer.empty[ClassInfo]\n\n    var first = true\n\n    var curNfds = nfds\n    var curNtds = ntds\n    val main = buildResultFromTerm(using ctx)(Blk(terms)){ k => k }\n    while first || ctx.hasLifted do\n      first = false\n      ctx.jpAcc.clear()\n      ctx.defAcc.clear()\n      ctx.lcAcc.clear()\n      definitions.addAll(curNfds.map(buildDefFromNuFunDef(using ctx)))\n      definitions.addAll(ctx.jpAcc)\n      classes.addAll(curNtds.map(buildClassInfo(using ctx)))\n      curNfds = ctx.defAcc.toList\n      curNtds = ctx.lcAcc.toList\n      ctx = initContextForStatementsFrom(curNfds, curNtds, Nil, Set.empty)(using ctx)\n\n    val clsInfo = classes.toSet\n    val defs = definitions.toSet\n\n    resolveRef(main, defs, clsInfo, true)\n    validate(main, defs, clsInfo)\n    \n    Program(clsInfo, defs, main)\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/ir/Fresh.scala",
    "content": "package mlscript.compiler.ir\n\nimport collection.mutable.{HashMap => MutHMap}\nimport mlscript.utils.shorthands._\n\nfinal class Fresh(div : Char = '$'):\n  private val counter = MutHMap[Str, Int]()\n  private def gensym(s: Str) = {\n    val n = s.lastIndexOf(div)\n    val (ts, suffix) = s.splitAt(if n == -1 then s.length() else n)\n    var x = if suffix.stripPrefix(div.toString).forall(_.isDigit) then ts else s\n    val count = counter.getOrElse(x, 0)\n    val tmp = s\"$x$div$count\"\n    counter.update(x, count + 1)\n    Name(tmp)\n  }\n\n  def make(s: Str) = gensym(s)\n  def make = gensym(\"x\")\n\nfinal class FreshInt:\n  private var counter = 0\n  def make: Int = {\n    val tmp = counter\n    counter += 1\n    tmp\n  }\n\n\n  "
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/ir/IR.scala",
    "content": "package mlscript.compiler.ir\n\nimport mlscript._\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\nimport mlscript.compiler.utils._\nimport mlscript.compiler.optimizer._\nimport mlscript.compiler.ir._\n\nimport mlscript.Loc\n\nimport collection.mutable.{Map as MutMap, Set as MutSet, HashMap, ListBuffer}\nimport annotation.unused\nimport util.Sorting\nimport scala.collection.immutable.SortedSet\nimport scala.language.implicitConversions\n\nfinal case class IRError(message: String) extends Exception(message)\n\ncase class Program(\n  classes: Set[ClassInfo],\n  defs: Set[Defn],\n  main: Node,\n):\n  override def toString: String =\n    val t1 = classes.toArray\n    val t2 = defs.toArray\n    Sorting.quickSort(t1)\n    Sorting.quickSort(t2)\n    s\"Program({${t1.mkString(\",\\n\")}}, {\\n${t2.mkString(\"\\n\")}\\n},\\n$main)\"\n\n  def show(hiddenNames: Set[Str] = Set.empty) = toDocument(hiddenNames).print\n\n  def toDocument(hiddenNames: Set[Str] = Set.empty) : Document =\n    val t1 = classes.toArray\n    val t2 = defs.toArray\n    Sorting.quickSort(t1)\n    Sorting.quickSort(t2)\n    given Conversion[String, Document] = raw\n    stack(\n      \"Program:\",\n      stack_list(t1.filter(x => !hiddenNames.contains(x.name)).map(_.toDocument).toList) |> indent,\n      stack_list(t2.map(_.toDocument).toList) |> indent,\n      main.toDocument |> indent\n    )\n\nimplicit object ClassInfoOrdering extends Ordering[ClassInfo] {\n  def compare(a: ClassInfo, b: ClassInfo) = a.id.compare(b.id)\n}\n\ncase class ClassInfo(\n  id: Int,\n  name: Str,\n  fields: Ls[Str],\n):\n  var parents: Set[Str] = Set.empty\n  var methods: Map[Str, Defn] = Map.empty\n  override def hashCode: Int = id\n  override def toString: String =\n    s\"ClassInfo($id, $name, [${fields mkString \",\"}], parents: ${parents mkString \",\"}, methods:\\n${methods mkString \",\\n\"})\"\n\n  def show = toDocument.print\n  def toDocument: Document =\n    given Conversion[String, Document] = raw\n    val extension = if parents.isEmpty then \"\" else \" extends \" + parents.mkString(\", \")\n    if methods.isEmpty then\n      \"class\" <:> name <#> \"(\" <#> fields.mkString(\",\") <#> \")\" <#> extension\n    else\n      stack(\n        \"class\" <:> name <#> \"(\" <#> fields.mkString(\",\") <#> \")\" <#> extension <:> \"{\",\n        stack_list( methods.map { (_, defn) => defn.toDocument |> indent }.toList),\n        \"}\"\n      )\n\ncase class Name(val str: Str):\n  def copy: Name = Name(str)\n  def trySubst(map: Map[Str, Name]) = map.getOrElse(str, this)\n  override def toString: String =\n    str\n\nclass DefnRef(var defn: Either[Defn, Str]):\n  def name: String = defn.fold(_.name, x => x)\n  def expectDefn: Defn = defn match {\n    case Left(defn) => defn\n    case Right(name) => throw Exception(s\"Expected a def, but got $name\")\n  }\n  def getDefn: Opt[Defn] = defn.left.toOption\n  override def equals(o: Any): Bool = o match {\n    case o: DefnRef => o.name == this.name\n    case _ => false\n  }\n\nclass ClassRef(var cls: Either[ClassInfo, Str]):\n  def name: String = cls.fold(_.name, x => x)\n  def expectClass: ClassInfo = cls match {\n    case Left(cls) => cls\n    case Right(name) => throw Exception(s\"Expected a class, but got $name\")\n  }\n  def getClass: Opt[ClassInfo] = cls.left.toOption\n  override def equals(o: Any): Bool = o match {\n    case o: ClassRef => o.name == this.name\n    case _ => false\n  }\n\nimplicit object DefOrdering extends Ordering[Defn] {\n  def compare(a: Defn, b: Defn) = a.id.compare(b.id)\n}\n\ncase class Defn(\n  id: Int,\n  name: Str,\n  params: Ls[Name],\n  resultNum: Int,\n  body: Node,\n  isTailRec: Bool,\n  loc: Opt[Loc] = None\n):\n  override def hashCode: Int = id\n\n  override def toString: String =\n    val ps = params.map(_.toString).mkString(\"[\", \",\", \"]\")\n    s\"Def($id, $name, $ps,\\n$resultNum, \\n$body\\n)\"\n\n  def show = toDocument.print\n\n  def toDocument: Document =\n    given Conversion[String, Document] = raw\n    stack(\n      \"def\" <:> name <#> \"(\" <#> params.map(_.toString).mkString(\",\")  <#> \")\" <:> \"=\",\n      body.toDocument |> indent\n    )\n\nsealed trait TrivialExpr:\n  import Expr._\n  override def toString: String\n  def show: String\n  def toDocument: Document\n  def mapNameOfTrivialExpr(f: Name => Name): TrivialExpr = this match\n    case x: Ref => Ref(f(x.name))\n    case x: Literal => x\n  def toExpr: Expr = this match { case x: Expr => x }\n\nprivate def showArguments(args: Ls[TrivialExpr]) = args map (_.show) mkString \",\"\n\nenum Expr:\n  case Ref(name: Name) extends Expr, TrivialExpr \n  case Literal(lit: Lit) extends Expr, TrivialExpr\n  case CtorApp(cls: ClassRef, args: Ls[TrivialExpr])\n  case Select(name: Name, cls: ClassRef, field: Str)\n  case BasicOp(name: Str, args: Ls[TrivialExpr])\n  case AssignField(assignee: Name, cls: ClassRef, field: Str, value: TrivialExpr)\n  \n  override def toString: String = show\n\n  def show: String =\n    toDocument.print\n  \n  def toDocument: Document = \n    given Conversion[String, Document] = raw\n    this match\n    case Ref(s) => s.toString\n    case Literal(IntLit(lit)) => s\"$lit\"\n    case Literal(DecLit(lit)) => s\"$lit\"\n    case Literal(StrLit(lit)) => s\"$lit\"\n    case Literal(UnitLit(lit)) => s\"$lit\"\n    case CtorApp(cls, args) =>\n      cls.name <#> \"(\" <#> (args |> showArguments) <#> \")\"\n    case Select(s, cls, fld) =>\n      cls.name <#> \".\" <#> fld <#> \"(\" <#> s.toString <#> \")\"\n    case BasicOp(name: Str, args) =>\n      name <#> \"(\" <#> (args |> showArguments) <#> \")\"\n    case AssignField(assignee, clsInfo, fieldName, value) => \n      stack(\n        \"assign\"\n        <:> (assignee.toString + \".\" + fieldName)\n        <:> \":=\"\n        <:> value.toDocument\n      )\n\n  def mapName(f: Name => Name): Expr = this match\n    case Ref(name) => Ref(f(name))\n    case Literal(lit) => Literal(lit)\n    case CtorApp(cls, args) => CtorApp(cls, args.map(_.mapNameOfTrivialExpr(f)))\n    case Select(x, cls, field) => Select(f(x), cls, field)\n    case BasicOp(name, args) => BasicOp(name, args.map(_.mapNameOfTrivialExpr(f)))\n    case AssignField(assignee, clsInfo, fieldName, value) => AssignField(f(assignee), clsInfo, fieldName, value.mapNameOfTrivialExpr(f))\n\n  def locMarker: LocMarker = this match\n    case Ref(name) => LocMarker.MRef(name.str)\n    case Literal(lit) => LocMarker.MLit(lit)\n    case CtorApp(cls, args) => LocMarker.MCtorApp(cls, args.map(_.toExpr.locMarker))\n    case Select(name, cls, field) => LocMarker.MSelect(name.str, cls, field)\n    case BasicOp(name, args) => LocMarker.MBasicOp(name, args.map(_.toExpr.locMarker))\n    case AssignField(assignee, clsInfo, fieldName, value) => LocMarker.MAssignField(assignee.str, fieldName, value.toExpr.locMarker)\n\nenum Pat:\n  case Lit(lit: mlscript.Lit)\n  case Class(cls: ClassRef)\n\n  def isTrue = this match\n    case Class(cls) => cls.name == \"True\"\n    case _ => false\n  \n  def isFalse = this match\n    case Class(cls) => cls.name == \"False\"\n    case _ => false\n\n  override def toString: String = this match\n    case Lit(lit) => s\"$lit\"\n    case Class(cls) => s\"${cls.name}\"\n\nenum Node:\n  // Terminal forms:\n  case Result(res: Ls[TrivialExpr])\n  case Jump(defn: DefnRef, args: Ls[TrivialExpr])\n  case Case(scrut: Name, cases: Ls[(Pat, Node)], default: Opt[Node])\n  // Intermediate forms:\n  case LetExpr(name: Name, expr: Expr, body: Node)\n  case LetMethodCall(names: Ls[Name], cls: ClassRef, method: Name, args: Ls[TrivialExpr], body: Node)\n  // Deprecated:\n  //   LetApply(names, fn, args, body) => LetMethodCall(names, ClassRef(R(\"Callable\")), Name(\"apply\" + args.length), (Ref(fn): TrivialExpr) :: args, body)\n  // case LetApply(names: Ls[Name], fn: Name, args: Ls[TrivialExpr], body: Node)\n  case LetCall(names: Ls[Name], defn: DefnRef, args: Ls[TrivialExpr], isTailRec: Bool, body: Node)(val loc: Opt[Loc] = None)\n\n  var tag = DefnTag(-1)\n\n  def attachTag(x: FreshInt): Node =\n    this.tag = DefnTag(x.make)\n    this\n  def attachTagAs[V](x: FreshInt): V =\n    attachTag(x).asInstanceOf[V]\n  def copyTag(x: Node) =\n    this.tag = x.tag\n    this\n\n  override def toString: String = show\n\n  def show: String =\n    toDocument.print\n\n  def mapName(f: Name => Name): Node = this match\n    case Result(res) => Result(res.map(_.mapNameOfTrivialExpr(f)))\n    case Jump(defn, args) => Jump(defn, args.map(_.mapNameOfTrivialExpr(f)))\n    case Case(scrut, cases, default) => Case(f(scrut), cases.map { (cls, arm) => (cls, arm.mapName(f)) }, default.map(_.mapName(f)))\n    case LetExpr(name, expr, body) => LetExpr(f(name), expr.mapName(f), body.mapName(f))\n    case LetMethodCall(names, cls, method, args, body) => LetMethodCall(names.map(f), cls, f(method), args.map(_.mapNameOfTrivialExpr(f)), body.mapName(f))\n    case lc @ LetCall(names, defn, args, itr, body) => LetCall(names.map(f), defn, args.map(_.mapNameOfTrivialExpr(f)), itr, body.mapName(f))(lc.loc)\n  \n  def copy(ctx: Map[Str, Name]): Node = this match\n    case Result(res) => Result(res.map(_.mapNameOfTrivialExpr(_.trySubst(ctx))))\n    case Jump(defn, args) => Jump(defn, args.map(_.mapNameOfTrivialExpr(_.trySubst(ctx))))\n    case Case(scrut, cases, default) => Case(ctx(scrut.str), cases.map { (cls, arm) => (cls, arm.copy(ctx)) }, default.map(_.copy(ctx)))\n    case LetExpr(name, expr, body) => \n      val name_copy = name.copy\n      LetExpr(name_copy, expr.mapName(_.trySubst(ctx)), body.copy(ctx + (name_copy.str -> name_copy)))\n    case LetMethodCall(names, cls, method, args, body) =>\n      val names_copy = names.map(_.copy)\n      LetMethodCall(names_copy, cls, method.copy, args.map(_.mapNameOfTrivialExpr(_.trySubst(ctx))), body.copy(ctx ++ names_copy.map(x => x.str -> x)))\n    case lc @ LetCall(names, defn, args, itr, body) =>\n      val names_copy = names.map(_.copy)\n      LetCall(names_copy, defn, args.map(_.mapNameOfTrivialExpr(_.trySubst(ctx))), itr, body.copy(ctx ++ names_copy.map(x => x.str -> x)))(lc.loc)\n\n  def toDocument: Document =\n    given Conversion[String, Document] = raw\n    this match\n    case Result(res) => (res |> showArguments) <:> s\"-- $tag\"\n    case Jump(jp, args) =>\n      \"jump\"\n      <:> jp.name\n      <#> \"(\"\n      <#> (args |> showArguments)\n      <#> \")\"\n      <:> s\"-- $tag\" \n    case Case(x, Ls((tpat, tru), (fpat, fls)), N) if tpat.isTrue && fpat.isFalse =>\n      val first = \"if\" <:> x.toString <:> s\"-- $tag\" \n      val tru2 = indent(stack(\"true\" <:> \"=>\", tru.toDocument |> indent))\n      val fls2 = indent(stack(\"false\" <:> \"=>\", fls.toDocument |> indent))\n      Document.Stacked(Ls(first, tru2, fls2))\n    case Case(x, cases, default) =>\n      val first = \"case\" <:> x.toString <:> \"of\" <:> s\"-- $tag\" \n      val other = cases flatMap {\n        case (pat, node) =>\n          Ls(pat.toString <:> \"=>\", node.toDocument |> indent)\n      }\n      default match\n        case N => stack(first, (Document.Stacked(other) |> indent))\n        case S(dc) =>\n          val default = Ls(\"_\" <:> \"=>\", dc.toDocument |> indent)\n          stack(first, (Document.Stacked(other ++ default) |> indent))\n    case LetExpr(x, expr, body) => \n      stack(\n        \"let\"\n          <:> x.toString\n          <:> \"=\"\n          <:> expr.toDocument\n          <:> \"in\"\n          <:> s\"-- $tag\",\n        body.toDocument)\n    case LetMethodCall(xs, cls, method, args, body) =>\n      stack(\n        \"let\"\n          <:> xs.map(_.toString).mkString(\",\")\n          <:> \"=\"\n          <:> cls.name\n          <#> \".\"\n          <#> method.toString\n          <#> \"(\"\n          <#> args.map{ x => x.toString }.mkString(\",\")\n          <#> \")\"\n          <:> \"in\" \n          <:> s\"-- $tag\",\n        body.toDocument)\n    case LetCall(xs, defn, args, itr, body) => \n      stack(\n        \"let*\"\n          <:> \"(\"\n          <#> xs.map(_.toString).mkString(\",\")\n          <#> \")\"\n          <:> \"=\"\n          <:> (if itr then \"@tailcall \" else \"\") + defn.name\n          <#> \"(\"\n          <#> args.map{ x => x.toString }.mkString(\",\")\n          <#> \")\"\n          <:> \"in\" \n          <:> s\"-- $tag\",\n        body.toDocument)\n  \n  def locMarker: LocMarker =\n    val marker = this match\n      case Result(res) => LocMarker.MResult(res.map(_.toExpr.locMarker))\n      case Jump(defn, args) => LocMarker.MJump(defn.name, args.map(_.toExpr.locMarker))\n      case Case(scrut, cases, default) => LocMarker.MCase(scrut.str, cases.map(_._1), default.isDefined)\n      case LetExpr(name, expr, _) => LocMarker.MLetExpr(name.str, expr.locMarker)\n      case LetMethodCall(names, cls, method, args, _) => LocMarker.MLetMethodCall(names.map(_.str), cls, method.str, args.map(_.toExpr.locMarker))\n      case LetCall(names, defn, args, _, _) => LocMarker.MLetCall(names.map(_.str), defn.name, args.map(_.toExpr.locMarker))\n    marker.tag = this.tag\n    marker\n\n\ntrait DefTraversalOrdering:\n  def ordered(entry: Node, defs: Set[Defn]): Ls[Defn]\n  def orderedNames(entry: Node, defs: Set[Defn]): Ls[Str]\n\nobject DefDfs:\n  import Node._\n  \n  private object Successors:\n    def find(node: Node)(using acc: Ls[Defn]): Ls[Defn] =\n      node match\n        case Result(res) => acc\n        case Jump(defn, args) => defn.expectDefn :: acc\n        case Case(scrut, cases, default) =>\n          val acc2 = cases.map(_._2) ++ default.toList\n          acc2.foldLeft(acc)((acc, x) => find(x)(using acc))\n        case LetExpr(name, expr, body) => find(body)\n        case LetMethodCall(names, cls, method, args, body) => find(body)\n        case LetCall(names, defn, args, _, body) => find(body)(using defn.expectDefn :: acc)\n      \n    def find(defn: Defn)(using acc: Ls[Defn]): Ls[Defn] = find(defn.body)\n    def findNames(node: Node)(using acc: Ls[Str]): Ls[Str] =\n      node match\n        case Result(res) => acc\n        case Jump(defn, args) => defn.name :: acc\n        case Case(scrut, cases, default) =>\n          val acc2 = cases.map(_._2) ++ default.toList\n          acc2.foldLeft(acc)((acc, x) => findNames(x)(using acc))\n        case LetExpr(name, expr, body) => findNames(body)\n        case LetMethodCall(names, cls, method, args, body) => findNames(body)\n        case LetCall(names, defn, args, _, body) => findNames(body)(using defn.name :: acc)\n      \n    def findNames(defn: Defn)(using acc: Ls[Str]): Ls[Str] = findNames(defn.body)\n\n  private def dfs(using visited: HashMap[Str, Bool], out: ListBuffer[Defn], postfix: Bool)(x: Defn): Unit =\n    visited.update(x.name, true)\n    if (!postfix)\n      out += x\n    Successors.find(x)(using Nil).foreach { y =>\n      if (!visited(y.name))\n        dfs(y)\n    }\n    if (postfix)\n      out += x\n  \n  private def dfs(using visited: HashMap[Str, Bool], out: ListBuffer[Defn], postfix: Bool)(x: Node): Unit =\n    Successors.find(x)(using Nil).foreach { y =>\n      if (!visited(y.name))\n        dfs(y)\n    }\n\n  private def dfsNames(using visited: HashMap[Str, Bool], defs: Set[Defn], out: ListBuffer[Str], postfix: Bool)(x: Defn): Unit =\n    visited.update(x.name, true)\n    if (!postfix)\n      out += x.name\n    Successors.findNames(x)(using Nil).foreach { y =>\n      if (!visited(y))\n        dfsNames(defs.find(_.name == y).get)\n    }\n    if (postfix)\n      out += x.name\n  \n  private def dfsNames(using visited: HashMap[Str, Bool], defs: Set[Defn], out: ListBuffer[Str], postfix: Bool)(x: Node): Unit =\n    Successors.findNames(x)(using Nil).foreach { y =>\n      if (!visited(y))\n        dfsNames(defs.find(_.name == y).get)\n    }\n\n  def dfs(entry: Node, defs: Set[Defn], postfix: Bool): Ls[Defn] =\n    val visited = HashMap[Str, Bool]()\n    visited ++= defs.map(_.name -> false)\n    val out = ListBuffer[Defn]()\n    dfs(using visited, out, postfix)(entry)\n    out.toList\n\n  def dfsNames(entry: Node, defs: Set[Defn], postfix: Bool): Ls[Str] =\n    val visited = HashMap[Str, Bool]()\n    visited ++= defs.map(_.name -> false)\n    val out = ListBuffer[Str]()\n    dfsNames(using visited, defs, out, postfix)(entry)\n    out.toList\n    \nobject DefRevPostOrdering extends DefTraversalOrdering:\n  def ordered(entry: Node, defs: Set[Defn]): Ls[Defn] =\n    DefDfs.dfs(entry, defs, true).reverse\n  def orderedNames(entry: Node, defs: Set[Defn]): Ls[Str] =\n    DefDfs.dfsNames(entry, defs, true).reverse\n\nobject DefRevPreOrdering extends DefTraversalOrdering:\n  def ordered(entry: Node, defs: Set[Defn]): Ls[Defn] =\n    DefDfs.dfs(entry, defs, false).reverse\n  def orderedNames(entry: Node, defs: Set[Defn]): Ls[Str] =\n    DefDfs.dfsNames(entry, defs, false).reverse\n\n\n\ncase class DefnTag(inner: Int):\n  def is_valid = inner >= 0\n  override def equals(x: Any): Bool = x match\n    case o: DefnTag =>\n      (this, o) match\n        case (DefnTag(a), DefnTag(b)) => this.is_valid && o.is_valid && a == b\n    case _ => false\n  override def toString: String = if is_valid then s\"#$inner\" else \"#x\"\n\ncase class DefnLocMarker(val defn: Str, val marker: LocMarker):\n  override def toString: String = s\"$defn:$marker\"\n  def matches = marker.matches\n\nenum LocMarker:\n  case MRef(name: Str)\n  case MLit(lit: Lit)\n  case MCtorApp(name: ClassRef, args: Ls[LocMarker])\n  case MSelect(name: Str, cls: ClassRef, field: Str)\n  case MBasicOp(name: Str, args: Ls[LocMarker])\n  case MAssignField(assignee: Str, field: Str, value: LocMarker)\n  case MResult(res: Ls[LocMarker])\n  case MJump(name: Str, args: Ls[LocMarker])\n  case MCase(scrut: Str, cases: Ls[Pat], default: Bool)\n  case MLetExpr(name: Str, expr: LocMarker)\n  case MLetMethodCall(names: Ls[Str], cls: ClassRef, method: Str, args: Ls[LocMarker])\n  case MLetCall(names: Ls[Str], defn: Str, args: Ls[LocMarker])\n  var tag = DefnTag(-1)\n\n  def toDocument: Document = \n    given Conversion[String, Document] = raw\n    this match\n    case MResult(res) => \"...\"\n    case MJump(jp, args) =>\n      \"jump\"\n      <:> jp\n      <:> \"...\"\n    case MCase(x, Ls(tpat, fpat), false) if tpat.isTrue && fpat.isFalse =>\n      \"if\" <:> x.toString <:> \"...\"\n    case MCase(x, cases, default) =>\n      \"case\" <:> x.toString <:> \"of\" <:> \"...\"\n    case MLetExpr(x, expr) => \n      \"let\"\n        <:> x.toString\n        <:> \"=\"\n        <:> \"...\"\n    case MLetMethodCall(xs, cls, method, args) =>\n      \"let\"\n        <:> xs.map(_.toString).mkString(\",\")\n        <:> \"=\"\n        <:> cls.name\n        <:> \".\"\n        <:> method\n        <:> \"...\"\n    case MLetCall(xs, defn, args) =>\n      \"let*\"\n        <:> \"(\"\n        <#> xs.map(_.toString).mkString(\",\")\n        <#> \")\"\n        <:> \"=\"\n        <:> defn\n        <:> \"...\"\n    case MRef(s) => s.toString\n    case MLit(IntLit(lit)) => s\"$lit\"\n    case MLit(DecLit(lit)) => s\"$lit\"\n    case MLit(StrLit(lit)) => s\"$lit\"\n    case MLit(UnitLit(undefinedOrNull)) => if undefinedOrNull then \"undefined\" else \"null\"\n    case _ => \"...\"\n\n  def show = s\"$tag-\" + toDocument.print\n\n  override def toString: String = show\n\n  def matches(x: Node): Bool = this.tag == x.tag\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/ir/Interp.scala",
    "content": "package mlscript.compiler.ir\n\nimport mlscript._\nimport mlscript.compiler.ir._\nimport mlscript.compiler.utils._\nimport mlscript.compiler.optimizer._\nimport mlscript.utils._\nimport scala.collection.immutable._\nimport scala.annotation._\nimport shorthands._\nimport scala.collection.mutable.ListBuffer\nimport scala.util.boundary, boundary.break\n\nenum Stuck:\n  case StuckExpr(expr: Expr, msg: Str)\n  case StuckNode(node: Node, msg: Str)\n\n  override def toString: String =\n    this match\n      case StuckExpr(expr, msg) => s\"StuckExpr(${expr.show}, $msg)\"\n      case StuckNode(node, msg) => s\"StuckNode(${node.show}, $msg)\"\n\nfinal case class InterpreterError(message: String) extends Exception(message)\n\nclass Interpreter(verbose: Bool):\n  private def log(x: Any) = if verbose then println(x)\n  import Stuck._\n\n  private case class Configuration(\n    var context: Ctx\n  )\n\n  private type Result[T] = Either[Stuck, T]\n\n  private enum Value:\n    case Class(cls: ClassInfo, var fields: Ls[Value])\n    case Literal(lit: Lit)\n\n    override def toString: String = \n      this match\n        case Class(cls, fields) => s\"${cls.name}(${fields.mkString(\",\")})\"\n        case Literal(IntLit(lit)) => lit.toString\n        case Literal(DecLit(lit)) => lit.toString\n        case Literal(StrLit(lit)) => lit.toString\n        case Literal(UnitLit(undefinedOrNull)) => if undefinedOrNull then \"undefined\" else \"null\"\n\n  private final case class Ctx(\n    bindingCtx: Map[Str, Value],\n    classCtx: Map[Str, ClassInfo],\n    defnCtx: Map[Str, Defn],\n  )\n  \n  import Node._\n  import Expr._\n\n  private def getTrue(using ctx: Ctx) = Value.Class(ctx.classCtx(\"True\"), Ls.empty)\n  private def getFalse(using ctx: Ctx) = Value.Class(ctx.classCtx(\"False\"), Ls.empty)\n  \n  private def eval(op: Str, x1: Value, x2: Value)(using ctx: Ctx): Opt[Value] =\n    import Value.{Literal => Li}\n    (op, x1, x2) match\n    case (\"+\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x + y)))\n    case (\"-\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x - y)))\n    case (\"*\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x * y)))\n    case (\"/\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x / y)))\n    case (\"==\", Li(IntLit(x)), Li(IntLit(y))) => S(if x == y then getTrue else getFalse)\n    case (\"!=\", Li(IntLit(x)), Li(IntLit(y))) => S(if x != y then getTrue else getFalse)\n    case (\"<=\", Li(IntLit(x)), Li(IntLit(y))) => S(if x <= y then getTrue else getFalse)\n    case (\">=\", Li(IntLit(x)), Li(IntLit(y))) => S(if x >= y then getTrue else getFalse)\n    case (\">\", Li(IntLit(x)), Li(IntLit(y))) => S(if x > y then getTrue else getFalse)\n    case (\"<\", Li(IntLit(x)), Li(IntLit(y))) => S(if x < y then getTrue else getFalse)\n    case _ => N\n\n  private def evalArgs(using ctx: Ctx)(exprs: Ls[TrivialExpr]): Result[Ls[Value]] =\n    var values = ListBuffer.empty[Value]\n    var stuck: Opt[Stuck] = None\n    exprs foreach { expr =>\n      stuck match\n        case None => eval(expr) match\n          case L(x) => stuck = Some(x)\n          case R(x) => values += x\n        case _ => ()\n    } \n    stuck.toLeft(values.toList)\n\n  private def eval(expr: TrivialExpr)(using ctx: Ctx): Result[Value] = expr match\n    case e @ Ref(name) => ctx.bindingCtx.get(name.str).toRight(StuckExpr(e, s\"undefined variable $name\"))\n    case Literal(lit) => R(Value.Literal(lit))\n  \n  private def eval(expr: Expr)(using ctx: Ctx): Result[Value] = expr match\n    case Ref(Name(x)) => ctx.bindingCtx.get(x).toRight(StuckExpr(expr, s\"undefined variable $x\"))\n    case Literal(x) => R(Value.Literal(x))\n    case CtorApp(cls, args) => for {\n        xs <- evalArgs(args)\n        cls <- ctx.classCtx.get(cls.name).toRight(StuckExpr(expr, s\"undefined class ${cls.name}\"))\n      } yield Value.Class(cls, xs)\n    case Select(name, cls, field) =>\n      ctx.bindingCtx.get(name.str).toRight(StuckExpr(expr, s\"undefined variable $name\")).flatMap {\n        case Value.Class(cls2, xs) if cls.name == cls2.name =>\n          xs.zip(cls2.fields).find{_._2 == field} match\n            case Some((x, _)) => R(x)\n            case None => L(StuckExpr(expr, s\"unable to find selected field $field\"))\n        case Value.Class(cls2, xs) => L(StuckExpr(expr, s\"unexpected class $cls2\"))\n        case x => L(StuckExpr(expr, s\"unexpected value $x\"))\n      }\n    case BasicOp(name, args) => boundary:\n      evalArgs(args).flatMap(\n        xs => \n          name match\n            case \"+\" | \"-\" | \"*\" | \"/\" | \"==\" | \"!=\" | \"<=\" | \">=\" | \"<\" | \">\" => \n              if xs.length < 2 then break:\n                L(StuckExpr(expr, s\"not enough arguments for basic operation $name\"))\n              else eval(name, xs.head, xs.tail.head).toRight(StuckExpr(expr, s\"unable to evaluate basic operation\"))\n            case _ => L(StuckExpr(expr, s\"unexpected basic operation $name\")))\n    case AssignField(assignee, cls, field, value) =>\n      for {\n        x <- eval(Ref(assignee): TrivialExpr)\n        y <- eval(value)\n        res <- x match\n          case obj @ Value.Class(cls2, xs) if cls.name == cls2.name =>\n            xs.zip(cls2.fields).find{_._2 == field} match\n              case Some((_, _)) =>\n                obj.fields = xs.map(x => if x == obj then y else x)\n                // Ideally, we should return a unit value here, but here we return the assignee value for simplicity.\n                R(obj)\n              case None => L(StuckExpr(expr, s\"unable to find selected field $field\"))\n          case Value.Class(cls2, xs) => L(StuckExpr(expr, s\"unexpected class $cls2\"))\n          case x => L(StuckExpr(expr, s\"unexpected value $x\"))\n      } yield res\n\n  private def eval(node: Node)(using ctx: Ctx): Result[Ls[Value]] = node match\n    case Result(res) => evalArgs(res)\n    case Jump(defn, args) => for {\n        xs <- evalArgs(args)\n        defn <- ctx.defnCtx.get(defn.name).toRight(StuckNode(node, s\"undefined function ${defn.name}\"))\n        ctx1 = ctx.copy(bindingCtx = ctx.bindingCtx ++ defn.params.map{_.str}.zip(xs))\n        res <- eval(defn.body)(using ctx1)\n      } yield res\n    case Case(scrut, cases, default) =>\n      eval(Ref(scrut): Expr) flatMap {\n        case Value.Class(cls, fields) => \n          cases.find {\n            case (Pat.Class(cls2), _) => cls.name == cls2.name\n            case _ => false\n          } match {\n            case Some((_, x)) => eval(x)\n            case None => \n              default match\n                case S(x) => eval(x)\n                case N => L(StuckNode(node, s\"can not find the matched case, ${cls.name} expected\"))\n          }\n        case Value.Literal(lit) => \n          cases.find {\n            case (Pat.Lit(lit2), _) => lit == lit2\n            case _ => false\n          } match {\n            case Some((_, x)) => eval(x)\n            case None => \n              default match\n                case S(x) => eval(x)\n                case N => L(StuckNode(node, s\"can not find the matched case, $lit expected\"))\n          }\n      }\n    case LetExpr(name, expr, body) =>\n      for {\n        x <- eval(expr)\n        ctx1 = ctx.copy(bindingCtx = ctx.bindingCtx + (name.str -> x))\n        res <- eval(body)(using ctx1)\n      } yield res\n    case LetMethodCall(names, cls, method, args, body) =>\n      for {\n        ys <- evalArgs(args).flatMap {\n          case Value.Class(cls2, xs) :: args =>\n            cls2.methods.get(method.str).toRight(StuckNode(node, s\"undefined method ${method.str}\")).flatMap { method =>\n              val ctx1 = ctx.copy(bindingCtx = ctx.bindingCtx ++ cls2.fields.zip(xs) ++ method.params.map{_.str}.zip(args))\n              eval(method.body)(using ctx1)\n            }\n          case _ => L(StuckNode(node, s\"not enough arguments for method call, or the first argument is not a class\"))\n        }\n        ctx2 = ctx.copy(bindingCtx = ctx.bindingCtx ++ names.map{_.str}.zip(ys))\n        res <- eval(body)(using ctx2)\n      } yield res\n    // case LetApply(names, fn, args, body) => eval(LetMethodCall(names, ClassRef(R(\"Callable\")), Name(\"apply\" + args.length), (Ref(fn): TrivialExpr) :: args, body))\n    case LetCall(names, defn, args, _, body) =>\n      for {\n        xs <- evalArgs(args)\n        defn <- ctx.defnCtx.get(defn.name).toRight(StuckNode(node, s\"undefined function ${defn.name}\"))\n        ctx1 = ctx.copy(bindingCtx = ctx.bindingCtx ++ defn.params.map{_.str}.zip(xs))\n        ys <- eval(defn.body)(using ctx1)\n        ctx2 = ctx.copy(bindingCtx = ctx.bindingCtx ++ names.map{_.str}.zip(ys))\n        res <- eval(body)(using ctx2)\n      } yield res\n\n  private def f(prog: Program): Ls[Value] =\n    val Program(classes, defs, main) = prog\n    given Ctx = Ctx(\n      bindingCtx = Map.empty,\n      classCtx = classes.map{cls => cls.name -> cls}.toMap,\n      defnCtx = defs.map{defn => defn.name -> defn}.toMap,\n    )\n    eval(main) match\n      case R(x) => x\n      case L(x) => throw InterpreterError(\"Stuck evaluation: \" + x.toString)\n    \n  def interpret(prog: Program): Str =\n    val node = f(prog) \n    node.map(_.toString).mkString(\",\")\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/ir/RefResolver.scala",
    "content": "package mlscript.compiler.ir\n\nimport mlscript.utils.shorthands._\nimport mlscript.compiler.ir._\n\nimport Node._\n\n// Resolves the definition references by turning them from Right(name) to Left(Defn).\nprivate final class RefResolver(defs: Map[Str, Defn], classes: Map[Str, ClassInfo], allowInlineJp: Bool):\n  private def f(x: Expr): Unit = x match\n    case Expr.Ref(name) => \n    case Expr.Literal(lit) =>\n    case Expr.CtorApp(cls, args) => classes.get(cls.name) match\n      case None => throw IRError(f\"unknown class ${cls.name} in ${classes.keySet.mkString(\",\")}\")\n      case Some(value) => cls.cls = Left(value)\n    case Expr.Select(name, cls, field) => classes.get(cls.name) match\n      case None => throw IRError(f\"unknown class ${cls.name} in ${classes.keySet.mkString(\",\")}\")\n      case Some(value) => cls.cls = Left(value)\n    case Expr.BasicOp(name, args) =>\n    case Expr.AssignField(assigneee, cls, field, value) => classes.get(cls.name) match\n      case None => throw IRError(f\"unknown class ${cls.name} in ${classes.keySet.mkString(\",\")}\")\n      case Some(value) => cls.cls = Left(value)\n\n  private def f(x: Pat): Unit = x match\n    case Pat.Lit(lit) => \n    case Pat.Class(cls) => classes.get(cls.name) match\n      case None => throw IRError(f\"unknown class ${cls.name} in ${classes.keySet.mkString(\",\")}\")\n      case Some(value) => cls.cls = Left(value)\n  \n  private def f(x: Node): Unit = x match\n    case Result(res) =>\n    case Case(scrut, cases, default) => cases foreach { (_, body) => f(body) }; default foreach f\n    case LetExpr(name, expr, body) => f(expr); f(body)\n    case LetMethodCall(names, cls, method, args, body) => f(body)\n    case LetCall(resultNames, defnref, args, _, body) =>\n      defs.get(defnref.name) match\n        case Some(defn) => defnref.defn = Left(defn)\n        case None => throw IRError(f\"unknown function ${defnref.name} in ${defs.keySet.mkString(\",\")}\")\n        f(body)\n    case Jump(defnref, _) =>\n      // maybe not promoted yet\n      defs.get(defnref.name) match\n        case Some(defn) => defnref.defn = Left(defn)\n        case None =>\n          if (!allowInlineJp)\n            throw IRError(f\"unknown function ${defnref.name} in ${defs.keySet.mkString(\",\")}\")\n  def run(node: Node) = f(node)\n  def run(node: Defn) = f(node.body)\n\ndef resolveRef(entry: Node, defs: Set[Defn], classes: Set[ClassInfo], allowInlineJp: Bool = false): Unit  =\n  val defsMap = defs.map(x => x.name -> x).toMap\n  val classesMap = classes.map(x => x.name -> x).toMap\n  val rl = RefResolver(defsMap, classesMap, allowInlineJp)\n  rl.run(entry)\n  defs.foreach(rl.run(_))\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/ir/Validator.scala",
    "content": "package mlscript.compiler.ir\n\nimport mlscript.utils.shorthands._\nimport mlscript.compiler.ir._\n\n\nprivate final class DefnRefInSet(defs: Set[Defn], classes: Set[ClassInfo]):\n  import Node._\n  import Expr._\n  \n  private def f(x: Expr): Unit = x match\n    case Ref(name) => \n    case Literal(lit) =>\n    case CtorApp(name, args) =>\n    case Select(name, clsref, field) => clsref.getClass match {\n      case Some(real_class) => if (!classes.exists(_ eq real_class)) throw IRError(\"ref is not in the set\")\n      case _ =>\n    }\n    case BasicOp(name, args) =>\n    case AssignField(assignee, clsref, _, value) => clsref.getClass match {\n      case Some(real_class) => if (!classes.exists(_ eq real_class)) throw IRError(\"ref is not in the set\")\n      case _ =>\n    }\n  \n  private def f(x: Node): Unit = x match\n    case Result(res) => \n    case Jump(defn, args) =>\n    case Case(scrut, cases, default) => cases foreach { (_, body) => f(body) }; default foreach f\n    case LetExpr(name, expr, body) => f(body)\n    case LetMethodCall(names, cls, method, args, body) => f(body)\n    case LetCall(res, defnref, args, _, body) =>\n      defnref.getDefn match {\n        case Some(real_defn) => if (!defs.exists(_ eq real_defn)) throw IRError(\"ref is not in the set\")\n        case _ =>\n      }\n      f(body)\n  def run(node: Node) = f(node)\n  def run(defn: Defn) = f(defn.body)\n\ndef validateRefInSet(entry: Node, defs: Set[Defn], classes: Set[ClassInfo]): Unit =\n  val dris = DefnRefInSet(defs, classes)\n  defs.foreach(dris.run(_))\n\ndef validate(entry: Node, defs: Set[Defn], classes: Set[ClassInfo]): Unit =\n  validateRefInSet(entry, defs, classes)\n\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/optimizer/Analysis.scala",
    "content": "package mlscript.compiler.optimizer\n\nimport mlscript._\nimport mlscript.compiler.ir._\nimport mlscript.utils._\nimport shorthands._\n\nimport scala.annotation.tailrec\nimport scala.collection.immutable.*\nimport scala.collection.mutable.{HashMap => MutHMap}\nimport scala.collection.mutable.{HashSet => MutHSet, Set => MutSet}\n\nclass UsefulnessAnalysis(verbose: Bool = false): \n  import Expr._\n  import Node._\n\n  def log(x: Any) = if verbose then println(x)\n  \n  val uses = MutHMap[(Name, Int), Int]()\n  val defs = MutHMap[Name, Int]()\n\n  private def addDef(x: Name) =\n    defs.update(x, defs.getOrElse(x, 0) + 1)\n  \n  private def addUse(x: Name) =\n    val def_count = defs.get(x) match\n      case None => throw IRError(s\"Use of undefined variable $x\")\n      case Some(value) => value\n    val key = (x, defs(x))\n    uses.update(key, uses.getOrElse(key, 0) + 1)\n  \n  private def f(x: TrivialExpr): Unit = x match\n    case Ref(name) => addUse(name)\n    case _ => ()\n\n  private def f(x: Expr): Unit = x match\n    case Ref(name) => addUse(name)\n    case Literal(lit) =>\n    case CtorApp(name, args) => args.foreach(f)\n    case Select(name, cls, field) => addUse(name)\n    case BasicOp(name, args) => args.foreach(f)\n    case AssignField(assignee, _, _, value) =>\n      addUse(assignee)\n      f(value)\n  \n  private def f(x: Node): Unit = x match\n    case Result(res) => res.foreach(f)\n    case Jump(defn, args) => args.foreach(f)\n    case Case(scrut, cases, default) => addUse(scrut); cases.foreach { case (cls, body) => f(body) }; default.foreach(f)\n    case LetMethodCall(names, cls, method, args, body) => addUse(method); args.foreach(f); names.foreach(addDef); f(body)\n    case LetExpr(name, expr, body) => f(expr); addDef(name); f(body)\n    case LetCall(names, defn, args, _, body) => args.foreach(f); names.foreach(addDef); f(body)\n  \n  def run(x: Defn) =\n    x.params.foreach(addDef)\n    f(x.body)\n    uses.toMap\n\nclass FreeVarAnalysis(extended_scope: Bool = true, verbose: Bool = false):\n  import Expr._\n  import Node._\n\n  private val visited = MutHSet[Str]()\n  private def f(using defined: Set[Str])(defn: Defn, fv: Set[Str]): Set[Str] =\n    val defined2 = defn.params.foldLeft(defined)((acc, param) => acc + param.str)\n    f(using defined2)(defn.body, fv)\n  private def f(using defined: Set[Str])(expr: Expr, fv: Set[Str]): Set[Str] = expr match\n    case Ref(name) => if (defined.contains(name.str)) fv else fv + name.str\n    case Literal(lit) => fv\n    case CtorApp(name, args) => args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n    case Select(name, cls, field) => if (defined.contains(name.str)) fv else fv + name.str\n    case BasicOp(name, args) => args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n    case AssignField(assignee, _, _, value) => f(using defined)(\n      value.toExpr, \n      if defined.contains(assignee.str) then fv + assignee.str else fv\n    ) \n  private def f(using defined: Set[Str])(node: Node, fv: Set[Str]): Set[Str] = node match\n    case Result(res) => res.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n    case Jump(defnref, args) =>\n      var fv2 = args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n      if (extended_scope && !visited.contains(defnref.name))\n        val defn = defnref.expectDefn\n        visited.add(defn.name)\n        val defined2 = defn.params.foldLeft(defined)((acc, param) => acc + param.str)\n        fv2 = f(using defined2)(defn, fv2)\n      fv2\n    case Case(scrut, cases, default) =>\n      val fv2 = if (defined.contains(scrut.str)) fv else fv + scrut.str\n      val fv3 = cases.foldLeft(fv2) {\n        case (acc, (cls, body)) => f(using defined)(body, acc)\n      }\n      fv3\n    case LetMethodCall(resultNames, cls, method, args, body) =>\n      var fv2 = args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n      val defined2 = resultNames.foldLeft(defined)((acc, name) => acc + name.str)\n      f(using defined2)(body, fv2)\n    case LetExpr(name, expr, body) =>\n      val fv2 = f(using defined)(expr, fv)\n      val defined2 = defined + name.str\n      f(using defined2)(body, fv2)\n    case LetCall(resultNames, defnref, args, _, body) =>\n      var fv2 = args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n      val defined2 = resultNames.foldLeft(defined)((acc, name) => acc + name.str)\n      if (extended_scope && !visited.contains(defnref.name))\n        val defn = defnref.expectDefn\n        visited.add(defn.name)\n        val defined2 = defn.params.foldLeft(defined)((acc, param) => acc + param.str)\n        fv2 = f(using defined2)(defn, fv2)\n      f(using defined2)(body, fv2)\n  def run(node: Node) = f(using Set.empty)(node, Set.empty)\n  def run_with(node: Node, defined: Set[Str]) = f(using defined)(node, Set.empty)\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/optimizer/TailRecOpt.scala",
    "content": "package mlscript\npackage compiler.optimizer\n\nimport scala.annotation.tailrec\n\nimport utils.shorthands._\nimport Message.MessageContext\n\nimport compiler.ir._\nimport compiler.ir.Node._\n\n/*\n\nDOCUMENTATION OF SEMANTICS OF @tailcall and @tailrec\n\n@tailcall: Used to annotate specific function calls. Calls annotated with @tailcall \nmust be tail calls or tail modulo-cons calls. These calls must be optimized to not\nconsume additional stack space. If such an optimization is not possible, then the\ncompiler will throw an error.\n\nIf there are multiple possible candidates for tail modulo-cons calls in a single\nbranch of an expression, then @tailcall can be uesd to indicate which one will be\noptimized. For instance in\n\nfun foo() =\n  A(foo(), bar())\n\nwe can use @tailcall to annotate the call foo() or bar(). If a call other than the\nlast call is annotated with @tailcall, then the remaining functions must be pure\nto ensure that reordering computations does not change the result.\n\nIf bar() is impure but you still want to optimize the call foo(), then you can do\n\nfun foo() =\n  let b = bar()\n  let a = @tailcall foo()\n  A(a, b)\n\nbecause here, you are taking responsibility for the reordering of the computations.\n\n@tailrec: Used to annotate functions. When this annotation is used on a function, say\n@tailrec fun foo(), the compiler will ensure no sequence of direct recursive calls back \nto foo() consume stack space, i.e. they are all tail calls. Note that a call to foo() \nmay consume an arbitrary amount of stack space as long as foo() is only consuming finite\nstack space. For example,\n\n@tailrec fun foo() = bar()\nfun bar() =\n  bar()\n  bar()\n\nis valid. However,\n\n@tailrec fun foo() = bar()\nfun bar() =\n  foo()\n  bar()\n\nis invalid. If we swap the position of foo() and bar() in the body of bar, it is still invalid.\n\nEquivalently, if fun foo() is annotated with @tailrec, let S be the largest strongly\nconnected component in the call-graph of the program that contains foo. Then an error\nwill be thrown unless all edges (calls) connecting the nodes of the strongly\nconnected component are tail calls or tail modulo-cons calls.\n\n*/\n\n// fnUid should be the same FreshInt that was used to build the graph being passed into this class\nclass TailRecOpt(fnUid: FreshInt, classUid: FreshInt, tag: FreshInt, raise: Diagnostic => Unit):\n  case class LetCtorNodeInfo(node: LetExpr, ctor: Expr.CtorApp, cls: ClassInfo, ctorValName: Name, fieldName: String, idx: Int)\n\n  enum CallInfo:\n    case NormalCallInfo(src: Defn, defn: Defn)(val loc: Option[Loc]) extends CallInfo\n    case TailCallInfo(src: Defn, defn: Defn) extends CallInfo\n    case ModConsCallInfo(src: Defn, startNode: Node, defn: Defn, letCallNode: LetCall, letCtorNode: LetCtorNodeInfo, retName: Name, retNode: Node) extends CallInfo\n\n    override def toString(): String = this match\n      case NormalCallInfo(src, defn) =>\n        f\"Call { ${src.name}$$${src.id} -> ${defn.name}$$${defn.id} }\"\n      case TailCallInfo(src, defn) => \n        f\"TailCall { ${src.name}$$${src.id} -> ${defn.name}$$${defn.id} }\"\n      case ModConsCallInfo(src, startNode, defn, letCallNode, letCtorNode, _, _) =>\n        f\"ModConsCall { ${src.name}$$${src.id} -> ${defn.name}$$${defn.id}, class: ${letCtorNode.cls.name}, field: ${letCtorNode.fieldName} }\"\n\n    def getSrc = this match\n      case NormalCallInfo(src, _) => src \n      case TailCallInfo(src, _) => src\n      case ModConsCallInfo(src, _, _, _, _, _, _) => src \n\n    def getDefn = this match\n      case NormalCallInfo(_, defn) => defn\n      case TailCallInfo(_, defn) => defn\n      case ModConsCallInfo(_, _, defn, _, _, _, _) => defn\n    \n  private class DefnGraph(val nodes: Set[DefnNode], val edges: Set[CallInfo], val joinPoints: Set[Defn]):\n    def removeMetadata: ScComponent = ScComponent(nodes.map(_.defn), edges, joinPoints)\n  \n  private class ScComponent(val nodes: Set[Defn], val edges: Set[CallInfo], val joinPoints: Set[Defn])\n\n  import CallInfo._\n\n  def filterOptCalls(calls: Iterable[CallInfo]) =\n    calls.collect { case c: TailCallInfo => c; case c: ModConsCallInfo => c }\n\n  def filterNormalCalls(calls: Iterable[CallInfo]) =\n    calls.collect { case c: NormalCallInfo => c }\n\n  // Hack to make scala think discoverJoinPoints is tail recursive and be\n  // partially optimized :P\n  def casesToJps(cases: List[(Pat, Node)], default: Opt[Node], acc: Set[Defn]): Set[Defn] =\n    cases.foldLeft(default.fold(acc)(x => discoverJoinPoints(x, acc)))((jps, branch) => discoverJoinPoints(branch._2, jps))\n  \n  def discoverJoinPointsCont(defn: Defn, acc: Set[Defn]) =\n    discoverJoinPoints(defn.body, acc) + defn\n\n  // TODO: implement proper purity checking. This is a very simple purity check that only allows the last\n  // parameter of a mod cons call to be optimised.\n  private val pureCache: scala.collection.mutable.Map[Int, Bool] = scala.collection.mutable.Map[Int, Bool]()\n  private def isPure(node: Node): Bool = \n    pureCache.get(node.tag.inner) match\n      case None => \n        val ret = node match\n          case Jump(defn, args) => isIdentityJp(defn.expectDefn)\n          case _: LetCall => false\n          case LetMethodCall(names, cls, method, args, body) => false\n          case Case(scrut, cases, default) => cases.foldLeft(default.fold(false)(isPure))((value, branch) => value && isPure(branch._2))\n          case LetExpr(name, expr: Expr.AssignField, body) => false\n          case x: LetExpr => true\n          case Result(res) => true\n        pureCache.put(node.tag.inner, ret)\n        ret\n    \n      case Some(value) => value\n\n    \n\n\n  // do a DFS to discover join points\n  @tailrec\n  private def discoverJoinPoints(node: Node, acc: Set[Defn]): Set[Defn] =\n    node match\n      case Result(res) => Set()\n      case Jump(defn_, args) => \n        val defn = defn_.expectDefn\n        if isIdentityJp(defn) then acc\n        else if acc.contains(defn) then acc\n        else discoverJoinPointsCont(defn, acc + defn)\n      case Case(scrut, cases, default) => casesToJps(cases, default, acc)\n      case LetExpr(name, expr, body) => discoverJoinPoints(body, acc)\n      case LetMethodCall(names, cls, method, args, body) => discoverJoinPoints(body, acc)\n      case LetCall(names, defn, args, isTailRec, body) => discoverJoinPoints(body, acc)\n\n  private def getRetName(names: Set[Name], retVals: List[TrivialExpr]): Option[Name] =\n    val names = retVals.collect { case Expr.Ref(nme) => nme }\n    if names.length != 1 then None\n    else\n      val nme = names.head\n      if names.contains(nme) then Some(nme)\n      else None\n\n  // would prefer to have this inside discoverOptCalls, but scala does not support partially tail recursive functions directly\n  def shadowAndCont(next: Node, nme: Name)(implicit\n    acc: Set[CallInfo],\n    src: Defn,\n    scc: Set[Defn],\n    start: Node,\n    calledDefn: Option[Defn],\n    letCallNode: Option[LetCall],\n    letCtorNode: Option[LetCtorNodeInfo],\n    containingCtors: Set[Name]\n  ) = searchOptCalls(next)(using acc, src, scc, start, calledDefn, letCallNode, letCtorNode, containingCtors - nme) \n\n  // same here...\n  def invalidateAndCont(body: Node)(implicit\n    acc: Set[CallInfo],\n    src: Defn,\n    scc: Set[Defn],\n    start: Node,\n    calledDefn: Option[Defn],\n    letCallNode: Option[LetCall],\n    letCtorNode: Option[LetCtorNodeInfo],\n    containingCtors: Set[Name]\n  ) =\n    letCallNode match\n      case None => searchOptCalls(body)(using acc, src, scc, start, None, None, None, Set()) // invalidate everything that's been discovered\n      case Some(x: LetCall) =>\n        val LetCall(_, defn, _, isTailRec, _) = x\n        if isTailRec then \n          raise(ErrorReport(List(msg\"not a tail call\" -> x.loc), true, Diagnostic.Compilation))\n\n        val newAcc = acc + NormalCallInfo(src, defn.expectDefn)(x.loc)\n        searchOptCalls(body)(using newAcc, src, scc, start, None, None, None, Set()) // invalidate everything that's been discovered\n  \n  @tailrec\n  private def searchOptCalls(node: Node)(implicit\n    acc: Set[CallInfo],\n    src: Defn,\n    scc: Set[Defn],\n    start: Node,\n    calledDefn: Option[Defn], // The definition that was called in a tailrec mod cons call\n    letCallNode: Option[LetCall], // The place where that definition was called\n    letCtorNode: Option[LetCtorNodeInfo], // The place where the result from that call was put into a constructor\n    containingCtors: Set[Name], // Value names of ctors containing the constructor containing the result from the call\n  ): Either[Set[CallInfo], List[Node]] = \n\n    def updateMapSimple(c: CallInfo) = acc + c\n\n    def returnNoneCont = calledDefn match\n      case None => Left(acc)\n      case Some(dest) => \n        Left(updateMapSimple(NormalCallInfo(src, dest)(letCallNode.flatMap(_.loc)))) // treat the discovered call as a normal call\n\n    def returnNone = letCallNode match\n      case Some(x: LetCall) =>\n        val LetCall(_, _, _, isTailRec, _) = x\n        if isTailRec then\n          raise(ErrorReport(List(msg\"not a tail call\" -> x.loc), true, Diagnostic.Compilation))\n        returnNoneCont\n      case _ => returnNoneCont\n\n    node match // Left if mod cons call found, Right if none was found -- we return the next nodes to be scanned \n      case Result(res) =>\n        (calledDefn, letCallNode, letCtorNode) match\n          case (Some(defn), Some(letCallNode), Some(letCtorName)) =>\n            getRetName(containingCtors, res) match\n              case None => returnNone\n              case Some(value) => Left(updateMapSimple(ModConsCallInfo(src, start, defn, letCallNode, letCtorName, value, node)))\n          case _ => returnNone\n      case Jump(jp, args) => \n        // different cases\n        (calledDefn, letCallNode, letCtorNode) match\n          case (Some(defn), Some(letCallNode), Some(letCtorName)) =>\n            getRetName(containingCtors, args) match\n              case Some(value) if isIdentityJp(jp.expectDefn) => \n                Left(updateMapSimple(ModConsCallInfo(src, start, defn, letCallNode, letCtorName, value, node)))\n              case _ => returnNone\n          case _ => returnNone\n        \n      case Case(scrut, cases, default) => Right(cases.map(_._2) ++ default.toList)\n      case x @ LetExpr(name, expr, body) =>\n        expr match\n          // Check if this let binding references the mod cons call.\n          case Expr.Ref(name) => \n            letCallNode match\n              case None => \n                shadowAndCont(body, name) // OK\n              case Some(LetCall(names, _, _, isTailRec, _)) =>\n                // for it to be mod cons, other values cannot use the return value from the call.\n                if names.contains(name) then\n                  // if the is marked as tail recursive, we must use that call as the mod cons call, so error. otherwise,\n                  // invalidate the discovered call and continue\n                  invalidateAndCont(body)\n                else\n                  shadowAndCont(body, name) // OK\n          \n          case Expr.Literal(lit) => shadowAndCont(body, name) // OK\n          case y @ Expr.CtorApp(clsInfo, ctorArgs) =>\n            // if expr is a constructor with a call to some function as a parameter\n            letCallNode match\n              case None => shadowAndCont(body, name) // OK\n              case Some(LetCall(letCallNames, _, _, isTailRec, _)) => // there was a previous call\n                // 1. Check if the ctor application contains this call\n                val argNames = ctorArgs.collect { case Expr.Ref(name) => name }.toSet\n                val namesSet = letCallNames.toSet\n                val inters = argNames.intersect(namesSet)\n\n                if inters.isEmpty then\n                  // OK, this constructor does not use the mod cons call\n                  // Now check if the constructor uses any previous ctor containing the call.\n                  // If it does, then add this name to the list of constructors containing the call\n                  val inters = containingCtors.intersect(argNames)\n                  \n                  if inters.isEmpty then\n                    shadowAndCont(body, name) // does not use, OK to ignore this one\n                  else \n                    // add this name to the list of constructors containing the call\n                    searchOptCalls(body)(using acc, src, scc, start, calledDefn, letCallNode, letCtorNode, containingCtors + name) \n                else\n                  // it does use it, further analyse\n                  letCtorNode match\n                    case None => \n                      // First constructor discovered using this call as a parameter.\n                      // This is OK. Add this discovered information\n                      \n                      // TODO: for now, assume functions return only one value. handling multiple\n                      // values is a bit more complicated\n                      val ctorArgName = inters.head\n                      val ctorArgIndex = ctorArgs.indexWhere { \n                        case Expr.Ref(nme) => nme == ctorArgName\n                        case _ => false \n                      }\n\n                      val fieldName = clsInfo.expectClass.fields(ctorArgIndex)\n                      \n                      // populate required values\n                      searchOptCalls(body)(using acc, src, scc, start, calledDefn, letCallNode, Some(LetCtorNodeInfo(x, y, clsInfo.expectClass, name, fieldName, ctorArgIndex)), Set(name))\n                    case Some(_) =>\n                      // another constructor is already using the call. Not OK\n\n                      // if the is marked as tail recursive, we must use that call as the mod cons call, so error. otherwise,\n                      // invalidate the discovered call and continue\n                      invalidateAndCont(body)\n\n          case Expr.Select(name, cls, field) =>\n            letCallNode match\n              case None => shadowAndCont(body, name) // OK\n              case Some(LetCall(names, _, _, isTailRec, _)) =>\n                // for it to be mod cons, other values cannot use the return value from the call.\n                if names.contains(name) then\n                  // if the is marked as tail recursive, we must use that call as the mod cons call, so error. otherwise,\n                  // invalidate the discovered call and continue\n                  invalidateAndCont(body)\n                else\n                  shadowAndCont(body, name) // OK\n          case Expr.BasicOp(_, args) =>\n            letCallNode match\n              case None => shadowAndCont(body, name) // OK\n              case Some(LetCall(names, _, _, isTailRec, _)) =>\n                // for it to be mod cons, other values cannot use the return value from the call.\n                val argNames = args.collect { case Expr.Ref(name) => name }.toSet\n                val namesSet = names.toSet\n                val inters = argNames.intersect(namesSet)\n\n                if inters.isEmpty then\n                  shadowAndCont(body, name) // OK\n                else\n                  // if the is marked as tail recursive, we must use that call as the mod cons call, so error. otherwise,\n                  // invalidate the discovered call and continue\n                  invalidateAndCont(body)\n          case Expr.AssignField(assignee, clsInfo, assignmentFieldName, value) =>\n            // make sure `value` is not the mod cons call\n            letCallNode match\n              case None => searchOptCalls(body) // OK\n              case Some(LetCall(names, defn, args, isTailRec, _)) =>\n                value match\n                  case Expr.Ref(name) =>\n                    invalidateAndCont(body)\n                  case _ =>\n                    letCtorNode match\n                      case None => searchOptCalls(body) // OK\n                      case Some(LetCtorNodeInfo(_, ctor, _, name, fieldName, _)) =>\n                        // If this assignment overwrites the mod cons value, forget it\n                        if containingCtors.contains(assignee) then invalidateAndCont(body)\n                        else searchOptCalls(body)\n      case LetMethodCall(names, cls, method, args, body) =>\n        // method call is unresolved, just ignore it\n        // `containingCtors -- names.toSet` takes care of variable shadowing\n        searchOptCalls(body)(using acc, src, scc, start, calledDefn, letCallNode, letCtorNode, containingCtors -- names.toSet)\n      case x @ LetCall(names, defn, args, isTailRec, body) =>\n        val callInScc = scc.contains(defn.expectDefn)\n        \n        // Only deal with calls in the scc\n        if callInScc && isTailCall(x) then\n          // If there is an old call marked as @tailcall, it cannot be a tail call, error\n\n          val updatedMap = letCallNode match\n            case Some(y) =>\n              // If both these calls are marked @tailrec, error\n              if y.isTailRec && x.isTailRec then\n                raise(ErrorReport(\n                  List(\n                    msg\"multiple calls in the same branch marked with @tailcall\" -> None,\n                    msg\"first call\" -> y.loc,\n                    msg\"second call\" -> x.loc,\n                  ),\n                  true,\n                  Diagnostic.Compilation\n                  )\n                )\n              if y.isTailRec then\n                raise(ErrorReport(List(msg\"not a tail call\" -> y.loc), true, Diagnostic.Compilation)) \n\n              updateMapSimple(NormalCallInfo(src, y.defn.expectDefn)(y.loc))\n\n            case None => acc\n            \n          Left(updatedMap + TailCallInfo(src, defn.expectDefn))\n        else\n          val restIsPure = isPure(body)\n          letCallNode match\n            case None => // OK, we may use this LetCall as the mod cons\n              // For now, only optimize functions which return one value\n              if callInScc && defn.expectDefn.resultNum == 1 && restIsPure then\n                searchOptCalls(body)(using acc, src, scc, start, Some(defn.expectDefn), Some(x), None, Set())\n              else\n                if isTailRec then\n                  if !restIsPure then\n                    raise(ErrorReport(List(msg\"not a tail call, as the remaining functions may be impure\" -> x.loc), true, Diagnostic.Compilation))\n                  else\n                    raise(ErrorReport(List(msg\"not a tail call\" -> x.loc), true, Diagnostic.Compilation)) \n                  \n                // Treat this as a normal call\n                val newMap = updateMapSimple(NormalCallInfo(src, defn.expectDefn)(x.loc))\n                searchOptCalls(body)(using newMap, src, scc, start, calledDefn, letCallNode, letCtorNode, containingCtors)\n            case Some(y: LetCall) =>\n              val LetCall(namesOld, defnOld, argsOld, isTailRecOld, bodyOld) = y\n              if isTailRecOld then\n                // 1. If both the old and newly discovered call are marked with tailrec, error\n                if isTailRec then \n                  raise(ErrorReport(\n                    List(\n                      msg\"multiple calls in the same branch marked with @tailcall\" -> None,\n                      msg\"first call\" -> y.loc,\n                      msg\"second call\" -> x.loc,\n                    ),\n                    true,\n                    Diagnostic.Compilation\n                    )\n                  )\n                // 2. old call is marked as tailrec so we must continue using it as the mod cons call.\n                // make sure the newly discovered call does not use the current call as a parameter\n                val argNames = args.collect { case Expr.Ref(name) => name }.toSet\n                val namesSet = namesOld.toSet\n                val inters = argNames.intersect(namesSet)\n\n                if !inters.isEmpty then\n                  raise(ErrorReport(List(msg\"not a tail call\" -> y.loc), true, Diagnostic.Compilation)) \n                // Treat new call as a normal call\n                val newMap = updateMapSimple(NormalCallInfo(src, defn.expectDefn)(x.loc))\n                searchOptCalls(body)(using newMap, src, scc, start, calledDefn, letCallNode, letCtorNode, containingCtors) // OK\n              else\n                // only include mod cons calls that have one return value\n                if callInScc && defn.expectDefn.resultNum == 1 && restIsPure then \n                  // old call is not tailrec, so we can override it however we want\n                  // we take a lucky guess and mark this as the mod cons call, but the\n                  // user really should mark which calls should be tailrec\n                    \n                  // Treat the old call as a normal call\n                  val newMap = updateMapSimple(NormalCallInfo(src, defnOld.expectDefn)(y.loc))\n                  searchOptCalls(body)(using newMap, src, scc, start, Some(defn.expectDefn), Some(x), None, Set())\n                else\n                  if isTailRec then\n                    if !restIsPure then\n                      raise(ErrorReport(List(msg\"not a tail call, as the remaining functions may be impure\" -> x.loc), true, Diagnostic.Compilation))\n                    else\n                      raise(ErrorReport(List(msg\"not a tail call\" -> x.loc), true, Diagnostic.Compilation)) \n                  // shadow all the variables in this letcall\n                  \n                  // Treat this as a normal call\n                  val newMap = updateMapSimple(NormalCallInfo(src, defn.expectDefn)(x.loc))\n                  searchOptCalls(body)(using newMap, src, scc, start, calledDefn, letCallNode, letCtorNode, containingCtors -- names)\n\n  // checks whether a list of names is equal to a list of trivial expressions referencing those names\n  private def argsListEqual(names: List[Name], exprs: List[TrivialExpr]) =\n    if names.length == exprs.length then\n      val results = exprs.collect { case Expr.Ref(name) => name }\n      names == results\n    else\n      false\n\n  private def isIdentityJp(d: Defn): Bool = d.body match\n    case Result(res) => argsListEqual(d.params, res)\n    case Jump(defn, args) => argsListEqual(d.params, args) && isIdentityJp(defn.expectDefn)\n    case _ => false\n\n  private def isTailCall(node: Node): Boolean = node match\n    case LetCall(names, defn, args, _, body) =>\n      body match\n        case Result(res)      => argsListEqual(names, res)\n        case Jump(defn, args) => argsListEqual(names, args) && isIdentityJp(defn.expectDefn)\n        case _                => false\n    case _ => false\n\n  private def discoverOptCallsNode(node: Node)(implicit src: Defn, scc: Set[Defn], acc: Set[CallInfo]): Set[CallInfo] = \n    searchOptCalls(node)(using acc, src, scc, node, None, None, None, Set()) match\n      case Left(acc) => acc\n      case Right(nodes) => nodes.foldLeft(acc)((acc, node) => discoverOptCallsNode(node)(using src, scc, acc))\n\n  private def discoverOptCalls(defn: Defn, jps: Set[Defn])(implicit scc: Set[Defn], acc: Set[CallInfo]): Set[CallInfo] =\n    val combined = jps + defn\n    combined.foldLeft(acc)((acc, defn_) => discoverOptCallsNode(defn_.body)(using defn, scc, acc))\n\n  private def searchCalls(node: Node)(implicit src: Defn, acc: Map[Int, Set[Defn]]): Map[Int, Set[Defn]] =\n    node match\n      case Result(res) => acc\n      case Jump(defn, args) => acc\n      case Case(scrut, cases, default) => cases.foldLeft(default.fold(acc)(x => searchCalls(x)(using src, acc)))((acc, item) => searchCalls(item._2)(using src, acc))\n      case LetExpr(name, expr, body) => searchCalls(body)\n      case LetMethodCall(names, cls, method, args, body) => searchCalls(body)\n      case LetCall(names, defn, args, isTailRec, body) => \n        val newSet = acc.get(src.id) match\n          case None => Set(defn.expectDefn)\n          case Some(defns) => defns + defn.expectDefn\n        searchCalls(body)(using src, acc + (src.id -> newSet))\n    \n\n  private def discoverCalls(defn: Defn, jps: Set[Defn])(implicit acc: Map[Int, Set[Defn]]): Map[Int, Set[Defn]] =\n    val combined = jps + defn\n    combined.foldLeft(acc)((acc, defn_) => searchCalls(defn_.body)(using defn, acc))\n  \n  // Partions a tail recursive call graph into strongly connected components\n  // Refernece: https://en.wikipedia.org/wiki/Strongly_connected_component\n\n  // Implements Tarjan's algorithm.\n  // Wikipedia: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm\n  // Implementation Reference: https://www.baeldung.com/cs/scc-tarjans-algorithm\n\n  private class DefnNode(val defn: Defn):\n    override def hashCode(): Int = defn.hashCode\n\n    var num: Int = Int.MaxValue\n    var lowest: Int = Int.MaxValue\n    var visited: Boolean = false\n    var processed: Boolean = false\n\n  private def partitionNodes(implicit nodeMap: Map[Int, DefnNode]): List[DefnGraph] =\n    val defns = nodeMap.values.toSet\n    val inital = Map[Int, Set[Defn]]()\n    val joinPoints = defns.map(d => (d.defn.id -> discoverJoinPoints(d.defn.body, Set()))).toMap\n    val allJoinPoints = joinPoints.values.flatMap(x => x).toSet\n    val edges = defns.foldLeft(inital)((acc, defn) => discoverCalls(defn.defn, joinPoints(defn.defn.id))(using acc)).withDefaultValue(Set())\n\n    var ctr = 0\n    // nodes, edges\n    var stack: List[DefnNode] = Nil\n    var sccs: List[DefnGraph] = Nil\n\n    def dfs(src: DefnNode): Unit =\n      src.num = ctr\n      src.lowest = ctr\n      ctr += 1\n      src.visited = true\n      \n      val tailCalls = edges(src.defn.id)\n      stack = src :: stack\n      for u <- tailCalls do\n        val neighbour = nodeMap(u.id)\n        if (neighbour.visited) then\n          if (!neighbour.processed)\n            src.lowest = neighbour.num.min(src.lowest)\n        else\n          dfs(neighbour)\n          src.lowest = neighbour.lowest.min(src.lowest)\n      \n\n      src.processed = true\n\n      if (src.num == src.lowest) then\n        var scc: Set[DefnNode] = Set()\n\n        def pop(): DefnNode =\n          val ret = stack.head\n          stack = stack.tail\n          ret\n        \n\n        var vertex = pop()\n\n        while (vertex != src) {\n          scc = scc + vertex\n          \n          val next = pop()\n          vertex = next\n        }\n\n        scc = scc + vertex\n\n        val sccIds = scc.map { d => d.defn.id }\n\n        val sccJoinPoints = scc.foldLeft(Set[Defn]())((jps, defn) => joinPoints(defn.defn.id))\n\n        val sccDefns = scc.map(d => d.defn)\n\n        val categorizedEdges = scc\n          .foldLeft(Set[CallInfo]())(\n            (calls, defn) => discoverOptCalls(defn.defn, joinPoints(defn.defn.id))(using sccDefns, calls)\n          )\n          .filter(c => sccDefns.contains(c.getDefn))\n\n        sccs = DefnGraph(scc, categorizedEdges, sccJoinPoints) :: sccs\n      \n    for v <- defns do\n      if !allJoinPoints.contains(v.defn) && !v.visited then\n        dfs(v)\n\n    sccs\n  \n\n  private case class DefnInfo(defn: Defn, stackFrameIdx: Int)\n\n  def asLit(x: Int) = Expr.Literal(IntLit(x))\n\n  private def makeSwitch(scrutName: Name, cases: List[(Int, Node)], default: Node)(implicit trueClass: ClassInfo, falseClass: ClassInfo): Node =\n    // given expressions value, e1, e2, transform it into\n    // let scrut = tailrecBranch == value\n    // in case scrut of True  -> e1\n    //                  False -> e2\n    def makeCaseBranch(value: Int, e1: Node, e2: Node): Node =\n      val name = Name(\"scrut\")\n      val cases = Case(name, List((Pat.Class(ClassRef(L(trueClass))), e1), (Pat.Class(ClassRef(L(falseClass))), e2)), None).attachTag(tag)\n      LetExpr(\n        name,\n        Expr.BasicOp(\"==\", List(asLit(value), Expr.Ref(scrutName))),\n        cases\n      ).attachTag(tag)\n      \n    cases.foldLeft(default)((elz, item) => \n      val cmpValue = item._1\n      val nodeIfTrue = item._2\n      makeCaseBranch(cmpValue, nodeIfTrue, elz)\n    )\n  \n  // TAIL RECURSION MOD CONS\n  // Uses the ideas in section 2.2 of the paper `Tail Recursion Modulo Context` \n  // by Leijen and Lorenzen: https://dl.acm.org/doi/abs/10.1145/3571233\n  // of whom attribute the method to Risch, Friedman, Wise, Minamide.\n\n  final val ID_CONTEXT_NAME = \"_IdContext\"\n  final val CONTEXT_NAME = \"_Context\"\n\n  // `ctx` class for tailrec mod cons.\n  // The paper uses two values `res: T` and `hole: ptr<T>` to represent the context. \n  // We represent the context as three values instead of two to avoid needing pointers:\n  //\n  // acc:       The accumulated value. This is the same as `res`  in the paper. If the functions f1, ..., fn\n  //            in the compoennt return type T1, ..., Tn, then acc has type T1 | ... | Tn. \n  //\n  // The following together represent `hole` in the paper:\n  // ptr:       Represents the object containing the \"hole\" to be written to.\n  // field:     Integer representing which class and field the \"hole\" belongs to. Which class and field this\n  //            represents is different for each strongly connected component.\n  //\n  // The idea to use `ptr` and `field` to represent a pointer is by @LPTK.\n  final val ID_CTX_CLASS = ClassInfo(classUid.make, ID_CONTEXT_NAME, Nil)\n  final val CTX_CLASS = ClassInfo(classUid.make, CONTEXT_NAME, List(\"acc\", \"ptr\", \"field\"))\n  final val ID_CTX_CLASS_REF = ClassRef(L(ID_CTX_CLASS))\n  final val CTX_CLASS_REF = ClassRef(L(CTX_CLASS))\n  \n  // Given a strongly connected component `defns` of mutually\n  // tail recursive functions, returns a strongly connected component contaning the\n  // optimized functions and their associated join points, and also\n  // new function definitions not in this component, such as the\n  // original functions pointing to an optimized function and the context\n  // composition and application functions.\n  private def optimizeModCons(component: ScComponent, classes: Set[ClassInfo]): (ScComponent, Set[Defn]) = \n    val modConsCalls = component.edges.collect { case x: ModConsCallInfo => x }\n    val defns = component.nodes\n    val defnsIdSet = defns.map(_.id).toSet\n\n    // no mod cons, just return the original\n    if modConsCalls.isEmpty then\n      (component, Set())\n    else\n      val trueClass = classes.find(c => c.name == \"True\").get\n      val falseClass = classes.find(c => c.name == \"False\").get\n      \n      // CONTEXT APPLICATION\n      \n      val mergedNames = defns.foldLeft(\"\")(_ + \"_\" + _.name)\n      \n      val ctxAppId = fnUid.make\n      val ctxAppName = mergedNames + \"_ctx_app$\" + ctxAppId\n      val ctxCompId = fnUid.make\n      val ctxCompName = mergedNames + \"_ctx_comp$\" + ctxCompId\n      \n      // map integers to classes and fields which will be assigned to\n      val classIdMap = classes.map(c => c.id -> c).toMap\n      val possibleAssigns = modConsCalls.map(call => (call.letCtorNode.cls.id, call.letCtorNode.fieldName)).toSet\n      val possibleAssignsIdxes = possibleAssigns.toList.zipWithIndex\n\n      val assignToIdx = possibleAssignsIdxes.map((item, idx) => item -> idx).toMap\n\n      // fun app(ctx, x: T): T\n      val appCtxName = Name(\"ctx\")\n      val appValName = Name(\"x\")\n\n      val assignmentCases = possibleAssignsIdxes.map((item, idx) =>\n        val clsId = item._1\n        val fieldName = item._2\n        val cls = classIdMap(clsId)\n        \n        // let ptr = ctx.ptr in\n        // ptr.<fieldName> = x in\n        // let acc = ctx.acc\n        // acc\n        val node = LetExpr(\n          Name(\"ptr\"), \n          Expr.Select(appCtxName, CTX_CLASS_REF, \"ptr\"),\n          LetExpr(\n            Name(\"_\"), \n            Expr.AssignField(\n              Name(\"ptr\"), \n              ClassRef(L(cls)), \n              fieldName, \n              Expr.Ref(appValName)\n            ),\n            LetExpr(\n              Name(\"acc\"), \n              Expr.Select(appCtxName, CTX_CLASS_REF, \"acc\"), // this could be a join point but it's not that bad\n              Result(\n                List(Expr.Ref(Name(\"acc\")))\n              ).attachTag(tag)\n            ).attachTag(tag)\n          ).attachTag(tag)\n        ).attachTag(tag)\n\n        (idx, node)\n      )\n      \n      \n      val ctxBranch = LetExpr(\n        Name(\"field\"), Expr.Select(appCtxName, CTX_CLASS_REF, \"field\"),\n        makeSwitch(Name(\"field\"), assignmentCases.tail, assignmentCases.head._2)(using trueClass, falseClass)\n      ).attachTag(tag)\n      \n      val idBranch = Result(List(Expr.Ref(appValName))).attachTag(tag)\n\n      val appNode = Case(appCtxName,\n        List(\n          (Pat.Class(ID_CTX_CLASS_REF), idBranch),\n          (Pat.Class(CTX_CLASS_REF), ctxBranch)\n        ),\n        None\n      ).attachTag(tag)\n\n      val appDefn = Defn(ctxAppId, ctxAppName, List(appCtxName, appValName), 1, appNode, false)\n\n      // CONTEXT COMPOSITION\n      val cmpCtx1Name = Name(\"ctx1\")\n      val cmpCtx2Name = Name(\"ctx2\")\n\n      // Note that ctx2 may never be an identity context. If we ever want to compose ctx1 and ctx2\n      // where ctx2 is the identity, just use ctx1 directly.\n      \n      // Ctx(app(ctx1, ctx2), ctx2.ptr, ctx2.field) ->\n      // let ctx2acc = ctx2.acc in\n      // let ctx2ptr = ctx2.ptr in\n      // let ctx2field = ctx2.field in\n      // let newAcc = app(ctx1, ctx2acc) in\n      // let ret = Ctx(newAcc, ctx2ptr, ctx2field) in\n      // ret\n      val cmpNode = LetExpr(\n        Name(\"ctx2acc\"), \n        Expr.Select(cmpCtx2Name, CTX_CLASS_REF, \"acc\"),\n        LetExpr(\n          Name(\"ctx2ptr\"), \n          Expr.Select(cmpCtx2Name, CTX_CLASS_REF, \"ptr\"),\n          LetExpr(\n            Name(\"ctx2field\"), \n            Expr.Select(cmpCtx2Name, CTX_CLASS_REF, \"field\"),\n            LetCall(\n              List(Name(\"newAcc\")), \n              DefnRef(Left(appDefn)), List(Expr.Ref(cmpCtx1Name), Expr.Ref(Name(\"ctx2acc\"))),\n              false,\n              LetExpr(\n                Name(\"ret\"), \n                Expr.CtorApp(CTX_CLASS_REF, List(\"newAcc\", \"ctx2ptr\", \"ctx2field\").map(n => Expr.Ref(Name(n)))),\n                Result(\n                  List(Expr.Ref(Name(\"ret\")))\n                ).attachTag(tag)\n              ).attachTag(tag),\n            )().attachTag(tag)\n          ).attachTag(tag)\n        ).attachTag(tag)\n      ).attachTag(tag)\n\n      val cmpDefn = Defn(ctxCompId, ctxCompName, List(cmpCtx1Name, cmpCtx2Name), 1, cmpNode, false)\n\n      // We use tags to identify nodes\n      // a bit hacky but it's the most elegant way\n      // First, build a map of all branches that contain a mod cons call\n      val modConsBranches = modConsCalls.toList.map(call => (call.startNode.tag.inner -> call)).toMap\n\n      val modConsRefs = defns.map(d => d.id -> DefnRef(Right(d.name + \"_modcons\"))).toMap\n      val jpRefs = component.joinPoints.map(jp => jp.id -> DefnRef(Right(jp.name + \"_modcons\"))).toMap\n\n      def makeRet(ret: TrivialExpr): Node =\n        LetCall(\n          List(Name(\"res\")),\n          DefnRef(Left(appDefn)),\n          List(Expr.Ref(Name(\"ctx\")), ret),\n          false,\n          Result(List(Expr.Ref(Name(\"res\")))).attachTag(tag)\n        )().attachTag(tag)\n      \n      // Here, we assume we are inside the modcons version of the function and hence have an extra\n      // `ctx` parameter at the start.\n      def transformNode(node: Node): Node = \n        modConsBranches.get(node.tag.inner) match\n          case Some(call) => transformModConsBranch(node)(using call)\n          case None => node match\n            case Result(res) => \n              makeRet(res.head)\n            case Jump(defn, args) => \n              if isIdentityJp(defn.expectDefn) then makeRet(args.head) \n              else jpRefs.get(defn.expectDefn.id) match\n                case None => throw IRError(\"could not find jump point with id\" + defn.expectDefn.id)\n                case Some(value) => Jump(value, Expr.Ref(Name(\"ctx\")) :: args)\n              \n            case Case(scrut, cases, default) => Case(scrut, cases.map { (cls, body) => (cls, transformNode(body)) }, default.map(transformNode)).attachTag(tag)\n            case LetExpr(name, expr, body) => LetExpr(name, expr, transformNode(body)).attachTag(tag)\n            case LetMethodCall(names, cls, method, args, body) => LetMethodCall(names, cls, method, args, transformNode(body)).attachTag(tag)\n            case LetCall(names, defn, args, isTailRec, body) =>\n              // Handle the case when we see a tail call.\n              // This case is not handled by the paper. The way to transform this is: \n              // let res = foo(*args) in res\n              // --> let res = foo_modcons(ctx, *args) in res\n              if isTailCall(node) && defnsIdSet.contains(defn.expectDefn.id) then\n                // Transform it into a tail recursive call where we pass on the current context\n                LetCall(\n                  List(Name(\"res\")), \n                  modConsRefs(defn.expectDefn.id), Expr.Ref(Name(\"ctx\")) :: args, \n                  isTailRec,\n                  Result(List(Expr.Ref(Name(\"res\")))).attachTag(tag)\n                )().attachTag(tag)\n              else \n                LetCall(names, defn, args, isTailRec, transformNode(body))().attachTag(tag)\n\n      def transformModConsBranch(node: Node)(implicit call: ModConsCallInfo): Node = \n        def makeCall =\n          val field = assignToIdx((call.letCtorNode.cls.id, call.letCtorNode.fieldName))\n          \n          // let composed = comp(ctx, Ctx(retVal, ptr, field)) in\n          // f(composed, *args)\n          LetExpr(\n            Name(\"ctx2\"),\n            Expr.CtorApp(CTX_CLASS_REF, List(Expr.Ref(call.retName), Expr.Ref(call.letCtorNode.ctorValName), asLit(field))),\n            LetCall(\n              List(Name(\"composed\")),\n              DefnRef(Left(cmpDefn)),\n              List(\"ctx\", \"ctx2\").map(n => Expr.Ref(Name(n))),\n              false,\n              LetCall(\n                List(Name(\"res\")), \n                modConsRefs(call.defn.id),\n                Expr.Ref(Name(\"composed\")) :: call.letCallNode.args,\n                false,\n                Result(\n                  List(Expr.Ref(Name(\"res\")))\n                ).attachTag(tag)\n              )().attachTag(tag)\n            )().attachTag(tag)\n          ).attachTag(tag)\n\n        node match\n          case Result(res) if node.tag.inner == call.retNode.tag.inner =>\n            makeCall\n          case Jump(defn, args) if node.tag.inner == call.retNode.tag.inner =>\n            makeCall\n          case LetExpr(name, expr, body) => \n            if node.tag.inner == call.letCtorNode.node.tag.inner then\n              // rewrite the ctor, but set the field containing the call as to 0\n              val idx = call.letCtorNode.idx\n              val argsList = call.letCtorNode.ctor.args.updated(idx, asLit(0))\n              LetExpr(name, Expr.CtorApp(ClassRef(L(call.letCtorNode.cls)), argsList), transformModConsBranch(body)).attachTag(tag)\n            else\n              LetExpr(name, expr, transformModConsBranch(body)).attachTag(tag)\n          case LetCall(names, defn, args, isTailRec, body) =>\n            if node.tag.inner == call.letCallNode.tag.inner then\n              // discard it\n              transformModConsBranch(body)\n            else\n              LetCall(names, defn, args, isTailRec, transformModConsBranch(body))().attachTag(tag)\n          case _ => throw IRError(\"unreachable case when transforming mod cons call\")\n\n      def rewriteDefn(d: Defn): Defn =\n        val transformed = transformNode(d.body)\n        val id = fnUid.make\n        Defn(id, d.name + \"_modcons$\" + id, Name(\"ctx\") :: d.params, d.resultNum, transformed, d.isTailRec)\n      \n      // returns (new defn, mod cons defn)\n      // where new defn has the same signature and ids as the original, but immediately calls the mod cons defn\n      // and mod cons defn is the rewritten definition\n      def replaceDefn(d: Defn): (Defn, Defn) =\n        val modConsDefn = rewriteDefn(d)\n        val modConsCall = \n          LetExpr(\n            Name(\"idCtx\"),\n            Expr.CtorApp(ID_CTX_CLASS_REF, Nil),\n              LetCall(\n              List(Name(\"res\")), \n              DefnRef(Left(modConsDefn)),\n              Expr.Ref(Name(\"idCtx\")) :: d.params.map(Expr.Ref(_)),\n              false,\n              Result(List(Expr.Ref(Name(\"res\")))).attachTag(tag)\n            )().attachTag(tag)\n          ).attachTag(tag)\n        val newDefn = Defn(d.id, d.name, d.params, d.resultNum, modConsCall, false)\n        (newDefn, modConsDefn)\n\n      val jpsTransformed = component.joinPoints.map(d => d.id -> rewriteDefn(d)).toMap\n      val defnsTransformed = component.nodes.map(d => d.id -> replaceDefn(d)).toMap\n\n      // update defn refs\n      for (id, ref) <- jpRefs do\n        ref.defn = Left(jpsTransformed(id))\n      \n      for (id, ref) <- modConsRefs do\n        ref.defn = Left(defnsTransformed(id)._2) // set it to the mod cons defn, not the one with the original signature\n\n      val jps = jpsTransformed.values.toSet\n      val modConsDefs = defnsTransformed.values.map((a, b) => b).toSet \n      val normalDefs = defnsTransformed.values.map((a, b) => a).toSet + appDefn + cmpDefn\n\n      // the edges are not used later, but still, rewrite them for correctness\n      val newEdges = component.edges.map { c =>\n        val src = c.getSrc\n        val defn = c.getDefn\n        TailCallInfo(defnsTransformed(src.id)._2, defnsTransformed(defn.id)._2) \n      }\n\n      (ScComponent(modConsDefs, newEdges, jps), normalDefs)\n\n  // Given a strongly connected component `defns` of mutually\n  // tail recursive functions, returns a set containing the optimized function and the\n  // original functions pointing to an optimized function.\n  // Explicitly returns the merged function in case tailrec needs to be checked.\n  private def optimizeTailRec(component: ScComponent, classes: Set[ClassInfo]): (Set[Defn], Defn) = \n    // To build the case block, we need to compare integers and check if the result is \"True\"\n    val trueClass = classes.find(c => c.name == \"True\").get\n    val falseClass = classes.find(c => c.name == \"False\").get\n    // undefined for dummy values\n    val dummyVal = Expr.Literal(UnitLit(true))\n    \n    // join points need to be rewritten. For now, just combine them into the rest of the function. They will be inlined anyways\n    val defns = component.nodes ++ component.joinPoints\n    val defnsNoJp = component.nodes\n    val edges = component.edges\n\n    // dummy case, should not happen\n    if (defns.size == 0)\n      throw IRError(\"strongly connected component was empty\")\n\n    // for single tail recursive functions, just move the body into a join point\n    if (defns.size <= 1)\n      val defn = defns.head\n      \n      // if the function does not even tail call itself, just return\n      if filterOptCalls(edges).size == 0 then\n        return (defns, defns.head)\n      \n      val jpName = defn.name + \"_jp\"\n      val jpDefnRef = DefnRef(Right(jpName))\n      \n      def transformNode(node: Node): Node = node match\n        case Result(res) => node.attachTag(tag)\n        case Jump(defn, args) => node.attachTag(tag)\n        case Case(scrut, cases, default) => Case(scrut, cases.map((cls, body) => (cls, transformNode(body))), default.map(transformNode)).attachTag(tag)\n        case LetExpr(name, expr, body) => LetExpr(name, expr, transformNode(body)).attachTag(tag)\n        case LetMethodCall(names, cls, method, args, body) => LetMethodCall(names, cls, method, args, transformNode(body)).attachTag(tag)\n        case LetCall(names, defn_, args, isTailRec, body) =>\n          if isTailCall(node) && defn_.expectDefn.id == defn.id then\n            Jump(jpDefnRef, args).attachTag(tag)\n          else\n            LetCall(names, defn_, args, isTailRec, transformNode(body))().attachTag(tag)\n      \n      val jpDef = Defn(fnUid.make, jpName, defn.params, defn.resultNum, transformNode(defn.body), false)\n      \n      val rets = (0 until defn.resultNum).map(n => Name(\"r\" + n.toString)).toList\n      val callJpNode = LetCall(\n        rets, \n        DefnRef(Left(jpDef)),\n        defn.params.map(Expr.Ref(_)),\n        false,\n        Result(rets.map(Expr.Ref(_))).attachTag(tag),\n      )().attachTag(tag)\n      \n      val newDefn = Defn(fnUid.make, defn.name, defn.params, defn.resultNum, callJpNode, true)\n      (Set(newDefn, jpDef), newDefn)\n\n    else\n      // Note that we do not use the actual edges in ScCompoennt here.\n      // We assume the only things we can optimize are tail calls, which\n      // are cheap to identify, and nothing else.\n\n      // concretely order the functions as soon as possible, since the order of the functions matter\n      val defnsList = defns.toList\n\n      // assume all defns have the same number of results\n      // in fact, they should theoretically have the same return type if the program type checked\n      val resultNum = defnsList.head.resultNum\n\n      val trName = Name(\"tailrecBranch$\");\n\n      // To be used to replace variable names inside a definition to avoid variable name clashes\n      val nameMaps: Map[Int, Map[Name, Name]] = defnsList.map(defn => defn.id -> defn.params.map(n => n -> Name(defn.name + \"_\" + n.str)).toMap).toMap\n\n      val stackFrameIdxes = defnsList.foldLeft(1 :: Nil)((ls, defn) => defn.params.size + ls.head :: ls).drop(1).reverse\n\n      val defnInfoMap: Map[Int, DefnInfo] = (defnsList zip stackFrameIdxes)\n        .foldLeft(Map.empty)((map, item) => map + (item._1.id -> DefnInfo(item._1, item._2)))\n\n      val stackFrame = trName :: defnsList.flatMap(d => d.params.map(n => nameMaps(d.id)(n))) // take union of stack frames\n\n      val newId = fnUid.make\n      val newName = defns.foldLeft(\"\")(_ + \"_\" + _.name) + \"_opt$\" + newId\n      val jpId = fnUid.make\n      val jpName = defns.foldLeft(\"\")(_ + \"_\" + _.name) + \"_opt_jp$\" + jpId\n\n      val newDefnRef = DefnRef(Right(newName))\n      val jpDefnRef = DefnRef(Right(jpName))\n\n      def transformStackFrame(args: List[TrivialExpr], info: DefnInfo) =\n        val start = stackFrame.take(info.stackFrameIdx).drop(1).map { Expr.Ref(_) } // we drop tailrecBranch and replace it with the defn id\n        val end = stackFrame.drop(info.stackFrameIdx + args.size).map { Expr.Ref(_) }\n        asLit(info.defn.id) :: start ::: args ::: end\n\n      // Build the node which will be contained inside the jump point.\n      def transformNode(node: Node): Node = node match\n        case Jump(defn, args)          =>\n          if defnInfoMap.contains(defn.expectDefn.id) then\n            Jump(jpDefnRef, transformStackFrame(args, defnInfoMap(defn.expectDefn.id))).attachTag(tag)\n          else\n            node.attachTag(tag)\n        case Result(_) => node.attachTag(tag)\n        case Case(scrut, cases, default) => Case(scrut, cases.map(n => (n._1, transformNode(n._2))), default.map(transformNode)).attachTag(tag)\n        case LetExpr(name, expr, body) => LetExpr(name, expr, transformNode(body)).attachTag(tag)\n        case LetMethodCall(names, cls, method, args, body) =>\n          LetMethodCall(names, cls, method, args, transformNode(body)).attachTag(tag)\n        case LetCall(names, defn, args, isTailRec, body) =>\n          if isTailCall(node) && defnInfoMap.contains(defn.expectDefn.id) then\n            Jump(jpDefnRef, transformStackFrame(args, defnInfoMap(defn.expectDefn.id))).attachTag(tag)\n          else LetCall(names, defn, args, isTailRec, transformNode(body))().attachTag(tag)\n\n      // Tail calls to another function in the component will be replaced with a call\n      // to the merged function\n      // i.e. for mutually tailrec functions f(a, b) and g(c, d),\n      // f's body will be replaced with a call f_g(a, b, *, *), where * is a dummy value\n      def transformDefn(defn: Defn): Defn =\n        val info = defnInfoMap(defn.id)\n\n        val start =\n          stackFrame.take(info.stackFrameIdx).drop(1).map { _ => dummyVal } // we drop tailrecBranch and replace it with the defn id\n        val end = stackFrame.drop(info.stackFrameIdx + defn.params.size).map { _ => dummyVal }\n        val args = asLit(info.defn.id) :: start ::: defn.params.map(Expr.Ref(_)) ::: end\n\n        // We use a let call instead of a jump to avoid newDefn from being turned into a join point,\n        // which would cause it to be inlined and result in code duplication.\n        val names = (0 until resultNum).map(i => Name(\"r\" + i.toString())).toList\n        val namesExpr = names.map(Expr.Ref(_))\n        val res = Result(namesExpr).attachTag(tag)\n        val call = LetCall(names, newDefnRef, args, false, res)().attachTag(tag)\n        Defn(defn.id, defn.name, defn.params, defn.resultNum, call, false)\n\n      def getOrKey[T](m: Map[T, T])(key: T): T = m.get(key) match\n        case None        => key\n        case Some(value) => value\n\n      val first = defnsList.head;\n      val firstMap = nameMaps(first.id)\n      val firstBodyRenamed = first.body.mapName(getOrKey(firstMap))\n      val firstNode = transformNode(firstBodyRenamed)\n\n      val valsAndNodes = defnsList.map(defn =>\n        val nmeMap = nameMaps(defn.id)\n        val renamed = defn.body.mapName(getOrKey(nmeMap))\n        val transformed = transformNode(renamed)\n        (defn.id, transformed)\n      )\n\n      val newNode = makeSwitch(trName, valsAndNodes.tail, valsAndNodes.head._2)(using trueClass, falseClass)\n\n      val jpDefn = Defn(jpId, jpName, stackFrame, resultNum, newNode, false)\n\n      val jmp = Jump(jpDefnRef, stackFrame.map(Expr.Ref(_))).attachTag(tag)\n      val newDefn = Defn(newId, newName, stackFrame, resultNum, jmp, defnsNoJp.find { _.isTailRec }.isDefined )\n\n      jpDefnRef.defn = Left(jpDefn)\n      newDefnRef.defn = Left(newDefn)\n\n      (defnsNoJp.map { d => transformDefn(d) } + newDefn + jpDefn, newDefn)\n  \n  private def partition(defns: Set[Defn]): List[ScComponent] = \n    val nodeMap: Map[Int, DefnNode] = defns.foldLeft(Map.empty)((m, d) => m + (d.id -> DefnNode(d)))\n    partitionNodes(using nodeMap).map(_.removeMetadata)\n\n  private def optimizeParition(component: ScComponent, classes: Set[ClassInfo]): Set[Defn] =\n    val trFn = component.nodes.find { _.isTailRec }.headOption\n    val normalCall = filterNormalCalls(component.edges).headOption\n    \n    (trFn, normalCall) match\n      case (Some(fn), Some(call)) => \n        raise(ErrorReport(\n          List(\n            msg\"function `${fn.name}` is not tail-recursive, but is marked as @tailrec\" -> fn.loc,\n            msg\"it could self-recurse through this call, which may not be a tail-call\" -> call.loc\n          ), \n          true, Diagnostic.Compilation)\n        )\n      case _ =>\n\n    val (modConsComp, other) = optimizeModCons(component, classes)\n    val (trOpt, mergedDefn) = optimizeTailRec(modConsComp, classes)\n    other ++ trOpt\n\n  def apply(p: Program) = run(p)\n\n  def run_debug(p: Program): (Program, List[Set[String]]) = \n    val partitions = partition(p.defs)\n\n    val newDefs = partitions.flatMap { optimizeParition(_, p.classes) }.toSet\n    val newClasses = p.classes + ID_CTX_CLASS + CTX_CLASS\n\n    // update the definition refs\n    newDefs.foreach { defn => resolveRef(defn.body, newDefs, newClasses, true) }\n    resolveRef(p.main, newDefs, newClasses, true)\n\n    (Program(newClasses, newDefs, p.main), partitions.map(t => t.nodes.map(f => f.name)))\n\n  def run(p: Program): Program = run_debug(p)._1\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/printer/BlockPrinter.scala",
    "content": "package mlscript.compiler.printer\n\nimport scala.collection.mutable.{ArrayBuffer, Stack, StringBuilder}\n\nclass BlockPrinter:\n  import BlockPrinter.Indentation\n\n  private val indent = Indentation()\n  private val lines = ArrayBuffer[String]()\n  private val currentLine = StringBuilder()\n  private val scopes = Stack[Option[String]]()\n\n  def endLine(): Unit = if currentLine.isEmpty then () else {\n    lines += indent(currentLine.toString)\n    currentLine.clear()\n  }\n\n  def enter(): Unit =\n    endLine()\n    indent.increase()\n    scopes.push(None)\n\n  def enter(begin: String, end: String): Unit =\n    currentLine ++= begin\n    endLine()\n    indent.increase()\n    scopes.push(Some(end))\n\n  def leave(): Unit =\n    endLine() // ↵\n    indent.decrease()\n    scopes.pop().foreach { currentLine ++= _ }\n    endLine() // ↵\n\n  def print(content: String): Unit = currentLine ++= content\n\n  def toLines: List[String] =\n    endLine()\n    lines.toList\n\n  override def toString(): String = lines.mkString(\"\\n\")\n\nobject BlockPrinter:\n  class Indentation(mark: String = \"  \"):\n    private var indent = 0\n    private var spaces = ArrayBuffer[String](\"\")\n    def increase(): Unit =\n      indent += 1\n      spaces += spaces.last + mark\n    def decrease(): Unit = indent -= 1\n    def apply(content: String): String = spaces(indent) + content\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/simpledef/Simpledef.scala",
    "content": "package mlscript\npackage compiler\npackage simpledef\n\nimport mlscript.utils.*, shorthands.*\nimport scala.collection.mutable\nimport java.util.IdentityHashMap\nimport scala.jdk.CollectionConverters.*\n\ntype TypeVar\ntype TermId = Uid[Term]\ntype TypeVarId = Uid[TypeVar]\ntype Cnstr = ProdStrat -> ConsStrat\n\n/** Performs defunctionalization on selections on objects using simple-sub as for control-flow analysis.\n *  First we traverse the program and process all terms, constraining them to Producers and Consumers.\n *  During the constraining, we keep track of the input points of selection terms.\n *  Lastly, we rewrite selection terms by generating pattern matches on their possible inputs.\n */\n\nenum ProdStrat(using val euid: TermId) {\n  case NoProd()(using TermId) \n  case ProdObj(ctor: Option[Var], fields: Ls[Var -> ProdStrat], parents: Ls[ProdStrat] = Nil)(using TermId) extends ProdStrat, ProdObjImpl\n  case ProdFun(lhs: ConsStrat, rhs: ProdStrat)(using TermId) \n  case ProdVar(uid: TypeVarId, name: String)(boundary: Option[Var] = None)(using TermId) \n  case ProdTup(fields: Ls[ProdStrat])(using TermId) \n}\nenum ConsStrat(using val euid: TermId) {\n  case NoCons()(using TermId) \n  case ConsObj(name: Option[Var], fields: Ls[Var -> ConsStrat])(using TermId) extends ConsStrat, ConsObjImpl\n  case ConsFun(lhs: ProdStrat, rhs: ConsStrat)(using TermId) \n  case ConsVar(uid: TypeVarId, name: String)(boundary: Option[Var] = None)(using TermId) \n  case ConsTup(fields: Ls[ConsStrat])(using TermId) \n}\nimport ProdStrat.*, ConsStrat.*\n\ntrait ConsObjImpl { self: ConsObj =>\n  var selectionSource: Set[ProdStrat] = Set()\n}\n\ntrait ProdObjImpl { self: ProdObj =>\n  var objDestination: Set[ConsStrat] = Set()\n}\n\nclass Context(\n  variables: Map[Var, ProdVar],\n  classes: Map[Var, ProdObj],\n) {\n  def apply(v: Var): ProdVar =\n    variables(v)\n  def ++(other: IterableOnce[(Var, ProdVar)]): Context =\n    Context(variables ++ other, classes)\n  def +(other: (Var -> ProdVar)): Context =\n    Context(variables + other, classes)\n  override def toString(): String =\n    s\"${variables}\"\n}\n\nclass SimpleDef(debug: Debug) {\n  \n  extension (t: Term) {\n    def uid = termMap.getOrElse(t, {\n      val id = euid.nextUid\n      termMap.addOne((t, euid.nextUid))\n      id\n    })\n  }\n\n  val termMap = new IdentityHashMap[Term, TermId]().asScala\n  val varsName = mutable.Map.empty[TypeVarId, Str]\n  val vuid = Uid.TypeVar.State()\n  val euid = Uid.Term.State()\n  val noExprId = euid.nextUid\n\n  def freshVar(n: String)(using TermId): (ProdVar, ConsVar) =\n    val vid = vuid.nextUid\n    val pv = ProdVar(vid, n)()\n    val cv = ConsVar(vid, n)()\n    varsName += vid -> n\n    (pv, cv)\n  def freshVar(n: Var)(using TermId): (ProdVar, ConsVar) =\n   freshVar(n.name)\n\n  def apply(p: TypingUnit)(using ctx: Context = Context(Map(), Map())): (Ls[Var -> ProdStrat], ProdStrat) = \n    // Top-level def prototypes\n    val vars: Map[Var, ProdVar] = p.rawEntities.collect { \n      case fun: NuFunDef =>\n        fun.nme -> freshVar(fun.name)(using noExprId)._1\n    }.toMap\n    // Top-level constructor prototypes\n    val constructorPrototypes: Map[Var, Cnstr] = p.rawEntities.collect { \n      case ty: NuTypeDef =>\n        ty.nameVar -> freshVar(ty.nameVar)(using noExprId)\n    }.toMap\n    // Prototypes of constructor outputs, used for inheritance\n    val objectPrototypes: Map[Var, Cnstr] = p.rawEntities.collect { \n      case ty: NuTypeDef =>\n        ty.nameVar -> freshVar(ty.nameVar)(using noExprId)\n    }.toMap\n    val fullCtx = ctx ++ vars ++ constructorPrototypes.map((v, s) => (v, s._1.asInstanceOf[ProdVar]))\n    val classes: Map[Var, ProdObj] = p.rawEntities.collect { \n      case ty: NuTypeDef =>\n        debug.writeLine(s\"Completing type info for class ${ty.nameVar} with ctors ${constructorPrototypes.map((v, s) => (v, s._1))}\")\n        given TermId = noExprId\n        val argTup = ty.params.getOrElse(Tup(Nil))\n        val (pList, cList) = argTup.fields.map{\n          case (Some(v), Fld(flags, _)) if flags.genGetter =>\n            val fldVar = freshVar(s\"${argTup.uid}_${v.name}\")(using noExprId)\n            ((v, fldVar._1), (v, fldVar._2))\n          case (Some(v), Fld(flags, _)) if !flags.genGetter => \n            lastWords(s\"Non val ${v} class parameter is not supported.\")\n          case other =>\n            lastWords(s\"${other} class parameter is not supported.\")\n        }.unzip\n        val bodyStrats = apply(ty.body)(using fullCtx ++ pList.toMap)\n        val parents = ty.parents.map{\n          case v: Var => objectPrototypes(v)._1\n          case App(v: Var, _) => objectPrototypes(v)._1\n          case other => lastWords(s\"Unsupported inheritance pattern ${other}\")\n        }\n        if parents.length > 1 then lastWords(s\"Multiple Inheritance at ${ty} not supported yet\")\n        ty.kind match\n          case Cls => \n            ty.ctor match\n              case None => \n                val obj = ProdObj(Some(ty.nameVar), bodyStrats._1 ++ pList, parents)\n                val func = ProdFun(ConsTup(cList.map(_._2)),obj)\n                constrain(func, constructorPrototypes(ty.nameVar)._2)\n                constrain(obj, objectPrototypes(ty.nameVar)._2)\n                ty.nameVar -> obj\n              case Some(Constructor(t @ Tup(params), body)) =>\n                val mapping = params.map{\n                  case (None, Fld(_, v: Var)) =>\n                    (v, freshVar(s\"${t.uid}_${v.name}\")(using noExprId))\n                  case (Some(v1: Var), Fld(_, v2: Var)) =>\n                    (v1, freshVar(s\"${t.uid}_${v1.name}\")(using noExprId))\n                  case other => \n                    lastWords(s\"Unsupported term ${other}\")\n                }\n                process(body)(using fullCtx ++ pList.toMap ++ mapping.map((i, s) => (i, s._1)))\n                val obj = ProdObj(Some(ty.nameVar), bodyStrats._1 ++ pList, parents)\n                val func = ProdFun(ConsTup(mapping.map(_._2._2)),obj)\n                constrain(func, constructorPrototypes(ty.nameVar)._2)\n                constrain(obj, objectPrototypes(ty.nameVar)._2)\n                ty.nameVar -> obj\n          case Mod =>\n            val obj = ProdObj(Some(ty.nameVar), bodyStrats._1 ++ pList, parents) \n            constrain(obj, constructorPrototypes(ty.nameVar)._2)\n            constrain(obj, objectPrototypes(ty.nameVar)._2)\n            ty.nameVar -> obj\n          case other => \n            lastWords(s\"Unsupported class kind ${other}\")\n    }.toMap\n    val tys = p.rawEntities.flatMap{\n      case f: NuFunDef => {\n        f.rhs match \n          case Left(value) => \n            val p = process(value)(using fullCtx)\n            val v = vars(f.nme)\n            constrain(p, ConsVar(v.uid, v.name)()(using noExprId))\n            Some(p)\n          case Right(value) => None\n      }\n      case t: Term => {\n        val topLevelProd = process(t)(using fullCtx)\n        Some(topLevelProd)\n      }\n      case other => {\n        debug.writeLine(s\"Skipping ${other}\")\n        None\n      }\n    }\n    (vars.toList, tys.lastOption.getOrElse(ProdObj(Some(Var(\"prim$Unit\")), Nil)(using noExprId)))\n  \n  val termToProdType = mutable.Map.empty[TermId, ProdStrat]\n  // Selection terms -> Object types that they Consume\n  val selTermToType = mutable.Map.empty[TermId, ConsObj]\n\n  def builtinOps: Map[Var, ProdFun] = {\n    given TermId = noExprId\n    Map(\n      (Var(\"+\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$Int\")), Nil),ConsObj(Some(Var(\"prim$Int\")), Nil))), ProdObj(Some(Var(\"prim$Int\")), Nil))),\n      (Var(\"-\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$Int\")), Nil),ConsObj(Some(Var(\"prim$Int\")), Nil))), ProdObj(Some(Var(\"prim$Int\")), Nil))),\n      (Var(\"*\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$Int\")), Nil),ConsObj(Some(Var(\"prim$Int\")), Nil))), ProdObj(Some(Var(\"prim$Int\")), Nil))),\n      (Var(\">\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$Int\")), Nil),ConsObj(Some(Var(\"prim$Int\")), Nil))), ProdObj(Some(Var(\"prim$Bool\")), Nil))),\n      (Var(\"==\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$Int\")), Nil),ConsObj(Some(Var(\"prim$Int\")), Nil))), ProdObj(Some(Var(\"prim$Bool\")), Nil))),\n      (Var(\"is\") -> ProdFun(ConsTup(List(freshVar(\"is$rhs\")._2,freshVar(\"is$lhs\")._2)), ProdObj(Some(Var(\"prim$Bool\")), Nil))),\n      (Var(\"concat\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$String\")), Nil))), ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$String\")), Nil))), ProdObj(Some(Var(\"prim$String\")), Nil)))),\n      (Var(\"log\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$String\")), Nil))), ProdObj(Some(Var(\"prim$Unit\")), Nil))),\n      (Var(\"toString\") -> ProdFun(ConsTup(List(ConsObj(Some(Var(\"prim$Int\")), Nil))), ProdObj(Some(Var(\"prim$String\")), Nil)))\n    )\n  }\n\n  def process(t: Term)(using ctx: Context): ProdStrat = \n    debug.writeLine(s\"Processing term ${t}\")\n    debug.indent()\n    val res: ProdStrat = t match\n      case IntLit(_) => ProdObj(Some(Var(\"prim$Int\")), Nil)(using t.uid)\n      case StrLit(_) => ProdObj(Some(Var(\"prim$String\")), Nil)(using t.uid)\n      case UnitLit(_) => ProdObj(Some(Var(\"prim$Unit\")), Nil)(using t.uid)\n      case Var(\"true\") | Var(\"false\") => ProdObj(Some(Var(\"prim$Bool\")), Nil)(using t.uid)\n      case v @ Var(id) if builtinOps.contains(v) =>\n        builtinOps(v)\n      case v @ Var(id) =>\n        ctx(v).copy()(Some(v))(using t.uid)\n      case Asc(trm, ty) =>\n        // TODO: Enforce type ascription?\n        process(trm)\n      case Let(isRec, nme, rhs, body) =>\n        val rhsRes = process(rhs)\n        val sv = freshVar(s\"${t.uid}_let\")(using t.uid)\n        constrain(rhsRes, sv._2)\n        process(body)(using ctx + (nme -> sv._1))\n      case NuNew(cls) =>\n        process(App(NuNew(cls), Tup(Nil).withLoc(t.toLoc.map(_.right))))\n      case App(NuNew(cls), arg) => \n        val clsRes = process(cls)\n        val argRes = process(arg)\n        val sv = freshVar(s\"${t.uid}_callres\")(using t.uid)\n        constrain(clsRes, ConsFun(argRes, sv._2)(using noExprId))\n        sv._1\n      case App(func, arg) => \n        val funcRes = process(func)\n        val argRes = process(arg)\n        val sv = freshVar(s\"${t.uid}_callres\")(using t.uid)\n        constrain(funcRes, ConsFun(argRes, sv._2)(using noExprId))\n        sv._1\n      case Lam(t @ Tup(args), body) =>\n        val mapping = args.map{\n          case (None, Fld(_, v: Var)) =>\n            (v, freshVar(s\"${t.uid}_${v.name}\")(using noExprId))\n          case (Some(v1: Var), Fld(_, v2: Var)) =>\n            (v1, freshVar(s\"${t.uid}_${v1.name}\")(using noExprId))\n          case other => \n            lastWords(s\"Unsupported term ${other}\")\n        }\n        ProdFun(ConsTup(mapping.map(_._2._2))(using t.uid),\n          process(body)(using ctx ++ mapping.map((i, s) => (i, s._1))))(using t.uid)\n      case If(IfThen(scrut, thenn), S(elze)) =>\n        constrain(process(scrut), ConsObj(Some(Var(\"prim$Bool\")), Nil)(using noExprId))\n        val res = freshVar(s\"${t.uid}_ifres\")(using t.uid)\n        constrain(process(thenn), res._2)\n        constrain(process(elze), res._2)\n        res._1\n      case elf: If =>\n        elf.desugaredTerm match {\n          case S(desugared) => process(desugared)\n          case N => lastWords(s\"Undesugared UCS term ${t} found\")\n        }\n      case Tup(fields) =>\n        val mapping = fields.map{\n          case (None, Fld(_, fieldTerm: Term)) =>\n            process(fieldTerm)\n          case other => lastWords(s\"Unsupported tuple structure ${other}\") \n        }\n        ProdTup(mapping)(using t.uid)\n      case Sel(receiver, fieldName) =>\n        val selRes = freshVar(s\"${t.uid}_selres\")(using t.uid)\n        val selector = ConsObj(None, List(fieldName -> selRes._2))(using t.uid)\n        constrain(process(receiver), selector)\n        selTermToType += (t.uid -> selector.asInstanceOf[ConsObj])\n        selRes._1\n      case Bra(true, t) =>\n        process(t)\n      case Rcd(fields) =>\n        ProdObj(None, fields.map{\n          case (v, Fld(_, t)) => (v -> process(t))\n        })(using t.uid)\n      case Blk(stmts) => \n        apply(TypingUnit(stmts))._2\n      case Bra(false, term) =>\n        process(term)\n      case CaseOf(trm, cases) => // TODO: Complete constraining in conjunction with processCases\n        ???\n      case Eqn(lhs, rhs) =>\n        process(lhs)\n        process(rhs)\n      case other => lastWords(s\"Unsupported term ${other}\")\n\n    debug.outdent()\n    registerTermToType(t, res)\n\n  // TODO: Complete constraining for CaseBranches after implementing negative types and intersections\n  def processCases(scrut: ProdVar, cs: CaseBranches)(using ctx: Context, resCons: ConsVar): Unit =\n    cs match\n      case Wildcard(body) => \n        constrain(process(body), resCons)\n      case NoCases => ()\n      case Case(pat, body, rest) => ???\n\n  \n  val constraintCache = mutable.Set.empty[(ProdStrat, ConsStrat)]\n  val upperBounds = mutable.Map.empty[TypeVarId, Ls[ConsStrat]].withDefaultValue(Nil)\n  val lowerBounds = mutable.Map.empty[TypeVarId, Ls[ProdStrat]].withDefaultValue(Nil)\n\n  def constrain(prod: ProdStrat, cons: ConsStrat): Unit = {\n    debug.writeLine(s\"constraining ${prod} -> ${cons}\")\n    if (constraintCache.contains(prod -> cons)) return () else constraintCache += (prod -> cons)\n    \n    (prod, cons) match\n        case (ProdVar(v, pn), ConsVar(w, cn))\n          if v === w => ()\n        case (pv@ProdVar(v, _), _) =>\n          cons match {\n            case c: ConsObj if lowerBounds(v).isEmpty =>\n              c.selectionSource = c.selectionSource + pv\n            case _ => ()\n          }\n          upperBounds += v -> (cons :: upperBounds(v))\n          lowerBounds(v).foreach(lb_strat => constrain(lb_strat, cons))\n        case (_, cv@ConsVar(v, _)) =>\n          prod match {\n            case p: ProdObj if upperBounds(v).isEmpty =>\n              p.objDestination = p.objDestination + cv\n            case _ => ()\n          }\n          lowerBounds += v -> (prod :: lowerBounds(v))\n          upperBounds(v).foreach(ub_strat => constrain(prod, ub_strat))\n        case (ProdFun(lhs1, rhs1), ConsFun(lhs2, rhs2)) =>\n          constrain(lhs2, lhs1)\n          constrain(rhs1, rhs2)\n        case (pt@ProdTup(fields1), ct@ConsTup(fields2)) =>\n          if pt.fields.length != ct.fields.length\n          then lastWords(\"Tuple size mismatch\")\n          (fields1 zip fields2).map((p, c) =>\n            constrain(p, c)\n          )\n        case (pv@ProdObj(nme1, fields1, parents), cv@ConsObj(nme2, fields2)) =>\n          nme2 match \n            case Some(name) if name != nme1.get => lastWords(s\"Could not constrain ${(prod -> cons)}\")\n            case _ => ()\n          fields2.map((key, res2) => {\n            fields1.find(_._1 == key) match \n              case None => \n                debug.writeLine(\"field not found, try parent\") \n                // TODO: Handle multiple inheritance properly, currently assume only one parent\n                parents match\n                  case head :: next => \n                    constrain(head, cv)\n                  case Nil => \n                    lastWords(s\"Could not constrain ${(prod -> cons)}\")\n              case Some((_, res1)) => \n                cv.selectionSource = cv.selectionSource + pv\n                pv.objDestination = pv.objDestination + cv\n                constrain(res1, res2)\n          })\n        case (pv@ProdTup(fields1), cv@ConsObj(nme2, fields2)) =>\n          nme2 match \n            case Some(name) => lastWords(s\"Could not constrain ${(prod -> cons)}\")\n            case _ => ()\n          fields2.map((key, res2) => {\n            cv.selectionSource = cv.selectionSource + pv\n            constrain(fields1(key.name.toInt), res2)\n          })\n        case other => lastWords(s\"Could not constrain ${other}\")\n  }\n\n  // Selection terms -> Producers that they consume\n  lazy val selToResTypes: Map[TermId, Set[ProdStrat]] = selTermToType.map((termId, cons) =>\n    (termId, cons.selectionSource)\n  ).toMap\n\n  // Rewrite terms, replacing selections with pattern matches if they only select on objects\n  def rewriteTerm(t: Term): Term = \n    def objSetToMatchBranches(receiver: Var, fieldName: Var, objSet: List[ProdObj], acc: CaseBranches = NoCases)(using funcApp: Option[Term] = None): CaseBranches =\n      objSet match \n        case Nil => acc\n        case (p :: rest) if p.ctor.isDefined => \n          if funcApp.isDefined \n          then objSetToMatchBranches(receiver, fieldName, rest, Case(p.ctor.get, App(Sel(receiver, fieldName), funcApp.get), acc)(false))\n          else objSetToMatchBranches(receiver, fieldName, rest, Case(p.ctor.get, Sel(receiver, fieldName), acc)(false))\n        case other => lastWords(s\"Unexpected  ${other}\")\n    t match\n      case Var(_) | IntLit(_) | UnitLit(_) | StrLit(_) => t\n      // TODO: Remove the following case when eta expansion is supported, currently a workaround.\n      case App(t @ Sel(receiver, fieldName), arg) => \n        if (selToResTypes(t.uid).forall{\n          case _: ProdVar => true\n          case x: ProdObj if x.ctor.isDefined => true\n          case _ => false\n        }) {\n          val letName = Var(s\"selRes$$${t.uid}\")\n          Let(false, letName, rewriteTerm(receiver),\n            CaseOf(letName, objSetToMatchBranches(letName, fieldName, selToResTypes(t.uid).collect{case x: ProdObj => x}.toList)(using Some(rewriteTerm(arg))))\n          )\n        } else {\n          debug.writeLine(s\"${selToResTypes(t.uid)}\")\n          Sel(rewriteTerm(receiver), fieldName)\n        }\n      case App(func, arg) => \n        App(rewriteTerm(func), rewriteTerm(arg))\n      case Lam(t @ Tup(args), body) =>\n        Lam(rewriteTerm(t), rewriteTerm(body))\n      case If(IfThen(scrut, thenn), S(elze)) =>\n        If(IfThen(rewriteTerm(scrut), rewriteTerm(thenn)), S(rewriteTerm(elze)))\n      case Tup(fields) =>\n        Tup(fields.map{\n          case (x, Fld(flags, fieldTerm: Term)) =>\n            (x, Fld(flags, rewriteTerm(fieldTerm)))\n        })\n      case Sel(receiver, fieldName) =>\n        if (selToResTypes(t.uid).forall{\n          case _: ProdVar => true\n          case x: ProdObj if x.ctor.isDefined => true\n          case _ => false\n        }) {\n          val letName = Var(s\"selRes$$${t.uid}\")\n          Let(false, letName, rewriteTerm(receiver),\n            CaseOf(letName, objSetToMatchBranches(letName, fieldName, selToResTypes(t.uid).collect{case x: ProdObj => x}.toList))\n          )\n        } else {\n          debug.writeLine(s\"${selToResTypes(t.uid)}\")\n          Sel(rewriteTerm(receiver), fieldName)\n        }\n      case Bra(true, t) =>\n        Bra(true, rewriteTerm(t))\n      case Rcd(fields) =>\n        Rcd(fields.map{\n          case (v, Fld(flags, t)) => (v, Fld(flags, rewriteTerm(t)))\n        })\n      case Blk(stmts) => \n        Blk(rewriteStatements(stmts))\n      case Bra(false, term) =>\n        Bra(false, rewriteTerm(term))\n      case NuNew(cls) => \n        NuNew(rewriteTerm(cls))\n      case other => lastWords(s\"Unsupported term ${other}\")\n    \n  def rewriteStatements(stmts: List[Statement]): List[Statement] =\n    stmts.map{\n      case ty: NuTypeDef => \n        ty.copy(body = rewriteProgram(ty.body))(ty.declareLoc, ty.abstractLoc, ty.annotations)\n      case f: NuFunDef => \n        f.copy(rhs = f.rhs match\n          case Left(t) => Left(rewriteTerm(t))\n          case Right(_) => f.rhs\n        )(f.declareLoc, f.virtualLoc, f.mutLoc, f.signature, f.outer, f.genField, f.annotations)\n      case t: Term => \n        rewriteTerm(t)\n      case other => lastWords(s\"Unsupported term ${other}\")\n    }\n  def rewriteProgram(t: TypingUnit): TypingUnit = \n    TypingUnit(rewriteStatements(t.rawEntities))\n\n  private def registerTermToType(t: Term, s: ProdStrat) = {\n    termToProdType.get(t.uid) match {\n      case None => {\n        termToProdType += t.uid -> s\n        s\n      }\n      case Some(value) =>\n        lastWords(s\"${t} registered two prod strategies:\\n already has ${value}, but got ${s}\")\n    }\n  }\n}\n"
  },
  {
    "path": "compiler/shared/main/scala/mlscript/compiler/simpledef/Uid.scala",
    "content": "package mlscript\npackage compiler\npackage simpledef\n\nopaque type Uid[T] = Int\n\nobject Uid:\n  class Handler[T]:\n    class State:\n      private val uidStore = scala.collection.mutable.Map.empty[String, Uid[T]]\n      def nextUid: Uid[T] = nextUid(\"\")\n      def nextUid(key: String): Uid[T] =\n        uidStore.updateWith(key) {\n          case None => Some(0)\n          case Some(v) => Some(v + 1)\n        }.get\n  object TypeVar extends Handler[TypeVar]\n  object Term extends Handler[Term]"
  },
  {
    "path": "compiler/shared/test/diff/CompilerScratch.mls",
    "content": ":NewDefs\n\n\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/ClassConstructor.mls",
    "content": ":NewDefs\n\nclass X {\n    val num = 5\n}\nclass Y(val num: Int) {\n    constructor(y: Int) {\n        num = y+5\n    }\n}\nlet y = new Y(6)\nlet x = new X\n(if true then y else x).num\n//│ class X {\n//│   constructor()\n//│   val num: 5\n//│ }\n//│ class Y(num: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ let y: Y\n//│ let x: X\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class X {let num = 5}\n//│  class Y(val num: Int,) {}\n//│  let y = (new Y)(6,)\n//│  let x = new X\n//│  let selRes$40 = '(' if (true) then y else x ')' in case selRes$40 of { Y => (selRes$40).num\n//│  X => (selRes$40).num }}\n//│ End simpledef\n//│ \n//│ y\n//│   = Y {}\n//│ x\n//│   = X {}\n//│ res\n//│     = 11\n\nclass Z(val num1: Int) {\n    constructor(y, x) {\n        num1 = y+x\n    }\n}\nclass W(val num1: Int, val num2: Int) {\n    constructor(w) {\n        num1 = w\n        num2 = w\n    }\n}\nval w = new W(3)\nval z = new Z(6, 11)\n(if true then w else z).num1\n//│ class Z(num1: Int) {\n//│   constructor(y: Int, x: Int)\n//│ }\n//│ class W(num1: Int, num2: Int) {\n//│   constructor(w: Int)\n//│ }\n//│ val w: W\n//│ val z: Z\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class Z(val num1: Int,) {}\n//│  class W(val num1: Int, val num2: Int,) {}\n//│  let w = (new W)(3,)\n//│  let z = (new Z)(6, 11,)\n//│  let selRes$58 = '(' if (true) then w else z ')' in case selRes$58 of { W => (selRes$58).num1\n//│  Z => (selRes$58).num1 }}\n//│ End simpledef\n//│ \n//│ w\n//│   = W {}\n//│ z\n//│   = Z {}\n//│ res\n//│     = 3\n\n\n\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Classes.mls",
    "content": ":NewDefs\n\nclass Bar(val x: Int) {\n  fun foo(x) = x\n  fun FooMinus(y: Int) = x + y\n  fun car = foo(2)\n}\nclass Car() {\n  fun da(b: Bar) = b.foo(2)\n}\nfun baz(b: Bar) = b.foo(2)\nlet bar = Bar(42)\nbaz(bar)\n(Car()).da(Bar(1337))\nbar.car\n//│ class Bar(x: Int) {\n//│   fun FooMinus: (y: Int) -> Int\n//│   fun car: 2\n//│   fun foo: forall 'a. 'a -> 'a\n//│ }\n//│ class Car() {\n//│   fun da: (b: Bar) -> 2\n//│ }\n//│ fun baz: (b: Bar) -> 2\n//│ let bar: Bar\n//│ 2\n//│ \n//│ Simpledef:\n//│ {class Bar(val x: Int,) {fun foo = (x::0,) => x\n//│  fun FooMinus = (y: Int,) => +(x, y,)\n//│  fun car = foo(2,)}\n//│  class Car() {fun da = (b: Bar,) => let selRes$34 = b in case selRes$34 of { Bar => (selRes$34).foo(2,) }}\n//│  fun baz = (b: Bar,) => let selRes$48 = b in case selRes$48 of { Bar => (selRes$48).foo(2,) }\n//│  let bar = Bar(42,)\n//│  baz(bar,)\n//│  let selRes$76 = '(' Car() ')' in case selRes$76 of { Car => (selRes$76).da(Bar(1337,),) }\n//│  let selRes$98 = bar in case selRes$98 of { Bar => (selRes$98).car }}\n//│ End simpledef\n//│ \n//│ bar\n//│     = Bar {}\n//│ res\n//│     = 2\n//│ res\n//│     = 2\n//│ res\n//│     = 2\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/ClosureCapture.mls",
    "content": ":NewDefs\n:AllowRuntimeErrors\n\nfun foo(x) = \n  (f => f(x))(z => z+1)\nfoo(2)\n//│ fun foo: Int -> Int\n//│ Int\n//│ \n//│ Simpledef:\n//│ {fun foo = (x::0,) => {'(' (f::1,) => f(x,) ')'((z::2,) => +(z, 1,),)}\n//│  foo(2,)}\n//│ End simpledef\n//│ \n//│ res\n//│     = 3\n\nfun f(x) =\n  (y => f(x+y))(x+1)\nf(1)\n//│ fun f: Int -> nothing\n//│ nothing\n//│ \n//│ Simpledef:\n//│ {fun f = (x::3,) => {'(' (y::4,) => f(+(x, y,),) ')'(+(x, 1,),)}\n//│  f(1,)}\n//│ End simpledef\n//│ \n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Constructor.mls",
    "content": ":NewDefs\n\nclass X() {\n    val a = \n        log(\"ok\")\n        6\n}\nval object = X()\n(new X()).a\n(new X()).a\nobject.a\nobject.a\n//│ class X() {\n//│   val a: 6\n//│ }\n//│ val object: X\n//│ 6\n//│ \n//│ Simpledef:\n//│ {class X() {let a = {log(\"ok\",)\n//│  6}}\n//│  let object = X()\n//│  let selRes$20 = '(' (new X)() ')' in case selRes$20 of { X => (selRes$20).a }\n//│  let selRes$30 = '(' (new X)() ')' in case selRes$30 of { X => (selRes$30).a }\n//│  let selRes$40 = object in case selRes$40 of { X => (selRes$40).a }\n//│  let selRes$44 = object in case selRes$44 of { X => (selRes$44).a }}\n//│ End simpledef\n//│ \n//│ object\n//│        = X {}\n//│ // Output\n//│ ok\n//│ res\n//│     = 6\n//│ // Output\n//│ ok\n//│ res\n//│     = 6\n//│ // Output\n//│ ok\n//│ res\n//│     = 6\n//│ res\n//│     = 6\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/DelayedEvaluation.mls",
    "content": ":NewDefs\n\nclass G(val num: Int) {\n    val x = \n        log(\"once on construction\")\n        num+2\n    val y() =\n        log(\"once every call\")\n        num+2\n}\nval g = new G(6)\ng.y()\ng.x\ng.y()\ng.x\n//│ class G(num: Int) {\n//│   val x: Int\n//│   val y: () -> Int\n//│ }\n//│ val g: G\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class G(val num: Int,) {let x = {log(\"once on construction\",)\n//│  +(num, 2,)}\n//│  let y = () => {log(\"once every call\",)\n//│  +(num, 2,)}}\n//│  let g = (new G)(6,)\n//│  let selRes$56 = g in case selRes$56 of { G => (selRes$56).y() }\n//│  let selRes$64 = g in case selRes$64 of { G => (selRes$64).x }\n//│  let selRes$68 = g in case selRes$68 of { G => (selRes$68).y() }\n//│  let selRes$76 = g in case selRes$76 of { G => (selRes$76).x }}\n//│ End simpledef\n//│ \n//│ g\n//│   = G {}\n//│ // Output\n//│ once on construction\n//│ res\n//│     = 8\n//│ // Output\n//│ once every call\n//│ res\n//│     = 8\n//│ res\n//│     = 8\n//│ // Output\n//│ once every call\n//│ res\n//│     = 8\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Differentiation.mls",
    "content": "// A usecase test for defunctionalization\n\n:NewDefs\n\n\nabstract class Exp() {\n    virtual fun derive(): Exp\n    virtual fun getVal: Str\n}\nclass Numeric(val i: Int) extends Exp {\n    fun derive() = Numeric(0)\n    fun getNum = i\n    fun getVal = toString(i)\n}\nclass Variable(val nm: Str) extends Exp {\n    fun derive() = Numeric(1)\n    fun getVal = nm\n}\nclass Sum(val lhs: Exp, val rhs: Exp) extends Exp {\n    fun derive() = Sum(lhs.derive(), rhs.derive())\n    fun getVal = concat(\"(\")(concat(concat(concat(lhs.getVal)(\" + \"))(rhs.getVal))(\")\"))\n}\nclass Mul(val lhs: Exp, val rhs: Exp) extends Exp {\n    fun derive() = Sum(Mul(lhs.derive(), rhs), Mul(lhs, rhs.derive()))\n    fun getVal = concat(\"(\")(concat(concat(concat(lhs.getVal)(\" * \"))(rhs.getVal))(\")\"))\n}\nclass Pow(val lhs: Variable, val rhs: Numeric) extends Exp {\n    fun derive() = Mul(rhs, Pow(lhs, Numeric(rhs.getNum - 1)))\n    fun getVal = concat(\"(\")(concat(concat(concat(lhs.getVal)(\" ^ \"))(rhs.getVal))(\")\"))\n}\nSum(Variable(\"x\"), Numeric(3)).derive().getVal\nMul(Variable(\"x\"), Numeric(3)).derive().getVal\nPow(Variable(\"x\"), Numeric(3)).derive().getVal\nMul(Pow(Variable(\"x\"), Numeric(2)), Pow(Variable(\"y\"), Numeric(2))).derive().getVal\n//│ abstract class Exp() {\n//│   fun derive: () -> Exp\n//│   fun getVal: Str\n//│ }\n//│ class Numeric(i: Int) extends Exp {\n//│   fun derive: () -> Numeric\n//│   fun getNum: Int\n//│   fun getVal: Str\n//│ }\n//│ class Variable(nm: Str) extends Exp {\n//│   fun derive: () -> Numeric\n//│   fun getVal: Str\n//│ }\n//│ class Sum(lhs: Exp, rhs: Exp) extends Exp {\n//│   fun derive: () -> Sum\n//│   fun getVal: Str\n//│ }\n//│ class Mul(lhs: Exp, rhs: Exp) extends Exp {\n//│   fun derive: () -> Sum\n//│   fun getVal: Str\n//│ }\n//│ class Pow(lhs: Variable, rhs: Numeric) extends Exp {\n//│   fun derive: () -> Mul\n//│   fun getVal: Str\n//│ }\n//│ Str\n//│ \n//│ Simpledef:\n//│ {class Exp() {fun derive: () -> Exp\n//│  fun getVal: Str}\n//│  class Numeric(val i: Int,): Exp {fun derive = () => Numeric(0,)\n//│  fun getNum = i\n//│  fun getVal = toString(i,)}\n//│  class Variable(val nm: Str,): Exp {fun derive = () => Numeric(1,)\n//│  fun getVal = nm}\n//│  class Sum(val lhs: Exp, val rhs: Exp,): Exp {fun derive = () => Sum(let selRes$48 = lhs in case selRes$48 of { Variable => (selRes$48).derive()\n//│  Mul => (selRes$48).derive()\n//│  Sum => (selRes$48).derive()\n//│  Numeric => (selRes$48).derive() }, let selRes$56 = rhs in case selRes$56 of { Numeric => (selRes$56).derive()\n//│  Sum => (selRes$56).derive()\n//│  Mul => (selRes$56).derive() },)\n//│  fun getVal = concat(\"(\",)(concat(concat(concat(let selRes$84 = lhs in case selRes$84 of { Variable => (selRes$84).getVal\n//│  Mul => (selRes$84).getVal\n//│  Sum => (selRes$84).getVal\n//│  Numeric => (selRes$84).getVal },)(\" + \",),)(let selRes$102 = rhs in case selRes$102 of { Numeric => (selRes$102).getVal\n//│  Sum => (selRes$102).getVal\n//│  Mul => (selRes$102).getVal },),)(\")\",),)}\n//│  class Mul(val lhs: Exp, val rhs: Exp,): Exp {fun derive = () => Sum(Mul(let selRes$132 = lhs in case selRes$132 of { Variable => (selRes$132).derive()\n//│  Mul => (selRes$132).derive()\n//│  Sum => (selRes$132).derive()\n//│  Numeric => (selRes$132).derive()\n//│  Pow => (selRes$132).derive() }, rhs,), Mul(lhs, let selRes$150 = rhs in case selRes$150 of { Mul => (selRes$150).derive()\n//│  Sum => (selRes$150).derive()\n//│  Numeric => (selRes$150).derive()\n//│  Pow => (selRes$150).derive() },),)\n//│  fun getVal = concat(\"(\",)(concat(concat(concat(let selRes$182 = lhs in case selRes$182 of { Variable => (selRes$182).getVal\n//│  Mul => (selRes$182).getVal\n//│  Sum => (selRes$182).getVal\n//│  Numeric => (selRes$182).getVal\n//│  Pow => (selRes$182).getVal },)(\" * \",),)(let selRes$200 = rhs in case selRes$200 of { Mul => (selRes$200).getVal\n//│  Sum => (selRes$200).getVal\n//│  Numeric => (selRes$200).getVal\n//│  Pow => (selRes$200).getVal },),)(\")\",),)}\n//│  class Pow(val lhs: Variable, val rhs: Numeric,): Exp {fun derive = () => Mul(rhs, Pow(lhs, Numeric(-(let selRes$238 = rhs in case selRes$238 of { Numeric => (selRes$238).getNum }, 1,),),),)\n//│  fun getVal = concat(\"(\",)(concat(concat(concat(let selRes$276 = lhs in case selRes$276 of { Variable => (selRes$276).getVal },)(\" ^ \",),)(let selRes$294 = rhs in case selRes$294 of { Numeric => (selRes$294).getVal },),)(\")\",),)}\n//│  let selRes$316 = let selRes$318 = Sum(Variable(\"x\",), Numeric(3,),) in case selRes$318 of { Sum => (selRes$318).derive() } in case selRes$316 of { Sum => (selRes$316).getVal }\n//│  let selRes$346 = let selRes$348 = Mul(Variable(\"x\",), Numeric(3,),) in case selRes$348 of { Mul => (selRes$348).derive() } in case selRes$346 of { Sum => (selRes$346).getVal }\n//│  let selRes$376 = let selRes$378 = Pow(Variable(\"x\",), Numeric(3,),) in case selRes$378 of { Pow => (selRes$378).derive() } in case selRes$376 of { Mul => (selRes$376).getVal }\n//│  let selRes$406 = let selRes$408 = Mul(Pow(Variable(\"x\",), Numeric(2,),), Pow(Variable(\"y\",), Numeric(2,),),) in case selRes$408 of { Mul => (selRes$408).derive() } in case selRes$406 of { Sum => (selRes$406).getVal }}\n//│ End simpledef\n//│ \n//│ res\n//│     = '(1 + 0)'\n//│ res\n//│     = '((1 * 3) + (x * 0))'\n//│ res\n//│     = '(3 * (x ^ 2))'\n//│ res\n//│     = '(((2 * (x ^ 1)) * (y ^ 2)) + ((x ^ 2) * (2 * (y ^ 1))))'\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/FreeVariables.mls",
    "content": ":NewDefs\n\nclass X() {\n    val num = 5\n    fun get() = num\n}\nX().get()\n//│ class X() {\n//│   fun get: () -> 5\n//│   val num: 5\n//│ }\n//│ 5\n//│ \n//│ Simpledef:\n//│ {class X() {let num = 5\n//│  fun get = () => num}\n//│  let selRes$10 = X() in case selRes$10 of { X => (selRes$10).get() }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 5\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/FuncsWithParams.mls",
    "content": ":NewDefs\n\n\nabstract class Arithmetic() {\n    virtual fun use(num1: Int, num2: Int): Int\n}\nclass Add() extends Arithmetic {\n    fun use(num1, num2) = num1+num2\n}\nclass Sub() extends Arithmetic {\n    fun use(num1, num2) = num1-num2\n}\nfun getArith(choice) = if choice == 1 then Add() else Sub()\ngetArith(1).use(4,6)\ngetArith(2).use(4,6)\n//│ abstract class Arithmetic() {\n//│   fun use: (num1: Int, num2: Int) -> Int\n//│ }\n//│ class Add() extends Arithmetic {\n//│   fun use: (Int, Int) -> Int\n//│ }\n//│ class Sub() extends Arithmetic {\n//│   fun use: (Int, Int) -> Int\n//│ }\n//│ fun getArith: Num -> (Add | Sub)\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class Arithmetic() {fun use: (num1: Int, num2: Int) -> Int}\n//│  class Add(): Arithmetic {fun use = (num1::0, num2::1,) => +(num1, num2,)}\n//│  class Sub(): Arithmetic {fun use = (num1::2, num2::3,) => -(num1, num2,)}\n//│  fun getArith = (choice::4,) => if (==(choice, 1,)) then Add() else Sub()\n//│  let selRes$58 = getArith(1,) in case selRes$58 of { Sub => (selRes$58).use(4, 6,)\n//│  Add => (selRes$58).use(4, 6,) }\n//│  let selRes$76 = getArith(2,) in case selRes$76 of { Sub => (selRes$76).use(4, 6,)\n//│  Add => (selRes$76).use(4, 6,) }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 10\n//│ res\n//│     = -2\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Inheritance.mls",
    "content": ":NewDefs\n\n// FIXME: Pattern matches on superclass instead of subclass\nclass Sup() {\n    fun add(num1, num2) = num1+num2\n}\nclass Sub1() extends Sup() {}\nclass Sub2() extends Sub1() {}\nSub1().add(3,4)\nSub2().add(5,6)\n//│ class Sup() {\n//│   fun add: (Int, Int) -> Int\n//│ }\n//│ class Sub1() extends Sup {\n//│   fun add: (Int, Int) -> Int\n//│ }\n//│ class Sub2() extends Sub1, Sup {\n//│   fun add: (Int, Int) -> Int\n//│ }\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class Sup() {fun add = (num1::0, num2::1,) => +(num1, num2,)}\n//│  class Sub1(): Sup() {}\n//│  class Sub2(): Sub1() {}\n//│  let selRes$16 = Sub1() in case selRes$16 of { Sup => (selRes$16).add(3, 4,) }\n//│  let selRes$32 = Sub2() in case selRes$32 of { Sup => (selRes$32).add(5, 6,) }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 7\n//│ res\n//│     = 11\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Lambda.mls",
    "content": ":NewDefs\n\n\nclass X(val foo: Int => Int){}\nclass Y(val foo: Int => Bool){}\nfun x(pred) = if pred then X(x => x+1) else Y(x => true)\nx(true).foo(5)\n//│ class X(foo: Int -> Int)\n//│ class Y(foo: Int -> Bool)\n//│ fun x: Bool -> (X | Y)\n//│ Int | false | true\n//│ \n//│ Simpledef:\n//│ {class X(val foo: (Int,) => Int,) {}\n//│  class Y(val foo: (Int,) => Bool,) {}\n//│  fun x = (pred::0,) => if (pred) then X((x::1,) => +(x, 1,),) else Y((x::2,) => true,)\n//│  let selRes$46 = x(true,) in case selRes$46 of { Y => (selRes$46).foo(5,)\n//│  X => (selRes$46).foo(5,) }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 6\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Lambdas.mls",
    "content": ":NewDefs\n\n((f, g) => f(g))(f => f, true)\n//│ true\n//│ \n//│ Simpledef:\n//│ {'(' (f::0, g::1,) => f(g,) ')'((f::2,) => f, true,)}\n//│ End simpledef\n//│ \n//│ res\n//│     = true\n\n(b => if b then true else false) (true)\n//│ Bool\n//│ \n//│ Simpledef:\n//│ {'(' (b::3,) => if (b) then true else false ')'(true,)}\n//│ End simpledef\n//│ \n//│ res\n//│     = true\n\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/ListConstruction.mls",
    "content": ":NewDefs\n\n\nabstract class List() {\n    fun getRes: Str\n    fun map: error\n}\nclass Cons(val x: Int, val xs: List) extends List {\n    fun getRes = concat(concat(toString(x))(\" :: \"))(xs.getRes)\n    fun map(f) = Cons(f(x), xs.map(f))\n}\nclass Nil() extends List {\n    fun getRes = \"Nil\"\n    fun map(f) = Nil()\n}\nfun mkList(len) =\n    if len == 0 then Nil()\n    else Cons(len, mkList(len-1))\nmkList(5).map(x => x*2).getRes\n//│ abstract class List() {\n//│   fun getRes: Str\n//│   fun map: error\n//│ }\n//│ class Cons(x: Int, xs: List) extends List {\n//│   fun getRes: Str\n//│   fun map: (Int -> Int) -> Cons\n//│ }\n//│ class Nil() extends List {\n//│   fun getRes: \"Nil\"\n//│   fun map: anything -> Nil\n//│ }\n//│ fun mkList: Int -> (Cons | Nil)\n//│ Str\n//│ \n//│ Simpledef:\n//│ {class List() {fun getRes: Str\n//│  fun map: error}\n//│  class Cons(val x: Int, val xs: List,): List {fun getRes = concat(concat(toString(x,),)(\" :: \",),)(let selRes$30 = xs in case selRes$30 of { Nil => (selRes$30).getRes\n//│  Cons => (selRes$30).getRes },)\n//│  fun map = (f::0,) => Cons(f(x,), let selRes$50 = xs in case selRes$50 of { Nil => (selRes$50).map(f,)\n//│  Cons => (selRes$50).map(f,) },)}\n//│  class Nil(): List {fun getRes = \"Nil\"\n//│  fun map = (f::1,) => Nil()}\n//│  fun mkList = (len::2,) => {if (==(len, 0,)) then Nil() else Cons(len, mkList(-(len, 1,),),)}\n//│  let selRes$126 = let selRes$128 = mkList(5,) in case selRes$128 of { Cons => (selRes$128).map((x::3,) => *(x, 2,),)\n//│  Nil => (selRes$128).map((x::3,) => *(x, 2,),) } in case selRes$126 of { Cons => (selRes$126).getRes\n//│  Nil => (selRes$126).getRes }}\n//│ End simpledef\n//│ \n//│ res\n//│     = '10 :: 8 :: 6 :: 4 :: 2 :: Nil'\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Modules.mls",
    "content": ":NewDefs\n\n\nclass Foo() {fun f = 0}\nmodule x { val y = Foo() }\nx.y.f\n//│ class Foo() {\n//│   fun f: 0\n//│ }\n//│ module x {\n//│   val y: Foo\n//│ }\n//│ 0\n//│ \n//│ Simpledef:\n//│ {class Foo() {fun f = 0}\n//│  module x {let y = Foo()}\n//│  let selRes$10 = let selRes$12 = x in case selRes$12 of { x => (selRes$12).y } in case selRes$10 of { Foo => (selRes$10).f }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 0\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/MonoNonLambda.mls",
    "content": ":NewDefs\n\nclass A() {\n    val x = 2\n    val y() = 3\n    fun z = 4\n    fun w() = 5\n}\nval a = A()\na.x\na.y()\na.z\na.w()\n//│ class A() {\n//│   fun w: () -> 5\n//│   val x: 2\n//│   val y: () -> 3\n//│   fun z: 4\n//│ }\n//│ val a: A\n//│ 5\n//│ \n//│ Simpledef:\n//│ {class A() {let x = 2\n//│  let y = () => 3\n//│  fun z = 4\n//│  fun w = () => 5}\n//│  let a = A()\n//│  let selRes$24 = a in case selRes$24 of { A => (selRes$24).x }\n//│  let selRes$28 = a in case selRes$28 of { A => (selRes$28).y() }\n//│  let selRes$36 = a in case selRes$36 of { A => (selRes$36).z }\n//│  let selRes$40 = a in case selRes$40 of { A => (selRes$40).w() }}\n//│ End simpledef\n//│ \n//│ a\n//│   = A {}\n//│ res\n//│     = 2\n//│ res\n//│     = 3\n//│ res\n//│     = 4\n//│ res\n//│     = 5\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/MonoTupSelect.mls",
    "content": ":NewDefs\n\nclass Foo() {fun f() = 0}\nclass Bar() {fun f = 0}\n[Foo(), Bar()].0.f()\n[Foo(), Bar()].1.f\n//│ class Foo() {\n//│   fun f: () -> 0\n//│ }\n//│ class Bar() {\n//│   fun f: 0\n//│ }\n//│ 0\n//│ \n//│ Simpledef:\n//│ {class Foo() {fun f = () => 0}\n//│  class Bar() {fun f = 0}\n//│  let selRes$10 = ([Foo(), Bar(),]).0 in case selRes$10 of { Foo => (selRes$10).f() }\n//│  let selRes$32 = ([Foo(), Bar(),]).1 in case selRes$32 of { Bar => (selRes$32).f }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 0\n//│ res\n//│     = 0\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/MutableParams.mls",
    "content": ":NewDefs // TODO: Mutable Parameters\n\n//class Bar(#x)\n//fun foo(#b) = b\n//let a = foo(new Bar(1))\n//let b = foo(new Bar(2))\n\n//class OneInt(#a){\n//  fun inc() = a+1\n//}\n//(new OneInt(1)).inc()\n\n//class OneInt(#a){\n//  fun add(x) = \n//    new OneInt(a+x.a)\n//}\n//(new OneInt(1)).add(new OneInt(2))\n\n//trait AnyFoo {\n//}\n//class FooPlus(#a): AnyFoo {\n//  fun bar(b) = a + b\n//}\n//class FooMinus(#a): AnyFoo {\n//  fun bar(b) = a - b\n//}\n//fun f(x) = x.bar(42)\n//f(new FooPlus(1))\n//f(new FooMinus(2))\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/MutualRec.mls",
    "content": ":NewDefs\n:AllowRuntimeErrors\n\nval any = -20\nfun f(x) = \n  if x > any then 0\n  else g(x - 1)\nfun g(x) = \n  if x > any then g(x - 1)\n  else f(x - 2)\ng(1)\n//│ val any: -20\n//│ fun f: Int -> 0\n//│ fun g: Int -> 0\n//│ 0\n//│ \n//│ Simpledef:\n//│ {let any = -20\n//│  fun f = (x::0,) => {if (>(x, any,)) then 0 else g(-(x, 1,),)}\n//│  fun g = (x::1,) => {if (>(x, any,)) then g(-(x, 1,),) else f(-(x, 2,),)}\n//│  g(1,)}\n//│ End simpledef\n//│ \n//│ any\n//│     = -20\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/NewOperator.mls",
    "content": ":NewDefs\n\nclass Foo(val x: Int) {\n}\nnew Foo(5).x\n//│ class Foo(x: Int)\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class Foo(val x: Int,) {}\n//│  let selRes$4 = (new Foo)(5,) in case selRes$4 of { Foo => (selRes$4).x }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 5\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/NuMono.mls",
    "content": ":NewDefs\n\n// old \"new\" syntax\n//class A() {\n//    val num() = 0\n//}\n//class B() {\n//    val num() = 1\n//}\n//fun foo(num: Int) = if false then new A() else new B()\n//foo(10).num()\n\n\nclass A() {\n    val num() = 0\n}\nclass B() {\n    val num() = 1\n}\nfun foo(num: Int) = if num > 5 then A() else B()\nfoo(10).num()\n//│ class A() {\n//│   val num: () -> 0\n//│ }\n//│ class B() {\n//│   val num: () -> 1\n//│ }\n//│ fun foo: (num: Int) -> (A | B)\n//│ 0 | 1\n//│ \n//│ Simpledef:\n//│ {class A() {let num = () => 0}\n//│  class B() {let num = () => 1}\n//│  fun foo = (num: Int,) => if (>(num, 5,)) then A() else B()\n//│  let selRes$42 = foo(10,) in case selRes$42 of { B => (selRes$42).num()\n//│  A => (selRes$42).num() }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 0\n\n\nclass A(val num1: Int, val num2: Int) {\n    fun foo() = num1-num2\n}\nclass B(val num1: Int, val num2: Int) {\n    fun foo() = num1+num2\n}\nfun foo(num: Int) = if num > 5 then A(10,6) else B(8,7)\nfoo(10).foo()\nfoo(0).foo()\n//│ class A(num1: Int, num2: Int) {\n//│   fun foo: () -> Int\n//│ }\n//│ class B(num1: Int, num2: Int) {\n//│   fun foo: () -> Int\n//│ }\n//│ fun foo: (num: Int) -> (A | B)\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class A(val num1: Int, val num2: Int,) {fun foo = () => -(num1, num2,)}\n//│  class B(val num1: Int, val num2: Int,) {fun foo = () => +(num1, num2,)}\n//│  fun foo = (num: Int,) => if (>(num, 5,)) then A(10, 6,) else B(8, 7,)\n//│  let selRes$70 = foo(10,) in case selRes$70 of { B => (selRes$70).foo()\n//│  A => (selRes$70).foo() }\n//│  let selRes$84 = foo(0,) in case selRes$84 of { B => (selRes$84).foo()\n//│  A => (selRes$84).foo() }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 4\n//│ res\n//│     = 15\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/ObjFieldAccess.mls",
    "content": ":NewDefs\n\nclass A(val i: Int) {\n    fun get1() = i\n    fun get2 = i\n}\nval a = A(6)\na.get1()\na.get2\n//│ class A(i: Int) {\n//│   fun get1: () -> Int\n//│   fun get2: Int\n//│ }\n//│ val a: A\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class A(val i: Int,) {fun get1 = () => i\n//│  fun get2 = i}\n//│  let a = A(6,)\n//│  let selRes$20 = a in case selRes$20 of { A => (selRes$20).get1() }\n//│  let selRes$28 = a in case selRes$28 of { A => (selRes$28).get2 }}\n//│ End simpledef\n//│ \n//│ a\n//│   = A {}\n//│ res\n//│     = 6\n//│ res\n//│     = 6\n\nclass A(val i: Str) {\n    fun get1() = i\n    fun get2 = i\n}\nval a = A(\"6\")\na.get1()\na.get2\n//│ class A(i: Str) {\n//│   fun get1: () -> Str\n//│   fun get2: Str\n//│ }\n//│ val a: A\n//│ Str\n//│ \n//│ Simpledef:\n//│ {class A(val i: Str,) {fun get1 = () => i\n//│  fun get2 = i}\n//│  let a = A(\"6\",)\n//│  let selRes$20 = a in case selRes$20 of { A => (selRes$20).get1() }\n//│  let selRes$28 = a in case selRes$28 of { A => (selRes$28).get2 }}\n//│ End simpledef\n//│ \n//│ a\n//│   = A {}\n//│ res\n//│     = '6'\n//│ res\n//│     = '6'\n\nclass X()\nclass Y(val foo: X) {\n    fun get1() = foo\n    fun get2 = foo\n}\nval a = Y(X())\na.get1()\na.get2\n//│ class X()\n//│ class Y(foo: X) {\n//│   fun get1: () -> X\n//│   fun get2: X\n//│ }\n//│ val a: Y\n//│ X\n//│ \n//│ Simpledef:\n//│ {class X() {}\n//│  class Y(val foo: X,) {fun get1 = () => foo\n//│  fun get2 = foo}\n//│  let a = Y(X(),)\n//│  let selRes$24 = a in case selRes$24 of { Y => (selRes$24).get1() }\n//│  let selRes$32 = a in case selRes$32 of { Y => (selRes$32).get2 }}\n//│ End simpledef\n//│ \n//│ a\n//│   = Y {}\n//│ res\n//│     = X {}\n//│ res\n//│     = X {}\n\nclass I() {}\nclass J() {}\nclass K(val foo: I, val bar: J) {\n    fun getFoo = foo\n    fun getBar = bar\n}\nval k = K(I(), J())\nk.getFoo\nk.getBar\n//│ class I()\n//│ class J()\n//│ class K(foo: I, bar: J) {\n//│   fun getBar: J\n//│   fun getFoo: I\n//│ }\n//│ val k: K\n//│ J\n//│ \n//│ Simpledef:\n//│ {class I() {}\n//│  class J() {}\n//│  class K(val foo: I, val bar: J,) {fun getFoo = foo\n//│  fun getBar = bar}\n//│  let k = K(I(), J(),)\n//│  let selRes$26 = k in case selRes$26 of { K => (selRes$26).getFoo }\n//│  let selRes$30 = k in case selRes$30 of { K => (selRes$30).getBar }}\n//│ End simpledef\n//│ \n//│ k\n//│   = K {}\n//│ res\n//│     = I {}\n//│ res\n//│     = J {}\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/ObjFields.mls",
    "content": ":NewDefs\n\n\nclass X(val bar: Int) {}\nclass Y(val bar: Str) {}\nclass A(val foo: X) {}\nclass B(val foo: Y) {}\nfun getObj(pred) = if pred then A(X(1)) else B(Y(\"abc\"))\nval x = getObj(true)\nx.foo.bar\n//│ class X(bar: Int)\n//│ class Y(bar: Str)\n//│ class A(foo: X)\n//│ class B(foo: Y)\n//│ fun getObj: Bool -> (A | B)\n//│ val x: A | B\n//│ Int | Str\n//│ \n//│ Simpledef:\n//│ {class X(val bar: Int,) {}\n//│  class Y(val bar: Str,) {}\n//│  class A(val foo: X,) {}\n//│  class B(val foo: Y,) {}\n//│  fun getObj = (pred::0,) => if (pred) then A(X(1,),) else B(Y(\"abc\",),)\n//│  let x = getObj(true,)\n//│  let selRes$54 = let selRes$56 = x in case selRes$56 of { A => (selRes$56).foo\n//│  B => (selRes$56).foo } in case selRes$54 of { Y => (selRes$54).bar\n//│  X => (selRes$54).bar }}\n//│ End simpledef\n//│ \n//│ x\n//│   = A {}\n//│ res\n//│     = 1\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/ObjMultiFields.mls",
    "content": ":NewDefs\n\n\nclass X(val foo: Int, val bar: Bool) {}\nclass Y(val foo: Str, val bar: Int) {}\nclass A(val foo: X) {}\nclass B(val foo: Y) {}\nfun foo(pred) = if pred then A(X(1, false)) else B(Y(\"abc\", 5))\nval x = foo(true)\nx.foo.bar\nfoo(false).foo.bar\n//│ class X(foo: Int, bar: Bool)\n//│ class Y(foo: Str, bar: Int)\n//│ class A(foo: X)\n//│ class B(foo: Y)\n//│ fun foo: Bool -> (A | B)\n//│ val x: A | B\n//│ Int | false | true\n//│ \n//│ Simpledef:\n//│ {class X(val foo: Int, val bar: Bool,) {}\n//│  class Y(val foo: Str, val bar: Int,) {}\n//│  class A(val foo: X,) {}\n//│  class B(val foo: Y,) {}\n//│  fun foo = (pred::0,) => if (pred) then A(X(1, false,),) else B(Y(\"abc\", 5,),)\n//│  let x = foo(true,)\n//│  let selRes$58 = let selRes$60 = x in case selRes$60 of { A => (selRes$60).foo\n//│  B => (selRes$60).foo } in case selRes$58 of { Y => (selRes$58).bar\n//│  X => (selRes$58).bar }\n//│  let selRes$64 = let selRes$66 = foo(false,) in case selRes$66 of { B => (selRes$66).foo\n//│  A => (selRes$66).foo } in case selRes$64 of { X => (selRes$64).bar\n//│  Y => (selRes$64).bar }}\n//│ End simpledef\n//│ \n//│ x\n//│   = A {}\n//│ res\n//│     = false\n//│ res\n//│     = 5\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/ObjsSelection.mls",
    "content": ":NewDefs\n\nclass X() {\n    val num = 6\n}\nclass Y() {\n    val num = true\n}\nfun foo(pred) = if pred then X() else Y()\nfun id(x) = x\nval a = foo(true)\nval b = id(a)\nb.num\n//│ class X() {\n//│   val num: 6\n//│ }\n//│ class Y() {\n//│   val num: true\n//│ }\n//│ fun foo: Bool -> (X | Y)\n//│ fun id: forall 'a. 'a -> 'a\n//│ val a: X | Y\n//│ val b: X | Y\n//│ 6 | true\n//│ \n//│ Simpledef:\n//│ {class X() {let num = 6}\n//│  class Y() {let num = true}\n//│  fun foo = (pred::0,) => if (pred) then X() else Y()\n//│  fun id = (x::1,) => x\n//│  let a = foo(true,)\n//│  let b = id(a,)\n//│  let selRes$48 = b in case selRes$48 of { Y => (selRes$48).num\n//│  X => (selRes$48).num }}\n//│ End simpledef\n//│ \n//│ a\n//│   = X {}\n//│ b\n//│   = X {}\n//│ res\n//│     = 6\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/OldMonoList.mls",
    "content": ":NewDefs\n\nclass List(val e: Int, val tail: List | Nil) {\n  fun map: (Int -> Int) -> List \n  fun map(f)= List(f(e), tail.map(f))\n  fun count(): Int\n  fun count() = 1 + tail.count()\n}\nclass Nil() {\n  fun map(f) = Nil()\n  fun count() = 0\n}\nfun add2(x) = x+2\n(List(1, List(2, Nil()))).map(x => x+1).map(x => add2(x))\n//│ class List(e: Int, tail: List | Nil) {\n//│   fun count: () -> Int\n//│   fun map: (Int -> Int) -> List\n//│ }\n//│ class Nil() {\n//│   fun count: () -> 0\n//│   fun map: anything -> Nil\n//│ }\n//│ fun add2: Int -> Int\n//│ List\n//│ \n//│ Simpledef:\n//│ {class List(val e: Int, val tail: |(List, Nil,),) {fun map: (Int -> Int) -> List\n//│  fun map = (f::0,) => List(f(e,), let selRes$16 = tail in case selRes$16 of { List => (selRes$16).map(f,)\n//│  Nil => (selRes$16).map(f,) },)\n//│  fun count: () -> Int\n//│  fun count = () => +(1, let selRes$38 = tail in case selRes$38 of { List => (selRes$38).count()\n//│  Nil => (selRes$38).count() },)}\n//│  class Nil() {fun map = (f::1,) => Nil()\n//│  fun count = () => 0}\n//│  fun add2 = (x::2,) => +(x, 2,)\n//│  let selRes$82 = let selRes$84 = '(' List(1, List(2, Nil(),),) ')' in case selRes$84 of { List => (selRes$84).map((x::3,) => +(x, 1,),) } in case selRes$82 of { List => (selRes$82).map((x::4,) => add2(x,),) }}\n//│ End simpledef\n//│ \n//│ res\n//│     = List {}\n\nclass List(val e: Int, val tail: List | Nil) {\n  fun count(): Int\n  fun count() = 1 + tail.count()\n}\nclass Nil() {\n  fun count() = 0\n}\nfun foo(x) = x.count()\nfun generate(x) = \n  if x > 0 then List(x, generate(x-1)) else Nil()\nfoo(List(1, List(2, Nil())))\nfoo(generate(50))\n//│ class List(e: Int, tail: List | Nil) {\n//│   fun count: () -> Int\n//│ }\n//│ class Nil() {\n//│   fun count: () -> 0\n//│ }\n//│ fun foo: forall 'a. {count: () -> 'a} -> 'a\n//│ fun generate: Int -> (List | Nil)\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class List(val e: Int, val tail: |(List, Nil,),) {fun count: () -> Int\n//│  fun count = () => +(1, let selRes$10 = tail in case selRes$10 of { List => (selRes$10).count()\n//│  Nil => (selRes$10).count() },)}\n//│  class Nil() {fun count = () => 0}\n//│  fun foo = (x::5,) => let selRes$32 = x in case selRes$32 of { Nil => (selRes$32).count()\n//│  List => (selRes$32).count() }\n//│  fun generate = (x::6,) => {if (>(x, 0,)) then List(x, generate(-(x, 1,),),) else Nil()}\n//│  foo(List(1, List(2, Nil(),),),)\n//│  foo(generate(50,),)}\n//│ End simpledef\n//│ \n//│ res\n//│     = 2\n//│ res\n//│     = 50\n\nclass Cons(val e: 'A, val tail: Cons | Nil) {\n  fun count(): Int\n  fun count() = 1 + tail.count()\n}\nclass Nil() {\n  fun count() = 0\n}\nclass Lambda(){\n  fun apply(l) = \n    l.count()\n}\nclass Lambda2(val a: Int){\n  fun apply(l) = \n    ( Cons(a, l)).count()\n}\nfun foo(x) = \n  x.apply(Cons(1, Nil())) + x.apply(Nil())\nfoo(Lambda())\nfoo(Lambda2(2))\n//│ class Cons(e: nothing, tail: Cons | Nil) {\n//│   fun count: () -> Int\n//│ }\n//│ class Nil() {\n//│   fun count: () -> 0\n//│ }\n//│ class Lambda() {\n//│   fun apply: forall 'a. {count: () -> 'a} -> 'a\n//│ }\n//│ class Lambda2(a: Int) {\n//│   fun apply: (Cons | Nil) -> Int\n//│ }\n//│ fun foo: {apply: (Cons | Nil) -> Int} -> Int\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class Cons(val e: 'A, val tail: |(Cons, Nil,),) {fun count: () -> Int\n//│  fun count = () => +(1, let selRes$10 = tail in case selRes$10 of { Cons => (selRes$10).count()\n//│  Nil => (selRes$10).count() },)}\n//│  class Nil() {fun count = () => 0}\n//│  class Lambda() {fun apply = (l::7,) => {let selRes$32 = l in case selRes$32 of { Cons => (selRes$32).count()\n//│  Nil => (selRes$32).count() }}}\n//│  class Lambda2(val a: Int,) {fun apply = (l::8,) => {let selRes$48 = '(' Cons(a, l,) ')' in case selRes$48 of { Cons => (selRes$48).count() }}}\n//│  fun foo = (x::9,) => {+(let selRes$74 = x in case selRes$74 of { Lambda2 => (selRes$74).apply(Cons(1, Nil(),),)\n//│  Lambda => (selRes$74).apply(Cons(1, Nil(),),) }, let selRes$96 = x in case selRes$96 of { Lambda2 => (selRes$96).apply(Nil(),)\n//│  Lambda => (selRes$96).apply(Nil(),) },)}\n//│  foo(Lambda(),)\n//│  foo(Lambda2(2,),)}\n//│ End simpledef\n//│ \n//│ res\n//│     = 1\n//│ res\n//│     = 3\n\nclass Cons(val e: Int, val tail: Cons | Nil) {\n  fun count(): Int\n  fun count() = 1 + tail.count()\n}\nclass Nil() {\n  fun count() = 0\n}\nfun foo(x) = \n  x(Cons(1, Nil())) + x(Nil())\nfoo(l => l.count())\nfoo(l => (Cons(2, l)).count())\n//│ class Cons(e: Int, tail: Cons | Nil) {\n//│   fun count: () -> Int\n//│ }\n//│ class Nil() {\n//│   fun count: () -> 0\n//│ }\n//│ fun foo: ((Cons | Nil) -> Int) -> Int\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class Cons(val e: Int, val tail: |(Cons, Nil,),) {fun count: () -> Int\n//│  fun count = () => +(1, let selRes$10 = tail in case selRes$10 of { Cons => (selRes$10).count()\n//│  Nil => (selRes$10).count() },)}\n//│  class Nil() {fun count = () => 0}\n//│  fun foo = (x::10,) => {+(x(Cons(1, Nil(),),), x(Nil(),),)}\n//│  foo((l::11,) => let selRes$78 = l in case selRes$78 of { Cons => (selRes$78).count()\n//│  Nil => (selRes$78).count() },)\n//│  foo((l::12,) => let selRes$96 = '(' Cons(2, l,) ')' in case selRes$96 of { Cons => (selRes$96).count() },)}\n//│ End simpledef\n//│ \n//│ res\n//│     = 1\n//│ res\n//│     = 3\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Polymorphic.mls",
    "content": ":NewDefs\n\nlet b = true\nclass OneInt(val a: Int){\n  fun get = () -> a\n}\nclass OneBool(val b: Bool){\n  fun get = () -> b\n}\n(if b then OneInt(1) else OneBool(true)).get()\n//│ let b: true\n//│ class OneInt(a: Int) {\n//│   fun get: () -> Int\n//│ }\n//│ class OneBool(b: Bool) {\n//│   fun get: () -> Bool\n//│ }\n//│ Int | false | true\n//│ \n//│ Simpledef:\n//│ {let b = true\n//│  class OneInt(val a: Int,) {fun get = () => a}\n//│  class OneBool(val b: Bool,) {fun get = () => b}\n//│  let selRes$20 = '(' if (b) then OneInt(1,) else OneBool(true,) ')' in case selRes$20 of { OneInt => (selRes$20).get()\n//│  OneBool => (selRes$20).get() }}\n//│ End simpledef\n//│ \n//│ b\n//│   = true\n//│ res\n//│     = 1\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Record.mls",
    "content": ":NewDefs\n\n\nclass K() {\n    val f = true\n}\nval x = {\n    5: \"five\",\n    7: \"seven\",\n    f: 6\n}\nfun muddle(pred) = if pred then K() else x\nmuddle(false).f\n//│ class K() {\n//│   val f: true\n//│ }\n//│ val x: {5: \"five\", 7: \"seven\", f: 6}\n//│ fun muddle: Bool -> (K | {5: \"five\", 7: \"seven\", f: 6})\n//│ 6 | true\n//│ \n//│ Simpledef:\n//│ {class K() {let f = true}\n//│  let x = '{' {5: \"five\", 7: \"seven\", f: 6} '}'\n//│  fun muddle = (pred::0,) => if (pred) then K() else x\n//│  (muddle(false,)).f}\n//│ End simpledef\n//│ \n//│ x\n//│   = { '5': 'five', '7': 'seven', f: 6 }\n//│ res\n//│     = 6\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/RecursiveFunc.mls",
    "content": ":NewDefs\n\nfun fac(n) = \n  if (n > 1) then fac(n - 1) * n else 1\nfac(5)\n//│ fun fac: Int -> Int\n//│ Int\n//│ \n//│ Simpledef:\n//│ {fun fac = (n::0,) => {if ('(' >(n, 1,) ')') then *(fac(-(n, 1,),), n,) else 1}\n//│  fac(5,)}\n//│ End simpledef\n//│ \n//│ res\n//│     = 120\n\n// TODO: Support for specialized pattern matching types\n// In this example, the type of l in count(l) would need to be constrained to\n// object & ~(), which requires implementing neg types, intersections, etc.\nclass List(val l: List | Nil | undefined, val hasTail: Bool)  {}\nclass Nil(val l: List | Nil | undefined, val hasTail: Bool)  {}\nfun count(lst) =\n  if lst.hasTail then\n    let l = lst.l\n    if l is undefined then 1 else count(l)+1\n  else 0\ncount(new List(new List(new Nil(undefined, false), true), true))\n//│ class List(l: List | Nil | (), hasTail: Bool)\n//│ class Nil(l: List | Nil | (), hasTail: Bool)\n//│ fun count: forall 'a. 'a -> Int\n//│ Int\n//│ where\n//│   'a <: {hasTail: Bool, l: Object & 'a & ~() | ()}\n//│ \n//│ Simpledef:\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Could not constrain (ProdObj(Some(Var(prim$Unit)),List(),List()),ConsObj(None,List((Var(l),ConsVar(15,13_selres)))))\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/SelfReference.mls",
    "content": ":NewDefs\n:AllowRuntimeErrors\n\nfun f(x) = f(x)\nf(0)\nf(1)\n//│ fun f: anything -> nothing\n//│ nothing\n//│ \n//│ Simpledef:\n//│ {fun f = (x::0,) => f(x,)\n//│  f(0,)\n//│  f(1,)}\n//│ End simpledef\n//│ \n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/SimpleClasses.mls",
    "content": ":NewDefs\n\nclass Foo(val x: Int){\n  fun bar(y) = x+y\n  fun boo(z) = bar(z)+x\n}\n(Foo(1)).boo(2)\n//│ class Foo(x: Int) {\n//│   fun bar: Int -> Int\n//│   fun boo: Int -> Int\n//│ }\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class Foo(val x: Int,) {fun bar = (y::0,) => +(x, y,)\n//│  fun boo = (z::1,) => +(bar(z,), x,)}\n//│  let selRes$38 = '(' Foo(1,) ')' in case selRes$38 of { Foo => (selRes$38).boo(2,) }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 4\n\nclass OneInt(val a: Int){\n  fun fac: () -> Int\n  fun fac = () ->\n    if(a > 0) then (OneInt(a - 1)).fac() else 1 \n}\n(OneInt(10)).fac()\n//│ class OneInt(a: Int) {\n//│   fun fac: () -> Int\n//│ }\n//│ Int\n//│ \n//│ Simpledef:\n//│ {class OneInt(val a: Int,) {fun fac: () -> Int\n//│  fun fac = () => {if ('(' >(a, 0,) ')') then let selRes$20 = '(' OneInt(-(a, 1,),) ')' in case selRes$20 of { OneInt => (selRes$20).fac() } else 1}}\n//│  let selRes$50 = '(' OneInt(10,) ')' in case selRes$50 of { OneInt => (selRes$50).fac() }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 1\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/SimpleConditionals.mls",
    "content": ":NewDefs\nif true then 1 else 0\nif 1+1 > 1 then 1 - 1 else 1*1\n//│ Int\n//│ \n//│ Simpledef:\n//│ {if (true) then 1 else 0\n//│  if (>(+(1, 1,), 1,)) then -(1, 1,) else *(1, 1,)}\n//│ End simpledef\n//│ \n//│ res\n//│     = 1\n//│ res\n//│     = 0\n\nlet b = true\nif(b) then 1 else 2\n//│ let b: true\n//│ 1 | 2\n//│ \n//│ Simpledef:\n//│ {let b = true\n//│  if ('(' b ')') then 1 else 2}\n//│ End simpledef\n//│ \n//│ b\n//│   = true\n//│ res\n//│     = 1\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/SimpleFunc.mls",
    "content": ":NewDefs\n\nfun f(x: Bool) = if x then 42 else 1337\n//│ fun f: (x: Bool) -> (1337 | 42)\n//│ \n//│ Simpledef:\n//│ {fun f = (x: Bool,) => if (x) then 42 else 1337}\n//│ End simpledef\n//│ \n\nfun foo() = 42\n//│ fun foo: () -> 42\n//│ \n//│ Simpledef:\n//│ {fun foo = () => 42}\n//│ End simpledef\n//│ \n\nfun f(x) =\n  if(x > 0) then x+1 else x - 1\nf(2)+3\n//│ fun f: Int -> Int\n//│ Int\n//│ \n//│ Simpledef:\n//│ {fun f = (x::0,) => {if ('(' >(x, 0,) ')') then +(x, 1,) else -(x, 1,)}\n//│  +(f(2,), 3,)}\n//│ End simpledef\n//│ \n//│ res\n//│     = 6\n\nfun foo(x, #b) = if b then x else 1337\nlet a = foo(42, true)\nlet b = foo(23, false)\n//│ fun foo: forall 'a. ('a, Bool) -> (1337 | 'a)\n//│ let a: 1337 | 42\n//│ let b: 1337 | 23\n//│ \n//│ Simpledef:\n//│ {fun foo = (x::1, #b::2,) => if (b) then x else 1337\n//│  let a = foo(42, true,)\n//│  let b = foo(23, false,)}\n//│ End simpledef\n//│ \n//│ a\n//│   = 42\n//│ b\n//│   = 1337\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/Simpledef.mls",
    "content": ":NewDefs\n\nclass X() {\n    val num = 6\n}\nclass Y() {\n    val num = true\n}\nfun foo(pred) = if pred then X() else Y()\nfoo(true).num\n//│ class X() {\n//│   val num: 6\n//│ }\n//│ class Y() {\n//│   val num: true\n//│ }\n//│ fun foo: Bool -> (X | Y)\n//│ 6 | true\n//│ \n//│ Simpledef:\n//│ {class X() {let num = 6}\n//│  class Y() {let num = true}\n//│  fun foo = (pred::0,) => if (pred) then X() else Y()\n//│  let selRes$26 = foo(true,) in case selRes$26 of { Y => (selRes$26).num\n//│  X => (selRes$26).num }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 6\n\nclass X() {\n    val num = 6\n}\nclass Y() {\n    val num = true\n}\nclass A() {\n    val num = X()\n}\nclass B() {\n    val num = Y()\n}\nclass C() {\n    val num = X()\n}\nfun foo(pred) =\n    if pred == 1 then A() else \n        if pred == 2 then B() else C()\nfoo(5).num.num\n//│ class X() {\n//│   val num: 6\n//│ }\n//│ class Y() {\n//│   val num: true\n//│ }\n//│ class A() {\n//│   val num: X\n//│ }\n//│ class B() {\n//│   val num: Y\n//│ }\n//│ class C() {\n//│   val num: X\n//│ }\n//│ fun foo: Num -> (A | B | C)\n//│ 6 | true\n//│ \n//│ Simpledef:\n//│ {class X() {let num = 6}\n//│  class Y() {let num = true}\n//│  class A() {let num = X()}\n//│  class B() {let num = Y()}\n//│  class C() {let num = X()}\n//│  fun foo = (pred::1,) => {if (==(pred, 1,)) then A() else {if (==(pred, 2,)) then B() else C()}}\n//│  let selRes$74 = let selRes$76 = foo(5,) in case selRes$76 of { B => (selRes$76).num\n//│  C => (selRes$76).num\n//│  A => (selRes$76).num } in case selRes$74 of { X => (selRes$74).num\n//│  Y => (selRes$74).num }}\n//│ End simpledef\n//│ \n//│ res\n//│     = 6\n"
  },
  {
    "path": "compiler/shared/test/diff/Defunctionalize/TupleSelect.mls",
    "content": ":NewDefs\n\n\n[0,\"abc\",()].2\n//│ ()\n//│ \n//│ Simpledef:\n//│ {([0, \"abc\", undefined,]).2}\n//│ End simpledef\n//│ \n//│ res\n//│     = undefined\n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/FunctionTypeAnnotations.mls",
    "content": ":NewDefs \n:ParseOnly\n\n:lift\nfun foo(x) =\n    (y) => x+y\nfoo(1)(2)\nfoo(2)(2)\n//│ |#fun| |foo|(|x|)| |#=|→|(|y|)| |#=>| |x|+|y|←|↵|foo|(|1|)|(|2|)|↵|foo|(|2|)|(|2|)|\n//│ Parsed: {fun foo = (x,) => {('(' y ')',) => +(x, y,)}; foo(1,)(2,); foo(2,)(2,)}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Lambda1$2$1([x,]) {fun apply = ('(' y ')',) => +((this).x, y,)}\n//│   fun foo$1 = (x,) => {{Lambda1$2$1(x,)}}\n//│   Code(List(foo$1(1,)(2,)))\n//│   Code(List(foo$1(2,)(2,)))\n//│ }\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/LambLift.mls",
    "content": ":NewDefs\n:ParseOnly\n\n:lift\nfun foo() =\n  let local(x) =\n    class Foo {\n      fun bar = x + foo()\n    }\n    (new Foo()).bar\n  local(1)\nfoo()\n//│ |#fun| |foo|(||)| |#=|→|#let| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |foo|(||)|←|↵|}|↵|(|#new| |Foo|(||)|)|.bar|←|↵|local|(|1|)|←|↵|foo|(||)|\n//│ Parsed: {fun foo = () => {let local = (x,) => {class Foo {fun bar = +(x, foo(),)}; ('(' (new Foo)() ')').bar}; local(1,)}; foo()}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Foo$1([x,]) {fun bar = +((this).x, foo$1(),)}\n//│   let local$2 = (x,) => {('(' (new Foo$1)(x,) ')').bar}\n//│   fun foo$1 = () => {local$2(1,)}\n//│   Code(List(foo$1()))\n//│ }\n//│ \n\n:lift\nfun foo(f) = \n  f(1)\nfoo(x => x+1)\n//│ |#fun| |foo|(|f|)| |#=| |→|f|(|1|)|←|↵|foo|(|x| |#=>| |x|+|1|)|\n//│ Parsed: {fun foo = (f,) => {f(1,)}; foo((x,) => +(x, 1,),)}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Lambda1$2$1([]) {fun apply = (x,) => +(x, 1,)}\n//│   fun foo$1 = (f,) => {f(1,)}\n//│   Code(List(foo$1({Lambda1$2$1()},)))\n//│ }\n//│ \n\n:lift\nfun foo(x) = \n  let bar(f) = \n    f(x)\n  bar(y => y+x)\nfoo(1)\n//│ |#fun| |foo|(|x|)| |#=| |→|#let| |bar|(|f|)| |#=| |→|f|(|x|)|←|↵|bar|(|y| |#=>| |y|+|x|)|←|↵|foo|(|1|)|\n//│ Parsed: {fun foo = (x,) => {let bar = (f,) => {f(x,)}; bar((y,) => +(y, x,),)}; foo(1,)}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Lambda1$3$1([x,]) {fun apply = (y,) => +(y, (this).x,)}\n//│   let bar$2 = (f, x,) => {f(x,)}\n//│   fun foo$1 = (x,) => {bar$2({Lambda1$3$1(x,)}, x,)}\n//│   Code(List(foo$1(1,)))\n//│ }\n//│ \n\n:lift\nfun foo(f) = \n    f(1)\nclass A(y: Int){\n  fun bar(z) = y+z\n}\nfun app(a) = \n  foo(z => a.bar(z))\napp(new A(1))\n//│ |#fun| |foo|(|f|)| |#=| |→|f|(|1|)|←|↵|#class| |A|(|y|#:| |Int|)|{|→|#fun| |bar|(|z|)| |#=| |y|+|z|←|↵|}|↵|#fun| |app|(|a|)| |#=| |→|foo|(|z| |#=>| |a|.bar|(|z|)|)|←|↵|app|(|#new| |A|(|1|)|)|\n//│ Parsed: {fun foo = (f,) => {f(1,)}; class A(y: Int,) {fun bar = (z,) => +(y, z,)}; fun app = (a,) => {foo((z,) => (a).bar(z,),)}; app((new A)(1,),)}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([y: Int,]) {fun bar = (z,) => +((this).y, z,)}\n//│   class Lambda1$3$2([a,]) {fun apply = (z,) => ((this).a).bar(z,)}\n//│   fun foo$2 = (f,) => {f(1,)}\n//│   fun app$1 = (a,) => {foo$2({Lambda1$3$2(a,)},)}\n//│   Code(List(app$1((new A$1)(1,),)))\n//│ }\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/LiftNew.mls",
    "content": ":NewDefs\n\n:lift\nclass A(num: Int) {\n}\nnew A(5)\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([num: Int,]) {}\n//│   Code(List((new A$1)(5,)))\n//│ }\n//│ class A$1(num: Int)\n//│ A$1\n//│ res\n//│     = A$1 {}\n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/LiftType.mls",
    "content": ":NewDefs\n:ParseOnly\n\n:lift\nclass CTX{\n  class A {}\n  fun foo(f: A => A): (A => A) => A = f(new A)\n}\n//│ |#class| |CTX|{|→|#class| |A| |{||}|↵|#fun| |foo|(|f|#:| |A| |#=>| |A|)|#:| |(|A| |#=>| |A|)| |#=>| |A| |#=| |f|(|#new| |A|)|←|↵|}|\n//│ Parsed: {class CTX {class A {}; fun foo = (f: (A,) => A,) => f(new A,) : (A -> A) -> A}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class CTX$1_A$2([par$CTX$1,]) {}\n//│   class CTX$1([]) {\n//│     fun foo = (f: (CTX$1_A$2,) => CTX$1_A$2,) => f((new CTX$1_A$2)(this,),) : (CTX$1_A$2 -> CTX$1_A$2) -> CTX$1_A$2\n//│   }\n//│ }\n//│ \n\n:lift\nclass CTX(x, y){\n  class A{ fun foo = x}\n  class B: A { fun foo = y}\n  fun foo(any: [A, B]): [B, A] = [any._2, any._1]\n}\n//│ |#class| |CTX|(|x|,| |y|)|{|→|#class| |A|{| |#fun| |foo| |#=| |x|}|↵|#class| |B|#:| |A| |{| |#fun| |foo| |#=| |y|}|↵|#fun| |foo|(|any|#:| |[|A|,| |B|]|)|#:| |[|B|,| |A|]| |#=| |[|any|._2|,| |any|._1|]|←|↵|}|\n//│ Parsed: {class CTX(x, y,) {class A {fun foo = x}; class B: A {fun foo = y}; fun foo = (any: [A, B,],) => [(any)._2, (any)._1,] : [B, A]}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class CTX$1_A$2([par$CTX$1,]) {fun foo = ((this).par$CTX$1).x}\n//│   class CTX$1_B$3([par$CTX$1,]) {fun foo = ((this).par$CTX$1).y}\n//│   class CTX$1([x, y,]) {\n//│     fun foo = (any: [CTX$1_A$2, CTX$1_B$3,],) => [(any)._2, (any)._1,] : [CTX$1_B$3, CTX$1_A$2]\n//│   }\n//│ }\n//│ \n\n:lift\nclass CTX(x, y){\n  class A{ fun foo = x}\n  class B: A { fun foo = y}\n  fun foo(any: {p1: A, p2: B}): [B, A] = [any.p2, any.p1]\n}\n//│ |#class| |CTX|(|x|,| |y|)|{|→|#class| |A|{| |#fun| |foo| |#=| |x|}|↵|#class| |B|#:| |A| |{| |#fun| |foo| |#=| |y|}|↵|#fun| |foo|(|any|#:| |{|p1|#:| |A|,| |p2|#:| |B|}|)|#:| |[|B|,| |A|]| |#=| |[|any|.p2|,| |any|.p1|]|←|↵|}|\n//│ Parsed: {class CTX(x, y,) {class A {fun foo = x}; class B: A {fun foo = y}; fun foo = (any: '{' {p1: A, p2: B} '}',) => [(any).p2, (any).p1,] : [B, A]}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class CTX$1_A$2([par$CTX$1,]) {fun foo = ((this).par$CTX$1).x}\n//│   class CTX$1_B$3([par$CTX$1,]) {fun foo = ((this).par$CTX$1).y}\n//│   class CTX$1([x, y,]) {\n//│     fun foo = (any: '{' {p1: CTX$1_A$2, p2: CTX$1_B$3} '}',) => [(any).p2, (any).p1,] : [CTX$1_B$3, CTX$1_A$2]\n//│   }\n//│ }\n//│ \n\n:lift\nclass CTX(x, y){\n  class A{ fun foo = x}\n  class B<T> { fun foo = y}\n  fun foo(any: [A, B<A>]): [[B<A>, A], A] = [any, any._1]\n}\n//│ |#class| |CTX|(|x|,| |y|)|{|→|#class| |A|{| |#fun| |foo| |#=| |x|}|↵|#class| |B|‹|T|›| |{| |#fun| |foo| |#=| |y|}|↵|#fun| |foo|(|any|#:| |[|A|,| |B|‹|A|›|]|)|#:| |[|[|B|‹|A|›|,| |A|]|,| |A|]| |#=| |[|any|,| |any|._1|]|←|↵|}|\n//│ Parsed: {class CTX(x, y,) {class A {fun foo = x}; class B‹T› {fun foo = y}; fun foo = (any: [A, B‹A›,],) => [any, (any)._1,] : [[B[A], A], A]}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class CTX$1_A$2([par$CTX$1,]) {fun foo = ((this).par$CTX$1).x}\n//│   class CTX$1_B$3[T]([par$CTX$1,]) {fun foo = ((this).par$CTX$1).y}\n//│   class CTX$1([x, y,]) {\n//│     fun foo = (any: [CTX$1_A$2, CTX$1_B$3‹CTX$1_A$2›,],) => [any, (any)._1,] : [[CTX$1_B$3[CTX$1_A$2], CTX$1_A$2], CTX$1_A$2]\n//│   }\n//│ }\n//│ \n\n:lift\nclass CTX{\n  fun ctx(x,y) = \n    class A{ fun foo = x }\n    fun bar<T>(any: T): A = \n      let x = new T\n      new A\n    (new CTX).bar<CTX>\n}\n//│ |#class| |CTX|{|→|#fun| |ctx|(|x|,|y|)| |#=| |→|#class| |A|{| |#fun| |foo| |#=| |x| |}|↵|#fun| |bar|‹|T|›|(|any|#:| |T|)|#:| |A| |#=| |→|#let| |x| |#=| |#new| |T|↵|#new| |A|←|↵|(|#new| |CTX|)|.bar|‹|CTX|›|←|←|↵|}|\n//│ Parsed: {class CTX {fun ctx = (x, y,) => {class A {fun foo = x}; fun bar = (any: T,) => {let x = new T; new A} : A; ('(' new CTX ')').bar‹CTX›}}}\n//│ Lifted:\n//│ Lifting failed: mlscript.codegen.CodeGenError: Cannot find type T. Class values are not supported in lifter. \n//│ \n\n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/Lifter.mls",
    "content": ":NewDefs\n:ParseOnly\n\n:lift\nclass A(x) {\n  class B(y) {\n    fun getX = x\n    fun getB1 = B1(y)\n    class C(z) {\n      fun inc() = x + 1\n      fun getY = y\n      fun getA = A(z)\n      fun getB(w) = B(w)\n      fun getC = new C(inc())\n      fun getSelf = this\n    }\n  }\n  class B1(y) {\n    fun getX = x\n    fun getY = y\n    fun getB = new B(y)\n    fun getB1 = new B1(y)\n  }\n  fun getB = new B(x)\n  fun getB2(y) = B1(y)\n  fun getB3(z) = getB2(z)\n  fun getA = A(x)\n}\n//│ |#class| |A|(|x|)| |{|→|#class| |B|(|y|)| |{|→|#fun| |getX| |#=| |x|↵|#fun| |getB1| |#=| |B1|(|y|)|↵|#class| |C|(|z|)| |{|→|#fun| |inc|(||)| |#=| |x| |+| |1|↵|#fun| |getY| |#=| |y|↵|#fun| |getA| |#=| |A|(|z|)|↵|#fun| |getB|(|w|)| |#=| |B|(|w|)|↵|#fun| |getC| |#=| |#new| |C|(|inc|(||)|)|↵|#fun| |getSelf| |#=| |this|←|↵|}|←|↵|}|↵|#class| |B1|(|y|)| |{|→|#fun| |getX| |#=| |x|↵|#fun| |getY| |#=| |y|↵|#fun| |getB| |#=| |#new| |B|(|y|)|↵|#fun| |getB1| |#=| |#new| |B1|(|y|)|←|↵|}|↵|#fun| |getB| |#=| |#new| |B|(|x|)|↵|#fun| |getB2|(|y|)| |#=| |B1|(|y|)|↵|#fun| |getB3|(|z|)| |#=| |getB2|(|z|)|↵|#fun| |getA| |#=| |A|(|x|)|←|↵|}|\n//│ Parsed: {class A(x,) {class B(y,) {fun getX = x; fun getB1 = B1(y,); class C(z,) {fun inc = () => +(x, 1,); fun getY = y; fun getA = A(z,); fun getB = (w,) => B(w,); fun getC = (new C)(inc(),); fun getSelf = this}}; class B1(y,) {fun getX = x; fun getY = y; fun getB = (new B)(y,); fun getB1 = (new B1)(y,)}; fun getB = (new B)(x,); fun getB2 = (y,) => B1(y,); fun getB3 = (z,) => getB2(z,); fun getA = A(x,)}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2_C$4([par$A$1_B$2, z, x,]) {\n//│     fun inc = () => +((this).x, 1,)\n//│     fun getY = ((this).par$A$1_B$2).y\n//│     fun getA = A$1((this).z,)\n//│     fun getB = (w,) => A$1_B$2(((this).par$A$1_B$2).par$A$1, w,)\n//│     fun getC = (new A$1_B$2_C$4)((this).par$A$1_B$2, (this).inc(), (this).x,)\n//│     fun getSelf = this\n//│   }\n//│   class A$1_B$2([par$A$1, y,]) {\n//│     fun getX = ((this).par$A$1).x\n//│     fun getB1 = A$1_B1$3((this).par$A$1, (this).y,)\n//│   }\n//│   class A$1_B1$3([par$A$1, y,]) {\n//│     fun getX = ((this).par$A$1).x\n//│     fun getY = (this).y\n//│     fun getB = (new A$1_B$2)((this).par$A$1, (this).y,)\n//│     fun getB1 = (new A$1_B1$3)((this).par$A$1, (this).y,)\n//│   }\n//│   class A$1([x,]) {\n//│     fun getB = (new A$1_B$2)(this, (this).x,)\n//│     fun getB2 = (y,) => A$1_B1$3(this, y,)\n//│     fun getB3 = (z,) => (this).getB2(z,)\n//│     fun getA = A$1((this).x,)\n//│   }\n//│ }\n//│ \n\n:lift\nclass A(x) {\n  class B(y) {\n    class C(z) {\n      fun sum = x + y + z\n    }\n  }\n}\n//│ |#class| |A|(|x|)| |{|→|#class| |B|(|y|)| |{|→|#class| |C|(|z|)| |{|→|#fun| |sum| |#=| |x| |+| |y| |+| |z|←|↵|}|←|↵|}|←|↵|}|\n//│ Parsed: {class A(x,) {class B(y,) {class C(z,) {fun sum = +(+(x, y,), z,)}}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2_C$3([par$A$1_B$2, z, x,]) {\n//│     fun sum = +(+((this).x, ((this).par$A$1_B$2).y,), (this).z,)\n//│   }\n//│   class A$1_B$2([par$A$1, y,]) {}\n//│   class A$1([x,]) {}\n//│ }\n//│ \n\n:lift\nclass A(x) {\n  class B{\n    fun foo = 1\n    fun bar = 11\n  }\n  fun getB = new B{\n    fun foo = 2\n    fun bar = 12\n  }\n  fun bar = 13\n}\nclass C: A{\n  fun getB = new B{\n    fun foo = 3\n    fun bar = 14\n  }\n  fun bar = 15\n}\nnew C{\n  fun getB = new B{\n    fun foo = 4\n    fun bar = 16\n  }\n  fun bar = 17\n}\n//│ |#class| |A|(|x|)| |{|→|#class| |B|{|→|#fun| |foo| |#=| |1|↵|#fun| |bar| |#=| |11|←|↵|}|↵|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |2|↵|#fun| |bar| |#=| |12|←|↵|}|↵|#fun| |bar| |#=| |13|←|↵|}|↵|#class| |C|#:| |A|{|→|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |3|↵|#fun| |bar| |#=| |14|←|↵|}|↵|#fun| |bar| |#=| |15|←|↵|}|↵|#new| |C|{|→|#fun| |getB| |#=| |#new| |B|{|→|#fun| |foo| |#=| |4|↵|#fun| |bar| |#=| |16|←|↵|}|↵|#fun| |bar| |#=| |17|←|↵|}|\n//│ Parsed: {class A(x,) {class B {fun foo = 1; fun bar = 11}; fun getB = new B {fun foo = 2; fun bar = 12}; fun bar = 13}; class C: A {fun getB = new B {fun foo = 3; fun bar = 14}; fun bar = 15}; new C {fun getB = new B {fun foo = 4; fun bar = 16}; fun bar = 17}}\n//│ Lifted:\n//│ Lifting failed: mlscript.codegen.CodeGenError: Cannot find type B. Class values are not supported in lifter. \n//│ \n\n\n:lift\nclass Parent<T, U, V>(x) { \n  fun foo(x: Int): T = x+1\n  class Inner<W>(y: Int){\n    fun bar(z: U) = foo(y)\n    fun boo(z: W) = z\n  }\n}\n//│ |#class| |Parent|‹|T|,| |U|,| |V|›|(|x|)| |{| |→|#fun| |foo|(|x|#:| |Int|)|#:| |T| |#=| |x|+|1|↵|#class| |Inner|‹|W|›|(|y|#:| |Int|)|{|→|#fun| |bar|(|z|#:| |U|)| |#=| |foo|(|y|)|↵|#fun| |boo|(|z|#:| |W|)| |#=| |z|←|↵|}|←|↵|}|\n//│ Parsed: {class Parent‹T, U, V›(x,) {fun foo = (x: Int,) => +(x, 1,) : T; class Inner‹W›(y: Int,) {fun bar = (z: U,) => foo(y,); fun boo = (z: W,) => z}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Parent$1_Inner$2[W,U]([par$Parent$1, y: Int,]) {\n//│     fun bar = (z: U,) => ((this).par$Parent$1).foo((this).y,)\n//│     fun boo = (z: W,) => z\n//│   }\n//│   class Parent$1[T,U,V]([x,]) {fun foo = (x: Int,) => +(x, 1,) : T}\n//│ }\n//│ \n\n:lift\nclass B<T> {}\nclass C {}\nclass D(y: Int) {}\nclass A<T, U>(x: Int): ({a1: Int} & B<T> & D(x)) {\n  fun getA() = new C{\n    fun foo(x: T) = x\n  }\n}\n//│ |#class| |B|‹|T|›| |{||}|↵|#class| |C| |{||}|↵|#class| |D|(|y|#:| |Int|)| |{||}|↵|#class| |A|‹|T|,| |U|›|(|x|#:| |Int|)|#:| |(|{|a1|#:| |Int|}| |&| |B|‹|T|›| |&| |D|(|x|)|)| |{|→|#fun| |getA|(||)| |#=| |#new| |C|{|→|#fun| |foo|(|x|#:| |T|)| |#=| |x|←|↵|}|←|↵|}|\n//│ Parsed: {class B‹T› {}; class C {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): {a1: Int} & B[T] & D[x] {fun getA = () => new C {fun foo = (x: T,) => x}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class B$1[T]([]) {}\n//│   class C$2([]) {}\n//│   class D$3([y: Int,]) {}\n//│   class A$4[T,U]([x: Int,]) {fun getA = () => new C$2([]) {}}\n//│ }\n//│ \n// │ TypingUnit(NuTypeDef(class, B, (TypeName(T)), Tup(), (), TypingUnit()), NuTypeDef(class, C, (), Tup(), (), TypingUnit()), NuTypeDef(class, A, (TypeName(T), TypeName(U)), Tup(x: Var(Int)), (App(App(Var(&), Tup(_: Bra(rcd = true, Rcd(Var(a1) = Var(Int)})))), Tup(_: TyApp(Var(B), List(TypeName(T)))))), TypingUnit(NuFunDef(None, getA, [], Lam(Tup(), New(Some((TypeName(C),)), TypingUnit(List(fun foo = x: T, => x))))))))\n\n:lift\nclass B<T> {}\nclass C {}\nclass D(y: Int) {}\nclass A<T, U>(x: Int) extends {a1: Int}, B<T>, D(x){\n  fun getA() = new C{\n    fun foo(x) = x\n  }\n}\n//│ |#class| |B|‹|T|›| |{||}|↵|#class| |C| |{||}|↵|#class| |D|(|y|#:| |Int|)| |{||}|↵|#class| |A|‹|T|,| |U|›|(|x|#:| |Int|)| |#extends| |{|a1|#:| |Int|}|,| |B|‹|T|›|,| |D|(|x|)|{|→|#fun| |getA|(||)| |#=| |#new| |C|{|→|#fun| |foo|(|x|)| |#=| |x|←|↵|}|←|↵|}|\n//│ Parsed: {class B‹T› {}; class C {}; class D(y: Int,) {}; class A‹T, U›(x: Int,): '{' {a1: Int} '}', B‹T›, D(x,) {fun getA = () => new C {fun foo = (x,) => x}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class B$1[T]([]) {}\n//│   class C$2([]) {}\n//│   class D$3([y: Int,]) {}\n//│   class A$4[T,U]([x: Int,]): '{' {a1: Int} '}', B$1‹T›, D$3((this).x,) {fun getA = () => new C$2([]) {}}\n//│ }\n//│ \n\n:lift\nclass Child<T, U>(x): ({ age: T } & { name: String}) {\n  class Inner{\n    fun foo = age\n  }\n  fun bar = age\n  fun boo = new Inner\n}\n//│ |#class| |Child|‹|T|,| |U|›|(|x|)|#:| |(|{| |age|#:| |T| |}| |&| |{| |name|#:| |String|}|)| |{|→|#class| |Inner|{|→|#fun| |foo| |#=| |age|←|↵|}|↵|#fun| |bar| |#=| |age|↵|#fun| |boo| |#=| |#new| |Inner|←|↵|}|\n//│ Parsed: {class Child‹T, U›(x,): {age: T} & {name: String} {class Inner {fun foo = age}; fun bar = age; fun boo = new Inner}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Child$1_Inner$2([par$Child$1, age,]) {fun foo = (this).age}\n//│   class Child$1[T,U]([x,]) {\n//│     fun bar = age\n//│     fun boo = (new Child$1_Inner$2)(this, age,)\n//│   }\n//│ }\n//│ \n\n:lift\nclass A(x: Int) {\n  fun getA: Int = 0\n  fun getA1 = 1\n}\nnew A(0) {\n  fun getA = 3\n  fun getA2 = 2\n}\n//│ |#class| |A|(|x|#:| |Int|)| |{|→|#fun| |getA|#:| |Int| |#=| |0|↵|#fun| |getA1| |#=| |1|←|↵|}|↵|#new| |A|(|0|)| |{|→|#fun| |getA| |#=| |3|↵|#fun| |getA2| |#=| |2|←|↵|}|\n//│ Parsed: {class A(x: Int,) {fun getA = 0 : Int; fun getA1 = 1}; (new A)(0,) {fun getA = 3; fun getA2 = 2}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([x: Int,]) {fun getA = 0 : Int; fun getA1 = 1}\n//│   class A$1$2([x: Int,]): A$1((this).x,) {fun getA = 3; fun getA2 = 2}\n//│   Code(List({new A$1$2([0,]) {}}))\n//│ }\n//│ \n\n:lift\nclass A(x) {\n  class B(y) {  }\n}\nnew A(1) {\n  fun getB = new B(2){\n    fun getB = new B(3)\n  }\n}\n//│ |#class| |A|(|x|)| |{|→|#class| |B|(|y|)| |{| |}|←|↵|}|↵|#new| |A|(|1|)| |{|→|#fun| |getB| |#=| |#new| |B|(|2|)|{|→|#fun| |getB| |#=| |#new| |B|(|3|)|←|↵|}|←|↵|}|\n//│ Parsed: {class A(x,) {class B(y,) {}}; (new A)(1,) {fun getB = (new B)(2,) {fun getB = (new B)(3,)}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2([par$A$1, y,]) {}\n//│   class A$1([x,]) {}\n//│   class A$1$3_B$2$4([par$A$1$3, y,]): A$1_B$2((this).par$A$1$3, (this).y,) {fun getB = (new A$1_B$2)((this).par$A$1$3, 3,)}\n//│   class A$1$3([x,]): A$1((this).x,) {fun getB = {new A$1$3_B$2$4([this, 2,]) {}}}\n//│   Code(List({new A$1$3([1,]) {}}))\n//│ }\n//│ \n\n\n:lift\nclass A {\n  fun getA = 0\n  fun funcA = 10\n}\nclass B: A{\n  fun getA = 1\n  fun funcB = 11\n}\nnew A\nnew B\nfun f(x) = if x is A then 0 else 1\nf(new A{\n  fun getA = 2\n})\nnew B{\n  fun getA = funcB\n}\n//│ |#class| |A| |{|→|#fun| |getA| |#=| |0|↵|#fun| |funcA| |#=| |10|←|↵|}|↵|#class| |B|#:| |A|{|→|#fun| |getA| |#=| |1|↵|#fun| |funcB| |#=| |11|←|↵|}|↵|#new| |A|↵|#new| |B|↵|#fun| |f|(|x|)| |#=| |#if| |x| |is| |A| |#then| |0| |#else| |1|↵|f|(|#new| |A|{|→|#fun| |getA| |#=| |2|←|↵|}|)|↵|#new| |B|{|→|#fun| |getA| |#=| |funcB|←|↵|}|\n//│ Parsed: {class A {fun getA = 0; fun funcA = 10}; class B: A {fun getA = 1; fun funcB = 11}; new A; new B; fun f = (x,) => if (is(x, A,)) then 0 else 1; f(new A {fun getA = 2},); new B {fun getA = funcB}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([]) {fun getA = 0; fun funcA = 10}\n//│   class B$2([]) {fun getA = 1; fun funcB = 11}\n//│   fun f$1 = (x,) => if (is(x, A$1,)) then 0 else 1\n//│   Code(List((new A$1)()))\n//│   Code(List((new B$2)()))\n//│   Code(List(f$1(new A$1([]) {},)))\n//│   Code(List(new B$2([]) {}))\n//│ }\n//│ \n\n:lift\nclass A{\n  class B{\n    fun funB = 1\n    fun foo = 100\n  }\n  class C: B{\n    fun funC = 2\n    fun foo = 1000\n  }\n  class D{\n    fun funD = 3\n    fun foo = 10000    \n    class E: C{\n      fun funE = 4\n      fun foo = 100000\n    }\n    class F: E{\n      fun funF = 5\n      fun foo = 1000000\n    }\n  }\n}\n//│ |#class| |A|{|→|#class| |B|{|→|#fun| |funB| |#=| |1|↵|#fun| |foo| |#=| |100|←|↵|}|↵|#class| |C|#:| |B|{|→|#fun| |funC| |#=| |2|↵|#fun| |foo| |#=| |1000|←|↵|}|↵|#class| |D|{|→|#fun| |funD| |#=| |3|↵|#fun| |foo| |#=| |10000| |↵|#class| |E|#:| |C|{|→|#fun| |funE| |#=| |4|↵|#fun| |foo| |#=| |100000|←|↵|}|↵|#class| |F|#:| |E|{|→|#fun| |funF| |#=| |5|↵|#fun| |foo| |#=| |1000000|←|↵|}|←|↵|}|←|↵|}|\n//│ Parsed: {class A {class B {fun funB = 1; fun foo = 100}; class C: B {fun funC = 2; fun foo = 1000}; class D {fun funD = 3; fun foo = 10000; class E: C {fun funE = 4; fun foo = 100000}; class F: E {fun funF = 5; fun foo = 1000000}}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2([par$A$1,]) {fun funB = 1; fun foo = 100}\n//│   class A$1_C$3([par$A$1,]) {fun funC = 2; fun foo = 1000}\n//│   class A$1_D$4_E$5([par$A$1_D$4,]) {fun funE = 4; fun foo = 100000}\n//│   class A$1_D$4_F$6([par$A$1_D$4,]) {fun funF = 5; fun foo = 1000000}\n//│   class A$1_D$4([par$A$1,]) {fun funD = 3; fun foo = 10000}\n//│   class A$1([]) {}\n//│ }\n//│ \n\n:lift\nclass A{\n  class B{\n    fun funB = 1\n    fun foo = 100\n  }\n  class C: B{\n    fun funC = 2\n    fun foo = 1000\n    fun getB = new B\n  }\n  class D{\n    fun funD = 3\n    fun foo = 10000    \n    class E: C{\n      fun funE = 4\n      fun foo = 100000\n      fun getD = new D\n    }\n    class F: E{\n      fun funF = 5\n      fun foo = 1000000\n      fun getE = new E{\n        fun foo = 0\n      }\n    }\n  }\n}\n//│ |#class| |A|{|→|#class| |B|{|→|#fun| |funB| |#=| |1|↵|#fun| |foo| |#=| |100|←|↵|}|↵|#class| |C|#:| |B|{|→|#fun| |funC| |#=| |2|↵|#fun| |foo| |#=| |1000|↵|#fun| |getB| |#=| |#new| |B|←|↵|}|↵|#class| |D|{|→|#fun| |funD| |#=| |3|↵|#fun| |foo| |#=| |10000| |↵|#class| |E|#:| |C|{|→|#fun| |funE| |#=| |4|↵|#fun| |foo| |#=| |100000|↵|#fun| |getD| |#=| |#new| |D|←|↵|}|↵|#class| |F|#:| |E|{|→|#fun| |funF| |#=| |5|↵|#fun| |foo| |#=| |1000000|↵|#fun| |getE| |#=| |#new| |E|{|→|#fun| |foo| |#=| |0|←|↵|}|←|↵|}|←|↵|}|←|↵|}|\n//│ Parsed: {class A {class B {fun funB = 1; fun foo = 100}; class C: B {fun funC = 2; fun foo = 1000; fun getB = new B}; class D {fun funD = 3; fun foo = 10000; class E: C {fun funE = 4; fun foo = 100000; fun getD = new D}; class F: E {fun funF = 5; fun foo = 1000000; fun getE = new E {fun foo = 0}}}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2([par$A$1,]) {fun funB = 1; fun foo = 100}\n//│   class A$1_C$3([par$A$1,]) {\n//│     fun funC = 2\n//│     fun foo = 1000\n//│     fun getB = (new A$1_B$2)((this).par$A$1,)\n//│   }\n//│   class A$1_D$4_E$5([par$A$1_D$4,]) {\n//│     fun funE = 4\n//│     fun foo = 100000\n//│     fun getD = (new A$1_D$4)(((this).par$A$1_D$4).par$A$1,)\n//│   }\n//│   class A$1_D$4_F$6([par$A$1_D$4,]) {\n//│     fun funF = 5\n//│     fun foo = 1000000\n//│     fun getE = new A$1_D$4_E$5([(this).par$A$1_D$4,]) {}\n//│   }\n//│   class A$1_D$4([par$A$1,]) {fun funD = 3; fun foo = 10000}\n//│   class A$1([]) {}\n//│ }\n//│ \n\n:lift\nclass A{\n  class B{\n    fun foo = 1\n  }\n  fun bar = new B\n}\nnew A\n//│ |#class| |A|{|→|#class| |B|{|→|#fun| |foo| |#=| |1|←|↵|}|↵|#fun| |bar| |#=| |#new| |B|←|↵|}|↵|#new| |A|\n//│ Parsed: {class A {class B {fun foo = 1}; fun bar = new B}; new A}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2([par$A$1,]) {fun foo = 1}\n//│   class A$1([]) {fun bar = (new A$1_B$2)(this,)}\n//│   Code(List((new A$1)()))\n//│ }\n//│ \n\n:lift\nclass A(x) {\n  fun foo = 0\n  fun bar = x\n}\nlet x = new A{\n  fun foo = 1\n  fun newFun = 2\n  fun bar = new A(foo){\n    fun foo = bar + 1\n    fun bar2 = newFun + 1\n  }\n}\n//│ |#class| |A|(|x|)| |{|→|#fun| |foo| |#=| |0|↵|#fun| |bar| |#=| |x|←|↵|}|↵|#let| |x| |#=| |#new| |A|{|→|#fun| |foo| |#=| |1|↵|#fun| |newFun| |#=| |2|↵|#fun| |bar| |#=| |#new| |A|(|foo|)|{|→|#fun| |foo| |#=| |bar| |+| |1|↵|#fun| |bar2| |#=| |newFun| |+| |1|←|↵|}|←|↵|}|\n//│ Parsed: {class A(x,) {fun foo = 0; fun bar = x}; let x = new A {fun foo = 1; fun newFun = 2; fun bar = (new A)(foo,) {fun foo = +(bar, 1,); fun bar2 = +(newFun, 1,)}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([x,]) {fun foo = 0; fun bar = x$1}\n//│   let x$1 = new A$1([]) {}\n//│ }\n//│ \n\n:lift\nclass A {}\nnew A{\n  fun foo = 1\n  fun bar = new A{\n    fun foo1 = foo\n    fun bar1 = new A{\n      fun foo2 = foo\n      fun bar2 = new A{\n        fun foo3 = foo\n        fun bar3 = new A{\n          fun foo4 = foo\n          fun bar4 = 0\n        }\n      }\n    }\n  }\n}\n//│ |#class| |A| |{||}|↵|#new| |A|{|→|#fun| |foo| |#=| |1|↵|#fun| |bar| |#=| |#new| |A|{|→|#fun| |foo1| |#=| |foo|↵|#fun| |bar1| |#=| |#new| |A|{|→|#fun| |foo2| |#=| |foo|↵|#fun| |bar2| |#=| |#new| |A|{|→|#fun| |foo3| |#=| |foo|↵|#fun| |bar3| |#=| |#new| |A|{|→|#fun| |foo4| |#=| |foo|↵|#fun| |bar4| |#=| |0|←|↵|}|←|↵|}|←|↵|}|←|↵|}|←|↵|}|\n//│ Parsed: {class A {}; new A {fun foo = 1; fun bar = new A {fun foo1 = foo; fun bar1 = new A {fun foo2 = foo; fun bar2 = new A {fun foo3 = foo; fun bar3 = new A {fun foo4 = foo; fun bar4 = 0}}}}}}\n//│ Lifted:\n//│ TypingUnit {class A$1([]) {}; Code(List(new A$1([]) {}))}\n//│ \n\n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/LifterBlks.mls",
    "content": ":NewDefs\n:ParseOnly\n\n:lift\nfun foo =\n  print(\"ok\")\n  print(\"ko\")\n//│ |#fun| |foo| |#=|→|print|(|\"ok\"|)|↵|print|(|\"ko\"|)|←|\n//│ Parsed: {fun foo = {print(\"ok\",); print(\"ko\",)}}\n//│ Lifted:\n//│ TypingUnit {fun foo$1 = {print(\"ok\",); print(\"ko\",)}}\n//│ \n\n:lift\nclass A{\n  class B {}\n  fun foo(x: B) = (x : B)\n}\n//│ |#class| |A|{|→|#class| |B| |{||}|↵|#fun| |foo|(|x|#:| |B|)| |#=| |(|x| |#:| |B|)|←|↵|}|\n//│ Parsed: {class A {class B {}; fun foo = (x: B,) => '(' x : B ')'}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2([par$A$1,]) {}\n//│   class A$1([]) {fun foo = (x: A$1_B$2,) => '(' x : A$1_B$2 ')'}\n//│ }\n//│ \n\n:lift\nfun foo =\n  let local(x) =\n    class Foo {\n      fun bar = x + 1\n    }\n    Foo().bar\n  print of local(0) + local(1)\n  print of (local of 0) + local of 1\n  fun tmp = 1\n  print of local of 0 + local of 1\n  fun tmp = 2\n//│ |#fun| |foo| |#=|→|#let| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |1|←|↵|}|↵|Foo|(||)|.bar|←|↵|print| |#of| |local|(|0|)| |+| |local|(|1|)|↵|print| |#of| |(|local| |#of| |0|)| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |1|↵|print| |#of| |local| |#of| |0| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |2|←|\n//│ Parsed: {fun foo = {let local = (x,) => {class Foo {fun bar = +(x, 1,)}; (Foo()).bar}; print(+(local(0,), local(1,),),); print(+('(' local(0,) ')', local(1,),),); fun tmp = 1; print(local(+(0, local(1,),),),); fun tmp = 2}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Foo$1([x,]) {fun bar = +((this).x, 1,)}\n//│   let local$3 = (x,) => {(Foo$1(x,)).bar}\n//│   fun tmp$2 = 1\n//│   fun foo$1 = {print(+(local$3(0,), local$3(1,),),); print(+('(' local$3(0,) ')', local$3(1,),),); print(local$3(+(0, local$3(1,),),),)}\n//│ }\n//│ \n\n:lift\nclass A(y){}\nlet f = x => new A(0){fun bar = x+y}\nf(0)\n//│ |#class| |A|(|y|)|{||}|↵|#let| |f| |#=| |x| |#=>| |#new| |A|(|0|)|{|#fun| |bar| |#=| |x|+|y|}|↵|f|(|0|)|\n//│ Parsed: {class A(y,) {}; let f = (x,) => (new A)(0,) {fun bar = +(x, y,)}; f(0,)}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([y,]) {}\n//│   class A$2$2([y, x,]): A$1((this).y,) {fun bar = +((this).x, (this).y,)}\n//│   let f$1 = (x,) => {new A$2$2([0, x,]) {}}\n//│   Code(List(f$1(0,)))\n//│ }\n//│ \n\n:lift\nclass A(x){\n  fun w = x\n  fun foo(y) = \n    class B(z){\n      fun bar = x+y+z\n    }\n    new B(0){\n      fun bar = w+y+z\n    }\n}\n//│ |#class| |A|(|x|)|{|→|#fun| |w| |#=| |x|↵|#fun| |foo|(|y|)| |#=| |→|#class| |B|(|z|)|{|→|#fun| |bar| |#=| |x|+|y|+|z|←|↵|}|↵|#new| |B|(|0|)|{|→|#fun| |bar| |#=| |w|+|y|+|z|←|↵|}|←|←|↵|}|\n//│ Parsed: {class A(x,) {fun w = x; fun foo = (y,) => {class B(z,) {fun bar = +(+(x, y,), z,)}; (new B)(0,) {fun bar = +(+(w, y,), z,)}}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2([par$A$1, z, y,]) {fun bar = +(+(((this).par$A$1).x, (this).y,), (this).z,)}\n//│   class A$1_B$1$3([par$A$1, z, y,]): A$1_B$2((this).par$A$1, (this).z, (this).y,) {fun bar = +(+(((this).par$A$1).w, (this).y,), (this).z,)}\n//│   class A$1([x,]) {\n//│     fun w = (this).x\n//│     fun foo = (y,) => {{new A$1_B$1$3([this, 0, y,]) {}}}\n//│   }\n//│ }\n//│ \n\n:lift\nfun f(x,y,z) = \n  class A{\n    fun foo = new B\n    fun bar1 = x\n  }\n  class B{\n    fun foo = new A\n    fun bar2 = y\n  }\n  class C extends A, B {\n    fun bar = bar1 + bar2\n  }\n//│ |#fun| |f|(|x|,|y|,|z|)| |#=| |→|#class| |A|{|→|#fun| |foo| |#=| |#new| |B|↵|#fun| |bar1| |#=| |x|←|↵|}|↵|#class| |B|{|→|#fun| |foo| |#=| |#new| |A|↵|#fun| |bar2| |#=| |y|←|↵|}|↵|#class| |C| |#extends| |A|,| |B| |{|→|#fun| |bar| |#=| |bar1| |+| |bar2|←|↵|}|←|\n//│ Parsed: {fun f = (x, y, z,) => {class A {fun foo = new B; fun bar1 = x}; class B {fun foo = new A; fun bar2 = y}; class C: A, B {fun bar = +(bar1, bar2,)}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([x, y,]) {\n//│     fun foo = (new B$2)((this).y, (this).x,)\n//│     fun bar1 = (this).x\n//│   }\n//│   class B$2([y, x,]) {\n//│     fun foo = (new A$1)((this).x, (this).y,)\n//│     fun bar2 = (this).y\n//│   }\n//│   class C$3([x, y,]): A$1, B$2 {fun bar = +((this).bar1, (this).bar2,)}\n//│   fun f$1 = (x, y, z,) => {}\n//│ }\n//│ \n\n:lift\nfun f(x,y,z) = \n  class C{\n    class A{\n      fun foo = new B\n      fun bar1 = x\n    }\n    class B{\n      fun foo = new A\n      fun bar2 = y\n    }\n    fun boo = (new A).bar1 + B().bar2 + z\n  }\n//│ |#fun| |f|(|x|,|y|,|z|)| |#=| |→|#class| |C|{|→|#class| |A|{|→|#fun| |foo| |#=| |#new| |B|↵|#fun| |bar1| |#=| |x|←|↵|}|↵|#class| |B|{|→|#fun| |foo| |#=| |#new| |A|↵|#fun| |bar2| |#=| |y|←|↵|}|↵|#fun| |boo| |#=| |(|#new| |A|)|.bar1| |+| |B|(||)|.bar2| |+| |z|←|↵|}|←|\n//│ Parsed: {fun f = (x, y, z,) => {class C {class A {fun foo = new B; fun bar1 = x}; class B {fun foo = new A; fun bar2 = y}; fun boo = +(+(('(' new A ')').bar1, (B()).bar2,), z,)}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class C$1_A$2([par$C$1,]) {\n//│     fun foo = (new C$1_B$3)((this).par$C$1,)\n//│     fun bar1 = ((this).par$C$1).x\n//│   }\n//│   class C$1_B$3([par$C$1,]) {\n//│     fun foo = (new C$1_A$2)((this).par$C$1,)\n//│     fun bar2 = ((this).par$C$1).y\n//│   }\n//│   class C$1([x, y, z,]) {\n//│     fun boo = +(+(('(' (new C$1_A$2)(this,) ')').bar1, (C$1_B$3(this,)).bar2,), (this).z,)\n//│   }\n//│   fun f$1 = (x, y, z,) => {}\n//│ }\n//│ \n\n:lift\nfun f(y) =\n  let g(x) = x + y + 1\n  class Foo(x) {\n    fun h = g(x)\n  }\n  Foo(1).h \n  Foo(x).h\n//│ |#fun| |f|(|y|)| |#=|→|#let| |g|(|x|)| |#=| |x| |+| |y| |+| |1|↵|#class| |Foo|(|x|)| |{|→|#fun| |h| |#=| |g|(|x|)|←|↵|}|↵|Foo|(|1|)|.h| |↵|Foo|(|x|)|.h|←|\n//│ Parsed: {fun f = (y,) => {let g = (x,) => +(+(x, y,), 1,); class Foo(x,) {fun h = g(x,)}; (Foo(1,)).h; (Foo(x,)).h}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Foo$1([x, y,]) {fun h = g$2((this).x, y,)}\n//│   let g$2 = (x, y,) => +(+(x, y,), 1,)\n//│   fun f$1 = (y,) => {(Foo$1(1, y,)).h; (Foo$1(x, y,)).h}\n//│ }\n//│ \n\n:lift\nfun f(x) =\n  let g(x) = \n    let h(x) = x + 2\n    Foo(h(x), x).bar\n  class Foo(x, y) {\n    fun bar = g(x)+y\n  }\n  Foo(x, x).bar\n//│ |#fun| |f|(|x|)| |#=|→|#let| |g|(|x|)| |#=| |→|#let| |h|(|x|)| |#=| |x| |+| |2|↵|Foo|(|h|(|x|)|,| |x|)|.bar|←|↵|#class| |Foo|(|x|,| |y|)| |{|→|#fun| |bar| |#=| |g|(|x|)|+|y|←|↵|}|↵|Foo|(|x|,| |x|)|.bar|←|\n//│ Parsed: {fun f = (x,) => {let g = (x,) => {let h = (x,) => +(x, 2,); (Foo(h(x,), x,)).bar}; class Foo(x, y,) {fun bar = +(g(x,), y,)}; (Foo(x, x,)).bar}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Foo$1([x, y,]) {fun bar = +(g$2((this).x,), (this).y,)}\n//│   let h$3 = (x,) => +(x, 2,)\n//│   let g$2 = (x,) => {(Foo$1(h$3(x,), x,)).bar}\n//│   fun f$1 = (x,) => {(Foo$1(x, x,)).bar}\n//│ }\n//│ \n\n:lift\nclass Foo(x, y) extends Bar(y, x), Baz(x + y)\n//│ |#class| |Foo|(|x|,| |y|)| |#extends| |Bar|(|y|,| |x|)|,| |Baz|(|x| |+| |y|)|\n//│ Parsed: {class Foo(x, y,): Bar(y, x,), Baz(+(x, y,),) {}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Foo$1([x, y,]): Bar((this).y, (this).x,), Baz(+((this).x, (this).y,),) {}\n//│ }\n//│ \n\n:lift\nfun foo<T, U>(x: T): string = \n  class A(y) extends B<T>, C(y: U) {\n    fun bar = this\n  }\n  \"rua\"\n//│ |#fun| |foo|‹|T|,| |U|›|(|x|#:| |T|)|#:| |string| |#=| |→|#class| |A|(|y|)| |#extends| |B|‹|T|›|,| |C|(|y|#:| |U|)| |{|→|#fun| |bar| |#=| |this|←|↵|}|↵|\"rua\"|←|\n//│ Parsed: {fun foo = (x: T,) => {class A(y,): B‹T›, C(y: U,) {fun bar = this}; \"rua\"} : string}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1[T,U]([y,]): B‹T›, C(y: U,) {fun bar = this}\n//│   fun foo$1[T, U] = (x: T,) => {\"rua\"} : string\n//│ }\n//│ \n\n:lift\nclass A<T>{\n  class B{\n    fun f = x => y => x\n    fun g: T => B => T\n  }\n}\n//│ |#class| |A|‹|T|›|{|→|#class| |B|{|→|#fun| |f| |#=| |x| |#=>| |y| |#=>| |x|↵|#fun| |g|#:| |T| |#=>| |B| |#=>| |T|←|↵|}|←|↵|}|\n//│ Parsed: {class A‹T› {class B {fun f = (x,) => (y,) => x; fun g: T -> B -> T}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1_B$2_Lambda1$1$3([par$A$1_B$2, x,]) {fun apply = (y,) => (this).x}\n//│   class A$1_B$2[T]([par$A$1,]) {\n//│     fun f = (x,) => {A$1_B$2_Lambda1$1$3(this, x,)}\n//│     fun g = T -> A$1_B$2 -> T\n//│   }\n//│   class A$1[T]([]) {}\n//│ }\n//│ \n\n:lift\nclass Foo<T>{\n  class RectangleBox: Box<T> & { breadth: T }\n  class StackedRectangleBoxes<N> : RectangleBox<T> & { size: N }\n  class Bar: {any: RectangleBox => StackedRectangleBoxes}\n}\n//│ |#class| |Foo|‹|T|›|{|→|#class| |RectangleBox|#:| |Box|‹|T|›| |&| |{| |breadth|#:| |T| |}|↵|#class| |StackedRectangleBoxes|‹|N|›| |#:| |RectangleBox|‹|T|›| |&| |{| |size|#:| |N| |}|↵|#class| |Bar|#:| |{|any|#:| |RectangleBox| |#=>| |StackedRectangleBoxes|}|←|↵|}|\n//│ Parsed: {class Foo‹T› {class RectangleBox: Box[T] & {breadth: T} {}; class StackedRectangleBoxes‹N›: RectangleBox[T] & {size: N} {}; class Bar: {any: RectangleBox -> StackedRectangleBoxes} {}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Foo$1_RectangleBox$2([par$Foo$1,]) {}\n//│   class Foo$1_StackedRectangleBoxes$3[N]([par$Foo$1,]) {}\n//│   class Foo$1_Bar$4([par$Foo$1,]) {}\n//│   class Foo$1[T]([]) {}\n//│ }\n//│ \n\n:lift\nclass Func<T, U> {\n  fun apply: T => U\n}\nclass Lambda<T, U> : Func<T, U> {}\nfun ctx(a,b) =\n  fun foo(f: Func, x) = \n    f.apply(x)\n  foo(new Lambda{\n    fun apply(x) = a+x\n  }, b)\n//│ |#class| |Func|‹|T|,| |U|›| |{|→|#fun| |apply|#:| |T| |#=>| |U|←|↵|}|↵|#class| |Lambda|‹|T|,| |U|›| |#:| |Func|‹|T|,| |U|›| |{||}|↵|#fun| |ctx|(|a|,|b|)| |#=|→|#fun| |foo|(|f|#:| |Func|,| |x|)| |#=| |→|f|.apply|(|x|)|←|↵|foo|(|#new| |Lambda|{|→|#fun| |apply|(|x|)| |#=| |a|+|x|←|↵|}|,| |b|)|←|\n//│ Parsed: {class Func‹T, U› {fun apply: T -> U}; class Lambda‹T, U›: Func[T, U] {}; fun ctx = (a, b,) => {fun foo = (f: Func, x,) => {(f).apply(x,)}; foo(new Lambda {fun apply = (x,) => +(a, x,)}, b,)}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class Func$1[T,U]([]) {fun apply = T -> U}\n//│   class Lambda$2[T,U]([]) {}\n//│   fun foo$2 = (f: Func$1, x,) => {(f).apply(x,)}\n//│   fun ctx$1 = (a, b,) => {foo$2(new Lambda$2([]) {}, b,)}\n//│ }\n//│ \n\n:lift\nfun f(T) = \n  new T()\nf(MyClass)\n//│ |#fun| |f|(|T|)| |#=| |→|#new| |T|(||)|←|↵|f|(|MyClass|)|\n//│ Parsed: {fun f = (T,) => {(new T)()}; f(MyClass,)}\n//│ Lifted:\n//│ Lifting failed: mlscript.codegen.CodeGenError: Cannot find type T. Class values are not supported in lifter. \n//│ \n\n:lift\nclass A {\n  fun foo = \n    fun bar = foo()\n    bar()\n}\n//│ |#class| |A| |{|→|#fun| |foo| |#=| |→|#fun| |bar| |#=| |foo|(||)|↵|bar|(||)|←|←|↵|}|\n//│ Parsed: {class A {fun foo = {fun bar = foo(); bar()}}}\n//│ Lifted:\n//│ TypingUnit {\n//│   class A$1([]) {fun foo = {bar$1(this,)}}\n//│   fun bar$1 = (this).foo()\n//│ }\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/NestedClasses.mls",
    "content": ":NewDefs\n\n:e // FIXME: Nested class references not updated\n:lift\nclass X() {\n    class Y() {}\n}\nX.Y()\n//│ Lifted:\n//│ TypingUnit {\n//│   class X$1_Y$2([par$X$1,]) {}\n//│   class X$1([]) {}\n//│   Code(List((X$1).Y()))\n//│ }\n//│ ╔══[ERROR] Class parameters currently need type annotations\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.8: \tX.Y()\n//│ ║       \t ^^\n//│ ╙── expression of type `() -> X$1` does not have field 'Y'\n//│ class X$1_Y$2(par$X$1: error)\n//│ class X$1()\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: X$1.Y is not a function\n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/NestedFuncs.mls",
    "content": ":NewDefs\n\n:e // FIXME: Incorrect lifting\n:lift\nfun test(a) =\n  let f(x) = a + x\n  f\ntest(6)(4)\n//│ Lifted:\n//│ TypingUnit {\n//│   let f$2 = (x, a,) => +(a, x,)\n//│   fun test$1 = (a,) => {f$2}\n//│   Code(List(test$1(6,)(4,)))\n//│ }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.8: \ttest(6)(4)\n//│ ║       \t     ^^^^\n//│ ╟── argument of type `[4]` does not match type `[?a, ?b]`\n//│ ║  l.8: \ttest(6)(4)\n//│ ║       \t        ^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.6: \t  let f(x) = a + x\n//│ ╙──     \t        ^^^^^^\n//│ val f$2: (Int, Int) -> Int\n//│ fun test$1: anything -> (Int, Int) -> Int\n//│ Int | error\n//│ f$2\n//│     = [Function: f$2]\n//│ res\n//│     = NaN\n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/ParameterizedInheritance.mls",
    "content": ":NewDefs\n\n// FIXME: correctly lift parameterized inheritance\n:lift\nval c = 5\nclass Sup(val a: Int){\n  virtual fun foo = () -> a\n}\nclass Sub(b: Int) extends Sup(b+b){\n}\nclass Sub2(c: Int) extends Sub(c+c){\n  fun foo = () -> c+c\n}\n(Sub(10)).foo()\n(Sub2(c)).foo()\n//│ Lifted:\n//│ TypingUnit {\n//│   class Sup$1([val a: Int,]) {fun foo = () => (this).a}\n//│   class Sub$2([b: Int,]): Sup$1(+((this).b, (this).b,),) {}\n//│   class Sub2$3([c: Int,]): Sub$2(+(c$1, c$1,),) {fun foo = () => +(c$1, c$1,)}\n//│   let c$1 = 5\n//│   Code(List(('(' Sub$2(10,) ')').foo()))\n//│   Code(List(('(' Sub2$3(c$1,) ')').foo()))\n//│ }\n//│ ╔══[ERROR] identifier not found: this\n//│ ╙──\n//│ ╔══[ERROR] identifier not found: this\n//│ ╙──\n//│ class Sup$1(a: Int) {\n//│   fun foo: () -> Int\n//│ }\n//│ class Sub$2(b: Int) extends Sup$1 {\n//│   fun foo: () -> Int\n//│ }\n//│ class Sub2$3(c: Int) extends Sub$2, Sup$1 {\n//│   fun foo: () -> Int\n//│ }\n//│ val c$1: 5\n//│ Int\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding c$1\n"
  },
  {
    "path": "compiler/shared/test/diff/Lifter/TypedClassParams.mls",
    "content": ":NewDefs\n\n:lift\nclass A() {}\nclass B(foo: A) {}\n//│ Lifted:\n//│ TypingUnit {class A$1([]) {}; class B$2([foo: A$1,]) {}}\n//│ class A$1()\n//│ class B$2(foo: A$1)\n"
  },
  {
    "path": "compiler/shared/test/diff-ir/Class.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:genCpp\n:runCpp\n:showCpp\nmodule Fn extends Callable {\n  fun apply1(x) = builtin(\"println\", x)\n}\nclass Fn2(a) extends Callable {\n  fun apply1(x) =\n    builtin(\"println\", a)\n    builtin(\"println\", x)\n}\nclass Demo(n) {\n  fun x() = n\n}\nfun f(fn) = fn(1)\nfun main() =\n  let d1 = Demo(2)\n  Demo.x(d1)\n  let print = Fn()\n  Fn.apply1(print, 3)\n  f(print)\n  let print2 = Fn2(4)\n  Fn2.apply1(print2, 5)\n  print2(6)\n  f(print2)\nmain()\n//│ |#module| |Fn| |#extends| |Callable| |{|→|#fun| |apply1|(|x|)| |#=| |builtin|(|\"println\"|,| |x|)|←|↵|}|↵|#class| |Fn2|(|a|)| |#extends| |Callable| |{|→|#fun| |apply1|(|x|)| |#=|→|builtin|(|\"println\"|,| |a|)|↵|builtin|(|\"println\"|,| |x|)|←|←|↵|}|↵|#class| |Demo|(|n|)| |{|→|#fun| |x|(||)| |#=| |n|←|↵|}|↵|#fun| |f|(|fn|)| |#=| |fn|(|1|)|↵|#fun| |main|(||)| |#=|→|#let| |d1| |#=| |Demo|(|2|)|↵|Demo|.x|(|d1|)|↵|#let| |print| |#=| |Fn|(||)|↵|Fn|.apply1|(|print|,| |3|)|↵|f|(|print|)|↵|#let| |print2| |#=| |Fn2|(|4|)|↵|Fn2|.apply1|(|print2|,| |5|)|↵|print2|(|6|)|↵|f|(|print2|)|←|↵|main|(||)|\n//│ Parsed: {module Fn: Callable {fun apply1 = (x,) => builtin(\"println\", x,)}; class Fn2(a,): Callable {fun apply1 = (x,) => {builtin(\"println\", a,); builtin(\"println\", x,)}}; class Demo(n,) {fun x = () => n}; fun f = (fn,) => fn(1,); fun main = () => {let d1 = Demo(2,); (Demo).x(d1,); let print = Fn(); (Fn).apply1(print, 3,); f(print,); let print2 = Fn2(4,); (Fn2).apply1(print2, 5,); print2(6,); f(print2,)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Fn() extends Callable {\n//│     def apply1(x$11) =\n//│       let x$12 = Callable.apply2(builtin,println,x$11) in -- #64\n//│       x$12 -- #63\n//│   }\n//│   class Fn2(a) extends Callable {\n//│     def apply1(x$13) =\n//│       let x$14 = Callable.apply2(builtin,println,a) in -- #80\n//│       let x$15 = Callable.apply2(builtin,println,x$13) in -- #79\n//│       x$15 -- #78\n//│   }\n//│   class Demo(n) {\n//│     def x() =\n//│       n -- #81\n//│   }\n//│   def f(fn$0) =\n//│     let x$1 = Callable.apply1(fn$0,1) in -- #8\n//│     x$1 -- #7\n//│   def main() =\n//│     let x$2 = Demo(2) in -- #56\n//│     let x$3 = Demo.x(x$2) in -- #55\n//│     let x$4 = Fn() in -- #54\n//│     let x$5 = Fn.apply1(x$4,3) in -- #53\n//│     let* (x$6) = f(x$4) in -- #52\n//│     let x$7 = Fn2(4) in -- #51\n//│     let x$8 = Fn2.apply1(x$7,5) in -- #50\n//│     let x$9 = Callable.apply1(x$7,6) in -- #49\n//│     let* (x$10) = f(x$7) in -- #48\n//│     x$10 -- #47\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Cpp:\n//│ struct _mls_Demo: public _mlsObject {\n//│   _mlsValue _mls_n;\n//│   constexpr static inline const char *typeName = \"Demo\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); std::printf(\"(\"); this->_mls_n.print();  std::printf(\")\"); }\n//│   virtual void destroy() override { _mlsValue::destroy(this->_mls_n);  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create(_mlsValue _mls_n) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Demo; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_n = _mls_n;  return _mlsValue(_mlsVal); }\n//│   virtual _mlsValue _mls_x(){\n//│     _mlsValue _mls_retval;\n//│     _mls_retval = _mls_n;\n//│     return _mls_retval;\n//│   }\n//│ };\n//│ struct _mls_Fn: public _mls_Callable {\n//│ \n//│   constexpr static inline const char *typeName = \"Fn\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); }\n//│   virtual void destroy() override {  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Fn; _mlsVal->refCount = 1; _mlsVal->tag = typeTag;  return _mlsValue(_mlsVal); }\n//│   virtual _mlsValue _mls_apply1(_mlsValue _mls_x_11){\n//│     _mlsValue _mls_retval;\n//│     auto _mls_x_12 = _mls_builtin_println(_mls_x_11);\n//│     _mls_retval = _mls_x_12;\n//│     return _mls_retval;\n//│   }\n//│ };\n//│ struct _mls_Fn2: public _mls_Callable {\n//│   _mlsValue _mls_a;\n//│   constexpr static inline const char *typeName = \"Fn2\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); std::printf(\"(\"); this->_mls_a.print();  std::printf(\")\"); }\n//│   virtual void destroy() override { _mlsValue::destroy(this->_mls_a);  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create(_mlsValue _mls_a) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Fn2; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_a = _mls_a;  return _mlsValue(_mlsVal); }\n//│   virtual _mlsValue _mls_apply1(_mlsValue _mls_x_13){\n//│     _mlsValue _mls_retval;\n//│     auto _mls_x_14 = _mls_builtin_println(_mls_a);\n//│     auto _mls_x_15 = _mls_builtin_println(_mls_x_13);\n//│     _mls_retval = _mls_x_15;\n//│     return _mls_retval;\n//│   }\n//│ };\n//│ _mlsValue _mls_f(_mlsValue _mls_fn_0){\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x_1 = _mlsMethodCall<_mls_Callable>(_mls_fn_0)->_mls_apply1(_mlsValue::fromIntLit(1));\n//│   _mls_retval = _mls_x_1;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_main(){\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x_2 = _mlsValue::create<_mls_Demo>(_mlsValue::fromIntLit(2));\n//│   auto _mls_x_3 = _mlsMethodCall<_mls_Demo>(_mls_x_2)->_mls_x();\n//│   auto _mls_x_4 = _mlsValue::create<_mls_Fn>();\n//│   auto _mls_x_5 = _mlsMethodCall<_mls_Fn>(_mls_x_4)->_mls_apply1(_mlsValue::fromIntLit(3));\n//│   auto _mls_x_6 = _mls_f(_mls_x_4);\n//│   auto _mls_x_7 = _mlsValue::create<_mls_Fn2>(_mlsValue::fromIntLit(4));\n//│   auto _mls_x_8 = _mlsMethodCall<_mls_Fn2>(_mls_x_7)->_mls_apply1(_mlsValue::fromIntLit(5));\n//│   auto _mls_x_9 = _mlsMethodCall<_mls_Callable>(_mls_x_7)->_mls_apply1(_mlsValue::fromIntLit(6));\n//│   auto _mls_x_10 = _mls_f(_mls_x_7);\n//│   _mls_retval = _mls_x_10;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mlsMain(){\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x_0 = _mls_main();\n//│   _mls_retval = _mls_x_0;\n//│   return _mls_retval;\n//│ }\n//│ int main() { return _mlsLargeStack(_mlsMainWrapper); }\n//│ \n//│ \n//│ Execution succeeded: \n//│ 3\n//│ 1\n//│ 4\n//│ 5\n//│ 4\n//│ 6\n//│ 4\n//│ 1\n//│ Unit\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/Currying.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:interpIR\n:genCpp\n:runCpp\nfun add2c(a)(b) = a + b\nfun add2(a, b) = a + b\nfun add3c(a)(b)(c) = a + b + c\nfun main() =\n  add2c(1)(2)\n  add2(1, 2)\n  add3c(1)(2)(3)\nmain()\n//│ |#fun| |add2c|(|a|)|(|b|)| |#=| |a| |+| |b|↵|#fun| |add2|(|a|,| |b|)| |#=| |a| |+| |b|↵|#fun| |add3c|(|a|)|(|b|)|(|c|)| |#=| |a| |+| |b| |+| |c|↵|#fun| |main|(||)| |#=|→|add2c|(|1|)|(|2|)|↵|add2|(|1|,| |2|)|↵|add3c|(|1|)|(|2|)|(|3|)|←|↵|main|(||)|\n//│ Parsed: {fun add2c = (a,) => (b,) => +(a, b,); fun add2 = (a, b,) => +(a, b,); fun add3c = (a,) => (b,) => (c,) => +(+(a, b,), c,); fun main = () => {add2c(1,)(2,); add2(1, 2,); add3c(1,)(2,)(3,)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Lambda$0(a) extends Callable {\n//│     def apply1(b$1) =\n//│       let x$12 = +(a,b$1) in -- #58\n//│       x$12 -- #57\n//│   }\n//│   class Lambda$1(a) extends Callable {\n//│     def apply1(b$2) =\n//│       let x$14 = Lambda$2(a,b$2) in -- #60\n//│       x$14 -- #59\n//│   }\n//│   class Lambda$2(a,b) extends Callable {\n//│     def apply1(c$0) =\n//│       let x$15 = +(a,b) in -- #73\n//│       let x$16 = +(x$15,c$0) in -- #72\n//│       x$16 -- #71\n//│   }\n//│   def add2c(a$0) =\n//│     let x$2 = Lambda$0(a$0) in -- #4\n//│     x$2 -- #3\n//│   def add2(a$1,b$0) =\n//│     let x$3 = +(a$1,b$0) in -- #11\n//│     x$3 -- #10\n//│   def add3c(a$2) =\n//│     let x$5 = Lambda$1(a$2) in -- #13\n//│     x$5 -- #12\n//│   def main() =\n//│     let* (x$6) = add2c(1) in -- #45\n//│     let x$7 = Callable.apply1(x$6,2) in -- #44\n//│     let* (x$8) = add2(1,2) in -- #43\n//│     let* (x$9) = add3c(1) in -- #42\n//│     let x$10 = Callable.apply1(x$9,2) in -- #41\n//│     let x$11 = Callable.apply1(x$10,3) in -- #40\n//│     x$11 -- #39\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 6\n//│ \n//│ \n//│ Execution succeeded: \n//│ 6\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/IR.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nmodule Either[A, B]\nclass Left[A, B](x: A) extends Either[A, B]\nclass Right[A, B](y: B) extends Either[A, B]\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O, _16: Either, _17: Left, _18: Right)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#module| |Either|[|A|,| |B|]|↵|#class| |Left|[|A|,| |B|]|(|x|#:| |A|)| |#extends| |Either|[|A|,| |B|]|↵|#class| |Right|[|A|,| |B|]|(|y|#:| |B|)| |#extends| |Either|[|A|,| |B|]|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|,| |_16|#:| |Either|,| |_17|#:| |Left|,| |_18|#:| |Right|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; module Either‹A, B› {}; class Left‹A, B›(x: A,): Either‹A, B› {}; class Right‹A, B›(y: B,): Either‹A, B› {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O, _16: Either, _17: Left, _18: Right,) {}}\n//│ \n//│ Preluded.\n//│ \n\n\n:interpIR\nfun mktup2(x, y) = mktup(x, y)\nfun mktup(x, y) = Pair(x, y)\nfun foo() =\n  mktup2(1, 2)\nfoo()\n//│ |#fun| |mktup2|(|x|,| |y|)| |#=| |mktup|(|x|,| |y|)|↵|#fun| |mktup|(|x|,| |y|)| |#=| |Pair|(|x|,| |y|)|↵|#fun| |foo|(||)| |#=|→|mktup2|(|1|,| |2|)|←|↵|foo|(||)|\n//│ Parsed: {fun mktup2 = (x, y,) => mktup(x, y,); fun mktup = (x, y,) => Pair(x, y,); fun foo = () => {mktup2(1, 2,)}; foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def mktup2(x$1,y$0) =\n//│     let* (x$2) = mktup(x$1,y$0) in -- #9\n//│     x$2 -- #8\n//│   def mktup(x$3,y$1) =\n//│     let x$4 = Pair(x$3,y$1) in -- #16\n//│     x$4 -- #15\n//│   def foo() =\n//│     let* (x$5) = mktup2(1,2) in -- #23\n//│     x$5 -- #22\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ Pair(1,2)\n//│ \n\n:interpIR\nfun foo(pair) =\n  if pair is\n    Pair(x, y) then Pair(x, y)\nfun bar() =\n  foo(Pair(1, 2))\nbar()\n//│ |#fun| |foo|(|pair|)| |#=|→|#if| |pair| |is|→|Pair|(|x|,| |y|)| |#then| |Pair|(|x|,| |y|)|←|←|↵|#fun| |bar|(||)| |#=|→|foo|(|Pair|(|1|,| |2|)|)|←|↵|bar|(||)|\n//│ Parsed: {fun foo = (pair,) => {if pair is ‹(Pair(x, y,)) then Pair(x, y,)›}; fun bar = () => {foo(Pair(1, 2,),)}; bar()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo(pair$0) =\n//│     case pair$0 of -- #23\n//│       Pair =>\n//│         let x$2 = Pair.y(pair$0) in -- #22\n//│         let x$3 = Pair.x(pair$0) in -- #21\n//│         let x$4 = Pair(x$3,x$2) in -- #20\n//│         jump j$0(x$4) -- #19\n//│   def j$0(x$1) =\n//│     x$1 -- #4\n//│   def bar() =\n//│     let x$5 = Pair(1,2) in -- #34\n//│     let* (x$6) = foo(x$5) in -- #33\n//│     x$6 -- #32\n//│   let* (x$0) = bar() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ Pair(1,2)\n//│ \n\n\n\n:interpIR\nfun silly(pair) =\n  let _ = 0\n  let n = if pair is\n    Pair(x1, x2) then\n      if pair is\n        Pair (x3, x4) then x3 + 1\n  n + 1\nfun foo() =\n    let a = Pair(0, 1)\n    let b = silly(a)\n    b\nfoo()\n//│ |#fun| |silly|(|pair|)| |#=|→|#let| |_| |#=| |0|↵|#let| |n| |#=| |#if| |pair| |is|→|Pair|(|x1|,| |x2|)| |#then|→|#if| |pair| |is|→|Pair| |(|x3|,| |x4|)| |#then| |x3| |+| |1|←|←|←|↵|n| |+| |1|←|↵|#fun| |foo|(||)| |#=|→|#let| |a| |#=| |Pair|(|0|,| |1|)|↵|#let| |b| |#=| |silly|(|a|)|↵|b|←|↵|foo|(||)|\n//│ Parsed: {fun silly = (pair,) => {let _ = 0; let n = if pair is ‹(Pair(x1, x2,)) then {if pair is ‹(Pair(x3, x4,)) then +(x3, 1,)›}›; +(n, 1,)}; fun foo = () => {let a = Pair(0, 1,); let b = silly(a,); b}; foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def silly(pair$0) =\n//│     let x$1 = 0 in -- #46\n//│     case pair$0 of -- #45\n//│       Pair =>\n//│         let x$4 = Pair.y(pair$0) in -- #44\n//│         let x$5 = Pair.x(pair$0) in -- #43\n//│         case pair$0 of -- #42\n//│           Pair =>\n//│             let x$7 = Pair.y(pair$0) in -- #41\n//│             let x$8 = Pair.x(pair$0) in -- #40\n//│             let x$9 = +(x$8,1) in -- #39\n//│             jump j$1(x$9) -- #38\n//│   def j$0(x$2) =\n//│     let x$3 = +(x$2,1) in -- #12\n//│     x$3 -- #11\n//│   def j$1(x$6) =\n//│     jump j$0(x$6) -- #23\n//│   def foo() =\n//│     let x$10 = Pair(0,1) in -- #59\n//│     let* (x$11) = silly(x$10) in -- #58\n//│     x$11 -- #57\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 2\n//│ \n\n\n\n\n:interpIR\nfun inc_fst(pair) =\n  let c = 2\n  if pair is\n    Pair(x1, x2) then x1 + c\nfun foo() =\n    let a = Pair(0, 1)\n    let b = inc_fst(a)\n    b\nfoo()\n//│ |#fun| |inc_fst|(|pair|)| |#=|→|#let| |c| |#=| |2|↵|#if| |pair| |is|→|Pair|(|x1|,| |x2|)| |#then| |x1| |+| |c|←|←|↵|#fun| |foo|(||)| |#=|→|#let| |a| |#=| |Pair|(|0|,| |1|)|↵|#let| |b| |#=| |inc_fst|(|a|)|↵|b|←|↵|foo|(||)|\n//│ Parsed: {fun inc_fst = (pair,) => {let c = 2; if pair is ‹(Pair(x1, x2,)) then +(x1, c,)›}; fun foo = () => {let a = Pair(0, 1,); let b = inc_fst(a,); b}; foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def inc_fst(pair$0) =\n//│     let x$1 = 2 in -- #25\n//│     case pair$0 of -- #24\n//│       Pair =>\n//│         let x$3 = Pair.y(pair$0) in -- #23\n//│         let x$4 = Pair.x(pair$0) in -- #22\n//│         let x$5 = +(x$4,x$1) in -- #21\n//│         jump j$0(x$5) -- #20\n//│   def j$0(x$2) =\n//│     x$2 -- #5\n//│   def foo() =\n//│     let x$6 = Pair(0,1) in -- #38\n//│     let* (x$7) = inc_fst(x$6) in -- #37\n//│     x$7 -- #36\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 2\n//│ \n\n:interpIR\nfun inc_fst(pair) =\n  let _ = 0\n  if pair is\n    Pair(x1, x2) then x2 + 1\nfun foo() =\n    let b = inc_fst(Pair(0, 1))\n    b\nfoo()\n//│ |#fun| |inc_fst|(|pair|)| |#=|→|#let| |_| |#=| |0|↵|#if| |pair| |is|→|Pair|(|x1|,| |x2|)| |#then| |x2| |+| |1|←|←|↵|#fun| |foo|(||)| |#=|→|#let| |b| |#=| |inc_fst|(|Pair|(|0|,| |1|)|)|↵|b|←|↵|foo|(||)|\n//│ Parsed: {fun inc_fst = (pair,) => {let _ = 0; if pair is ‹(Pair(x1, x2,)) then +(x2, 1,)›}; fun foo = () => {let b = inc_fst(Pair(0, 1,),); b}; foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def inc_fst(pair$0) =\n//│     let x$1 = 0 in -- #25\n//│     case pair$0 of -- #24\n//│       Pair =>\n//│         let x$3 = Pair.y(pair$0) in -- #23\n//│         let x$4 = Pair.x(pair$0) in -- #22\n//│         let x$5 = +(x$3,1) in -- #21\n//│         jump j$0(x$5) -- #20\n//│   def j$0(x$2) =\n//│     x$2 -- #5\n//│   def foo() =\n//│     let x$6 = Pair(0,1) in -- #37\n//│     let* (x$7) = inc_fst(x$6) in -- #36\n//│     x$7 -- #35\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 2\n//│ \n\n:interpIR\nfun foo(a, b) =\n  let t = if a is\n    Left(x) then Left(x + 1)\n    Right(y) then Right(b)\n  if t is\n    Left(x) then x\n    Right(y) then y\nfun bar() =\n  foo(Right(2), 2)\nbar()\n//│ |#fun| |foo|(|a|,| |b|)| |#=|→|#let| |t| |#=| |#if| |a| |is|→|Left|(|x|)| |#then| |Left|(|x| |+| |1|)|↵|Right|(|y|)| |#then| |Right|(|b|)|←|↵|#if| |t| |is|→|Left|(|x|)| |#then| |x|↵|Right|(|y|)| |#then| |y|←|←|↵|#fun| |bar|(||)| |#=|→|foo|(|Right|(|2|)|,| |2|)|←|↵|bar|(||)|\n//│ Parsed: {fun foo = (a, b,) => {let t = if a is ‹(Left(x,)) then Left(+(x, 1,),); (Right(y,)) then Right(b,)›; if t is ‹(Left(x,)) then x; (Right(y,)) then y›}; fun bar = () => {foo(Right(2,), 2,)}; bar()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo(a$0,b$0) =\n//│     case a$0 of -- #50\n//│       Left =>\n//│         let x$5 = Left.x(a$0) in -- #38\n//│         let x$6 = +(x$5,1) in -- #37\n//│         let x$7 = Left(x$6) in -- #36\n//│         jump j$0(x$7) -- #35\n//│       Right =>\n//│         let x$8 = Right.y(a$0) in -- #49\n//│         let x$9 = Right(b$0) in -- #48\n//│         jump j$0(x$9) -- #47\n//│   def j$1(x$2) =\n//│     x$2 -- #6\n//│   def j$0(x$1) =\n//│     case x$1 of -- #21\n//│       Left =>\n//│         let x$3 = Left.x(x$1) in -- #13\n//│         jump j$1(x$3) -- #12\n//│       Right =>\n//│         let x$4 = Right.y(x$1) in -- #20\n//│         jump j$1(x$4) -- #19\n//│   def bar() =\n//│     let x$10 = Right(2) in -- #61\n//│     let* (x$11) = foo(x$10,2) in -- #60\n//│     x$11 -- #59\n//│   let* (x$0) = bar() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 2\n//│ \n\n:interpIR\nfun foo(a) = Pair.x(a) + Pair.y(a)\nfun bar() =\n  foo(Pair(1, 0))\nbar()\n//│ |#fun| |foo|(|a|)| |#=| |Pair|.x|(|a|)| |+| |Pair|.y|(|a|)|↵|#fun| |bar|(||)| |#=|→|foo|(|Pair|(|1|,| |0|)|)|←|↵|bar|(||)|\n//│ Parsed: {fun foo = (a,) => +((Pair).x(a,), (Pair).y(a,),); fun bar = () => {foo(Pair(1, 0,),)}; bar()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo(a$0) =\n//│     let x$1 = Pair.x(a$0) in -- #17\n//│     let x$2 = Pair.y(a$0) in -- #16\n//│     let x$3 = +(x$1,x$2) in -- #15\n//│     x$3 -- #14\n//│   def bar() =\n//│     let x$4 = Pair(1,0) in -- #28\n//│     let* (x$5) = foo(x$4) in -- #27\n//│     x$5 -- #26\n//│   let* (x$0) = bar() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 1\n//│ \n\n\n\n:interpIR\nfun foo(a, b) =\n  let x1 = Pair.x(a)\n  let y1 = Pair.y(a)\n  let x2 = Pair.x(b)\n  let y2 = Pair.y(b)\n  x1 + y1 + x2 + y2\nfun bar(c) =\n  foo(Pair(0, 1), c)\n  foo(c, Pair(2, 3))\n  foo(Pair(0, 1), Pair(2, 3))\nfun baz() =\n  bar(Pair(4,5))\nbaz()\n//│ |#fun| |foo|(|a|,| |b|)| |#=|→|#let| |x1| |#=| |Pair|.x|(|a|)|↵|#let| |y1| |#=| |Pair|.y|(|a|)|↵|#let| |x2| |#=| |Pair|.x|(|b|)|↵|#let| |y2| |#=| |Pair|.y|(|b|)|↵|x1| |+| |y1| |+| |x2| |+| |y2|←|↵|#fun| |bar|(|c|)| |#=|→|foo|(|Pair|(|0|,| |1|)|,| |c|)|↵|foo|(|c|,| |Pair|(|2|,| |3|)|)|↵|foo|(|Pair|(|0|,| |1|)|,| |Pair|(|2|,| |3|)|)|←|↵|#fun| |baz|(||)| |#=|→|bar|(|Pair|(|4|,|5|)|)|←|↵|baz|(||)|\n//│ Parsed: {fun foo = (a, b,) => {let x1 = (Pair).x(a,); let y1 = (Pair).y(a,); let x2 = (Pair).x(b,); let y2 = (Pair).y(b,); +(+(+(x1, y1,), x2,), y2,)}; fun bar = (c,) => {foo(Pair(0, 1,), c,); foo(c, Pair(2, 3,),); foo(Pair(0, 1,), Pair(2, 3,),)}; fun baz = () => {bar(Pair(4, 5,),)}; baz()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo(a$0,b$0) =\n//│     let x$1 = Pair.x(a$0) in -- #41\n//│     let x$2 = Pair.y(a$0) in -- #40\n//│     let x$3 = Pair.x(b$0) in -- #39\n//│     let x$4 = Pair.y(b$0) in -- #38\n//│     let x$5 = +(x$1,x$2) in -- #37\n//│     let x$6 = +(x$5,x$3) in -- #36\n//│     let x$7 = +(x$6,x$4) in -- #35\n//│     x$7 -- #34\n//│   def bar(c$0) =\n//│     let x$8 = Pair(0,1) in -- #86\n//│     let* (x$9) = foo(x$8,c$0) in -- #85\n//│     let x$10 = Pair(2,3) in -- #84\n//│     let* (x$11) = foo(c$0,x$10) in -- #83\n//│     let x$12 = Pair(0,1) in -- #82\n//│     let x$13 = Pair(2,3) in -- #81\n//│     let* (x$14) = foo(x$12,x$13) in -- #80\n//│     x$14 -- #79\n//│   def baz() =\n//│     let x$15 = Pair(4,5) in -- #97\n//│     let* (x$16) = bar(x$15) in -- #96\n//│     x$16 -- #95\n//│   let* (x$0) = baz() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 6\n//│ \n\n:interpIR\nfun foo() =\n  let p = Pair(0, 1)\n  let b = Pair.x(p)\n  b\nfoo()\n//│ |#fun| |foo|(||)| |#=|→|#let| |p| |#=| |Pair|(|0|,| |1|)|↵|#let| |b| |#=| |Pair|.x|(|p|)|↵|b|←|↵|foo|(||)|\n//│ Parsed: {fun foo = () => {let p = Pair(0, 1,); let b = (Pair).x(p,); b}; foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo() =\n//│     let x$1 = Pair(0,1) in -- #15\n//│     let x$2 = Pair.x(x$1) in -- #14\n//│     x$2 -- #13\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 0\n//│ \n\n:interpIR\nfun foo() =\n  bar(S(O))\nfun bar(x) =\n  baz(x)\nfun baz(x) =\n  if x is\n    S(s) then s\n    O then x\nfoo()\n//│ |#fun| |foo|(||)| |#=|→|bar|(|S|(|O|)|)|←|↵|#fun| |bar|(|x|)| |#=|→|baz|(|x|)|←|↵|#fun| |baz|(|x|)| |#=|→|#if| |x| |is|→|S|(|s|)| |#then| |s|↵|O| |#then| |x|←|←|↵|foo|(||)|\n//│ Parsed: {fun foo = () => {bar(S(O,),)}; fun bar = (x,) => {baz(x,)}; fun baz = (x,) => {if x is ‹(S(s,)) then s; (O) then x›}; foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo() =\n//│     let x$1 = O() in -- #12\n//│     let x$2 = S(x$1) in -- #11\n//│     let* (x$3) = bar(x$2) in -- #10\n//│     x$3 -- #9\n//│   def bar(x$4) =\n//│     let* (x$5) = baz(x$4) in -- #17\n//│     x$5 -- #16\n//│   def baz(x$6) =\n//│     case x$6 of -- #29\n//│       S =>\n//│         let x$8 = S.s(x$6) in -- #26\n//│         jump j$0(x$8) -- #25\n//│       O =>\n//│         jump j$0(x$6) -- #28\n//│   def j$0(x$7) =\n//│     x$7 -- #19\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ O()\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/IRComplex.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:interpIR\nclass A(x, y, z)\nclass B(m, n)\nfun complex_foo(t) =\n  let r = if t is\n    A(x, y, z) then x + y * z\n    B(m, n) then m - n\n  let s = B(1, 2)\n  let u = if s is\n    A(x, y, z) then 3\n    B(m, n) then 4\n  r + u\nfun bar() =\n  complex_foo(A(6, 7, 8))\n  complex_foo(B(9, 10))\nbar()\n//│ |#class| |A|(|x|,| |y|,| |z|)|↵|#class| |B|(|m|,| |n|)|↵|#fun| |complex_foo|(|t|)| |#=|→|#let| |r| |#=| |#if| |t| |is|→|A|(|x|,| |y|,| |z|)| |#then| |x| |+| |y| |*| |z|↵|B|(|m|,| |n|)| |#then| |m| |-| |n|←|↵|#let| |s| |#=| |B|(|1|,| |2|)|↵|#let| |u| |#=| |#if| |s| |is|→|A|(|x|,| |y|,| |z|)| |#then| |3|↵|B|(|m|,| |n|)| |#then| |4|←|↵|r| |+| |u|←|↵|#fun| |bar|(||)| |#=|→|complex_foo|(|A|(|6|,| |7|,| |8|)|)|↵|complex_foo|(|B|(|9|,| |10|)|)|←|↵|bar|(||)|\n//│ Parsed: {class A(x, y, z,) {}; class B(m, n,) {}; fun complex_foo = (t,) => {let r = if t is ‹(A(x, y, z,)) then +(x, *(y, z,),); (B(m, n,)) then -(m, n,)›; let s = B(1, 2,); let u = if s is ‹(A(x, y, z,)) then 3; (B(m, n,)) then 4›; +(r, u,)}; fun bar = () => {complex_foo(A(6, 7, 8,),); complex_foo(B(9, 10,),)}; bar()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class A(x,y,z)\n//│   class B(m,n)\n//│   def complex_foo(t$0) =\n//│     case t$0 of -- #98\n//│       A =>\n//│         let x$10 = A.z(t$0) in -- #79\n//│         let x$11 = A.y(t$0) in -- #78\n//│         let x$12 = A.x(t$0) in -- #77\n//│         let x$13 = *(x$11,x$10) in -- #76\n//│         let x$14 = +(x$12,x$13) in -- #75\n//│         jump j$0(x$14) -- #74\n//│       B =>\n//│         let x$15 = B.n(t$0) in -- #97\n//│         let x$16 = B.m(t$0) in -- #96\n//│         let x$17 = -(x$16,x$15) in -- #95\n//│         jump j$0(x$17) -- #94\n//│   def j$1(x$3,x$1) =\n//│     let x$4 = +(x$1,x$3) in -- #19\n//│     x$4 -- #18\n//│   def j$0(x$1) =\n//│     let x$2 = B(1,2) in -- #50\n//│     case x$2 of -- #49\n//│       A =>\n//│         let x$5 = A.z(x$2) in -- #36\n//│         let x$6 = A.y(x$2) in -- #35\n//│         let x$7 = A.x(x$2) in -- #34\n//│         jump j$1(3,x$1) -- #33\n//│       B =>\n//│         let x$8 = B.n(x$2) in -- #48\n//│         let x$9 = B.m(x$2) in -- #47\n//│         jump j$1(4,x$1) -- #46\n//│   def bar() =\n//│     let x$18 = A(6,7,8) in -- #122\n//│     let* (x$19) = complex_foo(x$18) in -- #121\n//│     let x$20 = B(9,10) in -- #120\n//│     let* (x$21) = complex_foo(x$20) in -- #119\n//│     x$21 -- #118\n//│   let* (x$0) = bar() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 3\n//│ \n\n:interpIR\nclass A(w, x)\nclass B(y)\nclass C(z)\nfun complex_foo(t) =\n  let a = 1 + 2\n  let b = 1 * 2\n  let x = if t is\n    A(x, y) then y\n    B(x) then B(x + b)\n    C(x) then C(0)\n  let z = A(5, x)\n  let v = B(6)\n  let y = if x is\n    A(x, y) then\n      let m = x + a + b\n      if y is\n        A(x, y) then x\n        B(x) then m\n        C(x) then 0\n    B(x) then 2\n    C(x) then 3\n  if z is\n    A(x, y) then x\n    B(x) then 4\n    C(x) then\n      if v is\n        A(x, y) then x\n        B(x) then 7\n        C(x) then 8\nfun bar() =\n  complex_foo(A(10, A(9, B(10))))\nbar()\n//│ |#class| |A|(|w|,| |x|)|↵|#class| |B|(|y|)|↵|#class| |C|(|z|)|↵|#fun| |complex_foo|(|t|)| |#=|→|#let| |a| |#=| |1| |+| |2|↵|#let| |b| |#=| |1| |*| |2|↵|#let| |x| |#=| |#if| |t| |is|→|A|(|x|,| |y|)| |#then| |y|↵|B|(|x|)| |#then| |B|(|x| |+| |b|)|↵|C|(|x|)| |#then| |C|(|0|)|←|↵|#let| |z| |#=| |A|(|5|,| |x|)|↵|#let| |v| |#=| |B|(|6|)|↵|#let| |y| |#=| |#if| |x| |is|→|A|(|x|,| |y|)| |#then|→|#let| |m| |#=| |x| |+| |a| |+| |b|↵|#if| |y| |is|→|A|(|x|,| |y|)| |#then| |x|↵|B|(|x|)| |#then| |m|↵|C|(|x|)| |#then| |0|←|←|↵|B|(|x|)| |#then| |2|↵|C|(|x|)| |#then| |3|←|↵|#if| |z| |is|→|A|(|x|,| |y|)| |#then| |x|↵|B|(|x|)| |#then| |4|↵|C|(|x|)| |#then|→|#if| |v| |is|→|A|(|x|,| |y|)| |#then| |x|↵|B|(|x|)| |#then| |7|↵|C|(|x|)| |#then| |8|←|←|←|←|↵|#fun| |bar|(||)| |#=|→|complex_foo|(|A|(|10|,| |A|(|9|,| |B|(|10|)|)|)|)|←|↵|bar|(||)|\n//│ Parsed: {class A(w, x,) {}; class B(y,) {}; class C(z,) {}; fun complex_foo = (t,) => {let a = +(1, 2,); let b = *(1, 2,); let x = if t is ‹(A(x, y,)) then y; (B(x,)) then B(+(x, b,),); (C(x,)) then C(0,)›; let z = A(5, x,); let v = B(6,); let y = if x is ‹(A(x, y,)) then {let m = +(+(x, a,), b,); if y is ‹(A(x, y,)) then x; (B(x,)) then m; (C(x,)) then 0›}; (B(x,)) then 2; (C(x,)) then 3›; if z is ‹(A(x, y,)) then x; (B(x,)) then 4; (C(x,)) then {if v is ‹(A(x, y,)) then x; (B(x,)) then 7; (C(x,)) then 8›}›}; fun bar = () => {complex_foo(A(10, A(9, B(10,),),),)}; bar()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class A(w,x)\n//│   class B(y)\n//│   class C(z)\n//│   def complex_foo(t$0) =\n//│     let x$1 = +(1,2) in -- #198\n//│     let x$2 = *(1,2) in -- #197\n//│     case t$0 of -- #196\n//│       A =>\n//│         let x$28 = A.x(t$0) in -- #167\n//│         let x$29 = A.w(t$0) in -- #166\n//│         jump j$0(x$28,x$1,x$2) -- #165\n//│       B =>\n//│         let x$30 = B.y(t$0) in -- #184\n//│         let x$31 = +(x$30,x$2) in -- #183\n//│         let x$32 = B(x$31) in -- #182\n//│         jump j$0(x$32,x$1,x$2) -- #181\n//│       C =>\n//│         let x$33 = C.z(t$0) in -- #195\n//│         let x$34 = C(0) in -- #194\n//│         jump j$0(x$34,x$1,x$2) -- #193\n//│   def j$2(x$7) =\n//│     x$7 -- #30\n//│   def j$3(x$12) =\n//│     jump j$2(x$12) -- #56\n//│   def j$1(x$6,x$4,x$5) =\n//│     case x$4 of -- #85\n//│       A =>\n//│         let x$8 = A.x(x$4) in -- #42\n//│         let x$9 = A.w(x$4) in -- #41\n//│         jump j$2(x$9) -- #40\n//│       B =>\n//│         let x$10 = B.y(x$4) in -- #49\n//│         jump j$2(4) -- #48\n//│       C =>\n//│         let x$11 = C.z(x$4) in -- #84\n//│         case x$5 of -- #83\n//│           A =>\n//│             let x$13 = A.x(x$5) in -- #68\n//│             let x$14 = A.w(x$5) in -- #67\n//│             jump j$3(x$14) -- #66\n//│           B =>\n//│             let x$15 = B.y(x$5) in -- #75\n//│             jump j$3(7) -- #74\n//│           C =>\n//│             let x$16 = C.z(x$5) in -- #82\n//│             jump j$3(8) -- #81\n//│   def j$4(x$21,x$4,x$5) =\n//│     jump j$1(x$21,x$4,x$5) -- #107\n//│   def j$0(x$3,x$1,x$2) =\n//│     let x$4 = A(5,x$3) in -- #155\n//│     let x$5 = B(6) in -- #154\n//│     case x$3 of -- #153\n//│       A =>\n//│         let x$17 = A.x(x$3) in -- #138\n//│         let x$18 = A.w(x$3) in -- #137\n//│         let x$19 = +(x$18,x$1) in -- #136\n//│         let x$20 = +(x$19,x$2) in -- #135\n//│         case x$17 of -- #134\n//│           A =>\n//│             let x$22 = A.x(x$17) in -- #119\n//│             let x$23 = A.w(x$17) in -- #118\n//│             jump j$4(x$23,x$4,x$5) -- #117\n//│           B =>\n//│             let x$24 = B.y(x$17) in -- #126\n//│             jump j$4(x$20,x$4,x$5) -- #125\n//│           C =>\n//│             let x$25 = C.z(x$17) in -- #133\n//│             jump j$4(0,x$4,x$5) -- #132\n//│       B =>\n//│         let x$26 = B.y(x$3) in -- #145\n//│         jump j$1(2,x$4,x$5) -- #144\n//│       C =>\n//│         let x$27 = C.z(x$3) in -- #152\n//│         jump j$1(3,x$4,x$5) -- #151\n//│   def bar() =\n//│     let x$35 = B(10) in -- #219\n//│     let x$36 = A(9,x$35) in -- #218\n//│     let x$37 = A(10,x$36) in -- #217\n//│     let* (x$38) = complex_foo(x$37) in -- #216\n//│     x$38 -- #215\n//│   let* (x$0) = bar() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 5\n//│ \n\n:interpIR\nclass A(w, x)\nclass B(y)\nclass C(z)\nfun complex_foo(t) =\n  let a = 1 + 2\n  let b = 1 * 2\n  let x = if t is\n    A(x, y) then A(x, C(0))\n    B(x) then B(x + b)\n    C(x) then C(0)\n  let z = A(5, x)\n  let v = B(6)\n  let y = if x is\n    A(x, y) then\n      let m = x + a + b\n      if y is\n        A(x, y) then x\n        B(x) then m\n        C(x) then 0\n    B(x) then 2\n    C(x) then 3\n  if z is\n    A(x, y) then x\n    B(x) then 4\n    C(x) then\n      if v is\n        A(x, y) then x\n        B(x) then 7\n        C(x) then 8\nfun bar() =\n  complex_foo(A(10, A(9, B(10))))\nbar()\n//│ |#class| |A|(|w|,| |x|)|↵|#class| |B|(|y|)|↵|#class| |C|(|z|)|↵|#fun| |complex_foo|(|t|)| |#=|→|#let| |a| |#=| |1| |+| |2|↵|#let| |b| |#=| |1| |*| |2|↵|#let| |x| |#=| |#if| |t| |is|→|A|(|x|,| |y|)| |#then| |A|(|x|,| |C|(|0|)|)|↵|B|(|x|)| |#then| |B|(|x| |+| |b|)|↵|C|(|x|)| |#then| |C|(|0|)|←|↵|#let| |z| |#=| |A|(|5|,| |x|)|↵|#let| |v| |#=| |B|(|6|)|↵|#let| |y| |#=| |#if| |x| |is|→|A|(|x|,| |y|)| |#then|→|#let| |m| |#=| |x| |+| |a| |+| |b|↵|#if| |y| |is|→|A|(|x|,| |y|)| |#then| |x|↵|B|(|x|)| |#then| |m|↵|C|(|x|)| |#then| |0|←|←|↵|B|(|x|)| |#then| |2|↵|C|(|x|)| |#then| |3|←|↵|#if| |z| |is|→|A|(|x|,| |y|)| |#then| |x|↵|B|(|x|)| |#then| |4|↵|C|(|x|)| |#then|→|#if| |v| |is|→|A|(|x|,| |y|)| |#then| |x|↵|B|(|x|)| |#then| |7|↵|C|(|x|)| |#then| |8|←|←|←|←|↵|#fun| |bar|(||)| |#=|→|complex_foo|(|A|(|10|,| |A|(|9|,| |B|(|10|)|)|)|)|←|↵|bar|(||)|\n//│ Parsed: {class A(w, x,) {}; class B(y,) {}; class C(z,) {}; fun complex_foo = (t,) => {let a = +(1, 2,); let b = *(1, 2,); let x = if t is ‹(A(x, y,)) then A(x, C(0,),); (B(x,)) then B(+(x, b,),); (C(x,)) then C(0,)›; let z = A(5, x,); let v = B(6,); let y = if x is ‹(A(x, y,)) then {let m = +(+(x, a,), b,); if y is ‹(A(x, y,)) then x; (B(x,)) then m; (C(x,)) then 0›}; (B(x,)) then 2; (C(x,)) then 3›; if z is ‹(A(x, y,)) then x; (B(x,)) then 4; (C(x,)) then {if v is ‹(A(x, y,)) then x; (B(x,)) then 7; (C(x,)) then 8›}›}; fun bar = () => {complex_foo(A(10, A(9, B(10,),),),)}; bar()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class A(w,x)\n//│   class B(y)\n//│   class C(z)\n//│   def complex_foo(t$0) =\n//│     let x$1 = +(1,2) in -- #208\n//│     let x$2 = *(1,2) in -- #207\n//│     case t$0 of -- #206\n//│       A =>\n//│         let x$28 = A.x(t$0) in -- #177\n//│         let x$29 = A.w(t$0) in -- #176\n//│         let x$30 = C(0) in -- #175\n//│         let x$31 = A(x$29,x$30) in -- #174\n//│         jump j$0(x$31,x$1,x$2) -- #173\n//│       B =>\n//│         let x$32 = B.y(t$0) in -- #194\n//│         let x$33 = +(x$32,x$2) in -- #193\n//│         let x$34 = B(x$33) in -- #192\n//│         jump j$0(x$34,x$1,x$2) -- #191\n//│       C =>\n//│         let x$35 = C.z(t$0) in -- #205\n//│         let x$36 = C(0) in -- #204\n//│         jump j$0(x$36,x$1,x$2) -- #203\n//│   def j$2(x$7) =\n//│     x$7 -- #30\n//│   def j$3(x$12) =\n//│     jump j$2(x$12) -- #56\n//│   def j$1(x$6,x$4,x$5) =\n//│     case x$4 of -- #85\n//│       A =>\n//│         let x$8 = A.x(x$4) in -- #42\n//│         let x$9 = A.w(x$4) in -- #41\n//│         jump j$2(x$9) -- #40\n//│       B =>\n//│         let x$10 = B.y(x$4) in -- #49\n//│         jump j$2(4) -- #48\n//│       C =>\n//│         let x$11 = C.z(x$4) in -- #84\n//│         case x$5 of -- #83\n//│           A =>\n//│             let x$13 = A.x(x$5) in -- #68\n//│             let x$14 = A.w(x$5) in -- #67\n//│             jump j$3(x$14) -- #66\n//│           B =>\n//│             let x$15 = B.y(x$5) in -- #75\n//│             jump j$3(7) -- #74\n//│           C =>\n//│             let x$16 = C.z(x$5) in -- #82\n//│             jump j$3(8) -- #81\n//│   def j$4(x$21,x$4,x$5) =\n//│     jump j$1(x$21,x$4,x$5) -- #107\n//│   def j$0(x$3,x$1,x$2) =\n//│     let x$4 = A(5,x$3) in -- #155\n//│     let x$5 = B(6) in -- #154\n//│     case x$3 of -- #153\n//│       A =>\n//│         let x$17 = A.x(x$3) in -- #138\n//│         let x$18 = A.w(x$3) in -- #137\n//│         let x$19 = +(x$18,x$1) in -- #136\n//│         let x$20 = +(x$19,x$2) in -- #135\n//│         case x$17 of -- #134\n//│           A =>\n//│             let x$22 = A.x(x$17) in -- #119\n//│             let x$23 = A.w(x$17) in -- #118\n//│             jump j$4(x$23,x$4,x$5) -- #117\n//│           B =>\n//│             let x$24 = B.y(x$17) in -- #126\n//│             jump j$4(x$20,x$4,x$5) -- #125\n//│           C =>\n//│             let x$25 = C.z(x$17) in -- #133\n//│             jump j$4(0,x$4,x$5) -- #132\n//│       B =>\n//│         let x$26 = B.y(x$3) in -- #145\n//│         jump j$1(2,x$4,x$5) -- #144\n//│       C =>\n//│         let x$27 = C.z(x$3) in -- #152\n//│         jump j$1(3,x$4,x$5) -- #151\n//│   def bar() =\n//│     let x$37 = B(10) in -- #229\n//│     let x$38 = A(9,x$37) in -- #228\n//│     let x$39 = A(10,x$38) in -- #227\n//│     let* (x$40) = complex_foo(x$39) in -- #226\n//│     x$40 -- #225\n//│   let* (x$0) = bar() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 5\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/IRRec.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:interpIR\n:genCpp\nfun fib(n) = if n < 2 then n else fib(n-1) + fib(n-2)\nfib(20)\n//│ |#fun| |fib|(|n|)| |#=| |#if| |n| |<| |2| |#then| |n| |#else| |fib|(|n|-|1|)| |+| |fib|(|n|-|2|)|↵|fib|(|20|)|\n//│ Parsed: {fun fib = (n,) => if (<(n, 2,)) then n else +(fib(-(n, 1,),), fib(-(n, 2,),),); fib(20,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def fib(n$0) =\n//│     let x$1 = <(n$0,2) in -- #43\n//│     if x$1 -- #42\n//│       true =>\n//│         jump j$0(n$0) -- #13\n//│       false =>\n//│         let x$3 = -(n$0,1) in -- #41\n//│         let* (x$4) = fib(x$3) in -- #40\n//│         let x$5 = -(n$0,2) in -- #39\n//│         let* (x$6) = fib(x$5) in -- #38\n//│         let x$7 = +(x$4,x$6) in -- #37\n//│         jump j$0(x$7) -- #36\n//│   def j$0(x$2) =\n//│     x$2 -- #11\n//│   let* (x$0) = fib(20) in -- #4\n//│   x$0 -- #3\n//│ \n//│ Interpreted:\n//│ 6765\n//│ \n\n:interpIR\n:genCpp\nfun odd(x) = if x == 0 then False else even(x-1)\nfun even(x) = if x == 0 then True else odd(x-1)\nfun foo() = odd(10)\nfoo()\n//│ |#fun| |odd|(|x|)| |#=| |#if| |x| |==| |0| |#then| |False| |#else| |even|(|x|-|1|)|↵|#fun| |even|(|x|)| |#=| |#if| |x| |==| |0| |#then| |True| |#else| |odd|(|x|-|1|)|↵|#fun| |foo|(||)| |#=| |odd|(|10|)|↵|foo|(||)|\n//│ Parsed: {fun odd = (x,) => if (==(x, 0,)) then False else even(-(x, 1,),); fun even = (x,) => if (==(x, 0,)) then True else odd(-(x, 1,),); fun foo = () => odd(10,); foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def odd(x$1) =\n//│     let x$2 = ==(x$1,0) in -- #26\n//│     if x$2 -- #25\n//│       true =>\n//│         let x$4 = False() in -- #12\n//│         jump j$0(x$4) -- #11\n//│       false =>\n//│         let x$5 = -(x$1,1) in -- #24\n//│         let* (x$6) = even(x$5) in -- #23\n//│         jump j$0(x$6) -- #22\n//│   def j$0(x$3) =\n//│     x$3 -- #9\n//│   def even(x$7) =\n//│     let x$8 = ==(x$7,0) in -- #50\n//│     if x$8 -- #49\n//│       true =>\n//│         let x$10 = True() in -- #36\n//│         jump j$1(x$10) -- #35\n//│       false =>\n//│         let x$11 = -(x$7,1) in -- #48\n//│         let* (x$12) = odd(x$11) in -- #47\n//│         jump j$1(x$12) -- #46\n//│   def j$1(x$9) =\n//│     x$9 -- #33\n//│   def foo() =\n//│     let* (x$13) = odd(10) in -- #55\n//│     x$13 -- #54\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ False()\n//│ \n\n:interpIR\n:genCpp\nfun not(x) =\n  if x then False else True\nfun foo(x) =\n  if x then None\n       else Some(foo(not(x)))\nfun main() = foo(False)\nmain()\n//│ |#fun| |not|(|x|)| |#=|→|#if| |x| |#then| |False| |#else| |True|←|↵|#fun| |foo|(|x|)| |#=|→|#if| |x| |#then| |None|→|#else| |Some|(|foo|(|not|(|x|)|)|)|←|←|↵|#fun| |main|(||)| |#=| |foo|(|False|)|↵|main|(||)|\n//│ Parsed: {fun not = (x,) => {if (x) then False else True}; fun foo = (x,) => {if (x) then None else Some(foo(not(x,),),)}; fun main = () => foo(False,); main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def not(x$1) =\n//│     if x$1 -- #11\n//│       true =>\n//│         let x$3 = False() in -- #7\n//│         jump j$0(x$3) -- #6\n//│       false =>\n//│         let x$4 = True() in -- #10\n//│         jump j$0(x$4) -- #9\n//│   def j$0(x$2) =\n//│     x$2 -- #4\n//│   def foo(x$5) =\n//│     if x$5 -- #31\n//│       true =>\n//│         let x$7 = None() in -- #16\n//│         jump j$1(x$7) -- #15\n//│       false =>\n//│         let* (x$8) = not(x$5) in -- #30\n//│         let* (x$9) = foo(x$8) in -- #29\n//│         let x$10 = Some(x$9) in -- #28\n//│         jump j$1(x$10) -- #27\n//│   def j$1(x$6) =\n//│     x$6 -- #13\n//│   def main() =\n//│     let x$11 = False() in -- #37\n//│     let* (x$12) = foo(x$11) in -- #36\n//│     x$12 -- #35\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ Some(None())\n//│ \n\n:interpIR\n:genCpp\nfun aaa() =\n  let m = 1\n  let n = 2\n  let p = 3\n  let q = 4\n  m + n - p + q\nfun bbb() =\n  let x = aaa()\n  x * 100 + 4\nfun not(x) =\n  if x then False else True\nfun foo(x) =\n  if x then None\n       else Some(foo(not(x)))\nfun main() =\n  let x = foo(False)\n  if x is\n    None then aaa()\n    Some(b1) then bbb()\nmain()\n//│ |#fun| |aaa|(||)| |#=|→|#let| |m| |#=| |1|↵|#let| |n| |#=| |2|↵|#let| |p| |#=| |3|↵|#let| |q| |#=| |4|↵|m| |+| |n| |-| |p| |+| |q|←|↵|#fun| |bbb|(||)| |#=|→|#let| |x| |#=| |aaa|(||)|↵|x| |*| |100| |+| |4|←|↵|#fun| |not|(|x|)| |#=|→|#if| |x| |#then| |False| |#else| |True|←|↵|#fun| |foo|(|x|)| |#=|→|#if| |x| |#then| |None|→|#else| |Some|(|foo|(|not|(|x|)|)|)|←|←|↵|#fun| |main|(||)| |#=|→|#let| |x| |#=| |foo|(|False|)|↵|#if| |x| |is|→|None| |#then| |aaa|(||)|↵|Some|(|b1|)| |#then| |bbb|(||)|←|←|↵|main|(||)|\n//│ Parsed: {fun aaa = () => {let m = 1; let n = 2; let p = 3; let q = 4; +(-(+(m, n,), p,), q,)}; fun bbb = () => {let x = aaa(); +(*(x, 100,), 4,)}; fun not = (x,) => {if (x) then False else True}; fun foo = (x,) => {if (x) then None else Some(foo(not(x,),),)}; fun main = () => {let x = foo(False,); if x is ‹(None) then aaa(); (Some(b1,)) then bbb()›}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def aaa() =\n//│     let x$1 = 1 in -- #29\n//│     let x$2 = 2 in -- #28\n//│     let x$3 = 3 in -- #27\n//│     let x$4 = 4 in -- #26\n//│     let x$5 = +(x$1,x$2) in -- #25\n//│     let x$6 = -(x$5,x$3) in -- #24\n//│     let x$7 = +(x$6,x$4) in -- #23\n//│     x$7 -- #22\n//│   def bbb() =\n//│     let* (x$8) = aaa() in -- #45\n//│     let x$9 = *(x$8,100) in -- #44\n//│     let x$10 = +(x$9,4) in -- #43\n//│     x$10 -- #42\n//│   def not(x$11) =\n//│     if x$11 -- #54\n//│       true =>\n//│         let x$13 = False() in -- #50\n//│         jump j$0(x$13) -- #49\n//│       false =>\n//│         let x$14 = True() in -- #53\n//│         jump j$0(x$14) -- #52\n//│   def j$0(x$12) =\n//│     x$12 -- #47\n//│   def foo(x$15) =\n//│     if x$15 -- #74\n//│       true =>\n//│         let x$17 = None() in -- #59\n//│         jump j$1(x$17) -- #58\n//│       false =>\n//│         let* (x$18) = not(x$15) in -- #73\n//│         let* (x$19) = foo(x$18) in -- #72\n//│         let x$20 = Some(x$19) in -- #71\n//│         jump j$1(x$20) -- #70\n//│   def j$1(x$16) =\n//│     x$16 -- #56\n//│   def main() =\n//│     let x$21 = False() in -- #96\n//│     let* (x$22) = foo(x$21) in -- #95\n//│     case x$22 of -- #94\n//│       None =>\n//│         let* (x$24) = aaa() in -- #84\n//│         jump j$2(x$24) -- #83\n//│       Some =>\n//│         let x$25 = Some.x(x$22) in -- #93\n//│         let* (x$26) = bbb() in -- #92\n//│         jump j$2(x$26) -- #91\n//│   def j$2(x$23) =\n//│     x$23 -- #80\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 404\n//│ \n\n\n:interpIR\nfun odd(x) =\n  if x is\n    O then False\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then True\n    S(s) then odd(s)\nfun foo() = odd(S(S(S(O))))\nfoo()\n//│ |#fun| |odd|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |False|↵|S|(|s|)| |#then| |even|(|s|)|←|←|↵|#fun| |even|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |True|↵|S|(|s|)| |#then| |odd|(|s|)|←|←|↵|#fun| |foo|(||)| |#=| |odd|(|S|(|S|(|S|(|O|)|)|)|)|↵|foo|(||)|\n//│ Parsed: {fun odd = (x,) => {if x is ‹(O) then False; (S(s,)) then even(s,)›}; fun even = (x,) => {if x is ‹(O) then True; (S(s,)) then odd(s,)›}; fun foo = () => odd(S(S(S(O,),),),); foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def odd(x$1) =\n//│     case x$1 of -- #19\n//│       O =>\n//│         let x$3 = False() in -- #7\n//│         jump j$0(x$3) -- #6\n//│       S =>\n//│         let x$4 = S.s(x$1) in -- #18\n//│         let* (x$5) = even(x$4) in -- #17\n//│         jump j$0(x$5) -- #16\n//│   def j$0(x$2) =\n//│     x$2 -- #4\n//│   def even(x$6) =\n//│     case x$6 of -- #36\n//│       O =>\n//│         let x$8 = True() in -- #24\n//│         jump j$1(x$8) -- #23\n//│       S =>\n//│         let x$9 = S.s(x$6) in -- #35\n//│         let* (x$10) = odd(x$9) in -- #34\n//│         jump j$1(x$10) -- #33\n//│   def j$1(x$7) =\n//│     x$7 -- #21\n//│   def foo() =\n//│     let x$11 = O() in -- #54\n//│     let x$12 = S(x$11) in -- #53\n//│     let x$13 = S(x$12) in -- #52\n//│     let x$14 = S(x$13) in -- #51\n//│     let* (x$15) = odd(x$14) in -- #50\n//│     x$15 -- #49\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ True()\n//│ \n\n:interpIR\n:genCpp\nfun odd(x) =\n  if x is\n    O then False\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then True\n    S(s) then odd(s)\nfun mk(n) = if n > 0 then S(mk(n - 1)) else O\nfun foo() = odd(mk(10))\nfoo() \n//│ |#fun| |odd|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |False|↵|S|(|s|)| |#then| |even|(|s|)|←|←|↵|#fun| |even|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |True|↵|S|(|s|)| |#then| |odd|(|s|)|←|←|↵|#fun| |mk|(|n|)| |#=| |#if| |n| |>| |0| |#then| |S|(|mk|(|n| |-| |1|)|)| |#else| |O|↵|#fun| |foo|(||)| |#=| |odd|(|mk|(|10|)|)|↵|foo|(||)| |\n//│ Parsed: {fun odd = (x,) => {if x is ‹(O) then False; (S(s,)) then even(s,)›}; fun even = (x,) => {if x is ‹(O) then True; (S(s,)) then odd(s,)›}; fun mk = (n,) => if (>(n, 0,)) then S(mk(-(n, 1,),),) else O; fun foo = () => odd(mk(10,),); foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def odd(x$1) =\n//│     case x$1 of -- #19\n//│       O =>\n//│         let x$3 = False() in -- #7\n//│         jump j$0(x$3) -- #6\n//│       S =>\n//│         let x$4 = S.s(x$1) in -- #18\n//│         let* (x$5) = even(x$4) in -- #17\n//│         jump j$0(x$5) -- #16\n//│   def j$0(x$2) =\n//│     x$2 -- #4\n//│   def even(x$6) =\n//│     case x$6 of -- #36\n//│       O =>\n//│         let x$8 = True() in -- #24\n//│         jump j$1(x$8) -- #23\n//│       S =>\n//│         let x$9 = S.s(x$6) in -- #35\n//│         let* (x$10) = odd(x$9) in -- #34\n//│         jump j$1(x$10) -- #33\n//│   def j$1(x$7) =\n//│     x$7 -- #21\n//│   def mk(n$0) =\n//│     let x$11 = >(n$0,0) in -- #64\n//│     if x$11 -- #63\n//│       true =>\n//│         let x$13 = -(n$0,1) in -- #59\n//│         let* (x$14) = mk(x$13) in -- #58\n//│         let x$15 = S(x$14) in -- #57\n//│         jump j$2(x$15) -- #56\n//│       false =>\n//│         let x$16 = O() in -- #62\n//│         jump j$2(x$16) -- #61\n//│   def j$2(x$12) =\n//│     x$12 -- #43\n//│   def foo() =\n//│     let* (x$17) = mk(10) in -- #73\n//│     let* (x$18) = odd(x$17) in -- #72\n//│     x$18 -- #71\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ False()\n//│ \n\n:interpIR\n:genCpp\nfun odd(x) =\n  if x is\n    O then False\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then True\n    S(s) then odd(s)\nfun mk(n) = if n > 0 then S(mk(n - 1)) else O\nfun foo() = odd(S(S(mk(10))))\nfoo()\n//│ |#fun| |odd|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |False|↵|S|(|s|)| |#then| |even|(|s|)|←|←|↵|#fun| |even|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |True|↵|S|(|s|)| |#then| |odd|(|s|)|←|←|↵|#fun| |mk|(|n|)| |#=| |#if| |n| |>| |0| |#then| |S|(|mk|(|n| |-| |1|)|)| |#else| |O|↵|#fun| |foo|(||)| |#=| |odd|(|S|(|S|(|mk|(|10|)|)|)|)|↵|foo|(||)|\n//│ Parsed: {fun odd = (x,) => {if x is ‹(O) then False; (S(s,)) then even(s,)›}; fun even = (x,) => {if x is ‹(O) then True; (S(s,)) then odd(s,)›}; fun mk = (n,) => if (>(n, 0,)) then S(mk(-(n, 1,),),) else O; fun foo = () => odd(S(S(mk(10,),),),); foo()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def odd(x$1) =\n//│     case x$1 of -- #19\n//│       O =>\n//│         let x$3 = False() in -- #7\n//│         jump j$0(x$3) -- #6\n//│       S =>\n//│         let x$4 = S.s(x$1) in -- #18\n//│         let* (x$5) = even(x$4) in -- #17\n//│         jump j$0(x$5) -- #16\n//│   def j$0(x$2) =\n//│     x$2 -- #4\n//│   def even(x$6) =\n//│     case x$6 of -- #36\n//│       O =>\n//│         let x$8 = True() in -- #24\n//│         jump j$1(x$8) -- #23\n//│       S =>\n//│         let x$9 = S.s(x$6) in -- #35\n//│         let* (x$10) = odd(x$9) in -- #34\n//│         jump j$1(x$10) -- #33\n//│   def j$1(x$7) =\n//│     x$7 -- #21\n//│   def mk(n$0) =\n//│     let x$11 = >(n$0,0) in -- #64\n//│     if x$11 -- #63\n//│       true =>\n//│         let x$13 = -(n$0,1) in -- #59\n//│         let* (x$14) = mk(x$13) in -- #58\n//│         let x$15 = S(x$14) in -- #57\n//│         jump j$2(x$15) -- #56\n//│       false =>\n//│         let x$16 = O() in -- #62\n//│         jump j$2(x$16) -- #61\n//│   def j$2(x$12) =\n//│     x$12 -- #43\n//│   def foo() =\n//│     let* (x$17) = mk(10) in -- #81\n//│     let x$18 = S(x$17) in -- #80\n//│     let x$19 = S(x$18) in -- #79\n//│     let* (x$20) = odd(x$19) in -- #78\n//│     x$20 -- #77\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ False()\n//│ \n\n:interpIR\n:genCpp\nfun odd(x) =\n  if x is\n    O then False\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then True\n    S(s) then odd(s)\nfun foo() = odd(if 10 > 0 then S(O) else O)\nfun bar() = if 10 > 0 then odd(S(O)) else odd(O)\nfun main() =\n  foo()\n  bar()\nmain()\n//│ |#fun| |odd|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |False|↵|S|(|s|)| |#then| |even|(|s|)|←|←|↵|#fun| |even|(|x|)| |#=|→|#if| |x| |is|→|O| |#then| |True|↵|S|(|s|)| |#then| |odd|(|s|)|←|←|↵|#fun| |foo|(||)| |#=| |odd|(|#if| |10| |>| |0| |#then| |S|(|O|)| |#else| |O|)|↵|#fun| |bar|(||)| |#=| |#if| |10| |>| |0| |#then| |odd|(|S|(|O|)|)| |#else| |odd|(|O|)|↵|#fun| |main|(||)| |#=|→|foo|(||)|↵|bar|(||)|←|↵|main|(||)|\n//│ Parsed: {fun odd = (x,) => {if x is ‹(O) then False; (S(s,)) then even(s,)›}; fun even = (x,) => {if x is ‹(O) then True; (S(s,)) then odd(s,)›}; fun foo = () => odd(if (>(10, 0,)) then S(O,) else O,); fun bar = () => if (>(10, 0,)) then odd(S(O,),) else odd(O,); fun main = () => {foo(); bar()}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def odd(x$1) =\n//│     case x$1 of -- #19\n//│       O =>\n//│         let x$3 = False() in -- #7\n//│         jump j$0(x$3) -- #6\n//│       S =>\n//│         let x$4 = S.s(x$1) in -- #18\n//│         let* (x$5) = even(x$4) in -- #17\n//│         jump j$0(x$5) -- #16\n//│   def j$0(x$2) =\n//│     x$2 -- #4\n//│   def even(x$6) =\n//│     case x$6 of -- #36\n//│       O =>\n//│         let x$8 = True() in -- #24\n//│         jump j$1(x$8) -- #23\n//│       S =>\n//│         let x$9 = S.s(x$6) in -- #35\n//│         let* (x$10) = odd(x$9) in -- #34\n//│         jump j$1(x$10) -- #33\n//│   def j$1(x$7) =\n//│     x$7 -- #21\n//│   def foo() =\n//│     let x$11 = >(10,0) in -- #59\n//│     if x$11 -- #58\n//│       true =>\n//│         let x$14 = O() in -- #54\n//│         let x$15 = S(x$14) in -- #53\n//│         jump j$2(x$15) -- #52\n//│       false =>\n//│         let x$16 = O() in -- #57\n//│         jump j$2(x$16) -- #56\n//│   def j$2(x$12) =\n//│     let* (x$13) = odd(x$12) in -- #47\n//│     x$13 -- #46\n//│   def bar() =\n//│     let x$17 = >(10,0) in -- #86\n//│     if x$17 -- #85\n//│       true =>\n//│         let x$19 = O() in -- #77\n//│         let x$20 = S(x$19) in -- #76\n//│         let* (x$21) = odd(x$20) in -- #75\n//│         jump j$3(x$21) -- #74\n//│       false =>\n//│         let x$22 = O() in -- #84\n//│         let* (x$23) = odd(x$22) in -- #83\n//│         jump j$3(x$23) -- #82\n//│   def j$3(x$18) =\n//│     x$18 -- #66\n//│   def main() =\n//│     let* (x$24) = foo() in -- #92\n//│     let* (x$25) = bar() in -- #91\n//│     x$25 -- #90\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ True()\n//│ \n\n:interpIR\n:genCpp\nfun aaa() =\n  let m = 1\n  let n = 2\n  let p = 3\n  let q = 4\n  m + n - p + q\nfun bbb() =\n  let x = aaa()\n  x * 100 + 4\nfun not(x) =\n  if x then False else True\nfun foo(x) =\n  if x then None else Some(foo(not(x)))\nfun main(flag) =\n  let x = foo(flag)\n  if x is\n    None then aaa()\n    Some(b1) then bbb()\nmain(False)\n//│ |#fun| |aaa|(||)| |#=|→|#let| |m| |#=| |1|↵|#let| |n| |#=| |2|↵|#let| |p| |#=| |3|↵|#let| |q| |#=| |4|↵|m| |+| |n| |-| |p| |+| |q|←|↵|#fun| |bbb|(||)| |#=|→|#let| |x| |#=| |aaa|(||)|↵|x| |*| |100| |+| |4|←|↵|#fun| |not|(|x|)| |#=|→|#if| |x| |#then| |False| |#else| |True|←|↵|#fun| |foo|(|x|)| |#=|→|#if| |x| |#then| |None| |#else| |Some|(|foo|(|not|(|x|)|)|)|←|↵|#fun| |main|(|flag|)| |#=|→|#let| |x| |#=| |foo|(|flag|)|↵|#if| |x| |is|→|None| |#then| |aaa|(||)|↵|Some|(|b1|)| |#then| |bbb|(||)|←|←|↵|main|(|False|)|\n//│ Parsed: {fun aaa = () => {let m = 1; let n = 2; let p = 3; let q = 4; +(-(+(m, n,), p,), q,)}; fun bbb = () => {let x = aaa(); +(*(x, 100,), 4,)}; fun not = (x,) => {if (x) then False else True}; fun foo = (x,) => {if (x) then None else Some(foo(not(x,),),)}; fun main = (flag,) => {let x = foo(flag,); if x is ‹(None) then aaa(); (Some(b1,)) then bbb()›}; main(False,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def aaa() =\n//│     let x$2 = 1 in -- #32\n//│     let x$3 = 2 in -- #31\n//│     let x$4 = 3 in -- #30\n//│     let x$5 = 4 in -- #29\n//│     let x$6 = +(x$2,x$3) in -- #28\n//│     let x$7 = -(x$6,x$4) in -- #27\n//│     let x$8 = +(x$7,x$5) in -- #26\n//│     x$8 -- #25\n//│   def bbb() =\n//│     let* (x$9) = aaa() in -- #48\n//│     let x$10 = *(x$9,100) in -- #47\n//│     let x$11 = +(x$10,4) in -- #46\n//│     x$11 -- #45\n//│   def not(x$12) =\n//│     if x$12 -- #57\n//│       true =>\n//│         let x$14 = False() in -- #53\n//│         jump j$0(x$14) -- #52\n//│       false =>\n//│         let x$15 = True() in -- #56\n//│         jump j$0(x$15) -- #55\n//│   def j$0(x$13) =\n//│     x$13 -- #50\n//│   def foo(x$16) =\n//│     if x$16 -- #77\n//│       true =>\n//│         let x$18 = None() in -- #62\n//│         jump j$1(x$18) -- #61\n//│       false =>\n//│         let* (x$19) = not(x$16) in -- #76\n//│         let* (x$20) = foo(x$19) in -- #75\n//│         let x$21 = Some(x$20) in -- #74\n//│         jump j$1(x$21) -- #73\n//│   def j$1(x$17) =\n//│     x$17 -- #59\n//│   def main(flag$0) =\n//│     let* (x$22) = foo(flag$0) in -- #98\n//│     case x$22 of -- #97\n//│       None =>\n//│         let* (x$24) = aaa() in -- #87\n//│         jump j$2(x$24) -- #86\n//│       Some =>\n//│         let x$25 = Some.x(x$22) in -- #96\n//│         let* (x$26) = bbb() in -- #95\n//│         jump j$2(x$26) -- #94\n//│   def j$2(x$23) =\n//│     x$23 -- #83\n//│   let x$0 = False() in -- #5\n//│   let* (x$1) = main(x$0) in -- #4\n//│   x$1 -- #3\n//│ \n//│ Interpreted:\n//│ 404\n//│ \n\n\n:interpIR\n:genCpp\nfun head_opt(l) =\n  if l is\n    Nil then None\n    Cons(h, t) then Some(h)\nfun is_none(o) =\n  if o is\n    None then True\n    Some(x) then False\nfun is_empty(l) =\n  is_none(head_opt(l))\nfun main() =\n  is_empty(Cons(1, Cons(2, Nil)))\nmain()\n//│ |#fun| |head_opt|(|l|)| |#=|→|#if| |l| |is|→|Nil| |#then| |None|↵|Cons|(|h|,| |t|)| |#then| |Some|(|h|)|←|←|↵|#fun| |is_none|(|o|)| |#=|→|#if| |o| |is|→|None| |#then| |True|↵|Some|(|x|)| |#then| |False|←|←|↵|#fun| |is_empty|(|l|)| |#=|→|is_none|(|head_opt|(|l|)|)|←|↵|#fun| |main|(||)| |#=|→|is_empty|(|Cons|(|1|,| |Cons|(|2|,| |Nil|)|)|)|←|↵|main|(||)|\n//│ Parsed: {fun head_opt = (l,) => {if l is ‹(Nil) then None; (Cons(h, t,)) then Some(h,)›}; fun is_none = (o,) => {if o is ‹(None) then True; (Some(x,)) then False›}; fun is_empty = (l,) => {is_none(head_opt(l,),)}; fun main = () => {is_empty(Cons(1, Cons(2, Nil,),),)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def head_opt(l$0) =\n//│     case l$0 of -- #24\n//│       Nil =>\n//│         let x$2 = None() in -- #7\n//│         jump j$0(x$2) -- #6\n//│       Cons =>\n//│         let x$3 = Cons.t(l$0) in -- #23\n//│         let x$4 = Cons.h(l$0) in -- #22\n//│         let x$5 = Some(x$4) in -- #21\n//│         jump j$0(x$5) -- #20\n//│   def j$0(x$1) =\n//│     x$1 -- #4\n//│   def is_none(o$0) =\n//│     case o$0 of -- #38\n//│       None =>\n//│         let x$7 = True() in -- #29\n//│         jump j$1(x$7) -- #28\n//│       Some =>\n//│         let x$8 = Some.x(o$0) in -- #37\n//│         let x$9 = False() in -- #36\n//│         jump j$1(x$9) -- #35\n//│   def j$1(x$6) =\n//│     x$6 -- #26\n//│   def is_empty(l$1) =\n//│     let* (x$10) = head_opt(l$1) in -- #47\n//│     let* (x$11) = is_none(x$10) in -- #46\n//│     x$11 -- #45\n//│   def main() =\n//│     let x$12 = Nil() in -- #65\n//│     let x$13 = Cons(2,x$12) in -- #64\n//│     let x$14 = Cons(1,x$13) in -- #63\n//│     let* (x$15) = is_empty(x$14) in -- #62\n//│     x$15 -- #61\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ False()\n//│ \n\n:interpIR\n:genCpp\nfun mk_list(n) =\n  if n == 0 then Nil else Cons(n, mk_list(n - 1))\nfun head_opt(l) =\n  if l is\n    Nil then None\n    Cons(h, t) then Some(h)\nfun is_none(o) =\n  if o is\n    None then True\n    Some(x) then False\nfun is_empty(l) =\n  is_none(head_opt(l))\nfun main() =\n  is_empty(mk_list(10))\nmain()\n//│ |#fun| |mk_list|(|n|)| |#=|→|#if| |n| |==| |0| |#then| |Nil| |#else| |Cons|(|n|,| |mk_list|(|n| |-| |1|)|)|←|↵|#fun| |head_opt|(|l|)| |#=|→|#if| |l| |is|→|Nil| |#then| |None|↵|Cons|(|h|,| |t|)| |#then| |Some|(|h|)|←|←|↵|#fun| |is_none|(|o|)| |#=|→|#if| |o| |is|→|None| |#then| |True|↵|Some|(|x|)| |#then| |False|←|←|↵|#fun| |is_empty|(|l|)| |#=|→|is_none|(|head_opt|(|l|)|)|←|↵|#fun| |main|(||)| |#=|→|is_empty|(|mk_list|(|10|)|)|←|↵|main|(||)|\n//│ Parsed: {fun mk_list = (n,) => {if (==(n, 0,)) then Nil else Cons(n, mk_list(-(n, 1,),),)}; fun head_opt = (l,) => {if l is ‹(Nil) then None; (Cons(h, t,)) then Some(h,)›}; fun is_none = (o,) => {if o is ‹(None) then True; (Some(x,)) then False›}; fun is_empty = (l,) => {is_none(head_opt(l,),)}; fun main = () => {is_empty(mk_list(10,),)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def mk_list(n$0) =\n//│     let x$1 = ==(n$0,0) in -- #32\n//│     if x$1 -- #31\n//│       true =>\n//│         let x$3 = Nil() in -- #12\n//│         jump j$0(x$3) -- #11\n//│       false =>\n//│         let x$4 = -(n$0,1) in -- #30\n//│         let* (x$5) = mk_list(x$4) in -- #29\n//│         let x$6 = Cons(n$0,x$5) in -- #28\n//│         jump j$0(x$6) -- #27\n//│   def j$0(x$2) =\n//│     x$2 -- #9\n//│   def head_opt(l$0) =\n//│     case l$0 of -- #54\n//│       Nil =>\n//│         let x$8 = None() in -- #37\n//│         jump j$1(x$8) -- #36\n//│       Cons =>\n//│         let x$9 = Cons.t(l$0) in -- #53\n//│         let x$10 = Cons.h(l$0) in -- #52\n//│         let x$11 = Some(x$10) in -- #51\n//│         jump j$1(x$11) -- #50\n//│   def j$1(x$7) =\n//│     x$7 -- #34\n//│   def is_none(o$0) =\n//│     case o$0 of -- #68\n//│       None =>\n//│         let x$13 = True() in -- #59\n//│         jump j$2(x$13) -- #58\n//│       Some =>\n//│         let x$14 = Some.x(o$0) in -- #67\n//│         let x$15 = False() in -- #66\n//│         jump j$2(x$15) -- #65\n//│   def j$2(x$12) =\n//│     x$12 -- #56\n//│   def is_empty(l$1) =\n//│     let* (x$16) = head_opt(l$1) in -- #77\n//│     let* (x$17) = is_none(x$16) in -- #76\n//│     x$17 -- #75\n//│   def main() =\n//│     let* (x$18) = mk_list(10) in -- #86\n//│     let* (x$19) = is_empty(x$18) in -- #85\n//│     x$19 -- #84\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ False()\n//│ \n\n:interpIR\n:genCpp\nfun mk_list(n) =\n  if n == 0 then Nil else Cons(n, mk_list(n - 1))\nfun last_opt(l) =\n  if l is\n    Nil then None\n    Cons(h, t) then\n      if t is\n        Nil then Some(h)\n        Cons(h2, t2) then last_opt(t)\nfun main() =\n  last_opt(mk_list(10))\nmain()\n//│ |#fun| |mk_list|(|n|)| |#=|→|#if| |n| |==| |0| |#then| |Nil| |#else| |Cons|(|n|,| |mk_list|(|n| |-| |1|)|)|←|↵|#fun| |last_opt|(|l|)| |#=|→|#if| |l| |is|→|Nil| |#then| |None|↵|Cons|(|h|,| |t|)| |#then|→|#if| |t| |is|→|Nil| |#then| |Some|(|h|)|↵|Cons|(|h2|,| |t2|)| |#then| |last_opt|(|t|)|←|←|←|←|↵|#fun| |main|(||)| |#=|→|last_opt|(|mk_list|(|10|)|)|←|↵|main|(||)|\n//│ Parsed: {fun mk_list = (n,) => {if (==(n, 0,)) then Nil else Cons(n, mk_list(-(n, 1,),),)}; fun last_opt = (l,) => {if l is ‹(Nil) then None; (Cons(h, t,)) then {if t is ‹(Nil) then Some(h,); (Cons(h2, t2,)) then last_opt(t,)›}›}; fun main = () => {last_opt(mk_list(10,),)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def mk_list(n$0) =\n//│     let x$1 = ==(n$0,0) in -- #32\n//│     if x$1 -- #31\n//│       true =>\n//│         let x$3 = Nil() in -- #12\n//│         jump j$0(x$3) -- #11\n//│       false =>\n//│         let x$4 = -(n$0,1) in -- #30\n//│         let* (x$5) = mk_list(x$4) in -- #29\n//│         let x$6 = Cons(n$0,x$5) in -- #28\n//│         jump j$0(x$6) -- #27\n//│   def j$0(x$2) =\n//│     x$2 -- #9\n//│   def last_opt(l$0) =\n//│     case l$0 of -- #74\n//│       Nil =>\n//│         let x$8 = None() in -- #37\n//│         jump j$1(x$8) -- #36\n//│       Cons =>\n//│         let x$9 = Cons.t(l$0) in -- #73\n//│         let x$10 = Cons.h(l$0) in -- #72\n//│         case x$9 of -- #71\n//│           Nil =>\n//│             let x$12 = Some(x$10) in -- #54\n//│             jump j$2(x$12) -- #53\n//│           Cons =>\n//│             let x$13 = Cons.t(x$9) in -- #70\n//│             let x$14 = Cons.h(x$9) in -- #69\n//│             let* (x$15) = last_opt(x$9) in -- #68\n//│             jump j$2(x$15) -- #67\n//│   def j$1(x$7) =\n//│     x$7 -- #34\n//│   def j$2(x$11) =\n//│     jump j$1(x$11) -- #48\n//│   def main() =\n//│     let* (x$16) = mk_list(10) in -- #83\n//│     let* (x$17) = last_opt(x$16) in -- #82\n//│     x$17 -- #81\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ Some(1)\n//│ \n\n:interpIR\n:genCpp\nfun is_some(o) =\n  if o is\n    Some(x) then True\n    None then False\nfun e0(w) =\n  w + 8 + 9 + 10\nfun e1(a, c) =\n  a + 1 + 2 + 3 + 4\nfun e3(c) =\n  let m = 4\n  let n = 5\n  let p = 6\n  let q = 7\n  if c then m + n + p + q else m + n - p + q\nfun e2(x) =\n  x + 12 + 13 + 14\nfun f(x) =\n  let c1 = is_some(x)\n  let z = e3(c1)\n  let w = if x is\n    Some(a) then e1(a, z)\n    None then e2(z)\n  e0(w)\nfun main() =\n  f(Some(2)) + f(None)\nmain()\n//│ |#fun| |is_some|(|o|)| |#=|→|#if| |o| |is|→|Some|(|x|)| |#then| |True|↵|None| |#then| |False|←|←|↵|#fun| |e0|(|w|)| |#=|→|w| |+| |8| |+| |9| |+| |10|←|↵|#fun| |e1|(|a|,| |c|)| |#=|→|a| |+| |1| |+| |2| |+| |3| |+| |4|←|↵|#fun| |e3|(|c|)| |#=|→|#let| |m| |#=| |4|↵|#let| |n| |#=| |5|↵|#let| |p| |#=| |6|↵|#let| |q| |#=| |7|↵|#if| |c| |#then| |m| |+| |n| |+| |p| |+| |q| |#else| |m| |+| |n| |-| |p| |+| |q|←|↵|#fun| |e2|(|x|)| |#=|→|x| |+| |12| |+| |13| |+| |14|←|↵|#fun| |f|(|x|)| |#=|→|#let| |c1| |#=| |is_some|(|x|)|↵|#let| |z| |#=| |e3|(|c1|)|↵|#let| |w| |#=| |#if| |x| |is|→|Some|(|a|)| |#then| |e1|(|a|,| |z|)|↵|None| |#then| |e2|(|z|)|←|↵|e0|(|w|)|←|↵|#fun| |main|(||)| |#=|→|f|(|Some|(|2|)|)| |+| |f|(|None|)|←|↵|main|(||)|\n//│ Parsed: {fun is_some = (o,) => {if o is ‹(Some(x,)) then True; (None) then False›}; fun e0 = (w,) => {+(+(+(w, 8,), 9,), 10,)}; fun e1 = (a, c,) => {+(+(+(+(a, 1,), 2,), 3,), 4,)}; fun e3 = (c,) => {let m = 4; let n = 5; let p = 6; let q = 7; if (c) then +(+(+(m, n,), p,), q,) else +(-(+(m, n,), p,), q,)}; fun e2 = (x,) => {+(+(+(x, 12,), 13,), 14,)}; fun f = (x,) => {let c1 = is_some(x,); let z = e3(c1,); let w = if x is ‹(Some(a,)) then e1(a, z,); (None) then e2(z,)›; e0(w,)}; fun main = () => {+(f(Some(2,),), f(None,),)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def is_some(o$0) =\n//│     case o$0 of -- #16\n//│       Some =>\n//│         let x$2 = Some.x(o$0) in -- #12\n//│         let x$3 = True() in -- #11\n//│         jump j$0(x$3) -- #10\n//│       None =>\n//│         let x$4 = False() in -- #15\n//│         jump j$0(x$4) -- #14\n//│   def j$0(x$1) =\n//│     x$1 -- #4\n//│   def e0(w$0) =\n//│     let x$5 = +(w$0,8) in -- #35\n//│     let x$6 = +(x$5,9) in -- #34\n//│     let x$7 = +(x$6,10) in -- #33\n//│     x$7 -- #32\n//│   def e1(a$0,c$0) =\n//│     let x$8 = +(a$0,1) in -- #60\n//│     let x$9 = +(x$8,2) in -- #59\n//│     let x$10 = +(x$9,3) in -- #58\n//│     let x$11 = +(x$10,4) in -- #57\n//│     x$11 -- #56\n//│   def e3(c$1) =\n//│     let x$12 = 4 in -- #111\n//│     let x$13 = 5 in -- #110\n//│     let x$14 = 6 in -- #109\n//│     let x$15 = 7 in -- #108\n//│     if c$1 -- #107\n//│       true =>\n//│         let x$17 = +(x$12,x$13) in -- #86\n//│         let x$18 = +(x$17,x$14) in -- #85\n//│         let x$19 = +(x$18,x$15) in -- #84\n//│         jump j$1(x$19) -- #83\n//│       false =>\n//│         let x$20 = +(x$12,x$13) in -- #106\n//│         let x$21 = -(x$20,x$14) in -- #105\n//│         let x$22 = +(x$21,x$15) in -- #104\n//│         jump j$1(x$22) -- #103\n//│   def j$1(x$16) =\n//│     x$16 -- #66\n//│   def e2(x$23) =\n//│     let x$24 = +(x$23,12) in -- #130\n//│     let x$25 = +(x$24,13) in -- #129\n//│     let x$26 = +(x$25,14) in -- #128\n//│     x$26 -- #127\n//│   def f(x$27) =\n//│     let* (x$28) = is_some(x$27) in -- #167\n//│     let* (x$29) = e3(x$28) in -- #166\n//│     case x$27 of -- #165\n//│       Some =>\n//│         let x$32 = Some.x(x$27) in -- #158\n//│         let* (x$33) = e1(x$32,x$29) in -- #157\n//│         jump j$2(x$33) -- #156\n//│       None =>\n//│         let* (x$34) = e2(x$29) in -- #164\n//│         jump j$2(x$34) -- #163\n//│   def j$2(x$30) =\n//│     let* (x$31) = e0(x$30) in -- #145\n//│     x$31 -- #144\n//│   def main() =\n//│     let x$35 = Some(2) in -- #187\n//│     let* (x$36) = f(x$35) in -- #186\n//│     let x$37 = None() in -- #185\n//│     let* (x$38) = f(x$37) in -- #184\n//│     let x$39 = +(x$36,x$38) in -- #183\n//│     x$39 -- #182\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 115\n//│ \n\n:interpIR\n:genCpp\nfun is_some(o) =\n  if o is\n    Some(x) then True\n    None then False\nfun e0(w) =\n  w + 8 + 9 + 10\nfun e1(a, z) =\n  if a > 0 then f(Some(a - 1)) else z\nfun e3(c) =\n  let m = 4\n  let n = 5\n  let p = 6\n  let q = 7\n  if c then m + n + p + q else m + n - p + q\nfun e2(x) =\n  x + 12 + 13 + 14\nfun f(x) =\n  let c1 = is_some(x)\n  let z = e3(c1)\n  let w = if x is\n    Some(a) then e1(a, z)\n    None then e2(z)\n  e0(w)\nfun main() =\n  f(Some(2)) + f(None)\nmain()\n//│ |#fun| |is_some|(|o|)| |#=|→|#if| |o| |is|→|Some|(|x|)| |#then| |True|↵|None| |#then| |False|←|←|↵|#fun| |e0|(|w|)| |#=|→|w| |+| |8| |+| |9| |+| |10|←|↵|#fun| |e1|(|a|,| |z|)| |#=|→|#if| |a| |>| |0| |#then| |f|(|Some|(|a| |-| |1|)|)| |#else| |z|←|↵|#fun| |e3|(|c|)| |#=|→|#let| |m| |#=| |4|↵|#let| |n| |#=| |5|↵|#let| |p| |#=| |6|↵|#let| |q| |#=| |7|↵|#if| |c| |#then| |m| |+| |n| |+| |p| |+| |q| |#else| |m| |+| |n| |-| |p| |+| |q|←|↵|#fun| |e2|(|x|)| |#=|→|x| |+| |12| |+| |13| |+| |14|←|↵|#fun| |f|(|x|)| |#=|→|#let| |c1| |#=| |is_some|(|x|)|↵|#let| |z| |#=| |e3|(|c1|)|↵|#let| |w| |#=| |#if| |x| |is|→|Some|(|a|)| |#then| |e1|(|a|,| |z|)|↵|None| |#then| |e2|(|z|)|←|↵|e0|(|w|)|←|↵|#fun| |main|(||)| |#=|→|f|(|Some|(|2|)|)| |+| |f|(|None|)|←|↵|main|(||)|\n//│ Parsed: {fun is_some = (o,) => {if o is ‹(Some(x,)) then True; (None) then False›}; fun e0 = (w,) => {+(+(+(w, 8,), 9,), 10,)}; fun e1 = (a, z,) => {if (>(a, 0,)) then f(Some(-(a, 1,),),) else z}; fun e3 = (c,) => {let m = 4; let n = 5; let p = 6; let q = 7; if (c) then +(+(+(m, n,), p,), q,) else +(-(+(m, n,), p,), q,)}; fun e2 = (x,) => {+(+(+(x, 12,), 13,), 14,)}; fun f = (x,) => {let c1 = is_some(x,); let z = e3(c1,); let w = if x is ‹(Some(a,)) then e1(a, z,); (None) then e2(z,)›; e0(w,)}; fun main = () => {+(f(Some(2,),), f(None,),)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def is_some(o$0) =\n//│     case o$0 of -- #16\n//│       Some =>\n//│         let x$2 = Some.x(o$0) in -- #12\n//│         let x$3 = True() in -- #11\n//│         jump j$0(x$3) -- #10\n//│       None =>\n//│         let x$4 = False() in -- #15\n//│         jump j$0(x$4) -- #14\n//│   def j$0(x$1) =\n//│     x$1 -- #4\n//│   def e0(w$0) =\n//│     let x$5 = +(w$0,8) in -- #35\n//│     let x$6 = +(x$5,9) in -- #34\n//│     let x$7 = +(x$6,10) in -- #33\n//│     x$7 -- #32\n//│   def e1(a$0,z$0) =\n//│     let x$8 = >(a$0,0) in -- #62\n//│     if x$8 -- #61\n//│       true =>\n//│         let x$10 = -(a$0,1) in -- #58\n//│         let x$11 = Some(x$10) in -- #57\n//│         let* (x$12) = f(x$11) in -- #56\n//│         jump j$1(x$12) -- #55\n//│       false =>\n//│         jump j$1(z$0) -- #60\n//│   def j$1(x$9) =\n//│     x$9 -- #42\n//│   def e3(c$0) =\n//│     let x$13 = 4 in -- #113\n//│     let x$14 = 5 in -- #112\n//│     let x$15 = 6 in -- #111\n//│     let x$16 = 7 in -- #110\n//│     if c$0 -- #109\n//│       true =>\n//│         let x$18 = +(x$13,x$14) in -- #88\n//│         let x$19 = +(x$18,x$15) in -- #87\n//│         let x$20 = +(x$19,x$16) in -- #86\n//│         jump j$2(x$20) -- #85\n//│       false =>\n//│         let x$21 = +(x$13,x$14) in -- #108\n//│         let x$22 = -(x$21,x$15) in -- #107\n//│         let x$23 = +(x$22,x$16) in -- #106\n//│         jump j$2(x$23) -- #105\n//│   def j$2(x$17) =\n//│     x$17 -- #68\n//│   def e2(x$24) =\n//│     let x$25 = +(x$24,12) in -- #132\n//│     let x$26 = +(x$25,13) in -- #131\n//│     let x$27 = +(x$26,14) in -- #130\n//│     x$27 -- #129\n//│   def f(x$28) =\n//│     let* (x$29) = is_some(x$28) in -- #169\n//│     let* (x$30) = e3(x$29) in -- #168\n//│     case x$28 of -- #167\n//│       Some =>\n//│         let x$33 = Some.x(x$28) in -- #160\n//│         let* (x$34) = e1(x$33,x$30) in -- #159\n//│         jump j$3(x$34) -- #158\n//│       None =>\n//│         let* (x$35) = e2(x$30) in -- #166\n//│         jump j$3(x$35) -- #165\n//│   def j$3(x$31) =\n//│     let* (x$32) = e0(x$31) in -- #147\n//│     x$32 -- #146\n//│   def main() =\n//│     let x$36 = Some(2) in -- #189\n//│     let* (x$37) = f(x$36) in -- #188\n//│     let x$38 = None() in -- #187\n//│     let* (x$39) = f(x$38) in -- #186\n//│     let x$40 = +(x$37,x$39) in -- #185\n//│     x$40 -- #184\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 179\n//│ \n\n:genCpp\nfun pred(n) =\n  if n is\n    S(p) then p\n    O then O\nfun plus(n1, n2) =\n  if n1 is\n    O then n2\n    S(p) then S(plus(p, n2))\nfun fib(n) =\n  if n is\n    O then S(O)\n    S(p) then\n      if p is\n        O then S(O)\n        S(q) then plus(fib(p), fib(q))\nfun to_int(n) =\n  if n is\n    O then 0\n    S(p) then 1 + to_int(p)\nfun to_nat(n) =\n  if n == 0 then O\n  else S(to_nat(n - 1))\nfun main() =\n  to_int(fib(to_nat(30)))\nmain()\n//│ |#fun| |pred|(|n|)| |#=|→|#if| |n| |is|→|S|(|p|)| |#then| |p|↵|O| |#then| |O|←|←|↵|#fun| |plus|(|n1|,| |n2|)| |#=|→|#if| |n1| |is|→|O| |#then| |n2|↵|S|(|p|)| |#then| |S|(|plus|(|p|,| |n2|)|)|←|←|↵|#fun| |fib|(|n|)| |#=|→|#if| |n| |is|→|O| |#then| |S|(|O|)|↵|S|(|p|)| |#then|→|#if| |p| |is|→|O| |#then| |S|(|O|)|↵|S|(|q|)| |#then| |plus|(|fib|(|p|)|,| |fib|(|q|)|)|←|←|←|←|↵|#fun| |to_int|(|n|)| |#=|→|#if| |n| |is|→|O| |#then| |0|↵|S|(|p|)| |#then| |1| |+| |to_int|(|p|)|←|←|↵|#fun| |to_nat|(|n|)| |#=|→|#if| |n| |==| |0| |#then| |O|↵|#else| |S|(|to_nat|(|n| |-| |1|)|)|←|↵|#fun| |main|(||)| |#=|→|to_int|(|fib|(|to_nat|(|30|)|)|)|←|↵|main|(||)|\n//│ Parsed: {fun pred = (n,) => {if n is ‹(S(p,)) then p; (O) then O›}; fun plus = (n1, n2,) => {if n1 is ‹(O) then n2; (S(p,)) then S(plus(p, n2,),)›}; fun fib = (n,) => {if n is ‹(O) then S(O,); (S(p,)) then {if p is ‹(O) then S(O,); (S(q,)) then plus(fib(p,), fib(q,),)›}›}; fun to_int = (n,) => {if n is ‹(O) then 0; (S(p,)) then +(1, to_int(p,),)›}; fun to_nat = (n,) => {if (==(n, 0,)) then O else S(to_nat(-(n, 1,),),)}; fun main = () => {to_int(fib(to_nat(30,),),)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def pred(n$0) =\n//│     case n$0 of -- #15\n//│       S =>\n//│         let x$2 = S.s(n$0) in -- #11\n//│         jump j$0(x$2) -- #10\n//│       O =>\n//│         let x$3 = O() in -- #14\n//│         jump j$0(x$3) -- #13\n//│   def j$0(x$1) =\n//│     x$1 -- #4\n//│   def plus(n1$0,n2$0) =\n//│     case n1$0 of -- #37\n//│       O =>\n//│         jump j$1(n2$0) -- #19\n//│       S =>\n//│         let x$5 = S.s(n1$0) in -- #36\n//│         let* (x$6) = plus(x$5,n2$0) in -- #35\n//│         let x$7 = S(x$6) in -- #34\n//│         jump j$1(x$7) -- #33\n//│   def j$1(x$4) =\n//│     x$4 -- #17\n//│   def fib(n$1) =\n//│     case n$1 of -- #84\n//│       O =>\n//│         let x$9 = O() in -- #46\n//│         let x$10 = S(x$9) in -- #45\n//│         jump j$2(x$10) -- #44\n//│       S =>\n//│         let x$11 = S.s(n$1) in -- #83\n//│         case x$11 of -- #82\n//│           O =>\n//│             let x$13 = O() in -- #60\n//│             let x$14 = S(x$13) in -- #59\n//│             jump j$3(x$14) -- #58\n//│           S =>\n//│             let x$15 = S.s(x$11) in -- #81\n//│             let* (x$16) = fib(x$11) in -- #80\n//│             let* (x$17) = fib(x$15) in -- #79\n//│             let* (x$18) = plus(x$16,x$17) in -- #78\n//│             jump j$3(x$18) -- #77\n//│   def j$2(x$8) =\n//│     x$8 -- #39\n//│   def j$3(x$12) =\n//│     jump j$2(x$12) -- #53\n//│   def to_int(n$2) =\n//│     case n$2 of -- #106\n//│       O =>\n//│         jump j$4(0) -- #88\n//│       S =>\n//│         let x$20 = S.s(n$2) in -- #105\n//│         let* (x$21) = to_int(x$20) in -- #104\n//│         let x$22 = +(1,x$21) in -- #103\n//│         jump j$4(x$22) -- #102\n//│   def j$4(x$19) =\n//│     x$19 -- #86\n//│   def to_nat(n$3) =\n//│     let x$23 = ==(n$3,0) in -- #134\n//│     if x$23 -- #133\n//│       true =>\n//│         let x$25 = O() in -- #116\n//│         jump j$5(x$25) -- #115\n//│       false =>\n//│         let x$26 = -(n$3,1) in -- #132\n//│         let* (x$27) = to_nat(x$26) in -- #131\n//│         let x$28 = S(x$27) in -- #130\n//│         jump j$5(x$28) -- #129\n//│   def j$5(x$24) =\n//│     x$24 -- #113\n//│   def main() =\n//│     let* (x$29) = to_nat(30) in -- #147\n//│     let* (x$30) = fib(x$29) in -- #146\n//│     let* (x$31) = to_int(x$30) in -- #145\n//│     x$31 -- #144\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/IRTailRec.mls",
    "content": ":NewParser\n:ParseOnly\n:UseIR\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n\n:noTailRec\n:interpIR\nfun fact(acc, n) =\n  if n == 0 then acc\n  else fact(acc * n, n - 1)\nfact(1, 5)\n//│ |#fun| |fact|(|acc|,| |n|)| |#=|→|#if| |n| |==| |0| |#then| |acc|↵|#else| |fact|(|acc| |*| |n|,| |n| |-| |1|)|←|↵|fact|(|1|,| |5|)|\n//│ Parsed: {fun fact = (acc, n,) => {if (==(n,)(0,)) then acc else fact(*(acc,)(n,), -(n,)(1,),)}; fact(1, 5,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def fact(acc$0,n$0) =\n//│     let x$1 = ==(n$0,0) in -- #28\n//│     if x$1 -- #27\n//│       true =>\n//│         jump j$0(acc$0) -- #12\n//│       false =>\n//│         let x$3 = *(acc$0,n$0) in -- #26\n//│         let x$4 = -(n$0,1) in -- #25\n//│         let* (x$5) = fact(x$3,x$4) in -- #24\n//│         jump j$0(x$5) -- #23\n//│   def j$0(x$2) =\n//│     x$2 -- #10\n//│   let* (x$0) = fact(1,5) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ 120\n\n:interpIR\n@tailrec\nfun fact(acc, n) =\n  if n == 0 then acc\n  else fact(acc * n, n - 1)\nfact(1, 5)\n//│ |@|tailrec|↵|#fun| |fact|(|acc|,| |n|)| |#=|→|#if| |n| |==| |0| |#then| |acc|↵|#else| |fact|(|acc| |*| |n|,| |n| |-| |1|)|←|↵|fact|(|1|,| |5|)|\n//│ Parsed: {fun fact = (acc, n,) => {if (==(n,)(0,)) then acc else fact(*(acc,)(n,), -(n,)(1,),)}; fact(1, 5,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def fact(acc$0,n$0) =\n//│     let x$1 = ==(n$0,0) in -- #28\n//│     if x$1 -- #27\n//│       true =>\n//│         jump j$0(acc$0) -- #12\n//│       false =>\n//│         let x$3 = *(acc$0,n$0) in -- #26\n//│         let x$4 = -(n$0,1) in -- #25\n//│         let* (x$5) = fact(x$3,x$4) in -- #24\n//│         jump j$0(x$5) -- #23\n//│   def j$0(x$2) =\n//│     x$2 -- #10\n//│   let* (x$0) = fact(1,5) in -- #6\n//│   x$0 -- #5\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$0), Set(fact))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def j$0(x$2) =\n//│     x$2 -- #10\n//│   def fact_jp(acc$0,n$0) =\n//│     let x$1 = ==(n$0,0) in -- #40\n//│     if x$1 -- #39\n//│       true =>\n//│         jump j$0(acc$0) -- #35\n//│       false =>\n//│         let x$3 = *(acc$0,n$0) in -- #38\n//│         let x$4 = -(n$0,1) in -- #37\n//│         jump fact_jp(x$3,x$4) -- #36\n//│   def fact(acc$0,n$0) =\n//│     let* (r0) = fact_jp(acc$0,n$0) in -- #42\n//│     r0 -- #41\n//│   let* (x$0) = fact(1,5) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ 120\n\n:interpIR\n@tailrec\nfun fact(acc, n) =\n  val x = if n > 0 then n - 1\n    else 0\n  if x <= 0 then\n    acc\n  else \n    @tailcall fact(n * acc, x) \nfact(1, 5)\n//│ |@|tailrec|↵|#fun| |fact|(|acc|,| |n|)| |#=|→|#val| |x| |#=| |#if| |n| |>| |0| |#then| |n| |-| |1|→|#else| |0|←|↵|#if| |x| |<=| |0| |#then|→|acc|←|↵|#else| |→|@|tailcall| |fact|(|n| |*| |acc|,| |x|)| |←|←|↵|fact|(|1|,| |5|)|\n//│ Parsed: {fun fact = (acc, n,) => {let x = if (>(n,)(0,)) then -(n,)(1,) else 0; if (<=(x,)(0,)) then {acc} else {@tailcall fact(*(n,)(acc,), x,)}}; fact(1, 5,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def fact(acc$0,n$0) =\n//│     let x$1 = >(n$0,0) in -- #38\n//│     if x$1 -- #37\n//│       true =>\n//│         let x$7 = -(n$0,1) in -- #34\n//│         jump j$0(x$7,acc$0,n$0) -- #33\n//│       false =>\n//│         jump j$0(0,acc$0,n$0) -- #36\n//│   def j$1(x$4) =\n//│     x$4 -- #14\n//│   def j$0(x$2,acc$0,n$0) =\n//│     let x$3 = <=(x$2,0) in -- #29\n//│     if x$3 -- #28\n//│       true =>\n//│         jump j$1(acc$0) -- #16\n//│       false =>\n//│         let x$5 = *(n$0,acc$0) in -- #27\n//│         let* (x$6) = @tailcall fact(x$5,x$2) in -- #26\n//│         jump j$1(x$6) -- #25\n//│   let* (x$0) = fact(1,5) in -- #6\n//│   x$0 -- #5\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$1), Set(fact))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def fact(acc$0,n$0) =\n//│     let* (r0) = _fact_j$0_opt$9(0,acc$0,n$0,true,true,true) in -- #64\n//│     r0 -- #63\n//│   def j$1(x$4) =\n//│     x$4 -- #14\n//│   def _fact_j$0_opt$9(tailrecBranch$,fact_acc$0,fact_n$0,j$0_x$2,j$0_acc$0,j$0_n$0) =\n//│     jump _fact_j$0_opt_jp$10(tailrecBranch$,fact_acc$0,fact_n$0,j$0_x$2,j$0_acc$0,j$0_n$0) -- #62\n//│   def _fact_j$0_opt_jp$10(tailrecBranch$,fact_acc$0,fact_n$0,j$0_x$2,j$0_acc$0,j$0_n$0) =\n//│     let scrut = ==(2,tailrecBranch$) in -- #61\n//│     if scrut -- #60\n//│       true =>\n//│         let x$3 = <=(j$0_x$2,0) in -- #59\n//│         if x$3 -- #58\n//│           true =>\n//│             jump j$1(j$0_acc$0) -- #55\n//│           false =>\n//│             let x$5 = *(j$0_n$0,j$0_acc$0) in -- #57\n//│             jump _fact_j$0_opt_jp$10(0,x$5,j$0_x$2,j$0_x$2,j$0_acc$0,j$0_n$0) -- #56\n//│       false =>\n//│         let x$1 = >(fact_n$0,0) in -- #54\n//│         if x$1 -- #53\n//│           true =>\n//│             let x$7 = -(fact_n$0,1) in -- #51\n//│             jump _fact_j$0_opt_jp$10(2,fact_acc$0,fact_n$0,x$7,fact_acc$0,fact_n$0) -- #50\n//│           false =>\n//│             jump _fact_j$0_opt_jp$10(2,fact_acc$0,fact_n$0,0,fact_acc$0,fact_n$0) -- #52\n//│   let* (x$0) = fact(1,5) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ 120\n\n:noTailRec\n:interpIR\nfun double(x) = x * 2\nfun f(n, acc) = if n == 0 then double(acc) else g(n - 1, acc + 1)\nfun g(m, acc) = if m == 0 then -double(acc) else f(m - 1, acc + 1)\ng(6, 0)\n//│ |#fun| |double|(|x|)| |#=| |x| |*| |2|↵|#fun| |f|(|n|,| |acc|)| |#=| |#if| |n| |==| |0| |#then| |double|(|acc|)| |#else| |g|(|n| |-| |1|,| |acc| |+| |1|)|↵|#fun| |g|(|m|,| |acc|)| |#=| |#if| |m| |==| |0| |#then| |-|double|(|acc|)| |#else| |f|(|m| |-| |1|,| |acc| |+| |1|)|↵|g|(|6|,| |0|)|\n//│ Parsed: {fun double = (x,) => *(x,)(2,); fun f = (n, acc,) => if (==(n,)(0,)) then double(acc,) else g(-(n,)(1,), +(acc,)(1,),); fun g = (m, acc,) => if (==(m,)(0,)) then -(0,)(double(acc,),) else f(-(m,)(1,), +(acc,)(1,),); g(6, 0,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def double(x$1) =\n//│     let x$2 = *(x$1,2) in -- #10\n//│     x$2 -- #9\n//│   def f(n$0,acc$0) =\n//│     let x$3 = ==(n$0,0) in -- #36\n//│     if x$3 -- #35\n//│       true =>\n//│         let* (x$5) = double(acc$0) in -- #20\n//│         jump j$0(x$5) -- #19\n//│       false =>\n//│         let x$6 = -(n$0,1) in -- #34\n//│         let x$7 = +(acc$0,1) in -- #33\n//│         let* (x$8) = g(x$6,x$7) in -- #32\n//│         jump j$0(x$8) -- #31\n//│   def j$0(x$4) =\n//│     x$4 -- #14\n//│   def g(m$0,acc$1) =\n//│     let x$9 = ==(m$0,0) in -- #65\n//│     if x$9 -- #64\n//│       true =>\n//│         let* (x$11) = double(acc$1) in -- #49\n//│         let x$12 = -(0,x$11) in -- #48\n//│         jump j$1(x$12) -- #47\n//│       false =>\n//│         let x$13 = -(m$0,1) in -- #63\n//│         let x$14 = +(acc$1,1) in -- #62\n//│         let* (x$15) = f(x$13,x$14) in -- #61\n//│         jump j$1(x$15) -- #60\n//│   def j$1(x$10) =\n//│     x$10 -- #40\n//│   let* (x$0) = g(6,0) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ -12\n\n:interpIR\nfun double(x) = x * 2\n@tailrec fun f(n, acc) = if n == 0 then double(acc) else g(n - 1, acc + 1)\n@tailrec fun g(m, acc) = if m == 0 then -double(acc) else f(m - 1, acc + 1)\ng(6, 0)\n//│ |#fun| |double|(|x|)| |#=| |x| |*| |2|↵|@|tailrec| |#fun| |f|(|n|,| |acc|)| |#=| |#if| |n| |==| |0| |#then| |double|(|acc|)| |#else| |g|(|n| |-| |1|,| |acc| |+| |1|)|↵|@|tailrec| |#fun| |g|(|m|,| |acc|)| |#=| |#if| |m| |==| |0| |#then| |-|double|(|acc|)| |#else| |f|(|m| |-| |1|,| |acc| |+| |1|)|↵|g|(|6|,| |0|)|\n//│ Parsed: {fun double = (x,) => *(x,)(2,); fun f = (n, acc,) => if (==(n,)(0,)) then double(acc,) else g(-(n,)(1,), +(acc,)(1,),); fun g = (m, acc,) => if (==(m,)(0,)) then -(0,)(double(acc,),) else f(-(m,)(1,), +(acc,)(1,),); g(6, 0,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def double(x$1) =\n//│     let x$2 = *(x$1,2) in -- #10\n//│     x$2 -- #9\n//│   def f(n$0,acc$0) =\n//│     let x$3 = ==(n$0,0) in -- #36\n//│     if x$3 -- #35\n//│       true =>\n//│         let* (x$5) = double(acc$0) in -- #20\n//│         jump j$0(x$5) -- #19\n//│       false =>\n//│         let x$6 = -(n$0,1) in -- #34\n//│         let x$7 = +(acc$0,1) in -- #33\n//│         let* (x$8) = g(x$6,x$7) in -- #32\n//│         jump j$0(x$8) -- #31\n//│   def j$0(x$4) =\n//│     x$4 -- #14\n//│   def g(m$0,acc$1) =\n//│     let x$9 = ==(m$0,0) in -- #65\n//│     if x$9 -- #64\n//│       true =>\n//│         let* (x$11) = double(acc$1) in -- #49\n//│         let x$12 = -(0,x$11) in -- #48\n//│         jump j$1(x$12) -- #47\n//│       false =>\n//│         let x$13 = -(m$0,1) in -- #63\n//│         let x$14 = +(acc$1,1) in -- #62\n//│         let* (x$15) = f(x$13,x$14) in -- #61\n//│         jump j$1(x$15) -- #60\n//│   def j$1(x$10) =\n//│     x$10 -- #40\n//│   let* (x$0) = g(6,0) in -- #6\n//│   x$0 -- #5\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$1), Set(j$0), Set(g, f), Set(double))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def double(x$1) =\n//│     let x$2 = *(x$1,2) in -- #10\n//│     x$2 -- #9\n//│   def f(n$0,acc$0) =\n//│     let* (r0) = _g_f_opt$11(1,true,true,n$0,acc$0) in -- #101\n//│     r0 -- #100\n//│   def j$0(x$4) =\n//│     x$4 -- #14\n//│   def g(m$0,acc$1) =\n//│     let* (r0) = _g_f_opt$11(3,m$0,acc$1,true,true) in -- #99\n//│     r0 -- #98\n//│   def j$1(x$10) =\n//│     x$10 -- #40\n//│   def _g_f_opt$11(tailrecBranch$,g_m$0,g_acc$1,f_n$0,f_acc$0) =\n//│     jump _g_f_opt_jp$12(tailrecBranch$,g_m$0,g_acc$1,f_n$0,f_acc$0) -- #97\n//│   def _g_f_opt_jp$12(tailrecBranch$,g_m$0,g_acc$1,f_n$0,f_acc$0) =\n//│     let scrut = ==(1,tailrecBranch$) in -- #96\n//│     if scrut -- #95\n//│       true =>\n//│         let x$3 = ==(f_n$0,0) in -- #94\n//│         if x$3 -- #93\n//│           true =>\n//│             let* (x$5) = double(f_acc$0) in -- #89\n//│             jump j$0(x$5) -- #88\n//│           false =>\n//│             let x$6 = -(f_n$0,1) in -- #92\n//│             let x$7 = +(f_acc$0,1) in -- #91\n//│             jump _g_f_opt_jp$12(3,x$6,x$7,f_n$0,f_acc$0) -- #90\n//│       false =>\n//│         let x$9 = ==(g_m$0,0) in -- #87\n//│         if x$9 -- #86\n//│           true =>\n//│             let* (x$11) = double(g_acc$1) in -- #82\n//│             let x$12 = -(0,x$11) in -- #81\n//│             jump j$1(x$12) -- #80\n//│           false =>\n//│             let x$13 = -(g_m$0,1) in -- #85\n//│             let x$14 = +(g_acc$1,1) in -- #84\n//│             jump _g_f_opt_jp$12(1,g_m$0,g_acc$1,x$13,x$14) -- #83\n//│   let* (x$0) = g(6,0) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ -12\n\n@tailrec fun f(a, b, c) = g(0, 0)\n@tailrec fun g(d, e) = h(0, 0, 0, 0)\n@tailrec fun h(p, q, r, s) = f(0, 0, 0)\n2 \n//│ |@|tailrec| |#fun| |f|(|a|,| |b|,| |c|)| |#=| |g|(|0|,| |0|)|↵|@|tailrec| |#fun| |g|(|d|,| |e|)| |#=| |h|(|0|,| |0|,| |0|,| |0|)|↵|@|tailrec| |#fun| |h|(|p|,| |q|,| |r|,| |s|)| |#=| |f|(|0|,| |0|,| |0|)|↵|2| |\n//│ Parsed: {fun f = (a, b, c,) => g(0, 0,); fun g = (d, e,) => h(0, 0, 0, 0,); fun h = (p, q, r, s,) => f(0, 0, 0,); 2}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def f(a$0,b$0,c$0) =\n//│     let* (x$0) = g(0,0) in -- #7\n//│     x$0 -- #6\n//│   def g(d$0,e$0) =\n//│     let* (x$1) = h(0,0,0,0) in -- #18\n//│     x$1 -- #17\n//│   def h(p$0,q$0,r$0,s$0) =\n//│     let* (x$2) = f(0,0,0) in -- #27\n//│     x$2 -- #26\n//│   2 -- #0\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(h, g, f))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def f(a$0,b$0,c$0) =\n//│     let* (r0) = _h_g_f_opt$9(0,true,true,true,true,true,true,a$0,b$0,c$0) in -- #48\n//│     r0 -- #47\n//│   def g(d$0,e$0) =\n//│     let* (r0) = _h_g_f_opt$9(1,true,true,true,true,d$0,e$0,true,true,true) in -- #46\n//│     r0 -- #45\n//│   def h(p$0,q$0,r$0,s$0) =\n//│     let* (r0) = _h_g_f_opt$9(2,p$0,q$0,r$0,s$0,true,true,true,true,true) in -- #44\n//│     r0 -- #43\n//│   def _h_g_f_opt$9(tailrecBranch$,h_p$0,h_q$0,h_r$0,h_s$0,g_d$0,g_e$0,f_a$0,f_b$0,f_c$0) =\n//│     jump _h_g_f_opt_jp$10(tailrecBranch$,h_p$0,h_q$0,h_r$0,h_s$0,g_d$0,g_e$0,f_a$0,f_b$0,f_c$0) -- #42\n//│   def _h_g_f_opt_jp$10(tailrecBranch$,h_p$0,h_q$0,h_r$0,h_s$0,g_d$0,g_e$0,f_a$0,f_b$0,f_c$0) =\n//│     let scrut = ==(0,tailrecBranch$) in -- #41\n//│     if scrut -- #40\n//│       true =>\n//│         jump _h_g_f_opt_jp$10(1,h_p$0,h_q$0,h_r$0,h_s$0,0,0,f_a$0,f_b$0,f_c$0) -- #37\n//│       false =>\n//│         let scrut = ==(1,tailrecBranch$) in -- #39\n//│         if scrut -- #38\n//│           true =>\n//│             jump _h_g_f_opt_jp$10(2,0,0,0,0,g_d$0,g_e$0,f_a$0,f_b$0,f_c$0) -- #36\n//│           false =>\n//│             jump _h_g_f_opt_jp$10(0,h_p$0,h_q$0,h_r$0,h_s$0,g_d$0,g_e$0,0,0,0) -- #35\n//│   2 -- #0\n\n:ce\nfun hello() =\n    @tailcall hello()\n    @tailcall hello()\n    2\nhello() \n//│ |#fun| |hello|(||)| |#=|→|@|tailcall| |hello|(||)|↵|@|tailcall| |hello|(||)|↵|2|←|↵|hello|(||)| |\n//│ Parsed: {fun hello = () => {@tailcall hello(); @tailcall hello(); 2}; hello()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def hello() =\n//│     let* (x$1) = @tailcall hello() in -- #9\n//│     let* (x$2) = @tailcall hello() in -- #8\n//│     2 -- #7\n//│   let* (x$0) = hello() in -- #2\n//│   x$0 -- #1\n//│ ╔══[COMPILATION ERROR] not a tail call, as the remaining functions may be impure\n//│ ║  l.396: \t    @tailcall hello()\n//│ ╙──       \t              ^^^^^\n//│ ╔══[COMPILATION ERROR] not a tail call\n//│ ║  l.397: \t    @tailcall hello()\n//│ ╙──       \t              ^^^^^\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(hello))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def hello() =\n//│     let* (x$1) = @tailcall hello() in -- #9\n//│     let* (x$2) = @tailcall hello() in -- #8\n//│     2 -- #7\n//│   let* (x$0) = hello() in -- #2\n//│   x$0 -- #1\n\n:ce\nfun hello() =\n    @tailcall hello()\n    2\nhello() \n//│ |#fun| |hello|(||)| |#=|→|@|tailcall| |hello|(||)|↵|2|←|↵|hello|(||)| |\n//│ Parsed: {fun hello = () => {@tailcall hello(); 2}; hello()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def hello() =\n//│     let* (x$1) = @tailcall hello() in -- #6\n//│     2 -- #5\n//│   let* (x$0) = hello() in -- #2\n//│   x$0 -- #1\n//│ ╔══[COMPILATION ERROR] not a tail call\n//│ ║  l.435: \t    @tailcall hello()\n//│ ╙──       \t              ^^^^^\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(hello))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def hello() =\n//│     let* (x$1) = @tailcall hello() in -- #6\n//│     2 -- #5\n//│   let* (x$0) = hello() in -- #2\n//│   x$0 -- #1\n\n:interpIR\n@tailrec fun addOne(xs) =\n  if xs is\n    Cons(h, t) then Cons(h + 1, @tailcall addOne(t))\n    Nil then Nil\naddOne(Cons(1, Cons(2, Cons(3, Nil))))\n//│ |@|tailrec| |#fun| |addOne|(|xs|)| |#=|→|#if| |xs| |is|→|Cons|(|h|,| |t|)| |#then| |Cons|(|h| |+| |1|,| |@|tailcall| |addOne|(|t|)|)|↵|Nil| |#then| |Nil|←|←|↵|addOne|(|Cons|(|1|,| |Cons|(|2|,| |Cons|(|3|,| |Nil|)|)|)|)|\n//│ Parsed: {fun addOne = (xs,) => {if xs is ‹(Cons(h, t,)) then Cons(+(h,)(1,), @tailcall addOne(t,),); (Nil) then Nil›}; addOne(Cons(1, Cons(2, Cons(3, Nil,),),),)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def addOne(xs$0) =\n//│     case xs$0 of -- #54\n//│       Cons =>\n//│         let x$6 = Cons.t(xs$0) in -- #50\n//│         let x$7 = Cons.h(xs$0) in -- #49\n//│         let x$8 = +(x$7,1) in -- #48\n//│         let* (x$9) = @tailcall addOne(x$6) in -- #47\n//│         let x$10 = Cons(x$8,x$9) in -- #46\n//│         jump j$0(x$10) -- #45\n//│       Nil =>\n//│         let x$11 = Nil() in -- #53\n//│         jump j$0(x$11) -- #52\n//│   def j$0(x$5) =\n//│     x$5 -- #25\n//│   let x$0 = Nil() in -- #23\n//│   let x$1 = Cons(3,x$0) in -- #22\n//│   let x$2 = Cons(2,x$1) in -- #21\n//│   let x$3 = Cons(1,x$2) in -- #20\n//│   let* (x$4) = addOne(x$3) in -- #19\n//│   x$4 -- #18\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$0), Set(addOne))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def addOne(xs$0) =\n//│     let idCtx = _IdContext() in -- #88\n//│     let* (res) = addOne_modcons$10(idCtx,xs$0) in -- #87\n//│     res -- #86\n//│   def j$0(x$5) =\n//│     x$5 -- #25\n//│   def _addOne_ctx_app$8(ctx,x) =\n//│     case ctx of -- #67\n//│       _IdContext =>\n//│         x -- #66\n//│       _Context =>\n//│         let field = _Context.field(ctx) in -- #65\n//│         let ptr = _Context.ptr(ctx) in -- #64\n//│         let _ = assign ptr.t := x in -- #63\n//│         let acc = _Context.acc(ctx) in -- #62\n//│         acc -- #61\n//│   def _addOne_ctx_comp$9(ctx1,ctx2) =\n//│     let ctx2acc = _Context.acc(ctx2) in -- #73\n//│     let ctx2ptr = _Context.ptr(ctx2) in -- #72\n//│     let ctx2field = _Context.field(ctx2) in -- #71\n//│     let* (newAcc) = _addOne_ctx_app$8(ctx1,ctx2acc) in -- #70\n//│     let ret = _Context(newAcc,ctx2ptr,ctx2field) in -- #69\n//│     ret -- #68\n//│   def addOne_modcons$10_jp(ctx,xs$0) =\n//│     case xs$0 of -- #99\n//│       Cons =>\n//│         let x$6 = Cons.t(xs$0) in -- #95\n//│         let x$7 = Cons.h(xs$0) in -- #94\n//│         let x$8 = +(x$7,1) in -- #93\n//│         let x$10 = Cons(x$8,0) in -- #92\n//│         let ctx2 = _Context(x$10,x$10,0) in -- #91\n//│         let* (composed) = _addOne_ctx_comp$9(ctx,ctx2) in -- #90\n//│         jump addOne_modcons$10_jp(composed,x$6) -- #89\n//│       Nil =>\n//│         let x$11 = Nil() in -- #98\n//│         let* (res) = _addOne_ctx_app$8(ctx,x$11) in -- #97\n//│         res -- #96\n//│   def addOne_modcons$10(ctx,xs$0) =\n//│     let* (r0) = addOne_modcons$10_jp(ctx,xs$0) in -- #101\n//│     r0 -- #100\n//│   let x$0 = Nil() in -- #23\n//│   let x$1 = Cons(3,x$0) in -- #22\n//│   let x$2 = Cons(2,x$1) in -- #21\n//│   let x$3 = Cons(1,x$2) in -- #20\n//│   let* (x$4) = addOne(x$3) in -- #19\n//│   x$4 -- #18\n//│ \n//│ Interpreted:\n//│ Cons(2,0)\n\n:noTailRec\n:interpIR\nclass Zero\nclass S(x)\nfun a(n) =\n  if n is\n    S(x) then S(@tailcall b(x))\n    Zero then S(Zero)\nfun b(n) =\n  if n is\n    S(x) then S(S(@tailcall a(x)))\n    Zero then S(S(Zero))\na(S(S(S(Zero))))\n//│ |#class| |Zero|↵|#class| |S|(|x|)|↵|#fun| |a|(|n|)| |#=|→|#if| |n| |is|→|S|(|x|)| |#then| |S|(|@|tailcall| |b|(|x|)|)|↵|Zero| |#then| |S|(|Zero|)|←|←|↵|#fun| |b|(|n|)| |#=|→|#if| |n| |is|→|S|(|x|)| |#then| |S|(|S|(|@|tailcall| |a|(|x|)|)|)|↵|Zero| |#then| |S|(|S|(|Zero|)|)|←|←|↵|a|(|S|(|S|(|S|(|Zero|)|)|)|)|\n//│ Parsed: {class Zero {}; class S(x,) {}; fun a = (n,) => {if n is ‹(S(x,)) then S(@tailcall b(x,),); (Zero) then S(Zero,)›}; fun b = (n,) => {if n is ‹(S(x,)) then S(S(@tailcall a(x,),),); (Zero) then S(S(Zero,),)›}; a(S(S(S(Zero,),),),)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Zero()\n//│   def a(n$0) =\n//│     case n$0 of -- #42\n//│       S =>\n//│         let x$6 = S.s(n$0) in -- #34\n//│         let* (x$7) = @tailcall b(x$6) in -- #33\n//│         let x$8 = S(x$7) in -- #32\n//│         jump j$0(x$8) -- #31\n//│       Zero =>\n//│         let x$9 = Zero() in -- #41\n//│         let x$10 = S(x$9) in -- #40\n//│         jump j$0(x$10) -- #39\n//│   def j$0(x$5) =\n//│     x$5 -- #19\n//│   def b(n$1) =\n//│     case n$1 of -- #75\n//│       S =>\n//│         let x$12 = S.s(n$1) in -- #63\n//│         let* (x$13) = @tailcall a(x$12) in -- #62\n//│         let x$14 = S(x$13) in -- #61\n//│         let x$15 = S(x$14) in -- #60\n//│         jump j$1(x$15) -- #59\n//│       Zero =>\n//│         let x$16 = Zero() in -- #74\n//│         let x$17 = S(x$16) in -- #73\n//│         let x$18 = S(x$17) in -- #72\n//│         jump j$1(x$18) -- #71\n//│   def j$1(x$11) =\n//│     x$11 -- #44\n//│   let x$0 = Zero() in -- #17\n//│   let x$1 = S(x$0) in -- #16\n//│   let x$2 = S(x$1) in -- #15\n//│   let x$3 = S(x$2) in -- #14\n//│   let* (x$4) = a(x$3) in -- #13\n//│   x$4 -- #12\n//│ \n//│ Interpreted:\n//│ S(S(S(S(S(S(Zero()))))))\n\n:interpIR\nclass Zero\nclass S(x)\n@tailrec fun a(n) =\n  if n is\n    S(x) then S(@tailcall b(x))\n    Zero then S(Zero)\n@tailrec fun b(n) =\n  if n is\n    S(x) then S(S(@tailcall a(x)))\n    Zero then S(S(Zero))\na(S(S(S(Zero))))\n//│ |#class| |Zero|↵|#class| |S|(|x|)|↵|@|tailrec| |#fun| |a|(|n|)| |#=|→|#if| |n| |is|→|S|(|x|)| |#then| |S|(|@|tailcall| |b|(|x|)|)|↵|Zero| |#then| |S|(|Zero|)|←|←|↵|@|tailrec| |#fun| |b|(|n|)| |#=|→|#if| |n| |is|→|S|(|x|)| |#then| |S|(|S|(|@|tailcall| |a|(|x|)|)|)|↵|Zero| |#then| |S|(|S|(|Zero|)|)|←|←|↵|a|(|S|(|S|(|S|(|Zero|)|)|)|)|\n//│ Parsed: {class Zero {}; class S(x,) {}; fun a = (n,) => {if n is ‹(S(x,)) then S(@tailcall b(x,),); (Zero) then S(Zero,)›}; fun b = (n,) => {if n is ‹(S(x,)) then S(S(@tailcall a(x,),),); (Zero) then S(S(Zero,),)›}; a(S(S(S(Zero,),),),)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Zero()\n//│   def a(n$0) =\n//│     case n$0 of -- #42\n//│       S =>\n//│         let x$6 = S.s(n$0) in -- #34\n//│         let* (x$7) = @tailcall b(x$6) in -- #33\n//│         let x$8 = S(x$7) in -- #32\n//│         jump j$0(x$8) -- #31\n//│       Zero =>\n//│         let x$9 = Zero() in -- #41\n//│         let x$10 = S(x$9) in -- #40\n//│         jump j$0(x$10) -- #39\n//│   def j$0(x$5) =\n//│     x$5 -- #19\n//│   def b(n$1) =\n//│     case n$1 of -- #75\n//│       S =>\n//│         let x$12 = S.s(n$1) in -- #63\n//│         let* (x$13) = @tailcall a(x$12) in -- #62\n//│         let x$14 = S(x$13) in -- #61\n//│         let x$15 = S(x$14) in -- #60\n//│         jump j$1(x$15) -- #59\n//│       Zero =>\n//│         let x$16 = Zero() in -- #74\n//│         let x$17 = S(x$16) in -- #73\n//│         let x$18 = S(x$17) in -- #72\n//│         jump j$1(x$18) -- #71\n//│   def j$1(x$11) =\n//│     x$11 -- #44\n//│   let x$0 = Zero() in -- #17\n//│   let x$1 = S(x$0) in -- #16\n//│   let x$2 = S(x$1) in -- #15\n//│   let x$3 = S(x$2) in -- #14\n//│   let* (x$4) = a(x$3) in -- #13\n//│   x$4 -- #12\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$1), Set(j$0), Set(b, a))\n//│ Program:\n//│   class Zero()\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def a(n$0) =\n//│     let idCtx = _IdContext() in -- #124\n//│     let* (res) = a_modcons$13(idCtx,n$0) in -- #123\n//│     res -- #122\n//│   def j$0(x$5) =\n//│     x$5 -- #19\n//│   def b(n$1) =\n//│     let idCtx = _IdContext() in -- #110\n//│     let* (res) = b_modcons$12(idCtx,n$1) in -- #109\n//│     res -- #108\n//│   def j$1(x$11) =\n//│     x$11 -- #44\n//│   def _b_a_ctx_app$10(ctx,x) =\n//│     case ctx of -- #88\n//│       _IdContext =>\n//│         x -- #87\n//│       _Context =>\n//│         let field = _Context.field(ctx) in -- #86\n//│         let ptr = _Context.ptr(ctx) in -- #85\n//│         let _ = assign ptr.s := x in -- #84\n//│         let acc = _Context.acc(ctx) in -- #83\n//│         acc -- #82\n//│   def _b_a_ctx_comp$11(ctx1,ctx2) =\n//│     let ctx2acc = _Context.acc(ctx2) in -- #94\n//│     let ctx2ptr = _Context.ptr(ctx2) in -- #93\n//│     let ctx2field = _Context.field(ctx2) in -- #92\n//│     let* (newAcc) = _b_a_ctx_app$10(ctx1,ctx2acc) in -- #91\n//│     let ret = _Context(newAcc,ctx2ptr,ctx2field) in -- #90\n//│     ret -- #89\n//│   def b_modcons$12(ctx,n$1) =\n//│     let* (r0) = _b_modcons$12_a_modcons$13_opt$14(12,ctx,n$1,true,true) in -- #163\n//│     r0 -- #162\n//│   def a_modcons$13(ctx,n$0) =\n//│     let* (r0) = _b_modcons$12_a_modcons$13_opt$14(13,true,true,ctx,n$0) in -- #165\n//│     r0 -- #164\n//│   def _b_modcons$12_a_modcons$13_opt$14(tailrecBranch$,b_modcons$12_ctx,b_modcons$12_n$1,a_modcons$13_ctx,a_modcons$13_n$0) =\n//│     jump _b_modcons$12_a_modcons$13_opt_jp$15(tailrecBranch$,b_modcons$12_ctx,b_modcons$12_n$1,a_modcons$13_ctx,a_modcons$13_n$0) -- #161\n//│   def _b_modcons$12_a_modcons$13_opt_jp$15(tailrecBranch$,b_modcons$12_ctx,b_modcons$12_n$1,a_modcons$13_ctx,a_modcons$13_n$0) =\n//│     let scrut = ==(13,tailrecBranch$) in -- #160\n//│     if scrut -- #159\n//│       true =>\n//│         case a_modcons$13_n$0 of -- #158\n//│           S =>\n//│             let x$6 = S.s(a_modcons$13_n$0) in -- #153\n//│             let x$8 = S(0) in -- #152\n//│             let ctx2 = _Context(x$8,x$8,0) in -- #151\n//│             let* (composed) = _b_a_ctx_comp$11(a_modcons$13_ctx,ctx2) in -- #150\n//│             jump _b_modcons$12_a_modcons$13_opt_jp$15(12,composed,x$6,a_modcons$13_ctx,a_modcons$13_n$0) -- #149\n//│           Zero =>\n//│             let x$9 = Zero() in -- #157\n//│             let x$10 = S(x$9) in -- #156\n//│             let* (res) = _b_a_ctx_app$10(a_modcons$13_ctx,x$10) in -- #155\n//│             res -- #154\n//│       false =>\n//│         case b_modcons$12_n$1 of -- #148\n//│           S =>\n//│             let x$12 = S.s(b_modcons$12_n$1) in -- #142\n//│             let x$14 = S(0) in -- #141\n//│             let x$15 = S(x$14) in -- #140\n//│             let ctx2 = _Context(x$15,x$14,0) in -- #139\n//│             let* (composed) = _b_a_ctx_comp$11(b_modcons$12_ctx,ctx2) in -- #138\n//│             jump _b_modcons$12_a_modcons$13_opt_jp$15(13,b_modcons$12_ctx,b_modcons$12_n$1,composed,x$12) -- #137\n//│           Zero =>\n//│             let x$16 = Zero() in -- #147\n//│             let x$17 = S(x$16) in -- #146\n//│             let x$18 = S(x$17) in -- #145\n//│             let* (res) = _b_a_ctx_app$10(b_modcons$12_ctx,x$18) in -- #144\n//│             res -- #143\n//│   let x$0 = Zero() in -- #17\n//│   let x$1 = S(x$0) in -- #16\n//│   let x$2 = S(x$1) in -- #15\n//│   let x$3 = S(x$2) in -- #14\n//│   let* (x$4) = a(x$3) in -- #13\n//│   x$4 -- #12\n//│ \n//│ Interpreted:\n//│ S(0)\n\n:interpIR\n@tailrec fun addOne(xs) =\n  if xs is \n    Cons(h, t) then\n      val next = @tailcall addOne(t)\n      val ret = Cons(h + 1, next)\n      val rett = ret\n      rett\n    Nil then \n      Nil\naddOne(Cons(1, Cons(2, Cons(3, Nil))))\n//│ |@|tailrec| |#fun| |addOne|(|xs|)| |#=|→|#if| |xs| |is| |→|Cons|(|h|,| |t|)| |#then|→|#val| |next| |#=| |@|tailcall| |addOne|(|t|)|↵|#val| |ret| |#=| |Cons|(|h| |+| |1|,| |next|)|↵|#val| |rett| |#=| |ret|↵|rett|←|↵|Nil| |#then| |→|Nil|←|←|←|↵|addOne|(|Cons|(|1|,| |Cons|(|2|,| |Cons|(|3|,| |Nil|)|)|)|)|\n//│ Parsed: {fun addOne = (xs,) => {if xs is ‹(Cons(h, t,)) then {let next = @tailcall addOne(t,); let ret = Cons(+(h,)(1,), next,); let rett = ret; rett}; (Nil) then {Nil}›}; addOne(Cons(1, Cons(2, Cons(3, Nil,),),),)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def addOne(xs$0) =\n//│     case xs$0 of -- #57\n//│       Cons =>\n//│         let x$6 = Cons.t(xs$0) in -- #53\n//│         let x$7 = Cons.h(xs$0) in -- #52\n//│         let* (x$8) = @tailcall addOne(x$6) in -- #51\n//│         let x$9 = +(x$7,1) in -- #50\n//│         let x$10 = Cons(x$9,x$8) in -- #49\n//│         jump j$0(x$10) -- #48\n//│       Nil =>\n//│         let x$11 = Nil() in -- #56\n//│         jump j$0(x$11) -- #55\n//│   def j$0(x$5) =\n//│     x$5 -- #25\n//│   let x$0 = Nil() in -- #23\n//│   let x$1 = Cons(3,x$0) in -- #22\n//│   let x$2 = Cons(2,x$1) in -- #21\n//│   let x$3 = Cons(1,x$2) in -- #20\n//│   let* (x$4) = addOne(x$3) in -- #19\n//│   x$4 -- #18\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$0), Set(addOne))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def addOne(xs$0) =\n//│     let idCtx = _IdContext() in -- #91\n//│     let* (res) = addOne_modcons$10(idCtx,xs$0) in -- #90\n//│     res -- #89\n//│   def j$0(x$5) =\n//│     x$5 -- #25\n//│   def _addOne_ctx_app$8(ctx,x) =\n//│     case ctx of -- #70\n//│       _IdContext =>\n//│         x -- #69\n//│       _Context =>\n//│         let field = _Context.field(ctx) in -- #68\n//│         let ptr = _Context.ptr(ctx) in -- #67\n//│         let _ = assign ptr.t := x in -- #66\n//│         let acc = _Context.acc(ctx) in -- #65\n//│         acc -- #64\n//│   def _addOne_ctx_comp$9(ctx1,ctx2) =\n//│     let ctx2acc = _Context.acc(ctx2) in -- #76\n//│     let ctx2ptr = _Context.ptr(ctx2) in -- #75\n//│     let ctx2field = _Context.field(ctx2) in -- #74\n//│     let* (newAcc) = _addOne_ctx_app$8(ctx1,ctx2acc) in -- #73\n//│     let ret = _Context(newAcc,ctx2ptr,ctx2field) in -- #72\n//│     ret -- #71\n//│   def addOne_modcons$10_jp(ctx,xs$0) =\n//│     case xs$0 of -- #102\n//│       Cons =>\n//│         let x$6 = Cons.t(xs$0) in -- #98\n//│         let x$7 = Cons.h(xs$0) in -- #97\n//│         let x$9 = +(x$7,1) in -- #96\n//│         let x$10 = Cons(x$9,0) in -- #95\n//│         let ctx2 = _Context(x$10,x$10,0) in -- #94\n//│         let* (composed) = _addOne_ctx_comp$9(ctx,ctx2) in -- #93\n//│         jump addOne_modcons$10_jp(composed,x$6) -- #92\n//│       Nil =>\n//│         let x$11 = Nil() in -- #101\n//│         let* (res) = _addOne_ctx_app$8(ctx,x$11) in -- #100\n//│         res -- #99\n//│   def addOne_modcons$10(ctx,xs$0) =\n//│     let* (r0) = addOne_modcons$10_jp(ctx,xs$0) in -- #104\n//│     r0 -- #103\n//│   let x$0 = Nil() in -- #23\n//│   let x$1 = Cons(3,x$0) in -- #22\n//│   let x$2 = Cons(2,x$1) in -- #21\n//│   let x$3 = Cons(1,x$2) in -- #20\n//│   let* (x$4) = addOne(x$3) in -- #19\n//│   x$4 -- #18\n//│ \n//│ Interpreted:\n//│ Cons(2,0)\n\n:interpIR\n@tailrec fun a(x) =\n  if x is\n    Cons(m, n) then\n      if m < 0 then\n        Cons(-1, Nil)\n      else \n        Cons(m * 4, b(m - 2))\n    Nil then Nil\n@tailrec fun b(n) =\n  if n <= 0 then \n    Cons(0, Nil)\n  else \n    a(Cons(n, Nil))\nb(16)\n//│ |@|tailrec| |#fun| |a|(|x|)| |#=|→|#if| |x| |is|→|Cons|(|m|,| |n|)| |#then|→|#if| |m| |<| |0| |#then|→|Cons|(|-|1|,| |Nil|)|←|↵|#else| |→|Cons|(|m| |*| |4|,| |b|(|m| |-| |2|)|)|←|←|↵|Nil| |#then| |Nil|←|←|↵|@|tailrec| |#fun| |b|(|n|)| |#=|→|#if| |n| |<=| |0| |#then| |→|Cons|(|0|,| |Nil|)|←|↵|#else| |→|a|(|Cons|(|n|,| |Nil|)|)|←|←|↵|b|(|16|)|\n//│ Parsed: {fun a = (x,) => {if x is ‹(Cons(m, n,)) then {if (<(m,)(0,)) then {Cons(-1, Nil,)} else {Cons(*(m,)(4,), b(-(m,)(2,),),)}}; (Nil) then Nil›}; fun b = (n,) => {if (<=(n,)(0,)) then {Cons(0, Nil,)} else {a(Cons(n, Nil,),)}}; b(16,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def a(x$1) =\n//│     case x$1 of -- #54\n//│       Cons =>\n//│         let x$3 = Cons.t(x$1) in -- #50\n//│         let x$4 = Cons.h(x$1) in -- #49\n//│         let x$5 = <(x$4,0) in -- #48\n//│         if x$5 -- #47\n//│           true =>\n//│             let x$7 = Nil() in -- #28\n//│             let x$8 = Cons(-1,x$7) in -- #27\n//│             jump j$1(x$8) -- #26\n//│           false =>\n//│             let x$9 = *(x$4,4) in -- #46\n//│             let x$10 = -(x$4,2) in -- #45\n//│             let* (x$11) = b(x$10) in -- #44\n//│             let x$12 = Cons(x$9,x$11) in -- #43\n//│             jump j$1(x$12) -- #42\n//│       Nil =>\n//│         let x$13 = Nil() in -- #53\n//│         jump j$0(x$13) -- #52\n//│   def j$0(x$2) =\n//│     x$2 -- #6\n//│   def j$1(x$6) =\n//│     jump j$0(x$6) -- #19\n//│   def b(n$0) =\n//│     let x$14 = <=(n$0,0) in -- #82\n//│     if x$14 -- #81\n//│       true =>\n//│         let x$16 = Nil() in -- #67\n//│         let x$17 = Cons(0,x$16) in -- #66\n//│         jump j$2(x$17) -- #65\n//│       false =>\n//│         let x$18 = Nil() in -- #80\n//│         let x$19 = Cons(n$0,x$18) in -- #79\n//│         let* (x$20) = a(x$19) in -- #78\n//│         jump j$2(x$20) -- #77\n//│   def j$2(x$15) =\n//│     x$15 -- #58\n//│   let* (x$0) = b(16) in -- #4\n//│   x$0 -- #3\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$2), Set(j$1), Set(j$0), Set(b, a))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def a(x$1) =\n//│     let idCtx = _IdContext() in -- #136\n//│     let* (res) = a_modcons$14(idCtx,x$1) in -- #135\n//│     res -- #134\n//│   def j$0(x$2) =\n//│     x$2 -- #6\n//│   def j$1(x$6) =\n//│     jump j$0(x$6) -- #19\n//│   def b(n$0) =\n//│     let idCtx = _IdContext() in -- #114\n//│     let* (res) = b_modcons$13(idCtx,n$0) in -- #113\n//│     res -- #112\n//│   def j$2(x$15) =\n//│     x$15 -- #58\n//│   def _b_a_ctx_app$11(ctx,x) =\n//│     case ctx of -- #95\n//│       _IdContext =>\n//│         x -- #94\n//│       _Context =>\n//│         let field = _Context.field(ctx) in -- #93\n//│         let ptr = _Context.ptr(ctx) in -- #92\n//│         let _ = assign ptr.t := x in -- #91\n//│         let acc = _Context.acc(ctx) in -- #90\n//│         acc -- #89\n//│   def _b_a_ctx_comp$12(ctx1,ctx2) =\n//│     let ctx2acc = _Context.acc(ctx2) in -- #101\n//│     let ctx2ptr = _Context.ptr(ctx2) in -- #100\n//│     let ctx2field = _Context.field(ctx2) in -- #99\n//│     let* (newAcc) = _b_a_ctx_app$11(ctx1,ctx2acc) in -- #98\n//│     let ret = _Context(newAcc,ctx2ptr,ctx2field) in -- #97\n//│     ret -- #96\n//│   def b_modcons$13(ctx,n$0) =\n//│     let* (r0) = _b_modcons$13_a_modcons$14_opt$15(13,ctx,n$0,true,true) in -- #177\n//│     r0 -- #176\n//│   def a_modcons$14(ctx,x$1) =\n//│     let* (r0) = _b_modcons$13_a_modcons$14_opt$15(14,true,true,ctx,x$1) in -- #179\n//│     r0 -- #178\n//│   def _b_modcons$13_a_modcons$14_opt$15(tailrecBranch$,b_modcons$13_ctx,b_modcons$13_n$0,a_modcons$14_ctx,a_modcons$14_x$1) =\n//│     jump _b_modcons$13_a_modcons$14_opt_jp$16(tailrecBranch$,b_modcons$13_ctx,b_modcons$13_n$0,a_modcons$14_ctx,a_modcons$14_x$1) -- #175\n//│   def _b_modcons$13_a_modcons$14_opt_jp$16(tailrecBranch$,b_modcons$13_ctx,b_modcons$13_n$0,a_modcons$14_ctx,a_modcons$14_x$1) =\n//│     let scrut = ==(14,tailrecBranch$) in -- #174\n//│     if scrut -- #173\n//│       true =>\n//│         case a_modcons$14_x$1 of -- #172\n//│           Cons =>\n//│             let x$3 = Cons.t(a_modcons$14_x$1) in -- #168\n//│             let x$4 = Cons.h(a_modcons$14_x$1) in -- #167\n//│             let x$5 = <(x$4,0) in -- #166\n//│             if x$5 -- #165\n//│               true =>\n//│                 let x$7 = Nil() in -- #158\n//│                 let x$8 = Cons(-1,x$7) in -- #157\n//│                 let* (res) = _b_a_ctx_app$11(a_modcons$14_ctx,x$8) in -- #156\n//│                 res -- #155\n//│               false =>\n//│                 let x$9 = *(x$4,4) in -- #164\n//│                 let x$10 = -(x$4,2) in -- #163\n//│                 let x$12 = Cons(x$9,0) in -- #162\n//│                 let ctx2 = _Context(x$12,x$12,0) in -- #161\n//│                 let* (composed) = _b_a_ctx_comp$12(a_modcons$14_ctx,ctx2) in -- #160\n//│                 jump _b_modcons$13_a_modcons$14_opt_jp$16(13,composed,x$10,a_modcons$14_ctx,a_modcons$14_x$1) -- #159\n//│           Nil =>\n//│             let x$13 = Nil() in -- #171\n//│             let* (res) = _b_a_ctx_app$11(a_modcons$14_ctx,x$13) in -- #170\n//│             res -- #169\n//│       false =>\n//│         let x$14 = <=(b_modcons$13_n$0,0) in -- #154\n//│         if x$14 -- #153\n//│           true =>\n//│             let x$16 = Nil() in -- #149\n//│             let x$17 = Cons(0,x$16) in -- #148\n//│             let* (res) = _b_a_ctx_app$11(b_modcons$13_ctx,x$17) in -- #147\n//│             res -- #146\n//│           false =>\n//│             let x$18 = Nil() in -- #152\n//│             let x$19 = Cons(b_modcons$13_n$0,x$18) in -- #151\n//│             jump _b_modcons$13_a_modcons$14_opt_jp$16(14,b_modcons$13_ctx,b_modcons$13_n$0,b_modcons$13_ctx,x$19) -- #150\n//│   let* (x$0) = b(16) in -- #4\n//│   x$0 -- #3\n//│ \n//│ Interpreted:\n//│ Cons(64,0)\n\n:noTailRec\n:interpIR\nfun foo(xs) =\n  if xs is \n    Cons(h, t) then\n      if h > 5 then foo(t)\n      else \n        val item = if h < 3 then -1 else 100 \n        Cons(item, Cons(h, foo(t)))\n    Nil then \n      Nil\nfoo(Cons(1, Cons(6, Cons(7, Cons(4, Cons(2, Cons(3, Cons(9, Nil))))))))\n//│ |#fun| |foo|(|xs|)| |#=|→|#if| |xs| |is| |→|Cons|(|h|,| |t|)| |#then|→|#if| |h| |>| |5| |#then| |foo|(|t|)|↵|#else| |→|#val| |item| |#=| |#if| |h| |<| |3| |#then| |-|1| |#else| |100| |↵|Cons|(|item|,| |Cons|(|h|,| |foo|(|t|)|)|)|←|←|↵|Nil| |#then| |→|Nil|←|←|←|↵|foo|(|Cons|(|1|,| |Cons|(|6|,| |Cons|(|7|,| |Cons|(|4|,| |Cons|(|2|,| |Cons|(|3|,| |Cons|(|9|,| |Nil|)|)|)|)|)|)|)|)|\n//│ Parsed: {fun foo = (xs,) => {if xs is ‹(Cons(h, t,)) then {if (>(h,)(5,)) then foo(t,) else {let item = if (<(h,)(3,)) then -1 else 100; Cons(item, Cons(h, foo(t,),),)}}; (Nil) then {Nil}›}; foo(Cons(1, Cons(6, Cons(7, Cons(4, Cons(2, Cons(3, Cons(9, Nil,),),),),),),),)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo(xs$0) =\n//│     case xs$0 of -- #104\n//│       Cons =>\n//│         let x$10 = Cons.t(xs$0) in -- #100\n//│         let x$11 = Cons.h(xs$0) in -- #99\n//│         let x$12 = >(x$11,5) in -- #98\n//│         if x$12 -- #97\n//│           true =>\n//│             let* (x$14) = foo(x$10) in -- #68\n//│             jump j$1(x$14) -- #67\n//│           false =>\n//│             let x$15 = <(x$11,3) in -- #96\n//│             if x$15 -- #95\n//│               true =>\n//│                 jump j$2(-1,x$10,x$11) -- #92\n//│               false =>\n//│                 jump j$2(100,x$10,x$11) -- #94\n//│       Nil =>\n//│         let x$20 = Nil() in -- #103\n//│         jump j$0(x$20) -- #102\n//│   def j$0(x$9) =\n//│     x$9 -- #49\n//│   def j$1(x$13) =\n//│     jump j$0(x$13) -- #62\n//│   def j$2(x$16,x$10,x$11) =\n//│     let* (x$17) = foo(x$10) in -- #90\n//│     let x$18 = Cons(x$11,x$17) in -- #89\n//│     let x$19 = Cons(x$16,x$18) in -- #88\n//│     jump j$1(x$19) -- #87\n//│   let x$0 = Nil() in -- #47\n//│   let x$1 = Cons(9,x$0) in -- #46\n//│   let x$2 = Cons(3,x$1) in -- #45\n//│   let x$3 = Cons(2,x$2) in -- #44\n//│   let x$4 = Cons(4,x$3) in -- #43\n//│   let x$5 = Cons(7,x$4) in -- #42\n//│   let x$6 = Cons(6,x$5) in -- #41\n//│   let x$7 = Cons(1,x$6) in -- #40\n//│   let* (x$8) = foo(x$7) in -- #39\n//│   x$8 -- #38\n//│ \n//│ Interpreted:\n//│ Cons(-1,Cons(1,Cons(100,Cons(4,Cons(-1,Cons(2,Cons(100,Cons(3,Nil()))))))))\n\n:interpIR\n@tailrec fun foo(xs) =\n  if xs is \n    Cons(h, t) then\n      if h > 5 then @tailcall foo(t)\n      else \n        val item = if h < 3 then -1 else 100 \n        Cons(item, Cons(h, @tailcall foo(t)))\n    Nil then \n      Nil\nfoo(Cons(1, Cons(6, Cons(7, Cons(4, Cons(2, Cons(3, Cons(9, Nil))))))))\n//│ |@|tailrec| |#fun| |foo|(|xs|)| |#=|→|#if| |xs| |is| |→|Cons|(|h|,| |t|)| |#then|→|#if| |h| |>| |5| |#then| |@|tailcall| |foo|(|t|)|↵|#else| |→|#val| |item| |#=| |#if| |h| |<| |3| |#then| |-|1| |#else| |100| |↵|Cons|(|item|,| |Cons|(|h|,| |@|tailcall| |foo|(|t|)|)|)|←|←|↵|Nil| |#then| |→|Nil|←|←|←|↵|foo|(|Cons|(|1|,| |Cons|(|6|,| |Cons|(|7|,| |Cons|(|4|,| |Cons|(|2|,| |Cons|(|3|,| |Cons|(|9|,| |Nil|)|)|)|)|)|)|)|)|\n//│ Parsed: {fun foo = (xs,) => {if xs is ‹(Cons(h, t,)) then {if (>(h,)(5,)) then @tailcall foo(t,) else {let item = if (<(h,)(3,)) then -1 else 100; Cons(item, Cons(h, @tailcall foo(t,),),)}}; (Nil) then {Nil}›}; foo(Cons(1, Cons(6, Cons(7, Cons(4, Cons(2, Cons(3, Cons(9, Nil,),),),),),),),)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo(xs$0) =\n//│     case xs$0 of -- #104\n//│       Cons =>\n//│         let x$10 = Cons.t(xs$0) in -- #100\n//│         let x$11 = Cons.h(xs$0) in -- #99\n//│         let x$12 = >(x$11,5) in -- #98\n//│         if x$12 -- #97\n//│           true =>\n//│             let* (x$14) = @tailcall foo(x$10) in -- #68\n//│             jump j$1(x$14) -- #67\n//│           false =>\n//│             let x$15 = <(x$11,3) in -- #96\n//│             if x$15 -- #95\n//│               true =>\n//│                 jump j$2(-1,x$10,x$11) -- #92\n//│               false =>\n//│                 jump j$2(100,x$10,x$11) -- #94\n//│       Nil =>\n//│         let x$20 = Nil() in -- #103\n//│         jump j$0(x$20) -- #102\n//│   def j$0(x$9) =\n//│     x$9 -- #49\n//│   def j$1(x$13) =\n//│     jump j$0(x$13) -- #62\n//│   def j$2(x$16,x$10,x$11) =\n//│     let* (x$17) = @tailcall foo(x$10) in -- #90\n//│     let x$18 = Cons(x$11,x$17) in -- #89\n//│     let x$19 = Cons(x$16,x$18) in -- #88\n//│     jump j$1(x$19) -- #87\n//│   let x$0 = Nil() in -- #47\n//│   let x$1 = Cons(9,x$0) in -- #46\n//│   let x$2 = Cons(3,x$1) in -- #45\n//│   let x$3 = Cons(2,x$2) in -- #44\n//│   let x$4 = Cons(4,x$3) in -- #43\n//│   let x$5 = Cons(7,x$4) in -- #42\n//│   let x$6 = Cons(6,x$5) in -- #41\n//│   let x$7 = Cons(1,x$6) in -- #40\n//│   let* (x$8) = foo(x$7) in -- #39\n//│   x$8 -- #38\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$1), Set(j$0), Set(foo))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def foo(xs$0) =\n//│     let idCtx = _IdContext() in -- #144\n//│     let* (res) = foo_modcons$13(idCtx,xs$0) in -- #143\n//│     res -- #142\n//│   def j$0(x$9) =\n//│     x$9 -- #49\n//│   def j$1(x$13) =\n//│     jump j$0(x$13) -- #62\n//│   def _foo_ctx_app$10(ctx,x) =\n//│     case ctx of -- #117\n//│       _IdContext =>\n//│         x -- #116\n//│       _Context =>\n//│         let field = _Context.field(ctx) in -- #115\n//│         let ptr = _Context.ptr(ctx) in -- #114\n//│         let _ = assign ptr.t := x in -- #113\n//│         let acc = _Context.acc(ctx) in -- #112\n//│         acc -- #111\n//│   def _foo_ctx_comp$11(ctx1,ctx2) =\n//│     let ctx2acc = _Context.acc(ctx2) in -- #123\n//│     let ctx2ptr = _Context.ptr(ctx2) in -- #122\n//│     let ctx2field = _Context.field(ctx2) in -- #121\n//│     let* (newAcc) = _foo_ctx_app$10(ctx1,ctx2acc) in -- #120\n//│     let ret = _Context(newAcc,ctx2ptr,ctx2field) in -- #119\n//│     ret -- #118\n//│   def foo_modcons$13(ctx,xs$0) =\n//│     let* (r0) = _foo_modcons$13_j$2_modcons$12_opt$14(13,ctx,xs$0,true,true,true,true) in -- #180\n//│     r0 -- #179\n//│   def _foo_modcons$13_j$2_modcons$12_opt$14(tailrecBranch$,foo_modcons$13_ctx,foo_modcons$13_xs$0,j$2_modcons$12_ctx,j$2_modcons$12_x$16,j$2_modcons$12_x$10,j$2_modcons$12_x$11) =\n//│     jump _foo_modcons$13_j$2_modcons$12_opt_jp$15(tailrecBranch$,foo_modcons$13_ctx,foo_modcons$13_xs$0,j$2_modcons$12_ctx,j$2_modcons$12_x$16,j$2_modcons$12_x$10,j$2_modcons$12_x$11) -- #178\n//│   def _foo_modcons$13_j$2_modcons$12_opt_jp$15(tailrecBranch$,foo_modcons$13_ctx,foo_modcons$13_xs$0,j$2_modcons$12_ctx,j$2_modcons$12_x$16,j$2_modcons$12_x$10,j$2_modcons$12_x$11) =\n//│     let scrut = ==(12,tailrecBranch$) in -- #177\n//│     if scrut -- #176\n//│       true =>\n//│         let x$18 = Cons(j$2_modcons$12_x$11,0) in -- #175\n//│         let x$19 = Cons(j$2_modcons$12_x$16,x$18) in -- #174\n//│         let ctx2 = _Context(x$19,x$18,0) in -- #173\n//│         let* (composed) = _foo_ctx_comp$11(j$2_modcons$12_ctx,ctx2) in -- #172\n//│         jump _foo_modcons$13_j$2_modcons$12_opt_jp$15(13,composed,j$2_modcons$12_x$10,j$2_modcons$12_ctx,j$2_modcons$12_x$16,j$2_modcons$12_x$10,j$2_modcons$12_x$11) -- #171\n//│       false =>\n//│         case foo_modcons$13_xs$0 of -- #170\n//│           Cons =>\n//│             let x$10 = Cons.t(foo_modcons$13_xs$0) in -- #166\n//│             let x$11 = Cons.h(foo_modcons$13_xs$0) in -- #165\n//│             let x$12 = >(x$11,5) in -- #164\n//│             if x$12 -- #163\n//│               true =>\n//│                 jump _foo_modcons$13_j$2_modcons$12_opt_jp$15(13,foo_modcons$13_ctx,x$10,j$2_modcons$12_ctx,j$2_modcons$12_x$16,j$2_modcons$12_x$10,j$2_modcons$12_x$11) -- #158\n//│               false =>\n//│                 let x$15 = <(x$11,3) in -- #162\n//│                 if x$15 -- #161\n//│                   true =>\n//│                     jump _foo_modcons$13_j$2_modcons$12_opt_jp$15(12,foo_modcons$13_ctx,foo_modcons$13_xs$0,foo_modcons$13_ctx,-1,x$10,x$11) -- #159\n//│                   false =>\n//│                     jump _foo_modcons$13_j$2_modcons$12_opt_jp$15(12,foo_modcons$13_ctx,foo_modcons$13_xs$0,foo_modcons$13_ctx,100,x$10,x$11) -- #160\n//│           Nil =>\n//│             let x$20 = Nil() in -- #169\n//│             let* (res) = _foo_ctx_app$10(foo_modcons$13_ctx,x$20) in -- #168\n//│             res -- #167\n//│   let x$0 = Nil() in -- #47\n//│   let x$1 = Cons(9,x$0) in -- #46\n//│   let x$2 = Cons(3,x$1) in -- #45\n//│   let x$3 = Cons(2,x$2) in -- #44\n//│   let x$4 = Cons(4,x$3) in -- #43\n//│   let x$5 = Cons(7,x$4) in -- #42\n//│   let x$6 = Cons(6,x$5) in -- #41\n//│   let x$7 = Cons(1,x$6) in -- #40\n//│   let* (x$8) = foo(x$7) in -- #39\n//│   x$8 -- #38\n//│ \n//│ Interpreted:\n//│ Cons(-1,Cons(1,0))\n\n:ce\nfun b() =\n  a()\n  a()\n@tailrec \nfun a() = \n  if 0 < 1 then a()\n  else b()\na()\n//│ |#fun| |b|(||)| |#=|→|a|(||)|↵|a|(||)|←|↵|@|tailrec| |↵|#fun| |a|(||)| |#=| |→|#if| |0| |<| |1| |#then| |a|(||)|↵|#else| |b|(||)|←|↵|a|(||)|\n//│ Parsed: {fun b = () => {a(); a()}; fun a = () => {if (<(0,)(1,)) then a() else b()}; a()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def b() =\n//│     let* (x$1) = a() in -- #8\n//│     let* (x$2) = a() in -- #7\n//│     x$2 -- #6\n//│   def a() =\n//│     let x$3 = <(0,1) in -- #22\n//│     if x$3 -- #21\n//│       true =>\n//│         let* (x$5) = a() in -- #16\n//│         jump j$0(x$5) -- #15\n//│       false =>\n//│         let* (x$6) = b() in -- #20\n//│         jump j$0(x$6) -- #19\n//│   def j$0(x$4) =\n//│     x$4 -- #12\n//│   let* (x$0) = a() in -- #2\n//│   x$0 -- #1\n//│ ╔══[COMPILATION ERROR] function `a` is not tail-recursive, but is marked as @tailrec\n//│ ║  l.1203: \t@tailrec \n//│ ║          \t ^^^^^^^\n//│ ╟── it could self-recurse through this call, which may not be a tail-call\n//│ ║  l.1201: \t  a()\n//│ ╙──        \t  ^\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(j$0), Set(a, b))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def b() =\n//│     let* (r0) = _a_b_opt$9(0) in -- #45\n//│     r0 -- #44\n//│   def a() =\n//│     let* (r0) = _a_b_opt$9(1) in -- #43\n//│     r0 -- #42\n//│   def j$0(x$4) =\n//│     x$4 -- #12\n//│   def _a_b_opt$9(tailrecBranch$) =\n//│     jump _a_b_opt_jp$10(tailrecBranch$) -- #41\n//│   def _a_b_opt_jp$10(tailrecBranch$) =\n//│     let scrut = ==(0,tailrecBranch$) in -- #40\n//│     if scrut -- #39\n//│       true =>\n//│         let* (x$1) = a() in -- #38\n//│         jump _a_b_opt_jp$10(1) -- #37\n//│       false =>\n//│         let x$3 = <(0,1) in -- #36\n//│         if x$3 -- #35\n//│           true =>\n//│             jump _a_b_opt_jp$10(1) -- #33\n//│           false =>\n//│             jump _a_b_opt_jp$10(0) -- #34\n//│   let* (x$0) = a() in -- #2\n//│   x$0 -- #1\n\n:ce\nclass A(a, b)\n@tailrec\nfun a() = A(b(), 1)\nfun b() = A(c(), @tailcall a())\nfun c() = A(b(), 1)\na()\n//│ |#class| |A|(|a|,| |b|)|↵|@|tailrec|↵|#fun| |a|(||)| |#=| |A|(|b|(||)|,| |1|)|↵|#fun| |b|(||)| |#=| |A|(|c|(||)|,| |@|tailcall| |a|(||)|)|↵|#fun| |c|(||)| |#=| |A|(|b|(||)|,| |1|)|↵|a|(||)|\n//│ Parsed: {class A(a, b,) {}; fun a = () => A(b(), 1,); fun b = () => A(c(), @tailcall a(),); fun c = () => A(b(), 1,); a()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class A(a,b)\n//│   def a() =\n//│     let* (x$1) = b() in -- #11\n//│     let x$2 = A(x$1,1) in -- #10\n//│     x$2 -- #9\n//│   def b() =\n//│     let* (x$3) = c() in -- #22\n//│     let* (x$4) = @tailcall a() in -- #21\n//│     let x$5 = A(x$3,x$4) in -- #20\n//│     x$5 -- #19\n//│   def c() =\n//│     let* (x$6) = b() in -- #31\n//│     let x$7 = A(x$6,1) in -- #30\n//│     x$7 -- #29\n//│   let* (x$0) = a() in -- #2\n//│   x$0 -- #1\n//│ ╔══[COMPILATION ERROR] function `a` is not tail-recursive, but is marked as @tailrec\n//│ ║  l.1273: \t@tailrec\n//│ ║          \t ^^^^^^^\n//│ ╟── it could self-recurse through this call, which may not be a tail-call\n//│ ║  l.1275: \tfun b() = A(c(), @tailcall a())\n//│ ╙──        \t            ^\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(c, b, a))\n//│ Program:\n//│   class A(a,b)\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def a() =\n//│     let idCtx = _IdContext() in -- #81\n//│     let* (res) = a_modcons$13(idCtx) in -- #80\n//│     res -- #79\n//│   def b() =\n//│     let idCtx = _IdContext() in -- #73\n//│     let* (res) = b_modcons$12(idCtx) in -- #72\n//│     res -- #71\n//│   def c() =\n//│     let idCtx = _IdContext() in -- #64\n//│     let* (res) = c_modcons$11(idCtx) in -- #63\n//│     res -- #62\n//│   def _c_b_a_ctx_app$9(ctx,x) =\n//│     case ctx of -- #50\n//│       _IdContext =>\n//│         x -- #49\n//│       _Context =>\n//│         let field = _Context.field(ctx) in -- #48\n//│         let scrut = ==(1,field) in -- #47\n//│         if scrut -- #46\n//│           true =>\n//│             let ptr = _Context.ptr(ctx) in -- #45\n//│             let _ = assign ptr.b := x in -- #44\n//│             let acc = _Context.acc(ctx) in -- #43\n//│             acc -- #42\n//│           false =>\n//│             let ptr = _Context.ptr(ctx) in -- #41\n//│             let _ = assign ptr.a := x in -- #40\n//│             let acc = _Context.acc(ctx) in -- #39\n//│             acc -- #38\n//│   def _c_b_a_ctx_comp$10(ctx1,ctx2) =\n//│     let ctx2acc = _Context.acc(ctx2) in -- #56\n//│     let ctx2ptr = _Context.ptr(ctx2) in -- #55\n//│     let ctx2field = _Context.field(ctx2) in -- #54\n//│     let* (newAcc) = _c_b_a_ctx_app$9(ctx1,ctx2acc) in -- #53\n//│     let ret = _Context(newAcc,ctx2ptr,ctx2field) in -- #52\n//│     ret -- #51\n//│   def c_modcons$11(ctx) =\n//│     let* (r0) = _c_modcons$11_b_modcons$12_a_modcons$13_opt$14(11,ctx,true,true) in -- #105\n//│     r0 -- #104\n//│   def b_modcons$12(ctx) =\n//│     let* (r0) = _c_modcons$11_b_modcons$12_a_modcons$13_opt$14(12,true,ctx,true) in -- #107\n//│     r0 -- #106\n//│   def a_modcons$13(ctx) =\n//│     let* (r0) = _c_modcons$11_b_modcons$12_a_modcons$13_opt$14(13,true,true,ctx) in -- #109\n//│     r0 -- #108\n//│   def _c_modcons$11_b_modcons$12_a_modcons$13_opt$14(tailrecBranch$,c_modcons$11_ctx,b_modcons$12_ctx,a_modcons$13_ctx) =\n//│     jump _c_modcons$11_b_modcons$12_a_modcons$13_opt_jp$15(tailrecBranch$,c_modcons$11_ctx,b_modcons$12_ctx,a_modcons$13_ctx) -- #103\n//│   def _c_modcons$11_b_modcons$12_a_modcons$13_opt_jp$15(tailrecBranch$,c_modcons$11_ctx,b_modcons$12_ctx,a_modcons$13_ctx) =\n//│     let scrut = ==(13,tailrecBranch$) in -- #102\n//│     if scrut -- #101\n//│       true =>\n//│         let x$2 = A(0,1) in -- #98\n//│         let ctx2 = _Context(x$2,x$2,0) in -- #97\n//│         let* (composed) = _c_b_a_ctx_comp$10(a_modcons$13_ctx,ctx2) in -- #96\n//│         jump _c_modcons$11_b_modcons$12_a_modcons$13_opt_jp$15(12,c_modcons$11_ctx,composed,a_modcons$13_ctx) -- #95\n//│       false =>\n//│         let scrut = ==(12,tailrecBranch$) in -- #100\n//│         if scrut -- #99\n//│           true =>\n//│             let* (x$3) = c() in -- #94\n//│             let x$5 = A(x$3,0) in -- #93\n//│             let ctx2 = _Context(x$5,x$5,1) in -- #92\n//│             let* (composed) = _c_b_a_ctx_comp$10(b_modcons$12_ctx,ctx2) in -- #91\n//│             jump _c_modcons$11_b_modcons$12_a_modcons$13_opt_jp$15(13,c_modcons$11_ctx,b_modcons$12_ctx,composed) -- #90\n//│           false =>\n//│             let x$7 = A(0,1) in -- #89\n//│             let ctx2 = _Context(x$7,x$7,0) in -- #88\n//│             let* (composed) = _c_b_a_ctx_comp$10(c_modcons$11_ctx,ctx2) in -- #87\n//│             jump _c_modcons$11_b_modcons$12_a_modcons$13_opt_jp$15(12,c_modcons$11_ctx,composed,a_modcons$13_ctx) -- #86\n//│   let* (x$0) = a() in -- #2\n//│   x$0 -- #1\n\n// TODO: Purity check\nclass A(a, b)\n@tailrec\nfun a() = A(b(), 1)\nfun b() = A(@tailcall a(), c())\nfun c() = A(0, 1)\na()\n//│ |#class| |A|(|a|,| |b|)|↵|@|tailrec|↵|#fun| |a|(||)| |#=| |A|(|b|(||)|,| |1|)|↵|#fun| |b|(||)| |#=| |A|(|@|tailcall| |a|(||)|,| |c|(||)|)|↵|#fun| |c|(||)| |#=| |A|(|0|,| |1|)|↵|a|(||)|\n//│ Parsed: {class A(a, b,) {}; fun a = () => A(b(), 1,); fun b = () => A(@tailcall a(), c(),); fun c = () => A(0, 1,); a()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class A(a,b)\n//│   def a() =\n//│     let* (x$1) = b() in -- #11\n//│     let x$2 = A(x$1,1) in -- #10\n//│     x$2 -- #9\n//│   def b() =\n//│     let* (x$3) = @tailcall a() in -- #22\n//│     let* (x$4) = c() in -- #21\n//│     let x$5 = A(x$3,x$4) in -- #20\n//│     x$5 -- #19\n//│   def c() =\n//│     let x$6 = A(0,1) in -- #29\n//│     x$6 -- #28\n//│   let* (x$0) = a() in -- #2\n//│   x$0 -- #1\n//│ ╔══[COMPILATION ERROR] not a tail call, as the remaining functions may be impure\n//│ ║  l.1391: \tfun b() = A(@tailcall a(), c())\n//│ ╙──        \t                      ^\n//│ ╔══[COMPILATION ERROR] function `a` is not tail-recursive, but is marked as @tailrec\n//│ ║  l.1389: \t@tailrec\n//│ ║          \t ^^^^^^^\n//│ ╟── it could self-recurse through this call, which may not be a tail-call\n//│ ║  l.1391: \tfun b() = A(@tailcall a(), c())\n//│ ╙──        \t                      ^\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(b, a), Set(c))\n//│ Program:\n//│   class A(a,b)\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def a() =\n//│     let idCtx = _IdContext() in -- #64\n//│     let* (res) = a_modcons$12(idCtx) in -- #63\n//│     res -- #62\n//│   def b() =\n//│     let idCtx = _IdContext() in -- #56\n//│     let* (res) = b_modcons$11(idCtx) in -- #55\n//│     res -- #54\n//│   def c() =\n//│     let x$6 = A(0,1) in -- #29\n//│     x$6 -- #28\n//│   def _b_a_ctx_app$9(ctx,x) =\n//│     case ctx of -- #42\n//│       _IdContext =>\n//│         x -- #41\n//│       _Context =>\n//│         let field = _Context.field(ctx) in -- #40\n//│         let ptr = _Context.ptr(ctx) in -- #39\n//│         let _ = assign ptr.a := x in -- #38\n//│         let acc = _Context.acc(ctx) in -- #37\n//│         acc -- #36\n//│   def _b_a_ctx_comp$10(ctx1,ctx2) =\n//│     let ctx2acc = _Context.acc(ctx2) in -- #48\n//│     let ctx2ptr = _Context.ptr(ctx2) in -- #47\n//│     let ctx2field = _Context.field(ctx2) in -- #46\n//│     let* (newAcc) = _b_a_ctx_app$9(ctx1,ctx2acc) in -- #45\n//│     let ret = _Context(newAcc,ctx2ptr,ctx2field) in -- #44\n//│     ret -- #43\n//│   def b_modcons$11(ctx) =\n//│     let* (r0) = _b_modcons$11_a_modcons$12_opt$13(11,ctx,true) in -- #83\n//│     r0 -- #82\n//│   def a_modcons$12(ctx) =\n//│     let* (r0) = _b_modcons$11_a_modcons$12_opt$13(12,true,ctx) in -- #85\n//│     r0 -- #84\n//│   def _b_modcons$11_a_modcons$12_opt$13(tailrecBranch$,b_modcons$11_ctx,a_modcons$12_ctx) =\n//│     jump _b_modcons$11_a_modcons$12_opt_jp$14(tailrecBranch$,b_modcons$11_ctx,a_modcons$12_ctx) -- #81\n//│   def _b_modcons$11_a_modcons$12_opt_jp$14(tailrecBranch$,b_modcons$11_ctx,a_modcons$12_ctx) =\n//│     let scrut = ==(12,tailrecBranch$) in -- #80\n//│     if scrut -- #79\n//│       true =>\n//│         let x$2 = A(0,1) in -- #78\n//│         let ctx2 = _Context(x$2,x$2,0) in -- #77\n//│         let* (composed) = _b_a_ctx_comp$10(a_modcons$12_ctx,ctx2) in -- #76\n//│         jump _b_modcons$11_a_modcons$12_opt_jp$14(11,composed,a_modcons$12_ctx) -- #75\n//│       false =>\n//│         let* (x$3) = @tailcall a() in -- #74\n//│         let* (x$4) = c() in -- #73\n//│         let x$5 = A(x$3,x$4) in -- #72\n//│         let* (res) = _b_a_ctx_app$9(b_modcons$11_ctx,x$5) in -- #71\n//│         res -- #70\n//│   let* (x$0) = a() in -- #2\n//│   x$0 -- #1\n\n:ce\n@tailcall 1\n//│ |@|tailcall| |1|\n//│ Parsed: {@tailcall 1}\n//│ ╔══[COMPILATION ERROR] @tailcall may only be used to annotate function calls\n//│ ║  l.1486: \t@tailcall 1\n//│ ╙──        \t ^^^^^^^^\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│ \n//│   1 -- #0\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List()\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│ \n//│   1 -- #0\n\n:ce\n@tailrec 1\n//│ |@|tailrec| |1|\n//│ Parsed: {@tailrec 1}\n//│ ╔══[COMPILATION ERROR] @tailrec may only be used to annotate functions\n//│ ║  l.1510: \t@tailrec 1\n//│ ╙──        \t ^^^^^^^\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│ \n//│   1 -- #0\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List()\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│ \n//│   1 -- #0\n\n:ce\nfun foo() =\n  @tailrec foo()\nfoo()\n//│ |#fun| |foo|(||)| |#=|→|@|tailrec| |foo|(||)|←|↵|foo|(||)|\n//│ Parsed: {fun foo = () => {@tailrec foo()}; foo()}\n//│ ╔══[COMPILATION ERROR] @tailrec is for annotating functions; try @tailcall instead\n//│ ║  l.1535: \t  @tailrec foo()\n//│ ╙──        \t   ^^^^^^^\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo() =\n//│     let* (x$1) = foo() in -- #5\n//│     x$1 -- #4\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(foo))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def foo_jp() =\n//│     jump foo_jp() -- #12\n//│   def foo() =\n//│     let* (r0) = foo_jp() in -- #14\n//│     r0 -- #13\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n\n:ce\n@tailcall\nfun foo() =\n  foo()\nfoo()\n//│ |@|tailcall|↵|#fun| |foo|(||)| |#=|→|foo|(||)|←|↵|foo|(||)|\n//│ Parsed: {fun foo = () => {foo()}; foo()}\n//│ ╔══[COMPILATION ERROR] @tailcall is for annotating function calls; try @tailrec instead\n//│ ║  l.1568: \t@tailcall\n//│ ╙──        \t ^^^^^^^^\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def foo() =\n//│     let* (x$1) = foo() in -- #5\n//│     x$1 -- #4\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n//│ \n//│ \n//│ Strongly Connected Tail Calls:\n//│ List(Set(foo))\n//│ Program:\n//│   class _IdContext()\n//│   class _Context(acc,ptr,field)\n//│   def foo_jp() =\n//│     jump foo_jp() -- #12\n//│   def foo() =\n//│     let* (r0) = foo_jp() in -- #14\n//│     r0 -- #13\n//│   let* (x$0) = foo() in -- #2\n//│   x$0 -- #1\n"
  },
  {
    "path": "compiler/shared/test/diff-ir/LiftClass.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:genCpp\n:runCpp\n:interpIR\nfun main(x) =\n  class InnerClass(y) extends Callable {\n    fun apply1(z) = x + y + z\n  }\n  let ic = InnerClass(1)\n  ic(2) + ic(3)\nmain(4)\n//│ |#fun| |main|(|x|)| |#=|→|#class| |InnerClass|(|y|)| |#extends| |Callable| |{|→|#fun| |apply1|(|z|)| |#=| |x| |+| |y| |+| |z|←|↵|}|↵|#let| |ic| |#=| |InnerClass|(|1|)|↵|ic|(|2|)| |+| |ic|(|3|)|←|↵|main|(|4|)|\n//│ Parsed: {fun main = (x,) => {class InnerClass(y,): Callable {fun apply1 = (z,) => +(+(x, y,), z,)}; let ic = InnerClass(1,); +(ic(2,), ic(3,),)}; main(4,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class InnerClass(y,x) extends Callable {\n//│     def apply1(z$0) =\n//│       let x$6 = +(x,y) in -- #45\n//│       let x$7 = +(x$6,z$0) in -- #44\n//│       x$7 -- #43\n//│   }\n//│   def main(x$1) =\n//│     let x$2 = InnerClass(1,x$1) in -- #26\n//│     let x$3 = Callable.apply1(x$2,2) in -- #25\n//│     let x$4 = Callable.apply1(x$2,3) in -- #24\n//│     let x$5 = +(x$3,x$4) in -- #23\n//│     x$5 -- #22\n//│   let* (x$0) = main(4) in -- #4\n//│   x$0 -- #3\n//│ \n//│ Interpreted:\n//│ 15\n//│ \n//│ \n//│ Execution succeeded: \n//│ 15\n//│ \n\n:genCpp\n:runCpp\n:interpIR\nfun main(x) =\n  class InnerClass(y) extends Callable {\n    fun apply1(z) =\n      module InnerClass2 extends Callable {\n        fun apply1(w) = w + z\n      }\n      InnerClass2\n  }\n  let ic = InnerClass(1)\n  ic(2)(2) + ic(3)(1)\nmain(4)\n//│ |#fun| |main|(|x|)| |#=|→|#class| |InnerClass|(|y|)| |#extends| |Callable| |{|→|#fun| |apply1|(|z|)| |#=|→|#module| |InnerClass2| |#extends| |Callable| |{|→|#fun| |apply1|(|w|)| |#=| |w| |+| |z|←|↵|}|↵|InnerClass2|←|←|↵|}|↵|#let| |ic| |#=| |InnerClass|(|1|)|↵|ic|(|2|)|(|2|)| |+| |ic|(|3|)|(|1|)|←|↵|main|(|4|)|\n//│ Parsed: {fun main = (x,) => {class InnerClass(y,): Callable {fun apply1 = (z,) => {module InnerClass2: Callable {fun apply1 = (w,) => +(w, z,)}; InnerClass2}}; let ic = InnerClass(1,); +(ic(2,)(2,), ic(3,)(1,),)}; main(4,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class InnerClass(y) extends Callable {\n//│     def apply1(z$0) =\n//│       let x$8 = InnerClass2(z$0) in -- #44\n//│       x$8 -- #43\n//│   }\n//│   class InnerClass2(z) extends Callable {\n//│     def apply1(w$0) =\n//│       let x$9 = +(w$0,z) in -- #51\n//│       x$9 -- #50\n//│   }\n//│   def main(x$1) =\n//│     let x$2 = InnerClass(1) in -- #36\n//│     let x$3 = Callable.apply1(x$2,2) in -- #35\n//│     let x$4 = Callable.apply1(x$3,2) in -- #34\n//│     let x$5 = Callable.apply1(x$2,3) in -- #33\n//│     let x$6 = Callable.apply1(x$5,1) in -- #32\n//│     let x$7 = +(x$4,x$6) in -- #31\n//│     x$7 -- #30\n//│   let* (x$0) = main(4) in -- #4\n//│   x$0 -- #3\n//│ \n//│ Interpreted:\n//│ 8\n//│ \n//│ \n//│ Execution succeeded: \n//│ 8\n//│ \n\n:genCpp\n:runCpp\n:interpIR\nfun main(x) =\n  class InnerClass(y) extends Callable {\n    fun f(x) = y\n  }\n  let ic = InnerClass(1)\n  InnerClass.f(ic, Nil)\nmain(2)\n//│ |#fun| |main|(|x|)| |#=|→|#class| |InnerClass|(|y|)| |#extends| |Callable| |{|→|#fun| |f|(|x|)| |#=| |y|←|↵|}|↵|#let| |ic| |#=| |InnerClass|(|1|)|↵|InnerClass|.f|(|ic|,| |Nil|)|←|↵|main|(|2|)|\n//│ Parsed: {fun main = (x,) => {class InnerClass(y,): Callable {fun f = (x,) => y}; let ic = InnerClass(1,); (InnerClass).f(ic, Nil,)}; main(2,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class InnerClass(y) extends Callable {\n//│     def f(x$5) =\n//│       y -- #24\n//│   }\n//│   def main(x$1) =\n//│     let x$2 = InnerClass(1) in -- #17\n//│     let x$3 = Nil() in -- #16\n//│     let x$4 = InnerClass.f(x$2,x$3) in -- #15\n//│     x$4 -- #14\n//│   let* (x$0) = main(2) in -- #4\n//│   x$0 -- #3\n//│ \n//│ Interpreted:\n//│ 1\n//│ \n//│ \n//│ Execution succeeded: \n//│ 1\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/LiftFun.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:genCpp\n:runCpp\n:interpIR\nfun main(init, key) =\n  fun r(x) = if x <= 0 then key else r(x - 1)\n  r(init)\nmain(1, 42)\n//│ |#fun| |main|(|init|,| |key|)| |#=|→|#fun| |r|(|x|)| |#=| |#if| |x| |<=| |0| |#then| |key| |#else| |r|(|x| |-| |1|)|↵|r|(|init|)|←|↵|main|(|1|,| |42|)|\n//│ Parsed: {fun main = (init, key,) => {fun r = (x,) => if (<=(x, 0,)) then key else r(-(x, 1,),); r(init,)}; main(1, 42,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def main(init$0,key$0) =\n//│     let* (x$1) = r(init$0,key$0) in -- #11\n//│     x$1 -- #10\n//│   def r(x$2,key$1) =\n//│     let x$3 = <=(x$2,0) in -- #40\n//│     if x$3 -- #39\n//│       true =>\n//│         jump j$0(key$1) -- #26\n//│       false =>\n//│         let x$5 = -(x$2,1) in -- #38\n//│         let* (x$6) = r(x$5,key$1) in -- #37\n//│         jump j$0(x$6) -- #36\n//│   def j$0(x$4) =\n//│     x$4 -- #24\n//│   let* (x$0) = main(1,42) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ 42\n//│ \n//│ \n//│ Execution succeeded: \n//│ 42\n//│ \n\n:genCpp\n:runCpp\n:interpIR\nfun main(init, key) =\n  fun ping(x) = if x <= 0 then key + 1 else pong(x - 1)\n  fun pong(x) = if x <= 0 then key + 2 else ping(x - 1)\n  ping(init)\nmain(1, 42)\n//│ |#fun| |main|(|init|,| |key|)| |#=|→|#fun| |ping|(|x|)| |#=| |#if| |x| |<=| |0| |#then| |key| |+| |1| |#else| |pong|(|x| |-| |1|)|↵|#fun| |pong|(|x|)| |#=| |#if| |x| |<=| |0| |#then| |key| |+| |2| |#else| |ping|(|x| |-| |1|)|↵|ping|(|init|)|←|↵|main|(|1|,| |42|)|\n//│ Parsed: {fun main = (init, key,) => {fun ping = (x,) => if (<=(x, 0,)) then +(key, 1,) else pong(-(x, 1,),); fun pong = (x,) => if (<=(x, 0,)) then +(key, 2,) else ping(-(x, 1,),); ping(init,)}; main(1, 42,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│ \n//│   def main(init$0,key$0) =\n//│     let* (x$1) = ping(init$0,key$0) in -- #11\n//│     x$1 -- #10\n//│   def ping(x$2,key$1) =\n//│     let x$3 = <=(x$2,0) in -- #46\n//│     if x$3 -- #45\n//│       true =>\n//│         let x$5 = +(key$1,1) in -- #32\n//│         jump j$0(x$5) -- #31\n//│       false =>\n//│         let x$6 = -(x$2,1) in -- #44\n//│         let* (x$7) = pong(x$6,key$1) in -- #43\n//│         jump j$0(x$7) -- #42\n//│   def j$0(x$4) =\n//│     x$4 -- #24\n//│   def pong(x$8,key$2) =\n//│     let x$9 = <=(x$8,0) in -- #75\n//│     if x$9 -- #74\n//│       true =>\n//│         let x$11 = +(key$2,2) in -- #61\n//│         jump j$1(x$11) -- #60\n//│       false =>\n//│         let x$12 = -(x$8,1) in -- #73\n//│         let* (x$13) = ping(x$12,key$2) in -- #72\n//│         jump j$1(x$13) -- #71\n//│   def j$1(x$10) =\n//│     x$10 -- #53\n//│   let* (x$0) = main(1,42) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ 44\n//│ \n//│ \n//│ Execution succeeded: \n//│ 44\n//│ \n\n:genCpp\n:runCpp\n:interpIR\nfun main(init, key) =\n  let ping =\n    fun ping(x) = if x <= 0 then key + 1 else pong(x - 1)\n    fun pong(x) = if x <= 0 then key + 2 else ping(x - 1)\n    ping\n  ping(init)\nmain(1, 42)\n//│ |#fun| |main|(|init|,| |key|)| |#=|→|#let| |ping| |#=|→|#fun| |ping|(|x|)| |#=| |#if| |x| |<=| |0| |#then| |key| |+| |1| |#else| |pong|(|x| |-| |1|)|↵|#fun| |pong|(|x|)| |#=| |#if| |x| |<=| |0| |#then| |key| |+| |2| |#else| |ping|(|x| |-| |1|)|↵|ping|←|↵|ping|(|init|)|←|↵|main|(|1|,| |42|)|\n//│ Parsed: {fun main = (init, key,) => {let ping = {fun ping = (x,) => if (<=(x, 0,)) then +(key, 1,) else pong(-(x, 1,),); fun pong = (x,) => if (<=(x, 0,)) then +(key, 2,) else ping(-(x, 1,),); ping}; ping(init,)}; main(1, 42,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Lambda$0(key) extends Callable {\n//│     def apply1(x$17) =\n//│       let* (x$18) = ping(x$17,key) in -- #85\n//│       x$18 -- #84\n//│   }\n//│   def main(init$0,key$0) =\n//│     let x$3 = Lambda$0(key$0) in -- #14\n//│     let x$4 = Callable.apply1(x$3,init$0) in -- #13\n//│     x$4 -- #12\n//│   def ping(x$5,key$1) =\n//│     let x$6 = <=(x$5,0) in -- #49\n//│     if x$6 -- #48\n//│       true =>\n//│         let x$8 = +(key$1,1) in -- #35\n//│         jump j$0(x$8) -- #34\n//│       false =>\n//│         let x$9 = -(x$5,1) in -- #47\n//│         let* (x$10) = pong(x$9,key$1) in -- #46\n//│         jump j$0(x$10) -- #45\n//│   def j$0(x$7) =\n//│     x$7 -- #27\n//│   def pong(x$11,key$2) =\n//│     let x$12 = <=(x$11,0) in -- #78\n//│     if x$12 -- #77\n//│       true =>\n//│         let x$14 = +(key$2,2) in -- #64\n//│         jump j$1(x$14) -- #63\n//│       false =>\n//│         let x$15 = -(x$11,1) in -- #76\n//│         let* (x$16) = ping(x$15,key$2) in -- #75\n//│         jump j$1(x$16) -- #74\n//│   def j$1(x$13) =\n//│     x$13 -- #56\n//│   let* (x$0) = main(1,42) in -- #6\n//│   x$0 -- #5\n//│ \n//│ Interpreted:\n//│ 44\n//│ \n//│ \n//│ Execution succeeded: \n//│ 44\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/LiftLambda.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:genCpp\n:runCpp\n:interpIR\nfun compose(f)(g)(x) = f(g(x))\nfun main(x) =\n  let y = 1\n  let lam = z => x + y + z\n  compose(lam)(lam)(2)\nmain(3)\n//│ |#fun| |compose|(|f|)|(|g|)|(|x|)| |#=| |f|(|g|(|x|)|)|↵|#fun| |main|(|x|)| |#=|→|#let| |y| |#=| |1|↵|#let| |lam| |#=| |z| |#=>| |x| |+| |y| |+| |z|↵|compose|(|lam|)|(|lam|)|(|2|)|←|↵|main|(|3|)|\n//│ Parsed: {fun compose = (f,) => (g,) => (x,) => f(g(x,),); fun main = (x,) => {let y = 1; let lam = (z,) => +(+(x, y,), z,); compose(lam,)(lam,)(2,)}; main(3,)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Lambda$0(f) extends Callable {\n//│     def apply1(g$0) =\n//│       let x$11 = Lambda$2(f,g$0) in -- #33\n//│       x$11 -- #32\n//│   }\n//│   class Lambda$1(x,y) extends Callable {\n//│     def apply1(z$0) =\n//│       let x$12 = +(x,y) in -- #46\n//│       let x$13 = +(x$12,z$0) in -- #45\n//│       x$13 -- #44\n//│   }\n//│   class Lambda$2(f,g) extends Callable {\n//│     def apply1(x$14) =\n//│       let x$15 = Callable.apply1(g,x$14) in -- #57\n//│       let x$16 = Callable.apply1(f,x$15) in -- #56\n//│       x$16 -- #55\n//│   }\n//│   def compose(f$0) =\n//│     let x$2 = Lambda$0(f$0) in -- #6\n//│     x$2 -- #5\n//│   def main(x$3) =\n//│     let x$4 = 1 in -- #25\n//│     let x$6 = Lambda$1(x$3,x$4) in -- #24\n//│     let* (x$7) = compose(x$6) in -- #23\n//│     let x$8 = Callable.apply1(x$7,x$6) in -- #22\n//│     let x$9 = Callable.apply1(x$8,2) in -- #21\n//│     x$9 -- #20\n//│   let* (x$0) = main(3) in -- #4\n//│   x$0 -- #3\n//│ \n//│ Interpreted:\n//│ 10\n//│ \n//│ \n//│ Execution succeeded: \n//│ 10\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/NuScratch.mls",
    "content": ":NewParser\n:ParseOnly\n:UseIR\n"
  },
  {
    "path": "compiler/shared/test/diff-ir/Override.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:genCpp\n:runCpp\n:interpIR\nmodule Base {\n  fun f() = 1\n}\nmodule Child extends Base {\n  fun f() = 2\n}\nfun main() =\n  let c = Child()\n  Base.f(c)\n  Child.f(c)\nmain()\n//│ |#module| |Base| |{|→|#fun| |f|(||)| |#=| |1|←|↵|}|↵|#module| |Child| |#extends| |Base| |{|→|#fun| |f|(||)| |#=| |2|←|↵|}|↵|#fun| |main|(||)| |#=|→|#let| |c| |#=| |Child|(||)|↵|Base|.f|(|c|)|↵|Child|.f|(|c|)|←|↵|main|(||)|\n//│ Parsed: {module Base {fun f = () => 1}; module Child: Base {fun f = () => 2}; fun main = () => {let c = Child(); (Base).f(c,); (Child).f(c,)}; main()}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Base() {\n//│     def f() =\n//│       1 -- #16\n//│   }\n//│   class Child() extends Base {\n//│     def f() =\n//│       2 -- #17\n//│   }\n//│   def main() =\n//│     let x$1 = Child() in -- #15\n//│     let x$2 = Base.f(x$1) in -- #14\n//│     let x$3 = Child.f(x$1) in -- #13\n//│     x$3 -- #12\n//│   let* (x$0) = main() in -- #2\n//│   x$0 -- #1\n//│ \n//│ Interpreted:\n//│ 2\n//│ \n//│ \n//│ Execution succeeded: \n//│ 2\n//│ \n"
  },
  {
    "path": "compiler/shared/test/diff-ir/cpp/Makefile",
    "content": "CXX := g++\nCFLAGS += -O3 -Wall -Wextra -std=c++20 -I. -Wno-inconsistent-missing-override -I/opt/homebrew/include\nLDFLAGS += -L/opt/homebrew/lib\nLDLIBS := -lmimalloc -lgmp\nSRC :=\nINCLUDES := mlsprelude.h\nDST :=\nDEFAULT_TARGET := mls\nTARGET := $(or $(DST),$(DEFAULT_TARGET))\n\n.PHONY: pre all run clean auto\n\nall: $(TARGET)\n\nrun: $(TARGET) \n\t./$(TARGET)\n\npre: $(SRC)\n\tsed -i '' 's#^//│ ##g' $(SRC)\n\nclean:\n\trm -r $(TARGET) $(TARGET).dSYM\n\nauto: $(TARGET)\n\n$(TARGET): $(SRC) $(INCLUDES)\n\t$(CXX) $(CFLAGS) $(LDFLAGS) $(SRC) $(LDLIBS) -o $(TARGET)\n"
  },
  {
    "path": "compiler/shared/test/diff-ir/cpp/mlsprelude.h",
    "content": "#include <cassert>\n#include <cinttypes>\n#include <cstdint>\n#include <cstdio>\n#include <limits>\n#include <new>\n#include <pthread.h>\n#include <stdexcept>\n#include <sys/resource.h>\n#include <tuple>\n#include <typeinfo>\n#include <utility>\n\nconstexpr std::size_t _mlsAlignment = 8;\n\ntemplate <typename T, size_t N> class tuple_type {\n  template <typename = std::make_index_sequence<N>> struct impl;\n  template <size_t... Is> struct impl<std::index_sequence<Is...>> {\n    template <size_t> using wrap = T;\n    using type = std::tuple<wrap<Is>...>;\n  };\n\npublic:\n  using type = typename impl<>::type;\n};\ntemplate <auto Id> struct counter {\n  using tag = counter;\n\n  struct generator {\n    friend consteval auto is_defined(tag) { return true; }\n  };\n  friend consteval auto is_defined(tag);\n\n  template <typename Tag = tag, auto = is_defined(Tag{})>\n  static consteval auto exists(auto) {\n    return true;\n  }\n\n  static consteval auto exists(...) { return generator(), false; }\n};\n\ntemplate <auto Id = int{}, typename = decltype([] {})>\nconsteval auto nextTypeTag() {\n  if constexpr (not counter<Id>::exists(Id))\n    return Id;\n  else\n    return nextTypeTag<Id + 1>();\n}\n\nstruct _mlsObject {\n  uint32_t refCount;\n  uint32_t tag;\n  constexpr static inline uint32_t stickyRefCount =\n      std::numeric_limits<decltype(refCount)>::max();\n\n  void incRef() {\n    if (refCount != stickyRefCount)\n      ++refCount;\n  }\n  bool decRef() {\n    if (refCount != stickyRefCount && --refCount == 0)\n      return true;\n    return false;\n  }\n\n  virtual void print() const = 0;\n  virtual void destroy() = 0;\n};\n\nstruct _mls_True;\nstruct _mls_False;\n\nclass _mlsValue {\n  using uintptr_t = std::uintptr_t;\n  using uint64_t = std::uint64_t;\n\n  void *value alignas(_mlsAlignment);\n\n  bool isInt63() const { return (reinterpret_cast<uintptr_t>(value) & 1) == 1; }\n\n  bool isPtr() const { return (reinterpret_cast<uintptr_t>(value) & 1) == 0; }\n\n  uint64_t asInt63() const { return reinterpret_cast<uintptr_t>(value) >> 1; }\n\n  uintptr_t asRawInt() const { return reinterpret_cast<uintptr_t>(value); }\n\n  static _mlsValue fromRawInt(uintptr_t i) {\n    return _mlsValue(reinterpret_cast<void *>(i));\n  }\n\n  static _mlsValue fromInt63(uint64_t i) {\n    return _mlsValue(reinterpret_cast<void *>((i << 1) | 1));\n  }\n\n  void *asPtr() const {\n    assert(!isInt63());\n    return value;\n  }\n\n  _mlsObject *asObject() const {\n    assert(isPtr());\n    return static_cast<_mlsObject *>(value);\n  }\n\n  bool eqInt63(const _mlsValue &other) const {\n    return asRawInt() == other.asRawInt();\n  }\n\n  _mlsValue addInt63(const _mlsValue &other) const {\n    return fromRawInt(asRawInt() + other.asRawInt() - 1);\n  }\n\n  _mlsValue subInt63(const _mlsValue &other) const {\n    return fromRawInt(asRawInt() - other.asRawInt() + 1);\n  }\n\n  _mlsValue mulInt63(const _mlsValue &other) const {\n    return fromInt63(asInt63() * other.asInt63());\n  }\n\n  _mlsValue divInt63(const _mlsValue &other) const {\n    return fromInt63(asInt63() / other.asInt63());\n  }\n\n  _mlsValue gtInt63(const _mlsValue &other) const {\n    return asInt63() > other.asInt63() ? _mlsValue::create<_mls_True>()\n                                       : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue ltInt63(const _mlsValue &other) const {\n    return asInt63() < other.asInt63() ? _mlsValue::create<_mls_True>()\n                                       : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue geInt63(const _mlsValue &other) const {\n    return asInt63() >= other.asInt63() ? _mlsValue::create<_mls_True>()\n                                        : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue leInt63(const _mlsValue &other) const {\n    return asInt63() <= other.asInt63() ? _mlsValue::create<_mls_True>()\n                                        : _mlsValue::create<_mls_False>();\n  }\n\npublic:\n  explicit _mlsValue() : value(nullptr) {}\n  explicit _mlsValue(void *value) : value(value) {}\n  _mlsValue(const _mlsValue &other) : value(other.value) {\n    if (isPtr())\n      asObject()->incRef();\n  }\n\n  _mlsValue &operator=(const _mlsValue &other) {\n    if (value != nullptr && isPtr())\n      asObject()->decRef();\n    value = other.value;\n    if (isPtr())\n      asObject()->incRef();\n    return *this;\n  }\n\n  ~_mlsValue() {\n    if (isPtr())\n      if (asObject()->decRef()) {\n        asObject()->destroy();\n        value = nullptr;\n      }\n  }\n\n  uint64_t asInt() const {\n    assert(isInt63());\n    return asInt63();\n  }\n\n  static _mlsValue fromIntLit(uint64_t i) { return fromInt63(i); }\n\n  template <unsigned N> static tuple_type<_mlsValue, N> never() {\n    __builtin_unreachable();\n  }\n  static _mlsValue never() { __builtin_unreachable(); }\n\n  template <typename T, typename... U> static _mlsValue create(U... args) {\n    return _mlsValue(T::create(args...));\n  }\n\n  static void destroy(_mlsValue &v) { v.~_mlsValue(); }\n\n  template <typename T> static bool isValueOf(const _mlsValue &v) {\n    return v.asObject()->tag == T::typeTag;\n  }\n\n  static bool isIntLit(const _mlsValue &v, uint64_t n) {\n    return v.asInt63() == n;\n  }\n\n  static bool isIntLit(const _mlsValue &v) { return v.isInt63(); }\n\n  template <typename T> static T *as(const _mlsValue &v) {\n    return dynamic_cast<T *>(v.asObject());\n  }\n\n  template <typename T> static T *cast(_mlsValue &v) {\n    return static_cast<T *>(v.asObject());\n  }\n\n  // Operators\n\n  _mlsValue operator==(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return eqInt63(other) ? _mlsValue::create<_mls_True>()\n                            : _mlsValue::create<_mls_False>();\n    assert(false);\n  }\n\n  _mlsValue operator+(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return addInt63(other);\n    assert(false);\n  }\n\n  _mlsValue operator-(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return subInt63(other);\n    assert(false);\n  }\n\n  _mlsValue operator*(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return mulInt63(other);\n    assert(false);\n  }\n\n  _mlsValue operator/(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return divInt63(other);\n    assert(false);\n  }\n\n  _mlsValue operator>(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return gtInt63(other);\n    assert(false);\n  }\n\n  _mlsValue operator<(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return ltInt63(other);\n    assert(false);\n  }\n\n  _mlsValue operator>=(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return geInt63(other);\n    assert(false);\n  }\n\n  _mlsValue operator<=(const _mlsValue &other) const {\n    if (isInt63() && other.isInt63())\n      return leInt63(other);\n    assert(false);\n  }\n\n  // Auxiliary functions\n\n  void print() const {\n    if (isInt63())\n      std::printf(\"%\" PRIu64, asInt63());\n    else if (isPtr() && asObject())\n      asObject()->print();\n  }\n};\n\nstruct _mls_Callable : public _mlsObject {\n  virtual _mlsValue _mls_apply0() { throw std::runtime_error(\"Not implemented\"); }\n  virtual _mlsValue _mls_apply1(_mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual _mlsValue _mls_apply2(_mlsValue, _mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual _mlsValue _mls_apply3(_mlsValue, _mlsValue, _mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual _mlsValue _mls_apply4(_mlsValue, _mlsValue, _mlsValue, _mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual void destroy() override {}\n};\n\ninline static _mls_Callable *_mlsToCallable(_mlsValue fn) {\n  auto *ptr = _mlsValue::as<_mls_Callable>(fn);\n  if (!ptr)\n    throw std::runtime_error(\"Not a callable object\");\n  return ptr;\n}\n\ntemplate <typename... U>\ninline static _mlsValue _mlsCall(_mlsValue f, U... args) {\n  static_assert(sizeof...(U) <= 4, \"Too many arguments\");\n  if constexpr (sizeof...(U) == 0)\n    return _mlsToCallable(f)->_mls_apply0();\n  else if constexpr (sizeof...(U) == 1)\n    return _mlsToCallable(f)->_mls_apply1(args...);\n  else if constexpr (sizeof...(U) == 2)\n    return _mlsToCallable(f)->_mls_apply2(args...);\n  else if constexpr (sizeof...(U) == 3)\n    return _mlsToCallable(f)->_mls_apply3(args...);\n  else if constexpr (sizeof...(U) == 4)\n    return _mlsToCallable(f)->_mls_apply4(args...);\n}\n\ntemplate <typename T>\ninline static T *_mlsMethodCall(_mlsValue self) {\n  auto *ptr = _mlsValue::as<T>(self);\n  if (!ptr)\n    throw std::runtime_error(\"unable to convert object for method calls\");\n  return ptr;\n}\n\ninline int _mlsLargeStack(void *(*fn)(void *)) {\n  pthread_t thread;\n  pthread_attr_t attr;\n\n  size_t stacksize = 512 * 1024 * 1024;\n  pthread_attr_init(&attr);\n  pthread_attr_setstacksize(&attr, stacksize);\n\n  int rc = pthread_create(&thread, &attr, fn, nullptr);\n  if (rc) {\n    printf(\"ERROR: return code from pthread_create() is %d\\n\", rc);\n    return 1;\n  }\n  pthread_join(thread, NULL);\n  return 0;\n}\n\n_mlsValue _mlsMain();\n\ninline void *_mlsMainWrapper(void *) {\n  _mlsValue res = _mlsMain();\n  res.print();\n  return nullptr;\n}\n\nstruct _mls_Unit final : public _mlsObject {\n  constexpr static inline const char *typeName = \"Unit\";\n  constexpr static inline uint32_t typeTag = nextTypeTag();\n  virtual void print() const override { std::printf(typeName); }\n  static _mlsValue create() {\n    static _mls_Unit mlsUnit alignas(_mlsAlignment);\n    mlsUnit.refCount = stickyRefCount;\n    mlsUnit.tag = typeTag;\n    return _mlsValue(&mlsUnit);\n  }\n  virtual void destroy() override {}\n};\n\nstruct _mls_Boolean : public _mlsObject {};\n\nstruct _mls_True final : public _mls_Boolean {\n  constexpr static inline const char *typeName = \"True\";\n  constexpr static inline uint32_t typeTag = nextTypeTag();\n  virtual void print() const override { std::printf(typeName); }\n  static _mlsValue create() {\n    static _mls_True mlsTrue alignas(_mlsAlignment);\n    mlsTrue.refCount = stickyRefCount;\n    mlsTrue.tag = typeTag;\n    return _mlsValue(&mlsTrue);\n  }\n  virtual void destroy() override {}\n};\n\nstruct _mls_False final : public _mls_Boolean {\n  constexpr static inline const char *typeName = \"False\";\n  constexpr static inline uint32_t typeTag = nextTypeTag();\n  virtual void print() const override { std::printf(typeName); }\n  static _mlsValue create() {\n    static _mls_False mlsFalse alignas(_mlsAlignment);\n    mlsFalse.refCount = stickyRefCount;\n    mlsFalse.tag = typeTag;\n    return _mlsValue(&mlsFalse);\n  }\n  virtual void destroy() override {}\n};\n\n#include <boost/multiprecision/gmp.hpp>\n\nstruct _mls_ZInt final : public _mlsObject {\n  boost::multiprecision::mpz_int z;\n  constexpr static inline const char *typeName = \"Z\";\n  constexpr static inline uint32_t typeTag = nextTypeTag();\n  virtual void print() const override {\n    std::printf(typeName);\n    std::printf(\"(\");\n    std::printf(\"%s\", z.str().c_str());\n    std::printf(\")\");\n  }\n  virtual void destroy() override {\n    z.~number();\n    operator delete(this, std::align_val_t(_mlsAlignment));\n  }\n  static _mlsValue create() {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_ZInt;\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    return _mlsValue(_mlsVal);\n  }\n  static _mlsValue create(_mlsValue z) {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_ZInt;\n    _mlsVal->z = z.asInt();\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    return _mlsValue(_mlsVal);\n  }\n  _mlsValue operator+(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z + other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator-(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z - other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator*(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z * other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator/(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z / other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator%(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z % other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator==(const _mls_ZInt &other) const {\n    return z == other.z ? _mlsValue::create<_mls_True>()\n                        : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue operator>(const _mls_ZInt &other) const {\n    return z > other.z ? _mlsValue::create<_mls_True>()\n                       : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue operator<(const _mls_ZInt &other) const {\n    return z < other.z ? _mlsValue::create<_mls_True>()\n                       : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue operator>=(const _mls_ZInt &other) const {\n    return z >= other.z ? _mlsValue::create<_mls_True>()\n                        : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue operator<=(const _mls_ZInt &other) const {\n    return z <= other.z ? _mlsValue::create<_mls_True>()\n                        : _mlsValue::create<_mls_False>();\n  }\n\n  _mlsValue toInt() const {\n    return _mlsValue::fromIntLit(z.convert_to<uint64_t>());\n  }\n\n  static _mlsValue fromInt(uint64_t i) {\n    return _mlsValue::create<_mls_ZInt>(_mlsValue::fromIntLit(i));\n  }\n};\n\n__attribute__((noinline)) inline void _mlsNonExhaustiveMatch() {\n  throw std::runtime_error(\"Non-exhaustive match\");\n}\n\ninline _mlsValue _mls_builtin_z_add(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) + *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_sub(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) - *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_mul(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) * *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_div(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) / *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_mod(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) % *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_equal(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) == *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_gt(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) > *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_lt(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) < *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_geq(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) >= *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_leq(_mlsValue a, _mlsValue b) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) <= *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_to_int(_mlsValue a) {\n  assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  return _mlsValue::cast<_mls_ZInt>(a)->toInt();\n}\n\ninline _mlsValue _mls_builtin_z_of_int(_mlsValue a) {\n  assert(_mlsValue::isIntLit(a));\n  return _mlsValue::create<_mls_ZInt>(a);\n}\n\ninline _mlsValue _mls_builtin_print(_mlsValue a) {\n  a.print();\n  return _mlsValue::create<_mls_Unit>();\n}\n\ninline _mlsValue _mls_builtin_println(_mlsValue a) {\n  a.print();\n  std::puts(\"\");\n  return _mlsValue::create<_mls_Unit>();\n}\n\ninline _mlsValue _mls_builtin_debug(_mlsValue a) {\n  a.print();\n  std::puts(\"\");\n  return a;\n}\n"
  },
  {
    "path": "compiler/shared/test/diff-ir/gcd.mls",
    "content": ":NewDefs\n:ParseOnly\n:UseIR\n:NoTailRec\n\n:prelude\nmodule True\nmodule False\nmodule Callable {\n  fun apply0() = 0\n  fun apply1(x0) = 0\n  fun apply2(x0,x1) = 0\n  fun apply3(x0,x1,x2) = 0\n  fun apply4(x0,x1,x2,x3) = 0\n  fun apply5(x0,x1,x2,x3,x4) = 0\n}\nmodule List[A, B]\nclass Cons[A, B](h: A, t: Cons[A, B]) extends List[A, B]\nmodule Nil[A, B] extends List[A, B]\nmodule Option[A]\nclass Some[A](x: A) extends Option[A]\nmodule None[A] extends Option[A]\nclass Pair[A, B](x: A, y: B)\nclass Tuple2[A, B](x: A, y: B)\nclass Tuple3[A, B, C](x: A, y: B, z: C)\nmodule Nat\nclass S(s: Nat) extends Nat\nmodule O extends Nat\nclass HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O)\n//│ |#module| |True|↵|#module| |False|↵|#module| |Callable| |{|→|#fun| |apply0|(||)| |#=| |0|↵|#fun| |apply1|(|x0|)| |#=| |0|↵|#fun| |apply2|(|x0|,|x1|)| |#=| |0|↵|#fun| |apply3|(|x0|,|x1|,|x2|)| |#=| |0|↵|#fun| |apply4|(|x0|,|x1|,|x2|,|x3|)| |#=| |0|↵|#fun| |apply5|(|x0|,|x1|,|x2|,|x3|,|x4|)| |#=| |0|←|↵|}|↵|#module| |List|[|A|,| |B|]|↵|#class| |Cons|[|A|,| |B|]|(|h|#:| |A|,| |t|#:| |Cons|[|A|,| |B|]|)| |#extends| |List|[|A|,| |B|]|↵|#module| |Nil|[|A|,| |B|]| |#extends| |List|[|A|,| |B|]|↵|#module| |Option|[|A|]|↵|#class| |Some|[|A|]|(|x|#:| |A|)| |#extends| |Option|[|A|]|↵|#module| |None|[|A|]| |#extends| |Option|[|A|]|↵|#class| |Pair|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple2|[|A|,| |B|]|(|x|#:| |A|,| |y|#:| |B|)|↵|#class| |Tuple3|[|A|,| |B|,| |C|]|(|x|#:| |A|,| |y|#:| |B|,| |z|#:| |C|)|↵|#module| |Nat|↵|#class| |S|(|s|#:| |Nat|)| |#extends| |Nat|↵|#module| |O| |#extends| |Nat|↵|#class| |HiddenTheseEntities|(|_0|#:| |HiddenTheseEntities|,| |_1|#:| |True|,| |_2|#:| |False|,| |_3|#:| |Callable|,| |_4|#:| |List|,| |_5|#:| |Cons|,| |_6|#:| |Nil|,| |_7|#:| |Option|,| |_8|#:| |Some|,| |_9|#:| |None|,| |_10|#:| |Pair|,| |_11|#:| |Tuple2|,| |_12|#:| |Tuple3|,| |_13|#:| |Nat|,| |_14|#:| |S|,| |_15|#:| |O|)|\n//│ Parsed: {module True {}; module False {}; module Callable {fun apply0 = () => 0; fun apply1 = (x0,) => 0; fun apply2 = (x0, x1,) => 0; fun apply3 = (x0, x1, x2,) => 0; fun apply4 = (x0, x1, x2, x3,) => 0; fun apply5 = (x0, x1, x2, x3, x4,) => 0}; module List‹A, B› {}; class Cons‹A, B›(h: A, t: Cons‹A, B›,): List‹A, B› {}; module Nil‹A, B›: List‹A, B› {}; module Option‹A› {}; class Some‹A›(x: A,): Option‹A› {}; module None‹A›: Option‹A› {}; class Pair‹A, B›(x: A, y: B,) {}; class Tuple2‹A, B›(x: A, y: B,) {}; class Tuple3‹A, B, C›(x: A, y: B, z: C,) {}; module Nat {}; class S(s: Nat,): Nat {}; module O: Nat {}; class HiddenTheseEntities(_0: HiddenTheseEntities, _1: True, _2: False, _3: Callable, _4: List, _5: Cons, _6: Nil, _7: Option, _8: Some, _9: None, _10: Pair, _11: Tuple2, _12: Tuple3, _13: Nat, _14: S, _15: O,) {}}\n//│ \n//│ Preluded.\n//│ \n\n:genCpp\n:runCpp\nfun error() = builtin(\"error\")\nfun z_of_int(x) = builtin(\"z_of_int\", x)\nfun z_to_int(x) = builtin(\"z_to_int\", x)\nfun z_add(x, y) = builtin(\"z_add\", x, y)\nfun z_sub(x, y) = builtin(\"z_sub\", x, y)\nfun z_div(x, y) = builtin(\"z_div\", x, y)\nfun z_mul(x, y) = builtin(\"z_mul\", x, y)\nfun z_mod(x, y) = builtin(\"z_mod\", x, y)\nfun z_lt(x, y) = builtin(\"z_lt\", x, y)\nfun z_leq(x, y) = builtin(\"z_leq\", x, y)\nfun z_equal(x, y) = builtin(\"z_equal\", x, y)\nfun z_gt(x, y) = builtin(\"z_gt\", x, y)\nfun z_geq(x, y) = builtin(\"z_geq\", x, y)\nfun println(x) = builtin(\"println\", x)\nfun print(x) = builtin(\"print\", x)\nfun debug(x) = builtin(\"debug\", x)\nfun map(f, ls) =\n  if ls is\n    Cons (h, t) then\n      Cons (f(h), map(f, t))\n    Nil then\n      Nil\nfun filter(f_2, ls_2) =\n  if ls_2 is\n    Cons (h_2, t_2) then\n      if f_2(h_2) then\n        Cons (h_2, filter(f_2, t_2))\n      else\n        (filter(f_2, t_2))\n    Nil then\n      Nil\nfun foldl(f_4, i, ls_4) =\n  if ls_4 is\n    Cons (h_4, t_4) then\n      foldl(f_4, f_4(i, h_4), t_4)\n    Nil then\n      i\nfun foldr(f_5, i_1, ls_5) =\n  if ls_5 is\n    Cons (h_5, t_5) then\n      f_5(h_5, foldr(f_5, i_1, t_5))\n    Nil then\n      i_1\nfun zip(xs, ys) =\n  if xs is\n    Cons (hx, tx) then\n      if ys is\n        Cons (hy, ty) then\n          Cons (Tuple2 (hx, hy), zip(tx, ty))\n        Nil then\n          Nil\n    Nil then\n      Nil\nfun zipWith(f_7, xs_4, ys_4) =\n  if xs_4 is\n    Cons (hx_4, tx_4) then\n      if ys_4 is\n        Cons (hy_4, ty_4) then\n          Cons (f_7(hx_4, hy_4), zipWith(f_7, tx_4, ty_4))\n        Nil then\n          Nil\n    Nil then\n      Nil\nfun head(ls_7) =\n  if ls_7 is\n    Cons (h_7, t_7) then\n      h_7\n    Nil then\n      error\nfun tail(ls_9) =\n  if ls_9 is\n    Cons (h_9, t_9) then\n      t_9\n    Nil then\n      error\nfun enumFromTo(a, b) =\n  if a <= b then\n    Cons (a, enumFromTo(a + 1, b))\n  else\n    (Nil)\nfun enumFromThenTo(a_1, t_11, b_1) =\n  if a_1 <= b_1 then\n    Cons (a_1, enumFromThenTo(t_11, 2 * t_11 - a_1, b_1))\n  else\n    (Nil)\nfun take(n, ls_11) =\n  if n > 0 then\n    if ls_11 is\n      Cons (h_11, t_13) then\n        Cons (h_11, take(n - 1, t_13))\n      Nil then\n        Nil\n  else\n    (Nil)\nfun length(ls_13) =\n  if ls_13 is\n    Cons (h_13, t_15) then\n      1 + (length(t_15))\n    Nil then\n      0\nfun mappend(xs_8, ys_8) =\n  if xs_8 is\n    Cons (h_14, t_16) then\n      Cons (h_14, mappend(t_16, ys_8))\n    Nil then\n      ys_8\nfun sum(ls_14) =\n  sumAux(ls_14, 0)\nfun sumAux(ls_15, a_4) =\n  if ls_15 is\n    Nil then\n      a_4\n    Cons (h_15, t_17) then\n      sumAux(t_17, a_4 + h_15)\nfun atIndex(n_2, ls_16) =\n  if n_2 < 0 then\n    error\n  else\n    if ls_16 is\n      Cons (h_16, t_18) then\n        if n_2 == 0 then\n          h_16\n        else\n          (atIndex(n_2 - 1, t_18))\n      Nil then\n        error\nfun concat(lss) =\n  if lss is\n    Cons (h_18, t_20) then\n      mappend(h_18, concat(t_20))\n    Nil then\n      Nil\nfun reverse(ls_18) =\n  reverse_helper(ls_18, Nil)\nfun reverse_helper(ls_19, a_5) =\n  if ls_19 is\n    Cons (h_19, t_21) then\n      reverse_helper(t_21, Cons (h_19, a_5))\n    Nil then\n      a_5\nfun listcomp_fun1(ms, listcomp_fun_para) =\n  if listcomp_fun_para is\n      Cons(listcomp_fun_ls_h, listcomp_fun_ls_t) then\n        listcomp_fun2(ms, listcomp_fun_ls_h, listcomp_fun_ls_t, ms)\n      Nil then\n        Nil\nfun listcomp_fun2(ms, listcomp_fun_ls_h_out, listcomp_fun_ls_t_out, listcomp_fun_para) =\n  if listcomp_fun_para is\n    Cons(listcomp_fun_ls_h, listcomp_fun_ls_t) then\n      Cons(Tuple2 (listcomp_fun_ls_h_out, listcomp_fun_ls_h), listcomp_fun2(ms, listcomp_fun_ls_h_out, listcomp_fun_ls_t_out, listcomp_fun_ls_t))\n    Nil then\n      listcomp_fun1(ms, listcomp_fun_ls_t_out)\nfun test(test_arg1) =\n  let ns = z_enumFromTo(const5000(), z_add(const5000(), test_arg1))\n  let ms = z_enumFromTo(const10000(), z_add(const10000(), test_arg1))\n  let tripls = map(f1, listcomp_fun1(ms, ns))\n  let rs = map(f2, tripls)\n  max'(rs)\nfun const10000() =\n  z_of_int(10000)\nfun f1(f1_arg1) =\n  if f1_arg1 is\n    Tuple2 (f1_Tuple2_0, f1_Tuple2_1) then\n      Tuple3 (f1_Tuple2_0, f1_Tuple2_1, gcdE(f1_Tuple2_0, f1_Tuple2_1))\nfun quotRem(quotRem_arg1, quotRem_arg2) =\n  Tuple2 (z_div(quotRem_arg1, quotRem_arg2), z_mod(quotRem_arg1, quotRem_arg2))\nfun max'(max'_arg1) =\n  if max'_arg1 is\n    Cons (max'_Cons_0, max'_Cons_1) then\n      if max'_Cons_1 is\n        Nil then\n          max'_Cons_0\n        Cons (max'_Cons_0_1, max'_Cons_1_1) then\n          if z_lt(max'_Cons_0, max'_Cons_0_1) then\n            max'(Cons (max'_Cons_0_1, max'_Cons_1_1))\n          else\n            (max'(Cons (max'_Cons_0, max'_Cons_1_1)))\nfun g(g_arg1, g_arg2) =\n  if g_arg1 is\n    Tuple3 (g_Tuple3_0, g_Tuple3_1, g_Tuple3_2) then\n      if g_arg2 is\n        Tuple3 (g_Tuple3_0_1, g_Tuple3_1_1, g_Tuple3_2_1) then\n          if z_equal(g_Tuple3_2_1, const0()) then\n            Tuple3 (g_Tuple3_2, g_Tuple3_0, g_Tuple3_1)\n          else\n            let matchIdent = quotRem(g_Tuple3_2, g_Tuple3_2_1)\n            if matchIdent is\n              Tuple2 (g_Tuple2_0, g_Tuple2_1) then\n                g(Tuple3 (g_Tuple3_0_1, g_Tuple3_1_1, g_Tuple3_2_1), Tuple3 (z_sub(g_Tuple3_0, z_mul(g_Tuple2_0, g_Tuple3_0_1)), z_sub(g_Tuple3_1, z_mul(g_Tuple2_0, g_Tuple3_1_1)), g_Tuple2_1))\nfun abs(abs_arg1) =\n  if z_lt(abs_arg1, const0()) then\n    z_sub(const0(), abs_arg1)\n  else\n    abs_arg1\nfun f2(f2_arg1) =\n  if f2_arg1 is\n    Tuple3 (f2_Tuple3_0, f2_Tuple3_1, f2_Tuple3_2) then\n      if f2_Tuple3_2 is\n        Tuple3 (f2_Tuple3_0_1, f2_Tuple3_1_1, f2_Tuple3_2_1) then\n          abs(z_add(z_add(f2_Tuple3_0_1, f2_Tuple3_1_1), f2_Tuple3_2_1))\nfun const0() =\n  z_of_int(0)\nfun gcdE(gcdE_arg1, gcdE_arg2) =\n  if z_equal(gcdE_arg1, const0()) then\n    Tuple3 (gcdE_arg2, const0(), const1())\n  else\n    (g(Tuple3 (const1(), const0(), gcdE_arg1), Tuple3 (const0(), const1(), gcdE_arg2)))\nfun const1() =\n  z_of_int(1)\nfun const5000() =\n  z_of_int(5000)\nfun testGcd_nofib(testGcd_nofib_arg1) =\n  test(testGcd_nofib_arg1)\nfun z_enumFromTo(z_enumFromTo_arg1, z_enumFromTo_arg2) =\n  if z_leq(z_enumFromTo_arg1, z_enumFromTo_arg2) then\n    Cons (z_enumFromTo_arg1, z_enumFromTo(z_add(z_enumFromTo_arg1, const1()), z_enumFromTo_arg2))\n  else\n    (Nil)\ntestGcd_nofib(z_of_int(400))\n//│ |#fun| |error|(||)| |#=| |builtin|(|\"error\"|)|↵|#fun| |z_of_int|(|x|)| |#=| |builtin|(|\"z_of_int\"|,| |x|)|↵|#fun| |z_to_int|(|x|)| |#=| |builtin|(|\"z_to_int\"|,| |x|)|↵|#fun| |z_add|(|x|,| |y|)| |#=| |builtin|(|\"z_add\"|,| |x|,| |y|)|↵|#fun| |z_sub|(|x|,| |y|)| |#=| |builtin|(|\"z_sub\"|,| |x|,| |y|)|↵|#fun| |z_div|(|x|,| |y|)| |#=| |builtin|(|\"z_div\"|,| |x|,| |y|)|↵|#fun| |z_mul|(|x|,| |y|)| |#=| |builtin|(|\"z_mul\"|,| |x|,| |y|)|↵|#fun| |z_mod|(|x|,| |y|)| |#=| |builtin|(|\"z_mod\"|,| |x|,| |y|)|↵|#fun| |z_lt|(|x|,| |y|)| |#=| |builtin|(|\"z_lt\"|,| |x|,| |y|)|↵|#fun| |z_leq|(|x|,| |y|)| |#=| |builtin|(|\"z_leq\"|,| |x|,| |y|)|↵|#fun| |z_equal|(|x|,| |y|)| |#=| |builtin|(|\"z_equal\"|,| |x|,| |y|)|↵|#fun| |z_gt|(|x|,| |y|)| |#=| |builtin|(|\"z_gt\"|,| |x|,| |y|)|↵|#fun| |z_geq|(|x|,| |y|)| |#=| |builtin|(|\"z_geq\"|,| |x|,| |y|)|↵|#fun| |println|(|x|)| |#=| |builtin|(|\"println\"|,| |x|)|↵|#fun| |print|(|x|)| |#=| |builtin|(|\"print\"|,| |x|)|↵|#fun| |debug|(|x|)| |#=| |builtin|(|\"debug\"|,| |x|)|↵|#fun| |map|(|f|,| |ls|)| |#=|→|#if| |ls| |is|→|Cons| |(|h|,| |t|)| |#then|→|Cons| |(|f|(|h|)|,| |map|(|f|,| |t|)|)|←|↵|Nil| |#then|→|Nil|←|←|←|↵|#fun| |filter|(|f_2|,| |ls_2|)| |#=|→|#if| |ls_2| |is|→|Cons| |(|h_2|,| |t_2|)| |#then|→|#if| |f_2|(|h_2|)| |#then|→|Cons| |(|h_2|,| |filter|(|f_2|,| |t_2|)|)|←|↵|#else|→|(|filter|(|f_2|,| |t_2|)|)|←|←|↵|Nil| |#then|→|Nil|←|←|←|↵|#fun| |foldl|(|f_4|,| |i|,| |ls_4|)| |#=|→|#if| |ls_4| |is|→|Cons| |(|h_4|,| |t_4|)| |#then|→|foldl|(|f_4|,| |f_4|(|i|,| |h_4|)|,| |t_4|)|←|↵|Nil| |#then|→|i|←|←|←|↵|#fun| |foldr|(|f_5|,| |i_1|,| |ls_5|)| |#=|→|#if| |ls_5| |is|→|Cons| |(|h_5|,| |t_5|)| |#then|→|f_5|(|h_5|,| |foldr|(|f_5|,| |i_1|,| |t_5|)|)|←|↵|Nil| |#then|→|i_1|←|←|←|↵|#fun| |zip|(|xs|,| |ys|)| |#=|→|#if| |xs| |is|→|Cons| |(|hx|,| |tx|)| |#then|→|#if| |ys| |is|→|Cons| |(|hy|,| |ty|)| |#then|→|Cons| |(|Tuple2| |(|hx|,| |hy|)|,| |zip|(|tx|,| |ty|)|)|←|↵|Nil| |#then|→|Nil|←|←|←|↵|Nil| |#then|→|Nil|←|←|←|↵|#fun| |zipWith|(|f_7|,| |xs_4|,| |ys_4|)| |#=|→|#if| |xs_4| |is|→|Cons| |(|hx_4|,| |tx_4|)| |#then|→|#if| |ys_4| |is|→|Cons| |(|hy_4|,| |ty_4|)| |#then|→|Cons| |(|f_7|(|hx_4|,| |hy_4|)|,| |zipWith|(|f_7|,| |tx_4|,| |ty_4|)|)|←|↵|Nil| |#then|→|Nil|←|←|←|↵|Nil| |#then|→|Nil|←|←|←|↵|#fun| |head|(|ls_7|)| |#=|→|#if| |ls_7| |is|→|Cons| |(|h_7|,| |t_7|)| |#then|→|h_7|←|↵|Nil| |#then|→|error|←|←|←|↵|#fun| |tail|(|ls_9|)| |#=|→|#if| |ls_9| |is|→|Cons| |(|h_9|,| |t_9|)| |#then|→|t_9|←|↵|Nil| |#then|→|error|←|←|←|↵|#fun| |enumFromTo|(|a|,| |b|)| |#=|→|#if| |a| |<=| |b| |#then|→|Cons| |(|a|,| |enumFromTo|(|a| |+| |1|,| |b|)|)|←|↵|#else|→|(|Nil|)|←|←|↵|#fun| |enumFromThenTo|(|a_1|,| |t_11|,| |b_1|)| |#=|→|#if| |a_1| |<=| |b_1| |#then|→|Cons| |(|a_1|,| |enumFromThenTo|(|t_11|,| |2| |*| |t_11| |-| |a_1|,| |b_1|)|)|←|↵|#else|→|(|Nil|)|←|←|↵|#fun| |take|(|n|,| |ls_11|)| |#=|→|#if| |n| |>| |0| |#then|→|#if| |ls_11| |is|→|Cons| |(|h_11|,| |t_13|)| |#then|→|Cons| |(|h_11|,| |take|(|n| |-| |1|,| |t_13|)|)|←|↵|Nil| |#then|→|Nil|←|←|←|↵|#else|→|(|Nil|)|←|←|↵|#fun| |length|(|ls_13|)| |#=|→|#if| |ls_13| |is|→|Cons| |(|h_13|,| |t_15|)| |#then|→|1| |+| |(|length|(|t_15|)|)|←|↵|Nil| |#then|→|0|←|←|←|↵|#fun| |mappend|(|xs_8|,| |ys_8|)| |#=|→|#if| |xs_8| |is|→|Cons| |(|h_14|,| |t_16|)| |#then|→|Cons| |(|h_14|,| |mappend|(|t_16|,| |ys_8|)|)|←|↵|Nil| |#then|→|ys_8|←|←|←|↵|#fun| |sum|(|ls_14|)| |#=|→|sumAux|(|ls_14|,| |0|)|←|↵|#fun| |sumAux|(|ls_15|,| |a_4|)| |#=|→|#if| |ls_15| |is|→|Nil| |#then|→|a_4|←|↵|Cons| |(|h_15|,| |t_17|)| |#then|→|sumAux|(|t_17|,| |a_4| |+| |h_15|)|←|←|←|↵|#fun| |atIndex|(|n_2|,| |ls_16|)| |#=|→|#if| |n_2| |<| |0| |#then|→|error|←|↵|#else|→|#if| |ls_16| |is|→|Cons| |(|h_16|,| |t_18|)| |#then|→|#if| |n_2| |==| |0| |#then|→|h_16|←|↵|#else|→|(|atIndex|(|n_2| |-| |1|,| |t_18|)|)|←|←|↵|Nil| |#then|→|error|←|←|←|←|↵|#fun| |concat|(|lss|)| |#=|→|#if| |lss| |is|→|Cons| |(|h_18|,| |t_20|)| |#then|→|mappend|(|h_18|,| |concat|(|t_20|)|)|←|↵|Nil| |#then|→|Nil|←|←|←|↵|#fun| |reverse|(|ls_18|)| |#=|→|reverse_helper|(|ls_18|,| |Nil|)|←|↵|#fun| |reverse_helper|(|ls_19|,| |a_5|)| |#=|→|#if| |ls_19| |is|→|Cons| |(|h_19|,| |t_21|)| |#then|→|reverse_helper|(|t_21|,| |Cons| |(|h_19|,| |a_5|)|)|←|↵|Nil| |#then|→|a_5|←|←|←|↵|#fun| |listcomp_fun1|(|ms|,| |listcomp_fun_para|)| |#=|→|#if| |listcomp_fun_para| |is|→|Cons|(|listcomp_fun_ls_h|,| |listcomp_fun_ls_t|)| |#then|→|listcomp_fun2|(|ms|,| |listcomp_fun_ls_h|,| |listcomp_fun_ls_t|,| |ms|)|←|↵|Nil| |#then|→|Nil|←|←|←|↵|#fun| |listcomp_fun2|(|ms|,| |listcomp_fun_ls_h_out|,| |listcomp_fun_ls_t_out|,| |listcomp_fun_para|)| |#=|→|#if| |listcomp_fun_para| |is|→|Cons|(|listcomp_fun_ls_h|,| |listcomp_fun_ls_t|)| |#then|→|Cons|(|Tuple2| |(|listcomp_fun_ls_h_out|,| |listcomp_fun_ls_h|)|,| |listcomp_fun2|(|ms|,| |listcomp_fun_ls_h_out|,| |listcomp_fun_ls_t_out|,| |listcomp_fun_ls_t|)|)|←|↵|Nil| |#then|→|listcomp_fun1|(|ms|,| |listcomp_fun_ls_t_out|)|←|←|←|↵|#fun| |test|(|test_arg1|)| |#=|→|#let| |ns| |#=| |z_enumFromTo|(|const5000|(||)|,| |z_add|(|const5000|(||)|,| |test_arg1|)|)|↵|#let| |ms| |#=| |z_enumFromTo|(|const10000|(||)|,| |z_add|(|const10000|(||)|,| |test_arg1|)|)|↵|#let| |tripls| |#=| |map|(|f1|,| |listcomp_fun1|(|ms|,| |ns|)|)|↵|#let| |rs| |#=| |map|(|f2|,| |tripls|)|↵|max'|(|rs|)|←|↵|#fun| |const10000|(||)| |#=|→|z_of_int|(|10000|)|←|↵|#fun| |f1|(|f1_arg1|)| |#=|→|#if| |f1_arg1| |is|→|Tuple2| |(|f1_Tuple2_0|,| |f1_Tuple2_1|)| |#then|→|Tuple3| |(|f1_Tuple2_0|,| |f1_Tuple2_1|,| |gcdE|(|f1_Tuple2_0|,| |f1_Tuple2_1|)|)|←|←|←|↵|#fun| |quotRem|(|quotRem_arg1|,| |quotRem_arg2|)| |#=|→|Tuple2| |(|z_div|(|quotRem_arg1|,| |quotRem_arg2|)|,| |z_mod|(|quotRem_arg1|,| |quotRem_arg2|)|)|←|↵|#fun| |max'|(|max'_arg1|)| |#=|→|#if| |max'_arg1| |is|→|Cons| |(|max'_Cons_0|,| |max'_Cons_1|)| |#then|→|#if| |max'_Cons_1| |is|→|Nil| |#then|→|max'_Cons_0|←|↵|Cons| |(|max'_Cons_0_1|,| |max'_Cons_1_1|)| |#then|→|#if| |z_lt|(|max'_Cons_0|,| |max'_Cons_0_1|)| |#then|→|max'|(|Cons| |(|max'_Cons_0_1|,| |max'_Cons_1_1|)|)|←|↵|#else|→|(|max'|(|Cons| |(|max'_Cons_0|,| |max'_Cons_1_1|)|)|)|←|←|←|←|←|←|↵|#fun| |g|(|g_arg1|,| |g_arg2|)| |#=|→|#if| |g_arg1| |is|→|Tuple3| |(|g_Tuple3_0|,| |g_Tuple3_1|,| |g_Tuple3_2|)| |#then|→|#if| |g_arg2| |is|→|Tuple3| |(|g_Tuple3_0_1|,| |g_Tuple3_1_1|,| |g_Tuple3_2_1|)| |#then|→|#if| |z_equal|(|g_Tuple3_2_1|,| |const0|(||)|)| |#then|→|Tuple3| |(|g_Tuple3_2|,| |g_Tuple3_0|,| |g_Tuple3_1|)|←|↵|#else|→|#let| |matchIdent| |#=| |quotRem|(|g_Tuple3_2|,| |g_Tuple3_2_1|)|↵|#if| |matchIdent| |is|→|Tuple2| |(|g_Tuple2_0|,| |g_Tuple2_1|)| |#then|→|g|(|Tuple3| |(|g_Tuple3_0_1|,| |g_Tuple3_1_1|,| |g_Tuple3_2_1|)|,| |Tuple3| |(|z_sub|(|g_Tuple3_0|,| |z_mul|(|g_Tuple2_0|,| |g_Tuple3_0_1|)|)|,| |z_sub|(|g_Tuple3_1|,| |z_mul|(|g_Tuple2_0|,| |g_Tuple3_1_1|)|)|,| |g_Tuple2_1|)|)|←|←|←|←|←|←|←|←|↵|#fun| |abs|(|abs_arg1|)| |#=|→|#if| |z_lt|(|abs_arg1|,| |const0|(||)|)| |#then|→|z_sub|(|const0|(||)|,| |abs_arg1|)|←|↵|#else|→|abs_arg1|←|←|↵|#fun| |f2|(|f2_arg1|)| |#=|→|#if| |f2_arg1| |is|→|Tuple3| |(|f2_Tuple3_0|,| |f2_Tuple3_1|,| |f2_Tuple3_2|)| |#then|→|#if| |f2_Tuple3_2| |is|→|Tuple3| |(|f2_Tuple3_0_1|,| |f2_Tuple3_1_1|,| |f2_Tuple3_2_1|)| |#then|→|abs|(|z_add|(|z_add|(|f2_Tuple3_0_1|,| |f2_Tuple3_1_1|)|,| |f2_Tuple3_2_1|)|)|←|←|←|←|←|↵|#fun| |const0|(||)| |#=|→|z_of_int|(|0|)|←|↵|#fun| |gcdE|(|gcdE_arg1|,| |gcdE_arg2|)| |#=|→|#if| |z_equal|(|gcdE_arg1|,| |const0|(||)|)| |#then|→|Tuple3| |(|gcdE_arg2|,| |const0|(||)|,| |const1|(||)|)|←|↵|#else|→|(|g|(|Tuple3| |(|const1|(||)|,| |const0|(||)|,| |gcdE_arg1|)|,| |Tuple3| |(|const0|(||)|,| |const1|(||)|,| |gcdE_arg2|)|)|)|←|←|↵|#fun| |const1|(||)| |#=|→|z_of_int|(|1|)|←|↵|#fun| |const5000|(||)| |#=|→|z_of_int|(|5000|)|←|↵|#fun| |testGcd_nofib|(|testGcd_nofib_arg1|)| |#=|→|test|(|testGcd_nofib_arg1|)|←|↵|#fun| |z_enumFromTo|(|z_enumFromTo_arg1|,| |z_enumFromTo_arg2|)| |#=|→|#if| |z_leq|(|z_enumFromTo_arg1|,| |z_enumFromTo_arg2|)| |#then|→|Cons| |(|z_enumFromTo_arg1|,| |z_enumFromTo|(|z_add|(|z_enumFromTo_arg1|,| |const1|(||)|)|,| |z_enumFromTo_arg2|)|)|←|↵|#else|→|(|Nil|)|←|←|↵|testGcd_nofib|(|z_of_int|(|400|)|)|\n//│ Parsed: {fun error = () => builtin(\"error\",); fun z_of_int = (x,) => builtin(\"z_of_int\", x,); fun z_to_int = (x,) => builtin(\"z_to_int\", x,); fun z_add = (x, y,) => builtin(\"z_add\", x, y,); fun z_sub = (x, y,) => builtin(\"z_sub\", x, y,); fun z_div = (x, y,) => builtin(\"z_div\", x, y,); fun z_mul = (x, y,) => builtin(\"z_mul\", x, y,); fun z_mod = (x, y,) => builtin(\"z_mod\", x, y,); fun z_lt = (x, y,) => builtin(\"z_lt\", x, y,); fun z_leq = (x, y,) => builtin(\"z_leq\", x, y,); fun z_equal = (x, y,) => builtin(\"z_equal\", x, y,); fun z_gt = (x, y,) => builtin(\"z_gt\", x, y,); fun z_geq = (x, y,) => builtin(\"z_geq\", x, y,); fun println = (x,) => builtin(\"println\", x,); fun print = (x,) => builtin(\"print\", x,); fun debug = (x,) => builtin(\"debug\", x,); fun map = (f, ls,) => {if ls is ‹(Cons(h, t,)) then {Cons(f(h,), map(f, t,),)}; (Nil) then {Nil}›}; fun filter = (f_2, ls_2,) => {if ls_2 is ‹(Cons(h_2, t_2,)) then {if (f_2(h_2,)) then {Cons(h_2, filter(f_2, t_2,),)} else {'(' filter(f_2, t_2,) ')'}}; (Nil) then {Nil}›}; fun foldl = (f_4, i, ls_4,) => {if ls_4 is ‹(Cons(h_4, t_4,)) then {foldl(f_4, f_4(i, h_4,), t_4,)}; (Nil) then {i}›}; fun foldr = (f_5, i_1, ls_5,) => {if ls_5 is ‹(Cons(h_5, t_5,)) then {f_5(h_5, foldr(f_5, i_1, t_5,),)}; (Nil) then {i_1}›}; fun zip = (xs, ys,) => {if xs is ‹(Cons(hx, tx,)) then {if ys is ‹(Cons(hy, ty,)) then {Cons(Tuple2(hx, hy,), zip(tx, ty,),)}; (Nil) then {Nil}›}; (Nil) then {Nil}›}; fun zipWith = (f_7, xs_4, ys_4,) => {if xs_4 is ‹(Cons(hx_4, tx_4,)) then {if ys_4 is ‹(Cons(hy_4, ty_4,)) then {Cons(f_7(hx_4, hy_4,), zipWith(f_7, tx_4, ty_4,),)}; (Nil) then {Nil}›}; (Nil) then {Nil}›}; fun head = (ls_7,) => {if ls_7 is ‹(Cons(h_7, t_7,)) then {h_7}; (Nil) then {error}›}; fun tail = (ls_9,) => {if ls_9 is ‹(Cons(h_9, t_9,)) then {t_9}; (Nil) then {error}›}; fun enumFromTo = (a, b,) => {if (<=(a, b,)) then {Cons(a, enumFromTo(+(a, 1,), b,),)} else {'(' Nil ')'}}; fun enumFromThenTo = (a_1, t_11, b_1,) => {if (<=(a_1, b_1,)) then {Cons(a_1, enumFromThenTo(t_11, -(*(2, t_11,), a_1,), b_1,),)} else {'(' Nil ')'}}; fun take = (n, ls_11,) => {if (>(n, 0,)) then {if ls_11 is ‹(Cons(h_11, t_13,)) then {Cons(h_11, take(-(n, 1,), t_13,),)}; (Nil) then {Nil}›} else {'(' Nil ')'}}; fun length = (ls_13,) => {if ls_13 is ‹(Cons(h_13, t_15,)) then {+(1, '(' length(t_15,) ')',)}; (Nil) then {0}›}; fun mappend = (xs_8, ys_8,) => {if xs_8 is ‹(Cons(h_14, t_16,)) then {Cons(h_14, mappend(t_16, ys_8,),)}; (Nil) then {ys_8}›}; fun sum = (ls_14,) => {sumAux(ls_14, 0,)}; fun sumAux = (ls_15, a_4,) => {if ls_15 is ‹(Nil) then {a_4}; (Cons(h_15, t_17,)) then {sumAux(t_17, +(a_4, h_15,),)}›}; fun atIndex = (n_2, ls_16,) => {if (<(n_2, 0,)) then {error} else {if ls_16 is ‹(Cons(h_16, t_18,)) then {if (==(n_2, 0,)) then {h_16} else {'(' atIndex(-(n_2, 1,), t_18,) ')'}}; (Nil) then {error}›}}; fun concat = (lss,) => {if lss is ‹(Cons(h_18, t_20,)) then {mappend(h_18, concat(t_20,),)}; (Nil) then {Nil}›}; fun reverse = (ls_18,) => {reverse_helper(ls_18, Nil,)}; fun reverse_helper = (ls_19, a_5,) => {if ls_19 is ‹(Cons(h_19, t_21,)) then {reverse_helper(t_21, Cons(h_19, a_5,),)}; (Nil) then {a_5}›}; fun listcomp_fun1 = (ms, listcomp_fun_para,) => {if listcomp_fun_para is ‹(Cons(listcomp_fun_ls_h, listcomp_fun_ls_t,)) then {listcomp_fun2(ms, listcomp_fun_ls_h, listcomp_fun_ls_t, ms,)}; (Nil) then {Nil}›}; fun listcomp_fun2 = (ms, listcomp_fun_ls_h_out, listcomp_fun_ls_t_out, listcomp_fun_para,) => {if listcomp_fun_para is ‹(Cons(listcomp_fun_ls_h, listcomp_fun_ls_t,)) then {Cons(Tuple2(listcomp_fun_ls_h_out, listcomp_fun_ls_h,), listcomp_fun2(ms, listcomp_fun_ls_h_out, listcomp_fun_ls_t_out, listcomp_fun_ls_t,),)}; (Nil) then {listcomp_fun1(ms, listcomp_fun_ls_t_out,)}›}; fun test = (test_arg1,) => {let ns = z_enumFromTo(const5000(), z_add(const5000(), test_arg1,),); let ms = z_enumFromTo(const10000(), z_add(const10000(), test_arg1,),); let tripls = map(f1, listcomp_fun1(ms, ns,),); let rs = map(f2, tripls,); max'(rs,)}; fun const10000 = () => {z_of_int(10000,)}; fun f1 = (f1_arg1,) => {if f1_arg1 is ‹(Tuple2(f1_Tuple2_0, f1_Tuple2_1,)) then {Tuple3(f1_Tuple2_0, f1_Tuple2_1, gcdE(f1_Tuple2_0, f1_Tuple2_1,),)}›}; fun quotRem = (quotRem_arg1, quotRem_arg2,) => {Tuple2(z_div(quotRem_arg1, quotRem_arg2,), z_mod(quotRem_arg1, quotRem_arg2,),)}; fun max' = (max'_arg1,) => {if max'_arg1 is ‹(Cons(max'_Cons_0, max'_Cons_1,)) then {if max'_Cons_1 is ‹(Nil) then {max'_Cons_0}; (Cons(max'_Cons_0_1, max'_Cons_1_1,)) then {if (z_lt(max'_Cons_0, max'_Cons_0_1,)) then {max'(Cons(max'_Cons_0_1, max'_Cons_1_1,),)} else {'(' max'(Cons(max'_Cons_0, max'_Cons_1_1,),) ')'}}›}›}; fun g = (g_arg1, g_arg2,) => {if g_arg1 is ‹(Tuple3(g_Tuple3_0, g_Tuple3_1, g_Tuple3_2,)) then {if g_arg2 is ‹(Tuple3(g_Tuple3_0_1, g_Tuple3_1_1, g_Tuple3_2_1,)) then {if (z_equal(g_Tuple3_2_1, const0(),)) then {Tuple3(g_Tuple3_2, g_Tuple3_0, g_Tuple3_1,)} else {let matchIdent = quotRem(g_Tuple3_2, g_Tuple3_2_1,); if matchIdent is ‹(Tuple2(g_Tuple2_0, g_Tuple2_1,)) then {g(Tuple3(g_Tuple3_0_1, g_Tuple3_1_1, g_Tuple3_2_1,), Tuple3(z_sub(g_Tuple3_0, z_mul(g_Tuple2_0, g_Tuple3_0_1,),), z_sub(g_Tuple3_1, z_mul(g_Tuple2_0, g_Tuple3_1_1,),), g_Tuple2_1,),)}›}}›}›}; fun abs = (abs_arg1,) => {if (z_lt(abs_arg1, const0(),)) then {z_sub(const0(), abs_arg1,)} else {abs_arg1}}; fun f2 = (f2_arg1,) => {if f2_arg1 is ‹(Tuple3(f2_Tuple3_0, f2_Tuple3_1, f2_Tuple3_2,)) then {if f2_Tuple3_2 is ‹(Tuple3(f2_Tuple3_0_1, f2_Tuple3_1_1, f2_Tuple3_2_1,)) then {abs(z_add(z_add(f2_Tuple3_0_1, f2_Tuple3_1_1,), f2_Tuple3_2_1,),)}›}›}; fun const0 = () => {z_of_int(0,)}; fun gcdE = (gcdE_arg1, gcdE_arg2,) => {if (z_equal(gcdE_arg1, const0(),)) then {Tuple3(gcdE_arg2, const0(), const1(),)} else {'(' g(Tuple3(const1(), const0(), gcdE_arg1,), Tuple3(const0(), const1(), gcdE_arg2,),) ')'}}; fun const1 = () => {z_of_int(1,)}; fun const5000 = () => {z_of_int(5000,)}; fun testGcd_nofib = (testGcd_nofib_arg1,) => {test(testGcd_nofib_arg1,)}; fun z_enumFromTo = (z_enumFromTo_arg1, z_enumFromTo_arg2,) => {if (z_leq(z_enumFromTo_arg1, z_enumFromTo_arg2,)) then {Cons(z_enumFromTo_arg1, z_enumFromTo(z_add(z_enumFromTo_arg1, const1(),), z_enumFromTo_arg2,),)} else {'(' Nil ')'}}; testGcd_nofib(z_of_int(400,),)}\n//│ \n//│ \n//│ IR:\n//│ Program:\n//│   class Lambda$0() extends Callable {\n//│     def apply0() =\n//│       let* (x$270) = error() in -- #1354\n//│       x$270 -- #1353\n//│   }\n//│   class Lambda$1() extends Callable {\n//│     def apply0() =\n//│       let* (x$271) = error() in -- #1357\n//│       x$271 -- #1356\n//│   }\n//│   class Lambda$2() extends Callable {\n//│     def apply0() =\n//│       let* (x$272) = error() in -- #1360\n//│       x$272 -- #1359\n//│   }\n//│   class Lambda$3() extends Callable {\n//│     def apply0() =\n//│       let* (x$273) = error() in -- #1363\n//│       x$273 -- #1362\n//│   }\n//│   class Lambda$4() extends Callable {\n//│     def apply1(x$274) =\n//│       let* (x$275) = f1(x$274) in -- #1368\n//│       x$275 -- #1367\n//│   }\n//│   class Lambda$5() extends Callable {\n//│     def apply1(x$276) =\n//│       let* (x$277) = f2(x$276) in -- #1373\n//│       x$277 -- #1372\n//│   }\n//│   def error() =\n//│     let x$2 = Callable.apply1(builtin,error) in -- #14\n//│     x$2 -- #13\n//│   def z_of_int(x$3) =\n//│     let x$4 = Callable.apply2(builtin,z_of_int,x$3) in -- #22\n//│     x$4 -- #21\n//│   def z_to_int(x$5) =\n//│     let x$6 = Callable.apply2(builtin,z_to_int,x$5) in -- #30\n//│     x$6 -- #29\n//│   def z_add(x$7,y$0) =\n//│     let x$8 = Callable.apply3(builtin,z_add,x$7,y$0) in -- #40\n//│     x$8 -- #39\n//│   def z_sub(x$9,y$1) =\n//│     let x$10 = Callable.apply3(builtin,z_sub,x$9,y$1) in -- #50\n//│     x$10 -- #49\n//│   def z_div(x$11,y$2) =\n//│     let x$12 = Callable.apply3(builtin,z_div,x$11,y$2) in -- #60\n//│     x$12 -- #59\n//│   def z_mul(x$13,y$3) =\n//│     let x$14 = Callable.apply3(builtin,z_mul,x$13,y$3) in -- #70\n//│     x$14 -- #69\n//│   def z_mod(x$15,y$4) =\n//│     let x$16 = Callable.apply3(builtin,z_mod,x$15,y$4) in -- #80\n//│     x$16 -- #79\n//│   def z_lt(x$17,y$5) =\n//│     let x$18 = Callable.apply3(builtin,z_lt,x$17,y$5) in -- #90\n//│     x$18 -- #89\n//│   def z_leq(x$19,y$6) =\n//│     let x$20 = Callable.apply3(builtin,z_leq,x$19,y$6) in -- #100\n//│     x$20 -- #99\n//│   def z_equal(x$21,y$7) =\n//│     let x$22 = Callable.apply3(builtin,z_equal,x$21,y$7) in -- #110\n//│     x$22 -- #109\n//│   def z_gt(x$23,y$8) =\n//│     let x$24 = Callable.apply3(builtin,z_gt,x$23,y$8) in -- #120\n//│     x$24 -- #119\n//│   def z_geq(x$25,y$9) =\n//│     let x$26 = Callable.apply3(builtin,z_geq,x$25,y$9) in -- #130\n//│     x$26 -- #129\n//│   def println(x$27) =\n//│     let x$28 = Callable.apply2(builtin,println,x$27) in -- #138\n//│     x$28 -- #137\n//│   def print(x$29) =\n//│     let x$30 = Callable.apply2(builtin,print,x$29) in -- #146\n//│     x$30 -- #145\n//│   def debug(x$31) =\n//│     let x$32 = Callable.apply2(builtin,debug,x$31) in -- #154\n//│     x$32 -- #153\n//│   def map(f$0,ls$0) =\n//│     case ls$0 of -- #189\n//│       Cons =>\n//│         let x$34 = Cons.t(ls$0) in -- #185\n//│         let x$35 = Cons.h(ls$0) in -- #184\n//│         let x$36 = Callable.apply1(f$0,x$35) in -- #183\n//│         let* (x$37) = map(f$0,x$34) in -- #182\n//│         let x$38 = Cons(x$36,x$37) in -- #181\n//│         jump j$0(x$38) -- #180\n//│       Nil =>\n//│         let x$39 = Nil() in -- #188\n//│         jump j$0(x$39) -- #187\n//│   def j$0(x$33) =\n//│     x$33 -- #156\n//│   def filter(f_2$0,ls_2$0) =\n//│     case ls_2$0 of -- #236\n//│       Cons =>\n//│         let x$41 = Cons.t(ls_2$0) in -- #232\n//│         let x$42 = Cons.h(ls_2$0) in -- #231\n//│         let x$43 = Callable.apply1(f_2$0,x$42) in -- #230\n//│         if x$43 -- #229\n//│           true =>\n//│             let* (x$45) = filter(f_2$0,x$41) in -- #220\n//│             let x$46 = Cons(x$42,x$45) in -- #219\n//│             jump j$2(x$46) -- #218\n//│           false =>\n//│             let* (x$47) = filter(f_2$0,x$41) in -- #228\n//│             jump j$2(x$47) -- #227\n//│       Nil =>\n//│         let x$48 = Nil() in -- #235\n//│         jump j$1(x$48) -- #234\n//│   def j$1(x$40) =\n//│     x$40 -- #191\n//│   def j$2(x$44) =\n//│     jump j$1(x$44) -- #206\n//│   def foldl(f_4$0,i$0,ls_4$0) =\n//│     case ls_4$0 of -- #268\n//│       Cons =>\n//│         let x$50 = Cons.t(ls_4$0) in -- #265\n//│         let x$51 = Cons.h(ls_4$0) in -- #264\n//│         let x$52 = Callable.apply2(f_4$0,i$0,x$51) in -- #263\n//│         let* (x$53) = foldl(f_4$0,x$52,x$50) in -- #262\n//│         jump j$3(x$53) -- #261\n//│       Nil =>\n//│         jump j$3(i$0) -- #267\n//│   def j$3(x$49) =\n//│     x$49 -- #238\n//│   def foldr(f_5$0,i_1$0,ls_5$0) =\n//│     case ls_5$0 of -- #300\n//│       Cons =>\n//│         let x$55 = Cons.t(ls_5$0) in -- #297\n//│         let x$56 = Cons.h(ls_5$0) in -- #296\n//│         let* (x$57) = foldr(f_5$0,i_1$0,x$55) in -- #295\n//│         let x$58 = Callable.apply2(f_5$0,x$56,x$57) in -- #294\n//│         jump j$4(x$58) -- #293\n//│       Nil =>\n//│         jump j$4(i_1$0) -- #299\n//│   def j$4(x$54) =\n//│     x$54 -- #270\n//│   def zip(xs$0,ys$0) =\n//│     case xs$0 of -- #353\n//│       Cons =>\n//│         let x$60 = Cons.t(xs$0) in -- #349\n//│         let x$61 = Cons.h(xs$0) in -- #348\n//│         case ys$0 of -- #347\n//│           Cons =>\n//│             let x$63 = Cons.t(ys$0) in -- #343\n//│             let x$64 = Cons.h(ys$0) in -- #342\n//│             let x$65 = Tuple2(x$61,x$64) in -- #341\n//│             let* (x$66) = zip(x$60,x$63) in -- #340\n//│             let x$67 = Cons(x$65,x$66) in -- #339\n//│             jump j$6(x$67) -- #338\n//│           Nil =>\n//│             let x$68 = Nil() in -- #346\n//│             jump j$6(x$68) -- #345\n//│       Nil =>\n//│         let x$69 = Nil() in -- #352\n//│         jump j$5(x$69) -- #351\n//│   def j$5(x$59) =\n//│     x$59 -- #302\n//│   def j$6(x$62) =\n//│     jump j$5(x$62) -- #313\n//│   def zipWith(f_7$0,xs_4$0,ys_4$0) =\n//│     case xs_4$0 of -- #409\n//│       Cons =>\n//│         let x$71 = Cons.t(xs_4$0) in -- #405\n//│         let x$72 = Cons.h(xs_4$0) in -- #404\n//│         case ys_4$0 of -- #403\n//│           Cons =>\n//│             let x$74 = Cons.t(ys_4$0) in -- #399\n//│             let x$75 = Cons.h(ys_4$0) in -- #398\n//│             let x$76 = Callable.apply2(f_7$0,x$72,x$75) in -- #397\n//│             let* (x$77) = zipWith(f_7$0,x$71,x$74) in -- #396\n//│             let x$78 = Cons(x$76,x$77) in -- #395\n//│             jump j$8(x$78) -- #394\n//│           Nil =>\n//│             let x$79 = Nil() in -- #402\n//│             jump j$8(x$79) -- #401\n//│       Nil =>\n//│         let x$80 = Nil() in -- #408\n//│         jump j$7(x$80) -- #407\n//│   def j$7(x$70) =\n//│     x$70 -- #355\n//│   def j$8(x$73) =\n//│     jump j$7(x$73) -- #366\n//│   def head(ls_7$0) =\n//│     case ls_7$0 of -- #427\n//│       Cons =>\n//│         let x$82 = Cons.t(ls_7$0) in -- #423\n//│         let x$83 = Cons.h(ls_7$0) in -- #422\n//│         jump j$9(x$83) -- #421\n//│       Nil =>\n//│         let x$85 = Lambda$0() in -- #426\n//│         jump j$9(x$85) -- #425\n//│   def j$9(x$81) =\n//│     x$81 -- #411\n//│   def tail(ls_9$0) =\n//│     case ls_9$0 of -- #445\n//│       Cons =>\n//│         let x$87 = Cons.t(ls_9$0) in -- #441\n//│         let x$88 = Cons.h(ls_9$0) in -- #440\n//│         jump j$10(x$87) -- #439\n//│       Nil =>\n//│         let x$90 = Lambda$1() in -- #444\n//│         jump j$10(x$90) -- #443\n//│   def j$10(x$86) =\n//│     x$86 -- #429\n//│   def enumFromTo(a$0,b$0) =\n//│     let x$91 = <=(a$0,b$0) in -- #477\n//│     if x$91 -- #476\n//│       true =>\n//│         let x$93 = +(a$0,1) in -- #472\n//│         let* (x$94) = enumFromTo(x$93,b$0) in -- #471\n//│         let x$95 = Cons(a$0,x$94) in -- #470\n//│         jump j$11(x$95) -- #469\n//│       false =>\n//│         let x$96 = Nil() in -- #475\n//│         jump j$11(x$96) -- #474\n//│   def j$11(x$92) =\n//│     x$92 -- #452\n//│   def enumFromThenTo(a_1$0,t_11$0,b_1$0) =\n//│     let x$97 = <=(a_1$0,b_1$0) in -- #517\n//│     if x$97 -- #516\n//│       true =>\n//│         let x$99 = *(2,t_11$0) in -- #512\n//│         let x$100 = -(x$99,a_1$0) in -- #511\n//│         let* (x$101) = enumFromThenTo(t_11$0,x$100,b_1$0) in -- #510\n//│         let x$102 = Cons(a_1$0,x$101) in -- #509\n//│         jump j$12(x$102) -- #508\n//│       false =>\n//│         let x$103 = Nil() in -- #515\n//│         jump j$12(x$103) -- #514\n//│   def j$12(x$98) =\n//│     x$98 -- #484\n//│   def take(n$0,ls_11$0) =\n//│     let x$104 = >(n$0,0) in -- #566\n//│     if x$104 -- #565\n//│       true =>\n//│         case ls_11$0 of -- #561\n//│           Cons =>\n//│             let x$107 = Cons.t(ls_11$0) in -- #557\n//│             let x$108 = Cons.h(ls_11$0) in -- #556\n//│             let x$109 = -(n$0,1) in -- #555\n//│             let* (x$110) = take(x$109,x$107) in -- #554\n//│             let x$111 = Cons(x$108,x$110) in -- #553\n//│             jump j$14(x$111) -- #552\n//│           Nil =>\n//│             let x$112 = Nil() in -- #560\n//│             jump j$14(x$112) -- #559\n//│       false =>\n//│         let x$113 = Nil() in -- #564\n//│         jump j$13(x$113) -- #563\n//│   def j$13(x$105) =\n//│     x$105 -- #524\n//│   def j$14(x$106) =\n//│     jump j$13(x$106) -- #527\n//│   def length(ls_13$0) =\n//│     case ls_13$0 of -- #593\n//│       Cons =>\n//│         let x$115 = Cons.t(ls_13$0) in -- #590\n//│         let x$116 = Cons.h(ls_13$0) in -- #589\n//│         let* (x$117) = length(x$115) in -- #588\n//│         let x$118 = +(1,x$117) in -- #587\n//│         jump j$15(x$118) -- #586\n//│       Nil =>\n//│         jump j$15(0) -- #592\n//│   def j$15(x$114) =\n//│     x$114 -- #568\n//│   def mappend(xs_8$0,ys_8$0) =\n//│     case xs_8$0 of -- #622\n//│       Cons =>\n//│         let x$120 = Cons.t(xs_8$0) in -- #619\n//│         let x$121 = Cons.h(xs_8$0) in -- #618\n//│         let* (x$122) = mappend(x$120,ys_8$0) in -- #617\n//│         let x$123 = Cons(x$121,x$122) in -- #616\n//│         jump j$16(x$123) -- #615\n//│       Nil =>\n//│         jump j$16(ys_8$0) -- #621\n//│   def j$16(x$119) =\n//│     x$119 -- #595\n//│   def sum(ls_14$0) =\n//│     let* (x$124) = sumAux(ls_14$0,0) in -- #629\n//│     x$124 -- #628\n//│   def sumAux(ls_15$0,a_4$0) =\n//│     case ls_15$0 of -- #658\n//│       Nil =>\n//│         jump j$17(a_4$0) -- #633\n//│       Cons =>\n//│         let x$126 = Cons.t(ls_15$0) in -- #657\n//│         let x$127 = Cons.h(ls_15$0) in -- #656\n//│         let x$128 = +(a_4$0,x$127) in -- #655\n//│         let* (x$129) = sumAux(x$126,x$128) in -- #654\n//│         jump j$17(x$129) -- #653\n//│   def j$17(x$125) =\n//│     x$125 -- #631\n//│   def atIndex(n_2$0,ls_16$0) =\n//│     let x$130 = <(n_2$0,0) in -- #713\n//│     if x$130 -- #712\n//│       true =>\n//│         let x$133 = Lambda$2() in -- #668\n//│         jump j$18(x$133) -- #667\n//│       false =>\n//│         case ls_16$0 of -- #711\n//│           Cons =>\n//│             let x$135 = Cons.t(ls_16$0) in -- #707\n//│             let x$136 = Cons.h(ls_16$0) in -- #706\n//│             let x$137 = ==(n_2$0,0) in -- #705\n//│             if x$137 -- #704\n//│               true =>\n//│                 jump j$20(x$136) -- #689\n//│               false =>\n//│                 let x$139 = -(n_2$0,1) in -- #703\n//│                 let* (x$140) = atIndex(x$139,x$135) in -- #702\n//│                 jump j$20(x$140) -- #701\n//│           Nil =>\n//│             let x$142 = Lambda$3() in -- #710\n//│             jump j$19(x$142) -- #709\n//│   def j$18(x$131) =\n//│     x$131 -- #665\n//│   def j$19(x$134) =\n//│     jump j$18(x$134) -- #671\n//│   def j$20(x$138) =\n//│     jump j$19(x$138) -- #687\n//│   def concat(lss$0) =\n//│     case lss$0 of -- #741\n//│       Cons =>\n//│         let x$144 = Cons.t(lss$0) in -- #737\n//│         let x$145 = Cons.h(lss$0) in -- #736\n//│         let* (x$146) = concat(x$144) in -- #735\n//│         let* (x$147) = mappend(x$145,x$146) in -- #734\n//│         jump j$21(x$147) -- #733\n//│       Nil =>\n//│         let x$148 = Nil() in -- #740\n//│         jump j$21(x$148) -- #739\n//│   def j$21(x$143) =\n//│     x$143 -- #715\n//│   def reverse(ls_18$0) =\n//│     let x$149 = Nil() in -- #749\n//│     let* (x$150) = reverse_helper(ls_18$0,x$149) in -- #748\n//│     x$150 -- #747\n//│   def reverse_helper(ls_19$0,a_5$0) =\n//│     case ls_19$0 of -- #778\n//│       Cons =>\n//│         let x$152 = Cons.t(ls_19$0) in -- #775\n//│         let x$153 = Cons.h(ls_19$0) in -- #774\n//│         let x$154 = Cons(x$153,a_5$0) in -- #773\n//│         let* (x$155) = reverse_helper(x$152,x$154) in -- #772\n//│         jump j$22(x$155) -- #771\n//│       Nil =>\n//│         jump j$22(a_5$0) -- #777\n//│   def j$22(x$151) =\n//│     x$151 -- #751\n//│   def listcomp_fun1(ms$0,listcomp_fun_para$0) =\n//│     case listcomp_fun_para$0 of -- #806\n//│       Cons =>\n//│         let x$157 = Cons.t(listcomp_fun_para$0) in -- #802\n//│         let x$158 = Cons.h(listcomp_fun_para$0) in -- #801\n//│         let* (x$159) = listcomp_fun2(ms$0,x$158,x$157,ms$0) in -- #800\n//│         jump j$23(x$159) -- #799\n//│       Nil =>\n//│         let x$160 = Nil() in -- #805\n//│         jump j$23(x$160) -- #804\n//│   def j$23(x$156) =\n//│     x$156 -- #780\n//│   def listcomp_fun2(ms$1,listcomp_fun_ls_h_out$0,listcomp_fun_ls_t_out$0,listcomp_fun_para$1) =\n//│     case listcomp_fun_para$1 of -- #851\n//│       Cons =>\n//│         let x$162 = Cons.t(listcomp_fun_para$1) in -- #842\n//│         let x$163 = Cons.h(listcomp_fun_para$1) in -- #841\n//│         let x$164 = Tuple2(listcomp_fun_ls_h_out$0,x$163) in -- #840\n//│         let* (x$165) = listcomp_fun2(ms$1,listcomp_fun_ls_h_out$0,listcomp_fun_ls_t_out$0,x$162) in -- #839\n//│         let x$166 = Cons(x$164,x$165) in -- #838\n//│         jump j$24(x$166) -- #837\n//│       Nil =>\n//│         let* (x$167) = listcomp_fun1(ms$1,listcomp_fun_ls_t_out$0) in -- #850\n//│         jump j$24(x$167) -- #849\n//│   def j$24(x$161) =\n//│     x$161 -- #808\n//│   def test(test_arg1$0) =\n//│     let* (x$168) = const5000() in -- #912\n//│     let* (x$169) = const5000() in -- #911\n//│     let* (x$170) = z_add(x$169,test_arg1$0) in -- #910\n//│     let* (x$171) = z_enumFromTo(x$168,x$170) in -- #909\n//│     let* (x$172) = const10000() in -- #908\n//│     let* (x$173) = const10000() in -- #907\n//│     let* (x$174) = z_add(x$173,test_arg1$0) in -- #906\n//│     let* (x$175) = z_enumFromTo(x$172,x$174) in -- #905\n//│     let x$178 = Lambda$4() in -- #904\n//│     let* (x$179) = listcomp_fun1(x$175,x$171) in -- #903\n//│     let* (x$180) = map(x$178,x$179) in -- #902\n//│     let x$183 = Lambda$5() in -- #901\n//│     let* (x$184) = map(x$183,x$180) in -- #900\n//│     let* (x$185) = max'(x$184) in -- #899\n//│     x$185 -- #898\n//│   def const10000() =\n//│     let* (x$186) = z_of_int(10000) in -- #917\n//│     x$186 -- #916\n//│   def f1(f1_arg1$0) =\n//│     case f1_arg1$0 of -- #946\n//│       Tuple2 =>\n//│         let x$188 = Tuple2.y(f1_arg1$0) in -- #945\n//│         let x$189 = Tuple2.x(f1_arg1$0) in -- #944\n//│         let* (x$190) = gcdE(x$189,x$188) in -- #943\n//│         let x$191 = Tuple3(x$189,x$188,x$190) in -- #942\n//│         jump j$25(x$191) -- #941\n//│   def j$25(x$187) =\n//│     x$187 -- #919\n//│   def quotRem(quotRem_arg1$0,quotRem_arg2$0) =\n//│     let* (x$192) = z_div(quotRem_arg1$0,quotRem_arg2$0) in -- #965\n//│     let* (x$193) = z_mod(quotRem_arg1$0,quotRem_arg2$0) in -- #964\n//│     let x$194 = Tuple2(x$192,x$193) in -- #963\n//│     x$194 -- #962\n//│   def max'(max'_arg1$0) =\n//│     case max'_arg1$0 of -- #1028\n//│       Cons =>\n//│         let x$196 = Cons.t(max'_arg1$0) in -- #1027\n//│         let x$197 = Cons.h(max'_arg1$0) in -- #1026\n//│         case x$196 of -- #1025\n//│           Nil =>\n//│             jump j$27(x$197) -- #980\n//│           Cons =>\n//│             let x$199 = Cons.t(x$196) in -- #1024\n//│             let x$200 = Cons.h(x$196) in -- #1023\n//│             let* (x$201) = z_lt(x$197,x$200) in -- #1022\n//│             if x$201 -- #1021\n//│               true =>\n//│                 let x$203 = Cons(x$200,x$199) in -- #1008\n//│                 let* (x$204) = max'(x$203) in -- #1007\n//│                 jump j$28(x$204) -- #1006\n//│               false =>\n//│                 let x$205 = Cons(x$197,x$199) in -- #1020\n//│                 let* (x$206) = max'(x$205) in -- #1019\n//│                 jump j$28(x$206) -- #1018\n//│   def j$26(x$195) =\n//│     x$195 -- #967\n//│   def j$27(x$198) =\n//│     jump j$26(x$198) -- #978\n//│   def j$28(x$202) =\n//│     jump j$27(x$202) -- #996\n//│   def g(g_arg1$0,g_arg2$0) =\n//│     case g_arg1$0 of -- #1156\n//│       Tuple3 =>\n//│         let x$208 = Tuple3.z(g_arg1$0) in -- #1155\n//│         let x$209 = Tuple3.y(g_arg1$0) in -- #1154\n//│         let x$210 = Tuple3.x(g_arg1$0) in -- #1153\n//│         case g_arg2$0 of -- #1152\n//│           Tuple3 =>\n//│             let x$212 = Tuple3.z(g_arg2$0) in -- #1151\n//│             let x$213 = Tuple3.y(g_arg2$0) in -- #1150\n//│             let x$214 = Tuple3.x(g_arg2$0) in -- #1149\n//│             let* (x$215) = const0() in -- #1148\n//│             let* (x$216) = z_equal(x$212,x$215) in -- #1147\n//│             if x$216 -- #1146\n//│               true =>\n//│                 let x$218 = Tuple3(x$208,x$210,x$209) in -- #1076\n//│                 jump j$31(x$218) -- #1075\n//│               false =>\n//│                 let* (x$219) = quotRem(x$208,x$212) in -- #1145\n//│                 case x$219 of -- #1144\n//│                   Tuple2 =>\n//│                     let x$221 = Tuple2.y(x$219) in -- #1143\n//│                     let x$222 = Tuple2.x(x$219) in -- #1142\n//│                     let x$223 = Tuple3(x$214,x$213,x$212) in -- #1141\n//│                     let* (x$224) = z_mul(x$222,x$214) in -- #1140\n//│                     let* (x$225) = z_sub(x$210,x$224) in -- #1139\n//│                     let* (x$226) = z_mul(x$222,x$213) in -- #1138\n//│                     let* (x$227) = z_sub(x$209,x$226) in -- #1137\n//│                     let x$228 = Tuple3(x$225,x$227,x$221) in -- #1136\n//│                     let* (x$229) = g(x$223,x$228) in -- #1135\n//│                     jump j$32(x$229) -- #1134\n//│   def j$29(x$207) =\n//│     x$207 -- #1030\n//│   def j$30(x$211) =\n//│     jump j$29(x$211) -- #1045\n//│   def j$31(x$217) =\n//│     jump j$30(x$217) -- #1066\n//│   def j$32(x$220) =\n//│     jump j$31(x$220) -- #1085\n//│   def abs(abs_arg1$0) =\n//│     let* (x$230) = const0() in -- #1179\n//│     let* (x$231) = z_lt(abs_arg1$0,x$230) in -- #1178\n//│     if x$231 -- #1177\n//│       true =>\n//│         let* (x$233) = const0() in -- #1174\n//│         let* (x$234) = z_sub(x$233,abs_arg1$0) in -- #1173\n//│         jump j$33(x$234) -- #1172\n//│       false =>\n//│         jump j$33(abs_arg1$0) -- #1176\n//│   def j$33(x$232) =\n//│     x$232 -- #1164\n//│   def f2(f2_arg1$0) =\n//│     case f2_arg1$0 of -- #1234\n//│       Tuple3 =>\n//│         let x$236 = Tuple3.z(f2_arg1$0) in -- #1233\n//│         let x$237 = Tuple3.y(f2_arg1$0) in -- #1232\n//│         let x$238 = Tuple3.x(f2_arg1$0) in -- #1231\n//│         case x$236 of -- #1230\n//│           Tuple3 =>\n//│             let x$240 = Tuple3.z(x$236) in -- #1229\n//│             let x$241 = Tuple3.y(x$236) in -- #1228\n//│             let x$242 = Tuple3.x(x$236) in -- #1227\n//│             let* (x$243) = z_add(x$242,x$241) in -- #1226\n//│             let* (x$244) = z_add(x$243,x$240) in -- #1225\n//│             let* (x$245) = abs(x$244) in -- #1224\n//│             jump j$35(x$245) -- #1223\n//│   def j$34(x$235) =\n//│     x$235 -- #1181\n//│   def j$35(x$239) =\n//│     jump j$34(x$239) -- #1196\n//│   def const0() =\n//│     let* (x$246) = z_of_int(0) in -- #1239\n//│     x$246 -- #1238\n//│   def gcdE(gcdE_arg1$0,gcdE_arg2$0) =\n//│     let* (x$247) = const0() in -- #1296\n//│     let* (x$248) = z_equal(gcdE_arg1$0,x$247) in -- #1295\n//│     if x$248 -- #1294\n//│       true =>\n//│         let* (x$250) = const0() in -- #1261\n//│         let* (x$251) = const1() in -- #1260\n//│         let x$252 = Tuple3(gcdE_arg2$0,x$250,x$251) in -- #1259\n//│         jump j$36(x$252) -- #1258\n//│       false =>\n//│         let* (x$253) = const1() in -- #1293\n//│         let* (x$254) = const0() in -- #1292\n//│         let x$255 = Tuple3(x$253,x$254,gcdE_arg1$0) in -- #1291\n//│         let* (x$256) = const0() in -- #1290\n//│         let* (x$257) = const1() in -- #1289\n//│         let x$258 = Tuple3(x$256,x$257,gcdE_arg2$0) in -- #1288\n//│         let* (x$259) = g(x$255,x$258) in -- #1287\n//│         jump j$36(x$259) -- #1286\n//│   def j$36(x$249) =\n//│     x$249 -- #1247\n//│   def const1() =\n//│     let* (x$260) = z_of_int(1) in -- #1301\n//│     x$260 -- #1300\n//│   def const5000() =\n//│     let* (x$261) = z_of_int(5000) in -- #1306\n//│     x$261 -- #1305\n//│   def testGcd_nofib(testGcd_nofib_arg1$0) =\n//│     let* (x$262) = test(testGcd_nofib_arg1$0) in -- #1311\n//│     x$262 -- #1310\n//│   def z_enumFromTo(z_enumFromTo_arg1$0,z_enumFromTo_arg2$0) =\n//│     let* (x$263) = z_leq(z_enumFromTo_arg1$0,z_enumFromTo_arg2$0) in -- #1345\n//│     if x$263 -- #1344\n//│       true =>\n//│         let* (x$265) = const1() in -- #1340\n//│         let* (x$266) = z_add(z_enumFromTo_arg1$0,x$265) in -- #1339\n//│         let* (x$267) = z_enumFromTo(x$266,z_enumFromTo_arg2$0) in -- #1338\n//│         let x$268 = Cons(z_enumFromTo_arg1$0,x$267) in -- #1337\n//│         jump j$37(x$268) -- #1336\n//│       false =>\n//│         let x$269 = Nil() in -- #1343\n//│         jump j$37(x$269) -- #1342\n//│   def j$37(x$264) =\n//│     x$264 -- #1318\n//│   let* (x$0) = z_of_int(400) in -- #8\n//│   let* (x$1) = testGcd_nofib(x$0) in -- #7\n//│   x$1 -- #6\n//│ \n//│ \n//│ Execution succeeded: \n//│ Z(5201)\n//│ \n"
  },
  {
    "path": "compiler/shared/test/scala/mlscript/compiler/Test.scala",
    "content": "package mlscript\npackage compiler\n\nimport mlscript.utils.shorthands._\nimport scala.util.control.NonFatal\nimport scala.collection.mutable.StringBuilder\nimport mlscript.compiler.TreeDebug\nimport simpledef.SimpleDef\n\nimport DiffTestCompiler.*\n\nclass DiffTestCompiler extends DiffTests(State) {\n  \n  override def postProcess(mode: ModeType, basePath: List[Str], testName: Str, unit: TypingUnit, output: Str => Unit, raise: Diagnostic => Unit): (List[Str], Option[TypingUnit]) = \n    val outputBuilder = StringBuilder()\n\n    var rstUnit = unit;\n    try\n      val lifter = ClassLifter(mode.fullExceptionStack)\n      if (mode.lift) {\n        output(\"Lifted:\")\n        rstUnit = lifter.liftTypingUnit(unit)\n        output(PrettyPrinter.showTypingUnit(rstUnit))\n      }\n      if (mode.showParse) output(rstUnit.toString())\n      if (mode.dbgLifting) \n        output(lifter.getLog)\n    catch\n      case NonFatal(err) =>\n        output(\"Lifting failed: \" ++ err.toString())\n        if mode.fullExceptionStack then \n          outputBuilder ++= \"\\n\" ++ err.getStackTrace().map(_.toString()).mkString(\"\\n\")\n    if (mode.lift) {\n      (outputBuilder.toString().linesIterator.toList, Some(rstUnit))  \n    } else {\n      (outputBuilder.toString().linesIterator.toList, None)\n    }\n  \n  override def postTypingProcess(mode: ModeType, basePath: List[Str], testName: Str, unit: TypingUnit, output: Str => Unit): Option[TypingUnit] = \n    if(mode.simpledef || basePath.contains(\"Defunctionalize\")) {\n      output(\"\\nSimpledef:\")\n      val treeDebug = new TreeDebug(if mode.dbgSimpledef then output else (str) => ())\n      val pd = SimpleDef(treeDebug)\n      pd(unit)\n      val defuncAST = pd.rewriteProgram(unit)\n      output(defuncAST.showDbg.replace(\";\", \"\\n\"))\n      output(\"End simpledef\\n\")\n      return Some(defuncAST)\n    }\n    None\n    \n}\n\nobject DiffTestCompiler {\n  \n  lazy val State =\n    new DiffTests.State(DiffTests.pwd/\"compiler\"/\"shared\"/\"test\"/\"diff\")\n  \n}\n"
  },
  {
    "path": "compiler/shared/test/scala/mlscript/compiler/TestIR.scala",
    "content": "package mlscript.compiler\n\n\nimport mlscript.utils.shorthands._\nimport mlscript.compiler.ir._\nimport scala.collection.mutable.{ListBuffer, StringBuilder}\nimport mlscript.Statement\nimport mlscript.{DiffTests, ModeType, TypingUnit}\nimport mlscript.compiler.ir.{Fresh, FreshInt, Builder}\nimport mlscript.compiler.codegen.cpp._\nimport mlscript.Diagnostic\nimport mlscript.compiler.optimizer.TailRecOpt\n\nimport IRDiffTestCompiler.*\n\nclass IRDiffTestCompiler extends DiffTests(State) {\n  def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) = {\n    val p = new java.io.PrintWriter(f)\n    try { op(p) } finally { p.close() }\n  }\n\n  val preludeSource = ListBuffer[Statement]()\n\n  override def postProcess(mode: ModeType, basePath: List[Str], testName: Str, originalUnit: TypingUnit, output: Str => Unit, raise: Diagnostic => Unit): (List[Str], Option[TypingUnit]) = \n    val outputBuilder = StringBuilder()\n    if (mode.prelude)\n      preludeSource.addAll(originalUnit.rawEntities)\n      output(\"\\nPreluded.\")\n    else if (mode.useIR || mode.irVerbose)\n      try\n        val (fresh, freshFnId, freshClassId, freshTag) = (Fresh(), FreshInt(), FreshInt(), FreshInt())\n        val gb = Builder(fresh, freshFnId, freshClassId, freshTag, raise, mode.irVerbose)\n        val prelude = TypingUnit(preludeSource.toList)\n        var graph = gb.buildGraph(prelude, originalUnit)\n        val hiddenNames = gb.getHiddenNames(prelude)\n\n        output(\"\\n\\nIR:\")\n        output(graph.show(hiddenNames))\n        if !mode.noTailRecOpt then\n          val tailRecOpt = new TailRecOpt(freshFnId, freshClassId, freshTag, raise)\n          val (g, comps) = tailRecOpt.run_debug(graph)\n          output(\"\\n\\nStrongly Connected Tail Calls:\")\n          output(comps.toString)\n          graph = g\n          output(graph.show(hiddenNames))\n        var interp_result: Opt[Str] = None\n        if (mode.interpIR)\n          output(\"\\nInterpreted:\")\n          val ir = Interpreter(mode.irVerbose).interpret(graph)\n          interp_result = Some(ir)\n          output(ir)\n        if (mode.genCpp)\n          val cpp = codegen(graph)\n          if (mode.showCpp)\n            output(\"\\nCpp:\")\n            if (mode.irVerbose)\n              output(cpp.toDocument.print)\n            else\n              output(cpp.toDocumentWithoutHidden.print)\n          if (mode.writeCpp)\n            printToFile(java.io.File(s\"compiler/shared/test/diff-ir/cpp/${testName}.cpp\")) { p =>\n              p.println(cpp.toDocument.print)\n            }\n          if (mode.runCpp)\n            val auxPath = os.pwd/\"compiler\"/\"shared\"/\"test\"/\"diff-ir\"/\"cpp\"\n            val cppHost = CppCompilerHost(auxPath.toString)\n            if !cppHost.ready then\n              output(\"\\nCpp Compilation Failed: Cpp compiler or GNU Make not found\")\n            else\n              output(\"\\n\")\n              cppHost.compileAndRun(cpp.toDocument.print, output)\n      catch\n        case err: Exception =>\n          output(s\"\\nIR Processing Failed: ${err.getMessage()}\")\n          output(\"\\n\" ++ err.getStackTrace().mkString(\"\\n\"))\n        case err: StackOverflowError =>\n          output(s\"\\nIR Processing Failed: ${err.getMessage()}\")\n          output(\"\\n\" ++ err.getStackTrace().mkString(\"\\n\"))\n      \n    (outputBuilder.toString.linesIterator.toList, None)\n  \n}\n\nobject IRDiffTestCompiler {\n  \n  lazy val State =\n    new DiffTests.State(DiffTests.pwd/\"compiler\"/\"shared\"/\"test\"/\"diff-ir\")\n  \n}\n"
  },
  {
    "path": "core/shared/main/scala/utils/Identity.scala",
    "content": "package mlscript.utils\n\n\nclass Identity[T <: AnyRef](val value: T) {\n  \n  override def equals(other: Any): Boolean = other match {\n    case that: Identity[_] => (that.value: Any) is this.value\n    case _ => false\n  }\n  \n  override def hashCode(): Int = System.identityHashCode(value)\n  \n}\n\n"
  },
  {
    "path": "core/shared/main/scala/utils/Lazy.scala",
    "content": "package mlscript.utils\n\nimport shorthands._\n\nabstract class Box[+A] {\n  def force: Opt[A]\n  def force_! : A\n  def isComputing: Bool\n}\n\nclass Eager[+A](val value: A) extends Box[A] {\n  def isComputing = false\n  lazy val force = S(value)\n  def force_! = value\n}\n\nobject Lazy {\n  def apply[A](thunk: => A): Lazy[A] = new Lazy[A] {\n    def compute: A = thunk\n  }\n}\n\nabstract class Lazy[A] extends Box[A] {\n  protected def compute: A\n  def isComputing = _isComputing\n  def isEmpty: Bool = _value.isEmpty\n  private var _isComputing = false\n  private var _value: Opt[A] = N\n  def force = if (_isComputing) N else S(force_!)\n  def force_! = {\n    assert(!_isComputing)\n    _value.getOrElse(_compute)\n  }\n  private def _compute = {\n    _isComputing = true\n    try {\n      val v = compute\n      _value = S(v)\n      v\n    } finally {\n      _isComputing = false\n    }\n  }\n}\n"
  },
  {
    "path": "core/shared/main/scala/utils/algorithms.scala",
    "content": "package mlscript.utils\n\nimport scala.annotation.tailrec\nimport scala.collection.immutable.SortedMap\n\n\nobject algorithms {\n  final class CyclicGraphError(message: String) extends Exception(message)\n\n  /**\n    * Sort a graph topologically.\n    *\n    * @param edges edges (target, source) in the directed acyclic graph\n    * @param nodes provide if you want to include some isolated nodes in the result\n    * @return\n    */\n  def topologicalSort[A: Ordering](edges: Iterable[(A, A)], nodes: Iterable[A] = Nil): Iterable[A] = {\n    @tailrec\n    def sort(toPreds: SortedMap[A, Set[A]], done: Iterable[A]): Iterable[A] = {\n      val (noPreds, hasPreds) = toPreds.partition { _._2.isEmpty }\n      if (noPreds.isEmpty) {\n        if (hasPreds.isEmpty) done else throw new CyclicGraphError(hasPreds.toString)\n      } else {\n        val found = noPreds.map { _._1 }\n        sort(SortedMap.from(hasPreds.view.mapValues(_ -- found)), done ++ found)\n      }\n    }\n    val toPred = edges.foldLeft(SortedMap.from(nodes.map { _ -> Set.empty[A] })) { (acc, e) => \n      acc + (e._1 -> (acc.getOrElse(e._1, Set()) + e._2)) + (e._2 -> acc.getOrElse(e._2, Set()))\n    }\n    sort(toPred, Seq())\n  }\n\n  /**\n    * Partitions a graph into its strongly connected components. The input type must be able to\n    * be hashed efficiently as it will be used as a key.\n    *\n    * @param edges The edges of the graph.\n    * @param nodes Any additional nodes that are not necessarily in the edges list. (Overlap is fine)\n    * @return A list of strongly connected components of the graph.\n    */\n  def partitionScc[A](edges: Iterable[(A, A)], nodes: Iterable[A]): List[List[A]] = {\n    case class SccNode[A](\n      val node: A,\n      val id: Int,\n      var num: Int = -1, \n      var lowlink: Int = -1,\n      var visited: Boolean = false,\n      var onStack: Boolean = false\n    )\n\n    // pre-process: assign each node an id\n    val nodesUniq = {\n      val seen = collection.mutable.LinkedHashSet.empty[A]\n      for ((a, b) <- edges) { seen.add(a); seen.add(b) }\n      for (n <- nodes) seen.add(n)\n      seen.toList\n    }\n    val nodesN = nodesUniq.zipWithIndex.map { case (node, idx) => SccNode(node, idx) }\n    val nodeToIdx = nodesN.map(node => node.node -> node.id).toMap\n    val nodesIdx = nodesN.map { case node => node.id -> node }.toMap\n\n    val neighbours = edges\n      .map { case (a, b) => (nodeToIdx(a), nodesIdx(nodeToIdx(b))) }\n      .groupBy(_._1)\n      .map { case (a, b) => a -> b.map(_._2) }\n      .withDefault(_ => Nil)\n\n    // Tarjan's algorithm\n\n    var stack: List[SccNode[A]] = List.empty\n    var sccs: List[List[A]] = List.empty\n    var i = 0\n\n    def dfs(node: SccNode[A], depth: Int = 0): Unit = {\n      def printlnsp(s: String) = {\n        println(s)\n      }\n      \n      node.num = i\n      node.lowlink = node.num\n      node.visited = true\n      stack = node :: stack\n      i += 1\n      for (n <- neighbours(node.id)) {\n        if (!n.visited) {\n          dfs(n, depth + 1)\n          node.lowlink = n.lowlink.min(node.lowlink)\n        } else if (!n.onStack) {\n          node.lowlink = n.num.min(node.lowlink)\n        } \n      }\n      if (node.lowlink == node.num) {\n        var scc: List[A] = List.empty\n        var cur = stack.head\n        stack = stack.tail\n        cur.onStack = true\n        while (cur.id != node.id) {\n          scc = cur.node :: scc\n          cur = stack.head\n          stack = stack.tail\n          cur.onStack = true\n        }\n        scc = cur.node :: scc\n        sccs = scc :: sccs\n      }\n    }\n\n    for (n <- nodesN) {\n      if (!n.visited) dfs(n)\n    }\n    sccs\n  }\n  \n\n  /**\n    * Info about a graph partitioned into its strongly-connected sets. The input type must be able to\n    * be hashed efficiently as it will be used as a key.\n    *\n    * @param sccs The strongly connected sets.\n    * @param edges The edges of the strongly-connected sets. Together with `sccs`, this forms an acyclic graph.\n    * @param inDegs The in-degrees of the above described graph.\n    * @param outDegs The out-degrees of the above described graph.\n    */\n  case class SccsInfo[A](\n    sccs: Map[Int, List[A]],\n    edges: Map[Int, Iterable[Int]],\n    inDegs: Map[Int, Int],\n    outDegs: Map[Int, Int],\n  )\n\n  /**\n    * Partitions a graph into its strongly connected components and returns additional information\n    * about the partition. The input type must be able to be hashed efficiently as it will be used as a key.\n    *\n    * @param edges The edges of the graph.\n    * @param nodes Any additional nodes that are not necessarily in the edges list. (Overlap is fine)\n    * @return The partitioned graph and info about it.\n    */\n  def sccsWithInfo[A](edges: Iterable[(A, A)], nodes: Iterable[A]): SccsInfo[A] = {\n    val sccs = partitionScc(edges, nodes)\n    val withIdx = sccs.zipWithIndex.map(_.swap).toMap\n    val lookup = (\n      for {\n        (id, scc) <- withIdx\n        node <- scc\n      } yield node -> id\n    ).toMap\n\n    val notInSccEdges = edges.map {\n      case (a, b) => (lookup(a), lookup(b))\n    }.filter {\n      case (a, b) => a != b\n    }\n\n    val outs = notInSccEdges.groupBy {\n      case (a, b) => a\n    }\n\n    val sccEdges = withIdx.map {\n      case (a, _) => a -> Nil // add default case\n    } ++ outs.map {\n      case (a, edges) => a -> edges.map(_._2)\n    }.toMap\n    \n    val inDegs = notInSccEdges.groupBy {\n      case (a, b) => b\n    }.map {\n      case (b, edges) => b -> edges.size\n    }\n\n    val outDegs = outs.map {\n      case (a, edges) => a -> edges.size\n    }\n\n    SccsInfo(withIdx, sccEdges, inDegs, outDegs)\n  }\n}\n"
  },
  {
    "path": "core/shared/main/scala/utils/package.scala",
    "content": "package mlscript\n\nimport utils.shorthands._\nimport scala.collection.mutable\n\npackage object utils {\n\n  import scala.collection.mutable\n  import scala.collection.immutable.{SortedSet, SortedMap}\n  \n  @SuppressWarnings(Array(\n    \"org.wartremover.warts.Equals\",\n    \"org.wartremover.warts.AsInstanceOf\"))\n  implicit final class AnyOps[A](self: A) {\n    def ===(other: A): Bool = self == other\n    def =/=(other: A): Bool = self != other\n    def is(other: A): Bool = self.asInstanceOf[AnyRef] eq other.asInstanceOf[AnyRef]\n    def isnt(other: AnyRef): Bool = !(self.asInstanceOf[AnyRef] eq other)\n    /** An alternative to === when in ScalaTest, which shadows our === */\n    def =:=(other: A): Bool = self == other\n    def in(xs: A => Bool): Bool = xs(self)\n    def in(xs: Seq[_ >: A]): Bool = xs.exists(_ === self)\n  }\n\n  implicit class IntOps(private val self: Int) extends AnyVal {\n    def toOrdinalWord: String = {\n      require(self >= 0)\n      self + 1 match {\n        case 1 => \"first\"\n        case 2 => \"second\"\n        case 3 => \"third\"\n        case n @ (11 | 12 | 13) => s\"${n}th\"\n        case n => self.toString + (n % 10 match {\n          case 1 => \"st\"\n          case 2 => \"nd\"\n          case 3 => \"rd\"\n          case _ => \"th\"\n        })\n      }\n    }\n  }\n  \n  implicit class StringOps(private val self: String) extends AnyVal {\n    import collection.mutable\n    def splitSane(sep: Char): mutable.ArrayBuffer[Str] = {\n      val buf = mutable.ArrayBuffer(new StringBuilder)\n      self.foreach { c => if (c === sep) buf += new StringBuilder else buf.last append c; () }\n      buf.map(_.toString)\n    }\n    def mapLines(f: String => String): String = splitSane('\\n') map f mkString \"\\n\"\n    def indent(pre: String): String = mapLines(pre + _)\n    def indent: String = indent(\"\\t\")\n    def indentNewLines(pre: String = \"\\t\"): String = splitSane('\\n').toList match {\n      case head :: (rest @ _ :: _)  => head + \"\\n\" + rest.map(pre + _).mkString(\"\\n\")\n      case _ => self\n    }\n    def truncate(maxChars: Int, replace: String): String = {\n      val newStr = self.take(maxChars)\n      if (newStr.length < self.length) newStr + replace\n      else newStr\n    }\n    def isCapitalized: Bool = self.nonEmpty && self.head.isUpper\n    def isUncapitalized: Bool = self.nonEmpty && self.head.isLower\n    def decapitalize: String =\n      if (self.length === 0 || !self.charAt(0).isUpper) self\n      else self.updated(0, self.charAt(0).toLower)\n    def pluralize(quantity: Int, inclusive: Boolean = false, es: Boolean = false): String =\n      (if (inclusive) quantity.toString + \" \" else \"\") +\n        (if (quantity > 1 || quantity === 0) self + (if (es) \"es\" else \"s\") else self)\n    @SuppressWarnings(Array(\"org.wartremover.warts.Equals\"))\n    def ===(other: String): Bool = self.equals(other)\n  }\n  \n  implicit class IterableOps[A](private val self: IterableOnce[A]) extends AnyVal {\n    def mkStringOr(\n      sep: String = \"\", start: String = \"\", end: String = \"\", els: String = \"\"\n    ): String = {\n      val ite = self.iterator\n      if (ite.nonEmpty) ite.mkString(start, sep, end) else els\n    }\n    def lnIndent(pre: String = \"\\t\"): Str =\n      self.iterator.map(\"\\n\" + _.toString.indent(pre)).mkString\n    def collectLast[B](f: Paf[A, B]): Opt[B] = self.iterator.collect(f).foldLeft[Opt[B]](N)((_, a) => S(a))\n    def toSortedSet(implicit ord: Ordering[A]): SortedSet[A] =\n      SortedSet.from(self)\n  }\n  implicit class OptIterableOps[A](private val self: IterableOnce[Opt[A]]) extends AnyVal {\n    def firstSome: Opt[A] = self.iterator.collectFirst { case Some(v) => v }\n  }\n  implicit class PairIterableOps[A, B](private val self: IterableOnce[A -> B]) extends AnyVal {\n    def mapKeys[C](f: A => C): List[C -> B] = mapKeysIter(f).toList\n    def mapValues[C](f: B => C): List[A -> C] = mapValuesIter(f).toList\n    def mapKeysIter[C](f: A => C): Iterator[C -> B] = self.iterator.map(p => f(p._1) -> p._2)\n    def mapValuesIter[C](f: B => C): Iterator[A -> C] = self.iterator.map(p => p._1 -> f(p._2))\n    def keys: Iterator[A] = self.iterator.map(_._1)\n    def values: Iterator[B] = self.iterator.map(_._2)\n    def toSortedMap(implicit ord: Ordering[A]): SortedMap[A, B] =\n      SortedMap.from(self)\n  }\n  \n  implicit class MapOps[A, B](private val self: Map[A, B]) extends AnyVal {\n    def +++(that: Map[A, B]): Map[A, B] = {\n      require(!self.keysIterator.exists(that.keySet), (self.keySet, that.keySet))\n      self ++ that\n    }\n    def +++(that: Iterable[A -> B]): Map[A, B] = {\n      val thatKeySet = that.iterator.map(_._1).toSet\n      require(!self.keysIterator.exists(thatKeySet), (self.keySet, thatKeySet))\n      self ++ that\n    }\n  }\n  \n  def mergeOptionsFlat[A](lhs: Option[A], rhs: Option[A])(f: (A, A) => Opt[A]): Option[A] = (lhs, rhs) match {\n    case (Some(l), Some(r)) => f(l, r)\n    case (lhs @ Some(_), _) => lhs\n    case (_, rhs @ Some(_)) => rhs\n    case (None, None) => None\n  }\n  def mergeOptions[A](lhs: Option[A], rhs: Option[A])(f: (A, A) => A): Option[A] =\n    mergeOptionsFlat(lhs, rhs)(f(_, _) |> some)\n  \n  def mergeMap[A, B](lhs: Iterable[(A, B)], rhs: Iterable[(A, B)])(f: (B, B) => B): Map[A,B] =\n    new mutable.ArrayBuffer(lhs.knownSize + rhs.knownSize max 8)\n      .addAll(lhs).addAll(rhs).groupMapReduce(_._1)(_._2)(f)\n  \n  def mergeSortedMap[A: Ordering, B](lhs: Iterable[(A, B)], rhs: Iterable[(A, B)])(f: (B, B) => B): SortedMap[A,B] =\n    SortedMap.from(mergeMap(lhs, rhs)(f))\n  \n  \n  implicit final class PafHelper[A,B](private val self: Paf[A,B]) extends AnyVal {\n    // def appOrElse[C](arg: A)(els: A => )\n    def appOrElse[A1 <: A, B1 >: B](x: A1)(default: A1 => B1): B1 =\n      self.applyOrElse(x, default)\n  }\n  implicit final class GenHelper[A](private val self: A) extends AnyVal {\n    \n    @inline def into [B] (rhs: A => B): B = rhs(self)\n    \n    @inline def |> [B] (rhs: A => B): B = rhs(self)\n    @inline def |>? [B] (rhs: PartialFunction[A, B]): Option[B] =\n      rhs.andThen(some).appOrElse(self)(_ => none)\n    @inline def |>?? [B] (rhs: PartialFunction[A, Option[B]]): Option[B] =\n      rhs.appOrElse(self)(_ => none)\n    @inline def |>! [B] (rhs: PartialFunction[A, B]): B = rhs(self)\n    \n    /** Like |> but expects the function to return the same type */\n    @inline def |>= (rhs: A => A): A = rhs(self)\n    @inline def |>=? (rhs: PartialFunction[A, A]): A =\n      rhs.appOrElse(self)(_ => self)\n    \n    /** A lesser precedence one! */\n    @inline def /> [B] (rhs: A => B): B = rhs(self)\n    \n    @inline def matches(pf: PartialFunction[A, Bool]): Bool =\n      pf.lift(self).contains(true)\n    \n    @inline def optionIf(cond: A => Bool): Option[A] = if (cond(self)) Some(self) else None\n    @inline def optionUnless(cond: A => Bool): Option[A] = if (!cond(self)) Some(self) else None\n    \n    /** \n     * A helper to write left-associative applications, mainly used to get rid of paren hell\n     * Example:\n     *   println(Id(Sym(f(chars))))\n     *   println(Id <|: Sym.apply <|: f <|: chars)  // `Sym` needs `.apply` because it's overloaded\n     */\n    @inline def <|: [B] (lhs: A => B): B = lhs(self)\n    \n    def withTypeOf[T >: A](x: T): T = self: T\n    \n  }\n  \n  implicit final class LazyGenHelper[A](self: => A) {\n    \n    @inline def optionIf(cond: Bool): Option[A] = if (cond) Some(self) else None\n    \n    @inline def optionUnless(cond: Bool): Option[A] = if (!cond) Some(self) else None\n    \n  }\n  \n  implicit final class ListHelpers[A](ls: Ls[A]) {\n    def filterOutConsecutive(f: (A, A) => Bool = _ === _): Ls[A] =\n      ls.foldRight[List[A]](Nil) { case (x, xs) => if (xs.isEmpty || !f(xs.head, x)) x :: xs else xs }\n    def tailOption: Opt[Ls[A]] = if (ls.isEmpty) N else S(ls.tail)\n    def headOr(els: => A): A = if (ls.isEmpty) els else ls.head\n    def tailOr(els: => Ls[A]): Ls[A] = if (ls.isEmpty) els else ls.tail\n    def mapHead(f: A => A): Ls[A] = ls match {\n      case h :: t => f(h) :: t\n      case Nil => Nil\n    }\n  }\n  \n  implicit final class OptionHelpers[A](opt: Opt[A]) {\n    def dlof[B](f: A => B)(b: => B): B = opt.fold(b)(f)\n  }\n  \n  implicit class MutSetHelpers[A](self: mutable.Set[A]) {\n    def setAndIfUnset(x: A)(thunk: => Unit): Unit = {\n      if (!self.contains(x)) {\n        self += x\n        thunk\n      }\n    }\n    def setAnd[R](x: A)(ifSet: => R)(ifUnset: => R): R = {\n      if (self.contains(x)) ifSet else {\n        self += x\n        ifUnset\n      }\n    }\n  }\n  \n  // * The goal of these is to avoid the use of varargs, which I've found to be a source of\n  // * overhead in the past, due to the allocation of intermediate arrays.\n  // * Remains to be seen if using these is always (or ever?) necessarily a win.\n  implicit class MutSetObjectHelpers(self: mutable.Set.type) {\n    def single[A](a: A): mutable.Set[A] = mutable.Set.empty[A] += a\n  }\n  implicit class SetObjectHelpers(self: Set.type) {\n    def single[A](a: A): Set[A] = (Set.newBuilder[A] += a).result()\n  }\n  implicit class SortedSetObjectHelpers(self: SortedSet.type) {\n    def single[A: Ordering](a: A): SortedSet[A] = (SortedSet.newBuilder[A] += a).result()\n  }\n  implicit class MapObjectHelpers(self: Map.type) {\n    def single[A, B](ab: A -> B): Map[A, B] = (Map.newBuilder[A, B] += ab).result()\n  }\n  implicit class SortedMapObjectHelpers(self: SortedMap.type) {\n    def single[A: Ordering, B](ab: A -> B): SortedMap[A, B] = (SortedMap.newBuilder[A, B] += ab).result()\n  }\n  implicit class VectorObjectHelpers(self: Vector.type) {\n    def single[A](a: A): Vector[A] = a +: Vector.empty\n    def double[A](a: A, b: A): Vector[A] = a +: b +: Vector.empty\n    def triple[A](a: A, b: A, c: A): Vector[A] = a +: b +: c +: Vector.empty\n  }\n  \n  def TODO(msg: Any): Nothing = throw new NotImplementedError(\n    msg.toString + s\" (of class ${msg.getClass().getSimpleName()})\")\n  def TODO(msg: Any, cond: Bool): Unit = if (cond) TODO(msg)\n  def die: Nothing = lastWords(\"Program reached an unexpected state.\")\n  def lastWords(msg: String): Nothing = throw new Exception(s\"Internal Error: $msg\")\n  def wat(msg: String, obj: Any): Nothing = lastWords(s\"$msg ($obj)\")\n  def wat(obj: Any): Nothing = wat(s\"unexpected value\", obj)\n  \n  /** To make Scala unexhaustivity warnings believed to be spurious go away,\n   * while clearly indicating the intent. */\n  def spuriousWarning: Nothing = lastWords(\"Case was reached that was thought to be unreachable.\")\n  \n  def checkless[A, B](pf: Paf[A, B]): A => B = pf\n  \n  private val _id: Any => Any = x => x\n  def id[A]: A => A = _id.asInstanceOf[A => A]\n  \n  \n  def closeOver[A](xs: Set[A])(f: A => Set[A]): Set[A] =\n    closeOverCached(Set.empty, xs)(f)\n  def closeOverCached[A](done: Set[A], todo: Set[A])(f: A => Set[A]): Set[A] =\n    if (todo.isEmpty) done else {\n      val newDone = done ++ todo\n      closeOverCached(newDone, todo.flatMap(f) -- newDone)(f)\n    }\n  \n  \n  object EmptyColl {\n    def unapply(it: Iterable[Any]): Bool = it.isEmpty\n  }\n  \n}\n"
  },
  {
    "path": "core/shared/main/scala/utils/shorthands.scala",
    "content": "package mlscript.utils\n\nimport scala.annotation.showAsInfix\nimport scala.util.chaining._\n\nobject shorthands {\n  \n  /** We have Int instead of Integer; why not Bool instead of Boolean? */\n  type Bool = Boolean\n  \n  /** Dotty syntax for intersection types */\n  @showAsInfix\n  type & [+A,+B] = A with B\n  \n  type Ls[+A] = List[A]\n  val Ls: List.type = List\n  \n  type NELs[+A] = ::[A]\n  \n  type Str = String\n  \n  type Ite[+A] = Iterator[A]\n  val Ite: Iterator.type = Iterator\n  \n  type Opt[+A] = Option[A]\n  val Opt: Option.type = Option\n  type S[+A] = Some[A]\n  val S: Some.type = Some\n  val N: None.type = None\n  def some[A]: A => Option[A] = Some(_)\n  def none[A]: Option[A] = None\n  \n  def nil[A]: List[A] = Nil\n  \n  type Paf[-A,+B] = PartialFunction[A,B]\n  \n  type Exc = Exception\n  type Err = Error\n  \n  type Ord[A] = Ordering[A]\n  type Num[A] = Numeric[A]\n  \n  type \\/[+A, +B] = Either[A, B]\n  val \\/ : Either.type = Either\n  \n  def left[A]: A => Left[A, Nothing] = Left(_)\n  def right[B]: B => Right[Nothing, B] = Right(_)\n  \n  type L[+A] = Left[A, Nothing]\n  val L: Left.type = Left\n  \n  type R[+B] = Right[Nothing, B]\n  val R: Right.type = Right\n  \n  @showAsInfix\n  type -> [+A,+B] = (A,B)\n  object -> {\n    def unapply[A, B](ab: (A, B)): Some[(A, B)] = Some(ab)\n  }\n  implicit class Tuple2Helper[A,B](private val self: (A,B)) extends AnyVal {\n    @inline def mapFirst[C](f: A => C): (C,B) = (self._1 pipe f, self._2)\n    @inline def mapSecond[C](f: B => C): (A,C) = (self._1, self._2 pipe f)\n  }\n  \n}\n"
  },
  {
    "path": "doc/Parsing.md",
    "content": "# Advanced MLscript Parser\n\n## Indentation\n\nThe parsing is indentation-sensitive,\nbut it follows some very simple rules uniformly.\n\nIndentation is used only for two things:\n * to form indented blocks of code\n \n * to form single expressions spanning multiple line\n\n\n### Indented blocks of code\n\nIn general, you can understand an indented block of code\nas a syntax for nesting a list of `;`-separated statements inside an argument expression.\n\nAn indented block of the form:\n\n```ts\nsome header expression\n  aaa bbb ccc\n  ddd eee fff\n  ggg hhh iii\n```\n\nis equivalent to the form:\n\n```ts\nsome header expression / (aaa bbb ccc; ddd eee fff; ggg hhh iii)\n```\n\nwhere `/` is a right-associated expression separator with low precedence\n(whose goal is to avoid having to nest parentheses, similar to Haskell's `$`).\n\nSo in particular,  the following:\n\n```ts\nfoo x\n  bar y\n    baz z\n```\n\nis equivalent to:\n\n```ts\nfoo x / bar y / baz z\n```\n\nwhich is shorthand for:\n\n```ts\nfoo x (bar y (baz z))\n```\n\n\n\n### Single expressions spanning multiple line\n\n**Rule 1:**\nif a line finishes on an operator,\nthen the following indented block is understood as an argument to that operator:\n\n```ts\nsome header expression +\n  aaa bbb ccc\n  ddd eee fff\n  ggg hhh iii\n```\n\nis equivalent to:\n\n```ts\nsome header expression + (aaa bbb ccc; ddd eee fff; ggg hhh iii)\n```\n\n**Rule 2:**\na header expression followed by a succession of indented lines all starting by an operator\nis understood as the application of the corresponding operators,\nin order (operator precedence is ignored),\nto the header expression:\n\n```ts\nsome header expression\n  + aaa bbb ccc\n  * ddd eee fff\n  - ggg hhh iii\n```\n\nis equivalent to:\n\n```ts\n(((some header expression) + (aaa bbb ccc)) * (ddd eee fff)) - (ggg hhh iii)\n```\n\n**Note:**\nIn both of these rules, one can use `/` as an operator;\nso one can write:\n\n```ts\nfoo\n  / arg 1\n  / arg 2\n// i.e.,\n(foo / arg 1) / arg 2\n\nfoo / bar /  // this last `/` is not actually useful!\n  arg 1\n  arg 2\n// i.e.,\nfoo / bar / (arg 1; arg 2)\n```\n\n[TODO actually implement]\n\n**Note:**\nfield accessors are considered operators (with tightest precedence):\n\n```ts\nfoo\n  .bar 1\n  .baz 2\n// i.e.,\n(foo.bar 1).baz 2\n```\n\n[TODO actually implement]\n\n"
  },
  {
    "path": "doc/mls-codebase-doc.md",
    "content": "# Documentation of the MLscript Codebase\n\nThis is the documentation of the MLscript codebase.\n\n## Overview\n\nThis codebase of the MLscript Programming Language has all the basic components\nof a static-typed programming language compiler: lexer, parser, typer, and code generator.\nFor testing, there is a web demo of MLscript as well as a test suite.\nWe now give a high-level introduction to each compiler component and its correspondence to\nour Scala sources. Note that source file paths are rooted in `/shared/src/main/scala/mlscript`.\n\n### Lexing\n\nThe lexer accepts source strings and returns tokens to be parsed.\nThe corresponding files are:\n\n- `NewLexer.scala` contains the lexer class.\n- `Token.scala` contains the token data types.\n\n### Parsing\n\nThe parser accepts tokens generated by the lexer and\nreturns an abstract syntax tree of the input program in the surface syntax.\nThe corresponding files are:\n\n- `NewParser.scala` contains the parser class.\n- `syntax.scala` contains the **surface** syntax data types of the language.\n\n### Typing\n\nThe typer accepts an abstract syntax tree of a program\nand performs type checking.\nMLscript's typer supports principal type inference with subtyping.\nFor more information about the type system,\nplease refer to [MLstruct](https://dl.acm.org/doi/abs/10.1145/3563304).\n\nThe corresponding files are:\n- `Typer.scala` contains the typer class.\n- `TypeSimplifier.scala` contains type simplification algorithms to simplify\ninferred types.\n- `ucs/Desugarer.scala` contains class `ucs.Desugarer` which implements desugaring\nmethods.\n- `TypeDefs.scala` and `NuTypeDefs.scala` contain class `TypeDef` and methods for\ndeclarations like classes, interfaces, and type aliases.\n- `ConstraitSolver.scala` contains class `ConstraintSolver` which solves subtyping\nconstraints.\n- `NormalForms.scala` contains class `NormalForms` which provides the infrastructure\nto solve tricky subtyping constraints with disjunct normal forms (DNF) on the left\nand conjunct normal forms (CNF) on the right.\n- `TyperDatatypes.scala` contains class `TyperDatatypes` which includes\ndata types to support **internal** representation of types with mutable states to support\ntype inference with subtyping.\n- `TyperHelpers.scala` contains class `TyperHelpers` that provides helper methods\nfor the typer.\n\nNote that the inheritance relationships between these typer classes do *not* have any actual semantics\n- we are following Scala's *Cake Pattern*. Typer classes will be finally composed\ninto the `Typer` class by inheritance.\n\n### Code Generation\n\nThe code generator translates MLscript AST into JavaScript AST and generates the corresponding JavaScript code.\n\nThe corresponding files are:\n\n- `codegen/Codegen.scala` contains definitions of JavaScript AST nodes\n  and methods for JavaScript code generation.\n- `codegen/Scope.scala` contains class `Scope` which manages symbols\n  and provides hygienic runtime name generation.\n- `codegen/Symbol.scala` contains classes `NewClassSymbol`, `MixinSymbol`,\n  and `ModuleSymbol` which include information on `class`, `mixin` and `module` definitions.\n- `JSBackend.scala` contains class `JSBackend` that translates an MLscript AST\n  into a JavaScript AST. Classes `JSWebBackend` and `JSTestBackend` inherit class `JSBackend`\n  and generate adapted code for the web demo and the test suite.\n\n### Web Demo and Testing\n\n\nTesting of MLscript works as follows:\n - the MLscript compiler reads the given test file one code block at a time (code blocks are separated by empty lines);\n - after reading the code block, it outputs the inferred types as well as any type errors encountered;\n - after that, it executes the code block in NodeJS (by shelling out to a `node` process) and outputs the results.\n\nWe have a web demo for users to test our implementation in any modern browser.\nIt has a textbox for MLscript source code input and it produces typing and running\nresults live. The implementation can be tried online at https://hkust-taco.github.io/superoop/\nand locally in `/js/src/main/scala/Main.scala`.\n\nWe have a \"`diff`-based\" test suite for our implementation.\nIt detects changes to MLscript test sources (using git),\ngenerates typing and running results, and inserts those results\ninto test sources. The diff-based testing implementation is in\n`/shared/src/test/scala/mlscript/DiffTests.scala`.\nMLscript test sources are in `/shared/src/test/diff`.\n\n## Detailed Introduction\n\nWe now introduce the implementation of each compiler component\nin more detail.\n\n### Lexing\n\nClass `NewLexer` in `NewLexer.scala` is the lexer class. It takes an `origin` object,\nwhich contains the original source string together with the source file name,\nthe number of the first line, and some helper functions. Lazy value `tokens` generates\na list of tokens with their location in the source code. Lazy value `bracketedTokens`\nconverts the lexed tokens into *structured tokens*,\nwhich use `BRACKETS` constructs instead of `OPEN_BRACKET`/`CLOSE_BRACKET` and `INDENT`/`DEINDENT`.\nToken and structured token data types can be found in `Tokens.scala`.\n\n### Parsing\n\nClass `NewParser` in `NewParser.scala` is the parser class. It takes a list\nof structured tokens with their location information. Method `typingUnit`\ncalls method `block` to parse the token list into a list of `Statement` or\n`IfBody` (defined in `syntax.scala`), filters out unexpected `then/else`\nclauses introduced by `Ifbody`, and returns a `TypingUnit` (a list of `Statement`).\n\nFile `syntax.scala` contains *immutable* surface syntax data types of MLscript,\nwhich are different from the internal representations in the typer for later type inference.\nHere we introduce several surface syntax data types:\n\n- Classes `Decl`, `TypeDef`, `MethodDef` are deprecated.\n- Class `TypeDefKind` includes type definition kinds: classes and mixins, etc.\n- Class `Term` includes MLscript term data types. Case class `Bind` is no longer used.\nCase class `Splc` is for the rest of a parameter list, similar to the rest parameter in JavaScript.\nCase classes `Forall` and `Inst` are for first-class polymorphism.\n- Class `IfBody` includes if-then-else structure data types.\n- Class `CaseBranches` includes case branch data types for MLscript pattern matching.\n- Class `TypeLike` includes `Type`, `Signature`, and `NuDecl`.\n- Class `Type` includes MLscript type data types. Case class `Rem` is for record member removal.\nCase class `WithExtension` is for record type extension. For example, `A with {x : int}`\nis equivalent to `A\\x & {x : int}`.\n- Class `TypeVar` represents the type variable. Its identifier can be an `Int`\ngenerated internally by the compiler or `Str` specified by the user.\n- Class `NuTypeDef` is a `NuDecl` for type definitions.\nNote that it has optional `superAnnot`\nand `thisAnnot` for precisely-typed open recursion.\n- Class `NuFunDef` is a `NuDecl` for function and let-bindings.\n\n### Typing\n\nThe MLscript typer (class `Typer`) works with a typing context (class `Ctx`) which\nmainly maintains all global and local bindings of names to their types.\nThe typer accepts a typing unit from the parser, types the typing unit, and returns a typed typing unit.\nThe typed typing unit\nis sent to the type simplifier and is finally expanded, i.e., converted\nback to types in the surface syntax for presentation.\nThe typer has **internal** representations of types\n(defined in `TyperDatatypes.scala`)\nwith mutable states for type inference with subtyping. \n\nWe first introduce several typer data types defined in `TyperDatatypes.scala`:\n\n- Class `TypeProvenance` stores the location where a type is introduced.\n- Class `LazyTypeInfo` is for type definitions including classes, mixins, modules.\nIts type is lazily computed to support *mutual recursive* type\ndefinitions. It has a `complete` method to complete typing lazily typed definitions.\n- Class `PolymorphicType` represents a type with universally quantified type variables.\nBy convention, in the type body, type variables of levels greater than\nthe polymorphic type's level are polymorphic.\n- Class `SimpleType` is a general type form of all types.\nIt requires a method `level` for level-based polymorphism.\n- Class `BaseType` includes base types such as function, array, tuple, and class tag types.\nIt can later be refined by `RecordType`.\n- Class `RecordType` is a record type. It has a list of bindings from record fields to their types.\n- Class `SpliceType` is not used for now.\n- Class `ProxyType` is a derived type form to store more type provenance information.\n- Class `TypeRef` is a reference to named types such as type definitions like classes.\nIt has a list of type arguments. A type reference with type arguments is expanded to\na class tag type with the class's type parameters refined by the corresponding type arguments as type members.\nFor example, `Foo[Int]` is expanded to `#Foo & {Foo.A: int..int}`.\n- Class `TypeTag` has different kinds of type tags including class tags and abstract tags, etc.\n- Class `FieldType` represents a term field type or a type member.\nWhen it represents a term field type, `lb` represents if the type is mutable.\nOtherwise, `lb` is the lower bound of the type member.\n- Class `TypeVariable` represents a type variable, which has upper and lower bounds\nfor type inference with subtyping.\n\nMethod `typeTypingUnit` in class `NuTypeDefs` accepts the typing unit to type. It inspects each statement\nin the typing unit. If the statement is a type definition, a `DelayedTypeInfo` (which is a subclass of `LazyTypeInfo`)\nis produced and stored in the typing context (note the typing context only uses `tyDefs2` to store\ntype definitions). Otherwise, it desugars the statement and calls `typeTerms` to type\nthe desugared statements. For a single `Term`, it is passed to `typeTerm` to type.\nMethod `typeTerm` in class `Typer` types a term. If the term needs type information of a `LazyTypeInfo`,\nthe typing of that lazily typed definition will be completed. Subtyping constraints are generated during typing\nand sent to `ConstraintSolver` to propagate constraints to type variables.\nFor more about type inference of subtyping, please refer to [MLstruct](https://dl.acm.org/doi/abs/10.1145/3563304).\n\nOf particular interest,\nwe introduce how classes and mixins are typed to implement precisely-typed open recursion in more detail.\nMethod `complete` of `DelayedTypeInfoImpl`,\ntypes type definitions: classes, modules, and mixins and let-/fun-bindings.\n\nWhen a class (`Cls` which is a `NuTypeDef`) is typed, class fields are first\nadded into the typing context, and `this` is associated with a fresh type variable.\nThe `inherit` helper methods deal with the inheritance clauses of the type definitions.\nThe inheritance process starts with an empty record type as the initial `super` type.\nIt inspects each parent, accumulates members of parents, and updates the `super` type on the way.\nFor each parent,\nif it is a mixin, and the typing context has that mixin defined, it completes the type of the mixin\nand freshens each type variable of the mixin, as each mixin's type should be constrained\ndifferently at different use-sites. Then, two subtyping constraints are generated:\nthe current `super` type and the final\nobject type (`this` type) should be subtypes of the mixin's `super` and `this` type refinements.\nFinally, the mixin's members are accumulated to the class, and the current `super` type is\nupdated using `WithType` because methods in mixins are always *overriding*.\nAfter processing the whole inheritance clause,\nwe update the current `super` type with the class fields' types as `thisType`, and we constrain that\nthe resulting `thisType` (i.e. the final object type) should be a subtype of `finalType`\nwhich is a type variable with all `this` type refinements of mixins accumulated.\n\nTyping of mixins is not that surprising. We associate `this` and `super`\nwith fresh type variables in the typing context and then type the mixin body.\n\n### Code Generation\n\nThe code generation consists of three steps.\nFirstly, class `JSBackend` translates MLscript data types (i.e. class `NuTypeDef`)\ninto corresponding symbols. Then class `JSBackend` generates JavaScript AST nodes\nbased on those symbols.\nFinally, we generate JavaScript code from JavaScript AST nodes.\n\nThe first step is implemented in the method `declareNewTypeDefs`.\nHere we extract information (including name, parameter list, type, members, parents, and so on)\nof classes, mixins, and modules from the given `NuTypeDef` list and generate \na hygienic runtime name for each symbol.\n\nIn the second step, we translate `NewClassSymbol`, `MixinSymbol`, and `ModuleSymbol`\ninto JavaScript AST nodes by using methods `translateNewClassDeclaration`, `translateMixinDeclaration`, and `translateModuleDeclaration`.\nThese three methods invoke another method `translateNewTypeDefinition` to translate\nclasses, mixins, and modules into JavaScript classes.\nThe method `translateNewClassMember` contains the translation of members.\nWe call `translateParents` to get the parent class of a type.\nAssuming we have code:\n```ts\nmodule A extends B, C\n```\n\nThe method `translateParents` processes the inheritance clause in a left-to-right way:\n\n- First, we process the parent `B`:\n  - If `B` is a `class` or a `module`, the JS class definition would be `class A extends B`.\n  - If `B` is a `mixin`, we need a base class for `B`.\n    Here we choose `Object` in JavaScript and the JS class definition would be `class A extends B(Object)`\n- Then we process the parent `C`:\n  - If `C` is a `mixin`, we can use `B(Object)` as `C`'s base class.\n    The JS class definition would be `class A extends C(B(Object))`.\n  - Otherwise, we reject the code because a JavaScript class can have only one parent class.\n  - If module `A` has more parents on the right of `C`, \n    we process them similarly as we deal with `C`.\n\nIf there are initialization parameters in the parent list,\nwe move the arguments into the class constructor and pass them to `super()`.\nNote we need to reverse the order of arguments of `mixin`.\nFor example, assume we have MLscript code below:\n\n```ts\nmodule A extends MixinA(1), MixinB(2, 3), MixinC(4)\n```\n\nThe parameters in `super()` of `A` would be:\n```js\nsuper(4, 2, 3, 1);\n```\n\nWe generate the JavaScript classes inside `typing_unit` objects.\nNote we create `...rest` parameters in each constructor of `mixin`\nbecause we have no information about the actual parent mixin until the mixin composition is finished.\nFor modules, we store the instance of the JavaScript class in the cache.\nFor classes, if they have primitive parameter lists,\nwe store the arrow functions in the cache as class constructors that instantiate classes.\nMixins have no constructor because of the uncertainty of the `base` parameter of mixins.\n\nIn the final step, we emit the JavaScript code by using `toSourceCode` methods in each JavaScript AST node class.\n\nFor a class in MLscript:\n```ts\nclass Lit(n: int)\n```\n\nThe generated code would be:\n```js\nclass TypingUnit {\n  #Lit;\n  constructor() {\n  }\n  get Lit() {\n    const qualifier = this;\n    if (this.#Lit === undefined) {\n      class Lit {\n        #n;\n        constructor(n) {\n          this.#n = n;\n        }\n      static\n        unapply(x) {\n          return [x.#n];\n        }\n      };\n      this.#Lit = ((n) => Object.freeze(new Lit(n)));\n      this.#Lit.class = Lit;\n      this.#Lit.unapply = Lit.unapply;\n    }\n    return this.#Lit;\n  }\n}\nconst typing_unit = new TypingUnit;\nglobalThis.Lit = typing_unit.Lit;\n```\n\nFor a mixin in MLscript:\n```ts\nmixin EvalBase {\n  fun eval(e) =\n    if e is\n      Lit(n) then n: int\n}\n```\n\nThe generated code would be:\n```js\nclass TypingUnit {\n  constructor() {\n  }\n  EvalBase(base) {\n    const qualifier = this;\n    return (class EvalBase extends base {\n      constructor(...rest) {\n        super(...rest);\n      }\n      eval(e) {\n        return ((() => {\n          let a;\n          return (a = e, a instanceof Lit.class ? (([n]) => n)(Lit.unapply(e)) : (() => {\n            throw new Error(\"non-exhaustive case expression\");\n          })());\n        })());\n      }\n    });\n  }\n}\nconst typing_unit = new TypingUnit;\nglobalThis.EvalBase = ((base) => typing_unit.EvalBase(base));\n```\n\nFor a module in MLscript:\n```ts\nmodule TestLang extends EvalBase, EvalNeg, EvalNegNeg\n```\n\nThe generated code would be like this:\n```js\nclass TypingUnit {\n  #TestLang;\n  constructor() {\n  }\n  get TestLang() {\n    const qualifier = this;\n    if (this.#TestLang === undefined) {\n      class TestLang extends EvalNegNeg(EvalNeg(EvalBase(Object))) {\n        constructor() {\n          super();\n        }\n      }\n      this.#TestLang = new TestLang();\n      this.#TestLang.class = TestLang;\n    }\n    return this.#TestLang;\n  }\n}\nconst typing_unit = new TypingUnit;\nglobalThis.TestLang = typing_unit.TestLang;\n```\n\nFor more code generation examples, please check the test source `shared/src/test/diff/codegen/Mixin.mls`.\n"
  },
  {
    "path": "doc/tuple-patterns.md",
    "content": "# Tuple Patterns\n\n```\nb is refined D and\n  let y = b.y\n  ...\n  // pattern with fixed length\n  b is Array { length: 3 }\n  b is [_, _, _]\n\n  // let bindings single field selector and range selector\n  let z = b.z\n  let w = b[1..]\n  let w = b[..-1]\n```\n"
  },
  {
    "path": "flake.nix",
    "content": "{\n  description = \"mlscript\";\n\n  inputs.nixpkgs.url = \"github:NixOS/nixpkgs\";\n  inputs.flake-utils.url = \"github:numtide/flake-utils\";\n  inputs.sbt-deriv.url = \"github:zaninime/sbt-derivation\";\n  inputs.sbt-deriv.inputs.nixpkgs.follows = \"nixpkgs\";\n\n  outputs = { self, nixpkgs, flake-utils, sbt-deriv }:\n    flake-utils.lib.eachDefaultSystem\n      (system:\n      let \n        sbtOverlay = self: super: {\n          sbt = super.sbt.override { jre = super.jdk17_headless; };\n        };\n        pkgs = import nixpkgs { \n          inherit system;\n          overlays = [ sbtOverlay ];\n        };\n      in with pkgs; {\n          devShells.default = mkShell {\n            buildInputs = [\n              clang\n              gcc\n              gnumake\n              boost\n              gmp\n              mimalloc\n              sbt\n              nodejs_24\n            ];\n          };\n      });\n}\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/Compiler.scala",
    "content": "package hkmc2\n\nimport scala.util.Try\nimport scala.scalajs.js.annotation.*\nimport org.scalajs.dom\nimport org.scalajs.dom.document\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\nimport scala.util.matching.Regex\nimport scala.scalajs.js, js.JSConverters.*\nimport scala.collection.immutable\nimport scala.collection.mutable.Map as MutMap\n\nimport io.*\nimport scala.collection.mutable.{ArrayBuffer, Buffer}\n\n@JSExportTopLevel(\"Compiler\")\nclass Compiler(paths: MLsCompiler.Paths)(using cctx: CompilerCtx):\n  private given Config = Config.default(io.Path(\"/\"))\n  \n  private var pathDiagnosticsMap = MutMap.empty[Str, (Int, Buffer[Diagnostic])]\n  \n  private def mkRaise(path: io.Path): Raise = d =>\n    pathDiagnosticsMap.getOrElseUpdate(path.toString, (pathDiagnosticsMap.size, Buffer.empty))._2 += d\n  \n  private val compiler = MLsCompiler(paths, mkRaise)\n  \n  private def collectDiagnostics(): js.Array[js.Dynamic] =\n    pathDiagnosticsMap.toArray.sortBy(_._2._1).map:\n      case (path, (_, diagnostics)) => js.Dynamic.literal(\n        path = path,\n        diagnostics = diagnostics.iterator.map: d =>\n          js.Dynamic.literal(\n            kind = d.kind.toString().toLowerCase(),\n            source = d.source.toString().toLowerCase(),\n            mainMessage = d.theMsg,\n            allMessages = d.allMsgs.iterator.map:\n              case (message, loc) =>\n                lazy val ctx = ShowCtx.mk:\n                  message.bits.collect:\n                    case Message.Code(t) => t\n                js.Dynamic.literal(\n                  messageBits = message.bits.map:\n                    case Message.Text(text) => js.Dynamic.literal(text = text)\n                    case Message.Code(ty) => ty.showIn(0)(using ctx)\n                  .toJSArray,\n                  location = loc match\n                    case S(loc) => js.Dynamic.literal(\n                      start = loc.spanStart,\n                      end = loc.spanEnd\n                    )\n                    case N => null\n                )\n            .toJSArray\n          )\n        .toJSArray)\n    .toJSArray\n  \n  @JSExport\n  def compile(filePath: Str): js.Array[js.Dynamic] =\n    compiler.compileModule(Path(filePath))\n    val perFileDiagnostics = collectDiagnostics()\n    pathDiagnosticsMap = MutMap.empty\n    perFileDiagnostics\n\n@JSExportTopLevel(\"Paths\")\nfinal class Paths(prelude: Str, runtime: Str, term: Str) extends MLsCompiler.Paths:\n  val preludeFile = Path(prelude)\n  val runtimeFile = Path(runtime)\n  val termFile = Path(term)\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/io/InMemoryFileSystem.scala",
    "content": "package hkmc2.io\n\nimport mlscript.utils._, shorthands._\nimport collection.mutable.Map as MutMap\nimport scala.scalajs.js, js.annotation.JSExport, js.JSConverters.*\nimport scala.scalajs.js.annotation.JSExportTopLevel\n\n/**\n * In-memory file system for testing and web compiler. Stores files as a map\n * from path strings to content strings. Note that separators are not normalized.\n */\nclass InMemoryFileSystem(initialFiles: Map[String, String]) extends FileSystem:\n  // We assume that all paths are normalized here.\n  private val files: MutMap[String, (Int, String)] = MutMap.from:\n    initialFiles.map { case (k, v) => (k, (0, v)) }\n  \n  def read(path: Path): String = read(path.toString)\n  \n  def write(path: Path, content: String): Unit =\n    write(path.toString, content)\n  \n  def exists(path: Path): Bool = files.contains(path.toString)\n  \n  def getLastChangedTimestamp(path: Path): Long =\n    files.get(path.toString) match\n      case Some((ts, _)) => ts.toLong\n      case None => throw new FileSystem.FileNotFoundException(path)\n  \n  @JSExport(\"write\")\n  def write(path: Str, content: Str): Unit =\n    files.updateWith(path):\n      case Some((ts, _)) => Some((ts + 1, content))\n      case None => Some((0, content))\n  \n  @JSExport(\"read\")\n  def read(path: Str): Str =\n    files.getOrElse(path, throw new FileSystem.FileNotFoundException(Path(path)))._2\n  \n  @JSExport(\"list\")\n  def list: js.Array[Str] = allFiles.keys.toJSArray\n  \n  /** Get all files (for debugging) */\n  def allFiles: Map[String, String] = files.view.mapValues(_._2).toMap\n\nobject InMemoryFileSystem:\n  /** Create an empty in-memory file system. */\n  @JSExportTopLevel(\"InMemoryFileSystem\")\n  def apply(files: js.Array[js.Tuple2[Str, Str]]): InMemoryFileSystem =\n    new InMemoryFileSystem(files.map(t => t._1 -> t._2).toMap)\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/io/PlatformFileSystem.scala",
    "content": "package hkmc2\npackage io\n\nprivate[io] object PlatformFileSystem:\n  def default: FileSystem = new node.NodeFileSystem\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/io/PlatformPath.scala",
    "content": "package hkmc2\npackage io\n\n/**\n * Platform-specific factory for creating Path instances\n */\nprivate[io] object PathFactory:\n  def fromString(str: String) = new VirtualPath(str)\n  def separator: String = VirtualPath.sep\n  def relPathFromString(str: String) = new VirtualRelPath(str)\n  def relPathUp = new VirtualRelPath(\"..\")\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/io/VirtualPath.scala",
    "content": "package hkmc2.io\n\nimport scala.scalajs.js\nimport mlscript.utils._, shorthands._\nimport VirtualPath.sep\n\n/**\n * Pure JavaScript implementation of Path without using Node.js path module\n */\nprivate[io] case class VirtualPath(val pathString: String) extends Path:\n  private def normalizePath(path: String): String =\n    if path.isEmpty then path\n    else\n      // Split by separator and filter out empty segments\n      val segments = path.split(sep).filter(_.nonEmpty)\n      val isAbs = path.startsWith(sep)\n\n      // Resolve . and .. segments\n      val normalized = segments.foldLeft(List.empty[String]): (acc, seg) =>\n        seg match\n          case \".\" => acc  // Current directory, skip it\n          case \"..\" =>\n            // Parent directory, pop the last segment if possible\n            if acc.isEmpty || acc.last == \"..\" then acc :+ seg\n            else acc.dropRight(1)\n          case _ => acc :+ seg\n      \n      if isAbs then sep + normalized.mkString(sep)\n      else if normalized.isEmpty then \".\"\n      else normalized.mkString(sep)\n  \n  override def toString: String = pathString\n  \n  def last: String =\n    val idx = pathString.lastIndexOf(sep)\n    if idx < 0 then pathString\n    else pathString.substring(idx + 1)\n  \n  def baseName: String =\n    val filename = last\n    val dotIdx = filename.lastIndexOf('.')\n    if dotIdx <= 0 then filename  // .hidden files or no extension\n    else filename.substring(0, dotIdx)\n  \n  def ext: String =\n    val filename = last\n    val dotIdx = filename.lastIndexOf('.')\n    if dotIdx <= 0 then \"\"  // .hidden files or no extension\n    else filename.substring(dotIdx + 1)\n  \n  def up: Path =\n    val idx = pathString.lastIndexOf(sep)\n    if idx < 0 then new VirtualPath(\".\")\n    else if idx == 0 then new VirtualPath(sep)  // root case\n    else new VirtualPath(pathString.substring(0, idx))\n  \n  def /(relPath: RelPath): Path =\n    val combined = if pathString.endsWith(sep) then\n      pathString + relPath.toString\n    else\n      pathString + sep + relPath.toString\n    new VirtualPath(normalizePath(combined))\n  \n  def /(fragment: String): Path =\n    val combined = if pathString.endsWith(sep) then\n      pathString + fragment\n    else\n      pathString + sep + fragment\n    new VirtualPath(normalizePath(combined))\n  \n  def relativeTo(base: Path): Opt[RelPath] =\n    try\n      val baseSegs = base.segments\n      val targetSegs = segments\n      \n      // Find common prefix\n      var i = 0\n      while i < baseSegs.length && i < targetSegs.length && baseSegs(i) == targetSegs(i) do\n        i += 1\n      \n      // Build relative path\n      val upCount = baseSegs.length - i\n      val ups = List.fill(upCount)(\"..\")\n      val downs = targetSegs.drop(i)\n      \n      val relSegs = ups ++ downs\n      if relSegs.isEmpty then S(new VirtualRelPath(\".\"))\n      else S(new VirtualRelPath(relSegs.mkString(sep)))\n    catch case _: Exception => N\n  \n  def segments: Ls[String] =\n    pathString.split(sep).toList.filter(_.nonEmpty)\n  \n  def isAbsolute: Bool = pathString.startsWith(sep)\n\nprivate[io] object VirtualPath:\n  val sep = \"/\"\n\n/**\n * Pure JavaScript implementation of RelPath without using Node.js path module\n */\nprivate[io] class VirtualRelPath(val pathString: String) extends RelPath:\n  override def toString: String = pathString\n  \n  def segments: Ls[String] =\n    pathString.split(sep).toList.filter(_.nonEmpty)\n  \n  def /(other: RelPath): RelPath =\n    val combined = if pathString.endsWith(sep) then\n      pathString + other.toString\n    else\n      pathString + sep + other.toString\n    new VirtualRelPath(combined)\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/io/node/NodeFileSystem.scala",
    "content": "package hkmc2\npackage io\npackage node\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation._\n\nimport mlscript.utils._, shorthands._\n\n/**\n * JavaScript implementation of [[FileSystem]] using Node.js fs module.\n */\nprivate[io] class NodeFileSystem extends FileSystem:\n  def read(path: Path): String =\n    fs.readFileSync(path.toString, \"utf8\")\n  \n  def write(path: Path, content: String): Unit =\n    fs.writeFileSync(path.toString, content)\n  \n  def exists(path: Path): Bool =\n    fs.existsSync(path.toString)\n  \n  def getLastChangedTimestamp(path: Path): Long =\n    fs.lstatSync(path.toString).mtime.getTime().toLong\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/io/node/NodePath.scala",
    "content": "package hkmc2\npackage io\npackage node\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation._\n\nimport mlscript.utils._, shorthands._\n\n/**\n * JavaScript implementation of Path using Node.js path module\n */\nprivate[io] case class NodePath(val pathString: String) extends Path:\n  private lazy val parsed = path.parse(pathString)\n  \n  override def toString: String = pathString\n  \n  def last: String = parsed.base\n  \n  def baseName: String = parsed.name\n  \n  def ext: String =\n    if parsed.ext.startsWith(\".\") then parsed.ext.substring(1)\n    else parsed.ext\n  \n  def up: Path = new NodePath(path.dirname(pathString))\n  \n  def /(relPath: RelPath): Path =\n    new NodePath(path.join(pathString, relPath.toString))\n  \n  def /(fragment: String): Path =\n    new NodePath(pathString + path.sep + fragment)\n  \n  def relativeTo(base: Path): Opt[RelPath] =\n    try S(new NodeRelPath(path.relative(base.toString, pathString)))\n    catch case _: Exception => N\n  \n  def segments: Ls[String] =\n    pathString.split(path.sep).toList.filter(_.nonEmpty)\n  \n  def isAbsolute: Bool = path.isAbsolute(pathString)\n\n/**\n * JavaScript implementation of RelPath using Node.js path module\n */\nprivate[io] class NodeRelPath(val pathString: String) extends RelPath:\n  override def toString: String = pathString\n  \n  def segments: Ls[String] =\n    pathString.split(path.sep).toList.filter(_.nonEmpty)\n  \n  def /(other: RelPath): RelPath =\n    new NodeRelPath(path.join(pathString, other.toString))\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/io/node/package.scala",
    "content": "package hkmc2\npackage io\n\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation._\n\nimport mlscript.utils._, shorthands._\n\n/**\n  * The package object contains facades for Node.js modules. So, it can be used\n  * conveniently in \n  */\npackage object node:\n  /**\n    * Node.js fs module facade.\n    */\n  @js.native\n  @JSImport(\"fs\", JSImport.Namespace)\n  object fs extends js.Object:\n    def readFileSync(path: Str, encoding: Str): Str = js.native\n    def writeFileSync(path: Str, data: Str): Unit = js.native\n    def readdirSync(path: Str): js.Array[Str] = js.native\n    def existsSync(path: Str): Bool = js.native\n    def lstatSync(path: Str): Stats = js.native\n  \n  /**\n    * The facade for [[fs.Stats]]. Only a few useful members are listed here.\n    * Refer to https://nodejs.org/api/fs.html#class-fsstats for the full list\n    * of methods.\n    */\n  @js.native\n  trait Stats extends js.Object:\n    def isDirectory(): Bool = js.native\n    def isFile(): Bool = js.native\n    def isSymbolicLink(): Bool = js.native\n    /** The size of the file in bytes. */\n    val size: Long = js.native\n    /** The timestamp indicating the last time this file was accessed. */\n    def atime: js.Date = js.native\n    /** The timestamp indicating the last time this file was modified. */\n    def mtime: js.Date = js.native\n    /** The timestamp indicating the last time the file status was changed. */\n    def ctime: js.Date = js.native\n    /** The timestamp indicating the creation time of this file. */\n    def birthtime: js.Date = js.native\n  \n  @js.native\n  trait ParsedPath extends js.Object:\n    val base: Str = js.native\n    val name: Str = js.native\n    val ext: Str = js.native\n  \n  /**\n    * Node.js path module facade.\n    */\n  @js.native\n  @JSImport(\"path\", JSImport.Namespace)\n  object path extends js.Object:\n    def sep: Str = js.native\n    def parse(path: Str): ParsedPath = js.native\n    def relative(from: Str, to: Str): Str = js.native\n    def join(paths: Str*): Str = js.native\n    def isAbsolute(path: Str): Bool = js.native\n    def dirname(path: Str): Str = js.native\n  \n  /**\n    * Node.js process module facade.\n    */\n  @js.native\n  @JSGlobal(\"process\")\n  object process extends js.Object:\n    def cwd(): Str = js.native\n"
  },
  {
    "path": "hkmc2/js/src/main/scala/hkmc2/utils/PlatformCompilerCache.scala",
    "content": "package hkmc2\npackage utils\n\nimport CompilerCache.Artifact\nimport collection.mutable.Map as MutMap\nimport mlscript.utils.*, shorthands.*\n\nclass PlatformCompilerCache extends CompilerCache:\n  \n  val elabCache: MutMap[io.Path, Artifact] = MutMap.empty\n  \n"
  },
  {
    "path": "hkmc2/js/src/test/scala/hkmc2/CompilerTest.scala",
    "content": "package hkmc2\n\nimport org.scalatest.funsuite.AnyFunSuite\nimport io.{InMemoryFileSystem, Path, node}\nimport mlscript.utils._, shorthands._\nimport scala.scalajs.js\nimport scala.scalajs.js.annotation._\nimport scala.scalajs.js.Dynamic.global\n\nclass CompilerTest extends AnyFunSuite:\n  private def loadStandardLibrary(): Map[String, String] =\n    val projectRoot = node.process.cwd()\n    val compilePath = node.path.join(projectRoot, \"hkmc2\", \"shared\", \"src\", \"test\", \"mlscript-compile\")\n    val preludePath = node.path.join(projectRoot, \"hkmc2\", \"shared\", \"src\", \"test\", \"mlscript\", \"decls\", \"Prelude.mls\")\n    \n    node.fs.readdirSync(compilePath).filter(_.endsWith(\".mls\")).toSeq.flatMap: fileName =>\n      val filePath = node.path.join(compilePath, fileName)\n      if node.fs.existsSync(filePath) then\n        Some(s\"/std/$fileName\" -> node.fs.readFileSync(filePath, \"utf-8\"))\n      else\n        None\n    .toMap + (\"/std/Prelude.mls\" -> node.fs.readFileSync(preludePath, \"utf-8\"))\n  \n  private val paths = new Paths(\"/std/Prelude.mls\", \"/std/Runtime.mjs\", \"/std/Term.mjs\")\n  \n  private def createCompiler(): (InMemoryFileSystem, Compiler) =\n    val stdLib = loadStandardLibrary()\n    val fs = new InMemoryFileSystem(stdLib)\n    given CompilerCtx = CompilerCtx.fresh(fs)\n    (fs, new Compiler(paths))\n  \n  test(\"compiler can compile a simple program\"):\n    val (fs, compiler) = createCompiler()\n    \n    // Write test program to the file system\n    val code = \"\"\"|import \"./std/Option.mls\"\n                  |import \"./std/Stack.mls\"\n                  |import \"./std/Predef.mls\"\n                  |\n                  |open Stack\n                  |open Option\n                  |open Predef\n                  |\n                  |fun findFirst(xs, f) = if xs is\n                  |  Nil then None\n                  |  Cons(x, xs') and\n                  |    f(x) then Some(x)\n                  |    else findFirst(xs', f)\n                  |\n                  |let nums = 1 :: 2 :: 3 :: 4 :: 5 :: Nil\n                  |let result = nums \\findFirst of x => x * 6 is 24\n                  |\"\"\".stripMargin\n    val inputPath = \"/findFirstTest.mls\"\n    val outputPath = \"/findFirstTest.mjs\"\n    \n    fs.write(inputPath, code)\n    \n    val diagnostics = compiler.compile(inputPath)\n    \n    val hasErrors = diagnostics.exists: perFile =>\n      val fileDiagnostics = perFile.diagnostics.asInstanceOf[scala.scalajs.js.Array[scala.scalajs.js.Dynamic]]\n      fileDiagnostics.exists(_.kind is \"error\")\n    assert(!hasErrors, \"Compilation should succeed without errors\")\n    \n    val outputExists = fs.exists(Path(outputPath))\n    assert(outputExists, \"Output JavaScript file should be generated\")\n    \n    val output = fs.read(outputPath)\n    assert(output.contains(\"findFirst\"), \"Output should contain the findFirst function\")\n  \n  test(\"compiler can compile two files that import each other\"):\n    val (fs, compiler) = createCompiler()\n    \n    val foo = \"\"\"|import \"./std/Predef.mls\"\n                 |\n                 |open Predef\n                 |\n                 |module Foo with...\n                 |\n                 |fun sayHello() = print of \"Hello, world!\"\n                 |\"\"\".stripMargin\n    fs.write(\"/Foo.mls\", foo)\n    \n    val bar = \"\"\"|import \"./Foo.mls\"\n                 |\n                 |Foo.sayHello()\n                 |\"\"\".stripMargin\n    fs.write(\"/Bar.mls\", bar)\n    \n    val diag1 = compiler.compile(\"/Foo.mls\")\n    val diag2 = compiler.compile(\"/Bar.mls\")\n    \n    assert(fs.exists(Path(\"/Foo.mjs\")), \"First output should exist\")\n    assert(fs.exists(Path(\"/Bar.mjs\")), \"Second output should exist\")\n  \n  test(\"compiler can report errors\"):\n    val (fs, compiler) = createCompiler()\n    \n    fs.write(\"/test.mls\", \"\"\"fun f(x) = x + y\"\"\") // `y` is not defined.\n    \n    val diagnostics = compiler.compile(\"/test.mls\")\n    \n    assert(diagnostics.length is 1, \"Should report diagnostics for only one file\")\n    \n    val hasErrors = diagnostics.exists: perFile =>\n      val fileDiagnostics = perFile.diagnostics.asInstanceOf[scala.scalajs.js.Array[scala.scalajs.js.Dynamic]]\n      fileDiagnostics.exists(_.kind is \"error\")\n    \n    assert(hasErrors, \"Compilation should report errors\")\n"
  },
  {
    "path": "hkmc2/js/src/test/scala/hkmc2/io/VirtualPathTests.scala",
    "content": "package hkmc2.io\n\nimport org.scalatest.funsuite.AnyFunSuite\nimport mlscript.utils._, shorthands._\n\nclass VirtualPathTests extends AnyFunSuite:\n  \n  test(\"basic path creation and toString\"):\n    val path = VirtualPath(\"foo/bar\")\n    assert(path.toString == \"foo/bar\")\n  \n  test(\"/ operator with simple fragment\"):\n    val path = VirtualPath(\"foo\")\n    val result = path / \"bar\"\n    assert(result.toString == \"foo/bar\")\n  \n  test(\"/ operator with fragment starting with .\"):\n    val path = VirtualPath(\"foo\")\n    val result = path / \"./bar\"\n    assert(result.toString == \"foo/bar\", \"Current directory '.' should be removed\")\n  \n  test(\"/ operator with fragment starting with ./\"):\n    val path = VirtualPath(\"foo/baz\")\n    val result = path / \"./bar\"\n    assert(result.toString == \"foo/baz/bar\", \"Current directory '.' should be removed\")\n  \n  test(\"/ operator with fragment containing ..\"):\n    val path = VirtualPath(\"foo/baz\")\n    val result = path / \"../bar\"\n    assert(result.toString == \"foo/bar\", \"Parent directory '..' should navigate up one level\")\n  \n  test(\"/ operator with multiple .. segments\"):\n    val path = VirtualPath(\"a/b/c\")\n    val result = path / \"../../d\"\n    assert(result.toString == \"a/d\", \"Multiple '..' should navigate up multiple levels\")\n  \n  test(\"/ operator with . in the middle of path\"):\n    val path = VirtualPath(\"foo\")\n    val result = path / \"bar/./baz\"\n    assert(result.toString == \"foo/bar/baz\", \"Current directory '.' in middle should be removed\")\n  \n  test(\"/ operator with .. in the middle of path\"):\n    val path = VirtualPath(\"foo\")\n    val result = path / \"bar/../baz\"\n    assert(result.toString == \"foo/baz\", \"Parent directory '..' in middle should collapse segments\")\n  \n  test(\"/ operator with absolute path\"):\n    val path = VirtualPath(\"/abs/path\")\n    val result = path / \"./file.txt\"\n    assert(result.toString == \"/abs/path/file.txt\", \"Should work with absolute paths\")\n  \n  test(\"/ operator with RelPath containing .\"):\n    val path = VirtualPath(\"foo\")\n    val relPath = VirtualRelPath(\"./bar\")\n    val result = path / relPath\n    assert(result.toString == \"foo/bar\", \"RelPath with '.' should be normalized\")\n  \n  test(\"/ operator with RelPath containing ..\"):\n    val path = VirtualPath(\"foo/baz\")\n    val relPath = VirtualRelPath(\"../bar\")\n    val result = path / relPath\n    assert(result.toString == \"foo/bar\", \"RelPath with '..' should be normalized\")\n  \n  test(\"/ operator with RelPath containing multiple . and ..\"):\n    val path = VirtualPath(\"a/b\")\n    val relPath = VirtualRelPath(\"./c/../d\")\n    val result = path / relPath\n    assert(result.toString == \"a/b/d\", \"Complex RelPath should be normalized\")\n  \n  test(\"normalization with too many .. segments\"):\n    val path = VirtualPath(\"foo\")\n    val result = path / \"../../bar\"\n    assert(result.toString == \"../bar\", \"Extra '..' should be preserved for relative paths\")\n  \n  test(\"normalization resulting in just .\"):\n    val path = VirtualPath(\"foo\")\n    val result = path / \"..\"\n    assert(result.toString == \".\", \"Navigating up from single segment should result in '.'\")\n  \n  test(\"/ operator with trailing slash\"):\n    val path = VirtualPath(\"foo/\")\n    val result = path / \"bar\"\n    assert(result.toString == \"foo/bar\", \"Should handle trailing slash correctly\")\n  \n  test(\"path segments\"):\n    val path = VirtualPath(\"foo/bar/baz\")\n    assert(path.segments == List(\"foo\", \"bar\", \"baz\"))\n  \n  test(\"last segment\"):\n    val path = VirtualPath(\"foo/bar/baz.txt\")\n    assert(path.last == \"baz.txt\")\n  \n  test(\"baseName\"):\n    val path = VirtualPath(\"foo/bar/baz.txt\")\n    assert(path.baseName == \"baz\")\n  \n  test(\"ext\"):\n    val path = VirtualPath(\"foo/bar/baz.txt\")\n    assert(path.ext == \"txt\")\n  \n  test(\"up\"):\n    val path = VirtualPath(\"foo/bar/baz\")\n    assert(path.up.toString == \"foo/bar\")\n  \n  test(\"isAbsolute - relative path\"):\n    val path = VirtualPath(\"foo/bar\")\n    assert(!path.isAbsolute)\n  \n  test(\"isAbsolute - absolute path\"):\n    val path = VirtualPath(\"/foo/bar\")\n    assert(path.isAbsolute)\n  \n  test(\"complex normalization case\"):\n    val path = VirtualPath(\"a/b/c\")\n    val result = path / \"./d/../e/./f\"\n    assert(result.toString == \"a/b/c/e/f\", \"Complex path with mixed . and .. should normalize correctly\")\n  \n  test(\"normalization with only .\"):\n    val path = VirtualPath(\"foo\")\n    val result = path / \".\"\n    assert(result.toString == \"foo\", \"Single '.' should result in same path\")\n  \n  test(\"normalization preserves absolute paths\"):\n    val path = VirtualPath(\"/a/b\")\n    val result = path / \"../c\"\n    assert(result.toString == \"/a/c\", \"Absolute paths should remain absolute after normalization\")\n  \n  test(\"RelPath / operator\"):\n    val rel1 = VirtualRelPath(\"foo/bar\")\n    val rel2 = VirtualRelPath(\"baz\")\n    val result = rel1 / rel2\n    assert(result.toString == \"foo/bar/baz\")\n"
  },
  {
    "path": "hkmc2/jvm/src/main/scala/hkmc2/io/PlatformFileSystem.scala",
    "content": "package hkmc2\npackage io\n\nimport mlscript.utils._, shorthands._\n\nprivate[io] class JavaFileSystem extends FileSystem:\n  def read(path: Path): String = os.read(unwrap(path))\n\n  def write(path: Path, content: String): Unit = os.write.over(unwrap(path), content)\n\n  def exists(path: Path): Bool = os.exists(unwrap(path))\n  \n  def getLastChangedTimestamp(path: Path): Long = os.mtime(unwrap(path))\n  \n  private def unwrap(path: Path): os.Path = path match\n    case path: WrappedPath => path.underlying\n    case _ => lastWords(s\"The given path is not compatible with the current platform (JVM).\")\n\nobject PlatformFileSystem:\n  val default: FileSystem = new JavaFileSystem\n"
  },
  {
    "path": "hkmc2/jvm/src/main/scala/hkmc2/io/PlatformPath.scala",
    "content": "package hkmc2\npackage io\n\nimport mlscript.utils._, shorthands._\n\n/**\n * JVM implementation of [[Path]] that wraps [[os.Path]].\n */\nprivate[io] case class WrappedPath(private[io] val underlying: os.Path) extends Path:\n  override def toString: String = underlying.toString\n\n  def last: String = underlying.last\n\n  def baseName: String = underlying.baseName\n\n  def ext: String = underlying.ext\n\n  def up: Path = new WrappedPath(underlying / os.up)\n\n  def /(relPath: RelPath): Path =\n    new WrappedPath(underlying / relPath.asInstanceOf[WrappedRelPath].underlying)\n  \n  def /(fragment: Str): Path =\n    new WrappedPath(underlying / fragment)\n\n  def relativeTo(base: Path): Opt[RelPath] =\n    try S(new WrappedRelPath(underlying.relativeTo(base.asInstanceOf[WrappedPath].underlying)))\n    catch case _: Exception => N\n\n  def segments: Ls[String] = underlying.segments.toList\n\n  def isAbsolute: Bool = underlying.startsWith(os.root)\n\n/**\n * JVM implementation of [[RelPath]] that wraps [[os.RelPath]].\n */\nprivate[io] class WrappedRelPath(private[io] val underlying: os.RelPath) extends RelPath:\n  override def toString: String = underlying.toString\n\n  def segments: Ls[String] = underlying.segments.toList\n\n  def /(other: RelPath): RelPath =\n    new WrappedRelPath(underlying / other.asInstanceOf[WrappedRelPath].underlying)\n\n/**\n * Platform-specific factory for creating Path instances\n */\nprivate[io] object PathFactory:\n  def fromString(str: String) = new WrappedPath(os.Path(str))\n  def separator: String = \"/\"\n  def relPathFromString(str: String) = new WrappedRelPath(os.RelPath(str))\n  def relPathUp = new WrappedRelPath(os.up)\n\n/**\n * JVM-specific utilities for Path conversion\n */\nobject PlatformPath:\n  /** Convert os.Path to io.Path */\n  def fromOsPath(osPath: os.Path): Path = new WrappedPath(osPath)\n\n  /** Convert os.RelPath to io.RelPath */\n  def fromOsRelPath(osRelPath: os.RelPath): RelPath = new WrappedRelPath(osRelPath)\n\n  /** Implicit conversion from os.Path to io.Path (import to use) */\n  given Conversion[os.Path, Path] = fromOsPath\n\n  /** Implicit conversion from os.RelPath to io.RelPath (import to use) */\n  given Conversion[os.RelPath, RelPath] = fromOsRelPath\n"
  },
  {
    "path": "hkmc2/jvm/src/main/scala/hkmc2/utils/PlatformCompilerCache.scala",
    "content": "package hkmc2\npackage utils\n\nimport CompilerCache.Artifact\nimport collection.concurrent.{Map => ConcMap, TrieMap}\nimport mlscript.utils.*, shorthands.*\n\nclass PlatformCompilerCache extends CompilerCache:\n  \n  val elabCache: ConcMap[io.Path, Artifact] = TrieMap.empty\n  \n"
  },
  {
    "path": "hkmc2/jvm/src/test/scala/hkmc2/CompileTestRunner.scala",
    "content": "package hkmc2\n\nimport mlscript.utils._, shorthands._\nimport io.PlatformPath.given\n\n\nclass CompileTestRunner extends CompileTestRunnerBase(\n  compileDirs = TestFolders.mainCompileDirs(os.pwd),\n  excludedDirs = TestFolders.mainExcludedCompileDirs(os.pwd),\n):\n  protected def cctx: CompilerCtx = CompileTestRunner.cctx\n\nend CompileTestRunner\n\n\nobject CompileTestRunner:\n  \n  given cctx: CompilerCtx = CompilerCtx.fresh(io.FileSystem.default)\n  \nend CompileTestRunner\n\n"
  },
  {
    "path": "hkmc2/jvm/src/test/scala/hkmc2/CompileTestRunnerBase.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\nimport org.scalatest.concurrent.{TimeLimitedTests, Signaler}\n\nimport mlscript.utils._, shorthands._\nimport io.PlatformPath.given\n\n\n// Reusable base class for compile test runners. Subclasses provide the\n// directories to scan and the compiler context to use, and this base class\n// handles walking directories, filtering for mlscript-compile files,\n// and registering ScalaTest tests.\nabstract class CompileTestRunnerBase(\n  compileDirs: Ls[os.Path],\n  excludedDirs: Ls[os.Path] = Nil,\n)\n  extends funsuite.AnyFunSuite\n  with ParallelTestExecution\n:\n  \n  given CompilerCtx = cctx\n  \n  protected def cctx: CompilerCtx\n  \n  private val inParallel = isInstanceOf[ParallelTestExecution]\n  \n  val workingDir: os.Path = os.pwd\n  \n  val mainTestDir: os.Path = TestFolders.mainTestDir(workingDir)\n  \n  val validExt = Set(\"mls\")\n  \n  for dir <- compileDirs do {\n    val allFiles = os.walk(dir)\n      .filter(_.toIO.isFile)\n      .filter(_.ext in validExt)\n    \n    lazy val compileTestFiles = allFiles.filter: file =>\n      file.segments.contains(\"mlscript-compile\")\n        && !TestFolders.isExcluded(file, excludedDirs)\n    \n    compileTestFiles.foreach: file =>\n      \n      val basePath = file.segments.drop(dir.segmentCount).toList.init\n      val relativeName = basePath.map(_ + \"/\").mkString + file.baseName\n      \n      test(relativeName):\n        \n        this.synchronized:\n          println(s\"Compiling: $relativeName\")\n        \n        // * Stack safety relies on the fact that runtime uses while loops for resumption\n        // * and does not create extra stack depth. Hence, while loop rewriting should be disabled here.\n        // * (It used to be on by default, but now is off by default, so nothing to do.)\n        given Config = Config.default(mainTestDir)\n        \n        // Synchronize diagnostic output to avoid interleaving since the compiler tests run in parallel.\n        val wrap: (=> Unit) => Unit = body => this.synchronized(body)\n        val report = ReportFormatter(System.out.println, colorize = true, wrap = Some(wrap))\n        val compiler = MLsCompiler(\n          paths = new MLsCompiler.Paths:\n            val preludeFile = mainTestDir / \"mlscript\" / \"decls\" / \"Prelude.mls\"\n            val runtimeFile = mainTestDir / \"mlscript-compile\" / \"Runtime.mjs\"\n            val termFile = mainTestDir / \"mlscript-compile\" / \"Term.mjs\",\n          mkRaise = report.mkRaise\n        )\n        compiler.compileModule(file)\n        \n        if report.badLines.nonEmpty then\n          fail(s\"Unexpected diagnostic at: \" +\n            report.badLines.distinct.sorted\n              .map(\"\\n\\t\"+relativeName+\".\"+file.ext+\":\"+_).mkString(\", \"))\n  }\n\nend CompileTestRunnerBase\n"
  },
  {
    "path": "hkmc2/jvm/src/test/scala/hkmc2/TestFolders.scala",
    "content": "package hkmc2\n\nimport mlscript.utils._, shorthands._\n\n\n/** Centralized definitions of which test directories belong to which SBT project.\n  * Each project specifies the `mlscript/` subdirectories (for diff tests) and the\n  * `mlscript-compile/` subdirectories (for compile tests) that it owns. */\nobject TestFolders:\n  \n  /** Helper to check whether `file` is inside (i.e. a descendant of) `dir`. */\n  def isInDir(file: os.Path, dir: os.Path): Bool =\n    file.startsWith(dir)\n  \n  /** The base test directory: `hkmc2/shared/src/test`. */\n  def mainTestDir(wd: os.Path): os.Path =\n    wd/\"hkmc2\"/\"shared\"/\"src\"/\"test\"\n  \n  /** The diff test directory: `hkmc2/shared/src/test/mlscript`. */\n  def diffTestDir(wd: os.Path): os.Path =\n    mainTestDir(wd)/\"mlscript\"\n  \n  /** The compile test directory: `hkmc2/shared/src/test/mlscript-compile`. */\n  def compileTestDir(wd: os.Path): os.Path =\n    mainTestDir(wd)/\"mlscript-compile\"\n  \n  // ——— Diff test subdirectories excluded from the main DiffTestRunner ———\n  \n  /** Diff test subdirectories that belong to the hkmc2NofibTests project. */\n  def nofibDiffDir(wd: os.Path): os.Path =\n    diffTestDir(wd)/\"nofib\"\n  \n  /** Diff test subdirectories that belong to the hkmc2AppsTests project. */\n  def appsDiffDir(wd: os.Path): os.Path =\n    diffTestDir(wd)/\"apps\"\n  \n  /** Diff test subdirectories that belong to the hkmc2WasmTests project. */\n  def wasmDiffDir(wd: os.Path): os.Path =\n    diffTestDir(wd)/\"wasm\"\n  \n  /** Diff test directories that are always excluded (staging, mlscript-compile). */\n  def alwaysExcludedDiffDirs(wd: os.Path): Ls[os.Path] =\n    (diffTestDir(wd)/\"ucs\"/\"staging\") :: compileTestDir(wd) :: Nil\n  \n  /** All diff test directories excluded from the main DiffTestRunner. */\n  def mainExcludedDiffDirs(wd: os.Path): Ls[os.Path] =\n    nofibDiffDir(wd) ::\n    appsDiffDir(wd) ::\n    wasmDiffDir(wd) ::\n    alwaysExcludedDiffDirs(wd)\n  \n  /** Check whether a file should be excluded from the given list of excluded\n    * directories and/or individual files. */\n  def isExcluded(file: os.Path, excludedDirs: Ls[os.Path]): Bool =\n    excludedDirs.exists(dir => isInDir(file, dir))\n  \n  // ——— Compile test directories ———\n  \n  /** Compile test directories for the main hkmc2JVM project.\n    * We walk from `mainTestDir` so test names include the `mlscript-compile/` prefix. */\n  def mainCompileDirs(wd: os.Path): Ls[os.Path] =\n    mainTestDir(wd) :: Nil\n  \n  /** Directories whose compile files are excluded from the main CompileTestRunner. */\n  def mainExcludedCompileDirs(wd: os.Path): Ls[os.Path] =\n    nofibCompileDirs(wd) ::: appsCompileDirs(wd) ::: wasmCompileDirs(wd)\n  \n  /** Compile test directories for the hkmc2NofibTests project.\n    * We walk from `bench/` so test names include the `mlscript-compile/` prefix. */\n  def nofibCompileDirs(wd: os.Path): Ls[os.Path] =\n    compileTestDir(wd)/\"nofib\" :: Nil\n  \n  /** Compile test directories for the hkmc2AppsTests project.\n    * We walk from `mlscript-compile/apps/` directly. */\n  def appsCompileDirs(wd: os.Path): Ls[os.Path] =\n    compileTestDir(wd)/\"apps\" :: Nil\n  \n  /** Compile test directories for the hkmc2WasmTests project.\n    * We walk from `mainTestDir` so test names include the `mlscript-compile/` prefix.. */\n  def wasmCompileDirs(wd: os.Path): Ls[os.Path] =\n    compileTestDir(wd)/\"wasm\" :: Nil\n  \nend TestFolders\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/CompilerCtx.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\nimport scala.annotation.tailrec\nimport collection.mutable.Map as MutMap\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\nimport hkmc2.Message.MessageContext\nimport hkmc2.io\nimport utils.TraceLogger\n\nimport semantics.*\nimport Elaborator.*\nimport hkmc2.syntax.LetBind\n\n\nimport CompilerCache.*\n\n\nclass CompilerCtx(\n    val importing: Opt[(io.Path, CompilerCtx)],\n    val beingCompiled: Set[io.Path],\n    val fs: io.FileSystem,\n    cache: CompilerCache,\n):\n  \n  def allFilesBeingImported: Ls[io.Path] =\n    importing match\n    case S((path, parent)) => path :: parent.allFilesBeingImported\n    case N => Nil\n  \n  def derive(newFile: io.Path): CompilerCtx =\n    CompilerCtx(S(newFile, this), beingCompiled + newFile, fs, cache)\n  \n  def getElaboratedBlock\n        (file: io.Path, prelude: Ctx)\n        (using TL, Raise, Config)\n        : Artifact =\n    \n    // println(s\"Cache has: ${cache.elabCache.contains(file)} ${cache.elabCache.keys}\")\n    \n    // * FIXME:\n    // * This is not quite correct, but might be good enough for now\n    // * (to be fixed when we overhaul the symbol and elaboration systems).\n    // * The problem is that different modules will see different builtin symbols\n    // * for things like `unitSymbol` and `termSymbol`, which could in theory cause problems\n    // * if the compiler later wants to compare them as part of the type checking/compilation/optimization logic.\n    // * Technically, we should also have the same problem with the symbols loaded from the prelude,\n    // * which are passed on to imported modules from the first importer\n    // * (and the \"first importer\" is nondeterministic, due to concurrent tests),\n    // * and since the imported modules are cached,\n    // * this means subsequent importers will not have see same prelude symbols.\n    // * The correct approach should be to only cache a *single* State and prelude Ctx at the start,\n    // * and reuse it for every compilation unit (each compilation unit duplicating the root State).\n    given Elaborator.State = new Elaborator.State\n    \n    val lastMod = fs.getLastChangedTimestamp(file)\n    \n    def mk =\n      val parse =\n        given CompilerCtx = this\n        ParserSetup(file, dbgParsing = false)\n      val resBlk = parse.resultBlk\n      given Elaborator.Ctx = prelude.copy(mode = Mode.Light).nestLocal(\"prelude\")\n      val elab =\n        given CompilerCtx = derive(parse.origin.fileName)\n        Elaborator(tl, file.up, prelude)\n      val elabbed = elab.importFrom(resBlk)\n      Artifact(resBlk, elabbed._1, lastMod)\n    \n    cache.upsert(file):\n      case N => mk\n      case cur @ S(art) =>\n        if art.lastChangedTimestamp < lastMod then mk\n        else art\n  \n  \nobject CompilerCtx:\n  \n  inline def get(using cctx: CompilerCtx) = cctx\n  \n  def fresh(fs: io.FileSystem): CompilerCtx = CompilerCtx(N, Set.empty, fs, new PlatformCompilerCache)\n  \nend CompilerCtx\n\n\n\nobject CompilerCache:\n  \n  class Artifact(val tree: syntax.Tree.Block, val term: semantics.Term.Blk, val lastChangedTimestamp: Long)\n  \nend CompilerCache\n\n\ntrait CompilerCache:\n  // TODO also use hash comparison to avoid needless re-parses?\n  \n  def elabCache: MutMap[io.Path, Artifact]\n  \n  /** Create or update an artifact at the given path in the cache. */\n  def upsert(path: io.Path)(update: Option[Artifact] => Artifact): Artifact =\n    elabCache\n      .updateWith(path):\n        case N => S(update(N))\n        case cur @ S(oldArt) =>\n          val newArt = update(cur)\n          if newArt is oldArt then cur else S(newArt)\n      .get // * above, we always returns Some\n  \nend CompilerCache\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/Config.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport Config.*\nimport Message.MessageContext\n\n\n/** The compilation target of a program. */\nenum CompilationTarget:\n  case JS\n  case Wasm\n\n\ndef config(using Config): Config = summon\n\ntype Cfg[A] = Config ?=> A\n\ncase class Config(\n  baseDir: io.Path,\n  sanityChecks: Opt[SanityChecks],\n  effectHandlers: Opt[EffectHandlers],\n  liftDefns: Opt[LiftDefns],\n  patMatConsequentSharingThreshold: Opt[Int],\n  stageCode: Bool,\n  target: CompilationTarget,\n  rewriteWhileLoops: Bool,\n  tailRecOpt: Bool,\n  deforest: Opt[Deforest],\n  inlining: Opt[Inliner],\n  qqEnabled: Bool,\n  funcToCls: Bool,\n  commentGeneratedCode: Bool,\n  noFreeze: Bool,\n  noModuleCheck: Bool,\n  deadParamElim: Opt[DeadParamElim],\n):\n  \n  def stackSafety: Opt[StackSafety] = effectHandlers.flatMap(_.stackSafety)\n\n  def checkInstantiateEffect: Bool = effectHandlers.exists(_.checkInstantiateEffect)\n  \n  // NOTE: We force the rewriting of while loops to functions when handler lowering is on\n  // to prevent the \"floating out\" of definitions done by handler lowering,\n  // which currently does not respect scopes introduced by `Scoped` blocks.\n  // Currently, this is only a problem with while loops because we do not yet\n  // construct nested Scoped blocks in other places (but will in the future).\n  // see https://github.com/hkust-taco/mlscript/pull/356#discussion_r2579529893\n  // and https://github.com/hkust-taco/mlscript/pull/356#discussion_r2585183902\n  def shouldRewriteWhile: Bool =\n    rewriteWhileLoops || effectHandlers.isDefined\n  \nend Config\n\n\nobject Config:\n  \n  def default(baseDir: io.Path): Config = Config(\n    baseDir = baseDir,\n    sanityChecks = N, // TODO make the default S\n    // sanityChecks = S(SanityChecks(light = true)),\n    effectHandlers = N,\n    liftDefns = N,\n    patMatConsequentSharingThreshold = default.patMatConsequentSharingThreshold, // minimum: 1\n    target = CompilationTarget.JS,\n    rewriteWhileLoops = false,\n    stageCode = false,\n    tailRecOpt = true,\n    deforest = N,\n    inlining = S(Inliner(1)),\n    qqEnabled = false,\n    funcToCls = false,\n    commentGeneratedCode = false,\n    noFreeze = false,\n    noModuleCheck = false,\n    deadParamElim = S(DeadParamElim.default)\n  )\n  object default:\n    val patMatConsequentSharingThreshold = S(15)\n  \n  case class SanityChecks(light: Bool)\n  \n  case class EffectHandlers(\n    debug: Bool,\n    stackSafety: Opt[StackSafety],\n    // Whether we check `Instantiate` nodes for effects. Currently, effects cannot be raised in constructors.\n    checkInstantiateEffect: Bool = false,\n    // A debug option that allows codegen to continue even if an unlifted definition is encountered.\n    softLifterError: Bool = false,\n    // Skips instrumenting module constructors, this can be used when the file is statically known to not\n    // raise any effect and cannot use the Runtime.mls module during module construction due to cyclic dependency.\n    // One specific scenario is Rendering.mls, which Runtime.mls depends on, and hence using stack safety will\n    // reference Runtime.mls during construction of the Rendering module, causing a cyclic dependency error.\n    doNotInstrumentTopLevelModCtor: Bool = false,\n  )\n  \n  case class StackSafety(stackLimit: Int)\n  object StackSafety:\n    val default: StackSafety = StackSafety(\n      stackLimit = 1000,\n    )\n  \n  case class LiftDefns() // there may be other settings in the future, having it as a case class now\n  \n  case class Deforest(val debug: Boolean, val mono: Boolean)\n  object Deforest:\n    val default = Deforest(true, false)\n\n  case class DeadParamElim(val debug: Boolean, val mono: Boolean)\n  object DeadParamElim:\n    val default = DeadParamElim(false, true)\n  \n  case class Inliner(inlineThreshold: Int)\n\n  def extractConfigFromStats(prgm: semantics.Term.Blk)(using Config) =\n    // Extract cumulative config modifications from SetConfig statements\n    val configModify = prgm.stats.collect:\n      case sc: semantics.SetConfig => sc.modify\n    .foldLeft(identity[Config]): (acc, modify) =>\n      cfg => modify(acc(cfg))\n    configModify(config)\n\nend Config\n\n\nobject ConfigParser:\n  import syntax.Tree\n  import syntax.Tree.*\n  import syntax.Keyword\n  \n  /** Parse a list of config override arguments (from the Tup tree) into a Config modification function. */\n  def parseOverrides(args: Ls[Tree])(using Raise): Config => Config =\n    args.foldLeft(identity[Config]): (acc, arg) =>\n      val override_ = parseOverride(arg)\n      cfg => override_(acc(cfg))\n  \n  /** Parse a single config override argument. */\n  def parseOverride(arg: Tree)(using Raise): Config => Config = arg match\n    case InfixApp(Ident(name), Keywrd(Keyword.`:`), value) =>\n      parseField(name, value)\n    case _ =>\n      raise(ErrorReport(\n        msg\"Unsupported config override syntax\" -> arg.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      identity\n  \n  private def parseBool(tree: Tree)(using Raise): Opt[Bool] = tree match\n    case BoolLit(v) => S(v)\n    case Ident(\"true\") => S(true)\n    case Ident(\"false\") => S(false)\n    case _ =>\n      raise(ErrorReport(\n        msg\"Expected a boolean value\" -> tree.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      N\n  \n  private def parseInt(tree: Tree)(using Raise): Opt[Int] = tree match\n    case IntLit(v) => S(v.toInt)\n    case App(Ident(\"-\"), Tup(IntLit(v) :: Nil)) => S(-v.toInt)\n    case _ =>\n      raise(ErrorReport(\n        msg\"Expected an integer value\" -> tree.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      N\n\n  /** Parse the `None`/`Some(...)` syntax for optional config fields.\n    * Also accepts unwrapped values as a convenience (treated as `Some(value)`). */\n  private def parseOpt[A](tree: Tree)(parseInner: Tree => Opt[A])(using Raise): Opt[Opt[A]] = tree match\n    case Ident(\"None\") | Ident(\"N\") =>\n      S(N)\n    case App(Ident(\"Some\") | Ident(\"S\"), Tup(inner :: Nil)) =>\n      parseInner(inner).map(v => S(v))\n    case other =>\n      parseInner(other).map(v => S(v))\n  \n  private def parseStackSafety(tree: Tree)(using Raise): Opt[Config.StackSafety] = tree match\n    case App(Ident(\"StackSafety\"), Tup(args)) =>\n      var stackLimit = Config.StackSafety.default.stackLimit\n      args.foreach:\n        case InfixApp(Ident(\"stackLimit\"), Keywrd(Keyword.`:`), value) =>\n          parseInt(value).foreach(v => stackLimit = v)\n        case IntLit(v) =>\n          stackLimit = v.toInt\n        case other =>\n          raise(ErrorReport(\n            msg\"Unsupported StackSafety argument\" -> other.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation))\n      S(Config.StackSafety(stackLimit))\n    case IntLit(v) =>\n      S(Config.StackSafety(v.toInt))\n    case _ =>\n      raise(ErrorReport(\n        msg\"Expected StackSafety(...) or an integer\" -> tree.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      N\n  \n  private def parseEffectHandlers(tree: Tree, current: Opt[Config.EffectHandlers])(using Raise): Opt[Config.EffectHandlers] = tree match\n    case App(Ident(\"EffectHandlers\"), Tup(args)) =>\n      val base = current.getOrElse(Config.EffectHandlers(debug = false, stackSafety = N))\n      var debug = base.debug\n      var stackSafety = base.stackSafety\n      var checkInstantiateEffect = base.checkInstantiateEffect\n      var softLifterError = base.softLifterError\n      var doNotInstrumentTopLevelModCtor = base.doNotInstrumentTopLevelModCtor\n      args.foreach:\n        case InfixApp(Ident(\"debug\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => debug = v)\n        case InfixApp(Ident(\"stackSafety\"), Keywrd(Keyword.`:`), value) =>\n          parseOpt(value)(parseStackSafety).foreach(v => stackSafety = v)\n        case InfixApp(Ident(\"checkInstantiateEffect\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => checkInstantiateEffect = v)\n        case InfixApp(Ident(\"softLifterError\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => softLifterError = v)\n        case InfixApp(Ident(\"doNotInstrumentTopLevelModCtor\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => doNotInstrumentTopLevelModCtor = v)\n        case other =>\n          raise(ErrorReport(\n            msg\"Unsupported EffectHandlers argument\" -> other.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation))\n      S(Config.EffectHandlers(debug, stackSafety, checkInstantiateEffect, softLifterError, doNotInstrumentTopLevelModCtor))\n    case _ =>\n      raise(ErrorReport(\n        msg\"Expected EffectHandlers(...)\" -> tree.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      N\n\n  private def parseDeforest(tree: Tree, current: Opt[Config.Deforest])(using Raise): Opt[Config.Deforest] = tree match\n    case BoolLit(true) | Ident(\"true\") | Ident(\"Deforest\") =>\n      S(current.getOrElse(Config.Deforest.default))\n    case App(Ident(\"Deforest\"), Tup(args)) =>\n      val base = current.getOrElse(Config.Deforest.default)\n      var debug = base.debug\n      var mono = base.mono\n      args.foreach:\n        case InfixApp(Ident(\"debug\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => debug = v)\n        case InfixApp(Ident(\"mono\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => mono = v)\n        case other =>\n          raise(ErrorReport(\n            msg\"Unsupported Deforest argument\" -> other.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation))\n      S(Config.Deforest(debug, mono))\n    case _ =>\n      raise(ErrorReport(\n        msg\"Expected Deforest(...), Deforest, or true\" -> tree.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      N\n\n  private def parseDeadParamElim(tree: Tree, current: Opt[Config.DeadParamElim])(using Raise): Opt[Config.DeadParamElim] = tree match\n    case BoolLit(true) | Ident(\"true\") | Ident(\"DeadParamElim\") =>\n      S(current.getOrElse(Config.DeadParamElim.default))\n    case App(Ident(\"DeadParamElim\"), Tup(args)) =>\n      val base = current.getOrElse(Config.DeadParamElim.default)\n      var debug = base.debug\n      var mono = base.mono\n      args.foreach:\n        case InfixApp(Ident(\"debug\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => debug = v)\n        case InfixApp(Ident(\"mono\"), Keywrd(Keyword.`:`), value) =>\n          parseBool(value).foreach(v => mono = v)\n        case other =>\n          raise(ErrorReport(\n            msg\"Unsupported DeadParamElim argument\" -> other.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation))\n      S(Config.DeadParamElim(debug, mono))\n    case _ =>\n      raise(ErrorReport(\n        msg\"Expected DeadParamElim(...), DeadParamElim, or true\" -> tree.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      N\n  \n  /** Parse a single field override like `tailRecOpt: false`. */\n  private def parseField(name: Str, value: Tree)(using Raise): Config => Config = name match\n    case \"tailRecOpt\" => parseBool(value) match\n      case S(v) => _.copy(tailRecOpt = v)\n      case N => identity\n    case \"noFreeze\" => parseBool(value) match\n      case S(v) => _.copy(noFreeze = v)\n      case N => identity\n    case \"noModuleCheck\" => parseBool(value) match\n      case S(v) => _.copy(noModuleCheck = v)\n      case N => identity\n    case \"rewriteWhileLoops\" => parseBool(value) match\n      case S(v) => _.copy(rewriteWhileLoops = v)\n      case N => identity\n    case \"stageCode\" => parseBool(value) match\n      case S(v) => _.copy(stageCode = v)\n      case N => identity\n    case \"qqEnabled\" => parseBool(value) match\n      case S(v) => _.copy(qqEnabled = v)\n      case N => identity\n    case \"funcToCls\" => parseBool(value) match\n      case S(v) => _.copy(funcToCls = v)\n      case N => identity\n    case \"commentGeneratedCode\" => parseBool(value) match\n      case S(v) => _.copy(commentGeneratedCode = v)\n      case N => identity\n    case \"effectHandlers\" =>\n      cfg =>\n        parseOpt(value)(v => parseEffectHandlers(v, cfg.effectHandlers)) match\n          case S(v) => cfg.copy(effectHandlers = v)\n          case N => cfg\n    case \"liftDefns\" =>\n      parseOpt(value)(_ => S(Config.LiftDefns())) match\n        case S(v) => _.copy(liftDefns = v)\n        case N => identity\n    case \"deforest\" =>\n      cfg =>\n        parseOpt(value)(v => parseDeforest(v, cfg.deforest)) match\n          case S(v) => cfg.copy(deforest = v)\n          case N => cfg\n    case \"deadParamElim\" =>\n      cfg =>\n        parseOpt(value)(v => parseDeadParamElim(v, cfg.deadParamElim)) match\n          case S(v) => cfg.copy(deadParamElim = v)\n          case N => cfg\n    case \"sanityChecks\" =>\n      parseOpt(value)(_ => S(Config.SanityChecks(light = true))) match\n        case S(v) => _.copy(sanityChecks = v)\n        case N => identity\n    case \"patMatConsequentSharingThreshold\" =>\n      parseInt(value) match\n        case S(v) => _.copy(patMatConsequentSharingThreshold = S(v))\n        case N => identity\n    case \"inlining\" =>\n      parseOpt(value)(parseInt) match\n        case S(v) => _.copy(inlining = v.map(Inliner.apply))\n        case _ => identity\n    case _ =>\n      raise(ErrorReport(\n        msg\"Unknown config field '${name}'\" -> value.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation))\n      identity\nend ConfigParser\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/Diagnostic.scala",
    "content": "package hkmc2\n\nimport scala.util.chaining._\nimport sourcecode.{Name, Line, FileName}\n\nimport mlscript.utils._, shorthands._\nimport hkmc2.io\n\nimport Diagnostic._\n\nsealed abstract class Diagnostic\n      (val theMsg: String)\n      (using val srcLine: Line, val srcName: Name, val srcFile: FileName)\n    extends Exception(theMsg):\n  val allMsgs: Ls[Message -> Opt[Loc]]\n  val kind: Kind\n  val source: Source\n  val mkExtraInfo: () => Opt[Any]\n  def srcLoc: Str = s\"${srcName.value} (${srcFile.value}:${srcLine.value})\"\nobject Diagnostic:\n  \n  enum Kind:\n    case Error\n    case Warning\n    case Internal\n  \n  enum Source:\n    case Lexing\n    case Parsing\n    case Typing\n    case Compilation\n    case Runtime\n  \n\nfinal case class ErrorReport(\n    mainMsg: Str,\n    allMsgs: Ls[Message -> Opt[Loc]],\n    mkExtraInfo: () => Opt[Any],\n    source: Source,\n)(using Line, Name, FileName) extends Diagnostic(mainMsg):\n  val kind: Kind = Kind.Error\nobject ErrorReport:\n  def apply(using Line, FileName)\n      (msgs: Ls[Message -> Opt[Loc]], extraInfo: => Opt[Any] = N, source: Source = Source.Compilation)\n      (using Name): ErrorReport =\n    ErrorReport(msgs.head._1.show, msgs, () => extraInfo, source)\n\nfinal case class WarningReport(\n    mainMsg: Str,\n    allMsgs: Ls[Message -> Opt[Loc]],\n    mkExtraInfo: () => Opt[Any],\n    source: Source,\n)(using Line, Name, FileName) extends Diagnostic(mainMsg):\n  val kind: Kind = Kind.Warning\nobject WarningReport:\n  def apply(using Line, FileName)\n      (msgs: Ls[Message -> Opt[Loc]], extraInfo: => Opt[Any] = N, source: Source = Source.Compilation)\n      (using Name): WarningReport =\n    WarningReport(msgs.head._1.show, msgs, () => extraInfo, source)\n\nfinal case class InternalError(\n    mainMsg: Str,\n    allMsgs: Ls[Message -> Opt[Loc]],\n    mkExtraInfo: () => Opt[Any],\n    source: Source\n)(using Line, Name, FileName) extends Diagnostic(mainMsg):\n  val kind: Kind = Kind.Internal\nobject InternalError:\n  def apply(using Line, FileName)\n      (msgs: Ls[Message -> Opt[Loc]], extraInfo: => Opt[Any] = N, source: Source = Source.Compilation)\n      (using Name): InternalError =\n    InternalError(msgs.head._1.show, msgs, () => extraInfo, source)\n\n\nfinal case class Loc(spanStart: Int, spanEnd: Int, origin: Origin):\n  assert(spanStart >= 0)\n  assert(spanEnd >= spanStart)\n  def covers(that: Loc): Bool = that.origin === this.origin && (\n    that.spanStart >= this.spanStart && that.spanEnd <= this.spanEnd\n  )\n  def touches(that: Loc): Bool = that.origin === this.origin && (\n    that.spanStart >= this.spanStart && that.spanStart <= this.spanEnd\n    || that.spanEnd <= this.spanEnd && that.spanEnd >= this.spanStart\n  )\n  def ++(that: Loc): Loc =\n    require(this.origin is that.origin)\n    Loc(this.spanStart min that.spanStart, this.spanEnd max that.spanEnd, origin)\n  def ++(that: Opt[Loc]): Loc = that.fold(this)(this ++ _)\n  def right: Loc = copy(spanStart = spanEnd)\n  def left: Loc = copy(spanEnd = spanStart)\nobject Loc:\n  def apply(xs: Located*): Opt[Loc] =\n    apply(xs.iterator)\n  def apply(xs: IterableOnce[Located]): Opt[Loc] =\n    xs.iterator.foldLeft(none[Loc])((acc, l) => acc.fold(l.toLoc)(_ ++ l.toLoc |> some))\n\nfinal case class Origin(fileName: io.Path, startLineNum: Int, fph: FastParseHelpers):\n  override def toString = s\"${fileName.last}:+$startLineNum\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/MLsCompiler.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.io\nimport utils.*\n\nimport hkmc2.semantics.*\nimport hkmc2.syntax.Keyword.`override`\nimport semantics.Elaborator.{Ctx, State}\n\n\nclass ParserSetup(file: io.Path, dbgParsing: Bool)(using state: Elaborator.State, raise: Raise, cctx: CompilerCtx):\n  \n  val block = cctx.fs.read(file)\n  val fph = new FastParseHelpers(block)\n  val origin = Origin(file, 0, fph)\n  \n  val lexer = new syntax.Lexer(origin, dbg = dbgParsing)\n  val tokens = lexer.bracketedTokens\n  \n  // if showParse.isSet || dbgParsing.isSet then\n  //   output(syntax.Lexer.printTokens(tokens))\n  \n  val rules = syntax.ParseRules()\n  val parser = new syntax.Parser(origin, tokens, rules, raise, dbg = dbgParsing):\n    def doPrintDbg(msg: => Str): Unit =\n      // if dbg then output(msg)\n      if dbg then println(msg)\n  \n  val result = parser.parseAll(parser.block(allowNewlines = true))\n  \n  val resultBlk = new syntax.Tree.Block(result)\n\nobject MLsCompiler:\n  /** The class contains the necessary paths to files for the MLscript compiler. */\n  trait Paths:\n    def preludeFile: io.Path\n    def runtimeFile: io.Path\n    def termFile: io.Path\n\n/**\n  * The compiler that compiles MLscript code into JavaScript modules.\n  *\n  * @param paths required paths needed by the compiler\n  * @param mkRaise generates a separate `Raise` function for each file.\n  * @param config the compiler's configuration object\n  * @param fs the file system interface\n  */\nclass MLsCompiler\n    (paths: MLsCompiler.Paths, mkRaise: io.Path => Raise)\n    (using cctx: CompilerCtx, config: Config):\n  import paths.*\n  \n  \n  \n  // TODO adapt logic\n  given DebugPrinter = new DebugPrinter\n  val etl = new TraceLogger{override def doTrace: Bool = false}\n  val ltl = new TraceLogger{override def doTrace: Bool = false}\n  // val ltl = new TraceLogger{override def doTrace: Bool = true}\n  val rtl = new TraceLogger{override def doTrace: Bool = false}\n  \n  \n  var dbgParsing = false\n  var dbgElab = false\n  \n  \n  def compileModule(file: io.Path): Unit =\n    \n    val wd = file.up\n    \n    given Raise = mkRaise(file)\n    \n    given Elaborator.State = new Elaborator.State:\n      override def dbg: Bool = dbgElab\n    \n    val preludeParse = ParserSetup(preludeFile, dbgParsing)\n    val mainParse = ParserSetup(file, dbgParsing)\n    \n    val elab = Elaborator(etl, wd, Ctx.empty)\n    \n    val initState = State.init.nestLocal(\"prelude\")\n    \n    val (pblk, newCtx) = elab.importFrom(preludeParse.resultBlk)(using initState)\n    \n    newCtx.nestLocal(\"file:\"+file.baseName).givenIn:\n      given CompilerCtx = cctx.derive(file)\n      val elab = Elaborator(etl, wd, newCtx)\n      val parsed = mainParse.resultBlk\n      val (blk0, _) = elab.importFrom(parsed)\n      Config.extractConfigFromStats(blk0).givenIn {\n      val resolver = Resolver(rtl)\n      resolver.traverseBlock(blk0)(using Resolver.ICtx.empty)\n      def findQuote(t: semantics.Statement): Bool = t match\n        case Term.Quoted(_) | Term.Unquoted(_) => true\n        case Term.Ref(sym) => sym === State.termSymbol\n        case _ => t.subTerms.exists(findQuote)\n      val hasQuote = findQuote(blk0)\n      val blk = new Term.Blk(\n        Import(State.runtimeSymbol, runtimeFile.toString, runtimeFile) ::\n          // Only import `Term.mls` when necessary.\n          (if hasQuote then\n            Import(State.termSymbol, termFile.toString, termFile) :: blk0.stats\n          else\n            blk0.stats),\n        blk0.res\n      )\n      val low = ltl.givenIn:\n        new codegen.Lowering()\n          with codegen.LoweringSelSanityChecks\n      val jsb = ltl.givenIn:\n        codegen.js.JSBuilder()\n      val le_0 = low.program(blk)\n      val nme = file.baseName\n      val exportedSymbol = parsed.definedSymbols.find(_._1 === nme).map(_._2)\n      val le_1 = ltl.givenIn:\n        codegen.BlockSimplifier(exportedSymbol.toSet)(le_0)\n      val le_2 = ltl.givenIn:\n        codegen.DeadParamElim(le_1)\n      val baseScp: utils.Scope =\n        utils.Scope.empty(utils.Scope.Cfg.default)\n      // * This line serves for `import.meta.url`, which retrieves directory and file names of mjs files.\n      // * Having `module id\"import\" with ...` in `prelude.mls` will generate `globalThis.import` that is undefined.\n      baseScp.addToBindings(Elaborator.State.importSymbol, \"import\", shadow = false)\n      val nestedScp = baseScp.nest\n      val je = nestedScp.givenIn:\n        jsb.program(le_2, exportedSymbol, wd)\n      val jsStr = je.stripBreaks.mkString(100)\n      val out = file.up / io.RelPath(file.baseName + \".mjs\")\n      cctx.fs.write(out, jsStr)\n      }\n  \n  \nend MLsCompiler\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/Message.scala",
    "content": "package hkmc2\n\nimport scala.language.implicitConversions\nimport mlscript.utils._, shorthands._\n\nfinal case class Message(bits: Ls[Message.Bit]):\n  def show: Str =\n    val ctx = ShowCtx.mk(typeBits)\n    showIn(using ctx)\n  def typeBits: Ls[TypeLike] = bits.collect{ case Message.Code(t) => t }\n  def showIn(implicit ctx: ShowCtx): Str =\n    bits.map {\n      case Message.Code(ty) => ty.showIn(0)\n      case Message.Text(txt) => txt\n    }.mkString\n  def showDbg: Str =\n    bits.iterator.map {\n      case Message.Code(trm) => s\"$trm\"\n      case Message.Text(txt) => txt\n    }.mkString\n  def +(that: Message): Message = Message(bits ++ that.bits)\nobject Message:\n  \n  def mkCtx(msgs: IterableOnce[Message],pre: Str = \"'\"): ShowCtx =\n    ShowCtx.mk(msgs.iterator.flatMap(_.typeBits), pre)\n  \n  def join(msgs: Seq[Message]): Message = Message(msgs.iterator.flatMap(_.bits).toList)\n  \n  sealed abstract class Bit\n  final case class Text(str: Str) extends Bit\n  final case class Code(ty: TypeLike) extends Bit\n  implicit def fromType(ty: TypeLike): Message = Message(Code(ty) :: Nil)\n  implicit def fromStr(str: Str): Message = Message(Text(str) :: Nil)\n  implicit def fromInt(int: Int): Message = Message(Text(int.toString) :: Nil)\n  \n  implicit class MessageContext(private val ctx: StringContext):\n    def msg(inserted: Message*): Message =\n      assert(inserted.length === ctx.parts.length - 1)\n      val parts = ctx.parts.map(str => Text(StringContext(str).s()))\n      val h = parts.head\n      val t = parts.tail\n      Message((h +: inserted.lazyZip(t).flatMap(_.bits :+ _)).toList)\n  \n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/ShowCtx.scala",
    "content": "package hkmc2\n\nimport scala.util.chaining._\nimport scala.collection.mutable.{Map => MutMap, SortedMap => SortedMutMap, Set => MutSet, Buffer}\nimport scala.collection.immutable.SortedMap\n\nimport math.Ordered.orderingToOrdered\n\nimport mlscript.utils._, shorthands._\n\n\nfinal case class ShowCtx(\n    vs: SortedMap[TypeVar, Str],\n    indentLevel: Int,\n    angletards: Bool = false,\n  )\n:\n  lazy val indStr: Str = ShowCtx.indentation * indentLevel\n  def lnIndStr: Str = \"\\n\" + indStr\n  def indent: ShowCtx = copy(indentLevel = indentLevel + 1)\n  def < : Str = if angletards then \"<\" else \"[\"\n  def > : Str = if angletards then \">\" else \"]\"\nobject ShowCtx:\n  val ExtrusionPrefix: Str = \"??\"\n  \n  def indentation: Str = \"  \"\n  /**\n    * Create a context from a list of types. For named variables and\n    * hinted variables use what is given. For unnamed variables generate\n    * completely new names. If same name exists increment counter suffix\n    * in the name.\n    */\n  def mk(tys: IterableOnce[TypeLike], _pre: Str = \"'\"): ShowCtx =\n    val (otherVars, namedVars) = tys.iterator.toList.flatMap(_.typeVarsList).distinct.partitionMap { tv =>\n      tv.identifier match { case L(_) => L(tv.nameHint -> tv); case R(nh) => R(nh -> tv) }\n    }\n    val (hintedVars, unnamedVars) = otherVars.partitionMap:\n      case (S(nh), tv) => L(nh -> tv)\n      case (N, tv) => R(tv)\n    val usedNames = MutMap.empty[Str, Int]\n    def assignName(n: Str): Str =\n      val pre = if n.startsWith(\"'\") || n.startsWith(ExtrusionPrefix) then \"\" else _pre\n      usedNames.get(n) match\n        case S(cnt) =>\n          usedNames(n) = cnt + 1\n          pre + \n          n + cnt\n        case N =>\n          usedNames(n) = 0\n          pre + \n          n\n    val namedMap = (namedVars ++ hintedVars).map { case (nh, tv) =>\n      // tv -> assignName(nh.dropWhile(_ === '\\''))\n      tv -> assignName(nh.stripPrefix(_pre))\n    }.toSortedMap\n    val used = usedNames.keySet\n    \n    // * Generate names for unnamed variables\n    val numLetters = 'z' - 'a' + 1\n    val names = Iterator.unfold(0) { idx =>\n      val postfix = idx/numLetters\n      S(('a' + idx % numLetters).toChar.toString + (if postfix === 0 then \"\" else postfix.toString), idx + 1)\n    }.filterNot(used).map(assignName)\n    \n    ShowCtx(namedMap ++ unnamedVars.zip(names), indentLevel = 0)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/Uid.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\n\nopaque type Uid[T] = Int\n\nobject Uid:\n  class Handler[T]:\n    class State:\n      private var curUid = -1\n      def nextUid: Uid[T] =\n        curUid += 1\n        curUid\n      def reset = curUid = -1\n  object Symbol extends Handler[semantics.Symbol]\n  object Result extends Handler[codegen.Result]\n  object StratVar extends Handler[codegen.flowAnalysis.StratVar]\n\nextension [T] (x: Uid[T])\n  def <=(rhs: Uid[T]) = x <= rhs\n\nprivate val ord = Ordering.Int\ngiven [A]: Ordering[Uid[A]] = ord\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/Block.scala",
    "content": "package hkmc2\npackage codegen\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.Message.MessageContext\n\nimport hkmc2.{semantics => sem}\nimport hkmc2.semantics.{Term => st}\n\nimport syntax.{Literal, Tree, SpreadKind, Keyword}\nimport semantics.*\nimport semantics.Term.*\nimport sem.Elaborator.State\n\n\ncase class Program(\n  imports: Ls[Local -> Str],\n  main: Block,\n)\n\n\nsealed abstract class Block extends Product:\n  \n  def ~(that: Block): Block = Begin(this, that)\n  \n  def isEmpty: Bool = this match\n    case _: End => true\n    case _ => false\n  \n  lazy val isAbortive: Bool = this match\n    case _: End => false\n    case _: Throw | _: Break | _: Continue | _: Unreachable => true\n    case ret: Return => !ret.implct\n    case Begin(sub, rst) => sub.isAbortive || rst.isAbortive\n    case Assign(_, _, rst) => rst.isAbortive\n    case AssignField(_, _, _, rst) => rst.isAbortive\n    case AssignDynField(_, _, _, _, rst) => rst.isAbortive\n    case Match(_, arms, dflt, rst) => rst.isAbortive || arms.forall(_._2.isAbortive) && dflt.exists(_.isAbortive)\n    case Define(_, rst) => rst.isAbortive\n    case TryBlock(sub, fin, rst) => rst.isAbortive || sub.isAbortive || fin.isAbortive\n    case Label(sym, loop, bod, rst) =>\n      // * Note: the body may be abortive for the reason of breaking to the rest!\n      // * So we can't really use the result of bod.isAbortive even when `loop` is false.\n      rst.isAbortive\n    case Scoped(_, body) => body.isAbortive\n  \n  // * Note: it seems most historical uses of `definedVars` would be better removed,\n  // * now that we properly put everything in proper Scoped blocks;\n  // * and `definedVars` itself should be removed.\n  lazy val definedVars: Set[Local] = this match\n    case _: Return | _: Throw | _: Unreachable => Set.empty\n    case Begin(sub, rst) => sub.definedVars ++ rst.definedVars\n    case Assign(l: TermSymbol, r, rst) => rst.definedVars\n    case Assign(l, r, rst) => rst.definedVars + l\n    case AssignField(l, n, r, rst) => rst.definedVars\n    case AssignDynField(l, n, ai, r, rst) => rst.definedVars\n    case Match(scrut, arms, dflt, rst) =>\n      arms.flatMap(_._2.definedVars).toSet ++ dflt.toList.flatMap(_.definedVars) ++ rst.definedVars\n    case End(_) => Set.empty\n    case Break(_) => Set.empty\n    case Continue(_) => Set.empty\n    case Define(defn, rst) =>\n      val rest = rst.definedVars\n      if defn.isOwned then rest else rest + defn.sym\n    case TryBlock(sub, fin, rst) => sub.definedVars ++ fin.definedVars ++ rst.definedVars\n    case Label(lbl, _, bod, rst) => bod.definedVars ++ rst.definedVars\n    case Scoped(syms, body) => body.definedVars ++ syms\n  \n  lazy val size: Int = this match\n    case _: Return | _: Throw | _: End | _: Break | _: Continue | _: Unreachable => 1\n    case Begin(sub, rst) => sub.size + rst.size\n    case Assign(_, _, rst) => 1 + rst.size\n    case AssignField(_, _, _, rst) => 1 + rst.size\n    case AssignDynField(_, _, _, _, rst) => 1 + rst.size\n    case Match(_, arms, dflt, rst) =>\n      1 + arms.map(_._2.size).sum + dflt.map(_.size).getOrElse(0) + rst.size\n    case Define(_, rst) => 1 + rst.size\n    case TryBlock(sub, fin, rst) => 1 + sub.size + fin.size + rst.size\n    case Label(_, _, bod, rst) => 1 + bod.size + rst.size\n    case Scoped(_, body) => body.size\n  \n  \n  // TODO: make patmat use unreach\n  \n  def mapReturn(f: Return => Block): Block =\n    new BlockTransformerShallow(SymbolSubst.Id):\n      override def applyBlock(b: Block): Block = b match\n        case ret: Return => f(ret)\n        case _ => super.applyBlock(b)\n    .applyBlock(this)\n  \n  lazy val freeVars: Set[Local] = this match\n    case Match(scrut, arms, dflt, rest) =>\n      scrut.freeVars ++ dflt.toList.flatMap(_.freeVars) ++ rest.freeVars\n      ++ arms.flatMap:\n        (pat, arm) => arm.freeVars -- pat.freeVars\n    case Return(res, implct) => res.freeVars\n    case Throw(exc) => exc.freeVars\n    case Label(label, _, body, rest) => (body.freeVars - label) ++ rest.freeVars \n    case Break(label) => Set.single(label)\n    case Continue(label) => Set.single(label)\n    case Begin(sub, rest) => sub.freeVars ++ rest.freeVars\n    case TryBlock(sub, finallyDo, rest) => sub.freeVars ++ finallyDo.freeVars ++ rest.freeVars\n    case Assign(lhs, rhs, rest) => Set.single(lhs) ++ rhs.freeVars ++ rest.freeVars\n    case AssignField(lhs, nme, rhs, rest) => lhs.freeVars ++ rhs.freeVars ++ rest.freeVars\n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) => lhs.freeVars ++ fld.freeVars ++ rhs.freeVars ++ rest.freeVars\n    case Define(defn, rest) => defn.freeVars ++ rest.freeVars\n    case Scoped(syms, body) => body.freeVars\n    case End(msg) => Set.empty\n    case Unreachable(msg) => Set.empty\n  \n  lazy val freeVarsLLIR: Set[Local] = this match\n    case Match(scrut, arms, dflt, rest) =>\n      scrut.freeVarsLLIR ++ dflt.toList.flatMap(_.freeVarsLLIR) ++ rest.freeVarsLLIR\n      ++ arms.flatMap:\n        (pat, arm) => arm.freeVarsLLIR -- pat.freeVarsLLIR\n    case Return(res, implct) => res.freeVarsLLIR\n    case Throw(exc) => exc.freeVarsLLIR\n    case Label(label, _, body, rest) => (body.freeVarsLLIR - label) ++ rest.freeVarsLLIR \n    case Break(label) => Set.empty\n    case Continue(label) => Set.empty\n    case Begin(sub, rest) => sub.freeVarsLLIR ++ rest.freeVarsLLIR\n    case TryBlock(sub, finallyDo, rest) => sub.freeVarsLLIR ++ finallyDo.freeVarsLLIR ++ rest.freeVarsLLIR\n    case Assign(lhs, rhs, rest) => rhs.freeVarsLLIR ++ (rest.freeVarsLLIR - lhs)\n    case AssignField(lhs, nme, rhs, rest) => lhs.freeVarsLLIR ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR\n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) => lhs.freeVarsLLIR ++ fld.freeVarsLLIR ++ rhs.freeVarsLLIR ++ rest.freeVarsLLIR\n    case Define(defn, rest) => defn.freeVarsLLIR ++ (rest.freeVarsLLIR - defn.sym)\n    case Scoped(syms, body) => body.freeVarsLLIR\n    case End(msg) => Set.empty\n    case Unreachable(msg) => Set.empty\n  \n  lazy val subBlocks: Ls[Block] = this match\n    case Match(p, arms, dflt, rest) => p.subBlocks ++ arms.map(_._2) ++ dflt.toList :+ rest\n    case Begin(sub, rest) => sub :: rest :: Nil\n    case TryBlock(sub, finallyDo, rest) => sub :: finallyDo :: rest :: Nil\n    case Assign(_, rhs, rest) => rhs.subBlocks ::: rest :: Nil\n    case AssignField(_, _, rhs, rest) => rhs.subBlocks ::: rest :: Nil\n    case AssignDynField(_, _, _, rhs, rest) => rhs.subBlocks ::: rest :: Nil\n    case Define(d, rest) => d.subBlocks ::: rest :: Nil\n    case Label(_, _, body, rest) => body :: rest :: Nil\n    case Scoped(_, body) => body :: Nil\n    \n    // TODO rm Lam from values and thus the need for these cases\n    case Return(r, _) => r.subBlocks\n    case Throw(r) => r.subBlocks\n    \n    case _: Return | _: Throw | _: Break | _: Continue | _: End | _: Unreachable => Nil\n  \n  // Moves definitions in a block to the top. Only scans the top-level definitions of the block;\n  // i.e, definitions inside other definitions are not moved out. Definitions inside `match`/`if`\n  // and `while` statements are moved out.\n  //\n  // Note that this returns the definitions in reverse order, with the bottommost definiton appearing\n  // last. This is so that using defns.foldLeft later to add the definitions to the front of a block, \n  // we don't need to reverse the list again to preserve the order of the definitions.\n  def extractDefns(\n        ignore: Defn => Bool = _ => false, \n        preserve: Defn => Bool = _ => false\n      ): (Block, List[Defn]) =\n    var defns: List[Defn] = Nil\n    val transformer = new BlockTransformerShallow(SymbolSubst.Id):\n      override def applyBlock(b: Block): Block = b match\n        case Define(defn, rest) if !ignore(defn) => defn match\n          case v: ValDefn => super.applyBlock(b)\n          case _ =>\n            defns ::= defn\n            if preserve(defn) then super.applyBlock(b)\n            else applyBlock(rest)\n        case _ => super.applyBlock(b)\n    \n    (transformer.applyBlock(this), defns)\n    \n  def gatherDefns(\n      ignore: Defn => Bool = _ => false, \n      preserve: Defn => Bool = _ => false\n    ): List[Defn] = extractDefns(ignore, preserve)._2 // TODO: fix this very inefficient implementation\n  \n  \n  lazy val flattened: Block = this.flatten(identity)\n  \n  private def flatten(k: End => Block): Block = this match\n    \n    case Match(scrut, arms, dflt, rest) =>\n      val newRest = rest.flatten(k)\n      val newArms = arms.mapConserve: arm =>\n        val newBody = arm._2.flattened\n        if newBody is arm._2 then arm else (arm._1, newBody)\n      val newDflt = dflt.mapConserve(_.flattened)\n      if (newRest is rest) && (newArms is arms) && (newDflt is dflt)\n      then this\n      else Match(scrut, newArms, newDflt, newRest)\n      \n    case Label(label, loop, body, rest) =>\n      val newBody = body.flattened\n      val newRest = rest.flatten(k)\n      if (newBody is body) && (newRest is rest)\n      then this\n      else Label(label, loop, newBody, newRest)\n      \n    case Begin(sub, rest) =>\n      sub.flatten(_ => rest.flatten(k))\n      \n    case TryBlock(sub, finallyDo, rest) =>\n      val newSub = sub.flattened\n      val newFinallyDo = finallyDo.flattened\n      val newRest = rest.flatten(k)\n      if (newSub is sub) && (newFinallyDo is finallyDo) && (newRest is rest)\n      then this\n      else TryBlock(newSub, newFinallyDo, newRest)\n      \n    case Assign(lhs, rhs, rest) =>\n      val newRest = rest.flatten(k)\n      if newRest is rest\n      then this\n      else Assign(lhs, rhs, newRest)\n      \n    case a @ AssignField(lhs, nme, rhs, rest) =>\n      val newRest = rest.flatten(k)\n      if newRest is rest\n      then this\n      else AssignField(lhs, nme, rhs, newRest)(a.symbol)\n      \n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>\n      val newRest = rest.flatten(k)\n      if newRest is rest\n      then this\n      else AssignDynField(lhs, fld, arrayIdx, rhs, newRest)\n    \n    case Define(defn, rest) =>\n      val newDefn = defn match\n        case d: FunDefn =>\n          val newBody = d.body.flattened\n          if newBody is d.body\n          then d\n          else d.copy(body = newBody)(configOverride = d.configOverride, annotations = d.annotations)\n        case v: ValDefn => v\n        case c: ClsLikeDefn =>\n          val newPreCtor = c.preCtor.flattened\n          val newCtor = c.ctor.flattened\n          def flattenMethods(ms: List[FunDefn]) = ms.mapConserve:\n            case f@FunDefn(owner, sym, dSym, params, body) =>\n              val newBody = body.flattened\n              if newBody is body then f else f.copy(body = newBody)(configOverride = f.configOverride, annotations = f.annotations)\n          val newMethods = flattenMethods(c.methods)\n          val newCompanion = c.companion.mapConserve: c =>\n            val newCtor = c.ctor.flattened\n            val newMethods = flattenMethods(c.methods)\n            if (newCtor is c.ctor) && (newMethods is c.methods) then c\n              else c.copy(ctor = newCtor, methods = newMethods)\n          if (newPreCtor is c.preCtor)\n          && (newCtor is c.ctor)\n          && (newMethods is c.methods)\n          && (newCompanion is c.companion)\n          then c\n          else c.copy(\n            preCtor = newPreCtor,\n            ctor = newCtor,\n            methods = newMethods,\n            companion = newCompanion,\n          )(c.configOverride, c.annotations)\n      \n      val newRest = rest.flatten(k)\n      if (newDefn is defn) && (newRest is rest)\n      then this\n      else Define(newDefn, newRest)\n    \n    case Scoped(syms, body) =>\n      val newBody = body.flatten(k)\n      if newBody is body\n      then this\n      else Scoped(syms, newBody)\n\n    case e: End => k(e)\n    case t: BlockTail => this\n  \nend Block\n\nsealed abstract class BlockTail extends Block\n\nsealed abstract trait NonBlockTail:\n  val rest: Block\n\ncase class Match(\n  scrut: Path,\n  arms: Ls[Case -> Block],\n  dflt: Opt[Block],\n  rest: Block,\n) extends Block with ProductWithTail with NonBlockTail\n\n// * `implct`: metadata indicating whether this is a JS implicit return, without the `return` keyword.\n// * This is currenlty only used for the main blocks of modules and diff-test blocks;\n// * for all intents and purposes, one can view an implicit return as a normal return.\n// * I would remove it, but it helps print cleaner outputs for diff tests (eg, using `:sir`).\ncase class Return(res: Result, implct: Bool) extends BlockTail\n\ncase class Throw(exc: Result) extends BlockTail\n\ncase class Label(label: LabelSymbol, loop: Bool, body: Block, rest: Block)\nextends Block with NonBlockTail with ProductWithTail\n\ncase class Break(label: LabelSymbol) extends BlockTail\ncase class Continue(label: LabelSymbol) extends BlockTail\n\n\ncase class Scoped(syms: collection.Set[Local], body: Block)\nextends Block with NonBlockTail:\n  val rest = body\n\n// TODO: remove this form?\ncase class Begin(sub: Block, rest: Block) extends Block with ProductWithTail with NonBlockTail\n\ncase class TryBlock(sub: Block, finallyDo: Block, rest: Block) extends Block with ProductWithTail with NonBlockTail\n\ncase class Assign(lhs: Local, rhs: Result, rest: Block) extends Block with ProductWithTail with NonBlockTail\n// case class Assign(lhs: Path, rhs: Result, rest: Block) extends Block with ProductWithTail\n\ncase class AssignField(lhs: Path, nme: Tree.Ident, rhs: Result, rest: Block)(val symbol: Opt[MemberSymbol])\n  extends Block with ProductWithTail with NonBlockTail\n\ncase class AssignDynField(lhs: Path, fld: Path, arrayIdx: Bool, rhs: Result, rest: Block)\n  extends Block with ProductWithTail with NonBlockTail\n\ncase class Define(defn: Defn, rest: Block) extends Block with ProductWithTail with NonBlockTail\n\ninline def whenValidatingIR(inline code: => Unit): Unit =\n  () // code // * uncomment to run on-the fly IR validations\n  \nobject Label:\n  def apply(label: LabelSymbol, loop: Bool, body: Block, rest: Block): Block = body match\n    case _: Unreachable => body\n    case _ =>\n      rest match\n      case Scoped(syms, rest) => Scoped(syms, Label(label, loop, body, rest))\n      case _ => new Label(label, loop, body, rest)\nobject Scoped:\n  def apply(syms: collection.Set[Local], body: Block): Block = body match\n    case _: Unreachable => body\n    case _ if syms.isEmpty => body\n    case Scoped(syms2, body) =>\n      whenValidatingIR:\n        assert(!syms2.exists(syms.contains), \"overlapping symbols in nested Scoped\")\n      Scoped(syms ++ syms2, body)\n    case _ =>\n      new Scoped(syms, body)\nobject TryBlock:\n  def apply(body: Block, finallyDo: Block, rest: Block): Block =\n    body match\n    case _: Unreachable => body\n    case _ =>\n      rest match\n      case Scoped(syms, innerRest) => Scoped(syms, TryBlock(body, finallyDo, innerRest))\n      case _ => new TryBlock(body, finallyDo, rest)\nobject Assign:\n  def apply(lhs: Local, rhs: Result, rest: Block): Block = rest match\n    case _: Unreachable =>\n      if rhs.isPure then rest else new Assign(lhs, rhs, rest)\n    case Scoped(syms, body) => Scoped(syms, Assign(lhs, rhs, body))\n    case _ =>\n      lhs match\n      case _: NoSymbol =>\n        if rhs.isPure then rest else new Assign(lhs, rhs, rest)\n      case _ => new Assign(lhs, rhs, rest)\n  def discard(res: Result, rest: Block)(using State): Block =\n    res match\n    case _: Value | _: Lambda => rest\n    case p: Path if p.isPure => rest\n    case r => Assign(State.noSymbol, r, rest)\nobject AssignField:\n  def apply(lhs: Path, nme: Tree.Ident, rhs: Result, rest: Block)(symbol: Opt[MemberSymbol]): Block = rest match\n    case Scoped(syms, body) => Scoped(syms, AssignField(lhs, nme, rhs, body)(symbol))\n    case _ => new AssignField(lhs, nme, rhs, rest)(symbol)\nobject AssignDynField:\n  def apply(lhs: Path, fld: Path, arrayIdx: Bool, rhs: Result, rest: Block): Block = rest match\n    case Scoped(syms, body) => Scoped(syms, AssignDynField(lhs, fld, arrayIdx, rhs, body))\n    case _ => new AssignDynField(lhs, fld, arrayIdx, rhs, rest)\nobject Define:\n  def apply(defn: Defn, rest: Block): Block = rest match\n    case Scoped(syms, body) => Scoped(syms, Define(defn, body))\n    case _ => new Define(defn, rest)\n\nobject Match:\n  def apply(scrut: Path, _arms: Ls[Case -> Block], _dflt: Opt[Block], rest: Block): Block =\n    val emptyDflt = _dflt.forall(_.isEmpty)\n    val dflt = if emptyDflt then N else _dflt\n    val arms = if emptyDflt then _arms.filterNot(_._2.isEmpty) else _arms\n    if arms.isEmpty && scrut.isPure then dflt.fold(rest)(Begin(_, rest))\n    else dflt match\n    case S(Match(`scrut`, arms2, dflt2, _: End)) => // TODO: also handle non-End rest (may require a join point)\n      // * Currently, this branch does not seem used often (or at all?),\n      // * because the UCS and (especially) MergeMatchArmTransformer already do a good job at merging matches\n      Match(scrut, arms ::: arms2, dflt2, rest)\n    case _ =>\n      val numNonAbortive = arms.count(!_._2.isAbortive)\n      def mapDflt = dflt match\n        case S(d) => S(if d.isAbortive then d else Begin(d, rest))\n        case N => S(rest)\n      if numNonAbortive === 0 then\n        if rest.isEmpty then new Match(scrut, arms, mapDflt, rest)\n        else new Match(scrut, arms, mapDflt, End(\"(Unreachable:) rest of abortive match\"))\n      else if numNonAbortive === 1 && dflt.exists(_.isAbortive) || rest.size <= 1 then\n        new Match(scrut,\n          arms.map: a =>\n            if a._2.isAbortive then a else (a._1, Begin(a._2, rest)),\n          mapDflt,\n          // * We used to produce an `Unreachable` here, but that got in the way of the useless-break optimization;\n          // * Indeed, `L: { match scrut { C => break L }; end }` can no longer be optimized\n          // * if we replace `end` with `unreachable`, since the break is no longer jumping over nothing,\n          // * ie no longer in tail position of the label (trying to treat it as such is unsound).\n          End(\"Rest moved to non-abortive branch(es)\"))\n      else rest match\n        case Scoped(syms, body) => Scoped(syms, Match(scrut, arms, dflt, body))\n        case _ => new Match(scrut, arms, dflt, rest)\n\nobject Begin:\n  def apply(sub: Block, rest: Block): Block =\n    if sub.isEmpty then rest\n    else if rest.isEmpty then sub\n    else if sub.isAbortive then sub\n    else (sub, rest) match\n      case (Scoped(symsSub, bodySub), Scoped(symsRest, bodyRest)) =>\n        whenValidatingIR:\n          assert(\n            !symsSub.exists(symsRest.contains),\n            \"overlapping symbols when trying to merge Scoped blocks\")\n        Scoped(symsSub ++ symsRest, Begin(bodySub, bodyRest))\n      case (Scoped(symsSub, bodySub), _) => Scoped(symsSub, Begin(bodySub, rest))\n      case (_, Scoped(symsRest, bodyRest)) => Scoped(symsRest, Begin(sub, bodyRest))\n      case _ => new Begin(sub, rest)\n\n\nobject HandleBlock:\n\n  def suspend(tag: Path, handlerFun: Path)(using Elaborator.Ctx): Result =\n    Call(Value.Ref(Elaborator.ctx.builtins.runtime.suspend, N), (tag.asArg :: handlerFun.asArg :: Nil) ne_:: Nil)(true, true, false)\n\n  def handleSuspension(tag: Path, bodyFun: Path)(using Elaborator.Ctx): Result =\n    Call(Value.Ref(Elaborator.ctx.builtins.runtime.handle_suspension, N), (tag.asArg :: bodyFun.asArg :: Nil) ne_:: Nil)(true, true, false)\n  \n  private def create(\n      lhs: Local,\n      res: Local,\n      par: Path,\n      args: Ls[Path],\n      cls: ClassSymbol,\n      handlers: Ls[Handler],\n      body: Block,\n      rest: Block\n  )(using Elaborator.State, Elaborator.Ctx) =\n    val sym = new BlockMemberSymbol(\"handleBlock$\", Nil, false)\n\n    val bodyDefn = FunDefn.withFreshSymbol(N, sym, PlainParamList(Nil) :: Nil, body)(N, annotations = Nil)\n    \n    val handlerMtds = handlers.map: handler =>\n      val sym = BlockMemberSymbol(cls.nme + handler.sym.nme, Nil, true)\n      val fDef = FunDefn.withFreshSymbol(\n        N, sym, PlainParamList(Param(FldFlags.empty, handler.resumeSym, N, Modulefulness.none) :: Nil) :: Nil,\n        handler.body\n        )(N, annotations = Nil)\n      val rSym = TempSymbol(N, \"suspendRes\")\n      FunDefn.withFreshSymbol(\n        S(cls),\n        handler.sym,\n        handler.params,\n        Scoped(Set(sym, rSym), Define(\n          fDef,\n          Return(suspend(cls.asPath, Value.Ref(sym, S(fDef.dSym))), false))))(N, annotations = Nil)\n\n    val clsDefn = ClsLikeDefn(\n      N, // no owner\n      cls,\n      BlockMemberSymbol(cls.id.name, Nil),\n      N,\n      syntax.Cls,\n      N, Nil,\n      S(par), handlerMtds, Nil, Nil,\n      // Apparently, the lifter is not happy with any assignment in the preCtor...\n      Return(Call(Value.Ref(State.builtinOpsMap(\"super\")), args.map(_.asArg) ne_:: Nil)(true, true, false), true),\n      End(),\n      N,\n      N,\n    )(N, Nil)\n\n    blockBuilder\n      .scopedVars(Set(clsDefn.sym, sym))\n      .define(clsDefn)\n      .assign(lhs, Instantiate(mut = true, Value.Ref(clsDefn.sym, S(cls)), Nil :: Nil))\n      .define(bodyDefn)\n      .assign(res, handleSuspension(lhs.asPath, Value.Ref(bodyDefn.sym, S(bodyDefn.dSym))))\n      .rest(rest)\n  \n  def apply(\n      lhs: Local,\n      res: Local,\n      par: Path,\n      args: Ls[Path],\n      cls: ClassSymbol,\n      handlers: Ls[Handler],\n      body: Block,\n      rest: Block\n    )(using Elaborator.State, Elaborator.Ctx) =\n  rest match\n  case Scoped(syms, rest) =>\n    Scoped(syms, create(lhs, res, par, args, cls, handlers, body, rest))\n  case _ => create(lhs, res, par, args, cls, handlers, body, rest)\n\n\nsealed abstract class Defn:\n  val innerSym: Opt[MemberSymbol]\n  val sym: BlockMemberSymbol\n  val annotations: Ls[Annot]\n  def isStaged: Bool = annotations.exists:\n    case Annot.Modifier(Keyword.`staged`) => true\n    case _ => false\n  def isOwned: Bool = owner.isDefined\n  def owner: Opt[InnerSymbol]\n  \n  /** Whether this definition as a statement has any side effect (if unused). */\n  def isPure: Bool = this match\n    case vd: ValDefn => vd.rhs.isPure && vd.tsym.owner.isEmpty\n    case fd: FunDefn => fd.owner.isEmpty\n    case c: ClsLikeDefn =>\n      // * Simple heuristic. TODO: check the purity of the ctor somehow? (ignore pure local field inits)\n      c.companion.isEmpty\n        && (!(c.k is syntax.Obj) || c.ctor.isEmpty)\n  \n  def subBlocks: Ls[Block] = this match\n    case FunDefn(body = body) => body :: Nil\n    case _: ValDefn => Nil\n    case ClsLikeDefn(preCtor = preCtor, ctor = ctor, methods = mtds, companion = comp) =>\n      preCtor :: ctor :: mtds.flatMap(_.subBlocks) ::: comp.toList.flatMap(_.subBlocks)\n  \n  // * Note that `privateFields` abd `publicFields` can't possibly be free since they are never\n  // * referred to directly (they are only accessed through selections).\n  // * At some point we'll want to make `Local` more specific than `Symbol` to express this\n  // * in the type system.\n  lazy val freeVars: Set[Local] = this match\n    case FunDefn(own, sym, dSym, params, body) =>\n      body.freeVars -- params.flatMap(_.paramSyms) ++ sym.optionIf(own.isEmpty)\n    case ValDefn(tsym, sym, rhs) => rhs.freeVars ++ sym.optionIf(tsym.owner.isEmpty)\n    case ClsLikeDefn(own, isym, sym, ctorSym, k, paramsOpt, auxParams, parentSym, \n        methods, privateFields, publicFields, preCtor, ctor, stat, bufferable) =>\n      preCtor.freeVars\n        ++ ctor.freeVars ++ methods.flatMap(_.freeVars)\n        -- auxParams.flatMap(_.paramSyms)\n        ++ stat.iterator.flatMap(_.freeVars)\n        ++ sym.optionIf(own.isEmpty)\n  \n  lazy val freeVarsLLIR: Set[Local] = this match\n    case FunDefn(own, sym, dSym, params, body) => body.freeVarsLLIR -- params.flatMap(_.paramSyms) - sym\n    case ValDefn(tsym, sym, rhs) => rhs.freeVarsLLIR\n    case ClsLikeDefn(own, isym, sym, ctorSym, k, paramsOpt, auxParams, parentSym, \n        methods, privateFields, publicFields, preCtor, ctor, stat, bufferable) =>\n      preCtor.freeVarsLLIR\n        ++ ctor.freeVarsLLIR ++ methods.flatMap(_.freeVarsLLIR) ++ stat.iterator.flatMap(_.freeVarsLLIR)\n        -- auxParams.flatMap(_.paramSyms)\n  \n\n// NOTE: Setting isTailRec to false does not affect whether the function is optimized.\n// It only affects whether a warning is thrown if the function is not actually tailrec.\nfinal case class FunDefn(\n    owner: Opt[InnerSymbol],\n    sym: BlockMemberSymbol,\n    dSym: TermSymbol,\n    params: Ls[ParamList],\n    body: Block,\n  )(\n    val configOverride: Opt[Config],\n    val annotations: Ls[Annot],\n) extends Defn:\n  val innerSym = N\n  val asPath = Value.Ref(sym, S(dSym))\n  lazy val forceTailRec: Bool = annotations.contains(Annot.TailRec)\n  lazy val visibility: Visibility = annotations.collectFirst:\n    case Annot.Modifier(Keyword.`private`) => Visibility.Private\n    case Annot.Modifier(Keyword.`public`) => Visibility.Public\n  .getOrElse(Visibility.Public)\nobject FunDefn:\n  def withFreshSymbol(owner: Opt[InnerSymbol], sym: BlockMemberSymbol, params: Ls[ParamList], body: Block)(configOverride: Opt[Config], annotations: Ls[Annot])(using State) =\n    val tSym = TermSymbol(syntax.Fun, owner, Tree.Ident(sym.nme))\n    sym.tsym = S(tSym)\n    FunDefn(owner, sym, tSym, params, body)(configOverride, annotations)\n\nfinal case class ValDefn(\n    tsym: TermSymbol,\n    sym: BlockMemberSymbol,\n    rhs: Path,\n)(\n    val configOverride: Opt[Config],\n    val annotations: Ls[Annot],\n) extends Defn:\n  val innerSym = S(tsym)\n  val owner: Opt[InnerSymbol] = tsym.owner\n\n\nobject ValDefn:\n  def mk(\n      owner: Opt[InnerSymbol],\n      k: syntax.Val,\n      sym: BlockMemberSymbol,\n      rhs: Path,\n      configOverride: Opt[Config],\n      annotations: Ls[Annot],\n    )(using State)\n    : ValDefn =\n      ValDefn(tsym = TermSymbol(k, owner, Tree.Ident(sym.nme)), sym = sym, rhs = rhs)(configOverride, annotations)\n\n\n/*\n  The following explains the difference between paramsOpt, auxParams, privateFields and publicFields.\n  \n  paramsOpt is the main parameter list of a class, i.e. in `class A(plist0)`, `plist0` will be in paramsOpt.\n  If there is no such parameter list, for example `class A`, then paramsOpt will be None.\n  \n  auxParams are the secondary parameter lists, and in the future, will be defined using the syntax\n  \n  class A with\n    constructor(plist1)(plist2) = ...\n  \n  with the difference being that they are not printed in the class's toString function. If paramsOpt is None,\n  the class won't have a `.class` field and must be instantiated using `new`. Otherwise, it can be instantiated\n  using either a function call or `new A` or even `new A.class` (the latter is the recommended way when done in JS). The first parameter list will always be passed to `paramsOpt`,\n  if it exists.\n  \n  Private and public fields are defined by the user using `let` and `val` in the class's constructor.\n  Each parameter in the main parameter list **defined by the user** will automatically have an asociated\n  public/private field. The field will be public if the parameter is marked `val`, i.e. class `A(val x)`, \n  and private otherwise. Fields in the main parameter list created after lowering will not automatically\n  have a field created.\n  \n  For example:\n  \n  class A(privateField0, val publicField0) with\n    let privateField1 = 0\n    val publicField1 = 0\n    \n  In the codegen, private and public fields are initialized by an assignment to a member symbol and a term definition\n  respectively. The symbols must match what is defined in `privateFields` and `publicFields`. \n  (An assignment to a flow symbol will be treated as a local symbol to the constructor, not a field assignment.)\n*/\n// * This is only supposed to be for classes, objects, and patterns;\n// * a lone module is represented as an empty class with a `companion` module.\nfinal case class ClsLikeDefn(\n    owner: Opt[InnerSymbol],\n    isym: DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol,\n    sym: BlockMemberSymbol,\n    ctorSym: Opt[TermSymbol],\n    k: syntax.ClsLikeKind,\n    paramsOpt: Opt[ParamList],\n    auxParams: List[ParamList],\n    parentPath: Opt[Path],\n    methods: Ls[FunDefn],\n    privateFields: Ls[TermSymbol],\n    publicFields: Ls[BlockMemberSymbol -> TermSymbol],\n    preCtor: Block,\n    ctor: Block,\n    companion: Opt[ClsLikeBody],\n    bufferable: Option[Bool],\n)(\n    val configOverride: Opt[Config],\n    val annotations: Ls[Annot],\n) extends Defn:\n  require(k isnt syntax.Mod)\n  val innerSym = S(isym.asMemSym)\n\n\n// * This is only supposed to be for companion module definitions (notably, not for `object`)\nfinal case class ClsLikeBody(\n    isym: DefinitionSymbol[? <: ModuleOrObjectDef] & InnerSymbol,\n    methods: Ls[FunDefn],\n    privateFields: Ls[TermSymbol],\n    publicFields: Ls[BlockMemberSymbol -> TermSymbol],\n    ctor: Block,\n    annotations: Ls[Annot],\n):\n  def isStaged: Bool = annotations.exists:\n    case Annot.Modifier(Keyword.`staged`) => true\n    case _ => false\n  def subBlocks: Ls[Block] =\n    ctor :: methods.flatMap(_.subBlocks)\n  lazy val freeVars: Set[Local] =\n    ctor.freeVars ++ methods.flatMap(_.freeVars)\n  lazy val freeVarsLLIR: Set[Local] = ???\n\n/*\nobject ClsLikeBody:\n  // TODO rm `empty`? it's currently unused\n  def empty(id: Tree.Ident)(using State) = ClsLikeBody(\n    isym = ModuleOrObjectSymbol(Tree.DummyTypeDef(syntax.Mod), id),\n    methods = Nil,\n    privateFields = Nil,\n    publicFields = Nil,\n    ctor = End(),\n  )\n*/\n\nfinal case class Handler(\n    sym: BlockMemberSymbol,\n    resumeSym: VarSymbol,\n    params: Ls[ParamList],\n    body: Block,\n):\n  lazy val freeVars: Set[Local] = body.freeVars -- params.flatMap(_.paramSyms) - sym - resumeSym\n  lazy val freeVarsLLIR: Set[Local] = body.freeVarsLLIR -- params.flatMap(_.paramSyms) - sym - resumeSym\n\n\n/* Represents either unreachable code (for functions that must return a result)\n * or the end of a non-returning function or a REPL block */\ncase class End(msg: Str = \"\") extends BlockTail with ProductWithTail\n\ncase class Unreachable(cause: Str) extends BlockTail with ProductWithTail\n\nenum Case:\n  case Lit(lit: Literal)\n  case Cls(cls: ClassLikeSymbol, path: Path)\n  case Tup(len: Int, inf: Bool)\n  /** checks field existence\n    * @param safe true will omit the instanceof Object check\n  */\n  case Field(name: Tree.Ident, safe: Bool)\n\n  lazy val freeVars: Set[Local] = this match\n    case Lit(_) => Set.empty\n    case Cls(_, path) => path.freeVars\n    case Tup(_, _) => Set.empty\n    case Field(_, _) => Set.empty\n  \n  lazy val freeVarsLLIR: Set[Local] = this match\n    case Lit(_) => Set.empty\n    case Cls(_, path) => path.freeVarsLLIR\n    case Tup(_, _) => Set.empty\n    case Field(_, _) => Set.empty\n\nsealed trait TrivialResult extends Result\n\nsealed abstract class Result extends AutoLocated:\n// // * Used for debugging locations:\n// sealed abstract class Result extends AutoLocated with ProductWithExtraInfo:\n//   def extraInfo: Str = toLoc.toString\n  \n  lazy val isPure: Bool = this match\n    case _: Value => true\n    case sel @ Select(q, n) =>\n      q.isPure && sel.symbol.exists(_.isPure)\n    case Call(Value.Ref(bs: BuiltinSymbol, _), ass) if bs.isPure =>\n      ass.forall(_.forall(_.value.isPure))\n    case Record(mut, args) => args.forall(_.value.isPure)\n    case Tuple(mut, elems) => elems.forall(_.value.isPure)\n    // case Instantiate(mut, cls, args) => // TODO?\n    case _ => false\n  \n  // * Note: this function is used to piece together a location;\n  // * for the location to be valid, we should NOT have it include children whose location\n  // * is from some different place (with a different Origin), such as the location attached to symbols.\n  // * That's why for example, we're not adding the `l` of `Value.Ref` to the children list.\n  protected def children: Vector[Located] = this match\n    case Call(fun, argss) => fun +: argss.iterator.flatten.map(_.value).toVector\n    case Instantiate(mut, cls, argss) => cls +: argss.iterator.flatten.map(_.value).toVector\n    case Select(qual, name) => Vector.double(qual, name)\n    case DynSelect(qual, fld, arrayIdx) => Vector.double(qual, fld)\n    case Lambda(params, body) => Vector.single(params)\n    case Tuple(mut, elems) => elems.iterator.map(_.value).toVector\n    case Record(mut, elems) => elems.iterator.map(_.value).toVector\n    case Value.Ref(l, disamb) => Vector.empty\n    case Value.This(sym) => Vector.empty\n    case Value.Lit(lit) => Vector.single(lit)\n  \n  // TODO rm Lam from values and thus the need for this method\n  def subBlocks: Ls[Block] = this match\n    case Call(fun, argss) => fun.subBlocks ::: argss.flatten.flatMap(_.value.subBlocks)\n    case Instantiate(mut, cls, argss) => argss.flatten.flatMap(_.value.subBlocks)\n    case Select(qual, name) => qual.subBlocks\n    case Lambda(params, body) => body :: Nil\n    case Tuple(mut, elems) => elems.flatMap(_.value.subBlocks)\n    case _ => Nil\n  \n  lazy val freeVars: Set[Local] = this match\n    case Call(fun, argss) => fun.freeVars ++ argss.flatten.flatMap(_.value.freeVars).toSet\n    case Instantiate(mut, cls, argss) => cls.freeVars ++ argss.flatten.flatMap(_.value.freeVars).toSet\n    case Select(qual, name) => qual.freeVars \n    case Lambda(params, body) => body.freeVars -- params.paramSyms\n    case Tuple(mut, elems) => elems.flatMap(_.value.freeVars).toSet\n    case Record(mut, args) =>\n      args.flatMap(arg => arg.idx.fold(Set.empty)(_.freeVars) ++ arg.value.freeVars).toSet\n    case Value.Ref(l, disamb) => Set(l)\n    case Value.This(sym) => Set.empty\n    case Value.Lit(lit) => Set.empty\n    case DynSelect(qual, fld, arrayIdx) => qual.freeVars ++ fld.freeVars\n  \n  lazy val freeVarsLLIR: Set[Local] = this match\n    case Call(fun, argss) => fun.freeVarsLLIR ++ argss.flatten.flatMap(_.value.freeVarsLLIR).toSet\n    case Instantiate(mut, cls, argss) => cls.freeVarsLLIR ++ argss.flatten.flatMap(_.value.freeVarsLLIR).toSet\n    case Select(qual, name) => qual.freeVarsLLIR \n    case Lambda(params, body) => body.freeVarsLLIR -- params.paramSyms\n    case Tuple(mut, elems) => elems.flatMap(_.value.freeVarsLLIR).toSet\n    case Record(mut, args) =>\n      args.flatMap(arg => arg.idx.fold(Set.empty)(_.freeVarsLLIR) ++ arg.value.freeVarsLLIR).toSet\n    case Value.Ref(l: (BuiltinSymbol | TopLevelSymbol | ClassSymbol | TermSymbol), disamb) => Set.empty\n    case Value.Ref(l: BlockMemberSymbol, S(disamb)) => disamb.defn match\n      case Some(d: ClassLikeDef) => Set.empty\n      case Some(d: TermDefinition) if d.companionClass.isDefined => Set.empty\n      case _ => Set(l)\n    case Value.Ref(l: DefinitionSymbol[?], N) => l.defn match\n      case Some(d: ClassLikeDef) => Set.empty\n      case Some(d: TermDefinition) if d.companionClass.isDefined => Set.empty\n      case _ => Set(l)\n    case Value.Ref(l, disamb) => Set(l)\n    case Value.This(sym) => Set.empty\n    case Value.Lit(lit) => Set.empty\n    case DynSelect(qual, fld, arrayIdx) => qual.freeVarsLLIR ++ fld.freeVarsLLIR\n  \n// type Local = LocalSymbol\ntype Local = Symbol\n\n/* mayRaiseEffects indicates whether this call may raise effect (algebraic effect),\n * regardless of whether the check for effect is inserted or not.\n * Note that the check for effect is inserted during HandlerLowering and setting this to true\n * after handler is lowered does not have any effect on the code generation. */\ncase class Call(fun: Path, argss: NELs[Ls[Arg]])(val isMlsFun: Bool, val mayRaiseEffects: Bool, val explicitTailCall: Bool) extends Result\n\ncase class Instantiate(mut: Bool, cls: Path, argss: Ls[Ls[Arg]]) extends Result\n\ncase class Lambda(params: ParamList, body: Block) extends Result\n\ncase class Tuple(mut: Bool, elems: Ls[Arg]) extends Result\n\ncase class Record(mut: Bool, elems: Ls[RcdArg]) extends Result\n\n\nsealed abstract class Path extends TrivialResult:\n  def selN(id: Tree.Ident): Path = Select(this, id)(N)\n  def sel(id: Tree.Ident, sym: DefinitionSymbol[?]): Path = Select(this, id)(S(sym))\n  def selSN(id: Str): Path = selN(new Tree.Ident(id))\n  def asArg = Arg(spread = N, this)\n  def targetSymbol: Opt[DefinitionSymbol[?]] = this match\n    case sel: Select => sel.symbol\n    case Value.Ref(l, d) => d\n    case _ => N\n\n/**\n * @param symbol The symbol representing the definition that the selection refers to, if known.\n */\ncase class Select(qual: Path, name: Tree.Ident)(val symbol: Opt[DefinitionSymbol[?]]) extends Path with ProductWithExtraInfo:\n  def extraInfo(using DebugPrinter): Str = symbol.map(s => s\"sym=${s.showAsPlain}\").mkString\n\ncase class DynSelect(qual: Path, fld: Path, arrayIdx: Bool) extends Path\n\nenum Value extends Path with ProductWithExtraInfo:\n  /**\n   * @param disamb The symbol disambiguating the definition that the reference refers to. This\n   * exists if and only if l is a BlockMemberSymbol.\n   */\n  case Ref(l: Local, disamb: Opt[DefinitionSymbol[?]])\n  case This(sym: InnerSymbol) // TODO rm – just use Ref\n  case Lit(lit: Literal)\n  \n  override def extraInfo(using DebugPrinter): Str = this match\n    case Ref(l, disamb) => disamb.map(s => s\"disamb=${s.showAsPlain}\").mkString\n    case _ => \"\"\n\nobject Value:\n  object Ref:\n    // * Some helper constructors that allow omitting the disambiguation symbol.\n    // * If the ref itself is a DefinitionSymbol, then disambiguating it results in itself.\n    def apply(l: DefinitionSymbol[?]): Ref = Ref(l, S(l))\n    // * If the ref is a symbol that does not refer to a definition, then there is no disambiguation.\n    def apply(l: TempSymbol | VarSymbol | BuiltinSymbol): Ref = Ref(l, N)\n\ncase class Arg(spread: Opt[SpreadKind], value: Path)\n\n// * `IndxdArg(S(idx), value)` represents a key-value pair in a record `(idx): value`\n// * `IndxdArg(N, value)` represents a spread element in a record `...value`\ncase class RcdArg(idx: Opt[Path], value: Path):\n  def spread: Bool = idx.isEmpty\n\nextension (k: Block => Block)\n  \n  def chain(other: Block => Block): Block => Block = b => k(other(b))\n  def rest(b: Block): Block = k(b)\n  def transform(f: (Block => Block) => (Block => Block)) = f(k)\n  \n  def assign(l: Local, r: Result) = k.chain(Assign(l, r, _))\n  def assignScoped(l: Local, r: Result) = k.scopedVars(Set.single(l)).assign(l, r)\n  def assignFieldN(lhs: Path, nme: Tree.Ident, rhs: Result) = k.chain(AssignField(lhs, nme, rhs, _)(N))\n  def break(l: LabelSymbol): Block = k.rest(Break(l))\n  def continue(l: LabelSymbol): Block = k.rest(Continue(l))\n  def define(defn: Defn) = k.chain(Define(defn, _))\n  def end = k.rest(End())\n  def ifthen(scrut: Path, cse: Case, trm: Block, els: Opt[Block] = N): Block => Block =\n    k.chain(Match(scrut, cse -> trm :: Nil, els, _))\n  def label(label: LabelSymbol, loop: Bool, body: Block) = k.chain(Label(label, loop, body, _))\n  def ret(r: Result) = k.rest(Return(r, false))\n  def scopedVars(s: collection.Set[Local]) = k.chain(Scoped(s, _))\n  def staticif(b: Boolean, f: (Block => Block) => (Block => Block)) = if b then k.transform(f) else k\n  def foldLeft[A](xs: Iterable[A])(f: (Block => Block, A) => Block => Block) = xs.foldLeft(k)(f)\n\ndef blockBuilder: Block => Block = identity\n\nextension (l: Local)\n  def asPath: Path = Value.Ref(l, N)\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/BlockChecker.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet}\nimport sourcecode.Line\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\nimport hkmc2.Message.MessageContext\n\nimport semantics.*\nimport semantics.Elaborator.State\n\n\n/** An invariant of the IR is that each symbol should be bound at most once\n  * (this simplifies various analyses and transformations).\n  * This class checks this invariant. */\nclass BlockChecker()(using DebugPrinter, State, Raise) extends BlockTraverser:\n  \n  val definedSyms = MutSet.empty[Local]\n  \n  private def checkSymbol(sym: Local, info: => Any): Unit =\n    if !definedSyms.add(sym) then\n      raise:\n        InternalError(\n          msg\"[BlockChecker] Invalid IR: symbol ${sym.showAsPlain} is bound more than once\" -> sym.toLoc\n            :: Nil,\n          extraInfo = S(info)\n        )\n  \n  override def applyBlock(b: Block): Unit =\n    b match\n    case Scoped(syms, body) =>\n      syms.foreach(checkSymbol(_, b))\n    case _ => ()\n    super.applyBlock(b)\n  \n  override def applyParamList(pl: ParamList): Unit =\n    pl.paramSyms.foreach(checkSymbol(_, pl))\n    super.applyParamList(pl)\n  \nend BlockChecker\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/BlockSimplifier.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet, Buffer}\nimport scala.annotation.tailrec\nimport sourcecode.Line\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport semantics.*\nimport semantics.Elaborator.State\nimport mlscript.utils.algorithms.partitionScc\n\n\n/** `symbolsToPreserve` is the set of local symbols we want to leave alone;\n  * typically, these will be top-level symbols that are being exported from a diff-test block;\n  * we don't want to eliminate these. */\nclass BlockSimplifier(symbolsToPreserve: Set[Local])(using DebugPrinter, State, Config, TL):\n  \n  \n  private var changed = true\n  \n  def registerChange = changed = true\n  // * For debugging:\n  // def registerChange(using line: Line) = { println(s\"Change at line ${line.value}\"); changed = true }\n  \n  def apply(prog: Program): Program =\n    var res = prog\n    while changed do\n      changed = false\n      res = new DeadCodeElim().apply(res)\n      summon[Config].inlining.foreach: cfg =>\n        res = new Inliner.Inliner(using cfg).applyProgram(res)\n      // TODO: other simplifications, such as inlining\n    res\n  end apply\n  \n  \n  class DeadCodeElim() extends BlockTransformer(SymbolSubst.Id):\n    \n    \n    val usedLabels = MutSet.empty[LabelSymbol]\n    val definedVars = MutSet.empty[Local]\n    val localVars = MutSet.empty[Local]\n    val usedVars = MutSet.empty[Local]\n    var tailLabels = MutSet.empty[LabelSymbol]\n    \n    def apply(prog: Program): Program =\n      \n      new BlockTraverser:\n        \n        applyProgram(prog)\n        \n        override def applyDefn(defn: Defn): Unit =\n          defn match\n          case cls: ClsLikeDefn =>\n            localVars ++= cls.privateFields\n            cls.companion.foreach(localVars ++= _.privateFields)\n          case _ =>\n          super.applyDefn(defn)\n        \n        override def applyPath(p: Path): Unit =\n          p match\n            case Value.Ref(loc, _) =>\n              usedVars += loc\n            case _ =>\n          super.applyPath(p)\n        \n        override def applyBlock(b: Block): Unit =\n          b match\n            case Define(defn, rst) =>\n              definedVars += defn.sym\n            case Scoped(syms, _) =>\n              localVars ++= syms\n            case Break(lbl) => usedLabels += lbl\n            case Continue(lbl) => usedLabels += lbl\n            case Assign(lhs, rhs, rst) =>\n              definedVars += lhs\n            case _ =>\n          super.applyBlock(b)\n      \n      applyProgram(prog)\n    \n    // Evaluate `thunk` with a new tail label set. This is used for evaluating any sub blocks that is not in the tail position.\n    // For example, the match arms within a `Match` node are not in the tail position unless the rest block is `End`.\n    // When evaluating the match arms, the tail labels should not be considered to be at tail.\n    // The tail label set is restored after `thunk` completes.\n    inline def nestLabelCtx[T](inline thunk: => T): T =\n      val oldTailLabels = tailLabels\n      tailLabels = MutSet.empty\n      val result = thunk\n      tailLabels = oldTailLabels\n      result\n    \n    // Add the new label to the tail label set during the execution of `thunk`.\n    inline def withTailLabel[T](newLabel: LabelSymbol)(inline thunk: => T): T =\n      assert(!tailLabels.contains(newLabel))\n      tailLabels += newLabel\n      val result = thunk\n      tailLabels -= newLabel\n      result\n    \n    // * Cached analysis to find which labels are the targets of `break`s in a given block\n    object BrokenLabels extends CachedAnalysis[Block, Set[LabelSymbol]]:\n      \n      def analyzeUncached(block: Block): Set[LabelSymbol] = block match\n        case Break(lbl) => Set.single(lbl)\n        case _ => block.subBlocks.iterator.flatMap(analyze).toSet\n      \n    end BrokenLabels\n    \n    \n    // * Cached analysis to find whether a block is abortive\n    // * (i.e. always throws, returns, breaks, continues, or is unreachable)\n    object AbortiveAnalysis extends CachedAnalysis[Block, Bool]:\n      \n      def analyzeUncached(block: Block): Bool = block match\n        case Scoped(syms, body) =>\n          body.analyze\n        case Match(scrut, arms, dflt, rest) =>\n          rest.analyze || arms.forall(_._2.analyze) && dflt.exists(_.analyze)\n        case Begin(sub, rest) =>\n          sub.analyze || rest.analyze\n        case Define(defn, rest) =>\n          // TODO: we could also analyse the effects of the extends clauses and companion module ctor\n          rest.analyze\n        case x: (Assign | AssignField | AssignDynField) =>\n          x.rest.analyze\n        case TryBlock(sub, finallyDo, rest) =>\n          sub.analyze || rest.analyze\n        case Label(lbl, loop, bod, rst) =>\n          bod.analyze\n            && !BrokenLabels.analyze(bod).contains(lbl) // if `bod` breaks to `lbl`, then we must consider `rst`\n            || rst.analyze\n        case _: Throw | Return(_, false) | _: Unreachable | _: Continue | _: Break => true\n        case Return(_, true) => false\n        case _: End => false\n        \n    end AbortiveAnalysis\n    \n    \n    val removedLocals: MutSet[Local] = MutSet.empty\n    \n    \n    override def applyValue(v: Value)(k: Value => Block) = v match\n      // * Replace with `undefined` those references to local variables that are never assigned\n      case Value.Ref(loc, N) if localVars.contains(loc) && !definedVars.contains(loc) =>\n        registerChange\n        if !symbolsToPreserve(loc) then removedLocals += loc\n        k(Value.Lit(syntax.Tree.UnitLit(false)))\n      case _ => super.applyValue(v)(k)\n    \n    override def applyBlock(b: Block): Block = b match\n      \n      // * Discard assignments to local variables that are never read (and are not preserved)\n      case Assign(lhs, rhs, rst) if localVars(lhs) && !usedVars(lhs) && !symbolsToPreserve(lhs) =>\n        registerChange\n        removedLocals += lhs\n        applyResult(rhs)(r => Assign.discard(r, applyBlock(rst)))\n      \n      // * Remove local pure definitions that are never read (and are not preserved)\n      case Define(defn, rest) =>\n        if !defn.isPure\n        || !localVars(defn.sym)\n        || usedVars(defn.sym)\n        || symbolsToPreserve(defn.sym)\n        then super.applyBlock(b)\n        else\n          registerChange\n          removedLocals += defn.sym\n          applyBlock(rest)\n        \n      // * Simplify labelled blocks\n      case Label(lbl, loop, bod, rst) =>\n        if !BrokenLabels.analyze(bod).contains(lbl) && AbortiveAnalysis.analyze(bod) && !rst.isInstanceOf[Unreachable] then\n          registerChange\n          val unr = Unreachable(\"Rest of abortive labelled block\")\n          if usedLabels.contains(lbl)\n          then Label(lbl, loop, nestLabelCtx(applyBlock(bod)), unr)\n          else Begin(nestLabelCtx(applyBlock(bod)), unr)\n        else\n          if usedLabels.contains(lbl) then\n            def computeBod =\n              withTailLabel(lbl):\n                applyBlock(bod)\n            val lbl2 = lbl.subst\n            val bod2 = if rst.isEmpty && !loop then computeBod else nestLabelCtx(computeBod)\n            val rst2 = applySubBlock(rst)\n            if (lbl2 is lbl) && (bod2 is bod) && (rst2 is rst) then b else Label(lbl2, loop, bod2, rst2)\n          else\n            registerChange\n            Begin(nestLabelCtx(applyBlock(bod)), applyBlock(rst))\n      \n      // * Remove useless break\n      case Break(label) if tailLabels.contains(label) =>\n        tl.log(s\"Break ${label} is eliminated: current tail label list is ${tailLabels}\")\n        registerChange\n        End()\n      \n      case x => super.applyBlock(x)\n    \n    \n    // FIXME: refactor transformers so this is not so error-prone (adding this case to `applyBlock` doesn't work)\n    override def applyScopedBlock(b: Block): Block = b match\n      // * Delete removed local variables from Scoped blocks\n      case Scoped(syms, body) =>\n        val body2 = applyBlock(body)\n        // println(s\">> $body2 ${body is body2}\")\n        // println(s\">> $body2 ${changed}\")\n        if changed then\n        // if changed || (body isnt body2) then\n          val syms2 = syms.filterNot(removedLocals)\n          // println(s\">> $syms $syms2 ${removedLocals}\")\n          if syms2.size === syms.size && (body2 is body) then b\n          else Scoped(syms2, body2)\n        else b\n      case _ => super.applyScopedBlock(b)\n    \n    override def applyFunBodyLikeBlock(b: Block): Block =\n      nestLabelCtx:\n        super.applyFunBodyLikeBlock(b)\n    \n    override def applySubBlockNonTail(b: Block): Block =\n      nestLabelCtx:\n        super.applySubBlockNonTail(b)\n    \n  end DeadCodeElim\n  \n  \n  object Inliner:\n    object Inliner:\n\n      // Reference to a function body can occur as a.f or f, this handles both cases.\n      object TermSymbolPath:\n        def unapply(p: Path) = p match\n          case Value.Ref(l, S(ts: TermSymbol)) => S(ts)\n          case s: Select => s.symbol match\n            case S(ts: TermSymbol) => S(ts)\n            case _ => N\n          case _ => N\n      \n      def matchArgs(args: List[Arg], params: ParamList): Option[List[(VarSymbol, Result)]] =\n        if args.exists(_.spread.isDefined) then\n          // we require a precise match when any arg is a spread arg\n          if params.restParam.isEmpty then return N\n          if args.exists(_.spread.exists(!_.isEager)) then return N\n          if args.size =/= params.params.size then return N\n          val pairs = args.zip(params.params.iterator.map((_, false)) ++ params.restParam.map((_, true)))\n          if pairs.exists((arg, param) => arg.spread.isDefined =/= param._2) then return N\n          S(pairs.map((arg, param) => (param._1.sym, arg.value)))\n        else\n          // otherwise arg list is a simple list, and\n          // we can perform manual array instantiation if params contain a spread param\n          if params.restParam.isEmpty then\n            if args.size =/= params.params.size then return N\n            S(args.zip(params.params).map((arg, param) => (param.sym, arg.value)))\n          else\n            if args.size < params.params.size then return N\n            val (fixedArgs, restArgs) = args.splitAt(params.params.size)\n            S(fixedArgs.zip(params.params).map((arg, param) => (param.sym, arg.value)) ++\n              List((params.restParam.get.sym, Tuple(true, restArgs))))\n      \n      /** Match multiple argument lists against multiple parameter lists.\n        * Returns None if any arg list fails to match its corresponding param list,\n        * or if there are fewer arg lists than param lists (partial application).\n        * Extra arg lists beyond the param lists are ignored here and should be\n        * handled by the caller (e.g., applied as a chained call on the result). */\n      def matchAllArgs(argss: List[List[Arg]], params: List[ParamList]): Option[List[(VarSymbol, Result)]] =\n        if argss.length < params.length then return N\n        val matchedPairs = argss.zip(params)\n        val allMatched = matchedPairs.foldLeft[Option[List[(VarSymbol, Result)]]](S(Nil)):\n          case (N, _) => N\n          case (S(acc), (args, paramList)) =>\n            matchArgs(args, paramList).map(acc ::: _)\n        allMatched\n    \n    import Inliner.*\n    \n    object InlinerAnalyzer:\n      case class InlinerFunInfo(\n        defn: FunDefn,\n        isMethod: Bool,\n        private[InlinerAnalyzer] var useCount: Int,\n        private[InlinerAnalyzer] var disallowElimination: Bool,\n        private[InlinerAnalyzer] var isLoopBreaker: Bool,\n      ):\n        def isPrivate = !symbolsToPreserve.contains(defn.sym)\n        \n        // Whether this function can be inlined without causing any code duplication,\n        // i.e. the original definition can be removed and there is only one usage.\n        def canBeInlineEliminated =\n          isPrivate && !isMethod && useCount <= 1 && !disallowElimination && !isLoopBreaker\n          // false\n        \n        def shouldBeInlined(newBlk: Block)(using Config.Inliner): Bool =\n          if isLoopBreaker then return false\n          // method requires the capturing of `this`, which is not supported currently.\n          if isMethod then return false\n          val threshold = summon[Config.Inliner].inlineThreshold\n          newBlk.size <= threshold || canBeInlineEliminated\n        \n      type InlinerMap = Map[TermSymbol, InlinerFunInfo]\n      \n      case class FunLikeContext(\n        curFunSym: Opt[TermSymbol],\n      )\n      \n      class Traverser extends BlockTraverser:\n        var map: InlinerMap = Map.empty\n        val useCnt = MutMap.WithDefault(MutMap.empty[TermSymbol, Int], _ => 0)\n        val usages = MutMap.WithDefault(MutMap.empty[TermSymbol, List[(Option[TermSymbol], Call)]], _ => Nil)\n        val hasNakedRef = MutMap.WithDefault(MutMap.empty[TermSymbol, Bool], _ => false)\n        var contextList: List[FunLikeContext] = FunLikeContext(N) :: Nil\n        \n        def currentContext = contextList.head\n        \n        def currentFunSym = currentContext.curFunSym\n        \n        def nested(ts: Option[TermSymbol])(thunk: => Unit) =\n          contextList = FunLikeContext(ts) :: contextList\n          thunk\n          val res = contextList.head\n          contextList = contextList.tail\n          res\n        \n        def addFunctionAndApplyBody(f: FunDefn, isMethod: Bool) =\n          val r = nested(S(f.dSym)):\n            applyBlock(f.body)\n          map = map + (f.dSym -> InlinerFunInfo(f, isMethod, 0, false, false))\n        \n        override def applyDefn(defn: Defn): Unit = defn match\n          case f: FunDefn =>\n            addFunctionAndApplyBody(f, false)\n          case c: ClsLikeDefn =>\n            c.parentPath.foreach(applyPath)\n            c.methods.foreach: f =>\n              addFunctionAndApplyBody(f, true)\n            // Note: no tracking, since `Instantiate` will not be inlined and won't cause cycles.\n            nested(N):\n              applySubBlock(c.preCtor)\n              applySubBlock(c.ctor)\n            c.companion.foreach: m =>\n              m.methods.foreach: f =>\n                addFunctionAndApplyBody(f, true)\n              // This inherits the previous context as the module ctor is run with the constructor.\n              applySubBlock(m.ctor)\n          case _ => super.applyDefn(defn)\n        \n        override def applyResult(r: Result): Unit = r match\n          case c @ Call(TermSymbolPath(ts), argss) =>\n            useCnt(ts) += 1\n            usages(ts) ::= (currentFunSym, c)\n            argss.foreach(_.foreach(applyArg))\n          case _ => super.applyResult(r)\n        \n        override def applySymbol(sym: Symbol): Unit =\n          sym.asTrm.foreach: ts =>\n            useCnt(ts) += 1\n            hasNakedRef(ts) = true\n        \n        def analyze(blk: Block): InlinerMap =\n          applyBlock(blk)\n          map.foreach: (sym, info) =>\n            info.useCount = useCnt(sym)\n            info.disallowElimination = info.disallowElimination || hasNakedRef(sym)\n          val edges: Buffer[(TermSymbol, TermSymbol)] = Buffer.empty\n          usages.foreach: (sym, calls) =>\n            calls.foreach: (caller, call) =>\n              if map.contains(sym) then\n                map(sym).disallowElimination = map(sym).disallowElimination ||\n                  map(sym).defn.params.isEmpty ||\n                  matchAllArgs(call.argss, map(sym).defn.params).isEmpty\n                caller.foreach: caller =>\n                  edges.append((caller, sym))\n          \n          @tailrec\n          def assignLoopBreakers(): Unit =\n            val sccs = partitionScc(edges.filterNot((from, to) => map(to).isLoopBreaker), map.keys)\n            if sccs.forall(_.sizeIs == 1) then return\n            sccs.foreach: sccComp =>\n              if sccComp.sizeIs > 1 then\n                // TODO: Score computation\n                map(sccComp.minBy(_.uid)).isLoopBreaker = true\n            assignLoopBreakers()\n          edges.foreach: (from, to) =>\n            if from === to then\n              map(from).isLoopBreaker = true\n          assignLoopBreakers()\n          map\n      \n      def walk(blk: Block): InlinerMap = Traverser().analyze(blk)\n    \n    import InlinerAnalyzer.InlinerMap\n    \n    \n    object InlinerReplacer:\n      \n      class Copier(resSym: Symbol, existingMapping: Map[Symbol, Symbol])(using State):\n        val lblSym = LabelSymbol(N, \"inlinedLbl\")\n        \n        object Copier extends SymbolRefresher(existingMapping):\n          var currentlyNested = false\n          \n          override def applyFunBodyLikeBlock(b: Block): Block =\n            val saved = currentlyNested\n            currentlyNested = true\n            val res = super.applyFunBodyLikeBlock(b)\n            currentlyNested = saved\n            res\n          \n          override def applyBlock(b: Block): Block = b match\n            case Return(res, false) if !currentlyNested =>\n              applyResult(res): r2 =>\n                Assign(resSym, r2, Break(lblSym))\n            case _ => super.applyBlock(b)\n        \n        def applyBlock(blk: Block) =\n          Label(lblSym, false, Copier.applyBlock(blk), _)\n      \n      class Transformer(m: InlinerMap)(using Config.Inliner, State) extends BlockTransformer(SymbolSubst()):\n        \n        // The call graph may be cyclic, in which case we break the infinite loop using this map by\n        // assuring that the block corresponding to a term symbol may only be transformed once.\n        // This map also allows the function block to be optimized on first use before its declaration.\n        // Key not in map -> not yet analyzed\n        // Key in map but value is None -> the optimized body is being computed\n        // Key in map with value -> the function is optimized\n        val newFunctionBody = MutMap.empty[TermSymbol, Option[Block]]\n        \n        override def applyMainBlock(main: Block): Block =\n          super.applyMainBlock(main).flattened\n        \n        override def applyBlock(blk: Block) = blk match\n          case Define(defn: FunDefn, rest) if m(defn.dSym).canBeInlineEliminated =>\n            tl.log(s\"Inline elimination: ${defn.dSym}\")\n            registerChange\n            applyBlock(rest)\n          case _ => super.applyBlock(blk)\n        \n        override def applyFunDefn(fun: FunDefn): FunDefn =\n          newFunctionBody.get(fun.dSym) match\n            case N =>\n              newFunctionBody(fun.dSym) = N\n              val newBdy = applyBlock(fun.body)\n              newFunctionBody(fun.dSym) = S(newBdy)\n              if newBdy is fun.body then fun else\n              FunDefn(fun.owner, fun.sym, fun.dSym, fun.params, newBdy)(fun.configOverride, fun.annotations)\n            case S(N) =>\n              // The expansion of the function body itself reaches its own definition, which is impossible\n              lastWords(\"Function body contains its own definition.\")\n            case S(S(blk)) =>\n              if blk is fun.body then fun else\n              FunDefn(fun.owner, fun.sym, fun.dSym, fun.params, blk)(fun.configOverride, fun.annotations)\n        \n        override def applyResult(r: Result)(k: Result => Block): Block = r match\n          case c @ Call(TermSymbolPath(ts), argss) if m.contains(ts) && argss.nonEmpty =>\n            newFunctionBody.get(ts)\n            .getOrElse:\n              newFunctionBody(ts) = N\n              val newBdy = applyBlock(m(ts).defn.body)\n              newFunctionBody(ts) = S(newBdy)\n              S(newBdy)\n            .fold(super.applyResult(r)(k)): blk =>\n              val info = m(ts)\n              if !info.shouldBeInlined(blk) then\n                super.applyResult(r)(k)\n              else\n                val matchedArgs = matchAllArgs(argss, info.defn.params)\n                matchedArgs match\n                case N =>\n                  super.applyResult(r)(k)\n                case S(matchedArgs) =>\n                  registerChange\n                  tl.log(s\"Inline call for ${ts}, with args ${argss}\")\n                  val extraArgss = argss.drop(info.defn.params.length)\n                  def go(acc: Block => Block, args: List[(VarSymbol, Result)], mapping: Map[Symbol, Symbol]): Block =\n                    args match\n                    case Nil =>\n                      val resSym = TempSymbol(N, \"inlinedVal\")\n                      val copier = Copier(resSym, mapping)\n                      val newBlk = copier.applyBlock(blk)\n                      if extraArgss.isEmpty then\n                        acc(Scoped(Set.single(resSym), newBlk(k(Value.Ref(resSym)))))\n                      else\n                        acc(Scoped(Set(resSym), newBlk(\n                          k(Call(resSym.asPath, extraArgss.ne_!)(c.isMlsFun, c.mayRaiseEffects, false)))))\n                    case (sym, value) :: argRest =>\n                      val newSym = VarSymbol(sym.id)\n                      go(acc.assignScoped(newSym, value), argRest, mapping + (sym -> newSym))\n                  go(blockBuilder, matchedArgs, Map.empty)\n          case _ => super.applyResult(r)(k)\n      \n      def replace(m: InlinerMap, prog: Program)(using Config.Inliner, State): Program =\n        Transformer(m).applyProgram(prog)\n    \n    class Inliner(using Config.Inliner, State):\n      def applyProgram(prog: Program): Program =\n        val m = InlinerAnalyzer.walk(prog.main)\n        InlinerReplacer.replace(m, prog)\n  end Inliner\n  \n  \nend BlockSimplifier\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTransformer.scala",
    "content": "package hkmc2\npackage codegen\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport semantics.*\n\n\n// Default implementation: nothing is transformed\nclass BlockTransformer(subst: SymbolSubst):\n  \n  given SymbolSubst = subst\n  \n  def applyProgram(prog: Program): Program =\n    val imports2 = prog.imports.mapConserve(applyImport)\n    val main2 = applyMainBlock(prog.main)\n    if (imports2 is prog.imports) && (main2 is prog.main) then prog\n    else Program(imports2, main2)\n  \n  def applyMainBlock(main: Block): Block =\n    applyBlock(main)\n  \n  def applyImport(imp: Local -> Str): Local -> Str =\n    val (l, s) = imp\n    val l2 = applyLocal(l)\n    if l2 is l then imp else l2 -> s\n  \n  def applySubBlock(b: Block): Block = applyBlock(b)\n\n  /** Called for any sub block not in the `rest` position (when `rest` is nonempty).\n    * This is not called for Label body or function body. */\n  def applySubBlockNonTail(b: Block): Block = applySubBlock(b)\n  \n  def applyBlock(b: Block): Block = b match\n    case _: End | _: Unreachable => b\n    case Break(lbl) =>\n      val lbl2 = lbl.subst\n      if lbl2 is lbl then b else Break(lbl2)\n    case Continue(lbl) =>\n      val lbl2 = lbl.subst\n      if lbl2 is lbl then b else Continue(lbl2)\n    case Return(res, implct) =>\n      applyResult(res): res2 =>\n        if res2 is res then b else Return(res2, implct)\n    case Throw(exc) =>\n      applyResult(exc): exc2 =>\n        if exc2 is exc then b else Throw(exc2)\n    case Match(scrut, arms, dflt, rst) =>\n      def applySub(b: Block) = if rst.isEmpty then applySubBlock(b) else applySubBlockNonTail(b)\n      applyPath(scrut): scrut2 =>\n        applyListOf(\n          arms,\n          (tup, k) =>\n            val (cse, blk) = tup\n            val blk2 = applySub(blk)\n            applyCase(cse): cse2 =>\n              if (cse2 is cse) && (blk is blk2) then k(tup) else k(cse2 -> blk2)\n        ): arms2 =>\n            val dflt2 = dflt.mapConserve(applySub)\n            val rst2 = applySubBlock(rst)\n            if (scrut2 is scrut) &&\n                (arms2 is arms) &&\n                (dflt2 is dflt) && (rst2 is rst)\n              then b else Match(scrut2, arms2, dflt2, rst2)\n    case Label(lbl, loop, bod, rst) =>\n      val lbl2 = lbl.subst\n      val bod2 = if loop then applyScopedBlock(bod) else applySubBlock(bod)\n      val rst2 = applySubBlock(rst)\n      if (lbl2 is lbl) && (bod2 is bod) && (rst2 is rst) then b else Label(lbl2, loop, bod2, rst2)\n    case Begin(sub, rst) =>\n      def applySub(b: Block) = if rst.isEmpty then applySubBlock(b) else applySubBlockNonTail(b)\n      val sub2 = applySub(sub)\n      val rst2 = applySubBlock(rst)\n      if (sub2 is sub) && (rst2 is rst) then b else Begin(sub2, rst2)\n    case TryBlock(sub, fin, rst) =>\n      def applySub(b: Block) = if rst.isEmpty then applySubBlock(b) else applySubBlockNonTail(b)\n      val sub2 = applySub(sub)\n      val fin2 = applySub(fin)\n      val rst2 = applySubBlock(rst)\n      if (sub2 is sub) && (fin2 is fin) && (rst2 is rst) then b else TryBlock(sub2, fin2, rst2)\n    case Assign(l, r, rst) =>\n      applyResult(r): r2 =>\n        val l2 = applyLocal(l)\n        val rst2 = applySubBlock(rst)\n        if (l2 is l) && (r2 is r) && (rst2 is rst) then b else Assign(l2, r2, rst2)\n    case b @ AssignField(l, n, r, rst) =>\n      applyResult(r): r2 =>\n        applyPath(l): l2 =>\n          val rst2 = applySubBlock(rst)\n          val sym = b.symbol.mapConserve(_.subst)\n          if (l2 is l) && (r2 is r) && (rst2 is rst) && (sym is b.symbol)\n            then b else AssignField(l2, n, r2, rst2)(sym)\n    case Define(defn, rst) =>\n      applyDefn(defn): defn2 =>\n        val rst2 = applySubBlock(rst)\n        if (defn2 is defn) && (rst2 is rst) then b else Define(defn2, rst2)\n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>\n      applyResult(rhs): rhs2 =>\n        applyPath(lhs): lhs2 =>\n          applyPath(fld): fld2 =>\n            val rest2 = applySubBlock(rest)\n            if (lhs2 is lhs) && (fld2 is fld) && (rhs2 is rhs) && (rest2 is rest)\n            then b\n            else AssignDynField(lhs2, fld2, arrayIdx, rhs2, rest2)\n    case _: Scoped => applyScopedBlock(b)\n  \n  // FunDefn body, Lambda body, Handler body, ctor and pCtor are considered \"funBodyLike\"\n  def applyFunBodyLikeBlock(b: Block): Block = applyScopedBlock(b)\n  \n  // Apply to Blocks that are conceptually \"scoped\", which includes:\n  // - \"funBodyLike\" blocks\n  // - loop body blocks\n  // - manually nested `Scoped` blocks\n  // These blocks are usually instances of `Scoped`, but \"funBodyLike\" and loop bodies\n  // may not be `Scoped` in practice, because empty `Scoped` blocks may be ignored\n  def applyScopedBlock(b: Block): Block = b match\n    case Scoped(s, bd) =>\n      val nb = applySubBlock(bd)\n      if nb is bd then b else Scoped(s, nb)\n    case _ => applySubBlock(b)\n  \n  \n  def applyRcdArg(rcdArg: RcdArg)(k: RcdArg => Block): Block =\n    val RcdArg(idx, p) = rcdArg\n    val toBeIdxed = (idx2: Opt[Path]) =>\n      applyPath(p): p2 =>\n        k(if (p2 is p) && (idx2 is idx) then rcdArg else RcdArg(idx2, p2))\n    idx match\n      case Some(i) =>\n        applyPath(i): i2 =>\n          toBeIdxed(if i is i2 then idx else Some(i2))\n      case None => toBeIdxed(idx)\n  \n  def applyRcdArgs(rcdArgs: List[RcdArg])(k: List[RcdArg] => Block): Block =\n    applyListOf(rcdArgs, applyRcdArg(_)(_))(k)\n  \n  def applyArgs(args: List[Arg])(k: List[Arg] => Block): Block =\n    applyListOf(args, applyArg(_)(_))(k)\n\n  def applyArgss(argss: NELs[List[Arg]])(k: NELs[List[Arg]] => Block): Block =\n    applyListOf(argss, applyArgs(_)(_)): newArgss =>\n      k(newArgss.ne_!)\n  \n  def applyArgss(argss: List[List[Arg]])(k: List[List[Arg]] => Block): Block =\n    applyListOf(argss, applyArgs(_)(_))(k)\n  \n  def applyResult(r: Result)(k: Result => Block): Block =\n    r match\n    case r @ Call(fun, argss) =>\n      applyPath(fun): fun2 =>\n        applyListOf(argss, (args, k2) => applyArgs(args)(k2)): argss2 =>\n          k(if (fun2 is fun) && (argss2 is argss) then r\n            else Call(fun2, argss2.ne_!)(r.isMlsFun, r.mayRaiseEffects, r.explicitTailCall).withLocOf(r))\n    case Instantiate(mut, cls, argss) =>\n      applyPath(cls): cls2 =>\n        applyListOf(argss, (args, k2) => applyArgs(args)(k2)): argss2 =>\n          k(if (cls2 is cls) && (argss2 is argss) then r\n            else Instantiate(mut, cls2, argss2).withLocOf(r))\n    case l: Lambda => k(applyLam(l))\n    case Tuple(mut, elems) =>\n      applyArgs(elems): elems2 =>\n        k(if (elems2 is elems) then r else Tuple(mut, elems2).withLocOf(r))\n    case Record(mut, fields) =>\n      applyRcdArgs(fields): fields2 =>\n        k(if fields2 is fields then r else Record(mut, fields2).withLocOf(r))\n    case p: Path => applyPath(p)(k)\n  \n  def applyPath(p: Path)(k: Path => Block): Block = p match\n    case DynSelect(qual, fld, arrayIdx) =>\n      applyPath(qual): qual2 =>\n        applyPath(fld): fld2 =>\n          k(if (qual2 is qual) && (fld2 is fld) then p else DynSelect(qual2, fld2, arrayIdx).withLocOf(p))\n    case p @ Select(qual, name) =>\n      applyPath(qual): qual2 =>\n        val sym2 = p.symbol.mapConserve(_.subst)\n        k(if (qual2 is qual) && (sym2 is p.symbol) then p else Select(qual2, name)(sym2).withLocOf(p))\n    case v: Value => applyValue(v)(k)\n  \n  def applyValue(v: Value)(k: Value => Block) = v match\n    case Value.Ref(l, disamb) =>\n      val l2 = applyLocal(l)\n      k(if (l2 is l) then v else Value.Ref(l2, disamb).withLocOf(v))\n    case Value.This(sym) =>\n      val sym2 = sym.subst\n      k(if (sym2 is sym) then v else Value.This(sym2).withLocOf(v))\n    case Value.Lit(lit) => k(v)\n  \n  def applyLocal(sym: Local): Local = sym.subst\n  \n  def applyFunDefn(fun: FunDefn): FunDefn =\n    val own2 = fun.owner.mapConserve(_.subst)\n    val sym2 = fun.sym.subst\n    val dSym2 = fun.dSym.subst\n    val params2 = fun.params.mapConserve(applyParamList)\n    val body2 = applyFunBodyLikeBlock(fun.body)\n    if (own2 is fun.owner) && (sym2 is fun.sym) && (dSym2 is fun.dSym) && (params2 is fun.params) && (body2 is fun.body)\n      then fun else FunDefn(own2, sym2, dSym2, params2, body2)(fun.configOverride, fun.annotations)\n  \n  def applyValDefn(defn: ValDefn)(k: ValDefn => Block): Block =\n    val ValDefn(tsym, sym, rhs) = defn\n    val tsym2 = tsym.subst\n    val sym2 = sym.subst\n    applyPath(rhs): rhs2 =>\n      if (tsym2 is tsym) && (sym2 is sym) && (rhs2 is rhs)\n        then k(defn) else k(ValDefn(tsym2, sym2, rhs2)(defn.configOverride, defn.annotations))\n  \n  def applyPublicField(f: BlockMemberSymbol -> TermSymbol): BlockMemberSymbol -> TermSymbol =\n    val f_1_2 = f._1.subst\n    val f_2_2 = f._2.subst\n    if (f_1_2 is f._1) && (f_2_2 is f._2) then f else f_1_2 -> f_2_2\n  \n  def applyObjBody(defn: ClsLikeBody): ClsLikeBody =\n    val isym2 = defn.isym.subst\n    val methods2 = defn.methods.mapConserve(applyFunDefn)\n    val privateFields2 = defn.privateFields.mapConserve(_.subst)\n    val publicFields2 = defn.publicFields.mapConserve(applyPublicField)\n    val ctor2 = applyFunBodyLikeBlock(defn.ctor)\n    if (methods2 is defn.methods) &&\n        (privateFields2 is defn.privateFields) &&\n        (publicFields2 is defn.publicFields) &&\n        (ctor2 is defn.ctor)\n      then defn else ClsLikeBody(isym2, methods2, privateFields2, publicFields2, ctor2, defn.annotations)\n    \n  def applyDefn(defn: Defn)(k: Defn => Block): Block = defn match\n    case defn: FunDefn => k(applyFunDefn(defn))\n    case defn: ValDefn => applyValDefn(defn)(k)\n    case defn @ ClsLikeDefn(own, isym, sym, ctorSym, kind, paramsOpt, auxParams, parentPath, methods,\n        privateFields, publicFields, preCtor, ctor, mod, bufferable)\n    =>\n      val own2 = own.mapConserve(_.subst)\n      val isym2 = isym.subst\n      val sym2 = sym.subst\n      val ctorSym2 = ctorSym.mapConserve(_.subst)\n      val paramsOpt2 = paramsOpt.mapConserve(applyParamList)\n      val auxParams2 = auxParams.mapConserve(applyParamList)\n      def helper(parentPath2: Opt[Path]) =\n        val methods2 = methods.mapConserve(applyFunDefn)\n        val privateFields2 = privateFields.mapConserve(_.subst)\n        val publicFields2 = publicFields.mapConserve(applyPublicField)\n        val preCtor2 = applyFunBodyLikeBlock(preCtor)\n        val ctor2 = applyFunBodyLikeBlock(ctor)\n        val mod2 = mod.mapConserve(applyObjBody)\n        k:\n          if (own2 is own) && (isym2 is isym) && (sym2 is sym) && (ctorSym2 is ctorSym) &&\n              (paramsOpt2 is paramsOpt) &&\n              (auxParams2 is auxParams) &&\n              (parentPath2 is parentPath) &&\n              (methods2 is methods) &&\n              (privateFields2 is privateFields) &&\n              (publicFields2 is publicFields) &&\n              (preCtor2 is preCtor) && (ctor2 is ctor) &&\n              (mod2 is mod)\n            then defn else ClsLikeDefn(own2, isym2, sym2, ctorSym2, kind, paramsOpt2, \n              auxParams2, parentPath2, methods2, privateFields2, publicFields2, preCtor2, ctor2, mod2, bufferable)(defn.configOverride, defn.annotations)\n      parentPath match\n      case Some(pp) => applyPath(pp): pp2 =>\n        helper:\n          if pp2 is pp then parentPath else Some(pp2)\n      case None => helper(parentPath)\n      \n  \n  def applyArg(arg: Arg)(k: Arg => Block): Block =\n    applyPath(arg.value): val2 =>\n      k(if val2 is arg.value then arg else Arg(arg.spread, val2))\n  \n  def applyParamList(pl: ParamList): ParamList =\n    def applyParam(p: Param): Param =\n      val sym2 = p.sym.subst\n      if sym2 is p.sym then p else p.copy(sym = sym2)\n    val params2 = pl.params.mapConserve(applyParam)\n    val rest2 = pl.restParam.mapConserve(applyParam)\n    if (params2 is pl.params) && (rest2 is pl.restParam)\n      then pl else ParamList(pl.flags, params2, rest2)\n  \n  def applyCase(cse: Case)(k: Case => Block): Block = cse match\n    case Case.Lit(lit) => k(cse)\n    case Case.Cls(cls, path) =>\n      val cls2 = cls.subst\n      applyPath(path): path2 =>\n        k(if (cls2 is cls) && (path2 is path) then cse else Case.Cls(cls2, path2))\n    case Case.Tup(len, inf) => k(cse)\n    case Case.Field(name, safe) => k(cse)\n  \n  def applyHandler(hdr: Handler): Handler =\n    val sym2 = hdr.sym.subst\n    val resumeSym2 = hdr.resumeSym.subst\n    val params2 = hdr.params.mapConserve(applyParamList)\n    val body2 = applyFunBodyLikeBlock(hdr.body)\n    if (sym2 is hdr.sym) && (resumeSym2 is hdr.resumeSym) &&\n        (params2 is hdr.params) && (body2 is hdr.body)\n      then hdr else Handler(sym2, resumeSym2, params2, body2)\n  \n  def applyLam(lam: Lambda): Lambda =\n    val params2 = applyParamList(lam.params)\n    val body2 = applyFunBodyLikeBlock(lam.body)\n    if (params2 is lam.params) && (body2 is lam.body) then lam else Lambda(params2, body2)\n  \n  def applyListOf[A](ls: List[A], f: (A, (A => Block)) => Block)(k: List[A] => Block): Block =\n    def rec(ls: List[A], k: List[A] => Block): Block = ls match\n      case Nil => k(Nil)\n      case a :: t =>\n        f(a, a2 => rec(t, t2 => if (a2 is a) && (t2 is t) then k(ls) else k(a2 :: t2)))\n    rec(ls, k)\n\n\n\nclass BlockTransformerShallow(subst: SymbolSubst) extends BlockTransformer(subst):\n  override def applyLam(lam: Lambda) = lam\n  // Note: no need to override things like applyFunDefn, as they are only called by applyDefn\n  override def applyDefn(defn: Defn)(k: Defn => Block): Block = defn match\n    case _: FunDefn | _: ClsLikeDefn => k(defn)\n    case _: ValDefn => super.applyDefn(defn)(k)\n  \n  override def applyHandler(hdr: Handler): Handler = hdr\n\n// Does not traverse into sub-blocks or definitions. The purpose of this is is to only rewrite a block's data, i.e. \n// paths, values, cases, etc. within a block. Can be used in tandem with `BlockTransformer` or `BlockTransformerShallow` \n// to traverse sub-blocks while using this class to perform more complicated transformations on the blocks themselves.\nclass BlockDataTransformer(subst: SymbolSubst) extends BlockTransformerShallow(subst):\n  override def applySubBlock(b: Block): Block = b\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/BlockTraverser.scala",
    "content": "package hkmc2\npackage codegen\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport semantics.*\n\n\n// These all work like BlockTransformer and its derivatives, but do not rewrite the block. See BlockTransformer.scala.\n// Please use this instead of BlockTransformer for static analysis.\n\nclass BlockTraverser:\n  \n  extension (sym: Symbol)\n    inline def traverse: Unit = applySymbol(sym)\n  \n  \n  def applyProgram(prog: Program): Unit =\n    prog.imports.foreach(applyImport)\n    applyBlock(prog.main)\n  \n  def applyImport(imp: Local -> Str): Unit =\n    applyLocal(imp._1)\n  \n  \n  def applySymbol(sym: Symbol): Unit = ()\n  \n  def applySubBlock(b: Block): Unit = applyBlock(b)\n  \n  def applyBlock(b: Block): Unit = b match\n    case _: End | _: Unreachable => ()\n    case Break(lbl) => applyLocal(lbl)\n    case Continue(lbl) => applyLocal(lbl)\n    case Return(res, implct) => applyResult(res)\n    case Throw(exc) => applyResult(exc)\n    case Match(scrut, arms, dflt, rst) =>\n      val scrut2 = applyPath(scrut)\n      arms.foreach: arm =>\n        applyCase(arm._1); applySubBlock(arm._2)\n      dflt.foreach(applySubBlock)\n      applySubBlock(rst)\n    case Label(lbl, loop, bod, rst) => applyLocal(lbl); applySubBlock(bod); applySubBlock(rst)\n    case Begin(sub, rst) => applySubBlock(sub); applySubBlock(rst)\n    case TryBlock(sub, fin, rst) => applySubBlock(sub); applySubBlock(fin); applySubBlock(rst)\n    case Assign(l, r, rst) => applyLocal(l); applyResult(r); applySubBlock(rst)\n    case b @ AssignField(l, n, r, rst) =>\n      applyPath(l); applyResult(r); applySubBlock(rst); b.symbol.foreach(_.traverse)\n    case Define(defn, rst) => applyDefn(defn); applySubBlock(rst)\n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>\n      applyPath(lhs)\n      applyResult(rhs)\n      applyPath(fld)\n      applySubBlock(rest)\n    case Scoped(_, body) => applySubBlock(body)\n  \n  def applyResult(r: Result): Unit = r match\n    case r @ Call(fun, argss) => applyPath(fun); argss.foreach(_.foreach(applyArg))\n    case Instantiate(mut, cls, argss) => applyPath(cls); argss.foreach(_.foreach(applyArg))\n    case l @ Lambda(params, body) => applyLam(l)\n    case Tuple(mut, elems) => elems.foreach(applyArg)\n    case Record(mut, fields) => fields.foreach:\n      case RcdArg(idx, value) => idx.foreach(applyPath); applyPath(value)\n    case p: Path => applyPath(p)\n  \n  def applyPath(p: Path): Unit = p match\n    case DynSelect(qual, fld, arrayIdx) =>\n      applyPath(qual); applyPath(fld)\n    case p @ Select(qual, name) =>\n      applyPath(qual); p.symbol.foreach(_.traverse)\n    case v: Value => applyValue(v)\n  \n  def applyValue(v: Value): Unit = v match\n    case Value.Ref(l, disamb) =>\n      l.traverse\n      disamb.foreach(_.traverse)\n    case Value.This(sym) => sym.traverse\n    case Value.Lit(lit) => ()\n  \n  def applyLocal(sym: Local): Unit = sym.traverse\n  \n  def applyFunDefn(fun: FunDefn): Unit =\n    fun.owner.foreach(_.traverse)\n    fun.sym.traverse\n    fun.dSym.traverse\n    fun.params.foreach(applyParamList)\n    applySubBlock(fun.body)\n  \n  def applyValDefn(defn: ValDefn): Unit =\n    val ValDefn(tsym, sym, rhs) = defn\n    tsym.owner.foreach(_.traverse); sym.traverse; applyPath(rhs)\n  \n  def applyDefn(defn: Defn): Unit = defn match\n    case defn: FunDefn => applyFunDefn(defn)\n    case defn: ValDefn => applyValDefn(defn)\n    case ClsLikeDefn(own, isym, sym, ctorSym, k, paramsOpt, auxParams, parentPath, methods,\n        privateFields, publicFields, preCtor, ctor, mod, bufferable)\n    =>\n      own.foreach(_.traverse)\n      isym.traverse\n      sym.traverse\n      ctorSym.foreach(_.traverse)\n      paramsOpt.foreach(applyParamList)\n      auxParams.foreach(applyParamList)\n      parentPath.foreach(applyPath)\n      methods.foreach(applyFunDefn)\n      privateFields.foreach(_.traverse)\n      publicFields.foreach: f =>\n        f._1.traverse; f._2.traverse\n      applySubBlock(preCtor)\n      applySubBlock(ctor)\n      mod.foreach(applyCompanionModule)\n  \n  def applyCompanionModule(b: ClsLikeBody): Unit =\n    b.isym.traverse\n    b.methods.foreach(applyFunDefn)\n    b.privateFields.foreach(_.traverse)\n    b.publicFields.foreach: f =>\n      f._1.traverse; f._2.traverse\n    applySubBlock(b.ctor)\n\n  def applyArg(arg: Arg): Unit =\n    applyPath(arg.value)\n  \n  def applyParamList(pl: ParamList): Unit =\n    pl.params.foreach(_.sym.traverse)\n    pl.restParam.foreach(_.sym.traverse)\n  \n  def applyCase(cse: Case): Unit = cse match\n    case Case.Lit(lit) => ()\n    case Case.Cls(cls, path) =>\n      cls.traverse\n      applyPath(path)\n    case Case.Tup(len, inf) => ()\n    case Case.Field(_, _) => ()\n  \n  def applyHandler(hdr: Handler): Unit =\n    hdr.sym.traverse\n    hdr.resumeSym.traverse\n    hdr.params.foreach(applyParamList)\n    applySubBlock(hdr.body)\n  \n  def applyLam(lam: Lambda): Unit =\n    applyParamList(lam.params)\n    applySubBlock(lam.body)\n  \nclass BlockTraverserShallow extends BlockTraverser:\n  override def applyLam(lam: Lambda) = ()\n  override def applyFunDefn(fun: FunDefn): Unit = ()\n  override def applyDefn(defn: Defn): Unit = defn match\n    case _: FunDefn | _: ClsLikeDefn => ()\n    case _: ValDefn => super.applyDefn(defn)\n  \n  override def applyHandler(hdr: Handler): Unit = ()\n\nclass BlockDataTraverser extends BlockTraverserShallow:\n  override def applySubBlock(b: Block): Unit = ()\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/BufferableTransform.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.annotation.tailrec\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\nimport hkmc2.utils.SymbolSubst\n\nimport syntax.{Literal, Tree}\nimport semantics.*\nimport semantics.Elaborator.{Ctx, ctx}\nimport semantics.Elaborator.State\nimport hkmc2.Message.MessageContext\nimport hkmc2.syntax.Tree.DummyTypeDef\n\nclass BufferableTransform()(using Ctx, State, Raise):\n  def transform(blk: Block): Block =\n    val transformer = new BlockTransformer(SymbolSubst.Id):\n      override def applyDefn(defn: Defn)(k: Defn => Block): Block = defn match\n        case cls: ClsLikeDefn if cls.k is syntax.Cls =>\n          cls.bufferable.fold(super.applyDefn(defn)(k)): bufferable =>\n            val companionSym = ModuleOrObjectSymbol(DummyTypeDef(syntax.Mod), new Tree.Ident(cls.sym.nme))\n            val clsSizeSym = BlockMemberSymbol(\"size\", Nil, false)\n            val clsSizeTermSym = TermSymbol(syntax.ImmutVal, S(companionSym), new Tree.Ident(\"size\"))\n            val pubFieldMap: Map[Symbol, Symbol] = cls.publicFields.toMap\n            val fields = cls.privateFields ++ cls.publicFields.map(_._2)\n            val fieldMap: Map[Symbol, Int] = fields.zipWithIndex.toMap\n            def mkSymbolReplacer(params: List[ParamList]): (List[ParamList], Map[Symbol, Symbol]) =\n              val allVars = params.flatMap(_.allParams).map(_.sym)\n              val varMap = allVars\n                .map: sym =>\n                  (sym, VarSymbol(sym.id))\n                .toMap\n              def mapParam(p: Param) =\n                Param(p.flags, varMap(p.sym), p.sign, p.modulefulness)\n              (params.map(pl => ParamList(pl.flags, pl.params.map(mapParam), pl.restParam.map(mapParam))), varMap.toMap)\n            def mkFieldReplacer(buf: Local, baseIdx: Local, symMap: Map[Symbol, Symbol]) =\n              def getOffset(off: Int)(k: Path => Block): Block =\n                val idxSymbol = new TempSymbol(N, \"idx\")\n                Scoped(Set.single(idxSymbol), Assign(idxSymbol, Call(State.builtinOpsMap(\"+\").asPath, (baseIdx.asPath.asArg :: Value.Lit(Tree.IntLit(off)).asArg :: Nil) ne_:: Nil)(true, false, false),\n                  k(DynSelect(buf.asPath.selSN(\"buf\"), idxSymbol.asPath, true))))\n              def assignToOffset(off: Int, r: Result, rst: Block) =\n                val idxSymbol = new TempSymbol(N, \"idx\")\n                Scoped(Set.single(idxSymbol), Assign(idxSymbol, Call(State.builtinOpsMap(\"+\").asPath, (baseIdx.asPath.asArg :: Value.Lit(Tree.IntLit(off)).asArg :: Nil) ne_:: Nil)(true, false, false),\n                  AssignDynField(buf.asPath.selSN(\"buf\"), idxSymbol.asPath, true, r, applyBlock(rst))))\n              new BlockTransformer(SymbolSubst.Id):\n                override def applyLocal(sym: Local): Local = symMap.getOrElse(sym, sym)\n                override def applyBlock(b: Block): Block = b match\n                  case Assign(l, r, rst) =>\n                    fieldMap.get(l).fold(super.applyBlock(b)): off =>\n                      applyResult(r): r2 =>\n                        assignToOffset(off, r2, applyBlock(rst))\n                  case af @ AssignField(l, n, r, rst) =>\n                    af.symbol.flatMap(pubFieldMap.get(_)).flatMap(fieldMap.get(_))\n                      .fold(super.applyBlock(b)): off =>\n                        applyResult(r): r2 =>\n                          assignToOffset(off, r2, applyBlock(rst))\n                  case Define(defn: ValDefn, rst) =>\n                    fieldMap.get(defn.tsym).fold(super.applyBlock(b)): off =>\n                      applyResult(defn.rhs): r2 =>\n                        assignToOffset(off, r2, applyBlock(rst))\n                  case _ => super.applyBlock(b)\n                override def applyPath(p: Path)(k: Path => Block): Block = p match\n                  case sel: Select =>\n                    sel.symbol.fold(super.applyPath(p)(k)): sym =>\n                      fieldMap.get(sym).orElse(pubFieldMap.get(sym).flatMap(fieldMap.get(_))).fold(super.applyPath(p)(k)): off =>\n                        getOffset(off): res =>\n                          k(res)\n                  case Value.Ref(l, _) =>\n                    fieldMap.get(l).fold(super.applyPath(p)(k)): off =>\n                      getOffset(off): res =>\n                        k(res)\n                  case _ => super.applyPath(p)(k)\n            def transformFunDefn(f: FunDefn, isCtor: Bool): FunDefn =\n              val buf = VarSymbol(new Tree.Ident(\"buf\"))\n              val idx = VarSymbol(new Tree.Ident(\"idx\"))\n              val (newParams, symMap) = mkSymbolReplacer(f.params)\n              val blk = mkFieldReplacer(buf, idx, symMap).applyBlock(f.body)\n              FunDefn(f.owner, f.sym, TermSymbol(f.dSym.k, f.dSym.owner, f.dSym.id), PlainParamList(\n                Param(FldFlags.empty, buf, N, Modulefulness.none) :: Param(FldFlags.empty, idx, N, Modulefulness.none) :: Nil) :: newParams,\n                if isCtor then Begin(blk, Return(idx.asPath, false)) else blk)(configOverride = f.configOverride, annotations = f.annotations)\n            val fakeCtor = transformFunDefn(FunDefn.withFreshSymbol(\n                S(companionSym), \n                BlockMemberSymbol(\"ctor\", Nil, false), \n                cls.paramsOpt.toList,\n                Begin(cls.preCtor, cls.ctor),\n              )(N, annotations = Nil), true)\n            val fakeCompanion = ClsLikeBody(\n              companionSym,\n              fakeCtor :: cls.methods.map(transformFunDefn(_, false)),\n              Nil,\n              clsSizeSym -> clsSizeTermSym :: Nil,\n              Define(ValDefn(clsSizeTermSym, clsSizeSym, Value.Lit(Tree.IntLit(fields.size)))(N, Nil), End()),\n              annotations = Nil,\n            )\n            k:\n              ClsLikeDefn(\n                cls.owner,\n                cls.isym,\n                cls.sym,\n                cls.ctorSym,\n                cls.k,\n                if bufferable then cls.paramsOpt else N,\n                if bufferable then cls.auxParams else Nil,\n                cls.parentPath,\n                if bufferable then cls.methods else Nil,\n                cls.privateFields,\n                cls.publicFields,\n                if bufferable then cls.preCtor else End(),\n                if bufferable then cls.ctor else End(),\n                S(fakeCompanion),\n                cls.bufferable,\n              )(cls.configOverride, cls.annotations)\n        case _ => super.applyDefn(defn)(k)\n    transformer.applyBlock(blk)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/CachedAnalysis.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet}\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\n\ntrait CachedAnalysis[A, R]:\n  \n  def analyzeUncached(a: A): R\n  \n  import java.util.IdentityHashMap\n  \n  val cache: IdentityHashMap[A, R] = new IdentityHashMap\n  extension (a: A) def analyze: R =\n    cache.get(a) match\n      case null =>\n        val res = analyzeUncached(a)\n        cache.put(a, res)\n        res\n      case res => res\n\nend CachedAnalysis\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/DeadParamElim.scala",
    "content": "package hkmc2\npackage codegen\n\nimport utils.*\nimport mlscript.utils.*, shorthands.*\nimport semantics.*\nimport syntax.Tree\nimport hkmc2.codegen.flowAnalysis.*\nimport hkmc2.syntax.Fun\nimport scala.collection.mutable.{Set as MutSet, Map as MutMap, LinkedHashMap, Buffer}\n\n\ntype ConcreteFunId = FunId -> InstantiationId\ntype ConcreteCallSiteId = ResultId -> InstantiationId\n\n\nclass DeadParamElimSolver(val constraintSolver: FlowConstraintSolver):\n  \n  given tl: TraceLogger = constraintSolver.tl\n  given fState: FlowAnalysis.State = constraintSolver.fState\n  given eState: Elaborator.State = constraintSolver.eState\n\n  val collector: FlowConstraintsCollector = constraintSolver.collector\n  val funDests: collection.Map[ProdFun, Set[ConsFun | NoCons.type]] =\n    constraintSolver.funDests\n  val funSrcs: collection.Map[ConsFun, Set[ProdFun | NoProd.type]] =\n    constraintSolver.funSrcs\n\n  extension (prodFun: ProdFun)\n    def concreteId: ConcreteFunId = prodFun.funId -> prodFun.instantiationId.get\n  \n  extension (consFun: ConsFun)\n    def concreteId: ConcreteCallSiteId = consFun.exprId -> consFun.instantiationId.get\n  \n  // handle clashes for dead param elim\n  val (liveParams, liveCallSiteParams) =\n    def isSyntheticRoot(prodFun: ProdFun): Bool =\n      val instId = prodFun.instantiationId.get\n      collector.synthesizedInstIdToFunSym.get(instId).exists: rootFunSym =>\n        prodFun.funId match\n          case (funSym: TermSymbol, _) =>\n            (collector.funToSccRep(funSym), collector.funToSccRep(rootFunSym)) match\n            case S(rep1) -> S(rep2) => rep1 is rep2\n            case _ => false\n          case _ => false\n    end isSyntheticRoot\n    \n    val prodRoots = Buffer.empty[(ProdFun, Int)]\n    val consRoots = Buffer.empty[(ConsFun, Int)]\n    for (prodFun, dests) <- funDests do\n      if isSyntheticRoot(prodFun) || dests.contains(NoCons) then\n        prodFun.params.indices.foreach: i =>\n          prodRoots += prodFun -> i\n      else\n        prodFun.params.zipWithIndex.foreach:\n          case (ConsVar(s), i) =>\n            val ubs = constraintSolver.upperBounds(s.uid)\n            if ubs.exists(!_.isInstanceOf[ConsVar]) then\n              prodRoots += prodFun -> i\n          case (_, i) =>\n            prodRoots += prodFun -> i\n\n    for (consFun, srcs) <- funSrcs do\n      if srcs.contains(NoProd) then\n        consFun.params.indices.foreach: i =>\n          consRoots += consFun -> i\n      else\n        val minSize = srcs\n          .collect:\n            case p: ProdFun if p.restParam.isDefined => p.params.size\n          .minOption\n        minSize match\n        case None => ()\n        case Some(s) =>\n          (s until consFun.params.size).foreach: i =>\n            consRoots += consFun -> i\n        \n\n    val result = FlowWebComputation[(ProdFun, Int), (ConsFun, Int)](\n      (prodFun, idx) => funDests(prodFun).collect:\n        case c: ConsFun => (c, idx),\n      (consFun, idx) => funSrcs(consFun).collect:\n        case p: ProdFun => (p, idx),\n      prodRoots,\n      consRoots,\n    )\n    (result.markedProducers, result.markedConsumers)\n  end val\n  \n  val eliminableParamsById =\n    LinkedHashMap.empty[ConcreteFunId, Set[Int]].withDefaultValue(Set.empty)\n  val eliminableCallSiteArgsById =\n    LinkedHashMap.empty[ConcreteCallSiteId, Set[Int]].withDefaultValue(Set.empty)\n  \n  for (prodFun, _) <- funDests do\n    val eliminable = prodFun.params.indices.filterNot: i =>\n      liveParams.contains(prodFun -> i)\n    if eliminable.nonEmpty then\n      eliminableParamsById.get(prodFun.concreteId) match\n      case None => eliminableParamsById(prodFun.concreteId) = eliminable.toSet\n      case S(existing) => assert(existing.toList.sorted === eliminable)\n  \n  for (consFun, _) <- funSrcs do\n    val eliminable = consFun.params.indices.filterNot: i =>\n      liveCallSiteParams.contains(consFun -> i)\n    if eliminable.nonEmpty then\n      eliminableCallSiteArgsById.get(consFun.concreteId) match\n      case None => eliminableCallSiteArgsById(consFun.concreteId) = eliminable.toSet\n      case S(existing) => assert(existing.toList.sorted === eliminable)\n  \n  if tl.doTrace then\n    def showRefSite(resultId: ResultId): Str =\n      resultId.getReferredFun match\n        case Some(fun) => s\"${fun.nme}@$resultId\"\n        case None => resultId.getResult match\n          case Value.Ref(sym, _) => s\"${sym.nme}@$resultId\"\n          case res => s\"$res@$resultId\"\n    end showRefSite\n\n    def showInstId(instId: InstantiationId): Str =\n      if instId.isEmpty then \"<root>\" else instId.map(showRefSite).mkString(\".\")\n    end showInstId\n\n    def showProdFun(prodFun: ProdFun): Str =\n      def showFunId(funId: FunId): Str = funId match\n        case (funSym: Symbol, whichParamList) => s\"${funSym.nme}#$whichParamList\"\n        case exprId: ResultId => exprId.getResult match\n          case Lambda(_, _) => s\"lambda@$exprId\"\n          case _ => showRefSite(exprId)\n      val inst = prodFun.instantiationId.fold(\"\")(instId => s\" @ ${showInstId(instId)}\")\n      s\"prodfun ${showFunId(prodFun.funId)}$inst\"\n    end showProdFun\n    \n    assert(eliminableCallSiteArgsById.nonEmpty === eliminableParamsById.nonEmpty)\n    tl.log(\">>> dead-param-elim results >>>\")\n    for (prodFun, _) <- funDests.toSeq.sortBy(pair => showProdFun(pair._1)) do\n      eliminableParamsById.get(prodFun.concreteId) match\n        case Some(elim) =>\n          tl.log(s\"${showProdFun(prodFun)} -> eliminable: {${elim.toSeq.sorted.mkString(\", \")}}\")\n        case _ => ()\n    tl.log(\"<<< dead-param-elim results <<<\")\n  end if\nend DeadParamElimSolver\n\n\nclass Rewrite(val deadParamElimSolver: DeadParamElimSolver)(using Raise):\n  \n  def apply(): Program =\n    if newBody is pre.pgrm.main then pre.pgrm\n    else Program(pre.pgrm.imports, newBody)\n  \n  val constraintSolver = deadParamElimSolver.constraintSolver\n  val collector = deadParamElimSolver.collector\n  given tl: TraceLogger = constraintSolver.tl\n  given fState: FlowAnalysis.State = constraintSolver.fState\n  given eState: Elaborator.State = constraintSolver.eState\n  given pre: FlowPreAnalyzer = constraintSolver.preAnalyzer\n  \n  private val _symSubst = SymbolSubst.Id\n  val newPolyFnSyms = LinkedHashMap.empty[InstantiationId, Map[TermSymbol, (BlockMemberSymbol, TermSymbol)]]\n  \n  // compute necessary poly fun syms\n  locally {\n    def mkNewPolyFnSyms(instId: InstantiationId): Unit =\n      val referredFun = instId.last.getReferredFun.get\n      val groupFuns = collector.funToSccGroups(referredFun)\n      newPolyFnSyms.getOrElseUpdate(\n        instId,\n        groupFuns\n          .map: f =>\n            val name = instId.mkFunName + s\"$$${f.nme}\"\n            f -> (\n              new BlockMemberSymbol(name, Nil, true),\n              new TermSymbol(Fun, N, Tree.Ident(name)))\n          .toMap)\n    end mkNewPolyFnSyms\n    \n    for\n      (_, instId) <-\n        deadParamElimSolver.eliminableParamsById.keysIterator ++\n        deadParamElimSolver.eliminableCallSiteArgsById.keysIterator\n      path <- instId.inits\n      if path.nonEmpty && !collector.synthesizedInstIdToFunSym.contains(path)\n    do mkNewPolyFnSyms(path)\n  }\n  \n  class Rewriter(instId: InstantiationId) extends BlockTransformer(_symSubst):\n    \n    private val activeEliminatedParams = MutSet.empty[VarSymbol]\n\n    private def withEliminatedParams[A](removed: Set[VarSymbol])(thunk: => A): A =\n      if removed.isEmpty then thunk\n      else\n        activeEliminatedParams ++= removed\n        try thunk\n        finally activeEliminatedParams --= removed\n\n    private def filterParamList(pl: ParamList, eliminable: Set[Int]): (ParamList, Set[VarSymbol]) =\n      if eliminable.isEmpty then pl -> Set.empty\n      else\n        val removed = MutSet.empty[VarSymbol]\n        val keptParams = Buffer.empty[Param]\n        pl.params.zipWithIndex.foreach:\n          case (param, i) =>\n            if eliminable(i) then removed.add(param.sym)\n            else keptParams.append(param)\n        ParamList(pl.flags, keptParams.toList, pl.restParam) -> removed.toSet\n    \n    private def filterFunParams(funSym: TermSymbol, params: Ls[ParamList]): (Ls[ParamList], Set[VarSymbol]) =\n      val removed = MutSet.empty[VarSymbol]\n      var changed = false\n      val params2 = params.zipWithIndex.map:\n        case (pl, whichParamList) =>\n          val (pl2, removed2) =\n            filterParamList(pl, deadParamElimSolver.eliminableParamsById((funSym, whichParamList), instId))\n          if pl2 isnt pl then changed = true\n          removed ++= removed2\n          pl2\n      (if changed then params2 else params) -> removed.toSet\n\n    def rewriteFunBody(funSym: TermSymbol, params: Ls[ParamList], body: Block): Block =\n      val (_, removed) = filterFunParams(funSym, params)\n      withEliminatedParams(removed):\n        applyFunBodyLikeBlock(body)\n    \n    override def applyPath(p: Path)(k: Path => Block): Block =\n      def newRefId(refId: ResultId, refSym: TermSymbol): InstantiationId =\n        instId match\n        case Nil => refId :: Nil\n        case pathTo :+ called =>\n          val lastRefedSymbol = called.getReferredFun.get\n          val funToSccRepMap = collector.funToSccRep\n          (funToSccRepMap(lastRefedSymbol), funToSccRepMap(refSym)) match\n            case (Some(a), Some(b)) if a is b => instId\n            case _ => instId :+ refId\n      end newRefId\n    \n      p match\n      case ref@FunRef(f) if newPolyFnSyms.isDefinedAt(newRefId(ref.uid, f)) =>\n        val (bms, tSym) = newPolyFnSyms(newRefId(ref.uid, f))(f)\n        k(Value.Ref(bms, S(tSym)))\n      case _ => super.applyPath(p)(k)\n\n    override def applyValue(v: Value)(k: Value => Block): Block = v match\n      case ref@Value.Ref(l: VarSymbol, _) if activeEliminatedParams(l) =>\n        k(Value.Lit(Tree.UnitLit(false)).withLocOf(ref))\n      case _ => super.applyValue(v)(k)\n\n    override def applyBlock(b: Block): Block = b match\n      case Assign(lhs: VarSymbol, rhs, rst) if activeEliminatedParams(lhs) =>\n        applyResult(rhs): rhs2 =>\n          Assign.discard(rhs2, applySubBlock(rst))\n      case _ => super.applyBlock(b)\n    \n    override def applyResult(r: Result)(k: Result => Block): Block =\n      def rewriteArgs(args: Ls[Arg], eliminable: Set[Int])(k: Ls[Arg] => Block): Block =\n        if eliminable.isEmpty then applyArgs(args)(k)\n        else\n          def rec(rest: Ls[Arg], idx: Int, changed: Bool, accRev: Ls[Arg]): Block = rest match\n            case Nil =>\n              k(if changed then accRev.reverse else args)\n            case arg :: tl if eliminable(idx) =>\n              rec(tl, idx + 1, true, accRev)\n            case arg :: tl =>\n              applyArg(arg): arg2 =>\n                rec(tl, idx + 1, changed || !(arg2 is arg), arg2 :: accRev)\n          rec(args, 0, false, Nil)\n      end rewriteArgs\n      \n      r match\n      case c@Call(fun, args :: restArgss) if args.forall(_.spread.isEmpty) =>\n        val eliminable = deadParamElimSolver.eliminableCallSiteArgsById(c.uid, instId)\n        applyPath(fun): fun2 =>\n          rewriteArgs(args, eliminable): args2 =>\n            k(\n              if (fun2 is fun) && (args2 is args) then c\n              else Call(fun2, args2 ne_:: restArgss)(c.isMlsFun, c.mayRaiseEffects, c.explicitTailCall).withLocOf(c)\n            )\n      case i@Instantiate(mut, cls, args :: restArgss) if args.forall(_.spread.isEmpty) =>\n        val eliminable = deadParamElimSolver.eliminableCallSiteArgsById(i.uid, instId)\n        applyPath(cls): cls2 =>\n          rewriteArgs(args, eliminable): args2 =>\n            k(\n              if (cls2 is cls) && (args2 is args) then i\n              else Instantiate(mut, cls2, args2 :: restArgss).withLocOf(i)\n            )\n      case _ => super.applyResult(r)(k)\n    \n    override def applyLam(lam: Lambda): Lambda =\n      val (params2, removed) = filterParamList(lam.params, deadParamElimSolver.eliminableParamsById(lam.uid, instId))\n      val body2 = withEliminatedParams(removed):\n        applyFunBodyLikeBlock(lam.body)\n      if (params2 is lam.params) && (body2 is lam.body) then lam else Lambda(params2, body2)\n    \n    override def applyFunDefn(fun: FunDefn): FunDefn =\n      val own2 = fun.owner.mapConserve(_.subst)\n      val sym2 = fun.sym.subst\n      val dSym2 = fun.dSym.subst\n      val (params2, removed) = filterFunParams(fun.dSym, fun.params)\n      val body2 = withEliminatedParams(removed):\n        applyFunBodyLikeBlock(fun.body)\n      if (own2 is fun.owner) && (sym2 is fun.sym) && (dSym2 is fun.dSym) &&\n          (params2 is fun.params) && (body2 is fun.body)\n      then fun else FunDefn(own2, sym2, dSym2, params2, body2)(fun.configOverride, fun.annotations)\n  end Rewriter\n  \n  val newBody =\n    \n    def filterParamList(pl: ParamList, eliminable: Set[Int]): ParamList =\n      if eliminable.isEmpty then pl\n      else\n        ParamList(\n          pl.flags,\n          pl.params.zipWithIndex.collect:\n            case (param, i) if !eliminable(i) => param,\n          pl.restParam\n        )\n    end filterParamList\n    \n    def filterFunParams(funSym: TermSymbol, params: Ls[ParamList], instId: InstantiationId): Ls[ParamList] =\n      params.zipWithIndex.map:\n        case (pl, whichParamList) =>\n          filterParamList(pl, deadParamElimSolver.eliminableParamsById((funSym, whichParamList), instId))\n    end filterFunParams\n    \n    class RefreshSymbol(existingMapping: Map[Symbol, Symbol]) extends SymbolRefresher(existingMapping):\n      override def applyValue(v: Value)(k: Value => Block): Block = v match\n        case Value.Ref(l, x) =>\n          pre.res.modSymToBms.get(l) match\n            case Some(bms) =>\n              k(Value.Ref(bms, l.asMod))\n            case None => super.applyValue(v)(k)\n        case _ => super.applyValue(v)(k)\n    end RefreshSymbol\n    \n    def makeRefreshedParams(params: Ls[ParamList]): (Ls[ParamList], Map[Symbol, Symbol]) =\n      val refreshParamMap = MutMap.empty[Symbol, Symbol]\n      val refreshedParams = params.map:\n        case ParamList(flags, params, restParam) =>\n          val params2 = params.map:\n            case p =>\n              val newSym = new VarSymbol(Tree.Ident(p.sym.name))\n              refreshParamMap(p.sym) = newSym\n              Param(p.flags, newSym, p.sign, p.modulefulness)\n          val rest2 = restParam.map:\n            case p =>\n              val newSym = new VarSymbol(Tree.Ident(p.sym.name))\n              refreshParamMap(p.sym) = newSym\n              Param(p.flags, newSym, p.sign, p.modulefulness)\n          ParamList(flags, params2, rest2)\n      refreshedParams -> refreshParamMap.toMap\n    end makeRefreshedParams\n    \n    val newPolyFuns =\n      for\n        (instId, funSymMap) <- newPolyFnSyms\n        (referringFun, (bms, tSym)) <- funSymMap.toList.sortBy(_._1.uid)\n      yield\n        val fDefn = pre.res.funSymToFunDefn(referringFun)\n        val filteredParams = filterFunParams(fDefn.dSym, fDefn.params, instId)\n        val transformedBody = new Rewriter(instId).rewriteFunBody(fDefn.dSym, fDefn.params, fDefn.body)\n        val (refreshedParams, refreshParamMap) = makeRefreshedParams(filteredParams)\n        val bodyWithCorrectSymbols = new RefreshSymbol(refreshParamMap).applyBlock(transformedBody)\n        FunDefn(\n          N, bms, tSym, refreshedParams,\n          bodyWithCorrectSymbols)(fDefn.configOverride, fDefn.annotations)\n    \n    val inplaceRewrittenFunBodies = Map.from[TermSymbol, Block]:\n      for (selfInstId, funSym) <- collector.synthesizedInstIdToFunSym yield\n        val fDefn = pre.res.funSymToFunDefn(funSym)\n        funSym -> new Rewriter(selfInstId).rewriteFunBody(funSym, fDefn.params, fDefn.body)\n    \n    val newMainBody =\n      object mainRewriter extends Rewriter(Nil):\n        override def applyFunDefn(fun: FunDefn): FunDefn =\n          inplaceRewrittenFunBodies.get(fun.dSym) match\n            case Some(rewrittenBody) =>\n              FunDefn(fun.owner, fun.sym, fun.dSym, fun.params, rewrittenBody)(fun.configOverride, fun.annotations)\n            case None => super.applyFunDefn(fun)\n      Scoped(\n        Set.from(newPolyFuns.map(_.sym)),\n        mainRewriter.applyBlock(pre.pgrm.main))\n    \n    newPolyFuns.foldRight(newMainBody): (fdef, rest) =>\n      Define(fdef, rest)\n  \n  end newBody\n  \nend Rewrite\n\n\nobject DeadParamElim:\n  def apply(p: Program)(using\n    cfg: Config,\n    tl: TL,\n    raise: Raise,\n    eState: Elaborator.State,\n  ): Program =\n    cfg.deadParamElim match\n      case None => p\n      case Some(dCfg) =>\n        val outerTl = tl\n        (new TraceLogger:\n          override def doTrace: Bool = dCfg.debug\n          override def emitDbg(str: Str): Unit = outerTl.emitDbg(s\"dead-param-elim > $str\")\n        ).givenIn:\n          val flowAnalysisRes = FlowAnalysis(p, mono = dCfg.mono)\n          val deadParamElimSolver = new DeadParamElimSolver(flowAnalysisRes)\n          if deadParamElimSolver.eliminableParamsById.isEmpty\n            && deadParamElimSolver.eliminableCallSiteArgsById.isEmpty\n          then p\n          else\n            val rewrite = new Rewrite(deadParamElimSolver)\n            rewrite()\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/FirstClassFunctionTransformer.scala",
    "content": "package hkmc2\npackage codegen\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\nimport semantics.*\nimport syntax.Tree\nimport semantics.Elaborator.{ctx, State}\nimport hkmc2.Message.MessageContext\n\nimport collection.mutable.HashMap\n\n\nclass FirstClassFunctionTransformer(using Elaborator.State, Elaborator.Ctx, Raise) extends BlockTransformer(new SymbolSubst):\n  // Anonymous lambdas' parameter lists cannot be retrieved from the term symbol\n  private val funDefns = HashMap.empty[BlockMemberSymbol, FunDefn] \n  class CollectFunDefns extends BlockTraverser:\n    override def applyFunDefn(fun: FunDefn) =\n      funDefns += (fun.sym -> fun)\n      super.applyFunDefn(fun)\n\n  private def generateFCFunctionClass(p: Path, params: ParamList) =\n    val clsSym = ClassSymbol(\n      syntax.Tree.DummyTypeDef(syntax.Cls),\n      syntax.Tree.Ident(\"Function$\")\n    )\n    val defSym = new BlockMemberSymbol(\"Function$\", Nil, false)\n    val callDef = FunDefn.withFreshSymbol(Some(clsSym), new BlockMemberSymbol(\"call\", Nil, true), params :: Nil,\n      Return(Call(p, params.params.map(_.sym.asPath.asArg) ne_:: Nil)(true, false, false), false))(N, annotations = Nil)\n    ClsLikeDefn(None, clsSym, defSym, None, syntax.Cls, None, Nil,\n      Some(Select(Value.Ref(State.globalThisSymbol, Some(State.globalThisSymbol)), Tree.Ident(\"Function\"))(Some(ctx.builtins.Function))),\n      callDef :: Nil, Nil, Nil, Return(Call(Value.Ref(State.builtinOpsMap(\"super\")), Nil ne_:: Nil)(false, false, false), true), End(), None, None)(N, annotations = Nil)\n\n  private def getParamList(l: BlockMemberSymbol): Option[ParamList] = funDefns.get(l) match\n    case Some(fd) => fd.params.headOption\n    case _ => l.tsym.flatMap(getParamList)\n\n  private def getParamList(ts: TermSymbol): Option[ParamList] = ts.defn.flatMap(_.params.headOption)\n\n  override def applyPath(p: Path)(k: Path => Block): Block = p match\n    case ref @ Value.Ref(l: BlockMemberSymbol, disamb) => disamb match\n      case Some(s: TermSymbol) if s.k is syntax.Fun =>\n        val params = getParamList(l).getOrElse(lastWords(s\"Cannot get ${l.nme}'s parameter list.\"))\n        val clsDef = generateFCFunctionClass(ref, params)\n        val tmp = new TempSymbol(None)\n        val cls = Value.Ref(clsDef.sym, Some(clsDef.isym))\n        Scoped(Set(clsDef.sym, tmp), Define(clsDef, Assign(tmp, Instantiate(false, cls, Nil :: Nil), k(Value.Ref(tmp, None)))))\n      case Some(_) => k(p)\n      case None => lastWords(s\"${l.nme}'s disamb cannot be empty.\")\n    case sel: Select => sel.symbol match\n      case Some(s: TermSymbol) if (s.k is syntax.Fun) =>\n        val params = getParamList(s).getOrElse(lastWords(s\"Cannot get ${s.nme}'s parameter list.\"))\n        val clsDef = generateFCFunctionClass(sel, params)\n        val tmp = new TempSymbol(None)\n        val cls = Value.Ref(clsDef.sym, Some(clsDef.isym))\n        Scoped(Set(clsDef.sym, tmp), Define(clsDef, Assign(tmp, Instantiate(false, cls, Nil :: Nil), k(Value.Ref(tmp, None)))))\n      case Some(_) => k(p)\n      case _ =>\n        raise(ErrorReport(msg\"Cannot determine if ${sel.name.name} is a function.\" -> sel.toLoc :: Nil,\n          source = Diagnostic.Source.Compilation))\n        k(p)\n    case _ => k(p)  \n\n  private def pathStartsWith(p: Path, symbol: Local): Bool = p match\n    case Value.Ref(l, _) => l is symbol\n    case Select(p, _) => pathStartsWith(p, symbol)\n    case DynSelect(p, _, _) => pathStartsWith(p, symbol)\n    case _ => false\n\n  override def applyResult(r: Result)(k: Result => Block): Block = r match\n    case c @ Call(fun, argss) => applyListOf(argss, (args, k2) => applyArgs(args)(k2)): argss2 =>\n      def call(f: Path) = Call(f, argss2.ne_!)(c.isMlsFun, c.mayRaiseEffects, c.explicitTailCall)\n      fun match\n        case ref @ Value.Ref(sym, _) => sym match\n          case _: VarSymbol |  _: TempSymbol => k(call(ref.selSN(\"call\")))\n          case _ => k(call(fun))\n        case sel: Select => sel.symbol match\n          case Some(s: TermSymbol) =>\n            if s.k is syntax.Fun then k(call(fun))\n            else k(call(sel.selSN(\"call\")))\n          case _ =>\n            raise(ErrorReport(msg\"Cannot determine if ${sel.name.name} is a function object.\" -> fun.toLoc :: Nil,\n                source = Diagnostic.Source.Compilation))\n            k(call(fun))\n        case s: DynSelect =>\n          raise(ErrorReport(msg\"Cannot determine if the dynamic selection is a function object.\" -> s.toLoc :: Nil,\n              source = Diagnostic.Source.Compilation))\n          k(call(fun))\n        case _ => k(call(fun))\n    case _: Lambda => lastWords(\"Lambda functions should be rewritten into function definitions first.\")\n    case _ => super.applyResult(r)(k)\n  \n  class DesugarMultipleParamList extends BlockTransformer(new SymbolSubst):\n    override def applyFunDefn(fd: FunDefn): FunDefn = fd.params match\n      case Nil => fd\n      case _ :: Nil => fd\n      case head :: tail =>\n        def rec(params: List[ParamList]): Block = params match\n          case head :: rest =>\n            val newBody = rec(rest)\n            val funSym = new BlockMemberSymbol(\"lambda$\", Nil, false)\n            val funDef = FunDefn.withFreshSymbol(None, funSym, head :: Nil, newBody)(N, annotations = Nil)\n            Scoped(Set(funSym), Define(funDef, Return(Value.Ref(funDef.sym, Some(funDef.dSym)), false)))\n          case Nil => fd.body\n        FunDefn.withFreshSymbol(fd.owner, fd.sym, head :: Nil, rec(tail))(fd.configOverride, fd.annotations)\n  \n  def transform(b: Block): Block =\n    val desugared = new DesugarMultipleParamList().applyBlock(b)\n    new CollectFunDefns().applyBlock(desugared)\n    applyBlock(desugared)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/HandlerLowering.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.annotation.tailrec\nimport scala.collection.mutable\nimport scala.util.boundary\nimport sourcecode.{ Line, FileName, Name }\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\nimport hkmc2.utils.SymbolSubst\nimport hkmc2.Message.MessageContext\n\nimport syntax.{Literal, Tree}\nimport semantics.*\nimport semantics.Elaborator.ctx\nimport semantics.Elaborator.State\nimport hkmc2.Config.EffectHandlers\n\n\nobject HandlerLowering:\n\n  private val pcIdent: Tree.Ident = Tree.Ident(\"pc\")\n  private val nextIdent: Tree.Ident = Tree.Ident(\"next\")\n  private val lastIdent: Tree.Ident = Tree.Ident(\"last\")\n  private val contTraceIdent: Tree.Ident = Tree.Ident(\"contTrace\")\n  private def unit = Value.Lit(Tree.UnitLit(true))\n  private def intLit(i: BigInt) = Value.Lit(Tree.IntLit(i))\n\n  private def locToStr(loc: Loc) =\n    val (line, _, col) = loc.origin.fph.getLineColAt(loc.spanStart)\n    Value.Lit(Tree.StrLit(s\"${loc.origin.fileName.last}:${line + loc.origin.startLineNum - 1}:$col\"))\n  \n  extension (p: Path)\n    def pc = p.selN(pcIdent)\n    def value = p.selN(Tree.Ident(\"value\"))\n    def next = p.selN(nextIdent)\n    def last = p.selN(lastIdent)\n    def contTrace = p.selN(contTraceIdent)\n  \n  private case class LinkState(res: Local, cls: Path, uid: Path)\n  \n  type FnOrCls = Either[BlockMemberSymbol, DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol]\n\n  private enum HandlerCtx:\n    case FunctionLike(ctx: FunctionCtx)\n    case Ctor\n    case ModCtor(trulyNested: Bool)\n    case TopLevel\n\n    def inCtor = this === Ctor || this.isInstanceOf[ModCtor]\n    def inTopLevel = this === TopLevel\n    def allowDefn = inTopLevel || this.isInstanceOf[ModCtor]\n    def innerDefIsTrulyNested = this match\n      case FunctionLike(_) => true\n      case Ctor => true\n      case ModCtor(trulyNested) => trulyNested\n      case TopLevel => false\n    \n  \n  // currentFun: path to the current function for resumption\n  // thisPath: path to `this` binding if the function is a method, `this` will be rebinded on resumption\n  private case class FunctionCtx(currentFun: Path, thisPath: Option[Path], resumeInfo: ResumeInfo, debugInfo: DebugInfo, inGetter: Bool):\n    def doUnwind(loc: Value, stateId: BigInt, restoreList: List[Local])(using paths: HandlerPaths) =\n      Return(Call(paths.unwindPath, (\n        currentFun ::\n        intLit(stateId) ::\n        loc ::\n        debugInfo.debugInfoPath ::\n        thisPath.getOrElse(unit) ::\n        resumeInfo.argLists ++:\n        (intLit(restoreList.length) ::\n        restoreList.map(_.asPath))\n      ).map(_.asArg) ne_:: Nil)(true, true, false), false)\n  \n  // argLists: length-encoded argument list used for resumption.\n  // currentLocals: All locals to be saved and reloaded, this cannot include any variables in outer scopes\n  // currentStackSafetySym: The symbol to be used for stack safety\n  private case class ResumeInfo(\n    argLists: List[Path],\n    currentLocals: List[Local],\n    currentStackSafetySym: FnOrCls,\n  )\n  \n  private case class DebugInfo(\n    debugNme: Str,\n    debugInfoPath: Path,\n  )\n  \n  type StateId = BigInt\n\nimport HandlerLowering.*\n\nclass HandlerPaths(using Elaborator.State):\n  val runtimePath: Path = State.runtimeSymbol.asPath\n  val contClsPath: Path = runtimePath.selSN(\"FunctionContFrame\").selSN(\"class\")\n  val mkEffectPath: Path = runtimePath.selSN(\"mkEffect\")\n  val handleBlockImplPath: Path = runtimePath.selSN(\"handleBlockImpl\")\n  val stackDelayClsPath: Path = runtimePath.selSN(\"StackDelay\")\n  val topLevelEffectPath: Path = runtimePath.selSN(\"topLevelEffect\")\n  val illegalEffectPath: Path = runtimePath.selSN(\"illegalEffect\")\n  val enterHandleBlockPath: Path = runtimePath.selSN(\"enterHandleBlock\")\n  val stackDepthIdent = new Tree.Ident(\"stackDepth\")\n  val stackDepthPath: Path = runtimePath.selN(stackDepthIdent)\n  val fnLocalsPath: Path = runtimePath.selSN(\"FnLocalsInfo\").selSN(\"class\")\n  val localVarInfoPath: Path = runtimePath.selSN(\"LocalVarInfo\").selSN(\"class\")\n  val curEffect: Path = runtimePath.selSN(\"curEffect\")\n  val unwindPath: Path = runtimePath.selSN(\"unwind\")\n  val resetEffects: Path = runtimePath.selSN(\"resetEffects\")\n  val resumePc: Path = runtimePath.selSN(\"resumePc\")\n  val resumeIdx: Path = runtimePath.selSN(\"resumeIdx\")\n  val resumeValueIdent = new Tree.Ident(\"resumeValue\")\n  val resumeValue: Path = runtimePath.selN(resumeValueIdent)\n\ntype StackSafetyMap = collection.Map[FnOrCls, (Int, Block)]\n\nclass HandlerLowering(paths: HandlerPaths, opt: EffectHandlers)(using TL, Raise, Elaborator.State, Elaborator.Ctx):\n  \n  private def freshTmp(dbgNme: Str = \"tmp\") = new TempSymbol(N, dbgNme)\n  private def freshLabel(nme: Str) = new LabelSymbol(N, nme)\n  \n  private def rtThrowMsg(msg: Str) = Throw(\n    Instantiate(mut = false, State.globalThisSymbol.asPath.selN(Tree.Ident(\"Error\")),\n    (Value.Lit(Tree.StrLit(msg)).asArg :: Nil) :: Nil)\n  )\n  \n  object PureCall:\n    def apply(fun: Path, args: List[Path]) = Call(fun, args.map(Arg(N, _)) ne_:: Nil)(true, false, false)\n    def unapply(res: Result) = res match\n      case Call(fun, args :: Nil) => args.foldRight[Opt[List[Path]]](S(Nil)): (arg, acc) =>\n          acc.flatMap: acc =>\n            arg match\n              case Arg(N, p) => S(p :: acc)\n              case _ => N\n        .map((fun, _))\n      case _ => N\n  \n  object StateTransition:\n    private val transitionSymbol = freshTmp(\"transition\")\n    def apply(uid: StateId) =\n      Return(PureCall(Value.Ref(transitionSymbol), List(Value.Lit(Tree.IntLit(uid)))), false)\n    def unapply(blk: Block) = blk match\n      case Return(PureCall(Value.Ref(`transitionSymbol`, _), List(Value.Lit(Tree.IntLit(uid)))), false) =>\n        S(uid)\n      case _ => N\n\n  object Unwind:\n    private val unwindSymbol = freshTmp(\"unwind\")\n    def apply(uid: StateId, loc: Value) =\n      Return(PureCall(Value.Ref(unwindSymbol), List(Value.Lit(Tree.IntLit(uid)), loc)), false)\n    def unapply(blk: Block) = blk match\n      case Return(PureCall(Value.Ref(`unwindSymbol`, _), List(Value.Lit(Tree.IntLit(uid)), loc: Value)), false) =>\n        S(uid, loc)\n      case _ => N\n\n  abstract class LazyId extends Lazy[StateId]:\n    def isUsed: Bool = !isEmpty\n    def transitionOrBlk(blk: => Block) =\n      if isEmpty then blk else StateTransition(force_!)\n  \n  private class IdAllocator:\n    var id: Int = 0\n    def apply() =\n      val tmp = id\n      id += 1\n      tmp\n  \n  // blk: the block of code within this state\n  private case class BlockPartition(blk: Block, resumable: Bool)\n  private case class PartitionedBlock(\n    entry: StateId,\n    states: Map[StateId, BlockPartition],\n    allocId: IdAllocator,\n    containsCall: Bool,\n    containsError: Bool\n  )\n\n  object EffectfulResult:\n    def unapply(r: Result) = r match\n      case c: Call if c.mayRaiseEffects => S(r)\n      case _: Instantiate if opt.checkInstantiateEffect => S(r)\n      case _ => N\n  \n  private def partitionBlock(blk: Block): PartitionedBlock =\n    val result = mutable.HashMap.empty[StateId, BlockPartition]\n    val labelIds = mutable.HashMap.empty[LabelSymbol, (LazyId, LazyId)]\n    val allocId = new IdAllocator()\n    var containsCall = false\n    var containsError = false\n\n    // * blk: The block to transform\n    // * partitioned: whether we are already in a partitioned state\n    // *              if we are not partitioned, we do not need to jump to afterEnd,\n    // *              this is because we are still in the original block, which shares\n    // *              the same code path.\n    // * labelIds: maps label IDs to the state at the start of the label and the state after the label\n    // * afterEnd: The block that follows End, None if the function ends.\n    def go(blk: Block)(using afterEnd: Option[LazyId], partitioned: Bool): Block = boundary:\n      // First check if the current block contain any non trivial call, if so we need a partition\n\n      def forceId(blk: Block, resumable: Bool): StateId = blk match\n        case StateTransition(uid) =>\n          if !result(uid).resumable && resumable then\n            result(uid) = BlockPartition(result(uid).blk, true)\n          uid\n        case _ =>\n          val id = allocId()\n          result(id) = BlockPartition(blk, resumable)\n          id\n\n      def doNewEffectPartition(res: Result, rst: Block) =\n        val stateId = forceId(go(rst)(using partitioned = true), true)\n        val newBlock = blockBuilder\n          .assignFieldN(paths.runtimePath, paths.resumeValueIdent, res)\n          .ifthen(\n            paths.curEffect,\n            Case.Lit(Tree.UnitLit(true)),\n            End(),\n            S(Unwind(stateId, res.toLoc.fold(unit)(locToStr(_))))\n          )\n          .rest(StateTransition(stateId))\n        boundary.break(newBlock)\n      class RestLazyId(rst: Block) extends LazyId:\n        def compute: StateId = forceId(go(rst)(using partitioned = true), false)\n        def transitionSoft: Block = transitionOrBlk(go(rst))\n\n      val nonTrivialBlockChecker = new BlockDataTransformer(SymbolSubst.Id):\n        override def applyBlock(b: Block) = b match\n          // Special handling for tail calls\n          case Return(c @ Call(fun, args), false) =>\n            containsCall = true\n            b // Prevents the recursion into applyResult\n          case _ => super.applyBlock(b)\n        override def applyResult(r: Result)(k: Result => Block) = r match\n          case EffectfulResult(r) =>\n            containsCall = true\n            doNewEffectPartition(r, k(paths.resumeValue))\n          case _ => super.applyResult(r)(k)\n      \n      // If current block contains direct effectful result the following call will early exit.\n      nonTrivialBlockChecker.applyBlock(blk)\n\n      blk match\n\n      case Match(scrut, arms, dflt, rest) =>\n        val restId = RestLazyId(rest)\n        val newArms = arms.map((cse, blkk) => (cse, go(blkk)(using afterEnd = S(restId))))\n        val newDflt = dflt.map(blkk => go(blkk)(using afterEnd = S(restId)))\n        Match(scrut, newArms, newDflt, restId.transitionSoft)\n\n      case Label(label, loop, body, rest) =>\n        val restId = RestLazyId(rest)\n        val startId = new LazyId:\n          def compute = allocId()\n        labelIds(label) = (startId, restId)\n        val newBody = go(body)(using S(restId))\n        if startId.isUsed then\n          // We break down the label, and force the usage of rest so that all Break will be rewritten later\n          result(startId.force_!) = BlockPartition(Begin(newBody, StateTransition(restId.force_!)), false)\n          StateTransition(startId.force_!)\n        else\n          Label(label, loop, newBody, restId.transitionSoft)\n\n      case Break(label) =>\n        val (start, end) = labelIds.get(label) match\n          case N => raise(InternalError(\n            msg\"Could not find label '${label.nme}'\" ->\n            label.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation))\n            return blk\n          case S(value) => value\n        if partitioned then\n          StateTransition(end.force_!)\n        else\n          // We might still need to do a StateTransition if the label is broken down.\n          // This is done afterwards in a replacement pass.\n          Break(label)\n\n      case Continue(label) =>\n        val (start, end) = labelIds.get(label) match\n          case N => raise(InternalError(\n            msg\"Could not find label '${label.nme}'\" ->\n            label.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation))\n            return blk\n          case S(value) => value\n        if partitioned then\n          StateTransition(start.force_!)\n        else\n          // Same as above.\n          Continue(label)\n\n      case Begin(sub, rest) =>\n        val restId = RestLazyId(rest)\n        val newSub = go(sub)(using afterEnd = S(restId))\n        Begin(newSub, restId.transitionSoft)\n\n      case u: Unreachable => u\n      \n      case End(_) =>\n        if partitioned then\n          afterEnd.fold(blk)(id => StateTransition(id.force_!))\n        else\n          blk\n\n      // Currently, implicit returns are only used in top level and tail call of constructor\n      // The former case never enters the partitioning function, so it must be the later case here.\n      // We no longer handle the later case, hence we can ignore this case.\n      // case Return(_, true) => afterEnd match\n      //   case None => End()\n      //   case Some(id) => StateTransition(id)\n\n      // identity cases\n\n      case Define(defn, rest) => Define(defn, go(rest))\n      case Assign(lhs, rhs, rest) => Assign(lhs, rhs, go(rest))\n      case blk @ AssignField(lhs, nme, rhs, rest) => AssignField(lhs, nme, rhs, go(rest))(blk.symbol)\n      case AssignDynField(lhs, fld, arrayIdx, rhs, rest) => AssignDynField(lhs, fld, arrayIdx, rhs, go(rest))\n      case _: Return => blk\n\n      // ignored cases\n      case TryBlock(sub, finallyDo, rest) =>\n        containsError = true\n        Lowering.fail(ErrorReport(\n          msg\"`try`-`finally` blocks are not currently supported with effect handlers enabled.\" ->\n          N :: Nil,\n          source = Diagnostic.Source.Compilation))\n      case Throw(_) => blk\n      case Scoped(_, body) => go(body) // PreHandlerLowering\n\n    val initId = allocId()\n    // Note: initial part will only be resumed if stack safety is on.\n    val initPart = BlockPartition(go(blk)(using N, false), opt.stackSafety.isDefined)\n    result(initId) = initPart\n\n    val replaceStaleLabels = new BlockTransformerShallow(SymbolSubst.Id):\n      override def applyBlock(b: Block): Block = b match\n        case Break(label) if labelIds(label)._2.isUsed => StateTransition(labelIds(label)._2.force_!)\n        case Continue(label) if labelIds(label)._1.isUsed => StateTransition(labelIds(label)._2.force_!)\n        case _ => super.applyBlock(b)\n    val newMap = Map.from(result.map: (id, part) =>\n      id -> BlockPartition(replaceStaleLabels.applyBlock(part.blk), part.resumable))\n    PartitionedBlock(initId, newMap, allocId, containsCall, containsError)\n\n  private def computeRestoreList(parts: PartitionedBlock)(using ctx: FunctionCtx): List[Local] =\n    // We compute the restore list by taking the union of live variables at each resumption point\n    // The live variable analysis uses a classic work list approach\n    val locals = ctx.resumeInfo.currentLocals\n\n    val localSetMap = locals.zipWithIndex.toMap\n    val allocId = parts.allocId\n\n    type PartitionVarInfo = (used: mutable.BitSet, assigned: mutable.BitSet, outgoing: List[StateId])\n    val states = mutable.HashMap.from(parts.states)\n    val labelMap = mutable.HashMap.empty[LabelSymbol, (StateId, StateId)]\n\n    def createState(blk: Block): StateId =\n      val newId = allocId()\n      states(newId) = BlockPartition(blk, false)\n      newId\n\n    def computeVarInfo(blk: Block): PartitionVarInfo =\n      // Variables that are assigned in the block\n      val assigned = mutable.BitSet.empty\n      // Variables that are used before any assignment in the block, which means they must be live\n      val used = mutable.BitSet.empty\n      val outgoing = mutable.HashSet.empty[StateId]\n\n      def assignToSym(l: Local) =\n        localSetMap.get(l).foreach: idx =>\n          assigned += idx\n\n      new BlockTraverserShallow():\n        applyBlock(blk)\n        override def applyBlock(b: Block): Unit = b match\n          case Unwind(uid, loc) => ()\n          case StateTransition(uid) =>\n            outgoing += uid\n          case Match(scrut, arms, dflt, rest) =>\n            applyPath(scrut)\n            val restId = createState(rest)\n            arms.foreach: arm =>\n              val newId = createState(Begin(arm._2, StateTransition(restId)))\n              outgoing += newId\n            dflt match\n              case N => outgoing += restId\n              case S(blk) =>\n                outgoing += createState(Begin(blk, StateTransition(restId)))\n          case Label(label, loop, body, rest) =>\n            val restId = createState(rest)\n            val bodyId = createState(Begin(body, StateTransition(restId)))\n            labelMap(label) = (bodyId, restId)\n            outgoing += bodyId\n          case Break(label) =>\n            outgoing += labelMap(label)._2\n          case Continue(label) =>\n            outgoing += labelMap(label)._1\n          case Assign(lhs, rhs, rest) =>\n            applyResult(rhs)\n            assignToSym(lhs)\n            applyBlock(rest)\n          case Define(defn: ValDefn, rest) =>\n            applyPath(defn.rhs)\n            assignToSym(defn.sym)\n            applyBlock(rest)\n          case Define(defn, rest) =>\n            assignToSym(defn.sym)\n            applyBlock(rest)\n          case _ => super.applyBlock(b)\n        override def applySymbol(sym: Symbol): Unit =\n          localSetMap.get(sym).foreach: idx =>\n            if !assigned.contains(idx) then\n              used += idx\n\n      (used, assigned, outgoing.toList)\n\n    val worklist = mutable.Queue.empty[StateId]\n    val worklistSet = mutable.Set.empty[StateId]\n    val stateInfo = mutable.HashMap.empty[StateId, (live: mutable.BitSet, varInfo: PartitionVarInfo, incoming: mutable.ArrayBuffer[StateId])]\n\n    def traverse(id: StateId): Unit =\n      if stateInfo.contains(id) then return ()\n      val info = computeVarInfo(states(id).blk)\n      stateInfo(id) = (mutable.BitSet.empty, info, mutable.ArrayBuffer.empty)\n      info.outgoing.foreach: entry =>\n        traverse(entry)\n        stateInfo(entry).incoming += id\n      worklist.enqueue(id)\n      worklistSet += id\n\n    traverse(parts.entry)\n\n    while worklist.nonEmpty do\n      val cur = worklist.dequeue()\n      worklistSet -= cur\n      val info = stateInfo(cur)\n      val newLive = info.varInfo.outgoing\n        .map: entry =>\n          stateInfo(entry).live\n        .fold(mutable.BitSet.empty)(_ | _).diff(info.varInfo.assigned) | info.varInfo.used\n      if newLive != info.live then\n        stateInfo(cur).live |= newLive\n        stateInfo(cur).incoming.foreach: id =>\n          if !worklistSet.contains(id) then\n            worklist.enqueue(id)\n            worklistSet += id\n\n    parts.states\n      .flatMap: (id, part) =>\n        if !part.resumable then N\n        else\n          S(stateInfo.get(id).fold(mutable.BitSet.empty)(_.live))\n      .fold(mutable.BitSet.empty)(_ | _)\n      .toList\n      .map(locals(_))\n\n  private def computeEdges(parts: PartitionedBlock): Map[StateId, List[StateId]] =\n    val edges = mutable.ListBuffer.empty[(StateId, StateId)]\n    def findEdges(uid: StateId, b: Block) =\n      new BlockTraverser:\n        override def applyBlock(b: Block): Unit = b match\n          case StateTransition(uid2) => edges.addOne((uid, uid2))\n          case _ => super.applyBlock(b)\n        applyBlock(b)\n    for (uid, blk) <- parts.states do\n      findEdges(uid, blk.blk)\n    edges.groupBy(_._1).map:\n      case uid -> ids => uid -> ids.map:\n          case (a, b) => b\n        .toList\n        .distinct\n  \n  // Denotes whether a block transitions to another state only on the outer level,\n  // i.e. should return false iff there is a state transition within an if, label, etc.\n  // A precondition is that the state corresponding to the input block has an out-degree\n  // of 1. This means if a state transition cannot be found on the outer level, there\n  // must be a state transition within another construct and should return false.\n  @tailrec\n  private def isSimpleTransition(b: Block): Bool = b match\n    case StateTransition(uid) => true\n    case b: NonBlockTail => isSimpleTransition(b.rest)\n    case _: BlockTail => false\n\n  // Given a directed graph, computes the \"straight line\" segments of the graph, i.e. partitions it\n  // into segments such that the out-degree of all elements in each segment is 1, except\n  // for the last element. Note that the partitioning is not necessarily unique and this does\n  // not necessarily produce a \"maximal\" partitioning. (I actually suspect that producing a\n  // maximal partitioning is NP-hard...)\n  //\n  // I do have some ideas to improve this though, but those can be done later.\n  private def computeStraightLines(entry: StateId, edges: Map[StateId, List[StateId]]): List[List[StateId]] =\n    val visited = mutable.HashSet.empty[StateId]\n    val ret = mutable.ListBuffer.empty[List[StateId]]\n    // Algorithm: Perform a DFS and accumulate the current straight-line segment as we visit nodes.\n    // Once we reach a node that has an out degree of != 1, we end the current straight line segment.\n    def dfs(state: StateId, acc: List[StateId]): Unit =\n      var curAcc = acc\n      def concludeSegment =\n        ret.addOne(curAcc)\n        curAcc = List.empty\n      if !visited.contains(state) then\n        // Not yet visited: Add this node to the current segment.\n        curAcc = state :: curAcc\n        visited.add(state)\n        edges.get(state) match\n        case Some(nexts) =>\n          // If this state has an out degree of != 1, then end the current segment.\n          if nexts.size != 1 then\n            concludeSegment\n          for n <- nexts do dfs(n, curAcc)\n        case None => concludeSegment\n      // If this state was visited from a node u with an out-degree of 1, but this state\n      // has already been previously visited, then we must conclude the current segment,\n      // ending at the node u.\n      else if !curAcc.isEmpty then\n        concludeSegment\n    dfs(entry, List.empty)\n    ret.sortBy(x => x.headOption.getOrElse(BigInt(-1))).toList\n\n  val stackSafetyMap: mutable.Map[FnOrCls, (Int, Block)] = mutable.HashMap.empty\n  \n  private def lifterReport(using Line, FileName)(msgs: Ls[Message -> Opt[Loc]])(using Name) =\n    if opt.softLifterError then\n      WarningReport(msgs, source = Diagnostic.Source.Compilation)\n    else\n      InternalError(msgs, source = Diagnostic.Source.Compilation)\n\n  /**\n   * The actual translation:\n   * 1. rewrite handler blocks in terms of classes and functions (directly during Lowering)\n   * 2. class lifter\n   * 3. state machine transformation of all functions (HandlerLowering, this class)\n   */\n\n  private def translateBlock(blk: Block, h: HandlerCtx, scopedVars: collection.Set[Local]): Block =\n    given HandlerCtx = h\n\n    def translateFunLike(fun: FunDefn, funcPath: Path, thisPath: Option[Path], debugNme: Str) =\n      val scopedVars = fun.body match\n        case Scoped(syms, body) => syms\n        case _ => Set()\n      val varList = scopedVars.toList.sortBy(_.uid)\n      val debugInfo = Value.Lit(Tree.StrLit(debugNme)).asArg :: varList.zipWithIndex.filter(_._1.isInstanceOf[VarSymbol])\n        .flatMap: (sym, idx) =>\n          List(intLit(idx), Value.Lit(Tree.StrLit(sym.nme)))\n        .map(_.asArg)\n      val debugInfoSym = freshTmp(s\"$debugNme$$debugInfo\")\n      // TODO: properly support spread argument by calculating the correct length.\n      val rtArgLists = intLit(fun.params.length) :: fun.params.flatMap: pl =>\n        intLit(pl.params.length) :: pl.params.map(_.sym.asPath)\n      val newCtx = HandlerCtx.FunctionLike(FunctionCtx(funcPath, thisPath, ResumeInfo(rtArgLists, varList, L(fun.sym)),\n        DebugInfo(debugNme, if opt.debug then debugInfoSym.asPath else unit), thisPath.isDefined && fun.params.isEmpty))\n      val bod2 = translateBlock(fun.body, newCtx, scopedVars)\n      val fun2 = if fun.body is bod2 then fun else\n        FunDefn(fun.owner, fun.sym, fun.dSym, fun.params, bod2)(fun.configOverride, fun.annotations)\n      (debugInfoSym, debugInfo, fun2)\n\n    // transform inner function/class and effect handler intrinsics to the runtime functions.\n    val preTransform = new BlockTransformer(SymbolSubst.Id):\n      override def applyResult(r: Result)(k: Result => Block): Block = r match\n        case Call(Value.Ref(sym, _), args) if sym is Elaborator.ctx.builtins.runtime.suspend =>\n          k(Call(paths.mkEffectPath, args)(true, true, false))\n        case Call(Value.Ref(sym, _), args) if sym is Elaborator.ctx.builtins.runtime.handle_suspension =>\n          k(Call(paths.enterHandleBlockPath, args)(true, true, false))\n        case _ => super.applyResult(r)(k)\n      override def applyDefn(defn: Defn)(k: Defn => Block): Block = defn match\n        case fun: FunDefn =>\n          if !h.allowDefn then\n            raise(lifterReport(msg\"Unexpected nested function: lambdas may not function correctly.\" -> fun.sym.toLoc :: Nil))\n          val (debugInfoSym, debugInfo, fun2) = translateFunLike(fun, Value.Ref(fun.sym, S(fun.dSym)), N, fun.sym.nme)\n          if opt.debug then Scoped(Set.single(debugInfoSym), Assign(debugInfoSym, Tuple(false, debugInfo), k(fun2))) else k(fun2)\n        case defn @ ClsLikeDefn(owner, isym, sym, ctorSym, kind, paramsOpt, auxParams, parentPath, methods, privateFields, publicFields, preCtor, ctor, companion, bufferable) =>\n          if !h.allowDefn then\n            raise(lifterReport(msg\"Unexpected nested class: lambdas may not function correctly.\" -> isym.toLoc :: Nil))\n          val debugInfos = mutable.ArrayBuffer.empty[(Local, List[Arg])]\n          val newMtds = methods.map: f =>\n            val (debugInfoSym, debugInfo, fun2) = translateFunLike(f, Value.Ref(isym).sel(new Tree.Ident(f.sym.nme), f.dSym),\n              S(Value.Ref(isym)), s\"${sym.nme}#${f.sym.nme}\")\n            debugInfos += debugInfoSym -> debugInfo\n            fun2\n          val companion2 = companion.map: bod =>\n            val newMtds = bod.methods.map: f =>\n              val (debugInfoSym, debugInfo, fun2) = translateFunLike(f, Value.Ref(bod.isym).sel(new Tree.Ident(f.sym.nme), f.dSym),\n                S(Value.Ref(bod.isym)), s\"${sym.nme}.${f.sym.nme}\")\n              debugInfos += debugInfoSym -> debugInfo\n              fun2\n            // We cannot use this bc there is no subblock transform...\n            // val newCtor = translateTrivialOrTopLevel(bod.ctor)\n            // TODO: Companion's ctor is more well behaved so it is possible to handle it\n            // However, JSBuilder inserts extra statements between preCtor and ctor and it's not possible to replicate the exact behavior\n            // without many special handling.\n            val newCtor = if opt.doNotInstrumentTopLevelModCtor && !h.innerDefIsTrulyNested then bod.ctor else\n              translateCtorLike(bod.ctor, bod.isym.asPath, true)\n            tl.log(s\"companion name: ${bod.isym.nme}\")\n            ClsLikeBody(bod.isym, newMtds, bod.privateFields, bod.publicFields, newCtor, bod.annotations)\n          val c2 = ClsLikeDefn(owner, isym, sym, ctorSym, kind, paramsOpt, auxParams, parentPath, newMtds, privateFields, publicFields,\n            translateCtorLike(preCtor, isym.asPath, false), translateCtorLike(ctor, isym.asPath, false), companion2, bufferable)(defn.configOverride, defn.annotations)\n          if opt.debug then\n            Scoped(debugInfos.map(_._1).toSet, debugInfos.foldRight(k(c2)): (elem, blk) =>\n              Assign(elem._1, Tuple(false, elem._2), blk))\n          else k(c2)\n        case _ => super.applyDefn(defn)(k)\n    val b = preTransform.applyBlock(blk)\n    if h.inCtor then\n      return translateIllegalEffectCtx(b, Call(paths.illegalEffectPath, (Value.Lit(Tree.StrLit(\"in a constructor\")).asArg :: Nil) ne_:: Nil)(true, true, false))\n    if h.inTopLevel then\n      return translateIllegalEffectCtx(b, Call(paths.topLevelEffectPath, (Value.Lit(Tree.BoolLit(opt.debug)).asArg :: Nil) ne_:: Nil)(true, false, false))\n    val ctx = h.asInstanceOf[HandlerCtx.FunctionLike].ctx\n    if ctx.inGetter then\n      return translateIllegalEffectCtx(b, Call(paths.illegalEffectPath, (Value.Lit(Tree.StrLit(\"in a getter\")).asArg :: Nil) ne_:: Nil)(true, false, false))\n    given FunctionCtx = ctx\n    val parts = partitionBlock(b)\n    stackSafetyMap += ctx.resumeInfo.currentStackSafetySym ->\n      (\n        1,\n        ctx.doUnwind(ctx.resumeInfo.currentStackSafetySym.fold(_.toLoc, _.toLoc).fold(unit)(locToStr(_)), -1, Nil)(using paths)\n      )\n    if parts.states.size <= 1 && !parts.containsError then\n      return b\n    val vars = if opt.debug then ctx.resumeInfo.currentLocals else computeRestoreList(parts)\n\n    val pcVar = freshTmp(\"pc\")\n    val mainLoopLbl = freshLabel(\"main\")\n\n    val edges = computeEdges(parts)\n    val straightLines = computeStraightLines(parts.entry, edges)\n\n    val segmentTailTransform = new BlockTransformerShallow(SymbolSubst.Id):\n      override def applyBlock(b: Block) = b match\n        case StateTransition(uid) =>\n          Assign(pcVar, Value.Lit(Tree.IntLit(uid)), Continue(mainLoopLbl))\n        case Unwind(uid, loc) =>\n          ctx.doUnwind(loc, uid, vars)(using paths)\n        case _ => super.applyBlock(b)\n\n    // Note: `line` has the last state as the head, and the first state at the end\n    def straightLineToArms(line: List[StateId]): Block => Block =\n      def transformState(state: StateId) =\n        val blk = parts.states(state)\n        // If the state transition does not appear in tail position on the outer level,\n        // we must wrap the transformed state in a label, and jump to that label when\n        // encountering a state transition\n        val isSimple = isSimpleTransition(blk.blk)\n        lazy val lblSym = LabelSymbol(N, \"brk\" + state.toString())\n        val nextState = edges(state).head\n        val transform = new BlockTransformerShallow(SymbolSubst.Id):\n          override def applyBlock(b: Block) = b match\n            case StateTransition(uid) =>\n              assert(uid === nextState)\n              if isSimple then\n                Assign(pcVar, Value.Lit(Tree.IntLit(uid)), End())\n              else\n                Break(lblSym)\n            case Unwind(uid, loc) =>\n              ctx.doUnwind(loc, uid, vars)(using paths)\n            case _ => super.applyBlock(b)\n        val transformed = transform.applyBlock(blk.blk)\n        if isSimple then transformed\n        else Label(\n          lblSym, false, transformed,\n          Assign(pcVar, Value.Lit(Tree.IntLit(nextState)), End())\n        )\n      line match\n        case head :: next =>\n          val headTransformed = segmentTailTransform.applyBlock(parts.states(head).blk)\n          val initial: Block => Block = blk =>\n            Match(\n              Value.Ref(pcVar),\n              Case.Lit(Tree.IntLit(head)) -> headTransformed :: Nil,\n              N,\n              blk\n            )\n          next.foldLeft(initial):\n            // Applying this function to a block b will result in b appearing in the tail\n            // of the sequence of match blocks\n            case (acc, uid) => \n              val transformed = transformState(uid)\n              blk =>\n              Match(\n                Value.Ref(pcVar),\n                Case.Lit(Tree.IntLit(uid)) -> transformed :: Nil,\n                N,\n                acc(blk)\n              )\n        case Nil => id\n      \n      \n\n    val mainLoop =\n      if parts.states.size <= 1 then\n        segmentTailTransform.applyBlock(parts.states.head._2.blk)\n      else\n        val matches = straightLines.map(straightLineToArms).foldLeft[Block](End()):\n          case (acc, f) => f(acc)\n        Label(mainLoopLbl, true, matches, End())\n        \n    val getSavedTmp = freshTmp(\"saveOffset\")\n    def getSaved(off: BigInt): (Block => Block, Path) =\n      if off == 0 then\n        return (id, DynSelect(paths.runtimePath.selSN(\"resumeArr\"), paths.runtimePath.selSN(\"resumeIdx\"), true))\n      val addOne = Assign(getSavedTmp, Call(State.builtinOpsMap(\"+\").asPath, (paths.runtimePath.selSN(\"resumeIdx\").asArg :: intLit(off).asArg :: Nil) ne_:: Nil)(false, false, false), _)\n      (addOne, DynSelect(paths.runtimePath.selSN(\"resumeArr\"), getSavedTmp.asPath, true))\n\n    val resumeArrIndexed = DynSelect(paths.runtimePath.selSN(\"resumeArr\"), getSavedTmp.asPath, true)\n    val plus = State.builtinOpsMap(\"+\").asPath\n    val preRestore = blockBuilder\n        .assign(pcVar, paths.resumePc)\n        .scopedVars(Set(getSavedTmp))\n    val restoreVars = vars.zipWithIndex.foldLeft(preRestore):\n      case (builder, (local, idx)) => builder\n        .assign(getSavedTmp, if idx == 0 then paths.resumeIdx else Call(plus, (getSavedTmp.asPath.asArg :: intLit(1).asArg :: Nil) ne_:: Nil)(false, false, false))\n        .assign(local, resumeArrIndexed)\n\n    Scoped(\n      scopedVars ++ Set(pcVar),\n      Match(\n        paths.resumePc,\n        Case.Lit(Tree.IntLit(-1)) ->\n          Assign(pcVar, intLit(parts.entry), End()) :: Nil,\n        S(restoreVars\n            .assignFieldN(paths.runtimePath, new Tree.Ident(\"resumePc\"), Value.Lit(Tree.IntLit(-1))).end),\n        mainLoop))\n  \n  private def translateCtorLike(b: Block, thisPath: Path, isModCtor: Bool)(using h: HandlerCtx): Block =\n    translateBlock(b, if isModCtor then HandlerCtx.ModCtor(h.innerDefIsTrulyNested) else HandlerCtx.Ctor, Set.empty)\n\n  private def translateIllegalEffectCtx(b: Block, onEffect: Call)(using HandlerCtx): Block =\n    def effectCheck(l: Local, r: Result, rst: Block): Block =\n      blockBuilder\n        .assign(l, r)\n        .ifthen(\n          paths.curEffect,\n          Case.Lit(Tree.UnitLit(true)),\n          End(),\n          S(Assign(l, onEffect, End())))\n        .rest(rst)\n    val topLevelTransform = new BlockTransformerShallow(SymbolSubst.Id):\n      override def applyBlock(b: Block) = b match\n        case Assign(lhs, EffectfulResult(r), rest) =>\n          // Optimization to reuse lhs instead of fresh local\n          effectCheck(lhs, r, applyBlock(rest))\n        case _ => super.applyBlock(b)\n      override def applyResult(r: Result)(k: Result => Block) = r match\n        case EffectfulResult(r) =>\n          // Fallback case, this may lead to unnecessary assignments if it is assign-like\n          val l = freshTmp()\n          Scoped(Set(l), effectCheck(l, r, k(Value.Ref(l))))\n        case _ => super.applyResult(r)(k)\n    topLevelTransform.applyBlock(b)\n\n\n  def translateTopLevel(b: Block): (Block, StackSafetyMap) =\n    val preTransformed = new ScopeFlattener().applyBlock(b)\n    val ctx = HandlerCtx.TopLevel\n    val transformed = translateBlock(preTransformed, ctx, Set.empty)\n    val blk = blockBuilder\n      .assign(State.noSymbol, Call(paths.resetEffects, Nil ne_:: Nil)(true, false, false))\n      .rest(transformed)\n    (blk, stackSafetyMap)\n    \n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/LambdaRewriter.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.codegen.*\nimport hkmc2.semantics.*\nimport semantics.Elaborator.State\nimport hkmc2.syntax.Tree\n\nobject LambdaRewriter:\n  \n  def desugar(b: Block)(using State) =\n    val transformer = new BlockTransformer(SymbolSubst.Id):\n      override def applyResult(r: Result)(k: Result => Block): Block = r match\n        case lam: Lambda =>\n          val sym = BlockMemberSymbol(\"lambda\", Nil, nameIsMeaningful = false)\n          val Lambda(params, body) = super.applyLam(lam)\n          val lamDefn = FunDefn.withFreshSymbol(N, sym, params :: Nil, body)(N, annotations = Nil)\n          Scoped(Set.single(sym), Define(lamDefn, k(lamDefn.asPath)))\n        case _ => super.applyResult(r)(k)\n      \n      override def applyBlock(b: Block): Block = b match\n        case Assign(lhs, Lambda(params, body), rest) if !lhs.isInstanceOf[TempSymbol] =>\n          val newSym = BlockMemberSymbol(lhs.nme, Nil,\n            nameIsMeaningful = true // TODO: lhs.nme is not always meaningful\n          )\n          val defn = FunDefn.withFreshSymbol(N, newSym, params :: Nil, applyBlock(body))(N, annotations = Nil)\n          val blk = blockBuilder\n            .define(defn)\n            .assign(lhs, defn.asPath)\n            .rest(applyBlock(rest))\n          Scoped(Set.single(newSym), blk)\n        case _ => super.applyBlock(b)\n    \n    transformer.applyBlock(b)\n  \n  \n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport syntax.{Keyword, SpreadKind}\nimport hkmc2.codegen.*\nimport hkmc2.semantics.*\nimport hkmc2.Message.*\nimport hkmc2.ScopeData.*\nimport hkmc2.semantics.Elaborator.State\nimport hkmc2.syntax.Tree\nimport hkmc2.codegen.llir.FreshInt\n\nimport scala.collection.mutable.LinkedHashMap\nimport scala.collection.mutable.Map as MutMap\nimport scala.collection.mutable.Set as MutSet\nimport scala.collection.mutable.ListBuffer\n\nobject Lifter:\n  \n  /**\n    * Describes the free variables of a function that have been accessed by its nested definitions.\n    * @param vars The free variables that are accessed by nested classes/functions.\n    * @param reqCapture The free variables that must be captured using a heap-allocated object.\n    */\n  case class FreeVars(vars: Set[Local], reqCapture: Set[Local]):\n    def ++(that: FreeVars) = FreeVars(vars ++ that.vars, reqCapture ++ that.reqCapture)\n  object FreeVars:\n    val empty = FreeVars(Set.empty, Set.empty)\n  \n  extension (l: List[Lazy[Defn] | Defn])\n    def gatherUsed: List[Defn] = l.collect:\n      case l: Lazy[?] if !l.isEmpty => l.force_!\n      case d: Defn => d\n\n  /**\n    * Describes previously defined locals and definitions which could possibly be accessed or mutated by particular definition.\n    * Here, a \"previously defined\" local or definition means it is accessible to the particular definition (which we call `d`), \n    * but is not defined *by* `d`.\n    *\n    * @param accessed Previously defined locals which could possibly be accessed or mutated.\n    * @param mutated Such locals which could also be mutated by this definition.\n    * @param refdDefns Previously defined definitions which could possibly be used by this definition.\n    */\n  case class AccessInfo(\n      accessed: Set[Local], \n      mutated: Set[Local], \n      refdDefns: Set[ScopedInfo]\n    ):\n    def ++(that: AccessInfo) = AccessInfo(\n        accessed ++ that.accessed,\n        mutated ++ that.mutated,\n        refdDefns ++ that.refdDefns\n      )\n    def withoutLocals(locals: Set[Local]) = AccessInfo(\n        accessed -- locals,\n        mutated -- locals,\n        refdDefns\n      )\n    def intersectLocals(locals: Set[Local]) = AccessInfo(\n        accessed.intersect(locals),\n        mutated.intersect(locals),\n        refdDefns\n      )\n    def addAccess(l: Local) = copy(accessed = accessed + l)\n    def addMutated(l: Local) = copy(accessed = accessed + l, mutated = mutated + l)\n    def addRefdScopedObj(l: ScopedInfo) = copy(refdDefns = refdDefns + l)\n    \n  object AccessInfo:\n    val empty = AccessInfo(Set.empty, Set.empty, Set.empty)\n\n  object RefOfBms:\n    def unapply(p: Path): Opt[(BlockMemberSymbol, Opt[DefinitionSymbol[?]], Bool)] = p match\n      case Value.Ref(l: BlockMemberSymbol, disamb) => S((l, disamb, false))\n      case s @ Select(_, _) => s.symbol match\n        case Some(value) => value.asBlkMember.map((_, S(value), true))\n        case _ => N\n      case _ => N\n  \n  def modOrObj(d: Defn) = d match\n    case c: ClsLikeDefn => (c.companion.isDefined) || (c.k is syntax.Obj)\n    case _ => false\n\n/**\n  * Lifts classes and functions to the top-level. Also automatically rewrites lambdas.\n  * Assumes the input block does not have any `HandleBlock`s.\n  */\nclass Lifter(topLevelBlk: Block)(using State, Raise, Config):\n  // TODO: implement tracing debug system\n\n  import Lifter.*\n  \n  extension (l: Local)\n    def asLocalPath: LocalPath = LocalPath.Sym(l)\n    def asDefnRef: DefnRef = DefnRef.Sym(l)\n  \n  enum LocalPath:\n    case Sym(l: Local)\n    case BmsRef(l: BlockMemberSymbol, d: DefinitionSymbol[?])\n    case InCapture(capturePath: Path, field: TermSymbol)\n    \n    def read(using ctx: LifterCtxNew): Path = this match\n      case Sym(l) => l.asPath\n      case BmsRef(l, d) => Value.Ref(l, S(d))\n      case InCapture(path, field) => Select(path, field.id)(S(field))\n      \n    def asArg(using ctx: LifterCtxNew) = read.asArg\n    \n    def assign(value: Result, rest: Block)(using ctx: LifterCtxNew): Block = this match\n      case Sym(l) => Assign(l, value, rest)\n      case BmsRef(l, d) => lastWords(\"Tried to assign to a BlockMemberSymbol\")\n      case InCapture(path, field) => AssignField(path, field.id, value, rest)(S(field))\n\n  enum DefnRef:\n    case Sym(l: Local)\n    case InScope(l: BlockMemberSymbol, d: DefinitionSymbol[?])\n    case Field(isym: InnerSymbol, l: BlockMemberSymbol, d: DefinitionSymbol[?])\n  \n    def read(using ctx: LifterCtxNew): Path = this match\n      case Sym(l) => l.asPath\n      case InScope(l, d) => Value.Ref(l, S(d))\n      case Field(isym, l, d) => Select(ctx.symbolsMap(isym).read, Tree.Ident(l.nme))(S(d))\n    \n    def asArg(using ctx: LifterCtxNew) = read.asArg\n  \n  case class FunSyms[T <: DefinitionSymbol[?]](b: BlockMemberSymbol, d: T):\n    def asPath = Value.Ref(b, S(d))\n  object FunSyms:\n    def fromFun(b: BlockMemberSymbol, owner: Opt[InnerSymbol] = N) =\n      FunSyms(b, TermSymbol.fromFunBms(b, owner))\n  \n  type ClsLikeSym = DefinitionSymbol[? <: ClassDef | ModuleOrObjectDef]\n  type ClsSym = DefinitionSymbol[? <: ClassLikeDef]\n  type ModuleOrObjSym = DefinitionSymbol[? <: ModuleOrObjectDef]\n  \n  case class LifterMetadata(\n    unliftable: Set[ClsSym | ModuleOrObjSym],\n  ):\n    def ++(that: LifterMetadata) =\n      LifterMetadata(unliftable ++ that.unliftable)\n  object LifterMetadata:\n    def empty = LifterMetadata(Set.empty)\n  \n  // s is a top-level definition\n  // returns (ignored classes, modules)\n  private def createMetadata(s: ScopeNode): LifterMetadata =\n    var ignored: Set[ClsSym | ModuleOrObjSym] = Set.empty\n    val nestedScopes: Set[ScopedInfo] = s.allChildNodes.map(_.obj.toInfo).toSet - s.obj.toInfo\n    \n    // hack: ClassLikeSymbol does not extend DefinitionSymbol directly, so we must\n    // use a map to convert\n    \n    val moduleObjs: List[ScopedObject.Companion | ScopedObject.Class] = s.allChildNodes.collect:\n      case s @ ScopeNode(obj = o: ScopedObject.Companion) if !s.inModOrTopLevel => o\n      case s @ ScopeNode(obj = o: ScopedObject.Class) if !s.inModOrTopLevel && o.isObj => o\n    \n    for m <- moduleObjs do\n      m match\n        case c: ScopedObject.Class =>\n          ignored += c.cls.isym\n          raise(WarningReport(\n            msg\"Objects are not yet lifted.\" -> c.cls.isym.toLoc :: Nil,\n            N, Diagnostic.Source.Compilation\n          ))\n        case m: ScopedObject.Companion =>\n          ignored += m.compDefn.isym\n          ignored += m.clsBody.isym\n          raise(WarningReport(\n            msg\"Modules are not yet lifted.\" -> m.clsBody.isym.toLoc :: Nil,\n            N, Diagnostic.Source.Compilation\n          ))\n    \n    var inheritanceTree: Set[(ClsSym, ClsSym)] = Set.empty\n    \n    // search for unliftable classes and build the extends graph\n    new BlockTraverser:\n      this.applyScopedObject(s.obj)\n      override def applyCase(cse: Case): Unit =\n        cse match\n          case Case.Cls(cls: (ClassSymbol | ModuleOrObjectSymbol), _) =>\n            if nestedScopes.contains(cls) && !ignored.contains(cls) && !data.getNode(cls).inModOrTopLevel then // don't generate a warning if it's already ignored\n              raise(WarningReport(\n                msg\"Cannot yet lift class/module `${cls.nme}` as it is used in an instance check.\" -> N :: Nil,\n                N, Diagnostic.Source.Compilation\n              ))\n              ignored += cls\n          case _ => ()\n      \n      override def applyResult(r: Result): Unit = r match\n        // do not search the ref to the class\n        case Instantiate(mut, RefOfBms(_, S(d), _), argss) =>\n          argss.flatten.foreach(applyArg)\n        // for class constructors\n        case Call(RefOfBms(_, S(d), _), argss) =>\n          argss.flatten.foreach(applyArg)\n        case _ => super.applyResult(r)\n      \n      override def applyDefn(defn: Defn): Unit = defn match\n        case defn: FunDefn => applyFunDefn(defn)\n        case ValDefn(tsym, sym, rhs) =>\n          tsym.owner.foreach(_.traverse)\n          sym.traverse\n          applyPath(rhs)\n        case ClsLikeDefn(own, isym, sym, ctorSym, k, paramsOpt, auxParams, parentPath, methods,\n            privateFields, publicFields, preCtor, ctor, mod, bufferable)\n        =>\n          own.foreach(_.traverse)\n          isym.traverse\n          sym.traverse\n          // Check if `extends` is a complex expression, i.e. not just extending a class.\n          // If it's just a class, add it to an graph where edges are class extensions.\n          // If B extends A, then A -> B is an edge\n          parentPath match\n            case None => ()\n            case Some(RefOfBms(_, S(s: (ClassSymbol | ModuleOrObjectSymbol)), _)) =>\n              if nestedScopes.contains(s) then inheritanceTree += (s -> isym)\n            case _ if !ignored.contains(isym) =>\n              raise(WarningReport(\n                msg\"Cannot yet lift definition `${sym.nme}` as it extends an expression.\" -> N :: Nil,\n                N, Diagnostic.Source.Compilation\n              ))\n              ignored += isym\n            case _ => ()\n          paramsOpt.foreach(applyParamList)\n          auxParams.foreach(applyParamList)\n          methods.foreach(applyFunDefn)\n          privateFields.foreach(_.traverse)\n          publicFields.foreach: f =>\n            f._1.traverse; f._2.traverse\n          applyBlock(preCtor)\n          applyBlock(ctor)\n          mod.foreach(applyCompanionModule)\n      \n      def isFun(d: Defn) = d match\n        case _: FunDefn => true\n        case _ => false\n      \n      override def applyValue(v: Value): Unit = v match\n        case RefOfBms(_, S(l), _) if nestedScopes.contains(l) => data.getNode(l).obj match\n          case c: ScopedObject.Class if c.isObj => ()\n          // Parameterized class constructors used as naked references are constructor function\n          // references, not first-class class uses. They can be lifted using a curried wrapper.\n          case c: ScopedObject.ClassCtor => ()\n          case c: ScopedObject.Class =>\n            if !c.node.get.inModOrTopLevel then\n              raise(WarningReport(\n                msg\"Cannot yet lift class `${l.nme}` as it is used as a first-class class.\" -> N :: Nil,\n                N, Diagnostic.Source.Compilation\n              ))\n            ignored += c.cls.isym\n          case _ => super.applyValue(v)\n        case _ => super.applyValue(v)\n    \n    // analyze the extends graph\n    val extendsEdges = inheritanceTree.groupBy(_._1).map:\n        case (a, bs) => a -> bs.map(_._2)\n      .toMap\n    var newUnliftable: Set[ClsSym] = Set.empty\n    // dfs starting from unliftable classes\n    def dfs(s: ClsSym): Unit =\n      for \n        edges <- extendsEdges.get(s)\n        b <- edges if !newUnliftable.contains(b) && !ignored.contains(b) \n      do \n        raise(WarningReport(\n          msg\"Cannot yet lift definition `${b.nme}` as it extends an unliftable class.\" -> N :: Nil,\n          N, Diagnostic.Source.Compilation\n        ))\n        newUnliftable += b\n        dfs(b)\n    for case s: ClsLikeSym <- ignored do\n      dfs(s)\n    \n    LifterMetadata(ignored ++ newUnliftable)\n  \n  // This rewrites code so that it's valid when lifted to the top level.\n  // This way, no piece of code must be traversed by a BlockRewriter more than once.\n  // Remark: This is why so much prior analysis is needed and is the main source of complexity in the lifter.\n  class BlockRewriter(using ctx: LifterCtxNew) extends ScopeRewriter:\n    // Closure symbols that point to an initialized closure in this scope\n    var activeClosures: Set[Local] = Set.empty\n    // Map from block member symbols to initialized closures\n    val closureMap: MutMap[BlockMemberSymbol, Local] = MutMap.empty\n    val extraLocals: MutSet[Local] = MutSet.empty\n    \n    def rewrite(b: Block) =\n      val ret = applyBlock(b)\n      Scoped(extraLocals, ret)\n    \n    // Replaces references to BlockMemberSymbols as needed with fresh variables, and\n    // returns the mapping from the symbol to the required variable. When possible,\n    // it also directly rewrites Results (Calls and Instantiates).\n    // Since first-class classes can't be lifted, this is where class\n    // instantiations are rewritten.\n    //\n    // Does *not* rewrite references to non-lifted BMS symbols.\n    //\n    // References to methods and unlifted classes nested inside classes/modules are\n    // always rewritten using `this.defnName` (when accessed internally) or `object.defnName`.\n    def rewriteBms(b: Block) =\n      // BMS's that need to be created\n      val syms: LinkedHashMap[FunSyms[?], Local] = LinkedHashMap.empty\n      val extraLocals: MutSet[Local] = MutSet.empty\n\n      val walker = new BlockDataTransformer(SymbolSubst.Id):\n        // only scan within the block. don't traverse\n        \n        def resolveDefnRef(l: BlockMemberSymbol, d: DefinitionSymbol[?], r: RewrittenScope[?]) =\n          ctx.defnsMap.get(d) match\n          case Some(defnRef) => S(defnRef.read)\n          case None => r.obj match\n            case c: ScopedObject.Class if c.isObj =>\n              ctx.symbolsMap.get(c.cls.isym).map(_.read)\n            case c: ScopedObject.Companion =>\n              ctx.symbolsMap.get(c.clsBody.isym).map(_.read)\n            case _ => N\n\n        override def applyResult(r: Result)(k: Result => Block): Block =\n          r match\n          // if possible, directly rewrite the call using the efficient version\n          case c @ Call(RefOfBms(l, S(d), _), argss) =>\n            ctx.rewrittenScopes.get(d) match\n              case N => super.applyResult(r)(k) // external call, or have not yet traversed that function\n              case S(r) =>\n                applyArgss(argss): newArgss =>\n                  def join2: Block =\n                    resolveDefnRef(l, d, r) match\n                      case Some(value) => k(c.copy(fun = value, argss = newArgss.ne_!)(c.isMlsFun, c.mayRaiseEffects, c.explicitTailCall).withLoc(c.toLoc))\n                      case None => super.applyPath(c.fun): fun2 =>\n                        if (fun2 is c.fun) && (argss is newArgss) then k(c)\n                        else k(c.copy(fun = fun2, argss = newArgss.ne_!)(c.isMlsFun, c.mayRaiseEffects, c.explicitTailCall).withLoc(c.toLoc))\n                  r match\n                    // function call\n                    case f: LiftedFunc => k(f.rewriteCall(c, newArgss))\n                    // ctor call (without using `new`)\n                    case ctor: RewrittenClassCtor => ctor.getRewrittenCls match\n                      case cls: LiftedClass =>\n                        cls.rewriteCall(c, newArgss)(k)\n                      case _ => join2\n                    case _ => join2\n          case inst @ Instantiate(mut, RefOfBms(l, S(d), _), argss) =>\n            applyArgss(argss): newArgss =>\n              def join =\n                if argss is newArgss then inst\n                else inst.copy(argss = newArgss).withLoc(inst.toLoc)\n              ctx.rewrittenScopes.get(d) match\n                case N => k(join)\n                case S(c: LiftedClass) => c.rewriteInstantiate(inst, newArgss)(k)\n                case S(r) => resolveDefnRef(l, d, r) match\n                  case Some(value) => k(Instantiate(inst.mut, value, newArgss).withLoc(inst.toLoc))\n                  case None => k(join)\n          case _ => super.applyResult(r)(k)\n        \n        // extract the call\n        override def applyPath(p: Path)(k: Path => Block): Block = p match\n          case r @ RefOfBms(l, S(d), isSel) => ctx.rewrittenScopes.get(d) match\n            case S(f: LiftedFunc) =>\n              if f.isTrivial then k(r)\n              else\n                val newSym = closureMap.get(l) match\n                  case None =>\n                    val newSym = TempSymbol(N, l.nme + \"$here\")\n                    extraLocals.add(newSym)\n                    syms.addOne(FunSyms(l, d) -> newSym) // add to `syms`: this closure will be initialized in `applyBlock`\n                    closureMap.addOne(l -> newSym) // add to `closureMap`: `newSym` refers to the closure and can be used later\n                    newSym\n\n                  // symbol exists, and is initialized\n                  case Some(value) if activeClosures.contains(value) => value\n                  // symbol exists, needs initialization\n                  case Some(value) =>\n                    syms.addOne(FunSyms(l, d) -> value)\n                    value\n                k(Value.Ref(newSym, N))\n            \n            // Naked reference to a parameterized class constructor (used as a first-class function).\n            // Replace with a partially applied curried C$ wrapper.\n            case S(ctor: RewrittenClassCtor) if !isSel => ctor.getRewrittenCls match\n              case cls: LiftedClass if !cls.isTrivial =>\n                val newSym = closureMap.get(l) match\n                  case None =>\n                    val newSym = TempSymbol(N, l.nme + \"$here\")\n                    extraLocals.add(newSym)\n                    syms.addOne(FunSyms(l, d) -> newSym)\n                    closureMap.addOne(l -> newSym)\n                    newSym\n                  case Some(value) if activeClosures.contains(value) => value\n                  case Some(value) =>\n                    syms.addOne(FunSyms(l, d) -> value)\n                    value\n                k(Value.Ref(newSym, N))\n              case _ =>\n                resolveDefnRef(l, d, ctor) match\n                case Some(value) => k(value)\n                case None => super.applyPath(p)(k)\n            \n            // Other naked references to BlockMemberSymbols.\n            // \n            // For now, do not immediately rewrite selections if they are not referencing\n            // a lifted function, and instead rewrite `qual`. This is so that, when we reference\n            // a nested object or class using a selection `A.B`, we just rewrite the reference to `A`\n            // instead of trying to rewrite the whole reference to `B`. The variable analyzer is\n            // written so that a reference to `A` is available (in the case that `A` is a module or object),\n            // as a passed parameter if needed.\n            //\n            // Once we properly support lifting objects, which involves putting the object instance in\n            // a new public field belonging to its owner, we will need to replace the selection's \n            // disambiguation with that public field's symbol.\n            case S(r) if !isSel =>\n              resolveDefnRef(l, d, r) match\n              case Some(value) => k(value)\n              case None => super.applyPath(p)(k)\n            case _ => super.applyPath(p)(k)\n          \n          case _ => super.applyPath(p)(k)\n      (walker.applyBlock(b), syms.toList, extraLocals)\n    end rewriteBms\n    \n    def applySubBlockAndReset(b: Block): Block =\n      val curActive = activeClosures\n      val ret = applySubBlock(b)\n      activeClosures = curActive\n      ret\n    \n    override def applyBlock(b: Block): Block =\n      // extract references to BlockMemberSymbols in the block which now may\n      // need to be enriched with aux parameters\n      val (rewritten, syms, extras) = rewriteBms(b)\n      extraLocals.addAll(extras)\n      val pre = syms.foldLeft(blockBuilder):\n        case (blk, (funSym, local)) =>\n          ctx.liftedScopes.get(funSym.d) match\n            case Some(l: LiftedFunc) => blk.assign(local, l.rewriteRef)\n            case _ =>\n              // ClassCtor reference: look up the rewritten class ctor to get the LiftedClass\n              ctx.rewrittenScopes(funSym.d) match\n                case ctor: RewrittenClassCtor => ctor.getRewrittenCls match\n                  case cls: LiftedClass => blk.assign(local, cls.rewriteCtorRef)\n                  case _ => die\n                case _ => die\n      \n      // Rewrite the rest\n      val remaining = rewritten match\n        \n        // We create closures once the first time we see them, then re-use them later.\n        // We store already-created closures in a set in the BlockRewriter class.\n        // This set needs to be reset after processing an if-else branch or while loop,\n        // since closures nested inside each branch may not be re-used elsewhere.\n        case Match(scrut, arms, dflt, rst) =>\n          applyPath(scrut): scrut2 =>\n            applyListOf(\n              arms,\n              (tup, k) =>\n                val (cse, blk) = tup\n                val blk2 = applySubBlockAndReset(blk)\n                applyCase(cse): cse2 =>\n                  if (cse2 is cse) && (blk is blk2) then k(tup) else k(cse2 -> blk2)\n            ): arms2 =>\n                val dflt2 = dflt.mapConserve(applySubBlockAndReset)\n                val rst2 = applySubBlock(rst)\n                if (scrut2 is scrut) &&\n                    (arms2 is arms) &&\n                    (dflt2 is dflt) && (rst2 is rst)\n                  then rewritten else Match(scrut2, arms2, dflt2, rst2)\n            \n        case Label(lbl, false, bod, rst) =>\n          val lbl2 = lbl.subst\n          val bod2 = applySubBlockAndReset(bod)\n          val rst2 = applySubBlock(rst)\n          if (lbl2 is lbl) && (bod2 is bod) && (rst2 is rst) then rewritten else Label(lbl2, false, bod2, rst2)\n        case TryBlock(sub, fin, rst) =>\n          val sub2 = applySubBlockAndReset(sub)\n          val fin2 = applySubBlockAndReset(fin)\n          val rst2 = applySubBlock(rst)\n          if (sub2 is sub) && (fin2 is fin) && (rst2 is rst) then rewritten else TryBlock(sub2, fin2, rst2)\n        \n        // Assignment to variables\n        case Assign(lhs, rhs, rest) => ctx.symbolsMap.get(lhs) match\n          case Some(path) => applyResult(rhs): rhs2 =>\n            path.assign(rhs2, applySubBlock(rest))\n          case _ => super.applyBlock(rewritten)\n        \n        // rewrite object definitions, assigning to the saved symbol\n        case Define(d @ ClsLikeDefn(k = syntax.Obj), rest: Block) => ctx.liftedScopes.get(d.isym) match\n          case Some(l: LiftedClass) if l.obj.isObj =>\n            ctx.symbolsMap(l.cls.isym).assign(l.instObject, applySubBlock(rest))\n          case _ => super.applyBlock(rewritten)\n        case _ => super.applyBlock(rewritten)\n      \n      pre.rest(remaining)\n    \n    override def applyPath(p: Path)(k: Path => Block): Block = p match\n      // This rewrites naked references to locals,\n      case Value.Ref(l, _) => ctx.symbolsMap.get(l) match\n        case Some(value) => k(value.read)\n        case _ => super.applyPath(p)(k)\n      \n      case _ => super.applyPath(p)(k)\n  \n  case class LifterResult[+T](liftedDefn: T, extraDefns: List[Lazy[Defn] | Defn])\n  case class LifterCtxNew(\n    liftedScopes: MutMap[LiftedSym, LiftedScope[?]] = MutMap.empty,\n    rewrittenScopes: MutMap[ScopedInfo, RewrittenScope[?]] = MutMap.empty,\n    var symbolsMap: Map[Local, LocalPath] = Map.empty,\n    var defnsMap: Map[DefinitionSymbol[?], DefnRef] = Map.empty,\n    var capturesMap: Map[ScopedInfo, Path] = Map.empty\n  )\n  \n  /**\n    * Creates a capture class for a function consisting of its mutable (and possibly immutable) local variables.\n    * @param f The function to create the capture class for.\n    * @param ctx The lifter context. Determines which variables will be captured.\n    * @return The tuple (defn, varsMap), where `defn` is the capture class's definition, and\n    * `varsMap` maps the function's locals to the corresponding `VarSymbol` (for the class parameters) in the correct order. \n    */\n  def createCaptureCls(s: ScopedObject)\n      : (ClsLikeDefn, List[(Symbol, TermSymbol)]) =\n    val nme = \"Capture$\" + s.nme\n\n    val clsSym = ClassSymbol(\n      Tree.DummyTypeDef(syntax.Cls),\n      Tree.Ident(nme)\n    )\n\n    val cap = usedVars.reqdCaptures(s.toInfo)\n\n    val fresh = FreshInt()\n    \n    val sortedVars: Array[(ctorSyms: (local: Local, vs: VarSymbol), param: Param, valDefn: ValDefn)] =\n      cap.toArray.sortBy(_.uid).map: sym =>\n        val id = fresh.make\n        val nme = sym.nme + \"$\" + id\n        \n        val ident = new Tree.Ident(nme)\n        val varSym = VarSymbol(ident)\n        val fldSym = BlockMemberSymbol(nme, Nil)\n        val tSym = TermSymbol(syntax.MutVal, S(clsSym), ident)\n        \n        val p = Param(FldFlags.empty.copy(isVal = true), varSym, N, Modulefulness.none)\n        varSym.decl = S(p) // * Currently this is only accessed to create the class' toString method\n        \n        val vd = ValDefn(\n          tSym,\n          fldSym,\n          Value.Ref(varSym)\n        )(N, Nil)\n        \n        (sym -> varSym, p, vd)\n    \n    val defn = ClsLikeDefn(\n      None, clsSym, BlockMemberSymbol(nme, Nil),\n      S(TermSymbol(syntax.Fun, S(clsSym), clsSym.id)),\n      syntax.Cls,\n      N,\n      PlainParamList(sortedVars.iterator.map(_.param).toList) :: Nil, None, Nil, Nil, \n      Nil,\n      End(),\n      sortedVars.iterator.foldLeft[Block](End()):\n        case (acc, (_, _, vd)) => Define(vd, acc),\n      N,\n      N,\n    )(N, Nil)\n    \n    (defn, sortedVars.iterator.map(x => (x.ctorSyms.local, x.valDefn.tsym)).toList)\n  \n  class ScopeRewriter(using ctx: LifterCtxNew) extends BlockTransformerShallow(SymbolSubst.Id):\n    \n    val extraDefns: ListBuffer[Defn] = ListBuffer.empty\n    \n    def applyRewrittenScope[T](r: RewrittenScope[T]): T =\n      val LifterResult(rewritten, defns) = liftNestedScopes(r)\n      extraDefns ++= defns.gatherUsed\n      rewritten\n    \n    override def applyBlock(b: Block): Block = b match\n      case s: Scoped =>\n        val uid = data.getUID(s)\n        applyRewrittenScope(ctx.rewrittenScopes(uid)) match\n          case b: Block => b\n          case _ => die\n      case l: Label if l.loop =>\n        val node = data.getNode(l.label)\n        val blk = applyRewrittenScope(ctx.rewrittenScopes(l.label)) match\n          case b: Block => b\n          case _ => die\n        l.copy(body = blk)\n      case Define(defn, rest) =>\n        val dsym = defn match\n          case f: FunDefn => f.dSym\n          case v: ValDefn => v.tsym\n          case c: ClsLikeDefn => c.isym\n        ctx.liftedScopes.get(dsym) match\n          case Some(_) => applySubBlock(rest)\n          case None => super.applyBlock(b)\n      case _ => super.applyBlock(b)\n    override def applyFunDefn(fun: FunDefn) =\n      applyRewrittenScope(ctx.rewrittenScopes(fun.dSym)) match\n        case f: FunDefn => f\n        case _ => die\n    override def applyDefn(defn: Defn)(k: Defn => Block) = defn match\n      case f: FunDefn => k(applyFunDefn(f))\n      case c: ClsLikeDefn =>\n        val newCls = applyRewrittenScope(ctx.rewrittenScopes(c.isym)) match\n          case c: ClsLikeDefn => c\n          case _ => die\n        val newComp = c.companion.map(comp => applyRewrittenScope(ctx.rewrittenScopes(comp.isym))) match\n          case Some(c: ClsLikeBody) => S(c)\n          case Some(_) => die \n          case None => N\n        \n        k(newCls.copy(companion = newComp)(newCls.configOverride, newCls.annotations))\n      case _ => super.applyDefn(defn)(k)\n\n  /**\n    * Represents a scoped object that will be rewritten to reference the lifted version of objects and variables.\n    */\n  sealed abstract class RewrittenScope[T](val obj: TScopedObject[T]):\n    val node = obj.node.get\n    \n    protected final val thisCapturedLocals = usedVars.reqdCaptures(obj.toInfo)\n    val hasCapture = !thisCapturedLocals.isEmpty\n    \n    // These are lazy, because we don't necessarily need a captrue \n    private final lazy val captureInfo: (ClsLikeDefn, List[(Local, TermSymbol)]) = createCaptureCls(obj)\n    \n    lazy val captureClass = captureInfo._1\n    lazy val captureMap = captureInfo._2.toMap\n    lazy val liftedObjsMap: Map[InnerSymbol, LocalPath]\n    \n    lazy val capturePath: Path\n\n    protected def rewriteImpl: LifterResult[T]\n    \n    protected final def addExtraSyms(b: Block, captureSym: Local, objSyms: Iterable[Local], define: Bool): Block =\n      if hasCapture then\n        val undef = Value.Lit(Tree.UnitLit(false)).asArg\n        val inst = Instantiate(\n          true,\n          Value.Ref(captureClass.sym, S(captureClass.isym)),\n          captureInfo._2.map(\n            (sym, _) => sym.asPath.asArg) :: Nil\n        )\n        val assign = Assign(captureSym, inst, b)\n        if define then\n          Scoped(\n            Set(captureSym) ++ objSyms,\n            assign\n          )\n        else assign\n      else\n        if define then Scoped(objSyms.toSet, b) else b\n    \n    /**\n      * Rewrites the contents of this scoped object to reference the lifted versions of variables.\n      *\n      * @return The rewritten scoped object, plus any extra scoped definitions arising from lifting the nested scoped objects.\n      */\n    final def rewrite =\n      if hasCapture then\n        val LifterResult(defn, extra) = rewriteImpl\n        LifterResult(defn, captureClass :: extra)\n      else rewriteImpl\n    \n    /** The path to access locals defined by this object. The primary purpose of this is to rewrite accesses\n      * to locals that have been moved to a capture.\n      */\n    protected final def pathsFromThisObj: Map[Local, LocalPath] =\n      // Remove child BlockMemberSymbols; we will use their definition symbols instead\n        \n      // Locals introduced by this object\n      val fromThisObj = node.localsWithoutBms\n        .map: s =>\n          s -> s.asLocalPath\n        .toMap\n      // Locals introduced by this object that are inside this object's capture\n      val fromCap = thisCapturedLocals\n        .map: s =>\n          val tSym = captureMap(s)\n          s -> LocalPath.InCapture(capturePath, tSym)\n        .toMap\n      // Inner symbols of nested modules and objects\n      val isyms = node.children\n        .collect:\n          case ScopeNode(obj = c: ScopedObject.Companion) =>\n            val s: Local = c.clsBody.isym\n            s -> LocalPath.BmsRef(c.bsym, c.clsBody.isym)\n          case ScopeNode(obj = c: ScopedObject.Class) if c.isObj =>\n            c.cls.isym -> (liftedObjsMap.get(c.cls.isym) match\n              case Some(value) => value // lifted\n              case None => LocalPath.BmsRef(c.bsym, c.cls.isym) // not lifted\n            )\n          \n        .toMap\n      // Note: the order here is important, as fromCap must override keys from\n      // fromThisObj.\n      isyms ++ fromThisObj ++ fromCap\n    \n    lazy val capturePaths =\n      if thisCapturedLocals.isEmpty then Map.empty\n      else Map(obj.toInfo -> capturePath)\n    \n    // BMS refs from ignored defns (including child defns of modules)\n    // Note that we map the DefinitionSymbol to the disambiguated BMS.\n    protected val defnPathsFromThisObj: Map[DefinitionSymbol[?], DefnRef] =\n      node.children.filter:\n        case s @ ScopeNode(obj = r: ScopedObject.Class) if r.isObj => false\n        case _ => true\n      .collect:\n        case s @ ScopeNode(obj = r: ScopedObject.Referencable[?]) if !s.isLifted => \n          val path = r.owner match\n            case Some(isym) => DefnRef.Field(isym, r.bsym, r.sym)\n            case None => DefnRef.InScope(r.bsym, r.sym)\n          r.sym -> path\n      .toMap\n    \n    lazy val defnPaths: Map[DefinitionSymbol[?], DefnRef] = defnPathsFromThisObj\n    \n    lazy val symbolsMap: Map[Local, LocalPath] = pathsFromThisObj\n  \n  /** Represents a scoped object that is to be rewritten and lifted. */\n  sealed abstract class LiftedScope[T <: Defn](override val obj: ScopedObject.Liftable[T])(using ctx: LifterCtxNew) extends RewrittenScope[T](obj):\n    private val AccessInfo(accessed, _, refdScopes) = usedVars.accessMap(obj.toInfo)\n    private val AccessInfo(_, _, allRefdScopes) = usedVars.accessMapWithIgnored(obj.toInfo)\n    private val refdDSyms = refdScopes.collect:\n        case d: LiftedSym => d\n      .toSet\n    \n    /** Symbols that this object will lose access to once lifted, and therefore must receive\n      * as a parameter. Does not include neighbouring objects that this definition may lose\n      * access to. Those are in a separate list.\n      * \n      * Includes symbols introduced by modules and objects, which could be introduced when\n      * accessing their member functions.\n      */\n    final val reqSymbols = accessed\n    \n    private val (reqPassedSymbols, captures) = reqSymbols\n      .partitionMap: s =>\n        usedVars.capturesMap.get(s) match\n          case Some(info) => R((s, info))\n          case None => L(s)\n    \n    /** Locals that are directly passed to this object, i.e. not via a capture. */\n    final val passedSyms: Set[Local] = reqPassedSymbols\n    /** Maps locals to the scope where they were defined. */\n    final val capturesOrigin: Map[Local, ScopedInfo] = captures.toMap\n    /** Locals that are inside captures. */\n    final val inCaptureSyms: Set[Local] = captures.map(_._1)\n    /** Scopes whose captures this object requires. */\n    final val reqCaptures: Set[ScopedInfo] = captures.map(_._2)\n    /**\n      * Neighbouring objects that this definition may lose access to\n      * once lifted, referenced by their *definition symbol* (not BMS).\n      */\n    final val reqDefns = node.reqCaptureObjs\n      .map(_.sym)\n      .toSet.intersect(refdDSyms)\n    \n    /** Maps directly passed locals to the path representing that local within this object. */\n    protected val passedSymsMap: Map[Local, LocalPath]\n    /** Maps scopes to the path representing their captures within this object. */\n    protected val capSymsMap: Map[ScopedInfo, Path]\n    /** Maps definition symbols to the path representing that definition. */\n    protected val passedDefnsMap: Map[DefinitionSymbol[?], DefnRef]\n    \n    protected lazy val capturesOrdered: List[ScopedInfo] = reqCaptures.toList.sorted\n    protected final lazy val passedSymsOrdered: List[Local] = reqPassedSymbols.toList.sortBy(_.uid)\n    protected final lazy val reqDefnsOrdered: List[DefinitionSymbol[?]] = reqDefns.toList.sortBy(_.uid)\n    \n    override lazy val capturePaths: Map[ScopedInfo, Path] =\n      if thisCapturedLocals.isEmpty then capSymsMap\n      else capSymsMap + (obj.toInfo -> capturePath)\n    \n    // Note: we have to make this lazy because Scala's type system is unsound and\n    // lets you access the above two fields before they are initialized\n    // (since this constructor runs before the child classes' constructors)\n    \n    /** Maps symbols to the path representing that local within this object.\n      * Includes locals defined by this object's parents, and this object's own defined locals.\n      */\n    override lazy val symbolsMap: Map[Local, LocalPath] = \n      val fromParents = reqSymbols\n        .map: s =>\n          passedSymsMap.get(s) match\n            // The symbol is passed directly\n            case Some(value) => s -> value\n            // The symbol is passed in a capture\n            case None =>\n              val fromScope = capturesOrigin(s)\n              val capSym = capSymsMap(fromScope)\n              val tSym = ctx.rewrittenScopes(fromScope).captureMap(s)\n              s -> LocalPath.InCapture(capSym, tSym)\n        .toMap\n      fromParents ++ pathsFromThisObj\n    \n    override lazy val defnPaths: Map[DefinitionSymbol[?], DefnRef] =\n      val fromParents = reqDefns\n        .map: s =>\n          s -> passedDefnsMap(s)\n        .toMap\n      defnPathsFromThisObj ++ fromParents\n    \n    final def formatArgs: List[Arg] =\n      val defnsArgs = reqDefnsOrdered.map(d => ctx.defnsMap(d).asArg)\n      val captureArgs = capturesOrdered.map(c => ctx.capturesMap(c).asArg)\n      val localArgs = passedSymsOrdered.map(l => ctx.symbolsMap(l).asArg)\n      defnsArgs ::: captureArgs ::: localArgs\n    \n    final lazy val liftedFromStagedModule: Bool =\n      node.allAncestors.exists:\n        case ScopeNode(ScopedObject.Companion(comp, _), _, _) => comp.isStaged\n        case _ => false\n  \n  /* MIXINS */\n  \n  /**\n    * A rewritten scope with a generic VarSymbol capture symbol.\n    */\n  sealed trait GenericRewrittenScope[T] extends RewrittenScope[T]:\n    lazy val captureSym = VarSymbol(Tree.Ident(obj.nme + \"$cap\"))\n    override lazy val capturePath = captureSym.asPath\n    protected val liftedObjsOrdered: List[InnerSymbol] = node.liftedObjSyms.toList.sortBy(_.uid)\n    protected val liftedObjsSyms: Map[InnerSymbol, VarSymbol] = liftedObjsOrdered.map: s =>\n        s -> VarSymbol(Tree.Ident(s.nme + \"$\"))\n      .toMap\n    override lazy val liftedObjsMap: Map[InnerSymbol, LocalPath] = liftedObjsSyms.map:\n      case k -> v => k -> v.asLocalPath\n    \n    protected def addExtraSyms(b: Block): Block = addExtraSyms(b, captureSym, liftedObjsSyms.values, true)\n    \n  /**\n    * A rewritten scope with a TermSymbol capture symbol.\n    */\n  sealed trait ClsLikeRewrittenScope[T](sym: InnerSymbol) extends RewrittenScope[T]:\n    lazy val captureSym = TermSymbol(syntax.ImmutVal, S(sym), Tree.Ident(obj.nme + \"$cap\"))\n    override lazy val capturePath = captureSym.asPath\n    protected val liftedObjsOrdered: List[InnerSymbol] = node.liftedObjSyms.toList.sortBy(_.uid)\n    protected val liftedObjsSyms: Map[InnerSymbol, TermSymbol] = liftedObjsOrdered.map: s =>\n        s -> TermSymbol(syntax.ImmutVal, S(sym), Tree.Ident(s.nme + \"$\"))\n      .toMap\n    override lazy val liftedObjsMap: Map[InnerSymbol, LocalPath] = liftedObjsSyms.map:\n      case k -> v => k -> v.asLocalPath\n    protected def appendCaptureField(privFields: List[TermSymbol]) =\n      if hasCapture then captureSym :: privFields else privFields\n    protected def rewriteMethods(node: ScopeNode, methods: List[FunDefn])(using ctx: LifterCtxNew) =\n      val mtds = node.children\n        .map: c =>\n          ctx.rewrittenScopes(c.obj.toInfo)\n        .collect:\n          case r: RewrittenFunc if r.obj.isMethod.isDefined => r \n      val (liftedMtds, extras) = mtds.map(liftNestedScopes).unzip(using l => (l.liftedDefn, l.extraDefns))\n      LifterResult(liftedMtds, extras.flatten)\n  \n  // some helpers\n  private def dupParam(p: Param): Param = p.copy(sym = VarSymbol(Tree.Ident(p.sym.nme)))\n  private def dupParams(plist: List[Param]): List[Param] = plist.map(dupParam)\n  private def dupParamList(plist: ParamList): ParamList =\n    plist.copy(params = dupParams(plist.params), restParam = plist.restParam.map(dupParam))\n  \n  /* CONCRETE IMPLS */\n  \n  class RewrittenScopedBlock(override val obj: ScopedObject.ScopedBlock)(using ctx: LifterCtxNew) extends RewrittenScope[Block](obj) with GenericRewrittenScope[Block]:\n    override def rewriteImpl: LifterResult[Block] =\n      val rewriter = new BlockRewriter\n      \n      // Remove symbols belonging to lifted scopes\n      val liftedChildSyms = node.allChildNodes.collect:\n        case s @ ScopeNode(obj = l: ScopedObject.Liftable[?]) if s.isLifted => l.defn.sym\n      \n      val (syms, rewritten) = (obj.block.syms.toSet -- liftedChildSyms, rewriter.rewrite(obj.block.body))\n      val withCapture = addExtraSyms(rewritten)\n      LifterResult(Scoped(syms, withCapture), rewriter.extraDefns.toList)\n  \n  class RewrittenLoop(override val obj: ScopedObject.Loop)(using ctx: LifterCtxNew) extends RewrittenScope[Block](obj) with GenericRewrittenScope[Block]:\n    override def rewriteImpl: LifterResult[Block] =\n      val rewriter = new BlockRewriter\n      \n      val rewritten = rewriter.rewrite(obj.body)\n      val withCapture = addExtraSyms(rewritten)\n      LifterResult(withCapture, rewriter.extraDefns.toList)\n  \n  class RewrittenFunc(override val obj: ScopedObject.Func)(using ctx: LifterCtxNew) extends RewrittenScope[FunDefn](obj) with GenericRewrittenScope[FunDefn]:\n    override def rewriteImpl: LifterResult[FunDefn] =\n      val rewriter = new BlockRewriter\n      \n      val rewritten = rewriter.rewrite(obj.fun.body)\n      val withCapture = addExtraSyms(rewritten)\n      LifterResult(obj.fun.copy(body = withCapture)(obj.fun.configOverride, obj.fun.annotations), rewriter.extraDefns.toList)\n  \n  class RewrittenClassCtor(override val obj: ScopedObject.ClassCtor)(using ctx: LifterCtxNew) extends RewrittenScope[Unit](obj):\n    override lazy val capturePath: Path = lastWords(\"tried to create a capture class for a class ctor\")\n    override lazy val liftedObjsMap: Map[InnerSymbol, LocalPath] = lastWords(\"tried to create obj syms for a class ctor\")\n\n    override protected def rewriteImpl: LifterResult[Unit] = LifterResult((), Nil) // dummy\n    \n    def getRewrittenCls = ctx.rewrittenScopes(obj.cls.isym)\n  \n  class RewrittenClass(override val obj: ScopedObject.Class)(using ctx: LifterCtxNew)\n      extends RewrittenScope[ClsLikeDefn](obj)\n      with ClsLikeRewrittenScope[ClsLikeDefn](obj.cls.isym):\n    \n    private val captureSym = TermSymbol(syntax.ImmutVal, S(obj.cls.isym), Tree.Ident(obj.nme + \"$cap\"))\n    override lazy val capturePath: Path = captureSym.asPath\n    \n    override def rewriteImpl: LifterResult[ClsLikeDefn] =\n      val rewriterCtor = new BlockRewriter\n      val rewriterPreCtor = new BlockRewriter\n      val rewrittenCtor = rewriterCtor.rewrite(obj.cls.ctor)\n      val rewrittenPrector = rewriterPreCtor.rewrite(obj.cls.preCtor)\n      val ctorWithCap = addExtraSyms(rewrittenCtor, captureSym, Nil, false)\n      \n      val LifterResult(newMtds, extras) = rewriteMethods(node, obj.cls.methods)\n      val newCls = obj.cls.copy(\n        ctor = ctorWithCap,\n        preCtor = rewrittenPrector,\n        privateFields = appendCaptureField(liftedObjsOrdered.map(liftedObjsSyms) ::: obj.cls.privateFields),\n        methods = newMtds,\n      )(obj.cls.configOverride, obj.cls.annotations)\n      LifterResult(newCls, rewriterCtor.extraDefns.toList ::: rewriterPreCtor.extraDefns.toList ::: extras)\n\n  class RewrittenCompanion(override val obj: ScopedObject.Companion)(using ctx: LifterCtxNew)\n      extends RewrittenScope[ClsLikeBody](obj)\n      with ClsLikeRewrittenScope[ClsLikeBody](obj.clsBody.isym):\n    \n    private val captureSym = TermSymbol(syntax.ImmutVal, S(obj.clsBody.isym), Tree.Ident(obj.nme + \"$cap\"))\n    override lazy val capturePath: Path = captureSym.asPath\n      \n    override def rewriteImpl: LifterResult[ClsLikeBody] =\n      val rewriterCtor = new BlockRewriter\n      val rewrittenCtor = rewriterCtor.rewrite(obj.clsBody.ctor)\n      val ctorWithCap = addExtraSyms(rewrittenCtor, captureSym, Nil, false)\n      val LifterResult(newMtds, extras) = rewriteMethods(node, obj.clsBody.methods)\n      val newComp = obj.clsBody.copy(\n        ctor = ctorWithCap,\n        privateFields = appendCaptureField(liftedObjsOrdered.map(liftedObjsSyms) ::: obj.clsBody.privateFields),\n        methods = newMtds\n      )\n      LifterResult(newComp, rewriterCtor.extraDefns.toList ::: extras)\n   \n  class LiftedFunc(override val obj: ScopedObject.Func)(using ctx: LifterCtxNew) extends LiftedScope[FunDefn](obj) with GenericRewrittenScope[FunDefn]:\n    private val passedSymsMap_ : Map[Local, VarSymbol] = passedSymsOrdered.map: s =>\n        s -> VarSymbol(Tree.Ident(s.nme))\n      .toMap\n    private val capSymsMap_ : Map[ScopedInfo, VarSymbol] = capturesOrdered.map: i =>\n        val nme = data.getNode(i).obj.nme\n        i -> VarSymbol(Tree.Ident(nme + \"$cap\"))\n      .toMap\n    private val defnSymsMap_ : Map[DefinitionSymbol[?], VarSymbol] = reqDefnsOrdered.sortBy(_.uid).map: i =>\n        val nme = data.getNode(i).obj.nme\n        i -> VarSymbol(Tree.Ident(nme + \"$\"))\n      .toMap\n    \n    override protected val passedSymsMap = passedSymsMap_.view.mapValues(_.asLocalPath).toMap\n    override protected val capSymsMap = capSymsMap_.view.mapValues(_.asPath).toMap\n    override protected val passedDefnsMap = defnSymsMap_.view.mapValues(_.asDefnRef).toMap\n    \n    val auxParams: List[Param] =\n      (reqDefnsOrdered.map(defnSymsMap_) ::: capturesOrdered.map(capSymsMap_) ::: passedSymsOrdered.map(passedSymsMap_))\n      .map: s =>\n        val decl = Param(FldFlags.empty.copy(isVal = false), s, N, Modulefulness.none)\n        s.decl = S(decl)\n        decl\n    \n    // Whether this can be lifted without the need to pass extra parameters.\n    val isTrivial = auxParams.isEmpty\n    \n    val fun = obj.fun\n    \n    val (mainSym, mainDsym) = (fun.sym, fun.dSym)\n    val auxSym = BlockMemberSymbol(fun.sym.nme + \"$\", Nil, fun.sym.nameIsMeaningful)\n    val auxDsym = TermSymbol.fromFunBms(auxSym, fun.owner)\n    \n    // Definition with the auxiliary parameters merged into the first parameter list.\n    private def mkFlattenedDefn: LifterResult[FunDefn] =  \n      val newPlists = fun.params match\n        case head :: next => head.copy(params = auxParams ::: head.params) :: next\n        case Nil => PlainParamList(auxParams) :: Nil\n      val rewriter = new BlockRewriter\n      val newBod = rewriter.rewrite(fun.body)\n      val withCapture = addExtraSyms(newBod)\n      val newDefn = fun.copy(owner = N, sym = mainSym, dSym = mainDsym, params = newPlists, body = withCapture)(\n        fun.configOverride,\n        if liftedFromStagedModule && !fun.isStaged then Annot.Modifier(Keyword.`staged`) :: fun.annotations\n        else fun.annotations)\n      LifterResult(newDefn, rewriter.extraDefns.toList)\n    \n    // Definition with the auxiliary parameters merged into the second parameter list.\n    private def mkAuxDefn: FunDefn =\n      val newPList = PlainParamList(dupParams(auxParams))\n      val (newPlists, syms, restSym) = fun.params match\n        case head :: _ =>\n          val duped = dupParamList(head)\n          (\n            newPList :: duped :: Nil,\n            newPList.params.map(_.sym) ::: duped.params.map(_.sym),\n            duped.restParam.map(_.sym))\n        case Nil => lastWords(\"tried to make an aux defn for a function with no parameter list\")\n      val args = restSym match\n        case Some(value) =>\n          val tail = Arg(S(SpreadKind.Eager), value.asPath) :: Nil\n          syms.foldLeft(tail):\n            case (acc, sym) => Arg(N, sym.asPath) :: acc\n        case None => syms.map(s => Arg(N, s.asPath))\n      \n      val call = Call(Value.Ref(fun.sym, S(fun.dSym)), args ne_:: Nil)(true, true, false)\n      val bod = Return(call, false)\n      \n      FunDefn(\n        N,\n        auxSym,\n        auxDsym,\n        newPlists,\n        bod\n      )(N, fun.annotations)\n    \n    private val aux = Lazy[Defn](mkAuxDefn)\n    \n    def rewriteCall(c: Call, argss: NELs[List[Arg]])(using ctx: LifterCtxNew): Call =\n      if isTrivial then\n        if argss is c.argss then c\n        else c.copy(argss = argss)(c.isMlsFun, c.mayRaiseEffects, c.explicitTailCall).withLocOf(c)\n      else\n        Call(\n          Value.Ref(mainSym, S(mainDsym)),\n          (formatArgs ::: argss.head) ne_:: argss.tail\n        )(\n          isMlsFun = true,\n          mayRaiseEffects = c.mayRaiseEffects,\n          explicitTailCall = c.explicitTailCall\n        ).withLoc(c.toLoc)\n    \n    def rewriteRef(using ctx: LifterCtxNew): Call =\n      if isTrivial then lastWords(\"tried to rewrite a ref to a trivial function\")\n      aux.force // forces computation\n      Call(\n        Value.Ref(auxSym, S(auxDsym)),\n        formatArgs ne_:: Nil\n      )(\n        isMlsFun = true,\n        mayRaiseEffects = false,\n        explicitTailCall = false\n      )\n    \n    def rewriteImpl: LifterResult[FunDefn] =\n      val LifterResult(lifted, extra) = mkFlattenedDefn\n      if isTrivial then LifterResult(lifted, extra)\n      else LifterResult(lifted, aux :: extra)\n  class LiftedClass(override val obj: ScopedObject.Class)(using ctx: LifterCtxNew)\n      extends LiftedScope[ClsLikeDefn](obj)\n      with ClsLikeRewrittenScope[ClsLikeDefn](obj.cls.isym):\n    \n    private val captureSym = TermSymbol(syntax.ImmutVal, S(obj.cls.isym), Tree.Ident(obj.nme + \"$cap\"))\n    override lazy val capturePath: Path = captureSym.asPath\n    \n    private val passedSymsMap_ : Map[Local, (vs: VarSymbol, ts: TermSymbol)] = passedSymsOrdered.map: s =>\n        s -> \n          (\n            VarSymbol(Tree.Ident(s.nme)),\n            TermSymbol(syntax.LetBind, S(obj.cls.isym), Tree.Ident(s.nme))\n          )\n      .toMap\n    private val capSymsMap_ : Map[ScopedInfo, (vs: VarSymbol, ts: TermSymbol)] = capturesOrdered.map: i =>\n        val nme = data.getNode(i).obj.nme + \"$cap\"\n        i ->\n          (\n            VarSymbol(Tree.Ident(nme)),\n            TermSymbol(syntax.LetBind, S(obj.cls.isym), Tree.Ident(nme))\n          )\n      .toMap\n    private val defnSymsMap_ : Map[DefinitionSymbol[?], (vs: VarSymbol, ts: TermSymbol)] = reqDefnsOrdered.map: i =>\n        i -> \n          (\n            VarSymbol(Tree.Ident(i.nme + \"$\")),\n            TermSymbol(syntax.LetBind, S(obj.cls.isym), Tree.Ident(i.nme + \"$\"))\n          )\n      .toMap\n    \n    private lazy val extraPrivSyms: List[TermSymbol] = \n      liftedObjsOrdered.map(liftedObjsSyms)\n      ::: reqDefnsOrdered.map(defnSymsMap_(_).ts)\n      ::: capturesOrdered.map(capSymsMap_(_).ts)\n      ::: passedSymsOrdered.map(passedSymsMap_(_).ts)\n    \n    override protected val passedSymsMap = passedSymsMap_.view.mapValues(_.ts.asLocalPath).toMap\n    override protected val capSymsMap = capSymsMap_.view.mapValues(_.ts.asPath).toMap\n    override protected val passedDefnsMap = defnSymsMap_.view.mapValues(_.ts.asDefnRef).toMap\n    \n    val auxParams: List[Param] =\n      (reqDefnsOrdered.map(x => defnSymsMap_(x).vs)\n        ::: capturesOrdered.map(x => capSymsMap_(x).vs)\n        ::: passedSymsOrdered.map(x => passedSymsMap_(x).vs))\n      .map(Param.simple(_))\n    val auxParamList = PlainParamList(auxParams)\n    \n    // Whether this can be lifted without the need to pass extra parameters.\n    val isTrivial = auxParams.isEmpty\n    \n    val cls = obj.cls\n    \n    val flattenedSym = BlockMemberSymbol(obj.cls.sym.nme + \"$\", Nil, true)\n    val flattenedDSym = TermSymbol.fromFunBms(flattenedSym, N)\n    \n    // Contains *all* parameters, and applies them all at once in a single `Instantiate`\n    def mkFlattenedDefn: FunDefn =\n      // Symbols for the aux parameter list\n      val auxSyms = auxParams.map(p => VarSymbol(Tree.Ident(p.sym.nme)))\n      val auxParamListLocal = PlainParamList(auxSyms.map(Param.simple(_)))\n      \n      val dupedClsAuxParams = cls.auxParams.map(dupParamList(_))\n      val dupedMainOpt = cls.paramsOpt.map(dupParamList(_))\n      val clsParamLists = dupedMainOpt match\n        case Some(dupedMain) => dupedMain :: dupedClsAuxParams\n        case None => dupedClsAuxParams\n      // Contains aux param list\n      val allParamLists = auxParamListLocal :: clsParamLists\n      \n      // Uses the symbols from pl1.\n      def applyPlToPl(pl1: ParamList, pl2: ParamList): List[Arg] = (pl1.restParam, pl2.restParam) match\n        case (S(rp), S(_)) => pl1.params.foldRight(Arg(S(SpreadKind.Eager), rp.sym.asPath) :: Nil)(_.sym.asPath.asArg :: _)\n        case (N, N) => pl1.paramSyms.map(_.asPath.asArg)\n        case _ => die\n      \n      // If class has a main param list, the aux list comes after it\n      inline def appliedMainAndAuxArgs(rest: List[List[Arg]]): List[List[Arg]] = (dupedMainOpt, cls.paramsOpt) match\n        case (S(dupedMain), S(clsParams)) => applyPlToPl(dupedMain, clsParams) :: applyPlToPl(auxParamListLocal, auxParamList) :: rest\n        case (N, N) => applyPlToPl(auxParamListLocal, auxParamList) :: rest\n        case _ => die\n      \n      val appliedClsAuxArgs = (dupedClsAuxParams zip cls.auxParams).map(applyPlToPl)\n      \n      // main :: aux :: clsAuxArgs\n      // or aux :: clsAuxArgs\n      val argsList = appliedMainAndAuxArgs(appliedClsAuxArgs)\n      \n      val ref = Value.Ref(obj.cls.sym, S(obj.cls.isym))\n      val inst = Instantiate(false, ref, argsList)\n      val bod = Return(inst, false)\n      \n      FunDefn(N, flattenedSym, flattenedDSym, allParamLists, bod)(N, annotations = Nil)\n    \n    private val flat = Lazy[Defn](mkFlattenedDefn)\n    \n    def instObject = Instantiate(false, Value.Ref(cls.sym, S(cls.isym)), formatArgs :: Nil)\n    \n    // Rewrite a naked reference to a parameterized class constructor.\n    // Returns a Call to the curried C$ wrapper partially applied with formatArgs.\n    def rewriteCtorRef: Call =\n      if isTrivial then lastWords(\"tried to rewrite a ref to a trivial class ctor\")\n      flat.force\n      Call(\n        Value.Ref(flattenedSym, S(flattenedDSym)),\n        formatArgs ne_:: Nil\n      )(\n        isMlsFun = true,\n        mayRaiseEffects = false,\n        explicitTailCall = false\n      )\n    \n    def rewriteInstantiate(inst: Instantiate, argss: List[List[Arg]])(k: Result => Block): Block =\n      if obj.isObj then lastWords(\"tried to rewrite instantiate for an object\")\n      val path = Value.Ref(cls.sym, S(cls.isym))\n      if isTrivial then\n        if (inst.cls === path) && (inst.argss is argss) then k(inst)\n        else k(inst.copy(cls = path, argss = argss).withLocOf(inst))\n      else if cls.paramsOpt.isEmpty && cls.auxParams.isEmpty then\n        // Paramless class: lifter args go directly into the Instantiate constructor\n        k(Instantiate(inst.mut, path, (formatArgs ::: argss.head) :: argss.tail).withLoc(inst.toLoc))\n      else\n        // Parameterized class: use Instantiate with original args + lifter args inserted after the first list\n        k(Instantiate(inst.mut, path, argss.head :: formatArgs :: argss.tail).withLoc(inst.toLoc))\n    \n    def rewriteCall(c: Call, argss: NELs[List[Arg]])(k: Result => Block)(using ctx: LifterCtxNew): Block =\n      if obj.isObj then lastWords(\"tried to rewrite instantiate for an object\")\n      val path = Value.Ref(cls.sym, S(cls.isym))\n      if isTrivial then\n        if c.argss is argss then k(c)\n        else k(c.copy(argss = argss)(c.isMlsFun, c.mayRaiseEffects, c.explicitTailCall).withLocOf(c))\n      else if cls.paramsOpt.isEmpty && cls.auxParams.isEmpty then\n        // Paramless class: unreachable\n        lastWords(\"Call to paramless class\")\n      else\n        // Parameterized class: Same as Instantiate case\n        k(Instantiate(false, path, argss.head :: formatArgs :: argss.tail).withLoc(c.toLoc))\n    \n    def rewriteImpl: LifterResult[ClsLikeDefn] =\n      val rewriterCtor = new BlockRewriter\n      val rewriterPreCtor = new BlockRewriter\n      val rewrittenCtor = rewriterCtor.rewrite(obj.cls.ctor)\n      val rewrittenPrector = rewriterPreCtor.rewrite(obj.cls.preCtor)\n      \n      val ctorWithCap = addExtraSyms(rewrittenCtor, captureSym, Nil, false)\n      \n      // Assign passed locals and captures\n      val ctorWithPassed = passedSymsOrdered.foldRight(ctorWithCap):\n        case (sym, acc) =>\n          val (vs, ts) = passedSymsMap_(sym)\n          Assign(ts, vs.asPath, acc)\n      val ctorWithCaps = capturesOrdered.foldRight(ctorWithPassed):\n        case (sym, acc) =>\n          val (vs, ts) = capSymsMap_(sym)\n          Assign(ts, vs.asPath, acc)\n      val ctorWithDefns = reqDefnsOrdered.foldRight(ctorWithCaps):\n        case (sym, acc) =>\n          val (vs, ts) = defnSymsMap_(sym)\n          Assign(ts, vs.asPath, acc)\n      \n      val newAuxList = \n        if isTrivial then cls.auxParams\n        else auxParamList :: cls.auxParams\n      \n      val LifterResult(newMtds, extras) = rewriteMethods(node, obj.cls.methods)\n      \n      val newCls = obj.cls.copy(\n        owner = N,\n        k = syntax.Cls, // turn objects into classes\n        ctor = ctorWithDefns,\n        preCtor = rewrittenPrector,\n        privateFields = appendCaptureField(extraPrivSyms ::: obj.cls.privateFields),\n        methods = newMtds,\n        auxParams = newAuxList\n      )(obj.cls.configOverride,\n        if liftedFromStagedModule && !obj.cls.isStaged then Annot.Modifier(Keyword.`staged`) :: obj.cls.annotations\n        else obj.cls.annotations)\n      val extrasDefns = rewriterCtor.extraDefns.toList ::: rewriterPreCtor.extraDefns.toList ::: extras\n      LifterResult(newCls, flat :: extrasDefns)\n  \n  private def createRewritten[T](s: TScopeNode[T])(using ctx: LifterCtxNew): RewrittenScope[T] = s.obj match\n    case _: ScopedObject.Top => lastWords(\"tried to rewrite the top-level scope\")\n    case o: ScopedObject.Class =>\n      if s.isLifted then LiftedClass(o)\n      else RewrittenClass(o)\n    case o: ScopedObject.Companion => RewrittenCompanion(o)\n    case o: ScopedObject.ClassCtor => RewrittenClassCtor(o)\n    case o: ScopedObject.Func =>\n      if s.isLifted then LiftedFunc(o)\n      else RewrittenFunc(o)\n    case o: ScopedObject.Loop => RewrittenLoop(o)\n    case o: ScopedObject.ScopedBlock =>\n      RewrittenScopedBlock(o)\n  \n  // Note: we must write this as a definition here to have tighter types\n  private def rewriteScope[T <: Defn](l: LiftedScope[T])(using ctx: LifterCtxNew) =\n    val LifterResult[T](d1, d2) = liftNestedScopes[T](l)\n    (d1, d2)\n  \n  /**\n    * Lifts scopes nested within `s`, and then rewrites `s`.\n    *\n    * @param s The scope to be rewritten.\n    * @param r The rewritten scope associated with `s`.\n    * @param ctx The lifter context.\n    * @return The rewritten scope with the additional definitions.\n    */\n  private def liftNestedScopesImpl[T](scope: RewrittenScope[T])(using ctx: LifterCtxNew): LifterResult[T] =\n    val node = scope.node\n    \n    // Add the symbols map of the current scope\n    // Note: this will be reset to the original value in liftNestedScopes\n    ctx.symbolsMap ++= scope.symbolsMap\n    ctx.capturesMap ++= scope.capturePaths\n    ctx.defnsMap ++= scope.defnPaths\n    \n    val rewrittenScopes = node.children.map(createRewritten)\n    // The scopes in `lifted` will be rewritten right now\n    // The scopes in `ignored` will be rewritten in-place when traversing the block\n    val (lifted, ignored) = rewrittenScopes.partitionMap:\n      case s: LiftedScope[?] => L(s)\n      case s => R(s)\n    for r <- rewrittenScopes do\n      ctx.rewrittenScopes.put(r.obj.toInfo, r)\n    for l <- lifted do\n      ctx.liftedScopes.put(l.obj.sym, l)\n    \n    val LifterResult(rewrittenObj, extraDefns) = scope.rewrite\n    val (res1, res2) = lifted.map(rewriteScope).unzip\n    val defns = res1 ++ res2.flatten ++ extraDefns\n    LifterResult(rewrittenObj, defns)\n    \n  \n  def liftNestedScopes[T](r: RewrittenScope[T])(using ctx: LifterCtxNew): LifterResult[T] =\n    val curSyms = ctx.symbolsMap\n    val curCaptures = ctx.capturesMap\n    val curDefns = ctx.defnsMap\n    if r.node.isLifted then\n      ctx.symbolsMap = Map.empty\n      ctx.capturesMap = Map.empty\n      ctx.defnsMap = Map.empty\n    val ret = liftNestedScopesImpl(r)\n    ctx.symbolsMap = curSyms\n    ctx.capturesMap = curCaptures\n    ctx.defnsMap = curDefns\n    ret\n  \n  // entry point\n  given ignoredScopes: IgnoredScopes = IgnoredScopes(N)\n  val data = ScopeData(topLevelBlk)\n  val metadata = data.root.children.foldLeft(LifterMetadata.empty)(_ ++ createMetadata(_))\n  \n  def asDSym(s: ClsSym | ModuleOrObjSym): DefinitionSymbol[?] = s\n  val ignored: Set[ScopedInfo] = metadata.unliftable.map(asDSym)\n  ignoredScopes.ignored = S(ignored)\n    \n  val usedVars = UsedVarAnalyzer(topLevelBlk, data)\n  \n  def transform =\n    given ctx: LifterCtxNew = new LifterCtxNew\n    val root = data.root\n    \n    val children = root.children\n    children.foreach: c =>\n      ctx.rewrittenScopes.put(c.obj.toInfo, createRewritten(c))\n    \n    val topLevelRewriter = new ScopeRewriter\n    \n    val (syms, top) = root.obj.contents match\n      case Scoped(syms, body) =>\n        (syms.toSet, body)\n      case b => (Set.empty, b)\n    \n    val transformed = topLevelRewriter.applyBlock(top)\n    val newSyms = syms ++ topLevelRewriter.extraDefns.map(_.sym)\n    val withDefns = topLevelRewriter.extraDefns.foldLeft(transformed):\n      case (acc, d) => Define(d, acc)\n    Scoped(newSyms, withDefns)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/Lowering.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.language.implicitConversions\nimport scala.annotation.tailrec\nimport os.{Path as AbsPath, RelPath}\nimport sourcecode.Line\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.Message.MessageContext\n\nimport codegen.ReflectionInstrumenter\n\nimport semantics.*, ucs.FlatPattern\nimport hkmc2.{semantics => sem}\nimport semantics.{Term => st}\nimport semantics.Term.{Throw => _, *}\nimport semantics.Elaborator.{State, Ctx, ctx}\n\nimport syntax.{Literal, Tree, SpreadKind}\nimport hkmc2.syntax.{Fun, Keyword}\n\n\nabstract class TailOp extends (Result => Block)\nobject Ret extends TailOp:\n  def apply(r: Result): Block = Return(r, implct = false)\nobject ImplctRet extends TailOp:\n  def apply(r: Result): Block =\n    r match\n    case Value.Lit(Tree.UnitLit(false)) => End()\n    case _ => Return(r, implct = true)\nobject Thrw extends TailOp:\n  def apply(r: Result): Block = Throw(r)\n\n\nclass LoweringCtx(\n  initMap: Map[Local, Value], // No longer in meaningful use and could be removed if we don't find a use for it\n  val mayRet: Bool, // For rewriting while loop into tail recursive function, represent whether an explicit return is legal in the current block\n  private val definedSymsDuringLowering: collection.mutable.Set[Symbol] // used to create Scoped blocks\n):\n  val map = initMap\n  def collectScopedSym(s: Symbol) = definedSymsDuringLowering.add(s)\n  def collectScopedSyms(s: Symbol*) = definedSymsDuringLowering.addAll(s)\n  def registerTempSymbol(trm: Option[Term], dbgNme: Str = \"tmp\")(using State) =\n    val tmp = new TempSymbol(trm, dbgNme)\n    definedSymsDuringLowering.add(tmp)\n    tmp\n  def getCollectedSym: collection.Set[Symbol] = definedSymsDuringLowering\n  /*\n  def +(kv: (Local, Value)): Subst =\n    kv match\n    case (ns: NamedSymbol, Value.Ref(ts: TempSymbol)) =>\n      ts.nameHints += ns.name\n    case _ =>\n    Subst(map + kv)\n  */\n  def apply(v: Value): Value = v match\n    case Value.Ref(l, _) => map.getOrElse(l, v)\n    case _ => v\nobject LoweringCtx:\n  def loweringCtx(using sub: LoweringCtx): LoweringCtx = sub\n  val empty =\n    LoweringCtx(Map.empty, mayRet = false, collection.mutable.Set.empty)\n  def nestFunc(using sub: LoweringCtx): LoweringCtx =\n    LoweringCtx(sub.map, mayRet = true, sub.definedSymsDuringLowering)\n  def nestScoped(using sub: LoweringCtx): LoweringCtx =\n    LoweringCtx(sub.map, sub.mayRet, collection.mutable.Set.empty)\nend LoweringCtx\n\nimport LoweringCtx.loweringCtx\n\n\nobject Lowering:\n  \n  def compError: Block =\n    Throw(Value.Lit(Tree.StrLit(\"This code cannot be run as its compilation yielded an error.\")))\n  \n  def fail(err: ErrorReport)(using Raise): Block =\n    raise(err)\n    compError\n  \nimport Lowering.*\n\nclass Lowering()(using Config, TL, Raise, State, Ctx):\n  \n  extension (t: Term)\n    def instantiated = t match\n      case r: Resolvable =>\n        tl.trace[Term](s\"Expanding term ${r}\", post = t => s\"~> ${t}\"):\n          r.expanded\n      case t => t\n  \n  val lowerHandlers: Bool = config.effectHandlers.isDefined\n  val lift: Bool = config.liftDefns.isDefined\n\n  private lazy val wasmBinaryIntrinsicMap: Map[Str, Str] = Map(\n    \"+\" -> \"plus_impl\",\n    \"-\" -> \"minus_impl\",\n    \"*\" -> \"times_impl\",\n    \"/\" -> \"div_impl\",\n    \"%\" -> \"mod_impl\",\n    \"===\" -> \"eq_impl\",\n    \"!==\" -> \"neq_impl\",\n    \"<\" -> \"lt_impl\",\n    \"<=\" -> \"le_impl\",\n    \">\" -> \"gt_impl\",\n    \">=\" -> \"ge_impl\"\n  )\n  private lazy val wasmUnaryIntrinsicMap: Map[Str, Str] = Map(\n    \"-\" -> \"neg_impl\",\n    \"+\" -> \"pos_impl\",\n    \"!\" -> \"not_impl\"\n  )\n  private def wasmIntrinsicPath(sym: BuiltinSymbol, unary: Bool): Opt[Path] =\n    if config.target is CompilationTarget.Wasm then\n      val map = if unary then wasmUnaryIntrinsicMap else wasmBinaryIntrinsicMap\n      map.get(sym.nme).map(name => Value.Ref(State.wasmSymbol).selN(Tree.Ident(name)))\n    else N\n  private lazy val wasmIntrinsicSymbols: Set[BlockMemberSymbol] = Set(\n    ctx.builtins.wasm.plus_impl,\n    ctx.builtins.wasm.minus_impl,\n    ctx.builtins.wasm.times_impl,\n    ctx.builtins.wasm.div_impl,\n    ctx.builtins.wasm.mod_impl,\n    ctx.builtins.wasm.eq_impl,\n    ctx.builtins.wasm.neq_impl,\n    ctx.builtins.wasm.lt_impl,\n    ctx.builtins.wasm.le_impl,\n    ctx.builtins.wasm.gt_impl,\n    ctx.builtins.wasm.ge_impl,\n    ctx.builtins.wasm.neg_impl,\n    ctx.builtins.wasm.pos_impl,\n    ctx.builtins.wasm.not_impl\n  )\n\n  lazy val unreachableFn =\n    Select(Value.Ref(State.runtimeSymbol), Tree.Ident(\"unreachable\"))(S(State.unreachableSymbol))\n  \n  def unit: Path =\n    Select(Value.Ref(State.runtimeSymbol), Tree.Ident(\"Unit\"))(S(State.unitSymbol))\n  \n  \n  // type Rcd = (mut: Bool, args: List[RcdArg]) // * Better, but Scala's patmat exhaustiveness chokes on it\n  type Rcd = (Bool, List[RcdArg])\n  \n  def returnedTerm(t: st)(using LoweringCtx): Block = term(t)(Ret)(using LoweringCtx.nestFunc)\n  \n  def parentConstructor(cls: Term, args: Ls[Term])(using LoweringCtx) = \n    if args.length > 1 then \n      raise:\n        ErrorReport(\n          msg\"Extending a class with multiple parameter lists is not supported\" -> Loc(cls :: args) :: Nil,\n          source = Diagnostic.Source.Compilation\n        )\n    lowerSuperCtorCall(\n      Value.Ref(State.builtinOpsMap(\"super\")),\n      isMlsFun = true,\n      isTailCall = false,\n      args.headOption,\n      N, // TODO: location?\n    )(c => Return(c, implct = true))\n  \n  // * Used to work around Scala's @tailrec annotation for those few calls that are not in tail position.\n  final def term_nonTail(t: st, inStmtPos: Bool = false)(k: Result => Block)(using LoweringCtx): Block =\n    term(t, inStmtPos = inStmtPos)(k)\n  \n\n  @tailrec\n  final def splitBlock(stats: Ls[Statement], imps: Ls[Import], funs: Ls[TermDefinition], rest: Ls[Statement])\n      : (Ls[Import], Ls[TermDefinition], Ls[Statement])\n      =\n    stats match\n    case (imp: Import) :: stats =>\n      splitBlock(stats, imp :: imps, funs, rest)\n    case (fun: TermDefinition) :: stats if fun.k is syntax.Fun =>\n      splitBlock(stats, imps, fun :: funs, rest)\n    case stat :: stats =>\n      splitBlock(stats, imps, funs, stat :: rest)\n    case Nil =>\n      (imps.reverse, funs.reverse, rest.reverse)\n  \n  \n  def block(stats: Ls[Statement], res: Rcd \\/ Term, inStmtPos: Bool = false)\n        (k: Result => Block)(using LoweringCtx): Block =\n    // TODO we should also isolate and reorder classes by inheritance topological sort\n    val (imps, funs, rest) = splitBlock(stats, Nil, Nil, Nil)\n  \n    def blockImpl(stats: Ls[Statement], res: Rcd \\/ Term)(using LoweringCtx): Block =\n      stats match\n      case (t: sem.Term) :: stats =>\n        term(t, inStmtPos = true)(Assign.discard(_, blockImpl(stats, res)))\n      case Nil =>\n        res match\n        case R(res) => term(res, inStmtPos = inStmtPos)(k)\n        case L((mut, flds)) =>\n          k(Record(mut, flds.reverse))\n      case RcdSpread(bod) :: stats =>\n        res match\n        case R(_) => wat(\"RcdField in non-Rcd context\", res)\n        case L((mut, flds)) =>\n          subTerm(bod): l =>\n            blockImpl(stats, L((mut, RcdArg(N, l) :: flds)))\n      case RcdField(lhs, rhs) :: stats =>\n        res match\n        case R(_) => wat(\"RcdField in non-Rcd context\", res)\n        case L((mut, flds)) =>\n          subTerm(lhs): l =>\n            subTerm_nonTail(rhs): r =>\n              blockImpl(stats, L((mut, RcdArg(S(l), r) :: flds)))\n      case (decl @ LetDecl(sym, annotations)) :: stats =>\n        reportAnnotations(decl, annotations)\n        if sym.asTrm.forall(_.owner.isEmpty) then loweringCtx.collectScopedSym(sym)\n        blockImpl(stats, res)\n      case DefineVar(sym, rhs) :: stats =>\n        term(rhs): r =>\n          Assign(sym, r, blockImpl(stats, res))\n      case (_: SetConfig) :: stats =>\n        // Config changes are handled at the program level; skip during block lowering\n        blockImpl(stats, res)\n      case (imp: Import) :: stats =>\n        raise(ErrorReport(\n          msg\"Imports must be at the top level\" ->\n          imp.toLoc :: Nil,\n          source = Diagnostic.Source.Compilation))\n        blockImpl(stats, res)\n      case (d: Declaration) :: stats =>\n        d match\n        case td: TermDefinition =>\n          reportAnnotations(td, td.extraAnnotations)\n          if td.owner.isEmpty && td.hasDeclareModifier.isEmpty then\n            loweringCtx.collectScopedSym(td.sym)\n          td.body match\n          case N => // abstract declarations have no lowering\n            blockImpl(stats, res)\n          case S(bod) =>\n            td.k match\n            case knd: syntax.Val =>\n              assert(td.params.isEmpty)\n              val cfgOverride = td.extraAnnotations.collectFirst:\n                case Annot.Config(modify) => modify(config)\n              subTerm_nonTail(bod)(r =>\n                // Assign(td.sym, r,\n                //   term(st.Blk(stats, res))(k)))\n                Define(ValDefn(td.tsym, td.sym, r)(cfgOverride, td.annotations),\n                  blockImpl(stats, res)))(using LoweringCtx.nestFunc)\n            case syntax.Fun =>\n              val (paramLists, bodyBlock) = setupFunctionOrByNameDef(td.params, bod, S(td.sym.nme))\n              val cfgOverride = td.extraAnnotations.collectFirst:\n                case Annot.Config(modify) => modify(config)\n              Define(FunDefn(td.owner, td.sym, td.tsym, paramLists, bodyBlock)(cfgOverride, td.annotations),\n                blockImpl(stats, res))\n            case syntax.Ins =>\n              // Implicit instances are not parameterized for now.\n              assert(td.params.isEmpty)\n              val cfgOverride = td.extraAnnotations.collectFirst:\n                case Annot.Config(modify) => modify(config)\n              subTerm(bod)(r =>\n                Define(ValDefn(td.tsym, td.sym, r)(cfgOverride, td.annotations),\n                  blockImpl(stats, res)))\n            case syntax.LetBind | syntax.HandlerBind => fail:\n              ErrorReport(\n                msg\"Unexpected declaration kind '${td.k.str}' in lowering\" -> td.toLoc :: Nil,\n                source = Diagnostic.Source.Compilation)\n        case cls: ClassLikeDef if cls.sym.defn.exists(_.hasDeclareModifier.isDefined) =>\n          // * Declarations have no lowering\n          blockImpl(stats, res)\n        case cls: ClassDef if cls.moduleCompanion.isDefined =>\n          // * Class definitions are pure, but their companions might not be,\n          // * as they may contain static initialization code;\n          // * therefore, we lower classes at the point where the companion is defined,\n          // * if it is defined, rather than at the point where the class is defined.\n          reportAnnotations(cls, cls.extraAnnotations)\n          blockImpl(stats, res)\n        case _defn: ClassLikeDef =>\n          if _defn.owner.isEmpty then loweringCtx.collectScopedSym(_defn.bsym)\n          val defn = _defn match\n            case cls: ClassDef => cls\n            case mod: ModuleOrObjectDef if mod.kind is syntax.Mod => // * Currently, both objects and modules are represented as `ModuleOrObjectDef`s\n              mod.classCompanion match\n              case S(comp) => comp.defn.getOrElse(wat(\"Module companion without definition\", mod.companion))\n              case N =>\n                val stagedAnnots = mod.annotations.collect { \n                  case Annot.Modifier(Keyword.`staged`) => Annot.Modifier(Keyword.`staged`) \n                }\n                ClassDef.Plain(mod.owner, syntax.Cls, new ClassSymbol(Tree.DummyTypeDef(syntax.Cls), mod.sym.id),\n                  mod.bsym,\n                  Nil,\n                  N,\n                  ObjBody(Blk(Nil, UnitVal())),\n                  S(mod.sym),\n                  stagedAnnots,\n                )\n            case _ => _defn\n          reportAnnotations(defn, defn.extraAnnotations)\n          val bufferableAnnots = defn.annotations.flatMap:\n            case Annot.Trm(trm: SynthSel) =>\n              if trm.sym.contains(ctx.builtins.annotations.buffered) then\n                S(false)\n              else if trm.sym.contains(ctx.builtins.annotations.bufferable) then\n                S(true)\n              else\n                N\n            case _ => N\n          if bufferableAnnots.length > 1 then\n            raise(ErrorReport(\n              msg\"Only one of bufferable annotation is allowed.\" -> defn.toLoc :: Nil,\n              source = Diagnostic.Source.Compilation\n            ))\n          if bufferableAnnots.length >= 1 then\n            if defn.companion.isDefined then\n              raise(ErrorReport(\n                msg\"No companion class is allowed with @buffered or @bufferable.\" -> defn.toLoc :: Nil,\n                source = Diagnostic.Source.Compilation\n              ))\n          val bufferable = bufferableAnnots.headOption\n          val (mtds, publicFlds, privateFlds, ctor) = defn match\n            case pd: PatternDef =>\n              // Compile the pattern definition into `unapply` and `unapplyStringPrefix`\n              // methods using the `SplitCompiler`, which transliterate the pattern into\n              // UCS splits that backtrack without any optimizations.\n              val compiler = new ups.SplitCompiler\n              val methods = compiler.compilePattern(pd)\n              // We only need `owner`, `sym`, `params` and `body`\n              val mtds = methods.map:\n                case (sym, params, split) =>\n                  val paramLists = params :: Nil\n                  val bodyBlock = inScopedBlock(ucs.Normalization(this)(split)(Ret))\n                  FunDefn.withFreshSymbol(N, sym, paramLists, bodyBlock)(configOverride = N, annotations = Nil)\n              // The return type is intended to be consistent with `gatherMembers`\n              (mtds, Nil, Nil, End())\n            case _ => gatherMembers(defn.body)\n          val mod = defn.companion match\n            case S(sym) =>\n              sym.defn match\n              case S(mod: ModuleOrObjectDef) =>\n                reportAnnotations(mod, mod.extraAnnotations)\n                mod.ext match\n                case S(ext) => fail:\n                  ErrorReport(\n                    msg\"Modules cannot have an extension clause.\" -> ext.toLoc :: Nil,\n                    source = Diagnostic.Source.Compilation\n                  )\n                case N =>\n                val (mtds, publicFlds, privateFlds, ctor) =\n                  gatherMembers(mod.body)\n                S(ClsLikeBody(mod.sym, mtds, privateFlds, publicFlds, ctor, mod.annotations))\n              case _ => N\n            case _ => N\n          defn.ext match\n          case N =>\n            val cfgOverride = defn.extraAnnotations.collectFirst:\n              case Annot.Config(modify) => modify(config)\n            Define(\n              ClsLikeDefn(defn.owner, defn.sym, defn.bsym, defn.ctorSym, defn.kind, defn.paramsOpt, defn.auxParams, N,\n                mtds,\n                privateFlds,\n                publicFlds,\n                End(),\n                ctor,\n                mod,\n                bufferable,\n              )(cfgOverride, defn.annotations),\n              blockImpl(stats, res))\n          case S(ext) =>\n            assert(k isnt syntax.Mod) // modules can't extend things and can't have super calls\n            val cfgOverride = defn.extraAnnotations.collectFirst:\n              case Annot.Config(modify) => modify(config)\n            subTerm(ext.cls): clsp =>\n              val pctor = inScopedBlock(parentConstructor(ext.cls, ext.args))\n              Define(\n                ClsLikeDefn(\n                  defn.owner, defn.sym, defn.bsym, defn.ctorSym, defn.kind, defn.paramsOpt, defn.auxParams, S(clsp),\n                  mtds, privateFlds, publicFlds, pctor, ctor, mod, bufferable,\n                )(cfgOverride, defn.annotations),\n                blockImpl(stats, res)\n              )\n        case td: TypeDef => // * Type definitions are erased\n          blockImpl(stats, res)\n    \n    blockImpl(imps ::: funs ::: rest, res)\n  \n  // * Lowers the `super(...)` call we get from the `extends C(...)` syntax\n  def lowerSuperCtorCall(fr: Path, isMlsFun: Bool, isTailCall: Bool, arg: Opt[Term], loc: Opt[Loc])(k: Result => Block)(using LoweringCtx): Block =\n    arg match\n    case S(arg) =>\n      lowerArgs(arg)(as => k(Call(fr, as ne_:: Nil)(isMlsFun, true, isTailCall).withLoc(loc)))\n    case N =>\n      // * No arguments to a super ctor means a nullary call, e.g., `extends C` means `extends C()`\n      k(Call(fr, Nil ne_:: Nil)(isMlsFun, true, isTailCall).withLoc(loc))\n  \n  /** Lower a call with multiple argument lists into `Call` nodes,\n    * trying to group as many as possible into a single one\n    * when they correspond to parameter lists of the same callee. */\n  def lowerMultiCall(fr: Path, isMlsFun: Bool, isTailCall: Bool, args: Ls[Term], loc: Opt[Loc])(k: Result => Block)(using LoweringCtx): Block =\n    def zipArgs(remainingParamss: Ls[ParamList], remainingArgss: Ls[Term], acc: Ls[Ls[Arg]]): Block =\n      (remainingParamss, remainingArgss) match\n      case (ps :: remainingParams, args :: remainingArgs) =>\n        lowerArgs(args)(as => zipArgs(remainingParams, remainingArgs, as :: acc))\n      case (Nil, Nil) =>\n        k(Call(fr, acc.reverse.ne_!)(isMlsFun, true, isTailCall).withLoc(loc))\n      case (Nil, args :: remainingArgss) =>\n        acc.reverse match\n        case Nil => lowerRemainingCalls(fr, args, remainingArgss, isTailCall, loc)(k)\n        case acc: NELs[Ls[Arg]] =>\n          val tmp = loweringCtx.registerTempSymbol(N, \"baseCall\")\n          val call = Call(fr, acc)(isMlsFun, true, isTailCall).withLoc(loc)\n          Assign(tmp, call, lowerRemainingCalls(Value.Ref(tmp), args, remainingArgss, isTailCall, loc)(k))\n      case (_ :: _, Nil) =>\n        k(Call(fr, acc.reverse.ne_!)(isMlsFun, true, isTailCall).withLoc(loc))\n    fr.targetSymbol match\n    case S(fs: TermSymbol) =>\n      fs.defn match\n      case S(td: TermDefinition) =>\n        zipArgs(td.params, args, Nil)\n      case _ => zipArgs(Nil, args, Nil)\n    case _ => zipArgs(Nil, args, Nil)\n  \n  def lowerRemainingCalls(base: Path, args: Term, remainingArgss: Ls[Term], isTailCall: Bool, loc: Opt[Loc])\n        (k: Result => Block)(using LoweringCtx): Block =\n    lowerArgs(args): as =>\n      val call = Call(base, as ne_:: Nil)(isMlsFun = false, true, isTailCall).withLoc(loc)\n      remainingArgss match\n      case Nil => k(call)\n      case args :: remainingArgss =>\n        val tmp = loweringCtx.registerTempSymbol(N, \"callPrefix\")\n        Assign(tmp, call,\n          lowerRemainingCalls(Value.Ref(tmp), args, remainingArgss, isTailCall, loc)(k))\n  \n  /** Lower an instantiation with multiple argument lists into `Instantiate` and `Call` nodes,\n    * trying to group as many as possible into a single `Instantiate`\n    * when they correspond to constructor parameter lists of the same class.\n    * If fewer argument lists are provided than constructor parameter lists, eta-expands\n    * the missing ones with fresh lambdas (avoiding reliance on mutable JS class curry semantics). */\n  def lowerMultiInstantiate(mut: Bool, cls: Path, args: Ls[Term])(k: Result => Block)(using LoweringCtx): Block =\n    // Nullary instantiations are represented with one empty argument list, matching existing `Instantiate` usage.\n    def buildInstantiate(argss: Ls[Ls[Arg]]): Instantiate =\n      Instantiate(mut, cls, if argss.isEmpty then Nil :: Nil else argss)\n    // * Zip constructor param lists with argument lists, accumulating lowered args.\n    // * Consumes one argument list per constructor param list; when all ctor params are\n    // * consumed but extra args remain, falls back to `Call` nodes on the result.\n    // * When args run out before ctor params are consumed, eta-expands the remaining ones.\n    def zipArgs(remainingCtorParamss: Ls[ParamList], remainingArgss: Ls[Term], acc: Ls[Ls[Arg]]): Block =\n      (remainingCtorParamss, remainingArgss) match\n      case (ps :: remainingParams, args :: remainingArgs) =>\n        lowerArgs(args)(as => zipArgs(remainingParams, remainingArgs, as :: acc))\n      case (Nil, Nil) =>\n        k(buildInstantiate(acc.reverse))\n      case (Nil, args :: remainingArgss) =>\n        val tmp = loweringCtx.registerTempSymbol(N, \"baseInst\")\n        Assign(tmp, buildInstantiate(acc.reverse),\n          lowerRemainingCalls(Value.Ref(tmp), args, remainingArgss, isTailCall = false, N)(k))\n      case (remainingParamss, Nil) =>\n        // * Eta-expand missing argument lists by creating lambdas for each remaining param list.\n        // * This makes partial `new C(args...)` explicit instead of relying on the JS class curry.\n        def etaExpand(remainingParamss: Ls[ParamList], accArgss: Ls[Ls[Arg]]): Result =\n          remainingParamss match\n          case Nil => buildInstantiate(accArgss)\n          case ps :: rest =>\n            val freshSyms = ps.params.map(p => new VarSymbol(new Tree.Ident(p.sym.nme)))\n            softTODO(ps.restParam.isEmpty, \"Eta expanding rest parameters in constructor definitions is not yet supported\")\n            val freshParams = (ps.params zip freshSyms).map((p, s) => Param(p.flags, s, N, p.modulefulness))\n            val freshParamList = ParamList(ps.flags, freshParams, N)\n            val freshArgs = freshSyms.map(s => Arg(N, Value.Ref(s)))\n            Lambda(freshParamList, Return(etaExpand(rest, accArgss :+ freshArgs), implct = false))\n        k(etaExpand(remainingParamss, acc.reverse))\n    // * Resolve the class definition to get the constructor param lists.\n    // * The class path typically resolves to a TermSymbol (the constructor function),\n    // * so we also look up the owner InnerSymbol via TermDefinition#owner.\n    // * Note: apparently, this can also be accessed through TermDefinition#companionClass\n    // * (what Copilot initially used), which is weird.\n    val ctorParamLists: Ls[ParamList] =\n      cls.targetSymbol.flatMap: sym =>\n        sym.asClsOrMod.flatMap(_.defn) orElse\n        sym.asTrm.flatMap(_.owner).flatMap(_.asDefnSym.defn)\n      .fold(Nil: Ls[ParamList]): clsDef =>\n        clsDef.paramsOpt.toList ::: clsDef.auxParams\n    if ctorParamLists.isEmpty then\n      // * Need to specially handle no-param classes\n      args match\n      case Nil =>\n        k(buildInstantiate(Nil))\n      case args :: remainingArgss =>\n        lowerArgs(args): as =>\n          remainingArgss match\n          case Nil =>\n            k(buildInstantiate(as :: Nil))\n          case remainingArgss =>\n            val tmp = loweringCtx.registerTempSymbol(N, \"baseInst\")\n            Assign(tmp, buildInstantiate(as :: Nil),\n              lowerRemainingCalls(Value.Ref(tmp), remainingArgss.head, remainingArgss.tail, isTailCall = false, N)(k))\n    else zipArgs(ctorParamLists, args, Nil)\n  \n  def lowerArgs(arg: Term)(k: Ls[Arg] => Block)(using LoweringCtx): Block =\n    arg match\n    case Tup(fs) =>\n      if fs.exists(e => e match\n        case Spd(SpreadKind.Lazy, _) => true // is lazy spread\n        case _ => false)\n      then\n        raise(ErrorReport(\n          msg\"Lazy spreads are not supported in call arguments\" -> arg.toLoc :: Nil, S(arg),\n          source = Diagnostic.Source.Compilation))\n      args(fs)(as => k(as))\n    case _ =>\n      // Application arguments that are not tuples represent spreads, as in `f(...arg)`\n      subTerm_nonTail(arg): ar =>\n        k(Arg(spread = S(SpreadKind.Eager), ar) :: Nil)\n  \n  def warnPureExprInStmtPos(loc: Opt[Loc], extraInfo: => Opt[Any] = N)(using Line): Unit =\n    raise:\n      WarningReport(msg\"Pure expression in statement position\" -> loc :: Nil, extraInfo,\n        source = Diagnostic.Source.Compilation)\n  \n  def ref(ref: st.Ref, annots: List[Annot], disamb: Opt[DefinitionSymbol[?]], inStmtPos: Bool)(k: Result => Block)(using LoweringCtx): Block =\n    def warnStmt = if inStmtPos then warnPureExprInStmtPos(ref.toLoc, S(ref))\n    \n    val sym = ref.sym\n    sym match\n      case ctx.builtins.source.bms | ctx.builtins.js.bms | ctx.builtins.wasm.bms | ctx.builtins.debug.bms | ctx.builtins.annotations.bms =>\n        return fail:\n          ErrorReport(\n            msg\"Module '${sym.nme}' is virtual (i.e., \\\"compiler fiction\\\"); cannot be used directly\" -> ref.toLoc ::\n            Nil, S(ref), source = Diagnostic.Source.Compilation)\n      case sym if sym.asCls.exists(ctx.builtins.virtualClasses) =>\n        return fail:\n          ErrorReport(\n            msg\"Symbol '${sym.nme}' is virtual (i.e., \\\"compiler fiction\\\"); cannot be used as a term\" -> ref.toLoc ::\n            Nil, S(ref), source = Diagnostic.Source.Compilation)\n      case _ => ()\n    \n    sym match\n    case sym: BuiltinSymbol =>\n      warnStmt\n      if sym.binary then\n        val t1 = new Tree.Ident(\"arg1\")\n        val t2 = new Tree.Ident(\"arg2\")\n        val p1 = Param(FldFlags.empty, VarSymbol(t1), N, Modulefulness.none)\n        val p2 = Param(FldFlags.empty, VarSymbol(t2), N, Modulefulness.none)\n        val ps = PlainParamList(p1 :: p2 :: Nil)\n        val bod = st.App(ref, st.Tup(List(st.Ref(p1.sym)(t1, 666, N).resolve, st.Ref(p2.sym)(t2, 666, N).resolve))\n          (Tree.Tup(Nil // FIXME should not be required (using dummy value)\n            )))(\n            Tree.App(Tree.Empty(), Tree.Empty()), // FIXME should not be required (using dummy value)\n            N,\n            FlowSymbol(sym.nme)\n          ).resolve\n        val (paramLists, bodyBlock) = setupFunctionDef(ps :: Nil, bod, S(sym.nme))\n        tl.log(s\"Ref builtin $sym\")\n        assert(paramLists.length === 1)\n        return k(Lambda(paramLists.head, bodyBlock).withLocOf(ref))\n      if sym.unary then\n        val t1 = new Tree.Ident(\"arg\")\n        val p1 = Param(FldFlags.empty, VarSymbol(t1), N, Modulefulness.none)\n        val ps = PlainParamList(p1 :: Nil)\n        val bod = st.App(ref, st.Tup(List(st.Ref(p1.sym)(t1, 666, N).resolve))\n          (Tree.Tup(Nil // FIXME should not be required (using dummy value)\n            )))(\n            Tree.App(Tree.Empty(), Tree.Empty()), // FIXME should not be required (using dummy value)\n            N,\n            FlowSymbol(sym.nme)\n          ).resolve\n        val (paramLists, bodyBlock) = setupFunctionDef(ps :: Nil, bod, S(sym.nme))\n        tl.log(s\"Ref builtin $sym\")\n        assert(paramLists.length === 1)\n        return k(Lambda(paramLists.head, bodyBlock).withLocOf(ref))\n    case bs: BlockMemberSymbol =>\n      disamb.flatMap(_.defn) match\n      case S(d) if d.hasDeclareModifier.isDefined =>\n        val sel = SynthSel(State.globalThisSymbol.ref().resolve, ref.tree)(S(bs), FlowSymbol.synthSel(ref.tree.name), N, N).withLocOf(ref).resolve\n        return disamb.fold(term(sel)(k))(d => term(st.Resolved(sel, d)(N))(k))\n        // * Note: the alternative below, which might seem more appealing,\n        // * works but does not instrument the selection to check for `undefined`!\n        // return k(Value.Ref(State.globalThisSymbol).sel(ref.tree, bs).withLocOf(ref))\n      case S(td: TermDefinition) if td.k is syntax.Fun =>\n        // * Local functions with no parameter lists are getters\n        // * and are lowered to functions with an empty parameter list\n        // * (non-local functions are compiled into getter methods selected on some prefix)\n        if td.params.isEmpty then\n          return k(Call(\n              Value.Ref(bs, disamb).withLocOf(ref), Nil ne_:: Nil\n            )(isMlsFun = true, true, annots.contains(Annot.TailCall)))\n      case S(_) => ()\n      case N => () // TODO panic here; can only lower refs to elab'd symbols\n    case _ => ()\n    warnStmt\n    k(loweringCtx(Value.Ref(sym, disamb).withLocOf(ref)))\n  \n  @tailrec\n  final def term(t: st, inStmtPos: Bool = false)(k: Result => Block)(using LoweringCtx): Block =\n    tl.log(s\"Lowering.term ${t.showDbg.truncate(100, \"[...]\")}${\n      if inStmtPos then \" (in stmt)\" else \"\"}${\n      t.resolvedSym.fold(\"\")(\" – symbol \" + _)}\")\n    \n    def warnStmt = if inStmtPos then warnPureExprInStmtPos(t.toLoc, S(t))\n    \n    @tailrec\n    def extractAnnots(t: st, acc: List[Annot]): (List[Annot], st) = t match\n      case st.Annotated(annot, trm) => extractAnnots(trm.instantiated, annot :: acc)\n      case _ => (acc, t)\n    \n    val insted = t.instantiated\n    val (annots, trm) = extractAnnots(insted, Nil)\n    reportAnnotations(trm, annots)\n    \n    trm match\n    case st.UnitVal() => k(unit)\n    case st.Lit(lit) =>\n      if lit =/= Tree.UnitLit(false) then warnStmt\n      k(Value.Lit(lit))\n    case st.Ret(res) =>\n      returnedTerm(res)\n    case st.Throw(res) =>\n      term(res)(Thrw)\n    case st.Asc(lhs, rhs) =>\n      term(lhs, inStmtPos = inStmtPos)(k)\n    case st.Tup(fs) =>\n      args(fs)(args => k(Tuple(mut = false, args)))\n    case Mut(st.Tup(fs)) =>\n      args(fs)(args => k(Tuple(mut = true, args)))\n    case st.CtxTup(fs) =>\n      // * This case is currently triggered for code such as `f(using 42)`\n      args(fs)(args => k(Tuple(mut = false, args)))\n    case t @ st.Ref(sym) =>\n      ref(t, annots, N, inStmtPos = inStmtPos)(k)\n    case st.Resolved(t @ st.Ref(bsym), sym) =>\n      ref(t, annots, S(sym), inStmtPos = inStmtPos)(k)\n    case st.App(ref @ Ref(sym: BuiltinSymbol), arg) =>\n      arg match\n      case st.Tup(Nil) =>\n        if !sym.nullary then raise:\n          ErrorReport(\n            msg\"Expected arguments for builtin operator '${sym.nme}'\" -> t.toLoc :: Nil, S(arg),\n            source = Diagnostic.Source.Compilation)\n        k(Value.Ref(sym).withLocOf(ref))\n      case st.Tup(Fld(FldFlags.benign(), arg, N) :: Nil) =>\n        if !sym.unary then raise:\n          ErrorReport(\n            msg\"Builtin '${sym.nme}' is not a unary operator\" -> t.toLoc :: Nil, S(arg),\n            source = Diagnostic.Source.Compilation)\n        subTerm(arg): ar =>\n          val target = wasmIntrinsicPath(sym, unary = true)\n            .getOrElse(Value.Ref(sym).withLocOf(ref))\n          k(Call(target, (Arg(N, ar) :: Nil) ne_:: Nil)(true, false, false))\n      case st.Tup(Fld(FldFlags.benign(), arg1, N) :: Fld(FldFlags.benign(), arg2, N) :: Nil) =>\n        if !sym.binary then raise:\n          ErrorReport(\n            msg\"Builtin '${sym.nme}' is not a binary operator\" -> t.toLoc :: Nil, S(arg),\n            source = Diagnostic.Source.Compilation)\n        subTerm(arg1): ar1 =>\n          def mkBooleanMatch(isAnd: Bool): Block =\n            val posLit = Tree.BoolLit(isAnd)\n            val negLit = Tree.BoolLit(!isAnd)\n            if k.isInstanceOf[TailOp] then Match(\n              ar1,\n              (Case.Lit(posLit) -> term_nonTail(arg2)(k)) :: Nil,\n              S(k(Value.Lit(negLit))),\n              Unreachable(\"tail operation in branches\"),\n            ) else\n              val ts = loweringCtx.registerTempSymbol(N)\n              Match(\n                ar1,\n                (Case.Lit(posLit) -> term_nonTail(arg2)(Assign(ts, _, End()))) :: Nil,\n                S(Assign(ts, Value.Lit(negLit), End())),\n                k(Value.Ref(ts)),\n              )\n          sym match\n          case State.andSymbol => mkBooleanMatch(true)\n          case State.orSymbol => mkBooleanMatch(false)\n          case _ =>\n            subTerm_nonTail(arg2): ar2 =>\n              val target = wasmIntrinsicPath(sym, unary = false)\n                .getOrElse(Value.Ref(sym).withLocOf(ref))\n              k(Call(target, (Arg(N, ar1) :: Arg(N, ar2) :: Nil) ne_:: Nil)(true, false, false))\n      case _ => fail:\n        ErrorReport(\n          msg\"Unexpected arguments for builtin symbol '${sym.nme}'\" -> arg.toLoc :: Nil, S(arg),\n          source = Diagnostic.Source.Compilation)\n    case st.TyApp(f, ts) => term(f)(k) // * Type arguments are erased\n    case st.App(f, arg) =>\n      \n      // Collect chains of App nodes: `f(a)(b)(c)` → (f, [a, b, c])\n      // This allows lowering curried calls as a single `Call` with multiple arg lists.\n      @tailrec\n      def collectAppChain(expr: st, args: Ls[Term]): (st, Ls[Term]) =\n        expr.instantiated match\n        case st.App(inner, innerArg) => collectAppChain(inner, innerArg :: args)\n        case st.TyApp(inner, _) => collectAppChain(inner, args) // type args are erased\n        case expr => (expr, args)\n      val (baseF, allArgs) = collectAppChain(f, arg :: Nil)\n      \n      val isMlsFun = baseF.resolvedSym.fold(baseF.isInstanceOf[st.Lam]):\n        case _: sem.BuiltinSymbol => true\n        case sym: sem.BlockMemberSymbol =>\n          sym.trmImplTree.fold(sym.clsTree.isDefined)(_.k is syntax.Fun)\n        case sym: sem.TermSymbol =>\n          (sym.k is syntax.Fun) && sym.defn.forall(!_.hasDeclareModifier.isDefined)\n        // Do not perform safety check on `MatchSuccess` and `MatchFailure`.\n        case sym => (sym is State.matchSuccessClsSymbol) ||\n          (sym is State.matchFailureClsSymbol)\n      \n      def conclude(fr: Path) =\n        lowerMultiCall(fr, isMlsFun, annots.contains(Annot.TailCall), allArgs, t.toLoc)(k)\n      \n      // * We have to instantiate `f` again because, if `f` is a Sel, the `term`\n      // * function is not called again with f. See below `Sel` and `SelProj` cases.\n      // * Note: now the instantiation is done by `collectAppChain`.\n      val instantiated = baseF\n      val instantiatedResolvedBms = instantiated.resolvedSym.flatMap(_.asBlkMember)\n      \n      instantiated match\n      case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.bitand) =>\n        conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident(\"bitand\")))\n      case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.bitnot) =>\n        conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident(\"bitnot\")))\n      case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.bitor) =>\n        conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident(\"bitor\")))\n      case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.shl) =>\n        conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident(\"shl\")))\n      case t if instantiatedResolvedBms.exists(_ is ctx.builtins.js.try_catch) =>\n        conclude(Value.Ref(State.runtimeSymbol).selN(Tree.Ident(\"try_catch\")))\n      case t if t.resolvedSym.exists {\n        case sym: BlockMemberSymbol => wasmIntrinsicSymbols.contains(sym)\n        case _ => false\n      } =>\n        val sym = t.resolvedSym.get.asInstanceOf[BlockMemberSymbol]\n        conclude(Value.Ref(State.wasmSymbol).selN(Tree.Ident(sym.nme)))\n      case t if instantiatedResolvedBms.exists(_ is ctx.builtins.debug.printStack) =>\n        if !config.effectHandlers.exists(_.debug) then\n          return fail:\n            ErrorReport(\n              msg\"Debugging functions are not enabled\" ->\n              t.toLoc :: Nil,\n              source = Diagnostic.Source.Compilation)\n        conclude(Value.Ref(State.runtimeSymbol).selSN(\"raisePrintStackEffect\").withLocOf(baseF))\n      case t if instantiatedResolvedBms.exists(_ is ctx.builtins.scope.locally) =>\n        // scope.locally only applies to the innermost call; extra args are applied on top\n        if allArgs.length > 1 then\n          subTerm(baseF)(conclude)\n        else\n          arg match\n          case Tup(Fld(FldFlags.benign(), body, N) :: Nil) =>\n            LoweringCtx.nestScoped.givenIn:\n              val res = block(Nil, R(body))(k)\n              val scopedSyms = loweringCtx.getCollectedSym\n              // Put the Scoped in the rest, so that the returned result can be found correctly\n              Scoped(scopedSyms, res)\n          case _ => return fail:\n            ErrorReport(\n              msg\"Unsupported form for scope.locally.\" ->\n              t.toLoc :: Nil,\n              source = Diagnostic.Source.Compilation)\n      // * Due to whacky JS semantics, we need to make sure that selections leading to a call\n      // * are preserved in the call and not moved to a temporary variable.\n      case sel @ Sel(prefix, nme) =>\n        subTerm(prefix): p =>\n          conclude(Select(p, nme)(N).withLocOf(sel))\n      case Resolved(sel @ Sel(prefix, nme), sym) =>\n        subTerm(prefix): p =>\n          conclude(Select(p, nme)(S(sym)).withLocOf(sel))\n      case sel @ SelProj(prefix, _, nme) =>\n        subTerm(prefix): p =>\n          conclude(Select(p, nme)(N).withLocOf(sel))\n      case Resolved(sel @ SelProj(prefix, _, nme), sym) =>\n        subTerm(prefix): p =>\n          conclude(Select(p, nme)(S(sym)).withLocOf(sel))\n      case _ => subTerm(baseF)(conclude)\n    case h @ Handle(lhs, rhs, as, cls, defs, bod) =>\n      if !lowerHandlers then\n        return fail:\n          ErrorReport(\n            msg\"Effect handlers are not enabled\" ->\n            h.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation)\n      val handlers = defs.map {\n        case HandlerTermDefinition(resumeSym, td) => td.body match\n          case None => \n            raise(ErrorReport(msg\"Handler function definitions cannot be empty\" -> td.toLoc :: Nil))\n            N\n          case Some(bod) =>\n            reportAnnotations(td, td.annotations)\n            val (paramLists, bodyBlock) = setupFunctionDef(td.params, bod, S(td.sym.nme))      \n            S(Handler(td.sym, resumeSym, paramLists, bodyBlock))\n      }.collect{ case Some(v) => v }\n      loweringCtx.collectScopedSym(lhs)\n      val resSym = loweringCtx.registerTempSymbol(S(t))\n      subTerm(rhs): par =>\n        subTerms(as): asr =>\n          HandleBlock(lhs, resSym, par, asr, cls, handlers,\n            inScopedBlock(returnedTerm(bod)),\n            k(Value.Ref(resSym)))\n    case st.Blk(sts, res) => block(sts, R(res), inStmtPos = inStmtPos)(k)\n    case Assgn(lhs, rhs) =>\n      lhs match\n      case Ref(sym) =>\n        subTerm(rhs): r =>\n          Assign(sym, r, k(unit))\n      case sel @ SynthSel(prefix, nme) =>\n        subTerm(prefix): p =>\n          subTerm_nonTail(rhs): r =>\n            AssignField(p, nme, r, k(unit))(sel.sym)\n      case sel @ Sel(prefix, nme) =>\n        subTerm(prefix): p =>\n          subTerm_nonTail(rhs): r =>\n            AssignField(p, nme, r, k(unit))(sel.sym)\n      case sel @ DynSel(prefix, fld, ai) =>\n        subTerm(prefix): p =>\n          subTerm_nonTail(fld): f =>\n            subTerm_nonTail(rhs): r =>\n              AssignDynField(p, f, ai, r, k(unit))\n      case sel @ SelProj(prefix, _, proj) =>\n        subTerm(prefix): p =>\n          subTerm_nonTail(rhs): r =>\n            AssignField(p, proj, r, k(unit))(sel.sym)\n      case _ => fail:\n        ErrorReport(\n          msg\"Unexpected left-hand side in assignment (${lhs.describe})\" -> lhs.toLoc :: Nil, S(lhs),\n          source = Diagnostic.Source.Compilation)\n      \n    case st.Lam(params, body) =>\n      warnStmt\n      val (paramLists, bodyBlock) = setupFunctionDef(params :: Nil, body, N)\n      if k.isInstanceOf[TailOp] || bodyBlock.size <= 5\n      then k(Lambda(paramLists.head, bodyBlock))\n      else\n        val lamSym = new BlockMemberSymbol(\"lambda\", Nil, false)\n        loweringCtx.collectScopedSym(lamSym)\n        val lamDef = FunDefn.withFreshSymbol(N, lamSym, paramLists, bodyBlock)(configOverride = N, annotations = Nil)\n        Define(\n          lamDef,\n          k(lamDef.asPath))\n    \n    \n    case iftrm: st.IfLike => ucs.Normalization(this)(iftrm)(k)\n    \n    case iftrm: st.SynthIf => ucs.Normalization(this)(iftrm)(k)\n      \n    case sel @ Sel(prefix, nme) =>\n      setupSelection(prefix, nme, N)(k)\n    case Resolved(sel @ Sel(prefix, nme), sym) =>\n      setupSelection(prefix, nme, S(sym))(k)\n    \n    case sel @ SynthSel(prefix, nme) =>\n      // * Not using `setupSelection` as these selections are not meant to be sanity-checked\n      subTerm(prefix): p =>\n        k(Select(p, nme)(sel.sym.collect:\n          case s: DefinitionSymbol[?] => s\n        ))\n    case Resolved(sel @ SynthSel(prefix, nme), sym) =>\n      // * Not using `setupSelection` as these selections are not meant to be sanity-checked\n      subTerm(prefix): p =>\n        k(Select(p, nme)(S(sym)))\n    \n    case DynSel(prefix, fld, ai) =>\n      subTerm(prefix): p =>\n        subTerm_nonTail(fld): f =>\n          k(DynSelect(p, f, ai))\n      \n      \n    case nw @ (_: New | _: DynNew | Mut(_: New | _: DynNew)) =>\n      val (mut, cls, as, rft) = nw match\n        case New(c, a, r) => (false, c, a, r)\n        case Mut(New(c, a, r)) => (true, c, a, r)\n        case DynNew(c, a) => (false, c, a, N)\n        case Mut(DynNew(c, a)) => (true, c, a, N)\n        case _ => spuriousWarning\n      subTerm(cls): sr =>\n        rft match\n        case N => lowerMultiInstantiate(mut, sr, as)(k)\n        case S((isym, rft)) =>\n          val sym = new BlockMemberSymbol(isym.name, Nil)\n          loweringCtx.collectScopedSym(sym)\n          val (mtds, publicFlds, privateFlds, ctor) = gatherMembers(rft)\n          val pctor = parentConstructor(cls, as)\n          val clsDef = ClsLikeDefn(N, isym, sym, N, syntax.Cls, N, Nil, S(sr),\n            mtds, privateFlds, publicFlds, pctor, ctor, N, N)(N, Nil)\n          val inner = new New(sym.ref().resolved(isym), Nil, N)(N)\n          Define(clsDef, term_nonTail(if mut then Mut(inner) else inner)(k))\n      \n    case Try(sub, finallyDo) =>\n      val l = loweringCtx.registerTempSymbol(S(sub))\n      TryBlock(\n        subTerm_nonTail(sub)(p => Assign(l, p, End())),\n        subTerm_nonTail(finallyDo)(_ => End()),\n        k(Value.Ref(l))\n      )\n    \n    case Quoted(body) => quote(body)(k)\n    \n    // * InvalML-specific cases: t.Cls#field and mutable operations\n    case sp @ SelProj(prefix, _, proj) =>\n      setupSelection(prefix, proj, N)(k)\n    case Resolved(sp @ SelProj(prefix, _, proj), sym) =>\n      setupSelection(prefix, proj, S(sym))(k)\n    case Region(reg, body) =>\n      loweringCtx.collectScopedSym(reg)\n      Assign(reg, Instantiate(mut = true, Select(Value.Ref(State.globalThisSymbol), Tree.Ident(\"Region\"))(N), Nil :: Nil),\n        term_nonTail(body)(k))\n    case RegRef(reg, value) =>\n      plainArgs(reg :: value :: Nil): args =>\n        k(Instantiate(mut = true, Select(Value.Ref(State.globalThisSymbol), Tree.Ident(\"Ref\"))(N), args :: Nil))\n    case Drop(ref) =>\n      subTerm(ref): _ =>\n        k(unit)\n    case Deref(ref) =>\n      subTerm(ref): r =>\n        k(Select(r, Tree.Ident(\"value\"))(N))\n    case SetRef(lhs, rhs) =>\n      subTerm(lhs): ref =>\n        subTerm_nonTail(rhs): value =>\n          AssignField(ref, Tree.Ident(\"value\"), value, k(value))(N)\n    \n    case Mut(Rcd(mut, stats)) => // TODO: warn when in statement position\n      // * Note: I don't think this is supposed to happen...\n      block(stats, L(mut -> Nil))(k)\n    case Rcd(mut, stats) => // TODO: warn when in statement position\n      block(stats, L(mut -> Nil))(k)\n    \n    case Missing => fail:\n      ErrorReport(\n        msg\"Cannot compile ${t.describe} term that was not elaborated (maybe elaboration was one in 'lightweight' mode?)\" ->\n          t.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation)\n    case _: CompType | _: Neg | _: Term.FunTy | _: Term.Forall | _: Term.WildcardTy | _: Term.Unquoted | _: LeadingDotSel\n    => fail:\n      ErrorReport(\n        msg\"Unexpected term form in expression position (${t.describe})\" ->\n          t.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation)\n    case Error => compError\n    \n    // case _ =>\n    //   subTerm(t)(k)\n  \n  def setupTerm(name: Str, args: Ls[Path])(k: Result => Block)(using LoweringCtx): Block =\n    k(Instantiate(mut = false, Value.Ref(State.termSymbol).selSN(name), args.map(_.asArg) :: Nil))\n\n  def setupQuotedKeyword(kw: Str): Path =\n    Value.Ref(State.termSymbol).selSN(\"Keyword\").selSN(kw)\n\n  def setupSymbol(symbol: Local)(k: Result => Block)(using LoweringCtx): Block =\n    k(Instantiate(mut = false, Value.Ref(State.termSymbol).selSN(\"Symbol\"),\n      (Value.Lit(Tree.StrLit(symbol.nme)).asArg :: Nil) :: Nil))\n\n  def quotePattern(p: FlatPattern)(k: Result => Block)(using LoweringCtx): Block = p match\n    case FlatPattern.Lit(lit) => setupTerm(\"LitPattern\", Value.Lit(lit) :: Nil)(k)\n    case _ => // TODO\n      fail:\n        ErrorReport(\n          msg\"Unsupported quasiquote pattern type\" ->\n          p.toLoc :: Nil,\n          source = Diagnostic.Source.Compilation\n        )\n  \n  def quoteSplit(split: Split)(k: Result => Block)(using LoweringCtx): Block = split match\n    case Split.Cons(Branch(scrutinee, pattern, continuation), tail) => quote(scrutinee): r1 =>\n      val l1, l2, l3, l4, l5 = loweringCtx.registerTempSymbol(N)\n      blockBuilder.assign(l1, r1)\n        .chain(b => quotePattern(pattern)(r2 => Assign(l2, r2, b)))\n        .chain(b => quoteSplit(continuation)(r3 => Assign(l3, r3, b)))\n        .chain(b => setupTerm(\"Branch\", (l1 :: l2 :: l3 :: Nil).map(s => Value.Ref(s)))(r4 => Assign(l4, r4, b)))\n        .chain(b => quoteSplit(tail)(r5 => Assign(l5, r5, b)))\n        .rest(setupTerm(\"Cons\", (l4 :: l5 :: Nil).map(s => Value.Ref(s)))(k))\n    case Split.Let(sym, term, tail) => setupSymbol(sym): r1 =>\n      loweringCtx.collectScopedSym(sym)\n      val l1, l2, l3 = loweringCtx.registerTempSymbol(N)\n      blockBuilder.assign(l1, r1)\n        .chain(b => setupTerm(\"Ref\", Value.Ref(l1) :: Nil)(r => Assign(sym, r, b)))\n        .chain(b => quote(term)(r2 => Assign(l2, r2, b)))\n        .chain(b => quoteSplit(tail)(r3 => Assign(l3, r3, b)))\n        .rest(setupTerm(\"Let\", (l1 :: l2 :: l3 :: Nil).map(s => Value.Ref(s)))(k))\n    case Split.Else(default) => quote(default): r =>\n      val l = loweringCtx.registerTempSymbol(N)\n      Assign(l, r, setupTerm(\"Else\", Value.Ref(l) :: Nil)(k))\n    case Split.End => setupTerm(\"End\", Nil)(k)\n\n  lazy val setupFilename: Path =\n    val state = summon[State]\n    Value.Ref(state.importSymbol).selSN(\"meta\").selSN(\"url\")\n\n  def quote(t: st)(k: Result => Block)(using LoweringCtx): Block = t match\n    case Lit(lit) =>\n      setupTerm(\"Lit\", Value.Lit(lit) :: Nil)(k)\n    case Ref(sym) if Elaborator.binaryOps.contains(sym.nme) => // builtin symbols\n      val l = loweringCtx.registerTempSymbol(N)\n      setupTerm(\"Builtin\", Value.Lit(Tree.StrLit(sym.nme)) :: Nil)(k)\n    case Resolved(Ref(sym), disamb) =>\n      k(Value.Ref(sym, S(disamb)))\n    case Ref(sym) =>\n      k(Value.Ref(sym, N))\n    case SynthSel(Ref(sym: ModuleOrObjectSymbol), name) => // Local cross-stage references\n      setupSymbol(sym): r1 =>\n        val l1, l2 = loweringCtx.registerTempSymbol(N)\n        Assign(l1, r1, setupTerm(\"CSRef\", Value.Ref(l1) :: setupFilename :: Value.Lit(syntax.Tree.UnitLit(false)) :: Nil)(r2 =>\n          Assign(l2, r2, setupTerm(\"Sel\", Value.Ref(l2) :: Value.Lit(syntax.Tree.StrLit(name.name)) :: Nil)(k))\n        ))\n    case SynthSel(Ref(sym: BlockMemberSymbol), name) => // Multi-file cross-stage references\n      if config.qqEnabled then fail:\n        ErrorReport(\n            msg\"Cross-stage reference to ${sym.nme}.${name.name} is only allowed in compiled files due to the lack of `import.meta` in REPL mode.\" ->\n            t.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation\n          )\n      else (t.toLoc, sym.toLoc) match\n        case (S(Loc(_, _, Origin(base, _, _))), S(Loc(_, _, Origin(filename, _, _)))) => setupSymbol(sym): r1 =>\n          val l1, l2 = loweringCtx.registerTempSymbol(N)\n          val basePath = base.up\n          val targetPath = filename\n          val relPath = targetPath.relativeTo(basePath).map(_.toString).getOrElse(targetPath.toString)\n          Assign(l1, r1, setupTerm(\"CSRef\", Value.Ref(l1) :: setupFilename :: Value.Lit(syntax.Tree.StrLit(relPath)) :: Nil)(r2 =>\n            Assign(l2, r2, setupTerm(\"Sel\", Value.Ref(l2) :: Value.Lit(syntax.Tree.StrLit(name.name)) :: Nil)(k))\n          ))\n        case _ => fail:\n          ErrorReport(\n            msg\"Cannot refer to imported module ${sym.nme} due to the lack of path.\" ->\n            t.toLoc :: Nil,\n            source = Diagnostic.Source.Compilation\n          )\n    case Lam(params, body) =>\n      def rec(ps: Ls[LocalSymbol & NamedSymbol], ds: Ls[Path])(k: Result => Block)(using LoweringCtx): Block = ps match\n        case Nil => quote(body): r =>\n          val l = loweringCtx.registerTempSymbol(N)\n          val arr = loweringCtx.registerTempSymbol(N, \"arr\")\n          Assign(\n            arr,\n            Tuple(mut = false, ds.reverse.map(_.asArg)),\n            Assign(l, r, setupTerm(\"Lam\", Value.Ref(arr) :: Value.Ref(l) :: Nil)(k)))\n        case sym :: rest =>\n          loweringCtx.collectScopedSym(sym)\n          setupSymbol(sym): r =>\n            val l = loweringCtx.registerTempSymbol(N)\n            Assign(l, r, setupTerm(\"Ref\", Value.Ref(l) :: Nil): r1 =>\n              Assign(sym, r1, rec(rest, Value.Ref(l) :: ds)(k)))\n      rec(params.params.map(_.sym), Nil)(k) // TODO: restParam?\n    case App(lhs, Tup(rhs)) => quote(lhs): r1 =>\n      def rec(es: Ls[Elem], xs: Ls[Path])(k: Result => Block): Block = es match\n        case Nil =>\n          val arrSym = loweringCtx.registerTempSymbol(N, \"arr\")\n          Assign(\n            arrSym,\n            Tuple(mut = false, xs.reverse.map(_.asArg)),\n            setupTerm(\"Tup\", Value.Ref(arrSym) :: Nil): r2 =>\n              val l1 = loweringCtx.registerTempSymbol(N)\n              val l2 = loweringCtx.registerTempSymbol(N)\n              Assign(l1, r1, Assign(l2, r2, setupTerm(\"App\", Value.Ref(l1) :: Value.Ref(l2) :: Nil)(k)))\n          )\n        case Fld(_, t, _) :: rest => quote(t): r2 =>\n          val l = loweringCtx.registerTempSymbol(N)\n          Assign(l, r2, rec(rest, Value.Ref(l) :: xs)(k))\n        case Spd(eager, term) :: rest =>\n          fail:\n            ErrorReport(\n              msg\"Unsupported spread in quasiquote application\" ->\n              term.toLoc :: Nil,\n              source = Diagnostic.Source.Compilation\n            )\n      rec(rhs, Nil)(k)\n    case Blk(LetDecl(sym, _) :: DefineVar(sym2, rhs) :: Nil, res) => // Let bindings\n      require(sym2 is sym)\n      loweringCtx.collectScopedSyms(sym)\n      setupSymbol(sym){r1 =>\n        val l1, l2, l3, l4, l5 = loweringCtx.registerTempSymbol(N)\n        val arrSym = loweringCtx.registerTempSymbol(N, \"arr\")\n        blockBuilder.assign(l1, r1)\n          .chain(b => setupTerm(\"Ref\", Value.Ref(l1) :: Nil)(r => Assign(sym, r, b)))\n          .chain(b => quote(rhs)(r2 => Assign(l2, r2, b)))\n          .chain(b => quote(res)(r3 => Assign(l3, r3, b)))\n          .chain(b => setupTerm(\"LetDecl\", Value.Ref(l1) :: Nil)(r4 => Assign(l4, r4, b)))\n          .chain(b => setupTerm(\"DefineVar\", Value.Ref(l1) :: Value.Ref(l2) :: Nil)(r5 => Assign(l5, r5, b)))\n          .assign(arrSym, Tuple(mut = false, (l4 :: l5 :: Nil).map(s => Value.Ref(s).asArg)))\n          .rest(setupTerm(\"Blk\", Value.Ref(arrSym) :: Value.Ref(l3) :: Nil)(k))\n      }\n    case IfLike(_, IfLikeForm.ReturningIf, split) => quoteSplit(split.getExpandedSplit): r =>\n      val l = loweringCtx.registerTempSymbol(N)\n      Assign(l, r, setupTerm(\"IfLike\", setupQuotedKeyword(\"If\") :: Value.Ref(l) :: Nil)(k))\n    case Unquoted(body) => term(body)(k)\n    case _ => fail:\n      ErrorReport(\n        msg\"Unsupported quasiquote type ${t.describe}\" ->\n        t.toLoc :: Nil,\n        source = Diagnostic.Source.Compilation\n      )\n  \n  def gatherMembers(clsBody: ObjBody)(using LoweringCtx)\n  : (Ls[FunDefn], Ls[BlockMemberSymbol -> TermSymbol], Ls[TermSymbol], Block) =\n    val mtds = clsBody.methods\n      .flatMap: td =>\n        td.body.map: bod =>\n          val (paramLists, bodyBlock) = setupFunctionDef(td.params, bod, S(td.sym.nme))\n          reportAnnotations(td, td.extraAnnotations)\n          val cfgOverride = td.extraAnnotations.collectFirst:\n            case Annot.Config(modify) => modify(config)\n          FunDefn(td.owner, td.sym, td.tsym, paramLists, bodyBlock)(cfgOverride, td.annotations)\n    val publicFlds = clsBody.publicFlds.map(f => f.sym -> f.tsym)\n    val privateFlds = clsBody.nonMethods.collect:\n      case decl @ LetDecl(sym: TermSymbol, annotations) =>\n        reportAnnotations(decl, annotations)\n        sym\n    val ctor =\n      inScopedBlock:\n        term_nonTail(Blk(clsBody.nonMethods, clsBody.blk.res), inStmtPos = true)(Assign.discard(_, End()))\n    \n    (mtds, publicFlds, privateFlds, ctor)\n  \n  def args(elems: Ls[Elem])(k: Ls[Arg] => Block)(using LoweringCtx): Block =\n    val as = elems.map:\n      case sem.Fld(sem.FldFlags.benign(), value, N) => R(N -> value)\n      case sem.Fld(sem.FldFlags.benign(), idx, S(rhs)) => L(idx -> rhs)\n      case arg @ sem.Fld(flags, value, asc) => TODO(s\"Other argument forms: $arg\")\n      case spd: Spd => R(S(spd.k) -> spd.term)\n    // * The straightforward way to lower arguments creates too much recursion depth\n    // * and makes Lowering stack overflow when lowering functions with lots of arguments.\n    /* \n    def rec(as: Ls[Bool -> st], asr: Ls[Arg]): Block = as match\n      case Nil => k(Call(fr, asr.reverse)(isMlsFun, true))\n      case (spd, a) :: as =>\n        subTerm_nonTail(a): ar =>\n          rec(as, Arg(spd, ar) :: asr)\n    rec(as, Nil)\n    */\n    var asr: Ls[Arg] = Nil\n    var fsr: Ls[RcdArg] = Nil\n    def rec(as: Ls[(Term -> Term) \\/ (Opt[SpreadKind] -> st)]): Block = as match\n      case Nil => End()\n      case R((spd, a)) :: as =>\n        subTerm_nonTail(a):\n          ensureOnce: (ar: Path) =>\n              asr ::= Arg(spd, ar)\n              rec(as)\n      case L((idx, t)) :: as =>\n        subTerm_nonTail(idx): ir =>\n          subTerm_nonTail(t):\n            ensureOnce: (tr: Path) =>\n              fsr ::= RcdArg(S(ir), tr)\n              rec(as)\n    val b = rec(as)\n    if fsr.isEmpty then\n      Begin(b, k(asr.reverse))\n    else\n      val rcdSym = loweringCtx.registerTempSymbol(N, \"rcd\")\n      Begin(\n        b,\n        Assign(\n          rcdSym,\n          Record(mut = false, fsr.reverse),\n          k((Arg(N, Value.Ref(rcdSym)) :: asr).reverse)))\n      \n  \n  inline def plainArgs(ts: Ls[st])(k: Ls[Arg] => Block)(using LoweringCtx): Block =\n    subTerms(ts)(asr => k(asr.map(Arg(N, _))))\n  \n  inline def subTerms(ts: Ls[st])(k: Ls[Path] => Block)(using LoweringCtx): Block =\n    // @tailrec // TODO\n    def rec(as: Ls[st], asr: Ls[Path]): Block = as match\n      case Nil => k(asr.reverse)\n      case a :: as =>\n        subTerm_nonTail(a): ar =>\n          rec(as, ar :: asr)\n    rec(ts, Nil)\n  \n  def subTerm_nonTail(t: st, inStmtPos: Bool = false)(k: Path => Block)(using LoweringCtx): Block =\n    subTerm(t, inStmtPos = inStmtPos)(k)\n  \n  inline def subTerm(t: st, inStmtPos: Bool = false)(k: Path => Block)(using LoweringCtx): Block =\n    term(t, inStmtPos = inStmtPos):\n      case v: Value => k(v)\n      case p: Path => k(p)\n      case Lambda(params, body) =>\n        val lamSym = BlockMemberSymbol(\"lambda\", Nil, false)\n        loweringCtx.collectScopedSym(lamSym)\n        val lamDef = FunDefn.withFreshSymbol(N, lamSym, params :: Nil, body)(configOverride = N, annotations = Nil)\n        Define(lamDef, k(lamDef.asPath))\n      case r =>\n        val l = loweringCtx.registerTempSymbol(N)\n        Assign(l, r, k(l |> Value.Ref.apply))\n  \n  \n  def program(main: st.Blk): Program =\n    \n    val (imps, funs, rest) = splitBlock(main.stats, Nil, Nil, Nil)\n    \n    val blk =\n      inScopedBlock(using LoweringCtx.empty):\n        block(funs ::: rest, R(main.res))(ImplctRet)\n    \n    val desug = LambdaRewriter.desugar(blk)\n    \n    val deforested =\n      val outterTl = tl\n      config.deforest match\n        case None => desug\n        case Some(dCfg) =>\n          /*\n          // * For some weird reason (Scala bug?),\n          // * the version below leads to a stack overflows during its initialization\n          given TraceLogger with\n            override def doTrace: Bool = dCfg.debug\n            override def emitDbg(str: Str): Unit = outterTl.emitDbg(s\"deforest > $str\")\n          */\n          (new TraceLogger:\n            override def doTrace: Bool = dCfg.debug\n            override def emitDbg(str: Str): Unit = outterTl.emitDbg(s\"deforest > $str\")\n          ).givenIn:\n            deforest.Deforest(Program(imps.map(imp => imp.sym -> imp.str), desug)).main\n    \n    val handlerPaths = new HandlerPaths\n    \n    val shouldFlattenScopes = config.effectHandlers.isDefined\n    \n    val scopeFlattened =\n      if shouldFlattenScopes then ScopeFlattener().applyBlock(deforested)\n      else deforested\n    \n    val lifted =\n      if lift then Lifter(scopeFlattened).transform\n      else scopeFlattened\n    \n    val (withHandlers2, stackSafetyInfo) = config.effectHandlers.fold((lifted, Map.empty)): opt =>\n      HandlerLowering(handlerPaths, opt).translateTopLevel(lifted)\n    \n    val stackSafe = config.stackSafety match\n      case N => withHandlers2\n      case S(sts) => StackSafeTransform(sts.stackLimit, handlerPaths, stackSafetyInfo).transformTopLevel(withHandlers2)\n    \n    val flattened = stackSafe.flattened\n    \n    val bufferable = BufferableTransform().transform(flattened)\n    \n    // * TODO[Anto]: Can we remove MergeMatchArmTransformer? Seems no longer necessary\n    val merged = MergeMatchArmTransformer.applyBlock(bufferable)\n    \n    val funcToCls =\n      if config.funcToCls then Lifter(FirstClassFunctionTransformer().transform(merged)).transform\n      else merged\n    \n    val staged = ReflectionInstrumenter(using summon).apply(funcToCls)\n    \n    val res =\n      if config.tailRecOpt then TailRecOpt().transform(staged)\n      else staged\n    \n    Program(\n      imps.map(imp => imp.sym -> imp.str),\n      res\n    )\n  \n  \n  def setupSelection(prefix: Term, nme: Tree.Ident, disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using LoweringCtx): Block =\n    subTerm(prefix): p =>\n      k(Select(p, nme)(disamb))\n  \n  final def setupFunctionOrByNameDef(paramLists: List[ParamList], bodyTerm: Term, name: Option[Str])\n      (using LoweringCtx): (List[ParamList], Block) =\n    val physicalParams = paramLists match\n      case Nil => ParamList(ParamListFlags.empty, Nil, N) :: Nil\n      case ps => ps\n    setupFunctionDef(physicalParams, bodyTerm, name)\n  \n  def inScopedBlock(using LoweringCtx)(mkBlock: LoweringCtx ?=> Block): Block =\n    LoweringCtx.nestScoped.givenIn:\n      val body = mkBlock\n      val scopedSyms = loweringCtx.getCollectedSym\n      Scoped(scopedSyms, body)\n  \n  def setupFunctionDef(paramLists: List[ParamList], bodyTerm: Term, name: Option[Str])\n      (using LoweringCtx): (List[ParamList], Block) =\n    val scopedBody = inScopedBlock(returnedTerm(bodyTerm))\n    (paramLists, scopedBody)\n  \n  \n  // TODO: reduce duplication between the two `reportAnnotations`\n  \n  def reportAnnotations(target: Statement, annotations: Ls[Annot]): Unit =\n    def warn(annot: Annot, msg: Opt[Message] = N) = raise:\n      msg match\n        case S(value) => WarningReport(value -> annot.toLoc :: Nil)\n        case N => WarningReport(msg\"This annotation has no effect.\" -> annot.toLoc :: Nil)\n    annotations.foreach:\n      case Annot.Untyped => ()\n      case a @ Annot.TailRec =>\n        target match\n          case TermDefinition(body = S(bod), k = syntax.Fun) => ()\n          case TermDefinition(k = syntax.Fun) => warn(a, S(msg\"Only functions with a body may be marked as @tailrec.\"))\n          case _ => warn(a)\n        \n      case Annot.Modifier(syntax.Keyword.`public` | syntax.Keyword.`private`) => ()\n      case Annot.Modifier(syntax.Keyword(\"staged\")) => ()\n      case _: Annot.Config => () // Config annotations are handled during FunDefn creation\n      case annot => warn(annot)\n\n  def reportAnnotations(receiver: Term, annotations: Ls[Annot]): Unit =\n    def warn(annot: Annot, msg: Opt[Message] = N) =\n      val message = msg match\n        case N => msg\"This annotation is not supported on ${receiver.describe} terms.\"\n        case S(value) => value\n      raise:\n        WarningReport(\n          msg\"This annotation has no effect.\" -> annot.toLoc ::\n          message -> receiver.toLoc :: Nil)\n    \n    annotations.foreach:\n      case Annot.Untyped => ()\n      case a @ Annot.TailCall => receiver match\n        case st.App(Ref(_: BuiltinSymbol), _) => warn(a, S(msg\"The @tailcall annotation has no effect on calls to built-in symbols.\"))\n        case st.App(_, _) => ()\n        case st.Resolved(_, defnSym) => defnSym.defn match\n          case S(td: TermDefinition) if (td.k is syntax.Fun) && td.params.isEmpty => ()\n          case _ => warn(a)\n        case _ => warn(a)\n      case annot => warn(annot)\n\ntrait LoweringSelSanityChecks(using Config, TL, Raise, State)\n    extends Lowering:\n  \n  private val instrument: Bool = config.sanityChecks.isDefined\n  \n  override def setupSelection(prefix: st, nme: Tree.Ident, disamb: Opt[DefinitionSymbol[?]])(k: Result => Block)(using LoweringCtx): Block =\n    if !instrument\n    // || disamb.exists(_.defn.exists(_.hasDeclareModifier.isEmpty)) // * This checks `declare` members, which is normally unwanted\n    || disamb.isDefined\n    // * ^ We assume that resolved selections are well-behaved (will not yield undefined or debind a method)\n    then super.setupSelection(prefix, nme, disamb)(k)\n    else subTerm(prefix): p =>\n      val selRes = loweringCtx.registerTempSymbol(N, \"selRes\")\n      // * We are careful to access `x.f` before `x.f$__checkNotMethod` in case `x` is, eg, `undefined` and\n      // * the access should throw an error like `TypeError: Cannot read property 'f' of undefined`.\n      blockBuilder\n        .assign(selRes, Select(p, nme)(disamb))\n        .assign(State.noSymbol, Select(p, Tree.Ident(nme.name+\"$__checkNotMethod\"))(N))\n          .ifthen(selRes.asPath,\n            Case.Lit(syntax.Tree.UnitLit(false)),\n            Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident(\"Error\"))(N),\n              (Value.Lit(syntax.Tree.StrLit(s\"Access to required field '${nme.name}' yielded 'undefined'\")).asArg :: Nil) :: Nil))\n          )\n          .rest(k(selRes.asPath))\n\n\n\ntrait LoweringTraceLog(instrument: Bool)(using TL, Raise, State)\n    extends Lowering:\n  \n  private def selFromGlobalThis(path: Str*): Path =\n      path.foldLeft[Path](Value.Ref(State.globalThisSymbol)):\n        (qual, name) => Select(qual, Tree.Ident(name))(N)\n    \n  private def assignStmts(stmts: (Local, Result)*)(rest: Block) =\n    stmts.foldRight(rest):\n      case ((sym, res), acc) => Assign(sym, res, acc)\n  \n  private def pureCall(fn: Path, args: Ls[Arg]): Call =\n    Call(fn, args ne_:: Nil)(true, false, false)\n  \n  extension (k: Block => Block)\n    def |>: (b: Block): Block = k(b)\n\n  private val traceLogFn = Value.Ref(State.runtimeSymbol).selSN(\"TraceLogger\").selSN(\"log\")\n  private val traceLogIndentFn = Value.Ref(State.runtimeSymbol).selSN(\"TraceLogger\").selSN(\"indent\")\n  private val traceLogResetFn = Value.Ref(State.runtimeSymbol).selSN(\"TraceLogger\").selSN(\"resetIndent\")\n  private val strConcatFn = selFromGlobalThis(\"String\", \"prototype\", \"concat\", \"call\")\n  private val inspectFn = selFromGlobalThis(\"util\", \"inspect\")\n  \n\n  override def setupFunctionDef(paramLists: List[ParamList], bodyTerm: st, name: Option[Str])\n      (using LoweringCtx): (List[ParamList], Block) =\n    if instrument then\n      val (ps, bod) = handleMultipleParamLists(paramLists, bodyTerm)\n      val instrumentedBody = setupFunctionBody(ps, bod, name)\n      (ps :: Nil, instrumentedBody)\n    else\n      super.setupFunctionDef(paramLists, bodyTerm, name)\n\n  def handleMultipleParamLists(paramLists: List[ParamList], bod: Term) =\n    def go(paramLists: List[ParamList], bod: Term): (ParamList, Term) =\n      paramLists match\n        case Nil => ???\n        case h :: Nil => (h, bod)\n        case h :: t => go(t, Term.Lam(h, bod))\n    go(paramLists.reverse, bod)\n  \n  def setupFunctionBody(params: ParamList, bod: Term, name: Option[Str])(using LoweringCtx): Block = inScopedBlock:\n    val enterMsgSym = loweringCtx.registerTempSymbol(N, dbgNme = \"traceLogEnterMsg\")\n    val prevIndentLvlSym = loweringCtx.registerTempSymbol(N, dbgNme = \"traceLogPrevIndent\")\n    val resSym = loweringCtx.registerTempSymbol(N, dbgNme = \"traceLogRes\")\n    val retMsgSym = loweringCtx.registerTempSymbol(N, dbgNme = \"traceLogRetMsg\")\n    val psInspectedSyms = params.params.map(p => loweringCtx.registerTempSymbol(N, dbgNme = s\"traceLogParam_${p.sym.nme}\") -> p.sym)\n    val resInspectedSym = loweringCtx.registerTempSymbol(N, dbgNme = \"traceLogResInspected\")\n    \n    \n    val psSymArgs = psInspectedSyms.zipWithIndex.foldRight[Ls[Arg]](Arg(N, Value.Lit(Tree.StrLit(\")\"))) :: Nil):\n      case (((s, p), i), acc) => if i == psInspectedSyms.length - 1\n        then Arg(N, Value.Ref(s)) :: acc\n        else Arg(N, Value.Ref(s)) :: Arg(N, Value.Lit(Tree.StrLit(\", \"))) :: acc\n    \n    val tmp1, tmp2, tmp3 = loweringCtx.registerTempSymbol(N)\n    \n    assignStmts(psInspectedSyms.map: (pInspectedSym, pSym) =>\n      pInspectedSym -> pureCall(inspectFn, Arg(N, Value.Ref(pSym)) :: Nil)\n    *) |>:\n    assignStmts(\n      enterMsgSym -> pureCall(\n        strConcatFn,\n        Arg(N, Value.Lit(Tree.StrLit(s\"CALL ${name.getOrElse(\"[arrow function]\")}(\"))) :: psSymArgs\n      ),\n      tmp1 -> pureCall(traceLogFn, Arg(N, Value.Ref(enterMsgSym)) :: Nil),\n      prevIndentLvlSym -> pureCall(traceLogIndentFn, Nil)\n    ) |>: \n    term(bod)(r =>\n    assignStmts(\n      resSym -> r,\n      resInspectedSym -> pureCall(inspectFn, Arg(N, Value.Ref(resSym)) :: Nil),\n      retMsgSym -> pureCall(\n        strConcatFn,\n        Arg(N, Value.Lit(Tree.StrLit(\"=> \"))) :: Arg(N, Value.Ref(resInspectedSym)) :: Nil\n      ),\n      tmp2 -> pureCall(traceLogResetFn, Arg(N, Value.Ref(prevIndentLvlSym)) :: Nil),\n      tmp3 -> pureCall(traceLogFn, Arg(N, Value.Ref(retMsgSym)) :: Nil)\n    ) |>:\n      Ret(Value.Ref(resSym))\n    )\n\n\nobject TrivialStatementsAndMatch:\n  def unapply(b: Block): Opt[(Opt[Block => Block], Match)] =\n    def handleAssignAndMatch(\n      assign: Block => Block,\n      m: Match,\n      k: Opt[Block => Block]\n    ): Some[(Some[Block => Block], Match)] =\n      def newK(r: Block): Block =\n        val newR = k.getOrElse(identity: Block => Block)(r)\n        assign(newR)\n      S(S(newK), m)\n    \n    b match\n      case m: Match => S(N, m)\n      case Assign(lhs, rhs: Path, TrivialStatementsAndMatch(k, m)) =>\n        handleAssignAndMatch(r => Assign(lhs, rhs, r), m, k)\n      case a@AssignField(lhs, nme, rhs: Path, TrivialStatementsAndMatch(k, m)) =>\n        handleAssignAndMatch(r => AssignField(lhs, nme, rhs, r)(a.symbol), m, k)\n      case AssignDynField(lhs, fld, arrayIdx, rhs: Path, TrivialStatementsAndMatch(k, m)) =>\n        handleAssignAndMatch(r =>  AssignDynField(lhs, fld, arrayIdx, rhs, r), m, k)\n      case Define(defn, TrivialStatementsAndMatch(k, m)) => \n        handleAssignAndMatch(r => Define(defn, r), m, k)\n      case _ => N\n\n\nobject MergeMatchArmTransformer extends BlockTransformer(SymbolSubst.Id):\n  override def applyBlock(b: Block): Block = super.applyBlock(b) match\n    case m @ Match(scrut, arms, Some(dflt), rest) =>\n      dflt match\n      case TrivialStatementsAndMatch(k, Match(scrutRewritten, armsRewritten, dfltRewritten, restRewritten))\n        if (scrutRewritten === scrut) && (restRewritten.size * armsRewritten.length) < 10 =>\n          val newArms = restRewritten match\n            case _: End => armsRewritten\n            case _ => armsRewritten.map:\n              case (cse, body) =>\n                cse -> Begin(body, restRewritten)\n          k.getOrElse(identity[Block]):\n            Match(scrut, arms ::: newArms,\n              dfltRewritten.fold(restRewritten)(Begin(_, restRewritten)) |> some, rest)\n      case _ => m\n    case b => b\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/Printer.scala",
    "content": "package hkmc2.codegen\n\nimport scala.collection.mutable.{Map => MutMap}\n\nimport mlscript.utils._, shorthands._\n\nimport hkmc2._\nimport hkmc2.Message.MessageContext\nimport hkmc2.document._\nimport hkmc2.semantics._\nimport hkmc2.syntax._\nimport hkmc2.semantics.Elaborator.State\nimport hkmc2.utils.Scope\nimport hkmc2.utils.Scope.scope\nimport hkmc2.document.Document.{braced, bracedbk}\n\n\n/** `SymbolPrinter` is used for printing symbols that are not locally bound, so that they are consistent\n  * with the debug-printed names shown in other parts of the compiler, such as showAsTreee. */\nclass Printer(using Raise, ShowCfg, SymbolPrinter, Config):\n  \n  val showPurity =\n    false\n    // true\n  \n  def print(l: Local)(using Scope): Document =\n    // * Symbols that are not local symbols in scope should be printed using their dbgName\n    // *  – these will appear like `x¹²` and will be globally unique.\n    scope.lookup(l) match\n      case S(str) => str\n      case N => summon[SymbolPrinter].printSymbol(l)\n  \n  def print(blk: Block)(using Scope): Document = blk match\n    case Match(scrut, arms, dflt, rest) =>\n      def case_doc(c: Case) = c match\n        case Case.Lit(lit) => doc\"${lit.idStr}\"\n        case Case.Cls(cls, path) => doc\"${print(cls)}\"\n        case Case.Tup(len, inf) => doc\"Array($len${if inf then \"+\" else \"\"})\"\n        case Case.Field(name, safe) => doc\"${if safe then \"\" else \"Object \"}{ ${name.name} }\"\n      val docCases = arms\n        .map{ case (c, b) => doc\"${case_doc(c)} => #{  # ${print(b)} #} \" }\n        .mkDocument(sep = doc\" # \")\n      val docDefault = dflt.fold(doc\"\")(e => doc\" # else #{  # ${print(e)} #} \")\n      doc\"match ${print(scrut)} #{  # ${docCases}$docDefault #}  # ${print(rest)}\"\n    case Return(res, implct) => if implct then print(res) else doc\"return ${print(res)}\"\n    case Throw(exc) => doc\"throw ${print(exc)}\"\n    case Label(label, loop, body, rest) =>\n      val l2 = scope.allocateOrGetName(label)\n      // * ^ if we print the same block with a top-level label more than once, using `scope.allocateName` will crash...\n      doc\"${if loop then \"loop\" else \"block\"} $l2: #{  # ${print(body)} #}  # ${print(rest)}\"\n    case Break(label) =>\n      doc\"break ${print(label)}\"\n    case Continue(label) =>\n      doc\"continue ${print(label)}\"\n    case Begin(sub, rest) =>\n      doc\"begin #{  # ${print(sub)}; #}  # ${print(rest)}\"\n    case TryBlock(sub, finallyDo, rest) =>\n      doc\"try #{  # ${print(sub)} #  #} finally #  #{ ${print(finallyDo)}; #  #} ${print(rest)}\"\n    case Assign(_: NoSymbol, rhs, rest) =>\n      doc\"do ${print(rhs)}; # ${print(rest)}\"\n    case Assign(lhs, rhs, rest) =>\n      doc\"set ${print(lhs)} = ${print(rhs)}; # ${print(rest)}\"\n    case AssignField(lhs, nme, rhs, rest) =>\n      doc\"set ${print(lhs)}.${nme.name} = ${print(rhs)}; # ${print(rest)}\"\n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>\n      doc\"set ${print(lhs)}${if arrayIdx then \".\" else \"!\"}${print(fld)} = ${print(rhs)}; # ${print(rest)}\"\n    case Define(defn, rest) =>\n      doc\"define ${print(defn.sym)} as ${print(defn)}; # ${print(rest)}\"\n    case Scoped(syms, body) =>\n      scope.nest.givenIn:\n        import hkmc2.given_Ordering_Uid // Not sure why needed...\n        val names = syms.toList.sortBy(_.uid).map(s => scope.allocateName(s))\n        doc\"let ${names.mkDocument(\", \")}; # ${print(body)}\"\n    case End(msg) if msg.nonEmpty && config.commentGeneratedCode => doc\"end /* ${msg} */\"\n    case End(_) => doc\"end\"\n    case Unreachable(msg) => doc\"unreachable /* ${msg} */\"\n    case _ => TODO(blk)\n  \n  def print(\n      privateFields: Ls[TermSymbol],\n      publicFields: Ls[(BlockMemberSymbol, TermSymbol)],\n      methods: Ls[FunDefn],\n      auxParams: Ls[ParamList],\n      preCtor: Opt[Block],\n      ctor: Block,\n      ctorSym: Opt[TermSymbol],\n  )(using Scope): Document =\n    val privFields = privateFields.map(x => doc\"private val ${print(x)};\").mkDocument(sep = doc\" # \")\n    val pubFields = publicFields.map(x => doc\"val ${print(x._1)};\").mkDocument(sep = doc\" # \")\n    val docPrivFlds = if privateFields.isEmpty then doc\"\" else doc\" # ${privFields}\"\n    val docPubFlds = if publicFields.isEmpty then doc\"\" else doc\" # ${pubFields}\"\n    val docPreCtor = preCtor match\n      case Some(End(_)) => doc\"\"\n      case Some(value) => print(value) :: doc\"; # \"\n      case None => doc\"\"\n    val docCtor = ctor match\n      case End(_) => doc\"\"\n      case _ => doc\" # constructor${ctorSym.fold(doc\"\")(doc\" \" :: print(_))}${printParamLists(auxParams)} ${\n        bracedbk(docPreCtor :: print(ctor))}\"\n    val mtds = methods.map(m => doc\"method ${print(m.sym)} = \" :: print(m)).mkDocument(sep = doc\" # \")\n    val docMethods = if methods.isEmpty then doc\"\" else doc\" # ${mtds}\"\n    if publicFields.isEmpty\n    && privateFields.isEmpty\n    && methods.isEmpty\n    && preCtor.forall(_.isEmpty)\n    && ctor.isEmpty\n    then doc\"\"\n    else doc\" \" :: braced(doc\"${docPrivFlds}${docPubFlds}${docCtor}${docMethods}\")\n  \n  def printParamLists(paramss: Ls[ParamList])(using Scope): Document =\n    paramss\n      .map: pl =>\n        val allParams =\n          pl.params.map(x => scope.allocateName(x.sym)) ++\n          pl.restParam.map(x => \"...\" + scope.allocateName(x.sym))\n        allParams.mkDocument(\"(\", \", \", \")\")\n      .mkDocument(\"\")\n  \n  def print(defn: Defn)(using Scope): Document = defn match\n    case fun @ FunDefn(own, sym, dSym, paramss, body) =>\n      scope.nest.givenIn:\n        val docParams = printParamLists(paramss)\n        val docBody = print(body)\n        val docStaged = if fun.isStaged then doc\"staged \" else doc\"\"\n        doc\"${docStaged}fun ${print(dSym)}${docParams} ${bracedbk(docBody)}\"\n    case ValDefn(tsym, sym, rhs) =>\n      doc\"val ${print(tsym)} = ${print(rhs)}\"\n    case cls @ ClsLikeDefn(own, isym, sym, ctorSym, k, paramsOpt, auxParams, parentSym, methods,\n        privateFields, publicFields, preCtor, ctor, mod, bufferable)\n    => scope.nest.givenIn:\n      val ctorParams = printParamLists(paramsOpt.toList)\n      val docStaged = if cls.isStaged then doc\"staged \" else doc\"\"\n      val docBody = print(privateFields, publicFields, methods, auxParams, S(preCtor), ctor, ctorSym)\n      val clsType = k.str\n      val docCls = doc\"${docStaged}${clsType} ${print(isym)}${ctorParams}${docBody}\"\n      val docModule = mod match\n        case Some(mod) =>\n          val docStaged = if mod.isStaged then doc\"staged \" else doc\"\"\n          val docBody = print(mod.privateFields, mod.publicFields, mod.methods, Nil, N, mod.ctor, N)\n          doc\" # ${docStaged}module ${print(mod.isym)}${docBody}\"\n        case None => doc\"\"\n      doc\"${docCls}${docModule}\"\n  \n  private def showSymbol(name: Str, sym: Opt[DefinitionSymbol[?]]): Document =\n    sym.fold(doc\"${name}﹖\")(sym =>\n      if summon[ShowCfg].debug then doc\"‹${sym.toString}›\" else summon[SymbolPrinter].printSymbol(sym))\n  \n  def print(arg: Arg)(using Scope): Document =\n    val doc = print(arg.value)\n    if arg.spread.nonEmpty\n      then doc\"...${doc}\"\n      else doc\n\n  def print(value: Value)(using Scope): Document = value match\n    case Value.Ref(l: InnerSymbol, N) => doc\"${print(l)}.this\"\n    case Value.Ref(l, N) => print(l)\n    case Value.Ref(l, disamb) => showSymbol(l.nme, disamb)\n    case Value.This(sym) => doc\"this\"\n    case Value.Lit(lit) => doc\"${lit.idStr}\"\n  \n  def print(path: Path)(using Scope): Document = path match\n    case sel @ Select(qual, name) =>\n      val docQual = print(qual)\n      doc\"${docQual}.${showSymbol(name.name, sel.symbol)}\"\n    case DynSelect(qual, fld, arrayIdx) =>\n      doc\"${print(qual)}${if arrayIdx then \".\" else \"!\"}${print(fld)}\"\n    case x: Value => print(x)\n    // case _ => TODO(path)\n  \n  def print(result: Result)(using Scope): Document =\n    (if !showPurity || result.isPure then \"\" else \"!\") ::\n    result.match\n    case Call(fun, argss) =>\n      val chainedArgs = argss.map(args => doc\"(${args.map(print).mkDocument(\", \")})\").mkDocument(\"\")\n      doc\"${print(fun)}${chainedArgs}\"\n    case Instantiate(mut, cls, argss) =>\n      val chainedArgs = argss.map(args => doc\"(${args.map(print).mkDocument(\", \")})\").mkDocument(\"\")\n      doc\"new ${if mut then \"mut \" else \"\"}${print(cls)}${chainedArgs}\"\n    case Lambda(params, body) =>\n      scope.nest.givenIn:\n        val allParams =\n          params.params.map(x => scope.allocateName(x.sym)) ++\n          params.restParam.map(x => \"...\" + scope.allocateName(x.sym))\n        val docParams = allParams.mkDocument(\"(\", \", \", \")\")\n        doc\"$docParams => ${bracedbk(print(body))}\"\n    case Tuple(mut, elems) =>\n      val docElems = elems.map(x => print(x)).mkDocument(\", \")\n      doc\"${if mut then \"mut \" else \"\"}[${docElems}]\"\n    case Record(mut, args) =>\n      doc\"${if mut then \"mut \" else \"\"}{ ${\n        args.map(x => x.idx.fold(doc\"...\")(p => print(p) :: \": \") :: print(x.value)).mkDocument(\", \")\n      } }\"\n    case x: Path => print(x)\n  \n  def print(imports: Ls[Local -> Str])(using Scope): Document =\n    imports.map: (local, path) =>\n        val docLocal = scope.allocateName(local)\n        doc\"import ${docLocal}; # \"\n      .mkDocument()\n  \n  def print(prog: Program)(using Scope): Document =\n    doc\"${print(prog.imports)}${print(prog.main)}\"\n  \n  def worksheet(prog: Program)(using Scope): Document =\n    doc\"${print(prog.imports)}${\n      prog.main match\n      case Scoped(syms, body) =>\n        // * The top-level Scoped block in a worksheet contains symbols that are actually\n        // * still visible in the following blocks;\n        // * therefore, we want to avoid printing them with fresh names but use their `dbgName`s instead.\n        scope.nest.givenIn:\n          import hkmc2.given_Ordering_Uid // Not sure why needed...\n          val names = syms.toList.sortBy(_.uid).map:\n            case s: TempSymbol => scope.allocateName(s)\n            case s => summon[SymbolPrinter].printSymbol(s)\n          doc\"let ${names.mkString(\", \")}; # ${print(body)}\"\n      case m => print(m)\n    }\"\n  \n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/ReflectionInstrumenter.scala",
    "content": "package hkmc2\npackage codegen\n\nimport utils.*\nimport hkmc2.Message.MessageContext\n\nimport scala.collection.mutable.HashMap\nimport scala.util.chaining.*\n\nimport mlscript.utils.*, shorthands.*\n\nimport semantics.*\nimport semantics.Elaborator.{State, Ctx, ctx}\n\nimport syntax.{Keyword, Literal, Tree}\n\n// it should be possible to cache some common constructions (End, Option) into the context\n// this avoids having to rebuild the same shapes everytime they are needed\n\n// transform Block to Block IR so that it can be instrumented in mlscript\nclass ReflectionInstrumenter(using State, Raise, Ctx) extends BlockTransformer(new SymbolSubst()):\n  // recover `defn` for when `sym.defn` is `None`, when the definition was generated by other compiler passes\n  val defnMap = HashMap[Symbol, ClsLikeDefn]()\n\n  type ArgWrappable = Path | Symbol\n  type Context = HashMap[Path, Path]\n  // TODO: there could be a fresh scope per function body, instead of a single one for the entire program\n  val scope = Scope.empty(Scope.Cfg.default)\n\n  def asArg(x: ArgWrappable): Arg = x match\n    case p: Path => p.asArg\n    case l: Symbol => l.asPath.asArg\n\n  // null and undefined are missing\n  def toValue(lit: Str | Int | BigDecimal | Bool): Value =\n    val l = lit match\n      case i: Int => Tree.IntLit(i)\n      case b: Bool => Tree.BoolLit(b)\n      case s: Str => Tree.StrLit(s)\n      case n: BigDecimal => Tree.DecLit(n)\n    Value.Lit(l)\n\n  extension [A, B](ls: Ls[(A => B) => B])\n    def collectApply(f: Ls[A] => B): B =\n      // defer applying k while prepending new elements to the list\n      ls.foldRight((_: Ls[A] => B)(Nil))((headCont, tailCont) =>\n        k =>\n          headCont: head =>\n            tailCont: tail =>\n              k(head :: tail)\n      )(f)\n\n  // helpers for constructing Block\n\n  def assign(res: Result, symName: Str = \"tmp\")(k: Path => Block): Block =\n    // TODO: skip assignment if res: Path?\n    val sym = new TempSymbol(N, symName)\n    Scoped(Set(sym), Assign(sym, res, k(sym.asPath)))\n\n  def tuple(elems: Ls[ArgWrappable], symName: Str = \"tmp\")(k: Path => Block): Block =\n    assign(Tuple(false, elems.map(asArg)), symName)(k)\n\n  // isMlsFun is probably always true?\n  def call(fun: Path, args: Ls[ArgWrappable], isMlsFun: Bool = true, symName: Str = \"tmp\")(k: Path => Block): Block =\n    assign(Call(fun, args.map(asArg) ne_:: Nil)(isMlsFun, false, false), symName)(k)\n\n  // helpers for instrumenting Block\n\n  def blockMod(name: Str) = summon[State].blockSymbol.asPath.selSN(name)\n  def optionMod(name: Str) = summon[State].optionSymbol.asPath.selSN(name)\n\n  def blockCtor(name: Str, args: Ls[ArgWrappable], symName: Str = \"tmp\")(k: Path => Block): Block =\n    call(blockMod(name), args, true, symName)(k)\n  def optionSome(arg: ArgWrappable, symName: Str = \"tmp\")(k: Path => Block): Block =\n    call(optionMod(\"Some\"), Ls(arg), true, symName)(k)\n  def optionNone(symName: Str = \"tmp\")(k: Path => Block): Block =\n    assign(optionMod(\"None\"), symName)(k)\n\n  def blockCall(name: Str, args: Ls[ArgWrappable], symName: Str = \"tmp\")(k: Path => Block): Block =\n    call(blockMod(name), args, symName = symName)(k)\n\n  // linking functions defined in MLscipt\n\n  def fnPrintCode(p: Path)(k: Block): Block =\n    // discard result, we only care about side effect\n    blockCall(\"printCode\", Ls(p))(_ => k)\n\n  def fnConcat(p1: Path, p2: Path, symName: String = \"concat\")(k: Path => Block): Block =\n    blockCall(\"concat\", Ls(p1, p2), symName)(k)\n\n  // transformation helpers\n\n  // if sym is ClassSymbol, we may need pOpt to link to the path pointing to the value of the symbol\n  def transformSymbol(sym: Symbol, pOpt: Option[Path] = N, symName: Str = \"sym\")(k: Path => Block): Block = sym match\n    case t: TermSymbol if t.defn.exists(_.sym.asClsOrMod.isDefined) =>\n      transformSymbol(t.defn.get.sym.asClsOrMod.get, pOpt, symName)(k)\n    // retain names to built-in functions or function definitions\n    case t: TermSymbol if t.defn.exists(_.k == syntax.Fun) =>\n      blockCtor(\"Symbol\", Ls(toValue(sym.nme)), symName)(k)\n    case clsSym: ClassSymbol if ctx.builtins.virtualClasses(clsSym) =>\n      blockCtor(\"VirtualClassSymbol\", Ls(toValue(sym.nme)), symName)(k)\n    case baseSym: BaseTypeSymbol =>\n      val name = scope.allocateOrGetName(sym)\n      val (owner, bsym, paramsOpt, auxParams) = (baseSym.defn, defnMap.get(baseSym)) match\n        case (S(defn), _) => (defn.owner, defn.bsym, defn.paramsOpt, defn.auxParams)\n        case (_, S(defn: ClsLikeDefn)) => (defn.owner, defn.sym, defn.paramsOpt, defn.auxParams)\n        // FIXME: hack to patch in staging for returning the object Unit.\n        case _ if baseSym == State.unitSymbol => (N, baseSym, N, Nil)\n        case _ =>\n          raise(ErrorReport(msg\"Unable to infer parameters from symbol in staged module, which are necessary to reconstruct class instances: ${sym.toString()}\" -> sym.toLoc :: Nil))\n          return End()\n\n      val path: ArgWrappable = pOpt.getOrElse(owner match\n        case S(owner) => owner.asPath.selSN(sym.nme)\n        case N => bsym)\n      baseSym match\n        case _: ClassSymbol =>\n          transformParamsOpt(paramsOpt): paramsOpt =>\n            auxParams.map(ps => transformParamList(ps)).collectApply: auxParams =>\n              tuple(auxParams): auxParams =>\n                blockCtor(\"ConcreteClassSymbol\", Ls(toValue(name), path, paramsOpt, auxParams), symName)(k)\n        case _: ModuleOrObjectSymbol =>\n          blockCtor(\"ModuleSymbol\", Ls(toValue(name), path), symName)(k)\n    case _: NoSymbol =>\n      blockCtor(\"NoSymbol\", Nil, symName)(k)\n    case _: TempSymbol | _: VarSymbol =>\n      val name = scope.allocateOrGetName(sym)\n      blockCtor(\"Symbol\", Ls(toValue(name)), symName)(k)\n    // preserve names to builtin symbols\n    case _: BuiltinSymbol =>\n      blockCtor(\"Symbol\", Ls(toValue(sym.nme)), symName)(k)\n    // FIXME: there may be more types of symbols that need to be renamed during staging\n    case _ =>\n      blockCtor(\"Symbol\", Ls(toValue(sym.nme)), symName)(k)\n\n  def transformOption[A](xOpt: Opt[A], f: A => (Path => Block) => Block)(k: Path => Block): Block = xOpt match\n    case S(x) => f(x)(optionSome(_)(k))\n    case N => optionNone()(k)\n\n  // instrumentation rules\n\n  def ruleEnd(symName: String = \"end\")(k: Path => Block): Block =\n    blockCtor(\"End\", Ls(), symName)(k)\n\n  def ruleBranches(x: Path, p: Path, arms: Ls[Case -> Block], dflt: Opt[Block], symName: String = \"branches\")(using Context)(k: (Path, Context) => Block): Block =\n    def applyRuleBranch(cse: Case, block: Block)(f: Path => Context => Block)(ctx: Context): Block =\n      transformCase(cse): cse =>\n        transformBlock(block)(using ctx.clone() += p -> x): (y, ctx) =>\n          blockCtor(\"Arm\", Ls(cse, y)): cde =>\n            f(cde)(ctx.clone() -= p)\n\n    (arms.map(applyRuleBranch).collectApply(_: Ls[Path] => Context => Block)(summon)): arms =>\n      ctx =>\n        tuple(arms): arms =>\n          ruleEnd(): e =>\n            // TODO: use transformOption here\n            def dfltStaged(k: (Path, Context) => Block) =\n              dflt match\n                case S(dflt) =>\n                  transformBlock(dflt)(using ctx.clone() += p -> x): (dflt, ctx) =>\n                    optionSome(dflt)(k(_, ctx.clone() -= p))\n                case N => optionNone()(k(_, ctx))\n            dfltStaged: (dflt, ctx) =>\n              blockCtor(\"Match\", Ls(x, arms, dflt, e), symName)(k(_, ctx))\n\n  // transformations of Block\n\n  def transformPath(p: Path)(using ctx: Context)(k: Path => Block): Block =\n    // rulePath\n    ctx.get(p).map(k).getOrElse:\n      p match\n        case Value.Ref(l, disamb) =>\n          transformSymbol(disamb.getOrElse(l)): sym =>\n            blockCtor(\"ValueRef\", Ls(sym), \"var\")(k)\n        case l: Value.Lit =>\n          blockCtor(\"ValueLit\", Ls(l), \"lit\")(k)\n        case s @ Select(p, Tree.Ident(name)) =>\n          transformPath(p): x =>\n            val sym = s.symbol.map(transformSymbol(_, S(s)))\n              .getOrElse(blockCtor(\"Symbol\", Ls(toValue(name))))\n            sym: sym =>\n              blockCtor(\"Select\", Ls(x, sym), \"sel\")(k)\n        case DynSelect(qual, fld, arrayIdx) =>\n          transformPath(qual): x =>\n            transformPath(fld): y =>\n              blockCtor(\"DynSelect\", Ls(x, y, toValue(arrayIdx)), \"dynsel\")(k)\n        case _: Value.This =>\n          raise(ErrorReport(msg\"Value.This not supported in staged module.\" -> p.toLoc :: Nil))\n          End()\n\n  def transformResult(r: Result)(using Context)(k: Path => Block): Block = r match\n    case p: Path => transformPath(p)(k)\n    case Tuple(mut, elems) =>\n      assert(!mut, \"mutable tuple not supported\")\n      transformArgs(elems): xs =>\n        tuple(xs.map(_._1)): codes =>\n          blockCtor(\"Tuple\", Ls(codes), \"tup\")(k)\n    case Instantiate(mut, cls, argss) =>\n      assert(!mut, \"mutable instantiation not supported\")\n      argss match\n        case Nil =>\n          raise(ErrorReport(msg\"Instantiate with no argument lists not supported in staged module.\" -> r.toLoc :: Nil))\n          End()\n        case args :: Nil =>\n          transformArgs(args): xs =>\n            transformPath(cls): cls =>\n              tuple(xs.map(_._1)): codes =>\n                blockCtor(\"Instantiate\", Ls(cls, codes), \"inst\")(k)\n        case args :: restArgss =>\n          raise(ErrorReport(msg\"Instantiate with multiple argument lists not supported in staged module.\" -> r.toLoc :: Nil))\n          End()\n    // desugar Runtime.Tuple.get into Select\n    case Call(fun, Ls(Arg(_, scrut), Arg(_, Value.Lit(Tree.IntLit(idx)))) :: _) if fun == State.runtimeSymbol.asPath.selSN(\"Tuple\").selSN(\"get\") =>\n      transformPath(Select(scrut, Tree.Ident(idx.toString()))(N))(k)\n    case Call(fun, argss) =>\n      val stagedFunPath = fun match\n        case s @ Select(qual, Tree.Ident(name)) => s.symbol.flatMap({\n            case t: TermSymbol => t.owner.flatMap({ case sym: DefinitionSymbol[?] =>\n                sym.defn.flatMap(_.hasStagedModifier.map(_ =>\n                  Select(qual, Tree.Ident(name + \"_gen\"))(N)\n                ))\n              })\n            case _ => N\n          })\n        case _ => N\n\n      argss match\n        case args :: Nil =>\n          val newFun = stagedFunPath.getOrElse(fun)\n          transformPath(newFun): fun =>\n            transformArgs(args): args =>\n              tuple(args.map(_._1)): tup =>\n                blockCtor(\"Call\", Ls(fun, tup), \"app\")(k)\n        case args :: restArgss =>\n          raise(ErrorReport(msg\"Call with multiple argument lists not supported in staged module.\" -> r.toLoc :: Nil))\n          End()\n    case _ =>\n      raise(ErrorReport(msg\"Other Results not supported in staged module: ${r.getClass.toString()}\" -> r.toLoc :: Nil))\n      End()\n\n  def transformArg(a: Arg)(using Context)(k: ((Path, Bool)) => Block): Block =\n    val Arg(spread, value) = a\n    if spread.isDefined then\n      raise(ErrorReport(msg\"Spread parameters are not supported in staged module: ${a.toString()}\" -> N :: Nil))\n      End()\n    else\n      transformPath(value): value =>\n        blockCtor(\"Arg\", Ls(value)): cde =>\n          k(cde, spread.isDefined)\n\n  def transformArgs(args: Ls[Arg])(using Context)(k: Ls[(Path, Bool)] => Block): Block =\n    args.map(transformArg).collectApply(k)\n\n  def transformParamList(ps: ParamList)(k: Path => Block) =\n    ps.params.map(p => transformSymbol(p.sym)).collectApply(tuple(_)(k))\n\n  def transformParamsOpt(pOpt: Opt[ParamList])(k: Path => Block) =\n    transformOption(pOpt, transformParamList)(k)\n\n  def transformCase(cse: Case)(using Context)(k: Path => Block): Block = cse match\n    case Case.Lit(lit) => blockCtor(\"Lit\", Ls(Value.Lit(lit)))(k)\n    case Case.Cls(cls, path) =>\n      transformSymbol(cls): cls =>\n        transformPath(path): path =>\n          blockCtor(\"Cls\", Ls(cls, path))(k)\n    case Case.Tup(len, true) =>\n      raise(ErrorReport(msg\"Spread parameters are not supported in staged module: ${cse.toString()}\" -> N :: Nil))\n      End()\n    case Case.Tup(len, false) =>\n      blockCtor(\"Tup\", Ls(toValue(len)))(k)\n    case Case.Field(name, safe) =>\n      raise(ErrorReport(msg\"Case.Field not supported in staged module.\" -> name.toLoc :: Nil))\n      End()\n\n  def transformBlock(b: Block)(using Context)(k: Path => Block): Block =\n    transformBlock(b)((p, _) => k(p))\n\n  def transformBlock(b: Block)(using ctx: Context)(k: (Path, Context) => Block): Block = b match\n    case Return(res, implct) =>\n      transformResult(res): x =>\n        blockCtor(\"Return\", Ls(x, toValue(implct)), \"return\")(k(_, ctx))\n    case Assign(x, r, b) =>\n      transformResult(r): y =>\n        transformSymbol(x): xSym =>\n          blockCtor(\"ValueRef\", Ls(xSym)): xStaged =>\n            (Assign(x, xStaged, _)):\n              given Context = ctx.clone() += x.asPath -> xStaged\n              transformBlock(b): (z, ctx) =>\n                blockCtor(\"Assign\", Ls(xSym, y, z), \"assign\")(k(_, ctx))\n    case Define(cls: ClsLikeDefn, rest) =>\n      assert(cls.companion.isEmpty, \"nested module not supported\")\n      transformBlock(rest): p =>\n        transformSymbol(cls.isym): c =>\n          // staging the methods within the module\n          cls.methods.map(transformFunDefn).collectApply: methods =>\n            tuple(methods): methods =>\n              optionNone(): none => // TODO: handle companion object\n                blockCtor(\"ClsLikeDefn\", Ls(c, methods, none)): cls =>\n                  blockCtor(\"Define\", Ls(cls, p))(k(_, ctx))\n    case Define(v: ValDefn, rest) =>\n      // TODO: only allow ValDefn inside ctors\n      transformBlock(rest): p =>\n        transformOption(v.tsym.owner, transformSymbol(_)): owner =>\n          transformSymbol(v.sym): sym =>\n            transformPath(v.rhs): rhs =>\n              blockCtor(\"ValDefn\", Ls(owner, sym, rhs)): v =>\n                blockCtor(\"Define\", Ls(v, p))(k(_, ctx))\n    case End(_) => ruleEnd()(k(_, ctx))\n    case Match(p, ks, dflt, rest) =>\n      transformPath(p): x =>\n        ruleBranches(x, p, ks, dflt): (stagedMatch, ctx) =>\n          transformBlock(rest)(using ctx): (z, ctx) =>\n            fnConcat(stagedMatch, z, \"match\")(k(_, ctx))\n    case Begin(sub, rest) =>\n      // TODO: This is untested as there is no test case that generates the Begin block yet\n      transformBlock(sub): (sub, ctx) =>\n        transformBlock(rest)(using ctx): (rest, ctx) =>\n          fnConcat(sub, rest)(k(_, ctx))\n    case Scoped(syms, body) =>\n      syms.toList.sortBy(_.uid).map(transformSymbol(_)).collectApply: symsStaged =>\n        tuple(symsStaged): tup =>\n          transformBlock(body): (body, ctx) =>\n            blockCtor(\"Scoped\", Ls(tup, body))(b => Scoped(syms, k(b, ctx)))\n    case Define(_: FunDefn, _) =>\n      raise(ErrorReport(msg\"Nested function definitions are not supported in staged modules. Try enabling :ftc.\" -> N :: Nil))\n      End()\n    case _: Label | _: Break =>\n      raise(ErrorReport(msg\"Other Blocks not supported in staged module: ${b.getClass.toString()}.\" -> N :: Nil))\n      End()\n    case _ =>\n      raise(ErrorReport(msg\"Other Blocks not supported in staged module: ${b.getClass.toString()}\" -> N :: Nil))\n      End()\n\n  def transformFunDefn(f: FunDefn)(using Context)(k: Path => Block): Block =\n    transformBlock(f.body): body =>\n      if f.params.length != 1 then\n        raise(ErrorReport(msg\":ftc must be enabled to desugar functions with multiple parameter lists.\" -> f.sym.toLoc :: Nil))\n      // maintain parameter names in instrumented code\n      f.params.map(\n        _.params.map(p => blockCtor(\"Symbol\", Ls(toValue(p.sym.nme)))).collectApply\n      ).collectApply: paramListSyms =>\n        blockCtor(\"Symbol\", Ls(toValue(f.sym.nme))): sym =>\n          paramListSyms.map(tuple(_)).collectApply: tups =>\n            tuple(tups): tup =>\n              blockCtor(\"FunDefn\", Ls(sym, tup, body, toValue(true)))(k)\n\n  def applyFunDefnInner(f: FunDefn): (FunDefn, Block => Block) =\n    val genSymName = f.sym.nme + \"_instr\"\n    val genSym = BlockMemberSymbol(genSymName, Nil, false)\n    val sym = f.owner.get.asPath.selSN(genSymName)\n\n    // turn into fundefn\n    val dSym = TermSymbol(f.dSym.k, f.dSym.owner, Tree.Ident(f.sym.nme + \"_instr\"))\n    val argSyms = f.params.flatMap(_.params).map(_.sym)\n    val newBody = Scoped(Set(argSyms*), transformFunDefn(f)(using new HashMap)(Return(_, false)))\n\n    // TODO: remove it. only for test\n    val debug = (k: Block) => call(sym, Nil)(fnPrintCode(_)(k))\n    val newFun = f.copy(sym = genSym, dSym = dSym, params = Ls(PlainParamList(Nil)), body = newBody)(f.configOverride, f.annotations)\n    (newFun, debug)\n\n  override def applyBlock(b: Block): Block = super.applyBlock(b) match\n    // find modules with staged annotation\n    case Define(c: ClsLikeDefn, rest) if c.companion.exists(_.isStaged) =>\n      val sym = c.sym.subst\n      val companion = c.companion.get\n      val (stagedMethods, debugPrintCode) = companion.methods\n        .map(applyFunDefnInner)\n        .unzip\n      val ctor = FunDefn.withFreshSymbol(S(companion.isym), BlockMemberSymbol(\"ctor$\", Nil), Ls(PlainParamList(Nil)), companion.ctor)(N, Nil)\n      val (stagedCtor, ctorPrint) = applyFunDefnInner(ctor)\n\n      val unit = State.runtimeSymbol.asPath.selSN(\"Unit\")\n      val debugBlock = (ctorPrint :: debugPrintCode).foldRight((Return(unit, true): Block))(_(_))\n      def debugCont(rest: Block) =\n        Begin(debugBlock, rest)\n      // add generator functions for classes within the constructor\n      val genCls = new BlockTransformer(SymbolSubst.Id):\n        override def applyBlock(b: Block): Block = super.applyBlock(b) match\n          case Define(c: ClsLikeDefn, rest) if c.companion.isEmpty =>\n            val (stagedMethods, debugPrintCode) = c.methods\n              .map(applyFunDefnInner)\n              .unzip\n            val newModule = c.copy(methods = c.methods ++ stagedMethods)(c.configOverride, c.annotations.filter:\n              case Annot.Modifier(Keyword.`staged`) => false\n              case _ => true)\n            Define(newModule, rest)\n          case b => b\n      val newCtor = genCls.applyBlock(companion.ctor)\n      val newCompanion = companion.copy(\n        methods = stagedCtor :: companion.methods ++ stagedMethods,\n        ctor = Begin(newCtor, debugCont(End())),\n      )\n      val newModule = c.copy(sym = sym, companion = S(newCompanion))(c.configOverride, c.annotations.filter:\n        case Annot.Modifier(Keyword.`staged`) => false\n        case _ => true)\n      Define(newModule, rest)\n    case b => b\n\n  def mkDefnMap(b: Block): Unit =\n    val transformer = new BlockTraverser:\n      override def applyDefn(defn: Defn) = defn match\n        case c: ClsLikeDefn =>\n          defnMap.addOne(c.isym, c)\n          super.applyDefn(defn)\n        case _ => super.applyDefn(defn)\n    transformer.applyBlock(b)\n\n  def apply(b: Block) =\n    mkDefnMap(b)\n    applyBlock(b)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/ScopeData.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.codegen.*\nimport hkmc2.semantics.*\nimport hkmc2.ScopeData.*\nimport hkmc2.semantics.Elaborator.State\n\nimport hkmc2.syntax.Tree\nimport hkmc2.codegen.llir.FreshInt\nimport java.util.IdentityHashMap\nimport scala.collection.mutable.Map as MutMap\nimport scala.collection.mutable.Set as MutSet\n\nobject ScopeData:\n  opaque type ScopeUID = Int\n  class FreshUID:\n    private val underlying = FreshInt()\n    def make: ScopeUID = underlying.make\n  \n  class ScopeFinder(fresh: FreshUID, ignoredClasses: Set[DefinitionSymbol[?] & InnerSymbol]) extends BlockTraverserShallow:\n    var objs: List[ScopedObject] = Nil\n    override def applyBlock(b: Block): Unit = b match\n      case s: Scoped =>\n        val id = fresh.make\n        objs ::= ScopedObject.ScopedBlock(id, s)\n      case l: Label if l.loop =>\n        objs ::= ScopedObject.Loop(l.label, l.body)\n        applySubBlock(l.rest)\n      case _ => super.applyBlock(b)\n    override def applyFunDefn(fun: FunDefn): Unit =\n      objs ::= ScopedObject.Func(fun, N)\n    override def applyDefn(defn: Defn): Unit = defn match\n      case f: FunDefn => applyFunDefn(f)\n      case c: ClsLikeDefn =>\n        if !ignoredClasses.contains(c.isym) then\n          objs ::= ScopedObject.Class(c, c.k === syntax.Obj)\n          c.ctorSym match\n            case Some(value) => objs ::= ScopedObject.ClassCtor(c)\n            case None => ()\n          c.companion.map: comp =>\n            objs ::= ScopedObject.Companion(comp, c)\n        \n      case _ => super.applyDefn(defn)\n  type ScopedInfo = DefinitionSymbol[?] | LabelSymbol | ScopeUID | Unit\n\n  given Ordering[ScopedInfo] with\n    def compare(x: ScopedInfo, y: ScopedInfo): Int = (x, y) match\n      case (a: Symbol, b: Symbol) => Ordering[Uid[Symbol]].compare(a.uid, b.uid)\n      case (_: Symbol, _) => -1\n      case (_, _: Symbol) => 1\n      case ((), ()) => 0\n      case ((), _) => -1\n      case (_, ()) => 1\n      case (a: Int, b: Int) => a compare b // ScopeUID is Int inside ScopeData\n\n  // ScopeData requires the set of ignored scopes to compute certain things, but\n  // the lifter requires the scope tree to generate the metadata. To solve this,\n  // we generate the scope tree then populate the metadata later.\n  case class IgnoredScopes(var ignored: Opt[Set[ScopedInfo]])\n  \n  type ScopedObject = ScopedObject.ScopedObject[?]\n  type TScopedObject[T] = ScopedObject.ScopedObject[T]\n  \n  type LiftedSym = DefinitionSymbol[?]\n  \n  extension (d: DefinitionSymbol[?])\n    def asBmsRef = Value.Ref(d.asBlkMember.get, S(d))\n  \n  enum MethodKind:\n    case ClsMethod\n    case ObjMethod\n    case ModMethod\n  \n  // These cannot be hashed\n  object ScopedObject:\n    // T: The actual contents of the scoped object\n    sealed abstract class ScopedObject[T]:\n      var node: Opt[TScopeNode[T]] = N\n      lazy val toInfo: ScopedInfo = this match\n        case Top(_) => ()\n        case Class(cls, _) => cls.isym\n        case Companion(clsBody, compDefn) => clsBody.isym\n        case ClassCtor(cls) => cls.ctorSym.get\n        case Func(fun, _) => fun.dSym\n        case ScopedBlock(uid, block) => uid\n        case Loop(sym, _) => sym\n      \n      // note: not unique\n      lazy val nme = this match\n        case Top(b) => \"top\"\n        case Class(cls, _) => cls.isym.nme\n        case Companion(clsBody, compDefn) => clsBody.isym.nme + \"_mod\"\n        case ClassCtor(cls) => cls.isym.nme // should be unused\n        case Func(fun, isMethod) => fun.dSym.nme\n        case Loop(sym, block) => \"loop$\" + sym.uid.toString()\n        case ScopedBlock(uid, block) => \"scope\" + uid\n      \n      // Locals defined by a scoped object.\n      lazy val definedLocals: Set[Local] = this match\n        // we want definedLocals for the top level scope to be empty, because otherwise,\n        // the lifter may try to capture those locals.\n        case Top(b) => Set.empty\n        case Class(cls, _) =>\n          // Public fields are not included, as they are accessed using\n          // a field selection rather than directly using the BlockMemberSymbol.\n          val paramsSet: Set[Local] = cls.paramsOpt match\n            case Some(value) => value.params.map(_.sym).toSet\n            case None => Set.empty\n          val auxSet: Set[Local] = cls.auxParams.flatMap: p =>\n              p.params.map(_.sym)\n            .toSet\n          paramsSet ++ auxSet ++ cls.privateFields + cls.isym\n        case Companion(clsBody, compDefn) =>\n          clsBody.privateFields.toSet + clsBody.isym\n        case _: ClassCtor => Set.empty\n        case Func(fun, _) => fun.params.flatMap: p =>\n            p.restParam.map(_.sym) ++ p.params.map(_.sym)\n          .toSet\n        case ScopedBlock(_, block) => block.syms.toSet\n        case _: Loop => Set.empty\n    \n      def contents: T = this match\n        case Top(b) => b\n        case Class(cls, _) => cls\n        case Companion(clsBody, compDefn) => clsBody\n        case ClassCtor(cls) => ()\n        case Func(fun, _) => fun\n        case ScopedBlock(_, block) => block\n        case Loop(_, blk) => blk\n    \n    // Scoped nodes which may be referenced using a symbol.\n    sealed abstract class Referencable[T] extends TScopedObject[T]:\n      def sym: LiftedSym = this match\n        case Class(cls, _) => cls.isym\n        case Companion(clsBody, compDefn) => clsBody.isym\n        case Func(fun, isMethod) => fun.dSym\n        case ClassCtor(cls) => cls.ctorSym.get\n      def bsym: BlockMemberSymbol = this match\n        case Class(cls, _) => cls.sym\n        case Companion(clsBody, compDefn) => compDefn.sym\n        case Func(fun, isMethod) => fun.sym\n        case ClassCtor(cls) => cls.sym\n      def owner: Opt[InnerSymbol] = this match\n        case Class(cls, _) => cls.owner\n        case Companion(clsBody, compDefn) => compDefn.owner\n        case ClassCtor(cls) => cls.owner\n        case Func(fun, isMethod) => fun.owner\n      \n    \n    // Scoped nodes which could possibly be lifted to the top level.\n    sealed abstract class Liftable[T <: Defn] extends Referencable[T]:\n      val defn: T\n    \n    // The top-level scope.\n    case class Top(b: Block) extends ScopedObject[Block] // b may be a scoped block, in which case, its variables represent the top-level variables.\n    case class Class(cls: ClsLikeDefn, isObj: Bool) extends Liftable[ClsLikeDefn]:\n      val defn = cls\n    case class Companion(clsBody: ClsLikeBody, compDefn: ClsLikeDefn) extends Referencable[ClsLikeBody]\n    // We model it like this: the ctor is just another function in the same scope as the class and initializes the corresponding class\n    case class ClassCtor(cls: ClsLikeDefn) extends Referencable[Unit]\n    // isMethod:\n    // N = not a method\n    // S(false) = module method\n    // S(true) = class or object method\n    case class Func(fun: FunDefn, isMethod: Opt[MethodKind]) extends Liftable[FunDefn]:\n      val defn = fun\n    // The purpose of `Loop` is to enforce the rule that the control flow remains linear when we enter\n    // a scoped block.\n    case class Loop(sym: LabelSymbol, body: Block) extends ScopedObject[Block]\n    case class ScopedBlock(uid: ScopeUID, block: Scoped) extends ScopedObject[Block]\n  \n  extension (traverser: BlockTraverser)\n    def applyScopedObject(obj: ScopedObject) = \n      extension (s: Symbol) def traverse =\n        traverser.applySymbol(s)\n      obj match\n      case ScopedObject.Top(b) => traverser.applyBlock(b)\n      case ScopedObject.Class(ClsLikeDefn(own, isym, sym, ctorSym, k, paramsOpt, auxParams, parentPath, methods,\n          privateFields, publicFields, preCtor, ctor, mod, bufferable), _)\n      =>\n        // do not traverse the companion -- it is a separate kind of scoped object\n        // and will therefore be traversed separately\n        own.foreach(_.traverse)\n        isym.traverse\n        sym.traverse\n        ctorSym.foreach(_.traverse)\n        paramsOpt.foreach(traverser.applyParamList)\n        auxParams.foreach(traverser.applyParamList)\n        parentPath.foreach(traverser.applyPath)\n        methods.foreach(traverser.applyFunDefn)\n        privateFields.foreach(_.traverse)\n        publicFields.foreach: f =>\n          f._1.traverse; f._2.traverse\n        traverser.applySubBlock(preCtor)\n        traverser.applySubBlock(ctor)\n      case ScopedObject.Companion(comp, cls) => traverser.applyCompanionModule(comp)\n      case ScopedObject.Func(fun, isMethod) => traverser.applyFunDefn(fun)\n      case ScopedObject.ScopedBlock(uid, block) => traverser.applyBlock(block)\n      case ScopedObject.ClassCtor(c) => ()\n      case ScopedObject.Loop(_, b) => traverser.applyBlock(b)\n    \n  // A simple tree data structure representing the nesting relation of definitions and scopes.\n  class NestedScopeTree(val root: TScopeNode[Block]):\n    val nodesMap: Map[ScopedInfo, ScopeNode] = root.allChildNodes.map(n => n.obj.toInfo -> n).toMap\n  \n  type ScopeNode = ScopeNode.ScopeNode[?]\n  type TScopeNode[T] = ScopeNode.ScopeNode[T]\n  object ScopeNode:\n    case class ScopeNode[T](obj: TScopedObject[T], var ancestor: Opt[ScopeNode[?]], children: List[ScopeNode[?]])(using ignoredScopes: IgnoredScopes):\n      \n      lazy val allAncestors: List[ScopeNode[?]] = ancestor match\n        case Some(value) => this :: value.allAncestors\n        case None => this :: Nil\n      \n      lazy val parentsSet = allAncestors.map(_.obj.toInfo).toSet\n      \n      def inSubtree(root: ScopedInfo) = parentsSet.contains(root)\n      \n      // note: includes itself\n      lazy val allChildNodes: List[ScopeNode[?]] = this :: children.flatMap(_.allChildNodes)\n      lazy val allChildren: List[ScopedObject] = allChildNodes.map(_.obj)\n      \n      // does not include variables introduced by itself\n      lazy val existingVars: Set[Local] = ancestor match\n        case Some(value) => value.existingVars ++ value.obj.definedLocals ++ value.nestedModObjSyms\n        case None => Set.empty\n      \n      lazy val inModOrTopLevel: Bool = ancestor match\n        case Some(par) => par.obj match\n          case _: ScopedObject.Companion => true\n          case _: ScopedObject.Top => true\n          case _ => false\n        case None => true\n      \n      // Scoped blocks include the BlockMemberSymbols of their nested definitions. This removes them.\n      lazy val localsWithoutBms: Set[Local] = obj match\n        case s: ScopedObject.ScopedBlock =>\n          val rmv = children.collect:\n            case c @ ScopeNode(obj = s: ScopedObject.Referencable[?]) => s.bsym\n          obj.definedLocals -- rmv\n        case _ => obj.definedLocals\n      \n      lazy val nestedModObjSyms: Set[InnerSymbol] = children.collect:\n          case ScopeNode(obj = c: ScopedObject.Class) if c.isObj => c.cls.isym\n          case ScopeNode(obj = c: ScopedObject.Companion) => c.clsBody.isym\n        .toSet\n      \n      lazy val liftedObjSyms: Set[InnerSymbol] = children.collect:\n          case n @ ScopeNode(obj = c: ScopedObject.Class) if c.isObj && n.isLifted => c.cls.isym\n        .toSet\n      \n      lazy val inScopeISyms: Set[Local] =\n        val parVals = ancestor match\n          case Some(value) => value.inScopeISyms\n          case None => Set.empty\n        \n        obj match\n        case c: ScopedObject.Class => parVals + c.cls.isym\n        case c: ScopedObject.Companion => parVals + c.clsBody.isym\n        case _ => parVals\n      \n      /**\n        * Partitions the nodes of the scope tree into two lists `as` and `bs`, where:\n        * - `bs` contains the the highest children of the curent node such that `f(b)` is `true` for `b` in `bs`, and\n        * - `as` contains the parents of all nodes in `bs`.\n        * \n        * @param f The predicicate used to partition the tree.\n        * @return The partitioned tree.\n        */\n      def partitionTree(f: ScopeNode[?] => Bool): (List[ScopeNode[?]], List[ScopeNode[?]]) =\n        val (as, bs) = children.foldLeft((List.empty[ScopeNode[?]], List.empty[ScopeNode[?]])):\n          case ((l1, l2), child) =>\n            if f(child) then (l1, child :: l2)\n            else \n              val (l1_, l2_) = child.partitionTree(f)\n              (l1_ ::: l1, l2_ ::: l2)\n        (this :: as, bs)\n      \n      /**\n        * Partitions the nodes of the scope tree into two lists `as` and `bs`, where:\n        * - `bs` contains the the highest children of the curent node such that `f(b.obj)` is `true` for `b` in `bs`, and\n        * - `as` contains the parents of all nodes in `bs`.\n        * \n        * @param f The predicicate used to partition the tree.\n        * @return The partitioned tree.\n        */\n      def partitionTree2(f: ScopedObject => Bool): (List[ScopeNode[?]], List[ScopeNode[?]]) = partitionTree(x => f(x.obj))\n      \n      // All of the following must not be called until ignoredScopes is populated with the relevant data.\n      \n      lazy val isLifted: Bool =\n        def impl: Bool =\n          val ignored = ignoredScopes.ignored match\n            case Some(value) => value\n            case None => lastWords(\"isLifted accessed before the set of ignored scopes was set\")\n          \n          // check if the owner is a module\n          obj match\n            case r: ScopedObject.Referencable[?] => r.owner match\n              case Some(value) => if value.asMod.isDefined then return false\n              case _ => ()\n            case _ => ()\n          \n          ancestor.map(_.obj) match\n          case Some(_: ScopedObject.Companion) => false // there is no need to lift objects nested inside a module\n          case _ =>\n            obj match\n            case _ if ignored.contains(obj.toInfo) => false\n            case _ if inModOrTopLevel => false\n            case ScopedObject.Func(isMethod = S(_)) => false\n            case c: ScopedObject.Class if c.isObj => false\n            case _: ScopedObject.Loop | _: ScopedObject.ClassCtor | _: ScopedObject.ScopedBlock | _: ScopedObject.Companion => false\n            case _ => true\n        impl\n      \n      // Finds the first ancestor that is a lifted object, i.e. a non-ignored definition, or the top level\n      lazy val firstLiftedAncestor: ScopedObject =\n        if !isLifted then\n          ancestor match\n          case Some(value) => value.firstLiftedAncestor\n          case None => obj match\n            case _: ScopedObject.Top => obj\n            case _ => lastWords(\"unreachable\")\n        else obj\n      \n      // When a node is lifted, some neighbouring ignored definitions may become out of scope. This computes\n      // the list of these definitions, and they could be passed to this node as a parameter once lifted.\n      private lazy val reqCaptureObjsImpl: List[ScopedObject.Referencable[?]] = obj match\n        case _: ScopedObject.Top => List.empty\n        case _ =>\n          // All unlifted neighbour nodes ::: ancestor's reqCaptureObjsImpl\n          val initial = ancestor.get.children\n            .filter:\n              case ScopeNode(obj = f: ScopedObject.Func) if f.isMethod.isDefined => false\n              case _ => true\n            .collect:\n              case c @ ScopeNode(obj = t: ScopedObject.Referencable[?]) if !c.isLifted && !inModOrTopLevel && !(t is obj) => t\n          initial ::: ancestor.get.reqCaptureObjsImpl\n      \n      lazy val reqCaptureObjs: List[ScopedObject.Referencable[?]] = obj match\n        case _: ScopedObject.Top => List.empty\n        case _ =>\n          if isLifted then reqCaptureObjsImpl\n          else ancestor.get.reqCaptureObjsImpl\n    \n  \n  def dSymUnapply(data: ScopeData, v: DefinitionSymbol[?] | Option[DefinitionSymbol[?]]) = v match\n    case Some(d) if data.contains(d) => S(d)\n    case d: DefinitionSymbol[?] if data.contains(d) => S(d)\n    case _ => None\n    \nclass ScopeData(b: Block)(using State, IgnoredScopes):\n  import ScopeData.*\n  \n  def contains(s: ScopedInfo) = scopeTree.nodesMap.contains(s)\n  \n  def getNode(x: ScopedInfo): ScopeNode = scopeTree.nodesMap(x)\n  def getNode(defn: ClsLikeDefn): ScopeNode = getNode(defn.isym)\n  def getNode(companion: ClsLikeBody): ScopeNode = getNode(companion.isym)\n  def getNode(defn: FunDefn): ScopeNode = getNode(defn.dSym)\n  def getUID(blk: Scoped): ScopeUID =\n    if scopedMap.containsKey(blk) then scopedMap.get(blk)\n    else lastWords(\"getUID: key not found\")\n  def getNode(blk: Scoped): ScopeNode = getNode(getUID(blk))\n  // From the input block or definition, traverses until a function, class or new scoped block is found and appends them.\n  \n  // Classes with owners are ignored, as they could be defined within a scoped block within the constructor.\n  // We instead add all these classes when we encounter them.\n  def scopeFinder = new ScopeFinder(fresh, classesWithOwner.keySet)\n  \n  // entry point\n  private val fresh = FreshUID()\n  \n  private val (classesWithOwner, classesMap) =\n    val mp1: MutMap[DefinitionSymbol[?] & InnerSymbol, InnerSymbol] = MutMap.empty\n    val mp2: MutMap[InnerSymbol, ClsLikeDefn] = MutMap.empty\n    new BlockTraverser:\n      applyBlock(b)\n      override def applyDefn(defn: Defn): Unit = defn match\n        case c @ ClsLikeDefn(owner = S(own)) =>\n          mp1.put(c.isym, own)\n          mp2.put(c.isym, c)\n          c.companion.foreach: comp =>\n            mp1.put(comp.isym, own)\n          super.applyDefn(c)\n        case _ => super.applyDefn(defn)\n    (mp1.toMap, mp2.toMap)\n  \n  private val ownersInv: Map[InnerSymbol, List[DefinitionSymbol[?] & InnerSymbol]] = classesWithOwner\n    .toList.groupBy(_._2)\n    .map:\n      case k -> v => k -> v.map(_._1)\n    .toMap\n  \n  val scopeTree = NestedScopeTree(makeScopeTreeRec(ScopedObject.Top(b)))\n  val root = scopeTree.root\n  val allBms = root.allChildren.collect:\n    case s: ScopedObject.Referencable[?] => s.bsym\n  private val scopedMap: IdentityHashMap[Scoped, ScopeUID] = new IdentityHashMap\n  for\n    case ScopeNode(obj = ScopedObject.ScopedBlock(uid, blk)) <- scopeTree.root.allChildNodes\n  do\n    scopedMap.put(blk, uid)\n  \n  def makeScopeTreeRec[T](obj: TScopedObject[T]): TScopeNode[T] =\n    // An annoying thing with class ctors:\n    // Sometimes, nested classes/objects appear inside the top-level scoped block of class/module ctor,\n    // despite being a child of the class, but we want these to be a direct child of the class/module.\n    val finder = scopeFinder\n    obj match\n      case ScopedObject.Top(s: Scoped) => finder.applyBlock(s.body)\n      case ScopedObject.Top(b) => finder.applyBlock(b)\n      case ScopedObject.Class(cls, _) =>\n        finder.applyBlock(cls.preCtor)\n        finder.applyBlock(cls.ctor)\n      case ScopedObject.Companion(comp, cls) =>\n        finder.applyBlock(comp.ctor)\n      case ScopedObject.Func(fun, _) =>\n        finder.applyBlock(fun.body)\n      case ScopedObject.ScopedBlock(_, block) =>\n        finder.applyBlock(block.body)\n      case ScopedObject.ClassCtor(c) => ()\n      case ScopedObject.Loop(_, b) => finder.applyBlock(b)\n    val mtdObjs = obj match\n      case ScopedObject.Class(cls, _) =>\n        val k = if cls.k is syntax.Obj then MethodKind.ObjMethod else MethodKind.ClsMethod\n        cls.methods.map(ScopedObject.Func(_, S(k)))\n      case ScopedObject.Companion(comp, cls) => comp.methods.map(ScopedObject.Func(_, S(MethodKind.ModMethod)))\n      case _ => Nil\n    \n    val isym = obj match\n      case c: ScopedObject.Class => S(c.cls.isym)\n      case c: ScopedObject.Companion => S(c.clsBody.isym)\n      case _ => N\n    val ownedClasses = isym.flatMap(ownersInv.get(_)) match\n      case S(syms) => syms.map(d => classesMap.get(d)).collect:\n        case S(c) => c\n      case N => Nil\n    val ownedClassObjs = ownedClasses.flatMap: c =>\n      var objs: List[ScopedObject] = List.empty\n      objs ::= ScopedObject.Class(c, c.k === syntax.Obj)\n      c.ctorSym match\n        case Some(value) => objs ::= ScopedObject.ClassCtor(c)\n        case None => ()\n      c.companion.map: comp =>\n        objs ::= ScopedObject.Companion(comp, c)\n      objs\n    \n    val children = (ownedClassObjs ::: mtdObjs ::: finder.objs).map(makeScopeTreeRec)\n    val retNode = ScopeNode.ScopeNode(obj, N, children)\n    obj.node = S(retNode)\n    for c <- children do c.ancestor = S(retNode)\n    retNode\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/ScopeFlattener.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport semantics.*\n\n\n/** - For function bodies, fuse all shallowly-nested scopes into one top-level one,\n  *   because certain passes, such as the handler lowering, rely on knowing all the local\n  *   variables of each function.\n  * - Assert the absence of Label(loop = true) blocks,\n  *   because loops should be rewritten to functions first,\n  *   otherwise we cannot fuse scopes correctly.\n  */\nclass ScopeFlattener extends BlockTransformer(new SymbolSubst):\n  override def applyBlock(b: Block): Block = b match\n    case Label(_, loop, _, _) =>\n      assert(!loop, \"loops should be rewritten to functions before scope flattening\")\n      super.applyBlock(b)\n    case _ => super.applyBlock(b)\n  \n  private var scopedSymForCurrentFun: Opt[mutable.Set[Symbol]] = N\n  override def applyFunBodyLikeBlock(b: Block): Block =\n    val prevScopedSymForCurrentFun = scopedSymForCurrentFun\n    val resBlk = b match\n      case Scoped(syms, body) =>\n        val tmp = mutable.Set.from(syms)\n        scopedSymForCurrentFun = S(tmp)\n        val newBody = applySubBlock(body)\n        if (newBody is body) && tmp.sizeCompare(syms) === 0\n        then b\n        else Scoped(tmp, newBody)\n      case _ =>\n        val tmp = mutable.Set.empty[Symbol]\n        scopedSymForCurrentFun = S(tmp)\n        val newBlk = applySubBlock(b)\n        Scoped(tmp, newBlk)\n    scopedSymForCurrentFun = prevScopedSymForCurrentFun\n    resBlk\n  \n  override def applyScopedBlock(b: Block): Block = b match\n    case Scoped(syms, body) =>\n      scopedSymForCurrentFun match\n        case N => super.applyScopedBlock(b)\n        case S(scopedForCurrentFun) =>\n          scopedForCurrentFun.addAll(syms)\n          super.applySubBlock(body)\n    case _ => super.applySubBlock(b)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/SpecializedSwitch.scala",
    "content": "package hkmc2\npackage codegen\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.codegen.*\nimport hkmc2.semantics.*\nimport hkmc2.syntax.{Literal}\nimport scala.annotation.tailrec\n\n/**\n  * Represents a switch case.\n  * @param l The case's literal value.\n  * @param b The case body.\n  */\nenum SwitchCase(val litValue: Literal, val body: Block):\n  /**\n    * A switch case that requires an explicit `break` to be inserted by the codegen.\n    * @param l The case's literal value.\n    * @param b The case body.\n    */\n  case ExplicitBreak(l: Literal, b: Block) extends SwitchCase(l, b)\n  /**\n    * A switch case that is abortive and does not explicitly require a `break`.\n    * @param l The case's literal value.\n    * @param b The case body.\n    */\n  case Abortive(l: Literal, b: Block) extends SwitchCase(l, b)\n  /**\n    * A switch case that falls through to the subsequent case.\n    * @param l The case's literal value.\n    * @param b The case body.\n    * @param next The literal value of the next case.\n    */\n  case Fallthrough(l: Literal, b: Block, next: Literal) extends SwitchCase(l, b)\n\nprivate enum MatchType:\n  case MFallthrough(value: Literal, body: Block, next: Literal)\n  case MAbortive(arms: List[Literal -> Block])\n  case MCases(arms: List[Literal -> Block])\n\n/*\n * We specialize chains of match statements of the following form:\n * \n * M1 M2 ... Mn\n * \n * where each Mi are match statements that match on a common scrutinee `x`, only have literal patterns,\n * and have an empty or no default case, except for Mn. We define three types of such match statements\n * (which are mostly unrelated to switch case types in the enum `SwitchCase`):\n * - MFallthrough(next): Has only one branch, and if the branch executes to completion, then `next` is assigned\n *   to `x`.\n * - MAbortive: All branches are abortive (and thus exits the scope that the match chain is defined in).\n * - MCases: Is not an MFallthrough or an MAbortive (but still matches on `x` and only has literals patterns).\n * \n * For this chain to be specialized, for each adjacent pair Mi and M(i+1), one of the following hold:\n * \n * - Mi = MFallthrough(_, _, v), and the first case of M(i+1) matches v.\n * - Mi = MAbortive.\n * \n * Note that this means Mi = MCases only if i = n.\n * \n * Furthermore, if M(n-1) is an MAbortive, then the last statement may have a non-empty default case and it will be\n * compiled into `default: body`.\n * \n * - MFallthrough is translated into SwitchCase.Fallthrough.\n * - MAbortive is translated into SwitchCase.Abortive.\n * - MCases is translated into a list of SwitchCase.ExplicitBreak.\n */\n\nprivate object PostCondRes:\n  val empty = PostCondRes(false, false, Map.empty)\n\n// isImpure: indicates whether the result was computed for a possibly impure expression. All analysis results\n// that could possibly come before this result must be discarded.\n// isAbortive: indicates whether the result was computed for an abortive block. When merging results from\n// different branches, the results for this must be discarded.\nprivate case class PostCondRes(isImpure: Bool, isAbortive: Bool, varsMap: Map[Local, Literal]):\n  def markImpure = copy(isImpure = true)\n\n// Combines postconditions from different branches.\nprivate def combinePostConds(p1: PostCondRes, p2: PostCondRes) =\n  if p1.isAbortive && p2.isAbortive then\n    PostCondRes(false, false, Map.empty)\n  else if p1.isAbortive then\n    PostCondRes(p2.isImpure, false, p2.varsMap) // We don't care about whether p1 is impure if it is abortive.\n  else if p2.isAbortive then\n    PostCondRes(p1.isImpure, false, p1.varsMap) // Same as above\n  else\n    // If a variable was set to a different value in either branch, or was only set in one branch, do not include\n    // Otherwise, we can combine them\n    val combined = p1.varsMap.collect:\n      case k -> v1 if p2.varsMap.contains(k) && p2.varsMap(k) == v1 => k -> v1\n    PostCondRes(p1.isImpure || p2.isImpure, false, combined)\n\nextension (r: PostCondRes)\n  // For combining postconditions derived in different branches\n  def ++(r2: PostCondRes): PostCondRes = combinePostConds(r, r2)\n  // For combining sequences of postconditions\n  def >=>(r2: PostCondRes): PostCondRes =\n    if r.isAbortive then r\n    else if r2.isImpure then r2\n    else PostCondRes(r.isImpure, r2.isAbortive, r.varsMap ++ r2.varsMap)\n  def +(v: Local -> Literal): PostCondRes = PostCondRes(r.isImpure, r.isAbortive, r.varsMap + v)\n\n// Analyzes postconditions for a block. Namely, determines variables that are\n// definitely set to a certain literal.\n//\n// Note that impure computations will lead to `isImpure` being set to true. This means\n// all analysis *before* the impure computation will be discarded.\n//\n// The intended semantics of this are, assuming the block finishes execution, i.e.\n// it does not break to a label that wraps the block or returns, then the \n// postconditions hold. Otherwise, the results are invalid, which does not matter,\n// because they will be irrelevant in that case anyway.\nprivate object PostCondAnalysisImpl extends CachedAnalysis[Block, PostCondRes]:\n  \n  private def res(lhs: Opt[Local], rhs: Result, rest: Block) =\n    if rhs.isPure then lhs match\n      case Some(lhs) => rhs match\n        case Value.Lit(lit) => PostCondRes(false, false, Map(lhs -> lit)) >=> analyze(rest)\n        case _ => analyze(rest)\n      case None => analyze(rest)\n    else analyze(rest).markImpure\n  \n  override def analyzeUncached(b: Block): PostCondRes = b match\n    case Label(label, loop, body, rest) =>\n      /* We do not traverse into the label body.\n       * If we do, then there are cases like this:\n       * \n       * label l1:\n       *   label l2:\n       *     body\n       *     set x = 1\n       *   end\n       * end\n       * \n       * and it is very difficult to tell whether we should have the postcondition x = 2 in the outer loop,\n       * because `body` could break out of `l1` or `l2`.\n       * \n       * Not traversing into labels also makes `Block.isAbortive` more useful, as we always know that\n       * if a block is abortive, then it aborts out of the \"initial\" block that `analyze` was called on.\n       */\n      val restRes = analyze(rest)\n      restRes.copy(isImpure = restRes.isImpure || analyze(body).isImpure)\n    case Match(scrut, arms, dflt, rest) =>\n      arms.foldLeft(dflt.map(analyze).getOrElse(PostCondRes.empty)):\n        case (acc, (_, blk)) => acc ++ analyze(blk)\n      >=> analyze(rest)\n    case Scoped(syms, body) => analyze(body)\n    case Begin(sub, rest) => analyze(sub) >=> analyze(rest)\n    case TryBlock(sub, finallyDo, rest) => analyze(sub) >=> analyze(finallyDo) >=> analyze(rest)\n    case Assign(lhs, rhs, rest) => res(S(lhs), rhs, rest)\n    case AssignField(path, _, rhs, rest) => res(N, rhs, rest)\n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) => res(N, rhs, rest)\n    case Define(defn, rest) => defn match\n      case v: ValDefn => res(S(v.sym), v.rhs, rest)\n      case c: ClsLikeDefn => analyze(rest).markImpure // TODO: refine for object and module ctors\n      case f: FunDefn => analyze(rest)\n    case b: BlockTail => PostCondRes.empty.copy(isAbortive = b.isAbortive)\n\nprivate object PostCondAnalysis extends CachedAnalysis[Block, Map[Local, Literal]]:\n  override def analyzeUncached(b: Block): Map[Symbol, Literal] = PostCondAnalysisImpl.analyze(b).varsMap\n\n// Matches List[Case.Lit -> Block]\nprivate object LitCases:\n  def unapply(arms: List[Case -> Block]) = arms.foldLeft[Opt[List[Literal -> Block]]](S(Nil)):\n    case (S(acc), Case.Lit(litVal) -> b) => S((litVal -> b) :: acc)\n    case _ => N\n\nprivate case class MatchChain(scrut: Value.Ref, cases: List[MatchType], dflt: Opt[Block], rest: Block)\n\n// Helper that determines whether a default branch is empty\nprivate def isEmptyDflt(dflt: Opt[Block]) = dflt match\n  case S(x) if x.isEmpty => true\n  case N => true\n  case _ => false\n\n// Extracts a valid match chain beginning at a block.\n@tailrec\nprivate def findMatchChainRec(\n  b: Block,\n  scrutRef: Value.Ref,\n  acc: List[MatchType]\n): MatchChain =\n  object TailAssign:\n    def unapply(b: Block) =\n      if b.isAbortive then N\n      else PostCondAnalysis.analyze(b).get(scrutRef.l) match\n        case S(value) => S(value)\n        case N => N\n  \n  \n  // Whether the current match may have a non-empty default case.\n  // It is allowed iff the previous case was a break, or if this is the only case.\n  val isDfltCaseAllowed = acc.headOption match\n    case Some(_: MatchType.MAbortive) => true\n    case None => true\n    case _ => false\n  \n  // This block does not include the match chain\n  inline def fail = MatchChain(scrutRef, acc, N, b)\n  \n  inline def success(res: MatchType, m: Match, dflt: Opt[Block], dfltEmpty: Bool, rest: Block) =\n    if !dfltEmpty then MatchChain(scrutRef, res :: acc, dflt, rest)\n    else findMatchChainRec(rest, scrutRef, res :: acc)\n  \n  inline def join: MatchChain = b match\n    case m: Match =>\n      val dfltEmpty = isEmptyDflt(m.dflt)\n      \n      // Classify the current match statement.\n      m match\n        // MFallthrough\n        case Match(\n          `scrutRef`,                                                 // * The scrutinee is a ref and is the same as the one before.\n          Case.Lit(curVal) -> (b @ TailAssign(nextVal)) :: Nil,       // * There is only one case matching a literal\n                                                                      //   and it assigns the scrut to a literal.\n          default, restBlk\n        ) =>\n          if !isDfltCaseAllowed && !dfltEmpty then fail               // Default branch not allowed\n          else\n            val res = MatchType.MFallthrough(curVal, b, nextVal)\n            success(res, m, m.dflt, dfltEmpty, restBlk)\n        // MAbortive or MCases\n        case Match(`scrutRef`, LitCases(arms), default, restBlk) =>\n          // MAbortive\n          if arms.forall(_._2.isAbortive) then\n            // If both default and restBlk are not End(), and default blocks are not allowed, then fail\n            // Otherwise, take the non-end one as the next block\n            val restEmpty = restBlk.isEmpty\n            val res = MatchType.MAbortive(arms)\n            if !dfltEmpty && !restEmpty then\n              if !isDfltCaseAllowed then fail\n              else success(res, m, m.dflt, dfltEmpty, restBlk)\n            else if restEmpty then\n              success(res, m, N, true, m.dflt.getOrElse(End()))\n            else\n              success(res, m, m.dflt, dfltEmpty, restBlk)\n          // MCases\n          else\n            if !isDfltCaseAllowed && !dfltEmpty then fail                // Default branch not allowed\n            else\n              val res = MatchType.MCases(arms)\n              success(res, m, m.dflt, dfltEmpty, restBlk)\n        case _ => fail\n    case _ => fail\n  \n  // Get the first case's value (in case the previous match is MFallthrough).\n  val curVal = b match\n    case m: Match => m.arms.headOption.collect:\n      case Case.Lit(lit) -> _ => lit\n    case _ => N\n  \n  // Check for the valid cases:\n  // - The previous match is a fallthrough that sets the scrut to curVal.\n  // - The previous match is abortive.\n  acc.headOption match\n    case S(MatchType.MFallthrough(next = expectedVal))\n      if curVal.map(_ == expectedVal).getOrElse(true) =>\n        join // OK\n    case S(_: MatchType.MAbortive) | N => join // OK\n    case S(_) => fail\n\nprivate case class SwitchLike(scrut: Value.Ref, cases: List[SwitchCase], dflt: Opt[Block], rest: Block)\n\n// Converts a match chain to a switch.\nprivate def matchChainToSwitch(m: MatchChain): SwitchLike =\n  def mpArms(arms: List[(Literal, Block)]) = arms.map:\n    case (l, b) =>\n      if b.isAbortive then SwitchCase.Abortive(l, b)\n      else SwitchCase.ExplicitBreak(l, b)\n  val cases = m.cases.flatMap:\n    case MatchType.MFallthrough(value, body, next) =>\n      SwitchCase.Fallthrough(value, body, next) :: Nil\n    case MatchType.MAbortive(arms) => mpArms(arms)\n    case MatchType.MCases(arms) => mpArms(arms)\n  SwitchLike(m.scrut, cases, m.dflt, m.rest)\n\nobject SpecializedSwitch:\n  def unapply(b: Block) = b match\n    case m @ Match(scrut = r @ Value.Ref(l, _)) =>\n      val chain = findMatchChainRec(m, r, Nil)\n      val SwitchLike(scrut, cases, dflt, rest) = matchChainToSwitch(chain)\n      if cases.size < 2 then N\n      else\n        S((scrut, cases.reverse, dflt, rest))\n    case _ => N\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/StackSafeTransform.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.codegen.*\nimport hkmc2.semantics.Elaborator.State\nimport hkmc2.semantics.*\nimport hkmc2.syntax.Tree\nimport hkmc2.codegen.HandlerLowering.FnOrCls\n\nclass StackSafeTransform(depthLimit: Int, paths: HandlerPaths, stackSafetyMap: StackSafetyMap)(using State, Config):\n  private val STACK_DEPTH_IDENT: Tree.Ident = Tree.Ident(\"stackDepth\")\n\n  private val runtimePath: Path = State.runtimeSymbol.asPath\n  private val checkDepthPath: Path = runtimePath.selN(Tree.Ident(\"checkDepth\"))\n  private val runStackSafePath: Path = runtimePath.selN(Tree.Ident(\"runStackSafe\"))\n  private val stackDepthPath: Path = runtimePath.selN(STACK_DEPTH_IDENT)\n\n  private def intLit(n: BigInt) = Value.Lit(Tree.IntLit(n))\n  \n  private def op(op: String, a: Path, b: Path) =\n    Call(State.builtinOpsMap(op).asPath, (a.asArg :: b.asArg :: Nil) ne_:: Nil)(true, false, false)\n\n  // Increases the stack depth, assigns the call to a value, then decreases the stack depth\n  // then binds that value to a desired block\n  def extractRes(res: Result, isTailCall: Bool, f: Result => Block, sym: Symbol, curDepth: => Symbol): Block =\n    if isTailCall then Return(res, false)\n    else\n      blockBuilder\n        .assign(sym, res)\n        .assignFieldN(runtimePath, STACK_DEPTH_IDENT, curDepth.asPath)\n        .rest(f(sym.asPath))\n  \n  def wrapStackSafe(body: Block, resSym: Local, rest: Block) =\n    val bodSym = BlockMemberSymbol(\"‹stack safe body›\", Nil, false)\n    val bodFun = FunDefn.withFreshSymbol(N, bodSym, ParamList(ParamListFlags.empty, Nil, N) :: Nil, body)(configOverride = N, annotations = Nil)\n    Scoped(Set.single(bodSym),\n      Define(bodFun, Assign(resSym, Call(runStackSafePath, (intLit(depthLimit).asArg :: bodSym.asPath.asArg :: Nil) ne_:: Nil)(true, true, false), rest))\n    )\n\n  def extractResTopLevel(res: Result, isTailCall: Bool, f: Result => Block, sym: Symbol, curDepth: => Symbol) =\n    val resSym = sym\n    wrapStackSafe(Ret(res), resSym, f(resSym.asPath))\n\n  // Rewrites anything that can contain a Call to increase the stack depth\n  def transform(b: Block, curDepth: => Symbol, isTopLevel: Bool = false): Block =\n    def usesStack(r: Result) = r match\n      case Call(Value.Ref(_: BuiltinSymbol, _), _) => false\n      case c: Call if !c.mayRaiseEffects => false // a call can only trigger a stack delay if it can raise effects\n      case _: Call | _: Instantiate => true\n      case _ => false\n\n    val extract = if isTopLevel then extractResTopLevel else extractRes\n    \n    val transform = new BlockTransformer(SymbolSubst.Id):\n\n      override def applyFunDefn(fun: FunDefn): FunDefn = rewriteFn(fun)\n      \n      override def applyDefn(defn: Defn)(k: Defn => Block): Block = defn match\n        case defn: ClsLikeDefn => k(rewriteCls(defn, isTopLevel))\n        case _: FunDefn | _: ValDefn => super.applyDefn(defn)(k)\n\n      override def applyBlock(b: Block): Block = b match\n        case Return(res, implct) if usesStack(res) =>\n          val tmp = TempSymbol(N, \"res\")\n          super.applyResult(res): res =>\n            Scoped(Set.single(tmp), extract(res, true, Return(_, implct), tmp, curDepth))\n        // Optimization to avoid generation of unnecessary variables\n        case Assign(lhs, r, rest) =>\n          if usesStack(r) then\n            super.applyResult(r): r =>\n              extract(r, false, _ => applyBlock(rest), lhs, curDepth)\n          else\n            super.applyBlock(b)\n        \n        case _ => super.applyBlock(b)\n        \n      override def applyHandler(hdr: Handler): Handler = lastWords(\"HandleBlock in stack safe transformation\")\n      \n      override def applyResult(r: Result)(k: Result => Block): Block =\n        if usesStack(r) then\n          val tmp = TempSymbol(N, \"res\")\n          Scoped(Set.single(tmp), extract(r, false, k, tmp, curDepth))\n        else\n          super.applyResult(r)(k)\n      \n      override def applyLam(lam: Lambda): Lambda = lastWords(\"Lambda in stack safe transformation\")\n  \n    transform.applyBlock(b)\n  \n  def isTrivial(b: Block): Boolean =\n    var trivial = true\n    new BlockTraverserShallow:\n      applyBlock(b)\n      override def applyResult(r: Result): Unit = r match\n        case Call(Value.Ref(_: BuiltinSymbol, _), _) => ()\n        case _: Call | _: Instantiate => trivial = false\n        case _ => ()\n    trivial\n  \n  def rewriteCls(defn: ClsLikeDefn, isTopLevel: Bool): ClsLikeDefn = defn.parentPath match\n    case Some(value) if value eq paths.contClsPath => defn\n    case _ =>\n      val ClsLikeDefn(owner, isym, sym, ctorSym, k, paramsOpt, auxParams,\n        parentPath, methods, privateFields, publicFields, preCtor, ctor, mod, bufferable) = defn\n      ClsLikeDefn(\n        owner, isym, sym, ctorSym, k, paramsOpt, auxParams, parentPath,\n        methods.map(rewriteFn),\n        privateFields,\n        publicFields, \n        preCtor,\n        ctor,\n        mod.map(rewriteObjBody(_, isTopLevel)),\n        bufferable,\n      )(defn.configOverride, defn.annotations)\n  \n  def rewriteObjBody(defn: ClsLikeBody, isTopLevel: Bool): ClsLikeBody =\n    ClsLikeBody(\n      defn.isym,\n      defn.methods.map(rewriteFn),\n      defn.privateFields,\n      defn.publicFields,\n      if isTopLevel then\n        if config.effectHandlers.exists(_.doNotInstrumentTopLevelModCtor) then defn.ctor else transformTopLevel(defn.ctor)\n      else rewriteBlk(defn.ctor, R(defn.isym)),\n      defn.annotations,\n    )\n\n  // fnOrCls points us to the doUnwind function\n  def rewriteBlk(blk: Block, fnOrCls: FnOrCls) =\n    (stackSafetyMap.get(fnOrCls), isTrivial(blk)) match\n    case (S((increment, doUnwindBlk)), false) =>\n      var usedDepth = false\n      lazy val curDepth =\n        usedDepth = true\n        TempSymbol(None, \"curDepth\")\n      val newBody = transform(blk, curDepth)\n      val resSym = TempSymbol(None, \"stackDelayRes\")\n      val addStackSafeEffect = blk => blockBuilder\n        .assignFieldN(runtimePath, STACK_DEPTH_IDENT, op(\"+\", stackDepthPath, intLit(increment)))\n        .staticif(usedDepth, _.assignScoped(curDepth, stackDepthPath))\n        .assignScoped(resSym, Call(checkDepthPath, Nil ne_:: Nil)(true, true, false))\n        .ifthen(\n          paths.curEffect,\n          Case.Lit(Tree.UnitLit(true)),\n          End(),\n          S(doUnwindBlk)\n        )\n        .rest(blk)\n      addStackSafeEffect(newBody)\n    case _ => blk\n\n\n\n  def rewriteFn(defn: FunDefn) = \n    FunDefn(defn.owner, defn.sym, defn.dSym, defn.params, rewriteBlk(defn.body, L(defn.sym)))(defn.configOverride, defn.annotations)\n\n  def transformTopLevel(b: Block) = transform(b, TempSymbol(N), true)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/SymbolRefresher.scala",
    "content": "package hkmc2\npackage codegen\n\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet, Buffer}\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport semantics.*\nimport semantics.Elaborator.State\n\nclass SymbolRefresher(existingMapping: Map[Symbol, Symbol])(using State) extends BlockTransformer(SymbolSubst.Id):\n  val mapping = MutMap.from(existingMapping)\n  // Stack of cleanup frames, one per scoped block. ClsLikeDefn / applyObjBody add\n  // class-internal symbols to the top frame; the enclosing applyScopedBlock pops\n  // and removes them from `mapping` when its body finishes. Initialized with a\n  // bottom frame so callers that hand us a non-Scoped entry block still have a\n  // valid `cleanupStack.head` to add to (the bottom frame is never popped).\n  private var toRemoveSymbols: List[MutSet[Symbol]] = MutSet.empty[Symbol] :: Nil\n\n  override def applyScopedBlock(b: Block): Block =\n    toRemoveSymbols = MutSet.empty[Symbol] :: toRemoveSymbols\n    val res = b match\n    case Scoped(syms, body) =>\n      val newSyms = MutSet.empty[Symbol]\n      val oldSyms = MutSet.empty[Symbol]\n      for s <- syms.toList.sortBy(_.uid) do\n        assert(!mapping.isDefinedAt(s), s\"already defined: $s\")\n        val newS = s match\n          case tmpSym: TempSymbol => new TempSymbol(N, tmpSym.nme)\n          case bms: BlockMemberSymbol =>\n            val newBms = new BlockMemberSymbol(bms.nme, Nil, bms.nameIsMeaningful)\n            newBms.tsym = bms.tsym.map: t =>\n              val newOwner: Opt[InnerSymbol] = t.owner.map: o =>\n                existingMapping.get(o) match\n                  case Some(inner: InnerSymbol) => inner\n                  case _ => o\n              val nt = new TermSymbol(t.k, newOwner, t.id)\n              mapping(t) = nt\n              oldSyms.add(t)\n              nt\n            newBms\n          case varSym: VarSymbol => new VarSymbol(varSym.id)\n          case _ => lastWords(s\"unexpected symbol kind: $s\")\n        mapping(s) = newS\n        oldSyms.add(s)\n        newSyms.add(newS)\n      val r = Scoped(newSyms, applyBlock(body))\n      for s <- oldSyms do mapping.remove(s)\n      r\n    case _ => super.applyScopedBlock(b)\n    val hd = toRemoveSymbols.head\n    toRemoveSymbols = toRemoveSymbols.tail\n    hd.foreach(mapping.remove)\n    res\n  override def applyBlock(b: Block): Block =\n    b match\n    case Assign(lhs, rhs, rest) =>\n      applyResult(rhs): newRhs =>\n        val newLhs = mapping.getOrElse(lhs, lhs)\n        val newRest = applyBlock(rest)\n        if (newLhs is lhs) && (newRhs is rhs) && (newRest is rest) then b else Assign(newLhs, newRhs, newRest)\n    case Label(label, loop, body, rest) =>\n      assert(!mapping.isDefinedAt(label))\n      val newLabel = new LabelSymbol(label.trm, label.nme)\n      mapping(label) = newLabel\n      val newBody = applyBlock(body)\n      mapping.remove(label)\n      val newRest = applyBlock(rest)\n      Label(newLabel, loop, newBody, newRest)\n    case Break(label) => Break(mapping.getOrElse(label, label).asInstanceOf[LabelSymbol])\n    case Continue(label) => Continue(mapping.getOrElse(label, label).asInstanceOf[LabelSymbol])\n    case _ => super.applyBlock(b)\n  \n  override def applyDefn(defn: Defn)(k: Defn => Block): Block =\n    defn match\n    case fun: FunDefn =>\n      assert(fun.owner.isEmpty)\n      // because fun sym is not treated as a free var, we refresh here\n      var newlyCreated = false\n      val (sym2, dSym2) = mapping.get(fun.sym) match\n        case Some(s: BlockMemberSymbol) => (s, s.tsym.get)\n        case None =>\n          newlyCreated = true\n          val newBms = new BlockMemberSymbol(fun.sym.nme, fun.sym.trees, fun.sym.nameIsMeaningful)\n          val newDsym = fun.sym.tsym.map: tsym =>\n            assert(tsym.owner.isEmpty)\n            new TermSymbol(tsym.k, N, tsym.id)\n          newBms.tsym = S(newDsym.get)\n          mapping(fun.sym) = newBms\n          (newBms, newDsym.get)\n        case _ => die\n      val oldParamSyms = Buffer.empty[VarSymbol]\n      val params2 = fun.params.map:\n        case ParamList(flags, params, restParam) =>\n          def handleSingleParam(p: Param) =\n            val Param(flags, sym, sign, modulefulness) = p\n            oldParamSyms.append(sym)\n            val newSym = new VarSymbol(sym.id)\n            assert(!mapping.isDefinedAt(sym))\n            mapping(sym) = newSym\n            Param(flags, newSym, sign, modulefulness)\n          val params2 = params.map(handleSingleParam)\n          val rest2 = restParam.map(handleSingleParam)\n          ParamList(flags, params2, rest2)\n      val body2 = applyFunBodyLikeBlock(fun.body)\n      for s <- oldParamSyms do mapping.remove(s)\n      if newlyCreated then\n        Scoped(Set.single(sym2), k(FunDefn(N, sym2, dSym2, params2, body2)(fun.configOverride, fun.annotations)))\n      else\n        k(FunDefn(N, sym2, dSym2, params2, body2)(fun.configOverride, fun.annotations))\n    case defn @ ValDefn(tsym, sym, rhs) =>\n      val (tsym2, sym2) = mapping.get(sym) match\n        case None =>\n          val newBms = new BlockMemberSymbol(sym.nme, sym.trees, sym.nameIsMeaningful)\n          val newTsym = new TermSymbol(tsym.k, tsym.owner, tsym.id)\n          newBms.tsym = S(newTsym)\n          (newTsym, newBms)\n        case S(bms: BlockMemberSymbol) =>\n          (bms.tsym.get, bms)\n        case _ => die\n      applyPath(rhs): rhs2 =>\n        k(ValDefn(tsym2, sym2, rhs2)(defn.configOverride, defn.annotations))\n    case defn: ClsLikeDefn =>\n      val hd = toRemoveSymbols.head\n      val oldIsym = defn.isym\n      assert(!mapping.isDefinedAt(oldIsym), s\"isym already in mapping: $oldIsym\")\n      val newIsym: DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol = oldIsym match\n        case c: ClassSymbol => new ClassSymbol(c.tree, c.id)\n        case m: ModuleOrObjectSymbol => new ModuleOrObjectSymbol(m.tree, m.id)\n        case p: PatternSymbol => new PatternSymbol(p.id, p.params, p.body)\n        case _ => lastWords(s\"unexpected isym kind: $oldIsym\")\n      mapping(oldIsym) = newIsym\n      hd += oldIsym\n\n      var newlyCreatedSym = false\n      val newSym: BlockMemberSymbol = mapping.get(defn.sym) match\n        case Some(bms: BlockMemberSymbol) => bms\n        case None =>\n          newlyCreatedSym = true\n          val nb = new BlockMemberSymbol(defn.sym.nme, Nil, defn.sym.nameIsMeaningful)\n          mapping(defn.sym) = nb\n          nb\n        case _ => die\n\n      val newCtorSym: Opt[TermSymbol] = defn.ctorSym.map: cs =>\n        assert(!mapping.isDefinedAt(cs))\n        val ncs = new TermSymbol(cs.k, S(newIsym), cs.id)\n        mapping(cs) = ncs\n        hd += cs\n        ncs\n\n      val newOwn: Opt[InnerSymbol] = defn.owner.map: o =>\n        mapping.get(o) match\n          case Some(inner: InnerSymbol) => inner\n          case _ => o\n\n      def freshenParamList(pl: ParamList): ParamList =\n        def handleParam(p: Param) =\n          val ns = new VarSymbol(p.sym.id)\n          assert(!mapping.isDefinedAt(p.sym))\n          mapping(p.sym) = ns\n          hd += p.sym\n          Param(p.flags, ns, p.sign, p.modulefulness)\n        ParamList(pl.flags, pl.params.map(handleParam), pl.restParam.map(handleParam))\n      val newParamsOpt = defn.paramsOpt.map(freshenParamList)\n      val newAuxParams = defn.auxParams.map(freshenParamList)\n\n      val newPrivateFields = freshenPrivateFields(defn.privateFields, newIsym)\n      val newPublicFields = freshenPublicFields(defn.publicFields, newIsym)\n      val newMethods = freshenMethods(defn.methods, oldIsym, newIsym)\n\n      val newPreCtor = applyFunBodyLikeBlock(defn.preCtor)\n      val newCtor = applyFunBodyLikeBlock(defn.ctor)\n      val newMod = defn.companion.map(applyObjBody)\n\n      def buildResult(newParentPath: Opt[Path]): Block =\n        val newDefn = ClsLikeDefn(newOwn, newIsym, newSym, newCtorSym, defn.k,\n          newParamsOpt, newAuxParams, newParentPath, newMethods,\n          newPrivateFields, newPublicFields, newPreCtor, newCtor, newMod, defn.bufferable)(defn.configOverride, defn.annotations)\n        if newlyCreatedSym then\n          Scoped(Set.single(newSym), k(newDefn))\n        else\n          k(newDefn)\n\n      defn.parentPath match\n        case Some(pp) => applyPath(pp): pp2 =>\n          buildResult(if pp2 is pp then defn.parentPath else Some(pp2))\n        case None => buildResult(None)\n  \n  override def applyPath(p: Path)(k: Path => Block): Block = p match\n    case p @ Select(qual, name) =>\n      applyPath(qual): qual2 =>\n        val sym2 = p.symbol.map: s =>\n          mapping.get(s) match\n            case Some(ds: DefinitionSymbol[?]) => ds\n            case _ => s\n        k(if (qual2 is qual) && (sym2 is p.symbol) then p else Select(qual2, name)(sym2).withLocOf(p))\n    case _ => super.applyPath(p)(k)\n\n  override def applyValue(v: Value)(k: Value => Block): Block = v match\n    case Value.Ref(l, x) =>\n      mapping.get(l) match\n        case None => super.applyValue(v)(k)\n        case Some(newBms: BlockMemberSymbol) =>\n          val newDisamb = x match\n            case Some(oldDisamb) =>\n              mapping.get(oldDisamb) match\n                case Some(nd: DefinitionSymbol[?]) => Some(nd)\n                case _ => newBms.tsym.orElse(x)\n            case None => newBms.tsym\n          k(Value.Ref(newBms, newDisamb))\n        case Some(newSym) => k(Value.Ref(newSym, N))\n    case Value.This(sym) =>\n      mapping.get(sym) match\n        case Some(inner: InnerSymbol) => k(Value.This(inner).withLocOf(v))\n        case _ => super.applyValue(v)(k)\n    case _ => super.applyValue(v)(k)\n  \n  private def freshenPrivateFields(\n    fields: Ls[TermSymbol], ownerIsym: InnerSymbol\n  ): Ls[TermSymbol] = fields.map: ts =>\n    assert(!mapping.isDefinedAt(ts))\n    val nts = new TermSymbol(ts.k, S(ownerIsym), ts.id)\n    mapping(ts) = nts\n    toRemoveSymbols.head += ts\n    nts\n\n  private def freshenPublicFields(\n    fields: Ls[BlockMemberSymbol -> TermSymbol], ownerIsym: InnerSymbol\n  ): Ls[BlockMemberSymbol -> TermSymbol] = fields.map:\n    case (bms, ts) =>\n      assert(!mapping.isDefinedAt(bms))\n      assert(!mapping.isDefinedAt(ts))\n      val nbms = new BlockMemberSymbol(bms.nme, Nil, bms.nameIsMeaningful)\n      val nts = new TermSymbol(ts.k, S(ownerIsym), ts.id)\n      nbms.tsym = S(nts)\n      mapping(bms) = nbms\n      mapping(ts) = nts\n      toRemoveSymbols.head.addAll(Seq(bms, ts))\n      nbms -> nts\n\n  private def freshenMethods(\n    methods: Ls[FunDefn], oldIsym: InnerSymbol, newIsym: InnerSymbol\n  ): Ls[FunDefn] =\n    val methodsAndNewSyms = methods.map: m =>\n      assert(m.owner.contains(oldIsym), s\"method owner mismatch: ${m.owner} vs S($oldIsym)\")\n      assert(!mapping.isDefinedAt(m.sym))\n      assert(!mapping.isDefinedAt(m.dSym))\n      val newMsym = new BlockMemberSymbol(m.sym.nme, Nil, m.sym.nameIsMeaningful)\n      val newDsym = new TermSymbol(m.dSym.k, S(newIsym), m.dSym.id)\n      newMsym.tsym = S(newDsym)\n      mapping(m.sym) = newMsym\n      mapping(m.dSym) = newDsym\n      toRemoveSymbols.head.addAll(Seq(m.sym, m.dSym))\n      (m, newMsym, newDsym)\n    methodsAndNewSyms.map: (m, newMsym, newDsym) =>\n      val methodParamOlds = MutSet.empty[VarSymbol]\n      val newParams = m.params.map: pl =>\n        def handleParam(p: Param) =\n          val ns = new VarSymbol(p.sym.id)\n          assert(!mapping.isDefinedAt(p.sym))\n          mapping(p.sym) = ns\n          methodParamOlds += p.sym\n          Param(p.flags, ns, p.sign, p.modulefulness)\n        ParamList(pl.flags, pl.params.map(handleParam), pl.restParam.map(handleParam))\n      val newBody = applyFunBodyLikeBlock(m.body)\n      methodParamOlds.foreach(mapping.remove)\n      FunDefn(S(newIsym), newMsym, newDsym, newParams, newBody)(m.configOverride, m.annotations)\n  \n  override def applyObjBody(defn: ClsLikeBody): ClsLikeBody =\n    val hd = toRemoveSymbols.head\n    val oldIsym = defn.isym\n    assert(!mapping.isDefinedAt(oldIsym), s\"companion isym already in mapping: $oldIsym\")\n    val newIsym: DefinitionSymbol[? <: ModuleOrObjectDef] & InnerSymbol = oldIsym match\n      case m: ModuleOrObjectSymbol => new ModuleOrObjectSymbol(m.tree, m.id)\n      case _ => lastWords(s\"unexpected companion isym kind: $oldIsym\")\n    mapping(oldIsym) = newIsym\n    hd += oldIsym\n\n    val newPrivateFields = freshenPrivateFields(defn.privateFields, newIsym)\n    val newPublicFields = freshenPublicFields(defn.publicFields, newIsym)\n    val newMethods = freshenMethods(defn.methods, oldIsym, newIsym)\n    val newCtor = applyFunBodyLikeBlock(defn.ctor)\n\n    ClsLikeBody(newIsym, newMethods, newPrivateFields, newPublicFields, newCtor, defn.annotations)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/TailRecOpt.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.codegen.*\nimport hkmc2.semantics.*\nimport hkmc2.Message.*\nimport hkmc2.semantics.Elaborator.State\nimport hkmc2.syntax.{Tree, SpreadKind}\nimport hkmc2.ScopeData.*\nimport hkmc2.Lifter.AccessInfo\nimport scala.collection.mutable.ArrayBuffer\nimport java.lang.instrument.ClassDefinition\n\n/*\n\nDOCUMENTATION OF SEMANTICS OF @tailcall and @tailrec\n\n@tailcall: Used to annotate specific function calls. Calls annotated with @tailcall \nmust be tail calls. These calls must be optimized to not consume additional stack\nspace. If such an optimization is not possible, then the compiler will report an error.\n\n@tailrec: Used to annotate functions. When this annotation is used on a function, say\n`@tailrec fun foo()`, the compiler will ensure no sequence of statically known recursive calls back \nto foo() consumes stack space, i.e. they are all tail calls. For example,\n\n@tailrec \nfun foo() =\n  bar()\n  foo()\n\nfun bar() =\n  bar()\n  bar()\n\nis valid. However,\n\n@tailrec\nfun foo() =\n  bar()\nfun bar() =\n  foo()\n  bar()\n\nis invalid. If we swap the position of foo() and bar() in the body of bar, i.e.\n\n@tailrec\nfun foo() =\n  bar()\nfun bar() =\n  bar()\n  foo()\n\nit is still invalid, since the following sequence of calls from foo to foo would incur extra stack space:\n      foo\n  ->  bar (tail call)\n  ->  bar (not a tail call)\n  ->  foo (tail call)\n\nEquivalently, if fun foo() is annotated with @tailrec, let S be the largest strongly\nconnected component in the call-graph of the program that contains foo. Then an error\nwill be thrown unless all edges (calls) connecting the nodes of the strongly\nconnected component are tail calls.\n\n*/\n\n// This optimization assumes the lifter has been run.\nclass TailRecOpt(using State, TL, Raise):\n  \n  type AccessMap = Map[ScopedInfo, AccessInfo]\n  \n  object CallToFun:\n    def unapply(c: Call): Opt[TermSymbol] = c match\n      case Call(fun = Value.Ref(b, S(r: TermSymbol))) => S(r)\n      case Call(fun = s: Select) => s.symbol match\n        case Some(r: TermSymbol) => S(r)\n        case _ => N\n      case _ => N\n  \n  object TailCallShape:\n    def unapply(b: Block): Opt[(TermSymbol, Call)] = b match\n      case Return(c @ CallToFun(r), _) => S((r, c))\n      case Assign(a, c @ CallToFun(r), Return(Value.Ref(b, _), _)) if a === b => S((r, c))\n      case _ => N\n    \n  \n  enum CallEdge:\n    val f1: TermSymbol\n    val f2: TermSymbol\n    val call: Call\n    case TailCall(f1: TermSymbol, f2: TermSymbol)(val call: Call)\n    case NormalCall(f1: TermSymbol, f2: TermSymbol)(val call: Call)\n  \n  class CallFinder(f: FunDefn)(using data: (ScopeData, AccessMap)) extends BlockTraverserShallow:\n    \n    val scopeData = data._1\n    \n    var edges: List[CallEdge] = Nil\n    \n    def find =\n      edges = Nil\n      applyBlock(f.body)\n      edges\n    \n    def getFun(d: TermSymbol) = \n      if scopeData.contains(d) then\n        scopeData.getNode(d) match\n        case ScopeNode(obj = ScopedObject.Func(f, _)) => S(f)\n        case _ => N\n      else N\n    \n    override def applyBlock(b: Block): Unit = b match\n      case TailCallShape(r, c) => getFun(r) match\n        case Some(value) =>\n          if c.argss.size != value.params.size then\n            if c.explicitTailCall then\n              raise(ErrorReport(msg\"Only fully applied calls may be marked @tailcall.\" -> c.toLoc :: Nil))\n          else edges ::= CallEdge.TailCall(f.dSym, r)(c)\n        case None =>\n          if c.explicitTailCall then\n            raise(ErrorReport(msg\"Only functions in this compilation unit may be marked @tailcall.\" -> c.toLoc :: Nil))\n      case Return(c: Call, _) =>\n        if c.explicitTailCall then\n          raise(ErrorReport(msg\"Only direct calls in tail position may be marked @tailcall.\" -> c.toLoc :: Nil))\n      case _ => super.applyBlock(b)\n    \n    override def applyResult(r: Result): Unit = r match\n      case c: Call =>\n        if c.explicitTailCall then\n          raise(ErrorReport(msg\"This call is not in tail position.\" -> c.toLoc :: Nil))\n        c match\n          case CallToFun(r) => edges ::= CallEdge.NormalCall(f.dSym, r)(c)\n          case _ =>\n      case _ => super.applyResult(r)\n  \n  def buildCallGraph(fs: List[FunDefn])(using (ScopeData, AccessMap)): List[CallEdge] =\n    fs.flatMap(f => CallFinder(f).find)\n  \n  case class SccOfCalls(funs: List[FunDefn], calls: List[CallEdge])\n  \n  def partFns(fs: List[FunDefn])(using (ScopeData, AccessMap)): List[SccOfCalls] =\n    val defnSyms = fs.map(_.dSym)\n    val tsToDefn = fs.map(f => f.dSym -> f).toMap\n    \n    // Only care about calls to functions in the same scope\n    // Note that the results may differ if the lifter has been run.\n    val cg = buildCallGraph(fs).filter: c =>\n      val cond = defnSyms.contains(c.f1) && defnSyms.contains(c.f2)\n      c.match\n        case c: CallEdge.TailCall if c.call.explicitTailCall && !cond =>\n          raise(ErrorReport(\n            msg\"This tail call exits the current scope and is not optimized.\" -> c.call.toLoc :: Nil))\n        case _ =>\n      cond\n    \n    val cgTup = cg.map(c => (c.f1, c.f2))\n    val sccs = algorithms.sccsWithInfo(cgTup, defnSyms)\n    \n    // partition the call graph\n    val sccMap = sccs.sccs.flatMap:\n      case (id, scc) => scc.map(f => f -> id)\n    \n    val cgLabelled = cg\n      .groupBy: c =>\n        val s1 = sccMap(c.f1)\n        val s2 = sccMap(c.f2)\n        if s1 =/= s2 && c.call.explicitTailCall then\n          raise(ErrorReport(\n            msg\"This call is not optimized as it does not directly recurse through its parent function.\" -> c.call.toLoc :: Nil))\n          -1\n        else s1\n      .filter:\n        (id, _) => id =/= -1\n    \n    sccs.sccs.toList.map: v =>\n      val (id, tss) = v\n      val cgs = cgLabelled.get(id) match\n        case Some(value) => value\n        case None => Nil\n      SccOfCalls(tss.map(tsToDefn), cgs)\n  \n  def maxInt[T](items: List[T], f: T => Int): Int = items.foldLeft(0):\n    case (l, item) =>\n      val x = f(item)\n      if x > l then x else l\n  \n  def getParamSyms(f: FunDefn) = f.params.flatMap:\n    case ParamList(_, params, S(rest)) =>\n      params.map(_.sym).appended(rest.sym)\n    case p => p.params.map(_.sym)\n  \n  def paramsLen(f: FunDefn): Int = f.params.foldLeft(0): (acc, head) =>\n    acc + (if head.restParam.isDefined then 1 + head.params.length\n      else head.params.length)\n  \n  // Success:       This arg list was successfully transformed. The args may be blindly assigned to the\n  //                parameters in order.\n  // ForceSpread:   This arg list may be rewritten, but contains spread parameters for which must use a tuple\n  //                to correctly extract the arguments correctly.\n  private enum CallArgsResult:\n    case Success(res: List[Result])\n    case ForceSpread\n  \n  // Tries to rewrite an application of an arg list to a param list without needing to forcibly\n  // unspread the arguments.\n  private def rewriteArgsList(f: FunDefn, paramList: ParamList, args: List[Arg]): CallArgsResult =\n    val (headArgs, restArgs) = paramList.restParam match\n      case Some(value) => args.splitAt(paramList.params.length)\n      case None => (args, Nil)\n    \n    var hasSpread = false\n    // If any args have a spre\n    val hd = for a <- headArgs yield a.spread match\n      case Some(SpreadKind.Eager) =>\n        hasSpread = true\n        a.value\n      case Some(SpreadKind.Lazy) => lastWords(\"Lazys pread in arguments\")\n      case _ => a.value\n    if hasSpread then return CallArgsResult.ForceSpread\n    \n    if paramList.restParam.isDefined then\n      val rest =\n        restArgs match\n          case Arg(S(SpreadKind.Eager), value) :: Nil => value\n          case _ => Tuple(true, restArgs)\n      CallArgsResult.Success(hd.appended(rest))\n    else\n      CallArgsResult.Success(hd)\n    \n  def optScc(scc: SccOfCalls, owner: Opt[InnerSymbol])(using accessInfo: (ScopeData, AccessMap)): (Opt[FunDefn], List[FunDefn]) =\n    // sort the functions so the order is more predictable\n    val funs = scc.funs.sortBy(f => f.dSym.uid)\n    val fSyms = funs.map(_.dSym).toSet\n    val funsMap = funs.map: f =>\n        f.dSym -> f\n      .toMap\n    \n    // remove calls which don't flow into this scc\n    val calls = scc.calls.filter(c => fSyms.contains(c.f2)) \n    \n    val nonTailCallsLs = calls.collect:\n      case c: CallEdge.NormalCall => c.f2 -> c.call\n    val nonTailCalls = nonTailCallsLs.toMap\n    \n    if nonTailCallsLs.sizeCompare(calls) === 0 then\n      for f <- funs if f.forceTailRec do\n        raise(WarningReport(msg\"This function does not directly self-recurse, but is marked @tailrec.\" -> f.dSym.toLoc :: Nil))\n      return (N, funs)\n    \n    if !nonTailCalls.isEmpty then\n      for f <- funs if f.forceTailRec do\n        val reportLoc = nonTailCalls.get(f.dSym) match\n          // always display a call to f, if possible\n          case Some(value) => value.toLoc \n          case None => nonTailCalls.head._2.toLoc\n        raise(ErrorReport(\n            msg\"This function is not tail recursive.\" -> f.dSym.toLoc\n            :: msg\"It could self-recurse through this call, which is not a tail call.\" -> reportLoc\n            :: Nil\n          ))\n\n    val maxParamLen = maxInt(funs, paramsLen)\n    val paramSyms =\n        if funs.length === 1 then (getParamSyms(funs.head))\n        else\n          for i <- 0 until maxParamLen yield VarSymbol(Tree.Ident(\"param\" + i))\n      .toList\n    val paramSymsArr = ArrayBuffer.from(paramSyms)\n    // Function -> param -> param symbol in the rewritten function\n    val paramSymsMap: Map[TermSymbol, Map[VarSymbol, VarSymbol]] = \n      funs.map: f =>\n        val flattenedSyms = f.params.flatMap(_.paramSyms)\n        val mp = flattenedSyms.zipWithIndex.map:\n            case (l, i) => l -> paramSymsArr(i)\n          .toMap\n        f.dSym -> mp\n      .toMap\n    \n    val dSymIds = funs.map(_.dSym).zipWithIndex.toMap\n    val dSymToDefn = funs.map(f => f.dSym -> f).toMap\n    val bms =\n      if funs.size === 1 then funs.head.sym\n      else BlockMemberSymbol(funs.map(_.sym.nme).mkString(\"_\"), Nil, true)\n    val dSym =\n      if funs.size === 1 then funs.head.dSym\n      else TermSymbol(syntax.Fun, owner, Tree.Ident(bms.nme))\n    val loopSym = LabelSymbol(N, \"loopLabel\")\n    val curIdSym = VarSymbol(Tree.Ident(\"id\"))\n    \n    class FunRewriter(f: FunDefn) extends BlockTransformerShallow(SymbolSubst.Id):\n      val params = getParamSyms(f)\n      val paramsSet = f.params.toSet\n      val paramsIdxes = params.zipWithIndex.toMap\n      \n      // Certain variables must be re-defined in the tailrec loop\n      // if they are captured by nested definitions or lambdas. Otherwise,\n      // when they are mutated by a tailrec call, the nested definitions\n      // would capture the mutated variable rather than the one defined\n      // in the original call. See https://github.com/hkust-taco/mlscript/issues/415\n      val copiedParams: Set[VarSymbol] = \n        // scopeData: A class that wraps a tree describing the scoping relation in the IR. Each node is\n        //            an object that introduces a scope, which could be a scoped block, function, class, etc.\n        //            A node's children represent that scope's nested scopes, functions, classes, etc.\n        // accessMap: Maps scopes to the variables that they could access, either directly or by entering\n        //            another scope. For functions, that would be the variables they could access.\n        val (scopeData, accessMap) = accessInfo\n        val node = scopeData.getNode(f)\n        // Finds the immediate child functions/classes of the the function `f`.\n        val (_, childDefNodes) = node.partitionTree2:\n          case _: ScopedObject.Class => true\n          case _: ScopedObject.Func => true\n          case _ => false\n        childDefNodes.iterator.map(_.obj)\n          .collect:\n            case r: ScopedObject.Referencable[?] => r.sym // Obtains the definition symbol of the nested class/function.\n          .flatMap(s => accessMap(s).accessed) // All local variables that each nested class/function could access.\n          .collect:\n            case x: VarSymbol => x \n          .filter(params.toSet)\n          .toSet\n      \n      val copiedParamSyms = copiedParams.map: x =>\n          x -> VarSymbol(x.id)\n        .toMap\n      \n      val subst = new SymbolSubst:\n        override def mapVarSym(l: VarSymbol): VarSymbol =\n          copiedParamSyms.getOrElse(\n            l,\n            paramsIdxes.get(l) match\n              case Some(idx) => paramSymsArr(idx)\n              case _ => l\n          )\n      val symRewriter = new BlockTransformer(subst)\n      \n      override def applyBlock(b: Block): Block = b match\n        // Note: the args in `c` have already been rewritten to point to the symbols in `paramSyms`.\n        case TailCallShape(calleeSym, c) => dSymIds.get(calleeSym) match\n          case None => super.applyBlock(b)\n          case Some(id) =>\n            val callee = dSymToDefn(calleeSym)\n            val calleeParamsMap = paramSymsMap(callee.dSym)\n            // We require the call to be fully applied.\n            if c.argss.size != callee.params.size then\n              super.applyBlock(b)\n            else\n              // The code used to continute the loop.\n              val cont =\n                if scc.funs.size === 1 then Continue(loopSym)\n                else Assign(curIdSym, Value.Lit(Tree.IntLit(dSymIds(calleeSym))), Continue(loopSym))\n              // In some cases, we could have assignments like this:\n              // param0 = whatever\n              // param1 = <a result containing param0>\n              // which means param1's value is incorrect.\n              // We should thus assign the params to temporary symbols\n              // if they are needed for a subsequent assignment.\n              var assignedSyms: Map[VarSymbol, Lazy[TempSymbol]] = paramSyms.map: sym =>\n                  sym -> Lazy(TempSymbol(N, sym.nme + \"_tmp\")) // Use `Lazy` to avoid generating useless symbols\n                .toMap\n              var requiredTmps: Set[(VarSymbol, TempSymbol)] = Set.empty\n              \n              // Rewrites references to mutated parameters to point to a temp variable instead, and\n              // reports that the parameter's value must be assigned to that temp variable\n              // before assigning to the parameters of this arg list.\n              val paramRewriter = new BlockDataTransformer(SymbolSubst.Id):\n                override def applyValue(v: Value)(k: Value => Block): Block = v match\n                  // `assignedSyms` contains all of the param symbols that have been assigned to\n                  // before the current assignment, and thus references to them must be rewritten\n                  // to point to a temporary variable.\n                  case Value.Ref(l: VarSymbol, disamb) => assignedSyms.get(l) match\n                    case S(v) =>\n                      val tmpSym = v.force_!\n                      // Adding this to `requiredTmps` will make sure we set the temporary variable\n                      // to the current variable at the start of the rewritten call.\n                      requiredTmps += (l, tmpSym)\n                      k(Value.Ref(tmpSym, disamb))\n                    case _ => super.applyValue(v)(k)\n                  case _ => super.applyValue(v)(k)\n              \n              val argListResults = callee.params.zip(c.argss).map:\n                case (params, args) => (params, params.paramSyms.map(calleeParamsMap), args, rewriteArgsList(callee, params, args))\n              \n              // Prevent stupid assignments like `set a = a`\n              val selfAssigns = argListResults.flatMap: (_, thisParamSyms, args, argsRes) =>\n                argsRes match\n                  case CallArgsResult.Success(res) => thisParamSyms.zip(res).collect:\n                    case (sym1, Value.Ref(sym2, _)) if sym1 === sym2 => sym1\n                  case CallArgsResult.ForceSpread => List.empty\n              assignedSyms --= selfAssigns\n                \n              \n              // Algorithm: Apply the args from right to left, but have the resulting assignment order\n              // be left to right.\n              // \n              // When applying each arg, keep track of the parameters that must be assigned to be a\n              // temporary variable. Also, remove each assigned parameter from `assignedSyms` after assigning\n              // them, so that assignments coming before them will not mistakenly add the param syms from \n              // future assignments to `requiredTmps`.\n              val assignments: Block = argListResults.foldRight(cont):\n                case ((ogParamList, thisParamSyms, ogArgs, argRes), rest) =>\n                  argRes match\n                  case CallArgsResult.Success(argVals) =>\n                    // Remove symbols from assignedSyms as we encounter them.\n                    // Note that foldRight will call the function right to left\n                    thisParamSyms.zip(argVals).foldRight[Block](rest): (v, acc) =>\n                      val (sym, res) = v\n                      assignedSyms -= sym\n                      // Rewrite the result with symbols pointing to the temporary variables as described above.\n                      // Note that we already rewrote the result with symbols pointing to the merged function parameters\n                      // in `rewrite`. Also note that `paramRewriter` will add all encountered rewritten variables\n                      // to `requiredTmps`.\n                      val ret = paramRewriter.applyResult(res)(Assign(sym, _, acc)) match\n                        case Assign(sym, Value.Ref(sym1, _), rest) if sym === sym1 => rest // avoid useless assignments\n                        case x => x\n                      ret\n                  case CallArgsResult.ForceSpread =>\n                    // Forcibly spread the args in an array.\n                    // Assume the lengths are correct\n                    val paramList = ogParamList.params\n                    val restParam = ogParamList.restParam\n                    \n                    val tupleSym = TempSymbol(N, \"argList\")\n                    \n                    // We can safely remove all of the symbols from this parameter list from `assignedSyms` at this stage,\n                    // because the RHS of every parameter will be computed when spreading them in the tuple, which happens\n                    // before any of the param symbols are assigned to.\n                    assignedSyms --= thisParamSyms\n                    paramRewriter.applyArgs(ogArgs): newArgs =>\n                      val tupleRes = Tuple(false, newArgs)\n                      \n                      // Main args\n                      def mainArgs(rest: List[Path]) = (0 until paramList.size).toList.foldRight(rest):\n                        case (n, acc) => DynSelect(tupleSym.asPath, Value.Lit(Tree.IntLit(n)), true) :: acc\n                      \n                      // If the rest param exists, append a slice\n                      val (initialBlk: (Block => Block), pathList: List[Path]) =\n                        if restParam.isDefined then\n                          val sliceResSym = TempSymbol(N, \"sliceRes\")\n                          // runtime.Tuple.slice(tupleSym, paramList.length, 0)\n                          val sliceRes = Call(\n                            State.runtimeSymbol.asPath\n                              .sel(Tree.Ident(\"Tuple\"), State.tupleSymbol)\n                              .sel(Tree.Ident(\"slice\"), State.tupleSliceSymbol),\n                            (tupleSym.asPath.asArg\n                              :: Value.Lit(Tree.IntLit(paramList.length)).asArg\n                              :: Value.Lit(Tree.IntLit(0)).asArg\n                              :: Nil) ne_:: Nil\n                          )(true, false, false)\n                          val blk = blockBuilder\n                            .assignScoped(tupleSym, tupleRes)\n                            .assignScoped(sliceResSym, sliceRes)\n                          (blk, mainArgs(sliceResSym.asPath :: Nil))\n                        else\n                          (blockBuilder.assignScoped(tupleSym, tupleRes), mainArgs(Nil))\n                      end val\n                      val paramAssignments = (thisParamSyms zip pathList).foldRight[Block](rest):\n                        case ((sym, path), restBlk) => Assign(sym, path, restBlk)\n                    \n                      initialBlk.rest(paramAssignments)\n              end assignments\n              \n              // Bind the tmps\n              Scoped(\n                requiredTmps.values.toSet,\n                requiredTmps.toList.foldRight(assignments):\n                  case ((v, l), acc) => Assign(l, Value.Ref(v), acc))\n        // Not a tail call\n        case _ => super.applyBlock(b)\n      \n      def rewrite(b: Block): Block =\n        // Rewrite the result with symbols pointing to the merged function parameters and possibly the copied parameters (see `copiedParams`).\n        val blk = applyBlock(symRewriter.applyBlock(b))\n        val withCopied = copiedParamSyms.toArray.sortBy(_._1.uid).foldRight(blk):\n          case ((ogParam, copiedParam), accBlk) => Assign(copiedParam, paramSymsArr(paramsIdxes(ogParam)).asPath, accBlk)\n        Scoped(copiedParamSyms.map(_._2).toSet, withCopied)\n        \n    val arms = funs.map: f =>\n      Case.Lit(Tree.IntLit(dSymIds(f.dSym))) -> FunRewriter(f).rewrite(f.body)\n    \n    val switch = \n      if arms.length === 1 then arms.head._2\n      else Match(curIdSym.asPath, arms, N, End())\n    \n    val loop = Label(loopSym, true, switch, End())\n    \n    val sel = owner match\n      case Some(value) => Select(Value.Ref(value, N), Tree.Ident(bms.nme))(S(dSym))\n      case None => Value.Ref(bms, S(dSym))\n    \n    val rewrittenFuns =\n      if funs.size === 1 then Nil\n      else funs.map: f =>\n        val paramArgs = getParamSyms(f).map(_.asPath.asArg)\n        val args = \n          Value.Lit(Tree.IntLit(dSymIds(f.dSym))).asArg\n            :: paramArgs\n            ::: List.fill(maxParamLen - paramArgs.length)(Value.Lit(Tree.UnitLit(false)).asArg)\n        val newBod = Return(\n          Call(sel, args ne_:: Nil)(true, false, false),\n          false\n        )\n        FunDefn(f.owner, f.sym, f.dSym, f.params, newBod)(N, f.annotations)\n    \n    val params =\n      val initial = paramSyms.map(Param.simple(_))\n      if funs.length === 1 then initial\n      else Param.simple(curIdSym) :: initial\n    \n    val loopDefn = FunDefn(\n      owner, bms, dSym,\n      PlainParamList(params) :: Nil,\n      loop)(N, annotations = Nil) // Q: maybe should be Private?\n    \n    if funs.size === 1 then\n      val f = funs.head\n      if f.params.length > 1 then\n        // When a function has multiple param lists, TailRecOpt flattens them into a single\n        // param list for the internal loop. We need a wrapper function that preserves the\n        // original multi-param-list interface and delegates to the flattened internal loop.\n        val loopBms = BlockMemberSymbol(bms.nme + \"$tailrec\", Nil, true)\n        val loopDSym = TermSymbol(syntax.Fun, owner, Tree.Ident(loopBms.nme))\n        val internalLoopDefn = FunDefn(\n          owner, loopBms, loopDSym,\n          PlainParamList(params) :: Nil,\n          loop)(N, annotations = Annot.Private :: Nil)\n        val paramArgs = getParamSyms(f).map(_.asPath.asArg)\n        val internalSel = owner match\n          case Some(value) => Select(Value.Ref(value, N), Tree.Ident(loopBms.nme))(S(loopDSym))\n          case None => Value.Ref(loopBms, S(loopDSym))\n        val wrapperBod = Return(\n          Call(internalSel, paramArgs ne_:: Nil)(true, false, false),\n          false\n        )\n        val wrapperDefn = FunDefn(f.owner, f.sym, f.dSym, f.params, wrapperBod)(\n          f.configOverride, annotations = f.annotations)\n        (S(internalLoopDefn), wrapperDefn :: Nil)\n      else\n        (N, loopDefn :: Nil)\n    else (S(loopDefn), rewrittenFuns)\n  \n  def optFunctions(fs: List[FunDefn], owner: Opt[InnerSymbol])(using (ScopeData, AccessMap)) =\n    val (newFsOpt, fsOpt) = partFns(fs).map(optScc(_, owner)).foldLeft[(List[FunDefn], List[FunDefn])](Nil, Nil):\n      case ((newFns, fns), (newFnOpt, fns_)) => newFnOpt match\n        case Some(value) => (value :: newFns, fns_ ::: fns)\n        case None => (newFns, fns_ ::: fns)\n    // preserve the order of function defns\n    val fMap = fsOpt.map(f => (f.dSym, f)).toMap\n    val fsRet = fs.map(f => fMap(f.dSym))\n    (newFsOpt, fsRet)\n  \n  def reportClassesTailrec(c: ClsLikeDefn) =\n    new BlockTraverserShallow():\n      for f <- c.methods do\n        applyBlock(f.body)\n        if f.forceTailRec then\n          raise(ErrorReport(msg\"Class methods may not yet be marked @tailrec.\" -> f.dSym.toLoc :: Nil))\n      override def applyResult(r: Result): Unit = r match\n        case c: Call if c.explicitTailCall =>\n          raise(ErrorReport(msg\"Calls from class methods cannot yet be marked @tailcall.\" -> c.toLoc :: Nil))\n        case _ => super.applyResult(r)\n  \n  def optFunctionsFlat(fs: List[FunDefn], owner: Opt[InnerSymbol])(using (ScopeData, AccessMap)) =\n    val (a, b) = optFunctions(fs, owner)\n    a ::: b\n    \n  def optClasses(cs: List[ClsLikeDefn])(using (ScopeData, AccessMap)) = cs.map: c =>\n    // Class methods cannot yet be optimized as they cannot yet be marked final.\n    \n    if c.k is syntax.Cls then\n      reportClassesTailrec(c)\n      val companion = c.companion.map: comp =>\n        val cMtds = optFunctionsFlat(comp.methods, S(comp.isym))\n        comp.copy(methods = cMtds)\n      c.copy(companion = companion)(c.configOverride, c.annotations)\n    else\n      val mtds = optFunctionsFlat(c.methods, S(c.isym))\n      val companion = c.companion.map: comp =>\n        val cMtds = optFunctionsFlat(comp.methods, S(comp.isym))\n        comp.copy(methods = cMtds)\n      c.copy(methods = mtds, companion = companion)(c.configOverride, c.annotations)\n  \n  def transform(b: Block) =\n    /* To avoid `x` being overridden in the following when the lifter is not run:\n     * \n     * let lam\n     * fun f(x) =\n     *   set lam = () => x\n     *   f(x + 1)\n     * \n     * we need to do some analysis on what nested functions use what variables. We\n     * re-use the analysis from the lifter to do this.\n     */\n    \n    given (ScopeData, AccessMap) = \n      // IgnoredScoes can be an empty set, since that information is only relevant for lifting\n      given IgnoredScopes = IgnoredScopes(S(Set.empty))\n      val scopeData = ScopeData(b)\n      val analyzer = new UsedVarAnalyzer(b, scopeData)\n      (scopeData, analyzer.accessMapWithIgnored)\n    \n    val defns = b.gatherDefns()\n    val (funs, clses) = defns.partitionMap:\n      case f: FunDefn => L(f)\n      case c: ClsLikeDefn => R(c)\n      case _ => die // unreachable as floatOutDefns only floats out FunDefns and ClsLikeDefns\n    // Filter out functions that have a @config annotation disabling tailRecOpt\n    val (tailRecFuns, _) = funs.partition: f =>\n      f.configOverride.forall(_.tailRecOpt)\n    val (optFNew, optF) = optFunctions(tailRecFuns, N)\n    val optC = optClasses(clses)\n    \n    val fMap = optF.map(f => f.dSym -> f).toMap\n    // Scala needs this annotation to type check for some reason\n    val cMap: Map[DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol, ClsLikeDefn] =\n      optC.map(c => c.isym -> c).toMap\n    \n    // replace them in place \n    val transformer = new BlockTransformerShallow(SymbolSubst.Id):\n      override def applyDefn(defn: Defn)(k: Defn => Block): Block = defn match\n        case f: FunDefn => fMap.get(f.dSym) match\n          case Some(value) => k(value)\n          case None => k(f)\n        \n        case c: ClsLikeDefn => cMap.get(c.isym) match\n          case Some(value) => k(value)\n          case None => k(c)\n        \n        case _ => super.applyDefn(defn)(k)\n    \n    val result = Scoped(\n      optFNew.map(_.sym).toSet,\n      optFNew.foldLeft(transformer.applyBlock(b)):\n        case (acc, f) => Define(f, acc))\n    \n    // Report @tailrec on functions that weren't processed by the optimization above,\n    // e.g. nested functions or functions with @config(tailRecOpt: false).\n    // Class/module methods are handled separately by optClasses and are skipped here.\n    val tailRecFunSyms = tailRecFuns.map(_.dSym).toSet\n    new BlockTraverser:\n      override def applyFunDefn(fun: FunDefn): Unit =\n        if fun.forceTailRec && !tailRecFunSyms.contains(fun.dSym) then\n          raise(ErrorReport(\n            msg\"This @tailrec function was not processed by the tail-call optimizer.\" -> fun.dSym.toLoc :: Nil))\n        super.applyFunDefn(fun)\n      override def applyDefn(defn: Defn): Unit = defn match\n        case _: ClsLikeDefn => ()\n        case _ => super.applyDefn(defn)\n    .applyBlock(result)\n    \n    result\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/UsedVarAnalyzer.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.codegen.*\nimport hkmc2.semantics.*\nimport hkmc2.Message.*\nimport hkmc2.semantics.Elaborator.State\nimport hkmc2.ScopeData.*\nimport hkmc2.Lifter.*\n\nimport scala.collection.mutable.Map as MutMap\nimport scala.collection.mutable.Set as MutSet\nimport scala.collection.mutable.Buffer\n\nobject UsedVarAnalyzer:\n  case class MutAccessInfo(\n    accessed: MutSet[Local], \n    mutated: MutSet[Local], \n    refdDefns: MutSet[ScopedInfo]\n  ):\n    def toIMut = AccessInfo(accessed.toSet, mutated.toSet, refdDefns.toSet)\n  object MutAccessInfo:\n    def empty = MutAccessInfo(\n      MutSet.empty,\n      MutSet.empty,\n      MutSet.empty\n    )\n/**\n  * Analyzes which variables have been used and mutated by which functions.\n  * Also finds which variables can be passed to a capture class without a heap\n  * allocation (during class lifting) despite being mutable.\n  *\n  * Assumes the input trees have no lambdas.\n  */\nclass UsedVarAnalyzer(b: Block, scopeData: ScopeData)(using State):\n  import UsedVarAnalyzer.*\n  \n  object SDSym:\n    def unapply(v: DefinitionSymbol[?] | Option[DefinitionSymbol[?]]) = dSymUnapply(scopeData, v)\n  \n  private def isObj(s: ScopeNode) = s.obj match\n    case c: ScopedObject.Class if c.isObj => true\n    case _ => false\n  \n  // Finds the locals that this block accesses/mutates, and the definitions which it could use.\n  private def blkAccessesShallow(b: Block): AccessInfo =\n    var accessed: MutAccessInfo = MutAccessInfo.empty\n    new BlockTraverserShallow:\n      applyBlock(b)\n      \n      override def applyBlock(b: Block): Unit = b match\n        case s: Scoped =>\n          accessed.refdDefns.add(scopeData.getUID(s))\n        case Assign(lhs, rhs, rest) =>\n          accessed.accessed.add(lhs)\n          accessed.mutated.add(lhs)\n          applyResult(rhs)\n          applyBlock(rest)\n        case l: Label if l.loop =>\n          accessed.refdDefns.add(l.label)\n        case d: Define => d.defn match\n          case v: ValDefn =>\n            applyDefn(v)\n            applySubBlock(d.rest)\n          case c @ ClsLikeDefn(k = syntax.Obj) =>\n            accessed.refdDefns.add(c.isym)\n          case _ => applySubBlock(d.rest)\n        \n        case _ => super.applyBlock(b)\n      \n      override def applyPath(p: Path): Unit = p match\n        case Value.Ref(_: BuiltinSymbol, _) => super.applyPath(p)\n        case RefOfBms(_, SDSym(dSym), _) =>\n          val node = scopeData.getNode(dSym)\n          node.obj match\n            // Here, we add an edge to a definition, even if it is the result of a field selection, if it is:\n            // - Lifted, but not an object\n            // - Is a module method\n            // - Is a ctor of a lifted class\n            // Otherwise, we ignore the disambiguated symbol and traverse into the the selection's path. Once\n            // we reach the \"base\" reference to an object, then we add a reference to that as required.\n            \n            case ScopedObject.Func(isMethod = S(MethodKind.ModMethod)) =>\n              accessed.refdDefns.add(node.obj.toInfo)\n              super.applyPath(p)\n            case ScopedObject.Func(isMethod = N) =>\n              accessed.refdDefns.add(node.obj.toInfo)\n              super.applyPath(p)\n            case _ if node.isLifted && !isObj(node) => accessed.refdDefns.add(node.obj.toInfo)\n            case ScopedObject.ClassCtor(cls) if scopeData.getNode(cls).isLifted => accessed.refdDefns.add(node.obj.toInfo)\n            case _ => p match\n              case _: Value.Ref => node.obj match\n                case c: ScopedObject.Class if c.isObj =>\n                  accessed.accessed.add(c.cls.isym)\n                case r: ScopedObject.Referencable[?] if !node.isLifted =>\n                  accessed.refdDefns.add(r.toInfo)\n                case _: ScopedObject.Class | _: ScopedObject.ClassCtor | _: ScopedObject.Companion => accessed.refdDefns.add(node.obj.toInfo)\n                case _ => ()\n              case _ => super.applyPath(p)\n              \n        case Value.Ref(l, _) =>\n          accessed.accessed.add(l)\n        case _ => super.applyPath(p)\n    accessed.toIMut\n    \n  /**\n    * Finds the variables belonging to a parent scope which this scoped object could possibly \n    * access or mutate, excluding mutations through calls to other functions and mutations \n    * of their own variables. Also finds the other scoped objects that this definition may enter.\n    * \n    * @param obj The scoped object to search through.\n    * @return The variables which this definition could possibly mutate.\n    */\n  private def findAccessesShallow(obj: ScopedObject): AccessInfo =\n    val accessed = obj match\n      case ScopedObject.Top(b) => b match\n        case s: Scoped => blkAccessesShallow(s.body)\n        case _ => blkAccessesShallow(b)\n      case ScopedObject.Func(f, _) =>\n        blkAccessesShallow(f.body)\n      case ScopedObject.Class(c, _) =>\n        // We must assume that classes may access all their methods.\n        // When the class symbol is referenced once, that symbol may be used in\n        // arbitrary ways, which includes calling any of this class's methods.\n        val res = blkAccessesShallow(c.preCtor) ++ blkAccessesShallow(c.ctor)\n        res.copy(refdDefns = res.refdDefns ++ c.methods.map(_.dSym))\n      case ScopedObject.ClassCtor(cls) =>\n        // Recall that we interpret the ctor as just another function in the same scope\n        // as the corresponding class, and initializes the class.\n        AccessInfo.empty.addRefdScopedObj(scopeData.getNode(cls).obj.toInfo)\n      case ScopedObject.ScopedBlock(uid, b) => blkAccessesShallow(b.body)\n      case ScopedObject.Companion(c, _) =>\n        // There likely won't be nested companion classes in the future, but for now,\n        // just assume they may access all their methods\n        val res = blkAccessesShallow(c.ctor)\n        res.copy(refdDefns = res.refdDefns ++ c.methods.map(_.dSym))\n      case ScopedObject.Loop(_, b) => blkAccessesShallow(b)\n    // Variables introduced by this scoped object do not belong to a parent scope, so\n    // we remove them\n    accessed.withoutLocals(obj.definedLocals)\n  \n  private def combineInfos(m1: Map[ScopedInfo, AccessInfo], m2: Map[ScopedInfo, AccessInfo]): Map[ScopedInfo, AccessInfo] =\n    if m2.size < m1.size then combineInfos(m2, m1)\n    else m1.foldLeft(m2):\n      case (acc, info -> accesses) => m2.get(info) match\n        case Some(value) => acc + (info -> (accesses ++ value))\n        case None => acc + (info -> accesses)\n  \n  // Find:\n  // - Map 1:\n  //    - Variables that each scoped object has accessed, either through itself or a nested scoped object.\n  //    - Variables that each scoped object has mutated, either through itself or a nested scoped object.\n  //    - Scoped objects that each object accesses, either through itself or a nested scoped object.\n  // - Map 2:\n  //    - Variables that each scoped object has accessed, either through itself or a *lifted* scoped object.\n  //    - Variables that each scoped object has mutated, either through itself or a lifted nested scoped object.\n  //    - Scoped objects that each object accesses, either through itself or a lifted nested scoped object.\n  //\n  // The former includes ignored objects, and is used to do the readers/writers analysis. The latter is used to determine\n  // whether we actually need to allocate a capture for the object. In particular, we never need to allocate a capture\n  // for a variable if only nested scopes mutate it.\n  //\n  // Note that it is possible for a lifted scoped object to be reached by traversing through an ignored object.\n  // \n  // Also observe that if a node is not accesed from any of its children, then we can re-use the result of its parent's analysis.\n  private def findAccesses(s: ScopeNode): (Map[ScopedInfo, AccessInfo], Map[ScopedInfo, AccessInfo]) =\n    // Note: these include `s`\n    val children = s.allChildren\n    val childInfo = children.map(_.toInfo).toSet\n\n    // Traverses the node's children, and stops when a child that is accessed by one of its children is found.\n    // The analysis will be performed on *all* of the traversed nodes simultaneously.\n    // We will later recurse on the children of all these nodes.\n    val (nodes, nexts) = s.partitionTree(x => accessedByChild(x.obj.toInfo))\n    \n    val allLocals = nodes.flatMap(node => node.obj.definedLocals).toSet\n    \n    val accessInfo = children.map: obj =>\n      val a @ AccessInfo(accessed, mutated, refdDefns) = shallowAccesses(obj.toInfo)\n      obj.toInfo -> AccessInfo(\n        accessed = accessed.intersect(allLocals),\n        mutated = mutated.intersect(allLocals),\n        refdDefns = refdDefns.intersect(childInfo)\n      )\n    \n    val accessInfoMap = accessInfo.toMap\n    val edges: Set[(ScopedInfo, ScopedInfo)] =\n      for\n        (src, AccessInfo(_, _, refd)) <- accessInfo\n        r <- refd\n        // remove self-edges: they do not affect this analysis\n        if src =/= r\n        // very important: we only care about edges that flow into the subtree rooted at `s`\n        if childInfo.contains(r) && r =/= s.obj.toInfo\n      yield src -> r\n    .toSet\n    \n    // (sccs, sccEdges) forms a directed acyclic graph (DAG)\n    val algorithms.SccsInfo(sccs, sccEdges, inDegs, outDegs) = algorithms.sccsWithInfo(edges, childInfo)\n\n    val rootInfo = s.obj.toInfo\n    val (rootId, rootElems) = sccs.find:\n        case (id, elems) => elems.contains(rootInfo)\n      .get\n    if rootElems.size != 1 then lastWords(\"SCC containing root had a degree other than 1.\")\n    \n    // With respect to the current scoped object `s`, we may \"ignore\" one of its children `c` if and only if\n    // it is ignored (not lifted), and `s` is in the subtree rooted at the first lifted parent of `c`. We\n    // \"ignore\" `c` in the sense that it does not need to capture `s`'s scoped object's variables, nor does\n    // it require the current scoped object to create a capture class for its accessed variables.\n    def isIgnored(c: ScopedInfo) =\n      s.inSubtree(scopeData.getNode(c).firstLiftedAncestor.toInfo)\n\n    // All objects in the same scc must have at least the same accesses as each other\n    def go(includeIgnored: Bool) =\n      val base = for (id, scc) <- sccs yield\n        // If all objects in this SCC are ignored, then we treat it as if it does not access anything,\n        // unless we explicitly want to count ignored items (for the readers-mutators analysis)\n        if !includeIgnored && scc.forall(isIgnored) then id -> AccessInfo.empty\n        else id -> scc.foldLeft(AccessInfo.empty):\n          case (acc, sym) => acc ++ accessInfoMap(sym)\n      \n      // dp on DAG\n      val dp: MutMap[Int, AccessInfo] = MutMap.empty\n      def sccAccessInfo(scc: Int): AccessInfo = dp.get(scc) match\n        case Some(value) => value\n        case None =>\n          val ret = sccEdges(scc).foldLeft(base(scc)):\n            case (acc, nextScc) => acc ++ sccAccessInfo(nextScc)\n          dp.addOne(scc -> ret)\n          ret\n      \n      for\n        (id, scc) <- sccs\n        sym <- scc\n      yield\n        sym -> sccAccessInfo(id).withoutLocals(scopeData.getNode(sym).obj.definedLocals)\n    \n    // Remove locals that are not yet defined\n    def removeUnused(m: Map[ScopedInfo, AccessInfo]) = m.map:\n      case k -> v =>\n        val node = scopeData.getNode(k)\n        k -> v.intersectLocals(node.existingVars)\n    \n    val (m1, m2) = (removeUnused(go(true)), removeUnused(go(false)))\n    \n    val subCases = nexts.map(findAccesses)\n    subCases.foldLeft((m1, m2)):\n      case ((acc1, acc2), (new1, new2)) => (combineInfos(acc1, new1), combineInfos(acc2, new2))\n\n  private def reqdCaptureLocals(s: ScopeNode): Map[ScopedInfo, Set[Local]] =\n    val blk = s.obj match\n      case ScopedObject.Top(b) => lastWords(\"reqdCaptureLocals called on top block\")\n      case ScopedObject.ClassCtor(cls) => return Map.empty + (s.obj.toInfo -> Set.empty)\n      case ScopedObject.Class(cls, _) => Begin(cls.preCtor, cls.ctor)\n      case ScopedObject.Companion(comp, _) => comp.ctor\n      case ScopedObject.Func(fun, _) => fun.body\n      case ScopedObject.ScopedBlock(uid, block) => block\n      case ScopedObject.Loop(sym, block) => block\n\n    val (nodes, nexts) = s.partitionTree2:\n      case obj: (ScopedObject.ScopedBlock | ScopedObject.Loop) => false\n      case _ => true\n    \n    val locals = nodes.flatMap(_.obj.definedLocals).toSet\n    \n    val cap = reqdCaptureLocalsBlk(blk, nexts.toList, s.obj.definedLocals, locals)\n    \n    // In a class, all variables that are mutated by a child scope and accessed by a lifted class must be captured\n    val additional = s.obj match\n      case _: ScopedObject.Companion | _: ScopedObject.Class =>\n        val (a, b) = s.children.map: c =>\n            val acc = accessMap(c.obj.toInfo)\n            val accAll = accessMapWithIgnored(c.obj.toInfo)\n            (accAll.mutated, acc.accessed)\n          .unzip\n        a.flatten.toSet.intersect(b.flatten.toSet)\n      case _ => Set.empty\n  \n    val newCap = cap ++ additional\n    \n    val cur: Map[ScopedInfo, Set[Local]] = nodes.map: n =>\n        n.obj.toInfo -> newCap.intersect(n.obj.definedLocals)\n      .toMap\n    \n    nexts.foldLeft(cur):\n      case (mp, acc) => mp ++ reqdCaptureLocals(acc)\n\n  // readers-mutators analysis\n  private def reqdCaptureLocalsBlk(b: Block, nextNodes: List[ScopeNode], startingVars: Set[Local], thisVars: Set[Local]): Set[Local] =\n    val scopeInfos: Map[ScopedInfo, ScopeNode] = nextNodes.map(node => node.obj.toInfo -> node).toMap\n\n    case class CaptureInfo(reqCapture: Set[Local], hasReader: Set[Local], hasMutator: Set[Local], mutated: Set[Local])\n    \n    // linearVars denotes the variables defined inside the scopes up to the nearest loop or the top level block.\n    // If a loop modifies a non-linear variable and then one of its nested definitions accesses it, we must put put\n    // that variable in a capture.\n    def go(b: Block, reqCapture_ : Set[Local], hasReader_ : Set[Local], hasMutator_ : Set[Local], mutated_ : Set[Local])(using linearVars: Set[Local]): CaptureInfo =\n      var reqCapture = reqCapture_\n      var hasReader = hasReader_\n      var hasMutator = hasMutator_\n      // note: the meaning of `mutated` is a bit strange: it basically means variables which are currently not linear that have been mutated\n      // if a variable is in this set but is linear, then it's ignored\n      var mutated = mutated_\n\n      inline def merge(c: CaptureInfo) =\n        reqCapture ++= c.reqCapture\n        hasReader ++= c.hasReader\n        hasMutator ++= c.hasMutator\n        mutated ++= c.mutated\n\n      def rec(blk: Block)(using linearVars: Set[Local]) =\n        go(blk, reqCapture, hasReader, hasMutator, mutated_)\n      \n      new BlockTraverserShallow:\n        applyBlock(b)\n        override def applyBlock(b: Block): Unit = b match\n          // Note that we traverse directly into scoped blocks without using handleCalledScope\n          case s: Scoped =>\n            rec(s.body)(using linearVars = linearVars ++ s.syms) |> merge\n          case l: Label if l.loop =>\n            rec(l.body)(using linearVars = Set.empty) |> merge\n            applySubBlock(l.rest)\n          case Assign(lhs, rhs, rest) =>\n            applyResult(rhs)\n            if hasReader.contains(lhs) || hasMutator.contains(lhs) then reqCapture += lhs\n            if !linearVars.contains(lhs) then mutated += lhs\n            applySubBlock(rest)\n          case Define(c @ ClsLikeDefn(k = syntax.Obj), rest) =>\n            handleCalledScope(c.isym)\n            applySubBlock(rest)\n          case Match(scrut, arms, dflt, rest) =>\n            applyPath(scrut)\n            val infos = arms.map:\n              case (_, arm) => rec(arm)\n            val dfltInfo = dflt.map:\n              case arm => rec(arm)\n            \n            infos.foreach(merge) // IMPORTANT: rec all first, then merge, since each branch is mutually exclusive\n            dfltInfo.foreach(merge)\n            applySubBlock(rest)\n          case Begin(sub, rest) =>\n            rec(sub) |> merge\n            applySubBlock(rest)\n          case TryBlock(sub, finallyDo, rest) =>\n            // sub and finallyDo could be executed sequentially, so we must merge\n            rec(sub) |> merge\n            rec(finallyDo) |> merge\n            applySubBlock(rest)\n          case Return(res, false) =>\n            applyResult(res)\n            hasReader = Set.empty\n            hasMutator = Set.empty\n          case _ => super.applyBlock(b)\n\n        def handleCalledScope(called: ScopedInfo): Unit = scopeInfos.get(called) match\n          case None => ()\n          case Some(node) =>\n            node.obj match\n              // ignore method calls to class or object methods\n              case ScopedObject.Func(_, S(MethodKind.ClsMethod | MethodKind.ObjMethod)) => return\n              case _ => ()\n            \n            val AccessInfo(accessed, muted, refd) = accessMapWithIgnored(called)\n            val muts = muted.intersect(thisVars)\n            val reads = accessed.intersect(thisVars) -- muts\n            val refdExcl = refd.filter: sym =>\n              scopeData.getNode(sym).obj match\n                case s: ScopedObject.ScopedBlock => false\n                case ScopedObject.Func(_, S(MethodKind.ClsMethod | MethodKind.ObjMethod)) => false\n                case _ => true\n            \n            // This not a naked reference. If it's a ref to a class, this can only ever create once instance\n            // so the \"one writer\" rule applies.\n            // However, if the control flow is not linear, we are forced to add all the mutated variables\n            for l <- muts do\n              if hasReader.contains(l) || hasMutator.contains(l) || !linearVars.contains(l) then\n                reqCapture += l\n              hasReader += l\n              hasMutator += l\n              mutated += l\n            for l <- reads do\n              if hasMutator.contains(l) then\n                reqCapture += l\n              if mutated.contains(l) && !linearVars.contains(l) then\n                reqCapture += l\n              hasReader += l\n            // if this defn calls another defn that creates a class or has a naked reference to a\n            // function, we must capture the latter's mutated variables in a capture, as arbitrarily\n            // many mutators could be created from it\n            for\n              sym <- refdExcl\n              l <- accessMapWithIgnored(sym).mutated\n            do\n              reqCapture += l\n              hasMutator += l\n        \n        def handleScopeRef(s: ScopedInfo) = scopeInfos.get(s) match\n          case None => // super.applyPath(p)\n          case Some(defn) =>\n            val isModOrObj = defn.obj match\n              case c: ScopedObject.Companion => true\n              case c: ScopedObject.Class => c.isObj\n              case _ => false\n            if isModOrObj then () //super.applyPath(p)\n            else\n              val AccessInfo(accessed, muted, refd) = accessMapWithIgnored(s)\n              val muts = muted.intersect(thisVars)\n              val reads = accessed.intersect(thisVars) -- muts\n              // this is a naked reference, we assume things it mutates always needs a capture\n              for l <- muts do\n                reqCapture += l\n                hasMutator += l\n              for l <- reads do\n                if hasMutator.contains(l) then\n                  reqCapture += l\n                if mutated.contains(l) && !linearVars.contains(l) then\n                  reqCapture += l\n                hasReader += l\n              // if this defn calls another defn that creates a class or has a naked reference to a\n              // function, we must capture the latter's mutated variables in a capture, as arbitrarily\n              // many mutators could be created from it\n              for\n                sym <- refd\n                l <- accessMapWithIgnored(sym).mutated\n              do\n                reqCapture += l\n                hasMutator += l\n\n        override def applyResult(r: Result): Unit = \n          r match\n          case Call(RefOfBms(_, SDSym(d), _), argss) =>\n            argss.foreach(_.foreach(super.applyArg(_)))\n            val numArgLists = scopeData.getNode(d).obj match\n              case ScopedObject.Func(fun, _) => fun.params.size.min(1)\n              case ScopedObject.Class(c, false) => c.paramsOpt.map(_.params.size).getOrElse(0).min(1)\n              case ScopedObject.ClassCtor(c) => c.paramsOpt.map(_.params.size).getOrElse(0).min(1)\n              case _ => die\n            \n            // Partial call; the resulting object requiring access to the scope may linger\n            if numArgLists != argss.size then handleScopeRef(d)\n             // Fully applied, we can treat it as a call\n            else handleCalledScope(d)\n          case Instantiate(mut, RefOfBms(_, SDSym(d), _), argss) =>\n            argss.foreach(_.foreach(super.applyArg(_)))\n            handleCalledScope(d)\n          case _ => super.applyResult(r)\n        \n        override def applyPath(p: Path): Unit = p match\n          case RefOfBms(_, SDSym(d), _) => handleScopeRef(d)          \n          case Value.Ref(l, _) =>\n            if hasMutator.contains(l) then reqCapture += (l)\n          case _ => super.applyPath(p)\n        \n        override def applyDefn(defn: Defn): Unit = defn match\n          case c: ClsLikeDefn if modOrObj(c) =>\n            handleCalledScope(c.isym)\n            super.applyDefn(defn)\n          case _ => super.applyDefn(defn)\n\n      CaptureInfo(reqCapture, hasReader, hasMutator, mutated)\n    \n    val reqCapture = go(b, Set.empty, Set.empty, Set.empty, Set.empty)(using linearVars = startingVars).reqCapture\n    reqCapture.intersect(thisVars)\n  \n  // entry point\n  val shallowAccesses: Map[ScopedInfo, AccessInfo] =\n    scopeData.scopeTree.root.allChildren.map(obj => obj.toInfo -> findAccessesShallow(obj)).toMap\n  \n  // Optimization: Find all nodes which are accessed by their children\n  // See the comment for findAccesses\n  private val allEdges =\n    for \n      (src, accesses) <- shallowAccesses\n      refd <- accesses.refdDefns\n      if src =/= refd\n    yield\n      (src, refd)\n  \n  private val accessedByChild = allEdges\n    .groupBy(_._2) // group by edge destination\n    .map:\n      case (_: Unit) -> _ => () -> false\n      case d -> edges =>\n        val par = scopeData.getNode(d).ancestor.get.obj.toInfo\n        d -> edges.exists:\n          case a -> b => a =/= par\n    .collect:\n      case d -> true => d\n    .toSet\n  \n  // Searching from the root makes no sense. We instead start searching from each scope nested in the top-level\n  private val (m1, m2) = scopeData.scopeTree.root.children.map(findAccesses).unzip\n  val accessMapWithIgnored = m1.foldLeft[Map[ScopedInfo, AccessInfo]](Map.empty)(_ ++ _)\n  val accessMap = m2.foldLeft[Map[ScopedInfo, AccessInfo]](Map.empty)(_ ++ _)\n  \n  // We make these lazy, because not all users of UsedVarAnalyzer need this analysis. For now, only the lifter needs it.\n  \n  lazy val reqdCaptures: Map[ScopedInfo, Set[Local]] = scopeData.root.children.foldLeft(Map.empty):\n    case (acc, node) => acc ++ reqdCaptureLocals(node)\n  \n  // For local inside a capture, finds the node to which this local belongs.\n  lazy val capturesMap =\n    for\n      case (info -> reqCap) <- reqdCaptures\n      s <- reqCap\n    yield s -> info\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/cpp/Ast.scala",
    "content": "package hkmc2\npackage codegen.cpp\n\nimport mlscript._\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\nimport scala.language.implicitConversions\n\nimport document._\n\nprivate def raw(x: String): Document = doc\"$x\"\ngiven Conversion[String, Document] = x => doc\"$x\"\n\nenum Specifier:\n  case Extern\n  case Static\n  case Inline\n\n  def toDocument = \n    this match\n    case Extern => \"extern\"\n    case Static => \"static\"\n    case Inline => \"inline\"\n\n  override def toString: Str = toDocument\n\nobject Type:\n  def toDocuments(args: Ls[Type], sep: Document, extraTypename: Bool = false): Document =\n    args.map(_.toDocument(extraTypename)).mkDocument(sep)\n\n  def toDocuments(args: Ls[(Str, Type)], sep: Document): Document =\n    args.map(x => doc\"${x._2.toDocument()} ${x._1}\").mkDocument(sep)\n\nenum Type:\n  case Prim(name: Str)\n  case Ptr(inner: Type)\n  case Ref(inner: Type)\n  case Array(inner: Type, size: Opt[Int])\n  case FuncPtr(ret: Type, args: List[Type])\n  case Struct(name: Str)\n  case Enum(name: Str)\n  case Template(name: Str, args: List[Type])\n  case Var(name: Str)\n  case Qualifier(inner: Type, qual: Str)\n\n  def toDocument(extraTypename: Bool = false): Document =\n    def aux(x: Type): Document = x match\n      case Prim(name) => name\n      case Ptr(inner) => doc\"${aux(inner)}*\" \n      case Ref(inner) => doc\"${aux(inner)}&\"\n      case Array(inner, size) => \n        doc\"${aux(inner)}[${size.fold(\"\")(x => x.toString)}]\"\n      case FuncPtr(ret, args) => \n        doc\"${aux(ret)}(${Type.toDocuments(args, sep = \", \")})\"\n      case Struct(name) => doc\"struct $name\"\n      case Enum(name) => doc\"enum $name\"\n      case Template(name, args) =>\n        doc\"$name<${Type.toDocuments(args, sep = \", \")}>\"\n      case Var(name) => name\n      case Qualifier(inner, qual) => doc\"${aux(inner)} $qual\"\n    aux(this)\n\n  override def toString: Str = toDocument().toString\n\nobject Stmt:\n  def toDocuments(decl: Ls[Decl], stmts: Ls[Stmt]): Document =\n    (decl.map(_.toDocument) ++ stmts.map(_.toDocument)).mkDocument(doc\" # \")\n\nenum Stmt:\n  case AutoBind(lhs: Ls[Str], rhs: Expr)\n  case Assign(lhs: Str, rhs: Expr)\n  case Return(expr: Expr)\n  case If(cond: Expr, thenStmt: Stmt, elseStmt: Opt[Stmt])\n  case While(cond: Expr, body: Stmt)\n  case For(init: Stmt, cond: Expr, update: Stmt, body: Stmt)\n  case ExprStmt(expr: Expr)\n  case Break\n  case Continue\n  case Block(decl: Ls[Decl], stmts: Ls[Stmt])\n  case Switch(expr: Expr, cases: Ls[(Expr, Stmt)])\n  case Raw(stmt: Str)\n\n  def toDocument: Document =\n    def aux(x: Stmt): Document = x match\n      case AutoBind(lhs, rhs) =>\n        lhs match\n          case Nil => rhs.toDocument\n          case x :: Nil =>\n            doc\"auto $x = ${rhs.toDocument};\"\n          case _ =>\n            doc\"auto [${lhs.mkDocument(\", \")}] = ${rhs.toDocument};\"\n      case Assign(lhs, rhs) =>\n        doc\"$lhs = ${rhs.toDocument};\"\n      case Return(expr) =>\n        doc\"return ${expr.toDocument};\"\n      case If(cond, thenStmt, elseStmt) =>\n        doc\"if (${cond.toDocument}) ${thenStmt.toDocument}${elseStmt.fold(doc\" \")(x => doc\" else ${x.toDocument}\")}\"\n      case While(cond, body) =>\n        doc\"while (${cond.toDocument}) ${body.toDocument}\"\n      case For(init, cond, update, body) =>\n        doc\"for (${init.toDocument}; ${cond.toDocument}; ${update.toDocument}) ${body.toDocument}\"\n      case ExprStmt(expr) =>\n        doc\"${expr.toDocument};\"\n      case Break => \"break;\"\n      case Continue => \"continue;\"\n      case Block(decl, stmts) => \n        doc\"{ #{  # ${Stmt.toDocuments(decl, stmts)} #}  # }\"\n      case Switch(expr, cases) =>\n        val docCases = cases.map {\n          case (cond, stmt) => doc\"case ${cond.toDocument}: ${stmt.toDocument}\"\n        }.mkDocument(doc\" # \")\n        doc\"switch (${expr.toDocument}) { #{  # ${docCases} #}  # }\"\n      case Raw(stmt) => stmt\n    aux(this)\n\nobject Expr:\n  def toDocuments(args: Ls[Expr], sep: Document): Document =\n    args.map(_.toDocument).mkDocument(sep)\n  \nenum Expr:\n  case Var(name: Str)\n  case IntLit(value: BigInt)\n  case DoubleLit(value: Double)\n  case StrLit(value: Str)\n  case CharLit(value: Char)\n  case Call(func: Expr, args: Ls[Expr])\n  case Member(expr: Expr, member: Str)\n  case Index(expr: Expr, index: Expr)\n  case Unary(op: Str, expr: Expr)\n  case Binary(op: Str, lhs: Expr, rhs: Expr)\n  case Initializer(exprs: Ls[Expr])\n\n  def toDocument: Document =\n    def aux(x: Expr): Document = x match\n      case Var(name) => name\n      case IntLit(value) => value.toString\n      case DoubleLit(value) => value.toString\n      case StrLit(value) => value.escaped\n      case CharLit(value) => value.toInt.toString\n      case Call(func, args) =>\n        doc\"${func.toDocument}(${Expr.toDocuments(args, sep = \", \")})\"\n      case Member(expr, member) => \n        doc\"${expr.toDocument}->$member\"\n      case Index(expr, index) =>\n        doc\"${expr.toDocument}[${index.toDocument}]\"\n      case Unary(op, expr) => \n        doc\"($op${expr.toDocument})\"\n      case Binary(op, lhs, rhs) =>\n        doc\"(${lhs.toDocument} $op ${rhs.toDocument})\"\n      case Initializer(exprs) => \n        doc\"{${Expr.toDocuments(exprs, sep = \", \")}}\"\n    aux(this)\n\ncase class CompilationUnit(includes: Ls[Str], decls: Ls[Decl], defs: Ls[Def]):\n  def toDocument: Document =\n    (includes.map(raw) ++ decls.map(_.toDocument) ++ defs.map(_.toDocument)).mkDocument(doc\" # \")\n  def toDocumentWithoutHidden: Document =\n    val hiddenNames: Set[Str] = Set()\n    defs.filterNot { \n      case Def.StructDef(name, _, _, _, _) => hiddenNames.contains(name.stripPrefix(\"_mls_\"))\n      case _ => false\n    }.map(_.toDocument).mkDocument(doc\" # \")\n\nenum Decl:\n  case StructDecl(name: Str)\n  case EnumDecl(name: Str)\n  case FuncDecl(ret: Type, name: Str, args: Ls[Type], isOverride: Bool, isVirtual: Bool)\n  case VarDecl(name: Str, typ: Type)\n\n  def toDocument: Document =\n    def aux(x: Decl): Document = x match\n      case StructDecl(name) => doc\"struct $name;\"\n      case EnumDecl(name) => doc\"enum $name;\"\n      case FuncDecl(ret, name, args, or, virt) =>\n        val docVirt = (if virt then doc\"virtual \" else doc\"\")\n        val docSpecRet = ret.toDocument()\n        val docArgs = Type.toDocuments(args, sep = \", \")\n        val docOverride = if or then doc\" override\" else doc\"\"\n        doc\"$docVirt$docSpecRet $name($docArgs)$docOverride;\"\n      case VarDecl(name, typ) => \n        doc\"${typ.toDocument()} $name;\"\n    aux(this)\n\nenum Def:\n  case StructDef(name: Str, fields: Ls[(Str, Type)], inherit: Opt[Ls[Str]], methods: Ls[Def], methodsDecl: Ls[Decl])\n  case EnumDef(name: Str, fields: Ls[(Str, Opt[Int])])\n  case FuncDef(specret: Type, name: Str, args: Ls[(Str, Type)], body: Stmt.Block, isOverride: Bool, isVirtual: Bool, in_scope: Opt[Str])\n  case VarDef(typ: Type, name: Str, init: Opt[Expr])\n  case RawDef(raw: Str)\n\n  def toDocument: Document =\n    def aux(x: Def): Document = x match\n      case StructDef(name, fields, inherit, defs, decls) =>\n        val docFirst = doc\"struct $name${inherit.fold(doc\"\")(x => doc\": public ${x.mkDocument(doc\", \")}\")} {\"\n        val docFields = fields.map {\n          case (name, typ) => doc\"${typ.toDocument()} $name;\"\n        }.mkDocument(doc\" # \")\n        val docDefs = defs.map(_.toDocument).mkDocument(doc\" # \")\n        val docDecls = decls.map(_.toDocument).mkDocument(doc\" # \")\n        val docLast = \"};\"\n        doc\"$docFirst #{  # $docFields # $docDefs # $docDecls #}  # $docLast\"\n      case EnumDef(name, fields) =>\n        val docFirst = doc\"enum $name {\"\n        val docFields = fields.map {\n          case (name, value) => value.fold(s\"$name\")(x => s\"$name = $x\")\n        }.mkDocument(doc\" # \")\n        val docLast = \"};\"\n        doc\"$docFirst #{  # $docFields #}  # $docLast\"\n      case FuncDef(specret, name, args, body, or, virt, scope) =>\n        val docVirt = (if virt then doc\"virtual \" else doc\"\")\n        val docSpecRet = specret.toDocument()\n        val docArgs = Type.toDocuments(args, sep = \", \")\n        val docOverride = if or then doc\" override\" else doc\"\"\n        val docBody = body.toDocument\n        val docScope = scope.fold(doc\"\")(x => doc\"$x::\")\n        doc\"$docVirt$docSpecRet $docScope$name($docArgs)$docOverride ${body.toDocument}\"\n      case VarDef(typ, name, init) =>\n        val docTyp = typ.toDocument()\n        val docInit = init.fold(raw(\"\"))(x => doc\" = ${x.toDocument}\")\n        doc\"$docTyp $name$docInit;\"\n      case RawDef(x) => x\n    aux(this)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/cpp/CodeGen.scala",
    "content": "package hkmc2\npackage codegen\npackage cpp\n\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\nimport scala.collection.mutable.ListBuffer\n\nimport llir.{Expr => IExpr, _}\nimport utils.{Scope, TraceLogger}\nimport Scope.scope\nimport semantics._\n\nclass CppCodeGen(builtinClassSymbols: Set[Local], tl: TraceLogger):\n  import tl.{trace, log, logs}\n  def mapName(name: Str): Str = \"_mls_\" + Scope.replaceInvalidCharacters(name)\n  def mapClsLikeName(sym: Local)(using Raise, Scope): Str = \n    if builtinClassSymbols.contains(sym) then sym.nme |> mapName\n    else allocIfNew(sym)\n  def directName(sym: Local): Str = \n    sym.nme |> mapName\n  val mlsValType = Type.Prim(\"_mlsValue\")\n  val mlsUnitValue = Expr.Call(Expr.Var(\"_mlsValue::create<_mls_Unit>\"), Ls());\n  val mlsRetValue  = \"_mls_retval\"\n  def mlsRetValType(n: Int) =\n    if n === 1 then\n      mlsValType\n    else\n      Type.Template(\"std::tuple\", Ls.fill(n)(mlsValType))\n  def mlsRetValueDecl(n: Int) =\n    if n === 1 then\n      Decl.VarDecl(mlsRetValue, mlsValType)\n    else\n      Decl.VarDecl(mlsRetValue, mlsRetValType(n))\n  val mlsMainName = \"_mlsMain\"\n  val mlsPrelude = \"#include \\\"mlsprelude.h\\\"\"\n  val mlsPreludeImpl = \"#include \\\"mlsprelude.cpp\\\"\"\n  val builtinClassSymbolNames = Set(\"Callable\", \"Lazy\")\n  def mlsIsInternalClass(sym: Local) = builtinClassSymbolNames.contains(sym.nme)\n  val mlsObject = \"_mlsObject\"\n  val mlsBuiltin = \"builtin\"\n  val mlsEntryPoint = s\"int main() { return _mlsLargeStack(_mlsMainWrapper); }\";\n  def mlsCallEntry(s: Str) = s\"_mlsValue _mlsMain() { return $s(); }\"\n  def mlsIntLit(x: BigInt) = Expr.Call(Expr.Var(\"_mlsValue::fromIntLit\"), Ls(Expr.IntLit(x)))\n  def mlsStrLit(x: Str) = Expr.Call(Expr.Var(\"_mlsValue::create<_mls_Str>\"), Ls(Expr.StrLit(x)))\n  def mlsDecLit(x: BigDecimal) = Expr.Call(Expr.Var(\"_mlsValue::create<_mls_Float>\"), Ls(Expr.DoubleLit(x.toDouble)))\n  def mlsCharLit(x: Char) = Expr.Call(Expr.Var(\"_mlsValue::fromIntLit\"), Ls(Expr.CharLit(x)))\n  def mlsNewValue(cls: Str, args: Ls[Expr]) = Expr.Call(Expr.Var(s\"_mlsValue::create<$cls>\"), args)\n  def mlsIsValueOf(cls: Str, scrut: Expr) = Expr.Call(Expr.Var(s\"_mlsValue::isValueOf<$cls>\"), Ls(scrut))\n  def mlsIsBoolLit(scrut: Expr, lit: hkmc2.syntax.Tree.BoolLit) = Expr.Call(Expr.Var(\"_mlsValue::isIntLit\"), Ls(scrut, Expr.IntLit(if lit.value then 1 else 0)))\n  def mlsIsIntLit(scrut: Expr, lit: hkmc2.syntax.Tree.IntLit) = Expr.Call(Expr.Var(\"_mlsValue::isIntLit\"), Ls(scrut, Expr.IntLit(lit.value)))\n  def mlsDebugPrint(x: Expr) = Expr.Call(Expr.Var(\"_mlsValue::print\"), Ls(x))\n  def mlsTupleValue(init: Ls[Expr]) = Expr.Call(Expr.Var(\"std::make_tuple\"), init)\n  def mlsAs(name: Str, cls: Str) = Expr.Var(s\"_mlsValue::as<$cls>($name)\")\n  def mlsAsUnchecked(name: Str, cls: Str) = Expr.Var(s\"_mlsValue::cast<$cls>($name)\")\n  def mlsObjectNameMethod(name: Str) = s\"constexpr static inline const char *typeName = \\\"${name}\\\";\"\n  def mlsTypeTag() = s\"constexpr static inline uint32_t typeTag = nextTypeTag();\"\n  def mlsTypeTag(n: Int) = s\"constexpr static inline uint32_t typeTag = $n;\"\n  def mlsCommonCreateMethod(cls: Str, fields: Ls[Str], id: Int) =\n    val parameters = fields.map{x => s\"_mlsValue $x\"}.mkString(\", \")\n    val fieldsAssignment = fields.map{x => s\"_mlsVal->$x = $x; \"}.mkString\n    s\"static _mlsValue create($parameters) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) $cls; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; $fieldsAssignment return _mlsValue(_mlsVal); }\"\n  def mlsCommonPrintMethod(fields: Ls[Str]) =\n    if fields.isEmpty then s\"virtual void print() const override { std::printf(\\\"%s\\\", typeName); }\"\n    else\n      val fieldsPrint = fields.map{x => s\"this->$x.print(); \"}.mkString(\"std::printf(\\\", \\\"); \")\n      s\"virtual void print() const override { std::printf(\\\"%s\\\", typeName); std::printf(\\\"(\\\"); $fieldsPrint std::printf(\\\")\\\"); }\"\n  def mlsCommonDestructorMethod(cls: Str, fields: Ls[Str]) = \n    val fieldsDeletion = fields.map{x => s\"_mlsValue::destroy(this->$x); \"}.mkString\n    s\"virtual void destroy() override { $fieldsDeletion operator delete (this, std::align_val_t(_mlsAlignment)); }\"\n  def mlsThrowNonExhaustiveMatch = Stmt.Raw(\"_mlsNonExhaustiveMatch();\");\n  def mlsCall(fn: Str, args: Ls[Expr]) = Expr.Call(Expr.Var(\"_mlsCall\"), Expr.Var(fn) :: args)\n  def mlsMethodCall(cls: Local, method: Str, args: Ls[Expr])(using Raise, Scope) =\n    Expr.Call(Expr.Member(Expr.Call(Expr.Var(s\"_mlsMethodCall<${cls |> mapClsLikeName}>\"), Ls(args.head)), method), args.tail)\n  def mlsThisCall(cls: Local, method: Str, args: Ls[Expr])(using Raise, Scope) =\n    Expr.Call(Expr.Member(Expr.Var(\"this\"), method), args)\n  def mlsFnWrapperName(fn: Str) = s\"_mlsFn_$fn\"\n  def mlsFnCreateMethod(fn: Str) = s\"static _mlsValue create() { static _mlsFn_$fn mlsFn alignas(_mlsAlignment); mlsFn.refCount = stickyRefCount; mlsFn.tag = typeTag; return _mlsValue(&mlsFn); }\"\n  def mlsNeverValue(n: Int) = if (n <= 1) then Expr.Call(Expr.Var(s\"_mlsValue::never\"), Ls()) else Expr.Call(Expr.Var(s\"_mlsValue::never<$n>\"), Ls())\n  val mlsThis = Expr.Var(\"_mlsValue(this, _mlsValue::inc_ref_tag{})\") // first construct a value, then incRef()\n\n  case class Ctx(\n    fieldCtx: Set[Local],\n  )\n\n  def getVar(l: Local)(using Raise, Scope): String = l match\n    case ts: hkmc2.semantics.TermSymbol =>\n      ts.owner match\n      case S(owner) => scope.lookup_!(ts, N)\n      case N => scope.lookup_!(ts, N)\n    case ts: hkmc2.semantics.InnerSymbol =>\n      scope.lookup_!(ts, N)\n    case _ => scope.lookup_!(l, N)\n\n  def allocIfNew(l: Local)(using Raise, Scope): Str =\n    trace[Str](s\"allocIfNew $l begin\", r => s\"allocIfNew $l end -> $r\"):\n      if scope.lookup(l).isDefined then\n        getVar(l) |> mapName\n      else\n        scope.allocateName(l) |> mapName\n  \n  def codegenClassInfo(using Ctx, Raise, Scope)(cls: ClassInfo) =\n    trace[(Opt[Def], Decl, Ls[Def])](s\"codegenClassInfo ${cls.symbol} begin\"):\n      val fields = cls.fields.map{x => (x |> directName, mlsValType)}\n      cls.fields.foreach(x => scope.allocateName(x))\n      val parents = if cls.parents.nonEmpty then cls.parents.toList.map(mapClsLikeName) else mlsObject :: Nil\n      val decl = Decl.StructDecl(cls.symbol |> mapClsLikeName)\n      if mlsIsInternalClass(cls.symbol) then (None, decl, Ls.empty)\n      else\n        val methods = cls.methods.map:\n          case (name, defn) =>\n            val (cdef, decl) = codegenDefn(using Ctx(summon[Ctx].fieldCtx ++ cls.fields))(defn)\n            val cdef2 = cdef match\n              case x: Def.FuncDef if builtinApply.contains(defn.name.nme) => x.copy(name = defn.name |> directName, in_scope = Some(cls.symbol |> mapClsLikeName))\n              case x: Def.FuncDef => x.copy(in_scope = Some(cls.symbol |> mapClsLikeName))\n              case _ => throw new Exception(s\"codegenClassInfo: unexpected def $cdef\")\n            val decl2 = decl match\n              case x: Decl.FuncDecl if builtinApply.contains(defn.name.nme) => x.copy(isVirtual = true, name = defn.name |> directName)\n              case x: Decl.FuncDecl => x.copy(isVirtual = true)\n              case _ => throw new Exception(s\"codegenClassInfo: unexpected decl $decl\")\n            log(s\"codegenClassInfo: ${cls.symbol} method ${defn.name} $decl2\")\n            (cdef2, decl2)\n        val theDef = Def.StructDef(\n          cls.symbol |> mapClsLikeName, fields,\n          if parents.nonEmpty then Some(parents) else None,\n          Ls(Def.RawDef(mlsObjectNameMethod(cls.symbol.nme)),\n            Def.RawDef(mlsTypeTag()),\n            Def.RawDef(mlsCommonPrintMethod(cls.fields.map(directName))),\n            Def.RawDef(mlsCommonDestructorMethod(cls.symbol |> mapClsLikeName, cls.fields.map(directName))),\n            Def.RawDef(mlsCommonCreateMethod(cls.symbol |> mapClsLikeName, cls.fields.map(directName), cls.id))),\n          methods.iterator.map(_._2).toList\n        )\n        (S(theDef), decl, methods.iterator.map(_._1).toList)\n  \n  def toExpr(texpr: TrivialExpr, reifyUnit: Bool = false)(using Ctx, Raise, Scope): Opt[Expr] = texpr match\n    case IExpr.Ref(name) if summon[Ctx].fieldCtx.contains(name) => S(Expr.Var(name |> directName))\n    case IExpr.Ref(name: BuiltinSymbol) if name.nme === \"<this>\" => S(mlsThis)\n    case IExpr.Ref(name) => S(Expr.Var(name |> allocIfNew))\n    case IExpr.Literal(hkmc2.syntax.Tree.BoolLit(x)) => S(mlsIntLit(if x then 1 else 0))\n    case IExpr.Literal(hkmc2.syntax.Tree.IntLit(x)) => S(mlsIntLit(x))\n    case IExpr.Literal(hkmc2.syntax.Tree.DecLit(x)) => S(mlsDecLit(x))\n    case IExpr.Literal(hkmc2.syntax.Tree.StrLit(x)) => S(mlsStrLit(x))\n    case IExpr.Literal(hkmc2.syntax.Tree.UnitLit(_)) => if reifyUnit then S(mlsUnitValue) else None\n  \n  def toExpr(texpr: TrivialExpr)(using Ctx, Raise, Scope): Expr = texpr match\n    case IExpr.Ref(name) if summon[Ctx].fieldCtx.contains(name) => Expr.Var(name |> directName)\n    case IExpr.Ref(name: BuiltinSymbol) if name.nme === \"<this>\" => mlsThis\n    case IExpr.Ref(name) => Expr.Var(name |> allocIfNew)\n    case IExpr.Literal(hkmc2.syntax.Tree.BoolLit(x)) => mlsIntLit(if x then 1 else 0)\n    case IExpr.Literal(hkmc2.syntax.Tree.IntLit(x)) => mlsIntLit(x)\n    case IExpr.Literal(hkmc2.syntax.Tree.DecLit(x)) => mlsDecLit(x)\n    case IExpr.Literal(hkmc2.syntax.Tree.StrLit(x)) => mlsStrLit(x)\n    case IExpr.Literal(hkmc2.syntax.Tree.UnitLit(_)) => mlsUnitValue\n  \n\n  def wrapMultiValues(exprs: Ls[TrivialExpr])(using Ctx, Raise, Scope): Expr = exprs match\n    case x :: Nil => toExpr(x, reifyUnit = true).get\n    case _ => \n      val init = exprs.map{x => toExpr(x)}\n      mlsTupleValue(init)\n  \n  def codegenCaseWithIfs(scrut: TrivialExpr, cases: Ls[(Pat, Node)], default: Opt[Node], storeInto: Str)(using decls: Ls[Decl], stmts: Ls[Stmt])(using Ctx, Raise, Scope): (Ls[Decl], Ls[Stmt]) =\n    val scrut2 = toExpr(scrut)\n    val init: Stmt = \n      default.fold(mlsThrowNonExhaustiveMatch)(x => {\n        val (decls2, stmts2) = codegen(x, storeInto)(using Ls.empty, Ls.empty[Stmt])\n        Stmt.Block(decls2, stmts2)\n      })\n    val stmt = cases.foldRight(S(init)) {\n      case ((Pat.Class(cls), arm), nextarm) =>\n        val (decls2, stmts2) = codegen(arm, storeInto)(using Ls.empty, Ls.empty[Stmt])\n        val stmt = Stmt.If(mlsIsValueOf(cls |> mapClsLikeName, scrut2), Stmt.Block(decls2, stmts2), nextarm)\n        S(stmt)\n      case ((Pat.Lit(i @ hkmc2.syntax.Tree.IntLit(_)), arm), nextarm) =>\n        val (decls2, stmts2) = codegen(arm, storeInto)(using Ls.empty, Ls.empty[Stmt])\n        val stmt = Stmt.If(mlsIsIntLit(scrut2, i), Stmt.Block(decls2, stmts2), nextarm)\n        S(stmt)\n      case ((Pat.Lit(i @ hkmc2.syntax.Tree.BoolLit(_)), arm), nextarm) =>\n        val (decls2, stmts2) = codegen(arm, storeInto)(using Ls.empty, Ls.empty[Stmt])\n        val stmt = Stmt.If(mlsIsBoolLit(scrut2, i), Stmt.Block(decls2, stmts2), nextarm)\n        S(stmt)\n      case _ => TODO(\"codegenCaseWithIfs doesn't support these patterns currently\")\n    }\n    (decls, stmt.fold(stmts)(x => stmts :+ x))\n\n  def codegenJumpWithCall(func: Local, args: Ls[TrivialExpr], storeInto: Opt[Str])(using decls: Ls[Decl], stmts: Ls[Stmt])(using Ctx, Raise, Scope): (Ls[Decl], Ls[Stmt]) =\n    val call = Expr.Call(Expr.Var(func |> allocIfNew), args.map(toExpr))\n    val stmts2 = stmts ++ Ls(storeInto.fold(Stmt.Return(call))(x => Stmt.Assign(x, call)))\n    (decls, stmts2)\n\n  def codegenOps(op: BuiltinSymbol, args: Ls[TrivialExpr])(using Ctx, Raise, Scope) = \n    trace[Expr](s\"codegenOps $op begin\"):\n      var op2 = op.nme\n      if op2 === \"===\" then\n        op2 = \"==\"\n      else if op2 === \"!===\" then\n        op2 = \"!=\"\n      if op.binary && args.length === 2 then \n        Expr.Binary(op2, toExpr(args(0)), toExpr(args(1)))\n      else if op.unary && args.length === 1 then\n        Expr.Unary(op2, toExpr(args(0)))\n      else\n        TODO(s\"codegenOps ${op.nme} ${args.size} ${op.binary} ${op.unary} ${args.map(_.show).mkString(\", \")}\")\n\n\n  def codegen(expr: IExpr)(using Ctx, Raise, Scope): Expr = expr match\n    case x @ (IExpr.Ref(_) | IExpr.Literal(_)) => toExpr(x, reifyUnit = true).get\n    case IExpr.CtorApp(cls, args) => mlsNewValue(cls |> mapClsLikeName, args.map(toExpr))\n    case IExpr.Select(name, cls, field) if field.forall(_.isDigit) => \n      Expr.Member(mlsAsUnchecked(name |> allocIfNew, cls |> mapClsLikeName), s\"field${field}\" |> mapName)\n    case IExpr.Select(name, cls, field) => Expr.Member(mlsAsUnchecked(name |> allocIfNew, cls |> mapClsLikeName), field |> mapName)\n    case IExpr.BasicOp(name, args) => codegenOps(name, args)\n    case IExpr.AssignField(assignee, cls, field, value) => TODO(\"codegen assign field\")\n\n  def codegenBuiltin(names: Ls[Local], builtin: Str, args: Ls[TrivialExpr])(using Ctx, Raise, Scope): Ls[Stmt] = builtin match\n    case \"error\" => Ls(Stmt.Raw(\"throw std::runtime_error(\\\"Error\\\");\"), Stmt.AutoBind(names.map(allocIfNew), mlsNeverValue(names.size)))\n    case _ => Ls(Stmt.AutoBind(names.map(allocIfNew), Expr.Call(Expr.Var(\"_mls_builtin_\" + builtin), args.map(toExpr))))\n\n  lazy val builtinApply = Set(\n    \"apply0\",\n    \"apply1\",\n    \"apply2\",\n    \"apply3\",\n    \"apply4\",\n    \"apply5\",\n    \"apply6\",\n    \"apply7\",\n    \"apply8\",\n    \"apply9\",\n  )\n  \n  def codegen(body: Node, storeInto: Str)(using decls: Ls[Decl], stmts: Ls[Stmt])(using Ctx, Raise, Scope): (Ls[Decl], Ls[Stmt]) =\n    trace[(Ls[Decl], Ls[Stmt])](s\"codegen $body begin\"):\n      body match\n      case Node.Result(res) => \n        val expr = wrapMultiValues(res)\n        val stmts2 = stmts ++ Ls(Stmt.Assign(storeInto, expr))\n        (decls, stmts2)\n      case Node.Jump(defn, args) =>\n        codegenJumpWithCall(defn, args, S(storeInto))\n      case Node.Panic(msg) => (decls, stmts :+ Stmt.Raw(s\"throw std::runtime_error(\\\"$msg\\\");\"))\n      case Node.LetExpr(name, expr, body) =>\n        val stmts2 = stmts ++ Ls(Stmt.AutoBind(Ls(name |> allocIfNew), codegen(expr)))\n        codegen(body, storeInto)(using decls, stmts2)\n      case Node.LetCall(names, bin: BuiltinSymbol, IExpr.Literal(syntax.Tree.StrLit(s)) :: tail, body) if bin.nme === \"<builtin>\" =>\n        val stmts2 = stmts ++ codegenBuiltin(names, s.replace(\"\\\"\", \"\"), tail)\n        codegen(body, storeInto)(using decls, stmts2)\n      case Node.LetMethodCall(names, cls, method, IExpr.Ref(bin: BuiltinSymbol) :: args, body) if bin.nme === \"<this>\" =>\n        val call = mlsThisCall(cls, method |> directName, args.map(toExpr))\n        val stmts2 = stmts ++ Ls(Stmt.AutoBind(names.map(allocIfNew), call))\n        codegen(body, storeInto)(using decls, stmts2)\n      case Node.LetMethodCall(names, cls, method, args, body) if builtinApply.contains(method.nme) =>\n        val call = mlsMethodCall(cls, method |> directName, args.map(toExpr))\n        val stmts2 = stmts ++ Ls(Stmt.AutoBind(names.map(allocIfNew), call))\n        codegen(body, storeInto)(using decls, stmts2)\n      case Node.LetMethodCall(names, cls, method, args, body) =>\n        val call = mlsMethodCall(cls, method |> allocIfNew, args.map(toExpr))\n        val stmts2 = stmts ++ Ls(Stmt.AutoBind(names.map(allocIfNew), call))\n        codegen(body, storeInto)(using decls, stmts2)\n      case Node.LetCall(names, defn, args, body) =>\n        val call = Expr.Call(Expr.Var(defn |> allocIfNew), args.map(toExpr))\n        val stmts2 = stmts ++ Ls(Stmt.AutoBind(names.map(allocIfNew), call))\n        codegen(body, storeInto)(using decls, stmts2)\n      case Node.Case(scrut, cases, default) =>\n        codegenCaseWithIfs(scrut, cases, default, storeInto)\n    \n  def codegenDefn(using Ctx, Raise, Scope)(defn: Func): (Def, Decl) = defn match\n    case Func(id, name, params, resultNum, body) =>\n      val decls = Ls(mlsRetValueDecl(resultNum))\n      val stmts = Ls.empty[Stmt]\n      val (decls2, stmts2) = codegen(body, mlsRetValue)(using decls, stmts)\n      val stmtsWithReturn = stmts2 :+ Stmt.Return(Expr.Var(mlsRetValue))\n      val theDef = Def.FuncDef(mlsRetValType(resultNum), name |> allocIfNew, params.map(x => (x |> allocIfNew, mlsValType)), Stmt.Block(decls2, stmtsWithReturn), false, false, None)\n      val decl = Decl.FuncDecl(mlsRetValType(resultNum), name |> allocIfNew, params.map(x => mlsValType), false, false)\n      (theDef, decl)\n\n  // Topological sort of classes based on inheritance relationships\n  def sortClasses(prog: Program)(using Raise, Scope): Ls[ClassInfo] =\n    var depgraph = prog.classes.map(x => (x.symbol, x.parents)).toMap\n      ++ builtinClassSymbols.map(x => (x, List.empty[Symbol]))\n    log(s\"depgraph: $depgraph\")\n    var degree = depgraph.view.mapValues(_.size).toMap\n    def removeNode(node: Symbol) =\n      degree -= node\n      depgraph -= node\n      depgraph = depgraph.view.mapValues(_.filter(_ =/= node)).toMap\n      degree = depgraph.view.mapValues(_.size).toMap\n    val sorted = ListBuffer.empty[ClassInfo]\n    given Ordering[Local] with\n      def compare(x: Local, y: Local): Int = x.nme.compareTo(y.nme)\n    var work = degree.filter(_._2 === 0).keys.toSortedSet\n    while work.nonEmpty do\n      val node = work.head\n      work -= node\n      prog.classes.find(x => (x.symbol) === node).foreach(sorted.addOne)\n      removeNode(node)\n      val next = degree.filter(_._2 === 0).keys.toSortedSet\n      work ++= next\n    if depgraph.nonEmpty then\n      val cycle = depgraph.keys.mkString(\", \")\n      throw new Exception(s\"Cycle detected in class hierarchy: $cycle\")\n    sorted.toList\n\n  def codegen(prog: Program)(using Raise, Scope): CompilationUnit =\n    val sortedClasses = sortClasses(prog)\n    val fieldCtx = Set.empty[Local]\n    given Ctx = Ctx(fieldCtx)\n    val (defs, decls, methodsDef) = sortedClasses.map(codegenClassInfo).unzip3\n    val (defs2, decls2) = prog.defs.map(codegenDefn).unzip\n    CompilationUnit(Ls(mlsPrelude), decls ++ decls2, defs.flatten ++ defs2 ++ methodsDef.flatten :+ Def.RawDef(mlsCallEntry(prog.entry |> allocIfNew)) :+ Def.RawDef(mlsEntryPoint))\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/cpp/CompilerHost.scala",
    "content": "package hkmc2.codegen.cpp\n\nimport mlscript._\nimport mlscript.utils.shorthands._\nimport scala.collection.mutable.ListBuffer\n\nfinal class CppCompilerHost(val auxPath: Str, val output: Str => Unit):\n  import scala.sys.process._\n  private def ifAnyCppCompilerExists(): Boolean =\n    Seq(\"g++\", \"--version\").! == 0 || Seq(\"clang++\", \"--version\").! == 0\n\n  private def isMakeExists(): Boolean =\n    import scala.sys.process._\n    Seq(\"make\", \"--version\").! == 0\n\n  val ready = ifAnyCppCompilerExists() && isMakeExists()\n  \n  def compileAndRun(src: Str): Unit =\n    if !ready then\n      return\n    val srcPath = os.temp(contents = src, suffix = \".cpp\")\n    val binPath = os.temp(suffix = \".mls.out\")\n    var stdout = ListBuffer[Str]()\n    var stderr = ListBuffer[Str]()\n    val buildLogger = ProcessLogger(stdout :+= _, stderr :+= _)\n    val buildResult = Seq(\"make\", \"-B\", \"-C\", auxPath, \"auto\", s\"SRC=$srcPath\", s\"DST=$binPath\") ! buildLogger\n    if buildResult != 0 then\n      output(\"Compilation failed: \")\n      for line <- stdout do output(line)\n      for line <- stderr do output(line)\n      return\n  \n    stdout.clear()\n    stderr.clear()\n    val runCmd = Seq(binPath.toString)\n    val runResult = runCmd ! buildLogger\n    if runResult != 0 then\n      output(\"Execution failed: \")\n      for line <- stdout do output(line)\n      for line <- stderr do output(line)\n      return\n\n    output(\"Execution succeeded: \")\n    for line <- stdout do output(line)"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Deforest.scala",
    "content": "package hkmc2\npackage codegen\npackage deforest\n\nimport utils.*\nimport mlscript.utils.*, shorthands.*\nimport semantics.*\nimport scala.collection.mutable.{Set as MutSet, Map as MutMap, LinkedHashMap}\nimport hkmc2.codegen.flowAnalysis.*\n\nsealed abstract class FinalDest\ncase class FinalDestMatch(dtor: CtorDtorId, sels: Set[CtorDtorId]) extends FinalDest\ncase class FinalDestSel(dtors: Set[CtorDtorId], field: SelField) extends FinalDest\n\nclass DeforestFusionSolver(val constraintSolver: FlowConstraintSolver):\n  given preAnalyzer: FlowPreAnalyzer = constraintSolver.preAnalyzer\n  given fState: FlowAnalysis.State = constraintSolver.fState\n  given eState: Elaborator.State = constraintSolver.eState\n  given tl: TraceLogger = constraintSolver.tl\n\n  private def selAndDtorIsSameConsumer(dtor: CtorDtorId, sels: Iterable[CtorDtorId]): Boolean =\n    sels.forall:\n      case CtorDtorId(selExpr, instId) =>\n        instId == dtor.instId &&\n        preAnalyzer.res.getEnclosingMatchesForSel(selExpr).exists(_._1 == dtor.exprId) &&\n        selExpr.getResult.matches:\n          case TrackableSelect(from, _, _) => from === dtor.exprId.getResult\n  \n  val finalCtorDests = LinkedHashMap.empty[CtorDtorId, FinalDest]\n  val finalDtorSrcs = LinkedHashMap.empty[CtorDtorId, Set[CtorDtorId]]\n  val fusingCtorInfo = MutMap.empty[CtorDtorId, ConcreteProducer]\n  val fusingDtorInfo = MutMap.empty[CtorDtorId, ConcreteConsumer]\n  \n  locally {\n    def mergeDests(dests: Set[ConcreteConsumer | NoCons.type]): Opt[FinalDest] =\n      def selsSelectingTheSameSymbol(sels: Set[FieldSel]) =\n        sels.map(s => s.field).size == 1\n      if dests.contains(NoCons) then N\n      else\n        val (dtors, sels) = dests.partitionMap:\n          case d: Dtor => Left(d)\n          case fs: FieldSel => Right(fs)\n          case _ => die\n        if dtors.size == 0 && selsSelectingTheSameSymbol(sels) then\n          S(FinalDestSel(\n            sels.map(_.toCtorDtorId),\n            sels.head.field\n          ))\n        else if dtors.size != 1 then N\n        else\n          val dtor = dtors.head\n          if selAndDtorIsSameConsumer(\n            dtor.toCtorDtorId,\n            sels.map(s => s.toCtorDtorId)\n          ) then\n            S(FinalDestMatch(\n              CtorDtorId(dtor.scrutExprId, dtor.instantiationId.get),\n              sels.map: s =>\n                CtorDtorId(s.exprId, s.instantiationId.get)\n            ))\n          else N\n    end mergeDests\n\n    val prodRoots =\n      for\n        (ctor, dests) <- constraintSolver.ctorDests\n        if mergeDests(dests).isEmpty\n      yield ctor\n    val consRoots =\n      for\n        (dtor, srcs) <- constraintSolver.dtorSrcs\n        if srcs.contains(NoProd)\n      yield dtor\n\n    val result = FlowWebComputation[ConcreteProducer, ConcreteConsumer](\n      p => constraintSolver.ctorDests(p).collect:\n        case c: ConcreteConsumer => c,\n      c => constraintSolver.dtorSrcs(c).collect:\n        case p: ConcreteProducer => p,\n      prodRoots,\n      consRoots,\n    )\n    val toRemoveCtor = result.markedProducers\n    val toRemoveDtor = result.markedConsumers\n\n    for\n      (ctor, dests) <- constraintSolver.ctorDests\n      if !toRemoveCtor(ctor)\n    do\n      finalCtorDests(ctor.toCtorDtorId) = mergeDests(dests).get\n      fusingCtorInfo(ctor.toCtorDtorId) = ctor\n    for\n      (dtor, srcs) <- constraintSolver.dtorSrcs\n      if !toRemoveDtor(dtor)\n    do\n      finalDtorSrcs(dtor.toCtorDtorId) =\n        // srcs are always ConcreteProducers after constraint solving\n        srcs.map(_.asInstanceOf[ConcreteProducer].toCtorDtorId)\n      fusingDtorInfo(dtor.toCtorDtorId) = dtor\n  }\n\n  tl.log(\">>> fusing >>>\")\n  for case (c, dest) <- finalCtorDests do\n    tl.log(s\"${c.pp} ->\")\n    dest match\n    case FinalDestMatch(dtor, sels) =>\n      tl.log(s\"\\t${dtor.pp}\")\n      for s <- sels.toSeq.sortBy(_.exprId) do tl.log(s\"\\t${s.pp}\")\n    case FinalDestSel(dtors, field) =>\n      tl.log(s\"\\t${field}\")\n  tl.log(\"<<< fusing <<<\")\nend DeforestFusionSolver\n\n\nobject Deforest:\n  def apply(p: Program)(using\n    cfg: Config,\n    tl: TL,\n    raise: Raise,\n    eState: Elaborator.State,\n  ): Program =\n    // TODO: handle see through imported modules\n    val flowAnalysisRes = FlowAnalysis(p, mono = cfg.deforest.exists(_.mono))\n    val solver = new DeforestFusionSolver(flowAnalysisRes)\n    if solver.finalCtorDests.isEmpty && solver.finalDtorSrcs.isEmpty then p\n    else\n      val rewrite = new DeforestRewriter(solver)\n      rewrite()\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/deforest/Rewrite.scala",
    "content": "package hkmc2\npackage codegen\npackage deforest\n\nimport utils.*\nimport mlscript.utils.*, shorthands.*\nimport semantics.*\nimport syntax.Tree\nimport scala.collection.mutable.{Set as MutSet, Map as MutMap, LinkedHashMap, Buffer}\nimport hkmc2.syntax.Fun\nimport hkmc2.codegen.flowAnalysis.*\n\n\n\nclass DeforestRewriter(val solver: DeforestFusionSolver)(using Raise):\n  \n  def apply(): Program =\n    if newBody is pre.pgrm.main then pre.pgrm\n    else Program(pre.pgrm.imports, newBody)\n  \n  val collector = solver.constraintSolver.collector\n  given tl: TraceLogger = solver.tl\n  given fState: FlowAnalysis.State = solver.fState\n  given eState: Elaborator.State = solver.eState\n  given pre: FlowPreAnalyzer = solver.preAnalyzer\n  \n  type MatchOrLabelId = ResultId | LabelSymbol\n  type BranchId = CtorDtorId -> Opt[CtorCls]\n  type LabelId = LabelSymbol -> InstantiationId\n  type RestFunId = CtorDtorId | LabelId\n  \n  extension (restFunId: RestFunId) def withoutInstId: MatchOrLabelId =\n    restFunId match\n    case CtorDtorId(exprId, instId) => exprId\n    case l: LabelId => l._1\n  extension (restFunId: RestFunId) def getInstId = restFunId match\n    case CtorDtorId(exprId, instId) => instId\n    case l: LabelId => l._2\n  extension (matchOrLabelId: MatchOrLabelId) def withInstId(instId: InstantiationId): RestFunId =\n    matchOrLabelId match\n    case l: LabelSymbol => l -> instId\n    case scrutId => CtorDtorId(scrutId.asInstanceOf[ResultId], instId)\n  extension (vs: Ls[VarSymbol]) def asParamList: ParamList =\n    ParamList(ParamListFlags.empty, vs.map(Param.simple), N)\n  extension (c: CtorCls) def ctorClsName: String = c match\n    case cls: ClassLikeSymbol => cls.nme\n    case n: Int => s\"tup$n\"\n  extension (f: SelField) def fieldName: String = f match\n    case tSym: TermSymbol => tSym.nme\n    case n: Int => n.toString\n\n  private def getParentLabelOrMatchesAndRestBefore(\n    matchOrLabelId: MatchOrLabelId\n  ): (Iterator[Label | Match], Block) =\n    val ctx = matchOrLabelId match\n      case label: LabelSymbol => pre.res.labelSymToCtxOfLabel(label)\n      case dtorId: ResultId => pre.res.matchScrutToCtxOfMatch(dtorId)\n    val simpleRest = matchOrLabelId match\n      case label: LabelSymbol => pre.res.labelSymToLabelBlk(label).rest\n      case dtorId: ResultId => pre.res.matchScrutToMatchBlock(dtorId).rest\n    def it = ctx.iterator\n      .takeWhile:\n        case _: (pre.InCtx.Fn | pre.InCtx.ModCtor | pre.InCtx.Cls | pre.InCtx.ClsPreCtor | pre.InCtx.ClsCtor | pre.InCtx.TopLvl) => false\n        case _ => true\n      .collect:\n        case pre.InCtx.LblBody(l) => l\n        case pre.InCtx.MtchBody(m, _) => m\n        case pre.InCtx.BegnBody(b) => b\n    val blockUntilParent = it\n      .takeWhile(_.isInstanceOf[Begin])\n      .collect:\n        case b: Begin => b.rest\n      .foldLeft(simpleRest)(Begin.apply)\n    val parents = it\n      .collect:\n        case l: Label => l\n        case m: Match => m\n      .asInstanceOf[Iterator[Label | Match]]\n    parents -> blockUntilParent\n\n  private val _symSubst = SymbolSubst.Id\n  \n  val newPolyFnSyms = LinkedHashMap.empty[InstantiationId, Map[TermSymbol, (BlockMemberSymbol, TermSymbol)]]\n  val branchSelSyms = MutMap.empty[CtorDtorId, VarSymbol]\n  // branch fun params for fields (which share the same symbol in `branchSelSyms`)\n  val branchFunParamFieldSyms = MutMap.empty[BranchId, Ls[VarSymbol]]\n  val ctorWhichBranch = MutMap.empty[CtorDtorId, BranchId]\n  \n  // Symbols of branch functions\n  // the content of those functions should be\n  // `<computation of the branch>; return match_rest(...)`\n  val branchFunSyms = LinkedHashMap.empty[BranchId, (BlockMemberSymbol, TermSymbol)]\n  \n  // Symbols of rest functions for relevant matches or labels.\n  // 1) Matches that will be fused or\n  // 2) Matches or Labels that properly nest other fusing matches\n  // should get their \"rest\"s extracted as functions,\n  // and the content of those functions should be\n  // `<computation of rests up to a parent>; return parent_rest(...)`\n  val restFunSyms = LinkedHashMap.empty[RestFunId, (BlockMemberSymbol, TermSymbol)]\n  \n  // original bodies of a branch\n  val branchOriginalBodies = MutMap.empty[ResultId -> Opt[CtorCls], Block]\n  // original rest function bodies and their parent matches (if any)\n  val restOriginalBodiesAndParentRest = MutMap.empty[MatchOrLabelId, Block -> Opt[MatchOrLabelId]]\n  \n  // compute new symbols\n  locally {\n    def mkNewPolyFnSyms(path: List[ResultId], refedFun: ResultId): Unit =\n      val groupFuns = collector.funToSccGroups(refedFun.getReferredFun.get)\n      newPolyFnSyms.getOrElseUpdate(\n        path,\n        groupFuns\n          .map: f =>\n            val name = path.mkFunName + s\"$$${f.nme}\"\n            f -> (\n              new BlockMemberSymbol(name, Nil, true),\n              new TermSymbol(Fun, N, Tree.Ident(name)))\n          .toMap)\n    end mkNewPolyFnSyms\n    \n    for case (ctor, finalDest) <- solver.finalCtorDests do\n      finalDest match\n      case FinalDestSel(dtors, field) =>\n        // create poly fun syms\n        val instIds = (dtors + ctor).toList.sortBy(_.exprId).map(_.instId)\n        for\n          ctorInstId <- instIds\n          case path@(pathTo :+ refedFun) <- ctorInstId.inits\n          // skip synthesized instIds — those rewrite in-place\n          if !collector.synthesizedInstIdToFunSym.contains(path)\n        do mkNewPolyFnSyms(path, refedFun)\n      case FinalDestMatch(dest, sels) =>\n        val ctorInfo = solver.fusingCtorInfo(ctor)\n\n        // create poly fun syms\n        for\n          ctorInstId <- List(ctor.instId, dest.instId)\n          case path@(pathTo :+ refedFun) <- ctorInstId.inits\n          // skip synthesized instIds — those rewrite in-place\n          if !collector.synthesizedInstIdToFunSym.contains(path)\n        do mkNewPolyFnSyms(path, refedFun)\n        \n        // create branch sel syms\n        val fieldSym = MutMap.empty[SelField, VarSymbol]\n        for sel <- sels.toList.sortBy(_._1) do\n          branchSelSyms.getOrElseUpdate(\n            sel,\n            locally:\n              val selInfo = solver.fusingDtorInfo(sel).asInstanceOf[FieldSel]\n              val clsNme = selInfo.selectsFrom.ctorClsName\n              fieldSym.getOrElseUpdate(\n                selInfo.field,\n                new VarSymbol(Tree.Ident(s\"${clsNme}_${selInfo.field.fieldName}\")))\n          )\n        \n        // ctor dest branch function computations\n        val matchBlk = pre.res.matchScrutToMatchBlock(dest._1)\n        val (whichBranch, whichBranchPreBody) =\n          val tmp =\n            val ctorCls = ctorInfo.ctor\n            matchBlk.arms\n              .find: (cse, _) =>\n                cse match\n                case Case.Cls(cls, path) => cls === ctorCls\n                case Case.Tup(len, inf) => len === ctorCls\n                case _ => die\n              .map(b => ctorCls -> b._2)\n          tmp.map(_._1) ->\n          tmp.fold(matchBlk.dflt.get)(_._2)\n        val destBranchId: BranchId = dest -> whichBranch\n        // identify the dest branchid for a ctor\n        ctorWhichBranch(ctor) = destBranchId\n        // compute the function symbols for branch funs\n        branchFunSyms.getOrElseUpdate(\n          destBranchId,\n          locally:\n            val branchName = whichBranch.fold(\"_dflt\")(c => s\"_${c.ctorClsName}\")\n            val scrutName = dest._1.getReferredSym.nme\n            val branchFnNme = s\"${dest.instId.mkFunName}$$$scrutName$branchName\"\n            new BlockMemberSymbol(branchFnNme, Nil, true)\n            -> new TermSymbol(Fun, N, Tree.Ident(branchFnNme))\n        )\n        // compute the function parameters corresponding to ctor fields of branch funs\n        branchFunParamFieldSyms.getOrElseUpdate(\n          destBranchId,\n          locally:\n            val completeArgs: Ls[SelField] = ctorInfo.args.unzip._1\n            val selsInfos: Map[SelField, CtorDtorId] = sels\n              .iterator\n              .map: sel =>\n                solver.fusingDtorInfo(sel).asInstanceOf[FieldSel].field -> sel\n              .toMap\n            completeArgs.map: selField =>\n              selsInfos.get(selField) match\n              case Some(selId) => branchSelSyms(selId)\n              case None => VarSymbol(Tree.Ident(s\"_${selField.fieldName}\"))\n        )\n        \n        val (parents, _) = getParentLabelOrMatchesAndRestBefore(dest.exprId)\n        for needRest <- Iterator.single(pre.res.matchScrutToMatchBlock(dest._1)) ++ parents do\n          val (matchOrLabelId, nme) = needRest match\n            case Match(scrut, arms, dflt, rest) => scrut.uid -> scrut.uid.getReferredSym.nme\n            case Label(label, loop, body, rest) => label -> label.nme\n          val restFunId = matchOrLabelId.withInstId(dest.instId)\n          restFunSyms.getOrElseUpdate(\n            restFunId,\n            locally:\n              val restFunName = dest.instId.mkFunName + s\"$$${nme}_rest\"\n              new BlockMemberSymbol(restFunName, Nil, true)\n              -> new TermSymbol(Fun, N, Tree.Ident(restFunName))\n          )\n          val (ps, restBeforeParent) = getParentLabelOrMatchesAndRestBefore(matchOrLabelId)\n          restOriginalBodiesAndParentRest.getOrElseUpdate(\n            matchOrLabelId,\n            restBeforeParent\n            -> ps.nextOption().map:\n              case Match(scrut, arms, dflt, rest) => scrut.uid\n              case Label(label, loop, body, rest) => label\n          )\n        \n        // compute the complete deforestable branch body of a fusing match\n        branchOriginalBodies.getOrElseUpdate(\n          dest._1 -> whichBranch,\n          whichBranchPreBody\n        )\n  }\n  \n  // compute free vars after we know new symbols\n  val dtorBranchFnFvs = MutMap.empty[CtorDtorId, Ls[Symbol]]\n  val restFnFvs = MutMap.empty[RestFunId, Ls[Symbol]]\n  locally {\n    val allBranchesOfDtor = branchFunSyms.keys.groupBy(_._1)\n    extension (b: Block)\n      // ctx should be the branch fun parameters corresponding to ctor fields \n      def deforestFreeVars(\n        ctx: collection.Set[Symbol],\n        instId: InstantiationId\n      ): collection.Set[Symbol] =\n        val traverser = new FreeVarTraverser(ctx, instId)\n        traverser.applyBlock(b)\n        traverser.freeVars\n        \n    class FreeVarTraverser(ctx: collection.Set[Symbol], instId: InstantiationId) extends BlockTraverser:\n      extension (resId: ResultId) def toCtorDtorId = CtorDtorId(resId, instId)\n      val inCtx = MutSet.from[Symbol]:\n        ctx\n        ++ newPolyFnSyms.values.flatMap(_.values.unzip._1)\n        ++ branchFunSyms.values.unzip._1\n        ++ eState.builtinOpsMap.values\n        ++ (eState.globalThisSymbol :: eState.runtimeSymbol :: eState.noSymbol :: Nil)\n        ++ locally:\n          pre.pgrm.main match\n          case Scoped(syms, _) => syms\n          case _ => Nil\n      val freeVars = MutSet.empty[Symbol]\n      \n      private def handleTrackableSel(s: Result) =\n        val toBeSubstSymbol = branchSelSyms(s.uid.toCtorDtorId)\n        if !inCtx(toBeSubstSymbol) then freeVars.add(toBeSubstSymbol)\n      \n      override def applyValue(v: Value): Unit =\n        v match\n        case Value.Ref(l, disamb) if !inCtx(l) && l.asClsLike.isEmpty => freeVars.add(l)\n        case _ => super.applyValue(v)\n      \n      override def applyResult(r: Result): Unit =\n        r match\n        case s@TrackableSelect(_, _, _) if branchSelSyms.isDefinedAt(s.uid.toCtorDtorId) =>\n          handleTrackableSel(s)\n        case Lambda(params, body) =>\n          for p <- params.allParams do inCtx.add(p.sym)\n          applyBlock(body)\n          for p <- params.allParams do inCtx.remove(p.sym)\n        case _ => super.applyResult(r)\n      \n      override def applyPath(p: Path): Unit =\n        p match\n        case s@TrackableSelect(_, _, _) if branchSelSyms.isDefinedAt(s.uid.toCtorDtorId) =>\n          handleTrackableSel(s)\n        case _ => super.applyPath(p)\n      \n      override def applyBlock(b: Block): Unit =\n        b match\n        case m: Match if solver.finalDtorSrcs.isDefinedAt(m.scrut.uid.toCtorDtorId) =>\n          for\n            fv <- fvsForDtor(m.scrut.uid.toCtorDtorId)\n            if !inCtx(fv)\n          do freeVars.add(fv)\n          super.applyPath(m.scrut)\n        case Assign(lhs, rhs, rest) =>\n          if !inCtx(lhs) then freeVars.add(lhs)\n          applyResult(rhs)\n          applyBlock(rest)\n        case Scoped(syms, body) =>\n          for s <- syms do inCtx.add(s)\n          applyBlock(body)\n          for s <- syms do inCtx.remove(s)\n        case _ => super.applyBlock(b)\n      \n      override def applyDefn(defn: Defn): Unit =\n        defn match\n        case fDef: FunDefn =>\n          inCtx.add(fDef.sym)\n          for p <- fDef.params.flatMap(_.allParams) do inCtx.add(p.sym)\n          applyBlock(fDef.body)\n          for p <- fDef.params.flatMap(_.allParams) do inCtx.remove(p.sym)\n        case cDef: ClsLikeDefn =>\n          inCtx.add(cDef.sym)\n          val ps = (cDef.auxParams ++ cDef.paramsOpt).flatMap(_.params).map(_.sym)\n          for p <- ps do inCtx.add(p)\n          super.applyDefn(cDef)\n          for p <- ps do inCtx.remove(p)\n        case vDef: ValDefn =>\n          inCtx.add(vDef.sym)\n          super.applyDefn(defn)\n    end FreeVarTraverser\n    \n    def fvsForDtor(dtorId: CtorDtorId): Ls[Symbol] =\n      dtorBranchFnFvs.get(dtorId) match\n      case Some(fvs) => fvs\n      case None =>\n        val fvsOfBranches = allBranchesOfDtor(dtorId)\n          .flatMap: branchId =>\n            branchOriginalBodies(branchId._1._1 -> branchId._2)\n              .deforestFreeVars(\n                branchFunParamFieldSyms(branchId).toSet,\n                branchId._1._2)\n          .toSortedSet(using Ordering.by[Symbol, Uid[Symbol]](_.uid))\n          .toList\n        val fvsOfRest = fvsForRest(dtorId)\n        val fvs = fvsOfBranches ++ fvsOfRest\n        dtorBranchFnFvs(dtorId) = fvs\n        fvs\n    \n    def fvsForRest(restFunId: RestFunId): Ls[Symbol] =\n      restFnFvs.get(restFunId) match\n      case Some(fvs) => fvs\n      case None =>\n        val instId = restFunId.getInstId\n        val (restBody, parentRest) = restOriginalBodiesAndParentRest(restFunId.withoutInstId)\n        val fvOfRestBody = restBody.deforestFreeVars(Set.empty, restFunId.getInstId).toList.sortBy(_.uid)\n        val fvOfRestParent = parentRest.fold(List.empty)(pr => fvsForRest(pr.withInstId(instId)))\n        val fvs = fvOfRestBody ++ fvOfRestParent\n        restFnFvs(restFunId) = fvs\n        fvs\n    \n    allBranchesOfDtor.keysIterator.foreach(fvsForDtor)\n  }\n  \n  // compute new program body\n  val newBody =\n    \n    extension (a: Symbol) def toValueRef =\n      a match\n      case bms: BlockMemberSymbol => Value.Ref(bms, bms.tsym)\n      case _ => Value.Ref(a, N)\n    def mkReturnCall(target: (BlockMemberSymbol, TermSymbol), args: Ls[Symbol]): Block =\n      Return(Call(\n        Value.Ref(target._1, S(target._2)),\n        args.map(a => Arg(N, a.toValueRef)) ne_:: Nil\n      )(true, false, false), false)\n    \n    class Rewriter(instId: InstantiationId) extends BlockTransformer(_symSubst):\n      extension (resId: ResultId) def toCtorDtorId = CtorDtorId(resId, instId)\n      \n      private def ctorLamFvs(ctorId: CtorDtorId): Ls[VarSymbol] =\n        // only for ctors that are fused with a match\n        val dtorId = solver.finalCtorDests(ctorId).asInstanceOf[FinalDestMatch].dtor\n        dtorBranchFnFvs(dtorId).map(s => new VarSymbol(Tree.Ident(s\"fv_ctorLam_${s.nme}\")))\n      \n      private def newRefId(refId: ResultId, refSym: TermSymbol) =\n        instId match\n        case Nil => refId :: Nil\n        case pathTo :+ called =>\n          val lastRefedSymbol = called.getReferredFun.get\n          val funToSccRepMap = collector.funToSccRep\n          (funToSccRepMap(lastRefedSymbol), funToSccRepMap(refSym)) match\n            case (Some(a), Some(b)) if a is b => instId\n            case _ => instId :+ refId\n        case _ => die\n      override def applyResult(r: Result)(k: Result => Block): Block =\n        r match\n        case s@TrackableSelect(from, _, _) =>\n          if branchSelSyms.isDefinedAt(s.uid.toCtorDtorId) then\n            k(Value.Ref(branchSelSyms(s.uid.toCtorDtorId)))\n          else if solver.finalDtorSrcs.contains(s.uid.toCtorDtorId) then\n            applyPath(from)(k)\n          else\n            super.applyResult(r)(k)\n        case ctor@CtorCall(cls, args) =>\n          def mkCtorFieldSyms(ctorDtorId: CtorDtorId): Ls[TempSymbol] =\n            val ctorInfo = solver.fusingCtorInfo(ctorDtorId)\n            val clsNme = ctorInfo.ctor.ctorClsName\n            ctorInfo.args.unzip._1.map: f =>\n              new TempSymbol(N, s\"${clsNme}_${f.fieldName}\")\n          end mkCtorFieldSyms\n          \n          solver.finalCtorDests.get(ctor.uid.toCtorDtorId) match\n          case None => super.applyResult(ctor)(k)\n          case Some(FinalDestSel(_, field)) =>\n            val ctorInfo = solver.fusingCtorInfo(ctor.uid.toCtorDtorId)\n            val idx = ctorInfo.args.unzip._1.indexOf(field)\n            val fieldSyms = mkCtorFieldSyms(ctor.uid.toCtorDtorId)\n            args.zip(fieldSyms).foldRight(k(Value.Ref(fieldSyms(idx)))):\n              case (Arg(N, a) -> s, rest) =>\n                applyPath(a): fusedField =>\n                  Scoped(Set.single(s), Assign(s, fusedField, rest))\n              case _ => TODO(\"spread args are not supported\")\n          case Some(_: FinalDestMatch) =>\n            val fieldSyms = mkCtorFieldSyms(ctor.uid.toCtorDtorId)\n            val (branchBms, branchTermSym) = branchFunSyms(ctorWhichBranch(ctor.uid.toCtorDtorId))\n            val ctorLamParams = ctorLamFvs(ctor.uid.toCtorDtorId)\n            val callBranchFun =\n              Lambda(\n                ctorLamParams.asParamList,\n                mkReturnCall((branchBms, branchTermSym), ctorLamParams ++ fieldSyms))\n            args.zip(fieldSyms).foldRight(k(callBranchFun)):\n              case (Arg(N, a) -> fieldSym, rest) =>\n                applyPath(a): fusedField =>\n                  Scoped(Set.single(fieldSym), Assign(fieldSym, fusedField, rest))\n              case _ => TODO(\"spread args are not supported\")\n        case _ => super.applyResult(r)(k)\n      \n      override def applyPath(p: Path)(k: Path => Block): Block =\n        p match\n        case ref@FunRef(f) if newPolyFnSyms.isDefinedAt(newRefId(ref.uid, f)) =>\n          val (bms, tSym) = newPolyFnSyms(newRefId(ref.uid, f))(f)\n          k(Value.Ref(bms, S(tSym)))\n        case ctor@CtorCall(_, args) if solver.finalCtorDests.isDefinedAt(ctor.uid.toCtorDtorId) =>\n          assert(args.isEmpty)\n          val (branchBms, branchTermSym) = branchFunSyms(ctorWhichBranch(ctor.uid.toCtorDtorId))\n          val ctorLamParams = ctorLamFvs(ctor.uid.toCtorDtorId)\n          val lambdaSym = new TempSymbol(N, \"deforest$lam\")\n          Scoped(\n            Set.single(lambdaSym),\n            Assign(\n              lambdaSym,\n              Lambda(\n                ctorLamParams.asParamList,\n                mkReturnCall((branchBms, branchTermSym), ctorLamParams)),\n              k(Value.Ref(lambdaSym, N)))\n          )\n        case s@TrackableSelect(from, _, _) =>\n          if branchSelSyms.isDefinedAt(s.uid.toCtorDtorId) then\n            k(Value.Ref(branchSelSyms(s.uid.toCtorDtorId)))\n          else if solver.finalDtorSrcs.contains(s.uid.toCtorDtorId) then\n            applyPath(from)(k)\n          else\n            super.applyPath(s)(k)\n        case _ => super.applyPath(p)(k)\n      \n      override def applyBlock(b: Block): Block =\n        b match\n        case m@Match(scrut, _, _, _) if solver.finalDtorSrcs.isDefinedAt(scrut.uid.toCtorDtorId) =>\n          val callWithFvs = dtorBranchFnFvs(scrut.uid.toCtorDtorId)\n          applyPath(scrut): newScrut =>\n            Return(\n              Call(newScrut, callWithFvs.map(s => Arg(N, s.toValueRef)) ne_:: Nil)(true, false, false),\n              false)\n        case Break(label) =>\n          val labelRestFunId = label.withInstId(instId)\n          restFunSyms.get(labelRestFunId) match\n          case None => super.applyBlock(b)\n          case Some(labelRestFunSym) =>\n            val labelRestFunFvs = restFnFvs(labelRestFunId)\n            mkReturnCall(labelRestFunSym, labelRestFunFvs)\n        case Return(res, true) => super.applyBlock(Return(res, false))\n        case _ => super.applyBlock(b)\n    end Rewriter\n    \n    class RefreshSymbol(existingMapping: Map[Symbol, Symbol]) extends SymbolRefresher(existingMapping):\n      override def applyScopedBlock(b: Block): Block =\n        b match\n        case Scoped(syms, body) =>\n          syms.foreach: sym =>\n            sym match\n              case bms: BlockMemberSymbol =>\n                assert(bms.tsym.forall(_.owner.isEmpty))\n              case _ =>\n        case _ =>\n        super.applyScopedBlock(b)\n      override def applyBlock(b: Block): Block =\n        b match\n        case Label(label, loop, body, rest) =>\n          assert(!loop)\n        case Continue(label) => TODO(\"unsupported `continue` instruction during rewriting\")\n        case _ =>\n        super.applyBlock(b)\n      override def applyValue(v: Value)(k: Value => Block): Block = v match\n        case Value.Ref(l, x) =>\n          pre.res.modSymToBms.get(l) match\n            case Some(bms) =>\n              k(Value.Ref(bms, l.asMod))\n            case None => super.applyValue(v)(k)\n        case _ => super.applyValue(v)(k)\n    end RefreshSymbol\n    \n    val newPolyFuns =\n      for\n        (instId, funSymMap) <- newPolyFnSyms\n        (referringFun, (bms, tSym)) <- funSymMap.toList.sortBy(_._1.uid)\n      yield\n        val fDefn = pre.res.funSymToFunDefn(referringFun)\n        val transformedBody = new Rewriter(instId).applyBlock(fDefn.body)\n        // refresh other local symbols: for funs, we can check existing scoped blocks and\n        // there is no need to add scoped blocks, because function bodies now already are scoped\n        val refreshParamMap = MutMap.empty[VarSymbol, VarSymbol]\n        val refreshedParams = fDefn.params.map: pl =>\n          ParamList(\n            pl.flags,\n            pl.params.map: p =>\n              val newSym = new VarSymbol(Tree.Ident(p.sym.name))\n              refreshParamMap(p.sym) = newSym\n              Param(p.flags, newSym, p.sign, p.modulefulness),\n            pl.restParam)\n        val bodyWithCorrectSymbols = new RefreshSymbol(refreshParamMap.toMap).applyBlock(transformedBody)\n        FunDefn(\n          N, bms, tSym, refreshedParams,\n          bodyWithCorrectSymbols)(N, fDefn.annotations)\n    end newPolyFuns\n    \n    val newBranchFuns =\n      for (branchId@(dtorId, whichBranch), (bms, tSym)) <- branchFunSyms yield\n        val instId = dtorId.getInstId\n        val ogBody = branchOriginalBodies(dtorId.exprId -> whichBranch)\n        val restFunSym = restFunSyms(dtorId)\n        val restFunArgs = restFnFvs(dtorId)\n        val actualBody = Begin(\n          new Rewriter(instId).applyBlock(ogBody),\n          mkReturnCall(restFunSym, restFunArgs))\n        val refreshedFvSymbols = dtorBranchFnFvs(branchId._1).map(s => s -> new VarSymbol(Tree.Ident(s\"fv_${s.nme}\")))\n        val bodyWithCorrectSymbols = new RefreshSymbol(refreshedFvSymbols.toMap).applyBlock(actualBody)\n        FunDefn(N, bms, tSym,\n          (refreshedFvSymbols.unzip._2 ++ branchFunParamFieldSyms(branchId)).asParamList :: Nil,\n          bodyWithCorrectSymbols\n        )(N, annotations = Nil)\n    end newBranchFuns\n    \n    val newRestFuns =\n      for (restFunId, (bms, tsym)) <- restFunSyms yield\n        val instId = restFunId.getInstId\n        val (ogBody, parent) = restOriginalBodiesAndParentRest(restFunId.withoutInstId)\n        val transformedOgBody = new Rewriter(instId).applyBlock(ogBody)\n        val actualBody = parent match\n          case Some(parentRestId) =>\n            val parentRestFunId = parentRestId.withInstId(instId)\n            val parentFunSym = restFunSyms(parentRestFunId)\n            val parentFunFvs = restFnFvs(parentRestFunId)\n            Begin(\n              transformedOgBody,\n              mkReturnCall(parentFunSym, parentFunFvs))\n          case None =>\n            Begin(transformedOgBody, Return(Value.Lit(Tree.UnitLit(true)), false))\n        val refreshedFvSymbols = restFnFvs(restFunId).map(s => s -> new VarSymbol(Tree.Ident(s\"fv_${s.nme}\")))\n        val bodyWithCorrectSymbols = new RefreshSymbol(refreshedFvSymbols.toMap).applyBlock(actualBody)\n        FunDefn(N, bms, tsym, refreshedFvSymbols.unzip._2.asParamList :: Nil, bodyWithCorrectSymbols)(N, annotations = Nil)\n    end newRestFuns\n\n    val inplaceRewrittenFunBodies = Map.from[TermSymbol, Block]:\n      for (selfInstId, funSym) <- collector.synthesizedInstIdToFunSym yield\n        val fDefn = pre.res.funSymToFunDefn(funSym)\n        funSym -> new Rewriter(selfInstId).applyBlock(fDefn.body)\n\n    val newMainBody =\n      object mainRewriter extends Rewriter(Nil):\n        override def applyFunDefn(fun: FunDefn): FunDefn =\n          inplaceRewrittenFunBodies.get(fun.dSym) match\n            case Some(rewrittenBody) =>\n              FunDefn(fun.owner, fun.sym, fun.dSym, fun.params, rewrittenBody)(fun.configOverride, fun.annotations)\n            case None => super.applyFunDefn(fun)\n      object implicitRetPass extends BlockTransformerShallow(_symSubst):\n        override def applyBlock(b: Block): Block = b match\n          case Return(res, false) => Return(res, true)\n          case _ => super.applyBlock(b)\n      Scoped(\n        Set.from(newPolyFuns.map(_.sym) ++ newBranchFuns.map(_.sym) ++ newRestFuns.map(_.sym)),\n        implicitRetPass.applyBlock(mainRewriter.applyBlock(pre.pgrm.main)))\n    \n    (newPolyFuns ++ newBranchFuns ++ newRestFuns).foldRight(newMainBody): (fdef, rest) =>\n      Define(fdef, rest)\n    \n  end newBody\n  \nend DeforestRewriter\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/flowAnalysis/FlowAnalysis.scala",
    "content": "package hkmc2\npackage codegen\npackage flowAnalysis\n\nimport scala.jdk.CollectionConverters.MapHasAsScala\nimport utils.*\nimport mlscript.utils.*, shorthands.*\nimport semantics.*\nimport syntax.Tree\nimport scala.collection.mutable\nimport scala.collection.mutable.{Set as MutSet, Map as MutMap, LinkedHashMap, LinkedHashSet}\n\n\nobject FlowAnalysis:\n  class State:\n    val resultToResultId = new java.util.IdentityHashMap[Result, Uid[Result]].asScala\n    val resultIdToResult = mutable.Map.empty[Uid[Result], Result]\n    object ResultUidState extends Uid.Result.State\n  \n    extension (instId: InstantiationId)\n      def mkFunName(using Elaborator.State): String =\n        instId\n          .map: i =>\n            s\"${i.getReferredFun.get.name}_$i\"\n          .mkString(\"_\")\n    \n    extension (resultId: ResultId)\n      def getResult = resultIdToResult(resultId)\n      def getReferredSym: Symbol =\n        resultId.getResult match\n        case Value.Ref(s, _) => s\n        case e => lastWords(s\"assumption failed: $e is not a Value.Ref\")\n      def getReferredFun(using Elaborator.State): Option[TermSymbol] =\n        resultId.getResult match\n        case FunRef(f) => Some(f)\n        case _ => None\n    \n    extension (r: Result)\n      def uid = resultToResultId.get(r) match\n        case None =>\n          val id = ResultUidState.nextUid\n          resultIdToResult(id) = r\n          resultToResultId(r) = id\n          id\n        case Some(id) => id\n  \n  \n  def apply(pgrm: Program, mono: Bool)(using TraceLogger, Elaborator.State, Raise) =\n    given State = new State\n    val pre = new FlowPreAnalyzer(pgrm)\n    val constrCol = new FlowConstraintsCollector(pre, mono)\n    new FlowConstraintSolver(constrCol)\n    \nend FlowAnalysis\n\n\ntype ResultId = Uid[Result]\ntype InstantiationId = Ls[ResultId]\ntype CtorCls = ClassLikeSymbol | Int\ntype SelField = TermSymbol | Int\ntype FunId = (funSym: Symbol, whichParamList: Int) | ResultId\n\nobject RefLike:\n  private def classCtorSymbol(sym: Symbol)(using Elaborator.State): Opt[ClassSymbol | ModuleOrObjectSymbol] =\n    sym.asObj orElse\n    sym.asTrm.flatMap: tSym =>\n      for\n        cls <- tSym.owner.flatMap(_.asCls)\n        clsDef <- cls.defn\n        ctorSym <- clsDef.ctorSym\n        if ctorSym is tSym\n      yield\n        cls\n  \n  def unapply(p: Value.Ref | Select)(using Elaborator.State): Opt[Symbol] =\n    p match\n      case Value.Ref(l, disamb) =>\n        val sym = disamb.getOrElse(l)\n        classCtorSymbol(sym) orElse S(sym)\n      case s: Select =>\n        s.symbol.flatMap: selSym =>\n          classCtorSymbol(selSym) orElse\n          locally:\n            for\n              selTermSym <- selSym.asTrm\n              owner <- selTermSym.owner\n              _ <- owner.asMod\n            yield\n              selTermSym\n\nobject TrackableFieldSelect:\n  def unapply(s: Select): Opt[Path -> (field: TermSymbol, owner: ClassSymbol)] =\n    s.symbol match\n    case S(sSym) if sSym.asTrm.exists(_.decl.exists(_.isInstanceOf[Param])) =>\n      val tSym = sSym.asTrm.get\n      for\n        owner <- tSym.owner\n        cls <- owner.asCls\n        if cls.tree.clsParams.size === 1\n      yield s.qual -> (tSym, cls)\n    case _ => N\n\nobject PossibleTrackableTupleSelect:\n  def unapply(s: Result)(using eState: Elaborator.State): Opt[Value.Ref -> Int] =\n    s match\n    case Call(\n      Select(Select(Value.Ref(runtimeSym, N), Tree.Ident(\"Tuple\")), Tree.Ident(\"get\")),\n      (Arg(N, ref@Value.Ref(scrut, N)) :: Arg(N, Value.Lit(Tree.IntLit(n))) :: Nil) :: Nil\n    ) if runtimeSym is eState.runtimeSymbol => S(ref -> n.toInt)\n    case _ => N\n\nobject TrackableSelect:\n  def unapply(s: Result)(using pre: FlowPreAnalyzer, eState: Elaborator.State): Opt[(from: Path, field: SelField, owner: CtorCls)] =\n    given fState: FlowAnalysis.State = pre.fState\n    s match\n    case sel@PossibleTrackableTupleSelect((ref@Value.Ref(scrut, N)) -> ith) =>\n      pre.res.getEnclosingMatchesForSel(sel.uid).find(_._1.getReferredSym is scrut).flatMap:\n        case (_, Some(tupSize: Int)) => S(ref, ith, tupSize)\n        case _ => N\n    case TrackableFieldSelect(qual, field -> owner) =>\n      Some((qual, field, owner))\n    case _ => N\n\nobject CtorRef:\n  def unapply(s: Path)(using Elaborator.State): Option[ClassSymbol | ModuleOrObjectSymbol] =\n    s match\n      case RefLike(s) => s.asCls orElse s.asObj\n      case _ => None\n\nobject CtorCall:\n  def unapply(r: Result)(using Elaborator.State): Option[(ClassSymbol | ModuleOrObjectSymbol | Int) -> Ls[Arg]] =\n    r match\n    case Instantiate(_, CtorRef(ctor), argss) => Some(ctor -> argss.flatten)\n    case Call(CtorRef(ctor), argss) => Some(ctor -> argss.flatten)\n    case CtorRef(ctor) if ctor.asObj.isDefined => Some(ctor -> Nil)\n    case Tuple(_, args) => Some(args.size, args)\n    case _ => None\n\nobject FunRef:\n  def unapply(s: Path)(using Elaborator.State): Option[TermSymbol] = s match\n    case RefLike(tSym: TermSymbol) if tSym.k is syntax.Fun => Some(tSym)\n    case _ => None\n\ntype StratVarId = Uid[StratVar]\n\nclass StratVarState(val uid: StratVarId, val name: Str, val generatedForFun: Opt[TermSymbol]):\n  lazy val asProdStrat = ProdVar(this)\n  lazy val asConsStrat = ConsVar(this)\n  override def toString(): String = s\"${if name.isEmpty() then \"$stratvar\" else name}@${uid}@$generatedForFun\"\n\nobject StratVarState:\n  def freshVar(nme: String)(using vuid: Uid.StratVar.State): StratVarState =\n    val newId = vuid.nextUid\n    StratVarState(newId, nme, N)\n  def freshVar(nme: String, generatedForFun: TermSymbol)(using vuid: Uid.StratVar.State): StratVarState =\n    val newId = vuid.nextUid\n    StratVarState(newId, s\"${nme}_for_${generatedForFun.nme}\", S(generatedForFun))\n  def freshVar(nme: String, forFunOpt: Opt[TermSymbol])(using vuid: Uid.StratVar.State): StratVarState =\n    forFunOpt match\n    case None => freshVar(nme)\n    case Some(forFun) => freshVar(nme, forFun)\n\ntrait StratVar(s: StratVarState):\n  this: ProdVar | ConsVar =>\n  def asProdStrat = s.asProdStrat\n  def asConsStrat = s.asConsStrat\n  def uid = s.uid\n\nsealed abstract class ProdStrat\ncase class ProdVar(s: StratVarState) extends ProdStrat with StratVar(s)\nclass ProdFun(\n  val funId: FunId,\n  val instantiationId: Opt[InstantiationId]\n)(\n  val params: Ls[ConsStrat],\n  val restParam: Opt[ConsStrat],\n  val res: ProdStrat\n) extends ProdStrat:\n  override def toString(): String =\n    s\"(${params.map(_.toString()).mkString(\", \")}) -> ${res.toString()}\"\n\ncase object NoProd extends ProdStrat\n\nclass Ctor(\n  val exprId: ResultId,\n  val instantiationId: Opt[InstantiationId]\n)(\n  val ctor: CtorCls,\n  val args: Ls[SelField -> ProdStrat]\n) extends ProdStrat with ToCtorDtorId(exprId, instantiationId):\n  override def toString(): String =\n    s\"$ctor(${args.map(_.toString()).mkString(\", \")})\"\n\nsealed abstract class ConsStrat\ncase class ConsVar(s: StratVarState) extends ConsStrat with StratVar(s)\nclass ConsFun(\n  val exprId: ResultId,\n  val instantiationId: Opt[InstantiationId]\n)(\n  val params: Ls[ProdStrat],\n  val res: ConsStrat\n) extends ConsStrat:\n  override def toString(): String =\n    s\"(${params.map(_.toString()).mkString(\", \")}) -> ${res.toString()}\"\n\ncase object NoCons extends ConsStrat\n\nclass FieldSel(\n  val exprId: ResultId,\n  val instantiationId: Opt[InstantiationId]\n)(\n  val field: SelField,\n  val selectsFrom: CtorCls,\n  val consVar: ConsVar\n) extends ConsStrat with ToCtorDtorId(exprId, instantiationId)\n\nclass Dtor(\n  val scrutExprId: ResultId,\n  val instantiationId: Opt[InstantiationId]\n) extends ConsStrat with ToCtorDtorId(scrutExprId, instantiationId)\n\nsealed trait ToCtorDtorId(exprId: ResultId, instId: Opt[InstantiationId]):\n  def toCtorDtorId = CtorDtorId(exprId, instId.get)\n\ncase class CtorDtorId(exprId: ResultId, instId: InstantiationId):\n  def pp(using FlowAnalysis.State) = s\"${exprId.getResult}\"\n\ntype ConcreteProducer = Ctor\ntype ConcreteConsumer = Dtor | FieldSel\n\nclass ProdStratScheme(val s: StratVarState, val constraints: Ls[ProdStrat -> ConsStrat])\n\nclass FlowPreAnalyzer(val pgrm: Program)(using\n  val tl: TraceLogger,\n  val eState: Elaborator.State,\n  val fState: FlowAnalysis.State,\n  val raise: Raise\n) extends BlockTraverser:\n  given stratVarUidState: Uid.StratVar.State = new Uid.StratVar.State\n  import StratVarState.freshVar\n  \n  ctxTracker.inTopLvl:\n    applyBlock(pgrm.main)\n  \n  object res:\n    val primitiveStratVar = StratVarState.freshVar(\"unknown\")\n    val rootFunDefns = LinkedHashSet.empty[FunDefn]\n    val funSymToFunDefn = MutMap.empty[TermSymbol, FunDefn]\n    val matchScrutToMatchBlock = MutMap.empty[ResultId, Match]\n    val labelSymToLabelBlk = MutMap.empty[Symbol, Label]\n    val matchScrutToCtxOfMatch = MutMap.empty[ResultId, Ls[InCtx]]\n    val labelSymToCtxOfLabel = MutMap.empty[Symbol, Ls[InCtx]]\n    val selToCtxOfSel = MutMap.empty[ResultId, Ls[InCtx]]\n    val modSymToBms = MutMap.empty[Symbol, BlockMemberSymbol]\n    val generatedProdVars = MutMap.empty[Symbol, StratVarState]\n    lazy val rootFunSyms: collection.Set[TermSymbol] = rootFunDefns.map(_.dSym).toSet\n    def getEnclosingMatchesForSel(selExprId: ResultId) =\n      selToCtxOfSel.get(selExprId).fold(Iterator.empty):\n        _.iterator\n        .collect:\n          case InCtx.MtchBody(m, cse) => m.scrut.uid -> cse\n        \n  end res\n  \n  enum InCtx:\n    case TopLvl()\n    case Mod(mod: ClsLikeBody)\n    case ModCtor(mod: ClsLikeBody)\n    case Cls(cls: ClsLikeDefn)\n    case ClsPreCtor(cls: ClsLikeDefn)\n    case ClsCtor(cls: ClsLikeDefn)\n    case Fn(f: FunDefn)\n    case LblBody(l: Label)\n    case MtchBody(m: Match, cse: Opt[CtorCls])\n    case BegnBody(b: Begin)\n    case Scped(s: Scoped)\n  \n  private object ctxTracker:\n    private var ctx: Ls[InCtx] = Nil\n    private def isTopLvlLikeFunCtx(ctx0: Ls[InCtx]): Boolean =\n      ctx0.forall:\n        case InCtx.TopLvl() => true\n        case InCtx.Mod(_) => true\n        case InCtx.ModCtor(_) => true\n        case InCtx.BegnBody(_) => true\n        case InCtx.Scped(_) => true\n        case _ => false\n  \n    def getAllCtx = ctx\n    def isTopLvlLikeModuleCtx: Boolean =\n      ctx.forall:\n        case InCtx.TopLvl() => true\n        case InCtx.BegnBody(_) => true\n        case InCtx.Scped(_) => true\n        case _ => false\n    def registerStratVar(sym: Symbol, nme: String): Unit =\n      val currentRootFun = ctx.tails.collectFirst:\n        case InCtx.Fn(fun) :: tl if isTopLvlLikeFunCtx(tl) => fun.dSym\n      res.generatedProdVars.getOrElseUpdate(sym, freshVar(nme, currentRootFun))\n    \n    private inline def withCtx(newCtx: InCtx)(inline body: => Any)(after: => Unit = ()): Unit =\n      ctx = newCtx :: ctx\n      body\n      ctx = ctx.tail\n      after\n    \n    inline def inMod(mod: ClsLikeBody)(inline body: => Any) =\n      withCtx(InCtx.Mod(mod))(body)()\n    \n    inline def inFun(fun: FunDefn)(inline body: => Any) =\n      withCtx(InCtx.Fn(fun))(body):\n        res.funSymToFunDefn(fun.dSym) = fun\n        if isTopLvlLikeFunCtx(ctx) then\n          res.rootFunDefns.add(fun)\n    \n    inline def inLabelBody(label: Label)(inline body: => Any) =\n      withCtx(InCtx.LblBody(label))(body):\n        res.labelSymToLabelBlk.addOne(label.label -> label)\n        res.labelSymToCtxOfLabel.addOne(label.label -> ctx)\n    \n    inline def inMatchBody(m: Match, cse: Opt[CtorCls])(inline body: => Any) =\n      withCtx(InCtx.MtchBody(m, cse))(body):\n        res.matchScrutToMatchBlock.addOne(m.scrut.uid -> m)\n        res.matchScrutToCtxOfMatch.addOne(m.scrut.uid -> ctx)\n    \n    inline def inBeginBody(begin: Begin)(inline body: => Any) =\n      withCtx(InCtx.BegnBody(begin))(body)()\n    \n    inline def inScoped(scpd: Scoped)(inline body: => Any) =\n      withCtx(InCtx.Scped(scpd))(body)()\n    \n    inline def inTopLvl(inline body: => Any) =\n      assert(ctx.isEmpty)\n      withCtx(InCtx.TopLvl())(body):\n        assert(ctx.isEmpty)\n    \n    inline def inModCtor(mod: ClsLikeBody)(inline body: => Any) =\n      assert(ctx.head.matches{ case _: InCtx.Mod => true })\n      withCtx(InCtx.ModCtor(mod))(body):\n        assert(ctx.head.matches{ case _: InCtx.Mod => true })\n    \n    inline def inCls(cls: ClsLikeDefn)(inline body: => Any) =\n      withCtx(InCtx.Cls(cls))(body)()\n    \n    inline def inClsPreCtor(cls: ClsLikeDefn)(inline body: => Any) =\n      withCtx(InCtx.ClsPreCtor(cls))(body)()\n    \n    inline def inClsCtor(cls: ClsLikeDefn)(inline body: => Any) =\n      withCtx(InCtx.ClsCtor(cls))(body)()\n  \n  end ctxTracker\n  \n  override def applyBlock(b: Block): Unit = b match\n    case scpd@Scoped(syms, body) =>\n      for s <- syms do\n        s match\n        case s: BlockMemberSymbol => ()\n        case _ => ctxTracker.registerStratVar(s, s.nme)\n      ctxTracker.inScoped(scpd):\n        applyBlock(body)\n    case m@Match(scrut, arms, dflt, rest) =>\n      applyPath(scrut)\n      for (cse, body) <- arms do\n        val cseCls = cse match\n          case Case.Cls(cls, _) => S(cls)\n          case Case.Tup(n, false) => S(n)\n          case _ => N\n        ctxTracker.inMatchBody(m, cseCls):\n          applyBlock(body)\n      for dft <- dflt do\n        ctxTracker.inMatchBody(m, N):\n          applyBlock(dft)\n      applyBlock(rest)\n    case Return(res, implct) => applyResult(res)\n    case lbl@Label(label, loop, body, rest) =>\n      ctxTracker.inLabelBody(lbl):\n        applyBlock(body)\n      applyBlock(rest)\n    case bgn@Begin(sub, rest) =>\n      ctxTracker.inBeginBody(bgn):\n        applyBlock(sub)\n      applyBlock(rest)\n    case Assign(lhs, rhs, rest) =>\n      applyResult(rhs)\n      applyBlock(rest)\n    case Define(defn, rest) =>\n      applyDefn(defn)\n      applyBlock(rest)\n    case Throw(exc) => applyResult(exc)\n    case Break(label) => ()\n    case Continue(label) => ()\n    case TryBlock(sub, finallyDo, rest) =>\n      applyBlock(sub)\n      applyBlock(finallyDo)\n      applyBlock(rest)\n    case AssignField(lhs, nme, rhs, rest) =>\n      applyPath(lhs)\n      applyResult(rhs)\n      applyBlock(rest)\n    case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>\n      applyPath(lhs)\n      applyPath(fld)\n      applyResult(rhs)\n      applyBlock(rest)\n    case End(_) => ()\n    case Unreachable(_) => ()\n  \n  override def applyResult(r: Result): Unit = r match\n    case tupSel@PossibleTrackableTupleSelect(_, _) =>\n      res.selToCtxOfSel.addOne(tupSel.uid -> ctxTracker.getAllCtx)\n    case Call(fun, argss) =>\n      applyPath(fun)\n      argss.foreach(_.foreach(applyArg))\n    case Instantiate(mut, cls, argss) =>\n      applyPath(cls)\n      argss.foreach(_.foreach(applyArg))\n    case l: Lambda =>\n      applyLam(l)\n    case Tuple(mut, elems) =>\n      elems.foreach(applyArg)\n    case Record(_, fields) =>\n      fields.foreach:\n        case RcdArg(idx, value) => idx.foreach(applyPath); applyPath(value)\n    case p: Path => applyPath(p)\n  \n  override def applyPath(p: Path): Unit = p match\n    case DynSelect(qual, fld, arrayIdx) =>\n      applyPath(qual); applyPath(fld)\n    case p@TrackableFieldSelect(qual, _ -> _) =>\n        res.selToCtxOfSel.addOne(p.uid -> ctxTracker.getAllCtx)\n        applyPath(qual)\n    case p: Select =>\n      super.applyPath(p)\n    case v: Value => applyValue(v)\n  \n  override def applyValue(v: Value): Unit = v match\n    case Value.Ref(l, disamb) => ()\n    case Value.This(sym) => ()\n    case Value.Lit(lit) => ()\n  \n  override def applyFunDefn(fun: FunDefn): Unit =\n    ctxTracker.inFun(fun):\n      ctxTracker.registerStratVar(fun.dSym, fun.sym.nme)\n      fun.params.foreach(applyParamList)\n      applyBlock(fun.body)\n  \n  override def applyValDefn(defn: ValDefn): Unit =\n    ctxTracker.registerStratVar(defn.tsym, defn.tsym.nme)\n    applyPath(defn.rhs)\n  \n  override def applyParamList(pl: ParamList): Unit =\n    pl.params.foreach(p => ctxTracker.registerStratVar(p.sym, p.sym.nme))\n    pl.restParam.foreach(p => ctxTracker.registerStratVar(p.sym, p.sym.nme))\n  \n  override def applyArg(arg: Arg): Unit =\n    applyPath(arg.value)\n  \n  override def applyDefn(defn: Defn): Unit = defn match\n    case defn: FunDefn => applyFunDefn(defn)\n    case defn: ValDefn => applyValDefn(defn)\n    case cls@ClsLikeDefn(own, isym, sym, ctorSym, k, paramsOpt, auxParams, parentPath, methods,\n        privateFields, publicFields, preCtor, ctor, mod, bufferable)\n    =>\n      ctxTracker.inCls(cls):\n        paramsOpt.foreach(applyParamList)\n        auxParams.foreach(applyParamList)\n        privateFields.foreach(tsym => ctxTracker.registerStratVar(tsym, tsym.nme))\n        publicFields.foreach: (_, tsym) =>\n          ctxTracker.registerStratVar(tsym, tsym.nme)\n        methods.foreach(applyFunDefn)\n        ctxTracker.inClsPreCtor(cls):\n          applyBlock(preCtor)\n        ctxTracker.inClsCtor(cls):\n          applyBlock(ctor)\n      for b: ClsLikeBody <- mod do\n        if ctxTracker.isTopLvlLikeModuleCtx then\n          res.modSymToBms(b.isym) = sym\n        ctxTracker.inMod(b):\n          b.privateFields.foreach(tsym => ctxTracker.registerStratVar(tsym, tsym.nme))\n          b.publicFields.foreach: (_, tsym) =>\n            ctxTracker.registerStratVar(tsym, tsym.nme)\n          b.methods.foreach(applyFunDefn)\n          ctxTracker.inModCtor(b):\n            applyBlock(b.ctor)\n      \n  override def applyCompanionModule(b: ClsLikeBody): Unit =\n    lastWords(\"handled inline in `applyDefn`\")\n  \nend FlowPreAnalyzer\n\nclass FlowConstraintsCollector(val preAnalyzer: FlowPreAnalyzer, val mono: Bool):\n  given FlowPreAnalyzer = preAnalyzer\n  given Uid.StratVar.State = preAnalyzer.stratVarUidState\n  given Raise = preAnalyzer.raise\n  given fState: FlowAnalysis.State = preAnalyzer.fState\n  given eState: Elaborator.State = preAnalyzer.eState\n  given tl: TraceLogger = preAnalyzer.tl\n  import StratVarState.freshVar\n  \n  private class ConstraintsCollector(val forFunGroup: Opt[TermSymbol]):\n    var constraints = Ls.empty[ProdStrat -> ConsStrat]\n    val instId: Opt[InstantiationId] = forFunGroup.fold(S(Nil))(_ => N)\n    def constrain(p: ProdStrat, c: ConsStrat) = constraints ::= p -> c\n    def constrain(cs: Iterable[ProdStrat -> ConsStrat]) = constraints :::= cs.toList\n  \n  private val globalCollector = new ConstraintsCollector(N)\n  def allConstraints = globalCollector.constraints\n  val funToSccGroups = MutMap.empty[TermSymbol, Ls[TermSymbol]]\n  def funToSccRep(tSym: TermSymbol): Option[TermSymbol] = funToSccGroups.get(tSym).map(_.head)\n  \n  // for fusing strictly internal parts of functions\n  val synthesizedInstIdToFunSym = LinkedHashMap.empty[InstantiationId, TermSymbol]\n  private val generatedProdVars: collection.Map[Symbol, StratVarState] =\n    preAnalyzer.res.generatedProdVars.withDefaultValue(preAnalyzer.res.primitiveStratVar)\n  \n  locally {\n    val funsToProdStratScheme = MutMap.empty[TermSymbol, ProdStratScheme]\n\n    if !mono then\n      // compute scc\n      val sccInOrder: Ls[Ls[TermSymbol]] =\n        import algorithms.partitionScc\n        var edges = Ls.empty[(TermSymbol, TermSymbol)]\n        for f <- preAnalyzer.res.rootFunDefns do\n          object CollectAllReferredFun extends BlockTraverser:\n            override def applyPath(p: Path) = p match\n              case FunRef(callee) =>\n                if preAnalyzer.res.rootFunDefns.exists(_.dSym is callee) then\n                  edges = (f.dSym -> callee) :: edges\n              case _ => ()\n          CollectAllReferredFun.applyBlock(f.body)\n        partitionScc(\n          edges,\n          preAnalyzer.res.rootFunDefns.map(_.dSym)\n        ).reverse\n      end sccInOrder\n      for\n        group <- sccInOrder\n        f <- group\n      do funToSccGroups(f) = group\n\n      // compute strat scheme for each scc group\n      for groupedFuns <- sccInOrder do\n        (new ConstraintsCollector(Some(funToSccRep(groupedFuns.head).get))).givenIn: cc ?=>\n          for funSym <- groupedFuns do\n            val fun = preAnalyzer.res.funSymToFunDefn(funSym)\n            val thisFunVar = generatedProdVars(fun.dSym)\n            val funProdStrat = processHandleableFun(\n              s\"${funSym.nme}_res\",\n              fun.params,\n              fun.body,\n              (fun.dSym, -1))\n            cc.constrain(funProdStrat, thisFunVar.asConsStrat)\n          for funSym <- groupedFuns do\n            funsToProdStratScheme(funSym) = ProdStratScheme(generatedProdVars(funSym), cc.constraints)\n    end if\n\n    // collect constraints from the top-level block\n    globalCollector.givenIn: cc ?=>\n      cc.constrain(preAnalyzer.res.primitiveStratVar.asProdStrat, NoCons)\n      cc.constrain(NoProd, preAnalyzer.res.primitiveStratVar.asConsStrat)\n      processBlock(preAnalyzer.pgrm.main)(using cc, NoCons)\n\n      if mono then\n        for\n          fun <- preAnalyzer.res.rootFunDefns\n          if fun.visibility is Visibility.Public\n        do\n          cc.constrain(generatedProdVars(fun.dSym).asProdStrat, NoCons)\n      else\n        for fun <- preAnalyzer.res.rootFunDefns do\n          val funSym = fun.dSym\n          val pScheme = funsToProdStratScheme(funSym)\n          val synthesizedRefUid =\n            Value.Ref(preAnalyzer.res.funSymToFunDefn(funSym).sym, S(funSym)).uid\n          val selfProd = pScheme.instantiate(synthesizedRefUid, funSym)\n          cc.constrain(selfProd, NoCons)\n          val selfInstId = synthesizedRefUid :: Nil\n          synthesizedInstIdToFunSym(selfInstId) = funSym\n    \n    // =========================\n    \n    extension (pScheme: ProdStratScheme) def instantiate(\n      referSite: ResultId,\n      referringTo: TermSymbol\n    )(using cc: ConstraintsCollector): ProdVar =\n      val groupRep: TermSymbol = funToSccRep(referringTo).get\n      val stratVarMap = MutMap.empty[StratVarState, StratVarState]\n      def updateInstantiationId(instId: Opt[InstantiationId]) =\n        S(instId.fold(referSite :: Nil)(referSite :: _))\n      def duplicateVarState(s: StratVarState) =\n        if s.generatedForFun.fold(false):\n          forFun => funToSccRep(forFun).fold(false)(_ is groupRep)\n        then stratVarMap.getOrElseUpdate(s, freshVar(s.name, cc.forFunGroup))\n        else s\n      def duplicateProdStrat(s: ProdStrat): ProdStrat = s match\n        case ProdVar(s) => duplicateVarState(s).asProdStrat\n        case p: ProdFun =>\n          new ProdFun(p.funId, updateInstantiationId(p.instantiationId))(\n            p.params.map(duplicateConsStrat),\n            p.restParam.map(duplicateConsStrat),\n            duplicateProdStrat(p.res))\n        case NoProd => NoProd\n        case c: Ctor => new Ctor(c.exprId, updateInstantiationId(c.instantiationId))(\n          c.ctor,\n          c.args.map((a, b) => a -> duplicateProdStrat(b)))\n      def duplicateConsStrat(c: ConsStrat): ConsStrat = c match\n        case ConsVar(s) => duplicateVarState(s).asConsStrat\n        case c: ConsFun =>\n          new ConsFun(c.exprId, updateInstantiationId(c.instantiationId))(\n            c.params.map(duplicateProdStrat),\n            duplicateConsStrat(c.res))\n        case NoCons => NoCons\n        case fSel: FieldSel =>\n          new FieldSel(fSel.exprId, updateInstantiationId(fSel.instantiationId))(\n            fSel.field,\n            fSel.selectsFrom,\n            duplicateVarState(fSel.consVar.s).asConsStrat)\n        case dtor: Dtor => new Dtor(dtor.scrutExprId, updateInstantiationId(dtor.instantiationId))\n      val newProd = duplicateVarState(pScheme.s).asProdStrat\n      pScheme.constraints.foreach: (p, c) =>\n        cc.constrain(duplicateProdStrat(p), duplicateConsStrat(c))\n      newProd\n    \n    enum OpaqueBoundary:\n      case Input, Output, Both\n    \n    extension (v: StratVarState)\n      def constrainOpaque(boundary: OpaqueBoundary)(using cc: ConstraintsCollector): Unit =\n        boundary match\n        case OpaqueBoundary.Input => cc.constrain(NoProd, v.asConsStrat)\n        case OpaqueBoundary.Output => cc.constrain(v.asProdStrat, NoCons)\n        case OpaqueBoundary.Both =>\n          cc.constrain(NoProd, v.asConsStrat)\n          cc.constrain(v.asProdStrat, NoCons)\n    \n    def mkFunProdStrat(\n      params: Ls[ParamList],\n      rootFunId: FunId,\n      res: ProdStrat\n    )(using cc: ConstraintsCollector): ProdStrat =\n      def paramListFunId(whichParamList: Int): FunId =\n        rootFunId match\n          case (sym: Symbol, _) => (sym, whichParamList)\n          case lambdaExprId: ResultId =>\n            assert(whichParamList == 0)\n            lambdaExprId\n      params.zipWithIndex.foldRight[ProdStrat](res):\n        case ((ps, whichParamList), acc) =>\n          new ProdFun(paramListFunId(whichParamList), cc.instId)(\n            ps.params.map(p => generatedProdVars(p.sym).asConsStrat),\n            ps.restParam.map(p => generatedProdVars(p.sym).asConsStrat),\n            acc)\n    \n    def processHandleableFun(\n      resName: String,\n      params: Ls[ParamList],\n      body: Block,\n      rootFunId: FunId\n    )(using cc: ConstraintsCollector): ProdStrat =\n      val res = freshVar(resName, cc.forFunGroup)\n      params.foreach:\n        _.restParam.foreach: p =>\n          generatedProdVars(p.sym).constrainOpaque(OpaqueBoundary.Both)\n      val funProdStrat = mkFunProdStrat(params, rootFunId, res.asProdStrat)\n      processBlock(body)(using cc, res.asConsStrat)\n      funProdStrat\n    \n    def constrainOpaqueResult(r: Result)(using cc: ConstraintsCollector): Unit =\n      cc.constrain(processResult(r), NoCons)\n    \n    def processHandleableFunDefn(fun: FunDefn)(using cc: ConstraintsCollector): Unit =\n      if mono || !preAnalyzer.res.rootFunSyms(fun.dSym) then\n        val funProdStrat = processHandleableFun(\n          s\"${fun.dSym.nme}_res\",\n          fun.params,\n          fun.body,\n          (fun.dSym, -1))\n        cc.constrain(funProdStrat, generatedProdVars(fun.dSym).asConsStrat)\n    \n    def processClsLikeDefn(cls: ClsLikeDefn)(using cc: ConstraintsCollector): Unit =\n      cls.privateFields.foreach(sym => generatedProdVars(sym).constrainOpaque(OpaqueBoundary.Both))\n      cls.publicFields.foreach: (_, tsym) =>\n        generatedProdVars(tsym).constrainOpaque(OpaqueBoundary.Both)\n      cls.methods.foreach: fun =>\n        processBlock(fun.body)(using cc, NoCons)\n      processBlock(cls.preCtor)(using cc, NoCons)\n      processBlock(cls.ctor)(using cc, NoCons)\n      cls.companion.foreach: mod =>\n        mod.privateFields.foreach(sym => generatedProdVars(sym).constrainOpaque(OpaqueBoundary.Both))\n        mod.publicFields.foreach: (_, tsym) =>\n          generatedProdVars(tsym).constrainOpaque(OpaqueBoundary.Both)\n        mod.methods.foreach: fun =>\n          processHandleableFunDefn(fun)\n        processBlock(mod.ctor)(using cc, NoCons)\n    \n    def processBlock(b: Block)(using cc: ConstraintsCollector, blkRes: ConsStrat): Unit =\n      val instId = cc.instId\n      b match\n      case Return(res, implct) => cc.constrain(processResult(res), blkRes)\n      case Throw(exc) => constrainOpaqueResult(exc)\n      case Match(scrut, arms, dflt, rest) =>\n        val scrutStrat = processResult(scrut)\n        cc.constrain(scrutStrat, new Dtor(scrut.uid, instId))\n        (arms.map(_._2) ++ dflt).foreach(processBlock)\n        processBlock(rest)\n      case Label(l, loop, body, rest) =>\n        processBlock(body)\n        processBlock(rest)\n      case Break(label) => ()\n      case Continue(label) => ()\n      case Scoped(syms, body) => processBlock(body)\n      case Begin(sub, rest) =>\n        processBlock(sub)\n        processBlock(rest)\n      case Assign(lhs, rhs, rest) =>\n        val rhsStrat = processResult(rhs)\n        lhs.match\n          case _: NoSymbol => ()\n          case _ => cc.constrain(rhsStrat, generatedProdVars(lhs).asConsStrat)\n        processBlock(rest)\n      case TryBlock(sub, finallyDo, rest) =>\n        processBlock(sub)\n        processBlock(finallyDo)\n        processBlock(rest)\n      case AssignField(lhs, nme, rhs, rest) =>\n        constrainOpaqueResult(lhs)\n        constrainOpaqueResult(rhs)\n        processBlock(rest)\n      case AssignDynField(lhs, fld, arrayIdx, rhs, rest) =>\n        constrainOpaqueResult(lhs)\n        constrainOpaqueResult(fld)\n        constrainOpaqueResult(rhs)\n        processBlock(rest)\n      case Define(defn, rest) =>\n        defn match\n        case ValDefn(tsym, sym, rhs) =>\n          val rhsStrat = processResult(rhs)\n          cc.constrain(rhsStrat, generatedProdVars(tsym).asConsStrat)\n        case fun: FunDefn =>\n          processHandleableFunDefn(fun)\n        case cls: ClsLikeDefn =>\n          processClsLikeDefn(cls)\n        processBlock(rest)\n      case End(msg) => ()\n      case Unreachable(_) => ()\n    \n    def processResult(r: Result)(using cc: ConstraintsCollector): ProdStrat =\n      val instId = cc.instId\n      def handleCallLike(callExprId: ResultId, f: Path, args: List[Arg]): ProdStrat =\n        val fStrat = processResult(f)\n        val argsStrat = args.map(a => processResult(a.value))\n        if args.exists(_.spread.isDefined) then\n          cc.constrain(fStrat, NoCons)\n          argsStrat.foreach(arg => cc.constrain(arg, NoCons))\n          NoProd\n        else\n          val callRes = freshVar(\"call_res\", cc.forFunGroup)\n          cc.constrain(fStrat, new ConsFun(callExprId, instId)(argsStrat, callRes.asConsStrat))\n          callRes.asProdStrat\n      r match\n        case sel@TrackableSelect(from, field, owner) =>\n          val fromStrat = processResult(from)\n          val selRes = freshVar(\"sel_res\", cc.forFunGroup)\n          cc.constrain(\n            fromStrat,\n            new FieldSel(sel.uid, instId)(field, owner, selRes.asConsStrat))\n          selRes.asProdStrat\n        case c@CtorCall(ctor, args) if args.forall(_.spread.isEmpty) =>\n          val argsStrat = args.map:\n            case Arg(_, a) => processResult(a)\n          ctor match\n          case cls: ClassSymbol =>\n            cls.tree.clsParams.size match\n            case 1 =>\n              val clsParams = cls.tree.clsParams.head\n              // TODO: properly check the parameter lists, which may change after passes like lifting\n              // softTODO(argsStrat.size === clsParams.size, s\"mismatched ctor arg and cls param sizes\")\n              new Ctor(c.uid, instId)(ctor, clsParams.zip(argsStrat))\n            case _ =>\n              // - the size of 0 means we don't know the cls param symbols,\n              // so we constrain args with NoCons and this CtorCall gives NoProd\n              // - if size > 1, we cannot handle multiple parameter class flow now,\n              //   constrain args with NoCons and this CtorCall gives NoProd\n              for a <- argsStrat do cc.constrain(a, NoCons)\n              NoProd\n          case _: ModuleOrObjectSymbol => new Ctor(c.uid, instId)(ctor, Nil)\n          case tupSize: Int => new Ctor(c.uid, instId)(tupSize, (0 until tupSize).zip(argsStrat).toList)\n        case c@CtorCall(_, args) =>\n          args.foreach(arg => cc.constrain(processResult(arg.value), NoCons))\n          NoProd\n        case c@Call(fun, argss) =>\n          argss match\n            case args :: Nil => handleCallLike(c.uid, fun, args)\n            case args :: rest =>\n              // For multi-arg-list calls, handle the first arg list normally for\n              // dead-param-elim, then constrain subsequent arg lists opaquely.\n              // We cannot reuse c.uid for subsequent ConsFuns because the\n              // DeadParamElim rewriter only rewrites the first arg list,\n              // and sharing the same exprId would cause conflicting eliminable sets.\n              val firstResult = handleCallLike(c.uid, fun, args)\n              cc.constrain(firstResult, NoCons)\n              rest.foreach: nextArgs =>\n                nextArgs.foreach(a => cc.constrain(processResult(a.value), NoCons))\n              NoProd\n            case Nil => handleCallLike(c.uid, fun, Nil)\n        case i@Instantiate(_, cls, argss) => handleCallLike(i.uid, cls, argss.flatten)\n        case lam@Lambda(ps, body) =>\n          processHandleableFun(\"lam_res\", ps :: Nil, body, lam.uid)\n        case _: Tuple => lastWords(\"should be handled in CtorCall\")\n        case Record(_, fields) =>\n          fields.foreach:\n            case RcdArg(idx, value) =>\n              idx.foreach(p => cc.constrain(processResult(p), NoCons))\n              cc.constrain(processResult(value), NoCons)\n          NoProd\n        case p: Path =>\n          p match\n          case CtorRef(ctor) => NoProd\n          case refSite@FunRef(f) =>\n            funsToProdStratScheme.get(f) match\n            case Some(fScheme) =>\n              fScheme.instantiate(refSite.uid, f)\n            case None => generatedProdVars(f).asProdStrat\n          case refLk@RefLike(sym) =>\n            refLk match\n              case Select(p, _) => cc.constrain(processResult(p), NoCons)\n              case _ => ()\n            generatedProdVars(sym).asProdStrat\n          case _: Value.Ref => lastWords(\"already handled in `RefLike` case\")\n          case Select(qual, name) =>\n            cc.constrain(processResult(qual), NoCons)\n            NoProd\n          case DynSelect(qual, fld, arrayIdx) =>\n            cc.constrain(processResult(qual), NoCons)\n            cc.constrain(processResult(fld), NoCons)\n            NoProd\n          case Value.This(sym) => NoProd\n          case Value.Lit(lit) => NoProd\n  }\nend FlowConstraintsCollector\n\nclass FlowConstraintSolver(val collector: FlowConstraintsCollector):\n  given tl: TraceLogger = collector.tl\n  given fState: FlowAnalysis.State = collector.fState\n  given eState: Elaborator.State = collector.eState\n  given preAnalyzer: FlowPreAnalyzer = collector.preAnalyzer\n  \n  \n  val ctorDests = LinkedHashMap.empty[ConcreteProducer, Set[ConcreteConsumer | NoCons.type]].withDefaultValue(Set.empty)\n  val dtorSrcs = LinkedHashMap.empty[ConcreteConsumer, Set[ConcreteProducer | NoProd.type]].withDefaultValue(Set.empty)\n  val funDests = LinkedHashMap.empty[ProdFun, Set[ConsFun | NoCons.type]].withDefaultValue(Set.empty)\n  val funSrcs = LinkedHashMap.empty[ConsFun, Set[ProdFun | NoProd.type]].withDefaultValue(Set.empty)\n  \n  val upperBounds = MutMap.empty[StratVarId, Ls[ConsStrat]].withDefaultValue(Nil)\n  val lowerBounds = MutMap.empty[StratVarId, Ls[ProdStrat]].withDefaultValue(Nil)\n  \n  locally {\n    val cache = MutSet.empty[ProdStrat -> ConsStrat]\n    def hasConcreteInstantiationId(prodOrCons: ProdStrat | ConsStrat): Boolean = prodOrCons match\n      case p: Ctor => p.instantiationId.isDefined\n      case p: ProdFun => p.instantiationId.isDefined\n      case c: Dtor => c.instantiationId.isDefined\n      case c: FieldSel => c.instantiationId.isDefined\n      case c: ConsFun => c.instantiationId.isDefined\n      case _ => true\n    def recordFlow[P, C](\n      dests: collection.mutable.Map[P, Set[C | NoCons.type]],\n      srcs: collection.mutable.Map[C, Set[P | NoProd.type]]\n    )(producer: P, consumer: C): Unit =\n      dests(producer) = dests(producer) + consumer\n      srcs(consumer) = srcs(consumer) + producer\n    def recordNoCons[P, C](\n      dests: collection.mutable.Map[P, Set[C | NoCons.type]]\n    )(producer: P): Unit =\n      dests(producer) = dests(producer) + NoCons\n    def recordNoProd[P, C](\n      srcs: collection.mutable.Map[C, Set[P | NoProd.type]]\n    )(consumer: C): Unit =\n      srcs(consumer) = srcs(consumer) + NoProd\n    def handle(constraint: ProdStrat -> ConsStrat): Unit = if cache.add(constraint) then\n      assert:\n        val (prod, cons) = constraint\n        hasConcreteInstantiationId(prod) &&\n        hasConcreteInstantiationId(cons)\n      constraint match\n      case (c: Ctor, d: Dtor) =>\n        recordFlow(ctorDests, dtorSrcs)(c, d)\n      case (c: Ctor, d: FieldSel) =>\n        if d.selectsFrom === c.ctor then\n          recordFlow(ctorDests, dtorSrcs)(c, d)\n          handle(\n            c.args.find(_._1 is d.field).get._2,\n            d.consVar)\n      case (c: Ctor, NoCons) =>\n        recordNoCons(ctorDests)(c)\n        for (_, argProd) <- c.args do handle(argProd, NoCons)\n      case (p: ProdFun, c: ConsFun) =>\n        recordFlow(funDests, funSrcs)(p, c)\n        c.params.take(p.params.size).lazyZip(p.params).foreach((argC, argP) => handle(argC -> argP))\n        for\n          restCons <- p.restParam\n          arg <- c.params.drop(p.params.size)\n        do handle(arg, restCons)\n        handle(p.res, c.res)\n      case (p: ProdFun, NoCons) =>\n        recordNoCons(funDests)(p)\n        for a <- p.params do handle(NoProd, a)\n        p.restParam.foreach(r => handle(NoProd, r))\n        handle(p.res, NoCons)\n      case (NoProd, d: Dtor) =>\n        recordNoProd(dtorSrcs)(d)\n      case (NoProd, sel: FieldSel) =>\n        recordNoProd(dtorSrcs)(sel)\n        handle(NoProd, sel.consVar)\n      case (NoProd, c: ConsFun) =>\n        recordNoProd(funSrcs)(c)\n        for a <- c.params do handle(a, NoCons)\n        handle(NoProd, c.res)\n      case (p: ProdVar, c: ConsVar) =>\n        upperBounds(p.s.uid) ::= c\n        for l <- lowerBounds(p.s.uid) do handle(l, c)\n        lowerBounds(c.s.uid) ::= p\n        for u <- upperBounds(c.s.uid) do handle(p, u)\n      case (p: ProdVar, c) =>\n        upperBounds(p.s.uid) ::= c\n        for l <- lowerBounds(p.s.uid) do handle(l, c)\n      case (p, c: ConsVar) =>\n        lowerBounds(c.s.uid) ::= p\n        for u <- upperBounds(c.s.uid) do handle(p, u)\n      case _ => () // ignore other cases\n    end handle\n    \n    for c <- collector.allConstraints do handle(c)\n  }\nend FlowConstraintSolver\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/flowAnalysis/FlowWebComputation.scala",
    "content": "package hkmc2\npackage codegen\npackage flowAnalysis\n\nimport scala.collection.mutable.{Set as MutSet}\n\nobject FlowWebComputation:\n  case class Result[P, C](markedProducers: collection.Set[P], markedConsumers: collection.Set[C])\n\n  def apply[P, C](\n    dests: P => IterableOnce[C],\n    srcs: C => IterableOnce[P],\n    producerRoots: IterableOnce[P],\n    consumerRoots: IterableOnce[C],\n  ): Result[P, C] =\n    val markedProducers = MutSet.empty[P]\n    val markedConsumers = MutSet.empty[C]\n    def markProducer(p: P): Unit =\n      if markedProducers.add(p) then dests(p).iterator.foreach(markConsumer)\n    def markConsumer(c: C): Unit =\n      if markedConsumers.add(c) then srcs(c).iterator.foreach(markProducer)\n    producerRoots.iterator.foreach(markProducer)\n    consumerRoots.iterator.foreach(markConsumer)\n    Result(markedProducers, markedConsumers)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala",
    "content": "package hkmc2\npackage codegen\npackage js\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\nimport document.*\nimport document.Document.{braced, bracketed}\n\nimport hkmc2.Message.MessageContext\nimport hkmc2.syntax.{Tree, MutVal, ImmutVal, SpreadKind}\nimport hkmc2.semantics.*\nimport Elaborator.{State, Ctx}\nimport hkmc2.codegen.Lambda\n\nimport Scope.scope\nimport hkmc2.syntax.Tree.UnitLit\nimport hkmc2.semantics.Elaborator.ctx\nimport hkmc2.syntax.Tree.{IntLit, StrLit}\nimport scala.annotation.tailrec\n\n\n// TODO factor some logic for other codegen backends\nabstract class CodeBuilder:\n    \n  type Context\n  \n\nclass JSBuilder(using Config, TL, State, Ctx) extends CodeBuilder:\n  import JSBuilder.*\n  \n  def checkMLsCalls: Bool = false\n  def checkSelections: Bool = false\n  def freezeDefinitions: Bool = false\n  \n  val builtinOpsBase: Ls[Str] = Ls(\n    \"+\", \"-\", \"*\", \"/\", \"%\",\n    \"==\", \"!=\", \"<\", \"<=\", \">\", \">=\",\n    \"===\",\n    \"&&\", \"||\")\n  val builtinOpsMap: Map[Str, Str] = (\n    builtinOpsBase.map(op => op -> op).toMap\n    + (\";\" -> \",\")\n  )\n  val needsParens: Set[Str] = Set(\",\")\n  \n  val freeze = if !config.noFreeze then \"globalThis.Object.freeze\" else \"\"\n  lazy val freezeDefns = if freezeDefinitions && !config.noFreeze then \"globalThis.Object.freeze\" else \"\"\n  \n  // TODO use this to avoid parens when we generate recomposed expressions later\n  enum Context:\n    case TopLevel\n    case SelectionPrefix\n    case Argument\n    case Operand(prec: Int)\n  \n  def mkErr(errMsg: Message)(using Raise, Scope): Document =\n    doc\"throw globalThis.Error(${result(Value.Lit(syntax.Tree.StrLit(errMsg.show)))})\"\n  \n  def errExpr(errMsg: Message)(using Raise, Scope): Document =\n    raise(ErrorReport(errMsg -> N :: Nil,\n      source = Diagnostic.Source.Compilation))\n    doc\"(()=>{${mkErr(errMsg)}})()\"\n  \n  def errStmt(errMsg: Message)(using Raise, Scope): Document =\n    raise(ErrorReport(errMsg -> N :: Nil,\n      source = Diagnostic.Source.Compilation))\n    doc\" # ${mkErr(errMsg)};\"\n  \n  def getVar(l: Local, loc: Opt[Loc])(using Raise, Scope): Document = l match\n    case ts: semantics.TermSymbol =>\n      ts.owner match\n      case S(owner) =>\n        doc\"${getVar(owner, loc)}${\n          if (ts.k is syntax.LetBind) && !owner.isInstanceOf[semantics.TopLevelSymbol]\n          then \".#\" + owner.privatesScope.lookup_!(ts, loc)\n          else fieldSelect(ts.id.name)\n        }\"\n      case N => scope.lookup_!(ts, loc)\n    case ts: semantics.ModuleOrObjectSymbol if ts.asMod.isDefined => // FIXME: currently, objects have a ModuleSymbol...\n      // * Module self-references use the module name itself instead of `this`\n      scope.lookup_!(ts, loc)\n    case ts: semantics.InnerSymbol =>\n      scope.findThis_!(ts)\n    case _ => scope.lookup_!(l, loc)\n  \n  def runtimeVar(using Raise, Scope): Document = getVar(State.runtimeSymbol, N)\n  \n  def argument(a: Arg)(using Raise, Scope): Document =\n    val spd = a.spread match\n      case S(SpreadKind.Eager) => doc\"...\"\n      case S(SpreadKind.Lazy) => doc\"$runtimeVar.Tuple.split, \"\n      case N => doc\"\"\n    doc\"${spd}${result(a.value)}\"\n  \n  def operand(a: Arg)(using Raise, Scope): Document =\n    if a.spread.nonEmpty then die else subexpression(a.value)\n  \n  def subexpression(r: Result)(using Raise, Scope): Document = r match\n    case _: Lambda => doc\"(${result(r)})\"\n    case _ => result(r)\n  \n  def fieldSelect(s: Str): Document = escapeField(s, \".\")\n  def escapeField(s: Str, defaultPrefix: Str): Document =\n    if JSBuilder.isValidFieldName(s) then doc\"$defaultPrefix$s\"\n    else s.toIntOption match\n      case S(index) => doc\"[$index]\"\n      case N => doc\"[${JSBuilder.makeStringLiteral(s)}]\"\n  \n  def result(r: Result)(using Raise, Scope): Document = r match\n    case Value.This(sym) => scope.findThis_!(sym)\n    case Value.Lit(Tree.StrLit(value)) => makeStringLiteral(value)\n    case Value.Lit(lit) => lit.idStr\n    case Value.Ref(l: BuiltinSymbol, _) =>\n      if l.nullary then l.nme\n      else errExpr(msg\"Illegal reference to builtin symbol '${l.nme}'\")\n    case Value.Ref(l, disamb) => l match\n      case l: BlockMemberSymbol if disamb.exists(_.shouldBeLifted) =>\n        doc\"${getVar(l, l.toLoc)}.class\"\n      case _ =>\n        getVar(l, r.toLoc)\n    case Call(Value.Ref(l: BuiltinSymbol, _), (lhs :: rhs :: Nil) :: Nil) if !l.functionLike =>\n      if l.binary then\n        val res = doc\"${operand(lhs)} ${l.nme} ${operand(rhs)}\"\n        if needsParens(l.nme) then doc\"(${res})\" else res\n      else errExpr(msg\"Cannot call non-binary builtin symbol '${l.nme}'\")\n    case Call(Value.Ref(l: BuiltinSymbol, _), (rhs :: Nil) :: Nil) if !l.functionLike =>\n      if l.unary then\n        val res = doc\"${l.nme} ${operand(rhs)}\"\n        if needsParens(l.nme) then doc\"(${res})\" else res\n      else errExpr(msg\"Cannot call non-unary builtin symbol '${l.nme}'\")\n    case Call(Value.Ref(l: BuiltinSymbol, _), args :: Nil) =>\n      if l.functionLike then\n        val argsDoc = args.map(argument).mkDocument(\", \")\n        doc\"${l.nme}(${argsDoc})\"\n      else errExpr(msg\"Illegal arity for builtin symbol '${l.nme}'\")\n    \n    case Call(s @ Select(_, Elaborator.ctx.builtins.BuiltInOpIdent(jsOp)), (lhs :: rhs :: Nil) :: Nil) =>\n      val res = doc\"${operand(lhs)} ${jsOp} ${operand(rhs)}\"\n      if needsParens(jsOp) then doc\"(${res})\" else res\n    case c @ Call(fun, argss) =>\n      val base = subexpression(fun)\n      val calls = argss.foldLeft(base): (acc, args) =>\n        val argsDoc = args.map(argument).mkDocument(\", \")\n        doc\"${acc}(${argsDoc})\"\n      if c.isMlsFun\n      then if checkMLsCalls\n        then doc\"$runtimeVar.checkCall(${calls})\"\n        else doc\"${calls}\"\n      else doc\"$runtimeVar.safeCall(${calls})\"\n    case Lambda(ps, bod) => scope.nest givenIn:\n      val (params, bodyDoc) = setupFunction(none, ps, bod, isLambda = true)\n      doc\"($params) => ${ braced(bodyDoc) }\"\n    case s @ Select(qual, id) => \n      val dotClass = s.symbol match\n        case S(ds) if ds.shouldBeLifted => doc\".class\"\n        case _ => doc\"\"\n      val name = id.name\n      doc\"${result(qual)}${\n        if isValidFieldName(name)\n        then doc\".$name\"\n        else name.toIntOption match\n          case S(index) => doc\"[$index]\"\n          case N => doc\"[${makeStringLiteral(name)}]\"\n      }${dotClass}\"\n    case DynSelect(qual, fld, ai) =>\n      if ai\n      then doc\"${result(qual)}.at(${result(fld)})\"\n      else doc\"${result(qual)}[${result(fld)}]\"\n    case Instantiate(mut, cls, argss) =>\n      val calls = argss.foldLeft(result(cls)): (acc, args) =>\n        doc\"${acc}(${args.map(argument).mkDocument(\", \")})\"\n      val inner = doc\"new $calls\"\n      if mut then inner else doc\"$freeze(${inner})\"\n    case Tuple(mut, es) if es.isEmpty => if mut then \"[]\" else doc\"$freeze([])\"\n    case Tuple(mut, es) =>\n      val inner =\n        val lazyConcat = es.exists(!_.spread.fold(true)(_.isEager))\n        if lazyConcat\n        then doc\"$runtimeVar.Tuple.lazyConcat(${es.map(argument).mkDocument(doc\", \")})\"\n        else bracketed(\"[\", \"]\", insertBreak = true):\n          es.map(argument).mkDocument(doc\", # \")\n      if mut then inner else doc\"$freeze(${inner})\"\n    case Record(mut, Nil) =>\n      if mut then \"{}\" else doc\"$freeze({})\"\n    case Record(mut, flds) =>\n      val inner = bracketed(pre = \"{\", post = \"}\", insertBreak = true):\n        flds.map:\n          case RcdArg(S(Value.Lit(IntLit(idx))), v) =>\n            doc\"${idx.toString}: ${result(v)}\"\n          case RcdArg(S(Value.Lit(StrLit(idx))), v) =>\n            doc\"${if isValidIdentifier(idx) then idx else s\"\\\"$idx\\\"\"}: ${result(v)}\"\n          case RcdArg(S(idx), v) =>\n            doc\"[${result(idx)}]: ${result(v)}\"\n          case RcdArg(N, v) => doc\"...${result(v)}\"\n        .mkDocument(doc\", # \")\n      if mut then inner else doc\"$freeze(${inner})\"\n  \n  /**\n    * Matches the following kind of if statement, where ai are ints:\n    * \n    * ```\n    * if scrut is a1 do\n    *   body1\n    *   set scrut = a2\n    * if scrut is a2 do\n    *   body2\n    *   set scrut = a3\n    * if scrut is an do\n    *   bodyn\n    * ```\n    * \n    * The intention is that this can be compiled efficiently into a switch statement:\n    * \n    * ```js\n    * switch (scrut) {\n    *   case a1:\n    *     body1\n    *     scrut = a2;\n    *   case a2:\n    *     body2\n    *     scrut = a3;\n    *   ...\n    *   case an:\n    *     bodyn\n    * }\n    * ```\n    * Note that `scrut` is guaranteed to not change between `set scrut = ai` and `if scrut is ai`,\n    * because the JS event loop waits until the entire call stack is cleared before running any other\n    * code. Hence, this transformation is safe.\n    */\n  object IfIntChain:\n    @tailrec\n    private def lastBlkAssign(b: Block): Opt[Assign] = b match\n      case a @ Assign(lhs, rhs, End(_)) => S(a)\n      case b: NonBlockTail => lastBlkAssign(b.rest)\n      case _: BlockTail => N\n    \n    @tailrec\n    private def unapplyImpl(\n      b: Block, \n      acc: List[(BigInt, Block)],\n      scrut: Opt[Value.Ref],\n      curVal: Opt[BigInt]\n    ): Opt[(Value.Ref, List[(BigInt, Block)], Block)] = \n      val scrutSym = scrut.map(_.l)\n      b match\n      case Match(\n        scrut_ @ Value.Ref(scrutSym_, _),                   // The scrutinee is a ref.\n        (Case.Lit(Tree.IntLit(curVal_)), b) :: Nil,         // There is only one case matching an int literal.\n        S(End(_)) | N, rest                                 // Default case exists and does nothing.\n      )\n        if scrutSym.map(_ === scrutSym_).getOrElse(true)    // The scrutinee is the same as the one before.\n        && curVal.map(_ === curVal_).getOrElse(true)        // The matched int literal is one previously set.\n        =>\n          lastBlkAssign(b) match\n          // the one branch ends by assigning `nextInt` to `scrutSym`\n          case S(Assign(`scrutSym_`, Value.Lit(Tree.IntLit(nextInt)), _)) =>\n            unapplyImpl(rest, (curVal_, b) :: acc, S(scrut_), S(nextInt))\n          case _ =>\n            S((scrut_, (curVal_, b) :: acc, rest))\n      case _ => scrut match\n        case Some(value) => S((value, acc, b))\n        case None => N\n    \n    def unapply(b: Block): Opt[(scrut: Value.Ref, cases: List[(BigInt, Block)], rest: Block)] =\n      unapplyImpl(b, Nil, N, N) match\n        case Some(value) if value._2.length > 1 => S(value)\n        case _ => N\n  \n  def returningTerm(t: Block, endSemi: Bool)(using Raise, Scope): Document =\n    def mkSemi = if endSemi then \";\" else \"\"\n    t match\n    case Assign(l, r, rst) if l is State.noSymbol =>\n      doc\" # ${result(r)};${returningTerm(rst, endSemi)}\"\n    case Assign(l, r, rst) =>\n      doc\" # ${getVar(l, l.toLoc // TODO: improve location\n        )} = ${result(r)};${returningTerm(rst, endSemi)}\"\n    case AssignField(p, n, r, rst) =>\n      doc\" # ${result(p)}${fieldSelect(n.name)} = ${result(r)};${returningTerm(rst, endSemi)}\"\n    case AssignDynField(p, f, ai, r, rst) =>\n      doc\" # ${result(p)}[${result(f)}] = ${result(r)};${returningTerm(rst, endSemi)}\"\n    case Define(defn, rst) =>\n      def mkThis(sym: InnerSymbol): Document =\n        result(Value.This(sym))\n      val resJS = defn match\n      case ValDefn(tsym, sym, p) =>\n        val sym = defn.sym\n        // * Currently we allow `val` outside of object/module scopes,\n        // * in which case it has no owner and is just a glorified local variable rather than a field.\n        tsym.owner match\n        case N =>\n          doc\"${getVar(sym, sym.toLoc)} = ${result(p)};${returningTerm(rst, endSemi)}\"\n        case S(owner) =>\n          val thisDoc = mkThis(owner)\n          val nme = sym.nme\n          owner match \n          case mod: ModuleOrObjectSymbol if (mod.tree.k is syntax.Mod) && (nme == \"name\" || nme == \"length\") =>\n            // * JavaScript class constructors have built-in non-writable `name` and `length` properties.\n            // * Use Object.defineProperty to override them in module/class static contexts.\n            doc\"Object.defineProperty(${thisDoc}, ${nme.escaped}, { configurable: true, enumerable: true, writable: true, value: ${result(p)} });${returningTerm(rst, endSemi)}\"\n          case _ =>\n            doc\"${thisDoc}${fieldSelect(nme)} = ${result(p)};${returningTerm(rst, endSemi)}\"\n      case defn: (FunDefn | ClsLikeDefn) =>\n        \n        val outerScope = scope\n        val (thisProxy, res) = scope.nestRebindThis(\n            // * Either this is an InnerSymbol or this is a Fun,\n            // * and we need to rebind `this` to None to shadow it.\n            defn.innerSym.collectFirst{ case s: InnerSymbol => s }):\n          defn match\n            \n          case FunDefn(params = Nil) =>\n            lastWords(\"cannot generate function with no parameter list\")\n          case FunDefn(own, sym, dSym, ps :: pss, bod) =>\n            val result = pss.foldRight(bod):\n              case (ps, block) =>\n                Return(Lambda(ps, block), false)\n            val displayName = if sym.nameIsMeaningful then S(dSym.name) else N\n            \n            // * We may need to set up the function in a nested scope in one case below, so this is marked as lazy.\n            lazy val (params, bodyDoc) = setupFunction(displayName, ps, result, isLambda = false)\n            \n            val symName = sym.nme\n            \n            // * If the name is a valid JavaScript identifier, use it in the generated function code.\n            if sym.nameIsMeaningful && isValidIdentifier(symName)\n            then\n              val varName = getVar(sym, dSym.toLoc)\n              scope.reverseLookup(sym.nme) match\n              // * Maybe the function's internal name was already bound in scope;\n              // * in that case, we need to forward it to a different variable to avoid unintended capture.\n              case S(otherSym) if (otherSym isnt sym) && bod.freeVars.contains(otherSym) => scope.nest.givenIn:\n                val externalName = scope.allocateName(otherSym, prefix = \"proxy$\", shadow = true)\n                val (params, bodyDoc) = setupFunction(displayName, ps, result, isLambda = false)\n                doc\"const $externalName = $symName; ${\n                  varName} = function $symName($params) ${ braced(bodyDoc) };\"\n              case _ =>\n                doc\"${varName} = function ${sym.nme}($params) ${ braced(bodyDoc) };\"\n            else\n              // * In JS, `let x = (0, function (args) {...})` makes the function anonymous;\n              // * otherwise, using `let x = function (args) {...}` would name the function `x`,\n              // * which is not meaningful, here.\n              doc\"${getVar(sym, dSym.toLoc)} = (undefined, function ($params) ${ braced(bodyDoc) });\"\n            \n          case ClsLikeDefn(ownr, isym, sym, ctorSym, kind, paramsOpt, auxParams, par, mtds,\n              privFlds, pubFlds, preCtor, ctor, modo, bufferable)\n          =>\n            val clsParams = paramsOpt.fold(Nil)(_.paramSyms)\n            val ctorParams = clsParams.map(p => p -> scope.allocateName(p))\n            val ctorAuxParams = auxParams.map(ps => ps.params.map(p => p.sym -> scope.allocateName(p.sym)))\n            \n            def mkMethods(mtds: Ls[FunDefn], mtdPrefix: Str)(using Scope): Document =\n              mtds.map:\n                case td @ FunDefn(params = ps :: pss, body = bod) =>\n                  val result = pss.foldRight(bod):\n                    case (ps, block) =>\n                      Return(Lambda(ps, block), false)\n                  val (params, bodyDoc) = scope.nest.givenIn:\n                    setupFunction(S(td.sym.nme), ps, result, isLambda = false)\n                  doc\" # $mtdPrefix${td.sym.nme}($params) ${ braced(bodyDoc) }\"\n                case td @ FunDefn(params = Nil, body = bod) =>\n                  doc\" # ${mtdPrefix}get ${td.sym.nme}() ${ braced(body(bod, endSemi = true)) }\"\n              .mkDocument(\" \")\n            \n            def mkPrivs(pubFlds: Ls[BlockMemberSymbol -> TermSymbol], privFlds: Ls[TermSymbol],\n                  mtdPrefix: Str, isym: InnerSymbol)(using Scope): Document =\n              // * Note: the non-mut-val parts of `pubFlds` are not used because in JS, fields are not declared\n              val mutPubFields =\n                pubFlds.collect:\n                  case (_, sym) if sym.k is MutVal =>\n                    sym -> TermSymbol(\n                      syntax.LetBind, S(isym), Tree.Ident(sym.nme))\n              val allPrivFlds = privFlds ++ mutPubFields.map(_._2)\n              val privDecls = allPrivFlds.map: fld =>\n                val nme = isym.privatesScope.allocateOrGetName(fld)\n                doc\" # $mtdPrefix#$nme;\"\n              val accessors = mutPubFields.flatMap: (valSym, letSym) =>\n                doc\" # ${mtdPrefix}get ${escapeField(valSym.name, \"\")\n                  }() { return ${getVar(letSym, letSym.toLoc)}; }\"\n                :: doc\" # ${mtdPrefix}set ${escapeField(valSym.name, \"\")\n                  }(value) { ${getVar(letSym, letSym.toLoc)} = value; }\"\n                :: Nil\n              (privDecls ::: accessors).mkDocument(doc\"\")\n            \n            val modDoc = modo match\n              case N => doc\"\"\n              case S(mod) =>\n                val (thisProxy, res) = outerScope.nestRebindThis(S(mod.isym)):\n                  val mtdPrefix = \"static \"\n                  val privs = mkPrivs(mod.publicFields, mod.privateFields, mtdPrefix, mod.isym)\n                  val ctorCode = if mod.ctor.isEmpty then doc\"\" else doc\" # static \" :: braced:\n                    body(mod.ctor, endSemi = true)\n                  privs :: ctorCode :: {\n                    mkMethods(mod.methods, mtdPrefix)\n                  }\n                // * Note that `thisProxy` might be defined at this point,\n                // * if the module accesses the self-reference of an outer definition.\n                // * But in that case, we'll already be creating a proxy through the `nestRebindThis` call above,\n                // * and that proxy will return the same symbol, so we don't need to bind it here.\n                res\n            \n            val mtdPrefix = \"\"\n            \n            val privs = mkPrivs(pubFlds, privFlds, mtdPrefix, isym)\n            \n            val isSingleton = (kind is syntax.Obj) || (kind is syntax.Pat)\n            \n            val (singletonInit, singletonFreeze) =\n              if isSingleton\n              then\n                val fz = doc\" # $freeze(this);\"\n                ownr match\n                case S(owner) =>\n                  (doc\" # ${result(Value.Ref(owner, N))}.${sym.nme} = this;\", fz)\n                case N =>\n                  (doc\" # ${getVar(sym, sym.toLoc)} = this;\", fz)\n              else (doc\"\", doc\"\")\n            \n            val ctorCode = scope.nest.givenIn:\n              val preCtorCode = nonNestedScoped(preCtor)(bd => block(bd, true))\n              doc\"$preCtorCode$singletonInit${nonNestedScoped(ctor)(bd => block(bd, endSemi = true))}${\n                  kind match\n                  case syntax.Obj =>\n                    doc\" # ${defineProperty(doc\"this\", \"class\", doc\"${scope.lookup_!(isym, isym.toLoc)}\")};\"\n                  case _ => \"\"\n                }$singletonFreeze\"\n            \n            // * If there are no ctor params, pop one param list off the aux params\n            val (newCtorAuxParams, initialCtorParams) = paramsOpt match\n              case None => ctorAuxParams match\n                case head :: next => (next, head)\n                case Nil => (ctorAuxParams, Nil)\n              case Some(_) => (ctorAuxParams, ctorParams)\n            \n            val ctorAux = if newCtorAuxParams.isEmpty then\n              ctorCode\n            else\n              val pss = newCtorAuxParams.map(_.map(_._2))\n              val newCtorCode = doc\"$ctorCode # return this;\"\n              val ctorBraced = doc\"${ braced(newCtorCode) }\"\n              val funBod = pss.foldRight(ctorBraced):\n                case (psDoc, doc) => doc\"(${psDoc.mkDocument(\", \")}) => $doc\"\n              doc\" # return $funBod\"\n            \n            val ctorBod = {{\n                val extraPath = if paramsOpt.isDefined then \".class\" else \"\"\n                doc\" # static \" :: braced:\n                  val v = getVar(isym, isym.toLoc)\n                  if isSingleton\n                  then doc\" # new $v\"\n                  else\n                    ownr match\n                    case S(owner) =>\n                      doc\" # ${result(Value.Ref(owner, N))}.${sym.nme}$extraPath = $v\"\n                    case N =>\n                      doc\" # ${getVar(sym, sym.toLoc)}$extraPath = $v\"\n              }} :: (\n                if ctorAux.isEmpty then doc\"\"\n                else doc\" # constructor(${initialCtorParams.unzip._2.mkDocument(\", \")}) \" :: braced(ctorAux)\n              )\n            \n            val clsJS = doc\"class ${scope.lookup_!(isym, isym.toLoc)}${\n                par.map(p => doc\" extends ${\n                  result(p)\n                }\").getOrElse(\"\")\n              } \" :: braced:\n                \n                ctorBod :: modDoc :: privs :: {\n                  // * Create \"debound method\" checkers as accessors\n                  if checkSelections\n                  then mtds\n                    .flatMap:\n                      case td @ FunDefn(params = ps :: pss, body = bod) => S:\n                        doc\" # get ${td.sym.nme}$$__checkNotMethod() { ${\n                          runtimeVar\n                        }.deboundMethod(${makeStringLiteral(td.sym.nme)}, ${\n                          makeStringLiteral(sym.nme)\n                        }); }\"\n                      case _ => N\n                    .mkDocument(\" \")\n                  else doc\"\"\n                } :: {\n                  mkMethods(mtds, mtdPrefix)\n                } :: {\n                  // * If this class has a `toString` implementation, then delegate\n                  // * `prettyPrint` to `toString`.\n                  if mtds.exists(_.sym.nme == \"toString\") then doc\"\"\" # [${\n                    getVar(State.prettyPrintSymbol, N)\n                  }]() { return this.toString(); }\"\"\"\n                  // * Call the `render` function in the default `toString` method.\n                  else doc\" # ${mtdPrefix}toString() { return $runtimeVar.render(this); }\"\n                } :: {\n                  doc\"\"\" # static [${getVar(State.definitionMetadataSymbol, N)}] = [${\n                    kind.desc.escaped}, ${sym.nme.escaped}${\n                    if (kind is syntax.Cls) && paramsOpt.isDefined then\n                      doc\", [${ctorParams.map { (p, _) => p.decl match\n                        case S(Param(flags = FldFlags(isVal = true))) => doc\"${p.name.escaped}\"\n                        case S(_) | N => doc\"null\"\n                      }.mkDocument(\", \")}]\"\n                    else doc\"\"\n                  }]; \"\"\"\n              }\n            \n            if isSingleton then\n              ownr match\n              case S(owner) =>\n                assert((kind is syntax.Pat) || paramsOpt.isEmpty)\n                doc\"$freezeDefns(${clsJS});\"\n              case N =>\n                doc\"$freezeDefns(${clsJS});\"\n            else\n              val paramsAll = paramsOpt match\n                case None => auxParams\n                case Some(value) => value :: auxParams\n              \n              val fun = paramsAll match\n                case ps_ :: pss_ if paramsOpt.isDefined => outerScope.nest.givenIn:\n                  val (ps, _) = setupFunction(some(sym.nme), ps_, End(), isLambda = false)\n                  val pss = pss_.map(setupFunction(N, _, End(), isLambda = false)._1)\n                  val paramsDoc = pss.foldLeft(doc\"($ps)\"):\n                    case (doc, ps) => doc\"${doc}(${ps})\"\n                  val inner = doc\"new ${sym.nme}.class$paramsDoc\"\n                  val bod = braced(doc\" # return $freeze($inner);\")\n                  val funBod = pss.foldRight(bod):\n                    case (psDoc, doc_) => doc\"($psDoc) => $doc_\"\n                  val funBodRet = if pss.isEmpty then funBod else braced(doc\" # return $funBod\")\n                  val nme = if isValidIdentifier(sym.nme) then sym.nme else \"\"\n                  S(doc\"function $nme($ps) ${ funBodRet }\")\n                case _ => N\n              \n              ownr match\n              case S(owner) =>\n                val ths = mkThis(owner)\n                fun match\n                case S(f) =>\n                  doc\"${ths}.${sym.nme} = ${f}; # $freezeDefns($clsJS);\"\n                case N =>\n                  doc\"$freezeDefns(${clsJS});\"\n              case N =>\n                fun match\n                case S(f) =>\n                  doc\"${getVar(sym, sym.toLoc)} = ${f}; # $freezeDefns($clsJS);\"\n                case N =>\n                  doc\"$freezeDefns(${clsJS});\"\n        \n        thisProxy match\n          case S(proxy) if !scope.thisProxyDefined =>\n            scope.thisProxyDefined = true\n            doc\"const $proxy = this; # $res${returningTerm(rst, endSemi)}\"\n          case _ => doc\"$res${returningTerm(rst, endSemi)}\"\n      \n      doc\" # $resJS\"\n      \n    case Return(Value.Lit(UnitLit(false)), false) => doc\" # return${mkSemi}\"\n    case Return(res, true) => doc\" # ${result(res)}${mkSemi}\"\n    case Return(res, false) => doc\" # return ${result(res)}${mkSemi}\"\n    \n    case Match(scrut, Nil, els, rest) =>\n      val e = els match\n      case S(el) => nonBracedScoped(el)(bod => returningTerm(bod, endSemi = true))\n      case N => doc\"\"\n      e :: returningTerm(rest, endSemi)\n    case Match(scrut, (Case.Lit(lit), End(msg)) :: Nil, S(el), rest) =>\n      val sd = result(scrut)\n      val e = braced(nonBracedScoped(el)(res => returningTerm(res, endSemi = false)))\n      doc\" # if ($sd !== ${lit.idStr}) $e\" :: returningTerm(rest, endSemi)\n    case SpecializedSwitch(scrut, cases, dflt, rest) =>\n      val switchBod = cases.foldLeft(doc\"\"): (acc, arm) =>\n        val needsBreak = arm.isInstanceOf[SwitchCase.ExplicitBreak]\n        acc :: doc\" # case ${result(Value.Lit(arm.litValue))}: #{ ${\n          // * Note: we use `block` here so that Scoped nodes will create proper brace sections,\n          // * necessary since `case` clauses do not create a new scope,\n          // * so something like `switch (x) { case 1: let y = 1; break; case 2: let y = 2 }` is ill-formed!\n          block(arm.body, endSemi = true)\n        }${if needsBreak then doc\" # break;\" else \"\"} #} \"\n      val bodWithDflt = doc\"${switchBod}${dflt match\n        case Some(bd) => doc\" # default: #{ ${nonBracedScoped(bd)(bd => returningTerm(bd, endSemi = true))} #} \"\n        case None => doc\"\"\n      }\"\n      doc\" # switch (${result(scrut)}) { #{ ${bodWithDflt} #}  # }\" :: returningTerm(rest, endSemi)\n    case Match(scrut, arms @ hd :: tl, els, rest) =>\n      val sd = result(scrut)\n      def cond(cse: Case) = cse match\n        case Case.Lit(lit) => doc\"$sd === ${lit.idStr}\"\n        case Case.Cls(cls, pth) => cls match\n          // case _: semantics.ModuleSymbol => doc\"=== ${result(pth)}\"\n          // [invariant:0] If the class represented by `cls` does not exist at\n          // runtime, then `pth` is a dummy value and should be discarded.\n          case Elaborator.ctx.builtins.Str => doc\"typeof $sd === 'string'\"\n          case Elaborator.ctx.builtins.Num => doc\"typeof $sd === 'number'\"\n          case Elaborator.ctx.builtins.Bool => doc\"typeof $sd === 'boolean'\"\n          case Elaborator.ctx.builtins.Int => doc\"globalThis.Number.isInteger($sd)\"\n          case Elaborator.ctx.builtins.BigInt => doc\"typeof $sd === 'bigint'\"\n          case Elaborator.ctx.builtins.Symbol.module => doc\"typeof $sd === 'symbol'\"\n          case Elaborator.ctx.builtins.TypedArray => doc\"globalThis.ArrayBuffer.isView($sd) && !($sd instanceof globalThis.DataView)\"\n          case _: ModuleOrObjectSymbol => doc\"$sd instanceof ${result(pth)}.class\"\n          case _ => doc\"$sd instanceof ${result(pth)}\"\n        case Case.Tup(len, inf) => doc\"$runtimeVar.Tuple.isArrayLike($sd) && $sd.length ${if inf then \">=\" else \"===\"} ${len}\"\n        case Case.Field(name = n, safe = false) =>\n          doc\"\"\"typeof $sd === \"object\" && $sd !== null && \"${n.name}\" in $sd\"\"\"\n        case Case.Field(name = n, safe = true) =>\n          doc\"\"\"\"${n.name}\" in $sd\"\"\"\n      val h = doc\" # if (${ cond(hd._1) }) ${ braced(nonBracedScoped(hd._2)(res => returningTerm(res, endSemi = false))) }\"\n      val t = tl.foldLeft(h)((acc, arm) =>\n        acc :: doc\" else if (${ cond(arm._1) }) ${ braced(nonBracedScoped(arm._2)(res => returningTerm(res, endSemi = false))) }\")\n      val e = els match\n        case S(End(_)) => doc\"\"\n        case S(el) if arms.forall(_._2.isAbortive) =>\n          // * We print the `else` branch outside, after the `if` when all arms are abortive.\n          // * This typically results in slightly more concise code.\n          // * Not sure it's necessarily a good idea, though. (Does it affect the performance of the generated code?)\n          returningTerm(el, endSemi = true)\n        case S(el) =>\n          doc\" else ${ braced(nonBracedScoped(el)(res => returningTerm(res, endSemi = false))) }\"\n        case N  => doc\"\"\n      t :: e :: returningTerm(rest, endSemi)\n    \n    case Begin(sub, thn) =>\n      doc\"${returningTerm(sub, endSemi = true)}${returningTerm(thn, endSemi)}\"\n      \n    case End(msg) if config.commentGeneratedCode && msg.nonEmpty =>\n      doc\" # /* $msg */\"\n    case End(_) => doc\"\"\n    \n    case Unreachable(msg) if config.commentGeneratedCode =>\n      if msg.isEmpty then doc\" # /* Unreachable */\"\n      else doc\" # /* Unreachable: $msg */\"\n    case Unreachable(_) => doc\"\"\n    \n    case Throw(res) =>\n      doc\" # throw ${result(res)}${mkSemi}\"\n    \n    case Break(lbl) =>\n      doc\" # break ${getVar(lbl, lbl.toLoc)}${mkSemi}\"\n      \n    case Continue(lbl) =>\n      doc\" # continue ${getVar(lbl, lbl.toLoc)}${mkSemi}\"\n      \n    case Label(lbl, loop, bod, rst) =>\n      scope.allocateName(lbl)\n      \n      // [fixme:0] TODO check scope and allocate local variables here (see: https://github.com/hkust-taco/mlscript/pull/293#issuecomment-2792229849)\n      \n      doc\" # ${getVar(lbl, lbl.toLoc)}:${if loop then doc\" while (true)\" else \"\"} \" :: braced {\n          nonBracedScoped(bod)(bd => returningTerm(bd, endSemi = true)) :: (if loop && !bod.isAbortive then doc\" # break;\" else doc\"\")\n      } :: returningTerm(rst, endSemi)\n      \n    case TryBlock(sub, fin, rst) =>\n      doc\" # try ${ braced(returningTerm(sub, endSemi = false)) } finally ${\n        braced(returningTerm(fin, endSemi = false))\n      } # ${\n        returningTerm(rst, endSemi).stripBreaks}\"\n\n    // Only nested scopes in unusual positions are handled here.\n    case Scoped(syms, body) =>\n      doc\" # \" :: braced:\n        scope.nest.givenIn:\n          blockPreamble(syms.view.filter(body.freeVars)) :: returningTerm(body, endSemi = endSemi)\n    \n    // case _ => ???\n  \n  /** We want to first reserve the names of all defined classes, object, and modules,\n    * as these will be used as the internal names for these things, which may differ from the external name.\n    * For instance, `class Foo() { ... Foo ... }` will essentially translate to\n    *     `Foo1 = function Foo() { return new Foo1.class }; Foo1.class = class Foo { ... Foo1 ... }`.\n    *   Here, we prefer the `class Foo` part to bear the original `Foo` name (and not, say, `Foo1` or `Foo2`),\n    *   as it will be visible at JS runtime.\n    *   Also note it is crucial here that the inner reference can access the outer definition `Foo1` and not `Foo`\n    *   – Foo refers to the inner class in generated code and not to the parameterized Foo class of the source.\n    * For modules, we do turn any `this` reference into a reference to the corresponding generated class,\n    * since modules represent static members and since we want them to avoid the problem of JS method debinding.\n    *   That means we must generate unique inner names, at least in the case of modules;\n    *   for instance, consider that `module M with { val x = 1; module M with { val y = x } }`\n    *   should generate something like `M2 = class M { static x = 1; static M1 = class M1 { static y = M.x } }`,\n    *   where it is crucial that the inner module's inner name M1 not clash with the outer module's inner name M.\n    * We do not reserve the names of functions, as we currently just use the source name as the inner name,\n    * since any unintentional capture will have no consequence.\n    *   For example, consider that `fun foo() = foo()` may generate something like\n    *     `foo = function foo() { return foo(); }`\n    *   or, if there was already a `foo` defined in some outer scope,\n    *     `foo1 = function foo() { return foo1(); }`\n    *   but the result has the same semantics.\n    *  */\n  def reserveNames(p: Program)(using Scope, Raise): Unit =\n    def go(blk: Block): Unit = tl.trace(s\"avoidNames ${blk.toString.take(100)}...\"):\n      blk match\n      case Define(defn, rest) =>\n        defn match\n          case d: ClsLikeDefn =>\n            val nme = scope.allocateName(d.isym)\n            d.companion match\n            case N => ()\n            case S(comp) =>\n              // * This is a bit messy.\n              // * If there is a companion module, we need to map its inner symbol to the same name\n              // * as the class' inner symbol, since in the end they are consolidated into a single definition.\n              scope.addToBindings(comp.isym, nme, shadow = false)\n          case _ => //scope.allocateName(defn.sym)\n        defn.subBlocks.foreach(go)\n        go(rest)\n      case _ => blk.subBlocks.foreach(go)\n    go(p.main)\n  \n  def program(p: Program, exprt: Opt[BlockMemberSymbol], wd: io.Path)(using Raise, Scope): Document =\n    scope.allocateName(State.definitionMetadataSymbol)\n    scope.allocateName(State.prettyPrintSymbol)\n    doc\"\"\"const ${getVar(State.definitionMetadataSymbol, N)} = globalThis.Symbol.for(\"mlscript.definitionMetadata\");\"\"\"\n      :/: doc\"\"\"const ${getVar(State.prettyPrintSymbol, N)} = globalThis.Symbol.for(\"mlscript.prettyPrint\");\"\"\"\n      :/: programBody(p, exprt, wd)\n  \n  def programBody(p: Program, exprt: Opt[BlockMemberSymbol], wd: io.Path)(using Raise, Scope): Document =\n    reserveNames(p)\n    // Allocate names for imported modules.\n    p.imports.foreach: i =>\n      i._1 -> scope.allocateName(i._1)\n    // Generate import statements.\n    val imps = p.imports.map: i =>\n      val path = i._2\n      val relPath = if path.startsWith(\"/\")\n        then \"./\" + io.Path(path).relativeTo(wd).map(_.toString).getOrElse(path)\n        else path\n      doc\"\"\"import ${getVar(i._1, N)} from \"${relPath}\";\"\"\"\n    imps.mkDocument(doc\" # \")\n    :/: nonNestedScoped(p.main)(block(_, endSemi = false)).stripBreaks\n    :: locally:\n      exprt match\n      case S(sym) => doc\"\\nlet ${sym.nme} = ${scope.lookup_!(sym, sym.toLoc)}; export default ${sym.nme};\\n\"\n      case N => doc\"\"\n  \n  def worksheet(p: Program)(using Raise, Scope): (Document, Document) =\n    reserveNames(p)\n    lazy val imps = p.imports.map: i =>\n      doc\"\"\"${getVar(i._1, N)} = await import(\"${i._2.toString}\").then(m => m.default ?? m);\"\"\"\n    p.main match\n    case Scoped(syms, body) =>\n      val fvs = body.freeVars\n      blockPreamble(p.imports.map(_._1) ++ syms.view.filter(s =>\n          !s.isInstanceOf[TempSymbol]\n          // ^ VarSymbols and TermSymbols should be kept as their value will be acessed and printed by the worksheet\n          || fvs(s))) ->\n        (imps.mkDocument(doc\" # \") :/: block(body, endSemi = false).stripBreaks)\n    case body =>\n      blockPreamble(p.imports.map(_._1)) ->\n        (imps.mkDocument(doc\" # \") :/: returningTerm(body, endSemi = false).stripBreaks)\n  \n  def genLetDecls(vars: Iterator[(Symbol, Str)]): Document =\n    if vars.isEmpty then doc\"\" else\n      doc\" # let \" :: vars.map: (_, nme) =>\n        nme\n      .toList.mkDocument(\", \")\n      :: doc\";\"\n  \n  def blockPreamble(ss: Iterable[Symbol])(using Raise, Scope): Document =\n    val vars = ss.toArray.sortBy(_.uid).iterator.map: l =>\n      whenValidatingIR:\n        if scope.lookup(l).isDefined then // * It is invalid to shadow symbols in the IR\n          raise:\n            WarningReport(msg\"var ${l.toString()} in scoped is already allocated\" -> N :: Nil)\n      l -> scope.allocateName(l)\n    genLetDecls(vars)\n\n  /** Specially handle top-level Scoped node: output the bindings, but do not add another pair of braces */\n  def nonBracedScoped(blk: Block)(k: Scope ?=> Block => Document)(using Raise, Scope): Document = blk match\n    case Scoped(syms, body) =>\n      scope.nest.givenIn:\n        blockPreamble(syms.view.filter(body.freeVars)) :: k(body)\n    case _ => k(blk)\n  \n  /** Like `nonBracedScoped`, but not not create a nested scope – useful in fringe JS scenarios */\n  def nonNestedScoped(blk: Block)(k: Block => Document)(using Raise, Scope): Document = blk match\n    case Scoped(syms, body) =>\n      blockPreamble(syms.view.filter(body.freeVars)) :: k(body)\n    case _ => k(blk)\n  \n  \n  def block(t: Block, endSemi: Bool)(using Raise, Scope): Document =\n    returningTerm(t, endSemi)\n  \n  def body(t: Block, endSemi: Bool)(using Raise, Scope): Document =\n    nonBracedScoped(t)(bd => block(bd, endSemi))\n  \n  def defineProperty(target: Document, prop: Str, value: Document, enumerable: Bool = false): Document =\n    doc\"Object.defineProperty(${target}, ${prop.escaped}, ${\n      bracketed(\"{\", \"}\", insertBreak = true):\n        (if enumerable then doc\"enumerable: true, # \" else doc\"\") :: doc\"value: ${value}\"\n    })\"\n  \n  def setupFunction(name: Option[Str], params: ParamList, body: Block, isLambda: Bool)\n      (using Raise, Scope): (Document, Document) =\n    val paramsList = params.params.map(p => scope.allocateName(p.sym))\n      .++(params.restParam.map(p => \"...\" + scope.allocateName(p.sym)))\n      .mkDocument(\", \")\n    (paramsList, this.body(body, endSemi = false))\n\n\n\nobject JSBuilder:\n  \n  def isValidIdentifier(s: Str): Bool = identifierPattern.matches(s) && !keywords.contains(s)\n  \n  // in this case, a keyword can be used as a field name\n  // e.g. `something.class` is valid\n  def isValidFieldName(s: Str): Bool = identifierPattern.matches(s)\n  \n  val keywords: Set[Str] = Set(\n    // Reserved keywords as of ECMAScript 2015\n    \"break\",\n    \"case\",\n    \"catch\",\n    \"class\",\n    \"const\",\n    \"continue\",\n    \"debugger\",\n    \"default\",\n    \"delete\",\n    \"do\",\n    \"else\",\n    \"export\",\n    \"extends\",\n    \"finally\",\n    \"for\",\n    \"function\",\n    \"if\",\n    \"import\",\n    \"in\",\n    \"instanceof\",\n    \"new\",\n    \"return\",\n    \"super\",\n    \"switch\",\n    \"this\",\n    \"throw\",\n    \"try\",\n    \"typeof\",\n    \"var\",\n    \"void\",\n    \"while\",\n    \"with\",\n    \"yield\",\n    // The following are reserved as future keywords by the ECMAScript specification.\n    // They have no special functionality at present, but they might at some future time,\n    // so they cannot be used as identifiers. These are always reserved:\n    \"enum\",\n    // The following are only reserved when they are found in strict mode code:\n    \"abstract\",\n    \"boolean\",\n    \"byte\",\n    \"char\",\n    \"double\",\n    \"final\",\n    \"float\",\n    \"goto\",\n    \"implements\",\n    \"int\",\n    \"long\",\n    \"native\",\n    \"package\",\n    \"protected\",\n    \"short\",\n    \"static\",\n    \"synchronized\",\n    \"throws\",\n    \"transient\",\n    \"volatile\",\n    // not a keyword, but cannot be declared as identifier in strict mode\n    \"arguments\",\n    \"eval\",\n  )\n  \n  def makeStringLiteral(s: Str): Str =\n    s\"\\\"${escapeStringCharacters(s)}\\\"\"\n  \n  def escapeStringCharacters(s: Str): Str =\n    s.map[Str] {\n      case '\"'  => \"\\\\\\\"\"\n      case '\\\\' => \"\\\\\\\\\"\n      case '\\b' => \"\\\\b\"\n      case '\\f' => \"\\\\f\"\n      case '\\n' => \"\\\\n\"\n      case '\\r' => \"\\\\r\"\n      case '\\t' => \"\\\\t\"\n      case c =>\n        if 0 < c && c <= 255 && !c.isControl\n        then c.toString\n        else f\"\\\\u${c.toInt}%04X\"\n    }.mkString\n  \n  extension (dsym: DefinitionSymbol[?])\n    def shouldBeLifted: Bool = \n      val bsym = dsym.asBlkMember\n      (\n        (dsym.asTrm orElse bsym.flatMap(_.asTrm)).isDefined ||\n        (dsym.asCls orElse bsym.flatMap(_.asCls)).flatMap(_.defn).exists(_.paramsOpt.isDefined)\n      ) && \n        (dsym.asModOrObj orElse dsym.asCls).isDefined\n  \nend JSBuilder\n\n\ntrait JSBuilderArgNumSanityChecks(using TL, Config, Elaborator.State)\n    extends JSBuilder:\n  \n  private val doInstrument = config.sanityChecks.isDefined\n  private val init = true\n  def instrument: Bool =\n    require(init, \"trait body is not yet initialized\")\n    doInstrument\n  \n  override def checkMLsCalls: Bool = instrument\n  override def checkSelections: Bool = instrument\n  override def freezeDefinitions: Bool = instrument\n  \n  val functionParamVarargSymbol = semantics.TempSymbol(N, \"args\")\n  \n  override def setupFunction(name: Option[Str], params: ParamList, body: Block, isLambda: Bool)(using Raise, Scope): (Document, Document) =\n    // * We used to instrument `fun f(x, y) = x + y` into something like\n    // * `function f(...args) { runtime.checkArgs(\"f\", 2, true, args.length); let x = args[0]; let y = args[1]; x + y }`\n    // * which was very verbose, in addition to possibly making things quite inefficient.\n    // * Now, we no longer instrument lambdas (which affects extra parameter lists),\n    // * and we instead use the JS builtin `arguments` array to get the number of received arguments, as in\n    // * `function f(x, y) { runtime.checkArgs(\"f\", 2, true, arguments.length); x + y }`\n    // * The idea is that later on, we'll add a runtime type sanity check as well anyway,\n    // * which will check arguments against the erased parameter type,\n    // * including checking they are not `undefined`, which should achieve most of the benefit.\n    /*\n    if instrument then\n      val paramsList = params.params.map(p => scope.allocateName(p.sym))\n      val paramRest = params.restParam.map(p => scope.allocateName(p.sym))\n      val paramsStr = scope.allocateName(functionParamVarargSymbol, shadow = true)\n      val functionName = JSBuilder.makeStringLiteral(name.fold(\"\")(n => s\"${JSBuilder.escapeStringCharacters(n)}\"))\n      val checkArgsNum = doc\"\\n$runtimeVar.checkArgs($functionName, ${params.paramCountLB}, ${params.paramCountUB.toString}, $paramsStr.length);\"\n      val paramsAssign = paramsList.zipWithIndex.map{(nme, i) =>\n        doc\"\\nlet ${nme} = ${paramsStr}[$i];\"}.mkDocument(\"\")\n      val restAssign = paramRest match\n        case N => doc\"\"\n        case S(p) => doc\"\\nlet $p = $runtimeVar.Tuple.slice($paramsStr, ${params.paramCountLB}, 0);\"\n      (doc\"...$paramsStr\", doc\"$checkArgsNum$paramsAssign$restAssign${this.body(body, endSemi = false)}\")\n    */\n    if instrument && !isLambda then\n      val functionName = JSBuilder.makeStringLiteral(name.fold(\"\")(n => s\"${JSBuilder.escapeStringCharacters(n)}\"))\n      val checkArgsNum = doc\"\\n$runtimeVar.checkArgs($functionName, ${params.paramCountLB}, ${params.paramCountUB.toString}, arguments.length);\"\n      val paramsList = params.params.map(p => scope.allocateName(p.sym))\n        .++(params.restParam.map(p => \"...\" + scope.allocateName(p.sym)))\n        .mkDocument(\", \")\n      (paramsList,\n        doc\"$checkArgsNum${this.body(body, endSemi = false)}\")\n    else\n      super.setupFunction(name, params, body, isLambda = isLambda)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Analysis.scala",
    "content": "package hkmc2\npackage codegen\npackage llir\n\nimport scala.annotation.tailrec\nimport scala.collection.immutable.*\nimport scala.collection.mutable.ListBuffer\nimport scala.collection.mutable.{HashMap => MutHMap}\nimport scala.collection.mutable.{HashSet => MutHSet, Set => MutSet}\n\nimport mlscript._\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\n\nimport syntax.Tree.UnitLit\nimport semantics.{BuiltinSymbol, InnerSymbol}\n\nclass UsefulnessAnalysis(verbose: Bool = false): \n  import Expr._\n  import Node._\n\n  def log(x: Any) = if verbose then println(x)\n  \n  val uses = MutHMap[(Local, Int), Int]()\n  val defs = MutHMap[Local, Int]()\n\n  private def addDef(x: Local) =\n    defs.update(x, defs.getOrElse(x, 0) + 1)\n  \n  private def addUse(x: Local) =\n    val def_count = defs.get(x) match\n      case None => throw Exception(s\"Use of undefined variable $x\")\n      case Some(value) => value\n    val key = (x, defs(x))\n    uses.update(key, uses.getOrElse(key, 0) + 1)\n  \n  private def f(x: TrivialExpr): Unit = x match\n    case Ref(name) => addUse(name)\n    case _ => ()\n\n  private def f(x: Expr): Unit = x match\n    case Ref(name) => addUse(name)\n    case Literal(lit) =>\n    case CtorApp(name, args) => args.foreach(f)\n    case Select(name, cls, field) => addUse(name)\n    case BasicOp(name, args) => args.foreach(f)\n    case AssignField(assignee, _, _, value) =>\n      addUse(assignee)\n      f(value)\n  \n  private def f(x: Node): Unit = x match\n    case Result(res) => res.foreach(f)\n    case Jump(defn, args) => args.foreach(f)\n    case Case(scrut, cases, default) => \n      scrut match\n        case Ref(name) => addUse(name)\n        case _ => ()\n      cases.foreach { case (cls, body) => f(body) }; default.foreach(f)\n    case LetMethodCall(names, cls, method, args, body) => addUse(method); args.foreach(f); names.foreach(addDef); f(body)\n    case LetExpr(name, expr, body) => f(expr); addDef(name); f(body)\n    case LetCall(names, defn, args, body) => args.foreach(f); names.foreach(addDef); f(body)\n  \n  def run(x: Func) =\n    x.params.foreach(addDef)\n    f(x.body)\n    uses.toMap\n\nclass FreeVarAnalysis(ctx: Local => Func):\n  import Expr._\n  import Node._\n\n  private val visited = MutHSet[Local]()\n  private def f(using defined: Set[Local])(defn: Func, fv: Set[Local]): Set[Local] =\n    val defined2 = defn.params.foldLeft(defined)((acc, param) => acc + param)\n    f(using defined2)(defn.body, fv)\n  private def f(using defined: Set[Local])(expr: Expr, fv: Set[Local]): Set[Local] = expr match\n    case Ref(name) => if defined.contains(name) then fv else fv + name\n    case Literal(lit) => fv\n    case CtorApp(name, args) => args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n    case Select(name, cls, field) => if defined.contains(name) then fv else fv + name\n    case BasicOp(name, args) => args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n    case AssignField(assignee, _, _, value) => f(using defined)(\n      value.toExpr, \n      if defined.contains(assignee) then fv + assignee else fv\n    ) \n  private def f(using defined: Set[Local])(node: Node, fv: Set[Local]): Set[Local] = node match\n    case Result(res) => res.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n    case Jump(defn, args) =>\n      args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n    case Case(scrut, cases, default) =>\n      val fv2 = scrut match\n        case Ref(name) => if defined.contains(name) then fv else fv + name\n        case _ => fv\n      val fv3 = cases.foldLeft(fv2):\n        case (acc, (cls, body)) => f(using defined)(body, acc)\n      default match\n        case Some(body) => f(using defined)(body, fv3)\n        case None => fv3\n    case Panic(msg) => fv\n    case LetMethodCall(resultNames, cls, method, args, body) =>\n      var fv2 = args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n      val defined2 = resultNames.foldLeft(defined)((acc, name) => acc + name)\n      f(using defined2)(body, fv2)\n    case LetExpr(name, expr, body) =>\n      val fv2 = f(using defined)(expr, fv)\n      val defined2 = defined + name\n      f(using defined2)(body, fv2)\n    case LetCall(resultNames, defn, args, body) =>\n      var fv2 = args.foldLeft(fv)((acc, arg) => f(using defined)(arg.toExpr, acc))\n      val defined2 = resultNames.foldLeft(defined)((acc, name) => acc + name)\n      f(using defined2)(body, fv2)\n  def run(node: Node) = f(using Set.empty)(node, Set.empty)\n  def run_with(node: Node, defined: Set[Local]) = f(using defined)(node, Set.empty)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Builder.scala",
    "content": "package hkmc2\npackage codegen\npackage llir\n\nimport scala.collection.mutable.ListBuffer\nimport scala.collection.mutable.{HashMap => MutMap}\n\nimport mlscript.utils.*\nimport mlscript.utils.shorthands.*\nimport utils.*\nimport document.*\nimport Message.MessageContext\nimport Scope.scope\n\nimport syntax.Tree\nimport semantics.*\nimport codegen.llir.{ Program => LlirProgram, Node, Func }\nimport codegen.Program\nimport cpp.Expr.StrLit\n\nprivate def bErrStop(msg: Message)(using Raise) =\n  raise(ErrorReport(msg -> N :: Nil,\n    source = Diagnostic.Source.Compilation))\n  throw LowLevelIRError(\"stopped\")\n\nfinal case class FuncInfo(paramsSize: Int)\n\nfinal case class BuiltinSymbols(\n  var callableSym: Opt[Local] = None,\n  var thisSym: Opt[Local] = None,\n  var builtinSym: Opt[Local] = None,\n  fieldSym: MutMap[Int, VarSymbol] = MutMap.empty,\n  applySym: MutMap[Int, BlockMemberSymbol] = MutMap.empty,\n  tupleSym: MutMap[Int, DefinitionSymbol[? <: ClassLikeDef]] = MutMap.empty,\n  runtimeSym: Opt[TempSymbol] = None,\n):\n  def hiddenClasses = callableSym.toSet\n\nfinal case class Ctx(\n  def_acc: ListBuffer[Func],\n  class_acc: ListBuffer[ClassInfo],\n  symbol_ctx: Map[Local, Local] = Map.empty,\n  fn_ctx: Map[Local, FuncInfo] = Map.empty, // is a known function\n  class_ctx: Map[DefinitionSymbol[? <: ClassLikeDef], ClassInfo] = Map.empty,\n  class_sym_ctx: Map[BlockMemberSymbol, DefinitionSymbol[? <: ClassLikeDef]] = Map.empty,\n  flow_ctx: Map[Path, Local] = Map.empty,\n  isTopLevel: Bool = true,\n  method_class: Opt[DefinitionSymbol[? <: ClassLikeDef]] = None,\n  builtinSym: BuiltinSymbols = BuiltinSymbols()\n):\n  def addFuncName(n: Local, paramsSize: Int) = copy(fn_ctx = fn_ctx + (n -> FuncInfo(paramsSize)))\n  def findFuncName(n: Local)(using Raise) = fn_ctx.get(n) match\n    case None => bErrStop(msg\"Function name not found: ${n.toString()}\")\n    case Some(value) => value\n  def addClassInfo(n: DefinitionSymbol[? <: ClassLikeDef], bsym: BlockMemberSymbol, m: ClassInfo) =\n    copy(class_ctx = class_ctx + (n -> m), class_sym_ctx = class_sym_ctx + (bsym -> n))\n  def addName(n: Local, m: Local) = copy(symbol_ctx = symbol_ctx + (n -> m))\n  def findName(n: Local)(using Raise) = symbol_ctx.get(n) match\n    case None => bErrStop(msg\"Name not found: ${n.toString}\")\n    case Some(value) => value\n  def findClassInfo(n: DefinitionSymbol[? <: ClassLikeDef])(using Raise) = class_ctx.get(n) match\n    case None => bErrStop(msg\"Class not found: ${n.toString}\")\n    case Some(value) => value\n  def addKnownClass(n: Path, m: Local) = copy(flow_ctx = flow_ctx + (n -> m))\n  def setClass(c: DefinitionSymbol[? <: ClassLikeDef]) = copy(method_class = Some(c))\n  def nonTopLevel = copy(isTopLevel = false)\n\nobject Ctx:\n  def empty(using Elaborator.State) =\n    Ctx(ListBuffer.empty, ListBuffer.empty, builtinSym = BuiltinSymbols(\n      runtimeSym = Some(Elaborator.State.runtimeSymbol)\n    ))\n\nfinal class LlirBuilder(using Elaborator.State)(tl: TraceLogger, uid: FreshInt):\n  import tl.{trace, log, logs}\n  given TraceLogger = tl\n  \n  def er = Expr.Ref\n  def nr = Node.Result\n  def sr(x: Local) = er(x)\n  def nsr(xs: Ls[Local]) = xs.map(er(_))\n\n  private def allocIfNew(l: Local)(using Raise, Scope): String =\n    trace[Str](s\"allocIfNew begin: $l\", x => s\"allocIfNew end: $x\"):\n      if scope.lookup(l).isDefined then\n        getVar_!(l)\n      else\n        scope.allocateName(l)\n\n  private def getVar_!(l: Local)(using Raise, Scope): String =\n    trace[Str](s\"getVar_! begin\", x => s\"getVar_! end: $x\"):\n      l match\n      case ts: semantics.TermSymbol =>\n        ts.owner match\n        case S(owner) => ts.id.name\n        case N =>\n          ts.id.name\n      case ts: semantics.BlockMemberSymbol => // this means it's a locally-defined member\n        ts.nme\n      case ts: semantics.InnerSymbol =>\n        scope.findThis_!(ts)\n      case _ => scope.lookup_!(l, N)\n\n  private def symMap(s: Local)(using ctx: Ctx)(using Raise, Scope) =\n    ctx.findName(s)\n\n  private def newTemp = TempSymbol(N, \"x\")\n  private def newNamedTemp(name: Str) = TempSymbol(N, name)\n  private def newNamedBlockMem(name: Str) = BlockMemberSymbol(name, Nil)\n  private def newNamed(name: Str) = VarSymbol(Tree.Ident(name))\n  private def newClassSym(name: Str) =\n    ClassSymbol(Tree.TypeDef(hkmc2.syntax.Cls, Tree.Empty(), N), Tree.Ident(name))\n  private def newTupleSym(len: Int) =\n    ClassSymbol(Tree.TypeDef(hkmc2.syntax.Cls, Tree.Empty(), N), Tree.Ident(s\"Tuple$len\"))\n  private def newVarSym(name: Str) = VarSymbol(Tree.Ident(name))\n  private def newFunSym(name: Str) = BlockMemberSymbol(name, Nil)\n  private def newBuiltinSym(name: Str) = BuiltinSymbol(name, false, false, false, false)\n  private def builtinField(n: Int)(using Ctx) = summon[Ctx].builtinSym.fieldSym.getOrElseUpdate(n, newVarSym(s\"field$n\"))\n  private def builtinApply(n: Int)(using Ctx) = summon[Ctx].builtinSym.applySym.getOrElseUpdate(n, newFunSym(s\"apply$n\"))\n  private def builtinTuple(n: Int)(using Ctx) = summon[Ctx].builtinSym.tupleSym.getOrElseUpdate(n, newTupleSym(n))\n  private def builtinCallable(using ctx: Ctx) : Local =\n    ctx.builtinSym.callableSym match\n      case None => \n        val sym = newBuiltinSym(\"Callable\")\n        ctx.builtinSym.callableSym = Some(sym);\n        sym\n      case Some(value) => value\n  private def builtinThis(using ctx: Ctx) : Local =\n    ctx.builtinSym.thisSym match\n      case None => \n        val sym = newBuiltinSym(\"<this>\")\n        ctx.builtinSym.thisSym = Some(sym);\n        sym\n      case Some(value) => value\n  private def builtin(using ctx: Ctx) : Local =\n    ctx.builtinSym.builtinSym match\n      case None => \n        val sym = newBuiltinSym(\"<builtin>\")\n        ctx.builtinSym.builtinSym = Some(sym);\n        sym\n      case Some(value) => value\n\n  private def bBind(name: Opt[Local], e: Result, body: Block)(k: TrivialExpr => Ctx ?=> Node)(ct: Block)(using ctx: Ctx)(using Raise, Scope): Node =\n    trace[Node](s\"bBind begin: $name\", x => s\"bBind end: ${x.show}\"):\n      bResult(e):\n        case r: Expr.Ref =>\n          given Ctx = ctx.addName(name.getOrElse(newTemp), r.sym)\n          log(s\"bBind ref: $name -> $r\")\n          bBlock(body)(k)(ct)\n        case l: Expr.Literal =>\n          val v = newTemp\n          given Ctx = ctx.addName(name.getOrElse(newTemp), v)\n          log(s\"bBind lit: $name -> $v\")\n          Node.LetExpr(v, l, bBlock(body)(k)(ct))\n  \n  private def bArgs(e: Ls[Arg])(k: Ls[TrivialExpr] => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope): Node =\n    trace[Node](s\"bArgs begin\", x => s\"bArgs end: ${x.show}\"):\n      e match\n      case Nil => k(Nil)\n      case Arg(spread, x) :: xs => bPath(x):\n        case r: TrivialExpr => bArgs(xs):\n          case rs: Ls[TrivialExpr] => k(r :: rs)\n  \n  private def bPaths(e: Ls[Path])(k: Ls[TrivialExpr] => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope): Node =\n    trace[Node](s\"bArgs begin\", x => s\"bArgs end: ${x.show}\"):\n      e match\n      case Nil => k(Nil)\n      case x :: xs => bPath(x):\n        case r: TrivialExpr => bPaths(xs):\n          case rs: Ls[TrivialExpr] => k(r :: rs)\n  \n  private def bNestedFunDef(e: FunDefn)(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope): Node =\n    val FunDefn(_own, sym, dSym, params, body) = e\n    // generate it as a single named lambda expression that may be self-recursing\n    if params.length === 0 then\n      bErrStop(msg\"Function without arguments not supported: ${params.length.toString}\")\n    else\n      val fstParams = params.head\n      val wrappedLambda = params.tail.foldRight(body)((params, acc) => Return(Lambda(params, acc), false))\n      bLam(Lambda(fstParams, wrappedLambda), S(sym.nme), S(sym))(k)(using ctx)\n\n  private def bFunDef(e: FunDefn)(using ctx: Ctx)(using Raise, Scope): Func =\n    trace[Func](s\"bFunDef begin: ${e.sym}\", x => s\"bFunDef end: ${x.show}\"):\n      val FunDefn(_own, sym, dSym, params, body) = e\n      assert(ctx.isTopLevel)\n      if params.length === 0 then\n        bErrStop(msg\"Function without arguments not supported: ${params.length.toString}\")\n      else \n        val paramsList = params.head.params\n        val ctx2 = paramsList.foldLeft(ctx)((acc, x) => acc.addName(x.sym, x.sym)).nonTopLevel\n        val pl = paramsList.map(_.sym)\n        val wrappedLambda = params.tail.foldRight(body)((params, acc) => Return(Lambda(params, acc), false))\n        Func(\n          uid.make, sym, params = pl, resultNum = 1,\n          body = bBlockWithEndCont(wrappedLambda)(x => Node.Result(Ls(x)))(using ctx2)\n        )\n\n  private def bMethodDef(e: FunDefn)(using ctx: Ctx)(using Raise, Scope): Func =\n    trace[Func](s\"bFunDef begin: ${e.sym}\", x => s\"bFunDef end: ${x.show}\"):\n      val FunDefn(_own, sym, dSym, params, body) = e\n      if !ctx.isTopLevel then\n        bErrStop(msg\"Non top-level definition ${sym.nme} not supported\")\n      else if params.length === 0 then\n        bErrStop(msg\"Function without arguments not supported: ${params.length.toString}\")\n      else \n        val paramsList = params.head.params\n        val ctx2 = paramsList.foldLeft(ctx)((acc, x) => acc.addName(x.sym, x.sym)).nonTopLevel\n        val pl = paramsList.map(_.sym)\n        val wrappedLambda = params.tail.foldRight(body)((params, acc) => Return(Lambda(params, acc), false))\n        Func(\n          uid.make, sym, params = pl, resultNum = 1,\n          body = bBlockWithEndCont(wrappedLambda)(x => Node.Result(Ls(x)))(using ctx2)\n        )\n\n  private def bClsLikeDef(e: ClsLikeDefn)(using ctx: Ctx)(using Raise, Scope): ClassInfo =\n    trace[ClassInfo](s\"bClsLikeDef begin\", x => s\"bClsLikeDef end: ${x.show}\"):\n      val ClsLikeDefn(\n        _own, isym, _sym, _ctorSym, kind, paramsOpt, auxParams, parentSym, methods, privateFields, publicFields, preCtor, ctor, mod, bufferable) = e\n      if !ctx.isTopLevel then\n        bErrStop(msg\"Non top-level definition ${isym.toString()} not supported\")\n      else\n        val clsParams = paramsOpt.fold(Nil)(_.paramSyms)\n        given Ctx = ctx.setClass(isym)\n        val funcs = methods.map(bMethodDef)\n        def parentFromPath(p: Path): Ls[Local] = p match\n          case Value.Ref(l, disamb) => fromMemToClass(l.orElseDisamb(disamb)) :: Nil\n          case _ => bErrStop(msg\"Unsupported parent path ${p.toString()}\")\n        ClassInfo(\n          uid.make,\n          isym,\n          clsParams,\n          parentSym.fold(Nil)(parentFromPath),\n          funcs.map(f => f.name -> f).toMap,\n        )\n  \n  private def bLam(lam: Lambda, nameHint: Opt[Str], recName: Opt[Local])(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope) : Node =\n    trace[Node](s\"bLam begin\", x => s\"bLam end: ${x.show}\"):\n      val Lambda(params, body) = lam\n      // Generate an auxiliary class inheriting from Callable\n      val freeVars = lam.freeVarsLLIR -- body.definedVars -- recName.iterator -- ctx.fn_ctx.keySet\n      log(s\"Defined vars: ${body.definedVars}\")\n      log(s\"Match free vars: ${lam.freeVarsLLIR -- body.definedVars} ${ctx.fn_ctx.keySet} ${params.params.map(p => p.sym)}\")\n      log(s\"Lot: $lam\")\n      val name = newClassSym(s\"Lambda${nameHint.fold(\"\")(x => \"_\" + x)}\")\n      val freeVarsList = freeVars.toList\n      val args = freeVarsList.map(symMap)\n      // args may have the same name (with different uid)\n      // it's not allowed when generating the names of fields in the backend\n      val clsParams = args.zipWithIndex.map:\n        case (arg, i) => newVarSym(s\"lam_arg$i\")\n      val applyParams = params.params\n      // add the parameters of lambda expression to the context\n      val ctx2 = applyParams.foldLeft(ctx)((acc, x) => acc.addName(x.sym, x.sym))\n      // add the free variables (class parameters) to the context\n      val ctx3 = clsParams.iterator.zip(freeVarsList).foldLeft(ctx2):\n        case (acc, (param, arg)) => acc.addName(arg, param)\n      val ctx4 = recName.fold(ctx3)(x => ctx3.addName(x, builtinThis)).nonTopLevel\n      val pl = applyParams.map(_.sym)\n      val method = Func(\n        uid.make,\n        builtinApply(params.params.length),\n        params = pl,\n        resultNum = 1,\n        body = bBlockWithEndCont(body)(x => Node.Result(Ls(x)))(using ctx4)\n      )\n      ctx.class_acc += ClassInfo(\n        uid.make,\n        name,\n        clsParams,\n        builtinCallable :: Nil,\n        Map(method.name -> method),\n      )\n      val v: Local = newTemp\n      val new_ctx = recName.fold(ctx)(x => ctx.addName(x, v))\n      Node.LetExpr(v, Expr.CtorApp(name, args.map(sr)), k(v |> sr)(using new_ctx))\n\n  private def bValue(v: Value)(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope) : Node =\n    trace[Node](s\"bValue { $v } begin\", x => s\"bValue end: ${x.show}\"):\n      v match\n      case Value.Ref(l: TermSymbol, _) if l.owner.nonEmpty =>\n        k(l |> sr)\n      case Value.Ref(sym, disamb) if sym.nme.isCapitalized =>\n        val v: Local = newTemp\n        Node.LetExpr(v, Expr.CtorApp(fromMemToClass(sym.orElseDisamb(disamb)), Ls()), k(v |> sr))\n      case Value.Ref(l, _) => \n        ctx.fn_ctx.get(l) match\n          case Some(f) =>\n            val tempSymbols = (0 until f.paramsSize).map(x => newNamed(\"arg\"))\n            val paramsList = PlainParamList(\n              (0 until f.paramsSize).zip(tempSymbols).map((_n, sym) =>\n                Param(FldFlags.empty, sym, N, Modulefulness.none)).toList)\n            val app = Call(v, tempSymbols.map(x => Arg(N, Value.Ref(x))).toList ne_:: Nil)(true, false, false)\n            bLam(Lambda(paramsList, Return(app, false)), S(l.nme), N)(k)\n          case None =>\n            k(ctx.findName(l) |> sr)\n      case Value.This(sym) => bErrStop(msg\"Unsupported value: This\")\n      case Value.Lit(lit) => k(Expr.Literal(lit))\n        \n  \n  private def getClassOfField(p: DefinitionSymbol[?])(using ctx: Ctx)(using Raise, Scope): Local =\n    trace[Local](s\"bClassOfField { $p } begin\", x => s\"bClassOfField end: $x\"):\n      p match\n      case ts: TermSymbol => ts.owner.get\n      case ms: MemberSymbol => \n        ms.defn match\n        case Some(d: ClassLikeDef) => d.owner.get\n        case Some(d: TermDefinition) => d.owner.get\n        case Some(value) => bErrStop(msg\"Member symbol without class definition ${value.toString}\")\n        case None => bErrStop(msg\"Member symbol without definition ${ms.toString}\") \n  \n  private def fromMemToClass(m: Symbol)(using ctx: Ctx)(using Raise, Scope): DefinitionSymbol[? <: ClassLikeDef] =\n    trace[DefinitionSymbol[? <: ClassLikeDef]](s\"bFromMemToClass $m\", x => s\"bFromMemToClass end: $x\"):\n      m match\n      case ms: DefinitionSymbol[?] =>\n        ms.defn match\n        case Some(d: TermDefinition) =>\n          val companion = d.companionClass.getOrElse(bErrStop(msg\"Term definition without companion ${d.toString}\"))\n          fromMemToClass(companion)\n        case Some(d: ClassLikeDef) => d.sym.asClsLike.getOrElse(bErrStop(msg\"Class definition without symbol\"))\n        case Some(value) => bErrStop(msg\"Member symbol without class definition ${value.toString}\")\n        case None => bErrStop(msg\"Member symbol without definition ${ms.toString}\") \n      case _ => bErrStop(msg\"Unsupported symbol kind ${m.toString}\")\n        \n  \n  private def bPath(p: Path)(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope) : Node =\n    trace[Node](s\"bPath { $p } begin\", x => s\"bPath end: ${x.show}\"):\n      p match\n      case s @ Select(Value.Ref(sym, _), Tree.Ident(\"Unit\")) if sym is ctx.builtinSym.runtimeSym.get =>\n        bPath(Value.Lit(Tree.UnitLit(false)))(k)\n      case s @ Select(Value.Ref(cls: ClassSymbol, _), name) if ctx.method_class.contains(cls) =>\n        s.symbol match\n          case None =>\n            ctx.flow_ctx.get(p) match\n              case Some(cls) =>\n                k(cls |> sr)\n              case None =>\n                bErrStop(msg\"Unsupported selection by users\")\n          case Some(s) =>\n            k(s |> sr)\n      case s @ DynSelect(qual, fld, arrayIdx) =>\n        bErrStop(msg\"Unsupported dynamic selection\")\n      case s @ Select(qual, name) =>\n        log(s\"bPath Select: $qual.$name with ${s.symbol}\")\n        s.symbol match\n          case None =>\n            ctx.flow_ctx.get(qual) match\n              case Some(cls) =>\n                bPath(qual):\n                  case q: Expr.Ref =>\n                    val v: Local = newTemp\n                    val field = name.name\n                    Node.LetExpr(v, Expr.Select(q.sym, cls, field), k(v |> sr))\n                  case q: Expr.Literal =>\n                    bErrStop(msg\"Unsupported select on literal\")\n              case None =>\n                log(s\"${ctx.flow_ctx}\")\n                bErrStop(msg\"Unsupported selection by users\")\n          case Some(value) =>\n            bPath(qual):\n              case q: Expr.Ref =>\n                val v: Local = newTemp\n                val cls = getClassOfField(s.symbol.get)\n                val field = name.name\n                Node.LetExpr(v, Expr.Select(q.sym, cls, field), k(v |> sr))\n              case q: Expr.Literal =>\n                bErrStop(msg\"Unsupported select on literal\")\n      case x: Value => bValue(x)(k)\n\n  private def bResult(r: Result)(k: TrivialExpr => Ctx ?=> Node)(using ctx: Ctx)(using Raise, Scope) : Node =\n    trace[Node](s\"bResult begin\", x => s\"bResult end: ${x.show}\"):\n      r match\n      case Call(_, argss) if argss.sizeIs > 1 =>\n        bErrStop(msg\"Calls with multiple argument lists are not yet supported in LLIR\")\n      case Call(Value.Ref(sym: BuiltinSymbol, _), argss) =>\n        bArgs(argss.flatten):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetExpr(v, Expr.BasicOp(sym, args), k(v |> sr))\n      case Call(Value.Ref(sym, S(disamb)), argss) if disamb.defn.exists(defn => defn match\n        case cls: ClassLikeDef => true\n        case trm: TermDefinition => trm.companionClass.isDefined\n        case _ => false\n      ) =>\n        bArgs(argss.flatten):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetExpr(v, Expr.CtorApp(fromMemToClass(disamb), args), k(v |> sr))\n      case Call(Value.Ref(sym: DefinitionSymbol[?], _), argss) if sym.defn.exists(defn => defn match\n        case cls: ClassLikeDef => true\n        case trm: TermDefinition => trm.companionClass.isDefined\n        case _ => false\n      ) =>\n        bArgs(argss.flatten):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetExpr(v, Expr.CtorApp(fromMemToClass(sym), args), k(v |> sr))\n      case Call(s @ Value.Ref(sym, _), argss) =>\n        val v: Local = newTemp\n        ctx.fn_ctx.get(sym) match\n          case Some(f) =>\n            bArgs(argss.flatten):\n              case args: Ls[TrivialExpr] =>\n                Node.LetCall(Ls(v), sym, args, k(v |> sr))\n          case None =>\n            bPath(s):\n              case f: TrivialExpr =>\n                bArgs(argss.flatten):\n                  case args: Ls[TrivialExpr] =>\n                    Node.LetMethodCall(Ls(v), builtinCallable, builtinApply(args.length), f :: args, k(v |> sr))\n      case Call(Select(Value.Ref(_: TopLevelSymbol, _), Tree.Ident(\"builtin\")), argss) =>\n        bArgs(argss.flatten):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetCall(Ls(v), builtin, args, k(v |> sr))\n      case Call(Select(Select(Value.Ref(_: TopLevelSymbol, _), Tree.Ident(\"console\")), Tree.Ident(\"log\")), argss) =>\n        bArgs(argss.flatten):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetCall(Ls(v), builtin, Expr.Literal(Tree.StrLit(\"println\")) :: args, k(v |> sr))\n      case Call(Select(Select(Value.Ref(_: TopLevelSymbol, _), Tree.Ident(\"Math\")), Tree.Ident(mathPrimitive)), argss) =>\n        bArgs(argss.flatten):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetCall(Ls(v), builtin, Expr.Literal(Tree.StrLit(mathPrimitive)) :: args, k(v |> sr))\n      case Call(s @ Select(r @ Value.Ref(sym, _), Tree.Ident(fld)), argss) if s.symbol.isDefined =>\n        bPath(r):\n          case r =>\n            bArgs(argss.flatten):\n              case args: Ls[TrivialExpr] =>\n                val v: Local = newTemp\n                log(s\"Method Call Select: $r.$fld with ${s.symbol}\")\n                Node.LetMethodCall(Ls(v), getClassOfField(s.symbol.get), s.symbol.get, r :: args, k(v |> sr))\n      case Call(_, _) => bErrStop(msg\"Unsupported kind of Call ${r.toString()}\")\n      case Instantiate(\n        false,\n        Value.Ref(sym, S(disamb: (ClassSymbol | ModuleOrObjectSymbol))), argss) =>\n        bArgs(argss.flatten):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetExpr(v, Expr.CtorApp(fromMemToClass(disamb), args), k(v |> sr))\n      case Instantiate(_, cls, argss) =>\n        bErrStop(msg\"Unsupported kind of Instantiate\")\n      case lam @ Lambda(params, body) => bLam(lam, N, N)(k)\n      case Tuple(false, elems) =>\n        bArgs(elems):\n          case args: Ls[TrivialExpr] =>\n            val v: Local = newTemp\n            Node.LetExpr(v, Expr.CtorApp(builtinTuple(elems.length), args), k(v |> sr))\n      case Record(mut, fields) => bErrStop(msg\"Unsupported value: Rcd\")\n      case x: Path => bPath(x)(k)\n\n  private def bBlockWithEndCont(blk: Block)(k: TrivialExpr => Ctx ?=> Node)(using Ctx)(using Raise, Scope) : Node =\n    bBlock(blk)(k)(End(\"\"))\n\n  private def bBlock(blk: Block)(k: TrivialExpr => Ctx ?=> Node)(ct: Block)(using ctx: Ctx)(using Raise, Scope) : Node =\n    trace[Node](s\"bBlock begin\", x => s\"bBlock end: ${x.show}\"):\n      blk match\n      case Match(scrut, arms, dflt, rest) =>\n        bPath(scrut):\n          case e: TrivialExpr =>\n            val nextCont = Begin(rest, ct)\n            val jp: BlockMemberSymbol = newNamedBlockMem(\"j\")\n            val fvset = nextCont.freeVarsLLIR -- nextCont.definedVars -- ctx.fn_ctx.keySet\n            val fvs1 = fvset.toList\n            log(s\"Match free vars: $fvset ${nextCont.freeVarsLLIR -- nextCont.definedVars} $fvs1\")\n            val new_ctx = fvs1.foldLeft(ctx)((acc, x) => acc.addName(x, x))\n            val fvs = fvs1.map(new_ctx.findName(_))\n            def cont(x: TrivialExpr)(using ctx: Ctx) = Node.Jump(\n              jp,\n              fvs1.map(x => ctx.findName(x)).map(sr)\n            )\n            val casesList: Ls[(Pat, Node)] = arms.map:\n              case (Case.Lit(lit), body) =>\n                (Pat.Lit(lit), bBlock(body)(cont)(nextCont)(using ctx))\n              case (Case.Cls(cls, _), body) =>\n                (Pat.Class(cls), bBlock(body)(cont)(nextCont)(using ctx))\n              case (Case.Tup(len, inf), body) =>\n                val ctx2 = ctx.addKnownClass(scrut, builtinTuple(len))\n                (Pat.Class(builtinTuple(len)), bBlock(body)(cont)(nextCont)(using ctx2))\n            val defaultCase = dflt.map(bBlock(_)(cont)(nextCont)(using ctx))\n            val jpdef = Func(\n              uid.make,\n              jp,\n              params = fvs,\n              resultNum = 1,\n              bBlock(rest)(k)(ct)(using new_ctx),\n            )\n            summon[Ctx].def_acc += jpdef\n            Node.Case(e, casesList, defaultCase)\n      case Return(res, implct) => bResult(res)(x => Node.Result(Ls(x)))\n      case Throw(Instantiate(false, Select(Value.Ref(_, _), ident),\n          Ls(Arg(N, Value.Lit(Tree.StrLit(e)))) :: Nil))\n      if ident.name === \"Error\" =>\n        Node.Panic(e)\n      case Label(label, loop, body, rest) => TODO(\"Label not supported\")\n      case Break(label) => TODO(\"Break not supported\")\n      case Continue(label) => TODO(\"Continue not supported\")\n      case Begin(sub, rest) =>\n        // re-associate rest blocks to correctly handle the continuation\n        sub match\n          case _: BlockTail => \n            val definedVars = sub.definedVars\n            definedVars.foreach(allocIfNew)\n            bBlock(sub)(x => bBlock(rest)(k)(ct))(Begin(rest, ct))\n          case Assign(lhs, rhs, rest2) =>\n            bBlock(Assign(lhs, rhs, Begin(rest2, rest)))(k)(ct)\n          case Begin(sub, rest2) =>\n            bBlock(Begin(sub, Begin(rest2, rest)))(k)(ct)\n          case Define(defn, rest2) =>\n            bBlock(Define(defn, Begin(rest2, rest)))(k)(ct)\n          case Match(scrut, arms, dflt, rest2) =>\n            bBlock(Match(scrut, arms, dflt, Begin(rest2, rest)))(k)(ct)\n          case _ => TODO(s\"Other non-tail sub components of Begin not supported $sub\")\n      case TryBlock(sub, finallyDo, rest) => TODO(\"TryBlock not supported\")\n      case Assign(lhs, rhs, rest) =>\n        bBind(S(lhs), rhs, rest)(k)(ct)\n      case AssignField(lhs, nme, rhs, rest) => TODO(\"AssignField not supported\")\n      case Define(fd: FunDefn, rest) =>\n        if ctx.isTopLevel then\n          val f = bFunDef(fd)\n          ctx.def_acc += f\n          bBlock(rest)(k)(ct)\n        else\n          bNestedFunDef(fd):\n            case r: TrivialExpr =>\n              bBlock(rest)(k)(ct)\n      case Define(_: ClsLikeDefn, rest) => bBlock(rest)(k)(ct)\n      case End(msg) => k(Expr.Literal(Tree.UnitLit(false)))\n      case Scoped(_, body) => bBlock(body)(k)(ct)\n      case _: Block =>\n        val docBlock = blk.showAsTree\n        bErrStop(msg\"Unsupported block: $docBlock\")\n  \n  def registerClasses(b: Block)(using ctx: Ctx)(using Raise, Scope): Ctx =\n    b match\n    case Define(cd @ ClsLikeDefn(_own, isym, sym, ctorSym, kind, _paramsOpt, auxParams,\n        parentSym, methods, privateFields, publicFields, preCtor, ctor, mod, bufferable), rest) =>\n      if !auxParams.isEmpty then\n        bErrStop(msg\"The class ${sym.nme} has auxiliary parameters, which are not yet supported\")\n      val c = bClsLikeDef(cd)\n      ctx.class_acc += c\n      val new_ctx = ctx.addClassInfo(isym, sym, c)\n      log(s\"Define class: ${isym.toString()} -> ${ctx}\")\n      registerClasses(rest)(using new_ctx)\n    case _ =>\n      b.subBlocks.foldLeft(ctx)((ctx, rest) => registerClasses(rest)(using ctx))\n\n  def registerBuiltinClasses(using ctx: Ctx)(using Raise, Scope): Ctx =\n    ctx.builtinSym.tupleSym.foldLeft(ctx):\n      case (ctx, (len, sym)) =>\n        val c = ClassInfo(uid.make, sym, (0 until len).map(x => builtinField(x)).toList, Nil, Map.empty)\n        ctx.class_acc += c\n        ctx.addClassInfo(sym, BlockMemberSymbol(sym.nme, Nil), c)\n  \n  def registerFunctions(b: Block)(using ctx: Ctx)(using Raise, Scope): Ctx =\n    var ctx2 = ctx\n    new BlockTraverser:\n      applyBlock(b)\n\n      override def applyBlock(b: Block): Unit = b match\n        case Match(scrut, arms, dflt, rest) => applyBlock(rest)\n        case Return(res, implct) =>\n        case Throw(exc) =>\n        case Label(label, loop, body, rest) => applyBlock(rest)\n        case Break(label) =>\n        case Continue(label) =>\n        case Begin(sub, rest) => applyBlock(rest)\n        case TryBlock(sub, finallyDo, rest) => applyBlock(rest)\n        case Assign(lhs, rhs, rest) => applyBlock(rest)\n        case AssignField(_, _, _, rest) => applyBlock(rest)\n        case AssignDynField(lhs, fld, arrayIdx, rhs, rest) => applyBlock(rest)\n        case Define(defn, rest) => applyDefn(defn); applyBlock(rest)\n        case Scoped(_, body) => applyBlock(body)\n        case End(msg) =>\n      \n      override def applyDefn(defn: Defn): Unit = defn match\n        case f: FunDefn => applyFunDefn(f)\n        case _ => ()\n  \n      override def applyFunDefn(fun: FunDefn): Unit =\n        val FunDefn(_own, sym, dSym, params, body) = fun\n        if params.length === 0 then\n          bErrStop(msg\"Function without arguments not supported: ${params.length.toString}\")\n        ctx2 = ctx2.addFuncName(sym, params.head.params.length)\n        log(s\"Define function: ${sym.nme} -> ${ctx2}\")\n    ctx2\n  \n  def bProg(e: Program)(using Raise, Scope, Ctx): (LlirProgram, Ctx) =\n    var ctx = summon[Ctx]\n    \n    // * Classes may be defined after other things such as functions,\n    // * especially now that the elaborator moves all functions to the top of the block.\n    ctx = registerClasses(e.main)(using ctx)\n    ctx = registerFunctions(e.main)(using ctx)\n    \n    log(s\"Classes: ${ctx.class_ctx}\")\n\n    val entryBody = bBlockWithEndCont(e.main)(x => Node.Result(Ls(x)))(using ctx)\n    val entryFunc = Func(\n      uid.make, newFunSym(\"entry\"), params = Ls.empty, resultNum = 1,\n      body = entryBody\n    )\n    ctx.def_acc += entryFunc\n\n    ctx = registerBuiltinClasses(using ctx)\n    \n    val prog = LlirProgram(ctx.class_acc.toSet, ctx.def_acc.toSet, entryFunc.name)\n\n    ctx.class_acc.clear()\n    ctx.def_acc.clear()\n    \n    (prog, ctx)\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Fresh.scala",
    "content": "package hkmc2.codegen.llir\n\nfinal class FreshInt:\n  private var counter = 0\n  def make: Int = {\n    val tmp = counter\n    counter += 1\n    tmp\n  }\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Interp.scala",
    "content": "package hkmc2\npackage codegen\npackage llir\n\nimport mlscript.*\nimport mlscript.utils.*\nimport scala.collection.immutable.*\nimport scala.collection.mutable.ListBuffer\nimport shorthands.*\nimport scala.util.boundary, boundary.break\n\nimport syntax.Tree\nimport hkmc2.utils.TraceLogger\nimport semantics.BuiltinSymbol\n\nenum Stuck:\n  case StuckExpr(expr: Expr, msg: Str)\n  case StuckNode(node: Node, msg: Str)\n\n  override def toString: String =\n    this match\n      case StuckExpr(expr, msg) => s\"StuckExpr(${expr.show}, $msg)\"\n      case StuckNode(node, msg) => s\"StuckNode(${node.show}, $msg)\"\n\nfinal case class InterpreterError(message: String) extends Exception(message)\n\nclass Interpreter(tl: TraceLogger):\n  import tl.{trace, log, logs}\n  import Stuck._\n\n  private case class Configuration(\n    var context: Ctx\n  )\n\n  private type Result[T] = Either[Stuck, T]\n\n  private enum Value:\n    case Class(cls: ClassInfo, var fields: Ls[Value])\n    case Literal(lit: hkmc2.syntax.Literal)\n\n    override def toString: String =\n      import hkmc2.syntax.Tree.*\n      this match\n        case Class(cls, fields) => s\"${cls.symbol.nme}(${fields.mkString(\",\")})\"\n        case Literal(IntLit(lit)) => lit.toString\n        case Literal(BoolLit(lit)) => lit.toString \n        case Literal(DecLit(lit)) => lit.toString\n        case Literal(StrLit(lit)) => lit.toString\n        case Literal(UnitLit(isNullNotUndefined)) =>\n          if isNullNotUndefined then \"null\" else \"undefined\"\n\n  private final case class Ctx(\n    bindingCtx: Map[Local, Value],\n    classCtx: Map[Local, ClassInfo],\n    funcCtx: Map[Local, Func],\n    thisVal: Opt[Value],\n  )\n  \n  import Node._\n  import Expr._\n\n  private def getTrue(using ctx: Ctx) = Value.Literal(hkmc2.syntax.Tree.BoolLit(true))\n  private def getFalse(using ctx: Ctx) = Value.Literal(hkmc2.syntax.Tree.BoolLit(false))\n  \n  private def eval(op: Str, x1: Value, x2: Value)(using ctx: Ctx): Opt[Value] =\n    import Value.{Literal => Li}\n    import hkmc2.syntax.Tree.*\n    (op, x1, x2) match\n    case (\"+\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x + y)))\n    case (\"-\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x - y)))\n    case (\"*\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x * y)))\n    case (\"/\", Li(IntLit(x)), Li(IntLit(y))) => S(Li(IntLit(x / y)))\n    case (\"&&\", Li(BoolLit(x)), Li(BoolLit(y))) => S(if x && y then getTrue else getFalse)\n    case (\"||\", Li(BoolLit(x)), Li(BoolLit(y))) => S(if x || y then getTrue else getFalse)\n    case (\"==\", Li(IntLit(x)), Li(IntLit(y))) => S(if x === y then getTrue else getFalse)\n    case (\"===\", Li(IntLit(x)), Li(IntLit(y))) => S(if x === y then getTrue else getFalse)\n    case (\"!=\", Li(IntLit(x)), Li(IntLit(y))) => S(if x != y then getTrue else getFalse)\n    case (\"<=\", Li(IntLit(x)), Li(IntLit(y))) => S(if x <= y then getTrue else getFalse)\n    case (\">=\", Li(IntLit(x)), Li(IntLit(y))) => S(if x >= y then getTrue else getFalse)\n    case (\">\", Li(IntLit(x)), Li(IntLit(y))) => S(if x > y then getTrue else getFalse)\n    case (\"<\", Li(IntLit(x)), Li(IntLit(y))) => S(if x < y then getTrue else getFalse)\n    case _ => N\n\n  private def evalArgs(using ctx: Ctx)(exprs: Ls[TrivialExpr]): Result[Ls[Value]] =\n    var values = ListBuffer.empty[Value]\n    var stuck: Opt[Stuck] = None\n    exprs foreach { expr =>\n      stuck match\n        case None => eval_t(expr) match\n          case L(x) => stuck = Some(x)\n          case R(x) => values += x\n        case _ => ()\n    } \n    stuck.toLeft(values.toList)\n\n  private def eval_t(expr: TrivialExpr)(using ctx: Ctx): Result[Value] = expr match\n    case Ref(x: BuiltinSymbol) => x.nme match\n      case \"<this>\" => ctx.thisVal.toRight(StuckExpr(expr.toExpr, s\"undefined this value\"))\n      case _ => L(StuckExpr(expr.toExpr, s\"undefined builtin ${x.nme}\"))\n    case Ref(x) => ctx.bindingCtx.get(x).toRight(StuckExpr(expr.toExpr, s\"undefined variable $x\"))\n    case Literal(x) => R(Value.Literal(x))\n  \n  private def eval(expr: Expr)(using ctx: Ctx): Result[Value] = expr match\n    case x: TrivialExpr => eval_t(x)\n    case CtorApp(cls, args) =>\n      for\n        xs <- evalArgs(args)\n        cls <- ctx.classCtx.get(cls).toRight(StuckExpr(expr, s\"undefined class ${cls.nme}\"))\n      yield Value.Class(cls, xs)\n    case Select(name, cls, field) if field.forall(_.isDigit) =>\n      val nth = field.toInt\n      ctx.bindingCtx.get(name).toRight(StuckExpr(expr, s\"undefined variable $name\")).flatMap {\n        case Value.Class(cls2, xs) if cls === cls2.symbol =>\n          xs.lift(nth) match\n            case Some(x) => R(x)\n            case None => L(StuckExpr(expr, s\"unable to find selected field $field\"))\n        case Value.Class(cls2, xs) => L(StuckExpr(expr, s\"unexpected class $cls2\"))\n        case x => L(StuckExpr(expr, s\"unexpected value $x\"))\n      }\n    case Select(name, cls, field) =>\n      ctx.bindingCtx.get(name).toRight(StuckExpr(expr, s\"undefined variable $name\")).flatMap {\n        case Value.Class(cls2, xs) if cls === cls2.symbol =>\n          xs.zip(cls2.fields).find{_._2.nme === field} match\n            case Some((x, _)) => R(x)\n            case None => L(StuckExpr(expr, s\"unable to find selected field $field\"))\n        case Value.Class(cls2, xs) => L(StuckExpr(expr, s\"unexpected class $cls2\"))\n        case x => L(StuckExpr(expr, s\"unexpected value $x\"))\n      }\n    case BasicOp(name, args) => boundary:\n      evalArgs(args).flatMap(\n        xs => \n          name.nme match\n            case \"+\" | \"-\" | \"*\" | \"/\" | \"==\" | \"===\" | \"!=\" | \"<=\" | \">=\" | \"<\" | \">\" => \n              if xs.length < 2 then break:\n                L(StuckExpr(expr, s\"not enough arguments for basic operation $name\"))\n              else eval(name.nme, xs.head, xs.tail.head).toRight(StuckExpr(expr, s\"unable to evaluate basic operation\"))\n            case _ => L(StuckExpr(expr, s\"unexpected basic operation $name\")))\n    case AssignField(assignee, cls, field, value) =>\n      for\n        x <- eval_t(Ref(assignee): TrivialExpr)\n        y <- eval_t(value)\n        res <- x match\n          case obj @ Value.Class(cls2, xs) if cls === cls2 =>\n            xs.zip(cls2.fields).find{_._2.nme === field} match\n              case Some((_, _)) =>\n                obj.fields = xs.map(x => if x === obj then y else x)\n                // Ideally, we should return a unit value here, but here we return the assignee value for simplicity.\n                R(obj)\n              case None => L(StuckExpr(expr, s\"unable to find selected field $field\"))\n          case Value.Class(cls2, xs) => L(StuckExpr(expr, s\"unexpected class $cls2\"))\n          case x => L(StuckExpr(expr, s\"unexpected value $x\"))\n      yield res\n\n  private def eval(node: Node)(using ctx: Ctx): Result[Ls[Value]] = node match\n    case Result(res) => evalArgs(res)\n    case Jump(func, args) =>\n      for\n        xs <- evalArgs(args)\n        func <- ctx.funcCtx.get(func).toRight(StuckNode(node, s\"undefined function ${func.nme}\"))\n        ctx1 = ctx.copy(bindingCtx = ctx.bindingCtx ++ func.params.zip(xs))\n        res <- eval(func.body)(using ctx1)\n      yield res\n    case Case(scrut, cases, default) =>\n      eval_t(scrut) flatMap {\n        case Value.Class(cls, fields) => \n          cases.find {\n            case (Pat.Class(cls2), _) => cls.symbol === cls2\n            case _ => false\n          } match {\n            case Some((_, x)) => eval(x)\n            case None => \n              default match\n                case S(x) => eval(x)\n                case N => L(StuckNode(node, s\"can not find the matched case, ${cls.symbol} expected\"))\n          }\n        case Value.Literal(lit) => \n          cases.find {\n            case (Pat.Lit(lit2), _) => lit === lit2\n            case _ => false\n          } match {\n            case Some((_, x)) => eval(x)\n            case None => \n              default match\n                case S(x) => eval(x)\n                case N => L(StuckNode(node, s\"can not find the matched case, $lit expected\"))\n          }\n      }\n    case LetExpr(name, expr, body) =>\n      for\n        x <- eval(expr)\n        ctx1 = ctx.copy(bindingCtx = ctx.bindingCtx + (name -> x))\n        res <- eval(body)(using ctx1)\n      yield res\n    case LetMethodCall(names, cls, method, args, body) =>\n      def lookup_method(cls: ClassInfo, method: Local): Option[Func] =\n        // The methods with the same name in a subclass will override the method in the superclass.\n        // But they have different symbols for the method definition.\n        // So, we don't directly use the method symbol to find the method.\n        // Instead, we fallback to use the method name.\n        cls.methods.find(_._1.nme === method.nme).map(_._2)\n      for\n        ys <- evalArgs(args).flatMap {\n          case (ths @ Value.Class(cls2, xs)) :: args =>\n            lookup_method(cls2, method).toRight(StuckNode(node, s\"undefined method ${method.nme}\")).flatMap { method =>\n              val ctx1 = ctx.copy(\n                bindingCtx = ctx.bindingCtx ++ cls2.fields.zip(xs) ++ method.params.zip(args),\n                thisVal = S(ths)\n              )\n              eval(method.body)(using ctx1)\n            }\n          case _ => L(StuckNode(node, s\"not enough arguments for method call, or the first argument is not a class\"))\n        }\n        ctx2 = ctx.copy(bindingCtx = ctx.bindingCtx ++ names.zip(ys))\n        res <- eval(body)(using ctx2)\n      yield res\n    case LetCall(names, func, args, body) =>\n      for\n        xs <- evalArgs(args)\n        func <- ctx.funcCtx.get(func).toRight(StuckNode(node, s\"undefined function ${func.nme}\"))\n        ctx1 = ctx.copy(bindingCtx = ctx.bindingCtx ++ func.params.zip(xs))\n        ys <- eval(func.body)(using ctx1)\n        ctx2 = ctx.copy(bindingCtx = ctx.bindingCtx ++ names.zip(ys))\n        res <- eval(body)(using ctx2)\n      yield res\n    case Panic(msg) => L(StuckNode(node, msg))\n\n  private def f(prog: Program): Ls[Value] =\n    val Program(classes, defs, entry) = prog\n    given Ctx = Ctx(\n      bindingCtx = Map.empty,\n      classCtx = classes.map(cls => (cls.symbol, cls)).toMap,\n      funcCtx = defs.map(func => (func.name, func)).toMap,\n      thisVal = None,\n    )\n    val entryFunc = summon[Ctx].funcCtx.getOrElse(entry, throw InterpreterError(\"Entry doesn't exist\"))\n    assert(entryFunc.params.isEmpty, \"Entry function should not have parameters\")\n    eval(entryFunc.body) match\n      case R(x) => x\n      case L(x) => throw InterpreterError(\"Stuck evaluation: \" + x.toString)\n    \n  def interpret(prog: Program): Str =\n    val node = f(prog) \n    node.map(_.toString).mkString(\",\")\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/llir/Llir.scala",
    "content": "package hkmc2\npackage codegen.llir\n\nimport mlscript._\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\n\nimport syntax._\nimport Message.MessageContext\nimport document._\nimport codegen._\n\nimport util.Sorting\nimport collection.immutable.SortedSet\nimport language.implicitConversions\nimport collection.mutable.{Map as MutMap, Set as MutSet, HashMap, ListBuffer}\nimport hkmc2.semantics._\n\nprivate def raw(x: String): Document = doc\"$x\"\n\nfinal case class LowLevelIRError(message: String) extends Exception(message)\n\nval hiddenPrefixes = Set(\"Tuple\")\n\ndef defaultHidden(x: Str): Bool =\n  hiddenPrefixes.exists(x.startsWith)\n\ncase class Program(\n  classes: Set[ClassInfo],\n  defs: Set[Func],\n  entry: Local,\n):\n  def show = LlirDebugPrinter.mkDocument(this).toString\n\nimplicit object ClassInfoOrdering extends Ordering[ClassInfo] {\n  def compare(a: ClassInfo, b: ClassInfo) = a.id.compare(b.id)\n}\n\ncase class ClassInfo(\n  id: Int,\n  symbol: DefinitionSymbol[? <: ClassLikeDef],\n  fields: Ls[VarSymbol],\n  parents: Ls[Local],\n  methods: Map[Local, Func],\n):\n  override def hashCode: Int = id\n  def show = LlirDebugPrinter.mkDocument(this).toString\n\nclass FuncRef(var func: Local):\n  def name: String = func.nme\n  override def equals(o: Any): Bool = o match {\n    case o: FuncRef => o.name === this.name\n    case _ => false\n  }\n\nimplicit object FuncOrdering extends Ordering[Func] {\n  def compare(a: Func, b: Func) = a.id.compare(b.id)\n}\n\ncase class Func(\n  id: Int,\n  name: BlockMemberSymbol,\n  params: Ls[Local],\n  resultNum: Int,\n  body: Node\n):\n  var recBoundary: Opt[Int] = None\n  override def hashCode: Int = id\n  def show = LlirDebugPrinter.mkDocument(this).toString\n\nsealed trait TrivialExpr:\n  import Expr._\n  def toExpr: Expr = this match { case x: Expr => x }\n  def foldRef(f: Local => TrivialExpr): TrivialExpr = this match\n    case Ref(sym) => f(sym)\n    case _ => this\n  def iterRef(f: Local => Unit): Unit = this match\n    case Ref(sym) => f(sym)\n    case _ => ()\n  def show: String\n\nenum Expr:\n  case Ref(sym: Local) extends Expr, TrivialExpr \n  case Literal(lit: hkmc2.syntax.Literal) extends Expr, TrivialExpr\n  case CtorApp(cls: DefinitionSymbol[? <: ClassLikeDef], args: Ls[TrivialExpr])\n  case Select(name: Local, cls: Local, field: Str)\n  case BasicOp(name: BuiltinSymbol, args: Ls[TrivialExpr])\n  case AssignField(assignee: Local, cls: Local, field: Str, value: TrivialExpr)\n  def show = LlirDebugPrinter.mkDocument(this).toString\n\nenum Pat:\n  case Lit(lit: hkmc2.syntax.Literal)\n  case Class(cls: Local)\n\nenum Node:\n  // Terminal forms:\n  case Result(res: Ls[TrivialExpr])\n  case Jump(func: Local, args: Ls[TrivialExpr])\n  case Case(scrutinee: TrivialExpr, cases: Ls[(Pat, Node)], default: Opt[Node])\n  case Panic(msg: Str)\n  // Intermediate forms:\n  case LetExpr(name: Local, expr: Expr, body: Node)\n  case LetMethodCall(names: Ls[Local], cls: Local, method: Local, args: Ls[TrivialExpr], body: Node)\n  case LetCall(names: Ls[Local], func: Local, args: Ls[TrivialExpr], body: Node)\n  def show = LlirDebugPrinter.mkDocument(this).toString\n\nabstract class LlirPrinting:\n  import hkmc2.utils.*\n  import hkmc2.semantics.Elaborator.State\n\n  def mkDocument(local: Local): Document\n  def mkDocument(lit: Literal): Document = doc\"${lit.idStr}\"\n  def mkDocument(texpr: TrivialExpr): Document = texpr match\n    case Expr.Ref(sym) => mkDocument(sym)\n    case Expr.Literal(lit) => mkDocument(lit)\n\n  def mkDocument(expr: Expr): Document =\n    expr match\n      case Expr.Ref(sym) => doc\"${mkDocument(sym)}\"\n      case Expr.Literal(lit) => doc\"${lit.idStr}\"\n      case Expr.CtorApp(cls, args) =>\n        doc\"${mkDocument(cls)}(${args.map(mkDocument).mkDocument(\",\")})\"\n      case Expr.Select(name, cls, field) =>\n        doc\"${mkDocument(name)}.<${mkDocument(cls)}:$field>\"\n      case Expr.BasicOp(sym, args) =>\n        doc\"${sym.nme}(${args.map(mkDocument).mkDocument(\",\")})\"\n      case Expr.AssignField(assignee, clsInfo, fieldName, value) => \n        doc\"${mkDocument(assignee)}.${fieldName} := ${mkDocument(value)}\"\n  def mkDocument(node: Node): Document =\n    node match\n      case Node.Result(res) => doc\"${res.map(mkDocument).mkDocument(\",\")}\"\n      case Node.Jump(func, args) =>\n        doc\"jump ${mkDocument(func)}(${args.map(mkDocument).mkDocument(\",\")})\"\n      case Node.Case(scrutinee, cases, default) =>\n        val docFirst = doc\"case ${mkDocument(scrutinee)} of\"\n        val docCases = cases.map {\n          case (pat, node) => doc\"${pat.toString} => #{  # ${mkDocument(node)} #} \"\n        }.mkDocument(doc\" # \")\n        default match\n          case N => doc\"$docFirst #{  # $docCases #} \"\n          case S(dc) =>\n            val docDeft = doc\"_ => #{  # ${mkDocument(dc)} #} \"\n            doc\"$docFirst #{  # $docCases # $docDeft #} \"\n      case Node.Panic(msg) =>\n        doc\"panic ${s\"\\\"$msg\\\"\"}\"\n      case Node.LetExpr(x, expr, body) => \n        doc\"let ${mkDocument(x)} = ${mkDocument(expr)} in # ${mkDocument(body)}\"\n      case Node.LetMethodCall(xs, cls, method, args, body) =>\n        doc\"let ${xs.map(mkDocument).mkDocument(\",\")} = ${mkDocument(cls)}.${method.nme}(${args.map(mkDocument).mkDocument(\",\")}) in # ${mkDocument(body)}\"\n      case Node.LetCall(xs, func, args, body) => \n        doc\"let* (${xs.map(mkDocument).mkDocument(\",\")}) = ${mkDocument(func)}(${args.map(mkDocument).mkDocument(\",\")}) in # ${mkDocument(body)}\"\n  def mkDocument(defn: Func): Document =\n    def docParams(params: Ls[Local]): Document =\n      params.map(mkDocument).mkDocument(\"(\", \",\", \")\")\n    given Conversion[String, Document] = raw\n    val docFirst = doc\"def ${mkDocument(defn.name)}${docParams(defn.params)} =\"\n    val docBody = mkDocument(defn.body)\n    doc\"$docFirst #{  # $docBody #} \"\n  def mkDocument(cls: ClassInfo): Document =\n    given Conversion[String, Document] = raw\n    val ext = if cls.parents.isEmpty then doc\"\" else \" extends \" :: cls.parents.map(mkDocument).mkDocument(\", \")\n    val docFirst = doc\"class ${mkDocument(cls.symbol)}(${cls.fields.map(_.nme).mkDocument(\",\")})$ext\"\n    if cls.methods.isEmpty then\n      doc\"$docFirst\"\n    else\n      val docMethods = cls.methods.map { (_, func) => mkDocument(func) }.toList.mkDocument(doc\" # \")\n      doc\"$docFirst { #{  # $docMethods #}  # }\"\n  def mkDocument(prog: Program, hide: Str => Bool = defaultHidden): Document =\n    given Conversion[String, Document] = raw\n    val t1 = prog.classes.iterator.filterNot(c => hide(c.symbol.nme)).toArray\n    val t2 = prog.defs.toArray\n    Sorting.quickSort(t1)\n    Sorting.quickSort(t2)\n    val docClasses = t1.filterNot(c => hide(c.symbol.nme)).map(mkDocument).toList.mkDocument(doc\" # \")\n    val docDefs = t2.map(mkDocument).toList.mkDocument(doc\" # \")\n    val docMain = doc\"entry = ${mkDocument(prog.entry)}\"\n    doc\" #{ $docClasses\\n$docDefs\\n$docMain #} \"\n\nclass LlirPrinter(using Raise, hkmc2.utils.Scope) extends LlirPrinting:\n  import hkmc2.utils.*\n  import hkmc2.semantics.Elaborator.State\n  import Scope.scope\n  \n  def getVar(l: Local): String = l match\n    case ts: hkmc2.semantics.TermSymbol =>\n      ts.owner match\n      case S(owner) => scope.lookup_!(ts, N)\n      case N => scope.lookup_!(ts, N)\n    case ts: hkmc2.semantics.InnerSymbol =>\n      scope.lookup_!(ts, N)\n    case _ => scope.lookup_!(l, N)\n  def allocIfNew(l: Local): String =\n    scope.lookup(l) match\n      case S(_) => getVar(l)\n      case N =>\n        scope.allocateName(l)\n  override def mkDocument(local: Local): Document = allocIfNew(local)\n        \nobject LlirDebugPrinter extends LlirPrinting:\n  import hkmc2.utils.*\n  def docSymWithUid(sym: Local): Document = doc\"${sym.nme}$$${sym.uid.toString()}\"\n  override def mkDocument(local: Local): Document = docSymWithUid(local)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/Ctx.scala",
    "content": "package hkmc2\npackage codegen\npackage wasm\npackage text\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport document.*\nimport document.Document\nimport semantics.{\n  BlockMemberSymbol, Elaborator, InnerSymbol, LabelSymbol, ModuleOrObjectSymbol, ParamList, Symbol, TempSymbol,\n},\n  Elaborator.State\nimport text.Param as WasmParam\nimport Instructions.*\n\nimport scala.collection.immutable.ListMap\nimport scala.collection.mutable.{ArrayBuffer as ArrayBuf, Map as MutMap, LinkedHashSet}\nimport scala.reflect.ClassTag\n\n/** Metadata for a REPL binding that can be imported by later Wasm modules. */\nsealed trait SessionBinding:\n  /** Returns the deduplication key for this binding. */\n  def bindingKey: Str\n\n  /** Returns the symbols that should resolve to this binding. */\n  def bindingSyms: Seq[Local]\n\n  /** Returns the export name if this binding is re-exported. */\n  def exportNameOpt: Opt[Str] = N\n\nobject SessionBinding:\n  val ReplModuleName: Str = \"repl\"\n\n/** Metadata for an exported function that later Wasm REPL modules can import.\n  *\n  * @param sym\n  *   The source symbol associated with the exported function.\n  * @param moduleName\n  *   The Wasm module name used by the import.\n  * @param exportName\n  *   The exported function name within `moduleName`.\n  * @param funcType\n  *   The Wasm function type expected by the import.\n  */\nfinal case class SessionFunc(\n    sym: BlockMemberSymbol,\n    wrapId: Opt[Str] -> Opt[Str],\n    moduleName: Str,\n    exportName: Str,\n    funcType: FunctionType,\n) extends SessionBinding:\n  def bindingKey: Str = s\"func:$moduleName:$exportName\"\n  def bindingSyms: Seq[Local] = sym :: Nil\n  override def exportNameOpt: Opt[Str] = S(exportName)\n\n/** Metadata for an exported global that later Wasm REPL modules can import.\n  *\n  * @param sym\n  *   The source symbol associated with the exported global.\n  * @param moduleName\n  *   The Wasm module name used by the import.\n  * @param exportName\n  *   The exported global name within `moduleName`.\n  * @param globalType\n  *   The Wasm global type expected by the import.\n  */\nfinal case class SessionGlobal(\n    sym: Symbol,\n    wrapId: Opt[Str] -> Opt[Str],\n    moduleName: Str,\n    exportName: Str,\n    globalType: GlobalType,\n) extends SessionBinding:\n  def bindingKey: Str = s\"global:$moduleName:$exportName\"\n  def bindingSyms: Seq[Local] = sym :: Nil\n  override def exportNameOpt: Opt[Str] = S(exportName)\n\n/** Metadata for a class type made visible to later Wasm REPL modules.\n  *\n  * @param sym\n  *   The block member symbol of the class.\n  * @param typeInfo\n  *   The Wasm type information that must be recreated in importing modules.\n  * @param runtimeTags\n  *   The class' runtime tag together with descendant class tags.\n  * @param aliasSyms\n  *   Additional symbols that should resolve to this class binding.\n  */\nfinal case class SessionClass(\n    sym: BlockMemberSymbol,\n    wrapId: Opt[Str] -> Opt[Str],\n    compType: CompType,\n    objectTag: Opt[Int],\n    runtimeTags: LinkedHashSet[Int],\n    aliasSyms: Seq[Local] = Nil,\n) extends SessionBinding:\n  def bindingKey: Str = s\"class:${sym.uid}\"\n  def bindingSyms: Seq[Local] = sym +: aliasSyms\n\n/** Metadata for a singleton object's backing global made visible to later Wasm REPL modules.\n  *\n  * @param blockSym\n  *   The block member symbol of the singleton object.\n  * @param objectSym\n  *   Optional object/module symbol that should also resolve to this singleton binding.\n  * @param moduleName\n  *   The Wasm module name used by the import.\n  * @param exportName\n  *   The exported global name within `moduleName`.\n  * @param globalTy\n  *   The Wasm reference type of the singleton backing global.\n  */\nfinal case class SessionSingleton(\n    blockSym: BlockMemberSymbol,\n    objectSym: Opt[ModuleOrObjectSymbol],\n    wrapId: Opt[Str] -> Opt[Str],\n    moduleName: Str,\n    exportName: Str,\n    globalTy: RefType,\n) extends SessionBinding:\n  def bindingKey: Str = s\"singleton:$moduleName:$exportName\"\n  def bindingSyms: Seq[Local] = blockSym +: objectSym.toSeq\n  override def exportNameOpt: Opt[Str] = S(exportName)\n\n/** The emitted Wasm module together with REPL/session export metadata.\n  *\n  * @param wat\n  *   The generated WAT for the module.\n  * @param entryName\n  *   The name of the module entry function.\n  * @param systemMemMinPages\n  *   The minimum number of imported system-memory pages required by the module.\n  * @param sessionExports\n  *   Session bindings exported by this module for use by later REPL blocks.\n  */\nfinal case class CompiledWasmModule(\n    wat: Document,\n    entryName: Str,\n    systemMemMinPages: Int,\n    sessionExports: Seq[SessionBinding],\n)\n\n/** Context used while collecting REPL/session exports for a single Wasm module.\n  *\n  * @param symbolsToExport\n  *   The symbols from the current module that should be recorded as session exports.\n  * @param collectedBindings\n  *   The session bindings accumulated while compiling the current module.\n  */\nfinal class SessionExportCtx(\n    val symbolsToExport: Set[Local],\n    val collectedBindings: ArrayBuf[SessionBinding],\n):\n  def shouldExport(sym: Local): Bool = symbolsToExport(sym)\n\n  def emit(binding: SessionBinding): Unit =\n    collectedBindings += binding\n\n  def freshCollector(): SessionExportCtx =\n    SessionExportCtx(symbolsToExport, ArrayBuf.empty)\n\n/** A Wasm function and its associated information.\n  *\n  * Each instance of [[FuncInfo]] represents a single function definition in a WebAssembly module.\n  *\n  * @param sym\n  *   The source [[Symbol]] which this function is generated from.\n  * @param wrapId\n  *   An pair of optional strings for adding a prefix and suffix to the generated identifier of this function.\n  * @param typeUse\n  *   [[TypeUse]] of the function's type in the module's type section.\n  * @param params\n  *   [[Seq]] of parameter local variables and their names.\n  * @param resultTypes\n  *   The result types of the function.\n  * @param locals\n  *   [[Seq]] of local variables (excluding parameters) and their names.\n  * @param body\n  *   The expression of the function body.\n  * @param exportName\n  *   Optional export name.\n  */\nclass FuncInfo(\n    val sym: BlockMemberSymbol | TempSymbol,\n    val typeUse: TypeUse,\n    val params: Seq[Local -> SymIdx],\n    val resultTypes: Seq[Result],\n    val locals: Seq[Local -> SymIdx],\n    val body: Expr,\n    val exportName: Opt[Str],\n    val wrapId: Opt[Str] -> Opt[Str] = N -> N,\n)(using Ctx, Raise) extends ToWat:\n\n  /** Symbolic identifier for the function. */\n  val id = SymIdx(summon[Ctx].funcScp.allocateOrGetNameWrapped(sym, wrapId))\n\n  /** Returns the type of this function as a [[SignatureType]]. */\n  def getSignatureType: SignatureType = SignatureType(\n    params = params.map((_, paramIdx) => WasmParam(paramIdx, RefType.anyref)),\n    results = resultTypes,\n  )\n\n  def toWat: Document =\n    doc\"\"\"(func ${id.toWat}${\n        exportName.fold(doc\"\"): e =>\n          doc\"\"\" (export \"$e\")\"\"\"\n      } ${typeUse.toWat}${\n        getSignatureType.toWat.surroundUnlessEmpty(doc\" \")\n      } #{ ${\n        locals.map: p =>\n          doc\"(local ${p._2.toWat} ${RefType.anyref.toWat})\"\n        .mkDocument(doc\" # \").surroundUnlessEmpty(doc\" # \")\n      } # ${body.toWat} #} )\"\"\"\nend FuncInfo\n\n/** A Wasm global and its associated information.\n  *\n  * Each instance of [[GlobalInfo]] represents a single global definition in a WebAssembly module.\n  *\n  * @param globalType\n  *   The type of the global.\n  * @param init\n  *   The initializer expression for the global.\n  * @param exportName\n  *   Optional export name.\n  * @param sym\n  *   The source [[Symbol]] which this global is generated from.\n  * @param wrapId\n  *   An pair of optional strings for adding a prefix and suffix to the generated identifier of this global.\n  */\nclass GlobalInfo(\n    val globalType: GlobalType,\n    val init: Expr,\n    val exportName: Opt[Str],\n    val sym: Symbol,\n    val wrapId: Opt[Str] -> Opt[Str] = N -> N,\n)(using Ctx, Raise) extends ToWat:\n\n  /** Symbolic identifier for the global. */\n  val id: SymIdx = SymIdx(summon[Ctx].globalScp.allocateOrGetNameWrapped(sym, wrapId))\n\n  def toWat: Document =\n    doc\"\"\"(global ${id.toWat}${\n        exportName.fold(doc\"\"): name =>\n          doc\"\"\" (export \"$name\")\"\"\"\n      } ${globalType.toWat} ${init.toWat})\"\"\"\nend GlobalInfo\n\n/** A WebAssembly memory and its associated information.\n  *\n  * Each instance of [[MemInfo]] represents a single memory definition in a WebAssembly module.\n  *\n  * @param sym\n  *   The source [[TempSymbol]] which this memory is generated from.\n  * @param memType\n  *   The type of the memory.\n  * @param wrapId\n  *   An pair of optional strings for adding a prefix and suffix to the generated identifier of this memory.\n  */\nclass MemInfo(val sym: TempSymbol, val memType: MemType, val wrapId: Opt[Str] -> Opt[Str] = N -> N)(using Ctx, Raise)\n    extends ToWat:\n\n  /** Symbolic identifier for the global. */\n  val id: SymIdx = SymIdx(summon[Ctx].memoryScp.allocateOrGetNameWrapped(sym, wrapId))\n\n  def toWat: Document = doc\"(memory ${id.toWat} ${memType.toWat})\"\nend MemInfo\n\n/** A Wasm type and its associated information.\n  *\n  * Each instance of [[TypeInfo]] represents a single type definition in a WebAssembly module.\n  *\n  * @param sym\n  *   The source [[Symbol]] which this type is generated from.\n  * @param wrapId\n  *   An pair of optional strings for adding a prefix and suffix to the generated identifier of this type.\n  * @param compType\n  *   The composite type this type definition represents.\n  * @param objectTag\n  *   An optional object tag number associated with this type.\n  */\nfinal class TypeInfo(\n    val sym: BlockMemberSymbol | TempSymbol,\n    val compType: CompType,\n    val objectTag: Opt[Int],\n    val wrapId: Opt[Str] -> Opt[Str] = N -> N,\n)(using Ctx, Raise) extends ToWat:\n\n  /** Symbolic identifier for the type. */\n  val id = SymIdx(summon[Ctx].typeScp.allocateOrGetNameWrapped(sym, wrapId))\n\n  def toWat: Document = doc\"(type ${id.toWat} ${compType.toWat})\"\n\n/** A WebAssembly exception tag declaration.\n  *\n  * In Wasm, a `tag` names an exception kind and points to a function type that describes the payload values carried by\n  * `throw tag ...` and extracted by matching `catch tag ...`.\n  *\n  * @param typeUse\n  *   The function type referenced by this tag.\n  * @param sym\n  *   The source [[Symbol]] which this tag is generated from.\n  */\nclass TagInfo(val typeUse: TypeUse, val sym: Symbol, val wrapId: Opt[Str] -> Opt[Str] = N -> N)(using Ctx, Raise)\n    extends ToWat:\n\n  /** Symbolic identifier for the tag. */\n  val id: SymIdx = SymIdx(summon[Ctx].tagScp.allocateOrGetNameWrapped(sym, wrapId))\n\n  def toWat: Document =\n    doc\"\"\"(tag ${id.toWat} (export \"${id.id}\") ${typeUse.toWat})\"\"\"\nend TagInfo\n\nenum WasmIntrinsicType:\n  case TupleArray(mutable: Bool)\n\n/** Class containing identifiers of labels to jump to when breaking or continuing from a control flow structure.\n  *\n  * @param breakLabel\n  *   The identifier of the label to jump to for exiting the control flow structure, e.g. for `break` statements.\n  * @param continueLabel\n  *   The identifier of the label to jump to for continuing the control flow structure, e.g. for `continue` statements\n  *   in loops. This is `None` for non-loop control flow structures.\n  */\ncase class LabelTarget(breakLabel: Str, continueLabel: Opt[Str])\n\nobject FunctionCtx:\n\n  def funcCtx(using funcCtx: FunctionCtx): FunctionCtx = funcCtx\n\n  /** Context for tracking control flow jump targets.\n    *\n    * @param scp\n    *   [[Scope]] for generating WAT identifiers of labels in this control flow context.\n    * @param breakLabel\n    *   The label to jump to for exiting this control flow context, e.g. for `break` statements.\n    * @param continueLabel\n    *   The label to jump to for continuing this control flow context, e.g. for `continue` statements in loops. This is\n    *   `None` for non-loop contexts.\n    */\n  private case class ControlFlowCtx(scp: Scope, breakLabel: LabelSymbol, continueLabel: Opt[LabelSymbol])\n\n/** Context associated with codegen for a Wasm function.\n  *\n  * @param _params\n  *   The parameters of this function.\n  * @param thisSym\n  *   The implicit `this` parameter symbol if this function is generated from a non-static method, or `N` otherwise.\n  */\nclass FunctionCtx(_params: Ls[ParamList], thisSym: Opt[InnerSymbol])(using Raise, State):\n\n  /** [[Scope]] for generating WAT identifiers of locals. */\n  private[text] val localScp = Scope.empty(Scope.Cfg.default)\n\n  /** The parameter of this function, represented by a tuple of the symbol representing the parameter and its symbolic\n    * identifier.\n    */\n  val params: Seq[Local -> SymIdx] =\n    if _params.length > 1 then\n      lastWords(\"Multiple parameter lists are not yet supported\")\n    val thisParam = thisSym.map: dis =>\n      dis -> SymIdx(localScp.addToBindings(dis, \"this\", shadow = false))\n    thisParam.toSeq ++ _params.flatMap(_.paramSyms).map(p => p -> SymIdx(localScp.allocateName(p)))\n  private val _locals = ArrayBuf.empty[Local]\n  private var labels = ListMap.empty[LabelSymbol, FunctionCtx.ControlFlowCtx]\n\n  /** Adds a Wasm local into this context.\n    *\n    * @param customName\n    *   An optional name for the local variable. If provided, the local will be emitted with the given name instead of\n    *   an auto-generated one.\n    */\n  def addLocal(local: Local, customName: Opt[Str] = N): LocalIdx =\n    customName match\n      case S(name) => localScp.addToBindings(local, name, shadow = false)\n      case N => localScp.allocateName(local)\n    _locals += local\n    LocalIdx(SymIdx(localScp.lookup_!(local, N)))\n\n  /** Looks up the given `sym` in this function context, returning its [[LocalIdx]] if it exists. */\n  def lookupLocal(sym: Local): Opt[LocalIdx] =\n    localScp.lookup(sym).map(idx => LocalIdx(SymIdx(idx)))\n\n  /** Similar to [[lookupLocal]], but throws an exception if `sym` is not in this context. */\n  def lookupLocal_!(sym: Local, loc: Opt[Loc]): LocalIdx =\n    LocalIdx(SymIdx(localScp.lookup_!(sym, loc)))\n\n  /** The locals of this function, represented by a tuple of the symbol representing the parameter and its symbolic\n    * identifier.\n    */\n  def locals: Seq[Local -> SymIdx] = _locals.map(l => l -> SymIdx(localScp.lookup_!(l, N))).toSeq\n\n  /** Pushes a label target for the dynamic extent of `body` and pops it afterwards.\n    *\n    * The `body` function is given a [[LabelTarget]] containing the `break` and `continue` labels corresponding to\n    * `label`.\n    *\n    * @param hasContinueLabel\n    *   Indicates whether a `continue` label should be generated for this control flow context, e.g. for loops.\n    */\n  def withLabel[T](label: LabelSymbol, hasContinueLabel: Bool)(body: LabelTarget => T): T =\n    val ctrlFlowCtx = FunctionCtx.ControlFlowCtx(\n      scp = labels.lastOption.fold(Scope.empty(Scope.Cfg.default))(_._2.scp.nest),\n      breakLabel = label,\n      continueLabel = if hasContinueLabel then S(LabelSymbol(N, s\"${label.nme}_cont\")) else N,\n    )\n    labels += label -> ctrlFlowCtx\n    val res = body:\n      LabelTarget(\n        breakLabel = ctrlFlowCtx.scp.allocateName(label),\n        continueLabel = ctrlFlowCtx.continueLabel.map(cl => ctrlFlowCtx.scp.allocateName(cl)),\n      )\n    labels = labels.init\n    res\n\n  /** Looks up the nearest in-scope target for `label`. */\n  def lookupLabel(label: LabelSymbol): Opt[LabelTarget] =\n    labels.lastOption.flatMap: (_, ctrlFlowCtx) =>\n      ctrlFlowCtx.scp.lookup(label).map: labelId =>\n        LabelTarget(\n          breakLabel = labelId,\n          continueLabel = labels(label).continueLabel.map(cl => labels.last._2.scp.lookup_!(cl, N)),\n        )\nend FunctionCtx\n\n/** Generates a function body, providing an instance of [[FunctionCtx]] for parameter and locals tracking.\n  *\n  * Returns the result of the `mkBody` function along with the [[FunctionCtx]].\n  */\ndef genFuncBody[T](\n    params: Ls[ParamList],\n    thisSym: Opt[InnerSymbol],\n)(mkBody: FunctionCtx ?=> T)(using Raise, State): T -> FunctionCtx =\n  val funcCtx = FunctionCtx(params, thisSym)\n  val result = mkBody(using funcCtx)\n  result -> funcCtx\n\nobject Ctx:\n  case class SingletonInfo(\n      globalName: Str,\n      globalTy: RefType,\n  )\n\n  val binaryOps: Map[Str, (Expr, Expr) => Expr] = Map(\n    \"plus_impl\" -> i32.add,\n    \"minus_impl\" -> i32.sub,\n    \"times_impl\" -> i32.mul,\n    \"div_impl\" -> i32.div_s,\n    \"mod_impl\" -> i32.rem_s,\n    \"eq_impl\" -> i32.eq,\n    \"neq_impl\" -> i32.ne,\n    \"lt_impl\" -> i32.lt_s,\n    \"le_impl\" -> i32.le_s,\n    \"gt_impl\" -> i32.gt_s,\n    \"ge_impl\" -> i32.ge_s,\n  )\n  val unaryOps: Map[Str, Expr => Expr] = Map(\n    \"neg_impl\" -> (value => i32.sub(i32.const(0), value)),\n    \"pos_impl\" -> identity,\n    \"not_impl\" -> i32.eqz,\n  )\n  val wasmIntrinsicArities: Map[Str, Int] = (binaryOps.keys.map(_ -> 2) ++ unaryOps.keys.map(_ -> 1)).toMap\n  val wasmIntrinsicNameSet: Set[Str] = wasmIntrinsicArities.keySet\n\n  def empty(using State): Ctx = Ctx()\n\n  def ctx(using ctx: Ctx): Ctx = ctx\n\n  extension (ref: CtxIdx | Symbol)\n    private def prettyString: Str = ref match\n      case idx: CtxIdx => s\"type index `${idx.toWat.mkString()}`\"\n      case sym: Symbol => s\"symbol `${sym.toString}`\"\nend Ctx\n\n/** Context for [[WatBuilder]]. */\nclass Ctx(using State) extends ToWat:\n\n  import Ctx.prettyString\n\n  /** [[Scope]] for generating WAT identifiers of types. */\n  private[text] val typeScp = Scope.empty(Scope.Cfg.default)\n\n  /** [[ListMap]] containing all type definitions in the module mapped by their symbolic identifiers. */\n  private var types = ListMap.empty[SymIdx, TypeInfo]\n\n  /** [[MutMap]] containing type symbols mapped to their corresponding [[TypeInfo]] instance. */\n  private val namedTypes = MutMap.empty[BlockMemberSymbol, TypeInfo]\n  \n  /** [[Scope]] for generating WAT identifiers of data segments. */\n  private[text] val dataSegmentScp = Scope.empty(Scope.Cfg.default)\n\n  /** [[ListMap]] containing all data segments in the module. */\n  private var dataSegments = ListMap.empty[SymIdx, DataSegment]\n  \n  /** [[Scope]] for generating WAT identifiers of element segments. */\n  private[text] val elemSegmentScp = Scope.empty(Scope.Cfg.default)\n\n  /** [[ListMap]] containing all element segments in the module. */\n  private var elemSegments = ListMap.empty[SymIdx, ElemSegment]\n\n  /** [[Scope]] for generating WAT identifiers of functions. */\n  private[text] val funcScp = Scope.empty(Scope.Cfg.default)\n\n  /** [[ListMap]] containing all function definitions and imports in the module mapped by their symbolic identifiers. */\n  private var funcs = ListMap.empty[SymIdx, FuncInfo | Import[ExternType.Func]]\n\n  /** [[MutMap]] containing function symbols mapped to the corresponding [[FuncInfo]] or [[Import]] instance. */\n  private val namedFuncs = MutMap.empty[Symbol, FuncInfo | Import[ExternType.Func]]\n\n  /** [[Scope]] for generating WAT identifiers of memories. */\n  private[text] val memoryScp = Scope.empty(Scope.Cfg.default)\n\n  /** [[ListMap]] containing all memory definitions and imports in the module mapped by their symbolic identifiers. */\n  private var memories = ListMap.empty[SymIdx, MemInfo | Import[ExternType.Mem]]\n  \n  /** [[Scope]] for generating WAT identifiers of tags. */\n  private[text] val tagScp = Scope.empty(Scope.Cfg.default)\n\n  /** [[ListMap]] containing all tag definitions in the module. */\n  private var tags = ListMap.empty[SymIdx, TagInfo]\n\n  /** [[Scope]] for generating WAT identifiers of globals. */\n  private[text] val globalScp = Scope.empty(Scope.Cfg.default)\n\n  /** [[ListMap]] containing all global definitions and imports in the module. */\n  private var globals = ListMap.empty[SymIdx, GlobalInfo | Import[ExternType.Global]]\n\n  /** [[MutMap]] containing global symbols mapped to their corresponding [[GlobalInfo]] or [[Import]] instance. */\n  private val namedGlobals = MutMap.empty[Symbol, GlobalInfo | Import[ExternType.Global]]\n\n  private var startFunc = N: Opt[FuncIdx]\n\n  /** Counter for generating object tags. */\n  private var objectTagNum = 0\n\n  private val wasmIntrinsicFuncs = MutMap.empty[Str, FuncIdx]\n  private val wasmIntrinsicTypes = MutMap.empty[WasmIntrinsicType, TypeIdx]\n  private val wasmIntrinsicTags = MutMap.empty[Str, TagIdx]\n\n  private val cachedMemoryImport = MutMap.empty[(Str, Str), SymIdx]\n  private val cachedFunctionImports = MutMap.empty[(Str, Str), FuncIdx]\n  private val cachedGlobalImports = MutMap.empty[(Str, Str), GlobalIdx]\n\n  private val singletonByBms = MutMap.empty[BlockMemberSymbol, Ctx.SingletonInfo]\n  private val singletonByIsym = MutMap.empty[ModuleOrObjectSymbol, Ctx.SingletonInfo]\n  private val singletonInitActions = ArrayBuf.empty[Expr]\n  private val runtimeClassTags = MutMap.empty[BlockMemberSymbol, LinkedHashSet[Int]]\n\n  private def imports: Seq[Import[?]] =\n    val importedFuncs = funcs.collect:\n      case (_, imp: Import[ExternType.Func]) => imp\n    val importedGlobals = globals.collect:\n      case (_, imp: Import[ExternType.Global]) => imp\n    val importedMems = memories.collect:\n      case (_, imp: Import[ExternType.Mem]) => imp\n    (importedFuncs ++ importedGlobals ++ importedMems).toSeq\n\n  private def globalExternType(globalEntry: GlobalInfo | Import[ExternType.Global])(using\n      Ctx,\n      Raise,\n  ): ExternType.Global =\n    globalEntry match\n      case globalInfo: GlobalInfo => ExternType.Global(globalInfo.globalType, globalInfo.sym)\n      case globalImport: Import[ExternType.Global] => globalImport.externType\n\n  /** Returns a new number to be used as an object tag. */\n  def getFreshObjectTag(): Int =\n    val tag = objectTagNum\n    objectTagNum += 1\n    tag\n\n  /** Adds a type into this context. */\n  def addType(typeInfo: TypeInfo): TypeIdx =\n    val id = typeInfo.id\n    types += (id -> typeInfo)\n    typeInfo.sym match\n      case bms: BlockMemberSymbol => namedTypes(bms) = typeInfo\n      case _ =>\n    TypeIdx(id)\n\n  /** Returns the [[TypeIdx]] of the given `typeref`.\n    */\n  def getType(typeref: TypeIdx | BlockMemberSymbol): Opt[TypeIdx] = typeref match\n    case typeidx: TypeIdx => S(typeidx)\n    case sym: BlockMemberSymbol => getTypeInfo(typeref).map(ti => TypeIdx(ti.id))\n\n  /** Same as [[getType]] but throws an exception when the `typeref` is not found. */\n  def getType_!(typeref: TypeIdx | BlockMemberSymbol): TypeIdx =\n    getType(typeref).getOrElse:\n      lastWords(s\"Missing type definition for ${typeref.prettyString}\")\n\n  /** Returns the [[TypeInfo]] instance associated with the given `typeref`. */\n  def getTypeInfo(typeref: TypeIdx | BlockMemberSymbol): Opt[TypeInfo] = typeref match\n    case TypeIdx(idx @ SymIdx(nme)) => types.get(idx)\n    case sym: BlockMemberSymbol => namedTypes.get(sym)\n\n  /** Same as [[getTypeInfo]] but throws an exception when the `typeref` is not found. */\n  def getTypeInfo_!(typeref: TypeIdx | BlockMemberSymbol): TypeInfo =\n    getTypeInfo(typeref).getOrElse:\n      lastWords(s\"Missing type definition for ${typeref.prettyString}\")\n\n  /** Records the class' runtime tag together with descendant class tags for `sym`. */\n  def registerRuntimeClassTags(sym: BlockMemberSymbol, tags: LinkedHashSet[Int]): Unit =\n    runtimeClassTags(sym) = tags\n\n  /** Returns the class' runtime tag together with descendant class tags for `sym`. */\n  def getAllRuntimeTags(sym: BlockMemberSymbol): Opt[LinkedHashSet[Int]] =\n    runtimeClassTags.get(sym)\n\n  /** Adds a function import into this context.\n    *\n    * Returns the function index in the global function index space.\n    */\n  def addFunctionImport(funcImport: Import[ExternType.Func]): FuncIdx =\n    val id = funcImport.externType.id\n    funcs = funcs + (id -> funcImport)\n    namedFuncs(funcImport.externType.sym) = funcImport\n    FuncIdx(id)\n\n  /** Returns the cached function import for (`module`, `name`), creating it with `createImport` if needed.\n    */\n  def getOrCreateFunctionImport(\n      module: Str,\n      name: Str,\n  )(createImport: => Import[ExternType.Func]): FuncIdx =\n    cachedFunctionImports.getOrElseUpdate((module, name), addFunctionImport(createImport))\n\n  /** Adds a global import into this context.\n    *\n    * Returns the global index in the global index space.\n    */\n  def addGlobalImport(globalImport: Import[ExternType.Global]): GlobalIdx =\n    val id = globalImport.externType.id\n    globals = globals + (id -> globalImport)\n    namedGlobals(globalImport.externType.sym) = globalImport\n    GlobalIdx(id)\n\n  /** Returns the cached global import for (`module`, `name`), creating it with `createImport` if needed.\n    */\n  def getOrCreateGlobalImport(\n      module: Str,\n      name: Str,\n  )(createImport: => Import[ExternType.Global]): GlobalIdx =\n    cachedGlobalImports.getOrElseUpdate((module, name), addGlobalImport(createImport))\n\n  /** Adds or updates a memory import. If the import already exists, its minimum pages are increased to at least\n    * `minPages`.\n    */\n  def ensureMemoryImport(module: Str, name: Str, minPages: Int)(using Ctx, Raise): Unit =\n    val key = module -> name\n    cachedMemoryImport.get(key) match\n      case S(idx) =>\n        val existing = memories(idx) match\n          case imp: Import[ExternType.Mem] => imp\n          case _ => lastWords(\n              s\"Expected an existing memory import \\\"$module\\\".\\\"$name\\\" for `${idx.toWat}`, got a definition instead.\",\n            )\n        val newMin = existing.externType.memType.lim.min max minPages\n        if newMin > existing.externType.memType.lim.min then\n          memories = memories +\n            (idx -> Import(\n              module,\n              name,\n              ExternType.Mem(\n                MemType(existing.externType.memType.lim.copy(min = minPages)),\n                sym = existing.externType.sym,\n                wrapId = existing.externType.wrapId,\n              ),\n            ))\n      case N =>\n        val id = SymIdx(name)\n        memories = memories +\n          (id ->\n            Import(module, name, ExternType.Mem(MemType(Limits(minPages)), sym = TempSymbol(N, name))))\n        cachedMemoryImport(key) = SymIdx(name)\n    end match\n  end ensureMemoryImport\n\n  /** Returns the memory import information for the given (`module`, `name`) tuple if present. */\n  def getMemoryImport(module: Str, name: Str): Opt[ExternType.Mem] =\n    memories.collectFirst:\n      case (_, imp @ Import(`module`, `name`, mem: ExternType.Mem)) => mem\n\n  /** Adds a data segment into this context. */\n  def addDataSegment(seg: DataSegment): Unit =\n    dataSegments = dataSegments + (seg.id -> seg)\n\n  /** Adds a tag into this context. */\n  def addTag(tagInfo: TagInfo): TagIdx =\n    val id = tagInfo.id\n    tags = tags + (id -> tagInfo)\n    TagIdx(id)\n\n  /** Adds a function into this context. */\n  def addFunc(funcInfo: FuncInfo)(using Ctx, Raise): FuncIdx =\n    val id = funcInfo.id\n    funcs = funcs + (id -> funcInfo)\n    funcInfo.sym match\n      case bms: BlockMemberSymbol => namedFuncs(bms) = funcInfo\n      case _ =>\n    val idx = FuncIdx(funcInfo.id)\n    val refType = RefType(funcInfo.typeUse.typeIdx, nullable = false)\n    elemSegments = elemSegments +\n      (id -> ElemSegment.Declare(refType -> Seq(ref.func(idx, refType)), funcInfo.sym, funcInfo.wrapId))\n    idx\n\n  /** Returns the [[FuncIdx]] of the given `funcref`.\n    */\n  def getFunc(funcref: FuncIdx | Symbol): Opt[FuncIdx] = funcref match\n    case funcidx: FuncIdx => S(funcidx)\n    case sym: Symbol =>\n      namedFuncs.get(sym).map: funcInfo =>\n        funcInfo match\n          case fi: FuncInfo => FuncIdx(fi.id)\n          case imp: Import[ExternType.Func] => FuncIdx(imp.externType.id)\n\n  /** Same as [[getFunc]] but throws an exception when the `funcref` is not found. */\n  def getFunc_!(funcref: FuncIdx | Symbol): FuncIdx =\n    getFunc(funcref).getOrElse:\n      lastWords(s\"Missing function definition for ${funcref.prettyString}\")\n\n  private def getFuncEntry(funcref: FuncIdx | Symbol): Opt[FuncInfo | Import[ExternType.Func]] = funcref match\n    case FuncIdx(idx @ SymIdx(_)) => funcs.get(idx)\n    case funcref: Symbol => namedFuncs.get(funcref)\n\n  /** Returns the [[FuncInfo]] instance associated with the given `funcref`. */\n  def getFuncInfo(funcref: FuncIdx | Symbol): Opt[FuncInfo] =\n    getFuncEntry(funcref).collect:\n      case funcInfo: FuncInfo => funcInfo\n\n  /** Same as [[getFuncInfo]] but throws an exception when the `funcref` is not found. */\n  def getFuncInfo_!(funcref: FuncIdx | Symbol): FuncInfo =\n    getFuncInfo(funcref).getOrElse:\n      lastWords(s\"Missing function definition for ${funcref.prettyString}\")\n\n  /** Returns the type use associated with the given `funcref`, whether it is a definition or an import. */\n  def getFuncTypeUse(funcref: FuncIdx | Symbol): Opt[TypeUse] =\n    getFuncEntry(funcref).map:\n      case funcInfo: FuncInfo => funcInfo.typeUse\n      case funcImport: Import[ExternType.Func] => funcImport.externType.typeUse\n\n  /** Same as [[getFuncTypeUse]] but throws an exception when the `funcref` is not found. */\n  def getFuncTypeUse_!(funcref: FuncIdx | Symbol): TypeUse =\n    getFuncTypeUse(funcref).getOrElse:\n      lastWords(s\"Missing function definition for ${funcref.prettyString}\")\n\n  /** Returns the [[GlobalIdx]] of the given `globalref`. */\n  def getGlobal(globalref: GlobalIdx | Symbol)(using Ctx, Raise): Opt[GlobalIdx] = globalref match\n    case globalidx: GlobalIdx => S(globalidx)\n    case sym: Symbol =>\n      namedGlobals.get(sym).map: globalEntry =>\n        GlobalIdx(globalExternType(globalEntry).id)\n\n  /** Same as [[getGlobal]] but throws an exception when the `globalref` is not found. */\n  def getGlobal_!(globalref: GlobalIdx | Symbol)(using Ctx, Raise): GlobalIdx =\n    getGlobal(globalref).getOrElse:\n      lastWords(s\"Missing global definition for ${globalref.prettyString}\")\n\n  private def getGlobalEntry(globalref: GlobalIdx | Symbol): Opt[GlobalInfo | Import[ExternType.Global]] =\n    globalref match\n      case GlobalIdx(idx @ SymIdx(_)) => globals.get(idx)\n      case sym: Symbol => namedGlobals.get(sym)\n\n  /** Returns the global extern metadata associated with the given `globalref`. */\n  def getGlobalType(globalref: GlobalIdx | Symbol)(using Ctx, Raise): Opt[ExternType.Global] =\n    getGlobalEntry(globalref).map(globalExternType)\n\n  /** Same as [[getGlobalType]] but throws an exception when the `globalref` is not found. */\n  def getGlobalType_!(globalref: GlobalIdx | Symbol)(using Ctx, Raise): ExternType.Global =\n    getGlobalType(globalref).getOrElse:\n      lastWords(s\"Missing global definition for ${globalref.prettyString}\")\n\n  /** Returns the [[GlobalInfo]] instance associated with the given `globalref` when it is a definition. */\n  def getGlobalInfo(globalref: GlobalIdx | Symbol): Opt[GlobalInfo] =\n    getGlobalEntry(globalref).collect:\n      case globalInfo: GlobalInfo => globalInfo\n\n  /** Same as [[getGlobalInfo]] but throws an exception when the `globalref` is not found. */\n  def getGlobalInfo_!(globalref: GlobalIdx | Symbol): GlobalInfo =\n    getGlobalInfo(globalref).getOrElse:\n      lastWords(s\"Missing global definition for ${globalref.prettyString}\")\n\n  /** Adds a new variable into the global variable scope. */\n  def addGlobal(globalInfo: GlobalInfo): GlobalIdx =\n    val id = globalInfo.id\n    globals = globals + (id -> globalInfo)\n    namedGlobals(globalInfo.sym) = globalInfo\n    GlobalIdx(id)\n\n  /** Adds a [[Seq]] of variables into the global variable scope. */\n  def addGlobals(globalDefs: Seq[GlobalInfo]): Seq[GlobalIdx] =\n    globalDefs.map(addGlobal)\n\n  /** Checks whether the global variable scope contains the variable `sym`. */\n  def containsGlobal(sym: Symbol): Bool = namedGlobals.contains(sym)\n  \n  /** Returns all globals in this context. */\n  def getGlobals: Seq[Symbol] = namedGlobals.keys.toSeq\n\n  /** Checks whether singleton metadata has been registered for class symbol `sym`. */\n  def containsSingleton(sym: BlockMemberSymbol): Bool = singletonByBms.contains(sym)\n\n  /** Returns singleton metadata for `sym` when it resolves to either the block-member symbol or module/object symbol\n    * used during singleton registration.\n    */\n  def getSingletonInfo(sym: Local): Opt[Ctx.SingletonInfo] = sym match\n    case bms: BlockMemberSymbol => singletonByBms.get(bms)\n    case isym: ModuleOrObjectSymbol => singletonByIsym.get(isym)\n    case _ => N\n\n  /** Registers singleton metadata under both its block-member symbol and optional module/object symbol alias.\n    */\n  def registerSingleton(\n      bms: BlockMemberSymbol,\n      isym: Opt[ModuleOrObjectSymbol],\n      info: Ctx.SingletonInfo,\n  ): Unit =\n    singletonByBms(bms) = info\n    isym.foreach(singletonByIsym(_) = info)\n\n  /** Appends one eager singleton initialization action for synthesized module start code. */\n  def addSingletonInitAction(action: Expr): Unit =\n    singletonInitActions += action\n\n  /** Returns the singleton initialization actions in deterministic insertion order. */\n  def getSingletonInitActions: Seq[Expr] = singletonInitActions.toSeq\n\n  /** Returns the runtime class tag for `sym`. */\n  def getRuntimeClassTag(sym: BlockMemberSymbol): Opt[Int] =\n    getAllRuntimeTags(sym).flatMap(_.headOption)\n\n  /** Same as [[getRuntimeClassTag]] but throws if no runtime tag is known. */\n  def getRuntimeClassTag_!(sym: BlockMemberSymbol): Int =\n    getRuntimeClassTag(sym).getOrElse:\n      lastWords(s\"Missing runtime class tag for `${sym.toString}`\")\n\n  /** Configures the module start function. */\n  def setStartFunc(funcIdx: FuncIdx): Unit =\n    startFunc = S(funcIdx)\n\n  /** Returns the cached [[FuncIdx]] for the intrinsic named `name`, creating it with `createIntrinsic` if it does not\n    * yet exist in this context.\n    */\n  def getOrCreateWasmIntrinsic(name: Str, createIntrinsic: => FuncIdx): FuncIdx =\n    wasmIntrinsicFuncs.getOrElseUpdate(name, createIntrinsic)\n\n  /** Returns the cached [[TypeIdx]] for the intrinsic type `key`, creating it with `createType` if it does not yet\n    * exist in this context.\n    */\n  def getOrCreateWasmIntrinsicType(key: WasmIntrinsicType)(createType: => TypeIdx): TypeIdx =\n    wasmIntrinsicTypes.getOrElseUpdate(key, createType)\n\n  /** Returns the cached [[TagIdx]] for the intrinsic tag named `name`, creating it if absent. */\n  def getOrCreateWasmIntrinsicTag(name: Str, createTag: => TagIdx): TagIdx =\n    wasmIntrinsicTags.getOrElseUpdate(name, createTag)\n\n  def toWat: Document =\n    val definedGlobals = globals.valuesIterator.collect:\n      case globalInfo: GlobalInfo => globalInfo.toWat\n    val memDefns = memories.valuesIterator.collect:\n      case memInfo: MemInfo => memInfo.toWat\n    val funcDefns = funcs.valuesIterator.collect:\n      case funcInfo: FuncInfo => funcInfo.toWat\n    doc\"(module #{  # ${\n        (\n          types.valuesIterator.map(_.toWat)\n            ++ imports.iterator.map(_.toWat)\n            ++ tags.valuesIterator.map(_.toWat)\n            ++ definedGlobals\n            ++ memDefns\n            ++ funcDefns\n            ++ dataSegments.valuesIterator.map(_.toWat)\n            ++ elemSegments.valuesIterator.map(_.toWat)\n            ++ startFunc.iterator.map(funcIdx => doc\"(start ${funcIdx.toWat})\")\n        ).toSeq.mkDocument(doc\" # \")\n      } #} )\"\n  end toWat\n\nend Ctx\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/Instructions.scala",
    "content": "package hkmc2\npackage codegen.wasm.text\n\nimport mlscript.utils.*, shorthands.*\n\nimport document.*\n\nobject Instructions:\n  /** Creates a `block` instruction. */\n  def block(\n      label: Opt[Str],\n      children: Seq[Expr],\n      resultTypes: Seq[Result],\n  ): FoldedInstr =\n    val labelWat = label.map(lbl => doc\"$$$lbl\")\n\n    FoldedInstr(\n      mnemonic = \"block\",\n      instrargs = labelWat.toSeq ++ resultTypes,\n      stackargs = children,\n      resultTypes = resultTypes.map(_.valtype),\n    )\n\n  /** Creates a `loop` instruction. */\n  def loop(\n      label: Opt[Str],\n      children: Seq[Expr],\n      resultTypes: Seq[Result],\n  ): FoldedInstr =\n    val labelWat = label.map(lbl => doc\"$$$lbl\")\n\n    FoldedInstr(\n      mnemonic = \"loop\",\n      instrargs = labelWat.toSeq ++ resultTypes,\n      stackargs = children,\n      resultTypes = resultTypes.map(_.valtype),\n    )\n\n  /** Creates an `if` instruction. */\n  def `if`(\n      condition: Expr,\n      ifTrue: Expr,\n      ifFalse: Opt[Expr],\n      resultTypes: Seq[Result],\n  ): FoldedInstr =\n    val thenInstr = FoldedInstr(\n      mnemonic = \"then\",\n      instrargs = Seq.empty,\n      stackargs = Seq(ifTrue),\n      resultTypes = ifTrue.resultTypes,\n    )\n    val elseInstr = ifFalse.map: elseExpr =>\n      FoldedInstr(\n        mnemonic = \"else\",\n        instrargs = Seq.empty,\n        stackargs = Seq(elseExpr),\n        resultTypes = elseExpr.resultTypes,\n      )\n\n    FoldedInstr(\n      mnemonic = \"if\",\n      instrargs = resultTypes,\n      stackargs = Seq(condition, thenInstr) ++ elseInstr.toSeq,\n      resultTypes = resultTypes.map(_.valtype),\n    )\n  end `if`\n\n  /** Creates a `call` instruction. */\n  def call(\n      funcidx: FuncIdx,\n      operands: Seq[Expr],\n      returnTypes: Seq[Result],\n  ): FoldedInstr = FoldedInstr(\n    mnemonic = \"call\",\n    instrargs = Seq(funcidx.toWat),\n    stackargs = operands,\n    resultTypes = returnTypes.map(_.valtype),\n  )\n\n  /** Creates a `call_ref` instruction. */\n  def call_ref(\n      target: Expr,\n      operands: Seq[Expr],\n      typeIdx: TypeIdx,\n      funcType: FunctionType,\n  ): FoldedInstr = FoldedInstr(\n    mnemonic = \"call_ref\",\n    instrargs = Seq(typeIdx.toWat),\n    stackargs = operands :+ target,\n    resultTypes = funcType.sigType.results.map(_.valtype),\n  )\n\n  /** Creates a `nop` instruction. */\n  def nop: FoldedInstr = FoldedInstr(\n    mnemonic = \"nop\",\n    instrargs = Seq.empty,\n    stackargs = Seq.empty,\n    resultType = N,\n  )\n\n  /** Creates a `drop` instruction. */\n  def drop(value: Expr): FoldedInstr = FoldedInstr(\n    mnemonic = \"drop\",\n    instrargs = Seq.empty,\n    stackargs = Seq(value),\n    resultType = N,\n  )\n\n  /** Creates a `return` instruction with an optional return value. */\n  def `return`(value: Opt[Expr]): FoldedInstr = FoldedInstr(\n    mnemonic = \"return\",\n    instrargs = Seq.empty,\n    stackargs = value.toSeq,\n    resultTypes = value.fold(Seq.empty)(_.resultTypes),\n  )\n\n  /** Creates a `throw` instruction. */\n  def `throw`(tag: TagIdx, operands: Seq[Expr]): FoldedInstr = FoldedInstr(\n    mnemonic = \"throw\",\n    instrargs = Seq(tag.toWat),\n    stackargs = operands,\n    resultType = S(UnreachableType),\n  )\n\n  /** Creates an `unreachable` instruction. */\n  def unreachable: FoldedInstr = FoldedInstr(\n    mnemonic = \"unreachable\",\n    instrargs = Seq.empty,\n    stackargs = Seq.empty,\n    resultType = S(UnreachableType),\n  )\n\n  /** Creates a `br` (branch) instruction. */\n  def br(label: Str): FoldedInstr = FoldedInstr(\n    mnemonic = \"br\",\n    instrargs = Seq(doc\"$$$label\"),\n    stackargs = Seq.empty,\n    resultType = S(UnreachableType),\n  )\n\n  object i32:\n    /** Creates an `i32.const` instruction. */\n    def const(value: Int): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.const\",\n      instrargs = Seq(doc\"$value\"),\n      stackargs = Seq.empty,\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.add` instruction. */\n    def add(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.add\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.add` instruction. */\n    def eq(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.eq\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(\n        (lhs.resultType, rhs.resultType) match\n          case (UnreachableType, _) | (_, UnreachableType) => UnreachableType\n          case _ => I32Type,\n      ),\n    )\n\n    /** Creates an `i32.ge_u` instruction (greater than or equal, unsigned). */\n    def ge_u(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.ge_u\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.and` instruction. */\n    def and(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.and\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.or` instruction. */\n    def or(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.or\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.sub` instruction. */\n    def sub(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.sub\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.mul` instruction. */\n    def mul(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.mul\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.div_s` instruction. */\n    def div_s(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.div_s\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.rem_s` instruction. */\n    def rem_s(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.rem_s\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.ne` instruction. */\n    def ne(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.ne\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.lt_s` instruction. */\n    def lt_s(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.lt_s\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.le_s` instruction. */\n    def le_s(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.le_s\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.gt_s` instruction. */\n    def gt_s(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.gt_s\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.ge_s` instruction. */\n    def ge_s(lhs: Expr, rhs: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.ge_s\",\n      instrargs = Seq.empty,\n      stackargs = Seq(lhs, rhs),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i32.eqz` instruction. */\n    def eqz(value: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"i32.eqz\",\n      instrargs = Seq.empty,\n      stackargs = Seq(value),\n      resultType = S(I32Type),\n    )\n  end i32\n\n  object array:\n    /** Creates an `array.len` instruction. */\n    def len(arrayRef: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"array.len\",\n      instrargs = Seq.empty,\n      stackargs = Seq(arrayRef),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `array.new_fixed` instruction. */\n    def new_fixed(arrayType: TypeIdx, items: Seq[Expr]): FoldedInstr = FoldedInstr(\n      mnemonic = \"array.new_fixed\",\n      instrargs = Seq(arrayType.toWat, doc\"${items.length}\"),\n      stackargs = items,\n      resultType = S(RefType(arrayType, nullable = false)),\n    )\n\n    /** Creates an `array.get` instruction. */\n    def get(arrayType: TypeIdx, arrayRef: Expr, index: Expr, elemType: Type): FoldedInstr = FoldedInstr(\n      mnemonic = \"array.get\",\n      instrargs = Seq(arrayType.toWat),\n      stackargs = Seq(arrayRef, index),\n      resultType = S(elemType),\n    )\n\n    /** Creates an `array.set` instruction. */\n    def set(arrayType: TypeIdx, arrayRef: Expr, index: Expr, value: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"array.set\",\n      instrargs = Seq(arrayType.toWat),\n      stackargs = Seq(arrayRef, index, value),\n      resultType = N,\n    )\n  end array\n\n  object ref:\n    /** Creates a `ref.null` instruction. */\n    def `null`(heapType: HeapType): FoldedInstr = FoldedInstr(\n      mnemonic = \"ref.null\",\n      instrargs = Seq(heapType.toWat),\n      stackargs = Seq.empty,\n      resultType = S(RefType(heapType, nullable = true)),\n    )\n\n    /** Creates a `ref.is_null` instruction. */\n    def is_null(value: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"ref.is_null\",\n      instrargs = Seq.empty,\n      stackargs = Seq(value),\n      resultType = S(I32Type),\n    )\n\n    /** Creates a `ref.func` instruction. */\n    def func(idx: FuncIdx, ty: RefType): FoldedInstr = FoldedInstr(\n      mnemonic = \"ref.func\",\n      instrargs = Seq(idx.toWat),\n      stackargs = Seq.empty,\n      resultType = S(ty),\n    )\n\n    /** Creates a `ref.i31` instruction. */\n    def i31(value: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"ref.i31\",\n      instrargs = Seq.empty,\n      stackargs = Seq(value),\n      resultType = S(RefType.i31ref),\n    )\n\n    /** Creates a `ref.test` instruction. */\n    def test(value: Expr, castType: RefType): FoldedInstr = FoldedInstr(\n      mnemonic = \"ref.test\",\n      instrargs = Seq(castType.toWat),\n      stackargs = Seq(value),\n      resultType = S(I32Type),\n    )\n\n    /** Creates a `ref.cast` instruction. */\n    def cast(value: Expr, castType: RefType): FoldedInstr = FoldedInstr(\n      mnemonic = \"ref.cast\",\n      instrargs = Seq(castType.toWat),\n      stackargs = Seq(value),\n      resultType = S(castType),\n    )\n  end ref\n\n  object i31:\n    def get(i31: Expr, signed: Bool): FoldedInstr = FoldedInstr(\n      mnemonic = s\"i31.get_${if signed then 's' else 'u'}\",\n      instrargs = Seq.empty,\n      stackargs = Seq(i31),\n      resultType = S(I32Type),\n    )\n\n    /** Creates an `i31.get_s` instruction. */\n    def get_s(i31: Expr): FoldedInstr = get(i31, true)\n  end i31\n\n  object local:\n    /** Creates a `local.get` instruction. */\n    def get(index: LocalIdx, ty: Type): FoldedInstr = FoldedInstr(\n      mnemonic = \"local.get\",\n      instrargs = Seq(index),\n      stackargs = Seq.empty,\n      resultType = S(ty),\n    )\n\n    /** Creates a `local.tee` instruction. */\n    def tee(index: LocalIdx, value: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"local.tee\",\n      instrargs = Seq(index),\n      stackargs = Seq(value),\n      resultTypes = value.resultTypes,\n    )\n\n    /** Creates a `local.set` instruction. */\n    def set(index: LocalIdx, value: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"local.set\",\n      instrargs = Seq(index),\n      stackargs = Seq(value),\n      resultType = N,\n    )\n  end local\n\n  object global:\n    /** Creates a `global.get` instruction. */\n    def get(index: GlobalIdx, ty: Type): FoldedInstr = FoldedInstr(\n      mnemonic = \"global.get\",\n      instrargs = Seq(index),\n      stackargs = Seq.empty,\n      resultType = S(ty),\n    )\n\n    /** Creates a `global.set` instruction. */\n    def set(index: GlobalIdx, value: Expr): FoldedInstr = FoldedInstr(\n      mnemonic = \"global.set\",\n      instrargs = Seq(index),\n      stackargs = Seq(value),\n      resultType = N,\n    )\n  end global\n\n  object struct:\n    /** Creates a `struct.new_default` instruction. */\n    def new_default(ty: TypeIdx): FoldedInstr = FoldedInstr(\n      mnemonic = \"struct.new_default\",\n      instrargs = Seq(ty.toWat),\n      stackargs = Seq.empty,\n      resultType = S(RefType(ty, nullable = false)),\n    )\n\n    /** Creates a `struct.set` instruction. */\n    def set(index: FieldIdx, ref: Expr, value: FoldedInstr): FoldedInstr = FoldedInstr(\n      mnemonic = \"struct.set\",\n      instrargs = Seq(ref.resultType_!.asInstanceOf[RefType].heapType, index),\n      stackargs = Seq(ref, value),\n      resultType = N,\n    )\n\n    /** Creates a `struct.get` instruction. */\n    def get(index: FieldIdx, ref: Expr, ty: Type): FoldedInstr = FoldedInstr(\n      mnemonic = \"struct.get\",\n      instrargs = Seq(ref.resultType_!.asInstanceOf[RefType].heapType, index),\n      stackargs = Seq(ref),\n      resultType = S(ty),\n    )\n\n  end struct\n\nend Instructions\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/Wasm.scala",
    "content": "package hkmc2\npackage codegen\npackage wasm\npackage text\n\nimport mlscript.utils.*, shorthands.*\n\nimport document.*\nimport semantics.{DefinitionSymbol, Elaborator, Symbol, TempSymbol}, Elaborator.State\nimport utils.Scope\n\nimport scala.collection.Map\n\nextension (doc: Document)\n  /** Surrounds a document by the given `prefix` and `suffix`, unless the document is empty. */\n  private def surroundUnlessEmpty(\n      prefix: => Document = Document.empty,\n      postfix: => Document = Document.empty,\n  ): Document =\n    doc.optionUnless(_.isEmpty).fold(doc): doc =>\n      doc\"$prefix$doc$postfix\"\n\nextension (scp: Scope)\n  /** Convenience function for [[Scope.allocateOrGetName]] with an optional prefix and suffix. */\n  private[text] def allocateOrGetNameWrapped(sym: Local, wrapId: Opt[Str] -> Opt[Str])(using Raise): Str =\n    val prefix = wrapId._1.fold(\"\")(prefix => s\"${prefix}_\")\n    wrapId._2 match\n      case S(suffix) =>\n        scp.lookup(sym).getOrElse:\n          scp.addToBindings(sym, s\"$prefix${sym.nme}_$suffix\", shadow = false)\n      case N => scp.allocateOrGetName(sym, prefix)\n\n/** Trait indicating a WAT representation is available. */\ntrait ToWat:\n  /** Converts this object into a WAT representation. */\n  def toWat: Document\n\n/** Abstract base class for all Wasm types. */\nsealed abstract class Type extends ToWat:\n\n  /** Attempts to convert this type to a [[[ValType]]]. */\n  def asValType: Opt[ValType] = this match\n    case ty: ValType => S(ty)\n    case _ => N\n\n  /** Same as [[[asValType]]], except throws an exception if this type is not a `ValType`. */\n  def asValType_! : ValType = asValType.getOrElse:\n    lastWords(s\"asValType_! called on non-ValType: `$toWat` (${getClass.getName})\")\n\nprivate case object I32Type extends Type:\n  def toWat: Document = doc\"i32\"\nprivate case object I64Type extends Type:\n  def toWat: Document = doc\"i64\"\nprivate case object F32Type extends Type:\n  def toWat: Document = doc\"f32\"\nprivate case object F64Type extends Type:\n  def toWat: Document = doc\"f64\"\nprivate case object V128Type extends Type:\n  def toWat: Document = doc\"v128\"\nprivate case object UnreachableType extends Type:\n  def toWat: Document = throw UnsupportedOperationException(\n    s\"${toString} is a compiler-internal type and cannot be converted to WAT\",\n  )\n\ntype NumType = I32Type.type | I64Type.type | F32Type.type | F64Type.type\ntype VecType = V128Type.type\n\nobject RefType:\n  def anyref: RefType = RefType(HeapType.Any, nullable = true)\n  def i31ref: RefType = RefType(HeapType.I31, nullable = true)\n  def funcref: RefType = RefType(HeapType.Func, nullable = true)\n\n/** Wasm type representing a reference to a [[HeapType]]. */\ncase class RefType(heapType: HeapType, nullable: Bool) extends Type:\n  def toWat: Document =\n    doc\"(ref${if nullable then \" null\" else \"\"} ${heapType.toWat})\"\n\nobject HeapType:\n  case object Func extends ToWat:\n    def toWat: Document = doc\"func\"\n  case object Ext extends ToWat:\n    def toWat: Document = doc\"extern\"\n  case object Any extends ToWat:\n    def toWat: Document = doc\"any\"\n  case object Eq extends ToWat:\n    def toWat: Document = doc\"eq\"\n  case object I31 extends ToWat:\n    def toWat: Document = doc\"i31\"\n  case object Struct extends ToWat:\n    def toWat: Document = doc\"struct\"\n  case object Array extends ToWat:\n    def toWat: Document = doc\"array\"\n  case object None extends ToWat:\n    def toWat: Document = doc\"none\"\n  case object NoExt extends ToWat:\n    def toWat: Document = doc\"noextern\"\n  case object NoFunc extends ToWat:\n    def toWat: Document = doc\"nofunc\"\nend HeapType\ntype ValType = NumType | VecType | RefType\n\n/** A Wasm parameter clause. Appears in function signatures. */\ncase class Param(id: SymIdx, valtype: ValType) extends ToWat:\n  def toWat: Document =\n    doc\"(param ${id.toWat} ${valtype.toWat})\"\n\n/** A Wasm result clause. Appears in function signatures and some instructions. */\ncase class Result(valtype: ValType) extends ToWat:\n  def toWat: Document = doc\"(result ${valtype.toWat})\"\n\n/** A type representing a function signature.\n  *\n  * Function signatures differ from [[FunctionType]] in that they do not include the `func` keyword.\n  */\ncase class SignatureType(params: Seq[Param], results: Seq[Result]) extends ToWat:\n  def toWat: Document = (params.map(_.toWat) ++ results.map(_.toWat)).mkDocument(doc\" \")\n\nobject FunctionType:\n  def apply(params: Seq[Param], results: Seq[Result]): FunctionType =\n    new FunctionType(SignatureType(params, results))\n\n/** A type representing a function type. */\ncase class FunctionType(sigType: SignatureType) extends ToWat:\n  def toWat: Document =\n    doc\"(func${sigType.toWat.surroundUnlessEmpty(doc\" \")})\"\n\n/** A type representing a struct field. */\ncase class Field(ty: ValType, mutable: Bool, id: Str) extends ToWat:\n  def toWat: Document =\n    doc\"(field $$$id ${if mutable then doc\"(mut ${ty.toWat})\" else ty.toWat})\"\n\n/** A type representing a structure type. */\ncase class StructType(\n    fields: Seq[DefinitionSymbol[?] -> Field],\n    parents: Seq[TypeIdx] = Seq.empty,\n    isFinal: Bool = false,\n) extends ToWat:\n\n  lazy val fieldsBySym: Map[DefinitionSymbol[?], Field] = fields.toMap\n\n  def toWat: Document =\n    val structWat = doc\"(struct${fields.map(_._2.toWat).mkDocument(doc\" \").surroundUnlessEmpty(doc\" \")})\"\n    if parents.isEmpty && isFinal then\n      structWat\n    else\n      doc\"(sub${\n          if isFinal then doc\" final\" else doc\"\"\n        }${\n          parents.map(_.toWat).mkDocument(doc\" \").surroundUnlessEmpty(doc\" \")\n        } $structWat)\"\n\n/** A type representing an array type. */\ncase class ArrayType(elemType: ValType, mutable: Bool) extends ToWat:\n  def toWat: Document =\n    val elemDoc = if mutable then doc\"(mut ${elemType.toWat})\" else elemType.toWat\n    doc\"(array ${elemDoc})\"\n\n/** A composite type. */\ntype CompType = StructType | FunctionType | ArrayType\n\ntype AbsHeapType =\n  HeapType.Func.type\n    | HeapType.Ext.type\n    | HeapType.Any.type\n    | HeapType.Eq.type\n    | HeapType.I31.type\n    | HeapType.Struct.type\n    | HeapType.Array.type\n    | HeapType.None.type\n    | HeapType.NoExt.type\n    | HeapType.NoFunc.type\ntype HeapType = AbsHeapType | TypeIdx\n\ncase class TypeUse(typeIdx: TypeIdx) extends ToWat:\n  def toWat: Document = doc\"(type ${typeIdx.toWat})\"\n\nsealed abstract class Index extends ToWat\n\n/** A symbolic identifier. */\ncase class SymIdx(val id: Str) extends Index:\n  def toWat: Document = doc\"$$$id\"\n\n/** An index that is bound to an index space. */\nsealed abstract class CtxIdx(idx: Index) extends ToWat:\n  def toWat: Document = idx.toWat\n\n/** An index bound to the ''types'' index space. */\ncase class TypeIdx(idx: Index) extends CtxIdx(idx)\n\n/** An index bound to the ''global'' index space. */\ncase class GlobalIdx(idx: Index) extends CtxIdx(idx)\n\n/** An index bound to the ''memory'' index space. */\ncase class MemIdx(idx: Index) extends CtxIdx(idx)\n\n/** An index bound to the ''funcs'' index space. */\ncase class FuncIdx(idx: Index) extends CtxIdx(idx)\n\n/** An index bound to the ''locals'' index space. */\ncase class LocalIdx(idx: Index) extends CtxIdx(idx)\n\n/** An index bound to the ''fields'' index space. */\ncase class FieldIdx(idx: Index) extends CtxIdx(idx)\n\n/** An index bound to the ''tags'' index space. */\ncase class TagIdx(idx: Index) extends CtxIdx(idx)\n\n/** An import entry. */\ncase class Import[ET <: ExternType](module: Str, name: Str, externType: ET) extends ToWat:\n  def toWat: Document =\n    doc\"\"\"(import \"$module\" \"$name\" ${externType.toWat})\"\"\"\n\n/** The address type of a memory type. */\nenum AddrType extends ToWat:\n  case i32\n  case i64\n\n  def toWat: Document = this match\n    case AddrType.i32 => doc\"i32\"\n    case AddrType.i64 => doc\"i64\"\n\n/** The size range of resizeable storage. */\ncase class Limits(min: Int, max: Opt[Int] = N) extends ToWat:\n  def toWat: Document = doc\"$min${max.fold(doc\"\")(max => doc\" $max\")}\"\n\n/** A linear memory entry. */\ncase class MemType(lim: Limits, addrType: AddrType = AddrType.i32) extends ToWat:\n  def toWat: Document =\n    doc\"${addrType.optionIf(_ != AddrType.i32).fold(doc\"\")(at => doc\"${at.toWat} \")}${lim.toWat}\"\n\n/** A global type. */\ncase class GlobalType(valType: ValType, mutable: Bool) extends ToWat:\n  def toWat: Document =\n    if mutable then doc\"(mut ${valType.toWat})\"\n    else valType.toWat\n\nobject ExternType:\n  /** An linear memory entry that is externally addressable. */\n  case class Mem(memType: MemType, override val sym: Symbol, wrapId: Opt[Str] -> Opt[Str] = N -> N)(using Ctx, Raise)\n      extends ExternType(sym):\n\n    val id: SymIdx = SymIdx(summon[Ctx].memoryScp.allocateOrGetNameWrapped(sym, wrapId))\n\n    def toWat: Document = doc\"\"\"(memory ${id.toWat} ${memType.toWat})\"\"\"\n\n  /** An function entry that is externally addressable. */\n  case class Func(typeUse: TypeUse, override val sym: Symbol, wrapId: Opt[Str] -> Opt[Str] = N -> N)(using Ctx, Raise)\n      extends ExternType(sym):\n\n    val id: SymIdx = SymIdx(summon[Ctx].funcScp.allocateOrGetNameWrapped(sym, wrapId))\n\n    def toWat: Document = doc\"\"\"(func ${id.toWat} ${typeUse.toWat})\"\"\"\n\n  /** A global entry that is externally addressable. */\n  case class Global(\n      globalType: GlobalType,\n      override val sym: Symbol,\n      wrapId: Opt[Str] -> Opt[Str] = N -> N,\n  )(using Ctx, Raise) extends ExternType(sym):\n\n    val id: SymIdx = SymIdx(summon[Ctx].globalScp.allocateOrGetNameWrapped(sym, wrapId))\n\n    def toWat: Document = doc\"\"\"(global ${id.toWat} ${globalType.toWat})\"\"\"\nend ExternType\n\nsealed abstract class ExternType(val sym: Symbol) extends ToWat:\n\n  /** Symbolic identifier for the extern declaration. */\n  val id: SymIdx\n\n/** A memory import entry. */\n@deprecated(\"Use `Import` with `ExternType.Mem` instead.\")\ncase class MemoryImport(module: Str, name: Str, id: SymIdx, minPages: Int) extends ToWat:\n  def toWat: Document =\n    doc\"\"\"(import \"$module\" \"$name\" (memory ${id.toWat} $minPages))\"\"\"\n\n/** A function import entry. */\n@deprecated(\"Use `Import` with `ExternType.Func` instead.\")\ncase class FuncImport(module: Str, name: Str, id: SymIdx, typeIdx: TypeIdx) extends ToWat:\n  def toWat: Document =\n    doc\"\"\"(import \"$module\" \"$name\" (func ${id.toWat} (type ${typeIdx.toWat})))\"\"\"\n\n/** A memory use entry. */\ncase class MemUse(memidx: MemIdx) extends ToWat:\n  def toWat: Document = doc\"(memory ${memidx.toWat})\"\n\nobject DataSegment:\n  /** A passive data segment, which is not associated with any memory and must be explicitly loaded with `memory.init`.\n    */\n  case class Passive(bytes: Seq[Str], override val sym: Symbol, wrapId: Opt[Str] -> Opt[Str] = N -> N)(using Ctx, Raise)\n      extends DataSegment(bytes, sym, wrapId):\n    \n    def toWat: Document =\n      doc\"(data ${id.toWat}${bytes.map(s => s\"\\\"$s\\\"\").mkDocument(doc\" \").surroundUnlessEmpty(doc\" \")})\"\n\n  /** An active data segment, which is automatically copied into a memory given by `memuse` and `offset`.\n    */\n  case class Active(\n      offset: Expr,\n      bytes: Seq[Str],\n      memuse: Opt[MemUse],\n      override val sym: Symbol,\n      wrapId: Opt[Str] -> Opt[Str] = N -> N,\n  )(using Ctx, Raise) extends DataSegment(bytes, sym, wrapId):\n\n    def toWat: Document =\n      doc\"(data ${id.toWat}${\n          memuse.fold(doc\"\")(memuse => doc\" ${memuse.toWat}\")\n        } ${offset.toWat}${\n          bytes.map(s => s\"\\\"$s\\\"\").mkDocument(doc\" \").surroundUnlessEmpty(doc\" \")\n        })\"\nend DataSegment\n\n/** A data segment entry. */\nsealed abstract class DataSegment(bytes: Seq[Str], val sym: Symbol, wrapId: Opt[Str] -> Opt[Str])(using Ctx, Raise)\n    extends ToWat:\n\n  /** Symbolic identifier for the data segment. */\n  val id = SymIdx(summon[Ctx].dataSegmentScp.allocateOrGetNameWrapped(sym, wrapId))\n\nobject ElemSegment:\n  /** A passive element segment, which is not associated with any table and must be explicitly initialized with\n    * `table.init`.\n    */\n  case class Passive(\n      override val elemlist: RefType -> Seq[Expr],\n      override val sym: Symbol,\n      wrapId: Opt[Str] -> Opt[Str] = N -> N,\n  )(using Ctx, Raise) extends ElemSegment(elemlist, sym, wrapId):\n  \n    def toWat: Document = doc\"(elem ${id.toWat} ${abbrevElemList})\"\n\n  /** An active element segment, which is automatically copied into a table given by `offset. */\n  case class Active(\n      offset: Expr,\n      override val elemlist: RefType -> Seq[Expr],\n      // TODO(Derppening): Add `tableuse` here if/when we support multiple tables.\n      override val sym: Symbol,\n      wrapId: Opt[Str] -> Opt[Str] = N -> N,\n  )(using Ctx, Raise) extends ElemSegment(elemlist, sym, wrapId):\n  \n    def toWat: Document = doc\"(elem ${id.toWat} ${offset.toWat} ${abbrevElemList})\"\n\n  /** A declarative element segment, which is used to forward declare references present in the code (such as using\n    * `ref.func`).\n    */\n  case class Declare(\n      override val elemlist: RefType -> Seq[Expr],\n      override val sym: Symbol,\n      wrapId: Opt[Str] -> Opt[Str] = N -> N,\n  )(using Ctx, Raise) extends ElemSegment(elemlist, sym, wrapId):\n  \n    def toWat: Document = doc\"(elem ${id.toWat} declare ${abbrevElemList})\"\nend ElemSegment\n\n/** An element segment entry. */\nsealed abstract class ElemSegment(\n    val elemlist: RefType -> Seq[Expr],\n    val sym: Symbol,\n    wrapId: Opt[Str] -> Opt[Str],\n)(using Ctx, Raise) extends ToWat:\n\n  /** Symbolic identifier for the element segment. */\n  val id = SymIdx(summon[Ctx].elemSegmentScp.allocateOrGetNameWrapped(sym, wrapId))\n\n  /** Applies abbreviations on the `elemlist` if a simpler replacement is available. */\n  protected def abbrevElemList: Document =\n    if elemlist._2.forall(_.mnemonic == \"ref.func\") then\n      doc\"func${\n          elemlist._2.map: e =>\n            e.instrargs.head match\n              case a: ToWat => a.toWat\n              case a: Document => a\n          .mkDocument(doc\" \").surroundUnlessEmpty(doc\" \")\n        }\"\n    else\n      doc\"${elemlist._1.toWat}${elemlist._2.map(_.toWat).mkDocument(doc\" \").surroundUnlessEmpty(doc\" \")}\"\nend ElemSegment\n\n/** An abstraction over a generic WebAssembly instructions.\n  */\nsealed abstract class Instruction extends ToWat:\n  /** The mnemonic of the instruction, e.g. \"i32.add\". */\n  val mnemonic: String\n\n  /** The arguments to the instruction. Note that this only includes arguments that are directly part of the\n    * instruction, not the stack arguments.\n    *\n    * For example, for `i32.add` this would be empty, but for `i32.const 42`, this would be `Seq(doc\"42\")`.\n    */\n  val instrargs: Seq[ToWat | Document]\n\nobject FoldedInstr:\n  def apply(\n      mnemonic: Str,\n      instrargs: Seq[ToWat | Document],\n      stackargs: Seq[FoldedInstr],\n      resultType: Opt[Type],\n  ): FoldedInstr =\n    new FoldedInstr(mnemonic, instrargs, stackargs, resultType.toSeq)\n\n/** A WebAssembly folded instruction.\n  *\n  * @param stackargs\n  *   The stack arguments of the instruction.\n  */\ncase class FoldedInstr(\n    mnemonic: Str,\n    instrargs: Seq[ToWat | Document],\n    stackargs: Seq[Expr],\n    resultTypes: Seq[Type],\n) extends Instruction:\n\n  /** Returns the result type of this instruction if this instruction only has 0-1 result values. */\n  def resultType: Opt[Type] = resultTypes match\n    case Seq() => N\n    case ty :: Seq() => S(ty)\n    case _ => lastWords(s\"resultType_! called on instruction with multi-value result type: $this\")\n\n  /** Returns the singular result type of this instruction, otherwise throws an exception. */\n  def resultType_! : Type = resultType.getOrElse:\n    lastWords(s\"resultType_! called on instruction with a non-unique result type: $this\")\n\n  def toWat: Document = doc\"($mnemonic${\n      instrargs.map: a =>\n        a match\n          case a: ToWat => a.toWat\n          case a: Document => a\n      .mkDocument(doc\" \").surroundUnlessEmpty(doc\" \")\n    } #{ ${\n      stackargs.map(_.toWat).mkDocument(doc\" # \").surroundUnlessEmpty(doc\" # \")\n    } #} )\"\nend FoldedInstr\n\n/** A WebAssembly expression, comprised of one or more instructions that generate a result value.\n  */\ntype Expr = FoldedInstr\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/codegen/wasm/text/WatBuilder.scala",
    "content": "package hkmc2\npackage codegen\npackage wasm\npackage text\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport document.*\nimport document.Document\nimport js.CodeBuilder\nimport semantics.*, Elaborator.State\nimport syntax.Tree.{BoolLit, IntLit, StrLit, Ident}\nimport text.{Import as WasmImport, Param as WasmParam}\nimport Message.MessageContext\n\nimport scala.collection.mutable.{ArrayBuffer as ArrayBuf, LinkedHashMap, LinkedHashSet, Queue}\nimport scala.util.boundary, boundary.break\nimport sourcecode.Line\n\nextension (instr: FoldedInstr)\n  /** Returns the mneomic prefix of this instruction.\n    *\n    * For example, for `local.get` it returns `Some(\"local\")`, and for `nop` it returns `None`.\n    */\n  private def mnemonicPrefix: Opt[Str] =\n    instr.mnemonic.split('.').optionUnless(_.size == 1).map(_.head)\n\nobject WatBuilder:\n  /** The maximum number of characters taken to be part of the identifier asscoiated with string constants. */\n  val StringConstantIdentMaxLength = 16\n\n  object ExternIntrinsics:\n    val SystemModule = \"system\"\n    val SystemMemoryImportName = \"mem\"\n    val StringFromUtf16ImportName = \"mlx_str_from_utf16\"\n    val WasmPageSizeBytes = 65536\n\nclass WatBuilder(using TraceLogger, State) extends CodeBuilder:\n  import Ctx.ctx\n  import Ctx.{SingletonInfo, binaryOps, unaryOps, wasmIntrinsicArities, wasmIntrinsicNameSet}\n  import FunctionCtx.funcCtx\n  import Instructions.{block as blockInstr, loop as loopInstr, *}\n  import WatBuilder.ExternIntrinsics\n\n  type Context = Ctx\n\n  private val baseObjectSym: BlockMemberSymbol = BlockMemberSymbol(\"Object\", Nil)\n  private val tagFieldSym: TermSymbol = TermSymbol(syntax.MutVal, owner = N, Ident(\"$tag\"))\n\n  private case class StringLitInfo(offset: Int, byteLen: Int, watBytes: Str)\n  private val stringLits: LinkedHashMap[Str, StringLitInfo] = LinkedHashMap.empty\n  private val initFuncSyms: LinkedHashMap[BlockMemberSymbol, BlockMemberSymbol] = LinkedHashMap.empty\n  private var nextStringDataOffset: Int = 0\n\n  private def baseObjectTypeIdx(using Ctx): TypeIdx =\n    ctx.getType_!(baseObjectSym)\n\n  private def baseObjectStruct(using Ctx): StructType =\n    ctx.getTypeInfo_!(baseObjectSym).compType match\n      case struct: StructType => struct\n      case other => lastWords(s\"Base Object type must be a struct, found ${other.toWat.mkString()}\")\n\n  private def baseObjectRefType(nullable: Bool)(using Ctx): RefType =\n    RefType(baseObjectTypeIdx, nullable = nullable)\n\n  /** True if this top-level class can be declared as a Wasm struct type. */\n  private def isSupportedTopLevelClass(defn: ClsLikeDefn): Bool =\n    defn.owner.isEmpty\n      && ((defn.k is syntax.Cls) || (defn.k is syntax.Obj))\n      && defn.auxParams.isEmpty\n      && (!(defn.k is syntax.Obj) || defn.parentPath.isEmpty)\n      && (!(defn.k is syntax.Obj) || defn.methods.isEmpty)\n      && defn.companion.isEmpty\n\n  /** Returns singleton metadata when `sym` resolves to a registered singleton object. */\n  private def singletonInfoFor(sym: Local)(using Ctx): Opt[SingletonInfo] =\n    ctx.getSingletonInfo(sym)\n\n  /** Loads the singleton object reference from its backing mutable global. */\n  private def singletonGlobalGet(info: SingletonInfo): Expr =\n    global.get(GlobalIdx(SymIdx(info.globalName)), info.globalTy)\n\n  /** The runtime representation of Unit as a singleton object. */\n  private lazy val syntheticUnitDefn: ClsLikeDefn =\n    ClsLikeDefn(\n      owner = N,\n      isym = State.unitSymbol,\n      sym = State.unitBlockMemberSymbol,\n      ctorSym = N,\n      k = syntax.Obj,\n      paramsOpt = N,\n      auxParams = Nil,\n      parentPath = N,\n      methods = Nil,\n      privateFields = Nil,\n      publicFields = Nil,\n      preCtor = End(\"\"),\n      ctor = End(\"\"),\n      companion = N,\n      bufferable = N,\n    )(N, Nil)\n\n  /** Registers the synthetic `Unit` singleton. */\n  private def RegisterUnitSingleton()(using Ctx, FunctionCtx, Raise, SessionExportCtx): Unit =\n    val unitDefn = syntheticUnitDefn\n    val singletonOwner = unitDefn.isym match\n      case mos: ModuleOrObjectSymbol => S(mos)\n      case _ => N\n    if ctx.containsSingleton(unitDefn.sym) then return\n\n    if ctx.getType(unitDefn.sym).isEmpty then\n      predeclareClassType(unitDefn)\n      predeclareClassInit(unitDefn)\n      predeclareClassConstructor(unitDefn)\n\n    returningTerm(Define(unitDefn, End(\"\")))\n\n    val typeInfo = ctx.getTypeInfo_!(unitDefn.sym)\n    val singletonInfo = ctx.getSingletonInfo(unitDefn.sym) getOrElse:\n      lastWords(\"Missing singleton metadata for synthetic Unit object\")\n    // Record session metadata for the synthetic Unit singleton.\n    summon[SessionExportCtx].emit(SessionClass(\n      sym = unitDefn.sym,\n      wrapId = typeInfo.wrapId,\n      compType = typeInfo.compType,\n      objectTag = typeInfo.objectTag,\n      runtimeTags = ctx.getAllRuntimeTags(unitDefn.sym) getOrElse:\n        LinkedHashSet(ctx.getRuntimeClassTag_!(unitDefn.sym))\n      ,\n      aliasSyms = singletonOwner.toSeq,\n    ))\n    summon[SessionExportCtx].emit(SessionSingleton(\n      blockSym = unitDefn.sym,\n      wrapId = N -> N,\n      objectSym = singletonOwner,\n      moduleName = SessionBinding.ReplModuleName,\n      exportName = singletonInfo.globalName,\n      globalTy = singletonInfo.globalTy,\n    ))\n  end RegisterUnitSingleton\n\n  /** Registers eager singleton runtime state by creating its global and start-init action. */\n  private def registerSingletonInit(\n      clsLikeDefn: ClsLikeDefn,\n      typeref: TypeIdx,\n  )(using Ctx, Raise): Unit =\n    if ctx.containsSingleton(clsLikeDefn.sym) then return\n  \n    val globalSym = BlockMemberSymbol(s\"${clsLikeDefn.sym.nme}$$inst\", Nil, nameIsMeaningful = false)\n    val globalTy = RefType(typeref, nullable = true)\n\n    val globalInfo = GlobalInfo(\n      globalType = GlobalType(globalTy, mutable = true),\n      init = ref.`null`(typeref),\n      exportName = S(globalSym.nme),\n      sym = globalSym,\n    )\n    val globalIdx = ctx.addGlobal(globalInfo)\n\n    val singletonOwner = clsLikeDefn.isym match\n      case mos: ModuleOrObjectSymbol => S(mos)\n      case _ => N\n    val info = SingletonInfo(globalInfo.id.id, globalTy)\n    ctx.registerSingleton(clsLikeDefn.sym, singletonOwner, info)\n\n    val ctorCall = call(\n      funcidx = ctx.getFunc_!(clsLikeDefn.sym),\n      operands = Seq.empty,\n      returnTypes = Seq(Result(RefType.anyref)),\n    )\n    ctx.addSingletonInitAction(global.set(globalIdx, ref.cast(ctorCall, globalTy)))\n  end registerSingletonInit\n\n  /** Collects only top-level class definitions in `block`. */\n  private def collectTopLevelClassDefns(block: Block): List[ClsLikeDefn] =\n    val acc = ArrayBuf.empty[ClsLikeDefn]\n    new BlockTraverserShallow:\n      applyBlock(block)\n      override def applyBlock(b: Block): Unit = b match\n        case Match(_, _, _, rst) => applySubBlock(rst)\n        case Label(_, _, _, rst) => applySubBlock(rst)\n        case TryBlock(_, _, rst) => applySubBlock(rst)\n        case _ => super.applyBlock(b)\n      override def applyDefn(defn: Defn): Unit = defn match\n        case clsLikeDefn: ClsLikeDefn =>\n          clsLikeDefn.optionIf(isSupportedTopLevelClass).foreach(acc += _)\n        case _ => ()\n    acc.toList\n\n  /** Resolves the parent symbol for a top-level class definition, if present. */\n  private def resolveParentSym(defn: ClsLikeDefn)(using Raise): Opt[BlockMemberSymbol] =\n    def unsupportedParent(): Opt[BlockMemberSymbol] =\n      raise(ErrorReport(\n        msg\"Wasm inheritance ordering only supports direct resolved parent class references.\" ->\n          defn.parentPath.flatMap(_.toLoc) :: Nil,\n        extraInfo = S(defn.showAsTree),\n        source = Diagnostic.Source.Compilation,\n      ))\n      N\n\n    defn.parentPath match\n      case N => N\n      case S(Value.Ref(sym, _)) =>\n        sym.asCls.flatMap(_.asBlkMember).orElse(unsupportedParent())\n      case S(sel: Select) =>\n        sel.symbol.flatMap(_.asCls).flatMap(_.asBlkMember).orElse(unsupportedParent())\n      case S(_) =>\n        unsupportedParent()\n\n  /** Orders top-level classes using a Kahn topological sort. */\n  private def sortTopLevelClasses(defns: List[ClsLikeDefn])(using Raise): List[ClsLikeDefn] =\n    val defnsBySym = defns.iterator.map(defn => defn.sym -> defn).toMap\n    val childrenBySym = LinkedHashMap.empty[BlockMemberSymbol, ArrayBuf[BlockMemberSymbol]]\n    val indegrees = LinkedHashMap.empty[BlockMemberSymbol, Int]\n\n    defns.foreach: defn =>\n      childrenBySym(defn.sym) = ArrayBuf.empty\n      indegrees(defn.sym) = 0\n\n    defns.foreach: defn =>\n      if defn.parentPath.nonEmpty then\n        val parentSym = resolveParentSym(defn).getOrElse(lastWords(\"unreachable\"))\n        if defnsBySym.contains(parentSym) then\n          childrenBySym(parentSym) += defn.sym\n          indegrees(defn.sym) += 1\n        else\n          raise(ErrorReport(\n            msg\"Wasm inheritance ordering requires parent classes to be supported top-level classes.\" ->\n              defn.parentPath.flatMap(_.toLoc) :: Nil,\n            extraInfo = S(s\"${defn.sym.nme} extends ${parentSym.nme}\"),\n            source = Diagnostic.Source.Compilation,\n          ))\n\n    val zeroIndegree = Queue.from:\n      defns.iterator.collect:\n        case defn if indegrees(defn.sym) == 0 => defn.sym\n\n    val ordered = ArrayBuf.empty[ClsLikeDefn]\n    while zeroIndegree.nonEmpty do\n      val sym = zeroIndegree.dequeue()\n      ordered += defnsBySym(sym)\n      childrenBySym(sym).foreach: childSym =>\n        indegrees(childSym) -= 1\n        if indegrees(childSym) == 0 then\n          zeroIndegree.enqueue(childSym)\n\n    if ordered.size != defns.size then\n      raise(ErrorReport(\n        msg\"Inheritance cycles are not supported.\" ->\n          defns.flatMap(_.sym.toLoc).headOption :: Nil,\n        extraInfo = S(\n          defns.iterator\n            .filter(defn => indegrees(defn.sym) > 0)\n            .map(_.sym.nme)\n            .mkString(\", \"),\n        ),\n        source = Diagnostic.Source.Compilation,\n      ))\n\n    ordered.toList\n  end sortTopLevelClasses\n\n  /** Declares one supported top-level class type for early wasm registration. */\n  private def predeclareClassType(defn: ClsLikeDefn)(using Ctx, Raise): Unit =\n    val parentTypeIdx =\n      if defn.parentPath.isEmpty then baseObjectTypeIdx\n      else\n        ctx.getType_!(\n          resolveParentSym(defn) getOrElse:\n            lastWords(s\"Expected resolved parent class symbol when predeclaring ${defn.sym.nme}\"),\n        )\n    val inheritedFields = ctx.getTypeInfo_!(parentTypeIdx).compType match\n      case struct: StructType => struct.fields\n      case other => lastWords(s\"Parent type must be a struct, found ${other.toWat.mkString()}\")\n\n    val classFields = (defn.publicFields.map(_._2) ++ defn.privateFields)\n      .map: f =>\n        f -> Field(RefType.anyref, mutable = true, id = f.nme)\n\n    val allFields = inheritedFields ++ classFields\n    val runtimeTag = ctx.getFreshObjectTag()\n\n    ctx.addType(TypeInfo(\n      sym = defn.sym,\n      compType = StructType(fields = allFields, parents = Seq(parentTypeIdx)),\n      objectTag = S(runtimeTag),\n    ))\n    ctx.registerRuntimeClassTags(defn.sym, LinkedHashSet(runtimeTag))\n  end predeclareClassType\n\n  /** Records the runtime tag accepted by each class pattern: the class's own tag and descendant tags. */\n  private def predeclareClassTags(\n      orderedDefns: List[ClsLikeDefn],\n  )(using Ctx, Raise): Unit =\n    val childrenBySym = LinkedHashMap.empty[BlockMemberSymbol, ArrayBuf[BlockMemberSymbol]]\n    orderedDefns.foreach: defn =>\n      childrenBySym(defn.sym) = ArrayBuf.empty\n    orderedDefns.foreach: defn =>\n      resolveParentSym(defn).foreach: parentSym =>\n        childrenBySym(parentSym) += defn.sym\n    orderedDefns.reverseIterator.foreach: defn =>\n      val ownTag = ctx.getTypeInfo_!(defn.sym).objectTag getOrElse:\n        lastWords(s\"Expected class ${defn.sym} to have an object tag\")\n      val childTags = childrenBySym(defn.sym).flatMap: childSym =>\n        ctx.getAllRuntimeTags(childSym).getOrElse(lastWords(\"unreachable\"))\n      ctx.registerRuntimeClassTags(defn.sym, LinkedHashSet(ownTag) ++ childTags)\n\n  /** Declares the shared Wasm function type used by a class-associated function placeholder. */\n  private def declareClassFuncType(\n      defn: ClsLikeDefn,\n      suffix: Str,\n      params: Seq[Local -> SymIdx],\n  )(using Ctx, Raise): TypeIdx =\n    ctx.addType(TypeInfo(\n      sym = TempSymbol(N, defn.sym.nme),\n      FunctionType(\n        params = params.map(p => WasmParam(p._2, RefType.anyref)),\n        results = Seq(Result(RefType.anyref)),\n      ),\n      objectTag = N,\n      wrapId = N -> S(suffix),\n    ))\n\n  /** Returns the symbol used to predeclare and later overwrite a class init function. */\n  private def initFuncSym(sym: BlockMemberSymbol): BlockMemberSymbol =\n    initFuncSyms.getOrElseUpdate(sym, BlockMemberSymbol(\"init\", Nil, nameIsMeaningful = false))\n\n  /** Registers a placeholder class-associated function so later lowering can overwrite it. */\n  private def predeclareClassFunc(\n      defn: ClsLikeDefn,\n      suffix: Str,\n      params: Seq[Local -> SymIdx],\n      sym: BlockMemberSymbol,\n      exportName: Opt[Str],\n  )(using Ctx, Raise): Unit =\n    val funcTy = declareClassFuncType(defn, suffix, params)\n    ctx.addFunc(new FuncInfo(\n      sym,\n      wrapId = if sym.asClsOrMod.isDefined then (N -> S(\"ctor\")) else (S(defn.sym.nme) -> N),\n      typeUse = TypeUse(funcTy),\n      params = params,\n      resultTypes = Seq(Result(RefType.anyref)),\n      locals = Seq.empty,\n      body = ref.`null`(ctx.getType_!(defn.sym)),\n      exportName = exportName,\n    ))\n\n  /** Declares one top-level class init function. */\n  private def predeclareClassInit(defn: ClsLikeDefn)(using Ctx, Raise): Unit =\n    val initParams = (defn.isym -> SymIdx(\"this\")) +:\n      defn.paramsOpt.fold(Nil): ps =>\n        ps.params.map: p =>\n          p.sym -> SymIdx(p.sym.nme)\n    predeclareClassFunc(defn, \"init\", initParams, initFuncSym(defn.sym), N)\n\n  /** Declares one top-level class constructor. */\n  private def predeclareClassConstructor(defn: ClsLikeDefn)(using Ctx, Raise): Unit =\n    val ctorParams = defn.paramsOpt.fold(Nil): ps =>\n      ps.params.map: p =>\n        p.sym -> SymIdx(p.sym.nme)\n    val ctorExportName = defn.sym\n      .optionIf: sym =>\n        !(defn.k is syntax.Obj) && sym.nameIsMeaningful\n      .map(_.nme)\n    predeclareClassFunc(defn, \"ctor\", ctorParams, defn.sym, ctorExportName)\n\n  /** Collects the symbols that should live in mutable globals so later REPL blocks can import them.\n    *\n    * TODO: replace this structural scan with an explicit \"session-visible bindings\" set from lowering once that\n    * information is available directly in the IR.\n    */\n  private def collectSessionGlobalSymbols(\n      b: Block,\n      sessionExportCtx: SessionExportCtx,\n  ): Set[Symbol] =\n    def restOf(block: Block): Opt[Block] = block match\n      case Define(_, rst) => S(rst)\n      case Assign(_, _, rst) => S(rst)\n      case AssignField(_, _, _, rst) => S(rst)\n      case AssignDynField(_, _, _, _, rst) => S(rst)\n      case Match(_, _, _, rst) => S(rst)\n      case TryBlock(_, _, rst) => S(rst)\n      case Label(_, _, _, rst) => S(rst)\n      case _ => N\n\n    def recur(block: Block): Set[Symbol] = block match\n      case Scoped(_, body) =>\n        recur(body)\n      case Begin(sub, rst) =>\n        recur(sub) ++ recur(rst)\n      case Define(ValDefn(_, sym, _), rst) if sessionExportCtx.shouldExport(sym) =>\n        recur(rst) + sym\n      case Define(_, rst) =>\n        recur(rst)\n      case Assign(sym: Symbol, _, rst) if sessionExportCtx.shouldExport(sym) =>\n        recur(rst) + sym\n      case _: BlockTail =>\n        Set.empty\n      case block =>\n        restOf(block).fold(Set.empty)(recur)\n\n    recur(b)\n  end collectSessionGlobalSymbols\n\n  /** Declares a mutable exported global for a REPL-visible binding produced by the current block. */\n  private def registerSessionGlobal(\n      sym: Symbol,\n  )(using Ctx, Raise, SessionExportCtx): Unit =\n    if ctx.containsGlobal(sym) then return\n    val exportName = sym.nme\n    val globalInfo = GlobalInfo(\n      globalType = GlobalType(RefType.anyref, mutable = true),\n      init = ref.`null`(HeapType.Any),\n      exportName = S(exportName),\n      sym,\n    )\n    ctx.addGlobal(globalInfo)\n    summon[SessionExportCtx].emit(SessionGlobal(\n      sym = sym,\n      wrapId = globalInfo.wrapId,\n      moduleName = SessionBinding.ReplModuleName,\n      exportName = exportName,\n      globalType = GlobalType(RefType.anyref, mutable = true),\n    ))\n  end registerSessionGlobal\n\n  /** Registers imported REPL bindings into the current module before codegen starts. */\n  private def registerSessionImports(\n      sessionImports: Seq[SessionBinding],\n  )(using Ctx, Raise): Unit =\n    sessionImports.foreach:\n      case cls: SessionClass =>\n        ctx.addType(TypeInfo(\n          sym = cls.sym,\n          wrapId = cls.wrapId,\n          compType = cls.compType,\n          objectTag = cls.objectTag,\n        ))\n        ctx.registerRuntimeClassTags(cls.sym, cls.runtimeTags)\n      case _ =>\n\n    sessionImports.foreach:\n      case func: SessionFunc =>\n        // If the function symbol comes from a class or module, generate a TempSymbol to avoid symbol collision with\n        // the class/module itself\n        val funcTySym = TempSymbol(N, func.sym.nme)\n        val typeIdx =\n          ctx.addType(TypeInfo(sym = funcTySym, wrapId = func.wrapId, compType = func.funcType, objectTag = N))\n        ctx.addFunctionImport(WasmImport(\n          func.moduleName,\n          func.exportName,\n          ExternType.Func(TypeUse(typeIdx), func.sym, wrapId = func.wrapId),\n        ))\n      case glob: SessionGlobal =>\n        ctx.addGlobalImport(WasmImport(\n          glob.moduleName,\n          glob.exportName,\n          ExternType.Global(glob.globalType, glob.sym, glob.wrapId),\n        ))\n      case singleton: SessionSingleton =>\n        val globalExtern =\n          ExternType.Global(\n            GlobalType(singleton.globalTy, mutable = true),\n            singleton.blockSym,\n            singleton.wrapId,\n          )\n        ctx.addGlobalImport(WasmImport(\n          singleton.moduleName,\n          singleton.exportName,\n          globalExtern,\n        ))\n        ctx.registerSingleton(\n          singleton.blockSym,\n          singleton.objectSym,\n          SingletonInfo(globalExtern.id.id, singleton.globalTy),\n        )\n      case _: SessionClass =>\n  end registerSessionImports\n\n  /** Declares one top-level class method. */\n  private def predeclareMethod(methodDefn: FunDefn, ownerCls: ClsLikeDefn)(using Ctx, Raise): Unit =\n    val methodParams = (ownerCls.isym -> SymIdx(\"this\")) +:\n      methodDefn.params.headOption.fold(Nil): ps =>\n        ps.params.map: p =>\n          p.sym -> SymIdx(p.sym.nme)\n    predeclareClassFunc(ownerCls, methodDefn.sym.nme, methodParams, methodDefn.sym, N)\n\n  /** Declares placeholders for all methods on one top-level class. */\n  private def predeclareClassMethods(defn: ClsLikeDefn)(using Ctx, Raise): Unit =\n    defn.methods.foreach:\n      case methodDefn @ FunDefn(_, _, _, Nil | _ :: Nil, _) =>\n        predeclareMethod(methodDefn, defn)\n      case FunDefn(_, sym, _, _ :: _ :: _, _) =>\n        raise(ErrorReport(\n          msg\"WatBuilder::predeclareClassMethods for ClsLikeDefn(...) with `multi-parameter-list method` not implemented yet\" ->\n            sym.toLoc :: Nil,\n          source = Diagnostic.Source.Compilation,\n        ))\n      case _ => ()\n\n  /** Gets (and caches) the exception tag used for MLX `throw`. */\n  private def exnTagIdx(using Ctx, Raise): TagIdx =\n    val sym = TempSymbol(N, \"mlx_exn\")\n    ctx.getOrCreateWasmIntrinsicTag(\n      \"mlx_exn\",\n      ctx.addTag(TagInfo(\n        typeUse = TypeUse(ctx.addType(TypeInfo(\n          sym,\n          FunctionType(params = Seq(WasmParam(SymIdx(\"ex\"), RefType.anyref)), results = Seq.empty),\n          objectTag = S(ctx.getFreshObjectTag()),\n        ))),\n        sym = sym,\n      )),\n    )\n\n  /** Returns (and caches) string literal data metadata, allocating data-segment space on first use.\n    */\n  private def internStringLiteral(value: Str): StringLitInfo =\n    stringLits.getOrElseUpdate(\n      value,\n      if value.isEmpty then\n        StringLitInfo(offset = 0, byteLen = 0, watBytes = \"\")\n      else\n        val sb = new StringBuilder(value.length * 6)\n        value.foreach: ch =>\n          val codeUnit = ch.toInt\n          sb.append(f\"\\\\${codeUnit & 0xff}%02x\")\n          sb.append(f\"\\\\${(codeUnit >>> 8) & 0xff}%02x\")\n        val watBytes = sb.toString\n        val offset = (nextStringDataOffset + 1) & ~1\n        val byteLen = value.length * 2\n        nextStringDataOffset = offset + byteLen\n        StringLitInfo(offset = offset, byteLen = byteLen, watBytes = watBytes),\n    )\n\n  /** Ensures imports required for string materialization exist and returns the constructor function.\n    */\n  private def getOrLoadStrCtorFunction(using Ctx, Raise): FuncIdx =\n    val minBytes = nextStringDataOffset\n    val pageSize = ExternIntrinsics.WasmPageSizeBytes\n    val minPages =\n      if minBytes <= 0 then 0\n      else (minBytes + pageSize - 1) / pageSize\n    ctx.ensureMemoryImport(\n      ExternIntrinsics.SystemModule,\n      ExternIntrinsics.SystemMemoryImportName,\n      minPages,\n    )\n    ctx.getOrCreateFunctionImport(\n      module = ExternIntrinsics.SystemModule,\n      name = ExternIntrinsics.StringFromUtf16ImportName,\n    ):\n      val importTySym = TempSymbol(N, ExternIntrinsics.StringFromUtf16ImportName)\n      val importTy = ctx.addType(TypeInfo(\n        sym = importTySym,\n        compType = FunctionType(\n          params = Seq(WasmParam(SymIdx(\"glob_offset\"), RefType.anyref), WasmParam(SymIdx(\"len\"), RefType.anyref)),\n          results = Seq(Result(RefType.anyref)),\n        ),\n        objectTag = N,\n      ))\n      WasmImport(\n        module = ExternIntrinsics.SystemModule,\n        name = ExternIntrinsics.StringFromUtf16ImportName,\n        externType = ExternType.Func(\n          typeUse = TypeUse(importTy),\n          sym = importTySym,\n          wrapId = N -> N,\n        ),\n      )\n  end getOrLoadStrCtorFunction\n\n  /** Gets (and caches) the Wasm GC array type used for tuples (`mut` selects mutability).\n    */\n  private def tupleArrayType(mut: Bool)(using Ctx, Raise): TypeIdx =\n    ctx.getOrCreateWasmIntrinsicType(WasmIntrinsicType.TupleArray(mutable = mut)):\n      val suffix = if mut then \"Mut\" else \"\"\n      val sym = BlockMemberSymbol(s\"TupleArray$suffix\", Nil)\n      ctx.addType(TypeInfo(\n        sym,\n        ArrayType(elemType = RefType.anyref, mutable = mut),\n        objectTag = N,\n      ))\n\n  /** Allocates a fresh temp local (typed `anyref`) and returns its `LocalIdx`.\n    */\n  private def mkTempLocal(base: Str)(using Ctx, FunctionCtx, Raise): LocalIdx =\n    funcCtx.addLocal(TempSymbol(N, base))\n\n  /** Binds constructor self (`thisSym`) to the Wasm local name `this` in the current function context.\n    */\n  private def bindCtorThis(thisSym: Local)(using Ctx, FunctionCtx, Raise): LocalIdx =\n    funcCtx.addLocal(thisSym, S(\"this\"))\n\n  /** Compiles a class init body under its own Wasm-local frame with explicit `this`. */\n  private def setupInitLocals(\n      clsLikeDefn: ClsLikeDefn,\n  )(using Ctx, Raise, SessionExportCtx): (Expr, FunctionCtx) =\n    genFuncBody(clsLikeDefn.paramsOpt.toList, thisSym = S(clsLikeDefn.isym)):\n      val thisVar = funcCtx.lookupLocal_!(clsLikeDefn.isym, N)\n      val preCtorWat = compilePreCtor(clsLikeDefn, thisVar)\n      val ctorWat = block(clsLikeDefn.ctor)\n      blockInstr(\n        label = N,\n        children = Seq(\n          preCtorWat,\n          ctorWat,\n          `return`(S(local.get(thisVar, RefType.anyref))),\n        ),\n        resultTypes = Seq(Result(RefType.anyref)),\n      )\n\n  /** Lowers an inherited pre-constructor by preserving its setup code and rewriting the final `super(...)` into\n    * `Parent_init(this, ...)`.\n    */\n  private def compilePreCtor(\n      clsLikeDefn: ClsLikeDefn,\n      thisVar: LocalIdx,\n  )(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr =\n    def withRest(block: NonBlockTail, rest: Block): Block = block match\n      case Scoped(syms, _) => Scoped(syms, rest)\n      case Begin(sub, _) => Begin(sub, rest)\n      case TryBlock(sub, finallyDo, _) => TryBlock(sub, finallyDo, rest)\n      case Assign(lhs, rhs, _) => Assign(lhs, rhs, rest)\n      case af @ AssignField(lhs, nme, rhs, _) => AssignField(lhs, nme, rhs, rest)(af.symbol)\n      case AssignDynField(lhs, fld, arrayIdx, rhs, _) => AssignDynField(lhs, fld, arrayIdx, rhs, rest)\n      case Define(defn, _) => Define(defn, rest)\n      case Match(scrut, arms, dflt, _) => Match(scrut, arms, dflt, rest)\n      case Label(label, loop, body, _) => Label(label, loop, body, rest)\n\n    def splitSuperTail(block: Block): Opt[Block -> Ls[Arg]] = block match\n      case End(_) => N\n      case Return(Call(Value.Ref(bs: BuiltinSymbol, _), argss), true) if bs eq State.builtinOpsMap(\"super\") =>\n        S(End(\"\") -> argss.flatten)\n      case b: NonBlockTail =>\n        splitSuperTail(b.rest).map: (prefix, args) =>\n          withRest(b, prefix) -> args\n      case _ => N\n\n    clsLikeDefn.preCtor match\n      case End(_) => nop\n      case _ =>\n        splitSuperTail(clsLikeDefn.preCtor) match\n          case S((prefixBlock, args)) =>\n            val prefixWat = block(prefixBlock)\n            resolveParentSym(clsLikeDefn) match\n              case S(parentSym) =>\n                val parentInitFunc = initFuncSym(parentSym)\n                val superCall = call(\n                  funcidx = ctx.getFunc_!(parentInitFunc),\n                  operands = local.get(thisVar, RefType.anyref) +: args.map(argument),\n                  returnTypes = Seq(Result(RefType.anyref)),\n                )\n                blockInstr(\n                  label = N,\n                  children = Seq(asStatement(prefixWat), drop(superCall)),\n                  resultTypes = Seq.empty,\n                )\n              case N =>\n                nop\n          case N =>\n            raise(ErrorReport(\n              msg\"Wasm preCtor lowering only supports lowered super(...) shapes.\" ->\n                clsLikeDefn.sym.toLoc :: Nil,\n              extraInfo = S(clsLikeDefn.preCtor.showAsTree),\n              source = Diagnostic.Source.Compilation,\n            ))\n            nop\n    end match\n  end compilePreCtor\n\n  /** Converts expression result types to WAT result clauses, dropping unreachable types. */\n  private def resultClauses(expr: Expr): Seq[Result] =\n    if expr.resultTypes.exists(_ is UnreachableType) then Seq.empty\n    else expr.resultTypes.map(ty => Result(ty.asValType_!))\n\n  /** Normalizes the exported `entry` body so it always returns single result. */\n  private def normalizeEntryExpr(\n      expr: Expr,\n      isAbortive: Bool,\n  )(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr =\n    if expr.resultTypes.isEmpty && !isAbortive then\n      blockInstr(\n        label = N,\n        children = Seq(expr, result(Value.Ref(State.unitSymbol))),\n        resultTypes = Seq(Result(RefType.anyref)),\n      )\n    else\n      expr\n\n  /** Validates an IntLit value fits signed 32-bit and delegates codegen to `onValid`.\n    */\n  private def withValidIntLit(\n      value: BigInt,\n      loc: Opt[Loc],\n  )(onValid: Int => Expr)(using Ctx, Raise, Line): Expr =\n    if value.isValidInt then onValid(value.toInt)\n    else\n      errExpr(\n        Ls(msg\"WatBuilder::IntLit lowering with value outside signed 32-bit range not implemented yet\" -> loc),\n        extraInfo = S(value.toString),\n      )\n\n  /** Emits a tuple element load that works for both mutable and immutable tuple arrays.\n    */\n  private def tupleArrayGet(tupleExpr: Expr, idxBuilder: Expr => Expr)(using Ctx, FunctionCtx, Raise): Expr =\n    val elemType = RefType.anyref\n    val mutArrayType = tupleArrayType(true)\n    val immArrayType = tupleArrayType(false)\n    val tupleTmp = mkTempLocal(\"tuple\")\n    val tupleIsMutable = ref.test(local.tee(tupleTmp, tupleExpr), RefType(mutArrayType, nullable = true))\n    val tupleValue = local.get(tupleTmp, RefType.anyref)\n    val mutableBranch =\n      val tupleRef = ref.cast(tupleValue, RefType(mutArrayType, nullable = false))\n      array.get(mutArrayType, tupleRef, idxBuilder(tupleRef), elemType)\n    val immutableBranch =\n      val tupleRef = ref.cast(tupleValue, RefType(immArrayType, nullable = false))\n      array.get(immArrayType, tupleRef, idxBuilder(tupleRef), elemType)\n    `if`(\n      condition = tupleIsMutable,\n      ifTrue = mutableBranch,\n      ifFalse = S(immutableBranch),\n      resultTypes = Seq(Result(elemType.asValType_!)),\n    )\n\n  /** Builds an i32 index for tuple indexing (supports negative indices; caches non-literals).\n    */\n  private def compileTupleIndex(\n      fld: Path,\n      loc: Opt[Loc],\n      errCtx: Str,\n      errExtra: => Str,\n  )(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr => Expr =\n    fld match\n      case Value.Lit(IntLit(value)) if value.isValidInt =>\n        val idx = value.toInt\n        tupleRef =>\n          if idx >= 0 then i32.const(idx)\n          else i32.add(array.len(tupleRef), i32.const(idx))\n      case _ =>\n        val rawIdx = result(fld)\n        val idxI32 = rawIdx.resultType match\n          case S(I32Type) => rawIdx\n          case S(RefType(HeapType.I31, _)) => i31.get(rawIdx, signed = true)\n          case S(RefType(HeapType.Any, _)) =>\n            val casted = ref.cast(rawIdx, RefType.i31ref)\n            i31.get(casted, signed = true)\n          case ty =>\n            return (_: Expr) =>\n              errExpr(\n                msg\"$errCtx expects an integer index but found ${ty.fold(\"(none)\")(_.toWat.mkString())}\" -> loc :: Nil,\n                extraInfo = S(errExtra),\n              )\n\n        val idxTmp = mkTempLocal(\"idx\")\n\n        tupleRef =>\n          val storeIdx = local.set(idxTmp, ref.i31(idxI32))\n          def idxVal: Expr = i31.get(ref.cast(local.get(idxTmp, RefType.anyref), RefType.i31ref), signed = true)\n\n          val normalizedIdx = `if`(\n            condition = i32.lt_s(idxVal, i32.const(0)),\n            ifTrue = i32.add(idxVal, array.len(tupleRef)),\n            ifFalse = S(idxVal),\n            resultTypes = Seq(Result(I32Type)),\n          )\n\n          blockInstr(\n            label = N,\n            children = Seq(storeIdx, normalizedIdx),\n            resultTypes = Seq(Result(I32Type)),\n          )\n\n  /** Raises a [[WarningReport]] with the given `warnMsgs` and `extraInfo`, and emits the `defaultValue` instruction.\n    */\n  def warnExpr(\n      warnMsgs: Ls[Message -> Opt[Loc]],\n      extraInfo: Opt[Any] = N,\n  )(defaultValue: => FoldedInstr = unreachable)(using Ctx, Raise)(using Line): Expr =\n    raise(WarningReport(warnMsgs, source = Diagnostic.Source.Compilation, extraInfo = extraInfo))\n    defaultValue\n\n  /** Raises an [[ErrorReport]] with the given `warnMsgs` and `extraInfo`, and emits an `unreachable` instruction.\n    */\n  def errExpr(\n      errMsgs: Ls[Message -> Opt[Loc]],\n      extraInfo: => Opt[Any] = N,\n  )(using Ctx, Raise)(using Line): Expr =\n    raise(ErrorReport(errMsgs, source = Diagnostic.Source.Compilation, extraInfo = extraInfo))\n    unreachable\n\n  def getVar(l: Local, loc: Opt[Loc])(using Ctx, FunctionCtx, Raise): Expr =\n    singletonInfoFor(l) match\n      case S(info) => singletonGlobalGet(info)\n      case N => l match\n          case ts: semantics.TermSymbol =>\n            errExpr(\n              Ls(msg\"WatBuilder::getVar for TermSymbol not implemented yet\" -> ts.toLoc),\n              extraInfo = S(ts.toString),\n            )\n          case ts: semantics.ModuleOrObjectSymbol if ts.asMod.isDefined =>\n            errExpr(\n              Ls(\n                msg\"WatBuilder::getVar for ModuleOrObjectSymbol (`ts.asMod.isDefined`) not implemented yet\" -> ts.toLoc,\n              ),\n              extraInfo = S(ts.toString),\n            )\n          case ts: semantics.InnerSymbol =>\n            funcCtx.lookupLocal(ts) match\n              case S(localIdx) => local.get(localIdx, RefType.anyref)\n              case N =>\n                errExpr(\n                  Ls(\n                    msg\"WatBuilder::getVar for InnerSymbol `${ts.toString}` (symbol not in top-level scope) not implemented yet\" ->\n                      ts.toLoc,\n                  ),\n                  extraInfo = S(\n                    s\"Locals: ${(funcCtx.params ++ funcCtx.locals).toString}\\nGlobals: ${ctx.getGlobals.toString}\",\n                  ),\n                )\n          case l =>\n            funcCtx.lookupLocal(l) match\n              case S(localIdx) => local.get(localIdx, RefType.anyref)\n              case N if ctx.containsGlobal(l) =>\n                global.get(ctx.getGlobal_!(l), ctx.getGlobalType_!(l).globalType.valType)\n              case _ =>\n                errExpr(\n                  Ls(\n                    msg\"Cannot find variable `${l.toString}` (${l.getClass.getSimpleName}) in local or global scope.\" ->\n                      l.toLoc,\n                  ),\n                  extraInfo = S(\n                    s\"Locals: ${(funcCtx.params ++ funcCtx.locals).toString}\\nGlobals: ${ctx.getGlobals.toString}\",\n                  ),\n                )\n  end getVar\n\n  def argument(a: Arg)(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr =\n    if a.spread.nonEmpty then\n      errExpr(\n        Ls(msg\"WatBackend::argument for spread expression not implemented yet\" -> a.value.toLoc),\n        extraInfo = S(a.showAsTree),\n      )\n    else result(a.value)\n\n  def operand(a: Arg)(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr =\n    if a.spread.nonEmpty then die else subexpression(a.value)\n\n  def subexpression(r: codegen.Result)(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr = r match\n    case r: Lambda =>\n      errExpr(\n        Ls(msg\"WatBuilder::subexpression for Lambda not implemented yet\" -> r.toLoc),\n        extraInfo = S(r.showAsTree),\n      )\n    case r => result(r)\n\n  /** Returns the owning class symbol for a resolved field/member symbol, when available. */\n  private def fieldOwner(sym: Symbol): Opt[BlockMemberSymbol] = sym match\n    case ts: TermSymbol => ts.owner.flatMap(_.asBlkMember)\n    case ms: MemberSymbol => ms.asTrm.flatMap(_.owner.flatMap(_.asBlkMember))\n    case _ => N\n\n  def fieldSelect(thisSym: BlockMemberSymbol, sym: DefinitionSymbol[?])(using Ctx, Raise): FieldIdx =\n    val structInfo = ctx.getTypeInfo_!(thisSym)\n    val symToField = structInfo.compType match\n      case ty: StructType => ty.fieldsBySym\n      case _ => lastWords(s\"Cannot select field from non-struct type: ${structInfo.compType.toWat.mkString()}\")\n    val fieldIdx = symToField.get(sym).fold(lastWords(\n      s\"Missing field `${sym.toString}` in struct `${thisSym.toString}` with type `${structInfo.toWat.mkString()}`\",\n    )): field =>\n      field.id\n    FieldIdx(SymIdx(fieldIdx))\n  end fieldSelect\n\n  /** Resolves `sym` to a predeclared class method symbol, if any. */\n  private def predeclaredClassMethodSym(sym: DefinitionSymbol[?])(using Ctx): Opt[BlockMemberSymbol] =\n    sym.asBlkMember.filter: methodSym =>\n      methodSym.asTrm.exists(_.owner.exists(_.asCls.isDefined)) && ctx.getFunc(methodSym).nonEmpty\n\n  def result(r: codegen.Result)(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr = r match\n    case Value.This(sym) =>\n      // TODO(Derppening): Add type tracking and refinement for locals, remove the `ref.cast`\n      ref.cast(\n        local.get(funcCtx.lookupLocal_!(sym, sym.toLoc), RefType.anyref),\n        RefType(\n          sym.asBlkMember.fold(baseObjectTypeIdx)(ctx.getType_!(_)),\n          nullable = false,\n        ),\n      )\n    case Value.Lit(BoolLit(value)) =>\n      ref.i31(i32.const(if value then 1 else 0))\n    case Value.Lit(IntLit(value)) =>\n      withValidIntLit(value, r.toLoc)(intVal => ref.i31(i32.const(intVal)))\n    case Value.Lit(StrLit(value)) =>\n      val lit = internStringLiteral(value)\n      val stringCtor = getOrLoadStrCtorFunction\n      call(\n        funcidx = stringCtor,\n        operands = Seq(ref.i31(i32.const(lit.offset)), ref.i31(i32.const(lit.byteLen))),\n        returnTypes = Seq(Result(RefType.anyref)),\n      )\n    case Value.Ref(l, disamb) =>\n      if (l is State.unitSymbol) || disamb.contains(State.unitSymbol) then\n        RegisterUnitSingleton()\n      singletonInfoFor(l) match\n        case S(info) => singletonGlobalGet(info)\n        case N =>\n          if disamb.exists(_.isInstanceOf[ClassSymbol]) then\n            errExpr:\n              Ls(msg\"Plain class references are not supported in Wasm; instantiate the class instead.\" -> r.toLoc)\n          else\n            ctx.getFunc(l) match\n              case S(funcIdx) => ref.func(funcIdx, RefType(ctx.getFuncTypeUse_!(l).typeIdx, nullable = false))\n              case N => getVar(l, r.toLoc)\n\n    case Call(Value.Ref(l: BuiltinSymbol, _), lhs :: rhs :: Nil) if !l.functionLike =>\n      if l.binary then\n        errExpr(\n          Ls(\n            msg\"WatBuilder::result encountered builtin '${\n                l.nme\n              }' which should be lowered to an intrinsic function\" ->\n              r.toLoc,\n          ),\n          extraInfo = S(r.toString),\n        )\n      else\n        errExpr(Ls(msg\"Cannot call non-binary builtin symbol '${l.nme}'\" -> r.toLoc))\n\n    case Call(sel @ Select(qual, _), argss) if sel.symbol.flatMap(predeclaredClassMethodSym).nonEmpty =>\n      if argss.length > 1 then\n        return errExpr(\n          Ls(msg\"WatBuilder::result for Call(...) with multiple argument lists is not supported yet\" -> r.toLoc),\n          extraInfo = S(r.toString),\n        )\n      val methodSym = sel.symbol.flatMap(predeclaredClassMethodSym).get\n      call(\n        funcidx = ctx.getFunc_!(methodSym),\n        operands = result(qual) +: argss.flatten.map(argument),\n        returnTypes = Seq(Result(RefType.anyref)),\n      )\n\n    case c @ Call(fun, argss) =>\n      if argss.length > 1 then\n        return errExpr(\n          Ls(msg\"WatBuilder::result for Call(...) with multiple argument lists is not supported yet\" -> c.toLoc),\n          extraInfo = S(c.toString),\n        )\n      val args = argss.flatten\n      wasmIntrinsicName(fun) match\n        case S(intrName) =>\n          val expectedArity = wasmIntrinsicArities(intrName)\n          if expectedArity =/= args.length then\n            return errExpr(\n              Ls(msg\"Wasm intrinsic '$intrName' called with incorrect arity (${args.length})\" -> c.toLoc),\n              extraInfo = S(c.toString),\n            )\n          val funcIdx = getIntrinsic(intrName)\n          call(\n            funcidx = funcIdx,\n            operands = args.map(argument),\n            returnTypes = Seq(Result(RefType.anyref)),\n          )\n        case N =>\n          fun match\n            case Value.Ref(l, _) =>\n              val base = fun match\n                case Value.Ref(l, _) => ctx.getFunc(l)\n                case _ => N\n              val baseFuncIdx = base match\n                case S(idx) => idx\n                case N => return errExpr(\n                    Ls(msg\"Expected static function reference in Call(...) expression\" -> fun.toLoc),\n                    extraInfo = S(fun.toString),\n                  )\n              val baseTypeInfo = ctx.getTypeInfo_!(ctx.getFuncTypeUse_!(baseFuncIdx).typeIdx)\n              val wasmArgs = args.map(argument)\n\n              call(\n                funcidx = baseFuncIdx,\n                operands = wasmArgs.toSeq,\n                returnTypes = baseTypeInfo.compType.asInstanceOf[FunctionType].sigType.results,\n              )\n            case _ =>\n              val base = subexpression(fun)\n              if base.resultTypes.exists(_ is UnreachableType) then return base\n              val wasmArgs = args.map(argument)\n\n              val baseTypeIdx = base.resultType match\n                case S(RefType(idx: TypeIdx, _)) => idx\n                case ty =>\n                  return errExpr(\n                    Ls(msg\"Expected WAT of `fun` expression in Call(...) to have a `(ref <typeidx>)` type\" -> r.toLoc),\n                    extraInfo = S(\n                      s\"Block IR: `${\n                          fun.toString\n                        }`\\nCompiled WAT: `${\n                          base.toWat.mkString()\n                        }`\\n... which has type `${\n                          ty.fold(\"(none)\")(_.toWat.mkString())\n                        }`\",\n                    ),\n                  )\n              val baseTypeInfo = ctx.getTypeInfo_!(baseTypeIdx)\n\n              call_ref(\n                target = base,\n                operands = wasmArgs.toSeq,\n                typeIdx = baseTypeIdx,\n                funcType = baseTypeInfo.compType.asInstanceOf[FunctionType],\n              )\n\n    case sel @ Select(qual, id) =>\n      sel.symbol match\n        case S(selObj: ModuleOrObjectSymbol) =>\n          if selObj is State.unitSymbol then\n            RegisterUnitSingleton()\n          singletonInfoFor(selObj) match\n            case S(info) => singletonGlobalGet(info)\n            case N =>\n              errExpr(\n                Ls(msg\"WatBuilder::result for object selection `${id.name}` not implemented yet\" -> sel.toLoc),\n                extraInfo = S(sel),\n              )\n\n        case S(selSym) if predeclaredClassMethodSym(selSym).nonEmpty =>\n          val methodSym = predeclaredClassMethodSym(selSym).get\n          methodSym.asTrm.flatMap(_.defn) match\n            case S(defn: TermDefinition) if defn.params.isEmpty =>\n              call(\n                funcidx = ctx.getFunc_!(methodSym),\n                operands = Seq(result(qual)),\n                returnTypes = Seq(Result(RefType.anyref)),\n              )\n            case _ =>\n              errExpr(\n                Ls(\n                  msg\"`${methodSym.toString}` is neither a field access nor a callable method\" ->\n                    sel.toLoc,\n                ),\n                extraInfo = S(sel),\n              )\n\n        case S(selSym: MemberSymbol) =>\n          val qualRes = result(qual)\n          val ownerInfo = fieldOwner(selSym)\n          val selCls = fieldOwner(selSym) getOrElse:\n            lastWords(\n              s\"Expected resolved class for Select(...) expression to be a BlockMemberSymbol, but got ${ownerInfo.fold(\"(none)\")(\n                  _.toString,\n                )}\",\n            )\n          val fieldidx = fieldSelect(selCls, selSym)\n          struct.get(\n            fieldidx,\n            ref = ref.cast(qualRes, RefType(ctx.getType_!(selCls), nullable = false)),\n            ty = RefType.anyref,\n          )\n        case N =>\n          errExpr(\n            Ls(\n              msg\"WatBuilder::result for field selection without a resolved symbol is not implemented (field `${\n                  id.name\n                }`). Use `_.[_]` for index-based accesses.\" ->\n                sel.toLoc,\n            ),\n            extraInfo = S(sel),\n          )\n\n    case dyn @ DynSelect(qual, fld, arrayIdx) =>\n      val qualRes = result(qual)\n      if arrayIdx then\n        val idxBuilder = compileTupleIndex(\n          fld = fld,\n          loc = fld.toLoc,\n          errCtx = \"WatBuilder::result for array-style dynamic selections\",\n          errExtra = dyn.toString,\n        )\n        tupleArrayGet(qualRes, idxBuilder)\n      else\n        errExpr(\n          Ls(msg\"WatBuilder::result for dynamic field selections is not implemented yet\" -> dyn.toLoc),\n          extraInfo = S(dyn),\n        )\n\n    case Instantiate(_, cls, argss) =>\n      if argss.length > 1 then\n        return errExpr(\n          Ls(msg\"WatBuilder::result for Instantiate(...) with multiple argument lists is not supported yet\" -> r.toLoc),\n          extraInfo = S(r.toString),\n        )\n      val as = argss.flatten\n      cls match\n        // TODO: Implement proper lowering for Errors with unit payloads.\n        case Select(Value.Ref(sym, _), id)\n            if (sym eq State.globalThisSymbol) && id.name == \"Error\" =>\n          return as.headOption match\n            case S(arg) => arg.value match\n                case Value.Lit(BoolLit(value)) => ref.i31(i32.const(if value then 1 else 0))\n                case Value.Lit(IntLit(value)) =>\n                  withValidIntLit(value, arg.value.toLoc)(intVal => ref.i31(i32.const(intVal)))\n                case Value.Lit(StrLit(_)) => result(arg.value)\n                case unsupported =>\n                  warnExpr(\n                    msg\"WatBuilder::result for Instantiate(...) of `globalThis.Error(...)` with payload `${\n                        unsupported.toString\n                      }` not implemented yet\" ->\n                      unsupported.toLoc :: Nil,\n                    extraInfo = S(unsupported.toString),\n                  ):\n                    ref.i31(i32.const(0))\n            case N => ref.i31(i32.const(0))\n        case _ => ()\n      end match\n      val ctorClsSymOpt = cls match\n        case ref: Value.Ref => ref.disamb\n        case sel: Select => sel.symbol\n        case cls => return errExpr(\n            Ls(\n              msg\"WatBuilder::result for Instantiate(...) where `cls` is not a Ref(...) or Select(...) path not implemented yet \" ->\n                cls.toLoc,\n            ),\n            extraInfo = S(s\"Block IR of `cls` expression: ${cls.toString}\"),\n          )\n      val ctorClsSym = ctorClsSymOpt match\n        case S(sym) => sym\n        case N => return errExpr(\n            Ls(msg\"Class path for an Instantiate(...) expression must be resolved\" -> cls.toLoc),\n            extraInfo = S(s\"Block IR of `cls` expression: ${cls.toString}\"),\n          )\n      val ctorClsBlkSym = ctorClsSym.asBlkMember match\n        case S(sym) => sym\n        case N => lastWords(\n            s\"Expected resolved class for an Instantiate(...) expression to be a BlockMemberSymbol, but got ${\n                ctorClsSym.getClass.getName\n              }\",\n          )\n      val ctorFuncIdx = ctx.getFunc(ctorClsBlkSym) match\n        case S(idx) => idx\n        case N => lastWords(s\"Missing constructor definition for class ${ctorClsBlkSym.toString}\")\n      call(funcidx = ctorFuncIdx, as.map(argument), Seq(Result(RefType.anyref)))\n\n    case Tuple(mut, elems) =>\n      val tupleValues = elems.map(argument)\n      array.new_fixed(tupleArrayType(mut), tupleValues)\n\n    case r =>\n      errExpr(\n        Ls(msg\"WatBackend::result for ${r.getClass.getSimpleName} expression not implemented yet\" -> r.toLoc),\n        extraInfo = S(s\"Block IR: `${r.toString}`\"),\n      )\n  end result\n\n  /** Returns the intrinsic name if `path` refers to a builtin under `wasm`, or `N` otherwise.\n    */\n  private def wasmIntrinsicName(path: Path): Opt[Str] = path match\n    case Select(Value.Ref(sym, _), ident) if (sym eq State.wasmSymbol) && wasmIntrinsicNameSet.contains(ident.name) =>\n      S(ident.name)\n    case _ => N\n\n  /** Gets (or creates) the intrinsic function implementing the wasm operator `name`.\n    */\n  private def getIntrinsic(name: Str)(using Ctx, Raise): FuncIdx =\n    ctx.getOrCreateWasmIntrinsic(name, importIntrinsic(name))\n\n  private def importIntrinsic(name: Str)(using Ctx, Raise): FuncIdx =\n    val typeIdx = declareIntrinsicType(name)\n    ctx.addFunctionImport(WasmImport(\n      ExternIntrinsics.SystemModule,\n      name,\n      ExternType.Func(TypeUse(typeIdx), TempSymbol(N, name), wrapId = N -> N),\n    ))\n\n  /** Creates the intrinsic definition for `name`.\n    */\n  private def createIntrinsic(name: Str, exportName: Opt[Str])(using Ctx, Raise): FuncIdx =\n    if binaryOps.contains(name) then createBinaryInt31Func(name, binaryOps(name), exportName)\n    else if unaryOps.contains(name) then createUnaryInt31Func(name, unaryOps(name), exportName)\n    else lastWords(s\"Unsupported wasm intrinsic '$name'\")\n\n  private def intrinsicParamSuffixes(name: Str): Seq[Str] =\n    if binaryOps.contains(name) then Seq(\"lhs\", \"rhs\") else Seq(\"arg\")\n\n  private def declareIntrinsicType(name: Str)(using Ctx, Raise): TypeIdx =\n    ctx.addType(TypeInfo(\n      sym = TempSymbol(N, name),\n      compType = FunctionType(\n        params = intrinsicParamSuffixes(name).map(nme => WasmParam(SymIdx(nme), RefType.anyref)),\n        results = Seq(Result(RefType.anyref)),\n      ),\n      objectTag = N,\n    ))\n\n  /** Creates a binary Int31 intrinsic with two parameters and body built from `op`.\n    */\n  private def createBinaryInt31Func(\n      name: Str,\n      op: (Expr, Expr) => Expr,\n      exportName: Opt[Str],\n  )(using Ctx, Raise): FuncIdx =\n    val params = mkIntrinsicParams(name, Seq(\"lhs\", \"rhs\"))\n    val lhsName = params.head._2\n    val rhsName = params(1)._2\n    val body = binaryInt31Body(LocalIdx(lhsName), LocalIdx(rhsName), op)\n    createIntrinsicFunc(name, params, body, exportName)\n\n  /** Creates a unary Int31 intrinsic with a single parameter and body built from `op`.\n    */\n  private def createUnaryInt31Func(\n      name: Str,\n      op: Expr => Expr,\n      exportName: Opt[Str],\n  )(using Ctx, Raise): FuncIdx =\n    val params = mkIntrinsicParams(name, Seq(\"arg\"))\n    val argName = params.head._2\n    val body = unaryInt31Body(LocalIdx(argName), op)\n    createIntrinsicFunc(name, params, body, exportName)\n\n  /** Allocates the Wasm type and function definition for an intrinsic with the given signature.\n    */\n  private def createIntrinsicFunc(\n      name: Str,\n      params: Seq[TempSymbol -> SymIdx],\n      body: Expr,\n      exportName: Opt[Str],\n  )(using Ctx, Raise): FuncIdx =\n    val funcTy = declareIntrinsicType(name)\n    val funcInfo = FuncInfo(\n      sym = TempSymbol(N, name),\n      typeUse = TypeUse(funcTy),\n      params = params,\n      locals = Seq.empty,\n      body = body,\n      resultTypes = Seq(Result(RefType.anyref)),\n      exportName = exportName,\n    )\n    ctx.addFunc(funcInfo)\n\n  def intrinsicSupportModule()(using Raise): Document =\n    val ctx = Ctx.empty\n    given Ctx = ctx\n    wasmIntrinsicNameSet.toSeq.sorted.foreach: name =>\n      createIntrinsic(name, S(name))\n    ctx.toWat\n\n  /** Builds the body for an Int31 binary operator.\n    */\n  private def binaryInt31Body(\n      lhsIdx: LocalIdx,\n      rhsIdx: LocalIdx,\n      op: (Expr, Expr) => Expr,\n  )(using Ctx): Expr =\n    val cond = i32.and(\n      ref.test(getLocalAnyref(lhsIdx), RefType.i31ref),\n      ref.test(getLocalAnyref(rhsIdx), RefType.i31ref),\n    )\n    val i31Op = ref.i31(op(getI32FromAnyref(lhsIdx), getI32FromAnyref(rhsIdx)))\n    `if`(\n      condition = cond,\n      ifTrue = i31Op,\n      ifFalse = S(unreachable),\n      resultTypes = Seq(Result(RefType.anyref)),\n    )\n\n  /** Builds the body for an Int31 unary operator.\n    */\n  private def unaryInt31Body(paramIdx: LocalIdx, op: Expr => Expr)(using Ctx): Expr =\n    val cond = ref.test(getLocalAnyref(paramIdx), RefType.i31ref)\n    val i31Op = ref.i31(op(getI32FromAnyref(paramIdx)))\n    `if`(\n      condition = cond,\n      ifTrue = i31Op,\n      ifFalse = S(unreachable),\n      resultTypes = Seq(Result(RefType.anyref)),\n    )\n\n  /** Creates parameters for an intrinsic.\n    */\n  private def mkIntrinsicParams(name: Str, suffixes: Seq[Str]): Seq[TempSymbol -> SymIdx] =\n    suffixes.map: suffix =>\n      val sym = TempSymbol(N, suffix)\n      sym -> SymIdx(suffix)\n\n  /** Loads the local `name` as an `anyref`.\n    */\n  private def getLocalAnyref(idx: LocalIdx): Expr =\n    local.get(idx, RefType.anyref)\n\n  /** Extracts the signed i32 value from the Int31 stored in the local `name`.\n    */\n  private def getI32FromAnyref(idx: LocalIdx): Expr =\n    i31.get(ref.cast(getLocalAnyref(idx), RefType.i31ref), true)\n\n  extension (expr: Expr)\n    private def isControlTransfer: Bool =\n      expr.resultType.contains(UnreachableType) || expr.mnemonic == \"return\"\n\n  private def asStatement(expr: Expr): Expr =\n    if expr.isControlTransfer then expr\n    else\n      expr.resultType match\n        case S(_) => drop(expr)\n        case N => expr\n\n  def returningTerm(t: Block)(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr =\n    t match\n      case Assign(l, r, rst) if l is State.noSymbol =>\n        val rExpr = result(r)\n        val evalExpr = rExpr.resultType match\n          case S(_) => drop(rExpr)\n          case N => rExpr\n        val rstBlk = returningTerm(rst)\n        blockInstr(\n          label = N,\n          children = Seq(evalExpr, rstBlk),\n          resultTypes = rstBlk.resultTypes.map(r => Result(r.asValType_!)),\n        )\n\n      case Assign(l, r, rst) =>\n        val lExpr = getVar(l, l.toLoc)\n        val rExpr = result(r)\n        val assignExpr = lExpr.mnemonicPrefix match\n          case S(\"global\") =>\n            global.set(lExpr.instrargs(0).asInstanceOf[GlobalIdx], rExpr)\n          case S(\"local\") =>\n            local.set(lExpr.instrargs(0).asInstanceOf[LocalIdx], rExpr)\n          case _ =>\n            lastWords(\n              s\"Expected `global.*` or `local.*` when compiling instruction for `$l`, but got ${lExpr.mnemonic}\",\n            )\n\n        val rstBlk = returningTerm(rst)\n        blockInstr(\n          label = N,\n          children = Seq(assignExpr, rstBlk),\n          resultTypes = resultClauses(rstBlk),\n        )\n\n      case assign @ AssignField(lhs, nme, rhs, rst) =>\n        val lhsExpr = result(lhs)\n        val rhsExpr = result(rhs)\n        val assignInstr = assign.symbol match\n          case S(selSym) =>\n            selSym.asTrm match\n              case S(fieldSym) =>\n                val selOwner = fieldSym.owner getOrElse\n                  lastWords(s\"Expected resolved AssignField(...) expression `$fieldSym` to have an owner\")\n                val selCls = selOwner.asBlkMember getOrElse\n                  lastWords(\n                    s\"Expected resolved class for AssignField(...) expression to be a BlockMemberSymbol, but got $selOwner (${\n                        selOwner.getClass.getName\n                      })\",\n                  )\n                val fieldidx = fieldSelect(selCls, fieldSym)\n                val objRef = ref.cast(lhsExpr, RefType(ctx.getType_!(selCls), nullable = false))\n                struct.set(fieldidx, objRef, rhsExpr)\n              case N =>\n                lastWords(\n                  s\"Expected resolved AssignField(...) expression to be a TermSymbol, but got $selSym (${\n                      selSym.getClass.getName\n                    })\",\n                )\n          case N =>\n            errExpr(\n              Ls(\n                msg\"WatBuilder::returningTerm for AssignField(...) without a resolved symbol is not implemented (field `${\n                    nme.name\n                  }`). Use `_.[_]` for index-based accesses.\" ->\n                  nme.toLoc,\n              ),\n              extraInfo = S(assign),\n            )\n\n        val rstBlk = returningTerm(rst)\n        blockInstr(\n          label = N,\n          children = Seq(assignInstr, rstBlk),\n          resultTypes = resultClauses(rstBlk),\n        )\n\n      case assign @ AssignDynField(lhs, fld, arrayIdx, rhs, rst) =>\n        val lhsExpr = result(lhs)\n        val rhsExpr = result(rhs)\n        val assignInstr =\n          if arrayIdx then\n            val tupleArrayType = this.tupleArrayType(mut = true)\n            val tupleRef = ref.cast(lhsExpr, RefType(tupleArrayType, nullable = false))\n            val idxBuilder = compileTupleIndex(\n              fld = fld,\n              loc = fld.toLoc,\n              errCtx = \"WatBuilder::returningTerm for AssignDynField(...)\",\n              errExtra = assign.toString,\n            )\n            val idxExpr = idxBuilder(tupleRef)\n            array.set(tupleArrayType, tupleRef, idxExpr, rhsExpr)\n          else\n            errExpr(\n              Ls(msg\"WatBuilder::returningTerm for AssignDynField(...) where `arrayIdx = false` is not implemented yet\" ->\n                lhs.toLoc),\n              extraInfo = S(assign),\n            )\n\n        val rstBlk = returningTerm(rst)\n        blockInstr(\n          label = N,\n          children = Seq(assignInstr, rstBlk),\n          resultTypes = resultClauses(rstBlk),\n        )\n\n      case Define(defn, rst) =>\n        def mkThis(sym: InnerSymbol): Expr = result(Value.This(sym))\n        defn match\n          case ValDefn(tsym, sym, p) =>\n            // * Currently we allow `val` outside of object/module scopes,\n            // * in which case it has no owner and is just a glorified local variable rather than a field\n            tsym.owner match\n              case N =>\n                val symExpr = getVar(sym, sym.toLoc)\n                val defineExpr = symExpr.mnemonicPrefix match\n                  case S(\"global\") =>\n                    global.set(symExpr.instrargs(0).asInstanceOf[GlobalIdx], result(p))\n                  case S(\"local\") =>\n                    local.set(symExpr.instrargs(0).asInstanceOf[LocalIdx], result(p))\n                  case _ =>\n                    lastWords(\n                      s\"Expected `global.*` or `local.*` when compiling definition for `$sym`, but got ${symExpr.mnemonic}\",\n                    )\n                val rstWat = returningTerm(rst)\n                blockInstr(\n                  label = N,\n                  children = Seq(\n                    defineExpr,\n                    rstWat,\n                  ),\n                  resultTypes = rstWat.resultTypes.map(r => Result(r.asValType_!)),\n                )\n              case S(owner) =>\n                val ownerBlkMem = owner.asBlkMember.get\n                val rstWat = returningTerm(rst)\n                blockInstr(\n                  label = N,\n                  children = Seq(\n                    struct.set(\n                      index = fieldSelect(ownerBlkMem, tsym),\n                      ref = mkThis(owner),\n                      value = result(p),\n                    ),\n                    rstWat,\n                  ),\n                  resultTypes = resultClauses(rstWat),\n                )\n\n          case defn: (FunDefn | ClsLikeDefn) =>\n            val res = boundary:\n              defn match\n                case FunDefn(params = Nil) =>\n                  lastWords(\"cannot generate function with no parameter list\")\n                case fd @ FunDefn(own, sym, dSym, ps :: pss, bod) =>\n                  if own.nonEmpty then\n                    break(errExpr(\n                      Ls(\n                        msg\"WatBuilder::returningTerm for Define(...) with `owner.nonEmpty` not implemented yet\" ->\n                          defn.sym.toLoc,\n                      ),\n                      extraInfo = S(defn.showAsTree),\n                    ))\n\n                  val result = pss.foldRight(bod):\n                    case (ps, block) =>\n                      Return(Lambda(ps, block), false)\n                  val (bodyWat, fnCtx) = setupFunction(N, ps, result)\n                  if sym.nameIsMeaningful then\n                    val funcTy = ctx.addType(\n                      TypeInfo(\n                        sym = TempSymbol(N, sym.nme),\n                        FunctionType(\n                          params = fnCtx.params.map(p => WasmParam(p._2, RefType.anyref)),\n                          results = Seq.fill(bodyWat.resultTypes.length)(Result(RefType.anyref)),\n                        ),\n                        objectTag = N,\n                      ),\n                    )\n\n                    val funcInfo = FuncInfo(\n                      sym,\n                      typeUse = TypeUse(funcTy),\n                      params = ps.params.zip(fnCtx.params.map(_._2)).map((p, idx) => p.sym -> idx),\n                      resultTypes = Seq.fill(bodyWat.resultTypes.length)(Result(RefType.anyref)),\n                      locals = fnCtx.locals,\n                      body = bodyWat,\n                      exportName = sym.optionIf(_.nameIsMeaningful).map(_.nme),\n                    )\n                    ctx.addFunc(funcInfo)\n                    if summon[SessionExportCtx].shouldExport(defn.sym) then\n                      summon[SessionExportCtx].emit(SessionFunc(\n                        sym = defn.sym,\n                        wrapId = funcInfo.wrapId,\n                        moduleName = SessionBinding.ReplModuleName,\n                        exportName = sym.nme,\n                        funcType = FunctionType(funcInfo.getSignatureType),\n                      ))\n\n                    nop\n                  else\n                    errExpr(\n                      Ls(\n                        msg\"WatBuilder::returningTerm for FunDefn(...) where `!sym.nameIsMeaningful` not implemented yet\" ->\n                          defn.sym.toLoc,\n                      ),\n                      extraInfo = S(defn.showAsTree),\n                    )\n                  end if\n                case clsLikeDefn: ClsLikeDefn =>\n                  // Guard against unsupported features\n                  def errUnimplExpr(cond: Str): Nothing = break(errExpr(\n                    Ls(\n                      msg\"WatBuilder::returningTerm for ClsLikeDefn(...) where `$cond` not implemented yet\" ->\n                        clsLikeDefn.sym.toLoc,\n                    ),\n                    extraInfo = S(defn.showAsTree),\n                  ))\n                  val isSingletonObj = clsLikeDefn.k is syntax.Obj\n                  if clsLikeDefn.owner.nonEmpty then\n                    break(errUnimplExpr(\"owner.nonEmpty\"))\n                  if !(clsLikeDefn.k is syntax.Cls) && !isSingletonObj then\n                    break(errUnimplExpr(\"unsupported ClsLikeDefn kind\"))\n                  if isSingletonObj && clsLikeDefn.paramsOpt.nonEmpty then\n                    break(errUnimplExpr(\"paramsOpt.nonEmpty for object\"))\n                  if clsLikeDefn.auxParams.nonEmpty then\n                    break(errUnimplExpr(\"auxParams.nonEmpty\"))\n                  if isSingletonObj && clsLikeDefn.parentPath.nonEmpty then\n                    break(errUnimplExpr(\"parentPath.nonEmpty for object\"))\n                  if isSingletonObj && clsLikeDefn.methods.nonEmpty then\n                    break(errUnimplExpr(\"methods.nonEmpty for object\"))\n                  if clsLikeDefn.companion.isDefined then\n                    break(errUnimplExpr(\"companion.isDefined\"))\n\n                  val ctorAuxParams = clsLikeDefn.auxParams.map: ps =>\n                    ps.params.map: p =>\n                      p -> errUnimplExpr(\"auxParams.nonEmpty\")\n\n                  // Use the symbolic type reference (e.g. `$Foo`) in emitted WAT for readability.\n                  // Numeric indices are only needed for `$tag` values.\n                  val typeref = ctx.getType_!(clsLikeDefn.sym)\n                  val typeinfo = ctx.getTypeInfo_!(typeref)\n\n                  val (initWat, initFnCtx) = setupInitLocals(clsLikeDefn)\n\n                  // * If there are no ctor params, pop one param list off the aux params\n                  val newCtorAuxParams = clsLikeDefn.paramsOpt match\n                    case None => ctorAuxParams match\n                        case head :: next => next\n                        case Nil => ctorAuxParams\n                    case Some(_) => ctorAuxParams\n\n                  val tagValue = typeinfo.objectTag getOrElse:\n                    lastWords(s\"Expected class ${clsLikeDefn.sym} to have an object tag\")\n\n                  val initFuncRef = initFuncSym(clsLikeDefn.sym)\n                  val (ctorCode, ctorFnCtx) = genFuncBody(clsLikeDefn.paramsOpt.toList, thisSym = N):\n                    val thisVar = bindCtorThis(clsLikeDefn.isym)\n                    val initCall = call(\n                      funcidx = ctx.getFunc_!(initFuncRef),\n                      operands = local.get(thisVar, RefType.anyref) +:\n                        funcCtx.params.map((_, nme) => getLocalAnyref(LocalIdx(nme))),\n                      returnTypes = Seq(Result(RefType.anyref)),\n                    )\n                    blockInstr(\n                      label = N,\n                      Seq(\n                        local.set(thisVar, struct.new_default(typeref)),\n                        struct.set(\n                          FieldIdx(SymIdx(typeinfo.compType.asInstanceOf[StructType].fields(0)._2.id)),\n                          ref.cast(\n                            local.get(thisVar, RefType.anyref),\n                            RefType(typeref, nullable = false),\n                          ),\n                          i32.const(tagValue),\n                        ),\n                        drop(initCall),\n                        `return`(S(local.get(thisVar, RefType(typeref, nullable = false)))),\n                      ),\n                      resultTypes = Seq(Result(RefType.anyref)),\n                    )\n\n                  val ctorAux =\n                    if newCtorAuxParams.isEmpty then ctorCode\n                    else break(errUnimplExpr(\"newCtorAuxParams.nonEmpty\"))\n\n                  val predeclaredInit = ctx.getFuncInfo_!(initFuncRef)\n                  ctx.addFunc(FuncInfo(\n                    sym = initFuncRef,\n                    wrapId = S(clsLikeDefn.sym.nme) -> N,\n                    typeUse = predeclaredInit.typeUse,\n                    params = initFnCtx.params,\n                    resultTypes = initWat.resultTypes.map(ty => Result(ty.asValType_!)),\n                    locals = initFnCtx.locals,\n                    body = initWat,\n                    exportName = predeclaredInit.exportName,\n                  ))\n\n                  val predeclaredCtor = ctx.getFuncInfo_!(clsLikeDefn.sym)\n                  val ctorFuncInfo = FuncInfo(\n                    sym = clsLikeDefn.sym,\n                    wrapId = S(clsLikeDefn.sym.nme) -> N,\n                    typeUse = predeclaredCtor.typeUse,\n                    params = ctorFnCtx.params,\n                    resultTypes = ctorAux.resultTypes.map(ty => Result(ty.asValType_!)),\n                    locals = ctorFnCtx.locals,\n                    body = ctorAux,\n                    exportName = predeclaredCtor.exportName,\n                  )\n                  ctx.addFunc(ctorFuncInfo)\n\n                  def overwriteMethod(\n                      sym: BlockMemberSymbol,\n                      ps: ParamList,\n                      bod: Block,\n                  ): Unit =\n                    val (bodyWat, fnCtx) = setupFunction(S(clsLikeDefn.isym), ps, bod)\n                    val predeclaredMethod = ctx.getFuncInfo_!(sym)\n                    ctx.addFunc(FuncInfo(\n                      sym,\n                      wrapId = S(clsLikeDefn.sym.nme) -> N,\n                      typeUse = predeclaredMethod.typeUse,\n                      params = fnCtx.params,\n                      resultTypes = Seq.fill(bodyWat.resultTypes.length)(Result(RefType.anyref)),\n                      locals = fnCtx.locals,\n                      body = bodyWat,\n                      exportName = predeclaredMethod.exportName,\n                    ))\n\n                  clsLikeDefn.methods.foreach:\n                    case FunDefn(_, sym, _, Nil, bod) =>\n                      overwriteMethod(sym, PlainParamList(Nil), bod)\n                    case FunDefn(_, sym, _, ps :: Nil, bod) =>\n                      overwriteMethod(sym, ps, bod)\n                    case methodDefn =>\n                      lastWords(\n                        s\"Class method `$methodDefn` with multiple parameter lists should be rejected in predeclaration pass\",\n                      )\n                  if summon[SessionExportCtx].shouldExport(clsLikeDefn.sym) then\n                    summon[SessionExportCtx].emit(SessionClass(\n                      sym = clsLikeDefn.sym,\n                      wrapId = typeinfo.wrapId,\n                      compType = typeinfo.compType,\n                      objectTag = typeinfo.objectTag,\n                      runtimeTags = ctx.getAllRuntimeTags(clsLikeDefn.sym).getOrElse(LinkedHashSet(tagValue)),\n                      aliasSyms = clsLikeDefn.isym match\n                        case mos: ModuleOrObjectSymbol => mos :: Nil\n                        case _ => Nil,\n                    ))\n                    if !isSingletonObj && clsLikeDefn.sym.nameIsMeaningful then\n                      summon[SessionExportCtx].emit(SessionFunc(\n                        sym = clsLikeDefn.sym,\n                        wrapId = ctorFuncInfo.wrapId,\n                        moduleName = SessionBinding.ReplModuleName,\n                        exportName = clsLikeDefn.sym.nme,\n                        funcType = FunctionType(\n                          SignatureType(\n                            params = ctorFnCtx.params.map(p => WasmParam(p._2, RefType.anyref)),\n                            results = Seq(Result(RefType.anyref)),\n                          ),\n                        ),\n                      ))\n                  end if\n                  if isSingletonObj then\n                    registerSingletonInit(clsLikeDefn, typeref)\n                    if summon[SessionExportCtx].shouldExport(clsLikeDefn.sym) then\n                      ctx.getSingletonInfo(clsLikeDefn.sym).foreach: info =>\n                        val singletonOwner = clsLikeDefn.isym match\n                          case mos: ModuleOrObjectSymbol => S(mos)\n                          case _ => N\n                        summon[SessionExportCtx].emit(SessionSingleton(\n                          blockSym = clsLikeDefn.sym,\n                          wrapId = typeinfo.wrapId,\n                          objectSym = singletonOwner,\n                          moduleName = SessionBinding.ReplModuleName,\n                          exportName = info.globalName,\n                          globalTy = info.globalTy,\n                        ))\n\n                  nop\n\n                case defn =>\n                  errExpr(\n                    Ls(msg\"WatBuilder::returningTerm for Define(...) not implemented yet\" -> defn.sym.toLoc),\n                    extraInfo = S(defn.showAsTree),\n                  )\n              end match\n\n            val rstBlk = returningTerm(rst)\n            blockInstr(\n              label = N,\n              children = Seq(res, rstBlk),\n              resultTypes = resultClauses(rstBlk),\n            )\n        end match\n\n      case Return(res, true) =>\n        val resWat = result(res)\n        resWat.resultType match\n          case S(refTy: RefType) =>\n            refTy.heapType match\n              case HeapType.Func =>\n                errExpr(Ls(msg\"Returning function instances is not supported\" -> res.toLoc))\n              case typeidx: TypeIdx if ctx.getTypeInfo_!(typeidx).compType.isInstanceOf[FunctionType] =>\n                errExpr(Ls(msg\"Returning function instances is not supported\" -> res.toLoc))\n              case _ => ()\n          case _ => ()\n\n        resWat\n      case Return(res, false) =>\n        val resWat = result(res)\n        resWat.resultType match\n          case S(refTy: RefType) =>\n            refTy.heapType match\n              case HeapType.Func =>\n                errExpr(Ls(msg\"Returning function instances is not supported\" -> res.toLoc))\n              case typeidx: TypeIdx if ctx.getTypeInfo_!(typeidx).compType.isInstanceOf[FunctionType] =>\n                errExpr(Ls(msg\"Returning function instances is not supported\" -> res.toLoc))\n              case _ => ()\n          case _ => ()\n\n        `return`(S(resWat))\n\n      case Scoped(syms, body) =>\n        blockPreamble(syms)\n        returningTerm(body)\n      case Break(label) =>\n        funcCtx.lookupLabel(label) match\n          case S(target) => br(target.breakLabel)\n          case N =>\n            errExpr(\n              Ls(\n                msg\"WatBuilder::returningTerm for Break(...) to unknown label `${label.nme}`\" -> label.toLoc,\n              ),\n              extraInfo = S(t.showAsTree),\n            )\n      case Continue(label) =>\n        funcCtx.lookupLabel(label) match\n          case S(target) =>\n            target.continueLabel match\n              case S(continueLabel) => br(continueLabel)\n              case N =>\n                errExpr(\n                  Ls(\n                    msg\"WatBuilder::returningTerm for Continue(...) to non-loop label `${label.nme}`\" -> label.toLoc,\n                  ),\n                  extraInfo = S(t.showAsTree),\n                )\n          case N =>\n            errExpr(\n              Ls(\n                msg\"WatBuilder::returningTerm for Continue(...) to unknown label `${label.nme}`\" -> label.toLoc,\n              ),\n              extraInfo = S(t.showAsTree),\n            )\n      case Label(label, loop, body, rst) =>\n        val labeledRegion = funcCtx.withLabel(label, hasContinueLabel = loop):\n          case LabelTarget(breakLabel, continueLabel) =>\n            val bodyExpr = returningTerm(body)\n            val bodyStmt = asStatement(bodyExpr)\n\n            if loop then\n              blockInstr(\n                label = S(breakLabel),\n                children = Seq(\n                  loopInstr(\n                    label = continueLabel,\n                    children = Seq(bodyStmt),\n                    resultTypes = Seq.empty,\n                  ),\n                ),\n                resultTypes = Seq.empty,\n              )\n            else\n              blockInstr(\n                label = S(breakLabel),\n                children = Seq(bodyStmt),\n                resultTypes = Seq.empty,\n              )\n\n        val rstExpr = returningTerm(rst)\n        val rstResultTypes = rstExpr.resultTypes.flatMap(ty => ty.asValType.map(Result(_)))\n        blockInstr(\n          label = N,\n          children = Seq(labeledRegion, rstExpr),\n          resultTypes = rstResultTypes,\n        )\n      case Match(scrut, arms, dflt, rst) =>\n        val tailMode = rst.isInstanceOf[End]\n        val matchResLocal =\n          if tailMode then S(mkTempLocal(\"matchRes\"))\n          else N\n\n        def getScrutExpr: Expr = result(scrut)\n\n        def assignTailResult(target: LocalIdx, expr: Expr): Expr =\n          if expr.isControlTransfer then expr\n          else\n            expr.resultType match\n              case S(_) => local.set(target, expr)\n              case N => blockInstr(\n                  label = N,\n                  children = Seq(\n                    expr,\n                    local.set(target, result(Value.Ref(State.unitSymbol))),\n                  ),\n                  resultTypes = Seq.empty,\n                )\n\n        def lowerMatchBody(expr: Expr): Expr =\n          matchResLocal match\n            case S(localIdx) => assignTailResult(localIdx, expr)\n            case N => asStatement(expr)\n\n        val matchResInitExpr = matchResLocal.map: localIdx =>\n          local.set(localIdx, ref.`null`(HeapType.Any))\n\n        // Compile each match arm\n        val matchBlock = funcCtx.withLabel(LabelSymbol(N, \"match\"), hasContinueLabel = false):\n          case LabelTarget(matchLabel, _) =>\n            boundary:\n              val armExprs = arms.zipWithIndex.flatMap: (caseAndBody, armIdx) =>\n                val (cse, body) = caseAndBody\n                cse match\n                  case Case.Lit(lit) =>\n                    val testExpr: FoldedInstr = lit match\n                      case BoolLit(value) =>\n                        val scrutAsI31 = ref.cast(getScrutExpr, RefType.i31ref)\n                        val scrutValue = i31.get(scrutAsI31, signed = true)\n                        i32.eq(scrutValue, i32.const(if value then 1 else 0))\n                      case IntLit(value) =>\n                        val scrutAsI31 = ref.cast(getScrutExpr, RefType.i31ref)\n                        val scrutValue = i31.get(scrutAsI31, signed = true)\n                        i32.eq(scrutValue, withValidIntLit(value, lit.toLoc)(i32.const))\n                      case _ =>\n                        break(errExpr(Ls(msg\"Pattern matching for unit literals not implemented yet\" -> lit.toLoc)))\n\n                    val bodyExpr = returningTerm(body)\n                    val armBodyExpr = lowerMatchBody(bodyExpr)\n                    funcCtx.withLabel(LabelSymbol(N, \"arm\"), hasContinueLabel = false):\n                      case LabelTarget(armLabel, _) =>\n                        S(`if`(\n                          condition = testExpr,\n                          ifTrue = blockInstr(\n                            label = S(armLabel),\n                            children = Seq(armBodyExpr, br(matchLabel)),\n                            resultTypes = Seq.empty,\n                          ),\n                          ifFalse = N,\n                          resultTypes = Seq.empty,\n                        ))\n\n                  case Case.Cls(cls, _) =>\n                    val clsBlkMemberSym = cls.asBlkMember getOrElse:\n                      break(errExpr(\n                        Ls(msg\"Could not resolve BlockMemberSymbol for class pattern\" -> cls.toLoc),\n                        extraInfo = S(s\"ClassLikeSymbol: ${cls.toString}\"),\n                      ))\n                    val clsTypeIdx = ctx.getType_!(clsBlkMemberSym)\n                    val typeinfo = ctx.getTypeInfo_!(clsTypeIdx)\n\n                    val expectedTag = typeinfo.objectTag getOrElse:\n                      lastWords(s\"Expected class $clsBlkMemberSym to have an object tag\")\n\n                    // TODO (https://github.com/orgs/hkust-taco/projects/14/views/1?pane=issue&itemId=174476970):\n                    // replace with RTTI ancestry checks once each object carries runtime type information.\n                    val matchTags = ctx.getAllRuntimeTags(clsBlkMemberSym).getOrElse(LinkedHashSet(expectedTag))\n\n                    val scrutExpr = getScrutExpr\n                    val isStructCompatible = ref.test(scrutExpr, baseObjectRefType(nullable = true))\n\n                    val bodyExpr = returningTerm(body)\n                    val armBodyExpr = lowerMatchBody(bodyExpr)\n\n                    // Safe to cast and extract tag since ref.test passed\n                    val scrutAsObject = ref.cast(scrutExpr, baseObjectRefType(nullable = false))\n                    val scrutTag = struct.get(\n                      FieldIdx(SymIdx(typeinfo.compType.asInstanceOf[StructType].fields(0)._2.id)),\n                      scrutAsObject,\n                      I32Type,\n                    )\n                    val tagMatches = matchTags.toList match\n                      case tag :: Nil => i32.eq(scrutTag, i32.const(tag))\n                      case tag :: rest =>\n                        rest.foldLeft[Expr](i32.eq(scrutTag, i32.const(tag))): (acc, candidateTag) =>\n                          i32.or(acc, i32.eq(scrutTag, i32.const(candidateTag)))\n                      case Nil =>\n                        lastWords(s\"Expected class $clsBlkMemberSym to have at least one accepted runtime tag\")\n\n                    funcCtx.withLabel(LabelSymbol(N, \"arm\"), hasContinueLabel = false):\n                      case LabelTarget(armLabel, _) =>\n                        S(`if`(\n                          condition = isStructCompatible,\n                          ifTrue = `if`(\n                            condition = tagMatches,\n                            ifTrue = blockInstr(\n                              label = S(armLabel),\n                              children = Seq(armBodyExpr, br(matchLabel)),\n                              resultTypes = Seq.empty,\n                            ),\n                            ifFalse = N,\n                            resultTypes = Seq.empty,\n                          ),\n                          ifFalse = N,\n                          resultTypes = Seq.empty,\n                        ))\n                  case Case.Tup(len, inf) =>\n                    val arrayRefType = RefType(HeapType.Array, nullable = true)\n                    val isArrayTest = ref.test(getScrutExpr, arrayRefType)\n\n                    // Length check\n                    val scrutArray = ref.cast(getScrutExpr, arrayRefType)\n                    val arrayLength = array.len(scrutArray)\n                    val lengthTest = if inf then\n                      i32.ge_u(arrayLength, i32.const(len))\n                    else\n                      i32.eq(arrayLength, i32.const(len))\n\n                    val testExpr = i32.and(isArrayTest, lengthTest)\n                    val bodyExpr = returningTerm(body)\n                    val armBodyExpr = lowerMatchBody(bodyExpr)\n                    funcCtx.withLabel(LabelSymbol(N, \"arm\"), hasContinueLabel = false):\n                      case LabelTarget(armLabel, _) =>\n                        S(`if`(\n                          condition = testExpr,\n                          ifTrue = blockInstr(\n                            label = S(armLabel),\n                            children = Seq(armBodyExpr, br(matchLabel)),\n                            resultTypes = Seq.empty,\n                          ),\n                          ifFalse = N,\n                          resultTypes = Seq.empty,\n                        ))\n                  case _ =>\n                    break(errExpr(\n                      Ls(\n                        msg\"WatBuilder::returningTerm for Match(...) with case `${cse.toString}` not implemented yet\" ->\n                          N,\n                      ),\n                      extraInfo = S(cse.toString),\n                    ))\n                end match\n\n              val defaultExpr =\n                val rawDefaultExpr = dflt match\n                  case S(defaultBody) => returningTerm(defaultBody)\n                  case N => nop\n                lowerMatchBody(rawDefaultExpr)\n\n              // Generate the match block\n              blockInstr(\n                label = S(matchLabel),\n                children = matchResInitExpr.toSeq ++ armExprs :+ defaultExpr,\n                resultTypes = Seq.empty,\n              )\n\n        if tailMode then\n          blockInstr(\n            label = N,\n            children = Seq(\n              matchBlock,\n              local.get(matchResLocal.get, RefType.anyref),\n            ),\n            resultTypes = Seq(Result(RefType.anyref)),\n          )\n        else\n          val rstExpr = returningTerm(rst)\n          blockInstr(\n            label = N,\n            children = Seq(matchBlock, rstExpr),\n            resultTypes = rstExpr.resultTypes.flatMap(ty => ty.asValType.map(Result(_))),\n          )\n\n      // * Try/finally lowering is intentionally rejected for now: the previous implementation required `exnref` support\n      // * which can only be enabled with the `--experimental-wasm-exnref` flag.\n      // * Later, it will be implemented using intrinsic function.\n      case TryBlock(sub, _, _) =>\n        errExpr(\n          Ls(msg\"WatBuilder::returningTerm for TryBlock(...) not implemented yet\" -> N),\n          extraInfo = S(sub.showAsTree),\n        )\n\n      case Throw(res) =>\n        val excWat = result(res)\n        `throw`(exnTagIdx, Seq(excWat))\n\n      case End(_) => nop\n\n      case t =>\n        errExpr(\n          Ls(msg\"WatBuilder::returningTerm for ${t.getClass.getSimpleName} block not implemented yet\" -> N),\n          extraInfo = S(t.showAsTree),\n        )\n    end match\n  end returningTerm\n\n  def program(\n      p: Program,\n      exprt: Opt[BlockMemberSymbol],\n      wd: io.Path,\n      sessionImports: Seq[SessionBinding],\n      preservedSessionSymbols: Set[Local],\n  )(using Raise): CompiledWasmModule =\n    for imprt <- p.imports do\n      raise(\n        ErrorReport(\n          msg\"Import of symbol `${imprt._2}` not implemented yet\" -> imprt._1.toLoc :: Nil,\n          extraInfo = S(imprt),\n          source = Diagnostic.Source.Compilation,\n        ),\n      )\n    exprt.foreach: exprt =>\n      raise(\n        ErrorReport(\n          msg\"Export of symbol `${exprt.nme}` not implemented yet\" -> exprt.toLoc :: Nil,\n          extraInfo = S(exprt),\n          source = Diagnostic.Source.Compilation,\n        ),\n      )\n\n    val sessionExportCtx = SessionExportCtx(\n      symbolsToExport = preservedSessionSymbols,\n      collectedBindings = ArrayBuf.empty,\n    )\n    given SessionExportCtx = sessionExportCtx\n\n    val ctx = Ctx.empty\n    given Ctx = ctx\n\n    def systemMemMinPages: Int =\n      ctx.getMemoryImport(\n        ExternIntrinsics.SystemModule,\n        ExternIntrinsics.SystemMemoryImportName,\n      ).fold(0)(_.memType.lim.min)\n\n    def compiledModule(entryName: Str): CompiledWasmModule =\n      CompiledWasmModule(ctx.toWat, entryName, systemMemMinPages, sessionExportCtx.collectedBindings.toSeq)\n\n    // Create base Object struct with tag field that all other structs will inherit\n    ctx.addType(TypeInfo(\n      sym = baseObjectSym,\n      StructType(Seq(tagFieldSym -> Field(I32Type, mutable = true, id = \"$tag\"))),\n      objectTag = S(ctx.getFreshObjectTag() ensuring (_ == 0)),\n    ))\n\n    registerSessionImports(sessionImports)\n\n    collectSessionGlobalSymbols(\n      p.main,\n      sessionExportCtx,\n    ).toSeq.sortBy(_.uid).foreach: sym =>\n      registerSessionGlobal(sym)\n\n    boundary[CompiledWasmModule]:\n      val outerRaise = summon[Raise]\n\n      // Early registration scheme: collect supported top-level classes from main block,\n      // order by inheritance, predeclare struct types, init functions, and constructors.\n      locally:\n        given Raise = diag =>\n          outerRaise(diag)\n          diag match\n            case _: ErrorReport => break(compiledModule(\"entry\"))\n            case _ => ()\n        val ordered = sortTopLevelClasses(collectTopLevelClassDefns(p.main))\n        ordered.foreach(predeclareClassType)\n        predeclareClassTags(ordered)\n        ordered.foreach(predeclareClassInit)\n        ordered.foreach(predeclareClassConstructor)\n        ordered.foreach(predeclareClassMethods)\n\n      // Compile the entry function under a dedicated local scope so that any temp locals introduced\n      // during codegen (e.g., via `local.tee`) are declared in the entry function.\n      val (entryFnExpr, entryFnCtx) = genFuncBody(Nil, thisSym = N):\n        val rawEntryFnExpr = block(p.main)\n        normalizeEntryExpr(rawEntryFnExpr, p.main.isAbortive)\n\n      val entrySym = BlockMemberSymbol(\"entry\", Nil)\n\n      val entryFnTy = ctx.addType(TypeInfo(\n        sym = TempSymbol(N, entrySym.nme),\n        FunctionType(params = Seq.empty, results = Seq(Result(RefType.anyref))),\n        objectTag = N,\n      ))\n      val entryFnInfo = FuncInfo(\n        sym = entrySym,\n        typeUse = TypeUse(entryFnTy),\n        params = Seq.empty,\n        resultTypes = Seq(Result(RefType.anyref)),\n        locals = entryFnCtx.locals,\n        body = entryFnExpr,\n        exportName = S(entrySym.nme),\n      )\n\n      if stringLits.nonEmpty then\n        stringLits.foreach: (s, lit) =>\n          if lit.byteLen > 0 then\n            ctx.addDataSegment(DataSegment.Active(\n              offset = i32.const(lit.offset),\n              bytes = Seq(lit.watBytes),\n              memuse = N,\n              sym = TempSymbol(N, s.take(WatBuilder.StringConstantIdentMaxLength)),\n            ))\n\n      val singletonInitActions = ctx.getSingletonInitActions\n      if singletonInitActions.nonEmpty then\n        val initTy = ctx.addType(TypeInfo(\n          sym = TempSymbol(N, \"start\"),\n          FunctionType(params = Seq.empty, results = Seq.empty),\n          objectTag = N,\n        ))\n        val initBody = blockInstr(\n          label = N,\n          children = singletonInitActions.toSeq,\n          resultTypes = Seq.empty,\n        )\n        val initFn = ctx.addFunc(FuncInfo(\n          sym = TempSymbol(N, \"start\"),\n          typeUse = TypeUse(initTy),\n          params = Seq.empty,\n          resultTypes = Seq.empty,\n          locals = Seq.empty,\n          body = initBody,\n          exportName = N,\n        ))\n        ctx.setStartFunc(initFn)\n      end if\n\n      ctx.addFunc(entryFnInfo)\n\n      compiledModule(entrySym.nme)\n  end program\n\n  def blockPreamble(ss: Iterable[Symbol])(using Ctx, FunctionCtx, Raise): Unit =\n    ss.toArray.sortBy(_.uid).toSeq.filter: sym =>\n      !ctx.containsGlobal(sym) && ctx.getFunc(sym).isEmpty\n    .foreach: sym =>\n      funcCtx.addLocal(sym)\n\n  def nonNestedScoped(\n      blk: Block,\n  )(k: Block => Expr)(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr = blk match\n    case Scoped(syms, body) =>\n      blockPreamble(syms.view.filter(body.freeVars))\n      k(body)\n    case _ => k(blk)\n\n  def block(t: Block)(using Ctx, FunctionCtx, Raise, SessionExportCtx): Expr =\n    nonNestedScoped(t)(returningTerm)\n\n  def setupFunction(\n      thisParam: Opt[InnerSymbol],\n      params: ParamList,\n      body: Block,\n  )(using Ctx, Raise, SessionExportCtx): (Expr, FunctionCtx) =\n    genFuncBody(params :: Nil, thisSym = thisParam):\n      block(body)\n\nend WatBuilder\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/invalml/ConstraintSolver.scala",
    "content": "package hkmc2\npackage invalml\n\nimport scala.collection.mutable\n\nimport semantics.*\nimport Message.MessageContext\nimport mlscript.utils.*, shorthands.*\nimport utils.*\nimport utils.Scope\n\ntype Cache = mutable.HashSet[(Type, Type)]\ntype ExtrudeCache = mutable.HashMap[(Uid[InfVar], Bool), InfVar]\n\ncase class CCtx(cache: Cache, parents: Ls[(Type, Type)], origin: Term, exp: Opt[GeneralType])(using Scope):\n  def err(using Raise, InvalCtx) =\n    raise(ErrorReport(\n      msg\"Type error in ${origin.describe}${exp match\n          case S(ty) => msg\" with expected type ${ty.show}\"\n          case N => msg\"\"\n        }\" -> origin.toLoc\n      :: parents.reverse.map(p =>\n        msg\"because: cannot constrain  ${p._1.show}  <:  ${p._2.show}\" -> N\n      )\n    ))\n  def nest(sub: (Type, Type)): CCtx =\n    copy(cache = cache += sub, parents = parents match\n      case `sub` :: _ => parents\n      case _ =>  sub :: parents\n    )\nobject CCtx:\n  inline def init(origin: Term, exp: Opt[GeneralType])(using Scope) = CCtx(mutable.HashSet.empty, Nil, origin, exp)\ndef cctx(using CCtx): CCtx = summon\n\nclass ConstraintSolver(infVarState: InfVarUid.State, elState: Elaborator.State, tl: TraceLogger):\n  import tl.{trace, log}\n\n  import hkmc2.invalml.NormalForm.*\n\n  private def freshXVar(lvl: Int, sym: Symbol, hint: Str): InfVar =\n    InfVar(lvl, infVarState.nextUid, new VarState(), false)(InstSymbol(sym)(using elState), hint)\n\n  def extrude(ty: Type)(using lvl: Int, pol: Bool, cache: ExtrudeCache, invalctx: InvalCtx, cctx: CCtx, tl: TL): Type =\n  trace[Type](s\"Extruding[${printPol(pol)}] ${ty.showDbg}\", r => s\"~> ${r.showDbg}\"):\n    if ty.lvl <= lvl then ty else ty.toBasic/*TODO improve extrude directly*/ match\n    case ClassLikeType(sym, targs) =>\n      ClassLikeType(sym, targs.map {\n        case Wildcard(in, out) =>\n          Wildcard(extrude(in)(using lvl, !pol), extrude(out))\n        case t: Type => Wildcard(extrude(t)(using lvl, !pol), extrude(t))\n      })\n    case v @ InfVar(_, uid, state, true) => // * skolem\n      cache.getOrElse(uid -> pol, {\n        val nv = freshXVar(lvl, v.sym, v.hint)\n        cache += uid -> pol -> nv\n        if pol then\n          constrainImpl(state.upperBounds.foldLeft[Type](Top)(_ & _), nv)\n        else\n          constrainImpl(nv, state.lowerBounds.foldLeft[Type](Bot)(_ | _))\n        nv\n      })\n    case v @ InfVar(_, uid, _, false) =>\n      cache.getOrElse(uid -> pol, {\n        val nv = freshXVar(lvl, v.sym, v.hint)\n        cache += uid -> pol -> nv\n        if pol then\n          v.state.upperBounds ::= nv\n          nv.state.lowerBounds = v.state.lowerBounds.map(extrude) // * propagate\n        else\n          v.state.lowerBounds ::= nv\n          nv.state.upperBounds = v.state.upperBounds.map(extrude) // * propagate\n        nv\n      })\n    case ft @ FunType(args, ret, eff) =>\n      FunType(args.map(arg => extrude(arg)(using lvl, !pol)), extrude(ret), extrude(eff))\n    case ComposedType(lhs, rhs, p) =>\n      Type.mkComposedType(extrude(lhs), extrude(rhs), p)\n    case NegType(ty) => Type.mkNegType(extrude(ty)(using lvl, !pol))\n    case Top | Bot => ty\n\n  private def constrainConj(conj: Conj)(using InvalCtx, CCtx, TL): Unit = trace(s\"Constraining ${conj.showDbg}\"):\n    conj match\n      case Conj(i, u, (v, pol) :: tail) =>\n        var rest = Conj(i, u, tail)\n        if v.isSkolem then constrainConj(rest)\n        else\n          val bd = if v.lvl >= rest.lvl then rest else extrude(rest)(using v.lvl, true, mutable.HashMap.empty)\n          if pol then\n            val nc = Type.mkNegType(bd).toDnf // always cache the normal form to avoid unexpected cache misses\n            log(s\"New bound: ${v.showDbg} <: ${nc.showDbg}\")\n            cctx.nest(v.toDnf -> nc) givenIn:\n              v.state.upperBounds ::= nc\n              v.state.lowerBounds.foreach(lb => constrainImpl(lb, nc))\n          else\n            val c = bd.toDnf // always cache the normal form to avoid unexpected cache misses\n            log(s\"New bound: ${v.showDbg} :> ${c.showDbg}\")\n            cctx.nest(c -> v.toDnf) givenIn:\n              v.state.lowerBounds ::= c\n              v.state.upperBounds.foreach(ub => constrainImpl(c, ub))\n      case Conj(i, u, Nil) => (conj.i, conj.u) match\n        case (_, Union(N, Nil)) =>\n          // raise(ErrorReport(msg\"Cannot solve ${conj.i.toString()} ∧ ¬⊥\" -> N :: Nil))\n          cctx.err\n        case (Inter(S(ClassLikeType(cls1, targs1))), Union(f, ClassLikeType(cls2, targs2) :: rest)) =>\n          if cls1.uid === cls2.uid then\n            targs1.zip(targs2).foreach: (ta1, ta2) =>\n              constrainArgs(ta1, ta2)\n          else constrainConj(Conj(conj.i, Union(f, rest), Nil))\n        case (int: Inter, Union(f, _ :: rest)) => constrainConj(Conj(int, Union(f, rest), Nil))\n        case (Inter(S(FunType(args1, ret1, eff1))), Union(S(FunType(args2, ret2, eff2)), Nil)) =>\n          if args1.length =/= args2.length then\n            // raise(ErrorReport(msg\"Cannot constrain ${conj.i.toString()} <: ${conj.u.toString()}\" -> N :: Nil))\n            cctx.err\n          else\n            args1.zip(args2).foreach {\n              case (a1, a2) => constrainImpl(a2, a1)\n            }\n            constrainImpl(ret1, ret2)\n            constrainImpl(eff1, eff2)\n        case _ =>\n          // raise(ErrorReport(msg\"Cannot solve ${conj.i.toString()} <: ${conj.u.toString()}\" -> N :: Nil))\n          cctx.err\n\n  private def constrainDNF(disj: Disj)(using InvalCtx, CCtx, TL): Unit =\n    disj.conjs.foreach(constrainConj(_))\n\n  private def constrainArgs(lhs: TypeArg, rhs: TypeArg)(using InvalCtx, CCtx, TL): Unit =\n    constrainImpl(rhs.negPart, lhs.negPart)\n    constrainImpl(lhs.posPart, rhs.posPart)\n\n  private def inlineSkolemBounds(ty: Type, pol: Bool)(using cache: Set[Uid[InfVar]]): Type = ty.toBasic match\n    case v @ InfVar(_, uid, state, skolem) if skolem && !cache(uid) =>\n      given Set[Uid[InfVar]] = cache + uid\n      inlineSkolemBounds(if pol then state.upperBounds.foldLeft[Type](v)(_ & _) else state.lowerBounds.foldLeft[Type](v)(_ | _), pol)\n    case ComposedType(lhs, rhs, p) => ComposedType(inlineSkolemBounds(lhs, pol), inlineSkolemBounds(rhs, pol), p)\n    case NegType(ty) => NegType(inlineSkolemBounds(ty, !pol))\n    case _: ClassLikeType | _: FunType | _: InfVar | Top | Bot => ty\n\n  private def constrainImpl(lhs: Type, rhs: Type)(using InvalCtx, CCtx, TL): Unit =\n    val p = lhs.toDnf -> rhs.toDnf\n    if cctx.cache(p) then log(s\"Cached!\")\n    else trace(s\"CONSTRAINT ${lhs.showDbg} <: ${rhs.showDbg}\"):\n      cctx.nest(p) givenIn:\n        val ty = dnf(inlineSkolemBounds(lhs & rhs.!, true)(using Set.empty)) \n        constrainDNF(ty)\n  def constrain(lhs: Type, rhs: Type)(using InvalCtx, CCtx, TL): Unit =\n    constrainImpl(lhs, rhs)\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/invalml/InvalML.scala",
    "content": "package hkmc2\npackage invalml\n\n\nimport scala.collection.mutable.{HashSet, HashMap, ListBuffer}\nimport scala.annotation.tailrec\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport Message.MessageContext\nimport semantics.*, Term.*, ucs.FlatPattern\nimport Elaborator.Ctx\nimport syntax.*\nimport Tree.*\nimport utils.Scope\n\nobject InfVarUid extends Uid.Handler[InfVar]\n\n\nfinal case class InvalCtx(\n  raise: Raise,\n  ctx: Ctx,\n  parent: Option[InvalCtx],\n  lvl: Int,\n  env: HashMap[Uid[Symbol], GeneralType],\n  outRegAcc: Type,\n  symbolCache: HashMap[Str, TypeSymbol],\n):\n  def +=(p: Symbol -> GeneralType): Unit = env += p._1.uid -> p._2\n  def get(sym: Symbol): Option[GeneralType] = env.get(sym.uid) orElse parent.dlof(_.get(sym))(None)\n  def getCls(name: Str): TypeSymbol = symbolCache.getOrElseUpdate(name,\n    ctx.get(name).get.symbol.get.asTpe.get)\n  def &=(p: (Symbol, Type, InfVar)): Unit =\n    env += p._1.uid -> InvalCtx.varTy(p._2, p._3)(using this)\n  def nest: InvalCtx = copy(parent = Some(this), env = HashMap.empty)\n  def nextLevel: InvalCtx = copy(parent = Some(this), lvl = lvl + 1, env = HashMap.empty)\n  def nestReg(reg: InfVar): InvalCtx =\n    copy(parent = Some(this), lvl = lvl + 1, env = HashMap.empty, outRegAcc = outRegAcc | reg)\n  def nestWithOuter(outer: InfVar): InvalCtx =\n    copy(parent = Some(this), lvl = lvl + 1, env = HashMap.empty, outRegAcc = outRegAcc | outer)\n  def getRegEnv: Type = outRegAcc\n\ndef invalctx(using ctx: InvalCtx): InvalCtx = ctx\n\ngiven (using ctx: InvalCtx): Raise = ctx.raise\n\nobject InvalCtx:\n  def unitTy(using ctx: InvalCtx): Type = ClassLikeType(ctx.getCls(\"Unit\"), Nil)\n  def intTy(using ctx: InvalCtx): Type = ClassLikeType(ctx.getCls(\"Int\"), Nil)\n  def numTy(using ctx: InvalCtx): Type = ClassLikeType(ctx.getCls(\"Num\"), Nil)\n  def strTy(using ctx: InvalCtx): Type = ClassLikeType(ctx.getCls(\"Str\"), Nil)\n  def boolTy(using ctx: InvalCtx): Type = ClassLikeType(ctx.getCls(\"Bool\"), Nil)\n  def errTy(using ctx: InvalCtx): Type = ClassLikeType(ctx.getCls(\"Error\"), Nil)\n  private def codeBaseTy(ct: TypeArg, cr: TypeArg, isVar: TypeArg)(using ctx: InvalCtx): Type =\n    ClassLikeType(ctx.getCls(\"CodeBase\"), ct :: cr :: isVar :: Nil)\n  def codeTy(ct: Type, cr: Type)(using ctx: InvalCtx): Type =\n    codeBaseTy(Wildcard.out(ct), Wildcard.out(cr), Wildcard.out(Top))\n  def varTy(ct: Type, cr: Type)(using ctx: InvalCtx): Type =\n    codeBaseTy(ct, Wildcard(cr, cr), Wildcard.out(Bot))\n  def regionTy(sk: Type)(using ctx: InvalCtx): Type =\n    ClassLikeType(ctx.getCls(\"Region\"), Wildcard.out(sk) :: Nil)\n  def refTy(ct: Type, sk: Type)(using ctx: InvalCtx): Type =\n    ClassLikeType(ctx.getCls(\"Ref\"), Wildcard(ct, ct) :: Wildcard.out(sk) :: Nil)\n  def init(raise: Raise)(using Elaborator.State, Elaborator.Ctx): InvalCtx =\n    new InvalCtx(raise, summon, None, 1, HashMap.empty, Bot, HashMap.empty)\n\n  val builtinOps = Elaborator.binaryOps ++ Elaborator.unaryOps ++ Elaborator.aliasOps.keySet\nend InvalCtx\n\n\nclass InvalTyper(using elState: Elaborator.State, tl: TL)(using Ctx):\n  import tl.{trace, log}\n  \n  private val infVarState = new InfVarUid.State()\n  private val solver = new ConstraintSolver(infVarState, elState, tl)\n\n  // A temporary solution for ADT matching exhausive checking\n  // `adtCtors` maps IDs of ADTs to their constructors' IDs\n  // `adtParent` maps constructors' IDs to the ADT class symbol they belong to\n  // `typeNames` maintains all type names \n  // since we need to reject all non-variable patterns in ADT match for now\n  private val adtCtors = HashMap.empty[Uid[Symbol], ListBuffer[Uid[Symbol]]]\n  private val adtParent = HashMap.empty[Uid[Symbol], Symbol]\n  private val typeNames = HashSet.empty[Str]\n\n  private def freshSkolem(sym: Symbol, hint: Str = \"\")(using ctx: InvalCtx): InfVar =\n    InfVar(ctx.lvl, infVarState.nextUid, new VarState(), true)(sym, hint)\n  private def freshVar(sym: Symbol, hint: Str = \"\")(using ctx: InvalCtx): InfVar =\n    InfVar(ctx.lvl, infVarState.nextUid, new VarState(), false)(sym, hint)\n  private def freshWildcard(sym: Symbol)(using ctx: InvalCtx) =\n    val in = freshVar(sym, \"\")\n    val out = freshVar(sym, \"\")\n    // in.state.upperBounds ::= out // * Not needed for soundness; complicates inferred types\n    Wildcard(in, out)\n  private def freshReg(sym: Symbol)(using ctx: InvalCtx) =\n    val state = new VarState()\n    state.upperBounds = ctx.getRegEnv.! :: Nil\n    InfVar(ctx.lvl + 1, infVarState.nextUid, state, true)(sym, \"\")\n  private def freshOuter(sym: Symbol)(using ctx: InvalCtx): InfVar =\n    InfVar(ctx.lvl + 1, infVarState.nextUid, new VarState(), true)(sym, \"\")\n  private def freshEnv(sym: Symbol)(using ctx: InvalCtx): InfVar =\n    val state = new VarState()\n    state.upperBounds = ctx.getRegEnv :: Nil\n    state.lowerBounds = ctx.getRegEnv :: Nil\n    InfVar(ctx.lvl, infVarState.nextUid, state, false)(sym, \"\")\n\n  private def error(msg: Ls[Message -> Opt[Loc]], extraInfo: => Opt[Any] = N)(using InvalCtx) =\n    raise(ErrorReport(msg, extraInfo = extraInfo))\n    Bot // TODO: error type?\n\n  private def addADTCtor(pSym: Symbol, cSym: Symbol) =\n    if !adtCtors.keySet(pSym.uid) then\n      adtCtors += pSym.uid -> ListBuffer(cSym.uid)\n    else adtCtors(pSym.uid) += cSym.uid\n    adtParent += cSym.uid -> pSym\n    typeNames.add(pSym.nme)\n    typeNames.add(cSym.nme)\n\n  private def typeAndSubstType\n      (ty: Term, pol: Bool)(using map: Map[Uid[Symbol], TypeArg])(using ctx: InvalCtx, cctx: CCtx)\n      : GeneralType =\n  trace[GeneralType](s\"${ctx.lvl}. Typing type ${ty.showDbg}\", r => s\"~> ${r.showDbg}\"):\n    def mono(ty: Term, pol: Bool): Type =\n      monoOrErr(typeAndSubstType(ty, pol), ty)\n    ty match\n    case Ref(sym: LocalSymbol) =>\n      log(s\"Type lookup: ${sym.nme} ${sym.uid} ${map.keySet}\")\n      map.get(sym.uid) match\n        case Some(Wildcard(in, out)) => if pol then out else in\n        case Some(ty: Type) => ty\n        case N => ctx.get(sym) match\n          case Some(ty) => ty\n          case _ =>\n            error(msg\"Variable not found: ${sym.nme}\" -> ty.toLoc :: Nil)\n    case FunTy(Term.Tup(params), ret, eff) =>\n      PolyFunType(params.map {\n        case Fld(_, p, _) => typeAndSubstType(p, !pol)\n      }, typeAndSubstType(ret, pol), eff.map(e => typeAndSubstType(e, pol) match {\n        case t: Type => t\n        case _ => error(msg\"Effect cannot be polymorphic.\" -> ty.toLoc :: Nil)\n      }).getOrElse(Bot))\n    case f @ Term.Forall(tvs, outer, body) =>\n      val outVar = freshOuter(outer.getOrElse(new TempSymbol(S(f), \"outer\")))(using ctx)\n      val nestCtx = ctx.nestWithOuter(outVar)\n      outer.foreach(sym => nestCtx += sym -> outVar)\n      given InvalCtx = nestCtx\n      genPolyType(tvs, outVar, typeAndSubstType(body, pol))\n    case Term.TyApp(cls, targs) =>\n      // log(s\"Type application: ${cls.nme} with ${targs}\")\n      cls.symbol.flatMap(_.asTpe) match\n      case S(tpeSym) =>\n        if tpeSym.nme === \"Any\" then Top // FIXME hygiene\n        else if tpeSym.nme === \"Nothing\" then Bot // FIXME hygiene\n        else\n          val defn = tpeSym.defn.get\n          if targs.length != defn.tparams.length then\n            error(msg\"Type arguments do not match class definition\" -> ty.toLoc :: Nil)\n          val ts = defn.tparams.lazyZip(targs).map: (tp, t) =>\n            t match\n            case Term.WildcardTy(in, out) => Wildcard(\n                in.map(t => mono(t, !pol)).getOrElse(Bot),\n                out.map(t => mono(t, pol)).getOrElse(Top)\n              )\n            case _ =>\n              val ta = mono(t, pol)\n              tp.vce match\n                case S(false) => Wildcard.in(ta)\n                case S(true) => Wildcard.out(ta)\n                case N => ta\n          ClassLikeType(tpeSym, ts)\n      case N =>\n        error(msg\"Not a valid class: ${cls.describe}\" -> cls.toLoc :: Nil)\n    case Neg(rhs) =>\n      mono(rhs, !pol).!\n    case CompType(lhs, rhs, pol) =>\n      Type.mkComposedType(typeMonoType(lhs), typeMonoType(rhs), pol)\n    case UnitVal() =>\n      InvalCtx.unitTy\n    case _ =>\n      ty.symbol.flatMap(_.asTpe) match\n      case S(cls: (ClassSymbol | TypeAliasSymbol)) => typeAndSubstType(Term.TyApp(ty, Nil)(N), pol)\n      case N => error(msg\"Invalid type\" -> ty.toLoc :: Nil, S(ty)) // TODO\n\n  private def genPolyType(tvs: Ls[QuantVar], outer: InfVar, body: => GeneralType)(using ctx: InvalCtx, cctx: CCtx) =\n    val bds = tvs.map:\n      case qv @ QuantVar(sym, ub, lb) =>\n        val tv = freshVar(sym)\n        ctx += sym -> tv // TODO: a type var symbol may be better...\n        tv -> qv\n    bds.foreach:\n      case (tv, QuantVar(_, ub, lb)) =>\n        ub.foreach(ub => tv.state.upperBounds ::= typeMonoType(ub))\n        lb.foreach(lb => tv.state.lowerBounds ::= typeMonoType(lb))\n        val lbty = tv.state.lowerBounds.foldLeft[Type](Bot)(_ | _)\n        val ubty = tv.state.upperBounds.foldLeft[Type](Top)(_ & _)\n        constrain(lbty, ubty)\n    PolyType(bds.map(_._1), S(outer), body)\n\n  private def typeMonoType(ty: Term)(using ctx: InvalCtx, cctx: CCtx): Type = monoOrErr(typeType(ty), ty)\n\n  private def typeType(ty: Term)(using ctx: InvalCtx, cctx: CCtx): GeneralType =\n    typeAndSubstType(ty, pol = true)(using Map.empty)\n  \n  private def instantiate(ty: PolyType)(using ctx: InvalCtx): GeneralType =\n    ty.instantiate(infVarState.nextUid, freshEnv(new TempSymbol(N, \"env\")), ctx.lvl)(tl)\n\n  private def extrude(ty: GeneralType)(using ctx: InvalCtx, pol: Bool, cctx: CCtx): GeneralType = ty match\n    case ty: Type => solver.extrude(ty)(using ctx.lvl, pol, HashMap.empty)\n    case PolyType(tvs, outer, body) => PolyType(tvs, outer, extrude(body))\n    case pf @ PolyFunType(args, ret, eff) =>\n      PolyFunType(args.map(extrude(_)(using ctx, !pol)), extrude(ret), solver.extrude(eff)(using ctx.lvl, pol, HashMap.empty))\n\n  private def constrain(lhs: Type, rhs: Type)(using ctx: InvalCtx, cctx: CCtx): Unit =\n    solver.constrain(lhs, rhs)\n\n  private def typeCode(code: Term)(using ctx: InvalCtx, scope: Scope): (Type, Type, Type) =\n    given CCtx = CCtx.init(code, N)\n    code match\n    case UnitVal() => (Top, Bot, Bot)\n    case Lit(lit) => ((lit match // TODO dedup with other `case Lit(lit)`\n      case _: IntLit => InvalCtx.intTy\n      case _: DecLit => InvalCtx.numTy\n      case _: StrLit => InvalCtx.strTy\n      case _: UnitLit => InvalCtx.unitTy\n      case _: BoolLit => InvalCtx.boolTy), Bot, Bot)\n    case Ref(sym: Symbol) if sym.nme === \"error\" => (Bot, Bot, Bot)\n    case Ref(sym: Symbol) if InvalCtx.builtinOps(sym.nme) => ctx.get(sym) match\n      case S(ty) => (tryMkMono(ty, code), Bot, Bot)\n      case N =>\n        (error(msg\"Cannot quote operator ${sym.nme}\" -> code.toLoc :: Nil), Bot, Bot)\n    case f @ Lam(PlainParamList(params), body) =>\n      val nestCtx = ctx.nextLevel\n      given InvalCtx = nestCtx\n      val bds = params.map:\n        case Param(sym = sym) =>\n          val tv = freshVar(sym)\n          val sk = freshSkolem(sym)\n          nestCtx &= (sym, tv, sk)\n          (tv, sk)\n      val (bodyTy, ctxTy, eff) = typeCode(body)\n      val res = freshVar(new TempSymbol(S(f), \"ctx\"))(using ctx)\n      constrain(ctxTy, bds.foldLeft[Type](res)((res, bd) => res | bd._2))\n      (FunType(bds.map(_._1), bodyTy, Bot), res, eff)\n    case app @ Term.App(lhs, Term.Tup(rhs)) =>\n      val (lhsTy, lhsCtx, lhsEff) = typeCode(lhs)\n      val (rhsTy, rhsCtx, rhsEff) = rhs.foldLeft[(Ls[Type], Type, Type)]((Nil, Bot, Bot)):\n        case (res, p: Fld) =>\n          val (ty, ctx, eff) = typeCode(p.term)\n          (ty :: res._1, res._2 | ctx, res._3 | eff)\n      val resTy = freshVar(new TempSymbol(S(app), \"app\"))\n      constrain(lhsTy, FunType(rhsTy.reverse, resTy, Bot)) // TODO: right\n      (resTy, lhsCtx | rhsCtx, lhsEff | rhsEff)\n    case sel @ Term.SynthSel(Term.Ref(_: TopLevelSymbol), _) if sel.symbol.isDefined =>\n      val (opTy, eff) = typeCheck(Ref(sel.symbol.get)(sel.nme, 666, N)) // FIXME 666\n      (tryMkMono(opTy, sel), Bot, eff)\n    case unq @ Term.Unquoted(body) =>\n      val (ty, eff) = typeCheck(body)\n      val tv = freshVar(new TempSymbol(S(unq), \"cde\"))\n      val cr = freshVar(new TempSymbol(S(unq), \"ctx\"))\n      constrain(tryMkMono(ty, body), InvalCtx.codeTy(tv, cr))\n      (tv, cr, eff)\n    case blk @ Term.Blk(LetDecl(sym, _) :: DefineVar(sym2, rhs) :: Nil, body)\n    if sym2 is sym => // TODO: more than one!!\n      val (rhsTy, rhsCtx, rhsEff) = typeCode(rhs)(using ctx)\n      val nestCtx = ctx.nextLevel\n      given InvalCtx = nestCtx\n      val sk = freshSkolem(sym)\n      nestCtx &= (sym, rhsTy, sk)\n      val (bodyTy, bodyCtx, bodyEff) = typeCode(body)\n      val res = freshVar(new TempSymbol(S(blk), \"ctx\"))(using ctx)\n      constrain(bodyCtx, sk | res)\n      (bodyTy, rhsCtx | res, rhsEff | bodyEff)\n    case Term.IfLike(_, IfLikeForm.ReturningIf, SimpleSplit.IfThenElse(cond, cons, alts)) =>\n      val (condTy, condCtx, condEff) = typeCode(cond)\n      val (consTy, consCtx, consEff) = typeCode(cons)\n      val (altsTy, altsCtx, altsEff) = typeCode(alts)\n      constrain(condTy, InvalCtx.boolTy)\n      (consTy | altsTy, condCtx | consCtx | altsCtx, condEff | consEff | altsEff)\n    case _ =>\n      (error(msg\"Cannot quote ${code.toString}\" -> code.toLoc :: Nil), Bot, Bot)\n\n  private def typeFunDef(sym: Symbol, lam: Term, sig: Opt[Term])(using ctx: InvalCtx, cctx: CCtx, scope: Scope) = lam match\n    case Term.Lam(params, body) => sig match\n      case S(sig) =>\n        val sigTy = typeType(sig)(using ctx)\n        ctx += sym -> sigTy\n        ascribe(lam, sigTy)\n        ()\n      case N =>\n        val outer = freshOuter(new TempSymbol(S(lam), \"outer\"))(using ctx)\n        given InvalCtx = ctx.nestWithOuter(outer)\n        val funTyV = freshVar(sym)\n        ctx += sym -> funTyV // for recursive functions\n        val (res, _) = typeCheck(lam)\n        val funTy = tryMkMono(res, lam)\n        given CCtx = CCtx.init(lam, N)\n        constrain(funTy, funTyV)(using ctx)\n        ctx += sym -> PolyType.generalize(funTy, S(outer), ctx.lvl + 1)\n    case _ => error(msg\"Function definition shape not yet supported for ${sym.nme}\" -> lam.toLoc :: Nil)\n\n  // Check if a given matching expression is matching on an ADT.\n  // An `if` expression can only matching on one ADT and patterns can only carry variables so far.\n  // It is a temporary solution to ADTs.\n  private def isADTMatch(split: Split)(using InvalCtx) =\n    def rec(split: Split, acc: Either[Opt[Symbol], Unit]): Bool =\n      split match\n        case Split.Cons(Branch(_, pattern, _), alts) =>\n          pattern match\n            case FlatPattern.ClassLike(_, sym, _, _) if adtParent.keySet(sym.uid) =>\n              acc match\n                case L(N) => rec(alts, L(S(sym)))\n                case L(S(other)) if adtParent.get(other.uid).exists(p => p.uid == adtParent(sym.uid).uid) =>\n                  rec(alts, L(S(sym)))\n                case R(_) =>\n                  error(msg\"Mixing ADT pattern matching and general matching is not supported yet.\" -> split.toLoc :: Nil)\n                  false\n            case _ => acc match\n              case L(S(_)) =>\n                error(msg\"Mixing ADT pattern matching and general matching is not supported yet.\" -> split.toLoc :: Nil)\n                false\n              case _ => rec(alts, R(()))\n        case Split.Let(_, _, tail) => rec(tail, acc)\n        case _ => acc match\n          case L(S(sym)) => true\n          case _ => false\n    rec(split, L(N))\n\n  // Type check ADT matching, which also returns mentioned constructors for exhaustive checking.\n  // No GADT reasoning.\n  // It is a temporary solution to ADTs.\n  private def typeADTMatch\n    (split: Split, sign: Opt[GeneralType])(using ctx: InvalCtx)(using CCtx, Scope)\n    : (GeneralType, Type, Ls[Symbol], Bool) = split match\n    case Split.Cons(Branch(scrutinee, pattern, cons), alts) =>\n      val (scrutineeTy, scrutineeEff) = typeCheck(scrutinee)\n      val map = HashMap[Uid[Symbol], TypeArg]()\n      pattern match\n        case FlatPattern.ClassLike(_, sym, paramsOpt, _) =>\n          val clsTy = adtParent.get(sym.uid).flatMap(_.asCls.flatMap(_.defn)) match\n            case S(cls) =>\n              ClassLikeType(cls.sym, cls.tparams.map(_ => freshWildcard(sym)))\n            case _ =>\n              error(msg\"Cannot match ${scrutinee.toString} as ${sym.toString}\" -> split.toLoc :: Nil)\n              Bot\n          constrain(tryMkMono(scrutineeTy, scrutinee), clsTy)\n          val (paramList, tps, isGeneric, ext) = sym.asCls.flatMap(_.defn) match\n            case S(clsDef) =>\n              val isGeneric = clsDef.annotations.exists {\n                case Annot.Modifier(syntax.Keyword.data) => true\n                case _ => false\n              }\n              val ext = clsDef.ext match\n                case S(Term.New(p: Term, _, _)) => p\n                case _ => Term.Error\n              (clsDef.paramsOpt.map(p => p.params).getOrElse(Nil), clsDef.tparams, isGeneric, ext)\n            case N =>\n              error(msg\"${sym.toString} is not a valid constructor.\" -> split.toLoc :: Nil)\n              (Nil, Nil, false, Term.Error)\n          val params = paramsOpt.getOrElse(Nil)\n          if params.length != paramList.length then\n            error(msg\"${sym.toString} is not a valid constructor.\" -> split.toLoc :: Nil)\n            (Bot, Bot, sym :: Nil, false)\n          else\n            val nestCtx = if isGeneric then ctx.nextLevel else ctx.nest\n            tps.foreach {\n              case TyParam(_, _, targ) =>\n                val ty = if isGeneric then freshVar(targ)(using nestCtx) else freshWildcard(targ)(using nestCtx)\n                map += targ.uid -> ty\n            }\n            if !isGeneric then // no GADT reasoning so far\n              constrain(clsTy, tryMkMono(typeAndSubstType(ext, true)(using map.toMap), scrutinee))\n            params.iterator.zip(paramList).foreach:\n              case (p, Param(_, _, S(ty), _)) =>\n                nestCtx += p._1 -> typeAndSubstType(ty, true)(using map.toMap)\n            val (consTy, consEff) = typeAllSplits(cons, sign)(using nestCtx)\n            val (altsTy, altsEff, altCases, fallback) = typeADTMatch(alts, sign)\n            val allEff = scrutineeEff | (consEff | altsEff)\n            (sign.getOrElse(tryMkMono(consTy, cons) | tryMkMono(altsTy, alts)), allEff, sym :: altCases, fallback)\n    case Split.Let(name, term, tail) =>\n      val nestCtx = ctx.nest\n      given InvalCtx = nestCtx\n      val (termTy, termEff) = typeCheck(term)\n      nestCtx += name -> termTy\n      val (tailTy, tailEff, cases, fallback) = typeADTMatch(tail, sign)(using nestCtx)\n      (tailTy, termEff | tailEff, cases, fallback)\n    case Split.Else(alts) => sign match\n      case S(sign) =>\n        val (ty, res) = ascribe(alts, sign)\n        (ty, res, Nil, true)\n      case _ =>\n        val (ty, res) = typeCheck(alts)\n        (ty, res, Nil, true)\n    case Split.End => (Bot, Bot, Nil, false)\n\n  private def typeSplit\n      (split: Split, sign: Opt[GeneralType])(using ctx: InvalCtx)(using CCtx, Scope)\n      : (GeneralType, Type) =\n    split match\n    case Split.Cons(Branch(scrutinee, pattern, cons), alts) =>\n      val (scrutineeTy, scrutineeEff) = typeCheck(scrutinee)\n      val nestCtx1 = ctx.nest\n      val nestCtx2 = ctx.nest\n      val patTy = pattern match\n      case pat: FlatPattern.ClassLike =>\n        pat.constructor.symbol.flatMap(_.asCls) match\n          case S(sym) =>\n            val (clsTy, tv, emptyTy) = sym.defn.map(sym -> _) match\n            case S((sym, cls)) =>\n              (ClassLikeType(sym, cls.tparams.map(_ => freshWildcard(sym))), (freshVar(new TempSymbol(S(scrutinee), \"scrut\"))), ClassLikeType(sym, cls.tparams.map(_ => Wildcard.empty)))\n            case _ =>\n              error(msg\"Cannot match ${scrutinee.toString} as ${sym.toString}\" -> split.toLoc :: Nil)\n              (Bot, Bot, Bot)\n            scrutinee match // * refine\n              case Ref(sym: LocalSymbol) =>\n                nestCtx1 += sym -> clsTy\n                nestCtx2 += sym -> tv\n              case _ => () // TODO: refine all variables holding this value?\n            clsTy | (tv & Type.mkNegType(emptyTy))\n          case N =>\n            error(msg\"Not a valid class: ${pat.constructor.describe}\" -> pat.constructor.toLoc :: Nil)\n            Bot\n      case FlatPattern.Lit(lit) => lit match\n        case _: Tree.BoolLit => InvalCtx.boolTy\n        case _: Tree.IntLit => InvalCtx.intTy\n        case _: Tree.DecLit => InvalCtx.numTy\n        case _: Tree.StrLit => InvalCtx.strTy\n        case _: Tree.UnitLit => InvalCtx.unitTy\n      constrain(tryMkMono(scrutineeTy, scrutinee), patTy)\n      val (consTy, consEff) = typeSplit(cons, sign)(using nestCtx1)\n      val (altsTy, altsEff) = typeSplit(alts, sign)(using nestCtx2)\n      val allEff = scrutineeEff | (consEff | altsEff)\n      (sign.getOrElse(tryMkMono(consTy, cons) | tryMkMono(altsTy, alts)), allEff)\n    case Split.Let(name, term, tail) =>\n      val nestCtx = ctx.nest\n      given InvalCtx = nestCtx\n      val (termTy, termEff) = typeCheck(term)\n      nestCtx += name -> termTy\n      val (tailTy, tailEff) = typeSplit(tail, sign)(using nestCtx)\n      (tailTy, termEff | tailEff)\n    case Split.Else(alts) => sign match\n      case S(sign) => ascribe(alts, sign)\n      case _ => typeCheck(alts)\n    case Split.End => (Bot, Bot)\n\n  private def typeAllSplits\n    (split: Split, sign: Opt[GeneralType])(using ctx: InvalCtx)(using CCtx, Scope)\n    : (GeneralType, Type) =\n      if isADTMatch(split) then\n        val (res, eff, cases, fallback) = typeADTMatch(split, sign)\n        if !fallback then\n          cases match // A primitive exhaustive check\n            case c :: rest => // previous check already guarantees that all cases belong to the same ADT.\n              adtParent.get(c.uid).flatMap(p => adtCtors.get(p.uid)) match\n                case S(ctors) =>\n                  val dist = cases.map(_.uid).distinct\n                  if dist.length < cases.length then\n                    error(msg\"Duplicate match branches.\" -> split.toLoc :: Nil)\n                  if dist.length != ctors.length then\n                    error(msg\"Expect ${ctors.length.toString()} cases, but ${dist.length.toString()} got.\" -> split.toLoc :: Nil)\n                case N =>\n                  error(msg\"Unknown ADT constructor ${c.nme}\" -> split.toLoc :: Nil)\n            case Nil => ??? // impossible\n        (res, eff)\n      else typeSplit(split, sign)\n\n  // * Note: currently, the returned type is not used or useful, but it could be in the future\n  private def ascribe(lhs: Term, rhs: GeneralType)(using ctx: InvalCtx, scope: Scope): (GeneralType, Type) =\n  trace[(GeneralType, Type)](s\"${ctx.lvl}. Ascribing ${lhs.showDbg} : ${rhs.showDbg}\", res => s\"! ${res._2.showDbg}\"):\n    given CCtx = CCtx.init(lhs, S(rhs))\n    (lhs, rhs) match\n    case (Term.Lam(PlainParamList(params), body), ft @ PolyFunType(args, ret, eff)) => // * annoted functions\n      if params.length != args.length then\n        (error(msg\"Cannot type this ${lhs.describe} as ${rhs.show}\" -> lhs.toLoc :: Nil), Bot)\n      else\n        val nestCtx = ctx.nest\n        val argsTy = params.zip(args).map:\n          case (Param(sym = sym), ty) =>\n            nestCtx += sym -> ty\n            ty\n        given InvalCtx = nestCtx\n        val (_, effTy) = ascribe(body, ret)\n        constrain(effTy, eff)\n        (ft, Bot)\n    case (Term.Lam(params, body), ft @ FunType(args, ret, eff)) => ascribe(lhs, PolyFunType(args, ret, eff))\n    case (term, pt @ PolyType(_, outer, _)) => // * generalize\n      val nextCtx = outer match\n        case S(outer) => ctx.nestWithOuter(outer)\n        case N => ctx.nextLevel\n      given InvalCtx = nextCtx\n      constrain(ascribe(term, skolemize(pt))._2, Bot) // * never generalize terms with effects\n      (pt, Bot)\n    case (Term.IfLike(_, IfLikeForm.ReturningIf, split), ty) => // * propagate\n      typeAllSplits(split.getExpandedSplit, S(ty))\n    case (Term.Asc(term, ty), rhs) =>\n      ascribe(term, typeType(ty))\n      ascribe(term, rhs)\n    case _ =>\n      val (lhsTy, eff) = typeCheck(lhs)\n      rhs match\n        case pf: PolyFunType if pf.isPoly =>\n          (error(msg\"Cannot type non-function term ${lhs.toString} as ${rhs.show}\" -> lhs.toLoc :: Nil), Bot)\n        case _ =>\n          constrain(tryMkMono(lhsTy, lhs), monoOrErr(rhs, lhs))\n          (rhs, eff)\n\n  // TODO: t -> loc when toLoc is implemented\n  private def app(lhs: (GeneralType, Type), rhs: Ls[Elem], t: Term)\n      (using ctx: InvalCtx)(using CCtx, Scope)\n      : (GeneralType, Type) =\n    lhs match\n    case (PolyFunType(params, ret, eff), lhsEff) =>\n      // * if the function type is known, we can directly use it\n      if params.length != rhs.length\n      then (error(msg\"Incorrect number of arguments\" -> t.toLoc :: Nil), Bot)\n      else\n        var resEff: Type = lhsEff | eff\n        rhs.lazyZip(params).foreach:\n          case (f: Fld, t) =>\n            val (ty, ef) = ascribe(f.term, t)\n            resEff |= ef\n        (ret, resEff)\n    case (FunType(params, ret, eff), lhsEff) => app((PolyFunType(params, ret, eff), lhsEff), rhs, t)\n    case (ty: PolyType, eff) => app((instantiate(ty), eff), rhs, t)\n    case (funTy, lhsEff) =>\n      val (argTy, argEff) = rhs.flatMap:\n          case f: Fld =>\n            val (ty, eff) = typeCheck(f.term)\n            Left(ty) :: Right(eff) :: Nil\n        .partitionMap(x => x)\n      val effVar = freshVar(new TempSymbol(S(t), \"eff\"))\n      val retVar = freshVar(new TempSymbol(S(t), \"app\"))\n      constrain(tryMkMono(funTy, t), FunType(argTy.map((tryMkMono(_, t))), retVar, effVar))\n      (retVar, argEff.foldLeft[Type](effVar | lhsEff)((res, e) => res | e))\n\n  private def skolemize(ty: PolyType)(using ctx: InvalCtx) = ty.skolemize(infVarState.nextUid, ctx.lvl)(tl)\n\n  // TODO: implement toLoc\n  private def monoOrErr(ty: GeneralType, sc: Located)(using InvalCtx) =\n    ty.monoOr(error(msg\"General type is not allowed here.\" -> sc.toLoc :: Nil))\n\n  // * Try to instantiate the given type if it is forall quantified\n  private def tryMkMono(ty: GeneralType, sc: Located)(using InvalCtx, Scope): Type = ty match\n    case pt: PolyType => tryMkMono(instantiate(pt), sc)\n    case ft: PolyFunType =>\n      ft.monoOr(error(msg\"Expected a monomorphic type or an instantiable type here, but ${ty.show} found\" -> sc.toLoc :: Nil))\n    case ty: Type => ty\n  \n  private def createADTCtor(clsDef: ClassDef, resTy: Term)(using ctx: InvalCtx, scope: Scope, cctx: CCtx) =\n    val nestCtx = ctx.nextLevel\n    given InvalCtx = nestCtx\n    val map = HashMap[Uid[Symbol], TypeArg]()\n    val isGeneric = clsDef.annotations.exists {\n      case Annot.Modifier(syntax.Keyword.data) => true\n      case _ => false\n    }\n    val targs = clsDef.tparams.map {\n      case TyParam(_, vce, targ) =>\n        val ty = vce match\n          case S(v) =>\n            val tv = freshVar(targ)\n            if v then Wildcard.out(tv) else Wildcard.in(tv)\n          case _ => if isGeneric then freshVar(targ) else freshWildcard(targ)\n        map += targ.uid -> ty\n        ty\n    }\n    addADTCtor(clsDef.ext.flatMap(n => n.cls.symbol).getOrElse(???), clsDef.sym)\n    clsDef match\n      case clsDef: ClassDef.Plain =>\n        ctx += clsDef.bsym -> typeAndSubstType(resTy, true)(using map.toMap)\n      case clsDef: ClassDef.Parameterized =>\n        if clsDef.tparams.isEmpty then\n          ctx += clsDef.bsym -> PolyFunType(clsDef.params.params.map {\n            case Param(_, _, S(ty), _) => typeType(ty)\n            case p =>\n              error(msg\"Invalid ADT parameter.\" -> p.toLoc :: Nil)\n              Bot\n          }, typeAndSubstType(resTy, true)(using map.toMap), Bot)\n        else\n          ctx += clsDef.bsym -> PolyType(targs.flatMap {\n            case Wildcard(in: InfVar, out: InfVar) => in :: out :: Nil\n            case Wildcard(in: InfVar, _) => in :: Nil\n            case Wildcard(_, out: InfVar) => out :: Nil\n            case v: InfVar => v :: Nil\n          }, N, PolyFunType(clsDef.params.params.map {\n            case Param(_, _, S(ty), _) => typeAndSubstType(ty, true)(using map.toMap)\n            case p =>\n              error(msg\"Invalid ADT parameter.\" -> p.toLoc :: Nil)\n              Bot\n          }, typeAndSubstType(resTy, true)(using map.toMap), Bot))\n\n  private def typeCheck(t: Term)(using ctx: InvalCtx, scope: Scope): (GeneralType, Type) =\n  trace[(GeneralType, Type)](s\"${ctx.lvl}. Typing ${t.showDbg}\", res => s\": (${res._1.showDbg}, ${res._2.showDbg})\"):\n    given CCtx = CCtx.init(t, N)\n    t match\n      case Term.Annotated(Annot.Untyped, _) => (Bot, Bot)\n      case sel @ Term.SynthSel(Ref(_: TopLevelSymbol), nme)\n        if sel.symbol.isDefined =>\n        typeCheck(Ref(sel.symbol.get)(sel.nme, 666, N)) // FIXME 666\n      case Ref(sym) =>\n        ctx.get(sym) match\n          case Some(ty) => (ty, Bot)\n          case _ =>\n            // (error(msg\"Variable not found: ${sym.nme} (${sym.toString} @ ${sym.uid.toString})\"\n            (error(msg\"Variable not found: ${sym.nme}\"\n              -> t.toLoc :: Nil), Bot)\n      case Blk(stats, res) =>\n        val effBuff = ListBuffer.empty[Type]\n        def goStats(stats: Ls[Statement]): Unit = stats match\n          case Nil => ()\n          case (term: Term) :: stats =>\n            effBuff += typeCheck(term)._2\n            goStats(stats)\n          case LetDecl(sym, _) :: DefineVar(sym2, rhs) :: stats =>\n            require(sym2 is sym)\n            val (rhsTy, eff) = typeCheck(rhs)\n            effBuff += eff\n            ctx += sym -> rhsTy\n            goStats(stats)\n          case (td @ TermDefinition(k = Fun, params = ps :: Nil, sign = sig, body = S(body))) :: stats =>\n            typeFunDef(td.sym, Term.Lam(ps, body), sig)\n            goStats(stats)\n          case (td @ TermDefinition(k = Fun, params = Nil, sign = sig, body = S(body))) :: stats =>\n            typeFunDef(td.sym, body, sig)  // * may be a case expressions\n            goStats(stats)\n          case (td1 @ TermDefinition(k = Fun, sign = S(sig), body = None)) :: (td2 @ TermDefinition(k = Fun, body = S(body))) :: stats\n            if td1.sym === td2.sym => goStats(td2 :: stats) // * avoid type check signatures twice\n          case (td @ TermDefinition(k = Fun, sign = S(sig), body = None)) :: stats =>\n            ctx += td.sym -> typeType(sig)\n            goStats(stats)\n          case (clsDef: ClassDef) :: stats =>\n            typeNames.add(clsDef.sym.nme)\n            clsDef.ext match\n              case S(Term.New(ty, _, N)) => createADTCtor(clsDef, ty)\n              case _ => ()\n            goStats(stats)\n          case (modDef: ModuleOrObjectDef) :: stats =>\n            typeNames.add(modDef.sym.nme)\n            goStats(stats)\n          case Import(sym, str, pth) :: stats =>\n            goStats(stats) // TODO:\n          case stat :: _ =>\n            TODO(stat)\n        goStats(stats)\n        val (ty, eff) = typeCheck(res)\n        (ty, effBuff.foldLeft(eff)((res, e) => res | e))\n      case UnitVal() => (InvalCtx.unitTy, Bot)\n      case Lit(lit) => ((lit match\n        case _: IntLit => InvalCtx.intTy\n        case _: DecLit => InvalCtx.numTy\n        case _: StrLit => InvalCtx.strTy\n        case _: UnitLit => InvalCtx.unitTy\n        case _: BoolLit => InvalCtx.boolTy), Bot)\n      case Lam(PlainParamList(params), body) =>\n        val nestCtx = ctx.nest\n        given InvalCtx = nestCtx\n        val tvs = params.map:\n          case Param(_, sym, sign, _) =>\n            val ty = sign.map(s => typeType(s)(using nestCtx)).getOrElse(freshVar(sym))\n            nestCtx += sym -> ty\n            ty\n        val (bodyTy, eff) = typeCheck(body)\n        (PolyFunType(tvs, bodyTy, eff), Bot)\n      case Term.SelProj(term, cls, field) =>\n        val (ty, eff) = typeCheck(term)\n        cls.symbol.flatMap(_.asCls.flatMap(sym => sym.defn.map(sym -> _))) match\n          case S(clsSym -> clsDfn) =>\n            val map = HashMap[Uid[Symbol], TypeArg]()\n            val targs = clsDfn.tparams.map {\n              case TyParam(_, _, targ) =>\n                val ty = freshWildcard(targ)\n                map += targ.uid -> ty\n                ty\n            }\n            constrain(tryMkMono(ty, term), ClassLikeType(clsSym, targs))\n            require(clsDfn.paramsOpt.forall(_.restParam.isEmpty))\n            (clsDfn.paramsOpt.fold(Nil)(_.params).map {\n              case Param(_, sym, sign, _) =>\n                if sym.nme === field.name then sign else N\n            }.filter(_.isDefined)) match\n              case S(res) :: Nil => (typeAndSubstType(res, pol = true)(using map.toMap), eff)\n              case _ => (error(msg\"${field.name} is not a valid member in class ${clsSym.nme}\" -> t.toLoc :: Nil), Bot)\n          case N => \n            (error(msg\"Not a valid class: ${cls.describe}\" -> cls.toLoc :: Nil), Bot)\n      case t @ Term.App(lhs, Term.Tup(rhs)) =>\n        val (funTy, lhsEff) = typeCheck(lhs)\n        app((funTy, lhsEff), rhs, t)\n      case Term.New(cls, args, N) =>\n        cls.symbol.flatMap(_.asCls.flatMap(_.defn)) match\n        case S(clsDfn: ClassDef.Parameterized) =>\n          require(clsDfn.paramsOpt.forall(_.restParam.isEmpty))\n          val argsList = args match\n            case Nil => Nil\n            case Term.Tup(elems) :: Nil => elems.map:\n              case PlainFld(term) => term\n              case _ => ???\n            case _ => ???\n          if argsList.length != clsDfn.params.params.length then\n            (error(msg\"The number of parameters is incorrect\" -> t.toLoc :: Nil), Bot)\n          else\n            val map = HashMap[Uid[Symbol], TypeArg]()\n            val targs = clsDfn.tparams.map {\n              case TyParam(_, S(_), targ) =>\n                val ty = freshVar(targ)\n                map += targ.uid -> ty\n                ty\n              case TyParam(_, N, targ) =>\n                // val ty = freshWildcard // FIXME probably not correct\n                val ty = freshVar(targ)\n                map += targ.uid -> ty\n                ty\n            }\n            val effBuff = ListBuffer.empty[Type]\n            require(clsDfn.paramsOpt.forall(_.restParam.isEmpty))\n            argsList.iterator.zip(clsDfn.params.params).foreach {\n              case (arg, Param(sign = S(sign))) =>\n                val (ty, eff) = ascribe(arg, typeAndSubstType(sign, pol = true)(using map.toMap))\n                effBuff += eff\n              case _ => ???\n            }\n            (ClassLikeType(clsDfn.sym, targs), effBuff.foldLeft[Type](Bot)((res, e) => res | e))\n        case S(clsDfn: ClassDef.Plain) => ??? // TODO\n        case N => \n          (error(msg\"Not a valid class: ${cls.describe}\" -> cls.toLoc :: Nil), Bot)\n      case Term.Asc(term, ty) =>\n        val res = typeType(ty)(using ctx)\n        ascribe(term, res)\n      case Term.IfLike(_, IfLikeForm.ReturningIf, split) => typeAllSplits(split.getExpandedSplit, N)\n      case reg @ Term.Region(sym, body) =>\n        val sk = freshReg(sym)(using ctx)\n        val nestCtx = ctx.nestReg(sk)\n        given InvalCtx = nestCtx\n        nestCtx += sym -> InvalCtx.regionTy(sk)\n        val (res, eff) = typeCheck(body)\n        val tv = freshVar(new TempSymbol(S(reg), \"eff\"))(using ctx)\n        constrain(eff, tv | sk)\n        (extrude(res)(using ctx, true), tv)\n      case Term.RegRef(reg, value) =>\n        val (regTy, regEff) = typeCheck(reg)\n        val (valTy, valEff) = typeCheck(value)\n        val sk = freshVar(new TempSymbol(S(reg), \"reg\"))\n        constrain(tryMkMono(regTy, reg), InvalCtx.regionTy(sk))\n        (InvalCtx.refTy(tryMkMono(valTy, value), sk), sk | (regEff | valEff))\n      case Term.SetRef(lhs, rhs) =>\n        val (lhsTy, lhsEff) = typeCheck(lhs)\n        val (rhsTy, rhsEff) = typeCheck(rhs)\n        val sk = freshVar(new TempSymbol(S(lhs), \"reg\"))\n        constrain(tryMkMono(lhsTy, lhs), InvalCtx.refTy(tryMkMono(rhsTy, rhs), sk))\n        (tryMkMono(rhsTy, rhs), sk | (lhsEff | rhsEff))\n      case Term.Deref(ref) =>\n        val (refTy, refEff) = typeCheck(ref)\n        val sk = freshVar(new TempSymbol(S(ref), \"reg\"))\n        val ctnt = freshVar(new TempSymbol(S(ref), \"ref\"))\n        constrain(tryMkMono(refTy, ref), InvalCtx.refTy(ctnt, sk))\n        (ctnt, sk | refEff)\n      case Term.Quoted(body) =>\n        val nestCtx = ctx.nest\n        given InvalCtx = nestCtx\n        val (ty, ctxTy, eff) = typeCode(body)\n        (InvalCtx.codeTy(ty, ctxTy), eff)\n      case _: Term.Unquoted =>\n        (error(msg\"Unquote should nest in quasiquote\" -> t.toLoc :: Nil), Bot)\n      case Throw(e) =>\n        val (ty, eff) = typeCheck(e)\n        constrain(tryMkMono(ty, e), InvalCtx.errTy)\n        (Bot, eff)\n      case Term.Error =>\n        (Bot, Bot) // TODO: error type?\n      case _ =>\n        (error(msg\"Term shape not yet supported by InvalML: ${t.toString}\" -> t.toLoc :: Nil), Bot)\n\n  def typePurely(t: Term)(using InvalCtx, Scope): GeneralType =\n    val (ty, eff) = typeCheck(t)\n    given CCtx = CCtx.init(t, N)\n    constrain(eff, Bot)\n    ty\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/invalml/NormalForm.scala",
    "content": "package hkmc2\npackage invalml\n\nimport scala.annotation.tailrec\n\nimport semantics.*\nimport Message.MessageContext\nimport mlscript.utils.*, shorthands.*\nimport utils.*\nimport utils.Scope\n\nfinal case class Disj(conjs: Ls[Conj]) extends NormalForm with CachedBasicType:\n  def isBot: Bool = conjs.isEmpty\n  def mkBasic: BasicType =\n    BasicType.union(conjs.map(_.toBasic))\n  def toDnf(using TL): Disj = this\n  override def show(using Scope, InvalCtx, Raise): Str =\n    if conjs.isEmpty then \"⊥\"\n    else conjs.map(_.show).mkString(\" ∨ \")\n\n  override def showDbg: Str =\n    if conjs.isEmpty then \"D()\"\n    else s\"D( ${conjs.map(_.showDbg).mkString(\" || \")} )\"\nobject Disj:\n  val bot: Disj = Disj(Nil)\n  val top: Disj = Disj(Conj.empty :: Nil)\n\nsealed abstract case class Conj(i: Inter, u: Union, vars: Ls[(InfVar, Bool)])\nextends NormalForm with CachedBasicType:\n  def merge(that: Conj)(using TL): Option[Conj] =\n  tl.traceNot[Option[Conj]](s\"merge ${this.showDbg} and ${that.showDbg}\", r => s\"= ${r.map(_.showDbg)}\"):\n    val Conj(i1, u1, vars1) = this\n    val Conj(i2, u2, vars2) = that\n    i1.merge(i2) match\n      case S(i) =>\n        val u = u1.merge(u2)\n        val vars = (vars1 ++ vars2).sortWith {\n          case ((InfVar(_, uid1, _, _), _), (InfVar(_, uid2, _, _), _)) => uid1 <= uid2\n        }.foldLeft[Opt[Ls[(InfVar, Bool)]]](S(Nil))((res, p) => (res, p) match { // * None -> bot\n          case (N, _) => N\n          case (S(Nil), p) => S(p :: Nil)\n          case (S((lhs @ InfVar(v, uid1, s, k), p1) :: tail), (InfVar(_, uid2, _, _), p2)) if uid1 === uid2 =>\n            if p1 === p2 then S((InfVar(v, uid1, s, k)(lhs.sym, lhs.hint), p1) :: tail) else N\n          case (S(head :: tail), p) => S(p :: head :: tail)\n        })\n        vars match\n          case S(vars) => S(Conj(i, u, vars))\n          case _ => N\n      case N => N\n  def mkBasic: BasicType =\n    BasicType.inter(i.toBasic :: NegType(u.toBasic) :: vars.map{\n      case (tv, true) => tv\n      case (tv, false) => NegType(tv)\n    })\n  def toDnf(using TL): Disj = Disj(this :: Nil)\n  override def show(using Scope, InvalCtx, Raise): Str =\n    val s = ((i :: Nil).filterNot(_.isTop).map(_.show) :::\n      (u :: Nil).filterNot(_.isBot).map(\"¬{\"+_.show+\"}\") :::\n      vars.map:\n        case (tv, true) => tv.show\n        case (tv, false) => \"¬\" + tv.show\n    ).mkString(\" ∧ \")\n    if s.isEmpty then \"⊤\" else s\n\n  override def showDbg: Str =\n    val s = ((i :: Nil).filterNot(_.isTop).map(_.showDbg) :::\n      (u :: Nil).filterNot(_.isBot).map(\"~{\"+_.showDbg+\"}\") :::\n      vars.map:\n        case (tv, true) => tv.showDbg\n        case (tv, false) => \"~\" + tv.showDbg\n    ).mkString(\" && \")\n    if s.isEmpty then \"⊤\" else s\nobject Conj:\n  // * Conj objects cannot be created with `new` except in this file.\n  // * This is because we want to sort the vars in the apply function.\n  def apply(i: Inter, u: Union, vars: Ls[(InfVar, Bool)]) = new Conj(i, u, vars.sortWith {\n    case ((v1 @ InfVar(lv1, _, _, sk1), _), (v2 @ InfVar(lv2, _, _, sk2), _)) => !(sk1 || !sk2 && lv1 <= lv2)\n  }){}\n  lazy val empty: Conj = Conj(Inter.empty, Union.empty, Nil)\n  def mkVar(v: InfVar, pol: Bool) = Conj(Inter.empty, Union.empty, (v, pol) :: Nil)\n  def mkInter(inter: ClassLikeType | FunType) =\n    Conj(Inter(S(inter)), Union.empty, Nil)\n  def mkUnion(union: ClassLikeType | FunType) =\n    Conj(Inter.empty, union match {\n      case cls: ClassLikeType => Union(N, cls :: Nil)\n      case fun: FunType => Union(S(fun), Nil)\n    }, Nil)\n\n// * Some(ClassType) -> C[in D_i out D_i], Some(FunType) -> D_1 ->{D_2} D_3, None -> Top\nfinal case class Inter(v: Opt[ClassLikeType | FunType]) extends NormalForm:\n  def isTop: Bool = v.isEmpty\n  def merge(other: Inter): Option[Inter] = (v, other.v) match\n    case (S(ClassLikeType(cls1, targs1)), S(ClassLikeType(cls2, targs2))) if cls1.uid === cls2.uid =>\n      S(Inter(S(ClassLikeType(cls1, targs1.lazyZip(targs2).map(_ & _)))))\n    case (S(_: ClassLikeType), S(_: ClassLikeType)) => N\n    case (S(FunType(a1, r1, e1)), S(FunType(a2, r2, e2))) =>\n      S(Inter(S(FunType(a1.lazyZip(a2).map(_ | _), r1 & r2, e1 & e2))))\n    case (S(v), N) => S(Inter(S(v)))\n    case (N, v) => S(Inter(v))\n    case _ => N\n  def toBasic: BasicType = v.getOrElse(Top)\n  def toDnf(using TL): Disj = Disj(Conj(this, Union(N, Nil), Nil) :: Nil)\n  override def show(using Scope, InvalCtx, Raise): Str =\n    toBasic.show\n\n  override def showDbg: Str = toBasic.showDbg\nobject Inter:\n  lazy val empty: Inter = Inter(N)\n\n// * fun: Some(FunType) -> D_1 ->{D_2} D_3, None -> bot\nfinal case class Union(fun: Opt[FunType], cls: Ls[ClassLikeType])\nextends NormalForm with CachedBasicType:\n  def isBot = fun.isEmpty && cls.isEmpty\n  def toType = fun.getOrElse(Bot) |\n    cls.foldLeft[Type](Bot)(_ | _)\n  def merge(other: Union): Union = Union((fun, other.fun) match {\n    case (S(FunType(a1, r1, e1)), S(FunType(a2, r2, e2))) =>\n      S(FunType(a1.lazyZip(a2).map(_ & _), r1 | r2, e1 | e2))\n    case (S(f), N) => S(f)\n    case (N, S(f)) => S(f)\n    case (N, N) => N\n  }, (cls ++ other.cls).sortWith { // * Merge the same classes\n    case (cls1, cls2) => cls1.name.uid <= cls2.name.uid\n  }.foldLeft[Ls[ClassLikeType]](Nil)((res, cls) => (res, cls) match {\n    case (Nil, cls) => cls :: Nil\n    case (ClassLikeType(cls1, targs1) :: tail, ClassLikeType(cls2, targs2)) if cls1.uid === cls2.uid => \n      ClassLikeType(cls1, targs1.lazyZip(targs2).map(_ | _)) :: tail\n    case (head :: tail, cls) => cls :: head :: tail\n  }))\n  def mkBasic: BasicType =\n    BasicType.union(fun.toList ::: cls)\n  def toDnf(using TL): Disj = NormalForm.neg(this)\n  override def show(using Scope, InvalCtx, Raise): Str =\n    toType.show\n\n  override def showDbg: Str = toType.showDbg\nobject Union:\n  val empty: Union = Union(N, Nil)\n\nsealed abstract class NormalForm extends TypeExt:\n  def toBasic: BasicType\n  \n  lazy val lvl: Int = toBasic.lvl // TODO improve: avoid inefficient use of toBasic\n  \n  def subst(using map: Map[Uid[InfVar], InfVar]): ThisType =\n    toBasic.subst\n\n  def show(using Scope, InvalCtx, Raise): Str\n  def showDbg: Str\n\nobject NormalForm:\n  def inter(lhs: Disj, rhs: Disj)(using TL): Disj =\n  tl.traceNot[Disj](s\"inter ${lhs.showDbg} and ${rhs.showDbg}\", r => s\"= ${r.showDbg}\"):\n    if lhs.isBot || rhs.isBot then Disj.bot\n    else Disj(lhs.conjs.flatMap(lhs => rhs.conjs.flatMap(rhs => lhs.merge(rhs) match {\n      case S(conj) => conj :: Nil\n      case N => Nil\n    })))\n\n  def union(lhs: Disj, rhs: Disj): Disj = Disj(lhs.conjs ++ rhs.conjs)\n\n  def neg(ty: Type)(using TL): Disj =\n  tl.traceNot[Disj](s\"~DNF ${ty.showDbg} ${ty.getClass} ${ty.toBasic.showDbg}\", r => s\"= ${r.showDbg}\"):\n    ty match\n    case u: Union => Disj(Conj(Inter(N), u, Nil) :: Nil)\n    case _ => ty.toBasic match\n    case Top => Disj.bot\n    case Bot => Disj.top\n    case v: InfVar => Disj(Conj.mkVar(v, false) :: Nil)\n    case ct: ClassLikeType => Disj(Conj.mkUnion(ct) :: Nil)\n    case ft: FunType => Disj(Conj.mkUnion(ft) :: Nil)\n    case ComposedType(lhs, rhs, pol) =>\n      if pol then inter(neg(lhs), neg(rhs)) else union(neg(lhs), neg(rhs))\n    case NegType(ty) => dnf(ty)\n\n  def dnf(ty: Type)(using TL): Disj =\n  tl.traceNot[Disj](s\"DNF ${ty.showDbg} ${ty.getClass}\", r => s\"= ${r.showDbg}\"):\n    ty match\n    case d: Disj => d\n    case c: Conj => Disj(c :: Nil)\n    case i: Inter => Disj(Conj(i, Union(N, Nil), Nil) :: Nil)\n    case _ => ty.toBasic match\n    case Top => Disj.top\n    case Bot => Disj.bot\n    case v: InfVar => Disj(Conj.mkVar(v, true) :: Nil)\n    case ct: ClassLikeType => Disj(Conj.mkInter(ct.toNorm) :: Nil)\n    case ft: FunType => Disj(Conj.mkInter(ft.toNorm) :: Nil)\n    case ComposedType(lhs, rhs, pol) =>\n      if pol then union(dnf(lhs), dnf(rhs)) else inter(dnf(lhs), dnf(rhs))\n    case NegType(ty) => neg(ty)\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/invalml/PrettyPrinter.scala",
    "content": "package hkmc2\npackage invalml\nimport scala.collection.mutable.{Set => MutSet, ListBuffer}\nimport utils.Scope\n\nclass PrettyPrinter(output: String => Unit)(using Scope, InvalCtx):\n  def print(ty: GeneralType)(using Raise): Unit =\n    ty.show match\n    case \"()\" =>\n    case tyStr =>\n      output(s\"Type: ${tyStr}\")\n    val bounds = PrettyPrinter.collectBounds(ty).distinct\n    if !bounds.isEmpty then\n      output(\"Where:\")\n      bounds.foreach {\n        case (lhs, rhs) => output(s\"  ${lhs.show} <: ${rhs.show}\")\n      }\n\nobject PrettyPrinter:\n  def apply(output: String => Unit)(using Scope, InvalCtx): PrettyPrinter = new PrettyPrinter(output)\n\n  type Bound = (Type, Type) // * Type <: Type\n\n  private def collectBounds(ty: GeneralType): List[Bound] =\n    val res = ListBuffer[Bound]()\n    val cache = MutSet[Uid[InfVar]]()\n    object CollectBounds extends TypeTraverser:\n      override def apply(pol: Boolean)(ty: GeneralType): Unit = ty match\n        case v @ InfVar(_, uid, state, _) =>\n          if cache.add(uid) then\n            res ++= state.lowerBounds.map: bd =>\n              apply(true)(bd)\n              (bd, v)\n            res ++= state.upperBounds.map: bd =>\n              apply(false)(bd)\n              (v, bd)\n            super.apply(pol)(ty)\n        case _ => super.apply(pol)(ty)\n    CollectBounds(true)(ty)\n    res.toList\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/invalml/TypeSimplifier.scala",
    "content": "package hkmc2.invalml\n\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet, LinkedHashMap, LinkedHashSet}\nimport scala.collection.immutable.{SortedMap, SortedSet}\nimport scala.util.chaining._\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport Type.*\n\nfinal def printPol(pol: Bool): Str = pol match {\n    case true => \"+\"\n    case false => \"-\"\n  }\n\nclass TypeSimplifier(tl: TraceLogger):\n  import tl.{trace, log}\n  \n  def apply(pol: Bool, lvl: Int)(ty: GeneralType): GeneralType =\n    ty |> simplifyStructure(pol, lvl) |> simplifyBounds(pol, lvl) |> simplifyForall\n  \n  def simplifyStructure(pol: Bool, lvl: Int)(ty: GeneralType): GeneralType =\n    val done = MutSet.empty[InfVar]\n    def goTV(tv: InfVar): InfVar =\n      if done.add(tv) then\n        tv.state.lowerBounds = tv.state.lowerBounds.map(goType)\n        tv.state.upperBounds = tv.state.upperBounds.map(goType)\n      tv\n    def goType(ty: Type): Type =\n    trace[Type](s\"simplifyStructure(${ty.showDbg})\", r => s\"= ${r.showDbg}\"):\n      ty match\n      case tv: InfVar => goTV(tv)\n      case _ =>\n        ty.map(goType).simp\n    def go(ty: GeneralType): GeneralType = ty match\n      case ty: Type => goType(ty)\n      case pt: PolyType =>\n        pt.tvs.foreach(goTV)\n        pt.map(go)\n      case pf: PolyFunType => pf.map(go)\n    go(ty)\n  \n  def simplifyBounds(pol: Bool, lvl: Int)(ty: GeneralType): GeneralType =\n    \n    type IV = InfVar\n    \n    object Analysis extends TypeTraverser:\n      val posVars: MutSet[IV] = MutSet.empty\n      val negVars: MutSet[IV] = MutSet.empty\n      val recVars: MutSet[IV] = MutSet.empty\n      \n      val occsNum: MutMap[IV, Int] = MutMap.empty[IV, Int]\n      \n      var curPath: Ls[IV] = Nil\n      var pastPathsSet: MutSet[IV] = MutSet.empty\n\n      val outerPol: MutMap[IV, Bool] = MutMap.empty[IV, Bool] // outer polarity before entering next level\n      \n      val varSubst: MutMap[IV, IV] = MutMap.empty\n      \n      val traversedTVs: MutSet[IV] = MutSet.empty\n      \n      def getRepr(tv: IV): IV = varSubst.get(tv) match {\n        case S(tv2) =>\n          varSubst.get(tv2) match {\n            case S(tv3) =>\n              varSubst += tv -> tv3\n              // varSubst += tv2 -> tv3\n              getRepr(tv3)\n            case N => tv2\n          }\n        case N => tv\n      }\n      \n      override def apply(pol: Bool)(ty: GeneralType): Unit =\n        trace(s\"Analyse[${printPol(pol)}] ${ty.showDbg}  [${curPath.reverseIterator.mkString(\" ~> \")}]\"):\n          ty match\n            case ty if ty.lvl <= lvl =>\n              log(s\"Level is < $lvl\")\n            case tv: IV if { occsNum(tv) = occsNum.getOrElse(tv, 0) + 1; false } =>\n            case tv: IV =>\n              if varSubst.contains(tv) then return log(s\"Already subst'd\") // * If the IV was set to be substituted, it means it's been found recursive and we don't need to traverse it again\n              var continue = true\n              // if (!traversedTVs.contains(tv)) {\n              if curPath.exists(_ is tv) then // TODO opt\n                traversedTVs += tv\n                val recPrefix = curPath.takeWhile(_ isnt tv)\n                log(s\"UNIFYING ${tv.showDbg} with ${recPrefix.mkString(\", \")}\")\n                recPrefix.foreach: tv2 =>\n                  if tv2 isnt tv then\n                    traversedTVs += tv2\n                    var tvRepr = getRepr(tv2)\n                    assert(traversedTVs(tvRepr))\n                    if tvRepr isnt tv then\n                      // assert(!varSubst.contains(tvRepr))\n                      if tv.lvl === tvRepr.lvl /* && tvRepr.nameHint.isEmpty */ && !varSubst.contains(tvRepr) then {\n                        varSubst += tvRepr -> tv\n                      }\n                      else if tv.lvl > tvRepr.lvl then varSubst += tv -> tvRepr\n                      else if tvRepr.lvl > lvl && !varSubst.contains(tvRepr) then varSubst += tvRepr -> tv\n                continue = false\n              // TODO else??\n              if traversedTVs.contains(tv) then log(s\"Now already traversed ${tv.showDbg}\")\n              else if pastPathsSet.contains(tv) then\n                log(s\"REC ${tv.showDbg}\")\n                recVars += tv\n                continue = false\n              if continue then\n                // log(s\">>> $curPath\")\n                val oldPath = curPath\n                curPath ::= tv\n                \n                // * If tv is forall-qualified in a negative position, we need to **flip** the polarity\n                // * e.g., ([A] -> A -> Int) -> ([A] -> A -> Int)\n                // * Both `[A] -> A -> Int` should be simplified to the same type\n                // * The first `[A] -> A -> Int` is in a negative position\n                // * but the argument type `A` should be treated as negative instead of positive\n                if !outerPol.get(tv).getOrElse(true) then\n                  if !pol\n                  then posVars += tv\n                  else negVars += tv\n                else\n                  if pol\n                  then posVars += tv\n                  else negVars += tv\n                \n                // log(s\">>>> $curPath\")\n                // traversingTVs += tv\n                // traversedTVs += tv\n                super.apply(pol)(ty)\n                // traversingTVs -= tv\n                curPath = oldPath\n            case pt @ PolyType(tvs, outer, _) => // Avoid simplify outer variables to Top unexpectedly\n              outer.foreach(outer => {\n                posVars += outer\n                negVars += outer\n              })\n              val oldPath = curPath\n              pastPathsSet ++= oldPath\n              curPath = Nil\n              outerPol ++= (tvs.map(v => v -> pol))\n              super.apply(pol)(pt)\n              outerPol --= tvs\n              curPath = oldPath\n              pastPathsSet --= oldPath\n              ()\n            case _ =>\n              val oldPath = curPath\n              pastPathsSet ++= oldPath\n              curPath = Nil\n              super.apply(pol)(ty)\n              curPath = oldPath\n              pastPathsSet --= oldPath\n              ()\n    \n    trace(s\"Simplifying type ${ty.showDbg}\"):\n      Analysis(pol)(ty)\n    \n    log(\"Unif-pre: \" + Analysis.varSubst)\n    Analysis.varSubst.valuesIterator.foreach { Analysis.getRepr(_) }\n    // log(\"Unif-pst: \" + Analysis.varSubst)\n    \n    log(\"Occ#: \" + Analysis.occsNum.toSortedMap)\n    log(\"Pos: \" + Analysis.posVars.toSortedSet)\n    log(\"Neg: \" + Analysis.negVars.toSortedSet)\n    log(\"Rec: \" + Analysis.recVars.toSortedSet)\n    log(\"Unif: \" + Analysis.varSubst.toSortedMap)\n    \n    val cache: MutMap[IV, Type] = MutMap.empty\n    val traversed: MutSet[IV] = MutSet.empty\n    val transformed: MutMap[IV, Type] = MutMap.empty\n    \n    def subst(ty: GeneralType): GeneralType = trace[GeneralType](s\"subst(${ty.showDbg})\", r => s\"= ${r.showDbg}\"):\n      ty match\n        case ty if ty.lvl <= lvl => ty // TODO NOPE\n        case _tv: IV =>\n          val tv = Analysis.getRepr(_tv)\n          log(s\"Repr: ${tv.showDbg}\")\n          transformed.getOrElseUpdate(tv, {\n            if Analysis.recVars.contains(tv) then\n              log(s\"It's recursive!\")\n              transformed += tv -> tv\n            else transformed += tv ->\n              // TypeBounds(TopType, BotType)(noProv) // TODO improve? creates lots of junk...\n              Top // FIXME arbitrary\n            // TODO rm self-cycles\n            val newLBs = tv.state.lowerBounds.map(subst(_).monoOr(???))\n            val newUBs = tv.state.upperBounds.map(subst(_).monoOr(???))\n            tv.state.lowerBounds = newLBs\n            tv.state.upperBounds = newUBs\n            val isPos = Analysis.posVars.contains(tv)\n            val isNeg = Analysis.negVars.contains(tv)\n            // if (isPos && !isNeg && (Analysis.occsNum(tv) === 1 && {newLBs match { case (tv: IV) :: Nil => true; case _ => false }} || newLBs.forall(_.isSmall))) {\n            if isPos && !isNeg && ({newLBs match { case (tv: IV) :: Nil => true; case _ => false }} || newLBs.forall(_ => true)) then {\n            // if (isPos && !isNeg && ({newLBs match { case (tv: IV) :: Nil => true; case _ => false }})) {\n              newLBs.foldLeft(Bot: Type)(_ | _)\n            } else\n            // if (isNeg && !isPos && (Analysis.occsNum(tv) === 1 && {newUBs match { case (tv: IV) :: Nil => true; case _ => false }} || newUBs.forall(_.isSmall))) {\n            if isNeg && !isPos && ({newUBs match { case (tv: IV) :: Nil => true; case _ => false }} || newUBs.forall(_ => true)) then\n            // if (isNeg && !isPos && ({newUBs match { case (tv: IV) :: Nil => true; case _ => false }})) {\n              newUBs.foldLeft(Top: Type)(_ & _)\n            else\n              // tv.lowerBounds = newLBs\n              // tv.upperBounds = newUBs\n              tv\n          })\n        case ty: Type => ty.map(subst(_).monoOr(???))\n        case pt: PolyType => pt.map(subst)\n        case pf: PolyFunType => pf.map(subst)\n    \n    subst(ty)\n\n  def simplifyForall(ty: GeneralType): GeneralType = ty match\n    case PolyType(tvs, outer, body) =>\n      val newBody = simplifyForall(body)\n      val visited = PolyType.collectTVs(newBody)\n      val newTvs = tvs.filter(visited)\n      val newOuter = outer.filter(visited)\n      if newTvs.isEmpty && newOuter.isEmpty then newBody\n      else PolyType(newTvs, newOuter, newBody)\n    case PolyFunType(args, ret, eff) =>\n      PolyFunType(args.map(arg => simplifyForall(arg)), simplifyForall(ret), eff)\n    case _ => ty\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/invalml/TypeTraverser.scala",
    "content": "package hkmc2.invalml\n\nimport mlscript.utils.*, shorthands.*\n\nimport Type.*\n\nclass TypeTraverser:\n  def apply(pol: Bool)(ty: GeneralType): Unit = ty match\n    case Top | Bot =>\n    case NegType(ty) => apply(!pol)(ty)\n    case FunType(args, ret, eff) =>\n      args.foreach(apply(!pol))\n      apply(pol)(ret)\n      apply(pol)(eff)\n    case ClassLikeType(name, targs) =>\n      targs.foreach:\n        case Wildcard(in, out) =>\n          apply(!pol)(in)\n          apply(pol)(out)\n        case ty: Type =>\n          apply(pol)(ty)\n          apply(!pol)(ty)\n    case InfVar(vlvl, uid, state, _) =>\n      if pol then state.lowerBounds.foreach(apply(true))\n      else state.upperBounds.foreach(apply(false))\n    case ComposedType(lhs, rhs, _) =>\n      apply(pol)(lhs)\n      apply(pol)(rhs)\n    case PolyType(tv, outer, body) =>\n      apply(pol)(body)\n    case PolyFunType(args, ret, eff) =>\n      args.foreach(apply(!pol))\n      apply(pol)(ret)\n      apply(pol)(eff)\n    case ty: Type => apply(pol)(ty.toBasic) // TODO improve impl for all ctors\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/invalml/types.scala",
    "content": "package hkmc2\npackage invalml\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.*\nimport semantics.*, semantics.Term.*\nimport utils.*\nimport scala.collection.mutable.{Set => MutSet}\nimport utils.Scope, Scope.scope\nimport Elaborator.State\n\n// * General types include mono types (i.e., Type), forall quantified type, and poly function types\nsealed abstract class GeneralType:\n  // * Is this type polymorphic\n  lazy val isPoly: Bool\n  // * Polymorphic level\n  def lvl: Int\n  // * Return itself if it is actually monomorphic.\n  // * Otherwise, evaluate fallback\n  def monoOr(fallback: => Type): Type\n\n  // * The map function should not change the shape!\n  protected type ThisType <: GeneralType\n  def map(f: ThisType => ThisType): ThisType\n  def subst(using map: Map[Uid[InfVar], InfVar]): ThisType\n  def show(using Scope, InvalCtx, Raise): Str\n  def showDbg: Str\n\n// * Types that can be used as class type arguments\nsealed trait TypeArg:\n  def lvl: Int\n  def mapArg(f: Type => Type): TypeArg\n  def show(using Scope, InvalCtx, Raise): Str\n  def showDbg: Str\n  def & (that: TypeArg): TypeArg = (this, that) match\n    case (Wildcard(in1, out1), Wildcard(in2, out2)) => Wildcard(in1 | in2, out1 & out2)\n    case (ty: Type, Wildcard(in2, out2)) => Wildcard(ty | in2, ty & out2)\n    case (Wildcard(in1, out1), ty: Type) => Wildcard(in1 | ty, out1 & ty)\n    case (ty1: Type, ty2: Type) => ty1 & ty2\n  def | (that: TypeArg): TypeArg = (this, that) match\n    case (Wildcard(in1, out1), Wildcard(in2, out2)) => Wildcard(in1 & in2, out1 | out2)\n    case (ty: Type, Wildcard(in2, out2)) => Wildcard(ty & in2, ty | out2)\n    case (Wildcard(in1, out1), ty: Type) => Wildcard(in1 & ty, out1 | ty)\n    case (ty1: Type, ty2: Type) => ty1 | ty2\n  def posPart: Type = this match\n    case Wildcard(_, out) => out\n    case ty: Type => ty\n  def negPart: Type = this match\n    case Wildcard(in, _) => in\n    case ty: Type => ty\n\ncase class Wildcard(in: Type, out: Type) extends TypeArg {\n  def mapArg(f: Type => Type): Wildcard = Wildcard(f(in), f(out))\n\n  override def show(using Scope, InvalCtx, Raise): Str = in match\n    case `out` => in.show\n    case Bot =>\n      out match\n        case Top => \"?\"\n        case _ => s\"out ${out.show}\"\n    case _ =>\n      out match\n        case Top => s\"in ${in.show}\"\n        case _ => s\"in ${in.show} out ${out.show}\"\n\n  override def showDbg: Str = s\"in ${in.showDbg} out ${out.showDbg}\"\n  \n  override lazy val lvl: Int = in.lvl.max(out.lvl)\n}\n\nobject Wildcard:\n  def in(ty: Type): Wildcard = Wildcard(ty, Top)\n  def out(ty: Type): Wildcard = Wildcard(Bot, ty)\n  def empty: Wildcard = Wildcard(Bot, Top)\n\ntrait CachedBasicType extends Type:\n  override lazy val toBasic: BasicType = mkBasic\n  def mkBasic: BasicType\n\nabstract class TypeExt extends Type:\n  override def hashCode: Int =\n    toBasic.hashCode\n  \nsealed abstract class Type extends GeneralType with TypeArg:\n  \n  override protected type ThisType = Type\n  \n  def toBasic: BasicType\n  def toDnf(using TL): Disj\n  \n  // * Remove redundant Top/Bot.\n  // * e.g., Top & Int === Int\n  lazy val simp: Type = this\n  \n  \n  lazy val isPoly: Bool = false\n  \n  override def map(f: Type => Type): Type =\n    toBasic.mapBasic(f) // TODO improve: map on all type constructors\n  \n  def mapArg(f: Type => Type): Type = f(this)\n  \n  def monoOr(fallback: => Type): Type = this\n  \n  def & (that: Type): Type = this match\n    case Top => that\n    case Bot => Bot\n    case _ => that match\n      case Top => this\n      case Bot => Bot\n      case ComposedType(l, r, false) => this & l & r\n      case _ => if this === that\n        then this\n        else ComposedType(this, that, false)\n  def | (that: Type): Type = this match\n    case Top => Top\n    case Bot => that\n    case _ => that match\n      case Top => Top\n      case Bot => this\n      case ComposedType(l, r, true) => this | l | r\n      case _ => if this === that\n        then this\n        else ComposedType(this, that, true)\n  def ! : Type = this match\n    case Top => Bot\n    case Bot => Top\n    case NegType(res) => res\n    case ComposedType(l, r, true) => l.! & r.!\n    case ComposedType(l, r, false) => l.! | r.!\n    case _ => NegType(this)\n  \n  protected[invalml] def paren(using Scope, InvalCtx, Raise): Str = toBasic match\n    case _: InfVar | _: ClassLikeType | _: NegType | Top | Bot => show\n    case _: ComposedType | _: FunType => s\"($show)\"\n\n  protected[invalml] def parenDbg: Str = toBasic match\n    case _: InfVar | _: ClassLikeType | _: NegType | Top | Bot => showDbg\n    case _: ComposedType | _: FunType => s\"($showDbg)\"\n\nsealed abstract class BasicType extends Type:\n  \n  lazy val lvl: Int = this match\n    case ClassLikeType(name, targs) =>\n      targs.map(_.lvl).maxOption.getOrElse(0)\n    case InfVar(lvl, _, _, _) => lvl\n    case FunType(args, ret, eff) =>\n      (ret :: eff :: args).map(_.lvl).max\n    case ComposedType(lhs, rhs, _) =>\n      lhs.lvl.max(rhs.lvl)\n    case NegType(ty) => ty.lvl\n    case Top | Bot => 0\n  \n  def mapBasic(f: Type => Type): Type = this match\n    case ClassLikeType(name, targs) => ClassLikeType(name, targs.map(_.mapArg(f)))\n    case FunType(args, ret, eff) => FunType(args.map(f), f(ret), f(eff))\n    case ComposedType(lhs, rhs, pol) => Type.mkComposedType(f(lhs), f(rhs), pol)\n    case NegType(ty) => Type.mkNegType(f(ty))\n    case Top | Bot | _: InfVar => this\n    \n  override def show(using Scope, InvalCtx, Raise): Str =\n    def printEff(eff: Type) = eff match\n      case Bot => \"\"\n      // case ty if ty == allocSkolem => \"\"\n      case _ => s\"{${eff.show}}\"\n    this match\n    case ClassLikeType(sym, Nil) if sym is invalctx.getCls(\"Unit\") => \"()\"\n    case ClassLikeType(name, targs) =>\n      if targs.isEmpty then s\"${name.nme}\" else s\"${name.nme}[${targs.map(_.show).mkString(\", \")}]\"\n    case v @ InfVar(lvl, uid, _, isSkolem) =>\n      val name = scope.lookup(v.sym).getOrElse(scope.allocateName(v.sym, v.hint))\n      if isSkolem then name else s\"'${name}\"\n    case FunType(arg :: Nil, ret, eff) => s\"${arg.paren} ->${printEff(eff)} ${ret.paren}\"\n    case FunType(args, ret, eff) => s\"(${args.map(_.show).mkString(\", \")}) ->${printEff(eff)} ${ret.paren}\"\n    case ComposedType(lhs, rhs, pol) => s\"${lhs.paren} ${if pol then \"∨\" else \"∧\"} ${rhs.paren}\"\n    case NegType(ty) => s\"¬${ty.paren}\"\n    case Top => \"⊤\"\n    case Bot => \"⊥\"\n\n  override def showDbg: Str = this match\n    case ClassLikeType(name, targs) =>\n      if targs.isEmpty then s\"${name.nme}\" else s\"${name.nme}[${targs.map(_.showDbg).mkString(\", \")}]\"\n    case v @ InfVar(lvl, uid, _, isSkolem) =>\n      val name = if v.hint.isEmpty then s\"${v.sym.nme}\" else s\"${v.sym.nme}(${v.hint})\"\n      if isSkolem then s\"${name}${uid}_${lvl}\" else s\"'${name}${uid}_${lvl}\"\n    case FunType(arg :: Nil, ret, eff) => s\"${arg.parenDbg} ->{${eff.showDbg}} ${ret.parenDbg}\"\n    case FunType(args, ret, eff) => s\"(${args.map(_.showDbg).mkString(\", \")}) ->{${eff.showDbg}} ${ret.parenDbg}\"\n    case ComposedType(lhs, rhs, pol) => s\"${lhs.parenDbg} ${if pol then \"∨\" else \"∧\"} ${rhs.parenDbg}\"\n    case NegType(ty) => s\"¬${ty.parenDbg}\"\n    case Top => \"⊤\"\n    case Bot => \"⊥\"\n  \n  def toBasic: BasicType = this\n  \n  var _dnf: Disj = null\n  def withDnf(d: Disj): this.type = // TODO: remove?\n    assert(_dnf eq null)\n    _dnf = d\n    this\n  def toDnf(using TL) =\n    if _dnf eq null\n    then\n      val d = NormalForm.dnf(this)\n      _dnf = d\n      d\n    else _dnf\n\ntrait CachedNorm[A <: AnyRef]:\n  \n  def mkNorm(using TL): A\n  \n  private var _norm: A = null.asInstanceOf\n  final def hasNorm: Bool = !(_norm eq null)\n  def withNorm(d: A): this.type = // TODO: remove?\n    assert(!hasNorm)\n    _norm = d\n    this\n  def toNorm(using TL) =\n    if _norm eq null\n    then\n      val d = mkNorm\n      _norm = d\n      d\n    else _norm\n  \n\nobject BasicType:\n  // TOOD dedup\n  def union(tys: Ls[BasicType]): BasicType = tys match\n    case Nil => Bot\n    case ty :: Nil => ty\n    case ty :: tys => ComposedType(ty, union(tys), true)\n  def inter(tys: Ls[BasicType]): BasicType = tys match\n    case Nil => Bot\n    case ty :: Nil => ty\n    case ty :: tys => ComposedType(ty, inter(tys), false)\n\ncase class ClassLikeType(name: TypeSymbol | ModuleOrObjectSymbol, targs: Ls[TypeArg]) extends BasicType with CachedNorm[ClassLikeType]:\n  def mkNorm(using TL): ClassLikeType =\n    ClassLikeType(name,\n      targs.map:\n        case ty: Type => ty.toDnf\n        case Wildcard(i, o) => Wildcard(i.toDnf, o.toDnf)\n    )\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType =\n    ClassLikeType(name, targs.map {\n        case Wildcard(in, out) => Wildcard(in.subst, out.subst)\n        case ty: Type => ty.subst\n      })\n\nfinal case class InfVar(vlvl: Int, uid: Uid[InfVar], state: VarState, isSkolem: Bool)(val sym: Symbol, val hint: Str) extends BasicType:\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType = map.get(uid).getOrElse(this)\n\ngiven Ordering[InfVar] = Ordering.by(_.uid)\n\ncase class FunType(args: Ls[Type], ret: Type, eff: Type) extends BasicType with CachedNorm[FunType]:\n  def mkNorm(using TL): FunType =\n    FunType(args.map(_.toDnf), ret.toDnf, eff.toDnf)\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType =\n    FunType(args.map(_.subst), ret.subst, eff.subst)\n\ncase class ComposedType(lhs: Type, rhs: Type, pol: Bool) extends BasicType: // * Positive -> union\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType =\n    Type.mkComposedType(lhs.subst, rhs.subst, pol)\n  override lazy val simp: Type =\n    Type.mkComposedType(lhs.simp, rhs.simp, pol)\n  \nfinal case class NegType(ty: Type) extends BasicType:\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType = NegType(ty.subst)\n  override lazy val simp: Type = ty.simp.!\n\nobject Top extends BasicType:\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType = Top\n\nobject Bot extends BasicType:\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType = Bot\n\nobject Type:\n  def mkComposedType(lhs: Type, rhs: Type, pol: Bool): Type = if pol\n    then lhs | rhs\n    else lhs & rhs\n  def mkNegType(ty: Type): Type = ty.!\n\n// * Poly types can not be used as type arguments\ncase class PolyType(tvs: Ls[InfVar], outer: Opt[InfVar], body: GeneralType) extends GeneralType:\n  override protected type ThisType = GeneralType\n\n  override lazy val isPoly: Bool = true\n  override lazy val lvl: Int = (body :: tvs).map(_.lvl).max\n  override def show(using Scope, InvalCtx, Raise): Str =\n    given Scope = scope.nest\n    val lst = (outer match {\n      case S(outer) =>\n        val op = outer.show\n        (if op === \"outer\" then op else s\"outer $op\") :: Nil\n      case N => Nil\n    }) ++ tvs.map(_.show)\n    s\"[${lst.mkString(\", \")}] -> ${body.show}\"\n  override def showDbg: Str = s\"[${(outer.toList ++ tvs).map(_.showDbg).mkString(\", \")}] -> ${body.showDbg}\"\n  override def monoOr(fallback: => Type): Type = fallback\n  override def map(f: GeneralType => GeneralType): PolyType = PolyType(tvs, outer, f(body))\n\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType =\n    PolyType(tvs.map {\n      case v @ InfVar(lvl, uid, state, skolem) =>\n        val newSt = new VarState()\n        newSt.lowerBounds = state.lowerBounds.map(_.subst)\n        newSt.upperBounds = state.upperBounds.map(_.subst)\n        InfVar(lvl, uid, newSt, skolem)(v.sym, v.hint)\n    }, outer, body.subst) // * outer should have no bound!\n\n  // * This function will only return the body after substitution\n  // * and \\dom(map) should cover all tvs.\n  // * This function is dedicated to `skolemize` and `instantiate`.\n  private def substAndGetBody(using map: Map[Uid[InfVar], InfVar]): GeneralType =\n    tvs.foreach:\n      case InfVar(lvl, uid, state, skolem) =>\n        val v = map(uid)\n        v.state.lowerBounds = state.lowerBounds.map(_.subst)\n        v.state.upperBounds = state.upperBounds.map(_.subst)\n    body.subst\n\n  def skolemize(nextUid: => Uid[InfVar], lvl: Int)(tl: TL) =\n    // * Note that by this point, the state is supposed to be frozen/treated as immutable\n    // * `outer` is already skolemized when it is declared\n    val map = tvs.map(v =>\n      val sk = InfVar(lvl, nextUid, new VarState(), true)(v.sym, v.hint)\n      tl.log(s\"skolemize ${v.showDbg} ~> ${sk.showDbg}\")\n      v.uid -> sk\n    ).toMap\n    substAndGetBody(using map)\n  \n  def instantiate(nextUid: => Uid[InfVar], env: InfVar, lvl: Int)(tl: TL)(using State): GeneralType =\n    val map = (outer.map(_.uid -> env).toList ++ tvs.map(v =>\n      val nv = InfVar(lvl, nextUid, new VarState(), false)(new InstSymbol(v.sym), v.hint)\n      tl.log(s\"instantiate ${v.showDbg} ~> ${nv.showDbg}\")\n      v.uid -> nv\n    )).toMap\n    substAndGetBody(using map)\n\nobject PolyType:\n  def collectTVs(ty: GeneralType): Set[InfVar] =\n    val visited = MutSet.empty[InfVar]\n    object CollectTVs extends TypeTraverser:\n      override def apply(pol: Boolean)(ty: GeneralType): Unit = ty match\n        case v @ InfVar(_, _, state, _) =>\n          if visited.add(v) then\n            state.lowerBounds.foreach: bd =>\n              apply(true)(bd)\n            state.upperBounds.foreach: bd =>\n              apply(false)(bd)\n            super.apply(pol)(ty)\n        case _ => super.apply(pol)(ty)\n    CollectTVs(true)(ty)\n    visited.toSet\n\n  def generalize(ty: GeneralType, outer: Opt[InfVar], lvl: Int): PolyType =\n    PolyType(collectTVs(ty).filter(v => v.lvl == lvl && outer.map(_.uid != v.uid).getOrElse(true)).toList.sorted, outer, ty)\n\n// * Functions that accept/return a polymorphic type.\n// * Note that effects are always monomorphic\n// * Poly types can not be used as type arguments\ncase class PolyFunType(args: Ls[GeneralType], ret: GeneralType, eff: Type) extends GeneralType:\n  override protected type ThisType = GeneralType\n\n  lazy val isPoly: Bool = (ret :: args).exists(_.isPoly)\n  lazy val lvl: Int = (ret :: eff :: args).map(_.lvl).max\n  override def show(using Scope, InvalCtx, Raise): Str = s\"(${args.map(_.show).mkString(\", \")}) ->{${eff.show}} ${ret.show}\"\n  override def showDbg: Str = s\"(${args.map(_.showDbg).mkString(\", \")}) ->{${eff.showDbg}} ${ret.showDbg}\"\n  private lazy val mono: Opt[FunType] = if isPoly then N else\n    Some(FunType(args.map {\n      case t: Type => t\n      case pf: PolyFunType => pf.mono.get\n      case _ => ??? // * Impossible\n    }, ret match {\n      case t: Type => t\n      case pf: PolyFunType => pf.mono.get\n      case _ => ??? // * Impossible\n    }, eff))\n  override def monoOr(fallback: => Type): Type = mono.getOrElse(fallback)\n  override def map(f: GeneralType => GeneralType): PolyFunType =\n    PolyFunType(args.map(f), f(ret), f(eff).monoOr(???)) // * Must be mono\n\n  override def subst(using map: Map[Uid[InfVar], InfVar]): ThisType =\n    PolyFunType(args.map(_.subst), ret.subst, eff.subst)\n\nclass VarState:\n  var lowerBounds: Ls[Type] = Nil\n  var upperBounds: Ls[Type] = Nil\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/io/FileSystem.scala",
    "content": "package hkmc2\npackage io\n\nimport mlscript.utils._, shorthands._\n\n/**\n * Abstract file system operations.\n * \n * These are file system operations that can be directly called by the compiler.\n * More high-level file system operations, such as getting all files under a\n * folder or recursively walking through a specified path, should be handled by\n * the caller of the compiler.\n */\ntrait FileSystem:\n  /** Read entire file as string. */\n  def read(path: Path): String\n  \n  /** Write string to file, overwriting if exists. */\n  def write(path: Path, content: String): Unit\n  \n  /** Check if a file exists at the given path. */\n  def exists(path: Path): Bool\n  \n  /**\n    * Get the last changed timestamp of the file at the given path. The meaning\n    * of the timestamp is platform-dependent. The caller should ensure that the\n    * file exists before calling this method.\n    */\n  def getLastChangedTimestamp(path: Path): Long\n  \nobject FileSystem:\n  /** Get the platform default file system by delegating to the platform. */\n  def default: FileSystem = PlatformFileSystem.default\n  \n  class FileNotFoundException(path: Path) extends Exception:\n    override def getMessage(): String = s\"File not found: ${path.toString}\"\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/io/Path.scala",
    "content": "package hkmc2\npackage io\n\nimport mlscript.utils._, shorthands._\n\n/**\n * Cross-platform path abstraction.\n * Represents a file system path without performing any I/O.\n */\nabstract class Path:\n  /** Convert to platform-specific string representation */\n  def toString: String\n  \n  /** Get the last segment of the path (file or directory name) */\n  def last: String\n  \n  /** Get the base name without extension */\n  def baseName: String\n  \n  /** Get the file extension (without dot) */\n  def ext: String\n  \n  /** Navigate to parent directory */\n  def up: Path\n  \n  /** Join with a relative path */\n  def /(relPath: RelPath): Path\n  \n  /** Join with a single path fragment */\n  def /(fragment: Str): Path\n  \n  /** Calculate relative path from this to target */\n  def relativeTo(base: Path): Opt[RelPath]\n  \n  /** Get segments as a list */\n  def segments: Ls[String]\n  \n  /** Check if this is an absolute path */\n  def isAbsolute: Bool\n\nobject Path:\n  /** Create path from string - delegates to platform-specific implementation */\n  def apply(str: String): Path = PathFactory.fromString(str)\n  \n  /** Platform-specific path separator */\n  def separator: String = PathFactory.separator\n\n/**\n * Represents a relative path\n */\nabstract class RelPath:\n  def toString: String\n  def segments: Ls[String]\n  def /(other: RelPath): RelPath\n\nobject RelPath:\n  /** Create relative path from string - delegates to platform-specific implementation */\n  def apply(str: String): RelPath = PathFactory.relPathFromString(str)\n  \n  /** Represents parent directory (..) */\n  val up: RelPath = PathFactory.relPathUp\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/package.scala",
    "content": "package hkmc2\n\nimport sourcecode.{Line, FileName}\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\nimport hkmc2.Message.MessageContext\n\n\nextension [A](x: A)\n  infix inline def givenIn[R](inline k: A ?=> R) = k(using x)\n  infix inline def ne_::(xs: Ls[A]): NELs[A] = new ::(x, xs)\n\nextension [A](xs: Ls[A])\n  def ne_! : NELs[A] = xs match\n    case Nil => throw new IllegalArgumentException(\"Cannot convert an empty list to a non-empty list.\")\n    case xs: NELs[A] => xs\n  inline def ne_? : Opt[NELs[A]] = xs match\n    case Nil => N\n    case xs: NELs[A] => S(xs)\n\n\n// * Valid identifiers for the members of module and class-like definitions\n// * Importantly, these are the same as valid JavaScript identifiers,\n// * so we do not check them in JS code-generation.\nval identifierPattern: scala.util.matching.Regex = \"^[A-Za-z_$][A-Za-z0-9_$]*$\".r\n\n\ndef softAssert(cond: Boolean, msg: => Str = \"\")(using Line, FileName, Raise): Unit =\n  if !cond then\n    raise:\n      InternalError(\n        msg\"Compiler reached an unexpected state at '${summon[FileName].value}:${summon[Line].value}'${\n          if msg === \"\" then \"\" else s\": $msg\"}\" -> N\n        :: msg\"The compilation result may be incorrect.\" -> N\n        :: msg\"This is a compiler bug; please report it to the maintainers.\" -> N\n        :: Nil)\n\ndef softTODO(cond: Boolean, msg: => Str = \"\")(using Line, FileName, Raise): Unit =\n  if !cond then\n    raise:\n      InternalError(\n        msg\"Compiler reached an unsupported state${\n          if msg === \"\" then \"\" else s\": $msg\"}\" -> N\n        :: msg\"The compilation result may be incorrect.\" -> N\n        :: msg\"This is a known compiler limitation; if it is a blocker for you, please report it to the maintainers.\" -> N\n        :: Nil)\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/BlockImpl.scala",
    "content": "package hkmc2\npackage semantics\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.Tree\nimport syntax.Tree.*\nimport hkmc2.syntax.{PossiblyAnnotated, TypeOrTermDef}\n\n\ntrait BlockImpl(using Elaborator.State):\n  self: Block =>\n  \n  val desugStmts =\n    def desug(stmts: Ls[Tree]): Ls[Tree] =\n      stmts match\n      case syntax.Desugared(PossiblyAnnotated(anns, Assert(kw, cond, N, els))) :: stmts =>\n        PossiblyAnnotated(anns, Assert(kw, cond, S(Block(stmts)), els)) :: Nil\n      case syntax.Desugared(PossiblyAnnotated(anns, td: TypeDef)) :: stmts =>\n        val ctors = td.withPart.toList.flatMap:\n          case Block(sts) => sts.flatMap:\n            case Constructor(Block(ctors)) => ctors\n            case _ => Nil\n          case _ => Nil\n        // A temporary solution for ADTs, which desugars ADTs to normal class definitions.\n        // This will be removed after we truly support ADTs correctly.\n        // TODO: No raise contextual variable. Only `Error` nodes are returned if there is an error. \n        lazy val (headId, headPs) = td.baseHead match\n          case id: Ident => (id, Nil)\n          case App(id: Ident, TyTup(ps)) => (id, ps)\n        // Temporarily use `data` annotation to distinguish the following ctors:\n        // - Ctor(...)\n        // - Ctor[...](...) extends ADT[...]\n        // since the former will be desugared to `class Ctor[...](...) extends ADT[...]`,\n        // where `Ctor[...]` and `ADT[...]` share the same type parameter list\n        def getPossibleGenericAnns(decl: Tree, anns: Ls[Tree]) = decl match\n          case InfixApp(_, Keywrd(syntax.Keyword.`extends`), _) =>\n            Keywrd(syntax.Keyword.data) :: anns\n          case _ => anns\n        // Generate `extends` suffix if it is not provided by users\n        // Also check if the number of type parameters is correct\n        def genExt(decl: Tree) = decl match\n          case InfixApp(_, Keywrd(syntax.Keyword.`extends`), ext) => ext match\n            case _: Ident if headPs.isEmpty => ext\n            case App(id: Ident, TyTup(ps)) if id.name == headId.name && ps.length == headPs.length => ext\n            case _ => Error()\n          case _ => headPs match\n            case Nil => headId\n            case ps =>\n              App(headId, TyTup(ps.map {\n                case m @ Modified(Keywrd(syntax.Keyword.`in`) | Keywrd(syntax.Keyword.`out`), _) => m\n                case t => Tup(Tree.Modified(Keywrd(syntax.Keyword.`in`), t) :: Tree.Modified(Keywrd(syntax.Keyword.`out`), t) :: Nil)\n              }))\n        // Insert type parameters for constructors.\n        // e.g. `class Foo[T] with constructor Bar(x: T)` will be desugared to\n        // `class Bar[T](x: T) extends Foo[T]`\n        // Otherwise, the elaborator will complain `T` is not defined.\n        def genCtorHead(decl: Tree) = decl match\n          case InfixApp(decl, Keywrd(syntax.Keyword.`extends`), _) => decl // check will be applied in genExt\n          case App(_: Ident, tup: TyTup) => Error()\n          case App(id: Ident, ps: Tup) => App(App(id, TyTup(headPs)), ps)\n          case id: Ident => App(id, TyTup(headPs))\n          case _ => Error()\n        // Only fields modified by `val` can be extracted by pattern matching.\n        // For ADTs, all fields can be extracted, but we don't want to add `val`s manumally.\n        def insertVal(decl: Tree): Tree = decl match\n          case id: Ident => id\n          case App(f, Tup(ps)) => App(f, Tup(ps.map(p => TermDef(syntax.ImmutVal, p, N))))\n          case App(f, tup: TyTup) => App(insertVal(f), tup)\n          case _ => Error()\n        PossiblyAnnotated(anns, td) :: (\n          ctors.map(head => PossiblyAnnotated(getPossibleGenericAnns(head, anns), TypeDef(syntax.Cls,\n            td.name match\n                case L(_) => head\n                case R(name) =>\n                  InfixApp(insertVal(genCtorHead(head)), Keywrd(syntax.Keyword.`extends`), genExt(head))\n            , N)))\n        ) ::: desug(stmts)\n      case stmt :: stmts =>\n        stmt.desugared match\n        case PossiblyAnnotated(anns, h @ Hndl(body = N)) =>\n          PossiblyAnnotated(anns, h.copy(body = S(Block(stmts)))) :: Nil\n        case stmt => stmt :: desug(stmts)\n      case Nil => Nil\n    desug(stmts)\n  \n  val definedSymbols: Array[Str -> BlockMemberSymbol] =\n    desugStmts\n      .flatMap:\n        case PossiblyAnnotated(_, td: syntax.TypeOrTermDef) =>\n          td.name match\n            case L(_) => Nil\n            case R(id) =>\n              id.name -> R(td) :: (\n                td.symbName match\n                case S(R(sid)) => id.name -> L(sid.name) :: Nil\n                case _ => Nil\n              )\n        case _ => Nil\n      .groupMap(_._1)(_._2).flatMap:\n        case (nme, snmes_tds) =>\n          val (symNmes, tds) = snmes_tds.partitionMap(identity)\n          val sym = new BlockMemberSymbol(nme, tds)\n          nme -> sym :: symNmes.map(_ -> sym)\n      .toArray.sortBy(_._1)\n  \nend BlockImpl\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala",
    "content": "package hkmc2\npackage semantics\n\n\nimport scala.collection.mutable\nimport scala.annotation.tailrec\nimport scala.language.implicitConversions\n\nimport mlscript.utils.*, shorthands.*\nimport utils.TraceLogger\n\nimport syntax.*\nimport Tree.*\nimport BracketKind.*\nimport Term.{ Blk, Rcd }\nimport hkmc2.Message.MessageContext\n\nimport Keyword.{`let`, `set`}\nimport hkmc2.utils.Scope\n\n\nobject Elaborator:\n  \n  val binaryOps = Set(\n    \",\", // * Not currently used directly; but `;` (below) maps to it\n    \"+\", \"-\", \"*\", \"/\", \"%\",\n    \"==\", \"!=\", \"<\", \"<=\", \">\", \">=\",\n    \"===\", \"!==\",\n    \"&&\", \"||\")\n  val unaryOps = Set(\"-\", \"+\", \"!\", \"~\", \"typeof\")\n  val anyOps = Set(\"super\")\n  val builtins = binaryOps ++ unaryOps ++ anyOps\n  val aliasOps = Map(\n    \";\" -> \",\",\n    \"+.\" -> \"+\",\n    \"-.\" -> \"-\",\n    \"*.\" -> \"*\",\n    \"/.\" -> \"/\")\n  private val builtinBinOps = aliasOps ++ (binaryOps.map: op =>\n    op -> op).toMap\n\n  val reservedNames = binaryOps.toSet ++ aliasOps.keySet + \"NaN\" + \"Infinity\"\n  \n  // TODO: rename to ScopeKind?\n  enum OuterCtx:\n    case Function(returnHandlerSymbol: TempSymbol)\n    case InnerScope(innerSymbol: InnerSymbol)\n    case LocalScope(nameHint: Str)\n    case LambdaOrHandlerBlock\n    case NonReturnContext\n    \n    def showDbg: Str = this match\n      case Function(sym) => s\"fun:${sym.nme}\"\n      case InnerScope(inner) => inner.toString\n      case LocalScope(hint) => hint\n      case LambdaOrHandlerBlock => \"LambdaOrHandlerBlock\"\n      case NonReturnContext => \"NonReturnContext\"\n    \n    def inner: Opt[InnerSymbol] = this match\n      case InnerScope(inner) => S(inner)\n      case _ => N\n  \n  enum ReturnHandler:\n    case Required(handler: TempSymbol)\n    case Direct\n    case NotInFunction\n    case Forbidden\n  \n  /** Context used to keep track of underscores representing lambda shorthands, eg in `_ + 1`. */\n  // TODO later: use TempSymbol instead of VarSymbol? (currently, trying that creates lot of problems)\n  class UnderCtx(val unders: Opt[mutable.ArrayBuffer[VarSymbol]])\n  \n  case class Ctx(\n      outer: OuterCtx,\n      parent: Opt[Ctx],\n      env: Map[Str, Ctx.Elem],\n      mode: Mode,\n  ):\n    \n    override def toString: Str = s\"${parent.fold(\"\")(_.toString+\"/\")}${outer.showDbg}\"\n    \n    lazy val scope: SrcScope = SrcScope(outer, parent.map(_.scope))\n    \n    def +(local: Str -> Symbol): Ctx = copy(outer, env = env + local.mapSecond(Ctx.RefElem(_)))\n    def ++(locals: IterableOnce[Str -> Symbol]): Ctx =\n      copy(outer, env = env ++ locals.mapValues(Ctx.RefElem(_)))\n    def elem_++(locals: IterableOnce[Str -> Ctx.Elem]): Ctx =\n      copy(outer, env = env ++ locals.iterator.filter: kv =>\n        // * Imports should not shadow symbols defined in the same scope;\n        // * but they should be allowed to shadow previous imports.\n        env.get(kv._1).forall(_.isImport))\n    \n    def withMembers(members: Iterable[Str -> MemberSymbol]): Ctx =\n      copy(env = env ++ members.map:\n        case (nme, sym) =>\n          val elem = outer.inner match\n            case S(outer) => Ctx.SelElem(outer, sym.nme, S(sym), isImport = false)\n            case N => Ctx.RefElem(sym)\n          nme -> elem\n      )\n    \n    def nest(outerCtx: OuterCtx): Ctx = Ctx(outerCtx, Some(this), Map.empty, mode)\n    def nestLocal(nameHint: Str): Ctx = nest(OuterCtx.LocalScope(nameHint))\n    def nestInner(inner: InnerSymbol): Ctx = nest(OuterCtx.InnerScope(inner))\n    \n    def get(name: Str): Opt[Ctx.Elem] =\n      env.get(name).orElse(parent.flatMap(_.get(name)))\n    def getOuter: Opt[InnerSymbol] = outer.inner.orElse(parent.flatMap(_.getOuter))\n    def getNonLocalRetHandler: Opt[TempSymbol] = outer match\n      case OuterCtx.Function(sym) => S(sym)\n      case _ => parent.flatMap(_.getNonLocalRetHandler)\n    def getRetHandler: ReturnHandler = outer match\n      case OuterCtx.Function(sym) => ReturnHandler.Direct\n      case _: (OuterCtx.LambdaOrHandlerBlock.type | OuterCtx.InnerScope) =>\n        getNonLocalRetHandler.fold(ReturnHandler.NotInFunction)(ReturnHandler.Required(_))\n      case OuterCtx.NonReturnContext => ReturnHandler.Forbidden\n      case _: OuterCtx.LocalScope =>\n        parent.fold(ReturnHandler.NotInFunction)(_.getRetHandler)\n    \n    // * Invariant: We expect that the top-level context only contain hard-coded symbols like `globalThis`\n    // * and that built-in symbols like Int and Str be imported into another nested context on top of it.\n    // * It should not be possible to shadow these built-in symbols, so user code should always be compiled\n    // * in further nested contexts.\n    lazy val preludeCtx: Ctx =\n      parent match\n      case N => lastWords(\"Cannot find prelude context.\")\n      case S(par) => if par.parent.isEmpty then this else par.preludeCtx\n    \n    // * Method `getBuiltin` is used to look up built-in symbols in the context of builtin symbols.\n    def getBuiltin(nme: Str): Opt[Ctx.Elem] =\n      preludeCtx.env.get(nme)\n    \n    lazy val builtins: Ctx#MkBuiltins = preludeCtx.MkBuiltins\n    private object MkBuiltins extends MkBuiltins\n    \n    class MkBuiltins:\n      assert(Ctx.this is preludeCtx)\n      private def assumeBuiltin(nme: Str): Symbol =\n        getBuiltin(nme)\n          .getOrElse(throw new NoSuchElementException(s\"builtin $nme not in ${parent.map(_.env.keySet)}\"))\n          .symbol.getOrElse(throw new NoSuchElementException(s\"builtin symbol $nme\"))\n      private def assumeBuiltinTpe(nme: Str): TypeSymbol =\n        assumeBuiltin(nme).asTpe.getOrElse(throw new NoSuchElementException(\n          s\"builtin type symbol $nme\"))\n      private def assumeBuiltinCls(nme: Str): ClassSymbol =\n        assumeBuiltin(nme).asCls.getOrElse(throw new NoSuchElementException(\n          s\"builtin class symbol $nme\"))\n      private def assumeBuiltinObj(nme: Str): ModuleOrObjectSymbol =\n        assumeBuiltin(nme).asObj.getOrElse(throw new NoSuchElementException(\n          s\"builtin object symbol $nme\"))\n      private def assumeBuiltinMod(nme: Str): ModuleOrObjectSymbol =\n        assumeBuiltin(nme).asMod.getOrElse(throw new NoSuchElementException(\n          s\"builtin module symbol $nme\"))\n      val Int = assumeBuiltinCls(\"Int\")\n      // TODO(Derppening): Can we move the Int31 builtin in the wasm module?\n      val Int31 = assumeBuiltinCls(\"Int31\")\n      val Num = assumeBuiltinCls(\"Num\")\n      val Str = assumeBuiltinCls(\"Str\")\n      val BigInt = assumeBuiltinCls(\"BigInt\")\n      val Function = assumeBuiltinCls(\"Function\")\n      val Error = assumeBuiltinCls(\"Error\")\n      val Bool = assumeBuiltinCls(\"Bool\")\n      val Object = assumeBuiltinCls(\"Object\")\n      val Array = assumeBuiltinCls(\"Array\")\n      val TypedArray = assumeBuiltinCls(\"TypedArray\")\n      val untyped = assumeBuiltinTpe(\"untyped\")\n      val tailrec = assumeBuiltinTpe(\"tailrec\")\n      val tailcall = assumeBuiltinTpe(\"tailcall\")\n      // println(s\"Builtins: $Int, $Num, $Str, $untyped\")\n      class VirtualModule(val module: ModuleOrObjectSymbol):\n        val bms = getBuiltin(module.nme) match\n          case S(Ctx.RefElem(bms: BlockMemberSymbol)) => bms\n          case huh => wat(huh)\n        protected def assumeObject(nme: Str): BlockMemberSymbol =\n          module.tree.definedSymbols.get(nme).getOrElse:\n            throw new NoSuchElementException(\n              s\"builtin module symbol source.$nme\")\n      object Symbol extends VirtualModule(assumeBuiltinObj(\"Symbol\")):\n        val `for` = assumeObject(\"for\")\n        val iterator = assumeObject(\"iterator\")\n      object source extends VirtualModule(assumeBuiltinMod(\"source\")):\n        val line = assumeObject(\"line\")\n        val name = assumeObject(\"name\")\n        val file = assumeObject(\"file\")\n      object js extends VirtualModule(assumeBuiltinMod(\"js\")):\n        val bitand = assumeObject(\"bitand\")\n        val bitnot = assumeObject(\"bitnot\")\n        val bitor = assumeObject(\"bitor\")\n        val shl = assumeObject(\"shl\")\n        val try_catch = assumeObject(\"try_catch\")\n      object wasm extends VirtualModule(assumeBuiltinMod(\"wasm\")):\n        val plus_impl = assumeObject(\"plus_impl\")\n        val minus_impl = assumeObject(\"minus_impl\")\n        val times_impl = assumeObject(\"times_impl\")\n        val div_impl = assumeObject(\"div_impl\")\n        val mod_impl = assumeObject(\"mod_impl\")\n        val eq_impl = assumeObject(\"eq_impl\")\n        val neq_impl = assumeObject(\"neq_impl\")\n        val lt_impl = assumeObject(\"lt_impl\")\n        val le_impl = assumeObject(\"le_impl\")\n        val gt_impl = assumeObject(\"gt_impl\")\n        val ge_impl = assumeObject(\"ge_impl\")\n        val neg_impl = assumeObject(\"neg_impl\")\n        val pos_impl = assumeObject(\"pos_impl\")\n        val not_impl = assumeObject(\"not_impl\")\n      object debug extends VirtualModule(assumeBuiltinMod(\"debug\")):\n        val printStack = assumeObject(\"printStack\")\n      object annotations extends VirtualModule(assumeBuiltinMod(\"annotations\")):\n        val compile = assumeObject(\"compile\")\n        val buffered = assumeObject(\"buffered\")\n        val bufferable = assumeObject(\"bufferable\")\n      object scope extends VirtualModule(assumeBuiltinMod(\"scope\")):\n        val locally = assumeObject(\"locally\")\n      object runtime extends VirtualModule(assumeBuiltinMod(\"runtime\")):\n        val suspend = assumeObject(\"suspend\")\n        val handle_suspension = assumeObject(\"handle_suspension\")\n      def getBuiltinOp(op: Str): Opt[Str] =\n        if getBuiltin(op).isDefined then builtinBinOps.get(op) else N\n      object BuiltInOpIdent:\n        def unapply(id: Ident): Opt[Str] =\n          getBuiltinOp(id.name)\n      /** Classes that do not use `instanceof` in pattern matching. */\n      val virtualClasses = Set(Int, Num, Str, Bool, TypedArray)\n  \n  object Ctx:\n    abstract class Elem:\n      def nme: Str\n      def ref(id: Ident)(using Elaborator.State, Ctx): Resolvable\n      def symbol: Opt[Symbol]\n      def isImport: Bool\n    final case class RefElem(sym: Symbol) extends Elem:\n      val nme = sym.nme\n      def ref(id: Ident)(using Elaborator.State, Ctx): Resolvable =\n        // * Note: due to symbolic ops, we may have `id.name =/= nme`;\n        // * e.g., we can have `id.name = \"|>\"` and `nme = \"pipe\"`.\n        Term.Ref(sym)(id, 666, N) // FIXME: 666 is a temporary placeholder\n      def symbol = S(sym)\n      def isImport: Bool = false\n    final case class SelElem(base: Elem, nme: Str, symOpt: Opt[MemberSymbol], isImport: Bool) extends Elem:\n      def ref(id: Ident)(using Elaborator.State, Ctx): Resolvable =\n        // * Same remark as in RefElem#ref\n        Term.SynthSel(base.ref(Ident(base.nme)),\n          new Ident(nme).withLocOf(id))(symOpt, FlowSymbol.synthSel(nme), N, S(summon))\n      def symbol = symOpt\n    given Conversion[Symbol, Elem] = RefElem(_)\n    val empty: Ctx = Ctx(OuterCtx.LocalScope(\"top-level\"), N, Map.empty, Mode.Full)\n    \n  enum Mode:\n    case Full\n    case Light\n  \n  type Ctxl[A] = Ctx ?=> Cfg[A]\n  \n  transparent inline def ctx(using Ctx): Ctx = summon\n  \n  class State:\n    val suid = new Uid.Symbol.State\n    given State = this\n    val globalThisSymbol = TopLevelSymbol(\"globalThis\")\n    val unitSymbol = ModuleOrObjectSymbol(DummyTypeDef(syntax.Obj), Ident(\"Unit\"))\n    // Stable symbol for the synthetic Wasm Unit singleton\n    val unitBlockMemberSymbol = BlockMemberSymbol(\"Unit\", Nil)\n    val loopEndSymbol = ModuleOrObjectSymbol(DummyTypeDef(syntax.Obj), Ident(\"LoopEnd\"))\n    val tupleSymbol = ModuleOrObjectSymbol(DummyTypeDef(syntax.Mod), Ident(\"Tuple\"))\n    val strSymbol = ModuleOrObjectSymbol(DummyTypeDef(syntax.Mod), Ident(\"Str\"))\n    // In JavaScript, `import` can be used for getting current file path, as `import.meta`\n    val importSymbol = new VarSymbol(Ident(\"import\"))\n    val noSymbol = NoSymbol()\n    val runtimeSymbol = TempSymbol(N, \"runtime\")\n    val definitionMetadataSymbol = TempSymbol(N, \"definitionMetadata\")\n    val prettyPrintSymbol = TempSymbol(N, \"prettyPrint\")\n    val termSymbol = TempSymbol(N, \"Term\")\n    val blockSymbol = TempSymbol(N, \"Block\")\n    val optionSymbol = TempSymbol(N, \"option\")\n    val wasmSymbol = TempSymbol(N, \"wasm\")\n    val nonLocalRetHandlerTrm =\n      val id = new Ident(\"NonLocalReturn\")\n      val sym = ClassSymbol(DummyTypeDef(syntax.Cls), id)\n      val bsym = BlockMemberSymbol(\"ret\", Nil, true)\n      val defn = ClassDef(N, syntax.Cls, sym, bsym, N, Nil, Nil, N, ObjBody(Blk(Nil, Term.Lit(UnitLit(false)))), Nil, N)\n      sym.defn = S(defn)\n      Term.SynthSel(runtimeSymbol.ref(), id)(S(sym), FlowSymbol.synthSel(id.name), N, N)\n    val nonLocalRet =\n      val id = new Ident(\"ret\")\n      BlockMemberSymbol(id.name, Nil, true)\n    val unreachableSymbol = TermSymbol(syntax.ImmutVal, N, new Ident(\"unreachable\"))\n    val tupleGetSymbol = createFunSymbolInMod(\"get\", \"xs\" :: \"i\" :: Nil, tupleSymbol)\n    val tupleSliceSymbol = createFunSymbolInMod(\"slice\", \"xs\" :: \"i\" :: \"j\" :: Nil, tupleSymbol)\n    val tupleLazySliceSymbol = createFunSymbolInMod(\"lazySlice\", \"xs\" :: \"i\" :: \"j\" :: Nil, tupleSymbol)\n    val strStartsWithSymbol = createFunSymbolInMod(\"startsWith\", \"string\" :: \"prefix\" :: Nil, strSymbol)\n    val strGetSymbol = createFunSymbolInMod(\"get\", \"string\" :: \"i\" :: Nil, strSymbol)\n    val strTakeSymbol = createFunSymbolInMod(\"take\", \"string\" :: \"n\" :: Nil, strSymbol)\n    val strLeaveSymbol = createFunSymbolInMod(\"leave\", \"string\" :: \"n\" :: Nil, strSymbol)\n    val (matchSuccessClsSymbol, matchSuccessTrmSymbol) =\n      val id = new Ident(\"MatchSuccess\")\n      val td = TypeDef(syntax.Cls, App(id, Tup(Ident(\"output\") :: Ident(\"bindings\") :: Nil)), N)\n      val cs = ClassSymbol(td, id)\n      val ts = TermSymbol(syntax.Fun, N, id)\n      val flag = FldFlags.empty.copy(isVal = true)\n      val ps = PlainParamList(\n        Param(flag, VarSymbol(Ident(\"output\")), N, Modulefulness(N)(false)) ::\n        Param(flag, VarSymbol(Ident(\"bindings\")), N, Modulefulness(N)(false)) ::\n        Nil)\n      val ctsym = TermSymbol(Fun, S(cs), cs.id)\n      cs.defn = S(ClassDef.Parameterized(N, syntax.Cls, cs, BlockMemberSymbol(cs.name, Nil), S(ctsym),\n        Nil, ps, Nil, N, ObjBody(Blk(Nil, Term.Lit(UnitLit(false)))), N, Nil))\n      cs -> ts\n    val (matchFailureClsSymbol, matchFailureTrmSymbol) =\n      val id = new Ident(\"MatchFailure\")\n      val td = DummyTypeDef(syntax.Cls)\n      val cs = ClassSymbol(td, id)\n      val ts = TermSymbol(syntax.Fun, N, id)\n      val flag = FldFlags.empty.copy(isVal = true)\n      val ps = PlainParamList(Param(flag, VarSymbol(Ident(\"errors\")), N, Modulefulness(N)(false)) :: Nil)\n      val ctsym = TermSymbol(Fun, S(cs), cs.id)\n      cs.defn = S(ClassDef.Parameterized(N, syntax.Cls, cs, BlockMemberSymbol(cs.name, td :: Nil), S(ctsym),\n        Nil, ps, Nil, N, ObjBody(Blk(Nil, Term.Lit(UnitLit(false)))), N, Nil))\n      cs -> ts\n    val builtinOpsMap =\n      val baseBuiltins = builtins.map: op =>\n          op -> BuiltinSymbol(op,\n            binary = binaryOps(op),\n            unary = unaryOps(op),\n            nullary = false,\n            functionLike = anyOps(op))\n        .toMap\n      baseBuiltins ++ aliasOps.map:\n        case (alias, base) => alias -> baseBuiltins(base)\n    val andSymbol = builtinOpsMap(\"&&\")\n    val orSymbol = builtinOpsMap(\"||\")\n    def init(using State): Ctx = Ctx.empty.copy(env = Map(\n      \"globalThis\" -> globalThisSymbol,\n    ))\n    def dbg: Bool = false\n    def dbgRefNum(num: Int): Str =\n      if dbg then s\"#$num\" else \"\"\n    def dbgUid(uid: Uid[Symbol]): Str =\n      if dbg then s\"‹$uid›\" else \"\"\n      // ^ we do not display the uid by default to avoid polluting diff-test outputs\n    // Create a term symbol for a function defined in the given module\n    private def createFunSymbolInMod(name: Str, paramNames: List[Str], mod: ModuleOrObjectSymbol) =\n      val sym = TermSymbol(syntax.Fun, N, Ident(name))\n      val bsym = BlockMemberSymbol(name, Nil, true)\n      val ps = PlainParamList(paramNames.map(s => Param.simple(VarSymbol(Ident(s)))))\n      sym.defn = S(TermDefinition(syntax.Fun, bsym, sym, ps :: Nil, N, N, N,\n        TermDefFlags(true), Modulefulness(S(mod))(false), Nil, N))\n      sym\n  transparent inline def State(using state: State): State = state\n  \nend Elaborator\n\n\nimport Elaborator.*\n\n\nclass Elaborator(val tl: TraceLogger, val wd: io.Path, val prelude: Ctx)\n(using val raise: Raise, val state: State, val cctx: CompilerCtx, val config: Config)\nextends Importer with ucs.SplitElaborator:\n  import tl.*\n  given TraceLogger = tl\n  \n  lazy val illegalMemberNameTail =\n    msg\"Member names must start with a letter or underscore, followed by letters, digits, or underscores.\" -> N\n    :: Nil\n  \n  def mkLetBinding(kw: Tree.Keywrd[?], sym: LocalSymbol, rhs: Term, annotations: Ls[Annot]): Ls[Statement] =\n    LetDecl(sym, annotations).mkLocWith(kw, sym) :: DefineVar(sym, rhs) :: Nil\n  \n  def resolveField(srcTree: Tree, base: Opt[Symbol], nme: Ident): Opt[MemberSymbol] =\n    base match\n    case S(psym: BlockMemberSymbol) =>\n      psym.modOrObjTree match\n      case S(cls) =>\n        cls.definedSymbols.get(nme.name) match\n        case s @ S(clsSym) => s\n        case N =>\n          raise(ErrorReport(msg\"${cls.k.desc.capitalize} '${cls.symbol.nme\n            }' does not contain member '${nme.name}'\" -> srcTree.toLoc :: Nil))\n          S(ErrorSymbol(nme.name, srcTree))\n      case N =>\n        N\n    case _ => N\n  \n  def annot(tree: Tree): Ctxl[Opt[Annot]] = tree match\n    case Keywrd(kw @ (\n      Keyword.`abstract`\n      | Keyword.`declare`\n      | Keyword.`data`\n      | Keyword.`staged`\n      | Keyword.`public`\n      | Keyword.`private`\n    )) => S(Annot.Modifier(kw))\n    case App(Ident(\"config\"), Tup(args)) =>\n      val modify = ConfigParser.parseOverrides(args)\n      S(Annot.Config(modify))\n    case _ => term(tree) match\n      case Term.Error => N\n      case trm =>\n        trm.symbol match\n        case S(sym) =>\n          sym.asTpe match\n          case S(ctx.builtins.untyped) =>\n            return S(Annot.Untyped)\n          case S(ctx.builtins.tailcall) =>\n            return S(Annot.TailCall)\n          case S(ctx.builtins.tailrec) =>\n            return S(Annot.TailRec)\n          case _ => ()\n        case _ => ()\n        S(Annot.Trm(trm))\n  \n  def term(tree: Tree): Ctxl[Term] =\n  trace[Term](s\"Elab term ${tree.showDbg}\", r => s\"~> $r\"):\n    val unders = mutable.ArrayBuffer.empty[VarSymbol]\n    given UnderCtx = new UnderCtx(S(unders))\n    val st = subterm(tree, inAppPrefix = false, inTyAppPrefix = false)\n    val params = unders.iterator.map: sym =>\n        Param(FldFlags.empty, sym, N, Modulefulness.none)\n      .toList\n    if params.isEmpty then st\n    else Term.Lam(PlainParamList(params), st)\n  \n  def subterm(tree: Tree, inAppPrefix: Bool = false, inTyAppPrefix: Bool = false): Ctxl[UnderCtx ?=> Term] =\n  trace[Term](s\"Elab subterm ${tree.showDbg}\", r => s\"~> $r\"):\n    tree.desugared match\n    case Trm(term) => term\n    case unt @ Unt() => unit.withLocOf(unt)\n    case Bra(k, e) =>\n      k match\n      case Round =>\n      case Curly =>\n      case _ =>\n        raise(ErrorReport(msg\"Unsupported ${k.name} in this position\" -> tree.toLoc :: Nil))\n      term(e) // * not `subterm` as `e` could be a lambda shorthand\n    case b: Block =>\n      ctx.nestLocal(\"‹block›\").givenIn:\n        block(b, hasResult = true)._1 match\n        case Term.Blk(Nil, res) => res\n        case res => res\n    case lit: Literal =>\n      Term.Lit(lit)\n    case d: Def =>\n      subterm(Block(d :: Unt() :: Nil))\n    case LetLike(kw @ Keywrd(`let`), lhs, rhso, S(bod)) =>\n      subterm(Block(LetLike(kw, lhs, rhso, N) :: bod :: Nil))\n    case LetLike(kw @ Keywrd(`let`), lhs, rhso, N) =>\n      raise(ErrorReport(\n        msg\"Expected a body for let bindings in expression position\" ->\n          tree.toLoc :: Nil))\n      block(LetLike(kw, lhs, rhso, N) :: Nil, hasResult = true)._1\n    case LetLike(Keywrd(`set`), lhs, S(rhs), N) =>\n      Term.Assgn(subterm(lhs), subterm(rhs))\n    case LetLike(Keywrd(`set`), lhs, N, N) =>\n      raise(ErrorReport(\n        msg\"Expected a right-hand side for this assignment\" ->\n          tree.toLoc :: Nil))\n      Term.Error\n    case LetLike(Keywrd(`set`), lhs, S(rhs), S(bod)) =>\n      // * Backtracking assignment\n      if config.effectHandlers.isDefined then\n        raise(ErrorReport(\n          msg\"Backtracking assignment is not supported with effect handlers enabled\" ->\n            tree.toLoc :: Nil))\n        Term.Error\n      else\n        val lt = subterm(lhs)\n        val sym = TempSymbol(S(lt), \"old\")\n        Blk(\n          LetDecl(sym, Nil) :: DefineVar(sym, lt) :: Nil, Term.Try(Blk(\n            Term.Assgn(lt, subterm(rhs)) :: Nil,\n            subterm(bod),\n        ), Term.Assgn(lt, sym.ref())))\n    case (hd @ Hndl(id: Ident, c, Block(sts_), S(bod))) => ctx.nest(OuterCtx.LambdaOrHandlerBlock).givenIn:\n      \n      val sym = fieldOrVarSym(HandlerBind, id)\n      log(s\"Processing `handle` statement $id (${sym}) ${ctx.outer}\")\n      \n      val derivedClsSym = ClassSymbol(Tree.DummyTypeDef(syntax.Cls), Tree.Ident(s\"Handler$$${id.name}$$\"))\n      derivedClsSym.defn = S(ClassDef(\n        N, syntax.Cls, derivedClsSym,\n        BlockMemberSymbol(derivedClsSym.name, Nil), N,\n        Nil, Nil, N, ObjBody(Blk(Nil, Term.Lit(Tree.UnitLit(false)))), Nil, N))\n      \n      val elabed = ctx.nestInner(derivedClsSym).givenIn:\n        block(sts_, hasResult = false)._1\n      \n      elabed.res match\n      case Term.Lit(UnitLit(false)) => \n      case trm => raise(WarningReport(msg\"Terms in handler block do nothing\" -> trm.toLoc :: Nil))\n      \n      val tds = elabed.stats.map {\n          case td @ TermDefinition(Fun, sym, tsym, params, tparams, sign, body, flags, mf, annotations, comp) =>\n            params.reverse match\n              case ParamList(_, value :: Nil, _) :: newParams =>\n                if newParams.isEmpty then\n                  raise(ErrorReport(msg\"Handler function cannot be a getter\" -> td.toLoc :: Nil))\n                val newTd = TermDefinition(Fun, sym, tsym, newParams.reverse, tparams, sign, body, flags, mf, annotations, comp)\n                S(HandlerTermDefinition(value.sym, newTd))\n              case _ => \n                raise(ErrorReport(msg\"Handler function is missing resumption parameter\" -> td.toLoc :: Nil))\n                None\n              \n          case st => \n            raise(ErrorReport(msg\"Only function definitions are allowed in handler blocks\" -> st.toLoc :: Nil))\n            None\n        }.collect { case Some(x) => x }\n      \n      val (cp, p) = c match\n        case App(c, Tup(params)) =>\n          (subterm(c), params.map(subterm(_)))\n        case c =>\n          (subterm(c), Nil)\n      \n      (ctx + (id.name -> sym)).givenIn:\n        Term.Handle(sym, cp, p, derivedClsSym, tds, subterm(bod))\n    case h: Hndl =>\n      raise(ErrorReport(\n        msg\"Unsupported handle binding shape\" ->\n          h.toLoc :: Nil))\n      Term.Error\n    case id @ Ident(\"this\") =>\n      ctx.getOuter match\n      case S(sym) => sym.ref(id)\n      case N =>\n        raise:\n          ErrorReport(msg\"Cannot use 'this' outside of an object scope\" -> tree.toLoc :: Nil)\n        Term.Error\n    case id @ Ident(\"|\" | \"&\") =>\n      raise:\n        ErrorReport(msg\"Unexpected use of special operator '${id.name}'\" -> id.toLoc :: Nil)\n      Term.Error\n    case id @ Ident(name) => ident(id).getOrElse:\n      raise(ErrorReport(msg\"Name not found: $name\" -> id.toLoc :: Nil))\n      Term.Error\n    case TyApp(lhs, targs) =>\n      Term.TyApp(subterm(lhs, inTyAppPrefix = true), targs.map {\n        case Modified(Keywrd(Keyword.`in`), arg) => Term.WildcardTy(S(subterm(arg)), N)\n        case Modified(Keywrd(Keyword.`out`), arg) => Term.WildcardTy(N, S(subterm(arg)))\n        case Tup(Modified(Keywrd(Keyword.`in`), arg1) :: Modified(Keywrd(Keyword.`out`), arg2) :: Nil) =>\n          Term.WildcardTy(S(subterm(arg1)), S(subterm(arg2)))\n        case arg => subterm(arg)\n      })(N).withLocOf(tree)\n    case InfixApp(TyTup(tvs), Keywrd(Keyword.`->`), body) =>\n      val boundVars = mutable.HashMap.empty[Str, VarSymbol]\n      def genSym(id: Tree.Ident) =\n        val sym = VarSymbol(id)\n        sym.decl = S(TyParam(FldFlags.empty, N, sym)) // TODO vce\n        boundVars += id.name -> sym\n        sym\n      val syms = (tvs.collect:\n        case id: Tree.Ident => (genSym(id), N, N)\n        case InfixApp(id: Tree.Ident, Keywrd(Keyword.`extends`), ub) => (genSym(id), S(ub), N)\n        case InfixApp(id: Tree.Ident, Keywrd(Keyword.`restricts`), lb) => (genSym(id), N, S(lb))\n        case InfixApp(InfixApp(id: Tree.Ident, Keywrd(Keyword.`extends`), ub), Keywrd(Keyword.`restricts`), lb) => (genSym(id), S(ub), S(lb))\n      )\n      val outer = (tvs.collect:\n        case Outer(S(name: Tree.Ident)) => genSym(name)\n        case Outer(N) => genSym(Tree.Ident(\"outer\"))\n      ) match\n        case ot :: Nil => S(ot)\n        case _ :: rest =>\n          raise(ErrorReport(msg\"Only one outer variable can be bound.\" -> tree.toLoc :: Nil))\n          N\n        case Nil => N\n      \n      if syms.length + outer.count(_ => true) =/= tvs.length then\n        raise(ErrorReport(msg\"Illegal forall annotation.\" -> tree.toLoc :: Nil))\n        Term.Error\n      else\n        given Ctx = ctx ++ boundVars\n        val bds = syms.map:\n          case (sym, ub, lb) =>\n            QuantVar(sym, ub.map(ub => subterm(ub)), lb.map(lb => subterm(lb)))\n        Term.Forall(bds, outer, subterm(body))\n    case InfixApp(lhs, Keywrd(Keyword.`->`), Effectful(eff, rhs)) =>\n      Term.FunTy(subterm(lhs), subterm(rhs), S(subterm(eff)))\n    case InfixApp(lhs, Keywrd(Keyword.`->`), rhs) =>\n      Term.FunTy(subterm(lhs), subterm(rhs), N)\n    case InfixApp(lhs, Keywrd(Keyword.`=>`), rhs) =>\n      lhs match\n      case Tup(_) =>\n        ctx.nest(OuterCtx.LambdaOrHandlerBlock).givenIn:\n          val (syms, nestCtx) = funParams(lhs)\n          Term.Lam(syms, term(rhs)(using nestCtx))\n      case TyTup(tys) =>\n        val constraints = tys.flatMap(maybeConstraint)\n        val body = term(rhs)\n        Term.Constrained(constraints, body)\n    case InfixApp(lhs, Keywrd(Keyword.`as`), rhs) =>\n      Term.Asc(subterm(lhs), subterm(rhs))\n    case InfixApp(lhs, Keywrd(Keyword.`:`), rhs) =>\n      block(tree :: Nil, hasResult = false)._1\n    case PrefixApp(kw @ Keywrd(Keyword.`not`), rhs) =>\n      Term.App(State.builtinOpsMap(\"!\").ref(new Ident(\"not\").withLocOf(kw)), Term.Tup(\n        PlainFld(subterm(rhs, inAppPrefix = true)) :: Nil)(DummyTup))(DummyApp, N, FlowSymbol(\"not-app\"))\n    case tree @ InfixApp(lhs, Keywrd(Keyword.`is` | Keyword.`and` | Keyword.`or`), rhs) =>\n      Term.IfLike(Keyword.`if`, IfLikeForm.ReturningIf, shorthandSplit(tree))\n    case InfixApp(Sel(pre, idn: Ident), Keywrd(Keyword.`#`), idp: Ident) =>\n      val c = subterm(idn)\n      val f = c.symbol.flatMap(_.asCls) match\n        case S(cls: ClassSymbol) =>\n          cls.tree.allSymbols.get(idp.name) match\n          case S(fld: MemberSymbol) => S(fld)\n          case _ =>\n            raise(ErrorReport(msg\"Class '${cls.nme}' does not contain member '${idp.name}'.\" -> idp.toLoc :: Nil))\n            N\n        case _ =>\n          raise(ErrorReport(msg\"Identifier `${idn.name}` does not name a known class symbol.\" -> idn.toLoc :: Nil))\n          N\n      Term.SelProj(subterm(pre), c, idp)(f, FlowSymbol.selProj(idp.name), N, S(summon))\n    case InfixApp(lhs, kw, rhs) =>\n      raise:\n        ErrorReport(msg\"Unexpected infix use of keyword '${kw.name}' here\" -> tree.toLoc :: Nil)\n      Term.Error\n    case OpApp(lhs, Ident(\"|\"), rhs :: Nil) =>\n      Term.CompType(subterm(lhs), subterm(rhs), true)\n    case OpApp(lhs, Ident(\"&\"), rhs :: Nil) =>\n      Term.CompType(subterm(lhs), subterm(rhs), false)\n    case OpApp(lhs, Ident(\":=\"),rhs :: Nil) =>\n      Term.SetRef(subterm(lhs), subterm(rhs))\n    case App(Ident(\"!\"), Tup(rhs :: Nil)) =>\n      Term.Deref(subterm(rhs))\n    case App(Ident(\"~\"), Tup(rhs :: Nil)) =>\n      Term.Neg(subterm(rhs))\n    case App(Ident(\"|\" | \"&\"), Tup(rhs :: Nil)) =>\n      subterm(rhs)\n    case tree @ OpSplit(lhs, rhss) =>\n      val tree = rhss.foldLeft(lhs):\n        case (acc, rhs) =>\n          rhs.splitOn(acc)\n      subterm(tree)\n    case tree @ App(lhs, rhs) =>\n      val sym = FlowSymbol.app()\n      val lt = subterm(lhs, inAppPrefix = true)\n      val rt = subterm(rhs)\n      Term.App(lt, rt)(tree, N, sym)\n    case tree @ OpApp(lhs, op, rhss) =>\n      val sym = FlowSymbol.app()\n      val lt = subterm(lhs, inAppPrefix = true)\n      val ot = subterm(op, inAppPrefix = true)\n      val rts = rhss.map(r => PlainFld(subterm(r)))\n      Term.App(ot, Term.Tup(PlainFld(lt) :: rts)(DummyTup))(\n        DummyApp, N, sym)\n    case SynthSel(pre, nme) =>\n      val preTrm = subterm(pre)\n      val sym = resolveField(nme, preTrm.symbol, nme)\n      Term.SynthSel(preTrm, nme)(sym, FlowSymbol.synthSel(nme.name), N, S(summon)).withLocOf(tree)\n    case Sel(Empty(), nme) =>\n      Term.LeadingDotSel(nme)(S(summon)).withLocOf(tree)\n    case Sel(pre, nme) =>\n      val preTrm = subterm(pre)\n      val sym = resolveField(nme, preTrm.symbol, nme)\n      sym match\n      // * Enforcing [invariant:1]\n      case S(ms: BlockMemberSymbol)\n        // FIXME[Harry]: move the check to resolver because preTrm's symbol may not be resolved yet.\n        if\n          // * If we're selecting a parameterized class method without applying it, an error should be reported.\n          // * Note that module methods are fine to select without applying, since they don't use `this`.\n          !inAppPrefix && ms.isParameterizedMethod && !preTrm.symbol.exists(_.existsModuleful)\n        =>\n        raise:\n          ErrorReport(\n            msg\"[debinding error] Method '${nme.name}' cannot be accessed without being called.\" -> nme.toLoc :: Nil)\n      case S(_) | N => ()\n      if sym.contains(ctx.builtins.source.line) then\n        val loc = tree.toLoc.getOrElse(???)\n        val (line, _, _) = loc.origin.fph.getLineColAt(loc.spanStart)\n        Term.Lit(IntLit(loc.origin.startLineNum + line))\n      else if sym.contains(ctx.builtins.source.name) then\n        Term.Lit(StrLit(ctx.getOuter.map(_.nme).getOrElse(\"\")))\n      else if sym.contains(ctx.builtins.source.file) then\n        val loc = tree.toLoc.getOrElse(???)\n        Term.Lit(StrLit(loc.origin.fileName.toString))\n      else\n        Term.Sel(preTrm, nme)(sym, FlowSymbol.sel(nme.name), N, S(summon))\n    case MemberProj(ct, nme) =>\n      val c = subterm(ct)\n      val f = c.symbol.flatMap(_.asCls) match\n        case S(cls: ClassSymbol) =>\n          cls.tree.allSymbols.get(nme.name) match\n          case S(fld: MemberSymbol) => S(fld)\n          case _ =>\n            raise(ErrorReport(msg\"Class '${cls.nme}' does not contain member '${nme.name}'.\" -> nme.toLoc :: Nil))\n            N\n        case _ =>\n          raise:\n            ErrorReport:\n              msg\"${ct.describe.capitalize} is not a known class.\" -> ct.toLoc ::\n              msg\"Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\" -> N ::\n              msg\"  add a space before ‹identifier› to make it an operator application.\" -> N ::\n              Nil\n          N\n      val self = VarSymbol(Ident(\"self\"))\n      val args = VarSymbol(Ident(\"args\"))\n      val ps = ParamList(ParamListFlags.empty,\n        Param(FldFlags.empty, self, N, Modulefulness.none) :: Nil,\n        S:\n          Param(FldFlags.empty, args, N, Modulefulness.none)\n      )\n      val rs = FlowSymbol.app()\n      Term.Lam(ps,\n        Term.App(Term.SelProj(self.ref(), c, nme)(f, FlowSymbol.selProj(nme.name), N, S(summon)), args.ref())(\n          App(nme, Tup(Nil)) // FIXME\n          , N, rs)\n      )\n    case tree @ Tup(TermDef(Ins, f, N) :: fs) =>\n      Term.CtxTup((f :: fs).map(fld(_)))(tree)\n    case Modified(kw @ Keywrd(Keyword.`mut`), tree @ Tup(fields)) =>\n      Term.Mut(Term.Tup(fields.map(fld(_)))(tree)).mkLocWith(kw)\n    case tree @ Tup(fields) =>\n      Term.Tup(fields.map(fld(_)))(tree)\n      \n    case DynamicNew(Apps(c, args)) =>\n      val (mut, c2) = c match\n        case Modified(Keywrd(Keyword.`mut`), c) => (true, c)\n        case c => (false, c)\n      val base = new Term.DynNew(subterm(c2, inAppPrefix = inAppPrefix), args.map(subterm(_))).withLocOf(tree)\n      if mut then Term.Mut(base) else base\n    // case New(c, rfto) =>\n    //   assert(rfto.isEmpty)\n    //   Term.New(cls(subterm(c), inAppPrefix = inAppPrefix), params.map(subterm(_)), bodo).withLocOf(tree)\n    case ProperNew(body, rfto) => // TODO handle Under\n      lazy val bodo = rfto.map: rft =>\n        val clsSym = new ClassSymbol(DummyTypeDef(syntax.Cls), Ident(\"$anon\"))\n        ctx.nestInner(clsSym).givenIn:\n          clsSym ->\n            // TODO integrate context inherited from cls\n            // TODO make context with var symbols for class parameters\n            ObjBody(block(rft, hasResult = false)._1)\n      body match\n      case S(Apps(c, args)) =>\n        val (mut, c2) = c match\n          case Modified(Keywrd(Keyword.`mut`), c) => (true, c)\n          case c => (false, c)\n        val inner = new Term.New(\n          subterm(c2), // * Note: we'll catch bad `new` targets during type checking\n          args.map(subterm(_)),\n          bodo\n        )(N).withLocOf(tree)\n        if mut then Term.Mut(inner) else inner\n      case N =>\n        Term.New(State.globalThisSymbol.ref().sel(Ident(\"Object\"), S(ctx.builtins.Object)),\n          Nil, bodo)(N).withLocOf(tree)\n      // case _ =>\n      //   raise(ErrorReport(msg\"Illegal new expression.\" -> tree.toLoc :: Nil))\n      \n    case tree: IfLike => split(tree)\n    \n    case Assert(kw, rhs, thno, els) =>\n      val (fl, ln) = kw.toLoc match\n        case S(loc) =>\n          val org = loc.origin\n          (org.fileName.relativeTo(config.baseDir).getOrElse(org.fileName).toString,\n            (org.startLineNum + org.fph.getLineColAt(loc.spanStart)._1).toString)\n        case N => (\"‹unknown›\", \"‹unknown›\")\n      val elsPart = els.fold(PrefixApp(Keywrd(Keyword.`else`), Tree.Trm(\n        State.runtimeSymbol.ref().selNoSym(\"assertFail\")\n          .app(Term.Lit(StrLit(fl)), Term.Lit(StrLit(ln)))\n      )))(PrefixApp.apply.tupled)\n      subterm:\n        IfLike(new Keywrd(Keyword.`if`).withLocOf(kw), Block(\n          InfixApp(rhs, new Keywrd(Keyword.`then`), thno.getOrElse(Unt())) :: elsPart :: Nil))\n      \n    case Quoted(body) => Term.Quoted(subterm(body))\n    case Unquoted(body) => Term.Unquoted(subterm(body))\n    case tree @ Case(kw, _) =>\n      val scrut = VarSymbol(Ident(\"caseScrut\"))\n      val body = caseSplit(scrut, tree)\n      val params = Param(FldFlags.empty, scrut, N, Modulefulness.none) :: Nil\n      Term.Lam(PlainParamList(params), body).mkLocWith(kw)\n    case PrefixApp(kw @ Keywrd(Keyword.`return`), body) =>\n      ctx.getRetHandler match\n      case ReturnHandler.Required(sym) =>\n        log(s\"Non-local return: $sym\")\n        if config.effectHandlers.isEmpty then\n          raise:\n            ErrorReport(msg\"Non-local return statements are only supported with effect handlers enabled.\" -> tree.toLoc :: Nil)\n          Term.Error\n        else\n          val rs = FlowSymbol.app()\n          val retMtdTree = new Ident(\"ret\")\n          val argTree = new Tup(body :: Nil)\n          val dummyIdent = new Ident(\"return\").withLocOf(kw)\n          Term.App(\n            Term.Sel(sym.ref(dummyIdent), retMtdTree)(S(state.nonLocalRet), FlowSymbol.sel(dummyIdent.name), N, S(summon)),\n            Term.Tup(PlainFld(subterm(body)) :: Nil)(argTree)\n          )(App(Sel(dummyIdent, retMtdTree), argTree), N, rs)\n      case ReturnHandler.NotInFunction =>\n        raise:\n          ErrorReport(msg\"Return statements are not allowed outside of functions.\" -> tree.toLoc :: Nil)\n        Term.Error\n      case ReturnHandler.Direct =>\n        Term.Ret(subterm(body))\n      case ReturnHandler.Forbidden =>\n        raise:\n          ErrorReport(msg\"Return statements are not allowed in this context.\" -> tree.toLoc :: Nil)\n        Term.Error\n    case PrefixApp(kw @ Keywrd(Keyword.`throw`), body) =>\n      Term.Throw(subterm(body)).mkLocWith(kw)\n    case PrefixApp(kw @ Keywrd(Keyword.`do`), body) =>\n      Blk(subterm(body) :: Nil, unit).mkLocWith(kw)\n    case PrefixApp(kw @ Keywrd(Keyword.`drop`), body) =>\n      Term.Drop(subterm(body)).mkLocWith(kw)\n    case Region(id: Ident, body) =>\n      val sym = VarSymbol(id)\n      given Ctx = ctx + (id.name -> sym)\n      Term.Region(sym, subterm(body))\n    case RegRef(reg, value) => Term.RegRef(subterm(reg), subterm(value))\n    case Outer(S(_)) =>\n      raise(ErrorReport(msg\"Illegal outer binding.\" -> tree.toLoc :: Nil))\n      Term.Error\n    case Outer(N) => ctx.get(\"outer\") match\n      case S(sym) => sym.ref(Ident(\"outer\"))\n      case N =>\n        raise(ErrorReport(msg\"Illegal outer reference.\" -> tree.toLoc :: Nil))\n        Term.Error\n    case Empty() =>\n      raise(ErrorReport(msg\"A term was expected in this position, but no term was found.\" -> tree.toLoc :: Nil))\n      Term.Error\n    case Error() =>\n      Term.Error\n    case TermDef(k, nme, rhs) =>\n      raise(ErrorReport(msg\"Illegal definition in term position.\" -> tree.toLoc :: Nil))\n      Term.Error\n    case TypeDef(k, head, rhs) =>\n      raise(ErrorReport(msg\"Illegal type declaration in term position.\" -> tree.toLoc :: Nil))\n      Term.Error\n    case Modified(Keywrd(Keyword.`mut`), body: Block) =>\n      blockOrRcd(body, hasResult = true) match\n      case (Blk(Nil, Term.UnitVal()), ctx) =>\n        Rcd(mut = true, Nil).withLocOf(body)\n      case (blk: Blk, ctx) =>\n        raise(ErrorReport(msg\"Expected a record after 'mut' keyword; found a block\" -> blk.toLoc :: Nil))\n        blk\n      case (rcd: Rcd, ctx) => rcd.copy(mut = true).withLocOf(rcd)\n    case Modified(kw, body) =>\n      raise(ErrorReport(msg\"Illegal position for '${kw.name}' modifier.\" -> kw.toLoc :: Nil))\n      subterm(body)\n    case PrefixApp(kw, body) =>\n      raise(ErrorReport(msg\"Illegal position for prefix keyword '${kw.name}'.\" -> kw.toLoc :: Nil))\n      subterm(body)\n    case Jux(lhs, rhs) =>\n      def go(acc: Term, trees: Ls[Tree]): Term =\n        trees match\n        case Nil => acc\n        \n        // * FIXME this `f.name.head.isLetter` test is a big hack...\n        // * TODO would be better to keep the fixity of applications part of the Tree repr.\n        case (ap @ App(f: Ident, tup @ Tup(lhs :: args))) :: trees if !f.name.head.isLetter =>\n          val res = go(acc, lhs :: Nil)\n          val sym = FlowSymbol.app()\n          val fl = Fld(FldFlags.empty, res, N)\n          val app = Term.App(subterm(f, inAppPrefix = true), Term.Tup(\n            fl :: args.map(fld))(tup))(ap, N, sym)\n          go(app, trees)\n        case (ap @ App(f, tup @ Tup(args))) :: trees =>\n          val sym = FlowSymbol.app()\n          go(Term.App(subterm(f, inAppPrefix = true),\n              Term.Tup(Fld(FldFlags.empty, acc, N) :: args.map(fld))(tup)\n            )(ap, N, sym), trees)\n        case Block(sts) :: trees =>\n          go(acc, sts ::: trees)\n        case tree :: trees =>\n          raise(ErrorReport(msg\"Illegal juxtaposition right-hand side (${tree.describe}).\" -> tree.toLoc :: Nil))\n          go(acc, trees)\n      \n      go(subterm(lhs), rhs :: Nil)\n    case Open(op) =>\n      raise(ErrorReport(msg\"Illegal position for 'open' statement.\" -> tree.toLoc :: Nil))\n      Term.Error\n    case OpenIn(op, body) =>\n      subterm(Block(Open(op) :: body :: Nil), inAppPrefix)\n    case DynAccess(obj, rhs) =>\n      rhs match\n      case Bra(bk @ (Round | Square), fld) => Term.DynSel(subterm(obj), subterm(fld), bk is Square)\n      case fld: Literal => Term.DynSel(subterm(obj), subterm(fld), false)\n      case id: Ident =>\n        Term.DynSel(subterm(obj), Term.Lit(StrLit(id.name)).withLocOf(id), false)\n      case _ =>\n        raise(ErrorReport(msg\"Illegal dynamic field access selector (${rhs.describe}).\" -> tree.toLoc :: Nil))\n        Term.Error\n    case Spread(kw, body) =>\n      raise(ErrorReport(msg\"Illegal position for '${kw.name}' spread operator.\" -> kw.toLoc :: Nil))\n      Term.Error\n    case und: Under =>\n      summon[UnderCtx].unders match\n      case N =>\n        raise(ErrorReport(msg\"Illegal position for '_' placeholder.\" -> tree.toLoc :: Nil))\n        Term.Error\n      case S(unds) =>\n        val sym = VarSymbol(Ident(\"_\" + unds.size))\n        unds += sym\n        sym.ref()\n    case Annotated(lhs, rhs) =>\n      annot(lhs).fold(subterm(rhs))(ann =>\n        Term.Annotated(ann, subterm(rhs)))\n    case Keywrd(kw) =>\n      raise(ErrorReport(msg\"Unexpected keyword '${kw.name}' in this position.\" -> tree.toLoc :: Nil))\n      Term.Error\n    case Constructor(delc) =>\n      raise(ErrorReport(msg\"Unsupported constructor in this position.\" -> tree.toLoc :: Nil))\n      Term.Error\n    // case _ =>\n    //   ???\n  \n  def arg(tree: Tree)(using UnderCtx): Ctxl[Term] = tree match\n    case u: Under => subterm(tree) // Note: currently `f(a, _, c)` is treated the same as `f of a, _, c`\n    case _ => term(tree)\n  def fld(tree: Tree)(using UnderCtx): Ctxl[Elem] = tree match\n    case InfixApp(id: Ident, Keywrd(Keyword.`:`), rhs) =>\n      Fld(FldFlags.empty, Term.Lit(StrLit(id.name).withLocOf(id)), S(arg(rhs)))\n    case InfixApp(lhs, Keywrd(Keyword.`:`), rhs) =>\n      Fld(FldFlags.empty, term(lhs), S(arg(rhs)))\n    case Spread(Keywrd(Keyword.`..`), S(trm)) =>\n      Spd(SpreadKind.Lazy, arg(trm))\n    case Spread(Keywrd(Keyword.`...`), S(trm)) =>\n      Spd(SpreadKind.Eager, arg(trm))\n    case _ =>\n      val t = arg(tree)\n      var flags = FldFlags.empty\n      Fld(flags, t, N)\n  \n  def unit: Term.UnitVal = Term.UnitVal()\n  \n  \n  \n  def block(sts: Ls[Tree], hasResult: Bool)(using UnderCtx): Ctxl[(Blk, Ctx)] =\n    block(new Block(sts), hasResult)\n  \n  def block(blk: Block, hasResult: Bool)(using UnderCtx): Ctxl[(Blk, Ctx)] =\n    blockOrRcd(blk, hasResult) match\n    case (blk: Blk, ctx) => (blk, ctx)\n    case (rcd: Rcd, ctx) => (Blk(Nil, rcd), ctx)\n  \n  val supportedOverloadings: Set[(OuterKind, OuterKind)] = Set(\n    Cls -> Mod,\n    Obj -> Mod,\n    Als -> Mod,\n  )\n  val notYetSupportedOverloadings: Set[(OuterKind, OuterKind)] = Set(\n    Fun -> Cls,\n    Fun -> Mod,\n    Pat -> Mod,\n    ImmutVal -> Mod,\n    MutVal -> Mod,\n  )\n  \n  // * Some blocks do not have a meaningful result,\n  // * e.g., constructor blocks or top-level blocks (in MLscript files and diff-tests);\n  // * for these, elaborate with `hasResult = false`, which uses `undefined` as the result\n  // * when there is no other result available. This is fine since the value is never used.\n  // * These useless trailing `undefined`s are then removed by `Lowering`.\n  def blockOrRcd(blk: Block, hasResult: Bool)(using UnderCtx)\n    : Ctxl[(Blk | Rcd, Ctx)]\n    = trace[(Blk | Rcd, Ctx)](\n        pre = s\"Elab block ${blk.desugStmts.toString.truncate(100, \"[...]\")} ${ctx.outer}\", r => s\"~> ${r._1}\"\n      ):\n    \n    val members = blk.definedSymbols.toMap\n    val newSignatureTrees = mutable.Map.empty[Str, Tree] // * Store trees of signatures\n    \n    // * Check for double/incompatible definitions and declarations\n    blk.definedSymbols.foreach: (name, sym) =>\n      if sym.nme === name then // * This is not true when `name` is the symbolic name of a member\n        \n        sym.trees.foreach: td =>\n          td.symbName match\n          case S(R(id)) =>\n            val mem = members.getOrElse(id.name, die)\n            if mem isnt sym then raise:\n              ErrorReport:\n                msg\"Symbolic name '${id.name}' of ${\n                    td.name.fold(_ => \"this definition\", id => \"definition '\" + id.name + \"'\")\n                  } is already used\" -> td.toLoc\n                :: msg\"by sibling member '${mem.nme}'\" -> mem.toLoc\n                :: Nil\n          case _ => ()\n        \n        val defns = sym.trees.collect:\n          case td: TermDef if td.rhs.isDefined && td.name.exists(_.name === name) => td\n          case td: TypeDef if td.name.exists(_.name === name) => td\n        if defns.sizeCompare(1) > 0 then\n          val groups = defns.groupMapReduce(_.k)(_ :: Nil)(_ ::: _)\n          val sortedGroups = groups.toArray.sortBy(_._1)\n          sortedGroups.iterator.foreach: (k, group) =>\n            if group.size > 1 then\n              raise(ErrorReport(msg\"Multiple definitions of symbol '$name'\" -> N ::\n                group.map(msg\"defined here\" -> _.toLoc)))\n            val mainDefn = group.head // * Safe since these `groupMapReduce` groups cannot be empty\n            log(s\"Processing overloadings for '$name'\")\n            defns.iterator.foreach: defn =>\n              if defn.k > k then\n                if !supportedOverloadings(k -> defn.k) then raise:\n                  ErrorReport:\n                    if notYetSupportedOverloadings(k -> defn.k)\n                    then msg\"Not yet supported: overloading of ${k.desc} '$name'\" -> mainDefn.toLoc\n                      :: msg\"with ${defn.k.desc} of the same name\" -> defn.toLoc\n                      :: Nil\n                    else msg\"Illegal overloading of ${k.desc} '$name'\" -> mainDefn.toLoc\n                      :: msg\"with ${defn.k.desc} of the same name\" -> defn.toLoc\n                      :: Nil\n        \n        val decls = sym.trees.collect:\n          case td: TermDef if td.rhs.isEmpty => td\n        if decls.length > 1 then\n          raise(ErrorReport(msg\"Multiple declarations of symbol '$name'\" -> N ::\n            decls.map(msg\"declared here\" -> _.toLoc)))\n        val sig = decls.collectFirst:\n          case td\n            if td.annotatedResultType.isDefined\n            && td.paramLists.isEmpty\n            => td.annotatedResultType.get\n        sig.foreach: sig =>\n          newSignatureTrees += name -> sig\n    \n    // TODO extract this into a separate method\n    // * @param funs:\n    // *  While elaborating a block, we move all function definitions to the top (similar to JS function semantics)\n    @tailrec\n    def go(sts: Ls[Tree], annotations: Ls[Annot], acc: Ls[Statement]): Ctxl[(Blk | Rcd, Ctx)] =\n      /** Call this function when the following term cannot be annotated. */\n      def reportUnusedAnnotations: Unit = if annotations.nonEmpty then raise:\n        WarningReport:\n          msg\"This annotation has no effect\" -> (annotations.foldLeft[Opt[Loc]](N):\n            case (acc, ann) => acc match\n              case N => ann.toLoc\n              case S(loc) => S(loc ++ ann.toLoc)\n          ) :: (sts.headOption match\n            case N => msg\"A target term is expected at the end of block\" -> blk.toLoc.map(_.right)\n            case S(head) => msg\"Annotations are not supported on ${head.describe} terms.\" -> head.toLoc\n          ) :: Nil\n      sts match\n      case Nil =>\n        reportUnusedAnnotations\n        (mkBlk(acc, N, hasResult), ctx)\n      case Constructor(Block(ctors)) :: sts =>\n        // TODO properly handle (it currently desugars to sibling classes)\n        go(sts, annotations, acc)\n      case Open(bod) :: sts =>\n        reportUnusedAnnotations\n        bod match\n          case Jux(bse, Block(sts)) =>\n            some(bse -> some(sts))\n          // * There could be other shapes of open statements...\n          case bse: Ident =>\n            some(bse -> N)\n          case _ =>\n            raise(ErrorReport(msg\"Illegal 'open' statement shape.\" -> bod.toLoc :: Nil))\n            N\n        match\n        case N => go(sts, annotations, acc)\n        case S((base, importedTrees)) =>\n          base match\n          case baseId: Ident =>\n            ctx.get(baseId.name) match\n            case S(baseElem) =>\n              val importedNames = importedTrees match\n                case N => // \"wilcard\" open\n                  baseElem.symbol match\n                  case S(sym: BlockMemberSymbol) if sym.modOrObjTree.isDefined =>\n                    sym.modOrObjTree.get.definedSymbols.map:\n                      case (nme, sym) => nme -> Ctx.SelElem(baseElem, sym.nme, S(sym), isImport = true)\n                  case _ =>\n                    raise(ErrorReport(msg\"Wildcard 'open' not supported for this kind of symbol.\" -> baseId.toLoc :: Nil))\n                    Nil\n                case S(sts) => sts.flatMap:\n                  case id: Ident =>\n                    if ctx.env.contains(id.name) then\n                      raise(WarningReport(msg\"Imported name '${id.name}' is shadowed by a name already defined in the same scope\" -> id.toLoc :: Nil))\n                    val sym = resolveField(id, baseElem.symbol, id)\n                    val e = Ctx.SelElem(baseElem, id.name, sym, isImport = true)\n                    id.name -> e :: Nil\n                  case t =>\n                    raise(ErrorReport(msg\"Illegal 'open' statement element.\" -> t.toLoc :: Nil))\n                    Nil\n              (ctx elem_++ importedNames).givenIn:\n                go(sts, Nil, acc)\n            case N =>\n              raise(ErrorReport(msg\"Name not found: ${baseId.name}\" -> baseId.toLoc :: Nil))\n              go(sts, Nil, acc)\n          case _ =>\n            raise(ErrorReport(msg\"Illegal 'open' statement base.\" -> base.toLoc :: Nil))\n            go(sts, Nil, acc)\n      case (m @ PrefixApp(Keywrd(Keyword.`import`), arg)) :: sts =>\n        reportUnusedAnnotations\n        val pathAndAlias: Opt[(Tree, Opt[Ident])] = arg match\n          case InfixApp(pathArg, Keywrd(Keyword.`as`), alias: Ident) => S((pathArg, S(alias)))\n          case InfixApp(pathArg, Keywrd(Keyword.`as`), Error()) => N\n          case InfixApp(_, Keywrd(Keyword.`as`), badAlias) =>\n            raise(ErrorReport(\n              msg\"Expected identifier after 'as' in import statement\" ->\n              badAlias.toLoc :: Nil))\n            N\n          case pathArg => S((pathArg, N))\n        val (newCtx, newAcc) = pathAndAlias match\n          case S((StrLit(path), alias)) =>\n            val stmt = importPath(path, alias).withLocOf(m)\n            (ctx + (stmt.sym.nme -> stmt.sym),\n              stmt :: acc)\n          case S((pathArg, _)) =>\n            raise(ErrorReport(\n              msg\"Expected string literal after 'import' keyword\" ->\n              pathArg.toLoc :: Nil))\n            (ctx, acc)\n          case N => // errors have been reported above.\n            (ctx, acc)\n        newCtx.givenIn:\n          go(sts, Nil, newAcc)\n      \n      case Spread(Keywrd(Keyword.`...`), S(body)) :: sts =>\n        reportUnusedAnnotations\n        go(sts, Nil, RcdSpread(term(body)) :: acc)\n      case InfixApp(lhs, Keywrd(Keyword.`:`), rhs) :: sts =>\n        var newCtx = ctx\n        val (rlhs, rhs_t) = rhs match\n          case _: Under => (lhs, subterm(rhs))\n          case _ =>\n            lhs match\n            case Apps(base, tups) =>\n              val rrhs = tups.foldRight(rhs):\n                InfixApp(_, Keywrd(Keyword.`=>`), _)\n              (base, term(rrhs))\n        val newAcc = rlhs match\n          case id: Ident =>\n            val sym = new VarSymbol(id)\n            newCtx += id.name -> sym\n            RcdField(Term.Lit(StrLit(id.name)).withLocOf(id), sym.ref(id))\n              :: DefineVar(sym, rhs_t)\n              :: LetDecl(sym, annotations)\n              :: acc\n          case lit: Literal =>\n            reportUnusedAnnotations\n            RcdField(Term.Lit(lit).withLocOf(lit), rhs_t) :: acc\n          case Bra(Round, inner) =>\n            reportUnusedAnnotations\n            RcdField(term(inner), rhs_t) :: acc\n          case _ =>\n            raise(ErrorReport(msg\"Unexpected record key shape.\" -> rlhs.toLoc :: Nil))\n            RcdField(Term.Error, rhs_t) :: acc\n        newCtx.givenIn:\n          go(sts, Nil, newAcc)\n      case (hd @ LetLike(kw @ Keywrd(`let`), Apps(id: Ident, tups), rhso, N)) :: sts\n      if tups.isEmpty || id.name.headOption.exists(_.isLower) =>\n        val sym =\n          fieldOrVarSym(LetBind, id)\n        log(s\"Processing `let` statement $id (${sym}) ${ctx.outer}\")\n        members.get(id.name).foreach: s =>\n          raise(ErrorReport(msg\"Name '${id.name}' is already used\"\n            -> hd.toLoc :: msg\"by a member declared in the same block\" -> s.toLoc :: Nil))\n        val newAcc = rhso match\n          case S(rhs) =>\n            val rrhs = tups.foldRight(rhs):\n              InfixApp(_, Keywrd(Keyword.`=>`), _)\n            mkLetBinding(kw, sym, term(rrhs), annotations) reverse_::: acc\n          case N =>\n            if tups.nonEmpty then\n              raise(ErrorReport(msg\"Expected a right-hand side for let bindings with parameters\" -> hd.toLoc :: Nil))\n            LetDecl(sym, annotations).mkLocWith(kw) :: acc\n        (ctx + (id.name -> sym)) givenIn:\n          go(sts, Nil, newAcc)\n      case (tree @ LetLike(Keywrd(`let`), lhs, _, N)) :: sts =>\n        raise(ErrorReport(msg\"Unsupported let binding shape\" -> tree.toLoc :: Nil))\n        go(sts, Nil, Term.Error :: acc)\n      case Def(lhs, rhs) :: sts =>\n        reportUnusedAnnotations\n        lhs match\n        case id: Ident =>\n          val r = term(rhs)\n          ctx.get(id.name) match\n          case S(elem) =>\n            elem.symbol match\n            case S(sym: LocalSymbol) => go(sts, Nil, DefineVar(sym, r) :: acc)\n          case N =>\n            // TODO lookup in members? inherited/refined stuff?\n            raise(ErrorReport(msg\"Name not found: ${id.name}\" -> id.toLoc :: Nil))\n            go(sts, Nil, Term.Error :: acc)\n        case App(base, args) =>\n          go(Def(base, InfixApp(args, Keywrd(Keyword.`=>`), rhs)) :: sts, Nil, acc)\n        case _ =>\n          raise(ErrorReport(msg\"Unrecognized definitional assignment left-hand side: ${lhs.describe}\"\n            -> lhs.toLoc :: Nil)) // TODO BE\n          go(sts, Nil, Term.Error :: acc)\n      case (td @ TermDef(k, nme, rhs)) :: sts =>\n        log(s\"Processing term definition $nme\")\n        td.symbName match\n        case S(L(d)) => raise(d)\n        case _ => ()\n        td.name match\n          case R(id) =>\n            val sym = members.getOrElse(id.name, die)\n            val owner = ctx.outer.inner\n            if owner.isDefined && !identifierPattern.matches(id.name) then\n              raise:\n                ErrorReport:\n                  msg\"Illegal member ${k.desc} name: '${id.name}'\" -> nme.toLoc\n                  :: illegalMemberNameTail\n              return go(sts, Nil, acc)\n            val isMethod = owner.exists(_.isInstanceOf[ClassSymbol])\n            val tdf = ctx.nest(OuterCtx.NonReturnContext).givenIn: newCtx ?=>\n              // * Add type parameters to context\n              val (tps, newCtx1) = td.typeParams match\n                case S(t) => \n                  val (tps, ctx) = typeParams(t)\n                  (S(tps), ctx)\n                case N => (N, ctx)\n              // * Add parameters to context\n              var newCtx = newCtx1\n              val pss = td.paramLists.map: ps =>\n                val (res, newCtx2) = funParams(ps)(using newCtx)\n                newCtx = newCtx2\n                res\n              // * Elaborate signature\n              val st = td.annotatedResultType.orElse(newSignatureTrees.get(id.name))\n              val s = st.map:\n                // unwrap possible module modifier\n                // e.g, `fun f: module M`\n                //              ^^^^^^\n                case TypeDef(Mod, st, N) => term(st)(using newCtx)\n                case st => term(st)(using newCtx)\n              val body: Opt[Term] = rhs match\n                case N => N\n                case _ if ctx.mode is Mode.Light => S(Term.Missing)\n                case S(rhs) => S:\n                  val nonLocalRetHandler = TempSymbol(N, s\"nonLocalRetHandler$$${id.name}\")\n                  newCtx.nest(OuterCtx.Function(nonLocalRetHandler)).givenIn: newCtx ?=>\n                    val b = term(rhs)(using newCtx)\n                    if nonLocalRetHandler.directRefs.isEmpty then b else\n                      val clsSym = ClassSymbol(DummyTypeDef(Cls), Ident(\"‹non-local return effect›\"))\n                      val valueSym = VarSymbol(Ident(\"value\"))\n                      val resumeSym = VarSymbol(Ident(\"resume\"))\n                      val mtdSym = BlockMemberSymbol(\"ret\", Nil, true)\n                      val tsym = TermSymbol(Fun, N, Ident(\"ret\"))\n                      val td = TermDefinition(\n                        Fun, mtdSym, tsym, PlainParamList(Param(FldFlags.empty, valueSym, N, Modulefulness.none) :: Nil) :: Nil,\n                        N, N, S(valueSym.ref(Ident(\"value\"))), TermDefFlags.empty, Modulefulness.none, Nil, N)\n                      tsym.defn = S(td)\n                      mtdSym.tsym = S(tsym)\n                      val htd = HandlerTermDefinition(resumeSym, td)\n                      Term.Handle(nonLocalRetHandler, state.nonLocalRetHandlerTrm, Nil, clsSym, htd :: Nil, b)\n              val r = FlowSymbol(s\"‹result of ${sym}›\")\n              \n              val mfn = st match\n                // st.isModified(Mod) indicates if the function marks\n                // its result as \"module\". e.g, `fun f: module M`\n                //                                      ^^^^^^\n                case S(st) if st.isModified(Mod) => \n                  Modulefulness.ofSign(s)(true)\n                case _ =>\n                  Modulefulness.none\n              \n              val tsym = TermSymbol(k, owner, id) // TODO?\n              val tdf = TermDefinition(k, sym, tsym, pss, tps, s, body, \n                TermDefFlags.empty.copy(isMethod = isMethod), mfn, annotations, N).withLocOf(td)\n              tsym.defn = S(tdf)\n              sym.tsym = S(tsym)\n              \n              tdf\n            go(sts, Nil, tdf :: acc)\n          case L(d) =>\n            reportUnusedAnnotations\n            raise(d)\n            go(sts, Nil, acc)\n      case (td @ TypeDef(k, head, rhs)) :: sts =>\n        val owner = ctx.outer.inner\n        \n        assert((k is Als) || (k is Cls) || (k is Mod) || (k is Obj) || (k is Pat), k)\n        val body = td.withPart\n        \n        td.symbName match\n        case S(L(d)) => raise(d)\n        case _ => ()\n        val nme = td.name match\n          case R(id) => id\n          case L(d) =>\n            raise(d)\n            return go(sts, Nil, acc)\n        \n        if owner.isDefined && !identifierPattern.matches(nme.name) then\n          raise:\n            ErrorReport:\n              msg\"Illegal member ${k.desc} name: '${nme.name}'\" -> nme.toLoc\n              :: illegalMemberNameTail\n          return go(sts, Nil, acc)\n        \n        val sym = members.getOrElse(nme.name, lastWords(s\"Symbol not found: ${nme.name}\"))\n        \n        val outerCtx = ctx\n        \n        var newCtx = S(td.symbol).collectFirst:\n            case s: InnerSymbol => s\n          .fold(ctx.nest(OuterCtx.NonReturnContext))(ctx.nestInner(_))\n        \n        val tps = td.typeParams match\n          case S(ts) =>\n            ts.tys.flatMap: targ =>\n              val (id, vce) = targ match\n                case id: Ident =>\n                  (id, N)\n                case Modified(Keywrd(Keyword.`in`), id: Ident) =>\n                  (id, S(false))\n                case Modified(Keywrd(Keyword.`out`), id: Ident) =>\n                  (id, S(true))\n              val vs = VarSymbol(id)\n              val res = TyParam(FldFlags.empty, vce, vs)\n              vs.decl = S(res)\n              res :: Nil\n          case N => Nil\n        \n        newCtx ++= tps.map(tp => tp.sym.name -> tp.sym) // TODO: correct ++?\n        \n        val isDataClass = annotations.exists:\n          case Annot.Modifier(Keyword.`data`) => true\n          case _ => false\n        \n        val pss = td.paramLists.map: ps =>\n          val (res, newCtx2) =\n            given Ctx = newCtx\n            params(ps, isDataClass, k is Pat)\n          newCtx = newCtx2\n          res\n        \n        def withFields(using Ctx)(fn: (Ctx) ?=> (Term.Blk, Ctx)): (Term.Blk, Ctx) =\n          softAssert(pss.sizeCompare(td.clsParams) === 0,\n            s\"mismatched parameter list numbers ${pss} vs ${td.clsParams}\")\n          val fields: Ls[Statement] = pss.zip(td.clsParams).flatMap: (ps, cps) =>\n            // TODO: handle this gracefully (could be caused by erroneous input code)\n            softTODO(ps.params.sizeCompare(cps) === 0,\n              s\"mismatched param list lengths ${ps.params} vs ${cps}\")\n            ps.params.zip(cps).flatMap: (p, cp) =>\n              // For class-like types, \"desugar\" the parameters into additional class fields.\n              \n              val owner = td.symbol match\n                // Any MemberSymbol should be an InnerSymbol, except for TypeAliasSymbol, \n                // but type aliases should not call this function.\n                case s: InnerSymbol => S(s)\n                case _: TypeAliasSymbol => die\n              \n              if p.flags.isVal || isDataClass\n              then\n                val k = if p.flags.mut then MutVal else ImmutVal\n                val fsym = BlockMemberSymbol(p.sym.nme, Nil)\n                val tsym = cp\n                cp.decl = S(p)\n                val fdef = TermDefinition(\n                  k,\n                  fsym,\n                  tsym,\n                  Nil, N, N,\n                  S(p.sym.ref()),\n                  TermDefFlags.empty.copy(isMethod = (k is Cls)),\n                  p.modulefulness,\n                  Nil,\n                  N,\n                ).withLocOf(p)\n                assert(p.fldSym.isEmpty)\n                p.fldSym = S(fsym)\n                fsym.tsym = S(tsym)\n                tsym.defn = S(fdef)\n                fdef :: Nil\n              else\n                val psym = TermSymbol(LetBind, owner, p.sym.id)\n                val decl = LetDecl(psym, Nil)\n                val defn = DefineVar(psym, p.sym.ref())\n                p.fldSym = S(psym)\n                decl :: defn :: Nil\n          \n          val ctxWithFields =\n            val valParams = fields.collect:\n              case f: TermDefinition =>\n                f.sym.nme -> f.sym\n            val params = fields.collect:\n              case (f: LetDecl) =>\n                f.sym.nme -> f.sym\n            ctx.withMembers(valParams) ++ params\n          \n          val (blk, c) = fn(using ctxWithFields)\n          val blkWithFields: Blk = blk.copy(stats = fields ::: blk.stats)\n          ObjBody.extractMembers(blkWithFields) match\n            case R(_) =>\n              (blkWithFields, c)\n            case L(errs) =>\n              errs.foreach(raise)\n              (blk, c)\n        \n        def mkBody(using Ctx) = withFields:\n          body match\n          case N | S(Error()) => (new Blk(Nil, Term.Lit(UnitLit(false))), ctx)\n          case S(b: Block) => block(b, hasResult = false)\n          case S(t) =>\n            raise(ErrorReport(\n              msg\"Illegal body of ${k.desc} definition (should be a block; found ${t.describe}).\" -> t.toLoc :: Nil))\n            (new Blk(Nil, Term.Lit(UnitLit(false))), ctx)\n        \n        val defn = k match\n        case Als =>\n          val alsSym = td.symbol.asInstanceOf[TypeAliasSymbol] // TODO improve `asInstanceOf`\n          // newCtx.nest(S(alsSym)).givenIn:\n          newCtx.nestLocal.givenIn:\n            assert(pss.isEmpty)\n            assert(body.isEmpty)\n            val d =\n              given Ctx = newCtx\n              semantics.TypeDef(alsSym, sym, tps, rhs.map(term(_)), N, annotations)\n            alsSym.defn = S(d)\n            d\n        case Pat =>\n          val patSym = td.symbol.asInstanceOf[PatternSymbol] // TODO improve `asInstanceOf`\n          newCtx.givenIn:\n            if pss.length > 1 then raise:\n                ErrorReport:\n                  msg\"Multiple parameter lists are not supported for this definition.\" ->\n                    td.toLoc :: Nil\n            // Pattern definition should not have a body like class definition.\n            assert(body.isEmpty)\n            val ps = pss.headOption\n            val allParams = ps.fold(Nil):\n              _.params.flatMap:\n                // Only `pat` flag is `true`.\n                case p @ Param(flags = FldFlags(false, false, true, false)) => S(p)\n                // All flags are `false`.\n                case p @ Param(flags = FldFlags(false, false, false, false)) => S(p)\n                case Param(flags, sym, _, _) =>\n                  raise(ErrorReport(msg\"Unexpected pattern parameter ${sym.name} with modifiers: ${flags.show}\" -> sym.toLoc :: Nil))\n                  N\n            // The following iteration filters out:\n            // 1. pattern parameters, e.g., `T` in `pattern Nullable(pattern T) = ...`;\n            // 2. extraction bindings, e.g., `value` in `pattern Middle(value) = ...`; and\n            // 3. the rest are reported as invalid parameters.\n            val (patternParams, extractionParams) = allParams.partition(_.flags.pat)\n            log(s\"`${patSym.nme}`'s pattern parameters: ${patternParams.mkString(\"[\", \", \", \"]\")}\")\n            log(s\"`${patSym.nme}`'s extraction parameters: ${extractionParams.mkString(\"[\", \", \", \"]\")}\")\n            // Empty pattern body is considered as wildcard patterns.\n            val rhs = td.rhs.getOrElse:\n              raise(ErrorReport(msg\"Pattern definitions must have a body.\" -> td.toLoc :: Nil))\n              Tree.Under()\n            // Elaborate the pattern body with the pattern parameters.\n            val pat = pattern(rhs)(using ctx ++ patternParams.iterator.map(p => p.sym.name -> p.sym))\n            // Report all invalid variables we found in the top-level pattern.\n            pat.variables.report\n            // Note that the remaining variables have not been bound to any\n            // `VarSymbol` yet. Thus, we need to pair them with the extraction\n            // parameters. We only report warnings for unbound variables\n            // because they are harmless. Variables used in guard conditions\n            // (from `where` clauses) are not considered useless.\n            val guardedNames = pat.varNamesUsedInGuards\n            pat.variables.varMap.foreach: (name, aliases) =>\n              extractionParams.find(_.sym.name == name) match\n                case S(param) => aliases.foreach(_.symbol = param.sym)\n                case N if !guardedNames.contains(name) =>\n                  raise(WarningReport(msg\"Unused pattern binding: $name.\" -> aliases.head.toLoc :: Nil))\n                case _ => ()\n            scoped(\"ucs:ups\")(log(s\"elaborated pattern body: ${pat.showDbg}\"))\n            scoped(\"ucs:ups:tree\")(log(s\"elaborated pattern body: ${pat.showAsTree}\"))\n            // `paramsOpt` is set to `N` because we don't want parameters to\n            // appear in the generated class's constructor.\n            val pd = PatternDef(owner, patSym, sym, tps, allParams,\n              patternParams, extractionParams, pat, annotations)\n            patSym.defn = S(pd)\n            pd\n        case k: (Mod.type | Obj.type) =>\n          val modSym = td.symbol.asInstanceOf[ModuleOrObjectSymbol] // TODO: improve `asInstanceOf`\n          newCtx.givenIn:\n            trace(s\"Processing module/object definition $nme\"):\n              val comp = sym.asCls match\n                case comp @ S(_) =>\n                  assert(sym.asAls.isEmpty)\n                  comp\n                case N => sym.asAls\n              log(s\"Companion: ${comp}\")\n              val md =\n                val (bod, c) = mkBody\n                ModuleOrObjectDef(owner, modSym, sym,\n                  tps, pss.headOption, pss.tailOr(Nil), newOf(td), k, ObjBody(bod), comp, annotations)(outerCtx.scope)\n              modSym.defn = S(md)\n              md\n        case Cls =>\n          val clsSym = td.symbol.asInstanceOf[ClassSymbol] // TODO: improve `asInstanceOf`\n          newCtx.givenIn:\n            trace(s\"Processing class definition $nme\"):\n              val comp = sym.asMod\n              log(s\"Companion: ${comp}\")\n              val tsym = if pss.nonEmpty then\n                val ctsym = TermSymbol(Fun, S(clsSym), clsSym.id)\n                val ctdef =\n                  TermDefinition(\n                    Fun,\n                    sym,\n                    ctsym,\n                    pss,\n                    S(tps.map(tp => Param(FldFlags.empty, tp.sym, N, Modulefulness.none))),\n                    S(clsSym.ref()),\n                    N,\n                    TermDefFlags.empty,\n                    Modulefulness.none,\n                    annotations.collect: \n                      case a @ Annot.Modifier(Keyword.`declare`) => a\n                    ,\n                    S(clsSym),\n                  )\n                ctsym.defn = S(ctdef)\n                sym.tsym = S(ctsym)\n                S(ctsym)\n              else N\n              val cd =\n                val (bod, c) = mkBody\n                ClassDef(owner, Cls, clsSym, sym, tsym, tps, pss, newOf(td), ObjBody(bod), annotations, comp)\n              clsSym.defn = S(cd)\n              cd\n        go(sts, Nil, defn :: acc)\n      case Annotated(annotation, target) :: sts =>\n        go(target :: sts, annotations ++ annot(annotation), acc)\n      // * With tight right precedence, `#config(args)` is parsed as `App(Directive(config, Tup()), Tup(args))`.\n      // * Reconstruct as `Directive(config, Tup(args))` and re-process.\n      case App(Directive(prefix, _), args) :: sts =>\n        go(Directive(prefix, args) :: sts, annotations, acc)\n      case Directive(Ident(\"config\"), Tup(args)) :: sts =>\n        reportUnusedAnnotations\n        val modify = ConfigParser.parseOverrides(args)\n        go(sts, Nil, SetConfig(modify) :: acc)\n      case Directive(Ident(name), _) :: sts =>\n        raise(ErrorReport(\n          msg\"Unknown directive '#${name}'\" -> sts.headOption.flatMap(_.toLoc) :: Nil,\n          source = Diagnostic.Source.Compilation))\n        go(sts, annotations, acc)\n      case (dir @ Directive(prefix, _)) :: sts =>\n        raise(ErrorReport(\n          msg\"Expected a directive name after '#', but found ${prefix.describe}\" -> prefix.toLoc :: Nil,\n          source = Diagnostic.Source.Compilation))\n        go(sts, annotations, acc)\n      case (st: Tree) :: sts =>\n        // TODO reject plain term statements? Currently, `(1, 2)` is allowed to elaborate (tho it should be rejected in type checking later)\n        val res = annotations.foldLeft(term(st)):\n          case (acc, ann) => Term.Annotated(ann, acc)\n        sts match\n        case Nil => (mkBlk(acc, S(res), hasResult), ctx)\n        case _ => go(sts, Nil, res :: acc)\n    end go\n    \n    ctx.withMembers(members).givenIn:\n      go(blk.desugStmts, Nil, Nil)\n  \n  \n  def mkBlk(acc: Ls[Statement], res: Opt[Term], hasResult: Bool): Blk | Rcd =\n    // TODO forbid certain kinds of terms in records\n    val isRcd = acc.exists:\n      case _: (RcdField | RcdSpread) => true\n      case _ => false\n    if isRcd then Term.Rcd(mut = false, (res.toList ::: acc).reverse)\n    else Blk(acc.reverse, res.getOrElse:\n      if hasResult\n        then unit\n        else Term.Lit(UnitLit(false))\n    )\n  \n  def newOf(td: TypeDef): Ctxl[Opt[Term.New]] =\n    td.extension\n    match\n    case S(ext) => S(term(ProperNew(S(ext), N)))\n    case N => N\n    match\n    case S(n: Term.New) => S(n)\n    case S(trm) =>\n      raise:\n        ErrorReport:\n          msg\"Unexpected shape of extension clause: ${trm.describe}\" -> trm.toLoc :: Nil\n      N\n    case N => N\n  \n  def fieldOrVarSym(k: TermDefKind, id: Ident)(using Ctx): TermSymbol | VarSymbol =\n    if ctx.outer.inner.isDefined then TermSymbol(k, ctx.outer.inner, id)\n    else VarSymbol(id)\n  \n  def param(t: Tree, inUsing: Bool, inDataClass: Bool): Ctxl[Diagnostic \\/ (Param, Opt[SpreadKind])] =\n    t.desugared.asParam(inUsing).map:\n      case pt @ ParamTree(flags, id, sign, spd, modifiers) =>\n        log(s\"Elaborating ParamTree: ${pt}\")\n        val flg = flags.copy(isVal = flags.isVal || inDataClass)\n        val sym = VarSymbol(id)\n        val sig = sign.map(term(_))\n        val p = Param(flg, sym, sig, Modulefulness.ofSign(sig)(Mod in modifiers))\n        sym.decl = S(p)\n        (p, spd)\n  \n  def funParams(t: Tree): Ctxl[(ParamList, Ctx)] =\n    val ps_ctx = params(t, inDataClass = false, inPattern = false)\n    def checkFlags(p: Param): Unit =\n      if p.flags.isVal || p.flags.mut then\n        raise(ErrorReport(msg\"Illegal function parameter modifiers: ${p.flags.show}\" -> p.sym.toLoc :: Nil))\n    ps_ctx._1.params.foreach(checkFlags)\n    ps_ctx._1.restParam.foreach(checkFlags)\n    ps_ctx\n  \n  /** Elaborate a subtyping constraint. */\n  def constraint(lhs: Tree, op: \"<:<\" | \">:>\", rhs: Tree): Ctxl[SubConstraint] =\n    val l = term(lhs)\n    val r = term(rhs)\n    val dir = op match\n      case \"<:<\" => SubDir.Sub\n      case \">:>\" => SubDir.Sup\n    SubConstraint(l, r, dir)\n \n  /** Elaborate a subtyping constraint that may be malformed. */\n  def maybeConstraint(t: Tree): Ctxl[Option[SubConstraint]] =\n    t match\n    case OpApp(lhs, Ident(op : (\"<:<\" | \">:>\")), rhs :: Nil) =>\n      S(constraint(lhs, op, rhs))\n    case _ =>\n      raise(ErrorReport(msg\"Illegal constraint syntax.\" -> t.toLoc :: Nil))\n      N\n\n  /** Elaborate a parameter list of a term or a definition.\n   * @param inDataClass Whether the parameter list belongs to a data class.\n   * @param inPattern Whether the parameter list belongs to a pattern definition.\n   *                  If `inPattern` is `true`, only parameters with `pat` flag\n   *                  will be added to the context.\n   */\n  def params(t: Tree, inDataClass: Bool, inPattern: Bool): Ctxl[(ParamList, Ctx)] = t match\n    case Tup(ps) =>\n      def go(ps: Ls[Tree], acc: Ls[Param], ctx: Ctx, flags: ParamListFlags): (ParamList, Ctx) =\n        ps match\n        case Nil => (ParamList(flags, acc.reverse, N).withLocOf(t), ctx)\n        case hd :: tl =>\n          val isCtxParam = hd.isModified(Ins)\n          val inUsing = flags.ctx || isCtxParam\n          param(hd, inUsing, inDataClass)(using ctx) match\n          case R((p, spd)) =>\n            if isCtxParam && acc.nonEmpty then\n              raise(ErrorReport(msg\"Keyword `using` must occur before all parameters.\" -> hd.toLoc :: Nil))\n            val newCtx = if !inPattern || p.flags.pat then ctx + (p.sym.name -> p.sym) else ctx\n            val newFlags = flags.copy(ctx = inUsing)\n            spd match\n            case S(spd) =>\n              if spd is SpreadKind.Lazy then\n                raise(ErrorReport(msg\"Lazy spread parameters not allowed.\" -> hd.toLoc :: Nil))\n              if tl.isEmpty then \n                (ParamList(flags, acc.reverse, S(p)).withLocOf(t), newCtx)\n              else\n                raise(ErrorReport(msg\"Spread parameters must be the last in the parameter list.\" -> hd.toLoc :: Nil))\n                go(tl, p :: acc, newCtx, newFlags)\n            case N => go(tl, p :: acc, newCtx, newFlags)\n          case L(d) => raise(d); go(tl, acc, ctx, flags)\n      go(ps, Nil, ctx, ParamListFlags.empty)\n  \n  def ident(id: Ident)(using Ctx): Ctxl[Opt[Term]] = ctx.get(id.name) match\n    case S(elem) => S(elem.ref(id))\n    case N =>\n      state.builtinOpsMap.get(id.name) match\n      case S(bi) => S(bi.ref(id))\n      case N => N\n  \n  def pattern(t: Tree): Ctxl[Pattern] =\n    import ucs.{Ctor, unapply, error}, ucs.extractors.*, Keyword.*, Pattern.*, InvalidReason.*\n    given TraceLogger = tl\n    /** String range bounds must be single characters. */\n    def isInvalidStringBounds(lo: StrLit, hi: StrLit)(using Raise): Bool =\n      val ds = collection.mutable.Buffer.empty[(Message, Option[Loc])]\n      if lo.value.length =/= 1 then\n        ds += msg\"The lower bound of character ranges must be a single character.\" -> lo.toLoc\n      if hi.value.length =/= 1 then\n        ds += msg\"The upper bound of character ranges must be a single character.\" -> hi.toLoc\n      if ds.nonEmpty then error(ds.toSeq*)\n      ds.nonEmpty\n    /** Resolve an identifier. We need to perform a very preliminary check to\n     *  determine whether this identifier refers to a pattern, a class, an\n     *  object, or creates a new binding.\n     * \n     *  FIXME: This routine is insufficient to look up definitions defined\n     *  later in the program. */\n    def ident(id: Ident)(using Ctx): Ctxl[Opt[Term]] = scoped(\"ucs:pattern:resolution\"):\n      log(s\"resolve ${id}\")\n      ctx.get(id.name) match\n      case S(elem) =>\n        log(\"has elem!\")\n        elem.symbol.flatMap:\n          case vs: VarSymbol => vs.decl match\n            case S(d) if d.isPatternConstructor => S(elem.ref(id))\n            case S(_) | N => N\n          case sym: Symbol => sym.asCls.orElse(sym.asObj).orElse(sym.asPat) match\n            case S(_) => S(elem.ref(id))\n            case N => N\n      case N =>\n        state.builtinOpsMap.get(id.name) match\n        case S(bi) => S(bi.ref(id))\n        case N => N\n    /** Elaborate arrow patterns like `p => t`. Meanwhile, report all invalid\n     *  variables we found in `p`. */\n    def arrow(lhs: Tree, rhs: Tree): Ctxl[Pattern] =\n      val pattern = go(lhs)\n      // The symbol allocated here will be bound in `split` to the values\n      // destructed from the scrutinee.\n      val variables = pattern.variables.allocate\n      // The `VarSymbol` created here is used as the parameters of the\n      // lambda expression generated by extraction (such as `p => t`).\n      // To avoid duplicating `t`, we generate a lambda function before the\n      // branch starts, which will be called if the `split` succeeds.\n      // - `contextEntries` will be added to the context\n      // - `correspondence` is mapping from symbols representing variables\n      //   in the pattern to symbols for parameters to be used in the `term`.\n      val (contextEntries, correspondence) = variables.iterator.map:\n        case (name, symbol) =>\n          // We create a symbol specifically for `Param` for each variable to\n          // avoid redundantly redeclaring symbols in `Scope` during code\n          // generation, which triggers the assertion in `Scope.addToBindings`.\n          val parameterSymbol = VarSymbol(new Ident(symbol.name))\n          (name -> parameterSymbol, symbol -> parameterSymbol)\n      .toList.unzip\n      pattern.variables.report // Report all invalid variables we found in `pattern`.\n      Transform(pattern, correspondence, term(rhs)(using ctx ++ contextEntries))\n    /** Elaborate tuple patterns like `[p1, p2, ...ps, pn]`. */\n    def tuple(ts: Ls[Tree]): Ctxl[Pattern.Tuple] =\n      // We are accumulating two components: the leading patterns, the spread\n      // part including the trailing patterns.\n      val z = (Ls[Pattern](), N: Opt[(SpreadKind, Pattern, Ls[Pattern])])\n      val (leading, spread) = ts.foldLeft(z):\n        case (acc @ (_, S(_)), t: Spread) =>\n          // Found two `...p`s in the same tuple pattern. Report an error.\n          raise(ErrorReport(msg\"Multiple spread patterns are not supported.\" -> t.toLoc :: Nil))\n          acc // Do not modify the accumulator and skip this `Spread`.\n        case ((leading, N), Spread(ellipsis, S(t))) =>\n          // Found `...p`, elaborate `p` and assign it to the spread pattern.\n          (leading, S(SpreadKind.fromKw(ellipsis), go(t), Nil))\n        case ((leading, N), Spread(ellipsis, N)) =>\n          // Found `...` (no following patterns), which means the spread part\n          // will not be further matched. Set the spread pattern to `Wildcard`.\n          (leading, S(SpreadKind.fromKw(ellipsis), Wildcard(), Nil))\n        case ((leading, N), t) => \n          // Found a tuple field while the spread pattern is not set. Add the\n          // elaborated pattern to the leading patterns.\n          (go(t) :: leading, N)\n        case ((leading, S((spreadKind, spread, trailing))), t) => \n          // Found a tuple field while the spread pattern has been set. Add the\n          // elaborated pattern to the trailing patterns.\n          (leading, S((spreadKind, spread, go(t) :: trailing)))\n      Tuple(leading.reverse, spread)\n    /** Elaborate record patterns like `(a: p1, b: p2, ...pn)`. */\n    def record(ps: Ls[Tree]): Ctxl[Pattern.Record] =\n      val entries = ps.iterator.map(_.desugared).foldLeft(List[(Ident, Pattern)]()):\n        case (acc, InfixApp(id: Ident, Keywrd(Keyword.`:`), p)) => (id, go(p)) :: acc\n        case (acc, InfixApp(key: StrLit, Keywrd(Keyword.`:`), p)) =>\n          ((Ident(key.value): Ident).withLocOf(key), go(p)) :: acc\n        case (acc, Pun(false, p)) => (p, Variable(p)) :: acc\n        case (acc, t) =>\n          raise(ErrorReport(msg\"Unexpected record property pattern.\" -> t.toLoc :: Nil))\n          acc\n      Record(entries.reverse)\n    /** Elaborate a pattern argument. */\n    def arg(t: Tree): Ctxl[Pattern \\/ Pattern] = t match\n      case TypeDef(syntax.Pat, body, N) => L(go(body))\n      case _ => R(go(t))\n    def go(t: Tree): Ctxl[Pattern] = trace[Pattern](s\"Elab pattern ${t.showDbg}\", r => s\"~> $r\"):\n      t match\n      // Annotated patterns like `@compile P`.\n      case Tree.Annotated(annotation, target) =>\n        go(target).annotate(term(annotation), t.toLoc)\n      // Brackets.\n      case Bra(BracketKind.Round | BracketKind.Curly, t) => go(t)\n      // Tuple patterns like `[p1, p2, ...ps, pn]`.\n      case TyTup(ps) => tuple(ps)\n      case Tup(ps) => tuple(ps)\n      case t: syntax.Literal => Literal(t)\n      // Negation patterns: `~p`\n      case App(Ident(\"~\"), Tup(p :: Nil)) => Negation(go(p))\n      // Negative integer and decimal literals.\n      case app @ App(Ident(\"-\"), Tup(IntLit(n) :: Nil)) =>\n        Literal(IntLit(-n).withLocOf(app))\n      case app @ App(Ident(\"-\"), Tup(DecLit(n) :: Nil)) =>\n        Literal(DecLit(-n).withLocOf(app))\n      // Union and intersection patterns: `p | q` and `p & q`\n      case App(Ident(op @ (\"|\" | \"&\")), Tup(rhs :: Nil)) =>\n        go(rhs) // unary uses of `|` and `&` are no-ops\n      case OpApp(lhs, Ident(op @ (\"|\" | \"&\")), rhs :: Nil) =>\n        Composition(op === \"|\", go(lhs), go(rhs))\n      // Constructor patterns with pattern arguments and arguments.\n      case App(ctor: Ctor, Tup(argTrees)) =>\n        Constructor(term(ctor), S(argTrees.map(go(_))))\n      // `[p1, p2, ...ps, pn] => term`: All patterns are in the `TyTup`.\n      case (lhs: TyTup) `=>` rhs => arrow(lhs, rhs)\n      // `pattern => term`: Note that `pattern` is wrapped in a `Tup`.\n      case Tup(lhs) `=>` rhs => lhs match\n        case p @ Pun(false, _) :: Nil => record(p)\n        case p @ InfixApp(_: Ident, Keywrd(Keyword.`:`), _) :: Nil => record(p)\n        case lhs :: Nil => arrow(lhs, rhs)\n        case _ :: _ | Nil => ??? // TODO: this case reached by, eg, `pattern p = () => Unit`\n      case p as q => q match\n        // `p as id` is elaborated into alias if `id` is not a constructor.\n        case id: Ident => ident(id) match\n          case S(target) if target.symbol.exists(_.isInstanceOf[VarSymbol]) =>\n            // If the target is a variable, we should shadow it. This check is\n            // probably insufficient as there are more cases.\n            go(p) binds id\n          case S(target) => Chain(go(p), Constructor(target, N))\n          case N => go(p) binds id // Fallback to alias.\n        // `p as q` where `q` is not an identifier is elaborated into chain.\n        case _: Tree => Chain(go(p), go(q))\n      case p where t =>\n        val q = go(p)\n        Guarded(q, term(t)(using ctx ++ q.variables.allocate))\n      case Under() => Pattern.Wildcard().withLocOf(t)\n      // Singleton blocks like `{1}`.\n      case Block(p :: Nil) => go(p)\n      // Record patterns like `(a: p1, b: p2, ...pn)`.\n      case Block(ps) => record(ps)\n      // A single pun pattern is a record pattern.\n      case p @ Pun(false, _) => record(p :: Nil)\n      // A single record field is a record pattern.\n      case p @ InfixApp(_, Keywrd(Keyword.`:`), _) => record(p :: Nil)\n      // Range patterns. We can also desugar them into disjunctions of all the\n      // literals in the range.\n      case (lower: StrLit) to (incl, upper: StrLit) =>\n        if isInvalidStringBounds(lower, upper) then Pattern.Wildcard()\n        else Pattern.Range(lower, upper, incl)\n      case (lower: IntLit) to (incl, upper: IntLit) => Pattern.Range(lower, upper, incl)\n      case (lower: DecLit) to (incl, upper: DecLit) => Pattern.Range(lower, upper, incl)\n      case (lower: syntax.Literal) to (_, upper: syntax.Literal) =>\n        raise(ErrorReport(msg\"The upper and lower bounds of range patterns should be literals of the same type.\" -> t.toLoc :: Nil))\n        Pattern.Wildcard()\n      // String concatenation patterns: `p ~ q`. Currently, not supported by the\n      // pattern compilation. We elaborate them to keep the consistency with the\n      // pattern translation.\n      case OpApp(lhs, Ident(\"~\"), rhs :: Nil) => Pattern.Concatenation(go(lhs), go(rhs))\n      // Constructor patterns can be written in the infix form.\n      case OpApp(lhs, op, rhs :: Nil) => Pattern.Constructor(term(op), S(Ls(go(lhs), go(rhs))))\n      // Constructor patterns without arguments\n      case id @ Ident(name) if name.isUncapitalized => Variable(id)\n      case id @ Ident(name) => ident(id) match\n        case S(target) => Constructor(target, N)\n        case N =>\n          raise:\n            ErrorReport(msg\"Pattern name not found: ${id.name}.\" -> id.toLoc :: Nil)\n          Pattern.Wildcard()\n      case sel: (SynthSel | Sel) => Constructor(term(sel), N)\n      case _: Tree =>\n        raise(ErrorReport(msg\"Unrecognized pattern (${t.describe}).\" -> t.toLoc :: Nil))\n        Pattern.Wildcard()\n    go(t)\n  \n  def typeParams(t: Tree): Ctxl[(Ls[Param], Ctx)] = t match\n    case TyTup(ps) =>\n      val vs = ps.flatMap:\n        case id: Ident =>\n          val sym = VarSymbol(id)\n          sym.decl = S(TyParam(FldFlags.empty, N, sym))\n          Param(FldFlags.empty, sym, N, Modulefulness.none) :: Nil\n        case t =>\n          raise(ErrorReport(msg\"Unsupported type parameter ${t.describe}\" -> t.toLoc :: Nil))\n          Nil\n      (vs, ctx ++ vs.map(p => p.sym.name -> p.sym))\n  \n  def importFrom(sts: Block): Ctxl[(Blk, Ctx)] =\n    given UnderCtx = new UnderCtx(N)\n    val (res, newCtx) = block(sts, hasResult = false)\n    // TODO handle name clashes\n    (res, newCtx)\n\n  def topLevel(sts: Block): Ctxl[(Blk, Ctx)] =\n    given UnderCtx = new UnderCtx(N)\n    val (res, ctx) = block(sts, hasResult = false)\n    computeVariances(res)\n    (res, ctx)\n  \n  def computeVariances(s: Statement): Unit =\n    val trav = VarianceTraverser()\n    def go(s: Statement): Unit = s match\n      case TermDefinition(k, sym, tsym, pss, _, sign, body, r, _, _, _) =>\n        pss.foreach(ps => ps.params.foreach(trav.traverseType(S(false))))\n        sign.foreach(trav.traverseType(S(true)))\n        body match\n          case S(b) =>\n            go(b)\n          case N =>\n      case ClassDef(sym, tps, pso, body) =>\n        pso.foreach: ps =>\n          ps.foreach: p =>\n            p.sign.foreach(trav.traverseType(S(true)))\n        body.blk.stats.foreach(go)\n        // s.subStatements.foreach(go)\n      case _ =>\n        s.subStatements.foreach(go)\n    while trav.changed do\n      trav.changed = false\n      go(s)\n  \n  class VarianceTraverser(var changed: Bool = true) extends Traverser:\n    override def traverseType(pol: Pol)(trm: Term): Unit = trm match\n      case Term.TyApp(lhs, targs) =>\n        lhs.symbol.flatMap(sym => sym.asTpe) match\n          case S(sym: ClassSymbol) =>\n            sym.defn match\n            case S(td: ClassDef) =>\n              td.tparams.zip(targs).foreach:\n                case (tp, targ) =>\n                  if !tp.isContravariant then traverseType(pol)(targ)\n                  if !tp.isCovariant then traverseType(pol.!)(targ)\n            case N =>\n              // TODO(sym->sym.uid)\n          case S(sym: ModuleOrObjectSymbol) =>\n            sym.defn match\n            case S(td: ModuleOrObjectDef) =>\n              td.tparams.zip(targs).foreach:\n                case (tp, targ) =>\n                  if !tp.isContravariant then traverseType(pol)(targ)\n                  if !tp.isCovariant then traverseType(pol.!)(targ)\n            case N =>\n              // TODO(sym->sym.uid)\n          case S(sym: TypeAliasSymbol) =>\n            // TODO dedup with above...\n            sym.defn match\n            case S(td: semantics.TypeDef) =>\n              td.tparams.zip(targs).foreach:\n                case (tp, targ) =>\n                  if !tp.isContravariant then traverseType(pol)(targ)\n                  if !tp.isCovariant then traverseType(pol.!)(targ)\n            case N =>\n              TODO(sym->sym.uid)\n          // case S(sym) => ???\n          case N =>\n            log(s\"No symbol found $lhs ${lhs.symbol}\")\n            // ???\n            () // TODO\n      case Term.Ref(sym: VarSymbol) =>\n        sym.decl match\n          case S(ty: TyParam) =>\n            if pol =/= S(true) && ty.isCovariant then\n              changed = true\n              ty.isCovariant = false\n            if pol =/= S(false) && ty.isContravariant then\n              changed = true\n              ty.isContravariant = false\n          // case _ => ???\n          case N =>\n            lastWords(s\"VarSymbol ${sym.name} has no declaration\")\n      case _ => super.traverseType(pol)(trm)\n  abstract class Traverser:\n    def traverseType(pol: Pol)(trm: Term): Unit = trm match\n      case Term.Lit(_) | Term.UnitVal() | Term.Error =>\n      case Term.TyApp(lhs, targs) =>\n        // lhs.resolveSymbol\n        // targs.foreach(traverseType(pol))\n        ???\n      case r: Term.Ref =>\n      case Term.FunTy(l, r, e) =>\n        traverseType(pol.!)(l)\n        traverseType(pol)(r)\n        e.foreach(e => traverseType(pol)(e))\n      case Term.Forall(_, _, body) =>\n        traverseType(pol)(body)\n      case Term.WildcardTy(in, out) =>\n        in.foreach(t => traverseType(pol.!)(t))\n        out.foreach(t => traverseType(pol)(t))\n      case Term.CompType(lhs, rhs, _) => () // TODO:\n      case Term.SynthSel(bse, nme) =>\n        traverseType(pol)(bse) // FIXME: probably wrong for what we want to do\n      case Term.Tup(fields) =>\n        // fields.foreach(f => traverseType(pol)(f.value))\n        fields.foreach(traverseType(pol))\n      // case _ => ???\n      case Term.Neg(ty) => \n        traverseType(pol.!)(ty)\n      case _ =>\n        // TODO\n    def traverseType(pol: Pol)(f: Elem): Unit = f match\n      case f: Fld =>\n        traverseType(pol)(f.term)\n        f.asc.foreach(traverseType(pol))\n    def traverseType(pol: Pol)(f: Param): Unit =\n      f.sign.foreach(traverseType(pol))\nend Elaborator\n\ntype Pol = Opt[Bool]\nextension (p: Pol) def ! : Pol = p.map(!_)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/Importer.scala",
    "content": "package hkmc2\npackage semantics\n\nimport scala.collection.mutable\nimport scala.annotation.tailrec\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\nimport hkmc2.Message.MessageContext\nimport hkmc2.io\nimport utils.TraceLogger\n\nimport Elaborator.*\nimport hkmc2.syntax.LetBind\n\n\nclass Importer:\n  self: Elaborator =>\n  import tl.*\n  \n  def importPath(path: Str, alias: Opt[syntax.Tree.Ident])(using cfg: Config): Import =\n    // log(s\"pwd: ${os.pwd}\")\n    // log(s\"wd: ${wd}\")\n    \n    val file =\n      if path.startsWith(\"/\")\n      then io.Path(path)\n      else wd / io.RelPath(path)\n    \n    val nme = file.baseName\n    val id = alias.getOrElse(new syntax.Tree.Ident(nme)) // TODO loc\n    \n    lazy val sym = TermSymbol(LetBind, N, id)\n    \n    if path.startsWith(\".\") || path.startsWith(\"/\") then // leave alone imports like \"fs\"\n      log(s\"importing $file\")\n      \n      val nme = file.baseName\n      val id = new syntax.Tree.Ident(nme) // TODO loc\n      \n      file.ext match\n      \n      case \"mjs\" | \"js\" =>\n        Import(sym, file.toString, file)\n        \n      case \"mls\" if {\n        !cctx.beingCompiled.contains(file) `||`:\n          raise:\n            ErrorReport:\n                msg\"Circular imports of `mls` files are not yet supported\" -> N\n                :: (cctx.allFilesBeingImported :+ file).map(f => msg\"  importing ${f.toString}\" -> N)\n          false\n      } =>\n        \n        val importedSym = tl.trace(s\">>> Importing $file\"):\n          given TL = tl\n          val artifact = cctx.getElaboratedBlock(file, prelude)\n          artifact.tree.definedSymbols.find(_._1 === nme) match\n          case Some(nme -> imsym) => imsym\n          case None => lastWords(s\"File $file does not define a symbol named $nme\")\n        val sym = alias.fold(importedSym): alias =>\n          val res = BlockMemberSymbol(alias.name, importedSym.trees, importedSym.nameIsMeaningful)\n          res.tsym = importedSym.tsym\n          res\n        \n        val jsFile = file.up / io.RelPath(file.baseName + \".mjs\")\n        Import(sym, jsFile.toString, jsFile)\n        \n      case _ =>\n        if file.ext =/= \"mls\" then raise:\n          ErrorReport(msg\"Unsupported file extension: ${file.ext}\" -> N :: Nil)\n        Import(sym, path, file)\n      \n    else\n      Import(sym, path, file)\n    \n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/Pattern.scala",
    "content": "package hkmc2\npackage semantics\n\nimport mlscript.utils.*, shorthands.*\nimport collection.immutable.HashMap, collection.mutable.Buffer\nimport syntax.{Keyword, SpreadKind, Tree}, Tree.{Ident, StrLit}\nimport Elaborator.State, Message.MessageContext, ucs.error\nimport scala.annotation.tailrec, util.chaining.*\nimport utils.{TraceLogger, tl}\n\nobject Pattern:\n  /** The reason why a variable obtained from `Pattern.variables` is invalid. */\n  enum InvalidReason:\n    /** The variable shadowed another variable.\n     *  @param previous The identifiers shadowed by the current aliases. */\n    case Duplicated(previous: Ls[Ident])\n    /** The variable presents in one side of disjunction, but not the other. */\n    case Inconsistent(disjunction: Pattern.Composition, missingOnTheLeft: Bool)\n    /** The variable is bound in a `Negation` pattern. */\n    case Negated(negation: Pattern.Negation)\n    /** Higher-order pattern arguments contain free variables. For example, `x`\n     *  in `pattern MaybeInt = Nullable(pattern Int as x)` is invalid. Because\n     *  `MaybeInt` does not guarantee that `Int as x` is used in `Nullable`. */\n    case Escaped(pattern: Pattern)\n  \n  import InvalidReason.*\n  \n  /** A set of variables that present in a pattern.\n   *  \n   *  These variables are represented by `Tree.Ident` because not every identifier\n   *  can represent a meaningful binding. This set is used in the computed property\n   *  on the `Pattern` tree. We only create `VarSymbol` for these variables at the\n   *  root node or when elaborating the term of a `Transform` pattern.\n   * \n   *  @param varMap A map from variable names to their valid aliases. Multiple\n   *                aliases are allowed when they are in different disjunctions.\n   *  @param invalidVars A list of variables and the reason why they are invalid.\n   */\n  final case class Variables(\n      varMap: HashMap[Str, Ls[Pattern.Alias]],\n      invalidVars: Ls[(Pattern.Alias, InvalidReason)]\n  ):\n    /** Allocate symbols for all variables. */\n    def allocate(using State, TraceLogger): Seq[(Str, VarSymbol)] =\n      varMap.iterator.map: (name, aliases) =>\n        // We need to assign the same symbol to the same name. But I realize\n        // that the following cases will break this constraint: `(x where x > 0)\n        // | (x where x < 0)`. In both alternatives, `x` needs to be allocated\n        // in advanced, but at the level of the disjunction, `x` needs to be\n        // assigned to the same variable. This represents an edge case which\n        // needs to be fixed later.\n        val symbols = aliases.iterator.flatMap(_.symbolOption).toSet\n        // TODO: The above edge case would fail the following assertion.\n        assert(symbols.size <= 1)\n        // If no symbol had been created before, create a new symbol now.\n        val symbol = symbols.headOption.getOrElse(VarSymbol(Ident(name)))\n        aliases.foreach: alias =>\n          // For guarded patterns (`p where t`), the variables in `p` have to be\n          // allocated before `t` is elaborated. In that case, we don't need to\n          // allocate the variables in `p` again when the variables of pattern\n          // containing `p` are allocated.\n          if alias.symbolOption.isEmpty then alias.symbol = symbol\n        (name, symbol)\n      .toSeq\n    \n    /** Get all symbols for the variables. */\n    def symbols: Ls[VarSymbol] =\n      varMap.iterator.flatMap(_._2.head.symbolOption).toList\n    \n    /** Add a single variable to the variable set. */\n    def +(alias: Pattern.Alias): Variables =\n      varMap.get(alias.id.name) match\n        // Add the alias to the variable set if the name has not been used.\n        case N => Variables(varMap + (alias.id.name -> Ls(alias)), invalidVars)\n        case S(oldAliases) => Variables(\n          varMap.updated(alias.id.name, Ls(alias)),\n          // Append the invalid reason: `alias` shadows `oldAliases`.\n          invalidVars :+ (alias -> Duplicated(oldAliases.map(_.id))))\n    \n    /** Union two variable sets. If the latter contains a variable that is\n     *  already present in the former, the variable is considered duplicated. */\n    def ++(that: Variables): Variables =\n      val duplicated: Buffer[(Alias, InvalidReason)] = Buffer.empty\n      Variables(\n        varMap.merged(that.varMap):\n          case ((name, previous), (_, aliases)) =>\n            duplicated ++= aliases.map(_ -> Duplicated(previous.map(_.id)))\n            (name, aliases),\n        invalidVars ::: that.invalidVars ::: duplicated.toList)\n    \n    /** For debugging purpose only. */\n    def display: Str = varMap.iterator.map:\n      case (key, aliases) =>\n        key + \" -> \" + aliases.iterator.map(_.id.name).mkString(\", \")\n    .mkString(\"{\", \"; \", \"}\")\n    \n    /** Intersect two variable sets and move variables that are only present in\n     *  one side to the invalid variables. This method considers `this` as the\n     *  left side, and `that` as the right side. */\n    def intersect(that: Variables, pattern: Pattern.Composition): Variables =\n      // Check if two variable sets are the same.\n      val notInThat = varMap.removedAll(that.varMap.keys)\n      val notInThis = that.varMap.removedAll(varMap.keys)\n      Variables(\n        // Merge two sets and remove variables that only present in one side.\n        varMap.merged(that.varMap):\n          case ((name, left), (_, right)) => (name, left ::: right)\n        .removedAll(Iterable.concat(notInThat.keys, notInThis.keys)),\n        // Add variables that only present in one side to the invalid variables.\n        invalidVars :::\n          notInThis.iterator.flatMap(_._2.map(_ -> Inconsistent(pattern, true))).toList :::\n          notInThat.iterator.flatMap(_._2.map(_ -> Inconsistent(pattern, false))).toList)\n    \n    /** Mark all variables in this set as invalid. */\n    def invalidated(reason: InvalidReason): Variables =\n      Variables(HashMap.empty, invalidVars appendedAll varMap.iterator.flatMap(_._2.map(_ -> reason)))\n    \n    /** Report all invalid variables. */\n    def report(using Raise): Unit = invalidVars.foreach:\n      case (Alias(_, id), Duplicated(previous)) => raise(ErrorReport(\n        msg\"Duplicated pattern variable.\" -> id.toLoc ::\n        msg\"The previous definition ${if previous.size === 1 then \"is\" else \"are\"} as follows.\" -> previous.head.toLoc ::\n        previous.tail.map(msg\"\" -> _.toLoc)))\n      case (Alias(_, id), Inconsistent(disjunction, missingOnTheLeft)) => error(\n        msg\"Found an inconsistent variable in disjunction patterns.\" -> id.toLoc,\n        msg\"The variable is missing from this sub-pattern.\" -> (\n          if missingOnTheLeft then disjunction.left else disjunction.right\n        ).toLoc)\n      case (Alias(pattern, id), Negated(negation)) => error(\n        pattern match\n          case Wildcard() => msg\"This variable cannot be accessed.\" -> id.toLoc\n          case _: Pattern => msg\"This pattern cannot be bound.\" -> pattern.toLoc,\n        msg\"Because the pattern it belongs to is negated.\" -> negation.toLoc)\n    \n  object Variables:\n    lazy val empty: Variables = Variables(HashMap.empty, Nil)\n  \n  extension (patterns: IterableOnce[Pattern])\n    def variables: Variables = patterns.iterator.foldLeft(Variables.empty):\n      case (vars, pattern) => vars ++ pattern.variables\n  \n  /** A shorthand for creating a variable pattern. */\n  def Variable = Pattern.Wildcard() binds (_: Ident)\n  \n  trait ConstructorImpl:\n    self: Pattern.Constructor =>\n    \n    /** Get the resolved symbol of the target term. */\n    def symbol: Opt[Symbol] = self.target.resolvedSym\n    \n    /** Expect the `symbol` to be set. */\n    def symbol_! : Symbol = symbol.getOrElse:\n      lastWords(s\"target term `${self.target}` does not resolve to a symbol\")\n  \n  /** Add a mutable field to the `Alias` pattern to store the symbol for the\n   *  variable. Note that NOT every `Alias` pattern has a symbol. */\n  trait AliasImpl:\n    self: Pattern.Alias =>\n    private var _symbol: Opt[VarSymbol] = N\n    /** Directly set the symbol for the variable. This should be called in the\n     *  elaborator when elaborating the non-`Transform` top-level pattern. */\n    def symbol_=(symbol: VarSymbol): Unit = _symbol = S(symbol)\n    def symbolOption: Opt[VarSymbol] = _symbol\n    def symbol: VarSymbol = _symbol.getOrElse:\n      lastWords(s\"no symbol was assigned to variable `${id.name}` at ${id.toLoc}\")\n\nimport Pattern.*, InvalidReason.*\n\n/** An inductive data type for patterns. */\nenum Pattern extends AutoLocated:\n  /** A pattern that matches a constructor and its arguments.\n   *  @param target The term representing the constructor.\n   *  @param arguments `None` if the pattern does not have a parameter list. The\n   *      patterns that are used to destruct the constructor's arguments.\n   */\n  case Constructor(\n      target: Term,\n      arguments: Opt[Ls[Pattern]]\n  ) extends Pattern with ConstructorImpl\n  \n  /** A pattern that is the composition of two patterns.\n   *  @param polarity `true` if the pattern is a disjunction, `false` if it is\n   *                  a conjunction.\n   */\n  case Composition(polarity: Bool, left: Pattern, right: Pattern)\n  \n  /** A pattern that is the negation of another pattern. We don't allow negation\n   *  patterns to be nested. They can only be used as the top-level pattern.\n   *  Also, what's the point of binding the inner pattern? \n   */\n  case Negation(pattern: Pattern)\n  \n  /** A pattern that matches any value. It is syntically denoted by `_`. */\n  case Wildcard()\n  \n  /** A pattern that matches the given literal. */\n  case Literal(literal: syntax.Literal)\n  \n  /** A pattern that matches a range of values. */\n  case Range(lower: syntax.Literal, upper: syntax.Literal, rightInclusive: Bool)\n  \n  /** A pattern that matches the concatenation of two string patterns. The\n   *  concatenation of non-string patterns results in a never-match pattern. */\n  case Concatenation(left: Pattern, right: Pattern)\n  \n  /** A pattern that matches a tuple. At most one `spread` pattern is allowed.\n    * When the `spread` pattern is absent, sub-patterns should be placed in the \n    * `leading` field.\n    * @param leading matches a fixed number of leading elements in the tuple.\n    * @param spread matches a variable number of elements in the tuple plus\n    *               the trailing elements.\n    */\n  case Tuple(\n      leading: Ls[Pattern],\n      spread: Opt[(SpreadKind, Pattern, Ls[Pattern])],\n  )\n  \n  /** A pattern that matches a record consisting of a list of fields. Note that\n   *  the fields are not ordered semantically. */\n  case Record(fields: Ls[(Ident, Pattern)])\n  \n  /** Chain one pattern to another. The pattern matches the input value against\n   *  the `first` pattern, and then matches its output against the `second`\n   *  pattern. It fails when either of the patterns fails.\n   */\n  case Chain(first: Pattern, second: Pattern)\n  \n  /** A pattern that matches the same value as another pattern, but bind the\n   *  matched value to a new variable. This is the only class that holds the\n   *  symbol for the variable. */\n  case Alias(pattern: Pattern, id: Ident) extends Pattern with AliasImpl\n  \n  /** A pattern that matches the same value as other pattern, with an additional\n    * function applied to the bound variables in the pattern.\n    *\n    * @param pattern The pattern to be matched against.\n    * @param parameters A map from the variable symbols to parameter symbols.\n    * @param transform The term that should be applied to the extracted values.\n   */\n  case Transform(pattern: Pattern, parameters: Ls[(VarSymbol, VarSymbol)], transform: Term)\n  \n  /** If the term is `Error`, we add `Opt[Loc]` to the list instead. */\n  case Annotated(pattern: Pattern, annotations: Vector[Opt[Loc] \\/ Term])\n  \n  /** A pattern that comes with an extra condition. It works in a way similar to\n   *  `and` in split. */\n  case Guarded(pattern: Pattern, guard: Term)\n  \n  infix def binds(id: Ident): Pattern.Alias = Pattern.Alias(this, id)\n  \n  /** Annotate the pattern using the given term. If the term is `Error`, then\n    * use the location of the original tree for error reporting. */\n  inline def annotate(annotation: Term, treeLoc: Opt[Loc]): Pattern.Annotated =\n    val elem = if annotation is Term.Error then L(treeLoc) else R(annotation)\n    this match\n      case Annotated(pattern, annotations) =>\n        Annotated(pattern, annotations :+ elem)\n      case _ => Annotated(this, Vector.single(elem))\n  \n  inline def withGuard(guard: Term) = Pattern.Guarded(this, guard)\n  \n  /** Collect all variables in the pattern. Meanwhile, list invalid variables,\n   *  which will be reported when constructing symbols for variables. We use a\n   *  map because we want to replace variables. */\n  lazy val variables: Variables = this match\n    case Constructor(_, arguments) => arguments.fold(Variables.empty)(_.variables)\n    case Composition(false, left, right) => left.variables ++ right.variables\n    case union @ Composition(true, left, right) => left.variables.intersect(right.variables, union)\n    // If we only allow negation patterns to be used as the top-level pattern\n    // and the arguments represent the diagnostic information of match failure,\n    // then we can bind the variables in the pattern to the arguments.\n    // case Negation(Constructor(_, arguments)) => arguments.variables\n    // Otherwise, negation patterns should not bind any variables.\n    case negation @ Negation(pattern) => pattern.variables.invalidated(Negated(negation))\n    case _: (Wildcard | Literal | Range | Transform) => Variables.empty\n    case Concatenation(left, right) => left.variables ++ right.variables\n    case Tuple(leading, spread) => leading.variables ++ spread.fold(Variables.empty):\n      case (_, middle, trailing) => middle.variables ++ trailing.variables\n    case Record(fields) => fields.iterator.map(_._2).variables\n    case alias @ Alias(pattern, _) => pattern.variables + alias\n    case Chain(first, second) => first.variables ++ second.variables\n    case Annotated(pattern, _) => pattern.variables\n    case Guarded(pattern, _) => pattern.variables\n  \n  /** Collect the names of pattern variables that are actually referenced\n    * as free variables inside guard terms of `Guarded` patterns. Only\n    * variables whose names appear free (not locally re-bound) in the guard\n    * are included, so that truly unused pattern bindings (e.g.,\n    * `[x] where true`) and shadowed bindings (e.g.,\n    * `[x, y] where (let x = ..., x)`) still trigger warnings. */\n  lazy val varNamesUsedInGuards: Set[Str] = this match\n    case Guarded(pattern, guard) =>\n      val boundNames = pattern.variables.varMap.keySet\n      val referencedNames = guard.freeVars\n      (boundNames & referencedNames) ++ pattern.varNamesUsedInGuards\n    case _ =>\n      children.iterator.collect:\n        case p: Pattern => p.varNamesUsedInGuards\n      .foldLeft(Set.empty[Str])(_ ++ _)\n  \n  def children: Vector[Located] = this match\n    case Constructor(target, arguments) => target +: arguments.fold(Vector.empty)(_.toVector)\n    case Composition(polarity, left, right) => Vector.double(left, right)\n    case Negation(pattern) => Vector.single(pattern)\n    case Wildcard() => Vector.empty\n    case Literal(literal) => Vector.single(literal)\n    case Range(lower, upper, rightInclusive) => Vector.double(lower, upper)\n    case Concatenation(left, right) => Vector.double(left, right)\n    case Tuple(leading, spread) => leading.toVector ++ spread.fold(Vector.empty):\n      case (_, middle, trailing) => middle +: trailing.toVector\n    case Record(fields) =>\n      fields.iterator.flatMap:\n        case (name, pattern) => name +: pattern.children\n      .toVector\n    case Chain(first, second) => Vector.double(first, second)\n    case Alias(pattern, alias) => Vector.double(pattern, alias)\n    case Transform(pattern, _, transform) => Vector.double(pattern, transform)\n    case Annotated(pattern, annotations) => pattern +:\n      annotations.iterator.collect { case R(term) => term }.toVector\n    case Guarded(pattern, guard) => pattern.children :+ guard\n  \n  def subTerms: Vector[Term] = this match\n    case Constructor(target, arguments) =>\n      target +: Vector.concat(arguments.fold(Vector.empty)(_.iterator.flatMap(_.subTerms).toVector))\n    case Composition(_, left, right) => left.subTerms ++ right.subTerms\n    case Negation(pattern) => pattern.subTerms\n    case _: (Wildcard | Literal | Range) => Vector.empty\n    case Concatenation(left, right) => left.subTerms ++ right.subTerms\n    case Tuple(leading, spread) => leading.iterator.flatMap(_.subTerms).toVector ++ spread.fold(Vector.empty):\n      case (_, middle, trailing) => middle.subTerms ++ trailing.iterator.flatMap(_.subTerms).toVector\n    case Record(fields) => fields.iterator.flatMap(_._2.subTerms).toVector\n    case Chain(first, second) => first.subTerms ++ second.subTerms\n    case Alias(pattern, _) => pattern.subTerms\n    case Transform(pattern, _, transform) => pattern.subTerms :+ transform\n    case Annotated(pattern, annotations) => pattern.subTerms ++\n      annotations.iterator.collect { case R(term) => term }.toList\n    case Guarded(pattern, guard) => pattern.subTerms :+ guard\n  \n  def describe: Str = this match\n    case Constructor(_, _) => \"constructor\"\n    case Composition(true, _, _) => \"disjunction\"\n    case Composition(false, _, _) => \"conjunction\"\n    case Negation(_) => \"negation\"\n    case Wildcard() => \"wildcard\"\n    case Literal(_) => \"literal\"\n    case Range(_, _, _) => \"range\"\n    case Concatenation(_, _) => \"concatenation\"\n    case Tuple(_, _) => \"tuple\"\n    case Record(_) => \"record\"\n    case Chain(_, _) => \"chain\"\n    case Alias(_, _) => \"alias\"\n    case Transform(_, _, _) => \"transform\"\n    case Annotated(_, _) => \"annotated pattern\"\n    case Guarded(_, _) => \"guarded pattern\"\n  \n  private def showDbgWithPar(using DebugPrinter): Str =\n    val addPar = this match\n      case _: (Constructor | Wildcard | Literal | Tuple | Record | Negation | Annotated) => false\n      case Alias(Wildcard(), _) => false\n      case _: (Alias | Composition | Transform | Range | Concatenation | Chain | Guarded) => true\n    if addPar then s\"(${showDbg})\" else showDbg\n  \n  def showDbg(using DebugPrinter): Str = this match\n    case Constructor(target, arguments) =>\n      target.symbol.fold(target.showDbg)(_.nme) + arguments.fold(\"\"):\n        args => s\"(${args.map(_.showDbg).mkString(\", \")})\"\n    case Composition(true, left, right) => s\"${left.showDbg} ∨ ${right.showDbg}\"\n    case Composition(false, left, right) => s\"${left.showDbg} ∧ ${right.showDbg}\"\n    case Negation(pattern) => s\"¬${pattern.showDbgWithPar}\"\n    case Wildcard() => \"_\"\n    case Literal(literal) => literal.idStr\n    case Range(lower, upper, rightInclusive) =>\n      s\"${lower.idStr} ${if rightInclusive then \"to\" else \"until\"} ${upper.idStr}\"\n    case Concatenation(left, right) => s\"${left.showDbg} ~ ${right.showDbg}\"\n    case Tuple(leading, spread) =>\n      (leading.iterator.map(_.showDbg) ++ spread.fold(Iterator.empty):\n        case (spreadKind, middle, trailing) =>\n          Iterator.single(spreadKind.str + middle.showDbg) ++\n            trailing.iterator.map(_.showDbg)).mkString(\"[\", \", \", \"]\")\n    case Record(fields) => s\"{${fields.map((k, v) => s\"${k.name}: ${v.showDbg}\").mkString(\", \")}}\"\n    case Chain(first, second) => s\"${first.showDbgWithPar} as ${second.showDbgWithPar}\"\n    case Alias(Wildcard(), alias) => alias.name\n    case Alias(pattern, alias) => s\"${pattern.showDbgWithPar} as ${alias.name}\"\n    case Transform(pattern, _, transform) => s\"${pattern.showDbgWithPar} => ${transform.showDbg}\"\n    case Annotated(pattern, annotations) => annotations.iterator.map:\n        case L(errorLoc) => \"error\"\n        case R(term) => term.showDbg\n      .mkString(\"@\", \" @\", \" \") + pattern.showDbgWithPar\n    case Guarded(pattern, guard) => pattern.showDbg + \" where \" + guard.showDbg\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/Resolver.scala",
    "content": "package hkmc2\npackage semantics\n\nimport mlscript.utils.*, shorthands.*\nimport utils.TraceLogger\n\nimport syntax.Tree\nimport syntax.Tree.{DummyTup, DummyApp}\nimport syntax.{Fun, Ins, Mod, ImmutVal, MutVal, SpreadKind}\nimport syntax.Keyword.{`if`}\nimport Elaborator.State\nimport Resolvable.*\nimport typing.Type\n\nimport semantics.ucs.FlatPattern\n\nimport Message.MessageContext\nimport scala.annotation.tailrec\n\nobject Resolver:\n  \n  /**\n   * An \"implicit\" or \"instance\" context, as opposed to the one in\n   * Elaborator.\n   *\n   * Essentially, the resolver does the following:\n   *\n   * 1. If it sees an application with contextual arguments to be\n   *    resolved, it resolves the contextual arguments from the instance\n   *    environment. If the type of the contextual arguments involve\n   *    type parameters, it resolves the actual types from the type\n   *    environment.\n   *\n   * 2. If it sees an instance definition, it adds the instance to the\n   *    instance environment.\n   *\n   * 3. If it sees an application with contextual arguments to be\n   *    resolved and type arguments specified, it resolves the\n   *    contextual arguments from the instance environment, and adds the\n   *    type arguments to the type environment.\n   *\n   * @param parent the parent context, if any\n   * @param iEnv the instance environment, mapping types to instances\n   * @param tEnv the type environment, mapping type parameters to\n   * concrete types\n   */\n  case class ICtx(\n    parent: Opt[ICtx], \n    iEnv: Map[Type, Ls[(Type, ICtx.Instance)]],\n    tEnv: Map[VarSymbol, Type]\n  ):\n    \n    def +(typ: Type, ins: Symbol): ICtx = typ match\n      case Type.NotImplemented => lastWords(\"Cannot add instance with a not-yet implemented type.\")\n      case Type.Error => this\n      case _ => copy(iEnv = \n        iEnv + (typ.key -> ((typ -> ICtx.Instance(ins)) :: iEnv.getOrElse(typ.key, Nil)))  \n      )\n    \n    def withTypeArg(param: VarSymbol, arg: Type): ICtx =\n      copy(tEnv = tEnv + (param -> arg))\n    \n    extension (t: Type)\n      private def key: Type = t match\n        case Type.Ref(base, _) => Type.Ref(base, Nil)\n        case _ => t\n    extension (lhs: Type)\n      private def =:= (rhs: Type): Bool = lhs <:< rhs && rhs <:< lhs\n      private def <:< (rhs: Type): Bool = (lhs, rhs) match\n        case (_, Type.Top) => true\n        \n        // If LHS/RHS is unspecified (not substituted into a concrete type),\n        // we consider LHS/RHS is always a subtype of LHS/RHS.\n        case (lhs: Type.Ref, rhs @ Type.Ref(_: VarSymbol, Nil)) => true\n        case (lhs @ Type.Ref(_: VarSymbol, Nil), rhs: Type.Ref) => true\n        \n        case (lhs: Type.Ref, rhs: Type.Ref) =>\n          lhs.sym === rhs.sym // TODO: subtyping for Ref\n          && (lhs.args.sizeCompare(rhs.args.length) === 0)\n          && (lhs.args zip rhs.args).forall((a, b) => a.lb =:= b.lb && a.ub =:= b.ub) // suppose invariant\n        case (lhs: Type.Fun, rhs: Type.Fun) =>\n          rhs.args <:< lhs.args && lhs.ret <:< rhs.ret && (lhs.eff, rhs.eff).match\n            case (N, N) => true\n            case (S(le), S(re)) => le <:< re // covariant\n            case _ => false\n        case (lhs: Type.Neg, rhs) => ???\n        case (lhs, rhs: Type.Neg) => ???\n        case (lhs, rhs: Type.Union) => lhs <:< rhs.lhs || lhs <:< rhs.rhs\n        case (lhs, rhs: Type.Inter) => lhs <:< rhs.lhs && lhs <:< rhs.rhs\n        case (lhs, rhs) => lhs === rhs\n\n    def query(q: Type): Ls[Message -> Opt[Loc]] \\/ ICtx.Instance =\n      q match\n        case Type.NotImplemented => lastWords(\"Cannot resolve instance for a not-yet implemented type.\")\n        case q @ Type.Ref(sym: VarSymbol, args) if !tEnv.contains(sym) => L:\n          msg\"Illegal query for an unspecified type variable ${q.show}.\" -> N :: Nil\n        case q =>\n          q.subst:\n            case ty @ Type.Ref(sym: VarSymbol, Nil) =>\n              tEnv.getOrElse(sym, ty)\n            case ty @ Type.Ref(sym: VarSymbol, args) =>\n              lastWords(s\"Unsupported substitution with type arguments\")\n          .into: qq =>\n            iEnv.getOrElse(qq.key, Nil)\n              .find: (ty, _instance) =>\n                ty <:< qq\n              .map: (_ty, instance) =>\n                instance\n              .toRight:\n                msg\"Missing instance: Expected: ${showTy(q)}; Available: ${showEnv}\" -> N :: Nil\n    \n    def showEnv: Str =\n      iEnv.values\n        .flatMap(_.map((typ, instance) => s\"${typ.show}\"))\n        .toList\n        .distinct\n        .mkStringOr(\", \", els = \"‹none available›\")\n    \n    def showTy(ty: Type): Str = ty match\n      case Type.Ref(sym: VarSymbol, Nil) =>\n        s\"${tEnv.get(sym).map(_.show).getOrElse(\"‹unspecified›\")} (type parameter ${ty.show})\"\n      case Type.Ref(sym: VarSymbol, args) =>\n        s\"${tEnv.get(sym).map(_.show).getOrElse(\"‹unspecified›\")}${args.map(_.show).mkString(\"[\", \", \", \"]\")} (type parameter ${ty.show})\"\n      case _ => \n        s\"${ty.show}\"\n  \n  enum Expect:\n    case Module(reason: Opt[Message])\n    case NonModule(reason: Opt[Message])\n    case Class(reason: Opt[Message])\n    case Selectable(reason: Opt[Message])\n    case PatternConstructor(reason: Opt[Message])\n    case Any\n    \n    def message: Ls[Message -> Opt[Loc]] = this match\n      case Expect.Module(msg) => msg.toList.map(_ -> N)\n      case Expect.NonModule(msg) => msg.toList.map(_ -> N)\n      case Expect.Class(msg) => msg.toList.map(_ -> N)\n      case Expect.Selectable(msg) => msg.toList.map(_ -> N)\n      case Expect.PatternConstructor(msg) => msg.toList.map(_ -> N)\n      case Expect.Any => Nil\n    \n    def `module` = isInstanceOf[Module]\n    def `class` = isInstanceOf[Class]\n    def nonModule = isInstanceOf[NonModule]\n    \n    override def toString: Str = this match\n      case _: Expect.Module => \"Module\"\n      case _: Expect.NonModule => \"NonModule\"\n      case _: Expect.Class => \"Class\"\n      case _: Expect.Selectable => \"Selectable\"\n      case _: Expect.PatternConstructor => \"PatternConstructor\"\n      case Expect.Any => \"Any\"\n  \n  object Expect:\n    def fromModulefulness(mf: Modulefulness): Expect =\n      if mf.modified then\n        Expect.Module(N)\n      else\n        Expect.NonModule(N)\n  \n  object ICtx:\n    \n    case class Instance(sym: Symbol)\n    \n    val empty = ICtx(N, Map.empty, Map.empty)\n    \n  def ictx(using ICtx) = summon[ICtx]\n  \nend Resolver\n\n/**\n  * Resolver for the module system.\n  *\n  * Resolver mainly resolves the terms, definitions and symbols that are\n  * not yet ready during the elaboration. In addition, it also performs\n  * some checks on the modulefulness of the terms.\n  *\n  * Here are some notes that I used for reasoning about the design.\n  *\n  * ### Static Members vs. Class Members\n  *\n  * An important feature in MLscript is that the program should be\n  * compilable without type checking, and the user experience of doing\n  * so should be good and not error prone. (See:\n  * https://github.com/hkust-taco/mlscript-design-docs/blob/main/wiki/module-methods.md)\n  * A consequence of this design is that the definition of a method may\n  * not always be present at compilation-time, because the type\n  * information of the object is absent.\n  *\n  * In contrast, for a function, the definition is always known at the\n  * call sites at compilation time. This is important because most\n  * call-site features require the definition to be known. For example,\n  * by-name, lazy and implicit parameters all require the definition so\n  * that the compiler can perform the correct elaboration and\n  * resolution.\n  *\n  * ### Module Methods & Modulefulness Check\n  *\n  * In addition to functions, module methods also always have the\n  * definition present at compilation-time. We will now start to refer\n  * to the module methods as \"functions\".\n  *\n  * The definition of module functions are always present because of\n  * some restrictions on modules. Only declarations that have a\n  * signature and marked as `module` may bind to a module value. For\n  * example, \n  *\n  * ```mls\n  * val v: module M\n  * fun f(module m: M): module M\n  * ```\n  *\n  * This preserves the module definition even if the module is bound to\n  * other names. In order to maintain the correctness of this system,\n  * the resolver performs the extra checks to ensure that the definition\n  * of a module is never lost during re-binding. \n  *\n  * 1. Only declarations that have a signature and marked as `module`\n  *    may bind to a module value.\n  * 2. Only declarations of static members may bind to a module value.\n  *\n  * If a term evaluates to a module value (e.g., an application to a\n  * function returning a module, a reference to a module variable), it\n  * is said to be moduleful. All moduleful terms must only occur at\n  * certain locations in the program. For example, a moduleful term must\n  * not occur as a scrutinee because it may be re-bound to a different\n  * name, during when the module definition is lost.\n  *\n  * ### Symbol Resolution\n  *\n  * The resolver also resolves extra symbols that are not resolved\n  * during the elaboration. Consider the following example:\n  *\n  * ```mls\n  * val m: module M = M.v.v\n  * module M with\n  *   val v: module M = M\n  * ```\n  *\n  * At the time of elaboration on `M.v.v`, the elaborator hasn't\n  * elaborated the module `M` yet, so it merely knows that `M` is a\n  * module and `v` is a member of `M`. It doesn't know that `M.v` is a\n  * module, so it cannot resolve `M.v.v` to the correct member symbol.\n  * Therefore, resolution of such symbols is deferred to the resolver. \n  */\nclass Resolver(tl: TraceLogger)\n(using raise: Raise, state: State, ctx: Elaborator.Ctx, cfg: Config):\n  import tl.*\n  import Resolver.*\n  import Expect.*\n  import ModuleChecker.*\n  \n  given TraceLogger = tl\n  \n  /**\n    * Traverse a block and resolve any resolvable sub-terms. This is\n    * usually the entry point for the resolver.\n    */\n  def traverseBlock(blk: Term.Blk)(using ICtx): ICtx =\n  trace(s\"Traversing block: $blk\"):\n    traverseStmts(blk.stats).givenIn:\n      traverse(blk.res, expect = Any)\n      ictx\n  \n  @tailrec\n  final def traverseStmts(stmts: Ls[Statement])(using ICtx): ICtx = stmts match\n    case Nil => ictx\n    case stmt :: rest => \n      log(s\"Traversing statement: $stmt\")\n      val newICtx = stmt match\n        case tdf: Definition =>\n          traverseDefn(tdf)\n        \n        case t: Term =>\n          traverse(t, expect = Any)\n          ictx\n        \n        // Default Case. e.g., import statements, let bindings.\n        case _ =>\n          stmt.subTerms.foreach(traverse(_, expect = NonModule(N)))\n          ictx\n      \n      traverseStmts(rest)(using newICtx)\n  \n  /**\n    * Traverse a term: traverse the sub-terms, resolve the term, and\n    * check the modulefulness of the term.\n    */\n  def traverse(t: Term, expect: Expect)(using ictx: ICtx): Unit =\n  trace(s\"Traversing term: $t (expect = ${expect})\"):\n    \n    t match\n      case blk: Term.Blk =>\n        traverseBlock(blk)\n      case Term.Rcd(mut, stats) =>\n        traverseStmts(stats)\n      \n      case t: Term.IfLike =>\n        def simpleSplit(s: SimpleSplit): Unit = s match\n          case SimpleSplit.Cons(head: SimpleSplit.Head.Match, tail) =>\n            traverse(head.scrutinee, expect = NonModule(N))\n            traversePattern(head.pattern)\n            simpleSplit(head.consequent)\n            simpleSplit(tail)\n          case SimpleSplit.Cons(SimpleSplit.Head.Let(sym, term), tail) =>\n            traverse(term, expect = NonModule(N))\n            simpleSplit(tail)\n          case SimpleSplit.Else(default) =>\n            traverse(default, expect = Any)\n          case SimpleSplit.End =>\n        simpleSplit(t.split)\n        \n      case Term.Handle(lhs, rhs, args, derivedClsSym, defs, body) =>\n        traverse(rhs, expect = Class(S(\"The 'handle' keyword requires a statically known class.\")))\n        args.foreach(traverse(_, expect = NonModule(N)))\n        defs.foreach(d => traverseDefn(d.td))\n        traverse(body, expect = NonModule(N))\n      \n      case t: Term.Lam =>\n        t.params.foreach(traverseParam)\n        traverse(t.body, expect = NonModule(N))\n        \n      case t: Resolvable =>\n        resolve(t, prefer = expect, inAppPrefix = false, inTyPrefix = false, inCtxPrefix = false)\n      \n      case _ =>\n        t.subTerms.foreach(traverse(_, expect = NonModule(N)))\n    \n    \n    /* Post Traversal - Checks */\n    \n    // * The `module checks` checks the term's all possibly overloaded\n    // * definitions / declarations. It raise errors only if the term\n    // * can only be interpreted as a module.\n    \n    // TODO: currently it checks for only overloaded statically\n    // known classes, it might require checking other definitions also\n    // later.\n    if !cfg.noModuleCheck then\n      val evalsToModule = ModuleChecker.evalsToModule(t, prefer = expect)\n      val evalsToStaticClass = ModuleChecker.isStaticClass(t)\n      log(s\"Checking ${t}: expect ${expect}, evalsToModule = ${evalsToModule}, evalsToStaticClass = ${evalsToStaticClass}\")\n      \n      if expect.`module` && !evalsToModule then\n        raise(ErrorReport(msg\"Expected a module; found non-moduleful ${t.describe}.\" -> t.toLoc \n          :: expect.message))\n      if expect.nonModule && evalsToModule && !evalsToStaticClass then\n        raise(ErrorReport(msg\"Unexpected moduleful ${t.describe}.\" -> t.toLoc \n          :: expect.message))\n      \n      if expect.`class` && !evalsToStaticClass then\n        raise(ErrorReport(msg\"Expected a statically known class; found ${t.describe}.\" -> t.toLoc\n          :: expect.message))\n    \n  end traverse\n  \n  def traverseDefn(defn: Definition)(using ICtx): ICtx =\n  trace(s\"Resolving definition: $defn\"):\n    def traverseTermDef(tdf: TermDefinition) =\n      val TermDefinition(_k, _sym, _tsym, \n        pss, tps, sign, body, TermDefFlags(isMethod), modulefulness, annotations, comp\n      ) = tdf\n      /** \n       * Add the contextual parameters in pss to the ICtx so that they\n       * can later be referred (be resolved to) in the body of the term\n       * definition.\n       */\n      def withCtxParams(using ICtx): ICtx = pss\n        .filter(_.flags.ctx)\n        .foldLeft(ictx): (ictx, ps) => \n          ps.params.foldLeft(ictx): (ictx, p) => \n            p.sign match\n              case S(sign) =>\n                ictx + (resolveSign(sign, expect = Any), p.sym)\n              case N =>\n                // The type signature should be present because of the syntax of contextual parameter.\n                lastWords(s\"No type signature for contextual parameter ${defn.showDbg} at ${defn.toLoc}\")\n      \n      if isMethod && modulefulness.isModuleful then\n        raise(ErrorReport(msg\"${tdf.k.desc.capitalize} returning modules should not be a class member.\" -> defn.toLoc :: Nil))\n      \n      pss.foreach(_.allParams.foreach(traverseParam(_)))\n      tps.getOrElse(Nil).flatMap(_.subTerms).foreach(traverse(_, expect = NonModule(N)))\n      sign.foreach(traverseSign(_,\n        expect = if modulefulness.modified\n          then Module(S(msg\"${tdf.k.desc.capitalize} marked as returning a 'module' must have a module return type.\"))\n          else NonModule(S(msg\"${tdf.k.desc.capitalize} must be marked as returning a 'module' in order to have a module return type.\"))\n      ))\n      \n      body.foreach(traverse(_,\n        expect = if modulefulness.modified\n          then Module(S(msg\"${tdf.k.desc.capitalize} marked as returning a 'module' but not returning a module.\"))\n          else NonModule(S(msg\"${tdf.k.desc.capitalize} must be marked as returning a 'module' in order to return a module.\"))\n      )(using withCtxParams))\n      annotations.flatMap(_.subTerms).foreach(traverse(_, expect = NonModule(N)))\n    \n    def traverseClassLikeDef(cld: ClassLikeDef) =\n      /**\n       * Add the contextual parameters in the class-like definition to\n       * the ICtx so that they can later be referred (be resolved to) in\n       * the body of the class-like definition.\n       */\n      def withCtxParams(using ICtx): ICtx = (cld.paramsOpt.toList.iterator ++ cld.auxParams)\n        .filter(_.flags.ctx)\n        .foldLeft(ictx): (ictx, ps) => \n          ps.params.foldLeft(ictx): (ictx, p) => \n            p.sign match\n              case S(sign) => \n                val sym = p.fldSym.getOrElse(die)\n                ictx + (resolveSign(sign, expect = Any), sym)\n              case N =>\n                // The type signature should be present because of the syntax of contextual parameter.\n                lastWords(s\"No type signature for contextual parameter ${defn.showDbg} at ${defn.toLoc}\")\n      \n      cld.paramsOpt.foreach(_.allParams.foreach(traverseParam(_)))\n      cld.annotations.flatMap(_.subTerms).foreach(traverse(_, expect = NonModule(N)))\n      cld.ext.foreach(traverse(_, expect = NonModule(N)))\n\n      traverseBlock(cld.body.blk)(using withCtxParams)\n    \n    defn match\n    \n    // Case: instance definition. Add the instance to the context.\n    case defn @ TermDefinition(k = Ins, sym = sym, flags = TermDefFlags(isMethod), sign = sign) =>\n      log(s\"Resolving instance definition ${defn.showDbg}\")\n      traverseTermDef(defn)\n      sign match\n        case N =>\n          // By the syntax of instance defintiion, the type signature should be present.\n          lastWords(s\"No type signature for instance definition ${defn.showDbg} at ${defn.toLoc}\")\n        case S(sign) => \n          ictx + (resolveSign(sign, expect = Any), sym)\n    \n    // Case: Fun/Val definition. \n    case defn @ TermDefinition(k = Fun | ImmutVal | MutVal) =>\n      log(s\"Resolving ${defn.k.desc} definition $defn\")\n      traverseTermDef(defn)\n      ictx\n    \n    // Case: Class-like definition. Add the contextual parameters to the\n    // context and use the context to traverse through the body.\n    // Traverse through other subterms with original context.\n    case defn: ClassLikeDef =>\n      log(s\"Resolving ${defn.kind.desc} definition $defn\")\n      \n      defn match\n        case defn: PatternDef =>\n          // For pattern definitions, we need to traverse through the pattern body.\n          traversePattern(defn.pattern)\n        case _: ClassLikeDef => ()\n      \n      traverseClassLikeDef(defn)\n      ictx\n    \n    // Case: other definition forms. Just traverse through the sub-terms.\n    case t =>\n      t.subTerms.foreach(traverse(_, expect = NonModule(N)))\n      ictx\n  \n  def traversePattern(p: Pattern)(using ICtx): Unit = p match\n    case _: (Pattern.Wildcard | Pattern.Literal | Pattern.Range) => ()\n    case Pattern.Constructor(target, patternArguments) =>\n      traverse(target, expect = PatternConstructor(N))\n      patternArguments.foreach(_.foreach(traversePattern(_)))\n    case Pattern.Composition(_, left, right) =>\n      traversePattern(left)\n      traversePattern(right)\n    case Pattern.Negation(pattern) =>\n      traversePattern(pattern)\n    case Pattern.Concatenation(left, right) =>\n      traversePattern(left)\n      traversePattern(right)\n    case Pattern.Tuple(leading, spread) =>\n      leading.foreach(traversePattern(_))\n      spread.foreach: (_, spd, trailing) =>\n        traversePattern(spd)\n        trailing.foreach(traversePattern(_))\n    case Pattern.Record(fields) =>\n      fields.map((id, p) => traversePattern(p))\n    case Pattern.Chain(first, second) =>\n      traversePattern(first)\n      traversePattern(second)\n    case Pattern.Alias(pattern, _) =>\n      traversePattern(pattern)\n    case Pattern.Transform(pattern, _, transform) =>\n      traversePattern(pattern)\n      traverse(transform, expect = NonModule(N))\n    case Pattern.Annotated(pattern, annotations) =>\n      traversePattern(pattern)\n      annotations.map(_.toOption).flatten.foreach(traverse(_, expect = NonModule(N)))\n    case Pattern.Guarded(pattern, guard) =>\n      traversePattern(pattern)\n      traverse(guard, expect = NonModule(N))\n  \n  /**\n    * Resolve a resolvable term. This involves:\n    * 1. Resolving the sub-terms of the term. Because resolving a term\n    *    may require the sub-terms to be resolved first.\n    * 3. Resolving the (new) symbol of the term. If a term is moduleful,\n    *    the symbol should be some module symbol. The implicit arguments\n    *    resolved in the previous step should also be used to resolve\n    *    the symbol of the term.\n    * 2. Resolving the implicit arguments of the term. This may change\n    *    the semantic of the term, so it has to done before the symbol\n    *    resolution.\n    *\n    * @param inAppPrefix if true, the currently resolving term is the\n    * prefix of an App. The eta-expansion should only happens on the\n    * outer-most App term, rather than on the in-between App terms\n    * (otherwise the expansion might be redundant).\n    * \n    * @param inCtxPrefix if true, the currently resolving term is the\n    * prefix of an App where the implicit arguments are explicitly\n    * specified, e.g., `f(using 42)`. The implicit arguments should be\n    * resolved on the the App `f(using 42)`, but not on the base of the\n    * App `f`.\n    * @param inTyPrefix if true, the currently resolving term is the\n    * prefix of an TyApp, e.g., `f[Int]`. The implicit arguments should\n    * be resolved on the the TyApp `f[Int]`, but not on the base of the\n    * TyApp `f`.\n    */\n  def resolve(t: Resolvable, prefer: Expect, inAppPrefix: Bool, inCtxPrefix: Bool, inTyPrefix: Bool)(using ICtx): (Opt[CallableDefinition], ICtx) =\n  trace[(Opt[CallableDefinition], ICtx)](\n    s\"Resolving resolvable term: ${t}, (prefer = ${prefer}, inAppPrefix = ${inAppPrefix}, inCtxPrefix = ${inCtxPrefix}, inTyPrefix = ${inTyPrefix})\", \n    _ => s\"~> ${t.expanded} (sym = ${t.resolvedSym}, typ = ${t.resolvedTyp})\"\n  ):\n    // Resolve the sub-resolvable-terms of the term. \n    val (defn, newICtx1) = \n      t match\n      case _: Term.Resolved => lastWords(s\"Term ${t} is already resolved.\")\n      \n      // Note: the arguments of the App are traversed later because the\n      // definition is required.\n      case Term.App(lhs: Resolvable, args) =>\n        val result = args match\n          case t @ Term.CtxTup(_) => \n            resolve(lhs, prefer = Any, inAppPrefix = true, inCtxPrefix = true, inTyPrefix = inTyPrefix)\n          case _ => \n            resolve(lhs, prefer = Any, inAppPrefix = true, inCtxPrefix = inCtxPrefix, inTyPrefix = inTyPrefix)\n        resolveSymbol(t, prefer = prefer, sign = false)\n        resolveType(t, prefer = prefer)\n        result\n      case Term.App(lhs, _) =>\n        traverse(lhs, expect = Any)\n        (t.callableDefn, ictx)\n      \n      case Term.TyApp(lhs: Resolvable, targs) =>\n        resolve(lhs, prefer = prefer, inAppPrefix = inAppPrefix, inCtxPrefix = inCtxPrefix, inTyPrefix = true)\n        targs.foreach(traverseSign(_, expect = Any))\n        resolveSymbol(t, prefer = prefer, sign = false)\n        resolveType(t, prefer = prefer)\n        (t.callableDefn, ictx)\n      case Term.TyApp(lhs, targs) =>\n        traverse(lhs, expect = Any)\n        targs.foreach(traverse(_, expect = Any))\n        (t.callableDefn, ictx)\n      \n      case AnySel(pre: Resolvable, id, cls) =>\n        resolve(pre, prefer = Selectable(N), inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false)\n        cls.foreach:\n          case cls: Resolvable => resolve(cls, prefer = Class(N), inAppPrefix = false, inCtxPrefix = false, inTyPrefix = false)\n          case cls => traverse(cls, expect = Class(N))\n        resolveSymbol(t, prefer = prefer, sign = false)\n        resolveType(t, prefer = prefer)\n        (t.callableDefn, ictx)\n      case AnySel(pre, id, cls) =>\n        traverse(pre, expect = Selectable(N))\n        cls.foreach(traverse(_, expect = Class(N)))\n        (t.callableDefn, ictx)\n      \n      case Term.New(cls, args, rft) =>\n        // Term.New has only a type, but does not have a symbol.\n        traverse(cls, expect = Class(S(\"The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\")))\n        args.foreach(traverse(_, expect = NonModule(N)))\n        resolveType(t, prefer = prefer)\n        (t.callableDefn, ictx)\n      \n      case Term.LeadingDotSel(nme) => (N, ictx)\n\n      case Term.Ref(_: BlockMemberSymbol) =>\n        resolveSymbol(t, prefer = prefer, sign = false)\n        resolveType(t, prefer = prefer)\n        (t.callableDefn, ictx)\n      case Term.Ref(_) =>\n        resolveSymbol(t, prefer = prefer, sign = false)\n        resolveType(t, prefer = prefer)\n        (N, ictx)\n    \n    t.expandedResolvableIn: t =>\n      log(s\"Resolving resolvable term ${t} with sym = ${t.resolvedSym}, typ = ${t.resolvedTyp}\")\n      \n      // Fill the context with possibly the type arguments information.\n      val newICtx2 = newICtx1.givenIn:\n        defn match\n        case S(defn) =>\n          val tparams: Opt[Ls[Param]] = defn.tparams\n          val targs: Opt[Ls[Term]] = t match\n            case Term.TyApp(lhs, targs) => S(targs)\n            case _ => N\n          val newICtx = (tparams, targs) match\n            case (S(tparams), S(targs)) =>\n              if tparams.length != targs.length then\n                raise(ErrorReport(msg\"Expected ${tparams.length.toString()} type arguments, \" +\n                  msg\"got ${targs.length.toString()}\" -> t.toLoc :: Nil))\n              (tparams zip targs).foldLeft(ictx):\n                case (ictx, (tparam, targ)) => \n                  val sym = tparam.sym\n                  val typ = resolveSign(targ, expect = Any)\n                  log(s\"Resolving App with type arg ${sym} = $typ\")\n                  ictx.withTypeArg(sym, typ)\n            case (S(tparams), N) => tparams.foldLeft(ictx): \n              case (ictx, tparam) => \n                log(s\"Resolving App with type arg ${tparam.sym} unspecified\")\n                ictx\n            case (N, _) => ictx\n          newICtx\n        case N =>\n          ictx\n      \n      // Resolve the implicit arguments.\n      newICtx2.givenIn:\n        // Create a new term definition for App terms. The new term\n        // definition is for handling partial applications. \n        //\n        // For example: In `fun f(a)(b) = 42`, f's definition should\n        // indicate that it accepts two argument lists; f(42)'s definition\n        // should indicate that it accepts one argument list; f(42)(43)'s\n        // definition should indicate that it accepts zero argument lists.\n        //\n        // Currently, only parameters are processed for these new term\n        // definitions. The type parameters and result type are kept\n        // as-is. In the future we may take them into consideration as\n        // well.\n        val newDefn: Opt[CallableDefinition] = t match\n          case Term.App(lhs, as) => defn match\n            case S(defn @ CallableDefinition(params = ps :: pss)) =>\n              val (argCountUB, argCountLB) = as match\n              // Tup: regular arguments\n              case tup: (Term.Tup | Term.CtxTup) => \n                val fields = tup match\n                  case Term.Tup(fs) => fs\n                  case Term.CtxTup(fs) => fs\n                (\n                  !fields.exists(_.isInstanceOf[Spd]),\n                  (\n                    fields.count:\n                      case Fld(asc = S(_)) => false\n                      case _: Fld => true\n                      case _: Spd => false\n                  ) + (\n                    fields.collectFirst:\n                      case Fld(asc = S(_)) => 1\n                    .getOrElse(0)\n                  )\n                )\n              // Other: spread arguments\n              case _ => (false, 0)\n              \n              (ps.paramCountUB, argCountUB) match\n                case (true, true) => if ps.paramCountLB != argCountLB then\n                  raise(ErrorReport(msg\"Expected ${ps.paramCountLB.toString()} arguments, \" +\n                    msg\"got ${argCountLB.toString()}\" -> as.toLoc :: Nil))\n                case (true, false) => if ps.paramCountLB < argCountLB then\n                  raise(ErrorReport(msg\"Expected ${ps.paramCountLB.toString()} arguments, \" +\n                    msg\"got at least ${argCountLB.toString()}\" -> as.toLoc :: Nil))\n                case (false, true) => if ps.paramCountLB > argCountLB then\n                  raise(ErrorReport(msg\"Expected at least ${ps.paramCountLB.toString()} arguments, \" +\n                    msg\"got ${argCountLB.toString()}\" -> as.toLoc :: Nil))\n                case (false, false) => ()\n              \n              /**\n               * Zip (pair) a list of parameter and a list of arguments.\n               *\n               * If there are some spread parameters, we are not able to\n               * pair all the parameters and arguments statically. We will\n               * try to pair as many as possible.\n               */\n              @tailrec\n              def zip(ps: Ls[Param], as: Ls[Elem], recordArgs: Ls[Fld], beforeSpread: Bool): Ls[Fld] = (ps, as) match\n                // The spread argument takes all the remaining arguments.\n                case (ps, (a: Spd) :: as) =>\n                  traverse(a.term, expect = NonModule(N))\n                  zip(ps, as, recordArgs, false)\n                case (ps, a :: as) if !beforeSpread =>\n                  a.subTerms.foreach(traverse(_, expect = NonModule(N)))\n                  zip(ps, as, recordArgs, false)\n                \n                // Pair the parameter and the argument.\n                case (p :: ps, (a @ Fld(asc = N)) :: as) =>\n                  traverse(a.term, \n                    // note: we accept regular arguments for module parameters\n                    expect = if p.modulefulness.isModuleful\n                      then Any\n                      else NonModule(S(msg\"Module argument passed to a non-module parameter.\"))\n                  )\n                  zip(ps, as, recordArgs, true)\n                \n                // Record Arguments. They are pushed to the last parameter.\n                case (_, (a @ Fld(asc = S(_))) :: as) =>\n                  zip(ps, as, a :: recordArgs, true)\n                \n                // If there are more parameters, there must be a spread\n                // argument, or some record arguments before.\n                case (p :: ps, Nil) =>\n                  recordArgs.reverse\n                  \n                // If there are more arguments, all of them go to `restParam`.\n                case (Nil, a :: as) =>\n                  a.subTerms.foreach(traverse(_, expect = NonModule(N)))\n                  zip(Nil, as, recordArgs, beforeSpread)\n                \n                case (Nil, Nil) => \n                  recordArgs.reverse\n              end zip\n              \n              // Application arguments that are not tuples represent spreads, as in `f(...arg)`\n              val args = as match\n                case Term.Tup(args) => args\n                case Term.CtxTup(args) => args\n                case spd => Spd(SpreadKind.Eager, spd) :: Nil\n              \n              // The lhs of the App is already traversed by the recursive\n              // `traverse` or `resolve` at the beginning.\n              val recordArgs = zip(ps.params, args, Nil, true)\n              recordArgs.foreach:\n                _.subTerms.foreach(traverse(_, expect = NonModule(N)))\n              S(defn.copy(params = pss))\n            case _ =>\n              traverse(as, expect = NonModule(N))\n              N\n          case _ => defn\n        \n        // Resolve the implicit arguments.\n        newDefn match\n        case S(defn) if !inCtxPrefix && !inTyPrefix =>\n          /**\n           * Resolve all possible implicit arguments and perform eta-expansion.\n           * \n           * @return (1) A lambda accepting a term, applying the implicit\n           * arguments and performing eta-expansion on the term, and\n           * return the result. (2) The residual parameter lists that are not\n           * consumed by this resolution.\n           */\n          def expand(pss: Ls[ParamList], lam: Term => Term, bod: Term => Term): (Term => Term, Ls[ParamList]) =\n            pss match\n              // The current parameter list is not a using clause, and\n              // there are more using clauses in later parameter lists,\n              // so perform eta-expansion.\n              case (ps @ ParamList(\n                flags = ParamListFlags(ctx = false)\n              )) :: pss if !inAppPrefix && pss.exists(_.flags.ctx) =>\n                val as = ps.params.map(p => Fld(p.flags, p.sym.ref().dontResolve, N))\n              //   val as = ps.params.map(p => Fld(p.flags, p.sym.ref().resolve, N))\n                val newLam = (t: Term) => \n                  lam(Term.Lam(ps, t))\n                val newBod = (t: Term) =>\n                  Term.App(bod(t), Term.Tup(as)(DummyTup))(DummyApp, N, FlowSymbol(\"implicit app\")).dontResolve\n                expand(pss, newLam, newBod)\n              // The current parameter list is a using clause, so resolve\n              // implicit arguments from the context.\n              case (ps @ ParamList(\n                flags = ParamListFlags(ctx = true)\n              )) :: pss =>\n                val as = ps.params.map(resolveArg(_)(t))\n                val newBod = (t: Term) =>\n                  Term.App(bod(t), Term.Tup(as)(DummyTup))(DummyApp, N, FlowSymbol(\"implicit app\")).dontResolve\n                expand(pss, lam, newBod)\n              case _ =>\n                ((t: Term) => lam(bod(t)), pss)\n          \n          val (expansionFn, pss) = expand(defn.params, identity, identity)\n          if defn.params.length =/= pss.length then\n            val expansion = expansionFn(t.duplicate)\n            t.expand(S(expansion))\n            expansion match // * expansion may change the semantics, thus symbol is also changed\n            case r: Resolvable => \n              resolveSymbol(r, prefer = prefer, sign = false)\n              resolveType(r, prefer = prefer)\n            case _ => ()\n          \n          (S(defn.copy(params = pss)), ictx)\n        case S(defn) =>\n          t.dontResolve\n          (S(defn), ictx)\n        case _ =>\n          t.dontResolve\n          (N, ictx)\n  \n  def disambSym(expect: Expect, sign: Bool)(bms: BlockMemberSymbol): Opt[DefinitionSymbol[?]] =\n    expect match\n      // If it is expecting a class or module specifically, cast the symbol.\n      case _: Module => bms.asMod\n      case _: Class => bms.asCls\n      case _: Selectable => bms.asModOrObj orElse bms.asTrm\n      // If it is expecting a generic symbol, use asPrinciple for the \"default interpretation\".\n      case _: (Any.type | NonModule) if sign =>\n        bms.asTpe\n      case _: (Any.type | NonModule) =>\n        bms.asPrincipal\n      case _: PatternConstructor =>\n        bms.asCls orElse\n        bms.asObj orElse\n        bms.asAls orElse\n        bms.asPat orElse\n        bms.asMod orElse\n        bms.asTrm\n        \n        \n  \n  /**\n   * Resolve the symbol for a resolvable term, which was not resolved by\n   * the elaborator due to unready definitions. After the symbol\n   * resolution, the term is expanded into the same term, \n   *\n   * In particular, for Sel and SynthSel terms, it checks the definition\n   * of the prefix (note that the prefix should be resolved before this\n   * term is resolved), and if prefix is moduleful, it resolves the\n   * symbol for the member to be selected.\n   *\n   * Then, for all terms including Sel and SynthSel, it unwraps the\n   * parameters as an App, even for a generalized \"App\" that has no\n   * parameter list (in order to handle implicit applications), and\n   * resolves the symbol for the result of this App.\n   *\n   * This also expands the LHS `Foo` of a selection to `Foo.class` if\n   * the selection is selecting a static member from a lifted module.\n   */\n  def resolveSymbol(t: Resolvable, prefer: Expect, sign: Bool)(using ictx: ICtx): Unit =\n  trace[Unit](\n    s\"Resolving symbol for term: ${t} (prefer = ${prefer})\", \n    _ => s\"-> (sym = ${t.resolvedSym}, typ = ${t.resolvedTyp})\"\n  ):\n    // If the term has an expansion already, it is likely that there is\n    // an internal error because otherwise we should resolve the symbol\n    // of the expansion instead.\n    /*\n    if t.hasExpansion then lastWords:\n      s\"resolveSymbol: term ${t} already has an expansion ~> ${t.expanded}, \" +\n      s\"thus the resolver cannot resolve its symbol\"\n    */\n    // * We can't perform the check because of UCS and handler reusing terms.\n    \n    t.expandedResolvableIn: t =>\n      t match\n      \n      // The symbol resolution already failed in the elaborator. We will\n      // not try to resolve it again in the resolver.\n      case _ if t.symbol.exists(_.isInstanceOf[ErrorSymbol]) => ()\n      \n      case t @ Term.Ref(bsym: BlockMemberSymbol) =>\n        log(s\"Resolving symbol for reference ${t} (bsym = ${bsym})\")\n        val sym = disambSym(prefer, sign = sign)(bsym)\n        sym.foreach: sym =>\n          t.expand(S((t.duplicate.resolved(sym))))\n        resolveType(t, prefer = prefer)\n        log(s\"Resolved symbol for ${t}: ${sym}\")\n      \n      case t @ AnySel(lhs: Resolvable, id, cls) => lhs.expandedResolvableIn: lhs =>\n        log(s\"Resolving symbol for selection ${t}, defn = ${lhs.defn}\")\n        \n        val clsDefn = cls.flatMap: sym =>\n          sym.resolvedSym.flatMap(_.asCls).map: clsSym =>\n            clsSym.defn.getOrElse(die)\n        \n        // Singleton Definitions\n        lhs.singletonDefn.foreach: defn =>\n          val fsym = defn.body.members.get(id.name)\n          fsym match\n            case S(bms: BlockMemberSymbol) =>\n              log(s\"Resolving symbol for ${t}, defn = ${lhs.defn}\")\n              disambSym(prefer, sign)(bms) match\n                case S(ds) =>\n                  t.expand(S(t.withSym(bms).resolved(ds)))\n                case N =>\n                  log(s\"Unable to disambiguate ${bms}\")\n                  t.expand(S(t.withSym(bms)))\n              log(s\"Resolved symbol for ${t}: ${bms}\")\n            case N => \n              t.expand(S(t.withSym(ErrorSymbol(id.name, Tree.Dummy))))\n              raise: \n                ErrorReport(\n                  msg\"${defn.kind.desc.capitalize} '${defn.sym.nme}' \" +\n                  msg\"does not contain member '${id.name}'\" -> t.toLoc :: Nil,\n                  extraInfo = S(defn))\n        \n        // Class-Like Definitions\n        (clsDefn orElse lhs.typDefn).foreach: \n          case defn: ClassLikeDef =>\n            // A reference to a member within the class is elaborated into a SynthSel, e.g.,\n            // class C with\n            //   fun f = 42\n            //   f\n            // The `f` in the body is elaborated into SynthSel(class:Foo, 'f').\n            val fsym = defn.body.members.get(id.name)\n            fsym match\n              case S(bms: BlockMemberSymbol) =>\n                log(s\"Resolving symbol for ${t}, defn = ${lhs.defn}\")\n                disambSym(prefer, sign)(bms) match\n                  case S(ds) =>\n                    t.expand(S(t.withSym(bms).resolved(ds)))\n                  case N =>\n                    log(s\"Unable to disambiguate ${bms}\")\n                    t.expand(S(t.withSym(bms)))\n                log(s\"Resolved symbol for ${t}: ${bms}\")\n              case N =>\n                // TODO @Harry: Appropriately resolve all selections on classes.\n                // - MLscript programs selecting JS members without properly defining them.\n                // - Inherited members.\n          case defn =>\n            log(s\"Unsupported selection from definition: ${defn}\")\n      \n      case t @ Term.New(cls, _, N) =>\n        // cls is already resolved, so the symbol should be present;\n        // otherwise, there is already an error raised.\n        cls.resolvedSym match\n          case S(clsSym: ClassSymbol) =>\n            t.expand(S(t.duplicate.resolved(clsSym)))\n          case S(sym) =>\n            lastWords(s\"Expected a class symbol; found ${sym} for term ${t}.\")\n          case N =>\n      \n      case _ =>\n  \n  /**\n   * Resolve the type for a resolvable term representing an expression\n   * (as opposed to a term representing a type, i.e., signature). The\n   * resolvable term should should already be symbol-resolved by\n   * `resolveSymbol`. After this type resolution, the resolvable term is\n   * expanded into a copy of the term with the `typ` field set to the\n   * resolved type.\n   */\n  def resolveType(t: Resolvable, prefer: Expect)(using ictx: ICtx): Unit = t.expandedResolvableIn: t =>\n    trace[Unit](\n      s\"Resolving the type for term: ${t} (prefer = ${prefer}, sym = ${t.resolvedSym})\", \n      _ => s\"-> typ = ${t.resolvedTyp}\"\n    ):\n      def disambSym(bms: BlockMemberSymbol): Opt[DefinitionSymbol[?]] = prefer match\n        case _: Module => bms.asMod\n        case _: Class => bms.asCls\n        case _: Selectable => bms.asModOrObj orElse bms.asTrm\n        case _: (Any.type | NonModule) => bms.asPrincipal\n      \n      t match\n      case Term.New(cls, _, N) => cls.resolvedSym match\n        case S(clsSym: ClassSymbol) =>\n          val ty = Type.Ref(clsSym, Nil)\n          t.expand(S(t.withTyp(ty)))\n        case _ =>\n          // cls is already resolved, so the symbol should be present;\n          // otherwise, there is already an error raised.\n          ()\n      case t @ Apps(base: Resolvable, ass) => \n        val decl = base.resolvedSym match\n          case S(bms: BlockMemberSymbol) => \n            val disambBms = disambSym(bms)\n            log(s\"Disambiguate ${bms} (${bms.asTrm}) into ${disambBms} (defn = ${disambBms.map(_.defn)}), preferring ${prefer}\")\n            disambBms match\n            case S(disambBms) => disambBms.defn\n            case N => bms.asPrincipal.flatMap(_.defn)\n          case S(bls: BlockLocalSymbol) => bls.decl\n          case S(ds: DefinitionSymbol[?]) => ds.defn\n          case _ => N\n        log(s\"Declaration: ${decl}\")\n        decl match\n        case S(defn: TermDefinition) if defn.params.length === ass.length =>\n          val ty = defn.sign.map(resolveSign(_, expect = Expect.fromModulefulness(defn.modulefulness)))\n          ty.foreach(ty => t.expand(S(t.withTyp(ty))))\n        case S(defn: Param) if ass.isEmpty =>\n          val ty = defn.sign.map(resolveSign(_, expect = Expect.fromModulefulness(defn.modulefulness)))\n          ty.foreach(ty => t.expand(S(t.withTyp(ty))))\n        case S(defn: ModuleOrObjectDef) if ass.isEmpty =>\n          val ty = Type.Ref(defn.sym, Nil)\n          t.expand(S(t.withTyp(ty)))\n        case S(defn: ClassDef) => base match\n          case Term.Ref(inner: InnerSymbol) =>\n            val ty = Type.Ref(defn.sym, Nil)\n            t.expand(S(t.withTyp(ty)))\n          case _ =>\n        case _ =>\n      case _ =>\n  end resolveType\n  \n  def resolveArg(p: Param)(lhs: Term)(using ictx: ICtx): Elem =\n    log(s\"Resolving implicit argument, expecting a ${p.sign}\")\n    p.sign match\n      case S(sign) => \n        // FIXME[Harry]: Don't re-resolve signatures for every argument!\n        val ty = resolveSign(sign, expect = if p.modulefulness.modified then Module(N) else NonModule(N))\n        log(s\"Resolving implicit argument, expecting a ${ty.show}\")\n        ictx.query(ty) match\n        case R(i) =>\n          log(s\"Resolved ${p.sign} with instance ${i}\")\n          val ref = i.sym.ref()\n          traverse(ref,\n            // note: we accept regular arguments for module parameters\n            expect = if p.modulefulness.isModuleful\n              then Any\n              else NonModule(S(msg\"Module argument passed to a non-module parameter.\")),\n          )\n          Fld(p.flags, ref, N)\n        case L(msgs) =>\n          raise(ErrorReport(\n            msg\"Cannot query instance of type ${ictx.showTy(ty)} for call: \" -> lhs.toLoc ::\n            msg\"Required by contextual parameter declaration: \" -> p.toLoc :: msgs))\n          Fld(FldFlags.empty, Term.Error, N)\n      case N =>\n        // By the syntax of contextual parameter, \n        // the type signature should be present.\n        lastWords(s\"No type signature for contextual parameter ${p.showDbg} at ${p.toLoc}\")\n  \n  def traverseParam(p: Param)(using ictx: ICtx): Unit =\n    log(s\"Resolving parameter ${p.showDbg}\")\n    val ty = p.sign.map(sign =>\n      resolveSign(sign, expect = if p.modulefulness.modified then Module(N) else NonModule(N)))\n    p.signType = ty\n    if p.modulefulness.modified then\n      if p.sign.isEmpty then\n        raise(ErrorReport(msg\"Module parameter must have explicit type.\" -> p.sym.toLoc :: Nil))\n    p.sign.foreach:\n      traverseSign(_, \n        expect = if p.modulefulness.modified\n          then Module(S(msg\"Module parameter must have a module type.\"))\n          else NonModule(S(msg\"Non-module parameter must have a non-module type.\")),\n      )\n  \n  /**\n   * Traverse through a term that is expected to be a type. In this\n   * process, it reports any non-type terms, checks if the term\n   * satisfies the expectation, resolves the symbol of the term, and\n   * checks the arity of type params/args.\n   *\n   * @param inAppPrefix if true, the currently traversing term is the\n   * prefix of an TyApp. \n   * @param expect the expectation on the type. See [[Expect]] for\n   * details.\n   */\n  def traverseSign(t: Term, expect: Expect, inAppPrefix: Bool = false)(using ictx: ICtx): Unit =\n  trace(s\"Traversing type ${t}, expecting ${expect}\"):\n    \n    // * Traverse through the sub-terms.\n    t match\n    case Term.Ref(_) =>\n    case Term.Lit(_) =>\n    case Term.Tup(_) => t.subTerms.foreach(traverse(_, expect = NonModule(N)))\n    case Term.UnitVal() =>\n    // Literals with operators. e.g., -42\n    case Term.App(Term.Ref(_: BuiltinSymbol), Term.Tup(Fld(term = Term.Lit(_)) :: Nil)) =>\n    \n    // Selection. The prefix should be a term, rather than a type, that\n    // can be selected from. This should not be a selection projection.\n    case AnySel(base, _, N) =>\n      base.subTerms.foreach(traverse(_, expect = Any))\n    \n    // Type Application. Traverse the type constructor and arguments,\n    // respectively.\n    case Term.TyApp(con, targs) => \n      traverseSign(con, expect = expect, inAppPrefix = true)\n      targs.foreach(traverseSign(_, expect = Expect.NonModule(S(\"Type arguments should be non-moduleful types.\"))))\n    \n    // Complex type: Function type, Wildcard type, Composed type,\n    // Negation type, Forall type, \n    case t: (Term.FunTy | Term.WildcardTy | Term.CompType | Term.Neg | Term.Forall | Term.Constrained | Term.Tup) =>\n      t.subTerms.foreach(traverseSign(_, expect = Expect.NonModule(N)))\n    \n    // t is not a type.\n    case _ => \n      raise(ErrorReport(msg\"Expected a type, got ${t.describe}\" -> t.toLoc :: Nil))\n      return\n    \n    \n    \n    // * Resolve the symbol and type of the term.\n    val typ = t match\n      case t: Resolvable =>\n        resolveSymbol(t, prefer = expect, sign = true)\n        val typ = resolveSign(t, expect = expect)\n        t.expandedResolvableIn(_.withTyp(typ))\n        typ\n      case _ =>\n        val typ = resolveSign(t, expect = expect)\n        typ\n    \n    // * Check if the term satisfies the expectation.\n    // * Check the arity of type params/args.\n    typ match \n      case Type.Ref(sym: TypeSymbol, targs) if !inAppPrefix =>\n        sym.defn.flatMap(CallableDefinition.fromDefn(_)).foreach: \n          case CallableDefinition(tparams = tparams) =>\n            val tparamsNum = tparams.map(_.length)\n            val targsNum = targs.length\n            if tparamsNum.getOrElse(0) =/= targsNum then\n              val tparamsMsg = tparamsNum.getOrElse(\"no\").toString\n              val targsMsg = if targsNum === 0 then \"none\" else targsNum.toString\n              raise:\n                ErrorReport:\n                  msg\"Expected ${tparamsMsg} type arguments, \"\n                  + msg\"got ${targsMsg}\" -> t.toLoc :: Nil\n      case Type.Ref(sym: VarSymbol, targs) if !inAppPrefix =>\n        // TODO: check arity?\n      case _ =>\n  \n  /**\n   * Given a symbol-resolved term that represents a type, resolve the\n   * type that it represents.\n   */\n  def resolveSign(t: Term, expect: Expect): Type =\n    def raiseError(sym: Opt[Symbol] = N) =\n      val defnMsg = sym match\n        case S(sym: DefinitionSymbol[?]) => sym.defn match\n          case S(defn: TermDefinition) => s\" denoting ${defn.k.desc} '${defn.sym.nme}'\"\n          case S(defn: ClassLikeDef) => s\" denoting ${defn.kind.desc} '${defn.sym.nme}'\"\n          case _ => \"\"\n        case _ => \"\"\n      \n      expect match\n      case expect: Module => raise:\n        ErrorReport(msg\"Expected a module type; found ${t.describe}${defnMsg}.\" -> t.toLoc\n          :: expect.message)\n      case expect: Class => raise:\n        ErrorReport(msg\"Expected a statically resolvable class; found ${t.describe}${defnMsg}.\" -> t.toLoc\n          :: expect.message)\n      case expect: NonModule => raise:\n        ErrorReport(msg\"Expected a non-module type; found ${t.describe}${defnMsg}.\" -> t.toLoc\n          :: expect.message)\n      case _ => raise:\n        ErrorReport(msg\"Expected a type, got ${t.describe}${defnMsg}\" -> t.toLoc :: Nil)\n      Type.Error\n    \n    t match\n      // If the term is a type application, e.g., T[A, ...], resolve the\n      // type constructor and arguments respectively.\n      case Term.TyApp(con, args) => resolveSign(con, expect = expect) match\n        case Type.Ref(sym, Nil) =>\n          Type.Ref(sym, args.map(resolveSign(_, expect = Any)))\n        case _ =>\n          raise(ErrorReport(msg\"Expected a type constructor, got ${t.describe}\" -> t.toLoc :: Nil))\n          Type.Error\n      \n      case Term.Lit(_) => if expect.module \n        then raiseError()\n        else Type.NotImplemented // TODO: Support Lit\n      case Term.UnitVal() => if expect.module\n        then raiseError()\n        else Type.NotImplemented // TODO: Support UnitVal\n      case Term.App(Term.Ref(_: BuiltinSymbol), Term.Tup(Fld(term = Term.Lit(_)) :: Nil)) => if expect.module\n        then raiseError()\n        else Type.NotImplemented // TODO: Support Lit with operator\n      case _: (Term.FunTy | Term.WildcardTy | Term.CompType | Term.Neg | Term.Forall | Term.Constrained | Term.Tup | Term.Lit) =>\n        if expect.module\n        then raiseError()\n        else Type.NotImplemented // TODO: Support complex types\n      \n      // Otherwise, resolve the term directly.\n      case _ => t.resolvedSym match\n        // A VarSymbol is probably a type parameter.\n        case S(sym: VarSymbol) if ModuleChecker.isTypeParam(sym) =>\n          if expect.module \n          then raiseError(S(sym))\n          else Type.Ref(sym, Nil)\n        case S(tsym) =>\n          val dtsym = expect match\n          case expect: Module => tsym.asMod.getOrElse(raiseError(S(tsym)))\n          case expect: Class => tsym.asCls.getOrElse(raiseError(S(tsym)))\n          case expect: NonModule => tsym.asNonModTpe.getOrElse(raiseError(S(tsym)))\n          case _ => tsym.asTpe.getOrElse(raiseError(S(tsym)))\n          dtsym match\n            case dtsym: TypeSymbol => Type.Ref(dtsym, Nil)\n            case _ => Type.Error\n        case N =>\n          raise(ErrorReport(msg\"Expected a type, got a non-type ${t.describe}\" -> t.toLoc :: Nil))\n          Type.Error\n\nend Resolver\n\n\nobject ModuleChecker:\n  \n  extension (s: Split)\n    private def results: Ls[Term] = \n      def go(s: Split): Ls[Term] = s match\n        case Split.Cons(head, tail) => go(head.continuation) ::: go(tail)\n        case Split.Let(_, _, tail) => go(tail)\n        case Split.Else(term) => term :: Nil\n        case Split.End => Nil\n      go(s)\n  \n  /** Checks if a symbol is of a type parameter. */\n  def isTypeParam(sym: VarSymbol): Bool = sym.decl\n    .exists(_.isInstanceOf[TyParam])\n  \n  import Resolver.Expect\n  \n  /** Checks the term's modulefulness. */\n  def evalsToModule(t: Term, prefer: Expect): Bool =\n    def checkDecl(decl: Declaration): Bool = decl match\n      /* Type Declaration / Defintiions */\n      // A type is not moduleful if it is not a module. (obvious!)\n      case ModuleOrObjectDef(kind = Mod) => true\n      // Objects use ModuleDef but is not moduleful.\n      case _: TypeLikeDef => false\n      \n      /* Term Declarationis / Definitions */\n      case defn: TermDefinition => defn.modulefulness.isModuleful\n      case defn: Param => defn.modulefulness.isModuleful\n      // A type param is not a module because it is a type.\n      case defn: TyParam => false\n    \n    def checkSym(sym: Symbol): Bool = sym match\n      case sym: BuiltinSymbol => false\n      case sym: BlockLocalSymbol => sym.decl.exists(checkDecl)\n      case sym: MemberSymbol => prefer match\n        case Expect.Module(_) => sym.existsModuleful\n        case _ => !sym.existsNonModuleful\n      \n      case sym => lastWords(s\"unsupported symbol type ${sym.getClass} (${sym})\")\n    \n    t match\n    case Term.Blk(_, res) => evalsToModule(res, prefer = prefer)\n    case Term.IfLike(`if`, IfLikeForm.ReturningIf, split) => split.results.exists(evalsToModule(_, prefer = prefer))\n    case t: Resolvable => t.resolvedTyp match\n      case S(ty) => ty.symbol.map(checkSym(_)).getOrElse(false)\n      case N => false\n    case _ => false\n  \n  def isStaticClass(t: Term): Bool = t.resolvedSym.exists(_.asCls.isDefined)\n\nend ModuleChecker\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/SimpleSplit.scala",
    "content": "package hkmc2\npackage semantics\n\nimport mlscript.utils.*, shorthands.*, syntax.*, Tree.{BoolLit, Keywrd}\nimport Keyword.{`do`, `else`, `then`}, utils.TL, Elaborator.{Ctx, State}\n\n/**\n  * Similar to `Split` but contains nested patterns (i.e., class `Pattern`).\n  */\nenum SimpleSplit extends AutoLocated with ProductWithTail:\n  import SimpleSplit.Head\n  \n  case Cons(branch: SimpleSplit.Head, tail: SimpleSplit)\n  /**\n    * The end of splits with a default term.\n    * \n    * @param default The default term.\n    * @param kw The keyword of `then` or `else`. It is `None` if the split is\n    *           the topmost one.\n    */\n  case Else(default: Term)(val kw: Opt[Keywrd[`else`.type | `then`.type | `do`.type]])\n  case End\n  \n  inline def ~:(head: SimpleSplit.Head): Cons = Cons(head, this)\n  \n  def ~~:(front: SimpleSplit): SimpleSplit =\n    front match\n      case Cons(head, tail) => Cons(head, tail ~~: this)\n      case els: Else => els\n      case End => this\n  \n  protected def children: Vector[Located] = this match\n    case Cons(branch, tail) => Vector.double(branch, tail)\n    case els @ Else(default) => els.kw match\n      case N => Vector.single(default)\n      case S(kw) => Vector.double(kw, default)\n    case End => Vector.empty\n  \n  def subTerms: Vector[Term] = this match\n    case Cons(branch, tail) => branch.subTerms.toVector ++ tail.subTerms\n    case Else(default) => Vector.single(default)\n    case End => Vector.empty\n  \n  /** Free variable names, accounting for pattern bindings in match heads\n    * and let bindings in let heads. */\n  lazy val freeVars: Set[Str] = this match\n    case Cons(head, tail) => head match\n      case Head.Match(scrutinee, pattern, consequent) =>\n        val patVarNames = pattern.variables.varMap.keySet\n        scrutinee.freeVars ++ pattern.subTerms.iterator.flatMap(_.freeVars) ++\n          (consequent.freeVars -- patVarNames) ++ tail.freeVars\n      case Head.Let(binding, term) =>\n        term.freeVars ++ (tail.freeVars - binding.nme)\n    case Else(default) => default.freeVars\n    case End => Set.empty\n  \n  def showDbg(using DebugPrinter): Str = this match\n    case Cons(branch, tail) => s\"${branch.showDbg}; ${tail.showDbg}\"\n    case Else(default) => s\"else ${default.showDbg}\"\n    case End => \"\"\n  \n  def prettyPrint(kw: Keyword.SplitLike)(using DebugPrinter): Str = SimpleSplit.prettyPrint(this, kw)\n  \n  /** Get the results of all branches. */\n  def results: Ls[Term] =\n    def go(acc: Ls[Term], split: SimpleSplit): Ls[Term] = split match\n      case Cons(_: Head.Let, tail) => go(acc, tail)\n      case Cons(Head.Match(_, _, consequent), alternative) =>\n        go(go(acc, consequent), alternative)\n      case Else(default) => default :: acc\n      case End => acc\n    go(Nil, this).reverse\n  \n  /** This field is designed to be compatible with bbML. */\n  private var _expandedSplit: Opt[Split] = N\n  \n  /**  */\n  def getExpandedSplit(using TL, Ctx, State, Raise): Split = _expandedSplit.getOrElse:\n    val split = Split.from(this)\n    _expandedSplit = S(split)\n    split\n  \n  def mkClone(using State): SimpleSplit = this match\n    case Cons(head, tail) => Cons(head match\n      case Head.Match(scrutinee, pattern, consequent) =>\n        Head.Match(scrutinee.mkClone.asInstanceOf, pattern, consequent.mkClone) // TODO: clone `pattern`?\n      case Head.Let(binding, term) => Head.Let(binding, term.mkClone)\n    , tail.mkClone)\n    case e @ Else(default) => Else(default.mkClone)(e.kw)\n    case End => End\n  \nend SimpleSplit\n\nobject SimpleSplit:\n  \n  object IfThenElse:\n    def unapply(split: SimpleSplit): Opt[(Term, Term, Term)] = split match\n      case Cons(\n          Head.Let(binding, condition),\n          Cons(Head.Match(\n            scrutinee,\n            Pattern.Literal(BoolLit(true)), Else(consequent)),\n            Else(alternative))\n      ) if scrutinee.sym === binding => S((condition, consequent, alternative))\n      case _ => N\n  \n  /** Represents a single branch of a simple split. */\n  enum Head extends AutoLocated:\n    case Match(scrutinee: Term.Ref, pattern: Pattern, consequent: SimpleSplit)\n    case Let(binding: BlockLocalSymbol, term: Term)\n    \n    def subTerms: Vector[Term] = this match\n      case Match(scrutinee, pattern, consequent) =>\n        scrutinee +: (pattern.subTerms ++ consequent.subTerms)\n      case Let(_, term) => Vector.single(term)\n    \n    def showDbg(using DebugPrinter): Str = this match\n      case Match(scrutinee, pattern, consequent) =>\n        val consequentStr = consequent match\n          case Cons(_, _) => s\"and ${consequent.showDbg}\"\n          case Else(default) => s\"then ${default.showDbg}\"\n          case End => \"then {}\"\n        s\"${scrutinee.showDbg} is ${pattern.showDbg} ${consequentStr}\"\n      case Let(binding, term) => s\"let ${binding.nme} = ${term.showDbg}\"\n    \n    protected def children: Vector[Located] = this match\n      case Match(scrutinee, pattern, consequent) =>\n        Vector.triple(scrutinee, pattern, consequent)\n      case Let(binding, term) => Vector.double(binding, term)\n  \n  private[semantics] object prettyPrint:\n    /** Represents lines with indentations. */\n    type Lines = Ls[(Int, Str)]\n    \n    extension (lines: Lines)\n      /** Increase the indentation of all lines by one. */\n      def indent: Lines = lines.map:\n        case (n, line) => (n + 1, line)\n    \n      /** Make a multi-line string. */\n      def toIndentedString: Str = lines.iterator.map:\n        case (n, line) => \"  \" * n + line\n      .mkString(\"\\n\")\n    \n    extension (prefix: String)\n      /**\n        * If the first line does not have indentation and the remaining lines are\n        * indented, prepend the given string to the first line. Otherwise, prepend\n        * the given string to the first line and indent all remaining lines.\n        *\n        * When you want to amend the title of lines, you should use this function.\n        */\n      def #:(lines: Lines): Lines = lines match\n        case all @ ((0, line) :: lines) if lines.forall(_._1 > 0) =>\n          if prefix.isEmpty then all else (0, s\"$prefix $line\") :: lines\n        case lines => (0, prefix) :: lines.indent\n    \n    inline def apply(s: SimpleSplit, kw: Keyword.SplitLike)(using DebugPrinter): Str = showSplit(kw.name, s)\n    \n    /** Show a split as a list of lines.\n     *  @param isFirst whether this is the first and frontmost branch\n     *  @param isTopLevel whether this is the top-level split\n     */\n    private[semantics] def split(s: SimpleSplit, isFirst: Bool, isTopLevel: Bool)(using DebugPrinter): Lines = s match\n      case SimpleSplit.Cons(head: Head.Match, tail) => (branch(head, isTopLevel) match\n        case (n, line) :: tail => (n, line) :: tail\n        case Nil => Nil\n      ) ::: split(tail, false, isTopLevel)\n      case SimpleSplit.Cons(Head.Let(nme, rhs), tail) =>\n        (0, s\"let $nme = ${rhs.showDbg}\") :: split(tail, false, true)\n      case SimpleSplit.Else(t) =>\n        (if isFirst && !isTopLevel then \"\" else \"else\") #: term(t)\n      case SimpleSplit.End => Nil\n    \n    private def term(t: Statement)(using DebugPrinter): Lines = (0, t.showDbg) :: Nil\n    \n    private def branch(b: Head.Match, isTopLevel: Bool)(using DebugPrinter): Lines =\n      val Head.Match(scrutinee, pattern, consequent) = b\n      val lines = split(consequent, true, false)\n      val prefix = s\"${scrutinee.sym} is ${pattern.showDbg}\"\n      consequent match\n        case SimpleSplit.Else(_) => (prefix + \" then\") #: lines\n        case _ => (prefix + \" and\") #: lines\n    \n    private def showSplit(prefix: Str, s: SimpleSplit)(using DebugPrinter): Str =\n      val lines = split(s, true, true)\n      (if prefix.isEmpty then lines else prefix #: lines).toIndentedString\n  \n  end prettyPrint\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/Split.scala",
    "content": "package hkmc2\npackage semantics\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.*, Elaborator.State, ucs.FlatPattern\n\nfinal case class Branch(scrutinee: Term.Ref, pattern: FlatPattern, continuation: Split) extends AutoLocated:\n  def mkClone(using State): Branch =\n    val scrutineeClone = new Term.Ref(scrutinee.sym)\n        (Tree.Ident(scrutinee.tree.name), scrutinee.refNum, scrutinee.typ)\n    Branch(scrutineeClone, pattern.mkClone, continuation.mkClone)\n  \n  override def children: Vector[Located] = Vector.triple(scrutinee, pattern, continuation)\n  \n  def showDbg(using DebugPrinter): String = s\"${scrutinee.sym.nme} is ${pattern.showDbg} -> { ${continuation.showDbg} }\"\n\nobject Branch:\n  def apply(scrutinee: Term.Ref, continuation: Split): Branch =\n    Branch(scrutinee, FlatPattern.Lit(Tree.BoolLit(true)), continuation)\n\nenum Split extends AutoLocated with ProductWithTail:\n  case Cons(head: Branch, tail: Split)\n  case Let(sym: BlockLocalSymbol, term: Term, tail: Split)\n  case Else(default: Term)\n  case End\n  \n  inline def ~:(head: Branch): Split = Split.Cons(head, this)\n  \n  def mkClone(using State): Split = this match\n    case Cons(head, tail) => Cons(head.mkClone, tail.mkClone)\n    case Let(sym, term, tail) => Let(sym, term.mkClone, tail.mkClone)\n    case Else(default) => Else(default.mkClone)\n    case End => End\n  \n  /** Used to indicate whether the `Split` was duplicated during desugaring or\n    * normalization. */\n  def duplicated: Bool = false\n  \n  private var _duplicated: Bool = false\n  \n  def setDuplicated: this.type =\n    if this != End then _duplicated = true\n    this\n  \n  def duplicate: Split =\n    (this match\n      case Cons(head, tail) => Cons(head, tail.duplicate)\n      case Let(name, term, tail) => Let(name, term, tail.duplicate)\n      case Else(default) => Else(default)\n      case End => End).setDuplicated\n  \n  lazy val isFull: Bool = this match\n    case Split.Cons(_, tail) => tail.isFull\n    case Split.Let(_, _, tail) => tail.isFull\n    case Split.Else(_) => true\n    case Split.End => false\n  \n  lazy val isEmpty: Bool = this match\n    case Split.Let(_, _, tail) => tail.isEmpty\n    case Split.Else(_) | Split.Cons(_, _) => false\n    case Split.End => true\n  \n  final override def children: Vector[Located] = this match\n    case Split.Cons(head, tail) => Vector.double(head, tail)\n    case Split.Let(name, term, tail) => Vector.triple(name, term, tail)\n    case Split.Else(default) => Vector.single(default)\n    case Split.End => Vector.empty\n  \n  def subTerms: Vector[Term] = this match\n    case Split.Cons(Branch(scrutinee, pattern, continuation), tail) => \n      scrutinee +: (pattern.subTerms ++ continuation.subTerms ++ tail.subTerms)\n    case Split.Let(_, term, tail) => term +: tail.subTerms\n    case Split.Else(term) => Vector.single(term)\n    case Split.End => Vector.empty\n  \n  /** Free variable names, accounting for let bindings. */\n  lazy val freeVars: Set[Str] = this match\n    case Split.Cons(Branch(scrutinee, pattern, continuation), tail) =>\n      scrutinee.freeVars ++ pattern.subTerms.iterator.flatMap(_.freeVars) ++\n        continuation.freeVars ++ tail.freeVars\n    case Split.Let(sym, term, tail) =>\n      term.freeVars ++ (tail.freeVars - sym.nme)\n    case Split.Else(term) => term.freeVars\n    case Split.End => Set.empty\n  \n  final def showDbg(using DebugPrinter): String = this match\n    case Split.Cons(head, tail) => s\"${head.showDbg}; ${tail.showDbg}\"\n    case Split.Let(name, term, tail) => s\"let ${name} = ${term.showDbg}; ${tail.showDbg}\"\n    case Split.Else(default) => s\"else ${default.showDbg}\"\n    case Split.End => \"\"\n  \n  final override def withLoc(loco: Option[Loc]): this.type =\n    super.withLoc:\n      this match\n        // `Split.Nil` must not have a location. This prevents sharing locations,\n        // which causes the assertion of distinctness of origins to fail.\n        case Split.End => N\n        case _: Split.Else => N // FIXME: @Luyu pls clean up this mess\n        case _ => loco\n  \n  var isFallback: Bool = false\n  \n  def prettyPrint(using DebugPrinter): Str = Split.prettyPrint(this)\nend Split\n\nextension (split: Split)\n  def ~~:(fallback: Split): Split =\n    if fallback == Split.End || split.isFull\n    then split\n    else split match\n      case Split.Cons(head, tail) => Split.Cons(head, tail ~~: fallback)\n      case Split.Let(name, term, tail) => Split.Let(name, term, tail ~~: fallback)\n      case Split.Else(_) => lastWords(\"impossible since split is not full\")\n      case Split.End => fallback\n\nobject Split:\n  def default(term: Term): Split = Split.Else(term)\n  \n  import SimpleSplit as SS\n  import Elaborator.{Ctx, State}\n  import utils.{tl, TL}\n  import collection.mutable.{Map as MutMap}\n  import ups.SplitCompiler, SplitCompiler.{MakeConsequent, Scrut, SymbolScrut}\n  import Term.Ref\n  \n  def from(rootSplit: SS)(using tl: TL)(using Ctx, Raise, State): Split =\n    val compiler = new SplitCompiler()\n    val scrutCache = MutMap.empty[Ref, Scrut]\n    def go(split: SS): Split = split match\n      case SS.Cons(branch, tail) => branch match\n        case SS.Head.Match(ref, pattern, consequent) =>\n          lazy val alternative = go(tail)\n          val makeConsequent: MakeConsequent = (output, bindings) =>\n            bindings.iterator.foldLeft(go(consequent)):\n              case (innerSplit, (symbol, mkTerm)) => Let(symbol, mkTerm(), innerSplit)\n          compiler.makeMatchSplit\n            (scrutCache.getOrElseUpdate(ref, Scrut.from(ref)), pattern, false)\n            (makeConsequent, alternative)\n        case SS.Head.Let(binding, term) => Let(binding, term, go(tail))\n      case SS.Else(default) => Else(default)\n      case SS.End => End\n    go(rootSplit)\n\n  private object prettyPrint:\n    /** Represents lines with indentations. */\n    type Lines = Ls[(Int, Str)]\n    \n    extension (lines: Lines)\n      /** Increase the indentation of all lines by one. */\n      def indent: Lines = lines.map:\n        case (n, line) => (n + 1, line)\n    \n      /** Make a multi-line string. */\n      def toIndentedString: Str = lines.iterator.map:\n        case (n, line) => \"  \" * n + line\n      .mkString(\"\\n\")\n    \n    extension (prefix: String)\n      /**\n        * If the first line does not have indentation and the remaining lines are\n        * indented, prepend the given string to the first line. Otherwise, prepend\n        * the given string to the first line and indent all remaining lines.\n        *\n        * When you want to amend the title of lines, you should use this function.\n        */\n      def #:(lines: Lines): Lines = lines match\n        case all @ ((0, line) :: lines) if lines.forall(_._1 > 0) =>\n          if prefix.isEmpty then all else (0, s\"$prefix $line\") :: lines\n        case lines => (0, prefix) :: lines.indent\n    \n    inline def apply(s: Split)(using DebugPrinter): Str = showSplit(\"‹if|while›\", s)\n    \n    private def showSplit(prefix: Str, s: Split)(using DebugPrinter): Str =\n      /** Show a split as a list of lines.\n       *  @param isFirst whether this is the first and frontmost branch\n       *  @param isTopLevel whether this is the top-level split\n       */\n      def split(s: Split, isFirst: Bool, isTopLevel: Bool): Lines =\n        val lines = s match\n          case Split.Cons(head, tail) => (branch(head, isTopLevel) match\n            case (n, line) :: tail => (n, line) :: tail\n            case Nil => Nil\n          ) ::: split(tail, false, isTopLevel)\n          case Split.Let(nme, rhs, tail) =>\n            (0, s\"let $nme = ${rhs.showDbg}\") :: split(tail, false, true)\n          case Split.Else(t) =>\n            (if isFirst && !isTopLevel then \"\" else \"else\") #: term(t)\n          case Split.End => Nil\n        if s.duplicated then lines.map:\n          case (n, line) if !line.endsWith(\"// duplicated\") => (n, s\"$line // duplicated\")\n          case other => other\n        else\n          lines\n      def term(t: Statement): Lines = t match\n        case Term.Blk(stmts, term) =>\n          stmts.iterator.concat(Iterator.single(term)).flatMap:\n            case DefineVar(sym, Term.IfLike(kw, IfLikeForm.ReturningIf, splt)) =>\n              s\"$sym = ${kw.name}\" #: SimpleSplit.prettyPrint.split(splt, true, true)\n            case DefineVar(sym, Term.SynthIf(splt)) =>\n              s\"$sym = if\" #: split(splt, true, true)\n            case stmt => (0, stmt.showDbg) :: Nil\n          .toList\n        case t: Statement => (0, t.showDbg) :: Nil\n      def branch(b: Branch, isTopLevel: Bool): Lines =\n        val Branch(scrutinee, pattern, consequent) = b\n        val lines = split(consequent, true, false)\n        val prefix = s\"${scrutinee.sym} is ${pattern.showDbg}\"\n        consequent match\n          case Split.Else(_) => (prefix + \" then\") #: lines\n          case _ => (prefix + \" and\") #: lines\n      val lines = split(s, true, true)\n      (if prefix.isEmpty then lines else prefix #: lines).toIndentedString\n  \n  end prettyPrint\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/Symbol.scala",
    "content": "package hkmc2\npackage semantics\n\nimport scala.collection.mutable\nimport scala.collection.mutable.{Set => MutSet}\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.*\nimport hkmc2.utils.*\n\nimport Elaborator.State\nimport Tree.Ident\nimport hkmc2.utils.SymbolSubst\n\n\nabstract class Symbol(using State) extends Located:\n  \n  def nme: Str\n  \n  def getState: State = summon\n  \n  val uid: Uid[Symbol] = State.suid.nextUid\n  \n  def showPlainName(using scp: Scope): hkmc2.document.Document =\n    import hkmc2.document.*\n    scp.allocateOrGetName(this)(using throw _)\n  \n  def showName(using scp: Scope, cfg: ShowCfg)(using Raise): Str =\n    cfg.shownSymbols += this\n    import hkmc2.document.*\n    val name = nme\n    if cfg.showFlowSymbols\n    then s\"$name${scp.allocateOrGetName(this).stripPrefix(name)}\"\n    else name\n  \n  def prefix: Str = \"\"\n  \n  def showPrefix(using Scope, ShowCfg, Raise): Str = prefix\n  \n  def showFullName(using Scope, ShowCfg, Raise): Str =\n    showPrefix + showName + State.dbgUid(uid)\n  \n  override def toString: Str =\n    prefix + nme + State.dbgUid(uid)\n  \n  val directRefs: mutable.Buffer[Term.Ref] = mutable.Buffer.empty\n  def ref(id: Tree.Ident =\n    Tree.Ident(\"\") // FIXME hack\n  ): Term.Ref =\n    val res = new Term.Ref(this)(id, directRefs.size, N)\n    directRefs += res\n    res\n  def refsNumber: Int = directRefs.size\n  \n  def existsNonModuleful: Bool = this match\n    case mod: ModuleOrObjectSymbol => !(mod.tree.k is Mod)\n    case mem: BlockMemberSymbol =>\n      // Some block member symbols do not correspond to a definition\n      // Tree, e.g., val definitions of a data class. So, it is supposed\n      // that if there is no tree, then it is not moduleful (because\n      // modules do have a tree).\n      mem.trees.isEmpty\n      || mem.trees.exists:\n        case t @ Tree.TypeDef(k = Mod) => false\n        case _ => true\n    case _ => true\n  \n  def existsModuleful: Bool = \n    this match\n    case mod: ModuleOrObjectSymbol => (mod.tree.k is Mod)\n    case mem: BlockMemberSymbol => \n      mem.trees.exists:\n        case t @ Tree.TypeDef(k = Mod) => true\n        case _ => false\n    case _ => false\n  \n  \n  def hasTrmDef: Bool = this match\n    case trm: TermSymbol => true\n    case mem: BlockMemberSymbol => mem.trmTree.nonEmpty\n    case _ => false\n  \n  def asCls: Opt[ClassSymbol] = this match\n    case cls: ClassSymbol => S(cls)\n    case mem: BlockMemberSymbol => mem.clsTree.flatMap(_.symbol.asCls)\n    case _ => N\n  def asModOrObj: Opt[ModuleOrObjectSymbol] = this match\n    case mod: ModuleOrObjectSymbol => S(mod)\n    case mem: BlockMemberSymbol => mem.modOrObjTree.flatMap(_.symbol.asModOrObj)\n    case _ => N\n  def asMod: Opt[ModuleOrObjectSymbol] = asModOrObj.filter(_.tree.k is Mod)\n  def asObj: Opt[ModuleOrObjectSymbol] = asModOrObj.filter(_.tree.k is Obj)\n  def asClsOrMod: Opt[ClassSymbol | ModuleOrObjectSymbol] = asCls orElse asModOrObj\n  \n  // * This is a hack for that `TermDef` currently doesn't have a symbol. \n  // * So, the symbol is from the `TermDefinition`. \n  def asTrm: Opt[TermSymbol] = this match\n    case trm: TermSymbol => S(trm)\n    case mem: BlockMemberSymbol => mem.tsym\n    case _ => N\n  def asPat: Opt[PatternSymbol] = this match\n    case pat: PatternSymbol => S(pat)\n    case mem: BlockMemberSymbol => mem.patTree.flatMap(_.symbol.asPat)\n    case _ => N\n  def asAls: Opt[TypeAliasSymbol] = this match\n    case cls: TypeAliasSymbol => S(cls)\n    case mem: BlockMemberSymbol => mem.alsTree.flatMap(_.symbol.asAls)\n    case _ => N\n  \n  def asClsLike: Opt[ClassSymbol | ModuleOrObjectSymbol | PatternSymbol] =\n    (asCls: Opt[ClassSymbol | ModuleOrObjectSymbol | PatternSymbol]) orElse asModOrObj orElse asPat\n  def asTpe: Opt[TypeSymbol] = asCls\n    .orElse[TypeSymbol](asObj)\n    .orElse[TypeSymbol](asAls)\n    .orElse[TypeSymbol](asMod)\n  def asNonModTpe: Opt[TypeSymbol] = asCls\n    .orElse[TypeSymbol](asObj)\n    .orElse[TypeSymbol](asAls)\n  \n  def asBlkMember: Opt[BlockMemberSymbol] = this match\n    case mem: BlockMemberSymbol => S(mem)\n    case mem: DefinitionSymbol[?] => mem.defn match\n      case S(defn: TypeLikeDef) => S(defn.bsym)\n      case S(defn: TermDefinition) => S(defn.bsym)\n      case N => N\n    case _ => N\n  \n  /** Get the symbol corresponding to the \"representative\" of a set of overloaded definitions,\n    * or the sole definition, if it is not overloaded.\n    * We should consider the ordering terms > classes/objects/types > modules, for this purpose. */\n  def asPrincipal: Opt[TermSymbol | ClassSymbol | ModuleOrObjectSymbol | TypeAliasSymbol | PatternSymbol] =\n    val asTrm: Opt[TermSymbol | ClassSymbol | ModuleOrObjectSymbol | TypeAliasSymbol | PatternSymbol] = this.asTrm\n    asTrm orElse\n    asCls orElse\n    asObj orElse\n    asAls orElse\n    asPat orElse\n    asMod\n  \n  def orElseDisamb(disamb: Opt[DefinitionSymbol[?]]): Symbol = (this, disamb) match\n    case (bms: BlockMemberSymbol, S(disamb)) =>\n      disamb\n    case (bms: BlockMemberSymbol, N) =>\n      lastWords(s\"Cannot disambiguate overloaded member symbol ${bms.nme}: no disambiguation provided\")\n    case (sym, N) =>\n      sym\n    case (sym, S(_)) =>\n      lastWords(s\"Cannot disambiguate non-BlockMember symbol ${sym.nme}: disambiguation provided\")\n  \n  override def equals(x: Any): Bool = this is x\n  override def hashCode: Int = uid.hashCode\n  \n  def subst(using SymbolSubst): Symbol\n  \nend Symbol\n\n\n// * Used, eg, as the Assign receiver of intermediate computations whose result is not used\nfinal class NoSymbol(using State) extends Symbol:\n  def nme: Str = \"‹no symbol›\"\n  def toLoc: Option[Loc] = N\n  def subst(using s: SymbolSubst): NoSymbol = this\n\n\nclass FlowSymbol(label: Str)(using State) extends Symbol:\n  def nme: Str = label\n  def toLoc: Option[Loc] = N // TODO track source trees of flows\n  import flow.*\n  val outFlows: mutable.Buffer[FlowSymbol] = mutable.Buffer.empty\n  val consumers: mutable.Buffer[Consumer] = mutable.Buffer.empty\n  val producers: mutable.Buffer[ConcreteProd] = mutable.Buffer.empty\n  def showDbg: Str =\n    label + s\"‹$uid›\"\n  def subst(using s: SymbolSubst): FlowSymbol = s.mapFlowSym(this)\n\nobject FlowSymbol:\n  \n  def app()(using State) =\n    // FlowSymbol(\"‹app-res›\")\n    // FlowSymbol(\"@\")\n    FlowSymbol(\"app\")\n\n  def sel(nme: Str)(using State) =\n    FlowSymbol(s\"⋅$nme\")\n  def synthSel(nme: Str)(using State) =\n    FlowSymbol(s\"(⋅)$nme\")\n  def selProj(nme: Str)(using State) =\n    FlowSymbol(s\"#⋅$nme\")\n\n  def lds(nme: Str)(using State) =\n    FlowSymbol(s\"Ɛ⋅$nme\")\n  \nend FlowSymbol\n\nsealed trait LocalSymbol extends Symbol:\n  def subst(using s: SymbolSubst): LocalSymbol\nsealed trait NamedSymbol extends Symbol:\n  def name: Str\n  def id: Ident\n  def subst(using s: SymbolSubst): NamedSymbol\n\nclass LabelSymbol(val trm: Opt[Term], name: Str = \"lbl\")(using State) extends LocalSymbol:\n  def nme = name\n  def subst(using s: SymbolSubst): LabelSymbol = s.mapLabelSym(this)\n  def toLoc = trm.flatMap(_.toLoc)\n  override def prefix: Str = \"label:\"\n\nabstract class BlockLocalSymbol(name: Str)(using State) extends FlowSymbol(name):\n  self: LocalSymbol => // * using `with LocalSymbol` in the `extends` clause makes Scala think there's a bad override\n  var decl: Opt[Declaration] = N\n\nclass TempSymbol(val trm: Opt[Term], dbgNme: Str = \"tmp\")(using State) extends BlockLocalSymbol(dbgNme) with LocalSymbol:\n  // val nameHints: MutSet[Str] = MutSet.empty // * May be useful later?\n  override def toLoc: Option[Loc] = trm.flatMap(_.toLoc)\n  override def prefix: Str = \"tmp:\"\n  override def subst(using s: SymbolSubst): TempSymbol = s.mapTempSym(this)\n\n\n// * When instantiating forall-qualified TVs, we need to duplicate the information\n// * for pretty-printing, but each instantiation should be different from each other\n// * i.e., UID should be different\nclass InstSymbol(val origin: Symbol)(using State) extends LocalSymbol:\n  override def nme: Str = origin.nme\n  override def toLoc: Option[Loc] = origin.toLoc\n  def subst(using sub: SymbolSubst): InstSymbol = sub.mapInstSym(this)\n\n\nclass VarSymbol(val id: Ident)(using State) extends BlockLocalSymbol(id.name) with NamedSymbol with LocalSymbol:\n  val name: Str = id.name\n  override def toLoc: Opt[Loc] = id.toLoc\n  // override def toString: Str = s\"$name@$uid\"\n  override def subst(using s: SymbolSubst): VarSymbol = s.mapVarSym(this)\n\nclass BuiltinSymbol\n    (val nme: Str, val binary: Bool, val unary: Bool, val nullary: Bool, val functionLike: Bool)(using State)\n    extends Symbol:\n  def toLoc: Option[Loc] = N\n  override def prefix: Str = \"builtin:\"\n  \n  def subst(using sub: SymbolSubst): BuiltinSymbol = sub.mapBuiltInSym(this)\n  \n  def isPure: Bool = true // * For now, all builtins are pure\n  \n  // * A basic approximation of builtin operator types\n  lazy val signature : semantics.flow.Producer =\n    import typing.Type\n    import typing.Type.*\n    val binaryType : Type = Fun(args = Tup.mk(Top, Top), ret = Top, eff = N)\n    val unaryType : Type = Fun(args = Tup.mk(Top), ret = Top, eff = N)\n    val nullaryType : Type = Top\n    val typ = (binary, unary, nullary) match\n      case (true, true, true) => Union(binaryType, Union(unaryType, nullaryType))\n      case (true, true, _) => Union(binaryType, unaryType)\n      case (true, _, true) => Union(binaryType, nullaryType)\n      case (_, true, true) => Union(unaryType, nullaryType)\n      case (true, _, _) => binaryType\n      case (_, true, _) => unaryType\n      case (_, _, true) => nullaryType\n      case _ => Bot\n    semantics.flow.Producer.Typ(typ)\n\n\n/** This is the outside-facing symbol associated to a possibly-overloaded\n  * definition living in a block – e.g., a module or class.\n  * `nameIsMeaningful` is `true` when the name comes from the user's source code;\n  *   it is false when the name is a default given by the compiler, such as \"lambda\" when lifting lambdas. */\nclass BlockMemberSymbol(val nme: Str, val trees: Ls[TypeOrTermDef], val nameIsMeaningful: Bool = true)(using State)\n    extends MemberSymbol:\n  \n  // * This is a hack for that `TermDef` currently doesn't have a symbol. \n  var tsym: Opt[TermSymbol] = N\n  \n  def toLoc: Option[Loc] = Loc(trees)\n  \n  def describe: Str =\n    trees match\n    case td :: Nil => td.describe\n    case _ => trees.iterator.map(_.describe).mkString(\"overloaded \", \", \", \"symbol\")\n  \n  def clsTree: Opt[Tree.TypeDef] = trees.collectFirst:\n    case t: Tree.TypeDef if t.k is Cls => t\n  def modOrObjTree: Opt[Tree.TypeDef] = modTree orElse objTree\n  def objTree: Opt[Tree.TypeDef] = trees.collectFirst:\n    case t: Tree.TypeDef if (t.k is Obj) => t\n  def modTree: Opt[Tree.TypeDef] = trees.collectFirst:\n    case t: Tree.TypeDef if (t.k is Mod) => t\n  def alsTree: Opt[Tree.TypeDef] = trees.collectFirst:\n    case t: Tree.TypeDef if t.k is Als => t\n  def patTree: Opt[Tree.TypeDef] = trees.collectFirst:\n    case t: Tree.TypeDef if t.k is Pat => t\n  def trmTree: Opt[Tree.TermDef] = trees.collectFirst:\n    case t: Tree.TermDef /* if t.k is  */ => t\n  def trmImplTree: Opt[Tree.TermDef] = trees.collectFirst:\n    case t: Tree.TermDef if t.rhs.isDefined => t\n  \n  def isParameterizedMethod: Bool = trmTree.exists(_.isParameterizedMethod)\n  \n  override def prefix: Str = \"member:\"\n  \n  def subst(using sub: SymbolSubst): BlockMemberSymbol = sub.mapBlockMemberSym(this)\n  \n  // * The flow of this symbol, when interpreted as a term (assuming no disambiguation)\n  lazy val flow: FlowSymbol = FlowSymbol(s\"flow:$nme\")(using getState)\n  \nend BlockMemberSymbol\n\n\nsealed abstract class MemberSymbol(using State) extends Symbol:\n  def nme: Str\n  def subst(using SymbolSubst): MemberSymbol\n\n\nclass TermSymbol(val k: TermDefKind, val owner: Opt[InnerSymbol], val id: Tree.Ident)(using State)\n    extends MemberSymbol\n    with DefinitionSymbol[TermDefinition]\n    with LocalSymbol\n    with NamedSymbol:\n  def nme: Str = id.name\n  def name: Str = nme\n  \n  def toLoc: Option[Loc] = id.toLoc\n  override def prefix: Str = s\"term:${owner.map(o => s\"${o.nme}/\").getOrElse(\"\")}\"\n  override def showPrefix(using Scope, ShowCfg, Raise): Str =\n    \"term:\" + owner.map(_.showName + \"/\").getOrElse(\"\")\n  \n  def subst(using sub: SymbolSubst): TermSymbol = sub.mapTermSym(this)\n\nobject TermSymbol:\n  def fromFunBms(b: BlockMemberSymbol, owner: Opt[InnerSymbol])(using State) =\n    TermSymbol(syntax.Fun, owner, Tree.Ident(b.nme))\n\n\nsealed trait CtorSymbol extends Symbol:\n  def nme: Str\n  def subst(using sub: SymbolSubst): CtorSymbol = sub.mapCtorSym(this)\n\ncase class Extr(isTop: Bool)(using State) extends CtorSymbol:\n  def nme: Str = if isTop then \"Top\" else \"Bot\"\n  def toLoc: Option[Loc] = N\n  override def toString: Str = nme\n\nsealed abstract case class LitSymbol(lit: Literal)(using State) extends CtorSymbol:\n  def nme: Str = lit.idStr\n  def toLoc: Option[Loc] = lit.toLoc\n  override def prefix: Str = \"lit:\"\nobject LitSymbol:\n  val cache: mutable.Map[Literal, LitSymbol] = mutable.Map.empty\n  def apply(lit: Literal)(using State): LitSymbol =\n    cache.getOrElseUpdate(lit, new LitSymbol(lit){})\n\n\n/** A TypeSymbol that is not an alias. */\ntype BaseTypeSymbol = ClassSymbol | ModuleOrObjectSymbol\n\ntype TypeSymbol = BaseTypeSymbol | TypeAliasSymbol\n\n/**\n  * ErrorSymbol is a placeholder symbol denoting error (during symbol\n  * resolution in the elaborator / resolver). This helps prevent the\n  * same error from throwing multiple times.\n  */\ncase class ErrorSymbol(val nme: Str, tree: Tree)(using State) extends MemberSymbol:\n  override def toLoc: Option[Loc] = tree.toLoc\n  override def subst(using sub: SymbolSubst): ErrorSymbol = sub.mapErrorSym(this)\n  override def prefix: Str = \"error:\"\n\nsealed trait ClassLikeSymbol extends IdentifiedSymbol:\n  self: MemberSymbol & DefinitionSymbol[? <: ClassDef | ModuleOrObjectDef] =>\n  val tree: Tree.TypeDef\n  def subst(using sub: SymbolSubst): ClassLikeSymbol\n\n\n/**\n * A symbol for entities with a definition.\n *\n * This is different from `MemberSymbol` because `BlockMemberSymbol` extends `MemberSymbol`, and its\n * definition is ambiguous in the sense that a `BlockMemberSymbol` corresponds to multiple\n * overloaded definitions. In contrast, a `DefinitionSymbol` corresponds to only one specific\n * definition.\n */\nsealed trait DefinitionSymbol[Defn <: Definition] extends Symbol:\n  this: MemberSymbol =>\n  \n  var defn: Opt[Defn] = N\n  var decl: Opt[Declaration] = N // NOTE: currently only assigned for class params and only used by deforestation; may want to just remove it once deforestation is improved\n  def bms: Opt[BlockMemberSymbol] = defn.map(_.bsym) \n  \n  /** Whether we know it's pure when selected (eg getters are not always pure). */\n  def isPure: Bool =\n    this match\n    case _: ModuleOrObjectSymbol => true\n    case _ =>\n      defn.exists:\n        case d: ClassDef => true\n        case TermDefinition(k = _: syntax.ValLike) => true\n        case TermDefinition(k = syntax.Fun, params = _ :: _) =>\n          true // References to functions are only guaranteed to be pure when the functions have parameter lists\n        case _ => false\n  \n  def subst(using sub: SymbolSubst): DefinitionSymbol[Defn]\n  \n  def asMemSym: MemberSymbol = this\n  \nend DefinitionSymbol\n\n/** This is the symbol associated to specific definitions.\n  * One overloaded `BlockMemberSymbol` may correspond to multiple `InnerSymbol`s\n  * A `Ref(_: InnerSymbol)` represents a `this`-like reference to the current object. */\n  // TODO prevent from appearing in Ref\nsealed trait InnerSymbol(using State) extends Symbol:\n  // Ideally, InnerSymbol should extend DefinitionSymbol, but that requires us to specify the type\n  // parameter to all occurrences of InnerSymbol. So, we use a self-type annotation instead to\n  // ensure that any implementation of InnerSymbol is also a DefinitionSymbol.\n  self: DefinitionSymbol[? <: ClassLikeDef] =>\n  val privatesScope: Scope = Scope.empty(Scope.Cfg.default) // * Scope for private members of this symbol\n  val thisProxy: TempSymbol = TempSymbol(N, s\"this$$$nme\")\n  def subst(using SymbolSubst): InnerSymbol\n  def asDefnSym: DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol = this match\n    case d: DefinitionSymbol[? <: ClassLikeDef] => d\n\ntrait IdentifiedSymbol extends Symbol:\n  val id: Tree.Ident\n\nclass ClassSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State)\n    extends MemberSymbol\n    with ClassLikeSymbol\n    with CtorSymbol\n    with DefinitionSymbol[ClassDef]\n    with InnerSymbol\n    with NamedSymbol:\n\n  def name: Str = nme\n  def nme = id.name\n  def toLoc: Option[Loc] = id.toLoc // TODO track source tree of classe here\n  override def prefix: Str = \"class:\"\n  /** Compute the arity. */\n  def arity: Int = tree.paramLists.headOption.fold(0)(_.fields.length)\n  \n  override def subst(using sub: SymbolSubst): ClassSymbol = sub.mapClsSym(this)\n\nclass ModuleOrObjectSymbol(val tree: Tree.TypeDef, val id: Tree.Ident)(using State)\n    extends MemberSymbol\n    with ClassLikeSymbol\n    with CtorSymbol\n    with DefinitionSymbol[ModuleOrObjectDef]\n    with InnerSymbol\n    with NamedSymbol:\n  def name: Str = nme\n  def nme = id.name\n  def toLoc: Option[Loc] = id.toLoc // TODO track source tree of module here\n  override def prefix: Str =\n    if tree.k is Obj then \"object:\"\n    else \"module:\"\n\n  override def subst(using sub: SymbolSubst): ModuleOrObjectSymbol = sub.mapModuleSym(this)\n\nclass TypeAliasSymbol(val id: Tree.Ident)(using State)\n    extends MemberSymbol\n    with DefinitionSymbol[TypeDef]:\n  def nme = id.name\n  def toLoc: Option[Loc] = id.toLoc // TODO track source tree of type alias here\n  override def prefix: Str = \"type:\"\n\n  def subst(using sub: SymbolSubst): TypeAliasSymbol = sub.mapTypeAliasSym(this)\n\nclass PatternSymbol(val id: Tree.Ident, val params: Opt[Tree.Tup], val body: Tree)(using State)\n    extends MemberSymbol\n    with CtorSymbol\n    with DefinitionSymbol[PatternDef]\n    with InnerSymbol:\n  def nme = id.name\n  def toLoc: Option[Loc] = id.toLoc // TODO track source tree of pattern here\n  override def prefix: Str = \"pattern:\"\n  \n  override def subst(using sub: SymbolSubst): PatternSymbol = sub.mapPatSym(this)\n\nclass TopLevelSymbol(blockNme: Str)(using State)\n    extends MemberSymbol\n    with DefinitionSymbol[ModuleOrObjectDef]\n    with InnerSymbol:\n  def nme = blockNme\n  def toLoc: Option[Loc] = N\n  override def prefix: Str = \"globalThis:\"\n  \n  def subst(using sub: SymbolSubst): TopLevelSymbol = sub.mapTopLevelSym(this)\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/SymbolPrinter.scala",
    "content": "package hkmc2\npackage semantics\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.*\nimport hkmc2.utils.*\n\n\nclass SymbolPrinter(dbgScp: Scope) extends DebugPrinter:\n  \n  override def printPlain(v: Any): Str = v match\n    case sym: Symbol =>\n      sym.showFullName(using dbgScp, semantics.ShowCfg.internal, throw _)\n    case _ => super.printPlain(v)\n    \n  def printSymbol(sym: Symbol)(using Raise, ShowCfg): Str =\n    sym.showName(using dbgScp, summon)\n  \nend SymbolPrinter\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala",
    "content": "package hkmc2\npackage semantics\n\nimport scala.collection.mutable.{Buffer, Set as MutSet}\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.*\nimport hkmc2.utils.Scope\nimport hkmc2.utils.Scope.scope\nimport hkmc2.document.*\nimport hkmc2.document.Document.*\n\nimport Elaborator.State\nimport hkmc2.typing.Type\nimport hkmc2.semantics.Elaborator.{Ctx, ctx}\nimport hkmc2.Message.MessageContext\n\n\nfinal case class QuantVar(sym: VarSymbol, ub: Opt[Term], lb: Opt[Term])\n\nenum Annot extends AutoLocated:\n  case Untyped\n  case Modifier(mod: Keyword)\n  case Trm(trm: Term)\n  case TailRec\n  case TailCall\n  case Config(modify: hkmc2.Config => hkmc2.Config)\n  \n  def symbol: Opt[Symbol] = this match\n    case Trm(trm) => trm.symbol\n    case _ => N\n  \n  def subTerms: Vector[Term] = this match\n    case Trm(trm) => Vector.single(trm)\n    case _: Modifier | Untyped | TailRec | TailCall | _: Config => Vector.empty\n  \n  def children: Vector[Located] = this match\n    case Trm(trm) => Vector.single(trm)\n    case _: Modifier | Untyped | TailRec | TailCall | _: Config => Vector.empty\n  \n  def show(using Scope, ShowCfg, Raise): Document = this match\n    case Untyped => doc\"‹untyped›\"\n    case Modifier(mod) => doc\"@${mod.name}\"\n    case Trm(trm) => doc\"@${trm.show}\"\n    case Config(_) => doc\"@config(...)\"\n  \n  def mkClone(using State): Annot = this match\n    case Untyped => Untyped\n    case Modifier(mod) => Modifier(mod)\n    case Trm(trm) => Trm(trm.mkClone)\n    case TailRec => TailRec\n    case TailCall => TailCall\n    case c: Config => c\n\nobject Annot:\n  \n  val Private = Modifier(Keyword.`private`)\n  \nend Annot\n\ntype AnySelTerm = AnySel & Resolvable\n\nsealed trait AnySel extends ResolvableImpl:\n  self: Term.Sel | Term.SynthSel | Term.SelProj =>\n  \n  val sym: Opt[MemberSymbol]\n  val typ: Opt[Type]\n  val nme: Tree.Ident\n  val resSym: FlowSymbol\n  val prefix: Term\n  val originalCtx: Opt[SrcScope]\n  \n  var resolvedTargets: Ls[flow.SelectionTarget] = Nil // * filled during flow analysis\n  var isErroneous: Bool = false // * to avoid reporting follow-on errors after a flow/resolution error\nend AnySel\n\nobject AnySel:\n  def unapply(t: AnySelTerm): S[(Term, Tree.Ident, Opt[Term])] = t match\n    case Term.Sel(lhs, id) => S((lhs, id, N))\n    case Term.SynthSel(lhs, id) => S((lhs, id, N))\n    case Term.SelProj(lhs, cls, proj) => S((lhs, proj, S(cls)))\nend AnySel\n\ntype Resolvable = Term & ResolvableImpl\n\nsealed trait ResolvableImpl:\n  this: Term =>\n  \n  import Resolvable.CallableDefinition\n  \n  /**\n   * The expanded form of the term, if it exists. \n   * \n   * - If it is None, the term hasn't yet expanded.\n   * - If it is Some of None, the term has expanded to itself.\n   * - If it is Some of Some, the term has expanded to something else.\n   */\n  private[semantics]\n  var expansion: Opt[Opt[Term]] = N\n\n  def duplicate(using State): this.type =\n    this.match\n      case t: Term.Resolved => t.copy()(t.typ)\n      case t: Term.Ref => t.copy()(t.tree, t.refNum, t.typ)\n      case t: Term.App => t.copy()(t.tree, t.typ, t.resSym)\n      case t: Term.TyApp => t.copy()(t.typ)\n      case t: Term.Sel => t.copy()(t.sym, t.resSym, t.typ, t.originalCtx)\n      case t: Term.SynthSel => t.copy()(t.sym, t.resSym, t.typ, t.originalCtx)\n      case t: Term.LeadingDotSel => t.copy()(t.originalCtx)\n      case t: Term.SelProj => t.copy()(t.sym, t.resSym, t.typ, t.originalCtx)\n      case t: Term.New => t.copy()(t.typ)\n    .withLocOf(this)\n    .asInstanceOf\n  \n  def withSym(sym: MemberSymbol): this.type = \n    this.match\n      case t: Term.Sel => t.copy()(S(sym), t.resSym, t.typ, t.originalCtx)\n      case t: Term.SynthSel => t.copy()(S(sym), t.resSym, t.typ, t.originalCtx)\n      case t: Term.SelProj => t.copy()(S(sym), t.resSym, t.typ, t.originalCtx)\n    .withLocOf(this)\n    .asInstanceOf\n  \n  def withTyp(typ: Type)(using DebugPrinter): this.type = \n    this.match\n      case t: Term.Resolved => t.copy()(S(typ))\n      case t: Term.Ref => t.copy()(t.tree, t.refNum, S(typ))\n      case t: Term.App => t.copy()(t.tree, S(typ), t.resSym)\n      case t: Term.TyApp => t.copy()(S(typ))\n      case t: Term.Sel => t.copy()(t.sym, t.resSym, S(typ), t.originalCtx)\n      case t: Term.SynthSel => t.copy()(t.sym, t.resSym, S(typ), t.originalCtx)\n      case _: Term.LeadingDotSel => lastWords(s\"Cannot attach a type to leading dot selection: ${this.showDbg}\")\n      case t: Term.SelProj => t.copy()(t.sym, t.resSym, S(typ), t.originalCtx)\n      case t: Term.New => t.copy()(S(typ))\n    .withLocOf(this)\n    .asInstanceOf\n  \n  def expandedIn[T](in: Term => T): T =\n    in(expanded)\n  \n  def expandedResolvableIn[T](in: Resolvable => T)(using DebugPrinter): T =\n    expanded match\n      case r: Resolvable => in(r)\n      case t => lastWords(s\"Expected a resolvable term, but got ${t.showDbg}.\")\n\n  /** \n   * Expanding a term to another, which can be later retrieved by the\n   * `instantiate` method. \n   *\n   * If a term is expanding to a term that contains itself, the\n   * `instantiate` method goes into an infinite loop and the expansion\n   * never ends. Thus, the term itself should be duplicated by the\n   * `duplicate` method if it appears in its own expansion.\n   *\n   * This method is only supposed to be called by Resolver. \n   */\n  private[semantics] def expand(expansion: Opt[Term]): this.type =\n    // `expansion.isDefined`: Ideally, if a term is already expanded,\n    // one should look at the term's expansion and expand it again. This\n    // check is to prevent one from mistakenly overriding an expansion\n    // without looking at the instantiation.\n    //\n    // `expansion.get =/= newExpansion`: Waiting for @Luyu to revamp the\n    // desugaring stage so that no same term occurs in different places.\n    if this.expansion.isDefined && this.expansion.get =/= expansion then\n      lastWords(s\"Cannot expand the term ${this} multiple times (to different expansions ${expansion.get}).\")\n    \n    this.expansion = S(expansion)\n    this\n    \n  def resolve: this.type = expand(N)\n  def dontResolve: this.type = this // TODO rm\n  \n  /**\n   * A helper function to create a resolved term for this term.\n   */\n  def resolved(sym: DefinitionSymbol[?]): Term.Resolved =\n    Term.Resolved(this, sym)(typ = resolvedTyp)\n  \n  def hasExpansion = expansion.isDefined\n  \n  def defn: Opt[Definition] = resolvedSym match\n    case S(sym: BlockMemberSymbol) => N\n    case S(sym: DefinitionSymbol[?]) => sym.defn\n    case _ => N\n  \n  def typDefn = resolvedTyp match\n    case S(typ) => typ.symbol match\n      case S(sym: TypeSymbol) => sym.defn\n      case _ => N\n    case N => N\n  \n  def callableDefn: Opt[CallableDefinition] = defn.flatMap:\n    CallableDefinition.fromDefn(_)\n  \n  def singletonDefn: Opt[ModuleOrObjectDef] = typDefn match\n    case S(td: ModuleOrObjectDef) => S(td)\n    case _ => N\n\nobject Resolvable:\n  case class CallableDefinition(\n    sym: BlockMemberSymbol,\n    params: Ls[ParamList],\n    tparams: Opt[Ls[Param]],\n    sign: Opt[Term],\n    flags: TermDefFlags,\n    modulefulness: Modulefulness,\n    defn: Definition\n  )\n  \n  object CallableDefinition:\n    def fromDefn(defn: Definition): Opt[CallableDefinition] = defn match\n      case defn: TermDefinition => S(CallableDefinition(\n        defn.sym,\n        defn.params,\n        defn.tparams,\n        defn.sign,\n        defn.flags,\n        defn.modulefulness,\n        defn,\n      ))\n      case defn: TypeDef => S(CallableDefinition(\n        defn.bsym,\n        Nil,\n        if defn.tparams.isEmpty\n        then N\n        else S(defn.tparams.map(tp => Param(FldFlags.empty, tp.sym, N, Modulefulness.none))), \n        defn.rhs,\n        TermDefFlags.empty, // TODO: handle class-like definitions with flags\n        Modulefulness.none, // TODO: handle modulefulness for class-like definitions\n        defn,\n      ))\n      case defn: ClassLikeDef => S(CallableDefinition(\n        defn.bsym, \n        defn.paramsOpt.toList ::: defn.auxParams, \n        if defn.tparams.isEmpty\n        then N\n        else S(defn.tparams.map(tp => Param(FldFlags.empty, tp.sym, N, Modulefulness.none))), \n        N, // TODO: handle class-like definitions with signatures\n        TermDefFlags.empty, // TODO: handle class-like definitions with flags\n        Modulefulness.none, // TODO: handle modulefulness for class-like definitions\n        defn,\n      ))\n\ntrait LeadingDotSelImpl(using State):\n  self: Term.LeadingDotSel =>\n  val resSym: FlowSymbol = FlowSymbol.lds(self.nme.name)\n  var resolvedTargets: Ls[flow.SelectionTarget.CompanionMember] = Nil // * filled during flow analysis\n\ncase class SrcScope(outer: Elaborator.OuterCtx, parent: Opt[SrcScope]):\n  \n  /** Computes the outermost scope from which the current scope can still be accessed.\n    * For instance, from [scp2] here, [scp1] is the outermost accessible base:\n    *     [scp0]\n    *     fun foo =\n    *       [scp1]\n    *       module Foo with\n    *         module Bar with\n    *           [scp2]\n    * and the path is Foo :: Bar :: Nil.\n    * [scp0] cannot access [scp2] because there is a function (Function outer) on the way.\n    * The same would happen for:\n    *     [scp0]\n    *     if ... then // LocalScope also blocks access to [scp1] and [scp2]\n    *       [scp1]\n    *       module Foo with\n    *         module Bar with\n    *           [scp2]\n    */\n  lazy val outermostAcessibleBase: (SrcScope, Ls[InnerSymbol]) =\n      import Elaborator.OuterCtx.*\n      outer match\n      case InnerScope(inner) =>\n        parent match\n        case N => (this, inner :: Nil)\n        case S(par) =>\n          val (base, path) = par.outermostAcessibleBase\n          (base, inner :: path)\n      case _: (Function | LocalScope) | LambdaOrHandlerBlock | NonReturnContext =>\n        (this, Nil)\n\nobject SrcScope:\n  given s: Ctx => SrcScope = summon[Ctx].scope\n\nenum Term extends Statement:\n  case Error\n  case UnitVal()\n  case Missing // Placeholder terms that were not elaborated due to the \"lightweight\" elaboration mode `Mode.Light`\n  case Lit(lit: Literal)\n  /** A term that wraps another term, indicating that the symbol of the inner term is resolved.\n    * This is mainly used to disambiguate overloaded definitions. */\n  case Resolved(t: Term, sym: DefinitionSymbol[?])\n    (val typ: Opt[Type]) extends Term, ResolvableImpl\n  case Ref(sym: Symbol)\n    (val tree: Tree.Ident, val refNum: Int, val typ: Opt[Type]) extends Term, ResolvableImpl\n  case App(lhs: Term, rhs: Term)\n    (val tree: Tree.App, val typ: Opt[Type], val resSym: FlowSymbol) extends Term, ResolvableImpl\n  case TyApp(lhs: Term, targs: Ls[Term])\n    (val typ: Opt[Type]) extends Term, ResolvableImpl\n  case Sel(prefix: Term, nme: Tree.Ident)\n    (val sym: Opt[MemberSymbol], val resSym: FlowSymbol, val typ: Opt[Type], val originalCtx: Opt[SrcScope])\n    extends Term, AnySel\n  case SynthSel(prefix: Term, nme: Tree.Ident)\n    (val sym: Opt[MemberSymbol], val resSym: FlowSymbol, val typ: Opt[Type], val originalCtx: Opt[SrcScope])\n    extends Term, AnySel\n  case SelProj(prefix: Term, cls: Term, nme: Tree.Ident)\n    (val sym: Opt[MemberSymbol], val resSym: FlowSymbol, val typ: Opt[Type], val originalCtx: Opt[SrcScope])\n    extends Term, AnySel\n  case DynSel(prefix: Term, fld: Term, arrayIdx: Bool)\n  case Tup(fields: Ls[Elem])(val tree: Tree.Tup)\n  case Mut(underlying: Tup | Rcd | New | DynNew)\n  case CtxTup(fields: Ls[Elem])(val tree: Tree.Tup)\n  case IfLike(kw: Keyword.SplitLike, form: IfLikeForm, split: SimpleSplit)\n  /** `If` expressions synthesized by the pattern compiler. It should only be\n   *  created and used in `Lowering`. One must make sure that all terms in the\n   *  split are correctly resolved. In the future, we might look for a way to\n   *  remove `SynthIf` by generating IR `Match` blocks directly. */\n  case SynthIf(split: Split)\n  case Lam(params: ParamList, body: Term)\n  case FunTy(lhs: Term, rhs: Term, eff: Opt[Term])\n  case Forall(tvs: Ls[QuantVar], outer: Opt[VarSymbol], body: Term)\n  case Constrained(constraints: Ls[SubConstraint], body: Term)\n  case WildcardTy(in: Opt[Term], out: Opt[Term])\n  case Blk(stats: Ls[Statement], res: Term) extends Term, BlkImpl\n  case Rcd(mut: Bool, stats: Ls[Statement])\n  case Quoted(body: Term)\n  case Unquoted(body: Term)\n  case New(cls: Term, args: Ls[Term], rft: Opt[ClassSymbol -> ObjBody])\n    (val typ: Opt[Type]) extends Term, ResolvableImpl\n  case DynNew(cls: Term, args: Ls[Term])\n  case Asc(term: Term, ty: Term)\n  case CompType(lhs: Term, rhs: Term, pol: Bool)\n  case Neg(rhs: Term)\n  case Region(name: VarSymbol, body: Term)\n  case RegRef(reg: Term, value: Term)\n  case Assgn(lhs: Term, rhs: Term)\n  case Drop(trm: Term)\n  case Deref(ref: Term)\n  case SetRef(ref: Term, value: Term)\n  case Ret(result: Term)\n  case Throw(result: Term)\n  case Try(body: Term, finallyDo: Term)\n  case Annotated(annot: Annot, target: Term)\n  case Handle(lhs: LocalSymbol, rhs: Term, args: List[Term],\n    derivedClsSym: ClassSymbol, defs: Ls[HandlerTermDefinition], body: Term)\n  case LeadingDotSel(nme: Tree.Ident)(\n      val originalCtx: Opt[SrcScope]\n    ) (using State) extends Term, ResolvableImpl, LeadingDotSelImpl\n  \n  def expanded: Term = this match\n    case t: Resolvable => t.expansion match\n      case S(S(t)) => t.expanded\n      case S(N) => this\n      case N => this\n    case _ => this\n  \n  /**\n   * This field equals `S(lds)` if the term is a chain of selections\n   * and applications that originates with a leading-dot selection,\n   * namely `lds`. Otherwise this field equals `N`.\n   * It is evaluated during flow analysis to constrain the LDS with\n   * the type of the whole term.\n   */\n  lazy val ldsRoot: Opt[LeadingDotSel] = this match\n    case Sel(prefix, nme) => prefix.ldsRoot\n    case App(lhs, rhs) => lhs.ldsRoot\n    case sel: LeadingDotSel => S(sel)\n    case _ => N\n\n  /**\n   * The prelinminary symbol for the term that is resolved during\n   * elaboration. \n   */\n  lazy val symbol: Opt[Symbol] = this match\n    case res: Resolved => S(res.sym)\n    case Ref(sym) => S(sym)\n    case sel: Sel => sel.sym\n    case sel: SynthSel => sel.sym\n    case sel: SelProj => sel.sym\n    case TyApp(lhs = lhs) => lhs.symbol\n    case _ => N\n  \n  /**\n   * The symbol representing the evaluation result of the term. This\n   * symbol is resolved during the resolution stage.\n   */\n  def resolvedSym: Opt[Symbol] = expanded match\n    case res: Resolved => S(res.sym)\n    case ref: Ref => ref.symbol\n    case sel: Sel => sel.sym\n    case sel: SynthSel => sel.sym\n    case sel: SelProj => sel.sym\n    case app: TyApp => app.lhs.resolvedSym\n    case _ => N\n  \n  def resolvedTyp: Opt[Type] = expanded match\n    case res: Resolved => res.typ\n    case ref: Ref => ref.typ\n    case app: App => app.typ\n    case app: TyApp => app.typ\n    case sel: Sel => sel.typ\n    case sel: SynthSel => sel.typ\n    case nu: New => nu.typ\n    case _ => N\n  \n  /** The set of free variable names in this term.\n    * Note: it is wrong to compute this based on strings, rather than symbols,\n    * but strings are good enough for now. This is currently only used to detect useless pattern variables.\n    * (These definitions were generated as part of a slop PR.) */\n  lazy val freeVars: Set[Str] = this match\n    case Ref(sym) => Set.single(sym.nme)\n    case Lam(params, body) =>\n      val paramNames = params.allParams.iterator.map(_.sym.nme).toSet\n      body.freeVars -- paramNames\n    case Blk(stats, res) =>\n      Term.blkFreeVars(stats, res.freeVars)\n    case IfLike(_, _, split) => split.freeVars\n    case SynthIf(split) => split.freeVars\n    case Region(name, body) =>\n      body.freeVars - name.nme\n    case Handle(lhs, rhs, args, _, defs, body) =>\n      val rhsFree = rhs.freeVars\n      val argsFree = args.iterator.flatMap(_.freeVars).toSet\n      val defsFree = defs.iterator.flatMap(d => Term.termDefFreeVars(d.td)).toSet\n      val bodyFree = body.freeVars - lhs.nme\n      rhsFree ++ argsFree ++ defsFree ++ bodyFree\n    case Forall(_, _, body) => body.freeVars\n    case Error | Missing | _: Lit | _: UnitVal | _: LeadingDotSel => Set.empty\n    case _ => subTerms.iterator.flatMap(_.freeVars).toSet\n\n  def sel(id: Tree.Ident, sym: Opt[MemberSymbol])(using State, Elaborator.Ctx): Sel =\n    Sel(this, id)(sym, FlowSymbol.sel(id.name), N, S(summon))\n  def selNoSym(nme: Str, synth: Bool = false)(using State, Elaborator.Ctx): Sel | SynthSel =\n    val id = new Tree.Ident(nme)\n    if synth\n    then SynthSel(this, id)(N, FlowSymbol.synthSel(nme), N, S(summon))\n    else sel(id, N)\n  \n  def app(args: Term*)(using State) =\n    App(this, Tup(args.toList.map(PlainFld(_)))(Tree.DummyTup))\n      (Tree.App(Tree.Dummy, Tree.Dummy), N, FlowSymbol(\"\"))\n  \n  override def mkClone(using State): Term = \n    val that = this match\n      case Error => Error\n      case UnitVal() => UnitVal()\n      case Missing => Missing\n      case Lit(Tree.StrLit(value)) => Lit(Tree.StrLit(value))\n      case Lit(Tree.IntLit(value)) => Lit(Tree.IntLit(value))\n      case Lit(Tree.DecLit(value)) => Lit(Tree.DecLit(value))\n      case Lit(Tree.BoolLit(value)) => Lit(Tree.BoolLit(value))\n      case Lit(Tree.UnitLit(value)) => Lit(Tree.UnitLit(value))\n      case term @ Resolved(t, sym) => Resolved(t.mkClone, sym)(term.typ)\n      case term @ Ref(sym) => Ref(sym)(Tree.Ident(term.tree.name), term.refNum, term.typ)\n      case term @ App(lhs, rhs) => App(lhs.mkClone, rhs.mkClone)(term.tree, term.typ, term.resSym)\n      case term @ TyApp(lhs, targs) => TyApp(lhs.mkClone, targs.map(_.mkClone))(term.typ)\n      case term @ Sel(prefix, nme) => Sel(prefix.mkClone, Tree.Ident(nme.name))(term.sym, term.resSym, term.typ, term.originalCtx)\n      case term @ SynthSel(prefix, nme) => SynthSel(prefix.mkClone, Tree.Ident(nme.name))(term.sym, term.resSym, term.typ, term.originalCtx)\n      case DynSel(prefix, fld, arrayIdx) => DynSel(prefix.mkClone, fld.mkClone, arrayIdx)\n      case term @ Tup(fields) => Tup(fields.map {\n        case f: Fld => f.copy(term = f.term.mkClone, asc = f.asc.map(_.mkClone))\n        case s: Spd => s.copy(term = s.term.mkClone)\n      })(term.tree)\n      case Mut(underlying) => Mut(underlying.mkClone.asInstanceOf[Tup | Rcd | New | DynNew])\n      case term @ CtxTup(fields) => CtxTup(fields.map {\n        case f: Fld => f.copy(term = f.term.mkClone, asc = f.asc.map(_.mkClone))\n        case s: Spd => s.copy(term = s.term.mkClone)\n      })(term.tree)\n      case IfLike(kw, form, split) => IfLike(kw, form, split.mkClone)\n      case SynthIf(split) => SynthIf(split.mkClone)\n      case Lam(params, body) => Lam(params, body.mkClone)\n      case FunTy(lhs, rhs, eff) => FunTy(lhs.mkClone, rhs.mkClone, eff.map(_.mkClone))\n      case Forall(tvs, outer, body) => Forall(tvs, outer, body.mkClone)\n      case Constrained(constraints, body) => Constrained(constraints, body.mkClone)\n      case WildcardTy(in, out) => WildcardTy(in.map(_.mkClone), out.map(_.mkClone))\n      case blk: Blk => blk.mkBlkClone\n      case Rcd(mut, stats) => Rcd(mut, stats.map(_.mkClone))\n      case Quoted(body) => Quoted(body.mkClone)\n      case Unquoted(body) => Unquoted(body.mkClone)\n      case term @ New(cls, args, rft) =>\n        New(cls.mkClone, args.map(_.mkClone), rft.map { case (cs, ob) => cs -> ObjBody(ob.blk.mkBlkClone) })(term.typ)\n      case DynNew(cls, args) => DynNew(cls.mkClone, args.map(_.mkClone))\n      case term @ SelProj(prefix, cls, proj) =>\n        SelProj(prefix.mkClone, cls.mkClone, Tree.Ident(proj.name))(term.sym, term.resSym, term.typ, term.originalCtx)\n      case Asc(term, ty) => Asc(term.mkClone, ty.mkClone)\n      case CompType(lhs, rhs, pol) => CompType(lhs.mkClone, rhs.mkClone, pol)\n      case Neg(rhs) => Neg(rhs.mkClone)\n      case Region(name, body) => Region(name, body.mkClone)\n      case RegRef(reg, value) => RegRef(reg.mkClone, value.mkClone)\n      case Assgn(lhs, rhs) => Assgn(lhs.mkClone, rhs.mkClone)\n      case Drop(trm) => Drop(trm.mkClone)\n      case Deref(ref) => Deref(ref.mkClone)\n      case SetRef(ref, value) => SetRef(ref.mkClone, value.mkClone)\n      case Ret(result) => Ret(result.mkClone)\n      case Throw(result) => Throw(result.mkClone)\n      case Try(body, finallyDo) => Try(body.mkClone, finallyDo.mkClone)\n      case Annotated(annot, target) => Annotated(annot, target.mkClone)\n      case Handle(lhs, rhs, args, derivedClsSym, defs, body) =>\n        Handle(lhs, rhs.mkClone, args.map(_.mkClone), derivedClsSym, defs, body.mkClone)\n    (this, that) match\n      case (self: Resolvable, that: Resolvable) if self.expansion.isDefined =>\n        that.expand(self.expansion.get.map(_.mkClone))\n      case _ =>\n        that\n  \nend Term\n\nobject Term:\n  /** Compute the free variable names of a block given its statements and the\n    * free vars of its result term. Processes statements right-to-left so that\n    * bindings introduced by `LetDecl`, `TermDefinition`, class definitions,\n    * etc. correctly shadow uses in subsequent statements. */\n  private[semantics] def blkFreeVars(stats: Ls[Statement], resFree: Set[Str]): Set[Str] =\n    val blockLevelBinders = Buffer.empty[Str]\n    stats.foreach:\n      case td: TermDefinition =>\n        blockLevelBinders += td.sym.nme\n      case cls: ClassLikeDef =>\n        blockLevelBinders += cls.sym.nme\n      case td: TypeDef =>\n        blockLevelBinders += td.bsym.nme\n      case _: (Import | SetConfig | RcdField | RcdSpread | Term | LetDecl | DefineVar) => ()\n    (stats.foldRight(resFree): (stat, acc) =>\n      stat match\n        case LetDecl(sym, annotations) =>\n          (acc - sym.nme) ++ annotations.iterator.flatMap(_.subTerms).flatMap(_.freeVars)\n        case DefineVar(sym, rhs) =>\n          acc + sym.nme ++ rhs.freeVars\n        case t: Term =>\n          acc ++ t.freeVars\n        case _: (Import | SetConfig | RcdField | RcdSpread | TermDefinition | ClassLikeDef | TypeDef) =>\n          acc ++ stat.subTerms.iterator.flatMap(_.freeVars)\n    ) -- blockLevelBinders\n  \n  /** Free vars of a TermDefinition body, with its own params subtracted. */\n  private[semantics] def termDefFreeVars(td: TermDefinition): Set[Str] =\n    val paramNames = td.params.iterator.flatMap(_.allParams).map(_.sym.nme).toSet\n    val bodyFree = td.body.iterator.flatMap(_.freeVars).toSet\n    val signFree = td.sign.iterator.flatMap(_.freeVars).toSet\n    (bodyFree ++ signFree) -- paramNames\n  \n  /** Free vars of a ClassLikeDef body, with constructor params subtracted. */\n  private def classLikeDefFreeVars(cls: ClassLikeDef): Set[Str] =\n    val paramNames = cls.paramsOpt.iterator.flatMap(_.allParams).map(_.sym.nme).toSet\n    val bodyFree = cls.body.blk.freeVars\n    val extFree = cls.ext.iterator.flatMap(_.freeVars).toSet\n    (bodyFree ++ extFree) -- paramNames\nend Term\n\nimport Term.*\n\n\nextension (self: Blk)\n  def mapRes(f: Term => Term) =\n    Blk(self.stats, f(self.res))\n\n\ncase class ShowCfg(\n  showExpansionMappings: Bool,\n  showFlowSymbols: Bool,\n  debug: Bool,\n):\n  // * Rather ugly way of collecting shown symbols during show operations\n  val shownSymbols: MutSet[Symbol] = MutSet.empty\nend ShowCfg\n\nobject ShowCfg:\n  // * For use when displaying things for internal use (not for end users)\n  val internal = ShowCfg(\n    showFlowSymbols = true,\n    showExpansionMappings = false,\n    debug = false,\n  )\nend ShowCfg\n\n\nsealed trait Statement extends AutoLocated, ProductWithExtraInfo:\n  \n  def mkClone(using State): Statement = this match\n    case t: Term => lastWords(s\"overridden implementation\")\n    case d: Definition => ???\n    case imp: Import => Import(imp.sym, imp.str, imp.file)\n    case LetDecl(sym, annotations) => LetDecl(sym, annotations.map(_.mkClone))\n    case RcdField(field, rhs) => RcdField(field.mkClone, rhs.mkClone)\n    case RcdSpread(rcd) => RcdSpread(rcd.mkClone)\n    case DefineVar(sym, rhs) => DefineVar(sym, rhs.mkClone)\n    case sc: SetConfig => sc\n  \n  def describe: Str =\n    val desc = this match\n      case Error => \"‹error›\"\n      case UnitVal() => \"unit value\"\n      case Lit(lit) => lit.describeLit\n      case Ref(sym) => \"reference\"\n      case App(lhs, rhs) => \"application\"\n      case TyApp(lhs, targs) => \"type application\"\n      case Sel(pre, nme) => \"selection\"\n      case SynthSel(pre, nme) => \"selection\"\n      case DynSel(o, f, _) => \"dynamic selection\"\n      case Tup(fields) => \"tuple literal\"\n      case CtxTup(fields) => \"contextual tuple literal\"\n      case IfLike(_, IfLikeForm.ReturningIf, body) => \"`if` expression\"\n      case IfLike(_, IfLikeForm.ImperativeIf, body) => \"`if` statement\"\n      case IfLike(_, IfLikeForm.While, body) => \"`while` statement\"\n      case SynthIf(split) => \"synthetic `if` expression\"\n      case Lam(params, body) => \"function literal\"\n      case FunTy(lhs, rhs, eff) => \"function type\"\n      case Forall(tvs, outer, body) => \"universal quantification\"\n      case Constrained(constraints, body) => \"constrained type\"\n      case WildcardTy(in, out) => \"wildcard type\"\n      case Blk(stats, res) => \"block\"\n      case Quoted(term) => \"quoted term\"\n      case Unquoted(term) => \"unquoted term\"\n      case New(cls, args, rft) => \"object creation\"\n      case SelProj(pre, cls, proj) => \"field selection\"\n      case Asc(term, ty) => \"type ascription\"\n      case CompType(lhs, rhs, pol) => \"composed type\"\n      case Neg(rhs) => \"negation type\"\n      case Region(name, body) => \"region expression\"\n      case RegRef(reg, value) => \"reference creation\"\n      case Assgn(lhs, rhs) => \"assignment\"\n      case SetRef(ref, value) => \"mutable reference assignment\"\n      case Drop(ref) => \"drop\"\n      case Deref(ref) => \"dereference\"\n      case Throw(e) => \"throw\"\n      case Annotated(annotation, target) => \"annotation\"\n      case Ret(res) => \"return\"\n      case Try(body, finallyDo) => \"try expression\"\n      case Missing => \"missing\"\n      case LeadingDotSel(name) => \"leading dot selection\"\n      case Resolved(t, sym) => t.describe\n      case s => TODO(s)\n    this match\n      case self: Resolvable => self.resolvedTyp match\n        case S(typ) => s\"${desc} of type ${typ.show}\"\n        case N => desc\n      case _ => desc\n  \n  def extraInfo(using DebugPrinter): Str = this match\n    case r: Resolvable if r.resolvedSym.isDefined || r.resolvedTyp.isDefined => (\n        r.resolvedSym.map(s => s\"sym=${s.showAsPlain}\") ::\n        r.resolvedTyp.map(s => s\"typ=${s.showDbg}\") :: Nil\n      ).flatten.mkString(\",\")\n    case r: SelProj => r.symbol.mkString\n    case _ => \"\"\n  \n  def subStatements: Vector[Statement] = this match\n    case Blk(stats, res) => stats.toVector :+ res\n    case _ => subTerms\n  def subTerms: Vector[Term] = this match\n    case Error | Missing | _: Lit | _: Ref | _: UnitVal => Vector.empty\n    case Resolved(t, sym) => Vector.single(t)\n    case App(lhs, rhs) => Vector.double(lhs, rhs)\n    case RcdField(lhs, rhs) => Vector.double(lhs, rhs)\n    case RcdSpread(bod) => Vector.single(bod)\n    case FunTy(lhs, rhs, eff) => Vector.double(lhs, rhs) ++ eff.toVector\n    case TyApp(pre, tarsg) => pre +: tarsg.toVector\n    case Sel(pre, _) => Vector.single(pre)\n    case SynthSel(pre, _) => Vector.single(pre)\n    case DynSel(o, f, _) => Vector.double(o, f)\n    case Tup(fields) => fields.flatMap(_.subTerms).toVector\n    case Mut(und) => Vector.single(und)\n    case CtxTup(fields) => fields.flatMap(_.subTerms).toVector\n    case IfLike(_, _, split) => split.subTerms\n    case SynthIf(split) => split.subTerms\n    case Lam(params, body) => params.allParams.iterator.flatMap(_.sign).toVector :+ body\n    case Blk(stats, res) => stats.flatMap(_.subTerms).toVector :+ res\n    case Rcd(mut, stats) => stats.flatMap(_.subTerms).toVector\n    case Quoted(term) => Vector.single(term)\n    case Unquoted(term) => Vector.single(term)\n    case New(cls, args, rft) => (cls +: args.toVector) ++ rft.toVector.flatMap(_._2.blk.subTerms)\n    case DynNew(cls, args) => cls +: args.toVector\n    case SelProj(pre, cls, _) => Vector.double(pre, cls)\n    case Asc(term, ty) => Vector.double(term, ty)\n    case Ret(res) => Vector.single(res)\n    case Throw(res) => Vector.single(res)\n    case Forall(_, _, body) => Vector.single(body)\n    case Constrained(constraints, body) => constraints.flatMap(_.subTerms).toVector :+ body\n    case WildcardTy(in, out) => in.toVector ++ out.toVector\n    case CompType(lhs, rhs, _) => Vector.double(lhs, rhs)\n    case LetDecl(sym, annotations) => annotations.flatMap(_.subTerms).toVector\n    case DefineVar(sym, rhs) => Vector.single(rhs)\n    case Region(_, body) => Vector.single(body)\n    case RegRef(reg, value) => Vector.double(reg, value)\n    case Assgn(lhs, rhs) => Vector.double(lhs, rhs)\n    case SetRef(lhs, rhs) => Vector.double(lhs, rhs)\n    case Drop(term) => Vector.single(term)\n    case Deref(term) => Vector.single(term)\n    case TermDefinition(_, _, _, pss, tps, sign, body, _, _, annotations, _) =>\n      pss.toVector.flatMap(_.subTerms) ++ tps.getOrElse(Nil).flatMap(_.subTerms).toVector ++ sign.toVector ++ body.toVector ++ annotations.flatMap(_.subTerms).toVector\n    case cls: ClassDef =>\n      (cls.paramsOpt.toVector.flatMap(_.subTerms) :+ cls.body.blk) ++ cls.annotations.flatMap(_.subTerms).toVector\n    case mod: ModuleOrObjectDef =>\n      ( mod.paramsOpt.toVector.flatMap(_.subTerms) :+ mod.body.blk) ++ mod.annotations.flatMap(_.subTerms).toVector\n    case td: TypeDef =>\n      td.rhs.toVector ++ td.annotations.flatMap(_.subTerms).toVector\n    case pat: PatternDef =>\n      (pat.paramsOpt.toVector.flatMap(_.subTerms) :+ pat.body.blk) ++ pat.annotations.flatMap(_.subTerms).toVector\n    case Import(sym, str, pth) => Vector.empty\n    case Try(body, finallyDo) => Vector.single(body) ++ Vector.single(finallyDo)\n    case Handle(lhs, rhs, args, derivedClsSym, defs, bod) => (rhs +: args.toVector) ++ defs.flatMap(_.td.subTerms).toVector :+ bod\n    case Neg(e) => Vector.single(e)\n    case Annotated(ann, target) => ann.subTerms ++ Vector.single(target)\n    case LeadingDotSel(nme) => Vector.empty\n    case SetConfig(_) => Vector.empty\n  \n  // private def treeOrSubterms(t: Tree, t: Term): Ls[Located] = t match\n  private def treeOrSubterms(t: Tree): Vector[Located] = t match\n    case Tree.DummyApp | Tree.DummyTup => subTerms\n    case _ => Vector.single(t)\n  \n  protected def children: Vector[Located] = this match\n    case t: Lit => Vector.single(t.lit.asTree)\n    case t: Ref => treeOrSubterms(t.tree)\n    case t: Tup => treeOrSubterms(t.tree)\n    case l: Lam => Vector.double(l.params, l.body)\n    case t: App => treeOrSubterms(t.tree)\n    case IfLike(_, _, split) => Vector.single(split)\n    case SynthIf(split) => Vector.single(split)\n    case SynthSel(pre, nme) => Vector.double(pre, nme)\n    case Sel(pre, nme) => Vector.double(pre, nme)\n    case SelProj(prefix, cls, proj) => Vector.triple(prefix, cls, proj)\n    case _ =>\n      subTerms // TODO more precise (include located things that aren't terms)\n  \n  def show(using Scope, ShowCfg, Raise): Document =\n    def res: Document = this match\n      case lit: Lit => lit.lit.idStr\n      case r: Ref =>\n        r.sym match\n        case _: BuiltinSymbol => r.sym.nme\n        case _ => r.sym.showName\n      case sel: Sel =>\n        if summon[ShowCfg].showFlowSymbols\n        then doc\"${sel.prefix.show}.${sel.sym.fold(doc\"${sel.nme.name}‹?›\")(_.showName)}\"\n        else doc\"${sel.prefix.show}.${sel.nme.name}\"\n      case sel: SynthSel =>\n        if summon[ShowCfg].showFlowSymbols\n        then doc\"⟨${sel.prefix.show}.⟩${sel.sym.fold(doc\"${sel.nme.name}‹?›\")(_.showName)}\"\n        else doc\"${sel.prefix.show}.${sel.nme.name}\"\n      case Resolved(trm, sym) =>\n        trm.show\n      case app: App =>\n        doc\"${app.lhs.show}${app.rhs.showAsParams}${\n          if summon[ShowCfg].showFlowSymbols\n          then\n            summon[ShowCfg].shownSymbols.add(app.resSym)\n            \"‹\" :: app.resSym.showPlainName :: \"›\"\n          else \"\"\n        }\"\n      case lam: Lam => doc\"${lam.params.show} => ${lam.body.show}\"\n      case nw: New => doc\"new ${nw.cls.show}${nw.args.map(_.showAsParams).mkDocument()}${\n        nw.rft.fold(doc\"\")(doc\" with \" :: _._2.blk.show)}\"\n      case tup: Tup => bracketed(\"[\", \"]\", insertBreak = true):\n        tup.fields.map(_.show).mkDocument(doc\", # \")\n      case blk: Blk => braced:\n        doc\" # \" :: (blk.stats :::\n            blk.res.match\n            case Lit(Tree.UnitLit(false)) => Nil\n            case res => res :: Nil\n          ).map(_.show).mkDocument(doc\", # \")\n      case ld: LetDecl =>\n        (ld.annotations.map(_.show) ::: doc\"let ${ld.sym.showName}\" :: Nil).mkDocument()\n      case df: DefineVar =>\n        doc\"${df.sym.showName} = ${df.rhs.show}\"\n      case td: TermDefinition =>\n          td.annotations.map(_.show).mkDocument()\n          :: doc\"${td.k.str} ${td.sym.showName}\"\n          :: (if td.tparams.isEmpty then doc\"\"\n            else doc\"[${td.tparams.get.map(_.sym.showName).mkDocument(\", \")}]\")\n          :: td.params.map(_.show).mkDocument()\n          :: td.sign.fold(doc\"\")(s => doc\": ${s.show}\")\n          :: (if summon[ShowCfg].showFlowSymbols then doc\" ‹${td.bsym.flow.showName}›\" else doc\"\")\n          :: td.body.fold(doc\"\")(b => doc\" = ${b.show}\")\n      case cld: ClassLikeDef =>\n          cld.annotations.map(_.show).mkDocument()\n          :: doc\"${cld.kind.str} ${cld.sym.nme}\"\n          :: (if cld.tparams.isEmpty then doc\"\"\n            else doc\"[${cld.tparams.map(_.sym.showName).mkDocument(\", \")}]\")\n          :: cld.paramsOpt.map(_.show).toList.mkDocument()\n          :: cld.auxParams.map(_.show).mkDocument()\n          :: doc\" ${cld.body.blk.show}\"\n      case imp: Import =>\n        doc\"import ${\"\\\"\"}.../${imp.file.last}${\"\\\"\"} as ${imp.sym.showName}\"\n      case LeadingDotSel(name) => doc\"_?_.${name.name}\"\n      case Error => doc\"‹error›\"\n      case _ =>\n        doc\"TODO[show:${getClass.getSimpleName}](${toString})\"\n    this match\n    case t: Resolvable => t.expansion match\n      case S(S(exp)) =>\n        val rhs = exp.show(using summon, summon[ShowCfg].copy(showExpansionMappings = false))\n        if summon[ShowCfg].showExpansionMappings then\n          if exp === t then rhs\n          // ^ Some expansions only modify meta-data, such as types and symbols;\n          //    we don't print them for conciseness\n          else res :: doc\"{ ~> \" :: rhs :: doc\" }\"\n        else exp.show\n      case _ => res\n    case _ => res\n  \n  def size: Int = this match\n    case Lit(Tree.StrLit(str)) => str.size / 4 + 1\n    case _ => subTerms.iterator.map(_.size).sum + 1\n  \n  def showDbg(using DebugPrinter): Str = this match\n    case r: Ref => r.sym.showAsPlain\n    case r: Resolved =>\n      s\"${r.showPlain}‹${r.sym}›\"\n    case trm: Term =>\n      // s\"$showPlain‹${trm.symbol.getOrElse(\"\")}›\"\n      s\"$showPlain${trm.symbol.fold(\"\")(\"‹\"+_+\"›\")}\"\n    case _ =>\n      showPlain\n\n  def showAsParams(using Scope, ShowCfg, Raise): Document = this match\n    case tup: Tup => doc\"(${tup.fields.map(_.show).mkDocument(\", \")})\"\n    case _ => doc\"(...$show)\"\n  \n  def showDbgAsParams(using DebugPrinter): Str = this match\n    case tup: Tup => s\"(${tup.fields.map(_.showDbg).mkString(\", \")})\"\n    case _ => s\"(...$showDbg)\"\n  \n  def showPlain(using DebugPrinter): Str = this match\n    case Term.UnitVal() => \"()\"\n    case Lit(lit) => lit.idStr\n    case Resolved(t, sym) => t.showPlain\n    case r @ Ref(symbol) => symbol.toString + symbol.getState.dbgRefNum(r.refNum)\n    case App(lhs, rhs) => s\"${lhs.showDbg}${rhs.showDbgAsParams}\"\n    case RcdField(lhs, rhs) => s\"${lhs.showDbg}: ${rhs.showDbg}\"\n    case RcdSpread(bod) => s\"...${bod.showDbg}\"\n    case FunTy(lhs: Tup, rhs, eff) =>\n      s\"${lhs.fields.map(_.showDbg).mkString(\", \")} ->${\n        eff.map(e => s\"{${e.showDbg}}\").getOrElse(\"\")} ${rhs.showDbg}\"\n    case FunTy(lhs, rhs, eff) =>\n      s\"(...${lhs.showDbg}) ->${eff.map(e => s\"{${e.showDbg}}\").getOrElse(\"\")} ${rhs.showDbg}\"\n    case TyApp(lhs, targs) => s\"${lhs.showDbg}[${targs.mkString(\", \")}]\"\n    case Forall(tvs, outer, body) => s\"forall ${tvs.mkString(\", \")}${outer.map(v => s\", outer $v\").mkString}: ${body.toString}\"\n    case Constrained(constraints, body) => s\"[${constraints.map(_.showDbg).mkString(\", \")}] => ${body.showDbg}\"\n    case WildcardTy(in, out) => s\"in ${in.map(_.toString).getOrElse(\"⊥\")} out ${out.map(_.toString).getOrElse(\"⊤\")}\"\n    case Sel(pre, nme) => s\"${pre.showDbg}.${nme.name}\"\n    case SynthSel(pre, nme) => s\"(${pre.showDbg}.)${nme.name}\"\n    case DynSel(pre, fld, _) => s\"${pre.showDbg}[${fld.showDbg}]\"\n    case IfLike(kw, _, split) => s\"${kw.name} { ${split.showDbg} }\"\n    case SynthIf(split) => s\"if { ${split.showDbg} }\"\n    case Lam(params, body) => s\"λ${params.showDbg}. ${body.showDbg}\"\n    case Blk(stats, res) =>\n      (stats.map(_.showDbg + \"; \") :+ (res match { case Lit(Tree.UnitLit(false)) => \"\" case x => x.showDbg + \" \" }))\n      .mkString(\"{ \", \"\", \"}\")\n    case Rcd(mut, stats) =>\n      (if mut then \"mut \" else \"\") + stats.map(_.showDbg + \"; \").mkString(\"{ \", \"\", \"}\")\n    case Quoted(term) => s\"\"\"code\"${term.showDbg}\"\"\"\"\n    case Unquoted(term) => s\"$${${term.showDbg}}\"\n    case New(cls, args, rft) =>\n      s\"new ${cls.showDbg}${args.map(_.showDbgAsParams).mkString}${rft.fold(\"\")(r => s\"{ ${r._2.blk.showDbg} }\")}\"\n    case DynNew(cls, args) =>\n      s\"new! ${cls.showDbg}${args.map(_.showDbgAsParams).mkString}\"\n    case SelProj(pre, cls, proj) => s\"${pre.showDbg}.${cls.showDbg}#${proj.name}\"\n    case Asc(term, ty) => s\"${term.toString}: ${ty.toString}\"\n    case LetDecl(sym, _) => s\"let ${sym}\"\n    case DefineVar(sym, rhs) => s\"${sym} = ${rhs.showDbg}\"\n    case Handle(lhs, rhs, args, derivedClsSym, defs, bod) =>\n      s\"handle ${lhs} = ${rhs}(${args.mkString(\", \")}) ${defs} in ${bod}\"\n    case Region(name, body) => s\"region ${name.nme} in ${body.showDbg}\"\n    case RegRef(reg, value) => s\"(${reg.showDbg}).ref ${value.showDbg}\"\n    case Assgn(lhs, rhs) => s\"${lhs.showDbg} := ${rhs.showDbg}\"\n    case SetRef(lhs, rhs) => s\"${lhs.showDbg} := ${rhs.showDbg}\"\n    case Drop(term) => s\"drop $term\"\n    case Deref(term) => s\"!$term\"\n    case Neg(ty) => s\"~${ty.showDbg}\"\n    case CompType(lhs, rhs, pol) => s\"${lhs.showDbg} ${if pol then \"|\" else \"&\"} ${rhs.showDbg}\"\n    case Error => \"<error>\"\n    case Tup(fields) => fields.map(_.showDbg).mkString(\"[\", \", \", \"]\")\n    case Mut(und) => s\"mut ${und.showDbg}\"\n    case CtxTup(fields) => fields.map(_.showDbg).mkString(\"‹using›[\", \", \", \"]\")\n    case TermDefinition(k, sym, tsym, pss, tps, sign, body, flags, _, _, _) =>\n      s\"${flags.showDbg}${k.str} ${sym}${\n        tps.map(_.map(_.showDbg)).mkStringOr(\", \", \"[\", \"]\")\n      }${\n        pss.map(_.showDbg).mkString(\"\")\n      }${sign.fold(\"\")(\": \"+_.showDbg)}${\n        body match\n          case S(x) => \" = \" + x.showDbg\n          case N => \"\"\n        }\"\n    case cls: ClassLikeDef =>\n      s\"${cls.kind} ${cls.sym.nme}${\n        cls.tparams.map(_.showDbg).mkStringOr(\", \", \"[\", \"]\")}${\n        cls.paramsOpt.fold(\"\")(_.toString)} ${cls.body}\"\n    case Import(sym, str, file) => s\"import $str from ${file}\"\n    case Annotated(ann, target) => s\"@${ann} ${target.showDbg}\"\n    case Throw(res) => s\"throw ${res.showDbg}\"\n    case Try(body, finallyDo) => s\"try ${body.showDbg} finally ${finallyDo.showDbg}\"\n    case Ret(res) => s\"return ${res.showDbg}\"\n    case TypeDef(sym, _, tparams, rhs, _, _) =>\n      s\"type ${sym}${tparams.mkStringOr(\", \", \"[\", \"]\")} = ${rhs.fold(\"\")(x => x.showDbg)}\"\n    case Missing => \"missing\"\n    case LeadingDotSel(nme) => s\"_?_.${nme.name}\"\n\nfinal case class LetDecl(sym: LocalSymbol, annotations: Ls[Annot]) extends Statement\n\nfinal case class RcdField(field: Term, rhs: Term) extends Statement\nfinal case class RcdSpread(rcd: Term) extends Statement\n\nfinal case class DefineVar(sym: LocalSymbol, rhs: Term) extends Statement\n\n/** A global configuration change directive (`#config(...)`).\n  * Records a function that modifies the current compiler configuration. */\nfinal case class SetConfig(modify: hkmc2.Config => hkmc2.Config) extends Statement\n\nenum Visibility:\n  case Public, Private\n\n/**\n * isMethod: if the term is a method (as opposed to a function)\n */\nfinal case class TermDefFlags(isMethod: Bool):\n  def showDbg: Str = \n    val flags = Buffer.empty[String]\n    if isMethod then flags += \"method \"\n    flags.mkString\n  override def toString: String = \"‹\" + showDbg + \"›\"\n\nobject TermDefFlags { val empty: TermDefFlags = TermDefFlags(false) }\n\n/**\n * A case class representing the modulefulness of a declaration.\n *\n * @param msym if None, the declaration is non-moduful; if Some of\n * symbol, the declaration is moduleful and the symbol is the symbol of\n * the module's type\n */\nfinal case class Modulefulness(msym: Opt[ModuleOrObjectSymbol])(val modified: Bool):\n  \n  def isModuleful: Bool = msym.isDefined\n  \n  /**\n   * Return Some of the module definition if it is moduleful; None\n   * otherwise.\n   */\n  def mdef: Opt[ModuleOrObjectDef] = msym match\n    case S(msym) => msym.defn match\n      case S(defn: ModuleOrObjectDef) => S(defn)\n      case N => lastWords(s\"no definition for module symbol $msym\")\n    case N => N\n\nobject Modulefulness:\n  \n  def ofSign(sign: Option[Term])(modified: Bool) = \n    sign.flatMap(_.symbol) match\n      case S(sym: BlockMemberSymbol) if modified => sym.asMod match\n        case S(sym) => \n          Modulefulness(S(sym))(modified)\n        case N =>\n          Modulefulness(N)(modified)\n      case _ =>\n        Modulefulness(N)(modified)\n  \n  val none = Modulefulness(N)(false)\n\nfinal case class TermDefinition(\n    k: TermDefKind, // * The only reason we store it here in addition to tsym.k is for refining patmats\n    sym: BlockMemberSymbol,\n    tsym: TermSymbol,\n    params: Ls[ParamList],\n    tparams: Opt[Ls[Param]],\n    sign: Opt[Term],\n    body: Opt[Term],\n    flags: TermDefFlags,\n    modulefulness: Modulefulness,\n    annotations: Ls[Annot],\n    companion: Opt[CompanionSymbol],\n) extends CompanionValue:\n  require(k is tsym.k)\n  def bsym: BlockMemberSymbol = sym\n  val owner = tsym.owner\n  def visibility: Visibility = annotations.collectFirst:\n    case Annot.Modifier(Keyword.`private`) => Visibility.Private\n    case Annot.Modifier(Keyword.`public`) => Visibility.Public\n  .getOrElse(Visibility.Public)\n  def extraAnnotations: Ls[Annot] = annotations.filter:\n    case Annot.Modifier(Keyword.`declare` | Keyword.`abstract`) => false\n    case _ => true\n  \n  def companionClass: Opt[ClassSymbol] = companion match\n    case S(sym: ClassSymbol) if sym.defn.isDefined => S(sym)\n    case _ => N\n\nfinal case class HandlerTermDefinition(\n  resumeSym: VarSymbol,\n  td: TermDefinition\n)\n\nobject ObjBody:\n  \n  def extractMembers(blk: Term.Blk): Ls[ErrorReport] \\/ Map[Str, BlockMemberSymbol] =\n    val (errs, mems) = blk.stats.collect:\n      case td: TermDefinition => td.sym -> td\n      case td: ClassLikeDef => td.bsym -> td\n      case td: TypeDef => td.bsym -> td\n    .groupBy(_._1.nme)\n    .partitionMap: (nme, syms) =>\n      if syms.map(_._1).distinct.tail.nonEmpty then L:\n        (msg\"Duplicate definition of member named '${nme}'.\" -> N) ::\n        syms.map(_._2).map(msg\"Defined at: \" -> _.toLoc)\n      else R:\n        nme -> syms.head._1\n    \n    if errs.nonEmpty then\n      L(errs.map(ErrorReport(_)).toList)\n    else\n      R(mems.toMap)\n\ncase class ObjBody(blk: Term.Blk):\n  \n  lazy val members: Map[Str, BlockMemberSymbol] =\n    ObjBody.extractMembers(blk) match\n      case L(errs) => lastWords:\n        errs.map(_.mainMsg).mkString(\"\\n\")\n      case R(mems) =>\n        mems\n  \n  lazy val (methods, nonMethods) = blk.stats.partitionMap:\n    case td: TermDefinition if td.k is syntax.Fun => L(td)\n    case s => R(s)\n  \n  lazy val publicFlds: Ls[TermDefinition] = nonMethods.collect:\n    case td: TermDefinition if td.k.isInstanceOf[syntax.Val] => td\n  \n  // override def toString: String = statmts.mkString(\"{ \", \"; \", \" }\")\n  // override def toString: String = blk.showDbg\n\nend ObjBody\n\n\n/** `sym` is a `MemberSymbol` when the import is made by the user and can be referred to by name,\n  * in which case it is a `BlockMemberSymbol` when importing files explicitly\n  * and a `TermSymbol` when the import is made implicitly by the compiler (eg, importing \"Predef\").\n  * Note that the `file` Path may not represent a real file; eg when importing \"fs\". */\ncase class Import(sym: TempSymbol | MemberSymbol, str: Str, file: io.Path) extends Statement\n\n\nsealed abstract class Declaration:\n  val sym: Symbol\n  \n  /** Whether this declares a class, a pattern, an object, or a pattern\n    * parameter. Only these can be in patterns constructor position. */\n  def isPatternConstructor: Bool = this match\n    case _: (TermDefinition | TypeDef | TyParam) => false\n    case d: ModuleOrObjectDef => d.kind isnt Mod\n    case _: (PatternDef | ClassDef) => true\n    case p: Param => p.flags.pat\n\nsealed abstract class Definition extends Declaration, Statement:\n  val annotations: Ls[Annot]\n  def bsym: BlockMemberSymbol\n  def hasDeclareModifier: Opt[Annot.Modifier] = annotations.collectFirst:\n    case mod @ Annot.Modifier(Keyword.`declare`) => mod\n  def hasStagedModifier: Opt[Annot.Modifier] = annotations.collectFirst:\n    case mod @ Annot.Modifier(Keyword.`staged`) => mod\n\nsealed trait CompanionValue extends Definition\n\ntype CompanionSymbol = ModuleOrObjectSymbol | TypeAliasSymbol | ClassSymbol\ntype ClassCompanionSymbol = ModuleOrObjectSymbol | TypeAliasSymbol\ntype ModuleCompanionSymbol = TypeAliasSymbol | ClassSymbol\n\n\nsealed abstract class TypeLikeDef extends Definition:\n  val bsym: BlockMemberSymbol\n  val tparams: Ls[TyParam]\n  val annotations: Ls[Annot]\n\nsealed abstract class ClassLikeDef extends TypeLikeDef:\n  val owner: Opt[InnerSymbol]\n  val kind: ClsLikeKind\n  val sym: DefinitionSymbol[? <: ClassLikeDef] & InnerSymbol\n  val bsym: BlockMemberSymbol\n  val ctorSym: Opt[TermSymbol]\n  val tparams: Ls[TyParam]\n  val paramsOpt: Opt[ParamList]\n  val auxParams: Ls[ParamList]\n  val ext: Opt[New]\n  val body: ObjBody\n  val companion: Opt[CompanionSymbol]\n  val annotations: Ls[Annot]\n  def classCompanion = companion match\n    case S(sym: ClassSymbol) => S(sym)\n    case _ => N\n  def moduleCompanion = companion match\n    case S(sym: ModuleOrObjectSymbol) => S(sym)\n    case _ => N\n  def extraAnnotations(using Ctx): Ls[Annot] = annotations.filter:\n    case Annot.Modifier(Keyword.`declare` | Keyword.`abstract` | Keyword.`data`) => false\n    case Annot.Trm(trm: SynthSel) if\n      (kind is Cls) &&\n        (trm.sym.contains(ctx.builtins.annotations.bufferable) ||\n        trm.sym.contains(ctx.builtins.annotations.buffered)) => false\n    case _ => true\n\n\ncase class ModuleOrObjectDef(\n  owner: Opt[InnerSymbol], \n  sym: ModuleOrObjectSymbol, \n  bsym: BlockMemberSymbol,\n  tparams: Ls[TyParam], \n  paramsOpt: Opt[ParamList], \n  auxParams: Ls[ParamList], \n  ext: Opt[New],\n  kind: ClsLikeKind,\n  body: ObjBody,\n  companion: Opt[ModuleCompanionSymbol],\n  annotations: Ls[Annot],\n)(\n  val path: SrcScope\n) extends ClassLikeDef, CompanionValue:\n  val ctorSym: Option[TermSymbol] = N\n\ncase class PatternDef(\n    owner: Opt[InnerSymbol],\n    sym: PatternSymbol,\n    bsym: BlockMemberSymbol,\n    tparams: Ls[TyParam],\n    /** All parameters. */\n    parameters: Ls[Param],\n    /** The pattern parameters, for example, `T` in\n     *  `pattern Nullable(pattern T) = null | T`. */\n    patternParams: Ls[Param],\n    /** The extraction parameters, for example, `x` in\n     *  `pattern PairLike(x, y) = [x, y] | Pair(x, y)`. */\n    extractionParams: Ls[Param],\n    /** The elaborated pattern on the right-hand side, for example,\n     *  `[x, y] | Pair(x, y)` in `pattern PairLike(x, y) = [x, y] | Pair(x, y)`.\n     */\n    pattern: Pattern,\n    annotations: Ls[Annot],\n) extends ClassLikeDef:\n  self =>\n  val kind: ClsLikeKind = Pat\n  val ext: Opt[New] = N\n  /** Each pattern definition should contain two methods: `unapply` and\n   *  `unapplyStringPrefix`, which are generated in `Lowering`. Hence, there\n   *  is no need to make `body` a parameter. */\n  val body: ObjBody = ObjBody(Blk(Nil, Term.Lit(syntax.Tree.UnitLit(false))))\n  /** Pattern definitions do not need parameter lists. */\n  val paramsOpt: Opt[ParamList] = N\n  val auxParams: Ls[ParamList] = Nil\n  val companion: Opt[CompanionSymbol] = N // TODO support\n  val ctorSym: Option[TermSymbol] = N\n\n\nsealed abstract class ClassDef extends ClassLikeDef:\n  val kind: ClsLikeKind\n  val sym: ClassSymbol\n  val bsym: BlockMemberSymbol\n  val ctorSym: Opt[TermSymbol]\n  val tparams: Ls[TyParam]\n  val paramsOpt: Opt[ParamList]\n  val auxParams: Ls[ParamList]\n  val body: ObjBody\n  val companion: Opt[ClassCompanionSymbol]\n  val annotations: Ls[Annot]\n  def isData: Opt[Annot.Modifier] = annotations.collectFirst:\n    case mod @ Annot.Modifier(Keyword.`data`) => mod\n  override def extraAnnotations(using Ctx): Ls[Annot] = super.extraAnnotations.filter:\n    case Annot.Modifier(Keyword.`data`) => false\n    case _ => true\n\nobject ClassDef:\n  def apply(\n      owner: Opt[InnerSymbol],\n      kind: ClsLikeKind,\n      sym: InnerSymbol,\n      bsym: BlockMemberSymbol,\n      ctorSym: Opt[TermSymbol],\n      tparams: Ls[TyParam],\n      params: Ls[ParamList],\n      ext: Opt[New],\n      body: ObjBody,\n      annotations: Ls[Annot],\n      comp: Opt[ClassCompanionSymbol],\n  ): ClassDef =\n    params match\n      case ps :: pss => Parameterized(owner, kind, sym.asInstanceOf// TODO: improve\n        , bsym, S(ctorSym.getOrElse(lastWords(\"Parameterized classes should have a ctor symbol.\")))\n        , tparams, ps, pss, ext, body, comp, annotations)\n      case Nil => Plain(owner, kind, sym.asInstanceOf// TODO: improve\n        , bsym\n        , tparams, ext, body, comp, annotations)\n  \n  def unapply(cls: ClassDef): Opt[(ClassSymbol, Ls[TyParam], Opt[ParamList], ObjBody)] =\n    S((cls.sym, cls.tparams, cls.paramsOpt, cls.body))\n  \n  case class Parameterized(\n      owner: Opt[InnerSymbol],\n      kind: ClsLikeKind,\n      sym: ClassSymbol,\n      bsym: BlockMemberSymbol,\n      ctorSym: S[TermSymbol],\n      tparams: Ls[TyParam],\n      params: ParamList,\n      auxParams: Ls[ParamList],\n      ext: Opt[New],\n      body: ObjBody,\n      companion: Opt[ClassCompanionSymbol],\n      annotations: Ls[Annot],\n  ) extends ClassDef:\n    val paramsOpt: Opt[ParamList] = S(params)\n  \n  case class Plain(\n      owner: Opt[InnerSymbol],\n      kind: ClsLikeKind,\n      sym: ClassSymbol,\n      bsym: BlockMemberSymbol,\n      tparams: Ls[TyParam],\n      ext: Opt[New],\n      body: ObjBody,\n      companion: Opt[ClassCompanionSymbol],\n      annotations: Ls[Annot]\n  ) extends ClassDef:\n    val paramsOpt: Opt[ParamList] = N\n    val auxParams: List[ParamList] = Nil\n    val ctorSym: Opt[TermSymbol] = N\n  \nend ClassDef\n\n\ncase class TypeDef(\n  sym: TypeAliasSymbol,\n  bsym: BlockMemberSymbol,\n  tparams: Ls[TyParam],\n  rhs: Opt[Term],\n  companion: Opt[CompanionValue],\n  annotations: Ls[Annot],\n) extends TypeLikeDef\n\n\n// TODO Store optional source locations for the flags instead of booleans\nfinal case class FldFlags(mut: Bool, spec: Bool, pat: Bool, isVal: Bool):\n  def show: Str = \n    val flags = Buffer.empty[String]\n    if mut then flags += \"mut\"\n    if spec then flags += \"spec\"\n    if pat then flags += \"pattern\"\n    if isVal then flags += \"val\"\n    flags.mkString(\" \")\n  override def toString: String = \"‹\" + show + \"›\"\n\nobject FldFlags:\n  val empty: FldFlags = FldFlags(false, false, false, false)\n  object benign:\n    // * Some flags like `mut` and `module` are \"benign\" in the sense that they don't affect code-gen\n    def unapply(flags: FldFlags): Bool =\n      !flags.spec\n\n\nenum IfLikeForm:\n  case ReturningIf, ImperativeIf, While\n  def isImperative: Bool = this match\n    case ReturningIf => false\n    case ImperativeIf | While => true\n\n\nsealed abstract class Elem:\n  def subTerms: Ls[Term] = this match\n    case Fld(_, term, asc) => term :: asc.toList\n    case Spd(_, term) => term :: Nil\n  def show(using Scope, ShowCfg, Raise): Document\n  def showDbg(using DebugPrinter): Str\nobject Elem:\n  given Conversion[Term, Elem] = PlainFld(_)\nfinal case class Fld(flags: FldFlags, term: Term, asc: Opt[Term]) extends Elem, FldImpl\nobject PlainFld:\n  def apply(term: Term) = Fld(FldFlags.empty, term, N)\n  def unapply(fld: Fld): Opt[Term] = S(fld.term)\nfinal case class Spd(k: SpreadKind, term: Term) extends Elem:\n  def show(using Scope, ShowCfg, Raise): Document = k.str :: term.show\n  def showDbg(using DebugPrinter): Str = k.str + term.showDbg\n\nfinal case class TyParam(flags: FldFlags, vce: Opt[Bool], sym: VarSymbol) extends Declaration:\n  \n  // * For variance analysis\n  var isCovariant: Bool = true\n  var isContravariant: Bool = true\n  \n  def showDbg: Str =\n    // (if isContravariant then \"in \" else \"\") +\n    // (if isCovariant then \"out \" else \"\") +\n    (if isCovariant then\n      if isContravariant then \"\" else \"out \"\n      else if isContravariant then \"in \" else \"in out \") +\n    flags.show + sym\n\n\nobject Param:\n  def simple(sym: VarSymbol) = Param(FldFlags.empty, sym, N, Modulefulness.none)\n\nfinal case class Param(flags: FldFlags, sym: VarSymbol, sign: Opt[Term], modulefulness: Modulefulness)\nextends Declaration, AutoLocated:\n  var fldSym: Opt[MemberSymbol] = N\n  \n  val flow: FlowSymbol = sym\n\n  // * This field is filled in during flow analysis;\n  // * it is not meant to be maintained afterwards (so it does not need to be copied around).\n  var signType: Opt[Type] = N\n  \n  def withSignTypeOf(p: Param): this.type =\n    signType = p.signType\n    this\n  \n  def subTerms: Ls[Term] = sign.toList\n  \n  override protected def children: Vector[Located] = sym +: sign.toVector\n  \n  def show(using Scope, ShowCfg, Raise): Document =\n    doc\"${flags.show}${sym.showName}${sign.fold(doc\"\")(\": \" :: _.show)}\"\n  \n  def showDbg(using DebugPrinter): Str = flags.show + sym + sign.fold(\"\")(\": \" + _.showDbg)\n\nfinal case class ParamList(flags: ParamListFlags, params: Ls[Param], restParam: Opt[Param])\nextends AutoLocated:\n  override protected def children: Vector[Located] = params.toVector ++ restParam\n  def foreach(f: Param => Unit): Unit = (params.iterator ++ restParam).foreach(f)\n  def paramCountLB: Int = params.length\n  def paramCountUB: Bool = restParam.isEmpty\n  lazy val paramSyms = params.map(_.sym) ++ restParam.map(_.sym)\n  lazy val allParams = params ++ restParam.toList\n  def subTerms: Ls[Term] = params.flatMap(_.subTerms) ++ restParam.toList.flatMap(_.subTerms)\n  def show(using Scope, ShowCfg, Raise): Document =\n    flags.show\n    :: doc\"(\" :: (\n      params.map(_.show)\n      :::\n      restParam.map(p => doc\"...${p.show}\").toList\n    ).mkDocument(\", \")\n    :: doc\")\"\n  def showDbg(using DebugPrinter): Str = flags.showDbg\n    + (params.map(_.showDbg) ++ restParam.toList.map(\"...\" + _.showDbg)).mkString(\"(\", \", \", \")\")\nobject PlainParamList:\n  def apply(params: Ls[Param]) =\n    ParamList(ParamListFlags.empty, params, N)\n  def unapply(pl: ParamList): Opt[Ls[Param]] = pl match\n    case ParamList(ParamListFlags.empty, params, N) => S(params)\n    case _ => N\n\nfinal case class ParamListFlags(ctx: Bool):\n  def show: Str = (if ctx then \"ctx \" else \"\")\n  def showDbg: Str = (if ctx then \"ctx \" else \"\")\n  override def toString: String = \"‹\" + showDbg + \"›\"\n\n/** A subtyping direction. */\nenum SubDir:\n  case Sub, Sup\n  def showDbg: Str = this match\n    case Sub => \"<:\"\n    case Sup => \":>\"\n\n/** A subtyping constraint. */\nfinal case class SubConstraint(lhs: Term, rhs: Term, dir: SubDir) extends AutoLocated:\n  override protected def children: Vector[Located] = Vector(lhs, rhs)\n  def showDbg(using DebugPrinter): Str = s\"${lhs.showDbg} ${dir.showDbg} ${rhs.showDbg}\"\n  def subTerms: Ls[Term] = List(lhs, rhs)\n\nobject ParamListFlags:\n  val empty = ParamListFlags(false)\n\n\ntrait FldImpl extends AutoLocated:\n  self: Fld =>\n  def children: Vector[Located] = self.term +: self.asc.toVector\n  def show(using Scope, ShowCfg, Raise): Document = flags.show :: self.term.show\n  def showDbg(using DebugPrinter): Str = flags.show + self.term.showDbg\n  def describe: Str =\n    (if self.flags.spec then \"specialized \" else \"\") +\n    (if self.flags.mut then \"mutable \" else \"\") +\n    self.term.describe\n\n/**\n * Unwrapper that unwraps a term until it is no longer an App.\n */\nobject Apps:\n  def unapply(t: Term): S[(Term, Ls[Term])] = t match\n    case Term.App(Apps(base, args), arg) => S(base, args :+ arg)\n    case t => S(t, Nil)\n\n\ntrait BlkImpl:\n  this: Blk =>\n  def mkBlkClone(using State): Blk = Blk(stats.map(_.mkClone), res.mkClone)\n  def showTopLevel(using Scope, ShowCfg, Raise): Document =\n    (stats ::: (res match\n      case Lit(Tree.UnitLit(false)) => Nil\n      case res => res :: Nil)).map(_.show).mkDocument(doc\", # \")\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/flow/Constraint.scala",
    "content": "package hkmc2\npackage semantics\npackage flow\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.Scope\nimport hkmc2.utils.Scope.scope\nimport hkmc2.document.*\n\nimport typing.*\nimport semantics.*\nimport hkmc2.syntax.SpreadKind\nimport hkmc2.syntax.Tree.{UnitLit, Ident}\nimport hkmc2.semantics.AnySelTerm\n\n\ncase class Constraint(lhs: Producer, rhs: Consumer):\n  def showDbg(using DebugPrinter): Str =\n    s\"${lhs.showDbg} <: ${rhs.showDbg}\"\n\n\nenum Producer:\n  case Flow(sym: FlowSymbol)\n  case Fun(lhs: Consumer, rhs: Producer, captures: Ls[(Producer, Consumer)])\n  case Tup(elems: Ls[Opt[SpreadKind] -> Producer])\n  case Ctor(sym: CtorSymbol, args: List[Producer])(val trm: Term) extends Producer, CtorImpl\n  case LeadingDotSel(trm: Term.LeadingDotSel)\n  case Typ(typ: Type)\n  case Unknown(s: Statement) // `s` is just for error reporting/debugging purposes\n  \n  \n  def toLoc: Opt[Loc] = this match\n    case self: Ctor => self.trm.toLoc\n    case self: LeadingDotSel => self.trm.toLoc\n    case Unknown(t) => t.toLoc\n    case _ => None\n  \n  \n  def show(using Scope, Raise): Document = this match\n    case Flow(sym) => scope.allocateOrGetName(sym)\n    case Fun(lhs, rhs, caps) => doc\"(${lhs.showAsParams} -> ${rhs.show})\"\n    case tup: Tup => Document.bracketed(\"[\", \"]\")(showTupElems(tup))\n    case Ctor(LitSymbol(UnitLit(false)), Nil) => \"()\"\n    case Ctor(sym, args) => doc\"${sym.nme}${args.map(_.showAsParams).mkDocument()}\"\n    case LeadingDotSel(trm) =>\n      given ShowCfg = ShowCfg.internal\n      doc\"_?_.${trm.show}\"\n    case Typ(typ) => doc\"type ${typ.show}\"\n    case Unknown(t) =>\n      given ShowCfg = ShowCfg.internal\n      doc\"¿${t.show}?\"\n  \n  def showAsParams(using Scope, Raise): Document = this match\n    case tup: Tup => \"(\" :: showTupElems(tup) :: doc\")\"\n    case _ => Document.text(s\"...$show\")\n  \n  private def showTupElems(tup: Tup)(using Scope, Raise): Document =\n    tup.elems.map:\n      case (None, c) => c.show\n      case (Some(spd), c) => spd.str :: \" \" :: c.show\n    .mkDocument(\", \")\n  \n  \n  def showDbg(using DebugPrinter): Str = this match\n    case Flow(sym) => sym.showDbg\n    case Fun(lhs, rhs, caps) => s\"(${lhs.showDbgAsParams} -> ${rhs.showDbg})\"\n    case Ctor(LitSymbol(UnitLit(false)), Nil) => \"()\"\n    case Ctor(sym, Nil) => sym.nme\n    case Tup(args) => s\"[${args.map((spd, a) => spd.fold(\"\")(_.str) + a.showDbg).mkString(\", \")}]\"\n    case Ctor(sym, args) => s\"${sym.nme}${args.map(_.showDbgAsParams).mkString}\"\n    case sel @ LeadingDotSel(trm) => trm.showDbg\n    case Typ(typ) => s\"type ${typ.showDbg}\"\n    case Unknown(t) => s\"¿${t.showDbg}?\"\n  \n  def showDbgAsParams(using DebugPrinter): Str = this match\n    case Tup(args) => args.map:\n        case (None, c) => c.showDbg\n        case (Some(spd), c) => s\"${spd.str} ${c.showDbg}\"\n      .mkString(\"(\", \", \", \")\")\n    case _ => s\"(...$showDbg)\"\n  \n  \nend Producer\n\n\nenum Consumer:\n  case Flow(sym: FlowSymbol)\n  case Fun(lhs: Producer, rhs: Consumer)\n  case Tup(init: Ls[Consumer], rest: Opt[(SpreadKind, Consumer, Ls[Consumer])])\n  case Ctor(sym: CtorSymbol, args: List[Consumer])\n  case Sel(nme: Ident, res: Consumer)(val trm: AnySelTerm)\n  case Typ(typ: Type)\n  \n  \n  def show(using Scope, Raise): Document = this match\n    case Flow(sym) => scope.allocateOrGetName(sym)\n    case Fun(lhs, rhs) => doc\"(${lhs.showAsParams} -> ${rhs.show})\"\n    case tup: Tup => Document.bracketed(\"[\", \"]\")(showTupElems(tup))\n    case Ctor(sym, args) => doc\"${sym.nme}${args.map(_.showAsParams).mkDocument()}\"\n    case Sel(nme, res) => doc\"{${nme.name}: ${res.show}}\"\n    case Typ(typ) => doc\"type ${typ.show}\"\n  \n  def showAsParams(using Scope, Raise): Document = this match\n    case tup: Tup => \"(\" :: showTupElems(tup) :: doc\")\"\n    case _ => doc\"(...$show)\"\n  \n  private def showTupElems(tup: Tup)(using Scope, Raise): Document = (\n      tup.init.iterator.map(_.show) ++ tup.rest.iterator.flatMap:\n        case (spd, c, post) =>\n          (spd.str :: c.show) :: post.map(_.show)\n    ).toSeq.mkDocument(\", \")\n  \n  \n  def showDbg(using DebugPrinter): Str = this match\n    case Flow(sym) => sym.showDbg\n    case Fun(lhs, rhs) => s\"(${lhs.showDbgAsParams} -> ${rhs.showDbg})\"\n    case Ctor(sym, Nil) => sym.nme\n    case tup: Tup => \"[\" + showDbgTupElems(tup) + \"]\"\n    case Ctor(sym, args) => s\"${sym.nme}(${args.map(_.showDbg).mkString(\", \")})\"\n    case Sel(id, res) => s\"{${id.name}: ${res.showDbg}}\"\n    case Typ(typ) => s\"type ${typ.showDbg}\"\n  \n  private def showDbgTupElems(tup: Tup)(using DebugPrinter): Str = (\n      tup.init.iterator.map(_.showDbg) ++ tup.rest.iterator.flatMap:\n        case (spd, c, post) =>\n          s\"${spd.str}${c.showDbg}\" :: post.map(_.showDbg)\n    ).mkString(\", \")\n  \n  def showDbgAsParams(using DebugPrinter): Str = this match\n    case tup: Tup => \"(\" + showDbgTupElems(tup) + \")\"\n    case _ => s\"(...$showDbg)\"\n  \n  \nend Consumer\n\n\ntrait CtorImpl:\n  self: Producer.Ctor =>\n    \nend CtorImpl\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/flow/FlowAnalysis.scala",
    "content": "package hkmc2\npackage semantics\npackage flow\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport utils.TraceLogger\nimport Message.MessageContext\nimport semantics.*, semantics.Term.*, semantics.AnySelTerm\nimport typing.*\n\nimport syntax.SpreadKind\nimport syntax.Tree\nimport Elaborator.{State, Ctx, ctx}\nimport Producer as P\nimport Consumer as C\n\n\n\ntype FlowPoint = FlowSymbol | VarSymbol\n\ntype Path = Vector[FlowPoint]\n\ntype ProdCtor = Producer.Ctor | Producer.Fun | Producer.Typ | Producer.Tup | Producer.LeadingDotSel\n\ncase class ConcreteProd(path: Path, ctor: ProdCtor)\n\n\nenum SelectionTarget:\n  case ObjectMember(sym: MemberSymbol)\n  case CompanionMember(comp: Term, sym: MemberSymbol)\n\n\n/** This is a very sketchy exploration/proof of concept of flow analysis\n  * that can be used to help compile programs in a type-directed way without having to perform full type inference. */\nclass FlowAnalysis(using tl: TraceLogger)(using Raise, State, Ctx):\n  import tl.*\n  \n  val MAX_FUEL = 1000\n  \n  def typeBody(b: ObjBody): Unit =\n    typeProd(b.blk)\n  \n  def typeProd(t: Term, insideSelAppChain: Boolean = false): Producer =\n    typeProdImpl(t.expanded, insideSelAppChain)\n  \n  def typeProdImpl(t: Term, insideSelAppChain: Boolean): Producer =\n  trace[P](s\"Typing producer: ${t.showDbg}\", post = res => s\": ${res.showDbg}\"):\n    \n    def constrain(lhs: P, rhs: C): Unit = collectedConstraints += ((src = t, c = Constraint(lhs, rhs)))\n    \n    def checkLDS(sub: Term)(res: Producer => Producer): Producer =\n      t.ldsRoot match\n      case S(lds) if !insideSelAppChain =>\n        val sym = FlowSymbol(\"bind\")\n        log(s\"Constraining leading dot selection ${lds.showDbg} at the top level\")\n        constrain(P.LeadingDotSel(lds), C.Flow(sym))\n        constrain(res(typeProd(sub, insideSelAppChain = true)), C.Flow(sym))\n        P.Flow(sym)\n      case _ => res(typeProd(sub, insideSelAppChain = insideSelAppChain))\n    \n    t match\n    \n    case Resolved(trm, sym) =>\n      val _ = typeProd(trm) // * Discard the base producer because it's already resolved and `sym` is the real one\n      sym match\n      case cls: ClassSymbol => P.Ctor(cls, Nil)(t)\n      case cls: ModuleOrObjectSymbol => P.Ctor(cls, Nil)(t)\n      case ts: TermSymbol => getFlowSymOrType(ts.bms.get)\n      \n    case Ref(sym) =>\n      sym match\n      case sym: VarSymbol => P.Flow(sym)\n      case cls: ClassSymbol => P.Ctor(cls, Nil)(t)\n      case cls: ModuleOrObjectSymbol => P.Ctor(cls, Nil)(t)\n      case ts: TermSymbol => die\n      case bs: BuiltinSymbol =>\n        bs.signature\n      case bms: BlockMemberSymbol =>\n        if bms.asTrm.isEmpty then raise:\n          ErrorReport:\n            msg\"Cannot use non-term member ${bms.nme} in term position\" -> t.toLoc :: Nil\n        getFlowSymOrType(bms)\n      case _: Symbol =>\n        log(s\"/!\\\\ Unhandled symbol type: ${sym} (${sym.getClass.getSimpleName}) /!\\\\\")\n        P.Unknown(t)\n        \n    case Blk(stats, res) =>\n      stats.foreach:\n        case stmt: LetDecl => ()\n        case stmt: DefineVar =>\n          val rhs = typeProd(stmt.rhs)\n          stmt.sym match\n          case sym: FlowSymbol =>\n            constrain(rhs, C.Flow(sym))\n        case t: TermDefinition =>\n          val sign_ty = t.sign.map(typeType(_)) // TODO use sign_ty\n          val ps = t.params.map(typeParamList)\n          t.body.foreach: bod =>\n            val bod_ty = typeProd(bod)\n            val fun_ty = ps.foldRight(bod_ty): (pl, acc) =>\n              P.Fun(C.Tup(pl, N), acc, Nil)\n            constrain(fun_ty, C.Flow(t.sym.flow))\n        case t: Term =>\n          typeProd(t)\n          \n        case cd: ClassDef =>\n          \n          typeBody(cd.body)\n          \n          val prod = cd.paramsOpt match\n            case S(ps) =>\n              ps.restParam match\n              case S(_) => ???\n              case N =>\n                P.Fun(\n                  C.Tup(ps.params.map(typeParam), N),\n                  P.Ctor(cd.sym, Nil // FIXME: Nil\n                    )(\n                      Term.Missing // FIXME\n                    ),\n                  Nil,\n                )\n            case N => P.Unknown(cd)\n          \n          log(s\"Class member type: ${prod.showDbg}\")\n          \n          constrain(prod, C.Flow(cd.bsym.flow))\n          \n        case md: ModuleOrObjectDef =>\n          // TODO\n          log(s\"Module: ${md.path}\")\n          typeBody(md.body)\n          \n        case _: Import =>\n          // TODO?\n\n        case stt =>\n          log(s\"/!\\\\ Unhandled statement: ${stt} /!\\\\\")\n          P.Unknown(stt)\n          \n      typeProd(res)\n    \n    case Lit(lit) =>\n      P.Ctor(LitSymbol(lit), Nil)(t)\n\n    case sel @ LeadingDotSel(nme) =>\n      leadingDotSelsToExpand += sel\n      log(s\"Leading dot selection ${sel.showDbg}\")\n      val sym = sel.resSym\n      constrain(P.LeadingDotSel(sel), C.Flow(sym))\n      P.Flow(sym)\n    \n    case sel @ AnySel(pre, nme, cls) =>\n      log(s\"Selection ${sel.showDbg} ${sel.typ}\")\n      checkLDS(pre): pre_t =>\n        sel.resolvedSym match\n        case S(sym: BlockMemberSymbol) =>\n          log(s\"RES ${sym.nme} in ${sel.showDbg}\")\n          getFlowSymOrType(sym)\n        case S(sym) =>\n          selsToExpand += sel\n          log(s\"Unhandled symbol reference ${sym.nme} in ${sel.showDbg}\")\n          P.Unknown(sel)\n        case N =>\n          selsToExpand += sel\n          val sym = sel.resSym\n          constrain(pre_t, C.Sel(nme, C.Flow(sym))(sel))\n          P.Flow(sym)\n    \n    case nw @ New(cls, args, rft) =>\n      rft match\n      case N =>\n        cls.resolvedSym.flatMap(_.asCls) match\n        case N =>\n          log(s\"Unresolved or invalid class symbol in ${cls.showDbg}\")\n          P.Unknown(nw)\n        case S(sym) =>\n          sym match\n          case sym: ClassSymbol =>\n            val args_t = args.map(typeProd(_, insideSelAppChain = insideSelAppChain))\n            P.Ctor(sym, args_t)(t)\n    \n    case app @ App(lhs, rhs) =>\n      checkLDS(lhs): pre_t =>\n        val sym = app.resSym\n        val c = C.Fun(typeProd(rhs), C.Flow(sym))\n        constrain(pre_t, c)\n        P.Flow(sym)\n    \n    case Lam(pl, bod) =>\n      val ps = typeParamList(pl)\n      val pl_t = C.Tup(ps, N)\n      val bod_t = typeProd(bod)\n      P.Fun(pl_t, bod_t, Nil)\n    \n    case ft: FunTy =>\n      P.Typ(typeType(ft))\n    \n    case Tup(fields) =>\n      P.Tup(fields.map:\n        case f: Fld => N -> typeProd(f.term))\n    \n    case Error =>\n      P.Ctor(Extr(false), Nil)(t)\n    \n    // case _ => P.Flow(FlowSymbol(\"TODO\"))\n  \n  /* \n  def getType(t: Term): Type =\n    t.resolvedTyp.getOrElse:\n      raise:\n        ErrorReport:\n          msg\"Cannot use this ${t.describe} as a type, as it could not be resolved\" -> t.toLoc :: Nil\n      Type.Error\n  */\n  \n  def typeParam(p: Param): C =\n  trace[C](s\"Typing param: ${p.showDbg}\", post = res => s\": ${res.showDbg}\"):\n    p.signType match\n    case S(typ) =>\n      p.flow.producers += ConcreteProd(Vector.empty, P.Typ(typ))\n      C.Typ(typ)\n    case N =>\n      C.Flow(p.flow)\n  \n  def typeParamList(ps: ParamList): Ls[C] =\n    if ps.restParam.nonEmpty then\n      ??? // TODO\n    ps.params.map(typeParam)\n  \n  def typeType(t: Term): Type =\n  trace[Type](s\"Typing consumer: ${t.showDbg}\", post = res => s\": ${res.showDbg}\"):\n    t match\n    case Ref(sym: VarSymbol) => Type.Ref(sym, Nil) // unparameterized type variable\n    case Ref(cls: ClassSymbol) => Type.Ref(cls, Nil)\n    case Ref(ts: BlockMemberSymbol) =>\n      Type.Ref(ts.asTpe.getOrElse(TODO(t)), Nil)\n    case Tup(fields) =>\n      Type.Tup:\n        fields.map:\n          case f: Fld => typeType(f.term)\n          case Spd(eager, term) => (???, typeType(term))\n    case FunTy(lhs, rhs, _) =>\n      Type.Fun(typeType(lhs), typeType(rhs), N)\n    case _ => TODO(t)\n  \n  val collectedConstraints: mutable.Stack[(src: Term, c: Constraint)] = mutable.Stack.empty\n  \n  val selsToExpand: mutable.Buffer[AnySelTerm] = mutable.Buffer.empty\n  val leadingDotSelsToExpand: mutable.Buffer[LeadingDotSel] = mutable.Buffer.empty\n  \n  def expandTerms() =\n    import SelectionTarget.*\n    selsToExpand.foreach: sel =>\n      log(s\"Resolved targets for ${sel.showDbg}: ${sel.resolvedTargets.mkString(\", \")}\")\n      assert(sel.expansion.isEmpty)\n      sel.resolvedTargets match\n        case ObjectMember(sym) :: Nil =>\n          assert(sel.sym.isEmpty)\n          sel.expansion = S(S(sel.withSym(sym)))\n        case CompanionMember(comp, sym) :: Nil =>\n          val base = Sel(comp, Tree.Ident(sym.nme))(S(sym), FlowSymbol.sel(sym.nme), N, N)\n          val app = App(base, Tup(sel.prefix :: Nil)(Tree.DummyTup))(Tree.DummyApp, N, FlowSymbol.app())\n          log(s\"Expansion: ${app.showDbg}\")\n          sel.expansion = S(S(app))\n        case Nil =>\n          // FIXME: actually allow that in dead code (use floodfill constraints from exported members to detect)\n          if !sel.isErroneous then raise:\n            ErrorReport:\n              msg\"Cannot resolve selection\" -> sel.toLoc :: Nil\n          // * An error should alsoready be reported in this case\n        case targets => raise:\n          ErrorReport:\n            msg\"Ambiguous selection with multiple apparent targets\" -> sel.toLoc\n            :: targets.map:\n              case ObjectMember(sym) => msg\"object member ${sym.nme}\" -> sym.toLoc\n              case CompanionMember(_, sym) => msg\"companion member ${sym.nme}\" -> sym.toLoc\n    leadingDotSelsToExpand.foreach: sel =>\n      log(s\"Resolved targets for ${sel.showDbg}: ${sel.resolvedTargets.mkString(\", \")}\")\n      assert(sel.expansion.isEmpty)\n      sel.resolvedTargets match\n      case CompanionMember(comp, sym) :: Nil =>\n        val base = Sel(comp, Tree.Ident(sym.nme))(S(sym), FlowSymbol.sel(sym.nme), N, N)\n        log(s\"Leading dot expansion: ${base.showDbg}\")\n        sel.expansion = S(S(base))\n      case Nil =>\n        // FIXME: actually allow that in dead code (use floodfill constraints from exported members to detect)\n        sel.expansion = S(S(Error))\n        raise:\n          ErrorReport:\n            msg\"Cannot resolve leading dot selection\" -> sel.toLoc :: Nil\n      case targets => sel.expansion = S(S(Error)); raise:\n        ErrorReport:\n          msg\"Ambiguous selection with multiple apparent targets:\" -> sel.toLoc\n          :: targets.map:\n            case CompanionMember(_, sym) => msg\"companion member ${sym.nme}\" -> sym.toLoc\n\n  def getCompanionMember(name: Str, oc: Opt[SrcScope], sym: Symbol): Opt[(Term, BlockMemberSymbol)] = sym match\n    case ms: ModuleOrObjectSymbol => ms.defn.flatMap: d =>\n      d.body.members.get(name) match\n      case S(memb: BlockMemberSymbol) =>\n        oc\n        .flatMap(findAccessPath(_, d.path, ms))\n        .map((_, memb))\n      case _ => N\n    case cs: ClassSymbol =>\n      cs.defn\n      .flatMap(_.moduleCompanion)\n      .flatMap(x => x.defn.map((x, _)))\n      .flatMap: (comp, d) =>\n        d.body.members.get(name) match\n        case S(memb: BlockMemberSymbol) =>\n          oc\n          .flatMap(findAccessPath(_, d.path, comp))\n          .map((_, memb))\n        case _ => N\n    case _ => N\n  \n  \n  // * This is a rather hacky way to check whether we're looking at a BMS from the same compilation unit/file,\n  // * in which case we should get access to its internal flow symbol, or whether it's from another file,\n  // * in which case we shouldn't, as flow analysis is supposed to be local\n  // * (if not, we'd notably get race conditions and inconsistencies in compilation).\n  // * ASSUMPTION: This relies on the fact that each file is always elaborated in a distinct State instance.\n  def getFlowSymOrType(bms: BlockMemberSymbol): P =\n    if bms.getState is summon[State]\n    then P.Flow(bms.flow)\n    else P.Typ(Type.Top) // TODO: should get a frozen inferred type view of the internally inferred flow\n  \n  \n  def solveConstraints(): Unit =\n    \n    var fuel = MAX_FUEL\n    val toSolve: mutable.Stack[Constraint] = mutable.Stack.empty\n    val inCache: mutable.Set[FlowSymbol -> C] = mutable.Set.empty\n    val outCache: mutable.Set[P -> FlowSymbol] = mutable.Set.empty\n    \n    while fuel > 0 && collectedConstraints.nonEmpty\n    do\n      val (trm, cc) = collectedConstraints.pop()\n      toSolve.push(cc)\n      \n      trace(s\"Handling constraint: ${cc.showDbg} (from ${trm.showDbg})\"):\n        \n        while fuel > 0 && toSolve.nonEmpty\n        do\n          fuel -= 1\n          val c = toSolve.pop()\n          \n          def dig(lhs: P, rhs: C, path: Path): Unit =\n            \n            log(s\"Solving: ${lhs.showDbg} <: ${rhs.showDbg}   (${lhs.getClass.getSimpleName}, ${rhs.getClass.getSimpleName})\")\n            \n            (lhs, rhs) match\n            case (P.Flow(sym), rhs)\n            if inCache.contains(sym -> rhs)\n              => log(s\"In (in) cache!\")\n            case (lhs, C.Flow(sym))\n            if outCache.contains(lhs -> sym)\n              => log(s\"In (out) cache!\")\n            case (P.Flow(sym), C.Flow(sym2)) =>\n              log(s\"New flow $sym ~> $sym2\")\n              sym.outFlows += sym2\n              sym.producers.foreach(cp =>\n                dig(cp.ctor, rhs, cp.path ++ path))\n            case (lhs: ProdCtor, C.Flow(sym)) =>\n              log(s\"New flow $lhs ~> $sym\")\n              sym.producers += ConcreteProd(path, lhs)\n              sym.consumers.foreach: c =>\n                dig(lhs, c, path)\n            case (P.Flow(sym), rhs) =>\n              log(s\"New flow $sym ~> $rhs\")\n              sym.consumers += rhs\n              sym.producers.foreach: cp =>\n                dig(cp.ctor, rhs, cp.path ++ path)\n              sym.outFlows.foreach: fs =>\n                dig(P.Flow(fs), rhs, fs +: path)\n            case (P.Fun(pl, pr, _), C.Fun(cl, cr)) =>\n              dig(cl, pl, path) // FIXME path\n              dig(pr, cr, path) // FIXME path\n            case (P.Ctor(sym1, args1), C.Ctor(sym2, args2))\n            if (sym1 is sym2) && args1.size === args2.size // TODO generalize\n              =>\n              args1.zip(args2).foreach: (a1, a2) =>\n                dig(a1, a2, path) // FIXME path\n            case (P.Tup(args), C.Tup(ini, rst)) =>\n              def zip(args: Ls[Opt[SpreadKind] -> P], cons: Ls[C], rst: Opt[(SpreadKind, C, Ls[C])], path: Path): Unit\n                    = (args, cons) match\n                case (Nil, Nil) => ()\n                case ((N, a1) :: args, c1 :: cons) =>\n                  dig(a1, c1, path) // FIXME path\n                  zip(args, cons, rst, path)\n                case ((S(spd), a1) :: args, Nil) =>\n                  ???\n                case ((N, a1) :: args, Nil) =>\n                  // extra producers can be matched by spread in consumer\n                  rst match\n                  case S((spd, a2, post)) => ???\n                  case N =>\n                    raise(ErrorReport(\n                      msg\"Tuple arity mismatch: too many elements on the producer side\" -> trm.toLoc :: Nil))\n              zip(args, ini, rst, path)\n            case (sel @ P.LeadingDotSel(trm), rhs) => rhs match\n              case C.Typ(Type.Ref(sym, _)) =>\n                log(s\"Examining ${sym} for leading dot selection resolution\")\n                getCompanionMember(trm.nme.name, trm.originalCtx, sym) match\n                case S((path, memb)) =>\n                  sel.trm.resolvedTargets ::= SelectionTarget.CompanionMember(path, memb)\n                  log(s\"Found member ${memb}\")\n                  toSolve.push(Constraint(getFlowSymOrType(memb), C.Flow(trm.resSym)))\n                case _ =>\n                  log(s\"Could not find member ${trm.nme.name} in ${sym}\")\n              case _ => log(\"Unhandled RHS for leading dot selections\")\n            case (lhs, sel: C.Sel) =>\n              lhs match\n              case P.Typ(Type.Ref(sym: ClassSymbol, targs)) =>\n                if targs.nonEmpty then TODO(targs)\n                toSolve.push(Constraint(P.Ctor(sym, Nil)(Term.Missing), sel))\n              case P.Ctor(sym: ClassSymbol, args) =>\n                val d = sym.defn.getOrElse(die)\n                d.body.members.get(sel.nme.name) match\n                case S(memb: BlockMemberSymbol) =>\n                  sel.trm.resolvedTargets ::= SelectionTarget.ObjectMember(memb)\n                  log(s\"Found immediate member ${memb}\")\n                  toSolve.push(Constraint(getFlowSymOrType(memb), sel.res))\n                case S(memb) => TODO(memb)\n                case N =>\n                  d.moduleCompanion match\n                  case S(comp) =>\n                    val cd = comp.defn.getOrElse(die)\n                    cd.body.members.get(sel.nme.name) match\n                    case S(memb) =>\n                      log(s\"Found companion member ${memb}\")\n                      sel.trm.originalCtx match\n                      case S(oc) =>\n                        val patho = findAccessPath(oc, cd.path, comp)\n                        log(s\"Access path: ${patho}\")\n                        patho match\n                        case S(path) =>\n                          sel.trm.resolvedTargets ::= SelectionTarget.CompanionMember(path, memb)\n                          val newlhs = memb match\n                            case memb: BlockMemberSymbol => getFlowSymOrType(memb)\n                            case _ => TODO(memb)\n                          toSolve.push(Constraint(newlhs, C.Fun(P.Tup((N, lhs) :: Nil), sel.res)))\n                        case N => raise:\n                          sel.trm.isErroneous = true\n                          ErrorReport:\n                            msg\"Cannot access companion ${comp.name} from the context of this selection\" -> sel.trm.toLoc\n                            :: Nil\n                      case N => ???\n                    case N => ???\n                  case N => raise:\n                    sel.trm.isErroneous = true\n                    ErrorReport(\n                      // TODO construct proper error message\n                      msg\"Field ${sel.nme.name} is not a member of ${d.kind.desc} ${d.sym.name}\" -> trm.toLoc :: Nil)\n              case _ => raise:\n                sel.trm.isErroneous = true\n                ErrorReport(\n                  // TODO construct proper error message\n                  msg\"Unresolved selection:\" -> sel.trm.toLoc\n                  :: msg\"Type `${lhs.showDbg}` does not contain member '${sel.nme.name}'\" -> lhs.toLoc\n                  :: Nil)\n            case _ =>\n              log(s\"/!\\\\ Unhandled constraint /!\\\\\")\n          end dig\n          \n          dig(c.lhs, c.rhs, Vector.empty)\n          \n        if fuel === 0 then\n          raise(ErrorReport(\n            msg\"Could not solve all constraints within $MAX_FUEL iterations.\" -> N :: Nil))\n  \n  def findAccessPath(src: SrcScope, dst: SrcScope, moduleSym: ModuleOrObjectSymbol): Opt[Term] =\n    log(s\"outermostAcessibleBase ${dst.outermostAcessibleBase}\")\n    val (outermostBase, outermostPath) = dst.outermostAcessibleBase\n    var cur = src\n    while cur isnt outermostBase do\n      cur.parent match\n      case N =>\n        return N\n      case S(p) =>\n        cur = p\n    assert(cur is outermostBase)\n    (moduleSym :: outermostPath).reverse match\n    case Nil => die\n    case sym :: syms => S:\n      syms.foldLeft(sym.asInstanceOf[DefinitionSymbol[?]]//FIXME\n        .bms.getOrElse(die).ref(): Term): (a, b) =>\n        Sel(a, Tree.Ident(b.nme))(S(b.asInstanceOf[DefinitionSymbol[?]]//FIXME\n          .bms.getOrElse(die)), FlowSymbol.sel(b.nme), N, N)\n  \n  \n  import hkmc2.document.*\n  import utils.Scope\n  \n  def showFlows(using Scope, ShowCfg): Document =\n    val syms = summon[ShowCfg].shownSymbols.toIndexedSeq.sortBy(_.uid)\n    doc\" #{  # ${\n      syms.collect:\n        case sym: FlowSymbol =>\n          (\n            if sym.producers.isEmpty then Nil else doc\"${sym.showName}  <~  ${\n              sym.producers.toSeq.map(_.ctor.show).mkDocument(doc\"  \")}\" :: Nil\n          ) ::: (\n            if sym.consumers.isEmpty then Nil else doc\"${sym.showName}  ~>  ${\n                sym.consumers.toSeq.map(_.show).mkDocument(doc\"  \")}\" :: Nil\n          ) ::: (\n            if sym.outFlows.isEmpty then Nil else doc\"${sym.showName}  ->  ${\n                sym.outFlows.toSeq.map(_.showName).mkDocument(doc\"  \")}\" :: Nil\n          ) ::: Nil\n      .flatten.mkDocument(doc\" # \")\n    } #} \"\n  \nend FlowAnalysis\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/FlatPattern.scala",
    "content": "package hkmc2\npackage semantics\npackage ucs\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.*, Tree.Ident, Elaborator.State\n\n/**\n  * Flattened patterns used in splits for `Normalization` and `Lowering`. All\n  * cases of patterns declared hereby can be matched in constant time.\n  * Non-trivial patterns (e.g., unions, intersections,\n  * transformations, etc) have been compiled to `Split`.\n  */\nenum FlatPattern extends AutoLocated:\n  case Lit(literal: Literal)\n  \n  /**\n    * To match against a class or an object.\n    *\n    * @param constructor The term representing the class or the object.\n    * @param symbol The symbol resolved from `constructor`.\n    * @param arguments The sub-scrutinees and their locations. This field is\n    *        `None` when no argument list is provided, i.e., `x is Some`.\n    * @param refined Whether the type of the scrutinee can be further refined by\n    *        other patterns in nested splits. It is not used currently.\n    * @param tree The tree which this pattern is elaborated from. This is only\n    *        used for error reporting and should not be copied in `mkClone`.\n    */\n  case ClassLike(\n      val constructor: Term,\n      val symbol: ClassSymbol | ModuleOrObjectSymbol,\n      val arguments: Opt[Ls[(BlockLocalSymbol, Opt[Loc])]],\n      var refined: Bool\n  )(val tree: Tree)\n  \n  case Tuple(size: Int, inf: Bool)\n  \n  case Record(entries: List[(Ident -> BlockLocalSymbol)])\n  \n  def mkClone(using State): FlatPattern = this match\n    case Lit(literal) => Lit(literal)\n    case pattern @ ClassLike(constructor, symbol, arguments, refined) =>\n      ClassLike(constructor.mkClone, symbol, arguments, refined)(Tree.Dummy)\n    case Tuple(size, inf) => Tuple(size, inf)\n    case Record(entries) => Record(entries)\n  \n  def subTerms: Vector[Term] = this match\n    case p: ClassLike => Vector(p.constructor)\n    case _: (Lit | Tuple | Record) => Vector.empty\n  \n  def children: Vector[Located] = this match\n    case Lit(literal) => Vector(literal)\n    case ClassLike(ctor, symbol, scruts, _) => Vector(ctor) ++ scruts.fold(Vector.empty)(_.map(_._1))\n    case Tuple(fields, _) => Vector.empty\n    case Record(entries) =>\n      entries.iterator.flatMap:\n        case (nme, als) => Vector(nme, als)\n      .toVector\n  \n  def showDbg(using DebugPrinter): Str =\n    (this match\n    case Lit(literal) => literal.idStr\n    case ClassLike(ctor, symbol, args, rfd) =>\n      def showCtor(ctor: Term): Str = ctor match\n        // This prints the symbol name without `refNum` and \"member:\" prefix.\n        case Term.Ref(sym: BlockMemberSymbol) => sym.nme\n        // This prints the symbol without `refNum`.\n        case Term.Ref(sym) => sym.toString\n        case Term.Sel(p, i) => s\"${showCtor(p)}.${i.name}\"\n        case Term.SynthSel(p, i) => s\"${showCtor(p)}.${i.name}\"\n        case _ => ctor.showDbg\n      (if rfd then \"refined \" else \"\") + showCtor(ctor) +\n        args.fold(\"\")(_.iterator.map(_._1.nme).mkString(\"(\", \", \", \")\"))\n    case Tuple(size, inf) => \"[]\" + (if inf then \">=\" else \"=\") + size\n    case Record(Nil) => \"{}\"\n    case Record(entries) =>\n      entries.iterator.map(_.name + \": \" + _).mkString(\"{ \", \", \", \" }\"))\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/Normalization.scala",
    "content": "package hkmc2\npackage semantics\npackage ucs\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.{Literal, Tree, Keyword}, utils.*\nimport Message.MessageContext\nimport Elaborator.{Ctx, State, ctx}\nimport codegen.Lowering\nimport collection.mutable.{Map as MutMap}\n\n\nclass Normalization(lowering: Lowering)(using tl: TL)(using Raise, Ctx, State) extends TermSynthesizer:\n  import Normalization.*, Mode.*\n  import tl.*\n\n  def reportUnreachableCase[T <: Located](unreachable: Located, subsumedBy: T, when: Bool = true): T =\n    if when then warn(\n      msg\"this case is unreachable\" -> unreachable.toLoc,\n      msg\"because it is subsumed by the branch\" -> subsumedBy.toLoc)\n    subsumedBy\n\n  extension (these: Split)\n    def markAsFallback: Split =\n      these.isFallback = true\n      these\n\n    def clearFallback: Split =\n      these.isFallback = false\n      these\n\n    def ++(those: Split): Split =\n      if these.isFull then\n        log(\"tail is discarded\")\n        these\n      else (these match\n        case Split.Cons(head, tail) => Split.Cons(head, tail ++ those)\n        case Split.Let(name, term, tail) => Split.Let(name, term, tail ++ those)\n        case Split.Else(_) /* impossible */ | Split.End => those)\n  \n  extension (lhs: FlatPattern)\n    /** Checks if two patterns are the same. */\n    def =:=(rhs: FlatPattern): Bool = (lhs, rhs) match\n      case (lhs: FlatPattern.ClassLike, rhs: FlatPattern.ClassLike) =>\n        lhs.constructor.symbol === rhs.constructor.symbol\n      case (FlatPattern.Lit(l1), FlatPattern.Lit(l2)) => l1 === l2\n      case (FlatPattern.Tuple(n1, b1), FlatPattern.Tuple(n2, b2)) => n1 === n2 && b1 === b2\n      case (FlatPattern.Record(ls1), FlatPattern.Record(ls2)) =>\n        ls1.lazyZip(ls2).forall:\n          case ((fieldName1, p1), (fieldName2, p2)) =>\n            fieldName1 === fieldName2 && p1 === p2\n      case (_: FlatPattern.ClassLike, _) | (_: FlatPattern.Lit, _) |\n        (_: FlatPattern.Tuple, _) | (_: FlatPattern.Record, _) => false\n    /** Checks if `lhs` can be subsumed under `rhs`. */\n    def <:<(rhs: FlatPattern): Bool = compareCasePattern(lhs, rhs)\n    /** If the pattern is a class-like pattern, override its `refined` flag. */\n    def markAsRefined: Unit = lhs match\n      case lhs: FlatPattern.ClassLike => lhs.refined = true\n      case _ => ()\n  \n  extension (lhs: FlatPattern.Record)\n    /** reduces the record pattern `lhs` assuming we have matched `rhs`.\n      * It removes field matches that may now be unnecessary\n      */\n    infix def assuming(rhs: FlatPattern): FlatPattern.Record = rhs match\n      case FlatPattern.Record(rhsEntries) =>\n        val filteredEntries = lhs.entries.filter:\n          (fieldName1, _) => rhsEntries.forall { (fieldName2, _) => !(fieldName1 === fieldName2)}\n        FlatPattern.Record(filteredEntries)\n      case rhs: FlatPattern.ClassLike => rhs.constructor.symbol.flatMap(_.asCls) match\n        case S(cls: ClassSymbol) => cls.defn match\n          case S(ClassDef.Parameterized(params = paramList)) =>\n            val filteredEntries = lhs.entries.filter:\n              (fieldName1, _) => paramList.params.forall { (param:Param) => !(fieldName1 === param.sym.id)}\n            FlatPattern.Record(filteredEntries)\n          case S(_) | N => lhs\n        case S(_) | N => lhs\n      case _ => lhs\n\n  inline def apply(split: Split): Split = normalize(split)(using VarSet())\n  \n  /**\n    * Normalize core abstract syntax to MLscript syntax.\n    *\n    * @param split the split to normalize\n    * @return the normalized term\n    */ \n  private def normalize(split: Split)(using vs: VarSet): Split = trace(\n    pre = s\"normalize <<< ${split.prettyPrint}\",\n    post = (res: Split) => \"normalize >>> \" + res.prettyPrint,\n  ):\n    normalizeImpl(split)\n  \n  def normalizeImpl(split: Split)(using vs: VarSet): Split = split match\n    case Split.Cons(Branch(scrutinee, pattern, consequent), alternative) =>\n      log(s\"MATCH: ${scrutinee.showDbg} is ${pattern.showDbg}\")\n      val whenTrue = normalize(specialize(consequent ++ alternative.duplicate, +, scrutinee, pattern))\n      val whenFalse = normalizeImpl(specialize(alternative, -, scrutinee, pattern).clearFallback)\n      Branch(scrutinee, pattern, whenTrue) ~: whenFalse\n    case Split.Let(v, _, tail) if vs has v =>\n      log(s\"LET: SKIP already declared scrutinee $v\")\n      normalizeImpl(tail)\n    case Split.Let(v, rhs, tail) =>\n      log(s\"LET: $v\")\n      Split.Let(v, rhs, normalizeImpl(tail)(using vs + v))\n    case split @ Split.Else(default) =>\n      log(s\"DFLT: ${default.showDbg}\")\n      split\n    case Split.End => Split.End\n  \n  /**\n    * Specialize `split` with the assumption that `scrutinee` matches `pattern`.\n    *\n    * In mode `+` (positive), keeps branches consistent with the assumption:\n    *   - Case 1.1.1: Same pattern (`=:=`) → merge continuation and tail via alias bindings.\n    *   - Case 1.1.2: Branch pattern is more specific (`thatPattern <:< pattern`) → keep as-is,\n    *     mark the specializing pattern as refined, and recurse into the tail so remaining\n    *     branches on the same scrutinee are simplified with the known assumption.\n    *   - Case 1.1.3: Branch is a fallback → skip to tail.\n    *   - Case 1.1.4: Branch is a record → simplify fields already matched by the assumption.\n    *   - Case 1.1.5: Specializing pattern is more specific (`pattern <:< thatPattern`) → keep as-is\n    *     (the branch always matches when the assumption holds).\n    *   - Case 1.1.6: Patterns are unrelated — if provably disjoint (e.g., different literals,\n    *     sibling classes under single inheritance), skip; otherwise keep the branch to support\n    *     conjunction patterns like `A & B`.\n    *\n    * In mode `-` (negative), removes branches that the assumption makes unreachable:\n    *   - Case 1.2.1: Branch pattern equals or is subsumed by the assumption → remove.\n    *   - Case 1.2.2: Unrelated → keep, recurse into tail.\n    *\n    * Case 2: Different scrutinee → recurse into both continuation and tail.\n    */\n  private def specialize(\n      split: Split,\n      mode: Mode,\n      scrutinee: Term.Ref,\n      pattern: FlatPattern\n  )(using VarSet): Split = trace(\n    pre = s\"S$mode <<< ${scrutinee.showDbg} is ${pattern.showDbg} : ${split.prettyPrint}\",\n    post = (r: Split) => s\"S$mode >>> ${r.prettyPrint}\"\n  ):\n    def rec(split: Split)(using mode: Mode, vs: VarSet): Split = split match\n      case Split.End => log(\"CASE Nil\"); split\n      case Split.Else(_) => log(\"CASE Else\"); split\n      case split @ Split.Let(sym, _, tail) =>\n        log(s\"CASE Let ${sym}\")\n        split.copy(tail = rec(tail))\n      case split @ Split.Cons(head @ Branch(thatScrutinee, thatPattern, continuation), tail) =>\n        log(s\"CASE Cons ${head.showDbg}\")\n        if scrutinee === thatScrutinee then mode match\n          case + =>\n            log(s\"Case 1.1: $scrutinee === $thatScrutinee\")\n            if thatPattern =:= pattern then\n              log(s\"Case 1.1.1: $pattern =:= $thatPattern\")\n              aliasBindings(pattern, thatPattern)(rec(continuation) ++ rec(tail))\n            else if thatPattern <:< pattern then\n              log(s\"Case 1.1.2: $pattern <:< $thatPattern\")\n              pattern.markAsRefined; split.copy(tail = rec(tail))\n            else if split.isFallback then\n              log(s\"Case 1.1.3: $pattern is unrelated with $thatPattern\")\n              rec(tail)\n            else thatPattern match\n            case thatPattern: FlatPattern.Record =>\n              log(s\"Case 1.1.4: $thatPattern is a record\")\n              // we can use information if pattern is itself a record, or if it is a constructor with arguments\n              val simplifiedRecord = thatPattern assuming pattern\n              if simplifiedRecord.entries.isEmpty then\n                tail\n              else\n                Split.Cons(Branch(thatScrutinee, simplifiedRecord, continuation), tail)\n            case _ =>\n              if pattern <:< thatPattern then\n                // TODO: the warning will be useful when we have inheritance information\n                // raiseDesugaringWarning(\n                //   msg\"the pattern always matches\" -> thatPattern.toLoc,\n                //   msg\"the scrutinee was matched against ${pattern.toString}\" -> pattern.toLoc,\n                //   msg\"which is a subtype of ${thatPattern.toString}\" -> (pattern match {\n                //     case Pattern.Class(cls, _, _) => cls.toLoc\n                //     case _ => thatPattern.toLoc\n                //   }))\n                log(s\"case 1.1.5: $pattern <:< $thatPattern\")\n                split\n              else\n                if areProvablyDisjoint(pattern, thatPattern) then\n                  log(s\"Case 1.1.6: $pattern and $thatPattern are provably disjoint\")\n                  rec(tail)\n                else\n                  // When patterns are not provably disjoint, we cannot assume\n                  // the scrutinee can't match both (e.g., conjunction patterns\n                  // like `A & B`). Keep the branch.\n                  log(s\"Case 1.1.6: $pattern and $thatPattern are not provably disjoint\")\n                  head.copy(continuation = rec(continuation)) ~: rec(tail)\n          case - =>\n            log(s\"Case 1.2: $scrutinee === $thatScrutinee\")\n            if thatPattern =:= pattern || thatPattern <:< pattern then\n              log(s\"Case 1.2.1: $pattern =:= (or <:<) $thatPattern\")\n              rec(tail)\n            else\n              log(s\"Case 1.2.2: $pattern are unrelated to $thatPattern\")\n              split.copy(tail = rec(tail))\n        else\n          log(s\"Case 2: $scrutinee =/= $thatScrutinee\")\n          head.copy(continuation = rec(continuation)) ~: rec(tail)\n    end rec\n    rec(split)(using mode, summon)\n  \n  private def aliasBindings(p: FlatPattern, q: FlatPattern): Split => Split = (p, q) match\n    case (FlatPattern.ClassLike(_, _, S(ss1), _), FlatPattern.ClassLike(_, _, S(ss2), _)) =>\n      ss1.iterator.zip(ss2.iterator).foldLeft(identity[Split]):\n        case (acc, (l, r)) if l._1 === r._1 => acc\n        case (acc, (l, r)) => innermost => Split.Let(r._1, l._1.safeRef, acc(innermost))\n    case (_, _) => identity\n  \n  import codegen.*, lowering.{term_nonTail, subTerm_nonTail, unreachableFn}\n  \n  /** Collect terms that appear in multiple `Split.Else` branches. We will share\n   *  the corresponding blocks to avoid code duplication. */\n  private def createLabelsForDuplicatedBranches(split: Split)(using config: Config): Labels =\n    val counts: MutMap[Term, (order: Int, count: Int)] = MutMap.empty\n    var fallThroughCount = 0\n    def rec(s: Split): Unit = s match\n      case Split.End => fallThroughCount += 1\n      case Split.Else(els) => counts.updateWith(els):\n        case S((n, count)) => S((n, count + 1))\n        case N => S((counts.size + 1, 1))\n      case Split.Let(_, _, tail) => rec(tail)\n      case Split.Cons(Branch(_, _, cons), tail) => rec(cons); rec(tail)\n    rec(split)\n    val consequents = config.patMatConsequentSharingThreshold match\n      case S(threshold) =>\n        counts.iterator.filter(kv =>\n          kv._2.count > 1 && kv._2.count * kv._1.size > threshold).toSeq.sortBy(_._2.order).zipWithIndex.map:\n          case ((term, _), i) => (term, LabelSymbol(S(term), s\"split_${i + 1}$$\"))\n        .toList\n      case N => Nil\n    val matchError = if fallThroughCount > 1 then S(LabelSymbol(N, s\"split_default$$\")) else N\n    Labels(consequents, matchError)\n  \n  private def lowerSplit\n      (split: Split, cont: Result => Block)\n      (using labels: Labels, form: IfLikeForm)\n      (using LoweringCtx)\n      : Block = split match\n    case Split.Let(sym, trm, tl) =>\n      LoweringCtx.loweringCtx.collectScopedSym(sym)\n      term_nonTail(trm): r =>\n        Assign(sym, r, lowerSplit(tl, cont))\n    case Split.Cons(Branch(scrut, pat, tail), restSplit) =>\n      subTerm_nonTail(scrut): sr =>\n        tl.log(s\"Binding scrut $scrut to $sr (${summon[LoweringCtx].map})\") \n        def mkMatch(cse: Case -> Block) = Match(sr, cse :: Nil,\n            S(lowerSplit(restSplit, cont)),\n            End()\n          )\n        pat match\n          case FlatPattern.Lit(lit) => mkMatch(Case.Lit(lit) -> lowerSplit(tail, cont))\n          case FlatPattern.ClassLike(ctor, symbol, argsOpt, _refined) =>\n            for args <- argsOpt; (arg, _) <- args do LoweringCtx.loweringCtx.collectScopedSym(arg)\n            /** Make a continuation that creates the match. */\n            def k(ctorSym: ClassLikeSymbol, clsParams: Ls[TermSymbol])(st: Path): Block =\n              val args = argsOpt.map(_.map(_._1)).getOrElse(Nil)\n              // Normalization should reject cases where the user provides\n              // more sub-patterns than there are actual class parameters.\n              assert(argsOpt.isEmpty || args.length <= clsParams.length, (argsOpt, clsParams))\n              def mkArgs(args: Ls[TermSymbol -> BlockLocalSymbol])(using LoweringCtx): Case -> Block = args match\n                case Nil =>\n                  Case.Cls(ctorSym, st) -> lowerSplit(tail, cont)\n                case (param, arg) :: args =>\n                  val (cse, blk) = mkArgs(args)\n                  (cse, Assign(arg, Select(sr, new Tree.Ident(param.id.name).withLocOf(arg))(S(param)), blk))\n              mkMatch(mkArgs(clsParams.iterator.zip(args).toList))\n            symbol match\n              case cls: ClassSymbol if ctx.builtins.virtualClasses contains cls =>\n                // [invariant:0] Some classes (e.g., `Int`) from `Prelude` do\n                // not exist at runtime. If we do lowering on `trm`, backends\n                // (e.g., `JSBuilder`) will not be able to handle the corresponding selections.\n                // In this case the second parameter of `Case.Cls` will not be used.\n                // So we do not elaborate `ctor` when the `cls` is virtual\n                // and use it `Predef.unreachable` here.\n                k(cls, Nil)(unreachableFn)\n              case cls: ClassSymbol =>\n                subTerm_nonTail(ctor)(k(cls,\n                  cls.tree.clsParams.headOption.getOrElse(Nil) // FIXME? case when there are only aux parameter lists\n                  ))\n              case mod: ModuleOrObjectSymbol =>\n                subTerm_nonTail(ctor)(k(mod, Nil))\n          case FlatPattern.Tuple(len, inf) => mkMatch(Case.Tup(len, inf) -> lowerSplit(tail, cont))\n          case FlatPattern.Record(entries) =>\n            for (_, s) <- entries do LoweringCtx.loweringCtx.collectScopedSym(s)\n            val objectSym = ctx.builtins.Object\n            mkMatch( // checking that we have an object\n              Case.Cls(objectSym, Value.Ref(BuiltinSymbol(objectSym.nme, false, false, true, false))),\n              entries.foldRight(lowerSplit(tail, cont)):\n                case ((fieldName, fieldSymbol), blk) =>\n                  mkMatch(\n                    Case.Field(fieldName, safe = true), // we know we have an object, no need to check again\n                    Assign(fieldSymbol, Select(sr, fieldName)(N), blk)\n                  )\n            )\n    case Split.Else(els) => labels.get(els) match\n      case S(label) => Break(label)\n      case N => term_nonTail(els, inStmtPos = form.isImperative)(cont)\n    case Split.End =>\n      // * See comment [comment:1] above\n      if form is IfLikeForm.While then End()\n      else labels.matchError.fold(throwMatchErrorBlock)(Break(_))\n  \n  /**\n    * Make a block that throws the match error. We might add the information of\n    * match failure in the future.\n    */\n  private def throwMatchErrorBlock =\n    Throw(Instantiate(mut = false, Select(Value.Ref(State.globalThisSymbol), Tree.Ident(\"Error\"))(S(ctx.builtins.Error)),\n        (Value.Lit(syntax.Tree.StrLit(\"match error\")).asArg :: Nil) :: Nil)) // TODO add failed-match scrutinee info\n  \n  import syntax.Keyword.{`if`, `while`}\n  \n  def apply(t: Term.IfLike)(k: Result => Block)(using config: Config)(using LoweringCtx): Block =\n    val newSplit = t.split.getExpandedSplit\n    scoped(\"ucs:desugared\"):\n      log(s\"Split with nested patterns:\\n${t.split.prettyPrint(t.kw)}\")\n      log(s\"Expanded split with flattened patterns:\\n${newSplit.prettyPrint}\")\n    this(newSplit, t.form, S(t), k)\n  \n  def apply(t: Term.SynthIf)(k: Result => Block)(using Config, LoweringCtx): Block =\n    this(t.split, IfLikeForm.ReturningIf, S(t), k)\n  \n  def apply(split: Split)(k: Result => Block)(using Config, LoweringCtx): Block =\n    this(split, IfLikeForm.ReturningIf, N, k)\n  \n  private def apply(inputSplit: Split, form: IfLikeForm, t: Opt[Term], k: Result => Block)(using cfg: Config, outerCtx: LoweringCtx) =\n    // if it's `while`, we always make sure that loop bodies are proper nested scoped\n    // see https://github.com/hkust-taco/mlscript/pull/356#discussion_r2588412258\n    val useNestedScoped = form is IfLikeForm.While\n    (if useNestedScoped then LoweringCtx.nestScoped else outerCtx).givenIn:\n      var usesResTmp = false\n      // The symbol of the temporary variable for the result of the `if`-like term.\n      // It will be created in one of the following situations.\n      // 1. The continuation `k` is not a tail operation.\n      // 2. There are shared consequents in the `if`-like term.\n      // 3. The term is a `while` and the result is used.\n      lazy val l =\n        usesResTmp = true\n        val res = new TempSymbol(t)\n        outerCtx.collectScopedSym(res)\n        res\n      // The symbol for the loop label if the term is a `while`.\n      lazy val loopLabel = new LabelSymbol(t)\n      lazy val f =\n        val res = new BlockMemberSymbol(\"while\", Nil, false)\n        outerCtx.collectScopedSym(res)\n        res\n      lazy val tSym = TermSymbol.fromFunBms(f, N)\n      val normalized = tl.scoped(\"ucs:normalize\"):\n        normalize(inputSplit)(using VarSet())\n      tl.scoped(\"ucs:normalized\"):\n        tl.log(s\"Normalized:\\n${normalized.prettyPrint}\")\n      // Collect consequents that are shared in more than one branch.\n      given labels: Labels = createLabelsForDuplicatedBranches(normalized)\n      lazy val rootBreakLabel = new LabelSymbol(N, \"split_root$\")\n      lazy val breakRoot = if (k is Ret) || (k is Thrw) then k else (r: Result) => Assign(l, r, Break(rootBreakLabel))\n      lazy val assignResult = (r: Result) =>\n        form match\n        case IfLikeForm.ReturningIf => if (k is Ret) || (k is Thrw) then k(r) else Assign(l, r, End())\n        case IfLikeForm.ImperativeIf => Assign.discard(r, End())\n        case IfLikeForm.While => Assign(State.noSymbol, r, loopCont)\n      // NOTE: `shouldRewriteWhile` is not the same as `config.rewriteWhileLoops`\n      // as shouldRewriteWhile is always true when effect handler lowering is on\n      lazy val loopCont = if config.shouldRewriteWhile\n        then Return(Call(Value.Ref(f, S(tSym)), Nil ne_:: Nil)(true, true, false), false)\n        else Continue(loopLabel)\n      val cont =\n        form match\n        case IfLikeForm.While =>\n          // * Note that if the term is a `while`, the continuation `cont` corresponds to\n          // * what happens after each specified branch terminates,\n          // * ie, continuation to the next loop iteration.\n          (r: Result) => Assign.discard(r, loopCont)\n        case IfLikeForm.ImperativeIf =>\n          (r: Result) => Assign.discard(r, End())\n        case IfLikeForm.ReturningIf =>\n          if labels.isEmpty then\n            if k.isInstanceOf[TailOp] then\n              // If there are no shared consequents and the continuation is a tail\n              // operation, we can call it directly.\n              k\n            else\n              // Otherwise, if the continuation is not a tail operation, we should\n              // save the result in a temporary variable and call the continuation\n              // in the end.\n              assignResult\n          else\n            // When there are shared consequents, we are forced to save the result\n            // in the temporary variable nevertheless. Note that `cont` only gets\n            // called for non-shared consequents, so we should break to the end of\n            // the entire split after the assignment.\n            breakRoot\n      // When we are not rewriting while loops to tail-recursive functions,\n      // whether we need a `Break` to exit the loop at the end of the main block\n      // depends on whether there are shared consequents,\n      // as shared consequents will be lifted out of the main block and added as separate labelled blocks\n      // to jump to, so we cannot simply fall through the end of the main block to exit the loop.\n      // Note that when there is a `default` branch and we're in a loop,\n      // the semantics of that default branch is to always `continue` the loop,\n      // so we don't need to break out of the loop at the end of the main block as well.\n      val needsBreakToExitLoop =\n        (form is IfLikeForm.While) && !config.shouldRewriteWhile && labels.consequents.nonEmpty //&& labels.default.isEmpty\n      // The main block contains the lowered split, where each shared consequent\n      // is replaced with a `Break` to the corresponding label.\n      val mainBlock =\n        val innermostBlock =\n          given IfLikeForm = form\n          if needsBreakToExitLoop\n          then Begin(lowerSplit(normalized, cont), Break(rootBreakLabel))\n          else lowerSplit(normalized, cont)\n        // Wrap the main block in a labelled block for each shared consequent. The\n        // `rest` of each `Label` is the lowered consequent plus a `Break` to the\n        // end of the entire `if` term. Otherwise, it will fall through to the outer\n        // consequent, which is the wrong semantics.\n        val innerBlock: Block = labels.consequents match\n          case Nil => innermostBlock\n          case all @ (head :: tail) =>\n            def wrap(consequents: Ls[(Term, LabelSymbol)]): Block =\n              consequents.foldRight(innermostBlock):\n                case ((term, label), innerBlock) =>\n                  Label(label, false, innerBlock,\n                    if form is IfLikeForm.While\n                    then term_nonTail(term)(r => Assign.discard(r, loopCont))\n                    else term_nonTail(term)(breakRoot))\n            // There is no need to generate `break` for the outermost split\n            // if we're not generating an additional matchError block at the end.\n            if labels.matchError.isEmpty then\n              Label(head._2, false, wrap(tail), term_nonTail(head._1)(assignResult))\n            else wrap(all)\n        if form is IfLikeForm.While\n        then if needsBreakToExitLoop\n          then Begin(innerBlock, Break(rootBreakLabel))\n          else innerBlock\n        else labels.matchError match\n          case S(label) => Label(label, false, innerBlock, throwMatchErrorBlock)\n          case N => innerBlock\n      // If there are shared consequents, we need a wrap the entire block in a\n      // `Label` so that `Break`s in the shared consequents can jump to the end.\n      val body =\n        Scoped(\n          if useNestedScoped then LoweringCtx.loweringCtx.getCollectedSym else Set.empty,\n          if labels.isEmpty && !needsBreakToExitLoop\n          then mainBlock\n          else Label(rootBreakLabel, false, mainBlock, End()))\n      // Embed the `body` into `Label` if the term is a `while`.\n      lazy val rest = if usesResTmp then k(Value.Ref(l)) else k(lowering.unit)\n      val block =\n        if form === IfLikeForm.While then\n          // NOTE: `shouldRewriteWhile` is not the same as `config.rewriteWhileLoops`\n          // as shouldRewriteWhile is always true when effect handler lowering is on\n          if config.shouldRewriteWhile then\n            val loopResult = TempSymbol(N)\n            val isReturned = TempSymbol(N)\n            outerCtx.collectScopedSym(loopResult)\n            outerCtx.collectScopedSym(isReturned)\n            val loopEnd: Path =\n              Select(Value.Ref(State.runtimeSymbol), Tree.Ident(\"LoopEnd\"))(S(State.loopEndSymbol))\n            val blk = blockBuilder\n              .define(FunDefn(N, f, tSym, PlainParamList(Nil) :: Nil, Begin(body, Return(loopEnd, false)))(configOverride = N, annotations = Nil))\n              .assign(loopResult, Call(Value.Ref(f, S(tSym)), Nil ne_:: Nil)(true, true, false))\n            if summon[LoweringCtx].mayRet then\n              blk\n                .assign(isReturned, Call(Value.Ref(State.builtinOpsMap(\"!==\")),\n                  (loopResult.asPath.asArg :: loopEnd.asArg :: Nil) ne_:: Nil)(true, false, false))\n                .ifthen(Value.Ref(isReturned), Case.Lit(Tree.BoolLit(true)),\n                  Return(Value.Ref(loopResult), false),\n                  N\n                )\n                .rest(rest)\n            else\n              blk.rest(rest)\n          else\n            Begin(Label(loopLabel, true, body, End()), rest)\n        else if labels.isEmpty && k.isInstanceOf[TailOp]\n          && !form.isImperative\n            // * ^ Generated imperative `if` branches do not always yield a value, so if we removed this,\n            // * we would sometimes return `undefined`.\n            // * (This could be improved; currently, we fail to preserve the tail call in `fun f() = if false do f()`.)\n          then\n            body\n        else\n          Begin(body, rest)\n      scoped(\"ucs:lowered\"):\n        log(s\"Lowered:\\n${block.showAsTree}\")\n      block\nend Normalization\n\nobject Normalization:\n  /** This contains the labels for duplicated consequents and the default\n   *  branch which throws match errors. */\n  private class Labels(val consequents: Ls[(Term, LabelSymbol)], val matchError: Opt[LabelSymbol]):\n    private val map = consequents.toMap\n    \n    inline def isEmpty: Bool = consequents.isEmpty && matchError.isEmpty\n    \n    inline def get(term: Term): Opt[LabelSymbol] = map.get(term)\n  \n  /**\n    * Subtyping relations used in normalization and coverage checking.\n    */\n  def compareCasePattern(lhs: FlatPattern, rhs: FlatPattern)(using ctx: Elaborator.Ctx): Bool =\n    import FlatPattern.*, ctx.builtins as blt\n    (lhs, rhs) match\n    // `Object` is the supertype of all (non-virtual) classes and modules.\n    case (ClassLike(_, cs: ClassSymbol, _, _), ClassLike(symbol = blt.`Object`))\n        if !ctx.builtins.virtualClasses.contains(cs) => true\n    // Class and module are subtypes of `Object`.\n    case (ClassLike(_, cs: ModuleOrObjectSymbol, _, _), ClassLike(symbol = blt.`Object`)) => true\n    case (Tuple(n1, false), Tuple(n2, false)) if n1 === n2 => true\n    case (Tuple(n1, _), Tuple(n2, true)) if n2 <= n1 => true\n    // Note: We don't make Int31 compatible with Num, since Int31 needs to know how it should be\n    // sign-extended in order to convert into a Num.\n    case (ClassLike(symbol = blt.`Int`), ClassLike(symbol = blt.`Num`)) => true\n    // TODO(Derppening): Do we limit IntLit to (1 << 31) - 1 for `Int31`?\n    case (Lit(Tree.IntLit(_)), ClassLike(symbol = blt.`Int` | blt.`Int31` | blt.`Num`)) => true\n    case (Lit(Tree.StrLit(_)), ClassLike(symbol = blt.`Str`)) => true\n    case (Lit(Tree.DecLit(_)), ClassLike(symbol = blt.`Num`)) => true\n    case (Lit(Tree.BoolLit(_)), ClassLike(symbol = blt.`Bool`)) => true\n    case (Record(entries1), Record(entries2)) =>\n      entries1.forall { (fieldName1, _) => entries2.exists { (fieldName2, _) => fieldName1 === fieldName2 } }\n    case (Record(entries), rhs: ClassLike) =>\n      val clsParams = rhs.constructor.symbol.flatMap(_.asCls) match\n        case S(symbol) => symbol.defn match\n          case S(ClassDef.Parameterized(params = paramList)) => paramList.params\n          case S(_) | N => Nil\n        case (S(_) | N) => Nil\n      entries.forall { (fieldName, _) => clsParams.exists {\n        case Param(flags = FldFlags(isVal = isVal), sym = sym) => isVal && fieldName === sym.id\n      }}\n    // Check user-defined class hierarchy via extends clauses.\n    case (ClassLike(_, lhsSym, _, _), ClassLike(_, rhsSym, _, _)) =>\n      isSubclassOf(lhsSym, rhsSym)\n    case (_: FlatPattern, _: FlatPattern) => false\n  \n  /**\n    * Check if two patterns are provably disjoint, i.e., no value can match both.\n    * This is used to safely eliminate branches during specialization.\n    * Returns `true` for clear-cut cases (e.g., different literals,\n    * incompatible tuple sizes, sibling classes under single inheritance).\n    */\n  def areProvablyDisjoint(lhs: FlatPattern, rhs: FlatPattern)(using ctx: Elaborator.Ctx): Bool =\n    import FlatPattern.*\n    (lhs, rhs) match\n    case (Lit(l1), Lit(l2)) => !(l1 === l2)\n    case (Tuple(n1, false), Tuple(n2, false)) => n1 =/= n2\n    case (Tuple(n1, true), Tuple(n2, false)) => n2 < n1\n    case (Tuple(n1, false), Tuple(n2, true)) => n1 < n2\n    case (Lit(_), _: ClassLike) => !compareCasePattern(lhs, rhs)\n    case (_: ClassLike, Lit(_)) => !compareCasePattern(rhs, lhs)\n    case (Lit(_), Tuple(_, _)) | (Tuple(_, _), Lit(_)) => true\n    case (Record(_), Lit(_)) | (Lit(_), Record(_)) => true\n    case (Record(_), Tuple(_, _)) | (Tuple(_, _), Record(_)) => true\n    // Under the single-inheritance restriction, two classes where neither is a\n    // subclass of the other are provably disjoint. When we add matchable\n    // class-like things with multiple inheritance (e.g., interfaces), this check\n    // will need to be refined.\n    case (ClassLike(_, lhsSym, _, _), ClassLike(_, rhsSym, _, _)) =>\n      !isSubclassOf(lhsSym, rhsSym) && !isSubclassOf(rhsSym, lhsSym)\n    case _ => false\n  \n  /** Get the parent class-like symbol from the extends clause of a class or module. */\n  private def getParentClassLikeSymbol(sym: ClassSymbol | ModuleOrObjectSymbol)\n      : Opt[ClassSymbol | ModuleOrObjectSymbol] =\n    val ext: Opt[Term.New] = sym match\n      case cls: ClassSymbol => cls.defn.flatMap(_.ext)\n      case mod: ModuleOrObjectSymbol => mod.defn.flatMap(_.ext)\n    ext.flatMap(nw => nw.cls.symbol.flatMap(_.asClsOrMod))\n  \n  /** Check if `child` is a subclass of `parent` by traversing the class hierarchy.\n    * Uses a visited set to avoid infinite loops in case of cyclic inheritance. */\n  private def isSubclassOf(\n      child: ClassSymbol | ModuleOrObjectSymbol,\n      parent: ClassSymbol | ModuleOrObjectSymbol\n  ): Bool =\n    def go(sym: ClassSymbol | ModuleOrObjectSymbol,\n        visited: Set[ClassSymbol | ModuleOrObjectSymbol]): Bool =\n      !visited.contains(sym) && (getParentClassLikeSymbol(sym) match\n        case S(parentSym) =>\n          parentSym === parent || go(parentSym, visited + sym)\n        case N => false)\n    go(child, Set.empty)\n\n  final case class VarSet(declared: Set[BlockLocalSymbol]):\n    def +(nme: BlockLocalSymbol): VarSet = copy(declared + nme)\n    infix def has(nme: BlockLocalSymbol): Bool = declared.contains(nme)\n    def showDbg: Str = declared.iterator.mkString(\"{\", \", \", \"}\")\n\n  object VarSet:\n    def apply(): VarSet = VarSet(Set())\n\n  /** Specialization mode */\n  enum Mode:\n    case +\n    case -\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/SplitElaborator.scala",
    "content": "package hkmc2\npackage semantics\npackage ucs\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.{Keyword, Tree}, Tree.*\nimport Keyword.{`and`, `do`, `else`, `if`, `case`, `while`, `is`, `let`, `or`, `then`}\nimport Elaborator.{Ctx, Ctxl, UnderCtx, ctx}, SimpleSplit.*\nimport Message.MessageContext\nimport collection.mutable.SortedSet\nimport utils.TL\nimport scala.annotation.tailrec\n\nobject SplitElaborator:\n  /** A scrutinee is a function that returns a reference to the symbol. */\n  type Reference = () => Term.Ref\n  \n  type Connective = `do`.type | `then`.type\nimport SplitElaborator.*\n\ntrait SplitElaborator:\n  self: Elaborator =>\n  \n  import tl.*\n  \n  private given TL = tl\n  \n  private given Ordering[Loc] = Ordering.by(l => (l.spanStart, l.spanEnd))\n  \n  /** Keep track of the locations where `do` and `then` are used as connectives. */\n  private var kwLocSets = (SortedSet.empty[Loc], SortedSet.empty[Loc])\n  \n  private def reportInconsistentConnectives(kw: Keywrd[Keyword.SplitLike]): Unit =\n    (kwLocSets._1.headOption, kwLocSets._2.headOption) match\n      case (Some(doLoc), Some(thenLoc)) =>\n        raise(ErrorReport(\n          msg\"Mixed use of `do` and `then` in the `${kw.kw.name}` expression.\" -> kw.toLoc\n            :: msg\"Keyword `then` is used here.\" -> S(thenLoc)\n            :: msg\"Keyword `do` is used here.\" -> S(doLoc) :: Nil\n        ))\n      case _ => ()\n  \n  private def topmostDefault: SimpleSplit =\n    if kwLocSets._1.nonEmpty then Else(Term.UnitVal())(N) else End\n  \n  private object `~>`:\n    infix def unapply(tree: Tree): Opt[(Tree, Tree \\/ (Keywrd[Connective], Tree))] = tree match\n      case InfixApp(lhs, Keywrd(`and`), rhs) => S((lhs, L(rhs)))\n      case InfixApp(lhs, kwTree @ Keywrd(kw: `then`.type), rhs) =>\n        kwLocSets._2 ++= kwTree.toLoc\n        S((lhs, R((new Keywrd(kw).withLocOf(kwTree), rhs))))\n      case InfixApp(lhs, kwTree @ Keywrd(kw: `do`.type), rhs) =>\n        kwLocSets._1 ++= kwTree.toLoc\n        S((lhs, R((new Keywrd(kw).withLocOf(kwTree), rhs))))\n      case _ => N\n  \n  private def withScopedConnectives\n      (kw: Keywrd[Keyword.SplitLike])(evaluate: => SimpleSplit): (IfLikeForm, SimpleSplit) =\n    val savedKwLocSets = kwLocSets\n    kwLocSets = (SortedSet.empty, SortedSet.empty)\n    val split = evaluate\n    val (result, form) = kw.kw match\n      case `if` | `case` =>\n        (split ~~: topmostDefault,\n          if kwLocSets._1.nonEmpty then IfLikeForm.ImperativeIf else IfLikeForm.ReturningIf)\n      case `while` => (split, IfLikeForm.While)\n    reportInconsistentConnectives(kw)\n    kwLocSets = savedKwLocSets\n    (form, result)\n  \n  /** Transform trees into a UCS split. */\n  protected def split(t: IfLike): Ctxl[Term.IfLike] =\n    val (form, split) = withScopedConnectives(t.kw):\n      t.split match\n      case block: Block => termSplit(block.desugStmts, identity)\n      case other: Tree => termSplit(Ls(other), identity)\n    new Term.IfLike(t.kw.kw, form, split).withLocOf(t)\n  \n  /** Elaborate `case` expressions */\n  protected def caseSplit(scrut: VarSymbol, tree: Case): Ctxl[Term.IfLike] =\n    val (form, split) = withScopedConnectives(tree.kw):\n      patternBranch(() => scrut.ref(), tree.branches, identity)\n    new Term.IfLike(tree.kw.kw, form, split).withLocOf(tree)\n  \n  /** Elaborate shorthand expressions. */\n  protected def shorthandSplit(tree: Tree)(using UnderCtx): Ctxl[SimpleSplit] =\n    val affirmative = Else(Term.Lit(BoolLit(true)))(N)\n    val negative = Else(Term.Lit(BoolLit(false)))(N)\n    val (scrutinee, pattern) :: matches = disaggregate(tree)\n    subterm(scrutinee).reference: scrutinee =>\n      lazy val innerSplit: Ctxl[SimpleSplit] = expandMatches(matches)(affirmative)\n      pattern match\n        case Block(Nil) =>\n          val recordPattern = Pattern.Record(Nil).withLocOf(pattern)\n          Head.Match(scrutinee(), recordPattern, innerSplit) ~: negative\n        case Block(trees) => trees.foldRight(negative):\n          case (pattern, alternative) =>\n            Head.Match(scrutinee(), self.pattern(pattern), innerSplit) ~: alternative\n        case _ =>\n          val firstPattern = self.pattern(pattern)\n          firstPattern.variables.report\n          (ctx ++ firstPattern.variables.allocate).givenIn:\n            Head.Match(scrutinee(), firstPattern, innerSplit) ~: negative\n  \n  /** Desugar a list of trees as a term split. The returned function takes a\n    * function, which takes a `Ctx` and returns a `SimpleSplit` representing\n    * the _alternative_ split, and returns a `SimpleSplit` representing the\n    * split of the given trees. */\n  private def termSplit(ts: Ls[Tree], mk: Term => Term): Ctxl[SimpleSplit] =\n    val (_, splits) = ts.foldLeft((ctx, Ls[SimpleSplit]())):\n      case ((curCtx, splits), t) =>\n        termBranch(t, mk)(using curCtx).mapSecond(_ :: splits)\n    concatenate(splits)\n  \n  /** Concatenate a sequence of splits and report warning for splits that come\n    * after a split which ends with an `else` branch. */\n  private def concatenate(splits: Ls[SimpleSplit]): SimpleSplit =\n    // The first element is a list of branches. The second element is\n    // - `N` if no `else` branch has been found; or\n    // - `S((default, unreachables))` if `default` is the first `else` branch\n    //   in the split and all splits thereafter will be added to `unreachables`.\n    val z: (Ls[Head], Opt[(Else, Ls[SimpleSplit])]) = (Nil, N)\n    val (reachables, elseRest) = splits.reverseIterator.foldLeft(z):\n      // This is the case when we haven't found an `else` branch yet.\n      case ((branches, N), split) =>\n        @tailrec\n        def go(acc: Ls[Head], split: SimpleSplit): (Ls[Head], Opt[Else]) =\n          split match\n            case Cons(branch, tail) => go(branch :: acc, tail)\n            case els: Else => (acc, S(els))\n            case End => (acc, N)\n        go(branches, split).mapSecond(_.map(_ -> (Nil: Ls[SimpleSplit])))\n      case ((branches, S((default, unreachables))), split) =>\n        (branches, S((default, split :: unreachables)))\n    // Report unreachables splits.\n    elseRest match\n      case S((default, unreachables)) =>\n        val messages = unreachables.reverseIterator.map: split =>\n          msg\"This branch is unreachable.\" -> split.toLoc\n        .toList\n        if messages.nonEmpty then\n          raise(WarningReport((msg\"This catch-all clause makes the following branches unreachable.\" -> default.toLoc :: messages)))\n      case N => ()\n    // Reconstruct the split from the reachable `heads`.\n    reachables.foldLeft(elseRest.fold(SimpleSplit.End)(_._1)):\n      case (innerSplit, branch) => branch ~: innerSplit\n  \n  /** Handle the common cases of branches in splits. */\n  private def branch(using Ctx): Cfg[PartialFunction[Tree, (Ctx, SimpleSplit)]] =\n    // Interleaved-`let` bindings like `{ x is A then 0; let x = 1; ... }`.\n    case LetLike(Keywrd(`let`), ident: Ident, S(rhsTree), N) =>\n      val symbol = VarSymbol(ident)\n      val head = Head.Let(symbol, term(rhsTree)) \n      ((ctx + (ident.name -> symbol)), head ~: End)\n    // Interleaved-`do` statements like `{ x is A then 0; do log(1); ... }`.\n    case PrefixApp(Keywrd(`do`), rhsTree) =>\n      (ctx, Head.Let(TempSymbol(N, \"unused\"), term(rhsTree)) ~: End)\n    // Although the `else`-clause marks the end of the split, we cannot\n    // stop and still have to elaborate the remaining trees.\n    case PrefixApp(kwTree @ Keywrd(`else`), elseTree) =>\n      (ctx, Else(term(elseTree))(S(new Keywrd(`else`).withLocOf(kwTree))))\n  \n  private def expandMatches(matchesTree: Ls[TT])(consequent: Ctxl[SimpleSplit]): Ctxl[SimpleSplit] =\n    val z = (ctx, Ls[(Term, Pattern)]())\n    // Elaborate the term and the pattern in each match.\n    val (innerCtx, matches) = matchesTree.foldLeft(z):\n      case ((curCtx, matches), (scrutineeTree, patternTree)) =>\n        val scrutinee = term(scrutineeTree)(using curCtx)\n        val pattern = self.pattern(patternTree)(using curCtx)\n        pattern.variables.report\n        val resCtx = curCtx ++ pattern.variables.allocate\n        (resCtx, (scrutinee, pattern) :: matches)\n    // As `matches` is reversed, we should process it from the left.\n    val split = matches.foldLeft(consequent(using innerCtx)):\n      case (innerSplit, (scrutinee, pattern)) =>\n        scrutinee.reference: scrutineeRef =>\n          Head.Match(scrutineeRef(), pattern, innerSplit) ~: End\n    split\n  \n  private def termBranch(t: Tree, mk: Term => Term): Ctxl[(Ctx, SimpleSplit)] = branch.appOrElse(t):\n    case block: Block => (ctx, termSplit(block.desugStmts, mk))\n    case lhs is rhs => (ctx, mk(term(lhs)).reference(patternBranch(_, rhs, identity)))\n    // Several matches followed by `and`, `do`, or `then`.\n    case matchesTree ~> consequent =>\n      val (coda, patternTree) :: matches = disaggregate(matchesTree)\n      def innerSplit(using ctx: Ctx) = expandMatches(matches):\n        consequent match\n          case L(tree) => termSplit(Ls(tree), identity)\n          case R((kw, tree)) => Else(term(tree))(S(kw))\n      val split = coda match\n        case Under() => innerSplit\n        case coda => mk(term(coda)).reference: scrutinee =>\n          val pattern = self.pattern(patternTree)\n          val innerCtx = ctx ++ pattern.variables.allocate\n          Head.Match(scrutinee(), pattern, innerSplit(using innerCtx)) ~: End\n      (ctx, split)\n    // Handle splits on binary operators.\n    case OpApp(lhs, ident: Ident, rhss) =>\n      val op = term(ident)\n      val split = term(lhs).reference: lhs =>\n        val mk2 = (rhs: Term) =>\n          val args = Term.Tup(PlainFld(lhs()) :: PlainFld(rhs) :: Nil)(DummyTup)\n          Term.App(op, args)(Tree.DummyApp, N, FlowSymbol(\"‹operator-split›\"))\n        termSplit(rhss, mk2 andThen mk)\n      (ctx, split)\n    case OpSplit(lhs, rhss) =>\n      val split = mk(term(lhs)).reference: lhs =>\n        val (_, splits) = rhss.foldLeft((ctx, Ls[SimpleSplit]())):\n          case ((curCtx, splits), t) =>\n            operatorBranch(lhs, t)(using curCtx).mapSecond(_ :: splits)\n        concatenate(splits)\n      (ctx, split)\n    // Unrecognized term split.\n    case _ =>\n      error(msg\"Unrecognized term split (${t.describe})\" -> t.toLoc)\n      (ctx, End)\n  \n  private def operatorBranch(scrutinee: Reference, rhs: Tree): Ctxl[(Ctx, SimpleSplit)] =\n    branch.appOrElse(rhs): rhsTree => \n      termBranch(rhsTree.splitOn(Trm(scrutinee())), identity)\n  \n  private def patternBranch(scrutinee: Reference, t: Tree, mk: Tree => Tree): Ctxl[SimpleSplit] = t match\n    case block: Block =>\n      val (_, splits) = block.desugStmts.foldLeft((ctx, Ls[SimpleSplit]())):\n        case ((curCtx, splits), t) =>\n          branch(using curCtx).lift(t).getOrElse:\n            (curCtx, patternBranch(scrutinee, t, mk)(using curCtx))\n          .mapSecond(_ :: splits)\n      concatenate(splits)\n    case App(ctor: Ctor, Tup(rhss)) =>\n      val nl = (t: Tree) => mk(App(ctor, Tup(t :: Nil)))\n      patternBranch(scrutinee, Block(rhss), nl)\n    case Annotated(annotation, target) =>\n      patternBranch(scrutinee, target, Annotated(annotation, _) |> mk)\n    case patternAndMatches ~> consequentTree =>\n      val (firstPatternTree, _) :: matches = disaggregate(patternAndMatches)\n      val firstPattern = self.pattern(mk(firstPatternTree))\n      firstPattern.variables.report\n      (ctx ++ firstPattern.variables.allocate).givenIn:\n        val split = expandMatches(matches):\n          consequentTree match\n            case L(tree) =>\n              termSplit(Ls(tree), identity)\n            case R((kw, tree)) => Else(term(tree))(S(kw))\n        Head.Match(scrutinee(), firstPattern, split) ~: End\n    case _ =>\n      error(msg\"Unrecognized pattern split (${t.describe}).\" -> t.toLoc)\n      Else(Term.Error)(N).withLocOf(t) // To inspect the source of errors.\n  \n  extension (term: Term)\n    private inline def reference(continuation: Reference => SimpleSplit): SimpleSplit =\n      term match\n        // If the term is already a reference, we can re-reference its symbol.\n        case Term.Ref(symbol) => continuation(() => symbol.ref())\n        // Otherwise, we need to create a temporary symbol holding the term.\n        case term: Term =>\n          val symbol = TempSymbol(N, \"scrut\")\n          Head.Let(symbol, term) ~: continuation(() => symbol.ref())\n  \n  private type TT = (Tree, Tree)\n  \n  /** Decompose a `Tree` of conjunct matches. The tree is from the same line in\n   *  the source code and followed by a `then`, or `and` with a continued line.\n   *  A formal definition of the conjunction is:\n   *  \n   *  ```bnf\n   *  conjunction ::= conjunction `and` conjunction  # conjunction\n   *                | term `is` pattern              # pattern matching\n   *                | term                           # Boolean condition\n   *  ```\n   * \n   *  Each match is represented by a pair of a _coda_ and a _pattern_ that is\n   *  yet to be elaborated. For boolean conditions, the pattern is a `BoolLit`.\n   * \n   *  This function does not invoke elaboration and the implementation utilizes\n   *  functional lists to avoid calling the `reverse` method on the output,\n   *  which returns type `List[T]` instead of `::[T]`. See paper _A Novel\n   *  Representation of Lists and Its Application to the Function_ for details.\n   * \n   *  @param tree the tree to desugar\n   *  @return a non-empty list of scrutinee and pattern pairs represented in\n   *          type `::[T]` (instead of `List[T]`) so that the head element\n   *          can be retrieved in a type-safe manner\n   */\n  private def disaggregate(tree: Tree): ::[TT] =\n    def go(tree: Tree, acc: TT => ::[TT]): () => ::[TT] = tree match\n      case lhs `and` rhs  => go(lhs, ::(_, go(rhs, acc)()))\n      case lhs `or` rhs   =>\n        error(msg\"Logical `or` is not yet supported.\" -> tree.toLoc)\n        go(lhs, ::(_, go(rhs, acc)())) // FIXME: this is currently copy-pasted from the `and` case\n      case scrut `is` pat => () => acc((scrut, pat))\n      case test           => () => acc((test, Tree.BoolLit(true)))\n    go(tree, ::(_, Nil))()\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/TermSynthesizer.scala",
    "content": "package hkmc2\npackage semantics\npackage ucs\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.Tree, Tree.*, Elaborator.{Ctx, State, ctx}\n\n/** This trait includes some helpers for synthesizing `Term`s which look like \n  * they have already been processed by the `Resolver`. Its methods should only\n  * be called in stages after the `Resolver`. Currently, its derived classes are\n  * `Normalization`, `Compiler`, and `SplitCompiler`. */\ntrait TermSynthesizer(using State):\n  protected final def sel(p: Term, k: Ident): Term.SynthSel =\n    (Term.SynthSel(p, k)(N, FlowSymbol.synthSel(k.name), N, N): Term.SynthSel).resolve\n  protected final def sel(p: Term, k: Ident, s: MemberSymbol): Term.SynthSel =\n    (Term.SynthSel(p, k)(S(s), FlowSymbol.synthSel(k.name), N, N): Term.SynthSel).resolve\n  protected final def sel(p: Term, k: Str): Term.SynthSel = sel(p, Ident(k): Ident)\n  protected final def sel(p: Term, k: Str, s: MemberSymbol): Term.SynthSel = sel(p, Ident(k): Ident, s)\n  protected final def int(i: Int) = Term.Lit(IntLit(BigInt(i)))\n  protected final def str(s: Str) = Term.Lit(StrLit(s))\n  protected final def `null` = Term.Lit(UnitLit(true))\n  protected final def fld(t: Term) = Fld(FldFlags.empty, t, N)\n  protected final def tup(xs: List[Term]): Term.Tup =\n    Term.Tup(xs.iterator.map(fld).toList)(DummyTup)\n  protected final def tup(xs: Fld*): Term.Tup = Term.Tup(xs.toList)(DummyTup)\n  protected final def app(l: Term, r: Term, label: Str): Term.App = app(l, r, FlowSymbol(label))\n  protected final def app(l: Term, r: Term, s: FlowSymbol): Term.App =\n    (Term.App(l, r)(App(Dummy, Dummy), N, s): Term.App).resolve\n  protected final def `new`(cls: Term, args: Ls[Term], label: Str): Term.New = \n    Term.New(cls, args, N)(N)\n  protected final def rcd(fields: RcdField*): Term.Rcd = Term.Rcd(false, fields.toList)\n  \n  protected final def splitLet(sym: BlockLocalSymbol, term: Term)(inner: Split): Split =\n    Split.Let(sym, term, inner)\n  \n  protected final def param = Param(FldFlags.empty, _, N, Modulefulness.none)\n  protected final def paramList(params: Param*) = PlainParamList(params.toList)\n    \n  private lazy val runtimeRef: Term.Ref = State.runtimeSymbol.ref().resolve\n\n  /** Make a term that looks like `runtime.MatchSuccess` with its symbol. */\n  protected lazy val matchSuccessClass =\n    sel(runtimeRef, \"MatchSuccess\", State.matchSuccessClsSymbol).resolved(State.matchSuccessClsSymbol)\n\n  /** Make a pattern that looks like `runtime.MatchSuccess.class`. */\n  protected def matchSuccessPattern(parametersOpt: Opt[Ls[BlockLocalSymbol]]): FlatPattern.ClassLike =\n    val parameters = parametersOpt.map(_.map(_ -> N))\n    FlatPattern.ClassLike(matchSuccessClass, State.matchSuccessClsSymbol, parameters, false)(Tree.Dummy)\n\n  /** Make a term that looks like `runtime.MatchFailure` with its symbol. */\n  protected lazy val matchFailureClass =\n    sel(runtimeRef, \"MatchFailure\", State.matchFailureClsSymbol).resolved(State.matchFailureClsSymbol)\n\n  /** Make a pattern that looks like `runtime.MatchFailure.class`. */\n  protected def matchFailurePattern(parametersOpt: Opt[Ls[BlockLocalSymbol]]): FlatPattern.ClassLike =\n    val parameters = parametersOpt.map(_.map(_ -> N))\n    FlatPattern.ClassLike(matchFailureClass, State.matchFailureClsSymbol, parameters, false)(Tree.Dummy)\n\n  protected lazy val tupleSlice = sel(sel(runtimeRef, \"Tuple\"), \"slice\", State.tupleSliceSymbol)\n  protected lazy val tupleLazySlice = sel(sel(runtimeRef, \"Tuple\"), \"lazySlice\", State.tupleLazySliceSymbol)\n  protected lazy val tupleGet = sel(sel(runtimeRef, \"Tuple\"), \"get\", State.tupleGetSymbol)\n  protected lazy val stringStartsWith = sel(sel(runtimeRef, \"Str\"), \"startsWith\", State.strStartsWithSymbol)\n  protected lazy val stringGet = sel(sel(runtimeRef, \"Str\"), \"get\", State.strGetSymbol)\n  protected lazy val stringTake = sel(sel(runtimeRef, \"Str\"), \"take\", State.strTakeSymbol)\n  protected lazy val stringLeave = sel(sel(runtimeRef, \"Str\"), \"leave\", State.strLeaveSymbol)\n\n  /** Make a term that looks like `runtime.Tuple.get(t, i)`. */\n  protected final def callTupleGet(t: Term, i: Int, label: Str): Term =\n    callTupleGet(t, i, FlowSymbol(label))\n\n  /** Make a term that looks like `runtime.Tuple.slice(t, i)`. */\n  protected final def callTupleGet(t: Term, i: Int, s: FlowSymbol): Term =\n    app(tupleGet, tup(fld(t), fld(int(i))), s)\n  \n  /** Make a term that looks like `runtime.Tuple.slice(t, i, j)`. */\n  protected final def callTupleSlice(t: Term, i: Int, j: Int, label: Str): Term =\n    app(tupleSlice, tup(fld(t), fld(int(i)), fld(int(j))), label)\n\n  /** Make a term that looks like `runtime.Str.startsWith(t, p)`. */\n  protected final def callStringStartsWith(t: Term.Ref, p: Term, label: Str) =\n    app(stringStartsWith, tup(fld(t), fld(p)), label)\n\n  /** Make a term that looks like `runtime.Str.get(t, i)`. */\n  protected final def callStringGet(t: Term.Ref, i: Int, label: Str) =\n    app(stringGet, tup(fld(t), fld(int(i))), label)\n\n  /** Make a term that looks like `runtime.Str.drop(t, n)`. */\n  protected final def callStringTake(t: Term.Ref, n: Int, label: Str) =\n    app(stringTake, tup(fld(t), fld(int(n))), label)\n  \n  /** Make a term that looks like `runtime.Str.drop(t, n)`. */\n  protected final def callStringDrop(t: Term.Ref, n: Int, label: Str) =\n    app(stringLeave, tup(fld(t), fld(int(n))), label)\n\n  protected final def tempLet(dbgName: Str, term: Term)(inner: TempSymbol => Split): Split =\n    val s = TempSymbol(N, dbgName)\n    Split.Let(s, term, inner(s))\n\n  protected final def plainTest(cond: Term, dbgName: Str = \"cond\")(inner: => Split): Split =\n    val s = TempSymbol(N, dbgName)\n    Split.Let(s, cond, Branch(s.safeRef, inner) ~: Split.End)\n\n  protected final def makeBindings(fields: Ls[RcdField | RcdSpread]): Term =\n    if fields.isEmpty then `null` else Term.Rcd(false, fields)\n  \n  protected final def makeMatchSuccess(output: Term) =\n    `new`(matchSuccessClass, tup(fld(output), fld(`null`)) :: Nil, \"result of `MatchSuccess`\")\n  \n  protected final def makeMatchSuccess(output: Term, bindings: Term) =\n    `new`(matchSuccessClass, tup(fld(output), fld(bindings)) :: Nil, \"result of `MatchSuccess`\")\n  \n  protected final def makeMatchSuccess(output: Term, fields: Ls[RcdField | RcdSpread]) =\n    `new`(matchSuccessClass, tup(fld(output), fld(makeBindings(fields))) :: Nil, \"result of `MatchSuccess`\")\n    \n  protected final def makeMatchFailure(errors: Term = Term.Lit(UnitLit(true))) =\n    `new`(matchFailureClass, tup(fld(errors)) :: Nil, \"result of `MatchFailure`\")\n\n  /** Make a `Branch` that calls `Pattern` symbols' `unapply` functions. */\n  def makeLocalPatternBranch(\n      scrut: => Term.Ref,\n      localPatternSymbol: BlockLocalSymbol,\n      inner: => Split,\n  )(fallback: Split): Split =\n    val call = app(localPatternSymbol.safeRef, tup(fld(scrut)), s\"result of ${localPatternSymbol.nme}\")\n    tempLet(\"matchSuccess\", call): resultSymbol =>\n      Branch(resultSymbol.safeRef, matchSuccessPattern(N), inner) ~: fallback\n  \n  protected final def makeTupleBranch(\n    scrut: => Term.Ref,\n    subScrutinees: Ls[BlockLocalSymbol],\n    consequent: => Split,\n    alternative: Split\n  ): Split =\n    Branch(scrut, FlatPattern.Tuple(subScrutinees.size, false),\n      subScrutinees.iterator.zipWithIndex.foldRight(consequent):\n        case ((arg, index), innerSplit) =>\n          val label = s\"the $index-th element of the match result\"\n          Split.Let(arg, callTupleGet(scrut, index, label), innerSplit)\n    ) ~: alternative\n  \n  protected final def makeTupleBranch(\n    scrut: => Term.Ref,\n    leading: Ls[BlockLocalSymbol],\n    spread: BlockLocalSymbol,\n    trailing: Ls[BlockLocalSymbol],\n    consequent: => Split,\n    alternative: Split\n  ): Split =\n    val split0 = trailing.iterator.zipWithIndex.foldRight(consequent):\n      case ((arg, index), innerSplit) =>\n        val reverseIndex = trailing.size - index\n        val label = s\"the last $reverseIndex-th element of the tuple\"\n        Split.Let(arg, callTupleGet(scrut, -reverseIndex, label), innerSplit)\n    val split1 = Split.Let(spread, callTupleSlice(\n      scrut, leading.size, trailing.size, \"the middle part of the tuple\"), split0)\n    val split2 = leading.iterator.zipWithIndex.foldRight(split1):\n      case ((arg, index), innerSplit) =>\n        val label = s\"the first ${index + 1}-th element of the tuple\"\n        Split.Let(arg, callTupleGet(scrut, index, label), innerSplit)\n    Branch(scrut, FlatPattern.Tuple(leading.size + trailing.size, true), split2) ~: alternative\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ucs/package.scala",
    "content": "package hkmc2\npackage semantics\n\nimport sourcecode.{FileName, Line, Name}\nimport syntax.{Keyword, Tree}, Tree.{Ident, InfixApp, Keywrd, Sel, SynthSel}\nimport mlscript.utils.*, shorthands.*\n\npackage object ucs:\n  def error(using Line, FileName, Name, Raise)(msgs: (Message, Option[Loc])*): Unit =\n    raise(ErrorReport(msgs.toList))\n  \n  def warn(using Line, FileName, Name, Raise)(msgs: (Message, Option[Loc])*): Unit =\n    raise(WarningReport(msgs.toList))\n  \n  def bug(using Line, FileName, Name, Raise)(msgs: (Message, Option[Loc])*): Unit =\n    raise(InternalError(msgs.toList))\n  \n  extension (symbol: Symbol)\n    /** Create a `Ref` that does not have any implicit arguments. We need this\n     *  function because we generate a lot of `Ref`s after implicit resolution.\n     *  Writing `.resolve` is too verbose.\n     */\n    def safeRef: Term.Ref = symbol.ref().resolve\n  \n  extension (op: Keyword.Infix)\n    infix def unapply(tree: Tree): Opt[(Tree, Tree)] = tree match\n      case InfixApp(lhs, Keywrd(`op`), rhs) => S((lhs, rhs))\n      case _ => N\n  \n  type Ctor = SynthSel | Sel | Ident\n  \n  /** A helper extractor for matching the tree of `x | y`. */  \n  object extractors:\n    import Tree.OpApp\n    \n    /** A helper extractor for matching the tree of `x ..= y` and `x ..< y`.\n     *  The Boolean value indicates whether the range is inclusive.\n     */\n    object to:\n      infix def unapply(tree: Tree): Opt[(Tree, (Bool, Tree))] = tree match\n        case OpApp(lhs, Ident(\"..=\"), rhs :: Nil) => S(lhs, (true, rhs))\n        case OpApp(lhs, Ident(\"..<\"), rhs :: Nil) => S(lhs, (false, rhs))\n        case _ => N\nend ucs\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Compiler.scala",
    "content": "package hkmc2\npackage semantics\npackage ups\n\n\nimport mlscript.utils.*, shorthands.*\n\nimport syntax.{Keyword, LetBind, Tree}, Tree.{BoolLit, DecLit, Ident, IntLit, StrLit, UnitLit}\nimport Term.{Blk, Rcd, Ref, SynthIf, SynthSel}\nimport Pattern.{Instantiation, Head}\nimport Elaborator.{Ctx, State, ctx}, utils.TL\nimport ucs.{TermSynthesizer, FlatPattern, safeRef}\nimport Message.MessageContext, ucs.error\n\nimport collection.mutable.{Queue, Map as MutMap}, collection.immutable.{Set, Map}\nimport scala.annotation.tailrec\n\n/** The compiler for pattern definitions. It compiles instantiated patterns into\n  * a few matcher functions. Each matcher function matches a set of patterns\n  * and returns a record that contains the results of each pattern.\n  */\nclass Compiler(using Context)(using tl: TL)(using Ctx, State, Raise) extends TermSynthesizer:\n  import Compiler.*, tl.*\n  import Pattern.*\n\n  /** A previously-computed matcher result for one field of the current\n    * multi-matcher. The runtime representation is shape-dependent:\n    * singleton-label matchers return the label's value directly, while\n    * multi-label matchers return a record keyed by label field names.\n    */\n  private final case class MatcherResult(symbol: VarSymbol, labels: Set[Label]):\n    private def result: Term = sel(symbol.safeRef, \"result\")\n    def input: Term = sel(symbol.safeRef, \"input\")\n    /** Read the result for one label from this matcher result, abstracting over\n      * the singleton direct-return optimization.\n      */\n    def select(label: Label): Term =\n      if labels.size is 1 then result\n      else sel(result, label.asFieldName)\n    /** Produce the default failure value for this matcher result with the same\n      * shape that a successful submatcher call would have produced.\n      */\n    def default(using ResultMode): Term =\n      val result = labels.toList match\n        case label :: Nil => emptyMatchResult(\"empty\")\n        case labels =>\n          Rcd(false, labels.map: label =>\n            RcdField(str(label.asFieldName), emptyMatchResult(\"empty\")))\n      rcd(\n        RcdField(str(\"input\"), `null`),\n        RcdField(str(\"result\"), result)\n      )\n\n  private def bool(value: Bool): Term = Term.Lit(BoolLit(value))\n\n  private def isMatchOnly(using mode: ResultMode): Bool = mode is ResultMode.MatchOnly\n\n  private def emptyMatchResult(reason: Str)(using mode: ResultMode): Term =\n    if isMatchOnly then bool(false) else makeMatchFailure(str(reason))\n\n  private def nullifyEmptyBindings(bindings: Term): Term = bindings match\n    case Rcd(false, Nil) => `null`\n    case bindings => bindings\n  \n  extension (label: Label)\n    /** This decides the the field name of each label in the match record. */\n    def asFieldName: Str = s\"p_$label\"\n  \n  extension (pattern: Pat)\n    /** Get or create a label for the pattern. */\n    def label: Label = labelMap.getOrElseUpdate(pattern, labelMap.size)\n  \n  extension (field: Ident | Int)\n    def showDbg: Str = field match\n      case id: Ident => id.name\n      case index: Int => s\"p_$index\"\n    /** Convert the field name to an `Ident`. */\n    def asIdent: Ident = field match\n      case id: Ident => new Ident(id.name)\n      case index: Int => Ident(index.toString)\n  \n  extension (head: Head)\n    /** Create a flat pattern that can be used in the UCS expressions. */\n    def toFlatPattern: FlatPattern = head match\n      case lit: syntax.Literal => FlatPattern.Lit(lit)\n      case sym: (ClassSymbol | ModuleOrObjectSymbol) =>\n        val constructor = reference(sym, head.toLoc).getOrElse(Term.Error)\n        FlatPattern.ClassLike(constructor, sym, N, false)(Tree.Dummy)\n    def showDbg: Str = head match\n      case lit: syntax.Literal => lit.idStr\n      case sym: ClassLikeSymbol => sym.nme\n  \n  extension (patterns: Set[(Label, ExPat)])\n    /** Specialize a set of patterns. Also display them in the debug log. */\n    def specializeSet(head: Opt[Head]): Set[(Label, SpPat)] =\n      log(s\"Specialized patterns of ${head.fold(\"the case without tags\")(_.showDbg)}:\")\n      patterns.map: (label, pattern) =>\n        val spec = pattern.specialize(head)\n        val simp = spec.simplify\n        log(s\"• Label $label\")\n        log(s\"  ‣ Expanded: ${spec.showDbg}\")\n        log(s\"  ‣ Simplified: ${simp.showDbg}\")\n        (label, simp)\n  \n  val labelMap: MutMap[Pat, Label] = MutMap()\n  \n  val multiMatchers: MutMap[Set[Label], BlockLocalSymbol] = MutMap.empty\n  \n  /** The built multi-matcher functions. */\n  val implementations: MutMap[BlockLocalSymbol, (ParamList, Term)] = MutMap.empty\n  \n  val buildQueue: Queue[(BlockLocalSymbol, Set[Pat])] = Queue.empty\n  \n  /** Build a matcher function that matches a single pattern. This function\n   *  should be applied to the pattern that is considered as the entry point.*/\n  def buildMatcher(pattern: Pat, resultMode: ResultMode): (BlockLocalSymbol, Ls[Implementation]) = scoped(\"ucs:compiler\"):\n    given ResultMode = resultMode\n    val entryPointSymbol = buildMultiMatcher(Set(pattern))\n    while buildQueue.nonEmpty do\n      val (symbol, patterns) = buildQueue.dequeue()\n      implementations += (symbol -> buildMultiMatcherBody(patterns))\n    entryPointSymbol -> implementations.iterator.map:\n      case (symbol, (paramList, term)) => (symbol, paramList, term)\n    .toList\n  \n  /** Build a multi-matcher function and returns the local symbol that we can\n   *  use to call it. The built function definition is stored in the map\n   *  `implementations`. */\n  def buildMultiMatcher(patterns: Set[Pat])(using ResultMode): BlockLocalSymbol =\n    // Get or create the label for each pattern. Multi-matchers are identified\n    // by the set of labels (orders are not important).\n    val labels = patterns.map(_.label)\n    multiMatchers.get(labels).getOrElse:\n      val f = TempSymbol(N, makeMultiMatcherName(patterns))\n      multiMatchers += (labels -> f)\n      buildQueue enqueue (f -> patterns)\n      f // Return the symbol of the built function.\n  \n  /** Build the body of a multi-matcher function. The memoization is done by\n   *  `buildMultiMatcher`. */\n  def buildMultiMatcherBody(patterns: Set[Pat])(using ResultMode): (ParamList, Term) = trace(\n    pre = s\"buildMultiMatcherBody: ${\n      patterns.iterator.map: pattern =>\n        s\"${pattern.showDbg} => ${pattern.label}\"\n      .mkString(\"{\", \", \", \"}\")}\"\n  ):\n    val expandedPatterns = patterns.map(p => (p.label, p.expand(Set.empty)))\n    val heads = expandedPatterns.flatMap((_, p) => p.heads).toList\n    // This is the parameter of the current multi-matcher.\n    val scrutinee = VarSymbol(Ident(\"input\"))\n    // Assemble branches for constructors and literals.\n    val branches = heads.map: head =>\n      // Weird. Removing type annotations caused type errors.\n      val specialized = expandedPatterns.specializeSet(S(head))\n      val consequent = Split.Else(multiMatcherBranch(specialized, scrutinee))\n      Branch(scrutinee.safeRef, head.toFlatPattern, consequent)\n    // Assemble the default branch.\n    val default =\n      // Weird. Removing type annotations caused type errors.\n      val specialized = expandedPatterns.specializeSet(N)\n      Split.Else(multiMatcherBranch(specialized, scrutinee))\n    // Make a split that tries all branches in order.\n    val topmostSplit = branches.foldRight(default)(_ ~: _)\n    val bodyTerm = SynthIf(topmostSplit)\n    log(s\"Multi-matcher body:\\n${topmostSplit.prettyPrint}\")\n    (paramList(param(scrutinee)), bodyTerm)\n  \n  def multiMatcherBranch(\n      patterns: Set[(Label, SpPat)],\n      scrutinee: BlockLocalSymbol\n  )(using ResultMode): Blk = trace(\n    pre = s\"multiMatcherBranch: scrutinee = ${scrutinee} | patterns = ${\n      patterns.iterator.map: (label, pattern) =>\n        s\"${pattern.showDbg} => ${label}\"\n      .mkString(\"{\", \", \", \"}\")}\"\n  ):\n    val fields = patterns.flatMap((_, p) => p.fields)\n    log(s\"fields: ${fields.iterator.map(_.showDbg).mkString(\"{\", \", \", \"}\")}\")\n    val subPatternsByField = Map.from(fields.map: field =>\n      field -> patterns.flatMap((_, p) => p.collectSubPatterns(field)))\n    val subScrutinees = Map.from(subPatternsByField.map: (field, subPatterns) =>\n      field -> MatcherResult(VarSymbol(field.asIdent), subPatterns.map(_.label)))\n    // Let bindings that bind the sub-scrutinee to the result of each matcher.\n    val bindings = subPatternsByField.iterator.flatMap: (field, subPatterns) =>\n      val subScrutinee = subScrutinees(field)\n      log(s\"subPattern for field ${field.showDbg}: ${\n        subPatterns.iterator.map(_.showDbg).mkString(\"{\", \", \", \"}\")}\")\n      val subMatcherSymbol = buildMultiMatcher(subPatterns)\n      val conditional =\n        // Check the presence of the field, and call the matcher if it exists.\n        val fieldIdent: Ident = field.asIdent\n        val fieldSymbol = TempSymbol(N, fieldIdent.name)\n        val fieldTest = FlatPattern.Record((fieldIdent -> fieldSymbol) :: Nil)\n        val consequent = Split.Else:\n          val resultTerm = app(subMatcherSymbol.safeRef, tup(fld(fieldSymbol.safeRef)), \"result\")\n          rcd(\n            RcdField(str(\"input\"), fieldSymbol.safeRef),\n            RcdField(str(\"result\"), resultTerm)\n          )\n        val branch = Branch(scrutinee.safeRef, fieldTest, consequent)\n        SynthIf(branch ~: Split.Else(subScrutinee.default))\n      LetDecl(subScrutinee.symbol, Nil) :: DefineVar(subScrutinee.symbol, conditional) :: Nil\n    .toList\n    // For each pattern, we compile a split and bind the result to a variable.\n    // The variable will be a field of the output record.\n    val z = (Nil: Ls[Statement], Nil: Ls[(Label, Term)])\n    val (tests, resultTerms) = patterns.iterator.foldLeft(z):\n      case ((stmts, results), (label, pattern)) =>\n        val symbol = TempSymbol(N, label.asFieldName + \"$\")\n        val makeSplit = completePattern(pattern, scrutinee, subScrutinees, Nil)\n        val split = makeSplit(\n          // There is no topmost transform here, so we emit the direct success\n          // value: `MatchSuccess` in full mode, `true` in match-only mode.\n          makeConsequent = (outputSymbol, bindings) => Split.Else:\n            if isMatchOnly then bool(true)\n            else makeMatchSuccess(outputSymbol.use, nullifyEmptyBindings(bindings.use)),\n          alternative = Split.Else(emptyMatchResult(\"topmost\")))\n        val test = SynthIf(split)\n        (DefineVar(symbol, test) :: LetDecl(symbol, Nil) :: stmts, (label, symbol.safeRef) :: results)\n    // Materialize the matcher's final return value. Singleton matchers return\n    // their only field directly; multi-label matchers still return a record.\n    val resultTerm = resultTerms.reverse match\n      case (_, term) :: Nil => term\n      case terms => Rcd(false, terms.map: (label, term) =>\n        RcdField(str(label.asFieldName), term))\n    // Lastly, we return the matcher result, directly for singleton matchers\n    // and as a record otherwise.\n    Blk(bindings ::: tests.reverse, resultTerm)\n  \n  import Pattern.*\n  \n  /** Represent things that can be used as expressions in consequents. */\n  type Usable = BlockLocalSymbol | Term\n  \n  extension (usable: Usable)\n    def use: Term = usable match\n      case symbol: BlockLocalSymbol => symbol.safeRef\n      case term: Term => term\n  \n  /** The bindings can be a `Term` or a `TempSymbol`. */\n  type MakeConsequent = (output: Usable, bindings: Usable) => Split\n  \n  /** A function that makes a split in matcher functions. The first argument\n   *  is the function that makes the innermost split. The second argument is the\n   *  alternative split. Note that the alternative is not a fallback.\n   */\n  type MakeSplit = (makeConsequent: MakeConsequent, alternative: Split) => Split\n  \n  /** Create the innermost `Else` split based on whether we have a transform\n   *  term or not.\n   *  @param output The default output of the pattern. It will not be evaluated\n   *                if there is a transform term.\n   */\n  private def completeMatchSuccess(\n    transformOpt: Opt[TempSymbol],\n    output: => Term,\n    bindings: => Term\n  ): Split = transformOpt match\n    // If no transform is provided, we just return the current scrutinee and\n    // the bindings through `MatchSuccess`.\n    case N => Split.Else:\n      makeMatchSuccess(output, nullifyEmptyBindings(bindings))\n    case S(transform) =>\n      val resultSymbol = TempSymbol(N, \"transformResult\")\n      val bindingsTerm = nullifyEmptyBindings(bindings)\n      val transformTerm = app(transform.safeRef, tup(fld(bindingsTerm)), \"the transform's result\")\n      Split.Let(resultSymbol, transformTerm, Split.Else(\n        makeMatchSuccess(resultSymbol.safeRef)))\n  \n  private def completePattern(\n      pattern: SpPat,\n      scrutinee: BlockLocalSymbol,\n      subScrutinees: Map[Ident | Int, MatcherResult],\n      aliases: Ls[VarSymbol]\n  )(using ResultMode): MakeSplit = trace(pre = s\"completePattern: ${pattern.showDbg}\"):\n    pattern match\n    case MatchedClassLike(sym, fields) if isMatchOnly =>\n      val acceptAll: MakeSplit = (makeConsequent, _) => makeConsequent(scrutinee, rcd())\n      fields.iterator.foldRight(acceptAll):\n        case ((field, pattern), makeInnerSplit) =>\n          val label = pattern.label\n          val target = subScrutinees(field).select(label)\n          val resultSymbol = TempSymbol(N, s\"result$label$$\")\n          (makeConsequent, alternative) =>\n            Split.Let(resultSymbol, target,\n              Branch(resultSymbol.safeRef,\n                makeInnerSplit(makeConsequent, Split.End)) ~: alternative)\n    case MatchedClassLike(sym, fields) =>\n      val rebuildNeeded = fields.iterator.exists((_, pattern) => !pattern.preservesOriginalScrutinee)\n      val constructor = sym match\n        case symbol: (ClassSymbol | ModuleOrObjectSymbol) =>\n          reference(symbol, symbol.toLoc).getOrElse(Term.Error)\n      val makeMakeSplit = fields.iterator.foldRight(\n        (fields: Ls[(Ident, Term)], bindingsSymbols: Ls[TempSymbol]) =>\n          ((makeConsequent, alternative) =>\n            log(s\"current bindings: \" + aliases.map(_.name).mkString(\"{\", \", \", \"}\"))\n            val currentBindings = aliases.map:\n              alias => RcdField(str(alias.name), scrutinee.safeRef)\n            val bindings = bindingsSymbols match\n              case Nil => makeBindings(currentBindings)\n              case bindingsSymbol :: Nil =>\n                if currentBindings.isEmpty then bindingsSymbol.safeRef\n                else makeBindings(RcdSpread(bindingsSymbol.safeRef) :: currentBindings)\n              case _ =>\n                val spreads = bindingsSymbols.reverseIterator.map:\n                  _.safeRef |> RcdSpread.apply\n                .toList\n                makeBindings(spreads ::: currentBindings)\n            val output =\n              if rebuildNeeded then\n                `new`(\n                  constructor,\n                  tup(fields.reverseIterator.map(_._2 |> fld).toSeq*) :: Nil,\n                  s\"rebuilt ${sym.nme}\"\n                )\n              else\n                scrutinee.safeRef\n            makeConsequent(output, bindings)\n          ): MakeSplit\n      ):\n        case ((field, pattern), makeInnerSplit) =>\n          val label = pattern.label\n          val target = subScrutinees(field).select(label)\n          val resultSymbol = TempSymbol(N, s\"result$label$$\")\n          val outputSymbol = TempSymbol(N, s\"output$label$$\")\n          val fieldAliases = pattern.aliases\n          val fieldBindingsSymbol = TempSymbol(N, \"fieldBindings\")\n          val fieldBindingsTerm = makeBindings(fieldAliases.map:\n            alias => RcdField(str(alias.name), outputSymbol.safeRef))\n          val fieldOutput =\n            if rebuildNeeded && !pattern.preservesOriginalScrutinee then outputSymbol.safeRef\n            else subScrutinees(field).input\n          (outputFields: Ls[(Ident, Term)], bindingsSymbols: Ls[TempSymbol]) =>\n            ((makeConsequent, alternative) =>\n              val bindingsSymbol = TempSymbol(N, \"bindings\")\n              val accumulatedBindings =\n                val withFieldAliases =\n                  if fieldAliases.isEmpty then bindingsSymbols\n                  else fieldBindingsSymbol :: bindingsSymbols\n                if pattern.symbols.isEmpty then withFieldAliases\n                else bindingsSymbol :: withFieldAliases\n              val innerSplit =\n                makeInnerSplit((field, fieldOutput) :: outputFields, accumulatedBindings)\n                  (makeConsequent, Split.End)\n              Split.Let(resultSymbol, target, Branch(\n                scrutinee = resultSymbol.safeRef,\n                pattern = matchSuccessPattern(S(outputSymbol :: bindingsSymbol :: Nil)),\n                continuation =\n                  if fieldAliases.isEmpty then innerSplit\n                  else Split.Let(fieldBindingsSymbol, fieldBindingsTerm, innerSplit)\n              ) ~: alternative)): MakeSplit\n      makeMakeSplit(Nil, Nil)\n    case Record(fields) if isMatchOnly =>\n      val acceptAll: MakeSplit = (makeConsequent, _) => makeConsequent(scrutinee, rcd())\n      fields.iterator.foldRight(acceptAll):\n        case ((field, pattern), makeInnerSplit) =>\n          val label = pattern.label\n          val target = subScrutinees(field).select(label)\n          val resultSymbol = TempSymbol(N, s\"result$label$$\")\n          (makeConsequent, alternative) =>\n            Split.Let(resultSymbol, target,\n              Branch(resultSymbol.safeRef,\n                makeInnerSplit(makeConsequent, Split.End)) ~: alternative)\n    case Record(fields) =>\n      // Input: a record pattern made of several fields.\n      // Output: a record, each field of which is the output of the\n      //   corresponding field's pattern.\n      // Construct a conjunction of tests for each field.\n      val makeMakeSplit = fields.iterator.foldRight(\n        (fields: Ls[RcdField], bindingsSymbols: Ls[TempSymbol]) =>\n          ((makeConsequent, alternative) =>\n            log(s\"current bindings: \" + aliases.map(_.name).mkString(\"{\", \", \", \"}\"))\n            // The current pattern's bindings.\n            val currentBindings = aliases.map:\n              alias => RcdField(str(alias.name), scrutinee.safeRef)\n            // Here, we need to merge the current bindings with previously\n            // accumulated bindings. Some special cases here are to make the\n            // generated code more concise and efficient.\n            val bindings = bindingsSymbols match\n              case Nil => makeBindings(currentBindings)\n              case bindingsSymbol :: Nil =>\n                if currentBindings.isEmpty then bindingsSymbol.safeRef\n                else makeBindings(RcdSpread(bindingsSymbol.safeRef) :: currentBindings)\n              case _ =>\n                // Spread the previously accumulated bindings.\n                val spreads = bindingsSymbols.reverseIterator.map:\n                  _.safeRef |> RcdSpread.apply\n                .toList\n                // Append the current bindings to the spreads.\n                makeBindings(spreads ::: currentBindings)\n            makeConsequent(Rcd(false, fields.reverse), bindings)\n          ): MakeSplit\n      ):\n        case ((field, pattern), makeInnerSplit) =>\n          val label = pattern.label\n          val target = subScrutinees(field).select(label)\n          // This is the symbol for `MatchSuccess`.\n          val resultSymbol = TempSymbol(N, s\"result$label$$\")\n          // This is the symbol for the output of the pattern.\n          val outputSymbol = TempSymbol(N, s\"output$label$$\")\n          val outputField = RcdField(str(field.name), outputSymbol.safeRef)\n          // This is the bindings of the current field.\n          val fieldAliases = pattern.aliases\n          val fieldBindingsSymbol = TempSymbol(N, \"fieldBindings\")\n          val fieldBindingsTerm = makeBindings(fieldAliases.map:\n            alias => RcdField(str(alias.name), outputSymbol.safeRef))\n          (outputFields: Ls[RcdField], bindingsSymbols: Ls[TempSymbol]) =>\n            ((makeConsequent, alternative) =>\n              val bindingsSymbol = TempSymbol(N, \"bindings\")\n              val accumulatedBindings =\n                val withFieldAliases =\n                  if fieldAliases.isEmpty then bindingsSymbols\n                  else fieldBindingsSymbol :: bindingsSymbols\n                if pattern.symbols.isEmpty then withFieldAliases\n                else bindingsSymbol :: withFieldAliases\n              val innerSplit =\n                makeInnerSplit(outputField :: outputFields, accumulatedBindings)\n                  (makeConsequent, Split.End)\n              Split.Let(resultSymbol, target, Branch(\n                scrutinee = resultSymbol.safeRef,\n                pattern = matchSuccessPattern(S(outputSymbol :: bindingsSymbol :: Nil)),\n                continuation =\n                  if fieldAliases.isEmpty then innerSplit\n                  else Split.Let(fieldBindingsSymbol, fieldBindingsTerm, innerSplit)\n              ) ~: alternative)): MakeSplit\n      makeMakeSplit(Nil, Nil)\n    case Tuple(leading, spread) => (_, _) => \n      // TODO: Think about how to handle the spread pattern.\n      error(msg\"Tuple patterns are not supported yet.\" -> pattern.toLoc)\n      Split.Else(emptyMatchResult(\"unsupported tuple pattern\"))\n    // The wildcard case always succeeds. Thus, the `alternative` is not used.\n    case Or(Nil) => (makeConsequent, _) =>\n      if isMatchOnly then makeConsequent(scrutinee, rcd()) else\n        val bindings = aliases.map:\n          alias => RcdField(str(alias.name), scrutinee.safeRef)\n        makeConsequent(scrutinee, makeBindings(bindings))\n    // The never case should always fail.\n    case And(Nil) => (_, _) => Split.Else(emptyMatchResult(\"never\"))\n    // The disjunction case should check the result from each pattern in order.\n    case Or(patterns) =>\n      // Make those functions first so that symbols are allocated top-down.\n      val functions = patterns.map:\n        completePattern(_, scrutinee, subScrutinees, aliases)\n      (makeConsequent, alternative) => functions.foldRight(alternative):\n        case (makeSplit, innerSplit) => makeSplit(makeConsequent, innerSplit)\n    // The conjunction case should check all results from patterns and only\n    // return `MatchSuccess` if all patterns succeed.\n    case And(patterns) if isMatchOnly =>\n      val functions = patterns.map:\n        completePattern(_, scrutinee, subScrutinees, Nil)\n      val acceptAll: MakeSplit = (makeConsequent, _) => makeConsequent(scrutinee, rcd())\n      functions.foldRight(acceptAll):\n        case (makeSplit, makeInnerSplit) =>\n        (makeConsequent, alternative) => makeSplit(\n          makeConsequent = (_output, _bindings) =>\n            makeInnerSplit(makeConsequent, Split.End),\n          alternative = alternative)\n    case And(patterns) =>\n      val functions = patterns.map: pattern =>\n        pattern -> completePattern(pattern, scrutinee, subScrutinees, aliases)\n      val makeMakeSplit = functions.foldRight(\n        (allOutputs: Ls[Usable], allBindings: Ls[Usable]) => (\n          (makeConsequent, alternative) =>\n            // Here, we need to make a tuple of all output values of patterns.\n            // Then we merge the bindings of all patterns.\n            val outputSymbol = TempSymbol(N, \"combinedOutput\")\n            val outputTerm = tup(allOutputs.reverseIterator.map(_.use |> fld).toSeq*)\n            val bindingsSymbol = TempSymbol(N, \"combinedBindings\")\n            // I think the bindings do not need to be reversed.\n            val bindingsTerm = makeBindings(allBindings.map:\n              binding => RcdSpread(binding.use))\n            splitLet(outputSymbol, outputTerm) <|:\n              splitLet(bindingsSymbol, bindingsTerm) <|:\n                makeConsequent(outputSymbol, bindingsSymbol)\n        ): MakeSplit\n      ):\n        case ((pattern, makeSplit), makeInnerMakeSplit) =>\n          (accOutputs: Ls[Usable], accBindings: Ls[Usable]) => (\n            (makeConsequent, alternative) => makeSplit(\n              // Get the output and bindings of the current pattern.\n              makeConsequent = (output, bindings) =>\n                val nextBindings =\n                  if aliases.nonEmpty || pattern.symbols.nonEmpty then\n                    bindings :: accBindings\n                  else\n                    accBindings\n                makeInnerMakeSplit(output :: accOutputs, nextBindings)\n                  (makeConsequent, Split.End),\n              alternative = alternative)\n          ): MakeSplit\n      makeMakeSplit(Nil, Nil)\n    case Not(pattern) => (_, _) =>\n      // TODO: Think about how to handle negation patterns.\n      error(msg\"Negation patterns are not supported yet.\" -> pattern.toLoc)\n      Split.Else(emptyMatchResult(\"unsupported negation pattern\"))\n    case Rename(pattern, name) =>\n      completePattern(pattern, scrutinee, subScrutinees,\n        if isMatchOnly then Nil else name :: aliases)\n    case Extract(pattern, correspondence, term) =>\n      if isMatchOnly then\n        completePattern(pattern, scrutinee, subScrutinees, Nil)\n      else\n      // The symbol representing the transform function, which should be\n      // declared at the outermost level.\n        val transformSymbol = TempSymbol(N, \"transform\")\n        // The transform function takes a single record as the argument.\n        val bindingsSymbol = VarSymbol(Ident(\"args\"))\n        val params = paramList(param(bindingsSymbol))\n        // Because we pass the extracted values using recoreds. We need to bind\n        // each property to its corresponding variable which is accessible from\n        // then `term`.\n        val letBindings = pattern.symbols.flatMap: symbol =>\n          val termSymbol = correspondence(symbol)\n          LetDecl(termSymbol, Nil) ::\n          DefineVar(termSymbol, sel(bindingsSymbol.safeRef, termSymbol.name)) :: Nil\n        val makeSplit = completePattern(pattern, scrutinee, subScrutinees, Nil)\n        (makeConsequent, alternative) => Split.Let(\n          sym = transformSymbol,\n          term = Term.Lam(params, Blk(letBindings, term.mkClone)),\n          tail = makeSplit(\n            // The `outputSymbol` is the output of `pattern`.\n            //                vvvvvvvvvvvv\n            makeConsequent = (outputSymbol, bindings) =>\n              // Apply the transform to the bindings.\n              val transformTerm = app(transformSymbol.safeRef,\n                tup(fld(bindings.use)), \"the transform's result\")\n              // Bind the transformation result to a new output symbol.\n              val resultSymbol = TempSymbol(N, \"transformResult\")\n              // Don't forget that current pattern may also have aliases which are\n              // available in some outer transform patterns.\n              val currentBindingsSymbol = TempSymbol(N, \"bindings\")\n              val currentBindings = makeBindings(aliases.map:\n                alias => RcdField(str(alias.name), resultSymbol.safeRef))\n              Split.Let(resultSymbol, transformTerm,\n                Split.Let(currentBindingsSymbol, currentBindings,\n                  makeConsequent(resultSymbol, currentBindingsSymbol))),\n            alternative = alternative))\n  \n  /** Make a human-readable name for patterns that only have class patterns. If\n   *  the patterns are too complicated, we just use the counter. */\n  def makeMultiMatcherName(patterns: Set[Pat]): Str =\n    \"matcher\" +\n    patterns.iterator.mapOption(_.shortName()).fold(multiMatchers.size.toString):\n      _.reverse.mkString(\"__\", \"_\", \"\")\n    + \"$\"\n\nobject Compiler:\n  type Label = Int\n\n  enum ResultMode:\n    case Full, MatchOnly\n  \n  /** A multi-matcher implementation. */\n  type Implementation = (BlockLocalSymbol, ParamList, Term)\n  \n  /** Perform a reverse lookup for a term that references a symbol in the\n    *  current context. */\n  def reference(symbol: ClassSymbol | ModuleOrObjectSymbol | PatternSymbol, loc: Opt[Loc])(using tl: TL)(using Ctx, State): Opt[Term] =\n    /** To make `Lowering` happy about the terms. */\n    def fillImplicitArgs(term: Term): Term = term match\n      case ref: Ref => ref.resolve\n      case sel: SynthSel =>\n        fillImplicitArgs(sel.prefix)\n        sel.resolve\n      case _: Term => term\n    type ClassLikeDefnSymbol = ClassSymbol | ModuleOrObjectSymbol | PatternSymbol\n    def classLikeCandidates(symbol: Symbol): Iterator[ClassLikeDefnSymbol] = symbol match\n      case symbol: ClassLikeDefnSymbol =>\n        Iterator.single(symbol)\n      case member: BlockMemberSymbol =>\n        (member.clsTree.iterator.map(_.symbol.asClsLike) ++\n          member.modOrObjTree.iterator.map(_.symbol.asClsLike) ++\n          member.patTree.iterator.map(_.symbol.asClsLike))\n        .flatten\n      case _ => Iterator.empty\n    def memberReference(\n        ownerRef: Term,\n        key: Str,\n        member: Symbol\n    ): Opt[Term] =\n      classLikeCandidates(member).collectFirst:\n        case candidate if candidate is symbol =>\n          val memberSymbol = candidate.defn.get.bsym\n          SynthSel(ownerRef, new Ident(key).withLoc(loc))(S(memberSymbol), FlowSymbol.synthSel(key), N, S(summon))\n            .resolved(candidate)\n    def ownerMemberReference(owner: ClassSymbol | ModuleOrObjectSymbol): Opt[Term] =\n      val ownerRef = owner.defn.get.bsym.ref()\n      owner.tree.definedSymbols.iterator.map:\n        case (key, member) => memberReference(ownerRef, key, member)\n      .firstSome\n    def findSymbol(elem: Ctx.Elem): Opt[Term] =\n      val direct = elem.symbol.iterator.flatMap(classLikeCandidates).collectFirst:\n        case candidate if candidate is symbol =>\n          elem.ref(new Ident(candidate.nme)).withLoc(loc).resolved(candidate)\n      direct.orElse:\n        elem.symbol.iterator.collectFirst:\n          case owner: (ClassSymbol | ModuleOrObjectSymbol) =>\n            ownerMemberReference(owner)\n        .flatten\n    def ownerChainReference(symbol: ClassLikeDefnSymbol): Opt[Term] =\n      def mkSelect(prefix: Term, member: BlockMemberSymbol, target: ClassLikeDefnSymbol): Term =\n        SynthSel(prefix, new Ident(member.nme).withLoc(loc))(S(member), FlowSymbol.synthSel(member.nme), N, S(summon))\n          .resolved(target)\n      def go(symbol: ClassLikeDefnSymbol): Term =\n        val defn = symbol.defn.getOrElse(lastWords(s\"Missing definition for symbol `${symbol.nme}`.\"))\n        defn.owner match\n          case S(owner: ClassLikeDefnSymbol) =>\n            mkSelect(go(owner), defn.bsym, symbol)\n          case S(owner) =>\n            mkSelect(owner.ref().resolve, defn.bsym, symbol)\n          case N =>\n            defn.bsym.ref(new Ident(defn.bsym.nme).withLoc(loc)).resolved(symbol)\n      symbol.defn.map(_ => go(symbol))\n    @tailrec def go(ctx: Ctx): Opt[Term] =\n      val fromEnv = ctx.env.values.iterator.map(findSymbol).firstSome\n      val fromOuter = ctx.outer.inner.collectFirst:\n          case owner: (ClassSymbol | ModuleOrObjectSymbol) =>\n            ownerMemberReference(owner)\n        .flatten\n      (fromEnv orElse fromOuter) match\n        case S(term) => S(fillImplicitArgs(term))\n        case N => ctx.parent match\n          case N => N\n          case S(parent) => go(parent)\n    go(ctx).orElse(ownerChainReference(symbol))\n  \n  import Pattern.*\n  \n  extension [X](xs: Iterator[X])\n    /** Apply a function to each element of the iterator. If any of the calls\n     *  returns `None`, then the whole function returns `None`. */\n    def mapOption[Y](f: X => Opt[Y]): Opt[Ls[Y]] =\n      xs.foldLeft(S(Nil): Opt[Ls[Y]]):\n        case (S(acc), x) => f(x) match\n          case S(y) => S(y :: acc)\n          case N => N\n        case (N, _) => N\n  \n  /** Canadian Syllabics Pa */\n  val FAKE_LEFT_ANGLE = \"ᐸ\"\n  /** Canadian Syllabics Na */\n  val FAKE_RIGHT_ANGLE = \"ᐳ\"\n  \n  // I learned the characters above from Go's trick:\n  // https://news.ycombinator.com/item?id=14276891\n  // and I introduced more symbols by following the trick.\n  \n  /** Katakana-Hiragana Prolonged Sound Mark */\n  val FAKE_MINUS = \"ー\"\n  /** Lisu Letter Ta */\n  val FAKE_TOP = \"ꓔ\"\n  /** Lisu Letter Tha */\n  val FAKE_BOTTOM = \"ꓕ\"\n  /** Lisu Letter Tone Na Po */\n  val FAKE_COMMA = \"ꓹ\"\n  /** Modifier Letter Left Half Ring */\n  val FAKE_LEFT_PAREN = \"ʿ\"\n  /** Modifier Letter Right Half Ring */\n  val FAKE_RIGHT_PAREN = \"ʾ\"\n  /** Latin Letter Lateral Click */\n  val FAKE_BAR = \"ǁ\"\n  \n  extension (pattern: Pat)\n    /** Make a human-readable short name using Unicode letters, which are\n     *  allowed in in identifiers in the generated code, for patterns. */\n    def shortName(prec: Int = 0): Opt[Str] = pattern match\n      case Literal(IntLit(n)) => S((if n < 0 then FAKE_MINUS else \"\") + n.toString)\n      case Literal(StrLit(s)) => S(s\"str${s.length}\")\n      case Literal(UnitLit(true)) => S(\"null\")\n      case Literal(UnitLit(false)) => S(\"undefined\")\n      case ClassLike(sym, arguments) => arguments.fold(S(sym.nme)): arguments =>\n        arguments.iterator.mapOption:\n          case (_, pat) => pat.shortName(0)\n        .map(_.reverse.mkString(sym.nme + FAKE_LEFT_PAREN, FAKE_COMMA, FAKE_RIGHT_PAREN))\n      case MatchedClassLike(sym, entries) =>\n        entries.iterator.mapOption:\n          case (_, pat) => pat.shortName(0)\n        .map(_.reverse.mkString(sym.nme + FAKE_LEFT_PAREN, FAKE_COMMA, FAKE_RIGHT_PAREN))\n      case Synonym(Instantiation(symbol, patterns)) =>\n        if patterns.isEmpty then S(symbol.nme) else\n          patterns.iterator.mapOption(_.shortName(0)).map:\n            _.reverse.mkString(symbol.nme + FAKE_LEFT_ANGLE, FAKE_COMMA, FAKE_RIGHT_ANGLE)\n      case Or(Nil) => S(FAKE_BOTTOM)\n      case Or(patterns) => patterns.iterator.mapOption(_.shortName(1)).map:\n        _.reverse.mkString(\n          if prec > 0 then FAKE_LEFT_PAREN else \"\",\n          FAKE_BAR,\n          if prec > 0 then FAKE_RIGHT_PAREN else \"\")\n      case And(Nil) => S(FAKE_TOP)\n      case _ => N\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Context.scala",
    "content": "package hkmc2\npackage semantics\npackage ups\n\nimport mlscript.utils.*, shorthands.*\nimport Pattern.{Instantiation, Never}\nimport Message.MessageContext, ucs.bug\nimport sourcecode.{FileName, Line, Name}\n\n/** Before pattern compilation, we monomorphize higher-order patterns into\n  * first-order patterns. `Context` records the correspondence between each\n  * `Pattern.Instantiation` and the resulting `Pat` after monomorphization,\n  * to avoid redundant work.\n  */\nclass Context(val definitions: Map[Pattern.Instantiation, Pat]):\n  def get(instantiation: Instantiation)(using Raise): Pat =\n    definitions.get(instantiation) match\n      case Some(pattern) => pattern\n      case None =>\n        bug(msg\"The pattern is not instantiated.\" -> instantiation.toLoc)\n        Never\n\nobject Context:\n  extension (instantiation: Instantiation)\n    /** Get the body of the instantiated pattern definition. */\n    def body(using Context, Raise): Pat = summon[Context].get(instantiation)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Instantiator.scala",
    "content": "package hkmc2\npackage semantics\npackage ups\n\nimport mlscript.utils.*, shorthands.*\nimport Elaborator.{Ctx, State, ctx}\nimport Message.MessageContext, ucs.{error, warn}\nimport semantics.Pattern as SP, Pattern.*\nimport syntax.Tree, Tree.{StrLit, Ident, IntLit}\nimport collection.mutable.{Map as MutMap, Queue as MutQueue}\nimport utils.TL\nimport scala.collection.immutable.SeqMap\n\nobject Instantiator:\n  type Subst = Map[VarSymbol, Pat]\n\nclass Instantiator(using tl: TL)(using Ctx, State, Raise):\n  import tl.*\n  \n  /** The map contains all instantiated patterns. The key is a pattern symbol\n   *  paired with fully instantiated patterns as arguments. The value is the\n   *  pattern symbol's definition with all parameters have been substituted.\n   *  If the value is `None`, the pattern has not been instantiated yet. */\n  val progress: MutMap[Instantiation, Opt[Pat]] = MutMap.empty\n  \n  /** We instantiate patterns in a breadth-first manner. The queue contains all\n   *  patterns that need to be instantiated. */\n  val worklist: MutQueue[Instantiation] = MutQueue.empty\n  \n  /** Instantiate an anonymous pattern. */\n  def apply(pattern: SP): (Pat, Context) = scoped(\"ucs:instantiation\"):\n    val entryPoint = instantiate(pattern)(using Map.empty)\n    (entryPoint, runInstantiationLoop)\n  \n  /** Run the loop to recursively instantiate needed patterns. */\n  private def runInstantiationLoop: Context =\n    while worklist.nonEmpty do\n      val instantiation = worklist.dequeue()\n      val defn = instantiation.symbol.defn.get\n      // Check if the number of pattern parameters and pattern arguments match.\n      if defn.patternParams.size != instantiation.arguments.size then\n        val parameterCount = \"pattern parameter\" countBy defn.patternParams.size\n        val argumentCount = \"pattern argument\" countBy instantiation.arguments.size\n        error(msg\"Pattern `${instantiation.symbol.nme}` has $parameterCount.\" -> Loc(defn.patternParams),\n          msg\"But $argumentCount were provided.\" -> instantiation.toLoc)\n        // The entire pattern will not be instantiated. Use never instead.\n        progress += (instantiation -> S(Pattern.Never))\n      else\n        val subst = defn.patternParams.iterator.map(_.sym).zip(instantiation.arguments).toMap\n        log(\"Instantiating \" + instantiation.showDbg)\n        val instantiated = instantiate(defn.pattern)(using subst)\n        log(s\"Instantiated ${instantiation.showDbg}\\n\" +\n          s\"arity = ${instantiation.symbol.defn.get.patternParams.size}\\n\" +\n          s\"arguments = ${instantiation.arguments.iterator.map(_.showDbg).mkString(\", \")}\\n\" +\n          s\"instantiated = ${instantiated.showDbg}\")\n        // Add the instantiated pattern to the progress map.\n        progress += (instantiation -> S(instantiated))\n    // Finally, return the synonym representing the entry point pattern and all\n    // instantiated pattern definitions.\n    val definitions = progress.view.mapValues:\n      _.getOrElse(lastWords(\"The pattern is expected to be instantiated.\"))\n    .toMap\n    new Context(definitions)\n  \n  /** Add the instantiation to the queue if it has not been instantiated yet. */\n  def schedule(instantiation: Instantiation): Instantiation =\n    if !progress.contains(instantiation) then\n      progress += (instantiation -> N)\n      worklist.enqueue(instantiation)\n    else\n      log(s\"Already instantiated ${instantiation.showDbg}\")\n    progress(instantiation)\n    instantiation\n  \n  /** Instantiate the given pattern with a substitution map. */\n  def instantiate(pattern: SP)(using subst: Map[VarSymbol, Pat]): Pat = pattern match\n    case SP.Constructor(target, arguments) => target.symbol match\n      // Look up the corresponding pattern from the substitution.\n      case S(symbol: VarSymbol) => subst(symbol)\n      // Recursively instantiate the arguments of constructor patterns.\n      case S(symbol) => symbol.asClsLike match\n        case S(symbol: ClassSymbol) =>\n          val keyedArguments = symbol.defn.get.paramsOpt match\n            case S(ParamList(_, params, _)) => arguments match\n              case S(arguments) =>\n                if params.size != arguments.size then\n                  error(msg\"Class `${symbol.nme}` has ${params.size} parameters.\" -> Loc(params),\n                    msg\"But ${arguments.size} arguments were provided.\" -> Loc(arguments))\n                S(params.iterator.zip(arguments).flatMap:\n                  case (param, argument) if param.flags.isVal =>\n                    // The names are not from the source and are retrieved from\n                    // parameters in class definitions. Therefore, no `Loc`\n                    // should be attached.\n                    S(new Ident(param.sym.id.name) -> instantiate(argument))\n                  case (param, argument) =>\n                    error(msg\"Parameter `${param.sym.nme}` is not accessible.\" -> param.toLoc)\n                    N\n                .to(SeqMap))\n              case N => N // The class has parameters but no arguments are provided.\n            case N => arguments match\n              case N => N // No arguments are provided.\n              case S(arguments) =>\n                error(msg\"Class `${symbol.nme}` has no parameters.\" -> Loc(arguments))\n                N\n          ClassLike(symbol, keyedArguments)\n        case S(symbol: ModuleOrObjectSymbol) =>\n          arguments match\n            case N => ClassLike(symbol, N)\n            case S(arguments) => error(\n              msg\"`${symbol.nme}` is a module, thus it cannot have arguments.\" -> Loc(arguments))\n          ClassLike(symbol, N)\n        case S(symbol: PatternSymbol) =>\n          // TODO(after we defined the semantics of pattern parameters): We need\n          // to partition the arguments into pattern arguments and extraction\n          // arguments here.\n          val patternArguments = arguments.getOrElse(Nil).map(instantiate(_))\n          val instantiation = Instantiation(symbol, patternArguments)(pattern.toLoc)\n          Synonym(schedule(instantiation))\n    case SP.Composition(true, left, right) => instantiate(left) or instantiate(right)\n    case SP.Composition(false, left, right) => instantiate(left) and instantiate(right)\n    case SP.Negation(pattern) => Not(instantiate(pattern))\n    case SP.Wildcard() => Wildcard\n    case SP.Literal(literal) => Literal(literal)\n    case SP.Range(lower, upper, rightInclusive) =>\n      // Currently, we expand the range pattern into a list of literals. After\n      // the `where` clause or chain patterns are implemented, we could directly\n      // expand the range pattern into a range test.\n      (lower, upper) match\n        case (StrLit(lower), StrLit(upper)) =>\n          Or((lower.head to upper.head).map(c => Literal(StrLit(c.toString))).toList)\n        case (IntLit(lower), IntLit(upper)) =>\n          Or((lower to upper).map(i => Literal(IntLit(i))).toList)\n        case _ =>\n          error(msg\"Range patterns are not supported in pattern compilation.\" -> pattern.toLoc)\n          Never\n    case SP.Concatenation(left, right) =>\n      error(msg\"String concatenation is not supported in pattern compilation.\" -> pattern.toLoc)\n      Never\n    case SP.Tuple(leading, spread) =>\n      val instantiatedSpread = spread.map:\n        case (spreadKind, middle, trailing) =>\n          (spreadKind, instantiate(middle), trailing.map(instantiate(_)))\n      Tuple(leading.map(instantiate(_)), instantiatedSpread)\n    case SP.Record(fields) => Record:\n      fields.iterator.map((id, pattern) => (id, instantiate(pattern))).to(SeqMap)\n    case SP.Chain(first, second) =>\n      error(msg\"Pattern chaining is not supported in pattern compilation.\" -> pattern.toLoc)\n      Never\n    case alias @ SP.Alias(pattern, id) => alias.symbolOption match\n      case N => instantiate(pattern)\n      case S(symbol) => Rename(instantiate(pattern), symbol)\n    // Pattern arguments are accessible throughout the pattern.\n    case SP.Transform(pattern, parameters, transform) =>\n      Extract(instantiate(pattern), parameters.toMap, transform)\n    case SP.Annotated(pattern, annotations) =>\n      // Currently, we only support `@compile` annotation, so here we only\n      // check whether this annotation exists, and report an error for all\n      // other annotations.\n      val shouldCompile = annotations.foldLeft(true): (acc, termOrLoc) =>\n        val res = termOrLoc match\n          case R(term) => term.resolvedSym match\n            case S(symbol) if symbol.asBlkMember.exists(_ is ctx.builtins.annotations.compile) => N\n            case S(_) | N => S(term.toLoc)\n          case L(loc) => S(loc)\n        res match\n          case S(loc) =>\n            warn(msg\"This annotation is not supported here.\" -> loc,\n              msg\"Note: Patterns only support the `@compile` annotation.\" -> pattern.toLoc)\n            acc\n          case N => true\n      instantiate(pattern)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ups/Pattern.scala",
    "content": "package hkmc2\npackage semantics\npackage ups\n\n\nimport mlscript.utils.*, shorthands.*\nimport semantics.Pattern as SP\nimport syntax.{Tree, SpreadKind}, Tree.{Ident, StrLit}\nimport Message.MessageContext\nimport ucs.{error, warn}\nimport Context.*\nimport hkmc2.semantics.ups.Pattern.NonCompositional\nimport scala.collection.immutable.SeqMap\n\nprivate[ups] object Kind:\n  sealed trait Specialized extends Expanded\n  sealed trait Expanded extends Complete\n  sealed trait Complete\n\n/** This class `Pattern` with its case classes are the internal representation\n  * of patterns used in pattern compilation. The most important difference\n  * between these and those in the `semantics` package are as follows.\n  * \n  * 1. All symbols in this abstract data type are resolved, including bindings\n  *    used in pattern transformations. Ill-formed bindings have been rejected\n  *    during the elaboration stage.\n  * 2. Higher-order patterns have been instantiated. Diverging patterns have\n  *    been rejected during instantiation. Therefore, all symbols in this abstract\n  *    data type are guaranteed to be first-order.\n  */\nsealed abstract class Pattern[+K <: Kind.Complete] extends AutoLocated:\n  import Pattern.*\n  \n  infix def and[L >: K <: Kind.Complete](that: Pattern[L]): Pattern[L] = this match\n    case And(patterns) => that match\n      case And(patterns2) => And(patterns ++ patterns2)\n      case _ => And[L](patterns appended that)\n    case _ => that match\n      case And(patterns) => And(this :: patterns)\n      case _ => And[L](this :: that :: Nil)\n  \n  infix def or[L >: K <: Kind.Complete](that: Pattern[L]): Pattern[L] = this match\n    case Or(patterns) => that match\n      case Or(patterns2) => Or(patterns ++ patterns2)\n      case _ => Or[L](patterns appended that)\n    case _ => that match\n      case Or(patterns) => Or[L](this :: patterns)\n      case _ => Or[L](this :: that :: Nil)\n  \n  // TODO: Associate with locations.\n  protected def children: Vector[Located] = this match\n    case Literal(lit) => Vector.single(lit)\n    case ClassLike(sym, arguments) => arguments.fold(Vector.empty):\n      _.map((id, p) => p).toVector\n    case MatchedClassLike(sym, entries) => entries.values.toVector\n    case Record(entries) => entries.values.toVector\n    case Tuple(leading, spread) => leading.toVector ++ spread.fold(Vector.empty):\n      case (_, middle, trailing) => middle +: trailing.toVector\n    case And(patterns) => patterns.toVector\n    case Or(patterns) => patterns.toVector\n    case Not(pattern) => Vector.single(pattern)\n    case Rename(pattern, name) => Vector.single(pattern)\n    case Extract(pattern, _, term) => Vector.double(pattern, term)\n    case Synonym(pattern) => pattern.symbol +: pattern.arguments.toVector\n  \n  lazy val symbols: Ls[VarSymbol] = this match\n    case Literal(lit) => Nil\n    case ClassLike(sym, arguments) =>\n      arguments.fold(Nil)(_.values.flatMap(_.symbols).toList)\n    case MatchedClassLike(sym, entries) => entries.values.flatMap(_.symbols).toList\n    case Record(entries) => entries.values.flatMap(_.symbols).toList\n    case Tuple(leading, spread) => leading.flatMap(_.symbols) ::: spread.fold(Nil):\n      case (_, middle, trailing) => middle.symbols ::: trailing.flatMap(_.symbols)\n    case Synonym(_) => Nil\n    case And(patterns) => patterns.flatMap(_.symbols)\n    case Or(patterns) =>\n      // We have checked that bindings are consistent in the elaboration stage.\n      // Inconsistent bindings are not associated with symbols.\n      patterns.find(_ != Never).fold(Nil)(_.symbols)\n    case Not(_) => Nil\n    case Rename(pattern, name) => name :: pattern.symbols\n    case Extract(_, _, _) => Nil\n\n  /** Checks whether a successful match preserves the original scrutinee as the\n    * produced output.\n    *\n    * This property is context-sensitive because `Synonym` nodes must look\n    * through instantiated pattern definitions. Cycles are treated as\n    * preserving so the traversal stays well-founded on recursive patterns.\n    */\n  def preservesOriginalScrutinee(using Context, Raise): Bool =\n    def loop(pattern: Pat, visiting: Set[Instantiation]): Bool = pattern match\n      case Literal(_) => true\n      case ClassLike(_, arguments) =>\n        arguments.fold(true)(_.valuesIterator.forall(loop(_, visiting)))\n      case MatchedClassLike(_, entries) =>\n        entries.valuesIterator.forall(loop(_, visiting))\n      case Record(entries) =>\n        entries.valuesIterator.forall(loop(_, visiting))\n      case Tuple(leading, spread) =>\n        leading.forall(loop(_, visiting)) &&\n          spread.forall: (_, middle, trailing) =>\n            loop(middle, visiting) && trailing.forall(loop(_, visiting))\n      case And(patterns) =>\n        patterns.forall(loop(_, visiting))\n      case Or(patterns) =>\n        patterns.forall(loop(_, visiting))\n      case Not(_) => true\n      case Rename(pattern, _) => loop(pattern, visiting)\n      case Extract(_, _, _) => false\n      case Synonym(instantiation) =>\n        if visiting contains instantiation then true\n        else loop(instantiation.body, visiting + instantiation)\n    loop(this, Set.empty)\n  \n  /** Apply a partial function to every node in the pattern tree. Replace each\n   *  node with the result of the partial function. If the partial function is\n   *  not defined at a node, the node is left unchanged.\n   *  @param f The partial function to apply to each node.\n   */\n  def map[L <: Kind.Complete](f: NonCompositional[K] => Pattern[L]): Pattern[L] = this match\n    case p: NonCompositional[K] => f(p)\n    case And(patterns) => And[L](patterns.map(_.map(f)))\n    case Or(patterns) => Or[L](patterns.map(_.map(f)))\n    case Not(pattern) => Not[L](pattern.map(f))\n    case Rename(pattern, name) => Rename[L](pattern.map(f), name)\n    case Extract(pattern, correspondence, term) =>\n      Extract[L](pattern.map(f), correspondence, term)\n  \n  /** A simplified reduce for ``Pattern``.\n    * It is designed to be used when we want to\n    * compute a single value, starting from the leaves.\n    * It silently goes through ``Not``, ``Extract``, ``Rename`` and ``Synonym``.\n    * The function must provide all the other base cases, and how\n    * a list is merged (for ``And`` and ``Or`` nodes)\n    */\n  def reduce[A](merge: List[A] => A)(f: PartialFunction[Pattern[K], A]): A = this match\n    case p: NonCompositional[K] =>\n      if f.isDefinedAt(p) then f(p) else merge(Nil)\n    case And(patterns) => merge(patterns.map(_.reduce(merge)(f)))\n    case Or(patterns) => merge(patterns.map(_.reduce(merge)(f)))\n    case Not(pattern) => pattern.reduce(merge)(f)\n    case Rename(pattern, _) => pattern.reduce(merge)(f)\n    case Extract(pattern, _, _) => pattern.reduce(merge)(f)\n\n  def heads: Set[Head] = reduce[Set[Head]](_.toSet.flatten):\n    case Literal(lit) => Set(lit)\n    case ClassLike(sym, _) => Set(sym)\n\n  def fields: Set[Ident | Int] = reduce[Set[Ident | Int]](_.toSet.flatten):\n    case MatchedClassLike(_, entries) => entries.keys.toSet\n    case Record(entries) => entries.keys.toSet\n    case Tuple(leading, spread) =>\n      val n = leading.size + spread.fold(0)(_._3.size)\n      val subfields = Range(0, n).toSet[Ident | Int]\n      // if this is strict, then a condition is imposed on field n\n      if spread.isEmpty then subfields + n else subfields\n\n  def collectSubPatterns(field: Ident | Int): Set[Pat] = field match\n    case id: Ident => this.reduce[Set[Pat]](_.toSet.flatten):\n        // TODO: raise a warning\n      case ClassLike(sym, arguments) => /* TODO:raise a warning */ arguments match\n        case None => Set()\n        case Some(arguments) =>\n          arguments.find((id1, _) => id1 === id).map((_, p) => p).toSet\n      case MatchedClassLike(_, entries) => entries.get(id).toSet\n      case Record(entries) => entries.get(id).toSet\n      case Tuple(leading, spread) => Set()\n    case n: Int => this.reduce[Set[Pat]](_.toSet.flatten):\n      case Tuple(leading, S(_, _, trailing)) => trailing.lift(n).toSet\n  \n  /** Simplify the pattern by removing `Never` patterns. */\n  def simplify: Pattern[K] = this match\n    case _: Literal => this\n    case ClassLike(sym, arguments) =>\n      ClassLike(sym, arguments.map(_.map((id, p) => (id, p.simplify))))\n    case MatchedClassLike(sym, entries) =>\n      val simplified = entries.map((id, p) => (id, p.simplify))\n      if simplified.exists((_, p) => p === Never) then Never\n      else MatchedClassLike(sym, simplified)\n    case Record(entries) =>\n      val simplify = entries.map((id, p) => (id, p.simplify))\n      if simplify.exists((_, p) => p === Never) then Never else Record(simplify)\n    case Tuple(leading, N) =>\n      val simplified = leading.map(_.simplify)\n      if simplified contains Never then Never else Tuple(simplified, N)\n    case Tuple(leading, S((spreadKind, middle, trailing))) =>\n      val leading2 = leading.map(_.simplify)\n      val middle2 = middle.simplify\n      val trailing2 = trailing.map(_.simplify)\n      if leading2.contains(Never) || middle2 === Never ||\n        trailing2.contains(Never) then Never\n      else Tuple(leading2, S((spreadKind, middle2, trailing2)))\n    case And(patterns) =>\n      // TODO: Complete the simplification logic here.\n      val simplified = patterns.foldRight(Nil: Ls[Pattern[K]]):\n        case (p, acc) => p.simplify match\n          case `Wildcard` => acc match\n            case `Wildcard` :: _ => acc // One consecutive wildcard is enough.\n            case acc => Wildcard :: acc\n          case simplified => simplified :: acc\n      if simplified contains Never then Never else simplified.foldSingleton(And.apply)(identity)\n    case Or(patterns) =>\n      patterns.foldRight(Nil: Ls[Pattern[K]]):\n        case (p, acc) => p.simplify match\n          case Never => acc match\n            // The list should be a list of non-`Never` patterns or a singleton\n            // list of `Never` pattern.\n            case Nil => Never :: Nil\n            case Never :: Nil | _ => acc\n          // Should we discard the accumulated patterns?\n          // case `Wildcard` => Wildcard :: Nil // Discard the following patterns.\n          case `Wildcard` => acc match\n            case `Never` :: Nil => Wildcard :: Nil\n            case `Wildcard` :: _ => acc // One consecutive wildcard is enough.\n            case acc => Wildcard :: acc\n          case pat => acc match\n            case Nil | Never :: Nil => pat :: Nil\n            case _ => pat :: acc\n      .foldSingleton(Or.apply)(identity)\n    case Not(pattern) => Not(pattern.simplify)\n    case Rename(pattern, name) => Rename(pattern.simplify, name)\n    case Extract(pattern, correspondence, term) => pattern.simplify match\n      case `Never` => Never // Lift up `Never`. Let the caller reduce it.\n      case simplified => Extract(simplified, correspondence, term)\n    case Synonym(sym) => this\n  \n  /** Expand the pattern by replacing any top-level synonym with its body.\n   *  @return the expanded pattern named \"ExPat\" in the paper. */\n  def expand(alreadyExpanded: Set[Instantiation])(using Context, Raise): ExPat = map:\n    case Synonym(instantiation) =>\n      if alreadyExpanded contains instantiation then\n        error(msg\"Expanding this pattern leads to an infinite loop.\" -> instantiation.toLoc)\n        Never // Infinite recursive patterns are considered as never patterns.\n      else\n        // Otherwise, we expand the instantiated pattern definition's body.\n        instantiation.body.expand(alreadyExpanded + instantiation)\n    // I don't know how to make the GADT type checking work here.\n    // case pattern: NonCompositional[K] => pattern // Noop.\n    // case pattern: ExPat => pattern // Noop.\n    case pattern: ClassLike => pattern\n    case pattern: Record => pattern\n    case pattern: Tuple => pattern\n    case pattern: Literal => pattern\n  \n  /** Unwrap `Rename` patterns until we reach a non-`Rename` pattern. Collect\n   *  the symbols on the way. Maybe we can make `Rename` a property of each\n   *  pattern. */\n  def aliases: Ls[VarSymbol] = this match\n    case Rename(pattern, name) => name :: pattern.aliases\n    case _: Pattern[K] => Nil\n  \n  def showDbg(using DebugPrinter): Str = this match\n    case Literal(lit) => lit.idStr\n    case ClassLike(sym, arguments) =>\n      val argumentsText = arguments.fold(\"\"):\n        _.iterator.map((id, p) => s\"${id.name}: ${p.showDbg}\").mkString(\" { \", \", \", \" }\")\n      s\"${sym.nme}$argumentsText\"\n    case MatchedClassLike(sym, entries) =>\n      val argumentsText = entries.iterator.map:\n        case (id, p) => s\"${id.name}: ${p.showDbg}\"\n      .mkString(\" { \", \", \", \" }\")\n      s\"${sym.nme}$argumentsText\"\n    case Record(entries) =>\n      if entries.isEmpty then \"{}\" else entries.iterator.map:\n        case (id, p) => s\"${id.name}: ${p.showDbg}\"\n      .mkString(\"{ \", \", \", \" }\")\n    case Tuple(leading, N) =>\n      leading.iterator.map(_.showDbg).mkString(\"[\", \", \", \"]\")\n    case Tuple(leading, S(spreadKind, spread, trailing)) =>\n      val leadingItems = leading.iterator.map(_.showDbg)\n      val spreadItem = Iterator.single(spreadKind.str + spread.showDbg)\n      val trailingItems = trailing.iterator.map(_.showDbg)\n      (leadingItems ++ spreadItem ++ trailingItems).mkString(\"[\", \", \", \"]\")\n    case And(Nil) => \"⊤\"\n    case And(pattern :: Nil) => pattern.showDbg\n    case And(patterns) =>\n      patterns.map(_.showDbg).mkString(\"(\", \" ∧ \", \")\")\n    case Or(Nil) => \"⊥\"\n    case Or(pattern :: Nil) => pattern.showDbg\n    case Or(patterns) =>\n      patterns.map(_.showDbg).mkString(\"(\", \" ∨ \", \")\")\n    case Not(pattern) => s\"!${pattern.showDbg}\"\n    case Rename(Or(Nil), name) => name.name\n    case Rename(pattern, name) => s\"${pattern.showDbg} as $name\"\n    case Extract(pattern, _, term) => s\"${pattern.showDbg} => ${term.showDbg}\"\n    case Synonym(sym) => sym.showDbg\n\nobject Pattern:\n  sealed trait NonCompositional[+K <: Kind.Complete] extends Pattern[K]\n  \n  final case class Literal(lit: syntax.Literal) extends NonCompositional[Kind.Expanded]\n\n  /** Represents a constructor or a class, possibly with arguments.\n    * @param sym the class symbol corresponding to the class or the constructor\n    * @param arguments is None if no arguments were provided (as\n    * in ``Foo``, and is Some if there were arguments provided, even if\n    *  it is an empty argument list, e.g. ``Bar()``)\n    *\n    * the list contains the patterns in the order with which they were given\n    * along with the corresponding identifier, even if it was not present before.\n    * e.g. if we have a class defintion ``class L = Nil | Cons(hd: Int, tl: L)``\n    * then the pattern ``Cons(foo, bar)`` is expected to be\n    * ``ClassLike(sym=Cons, arguments=Some(List((hd, foo), tl, bar)))``\n    */\n  final case class ClassLike(\n      sym: ClassLikeSymbol,\n      arguments: Opt[SeqMap[Ident, Pat]]\n  ) extends NonCompositional[Kind.Expanded]\n\n  /** Represents a constructor pattern after its head has already been matched\n    * by specialization.\n    *\n    * We cannot reuse `ClassLike` here because that would still mean “a class\n    * head that must participate in head-based specialization”, which is no\n    * longer true at this stage. We also cannot collapse it to `Record`,\n    * because matching the remaining fields may still need to rebuild an output\n    * value of the original constructor, so the constructor symbol must be\n    * preserved.\n    *\n    * In other words, this node denotes the intermediate state where the class\n    * identity is already known, but the field subpatterns still need to be\n    * matched and may determine whether the final output reuses the original\n    * scrutinee or rebuilds a fresh instance of the same class.\n    */\n  final case class MatchedClassLike(\n      sym: ClassLikeSymbol,\n      entries: SeqMap[Ident, Pat]\n  ) extends NonCompositional[Kind.Specialized]\n\n  final case class Record(\n      entries: SeqMap[Ident, Pat]\n  ) extends NonCompositional[Kind.Specialized]\n\n  /** @param entries is the ordered list of patterns, from left to right\n    * @param strict is true if we matchexactly these fields, and no more,\n    * it is false, if we are allowed to have more fields.\n    *\n    * Tuple([p0, ..., p(n-1)], true) <~> {0:p0, ..., n-1: p(n-1)} & Not({n:_})\n    * Tuple([p0, ..., p(n-1)], false) <~> {0:p0, ..., n-1: p(n-1)}\n    */\n  final case class Tuple(\n      leading: List[Pat],\n      spread: Opt[(SpreadKind, Pat, List[Pat])],\n  ) extends NonCompositional[Kind.Specialized]\n  \n  /** Represents a pattern synonym.\n    * @param sym the pattern symbol corresponding\n    */\n  final case class Synonym(pattern: Instantiation) extends NonCompositional[Kind.Complete]\n  \n  // * Pattern kinds propagate through the following cases.\n  final case class And[+K <: Kind.Complete](patterns: List[Pattern[K]]) extends Pattern[K]\n  final case class Or[+K <: Kind.Complete](patterns: List[Pattern[K]]) extends Pattern[K]\n  final case class Not[+K <: Kind.Complete](pattern: Pattern[K]) extends Pattern[K]\n  final case class Rename[+K <: Kind.Complete](pattern: Pattern[K], name: VarSymbol) extends Pattern[K]\n  /**\n    * Similar to `Pattern.Transform`.\n    *\n    * @param pattern The pattern to be matched against.\n    * @param correspondence The correspondence between symbols in the pattern\n    *        and symbols in the transformation term.\n    * @param term The term to be applied to the extracted values.\n    */\n  final case class Extract[+K <: Kind.Complete](\n      pattern: Pattern[K],\n      correspondence: Map[VarSymbol, VarSymbol],\n      term: Term\n  ) extends Pattern[K]\n  \n  val Wildcard = Or(Nil)\n  \n  val Never = And(Nil)\n  \n  type Head = syntax.Literal | ClassLikeSymbol\n  \n  /** A representation of fully instantiated first-order patterns. */\n  final case class Instantiation(\n      symbol: PatternSymbol,\n      arguments: Ls[Pat]\n  )(val toLoc: Opt[Loc]) extends Located:\n    def showDbg(using DebugPrinter): Str =\n      val argumentsText = if arguments.isEmpty then \"\" else\n        arguments.iterator.map(_.showDbg).mkString(\"[\", \", \", \"]\")\n      s\"${symbol.nme}$argumentsText\"\n\ntype Pat = Pattern[Kind.Complete]\n\ntype ExPat = Pattern[Kind.Expanded]\n\ntype SpPat = Pattern[Kind.Specialized]\n\nimport Pattern.*\n\nextension (pattern: ExPat)\n  /** Modifies the pattern under the assumption that the scrutinee matches the\n   *  given literal. We decide to not care about literals with fields. (For\n   *  example, wrapped primitives with properties in JavaScript.) */\n  def specialize(lit: syntax.Literal): SpPat = pattern.map:\n    case Literal(`lit`) => Wildcard\n    case _: (Literal | ClassLike) => Never\n    case pattern: (Record | Tuple) => pattern\n  \n  /** Modifies the pattern under the assumption that the scrutinee matches the\n   *  given class. */\n  def specialize(symbol: ClassLikeSymbol): SpPat = pattern.map:\n    case Literal(_) => Never\n    /** Note that `ClassLike` corresponds the syntax sugar of class patterns\n     *  intersected with record patterns. So, we need to leave the arguments\n     *  part unchanged. If there's no arguments, we return `Wildcard`. */\n    case ClassLike(`symbol`, arguments) =>\n      arguments.fold(Wildcard)(MatchedClassLike(symbol, _))\n    case ClassLike(_, _) => Never\n    case pattern: (MatchedClassLike | Record | Tuple) => pattern\n  \n  /** Modifies the pattern under the assumption that the scrutinee matches the\n   *  given literal or class. */\n  def specialize(head: Option[Head]): SpPat = head match\n    case Some(h: syntax.Literal) => pattern.specialize(h)\n    case Some(h: ClassLikeSymbol) => pattern.specialize(h)\n    case None => pattern.map:\n      case _: (Literal | ClassLike) => Never\n      case pattern: (Record | Tuple) => pattern\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/semantics/ups/SplitCompiler.scala",
    "content": "package hkmc2\npackage semantics\npackage ups\n\nimport mlscript.utils.*, shorthands.*\nimport Message.MessageContext\nimport ucs.{TermSynthesizer, FlatPattern, error, warn, safeRef}, ucs.extractors.*\nimport syntax.{Fun, Keyword, Tree}, Tree.{Ident, StrLit}, Keyword.{`as`, `=>`}\nimport collection.mutable.{Buffer, HashMap}, collection.immutable.SeqMap\nimport Elaborator.{Ctx, State, ctx}, utils.TL\nimport semantics.Pattern as SP // \"SP\" is short for \"semantic patterns\"\nimport Term.Ref\nimport ups.Compiler.ResultMode\n\nobject SplitCompiler:\n  /** A class that can generate `Ref` to the scrutinee. It also comes with a few\n   *  mutable maps to reuse sub-scrutinees. Memoization of sub-scrutinees help\n   *  the normalization to merge let bindings from different branches.\n   */\n  sealed abstract class Scrut:\n    private val subScrutinees: HashMap[ClassSymbol | PatternSymbol, Buffer[SymbolScrut[?]]] = HashMap.empty\n    private val fields: HashMap[Ident, SymbolScrut[?]] = HashMap.empty\n    private val tupleLead: HashMap[Int, SymbolScrut[?]] = HashMap.empty\n    private val tupleLast: HashMap[Int, SymbolScrut[?]] = HashMap.empty\n    \n    def apply(): Term.Ref\n\n    def getSubScrutinee(cs: ClassSymbol | PatternSymbol)(i: Int)(using State): SymbolScrut[?] =\n      val scrutinees = subScrutinees.getOrElseUpdate(cs, Buffer.empty)\n      while scrutinees.size <= i do\n        scrutinees += TempSymbol(N, s\"arg$$${cs.nme}$$${scrutinees.size}$$\").toScrut\n      scrutinees(i)\n    def getTupleLeadSubScrutinee(index: Int)(using State): SymbolScrut[?] =\n      tupleLead.getOrElseUpdate(index, TempSymbol(N, s\"element$index$$\").toScrut)\n    def getTupleLastSubScrutinee(index: Int)(using State): SymbolScrut[?] =\n      tupleLast.getOrElseUpdate(index, TempSymbol(N, s\"lastElement$index$$\").toScrut)\n    def getFieldScrutinee(fieldName: Ident)(using State): SymbolScrut[?] =\n      fields.getOrElseUpdate(fieldName, TempSymbol(N, s\"field_${fieldName.name}$$\").toScrut)\n  \n  object Scrut:\n    def from(ref: Term.Ref): RefScrut = RefScrut(() => ref)\n  \n  class RefScrut(make: () => Term.Ref) extends Scrut:\n    def apply(): Ref = make()\n  \n  class SymbolScrut[SymbolType <: BlockLocalSymbol](val symbol: SymbolType) extends Scrut:\n    def apply(): Ref = symbol.ref()\n  \n  extension [SymbolType <: BlockLocalSymbol](symbol: SymbolType)\n    def toScrut: SymbolScrut[SymbolType] = SymbolScrut(symbol)\n  \n  type BindingMap = SeqMap[VarSymbol, Scrut]\n  \n  type SplitSequel[Output] = (makeConsequent: (Output, BindingMap) => Split, alternative: Split) => Split\n  \n  extension [Output](sequel: SplitSequel[Output])\n    def map[Result](f: Output => Result): SplitSequel[Result] = (makeConsequent, alternative) =>\n      sequel((output, bindings) => makeConsequent(f(output), bindings), alternative)\n  \n  type MakeConsequent = (output: Scrut, bindings: BindingMap) => Split\n  \n  /** The continuation function returned by `makeMatchSplit`.\n   *  Note that `alternative` does not serve as the fallback split. It means the\n   *  next split we should try when the current split fails.\n   *  \n   *  Note: I realized that it would make more sense to let `output` be a term.\n   *  Because in some cases, the output is not used in the consequent split.\n   *  For example, the output of the `negation` pattern is discarded.\n   *  \n   *  The `bindings` parameter is used to denote the variables that are bound\n   *  during the matching process. The key is the pattern's variable symbol and\n   *  the value is the local symbol that represents the matched values.\n   */\n  type MakeSplit = (makeConsequent: MakeConsequent, alternative: Split) => Split\n  \n  object RejectSplit extends ((MakeConsequent, Split) => Split):\n    def apply(makeConsequent: MakeConsequent, alternative: Split): Split = alternative\n  \n  extension (first: MakeSplit)\n    def | (second: MakeSplit): MakeSplit = (makeConsequent, alternative) =>\n      first(makeConsequent, second(makeConsequent, alternative))\n    def & (second: MakeSplit): SplitSequel[(Scrut, Scrut)] = (makeConsequent, alternative) =>\n      first(\n        (firstOutput, firstBindings) => second(\n          (secondOutput, secondBindings) => makeConsequent(\n            (firstOutput, secondOutput),\n            firstBindings ++ secondBindings // Do we need to duplicate the bindings?\n          ),\n          alternative),\n        alternative)\n  \n  type MakePrefixConsequent = (consumedOutput: Scrut, remainingOutput: Scrut, bindings: BindingMap) => Split\n  \n  /** The continuation function returned by `makeStringPrefixMatchSplit`. It\n   *  represents functions making splits that match any given string's prefix.\n   */\n  type MakePrefixSplit = (makeConsequent: MakePrefixConsequent, alternative: Split) => Split\n  \n  object RejectPrefixSplit extends ((MakePrefixConsequent, Split) => Split):\n    def apply(makeConsequent: MakePrefixConsequent, alternative: Split): Split = alternative\n    \n  extension (makePrefixSplit: MakePrefixSplit)\n    /** Build another `MakePrefixSplit` if the function does not reject. */\n    transparent inline def whenAccept(derivedFunction: => MakePrefixSplit): MakePrefixSplit =\n      if makePrefixSplit is RejectPrefixSplit then RejectPrefixSplit else derivedFunction\n  \n  /** A lazily created scrutinee. */\n  class LazyScrut(nameHint: Opt[Str] = N)(using State) extends Scrut:\n    private var _hasBeenUsed = false\n    private lazy val symbol =\n      _hasBeenUsed = true\n      TempSymbol(N, nameHint.getOrElse(\"output\"))\n    def apply(): Ref = symbol.safeRef\n    def toList: Ls[TempSymbol] = if _hasBeenUsed then symbol :: Nil else Nil\n    def toLet(term: => Term, tail: Split): Split =\n      if _hasBeenUsed then Split.Let(symbol, term, tail) else tail\n\nimport SplitCompiler.*\n\n/** This class compiles a pattern to a split that matches the pattern. */\nclass SplitCompiler(using tl: TL)(using State, Ctx, Raise) extends TermSynthesizer:\n  import tl.*, SP.*\n  \n  private lazy val lteq = State.builtinOpsMap(\"<=\")\n  private lazy val lt = State.builtinOpsMap(\"<\")\n  private lazy val add = State.builtinOpsMap(\"+\")\n\n  private def carriesExtractionSlots(context: Context): Bool =\n    context.definitions.keysIterator.exists:\n      _.symbol.defn.exists(_.extractionParams.nonEmpty)\n\n  /** Conservatively checks whether a source-level pattern preserves its own\n    * scrutinee as the produced output.\n    */\n  private def preservesOriginalScrutinee(pattern: SP): Bool =\n    def loop(\n        pattern: SP,\n        parameters: Map[VarSymbol, Bool],\n        visiting: Set[PatternSymbol]\n    ): Bool = pattern match\n      case Constructor(target, arguments) => target.resolvedSym match\n        case S(symbol: VarSymbol) =>\n          arguments.isEmpty && parameters.getOrElse(symbol, false)\n        case symbolOption => symbolOption.flatMap(_.asClsLike) match\n          case S(_: ClassSymbol | _: ModuleOrObjectSymbol) =>\n            arguments.forall(_.forall(loop(_, parameters, visiting)))\n          case S(symbol: PatternSymbol) => symbol.defn match\n            case N => false\n            case S(defn) =>\n              if visiting contains symbol then true\n              else\n                val allArguments = arguments.getOrElse(Nil)\n                if allArguments.length < defn.patternParams.length then false\n                else\n                  val patternArguments = allArguments.take(defn.patternParams.length)\n                  val parameterBindings =\n                    defn.patternParams.iterator.map(_.sym).zip(\n                      patternArguments.iterator.map(loop(_, parameters, visiting))\n                    ).toMap\n                  loop(defn.pattern, parameterBindings, visiting + symbol)\n          case N => false\n      case Composition(_, left, right) =>\n        loop(left, parameters, visiting) && loop(right, parameters, visiting)\n      case Negation(_) => true\n      case Wildcard() | Literal(_) | Range(_, _, _) => true\n      case Concatenation(left, right) =>\n        loop(left, parameters, visiting) && loop(right, parameters, visiting)\n      case Tuple(leading, spread) =>\n        leading.forall(loop(_, parameters, visiting)) &&\n          spread.forall: (_, middle, trailing) =>\n            loop(middle, parameters, visiting) &&\n              trailing.forall(loop(_, parameters, visiting))\n      case Record(fields) =>\n        fields.iterator.forall((_, pattern) => loop(pattern, parameters, visiting))\n      case Chain(first, second) =>\n        loop(first, parameters, visiting) && loop(second, parameters, visiting)\n      case Alias(pattern, _) =>\n        loop(pattern, parameters, visiting)\n      case Transform(_, _, _) => false\n      case Annotated(pattern, _) =>\n        loop(pattern, parameters, visiting)\n      case Guarded(pattern, _) =>\n        loop(pattern, parameters, visiting)\n    loop(pattern, Map.empty, Set.empty)\n\n  private def explicitlyDiscardsOutput(pattern: SP): Bool = pattern match\n    case Alias(_, id) if id.name == \"_\" => true\n    case Chain(_, Wildcard()) => true\n    case Annotated(pattern, _) => explicitlyDiscardsOutput(pattern)\n    case _ => false\n\n  private def warnOnDiscardedExtractionOutputs(\n      patternSymbol: PatternSymbol,\n      extractionMatches: Opt[Ls[SP]]\n  ): Unit =\n    extractionMatches.foreach(_.foreach: subPattern =>\n      if !explicitlyDiscardsOutput(subPattern) &&\n          !preservesOriginalScrutinee(subPattern)\n      then\n        warn(\n          msg\"This extraction argument's transformation result is discarded by pattern `${patternSymbol.nme}`.\" -> subPattern.toLoc,\n          msg\"Write `... as _` to discard it explicitly.\" -> N\n        ))\n\n  private def warnOnDiscardedExtractionOutputs(pattern: SP): Unit = pattern match\n    case Constructor(target, arguments) =>\n      target.resolvedSym.flatMap(_.asPat).foreach: patternSymbol =>\n        patternSymbol.defn.foreach: defn =>\n          val (_, extractionMatches, _) =\n            matchParametersWithArguments(defn, arguments, reportErrors = false)\n          warnOnDiscardedExtractionOutputs(patternSymbol, extractionMatches)\n      arguments.foreach(_.foreach(warnOnDiscardedExtractionOutputs))\n    case Composition(_, left, right) =>\n      warnOnDiscardedExtractionOutputs(left)\n      warnOnDiscardedExtractionOutputs(right)\n    case Negation(pattern) =>\n      warnOnDiscardedExtractionOutputs(pattern)\n    case Concatenation(left, right) =>\n      warnOnDiscardedExtractionOutputs(left)\n      warnOnDiscardedExtractionOutputs(right)\n    case Tuple(leading, spread) =>\n      leading.foreach(warnOnDiscardedExtractionOutputs)\n      spread.foreach: (_, middle, trailing) =>\n        warnOnDiscardedExtractionOutputs(middle)\n        trailing.foreach(warnOnDiscardedExtractionOutputs)\n    case Record(fields) =>\n      fields.iterator.foreach((_, pattern) => warnOnDiscardedExtractionOutputs(pattern))\n    case Chain(first, second) =>\n      warnOnDiscardedExtractionOutputs(first)\n      warnOnDiscardedExtractionOutputs(second)\n    case Alias(pattern, _) =>\n      warnOnDiscardedExtractionOutputs(pattern)\n    case Transform(pattern, _, _) =>\n      warnOnDiscardedExtractionOutputs(pattern)\n    case Annotated(pattern, _) =>\n      warnOnDiscardedExtractionOutputs(pattern)\n    case Guarded(pattern, _) =>\n      warnOnDiscardedExtractionOutputs(pattern)\n    case Wildcard() | Literal(_) | Range(_, _, _) => ()\n\n  private def hasExplicitExtractionMatches(scrutinee: Scrut, pattern: SP): Bool = pattern match\n    case Constructor(target, arguments) => target.resolvedSym.flatMap(_.asPat).exists: patternSymbol =>\n      val defn = patternSymbol.defn.getOrElse:\n        lastWords(s\"Pattern `${patternSymbol.nme}` has not been elaborated.\")\n      val (_, extractionMatches, _) =\n        matchParametersWithArguments(defn, arguments, reportErrors = false)\n      extractionMatches.exists(_.nonEmpty)\n    case _ => false\n  \n  private def makeRangeTest(scrut: Scrut, lo: syntax.Literal, hi: syntax.Literal, rightInclusive: Bool, innerSplit: Split) =\n    def scrutFld = fld(scrut())\n    val test1 = app(lteq.safeRef, tup(fld(Term.Lit(lo)), scrutFld), \"isGreaterThanLower\")\n    val upperOp = if rightInclusive then lteq else lt\n    val test2 = app(upperOp.safeRef, tup(scrutFld, fld(Term.Lit(hi))), \"isLessThanUpper\")\n    plainTest(test1, \"isGreaterThanLower\")(plainTest(test2, \"isLessThanUpper\")(innerSplit))\n  \n  extension (patterns: Ls[SP])\n    /**\n     * Folds over sub-patterns to create a consequent making function with\n     * accumulated sub-scrutinees. This function processes a list of patterns by\n     * creating a consequent making function that applies consequent making\n     * function of each sub-pattern from right to left.\n     * \n     * Mental model example: for patterns `[p1, p2, p3]` with sub-scrutinees\n     * `[s1, s2, s3]`, this function creates:\n      \n     * ```\n     * s1 is p1 and s2 is p2 and s3 is p3 and\n     *   {| z(outerOutput + bindings1 + bindings2 + bindings3) |}\n     * ```\n     * \n     * @param z The initial consequent making function to start the fold with.\n     * @param getSubScrutinee To get a scrutinee for a given pattern index.\n     * @return A tuple containing:\n     *         - A list of `(BlockLocalSymbol, Option[Loc])` pairs for each\n     *           sub-scrutinee and its location.\n     *         - A `MakeConsequent` function that creates the nested match split.\n     */\n    def folded(z: MakeConsequent)(getSubScrutinee: Int => SymbolScrut[?])\n    : (Ls[(BlockLocalSymbol, Opt[Loc])], MakeConsequent) =\n      patterns.iterator.zipWithIndex.foldRight((Nil, z)):\n        case ((subPattern, index), (accSubScrutinees, makeInnerSplit)) =>\n          val subScrutinee = getSubScrutinee(index)\n          val makeThisSplit: MakeConsequent = (outerOutput, outerBindings) =>\n            makeMatchSplit(subScrutinee, subPattern, false)(\n              // Note that the individual pattern's output is ignored because\n              // in real world it's hard to synthesized a valid object if the\n              // pattern carries some transformation.\n              (_elementOutput, elementBindings) => makeInnerSplit(\n                outerOutput, // TODO: Combine `outerOutput` and `elementOutput`\n                outerBindings ++ elementBindings),\n              Split.End)\n          ((subScrutinee.symbol -> subPattern.toLoc) :: accSubScrutinees, makeThisSplit)\n    \n    /** Same as the other overload, but for `MakePrefixConsequent`. */\n    def folded(z: MakePrefixConsequent)(getSubScrutinee: Int => SymbolScrut[?])\n    : (Ls[(BlockLocalSymbol, Opt[Loc])], MakePrefixConsequent) =\n      patterns.iterator.zipWithIndex.foldRight((Nil, z)):\n        case ((subPattern, index), (accSubScrutinees, makeInnerSplit)) =>\n          val subScrutinee = getSubScrutinee(index)\n          val makeThisSplit: MakePrefixConsequent = (outerOutput, outerRemaining, outerBindings) =>\n            makeStringPrefixMatchSplit(subScrutinee, subPattern)(\n              // Note that the individual pattern's output is ignored because\n              // in real world it's hard to synthesized a valid object if the\n              // pattern carries some transformation.\n              (_elementOutput, _elementRemaining, elementBindings) => makeInnerSplit(\n                outerOutput, // TODO: Combine `outerOutput` and `elementOutput`\n                outerRemaining, // TODO: Combine `outerRemaining` and `elementRemaining`\n                outerBindings ++ elementBindings),\n              Split.End)\n          ((subScrutinee.symbol -> subPattern.toLoc) :: accSubScrutinees, makeThisSplit)\n  \n    def makePatternBindings(using State): Ls[(TempSymbol, SP)] =\n      patterns.iterator.zipWithIndex.map:\n        case (pattern, index) => new TempSymbol(N, s\"patternArgument${index}$$\") -> pattern\n      .toList\n  \n  /**\n    * Check whether the number of parameters in class-like patterns matches the\n    * number in their definition, and whether each parameter is accessible.\n    *\n    * @param scrutinee the scrutinee\n    * @param classTerm the term that resolves to the class\n    * @param classSymbol the symbol for the class to be matched\n    * @param arguments sub-patterns \n    */\n  private def makeMatchClassSplit(\n      scrutinee: Scrut,\n      classTerm: Term,\n      classSymbol: ClassSymbol,\n      arguments: Opt[Ls[SP]],\n      outputNeeded: Bool\n  ): MakeSplit =\n    // Obtain the `classHead` used for error reporting and the parameter list\n    // from the class definitions.\n    val (classHead, paramsOpt) = classSymbol.defn match\n      case N => lastWords(s\"Class ${classSymbol.name} does not have a definition\")\n      // Use the constructor pattern's location for error reporting.\n      case S(cd) => new Tree.Ident(classSymbol.name).withLoc(classTerm.toLoc) -> cd.paramsOpt\n    // Check if the number of arguments matches the number of parameters.\n    val allArguments = arguments.getOrElse(Nil)\n    val rebuildNeeded = outputNeeded && allArguments.exists(arg => !preservesOriginalScrutinee(arg))\n    def reportInaccessibleParameter(param: Param, arg: SP): Unit =\n      val inaccessible = msg\"because the corresponding parameter `${param.sym.name}` is not publicly accessible\" -> param.sym.toLoc\n      if rebuildNeeded then\n        error(\n          msg\"This pattern cannot be matched\" -> arg.toLoc,\n          inaccessible,\n          msg\"because rebuilding the matched `${classSymbol.name}` value requires reading every constructor argument\" -> classHead.toLoc,\n          msg\"Suggestion: mark this parameter with `val` so it becomes accessible\" -> N\n        )\n      else\n        error(\n          msg\"This pattern cannot be matched\" -> arg.toLoc,\n          inaccessible,\n          msg\"Suggestion: use a wildcard pattern `_` in this position\" -> N,\n          msg\"Suggestion: mark this parameter with `val` so it becomes accessible\" -> N\n        )\n    val successful = paramsOpt match\n      case S(paramList) => arguments match\n        case S(args) =>\n          // Check the number of parameters is correct.\n          if args.size != paramList.params.size then\n            val loc = Loc(args) orElse classTerm.toLoc\n            error:\n              if paramList.params.isEmpty then\n                msg\"The constructor does not take any arguments but found ${\n                  \"argument\" countBy args.size}.\" -> loc\n              else\n                msg\"Expected ${\"argument\" countBy paramList.params.size\n                }, but found ${if args.size < paramList.params.size then \"only \" else \"\"\n                }${\"argument\" countBy args.size}.\" -> loc\n          // Check the fields are accessible.\n          paramList.params.iterator.zip(args).map:\n            case (param @ Param(flags, _, _, _), Wildcard()) if !flags.isVal && !rebuildNeeded => true\n            case (param @ Param(flags, _, _, _), arg) if !flags.isVal =>\n              reportInaccessibleParameter(param, arg)\n              false\n            case _ => true\n          // If the number of arguments are more than the number of parameters,\n          // or one of parameters is incessible, we cannot make the branch.\n          .foldLeft(args.size <= paramList.params.size)(_ && _)\n        case N => arguments match\n          case S(args) =>\n            error(msg\"class ${classSymbol.name} does not have parameters\" -> classHead.toLoc,\n              msg\"but the pattern has ${\"sub-pattern\" countBy args.size}\" -> Loc(args))\n            false\n          case N => true // No parameters, no arguments. This is fine.\n      case N => arguments match // No parameter lists. Check if scruts are empty.\n        case S(Nil) =>\n          error(msg\"Class ${classSymbol.name} does not have a parameter list\" -> classTerm.toLoc)\n          true\n        case S(args) =>\n          error(msg\"Class ${classSymbol.name} does not have a parameter list\" -> classTerm.toLoc,\n            msg\"but the pattern has ${\"sub-pattern\" countBy args.size}\" -> Loc(args))\n          false\n        case N => true\n    if successful then (makeConsequent, alternative) =>\n      val argumentInfos = allArguments.iterator.zipWithIndex.map:\n        case (argument, index) =>\n          val subScrutinee = scrutinee.getSubScrutinee(classSymbol)(index)\n          (argument, subScrutinee, preservesOriginalScrutinee(argument))\n      .toList\n      val destructuringArguments = arguments.map(_.iterator.zipWithIndex.map:\n        case (argument, index) => (scrutinee.getSubScrutinee(classSymbol)(index).symbol, argument.toLoc)\n      .toList)\n      def buildConsequent(\n          infos: Ls[(SP, SymbolScrut[?], Bool)],\n          rebuiltArguments: Ls[Scrut],\n          bindings: BindingMap\n      ): Split = infos match\n        case Nil =>\n          if rebuildNeeded then\n            val rebuiltOutput = new LazyScrut(S(s\"${classSymbol.name}Output\"))\n            val rebuiltTerm = `new`(\n              classTerm,\n              tup(rebuiltArguments.reverseIterator.map(scrut => scrut() |> fld).toSeq*) :: Nil,\n              s\"rebuilt ${classSymbol.name}\"\n            )\n            rebuiltOutput.toLet(rebuiltTerm, makeConsequent(rebuiltOutput, bindings))\n          else\n            makeConsequent(scrutinee, bindings)\n        case (argument, subScrutinee, preserves) :: rest =>\n          val childOutputNeeded = rebuildNeeded && !preserves\n          makeMatchSplit(subScrutinee, argument, childOutputNeeded)(\n            (argumentOutput, argumentBindings) =>\n              val nextArguments =\n                if rebuildNeeded then\n                  (if preserves then subScrutinee else argumentOutput) :: rebuiltArguments\n                else\n                  rebuiltArguments\n              buildConsequent(rest, nextArguments, bindings ++ argumentBindings),\n            Split.End)\n      val pattern = FlatPattern.ClassLike(classTerm, classSymbol, destructuringArguments, false)(Tree.Dummy)\n      Branch(scrutinee(), pattern, buildConsequent(argumentInfos, Nil, SeqMap.empty)) ~: alternative\n    else RejectSplit\n  \n  /**\n    * Make a split that matches the given object. Meanwhile, check whether the\n    * object pattern has an argument list.\n    *\n    * @param scrutinee the scrutinee\n    * @param objectSymbol the symbol for the object\n    * @param arguments objects do not have parameters, thus the arguments are\n    *                  only used for error checking\n    */\n  private def makeMatchObjectSplit(\n      patternLoc: Opt[Loc],\n      scrutinee: Scrut,\n      objectTerm: Term,\n      objectSymbol: ModuleOrObjectSymbol,\n      arguments: Opt[Ls[SP]]\n  ): MakeSplit =\n    val shouldReject = arguments match\n      case S(Nil) =>\n        // The object pattern comes with an unnecessary parameter list, but it\n        // can still be compiled.\n        error(msg\"`${objectSymbol.name}` is an object.\" -> objectSymbol.id.toLoc,\n          msg\"Its pattern cannot have an argument list.\" -> patternLoc)\n        false\n      case S(_ :: _) =>\n        // One or more parameters are provided, thus we cannot compile the\n        // following consequent split.\n        error(msg\"`${objectSymbol.name}` is an object.\" -> objectSymbol.id.toLoc,\n          msg\"Its pattern cannot have arguments.\" -> patternLoc)\n        true\n      case N => false\n    if shouldReject then RejectSplit else (makeConsequent, alternative) =>\n      val outputSymbol = new LazyScrut()\n      val consequent = makeConsequent(outputSymbol, SeqMap.empty)\n      val pattern = FlatPattern.ClassLike(objectTerm, objectSymbol, N, false)(Tree.Dummy)\n      Branch(scrutinee(), pattern, outputSymbol.toLet(scrutinee(), consequent)) ~: alternative\n  \n  /**\n    * When a scrutinee is matched with a defined pattern `P`, this method checks\n    * whether the arguments provided by the user (both pattern arguments and\n    * extraction parameters) match the parameters in the definition of `P`. This\n    * part of the logic is used by both efficiently compiled patterns and\n    * naively compiled patterns to ensure the consistency of diagnostics.\n    *\n   * @param defn the pattern's definition\n    * @param arguments all arguments provided by the user\n    * @return Return a triple. The first element is the pattern arguments\n    *         received when `P` is parameterized. The second element is the\n    *         sub-patterns used to match the value returned after `P` is applied.\n    *         The third element indicates whether expanding this branch should\n    *         be abandoned due to invalid arguments.\n    */\n  private def matchParametersWithArguments(\n      defn: PatternDef,\n      arguments: Opt[Ls[SP]],\n      reportErrors: Bool = true\n  )(using Raise): (Ls[SP], Opt[Ls[SP]], Bool) =\n    val argumentCount = arguments.fold(0)(_.length)\n    val patternParameterCount = defn.patternParams.length\n    val loc = Loc(arguments.getOrElse(Nil))\n    if argumentCount < patternParameterCount then\n      // Since pattern parameters are required, if the total number of arguments\n      // is less than this number, the pattern matching is definitely incorrect.\n      if reportErrors then\n        error:\n          msg\"Expected ${\"pattern argument\" countBy patternParameterCount\n          }, but found only ${\"pattern argument\" countBy argumentCount}.\" -> loc\n      (Nil, N, true)\n    else arguments match\n      // Now that the number of pattern parameters can definitely be satisfied,\n      // what we need is to properly pair the parameters with the arguments.\n      case N => (Nil, N, false) // This implies `patternParameterCount` is 0.\n      case S(arguments) if argumentCount === patternParameterCount =>\n        // All the arguments satisfy the pattern arguments, with none left over.\n        (arguments, N, false)\n      case S(arguments) =>\n        val extractionParameterCount = defn.extractionParams.size\n        val extractionArgumentCount = argumentCount - patternParameterCount\n        if extractionArgumentCount === extractionParameterCount then\n          // Match arguments and parameters pairwisely.\n          val (patternArguments, extractionSubPatterns) =\n            arguments.iterator.zip(defn.parameters).toList.partitionMap:\n              case (patternArgument, Param(FldFlags(pat = true), _, _, _)) =>\n                L(patternArgument)\n              case (subPattern, _) => R(subPattern)\n          (patternArguments, S(extractionSubPatterns), false)\n        else arguments match\n          // When the pattern does not have any parameters, the user can provide\n          // an argument as a shorthand of matching the output. For example,\n          // `x is P(Q) === x is P as Q` when `P`` is not parameterized.\n          case outputPattern :: Nil if defn.parameters.isEmpty =>\n            (Nil, S(outputPattern :: Nil), false)\n          case _ :: _ | Nil =>\n            if reportErrors then\n              error:\n                msg\"Expected ${\"extraction argument\" countBy extractionParameterCount\n                }, but found ${if extractionArgumentCount < extractionParameterCount then \"only \" else \"\"\n                }${\"argument\" countBy extractionArgumentCount}.\" -> loc\n            (Nil, N, true)\n  \n  /**\n    * Create a split that naively compiles and then binds the pattern arguments.\n    *\n    * @param patternArguments the pattern arguments with their symbols\n    * @param split the inner split to be enclosed\n    */\n  def buildPatternArguments(\n      patternArguments: List[(BlockLocalSymbol, SP)],\n      split: Split\n  ): Split = patternArguments.foldRight(split):\n    case ((symbol, pattern), innerSplit) =>\n      Split.Let(symbol, compileAnonymousPattern(Nil, Nil, pattern), innerSplit)\n  \n  /**\n    * Make a split that matches the given pattern in the naive way. Note that\n    * the efficient pattern compilation without backtracking is handled in the\n    * case of `Annotated(_, _)`.\n    *\n    * @param scrutinee the scrutinee\n    * @param patternTerm the term that resolved to the pattern\n    * @param patternSymbol the symbol for the pattern\n    * @param arguments pattern arguments and extraction arguments\n    */\n  private def makeMatchPatternSplit(\n      scrutinee: Scrut,\n      patternTerm: Term,\n      patternSymbol: PatternSymbol,\n      arguments: Opt[Ls[SP]]\n  ): MakeSplit =\n    val defn = patternSymbol.defn.getOrElse:\n      lastWords(s\"Pattern `${patternSymbol.nme}` has not been elaborated.\")\n    val (patternArguments, extractionMatches, shouldReject) =\n      matchParametersWithArguments(defn, arguments)\n    warnOnDiscardedExtractionOutputs(patternSymbol, extractionMatches)\n    if shouldReject then RejectSplit else (makeConsequent, alternative) =>\n      val (extractionArguments, makeConsequentForSubPatterns) =\n        val z = (N: Opt[Ls[(BlockLocalSymbol, Opt[Loc])]], makeConsequent)\n        extractionMatches.fold(z):\n          _.folded(makeConsequent)(scrutinee.getSubScrutinee(patternSymbol)).mapFirst(S(_))\n      // First, we need to prepare the objects that performs the naive matching\n      // of pattern arguments which will be passed to the pattern.\n      val patternBindings = patternArguments.makePatternBindings\n      val wrapPatternArgumentDefinitions = buildPatternArguments(patternBindings, _)\n      // Then, we can call the `unapply` method.\n      val unapplyArguments = patternBindings.map(_._1.safeRef |> fld) :+ fld(scrutinee())\n      val unapplyCall = app(sel(patternTerm, \"unapply\").resolve, tup(unapplyArguments*), s\"result of unapply\")\n      val unapplyResult = TempSymbol(N, \"unapplyResult\")\n      val wrapUnapply = Split.Let(unapplyResult, unapplyCall, _)\n      // Then, we need to destruct the produced `MatchSuccess`.\n      val outputSymbol = TempSymbol(N, \"output\").toScrut // TODO: We can use `LazyScrut` for this, but the match result pattern's parameters requires a symbol.\n      val bindingsSymbol = TempSymbol(N, \"bindings\") // TODO: This can be automatically removed when no transformation is used.\n      val wrapDestruction = (consequent: Split) =>\n        val pattern = matchSuccessPattern(S(outputSymbol.symbol :: bindingsSymbol :: Nil))\n        Branch(unapplyResult.safeRef, pattern, consequent) ~: alternative\n      // Check the number of extraction arguments.\n      val wrapExtractionArguments = extractionArguments match\n        case N | S(Nil) => identity[Split]\n        case S((single, _) :: Nil) => Split.Let(single, outputSymbol(), _)\n        case S(extractionArguments) => (split: Split) =>\n          makeTupleBranch(outputSymbol(), extractionArguments.map(_._1), split, Split.End)\n      // Finally, the inner split that does the work.\n      val consequent = makeConsequentForSubPatterns(outputSymbol, SeqMap.empty)\n      // Here we go!\n      wrapPatternArgumentDefinitions(wrapUnapply(wrapDestruction(wrapExtractionArguments(consequent))))\n  \n  /** Report errors when pattern parameters are used incorrectly. */\n  private def validatePatternParameter[A](\n      parameterTerm: Term,\n      parameterSymbol: VarSymbol,\n      arguments: Opt[Ls[SP]],\n      patternLoc: Opt[Loc],\n      default: A\n  )(body: => A)(using Raise): A = parameterSymbol.decl match\n    case S(param @ Param(flags = FldFlags(pat = true))) => arguments match\n      case S(list) =>\n        // The object pattern comes with an unnecessary parameter list, but it\n        // can still be compiled.\n        error(msg\"`${parameterSymbol.name}` is a pattern parameter.\" -> param.toLoc,\n          msg\"It cannot be applied${if list.isEmpty then \"\" else \" to any arguments\"}.\" -> patternLoc)\n        default\n      case N => body\n    case S(_) | N =>\n      error(msg\"Cannot use this ${parameterTerm.describe} as a pattern\" -> parameterTerm.toLoc)\n      default\n  \n  private def makeMatchPatternParameterSplit(\n      scrutinee: Scrut,\n      parameterTerm: Term,\n      parameterSymbol: VarSymbol,\n      arguments: Opt[Ls[SP]],\n      patternLoc: Opt[Loc]\n  ): MakeSplit =\n    validatePatternParameter[MakeSplit](\n      parameterTerm, parameterSymbol, arguments, patternLoc, RejectSplit\n    ): (makeConsequent, alternative) =>\n      val unapplyTerm = sel(parameterTerm, \"unapply\").resolve\n      val unapplyCall = app(unapplyTerm, tup(fld(scrutinee())), s\"result of unapply\")\n      tempLet(s\"matchSuccess_${parameterSymbol.name}\", unapplyCall): matchSuccessSymbol =>\n        val outputSymbol = TempSymbol(N, \"output\").toScrut\n        val bindingsSymbol = TempSymbol(N, \"bindings\").toScrut\n        val pattern = matchSuccessPattern(S(Ls(outputSymbol.symbol, bindingsSymbol.symbol)))\n        val consequent = makeConsequent(outputSymbol, SeqMap.empty)\n        Branch(matchSuccessSymbol.safeRef, pattern, consequent) ~: alternative\n  \n  def makeMatchSplit(scrutinee: Scrut, pattern: SP): MakeSplit =\n    makeMatchSplit(scrutinee, pattern, true)\n\n  /** Make a UCS split that matches the entire scrutinee against the pattern.\n   *  Since each pattern has an output, the split is responsible for creating\n   *  a binding that holds the output value and pass it to the continuation\n   *  function that makes the consequent split.\n   */\n  def makeMatchSplit(scrutinee: Scrut, pattern: SP, outputNeeded: Bool): MakeSplit =\n    pattern match\n      case Constructor(target, arguments) => target.resolvedSym match\n        case S(symbol: VarSymbol) =>\n          makeMatchPatternParameterSplit(scrutinee, target, symbol, arguments, pattern.toLoc)\n        case symbolOption => symbolOption.flatMap(_.asClsLike) match\n          case S(classSymbol: ClassSymbol) =>\n            makeMatchClassSplit(scrutinee, target, classSymbol, arguments, outputNeeded)\n          case S(objectSymbol: ModuleOrObjectSymbol) =>\n            makeMatchObjectSplit(pattern.toLoc, scrutinee, target, objectSymbol, arguments)\n          case S(patternSymbol: PatternSymbol) =>\n            makeMatchPatternSplit(scrutinee, target, patternSymbol, arguments)\n          case N =>\n            error(msg\"Cannot use this ${target.describe} as a pattern.\" -> target.toLoc)\n            RejectSplit\n      case Composition(true, left, right) =>\n        makeMatchSplit(scrutinee, left, outputNeeded) | makeMatchSplit(scrutinee, right, outputNeeded)\n      case Composition(false, left, right) => (makeConsequent, alternative) =>\n        if outputNeeded then\n          makeMatchSplit(scrutinee, left, true)(\n            (leftOutput, leftBindings) => makeMatchSplit(scrutinee, right, true)(\n              (rightOutput, rightBindings) =>\n                val outputScrut = new LazyScrut()\n                outputScrut.toLet(\n                  tup(leftOutput() |> fld, rightOutput() |> fld),\n                  makeConsequent(outputScrut, leftBindings ++ rightBindings) ~~: alternative),\n              alternative),\n            alternative)\n        else\n          makeMatchSplit(scrutinee, left, false)(\n            (_leftOutput, leftBindings) => makeMatchSplit(scrutinee, right, false)(\n              (_rightOutput, rightBindings) =>\n                makeConsequent(scrutinee, leftBindings ++ rightBindings) ~~: alternative,\n              alternative),\n            alternative)\n      case Negation(pattern) => (makeConsequent, alternative) =>\n        // Currently, the negation pattern produces the original value. In the\n        // future, we would include diagnostic information about why the pattern\n        // failed. Note that this feature requires the `alternative` parameter\n        // to be a function that takes a diagnostic information generation\n        // function.\n        val outputSymbol = new LazyScrut()\n        makeMatchSplit(scrutinee, pattern, false)(\n          (_output, _bindings) => alternative, // The output and bindings are discarded.\n          // The place where the diagnostic information should be stored.\n          outputSymbol.toLet(scrutinee(), makeConsequent(outputSymbol, SeqMap.empty) ~~: alternative)\n        )\n      // Note that we might duplicate the alternative split here.\n      case Wildcard() => (makeConsequent, alternative) => makeConsequent(scrutinee, SeqMap.empty) ~~: alternative\n      case Literal(literal) => (makeConsequent, alternative) =>\n        Branch(scrutinee(), FlatPattern.Lit(literal), makeConsequent(scrutinee, SeqMap.empty)) ~: alternative\n      case Range(lower, upper, rightInclusive) => (makeConsequent, alternative) =>\n        makeRangeTest(scrutinee, lower, upper, rightInclusive, makeConsequent(scrutinee, SeqMap.empty)) ~~: alternative\n      case Concatenation(left, right) => (makeConsequent, alternative) =>\n        makeStringPrefixMatchSplit(scrutinee, left)(\n          (consumedOutput, remainingOutput, bindingsFromConsumed) =>\n            makeMatchSplit(remainingOutput, right, outputNeeded)(\n              (postfixOutput, bindingsFromRemaining) =>\n                if outputNeeded then\n                  val combinedOutput = new LazyScrut(S(\"concatenatedOutput\"))\n                  val combinedTerm = app(\n                    add.ref(),\n                    tup(fld(consumedOutput()), fld(postfixOutput())),\n                    \"concatenated string output\"\n                  )\n                  combinedOutput.toLet(\n                    combinedTerm,\n                    makeConsequent(combinedOutput, bindingsFromConsumed ++ bindingsFromRemaining)\n                  ) ~~: alternative\n                else\n                  makeConsequent(scrutinee, bindingsFromConsumed ++ bindingsFromRemaining) ~~: alternative,\n              alternative),\n          alternative\n        )\n      case Tuple(elements, N) => (makeConsequent, alternative) =>\n        // Fixed-length tuple patterns are similar to constructor patterns.\n        val (subScrutinees, makeChainedConsequent) =\n          elements.folded(makeConsequent)(scrutinee.getTupleLeadSubScrutinee)\n        val consequent = makeChainedConsequent(scrutinee, SeqMap.empty)\n        makeTupleBranch(scrutinee(), subScrutinees.map(_._1), consequent, alternative)\n      case Tuple(leading, S((_, spread, trailing))) => (makeConsequent, alternative) =>\n        val trailingSize = trailing.size\n        val (trailSubScrutinees, makeConsequent0) = trailing.folded(makeConsequent):\n          index => scrutinee.getTupleLastSubScrutinee(trailingSize - index)\n        val spreadSubScrutinee = TempSymbol(N, \"middleElements\")\n        val makeConsequent1: MakeConsequent = (outerOutput, outerBindings) =>\n          makeMatchSplit(spreadSubScrutinee.toScrut, spread, false)(\n            (spreadOutput, spreadBindings) => makeConsequent0(\n              spreadOutput, // TODO: Combine `outerOutput` and `spreadOutput`\n              outerBindings ++ spreadBindings),\n            Split.End)\n        val (leadingSubScrutinees, makeConsequent2) = leading.folded(makeConsequent1):\n          index => scrutinee.getTupleLeadSubScrutinee(index)\n        makeTupleBranch(\n          scrutinee(),\n          leadingSubScrutinees.map(_._1),\n          spreadSubScrutinee,\n          trailSubScrutinees.map(_._1),\n          makeConsequent2(scrutinee, SeqMap.empty),\n          alternative)\n      case Record(fields) => (makeConsequent, alternative) =>\n        // This case is similar to the `Constructor` case.\n        val z = (Nil: Ls[(Ident, BlockLocalSymbol)], makeConsequent)\n        // TODO: Deduplicate the code with the `Constructor` case.\n        val (entries, makeChainedConsequent) = fields.iterator.zipWithIndex.foldRight(z):\n          case (((key, pattern), index), (fields, makeInnerSplit)) =>\n            val subScrutinee = scrutinee.getFieldScrutinee(key)\n            val makeThisSplit: MakeConsequent = (outerOutput, outerBindings) =>\n              makeMatchSplit(subScrutinee, pattern, false)(\n                (fieldOutput, fieldBindings) => makeInnerSplit(\n                  fieldOutput, // TODO: Combine `outerOutput` and `fieldOutput`\n                  outerBindings ++ fieldBindings),\n                alternative) // We fill in the alternative here. This is\n                             // different from the `Constructor` case.\n            ((key, subScrutinee.symbol) :: fields, makeThisSplit)\n        // END TODO\n        val consequent = makeChainedConsequent(scrutinee, SeqMap.empty)\n        Branch(scrutinee(), FlatPattern.Record(entries), consequent) ~: alternative\n      case Chain(first, second) => (makeConsequent, alternative) =>\n        makeMatchSplit(scrutinee, first, true)(\n          (firstOutput, firstBindings) => makeMatchSplit(firstOutput, second, outputNeeded)(\n            (secondOutput, secondBindings) => makeConsequent(secondOutput, firstBindings ++ secondBindings),\n            alternative),\n          alternative)\n      case alias @ Alias(pattern, id) => alias.symbolOption match\n        // Ignore those who don't have symbols. `Elaborator` should have\n        // reported errors.\n        case N => makeMatchSplit(scrutinee, pattern, true)\n        case S(symbol) => (makeConsequent, alternative) =>\n          makeMatchSplit(scrutinee, pattern, true)(\n            (output, bindings) =>\n              makeConsequent(output, bindings + (symbol -> output)),\n            alternative)\n      case Transform(pattern, parameters, transform) =>\n        if !outputNeeded then\n          makeMatchSplit(scrutinee, pattern, false)\n        else\n          // We should first create a local function that transforms the captured\n          // values. So far, `pattern`'s variables should be bound to symbols.\n          // Thus, we can make a parameter list from the symbols. Then, we make\n          // a lambda term from the parameter list and the transform term. Because\n          // `pattern` might be translated to many branches, making a lambda term\n          // in advance reduces code duplication.\n          val symbols = pattern.variables.symbols\n          val params = parameters.map:\n            case (_, parameterSymbol) =>\n              Param(FldFlags.empty, parameterSymbol, N, Modulefulness.none)\n          val lambdaSymbol = new TempSymbol(N, \"transform\")\n          // Next, we need to elaborate the pattern into a split. Note that\n          // `makeMatchSplit` returns a function that takes a split as the\n          // consequence. `makeMatchSplit` also takes a list of symbols so that\n          // it needs to make sure that those bindings are available in the\n          // consequence split.\n          (makeConsequent, alternative) => Split.Let(\n            sym = lambdaSymbol,\n            term = Term.Lam(PlainParamList(params), transform.mkClone),\n            // Declare the lambda function at the outermost level. Even if there\n            // are multiple disjunctions in the consequent, we will not need to\n            // repeat the `transform` term.\n            tail = makeMatchSplit(scrutinee, pattern, true)(\n              // Note that the output is not used. Semantically, the `transform`\n              // term can only access the matched values by bindings.\n              (_output, bindings) =>\n                val arguments = symbols.iterator.map(bindings).map(_() |> fld).toSeq\n                val resultTerm = app(lambdaSymbol.safeRef, tup(arguments*), \"the transform's result\")\n                val resultSymbol = TempSymbol(N, \"transformResult\")\n                Split.Let(resultSymbol, resultTerm, makeConsequent(resultSymbol.toScrut, SeqMap.empty)),\n              alternative))\n      case Annotated(pattern, annotations) =>\n        // Currently, we only support `@compile` annotation, so here we only\n        // check whether this annotation exists, and report an error for all\n        // other annotations.\n        val shouldCompile = annotations.foldLeft(true): (acc, termOrLoc) =>\n          val res = termOrLoc match\n            case R(term) => term.resolvedSym match\n              case S(symbol) if symbol.asBlkMember.exists(_  is ctx.builtins.annotations.compile) => N\n              case S(_) | N => S(term.toLoc)\n            case L(loc) => S(loc)\n          res match\n            case S(loc) =>\n              warn(msg\"This annotation is not supported here.\" -> loc,\n                msg\"Note: Patterns only support the `@compile` annotation.\" -> pattern.toLoc)\n              acc\n            case N => true\n        if shouldCompile then\n          compilePattern(scrutinee, pattern, outputNeeded)\n        else\n          makeMatchSplit(scrutinee, pattern, outputNeeded)\n      case Guarded(pattern, guard) => (makeConsequent, alternative) =>\n        makeMatchSplit(scrutinee, pattern, true)(\n          (output, bindings) =>\n            val guardSymbol = TempSymbol(N, \"guardResult\")\n            val branch = Branch(guardSymbol.ref(), makeConsequent(output, bindings))\n            val innermost = Split.Let(guardSymbol, guard, branch ~: Split.End)\n            // The creation of bindings here is repeated with the creation of\n            // bindings during desugaring. We can add a piece of information\n            // to the `bindings` map. See tests in `where.mls`.\n            bindings.iterator.foldLeft(innermost):\n              case (innerSplit, (symbol, mkTerm)) => Split.Let(symbol, mkTerm(), innerSplit),\n          alternative)\n  \n  private def makeMatchPrefixPatternSplit(\n      scrutinee: Scrut,\n      patternTerm: Term,\n      patternSymbol: PatternSymbol,\n      arguments: Opt[Ls[SP]]\n  )(using Raise): MakePrefixSplit =\n    val defn = patternSymbol.defn.getOrElse(die)\n    val (patternArguments, extractionMatches, shouldReject) =\n      matchParametersWithArguments(defn, arguments)\n    warnOnDiscardedExtractionOutputs(patternSymbol, extractionMatches)\n    if shouldReject then RejectPrefixSplit else (makeConsequent, alternative) =>\n      val outputSymbol = TempSymbol(N, \"output\").toScrut\n      val remainingSymbol = TempSymbol(N, \"remaining\").toScrut\n      val (extractionArguments, makeConsequentForArguments) =\n        extractionMatches.fold((N, makeConsequent)):\n          _.folded(makeConsequent)(scrutinee.getSubScrutinee(patternSymbol)).mapFirst(S(_))\n      val consequent = makeConsequentForArguments(outputSymbol, remainingSymbol, SeqMap.empty)\n      val patternBindings = patternArguments.makePatternBindings\n      val unapplyCall =\n        val method = \"unapplyStringPrefix\"\n        val args = tup(patternBindings.map(_._1.safeRef) :+ scrutinee())\n        app(sel(patternTerm, method), args, s\"result of $method\")\n      val split = tempLet(\"unapplyResult\", unapplyCall): matchSuccessSymbol =>\n        val outputPairSymbol = TempSymbol(N, \"outputPair\")\n        val bindingsSymbol = TempSymbol(N, \"bindings\")\n        Branch(\n          matchSuccessSymbol.safeRef,\n          matchSuccessPattern(S(outputPairSymbol :: bindingsSymbol :: Nil)),\n          // Bind the `remaining` variable to the second element of the output\n          // of `matchSuccess`.\n          Split.Let(outputSymbol.symbol, callTupleGet(outputPairSymbol.safeRef, 0, \"prefix\"),\n            Split.Let(remainingSymbol.symbol, callTupleGet(outputPairSymbol.safeRef, 1, \"postfix\"), consequent))\n        ) ~: alternative\n      buildPatternArguments(patternBindings, split)\n  \n  private def makeMatchPrefixPatternParameterSplit(\n      scrutinee: Scrut,\n      parameterTerm: Term,\n      parameterSymbol: VarSymbol,\n      arguments: Opt[Ls[SP]],\n      patternLoc: Opt[Loc]\n  )(using Raise): MakePrefixSplit =\n    validatePatternParameter[MakePrefixSplit](\n      parameterTerm, parameterSymbol, arguments, patternLoc, RejectPrefixSplit\n    ): (makeConsequent, alternative) =>\n      val unapplyTerm = sel(parameterTerm, \"unapplyStringPrefix\").resolve\n      val unapplyCall = app(unapplyTerm, tup(fld(scrutinee())), s\"result of unapply\")\n      tempLet(s\"matchSuccess_${parameterSymbol.name}\", unapplyCall): matchSuccessSymbol =>\n        // Destruct the `MatchSuccess` produced by the `unapply` method.\n        val outputPairSymbol = TempSymbol(N, \"outputPair\").toScrut\n        val bindingsSymbol = TempSymbol(N, \"bindings\").toScrut\n        val pattern = matchSuccessPattern(S(Ls(outputPairSymbol.symbol, bindingsSymbol.symbol)))\n        // Destruct the first field of the `MatchSuccess` as a pair.\n        val outputSymbol = TempSymbol(N, \"output\").toScrut // Denotes the pattern's output.\n        val remainingSymbol = TempSymbol(N, \"remaining\").toScrut // Denotes the remaining value.\n        // Assemble the `Split`s in order from inside to outside.\n        val consequent1 = makeConsequent(outputSymbol, remainingSymbol, SeqMap.empty)\n        val consequent2 = makeTupleBranch(outputPairSymbol(),\n          Ls(outputSymbol.symbol, remainingSymbol.symbol), consequent1, Split.End)\n        Branch(matchSuccessSymbol.safeRef, pattern, consequent2) ~: alternative\n  \n  /** Construct a UCS split to match the prefix of the given scrutinee.\n   * \n   *  @return The return value is a function that builds the split. */\n  protected def makeStringPrefixMatchSplit(\n      scrutinee: Scrut,\n      pattern: SP,\n  )(using Raise): MakePrefixSplit = pattern match\n    case Constructor(target, arguments) => target.resolvedSym match\n      // The case when the target refers to a pattern parameter.\n      case S(symbol: VarSymbol) =>\n        makeMatchPrefixPatternParameterSplit(scrutinee, target, symbol, arguments, pattern.toLoc)\n      case symbolOption => symbolOption.flatMap(_.asClsLike) match\n        case S(symbol: PatternSymbol) =>\n          makeMatchPrefixPatternSplit(scrutinee, target, symbol, arguments)\n        // We accept the string class as a valid string pattern as it literally\n        // means all strings.\n        case S(symbol: ClassSymbol) if symbol is ctx.builtins.Str =>\n          arguments match\n            case S(args) if args.nonEmpty =>\n              error(\n                msg\"`${symbol.name}` does not take any arguments.\" -> target.toLoc,\n                msg\"But the pattern has ${\"sub-pattern\" countBy args.size}.\" -> Loc(args)\n              )\n              RejectPrefixSplit\n            case _ => (makeConsequent, alternative) =>\n              val nonEmptySymbol = TempSymbol(N, \"nonEmpty\")\n              val nonEmptyTerm = app(\n                this.lt.safeRef,\n                tup(fld(int(0)), fld(sel(scrutinee(), \"length\"))),\n                \"string is not empty\"\n              )\n              val outputSymbol = TempSymbol(N, \"stringHead\")\n              val outputTerm = callStringGet(scrutinee(), 0, \"head\")\n              val remainsSymbol = TempSymbol(N, \"stringTail\")\n              val remainsTerm = callStringDrop(scrutinee(), 1, \"tail\")\n              Split.Let(nonEmptySymbol, nonEmptyTerm,\n                Branch(nonEmptySymbol.safeRef,\n                  Split.Let(outputSymbol, outputTerm,\n                    Split.Let(remainsSymbol, remainsTerm,\n                      makeConsequent(outputSymbol.toScrut, remainsSymbol.toScrut, SeqMap.empty)))\n                ) ~: alternative)\n        case S(_: ModuleOrObjectSymbol) | S(_: ClassSymbol) | N =>\n          RejectPrefixSplit\n    case Composition(true, left, right) =>\n      val makeLeft = makeStringPrefixMatchSplit(scrutinee, left)\n      val makeRight = makeStringPrefixMatchSplit(scrutinee, right)\n      (makeConsequent, alternative) =>\n        makeLeft(makeConsequent, makeRight(makeConsequent, alternative))\n    case Composition(false, left, right) => (makeConsequent, alternative) =>\n      // This case is different, as the left pattern should be matched in prefix\n      // mode, but the `right` pattern should be matched in full mode. If the\n      // `right` pattern fails, we should check if `left` can match a different\n      // prefix and retry `right`.\n      // TODO: Implement the correct backtracking behavior.\n      makeStringPrefixMatchSplit(scrutinee, left)(\n        (leftOutput, leftRemains, leftBindings) => makeMatchSplit(scrutinee, right)(\n          (rightOutput, rightBindings) => \n            val productSymbol = TempSymbol(N, \"product\")\n            val productTerm = tup(leftOutput() |> fld, rightOutput() |> fld)\n            Split.Let(productSymbol, productTerm, makeConsequent(\n              productSymbol.toScrut, leftRemains, leftBindings ++ rightBindings)),\n          alternative),\n        alternative)\n    case Negation(pattern) =>\n      // This case is tricky. The question is how many of characters should be\n      // left to the continuation? For example, to match string \"match is over\"\n      // against pattern `~\"game\" ~ \" is over\"`. The first step is to match\n      // pattern `\"game\"` as a prefix of the input. After we found it doesn't\n      // not match, how many characters should we consume in this step? From a\n      // global perspective, we know that we should consume the prefix\n      // `\"match is \"``, but with backtracking, we have to try every\n      // combinations before we can make a conclusion.\n      RejectPrefixSplit\n    case Wildcard() => (makeConsequent, alternative) => \n      // Because the wildcard pattern always matches, we can match the entire\n      // string and returns an empty string as the remaining value.\n      val emptyStringSymbol = TempSymbol(N, \"emptyString\")\n      makeConsequent(scrutinee, emptyStringSymbol.toScrut, SeqMap.empty)\n      Branch(scrutinee(), FlatPattern.ClassLike(ctx.builtins.Str.safeRef, ctx.builtins.Str, N, false)(Tree.Dummy),\n        Split.Let(emptyStringSymbol, str(\"\"),\n          makeConsequent(scrutinee, emptyStringSymbol.toScrut, SeqMap.empty))\n      ) ~: alternative\n    case Literal(prefix: StrLit) => (makeConsequent, alternative) =>\n      // Check if the scrutinee is the same as the literal. If so, we return\n      // an empty string as the remaining value.\n      val isLeadingSymbol = TempSymbol(N, \"isLeading\")\n      val isLeadingTerm = callStringStartsWith(\n        scrutinee(), Term.Lit(prefix), \"the result of startsWith\")\n      val outputSymbol = TempSymbol(N, \"consumed\")\n      val outputTerm = callStringTake(scrutinee(), prefix.value.length, \"the consumed part of input\")\n      val remainsSymbol = TempSymbol(N, \"remains\")\n      val remainsTerm = callStringDrop(scrutinee(), prefix.value.length, \"the remaining input\")\n      Split.Let(isLeadingSymbol, isLeadingTerm,\n        Branch(isLeadingSymbol.safeRef,\n          Split.Let(outputSymbol, outputTerm,\n            Split.Let(remainsSymbol, remainsTerm,\n              makeConsequent(outputSymbol.toScrut, remainsSymbol.toScrut, SeqMap.empty)))\n        ) ~: alternative)\n    // Non-string literal patterns are directly discarded.\n    case Literal(_) => RejectPrefixSplit\n    case Range(lower: StrLit, upper: StrLit, rightInclusive) => (makeConsequent, alternative) =>\n      // Check if the string is not empty. Then \n      val stringHeadSymbol = TempSymbol(N, \"stringHead\")\n      val stringTailSymbol = TempSymbol(N, \"stringTail\")\n      val nonEmptySymbol = TempSymbol(N, \"nonEmpty\")\n      val nonEmptyTerm = app(this.lt.safeRef, tup(fld(int(0)), fld(sel(scrutinee(), \"length\"))), \"string is not empty\")\n      Split.Let(nonEmptySymbol, nonEmptyTerm, // `0 < string.length`\n        Branch(nonEmptySymbol.safeRef,\n          Split.Let(stringHeadSymbol, callStringGet(scrutinee(), 0, \"head\"),\n            Split.Let(stringTailSymbol, callStringDrop(scrutinee(), 1, \"tail\"),\n              makeRangeTest(stringHeadSymbol.toScrut, lower, upper, rightInclusive,\n                makeConsequent(stringHeadSymbol.toScrut, stringTailSymbol.toScrut, SeqMap.empty))))\n        ) ~: alternative)\n    // Other range patterns cannot be string prefixes.\n    case Range(_, _, _) => RejectPrefixSplit\n    case Concatenation(left, right) => (makeConsequent, alternative) =>\n      makeStringPrefixMatchSplit(scrutinee, left)(\n        (leftConsumedOutput, leftRemainingOutput, leftBindings) =>\n          makeStringPrefixMatchSplit(leftRemainingOutput, right)(\n            (rightConsumedOutput, rightRemainingOutput, rightBindings) =>\n              val combinedOutputSymbol = LazyScrut(S(\"combinedOutput\"))\n              combinedOutputSymbol.toLet(\n                app(add.ref(), tup(fld(leftConsumedOutput()), fld(rightConsumedOutput())), \"combined output\"),\n                makeConsequent(combinedOutputSymbol, rightRemainingOutput, leftBindings ++ rightBindings)),\n            alternative),\n        alternative)\n    // Tuples and records cannot be string prefixes.\n    case Tuple(_, _) => RejectPrefixSplit\n    case Record(_) => RejectPrefixSplit\n    case Chain(first, second) => (makeConsequent, alternative) =>\n      // This case is different because the first pattern might haven\n      // non-string output. So, we should apply `makeMatchSplit` to the second\n      // pattern, and finally pass the remains from the first pattern to the\n      // continuation.\n      makeStringPrefixMatchSplit(scrutinee, first)(\n        (firstOutput, firstRemains, firstBindings) =>\n          makeMatchSplit(firstOutput, second)(\n            (secondOutput, secondBindings) =>\n              makeConsequent(secondOutput, firstRemains, firstBindings ++ secondBindings),\n            alternative),\n        alternative)\n    case alias @ Alias(pattern, id) =>\n      alias.symbolOption match\n        // Ignore those who don't have symbols. `Elaborator` should have\n        // reported errors.\n        case N => makeStringPrefixMatchSplit(scrutinee, pattern)\n        case S(symbol) =>\n          val make = makeStringPrefixMatchSplit(scrutinee, pattern)\n          make.whenAccept:\n            (makeConsequent, alternative) => make(\n              (output, remains, bindings) =>\n                makeConsequent(output, remains, bindings + (symbol -> output)),\n              alternative)\n    case Transform(pattern, parameters, transform) =>\n      val make = makeStringPrefixMatchSplit(scrutinee, pattern)\n      make.whenAccept:\n        // Declare the lambda function at the outermost level. Even if there are\n        // multiple disjunctions in the consequent, we will not need to repeat\n        // the `transform` term.\n        val symbols = pattern.variables.symbols\n        val params = parameters.map:\n          case (_, parameterSymbol) =>\n            Param(FldFlags.empty, parameterSymbol, N, Modulefulness.none)\n        val lambdaSymbol = new TempSymbol(N, \"transform\")\n        (makeConsequent, alternative) => Split.Let(\n          sym = lambdaSymbol,\n          term = Term.Lam(PlainParamList(params), transform),\n          tail = make(\n            // Note that the output is not used. Semantically, the `transform`\n            // term can only access the matched values by bindings.\n            (_output, remains, bindings) =>\n              val arguments = symbols.iterator.map(bindings).map(_() |> fld).toSeq\n              val resultTerm = app(lambdaSymbol.safeRef, tup(arguments*), \"the transform's result\")\n              val resultSymbol = TempSymbol(N, \"transformResult\")\n              Split.Let(resultSymbol, resultTerm, makeConsequent(resultSymbol.toScrut, remains, SeqMap.empty)),\n            alternative))\n    case Guarded(pattern, guard) =>\n      val make = makeStringPrefixMatchSplit(scrutinee, pattern)\n      make.whenAccept:\n        (makeConsequent, alternative) => make(\n          (output, remains, bindings) =>\n            val guardSymbol = TempSymbol(N, \"guardResult\")\n            val branch = Branch(guardSymbol.ref(), makeConsequent(output, remains, bindings))\n            val innermost = Split.Let(guardSymbol, guard, branch ~: Split.End)\n            // The creation of bindings here is repeated with the creation of\n            // bindings during desugaring. We can add a piece of information\n            // to the `bindings` map. See tests in `where.mls`.\n            bindings.iterator.foldLeft(innermost):\n              case (innerSplit, (symbol, mkTerm)) => Split.Let(symbol, mkTerm(), innerSplit),\n          alternative)\n    case Annotated(pattern, annotations) =>\n      // Currently, we only support `@compile` annotation, so here we only\n      // check whether this annotation exists, and report an error for all\n      // other annotations.\n      val shouldCompile = annotations.foldLeft(true): (acc, termOrLoc) =>\n        val res = termOrLoc match\n          case R(term) => term.resolvedSym match\n            case S(symbol) if symbol is ctx.builtins.annotations.compile => N\n            case S(_) | N => S(term.toLoc)\n          case L(loc) => S(loc)\n        res match\n          case S(loc) =>\n            warn(msg\"This annotation is not supported here.\" -> loc,\n              msg\"Note: Patterns only support the `@compile` annotation.\" -> pattern.toLoc)\n            acc\n          case N => true\n      if shouldCompile then error:\n        msg\"String patterns are not yet supported by efficient compilation.\" -> pattern.toLoc\n      makeStringPrefixMatchSplit(scrutinee, pattern)\n  \n  def compilePattern(scrutinee: Scrut, pattern: SP): MakeSplit =\n    compilePattern(scrutinee, pattern, true)\n\n  /** This method handles the efficient and non-backtracking pattern compilation. \n    * Note that we still have not supported accessing pattern parameters in the\n    * naive pattern declaration in the efficient pattern compilation. */\n  def compilePattern(scrutinee: Scrut, pattern: SP, outputNeeded: Bool): MakeSplit =\n  (makeConsequent, alternative) => scoped(\"ucs:ups:compilation\"):\n    warnOnDiscardedExtractionOutputs(pattern)\n    // Instantiate the pattern and all patterns used in it.\n    val instantiator = new Instantiator\n    val (synonym, context) = instantiator(pattern)\n    // Decide whether the compiled matcher needs to create `MatchSuccess` or can\n    // represent success and failure using Boolean values.\n    //\n    // We must stay in `Full` mode when\n    // - the pattern explicitly matches extraction arguments, or when any\n    //   reachable instantiated pattern definition has extraction slots;\n    // - otherwise, if the use site needs an output, we only need `Full`\n    //   mode when a successful match does have transformations.\n    // \n    // When the instantiated pattern is transform-free and thus preserves the\n    // original scrutinee as its output, `MatchOnly` is used and the caller can\n    // obtain the scrutinee directly.\n    val canReuseScrutineeOutput = synonym.preservesOriginalScrutinee(using context, summon[Raise])\n    val resultMode =\n      if hasExplicitExtractionMatches(scrutinee, pattern) ||\n          carriesExtractionSlots(context)\n      then ResultMode.Full\n      else if outputNeeded && !canReuseScrutineeOutput then ResultMode.Full\n      else ResultMode.MatchOnly\n    // Initiate the compilation.\n    val compiler = new Compiler(using context)\n    val (matcherSymbol, implementations) = compiler.buildMatcher(synonym, resultMode)\n    val innermostSplit = resultMode match\n      case ResultMode.MatchOnly =>\n        val resultSymbol = TempSymbol(N, \"matchSuccess\")\n        val resultTerm = app(matcherSymbol.safeRef, tup(fld(scrutinee())), \"result of matcher function\")\n        Split.Let(resultSymbol, resultTerm,\n          Branch(resultSymbol.safeRef, makeConsequent(scrutinee, SeqMap.empty)) ~: alternative)\n      case ResultMode.Full =>\n        // 1. Bind the call result to a variable.\n        val recordSymbol = TempSymbol(N, \"matchRecord\")\n        val recordTerm = app(matcherSymbol.safeRef, tup(fld(scrutinee())), \"result of matcher function\")\n        val f1 = Split.Let(recordSymbol, recordTerm, _)\n        // 2. Check if the direct result is a `MatchSuccess` and bind the output.\n        val outputSymbol = TempSymbol(N, \"patternOutput\")\n        val bindingsSymbol = TempSymbol(N, \"bindings\") // TODO: This is useless.\n        val consequent = makeConsequent(outputSymbol.toScrut, SeqMap.empty)\n        val pattern = matchSuccessPattern(S(outputSymbol :: bindingsSymbol :: Nil))\n        val branch = Branch(recordSymbol.safeRef, pattern, consequent)\n        f1(branch ~: alternative)\n    implementations.iterator.foldRight(innermostSplit):\n      case ((symbol, paramList, term), innerSplit) =>\n        log(term.showDbg)\n        Split.Let(symbol, Term.Lam(paramList, term), innerSplit)\n  \n  /** Make a term like `MatchFailure(null)`. We will synthesize detailed\n   *  error messages and pass them to the function. */\n  private def failure: Split = Split.Else(makeMatchFailure())\n  \n  /**\n    * Create a method from the given UCS splits. The function has a parameter\n    * list that contains the pattern parameters and a parameter that represents\n    * the input value.\n    *\n    * @param name the method's name\n    * @param patternParameters all pattern parameters\n    * @param scrut the symbol of the input value\n    * @param topmost the topmost split\n    */\n  private def makeMethod(\n      name: Str,\n      patternParameters: List[Param],\n      scrut: VarSymbol,\n      topmost: Split\n  ): (BlockMemberSymbol, ParamList, Split) =\n    val sym = BlockMemberSymbol(name, Nil)\n    // Pattern parameters are passed as objects.\n    val patternInputs = patternParameters.map(_.copy(flags = FldFlags.empty))\n    // The last parameter is the scrutinee.\n    val scrutParam = Param(FldFlags.empty, scrut, N, Modulefulness.none)\n    val ps = PlainParamList(patternInputs :+ scrutParam)\n    (sym, ps, topmost)\n  \n  /** Translate a list of extractor/matching functions for the given pattern.\n   *  There are currently two functions: `unapply` and `unapplyStringPrefix`.\n   *  \n   *  - `unapply` is used for matching the entire scrutinee. It returns the\n   *    captured/extracted values.\n   *  - `unapplyStringPrefix` is used for matching the string prefix of the\n   *    scrutinee. It returns the remaining string and the captured/extracted\n   *    values. If the given tree does not represent a string pattern, this\n   *    function will not be generated.\n   *  \n   *  @param pattern We will eventually generate methods from the omnipotent\n   *                 `Pattern` class. Now the new `pattern` parameter and the\n   *                 old `body` parameter are mixed.\n   */\n  def compilePattern(pd: PatternDef): Ls[(BlockMemberSymbol, ParamList, Split)] =\n  trace(\n    pre = s\"compilePattern <<< ${pd.showDbg}\", \n    post = (blk: Ls[(BlockMemberSymbol, ParamList, Split)]) =>\n      s\"compilePattern >>> $blk\"\n  ):\n    val unapply = scoped(\"ucs:translation\"):\n      val inputSymbol = VarSymbol(Ident(\"input\"))\n      val topmost = makeMatchSplit(inputSymbol.toScrut, pd.pattern, true)(\n        makeConsequent = (output, bindings) =>\n          def getBinding(p: Param) = bindings.get(p.sym).fold(Term.Error)(_())\n          pd.extractionParams match\n            case Nil =>\n              // If the pattern doesn't have any extraction parameters, we take\n              // the entire output as the match result.\n              Split.Else(makeMatchSuccess(output()))\n            case sole :: Nil =>\n              // If there is only one extraction parameter, we don't make a tuple.\n              Split.Else(makeMatchSuccess(getBinding(sole)))\n            case ps =>\n              // Otherwise, `bindings` records which symbol each extraction\n              // parameter is actually represented by. Here, we extract them and\n              // put them into a tuple, then return it.\n              Split.Else(makeMatchSuccess(tup(ps.map(getBinding)))),\n        alternative = failure\n      )\n      pd.extractionParams.map(_.sym)\n      log(s\"Translated `unapply`: ${topmost.prettyPrint}\")\n      makeMethod(\"unapply\", pd.patternParams, inputSymbol, topmost)\n    // TODO: Use `pd.extractionParams`.\n    val unapplyStringPrefix = scoped(\"ucs:cp\"):\n      // We don't report errors here because they have been already reported in\n      // the translation of `unapply` function.\n      given Raise = Function.const(())\n      val inputSymbol = VarSymbol(Ident(\"input\"))\n      val topmost = makeStringPrefixMatchSplit(inputSymbol.toScrut, pd.pattern)\n        ((consumedOutput, remainingOutput, bindings) => Split.Else:\n          makeMatchSuccess(tup(fld(consumedOutput()), fld(remainingOutput()))), failure)\n      log(s\"Translated `unapplyStringPrefix`: ${topmost.prettyPrint}\")\n      makeMethod(\"unapplyStringPrefix\", pd.patternParams, inputSymbol, topmost)\n    unapply :: unapplyStringPrefix :: Nil\n  \n  /** Generate the record statements of `unapply` methods that can be used in\n   *  objects for anonymous patterns. */\n  private def makeUnapplyRecordStatements(\n      name: Str,\n      patternParameters: List[Param],\n      scrut: VarSymbol,\n      topmost: Split\n  ): Ls[Statement] =\n    val fieldSymbol = TempSymbol(N, name)\n    val decl = LetDecl(fieldSymbol, Nil)\n    val param = Param(FldFlags.empty, scrut, N, Modulefulness.none)\n    val paramList = PlainParamList(param :: Nil)\n    val lambda = Term.Lam(paramList, Term.SynthIf(topmost))\n    val defineVar = DefineVar(fieldSymbol, lambda)\n    val field = RcdField(str(name), fieldSymbol.safeRef)\n    decl :: defineVar :: field :: Nil\n  \n  /** Translate an anonymous pattern. They are usually pattern arguments. */\n  private def compileAnonymousPattern(patternParams: Ls[Param], params: Ls[Param], pattern: SP): Term = trace(\n    pre = s\"compileAnonymousPattern <<< $pattern\", \n    post = (blk: Term) => s\"compileAnonymousPattern >>> $blk\"\n  ):\n    // If the `target` refers to a pattern symbol, we can reference the pattern.\n    val term = pattern match\n      case Constructor(target, N) =>\n        target.symbol.flatMap(_.asPat).flatMap(Compiler.reference(_, target.toLoc))\n      case _ => N\n    term.getOrElse:\n      val unapply = scoped(\"ucs:translation\"):\n        val inputSymbol = VarSymbol(Ident(\"input\"))\n        val topmost = makeMatchSplit(inputSymbol.toScrut, pattern, true)\n          ((output, bindings) => Split.Else(makeMatchSuccess(output())), failure)\n        log(s\"Translated `unapply`: ${topmost.prettyPrint}\")\n        makeUnapplyRecordStatements(\"unapply\", patternParams, inputSymbol, topmost)\n      val unapplyStringPrefix = scoped(\"ucs:cp\"):\n        // We don't report errors here because they have been already reported in\n        // the translation of `unapply` function.\n        given Raise = Function.const(())\n        val inputSymbol = VarSymbol(Ident(\"input\"))\n        val topmost = makeStringPrefixMatchSplit(inputSymbol.toScrut, pattern)\n          ((consumedOutput, remainingOutput, bindings) => Split.Else:\n            makeMatchSuccess(tup(fld(consumedOutput()), fld(remainingOutput()))), failure)\n        log(s\"Translated `unapplyStringPrefix`: ${topmost.prettyPrint}\")\n        makeUnapplyRecordStatements(\"unapplyStringPrefix\", patternParams, inputSymbol, topmost)\n      Term.Rcd(false, unapply ::: unapplyStringPrefix)\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/syntax/Keyword.scala",
    "content": "package hkmc2\npackage syntax\n\nimport collection.mutable\nimport mlscript.utils.*, shorthands.*\n\n\nclass Keyword(\n    val name: String,\n    val leftPrec: Opt[Int],\n    val rightPrec: Opt[Int],\n    \n    /** If the operator can be used infix, can it be done on a newline (with no indent)?\n        For instance, if `via` has `canStartInfixOnNewLine`, then one can write:\n          foo\n          via f\n          via g\n        But `is` does not have `canStartInfixOnNewLine` so that\n          if x\n            is A then foo\n            is B then bar\n        does not parse as\n          if x { is A then foo { is B then ... } }\n        Note: Currently, this just fails to parse.\n        We should probably rather make `is` a normal operator like `+`; then it would work.\n      */\n    val canStartInfixOnNewLine: Bool = true\n):\n  Keyword.all += name -> this\n  def assumeLeftPrec: Int = leftPrec.getOrElse(lastWords(s\"$this does not have left precedence\"))\n  def assumeRightPrec: Int = rightPrec.getOrElse(lastWords(s\"$this does not have right precedence\"))\n  def leftPrecOrMin: Int = leftPrec.getOrElse(Int.MinValue)\n  def rightPrecOrMin: Int = rightPrec.getOrElse(Int.MinValue)\n  def rightPrecOrMax: Int = rightPrec.getOrElse(Int.MaxValue)\n  override def toString: Str = s\"keyword '$name'\"\n\nobject Keyword:\n  def unapply(kw: Keyword): Opt[Str] = S(kw.name)\n  \n  val all: mutable.Map[Str, Keyword] = mutable.Map.empty\n  \n  // val Let = Keyword(\"let\", 0, 0)\n  // val Let = Keyword(\"let\", 0, 0)\n  \n  private var _curPrec = 2\n  private def curPrec: S[Int] = S(_curPrec)\n  private def nextPrec: S[Int] =\n    _curPrec += 1\n    S(_curPrec)\n  \n  val `class` = Keyword(\"class\", N, N)\n  \n  val `extends` = Keyword(\"extends\", nextPrec, curPrec)\n  val `restricts` = Keyword(\"restricts\", curPrec, curPrec)\n  val `with` = Keyword(\"with\", curPrec, curPrec)\n  \n  val `val` = Keyword(\"val\", N, curPrec)\n\n  val eqPrec = nextPrec\n  val ascPrec = nextPrec // * `x => x : T` should parsed as `x => (x : T)`\n  val `=` = Keyword(\"=\", eqPrec, eqPrec)\n  val `:` = Keyword(\":\", ascPrec, eqPrec)\n  val `..` = Keyword(\"..\", N, N)\n  val `...` = Keyword(\"...\", N, N)\n  // val `;` = Keyword(\";\", ascPrec, eqPrec)\n  \n  val `if` = Keyword(\"if\", N, nextPrec)\n  val `while` = Keyword(\"while\", N, curPrec)\n  val `assert` = Keyword(\"assert\", N, curPrec)\n  type `assert` = `assert`.type\n  \n  val `case` = Keyword(\"case\", N, curPrec)\n  \n  val thenPrec = nextPrec\n  val `then` = Keyword(\"then\", thenPrec, eqPrec)\n  val `do` = Keyword(\"do\", thenPrec, eqPrec)\n  val `drop` = Keyword(\"drop\", thenPrec, eqPrec)\n  \n  val `else` = Keyword(\"else\", N, eqPrec)\n  type `else` = `else`.type\n  \n  val `return` = Keyword(\"return\", N, curPrec)\n  val `throw` = Keyword(\"throw\", N, curPrec)\n  val `import` = Keyword(\"import\", N, curPrec)\n  \n  val `fun` = Keyword(\"fun\", N, N)\n  // val `val` = Keyword(\"val\", N, N)\n  val `var` = Keyword(\"var\", N, N)\n  val `where` = Keyword(\"where\", nextPrec, curPrec)\n  val `of` = Keyword(\"of\", N, N) // * Note that `of` is parsed specially, so its precedence is not listed here\n  val `or` = Keyword(\"or\", nextPrec, curPrec)\n  val `and` = Keyword(\"and\", nextPrec, nextPrec)\n  val `not` = Keyword(\"not\", nextPrec, nextPrec)\n  val `is` = Keyword(\"is\", nextPrec, curPrec, canStartInfixOnNewLine = false)\n  val `as` = Keyword(\"as\", nextPrec, curPrec)\n  // val `let` = Keyword(\"let\", nextPrec, curPrec)\n  val `let` = Keyword(\"let\", N, N)\n  val `handle` = Keyword(\"handle\", N, N)\n  val `region` = Keyword(\"region\", N, N)\n  val `rec` = Keyword(\"rec\", N, N)\n  val `in` = Keyword(\"in\", curPrec, curPrec)\n  val `out` = Keyword(\"out\", N, curPrec)\n  val `set` = Keyword(\"set\", N, curPrec)\n  val `declare` = Keyword(\"declare\", N, N)\n  val `data` = Keyword(\"data\", N, N)\n  val `trait` = Keyword(\"trait\", N, N)\n  val `mixin` = Keyword(\"mixin\", N, N)\n  val `interface` = Keyword(\"interface\", N, N)\n  val `override` = Keyword(\"override\", N, N)\n  val `super` = Keyword(\"super\", N, N)\n  // val `namespace` = Keyword(\"namespace\", N, N)\n  val `using` = Keyword(\"using\", N, N)\n  val `module` = Keyword(\"module\", N, N)\n  val `object` = Keyword(\"object\", N, N)\n  val `open` = Keyword(\"open\", N, curPrec)\n  val `type` = Keyword(\"type\", N, N)\n  val `forall` = Keyword(\"forall\", N, N)\n  val `exists` = Keyword(\"exists\", N, N)\n  val `null` = Keyword(\"null\", N, N)\n  val `undefined` = Keyword(\"undefined\", N, N)\n  val `abstract` = Keyword(\"abstract\", N, N)\n  val `constructor` = Keyword(\"constructor\", N, N)\n  val `virtual` = Keyword(\"virtual\", N, N)\n  val `staged` = Keyword(\"staged\", N, N)\n  val `true` = Keyword(\"true\", N, N)\n  val `false` = Keyword(\"false\", N, N)\n  val `public` = Keyword(\"public\", N, N)\n  val `private` = Keyword(\"private\", N, N)\n  val `this` = Keyword(\"this\", N, N)\n  val `outer` = Keyword(\"outer\", N, N)\n  val `pattern` = Keyword(\"pattern\", N, N)\n  \n  val `->` = Keyword(\"->\", nextPrec, eqPrec)\n  \n  val maxPrec = curPrec\n  \n  // * The lambda operator is special:\n  // *  it should associate very strongly on the left and very loosely on the right\n  // *  so that we can write things like `f() |> x => x is 0` ie `(f()) |> (x => (x is 0))`\n  // * Currently, the precedence of normal operators starts at the maximum precedence of keywords,\n  // * so we need to start the precedence of `=>` to account for that.\n  val `=>` = Keyword(\"=>\", S(maxPrec.get + charPrecList.length), eqPrec)\n\n  // * `new` is a strange keyword:\n  // * it has a very high precedence that sits between that of selection and that of application.\n  // * Indeed, `new Foo().bar` should parse as `(new Foo()).bar`, not `new (Foo().bar)`,\n  // * but `new Foo.Bar` should parse as `new (Foo.Bar)`.\n  val newRightPrec = S(maxPrec.get + charPrecList.length - 1)\n  // * ^ maxPrec.get + charPrecList.length is the precedence of selection\n  val `new` = Keyword(\"new\", N, newRightPrec)\n  val `new!` = Keyword(\"new!\", N, newRightPrec)\n  val `mut` = Keyword(\"mut\", N, newRightPrec)\n  \n  // * `#` is both a prefix keyword (for directives like `#config(...)`)\n  // * and an infix operator (for disambiguation like `Lazy#get()`).\n  // * It has very high left precedence (like selection) when used as infix.\n  // * The right precedence is set to the same level (very tight) so that infix `#`\n  // * only picks up the immediately following identifier, e.g., `arr.Cls#d.f()`\n  // * parses as `App(Sel(InfixApp(Sel(arr, Cls), #, d), f), ())`.\n  // * In prefix position, this means `#config` only gets the name; `(args)` is\n  // * consumed by `exprCont` and the elaborator reconstructs the directive.\n  // * `canStartInfixOnNewLine = false` prevents it from being parsed as infix\n  // * when it appears on a new line after an expression.\n  val hashSelPrec = S(maxPrec.get + charPrecList.length)\n  val `#` = Keyword(\"#\", hashSelPrec, hashSelPrec, canStartInfixOnNewLine = false)\n  \n  val __ = Keyword(\"_\", N, N)\n  \n  val modifiers = Set(\n    `abstract`, mut, virtual, `override`, declare, public, `private`)\n  \n  type Prefix =\n    `do`.type | `drop`.type | `not`.type | `new!`.type | `else`.type | `return`.type | `throw`.type | `import`.type\n  \n  type Infix =\n    `is`.type | `:`.type | `->`.type | `=>`.type | `extends`.type | `restricts`.type | `as`.type | `do`.type |\n    `where`.type | `with`.type | `and`.type | `or`.type | `then`.type | `else`.type | `#`.type\n  \n  type InfixSplittable =\n    `is`.type | `:`.type | `->`.type | `=>`.type | `extends`.type | `restricts`.type | `as`.type | `do`.type |\n    `where`.type | `with`.type | `of`.type\n  \n  type Ellipsis = `...`.type | `..`.type\n  \n  type IfLike = `if`.type | `while`.type\n  type SplitLike = IfLike | `case`.type\n  \n  type LetLike = `let`.type | `set`.type\n  \n  type Modifier = `in`.type | `out`.type | `mut`.type | `abstract`.type | `declare`.type | `data`.type | `virtual`.type | `override`.type |\n    `public`.type | `private`.type | `staged`.type\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/syntax/Lexer.scala",
    "content": "package hkmc2\npackage syntax\n\nimport scala.annotation.tailrec\nimport mlscript._\nimport utils._, shorthands._\n\nimport Message.MessageContext\nimport Diagnostic.Source.{Lexing, Parsing}\n\nimport Lexer._\nimport Tree.{IntLit, DecLit, StrLit}\n\nclass Lexer(origin: Origin, dbg: Bool)(using raise: Raise):\n  \n  val bytes: Array[Char] = origin.fph.blockStr.toArray\n  private val length = bytes.length\n  type State = Int\n  \n  private val isOpChar = Set(\n    '!', '#', '%', '&', '*', '+', '-', '/', ':', '<', '=', '>', '?', '@', '\\\\', '^', '|', '~', '.',\n    // ',', \n    // ';'\n  )\n  def isIdentFirstChar(c: Char): Bool =\n    c.isLetter || c === '_' || c === '\\''\n  def isIdentChar(c: Char): Bool =\n    isIdentFirstChar(c) || isDigit(c) || c === '\\''\n  def isHexDigit(c: Char): Bool =\n    isDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')\n  def isOctDigit(c: Char): Bool =\n    c >= '0' && c <= '7'\n  def isBinDigit(c: Char): Bool =\n    c === '0' || c === '1'\n  def isDigit(c: Char): Bool =\n    c >= '0' && c <= '9'\n  def matches(i: Int, syntax: Str, start: Int): Bool =\n    if start < syntax.length && i + start < length && bytes(i + start) === syntax(start) then matches(i, syntax, start + 1)\n    else start >= syntax.length\n  \n  /* // TODO remove (unused)\n  private val isNonStickyKeywordChar = Set(\n    ',',\n    ':',\n    ';',\n  )\n  */\n  \n  private val isSymKeyword = Set(\n    // \"->\",\n    \"=>\",\n    \"=\",\n    \":\",\n    \";\",\n    // \",\",\n    \"#\",\n    \"`\"\n    // \".\",\n    // \"<\",\n    // \">\",\n  )\n  \n  @tailrec final\n  def takeWhile(i: Int, cur: Ls[Char] = Nil)(pred: Char => Bool): (Str, Int) =\n    if i < length && pred(bytes(i)) then takeWhile(i + 1, bytes(i) :: cur)(pred)\n    else (cur.reverseIterator.mkString, i)\n\n  final def num(i: Int): (Literal, Int) =\n    def test(i: Int, p: Char => Bool): Bool = i < length && p(bytes(i))\n    def zero: IntLit = IntLit(BigInt(0))\n    /** Take a sequence of digits interleaved with underscores. */\n    def takeDigits(i: Int, pred: Char => Bool): (Opt[Str], Int) =\n      @tailrec def rec(i: Int, acc: Ls[Char], firstSep: Bool, lastSep: Bool): (Str, Bool, Bool, Int) =\n        if i < length then\n          val c = bytes(i)\n          if pred(c) then rec(i + 1, c :: acc, firstSep, false)\n          else if c === '_' then rec(i + 1, acc, acc.isEmpty, true)\n          else (acc.reverseIterator.mkString, firstSep, lastSep, i)\n        else (acc.reverseIterator.mkString, firstSep, lastSep, i)\n      val (str, firstSep, lastSep, j) = rec(i, Nil, false, false)\n      if firstSep then\n        raise(WarningReport(\n          msg\"Leading separator is not allowed\" -> S(loc(i - 1, i)) :: Nil,\n          source = Lexing))\n      if lastSep then\n        raise(WarningReport(\n          msg\"Trailing separator is not allowed\" -> S(loc(j - 1, j)) :: Nil,\n          source = Lexing))\n      (if str.isEmpty then N else S(str), j)\n    /** Take an integer and coverts to `BigInt`. Also checks if it is empty. */\n    def integer(i: Int, radix: Int, desc: Str, pred: Char => Bool): (IntLit, Int) =\n      takeDigits(i, pred) match\n        case (N, j) =>\n          raise(ErrorReport(msg\"Expected at least one $desc digit\" -> S(loc(i, i + 2)) :: Nil,\n            source = Lexing))\n          (zero, j)\n        case (S(str), j) => (IntLit(BigInt(str, radix)), j)\n    def isDecimalStart(ch: Char) = ch === '.' || ch === 'e' || ch === 'E'\n    /** Take a fraction part with an optional exponent part. Call at periods. */\n    def decimal(i: Int, integral: Str): (DecLit, Int) =\n      lazy val msgPrefix = \"Expected at least one digit after the \"\n      val (fraction, j) =\n        if test(i, _ === '.')\n        then takeDigits(i + 1, isDigit) match\n        case (N, j) =>\n          // TODO should parse a selection here; as in `1.toString()`\n          raise(ErrorReport(msg\"$msgPrefix decimal point\" -> S(loc(i + 1, i + 2)) :: Nil,\n            source = Lexing))\n          (\"\", j)\n        case (S(digits), j) => (\".\" + digits, j)\n        else (\"\", i)\n      val (exponent, k) =\n        if test(j, ch => ch === 'e' || ch === 'E')\n        then\n          val (sign, k) = if test(j + 1, ch => ch === '+' || ch === '-')\n            then (bytes(j + 1), j + 2)\n            else ('+', j + 1)\n          takeDigits(k, isDigit) match\n          case (N, l) =>\n            raise(ErrorReport(msg\"$msgPrefix exponent sign\" -> S(loc(l - 1, l)) :: Nil,\n              source = Lexing))\n            (\"\", l)\n          case (S(digits), l) => (\"E\" + sign + digits, l)\n        else (\"\", j)\n      (DecLit(BigDecimal(integral + fraction + exponent)), k)\n    if i < length then\n      bytes(i) match\n        case '0' if i + 1 < length => bytes(i + 1) match\n          case 'x' => integer(i + 2, 16, \"hexadecimal\", isHexDigit)\n          case 'o' => integer(i + 2, 8, \"octal\", isOctDigit)\n          case 'b' => integer(i + 2, 2, \"binary\", isBinDigit)\n          case '.' | 'E' | 'e' => decimal(i + 1, \"0\")\n          case _ => integer(i, 10, \"decimal\", isDigit)\n        case '0' => (zero, i + 1)\n        case _ => takeDigits(i, isDigit) match\n          case (N, j) =>\n            raise(ErrorReport(msg\"Expected a numeric literal\" -> S(loc(i, i + 1)) :: Nil,\n              source = Lexing))\n            (zero, i)\n          case (S(integral), j) =>\n            if j < length && isDecimalStart(bytes(j)) then decimal(j, integral)\n            else (IntLit(BigInt(integral)), j)\n    else\n      raise(ErrorReport(msg\"Expected a numeric literal instead of end of input\" -> S(loc(i, i + 1)) :: Nil,\n        source = Lexing))\n      (zero, i)\n\n  // * Check the end of a string (either single quotation or triple quotation)\n  final def closeStr(i: Int, isTriple: Bool): Int =\n    if !isTriple && bytes.lift(i) === Some('\"') then i + 1\n    else if isTriple && matches(i, \"\\\"\\\"\\\"\", 0) then i + 3\n    else\n      raise(ErrorReport(msg\"unclosed quotation mark\" -> S(loc(i, i + 1)) :: Nil, source = Lexing))\n      i\n\n  @tailrec final\n  def str(i: Int, escapeMode: Bool, cur: Ls[Char] = Nil)(using triple: Bool): (Str, Int) =\n    if escapeMode then\n      if i < length then\n        bytes(i) match\n          case '\\\\' => str(i + 1, false, '\\\\' :: cur)\n          case '\"' => str(i + 1, false, '\"' :: cur)\n          case 'n' => str(i + 1, false, '\\n' :: cur)\n          case 't' => str(i + 1, false, '\\t' :: cur)\n          case 'r' => str(i + 1, false, '\\r' :: cur)\n          case 'b' => str(i + 1, false, '\\b' :: cur)\n          case 'f' => str(i + 1, false, '\\f' :: cur)\n          case 'u' => \n            /**\n              * This code handles two types of Unicode escape sequences:\n              *\n              * + Traditional Unicode escape: \"\\uXXXX\"\n              *   - Consists of the characters '\\' and 'u' followed by exactly\n              *     four hexadecimal digits.\n              *   - Example: \"\\u0041\" represents the character 'A'.\n              * + Unicode code point escape: \"\\u{XXXXXX}\"\n              *   - Starts with \"\\u{\" and ends with \"}\", allowing between 1 and\n              *     6 hexadecimal digits in between.\n              *   - Example: \"\\u{1F600}\" represents the grinning face emoji.\n              *\n              * In both cases, the scanned code point is validated to ensure\n              * that it falls within the allowed Unicode range (0x0 to 0x10FFFF).\n              * If any errors occur during scanning or conversion, such as\n              * invalid characters, missing digits, or code points out of range,\n              * a warning is raised with a precise location.\n              */\n            @tailrec\n            def scanHexDigits(idx: Int, maxDigits: Int, value: Int, count: Int): (Int, Int, Int) =\n              if idx < length && isHexDigit(bytes(idx)) then\n                if count < maxDigits then\n                  scanHexDigits(idx + 1, maxDigits, (value << 4) + Character.digit(bytes(idx), 16), count + 1)\n                else\n                  scanHexDigits(idx + 1, maxDigits, value, count + 1)\n              else\n                (idx, value, count)\n            \n            if i + 1 < length && bytes(i + 1) == '{' then\n              // Scan up to 6 hex digits after the opening brace.\n              val (nextIdx, acc, count) = scanHexDigits(i + 2, 6, 0, 0)\n              val result = if count == 0 then\n                raise(WarningReport(msg\"Expected at least one hexadecimal digit in Unicode escape sequence\" -> S(loc(i + 1, nextIdx)) :: Nil,\n                  source = Lexing))\n                cur\n              else if count > 6 then\n                raise(WarningReport(msg\"Too many hexadecimal digits in Unicode escape sequence\" -> S(loc(nextIdx - (count - 6), nextIdx)) :: Nil,\n                  source = Lexing))\n                cur\n              else if acc > 0x10FFFF then\n                raise(WarningReport(msg\"Unicode code point out of range: 0x${acc.toHexString}\" -> S(loc(i + 2, nextIdx)) :: Nil,\n                  source = Lexing))\n                cur\n              else\n                Character.toChars(acc).reverseIterator.toList ::: cur\n              // Close the brace.\n              val finalIdx = if nextIdx >= length || bytes(nextIdx) != '}' then\n                raise(WarningReport(msg\"Unterminated Unicode escape sequence: missing '}'\" -> S(loc(nextIdx, nextIdx)) :: Nil,\n                  source = Lexing))\n                nextIdx\n              else\n                nextIdx + 1\n              str(finalIdx, false, result)\n            else\n              // Process the traditional 4-digit Unicode escape (\\uXXXX).\n              val (nextIdx, acc, count) = scanHexDigits(i + 1, 4, 0, 0)\n              if count =/= 4 then\n                raise(WarningReport(msg\"Invalid Unicode escape sequence: expected 4 hexadecimal digits but got ${count.toString}\" -> S(loc(i + 1, nextIdx)) :: Nil,\n                  source = Lexing))\n                str(nextIdx, false, cur)\n              else\n                str(nextIdx, false, acc.toChar :: cur)\n          case ch =>\n            raise(WarningReport(msg\"Found invalid escape character\" -> S(loc(i, i + 1)) :: Nil,\n              source = Lexing))\n            str(i + 1, false, ch :: cur)\n      else\n        raise(ErrorReport(msg\"Expected an escape character\" -> S(loc(i, i + 1)) :: Nil,\n          source = Lexing))\n        (cur.reverseIterator.mkString, i)\n    else if triple then\n      if i < length then\n        bytes(i) match\n          case '\"' =>\n            if matches(i, \"\\\"\\\"\\\"\", 0) && !matches(i + 1, \"\\\"\\\"\\\"\", 0) then // Find the last \"\"\"\n              (cur.reverseIterator.mkString, i)\n            else str(i + 1, false, '\"' :: cur)\n          case ch => str(i + 1, false, ch :: cur)\n      else (cur.reverseIterator.mkString, i)\n    else\n      if i < length then\n        bytes(i) match\n          case '\\\\' => str(i + 1, true, cur)\n          case '\"' | '\\n' => (cur.reverseIterator.mkString, i)\n          case ch => str(i + 1, false, ch :: cur)\n      else\n        (cur.reverseIterator.mkString, i)\n  \n  def loc(start: Int, end: Int): Loc = Loc(start, end, origin)\n  \n  def mkSymIdent(nme: Str) = nme match\n    case \"..\" => SUSPENSION(false)\n    case \"...\" => SUSPENSION(true)\n    case _ => IDENT(nme, true)\n  \n  @tailrec final\n  def lex(i: Int, ind: Ls[Int], acc: Ls[TokLoc])\n        (using qqList: Ls[BracketKind]): Ls[TokLoc] = if i >= length then acc.reverse else\n    \n    val c = bytes(i)\n    \n    def pe(msg: Message): Unit =\n      raise(ErrorReport(msg -> S(loc(i, i + 1)) :: Nil, source = Lexing))\n    \n    def isQuasiquoteOpening(i: Int): Bool = matches(i, BracketKind.Quasiquote.beg, 0)\n    def isQuasiquoteTripleOpening(i: Int): Bool =  matches(i, BracketKind.QuasiquoteTriple.beg, 0)\n    def isUnquoteOpening(i: Int): Bool = matches(i, BracketKind.Unquote.beg, 0)\n    def isQuasiquoteTripleClosing(i: Int): Bool = matches(i, BracketKind.QuasiquoteTriple.end, 0)\n    \n    inline def go(j: Int, tok: Token)(using qqList: Ls[BracketKind]) = lex(j, ind, (tok, loc(i, j)) :: acc)\n    \n    c match\n      case ' ' =>\n        val (_, j) = takeWhile(i)(_ === ' ')\n        go(j, SPACE)\n      case ',' =>\n        val j = i + 1\n        go(j, COMMA)\n      case '`' =>\n        go(i + 1, QUOTE)\n      case 'c' if isQuasiquoteOpening(i) || isQuasiquoteTripleOpening(i) =>\n        val isTripleQuoteQQ = isQuasiquoteTripleOpening(i)\n        val bracket_kind = if isTripleQuoteQQ then\n          BracketKind.QuasiquoteTriple\n        else\n          BracketKind.Quasiquote\n        val len = bracket_kind.beg.length\n        go(i + len, OPEN_BRACKET(bracket_kind))(using bracket_kind :: qqList)\n      case '$' if isUnquoteOpening(i) =>\n        go(i + 2, OPEN_BRACKET(BracketKind.Unquote))\n      case '$' if i + 1 < length && isIdentFirstChar(bytes(i + 1)) =>\n        val (n, j) = takeWhile(i + 1)(isIdentChar)\n        go(j, BRACKETS(BracketKind.Unquote, (\n            IDENT(n, false),\n            loc(i + 1, j)\n          ) :: Nil)(loc(i, j)))\n      case 'i' if i + 2 < length && bytes(i + 1) === 'd' && bytes(i + 2) === '\"' =>\n        val (n, j) = takeWhile(i + 3)(isIdentChar)\n        go(j + 1,\n          if bytes(j) === '\"' && !n.isEmpty() then ESC_IDENT(n)\n          else { pe(msg\"unexpected identifier escape\"); ERROR }\n        )\n      case ';' =>\n        val j = i + 1\n        // lex(j, ind, next(j, SEMI))\n        go(j, IDENT(\";\", true))\n      case '\"' =>\n        val (isTripleQQ, cons) = qqList match\n          case h :: t => (h === BracketKind.QuasiquoteTriple, t)\n          case Nil => (false, Nil)\n        if isTripleQQ && isQuasiquoteTripleClosing(i) then\n          val length = BracketKind.QuasiquoteTriple.end.length\n          go(i + length, CLOSE_BRACKET(BracketKind.QuasiquoteTriple))(using cons)\n        else if !isTripleQQ && qqList.nonEmpty then\n          go(i + 1, CLOSE_BRACKET(BracketKind.Quasiquote))(using cons)\n        else\n          val isTriple = matches(i, \"\\\"\\\"\\\"\", 0)\n          val j = i + (if isTriple then 3 else 1)\n          val (chars, k) = str(j, false)(using isTriple)\n          val k2 = closeStr(k, isTriple)\n          go(k2, LITVAL(StrLit(chars)))\n      case '/' if bytes.lift(i + 1).contains('/') =>\n        val j = i + 2\n        val (txt, k) =\n          takeWhile(j)(c => c =/= '\\n')\n        go(k, COMMENT(txt))\n      case '/' if bytes.lift(i + 1).contains('*') => // multiple-line comment\n        val j = i + 2\n        var prev1 = '/'; var prev2 = '*'\n        val (txt, k) =\n          takeWhile(j)(c => {\n            val res = prev1 =/= '*' || prev2 =/= '/'\n            prev1 = prev2; prev2 = c\n            res\n          })\n        go(k, COMMENT(txt.dropRight(2)))\n      case BracketKind(Left(k)) => go(i + 1, OPEN_BRACKET(k))\n      case BracketKind(Right(k)) => go(i + 1, CLOSE_BRACKET(k))\n      case '\\n' =>\n        val j = i + 1\n        val (space, k) =\n          takeWhile(j)(c => c === ' ' || c === '\\n')\n        val nextInd = space.reverseIterator.takeWhile(_ =/= '\\n').size\n        if ind.headOption.forall(_ < nextInd) && nextInd > 0 then\n          lex(k, nextInd :: ind, (INDENT, loc(j, k)) :: acc)\n        else\n          val newIndBase = ind.dropWhile(_ > nextInd)\n          val droppedNum = ind.size - newIndBase.size\n          val hasNewIndent = newIndBase.headOption.forall(_ < nextInd) && nextInd > 0\n          val newInd = if hasNewIndent then nextInd :: newIndBase else newIndBase\n          if dbg then\n            println(\"dbg: \" + bytes.drop(i).take(10).map(escapeChar).mkString+\"...\")\n            println((ind, nextInd, newIndBase, droppedNum, hasNewIndent, newInd))\n          lex(k, newInd,\n            if droppedNum > 0 then {\n              if hasNewIndent then (INDENT, loc(j, k))\n              else (NEWLINE, loc(i, k))\n            } :: List.fill(droppedNum)((DEINDENT, loc(j-1, k))) ::: acc\n            else (NEWLINE, loc(i, k)) :: acc\n          )\n      case _ if isIdentFirstChar(c) =>\n        val (n, j) = takeWhile(i)(isIdentChar)\n        go(j, IDENT(n, false))\n      case _ if isOpChar(c) =>\n        val (n, j) = takeWhile(i)(isOpChar)\n        if n === \".\" && j >= length then go(j, PERIOD) // * There is no other character to parse after `.`\n        else if (n === \".\" || n === \"!\") && j < length\n        then\n          inline def mkSelect(str: Str) = SELECT(str, n === \"!\")\n          val nc = bytes(j)\n          if isIdentFirstChar(nc) then\n            val (name, k) = takeWhile(j)(isIdentChar)\n            go(k, mkSelect(name))\n          else if\n            // The first character is '0' and the next character is not a digit\n            (nc === '0' && !(j + 1 < length && isDigit(bytes(j + 1)))) ||\n            ('0' < nc && nc <= '9') // The first character is a digit other than '0'\n          then\n            val (name, k) = takeWhile(j)(isDigit)\n            go(k, mkSelect(name))\n          else\n            go(j,\n              if n === \".\" then PERIOD else\n                // * Eventually we should also forbid `!` as an identifier, but it's currently used by BbML/InvalML\n                mkSymIdent(n)\n            )\n        else go(j, mkSymIdent(n))\n      case _ if isDigit(c) =>\n        val (lit, j) = num(i)\n        go(j, LITVAL(lit))\n      case _ =>\n        pe(msg\"unexpected character '${escapeChar(c)}'\")\n        go(i + 1, ERROR)\n  \n  def escapeChar(ch: Char): String = ch match\n    case '\\b' => \"\\\\b\"\n    case '\\t' => \"\\\\t\"\n    case '\\n' => \"\\\\n\"\n    case '\\f' => \"\\\\f\"\n    case '\\r' => \"\\\\r\"\n    case '\"'  => \"\\\\\\\"\"\n    case '\\'' => \"\\\\\\'\"\n    case '\\\\' => \"\\\\\\\\\"\n    case _    => if ch.isControl\n      then \"\\\\0\" + Integer.toOctalString(ch.toInt) \n      else String.valueOf(ch)\n  \n  \n  \n  lazy val tokens: Ls[Token -> Loc] = lex(0, Nil, Nil)(using Nil)\n  \n  \n  /** Converts the lexed tokens into structured tokens. */\n  lazy val bracketedTokens: Ls[Stroken -> Loc] =\n    import BracketKind._\n    def go(\n        toks: Ls[Token -> Loc],\n        canStartAngles: Bool,\n        stack: Ls[BracketKind -> Loc -> Ls[Stroken -> Loc]],\n        swallowedInd: Int, // * Number of previous indentations that were not closed by deindents but by closing other brackets\n        acc: Ls[Stroken -> Loc],\n    ): Ls[Stroken -> Loc] =\n      toks match\n        case (SUSPENSION(true), l0) :: Nil =>\n          // * This is an ugly special-case to handle things like `module M with ...`\n          // * where there is no actual body after the `...`.\n          // * It can't be handled in the parser because this is only valid at the top-level,\n          // * not within brackets, as in `(arg0, ...) => blah`.\n          go(OPEN_BRACKET(Indent) -> l0 :: LITVAL(Tree.UnitLit(false)) -> l0 :: Nil, false, stack, swallowedInd, acc)\n        case (QUOTE, l0) :: (IDENT(\"<\", true), l1) :: rest =>\n          go(rest, false, stack, swallowedInd, (IDENT(\"<\", true), l1) :: (QUOTE, l0) :: acc)\n        case (QUOTE, l0) :: (IDENT(\">\", true), l1) :: rest =>\n          go(rest, false, stack, swallowedInd, (IDENT(\">\", true), l1) :: (QUOTE, l0) :: acc)\n        case (OPEN_BRACKET(k), l0) :: rest =>\n          go(rest, false, k -> l0 -> acc :: stack, swallowedInd, Nil)\n        case (NEWLINE, l1) :: rest if swallowedInd > 0 =>\n          go((OPEN_BRACKET(Indent), l1) :: rest, false, stack, swallowedInd - 1, acc)\n        case (CLOSE_BRACKET(Indent), l1) :: rest if swallowedInd > 0 => go(rest, false, stack, swallowedInd - 1, acc)\n        case (CLOSE_BRACKET(k1), l1) :: rest =>\n          stack match\n            case ((k0 @ Indent, l0), oldAcc) :: oldStack if k1 =/= Indent =>\n              // * Sometimes, open/close parentheses are interleaved with indent/deindent; eg in\n              // *   module P with\n              // *     (\n              // *       2)\n              // *     1\n              // * which results in token stream `|module| |P| |with|→|(|→|2|)|←|↵|1|`.\n              // * So we temporarily swallow indentations until we reach a NL or deindent.\n              go(toks, false, oldStack, swallowedInd + 1,\n                BRACKETS(k0, acc.reverse)(l0.right ++ l1.left) -> (l0 ++ l1) :: oldAcc)\n            case ((Indent, loc), oldAcc) :: stack\n            if k1 === Indent && acc.forall { case (SPACE | NEWLINE, _) => true; case _ => false } =>\n              // * Ignore empty indented blocks:\n              go(rest, false, stack, swallowedInd, oldAcc)\n            case ((k0, l0), oldAcc) :: stack =>\n              if k0 =/= k1 && !(k0 === Unquote && k1 === Curly) then\n                raise(ErrorReport(msg\"Mistmatched closing ${k1.name}\" -> S(l1) ::\n                  msg\"does not correspond to opening ${k0.name}\" -> S(l0) :: Nil,\n                  source = Parsing))\n              val accr = acc match\n                // * This is to flatten nested brackets like `BRACES(INDENT(acc))`\n                // * ie to make:\n                // *    foo {\n                // *      a\n                // *      b\n                // *      c\n                // *    }\n                // * parse the same as:\n                // *    foo {a, b, c}\n                case (BRACKETS(Indent, acc), _) :: Nil if k0 is Curly => acc\n                case (NEWLINE, _) :: (BRACKETS(Indent, acc), _) :: Nil if k0 is Curly => acc\n                case _ => acc.reverse\n              val accr2 = accr.dropWhile(_._1 === SPACE)\n              go(rest, true, stack, swallowedInd, BRACKETS(k0, accr2)(l0.right ++ l1.left) -> (l0 ++ l1) :: oldAcc)\n            case Nil =>\n              raise(ErrorReport(msg\"Unexpected closing ${k1.name}\" -> S(l1) :: Nil,\n                source = Parsing))\n              go(rest, false, stack, swallowedInd, acc)\n        case (INDENT, loc) :: rest =>\n          go(OPEN_BRACKET(Indent) -> loc :: rest, false, stack, swallowedInd, acc)\n        case (DEINDENT, loc) :: rest =>\n          go(CLOSE_BRACKET(Indent) -> loc :: rest, false, stack, swallowedInd, acc)\n        case (IDENT(\"<\", true), loc) :: rest if canStartAngles =>\n          go(OPEN_BRACKET(Angle) -> loc :: rest, false, stack, swallowedInd, acc)\n        case (IDENT(\">\", true), loc) :: rest if canStartAngles && (stack match {\n          case ((Angle, _), _) :: _ => true\n          case _ => false\n        }) =>\n          go(CLOSE_BRACKET(Angle) -> loc :: rest, false, stack, swallowedInd, acc)\n        case (IDENT(id, true), loc) :: rest\n        if (canStartAngles && id.forall(_ == '>') && id.length > 1 && (stack match {\n          case ((Angle, _), _) :: _ => true\n          case _ => false\n        })) => // split  `>>` to `>` and `>` so that code like `A<B<C>>` can be parsed correctly\n          go((CLOSE_BRACKET(Angle) -> loc.left) :: (IDENT(id.drop(1), true) -> loc) :: rest, false, stack, swallowedInd, acc)\n        case ((tk @ IDENT(\">\", true), loc)) :: rest if canStartAngles =>\n          raise(WarningReport(\n            msg\"This looks like an angle bracket, but it does not close any angle bracket section\" -> S(loc) ::\n            msg\"Add spaces around it if you intended to use `<` as an operator\" -> N :: Nil,\n            source = Parsing))\n          go(rest, false, stack,swallowedInd, tk -> loc :: acc)\n        case (tk: Stroken, loc) :: rest =>\n          go(rest, tk match {\n            case SPACE | NEWLINE => false\n            case _ => true\n          }, stack, swallowedInd, tk -> loc :: acc)\n        case Nil =>\n          stack match\n            case ((Indent, loc), oldAcc) :: _ =>\n              go(CLOSE_BRACKET(Indent) -> loc/*FIXME not proper loc...*/ :: Nil, false, stack, swallowedInd, acc)\n            case ((k, l0), oldAcc) :: stack =>\n              raise(ErrorReport(msg\"Unmatched opening ${k.name}\" -> S(l0) :: (\n                if k === Angle then\n                  msg\"Note that `<` without spaces around it is considered as an angle bracket and not as an operator\" -> N :: Nil\n                else Nil\n              ), source = Parsing))\n              (oldAcc ::: acc).reverse\n            case Nil => acc.reverse\n    \n    go(tokens, false, Nil, 0, Nil)\n    \n  \n\nobject Lexer:\n  \n  type TokLoc = (Token, Loc)\n  \n  val keywords: Set[Str] = Set(\n    \"if\",\n    \"then\",\n    \"else\",\n    \"case\",\n    \"fun\",\n    \"val\",\n    \"var\",\n    // \"is\",\n    // \"as\",\n    \"of\",\n    // \"and\",\n    // \"or\",\n    \"let\",\n    \"rec\",\n    \"in\",\n    // \"any\",\n    // \"all\",\n    \"mut\",\n    \"set\",\n    \"do\",\n    \"while\",\n    \"declare\",\n    \"class\",\n    \"trait\",\n    \"mixin\",\n    \"interface\",\n    \"extends\",\n    \"override\",\n    \"super\",\n    \"new\",\n    \"namespace\",\n    \"module\",\n    \"type\",\n    \"where\",\n    \"forall\",\n    \"exists\",\n    \"in\",\n    \"out\",\n    \"null\",\n    \"undefined\",\n    \"abstract\",\n    \"constructor\",\n    \"virtual\",\n    \"staged\"\n  )\n  \n  private val SEP = \"┊\"\n  \n  def printToken(tl: TokLoc): Str = tl match\n    case (SPACE, _) => \" \"\n    case (COMMA, _) => \"`,`\"\n    case (PERIOD, _) => \"`.`\"\n    case (NEWLINE, _) => \"↵\"\n    case (INDENT, _) => \"→\"\n    case (DEINDENT, _) => \"←\"\n    case (ERROR, _) => \"<error>\"\n    case (QUOTE, _) => \"`\"\n    case (LITVAL(lv), _) => lv.idStr\n    // case (KEYWRD(name: String), _) => \"#\" + name\n    case (IDENT(name, symbolic), _) => name\n    case (SELECT(name, false), _) => \".\" + name\n    case (SELECT(name, true), _) => \"!\" + name\n    case (OPEN_BRACKET(k), _) => k.beg\n    case (CLOSE_BRACKET(k), _) => k.end\n    case (BRACKETS(k, contents), _) =>\n      k.beg + \"⟨\" + printTokens(contents) + \"⟩\" + k.end\n    case (COMMENT(text), _) => \"/*\" + text + \"*/\"\n    case (SUSPENSION(true), _) => \"...\"\n    case (SUSPENSION(false), _) => \"..\"\n    case (ESC_IDENT(name), _) => name\n  \n  def printTokens(ts: Ls[TokLoc]): Str =\n    ts.iterator.map(printToken).mkString(SEP, SEP, SEP)\n  \n  \n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/syntax/ParseRule.scala",
    "content": "package hkmc2\npackage syntax\n\nimport sourcecode.{Name, Line}\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.Message._\n\nimport BracketKind._\nimport syntax.Tree.Keywrd\nimport semantics.Elaborator.State\n\n\n// * TODO: add lookahead to Expr as a PartialFunction[Ls[Token], Bool]\n\nenum Alt[+A]:\n  case Kw[Rest, +Res](kw: Keyword)(val rest: ParseRule[Rest])(val k: (Keywrd[kw.type], Rest) => Res) extends Alt[Res]\n  case Expr[Rest, +Res](rest: ParseRule[Rest])(val k: (Tree, Rest) => Res) extends Alt[Res]\n  case Blk[Rest, +Res](rest: ParseRule[Rest])(val k: (Tree, Rest) => Res) extends Alt[Res]\n  case End()(val a: () => A)\n  \n  def map[B](f: A => B): Alt[B] = \n    this match\n    case k: Kw[rest, A] => Kw(k.kw)(k.rest)((kw, rest) => f(k.k(kw, rest)))\n    case e: Expr[rest, A] => Expr(e.rest)((tree, rest) => f(e.k(tree, rest)))\n    case e: End[?] => End()(() => f(e.a()))\n    case b: Blk[rest, A] => Blk(b.rest)((tree, rest) => f(b.k(tree, rest)))\n\ndef end[A](a: => A): Alt[A] = Alt.End()(() => a)\n\ndef discard[A]: (A, Unit) => A = { case (a, _) => a }\n\ndef extendLoc[T <: Tree]: (Keywrd[?], T) => T = { case (k, a) => a.mkLocWith(k) }\n\ndef discardKw[Rest](kw: Keyword)(rest: ParseRule[Rest]): Alt[Rest] =\n  Alt.Kw(kw)(rest)((_, rest) => rest)\ndef keepKw[Rest](kw: Keyword)(rest: ParseRule[Rest]): Alt[Keywrd[kw.type] -> Rest] = \n  Alt.Kw(kw)(rest)((k, rest) => k -> rest)\n\nclass ParseRule[+A](val name: Str, val omitAltsStr: Bool = false)(val alts: Alt[A]*):\n  def map[B](f: A => B): ParseRule[B] =\n    ParseRule(name)(alts.map(_.map(f))*)\n  \n  override def toString: Str = s\"$name ::= \" + alts.mkString(\" | \")\n  \n  lazy val emptyAlt = alts.collectFirst { case e: Alt.End[?] => e.a }\n  \n  lazy val kwAlts = alts.collect { case alt: Alt.Kw[rst, A] => alt.kw.name -> alt }.toMap\n\n  def getKwAlt(k: Keyword, loc: Opt[Loc]) =\n    kwAlts.get(k.name).map: kwAlt => \n      kwAlt.rest.map(a => kwAlt.k(new Keywrd(k.asInstanceOf[kwAlt.kw.type]).withLoc(loc), a))\n  \n  lazy val exprAlt = alts.collectFirst { case alt: Alt.Expr[rst, A] => alt }\n  lazy val blkAlt = alts.collectFirst { case alt: Alt.Blk[rst, A] => alt }\n  \n  def mkAfterStr: Str = if omitAltsStr then \"in this position\" else s\"after $name\"\n  \n  def whatComesAfter: Str = if omitAltsStr then name else\n    alts.map:\n      case Alt.Kw(kw) => s\"'${kw.name}' keyword\"\n      case Alt.Expr(rest) => \"expression\"\n      case Alt.Blk(rest) => \"block\"\n      case Alt.End() => \"end of input\"\n    .toList\n    match\n      case Nil => \"nothing at all\"\n      case str :: Nil => str\n      case str1 :: str2 :: Nil => s\"$str1 or $str2\"\n      case strs => strs.init.mkString(\", \") + \", or \" + strs.last\n\nend ParseRule\n\n\nclass ParseRules(using State):\n  import Keyword.*\n  import Alt.*\n  import Tree.*\n  \n  val standaloneExpr =\n    Expr(ParseRule(\"expression\")(end(())))((l, _: Unit) => l)\n  \n  def prefixed(kw: Keyword.Prefix): Alt[Tree] = prefixed(kw, standaloneExpr)\n  def prefixed(kw: Keyword.Prefix, body: Alt[Tree]) =\n    Kw(kw)(ParseRule(s\"prefix keyword '${kw.name}'\")(body))((k, r) => Tree.PrefixApp(k, r))\n  \n  def modified(kw: Keyword.Modifier): Alt[Tree] = modified(kw, standaloneExpr)\n  def modified(kw: Keyword.Modifier, body: Alt[Tree]) =\n    Kw(kw)(ParseRule(s\"modifier keyword '${kw.name}'\")(body)):\n      case (k: Keywrd[Keyword.Modifier], r) => Tree.Modified(k, r)\n  \n  def exprOrBlk[Rest, Res](body: ParseRule[Rest])(k: (Tree, Rest) => Res): List[Alt[Res]] =\n    Expr(body)(k) ::\n    Blk(body)(k) ::\n    Nil\n  \n  def standaloneExprOrBlk[Rest, Res]: List[Alt[Tree]] =\n    standaloneExpr ::\n    Blk(ParseRule(\"block\")(end(())))((l, _: Unit) => l) ::\n    Nil\n  \n  val typeDeclTemplate: Alt[Opt[Tree]] = end(N)\n  \n  /* // * What we had before we allowed parsing juxtapositions\n  def termDefBody(k: TermDefKind): ParseRule[Tree] = \n      ParseRule(s\"'${k.str}' binding keyword\")(\n        Expr(\n          ParseRule(s\"'${k.str}' binding head\")(\n            Expr(\n              ParseRule(s\"'${k.str}' binding name part\")(\n                funBody(k).map(b => (b, N)),\n                funSign(k),\n              )\n            ) { case (sym, (sign, rhs)) => (S(sym), sign, rhs) },\n            funBody(k).map(b => (N, N, b)),\n            funSign(k).map(sb => (N, sb._1, sb._2)),\n          )\n        ) {\n          case (lhs, (N, sign, rhs)) => TermDef(k, N, S(lhs), sign, rhs)\n          case (lhs, (sym, sign, rhs)) => TermDef(k, S(lhs), sym, sign, rhs)\n        }\n      )\n  */\n  def termDefBody(k: TermDefKind): ParseRule[Tree] = \n      ParseRule(s\"'${k.str}' binding keyword\")(\n        Expr(\n          ParseRule(s\"'${k.str}' binding head\")(\n            funBody(k),\n            end(N),\n          )\n        ) {\n          case (lhs, rhs) => TermDef(k, lhs, rhs)\n        }\n      )\n  \n  def typeDeclBody(k: TypeDefKind): ParseRule[TypeDef] =\n    ParseRule(\"type declaration keyword\"):\n      Expr(\n        ParseRule(\"type declaration head\"):\n          end(())\n      ):\n        case (head, ()) =>\n          TypeDef(k, head, N)\n  \n  def letLike(kw: Keyword.LetLike) = \n    keepKw(kw)(\n      ParseRule(s\"'${kw.name}' binding keyword\")(\n        Expr(\n          ParseRule(s\"'${kw.name}' binding head\")(\n            discardKw(`=`):\n              ParseRule(s\"'${kw.name}' binding equals sign\")(\n                exprOrBlk(\n                  ParseRule(s\"'${kw.name}' binding right-hand side\")(\n                    discardKw(`in`):\n                      ParseRule(s\"'${kw.name}' binding `in` clause\")(\n                        exprOrBlk(\n                          ParseRule(s\"'${kw.name}' binding body\"){end{()}}\n                        ){ (body, _: Unit) => S(body) }*\n                      ),\n                    end(N)\n                  )\n                ) { (rhs, body) => (S(rhs), body) }*\n              ),\n            discardKw(`in`):\n              ParseRule(s\"'${kw.name}' binding `in` clause\")(\n                exprOrBlk(\n                  ParseRule(s\"'${kw.name}' binding body\")(end(()))\n                ){ (body, _: Unit) => N -> S(body) }*\n              )\n            ,\n            end(N -> N)\n          )\n        ) {\n          case (lhs, (rhs, body)) => (lhs, rhs, body)\n        }\n      )\n    ).map {\n      case (kw, (lhs, rhs, body)) => LetLike(kw, lhs, rhs, body)\n    }\n  \n  def ifLike(kw: Keyword.IfLike): Alt[Tree] =\n    Kw(kw)(\n      ParseRule(s\"'${kw.name}' keyword\")(\n        Expr(\n          ParseRule(s\"'${kw.name}' expression\")(\n            end(N),\n            Kw(`else`)(\n              ParseRule(s\"`else` keyword\")(\n                exprOrBlk(ParseRule(s\"`else` expression\")(end(()))):\n                  discard\n                *\n              )\n            ) {  case (elsKw, default) => S((elsKw, default)) }\n          )\n        ):\n          case (split, S((elsKw, default))) =>\n            val clause = PrefixApp(elsKw, default)\n            val items = split match\n              case Block(stmts) => stmts.appended(clause)\n              case _ => split :: clause :: Nil\n            Block(items)\n          case (split, N) => split\n        ,\n        Blk(\n          ParseRule(s\"'${kw.name}' block\")(end(()))\n        )(discard)\n      )\n    ) { case (kw, body) => IfLike(kw, body) }\n  \n  def typeAliasLike(kw: Keyword, kind: TypeDefKind): Alt[TypeDef] =\n    keepKw(kw):\n      ParseRule(s\"${kind.desc} declaration\"):\n        Expr(\n          ParseRule(s\"${kind.desc} head\")(\n            discardKw(`=`):\n              ParseRule(s\"${kind.desc} declaration equals sign\")(\n                exprOrBlk(\n                  ParseRule(s\"${kind.desc} declaration right-hand side\")(\n                    end(())\n                  )\n                ) { case (rhs, ()) => S(rhs) }*),\n            end(N),\n          )\n        ) { (lhs, rhs) => TypeDef(kind, lhs, rhs) }\n    .map {\n      case (kw, t) => t.mkLocWith(kw)\n    }\n  \n  val prefixRules: ParseRule[Tree] = ParseRule(\"start of expression\", omitAltsStr = true)(\n    letLike(`let`),\n    letLike(`set`),\n    \n    keepKw(`handle`):\n      ParseRule(\"'handle' binding keyword\"):\n        Expr(\n          ParseRule(\"'handle' binding head\"):\n            discardKw(`=`):\n              ParseRule(\"'handle' binding equals sign\"):\n                Expr(\n                  ParseRule(\"'handle' binding class name\"):\n                    discardKw(`with`):\n                      ParseRule(\"type declaration body\")(\n                        Blk(\n                          ParseRule(\"type declaration block\")(\n                            discardKw(`in`):\n                              ParseRule(s\"'handle' binding `in` clause\")(\n                                exprOrBlk(ParseRule(s\"'handle' binding body\")(end(())))((body, _: Unit) => S(body))*\n                              ),\n                            end(N))\n                        ) { case (res, t) => (S(res), t) }\n                      )\n                ) { case (rhs, (S(defs), body)) => (rhs, defs, body) }\n        ) { case (lhs, (rhs, defs, body)) => Hndl(lhs, rhs, defs, body) }\n    .map { case (kw, h) => h.mkLocWith(kw) }\n    ,\n    keepKw(`new`):\n      val withRefinement = discardKw(`with`)(\n          ParseRule(\"'new' body\")(\n            Blk(ParseRule(\"'new' expression\")(end(()))) { case (res: Block // FIXME: can it be something else?\n              , ()) => S(res) }\n          )\n        )\n      ParseRule(\"`new` keyword\")(\n        (\n          withRefinement.map(rfto => LexicalNew(N, rfto)) ::\n          exprOrBlk(ParseRule(\"`new` expression\")(\n            withRefinement,\n            end(N),\n          ))((body, rfto) => LexicalNew(S(body), rfto))\n        )*\n      )\n    .map { case (kw, nu) => nu.mkLocWith(kw) }\n    ,\n    Kw(`in`)(\n      ParseRule(\"modifier keyword `in`\"):\n        Expr(\n          ParseRule(\"`in` expression\")(\n            Kw(`out`)(ParseRule(s\"modifier keyword `out`\")(standaloneExpr)):\n              case (kw, s) => S(Tree.Modified(kw, s)),\n            end(N),\n          )\n        ) {\n          case (lhs, S(rhs)) => Tup(lhs :: rhs :: Nil)\n          case (lhs, N) => lhs\n        }\n    ) {\n      case (kw, Tup(lhs :: rhs :: Nil)) => Tup(Modified(kw, lhs) :: rhs :: Nil)\n      case (kw, lhs) => Modified(kw, lhs)\n    },\n    ifLike(`if`),\n    ifLike(`while`),\n    Kw(`assert`)(\n      ParseRule(s\"'assert' keyword\")(\n        exprOrBlk(\n          ParseRule(s\"'assert' expression\")(\n            end(N),\n            Kw(`else`)(\n              ParseRule(s\"`else` keyword\")(\n                exprOrBlk(ParseRule(s\"`else` expression\")(end(()))):\n                  discard\n                *\n              )\n            ) {  case (elsKw, default) => S((elsKw, default)) }\n          )\n        )(_ -> _)*\n      )\n    ):\n      case (kw, (rhs, els)) => Assert(kw, rhs, N, els)\n    ,\n    Kw(`else`)(\n      ParseRule(\"`else` clause\")(\n        Expr(ParseRule(\"`else` expression\")(end(())))(discard),\n        Blk(ParseRule(\"`else` expression\")(end(())))(discard)\n      )\n    ) { case (kwrd, tree) => PrefixApp(kwrd, tree) },\n    keepKw(`case`):\n      ParseRule(\"`case` keyword\")(\n        exprOrBlk(ParseRule(\"`case` branches\")(end(())))((body, _: Unit) => body)*\n      )\n    .map { case (kw, body) => Case(kw, body) }\n    ,\n    keepKw(`region`):\n      ParseRule(\"`region` keyword\"):\n        Expr(\n          ParseRule(\"`region` declaration\"):\n            discardKw(`in`):\n              ParseRule(\"`in` keyword\")(\n                Expr(ParseRule(\"'region' expression\")(end(())))((body, _: Unit) => body),\n                Blk(ParseRule(\"'region' block\")(end(())))((body, _: Unit) => body)\n              )\n        ) { case (name, body) => Region(name, body) }\n    .map { case (kw, r) => r.mkLocWith(kw) }\n    ,\n    keepKw(`outer`):\n      ParseRule(\"outer binding operator\")(\n        Expr(\n          ParseRule(\"`outer` binding name\")(end(()))\n        ){ (body, _: Unit) => Outer(S(body)) },\n        end(Outer(N))\n      )\n    .map { case (kw, o) => o.mkLocWith(kw) }\n    ,\n    keepKw(`constructor`):\n      ParseRule(\"constructor keyword\"):\n        Blk(\n          ParseRule(s\"constructor block\")(end(()))\n        ) { case (body, _) => Constructor(body) }\n    .map { case (kw, c) => c.mkLocWith(kw) }\n    ,\n    Kw(`fun`)(termDefBody(Fun))(extendLoc),\n    Kw(`val`)(termDefBody(ImmutVal))(extendLoc),\n    Kw(`using`)(termDefBody(Ins))(extendLoc),\n    typeAliasLike(`type`, Als),\n    typeAliasLike(`pattern`, Pat),\n    Kw(`class`)(typeDeclBody(Cls))(extendLoc),\n    Kw(`trait`)(typeDeclBody(Trt))(extendLoc),\n    Kw(`module`)(typeDeclBody(Mod))(extendLoc),\n    Kw(`object`)(typeDeclBody(Obj))(extendLoc),\n    keepKw(`open`):\n      ParseRule(\"'open' keyword\")(\n        exprOrBlk(ParseRule(\"'open' declaration\")(end(()))){\n          case (body, _) => Open(body)}*)\n    .map { case (kw, o) => o.mkLocWith(kw) }\n    ,\n    modified(`abstract`, keepKw(`class`)(typeDeclBody(Cls)).map { case (kw, c) => c.mkLocWith(kw) }),\n    Kw(`mut`)(ParseRule(s\"'mut' keyword\")(standaloneExprOrBlk*)) {\n      case (kw, body) => Tree.Modified(kw, body)\n    },\n    Kw(`do`)(\n      ParseRule(s\"'do' keyword\")(\n        exprOrBlk(ParseRule(s\"'do' body\")(end(()))):\n          discard\n        *)\n    ) { case (kw, body) => Tree.PrefixApp(kw, body) },\n    Kw(`return`)(\n      ParseRule(s\"'return' keyword\")(\n        // * The Block alternative is important, otherwise\n        // *   > return\n        // *   >   print(\"returning...\")\n        // *   >   x\n        // * is terated as a keyword stutter: { return print(\"returning...\"); return x }\n        end(Unt()) :: exprOrBlk(ParseRule(s\"'return' body\")(end(()))):\n          discard\n        *)\n    ) { case (kw, body) => Tree.PrefixApp(kw, body) },\n    prefixed(`drop`),\n    prefixed(`not`),\n    prefixed(`new!`),\n    prefixed(`throw`),\n    prefixed(`import`),\n    modified(`virtual`),\n    modified(`override`),\n    modified(`declare`),\n    modified(`data`),\n    modified(`public`),\n    modified(`private`),\n    modified(`out`),\n    modified(`staged`),\n    singleKw(`true`)(BoolLit(true)),\n    singleKw(`false`)(BoolLit(false)),\n    singleKw(`undefined`)(UnitLit(false)),\n    singleKw(`null`)(UnitLit(true)),\n    singleKw(`this`)(Ident(\"this\")),\n    singleKw(Keyword.__)(Under()),\n    Kw(`#`)(\n      ParseRule(s\"'#' directive keyword\")(\n        Expr(ParseRule(s\"'#' directive body\")(end(()))){ case (body, ()) => body }\n      )\n    ) { case (kw, body) =>\n      body match\n        case App(prefix, args) => Directive(prefix, args).mkLocWith(kw)\n        case _ => Directive(body, Tup(Nil)).mkLocWith(kw)\n    },\n    standaloneExpr,\n  )\n  \n  def singleKw[T <: Tree](kw: Keyword)(v: => T): Alt[T] =\n    Kw(kw)(ParseRule(s\"'${kw.name}' keyword\")(end(v)))((kwrd, v) => v.withLocOf(kwrd))\n  \n  \n  val prefixRulesAllowIndentedBlock: ParseRule[Tree] =\n    ParseRule(prefixRules.name, prefixRules.omitAltsStr)(prefixRules.alts :+ \n        (Blk(\n          ParseRule(\"block\"):\n            end(())\n        ) { case (res, ()) => res })*)\n  \n  /* \n  def funSign(k: TermDefKind): Alt[(S[Tree], Opt[Tree])] =\n    Kw(`:`):\n      ParseRule(s\"'${k.str}' binding colon\"):\n        Expr(\n          ParseRule(s\"'${k.str}' binding signature\")(\n            funBody(k),\n            end(N),\n          )\n        ) { case (sign, rhs) => (S(sign), rhs) }\n  */\n  \n  def funBody(k: TermDefKind): Alt[S[Tree]] =\n    discardKw(`=`):\n      ParseRule(s\"'${k.str}' binding equals sign\")(\n        Expr(\n          ParseRule(s\"'${k.str}' binding right-hand side\")(end(()))\n        ) { case (rhs, ()) => S(rhs) }\n        ,\n        Blk(\n          ParseRule(s\"'${k.str}' binding block\")(end(()))\n        ) { case (rhs, _) => S(rhs) }\n      )\n  \n  def keywordThenTree[A, K <: Keyword](kw: K)(k: (Keywrd[kw.type], Tree) => A): Alt[A] =\n    keepKw(kw):\n      ParseRule(s\"'${kw}' operator\")(\n        Expr(ParseRule(s\"'${kw}' operator right-hand side\")(end(()))):\n          case (tree, ()) => tree\n        // * Interestingly, this does not seem to change anything:\n        // exprOrBlk(ParseRule(s\"'${kw}' operator right-hand side\")(End(())))(k)*\n      )\n    .map(k.tupled)\n  \n  def makeInfixRule[K <: Infix](kw: K): Alt[Tree => Tree] =\n    keywordThenTree(kw):\n      case (kw, rhs) => lhs => InfixApp(lhs, kw, rhs)\n  \n  val infixRules: ParseRule[Tree => Tree] = ParseRule(\"continuation of expression\")(\n    makeInfixRule(`and`),\n    makeInfixRule(`or`),\n    makeInfixRule(`is`),\n    makeInfixRule(`as`),\n    makeInfixRule(`then`),\n    makeInfixRule(`:`),\n    makeInfixRule(`extends`),\n    makeInfixRule(`restricts`),\n    makeInfixRule(`do`),\n    makeInfixRule(`where`),\n    makeInfixRule(`with`),\n    makeInfixRule(`#`),\n  )\n\nend ParseRules\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/syntax/Parser.scala",
    "content": "package hkmc2\npackage syntax\n\nimport scala.util.boundary\nimport sourcecode.{Name, Line}\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.Message._\nimport BracketKind._\n\nimport Tree.*\nimport Parser.*\nimport scala.annotation.tailrec\n\nimport Keyword.`let`\nimport hkmc2.syntax.Keyword.Ellipsis\n\nimport semantics.Elaborator.State\n\n\nval charPrecList: List[Str] = List(\n    \"\", // `of` rhs\n    \",\",\n    // ^ for keywords\n    \";\",\n    // \"=\", // higher than || means `a == 1 || b` parses surprisingly\n    \"@\",\n    \":\",\n    \"|\",\n    \"&\",\n    \"=\",\n    // \"/ \\\\\",\n    \"^\",\n    // \"= !\",\n    \"!\",\n    \"< >\",\n    \"+ -\",\n    \"* / %\",\n    \"~\",\n    \"\", // Precedence of prefix operators\n    \"\", // Precedence of application\n    \"\", // Precedence of `new`\n    // \".\",\n    \". \\\\\",\n  )\n\n\nobject Parser:\n  \n  type TokLoc = (Stroken, Loc)\n  \n  type LTL = Ls[TokLoc]\n  \n  private val MinPrec = 0\n  private val NoElsePrec = MinPrec + 1\n  \n  def verbose =\n    // true\n    false\n  \n  private val precOf: Map[Char,Int] =\n    charPrecList.zipWithIndex.flatMap {\n      case (cs, i) => cs.filterNot(_ === ' ').map(_ -> (i + Keyword.maxPrec.get))\n    }.toMap.withDefaultValue(Int.MaxValue)\n  \n  // * Note: keywords without a specified right precedence are now assumed to have right precedence `CommaPrecNext`\n  \n  // private val CommaPrec = prec(',')\n  private val CommaPrec = 0\n  private val CommaPrecNext = CommaPrec + 1\n  private val CommaPrecNext2 = CommaPrecNext + 1\n  private val SelPrec = precOf('.')\n  private val AppPrec = SelPrec - 1\n  private val PrefixOpsPrec = AppPrec - 1\n  // * Annotation body precedence: above all keyword infix ops (like `as`, `is`)\n  // * but below character-based operators (like `+`, `;`).\n  private val AnnotBodyPrec = Keyword.maxPrec.get + 1\n  \n  final def opCharPrec(opChar: Char): Int = precOf(opChar)\n  final def opPrec(opStr: Str): (Int, Int) = opStr match {\n    case \"+.\" | \"-.\" | \"*.\" =>\n      (precOf(opStr.head), precOf(opStr.head))\n    case _ if opStr.exists(_.isLetter) =>\n      (Keyword.maxPrec.get, Keyword.maxPrec.get)\n    case _ =>\n      val r = opStr.last\n      (precOf(opStr.head), precOf(r) - (if r === ',' || r === ':' then 1 else 0))\n  }\n  val prefixOps: Set[Str] = Set(\"!\", \"+\", \"-\", \"~\", \"@\", \"|\", \"&\")\n  \n  type Indent_Curly = Curly.type | Indent.type\n  \n  type NEWLINE_COMMA = NEWLINE.type | COMMA.type\n  \n  object KEYWORD:\n    def unapply(t: IDENT): Opt[Keyword] = t match\n      case IDENT(nme, sym) => Keyword.all.get(nme)\n      // case IDENT(nme, sym) => Keyword.all.get(nme).map(_.name)\n      // case IDENT(nme, sym) if Keyword.all.contains(nme) => S(nme)\n  \n  object OP:\n    def unapply(t: IDENT): Opt[Str] = t match\n      case IDENT(nme, true) if !Keyword.all.contains(nme) => S(nme)\n      case _ => N\n  \n  object ALPHA:\n    def unapply(t: Token): Opt[Str] = t match\n      case IDENT(nme, false) if !Keyword.all.contains(nme) => S(nme)\n      case _ => N\n  \n  object NOISE:\n    def get(ts: Ls[TokLoc]): Ls[TokLoc] = ts match\n      case (SPACE, _) :: rest => get(rest)\n      case (COMMENT(_), _) :: rest => get(rest)\n      case (NEWLINE, _) :: (COMMENT(_), _) :: rest => get(rest)\n      case (BRACKETS(Indent, NOISE(Nil)), _) :: rest => get(rest)\n      case _ => ts\n    def unapply(ts: Ls[TokLoc]): S[Ls[TokLoc]] =\n      S(get(ts))\n  \n  extension (loc: Loc)\n    def showStart: String =\n      loc.origin.fph.getLineColAt(loc.spanStart) match\n        case (ln, _, col) => s\"Ln $ln Col $col\"\n    def showEnd: String =\n      loc.origin.fph.getLineColAt(loc.spanStart) match\n        case (ln, _, col) => s\"Ln $ln Col $col\"\n  \n  extension (trees: Ls[Tree])\n    /** Note that the innermost annotation is the leftmost. */\n    def annotate(tree: Tree): Tree = trees.foldLeft(tree):\n      case (target, annotation) => Annotated(annotation, target)\n  \nend Parser\nimport Parser._\n\nabstract class Parser(\n  origin: Origin,\n  tokens: Ls[TokLoc],\n  rules: ParseRules,\n  raiseFun: Diagnostic => Unit,\n  val dbg: Bool,\n  // fallbackLoc: Opt[Loc], description: Str = \"input\",\n)(using State):\n  outer =>\n  \n  import rules.*\n  \n  object PrefixRule:\n    def unapply(t: IDENT): Opt[(Keyword, ParseRule[Tree])] = t match\n      // * the Loc of this Keywrd is added at the call site\n      case KEYWORD(kw) => prefixRules.getKwAlt(kw, N).map: subRule =>\n        kw -> subRule\n      case _ => N\n  \n  protected def doPrintDbg(msg: => Str): Unit\n  protected def printDbg(msg: => Any): Unit =\n    doPrintDbg(\"│ \" * this.indent + msg)\n  \n  protected var indent = 0\n  private var _cur: Ls[TokLoc] = preprocessTokens(tokens)\n  \n  private def preprocessTokens(tokens: Ls[TokLoc]): Ls[TokLoc] = tokens match\n    case (IDENT(\"new\", false), l1) :: (IDENT(\"!\", true), l2) :: rest =>\n      (IDENT(\"new!\", false), l1 ++ l2) :: preprocessTokens(rest)\n    // * Remove empty indented sections\n    case (BRACKETS(Indent, toks), _) :: rest\n    if toks.forall:\n      case (NEWLINE | SPACE, _) => true\n      case _ => false\n    =>\n      preprocessTokens(rest)\n    // * Expands end-of-line suspensions that introduce implied indentation,\n    // * skipping NOISE tokens between `...` and NEWLINE (eg `... // hello\\n body`)\n    // * Note: using `NEWLINE_COMMA` instead of `NEWLINE` causes misparsing of things like `fun foo(..., ...)`\n    case (SUSPENSION(true), l0) :: NOISE((NEWLINE, l1) :: rest) =>\n      val outerLoc = l0.left ++ rest.lastOption.map(_._2.right)\n      val innerLoc = l1.right ++ rest.lastOption.map(_._2.left)\n      BRACKETS(Indent, preprocessTokens(rest))(innerLoc) -> outerLoc :: Nil\n    case tl :: rest =>\n      val rest2 = preprocessTokens(rest)\n      if rest2 is rest then tokens\n      else tl :: rest2\n    case Nil => tokens\n  \n  private def wrap[R](args: => Any)(using l: Line, n: Name)(mkRes: => R): R =\n    printDbg(s\"@ ${n.value}${args match {\n      case it: Iterable[_] => it.mkString(\"(\", \",\", \")\")\n      case _: Product => args\n      case _ => s\"($args)\"\n    }}    [at syntax/Parser.scala:${l.value}]\")\n    val res = try\n      indent += 1\n      mkRes\n    finally indent -= 1\n    printDbg(s\"= $res\")\n    res\n  \n  final def rec(tokens: Ls[Stroken -> Loc], fallbackLoc: Opt[Loc], description: Str): Parser =\n    new Parser(origin, tokens, rules, raiseFun, dbg\n        // , fallbackLoc, description\n    ):\n      def doPrintDbg(msg: => Str): Unit = outer.printDbg(\"> \" + msg)\n  \n  def resetCur(newCur: Ls[TokLoc]): Unit =\n    _cur = newCur\n    // _modifiersCache = ModifierSet.empty\n  \n  private lazy val lastLoc =\n    tokens.lastOption.map(_._2.right)//.orElse(fallbackLoc)\n  \n  private def summarizeCur =\n    Lexer.printTokens(_cur.take(5)) + (if _cur.sizeIs > 5 then \"...\" else \"\")\n  \n  \n  private def cur(implicit l: Line, n: Name) =\n    if dbg then printDbg(s\"? ${n.value}\\t\\tinspects ${summarizeCur}    [at syntax/Parser.scala:${l.value}]\")\n    while !_cur.isEmpty && (_cur.head._1 match {\n      case COMMENT(_) => true\n      case _ => false\n    }) do consume\n    _cur\n  \n  private def cur_=(using l: Line, n: Name)(newCur: Ls[TokLoc]) =\n    if dbg then printDbg(s\"! ${n.value}\\t\\tresets ${Lexer.printTokens(newCur)}    [at syntax/Parser.scala:${l.value}]\")\n    _cur = newCur\n  \n  final def consume(implicit l: Line, n: Name): Unit =\n    if dbg then printDbg(s\"! ${n.value}\\t\\tconsumes ${Lexer.printTokens(_cur.take(1))}    [at syntax/Parser.scala:${l.value}]\")\n    resetCur(_cur.tailOption.getOrElse(Nil)) // FIXME throw error if empty?\n  \n  private def yeetSpaces(using Line, Name): Ls[TokLoc] =\n    _cur = NOISE.get(_cur)\n    _cur\n  \n  \n  // final def raise(mkDiag: => Diagnostic)(implicit fe: FoundErr = false): Unit =\n  //   if (!foundErr) raiseFun(mkDiag)\n  final def raise(mkDiag: => Diagnostic): Unit =\n    raiseFun(mkDiag)\n  \n  private def errExpr =\n    Tree.Error().withLoc(cur.headOption.fold(lastLoc)(_._2 |> some))\n  private def empty =\n    Tree.Empty().withLoc(cur.headOption.fold(lastLoc)(_._2.left |> some))\n  \n  final def err(msgs: Ls[Message -> Opt[Loc]])(implicit l: Line, n: Name): Unit =\n    printDbg(s\"Error    [at syntax/Parser.scala:${l.value}]\")\n    raise(ErrorReport(msgs, source = Diagnostic.Source.Parsing))\n  \n  \n  final def parseAll[R](parser: => R): R =\n    val res = parser\n    cur match\n      case c @ (tk, tkl) :: _ =>\n        val (relevantToken, rl) = c.dropWhile(_._1 === SPACE).headOption.getOrElse(tk, tkl)\n        err(msg\"Expected end of input; found ${relevantToken.describe} instead\" -> S(rl) :: Nil)\n      case Nil => ()\n    res\n  \n  \n  final def concludeWith[R](using l: Line)(f: this.type => R): R =\n    wrap(())(concludeWithImpl(f))\n  \n  final def concludeWithImpl[R](f: this.type => R): R =\n    val res = f(this)\n    cur.dropWhile(tk => (tk._1 === SPACE || tk._1 === NEWLINE) && { consume; true }) match\n      case c @ (tk, tkl) :: _ =>\n        val (relevantToken, rl) = c.dropWhile(_._1 === SPACE).headOption.getOrElse(tk, tkl)\n        err(msg\"Unexpected ${relevantToken.describe} here\" -> S(rl) :: Nil)\n      case Nil => ()\n    printDbg(s\"Concluded with $res\")\n    res\n  \n  final def continueWith[R](f: this.type => R): (R, Ls[TokLoc]) =\n    val res = f(this)\n    val rest = cur.dropWhile(tk => (tk._1 === SPACE || tk._1 === NEWLINE) && { consume; true })\n    printDbg(s\"Continued with $res, $rest\")\n    (res, rest)\n  \n  \n  final def maybeIndented[R](f: (Parser, Bool) => R): R =\n    yeetSpaces match\n      case (_: NEWLINE_COMMA, l0) :: _ =>\n        consume\n        while yeetSpaces.headOption.exists(_._1 === NEWLINE) do consume\n        cur match\n        case Nil =>\n        case (tok, loc) :: _ =>\n          raise(WarningReport(\n            msg\"This ${tok.describe} should be indented\" -> S(loc) :: \n            msg\"since it is a continuation of the new line here\" -> S(l0) :: \n            Nil))\n        maybeIndented(f)\n      // case (br @ BRACKETS(Indent | Curly, toks), _) :: _ =>\n      // * Note: not accepting Curly braces here, so as to allow things like `foo({X}, Y)` to parse\n      case (br @ BRACKETS(Indent, toks), _) :: _ =>\n        consume\n        rec(toks, S(br.innerLoc), br.describe).concludeWith(f(_, true))\n      case _ => f(this, false)\n  \n  final def blockMaybeIndented: Ls[Tree] =\n    maybeIndented((p, i) => p.block(allowNewlines = i))\n  \n  \n  /* Note on annotation parsing:\n      There is currently an inconsistency when parsing annotations that start blocks,\n      where the annotatee is parsed with no precedence (because this is done by `block`),\n      so that `@Test 2 as Int` at the top level parses as `@Test (2 as Int)`;\n      but within a subexpression, it is parsed with precendence AnnotBodyPrec,\n      so that, eg, `x is @compile P() as y` parses correctly...\n  */\n  def annot(id: Ident): Tree =\n    val pre = exprCont(id, SelPrec, allowNewlines = false, gobbleSpaces = false)\n    cur match\n    case (br @ BRACKETS(Round, toks), loc) :: _ =>\n      consume\n      val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockMaybeIndented)\n      App(pre, Tup(as).withLoc(S(loc)))\n    case _ => pre\n  \n  \n  def block(allowNewlines: Bool)(using Line): Ls[Tree] = blockOf(prefixRules, Nil, allowNewlines)\n  \n  def blockOf(rule: ParseRule[Tree], annotations: Ls[Tree], allowNewlines: Bool)(using Line): Ls[Tree] =\n    wrap(rule.name, s\"allowNewlines = $allowNewlines\")(blockOfImpl(rule, annotations, allowNewlines))\n  def blockOfImpl(rule: ParseRule[Tree], annotations: Ls[Tree], allowNewlines: Bool): Ls[Tree] =\n    def blockContOf(rule: ParseRule[Tree], annotations: Ls[Tree] = Nil): Ls[Tree] =\n      yeetSpaces match\n        case (COMMA, _) :: _ => consume; blockOf(rule, annotations, allowNewlines)\n        case (NEWLINE, _) :: _ if allowNewlines => consume; blockOf(rule, annotations, allowNewlines)\n        case _ => Nil\n    cur match\n    case Nil => Nil\n    case (NEWLINE, _) :: _ if allowNewlines => consume; blockOf(rule, annotations, allowNewlines)\n    case (COMMA, _) :: _ => consume; blockOf(rule, annotations, allowNewlines)\n    case (SPACE, _) :: _ => consume; blockOf(rule, annotations, allowNewlines)\n    case (br @ BRACKETS(Indent, toks), _) :: _ =>\n      // * Handle indented blocks appearing after comma continuations\n      // * (e.g., in multi-line function calls like `tuple(1,\\n  2)`)\n      consume\n      rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockOf(rule, annotations, true)) ++ blockContOf(rule)\n    case (IDENT(\"@\", _), l0) :: (IDENT(id, false), l1) :: _ =>\n      consume\n      consume\n      val a = annot(new Ident(id).withLoc(S(l0 ++ l1)))\n      yeetSpaces match\n      case Nil =>\n        err(\n          msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}\" -> a.toLoc.map(_.right)\n          :: msg\"found a lone annotation instead\" -> a.toLoc\n          :: Nil\n        )\n        errExpr :: Nil\n      case _ =>\n        blockOf(rule, a :: annotations, allowNewlines = allowNewlines)\n    case (tok @ (id: IDENT), loc) :: _ if id.name =/= \":\" =>\n      Keyword.all.get(id.name) match\n      case S(kw) =>\n        consume\n        rule.getKwAlt(kw, S(loc)) match\n        case S(subRule) =>\n          yeetSpaces match\n          case (tok @ BRACKETS(_: Indent_Curly, toks), loc) :: _ if subRule.blkAlt.isEmpty =>\n            consume\n            val blk = rec(toks, S(tok.innerLoc), tok.describe).concludeWith(_.blockOf(subRule, Nil, allowNewlines)) // FIXME allowNewlines?\n            if blk.isEmpty then\n              err(msg\"Expected ${subRule.whatComesAfter} ${subRule.mkAfterStr}; found end of block instead\" -> S(loc) :: Nil)\n              errExpr\n            blk.map(annotations.annotate) ::: blockContOf(rule)\n          case _ =>\n            val p = kw.rightPrec.getOrElse(CommaPrecNext)\n            val res = parseRule(p, subRule, allowNewlines = allowNewlines).getOrElse(errExpr)\n            annotations.annotate(exprCont(res, CommaPrecNext, allowNewlines = allowNewlines)) :: blockContOf(rule)\n        case N =>\n          \n          // TODO dedup this common-looking logic:\n          \n          rule.exprAlt match\n          case S(exprAlt) =>\n            yeetSpaces match\n            case (tok @ BRACKETS(_: Indent_Curly, toks), loc) :: _ =>\n              consume\n              prefixRules.getKwAlt(kw, S(loc)) match\n              case S(subRule) if subRule.blkAlt.isEmpty =>\n                rec(toks, S(tok.innerLoc), tok.describe).concludeWith { p =>\n                  p.blockOf(subRule.map(e => parseRule(CommaPrecNext, exprAlt.rest, allowNewlines = allowNewlines).map(res => exprAlt.k(e, res)).getOrElse(errExpr)), annotations, allowNewlines)\n                } ++ blockContOf(rule)\n              case _ =>\n                TODO(cur)\n            case _ =>\n              prefixRules.getKwAlt(kw, S(loc)) match\n              case S(subRule) =>\n                val e = exprCont(parseRule(CommaPrecNext, subRule, allowNewlines = allowNewlines)\n                  .getOrElse(errExpr), CommaPrecNext, allowNewlines = allowNewlines)\n                annotations.annotate(parseRule(CommaPrecNext, exprAlt.rest, allowNewlines = allowNewlines).map(res => exprAlt.k(e, res)).getOrElse(errExpr)) :: blockContOf(rule)\n              case N =>\n                // TODO dedup?\n                err(msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found ${tok.describe} instead\" -> S(loc) :: Nil)\n                annotations.annotate(errExpr) :: blockContOf(rule)\n          case N =>\n            err(msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found ${tok.describe} instead\" -> S(loc) :: Nil)\n            annotations.annotate(errExpr) :: blockContOf(rule)\n      case N =>\n        val lhs = tryParseExp(CommaPrecNext, tok, loc, rule, allowNewlines = allowNewlines).getOrElse(errExpr)\n        cur match\n        case (KEYWORD(kw @ (Keyword.`=`)), l0) :: _ /* if kw.leftPrecOrMin > prec */ =>\n          consume\n          val rhs = expr(CommaPrecNext, allowNewlines = allowNewlines)\n          Def(lhs, rhs) :: blockContOf(rule)\n        case _ =>\n          annotations.annotate(lhs) :: blockContOf(rule)\n    case (tok, loc) :: _ =>\n      annotations.annotate(\n        tryParseExp(CommaPrecNext, tok, loc, rule, allowNewlines = allowNewlines).getOrElse(errExpr)\n      ) :: blockContOf(rule)\n  \n  \n  private def tryParseExp[A](prec: Int, tok: Token, loc: Loc, rule: ParseRule[A], allowNewlines: Bool): Opt[A] =\n    rule.exprAlt match\n      case S(exprAlt) =>\n        val e = simpleExpr(prec, allowNewlines = allowNewlines)\n        if verbose then printDbg(\"$ proceed with rule: \" + exprAlt)\n        parseRule(prec, exprAlt.rest, allowNewlines = allowNewlines).map(res => exprAlt.k(e, res))\n      case N =>\n        rule.emptyAlt match\n        case S(res) =>\n          S(res())\n        case N =>\n          err(msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found ${tok.describe} instead\" -> S(loc) :: Nil)\n          N\n  \n  \n  /** A result of None means there was an error (already reported) and nothing could be parsed. */\n  def parseRule[A](prec: Int, rule: ParseRule[A], allowNewlines: Bool)(using Line): Opt[A] =\n    wrap(prec, rule, s\"allowNewlines = $allowNewlines\")(parseRuleImpl(prec, rule, allowNewlines = allowNewlines))\n  def parseRuleImpl[A](prec: Int, rule: ParseRule[A], allowNewlines: Bool): Opt[A] =\n    def tryEmpty(tok: Token, loc: Loc) = rule.emptyAlt match\n      case S(res) => S(res())\n      case N =>\n        consume\n        err(msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found ${tok.describe} instead\" -> S(loc) :: Nil)\n        N\n    yeetSpaces match\n    // case (tok @ (id: IDENT), loc) :: _ if Keyword.all.get(id.name).exists(_.leftPrecOrMin < prec) =>\n    //   printDbg(s\"Precedence of $id < $prec\")\n    //   // TODO dedup with \"nil\" case below?\n    //   rule.emptyAlt match\n    //     case S(res) =>\n    //       S(res)\n    //     case N =>\n    //      err((msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found end of phrase instead\" -> S(loc.left) :: Nil)\n    //       N\n    case (tok @ (id: IDENT), loc) :: _ =>\n      Keyword.all.get(id.name) match\n      case S(Keyword.`:`) | N =>\n        // encountering `:` should lead to parsing an expr (likely a pun)\n        tryParseExp(prec, tok, loc, rule, allowNewlines = allowNewlines)\n      case S(kw) =>\n        rule.getKwAlt(kw, S(loc)) match\n        case S(subRule) =>\n          if verbose then printDbg(s\"$$ proceed with rule: ${subRule.name}\")\n          consume\n          yeetSpaces match\n          case (tok @ BRACKETS(_: Indent_Curly, toks), loc) :: _ if subRule.blkAlt.isEmpty =>\n            consume\n            rec(toks, S(tok.innerLoc), tok.describe)\n              .concludeWith(_.parseRule(kw.rightPrec.getOrElse(CommaPrecNext), subRule, allowNewlines = true))\n          case _ =>\n            parseRule(kw.rightPrec.getOrElse(CommaPrecNext), subRule, allowNewlines = allowNewlines)\n        case N =>\n          if verbose then printDbg(s\"$$ cannot find a rule starting with: ${id.name}\")\n          rule.exprAlt match\n          case S(exprAlt) =>\n            consume\n            prefixRules.getKwAlt(kw, S(loc)) match\n            case S(subRule) =>\n              val e = yeetSpaces match\n                case (br @ BRACKETS(_: Indent_Curly, toks), _brLoc) :: _\n                if subRule.blkAlt.isEmpty && (subRule.kwAlts.nonEmpty || subRule.exprAlt.isDefined) =>\n                  // * Enter this indented block to parse the continuation of a prefix keyword,\n                  // * but only when the subrule doesn't already have its own block handler (`blkAlt.isEmpty`)\n                  // * and has keyword or expression alternatives to parse (`kwAlts.nonEmpty || exprAlt.isDefined`).\n                  // * This skips block entry for keywords registered via `singleKw` (e.g., `true`, `false`,\n                  // * `undefined`, `null`, `this`) whose continuation rule is end-only — they produce a\n                  // * `ParseRule(end(v))` with no `kwAlts`, no `exprAlt`, and no `blkAlt`.\n                  // * Without this guard, `if true` followed by an indented `then`/`else` would consume the\n                  // * block trying to parse `true`'s empty continuation, losing the `then`/`else` tokens.\n                  consume\n                  val blk = rec(toks, S(br.innerLoc), br.describe)\n                    .concludeWith(_.blockOf(subRule, Nil, allowNewlines = true))\n                  val tree = blk match\n                    case Nil =>\n                      err(msg\"Expected ${subRule.whatComesAfter} ${subRule.mkAfterStr}; found empty block instead\"\n                        -> S(_brLoc) :: Nil)\n                      errExpr\n                    case single :: Nil => single\n                    case multiple => Block(multiple)\n                  exprCont(tree, prec, allowNewlines = allowNewlines)\n                case _ =>\n                  exprCont(\n                    parseRule(kw.rightPrecOrMin, subRule, allowNewlines = allowNewlines)\n                      .getOrElse(errExpr), prec, allowNewlines = allowNewlines)\n              parseRule(prec, exprAlt.rest, allowNewlines = allowNewlines).map(res => exprAlt.k(e, res))\n            case N =>\n              tryEmpty(tok, loc)\n          case N =>\n            tryEmpty(tok, loc)\n    case (tok @ (_: NEWLINE_COMMA), l0) :: (id: IDENT, l1) :: _ if allowNewlines && rule.kwAlts.contains(id.name) =>\n      consume\n      parseRule(prec, rule, allowNewlines = allowNewlines)\n    case (tok @ (_: NEWLINE_COMMA), l0) :: _ =>\n      // TODO(cur)\n      rule.emptyAlt match\n        case S(res) => S(res())\n        case N =>\n          //err((msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found ${tok.describe} instead\" -> lastLoc :: Nil)\n          err(msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found ${tok.describe} instead\" -> S(l0) :: Nil)\n          N\n    case (br @ BRACKETS(_: Indent_Curly, toks), loc) :: _ =>\n      // rule.blkAlt match\n      //   case S(res) => S(res)\n      //   case N =>\n      //    err((msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found ${tok.describe} instead\" -> lastLoc :: Nil)\n      //     N\n      \n      if verbose then printDbg(\"$ found an indented\" + (toks match\n        case (_, loc) :: tail =>\n          val lastLoc = tail.lastOption.map(_._2).getOrElse(loc)\n          s\" block from ${loc.showStart} to ${lastLoc.showEnd}\"\n        case Nil => \"empty block\"))\n      rule.blkAlt match\n        case S(exprAlt) =>\n          consume\n          if verbose then printDbg(\"$ found blockAlt; proceed with block\")\n          val e = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.block(allowNewlines = true))\n            |> Tree.Block.apply\n          parseRule(prec, exprAlt.rest, allowNewlines = true).map(res => exprAlt.k(e, res))\n        case N =>\n          \n          if verbose then printDbg(\"$ no blockAlt; proceed with rule\")\n          \n          val continue = toks.headOption match\n            case S(LITVAL(_) -> _) => true\n            case S(IDENT(nme, sym) -> _) =>\n              Keyword.all.contains(nme) && (\n                  rule.kwAlts.contains(nme)\n                  || prefixRules.kwAlts.contains(nme) && rule.exprAlt.nonEmpty\n              ) || rule.exprAlt.nonEmpty\n            case _ => false\n            \n          if continue then\n            consume\n            rec(toks, S(br.innerLoc), br.describe).concludeWith(_.parseRule(prec, rule, allowNewlines = false))\n          else tryEmpty(br, loc)\n          \n    case (tok, loc) :: _ =>\n      if verbose then printDbg(\"$ treat as an expression: \" + tok.describe)\n      tryParseExp(prec, tok, loc, rule, allowNewlines =\n        true /* Making this false somehow makes the following not parse:\n          ```\n          if (print(\"Hello World\"), false)\n            then 0(0)\n            else 1\n          ```\n          and this parse incorrectly (as a kw stutter):\n          ```\n          mut\n            let x = 1\n            in x\n          ```\n        */)\n      // TODO(tok)\n    case Nil =>\n      rule.emptyAlt match\n        case S(res) =>\n          S(res())\n        case N =>\n          err(msg\"Expected ${rule.whatComesAfter} ${rule.mkAfterStr}; found end of input instead\" -> lastLoc :: Nil)\n          N\n  \n  \n  // TODO refactor? This is only used for quotes, which should parse like normal code\n  final def bindings(acc: Ls[Tree -> Tree]): Ls[Tree -> Tree] = \n    cur match {\n      case (SPACE, _) :: _ =>\n        consume\n        bindings(acc)\n      case (_: NEWLINE_COMMA, _) :: _ => // TODO: | ...\n        acc.reverse\n      case (IDENT(nme, sym), l0) :: _ =>\n        consume\n        yeetSpaces match\n          case (IDENT(\"=\", _), l1) :: _ => consume\n          case (tk, l1) :: _ =>\n            err(msg\"Expected `=` after ${nme}; found ${tk.toString} instead\" -> S(l1) :: Nil)\n          case _ => die\n        val rhs = simpleExprImpl(0, allowNewlines = true)\n        val v = Tree.Ident(nme).withLoc(S(l0))\n        cur match {\n          case (COMMA, l1) :: _ =>\n            consume\n            bindings((v -> rhs) :: acc)\n          case _ =>\n            ((v -> rhs) :: acc).reverse\n        }\n      case _ =>\n        Nil\n  }\n  \n  \n  def expr(prec: Int, allowNewlines: Bool)(using Line): Tree =\n    val res = parseRule(prec,\n        prefixRulesAllowIndentedBlock,\n        allowNewlines = allowNewlines\n      ).getOrElse(errExpr) // * a `None` result means an alread-reported error\n    exprCont(res, prec, allowNewlines = allowNewlines)\n  \n  def simpleExpr(prec: Int, allowNewlines: Bool)(using Line): Tree =\n    wrap(prec)(simpleExprImpl(prec, allowNewlines = allowNewlines))\n  def simpleExprImpl(prec: Int, allowNewlines: Bool): Tree =\n    yeetSpaces match\n    case (IDENT(\"=\", _), l0) :: (IDENT(nme, false), l1) :: rest =>\n      consume\n      consume\n      Pun(true, new Ident(nme).withLoc(S(l1)))\n    case (IDENT(\":\", _), l0) :: (IDENT(nme, false), l1) :: rest =>\n      consume\n      consume\n      Pun(false, new Ident(nme).withLoc(S(l1)))\n    case (IDENT(\"@\", _), l0) :: (IDENT(id, false), l1) :: _ =>\n      consume\n      consume\n      val a = annot(new Ident(id).withLoc(S(l0 ++ l1)))\n      exprCont(\n        Annotated(a, simpleExpr(AnnotBodyPrec, allowNewlines = allowNewlines)),\n        prec, allowNewlines = allowNewlines)\n    case (ESC_IDENT(name), loc) :: _ =>\n      consume\n      val id = Tree.Ident(name).withLoc(S(loc))\n      exprCont(id, prec, allowNewlines = true)\n    case (IDENT(nme, sym), loc) :: _ =>\n      Keyword.all.get(nme) match\n      case S(kw) => // * Expressions starting with keywords should be handled in parseRule\n        // * I guess this case is not really supposed to ever be reached (?)\n        err(msg\"Unexpected ${kw.toString} in this position\" -> S(loc) :: Nil)\n        errExpr\n      case N =>\n        consume\n        val id = Tree.Ident(nme).withLoc(S(loc))\n        if prefixOps.contains(nme)\n        then\n          yeetSpaces match\n          case Nil => id\n          case _ =>\n            val newPrec =\n              if nme === \"!\" then\n                // Special case: bang operator currently used in BbML\n                PrefixOpsPrec\n              else\n                opCharPrec(nme.head)\n            val rhs = expr(newPrec, allowNewlines = allowNewlines)\n            exprCont(App(id, PlainTup(rhs)), prec, allowNewlines = allowNewlines)\n        else exprCont(id, prec, allowNewlines = allowNewlines)\n    case (LITVAL(lit), loc) :: _ =>\n      consume\n      exprCont(lit.asTree.withLoc(S(loc)), prec, allowNewlines = allowNewlines)\n    case (br @ BRACKETS(bk @ (Round | Curly | Square), toks), loc) :: _ =>\n      consume\n      val ps = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockMaybeIndented)\n      yeetSpaces match\n        case (QUOTE, l) :: (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _ =>\n            consume\n            consume\n            val rhs = effectfulRhs(kw.rightPrecOrMin, allowNewlines = allowNewlines)\n            val lhs = bk match\n              case Round => Tup(ps)\n              case Curly => Bra(Curly, Block(ps))\n              case Square => TyTup(ps)\n            exprCont(\n              Quoted(InfixApp(lhs, new Keywrd(kw).withLoc(S(l0)), Unquoted(rhs)).withLoc(S(loc))).withLoc(S(l ++ loc)),\n              prec, allowNewlines = allowNewlines)\n        case (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _\n        if kw.leftPrecOrMin > prec =>\n          consume\n          val rhs = effectfulRhs(kw.rightPrecOrMin, allowNewlines = allowNewlines)\n          val lhs = bk match\n            case Round => Tup(ps)\n            case Curly => ???\n            case Square => TyTup(ps)\n          val res = InfixApp(lhs.withLoc(S(loc)), new Keywrd(kw).withLoc(S(l0)), rhs)\n          exprCont(res, prec, allowNewlines = allowNewlines)\n        case _ =>\n          val sts = ps\n          val res = bk match\n            case Square => Tup(sts).withLoc(S(loc))\n            case Round => sts match\n              case Nil => Unt().withLoc(S(loc))\n              case e :: Nil => Bra(Round, e).withLoc(S(loc))\n              case es => Bra(Round, Block(es).withLoc(S(loc)))\n            case Curly => Bra(Curly, Block(ps))\n          exprCont(res, prec, allowNewlines = allowNewlines)\n    case (QUOTE, loc) :: _ =>\n      consume\n      cur match {\n        case (IDENT(\"let\", _), l0) :: _ =>\n          consume\n          val bs = bindings(Nil)\n          val body = yeetSpaces match\n            case (QUOTE, l1) :: (IDENT(\"in\", _), l2) :: _ =>\n              consume\n              consume\n              simpleExpr(0, allowNewlines = false)\n            case (tk, loc) :: _ =>\n              err(msg\"Expected an expression; found ${tk.toString} instead\" -> S(loc) :: Nil)\n              errExpr\n            case Nil =>\n              err(msg\"Expected '`in'; found end of input instead\" -> lastLoc :: Nil)\n              errExpr\n          bs.foldRight(body) {\n            case ((v, r), acc) => Quoted(LetLike(new Keywrd(`let`).withLoc(S(l0)), v, S(Unquoted(r)), S(Unquoted(acc))))\n          }\n        case (IDENT(\"if\", _), l0) :: _ =>\n          consume\n          val term = simpleExprImpl(prec, allowNewlines = false)\n          yeetSpaces match\n            case (IDENT(\"else\", _), l1) :: _ =>\n              consume\n              val ele = simpleExprImpl(prec, allowNewlines = false)\n              term match\n                case InfixApp(lhs, kw @ Keywrd(Keyword.`then`), rhs) =>\n                  Quoted(IfLike(new Keywrd(Keyword.`if`).withLoc(S(l0)), Block(\n                    InfixApp(Unquoted(lhs), kw, Unquoted(rhs)) ::\n                      PrefixApp(new Keywrd(Keyword.`else`).withLoc(S(l1)), Unquoted(ele)) :: Nil\n                  )))\n                case tk =>\n                  err(msg\"Expected '`in'; found ${tk.toString} instead\" -> tk.toLoc :: Nil)\n                  errExpr\n            case (tk, loc) :: _ =>\n              err(msg\"Expected 'else'; found ${tk.toString} instead\" -> S(loc) :: Nil)\n              errExpr\n            case Nil =>\n              err(msg\"Expected 'else'; found end of input instead\" -> lastLoc :: Nil)\n              errExpr\n        case (IDENT(nme, sym), loc) :: _ =>\n          consume\n          val res =\n            if nme === \"true\" then Tree.BoolLit(true) else if nme === \"false\" then Tree.BoolLit(false) else Tree.Ident(nme)\n          exprCont(Tree.Quoted(res.withLoc(S(loc))), prec, allowNewlines = false)\n        case (LITVAL(lit), l0) :: _ =>\n          consume\n          exprCont(Tree.Quoted(lit.asTree.withLoc(S(l0))), prec, allowNewlines = false)\n        case _ => unsupportedQuote(S(loc))\n      }\n    case (BRACKETS(_: Indent_Curly, _), loc) :: _ =>\n      err(msg\"Expected an expression; found block instead\" -> lastLoc :: Nil)\n      errExpr\n    case (SUSPENSION(dotDotDot), loc) :: _ =>\n      consume\n      val bod = yeetSpaces match\n        case Nil | (COMMA, _) :: _ => N\n        case _ => S(expr(prec, allowNewlines = allowNewlines))\n      val kw = if dotDotDot \n        then new Keywrd(Keyword.`...`) \n        else new Keywrd(Keyword.`..`)\n      Spread(kw.withLoc(S(loc)), bod)\n    // case (NEWLINE, loc) :: _ => // this seems to never be reached\n    //   raise(WarningReport(msg\"???\" -> S(loc) :: Nil))\n    //   consume\n    //   simpleExprImpl(prec)\n    case (SELECT(name = nme, dynamic = false), loc) :: _ =>\n      consume\n      exprCont(Tree.Sel(Tree.Empty(), new Ident(nme).withLoc(S(loc))), prec, allowNewlines = false) // TODO: use a new tree ctor\n    case (tok, loc) :: _ =>\n      err(msg\"Expected an expression; found ${tok.describe} instead\" -> S(loc) :: Nil)\n      errExpr\n    case Nil =>\n      err(msg\"Expected an expression; found end of input instead\" -> lastLoc :: Nil)\n      errExpr\n  \n  \n  private def unsupportedQuote(loc: Opt[Loc]) = {\n    err(msg\"This quote syntax is not supported yet\" -> loc :: Nil)\n    errExpr\n  }\n  \n  \n  def effectfulRhs(prec: Int, allowNewlines: Bool)(using Line): Tree =\n    yeetSpaces match\n      case (br @ BRACKETS(Curly, toks), loc) :: _ =>\n        consume\n        val eff = rec(toks, S(loc), \"effect type\").concludeWith(_.expr(0, allowNewlines = allowNewlines))\n        Effectful(eff, expr(prec, allowNewlines = allowNewlines))\n      case _ => expr(prec, allowNewlines = allowNewlines)\n      // case _ => Block.mk(blockMaybeIndented)\n  \n  \n  def split(using Line): Ls[Tree] = wrap(\"\")(splitItem(Nil).reverse)\n  \n  @tailrec final private def splitItem(acc: Ls[Tree]): Ls[Tree] =\n    val item = wrap(s\"index = ${acc.size + 1}\"):\n      cur match // `true | false | Tree`\n      case Nil => false\n      case (_: NEWLINE_COMMA | SPACE, _) :: _ => consume; true\n      case (KEYWORD(kw), loc) :: _ if kw isnt Keyword.__ =>\n        prefixRules.getKwAlt(kw, S(loc)) match\n        case S(subRule) =>\n          consume\n          parseRule(CommaPrecNext, subRule, allowNewlines = false).getOrElse(errExpr)\n        case N => expr(0, allowNewlines = false)\n      case _ => expr(0, allowNewlines = false)\n    item match\n      case true => splitItem(acc) // continue\n      case false => printDbg(s\"! end of split\"); acc // break\n      case e: Tree => // needs further inspection\n        yeetSpaces match\n        case (_: NEWLINE_COMMA, _) :: _ =>\n          consume; splitItem(e :: acc)\n        case _ => printDbg(s\"! end of split\"); e :: acc\n  \n  \n  /** Parse an operator split (block of lines starting by an operator).\n   *  TODO: parse let bindings\n   */\n  def opSplit(lhs: Tree, splittingOpLoc: Loc, prec: Int)(using Line): Tree =\n    wrap((lhs, splittingOpLoc, prec))(opSplitImpl(lhs, splittingOpLoc, prec, Nil))\n  def opSplitImpl(lhs: Tree, splittingOpLoc: Loc, prec: Int, acc: Ls[Tree]): Tree =\n    val (newAcc, e) = yeetSpaces match\n      case (PrefixRule(kw, rule), loc) :: _ =>\n        consume\n        val e = parseRule(kw.rightPrecOrMin, rule.map(_.withLoc(S(loc))), allowNewlines = true).getOrElse(errExpr)\n        (e :: acc, S(e))\n      case _ => exprCont(SplitPoint(), prec, allowNewlines = false) match\n        case SplitPoint() => // * Note: nothing was parsed!\n          // * Kludge to accommodate the kludge for `then` below\n          (acc, N)\n        case e => (e :: acc, S(e))\n    yeetSpaces match\n    case Nil => OpSplit(lhs, newAcc.reverse)\n    case (_: NEWLINE_COMMA, l0) :: _ =>\n      consume\n      opSplitImpl(lhs, splittingOpLoc, prec, newAcc)\n    case (SELECT(nme, dyn), l0) :: rest =>\n      assert(SelPrec <= prec)\n      ??? // TODO?\n    case (IDENT(\"then\", false), l0) :: rest if e.isDefined =>\n      // * Kludge – when we have a proper generally splittable syntax, this will be handled by construction\n      consume\n      val rhs = expr(Keyword.`then`.rightPrecOrMin, allowNewlines = false)\n      e match\n      case N => die\n      case S(e) =>\n        opSplitImpl(lhs, splittingOpLoc, prec, InfixApp(e, new Keywrd(Keyword.`then`).withLoc(S(l0)), rhs) :: acc)\n    case (IDENT(op, true), l0) :: rest =>\n      assert(opPrec(op)._1 <= prec)\n      if rest.collectFirst{ case (_: NEWLINE_COMMA | IDENT(\"then\", false), _) => }.isEmpty // TODO dedup\n      then\n        OpSplit(lhs, acc.reverse)\n      else\n        err(\n          msg\"Operator cannot be used inside this operator split\" -> S(l0) ::\n          msg\"as it has lower precedence than the splitting operator here\" -> S(splittingOpLoc) ::\n          Nil)\n        val rhs = expr(opPrec(op)._2, allowNewlines = false)\n        opSplitImpl(OpApp(lhs, Ident(op).withLoc(S(l0)), rhs :: Nil), splittingOpLoc, prec, newAcc)\n    case (tok, loc) :: _ => // TODO indented op block\n      err(msg\"Unexpected ${tok.describe} in this operator split inner position\" -> S(loc)::\n          msg\"Note: the operator split starts here\" -> S(splittingOpLoc)\n          :: Nil)\n      OpSplit(lhs, acc reverse_::: errExpr :: Nil)\n  \n  \n  /** `gobbleSpaces` is currently only used to prevent `@foo (2 + 2)` from parsing as `@foo(2 + 2) ...` */\n  final def exprCont(acc: Tree, prec: Int, allowNewlines: Bool, gobbleSpaces: Bool = true)(using Line): Tree =\n    wrap(prec, s\"`$acc`\", allowNewlines)(exprContImpl(acc, prec, allowNewlines, gobbleSpaces))\n  \n  final def exprContImpl(acc: Tree, prec: Int, allowNewlines: Bool, gobbleSpaces: Bool): Tree =\n    cur match\n      \n      case (SPACE, l0) :: _ if gobbleSpaces =>\n        consume\n        acc match // TODO: [CY] looks fishy. a better way? [LP] indeed; ref should be a prefix keyword!\n        case Sel(reg, Ident(\"ref\")) => RegRef(reg, simpleExprImpl(0, allowNewlines = false))\n        case _ => exprCont(acc, prec, allowNewlines = allowNewlines)\n        \n      case (QUOTE, l) :: _ => cur match {\n        case _ :: (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _ if kw.leftPrecOrMin > prec =>\n          consume\n          consume\n          val rhs = effectfulRhs(kw.rightPrecOrMin, allowNewlines = allowNewlines)\n          exprCont(Quoted(InfixApp(PlainTup(acc), new Keywrd(kw).withLoc(S(l0)), Unquoted(rhs))), prec, allowNewlines = allowNewlines)\n        case _ :: (br @ BRACKETS(Round, toks), loc) :: _ =>\n          consume\n          consume\n          val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockMaybeIndented).map(t => Unquoted(t))\n          val res = App(Unquoted(acc), Tup(as).withLoc(S(loc)))\n          exprCont(Quoted(res), prec, allowNewlines = allowNewlines)\n        case _ :: (OP(opStr), l0) :: _ =>\n          if opPrec(opStr)._1 > prec then {\n            consume\n            consume\n            val v = Ident(opStr).withLoc(S(l0))\n            yeetSpaces match {\n              case (_: NEWLINE_COMMA, l0) :: _ => consume\n              case _ =>\n            }\n            val rhs = expr(opPrec(opStr)._2, allowNewlines = allowNewlines)\n            exprCont(opStr match {\n                case \"with\" => unsupportedQuote(S(l0))\n                case _ => Quoted(App(v, PlainTup(Unquoted(acc), Unquoted(rhs))))\n              }, prec, allowNewlines = allowNewlines)\n          }\n          else acc\n        case _ :: (KEYWORD(Keyword(\"in\")), _) :: _ =>\n          acc\n        case _ =>\n          consume\n          unsupportedQuote(acc.toLoc)\n          acc\n      }\n      case (COMMA, l0) :: _ if prec === 0 =>\n        consume\n        err(msg\"Unexpected comma in this position\" -> S(l0) :: Nil)\n        acc\n        /* \n      case (KEYWORD(opStr @ \"=>\"), l0) :: (_: NEWLINE_COMMA, l1) :: _ if opPrec(opStr)._1 > prec =>\n        consume\n        val rhs = Blk(typingUnit.entities)\n        R(Lam(PlainTup(acc), rhs))\n        */\n      // case (KEYWORD(kw @ (Keyword.`=`)), l0) :: _ if kw.leftPrecOrMin > prec =>\n      //   consume\n      //   ???\n      case (KEYWORD(kw @ (Keyword.`=>` | Keyword.`->`)), l0) :: _\n      if kw.leftPrecOrMin > prec =>\n        consume\n        val rhs = effectfulRhs(kw.rightPrecOrMin, allowNewlines = allowNewlines)\n        val res = acc match\n          case _ => InfixApp(PlainTup(acc), new Keywrd(kw).withLoc(S(l0)), rhs)\n        exprCont(res, prec, allowNewlines = allowNewlines)\n        \n      case (IDENT(\"!\", _), l0) :: (br @ BRACKETS(bk, toks), l1) :: _ =>\n        consume\n        consume\n        val inner = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.expr(0, allowNewlines = true))\n        exprCont(DynAccess(acc, Bra(bk, inner)), prec, allowNewlines = allowNewlines)\n      // TODO: these should eventually no longer be treated as dynamic:\n      case (PERIOD, l0) :: (br @ BRACKETS(bk @ (Round | Square), toks), l1) :: _ =>\n        consume\n        consume\n        val inner = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.expr(0, allowNewlines = true))\n        exprCont(DynAccess(acc, Bra(bk, inner)).withLoc(S(l0 ++ l1)), prec, allowNewlines = allowNewlines)\n      \n      case (PERIOD, l0) :: (br @ BRACKETS(Curly, toks), l1) :: _ =>\n        consume\n        consume\n        val inner = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockMaybeIndented)\n        exprCont(OpenIn(acc, Block(inner)), prec, allowNewlines = allowNewlines)\n        \n      case (PERIOD, l0) :: (LITVAL(lit: (Tree & Literal)), l1) :: _ =>\n        consume\n        consume\n        exprCont(DynAccess(acc, lit.withLoc(S(l1))).withLoc(S(l0 ++ l1)), prec, allowNewlines = allowNewlines)\n        \n        /* \n      case (PERIOD, l0) :: (br @ BRACKETS(Square, toks), l1) :: _ =>\n        consume\n        consume\n        val idx = rec(toks, S(br.innerLoc), br.describe)\n          .concludeWith(_.simpleExpr(0, allowSpace = true))\n        val newAcc = Subs(acc, idx).withLoc(S(l0 ++ l1 ++ idx.toLoc))\n        exprCont(newAcc, prec, allowNewlines)\n        */\n      \n      // * Parse operator splits\n      case (br @ BRACKETS(_: Indent_Curly,\n          toks @ ((tok @ (IDENT(_, true) | SELECT(_, _) | KEYWORD(_: Keyword.InfixSplittable)), l0) :: _)), loc) :: _\n      if tok.match {\n        case KEYWORD(Keyword.`of`) => AppPrec\n        case KEYWORD(kw) => kw.leftPrecOrMin\n        case id: IDENT => opPrec(id.name)._1\n        case sel: SELECT => SelPrec\n      } > prec\n      =>\n        consume\n        if toks.collectFirst{ case (_: NEWLINE_COMMA, _) => }.isEmpty then\n          // * If the indented block doens't have any newlines or commas,\n          // * this is not truly a split, and we can parse it as a normal expression continuation.\n          cur = toks ::: cur\n          exprCont(acc, prec, allowNewlines = allowNewlines)\n        else\n          val r = rec(toks, S(loc), \"operator block\")\n          val res = r.opSplit(acc, l0, prec)\n          r.yeetSpaces match\n          case Nil =>\n            exprCont(res, prec, allowNewlines = allowNewlines)\n          case toks =>\n            cur = toks ::: cur\n            exprCont(res, prec, allowNewlines = allowNewlines)\n      \n      // TODO\n      // case (NEWLINE, _) :: (SELECT(nme), _) :: _\n      // =>\n      \n      // * Parse newline-operators, eg `2 + 2\\n*\\n2 + 2` <=> `(2 + 2) * (2 + 2)`\n      // TODO also allow uses of SELECT\n      case (_: NEWLINE_COMMA, _) :: (OP(opStr), l0) :: rest\n      if allowNewlines\n      && prec <= NoElsePrec // (Q: why doesn't MinPrec work?)\n      && NOISE.get(rest).nonEmpty // * Don't treat as infix if there are no tokens for the RHS (eg `()\\n???`)\n      && (!prefixOps.contains(opStr) || rest.match\n        case (_: NEWLINE_COMMA, _) :: _ | (SPACE, _) :: _ | (BRACKETS(_: Indent_Curly, _), _) :: _ | Nil => true\n        case _ => false\n      ) =>\n        consume\n        consume\n        val v = Ident(opStr).withLoc(S(l0))\n        val rhsPrec = yeetSpaces match\n        case (_: NEWLINE_COMMA, l0) :: _ =>\n          consume\n          CommaPrecNext2 // for chained nl ops: left assoc\n        case _ =>\n          opPrec(opStr)._2\n        val rhs = expr(rhsPrec, allowNewlines = allowNewlines)\n        exprCont(OpApp(acc, v, rhs :: Nil), prec, allowNewlines = allowNewlines)\n        \n      case (OP(\"::\"), l0) :: (IDENT(id, false), l1) :: _ =>\n        consume\n        consume\n        exprCont(MemberProj(acc, new Ident(id).withLoc(S(l1))).withLoc(S(l0 ++ l1)), prec, allowNewlines = allowNewlines)\n      case (OP(opStr), l0) :: _ if /* isInfix(opStr) && */ opPrec(opStr)._1 > prec =>\n        consume\n        val v = Ident(opStr).withLoc(S(l0))\n        yeetSpaces match {\n          case (_: NEWLINE_COMMA, l0) :: _ => consume\n          case _ =>\n        }\n        printDbg(s\"! found operator `$opStr` with prec ${opPrec(opStr)}\")\n        yeetSpaces match\n          case (BRACKETS(_: Indent_Curly, toks), l0) :: _ =>\n            consume\n            // rec(toks, S(br.innerLoc), br.describe).concludeWith(f(_, true))\n            val rhs = rec(toks, S(l0), \"operator split\").concludeWith(_.split)\n            exprCont(OpApp(acc, v, Block(rhs).withLoc(S(l0)) :: Nil),\n              prec, allowNewlines = allowNewlines)\n          case _ => \n            // val rhs = simpleExpr(opPrec(opStr)._2)\n            val rhs = expr(opPrec(opStr)._2, allowNewlines = allowNewlines)\n            exprCont(opStr match {\n              case \"with\" =>\n                rhs match {\n                  // TODO?\n                  // case rhs: Rcd =>\n                  //   With(acc, rhs)//.withLocOf(term)\n                  // case Bra(true, rhs: Rcd) =>\n                  //   With(acc, rhs)//.withLocOf(term)\n                  case _ =>\n                    err(msg\"record literal expected here; found ${rhs.describe}\" -> rhs.toLoc :: Nil)\n                    acc\n                }\n              case _ => OpApp(acc, v, rhs :: Nil)\n            }, prec, allowNewlines = allowNewlines)\n        \n      case (SELECT(name, dyn), l0) :: _ if SelPrec >= prec =>\n        consume\n        val tree = if dyn then\n          DynAccess(acc, new Ident(name).withLoc(S(l0)))\n        else\n          Sel(acc, new Ident(name).withLoc(S(l0)))\n        exprCont(tree, prec, allowNewlines = allowNewlines)\n        \n      case (br @ BRACKETS(Angle | Square, toks), loc) :: _ =>\n        consume\n        val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockMaybeIndented)\n        // val res = TyApp(acc, as.map(_.mapSecond.to))\n        val res = TyApp(acc, as).withLoc(acc.toLoc.fold(some(loc))(_ ++ loc |> some))\n        exprCont(res, prec, allowNewlines = allowNewlines)\n        /*\n      /*case (br @ BRACKETS(Square, toks), loc) :: _ => // * Currently unreachable because we match Square brackets as tparams\n        consume\n        val idx = rec(toks, S(br.innerLoc), \"subscript\").concludeWith(_.simpleExpr(0))\n        val res = Subs(acc, idx.withLoc(S(loc)))\n        exprCont(res, prec, allowNewlines)*/\n      */\n      case (br @ BRACKETS(Round, toks), loc) :: _ if prec <= AppPrec =>\n        consume\n        val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockMaybeIndented)\n        val res = App(acc, Tup(as).withLoc(S(loc)))\n        exprCont(res, prec, allowNewlines = allowNewlines)\n      case (KEYWORD(Keyword.`of`), _) :: _ if prec <= AppPrec =>\n        consume\n        val as = blockMaybeIndented\n        val res = App(acc, Tup(as))\n        exprCont(res, prec, allowNewlines = allowNewlines)\n      \n      case (_: NEWLINE_COMMA, _) :: (KEYWORD(kw), _) :: _\n      if kw.canStartInfixOnNewLine && kw.leftPrecOrMin > prec\n      && infixRules.kwAlts.contains(kw.name)\n      && (kw isnt Keyword.`do`) // This is to avoid the following case:\n        //  ```\n        //  0 then \"null\"\n        //  do console.log(\"non-null\")\n        //  ```\n        // Otherwise, `do` will be parsed as an infix operator\n      =>\n        consume\n        exprCont(acc, prec, allowNewlines = allowNewlines)\n        \n      case (br @ BRACKETS(bk @ (_: Indent_Curly), toks @ ((KEYWORD(kw), _) :: _)), loc) :: _\n      if kw.leftPrecOrMin > prec\n      && infixRules.kwAlts.contains(kw.name)\n      =>\n        consume\n        val (res, rest) = rec(toks, S(br.innerLoc), br.describe).continueWith:\n          _.exprCont(acc, prec, allowNewlines = true)\n        rest match\n          case (_, l) :: _ =>\n            printDbg(s\"!! REDUCING BRACKET\")\n            cur = (NEWLINE, l.left) :: rest ::: cur\n          case _ =>\n        exprCont(res, prec, allowNewlines = allowNewlines)\n        \n      \n      case (KEYWORD(kw), l0) :: _ if kw.leftPrecOrMin > prec =>\n        if verbose then printDbg(s\"$$ found keyword: ${kw.name} (${kw.leftPrecOrMin})\")\n        infixRules.getKwAlt(kw, S(l0)) match\n          case S(subRule) =>\n            consume\n            if verbose then printDbg(s\"$$ proceed with rule: ${subRule.name}\")\n            subRule.exprAlt match\n              case S(exprAlt) =>\n                if verbose then printDbg(\"$ parsing the right-hand side\")\n                val rhs = expr(kw.rightPrecOrMin, allowNewlines = allowNewlines)\n                parseRule(kw.rightPrecOrMin, exprAlt.rest, allowNewlines = allowNewlines).map: rest =>\n                  exprCont(exprAlt.k(rhs, rest)(acc), prec, allowNewlines = allowNewlines) // FIXME prec??\n                .getOrElse(errExpr)\n              case N =>\n                // TODO other alts...?\n                err(msg\"Expected ${subRule.whatComesAfter} ${subRule.mkAfterStr}; found ${kw.name} instead\" -> S(l0) :: Nil)\n                acc\n          case _ => acc\n      case _ =>\n        exprJux(acc, prec, allowNewlines = false)\n  \n  \n  final def exprJux(acc: Tree, prec: Int, allowNewlines: Bool)(using Line): Tree =\n    wrap(prec, s\"`$acc`\", allowNewlines)(exprJuxImpl(acc, prec, allowNewlines))\n  \n  final def exprJuxImpl(acc: Tree, prec: Int, allowNewlines: Bool): Tree =\n    cur match\n    case (_: NEWLINE_COMMA, _) :: _ if allowNewlines =>\n      consume\n      exprJux(acc, prec, allowNewlines = allowNewlines)\n    case (IDENT(id, false), _) :: _\n    if prec < AppPrec && !Keyword.all.contains(id) =>\n      val res = exprCont(Jux(acc, expr(AppPrec, allowNewlines = allowNewlines)), prec, allowNewlines = allowNewlines)\n      exprJux(res, prec, allowNewlines = allowNewlines)\n    case (br @ BRACKETS(_: Indent_Curly, toks), l0) :: _\n    if prec < AppPrec && (toks.headOption match\n      case S((IDENT(nme, sym), _)) => !sym && !Keyword.all.contains(nme)\n      case _ => true\n    ) =>\n      consume\n      val res = rec(toks, S(br.innerLoc), br.describe).concludeWith:\n        _.block(allowNewlines = true)\n      exprCont(Jux(acc, Block(res).withLoc(S(l0))), prec, allowNewlines = true)\n    \n    case (tok, _) :: _ =>\n      printDbg(s\"stops at ${tok.toString}\")\n      acc\n    case Nil =>\n      printDbg(s\"stops at the end of input\")\n      acc  \n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/syntax/Token.scala",
    "content": "package hkmc2\npackage syntax\n\nimport mlscript.utils._, shorthands._\n\n\n/** Type of general Tokens */\nsealed abstract class Token:\n  def describe: Str = this match\n    case SPACE => \"space\"\n    case COMMA => \"comma\"\n    case PERIOD => \"period\"\n    case NEWLINE => \"new line\"\n    case INDENT => \"indentation\"\n    case DEINDENT => \"deindentation\"\n    case ERROR => \"error\"\n    case QUOTE => \"quote\"\n    case LITVAL(value) => \"literal\"\n    // case KEYWRD(name) =>\n    //   if name.headOption.exists(_.isLetter) then s\"'$name' keyword\" else s\"'$name'\"\n    case IDENT(name, symbolic) =>\n      if Keyword.all.contains(name) then s\"'$name' keyword\"\n      else if symbolic then \"operator\" else \"identifier\"\n    case SELECT(name, dyn) => (if dyn then \"dynamic\" else \"static\") + \" selector\"\n    case OPEN_BRACKET(k) => s\"opening ${k.name}\"\n    case CLOSE_BRACKET(k) => s\"closing ${k.name}\"\n    case BRACKETS(BracketKind.Indent, contents) => s\"indented block\"\n    case BRACKETS(k, contents) => s\"${k.name} section\"\n    case COMMENT(text) => \"comment\"\n    case SUSPENSION(true) => \"'...' ellipsis\"\n    case SUSPENSION(false) => \"'..' ellipsis\"\n    case ESC_IDENT(_) => \"identifier\"\n\n/** Type of 'Structured Tokens' aka 'Strokens',\n  * which use a `BRACKETS` construct instead of `OPEN_BRACKET`/`CLOSE_BRACKET` and `INDENT`/`DEINDENT` */\nsealed trait Stroken extends Token\n\ncase object SPACE extends Token with Stroken\ncase object COMMA extends Token with Stroken\ncase object PERIOD extends Token with Stroken\ncase object NEWLINE extends Token with Stroken // TODO rm\ncase object INDENT extends Token\ncase object DEINDENT extends Token\ncase object ERROR extends Token with Stroken\ncase object QUOTE extends Token with Stroken\nfinal case class LITVAL(value: Literal) extends Token with Stroken\n// final case class KEYWRD(name: String) extends Token with Stroken\nfinal case class IDENT(name: String, symbolic: Bool) extends Token with Stroken\nfinal case class SELECT(name: String, dynamic: Bool) extends Token with Stroken\nfinal case class OPEN_BRACKET(k: BracketKind) extends Token\nfinal case class CLOSE_BRACKET(k: BracketKind) extends Token\nfinal case class BRACKETS(k: BracketKind, contents: Ls[Stroken -> Loc])(val innerLoc: Loc) extends Token with Stroken\nfinal case class COMMENT(text: String) extends Token with Stroken\nfinal case class SUSPENSION(dotDotDot: Bool) extends Token with Stroken\nfinal case class ESC_IDENT(name: String) extends Token with Stroken\n\n\nsealed abstract class BracketKind:\n  import BracketKind._\n  lazy val (beg, end) = this match\n    case Round => \"(\" -> \")\"\n    case Curly => \"{\" -> \"}\"\n    case Square => \"[\" -> \"]\"\n    case Angle => \"‹\" -> \"›\"\n    case Indent => \"→\" -> \"←\"\n    case Quasiquote => \"code\\\"\" -> \"\\\"\"\n    case QuasiquoteTriple => \"code\\\"\\\"\\\"\" -> \"\\\"\\\"\\\"\"\n    case Unquote => \"${\" -> \"}\"\n  def name: Str = this match\n    case Round => \"parenthesis\"\n    case Curly => \"curly brace\"\n    case Square => \"square bracket\"\n    case Angle => \"angle bracket\"\n    case Indent => \"indentation\"\n    case Quasiquote => \"quasiquote\"\n    case QuasiquoteTriple => \"quasiquote triple\"\n    case Unquote => \"unquote\"\n\nobject BracketKind:\n  case object Round extends BracketKind\n  case object Curly extends BracketKind\n  case object Square extends BracketKind\n  case object Angle extends BracketKind\n  case object Indent extends BracketKind\n  case object Quasiquote extends BracketKind\n  case object QuasiquoteTriple extends BracketKind\n  case object Unquote extends BracketKind\n  \n  def unapply(c: Char): Opt[Either[BracketKind, BracketKind]] = c `|>?` :\n    case '(' => Left(Round)\n    case ')' => Right(Round)\n    case '{' => Left(Curly)\n    case '}' => Right(Curly)\n    case '[' => Left(Square)\n    case ']' => Right(Square)\n    case '‹' => Left(Angle)\n    case '›' => Right(Angle)\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala",
    "content": "package hkmc2\npackage syntax\n\nimport scala.annotation.tailrec\nimport scala.collection.mutable\nimport sourcecode.Line\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\nimport hkmc2.Message.MessageContext\nimport semantics.{FldFlags, TermDefFlags, Modulefulness}\nimport semantics.Elaborator.State\nimport Tree._\n\n\nsealed trait Literal extends AutoLocated:\n  this: Tree =>\n  \n  def asTree: Tree = this\n  \n  val idStr: Str = this match\n    case IntLit(value) => value.toString\n    case DecLit(value) => value.toString\n    case StrLit(value) => value.iterator.map: // TODO dedup logic with `JSBuilder.makeStringLiteral`?\n        case '\\b' => \"\\\\b\" case '\\t' => \"\\\\t\" case '\\n' => \"\\\\n\" case '\\r' => \"\\\\r\"\n        case '\\f' => \"\\\\f\" case '\"' => \"\\\\\\\"\" case '\\\\' => \"\\\\\\\\\"\n        case c if c.isControl => f\"\\\\u${c.toInt}%04x\"\n        case c => c.toString\n      .mkString(\"\\\"\", \"\", \"\\\"\")\n    case UnitLit(value) => if value then \"null\" else \"undefined\"\n    case BoolLit(value) => value.toString\n  \n  def describeLit: Str =\n    this.match\n      case _: IntLit => \"integer\"\n      case _: DecLit => \"decimal\"\n      case _: StrLit => \"string\"\n      case UnitLit(isNull) => if isNull then \"null\" else \"undefined\"\n      case _: BoolLit => \"boolean\"\n    + \" literal\"\n  \n  // def children: List[Located] = Nil\n\nenum SpreadKind:\n  case Eager, Lazy\n  def isEager: Bool = this match\n    case Eager => true\n    case Lazy => false\n  def str: Str = this match\n    case Eager => \"...\"\n    case Lazy => \"..\"\nobject SpreadKind:\n  def fromKw(kw: Keywrd[Keyword.Ellipsis]) = kw.kw match\n    case Keyword.`..` => SpreadKind.Lazy\n    case Keyword.`...` => SpreadKind.Eager\n\nenum Tree extends AutoLocated:\n  case Empty()\n  case Error()\n  case Dummy // TODO change the places where this is used\n  case Under()\n  case Unt()\n  case Ident(name: Str)\n  case Pun(eql: Bool, id: Ident) // `=ident` (eql) or `:ident` (!eql)\n  case Keywrd[+K <: Keyword & Singleton](kw: K)\n  case IntLit(value: BigInt)             extends Tree with Literal\n  case DecLit(value: BigDecimal)         extends Tree with Literal\n  case StrLit(value: Str)                extends Tree with Literal\n  case UnitLit(isNullNotUndefined: Bool) extends Tree with Literal\n  case BoolLit(value: Bool)              extends Tree with Literal\n  case Bra(k: BracketKind, inner: Tree)\n  case Block(stmts: Ls[Tree])(using State) extends Tree with semantics.BlockImpl\n  case LetLike(kw: Keywrd[Keyword.LetLike], lhs: Tree, rhs: Opt[Tree], body: Opt[Tree])\n  case Hndl(lhs: Tree, cls: Tree, defs: Tree, body: Opt[Tree])\n  case Def(lhs: Tree, rhs: Tree)\n  case TermDef(k: TermDefKind, head: Tree, rhs: Opt[Tree]) extends Tree with TermDefImpl\n  case TypeDef(k: TypeDefKind, head: Tree, rhs: Opt[Tree])(using State)\n    extends Tree with TypeDefImpl\n  case Open(opened: Tree)\n  case OpenIn(opened: Tree, body: Tree)\n  case DynAccess(obj: Tree, fld: Tree)\n  case Modified(modifier: Keywrd[Keyword.Modifier], body: Tree)\n  case Quoted(body: Tree)\n  case Unquoted(body: Tree)\n  case Tup(fields: Ls[Tree])\n  case TyTup(tys: Ls[Tree])\n  case App(lhs: Tree, rhs: Tree)\n  case OpApp(lhs: Tree, op: Tree, rhss: Ls[Tree])\n  case Jux(lhs: Tree, rhs: Tree)\n  case SynthSel(prefix: Tree, name: Ident)\n  case Sel(prefix: Tree, name: Ident)\n  case MemberProj(cls: Tree, name: Ident)\n  case PrefixApp(kw: Keywrd[Keyword.Prefix], rhs: Tree)\n  case InfixApp(lhs: Tree, kw: Keywrd[Keyword.Infix], rhs: Tree)\n  case LexicalNew(body: Opt[Tree], rft: Opt[Block]) // * New as it is parsed, with its weird precedence – eg (new C)(123)\n  case ProperNew(body: Opt[Tree], rft: Opt[Block]) // * A desugared version of New that sets it right – eg new(C(123))\n  case DynamicNew(cls: Tree) // * Dynamic version – eg new! C(123)\n  case IfLike(kw: Keywrd[Keyword.IfLike], split: Tree)\n  case Assert(kw: Keywrd[Keyword.`assert`], cond: Tree, thn: Opt[Tree], els: Opt[Keywrd[Keyword.`else`] -> Tree])\n  case SplitPoint()\n  case OpSplit(lhs: Tree, ops_rhss: Ls[Tree]) // * the rhss trees are expressions rooted in `SplitPoint`s\n  case Case(kw: Keywrd[Keyword.`case`.type], branches: Tree)\n  case Region(name: Tree, body: Tree)\n  case RegRef(reg: Tree, value: Tree)\n  case Effectful(eff: Tree, body: Tree)\n  case Outer(name: Opt[Tree])\n  case Spread(kw: Keywrd[Keyword.Ellipsis], body: Opt[Tree])\n  case Annotated(annotation: Tree, target: Tree)\n  case Directive(prefix: Tree, body: Tree)\n  case Constructor(decl: Tree)\n  /** Represents a term that has already been elaborated. When desugaring\n   *  operator splits in the UCS, the `lhs` of `OpSplit` has already been elaborated\n   *  into a `Term`, so we need to embed `Term` into `Tree` using `Trm`. */\n  case Trm(term: semantics.Term)\n  \n  def splitOn(acc: Tree): Tree = this match\n    case SplitPoint() => acc\n    case Sel(pre, id) => Sel(pre.splitOn(acc), id)\n    case App(lhs, rhs) => App(lhs.splitOn(acc), rhs)\n    case OpApp(lhs, op, rhss) => OpApp(lhs.splitOn(acc), op, rhss)\n    case OpSplit(lhs, rhss) => OpSplit(lhs.splitOn(acc), rhss)\n    case InfixApp(lhs, kw, rhs) => InfixApp(lhs.splitOn(acc), kw, rhs)\n    case _: (Ident | Literal | Error) => acc\n    case _ => die\n  \n  def children: Vector[Located] = this match\n    case _: Empty | _: Error | _: Ident | _: Literal | _: Under | _: Unt => Vector.empty\n    case Pun(_, e) => Vector.single(e)\n    case Bra(_, e) => Vector.single(e)\n    case Block(stmts) => stmts.toVector\n    case LetLike(kw, lhs, rhs, body) => lhs +: (rhs.toVector ++ body.toVector)\n    case Hndl(lhs, rhs, defs, body) => body match\n      case Some(value) => lhs +: rhs +: defs +: value +: Vector.empty\n      case None => lhs +: rhs +: defs +: Vector.empty\n    case TypeDef(k, head, rhs) => head +: rhs.toVector\n    case Modified(_, body) => Vector.single(body)\n    case Quoted(body) => Vector.single(body)\n    case Unquoted(body) => Vector.single(body)\n    case Tup(fields) => fields.toVector\n    case App(lhs, rhs) => Vector.double(lhs, rhs)\n    case OpApp(lhs, op, rhss) => lhs +: op +: rhss.toVector\n    case Jux(lhs, rhs) => Vector.double(lhs, rhs)\n    case PrefixApp(kw, rhs) => Vector.double(kw, rhs)\n    case InfixApp(lhs, kw, rhs) => Vector.triple(lhs, kw, rhs)\n    case TermDef(k, head, rhs) => head +: rhs.toVector\n    case LexicalNew(body, rft) => body.toVector ++ rft.toVector\n    case ProperNew(body, rft) => body.toVector ++ rft.toVector\n    case DynamicNew(body) => Vector.single(body)\n    case IfLike(_, split) => Vector.single(split)\n    case Assert(_, cond, thn, els) => cond +: (thn.toVector ++ els.toList.map(_._2))\n    case Case(_, bs) => Vector.single(bs)\n    case Region(name, body) => Vector.double(name, body)\n    case RegRef(reg, value) => Vector.double(reg, value)\n    case Effectful(eff, body) => Vector.double(eff, body)\n    case Outer(name) => name.toVector\n    case TyTup(tys) => tys.toVector\n    case Sel(prefix, name) => Vector.double(prefix, name)\n    case SynthSel(prefix, name) => Vector.single(prefix)\n    case DynAccess(prefix, fld) => Vector.double(prefix, fld)\n    case Open(bod) => Vector.single(bod)\n    case OpenIn(opened, body) => Vector.double(opened, body)\n    case Def(lhs, rhs) => Vector.double(lhs, rhs)\n    case Spread(kw, body) => Vector.single(kw) ++ body.toVector\n    case Annotated(annotation, target) => Vector.double(annotation, target)\n    case Directive(prefix, body) => Vector.double(prefix, body)\n    case Constructor(decl) => Vector.single(decl)\n    case MemberProj(cls, name) => Vector.single(cls)\n    case Keywrd(kw) => Vector.empty\n    case Dummy => Vector.empty\n    case OpSplit(lhs, ops_rhss) => lhs +: ops_rhss.toVector\n    case SplitPoint() => Vector.empty\n    case Trm(trm) => Vector.single(trm)\n  \n  def describe: Str = this match\n    case Empty() => \"empty\"\n    case Error() => \"‹erroneous syntax›\"\n    case Under() => \"underscore\"\n    case Ident(name) => \"identifier\"\n    case IntLit(value) => \"integer literal\"\n    case DecLit(value) => \"decimal literal\"\n    case StrLit(value) => \"string literal\"\n    case BoolLit(value) => s\"$value literal\"\n    case UnitLit(value) => if value then \"null\" else \"undefined\"\n    case Unt() => \"unit\"\n    case Bra(k, _) => k.name + \" section\"\n    case Block(stmts) => \"block\"\n    case LetLike(kw, lhs, rhs, body) => kw.name\n    case TermDef(k, alphaName, rhs) => \"term definition\"\n    case TypeDef(k, head, rhs) => \"type definition\"\n    case Modified(kw, body) => s\"'${kw.name}'-modified ${body.describe}\"\n    case Quoted(body) => \"quoted\"\n    case Unquoted(body) => \"unquoted\"\n    case Tup(fields) => \"tuple\"\n    case TyTup(tys) => \"type tuple\"\n    case App(lhs, rhs) => \"application\"\n    case OpApp(lhs, op, rhss) => \"operator application\"\n    case Jux(lhs, rhs) => \"juxtaposition\"\n    case Sel(prefix, name) => \"selection\"\n    case SynthSel(prefix, name) => \"synthetic selection\"\n    case DynAccess(prefix, name) => \"dynamic field access\"\n    case PrefixApp(kw, body) => s\"prefix operator '${kw.name}'\"\n    case InfixApp(lhs, kw, rhs) => s\"infix operator '${kw.name}'\"\n    case LexicalNew(body, _) => \"new\"\n    case ProperNew(body, _) => \"new\"\n    case DynamicNew(body) => \"dynamic new\"\n    case IfLike(Keywrd(Keyword.`if`), split) => \"if expression\"\n    case IfLike(Keywrd(Keyword.`while`), split) => \"while expression\"\n    case Case(_, branches) => \"case\"\n    case Region(name, body) => \"region\"\n    case RegRef(reg, value) => \"region reference\"\n    case Effectful(eff, body) => \"effectful\"\n    case Outer(_) => \"outer binding\"\n    case Hndl(_, _, _, _) => \"handle\"\n    case Def(lhs, rhs) => \"defining assignment\"\n    case Spread(_, _) => \"spread\"\n    case Annotated(_, _) => \"annotated\"\n    case Directive(_, _) => \"directive\"\n    case Open(_) => \"open\"\n    case Constructor(_) => \"constructor\"\n    case MemberProj(_, _) => \"member projection\"\n    case Keywrd(kw) => s\"'${kw.name}' keyword\"\n    case Dummy => \"‹dummy›\"\n    case Trm(t) => t.describe + \" term\"\n    case Pun(eql, id) => \"pun\"\n    case SplitPoint() => \"split point\"\n    case OpSplit(lhs, ops_rhss) => \"operator split\"\n    case OpenIn(opened, body) => \"open-in\"\n    \n  def deparenthesized: Tree = this match\n    case Bra(BracketKind.Round, inner) => inner.deparenthesized\n    case _ => this\n  \n  def showDbg: Str = toString // TODO\n  \n  lazy val desugared: Tree = this match\n    \n    case Ident(name) if name.startsWith(\"'\") =>\n      StrLit(name.drop(1)).withLocOf(this)\n    case InfixApp(lhs, Keywrd(Keyword.`:`), rhs) =>\n      InfixApp(lhs.desugared, Keywrd(Keyword.`:`), rhs.desugared)\n    case Sel(pre, nme) if nme.name.startsWith(\"'\") =>\n      DynAccess(pre.desugared, StrLit(nme.name.drop(1)).withLocOf(nme)).withLocOf(this)\n    \n    case Pun(false, id) =>\n      InfixApp(id, Keywrd(Keyword.`:`), id)\n    \n    // TODO generalize to pattern-let and rm this special case\n    case LetLike(kw, und @ Under(), r, b) =>\n      LetLike(kw, Ident(\"_\").withLocOf(und), r, b)\n    \n    case PossiblyAnnotated(anns, m: Modified) =>\n      PossiblyAnnotated(anns,\n        m match\n        case Modified(kw @ Keywrd(Keyword.`declare`), s) =>\n          Annotated(kw, s.desugared)\n        case Modified(kw @ Keywrd(Keyword.`data`), s) =>\n          Annotated(kw, s.desugared)\n        case Modified(kw @ Keywrd(Keyword.`abstract`), s) =>\n          Annotated(kw, s.desugared)\n        case Modified(kw @ Keywrd(Keyword.`staged`), s) =>\n          Annotated(kw, s.desugared)\n        case Modified(kw @ Keywrd(Keyword.`public`), s) =>\n          Annotated(kw, s.desugared)\n        case Modified(kw @ Keywrd(Keyword.`private`), s) =>\n          Annotated(kw, s.desugared)\n        case Modified(kw @ Keywrd(Keyword.`mut`), TermDef(ImmutVal, anme, rhs)) =>\n          TermDef(MutVal, anme, rhs).withLocOf(this).desugared\n        case _ => m\n      )\n    \n    case PossiblyAnnotated(anns, LetLike(letLike, OpApp(lhs, f @ Ident(nme), rhss), N, bodo))\n    if nme.endsWith(\"=\") =>\n      // TODO only do this if the lhs is non-expansive/a valid assignment receiver?\n      PossiblyAnnotated(anns, LetLike(letLike, lhs, S(OpApp(lhs, Ident(nme.init), rhss)), bodo).withLocOf(this).desugared)\n    \n    case Apps(PrefixApp(Keywrd(Keyword.`new!`), cls), argss) =>\n      DynamicNew(Apps(cls, argss)).withLocOf(this)\n    case Apps(LexicalNew(S(body), N), argss) =>\n      ProperNew(S(Apps(body, argss)), N).withLocOf(this)\n    case LexicalNew(bodo, rfto) =>\n      ProperNew(bodo, rfto).withLocOf(this)\n    case InfixApp(Desugared(ProperNew(bodo, N)), Keywrd(Keyword.`with`), rhs: Block) =>\n      ProperNew(bodo, S(rhs)).withLocOf(this)\n    \n    case _ => this\n  \n  /**\n   * Parse a tree as a parameter.\n   * @param inUsing whether the parameter is in a `using` parameter list\n   */\n  def asParam(inUsing: Bool): Diagnostic \\/ ParamTree =\n    @tailrec\n    def go(t: Tree, flags: FldFlags, modifiers: Set[DeclKind]): Diagnostic \\/ ParamTree = t match\n      // * Base Cases.\n      // fun f(_)\n      case und: Under => \n        R(ParamTree(flags, new Ident(\"_\").withLocOf(und), N, N, modifiers))\n      // fun f(a)\n      case id: Ident if !inUsing =>\n        R(ParamTree(flags, id, N, N, modifiers))\n      // fun f(a: A)\n      case InfixApp(id: Ident, Keywrd(Keyword.`:`), sign) =>\n        R(ParamTree(flags, id, S(sign), N, modifiers))\n      // fun f(..a) | fun f(...a)\n      case SpreadParam(id, spd) =>\n        R(ParamTree(flags, id, N, S(spd), modifiers))\n      \n      // * Unwrapping Cases\n      // fun f(module <...>)\n      case TypeDef(Mod, inner, N) =>\n        go(inner, flags, modifiers + Mod)\n      // fun f(pattern <...>)\n      case TypeDef(Pat, inner, N) =>\n        go(inner, flags.copy(pat = true), modifiers + Pat)\n      // class C(val <...>)\n      case TermDef(ImmutVal, inner, _) =>\n        go(inner, flags.copy(isVal = true), modifiers + ImmutVal)\n      // class C(mut val <...>)\n      case TermDef(MutVal, inner, _) =>\n        go(inner, flags.copy(isVal = true, mut = true), modifiers + MutVal)\n      // fun f(using <...>)\n      case TermDef(Ins, inner, N) =>\n        go(inner, flags, modifiers + Ins)\n      \n      // * Base Case (for `using` clause)\n      // fun f(using A)\n      case ty: Tree if inUsing =>\n        // In contextual parameter lists, a single Tree as parameter is\n        // understood as a type for unnamed contextual parameters, as\n        // opposed to that an identifier is understood as the identifier\n        // for a regular parameter list.\n        R(ParamTree(flags, Ident(\"\"), S(ty), N, modifiers))\n      \n      // * Default Case\n      case _ => L:\n        ErrorReport:\n          msg\"Expected a valid parameter, found ${this.describe}\" -> this.toLoc :: Nil\n    \n    go(this, flags = FldFlags.empty, modifiers = Set.empty)\n\n  def isModified(modifier: Keyword | DeclKind): Bool = this match\n    case td @ Tree.TypeDef(m, head, N) =>\n      (td.extension.isEmpty && td.withPart.isEmpty && m == modifier) || head.isModified(modifier)\n    case td @ Tree.TermDef(m, head, N) =>\n      (td.extension.isEmpty && td.withPart.isEmpty && m == modifier) || head.isModified(modifier)\n    case Modified(Keywrd(m), body) =>\n      (modifier is m) || body.isModified(modifier)\n    case _ =>\n      false\n\nobject Tree:\n  val DummyApp: App = App(Dummy, Dummy) // TODO change the places where this is used\n  val DummyTup: Tup = Tup(Dummy :: Nil)\n  def DummyTypeDef(k: TypeDefKind)(using State): TypeDef =\n    Tree.TypeDef(k, Tree.Dummy, N)\n  object Block:\n    def mk(stmts: Ls[Tree])(using State): Tree = stmts match\n      case Nil => UnitLit(false)\n      case e :: Nil => e\n      case es => Block(es)\n  object TyApp:\n    def apply(lhs: Tree, targs: Ls[Tree]): App =\n      App(lhs, TyTup(targs))\n    def unapply(t: App): Opt[(Tree, Ls[Tree])] = t match\n      case App(lhs, TyTup(targs)) => S(lhs, targs)\n      case _ => N\n  \n  extension [T <: Keyword & Singleton](kw: Tree.Keywrd[T])\n    def name = kw.kw.name\n\n/**\n * A parameter yet to be elaborated, which is different from\n * semantics.Param. It merely contains the information directly\n * extracted from the syntax tree.\n */\ncase class ParamTree(\n  flags: FldFlags, ident: Ident, sign: Opt[Tree], \n  spd: Opt[SpreadKind], modifiers: Set[DeclKind]\n)\n\nobject SpreadParam:\n  def unapply(t: Tree): Opt[(Ident, SpreadKind)] = t match\n    // fun f(..a)\n    // fun f(...a)\n    case Spread(kw, S(id: Ident)) =>\n      S(id, SpreadKind.fromKw(kw))\n    // fun f(.._)\n    // fun f(..._)\n    case Spread(kw, S(und: Under)) =>\n      S(new Ident(\"_\").withLocOf(und), SpreadKind.fromKw(kw))\n    // fun f(..)\n    // fun f(...)\n    case Spread(kw, N) =>\n      S(new Ident(\"_\").withLocOf(kw), SpreadKind.fromKw(kw))\n    case _ => N\n\nobject Desugared:\n  def unapply(t: Tree): S[Tree] = S(t.desugared)\n\nobject PlainTup:\n  def apply(fields: Tree*): Tree = Tup(fields.toList)\n\nobject Apps:\n  def apply(t: Tree, as: Ls[Tup]): Tree = as match\n    case Nil => t\n    case arg :: args => Apps(App(t, arg), args)\n  def unapply(t: Tree): S[(Tree, Ls[Tup])] = t match\n    case App(Apps(base, args), arg: Tup) => S(base, args :+ arg)\n    case t => S(t, Nil)\n    \nobject PossiblyAnnotated:\n  def apply(anns: Ls[Tree], t: Tree): Tree = anns.foldRight(t)(Annotated(_, _))\n  def unapply(t: Tree): Opt[(Ls[Tree], Tree)] = t match\n    case Annotated(q, PossiblyAnnotated(qs, target)) => S(q :: qs, target)\n    case other => S((Nil, other))\n\nobject PossiblyParenthesized:\n  def unapply(t: Tree): S[Tree] = t match\n    case Bra(BracketKind.Round, inner) => S(inner)\n    case _ => S(t)\n\n\nsealed abstract class OuterKind(val desc: Str)(using line: Line) extends Ordered[OuterKind]:\n  val ordinal: Int = line.value // YOLO\n  assert(!OuterKind.kinds.contains(ordinal))\n  OuterKind.kinds += (ordinal -> this)\n  def compare(that: OuterKind): Int = this.ordinal - that.ordinal\nobject OuterKind:\n  private var counter = 0\n  private val kinds = mutable.Map.empty[Int, OuterKind]\n\n// Please don't put any of these on the same line...\ncase object BlockKind extends OuterKind(\"block\")\nsealed abstract class DeclKind(val str: Str, desc: Str)(using Line) extends OuterKind(desc)\nsealed abstract class TermDefKind(str: Str, desc: Str)(using Line) extends DeclKind(str, desc)\nsealed abstract class ValLike(str: Str, desc: Str)(using Line) extends TermDefKind(str, desc)\nsealed abstract class Val(str: Str, desc: Str)(using Line) extends ValLike(str, desc)\ncase object ImmutVal extends Val(\"val\", \"value\")\ncase object MutVal extends Val(\"mut val\", \"mutable value\")\ncase object LetBind extends ValLike(\"let\", \"let binding\")\ncase object HandlerBind extends TermDefKind(\"handler\", \"handler binding\")\ncase object Fun extends TermDefKind(\"fun\", \"function\")\ncase object Ins extends TermDefKind(\"using\", \"implicit instance\")\nsealed abstract class TypeDefKind(str: Str, desc: Str)(using Line) extends DeclKind(str, desc)\nsealed trait ObjDefKind\nsealed trait ClsLikeKind extends ObjDefKind:\n  val str: Str\n  val desc: Str\ncase object Cls extends TypeDefKind(\"class\", \"class\") with ClsLikeKind\ncase object Trt extends TypeDefKind(\"trait\", \"trait\") with ObjDefKind\ncase object Mxn extends TypeDefKind(\"mixin\", \"mixin\") with ObjDefKind\ncase object Als extends TypeDefKind(\"type\", \"type alias\") with ObjDefKind\ncase object Pat extends TypeDefKind(\"pattern\", \"pattern\") with ClsLikeKind\ncase object Obj extends TypeDefKind(\"object\", \"object\") with ClsLikeKind\ncase object Mod extends TypeDefKind(\"module\", \"module\") with ClsLikeKind\n\n\n\ntrait TermDefImpl extends TypeOrTermDef:\n  this: TermDef =>\n  \n  def isParameterizedMethod: Bool =\n    (k is Fun) && paramLists.length > 0\n  \n\ntrait TypeOrTermDef extends Located:\n  this: TypeDef | TermDef =>\n  \n  def describe: Str\n  \n  def k: DeclKind\n  def head: Tree\n  \n  type MaybeIdent = Diagnostic \\/ Ident\n  \n  lazy val (symbName, name, paramLists, typeParams, annotatedResultType)\n      : (Opt[MaybeIdent], MaybeIdent, Ls[Tup], Opt[TyTup], Opt[Tree]) =\n    val k = this match\n      case td: TypeDef => td.k\n      case td: TermDef => td.k\n    def rec(t: Tree, symbName: Opt[MaybeIdent], annot: Opt[Tree]): \n      (Opt[MaybeIdent], MaybeIdent, Ls[Tup], Opt[TyTup], Opt[Tree]) = \n      t match\n      \n      // use Foo as foo = ...\n      case InfixApp(typ, Keywrd(Keyword.`as`), id: Ident) if k == Ins =>\n        (S(R(id)), R(id), Nil, N, S(typ))\n      \n      // use Foo = ...\n      case typ if k == Ins =>\n        val name = typ.showDbg\n        val id: Ident = Ident(s\"instance$$$name\")\n        (S(R(id)), R(id), Nil, N, S(typ))\n      \n      \n      case InfixApp(tree, Keywrd(Keyword.`:`), ann) =>\n        rec(tree, symbName, S(ann))\n      \n      // fun f\n      // fun f(n1: Int)\n      // fun f(n1: Int)(nn: Int)\n      case Apps(PossiblyParenthesized(id: Ident), paramLists) =>\n        (symbName, R(id), paramLists, N, annot)\n      \n      // fun f[T]\n      // fun f[T](n1: Int)\n      // fun f[T](n1: Int)(nn: Int)\n      case Apps(App(PossiblyParenthesized(id: Ident), typeParams: TyTup), paramLists) =>\n        (symbName, R(id), paramLists, S(typeParams), annot)\n      \n      case Jux(id: Ident, rhs) =>\n        val err = L:\n          ErrorReport:\n            msg\"Invalid ${k.desc} definition head: unexpected ${rhs.describe} in this position\" -> rhs.toLoc :: Nil\n        (S(err), R(id), Nil, N, annot)\n      \n      case Jux(lhs, rhs) => // happens in `fun (op) nme` form\n        val sn = lhs match\n          case Bra(BracketKind.Round, id: Ident) =>\n            require(symbName.isEmpty) // TODO\n            R(id)\n          case Bra(BracketKind.Round, lhs) =>\n            L:\n              ErrorReport:\n                msg\"This ${lhs.describe} is not a valid symbolic name\" -> lhs.toLoc :: Nil\n          case tree =>\n            L:\n              ErrorReport:\n                msg\"Invalid ${k.desc} definition head: unexpected ${lhs.describe} in this position\" -> lhs.toLoc :: Nil\n        rec(rhs, S(sn), annot)\n        \n      case _ =>\n        (N, L(ErrorReport(\n          msg\"Expected a valid ${k.desc} definition head; found ${t.describe} instead\" -> t.toLoc :: Nil)),\n          Nil, N, annot)\n      \n    rec(baseHead, N, N)\n  \n  val (baseHead, extension, withPart) =\n    head match\n    case InfixApp(InfixApp(base, Keywrd(Keyword.`extends`), ext), Keywrd(Keyword.`with`), wp) =>\n      (base, S(ext), S(wp))\n    case InfixApp(base, Keywrd(Keyword.`with`), wp) =>\n      (base, N, S(wp))\n    case InfixApp(base, Keywrd(Keyword.`extends`), ext) =>\n      (base, S(ext), N)\n    case h => \n      (h, N, N)\n  \nend TypeOrTermDef\n\n\ntrait TypeDefImpl(using State) extends TypeOrTermDef:\n  this: TypeDef =>\n  \n  import semantics.*\n  \n  lazy val symbol: DefinitionSymbol[? <: TypeLikeDef] = k match\n    case Cls => ClassSymbol(this, name.getOrElse(Ident(\"‹error›\")))\n    case Mod | Obj => ModuleOrObjectSymbol(this, name.getOrElse(Ident(\"‹error›\")))\n    case Als => TypeAliasSymbol(name.getOrElse(Ident(\"‹error›\")))\n    case Pat => PatternSymbol(\n      name.getOrElse(Ident(\"‹error›\")),\n      paramLists.headOption,\n      rhs.getOrElse(Empty()))\n    case Trt | Mxn => ???\n  \n  lazy val definedSymbols: Map[Str, BlockMemberSymbol] =\n    // val fromParams = \n    // val fromTypeParams = \n    withPart match\n    case S(blk: Block) =>\n      blk.definedSymbols.toMap\n    case _ =>\n      Map.empty\n  \n  lazy val clsParams: Ls[Ls[TermSymbol]] =\n    this.paramLists.map: tup =>\n      val pts = tup.fields\n      val inUsing = pts.headOption.exists(_.isModified(Ins))\n      pts.flatMap(_.desugared.asParam(inUsing = inUsing).toOption).map:\n        // case ParamTree(spd = S(_)) => lastWords(\"spreads are not allowed in class parameters\") // TODO: properly report this in Elaborator\n        case pt @ ParamTree(ident = id) =>\n          val k = if pt.flags.mut then MutVal else ImmutVal\n          TermSymbol(k, symbol.asClsLike, id)\n      .toList\n    \n  lazy val allSymbols = definedSymbols ++ clsParams.flatten.map(s => s.nme -> s).toMap\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/syntax.scala",
    "content": "package hkmc2\n\nimport scala.util.boundary\n\nimport mlscript.utils._, shorthands._\n\nimport math.Ordered.orderingToOrdered\n\n\ntype Raise = Diagnostic => Unit\ndef raise(using r: Raise): Raise = r\n\n\ntrait TypeLike:\n  def showIn(prec: Int)(using ShowCtx): Str = ???\n  lazy val typeVarsList: List[TypeVar] = this match\n    case uv: TypeVar => uv :: Nil\n    // case Recursive(n, b) => n :: b.typeVarsList\n    // case _ => childrenTypes.flatMap(_.typeVarsList)\n\ntrait NullaryType extends TypeLike\n\ntrait Located:\n  def toLoc: Opt[Loc]\n\ntrait AutoLocated extends Located:\n  protected def children: Vector[Located]\n  \n  private var loc: Opt[Loc] = N\n  \n  def withLoc(s: Int, e: Int, ori: Origin): this.type =\n    withLoc(S(Loc(s, e, ori)))\n  def withLoc(loco: Opt[Loc]): this.type =\n    require(loc.isEmpty, s\"'$this' already has a location: $loc\")\n    loc = loco\n    this\n  def withLocOf(that: Located): this.type = withLoc(that.toLoc)\n  def mkLocWith(otherChildren: Located*): this.type =\n    mkLoc(otherChildren ++ children)\n    this\n  private def mkLoc(allChildren: IterableOnce[Located]) = boundary:\n    if loc.isEmpty then\n      def subLocs = allChildren.iterator.flatMap(_.toLoc.iterator)\n      val spanStart =\n        subLocs.map(_.spanStart).minOption.getOrElse(boundary.break(N))\n      val spanEnd =\n        subLocs.map(_.spanEnd).maxOption.getOrElse(boundary.break(N))\n      val origins = subLocs.map(_.origin).toList.distinct\n      assert(origins.size === 1, (origins, this))\n      val res = S(Loc(spanStart, spanEnd, origins.head))\n      val _ = withLoc(res)\n      res\n    else loc\n  def toLoc: Opt[Loc] = mkLoc(children)\n  def withoutLoc: this.type =\n    loc = N\n    this\n  private[hkmc2] def getLoc: Opt[Loc] = ???\n  \n\n/** If the identifier is an integer, we can still have a string name used as a name hint. */\nfinal case class TypeVar(val identifier_name: EitherOrBoth[Int, Str]) extends NullaryType with TypeVarImpl:\n  val identifier: Int \\/ Str = identifier_name.reduce(left)(right)((x, y) => x)\n  def nameHint: Opt[Str] = identifier_name.second\n  override def toString: Str = identifier.fold(\"α\" + _, identity)\ntrait TypeVarImpl extends Ordered[TypeVar] { self: TypeVar =>\n  def name: Opt[Str] = identifier.toOption.orElse(nameHint)\n  def compare(that: TypeVar): Int =\n    (this.identifier.fold((_, \"\"), (0, _))) compare (that.identifier.fold((_, \"\"), (0, _)))\n}\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/typing/Type.scala",
    "content": "package hkmc2\npackage typing\n\nimport mlscript.utils.*, shorthands.*\nimport syntax.SpreadKind\nimport semantics.{TypeSymbol, VarSymbol}\n\n\nsealed trait TypeArg:\n  def subst(f: PartialFunction[Type.Ref, Type]): this.type\n  def show: Str\n  def showDbg(using DebugPrinter): Str\n  \n  def ub = this match\n    case Wildcard(_, out) => out\n    case ty: Type => ty\n  def lb = this match\n    case Wildcard(in, _) => in\n    case ty: Type => ty\nend TypeArg\n\n\nobject Type:\n  \n  object Tup:\n    def mk(xs: (Type | (SpreadKind, Type))*): Type =\n      Type.Tup(xs.toList)\n  \nenum Type extends TypeArg:\n  case Error\n  case Top\n  case Bot\n  case Ref(sym: TypeSymbol | VarSymbol, args: Ls[TypeArg])\n  case Fun(args: Type, ret: Type, eff: Opt[Type])\n  case Tup(fields: Ls[Type | (SpreadKind, Type)])\n  case Neg(t: Type)\n  case Union(lhs: Type, rhs: Type)\n  case Inter(lhs: Type, rhs: Type)\n  \n  // A placeholder for types that are not yet implemented.\n  case NotImplemented\n  \n  override def show: Str = this match\n    case Error => \"‹error›\"\n    case Top => \"⊤\"\n    case Bot => \"⊥\"\n    case Ref(sym, Nil) => sym.nme\n    case Ref(sym, args) =>\n      s\"${sym.nme}[${args.map(_.show).mkString(\", \")}]\"\n    case Fun(args, ret, eff) =>\n      val effStr = eff.map(e => s\" ! ${e.show}\").getOrElse(\"\")\n      s\"(${args.show}) -> ${ret.show}$effStr\" // TODO improve\n    case Neg(t) =>\n      s\"¬${t.show}\"\n    case Union(l, r) =>\n      s\"(${l.show} ∨ ${r.show})\"\n    case Inter(l, r) =>\n      s\"(${l.show} ∧ ${r.show})\"\n    case NotImplemented => \"‹not implemented›\"\n    case Tup(fields) =>\n      val fieldStrs = fields.map:\n        case ty: Type => ty.show\n        case (spd, ty) => s\"${spd.str}${ty.show}\"\n      s\"[${fieldStrs.mkString(\", \")}]\"\n  \n  override def showDbg(using DebugPrinter): Str = this match\n    case Error => \"‹error›\"\n    case Top => \"⊤\"\n    case Bot => \"⊥\"\n    case Ref(sym, Nil) => s\"${sym.showAsPlain}\"\n    case Ref(sym, args) =>\n      s\"${sym.showAsPlain}[${args.map(_.showDbg).mkString(\", \")}]\"\n    case Fun(args, ret, eff) =>\n      val effStr = eff.map(e => s\" ! ${e.showDbg}\").getOrElse(\"\")\n      s\"(${args.showDbg}) -> ${ret.showDbg}$effStr\" // TODO improve\n    case Neg(t) =>\n      s\"¬${t.showDbg}\"\n    case Union(l, r) =>\n      s\"(${l.showDbg} ∨ ${r.showDbg})\"\n    case Inter(l, r) =>\n      s\"(${l.showDbg} ∧ ${r.showDbg})\"\n    case NotImplemented => \"‹not implemented›\"\n    case Tup(fields) =>\n      val fieldStrs = fields.map:\n        case ty: Type => ty.showDbg\n        case (spd, ty) => s\"${spd.str}${ty.showDbg}\"\n      s\"[${fieldStrs.mkString(\", \")}]\"\n  \n  override def subst(f: PartialFunction[Ref, Type]): this.type =\n    this.match\n      case Error => Error\n      case Top => Top\n      case Bot => Bot\n      case ref: Ref if f.isDefinedAt(ref) =>\n        f(ref)\n      case ref: Ref =>\n        Ref(ref.sym, ref.args.map(_.subst(f)))\n      case Fun(args, ret, eff) =>\n        Fun(args.subst(f), ret.subst(f), eff.map(_.subst(f)))\n      case Neg(t) =>\n        Neg(t.subst(f))\n      case Union(l, r) =>\n        Union(l.subst(f), r.subst(f))\n      case Inter(l, r) =>\n        Inter(l.subst(f), r.subst(f))\n      case NotImplemented => NotImplemented\n      case Tup(fields) =>\n        Tup(fields.map:\n          case ty: Type => ty.subst(f)\n          case (spd, ty) => (spd, ty.subst(f))\n        )\n    .asInstanceOf[this.type]\n  \n  def symbol: Opt[TypeSymbol | VarSymbol] = this match\n    case Ref(sym, _) => S(sym)\n    case _ => N\n  \nend Type\n\ncase class Wildcard(in: Type, out: Type) extends TypeArg:\n  \n  override def subst(f: PartialFunction[Type.Ref, Type]): this.type =\n    Wildcard(in.subst(f), out.subst(f)).asInstanceOf\n  \n  override def show: Str =\n    s\"? <: ${out.show} >: ${in.show}\"\n  \n  override def showDbg(using DebugPrinter): Str =\n    s\"? <: ${out.showDbg} >: ${in.showDbg}\"\n  \nend Wildcard\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/ReplHost.scala",
    "content": "package hkmc2\n\nimport java.io.{BufferedWriter, BufferedReader, InputStreamReader, OutputStreamWriter}\n\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\n/**\n * A helper class to manipulate an interactive Node.js process.\n */\nclass ReplHost(rootPath: Str)(using TL) {\n  \n  private val builder = new java.lang.ProcessBuilder()\n  // `--interactive` always enters the REPL even if stdin is not a terminal.\n  builder.command(\"node\", \"--interactive\")\n  private val proc = builder.start()\n\n  private val stdin = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream))\n  private val stdout = new BufferedReader(new InputStreamReader(proc.getInputStream))\n  private val stderr = new BufferedReader(new InputStreamReader(proc.getErrorStream))\n  \n  // Skip the welcome message.\n  collectUntilPrompt()\n  execute(\"console.info = console.error\")\n  execute(s\"process.chdir('$rootPath')\")\n  \n  /**\n   * This function simply collects output from Node.js until meeting `\"\\n> \"`.\n   * It is useful to skip the welcome message and collect REPL reply from\n   * interactive Node.js. It also filters out syntax errors.\n   * \n   * @return when there are syntax errors, returns `Error` where `syntax` is \n   *         `true`; otherwise, returns the result\n   */\n  private def collectUntilPrompt(): ReplHost.Error | Str = {\n    val buffer = new StringBuilder()\n    while !buffer.endsWith(\"\\n> \") do {\n      val c = stdout.read()\n      if c === -1 then lastWords(s\"ReplHost could not read more from NodeJS stdout.\")\n      buffer.append(c.toChar)\n    }\n    // Remove the trailing `\"\\n> \"`\n    buffer.delete(buffer.length - 3, buffer.length)\n    val reply = buffer.toString()\n    // tl.log(s\"REPL> Collected (raw):\\n${reply}\")\n    val res = reply.linesIterator.find(_.startsWith(ReplHost.syntaxErrorHead)) match {\n      case None => reply.linesIterator.find(_.startsWith(ReplHost.uncaughtErrorHead)) match {\n        case None => reply\n        case Some(uncaughtErrorLine) => {\n          val message = uncaughtErrorLine.substring(ReplHost.uncaughtErrorHead.length)\n          ReplHost.Error(false, message, reply.take(reply.indexOf(uncaughtErrorLine)).trim())\n        }\n      }\n      case Some(syntaxErrorLine) =>\n        val message = syntaxErrorLine.substring(ReplHost.syntaxErrorHead.length)\n        ReplHost.Error(true, message, reply.take(reply.indexOf(syntaxErrorLine)).trim())\n    }\n    tl.log(s\"REPL> Collected:\\n${res}\")\n    res\n  }\n\n  private def consumeStderr(): String = {\n    val buffer = new StringBuilder()\n    while stderr.ready() do\n      buffer.append(stderr.read().toChar)\n    buffer.toString()\n  }\n\n  /**\n   * Parse query results from collected output from Node.js.\n   * \n   * - If there is a line begining with `\"Uncaught SyntaxError: \"`,\n   *    return the syntax error indicated in that line.\n   * - If character `0x200B` presents in the output,\n   *    return the trimmed error message.\n   * - Otherwise, returns the result string.\n   */\n  private def parseQueryResult(): ReplHost.Error | Str =\n    val parsed = collectUntilPrompt() match\n      case reply: Str =>\n        // Find error boundaries.\n        val begin = reply.indexOf(0x200b)\n        val end = reply.lastIndexOf(0x200b)\n        // If there is an error, returns `ReplHost.Error`.\n        if begin >= 0 && end >= 0 then\n          // `console.log` inserts a space between every two arguments,\n          // so + 1 and - 1 is necessary to get correct length.\n          ReplHost.Error(false, reply.substring(begin + 1, end), reply.takeWhile(_ != 0x200b).trim())\n        else reply\n      case error: ReplHost.Error => error\n    tl.log(s\"REPL> Parsed:\\n${parsed}\")\n    parsed\n  \n  /**\n    * Send code to Node.js process.\n    *\n    * @param code the code to execute\n    */\n  private def send(code: Str): Unit =\n    tl.log(s\"REPL> Sending: ${code}\")\n    stdin.write(if code.endsWith(\"\\n\") then code else code + \"\\n\")\n    stdin.flush()\n  \n  def query(prelude: Str, code: Str, showStackTrace: Bool): (ReplHost.Reply, Str) =\n    // Wrap the code with `try`-`catch` block.\n    val wrapped =\n      s\"${prelude}try { $code; undefined } catch (e) { console.log('\\\\u200B' + ${if showStackTrace then \"(e.stack ?? e)\" else \"e\"} + '\\\\u200B'); }\"\n    // Send the code\n    send(wrapped)\n    (parseQueryResult() match\n      case output: Str =>\n        ReplHost.Result(output)\n      case error: ReplHost.Error => error\n    , consumeStderr())\n  \n  /**\n    * Execute class and function declarations.\n    *\n    * @param code the code to execute\n    * @return\n    */\n  def execute(code: Str): ReplHost.Reply = {\n    send(code)\n    collectUntilPrompt() match\n    case res: Str => ReplHost.Result(res)\n    case error: ReplHost.Error => error\n  }\n\n  /**\n    * Kills the Node.js process.\n    */\n  def terminate(): Unit = proc.destroy()\n}\n\nobject ReplHost {\n\n  /**\n    * The syntax error beginning text from Node.js.\n    */\n  private val syntaxErrorHead = \"Uncaught SyntaxError: \"\n  val uncaughtErrorHead = \"Uncaught \"\n\n  /**\n    * The base class of all kinds of REPL replies.\n    */\n  sealed abstract class Reply {\n\n    /**\n      * Maps the successful part. Like `Option[T].map`.\n      *\n      * @param f the function over\n      * @return\n      */\n    def map(f: Str => Reply): Reply\n  }\n\n  /**\n    * Represents a successful reply from Node.js.\n    *\n    * @param content the reply content, i.e. the final result\n    */\n  final case class Result(content: Str) extends Reply {\n    override def map(f: Str => Reply): Reply = f(content)\n    override def toString(): Str = s\"[success] $content\"\n  }\n\n  /**\n    * If the query is `Empty`, we will receive this.\n    */\n  object Empty extends Reply {\n    override def map(f: Str => Reply): Reply = this\n    override def toString(): Str = \"[empty]\"\n  }\n\n  /**\n    * If the query is `Unexecuted`, we will receive this.\n    * @param message the error message\n    */\n  final case class Unexecuted(message: Str) extends Reply {\n    override def map(f: Str => Reply): Reply = this\n    override def toString(): Str = s\"[unexecuted] $message\"\n  }\n\n  /**\n    * If the `ReplHost` captured errors, it will response with `Error`.\n    * @param syntax if `true`, this is a syntax error; otherwise, this is a\n    *               runtime error\n    * @param message the error message\n    */\n  final case class Error(syntax: Bool, message: Str, otherOutputs: Str) extends Reply {\n    override def map(f: Str => Reply): Reply = this\n    override def toString(): Str =\n      if syntax then\n        s\"[syntax error] $message\"\n      else\n        s\"[runtime error] $message\"\n  }\n}\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/ReportFormatter.scala",
    "content": "package hkmc2\n\nimport collection.mutable\n\nimport mlscript.utils.*, shorthands.*\n\n\n/**\n  * Formats diagnostic reports using box drawing characters and/or ANSI colors.\n  *\n  * @param output The output function (e.g., `System.out.println`).\n  * @param colorize Whether to colorize the output using ANSI colors.\n  * @param wrap Optionally wraps each `Raise` call, e.g., with `synchronized`.\n  */\nclass ReportFormatter(\n  output: Str => Unit,\n  val colorize: Bool,\n  val wrap: Opt[(=> Unit) => Unit] = N\n):\n  val MaxLineCount = 5\n  \n  /** Output main text. */\n  private def text(str: Str) =\n    output(if colorize then fansi.Color.Red(str).toString else str)\n  \n  /** Output title text. */\n  private def title(str: Str) =\n    output(if colorize then fansi.Color.LightRed(str).toString else str)\n  \n  val badLines = mutable.Buffer.empty[Int]\n  \n  /** Create a `Raise` dedicated to reporting diagnostics for `file`. */\n  def mkRaise(file: io.Path): Raise =\n    // This shows the parent directory of a file and its name.\n    val relPath = file.relativeTo(file.up.up).map(_.toString).getOrElse(file.toString)\n    d =>\n      def mk =\n        title(s\"/!!!\\\\ Error in $relPath /!!!\\\\\")\n        apply(0, d :: Nil, showRelativeLineNums = false)\n      wrap.fold(mk)(_(mk))\n  \n  /** Report errors and warnings. */\n  def apply(blockLineNum: Int, diags: Ls[Diagnostic], showRelativeLineNums: Bool): Unit =\n    diags.foreach { diag =>\n      val sctx = Message.mkCtx(diag.allMsgs.iterator.map(_._1), \"?\")\n      val onlyOneLine = diag.allMsgs.size =:= 1 && diag.allMsgs.head._2.isEmpty\n      val headStr =\n        val headChar = if onlyOneLine then '═' else '╔'\n        diag match\n        case ErrorReport(msg, loco, mkei, src) =>\n          src match\n            case Diagnostic.Source.Lexing =>\n              s\"$headChar══[LEXICAL ERROR] \"\n            case Diagnostic.Source.Parsing =>\n              s\"$headChar══[PARSE ERROR] \"\n            case Diagnostic.Source.Compilation =>\n              s\"$headChar══[COMPILATION ERROR] \"\n            case Diagnostic.Source.Runtime =>\n              s\"$headChar══[RUNTIME ERROR] \"\n            case Diagnostic.Source.Typing =>\n              s\"$headChar══[TYPE ERROR] \"\n        case WarningReport(msg, loco, mkei, src) =>\n          s\"$headChar══[WARNING] \"\n        case InternalError(msg, loco, mkei, src) =>\n          s\"$headChar══[INTERNAL ERROR] \"\n      val lastMsgNum = diag.allMsgs.size - 1\n      var globalLineNum = blockLineNum\n      diag.allMsgs.zipWithIndex.foreach { case ((msg, loco), msgNum) =>\n        val isLastMsg = msgNum =:= lastMsgNum\n        val msgStr = msg.showIn(using sctx)\n        if msgNum =:= 0 then text(headStr + msgStr)\n        else if loco.isEmpty && diag.allMsgs.size =:= 1 then\n          if !onlyOneLine then text(\"╙──\")\n        else text(s\"${if isLastMsg && loco.isEmpty then \"╙──\" else \"╟──\"} ${msgStr}\")\n        loco.foreach { loc =>\n          val (startLineNum, startLineStr, startLineCol) =\n            loc.origin.fph.getLineColAt(loc.spanStart)\n          badLines += startLineNum\n          if globalLineNum =:= 0 then globalLineNum += startLineNum - 1\n          val (endLineNum, endLineStr, endLineCol) =\n            loc.origin.fph.getLineColAt(loc.spanEnd)\n          var l = startLineNum\n          var c = startLineCol\n          var lineCount = 0\n          while l <= endLineNum && lineCount < MaxLineCount do\n            val isLastLineOfLoc = l === endLineNum || lineCount === MaxLineCount - 1\n            lineCount += 1\n            val globalLineNum = loc.origin.startLineNum + l - 1\n            val relativeLineNum = globalLineNum - blockLineNum + 1\n            val shownLineNum =\n              if showRelativeLineNums && relativeLineNum > 0 then s\"l.+$relativeLineNum\"\n              else \"l.\" + globalLineNum\n            val prepre = \"║  \"\n            val pre = s\"$shownLineNum: \"\n            val curLine = if lineCount < MaxLineCount\n              then loc.origin.fph.lines(l - 1)\n              else \"... (more lines omitted) ...\"\n            text(prepre + pre + \"\\t\" + curLine)\n            val tickBuilder = new StringBuilder()\n            tickBuilder ++= (\n              (if isLastMsg && isLastLineOfLoc then \"╙──\" else prepre)\n              + \" \" * pre.length + \"\\t\" + \" \" * (c - 1))\n            val lastCol = if l =:= endLineNum then endLineCol else curLine.length + 1\n            while c < lastCol do { tickBuilder += ('^'); c += 1 }\n            if c =:= startLineCol then tickBuilder += ('^')\n            text(tickBuilder.toString)\n            c = 1\n            l += 1\n        }\n      }\n      if diag.allMsgs.isEmpty then text(\"╙──\")\n      \n      // if (!mode.fixme) {\n      //   if (!allowTypeErrors\n      //       && !mode.expectTypeErrors && diag.isInstanceOf[ErrorReport] && diag.source =:= Diagnostic.Typing)\n      //     { text(\"TEST CASE FAILURE: There was an unexpected type error\"); failures += globalLineNum }\n      //   if (!allowParseErrors\n      //       && !mode.expectParseErrors && diag.isInstanceOf[ErrorReport] && (diag.source =:= Diagnostic.Lexing || diag.source =:= Diagnostic.Parsing))\n      //     { text(\"TEST CASE FAILURE: There was an unexpected parse error\"); failures += globalLineNum }\n      //   if (!allowTypeErrors && !allowParseErrors\n      //       && !mode.expectWarnings && diag.isInstanceOf[WarningReport])\n      //     { text(\"TEST CASE FAILURE: There was an unexpected warning\"); failures += globalLineNum }\n      // }\n      \n      ()\n    }\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/Scope.scala",
    "content": "package hkmc2\npackage utils\n\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet}\nimport sourcecode.{Name, Line, FileName}\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.Message.MessageContext\nimport Scope.*\nimport hkmc2.semantics.InnerSymbol\nimport hkmc2.semantics.VarSymbol\nimport hkmc2.semantics.Elaborator\nimport hkmc2.semantics.TopLevelSymbol\nimport semantics.Elaborator.State\nimport hkmc2.codegen.Local\nimport hkmc2.codegen.js.JSBuilder\n\n\n/** When `curThis` is N, it means this scope does not rebind `this`.\n  * When `curThis` is Some(None), it means the scope rebinds `this`\n  * to something unknown, following JavaScript's inane `this` handling in `function`s.\n  * When `curThis` is Some(Some(sym)), it means the scope rebinds `this`\n  * to an inner symbol (e.g., class or module).\n  * Note: I made `Scope` a case class just so that it can benefit from `printAsTree`. */\ncase class Scope\n    (val parentOrCfg: Cfg \\/ Scope, val curThis: Opt[Opt[InnerSymbol]], private val bindings: MutMap[Local, Str])\n    (using State):\n  \n  lazy val parent: Opt[Scope] = parentOrCfg.toOption\n  lazy val cfg: Cfg = parentOrCfg.fold(identity, _.cfg)\n  \n  private val existingNames = MutMap.empty[Str, Local]\n  \n  private var thisProxyAccessed = false\n  lazy val thisProxy =\n    curThis match\n    case N | S(N) => die\n    case S(S(State.globalThisSymbol)) => \"globalThis\"\n    case S(S(thisSym)) => \n      thisProxyAccessed = true\n      given Raise = throw _\n      allocateName(thisSym.thisProxy)\n  \n  /** Whether the code generator has produced a binding for `thisProxy` yet. */\n  var thisProxyDefined: Bool = false\n  \n  private def thisError(thisSym: InnerSymbol)(using Raise): Str =\n    raise:\n      InternalError(msg\"`this` not in scope: ${thisSym.toString}\" -> N :: Nil,\n        extraInfo = Some(this),\n        source = Diagnostic.Source.Compilation)\n    \"‹MISSING_THIS›\"\n  \n  def addToBindings(symbol: Local, name: String, shadow: Bool)(using Raise, Line, Name, FileName) =\n    val fullName =\n      if !shadow && lookup(symbol).nonEmpty\n      then\n        raise:\n          InternalError(msg\"`${symbol.toString}` is already in scope\" -> symbol.toLoc :: Nil, extraInfo = Some(this))\n        name + \"‹BAD_SHADOW›\"\n      else name\n    bindings += symbol -> fullName\n    existingNames += fullName -> symbol\n    fullName\n  \n  def getBindings: Iterator[(Local, String)] =\n    bindings.iterator\n  \n  def findThis_!(thisSym: InnerSymbol)(using Raise): Str =\n    // println(s\"findThis_! $thisSym\")\n    def getParent = parent.fold(\n      if thisSym.isInstanceOf[TopLevelSymbol]\n      // * TopLevelSymbol scopes are special and not nested in codegen `Scope`s\n      // * to avoid needlessly generating new variable names in separate blocks.\n      then \"this\"\n      else thisError(thisSym)\n    )\n    curThis match\n    case S(S(sym: TopLevelSymbol)) if sym === State.globalThisSymbol =>\n      // `this` at the top level evaluates to `undefined` in strict mode.\n      // We need this because we generate some code that uses `this`/`globalThis`,\n      // for example the symbol loading code.\n      \"globalThis\"\n    case S(S(`thisSym`)) => \"this\" // no need to qualify `this`\n    case S(_) => getParent(_.findThisProxy_!(thisSym))\n    case N => getParent(_.findThis_!(thisSym))\n  \n  def findThisProxy_!(thisSym: InnerSymbol)(using Raise): Str =\n    // println(s\"findThisProxy_! $thisSym\")\n    if thisSym.isInstanceOf[TopLevelSymbol]\n    then \"globalThis\"\n    else curThis match\n      case S(S(`thisSym`)) => thisProxy\n      case _ => parent.fold(thisError(thisSym))(_.findThisProxy_!(thisSym))\n  \n  def nest: Scope = Scope(R(this), N, MutMap.empty)\n  \n  def getThisScope: Opt[Scope] = curThis.fold(parent.flatMap(_.getThisScope))(_ => S(this))\n  \n  def getOuterThisScope: Opt[Scope] = parent.flatMap(_.getThisScope)\n  \n  def nestRebindThis[R](thisSym: Opt[InnerSymbol])(k: Scope ?=> R): (Opt[Str], R) =\n    val nested = Scope(R(this), S(thisSym), MutMap.empty)\n    val res = k(using nested)\n    getOuterThisScope match\n    case N => (N, res)\n    case S(outer) =>\n      (if outer.thisProxyAccessed then S(outer.thisProxy) else N, res)\n  \n  \n  def inScope(name: Str): Bool =\n    existingNames.contains(name) || parent.exists(_.inScope(name))\n  def reverseLookup(name: Str): Opt[Local] =\n    existingNames.get(name).orElse(parent.flatMap(_.reverseLookup(name)))\n  \n  def lookup(l: Local): Opt[Str] =\n    // curThis.filter(_ is l).map(_ => thisProxy) orElse\n    bindings.get(l).orElse(parent.flatMap(_.lookup(l)))\n  \n  def lookup_!(l: Local, loc: Opt[Loc])(using Raise): Str =\n    lookup(l).getOrElse:\n      // * Prevent long-winded error messages which quote the entire definition.\n      val extraLoc = l match\n        case sym: semantics.BlockMemberSymbol =>\n          sym.trees.collectFirst:\n            case t: syntax.Tree.TypeDef => t.head.toLoc\n          .flatten.orElse(l.toLoc)\n        case other => other.toLoc\n      raise(ErrorReport(msg\"No definition found in scope for member '${l.nme}'\" -> loc ::\n          (if extraLoc.isEmpty then Nil else msg\"which references the symbol introduced here\" -> extraLoc :: Nil),\n        extraInfo = Some(l -> l.getClass -> this),\n        source = Diagnostic.Source.Compilation))\n      l.nme\n  \n  // * Note: it is sound for an existing name to have been allocated with a different prefix (which is only cosmetic)\n  def allocateOrGetName(l: Local, prefix: Str = \"\")(using Raise): Str =\n    lookup(l).getOrElse(allocateName(l, prefix = prefix))\n  \n  def allocateName(l: Local, prefix: Str = \"\", shadow: Bool = false)(using Raise, Line, Name, FileName): Str =\n    \n    val c = cfg\n    \n    // * May be useful later?\n    /* \n    val base: Str = l match\n      case tmp: semantics.TempSymbol if tmp.nameHints.sizeCompare(1) =/= 0 =>\n        prefix + tmp.nameHints.head\n      case _ => if l.nme.isEmpty && prefix.isEmpty then \"tmp\" else prefix + l.nme\n    */\n    val base = if l.nme.isEmpty && prefix.isEmpty then c.defaultName else prefix + l.nme\n    \n    val realBase = if cfg.escapeChars\n      then Scope.replaceInvalidCharacters(base)\n      else base\n    \n    val name =\n      // Try just realBase.\n      if !c.includeZero && !inScope(realBase) && !JSBuilder.keywords.contains(realBase) && realBase.nonEmpty\n      then realBase\n      else\n        // Try realBase with an integer.\n        ((if c.includeZero then 0 else 1) to Int.MaxValue).iterator\n          .map: i =>\n            val idx =\n              if c.useSuperscripts\n              then i.toString.map:\n                case '0' => '⁰'\n                case '1' => '¹'\n                case '2' => '²'\n                case '3' => '³'\n                case '4' => '⁴'\n                case '5' => '⁵'\n                case '6' => '⁶'\n                case '7' => '⁷'\n                case '8' => '⁸'\n                case '9' => '⁹'\n                case _ => die\n              else i.toString\n            s\"$realBase$idx\"\n          .filterNot(inScope).next()\n    \n    val fullName = addToBindings(l, name, shadow = shadow)\n    \n    fullName\n\n\nobject Scope:\n  \n  case class Cfg(escapeChars: Bool, useSuperscripts: Bool, includeZero: Bool, defaultName: Str)\n  object Cfg:\n    val default = Cfg(escapeChars = true, useSuperscripts = false, includeZero = false, defaultName = \"tmp\")\n  end Cfg\n  \n  def scope(using scp: Scope): Scope = scp\n  \n  def empty(cfg: Cfg)(using State): Scope =\n    Scope(L(cfg), S(S(State.globalThisSymbol)), MutMap.empty)\n  \n  def replaceInvalidCharacters(str: Str): Str =\n    str.iterator.map:\n        case c if c.isLetter || c.isDigit => c\n        // case '\\'' => \"$tick\"\n        case '$' => \"$\"\n        case '_' => \"_\"\n        case _ => \"$_\"\n      .mkString\n  \nend Scope\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/SymbolSubst.scala",
    "content": "package hkmc2.utils\n\nimport hkmc2.semantics.*\n\nclass SymbolSubst:\n  def mapBlockMemberSym(s: BlockMemberSymbol): BlockMemberSymbol = s\n  def mapFlowSym(s: FlowSymbol): FlowSymbol = s\n  def mapTempSym(s: TempSymbol): TempSymbol = s\n  def mapVarSym(s: VarSymbol): VarSymbol = s\n  def mapInstSym(s: InstSymbol): InstSymbol = s\n  def mapBuiltInSym(s: BuiltinSymbol): BuiltinSymbol = s\n  def mapTermSym(s: TermSymbol): TermSymbol = s\n  def mapCtorSym(s: CtorSymbol): CtorSymbol = s\n  def mapClsSym(s: ClassSymbol): ClassSymbol = s\n  def mapModuleSym(s: ModuleOrObjectSymbol): ModuleOrObjectSymbol = s\n  def mapTypeAliasSym(s: TypeAliasSymbol): TypeAliasSymbol = s\n  def mapPatSym(s: PatternSymbol): PatternSymbol = s\n  def mapTopLevelSym(s: TopLevelSymbol): TopLevelSymbol = s\n  def mapErrorSym(s: ErrorSymbol): ErrorSymbol = s\n  def mapLabelSym(s: LabelSymbol): LabelSymbol = s\n\nobject SymbolSubst:\n  object Id extends SymbolSubst\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/document/DocBuilder.scala",
    "content": "package hkmc2\npackage document\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport scala.collection._\nimport Document._\n\n/**\n * Use a [[DocBuilder]] to build [[Document]]s for large files. It works similarly to a [[StringBuilder]].\n */\ncase class DocBuilder(NEST_COUNT: Int = DEFAULT_NEST_COUNT) {\n\n  protected val nestedDocs = mutable.Stack(Document.empty: Document)\n\n  protected def thisret[T](x: T): this.type = this\n\n  /** Appends a document to the builder */\n  def +=(d: Document) = thisret {\n    nestedDocs push (nestedDocs.pop() :: d)\n  }\n\n  /** Append a document with a conditional break (breaks in a group are only rendered if the group does not fit on one line) */\n  def +=\\(d: Document) = thisret {\n    this += (d :: break)\n  }\n  /** Append a document with an unconditional break (always insert newline) */\n  def +=\\\\(d: Document) = thisret {\n    this += (d :: forceBreak)\n  }\n\n  /** Inserts an unconditional break */\n  def newLine = this += forceBreak\n\n  /** Indents all documents appended during the execution of `f` */\n  def nest(f: => Unit) = thisret {\n    nestedDocs push empty\n    f\n    this += Document.nest(nestedDocs.pop(), NEST_COUNT)\n  }\n\n  /**\n   * Groups all documents appended during the execution of `f` (grouped documents will have all their conditional\n   * linebreaks break together or not break at all)\n   */\n  def grouped(f: => Document) = thisret {\n    this += group(f)\n  }\n\n  /** Inserts curly braces around documents appended by `f`, in Scala style */\n  def braces(f: => Unit) = thisret {\n    this +=\\ \"{\"\n    nest { f }\n    this +=\\ \"}\"\n  }\n  /** Inserts curly braces around documents appended by the function passed in argument, after appending document `pre` */\n  def bracesAfter(pre: Document) = {\n    this += pre :: \" \"\n    braces\n  }\n\n  /** Inserts a line comment */\n  def comment(text: String) = this +=\\\\ (\"// \" + text)\n\n  /** Converts the current builder to a proper [[Document]] */\n  def toDoc = { require(nestedDocs.size == 1); nestedDocs.head }\n\n}\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/document/Document.scala",
    "content": "package hkmc2\npackage document\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\n\n/* adapted from advanced compiler course project */\n\nimport java.io.{ StringWriter, Writer }\nimport scala.annotation.tailrec\n\n/**\n * A basic pretty-printing library, based on Lindig's strict version\n * of Wadler's adaptation of Hughes' pretty-printer.\n *\n * @author Michel Schinz\n * @author Lionel Parreaux\n */\nsealed abstract class Document {\n  \n  def +(that: Str) = this :: DocText(that)\n  def +(that: Document) = this :: that\n  \n  def ::(that: Document): Document = (this, that) match\n    case (DocNil, _) => that\n    case (_, DocNil) => this\n    case _           => DocCons(that, this)\n  \n  def :/:(hd: Document): Document = hd :: DocBreak(force = false) :: this\n  def :\\\\:(hd: Document): Document = hd :: DocBreak(force = true) :: this\n  \n  def stripBreaks: Document = this match\n    case DocBreak(false) => DocNil\n    case DocCons(DocText(\"\"), t) => t.stripBreaks\n    case DocCons(h, t) =>\n      val res = h.stripBreaks\n      if res is h then this else res :: t\n    case _ => this\n  \n  def isEmpty: Bool = this match\n    case DocNil => true\n    case DocText(\"\") => true\n    case DocGroup(doc) => doc.isEmpty\n    case DocCons(hd, tl) => hd.isEmpty && tl.isEmpty\n    case _ => false\n  \n  /**\n   * Format this document on `writer` and try to set line\n   * breaks so that the result fits within `width` columns.\n   */\n  def format(width: Int, writer: Writer): Unit =\n    type FmtState = (Int, Boolean, Document) // indent, doBreak, doc\n    \n    @tailrec\n    def fits(w: Int, docs: List[Document]): Boolean = docs match\n      case _ if w < 0 =>\n        false\n      case Nil =>\n        true\n      case DocNil :: z =>\n        fits(w, z)\n      case DocCons(h, t) :: z =>\n        fits(w, h :: t :: z) // List prepend here, not doc\n      case DocText(t) :: z =>\n        fits(w - t.length, z)\n      case DocNest(ii, d) :: z =>\n        fits(w, d :: z)\n      case DocBreak(true) :: z =>\n        false\n      case DocBreak(false) :: z =>\n        fits(w - 1, z)\n      case DocGroup(d) :: z =>\n        fits(w, d :: z)\n    \n    def spaces(n: Int): Unit =\n      var rem = n\n      while rem >= 16 do { writer.write(\"                \"); rem -= 16 }\n      if rem >= 8 then { writer.write(\"        \"); rem -= 8 }\n      if rem >= 4 then { writer.write(\"    \"); rem -= 4 }\n      if rem >= 2 then { writer.write(\"  \"); rem -= 2 }\n      if rem === 1 then { writer.write(\" \") }\n    \n    @tailrec\n    def fmt(charsIntoLine: Int, state: List[FmtState]): Unit =\n      def write(indent: Int, text: String): Int =\n        val written = (\n            if charsIntoLine === 0\n            then\n              spaces(indent)\n              indent\n            else charsIntoLine\n          ) + text.length\n        writer.write(text)\n        written\n      state match\n      case Nil => ()\n      case (_, _, DocNil) :: z =>\n        fmt(charsIntoLine, z)\n      case (i, b, DocCons(h, t)) :: z =>\n        fmt(charsIntoLine, (i, b, h) :: (i, b, t) :: z)\n      case (i, _, DocText(t)) :: z =>\n        fmt(write(i, t), z)\n      case (i, b, DocNest(ii, d)) :: z =>\n        fmt(charsIntoLine, (i + ii, b, d) :: z)\n      case (i, doBreak, DocBreak(force)) :: z if doBreak || force =>\n        write(i, \"\\n\")\n        fmt(0, z)\n      case (i, false, DocBreak(false)) :: z =>\n        fmt(write(i, \" \"), z)\n      case (i, _b, DocGroup(d)) :: z =>\n        val fitsFlat = fits(width - charsIntoLine, d :: z.map(_._3))\n        fmt(charsIntoLine, (i, !fitsFlat, d) :: z)\n      case _ =>\n        ()\n    \n    fmt(0, (0, false, DocGroup(this)) :: Nil)\n    \n  end format\n  \n  def mkString(columns: Int = Int.MaxValue): Str =\n    val w = new StringWriter()\n    format(columns, w)\n    w.toString\n  \n}\n\nobject Document {\n  /** The empty document */\n  def empty: Document = DocNil\n  \n  /** A break, which will either be turned into a space or a line break */\n  def break: Document = DocBreak(false)\n  \n  /** An unconditional break */\n  def forceBreak: Document = DocBreak(true)\n  \n  /** A document consisting of some text literal; escapes \\n characters, unlike DocText */\n  def text(s: String): Document =\n    val docs = s.split(\"\\\\n\", -1).map(DocText(_)) // \\n needs not be escaped here because it's a single-character string...\n    docs.toSeq.mkDocument(forceBreak)\n  \n  /**\n   * A group, whose components will either be printed with all breaks\n   * rendered as spaces, or with all breaks rendered as line breaks.\n   */\n  def group(d: Document): Document = DocGroup(d)\n  \n  /** A nested document, which will be indented as specified. */\n  def nest(doc: Document, indent: Int = DEFAULT_NEST_COUNT): Document = DocNest(indent, doc)\n  \n  val DEFAULT_NEST_COUNT = 2\n  \n  def bracketed(pre: Str, post: Str, insertBreak: Bool = false)(d: Document): Document =\n    if d.isEmpty\n    then pre + post\n    else group(doc\"$pre #{ ${if insertBreak then break :: d else d} #}  # $post\")\n  \n  def braced(d: Document): Document = bracketed(\"{\", \"}\")(d)\n  def bracedbk(d: Document): Document = bracketed(\"{\", \"}\", insertBreak = true)(d)\n  \n}\n\nprivate case object DocNil extends Document\nprivate case class DocBreak(force: Boolean) extends Document\nprivate case class DocText(txt: String) extends Document {\n  if txt contains '\\n' then\n    System.err.println(s\"Warning: DocText should not contain \\\\n characters; use DocBreak instead:\\n\\t$txt\")\n}\nprivate case class DocGroup(doc: Document) extends Document\nprivate case class DocNest(indent: Int, doc: Document) extends Document\nprivate case class DocCons(hd: Document, tl: Document) extends Document\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/document/DocumentContext.scala",
    "content": "package hkmc2\npackage document\n\nimport collection.immutable.ArraySeq\nimport collection.immutable.ArraySeq.unsafeWrapArray\nimport util.matching.Regex\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport Document._\n\n/**\n * Doc formatter using string interpolation.\n * Markers \" #{ \", \" #} \" (including the space character) are used to express nesting\n * Marker \" # \" expresses document break, as well as \"\\n\".\n *\n * For example:\n * {{{\n *   doc\"class A { #{  # $decl #}  # }\"\n * }}}\n * instead of:\n * {{{\n *   \"class A {\" :: Document.nest(2, DocBreak :: decl) :/: \"}\"\n * }}}\n */\n\nobject DocumentContext:\n  private val NestRegex = \" #\\\\{ \".r\n  private val UnNestRegex = \" #\\\\} \".r\n  private val BeginGroupRegex = \"\\\\\\\\\\\\{\".r\n  private val EndGroupRegex = \"\\\\\\\\\\\\}\".r\n  private val DocBreakRegex = \" # \".r\n  private val ForceDocBreakRegex = \"\"\"\\\\n\"\"\".r\n\n  case object Nest; type Nest = Nest.type\n  case object UnNest; type UnNest = UnNest.type\n  case object BeginGroup; type BeginGroup = BeginGroup.type\n  case object EndGroup; type EndGroup = EndGroup.type\n  case object Insert; type Insert = Insert.type\n  case class RawDocText(s: String) // avoids the \"\\n chars\" warning of DocText\nimport DocumentContext.*\n\nclass DocumentContext(ctx: StringContext) {\n  \n  object doc {\n  \n    def apply(docs: Document*): Document =\n      \n      type DocsMarkers = Document | Nest | UnNest | BeginGroup | EndGroup | RawDocText\n      type DocsMarkersInsert = DocsMarkers | Insert\n      \n      assert(ctx.parts.size == docs.size + 1 && ctx.parts.size > 0)\n      \n      def interleave(docs: Seq[DocsMarkersInsert], interleaved: DocsMarkersInsert) =\n        docs.head :: (docs.iterator.drop(1).map { List(interleaved, _) }.flatten.toList: Ls[DocsMarkersInsert])\n      \n      def splitOn(mark: Regex, interleaved: DocsMarkersInsert) = (ds: Ls[DocsMarkersInsert]) => ds.flatMap:\n        case RawDocText(str) => \n          interleave(unsafeWrapArray(mark.pattern.split(str, -1)).map(RawDocText(_)), interleaved)\n        case d: DocsMarkersInsert     => Seq(d)\n      \n      // Makes a sequence of the parts separated with Nest, UnNest and Insert (for positions where docs are to be inserted)\n      val parts = (\n        splitOn(NestRegex, Nest) andThen\n        splitOn(UnNestRegex, UnNest) andThen\n        splitOn(BeginGroupRegex, BeginGroup) andThen\n        splitOn(EndGroupRegex, EndGroup) andThen\n        splitOn(DocBreakRegex, DocBreak(false)) andThen\n        splitOn(ForceDocBreakRegex, DocBreak(true)) // interpolated strings don't get special chars replaced (we escape \\n for the regex)\n      )(interleave(ctx.parts.map(RawDocText(_)), Insert)).map:\n          case RawDocText(s) => text(s) // 'text' escapes \\n chars\n          case d             => d\n      \n      val diter = docs.iterator\n      val allDocs = parts.map:\n        case Insert      => diter.next()\n        case d: DocsMarkers => d\n      \n      // Processes the sequence, replacing Nest..UnNest pairs by a nest(..) call\n      // and BeginGroup..EndGroup pairs by a group(..) call\n      var curDocs = allDocs\n      def process(acc: Document, outer: Insert | Nest | BeginGroup): Document = curDocs match\n        case Nil =>\n          outer match\n          case Insert      => acc\n          case Nest        => throw IllegalArgumentException(\"Unmatched opening nest marker\")\n          case BeginGroup  => throw IllegalArgumentException(\"Unmatched opening group marker\")\n        case doc :: rest =>\n          curDocs = rest\n          doc match\n          case Nest =>\n            process(acc :: nest(process(empty, Nest)), outer)\n          case UnNest =>\n            outer match\n            case Nest => acc\n            case _    => throw IllegalArgumentException(\"Closing nest marker closes nothing\")\n          case BeginGroup =>\n            process(acc :: group(process(empty, BeginGroup)), outer)\n          case EndGroup =>\n            outer match\n            case BeginGroup => acc\n            case _          => throw IllegalArgumentException(\"Closing group marker closes nothing\")\n          case doc: Document =>\n            process(acc :: doc, outer)\n          case RawDocText(str) =>\n            process(acc :: text(str), outer)\n      end process\n      process(empty, Insert)\n      \n  }\n  \n}\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/document/Liftable.scala",
    "content": "package hkmc2\npackage document\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport scala.annotation.implicitNotFound\n\n/**\n * Describes how to lift objects using the `doc` string interpolation.\n */\n@implicitNotFound(\"Cannot find document.Liftable implementation for type ${T}\")\ntrait Liftable[-T] {\n  def apply(value: T): Document\n}\n\nobject Liftable {\n\n  def apply[T](f: T => Document): Liftable[T] =\n    new Liftable[T] { def apply(value: T): Document = f(value) }\n\n}\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/document/package.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport scala.language.implicitConversions\n\n/**\n * A basic pretty-printing library that handles indentation and conditional line-breaking.\n *\n * The most convenient way to build a Document is with a combination of `doc\"...\"` string interpolation and use of [[DocBuilder]].\n * To use `doc` string interpolation, you have to import `document._`.\n *\n */\npackage object document {\n  import Document._\n\n  implicit def toDocumentContext(ctx: StringContext): DocumentContext = new DocumentContext(ctx)\n\n  implicit def toDocument[T: Liftable](x: T): Document = implicitly[Liftable[T]].apply(x)\n\n  implicit val docLift: Liftable[Document] = Liftable[Document](identity)\n\n  implicit val intLift: Liftable[Int] = Liftable[Int](_.toString)\n\n  implicit val strLift: Liftable[String] = Liftable[String](text)\n\n  // /** Lifting document lists with line breaks in between is almost never what the user wants, and leads to errors */\n  //  implicit def seqLift[T: Liftable]: Liftable[Seq[T]] = Liftable[Seq[T]] { ls =>\n  //    val lift = implicitly[Liftable[T]].apply _\n  //    (ls map lift).mkDocument()\n  //  }\n\n  implicit class LiftableSeqOps[A: Liftable](docs: Seq[A]) {\n    def mkDocument(pre: Document, sep: Document, post: Document): Document = docs filter (_ != empty) match {\n      case d +: ds => pre :: ((d: Document) +: ds.map(sep :: _)).foldLeft(empty)(_ :: _) :: post\n      case _       => pre :: post\n    }\n    def mkDocument(sep: Document = empty): Document = mkDocument(empty, sep, empty)\n  }\n\n}\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/hkmc2/utils/utils.scala",
    "content": "package hkmc2\n\nimport scala.util.chaining.scalaUtilChainingOps\n\nimport mlscript.utils.*, shorthands.*\n\ngiven utils.TraceLogger => DebugPrinter =\n  summon[utils.TraceLogger].debugPrinter\n\n\nextension (s: Str)\n  def escaped: Str =\n    s.iterator.flatMap:\n      case '\\b' => \"\\\\b\"\n      case '\\t' => \"\\\\t\"\n      case '\\n' => \"\\\\n\"\n      case '\\r' => \"\\\\r\"\n      case '\\f' => \"\\\\f\"\n      case '\"' => \"\\\\\\\"\"\n      case '\\\\' => \"\\\\\\\\\"\n      case c if c.isControl => f\"\\\\u${c.toInt}%04x\"\n      case c => c.toString\n    .mkString(\"\\\"\", \"\", \"\\\"\")\n\n\nabstract class OnceFunction[-A, +B] extends (A => B):\n  private var called = false\n  final def apply(x: A): B =\n    if called then throw new IllegalStateException(\"This function can only be called once.\")\n    called = true\n    applyBody(x)\n  def applyBody(x: A): B\ninline def ensureOnce[A, B](f: OnceFunction[A, B]): f.type = f\n\n\nimport hkmc2.semantics.{TermDefFlags, FldFlags, ParamListFlags, Resolvable}\nimport scala.collection.mutable.Buffer\n\n\ntrait ProductWithTail extends Product\n\ntrait ProductWithExtraInfo extends Product:\n  def extraInfo(using DebugPrinter): Str\n\n\nextension (t: Product)\n  def showAsTree(using ts: DebugPrinter): Str =\n    ts.printProduct(false, t)\n\nextension (t: Any)\n  def showAsPlain(using ts: DebugPrinter): Str =\n    ts.printPlain(t)\n\n\nclass DebugPrinter:\n  given DebugPrinter = this\n  \n  def preProcess(t: Product): Product = t\n  def postProcess(t: Product): Str = \"\"\n  \n  def printPlain(v: Any): Str = v.toString\n  \n  def printProduct(inTailPos: Bool, t: Product): Str =\n    \n    def aux(v: Any, inTailPos: Bool = false): Str =\n      v match\n      case Some(v) => \"S of \" + aux(v)\n      case None => \"N\"\n      case Nil => \"Nil\"\n      case xs: List[_] => \"Ls of \\n\" + xs.iterator.map(aux(_)).mkString(\"\\n\").indent(\"  \")\n      case xs: Vector[_] => \"Vector of \\n\" + xs.iterator.map(aux(_)).mkString(\"\\n\").indent(\"  \")\n      case s: Str => s.escaped\n      case TermDefFlags(isMethod) =>\n        val flags = Buffer.empty[Str]\n        if isMethod then flags += \"method\"\n        flags.mkString(\"(\", \", \", \")\")\n      case FldFlags(mut, spec, pat, value) =>\n        val flags = Buffer.empty[Str]\n        if mut then flags += \"mut\"\n        if spec then flags += \"spec\"\n        if pat then flags += \"pat\"\n        if value then flags += \"val\"\n        flags.mkString(\"(\", \", \", \")\")\n      case ParamListFlags(ctx) =>\n        val flags = Buffer.empty[Str]\n        if ctx then flags += \"ctx\"\n        flags.mkString(\"(\", \", \", \")\")\n      case Loc(start, end, origin) =>\n        val (sl, _, sc) = origin.fph.getLineColAt(start)\n        val (el, _, ec) = origin.fph.getLineColAt(end)\n        s\"Loc at :$sl:$sc-$el:$ec\"\n      case codegen.Scoped(syms, body) =>\n        val symsStr = \"{\" + syms.toArray.sortBy(_.uid).map(_.showAsPlain).mkString(\", \") + \"}\"\n        s\"Scoped(syms = $symsStr): \\n\" + s\"body = ${printProduct(false, body)}\".indent(\"  \")\n      \n      case t: Product => printProduct(inTailPos, t)\n      case v => printPlain(v)\n    \n    val tt = preProcess(t)\n    val postfix = postProcess(tt)\n    val midfix = tt match\n      case t: ProductWithExtraInfo => t.extraInfo match\n        case \"\" => \"\"\n        case str => \"{\" + str + \"}\"\n      case _ => \"\"\n    val prefix = tt.productPrefix + midfix + postfix\n    \n    tt.productArity match\n      case 0 => prefix\n      case 1 => prefix + \" of \" + aux(tt.productElement(0))\n      case a =>\n        var args = tt.productIterator.zipWithIndex.filterNot(DebugPrinter.emptyValues contains _._1).map:\n          case (v, i) => tt.productElementName(i) + \" = \" + aux(v, tt.isInstanceOf[ProductWithTail] && i === a - 1)\n        // val emptyArgs = args.isEmpty\n        // val argsStr = if emptyArgs then \"‹empty›\" else args.mkString(\"\\n\")\n        // prefix + locally:\n        //   if inTailPos then \": \\\\\\n\" + argsStr\n        //   else \":\\n\" + argsStr.indent(\"  \")\n        if args.isEmpty then prefix + \": ‹empty›\" else\n          val argsStr = args.mkString(\"\\n\")\n          prefix + locally:\n            if inTailPos then \": \\\\\\n\" + argsStr\n            else \":\\n\" + argsStr.indent(\"  \")\n\nend DebugPrinter\n\nobject DebugPrinter:\n  \n  val emptyValues: Set[Any] = Set(\n    None, Nil, Vector.empty,\n    semantics.PlainParamList(Nil),\n    ParamListFlags.empty,\n    TermDefFlags.empty,\n    FldFlags.empty,\n    codegen.End(\"\"),\n  )\n  \nend DebugPrinter\n\nextension [A](self: Opt[A])\n  def mapConserve[B](f: A => A): Opt[A] =\n    self match\n      case S(v) =>\n        val v2 = f(v)\n        if v2 is v then self\n        else S(v2)\n      case N => N\n\nextension [A](ls: Ls[A])\n  /** Apply a special function for lists with one element. */\n  def foldSingleton[B](no: Ls[A] => B)(yes: A => B): B = ls match\n    case x :: Nil => yes(x)\n    case Nil | _ :: _ => no(ls)\n\nextension (n: Int)\n  /** Converts a number to its English word representation. */\n  def spelled: Str = n match\n    case 0 => \"zero\"  case 1 => \"one\"       case 2 => \"two\"\n    case 3 => \"three\" case 4 => \"four\"      case 5 => \"five\"\n    case 6 => \"six\"   case 7 => \"seven\"     case 8 => \"eight\"\n    case 9 => \"nine\"  case _ => n.toString\n\nobject English:\n  // These lists are not complete (nor are they intended to be). Please add\n  // necessary words as needed.\n  val irregularPlurals = Map(\"datum\" -> \"data\", \"index\" -> \"indices\")\n  val ves = Set(\"proof\")\n  val o = Set(\"zero\")\n\nextension (str: Str)\n  /** Converts a singular noun to its plural form using English pluralization\n   *  rules. The rules should be updated as needed. */\n  def pluralize: Str = English.irregularPlurals.getOrElse(str,\n    if str.isEmpty then str else str(str.size - 1) match\n      // -s, -sh, -ch, -x, -z -> +es; e.g., bus -> buses, box -> boxes\n      case 's' | 'x' | 'z' => str + \"es\"\n      // -sh, -ch -> +es; e.g., brush -> brushes, church -> churches\n      case 'h' if str.size > 1 && (str(str.size - 2) === 's' || str(str.size - 2) === 'c') =>\n        str + \"es\"\n      // -o -> +es (with some exceptions); e.g., potato -> potatoes\n      case 'o' if !English.o.contains(str) => str + \"es\"\n      // -[^aeiou]y -> -ies; e.g., city -> cities, but not toy -> toys\n      case 'y' if str.size > 1 => str(str.size - 2) match\n        case 'a' | 'e' | 'i' | 'o' | 'u' => str + \"s\" // Vowel before 'y'\n        case _ => str.dropRight(1) + \"ies\" // Consonant before 'y'\n      // -f -> -ves (with exceptions); e.g., leaf -> leaves\n      case 'f' if !English.ves.contains(str) => str.dropRight(1) + \"ves\"\n      // -fe -> -ves; e.g., knife -> knives\n      case 'e' if str.size > 1 && str(str.size - 2) === 'f' => str.dropRight(2) + \"ves\"\n      // Default case: just add 's'\n      case _ => str + \"s\")\n  \n  /** Formats a number and a noun as a human-readable string. */\n  infix def countBy(n: Int): Str =\n    s\"${n.spelled} ${if n === 1 then str else str.toLowerCase.pluralize}\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/utils/EitherOrBoth.scala",
    "content": "package mlscript.utils\n\nimport shorthands.*\n\nenum EitherOrBoth[+A, +B]:\n  case First[+A](value: A) extends EitherOrBoth[A, Nothing]\n  case Second[+B](value: B) extends EitherOrBoth[Nothing, B]\n  case Both[+A, +B](firstValue: A, secondValue: B) extends EitherOrBoth[A, B]\n  \n  def first: Opt[A] = this `|>?` :\n    case First(v) => v\n    case Both(v, _) => v\n  def second: Opt[B] = this `|>?` :\n    case Second(v) => v\n    case Both(_, v) => v\n  def options: (Opt[A], Opt[B]) = (first, second)\n  \n  def fold[R](f: A => R)(g: B => R)(h: (A, B) => R): R = this match\n    case First(v) => f(v)\n    case Second(v) => g(v)\n    case Both(a, b) => h(a, b)\n  \n  def reduce[R](f: A => R)(g: B => R)(h: (R, R) => R): R =\n    fold(f)(g)((x, y) => h(f(x), g(y)))\n  \n  def merge[R](f: (A | B) => R)(h: (R, R) => R): R =\n    reduce(f)(f)(h)\n  \nend EitherOrBoth\nexport EitherOrBoth.{ First, Second, Both }\n\n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/utils/FastParseHelpers.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable.ArrayBuffer\n\nimport mlscript.utils._, shorthands._\n\nclass FastParseHelpers(val blockStr: Str, val lines: collection.IndexedSeq[Str]):\n  def this(lines: IndexedSeq[Str]) = this(lines.mkString(\"\\n\"), lines)\n  def this(blockStr: Str) = this(blockStr, blockStr.splitSane('\\n'))\n  \n  // this line-parsing logic was copied from fastparse internals:\n  // val lineNumberLookup: Array[Int] = fastparse.internal.Util.lineNumberLookup(blockStr)\n  val lineNumberLookup: Array[Int] = mkLineNumberLookup(blockStr)\n  def mkLineNumberLookup(data: String): Array[Int] =\n    val lineStarts = new ArrayBuffer[Int]()\n    var i = 0\n    var col = 1\n    var cr = false\n    var prev: Character = null\n    while i < data.length do\n      val char = data(i)\n      if char == '\\r' then\n        if prev != '\\n' && col == 1 then lineStarts.append(i)\n        col = 1\n        cr = true\n      else if char == '\\n' then\n        if prev != '\\r' && col == 1 then lineStarts.append(i)\n        col = 1\n        cr = false\n      else\n        if col == 1 then lineStarts.append(i)\n        col += 1\n        cr = false\n      prev = char\n      i += 1\n    if col == 1 then lineStarts.append(i)\n\n    lineStarts.toArray\n  \n  def getLineColAt(index: Int): (Int, String, Int) =\n    val lineNum = lineNumberLookup.indexWhere(_ > index) match\n      case -1 => lineNumberLookup.length\n      case n => math.max(1, n)\n    val idx = lineNum.min(lines.length) - 1\n    val colNum = index - lineNumberLookup(idx) + 1\n    val lineStr = lines(idx)\n    (lineNum, lineStr, colNum)\n  \n"
  },
  {
    "path": "hkmc2/shared/src/main/scala/utils/TraceLogger.scala",
    "content": "package hkmc2\npackage utils\n\nimport mlscript.utils.*, shorthands.*\n\n\ntype TL = TraceLogger\ndef tl(using TL): TL = summon\n\n\nabstract class TraceLogger(using val debugPrinter: DebugPrinter):\n  def doTrace: Bool = true\n  \n  protected val noPostTrace: Any => Str = _ => \"\"\n  \n  protected var indent = 0\n  def trace[T](pre: => Str, post: T => Str = noPostTrace)(thunk: => T): T = {\n    log(pre)\n    enter()\n    val res = try thunk finally exit()\n    if post isnt noPostTrace then log(post(res))\n    res\n  }\n  inline def traceNot[T](pre: => Str, post: T => Str = noPostTrace)(thunk: => T): T =\n    thunk\n  \n  inline def enter() = indent += 1\n  inline def exit() = indent -= 1\n  \n  protected[hkmc2] def emitDbg(str: Str): Unit = scala.Predef.println(str)\n  \n  inline def log(msg: => Any): Unit = log(msg, noIndent = false)\n\n  def logs(msgs: => Any*): Unit =\n    if doTrace then msgs.foreach(log(_))\n  \n  def log(msg: => Any, noIndent: Bool = false): Unit =\n    if doTrace then emitDbg(if noIndent then msg.toString\n      else \"| \" * indent + msg.toString.indentNewLines(\"| \" * indent + \">  \"))\n\n  protected var scope: Opt[Str] = N\n\n  def scoped[T](flag: Str)(thunk: => T): T =\n    var oldScope = scope\n    scope = S(flag)\n    try thunk finally scope = oldScope\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/js/MyClass.mjs",
    "content": "export default class MyClass {\n  constructor(name) {\n    this.name = name;\n  }\n  greet() {\n    console.log(`Hello from ${this.name}!`);\n  }\n}\n"
  },
  {
    "path": "hkmc2/shared/src/test/js/Test.mjs",
    "content": "\nexport function greet() {\n  console.log('Hello from Test.mjs!');\n}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ChangedTests.cmd",
    "content": ":tests\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ElabScratch.mls",
    "content": ":js\n// :de\n// :sjs\n// :pt\n// :elt\n\n:global\n:d\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/HkScratch.mls",
    "content": ":js\n// :de\n// :sjs\n// :pt\n// :elt\n\n:global\n// :d\n// :todo\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/OverloadedModulesInSignatures.mls",
    "content": ":js\n\n\nclass ClsMod with\n  val whoami = \"class\"\nmodule ClsMod with\n  val whoami = \"module\"\n\ntype TypMod = Int\nmodule TypMod with\n  val whoami = \"module\"\n\n:fixme\nfun TrmMod = 42\nmodule TrmMod with\n  val whoami = \"module\"\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of function 'TrmMod'\n//│ ║  l.14: \tfun TrmMod = 42\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── with module of the same name\n//│ ║  l.15: \tmodule TrmMod with\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.16: \t  val whoami = \"module\"\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^\n\nfun f: ClsMod = 42\n\n:rt\nf\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:f⁰,typ=class:ClsMod⁰}:\n//│     t = Ref{sym=member:f¹} of member:f¹\n//│     sym = term:f⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\nfun f: module ClsMod = ClsMod\n\n:rt\nf\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:f²,typ=module:ClsMod¹}:\n//│     t = Ref{sym=member:f³} of member:f³\n//│     sym = term:f²\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class ClsMod { whoami: \"module\" }\n\nfun f: TypMod = 42\n\n:rt\nf\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:f⁴,typ=type:TypMod⁰}:\n//│     t = Ref{sym=member:f⁵} of member:f⁵\n//│     sym = term:f⁴\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\nfun f: module TypMod = TypMod\n\n:rt\nf\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:f⁶,typ=module:TypMod¹}:\n//│     t = Ref{sym=member:f⁷} of member:f⁷\n//│     sym = term:f⁶\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class TypMod { whoami: \"module\" }\n\n:e\nfun f: TrmMod = 42\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference of type TrmMod denoting module 'TrmMod'.\n//│ ║  l.75: \tfun f: TrmMod = 42\n//│ ║        \t       ^^^^^^\n//│ ╙── Function must be marked as returning a 'module' in order to have a module return type.\n\n:sjs\nfun f = TrmMod\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f5; f5 = function f() { return TrmMod1() };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:fixme\n:expect 42\nf\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor TrmMod cannot be invoked without 'new'\n//│ ═══[RUNTIME ERROR] Expected: '42', got: 'undefined'\n\n:sjs\nfun f: module TrmMod = TrmMod\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f6; f6 = function f() { return TrmMod1.class };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun assertModule(module m: ClsMod): module ClsMod = m\n\nassertModule(ClsMod).whoami\n//│ = \"module\"\n\nassertModule(TypMod).whoami\n//│ = \"module\"\n\n:fixme\nassertModule(TrmMod).whoami\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor TrmMod cannot be invoked without 'new'\n\n\nfun assertNonModule(m) = m\n\n// FIXME: should not resolve to module's `.whoami`, hence should be an error\n:breakme\nassertNonModule(ClsMod).whoami\n//│ = \"module\"\n\n// FIXME: should not resolve to module's `.whoami`, hence should be an error\n:breakme\nassertNonModule(TypMod).whoami\n//│ = \"module\"\n\n// FIXME: should not resolve to module's `.whoami`, hence should be an error\n// FIXME: Should module-check as the term module (or probably we will remove module-checks before that)\n:breakme\n:fixme\nassertNonModule(TrmMod).whoami\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor TrmMod cannot be invoked without 'new'\n\n\ntype Foo[A] = Int\nmodule Foo\n\n:e\nfun f(x: Foo): Foo = x\n//│ ╔══[COMPILATION ERROR] Expected 1 type arguments, got none\n//│ ║  l.136: \tfun f(x: Foo): Foo = x\n//│ ╙──       \t         ^^^\n//│ ╔══[COMPILATION ERROR] Expected 1 type arguments, got none\n//│ ║  l.136: \tfun f(x: Foo): Foo = x\n//│ ╙──       \t               ^^^\n\nfun f(x: Foo[Int]): Foo[Int] = x\n\nfun f(module x: Foo): module Foo = x\n\n:e\nfun f(module x: Foo[Int]): module Foo[Int] = x\n//│ ╔══[COMPILATION ERROR] Expected no type arguments, got 1\n//│ ║  l.149: \tfun f(module x: Foo[Int]): module Foo[Int] = x\n//│ ╙──       \t                ^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected no type arguments, got 1\n//│ ║  l.149: \tfun f(module x: Foo[Int]): module Foo[Int] = x\n//│ ╙──       \t                                  ^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/AccountingTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/apps/Accounting.mls\"\n\n\nval acc = new Accounting\n//│ acc = Accounting {\n//│   warnings: [],\n//│   Project: fun Project { class: class Project },\n//│   Line: fun Line { class: class Line },\n//│   lines: [],\n//│   Report: fun Report { class: class Report }\n//│ }\n\nval proj = acc.Project(\"P1\")\n//│ proj = Project(\"P1\")\n\nval l1 = acc.mkLine(\"L1\", proj, 200_000, true)\nval l2 = acc.mkLine(\"L2\", proj, 1_000_000, true)\n//│ l1 = Line(\"L1\", Project(\"P1\"), 200000, true)\n//│ l2 = Line(\"L2\", Project(\"P1\"), 1000000, true)\n\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\nacc.process of \"out/apps/AccountingTest.md\", report => ...\n\n\nreport.snapShot of \"Initial\"\n\nl1.expense(33_880.87)\nl2.expense(666_666) // Luyu's juicy post-PQE salary\n\n\nreport.snapShot of \"Y1\"\n\nl1.expense(10_000)\nl2.expense(200_000)\n\n\nreport.snapShot of \"Y2\"\n\nl1.expense(10_000)\nl2.expense(130_000)\n\n\nreport.snapShot of \"Y3\"\n\nl1.mustBeEmpty()\nl2.mustBeEmpty()\n\n\n//│ > Report written to out/apps/AccountingTest.md\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/CSVTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/apps/CSV.mls\"\n\n\nlet csv = CSV(undefined)\n//│ csv = CSV(\",\")\n\n\ncsv.strDelimiter\n//│ = \",\"\n\ncsv.objPattern\n//│ = /(\\,|\\r?\\n|\\r|^)(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|([^\"\\,\\r\\n]*))/gi\n\ncsv.toArrays(\"a,b,c\")\n//│ = [[\"a\", \"b\", \"c\"]]\n\ncsv.toArrays(\"a,b,c\\n1,2,3\\n4,5,6\")\n//│ = [[\"a\", \"b\", \"c\"], [\"1\", \"2\", \"3\"], [\"4\", \"5\", \"6\"]]\n\ncsv.toArrays(\"a,b,c\\n\\n1,2,3\\n4,5,6\\n\")\n//│ = [[\"a\", \"b\", \"c\"], [\"\"], [\"1\", \"2\", \"3\"], [\"4\", \"5\", \"6\"], [\"\"]]\n\ncsv.toArrays(\",\")\n//│ = [[\"\"]]\n\ncsv.toArrays(\",,\")\n//│ = [[\"\", \"\"]]\n\ncsv.toArrays(\"1,\\\"2\\\"\")\n//│ = [[\"1\", \"2\"]]\n\ncsv.toArrays(\"1,\\\"2,3\\\",4\")\n//│ = [[\"1\", \"2,3\", \"4\"]]\n\ncsv.toArrays(\"1,\\\"\\\",4\")\n//│ = [[\"1\", \"\", \"4\"]]\n\ncsv.toArrays(\"1,\\\",4\")\n//│ = [[\"1\", \"\", \"4\"]]\n\ncsv.toArrays(\"1,\\\",4\\\"\")\n//│ = [[\"1\", \",4\"]]\n\n\n// We would probably rather expect \"A\\\\\\\"B\", here\ncsv.toArrays(\"1,\\\"A\\\\\\\"B\\\",4\").0.1\n//│ = \"A\\\\\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/IterTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Iter.mls\"\nimport \"../../mlscript-compile/Stack.mls\"\nimport \"../../mlscript-compile/MutMap.mls\"\n\nopen Iter\nopen Stack { Cons, Nil }\n\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n  filtering of x => x % 2 is 0\n  mapping of x => x * 2\n  toArray()\n//│ = [4, 8, 12, 16, 20]\n\n([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n  filtering of x => x % 2 is 0\n  folded of \"[\", (x, y) => if x is \"[\" then x + y else x + \", \" + y) + \"]\"\n//│ = \"[2, 4, 6, 8, 10]\"\n\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n  filtering of x => x % 2 is 1\n  rightFolded of Nil, Cons\n//│ = Cons(1, Cons(3, Cons(5, Cons(7, Cons(9, Nil)))))\n\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n  filtering of x => x % 2 is 0\n  reduced of (x, y) => x + y\n//│ = 30\n\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n  filtering of x => x % 2 is 0\n  folded of 1, *\n//│ = 3840\n\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n  leaving(2)\n  taking(5)\n  toArray()\n//│ = [3, 4, 5, 6, 7]\n\n[\"foo\", \"bar\", \"baz\"]\n  zippingWithIndex()\n  toArray()\n//│ = [[\"foo\", 0], [\"bar\", 1], [\"baz\", 2]]\n\n[\"foo\", \"bar\", \"baz\"]\n  zippingWithIndex()\n  mapping of case [x, y] then [y, x]\n  toArray()\n//│ = [[0, \"foo\"], [1, \"bar\"], [2, \"baz\"]]\n\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] joined(\" <> \")\n//│ = \"1 <> 2 <> 3 <> 4 <> 5 <> 6 <> 7 <> 8 <> 9 <> 10\"\n\n[\"foo\", \"bar\", \"\", \"\", \"baz\"]\n  flattening()\n  toArray()\n//│ = [\"f\", \"o\", \"o\", \"b\", \"a\", \"r\", \"b\", \"a\", \"z\"]\n\n[\"\", \"foo\", \"\", \"bar\", \"\", \"\", \"baz\"]\n  mapping of str => Array.from(str).reverse()\n  flattening()\n  toArray()\n//│ = [\"o\", \"o\", \"f\", \"r\", \"a\", \"b\", \"z\", \"a\", \"b\"]\n\n[\"\", \"\", \"\", \"\", \"\"]\n  flattening()\n  toArray()\n//│ = []\n\n[\"foo\", \"bar\", [], [\"qax\"], \"\", \"baz\"]\n  flattening()\n  toArray()\n//│ = [\"f\", \"o\", \"o\", \"b\", \"a\", \"r\", \"qax\", \"b\", \"a\", \"z\"]\n\n[1, 3, 5, 7, 9]\n  mapping of x => x * 2\n  appended of [2, 4, 6, 8, 10]\n  mapping of x => x / 2\n  toArray()\n//│ = [1, 3, 5, 7, 9, 1, 2, 3, 4, 5]\n\n[7, 8, 9, 10]\n  filtering of x => x % 2 is 0\n  mapping of x => x * 2\n  appended of []\n  toArray()\n//│ = [16, 20]\n\n[[\"foo\", 1]]\n  MutMap.toMap()\n  mapping of case [k, v] then [k + \"!\", v * 2]\n  appended of MutMap.toMap([[\"bar\", 2]])\n  toArray()\n//│ = [[\"foo!\", 2], [\"bar\", 2]]\n\n[1, 2, 3, 4, 5, 6]\n  Iter.some of x => x % 3 == 0\n//│ = true\n\n[1, 2, 3, 4, 5, 6]\n  Iter.some of x => x % 9 == 0\n//│ = false\n\n[1, 2, 3, 4, 5, 6]\n  Iter.every of x => x % 2 == 0\n//│ = false\n\n[1, 2, 3, 4, 5, 6]\n  Iter.mapping of x => x * 2\n  Iter.every of x => x % 2 == 0\n//│ = true\n\n[1, 2, -3, 4, 5, 6]\n  Iter.mapping of x => () => print(x + \" was accessed\"); x\n  Iter.some of get => get() < 0\n//│ > 1 was accessed\n//│ > 2 was accessed\n//│ > -3 was accessed\n//│ = true\n\n[1, 2, 3, -4, 5, 6]\n  Iter.mapping of x => () => print(x + \" was accessed\"); x\n  Iter.every of get => get() > 0\n//│ > 1 was accessed\n//│ > 2 was accessed\n//│ > 3 was accessed\n//│ > -4 was accessed\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/.gitignore",
    "content": "rule.html\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/CamlLightTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\n\nopen Test { example }\n\n//   ____      _             __        ___               _ \n//  / ___|___ | | ___  _ __  \\ \\      / / |__   ___  ___| |\n// | |   / _ \\| |/ _ \\| '__|  \\ \\ /\\ / /| '_ \\ / _ \\/ _ \\ |\n// | |__| (_) | | (_) | |      \\ V  V / | | | |  __/  __/ |\n//  \\____\\___/|_|\\___/|_|       \\_/\\_/  |_| |_|\\___|\\___|_|\n//                                                         \n\n// sources/examples/colwheel/colwheel.ml\n// =====================================\n\n// Note: We do not support or patterns for now, so I expanded the or patterns.\n\nexample of \"\"\"\nlet max = 255;;\nlet nround x y = (2*x+y)/(2*y);;\nlet rgb_of_hsb h s v =\n  let h = h*6 in\n  let i = h/max*max in\n  let f = h-i in\n  let m = v*(max-s)/max and n = v*(max-s*f/max)/max\n  and k = v*(max-s*(max-f)/max)/max in\n  graphics__rgb\n    (nround (max*(\n      match i/max with\n      | 0 -> v | 6 -> v | 1 -> n | 2 -> m | 3 -> m | 4 -> k | _ -> v\n    )) max)\n    (nround (max*(\n      match i/max with\n      | 0 -> k | 6 -> k | 1 -> v | 2 -> v | 3 -> n | 4 -> m | _ -> m\n    )) max)\n    (nround (max*(\n      match i/max with\n      | 0 -> m | 6 -> m | 1 -> m | 2 -> k | 3 -> v | 4 -> v | _ -> n\n    )) max)\n;;\nlet pi180 = 3.141592654 /. 180.0;;\nlet wheel s v r =\n  for theta = 0 to 23 do\n    set_color (rgb_of_hsb (theta * max / 24) s v);\n    fill_arc (size_x()/2) (size_y()/2) r r (theta * 15) (theta * 15 + 15)\n  done\n;;\nlet wheels v =\n  for r = 8 downto 1 do\n    wheel (r * max / 8) v (r * (size_y()/20))\n  done\n;;\nlet main() =\n  open_graph \"\";\n  let (msg_w, msg_h) = text_size \"Press 'q' to quit    R=999 G=999 B=999\" in\n  try\n    wheels max;\n    set_color foreground;\n    moveto 0 0; draw_string \"Press 'q' to quit\";\n    while true do\n      let e = wait_next_event [Button_down; Key_pressed] in\n        if e.keypressed then begin\n          match e.key with\n          | \"0\" ->\n              clear_graph();\n              wheels ((int_of_char e.key - 48) * max / 9)\n          | \"q\" ->\n              raise Exit\n          | _ ->\n              ()\n        end else\n        if e.button then begin\n          let c = point_color e.mouse_x e.mouse_y in\n          let r = c lsr 16 and g = (c lsr 8) land 255 and b = c land 255 in\n            set_color background;\n            fill_rect 0 0 msg_w msg_h;\n            set_color foreground;\n            moveto 0 0;\n            draw_string (\"Press 'q' to quit    R=\" ^ string_of_int r ^\n                         \" G=\" ^ string_of_int g ^ \" B=\" ^ string_of_int b)\n        end\n    done\n  with Exit ->\n    close_graph()\n;;\nif sys__interactive then () else begin main(); exit 0 end;;\n\"\"\"\n//│ > «let max = 255»\n//│ > «let nround x y = 2 * x + y / 2 * y»\n//│ > «let rgb_of_hsb h s v = let h = h * 6 in let i = h / max * max in let f = h - i in let m = v * (max - s) / max and n = v * (max - s * f / max) / max and k = v * (max - s * (max - f) / max) / max in graphics__rgb (nround (max * (match i / max with 0 -> v | 6 -> v | 1 -> n | 2 -> m | 3 -> m | 4 -> k | _ -> v)) max) (nround (max * (match i / max with 0 -> k | 6 -> k | 1 -> v | 2 -> v | 3 -> n | 4 -> m | _ -> m)) max) (nround (max * (match i / max with 0 -> m | 6 -> m | 1 -> m | 2 -> k | 3 -> v | 4 -> v | _ -> n)) max)»\n//│ > «let pi180 = 3.141592654 /. 180.0»\n//│ > «let wheel s v r = for theta = 0 to 23 do set_color (rgb_of_hsb (theta * max / 24) s v); fill_arc (size_x () / 2) (size_y () / 2) r r (theta * 15) (theta * 15 + 15) done»\n//│ > «let wheels v = for r = 8 to 1 do wheel (r * max / 8) v (r * (size_y () / 20)) done»\n//│ > «let main () = open_graph \"\"; let (msg_w, msg_h) = text_size \"Press…\" in try wheels max; set_color foreground; moveto 0 0; draw_string \"Press…\"; while true do let e = wait_next_event [Button_down; Key_pressed] in if e.keypressed then match e.key with \"0\" -> clear_graph (); wheels ((int_of_char e.key - 48) * max / 9) | \"q\" -> raise Exit | _ -> () then if e.button then let c = point_color e.mouse_x e.mouse_y in let r = c lsr 16 and g = c lsr 8 land 255 and b = c land 255 in set_color background; fill_rect 0 0 msg_w msg_h; set_color foreground; moveto 0 0; draw_string (\"Press…\" ^ string_of_int r ^ \" G=\" ^ string_of_int g ^ \" B=\" ^ string_of_int b) then None done»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «if sys__interactive then () then main (); exit 0»\n\n//  _   _                   _ \n// | | | | __ _ _ __   ___ (_)\n// | |_| |/ _` | '_ \\ / _ \\| |\n// |  _  | (_| | | | | (_) | |\n// |_| |_|\\__,_|_| |_|\\___/|_|\n//                            \n\n// sources/examples/hanoi/hanoi.ml\n// ===============================\n\n// The original example is too long and would cause the lexer to overflow,\n// so we will temporarily split it into three parts for parsing.\n\nexample of \"\"\"\nlet spaces n = make_string n \" \";;\nlet disk size =\n    let right_half = make_string size \">\"\n    and left_half = make_string size \"<\"\n    in left_half ^ \"|\" ^ right_half;;\nlet disk_number n largest_disk_size =\n    let white_part = spaces (largest_disk_size + 1 - n) in\n    white_part ^ (disk n) ^ white_part;;\nlet peg_base largest_disk_size =\n    let half = make_string largest_disk_size \"_\" in\n    \" \" ^ half ^ \"|\" ^ half ^ \" \";;\nlet rec peg largest_disk_size = function\n  | (0, []) -> []\n  | (0, head::rest) ->\n      disk_number head largest_disk_size ::\n      peg largest_disk_size (0, rest)\n  | (offset, lst) ->\n      disk_number 0 largest_disk_size ::\n      peg largest_disk_size (offset-1, lst);;\nlet rec join_lines l1 l2 l3 =\n  match (l1, l2, l3) with\n  | ([], [], []) -> []\n  | (t1::r1, t2::r2, t3::r3) -> (t1 ^ t2 ^ t3) :: join_lines r1 r2 r3\n  | _ -> failwith \"join_lines\";;\nlet print_line line = print_string line; print_newline();;\nlet print_game num_disks start middle end_ =\n    let drawing =\n        join_lines (peg num_disks start)\n                   (peg num_disks middle)\n                   (peg num_disks end_) in\n    do_list print_line drawing;\n    let b = peg_base num_disks in print_line (b ^ b ^ b);;\nlet add_disk disk (offset, disks) =\n    (offset - 1, disk::disks);;\nlet top = function\n  | (offset, top :: rest) -> top\n  | (offset, []) -> failwith \"top: empty peg\";;\nlet remove_top = function\n  | (offset, top :: rest) -> (offset + 1, rest)\n  | (offset, []) -> failwith \"remove_top: empty peg\";;\nlet move (name_start, peg_start) (name_finish, peg_finish) =\n    print_line (\"I move a disk from \" ^\n                name_start ^ \" to \" ^ name_finish);\n    let moved_disk = top !peg_start in\n    peg_start := remove_top !peg_start;\n    peg_finish := add_disk moved_disk !peg_finish;;\nlet empty_peg num_disks = (num_disks, []);;\nlet full_peg num_disks =\n    let rec list_of_disks i =\n        if i <= num_disks\n        then i :: list_of_disks (i+1)\n        else [] in\n    (0, list_of_disks 1);;\nlet game num_disks =\n    let left = ref (full_peg num_disks)\n    and middle = ref (empty_peg num_disks)\n    and right = ref (empty_peg num_disks) in\n    let rec hanoi height start_ intermediate destination =\n        if height > 0 then\n         begin\n           hanoi (height - 1) start_ destination intermediate;\n           move start_ destination;\n           print_game num_disks !left !middle !right;\n           hanoi (height - 1) intermediate start_ destination\n         end in\n    print_line \"I name the pegs A, B, and C.\";\n    print_line \"Starting position:\";\n    print_game num_disks !left !middle !right;\n    hanoi num_disks (\"A\", left) (\"B\", middle) (\"C\", right);;\nif sys__interactive then () else begin\n  game (int_of_string (sys__command_line.(1)));\n  exit 0\nend;;\n\"\"\"\n//│ > «let spaces n = make_string n \" \"»\n//│ > «let disk size = let right_half = make_string size \">\" and left_half = make_string size \"<\" in left_half ^ \"|\" ^ right_half»\n//│ > «let disk_number n largest_disk_size = let white_part = spaces (largest_disk_size + 1 - n) in white_part ^ disk n ^ white_part»\n//│ > «let peg_base largest_disk_size = let half = make_string largest_disk_size \"_\" in \" \" ^ half ^ \"|\" ^ half ^ \" \"»\n//│ > «let peg largest_disk_size = function (0, []) -> [] | (0, head :: rest) -> disk_number head largest_disk_size :: peg largest_disk_size (0, rest) | (offset, lst) -> disk_number 0 largest_disk_size :: peg largest_disk_size (offset - 1, lst)»\n//│ > «let join_lines l1 l2 l3 = match (l1, l2, l3) with ([], [], []) -> [] | (t1 :: r1, t2 :: r2, t3 :: r3) -> t1 ^ t2 ^ t3 :: join_lines r1 r2 r3 | _ -> failwith \"join_…\"»\n//│ > «let print_line line = print_string line; print_newline ()»\n//│ > «let print_game num_disks start middle end_ = let drawing = join_lines (peg num_disks start) (peg num_disks middle) (peg num_disks end_) in do_list print_line drawing; let b = peg_base num_disks in print_line (b ^ b ^ b)»\n//│ > «let add_disk disk (offset, disks) = (offset - 1, disk :: disks)»\n//│ > «let top = function (offset, top :: rest) -> top | (offset, []) -> failwith \"top: …\"»\n//│ > «let remove_top = function (offset, top :: rest) -> (offset + 1, rest) | (offset, []) -> failwith \"remov…\"»\n//│ > «let move (name_start, peg_start) (name_finish, peg_finish) = print_line (\"I mov…\" ^ name_start ^ \" to \" ^ name_finish); let moved_disk = top ! peg_start in peg_start := remove_top ! peg_start; peg_finish := add_disk moved_disk ! peg_finish»\n//│ > «let empty_peg num_disks = (num_disks, [])»\n//│ > «let full_peg num_disks = let list_of_disks i = if i <= num_disks then i :: list_of_disks (i + 1) then [] in (0, list_of_disks 1)»\n//│ > «let game num_disks = let left = ref (full_peg num_disks) and middle = ref (empty_peg num_disks) and right = ref (empty_peg num_disks) in let hanoi height start_ intermediate destination = if height > 0 then hanoi (height - 1) start_ destination intermediate; move start_ destination; print_game num_disks ! left ! middle ! right; hanoi (height - 1) intermediate start_ destination then None in print_line \"I nam…\"; print_line \"Start…\"; print_game num_disks ! left ! middle ! right; hanoi num_disks (\"A\", left) (\"B\", middle) (\"C\", right)»\n//│ > «if sys__interactive then () then game (int_of_string sys__command_line . 1); exit 0»\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/DirectiveTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/MutMap.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\n\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Rules.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Keywords.mls\"\n\nopen Test { example }\n\nexample of \"\"\"\n#open \"hello\";;\n  \nlet f x = x + 1;;\n  \nlet g x = x * 2;;\n\"\"\"\n//│ > «#open \"hello\"»\n//│ > «let f x = x + 1»\n//│ > «let g x = x * 2»\n\nexample of \"\"\"\n#newKeyword (\"hello\", None, None)\n#newKeyword (\"world\", Some 34, None)\n\"\"\"\n//│ > \n\nprint of Keywords.extended |> MutMap.valuesIterator |. Iter.joined(\"\\n\")\n//│ > Keyword(`hello`, N/A, N/A)\n//│ > Keyword(`world`, 34, N/A)\n\nexample of \"\"\"\n#newCategory \"lol\"\n\"\"\"\n//│ > \n\nexample of \"\"\"\n#extendCategory \"lol\", [ keyword(\"hello\"), \"lol\" ], foo\n#extendCategory \"lol\", [ keyword(\"world\") ], bar\n#extendCategory \"term\", [ \"lol\" ], baz\n\"\"\"\n//│ > \n\nRules.getRuleByKind(\"lol\").display print()\n//│ > <lol> ::= \n//│ >   | \"hello\" <lol>\n//│ >   | \"world\"\n\nRules.getRuleByKind(\"term\").display print()\n//│ > <prefix rules for expressions> ::= \n//│ >   | \"let\" [\"rec\"] <let-bindings> [\"in\" <term>]\n//│ >   | \"fun\" <term> \"->\" <term>\n//│ >   | \"match\" <term> \"with\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"function\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"if\" <term> \"then\" <term> [\"else\" <term>]\n//│ >   | \"while\" <term> \"do\" <term> \"done\"\n//│ >   | \"for\" <term> \"=\" <term> (\"to\" | \"downto\") <term> \"do\" <term> \"done\"\n//│ >   | \"(\" <term> \")\"\n//│ >   | \"[\" <term> \"]\"\n//│ >   | \"{\" <term> \"}\"\n//│ >   | \"begin\" <term> \"end\"\n//│ >   | <term> (\",\" <term> | \";\" <term> | \"<-\" <term> | \"==\" <term> | \"*\" <term> | \".\" (\"(\" <term> \")\" | <term>) | \":\" <type> | <term>)\n//│ >   | \"hello\" <lol>\n//│ >   | \"world\"\n\nexample of \"\"\"\nhello world\n\"\"\"\n//│ > «{}»\n//│ > «⚠»\n//│ > «⚠»\n\nexample of \"\"\"\n#newKeyword (\"assert\", None, None)\n#newCategory \"assert\"\n#extendCategory \"assert\", [ keyword \"assert\", \"term\" ], do_assert\n  \nassert 0\n\"\"\"\n//│ > «⚠»\n//│ > «⚠»\n\nexample of \"\"\"\n#newKeyword (\"hello\", Some 3, Some 3)\n#newKeyword (\"goodbye\", None, None)\n  \n#newCategory(\"greeting\")\n  \n#extendCategory(\"greeting\", [ keyword(\"hello\"), \"term\", \"greeting\" ], foo)\n#extendCategory(\"greeting\", [ keyword(\"goodbye\") ], bar)\n  \n#extendCategory(\"decl\", [ \"greeting\" ], baz)\n  \n  \nhello \"Rob\" hello \"Bob\" goodbye\n  \n#diagram \"\"\n\"\"\"\n//│ > «baz (foo \"Rob\" (foo \"Bob\" bar))»\n//│ > «#diagram \"\"»\n\nRules.getRuleByKind(\"term\").display print()\n//│ > <prefix rules for expressions> ::= \n//│ >   | \"let\" [\"rec\"] <let-bindings> [\"in\" <term>]\n//│ >   | \"fun\" <term> \"->\" <term>\n//│ >   | \"match\" <term> \"with\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"function\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"if\" <term> \"then\" <term> [\"else\" <term>]\n//│ >   | \"while\" <term> \"do\" <term> \"done\"\n//│ >   | \"for\" <term> \"=\" <term> (\"to\" | \"downto\") <term> \"do\" <term> \"done\"\n//│ >   | \"(\" <term> \")\"\n//│ >   | \"[\" <term> \"]\"\n//│ >   | \"{\" <term> \"}\"\n//│ >   | \"begin\" <term> \"end\"\n//│ >   | <term> (\",\" <term> | \";\" <term> | \"<-\" <term> | \"==\" <term> | \"*\" <term> | \".\" (\"(\" <term> \")\" | <term>) | \":\" <type> | <term>)\n//│ >   | \"hello\" <lol>\n//│ >   | \"world\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/LeftRecursion.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/MutMap.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\n\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Rules.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Keywords.mls\"\n\nopen Test { example }\n\nexample of \"\"\"\n#newKeyword (\"count\", Some 5, Some 5)\n#newKeyword (\"base\", None, None)\n#newKeyword (\"incr\", None, None)\n\"\"\"\n//│ > \n\nprint of Keywords.extended |> MutMap.valuesIterator |. Iter.joined(\"\\n\")\n//│ > Keyword(`count`, 5, 5)\n//│ > Keyword(`base`, N/A, N/A)\n//│ > Keyword(`incr`, N/A, N/A)\n\nexample of \"\"\"\n#newCategory \"counting\"\n\"\"\"\n//│ > \n\n// <counting> ::= <counting> \"incr\" | \"base\"\nexample of \"\"\"\n#extendCategory \"counting\", [ \"counting\", keyword(\"incr\") ], succ\n#extendCategory \"counting\", [ keyword(\"base\") ], zero\n#extendCategory \"term\", [ keyword(\"count\"), \"counting\" ], result\n\"\"\"\n//│ > \n\nRules.getRuleByKind(\"counting\").display print()\n//│ > <counting> ::= \n//│ >   | <counting> \"incr\"\n//│ >   | \"base\"\n\nexample of \"\"\"count base\"\"\"\n//│ > «result zero»\n\nexample of \"\"\"count base incr incr\"\"\"\n//│ > «result (succ (succ zero))»\n\nRules.getRuleByKind(\"term\").display print()\n//│ > <prefix rules for expressions> ::= \n//│ >   | \"let\" [\"rec\"] <let-bindings> [\"in\" <term>]\n//│ >   | \"fun\" <term> \"->\" <term>\n//│ >   | \"match\" <term> \"with\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"function\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"if\" <term> \"then\" <term> [\"else\" <term>]\n//│ >   | \"while\" <term> \"do\" <term> \"done\"\n//│ >   | \"for\" <term> \"=\" <term> (\"to\" | \"downto\") <term> \"do\" <term> \"done\"\n//│ >   | \"(\" <term> \")\"\n//│ >   | \"[\" <term> \"]\"\n//│ >   | \"{\" <term> \"}\"\n//│ >   | \"begin\" <term> \"end\"\n//│ >   | <term> (\",\" <term> | \";\" <term> | \"<-\" <term> | \"==\" <term> | \"*\" <term> | \".\" (\"(\" <term> \")\" | <term>) | \":\" <type> | <term>)\n//│ >   | \"count\" <counting>\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/LexerTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/Lexer.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Token.mls\"\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\n\nfun lines(...strs) = strs.join(\"\\n\")\n\nopen Lexer { lex }\nopen Stack\n\nfun printLexed(text) = print of\n  lex(text, false)\n    Iter.fromStack()\n    Iter.mapping of Token.display\n    Iter.joined of \"\\n\"\n\nprintLexed of \"0 1  0xDEADCAFE 0b1101 0o755     3.1415926535\"\n//│ > integer \"0\" at 1:1-1:2\n//│ > space at 1:2-1:3\n//│ > integer \"1\" at 1:3-1:4\n//│ > space at 1:4-1:6\n//│ > integer \"0xDEADCAFE\" at 1:1-1:7\n//│ > space at 1:16-1:17\n//│ > integer \"0b1101\" at 1:12-1:18\n//│ > space at 1:23-1:24\n//│ > integer \"0o755\" at 1:20-1:25\n//│ > space at 1:29-1:34\n//│ > decimal \"3.1415926535\" at 1:23-1:35\n\n// Good strings.\nprintLexed of \"\"\"\n\"hello, world\"\n\"\\x48\\x65\\x6C\\x6C\\x6F\\x2C\\x20\\x77\\x6F\\x72\\x6C\\x64\"\n\"\\u0048\\u0065\\u006C\\u006C\\u006F\\u002C\\u0020\\u0077\\u006F\\u0072\\u006C\\u0064\"\n\"\\u{48}\\u{65}\\u{6C}\\u{6C}\\u{6F}\\u{2C}\\u{20}\\u{77}\\u{6F}\\u{72}\\u{6C}\\u{64}\"\n\"\\u{1F600}\" // 😀\n\"\\u{1F601}\" // 😁\n\"\\u{1F602}\" // 😂\n\"\\u{1F603}\" // 😃\n\"\\u{1F604}\" // 😄\n\"\\n\\r\\t\\b\"\n\"\"\"\n//│ > space at 1:1-2:1\n//│ > string \"hello, world\" at 2:2-2:15\n//│ > space at 2:15-3:1\n//│ > string \"Hello, world\" at 3:2-3:51\n//│ > space at 3:51-4:1\n//│ > string \"Hello, world\" at 4:2-4:75\n//│ > space at 4:75-5:1\n//│ > string \"Hello, world\" at 5:2-5:75\n//│ > space at 5:75-6:1\n//│ > string \"😀\" at 6:2-6:12\n//│ > space at 6:12-6:13\n//│ > comment at 6:14-6:18\n//│ > space at 6:18-7:1\n//│ > string \"😁\" at 7:2-7:12\n//│ > space at 7:12-7:13\n//│ > comment at 7:14-7:18\n//│ > space at 7:18-8:1\n//│ > string \"😂\" at 8:2-8:12\n//│ > space at 8:12-8:13\n//│ > comment at 8:14-8:18\n//│ > space at 8:18-9:1\n//│ > string \"😃\" at 9:2-9:12\n//│ > space at 9:12-9:13\n//│ > comment at 9:14-9:18\n//│ > space at 9:18-10:1\n//│ > string \"😄\" at 10:2-10:12\n//│ > space at 10:12-10:13\n//│ > comment at 10:14-10:18\n//│ > space at 10:18-11:1\n//│ > string \"\\n\\r\\t\\b\" at 11:2-11:11\n//│ > space at 11:11-12:1\n\n// Ill-formed Strings\n// ==================\n\nprintLexed of \"\"\"\n\"hello, world.   \"\"\"\n//│ > space at 1:1-2:1\n//│ > string \"hello, world.   \" at 2:2-2:18\n\nprintLexed of \"\"\"\n\"hello, \\world\"\"\"\n//│ > space at 1:1-2:1\n//│ > string \"hello, world\" at 2:2-2:15\n\nprintLexed of \"\"\"let v' =\n  let a, b = (1, 2) in a + b\"\"\"\n//│ > identifier `let` at 1:1-1:4\n//│ > space at 1:4-1:5\n//│ > identifier `v'` at 1:5-1:7\n//│ > space at 1:7-1:8\n//│ > identifier `=` at 1:8-1:9\n//│ > space at 1:9-2:3\n//│ > identifier `let` at 2:3-2:6\n//│ > space at 2:6-2:7\n//│ > identifier `a` at 2:7-2:8\n//│ > identifier `,` at 2:8-2:9\n//│ > space at 2:9-2:10\n//│ > identifier `b` at 2:10-2:11\n//│ > space at 2:11-2:12\n//│ > identifier `=` at 2:12-2:13\n//│ > space at 2:13-2:14\n//│ > identifier `(` at 2:13-2:14\n//│ > integer \"1\" at 2:15-2:16\n//│ > identifier `,` at 2:16-2:17\n//│ > space at 2:17-2:18\n//│ > integer \"2\" at 2:18-2:19\n//│ > identifier `)` at 2:18-2:19\n//│ > space at 2:20-2:21\n//│ > identifier `in` at 2:21-2:23\n//│ > space at 2:23-2:24\n//│ > identifier `a` at 2:24-2:25\n//│ > space at 2:25-2:26\n//│ > identifier `+` at 2:26-2:27\n//│ > space at 2:27-2:28\n//│ > identifier `b` at 2:28-2:29\n\nprintLexed of lines of\n  \"let rec factorial x = // a simple factorial function\"\n  \"  if x <= 1 then 1 else x * factorial (x - 1)\"\n  \"\"\n  \"let bool_of_string = function\"\n  \"  | \\\"true\\\" -> true\"\n  \"  | \\\"false\\\" -> false\"\n  \"  | _ -> raise (Invalid_argument \\\"bool_of_string\\\")\"\n//│ > identifier `let` at 1:1-1:4\n//│ > space at 1:4-1:5\n//│ > identifier `rec` at 1:5-1:8\n//│ > space at 1:8-1:9\n//│ > identifier `factorial` at 1:9-1:18\n//│ > space at 1:18-1:19\n//│ > identifier `x` at 1:19-1:20\n//│ > space at 1:20-1:21\n//│ > identifier `=` at 1:21-1:22\n//│ > space at 1:22-1:23\n//│ > comment at 1:24-1:53\n//│ > space at 1:53-2:3\n//│ > identifier `if` at 2:3-2:5\n//│ > space at 2:5-2:6\n//│ > identifier `x` at 2:6-2:7\n//│ > space at 2:7-2:8\n//│ > identifier `<=` at 2:8-2:10\n//│ > space at 2:10-2:11\n//│ > integer \"1\" at 2:11-2:12\n//│ > space at 2:12-2:13\n//│ > identifier `then` at 2:13-2:17\n//│ > space at 2:17-2:18\n//│ > integer \"1\" at 2:18-2:19\n//│ > space at 2:19-2:20\n//│ > identifier `else` at 2:20-2:24\n//│ > space at 2:24-2:25\n//│ > identifier `x` at 2:25-2:26\n//│ > space at 2:26-2:27\n//│ > identifier `*` at 2:27-2:28\n//│ > space at 2:28-2:29\n//│ > identifier `factorial` at 2:29-2:38\n//│ > space at 2:38-2:39\n//│ > identifier `(` at 2:38-2:39\n//│ > identifier `x` at 2:40-2:41\n//│ > space at 2:41-2:42\n//│ > identifier `-` at 2:42-2:43\n//│ > space at 2:43-2:44\n//│ > integer \"1\" at 2:44-2:45\n//│ > identifier `)` at 2:44-2:45\n//│ > space at 2:46-4:1\n//│ > identifier `let` at 4:1-4:4\n//│ > space at 4:4-4:5\n//│ > identifier `bool_of_string` at 4:5-4:19\n//│ > space at 4:19-4:20\n//│ > identifier `=` at 4:20-4:21\n//│ > space at 4:21-4:22\n//│ > identifier `function` at 4:22-4:30\n//│ > space at 4:30-5:3\n//│ > identifier `|` at 5:3-5:4\n//│ > space at 5:4-5:5\n//│ > string \"true\" at 5:6-5:11\n//│ > space at 5:11-5:12\n//│ > identifier `->` at 5:12-5:14\n//│ > space at 5:14-5:15\n//│ > boolean \"true\" at 5:15-5:19\n//│ > space at 5:19-6:3\n//│ > identifier `|` at 6:3-6:4\n//│ > space at 6:4-6:5\n//│ > string \"false\" at 6:6-6:12\n//│ > space at 6:12-6:13\n//│ > identifier `->` at 6:13-6:15\n//│ > space at 6:15-6:16\n//│ > boolean \"false\" at 6:16-6:21\n//│ > space at 6:21-7:3\n//│ > identifier `|` at 7:3-7:4\n//│ > space at 7:4-7:5\n//│ > identifier `_` at 7:5-7:6\n//│ > space at 7:6-7:7\n//│ > identifier `->` at 7:7-7:9\n//│ > space at 7:9-7:10\n//│ > identifier `raise` at 7:10-7:15\n//│ > space at 7:15-7:16\n//│ > identifier `(` at 7:15-7:16\n//│ > identifier `Invalid_argument` at 7:17-7:33\n//│ > space at 7:33-7:34\n//│ > string \"bool_of_string\" at 7:35-7:50\n//│ > identifier `)` at 7:49-7:50\n\n// It turns out that OCaml identifiers' apostrophes are not limited to the end.\nprintLexed of \"a'b\"\nprintLexed of \"'a\"\n//│ > identifier `a'b` at 1:1-1:4\n//│ > identifier `'a` at 1:1-1:1\n\nprintLexed of \"[< ] < .. ... >\"\n//│ > identifier `[` at 1:1-1:1\n//│ > identifier `<` at 1:2-1:3\n//│ > space at 1:3-1:4\n//│ > identifier `]` at 1:3-1:4\n//│ > space at 1:5-1:6\n//│ > identifier `<` at 1:6-1:7\n//│ > space at 1:7-1:8\n//│ > identifier `..` at 1:8-1:10\n//│ > space at 1:10-1:11\n//│ > identifier `...` at 1:11-1:14\n//│ > space at 1:14-1:15\n//│ > identifier `>` at 1:15-1:16\n\nprintLexed of \"`a `b _\"\n//│ > identifier ``a` at 1:1-1:1\n//│ > space at 1:3-1:4\n//│ > identifier ``b` at 1:2-1:4\n//│ > space at 1:6-1:7\n//│ > identifier `_` at 1:7-1:8\n\n:e\n// It would be decent if we allow pattern parameters in functions.\nfun take(pattern P, idx: Str, acc: Str) =\n  while idx < str.length and str.charAt(idx) is ch and ch is P\n    then\n      set idx = idx + 1\n      set acc = acc + ch\n    else [acc, idx]\n//│ ╔══[COMPILATION ERROR] Name not found: str\n//│ ║  l.238: \t  while idx < str.length and str.charAt(idx) is ch and ch is P\n//│ ╙──       \t              ^^^\n//│ ╔══[COMPILATION ERROR] Name not found: str\n//│ ║  l.238: \t  while idx < str.length and str.charAt(idx) is ch and ch is P\n//│ ╙──       \t                             ^^^\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/LoopExpressions.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\n\nopen Test { example }\n\nexample of \"\"\"\n:tree\nlet x = 0 in\nwhile x < 10 do\n  print_int x;\n  print_newline ();\n  x <- x + 1\ndone\n\"\"\"\n//│ > LetIn:\n//│ >   bindings = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Ident of \"x\"\n//│ >       rhs = Literal#Integer of \"0\"\n//│ >   body = Some of While:\n//│ >     condition = App:\n//│ >       callee = Ident of \"<\"\n//│ >       argument = Stack of \n//│ >         Ident of \"x\"\n//│ >         Literal#Integer of \"10\"\n//│ >     body = Sequence of Stack of \n//│ >       App:\n//│ >         callee = Ident of \"print_int\"\n//│ >         argument = Ident of \"x\"\n//│ >       App:\n//│ >         callee = Ident of \"print_newline\"\n//│ >         argument = Tuple of Nil\n//│ >       Infix:\n//│ >         op = Keyword(`<-`, 9, 9)\n//│ >         lhs = Ident of \"x\"\n//│ >         rhs = App:\n//│ >           callee = Ident of \"+\"\n//│ >           argument = Stack of \n//│ >             Ident of \"x\"\n//│ >             Literal#Integer of \"1\"\n//│ > «let x = 0 in while x < 10 do print_int x; print_newline (); x <- x + 1 done»\n\nexample of \"\"\"\n:tree\nfor i = 0 to 10 do\n  print i\ndone\n\"\"\"\n//│ > For:\n//│ >   head = Ident of \"i\"\n//│ >   start = Literal#Integer of \"0\"\n//│ >   end = Literal#Integer of \"10\"\n//│ >   body = App:\n//│ >     callee = Ident of \"print\"\n//│ >     argument = Ident of \"i\"\n//│ > «for i = 0 to 10 do print i done»\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/ParseRuleVisualizerTest.mls",
    "content": ":js\n\n:silent\nimport \"../../../mlscript-compile/apps/parsing/Parser.mls\"\nimport \"../../../mlscript-compile/apps/parsing/ParseRuleVisualizer.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Rules.mls\"\nimport \"../../../mlscript-compile/apps/parsing/vendors/railroad/railroad.mjs\"\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/XML.mls\"\nimport \"path\"\n\nopen ParseRuleVisualizer { render }\nopen Rules { termRule, declRule, typeRule }\nopen XML { html, tag, elem, style }\n\n// Check if the given path exists.\nfun ensurePath(pathString) =\n  if fs.statSync(pathString).isDirectory() is false do\n    throw Error(\"The output directory does not exist.\")\n  pathString\n\n// `process.cwd()` is different in `hkmc2AllTests / test` and\n// `~hkmc2DiffTests / Test / run`. This is a workaround to make the path.\nfun findProjectRoot =\n  let base = process.cwd()\n  let fragments = base.split(path.sep)\n  if fragments.at(-1) is \"shared\" and fragments.at(-2) is \"hkmc2\" then\n    base\n  else\n    base + path.sep + \"hkmc2\" + path.sep + \"shared\"\n\nfun outputPath = ensurePath of path.resolve of\n  findProjectRoot, \"src\", \"test\", \"mlscript\", \"apps\", \"parsing\"\n\nfun filePath(...fragments) = path.join(outputPath, ...fragments)\n\nfun libraryPath = ensurePath of path.resolve of\n  findProjectRoot, \"src\", \"test\", \"mlscript-compile\", \"apps\", \"parsing\", \"vendors\", \"railroad\"\n\nfun loadRailroadStylesheet = fs.readFileSync of path.join(libraryPath, \"railroad.css\"), \"utf-8\"\n\nfun toHTML(...elements) = html(lang: \"en\") of\n  elem(\"head\") of\n    tag(\"meta\") of charset: \"UTF-8\"\n    tag(\"meta\") of\n      name: \"viewport\"\n      content: \"width=device-width, initial-scale=1.0\"\n    tag(\"link\") of\n      href: \"https://cdn.jsdelivr.net/npm/typeface-inconsolata@1.1.13/index.min.css\"\n      rel: \"stylesheet\"\n    elem(\"title\") of \"Parse Rules\"\n  elem(\"body\", style(padding: \"1em\")) of\n    elem(\"div\", style of\n      display: \"flex\"\n      \"flex-direction\": \"column\"\n      gap: \"1em\"\n    ) of\n      ...elements\n    elem(\"style\") of\n      \"body{margin:0;font-family:system-ui,sans-serif;font-size:16px}\"\n      \"figure{margin:0;display:flex;flex-direction:column;gap:0.5em}\"\n      \"figcaption{font-style:italic;font-weight:600}\"\n      \"figure:target figcaption{color:#007bff}\"\n      \"figure:target figcaption::before{font-style:normal;content:'⯈ '}\"\n      \"figure:target figcaption::after{font-style:normal;content:' ⯇'}\"\n      loadRailroadStylesheet\n\nfun toElements(diagrams) =\n  diagrams\n    Iter.mapping of case [caption, svg] then\n      elem(\"figure\", id: caption) of\n        elem(\"figcaption\") of caption\n        svg\n    Iter.toArray()\n\nfs.writeFileSync of\n  filePath of \"rule.html\"\n  toHTML of\n    elem(\"h1\") of \"Parse Rules\"\n    elem(\"h2\") of \"Terms\"\n    ...toElements of render(railroad, \"term\", termRule)\n    elem(\"h2\") of \"Types\"\n    ...toElements of render(railroad, \"type\", typeRule)\n    elem(\"h2\") of \"Definitions\"\n    ...toElements of render(railroad, \"definition\", declRule)\n  \"utf-8\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/ParserErrorTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\n\nopen Test { example }\n\nexample of \":tree ((x) ==> x\"\n//│ > Error of \"unexpected end of input\"\n//│ > «⚠»\n\nexample of \":tree ((x) ==> x))\"\n//│ > App:\n//│ >   callee = Ident of \"==>\"\n//│ >   argument = Stack of \n//│ >     Ident of \"x\"\n//│ >     Ident of \"x\"\n//│ > Error of \"unexpected token Identifier(\\\")\\\", true)\"\n//│ > «x ==> x»\n//│ > «⚠»\n\nexample of \"\"\"\ntype a = b and b = c\n\"\"\"\n//│ > «type a = b and b = c»\n\nexample of \"\"\"\n:tree\ntype test = Bar | Test | Foo\nand test' = Bar' | Test' | Foo'\n\"\"\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Ident of \"test\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`|`, N/A, N/A)\n//│ >         lhs = Ident of \"Bar\"\n//│ >         rhs = Infix:\n//│ >           op = Keyword(`|`, N/A, N/A)\n//│ >           lhs = Ident of \"Test\"\n//│ >           rhs = Ident of \"Foo\"\n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Ident of \"test'\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`|`, N/A, N/A)\n//│ >         lhs = Ident of \"Bar'\"\n//│ >         rhs = Infix:\n//│ >           op = Keyword(`|`, N/A, N/A)\n//│ >           lhs = Ident of \"Test'\"\n//│ >           rhs = Ident of \"Foo'\"\n//│ > «type test = Bar | Test | Foo and test' = Bar' | Test' | Foo'»\n\nexample of \"\"\"\n:tree\n-2 * 3\n~2 * 3\n\"\"\"\n//│ > App:\n//│ >   callee = Ident of \"*\"\n//│ >   argument = Stack of \n//│ >     App:\n//│ >       callee = Ident of \"*\"\n//│ >       argument = Stack of \n//│ >         App:\n//│ >           callee = Ident of \"-\"\n//│ >           argument = Literal#Integer of \"2\"\n//│ >         App:\n//│ >           callee = Ident of \"~\"\n//│ >           argument = Stack of \n//│ >             Literal#Integer of \"3\"\n//│ >             Literal#Integer of \"2\"\n//│ >     Literal#Integer of \"3\"\n//│ > «(-2) * 3 ~ 2 * 3»\n\nexample of \"\"\"\n:tree\nlet foo = -2 * 3\n2 * 3\n\"\"\"\n//│ > LetIn:\n//│ >   bindings = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Ident of \"foo\"\n//│ >       rhs = App:\n//│ >         callee = Ident of \"*\"\n//│ >         argument = Stack of \n//│ >           App:\n//│ >             callee = Ident of \"*\"\n//│ >             argument = Stack of \n//│ >               App:\n//│ >                 callee = Ident of \"-\"\n//│ >                 argument = Literal#Integer of \"2\"\n//│ >               App:\n//│ >                 callee = Literal#Integer of \"3\"\n//│ >                 argument = Literal#Integer of \"2\"\n//│ >           Literal#Integer of \"3\"\n//│ >   body = None\n//│ > «let foo = (-2) * 3 2 * 3»\n\n\n\n// TODO should fail\nexample of \"\"\"\n=> xx\n\"\"\"\n//│ > «=>xx»\n\nexample of \"\"\"\n:tree\nid fun x -> x\n\"\"\"\n//│ > Ident of \"id\"\n//│ > Error of \"unexpected token Identifier(\\\"fun\\\", false)\"\n//│ > Error of \"unexpected token Identifier(\\\"x\\\", false)\"\n//│ > Error of \"unexpected token Identifier(\\\"->\\\", true)\"\n//│ > Error of \"unexpected token Identifier(\\\"x\\\", false)\"\n//│ > «id»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n\nexample of \"\"\"\n:tree\nid if true then 1 else 0\n\"\"\"\n//│ > Ident of \"id\"\n//│ > Error of \"unexpected token Identifier(\\\"if\\\", false)\"\n//│ > Error of \"unexpected token Literal(Boolean, \\\"true\\\")\"\n//│ > Error of \"unexpected token Identifier(\\\"then\\\", false)\"\n//│ > Error of \"unexpected token Literal(Integer, \\\"1\\\")\"\n//│ > Error of \"unexpected token Identifier(\\\"else\\\", false)\"\n//│ > Error of \"unexpected token Literal(Integer, \\\"0\\\")\"\n//│ > «id»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n\nexample of \"\"\"\ntype;;\n\"\"\"\n//│ > «⚠»\n\nexample of \"\"\"\nfunction;;\n\"\"\"\n//│ > «⚠»\n\nexample of \"\"\"\nlet foo_bar = function;;\n\"\"\"\n//│ > «⚠»\n\nexample of \"\"\"\nlet let = 0;;\n\"\"\"\n//│ > «⚠»\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/ParserTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\n\nopen Test { example }\n\nexample of \"(x) => x\"\n//│ > «x => x»\n\nexample of \"let x: int = 0\"\n//│ > «let x : int = 0»\n\nexample of \"let x: int -> int = function | 0 -> 1 | x -> x\"\n//│ > «let x : int -> int = function 0 -> 1 | x -> x»\n\nexample of \"\"\"\nfun x y -> x + y\n\"\"\"\n//│ > «fun x y -> x + y»\n\nexample of \"\"\"\nfun true false -> false | false true -> true\n\"\"\"\n//│ > «fun true false -> false»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n//│ > «⚠»\n\nexample of \"\"\"\nid (fun x y -> x + y)\n\"\"\"\n//│ > «id (fun x y -> x + y)»\n\nexample of \"\"\"\n:tree\nlet x: int -> int -> int = fun x y -> x + y\n\"\"\"\n//│ > LetIn:\n//│ >   bindings = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Infix:\n//│ >         op = Keyword(`:`, 4, 3)\n//│ >         lhs = Ident of \"x\"\n//│ >         rhs = Infix:\n//│ >           op = Keyword(`->`, 5, 3)\n//│ >           lhs = Ident of \"int\"\n//│ >           rhs = Infix:\n//│ >             op = Keyword(`->`, 5, 3)\n//│ >             lhs = Ident of \"int\"\n//│ >             rhs = Ident of \"int\"\n//│ >       rhs = Lambda:\n//│ >         params = Stack of \n//│ >           App:\n//│ >             callee = Ident of \"x\"\n//│ >             argument = Ident of \"y\"\n//│ >         body = App:\n//│ >           callee = Ident of \"+\"\n//│ >           argument = Stack of \n//│ >             Ident of \"x\"\n//│ >             Ident of \"y\"\n//│ >   body = None\n//│ > «let x : int -> int -> int = fun x y -> x + y»\n\nexample of \"(1 + 2) * 3\"\n//│ > «(1 + 2) * 3»\n\nexample of \"1 + 2 ** 5 * 4\"\n//│ > «1 + 2 ** 5 * 4»\n\nexample of \"let zero = 0 in zero\"\n//│ > «let zero = 0 in zero»\n\nexample of \"\"\"\nlet one = 1 in\nlet zero = 0 in\none + zero\n\"\"\"\n//│ > «let one = 1 in let zero = 0 in one + zero»\n\nexample of \"\"\"\nf x y\n\"\"\"\n//│ > «f x y»\n\nexample of \"\"\"\nlet pi = 4.0 *. atan 1.0\n\"\"\"\n//│ > «let pi = 4.0 *. atan 1.0»\n\nexample of \"let square x = x *. x\"\n//│ > «let square x = x *. x»\n\nexample of \"square (sin pi) +. square (cos pi)\"\n//│ > «square (sin pi) +. square (cos pi)»\n\nexample of \"(1 < 2) = false\"\n//│ > «1 < 2»\n//│ > «⚠»\n//│ > «⚠»\n\nexample of \"let cat s1 s2 = s1 ^ \\\" \\\" ^ s2\"\n//│ > «let cat s1 s2 = s1 ^ \" \" ^ s2»\n\nexample of \"fun x -> x\"\n//│ > «fun x -> x»\n\nexample of \"\"\"\nlet compose f g = fun x -> f (g x) in\n  let cos2 = compose square cos\n\"\"\"\n//│ > «let compose f g = fun x -> f (g x) in let cos2 = compose square cos»\n\nexample of \"type sign = Positive | Negative\"\n//│ > «type sign = Positive | Negative»\n\nexample of \"true\"\n//│ > «true»\n\nexample of \"\"\"\nmatch x with true -> 1 | false -> 0\n\"\"\"\n//│ > «match x with true -> 1 | false -> 0»\n\nexample of \"\"\"\nfunction (_, 0) -> \"both zero\"\n\"\"\"\n//│ > «function (_, 0) -> \"both …\"»\n\nexample of \"\"\"\nfunction (0, 0) -> \"both zero\"\n       | (0, _) -> \"first only zero\"\n       | (_, 0) -> \"second only zero\"\n       | (_, _) -> \"neither zero\"\n\"\"\"\n//│ > «function (0, 0) -> \"both …\" | (0, _) -> \"first…\" | (_, 0) -> \"secon…\" | (_, _) -> \"neith…\"»\n\nexample of \"if f x then y else z\"\n//│ > «if f x then y then z»\n\nexample of \"id (if f x then y else z)\"\n//│ > «id (if f x then y then z)»\n\nexample of \"if f x then if g x then z else w else if h x then y else w\"\n//│ > «if f x then if g x then z then w then if h x then y then w»\n\nexample of \"1, 2, 3\"\n//│ > «(1, 2, 3)»\n\nexample of \"1; 2; 3\"\n//│ > «1; 2; 3»\n\nexample of \"\"\"\n1, 2; 3, 4; 5\n\"\"\"\n//│ > «(1, 2); (3, 4); 5»\n\n// > The expressions `( expr )` and `begin expr end` have the same value as `expr`.\n// > The two constructs are semantically equivalent, but it is good style to use\n// > `begin … end` inside control structures.\nexample of \"\"\"\nbegin\n  print_string \"hello\";\n  print_string \"world\"\nend\n\"\"\"\n//│ > «print_string \"hello\"; print_string \"world\"»\n\nexample of \"a == b\"\n//│ > «a == b»\n\n// TODO: comment on this syntax design smell in the paper\nexample of \"\"\"\nif a == b then\n  a\nelse\n  b\n\"\"\"\n//│ > «if a == b then a then b»\n\nexample of \"\"\"\nlet f a b =\n  if a == b then\n    print_endline \"Equal\"\n  else begin\n    print_string \"Not Equal: \";\n    print_int a;\n    print_string \" and \";\n    print_int b;\n    print_newline ()\n  end\n\"\"\"\n//│ > «let f a b = if a == b then print_endline \"Equal\" then print_string \"Not E…\"; print_int a; print_string \" and \"; print_int b; print_newline ()»\n\nexample of \"\"\"\nlet foo = y; x\n\"\"\"\n//│ > «let foo = y; x»\n\nexample of \"\"\"\nlet translate p dx dy =\n  p.x <- p.x +. dx;\n  p.y <- p.y +. dy\n\"\"\"\n//│ > «let translate p dx dy = p.x <- p.x +. dx; p.y <- p.y +. dy»\n\nexample of \"\"\":tree f x.y \"\"\"\n//│ > App:\n//│ >   callee = Ident of \"f\"\n//│ >   argument = Infix:\n//│ >     op = Keyword(`.`, 26, 26)\n//│ >     lhs = Ident of \"x\"\n//│ >     rhs = Ident of \"y\"\n//│ > «f x.y»\n\nexample of \"\"\":tree f x.y.z x.y \"\"\"\n//│ > App:\n//│ >   callee = App:\n//│ >     callee = Ident of \"f\"\n//│ >     argument = Infix:\n//│ >       op = Keyword(`.`, 26, 26)\n//│ >       lhs = Infix:\n//│ >         op = Keyword(`.`, 26, 26)\n//│ >         lhs = Ident of \"x\"\n//│ >         rhs = Ident of \"y\"\n//│ >       rhs = Ident of \"z\"\n//│ >   argument = Infix:\n//│ >     op = Keyword(`.`, 26, 26)\n//│ >     lhs = Ident of \"x\"\n//│ >     rhs = Ident of \"y\"\n//│ > «f x.y.z x.y»\n\nexample of \"\"\":tree f x.y.z x.y \"\"\"\n//│ > App:\n//│ >   callee = App:\n//│ >     callee = Ident of \"f\"\n//│ >     argument = Infix:\n//│ >       op = Keyword(`.`, 26, 26)\n//│ >       lhs = Infix:\n//│ >         op = Keyword(`.`, 26, 26)\n//│ >         lhs = Ident of \"x\"\n//│ >         rhs = Ident of \"y\"\n//│ >       rhs = Ident of \"z\"\n//│ >   argument = Infix:\n//│ >     op = Keyword(`.`, 26, 26)\n//│ >     lhs = Ident of \"x\"\n//│ >     rhs = Ident of \"y\"\n//│ > «f x.y.z x.y»\n\nexample of \"()\"\n//│ > «()»\n\nexample of \"\"\"\nmatch x with | 0 -> 1\n\"\"\"\n//│ > «match x with 0 -> 1»\n\nexample of \"\"\"\nlet fullname title first second =\n  match title with\n  | Some t -> t ^ \" \" ^ first ^ \" \" ^ second\n  | None -> first ^ \" \" ^ second\n\"\"\"\n//│ > «let fullname title first second = match title with Some t -> t ^ \" \" ^ first ^ \" \" ^ second | None -> first ^ \" \" ^ second»\n\nexample of \"\"\"\nlet a = if x then 1 else 0 in\nlet b = 0\n\"\"\"\n//│ > «let a = if x then 1 then 0 in let b = 0»\n\nexample of \"\"\"\nlet rec factorial x =\n  if x <= 1 then 1 else x * factorial (x - 1)\nand sum l =\n  match l with\n  | [] -> 0\n  | h :: t -> h + sum t\nin\n  factorial 5 + sum [1; 2; 3]\n\"\"\"\n//│ > «let factorial x = if x <= 1 then 1 then x * factorial (x - 1) and sum l = match l with [] -> 0 | h :: t -> h + sum t in factorial 5 + sum [1; 2; 3]»\n\nexample of \"begin end\"\n//│ > «»\n\nexample of \"\"\"\nlet v' =\n    let a, b = (1, 2) in a + b\n  in v'\n\"\"\"\n//│ > «let v' = let (a, b) = (1, 2) in a + b in v'»\n\nexample of \"\"\"\nlet a = 0 and b = 1 in a + b\n\"\"\"\n//│ > «let a = 0 and b = 1 in a + b»\n\nexample of \"\"\"\nlet rec even =\n  function 0 -> true | n -> odd (n - 1)\nand odd =\n  function 0 -> false | n -> even (n - 1)\nin\n  even 1000\n\"\"\"\n//│ > «let even = function 0 -> true | n -> odd (n - 1) and odd = function 0 -> false | n -> even (n - 1) in even 1000»\n\nexample of \"\"\"\nlet rec even =\n  function 0 -> true | n -> odd (n - 1)\nand odd =\n  function 0 -> false | n -> even (n - 1)\n\"\"\"\n//│ > «let even = function 0 -> true | n -> odd (n - 1) and odd = function 0 -> false | n -> even (n - 1)»\n\nexample of \"\"\"\nlet a = 0\nlet b = 0\nlet f x = x + 1\nlet g x = f (f x)\n\"\"\"\n//│ > «let a = 0»\n//│ > «let b = 0»\n//│ > «let f x = x + 1»\n//│ > «let g x = f (f x)»\n\nexample of \"\"\"\n:tree\n-2 * 3\n;;\n~2 * 3\nlet x = !true\n\"\"\"\n//│ > App:\n//│ >   callee = Ident of \"*\"\n//│ >   argument = Stack of \n//│ >     App:\n//│ >       callee = Ident of \"-\"\n//│ >       argument = Literal#Integer of \"2\"\n//│ >     Literal#Integer of \"3\"\n//│ > App:\n//│ >   callee = Ident of \"*\"\n//│ >   argument = Stack of \n//│ >     App:\n//│ >       callee = Ident of \"~\"\n//│ >       argument = Literal#Integer of \"2\"\n//│ >     Literal#Integer of \"3\"\n//│ > LetIn:\n//│ >   bindings = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Ident of \"x\"\n//│ >       rhs = App:\n//│ >         callee = Ident of \"!\"\n//│ >         argument = Literal#Boolean of \"true\"\n//│ >   body = None\n//│ > «(-2) * 3»\n//│ > «~2 * 3»\n//│ > «let x = !true»\n\nexample of \"\"\"\nlet f x = x\n;;\n1 + 2 * 3\n\"\"\"\n//│ > «let f x = x»\n//│ > «1 + 2 * 3»\n\nexample of \"\"\"\n:tree\nx.y <- 0\n\"\"\"\n//│ > Infix:\n//│ >   op = Keyword(`<-`, 9, 9)\n//│ >   lhs = Infix:\n//│ >     op = Keyword(`.`, 26, 26)\n//│ >     lhs = Ident of \"x\"\n//│ >     rhs = Ident of \"y\"\n//│ >   rhs = Literal#Integer of \"0\"\n//│ > «x.y <- 0»\n\nexample of \"\"\"\n:tree\nf expr .( expr ) <- expr\n\"\"\"\n//│ > Infix:\n//│ >   op = Keyword(`<-`, 9, 9)\n//│ >   lhs = App:\n//│ >     callee = Ident of \"f\"\n//│ >     argument = Infix:\n//│ >       op = Keyword(`.`, 26, 26)\n//│ >       lhs = Ident of \"expr\"\n//│ >       rhs = Ident of \"expr\"\n//│ >   rhs = Ident of \"expr\"\n//│ > «f expr.expr <- expr»\n\nexample of \"\"\"\n:tree\nf (expr .( expr ) <- expr)\n\"\"\"\n//│ > App:\n//│ >   callee = Ident of \"f\"\n//│ >   argument = Infix:\n//│ >     op = Keyword(`<-`, 9, 9)\n//│ >     lhs = Infix:\n//│ >       op = Keyword(`.`, 26, 26)\n//│ >       lhs = Ident of \"expr\"\n//│ >       rhs = Ident of \"expr\"\n//│ >     rhs = Ident of \"expr\"\n//│ > «f (expr.expr <- expr)»\n\nexample of \"\"\"\na:;\n\"\"\"\n//│ > «a :;»\n\nexample of \"\"\"\nlet sub = (-);;\n\"\"\"\n//│ > «let sub = -»\n\nexample of \"\"\"\n:tree\nf -1\n\"\"\"\n//│ > App:\n//│ >   callee = Ident of \"-\"\n//│ >   argument = Stack of \n//│ >     Ident of \"f\"\n//│ >     Literal#Integer of \"1\"\n//│ > «f - 1»\n\nexample of \"\"\"\n:tree\nf :: -1\n\"\"\"\n//│ > App:\n//│ >   callee = Ident of \"::\"\n//│ >   argument = Stack of \n//│ >     Ident of \"f\"\n//│ >     App:\n//│ >       callee = Ident of \"-\"\n//│ >       argument = Literal#Integer of \"1\"\n//│ > «f :: -1»\n\n\nlet x = 1\n//│ x = 1\n\nmkStr of \"A\", x is Str\n//│ // Standard Error:\n//│ Assertion failed\n//│ \n//│ = \"Afalse\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/PrattParsingTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/PrattParsing.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Expr.mls\"\nimport \"../../../mlscript-compile/apps/parsing/TokenHelpers.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Lexer.mls\"\n\nopen Lexer { lex }\nopen PrattParsing { parse }\n\nfun example(input) =\n  let tokens = lex of input, false\n  print of \"Tokens: \" + TokenHelpers.panorama(tokens)\n  let expr = parse of tokens\n  print of \"Parsed: \" + expr.toString()\n  print of \"Pretty-printed: \" + expr Expr.prettyPrint()\n\nexample of \"x + y - 3 * (a / b) ** 2\"\n//│ > Tokens: ┃x│␠│+│␠│y│␠│-│␠│3│␠│*│␠│(│a│␠│/│␠│b│)│␠│**│␠│2┃\n//│ > Parsed: Inf(\"-\", Inf(\"+\", Var(\"x\"), Var(\"y\")), Inf(\"*\", Lit(3), Inf(\"**\", Inf(\"/\", Var(\"a\"), Var(\"b\")), Lit(2))))\n//│ > Pretty-printed: x + y - 3 * (a / b) ** 2\n\nexample of \"((m - 2) / n) ** 3 + 5 * x\"\n//│ > Tokens: ┃(│(│m│␠│-│␠│2│)│␠│/│␠│n│)│␠│**│␠│3│␠│+│␠│5│␠│*│␠│x┃\n//│ > Parsed: Inf(\"+\", Inf(\"**\", Inf(\"/\", Inf(\"-\", Var(\"m\"), Lit(2)), Var(\"n\")), Lit(3)), Inf(\"*\", Lit(5), Var(\"x\")))\n//│ > Pretty-printed: ((m - 2) / n) ** 3 + 5 * x\n\nexample of \"(a ** 2) - (b / 3) * (c + d)\"\n//│ > Tokens: ┃(│a│␠│**│␠│2│)│␠│-│␠│(│b│␠│/│␠│3│)│␠│*│␠│(│c│␠│+│␠│d│)┃\n//│ > Parsed: Inf(\"-\", Inf(\"**\", Var(\"a\"), Lit(2)), Inf(\"*\", Inf(\"/\", Var(\"b\"), Lit(3)), Inf(\"+\", Var(\"c\"), Var(\"d\"))))\n//│ > Pretty-printed: a ** 2 - b / 3 * (c + d)\n\nexample of \"x * y / (a - b) + c ** 4\"\n//│ > Tokens: ┃x│␠│*│␠│y│␠│/│␠│(│a│␠│-│␠│b│)│␠│+│␠│c│␠│**│␠│4┃\n//│ > Parsed: Inf(\"+\", Inf(\"/\", Inf(\"*\", Var(\"x\"), Var(\"y\")), Inf(\"-\", Var(\"a\"), Var(\"b\"))), Inf(\"**\", Var(\"c\"), Lit(4)))\n//│ > Pretty-printed: x * y / (a - b) + c ** 4\n\nexample of \"2 + 3 - 4 * 5 / (x ** 2)\"\n//│ > Tokens: ┃2│␠│+│␠│3│␠│-│␠│4│␠│*│␠│5│␠│/│␠│(│x│␠│**│␠│2│)┃\n//│ > Parsed: Inf(\"-\", Inf(\"+\", Lit(2), Lit(3)), Inf(\"/\", Inf(\"*\", Lit(4), Lit(5)), Inf(\"**\", Var(\"x\"), Lit(2))))\n//│ > Pretty-printed: 2 + 3 - 4 * 5 / x ** 2\n\nexample of \"(x - y) ** (z + 3 / w) * 2\"\n//│ > Tokens: ┃(│x│␠│-│␠│y│)│␠│**│␠│(│z│␠│+│␠│3│␠│/│␠│w│)│␠│*│␠│2┃\n//│ > Parsed: Inf(\"*\", Inf(\"**\", Inf(\"-\", Var(\"x\"), Var(\"y\")), Inf(\"+\", Var(\"z\"), Inf(\"/\", Lit(3), Var(\"w\")))), Lit(2))\n//│ > Pretty-printed: (x - y) ** (z + 3 / w) * 2\n\nexample of \"((a + b) ** 2) / (c - d) * e - f\"\n//│ > Tokens: ┃(│(│a│␠│+│␠│b│)│␠│**│␠│2│)│␠│/│␠│(│c│␠│-│␠│d│)│␠│*│␠│e│␠│-│␠│f┃\n//│ > Parsed: Inf(\"-\", Inf(\"*\", Inf(\"/\", Inf(\"**\", Inf(\"+\", Var(\"a\"), Var(\"b\")), Lit(2)), Inf(\"-\", Var(\"c\"), Var(\"d\"))), Var(\"e\")), Var(\"f\"))\n//│ > Pretty-printed: (a + b) ** 2 / (c - d) * e - f\n\nexample of \"8 / (2 + (3 * x) - y) ** 2\"\n//│ > Tokens: ┃8│␠│/│␠│(│2│␠│+│␠│(│3│␠│*│␠│x│)│␠│-│␠│y│)│␠│**│␠│2┃\n//│ > Parsed: Inf(\"/\", Lit(8), Inf(\"**\", Inf(\"-\", Inf(\"+\", Lit(2), Inf(\"*\", Lit(3), Var(\"x\"))), Var(\"y\")), Lit(2)))\n//│ > Pretty-printed: 8 / (2 + 3 * x - y) ** 2\n\nexample of \"((p - q) * (r + s)) / (t ** (u - 1))\"\n//│ > Tokens: ┃(│(│p│␠│-│␠│q│)│␠│*│␠│(│r│␠│+│␠│s│)│)│␠│/│␠│(│t│␠│**│␠│(│u│␠│-│␠│1│)│)┃\n//│ > Parsed: Inf(\"/\", Inf(\"*\", Inf(\"-\", Var(\"p\"), Var(\"q\")), Inf(\"+\", Var(\"r\"), Var(\"s\"))), Inf(\"**\", Var(\"t\"), Inf(\"-\", Var(\"u\"), Lit(1))))\n//│ > Pretty-printed: (p - q) * (r + s) / t ** (u - 1)\n\nexample of \"1 + 2 * 3 - 4 / (5 ** (6 - x))\"\n//│ > Tokens: ┃1│␠│+│␠│2│␠│*│␠│3│␠│-│␠│4│␠│/│␠│(│5│␠│**│␠│(│6│␠│-│␠│x│)│)┃\n//│ > Parsed: Inf(\"-\", Inf(\"+\", Lit(1), Inf(\"*\", Lit(2), Lit(3))), Inf(\"/\", Lit(4), Inf(\"**\", Lit(5), Inf(\"-\", Lit(6), Var(\"x\")))))\n//│ > Pretty-printed: 1 + 2 * 3 - 4 / 5 ** (6 - x)\n\nexample of \"5 ** 6 ** 7 ** 8\"\n//│ > Tokens: ┃5│␠│**│␠│6│␠│**│␠│7│␠│**│␠│8┃\n//│ > Parsed: Inf(\"**\", Lit(5), Inf(\"**\", Lit(6), Inf(\"**\", Lit(7), Lit(8))))\n//│ > Pretty-printed: 5 ** 6 ** 7 ** 8\n\nexample of \"(a ** 2) ** 5 ** e\"\n//│ > Tokens: ┃(│a│␠│**│␠│2│)│␠│**│␠│5│␠│**│␠│e┃\n//│ > Parsed: Inf(\"**\", Inf(\"**\", Var(\"a\"), Lit(2)), Inf(\"**\", Lit(5), Var(\"e\")))\n//│ > Pretty-printed: (a ** 2) ** 5 ** e\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/RecursiveDescentTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/RecursiveDescent.mls\"\nimport \"../../../mlscript-compile/apps/parsing/BasicExpr.mls\"\nimport \"../../../mlscript-compile/apps/parsing/TokenHelpers.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Lexer.mls\"\n\nopen Lexer { lex }\nopen RecursiveDescent { parse }\nopen BasicExpr { Expr }\n\nfun example(input) =\n  let tokens = lex of input, false\n  print of \"Tokens: \" + TokenHelpers.panorama(tokens)\n  let expr = parse of tokens\n  print of \"Parsed: \" + expr.toString()\n  print of \"Pretty-printed: \" + expr BasicExpr.prettyPrint()\n\nexample of \"1 + 2 * 3\"\n//│ > Tokens: ┃1│␠│+│␠│2│␠│*│␠│3┃\n//│ > Parsed: Add(Lit(1), Mul(Lit(2), Lit(3)))\n//│ > Pretty-printed: 1 + 2 * 3\n\nexample of \"3 * x + 1\"\n//│ > Tokens: ┃3│␠│*│␠│x│␠│+│␠│1┃\n//│ > Parsed: Add(Mul(Lit(3), Var(\"x\")), Lit(1))\n//│ > Pretty-printed: 3 * x + 1\n\nexample of \"1 + (1 + 1)\"\n//│ > Tokens: ┃1│␠│+│␠│(│1│␠│+│␠│1│)┃\n//│ > Parsed: Add(Lit(1), Add(Lit(1), Lit(1)))\n//│ > Pretty-printed: 1 + 1 + 1\n\nexample of \"1 + (1 + 1\"\n//│ > Tokens: ┃1│␠│+│␠│(│1│␠│+│␠│1┃\n//│ > Parsed: Add(Lit(1), Err(Some(Add(Lit(1), Lit(1))), \"Expected token ), but found end of input\"))\n//│ > Pretty-printed: 1 + { 1 + 1 | \"Expected token ), but found end of input\" }\n\nexample of \"1 + 1 +\"\n//│ > Tokens: ┃1│␠│+│␠│1│␠│+┃\n//│ > Parsed: Add(Add(Lit(1), Lit(1)), Err(None, \"Unexpected end of input\"))\n//│ > Pretty-printed: 1 + 1 + { \"Unexpected end of input\" }\n\nexample of \"x + 5\"\n//│ > Tokens: ┃x│␠│+│␠│5┃\n//│ > Parsed: Add(Var(\"x\"), Lit(5))\n//│ > Pretty-printed: x + 5\n\nexample of \"3 * x + 2\"\n//│ > Tokens: ┃3│␠│*│␠│x│␠│+│␠│2┃\n//│ > Parsed: Add(Mul(Lit(3), Var(\"x\")), Lit(2))\n//│ > Pretty-printed: 3 * x + 2\n\nexample of \"(x + 1) * (y + 4)\"\n//│ > Tokens: ┃(│x│␠│+│␠│1│)│␠│*│␠│(│y│␠│+│␠│4│)┃\n//│ > Parsed: Mul(Add(Var(\"x\"), Lit(1)), Add(Var(\"y\"), Lit(4)))\n//│ > Pretty-printed: (x + 1) * (y + 4)\n\nexample of \"2 + (3 * y)\"\n//│ > Tokens: ┃2│␠│+│␠│(│3│␠│*│␠│y│)┃\n//│ > Parsed: Add(Lit(2), Mul(Lit(3), Var(\"y\")))\n//│ > Pretty-printed: 2 + 3 * y\n\nexample of \"(x + 2) + (3 * y)\"\n//│ > Tokens: ┃(│x│␠│+│␠│2│)│␠│+│␠│(│3│␠│*│␠│y│)┃\n//│ > Parsed: Add(Add(Var(\"x\"), Lit(2)), Mul(Lit(3), Var(\"y\")))\n//│ > Pretty-printed: x + 2 + 3 * y\n\nexample of \"3 * (x + y) + 7\"\n//│ > Tokens: ┃3│␠│*│␠│(│x│␠│+│␠│y│)│␠│+│␠│7┃\n//│ > Parsed: Add(Mul(Lit(3), Add(Var(\"x\"), Var(\"y\"))), Lit(7))\n//│ > Pretty-printed: 3 * (x + y) + 7\n\n// Unbalanced parentheses\nexample of \"((x + y)\"\n//│ > Tokens: ┃(│(│x│␠│+│␠│y│)┃\n//│ > Parsed: Err(Some(Add(Var(\"x\"), Var(\"y\"))), \"Expected token ), but found end of input\")\n//│ > Pretty-printed: { x + y | \"Expected token ), but found end of input\" }\n\n// Missing operand between '+' and '*'\nexample of \"x + * y\"\n//│ > Tokens: ┃x│␠│+│␠│*│␠│y┃\n//│ > Parsed: Add(Var(\"x\"), Mul(Err(None, \"Unexpected token *\"), Var(\"y\")))\n//│ > Pretty-printed: x + { \"Unexpected token *\" } * y\n\n// Another unbalanced parenthesis\nexample of \"3 + (y\"\n//│ > Tokens: ┃3│␠│+│␠│(│y┃\n//│ > Parsed: Add(Lit(3), Err(Some(Var(\"y\")), \"Expected token ), but found end of input\"))\n//│ > Pretty-printed: 3 + { y | \"Expected token ), but found end of input\" }\n\n// Unbalanced parenthesis\nexample of \"3 + 7)\"\n//│ > Tokens: ┃3│␠│+│␠│7│)┃\n//│ > Parsed: Err(Some(Add(Lit(3), Lit(7))), \"Expect end of input, but found )\")\n//│ > Pretty-printed: { 3 + 7 | \"Expect end of input, but found )\" }\n\n// Operator '+' missing a second operand\nexample of \"(x +) + y\"\n//│ > Tokens: ┃(│x│␠│+│)│␠│+│␠│y┃\n//│ > Parsed: Add(Add(Var(\"x\"), Err(None, \"Unexpected token )\")), Var(\"y\"))\n//│ > Pretty-printed: x + { \"Unexpected token )\" } + y\n\n// Expression starting with an operator '*'\nexample of \"* x + 5\"\n//│ > Tokens: ┃*│␠│x│␠│+│␠│5┃\n//│ > Parsed: Add(Mul(Err(None, \"Unexpected token *\"), Var(\"x\")), Lit(5))\n//│ > Pretty-printed: { \"Unexpected token *\" } * x + 5\n\n// Double operator '+' without an operand in between\nexample of \"x + + 5\"\n//│ > Tokens: ┃x│␠│+│␠│+│␠│5┃\n//│ > Parsed: Add(Add(Var(\"x\"), Err(None, \"Unexpected token +\")), Lit(5))\n//│ > Pretty-printed: x + { \"Unexpected token +\" } + 5\n\n// Missing operator between 'x' and 'y'\nexample of \"x y\"\n//│ > Tokens: ┃x│␠│y┃\n//│ > Parsed: Err(Some(Var(\"x\")), \"Expect end of input, but found y\")\n//│ > Pretty-printed: { x | \"Expect end of input, but found y\" }\n\n// Empty parentheses with no expression\nexample of \"()\"\n//│ > Tokens: ┃(│)┃\n//│ > Parsed: Err(None, \"Unexpected token )\")\n//│ > Pretty-printed: { \"Unexpected token )\" }\n\n// Operator '*' at the end with no following operand\nexample of \"3 + x *\"\n//│ > Tokens: ┃3│␠│+│␠│x│␠│*┃\n//│ > Parsed: Add(Lit(3), Mul(Var(\"x\"), Err(None, \"Unexpected end of input\")))\n//│ > Pretty-printed: 3 + x * { \"Unexpected end of input\" }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/RulesTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/MutMap.mls\"\n\nimport \"../../../mlscript-compile/apps/parsing/Keywords.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Rules.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\n\nopen Keywords { opPrec, opPrecOpt }\n\nKeywords.maxKeywordPrec\n//│ = 11\n\nKeywords.maxOperatorPrec\n//│ = 26\n\nopPrec(\"|>\")\n//│ = [14, 20]\n\nopPrec(\"<:\")\n//│ = [20, 12]\n\nopPrec(\"::\")\n//│ = [13, 12]\n\nopPrec of \"+\"\n//│ = [21, 21]\n\nopPrecOpt of \"==\"\n//│ = Some([16, 16])\n\nprint of Keywords.all |> MutMap.valuesIterator |. Iter.joined(\"\\n\")\n//│ > Keyword(`;;`, 0, 0)\n//│ > Keyword(`class`, N/A, 0)\n//│ > Keyword(`;`, 1, 0)\n//│ > Keyword(`,`, 2, 1)\n//│ > Keyword(`=`, 3, 3)\n//│ > Keyword(`and`, N/A, 4)\n//│ > Keyword(`|`, N/A, N/A)\n//│ > Keyword(`->`, 5, 3)\n//│ > Keyword(`:`, 4, 3)\n//│ > Keyword(`match`, 6, 6)\n//│ > Keyword(`while`, 7, 7)\n//│ > Keyword(`for`, 8, 8)\n//│ > Keyword(`to`, N/A, N/A)\n//│ > Keyword(`downto`, N/A, N/A)\n//│ > Keyword(`do`, N/A, N/A)\n//│ > Keyword(`done`, N/A, N/A)\n//│ > Keyword(`of`, N/A, N/A)\n//│ > Keyword(`with`, N/A, 8)\n//│ > Keyword(`case`, N/A, 8)\n//│ > Keyword(`if`, 10, 9)\n//│ > Keyword(`<-`, 9, 9)\n//│ > Keyword(`then`, 9, 9)\n//│ > Keyword(`else`, 9, 9)\n//│ > Keyword(`let`, 3, 1)\n//│ > Keyword(`in`, 9, 9)\n//│ > Keyword(`true`, N/A, N/A)\n//│ > Keyword(`false`, N/A, N/A)\n//│ > Keyword(`as`, 11, 11)\n//│ > Keyword(`fun`, 11, 5)\n//│ > Keyword(`function`, 11, 3)\n//│ > Keyword(`type`, 11, N/A)\n//│ > Keyword(`exception`, 11, N/A)\n//│ > Keyword(`rec`, 11, 3)\n//│ > Keyword(`#`, N/A, N/A)\n//│ > Keyword(`.`, 26, 26)\n//│ > Keyword(`*`, 22, 22)\n//│ > Keyword(`==`, 16, 16)\n//│ > Keyword(`(`, 27, 0)\n//│ > Keyword(`)`, 0, N/A)\n//│ > Keyword(`[`, 27, 0)\n//│ > Keyword(`]`, 0, N/A)\n//│ > Keyword(`{`, 27, 0)\n//│ > Keyword(`}`, 0, N/A)\n//│ > Keyword(`begin`, 27, 0)\n//│ > Keyword(`end`, 0, N/A)\n\nprint of Rules.termRule.display\n//│ > <prefix rules for expressions> ::= \n//│ >   | \"let\" [\"rec\"] <let-bindings> [\"in\" <term>]\n//│ >   | \"fun\" <term> \"->\" <term>\n//│ >   | \"match\" <term> \"with\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"function\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"if\" <term> \"then\" <term> [\"else\" <term>]\n//│ >   | \"while\" <term> \"do\" <term> \"done\"\n//│ >   | \"for\" <term> \"=\" <term> (\"to\" | \"downto\") <term> \"do\" <term> \"done\"\n//│ >   | \"(\" <term> \")\"\n//│ >   | \"[\" <term> \"]\"\n//│ >   | \"{\" <term> \"}\"\n//│ >   | \"begin\" <term> \"end\"\n//│ >   | <term> (\",\" <term> | \";\" <term> | \"<-\" <term> | \"==\" <term> | \"*\" <term> | \".\" (\"(\" <term> \")\" | <term>) | \":\" <type> | <term>)\n\nprint of Rules.typeRule.display\n//│ > <rules for types> ::= \n//│ >   | \"(\" <type> (<type-arguments-tail> \")\" <ident> | \")\" [<ident>])\n//│ >   | <type> (\"->\" <type> | \"*\" <type> | <type>)\n\nprint of Rules.declRule.display\n//│ > <prefix rules for module items> ::= \n//│ >   | \"let\" [\"rec\"] <let-bindings>\n//│ >   | \"type\" <typedefs>\n//│ >   | \"exception\" <constr-decls>\n//│ >   | \"#\" <ident> <term>\n\nRules.syntaxKinds\n  Iter.mapping of case [name, rule] then rule.display\n  Iter.joined(\"\\n\")\n  print()\n//│ > <let-bindings> ::= <term> \"=\" <term> [\"and\" <let-bindings>]\n//│ > <simple-matching> ::= <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ > <pattern-list> ::= <term> <pattern-list>\n//│ > <multiple-matching> ::= <pattern-list> \"->\" <term> [\"|\" <multiple-matching>]\n//│ > <type-arguments-tail> ::= \",\" <type> [<type-arguments-tail>]\n//│ > <constr-decl> ::= <ident> [\"of\" <type>]\n//│ > <variants> ::= <constr-decl> [\"|\" <variants>]\n//│ > <typedefs> ::= <typedef-lhs> <typedef-rhs> [\"and\" <typedefs>]\n//│ > <typedef-rhs> ::= \n//│ >   | \"=\" (<variants> | \"{\" <label-decls> \"}\")\n//│ >   | \"==\" <type>\n//│ > <label-decl> ::= <type> \":\" <type>\n//│ > <label-decls> ::= <label-decl> [\";\" <label-decls>]\n//│ > <constr-decls> ::= <constr-decl> [\"|\" <constr-decls>]\n//│ > <typedef-lhs> ::= <type-params> <ident>\n//│ > <type-params> ::= \n//│ >   | <typevar>\n//│ >   | \"(\" <typevar> <type-params-tail> \")\"\n//│ > <type-params-tail> ::= \",\" <typevar> <type-params-tail>\n//│ > <prefix rules for expressions> ::= \n//│ >   | \"let\" [\"rec\"] <let-bindings> [\"in\" <term>]\n//│ >   | \"fun\" <term> \"->\" <term>\n//│ >   | \"match\" <term> \"with\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"function\" [\"|\"] <term> \"->\" <term> [\"|\" <simple-matching>]\n//│ >   | \"if\" <term> \"then\" <term> [\"else\" <term>]\n//│ >   | \"while\" <term> \"do\" <term> \"done\"\n//│ >   | \"for\" <term> \"=\" <term> (\"to\" | \"downto\") <term> \"do\" <term> \"done\"\n//│ >   | \"(\" <term> \")\"\n//│ >   | \"[\" <term> \"]\"\n//│ >   | \"{\" <term> \"}\"\n//│ >   | \"begin\" <term> \"end\"\n//│ >   | <term> (\",\" <term> | \";\" <term> | \"<-\" <term> | \"==\" <term> | \"*\" <term> | \".\" (\"(\" <term> \")\" | <term>) | \":\" <type> | <term>)\n//│ > <rules for types> ::= \n//│ >   | \"(\" <type> (<type-arguments-tail> \")\" <ident> | \")\" [<ident>])\n//│ >   | <type> (\"->\" <type> | \"*\" <type> | <type>)\n//│ > <prefix rules for module items> ::= \n//│ >   | \"let\" [\"rec\"] <let-bindings>\n//│ >   | \"type\" <typedefs>\n//│ >   | \"exception\" <constr-decls>\n//│ >   | \"#\" <ident> <term>\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing/TypeTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\n\nopen Test { example }\n\nexample of \"\"\"\ntype 'a foo == 'a list\n\"\"\"\n//│ > «type foo ('a) == list 'a»\n\n// (A, List[A])\nexample of \"\"\"\ntype 'a foo == 'a * 'a list\n\"\"\"\n//│ > «type foo ('a) == 'a * list 'a»\n\n// (A, List[A], List[A])\nexample of \"\"\"\n:tree\ntype 'a foo == 'a * 'a list * 'a list\n\"\"\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`==`, 16, 16)\n//│ >       lhs = App:\n//│ >         callee = Ident of \"foo\"\n//│ >         argument = Tuple of Stack of \n//│ >           Ident of \"'a\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`*`, 22, 22)\n//│ >         lhs = Infix:\n//│ >           op = Keyword(`*`, 22, 22)\n//│ >           lhs = Ident of \"'a\"\n//│ >           rhs = App:\n//│ >             callee = Ident of \"list\"\n//│ >             argument = Ident of \"'a\"\n//│ >         rhs = App:\n//│ >           callee = Ident of \"list\"\n//│ >           argument = Ident of \"'a\"\n//│ > «type foo ('a) == 'a * list 'a * list 'a»\n\nexample of \"\"\"\ntype ('a, 'b) foo == 'a * 'b list -> 'b\n\"\"\"\n//│ > «type foo ('a, 'b) == 'a * list 'b -> 'b»\n\nexample of \"\"\"\ntype b == p * q * (r * s)\n\"\"\"\n//│ > «type b == p * q * r * s»\n\nexample of \"\"\"\ntype b == (p * q)\ntype f == int\n\"\"\"\n//│ > «type b == p * q»\n//│ > «type f == int»\n\nexample of \"\"\"\ntype a == b\ntype b == p * q * (r * s)\ntype f == int -> int\n\"\"\"\n//│ > «type a == b»\n//│ > «type b == p * q * r * s»\n//│ > «type f == int -> int»\n\nexample of \"\"\"\n:tree\ntype f == a -> b -> c\ntype g == (a -> b) -> c\n\"\"\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`==`, 16, 16)\n//│ >       lhs = Ident of \"f\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`->`, 5, 3)\n//│ >         lhs = Ident of \"a\"\n//│ >         rhs = Infix:\n//│ >           op = Keyword(`->`, 5, 3)\n//│ >           lhs = Ident of \"b\"\n//│ >           rhs = Ident of \"c\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`==`, 16, 16)\n//│ >       lhs = Ident of \"g\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`->`, 5, 3)\n//│ >         lhs = Infix:\n//│ >           op = Keyword(`->`, 5, 3)\n//│ >           lhs = Ident of \"a\"\n//│ >           rhs = Ident of \"b\"\n//│ >         rhs = Ident of \"c\"\n//│ > «type f == a -> b -> c»\n//│ > «type g == a -> b -> c»\n\nexample of \"\"\"\n:tree\ntype f == int * string -> float\ntype g == int * (string -> float)\n\"\"\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`==`, 16, 16)\n//│ >       lhs = Ident of \"f\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`->`, 5, 3)\n//│ >         lhs = Infix:\n//│ >           op = Keyword(`*`, 22, 22)\n//│ >           lhs = Ident of \"int\"\n//│ >           rhs = Ident of \"string\"\n//│ >         rhs = Ident of \"float\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`==`, 16, 16)\n//│ >       lhs = Ident of \"g\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`*`, 22, 22)\n//│ >         lhs = Ident of \"int\"\n//│ >         rhs = Infix:\n//│ >           op = Keyword(`->`, 5, 3)\n//│ >           lhs = Ident of \"string\"\n//│ >           rhs = Ident of \"float\"\n//│ > «type f == int * string -> float»\n//│ > «type g == int * string -> float»\n\nexample of \"\"\"\ntype 'a f == 'a * 'a\n\"\"\"\n//│ > «type f ('a) == 'a * 'a»\n\nexample of \"\"\"\ntype foo = Bar | Qux\nlet double n = n * 2\n\"\"\"\n//│ > «type foo = Bar | Qux»\n//│ > «let double n = n * 2»\n\nexample of \"\"\"\ntype foo = Bar of int | Qux of int * int\n\"\"\"\n//│ > «type foo = Bar of int | Qux of int * int»\n\nexample of \"\"\"\n:tree\ntype 'a option = Some of 'a | None\n\"\"\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = App:\n//│ >         callee = Ident of \"option\"\n//│ >         argument = Tuple of Stack of \n//│ >           Ident of \"'a\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`|`, N/A, N/A)\n//│ >         lhs = Infix:\n//│ >           op = Keyword(`of`, N/A, N/A)\n//│ >           lhs = Ident of \"Some\"\n//│ >           rhs = Ident of \"'a\"\n//│ >         rhs = Ident of \"None\"\n//│ > «type option ('a) = Some of 'a | None»\n\nexample of \"\"\"\n:tree\ntype 'a tree = Leaf | Node of 'a tree * 'a * 'a tree\n\"\"\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = App:\n//│ >         callee = Ident of \"tree\"\n//│ >         argument = Tuple of Stack of \n//│ >           Ident of \"'a\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`|`, N/A, N/A)\n//│ >         lhs = Ident of \"Leaf\"\n//│ >         rhs = Infix:\n//│ >           op = Keyword(`of`, N/A, N/A)\n//│ >           lhs = Ident of \"Node\"\n//│ >           rhs = Infix:\n//│ >             op = Keyword(`*`, 22, 22)\n//│ >             lhs = Infix:\n//│ >               op = Keyword(`*`, 22, 22)\n//│ >               lhs = App:\n//│ >                 callee = Ident of \"tree\"\n//│ >                 argument = Ident of \"'a\"\n//│ >               rhs = Ident of \"'a\"\n//│ >             rhs = App:\n//│ >               callee = Ident of \"tree\"\n//│ >               argument = Ident of \"'a\"\n//│ > «type tree ('a) = Leaf | Node of tree 'a * 'a * tree 'a»\n\nexample of \"\"\"\ntype ('a, 'b) twist == a list * b list\n\"\"\"\n//│ > «type twist ('a, 'b) == list a * list b»\n\n\n// example of \"\"\"\n// type qux = Qux of { q : int; u: int; x :int }\n// \"\"\"\n\n// example of \"\"\"\n// type colour =\n//   | Red | Green | Blue | Yellow | Black | White\n//   | RGB of {r : int; g : int; b : int}\n// type 'a tree = Lf | Br of 'a * 'a tree * 'a;;\n// \"\"\"\n\nexample of \"\"\"\n:tree\ntype t = {decoration : string; substance : t'}\nand t' = Int of int | List of t list\n\"\"\"\n//│ > Define:\n//│ >   kind = Type\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Ident of \"t\"\n//│ >       rhs = Bracketed#Curly of Sequence of Stack of \n//│ >         Infix:\n//│ >           op = Keyword(`:`, 4, 3)\n//│ >           lhs = Ident of \"decoration\"\n//│ >           rhs = Ident of \"string\"\n//│ >         Infix:\n//│ >           op = Keyword(`:`, 4, 3)\n//│ >           lhs = Ident of \"substance\"\n//│ >           rhs = Ident of \"t'\"\n//│ >     Infix:\n//│ >       op = Keyword(`=`, 3, 3)\n//│ >       lhs = Ident of \"t'\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`|`, N/A, N/A)\n//│ >         lhs = Infix:\n//│ >           op = Keyword(`of`, N/A, N/A)\n//│ >           lhs = Ident of \"Int\"\n//│ >           rhs = Ident of \"int\"\n//│ >         rhs = Infix:\n//│ >           op = Keyword(`of`, N/A, N/A)\n//│ >           lhs = Ident of \"List\"\n//│ >           rhs = App:\n//│ >             callee = Ident of \"list\"\n//│ >             argument = Ident of \"t\"\n//│ > «type t = {decoration : string; substance : t'} and t' = Int of int | List of list t»\n\nexample of \"\"\"\ntype int_to_int == int -> int\n\"\"\"\n//│ > «type int_to_int == int -> int»\n\nexample of \"\"\"\n:tree\nexception E of int * string\n\"\"\"\n//│ > Define:\n//│ >   kind = Exception\n//│ >   items = Stack of \n//│ >     Infix:\n//│ >       op = Keyword(`of`, N/A, N/A)\n//│ >       lhs = Ident of \"E\"\n//│ >       rhs = Infix:\n//│ >         op = Keyword(`*`, 22, 22)\n//│ >         lhs = Ident of \"int\"\n//│ >         rhs = Ident of \"string\"\n//│ > «exception E of int * string»\n\nexample of \"\"\"\ntype 'a bst = E | N of 'a * 'a bst * 'a bst\nlet rec insert x = function\n  | E -> N (x, E, E)\n  | N (y, l, r) ->\n      if x < y then N (y, insert x l, r)\n      else N (y, l, insert x r)\nlet rec min_elt = function\n  | E -> failwith \"min_elt called on empty tree\"\n  | N (x, E, _) -> x\n  | N (_, l, _) -> min_elt l\nlet rec remove x = function\n  | E -> E\n  | N (y, l, r) ->\n      if x < y then N (y, remove x l, r)\n      else if x > y then N (y, l, remove x r)\n      else\n        match (l, r) with\n        | (E, _) -> r\n        | (_, E) -> l\n        | _ ->\n            let m = min_elt r in\n            N (m, l, remove m r)\n\"\"\"\n//│ > «type bst ('a) = E | N of 'a * bst 'a * bst 'a»\n//│ > «let insert x = function E -> N (x, E, E) | N (y, l, r) -> if x < y then N (y, insert x l, r) then N (y, l, insert x r)»\n//│ > «let min_elt = function E -> failwith \"min_e…\" | N (x, E, _) -> x | N (_, l, _) -> min_elt l»\n//│ > «let remove x = function E -> E | N (y, l, r) -> if x < y then N (y, remove x l, r) then if x > y then N (y, l, remove x r) then match (l, r) with (E, _) -> r | (_, E) -> l | _ -> let m = min_elt r in N (m, l, remove m r)»\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/apps/parsing-web-demo/ExamplesTest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/MutMap.mls\"\nimport \"../../../mlscript-compile/apps/parsing/Test.mls\"\nimport \"../../../mlscript-compile/apps/parsing-web-demo/Examples.mls\"\n\n:silent\nval examples = (Examples.examples |> MutMap.values).sort of\n  (a, b) => a.name.localeCompare(b.name)\n\nexamples Iter.each of case entry then\n  print of \"Testing example: \" + entry.name\n  Test.example of entry.source\n//│ > Testing example: Extensible Syntax\n//│ > «baz (foo \"Rob\" (foo \"Bob\" bar))»\n//│ > «#diagram \"\"»\n//│ > Testing example: Hanoi from Caml Light\n//│ > «let spaces n = make_string n \" \"»\n//│ > «let disk size = let right_half = make_string size \">\" and left_half = make_string size \"<\" in left_half ^ \"|\" ^ right_half»\n//│ > «let disk_number n largest_disk_size = let white_part = spaces (largest_disk_size + 1 - n) in white_part ^ disk n ^ white_part»\n//│ > «let peg_base largest_disk_size = let half = make_string largest_disk_size \"_\" in \" \" ^ half ^ \"|\" ^ half ^ \" \"»\n//│ > «let peg largest_disk_size = function (0, []) -> [] | (0, head :: rest) -> disk_number head largest_disk_size :: peg largest_disk_size (0, rest) | (offset, lst) -> disk_number 0 largest_disk_size :: peg largest_disk_size (offset - 1, lst)»\n//│ > «let join_lines l1 l2 l3 = match (l1, l2, l3) with ([], [], []) -> [] | (t1 :: r1, t2 :: r2, t3 :: r3) -> t1 ^ t2 ^ t3 :: join_lines r1 r2 r3 | _ -> failwith \"join_…\"»\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/DestructuringBindings.mls",
    "content": ":js\n:todo\n\n\n[a, b] => [b, a]\n//│ ╔══[COMPILATION ERROR] Illegal constraint syntax.\n//│ ║  l.5: \t[a, b] => [b, a]\n//│ ╙──     \t ^\n//│ ╔══[COMPILATION ERROR] Illegal constraint syntax.\n//│ ║  l.5: \t[a, b] => [b, a]\n//│ ╙──     \t    ^\n//│ ╔══[COMPILATION ERROR] Name not found: b\n//│ ║  l.5: \t[a, b] => [b, a]\n//│ ╙──     \t           ^\n//│ ╔══[COMPILATION ERROR] Name not found: a\n//│ ║  l.5: \t[a, b] => [b, a]\n//│ ╙──     \t              ^\n//│ /!!!\\ Uncaught error: scala.MatchError: Constrained(List(),Tup(List(Fld(‹›,Error,None), Fld(‹›,Error,None)))) (of class hkmc2.semantics.Term$Constrained)\n\nfun eqTup2([a, b], [c, d]) = a == c and b == d\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found tuple\n//│ ║  l.20: \tfun eqTup2([a, b], [c, d]) = a == c and b == d\n//│ ╙──      \t           ^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found tuple\n//│ ║  l.20: \tfun eqTup2([a, b], [c, d]) = a == c and b == d\n//│ ╙──      \t                   ^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: a\n//│ ║  l.20: \tfun eqTup2([a, b], [c, d]) = a == c and b == d\n//│ ╙──      \t                             ^\n//│ ╔══[COMPILATION ERROR] Name not found: c\n//│ ║  l.20: \tfun eqTup2([a, b], [c, d]) = a == c and b == d\n//│ ╙──      \t                                  ^\n//│ ╔══[COMPILATION ERROR] Name not found: b\n//│ ║  l.20: \tfun eqTup2([a, b], [c, d]) = a == c and b == d\n//│ ╙──      \t                                        ^\n//│ ╔══[COMPILATION ERROR] Name not found: d\n//│ ║  l.20: \tfun eqTup2([a, b], [c, d]) = a == c and b == d\n//│ ╙──      \t                                             ^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/ExplicitLabels.mls",
    "content": ":js\n:ignore\n\n\n// TODO: would be nice to be able to define our own labels with the following syntax\n\n\nlet x = 0\n//│ x = 0\n\ndo label:\n  if x == 0 do label.break 42\n  print(\"Not zero!\")\n  x\n//│ ╔══[PARSE ERROR] Unexpected literal here\n//│ ║  l.12: \t  if x == 0 do label.break 42\n//│ ╙──      \t                           ^^\n//│ ╔══[COMPILATION ERROR] Name not found: label\n//│ ║  l.12: \t  if x == 0 do label.break 42\n//│ ╙──      \t               ^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nlet i = 10 in do\n  label1:\n    if i <= 0 do label1.break ()\n    print(\"Still > 0:\", i)\n    set i -= 1\n  label2: // this is implicitly nested in label1\n    label1.continue\n//│ ╔══[COMPILATION ERROR] Name not found: label1\n//│ ║  l.26: \t    if i <= 0 do label1.break ()\n//│ ╙──      \t                 ^^^^^^\n//│ > Still > 0: 10\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'continue' yielded 'undefined'\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/ForLLM.mls",
    "content": ":js\n\n// Instruction for agent: for each test case you solve, move it to its own test file outside of the `backlog` folder\n\n\n// ——— ——— ———\n// Bug: `pattern do body` inside `is` expression is not handled.\n// The root cause is at the parser level: in `Some of [process, rest] do \"hi\"`,\n// the `of` keyword greedily includes `do \"hi\"` inside the constructor argument,\n// producing `App(Some, Tup([InfixApp(Tup([process, rest]), do, \"hi\")]))`.\n// In `if`/`case`/`while` splits, the parser treats `do` as a split boundary\n// at the branch level, so it correctly separates pattern from consequent. But\n// in standalone `is` expressions, the block lines are parsed as regular\n// expressions, so `do` is parsed as an infix operator inside the constructor's\n// argument. Fixing this would require the parser to switch to a split-like\n// parsing mode for `is` RHS blocks, which is a significant refactoring.\n\nclass Some(val v)\n\n:fixme\nSome(1) is\n  Some of [process, rest] do \"hi\"\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (infix operator 'do').\n//│ ║  l.22: \t  Some of [process, rest] do \"hi\"\n//│ ╙──      \t          ^^^^^^^^^^^^^^^^^^^^^^^\n//│ = true\n\n// ——— ——— ———\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/Lifter.mls",
    "content": ":js\n:lift\n:ignore\n\n// The following are problems with lifting classes inside other definitions.\n\n// We use the optional `symbol` parameter of `Select` to detect references to the\n// BlockMemberSymbol. But when this symbol is not present, there is no way to properly\n// detect it.\n// \n// The following could instead be lifted as:\n//\n// class B$(y)(a) with\n//   fun getB() = a.x + y\n// class A(x) with\n//   fun B(y) = B$(y)(this)\n//   set B.class = B // so that `new a.B(n)` still works\n//   fun getA() = this.B(2).getB()\n// A(1).getA()\n//\n// where B must be marked as final.\n:expect 3\ndata class A(x) with\n  data class B(y) with\n    fun getB() = x + y\n  fun getA() = \n    // NOTE: The Term.Resolved PR made it so `this.B` gets resolved correctly.\n    // Explicitly binding `t = this` reproduces the previous error\n    let t = this\n    t.B(2).getB()\nA(1).getA()\n//│ ═══[RUNTIME ERROR] TypeError: t.B is not a function\n//│ ═══[RUNTIME ERROR] Expected: '3', got: 'undefined'\n\n// This is due to the order of classes after lifting\nclass Test\nfun hello() =\n  class Test2 extends Test\n  new Test2\n//│ ═══[RUNTIME ERROR] TypeError: Class extends value undefined is not a constructor or null\n\n// This is due to subclasses not calling `super` with the required locals. The analysis to\n// determine which locals are required is not in place yet.\n:expect 2\nfun test(x) =\n  class A with\n    fun get = x\n  class B() extends A\n  B().get\ntest(2)\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'get' yielded 'undefined'\n//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined'\n\n// This is due to `super` not being called with multiple parameter lists.\n:expect \"B()\"\nfun test(x) =\n  class A() with\n    fun get = x\n  class B() extends A() with\n    fun bar = x\n  B()\ntest(0).toString()\n//│ ═══[RUNTIME ERROR] Expected: '\"B()\"', got: '\"(x1) => {       this.#x = x1;       return this;     }\"'\n//│ = \"(x1) => {       this.#x = x1;       return this;     }\"\n\n// In fact, the correct way (using the current \"constructor returns a lambda\" hack) is this:\n// return (params) => {\n//   let ret = super(parentMainParams)(parentAuxParams);\n//   // ctor\n//   return ret;\n// }\n\n/// The following are related to first-class classes, instance checks, and private fields. ///\n\n:expect 1\nfun f(used1, unused1) =\n  fun g(g_arg) =\n    let used3 = 2\n    fun h = used3\n    used1 + h\n  let unused2 = 2\n  class Test(a) with\n    fun get() = used1\n  let foo = Test\n  foo(unused1)\nf(1, 2).get()\n//│ = 1\n\n\n:todo\n:w\nfun foo1(x, n) =\n  class C()\n  let res = if x is C then \"Y\" else \"N\"\n  if n > 0 then res + foo1(C(), n - 1) else \"\"\n//│ ═══[WARNING] Cannot yet lift class/module `C` as it is used in an instance check.\n\nfun foo2() =\n  class C()\n  C\n\n:w\nfun foo3() =\n  class C\n  fun f = new C\n  C\n//│ ═══[WARNING] Cannot yet lift class `C` as it is used as a first-class class.\n\n:expect \"NN\"\nfoo1(0, 2)\n//│ = \"NN\"\n\n// Since B extends A and A is not lifted, B cannot access A's BlockMemberSymbol. We can't lift B.\n:todo\nfun test(x) =\n  class A with\n    fun get = x\n  class B() extends A\n  0 is A\n  B().get\ntest(2)\n//│ ═══[WARNING] Cannot yet lift class/module `A` as it is used in an instance check.\n//│ ═══[WARNING] Cannot yet lift definition `B` as it extends an unliftable class.\n//│ = 2\n\n/// The following are related to modules and objects. ///\n\n:todo\nfun foo(x, y) =\n  module M with\n    val test = 2\n    fun foo() =\n      set y = 2\n      x + y + test\n  M.foo()\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.130: \t  module M with\n//│ ╙──       \t         ^\n\n:expect 14\nfoo(10, 0)\n//│ = 14\n\nfun foo(x, y) =\n  module M with\n    fun foo() =\n      set y = 2\n      x + y\n  fun foo = M.foo()\n  foo\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.145: \t  module M with\n//│ ╙──       \t         ^\n\n:expect 12\nfoo(10, 0)\n//│ = 12\n\n\ndata class A(x) with\n  module M with\n    fun getB() = x\n  fun getA() = M.getB()\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.161: \t  module M with\n//│ ╙──       \t         ^\n\n:expect 2\nA(2).getA()\n//│ = 2\n\n// TODO: Foo needs to be put in a mutable capture. Also, we need to pass the Foo instance itself into Foo\nfun foo(x) =\n  object Foo with\n    fun self1 = this\n    fun self2 = Foo\n  class Bar extends Foo\n  (new Bar).self2\nfoo(2)\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference of type Foo.\n//│ ║  l.177: \t  class Bar extends Foo\n//│ ║         \t                    ^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.174: \t  object Foo with\n//│ ╙──       \t         ^^^\n//│ ═══[WARNING] Cannot yet lift definition `Bar` as it extends an expression.\n//│ ═══[RUNTIME ERROR] TypeError: Class extends value [object Object] is not a constructor or null\n\n// `h` is lifted out, but then cannot access the BlockMemberSymbol M.\n:fixme\n:noInline\n:w\nfun f =\n  module M with\n    fun g =\n      fun h = M.g\n      h\n  M.g\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.195: \t  module M with\n//│ ╙──       \t         ^\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'M'\n//│ ║  l.197: \t      fun h = M.g\n//│ ║         \t              ^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.195: \t  module M with\n//│ ║         \t         ^^^^^^\n//│ ║  l.196: \t    fun g =\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.197: \t      fun h = M.g\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ║  l.198: \t      h\n//│ ╙──       \t^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/NewWith.mls",
    "content": ":js\n\n\n:pe\n:re\nnew\n//│ ╔══[PARSE ERROR] Expected 'with' keyword, expression, or block after `new` keyword; found end of input instead\n//│ ║  l.6: \tnew\n//│ ╙──     \t   ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nnew Object\n//│ = {}\n\n:pe\n:re\nnew with\n//│ ╔══[PARSE ERROR] Expected block after 'new' body; found end of input instead\n//│ ║  l.17: \tnew with\n//│ ╙──      \t        ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:pe\n:re\nnew Object with\n//│ ╔══[PARSE ERROR] Expected block after 'new' body; found end of input instead\n//│ ║  l.25: \tnew Object with\n//│ ╙──      \t               ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:pe\n:re\nnew Object with 1\n//│ ╔══[PARSE ERROR] Expected block after 'new' body; found literal instead\n//│ ║  l.33: \tnew Object with 1\n//│ ╙──      \t                ^\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.33: \tnew Object with 1\n//│ ╙──      \t                ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n(new Object) with 1\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'with' here\n//│ ║  l.43: \t(new Object) with 1\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// TODO don't show as `$anon`\nnew Object with { val x = 1 }\n//│ = $anon { x: 1 }\n\n:e\nnew Object with { val x = 1 } with { val y = 1 }\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'with' here\n//│ ║  l.54: \tnew Object with { val x = 1 } with { val y = 1 }\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nlet obj =\n  new Object with\n    val x = 12\n//│ obj = $anon { x: 12 }\n\nobj.x\n//│ = 12\n\n\nlet n =\n  new with\n    val x = 12\n//│ n = $anon { x: 12 }\n\nn.x\n//│ = 12\n\n\nclass Foo(x) with\n  fun foo = x + 1\n  print(\"Foo\", x, foo)\n\nnew Foo(123) with { fun foo = 27 }\n//│ > Foo 123 27\n//│ = $anon\n\n:e\n:re\nnew (Foo(123)) with { fun foo = 27 }\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found application of type Foo.\n//│ ║  l.89: \tnew (Foo(123)) with { fun foo = 27 }\n//│ ║        \t     ^^^^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ > Foo 123 124\n//│ ═══[RUNTIME ERROR] TypeError: Class extends value [object Object] is not a constructor or null\n\n:e\nnew! (Foo(123)) with { fun foo = 27 }\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'with' here\n//│ ║  l.98: \tnew! (Foo(123)) with { fun foo = 27 }\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n:re\nnew {Foo(123)} with { fun foo = 27 }\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found application of type Foo.\n//│ ║  l.106: \tnew {Foo(123)} with { fun foo = 27 }\n//│ ║         \t     ^^^^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ > Foo 123 124\n//│ ═══[RUNTIME ERROR] TypeError: Class extends value [object Object] is not a constructor or null\n\nnew Foo(123) with\n  // fun foo = super.foo + 1 // TODO (super)\n  fun foo = 27\n  print(\"Bar\", foo)\n//│ > Foo 123 27\n//│ > Bar 27\n//│ = $anon\n\n:e\nnew Foo(123) with 1\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'with' here\n//│ ║  l.123: \tnew Foo(123) with 1\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/NonReturningStatements.mls",
    "content": ":js\n\n\n// TODO `fun` does not return anything; the returned value should be the result of `bar + 1`\nfun foo =\n  bar + 1\n  fun bar = 1\n\nfoo\n\n\nfun foo =\n  print(bar)\n  fun bar = 1\n\nfoo\n//│ > 1\n\n\n// TODO maybe warn that this can be confusing: one might think that `bar` is the one defined above\nfun bar = 0\nfun foo =\n  print(bar)\n  \n  \n  print(\"...\")\n  \n  \n  fun bar = 1\n\n:sjs\nfoo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ foo2()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n//│ > ...\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/OfStatements.mls",
    "content": ":js\n:todo\n\n\nprint of\n  let x = 1\n  x + 1\n//│ ╔══[COMPILATION ERROR] Expected a body for let bindings in expression position\n//│ ║  l.6: \t  let x = 1\n//│ ╙──     \t      ^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.7: \t  x + 1\n//│ ╙──     \t  ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nprint of \n  open Predef\n  let x = 1\n  x + 1\n//│ ╔══[COMPILATION ERROR] Illegal position for 'open' statement.\n//│ ║  l.17: \t  open Predef\n//│ ╙──      \t  ^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected a body for let bindings in expression position\n//│ ║  l.18: \t  let x = 1\n//│ ╙──      \t      ^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.19: \t  x + 1\n//│ ╙──      \t  ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/ToTriage.mls",
    "content": ":js\n:ignore\n\n\n// ——— ——— ———\n\n// Too hard for Claude\n\n// FIXME: Printing of\n[..[], \"a\"]\n//│ = [a]\n// It should print the same as:\n[\"a\"]\n//│ = [\"a\"]\n\n// ——— ——— ———\n\n:breakme // TODO instrument Predef\n:re\nid(1, 2)\n//│ ╔══[COMPILATION ERROR] Expected 1 arguments, got 2\n//│ ║  l.20: \tid(1, 2)\n//│ ╙──      \t  ^^^^^^\n//│ = 1\n\n// ——— ——— ———\n\n:breakme // TODO confusing formatting should not be allowed\n:e\nlet x = if true\nthen 1\nelse 0\n//│ x = 1\n\n// ——— ——— ———\n\nInfinity\n//│ = Infinity\n\n:sjs\nval Infinity = 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Infinity; Infinity = 1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[COMPILATION ERROR] [Uncaught SyntaxError] Identifier 'Infinity' has already been declared\n//│ Infinity = Infinity\n\n:sjs\nInfinity\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Infinity\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Infinity\n\nmodule Test with\n  val Infinity = 1\n\nTest.Infinity\n//│ = 1\n\n// ——— ——— ———\n\n// TODO forbid declarations inside local blocks\n:breakme\n:e\nfun main() =\n  declare fun foo: Int\n  ()\n\n// TODO forbid unimplemented signatures inside local blocks\n:breakme\n:e\nfun main() =\n  fun bar: Int\n  ()\n\n// ——— ——— ———\n\n// * Objects should not be allowed to have parameters...\n// * Or these parameters should have default values.\n\n:sjs\nobject Cls(val x) with\n  fun huh = x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Cls1;\n//│ (class Cls {\n//│   static {\n//│     new this\n//│   }\n//│   constructor(x1) {\n//│     Cls1 = this;\n//│     this.x = x1;\n//│     Object.defineProperty(this, \"class\", {\n//│       value: Cls\n//│     });\n//│     globalThis.Object.freeze(this);\n//│   }\n//│   get huh() {\n//│     return this.x;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"object\", \"Cls\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:e\nCls.x\n//│ ╔══[COMPILATION ERROR] Object 'Cls' does not contain member 'x'\n//│ ║  l.108: \tCls.x\n//│ ╙──       \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n// * Note: the access is not checked because the selection is resolved\n// * (to an MLscript definition, which is not supposed to return `undefined`).\nprint(Cls.huh)\n//│ > undefined\n\nlet c = new Cls(123)\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference of type Cls.\n//│ ║  l.119: \tlet c = new Cls(123)\n//│ ║         \t            ^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: Cls1 is not a constructor\n//│ c = undefined\n\nc.x\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'x')\n\n// ——— ——— ———\n\n:breakme // TODO: warn against using `undefined`\n:w\nfun oops = undefined\n\n:re\noops\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n\n// ——— ——— ———\n\nclass C\n\n:sjs\nclass D extends id(C)\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found selection.\n//│ ║  l.145: \tclass D extends id(C)\n//│ ║         \t                ^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let D1;\n//│ (class D extends Predef.id {\n//│   static {\n//│     D1 = this\n//│   }\n//│   constructor() {\n//│     super(C1);\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"D\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Class extends value id(x) {\n//│     return x\n//│   } is not a constructor or null\n\n// ——— ——— ———\n\nlet x = 0\n//│ x = 0\n\n// This somehow parses as `set (x += 1; ())`\n:fixme\nset x += 1; ()\n//│ ╔══[COMPILATION ERROR] Expected a right-hand side for this assignment\n//│ ║  l.174: \tset x += 1; ()\n//│ ╙──       \t    ^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nset (x += 1; ())\n//│ ╔══[COMPILATION ERROR] Expected a right-hand side for this assignment\n//│ ║  l.181: \tset (x += 1; ())\n//│ ╙──       \t    ^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n(set x += 1); ()\n\n:fixme\n[x, set x += 1; x]\n//│ ╔══[COMPILATION ERROR] Expected a right-hand side for this assignment\n//│ ║  l.190: \t[x, set x += 1; x]\n//│ ╙──       \t        ^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// ——— ——— ———\n\nimport \"../../mlscript-compile/Stack.mls\"\n\n// The parser rejects this, but it should be allowed.\nopen Stack { ::, Nil }\n//│ ╔══[COMPILATION ERROR] Illegal 'open' statement shape.\n//│ ║  l.201: \topen Stack { ::, Nil }\n//│ ╙──       \t     ^^^^^^^^^^^^^^^\n\n// Instead, if we parenthesize the operator, it is rejected by the elaborator.\nopen Stack { (::), Nil }\n//│ ╔══[COMPILATION ERROR] Illegal 'open' statement element.\n//│ ║  l.207: \topen Stack { (::), Nil }\n//│ ╙──       \t             ^^^^\n\nopen Stack { Nil, :: }\n\n:sjs\n1 :: Nil\n//│ ╔══[COMPILATION ERROR] Module 'Stack' does not contain member '::'\n//│ ║  l.215: \t1 :: Nil\n//│ ╙──       \t  ^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(Stack[\"::\"](1, Stack.Nil))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Stack.:: is not a function\n\n// ——— ——— ———\n\ndata class Foo(x, y)\n\n// TODO missing sanity check\n:re\nid(Foo)(1)\n//│ = Foo(1, undefined)\n\n// ——— ——— ———\n\ndata class FooSpd(...args)\n//│ ╔══[INTERNAL ERROR] Compiler reached an unsupported state: mismatched param list lengths List() vs List(term:FooSpd/args)\n//│ ╟── The compilation result may be incorrect.\n//│ ╙── This is a known compiler limitation; if it is a blocker for you, please report it to the maintainers.\n\nFooSpd(1, 2, 3).args\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'args' yielded 'undefined'\n\n:todo\nif FooSpd(1, 2, 3) is FooSpd(...args) then args\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (spread).\n//│ ║  l.244: \tif FooSpd(1, 2, 3) is FooSpd(...args) then args\n//│ ╙──       \t                             ^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: args\n//│ ║  l.244: \tif FooSpd(1, 2, 3) is FooSpd(...args) then args\n//│ ╙──       \t                                           ^^^^\n//│ ╔══[COMPILATION ERROR] The constructor does not take any arguments but found one argument.\n//│ ║  l.244: \tif FooSpd(1, 2, 3) is FooSpd(...args) then args\n//│ ╙──       \t                      ^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\nif FooSpd(1, 2, 3) is FooSpd(a, b, c) then [a, b, c]\n//│ ╔══[COMPILATION ERROR] The constructor does not take any arguments but found three arguments.\n//│ ║  l.256: \tif FooSpd(1, 2, 3) is FooSpd(a, b, c) then [a, b, c]\n//│ ╙──       \t                             ^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\nif FooSpd(1, 2, 3) is FooSpd(arg) then arg\n//│ ╔══[COMPILATION ERROR] The constructor does not take any arguments but found one argument.\n//│ ║  l.262: \tif FooSpd(1, 2, 3) is FooSpd(arg) then arg\n//│ ╙──       \t                             ^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n// ——— ——— ———\n\n// To add to `mlscript/basics/LetBindings.mls`\nfun foo() =\n  let bar(x: Str): Str = x + x\n  bar(\"test\")\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.272: \t  let bar(x: Str): Str = x + x\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: bar\n//│ ║  l.273: \t  bar(\"test\")\n//│ ╙──       \t  ^^^\n\n// ——— ——— ———\n\n:breakme\nmodule Foo(x)\n\n:fixme // proper compilation error\n:sjs\nmodule Foo(x) with\n  print(x)\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'x'\n//│ ╟── which references the symbol introduced here\n//│ ║  l.288: \tmodule Foo(x) with\n//│ ╙──       \t           ^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo5;\n//│ (class Foo4 {\n//│   static {\n//│     Foo5 = this\n//│   }\n//│   static #x;\n//│   static {\n//│     Foo4.#x = x;\n//│     Predef.print(Foo4.#x);\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n\n:fixme // proper compilation error\n:sjs\nmodule Foo(val x)\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'x'\n//│ ╟── which references the symbol introduced here\n//│ ║  l.313: \tmodule Foo(val x)\n//│ ╙──       \t               ^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo7;\n//│ (class Foo6 {\n//│   static {\n//│     Foo7 = this\n//│   }\n//│   static {\n//│     this.x = x;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// ——— ——— ———\n\n// TODO support syntax?\ndata class Foo(mut x)\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found 'mut'-modified identifier\n//│ ║  l.335: \tdata class Foo(mut x)\n//│ ╙──       \t                   ^\n\n// ——— ——— ———\n\n// FIXME should report an error\nfun Foo\nclass Foo\n\n// ——— ——— ———\n\n// * TODO: improve errors (don't cascade meaningless errors)\n:e\nclass Id(name: UnboundName)\n//│ ╔══[COMPILATION ERROR] Name not found: UnboundName\n//│ ║  l.350: \tclass Id(name: UnboundName)\n//│ ╙──       \t               ^^^^^^^^^^^\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n\n// ——— ——— ———\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/backlog/UCS.mls",
    "content": ":js\n:ignore\n\n\n// ——— ——— ———\n\n// * Example confusing parses that should be fixed when we fix the parsing of operator splits\n\nif 1 + 0\n    == 0 then \"X\"\n    == 1 then \"A\"\n//│ = \"A\"\n\nif 1 + 1\n    * 2 == 4 then \"X\"\n    * 2 == 1 then \"A\"\n    |> id is r then r\n//│ ╔══[PARSE ERROR] Operator cannot be used inside this operator split\n//│ ║  l.15: \t    * 2 == 4 then \"X\"\n//│ ║        \t        ^^\n//│ ╟── as it has lower precedence than the splitting operator here\n//│ ║  l.15: \t    * 2 == 4 then \"X\"\n//│ ╙──      \t    ^\n//│ ╔══[PARSE ERROR] Unexpected literal in this operator split inner position\n//│ ║  l.15: \t    * 2 == 4 then \"X\"\n//│ ║        \t           ^\n//│ ╟── Note: the operator split starts here\n//│ ║  l.15: \t    * 2 == 4 then \"X\"\n//│ ╙──      \t    ^\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.15: \t    * 2 == 4 then \"X\"\n//│ ╙──      \t           ^\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (integer literal)\n//│ ║  l.15: \t    * 2 == 4 then \"X\"\n//│ ╙──      \t      ^\n//│ ═══[COMPILATION ERROR] Unrecognized term split (reference term)\n//│ ═══[RUNTIME ERROR] Error: match error\n\n// ——— ——— ———\n\nclass Some(val v)\nobject None\n\n// :ucs normalized\n// Uncomment the line above to see the explosion: ~1200 lines of code.\n// If the number of branches continues to increase, the time duration of\n// compilation will noticeably slow down.\nfun parse(text: Str): [Int, Str] =\n  fun char(idx: Int) = if idx < text.length then\n    Some of text.charAt of idx\n  else\n    None\n  \n  // Some helper parsing utilities.\n  fun a(idx: Int): [Int, Str] = ???\n  fun b(idx: Int): [Int, Str] = ???\n  fun c(idx: Int): [Int, Str] = ???\n  fun d(idx: Int): [Int, Str] = ???\n  fun e(idx: Int): [Int, Str] = ???\n  fun f(idx: Int): [Int, Str] = ???\n  fun g(idx: Int): [Int, Str] = ???\n  \n  // Note: Use `is` instead `==` can mitigate the explosion. Because the\n  // specialization knows those literal string patterns are disjoint.\n  fun launch(idx: Int) = if char(idx) is Some(ch) and ch ==\n    \"a\" and a(idx + 1) is [idx', res] then ???\n    \"b\" and b(idx + 1) is [idx', res'] then ???\n    \"c\" and c(idx + 1) is [idx', res''] then ???\n    \"d\" and d(idx + 1) is [idx', res'''] then ???\n    \"e\" and e(idx + 1) is [idx', res''''] then ???\n    \"f\" and f(idx + 1) is [idx', res'''''] then ???\n    \"g\" and g(idx + 1) is [idx', res'''''''] then ???\n    else [idx, \"\"]\n  \n  launch(0)\n\n// ——— ——— ———\n\ndata class Tuple(a, b, c)\n\nlet foo =\n  case\n    Tuple(...elements) then elements\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (spread).\n//│ ║  l.83: \t    Tuple(...elements) then elements\n//│ ╙──      \t          ^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: elements\n//│ ║  l.83: \t    Tuple(...elements) then elements\n//│ ╙──      \t                            ^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected three arguments, but found only one argument.\n//│ ║  l.83: \t    Tuple(...elements) then elements\n//│ ╙──      \t    ^^^^^\n//│ foo = fun foo\n\nfoo(Tuple(1, 2, 3))\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// ——— ——— ———\n\nmodule Foo with\n  class\n    Bar\n    Baz\n\nfun foo(x) = if x is Foo.\n  Bar then \"Bar\"\n  Foo then \"Foo\"\n//│ ╔══[PARSE ERROR] Expected end of input; found period instead\n//│ ║  l.105: \tfun foo(x) = if x is Foo.\n//│ ╙──       \t                        ^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (identifier).\n//│ ║  l.105: \tfun foo(x) = if x is Foo.\n//│ ╙──       \t                     ^^^\n\nfun foo(x) = if x is Foo\n  .Bar then \"Bar\"\n  .Foo then \"Foo\"\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (operator split).\n//│ ║  l.115: \tfun foo(x) = if x is Foo\n//│ ║         \t                     ^^^\n//│ ║  l.116: \t  .Bar then \"Bar\"\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ║  l.117: \t  .Foo then \"Foo\"\n//│ ╙──       \t^^^^^^^^^^^^^^^^^\n\n// ——— ——— ———\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ADTs.mls",
    "content": ":js\n:ignore\n\n\n// * Standard syntax of ADTs (TODO)\n\nclass Expr\n  constructor Lit(n: Int)\n  constructor Add(lhs: Expr, rhs: Expr)\n//│ ╔══[PARSE ERROR] Expected end of input; found indented block instead\n//│ ║  l.8: \t  constructor Lit(n: Int)\n//│ ╙──     \t^^\n\nclass Expr[A] with\n  constructor\n    Lit(n: Int) { A = Int }\n    Add(lhs: Expr[Int], rhs: Expr[Int]) { A = Int }\n//│ ═══[COMPILATION ERROR] Expected a valid class definition head; found ‹erroneous syntax› instead\n//│ ═══[COMPILATION ERROR] Expected a valid class definition head; found ‹erroneous syntax› instead\n\n\n// * one can also go the TypeScript way\n\ndata class Lit(n: Int)\ndata class Add(lhs: Expr, rhs: Expr)\ntype Expr = Lit | Add\n\n\n// * Which could get a \"blessed\" shorthand syntax as well\n\nenum Expr =\n  | Lit(n: Int)\n  | Add(lhs: Expr, rhs: Expr)\n//│ ╔══[COMPILATION ERROR] Unrecognized definitional assignment left-hand side: juxtaposition\n//│ ║  l.31: \tenum Expr =\n//│ ╙──      \t^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/AppOp.mls",
    "content": ":js\n\n\nid @ 123\n//│ = 123\n\nid@123\n//│ = 123\n\n\nfun inc(n) = n + 1\n\ninc @ 1\n//│ = 2\n\n:re\ninc @ inc @ 1\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\ninc @ (inc @ 1)\n//│ = 3\n\ninc of inc @ 1\n//│ = 3\n\ninc @ inc of 1\n//│ = 3\n\n\nfun add(l)(r) = l + r\n\nadd @ 1 @ 2\n//│ = 3\n\nadd@1@2\n//│ = 3\n\n\n@\n//│ = fun apply\n\n:sjs\n:fixme\n@(id, 123)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Predef.apply(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n(@)(id, 123)\n//│ = 123\n\n\n[tuple of 1, 2, 3]\n//│ = [[1, 2, 3]]\n\n[tuple @ 1, 2, 3]\n//│ = [[1], 2, 3]\n\n\nfun test(f) = f(42)\n\n// :dp\ntest @ x => x + 1\n//│ = 43\n\ntest @ (x) => x + 1\n//│ = 43\n\ntest @ (_ + 1)\n//│ = 43\n\ntest @ {_ + 1}\n//│ = 43\n\ntest @\n  _ + 1\n//│ = 43\n\n// * Note: this lambda shorthand includes the whole term, as `_ + 1` is not delimited/parenthesized\ntest @ _ + 1\n//│ = fun\n\n\npipeInto of 1, inc\n//│ = 2\n\n:re\npipeInto @ 1, inc\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\npipeInto(1, _) @ inc\n//│ = fun\n\n(pipeInto(1, _)) @ inc\n//│ = 2\n\n(pipeInto of 1, _) @ inc\n//│ = 2\n\n1 pipeInto(inc)\n//│ = 2\n\n// * Indeed should not work...\n// * application shorthand needs an actual application on the right-hand side\n:e\n:re\n1 pipeInto @ inc\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (identifier).\n//│ ║  l.108: \t1 pipeInto @ inc\n//│ ╙──       \t  ^^^^^^^^\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n(1 pipeInto(_)) @ inc\n//│ = 2\n\n\n// * Another argument for using `.` rather than juxtaposition\n1 \\pipeInto @ inc\n//│ = 2\n\n// * This is a bit surprising... parses as `(inc @ (1 . pipeInto)) @ inc`\n:re\ninc @ 1 \\pipeInto @ inc\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n(inc @ 1) \\pipeInto @ inc\n//│ = 3\n\n\n// * Now `of` has the same left-binding power as normal application\n1 \\pipeInto of inc\n//│ = 2\n\n(1 \\pipeInto) of inc\n//│ = 2\n\n\nlet n = inc of 42\n//│ n = 43\n\nn \\pipeInto @ inc\n//│ = 44\n\nn\n  \\pipeInto @ inc\n  \\pipeInto @ inc\n//│ = 45\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Assert.mls",
    "content": ":js\n\n\nlet xs = [1, 2, 3]\n//│ xs = [1, 2, 3]\n\n:sjs\nassert true\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut;\n//│ scrut = true;\n//│ if (scrut === true) {\n//│   runtime.Unit\n//│ } else { runtime.safeCall(runtime.assertFail(\"Assert.mls\", \"9\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:re\nassert false\n//│ ═══[RUNTIME ERROR] Error: Assertion failed (Assert.mls:19)\n\nassert xs is Array\n\n\n// * FIXME: Error-prone!!\n:sjs\n:fixme\nassert(true); 123\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut2;\n//│ scrut2 = (true , 123);\n//│ if (scrut2 === true) {\n//│   runtime.Unit\n//│ } else { runtime.safeCall(runtime.assertFail(\"Assert.mls\", \"28\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Assertion failed (Assert.mls:28)\n\n// * FIXME: the `else` is parsed as part of the `assert`!\n:sjs\n:fixme\nif 1 is\n  2 then assert true\n  else 3\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut3, scrut4;\n//│ scrut3 = 1;\n//│ if (scrut3 === 2) {\n//│   scrut4 = true;\n//│   if (scrut4 === true) {\n//│     runtime.Unit\n//│   } else { 3 }\n//│ } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\nassert true else 0\n1\n//│ = 1\n\nassert false else 0\n1\n//│ = 0\n\n\nassert xs is [1, ...ys] else []\nys\n//│ = [2, 3]\n\nassert xs is [2, ...ys] else []\nys\n//│ = []\n\n\n(assert true else 2) + 3\n//│ = \"()3\"\n\n(assert true else 2, 1) + 3\n//│ = 4\n\n(assert false else 2, 1) + 3\n//│ = 5\n\n:re\n(assert false else throw Error(\"whoops\")) + 3\n//│ ═══[RUNTIME ERROR] Error: whoops\n\n\nfun test(arg) =\n  assert arg is [l, r] else arg\n  [l + r]\n\ntest([2, 3])\n//│ = [5]\n\ntest([1])\n//│ = [1]\n\n\nimport \"../../mlscript-compile/Option.mls\"\nopen Option\n\n\nfun sumOpts(arg1, arg2) =\n  assert arg1 is Some(arg1) and arg2 is Some(arg2) else None\n  print(\"Both args are Some!\")\n  Some(arg1 + arg2)\n\nsumOpts(Some(2), Some(3))\n//│ > Both args are Some!\n//│ = Some(5)\n\nsumOpts(Some(2), None)\n//│ = None\n\nsumOpts(None, Some(3))\n//│ = None\n\nsumOpts(None, None)\n//│ = None\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadClasses.mls",
    "content": "\n\n// TODO should make better error messages!\n\n:e\nclass Foo { log(\"hi\") }\n//│ ╔══[COMPILATION ERROR] Invalid class definition head: unexpected block in this position\n//│ ║  l.6: \tclass Foo { log(\"hi\") }\n//│ ╙──     \t          ^^^^^^^^^^^^^\n\n:e\nclass Foo { 1 }\n//│ ╔══[COMPILATION ERROR] Invalid class definition head: unexpected block in this position\n//│ ║  l.12: \tclass Foo { 1 }\n//│ ╙──      \t          ^^^^^\n\n\n// * Note that these work:\n\n:w\nclass Foo with { 1 }\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.21: \tclass Foo with { 1 }\n//│ ╙──      \t                 ^\n\n:w\nclass Foo with\n  1\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.28: \t  1\n//│ ╙──      \t  ^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadDefs.mls",
    "content": ":js\n\n\nval (++) x = 0\n//│ ++ = 0\n//│ x = 0\n\nx\n//│ = 0\n\n++\n//│ = 0\n\n\n:sjs\nval ++ = 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let $_$_; $_$_ = 0;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ++ = 0\n\n:sjs\n++\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ $_$_\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:e\nval ++ y = 1\n//│ ╔══[COMPILATION ERROR] Invalid value definition head: unexpected identifier in this position\n//│ ║  l.31: \tval ++ y = 1\n//│ ╙──      \t       ^\n//│ ++ = 1\n\n:e\ny\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.38: \ty\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n++\n//│ = 1\n\n\n:e\nfun ++ z = 0\n//│ ╔══[COMPILATION ERROR] Invalid function definition head: unexpected identifier in this position\n//│ ║  l.49: \tfun ++ z = 0\n//│ ╙──      \t       ^\n\n:sjs\n++\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ $_$_2()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:e\nfun (class Lol) foo = 0\n//│ ╔══[COMPILATION ERROR] This type definition is not a valid symbolic name\n//│ ║  l.63: \tfun (class Lol) foo = 0\n//│ ╙──      \t     ^^^^^^^^^\n\nfoo\n//│ = 0\n\n:e\nLol\n//│ ╔══[COMPILATION ERROR] Name not found: Lol\n//│ ║  l.72: \tLol\n//│ ╙──      \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadMemberProjections.mls",
    "content": ":js\n\n\n:sjs\n:e\n1::x\n//│ ╔══[COMPILATION ERROR] Integer literal is not a known class.\n//│ ║  l.6: \t1::x\n//│ ║       \t^\n//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\n//│ ╙──   add a space before ‹identifier› to make it an operator application.\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found integer literal.\n//│ ║  l.6: \t1::x\n//│ ╙──     \t^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda;\n//│ lambda = (undefined, function (self, ...args) { return runtime.safeCall(self.x(...args)) });\n//│ lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n:ssjs\n:e\n:re\n1::x()\n//│ ╔══[COMPILATION ERROR] Integer literal is not a known class.\n//│ ║  l.25: \t1::x()\n//│ ║        \t^\n//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\n//│ ╙──   add a space before ‹identifier› to make it an operator application.\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found integer literal.\n//│ ║  l.25: \t1::x()\n//│ ╙──      \t^\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let lambda1;\n//│ lambda1 = (undefined, function (self, ...args) {\n//│   runtime.checkArgs(\"\", 1, false, arguments.length);\n//│   return runtime.safeCall(self.x(...args))\n//│ });\n//│ block$res2 = runtime.safeCall(lambda1());\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Function expected at least 1 argument but got 0\n\n\nfun (::) f(a, b) = [a, b]\n\nlet x = 1\n//│ x = 1\n\n\"A\" :: x\n//│ = [\"A\", 1]\n\n\"A\":: x\n//│ = [\"A\", 1]\n\n:e\n\"A\"::x\n//│ ╔══[COMPILATION ERROR] String literal is not a known class.\n//│ ║  l.58: \t\"A\"::x\n//│ ║        \t^^^\n//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\n//│ ╙──   add a space before ‹identifier› to make it an operator application.\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found string literal.\n//│ ║  l.58: \t\"A\"::x\n//│ ╙──      \t^^^\n//│ = fun\n\n:e\n\"A\" ::x\n//│ ╔══[COMPILATION ERROR] String literal is not a known class.\n//│ ║  l.70: \t\"A\" ::x\n//│ ║        \t^^^\n//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\n//│ ╙──   add a space before ‹identifier› to make it an operator application.\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found string literal.\n//│ ║  l.70: \t\"A\" ::x\n//│ ╙──      \t^^^\n//│ = fun\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadModuleUses.mls",
    "content": ":js\n\n\nmodule M with\n  fun mtd() = 42\n\n:e\nmodule Example with\n  fun foo(): module null = M\n//│ ╔══[COMPILATION ERROR] Expected a module type; found null literal.\n//│ ║  l.9: \t  fun foo(): module null = M\n//│ ║       \t                    ^^^^\n//│ ╙── Function marked as returning a 'module' must have a module return type.\n\nmodule Example with\n  fun foo(): module M = M\n\n:e\nlet m = Example.foo()\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful application of type M.\n//│ ║  l.19: \tlet m = Example.foo()\n//│ ╙──      \t        ^^^^^^^^^^^^^\n//│ m = class M\n\n:breakme // FIXME: should be an error\n:e\nid(m).mtd()\n//│ = 42\n\n\nExample.foo()\n//│ = class M\n\n:e\nid(Example.foo())\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful application of type M.\n//│ ║  l.35: \tid(Example.foo())\n//│ ║        \t   ^^^^^^^^^^^^^\n//│ ╙── Module argument passed to a non-module parameter.\n//│ = class M\n\nExample.foo().mtd()\n//│ = 42\n\n:e\nExample.foo() + 1\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful application of type M.\n//│ ║  l.46: \tExample.foo() + 1\n//│ ╙──      \t^^^^^^^^^^^^^\n//│ = \"class M {   static {     M1 = this   }   static mtd() {     runtime.checkArgs(\\\"mtd\\\", 0, true, arguments.length);     return 42   }   toString() { return runtime.render(this); }   static [definitionMetadata] = [\\\"class\\\", \\\"M\\\"];  }1\"\n\n:e\nM + 1\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.53: \tM + 1\n//│ ╙──      \t^\n//│ = \"class M {   static {     M1 = this   }   static mtd() {     runtime.checkArgs(\\\"mtd\\\", 0, true, arguments.length);     return 42   }   toString() { return runtime.render(this); }   static [definitionMetadata] = [\\\"class\\\", \\\"M\\\"];  }1\"\n\n:e\nM |> id\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.60: \tM |> id\n//│ ║        \t^\n//│ ╙── Module argument passed to a non-module parameter.\n//│ = class M\n\n:e\nid <| M\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.68: \tid <| M\n//│ ║        \t      ^\n//│ ╙── Module argument passed to a non-module parameter.\n//│ = class M\n\nfun (+) lol(a, b) = [a, b]\n\n:e\nM + 1\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.78: \tM + 1\n//│ ║        \t^\n//│ ╙── Module argument passed to a non-module parameter.\n//│ = [class M, 1]\n\n:e\nlet m = M\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.86: \tlet m = M\n//│ ╙──      \t        ^\n//│ m = class M\n\n\n:e\nmodule A with\n  fun f() = 2\nmodule B with\n  val a: module A = A\nprint(B.a)\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful selection of type A.\n//│ ║  l.98: \tprint(B.a)\n//│ ╙──      \t      ^^^\n//│ > class A\n\n\n:e\n:re\nid(module 1)\n//│ ╔══[COMPILATION ERROR] Illegal type declaration in term position.\n//│ ║  l.107: \tid(module 1)\n//│ ╙──       \t   ^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadModules.mls",
    "content": ":js\n\n\nclass Foo\n\n:ge\nmodule M extends Foo\n//│ ╔══[COMPILATION ERROR] Modules cannot have an extension clause.\n//│ ║  l.7: \tmodule M extends Foo\n//│ ╙──     \t                 ^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadMut.mls",
    "content": ":js\n\n\n:e\nmut \"oops\"\n//│ ╔══[COMPILATION ERROR] Illegal position for 'mut' modifier.\n//│ ║  l.5: \tmut \"oops\"\n//│ ╙──     \t^^^\n//│ = \"oops\"\n\n:e\nmut a: 1\n//│ ╔══[COMPILATION ERROR] Unexpected record key shape.\n//│ ║  l.12: \tmut a: 1\n//│ ╙──      \t    ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nmut {\"oops\"}\n//│ ╔══[COMPILATION ERROR] Expected a record after 'mut' keyword; found a block\n//│ ║  l.19: \tmut {\"oops\"}\n//│ ╙──      \t     ^^^^^^\n//│ = \"oops\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadOverloading.mls",
    "content": ":js\n\n\n:e\nclass Foo\nclass Foo\n//│ ╔══[COMPILATION ERROR] Multiple definitions of symbol 'Foo'\n//│ ╟── defined here\n//│ ║  l.5: \tclass Foo\n//│ ║       \t^^^^^^^^^\n//│ ╟── defined here\n//│ ║  l.6: \tclass Foo\n//│ ╙──     \t^^^^^^^^^\n\n:e\nclass Foo\nobject Foo\n//│ ╔══[COMPILATION ERROR] Illegal overloading of class 'Foo'\n//│ ║  l.16: \tclass Foo\n//│ ║        \t^^^^^^^^^\n//│ ╟── with object of the same name\n//│ ║  l.17: \tobject Foo\n//│ ╙──      \t^^^^^^^^^^\n\n:e\nobject Foo\nclass Foo\n//│ ╔══[COMPILATION ERROR] Illegal overloading of class 'Foo'\n//│ ║  l.27: \tclass Foo\n//│ ║        \t^^^^^^^^^\n//│ ╟── with object of the same name\n//│ ║  l.26: \tobject Foo\n//│ ╙──      \t^^^^^^^^^^\n\n:e\nfun Foo = 1\nobject Foo\n//│ ╔══[COMPILATION ERROR] Illegal overloading of function 'Foo'\n//│ ║  l.36: \tfun Foo = 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── with object of the same name\n//│ ║  l.37: \tobject Foo\n//│ ╙──      \t^^^^^^^^^^\n\n// * Note that this does not report an error at the moment:\nfun Foo: Int\nobject Foo\n\n:e\nfun Foo = 1\nobject Foo\nclass Foo\n//│ ╔══[COMPILATION ERROR] Illegal overloading of function 'Foo'\n//│ ║  l.50: \tfun Foo = 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── with object of the same name\n//│ ║  l.51: \tobject Foo\n//│ ╙──      \t^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of function 'Foo'\n//│ ║  l.50: \tfun Foo = 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── with class of the same name\n//│ ║  l.52: \tclass Foo\n//│ ╙──      \t^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Illegal overloading of class 'Foo'\n//│ ║  l.52: \tclass Foo\n//│ ║        \t^^^^^^^^^\n//│ ╟── with object of the same name\n//│ ║  l.51: \tobject Foo\n//│ ╙──      \t^^^^^^^^^^\n\n\n// TODO: support\n:e\nclass Foo\nfun Foo = 1\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of function 'Foo'\n//│ ║  l.76: \tfun Foo = 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── with class of the same name\n//│ ║  l.75: \tclass Foo\n//│ ╙──      \t^^^^^^^^^\n\n// TODO: support\n:e\nfun Foo = 1\nmodule Foo\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of function 'Foo'\n//│ ║  l.86: \tfun Foo = 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── with module of the same name\n//│ ║  l.87: \tmodule Foo\n//│ ╙──      \t^^^^^^^^^^\n\n// TODO: support\n:e\nval Foo = 1\nmodule Foo\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of value 'Foo'\n//│ ║  l.97: \tval Foo = 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── with module of the same name\n//│ ║  l.98: \tmodule Foo\n//│ ╙──      \t^^^^^^^^^^\n//│ Foo = class Foo\n\n\n:e\nfun (**) f1(a, b) = \"[\" + a + \" * \" + b + \"]\"\nfun (**) f2(a, b) = \"(\" + a + \" + \" + b + \")\"\n//│ ╔══[COMPILATION ERROR] Symbolic name '**' of definition 'f1' is already used\n//│ ║  l.109: \tfun (**) f1(a, b) = \"[\" + a + \" * \" + b + \"]\"\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── by sibling member 'f2'\n//│ ║  l.110: \tfun (**) f2(a, b) = \"(\" + a + \" + \" + b + \")\"\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n1 ** 2\n//│ = \"(1 + 2)\"\n\n:e\nfun (**) t() = 0\nfun (++) t() = 1\n//│ ╔══[COMPILATION ERROR] Multiple definitions of symbol 't'\n//│ ╟── defined here\n//│ ║  l.122: \tfun (**) t() = 0\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ╟── defined here\n//│ ║  l.123: \tfun (++) t() = 1\n//│ ╙──       \t^^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadParams.mls",
    "content": ":js\n\n\n:e\n(val x) => x\n//│ ╔══[COMPILATION ERROR] Illegal function parameter modifiers: val\n//│ ║  l.5: \t(val x) => x\n//│ ╙──     \t     ^\n//│ = fun\n\n:e\n(mut x) => x\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found 'mut'-modified identifier\n//│ ║  l.12: \t(mut x) => x\n//│ ╙──      \t     ^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.12: \t(mut x) => x\n//│ ╙──      \t           ^\n//│ = fun\n\n:e\n(mut val x) => x\n//│ ╔══[COMPILATION ERROR] Illegal function parameter modifiers: mut val\n//│ ║  l.22: \t(mut val x) => x\n//│ ╙──      \t         ^\n//│ = fun\n\n:e\nfun f(val x) = x\n//│ ╔══[COMPILATION ERROR] Illegal function parameter modifiers: val\n//│ ║  l.29: \tfun f(val x) = x\n//│ ╙──      \t          ^\n\n:e\n(...val x) => x\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found spread\n//│ ║  l.35: \t(...val x) => x\n//│ ╙──      \t ^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.35: \t(...val x) => x\n//│ ╙──      \t              ^\n//│ = fun\n\n// TODO: prevent duplicate parameter names?\n:sjs\n(x, x) => x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda4; lambda4 = (undefined, function (x, x1) { return x1 }); lambda4\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n:e\n(...x, ...y) => x\n//│ ╔══[COMPILATION ERROR] Spread parameters must be the last in the parameter list.\n//│ ║  l.53: \t(...x, ...y) => x\n//│ ╙──      \t ^^^^\n//│ = fun\n\n:e\n(..., ...y) => y\n//│ ╔══[COMPILATION ERROR] Spread parameters must be the last in the parameter list.\n//│ ║  l.60: \t(..., ...y) => y\n//│ ╙──      \t ^^^\n//│ = fun\n\n\n:e\nclass Foo(class C)\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found type definition\n//│ ║  l.68: \tclass Foo(class C)\n//│ ╙──      \t          ^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BadTypeClasses.mls",
    "content": "\n:e\nmodule M with\n  fun f(foo: Int, using bar: Int)\n//│ ╔══[COMPILATION ERROR] Keyword `using` must occur before all parameters.\n//│ ║  l.4: \t  fun f(foo: Int, using bar: Int)\n//│ ╙──     \t                  ^^^^^^^^^^^^^^\n\nmodule M with\n  fun f(using Int)\n\n:e\nM.f\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.13: \tM.f\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.10: \t  fun f(using Int)\n//│ ║        \t              ^^^\n//│ ╙── Missing instance: Expected: Int; Available: ‹none available›\n\n:todo // support literal type\nusing 42 = 42\nuse[42]\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Cannot add instance with a not-yet implemented type.\n\nval someInt = 42\n\n:e\nusing someInt = 42\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference.\n//│ ║  l.30: \tusing someInt = 42\n//│ ║        \t      ^^^^^^^\n//│ ╙── Implicit instance must be marked as returning a 'module' in order to have a module return type.\n//│ ╔══[COMPILATION ERROR] Expected a type, got reference\n//│ ║  l.30: \tusing someInt = 42\n//│ ╙──      \t      ^^^^^^^\n\n:e\nusing someInt: Int = 42\n//│ ╔══[COMPILATION ERROR] Expected a type, got block\n//│ ║  l.40: \tusing someInt: Int = 42\n//│ ╙──      \t      ^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected a type, got a non-type block\n//│ ║  l.40: \tusing someInt: Int = 42\n//│ ╙──      \t      ^^^^^^^^^^^^\n\nmodule M with\n  fun bar[A, B](a: A, b: B) = a + b\n\n:e\nM.bar[](1, 2)\n//│ ╔══[COMPILATION ERROR] Expected 2 type arguments, got 0\n//│ ║  l.52: \tM.bar[](1, 2)\n//│ ╙──      \t^^^^^^^\n\n:e\nM.bar[Int](1, 2)\n//│ ╔══[COMPILATION ERROR] Expected 2 type arguments, got 1\n//│ ║  l.58: \tM.bar[Int](1, 2)\n//│ ╙──      \t^^^^^^^^^^\n\nusing Int = 42\n\nmodule M with\n  fun foo()(using a: Int)\n\n// This should fail because M.foo() returns a function that requires special handling\n:breakme\n:e\nM.foo()\n\n:e\nfun f[T](using t: T) = t\nf\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: \n//│ ║  l.75: \tf\n//│ ║        \t^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.74: \tfun f[T](using t: T) = t\n//│ ║        \t               ^^^^\n//│ ╙── Illegal query for an unspecified type variable T.\n\n:e\nfun f(using t: Int = 42) = t\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found term definition\n//│ ║  l.85: \tfun f(using t: Int = 42) = t\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: t\n//│ ║  l.85: \tfun f(using t: Int = 42) = t\n//│ ╙──      \t                           ^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/BlockArgs.mls",
    "content": ":todo\n\n\nfun foo(x){f} =\n  f(x)\n//│ ╔══[COMPILATION ERROR] Expected a valid function definition head; found block instead\n//│ ║  l.4: \tfun foo(x){f} =\n//│ ╙──     \t          ^^^\n\nfoo(1){x => x}\n//│ ╔══[COMPILATION ERROR] Name not found: foo\n//│ ║  l.10: \tfoo(1){x => x}\n//│ ╙──      \t^^^\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (infix operator '=>').\n//│ ║  l.10: \tfoo(1){x => x}\n//│ ╙──      \t       ^^^^^^\n\nfoo(1)\n  x => x\n//│ ╔══[COMPILATION ERROR] Name not found: foo\n//│ ║  l.18: \tfoo(1)\n//│ ╙──      \t^^^\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (infix operator '=>').\n//│ ║  l.19: \t  x => x\n//│ ╙──      \t  ^^^^^^\n\nfoo(1) { x => x }\n//│ ╔══[COMPILATION ERROR] Name not found: foo\n//│ ║  l.27: \tfoo(1) { x => x }\n//│ ╙──      \t^^^\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (infix operator '=>').\n//│ ║  l.27: \tfoo(1) { x => x }\n//│ ╙──      \t         ^^^^^^\n\nfoo(1) with x => x\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'with' here\n//│ ║  l.35: \tfoo(1) with x => x\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^\n\n\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ByNameTailPosition.mls",
    "content": ":js\n\n// `baz()` should be a call in tail position (like `print(1)`), not bound to a variable\n:sir\nfun baz = print(1)\nfun bar() = baz\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let bar⁰, baz⁰;\n//│ define baz⁰ as fun baz¹() {\n//│   return Predef⁰.print⁰(1)\n//│ };\n//│ define bar⁰ as fun bar¹() { return baz¹() };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CallSyntaxes.mls",
    "content": ":js\n\n\n123 \\print()\n//│ > 123\n\n123 \\tuple()\n//│ = [123]\n\n\ntuple(123, 456)\n//│ = [123, 456]\n\n123 \\tuple(456)\n//│ = [123, 456]\n\n123 \\tuple of 456\n//│ = [123, 456]\n\n123 \\tuple @ 456\n//│ = [123, 456]\n\n123 |> (tuple(_, 456))\n//│ = [123, 456]\n\n// * Maybe later support this syntax?\n:pe\n:re\n123 |> tuple(., 456)\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.29: \t123 |> tuple(., 456)\n//│ ╙──      \t             ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.29: \t123 |> tuple(., 456)\n//│ ╙──      \t             ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Classes.mls",
    "content": ":js\n\n\nclass Foo\n\nclass Foo()\n\nclass Foo(x: Int)\n\nclass Foo(x: Int, y: Str)\n\nclass Foo(x: Int) with\n  val y = x\n\n\n:fixme\nclass Foo(x: Int) { val y = x }\n//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead\n//│ ║  l.17: \tclass Foo(x: Int) { val y = x }\n//│ ╙──      \t                  ^^^^^^^^^^^^^\n\n:fixme\nclass Foo(x: Int)\n  val y = x\n//│ ╔══[PARSE ERROR] Expected end of input; found indented block instead\n//│ ║  l.24: \t  val y = x\n//│ ╙──      \t^^\n\n:sjs\n:fixme\n:e\nclass Foo(x: Int) { log(\"Hello!\") }\n//│ ╔══[COMPILATION ERROR] Expected a valid class definition head; found block instead\n//│ ║  l.32: \tclass Foo(x: Int) { log(\"Hello!\") }\n//│ ╙──      \t                  ^^^^^^^^^^^^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n// *** *** ***\n\n:e\nclass Foo(42)\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found integer literal\n//│ ║  l.45: \tclass Foo(42)\n//│ ╙──      \t          ^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CompanionFunctions.mls",
    "content": ":js\n\n\n:fixme // TODO: support\n// :sjs\nfun Foo(x) = new Foo(x, 0)\ndata class Foo(x, y)\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of function 'Foo'\n//│ ║  l.6: \tfun Foo(x) = new Foo(x, 0)\n//│ ║       \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── with class of the same name\n//│ ║  l.7: \tdata class Foo(x, y)\n//│ ╙──     \t     ^^^^^^^^^^^^^^^\n\n:fixme\nFoo(123)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.16: \tFoo(123)\n//│ ╙──      \t   ^^^^^\n//│ = Foo(123, undefined)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CompanionModules_Classes.mls",
    "content": ":js\n\n\nclass C()\nmodule C with\n  val empty = 1\n\n:rt\nC()\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=class:C⁰}:\n//│     lhs = Resolved{sym=term:C⁰/C¹}:\n//│       t = Ref{sym=member:C²} of member:C²\n//│       sym = term:C⁰/C¹\n//│     rhs = Tup of Nil\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = C()\n\n:sir\nlet f = new C\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁰, f¹; define f¹ as fun f²() { return new C⁰() }; set f⁰ = f²; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\nf()\n//│ = C()\n\n:rt\nnew C()\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = New{typ=class:C⁰}:\n//│     cls = Resolved{sym=class:C⁰}:\n//│       t = Ref{sym=member:C²} of member:C²\n//│       sym = class:C⁰\n//│     args = Ls of \n//│       Tup of Nil\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = C()\n\n:rt\nC.empty\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:C³/empty⁰}:\n//│     t = Sel{sym=member:empty¹}:\n//│       prefix = Resolved{sym=module:C³,typ=module:C³}:\n//│         t = Ref{sym=member:C²} of member:C²\n//│         sym = module:C³\n//│       nme = Ident of \"empty\"\n//│     sym = term:C³/empty⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:breakme // TODO: should be an error, down the line, when we resolve all selections statically\n:e\n:re\nid(C).empty\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'empty' yielded 'undefined'\n\n\nclass C\nmodule C with\n  val empty = 1\n\n:rt\nC.empty\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:C⁴/empty²}:\n//│     t = Sel{sym=member:empty³}:\n//│       prefix = Resolved{sym=module:C⁴,typ=module:C⁴}:\n//│         t = Ref{sym=member:C⁵} of member:C⁵\n//│         sym = module:C⁴\n//│       nme = Ident of \"empty\"\n//│     sym = term:C⁴/empty²\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\nclass Test with\n  fun hi = Test.ans\nmodule Test with\n  val ans = 42\n  fun test = new Test\n\nTest.test.hi\n//│ = 42\n\n\nmut val state = 10\n//│ state = 10\n\n// * The order of evaluation of modules matters;\n// * they should not be moved to their companion classes (the opposite should happen)\n:sjs\nclass Foo() with // the class definition is moved to the location of its companion\n  fun foo = state\nset state += 1\nmodule Foo with\n  val res = Foo().foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1, tmp1;\n//│ tmp1 = state + 1;\n//│ state = tmp1;\n//│ Foo1 = function Foo() {\n//│   return globalThis.Object.freeze(new Foo.class());\n//│ };\n//│ (class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   static {\n//│     let tmp2;\n//│     tmp2 = Foo1();\n//│     this.res = tmp2.foo;\n//│   }\n//│   get foo() {\n//│     return state;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", []]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 11\nFoo.res\n//│ = 11\n\n\nfun bar =\n  using Int = 42\n  Foo.foo\nmut val x = 1\nprint(x)\nmodule Foo with\n  set x += 1\n  fun foo(using Int) = use[Int]\nprint(x)\nbar\n//│ > 1\n//│ > 2\n//│ = 42\n//│ x = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CompanionModules_Functions.mls",
    "content": ":js\n\n\n:fixme // TODO: support\n// :sjs\nfun foo(x) = x + 1\nmodule foo with\n  val zero = foo(0)\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of function 'foo'\n//│ ║  l.6: \tfun foo(x) = x + 1\n//│ ║       \t^^^^^^^^^^^^^^^^^^\n//│ ╟── with module of the same name\n//│ ║  l.7: \tmodule foo with\n//│ ║       \t^^^^^^^^^^^^^^^\n//│ ║  l.8: \t  val zero = foo(0)\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^\n\n:fixme\nfoo(123)\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor foo cannot be invoked without 'new'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CompanionModules_Patterns.mls",
    "content": ":js\n\n\n:fixme\npattern Foo = 1\nmodule Foo\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of pattern 'Foo'\n//│ ║  l.5: \tpattern Foo = 1\n//│ ║       \t^^^^^^^^^^^^^^^\n//│ ╟── with module of the same name\n//│ ║  l.6: \tmodule Foo\n//│ ╙──     \t^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CompanionModules_Types.mls",
    "content": ":js\n\n\ntype Foo = Int\nmodule Foo with\n  val default: Foo = 123\n\nFoo.default\n//│ = 123\n\n\ndata class Cons[A](head: A, tail: List[A])\nobject Nil\ntype List[A] = Cons[A]\nmodule List with\n  fun map[A, B](f: A -> B, xs: List[A]): List[B] = if xs is\n      Nil then Nil\n      Cons(head, tail) then Cons(f(head), map(f, tail))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CyclicModuleForwarders.mls",
    "content": ":js\n\nfun f: module M2 = M1.List\nmodule M1 with\n  fun List: module M2 = M2.List\nmodule M2 with\n  fun List: module M1 = M1.List\n\n:breakme // TODO: init error\n:e\nf\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/CyclicValues.mls",
    "content": ":js\n\n\ndata class Foo(x)\n\nlet foo = new mut Foo(null)\n//│ foo = Foo(null)\n\nset foo.x = foo\n\nfoo\n//│ = Foo(ref'1) as ref'1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/DataClass.mls",
    "content": ":js\n\n\ndata class Foo(x: Int)\n\nFoo(1).x\n//│ = 1\n\n\n// TODO: support?\n:todo\ndata Foo(x: Int)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ╟── This annotation is not supported on application of type Foo terms.\n//│ ║  l.12: \tdata Foo(x: Int)\n//│ ╙──      \t     ^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Symbol 'Int' is virtual (i.e., \"compiler fiction\"); cannot be used as a term\n//│ ║  l.12: \tdata Foo(x: Int)\n//│ ╙──      \t            ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Declare.mls",
    "content": ":js\n\n\n:sjs\ndeclare fun foo: Int\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// :re\n:sjs\nfoo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.foo\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\ndeclare fun p: Int\n\n// :re\np\n\n\nfun q: Int\nfun q = 1\n\nq\n//│ = 1\n\ndeclare module q with { val x }\n\n:re\nq.x\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'x')\n\n\ndeclare class C\n\nmodule M with\n  declare class D\n\n\n// * FIXME LP: @Harry why is this not resolved?\n:rt\nC\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=class:C⁰}:\n//│     t = Ref{sym=member:C¹} of member:C¹\n//│     sym = class:C⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n// * whereas this is:\nM.D\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=class:D⁰}:\n//│     t = Sel{sym=member:D¹}:\n//│       prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│         t = Ref{sym=member:M¹} of member:M¹\n//│         sym = module:M⁰\n//│       nme = Ident of \"D\"\n//│     sym = class:D⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:fixme // FIXME: Should report a proper error about lack of declared C companion module\nC.oops\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'C'\n//│ ║  l.66: \tC.oops\n//│ ║        \t^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.37: \tdeclare class C\n//│ ╙──      \t              ^\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'C'\n//│ ║  l.66: \tC.oops\n//│ ║        \t^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.37: \tdeclare class C\n//│ ╙──      \t              ^\n//│ ═══[RUNTIME ERROR] ReferenceError: C is not defined\n\n:re\nM.D.oops\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'D' yielded 'undefined'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/DisruptiveComments.mls",
    "content": ":js\n\n\n\"a\" + // hi\n  \"b\"\n//│ = \"ab\"\n\n\"a\" +\n  // hi\n\"b\"\n//│ = \"ab\"\n\n\"a\" +\n// hi\n\"b\"\n//│ = \"ab\"\n\n\n+ 1\n+ 2\n//│ = 3\n\n+ 1\n// oops\n+ 2\n//│ = 3\n\n\nobject Example with\n// whoops\n  val a = this\n\nassert Example.a is Example\n\n\npattern Bin =\n  | 0\n  // oops\n  | 1\n\nassert 1 is Bin\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Drop.mls",
    "content": ":js\n\n\n:sjs\ndrop id(2 + 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = 2 + 2; Predef.id(tmp); runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sir\n:sjs\ndrop { a: 0, b: 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.Unit\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let a⁰, b⁰, tmp, tmp1;\n//│ set a⁰ = 0;\n//│ set tmp = { \"a\": a⁰ };\n//│ set b⁰ = 1;\n//│ set tmp1 = { \"b\": b⁰ };\n//│ runtime⁰.Unit⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nlet discard = drop _\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let discard, discard1; discard1 = function discard(_0) { return runtime.Unit }; discard = discard1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ discard = fun discard\n\ndiscard of { a: 0, b: 1 }\n\n\n// * Notice the difference in how these are parsed:\n:pt\ndrop\n  id\n  id\ndo\n  id\n  id\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ PrefixApp:\n//│   kw = Keywrd of keyword 'drop'\n//│   rhs = Ident of \"id\"\n//│ PrefixApp:\n//│   kw = Keywrd of keyword 'drop'\n//│   rhs = Ident of \"id\"\n//│ PrefixApp:\n//│   kw = Keywrd of keyword 'do'\n//│   rhs = Block of Ls of \n//│     Ident of \"id\"\n//│     Ident of \"id\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/DynamicFields.mls",
    "content": ":js\n\n\nlet xs = mut [1, 2, 3]\n//│ xs = [1, 2, 3]\n\n:sjs\nxs.(0)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ xs[0]\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:sjs\nset xs.(0) = 4\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ xs[0] = 4; runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nxs.(0)\n//│ = 4\n\nset xs.[0] += 1\n\nset xs.[0] = xs.[0] + 1\n\nxs.[0]\n//│ = 6\n\nset xs.(\"lol\") = \"wat\"\n\nxs\n//│ = [6, 2, 3]\n\n\nclass Foo(val x)\n\nlet foo = Foo(123)\n//│ foo = Foo(123)\n\nfoo.(\"x\")\n//│ = 123\n\n// TODO sanitize\n:breakme\n:re\nfoo.(\"y\")\n\n// TODO sanitize\n:breakme\n:re\nfoo.(0)\n\n:re\nfoo.[0]\n//│ ═══[RUNTIME ERROR] TypeError: foo.at is not a function\n\n// * Array indexing syntax is only for numeric indices – this should throw\n:re\nfoo.[\"x\"]\n//│ ═══[RUNTIME ERROR] TypeError: foo.at is not a function\n\n\nclass DynCtor() with\n  set this.(\"dynField\") = 42\n\nDynCtor().dynField\n//│ = 42\n\nnew DynCtor().dynField\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/DynamicInstantiation.mls",
    "content": ":js\n\n\nclass C\n\n:sjs\nnew! C\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new C1())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = C\n\nlet c = C\n//│ c = class C\n\nnew! c\n//│ = C\n\nlet f = new! _\n//│ f = fun f\n\nf(c)\n//│ = C\n\n// * Same in JS:\n// *    > new id(C)\n// *    Uncaught TypeError: id is not a constructor\n// *    > new (id(C))\n// *    C {}\n:sjs\n:pt\n:re\nnew! id(C)\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ App:\n//│   lhs = PrefixApp:\n//│     kw = Keywrd of keyword 'new!'\n//│     rhs = Ident of \"id\"\n//│   rhs = Tup of Ls of \n//│     Ident of \"C\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new Predef.id(C1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Predef.id is not a constructor\n\n// * Ok (as in JS)\nnew! (id(C))\n//│ = C\n\n// * We should reject static new on an unknown class.\n:e\n:re\nnew id(C)\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found selection.\n//│ ║  l.53: \tnew id(C)\n//│ ║        \t    ^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: Predef.id is not a constructor\n\n:e\nnew (id(C))\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found application.\n//│ ║  l.61: \tnew (id(C))\n//│ ║        \t     ^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ = C\n\n\ndata class C(x, y)\n\n\n// Note: mismatched number of arguments and class parameters\n// (dead param elimination cannot yet handle this and used to throw a softTODO here)\n// :todo\nlet f = new! C()\n//│ f = C(undefined, undefined)\n\nlet f = new! C\n//│ f = fun f\n\nf(1, 2)\n//│ = C(1, 2)\n\nlet f = x => new! (id(C))(x, x)\n//│ f = fun f\n\nf(1)\n//│ = C(1, 1)\n\nnew! C(1, 2)\n//│ = C(1, 2)\n\n\nlet o = new! mut Object\n//│ o = {}\n\nset o.x = 1\n\no.x\n//│ = 1\n\nset o.x += 1 in o.x\n//│ = 2\n\no.x\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/DynamicSelection.mls",
    "content": ":js\n\n\nlet r =\n  a: 1\n  value: 2\n//│ r = {a: 1, value: 2}\n\n:pt\nr!a\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ DynAccess:\n//│   obj = Ident of \"r\"\n//│   fld = Ident of \"a\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\nr!(\"a\")\n//│ = 1\n\nr !a\n//│ = 1\n\n:e\n:fixme\nr! a\n//│ ╔══[COMPILATION ERROR] Name not found: a\n//│ ║  l.26: \tr! a\n//│ ╙──      \t   ^\n//│ ╔══[COMPILATION ERROR] Builtin '!' is not a binary operator\n//│ ║  l.26: \tr! a\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n:fixme\nr ! a\n//│ ╔══[COMPILATION ERROR] Name not found: a\n//│ ║  l.37: \tr ! a\n//│ ╙──      \t    ^\n//│ ╔══[COMPILATION ERROR] Builtin '!' is not a binary operator\n//│ ║  l.37: \tr ! a\n//│ ╙──      \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// * Note: artifact from BbML/InvalML\n:sjs\n!(r)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ r.value\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\nlet t = [1, 2, 3]\n//│ t = [1, 2, 3]\n\nt!0\n//│ = 1\n\nt!(\"0\")\n//│ = 1\n\nt!(0)\n//│ = 1\n\nt![0]\n//│ = 1\n\nt.1\n//│ = 2\n\nt.01\n//│ = 2\n\n\n:w\n:fixme // * Strange that this is treated as a statement\n!(1,2)\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.79: \t!(1,2)\n//│ ╙──      \t  ^\n//│ > try { block$res15 = 2.value; undefined; undefined } catch (e) { console.log('\\u200B' + e + '\\u200B'); }\n//│ >                     ^^\n//│ ═══[COMPILATION ERROR] [Uncaught SyntaxError] Invalid or unexpected token\n\n:ge\n(!)(1,2)\n//│ ╔══[COMPILATION ERROR] Builtin '!' is not a binary operator\n//│ ║  l.88: \t(!)(1,2)\n//│ ╙──      \t^^^^^^^^\n//│ ═══[COMPILATION ERROR] Cannot call non-binary builtin symbol '!'\n//│ ═══[RUNTIME ERROR] Error: Cannot call non-binary builtin symbol '!'\n\n:sjs\n(!)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda; lambda = (undefined, function (arg) { return ! arg }); lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n:fixme\n!1\n//│ ╔══[PARSE ERROR] Expected an expression; found dynamic selector instead\n//│ ║  l.103: \t!1\n//│ ╙──       \t^^\n//│ ╔══[PARSE ERROR] Expected end of input; found dynamic selector instead\n//│ ║  l.103: \t!1\n//│ ╙──       \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ExplicitSelections.mls",
    "content": ":js\n\n\nclass Foo() with\n  val x = 1\n  fun f() = x + 1\n\n\nFoo().x\n//│ = 1\n\nFoo().Foo#x\n//│ = 1\n\n\nFoo().f()\n//│ = 2\n\nFoo().Foo#f()\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/FunDefs.mls",
    "content": "\n\nfun foo = 1\n\nfoo\n\nfun (+) plus: Int\n\nfun (+) : Int\n\n1 + 2\n\n\nfun f = g\nfun g = f\n\n\nfun (++)(x, y) = 1\n\n1 ++ 2\n\n\nfun (**) pow = 1\n\n1 ** 2\n\n\nfun (:::) appendAll[A](a, b): A = a + b\n\n\nfun (>>) foo(a, b) = a * b\n\n2 >> 2\n\n\n:e\nfun ~ concat(a, b) = a + b\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found application\n//│ ║  l.37: \tfun ~ concat(a, b) = a + b\n//│ ╙──      \t      ^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: a\n//│ ║  l.37: \tfun ~ concat(a, b) = a + b\n//│ ╙──      \t                     ^\n//│ ╔══[COMPILATION ERROR] Name not found: b\n//│ ║  l.37: \tfun ~ concat(a, b) = a + b\n//│ ╙──      \t                         ^\n\n// * Note the strange parsing\n:pt\n:todo // better error?\nfun not(b) = !b\n//│ ╔══[PARSE ERROR] Expected an expression; found dynamic selector instead\n//│ ║  l.51: \tfun not(b) = !b\n//│ ╙──      \t             ^^\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ DynAccess:\n//│   obj = TermDef:\n//│     k = Fun\n//│     head = PrefixApp:\n//│       kw = Keywrd of keyword 'not'\n//│       rhs = Bra:\n//│         k = Round\n//│         inner = Ident of \"b\"\n//│     rhs = S of Error\n//│   fld = Ident of \"b\"\n//│ ╔══[COMPILATION ERROR] Illegal definition in term position.\n//│ ║  l.51: \tfun not(b) = !b\n//│ ╙──      \t^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/FunnyRecordKeys.mls",
    "content": ":js\n\n:global\n:sjs\n\n\n{ a: 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let a; a = 1; globalThis.Object.freeze({ a: a })\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = {a: 1}\n\n{ \"a\": 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze({ a: 1 })\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = {a: 1}\n\n:sjs\n{ \" \": 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze({ \" \": 1 })\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = {\" \": 1}\n\n:sjs\n{ 0: 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze({ 0: 1 })\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = {\"0\": 1}\n\n:sjs\n{ (0): 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze({ 0: 1 })\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = {\"0\": 1}\n\n:sjs\n{ (id(0)): 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = Predef.id(0); globalThis.Object.freeze({ [tmp]: 1 })\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = {\"0\": 1}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/GenericClasses.mls",
    "content": "\n\nclass Foo[A]\n\nclass Foo[A]()\n\nclass Foo[A](x: A)\n\nclass Foo[A](x: A -> Int)\n\nclass Foo[A](x: Foo[A])\n\nclass Foo[A](x: Foo[A] -> A)\n\nclass Foo[A](x: Bar[A])\nclass Bar[B](x: Foo[Int], y: B -> Int)\n\nclass Foo[A](x: Bar[A])\nclass Baz[C](x: C)\nclass Bar[B](x: Foo[Int], y: Baz[B] -> Int)\n\n\nclass Foo[A] with\n  fun foo: A -> A\n\n\n\n\n:e\nclass Foo[A](x: Foo[A, A])\n//│ ╔══[COMPILATION ERROR] Expected 1 type arguments, got 2\n//│ ║  l.30: \tclass Foo[A](x: Foo[A, A])\n//│ ╙──      \t                ^^^^^^^^^\n\n:e\nclass Foo[A](x: Bar[A])\nclass Bar(x: Foo[Int])\n//│ ╔══[COMPILATION ERROR] Expected no type arguments, got 1\n//│ ║  l.36: \tclass Foo[A](x: Bar[A])\n//│ ╙──      \t                ^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Getters.mls",
    "content": ":js\n:ignore\n\n\n\nget foo = 123\n//│ ╔══[COMPILATION ERROR] Unrecognized definitional assignment left-hand side: juxtaposition\n//│ ║  l.6: \tget foo = 123\n//│ ╙──     \t^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n// * These two should be equivalent and should *not* be getters: \n\nfun f = x => x\n\nfun f(x) = x\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/IdentEscape.mls",
    "content": "let id\"of\" = 42\nfun id\"fun\"(x: Int) = x + 1\n\nid\"fun\"(id\"of\")\n\nlet id\"if\" = 1\nid\"if\" + 1\n\nmodule id\"object\" with\n  object id\"class\"\n  class id\"module\"(x: Int)\n\n:pe\nid\"\"\n//│ ╔══[LEXICAL ERROR] unexpected identifier escape\n//│ ║  l.14: \tid\"\"\n//│ ╙──      \t^\n//│ ╔══[PARSE ERROR] Expected an expression; found error instead\n//│ ║  l.14: \tid\"\"\n//│ ╙──      \t^^^^\n//│ ╔══[PARSE ERROR] Expected end of input; found error instead\n//│ ║  l.14: \tid\"\"\n//│ ╙──      \t^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/IfThenNewline.mls",
    "content": ":js\n\n// Regression test: `if true` with `then` on a new indented line should work\n// the same as `if true then` on the same line.\n\n// Works (same line)\nif true then\n    5\n  else 1\n//│ = 5\n\n// Previously broken (then on next line)\nif true\n  then\n    5\n  else 1\n//│ = 5\n\n// Also test false\nif false\n  then\n    5\n  else 1\n//│ = 1\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Indentation.mls",
    "content": ":js\n\n\ntuple(\n  )\n//│ = []\n\ntuple(\n  )\n  tuple()\n//│ = [[]]\n\ntuple(\n  ) tuple()\n//│ = [[]]\n\ntuple(\n  id(2\n    +2))\n            tuple()\n//│ = [[4]]\n\ntuple(\n  id(2\n    +2))\n    tuple()\n//│ = [[4]]\n\ntuple(\n  id(2\n    +2))\ntuple()\n//│ = []\n\ntuple(\n  id(2\n    +2))\n    tuple()\n  tuple()\n//│ = [[[4]]]\n\n// 🤔\n:e\ntuple(\n  id(2\n    +2))\n      tuple()\n    tuple()\n  tuple()\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (juxtaposition).\n//│ ║  l.47: \t      tuple()\n//│ ║        \t      ^^^^^^^\n//│ ║  l.48: \t    tuple()\n//│ ║        \t^^^^^^^^^^^\n//│ ║  l.49: \t  tuple()\n//│ ╙──      \t^^\n//│ = [[4]]\n\nmodule A with {\n}\n\n:p\ntuple(\n)\n//│ ┊tuple┊(⟨┊↵┊⟩)┊\n//│ Parsed:\n//│ \tApp(Ident(tuple),Tup(List()))\n//│ = []\n\n:w\ntuple(\n1\n)\n//│ ╔══[WARNING] This literal should be indented\n//│ ║  l.72: \t1\n//│ ║        \t^\n//│ ╟── since it is a continuation of the new line here\n//│ ║  l.71: \ttuple(\n//│ ║        \t      ^\n//│ ║  l.72: \t1\n//│ ╙──      \t\n//│ = [1]\n\ntuple(\n  )\n//│ = []\n\nprint(\n  2)\n1\n//│ > 2\n//│ = 1\n\nid(\n  1)\n//│ = 1\n\nid(\n  id)(1)\n//│ = 1\n\n:p\nid(\n  2)\n  print()\n//│ ┊id┊(⟨┊→⟨┊2┊⟩←┊⟩)┊→⟨┊print┊(⟨┊┊⟩)┊⟩←┊\n//│ Parsed:\n//│ \tJux(App(Ident(id),Tup(List(IntLit(2)))),Block(List(App(Ident(print),Tup(List())))))\n//│ > 2\n\nid(0\n  passTo(id))(2)\n//│ = 0\n\n:p\nid(\n  2\n)\n  print()\n//│ ┊id┊(⟨┊→⟨┊2┊⟩←┊↵┊⟩)┊→⟨┊print┊(⟨┊┊⟩)┊⟩←┊\n//│ Parsed:\n//│ \tJux(App(Ident(id),Tup(List(IntLit(2)))),Block(List(App(Ident(print),Tup(List())))))\n//│ > 2\n\n:p\nid(\n  id\n)(1)\n//│ ┊id┊(⟨┊→⟨┊id┊⟩←┊↵┊⟩)┊(⟨┊1┊⟩)┊\n//│ Parsed:\n//│ \tApp(App(Ident(id),Tup(List(Ident(id)))),Tup(List(IntLit(1))))\n//│ = 1\n\n:e\n:p\nid\n  1\n//│ ┊id┊→⟨┊1┊⟩←┊\n//│ Parsed:\n//│ \tJux(Ident(id),Block(List(IntLit(1))))\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (integer literal).\n//│ ║  l.137: \t  1\n//│ ╙──       \t  ^\n//│ = fun id\n\n:e\n:re\n:p\nid(0\n  id)(1)\n//│ ┊id┊(⟨┊0┊→⟨┊id┊⟩←┊⟩)┊(⟨┊1┊⟩)┊\n//│ Parsed:\n//│ \tApp(App(Ident(id),Tup(List(Jux(IntLit(0),Block(List(Ident(id))))))),Tup(List(IntLit(1))))\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (identifier).\n//│ ║  l.150: \t  id)(1)\n//│ ╙──       \t  ^^\n//│ ═══[RUNTIME ERROR] TypeError: baseCall3 is not a function\n\n\nfun test2() =\n  fun funny = (case\n    0 then 1)\n  funny\n\ntest2()(0)\n//│ = 1\n\n\n:pt\nmodule P with\n  print(\n    2)\n  val x = 1\nP.x\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TypeDef:\n//│   k = Mod\n//│   head = InfixApp:\n//│     lhs = Ident of \"P\"\n//│     kw = Keywrd of keyword 'with'\n//│     rhs = Block of Ls of \n//│       App:\n//│         lhs = Ident of \"print\"\n//│         rhs = Tup of Ls of \n//│           IntLit of 2\n//│       TermDef:\n//│         k = ImmutVal\n//│         head = Ident of \"x\"\n//│         rhs = S of IntLit of 1\n//│ Sel:\n//│   prefix = Ident of \"P\"\n//│   name = Ident of \"x\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n//│ = 1\n\n\nmodule P with\n  (\n    )\n  module TraceLogger\n\nmodule P with\n  (\n  )\n  module TraceLogger\n\n\nmodule P with ...\nfun checkArgs(expected) =\n  (\"Function\" +\n    expected)\nmodule TraceLogger\n\nP.TraceLogger\n//│ = class TraceLogger\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Inheritance.mls",
    "content": ":js\n\n\nclass Foo with\n  val x = 10\n  fun foo = x + 1\n\n\nobject Bar extends Foo\n\n:todo // recognize fields that are inherited from superclasses\n[Bar.x, Bar.foo]\n//│ ╔══[COMPILATION ERROR] Object 'Bar' does not contain member 'x'\n//│ ║  l.12: \t[Bar.x, Bar.foo]\n//│ ╙──      \t    ^^\n//│ ╔══[COMPILATION ERROR] Object 'Bar' does not contain member 'foo'\n//│ ║  l.12: \t[Bar.x, Bar.foo]\n//│ ╙──      \t           ^^^^\n//│ = [10, 11]\n\nlet b = id(Bar) in [b.x, b.foo]\n//│ = [10, 11]\n\nBar is Foo\n//│ = true\n\nBar is String\n//│ = false\n\n\n// :pt\n// :elt\n// :de\ndata class Bar(y) extends Foo with\n  fun bar = y + 1\n\nlet b = Bar(42)\n//│ b = Bar(42)\n\nb is Foo\n//│ = true\n\nb is String\n//│ = false\n\n[b.x, b.foo]\n//│ = [10, 11]\n\n\n:sjs\ndata class Baz(z) extends Bar(z * 1) with\n  fun baz = this.bar * 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Baz1;\n//│ Baz1 = function Baz(z) {\n//│   return globalThis.Object.freeze(new Baz.class(z));\n//│ };\n//│ (class Baz extends Bar3.class {\n//│   static {\n//│     Baz1.class = this\n//│   }\n//│   constructor(z) {\n//│     let tmp;\n//│     tmp = z * 1;\n//│     super(tmp);\n//│     this.z = z;\n//│   }\n//│   get baz() {\n//│     return this.bar * 2;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Baz\", [\"z\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet b = Baz(42)\n//│ b = Baz(42)\n\nb is Foo\n//│ = true\n\nb is String\n//│ = false\n\n[b.x, b.foo]\n//│ = [10, 11]\n\n\n\nabstract class Option[out T]: Some[T] | None\nobject None extends Option[Nothing]\ndata class Some[out T](x: T) extends Option[T]\n[Some(123) is Option, None is Option, Some(123) is String, None is String]\n//│ = [true, true, false, false]\n\n\ndata class Barr(x: Int)(y: Int) with\n  fun f = x + y\n\n:todo\ndata class Bazz(z: Int) extends Bar(z % 10)(z / 10) with\n  fun g = z\n//│ ╔══[COMPILATION ERROR] Extending a class with multiple parameter lists is not supported\n//│ ║  l.101: \tdata class Bazz(z: Int) extends Bar(z % 10)(z / 10) with\n//│ ╙──       \t                                ^^^^^^^^^^^^^^^^^^^\n\n:todo\nBazz(42).f\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'f' yielded 'undefined'\n\n:todo\nnew Barr(40)(2) with\n  fun f = 43\n//│ ╔══[COMPILATION ERROR] Extending a class with multiple parameter lists is not supported\n//│ ║  l.112: \tnew Barr(40)(2) with\n//│ ╙──       \t    ^^^^^^^^^^^\n//│ = fun\n\n\n\nmodule M with\n  class A\n\n// * Check that the access to `M.A` is not sanity-checked, as it is resolved.\n:sjs\nclass B extends M.A\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let B1;\n//│ (class B extends M1.A {\n//│   static {\n//│     B1 = this\n//│   }\n//│   constructor() {\n//│     super();\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"B\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/LazySpreads.mls",
    "content": ":js\n\n:expect [[1, 2], 3]\nif [1, ..[2, 3]] is [..a, b] then [a, b]\n//│ = [[1, 2], 3]\n\n:expect [[1, 2], 3]\nif [1, ...[2, 3]] is [..a, b] then [a, b]\n//│ = [[1, 2], 3]\n\n:expect [[1, 2], 3]\nif [1, ..[2, 3]] is [..a, b] then [a, b]\n//│ = [[1, 2], 3]\n\n:sjs\nfun buildPalindrome = case\n  0 then []\n  n then [n, ..buildPalindrome(n - 1), n]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let buildPalindrome;\n//│ buildPalindrome = function buildPalindrome() {\n//│   let lambda;\n//│   lambda = (undefined, function (caseScrut) {\n//│     let n, tmp3, tmp4, tmp5;\n//│     if (caseScrut === 0) {\n//│       return globalThis.Object.freeze([])\n//│     }\n//│     n = caseScrut;\n//│     tmp3 = buildPalindrome();\n//│     tmp4 = n - 1;\n//│     tmp5 = runtime.safeCall(tmp3(tmp4));\n//│     return globalThis.Object.freeze(runtime.Tuple.lazyConcat(n, runtime.Tuple.split, tmp5, n));\n//│   });\n//│   return lambda\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:silent\nval arr = buildPalindrome(5)\n\n\n:expect [5, 4, 3, 2, 1, 1, 2, 3, 4, 5]\narr\n//│ = [5, 4, 3, 2, 1, 1, 2, 3, 4, 5]\n\n:sjs\nfun sum2 = case\n  [] then 0\n  [x, ..xs, y] then x + y + sum2(xs)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let sum2;\n//│ sum2 = function sum2() {\n//│   let lambda;\n//│   lambda = (undefined, function (caseScrut) {\n//│     let x, xs, y, lastElement1$3, middleElements3, element0$, tmp5, tmp6, tmp7;\n//│     if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length === 0) {\n//│       return 0\n//│     } else if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length >= 2) {\n//│       element0$ = runtime.Tuple.get(caseScrut, 0);\n//│       middleElements3 = runtime.Tuple.slice(caseScrut, 1, 1);\n//│       lastElement1$3 = runtime.Tuple.get(caseScrut, -1);\n//│       y = lastElement1$3;\n//│       xs = middleElements3;\n//│       x = element0$;\n//│       tmp5 = x + y;\n//│       tmp6 = sum2();\n//│       tmp7 = runtime.safeCall(tmp6(xs));\n//│       return tmp5 + tmp7\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   });\n//│   return lambda\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 30\nsum2(arr)\n//│ = 30\n\n:e\nfun f(..xs) = xs\n//│ ╔══[COMPILATION ERROR] Lazy spread parameters not allowed.\n//│ ║  l.81: \tfun f(..xs) = xs\n//│ ╙──      \t      ^^^^\n\n:ge\nsum2(..arr)\n//│ ╔══[COMPILATION ERROR] Lazy spreads are not supported in call arguments\n//│ ║  l.87: \tsum2(..arr)\n//│ ╙──      \t    ^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Function expected 1 argument but got 2\n\n\nfun map2(f) = case\n  [] then []\n  [x, ..xs, y] then [f(x), ..map2(f)(xs), f(y)]\n\n:expect [10, 8, 6, 4, 2, 2, 4, 6, 8, 10]\nmap2(x => x * 2)(arr)\n//│ = [10, 8, 6, 4, 2, 2, 4, 6, 8, 10]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/LetBindings.mls",
    "content": ":js\n\n\nlet x = 1\n//│ x = 1\n\nlet x = 1 in x\n//│ = 1\n\nlet x = 1\nlet y = 2\nx + y\n//│ = 3\n//│ x = 1\n//│ y = 2\n\nx\n//│ = 1\n\nlet z = 3\nx + y + z\n//│ = 6\n//│ z = 3\n\nlet x =\n  print(\"computing x\")\n  123\n//│ > computing x\n//│ x = 123\n\n\nlet x = 0\n//│ x = 0\n\nlet x += 1 in...\nx\n//│ = 1\n\nlet x += 1 in...\nprint of x\nx\n//│ > 1\n//│ = 1\n\nlet x += 1 in...\nprint(x)\nx\n//│ > 1\n//│ = 1\n\nlet x += 1 in\n  print(x)\n  x\n//│ > 1\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/LiteralSelection.mls",
    "content": ":js\n\n\nlet arr = [1, 2, 3]\n//│ arr = [1, 2, 3]\n\narr.1\n//│ = 2\n\narr.\"1\"\n//│ = 2\n\n// Equivalent:\narr.'1\n//│ = 2\n\n\n{a: 123}.'a\n//│ = 123\n\n{'a: 123}.'a\n//│ = 123\n\n{\"a\": 123}.'a\n//│ = 123\n\n\nlet obj = a: 1\n//│ obj = {a: 1}\n\nobj.a\n//│ = 1\n\nobj .a\n//│ = 1\n\nobj\n  .a\n//│ = 1\n\n:pe\nobj. a\n//│ ╔══[PARSE ERROR] Expected end of input; found period instead\n//│ ║  l.42: \tobj. a\n//│ ╙──      \t   ^\n//│ = {a: 1}\n\nobj.(\"a\")\n//│ = 1\n\nobj .(\"a\")\n//│ = 1\n\n:fixme\nobj\n  .(\"a\")\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.56: \t  .(\"a\")\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.56: \t  .(\"a\")\n//│ ╙──      \t  ^\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (‹erroneous syntax›).\n//│ ║  l.56: \t  .(\"a\")\n//│ ╙──      \t  ^\n//│ = {a: 1}\n\n:pe\nobj. (\"a\")\n//│ ╔══[PARSE ERROR] Expected end of input; found period instead\n//│ ║  l.69: \tobj. (\"a\")\n//│ ╙──      \t   ^\n//│ = {a: 1}\n\nobj.\"a\"\n//│ = 1\n\nobj .\"a\"\n//│ = 1\n\n:fixme\nobj\n  .\"a\"\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.83: \t  .\"a\"\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.83: \t  .\"a\"\n//│ ╙──      \t  ^\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (‹erroneous syntax›).\n//│ ║  l.83: \t  .\"a\"\n//│ ╙──      \t  ^\n//│ = {a: 1}\n\n:pe\nobj. \"a\"\n//│ ╔══[PARSE ERROR] Expected end of input; found period instead\n//│ ║  l.96: \tobj. \"a\"\n//│ ╙──      \t   ^\n//│ = {a: 1}\n\n\nlet obj =\n  \" \": 1\n  \"¯\\\\_(ツ)_/¯\": 2\n//│ obj = {\" \": 1, \"¯_(ツ)_/¯\": 2}\n\nobj.\" \"\n//│ = 1\n\n:fixme\n:expect 2\nobj.\"¯\\\\_(ツ)_/¯\"\n//│ ═══[RUNTIME ERROR] Expected: '2', got: 'undefined'\n\n:fixme\n\"¯\\_(ツ)_/¯\"\n:fixme\nlet obj = \"¯\\_(ツ)_/¯\": 2\n//│ ╔══[WARNING] Found invalid escape character\n//│ ║  l.117: \t\"¯\\_(ツ)_/¯\"\n//│ ╙──       \t   ^\n//│ ╔══[WARNING] Found invalid escape character\n//│ ║  l.119: \tlet obj = \"¯\\_(ツ)_/¯\": 2\n//│ ╙──       \t             ^\n//│ ╔══[COMPILATION ERROR] Name not found: fixme\n//│ ║  l.118: \t:fixme\n//│ ╙──       \t ^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'obj'\n//│ ╟── which references the symbol introduced here\n//│ ║  l.119: \tlet obj = \"¯\\_(ツ)_/¯\": 2\n//│ ╙──       \t    ^^^\n//│ obj = {a: 1}\n:fixme\nobj.\"¯\\_(ツ)_/¯\"\n//│ ╔══[WARNING] Found invalid escape character\n//│ ║  l.136: \tobj.\"¯\\_(ツ)_/¯\"\n//│ ╙──       \t       ^\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'obj'\n//│ ║  l.136: \tobj.\"¯\\_(ツ)_/¯\"\n//│ ║         \t^^^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.119: \tlet obj = \"¯\\_(ツ)_/¯\": 2\n//│ ╙──       \t    ^^^\n\n:fixme\n:expect ¯\\\\_(ツ)_/¯\n\"¯\\\\_(ツ)_/¯\"\n//│ ═══[RUNTIME ERROR] Expected: '¯\\\\_(ツ)_/¯', got: '\"¯\\\\_(ツ)_/¯\"'\n//│ = \"¯\\\\_(ツ)_/¯\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Literals.mls",
    "content": ":js\n\n\n1\n//│ = 1\n\n()\n\n(1)\n//│ = 1\n\n(1,)\n//│ = 1\n\n:w\n(1, 2)\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.16: \t(1, 2)\n//│ ╙──      \t ^\n//│ = 2\n\n:w\n(1, 2,)\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.23: \t(1, 2,)\n//│ ╙──      \t ^\n//│ = 2\n\n[]\n//│ = []\n\n[1]\n//│ = [1]\n\n[1,]\n//│ = [1]\n\n[1, 2]\n//│ = [1, 2]\n\n[1, 2,]\n//│ = [1, 2]\n\n\nnull\n//│ = null\n\nundefined\n\n\n0.5\n//│ = 0.5\n\n:todo\nNaN\n//│ ╔══[COMPILATION ERROR] Name not found: NaN\n//│ ║  l.55: \tNaN\n//│ ╙──      \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n\"\"\n//│ = \"\"\n\n\"AAA\"\n//│ = \"AAA\"\n\n'AAA\n//│ = \"AAA\"\n\n'AAA'\n//│ = \"AAA'\"\n\n:e\n'AA BB'\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (identifier).\n//│ ║  l.75: \t'AA BB'\n//│ ╙──      \t    ^^^\n//│ = \"AA\"\n\n\n\"\\u0068\\u0065\\u006c\\u006c\\u006f\"\n//│ = \"hello\"\n\n\"\\u{a}\"\n//│ = \"\\n\"\n\n\"\\ud83d\\ude00\"\n//│ = \"😀\"\n\n\"\\u{1F600}\"\n//│ = \"😀\"\n\n\"\\u{1F600}\" == \"\\ud83d\\ude00\"\n//│ = true\n\n:w\n\"\\uFE&&\"\n//│ ╔══[WARNING] Invalid Unicode escape sequence: expected 4 hexadecimal digits but got 2\n//│ ║  l.98: \t\"\\uFE&&\"\n//│ ╙──      \t   ^^\n//│ = \"&&\"\n\n:w\n\"\\u{}\"\n//│ ╔══[WARNING] Expected at least one hexadecimal digit in Unicode escape sequence\n//│ ║  l.105: \t\"\\u{}\"\n//│ ╙──       \t   ^\n//│ = \"\"\n\n:w\n\"\\u{ffffffff}\"\n//│ ╔══[WARNING] Too many hexadecimal digits in Unicode escape sequence\n//│ ║  l.112: \t\"\\u{ffffffff}\"\n//│ ╙──       \t          ^^\n//│ = \"\"\n\n:w\n\"\\u{efefef}\"\n//│ ╔══[WARNING] Unicode code point out of range: 0xefefef\n//│ ║  l.119: \t\"\\u{efefef}\"\n//│ ╙──       \t    ^^^^^^\n//│ = \"\"\n\n:w\n\"\\u{55\"\n//│ ╔══[WARNING] Unterminated Unicode escape sequence: missing '}'\n//│ ║  l.126: \t\"\\u{55\"\n//│ ╙──       \t      ^\n//│ = \"U\"\n\n:w\n\"\\u{41****\"\n//│ ╔══[WARNING] Unterminated Unicode escape sequence: missing '}'\n//│ ║  l.133: \t\"\\u{41****\"\n//│ ╙──       \t      ^\n//│ = \"A****\"\n\nprint of fold(+) of\n  \"\\u{250c}\\u{2500}\\u{252c}\\u{2510}\"\n  \"\\u{2554}\\u{2550}\\u{2566}\\u{2557}\"\n  \"\\u{2553}\\u{2500}\\u{2565}\\u{2556}\"\n  \"\\u{2552}\\u{2550}\\u{2564}\\u{2555}\"\n  \"\\u000A\"\n  \"\\u{2502}\\u{20}\\u{2502}\\u{2502}\"\n  \"\\u{2551}\\u{20}\\u{2551}\\u{2551}\"\n  \"\\u{2551}\\u{20}\\u{2551}\\u{2551}\"\n  \"\\u{2502}\\u{20}\\u{2502}\\u{2502}\"\n  \"\\u000A\"\n  \"\\u{251c}\\u{2500}\\u{253c}\\u{2524}\"\n  \"\\u{2560}\\u{2550}\\u{256c}\\u{2563}\"\n  \"\\u{255f}\\u{2500}\\u{256b}\\u{2562}\"\n  \"\\u{255e}\\u{2550}\\u{256a}\\u{2561}\"\n  \"\\u000A\"\n  \"\\u{2514}\\u{2500}\\u{2534}\\u{2518}\"\n  \"\\u{255a}\\u{2550}\\u{2569}\\u{255d}\"\n  \"\\u{2559}\\u{2500}\\u{2568}\\u{255c}\"\n  \"\\u{2558}\\u{2550}\\u{2567}\\u{255b}\"\n//│ > ┌─┬┐╔═╦╗╓─╥╖╒═╤╕\n//│ > │ ││║ ║║║ ║║│ ││\n//│ > ├─┼┤╠═╬╣╟─╫╢╞═╪╡\n//│ > └─┴┘╚═╩╝╙─╨╜╘═╧╛\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/LocalVal.mls",
    "content": ":js\n\n\nfun foo() =\n  val x = 1\n  x + 1\n\nfoo()\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MemberProjections.mls",
    "content": ":js\n\n\nmodule M with\n  data class Foo(x) with\n    fun m() = this.x + 1\n    fun n(y) = this.x + y\n\n\nlet foo = M.Foo(123)\n//│ foo = Foo(123)\n\n\nfoo.m()\n//│ = 124\n\nfoo.n(1)\n//│ = 124\n\n\nfoo M.Foo::m()\n//│ = 124\n\nfoo M.Foo::n(2)\n//│ = 125\n\nM.Foo::n(foo, 2)\n//│ = 125\n\nM.Foo ::n(foo, 2)\n//│ = 125\n\nM.Foo ::n (foo, 2)\n//│ = 125\n\n:e\nM.Foo:: n(foo, 2)\n//│ ╔══[COMPILATION ERROR] Name not found: ::\n//│ ║  l.37: \tM.Foo:: n(foo, 2)\n//│ ╙──      \t     ^^\n//│ ╔══[COMPILATION ERROR] Name not found: n\n//│ ║  l.37: \tM.Foo:: n(foo, 2)\n//│ ╙──      \t        ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:sjs\nlet m = M.Foo::m\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let m, m1; m1 = function m(self5, ...args5) { return self5.m(...args5) }; m = m1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ m = fun m\n\nm(foo)\n//│ = 124\n\nfoo m()\n//│ = 124\n\n\nM.{foo Foo::m()}\n//│ = 124\n\nM.{foo.Foo#m()}\n//│ = 124\n\ndo\n  open M\n  print of foo M.Foo::m()\n//│ > 124\n\ndo\n  open M\n  print of foo.Foo#m()\n//│ > 124\n\n// * This one still succeeds at runtime because the JS backend discards the class info\n:e\nfoo.Foo#m()\n//│ ╔══[COMPILATION ERROR] Name not found: Foo\n//│ ║  l.79: \tfoo.Foo#m()\n//│ ╙──      \t   ^^^^\n//│ ╔══[COMPILATION ERROR] Identifier `Foo` does not name a known class symbol.\n//│ ║  l.79: \tfoo.Foo#m()\n//│ ╙──      \t   ^^^^\n//│ ═══[COMPILATION ERROR] Expected a statically known class; found ‹error›.\n//│ = 124\n\n:e\n:re\nfoo.M.Foo::m()\n//│ ╔══[COMPILATION ERROR] Selection is not a known class.\n//│ ║  l.91: \tfoo.M.Foo::m()\n//│ ║        \t^^^^^^^^^\n//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\n//│ ╙──   add a space before ‹identifier› to make it an operator application.\n//│ ═══[RUNTIME ERROR] Error: Function expected at least 1 argument but got 0\n\n:e\n:re\nfoo.M.Foo#m()\n//│ ╔══[COMPILATION ERROR] Name not found: Foo\n//│ ║  l.101: \tfoo.M.Foo#m()\n//│ ╙──       \t     ^^^^\n//│ ╔══[COMPILATION ERROR] Identifier `Foo` does not name a known class symbol.\n//│ ║  l.101: \tfoo.M.Foo#m()\n//│ ╙──       \t     ^^^^\n//│ ═══[COMPILATION ERROR] Expected a statically known class; found ‹error›.\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'M' yielded 'undefined'\n\n:e\nFoo::m\n//│ ╔══[COMPILATION ERROR] Name not found: Foo\n//│ ║  l.112: \tFoo::m\n//│ ╙──       \t^^^\n//│ ╔══[COMPILATION ERROR] Identifier is not a known class.\n//│ ║  l.112: \tFoo::m\n//│ ║         \t^^^\n//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\n//│ ╙──   add a space before ‹identifier› to make it an operator application.\n//│ ═══[COMPILATION ERROR] Expected a statically known class; found ‹error›.\n//│ = fun\n\n:e\n:sjs\n:noInline\nFoo::n(foo, 2)\n//│ ╔══[COMPILATION ERROR] Name not found: Foo\n//│ ║  l.127: \tFoo::n(foo, 2)\n//│ ╙──       \t^^^\n//│ ╔══[COMPILATION ERROR] Identifier is not a known class.\n//│ ║  l.127: \tFoo::n(foo, 2)\n//│ ║         \t^^^\n//│ ╟── Note: any expression of the form `‹expression›::‹identifier›` is a member projection;\n//│ ╙──   add a space before ‹identifier› to make it an operator application.\n//│ ═══[COMPILATION ERROR] Expected a statically known class; found ‹error›.\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda9;\n//│ lambda9 = (undefined, function (self7, ...args7) {\n//│   return runtime.safeCall(self7.n(...args7))\n//│ });\n//│ runtime.safeCall(lambda9(foo, 2))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 125\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MiscArrayTests.mls",
    "content": ":js\n\n\nlet xs = [0, 1, 2]\n//│ xs = [0, 1, 2]\n\nxs \\print()\n//│ > [0, 1, 2]\n\n:re\nxs.reverse()\n//│ ═══[RUNTIME ERROR] TypeError: Cannot assign to read only property '0' of object '[object Array]'\n\nxs\n//│ = [0, 1, 2]\n\nlet xs = mut [...xs]\n//│ xs = [0, 1, 2]\n\nlet f = xs \\print\n//│ f = fun\n\nf()\n//│ > [0, 1, 2]\n\nxs.reverse()\n//│ = [2, 1, 0]\n\n:re\nxs.map(x => x * 2)\n//│ ═══[RUNTIME ERROR] Error: Function expected 1 argument but got 3\n\nxs.map((x, i, a) => x * 2)\n//│ = [4, 2, 0]\n\nxs.map((x, ...) => x * 2)\n//│ = [4, 2, 0]\n\nxs.map((x, ..._) => x * 2)\n//│ = [4, 2, 0]\n\nfun map(xs, f) = xs.map((x, ...bs) => f(x))\n\nxs \\map(x => x * 2) \\print()\n//│ > [4, 2, 0]\n\n// * Note: the RHS of `\\` is a self-contained block, thus implicitly parenthesized.\n:sjs\n:e\n:re\nxs \\\n  map(x => x * 2)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.52: \t  map(x => x * 2)\n//│ ╙──      \t     ^^^^^^^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda5, tmp1;\n//│ lambda5 = (undefined, function (x) { return x * 2 });\n//│ tmp1 = map(lambda5);\n//│ Predef.passTo(xs1, tmp1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Function 'map' expected 2 arguments but got 1\n\n:e\n:re\nxs\\\n  map(x => x * 2)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.67: \t  map(x => x * 2)\n//│ ╙──      \t     ^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Function 'map' expected 2 arguments but got 1\n\n:pt\nxs\n  \\ map(f)\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ App:\n//│   lhs = OpApp:\n//│     lhs = Ident of \"xs\"\n//│     op = Ident of \"\\\\\"\n//│     rhss = Ls of \n//│       Ident of \"map\"\n//│   rhs = Tup of Ls of \n//│     Ident of \"f\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > [2, 1, 0] 2\n//│ > [2, 1, 0] 1\n//│ > [2, 1, 0] 0\n//│ = [(), (), ()]\n\nxs\n  \\map(x => x * 2)\n//│ = [4, 2, 0]\n\nxs\n  \\map(x => x * 2)\n  \\print()\n//│ > [4, 2, 0]\n\nfun f = print(0)\n\nf\n//│ > 0\n\nf\n//│ > 0\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ModuleMethods.mls",
    "content": "module M\nmodule MM[T]\n\n\n\n// Parameters\n\n:e\nfun f(m: M)\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference.\n//│ ║  l.9: \tfun f(m: M)\n//│ ╙──     \t         ^\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference of type M denoting module 'M'.\n//│ ║  l.9: \tfun f(m: M)\n//│ ║       \t         ^\n//│ ╙── Non-module parameter must have a non-module type.\n\nfun f(m)\n\n:e\nf(M)\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.21: \tf(M)\n//│ ║        \t  ^\n//│ ╙── Module argument passed to a non-module parameter.\n\nf(42)\n\n:e\nfun f(module m)\n//│ ╔══[COMPILATION ERROR] Module parameter must have explicit type.\n//│ ║  l.30: \tfun f(module m)\n//│ ╙──      \t             ^\n\nfun f(module m: M)\n\nf(42)\n\nf(M)\n\n:e\nfun f[T](module m: T)\n//│ ╔══[COMPILATION ERROR] Expected a module type; found reference.\n//│ ║  l.42: \tfun f[T](module m: T)\n//│ ╙──      \t                   ^\n//│ ╔══[COMPILATION ERROR] Expected a module type; found reference.\n//│ ║  l.42: \tfun f[T](module m: T)\n//│ ║        \t                   ^\n//│ ╙── Module parameter must have a module type.\n\nfun f[T](module m: MM[T])\n\nf[Int](42)\n\n\nf[Int](MM[Int])\n\n\n\n// Results\n\nfun assertM(module m: M)\nfun assertNonM(m)\nfun assertMM[T](module m: MM[T])\nfun assertNonMM[T](m)\n\n:e\nfun f() = M\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.68: \tfun f() = M\n//│ ║        \t          ^\n//│ ╙── Function must be marked as returning a 'module' in order to return a module.\n\n:e\nfun f(): M = M\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference of type M denoting module 'M'.\n//│ ║  l.75: \tfun f(): M = M\n//│ ║        \t         ^\n//│ ╙── Function must be marked as returning a 'module' in order to have a module return type.\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.75: \tfun f(): M = M\n//│ ║        \t             ^\n//│ ╙── Function must be marked as returning a 'module' in order to return a module.\n\nfun f(): module M = M\n\n:e\nassertNonM(f())\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful application of type M.\n//│ ║  l.88: \tassertNonM(f())\n//│ ║        \t           ^^^\n//│ ╙── Module argument passed to a non-module parameter.\n\nassertM(f())\n\n:e\nfun f4[T](): module T = M\n//│ ╔══[COMPILATION ERROR] Expected a module type; found reference.\n//│ ║  l.97: \tfun f4[T](): module T = M\n//│ ║        \t                    ^\n//│ ╙── Function marked as returning a 'module' must have a module return type.\n\nfun f[T](): module MM[T] = MM[T]\n\n:e\nassertNonM(f[Int]())\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful application of type MM[T].\n//│ ║  l.106: \tassertNonM(f[Int]())\n//│ ║         \t           ^^^^^^^^\n//│ ╙── Module argument passed to a non-module parameter.\n\nassertM(f[Int]())\n\n\n:todo\n:e\nfun f3() = return M\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.117: \tfun f3() = return M\n//│ ╙──       \t                  ^\n\n:todo\n:e\nfun f3() = (() => M)()\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.124: \tfun f3() = (() => M)()\n//│ ╙──       \t                  ^\n\n// * [test:T4]\n:todo\n:e\n:effectHandlers\n:lift\nfun f3() = (() => return M)()\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.134: \tfun f3() = (() => return M)()\n//│ ╙──       \t                         ^\n\n\n\n// Parameters Modulefulness\n\n:e\nfun f(module m: M) = m\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.144: \tfun f(module m: M) = m\n//│ ║         \t                     ^\n//│ ╙── Function must be marked as returning a 'module' in order to return a module.\n\nfun f(module m: M): module M = m\n\n\n\n// Val Bindings\n\n:e\nval v = M\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.157: \tval v = M\n//│ ║         \t        ^\n//│ ╙── Value must be marked as returning a 'module' in order to return a module.\n\nval v: module M = M\n\n\n\n// *Module* Methods\n\nmodule N with\n  fun foo(): module M = M\n  fun bar(module m: M): module M = foo()\n\nN.bar(M)\n\n// Methods / Fields\n\n:e\nclass C with\n  fun foo: module M = M\n  val bar: module M = M\n//│ ╔══[COMPILATION ERROR] Function returning modules should not be a class member.\n//│ ║  l.179: \t  fun foo: module M = M\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Value returning modules should not be a class member.\n//│ ║  l.180: \t  val bar: module M = M\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Modules.mls",
    "content": "// :flow\n\n\nmodule Foo\n\n:pe\nmodule Foo with\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found end of input instead\n//│ ║  l.7: \tmodule Foo with\n//│ ╙──     \t               ^\n\n:e\nmodule Foo with val x = 1\n//│ ╔══[COMPILATION ERROR] Illegal body of module definition (should be a block; found term definition).\n//│ ║  l.13: \tmodule Foo with val x = 1\n//│ ╙──      \t                ^^^^^^^^^\n\n:e\nFoo.x\n//│ ╔══[COMPILATION ERROR] Module 'Foo' does not contain member 'x'\n//│ ║  l.19: \tFoo.x\n//│ ╙──      \t   ^^\n\nmodule Foo with\n  val x = 1\n\nFoo\n\nFoo.x\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MultiParamListClasses.mls",
    "content": ":js\n\n\ndata class Foo(x, y)(z)\n\nFoo\n//│ = fun Foo { class: class Foo }\n\nFoo(1, 2)\n//│ = fun\n\nFoo(1, 2)(3)\n//│ = Foo(1, 2)\n\n:re\n:sir\nFoo(1, 2)(3)(4)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let baseCall; set baseCall = Foo⁰(1, 2)(3); baseCall(4)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: baseCall is not a function\n\n\nnew Foo(1, 2)\n//│ = fun\n\nnew Foo(1, 2)(3)\n//│ = Foo(1, 2)\n\n:re\n:sir\nnew Foo(1, 2)(3)(4)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let baseInst; set baseInst = new Foo¹(1, 2)(3); baseInst(4)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: baseInst is not a function\n\n\n:sir\nnew Foo(1, 2)(3)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ new Foo¹(1, 2)(3)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo(1, 2)\n\n:sir\nnew Foo(1, 2)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda⁰; define lambda⁰ as fun lambda¹(z) { return new Foo¹(1, 2)(z) }; lambda¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n:todo\ndata class Foo with\n  constructor(x, y)\n//│ ╔══[PARSE ERROR] Expected block after constructor keyword; found parenthesis section instead\n//│ ║  l.56: \t  constructor(x, y)\n//│ ╙──      \t             ^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.56: \t  constructor(x, y)\n//│ ╙──      \t              ^\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.56: \t  constructor(x, y)\n//│ ╙──      \t                 ^\n\n:todo\ndata class Foo with\n  constructor(x, y)(z)\n//│ ╔══[PARSE ERROR] Expected block after constructor keyword; found parenthesis section instead\n//│ ║  l.69: \t  constructor(x, y)(z)\n//│ ╙──      \t             ^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.69: \t  constructor(x, y)(z)\n//│ ╙──      \t              ^\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.69: \t  constructor(x, y)(z)\n//│ ╙──      \t                 ^\n//│ ╔══[COMPILATION ERROR] Name not found: z\n//│ ║  l.69: \t  constructor(x, y)(z)\n//│ ╙──      \t                    ^\n\n\n// class Foo(using z: Int)\n// * is to be understood as\nclass Foo0\nfun Foo(using z: Int) = new mut Foo0 !> res =>\n  set res.z = z\n\nusing Int = 123\n\nFoo\n//│ = Foo0 { z: 123 }\n\n// class Foo(x, y)(using z)\n// * is to be understood as\nclass Foo0\nfun Foo(x, y)(using z: Int) = new mut Foo0 !> res =>\n  set\n    res.x = x\n    res.y = y\n    res.z = z\n\n\nFoo(1, 2)\n//│ = Foo0 { x: 1, y: 2, z: 123 }\n\n:sjs\nlet f = Foo // should compile to `(x, y) => Foo(x, y)(use[Int])`\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f, f1; f1 = function f(x, y) { return Foo7(x, y)(instance$Ident$_Int$_) }; f = f1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\n// Eta-expansion happens here. See EtaExpansion.mls.\nf(1, 2)\n//│ = Foo0 { x: 1, y: 2, z: 123 }\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MultiParamLists.mls",
    "content": ":js\n\n:global\n:sjs\n\n\nfun f(n1: Int): Int = n1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f; f = function f(n1) { return n1 };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(42)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f(42)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n// TODO compile this to\n// function f(n1) { return (n2) => f$(n1, n2); }\n// function f$(n1, n2) { let tmp; tmp = 10 * n1; return tmp + n2; }\n\nfun f(n1: Int)(n2: Int): Int =  (10 * n1 + n2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1; f1 = function f(n1) { return (n2) => { let tmp; tmp = 10 * n1; return tmp + n2 } };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// TODO compile this to\n// this.f$(4, 2)\n\nf(4)(2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f1(4)(2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\nfun f(n1: Int)(n2: Int)(n3: Int): Int = 10 * (10 * n1 + n2) + n3\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2;\n//│ f2 = function f(n1) {\n//│   return (n2) => {\n//│     return (n3) => {\n//│       let tmp, tmp1, tmp2;\n//│       tmp = 10 * n1;\n//│       tmp1 = tmp + n2;\n//│       tmp2 = 10 * tmp1;\n//│       return tmp2 + n3\n//│     }\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(4)(2)(0)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f2(4)(2)(0)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 420\n\nfun f(n1: Int)(n2: Int)(n3: Int)(n4: Int): Int = 10 * (10 * (10 * n1 + n2) + n3) + n4\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f3;\n//│ f3 = function f(n1) {\n//│   return (n2) => {\n//│     return (n3) => {\n//│       return (n4) => {\n//│         let tmp, tmp1, tmp2, tmp3, tmp4;\n//│         tmp = 10 * n1;\n//│         tmp1 = tmp + n2;\n//│         tmp2 = 10 * tmp1;\n//│         tmp3 = tmp2 + n3;\n//│         tmp4 = 10 * tmp3;\n//│         return tmp4 + n4\n//│       }\n//│     }\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(3)(0)(3)(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f3(3)(0)(3)(1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3031\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MultilineExpressions.mls",
    "content": ":js\n\n\n2 * 2 + 1\n//│ = 5\n\n2 *\n  2 + 1\n//│ = 6\n\n2 *\n  2 +\n  1\n//│ = 6\n\n\nfun (**) f1(a, b) = \"[\" + a + \" * \" + b + \"]\"\nfun (++) f2(a, b) = \"(\" + a + \" + \" + b + \")\"\n\n\n1 ** 2 ++ 3\n//│ = \"([1 * 2] + 3)\"\n\n1 ** 2\n  ++ 3\n//│ = \"([1 * 2] + 3)\"\n\n1 ** 2\n  ++ 3\n  ++ 4\n//│ = \"(([1 * 2] + 3) + 4)\"\n\n1 ++ 2\n  ** 3\n  ** 4\n//│ = \"(1 + [[2 * 3] * 4])\"\n\n1 ++ 2\n  ** 3\n    ** 4\n//│ = \"(1 + [[2 * 3] * 4])\"\n\n// TODO warn or error on such operator blocks\n1 ++ 2\n  ** 3\n  ++ 4\n//│ = \"((1 + [2 * 3]) + 4)\"\n\n1 ++ 2\n    ** 3\n  ++ 4\n//│ = \"((1 + [2 * 3]) + 4)\"\n\n1 ++ 2\n    ** 3\n  ** 4\n//│ = \"(1 + [[2 * 3] * 4])\"\n\n\n// FIXME problematic elaboration? or not?\n:pt\n// :elt\n:sjs\n:re\nif 1 + 2\n  * 3 then 0\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = OpApp:\n//│       lhs = IntLit of 1\n//│       op = Ident of \"+\"\n//│       rhss = Ls of \n//│         OpApp:\n//│           lhs = IntLit of 2\n//│           op = Ident of \"*\"\n//│           rhss = Ls of \n//│             IntLit of 3\n//│     kw = Keywrd of keyword 'then'\n//│     rhs = IntLit of 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut, tmp17;\n//│ tmp17 = 2 * 3;\n//│ scrut = 1 + tmp17;\n//│ if (scrut === true) {\n//│   0\n//│ } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:pt\n:re\nif 1 * 2\n  + 3 then 0\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = OpApp:\n//│       lhs = OpApp:\n//│         lhs = IntLit of 1\n//│         op = Ident of \"*\"\n//│         rhss = Ls of \n//│           IntLit of 2\n//│       op = Ident of \"+\"\n//│       rhss = Ls of \n//│         IntLit of 3\n//│     kw = Keywrd of keyword 'then'\n//│     rhs = IntLit of 0\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: match error\n\n// TODO perhaps we should just require parenthesizing (1 + 2) here\n:pe\n:e\nif 1 + 2\n  * 3 then 0\n  + 4 then 1\n//│ ╔══[PARSE ERROR] Operator cannot be used inside this operator split\n//│ ║  l.119: \t  + 4 then 1\n//│ ║         \t  ^\n//│ ╟── as it has lower precedence than the splitting operator here\n//│ ║  l.118: \t  * 3 then 0\n//│ ╙──       \t  ^\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword in this operator split inner position\n//│ ║  l.119: \t  + 4 then 1\n//│ ║         \t      ^^^^\n//│ ╟── Note: the operator split starts here\n//│ ║  l.118: \t  * 3 then 0\n//│ ╙──       \t  ^\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.117: \tif 1 + 2\n//│ ║         \t       ^\n//│ ║  l.118: \t  * 3 then 0\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.119: \t  + 4 then 1\n//│ ╙──       \t^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:pt\n:re\nif (1 + 2)\n  * 3 then 0\n  + 4 then 1\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = OpSplit:\n//│     lhs = Bra:\n//│       k = Round\n//│       inner = OpApp:\n//│         lhs = IntLit of 1\n//│         op = Ident of \"+\"\n//│         rhss = Ls of \n//│           IntLit of 2\n//│     ops_rhss = Ls of \n//│       InfixApp:\n//│         lhs = OpApp:\n//│           lhs = SplitPoint\n//│           op = Ident of \"*\"\n//│           rhss = Ls of \n//│             IntLit of 3\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = IntLit of 0\n//│       InfixApp:\n//│         lhs = OpApp:\n//│           lhs = SplitPoint\n//│           op = Ident of \"+\"\n//│           rhss = Ls of \n//│             IntLit of 4\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = IntLit of 1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: match error\n\nif (1 + 2)\n  * 3 === 8 then 0\n  + 4 === 7 then 1\n//│ = 1\n\nif 1 + 0\n    == 0 then \"X\"\n    == 1 then \"A\"\n//│ = \"A\"\n\nif (1 + 1)\n    * 2 == 4 then \"X\"\n    * 2 == 1 then \"A\"\n    |> id is r then r\n//│ = \"X\"\n\n\n1 ++\n  2\n//│ = \"(1 + 2)\"\n\n// TODO reject – hard to read; should be a postfix op\n// But then what about versions with many indented lines? -> require putting the op at line starts\n1 ++\n2\n//│ = \"(1 + 2)\"\n\n// * Note that the argument to the first `++` is a self-contained block, thus implicitly parenthesized.\n1 ++\n  2 ++\n  3\n//│ = \"(1 + (2 + 3))\"\n\n1 ++\n2 ++\n3\n//│ = \"((1 + 2) + 3)\"\n\n1 ++\n  2 **\n  3\n//│ = \"(1 + [2 * 3])\"\n\n// * Note that the argument to `**` is a self-contained block, thus implicitly parenthesized.\n1 **\n  2 ++\n  3\n//│ = \"[1 * (2 + 3)]\"\n\n1 ++\n  2 ++\n  3 ++\n  4\n//│ = \"(1 + ((2 + 3) + 4))\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MutArr.mls",
    "content": ":js\n\n\n:sjs\nlet t = [0, 1, 2]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let t; t = globalThis.Object.freeze([ 0, 1, 2 ]);\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ t = [0, 1, 2]\n\n:re\nt.push(4)\n//│ ═══[RUNTIME ERROR] TypeError: Cannot add property 3, object is not extensible\n\n// Has no effect, as t is frozen\nset t.[1] = 5\n\nt\n//│ = [0, 1, 2]\n\n\n:sjs\nlet t = mut [0, 1, 2]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let t1; t1 = [ 0, 1, 2 ];\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ t = [0, 1, 2]\n\nt.push(4)\n//│ = 4\n\nset t.[1] = 5\n\nt\n//│ = [0, 5, 2, 4]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MutCls.mls",
    "content": ":js\n\n\nclass C(val x)\n\nlet c = C(1)\n//│ c = C(1)\n\nset c.x = 2\n\nc\n//│ = C(1)\n\n\nclass Foo(val x)(val y)\n\nlet f = Foo(1)(2)\n//│ f = Foo(1)\n\nf.y\n//│ = 2\n\nset f.y = 3\n\nf.y\n//│ = 2\n\n\nclass Foo with\n  fun foo() = 1\n  fun bar = 2\n\n\nlet f = new mut Foo\n//│ f = Foo\n\nset f.foo = () => 3\nf.foo()\n//│ = 3\n\nset f.bar = 3\nf.bar\n//│ = 2\n\n\nlet f = new Foo\n//│ f = Foo\n\nset f.foo = () => 3\nf.foo()\n//│ = 1\n\nset f.bar = 3\nf.bar\n//│ = 2\n\n\n// * TODO: later, we might want to distinguish freezing from sealing;\n// * `new` would freeze and `new mut` would solely seal; `new open` would do neither.\n\n// let o = new open Object\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MutRcd.mls",
    "content": ":js\n\n\nlet r = {a: 0}\n//│ r = {a: 0}\n\nset\n  r.a = 1\n  r.foo = 1\n\n:expect 0\nr.a\n//│ = 0\n\n:re\nr.foo\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'foo' yielded 'undefined'\n\n\nlet r = mut {a: 1}\n//│ r = {a: 1}\n\nset\n  r.a = 1\n  r.foo = 1\n\n:expect 1\nr.a\n//│ = 1\n\n:expect 1\nr.foo\n//│ = 1\n\n\nlet r = mut {}\n//│ r = {}\n\nset r.foo = 1\n\n:expect 1\nr.foo\n//│ = 1\n\n\n:sjs\nlet r = {}\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let r3; r3 = runtime.Unit;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ r = ()\n\n:re\nr.x\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\nset r.foo = 1\n\n:re\nr.foo\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'foo' yielded 'undefined'\n\n:re\n().foo\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'foo' yielded 'undefined'\n\nlet s = {}\n//│ s = ()\n\nset s.foo = 2\n\n:re\nr.foo\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'foo' yielded 'undefined'\n\n\n:e\nmut()\n//│ ╔══[COMPILATION ERROR] Illegal position for 'mut' modifier.\n//│ ║  l.78: \tmut()\n//│ ╙──      \t^^^\n\n\nlet r = mut\n  x: 1\n//│ r = {x: 1}\n\nObject.freeze(r)\n//│ = {x: 1}\n\nset r.x = 2\n\n:expect 1\nr.x\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/MutVal.mls",
    "content": ":js\n\n\nmut val cached: Int = 1\n//│ cached = 1\n\n:sjs\nset cached = 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ cached = 2; runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ncached\n//│ = 2\n\n\nobject O with\n  val x = 1\n  let y = 1\n  fun gy = y\n  fun sy = set y += 1\n\nset O.x = 2\n\nO.x\n//│ = 1\n\nO.sy\n\nO.gy\n//│ = 2\n\n\n:soir\nclass Foo(x, val y, mut val z)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let Foo⁰;\n//│ define Foo⁰ as class Foo²(x, y, z) {\n//│   private val x⁰;\n//│   val y⁰;\n//│   val z⁰;\n//│   constructor Foo¹ { define y⁰ as val y¹ = y; define z⁰ as val z¹ = z; end }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:soir\nclass Foo(x, val y, mut val z) with\n  print(x)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let Foo³;\n//│ define Foo³ as class Foo⁵(x, y, z) {\n//│   private val x¹;\n//│   val y²;\n//│   val z²;\n//│   constructor Foo⁴ {\n//│     set x¹ = x;\n//│     define y² as val y³ = y;\n//│     define z² as val z³ = z;\n//│     do Predef⁰.print⁰(x¹);\n//│     end\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet f = Foo(1, 2, 3)\n//│ > 1\n//│ f = Foo(_, 2, 3)\n\nf.z\n//│ = 3\n\nset f.z = 0\n\nf.z\n//│ = 0\n\n\ndata class Foo(mut val x)\n\nlet f = Foo(1)\n//│ f = Foo(1)\n\nset f.x = 2\n\nf.x\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/NamedArgs.mls",
    "content": ":js\n\n\n// * Named tuple\n\n[a: 0]\n//│ = [{a: 0}]\n\n[1, 2, a: \"a\", 3, b: \"b\", 4, 5]\n//│ = [1, 2, 3, 4, 5, {a: \"a\", b: \"b\"}]\n\nlet r = [4, 5, c: \"c\"]\n//│ r = [4, 5, {c: \"c\"}]\n\n[1, 2, a: \"a\", 3, b: \"b\", ...r]\n//│ = [1, 2, 3, 4, 5, {c: \"c\"}, {a: \"a\", b: \"b\"}]\n\n\nlet aa = 123\n//│ aa = 123\n\n[aa: 0]\n//│ = [{aa: 0}]\n\n[aa: aa]\n//│ = [{aa: 123}]\n\n\n// * Named arguments\n\n// :de\n:elt\nid(a: 0)\n//│ —————————————| Elaborated tree |————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App:\n//│     lhs = SynthSel{sym=member:id⁰}:\n//│       prefix = Ref{sym=member:Predef⁰} of member:Predef⁰\n//│       nme = Ident of \"id\"\n//│     rhs = Tup of Ls of \n//│       Fld:\n//│         term = Lit of StrLit of \"a\"\n//│         asc = S of Lit of IntLit of 0\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = {a: 0}\n\nid of a: 0\n//│ = {a: 0}\n\n\nprint of\n  foo: 1\n  bar:\n    \"...\"\n//│ > {foo: 1, bar: \"...\"}\n\nprint of\n  \"Hello\"\n  foo: 1\n  bar:\n    \"...\"\n  \"World\"\n//│ > Hello World {foo: 1, bar: \"...\"}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/NestedBlocks.mls",
    "content": ":js\n\n\n// * Checking that a `val` in a nested block is not treated as a member of the enclosing object\n\nobject Foo with\n  if true then\n    val x = 0\n\n:e\n:re\nFoo.x\n//│ ╔══[COMPILATION ERROR] Object 'Foo' does not contain member 'x'\n//│ ║  l.12: \tFoo.x\n//│ ╙──      \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n\nmodule Oops with\n  if true then\n    fun f = 1\n    ()\n\n// * We used to forget to reset the owner to None in sub-blocks like this one\n:e\n:re\nobject Oops with\n  if true then\n    val fakeField = 1\n    print(fakeField)\n  print(this.fakeField) // shouldn't work!\n//│ ╔══[COMPILATION ERROR] Object 'Oops' does not contain member 'fakeField'\n//│ ║  l.31: \t  print(this.fakeField) // shouldn't work!\n//│ ╙──      \t        ^^^^^^^^^^^^^^\n//│ > 1\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'fakeField' yielded 'undefined'\n\n:e\n:re\nOops.fakeField\n//│ ╔══[COMPILATION ERROR] Object 'Oops' does not contain member 'fakeField'\n//│ ║  l.40: \tOops.fakeField\n//│ ╙──      \t    ^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'fakeField' yielded 'undefined'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/New.mls",
    "content": ":js\n\n\nclass Foo\n\nnew Foo\n//│ = Foo\n\nnew Foo()\n//│ = Foo\n\nnew\n  Foo\n//│ = Foo\n\n:e\n:w\nnew\n  Foo\n  Foo\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found block.\n//│ ║  l.20: \t  Foo\n//│ ║        \t  ^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.19: \t  Foo\n//│ ╙──      \t  ^^^\n//│ = Foo\n\n// * Interesting... it tries to call `Foo()` and instantiate the resulting class value...\n:e\n:re\nnew\n  Foo()\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found application.\n//│ ║  l.34: \t  Foo()\n//│ ║        \t  ^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor Foo cannot be invoked without 'new'\n\n:e\nnew\n  Foo\n    ()\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (unit).\n//│ ║  l.44: \t    ()\n//│ ╙──      \t    ^^\n//│ = Foo\n\n:e\n:w\n:re\nnew\n  Foo\n  ()\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found block.\n//│ ║  l.55: \t  ()\n//│ ║        \t  ^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.54: \t  Foo\n//│ ╙──      \t  ^^^\n//│ ═══[RUNTIME ERROR] TypeError: runtime.Unit is not a constructor\n\n:e\nnew Foo\n  ()\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (unit).\n//│ ║  l.67: \t  ()\n//│ ╙──      \t  ^^\n//│ = Foo\n\n\nlet xs = [1,2,3]\n//│ xs = [1, 2, 3]\n\ndata class Foo(a,b,c)\n\nnew Foo(...xs)\n//│ = Foo(1, 2, 3)\n\nnew Foo(...[1, 2])\n//│ = Foo(1, 2, undefined)\n\nnew Foo(...[1, 2, 3, 4])\n//│ = Foo(1, 2, 3)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/NewMut.mls",
    "content": ":js\n\n\nclass Foo with\n  val x = 0\n  fun change =\n    set x += 1\n\n\n:sjs\nlet f = new Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f; f = globalThis.Object.freeze(new Foo1());\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = Foo { x: 0 }\n\nset\n  f.x = 1\n  f.y = 1\n\n:expect 0\nf.x\n//│ = 0\n\n:re\nf.change\n//│ ═══[RUNTIME ERROR] TypeError: Cannot assign to read only property 'x' of object '[object Object]'\n\n:expect 0\nf.x\n//│ = 0\n\n:re\nf.y\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'y' yielded 'undefined'\n\n\n:sjs\n// :elt\nlet f = new mut Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1; f1 = new Foo1();\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = Foo { x: 0 }\n\nset\n  f.x = 1\n  f.y = 1\n\nf.change\n\n:expect 2\nf.x\n//│ = 2\n\n:expect 1\nf.y\n//│ = 1\n\n\n:e\nlet f = mut new Foo\n//│ ╔══[COMPILATION ERROR] Illegal position for 'mut' modifier.\n//│ ║  l.62: \tlet f = mut new Foo\n//│ ╙──      \t        ^^^\n//│ f = Foo { x: 0 }\n\n:e\n:re\nnew mut Foo.x\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found selection.\n//│ ║  l.70: \tnew mut Foo.x\n//│ ║        \t        ^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n\nlet f = new mut Foo()\n//│ f = Foo { x: 0 }\n\nset\n  f.x = 1\n  f.y = 1\n\nf.change\n\n:expect 2\nf.x\n//│ = 2\n\n:expect 1\nf.y\n//│ = 1\n\n\nnew mut Foo().x\n//│ = 0\n\nnew Foo().x\n//│ = 0\n\n\n\nclass Foo(val x)\n\n\nlet f = new Foo(0)\n//│ f = Foo(0)\n\nset f.x = 1\n\n:expect 0\nf.x\n//│ = 0\n\n\nlet f = new mut Foo(0)\n//│ f = Foo(0)\n\nset f.x = 1\n\n:expect 1\nf.x\n//│ = 1\n\n\nlet f = Foo(0)\n//│ f = Foo(0)\n\nset\n  f.x = 1\n  f.y = 1\n\n:expect 0\nf.x\n//│ = 0\n\n:re\nf.y\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'y' yielded 'undefined'\n\n\n\nclass Foo(mut val x) with\n  mut val y = 0\n\n\nlet f = new Foo(0)\n//│ f = Foo(0)\n\nset\n  f.x = 1\n  f.y = 1\n\n// * Note that `mut val`s are backed by an internally mutable private field.\n\n:expect 1\nf.x\n//│ = 1\n\n:expect 1\nf.y\n//│ = 1\n\n\n\nlet f = new Object with\n  val x = 12\n//│ f = $anon { x: 12 }\n\nset\n  f.x = 1\n  f.y = 1\n\nf.x\n//│ = 12\n\n:re\nf.y\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'y' yielded 'undefined'\n\n\nlet f = new mut Object with\n  val x = 12\n//│ f = $anon { x: 12 }\n\nset\n  f.x = 1\n  f.y = 1\n\nf.x\n//│ = 1\n\nf.y\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/NewlineOperatorEnd.mls",
    "content": ":js\n\n\n// * Operators like ??? on a new line at end of block should be standalone expressions, not newline-infix\n\nfun parse(tokens) =\n  ()\n  ???\n\n\nfun parse(tokens) =\n  ()\n  ??? // oops\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/NewlineOps.mls",
    "content": ":js\n\n\n// * Operator continuations on a new line include the whole previous expression as LHS operand\n\n:p\n2\n+\n2\n//│ ┊2┊↵┊+┊↵┊2┊\n//│ Parsed:\n//│ \tOpApp(IntLit(2),Ident(+),List(IntLit(2)))\n//│ = 4\n\n2\n+\n2\n*\n2\n//│ = 8\n\n2\n+ 2\n* 2\n//│ = 8\n\n// * Notice the difference\n2\n+ 2\n  * 2\n//│ = 6\n\n// * Generally, operators on the *same indentation level* are sequenced – applied in order\n2\n  + 2\n  * 2\n//│ = 8\n\n// * Somehow this also parses...\n2\n  +\n2\n  *\n2\n//│ = 6\n\n\n2 + 2\n\\print()\n//│ > 4\n\n2 + 2\n  \\print()\n//│ > 2\n//│ = \"2()\"\n\n\nlet xs = [1, 2, 3]\nlet ys = [4, 5, 6]\nfun len(xs) = xs.length\n//│ xs = [1, 2, 3]\n//│ ys = [4, 5, 6]\n\nxs |> len\n+\nxs |> len\n|> print\n//│ > 6\n\n\n\n:w\n:pt\nlet r = 10 in r\n-1\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ LetLike:\n//│   kw = Keywrd of keyword 'let'\n//│   lhs = Ident of \"r\"\n//│   rhs = S of IntLit of 10\n//│   body = S of Ident of \"r\"\n//│ App:\n//│   lhs = Ident of \"-\"\n//│   rhs = Tup of Ls of \n//│     IntLit of 1\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.74: \tlet r = 10 in r\n//│ ╙──      \t              ^\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = -1\n\nlet r = 10 in id(r)\n-1\n//│ = -1\n\nlet r = 10\n-1\n//│ = -1\n//│ r = 10\n\nlet r = id(id)(10)\n-1\n//│ = -1\n//│ r = 10\n\n:pt\nlet r = id(10)\n!(r)\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ LetLike:\n//│   kw = Keywrd of keyword 'let'\n//│   lhs = Ident of \"r\"\n//│   rhs = S of App:\n//│     lhs = Ident of \"id\"\n//│     rhs = Tup of Ls of \n//│       IntLit of 10\n//│ App:\n//│   lhs = Ident of \"!\"\n//│   rhs = Tup of Ls of \n//│     Bra:\n//│       k = Round\n//│       inner = Ident of \"r\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ r = 10\n\n\n\n// fun solution(bd, c, n) =\n//   if true then\n//     let a = 1\n//     a\n//   else ???\n\n\nif 0\n  === 1 then 2\n  else 3\n//│ = 3\n\n\nlet x\n= 1\n//│ x = 1\n\nlet x = 1\n//│ x = 1\n\nlet x\n= 1\n//│ x = 1\n\n\n2\n  + 1\n* 2\n//│ = 6\n\n2\n  |> (a: _)\n  .a\n//│ = 2\n\n:re\n2\n  |> (a: _)\n    .a\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'a' yielded 'undefined'\n\n:ge\n:re\n2\n  |> (a: _)\n.a\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (leading dot selection)\n//│ ║  l.173: \t.a\n//│ ╙──       \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n// :dp\n2\n    * 1\n  + 2\n//│ = 4\n\n// :dp\n2\n    * 1\n      + 2\n//│ = 4\n\n2\n    * 1\n      + 2\n      + 2\n//│ = 6\n\n2\n    * 1\n      + 2\n    + 2\n//│ = 6\n\n// :dp\n2 {+ 1} * 2\n//│ = 4\n\n{2\n  + 1} * 2\n//│ = 6\n\n{2 { + 1 }} * 2\n//│ = 6\n\n2 { * 1 { + 2 } }\n//│ = 4\n\n// :dp\n2\n    + 1\n      * 2\n//│ = 4\n\n2\n    + 1\n      * 2\n      * 2\n//│ = 6\n\n2\n    + 1\n      * 2\n    * 2\n//│ = 8\n\n\n2\n    + 1\n      |> print\n//│ > 3\n\n2\n    + 1\n    + 1\n      |> print\n//│ > 4\n\n2\n    + 1 |> print\n//│ > 3\n\n2\n    + 1\n    + 1 |> print\n//│ > 4\n\n2\n    + 1\n  |> print\n//│ > 3\n\nlet incr = _ + 1\n//│ incr = fun incr\n\n// :dp\n2\n    + 1\n    + 1\n  |> print\n//│ > 4\n\n2\n    + 1\n    + 1\n  |> incr\n  |> print\n//│ > 5\n\n2\n    + 1\n    + 1\n  |> incr\n    |> print\n//│ > 5\n\n2\n      + 1\n      + 1\n    |> incr\n  |> print\n//│ > 5\n\n// Uh...\n2\n      + 1\n      !> print\n      + 1\n    |> incr\n      !> print\n  |> print\n//│ > 3\n//│ > 5\n//│ > 5\n\n\n{1} + {1}\n//│ = 2\n\n{111} + {222} + {333}\n//│ = 666\n\n\n2\n* 3\n//│ = 6\n\n:pe\n:w\n2, * 3\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.319: \t2, * 3\n//│ ╙──       \t     ^\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.319: \t2, * 3\n//│ ╙──       \t^\n//│ = fun\n\n2,* 3\n//│ = 6\n\n2 ,* 3\n//│ = 6\n\n2 + 2\n* 3\n//│ = 12\n\n2 + 2 ,* 3\n//│ = 12\n\n2 + 2 ,* 2 + 2\n//│ = 10\n\n2 + 2 ,*, 2 + 2\n//│ = 16\n\nmodule Arr with\n  val len = _.length\n\nlet\n  xs = [1, 2]\n  ys = [3, 4, 5]\n//│ xs = [1, 2]\n//│ ys = [3, 4, 5]\n\nxs |> Arr.len\n+\nys |> Arr.len\n//│ = 5\n\nxs |> Arr.len,+\nys |> Arr.len\n//│ = 5\n\nxs |> Arr.len\n+, ys |> Arr.len\n//│ = 5\n\nxs |> Arr.len ,+, ys |> Arr.len\n//│ = 5\n\n:pe\n:re\nxs |> Arr.len\n,+\nys |> Arr.len\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found new line instead\n//│ ║  l.375: \t,+\n//│ ║         \t  ^\n//│ ║  l.376: \tys |> Arr.len\n//│ ╙──       \t\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nxs |> Arr.len\n,+ 1\n//│ = 1\n\n:pe\n:re\nxs |> Arr.len\n+,\nys |> Arr.len\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found new line instead\n//│ ║  l.391: \t+,\n//│ ║         \t  ^\n//│ ║  l.392: \tys |> Arr.len\n//│ ╙──       \t\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nxs |> Arr.len\n+, ys |> Arr.len\n//│ = 5\n\n// :pe\nxs |> Arr.len is 2 ,+, ys |> Arr.len\n//│ = 4\n\nxs |> Arr.len is 2 ,+, ys |> Arr.len is 3\n//│ = 2\n\n// :pe\nxs |> Arr.len is 2 ,+\nys |> Arr.len\n//│ = 4\n\n\n\n\nclass Foo(x)\n\nnew Foo(1) is Foo\n//│ = true\n\n:fixme // ?\nnew Foo(1) ,is Foo\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found 'is' keyword instead\n//│ ║  l.425: \tnew Foo(1) ,is Foo\n//│ ╙──       \t            ^^\n//│ ╔══[PARSE ERROR] Expected end of input; found identifier instead\n//│ ║  l.425: \tnew Foo(1) ,is Foo\n//│ ╙──       \t               ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:fixme // ?\nnew Foo(1)\nis Foo\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found 'is' keyword instead\n//│ ║  l.436: \tis Foo\n//│ ╙──       \t^^\n//│ ╔══[PARSE ERROR] Expected end of input; found identifier instead\n//│ ║  l.436: \tis Foo\n//│ ╙──       \t   ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/NewlineSels.mls",
    "content": ":js\n\n\nlet rcd = a: b: c: 1\n//│ rcd = {a: {b: {c: 1}}}\n\nrcd.a.b.c\n//│ = 1\n\nrcd\n  .a\n//│ = {b: {c: 1}}\n\nrcd\n  .a\n  .b\n//│ = {c: 1}\n\nrcd\n  .a.b\n//│ = {c: 1}\n\nrcd\n  .a\n  .b\n  .c\n//│ = 1\n\nrcd\n  .a.b.c\n//│ = 1\n\nrcd\n  .a.b\n  .c\n//│ = 1\n\n:todo\nrcd\n.a\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.39: \trcd\n//│ ╙──      \t^^^\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (leading dot selection)\n//│ ║  l.40: \t.a\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nlet rcd =\n  a: x => b: y => c: x + y\n//│ rcd = {a: fun a}\n\nrcd.a(1).b(2).c\n//│ = 3\n\nrcd\n  .a(1)\n  .b(2)\n  .c\n//│ = 3\n\nrcd\n  .a(1).b(2)\n  .c\n//│ = 3\n\nrcd\n  .a(1)\n  .b(2).c\n//│ = 3\n\nrcd\n  .a(1)\n  .b(2)\n  .c + 1\n//│ = 4\n\nrcd\n  .a(1) !> print\n  .b(2) !> print\n  .c !> print\n  + 1 !> print\n  + 1\n//│ > {b: fun b}\n//│ > {c: 3}\n//│ > 3\n//│ > 4\n//│ = 5\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ObjectExtensions.mls",
    "content": ":js\n\n\nobject Foo\n\n:fixme // Support?\nnew Foo\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference of type Foo.\n//│ ║  l.7: \tnew Foo\n//│ ║       \t    ^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: Foo1 is not a constructor\n\n:re\nnew! Foo\n//│ ═══[RUNTIME ERROR] TypeError: Foo1 is not a constructor\n\n:fixme // Support?\nnew! Foo.class\n//│ ╔══[COMPILATION ERROR] Object 'Foo' does not contain member 'class'\n//│ ║  l.19: \tnew! Foo.class\n//│ ╙──      \t        ^^^^^^\n//│ = Foo\n\nnew! Foo!class\n//│ = Foo\n\n:fixme // Support?\nobject Bar extends Foo\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference of type Foo.\n//│ ║  l.29: \tobject Bar extends Foo\n//│ ║        \t                   ^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: Class extends value [object Object] is not a constructor or null\n\n:e\n:re\nobject Bar extends Foo!class\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found dynamic selection.\n//│ ║  l.38: \tobject Bar extends Foo!class\n//│ ║        \t                   ^^^^^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: Cannot redefine property: class\n\n:fixme // Support?\nobject Bar extends! Foo!class\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference.\n//│ ║  l.46: \tobject Bar extends! Foo!class\n//│ ║        \t                  ^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/OfLambdaArgs.mls",
    "content": ":js\n\n\nfun id(x) = x\nfun foo(f, g) = f(g(1))\n\n\nfoo(id(x => 1), id(y => 2)) \n//│ = 1\n\nfoo of (id of x => 1), id of y => 2\n//│ = 1\n\n:e\n:re\nfoo(id of x => 1, id of y => 2) \n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.16: \tfoo(id of x => 1, id of y => 2) \n//│ ╙──      \t   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected 1 arguments, got 2\n//│ ║  l.16: \tfoo(id of x => 1, id of y => 2) \n//│ ╙──      \t          ^^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Function 'id' expected 1 argument but got 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/OpBlocks.mls",
    "content": ":js\n\n\n2\n  + 2\n//│ = 4\n\n2\n  + 2\n  + 2\n//│ = 6\n\n2\n  + 1\n  * 2\n//│ = 6\n\n2\n  + 1\n    * 2\n//│ = 4\n\n// * Note: indented newlines starting with an operator are always treated as continuations\n// * of the previous line, without any implicit grouping of the indented parts,\n// * explaining the result below.\n// * I originally tried to make such indented operators implicitly group subexpressions,\n// * but it turned out to be just too strange and confusing; the simple rule above seems better.\n2\n    + 1\n  * 2\n//│ = 4\n\n\n2 + 2\n//│ = 4\n\n1 + 2\n  * 3\n//│ = 7\n\n1 + 2\n  * 2\n  * 2\n//│ = 9\n\n1 + 2\n  * 3 + 1\n//│ = 8\n\n2 *\n  3 + 1\n//│ = 8\n\n2\n  *\n    3 + 1\n//│ = 8\n\n2\n  *\n  3 + 1\n//│ = 7\n\n// :pe\n2\n  *\n3 + 1\n//│ = 7\n\n1 + 1\n  *\n2\n//│ = 3\n\n1 + 1\n*\n2\n//│ = 4\n\n// Parses as: 1 + (1 * 3) + 1\n1 + 1\n  *\n3 + 1\n//│ = 5\n\n// :dp\n1 + 2\n  * 3\n    + 1\n//│ = 8\n\n:pe\n1 + 2\n  * 2\n    + 1\n  * 3\n//│ ╔══[PARSE ERROR] Unexpected indented block in this operator split inner position\n//│ ║  l.95: \t    + 1\n//│ ║        \t^^^^^^^\n//│ ║  l.96: \t  * 3\n//│ ║        \t^^\n//│ ╟── Note: the operator split starts here\n//│ ║  l.94: \t  * 2\n//│ ╙──      \t  ^\n//│ = 12\n\n:pe\n1 + 2\n  * 2 +\n    1\n  * 3\n//│ ╔══[PARSE ERROR] Operator cannot be used inside this operator split\n//│ ║  l.109: \t  * 2 +\n//│ ║         \t      ^\n//│ ╟── as it has lower precedence than the splitting operator here\n//│ ║  l.109: \t  * 2 +\n//│ ╙──       \t  ^\n//│ = 19\n\n:pe\n1 + 2\n  * 2\n  * 3\n    + 1\n//│ ╔══[PARSE ERROR] Unexpected indented block in this operator split inner position\n//│ ║  l.124: \t    + 1\n//│ ║         \t^^^^\n//│ ╟── Note: the operator split starts here\n//│ ║  l.122: \t  * 2\n//│ ╙──       \t  ^\n//│ = 6\n\n1 + 2 {* 3 {+ 1}}\n//│ = 8\n\n1 + 2\n  * 3\n  + 1\n//│ = 8\n\n:pe\n1 + 2\n  * 3 + 1\n  * 3\n//│ ╔══[PARSE ERROR] Operator cannot be used inside this operator split\n//│ ║  l.143: \t  * 3 + 1\n//│ ║         \t      ^\n//│ ╟── as it has lower precedence than the splitting operator here\n//│ ║  l.143: \t  * 3 + 1\n//│ ╙──       \t  ^\n//│ = 28\n\n// :pe\n1 + 2\n  * 3\n  * 3 + 1\n//│ = 8\n\n1 + 2\n  + 3\n  * 3 + 1\n//│ = 19\n\n\n:w\n1 >\n  1\n  0\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.167: \t  1\n//│ ╙──       \t  ^\n//│ = true\n\n\nlet f = x => x * 2\n//│ f = fun f\n\n2\n  + 1\n  |> f\n//│ = 6\n\nf\n  of 1\n//│ = 2\n\nf\n  |> id\n  of 1\n//│ = 2\n\n\nfun f(x)(y) = x + y\n\nf\n  of 1\n  of 2\n//│ = 3\n\nf\n  |> id\n  of 1\n  of 2\n//│ = 3\n\n\nfun f(a)(b) = [a, b]\nfun g(a, b) = [a, b]\n\nf of\n    g of\n      1\n      2\n  of 3\n//│ = [[1, 2], 3]\n\n(f of\n  g of\n    1\n    2\n) of 3\n//│ = [[1, 2], 3]\n\n\nfun f(x) = x\n  + 1\n\nf(123)\n//│ = 124\n\n\nfun f(x) = x\n  * 2\n  + 1\n\nf(123)\n//│ = 247\n\n\n:pt\nfun f(x) = x\n  + 1\n  * 2\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TermDef:\n//│   k = Fun\n//│   head = App:\n//│     lhs = Ident of \"f\"\n//│     rhs = Tup of Ls of \n//│       Ident of \"x\"\n//│   rhs = S of OpSplit:\n//│     lhs = Ident of \"x\"\n//│     ops_rhss = Ls of \n//│       OpApp:\n//│         lhs = SplitPoint\n//│         op = Ident of \"+\"\n//│         rhss = Ls of \n//│           IntLit of 1\n//│       OpApp:\n//│         lhs = SplitPoint\n//│         op = Ident of \"*\"\n//│         rhss = Ls of \n//│           IntLit of 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(123)\n//│ = 248\n\n\n:pt\nfun f(x) = x\n  + 1\n    * 2\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TermDef:\n//│   k = Fun\n//│   head = App:\n//│     lhs = Ident of \"f\"\n//│     rhs = Tup of Ls of \n//│       Ident of \"x\"\n//│   rhs = S of OpApp:\n//│     lhs = Ident of \"x\"\n//│     op = Ident of \"+\"\n//│     rhss = Ls of \n//│       OpApp:\n//│         lhs = IntLit of 1\n//│         op = Ident of \"*\"\n//│         rhss = Ls of \n//│           IntLit of 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(123)\n//│ = 125\n\n\nfun f(x) = x { + 1, * 2 }\n\nf(3)\n//│ = 8\n\n\n:pt\nfun f(x) = if x\n  == 0 then \"a\"\n  > 1 then \"b\"\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TermDef:\n//│   k = Fun\n//│   head = App:\n//│     lhs = Ident of \"f\"\n//│     rhs = Tup of Ls of \n//│       Ident of \"x\"\n//│   rhs = S of IfLike:\n//│     kw = Keywrd of keyword 'if'\n//│     split = OpSplit:\n//│       lhs = Ident of \"x\"\n//│       ops_rhss = Ls of \n//│         InfixApp:\n//│           lhs = OpApp:\n//│             lhs = SplitPoint\n//│             op = Ident of \"==\"\n//│             rhss = Ls of \n//│               IntLit of 0\n//│           kw = Keywrd of keyword 'then'\n//│           rhs = StrLit of \"a\"\n//│         InfixApp:\n//│           lhs = OpApp:\n//│             lhs = SplitPoint\n//│             op = Ident of \">\"\n//│             rhss = Ls of \n//│               IntLit of 1\n//│           kw = Keywrd of keyword 'then'\n//│           rhs = StrLit of \"b\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(0)\n//│ = \"a\"\n\n:re\nf(1)\n//│ ═══[RUNTIME ERROR] Error: match error\n\nf(2)\n//│ = \"b\"\n\n\nfun f(x) = if x\n  > 0 then \"a\"\n  is 0 then \"b\"\n\nf(0)\n//│ = \"b\"\n\nf(1)\n//│ = \"a\"\n\n\n// :pt\n:todo // TODO: juxtaposition splits?\n:e\nfun f(x) = if x\n  foo(A) then a\n  bar(B) then b\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (juxtaposition)\n//│ ║  l.361: \tfun f(x) = if x\n//│ ║         \t              ^\n//│ ║  l.362: \t  foo(A) then a\n//│ ╙──       \t^^\n\n\nif 0\n  is 0 then \"a\"\n//│ = \"a\"\n\nif 0\n  is 0 then \"a\"\n  is 1 then \"b\"\n//│ = \"a\"\n\nx => if x\n  is 0 then \"a\"\n//│ = fun\n\nx => if x\n  is 0 then \"a\"\n  is 1 then \"b\"\n//│ = fun\n\n\nfun f(x) = if x\n  is 0 then \"a\"\n  is 1 then \"b\"\n\nf(0)\n//│ = \"a\"\n\nf(1)\n//│ = \"b\"\n\n\n:pt\nid of id of 1\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ App:\n//│   lhs = Ident of \"id\"\n//│   rhs = Tup of Ls of \n//│     App:\n//│       lhs = Ident of \"id\"\n//│       rhs = Tup of Ls of \n//│         IntLit of 1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// :dp\nf of 1\n//│ = \"b\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/OpDivPrecedence.mls",
    "content": ":js\n\n// Division should have the same precedence as multiplication\n\n:expect 101\n100 + 100 / 100\n//│ = 101\n\n:expect 300\n100 * 3 + 0\n//│ = 300\n\n:expect 300\n0 + 100 * 3\n//│ = 300\n\n:expect 50\n100 / 2 + 0\n//│ = 50\n\n:expect 50\n0 + 100 / 2\n//│ = 50\n\n:expect 50\n200 / 2 / 2\n//│ = 50\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/OpenIn.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/StrOps.mls\"\n\n\nStrOps.{~}\n//│ = fun concat2\n\nStrOps.{~}(\"a\", \"b\")\n//│ = \"ab\"\n\n:e\nStrOps.{~}(\"a\", \"b\", \"c\")\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 3\n//│ ║  l.13: \tStrOps.{~}(\"a\", \"b\", \"c\")\n//│ ╙──      \t          ^^^^^^^^^^^^^^^\n//│ = \"ab\"\n\nStrOps.{\"a\" ~ \"b\"}\n//│ = \"ab\"\n\nStrOps.{\"a\" ~ from(123)}\n//│ = \"a123\"\n\n\n// Lexed as Str .~\n:pe\n:e\nStrOps.~\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found end of input instead\n//│ ║  l.29: \tStrOps.~\n//│ ╙──      \t        ^\n//│ ╔══[COMPILATION ERROR] Name not found: .~\n//│ ║  l.29: \tStrOps.~\n//│ ╙──      \t      ^^\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type StrOps.\n//│ ║  l.29: \tStrOps.~\n//│ ╙──      \t^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/OutParams.mls",
    "content": ":js\n:todo\n\n\n// fun typeTerm(_, set ctx) = case\n//   IntLit then\n//     let ctx = ....\n//     Int\n//   App(f, a) then\n//     let f_t = typeTerm(f, let ctx)\n//     let a_t = typeTerm(a, let ctx)\n//     resTy....\n\nfun typeTerm(_, set ctx) =\n  print(ctx)\n  ctx = 123\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found set\n//│ ║  l.14: \tfun typeTerm(_, set ctx) =\n//│ ╙──      \t                    ^^^\n//│ ╔══[COMPILATION ERROR] Name not found: ctx\n//│ ║  l.15: \t  print(ctx)\n//│ ╙──      \t        ^^^\n//│ ╔══[COMPILATION ERROR] Name not found: ctx\n//│ ║  l.16: \t  ctx = 123\n//│ ╙──      \t  ^^^\n\nfun typeTerm(_, let ctx) =\n  ctx = 123\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found let\n//│ ║  l.27: \tfun typeTerm(_, let ctx) =\n//│ ╙──      \t                    ^^^\n//│ ╔══[COMPILATION ERROR] Name not found: ctx\n//│ ║  l.28: \t  ctx = 123\n//│ ╙──      \t  ^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Overloading.mls",
    "content": ":js\n\n:global\n// :d\n\n\n:todo\nfun Foo() = 1\nmodule Foo with { val x = 1 }\n//│ ╔══[COMPILATION ERROR] Not yet supported: overloading of function 'Foo'\n//│ ║  l.8: \tfun Foo() = 1\n//│ ║       \t^^^^^^^^^^^^^\n//│ ╟── with module of the same name\n//│ ║  l.9: \tmodule Foo with { val x = 1 }\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nFoo\n//│ = class Foo { x: 1 }\n\n:todo\nFoo()\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor Foo cannot be invoked without 'new'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/PartialApps.mls",
    "content": ":js\n\n\n:pe\n:re\n.\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.6: \t.\n//│ ╙──     \t^\n//│ ╔══[PARSE ERROR] Expected end of input; found period instead\n//│ ║  l.6: \t.\n//│ ╙──     \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:pe\n:re\n. //\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.17: \t. //\n//│ ╙──      \t^\n//│ ╔══[PARSE ERROR] Expected end of input; found period instead\n//│ ║  l.17: \t. //\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:fixme\nid(.)\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.28: \tid(.)\n//│ ╙──      \t   ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.28: \tid(.)\n//│ ╙──      \t   ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nfun incr = _ + 1\nfun add = _ + _\n\npassTo(2, incr)()\n//│ = 3\n\n// TODO disallow\n:breakme\npassTo(2, incr(_))()\n//│ = 3\n\npassTo(2, incr @ _)()\n//│ = 3\n\n:fixme\npassTo(2, incr(.) @ _)()\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.53: \tpassTo(2, incr(.) @ _)()\n//│ ╙──      \t               ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.53: \tpassTo(2, incr(.) @ _)()\n//│ ╙──      \t               ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:breakme\npassTo(2, (incr(_)) @ _)()\n//│ = 3\n\n:breakme\npassTo(2, add(_, 2))()\n//│ = 4\n\n:fixme\npassTo(2, add(., 2))()\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.71: \tpassTo(2, add(., 2))()\n//│ ╙──      \t              ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.71: \tpassTo(2, add(., 2))()\n//│ ╙──      \t              ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:breakme\npassTo(1, incr(_) + _)(2)\n//│ = 4\n\n:breakme\npassTo(1, (incr(_)) @ _ + _)(2)\n//│ = 4\n\npassTo(1, (add(_, 1)) @ _ + _)(2)\n//│ = 4\n\n:fixme\npassTo(1, incr(.) @ _ + _)(2)\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.92: \tpassTo(1, incr(.) @ _ + _)(2)\n//│ ╙──      \t               ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.92: \tpassTo(1, incr(.) @ _ + _)(2)\n//│ ╙──      \t               ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:fixme\npassTo(1, add(., 1) @ _ + _)(2)\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.102: \tpassTo(1, add(., 1) @ _ + _)(2)\n//│ ╙──       \t              ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.102: \tpassTo(1, add(., 1) @ _ + _)(2)\n//│ ╙──       \t              ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:breakme\n:sjs\nlet f = add(_, 1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f, f1;\n//│ f1 = function f(_0) { let tmp1; tmp1 = add(); return runtime.safeCall(tmp1(_0, 1)) };\n//│ f = f1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\n:fixme\nlet f = add(., 1)\n//│ ╔══[PARSE ERROR] Expected an expression; found period instead\n//│ ║  l.123: \tlet f = add(., 1)\n//│ ╙──       \t            ^\n//│ ╔══[PARSE ERROR] Unexpected period here\n//│ ║  l.123: \tlet f = add(., 1)\n//│ ╙──       \t            ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ f = undefined\n\n:fixme\nf(1)\n//│ ═══[RUNTIME ERROR] TypeError: f2 is not a function\n\nlet f = add of _, 1\n//│ f = fun f\n\nf(1)\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/PrefixOps.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Stack.mls\"\nopen Stack\n\n\n0 *\n  + 1\n  + 2\n//│ = 0\n\nx =>\n  + 1\n  + 2\n//│ = fun\n\n\n| 1\n//│ = 1\n\n& 1\n//│ = 1\n\nlet res =\n  | 1\n//│ res = 1\n\n| 2 + 2\n*\n| 3 + 3\n//│ = 24\n\n2 + 2\n*\n3 + 3\n//│ = 24\n\n2 + 2\n  *\n3 + 3\n//│ = 11\n\n| 2 + 2\n  *\n| 3 + 3\n//│ = 14\n\n2 + 2 * | 3 + 3\n//│ = 14\n\n:pt\n1 + | 2 + 3\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpApp:\n//│   lhs = IntLit of 1\n//│   op = Ident of \"+\"\n//│   rhss = Ls of \n//│     App:\n//│       lhs = Ident of \"|\"\n//│       rhs = Tup of Ls of \n//│         OpApp:\n//│           lhs = IntLit of 2\n//│           op = Ident of \"+\"\n//│           rhss = Ls of \n//│             IntLit of 3\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 6\n\n:fixme // ?\n| 1\n| 2\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (composed type)\n//│ ║  l.70: \t| 1\n//│ ║        \t  ^\n//│ ║  l.71: \t| 2\n//│ ╙──      \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\npattern Bin =\n  | 0\n\n0 is Bin\n//│ = true\n\n1 is Bin\n//│ = false\n\n\npattern Bin =\n  | 0\n  | 1\n\n0 is Bin\n//│ = true\n\n1 is Bin\n//│ = true\n\n2 is Bin\n//│ = false\n\n\npattern Bin =\n  | 0 => false\n  | 1 => true\n\nBin.unapply(0)\n//│ = MatchSuccess(false, null)\nBin.unapply(1)\n//│ = MatchSuccess(true, null)\nBin.unapply(2)\n//│ = MatchFailure(null)\n\n\n// * Note:\n\nlet x =\n  +\n//│ x = fun x\n\nx(2, 3)\n//│ = 5\n\n\n:e\nlet x = |\n//│ ╔══[COMPILATION ERROR] Unexpected use of special operator '|'\n//│ ║  l.127: \tlet x = |\n//│ ╙──       \t        ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ x = undefined\n\n:e\nlet x = (|)\n//│ ╔══[COMPILATION ERROR] Unexpected use of special operator '|'\n//│ ║  l.135: \tlet x = (|)\n//│ ╙──       \t         ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ x = undefined\n\n:e\n&\n//│ ╔══[COMPILATION ERROR] Unexpected use of special operator '&'\n//│ ║  l.143: \t&\n//│ ╙──       \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nfun (|) test = 1\n\n:e\nlet x = |\n//│ ╔══[COMPILATION ERROR] Unexpected use of special operator '|'\n//│ ║  l.153: \tlet x = |\n//│ ╙──       \t        ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ x = undefined\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Puns.mls",
    "content": ":js\n\n\nlet a = 1\n//│ a = 1\n\n(a: 1)\n//│ = {a: 1}\n\n(a: a)\n//│ = {a: 1}\n\n(:a)\n//│ = {a: 1}\n\n{:a}\n//│ = {a: 1}\n\n\nfun foo(x) = :x\n\nfun foo(x) = (:x)\nfoo(1)\n//│ = {x: 1}\n\nfun foo(x) =\n  :x\n  y: x + 1\nfoo(1)\n//│ = {x: 1, y: 2}\n\n\nlet r =\n  :a\n  b: 2\n//│ r = {a: 1, b: 2}\n\nif r is\n  { a: x } then x\n//│ = 1\n\nif r is\n  (a: x) then x\n//│ = 1\n\n:e\nif r is\n  a: x then x\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (infix operator ':').\n//│ ║  l.48: \t  a: x then x\n//│ ╙──      \t  ^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nif 1 is\n  (((1))) then true\n//│ = true\n\nif 1 is\n  {1} then true\n//│ = true\n\n:js\nlet r2 = {a:2}\nif r2 is\n  {a:0} then false\n  0 then true\n  else 4\n//│ = 4\n//│ r2 = {a: 2}\n\n\n:js\nlet foo = case\n  (a: 0) then false\n  (a: 1) then true\n  (:a) then a\n//│ foo = fun\n\nfoo(r)\n//│ = true\n\nfoo(a: 2)\n//│ = 2\n\nfoo(:a)\n//│ = true\n\n\n:todo // would mean `val a = ‹the old a›`?\nval =a\n//│ ╔══[PARSE ERROR] Expected expression after 'val' binding keyword; found '=' keyword instead\n//│ ║  l.90: \tval =a\n//│ ╙──      \t    ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:pe\n:re\nlet =a\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found '=' keyword instead\n//│ ║  l.98: \tlet =a\n//│ ╙──      \t    ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nimport \"../../mlscript-compile/LazyArray.mls\"\n\n// * Should probably warn that `dropLeftRight` has no effect\n// * (this requires checking it's not an effectful getter!)\nLazyArray.{ dropLeftRight, concat }\n//│ = fun concat\n\nLazyArray.{ :dropLeftRight, :concat }\n//│ = {dropLeftRight: fun dropLeftRight, concat: fun concat}\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/PureTermStatements.mls",
    "content": ":js\n\n\n:w\ndo 1\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.5: \tdo 1\n//│ ╙──     \t   ^\n\n:w\nif true do 1\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.11: \tif true do 1\n//│ ╙──      \t           ^\n\n:w\nif true do () else 1\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.17: \tif true do () else 1\n//│ ╙──      \t                   ^\n\nif true then () else 1\n\n\n:w\nx => x, 0\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.26: \tx => x, 0\n//│ ╙──      \t^^^^^^\n//│ = 0\n\n:w\n() => 1\n2\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.33: \t() => 1\n//│ ╙──      \t^^^^^^^\n//│ = 2\n\n:w\ncase x then x, 0\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.41: \tcase x then x, 0\n//│ ╙──      \t^^^^^^^^^^^^^\n//│ = 0\n\n:w\ncase x then x\ncase x then x\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.48: \tcase x then x\n//│ ╙──      \t^^^^^^^^^^^^^\n//│ = fun\n\n\n:w\nfun foo(x) =\n  x\n  x\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.58: \t  x\n//│ ╙──      \t  ^\n\n:w\nfun foo() =\n  val x = 1\n  x\n  x\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.67: \t  x\n//│ ╙──      \t  ^\n\n:w\nfun foo() =\n  let x = 1\n  x\n  x\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.76: \t  x\n//│ ╙──      \t  ^\n\n\n// * Note that uses of `;` currently do not warn...\n\n:sjs\n1; id(2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = Predef.id(2); (1 , tmp)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Records.mls",
    "content": ":js\n\n\n// * Note that this currently denotes unit, not an empty record...\n// * (we could make them the same thing) \n\n{}\n\nlet r = {}\n//│ r = ()\n\n\n{1}\n//│ = 1\n\n:w\n{1, 2}\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.17: \t{1, 2}\n//│ ╙──      \t ^\n//│ = 2\n\n{foo: 1}\n//│ = {foo: 1}\n\n\nlet rcd = { foo: 1, bar: \"...\" }\n//│ rcd = {foo: 1, bar: \"...\"}\n\n[rcd.foo, rcd.bar]\n//│ = [1, \"...\"]\n\ntypeof(rcd)\n//│ = \"object\"\n\n\n// * Should we allow this syntax?\n\nlet rcd = (foo: 1, bar: \"...\")\n//│ rcd = {foo: 1, bar: \"...\"}\n\n[rcd.foo, rcd.bar]\n//│ = [1, \"...\"]\n\nlet rcd = (\n  foo: 1\n  bar: \"...\"\n)\n//│ rcd = {foo: 1, bar: \"...\"}\n\nlet rcd =\n  foo: 1\n  bar:\n    \"...\"\n//│ rcd = {foo: 1, bar: \"...\"}\n\n[rcd.foo, rcd.bar]\n//│ = [1, \"...\"]\n\nprint <|\n  foo: 1\n  bar:\n    \"...\"\n//│ > {foo: 1, bar: \"...\"}\n\n\n// * But not this syntax...\n\n:e\n:fixme\nlet rcd =\n  foo = 1\n  bar =\n    \"...\"\n//│ ╔══[COMPILATION ERROR] Name not found: foo\n//│ ║  l.72: \t  foo = 1\n//│ ╙──      \t  ^^^\n//│ ╔══[COMPILATION ERROR] Name not found: bar\n//│ ║  l.73: \t  bar =\n//│ ╙──      \t  ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ rcd = undefined\n\n\n// * How about this syntax?\n\n:todo\nlet rcd = new with\n  foo = 1\n  bar =\n    \"...\"\n//│ ╔══[COMPILATION ERROR] Name not found: foo\n//│ ║  l.89: \t  foo = 1\n//│ ╙──      \t  ^^^\n//│ ╔══[COMPILATION ERROR] Name not found: bar\n//│ ║  l.90: \t  bar =\n//│ ╙──      \t  ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ rcd = undefined\n\n\nid of (x: 1)\n//│ = {x: 1}\n\nid of { x: 1 }\n//│ = {x: 1}\n\nid of ({ x: 1 })\n//│ = {x: 1}\n\n\nid of ({ x: 1, y: 2 })\n//│ = {x: 1, y: 2}\n\nid of (x: 1, y: 2)\n//│ = {x: 1, y: 2}\n\nid of { x: 1, y: 2 }\n//│ = {x: 1, y: 2}\n\n\nlet m0 = {get(k): k + 1}\n//│ m0 = {get: fun get}\n\nm0.get(41)\n//│ = 42\n\n\nlet m0 = {(\"get\")(k): k + 1}\n//│ m0 = {get: fun}\n\nm0.get(41)\n//│ = 42\n\n\n:e\n{get(k): _}\n//│ ╔══[COMPILATION ERROR] Unexpected record key shape.\n//│ ║  l.137: \t{get(k): _}\n//│ ╙──       \t ^^^^^^\n//│ = fun\n\n\n\n:silent\nimport \"../../mlscript-compile/Iter.mls\"\nlet graphics = new Set of tuple of\n  \"circle\", \"ellipse\", \"image\", \"line\", \"path\"\n  \"polygon\", \"polyline\", \"rect\", \"text\", \"use\"\n\nfun showProps(x, y, props) = Object.entries(props)\n  Iter.mapping of case\n    [\"x\", x'] then \"x: \" + (x + x')\n    [\"y\", y'] then \"y: \" + (y + y')\n    [k, v] then k + \": \" + v\n  Iter.joined(\", \")\n\nfun output(i, s) = print of \"  \".repeat(i) + s\n\nfun t(kind, props) =\n  if graphics.has(kind) then\n    (args) => output of args.i, kind + \" \" + showProps(args.x, args.y, props)\n  else\n    (...children) => (args) =>\n      output of args.i, kind + \" \" + showProps(args.x, args.y, props) + \" with\"\n      children Iter.each of child => child of\n        x: args.x + props.x\n        y: args.y + props.y\n        i: args.i + 1\n\nlet display = t(\"group\", x: 20, y: 20) of\n  t(\"circle\", x: 30, y: 30, r: 42)\n  t(\"rect\", x: 40, y: 40, width: 80, height: 90)\n  t(\"ellipse\", x: 50, y: 50, rx: 40, ry: 60)\n//│ display = fun\n\ndisplay(x: 11, y: 22, i: 2)\n//│ >     group x: 31, y: 42 with\n//│ >       circle x: 61, y: 72, r: 42\n//│ >       rect x: 71, y: 82, width: 80, height: 90\n//│ >       ellipse x: 81, y: 92, rx: 40, ry: 60\n\nlet display = t(\"group\", x: 0, y: 0) of\n  t(\"circle\", x: 10, y: 10, r: 42)\n//│ display = fun\n\ndisplay(x: 88, y: 99, i: 0)\n//│ > group x: 88, y: 99 with\n//│ >   circle x: 98, y: 109, r: 42\n\n:todo\nt(\"group\")\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.192: \tt(\"group\")\n//│ ╙──       \t ^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Function 't' expected 2 arguments but got 1\n\n:todo\nt(\"group\")\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.199: \tt(\"group\")\n//│ ╙──       \t ^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Function 't' expected 2 arguments but got 1\n\nlet empty = Object.create of null\n//│ empty = {}\n\nt(\"group\", empty)\n//│ = fun\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/RefinedClasses.mls",
    "content": "\n\n:todo\nclass Foo { }\n//│ ╔══[COMPILATION ERROR] Invalid class definition head: unexpected block in this position\n//│ ║  l.4: \tclass Foo { }\n//│ ╙──     \t          ^^^\n\n:todo\nclass Foo() {\n  val x = 1\n}\n//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead\n//│ ║  l.10: \tclass Foo() {\n//│ ║        \t            ^\n//│ ║  l.11: \t  val x = 1\n//│ ║        \t^^^^^^^^^^^\n//│ ║  l.12: \t}\n//│ ╙──      \t^\n\n:todo\nclass Foo()\n  val x = 1\n//│ ╔══[PARSE ERROR] Expected end of input; found indented block instead\n//│ ║  l.23: \t  val x = 1\n//│ ╙──      \t^^\n\n:todo\nclass Bar { val x: Int }\n//│ ╔══[PARSE ERROR] Expected end of input; found curly brace section instead\n//│ ║  l.29: \tclass Bar { val x: Int }\n//│ ╙──      \t          ^^^^^^^^^^^^^^\n\n:todo\nclass Foo() extends Bar { x = 1 } with\n  val y = this.x\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (defining assignment).\n//│ ║  l.35: \tclass Foo() extends Bar { x = 1 } with\n//│ ╙──      \t                          ^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Return.mls",
    "content": ":js\n\n\nfun f =\n  print(\"reachable\")\n  return\n  print(\"unreachable\")\n\nf\n//│ > reachable\n\n\nfun foo(x) =\n  if x do\n    print(\"true\")\n    return 42\n  print(\"false\")\n  0\n\nfoo(true)\n//│ > true\n//│ = 42\n\nfoo(false)\n//│ > false\n//│ = 0\n\n\nfun foo(x) =\n  return\n    print(\"returning...\")\n    x\n\nfoo(123)\n//│ > returning...\n//│ = 123\n\n\n:e\nreturn \"whoops\"\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed outside of functions.\n//│ ║  l.40: \treturn \"whoops\"\n//│ ╙──      \t^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nx => return \"whoops\"\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed outside of functions.\n//│ ║  l.47: \tx => return \"whoops\"\n//│ ╙──      \t     ^^^^^^^^^^^^^^^\n//│ = fun\n\n:e\nfun foo() =\n  x => return \"whoops\"\n//│ ╔══[COMPILATION ERROR] Non-local return statements are only supported with effect handlers enabled.\n//│ ║  l.55: \t  x => return \"whoops\"\n//│ ╙──      \t       ^^^^^^^^^^^^^^^\n\n:e\nfun foo(x: return \"whoops\") = 1\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed in this context.\n//│ ║  l.61: \tfun foo(x: return \"whoops\") = 1\n//│ ╙──      \t           ^^^^^^^^^^^^^^^\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n\n:e\nfun foo() =\n  fun bar(x: return \"whoops\") = 1\n  bar(123)\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed in this context.\n//│ ║  l.70: \t  fun bar(x: return \"whoops\") = 1\n//│ ╙──      \t             ^^^^^^^^^^^^^^^\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/SetIndented.mls",
    "content": ":js\n\n// Same-line set with member selection parses fine\n:e\nset this.pc = 0\nset\n  (this).pc = 0\n//│ ╔══[COMPILATION ERROR] Cannot use 'this' outside of an object scope\n//│ ║  l.5: \tset this.pc = 0\n//│ ╙──     \t    ^^^^\n//│ ╔══[COMPILATION ERROR] Cannot use 'this' outside of an object scope\n//│ ║  l.7: \t  (this).pc = 0\n//│ ╙──     \t   ^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// Indented set with member selection should also parse fine\n:e\nset\n  this.pc = 0\n//│ ╔══[COMPILATION ERROR] Cannot use 'this' outside of an object scope\n//│ ║  l.19: \t  this.pc = 0\n//│ ╙──      \t  ^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ShortcircuitingOps.mls",
    "content": ":js\n\n\n:sjs\n1 && 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ if (1 === true) { 2 } else { false }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = false\n\n\nfun\n  loud(x) = print(x); x\n  loudTrue = loud(true)\n  loudFalse = loud(false)\n\n\ntrue && loudTrue\n//│ > true\n//│ = true\n\ntrue && loudFalse\n//│ > false\n//│ = false\n\nfalse && loudTrue\n//│ = false\n\n:sjs\nprint(1 && loudTrue)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp;\n//│ if (1 === true) { tmp = loudTrue(); Predef.print(tmp) } else { tmp = false; Predef.print(tmp) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > false\n\n:sjs\n1 || 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ if (1 === false) { 2 } else { true }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\nprint(1 || 2)\n//│ > true\n\n1 || loudTrue\n//│ = true\n\n1 || loudFalse\n//│ = true\n\ntrue || loudTrue\n//│ = true\n\n\n123 || loud(42)\n//│ = true\n\n0 || loud(42)\n//│ = true\n\n123 && loud(42)\n//│ = false\n\n:sjs\nfold(||)(0, false, 42, 123)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda, callPrefix;\n//│ lambda = (undefined, function (arg1, arg2) {\n//│   if (arg1 === false) {\n//│     return arg2\n//│   }\n//│   return true;\n//│ });\n//│ callPrefix = runtime.safeCall(Predef.fold(lambda));\n//│ runtime.safeCall(callPrefix(0, false, 42, 123))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\n\nprint of\n  print(\"A\") && print(\"B\")\n//│ > A\n//│ > false\n\n\nfun (&&) foo(x, y) =\n  print(x)\n  print(y)\n  x and y\n\n1 && 2\n//│ > 1\n//│ > 2\n//│ = false\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/StrTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/StrOps.mls\"\n\nopen StrOps\n\n\n:sjs\n\"a\" is Str\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut; scrut = \"a\"; if (typeof scrut === 'string') { true } else { false }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\n\nconcat of \"a\", \"b\", \"c\"\n//│ = \"abc\"\n\nconcat of\n  \"a\"\n  \"b\"\n  \"c\"\n//│ = \"abc\"\n\n\n// TODO (~) should be sanitized\n\n:e\n(~)(\"a\", \"b\", \"c\")\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 3\n//│ ║  l.29: \t(~)(\"a\", \"b\", \"c\")\n//│ ╙──      \t   ^^^^^^^^^^^^^^^\n//│ = \"ab\"\n\n\n:e\n(~)(\"a\")\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.37: \t(~)(\"a\")\n//│ ╙──      \t   ^^^^^\n//│ = \"aundefined\"\n\n:ge\n~\"a\"\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (negation type)\n//│ ║  l.44: \t~\"a\"\n//│ ╙──      \t ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:ge\n~(\"a\", \"b\")\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (negation type)\n//│ ║  l.52: \t~(\"a\", \"b\")\n//│ ╙──      \t       ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:pe\n:ge\n~ of \"a\", \"b\"\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found 'of' keyword instead\n//│ ║  l.61: \t~ of \"a\", \"b\"\n//│ ╙──      \t  ^^\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.61: \t~ of \"a\", \"b\"\n//│ ╙──      \t     ^^^\n//│ ═══[COMPILATION ERROR] Unexpected term form in expression position (negation type)\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n(~) of \"a\", \"b\"\n//│ = \"ab\"\n\n\nfun test(...xs) =\n  concat of ...xs, \"!\"\n\ntest(\"a\", \"b\", \"c\")\n//│ = \"abc!\"\n\n\n\"a\" StrOps.concat2(\"b\")\n//│ = \"ab\"\n\n\"a\" StrOps.concat2 of \"b\"\n//│ = \"ab\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/SuspensionComments.mls",
    "content": ":js\n\n\n// * Suspension with end-of-line comment should properly expand the continuation body\n\nmkStr of ... // hello\n\"oops\"\n//│ = \"oops\"\n\nmkStr of ...\n// hello\n\"oops\"\n//│ = \"oops\"\n\nmkStr of ...\n  // hello\n\"oops\"\n//│ = \"oops\"\n\nmkStr of ...\n  // hello\n    // hello\n\"oops\"\n//│ = \"oops\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ThenRecord.mls",
    "content": ":js\n\n\n//* Fixed: `if true then success: 42` should work like `if true then (success: 42)`\n\nif true then (success: 42)\n//│ = {success: 42}\n\nif true then\n  success: 42\n//│ = {success: 42}\n\nif true then success: 42\n//│ = {success: 42}\n\n\nif true then success: 42 else failure: \"oops\"\n//│ = {success: 42}\n\nif false then success: 42 else failure: \"oops\"\n//│ = {failure: \"oops\"}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/Underscores.mls",
    "content": ":js\n\n\n:sjs\n_\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda; lambda = (undefined, function (_0) { return _0 }); lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n(_)\n//│ = fun\n\n:e\ny: _\n//│ ╔══[COMPILATION ERROR] Illegal position for '_' placeholder.\n//│ ║  l.15: \ty: _\n//│ ╙──      \t   ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ y = undefined\n\n(y: _)\n//│ = fun\n\n:w\n_, _\n//│ ═══[WARNING] Pure expression in statement position\n//│ = fun\n\n\nlet inc = _ + 1\n//│ inc = fun inc\n\ninc(2)\n//│ = 3\n\n:sjs\n_ + _\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda4; lambda4 = (undefined, function (_0, _1) { return _0 + _1 }); lambda4\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\nlet f = _ + _\n//│ f = fun f\n\nf(2, 3)\n//│ = 5\n\n\nimport \"../../mlscript-compile/Iter.mls\"\nopen Iter\n\nfiltering of [], _ =>\n  1\n//│ = Iterable(_)\n\nprint(_)\n//│ = fun\n\n\n:sjs\nlet test = _.f(0, _, 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test, test1;\n//│ test1 = function test(_0, _1) { return runtime.safeCall(_0.f(0, _1, 2)) };\n//│ test = test1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ test = fun test\n\n:re\ntest(f: print)(1)\n//│ ═══[RUNTIME ERROR] Error: Function 'test' expected 2 arguments but got 1\n\ntest((f: print), 1)\n//│ > 0 1 2\n\ntest({f: print}, 1)\n//│ > 0 1 2\n\n{f: print}\n//│ = {f: fun print}\n\n({f: print})\n//│ = {f: fun print}\n\n[{f: print}]\n//│ = [{f: fun print}]\n\n[{f: print}, 1]\n//│ = [{f: fun print}, 1]\n\n\nprint(inc(_))\n//│ > fun\n\n:sjs\n_ is Int\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda8;\n//│ lambda8 = (undefined, function (_0) {\n//│   if (globalThis.Number.isInteger(_0)) { return true }\n//│   return false;\n//│ });\n//│ lambda8\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\nlet f = _ is Int\n[f(1), f(\"1\")]\n//│ = [true, false]\n//│ f = fun f\n\n[1, \"a\", 3, true] filtering(_ is Int) toArray()\n//│ = [1, 3]\n\n42 is _\n//│ = true\n\n\nlet x_to = x: _\n//│ x_to = fun x_to\n\nx_to(42)\n//│ = {x: 42}\n\n\nlet mkObj = (x: _, y: _, z: 3)\n//│ mkObj = fun mkObj\n\nmkObj(1, 2)\n//│ = {x: 1, y: 2, z: 3}\n\n\n// * Note: this is parsed as `{let mkObj = x: _}, y: _, z: 3`\n// * TODO: improve or at least raise a warning\n:e\n:ge\n:re\nlet mkObj = x: _, y: _, z: 3\n//│ ╔══[COMPILATION ERROR] Illegal position for '_' placeholder.\n//│ ║  l.140: \tlet mkObj = x: _, y: _, z: 3\n//│ ╙──       \t                     ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ mkObj = fun mkObj\n//│ y = undefined\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'z'\n//│ ╟── which references the symbol introduced here\n//│ ║  l.140: \tlet mkObj = x: _, y: _, z: 3\n//│ ╙──       \t                        ^\n//│ ═══[RUNTIME ERROR] ReferenceError: z is not defined\n\n// mkObj(1, 2)\n\n\nlet mkObj =\n  x: _, y: _, z: 3\n//│ mkObj = fun mkObj\n\nmkObj(1, 2)\n//│ = {x: 1, y: 2, z: 3}\n\n\nlet obj = f: _ + 1\n//│ obj = {f: fun f}\n\nobj.f(123)\n//│ = 124\n\n{f: _ + 1}.f(123)\n//│ = 124\n\n\nlet f = _ => 1\n//│ f = fun f\n\nf(2)\n//│ = 1\n\nlet f = x => _\n//│ f = fun f\n\nf(2)(3)\n//│ = 3\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/ValMemberSymbols.mls",
    "content": ":js\n:noSanityCheck\n\n\n\n:sir\nclass A(val x)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A⁰; define A⁰ as class A²(x) { val x⁰; constructor A¹ { define x⁰ as val x¹ = x; end } }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet a = A(1)\n//│ a = A(1)\n\n// * Currently, we don't get a symbol here, yet\n:sir\na.x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ a⁰.x﹖\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// * Check that the symbol here is the one we expect: `x¹`, from `define x⁰ as val x¹` above\n:sir\na.A#x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ a⁰.x¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// * Idem\n:sir\nA::x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda⁰; define lambda⁰ as fun lambda¹(self, ...args) { return self.x¹(...args) }; lambda¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n// * Idem\n:sir\ncase A(x) then x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda²;\n//│ define lambda² as fun lambda³(caseScrut) {\n//│   let x, arg$A$0$;\n//│   match caseScrut\n//│     A² =>\n//│       set arg$A$0$ = caseScrut.x¹;\n//│       set x = arg$A$0$;\n//│       return x\n//│     else\n//│       throw new globalThis⁰.Error⁰(\"match error\")\n//│   end\n//│ };\n//│ lambda³\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n:sir\nclass A()(val x)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A³; define A³ as class A⁵() { val x²; constructor A⁴(x) { define x² as val x³ = x; end } }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet a = A()(1)\n//│ a = A()\n\n:sir\na.x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ a¹.x﹖\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:sir\na.A#x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ a¹.x³\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:sir\nA::x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda⁴; define lambda⁴ as fun lambda⁵(self, ...args) { return self.x³(...args) }; lambda⁵\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n// * Note: no symbol info here, yet\n:sir\ncase A as a then a.x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda⁶;\n//│ define lambda⁶ as fun lambda⁷(caseScrut) {\n//│   let a;\n//│   match caseScrut\n//│     A⁵ =>\n//│       set a = caseScrut;\n//│       return a.x﹖\n//│     else\n//│       throw new globalThis⁰.Error⁰(\"match error\")\n//│   end\n//│ };\n//│ lambda⁷\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n// :ssjs\n:sir\n:lift\n// TODO: remove this flag when the lifter problem is resolved (see: the end of ClassInFun.mls)\n:deadParamElim off\nfun foo(x, y) =\n  class A(val u) with { val v = y }\n  let a = new A(x)\n  [a, a.A#u, a.A#v]\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A⁶, foo⁰;\n//│ define A⁶ as class A⁸(u) {\n//│   private val y⁰;\n//│   val u⁰;\n//│   val v⁰;\n//│   constructor A⁷(y) {\n//│     set y⁰ = y;\n//│     define u⁰ as val u¹ = u;\n//│     define v⁰ as val v¹ = y⁰;\n//│     end\n//│   }\n//│ };\n//│ define foo⁰ as fun foo¹(x, y) { let a; set a = new A⁸(x)(y); return [a, a.u¹, a.v¹] };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect [A(1), 1, 2]\nfoo(1, 2)\n//│ = [A(1), 1, 2]\n\n\n// TODO: when it's supported in the surface language, also test classes with only aux param lists, as in\n// class A with\n//   constructor(val x)\n// if new A(1) is\n//   A { x } then ...\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/basics/WeirdCalls.mls",
    "content": ":js\n\n\n// TODO: should report that such `print` reference does not do anything in statement position\nprint\n(\n  \"A\"\n)\n//│ = \"A\"\n\n:fixme\nprint\n  (\n    \"A\"\n  )\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (parenthesis section).\n//│ ║  l.13: \t  (\n//│ ║        \t  ^\n//│ ║  l.14: \t    \"A\"\n//│ ║        \t^^^^^^^\n//│ ║  l.15: \t  )\n//│ ╙──      \t^^^\n//│ = fun print\n\n:w\nprint of\n(\n  \"A\"\n)\n//│ ╔══[WARNING] This parenthesis section should be indented\n//│ ║  l.27: \t(\n//│ ║        \t^\n//│ ║  l.28: \t  \"A\"\n//│ ║        \t^^^^^\n//│ ║  l.29: \t)\n//│ ║        \t^\n//│ ╟── since it is a continuation of the new line here\n//│ ║  l.26: \tprint of\n//│ ║        \t        ^\n//│ ║  l.27: \t(\n//│ ╙──      \t\n//│ > A\n\n:w\nprint of\n(\"A\")\n//│ ╔══[WARNING] This parenthesis section should be indented\n//│ ║  l.46: \t(\"A\")\n//│ ║        \t^^^^^\n//│ ╟── since it is a continuation of the new line here\n//│ ║  l.45: \tprint of\n//│ ║        \t        ^\n//│ ║  l.46: \t(\"A\")\n//│ ╙──      \t\n//│ > A\n\nprint of\n  (\n    \"A\"\n  )\n//│ > A\n\n:pe\nprint of\n  (\n    \"A\"\n)\n//│ ╔══[PARSE ERROR] Mistmatched closing indentation\n//│ ║  l.66: \t    \"A\"\n//│ ║        \t       ^\n//│ ║  l.67: \t)\n//│ ║        \t\n//│ ╟── does not correspond to opening parenthesis\n//│ ║  l.65: \t  (\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Unexpected closing parenthesis\n//│ ║  l.67: \t)\n//│ ╙──      \t^\n//│ > A\n\nprint of (\n  \"A\"\n)\n//│ > A\n\nprint(\n  \"A\"\n)\n//│ > A\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/block-staging/Functions.mls",
    "content": ":js\n:staging\n\n:fixme // TODO: fix IR rebinding issue (each symbol should be bound at most once)\n:checkIR\nstaged module Expressions with\n  fun lit() =\n    let x = 42\n    x\n//│ ╔══[INTERNAL ERROR] [BlockChecker] Invalid IR: symbol x⁰ is bound more than once\n//│ ║  l.8: \t    let x = 42\n//│ ╙──     \t        ^\n//│ > fun ctor_() = ()\n//│ > fun lit() =\n//│ >   let {x}\n//│ >   x = 42\n//│ >   x\n\nlet x = [1, 2, 3]\nstaged module Expressions with\n  fun lit() = 1\n  fun assign() =\n    let x = 42\n    let y = x\n    y\n  fun tup1() = [1, 2]\n  fun tup2() = [1, x]\n  fun dynsel() = [1].(0)\n  fun match1() =\n    if 9 is\n      Bool then 1\n      8 then 2\n      Int then 3\n      9 then 4\n      else 0\n  fun match2() =\n    if x is\n      [] then 1\n      [1, 2] then 2\n      [a, _] then 3\n      else 0\n//│ > fun ctor_() = ()\n//│ > fun lit() = 1\n//│ > fun assign() =\n//│ >   let {x, y}\n//│ >   x = 42\n//│ >   y = x\n//│ >   y\n//│ > fun tup1() = [1, 2]\n//│ > fun tup2() = [1, x1]\n//│ > fun dynsel() =\n//│ >   let {tmp}\n//│ >   tmp = [1]\n//│ >   tmp.(0)\n//│ > fun match1() =\n//│ >   let {scrut}\n//│ >   scrut = 9\n//│ >   if scrut is\n//│ >     Bool then 1\n//│ >     8 then 2\n//│ >     Int then 3\n//│ >     else 0\n//│ > fun match2() =\n//│ >   let {a, element1_, element0_}\n//│ >   if x1 is\n//│ >     [] then 1\n//│ >     [_, _] then\n//│ >       element0_ = x1.0\n//│ >       element1_ = x1.1\n//│ >       if element0_ is\n//│ >         1 then\n//│ >           if element1_ is\n//│ >             2 then 2\n//│ >             else\n//│ >               a = element0_\n//│ >               3\n//│ >         else\n//│ >           a = element0_\n//│ >           3\n//│ >     else 0\n//│ x = [1, 2, 3]\n\nclass Outside(a)\nstaged module ClassInstrumentation with\n  class Inside(a, b)\n  class NoArg\n  fun inst1() = new Outside(1)\n  fun inst2() = new NoArg\n  fun app1() = Outside(1)\n  fun app2() = Inside(1, 2)\n//│ > fun ctor_() =\n//│ >   class Inside(a1, b)\n//│ >   class NoArg\n//│ > fun inst1() = new Outside(1)\n//│ > fun inst2() = new ClassInstrumentation.NoArg\n//│ > fun app1() = Outside(1)\n//│ > fun app2() = ClassInstrumentation.Inside(1, 2)\n\nmodule Nonstaged with\n  fun f() = 1\nstaged module Staged with\n  fun f() = 1\nstaged module CallSubst with\n  fun call() = \n    1 + 1\n    Nonstaged.f()\n    Staged.f()\n//│ > fun ctor_() = ()\n//│ > fun f() = 1\n//│ > fun ctor_() = ()\n//│ > fun call() =\n//│ >   Nonstaged.f()\n//│ >   Staged.f_gen()\n\n:ftc\nstaged module Arguments with\n  fun f(x) =\n    x = 1\n    x\n  fun g(x)(y, z)() = z\n//│ > fun ctor_() = ()\n//│ > fun f(x) =\n//│ >   x = 1\n//│ >   x\n//│ > fun g(x) =\n//│ >   let {tmp}\n//│ >   tmp = new Function_\n//│ >   tmp\n\n// :e\nstaged module BadArguments with\n  fun f() = Arguments.g(1)(2, 3)\n//│ > fun ctor_() = ()\n//│ > fun f() =\n//│ >   let {callPrefix}\n//│ >   callPrefix = Arguments.g_gen(1)\n//│ >   callPrefix(2, 3)\n\n\nstaged module OtherBlocks with\n  fun scope() =\n    scope.locally of (\n      let a = 1\n      a\n    )\n  fun breakAndLabel() =\n    if 1 is\n      2 then 0\n      3 then 0\n      else 0\n//│ > fun ctor_() = ()\n//│ > fun scope() =\n//│ >   let {a}\n//│ >   a = 1\n//│ >   OtherBlocks.scope.locally(a)\n//│ > fun breakAndLabel() =\n//│ >   let {scrut}\n//│ >   scrut = 1\n//│ >   if scrut is\n//│ >     2 then 0\n//│ >     3 then 0\n//│ >     else 0\n\nstaged module ClassDefs with\n  class A\n//│ > fun ctor_() =\n//│ >   class A\n\nstaged module ValClass with\n  class A(val a)\n//│ > fun ctor_() =\n//│ >   class A(a)\n\nstaged module ClassFunctions with\n  class InnerClass() with\n    fun f() = 1 + Arguments.f(1)\n    fun g() = f()\n//│ > fun ctor_() =\n//│ >   class InnerClass() with\n//│ >     fun f() =\n//│ >       let {tmp}\n//│ >       tmp = Arguments.f_gen(1)\n//│ >       1 + tmp\n//│ >     fun g() = InnerClass.f()\n\nstaged module RetUnit with\n  fun f() = ()\n//│ > fun ctor_() = ()\n//│ > fun f() = ()\n\n// name collision\nclass A()\nstaged module A with\n  fun f() = 1\n//│ > fun ctor_() = ()\n//│ > fun f() = 1\n\n// nested module\nmodule A with\n  staged module B with\n    fun f() = 1\n//│ > fun ctor_() = ()\n//│ > fun f() = 1\n\n// FIXME: for g to be defined in the next stage, we need to also print the other ClsLikeDefn/FunDefn nodes when printing the next stage\n:ftc\nstaged module NestedFunDefn with\n  fun f() =\n    fun g() = 1\n    g()\n//│ > fun ctor_() = ()\n//│ > fun f() = g()\n\n:todo\nstaged module LabelBreak with\n  fun f() =\n    let x = 1\n    while x == 1 do\n      set x = x + 1\n  fun g() = if 1 is\n    0 then 2\n    1 then 2\n    else 2\n//│ ═══[COMPILATION ERROR] Other Blocks not supported in staged module: class hkmc2.codegen.Label.\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'x'\n//│ ║  l.217: \t    let x = 1\n//│ ║         \t        ^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.217: \t    let x = 1\n//│ ╙──       \t        ^\n//│ > fun ctor_() = ()\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n\n:e\nclass C(val a)\nstaged module A with\n  let x = C(1)\n  fun f() = set x.a = 0\n  fun g() = {1 : 2}\n//│ ═══[COMPILATION ERROR] Other Blocks not supported in staged module: class hkmc2.codegen.AssignField\n//│ ╔══[COMPILATION ERROR] Other Results not supported in staged module: class hkmc2.codegen.Record\n//│ ║  l.239: \t  fun g() = {1 : 2}\n//│ ╙──       \t                 ^\n//│ > fun ctor_() =\n//│ >   x = C(1)\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n\n:todo\nstaged module Spread with\n  fun f() = if [1, ..[1, 2]] is [1, ...x] then x else 0\n//│ ═══[COMPILATION ERROR] Spread parameters are not supported in staged module: Arg(Some(Lazy),Ref(tmp:tmp,None))\n//│ ═══[COMPILATION ERROR] No definition found in scope for member 'tmp'\n//│ > fun ctor_() = ()\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/block-staging/Nested.mls",
    "content": ":js\n:ftc\n:sir\n:staging\n\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ import Predef; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\nstaged fun direct() = 1\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let direct⁰; define direct⁰ as staged fun direct¹() { return 1 }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nstaged module LiftedNested with\n  fun f() =\n    fun g() = 1\n    g()\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g⁰, LiftedNested⁰;\n//│ define g⁰ as staged fun g¹() {\n//│   return 1\n//│ };\n//│ define LiftedNested⁰ as class LiftedNested¹\n//│ staged module LiftedNested² {\n//│   constructor {\n//│     let tmp, tmp1, tmp2, tmp3;\n//│     set tmp2 = LiftedNested².this.ctor$_instr﹖();\n//│     set tmp3 = Block⁰.printCode﹖(tmp2);\n//│     set tmp = LiftedNested².this.f_instr﹖();\n//│     set tmp1 = Block⁰.printCode﹖(tmp);\n//│     runtime⁰.Unit﹖\n//│   }\n//│   method ctor$_instr⁰ = fun ctor$_instr¹() {\n//│     let end, tmp, tmp1, tmp2, tmp3;\n//│     set end = Block⁰.End﹖();\n//│     set tmp = Block⁰.Symbol﹖(\"ctor$\");\n//│     set tmp1 = [];\n//│     set tmp2 = [tmp1];\n//│     set tmp3 = Block⁰.FunDefn﹖(tmp, tmp2, end, true);\n//│     return tmp3\n//│   }\n//│   method f⁰ = fun f¹() {\n//│     return g¹()\n//│   }\n//│   method f_instr⁰ = fun f_instr¹() {\n//│     let sym, var1, tmp, app, return1, tmp1, tmp2, tmp3, tmp4;\n//│     set sym = Block⁰.Symbol﹖(\"g\");\n//│     set var1 = Block⁰.ValueRef﹖(sym);\n//│     set tmp = [];\n//│     set app = Block⁰.Call﹖(var1, tmp);\n//│     set return1 = Block⁰.Return﹖(app, false);\n//│     set tmp1 = Block⁰.Symbol﹖(\"f\");\n//│     set tmp2 = [];\n//│     set tmp3 = [tmp2];\n//│     set tmp4 = Block⁰.FunDefn﹖(tmp1, tmp3, return1, true);\n//│     return tmp4\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > fun ctor_() = ()\n//│ > fun f() = g()\n\n\nstaged module LiftedLambda with\n  fun foo(x) = y => x + y\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let LiftedLambda⁰, lambda⁰, Function$⁰;\n//│ define lambda⁰ as staged fun lambda¹(x, y) {\n//│   return +⁰(x, y)\n//│ };\n//│ define Function$⁰ as staged class Function$¹ {\n//│   private val x⁰;\n//│   constructor(x) {\n//│     super⁰();\n//│     set x⁰ = x;\n//│     end\n//│   }\n//│   method call⁰ = fun call¹(y) {\n//│     return lambda¹(x⁰, y)\n//│   }\n//│ };\n//│ define LiftedLambda⁰ as class LiftedLambda¹\n//│ staged module LiftedLambda² {\n//│   constructor {\n//│     let tmp, tmp1, tmp2, tmp3;\n//│     set tmp2 = LiftedLambda².this.ctor$_instr﹖();\n//│     set tmp3 = Block⁰.printCode﹖(tmp2);\n//│     set tmp = LiftedLambda².this.foo_instr﹖();\n//│     set tmp1 = Block⁰.printCode﹖(tmp);\n//│     runtime⁰.Unit﹖\n//│   }\n//│   method ctor$_instr² = fun ctor$_instr³() {\n//│     let end, tmp, tmp1, tmp2, tmp3;\n//│     set end = Block⁰.End﹖();\n//│     set tmp = Block⁰.Symbol﹖(\"ctor$\");\n//│     set tmp1 = [];\n//│     set tmp2 = [tmp1];\n//│     set tmp3 = Block⁰.FunDefn﹖(tmp, tmp2, end, true);\n//│     return tmp3\n//│   }\n//│   method foo⁰ = fun foo¹(x) {\n//│     let tmp;\n//│     set tmp = new Function$¹(x);\n//│     return tmp\n//│   }\n//│   method foo_instr⁰ = fun foo_instr¹() {\n//│     let x, tmp, sym, tmp1, sym1, var1, tmp2, tmp3, sym2, tmp4, tmp5, sym3, var2, tmp6, inst, sym4, tmp7, return1, assign, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13;\n//│     set sym = Block⁰.Symbol﹖(\"tmp\");\n//│     set tmp1 = [sym];\n//│     set sym1 = Block⁰.Symbol﹖(\"x\");\n//│     set var1 = Block⁰.ValueRef﹖(sym1);\n//│     set tmp2 = Block⁰.Arg﹖(var1);\n//│     set tmp3 = option⁰.None﹖;\n//│     set sym2 = Block⁰.Symbol﹖(\"x1\");\n//│     set tmp4 = [sym2];\n//│     set tmp5 = [tmp4];\n//│     set sym3 = Block⁰.ConcreteClassSymbol﹖(\"Function$\", Function$⁰, tmp3, tmp5);\n//│     set var2 = Block⁰.ValueRef﹖(sym3);\n//│     set tmp6 = [tmp2];\n//│     set inst = Block⁰.Instantiate﹖(var2, tmp6);\n//│     set sym4 = Block⁰.Symbol﹖(\"tmp\");\n//│     set tmp7 = Block⁰.ValueRef﹖(sym4);\n//│     set tmp = tmp7;\n//│     set return1 = Block⁰.Return﹖(tmp7, false);\n//│     set assign = Block⁰.Assign﹖(sym4, inst, return1);\n//│     set tmp8 = Block⁰.Scoped﹖(tmp1, assign);\n//│     set tmp9 = Block⁰.Symbol﹖(\"x\");\n//│     set tmp10 = Block⁰.Symbol﹖(\"foo\");\n//│     set tmp11 = [tmp9];\n//│     set tmp12 = [tmp11];\n//│     set tmp13 = Block⁰.FunDefn﹖(tmp10, tmp12, tmp8, true);\n//│     return tmp13\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > fun ctor_() = ()\n//│ > fun foo(x) =\n//│ >   let {tmp}\n//│ >   tmp = new Function_(x)\n//│ >   tmp\n\n\nstaged module LiftedMultParams with\n  fun foo(x)(y) = x + y\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let LiftedMultParams⁰, lambda$⁰, Function$²;\n//│ define lambda$⁰ as staged fun lambda$¹(x, y) {\n//│   return +⁰(x, y)\n//│ };\n//│ define Function$² as staged class Function$³ {\n//│   private val x¹;\n//│   constructor(x) {\n//│     super⁰();\n//│     set x¹ = x;\n//│     end\n//│   }\n//│   method call² = fun call³(y) {\n//│     return lambda$¹(x¹, y)\n//│   }\n//│ };\n//│ define LiftedMultParams⁰ as class LiftedMultParams¹\n//│ staged module LiftedMultParams² {\n//│   constructor {\n//│     let tmp, tmp1, tmp2, tmp3;\n//│     set tmp2 = LiftedMultParams².this.ctor$_instr﹖();\n//│     set tmp3 = Block⁰.printCode﹖(tmp2);\n//│     set tmp = LiftedMultParams².this.foo_instr﹖();\n//│     set tmp1 = Block⁰.printCode﹖(tmp);\n//│     runtime⁰.Unit﹖\n//│   }\n//│   method ctor$_instr⁴ = fun ctor$_instr⁵() {\n//│     let end, tmp, tmp1, tmp2, tmp3;\n//│     set end = Block⁰.End﹖();\n//│     set tmp = Block⁰.Symbol﹖(\"ctor$\");\n//│     set tmp1 = [];\n//│     set tmp2 = [tmp1];\n//│     set tmp3 = Block⁰.FunDefn﹖(tmp, tmp2, end, true);\n//│     return tmp3\n//│   }\n//│   method foo² = fun foo³(x) {\n//│     let tmp;\n//│     set tmp = new Function$³(x);\n//│     return tmp\n//│   }\n//│   method foo_instr² = fun foo_instr³() {\n//│     let x, tmp, sym, tmp1, sym1, var1, tmp2, tmp3, sym2, tmp4, tmp5, sym3, var2, tmp6, inst, sym4, tmp7, return1, assign, tmp8, tmp9, tmp10, tmp11, tmp12, tmp13;\n//│     set sym = Block⁰.Symbol﹖(\"tmp\");\n//│     set tmp1 = [sym];\n//│     set sym1 = Block⁰.Symbol﹖(\"x\");\n//│     set var1 = Block⁰.ValueRef﹖(sym1);\n//│     set tmp2 = Block⁰.Arg﹖(var1);\n//│     set tmp3 = option⁰.None﹖;\n//│     set sym2 = Block⁰.Symbol﹖(\"x1\");\n//│     set tmp4 = [sym2];\n//│     set tmp5 = [tmp4];\n//│     set sym3 = Block⁰.ConcreteClassSymbol﹖(\"Function$\", Function$², tmp3, tmp5);\n//│     set var2 = Block⁰.ValueRef﹖(sym3);\n//│     set tmp6 = [tmp2];\n//│     set inst = Block⁰.Instantiate﹖(var2, tmp6);\n//│     set sym4 = Block⁰.Symbol﹖(\"tmp\");\n//│     set tmp7 = Block⁰.ValueRef﹖(sym4);\n//│     set tmp = tmp7;\n//│     set return1 = Block⁰.Return﹖(tmp7, false);\n//│     set assign = Block⁰.Assign﹖(sym4, inst, return1);\n//│     set tmp8 = Block⁰.Scoped﹖(tmp1, assign);\n//│     set tmp9 = Block⁰.Symbol﹖(\"x\");\n//│     set tmp10 = Block⁰.Symbol﹖(\"foo\");\n//│     set tmp11 = [tmp9];\n//│     set tmp12 = [tmp11];\n//│     set tmp13 = Block⁰.FunDefn﹖(tmp10, tmp12, tmp8, true);\n//│     return tmp13\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > fun ctor_() = ()\n//│ > fun foo(x) =\n//│ >   let {tmp}\n//│ >   tmp = new Function_(x)\n//│ >   tmp\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/block-staging/PrintCode.mls",
    "content": ":staging\n:js\n\nimport \"../../mlscript-compile/Block.mls\"\nimport \"../../mlscript-compile/Option.mls\"\n\nopen Block\nopen Option\n\nprintCode(FunDefn(Symbol(\"f\"), [[Symbol(\"x\")]], Return(ValueLit(1), false)))\n//│ > fun f(x) = 1\n\nprintCode(ValueLit(true))\nprintCode(ValueLit(null))\nprintCode(ValueLit(undefined))\nprintCode(ValueLit(\"c\"))\nprintCode(ValueLit(\"string\"))\n//│ > true\n//│ > null\n//│ > undefined\n//│ > \"c\"\n//│ > \"string\"\n\nprintCode(Symbol(\"internal$\"))\n//│ > internal_\n\nprintCode(Select(ValueRef(Symbol(\"p\")), Symbol(\"x\")))\nprintCode(DynSelect(ValueRef(Symbol(\"p\")), ValueRef(Symbol(\"field\")), false))\n//│ > p.x\n//│ > p.(field)\n\n:silent\nclass A(val x)(y)\nclass B\nlet aSym = ConcreteClassSymbol(\"A\", A, Some([Symbol(\"x\")]), [[Symbol(\"y\")]])\nlet bSym = ConcreteClassSymbol(\"B\", B, None, [])\n\nprintCode(Call(ValueRef(Symbol(\"f\")), [Arg(ValueLit(3))]))\nprintCode(Instantiate(ValueRef(aSym), [Arg(ValueLit(0))]))\nprintCode(Tuple([Arg(ValueRef(Symbol(\"x\"))), Arg(ValueRef(Symbol(\"y\")))]))\n//│ > f(3)\n//│ > new A(0)\n//│ > [x, y]\n\n:silent\nlet f = FunDefn(Symbol(\"f\"), [[Symbol(\"x\")]], Return(ValueLit(1), false))\n\nprintCode(f)\nprintCode(ClsLikeDefn(aSym, [f], None))\nprintCode(ClsLikeDefn(bSym, [], None))\n//│ > fun f(x) = 1\n//│ > class A(x) with\n//│ >   fun f(x) = 1\n//│ > class B\n\nprintCode(Scoped([Symbol(\"x\"), Symbol(\"y\")], Assign(Symbol(\"x\"), ValueLit(4.2), Return(ValueRef(Symbol(\"x\")), true))))\n//│ > let {x, y}\n//│ > x = 4.2\n//│ > x\n\nprintCode(Define(ValDefn(Some(aSym), Symbol(\"x\"), ValueLit(1)), End()))\nprintCode(Define(ValDefn(None, Symbol(\"a\"), ValueLit(1)), End()))\n//│ > val x = 1\n//│ > val a = 1\n\nprintCode(Match(ValueRef(Symbol(\"x\")), [Arm(Lit(1), Return(ValueLit(2), false)), Arm(Cls(aSym, ValueRef(aSym)), Return(ValueLit(3), false))], Some(Return(ValueRef(Symbol(\"x\")), false)), End()))\n//│ > if x is\n//│ >   1 then 2\n//│ >   A then 3\n//│ >   else x\n\nprintCode(Scoped([Symbol(\"y\")], Match(\n    ValueLit(1), \n    [Arm(Lit(1), Return(ValueLit(1), false))], \n    Some(Return(ValueLit(1), false)), \n    Return(ValueRef(Symbol(\"y\")), false))))\n//│ > let {y}\n//│ > if 1 is\n//│ >   1 then 1\n//│ >   else 1\n//│ > y\n\nprintCode(Scoped([Symbol(\"y\")],  Match(\n    ValueLit(1), \n    [Arm(Lit(1), Assign(Symbol(\"y\"), ValueLit(1), Return(ValueRef(Symbol(\"y\")), false)))], \n    Some(Assign(Symbol(\"y\"), ValueLit(2), Return(ValueRef(Symbol(\"y\")), false))), \n    End())))\n//│ > let {y}\n//│ > if 1 is\n//│ >   1 then\n//│ >     y = 1\n//│ >     y\n//│ >   else\n//│ >     y = 2\n//│ >     y\n\nprintCode(Scoped([Symbol(\"y\")], Match(\n    ValueLit(1), \n    [Arm(Lit(1), Match(\n        ValueLit(2),\n        [Arm(Lit(2), Assign(Symbol(\"y\"), ValueLit(1), Return(ValueRef(Symbol(\"y\")), false)))],\n        Some(Assign(Symbol(\"y\"), ValueLit(2), Return(ValueRef(Symbol(\"y\")), false))),\n        End()\n    ))], \n    Some(Assign(Symbol(\"y\"), ValueLit(3), Return(ValueRef(Symbol(\"y\")), false))), \n    End())))\n//│ > let {y}\n//│ > if 1 is\n//│ >   1 then\n//│ >     if 2 is\n//│ >       2 then\n//│ >         y = 1\n//│ >         y\n//│ >       else\n//│ >         y = 2\n//│ >         y\n//│ >   else\n//│ >     y = 3\n//│ >     y\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/block-staging/StageSymbols.mls",
    "content": ":js\n:staging\n\nstaged module M with\n  class C with\n    fun f() = 1\n    fun g() = f()\n//│ > fun ctor_() =\n//│ >   class C with\n//│ >     fun f() = 1\n//│ >     fun g() = C.f()\n\nstaged module A with\n  fun f() = 1\nmodule B with\n  fun f() = 1\nclass C(val a, b)(c)(d)\nstaged module D with\n  class E\n  fun f() =\n    A.f()\n    B.f()\n  fun matching() =\n    1 is Int\n    1 is C\n//│ > fun ctor_() = ()\n//│ > fun f() = 1\n//│ > fun ctor_() =\n//│ >   class E\n//│ > fun f() =\n//│ >   A.f_gen()\n//│ >   B.f()\n//│ > fun matching() =\n//│ >   let {scrut, scrut1, tmp}\n//│ >   scrut = 1\n//│ >   if scrut is\n//│ >     Int then\n//│ >       tmp = true\n//│ >     else\n//│ >       tmp = false\n//│ >   scrut1 = 1\n//│ >   if scrut1 is\n//│ >     C then true\n//│ >     else false\n\nmodule A with\n  module B with\n    class C(a)\nstaged module M with\n  class E\n  fun f() = \n    D.E\n    A.B.C\n    A.B.C(1)\n    E\n//│ > fun ctor_() =\n//│ >   class E\n//│ > fun f() =\n//│ >   A.B.C(1)\n//│ >   M.E\n\n:e\nstaged module M with\n  fun g()() = 1\n//│ ╔══[COMPILATION ERROR] :ftc must be enabled to desugar functions with multiple parameter lists.\n//│ ║  l.64: \t  fun g()() = 1\n//│ ╙──      \t  ^^^^^^^^^^^^^\n//│ > fun ctor_() = ()\n//│ > fun g()() = 1\n\n:ftc\nstaged module M with\n  fun f() = x => x\n  fun g()() = 1\n//│ > fun ctor_() = ()\n//│ > fun f() =\n//│ >   let {tmp}\n//│ >   tmp = new Function_\n//│ >   tmp\n//│ > fun g() =\n//│ >   let {tmp1}\n//│ >   tmp1 = new Function_1\n//│ >   tmp1\n\n// TODO: these need to be printed, somehow:\n:noModuleCheck\nlet x = M.\"f_instr\"().body.rest.rhs.cls.l.value\nlet y = M.\"g_instr\"().body.rest.rhs.cls.l.value\n//│ x = class Function$\n//│ y = class Function$\n(new x).call(2)\n//│ = 2\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/block-staging/SymbolRenaming.mls",
    "content": ":js\n:staging\n\nstaged module TempVariable with\n  fun f() =\n    let x\n    let x\n    x\n//│ > fun ctor_() = ()\n//│ > fun f() =\n//│ >   let {x, x1}\n//│ >   x1\n\nstaged module DupeFunctionName with\n  fun f() = 1\n//│ > fun ctor_() = ()\n//│ > fun f() = 1\n\nclass C(val x)\n\nstaged module Selection with\n  fun f(x) =\n    x.call()\n    C(1).x is Bool\n//│ > fun ctor_() = ()\n//│ > fun f(x) =\n//│ >   let {scrut, tmp}\n//│ >   x.call()\n//│ >   tmp = C(1)\n//│ >   scrut = tmp.x\n//│ >   if scrut is\n//│ >     Bool then true\n//│ >     else false\n\nstaged module DupeClass with\n  class C(val y)\n  fun f() = C(1).y\n//│ > fun ctor_() =\n//│ >   class C(y)\n//│ > fun f() =\n//│ >   let {tmp}\n//│ >   tmp = DupeClass.C(1)\n//│ >   tmp.y\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/block-staging/Syntax.mls",
    "content": "\n:pt\nstaged module A\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ Modified:\n//│   modifier = Keywrd of keyword 'staged'\n//│   body = TypeDef:\n//│     k = Mod\n//│     head = Ident of \"A\"\n\n// TODO: reject these annotations?\nstaged object Foo\n\nstaged class Foo\n\nstaged fun f() = 0\n\n:js\n:sir\n:staging\nstaged module A\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A⁰;\n//│ define A⁰ as class A¹\n//│ staged module A² {\n//│   constructor {\n//│     let tmp, tmp1;\n//│     set tmp = A².this.ctor$_instr﹖();\n//│     set tmp1 = Block⁰.printCode﹖(tmp);\n//│     runtime⁰.Unit﹖\n//│   }\n//│   method ctor$_instr⁰ = fun ctor$_instr¹() {\n//│     let end, tmp, tmp1, tmp2, tmp3;\n//│     set end = Block⁰.End﹖();\n//│     set tmp = Block⁰.Symbol﹖(\"ctor$\");\n//│     set tmp1 = [];\n//│     set tmp2 = [tmp1];\n//│     set tmp3 = Block⁰.FunDefn﹖(tmp, tmp2, end, true);\n//│     return tmp3\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > fun ctor_() = ()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Arrays.mls",
    "content": ":js\n\n\nlet empty = []\n//│ empty = []\n\n:re\nempty.0\n//│ ═══[RUNTIME ERROR] Error: Access to required field '0' yielded 'undefined'\n\n:sjs\nlet single = [1]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let single; single = globalThis.Object.freeze([ 1 ]);\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ single = [1]\n\nsingle.0\n//│ = 1\n\n\n:sjs\nval single = [1]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let single1, tmp; tmp = globalThis.Object.freeze([ 1 ]); single1 = tmp;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ single = [1]\n\nsingle.0\n//│ = 1\n\nval pair = [1, 2]\n//│ pair = [1, 2]\n\npair.0\n//│ = 1\n\npair.1\n//│ = 2\n\nval triple = [1, 2, 3]\n//│ triple = [1, 2, 3]\n\ntriple.2\n//│ = 3\n\n:re\ntriple.3\n//│ ═══[RUNTIME ERROR] Error: Access to required field '3' yielded 'undefined'\n\n:re\ntriple.4\n//│ ═══[RUNTIME ERROR] Error: Access to required field '4' yielded 'undefined'\n\n\n// * Array hacking (taken from Anto's original port of nofib, which was slightly deranged)\n\nset Array.prototype.toString =\n  globalThis.eval(\"(function() { return '(' + Array.prototype.join.call(this, ',') + ')'; })\")\n\n[1, 2, 3]\n//│ = [1, 2, 3]\n\nnew Array(4)\n//│ = [<4 empty items>]\n\n\n// TODO also sanity-check these accesses\n\n:breakme\n:re\nempty.(0)\n\n:breakme\n:re\nempty.[0]\n\nempty.[\"oops\"]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadConfigDirective.mls",
    "content": ":js\n\n\n:w\n@config(tailRecOpt: false) \"hi\"\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ╟── This annotation is not supported on string literal terms.\n//│ ║  l.5: \t@config(tailRecOpt: false) \"hi\"\n//│ ╙──     \t                           ^^^^\n//│ = \"hi\"\n\n// TODO: report useless `tailRecOpt` config annotation on non-function term\n:breakme\n@config(tailRecOpt: false) val x = 1\n//│ x = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadFunctions.mls",
    "content": ":js\n\n\n:fixme\nfun (let) oops = 1\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found end of input instead\n//│ ║  l.5: \tfun (let) oops = 1\n//│ ╙──     \t        ^\n//│ ╔══[COMPILATION ERROR] This ‹erroneous syntax› is not a valid symbolic name\n//│ ║  l.5: \tfun (let) oops = 1\n//│ ╙──     \t        ^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadImport.mls",
    "content": ":js\n\n\n:e\nimport 123\n//│ ╔══[COMPILATION ERROR] Expected string literal after 'import' keyword\n//│ ║  l.5: \timport 123\n//│ ╙──     \t       ^^^\n\n\n// * Produces lots of output\n// import \"fs\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadInit.mls",
    "content": ":js\n\n\n// Note:\n//  This used to fail.\n//  It now works, but allowing this to work requires nontrivial compilation\n//  in a way that makes objects problematic to lift, in the lifter.\n//  So, we might just want to drop objects altogether\n//  and just use `val`s with more obvious initialization semantics (?)\n:sjs\nobject Bar with\n  val x = 1\n  module Baz with\n    val a = Bar.x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Bar1;\n//│ (class Bar {\n//│   static {\n//│     new this\n//│   }\n//│   constructor() {\n//│     Bar1 = this;\n//│     this.x = 1;\n//│     const this$Bar = this;\n//│     (class Baz {\n//│       static {\n//│         this$Bar.Baz = this\n//│       }\n//│       static {\n//│         this.a = Bar1.x;\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"Baz\"]; \n//│     });\n//│     Object.defineProperty(this, \"class\", {\n//│       value: Bar\n//│     });\n//│     globalThis.Object.freeze(this);\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"object\", \"Bar\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * Modules don't have this initialization problem because they set their bindings\n// * as the first thing in their static ctors.\n// * Objects can't really do so because their (non-static) ctors could be called from child classes.\n:sjs\nmodule Bar with\n  val x = 1\n  module Baz with\n    val a = Bar.x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Bar3;\n//│ (class Bar2 {\n//│   static {\n//│     Bar3 = this\n//│   }\n//│   static {\n//│     this.x = 1;\n//│     (class Baz1 {\n//│       static {\n//│         Bar2.Baz = this\n//│       }\n//│       static {\n//│         this.a = Bar3.x;\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"Baz\"]; \n//│     });\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Bar\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadNew.mls",
    "content": ":js\n\n\n:pe\n:re\nnew\n//│ ╔══[PARSE ERROR] Expected 'with' keyword, expression, or block after `new` keyword; found end of input instead\n//│ ║  l.6: \tnew\n//│ ╙──     \t   ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n:re\nnew 2\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found integer literal.\n//│ ║  l.14: \tnew 2\n//│ ║        \t    ^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: 2 is not a constructor\n\n:e\n:re\nnew 2 + 2\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found integer literal.\n//│ ║  l.23: \tnew 2 + 2\n//│ ║        \t    ^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: 2 is not a constructor\n\n:sjs\n:re\nnew! 2 + 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp1; tmp1 = globalThis.Object.freeze(new 2()); tmp1 + 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: 2 is not a constructor\n\n:e\n:re\nnew()\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found unit value.\n//│ ║  l.40: \tnew()\n//│ ║        \t   ^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: runtime.Unit is not a constructor\n\n:re\nnew!()\n//│ ═══[RUNTIME ERROR] TypeError: runtime.Unit is not a constructor\n\n:e\n:re\nnew {}\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found unit value.\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] TypeError: runtime.Unit is not a constructor\n\n:pe\nnew! {}\n//│ ╔══[PARSE ERROR] Expected expression after prefix keyword 'new!'; found end of block instead\n//│ ║  l.59: \tnew! {}\n//│ ╙──      \t     ^^\n\n\n// * Note that thanks to the parser \"feature\" for keyword-block stutter\n// * this used to parse as `((new x) = 1)`;\n// * it no longer does, since I make `new` accept `exprOrBlk`\n:e\n:pt\nnew { x = 1 }\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ LexicalNew:\n//│   body = S of Block of Ls of \n//│     Def:\n//│       lhs = Ident of \"x\"\n//│       rhs = IntLit of 1\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.70: \tnew { x = 1 }\n//│ ╙──      \t      ^\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found block.\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nnew! { x = 1 }\n//│ ╔══[COMPILATION ERROR] Unrecognized definitional assignment left-hand side: prefix operator 'new!'\n//│ ║  l.86: \tnew! { x = 1 }\n//│ ╙──      \t^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:e\nlet xs = new Oopsie\n//│ ╔══[COMPILATION ERROR] Name not found: Oopsie\n//│ ║  l.94: \tlet xs = new Oopsie\n//│ ╙──      \t             ^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found ‹error›.\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ xs = undefined\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadOpen.mls",
    "content": ":js\n\n\nmodule Foo with\n  val x = 1\n\n\n:e\n(open Foo { x })\n//│ ╔══[COMPILATION ERROR] Illegal position for 'open' statement.\n//│ ║  l.9: \t(open Foo { x })\n//│ ╙──     \t ^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n(((open Foo { x })))\n//│ ╔══[COMPILATION ERROR] Illegal position for 'open' statement.\n//│ ║  l.16: \t(((open Foo { x })))\n//│ ╙──      \t   ^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n(open Foo { x }) + 1\n//│ ╔══[COMPILATION ERROR] Illegal position for 'open' statement.\n//│ ║  l.23: \t(open Foo { x }) + 1\n//│ ╙──      \t ^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nopen Foo { y }\n//│ ╔══[COMPILATION ERROR] Module 'Foo' does not contain member 'y'\n//│ ║  l.30: \topen Foo { y }\n//│ ╙──      \t           ^\n\n:sjs\ny\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo1.y\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nval Oops = \"oops\"\n//│ Oops = \"oops\"\n\n:e\nopen Oops\n//│ ╔══[COMPILATION ERROR] Wildcard 'open' not supported for this kind of symbol.\n//│ ║  l.46: \topen Oops\n//│ ╙──      \t     ^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadSpreads.mls",
    "content": ":js\n\n\n:e\n..., 1\n//│ ╔══[COMPILATION ERROR] Illegal position for '...' spread operator.\n//│ ║  l.5: \t..., 1\n//│ ╙──     \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nfun f = ..., 1\n//│ ╔══[COMPILATION ERROR] Illegal position for '...' spread operator.\n//│ ║  l.12: \tfun f = ..., 1\n//│ ╙──      \t        ^^^\n//│ = 1\n\n\n:re\n[0, ...1]\n//│ ═══[RUNTIME ERROR] TypeError: 1 is not iterable\n\n\n:e\nfun foo(a, ...b, c) = [a, ...b, c]\n//│ ╔══[COMPILATION ERROR] Spread parameters must be the last in the parameter list.\n//│ ║  l.25: \tfun foo(a, ...b, c) = [a, ...b, c]\n//│ ╙──      \t           ^^^^\n\n:e\nfun foo(a, ...b, c) = [a, ...b]\n//│ ╔══[COMPILATION ERROR] Spread parameters must be the last in the parameter list.\n//│ ║  l.31: \tfun foo(a, ...b, c) = [a, ...b]\n//│ ╙──      \t           ^^^^\n\n:re\nfoo(1, 2, 3)\n//│ ═══[RUNTIME ERROR] TypeError: b is not iterable\n\n\nfun foo(a, ...b) = [a, ...b]\n\n:e\n:re\nfoo()\n//│ ╔══[COMPILATION ERROR] Expected at least 1 arguments, got 0\n//│ ║  l.45: \tfoo()\n//│ ╙──      \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Function 'foo' expected at least 1 argument but got 0\n\n\n:e\nfun foo(1) = 2\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found integer literal\n//│ ║  l.53: \tfun foo(1) = 2\n//│ ╙──      \t        ^\n\n:e\nfun foo(...1) = 2\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found spread\n//│ ║  l.59: \tfun foo(...1) = 2\n//│ ╙──      \t        ^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadThis.mls",
    "content": ":js\n\n\nglobalThis.clearInterval\n//│ = fun clearInterval\n\nclass A\n\n:re\nif 0 is A then 1\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n// * Unhygienic binding...\n// * TODO: prevent rebinding of `globalThis`\n:re\nval globalThis = \"oops\"\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n\n:re\nglobalThis.clearInterval\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n\n:re\nif 0 is A then 1\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadValInit.mls",
    "content": ":js\n\n\n// TODO raise initialization error at CT and RT\n// TODO show undefined-valued defined bindings\nval a = b\nval b = 1\n//│ a = undefined\n//│ b = 1\n\n\nval a = ()\n//│ a = ()\n\na\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BadWhile.mls",
    "content": ":js\n\n\n:e\n:sjs\nwhile {} do()\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'do' here\n//│ ║  l.6: \twhile {} do()\n//│ ╙──     \t         ^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ throw \"This code cannot be run as its compilation yielded an error.\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n// * Warn about pure expressions in statement position in `while` branches\n:w\nfun f() =\n  let i = 10\n  while i > 0 do\n    set i -= 1\n    i\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.22: \t    i\n//│ ╙──      \t    ^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BasicTerms.mls",
    "content": ":js\n\n:global\n:sjs\n\n\n1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:lot\n:w\n1\n2\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.15: \t1\n//│ ╙──      \t^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 2\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.15: \t1\n//│ ╙──      \t^\n//│ —————————————| Lowered IR Tree |————————————————————————————————————————————————————————————————————\n//│ Program:\n//│   main = Return:\n//│     res = Lit of IntLit of 2\n//│     implct = true\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\nprint(\"Hi\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Predef.print(\"Hi\")\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > Hi\n\n:lot\nprint(\"Hi\")\n2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Predef.print(\"Hi\"); 2\n//│ —————————————| Lowered IR Tree |————————————————————————————————————————————————————————————————————\n//│ Program:\n//│   main = Assign:\n//│     lhs = ‹no symbol›⁰\n//│     rhs = Call:\n//│       fun = Select{sym=term:Predef⁰/print⁰}:\n//│         qual = Ref{disamb=module:Predef⁰}:\n//│           l = member:Predef¹\n//│           disamb = S of module:Predef⁰\n//│         name = Ident of \"print\"\n//│       argss = Ls of \n//│         Ls of \n//│           Arg:\n//│             value = Lit of StrLit of \"Hi\"\n//│     rest = Return: \\\n//│     res = Lit of IntLit of 2\n//│     implct = true\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > Hi\n//│ = 2\n\n\n:re\n2(2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(2(2))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: 2 is not a function\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Bindings.mls",
    "content": ":js\n// :sjs\n// :elt\n// :lot\n\n\nlet x = 1\nx + 1\n//│ = 2\n//│ x = 1\n\nx\n//│ = 1\n\nlet x = 2\n//│ x = 2\n\nx\n//│ = 2\n\nlet x = 1\nlet y = x\nx + y\n//│ = 2\n//│ x = 1\n//│ y = 1\n\nlet x =\n  let y = 2 in y + 1\nx * 2\n//│ = 6\n//│ x = 3\n\nlet x =\n  let x = 2 in x + 1\nx * 2\n//│ = 6\n//│ x = 3\n\n\nlet x = 1\n//│ x = 1\n\nfun incr(n) = n + 1\nfun (|>) pipe(x, f) = f(x)\n\nlet x = x |> incr\n//│ x = 2\n\nlet x |>= incr\n//│ x = 3\n\n\n:e\nlet 2\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.55: \tlet 2\n//│ ╙──      \t    ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nlet x += 1 = 0\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.62: \tlet x += 1 = 0\n//│ ╙──      \t    ^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nlet x += 1 = 0 in x\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.69: \tlet x += 1 = 0 in x\n//│ ╙──      \t    ^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:e\n(let x = 1)\n//│ ╔══[COMPILATION ERROR] Expected a body for let bindings in expression position\n//│ ║  l.77: \t(let x = 1)\n//│ ╙──      \t     ^^^^^\n\n:e\n(let x = 1) + 1\n//│ ╔══[COMPILATION ERROR] Expected a body for let bindings in expression position\n//│ ║  l.83: \t(let x = 1) + 1\n//│ ╙──      \t     ^^^^^\n//│ = \"()1\"\n\n:e\n(let f(x) = x) + 1\n//│ ╔══[COMPILATION ERROR] Expected a body for let bindings in expression position\n//│ ║  l.90: \t(let f(x) = x) + 1\n//│ ╙──      \t     ^^^^^^^^\n//│ = \"()1\"\n\n(let f(x) = x + 1 in f(42)) + 1\n//│ = 44\n\n\nlet x = 1 in console.log(x); x\n//│ > 1\n//│ = 1\n\n\nlet x = 1 in\n  console.log(x)\n  console.log(x)\n//│ > 1\n//│ > 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BlockPrinter.mls",
    "content": ":js\n:sir\n\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ import Predef; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n#config(commentGeneratedCode: true)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n2 + 2 + 2\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let tmp; set tmp = +⁰(2, 2); +⁰(tmp, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 6\n\n\n:lot\nlet x = 1\nx + 1\n//│ —————————————| Lowered IR Tree |————————————————————————————————————————————————————————————————————\n//│ Program:\n//│   main = Scoped(syms = {x⁰}): \n//│     body = Assign:\n//│       lhs = x⁰\n//│       rhs = Lit of IntLit of 1\n//│       rest = Return: \\\n//│       res = Call:\n//│         fun = Ref:\n//│           l = builtin:+⁰\n//│         argss = Ls of \n//│           Ls of \n//│             Arg:\n//│               value = Ref:\n//│                 l = x⁰\n//│             Arg:\n//│               value = Lit of IntLit of 1\n//│       implct = true\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x⁰; set x⁰ = 1; +⁰(x⁰, 1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n//│ x = 1\n\nx\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ x⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\nlet x = 1\nx + 1\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x¹; set x¹ = 1; +⁰(x¹, 1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n//│ x = 1\n\n\n// * Notice that the IR has two symbols: the BlockMemberSymbol x² but also the more specific TermSymbol x³.\n// * This is because x² could be overloaded and contain other definitions, such as a type definition.\n// * In the end, the JS just uses one variable.\n:sjs\nval x = 1\nx + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x2; x2 = 1; x2 + 1\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x²; define x² as val x³ = 1; +⁰(x³, 1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n//│ x = 1\n\n\ncase\n  []         then print(\"empty\")\n  [x, ...xs] then print(\"non-empty\", x)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda⁰;\n//│ define lambda⁰ as fun lambda¹(caseScrut) {\n//│   let x, xs, middleElements, element0$;\n//│   match caseScrut\n//│     Array(0) =>\n//│       return Predef⁰.print⁰(\"empty\")\n//│     Array(1+) =>\n//│       set element0$ = runtime⁰.Tuple﹖.get⁰(caseScrut, 0);\n//│       set middleElements = runtime⁰.Tuple﹖.slice⁰(caseScrut, 1, 0);\n//│       set xs = middleElements;\n//│       set x = element0$;\n//│       return Predef⁰.print⁰(\"non-empty\", x)\n//│     else\n//│       throw new globalThis⁰.Error⁰(\"match error\")\n//│   end\n//│ };\n//│ lambda¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\nfun f(x) =\n  let y = 1 in x + y\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁰; define f⁰ as fun f¹(x) { let y; set y = 1; return +⁰(x, y) }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun f(x) =\n  let y = 1 in x + y\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f²; define f² as fun f³(x) { let y; set y = 1; return +⁰(x, y) }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nfun incr(n) = n + 1\nfun (|>) pipe(x, f) = f(x)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let incr⁰, pipe⁰;\n//│ define incr⁰ as fun incr¹(n) {\n//│   return +⁰(n, 1)\n//│ };\n//│ define pipe⁰ as fun pipe¹(x, f) { return f(x) };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet x = 1\nlet x = if x == 0 then 1 else 0\nlet x = x + 1\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x⁴, x⁵, scrut, x⁶, tmp;\n//│ set x⁴ = 1;\n//│ set scrut = Predef⁰.equals⁰(x⁴, 0);\n//│ match scrut\n//│   true =>\n//│     set tmp = 1;\n//│     end\n//│   else\n//│     set tmp = 0;\n//│     end\n//│ set x⁵ = tmp;\n//│ set x⁶ = +⁰(x⁵, 1);\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ x = 1\n\n\nclass C(x)\nC(123)\nnew C(123)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let C⁰;\n//│ define C⁰ as class C²(x) {\n//│   private val x⁷;\n//│   constructor C¹ { set x⁷ = x; end }\n//│ };\n//│ do C¹(123);\n//│ new C²(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = C(_)\n\nmodule A with\n  val x = 2\n  let y = 3\n  class C(x) with\n    fun f(x) = 2\n  fun g(x) = 3\nA.x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A⁰;\n//│ define A⁰ as class A¹\n//│ module A² {\n//│   private val y⁰;\n//│   val x⁸;\n//│   constructor {\n//│     define x⁸ as val x⁹ = 2;\n//│     set y⁰ = 3;\n//│     define C³ as class C⁵(x) {\n//│       private val x¹⁰;\n//│       constructor C⁴ {\n//│         set x¹⁰ = x;\n//│         end\n//│       }\n//│       method f⁴ = fun f⁵(x1) { return 2 }\n//│     };\n//│     end\n//│   }\n//│   method g⁰ = fun g¹(x) { return 3 }\n//│ };\n//│ A².x⁹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\nmodule A with\n  val x = 3\nA.x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A³;\n//│ define A³ as class A⁴\n//│ module A⁵ { val x¹¹; constructor { define x¹¹ as val x¹² = 3; end } };\n//│ A⁵.x¹²\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\nclass A\nclass B(x) extends A with\n  val y = 2\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A⁶, B⁰;\n//│ define A⁶ as class A⁷;\n//│ define B⁰ as class B²(x) {\n//│   private val x¹³;\n//│   val y¹;\n//│   constructor B¹ { super⁰(); set x¹³ = x; define y¹ as val y² = 2; end }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\npattern P = B\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let P⁰;\n//│ define P⁰ as pattern P¹ {\n//│   method unapply⁰ = fun unapply¹(input) {\n//│     match input\n//│       B² =>\n//│         return new runtime⁰.MatchSuccess⁰(input, null)\n//│       else\n//│         return new runtime⁰.MatchFailure⁰(null)\n//│     end\n//│   }\n//│   method unapplyStringPrefix⁰ = fun unapplyStringPrefix¹(input) {\n//│     return new runtime⁰.MatchFailure⁰(null)\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nobject A with\n  fun f = 42\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let A⁸; define A⁸ as object A⁹ { method f⁶ = fun f⁷ { return 42 } }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet x = [1, 2, 3]\nx.0\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x¹⁴, selRes;\n//│ set x¹⁴ = [1, 2, 3];\n//│ set selRes = x¹⁴.0﹖;\n//│ do x¹⁴.0$__checkNotMethod﹖;\n//│ match selRes\n//│   undefined =>\n//│     throw new globalThis⁰.Error﹖(\"Access to required field '0' yielded 'undefined'\")\n//│   else\n//│     selRes\n//│ end /* (Unreachable:) rest of abortive match */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n//│ x = [1, 2, 3]\n\nlet y = { x: 2 }\ny!x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let y³, x¹⁵; set x¹⁵ = 2; set y³ = { \"x\": x¹⁵ }; y³!\"x\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n//│ y = {x: 2}\n\n\nfun foo =\n  class A\n  new A\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo⁰; define foo⁰ as fun foo¹() { let A; define A as class A¹⁰; return new A¹⁰() }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BuiltinOps.mls",
    "content": ":js\n\n\n:sjs\n2 + 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 2 + 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 4\n\n:sjs\n2 +. 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 2 + 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 4\n\n:sjs\n+2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ + 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n+\n//│ = fun\n\n// * A bit confusing... but at least there's a warning!\n:w\n+(2, 3)\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.30: \t+(2, 3)\n//│ ╙──      \t  ^\n//│ = 3\n\n*(2, 3)\n//│ = 6\n\n:ge\n*(1)\n//│ ╔══[COMPILATION ERROR] Builtin '*' is not a unary operator\n//│ ║  l.40: \t*(1)\n//│ ╙──      \t^^^^\n//│ ═══[COMPILATION ERROR] Cannot call non-unary builtin symbol '*'\n//│ ═══[RUNTIME ERROR] Error: Cannot call non-unary builtin symbol '*'\n\n(+)\n//│ = fun\n\n(+)(2, 3)\n//│ = 5\n\n(*)(2, 3)\n//│ = 6\n\n:ge\n(*)(2)\n//│ ╔══[COMPILATION ERROR] Builtin '*' is not a unary operator\n//│ ║  l.57: \t(*)(2)\n//│ ╙──      \t^^^^^^\n//│ ═══[COMPILATION ERROR] Cannot call non-unary builtin symbol '*'\n//│ ═══[RUNTIME ERROR] Error: Cannot call non-unary builtin symbol '*'\n\nid(+)\n//│ = fun\n\nid(+)(1, 2)\n//│ = 3\n\n(+ 1)\n//│ = 1\n\n(+)(1)\n//│ = 1\n\n:sjs\n:re\nid(+)(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda4, baseCall1;\n//│ lambda4 = (undefined, function (arg1, arg2) {\n//│   return arg1 + arg2\n//│ });\n//│ baseCall1 = Predef.id(lambda4);\n//│ runtime.safeCall(baseCall1(1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Function expected 2 arguments but got 1\n\n\nfun (+) lol(a, b) = [a, b]\n\n:sjs\n1 + 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ lol(1, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [1, 2]\n\n\n:sjs\nid(~)(2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda5, baseCall2;\n//│ lambda5 = (undefined, function (arg) {\n//│   return ~ arg\n//│ });\n//│ baseCall2 = Predef.id(lambda5);\n//│ runtime.safeCall(baseCall2(2))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = -3\n\n2 |> ~\n//│ = -3\n\n\ntypeof\n//│ = fun\n\ntypeof(1)\n//│ = \"number\"\n\ntypeof(\"a\")\n//│ = \"string\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/BuiltinSymbols.mls",
    "content": ":js\n\n\n// * Prevent explicit accesses to Unit, Int etc. from Prelude or elaborate them\n\n:ge\nInt\n//│ ╔══[COMPILATION ERROR] Symbol 'Int' is virtual (i.e., \"compiler fiction\"); cannot be used as a term\n//│ ║  l.7: \tInt\n//│ ╙──     \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:ge\nStr\n//│ ╔══[COMPILATION ERROR] Symbol 'Str' is virtual (i.e., \"compiler fiction\"); cannot be used as a term\n//│ ║  l.14: \tStr\n//│ ╙──      \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:ge\nBool\n//│ ╔══[COMPILATION ERROR] Symbol 'Bool' is virtual (i.e., \"compiler fiction\"); cannot be used as a term\n//│ ║  l.21: \tBool\n//│ ╙──      \t^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:soir\n(case Bool then 1)(true)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let lambda⁰, caseScrut⁰, inlinedVal;\n//│ set caseScrut⁰ = true;\n//│ match caseScrut⁰\n//│   Bool⁰ =>\n//│     set inlinedVal = 1;\n//│     inlinedVal\n//│   else\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/CaseOfCase.mls",
    "content": ":js\n\n\ndata class Some[out A](value: A)\n\nobject None\n\n\n:sjs\nfun test(x) =\n  if (if x is\n    Some(v) then Some(v + 1)\n    None then None\n  ) is\n    Some(v) then print(v)\n    None then print(\"none\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test;\n//│ test = function test(x) {\n//│   let v, scrut, v1, arg$Some$0$, arg$Some$0$1, tmp, tmp1;\n//│   if (x instanceof Some1.class) {\n//│     arg$Some$0$1 = x.value;\n//│     v = arg$Some$0$1;\n//│     tmp = v + 1;\n//│     tmp1 = Some1(tmp);\n//│   } else if (x instanceof None1.class) {\n//│     tmp1 = None1;\n//│   } else {\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│   }\n//│   scrut = tmp1;\n//│   if (scrut instanceof Some1.class) {\n//│     arg$Some$0$ = scrut.value;\n//│     v1 = arg$Some$0$;\n//│     return Predef.print(v1)\n//│   } else if (scrut instanceof None1.class) {\n//│     return Predef.print(\"none\")\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/CaseShorthand.mls",
    "content": ":js\n\n\ncase x then x\n//│ = fun\n\n:sjs\ncase { x then x }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda1; lambda1 = (undefined, function (caseScrut) { let x; x = caseScrut; return x }); lambda1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n:sjs\nx => if x is\n  0 then true\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda2;\n//│ lambda2 = (undefined, function (x) {\n//│   if (x === 0) {\n//│     return true\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ lambda2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n:sjs\ncase 0 then true\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda3;\n//│ lambda3 = (undefined, function (caseScrut) {\n//│   if (caseScrut === 0) {\n//│     return true\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ lambda3\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n// * Note: `case`/`do` works analogously to `if`/`do`\n:sjs\ncase\n  0 do print(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda4;\n//│ lambda4 = (undefined, function (caseScrut) {\n//│   if (caseScrut === 0) { Predef.print(1); return runtime.Unit }\n//│   return runtime.Unit;\n//│ });\n//│ lambda4\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n(case x then x) of 1\n//│ = 1\n\n1 |> case x then x\n//│ = 1\n\n1 |> id of case x then x\n//│ = 1\n\n[1] |> case [x] then x\n//│ = 1\n\n1 |> (2 |> case x then case y then [x, y]) |> case [a, b] then [b, a]\n//│ = [1, 2]\n\n:todo // TODO: support this braceless syntax?\ncase [x] then x, [] then 0\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.75: \tcase [x] then x, [] then 0\n//│ ╙──      \t                 ^^^^^^^^^\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.75: \tcase [x] then x, [] then 0\n//│ ╙──      \t^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:sjs\ncase\n  0 then true\n  _ then false\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda11;\n//│ lambda11 = (undefined, function (caseScrut1) {\n//│   if (caseScrut1 === 0) { return true }\n//│   return false;\n//│ });\n//│ lambda11\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\ndata class Some(value)\nobject None\n\n:sjs\nval isDefined = case\n  Some then true\n  None then false\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let isDefined, lambda12;\n//│ lambda12 = (undefined, function (caseScrut1) {\n//│   if (caseScrut1 instanceof Some1.class) {\n//│     return true\n//│   } else if (caseScrut1 instanceof None1.class) {\n//│     return false\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ isDefined = lambda12;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ isDefined = fun\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ClassInClass.mls",
    "content": ":js\n\n\n:sjs\ndata class Outer(a, b) with\n  data class Inner(c) with\n    fun i1(d) = [b, c, d]\n    print(a)\n    print(c)\n    print(i1(a))\n  fun o1(c) = Inner(c)\n  fun o2(c, d) = Inner(c).i1(d)\n  val i = Inner(a)\n  print(i.c)\n  print(i.i1(1))\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Outer1;\n//│ Outer1 = function Outer(a, b) {\n//│   return globalThis.Object.freeze(new Outer.class(a, b));\n//│ };\n//│ (class Outer {\n//│   static {\n//│     Outer1.class = this\n//│   }\n//│   constructor(a, b) {\n//│     let tmp, tmp1;\n//│     this.a = a;\n//│     this.b = b;\n//│     const this$Outer = this;\n//│     this.Inner = function Inner(c) {\n//│       return globalThis.Object.freeze(new Inner.class(c));\n//│     };\n//│     (class Inner {\n//│       static {\n//│         this$Outer.Inner.class = this\n//│       }\n//│       constructor(c) {\n//│         let tmp2;\n//│         this.c = c;\n//│         Predef.print(this$Outer.a);\n//│         Predef.print(this.c);\n//│         tmp2 = this.i1(this$Outer.a);\n//│         Predef.print(tmp2);\n//│       }\n//│       i1(d) {\n//│         return globalThis.Object.freeze([\n//│           this$Outer.b,\n//│           this.c,\n//│           d\n//│         ])\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"Inner\", [\"c\"]]; \n//│     });\n//│     tmp = this.Inner(this.a);\n//│     this.i = tmp;\n//│     Predef.print(this.i.c);\n//│     tmp1 = runtime.safeCall(this.i.i1(1));\n//│     Predef.print(tmp1);\n//│   }\n//│   o1(c) {\n//│     return this.Inner(c)\n//│   } \n//│   o2(c, d) {\n//│     let tmp;\n//│     tmp = this.Inner(c);\n//│     return tmp.i1(d)\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Outer\", [\"a\", \"b\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nval o = Outer(100, 200)\n//│ > 100\n//│ > 100\n//│ > [200, 100, 100]\n//│ > 100\n//│ > [200, 100, 1]\n//│ o = Outer(100, 200)\n\no.o1(30)\n//│ > 100\n//│ > 30\n//│ > [200, 30, 100]\n//│ = Inner(30)\n\no.o2(30, 40)\n//│ > 100\n//│ > 30\n//│ > [200, 30, 100]\n//│ = [200, 30, 40]\n\no.i\n//│ = Inner(100)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ClassInFun.mls",
    "content": ":js\n\n\n:sjs\nfun test(a) =\n  class C with { val x = a }\n  new C\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test;\n//│ test = function test(a) {\n//│   let C1;\n//│   (class C {\n//│     static {\n//│       C1 = this\n//│     }\n//│     constructor() {\n//│       this.x = a;\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"class\", \"C\"]; \n//│   });\n//│   return globalThis.Object.freeze(new C1())\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ntest(12)\n//│ = C { x: 12 }\n\nfun test(x) =\n  data class Foo(x)\n  Foo(x)\n\ntest(3)\n//│ = Foo(3)\n\n:sjs\nfun test(x) =\n  data class Foo(a, b)\n  Foo(x, x + 1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test2;\n//│ test2 = function test(x) {\n//│   let Foo2, tmp;\n//│   Foo2 = function Foo(a, b) {\n//│     return globalThis.Object.freeze(new Foo.class(a, b));\n//│   };\n//│   (class Foo1 {\n//│     static {\n//│       Foo2.class = this\n//│     }\n//│     constructor(a, b) {\n//│       this.a = a;\n//│       this.b = b;\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"class\", \"Foo\", [\"a\", \"b\"]]; \n//│   });\n//│   tmp = x + 1;\n//│   return Foo2(x, tmp)\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\ntest(123)\n//│ = Foo(123, 124)\n\n\n// * Forgot to pass the arg:\n:e\n:re\ntest()\n//│ ╔══[COMPILATION ERROR] Expected 1 arguments, got 0\n//│ ║  l.71: \ttest()\n//│ ╙──      \t    ^^\n//│ ═══[RUNTIME ERROR] Error: Function 'test' expected 1 argument but got 0\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ClassMatching.mls",
    "content": ":js\n\n\ndata class Some[out A](value: A)\n\nobject None\n\n\n:sjs\nif Some(0) is Some(x) then x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut, x, arg$Some$0$;\n//│ scrut = Some1(0);\n//│ if (scrut instanceof Some1.class) {\n//│   arg$Some$0$ = scrut.value;\n//│   x = arg$Some$0$;\n//│   x\n//│ } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\nlet s = Some(0)\n//│ s = Some(0)\n\n:sjs\nif s is\n  Some(x) then x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x1, arg$Some$0$1;\n//│ if (s instanceof Some1.class) {\n//│   arg$Some$0$1 = s.value;\n//│   x1 = arg$Some$0$1;\n//│   x1\n//│ } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\nif s is\n  Some(x) then x\n  None then 1\n//│ = 0\n\n:sir\n:soir\n:re\nif s is\n  Some(1) then 0\n  None then 1\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let arg$Some$0$, tmp;\n//│ block split_root$:\n//│   block split_default$:\n//│     match s⁰\n//│       Some⁰ =>\n//│         set arg$Some$0$ = s⁰.value⁰;\n//│         match arg$Some$0$\n//│           1 =>\n//│             set tmp = 0;\n//│             break split_root$\n//│           else\n//│             break split_default$\n//│         end\n//│       None⁰ =>\n//│         set tmp = 1;\n//│         break split_root$\n//│       else\n//│         break split_default$\n//│     end\n//│   throw new globalThis⁰.Error⁰(\"match error\")\n//│ tmp\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let arg$Some$0$, tmp;\n//│ match s⁰\n//│   Some⁰ =>\n//│     set arg$Some$0$ = s⁰.value⁰;\n//│     match arg$Some$0$\n//│       1 =>\n//│         begin\n//│           set tmp = 0;\n//│           end;\n//│         tmp\n//│       else\n//│         throw new globalThis⁰.Error⁰(\"match error\")\n//│     end\n//│   None⁰ =>\n//│     set tmp = 1;\n//│     tmp\n//│   else\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:expect 0\nif s is\n  Some then s.value\n//│ = 0\n\n\n:sjs\nx => if x is Some(x) then x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda;\n//│ lambda = (undefined, function (x3) {\n//│   let x4, arg$Some$0$4;\n//│   if (x3 instanceof Some1.class) {\n//│     arg$Some$0$4 = x3.value;\n//│     x4 = arg$Some$0$4;\n//│     return x4\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\ndata class C(a)\n\nfun f(x) = if x is C(a) then a else 0\n\nf(C(27))\n//│ = 27\n\n\nfun f(x) = if x is C then 1 else 0\n\nf(C(27))\n//│ = 1\n\n\nobject M with\n  data class D(a)\n  val d = D(27)\n\nM.d\n//│ = D(27)\n\nfun f(x) = if x is M.D then 1 else 0\n\nM.D.class\n//│ = class D\n\nM is M.D\n//│ = false\n\nf(M.d)\n//│ = 1\n\nf(M.D(27))\n//│ = 1\n\n\nfun f(x) = if x is M.D(a) then a else 0\n\nf(M.d)\n//│ = 27\n\nf(M.D(27))\n//│ = 27\n\n\n// TODO dedup branches duplicated by UCS normalization\n:sjs\nfun f(x) = if x is\n  Some(x) and x > 0 then 42\n  None then \"ok\"\n  else print(\"oops\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f4;\n//│ f4 = function f(x3) {\n//│   let x4, scrut1, arg$Some$0$4;\n//│   if (x3 instanceof Some1.class) {\n//│     arg$Some$0$4 = x3.value;\n//│     x4 = arg$Some$0$4;\n//│     scrut1 = x4 > 0;\n//│     if (scrut1 === true) {\n//│       return 42\n//│     }\n//│     return Predef.print(\"oops\");\n//│   } else if (x3 instanceof None1.class) { return \"ok\" }\n//│   return Predef.print(\"oops\");\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(Some(0))\n//│ > oops\n\nf(Some(1))\n//│ = 42\n\nf(None)\n//│ = \"ok\"\n\nf(0)\n//│ > oops\n\n\ndata class Pair[out A, out B](fst: A, snd: B)\n\n\n:sjs\nfun f(x) = if x is\n  Some(u) then u\n  Pair(a, b) then a + b\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f5;\n//│ f5 = function f(x3) {\n//│   let u, a, b, arg$Pair$0$, arg$Pair$1$, arg$Some$0$4;\n//│   if (x3 instanceof Some1.class) {\n//│     arg$Some$0$4 = x3.value;\n//│     u = arg$Some$0$4;\n//│     return u\n//│   } else if (x3 instanceof Pair1.class) {\n//│     arg$Pair$0$ = x3.fst;\n//│     arg$Pair$1$ = x3.snd;\n//│     b = arg$Pair$1$;\n//│     a = arg$Pair$0$;\n//│     return a + b\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(Some(123))\n//│ = 123\n\nf(Pair(10, 5))\n//│ = 15\n\n\n// UCS term not in tail position\n:sjs\nfun f(x) = print of if x is\n  Some(0) then \"0\"\n  None then \"ok\"\n  else \"oops\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f6;\n//│ f6 = function f(x3) {\n//│   let arg$Some$0$4, tmp9;\n//│   if (x3 instanceof Some1.class) {\n//│     arg$Some$0$4 = x3.value;\n//│     if (arg$Some$0$4 === 0) {\n//│       tmp9 = \"0\";\n//│       return Predef.print(tmp9)\n//│     }\n//│     tmp9 = \"oops\";\n//│     return Predef.print(tmp9);\n//│   } else if (x3 instanceof None1.class) {\n//│     tmp9 = \"ok\";\n//│     return Predef.print(tmp9)\n//│   }\n//│   tmp9 = \"oops\";\n//│   return Predef.print(tmp9);\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(Some(0))\n//│ > 0\n\nf(Some(1))\n//│ > oops\n\nf(None)\n//│ > ok\n\nf(0)\n//│ > oops\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Classes.mls",
    "content": ":js\n\n:global\n:sjs\n\n\ndata class Foo(arguments)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ Foo1 = function Foo(arguments1) {\n//│   return globalThis.Object.freeze(new Foo.class(arguments1));\n//│ };\n//│ (class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   constructor(arguments1) {\n//│     this.arguments = arguments1;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"arguments\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\ndata class Foo(eval)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo3;\n//│ Foo3 = function Foo(eval1) {\n//│   return globalThis.Object.freeze(new Foo.class(eval1));\n//│ };\n//│ (class Foo2 {\n//│   static {\n//│     Foo3.class = this\n//│   }\n//│   constructor(eval1) {\n//│     this.eval = eval1;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"eval\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\ndata class Foo(static)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo5;\n//│ Foo5 = function Foo(static1) {\n//│   return globalThis.Object.freeze(new Foo.class(static1));\n//│ };\n//│ (class Foo4 {\n//│   static {\n//│     Foo5.class = this\n//│   }\n//│   constructor(static1) {\n//│     this.static = static1;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"static\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\ndata class Foo(v')\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo7;\n//│ Foo7 = function Foo(v$_) {\n//│   return globalThis.Object.freeze(new Foo.class(v$_));\n//│ };\n//│ (class Foo6 {\n//│   static {\n//│     Foo7.class = this\n//│   }\n//│   constructor(v$_) {\n//│     this[\"v'\"] = v$_;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"v'\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/CodegenScratch.mls",
    "content": ":js\n\n:global\n:sjs\n:sir\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Comma.mls",
    "content": ":js\n\n:global\n:sjs\n\n\nfun f() =\n  console.log(\"ok\"), 42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f; f = function f() { runtime.safeCall(globalThis.console.log(\"ok\")); return 42 };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun f() = { console.log(\"ok\"), 42 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1; f1 = function f() { runtime.safeCall(globalThis.console.log(\"ok\")); return 42 };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun f() = console.log(\"ok\"), 42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2; f2 = function f() { return runtime.safeCall(globalThis.console.log(\"ok\")) }; 42\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ConfigDirective.mls",
    "content": ":js\n\n\n// Test 1: #config global directive - test_before has tailRecOpt (default)\n:sir\nfun test_before(n, acc) = if n == 0 then acc else test_before(n - 1, n + acc)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let test_before⁰;\n//│ define test_before⁰ as fun test_before¹(n, acc) {\n//│   loop loopLabel:\n//│     let scrut, tmp, tmp1;\n//│     set scrut = Predef⁰.equals⁰(n, 0);\n//│     match scrut\n//│       true =>\n//│         return acc\n//│       else\n//│         set tmp = -⁰(n, 1);\n//│         set tmp1 = +⁰(n, acc);\n//│         set n = tmp;\n//│         set acc = tmp1;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n#config(tailRecOpt: false)\n\n// Test 2: After #config(tailRecOpt: false), functions should NOT be tail-rec optimized\n:sir\nfun test_after(n, acc) = if n == 0 then acc else test_after(n - 1, n + acc)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let test_after⁰;\n//│ define test_after⁰ as fun test_after¹(n, acc) {\n//│   let scrut, tmp, tmp1;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return acc\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       set tmp1 = +⁰(n, acc);\n//│       return test_after¹(tmp, tmp1)\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// Test 3: Re-enable tail recursion optimization\n#config(tailRecOpt: true)\n\n:sir\nfun test_reenabled(n, acc) = if n == 0 then acc else test_reenabled(n - 1, n + acc)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let test_reenabled⁰;\n//│ define test_reenabled⁰ as fun test_reenabled¹(n, acc) {\n//│   loop loopLabel:\n//│     let scrut, tmp, tmp1;\n//│     set scrut = Predef⁰.equals⁰(n, 0);\n//│     match scrut\n//│       true =>\n//│         return acc\n//│       else\n//│         set tmp = -⁰(n, 1);\n//│         set tmp1 = +⁰(n, acc);\n//│         set n = tmp;\n//│         set acc = tmp1;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// Test 4: @config local annotation - disable tailRecOpt for one function only\n:sir\n@config(tailRecOpt: false)\nfun foo(n, acc) = if n == 0 then acc else foo(n - 1, n + acc)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo⁰;\n//│ define foo⁰ as fun foo¹(n, acc) {\n//│   let scrut, tmp, tmp1;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return acc\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       set tmp1 = +⁰(n, acc);\n//│       return foo¹(tmp, tmp1)\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// Test 5: bar (no annotation) should still have tailRecOpt\n:sir\nfun bar(n, acc) = if n == 0 then acc else bar(n - 1, n + acc)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let bar⁰;\n//│ define bar⁰ as fun bar¹(n, acc) {\n//│   loop loopLabel:\n//│     let scrut, tmp, tmp1;\n//│     set scrut = Predef⁰.equals⁰(n, 0);\n//│     match scrut\n//│       true =>\n//│         return acc\n//│       else\n//│         set tmp = -⁰(n, 1);\n//│         set tmp1 = +⁰(n, acc);\n//│         set n = tmp;\n//│         set acc = tmp1;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * Make sure effect handlers with stack safety can be enabled in one go:\n\n// * Here, handlers are not enabled\n:sir\nfun foo(x) = { x.call(), print(42) }\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo²; define foo² as fun foo³(x) { do x.call﹖(); return Predef⁰.print⁰(42) }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n#config(effectHandlers: Some(EffectHandlers()))\nhandle h = Object with {}\nprint(h)\n//│\n//│ > Handler$h$\n\n\n#config(effectHandlers: Some(EffectHandlers(stackSafety: Some(StackSafety(100)))))\n#config(liftDefns: Some(LiftDefns)) // * Needed by effect handlers instrumentation\n\n// * Now, they are\nfun foo(x) = { x.call(), print(42) }\nhandle h = Object with\n  fun call()(resume) = \"Aborted!\"\nfoo(h)\n//│ = \"Aborted!\"\n\n\nprint(42)\n#config(liftDefns: None)\n//│\n//│ > 42\n\n\n#config(deadParamElim: Some(DeadParamElim(debug: true, mono: true)), inlining: None)\n\nprivate fun deadParamConfig(a) = 0\ndeadParamConfig(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun deadParamConfig#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n#config(deadParamElim: None)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n\n\n#config(deforest: Some(Deforest(mono: false)))\n#config(effectHandlers: Some(EffectHandlers(stackSafety: None)))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\ndata class Pair(a, b)\nfun fstConfig(p) = if p is Pair(x, y) then x\nfstConfig(Pair(1, 2))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(a))\n//│ deforest > \tSelect(Ref(p,None),Ident(b))\n//│ deforest > <<< fusing <<<\n//│ = 1\n\n#config(deforest: None)\n\nfun fstConfig(p) = if p is Pair(x, y) then x\nfstConfig(Pair(1, 2))\n//│ = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ConsoleLog.mls",
    "content": ":js\n\n:global\n:sjs\n\n\n:silent\ndeclare val console\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nconsole.log(\"a\")\nconsole.log(\"b\")\n123\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(globalThis.console.log(\"a\")); runtime.safeCall(globalThis.console.log(\"b\")); 123\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > a\n//│ > b\n//│ = 123\n\nlet l = console.log\nl(123)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let l; l = globalThis.console.log; runtime.safeCall(l(123))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 123\n//│ l = fun log\n\n42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 42\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\nconsole.log(\"a\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(globalThis.console.log(\"a\"))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > a\n\n\nlet x =\n  console.log(\"a\")\n  123\nconsole.log(\"b\")\nlet y = x + 1\nconsole.log(\"c\")\ny * 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x, y;\n//│ runtime.safeCall(globalThis.console.log(\"a\"));\n//│ x = 123;\n//│ runtime.safeCall(globalThis.console.log(\"b\"));\n//│ y = x + 1;\n//│ runtime.safeCall(globalThis.console.log(\"c\"));\n//│ y * 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > a\n//│ > b\n//│ > c\n//│ = 248\n//│ x = 123\n//│ y = 124\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/CurriedClasses.mls",
    "content": ":js\n\n\n// * The code-gen of curried classes is currently a bit crazy and unnecessary.\n// * It was intended to make interop better, but it turned out to be a surprising semantic footgun,\n// * as partially-applied class constructors will share the same \"this\" object, resulting in unexpected mutations!\n// * TODO: Compile differently and forbid the use of curried classes as first-class values.\n\n\n:sjs\nclass A(val x)(val y)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let A1;\n//│ A1 = function A(x) {\n//│   return (y) => {\n//│     return globalThis.Object.freeze(new A.class(x)(y));\n//│   }\n//│ };\n//│ (class A {\n//│   static {\n//│     A1.class = this\n//│   }\n//│   constructor(x) {\n//│     return (y) => {\n//│       this.x = x;\n//│       this.y = y;\n//│       return this;\n//│     }\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"A\", [\"x\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nlet w = new A(1)\n//│ w = fun w\n\nlet h = w(2)\nh.y\n//│ = 2\n//│ h = A(1)\n\n:expect 3\nlet h2 = w(3)\nh2.y\n//│ = 3\n//│ h2 = A(1)\n\n// * This used to return 3, but we now make sure instantiations are always saturated\n:expect 2\nh.y\n//│ = 2\n\n\n// * First-class class value; FIXME: should be forbidden\nlet a = A.class\n//│ a = class A\n\n// * Dynamic instantiation\nlet w = new! a(1)\n//│ w = fun\n\nlet h = w(2)\nh.y\n//│ = 2\n//│ h = A(1)\n\n:expect 3\nlet h2 = w(3)\nh2.y\n//│ = 3\n//│ h2 = A(1)\n\n:re // * Bad bad bad!\n:expect 2\nh.y\n//│ ═══[RUNTIME ERROR] Expected: '2', got: '3'\n//│ = 3\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/CurriedFunctions.mls",
    "content": ":js\n\n\n:soir\nfun foo(x)(y) = z => x + y + z\nfoo(1)(2)(3)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let foo⁰, baseCall;\n//│ define foo⁰ as fun foo¹(x)(y) {\n//│   let lambda;\n//│   define lambda as fun lambda⁰(z) {\n//│     let tmp;\n//│     set tmp = +⁰(x, y);\n//│     return +⁰(tmp, z)\n//│   };\n//│   return lambda⁰\n//│ };\n//│ set baseCall = foo¹(1)(2);\n//│ baseCall(3)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 6\n\n:sir\n:soir\n:lift\nfun foo(x)(y) = z => x + y + z\nfoo(1)(2)(3)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo², baseCall, lambda¹, lambda$⁰;\n//│ define lambda$⁰ as fun lambda$¹(x, y)(z) {\n//│   return lambda²(x, y, z)\n//│ };\n//│ define lambda¹ as fun lambda²(x, y, z) {\n//│   let tmp;\n//│   set tmp = +⁰(x, y);\n//│   return +⁰(tmp, z)\n//│ };\n//│ define foo² as fun foo³(x)(y) {\n//│   let lambda$here;\n//│   set lambda$here = lambda$¹(x, y);\n//│   return lambda$here\n//│ };\n//│ set baseCall = foo³(1)(2);\n//│ baseCall(3)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let foo², baseCall, lambda¹, lambda$⁰;\n//│ define lambda$⁰ as fun lambda$¹(x, y)(z) {\n//│   let x1, y1, z1, inlinedVal, tmp;\n//│   set x1 = x;\n//│   set y1 = y;\n//│   set z1 = z;\n//│   set tmp = +⁰(x1, y1);\n//│   set inlinedVal = +⁰(tmp, z1);\n//│   return inlinedVal\n//│ };\n//│ define foo² as fun foo³(x)(y) {\n//│   let lambda$here;\n//│   set lambda$here = lambda$¹(x, y);\n//│   return lambda$here\n//│ };\n//│ set baseCall = foo³(1)(2);\n//│ baseCall(3)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 6\n\n\nfun loudly(x) =\n  print(\"hi\", x)\n  x\n\nfun foo(x)(y) =\n  print(\"hello\")\n  z =>\n    print(\"world\")\n    a => print(x, y, z, a)\n\n// * Notice that the side effects should happen in the correct order\n:sir\nfoo(loudly(1))(loudly(2))(loudly(3))(loudly(4))\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let tmp, tmp1, baseCall, tmp2, callPrefix, tmp3;\n//│ set tmp = loudly⁰(1);\n//│ set tmp1 = loudly⁰(2);\n//│ set baseCall = foo⁴(tmp)(tmp1);\n//│ set tmp2 = loudly⁰(3);\n//│ set callPrefix = baseCall(tmp2);\n//│ set tmp3 = loudly⁰(4);\n//│ callPrefix(tmp3)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > hi 1\n//│ > hi 2\n//│ > hello\n//│ > hi 3\n//│ > world\n//│ > hi 4\n//│ > 1 2 3 4\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/DelayedLetInit.mls",
    "content": ":js\n\n:global\n:ssjs\n\n\nlet x\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let x;\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ x = undefined\n\nprint(x)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res2 = runtime.checkCall(Predef.print(x)); undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > undefined\n\nx = 1\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ x = 1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nx\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res4 = x; undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// TODO forbid redefining a let\nx = 2\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ x = 2;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nx\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res6 = x; undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\nlet y = 1\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let y;\n//│ y = 1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ y = 1\n\n:e\nz = 1\n//│ ╔══[COMPILATION ERROR] Name not found: z\n//│ ║  l.52: \tz = 1\n//│ ╙──      \t^\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ throw \"This code cannot be run as its compilation yielded an error.\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nfun f() = 1\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f;\n//│ f = function f() {\n//│   runtime.checkArgs(\"f\", 0, true, arguments.length);\n//│   return 1\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res10 = f; undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun f\n\n\nlet f\nf(x) = x + 1\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f1, f2;\n//│ f2 = function f(x1) {\n//│   runtime.checkArgs(\"f\", 1, true, arguments.length);\n//│   return x1 + 1\n//│ };\n//│ f1 = f2;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\nf(1)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res12 = runtime.safeCall(f1(1)); undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\nlet foo\nfoo = 0\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let foo;\n//│ foo = 0;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = 0\n\n:fixme\nlet foo\nif true\nthen foo = 0\nelse foo = 1\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' keyword instead\n//│ ║  l.108: \tthen foo = 0\n//│ ╙──       \t         ^\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let foo1, scrut;\n//│ scrut = true;\n//│ if (scrut === true) {\n//│   block$res14 = undefined;\n//│   undefined\n//│ } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = undefined\n\nlet foo\nif true\nthen\n  foo = 0\nelse\n  foo = 1\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let foo2, scrut1;\n//│ scrut1 = true;\n//│ if (scrut1 === true) {\n//│   foo2 = 0;\n//│   block$res15 = runtime.Unit;\n//│   undefined\n//│ } else { foo2 = 1; block$res15 = runtime.Unit; undefined }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = 0\n\n\nfun f() =\n  foo = 42\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f3;\n//│ f3 = function f() {\n//│   runtime.checkArgs(\"f\", 0, true, arguments.length);\n//│   foo2 = 42;\n//│   return runtime.Unit\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf()\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res17 = runtime.checkCall(f3()); undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfoo\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res18 = foo2; undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n:fixme\nfun f() = foo = 0\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' keyword instead\n//│ ║  l.165: \tfun f() = foo = 0\n//│ ╙──       \t              ^\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f4;\n//│ f4 = function f() {\n//│   runtime.checkArgs(\"f\", 0, true, arguments.length);\n//│   return foo2\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Do.mls",
    "content": ":js\n\n\n:elt\ndo ()\n//│ —————————————| Elaborated tree |————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Blk:\n//│     stats = Ls of \n//│       UnitVal\n//│     res = UnitVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ndo console.log(\"ok\")\n//│ > ok\n\n:w\ndo 1\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.18: \tdo 1\n//│ ╙──      \t   ^\n\ndo\n  let hello = 1\n  ()\n\n:re\nprint(globalThis.hello)\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'hello' yielded 'undefined'\n\n:ucs desugared\nval f = case\n  0 then \"null\"\n  do console.log(\"non-null\")\n  1 then \"unit\"\n  let res = \"other\"\n  do print(res)\n  _ then res\n//│ Split with nested patterns:\n//│ >  case\n//│ >    caseScrut is 0 then \"null\"\n//│ >    let tmp:unused = member:console⁰.log‹member:log›(\"non-null\")\n//│ >    caseScrut is 1 then \"unit\"\n//│ >    let res = \"other\"\n//│ >    let tmp:unused = (member:Predef⁰.)print‹member:print›(res⁰)\n//│ >    caseScrut is _ then res⁰\n//│ Expanded split with flattened patterns:\n//│ >  ‹if|while›\n//│ >    caseScrut is 0 then \"null\"\n//│ >    let tmp:unused = member:console⁰.log‹member:log›(\"non-null\")\n//│ >    caseScrut is 1 then \"unit\"\n//│ >    let res = \"other\"\n//│ >    let tmp:unused = (member:Predef⁰.)print‹member:print›(res⁰)\n//│ >    else res⁰\n//│ f = fun\n\nf(0)\n//│ = \"null\"\n\nf(1)\n//│ > non-null\n//│ = \"unit\"\n\nf(2)\n//│ > non-null\n//│ > other\n//│ = \"other\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/EarlyReturn.mls",
    "content": ":js\n\n\nfun f() =\n  print(\"--- pre ---\")\n  return 1\n  print(\"--- post ---\")\n  \n\nf()\n//│ > --- pre ---\n//│ = 1\n\n:sjs\nfun f(x) =\n  if x < 0 do\n    print(\"whoops\")\n    return 0\n  x + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1;\n//│ f1 = function f(x) {\n//│   let scrut;\n//│   scrut = x < 0;\n//│   if (scrut === true) { Predef.print(\"whoops\"); return 0 }\n//│   return x + 1;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(1)\n//│ = 2\n\nf(-1)\n//│ > whoops\n//│ = 0\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ElseLess.mls",
    "content": ":js\n\n\ndata class Foo(a)\n\n\n:todo // Treat else-less single-branch UCS as implicitly returning () in default case\nif Foo(0) is\n  Foo(x) and x > 0 then\n    print(\"ok\")\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\nlet x = 1\n//│ x = 1\n\n:todo\nif x > 0 and x < 0 then print(\"wat\")\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/FieldSymbols.mls",
    "content": ":js\n\n\ndata class Foo(val x) with\n  val y = x\n\n\n// TODO add symbol to this Sel\n:elt\nFoo(42).x\n//│ —————————————| Elaborated tree |————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Sel:\n//│     prefix = App:\n//│       lhs = Ref{sym=member:Foo⁰} of member:Foo⁰\n//│       rhs = Tup of Ls of \n//│         Fld:\n//│           term = Lit of IntLit of 42\n//│     nme = Ident of \"x\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\nlet foo = Foo(42)\n//│ foo = Foo(42)\n\n// TODO add symbol to this Sel\n:elt\nfoo.x\n//│ —————————————| Elaborated tree |————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Sel:\n//│     prefix = Ref{sym=foo⁰} of foo⁰\n//│     nme = Ident of \"x\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n// TODO add symbol to this Sel\n:elt\nfoo.y\n//│ —————————————| Elaborated tree |————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Sel:\n//│     prefix = Ref{sym=foo⁰} of foo⁰\n//│     nme = Ident of \"y\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n// * Notice that the `.x` selection has a symbol, propagated to the lowered tree, as expected\n:elt\n:sir\ncase\n  Foo(a) then a\n//│ —————————————| Elaborated tree |————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Lam:\n//│     params = ParamList:\n//│       params = Ls of \n//│         Param:\n//│           sym = caseScrut⁰\n//│           modulefulness = Modulefulness of N\n//│     body = IfLike:\n//│       kw = keyword 'case'\n//│       form = ReturningIf\n//│       split = Cons:\n//│         branch = Match:\n//│           scrutinee = Ref{sym=caseScrut⁰} of caseScrut⁰\n//│           pattern = Constructor:\n//│             target = Ref{sym=member:Foo⁰} of member:Foo⁰\n//│             arguments = S of Ls of \n//│               Alias:\n//│                 pattern = Wildcard\n//│                 id = Ident of \"a\"\n//│           consequent = Else of Ref{sym=a⁰} of a⁰\n//│         tail = End\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda⁰;\n//│ define lambda⁰ as fun lambda¹(caseScrut) {\n//│   let a, arg$Foo$0$;\n//│   match caseScrut\n//│     Foo¹ =>\n//│       set arg$Foo$0$ = caseScrut.x⁰;\n//│       set a = arg$Foo$0$;\n//│       return a\n//│     else\n//│       throw new globalThis⁰.Error⁰(\"match error\")\n//│   end\n//│ };\n//│ lambda¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n// TODO support:\n// data class Foo(x)\n\n// Foo(123).0\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/FirstClassFunctionTransform.mls",
    "content": ":js\n:ftc\n\n\n:sir\nfun aux(f) = f(1) + f(10)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let aux⁰;\n//│ define aux⁰ as fun aux¹(f) {\n//│   let tmp, tmp1;\n//│   set tmp = f.call﹖(1);\n//│   set tmp1 = f.call﹖(10);\n//│   return +⁰(tmp, tmp1)\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sir\nx => x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda⁰, Function$⁰, tmp;\n//│ define lambda⁰ as fun lambda¹(x) {\n//│   return x\n//│ };\n//│ define Function$⁰ as class Function$¹ {\n//│   method call⁰ = fun call¹(x) { return lambda¹(x) }\n//│ };\n//│ set tmp = new Function$¹();\n//│ tmp\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class anonymous\n\n:fixme // TODO: fix IR rebinding issue (each symbol should be bound at most once)\n:checkIR\n:noInline\nx => x\n//│ ╔══[INTERNAL ERROR] [BlockChecker] Invalid IR: symbol x⁰ is bound more than once\n//│ ║  l.37: \tx => x\n//│ ╙──      \t^\n//│ = class anonymous\n\n\nfun f(x, y, b) =\n  aux(z => x + z) * aux(z => if b then y + z else y - z)\n\n:expect 121\nf(0, 0, true)\n//│ = 121\n\n\n:sir\n(x => x)(42)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda²; define lambda² as fun lambda³(x) { return x }; lambda³(42)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\nlet x = 1 in (y => x + y)(0)\n//│ = 1\n\n\n:sir\nfun foo(x) = x + 1\nfun bar(f) = f(0)\nbar(foo)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let bar⁰, foo⁰, Function$², tmp;\n//│ define foo⁰ as fun foo¹(x) {\n//│   return +⁰(x, 1)\n//│ };\n//│ define bar⁰ as fun bar¹(f) {\n//│   return f.call﹖(0)\n//│ };\n//│ define Function$² as class Function$³ {\n//│   method call² = fun call³(x) { return foo¹(x) }\n//│ };\n//│ set tmp = new Function$³();\n//│ bar¹(tmp)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:expect 1\nbar(foo)\n//│ = 1\n\n\nfun foo(x) = x + 1\nfun bar(f) = f(0)\nlet f = foo in bar(f)\n//│ = 1\n\n\n:ge\nbar([foo].0)\nbar([foo, x => x].1)\n//│ ╔══[COMPILATION ERROR] Cannot determine if 0 is a function.\n//│ ║  l.96: \tbar([foo].0)\n//│ ╙──      \t         ^^\n//│ ═══[COMPILATION ERROR] Cannot determine if 0$__checkNotMethod is a function.\n//│ ═══[COMPILATION ERROR] Cannot determine if Error is a function.\n//│ ╔══[COMPILATION ERROR] Cannot determine if 1 is a function.\n//│ ║  l.97: \tbar([foo, x => x].1)\n//│ ╙──      \t                 ^^\n//│ ═══[COMPILATION ERROR] Cannot determine if 1$__checkNotMethod is a function.\n//│ ═══[COMPILATION ERROR] Cannot determine if Error is a function.\n//│ = 0\n\n\nlet i = 1\nbar([foo, x => x].(i))\n//│ = 0\n//│ i = 1\n\n\n// We have to reject this form, since in the following test case, the process is undecidable\n:ge\n[foo, x => x].(i)(0)\n//│ ╔══[COMPILATION ERROR] Cannot determine if the dynamic selection is a function object.\n//│ ║  l.119: \t[foo, x => x].(i)(0)\n//│ ╙──       \t               ^\n\n\nclass Foo() with\n  val f = x => x\n  val g = x => x + 1\n  fun h(x) = x - 1\n\n:ge\nlet foo = Foo()\nfoo.(\"f\")(0)\nfoo.(\"h\")(1)\n//│ ╔══[COMPILATION ERROR] Cannot determine if the dynamic selection is a function object.\n//│ ║  l.132: \tfoo.(\"f\")(0)\n//│ ╙──       \t^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Cannot determine if the dynamic selection is a function object.\n//│ ║  l.133: \tfoo.(\"h\")(1)\n//│ ╙──       \t^^^^^^^^\n//│ = 0\n//│ foo = Foo()\n\n\nclass Foo(x) with\n  fun foo(f) = f(x)\n\n\n:expect 0\n:sir\nFoo(1).foo(x => x - 1)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let tmp, lambda⁴, Function$⁴, tmp1;\n//│ set tmp = Foo⁰(1);\n//│ define lambda⁴ as fun lambda⁵(x) {\n//│   return -⁰(x, 1)\n//│ };\n//│ define Function$⁴ as class Function$⁵ {\n//│   method call⁴ = fun call⁵(x) { return lambda⁵(x) }\n//│ };\n//│ set tmp1 = new Function$⁵();\n//│ tmp.foo²(tmp1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:expect 1\n:sir\nfun foo() = x => x\nfoo()(1)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo³, baseCall, lambda⁶, Function$⁶;\n//│ define lambda⁶ as fun lambda⁷(x) {\n//│   return x\n//│ };\n//│ define Function$⁶ as class Function$⁷ {\n//│   method call⁶ = fun call⁷(x) {\n//│     return lambda⁷(x)\n//│   }\n//│ };\n//│ define foo³ as fun foo⁴() {\n//│   let tmp;\n//│   set tmp = new Function$⁷();\n//│   return tmp\n//│ };\n//│ set baseCall = foo⁴();\n//│ baseCall.call﹖(1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\nclass Bar() with\n  fun bar() = x => x \n\n\n:expect 42\nBar().bar()(42)\n//│ = 42\n\n\nclass Baz(b) with\n  fun baz() = x => x + b\n\n\n:expect 42\nBaz(42).baz()(0)\n//│ = 42\n\n\nmodule Foo with\n  fun aux(f) = f(1) + f(10)\n  fun f(x, y, b) =\n    aux(z => x + z) * aux(z => if b then y + z else y - z)\n\n\n:expect 121\nFoo.f(0, 0, true)\n//│ = 121\n\n\n:sir\nmodule Foo with\n  class Bar(y) with\n    fun bar(z) = x => x + y + z \n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let Foo¹, lambda⁸, Function$⁸;\n//│ define lambda⁸ as fun lambda⁹(y, z, x) {\n//│   let tmp;\n//│   set tmp = +⁰(x, y);\n//│   return +⁰(tmp, z)\n//│ };\n//│ define Function$⁸ as class Function$⁹ {\n//│   private val y⁰;\n//│   private val z⁰;\n//│   constructor(y, z) {\n//│     super⁰();\n//│     set y⁰ = y;\n//│     set z⁰ = z;\n//│     end\n//│   }\n//│   method call⁸ = fun call⁹(x) {\n//│     return lambda⁹(y⁰, z⁰, x)\n//│   }\n//│ };\n//│ define Foo¹ as class Foo²\n//│ module Foo³ {\n//│   constructor {\n//│     define Bar⁰ as class Bar²(y) {\n//│       private val y¹;\n//│       constructor Bar¹ {\n//│         set y¹ = y;\n//│         end\n//│       }\n//│       method bar² = fun bar³(z) {\n//│         let tmp;\n//│         set tmp = new Function$⁹(y¹, z);\n//│         return tmp\n//│       }\n//│     };\n//│     end\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:expect 3\nFoo.Bar(1).bar(1)(1)\n//│ = 3\n\n\nlet x = 1\n//│ x = 1\n\n\n:sir\ny => x + y\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lambda¹⁰, Function$¹⁰, tmp;\n//│ define lambda¹⁰ as fun lambda¹¹(y) {\n//│   return +⁰(x¹, y)\n//│ };\n//│ define Function$¹⁰ as class Function$¹¹ {\n//│   method call¹⁰ = fun call¹¹(y) { return lambda¹¹(y) }\n//│ };\n//│ set tmp = new Function$¹¹();\n//│ tmp\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class anonymous\n\n\n:expect 2\n(y => x + y)(1)\n//│ = 2\n\n\nfun foo(x) = x + 1\nfun bar(x) = foo(x) + 1\n\n\nclass A(val x)\n\n\nA(42)\n//│ = A(42)\n\n\nA(x => x).x(1)\n//│ = 1\n\n\nfun foo(x) = x + 1\nfun bar(x) = foo(x) + 1\nA(foo).x(0)\n//│ = 1\n\n\nmodule Foo with\n  fun foo(x) = x + 1\n\nfun foo(f) = f(0)\n\n\n:expect 1\nfoo(Foo.foo)\n//│ = 1\n\n\nmodule Foo with\n  module Bar1 with\n    fun bar(x) = x + 1\n  module Bar2 with\n    fun bar(x) = x - 1 \nfun foo(f) = f(0)\n\n\nfoo(Foo.Bar1.bar)\n//│ = 1\n\n\nfoo(Foo.Bar2.bar)\n//│ = -1\n\n\nmodule Foo with\n  val x = 1\n  fun bar() = 0\n\n\nfun foo(y) = y + 1\n\nfoo(Foo.x)\n//│ = 2\n\n\nclass Foo(val x) with\n  fun f(y) = y + 1\n\n\nFoo(0).f(1)\n//│ = 2\n\nFoo(0).x\n//│ = 0\n\nFoo(x => x).x(1)\n//│ = 1\n\n\nlet foo = Foo(1)\nfoo.Foo#x\n//│ = 1\n//│ foo = Foo(1)\n\n:ge\nfoo.f(0)\n//│ ╔══[COMPILATION ERROR] Cannot determine if f is a function object.\n//│ ║  l.375: \tfoo.f(0)\n//│ ╙──       \t^^^^^\n//│ = 1\n\nfoo.Foo#f(0)\n//│ = 1\n\nlet foo = Foo(x => x + 1)\n//│ foo = Foo(class anonymous)\n\n\nfoo.Foo#f(0)\n//│ = 1\n\n\n:ge\nfoo.x(0)\n//│ ╔══[COMPILATION ERROR] Cannot determine if x is a function object.\n//│ ║  l.393: \tfoo.x(0)\n//│ ╙──       \t^^^^^\n\n\nfoo.Foo#x(0)\n//│ = 1\n\n\nclass Bar() with\n  val x = 0\n  val bar = x => x + 1\n\n\nBar().bar(1)\n//│ = 2\n\nBar().x\n//│ = 0\n\nlet bar = Bar()\nbar.Bar#bar(1)\n//│ = 2\n//│ bar = Bar()\n\nbar.Bar#x\n//│ = 0\n\nlet bar = Bar().bar in bar(1)\n//│ = 2\n\n\nmodule Foo with\n  val f = x => x\n\n\nFoo.f(1)\n//│ = 1\n\nmodule Bar with\n  fun h(x) = x + 1\n  fun w(y) = y(0)\n  fun f(x) = w(h) + x\n\nBar.f(0)\n//│ = 1\n\nmodule Foo with\n  fun f(x) = x + 1\n  module Bar with\n    fun g1(h) = h(0)\n    fun g2(x) = g1(Foo.f) + x\n\n\nFoo.Bar.g2(1)\n//│ = 2\n\n\nlet f = x => y => x + y\n//│ f = class anonymous\n\n:expect 3\nf(1)(2)\n//│ = 3\n\n\n:sir\nfun foo(x)(y) = x + y\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo⁵, lambda$⁰, Function$¹²;\n//│ define lambda$⁰ as fun lambda$¹(x, y) {\n//│   return +⁰(x, y)\n//│ };\n//│ define Function$¹² as class Function$¹³ {\n//│   private val x²;\n//│   constructor(x) {\n//│     super⁰();\n//│     set x² = x;\n//│     end\n//│   }\n//│   method call¹² = fun call¹³(y) {\n//│     return lambda$¹(x², y)\n//│   }\n//│ };\n//│ define foo⁵ as fun foo⁶(x) { let tmp; set tmp = new Function$¹³(x); return tmp };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:expect 1\nlet bar = foo(1) in bar(0)\n//│ = 1\n\nfun foo(x)(y)(z) = x + y + z\n\n\n:expect 2\nlet bar = foo(1) in let baz = bar(0) in baz(1)\n//│ = 2\n\n\nfun foo(x) =\n  fun bar(y) =\n    x + y\n  bar(x * 2)\nfoo(1)\n//│ = 3\n\n\nfun foo(f) = f(\"abc\")\n\n// FIXME: should output \"abc\"\nfoo(print)\n//│ > \n\n:fixme\n:sir\n:expect [\"abc\"]\nfoo(tuple)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let Function$¹⁴, tmp;\n//│ define Function$¹⁴ as class Function$¹⁵ {\n//│   method call¹⁴ = fun call¹⁵(...xs) {\n//│     return Predef⁰.tuple⁰()\n//│   }\n//│ };\n//│ set tmp = new Function$¹⁵();\n//│ foo⁷(tmp)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Expected: '[\"abc\"]', got: '[]'\n//│ = []\n\n\nif true is true then print(\"true\")\n//│ > true\n\n\nif 0 is\n  Bool then 1\n  Str then 1\n  0 then 0\n  else 2\n  \n//│ = 0\n\nclass Foo(val x)\n\n\nif Foo(1) is\n  Foo(x) then x\n  else 0\n//│ = 1\n\n\nif [1, 2, 3] is\n  [x, y] then x + y\n  [x, y, z] then x + y + z\n  [x, ...y] then x\n  else 0\n//│ = 6\n\n\nclass Foo(val x)\n\nlet foo = Foo(1) in foo.Foo#x\n//│ = 1\n\nlet foo = new Foo(1) in foo.Foo#x\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Formatting.mls",
    "content": ":js\n:sjs\n\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ import Predef from \"./../../mlscript-compile/Predef.mjs\"; \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nlet discard = drop _\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let discard, discard1; discard1 = function discard(_0) { return runtime.Unit }; discard = discard1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ discard = fun discard\n\n\n// * Same code, but the latter occurrence is broken because of the slightly wider gensym'd idents\n\ndiscard of { a: 0, b: 11111 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let a, b, tmp;\n//│ a = 0;\n//│ b = 11111;\n//│ tmp = globalThis.Object.freeze({ a: a, b: b });\n//│ runtime.safeCall(discard(tmp))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ndiscard of { a: 0, b: 11111 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let a1, b1, tmp1;\n//│ a1 = 0;\n//│ b1 = 11111;\n//│ tmp1 = globalThis.Object.freeze({ a: a1, b: b1 });\n//│ runtime.safeCall(discard(tmp1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\ndiscard of { aaaa: 1 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let aaaa, tmp2;\n//│ aaaa = 1;\n//│ tmp2 = globalThis.Object.freeze({ aaaa: aaaa });\n//│ runtime.safeCall(discard(tmp2))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ndiscard of { aaaaaaaaa: 1, bbbb: 2 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let aaaaaaaaa, bbbb, tmp3;\n//│ aaaaaaaaa = 1;\n//│ bbbb = 2;\n//│ tmp3 = globalThis.Object.freeze({\n//│   aaaaaaaaa: aaaaaaaaa,\n//│   bbbb: bbbb\n//│ });\n//│ runtime.safeCall(discard(tmp3))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ndiscard of { aaaaaaaaa: 1, bbbbbbbb: 2, ccccccccc: 3, dddddddddd: 4 }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let aaaaaaaaa1, bbbbbbbb, ccccccccc, dddddddddd, tmp4;\n//│ aaaaaaaaa1 = 1;\n//│ bbbbbbbb = 2;\n//│ ccccccccc = 3;\n//│ dddddddddd = 4;\n//│ tmp4 = globalThis.Object.freeze({\n//│   aaaaaaaaa: aaaaaaaaa1,\n//│   bbbbbbbb: bbbbbbbb,\n//│   ccccccccc: ccccccccc,\n//│   dddddddddd: dddddddddd\n//│ });\n//│ runtime.safeCall(discard(tmp4))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\ndiscard of [ \"aaaaaaaaaaaaaaa\", \"bbbbbbbbbbbbbbbb\" ]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp5;\n//│ tmp5 = globalThis.Object.freeze([\n//│   \"aaaaaaaaaaaaaaa\",\n//│   \"bbbbbbbbbbbbbbbb\"\n//│ ]);\n//│ runtime.safeCall(discard(tmp5))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ndiscard of [ \"aaaaaaaaaaaaaaa\", \"bbbbbbbbbbbbbbbb\", \"ccccccccccccccccc\", \"dddddddddddddddddd\" ]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp6;\n//│ tmp6 = globalThis.Object.freeze([\n//│   \"aaaaaaaaaaaaaaa\",\n//│   \"bbbbbbbbbbbbbbbb\",\n//│   \"ccccccccccccccccc\",\n//│   \"dddddddddddddddddd\"\n//│ ]);\n//│ runtime.safeCall(discard(tmp6))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ndiscard of [[ \"aaaaaaaaaaaaaaa\", \"bbbbbbbbbbbbbbbb\", \"ccccccccccccccccc\", \"dddddddddddddddddd\" ]]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp7, tmp8;\n//│ tmp7 = globalThis.Object.freeze([\n//│   \"aaaaaaaaaaaaaaa\",\n//│   \"bbbbbbbbbbbbbbbb\",\n//│   \"ccccccccccccccccc\",\n//│   \"dddddddddddddddddd\"\n//│ ]);\n//│ tmp8 = globalThis.Object.freeze([ tmp7 ]);\n//│ runtime.safeCall(discard(tmp8))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/FunInClass.mls",
    "content": ":js\n\n\nfun test() =\n  data class C(a) with { fun f() = a }\n  C(0).f()\n\ntest()\n//│ = 0\n\n\n:sjs\nfun test(a) =\n  data class Inner(b) with\n    print(a)\n    fun f(c) = [a, b, c]\n    fun g(d) =\n      fun h(e) = [a, b, d, e]\n      h(d)\n  Inner(42)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test1;\n//│ test1 = function test(a) {\n//│   let Inner1;\n//│   Inner1 = function Inner(b) {\n//│     return globalThis.Object.freeze(new Inner.class(b));\n//│   };\n//│   (class Inner {\n//│     static {\n//│       Inner1.class = this\n//│     }\n//│     constructor(b) {\n//│       this.b = b;\n//│       Predef.print(a);\n//│     }\n//│     f(c) {\n//│       return globalThis.Object.freeze([\n//│         a,\n//│         this.b,\n//│         c\n//│       ])\n//│     } \n//│     g(d) {\n//│       let e, inlinedVal;\n//│       e = d;\n//│       inlinedVal = globalThis.Object.freeze([\n//│         a,\n//│         this.b,\n//│         d,\n//│         e\n//│       ]);\n//│       return inlinedVal\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"class\", \"Inner\", [\"b\"]]; \n//│   });\n//│   return Inner1(42)\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet i = test(100)\n//│ > 100\n//│ i = Inner(42)\n\ni.f(200)\n//│ = [100, 42, 200]\n\ni.g(200)\n//│ = [100, 42, 200, 200]\n\n\n:sjs\nfun test(a) =\n  data class C1(b) with\n    print of [a, b]\n  data class C2(b) with\n    print of [a, b]\n  [C1(1), C2(2)]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test2;\n//│ test2 = function test(a) {\n//│   let C11, C21, tmp, tmp1;\n//│   C11 = function C1(b) {\n//│     return globalThis.Object.freeze(new C1.class(b));\n//│   };\n//│   (class C1 {\n//│     static {\n//│       C11.class = this\n//│     }\n//│     constructor(b) {\n//│       let tmp2;\n//│       this.b = b;\n//│       tmp2 = globalThis.Object.freeze([\n//│         a,\n//│         this.b\n//│       ]);\n//│       Predef.print(tmp2);\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"class\", \"C1\", [\"b\"]]; \n//│   });\n//│   C21 = function C2(b) {\n//│     return globalThis.Object.freeze(new C2.class(b));\n//│   };\n//│   (class C2 {\n//│     static {\n//│       C21.class = this\n//│     }\n//│     constructor(b) {\n//│       let tmp2;\n//│       this.b = b;\n//│       tmp2 = globalThis.Object.freeze([\n//│         a,\n//│         this.b\n//│       ]);\n//│       Predef.print(tmp2);\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"class\", \"C2\", [\"b\"]]; \n//│   });\n//│   tmp = C11(1);\n//│   tmp1 = C21(2);\n//│   return globalThis.Object.freeze([ tmp, tmp1 ])\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ntest(123)\n//│ > [123, 1]\n//│ > [123, 2]\n//│ = [C1(1), C2(2)]\n\n\n// Inlining is disabled to test this proxy\n:sjs\n:noInline\ndata class Foo(a) with\n  fun foo() =\n    fun bar() = a\n    fun baz() = a\n    bar()\n    baz()\n  foo()\nFoo(123)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ Foo1 = function Foo(a) {\n//│   return globalThis.Object.freeze(new Foo.class(a));\n//│ };\n//│ (class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   constructor(a) {\n//│     this.a = a;\n//│     this.foo();\n//│   }\n//│   foo() {\n//│     let bar, baz;\n//│     const this$Foo = this;\n//│     bar = function bar() {\n//│       return this$Foo.a\n//│     };\n//│     baz = function baz() {\n//│       return this$Foo.a\n//│     };\n//│     bar();\n//│     return baz()\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"a\"]]; \n//│ });\n//│ Foo1(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo(123)\n\n:sjs\ndata class Bar(x) with\n  fun foo()() =\n    fun bar() =\n      x\n    bar()\n  foo()()\nBar(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Bar1;\n//│ Bar1 = function Bar(x) {\n//│   return globalThis.Object.freeze(new Bar.class(x));\n//│ };\n//│ (class Bar {\n//│   static {\n//│     Bar1.class = this\n//│   }\n//│   constructor(x) {\n//│     this.x = x;\n//│     this.foo()();\n//│   }\n//│   foo() {\n//│     return () => {\n//│       let inlinedVal;\n//│       inlinedVal = this.x;\n//│       return inlinedVal\n//│     }\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Bar\", [\"x\"]]; \n//│ });\n//│ Bar1(1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Bar(1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Functions.mls",
    "content": ":js\n\n\nfun foo() =\n  1 + 2\n\nfoo\n//│ = fun foo\n\nfoo()\n//│ = 3\n\nfun foo(x) =\n  x + 1\n\nfoo(123)\n//│ = 124\n\nfun foo(x) =\n  x + 1 + 2\n\nfoo(123)\n//│ = 126\n\nfun foo() = bar()\nfun bar() = 42\n\nbar()\n//│ = 42\n\nfoo()\n//│ = 42\n\nfun foo() = bar()\nlet r = foo()\nfun bar() = 42\nr\n//│ = 42\n//│ r = 42\n\n// * This fails to properly initialize, as expected\n:re\n:noInline\nfun foo() = bar()\nlet r = foo()\nfun bar() = r\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n//│ r = undefined\n\n// * Similar\n:re\nobject Outer with\n  fun foo() = bar()\n  val r = foo()\n  fun bar() = r\nOuter.r\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n\n\nfun outerfun(x) =\n  let r = x + 1\n  fun nested(y) =\n    r + x + y\n  print(nested(x))\n  nested\n\nlet f = outerfun(100)\nf(200)\n//│ > 301\n//│ = 401\n//│ f = fun nested\n\n// f(200)\n\nouterfun(100)\n//│ > 301\n//│ = fun nested\n\nouterfun(100)(200)\n//│ > 301\n//│ = 401\n\n\n// * Notice this strange JS phenomenon:\n// * functions leak from the `try` scope, although things like classes do not...\n\n:showRepl\nfun test1(x) = test2(x)\nfun test2(y) = y + 1\n//│ REPL> Sending: block$res18 = undefined\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Sending: let test2, test1;try { test1 = function test1(x) {   runtime.checkArgs(\"test1\", 1, true, arguments.length);   let y, inlinedVal;   y = x;   inlinedVal = y + 1;   return inlinedVal }; test2 = function test2(y) {   runtime.checkArgs(\"test2\", 1, true, arguments.length);   return y + 1 };; undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  undefined\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(block$res18)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  undefined\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  undefined\n//│ >  undefined\n\ntest1(1)\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/FunctionsThis.mls",
    "content": ":js\n\n\n:sjs\nval x = 2\nfun foo() =\n  x + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo, x; foo = function foo() { return x + 1 }; x = 2;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ x = 2\n\n:sjs\nclass Test with\n  print(foo())\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Test1;\n//│ (class Test {\n//│   static {\n//│     Test1 = this\n//│   }\n//│   constructor() {\n//│     let tmp;\n//│     tmp = foo();\n//│     Predef.print(tmp);\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Test\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nnew Test\n//│ > 3\n//│ = Test\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/FunnyOpen.mls",
    "content": ":js\n\n\nmodule Mod with\n  fun printt(x) = console.log(x)\n  fun (|>>) pipee(x, f) = f(x)\n\n:ctx\nopen Mod\n//│ Env:\n//│   pipee -> SelElem(RefElem(member:Mod),pipee,Some(member:pipee),true)\n//│   printt -> SelElem(RefElem(member:Mod),printt,Some(member:printt),true)\n//│   |>> -> SelElem(RefElem(member:Mod),pipee,Some(member:pipee),true)\n\npipee\n//│ = fun pipee\n\n(|>>)\n//│ = fun pipee\n\n|>>\n//│ = fun pipee\n\n:pe\n:e\nMod.|>>\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found end of input instead\n//│ ║  l.26: \tMod.|>>\n//│ ╙──      \t       ^\n//│ ╔══[COMPILATION ERROR] Name not found: .|>>\n//│ ║  l.26: \tMod.|>>\n//│ ╙──      \t   ^^^^\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type Mod.\n//│ ║  l.26: \tMod.|>>\n//│ ╙──      \t^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n1 |>> x => printt(x)\n//│ > 1\n\n\n:pe\n:e\nopen Mod { |>> }\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found end of input instead\n//│ ║  l.45: \topen Mod { |>> }\n//│ ╙──      \t                ^\n//│ ╔══[COMPILATION ERROR] Illegal 'open' statement shape.\n//│ ║  l.45: \topen Mod { |>> }\n//│ ╙──      \t     ^^^^^^^^^^^\n\n\n:e\nopen Mod { (|>>) }\n//│ ╔══[COMPILATION ERROR] Illegal 'open' statement element.\n//│ ║  l.55: \topen Mod { (|>>) }\n//│ ╙──      \t           ^^^^^\n\n12 |>> print\n//│ > 12\n\n\nopen Mod { printt, |>> }\n\n:fixme\n12 |>> printt\n//│ ╔══[COMPILATION ERROR] Module 'Mod' does not contain member '|>>'\n//│ ║  l.67: \t12 |>> printt\n//│ ╙──      \t   ^^^\n//│ ═══[RUNTIME ERROR] TypeError: Mod1.|>> is not a function\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Getters.mls",
    "content": ":js\n:noInline\n\n\n:sjs\nfun t = 42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let t; t = function t() { return 42 };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:expect 42\n:sjs\nt\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ t()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\nfun main() =\n  let n = 0\n  fun foo =\n    print(\"ok\")\n    set n += 1\n    n\n  foo + foo\n\n:expect 3\nmain()\n//│ > ok\n//│ > ok\n//│ = 3\n\n\n:sjs\nfun test() =\n  fun whoops =\n    print(\"ok\")\n    42\n  whoops + whoops\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test;\n//│ test = function test() {\n//│   let whoops, tmp, tmp1;\n//│   whoops = function whoops() {\n//│     Predef.print(\"ok\");\n//│     return 42\n//│   };\n//│   tmp = whoops();\n//│   tmp1 = whoops();\n//│   return tmp + tmp1\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ntest()\n//│ > ok\n//│ > ok\n//│ = 84\n\n\n:sjs\nmodule T with\n  fun t() = 1\n  fun p = 2\n  val a = t\n  val b = this.t\n  val c = p\n  val d = this.p\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let T1;\n//│ (class T {\n//│   static {\n//│     T1 = this\n//│   }\n//│   static {\n//│     this.a = T.t;\n//│     this.b = T.t;\n//│     this.c = T.p;\n//│     this.d = T.p;\n//│   }\n//│   static t() {\n//│     return 1\n//│   } \n//│   static get p() {\n//│     return 2;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"T\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nT.a\n//│ = fun t\n\nT.b\n//│ = fun t\n\nT.c\n//│ = 2\n\nT.d\n//│ = 2\n\n\n:sjs\nmodule M with\n  fun t = 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let M1;\n//│ (class M {\n//│   static {\n//│     M1 = this\n//│   }\n//│   static get t() {\n//│     return 0;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"M\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\nM.t\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ M1.t\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:sjs\nfun test() =\n  fun whoops = 42\n  whoops\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test1;\n//│ test1 = function test() { let whoops; whoops = function whoops() { return 42 }; return whoops() };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:re\nglobalThis.whoops\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'whoops' yielded 'undefined'\n\n\ntest()\n//│ = 42\n\n\n:re\nglobalThis.whoops\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'whoops' yielded 'undefined'\n\n\n:sjs\nfun bar() =\n  fun baz() = 42\n  baz\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let bar; bar = function bar() { let baz; baz = function baz() { return 42 }; return baz };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\nfun baz() =\n  fun w = 1\n  fun z = 2\n  (x, y) => x + y + w + z\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let baz;\n//│ baz = function baz() {\n//│   let w, z, lambda;\n//│   w = function w() {\n//│     return 1\n//│   };\n//│   z = function z() {\n//│     return 2\n//│   };\n//│   lambda = (undefined, function (x, y) {\n//│     let tmp, tmp1, tmp2, tmp3;\n//│     tmp = x + y;\n//│     tmp1 = w();\n//│     tmp2 = tmp + tmp1;\n//│     tmp3 = z();\n//│     return tmp2 + tmp3\n//│   });\n//│   return lambda\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nbaz()(3, 4)\n//│ = 10\n\n\n:sjs\nfun a() =\n  fun b = 1\n  fun c() =\n    fun d = 2\n    b + d\n  c\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let a;\n//│ a = function a() {\n//│   let b, c;\n//│   b = function b() {\n//│     return 1\n//│   };\n//│   c = function c() {\n//│     let d, tmp, tmp1;\n//│     d = function d() { return 2 };\n//│     tmp = b();\n//│     tmp1 = d();\n//│     return tmp + tmp1\n//│   };\n//│   return c\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\na()()\n//│ = 3\n\n\n:sjs\nfun b() =\n  fun c = 1\n  fun d() =\n    fun c = 2\n    c\n  d\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let b;\n//│ b = function b() {\n//│   let d;\n//│   d = function d() { let c; c = function c() { return 2 }; return c() };\n//│   return d\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nb()()\n//│ = 2\n\n\n:sjs\nfun c() =\n  fun f = 1\n  fun d =\n    fun e = 1\n    e + f\n  d\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let c;\n//│ c = function c() {\n//│   let d, f;\n//│   f = function f() {\n//│     return 1\n//│   };\n//│   d = function d() {\n//│     let e, tmp, tmp1;\n//│     e = function e() { return 1 };\n//│     tmp = e();\n//│     tmp1 = f();\n//│     return tmp + tmp1\n//│   };\n//│   return d()\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nc()\n//│ = 2\n\n\n:sjs\ndata class Foo(x) with\n  fun oops = x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ Foo1 = function Foo(x) {\n//│   return globalThis.Object.freeze(new Foo.class(x));\n//│ };\n//│ (class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   constructor(x) {\n//│     this.x = x;\n//│   }\n//│   get oops() {\n//│     return this.x;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"x\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nfun foo(f) =\n  f.oops\n\n\nfoo(Foo(42))\n//│ = 42\n\n\nfun foo(f) =\n  f.oops\n\ndata class Foo(x) with\n  fun oops = x\n\nfoo(Foo(42))\n//│ = 42\n\n:re\nfoo(Foo(42))()\n//│ ═══[RUNTIME ERROR] TypeError: baseCall3 is not a function\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/GlobalThis.mls",
    "content": ":js\n\n\n:silent\nlet g = globalThis\n\n\n// FIXME prevent rebinding of this name\n:re\nlet globalThis = \"oops\"\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n\n:re\nglobalThis\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n\n\n// * This one uses `this.Error` so it's fine\n:sjs\n:re\nif false then 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut;\n//│ scrut = false;\n//│ if (scrut === true) {\n//│   0\n//│ } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n\n// * This one uses `globalThis.Error`\n// * Notice the failed exception throw\n:sjs\n:re\nfun foo() =\n  if false then 0\nfoo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo;\n//│ foo = function foo() {\n//│   let scrut1;\n//│   scrut1 = false;\n//│   if (scrut1 === true) {\n//│     return 0\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ foo()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'freeze')\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Hygiene.mls",
    "content": ":js\n\n\n// * Note how we avoid the name clash between the internal name `Test` of the class\n// * and the external name `Test1` of its singleton instance.\n:sjs\nobject Test with\n  val x = 12\n  fun foo() =\n    print(Test)\n    Test.x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Test1;\n//│ (class Test {\n//│   static {\n//│     new this\n//│   }\n//│   constructor() {\n//│     Test1 = this;\n//│     this.x = 12;\n//│     Object.defineProperty(this, \"class\", {\n//│       value: Test\n//│     });\n//│     globalThis.Object.freeze(this);\n//│   }\n//│   foo() {\n//│     Predef.print(Test1);\n//│     return Test1.x\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"object\", \"Test\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nTest\n//│ = Test { x: 12, class: object Test }\n\nprint(Test)\n//│ > Test { x: 12, class: object Test }\n\n:sjs\nTest.foo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Test1.foo()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > Test { x: 12, class: object Test }\n//│ = 12\n\n:sjs\nval Test = \"oops\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Test2; Test2 = \"oops\";\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ Test = \"oops\"\n\n:re\nTest.foo()\n//│ ═══[RUNTIME ERROR] TypeError: Test2.foo is not a function\n\n\n:sjs\nlet x = 1\nlet f = () => x\nlet x = 2\nf()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x, f, x1, f1; x = 1; f1 = function f() { return x }; f = f1; x1 = 2; runtime.safeCall(f())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n//│ f = fun f\n//│ x = 2\n\n\n:ssjs\n:e\nmodule Test with\n  val x = 1\n  let x = 2\n//│ ╔══[COMPILATION ERROR] Name 'x' is already used\n//│ ║  l.78: \t  let x = 2\n//│ ║        \t      ^^^^^\n//│ ╟── by a member declared in the same block\n//│ ║  l.77: \t  val x = 1\n//│ ╙──      \t  ^^^^^^^^^\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let Test4;\n//│ globalThis.Object.freeze(class Test3 {\n//│   static {\n//│     Test4 = this\n//│   }\n//│   static #x;\n//│   static {\n//│     this.x = 1;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Test\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nTest.x\n//│ = 1\n\n\nmodule Test with\n  let x = 1\n  let f = () => x\n  let x = 2\n  print(f())\n//│ > 1\n\n\n:sjs\ndata class Cls(x) with\n  let x += 1\n  fun foo = x\n  let x *= 2\n  fun bar = x\n  print(this.x, x)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Cls1;\n//│ Cls1 = function Cls(x2) {\n//│   return globalThis.Object.freeze(new Cls.class(x2));\n//│ };\n//│ (class Cls {\n//│   static {\n//│     Cls1.class = this\n//│   }\n//│   constructor(x2) {\n//│     this.x = x2;\n//│     this.#x = this.x + 1;\n//│     this.#x1 = this.#x * 2;\n//│     Predef.print(this.x, this.#x1);\n//│   }\n//│   #x;\n//│   #x1;\n//│   get foo() {\n//│     return this.#x;\n//│   } \n//│   get bar() {\n//│     return this.#x1;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Cls\", [\"x\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet cls = Cls(10)\n//│ > 10 22\n//│ cls = Cls(10)\n\n:expect 10\ncls.x\n//│ = 10\n\n:expect 11\ncls.foo\n//│ = 11\n\n:expect 22\ncls.bar\n//│ = 22\n\nmodule M\n\nfun foo(): module M =\n  if false then\n    module A\n    A\n  else\n    module A\n    A\n\nfoo()\n//│ = class A\n\n\n:sjs\nmodule Whoops with\n  val v: module Whoops = this\n  fun f() = \"Hello\"\n  module Whoops with\n    val w: module Whoops = this\n    fun g() = f()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Whoops2;\n//│ (class Whoops {\n//│   static {\n//│     Whoops2 = this\n//│   }\n//│   static {\n//│     this.v = Whoops;\n//│     (class Whoops1 {\n//│       static {\n//│         Whoops.Whoops = this\n//│       }\n//│       static {\n//│         this.w = Whoops1;\n//│       }\n//│       static g() {\n//│         return Whoops.f()\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"Whoops\"]; \n//│     });\n//│   }\n//│   static f() {\n//│     return \"Hello\"\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Whoops\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nWhoops.f()\n//│ = \"Hello\"\n\nWhoops.Whoops\n//│ = class Whoops { w: ref'1 } as ref'1\n\nWhoops.Whoops.g()\n//│ = \"Hello\"\n\n\n:e\nRuntime\n//│ ╔══[COMPILATION ERROR] Name not found: Runtime\n//│ ║  l.225: \tRuntime\n//│ ╙──       \t^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:sjs\nmodule AA with\n  module BB with\n    val y = 2\n    fun test =\n      let BB = \"oops\"\n      y\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let AA1;\n//│ (class AA {\n//│   static {\n//│     AA1 = this\n//│   }\n//│   static {\n//│     (class BB {\n//│       static {\n//│         AA.BB = this\n//│       }\n//│       static {\n//│         this.y = 2;\n//│       }\n//│       static get test() {\n//│         return BB.y;\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"BB\"]; \n//│     });\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"AA\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/IfThenElse.mls",
    "content": ":js\n\n\n// :elt\nif true then 1 else 0\n//│ = 1\n\n\n:sjs\nlet f = x => if x then print(\"ok\") else print(\"ko\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f, f1;\n//│ f1 = function f(x) {\n//│   if (x === true) { return Predef.print(\"ok\") }\n//│   return Predef.print(\"ko\");\n//│ };\n//│ f = f1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\nf(true)\n//│ > ok\n\nf(false)\n//│ > ko\n\n\n:sjs\nlet f = x => print((if x then \"ok\" else \"ko\") + \"!\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2, lambda;\n//│ lambda = (undefined, function (x) {\n//│   let tmp, tmp1;\n//│   if (x === true) {\n//│     tmp = \"ok\";\n//│   } else { tmp = \"ko\"; }\n//│   tmp1 = tmp + \"!\";\n//│   return Predef.print(tmp1)\n//│ });\n//│ f2 = lambda;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun\n\n:sjs\nlet f = x => print((if x and x then \"ok\" else \"ko\") + \"!\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f3, lambda1;\n//│ lambda1 = (undefined, function (x) {\n//│   let tmp, tmp1;\n//│   if (x === true) {\n//│     tmp = \"ok\";\n//│   } else { tmp = \"ko\"; }\n//│   tmp1 = tmp + \"!\";\n//│   return Predef.print(tmp1)\n//│ });\n//│ f3 = lambda1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun\n// --- TODO: What we want ---\n// this.f = (x) => {\n//   let tmp, tmp1, flag;\n//   if (x) {\n//     if (x) {\n//       tmp = \"ok\";\n//     } else {\n//       flag = 1;\n//     }\n//   } else {\n//     flag = 1;\n//   }\n//   if (flag === 1) {\n//     tmp = \"ko\";\n//   }\n//   tmp1 = tmp + \"!\";\n//   return print(tmp1)\n// };\n// undefined\n// f = [Function (anonymous)]\n\nf(true)\n//│ > ok!\n\nf(false)\n//│ > ko!\n\n\nx => if x > 0 then print(\"Hi\") else print(\"Bye\")\n//│ = fun\n\nx => print(if true then \"Hi\" else \"Bye\")\n//│ = fun\n\nx => print(if x + 1 > 0 then \"Hi\" else \"Bye\")\n//│ = fun\n\nx =>\n  let str = (+)(if x + 1 > 0 then \"Hello\" else \"Bye\", \"World\")\n  print(str)\n//│ = fun\n\n\nfun f(x, y) =\n  if x\n    then y\n\nf(true, 42)\n//│ = 42\n\n:re\nf(false, 42)\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\nfun f(x, y, z) = if x then y else z\n\nf(true, 0, 1)\n//│ = 0\n\n\nfun f(x, y, z) =\n  if x\n    then y\n    else z\n\nf(true, 1, 0)\n//│ = 1\n\nf(false, 1, 0)\n//│ = 0\n\n\nif true then\n  100\n//│ = 100\n\nif true then\n  100\nelse\n  0\n//│ = 100\n\nif true then\n  100\nelse\n  fun f(x) = x\n  f(3)\n//│ = 100\n\nif true then\n  fun f(x) = x\n  f(3)\nelse\n  100\n//│ = 3\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImperativeConditionals.mls",
    "content": ":js\n:ignore\n\n\nlet x = -1\n//│ x = -1\n\nif x < 0 do set x = 0\n\n\nfun f(x) =\n  if x < 0 return 0\n  Math.sqrt(x)\n//│ ╔══[PARSE ERROR] Unexpected 'return' keyword here\n//│ ║  l.12: \t  if x < 0 return 0\n//│ ╙──      \t           ^^^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (integer literal)\n//│ ║  l.12: \t  if x < 0 return 0\n//│ ╙──      \t         ^\n\n\nfun hasZeroElement(xs) =\n  while xs is\n    Cons(0, tl) return true\n    Cons(hd, tl) do set xs = tl\n    Nil return false\n//│ ╔══[PARSE ERROR] Unexpected 'return' keyword here\n//│ ║  l.24: \t    Cons(0, tl) return true\n//│ ╙──      \t                ^^^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (integer literal).\n//│ ║  l.24: \t    Cons(0, tl) return true\n//│ ╙──      \t         ^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (identifier).\n//│ ║  l.24: \t    Cons(0, tl) return true\n//│ ╙──      \t            ^^\n//│ ╔══[WARNING] This catch-all clause makes the following branches unreachable.\n//│ ║  l.24: \t    Cons(0, tl) return true\n//│ ║        \t         ^\n//│ ╟── This branch is unreachable.\n//│ ║  l.24: \t    Cons(0, tl) return true\n//│ ╙──      \t            ^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportAlias.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Example.mls\" as AnotherExample\n\n:e\nExample.inc(0)\n//│ ╔══[COMPILATION ERROR] Name not found: Example\n//│ ║  l.7: \tExample.inc(0)\n//│ ╙──     \t^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:expect 1\nAnotherExample.inc(0)\n//│ = 1\n\n\n:silent\nimport \"../../mlscript-compile/Example.mjs\" as JSExample\n\n:e\nExample.inc(0)\n//│ ╔══[COMPILATION ERROR] Name not found: Example\n//│ ║  l.22: \tExample.inc(0)\n//│ ╙──      \t^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:expect 1\nJSExample.inc(0)\n//│ = 1\n\n\n:pe\nimport \"../../mlscript-compile/Example.mls\" as\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found end of input instead\n//│ ║  l.34: \timport \"../../mlscript-compile/Example.mls\" as\n//│ ╙──      \t                                              ^\n\n:e\nimport \"../../mlscript-compile/Example.mls\" as \"Examle\"\n//│ ╔══[COMPILATION ERROR] Expected identifier after 'as' in import statement\n//│ ║  l.40: \timport \"../../mlscript-compile/Example.mls\" as \"Examle\"\n//│ ╙──      \t                                               ^^^^^^^^\n\nimport \"../../mlscript-compile/Example.mls\"\n\n:expect 1\nExample.inc(0)\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportConflicts.mls",
    "content": ":js\n\n\nmodule Option1 with { fun Some1 = 1 }\n\nopen Option1\nfun Some1 = \"111\"\nSome1\n//│ = \"111\"\n\n\nmodule Option2 with { fun Some2 = 2 }\n\n// * Note that wildcard imports do not import names that are already defined in the same scope\nfun Some2 = \"222\"\nopen Option2\nSome2\n//│ = \"222\"\n\n\nmodule Option3 with { fun Some3 = 3 }\n\n:w\nfun Some3 = \"333\"\nopen Option3 { Some3 }\nSome3\n//│ ╔══[WARNING] Imported name 'Some3' is shadowed by a name already defined in the same scope\n//│ ║  l.25: \topen Option3 { Some3 }\n//│ ╙──      \t               ^^^^^\n//│ = \"333\"\n\n\nmodule Option4 with { fun Some4 = 4 }\n\nfun Some4 = \"444\"\nfun bar =\n  open Option4 { Some4 }\n  Some4\nbar\n//│ = 4\n\n\nmodule Option5 with { fun Some5 = 5 }\n\nfun Some5 = \"555\"\nfun bar =\n  open Option5\n  Some5\nbar\n//│ = 5\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportExample.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Example.mls\"\n\n\nExample.inc(123)\n//│ = 124\n\n\nExample.funnySlash(Example.inc, 123)\n//│ = 124\n\n\nExample.pubFun\n//│ = \"hi\"\n\n:e\n:re\nExample.privFun\n//│ ╔══[COMPILATION ERROR] Module 'Example' does not contain member 'privFun'\n//│ ║  l.20: \tExample.privFun\n//│ ╙──      \t       ^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'privFun' yielded 'undefined'\n\n:re\nExample.assertFail()\n//│ ═══[RUNTIME ERROR] Error: Assertion failed (mlscript-compile/Example.mls:27)\n\n\nlet n = 42\n//│ n = 42\n\n:sjs\nn / 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ n / 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 21\n\n\n// * Builtin operators can be shadowed/rebound\n\nopen Example\n\n:sjs\ninc / 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Example.funnySlash(Example.inc, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n:sjs\n:re\nn / 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Example.funnySlash(n, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\nfunnySlash(inc, 123)\n//│ = 124\n\ninc / 123\n//│ = 124\n\ntest(\"hello\")\n//│ = \"str\"\n\ntest / (inc / 123)\n//│ = \"int\"\n\n// Note: `/` is left-associative, so `test / inc / 123` parses as `(test / inc) / 123`,\n// which errors because `funnySlash(test, inc)` does not return a valid function.\n:re\ntest / inc / 123\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n:re\ntest / inc / 123 * 0.5\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportJSClass.mls",
    "content": ":js\n\n\n\nimport \"../../js/MyClass.mjs\"\n//│ MyClass = class MyClass\n\nMyClass\n//│ = class MyClass\n\nnew! MyClass(\"Bob\")\n//│ = MyClass { name: \"Bob\" }\n\nlet C = MyClass\n//│ C = class MyClass\n\nlet c = C\n//│ c = class MyClass\n\nnew! c(\"Bob\")\n//│ = MyClass { name: \"Bob\" }\n\n:re\nglobalThis.MyClass\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'MyClass' yielded 'undefined'\n\n\n:ge\nfun foo() =\n  import \"../../js/MyClass.mjs\"\n  ()\n//│ ╔══[COMPILATION ERROR] Imports must be at the top level\n//│ ║  l.30: \t  import \"../../js/MyClass.mjs\"\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportJSModule.mls",
    "content": ":js\n\nimport \"../../js/Test.mjs\"\n//│ Test = {greet: fun greet}\n\nTest\n//│ = {greet: fun greet}\n\nTest.greet()\n//│ > Hello from Test.mjs!\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportMLs.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Option.mls\"\n\n\nopen Option { isDefined }\n\nOption.None isDefined()\n//│ = false\n\nOption.Some(1) isDefined()\n//│ = true\n\n\nopen Option\n  Some, None\n  isDefined\n\n:sjs\nNone isDefined()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Option.isDefined(Option.None)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = false\n\ncase Some(x) then x\n//│ = fun\n\ncase { Some(x) then x }\n//│ = fun\n\nSome(1) isDefined()\n//│ = true\n\nSome(1)\n  isDefined()\n//│ = true\n\n:sjs\n(new Some(1)) isDefined()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp3; tmp3 = globalThis.Object.freeze(new Option.Some.class(1)); Option.isDefined(tmp3)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\nnew Some(1) isDefined()\n//│ = true\n\nnew Some(1)\n  isDefined()\n//│ = true\n\n\nopen Option { Some, None, isDefined }\n\n(new Some(1)) isDefined()\n//│ = true\n\nNone isDefined()\n//│ = false\n\nNone == Option.None\n//│ = true\n\n\n:e\n:re\nOption.oops\n//│ ╔══[COMPILATION ERROR] Module 'Option' does not contain member 'oops'\n//│ ║  l.69: \tOption.oops\n//│ ╙──      \t      ^^^^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'oops' yielded 'undefined'\n\n:e\nopen Option { oops }\n//│ ╔══[COMPILATION ERROR] Module 'Option' does not contain member 'oops'\n//│ ║  l.76: \topen Option { oops }\n//│ ╙──      \t              ^^^^\n\noops\n\n:e\n:re\nOption.None.oops\n//│ ╔══[COMPILATION ERROR] Object 'None' does not contain member 'oops'\n//│ ║  l.85: \tOption.None.oops\n//│ ╙──      \t           ^^^^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'oops' yielded 'undefined'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportMLsJS.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Option.mjs\"\n//│ Option = class Option {\n//│   Some: fun Some { class: class Some },\n//│   None: None,\n//│   Both: fun Both { class: class Both },\n//│   unsafe: class unsafe\n//│ }\n\n\n:e\nOption.isDefined(new Option.Some(1))\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found selection.\n//│ ║  l.14: \tOption.isDefined(new Option.Some(1))\n//│ ║        \t                     ^^^^^^^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ = true\n\nOption.isDefined(new! Option.Some(1))\n//│ = true\n\nOption.isDefined(new! Option.Some.class(1))\n//│ = true\n\nOption.isDefined(Option.None)\n//│ = false\n\n\n(new! Option.Some(1)) Option.isDefined()\n//│ = true\n\nOption.None Option.isDefined()\n//│ = false\n\n\nOption.None\n//│ = None\n\nnew! Option.Some(1)\n//│ = Some(1)\n\nnew! Option.Both(1, 2)\n//│ = Both(1, 2)\n\n\nOption.None\n//│ = None\n\n// * This used to misbehave due to inadequately handling the weird precedence of `new`\nnew! Option.Some(1)\n//│ = Some(1)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ImportedOps.mls",
    "content": ":js\n\n\nmodule M with\n  fun (~) concat(a, b) = a + b\n\nopen M\n\n:sjs\nfun foo() =\n  \"a\" ~ \"b\" ~ \"c\"\nfoo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo;\n//│ foo = function foo() { let tmp; tmp = M1.concat(\"a\", \"b\"); return M1.concat(tmp, \"c\") };\n//│ foo()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"abc\"\n\nlet name = \"_\"\n//│ name = \"_\"\n\nlet display(balance) = balance\n//│ display = fun display\n\n\"b\" ~ display(\"-\")\n//│ = \"b-\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/InlineLambdas.mls",
    "content": ":js\n:noInline\n\n:sjs\n(x => x + 1 + 1 + 1 + 1 + 1)(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda;\n//│ lambda = (undefined, function (x) {\n//│   let tmp, tmp1, tmp2, tmp3;\n//│   tmp = x + 1;\n//│   tmp1 = tmp + 1;\n//│   tmp2 = tmp1 + 1;\n//│   tmp3 = tmp2 + 1;\n//│   return tmp3 + 1\n//│ });\n//│ runtime.safeCall(lambda(1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 6\n\n:sjs\n(x => x + 1 + 1 + 1 + 1 + 1 + 1)(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda1;\n//│ lambda1 = (undefined, function (x) {\n//│   let tmp, tmp1, tmp2, tmp3, tmp4;\n//│   tmp = x + 1;\n//│   tmp1 = tmp + 1;\n//│   tmp2 = tmp1 + 1;\n//│   tmp3 = tmp2 + 1;\n//│   tmp4 = tmp3 + 1;\n//│   return tmp4 + 1\n//│ });\n//│ runtime.safeCall(lambda1(1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 7\n\n:sjs\n(x => x) + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda2; lambda2 = (undefined, function (x) { return x }); lambda2 + 1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"function (x) {   runtime.checkArgs(\\\"\\\", 1, true, arguments.length);   return x }1\"\n\n:sjs\n1 + (x => x)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda3; lambda3 = (undefined, function (x) { return x }); 1 + lambda3\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"1function (x) {   runtime.checkArgs(\\\"\\\", 1, true, arguments.length);   return x }\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/InlineMultiArgLists.mls",
    "content": ":js\n\n// * TODO: take `private` into accoutn and inline these single-use functions regardless of threshold\n\n\n// Test: Curried function with two parameter lists. Properly fully inlined.\n:soir\nprivate fun add(x)(y) = x + y\nadd(1)(2)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let add⁰, x⁰, y⁰, inlinedVal;\n//│ define add⁰ as fun add¹(x)(y) {\n//│   return +⁰(x, y)\n//│ };\n//│ set x⁰ = 1;\n//│ set y⁰ = 2;\n//│ set inlinedVal = +⁰(x⁰, y⁰);\n//│ inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n// Test: Function returning a lambda, called with 2 arg lists at use site.\n// We properly inline the outer function, but not yet the inner lambda.\n:inlineThreshold 100\n:soir\nprivate fun mkAdder(x) =\n  (y) => x + y\nmkAdder(10)(20)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let mkAdder⁰, baseCall, x¹, inlinedVal, lambda⁰;\n//│ define mkAdder⁰ as fun mkAdder¹(x) {\n//│   let lambda;\n//│   define lambda as fun lambda¹(y) {\n//│     return +⁰(x, y)\n//│   };\n//│   return lambda¹\n//│ };\n//│ set x¹ = 10;\n//│ define lambda⁰ as fun lambda²(y) {\n//│   return +⁰(x¹, y)\n//│ };\n//│ set inlinedVal = lambda²;\n//│ set baseCall = inlinedVal;\n//│ baseCall(20)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 30\n\n// Test: Partial application — call with fewer arg lists than param lists\n:soir\nprivate fun add2(x)(y) = x + y\nlet f = add2(10)\nf(5)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let add2⁰, f⁰; define add2⁰ as fun add2¹(x)(y) { return +⁰(x, y) }; set f⁰ = add2¹(10); f⁰(5)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 15\n//│ f = fun\n\n// Test: Three parameter lists — all properly inlined\n:inlineThreshold 100\n:soir\nprivate fun triple(x)(y)(z) = x + y + z\ntriple(1)(2)(3)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let triple⁰, x², y¹, z⁰, inlinedVal, tmp;\n//│ define triple⁰ as fun triple¹(x)(y)(z) {\n//│   let tmp1;\n//│   set tmp1 = +⁰(x, y);\n//│   return +⁰(tmp1, z)\n//│ };\n//│ set x² = 1;\n//│ set y¹ = 2;\n//│ set z⁰ = 3;\n//│ set tmp = +⁰(x², y¹);\n//│ set inlinedVal = +⁰(tmp, z⁰);\n//│ inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 6\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Inliner.mls",
    "content": ":js\n\n:soir\nfun f() = 0\nf()\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁰, inlinedVal; define f⁰ as fun f¹() { return 0 }; set inlinedVal = 0; inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:soir\nfun f(x) = x\nf(100)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f², x⁰, inlinedVal;\n//│ define f² as fun f³(x) { return x };\n//│ set x⁰ = 100;\n//│ set inlinedVal = x⁰;\n//│ inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 100\n\n\n:soir\nfun f() =\n  let done(x) = x\n  done\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁴;\n//│ define f⁴ as fun f⁵() {\n//│   let done, done1;\n//│   define done1 as fun done⁰(x) { return x };\n//│   set done = done⁰;\n//│   return done\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// * TODO: support spread arguments like this one\n:soir\n:inlineThreshold 10\nfun f(a, b, c) = a + b + c\nprint(f(1, 2, 3))\nprint(f(1, 2, ...[1]))\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁶, tmp, tmp1, tmp2, a⁰, b⁰, c⁰, inlinedVal, tmp3;\n//│ define f⁶ as fun f⁷(a, b, c) {\n//│   let tmp4;\n//│   set tmp4 = +⁰(a, b);\n//│   return +⁰(tmp4, c)\n//│ };\n//│ set a⁰ = 1;\n//│ set b⁰ = 2;\n//│ set c⁰ = 3;\n//│ set tmp3 = +⁰(a⁰, b⁰);\n//│ set inlinedVal = +⁰(tmp3, c⁰);\n//│ set tmp = inlinedVal;\n//│ do Predef⁰.print⁰(tmp);\n//│ set tmp1 = [1];\n//│ set tmp2 = f⁷(1, 2, ...tmp1);\n//│ Predef⁰.print⁰(tmp2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 6\n//│ > 4\n\n\n:soir\n:inlineThreshold 10\nfun f(a, ...b) =\n  print(a)\n  print(b)\nf(1, ...[2])\nf(1, ...[2], ...[3])\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁸, tmp, tmp1, tmp2;\n//│ define f⁸ as fun f⁹(a, ...b) {\n//│   do Predef⁰.print⁰(a);\n//│   return Predef⁰.print⁰(b)\n//│ };\n//│ set tmp = [2];\n//│ do f⁹(1, ...tmp);\n//│ set tmp1 = [2];\n//│ set tmp2 = [3];\n//│ f⁹(1, ...tmp1, ...tmp2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n//│ > [2]\n//│ > 1\n//│ > [2, 3]\n\n\n// All inlined\n:soir\n:inlineThreshold 10\nfun f(a, b, ...c) =\n  print(a + b)\n  print(c)\nf(1, 2)\nf(1, 2, 3)\nf(1, 2, 3, 4)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f¹⁰, a¹, b¹, c¹, a², b², c², a³, b³, c³, inlinedVal, tmp, tmp1, tmp2;\n//│ define f¹⁰ as fun f¹¹(a, b, ...c) {\n//│   let tmp3;\n//│   set tmp3 = +⁰(a, b);\n//│   do Predef⁰.print⁰(tmp3);\n//│   return Predef⁰.print⁰(c)\n//│ };\n//│ set a¹ = 1;\n//│ set b¹ = 2;\n//│ set c¹ = mut [];\n//│ set tmp2 = +⁰(a¹, b¹);\n//│ do Predef⁰.print⁰(tmp2);\n//│ do Predef⁰.print⁰(c¹);\n//│ set a² = 1;\n//│ set b² = 2;\n//│ set c² = mut [3];\n//│ set tmp1 = +⁰(a², b²);\n//│ do Predef⁰.print⁰(tmp1);\n//│ do Predef⁰.print⁰(c²);\n//│ set a³ = 1;\n//│ set b³ = 2;\n//│ set c³ = mut [3, 4];\n//│ set tmp = +⁰(a³, b³);\n//│ do Predef⁰.print⁰(tmp);\n//│ set inlinedVal = Predef⁰.print⁰(c³);\n//│ inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 3\n//│ > []\n//│ > 3\n//│ > [3]\n//│ > 3\n//│ > [3, 4]\n\n// only inline perfect match when spread is used\n:sjs\n:inlineThreshold 10\nfun f(a, b, ...c) =\n  print(a + b)\n  print(c)\nf(1, ...[2, 3])\nf(1, 2, ...[3])\nf(1, 2, 3, ...[4])\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f6, tmp10, tmp11, tmp12;\n//│ f6 = function f(a4, b4, ...c4) {\n//│   let tmp13;\n//│   tmp13 = a4 + b4;\n//│   Predef.print(tmp13);\n//│   return Predef.print(c4)\n//│ };\n//│ tmp10 = globalThis.Object.freeze([\n//│   2,\n//│   3\n//│ ]);\n//│ f6(1, ...tmp10);\n//│ tmp11 = globalThis.Object.freeze([\n//│   3\n//│ ]);\n//│ f6(1, 2, ...tmp11);\n//│ tmp12 = globalThis.Object.freeze([ 4 ]);\n//│ f6(1, 2, 3, ...tmp12)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 3\n//│ > [3]\n//│ > 3\n//│ > [3]\n//│ > 3\n//│ > [3, 4]\n\n\n// Multiple return points\n:sjs\n:expect true\nfun f() =\n  fun g(x) =\n    if x is true do return true\n    return false\n  g(true)\nf()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f7;\n//│ f7 = function f() {\n//│   let x1, inlinedVal4;\n//│   x1 = true;\n//│   if (x1 === true) {\n//│     inlinedVal4 = true;\n//│     return inlinedVal4\n//│   }\n//│   inlinedVal4 = false;\n//│   return inlinedVal4;\n//│ };\n//│ f7()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\n\n// Methods (not implemented currently)\n// NOTE: only final (ie, non-virtual) method may be inlined, as they could be overriden\n\n:sjs\n:soir\n:inlineThreshold 10\nmodule A with\n  fun f() = 1\n  fun g() = A.f()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let A1;\n//│ (class A {\n//│   static {\n//│     A1 = this\n//│   }\n//│   static f() {\n//│     return 1\n//│   } \n//│   static g() {\n//│     return A1.f()\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"A\"]; \n//│ });\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let A⁰;\n//│ define A⁰ as class A¹\n//│ module A² { method f¹² = fun f¹³() { return 1 } method g⁰ = fun g¹() { return A².f¹³() } };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// Inlining limits\n:soir\n:inlineThreshold 10\nfun f() = if false do f() + 1\nf()\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f¹⁴;\n//│ define f¹⁴ as fun f¹⁵() {\n//│   let scrut;\n//│   set scrut = false;\n//│   match scrut\n//│     true =>\n//│       do f¹⁵();\n//│       return runtime⁰.Unit⁰\n//│     else\n//│       return runtime⁰.Unit⁰\n//│   end\n//│ };\n//│ f¹⁵()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// Pathological case of inlining\n:soir\nfun g() =\n  fun f() = f()\n  f()\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let g²; define g² as fun g³() { let f; define f as fun f¹⁶() { return f¹⁶() }; return f¹⁶() }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/InnerNameHygiene.mls",
    "content": ":js\n:noInline\n\n\n// * Functions\n\n\nfun f(x) = x\n\n:sjs\nfun f(x) = x\nfun f1(x) = f(x) + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1, f11;\n//│ f1 = function f(x) {\n//│   return x\n//│ };\n//│ const proxy$f = f1; f11 = function f1(x) { let tmp; tmp = proxy$f(x); return tmp + 1 };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 42\nf1(41)\n//│ = 42\n\n\n:sjs\nfun g(x) = g(x) + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let g; g = function g(x) { let tmp; tmp = g(x); return tmp + 1 };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nfun ff(x) = 0\n\n:sjs\nfun ff(x) = x\nfun g() =\n  fun ff1(x) = ff(x)\n  ff1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let ff1, g1;\n//│ ff1 = function ff(x) {\n//│   return x\n//│ };\n//│ g1 = function g() {\n//│   let ff11;\n//│   const proxy$ff = ff1; ff11 = function ff1(x) { return proxy$ff(x) };\n//│   return ff11\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 42\ng()(42)\n//│ = 42\n\n\n:sjs\nfun h(x) = x\nfun g() =\n  fun h1(x) = h(x) + h1(x)\n  h1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let g2, h;\n//│ h = function h(x) {\n//│   return x\n//│ };\n//│ g2 = function g() {\n//│   let h1;\n//│   h1 = function h1(x) { let tmp, tmp1; tmp = h(x); tmp1 = h1(x); return tmp + tmp1 };\n//│   return h1\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * Classes\n\n\n:sjs\nclass C with\n  class C with\n    new C\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let C2;\n//│ (class C {\n//│   static {\n//│     C2 = this\n//│   }\n//│   constructor() {\n//│     const this$C = this;\n//│     (class C1 {\n//│       static {\n//│         this$C.C = this\n//│       }\n//│       constructor() {\n//│         globalThis.Object.freeze(new this$C.C());\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"C\"]; \n//│     });\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"C\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\nclass CC with\n  fun foo =\n    class CC2 with\n      new CC2\n    new CC2\n  new CC\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let CC1;\n//│ (class CC {\n//│   static {\n//│     CC1 = this\n//│   }\n//│   constructor() {\n//│     globalThis.Object.freeze(new CC1());\n//│   }\n//│   get foo() {\n//│     let CC21;\n//│     (class CC2 {\n//│       static {\n//│         CC21 = this\n//│       }\n//│       constructor() {\n//│         globalThis.Object.freeze(new CC21());\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"CC2\"]; \n//│     });\n//│     return globalThis.Object.freeze(new CC21());\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"CC\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nclass F\nmodule M with\n  object F1 with\n    val res = new F\n\n:expect true\nM.F1.res is F\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/InterleavedRecords.mls",
    "content": ":js\n\n\n// * Record fields can be interleaved with other statements.\n// * Also, later record fields can refer to prior ones.\n\n\nlet rcd =\n  a: 0\n  print(a)\n  let y = a + 1\n  b: y\n//│ > 0\n//│ rcd = {a: 0, b: 1}\n\nlet rcd =\n  a: 1\n  print(a)\n  b: a + 1\n  let tmp = a + b\n  c: tmp\n  print(\"Done!\")\n//│ > 1\n//│ > Done!\n//│ rcd = {a: 1, b: 2, c: 3}\n\n\nfun foo(x) =\n  x: x + 1\n  y: x\n\nlet r = foo(123) in [r.x, r.y]\n//│ = [124, 124]\n\n\n// * Yaml!\n\nlet rcd =\n  a: 0\n  b:\n    y: 1\n    z: 2\n  c: b.z\n//│ rcd = {a: 0, b: {y: 1, z: 2}, c: 2}\n\n[rcd.b.y, rcd.c]\n//│ = [1, 2]\n\n\n// * Imperative Yaml!\n\nlet config(useModules) =\n  ext: \"js\"\n  if useModules do set ext = \"m\" + ext\n  base: \"main\"\n  full: base + \".\" + ext\n//│ config = fun\n\nconfig(true)\n//│ = {ext: \"mjs\", base: \"main\", full: \"main.mjs\"}\n\nconfig(false)\n//│ = {ext: \"js\", base: \"main\", full: \"main.js\"}\n\n\n// * When any statement is a record field, the whole block is a record.\n\n:w\nlet rcd =\n  print(\"Hello!\")\n  a: 0\n  42\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.72: \t  42\n//│ ╙──      \t  ^^\n//│ > Hello!\n//│ rcd = {a: 0}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Juxtapositions.mls",
    "content": ":js\n\n\n42 print()\n//│ > 42\n\nprint(42)\n//│ > 42\n\n42 console.log()\n//│ > 42\n\n\nfun inc(x) = x + 1\n\n42 inc()\n//│ = 43\n\n42 inc() inc()\n//│ = 44\n\n42 inc() inc() print()\n//│ > 44\n\ninc(42) inc() print()\n//│ > 44\n\n\nfun add(x, y) = x + y\n\n42 add(2)\n//│ = 44\n\n42 add(2) inc()\n//│ = 45\n\n:e\n:re\n:w\n42\nadd(2)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.41: \tadd(2)\n//│ ╙──      \t   ^^^\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.40: \t42\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] Error: Function 'add' expected 2 arguments but got 1\n\n\n42 add(2) + 1\n//│ = 45\n\n42 add(2) * 1 add(1)\n//│ = 88\n\n\n42\n  add(2)\n//│ = 44\n\n42\n  add(2)\n  inc()\n//│ = 45\n\n\n42 { inc() }\n//│ = 43\n\n42 { inc() }\n  inc()\n//│ = 44\n\n42 { add(2) } inc()\n//│ = 45\n\n42 { add(2) } { inc() }\n//│ = 45\n\n42 { add(2), inc() }\n//│ = 45\n\n:e\n42 { add(2) inc() }\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (juxtaposition).\n//│ ║  l.85: \t42 { add(2) inc() }\n//│ ╙──      \t     ^^^^^^^^^^^^\n//│ = 42\n\n:e\n42 { add(2) { inc() } }\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (juxtaposition).\n//│ ║  l.92: \t42 { add(2) { inc() } }\n//│ ╙──      \t     ^^^^^^^^^^^^^^^^\n//│ = 42\n\n2 * 2\n  inc()\n//│ = 6\n\n:pt\ninc(2) * 2\n  inc()\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpApp:\n//│   lhs = App:\n//│     lhs = Ident of \"inc\"\n//│     rhs = Tup of Ls of \n//│       IntLit of 2\n//│   op = Ident of \"*\"\n//│   rhss = Ls of \n//│     Jux:\n//│       lhs = IntLit of 2\n//│       rhs = Block of Ls of \n//│         App:\n//│           lhs = Ident of \"inc\"\n//│           rhs = Tup of Nil\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 9\n\n// :pt\n// :elt\n// :sjs\n:todo // ? do we really want to support this\n42\n  inc() * 1\n    add(2)\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (operator application).\n//│ ║  l.127: \t  inc() * 1\n//│ ║         \t  ^^^^^^^^^\n//│ ║  l.128: \t    add(2)\n//│ ╙──       \t^^^^\n//│ = 42\n\n:e\n42\n  inc()\n    add(2)\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (juxtaposition).\n//│ ║  l.138: \t  inc()\n//│ ║         \t  ^^^^^\n//│ ║  l.139: \t    add(2)\n//│ ╙──       \t^^^^\n//│ = 42\n\n\n// :dp\n:todo // ? do we really want to support this\n42\n  inc() + 1\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (operator application).\n//│ ║  l.151: \t  inc() + 1\n//│ ╙──       \t  ^^^^^^^^^\n//│ = 42\n\n:todo // ? do we really want to support this\n42\n  add(2) + 1\n  inc()\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (operator application).\n//│ ║  l.159: \t  add(2) + 1\n//│ ╙──       \t  ^^^^^^^^^^\n//│ = 43\n\n:todo // ? do we really want to support this\n42\n  add(2)\n  inc() + 1\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (operator application).\n//│ ║  l.169: \t  inc() + 1\n//│ ╙──       \t  ^^^^^^^^^\n//│ = 44\n\n2 * 2\n  inc()\n  inc()\n//│ = 8\n\n(2 * 2)\n  inc()\n  inc()\n//│ = 6\n\n(2 * 2\n  inc()) inc()\n//│ = 7\n\n(2 * 2\n  inc())\n  inc()\n//│ = 7\n\n(2 * 2\n  inc()\n)\n  inc()\n//│ = 7\n\n:e\n:re\n(2 * 2\n  inc())\ninc()\n//│ ╔══[COMPILATION ERROR] Expected 1 arguments, got 0\n//│ ║  l.204: \tinc()\n//│ ╙──       \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Function 'inc' expected 1 argument but got 0\n\n:e\n:re\n(2 * 2\n  inc()\n)\ninc()\n//│ ╔══[COMPILATION ERROR] Expected 1 arguments, got 0\n//│ ║  l.215: \tinc()\n//│ ╙──       \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Function 'inc' expected 1 argument but got 0\n\n\n42\n  console.log()\n\"Done.\"\n  console.log()\n//│ > 42\n//│ > Done.\n\n\n\n:e\n42 console.log\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (selection).\n//│ ║  l.232: \t42 console.log\n//│ ╙──       \t   ^^^^^^^^^^^\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Lambdas.mls",
    "content": ":js\n\n:global\n:sjs\n\n\nx =>\n  let y = x\n  y\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda; lambda = (undefined, function (x) { let y; y = x; return y }); lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n(acc, _) => acc\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda1; lambda1 = (undefined, function (acc, _) { return acc }); lambda1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Lazy.mls",
    "content": ":js\n\n\ndata class Lazy[out A](init: () -> A) with\n  mut val cached: A | () = ()\n  fun get: A\n  // fun eq(that: Lazy[A]) = this.cached == that.cached // TODO `this`\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/LetPatterns.mls",
    "content": ":js\n\n\ndata class Some[out A](value: A)\n\n:todo\nlet Some(x) = Some(42)\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.7: \tlet Some(x) = Some(42)\n//│ ╙──     \t    ^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nobject None\n\nlet N = None\n//│ N = None\n\n:todo\nlet (None) = N\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.20: \tlet (None) = N\n//│ ╙──      \t    ^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\ndata class Foo(a)\n\n:todo\nlet Foo(x) = Foo(1) in print(x)\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.30: \tlet Foo(x) = Foo(1) in print(x)\n//│ ╙──      \t    ^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.30: \tlet Foo(x) = Foo(1) in print(x)\n//│ ╙──      \t                             ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:todo\nlet Foo(x) and x > 0 = Foo(1) in print(\"ok\")\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.40: \tlet Foo(x) and x > 0 = Foo(1) in print(\"ok\")\n//│ ╙──      \t    ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/MergeMatchArms.mls",
    "content": ":js\n\n#config(commentGeneratedCode: true)\n\n\nobject A\nobject B\nobject C\nobject D\nobject E\n\n\nlet a = A\nlet b = B\n//│ a = A\n//│ b = B\n\n:sjs\nif a is\n  A then 1\n  B then 2\n  C then 3\n  D then 4\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ if (a instanceof A1.class) {\n//│   1\n//│ } else if (a instanceof B1.class) {\n//│   2\n//│ } else if (a instanceof C1.class) {\n//│   3\n//│ } else if (a instanceof D1.class) {\n//│   4\n//│ } else {\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│ }\n//│ /* Rest moved to non-abortive branch(es) */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\n// manually written `else if`s branches on the same scrut is also merged \n:sjs\nif a is\n  A then 1\n  else\n    if a is\n      B then 2\n      C then 3\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ if (a instanceof A1.class) {\n//│   1\n//│ } else if (a instanceof B1.class) {\n//│   2\n//│ } else if (a instanceof C1.class) {\n//│   3\n//│ } else {\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│ }\n//│ /* Rest moved to non-abortive branch(es) */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\n:sjs\nif a is\n  A and b is\n    A then 1\n    B then 2\n  B then 2\n  C then 3\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp;\n//│ if (a instanceof A1.class) {\n//│   if (b instanceof A1.class) {\n//│     tmp = 1;\n//│     tmp\n//│   } else if (b instanceof B1.class) {\n//│     tmp = 2;\n//│     tmp\n//│   } else {\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│   }\n//│   /* Rest moved to non-abortive branch(es) */\n//│ } else if (a instanceof B1.class) {\n//│   tmp = 2;\n//│   tmp\n//│ } else if (a instanceof C1.class) {\n//│   tmp = 3;\n//│   tmp\n//│ } else {\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│ }\n//│ /* Rest moved to non-abortive branch(es) */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n// The match arms here are still merged because\n// `let tmp = 3` is moved out so that it does not get into the way\n// and `print(\"done\")` is duplicated and moved into match arm bodies\n:sjs\nlet x = if a is\n  A then 1\n  B then 2\n  C then 3\n  else\n    let tmp = 3\n    if a is\n      D then\n        if a is\n         A then 1 + tmp\n         B then 2 + tmp\n      E then 5\n    print(\"done\")\nprint(x)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x, tmp1;\n//│ if (a instanceof A1.class) {\n//│   tmp1 = 1;\n//│ } else if (a instanceof B1.class) {\n//│   tmp1 = 2;\n//│ } else if (a instanceof C1.class) {\n//│   tmp1 = 3;\n//│ } else if (a instanceof D1.class) {\n//│   if (a instanceof A1.class) {} else if (a instanceof B1.class) {} else {\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│   }\n//│   tmp1 = Predef.print(\"done\");\n//│ } else if (a instanceof E1.class) {\n//│   tmp1 = Predef.print(\"done\");\n//│ } else {\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│ }\n//│ x = tmp1;\n//│ Predef.print(x)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n//│ x = 1\n\n\n// The match arms here are still merged because\n// `let tmp = 2` is moved out so that it does not get into the way\n:sjs\nif a is\n  A then 1\n  let tmp = 2\n  B then 2 + tmp\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp2;\n//│ tmp2 = 2;\n//│ if (a instanceof A1.class) {\n//│   1\n//│ } else if (a instanceof B1.class) {\n//│   2 + tmp2\n//│ } else {\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│ }\n//│ /* Rest moved to non-abortive branch(es) */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\nfun printAndId(x) =\n  print(x)\n  x\n\n// `let tmp = printAndId(3)` is not moved out\n// because the rhs is not trivial\n:sjs\nif a is\n  A then 1\n  let tmp = printAndId(3)\n  B then 2 + tmp\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp3;\n//│ if (a instanceof A1.class) {\n//│   1\n//│ } else {\n//│   tmp3 = printAndId(3);\n//│   if (a instanceof B1.class) {\n//│     2 + tmp3\n//│   } else {\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│   }\n//│   /* Rest moved to non-abortive branch(es) */\n//│ }\n//│ /* Rest moved to non-abortive branch(es) */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\n// The match arms here are still merged because\n// `print(x)` is duplicated and moved into match arm bodies\n:sjs\nif a is\n  A then 1\n  else\n    let x = if a is\n      B then 2\n      C then 3\n    print(x)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x1, tmp4;\n//│ if (a instanceof A1.class) {\n//│   1\n//│ } else if (a instanceof B1.class) {\n//│   tmp4 = 2;\n//│   x1 = tmp4;\n//│   Predef.print(x1)\n//│ } else if (a instanceof C1.class) {\n//│   tmp4 = 3;\n//│   x1 = tmp4;\n//│   Predef.print(x1)\n//│ } else {\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│ }\n//│ /* Rest moved to non-abortive branch(es) */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\n// The match arms are not merged because\n// `print(x); print(x + 1); print(x + 2)` is\n// not moved into match arm bodies for being too big\n:sjs\nif a is\n  B then 1\n  else\n    let x = if a is\n      A then 2\n      C then 3\n    print(x)\n    print(x + 1)\n    print(x + 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x2, tmp5, tmp6, tmp7;\n//│ if (a instanceof B1.class) {\n//│   1\n//│ } else {\n//│   if (a instanceof A1.class) {\n//│     tmp5 = 2;\n//│   } else if (a instanceof C1.class) {\n//│     tmp5 = 3;\n//│   } else {\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│   }\n//│   x2 = tmp5;\n//│   Predef.print(x2);\n//│   tmp6 = x2 + 1;\n//│   Predef.print(tmp6);\n//│   tmp7 = x2 + 2;\n//│   Predef.print(tmp7)\n//│ }\n//│ /* Rest moved to non-abortive branch(es) */\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n//│ > 3\n//│ > 4\n\n\n:soir\nfun f(x) =\n  let acc = \"\"\n  if x is 5 then\n    return acc\n  else\n    if x is\n      8 then print(\"8\")\n      else print(\"?\")\n    print(\"hi\")\n    acc\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁰;\n//│ define f⁰ as fun f¹(x) {\n//│   let acc;\n//│   set acc = \"\";\n//│   match x\n//│     5 =>\n//│       return acc\n//│     8 =>\n//│       do Predef⁰.print⁰(\"8\");\n//│       do Predef⁰.print⁰(\"hi\");\n//│       return acc\n//│     else\n//│       do Predef⁰.print⁰(\"?\");\n//│       do Predef⁰.print⁰(\"hi\");\n//│       return acc\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(5)\n//│ = \"\"\n\nf(6)\n//│ > ?\n//│ > hi\n//│ = \"\"\n\nf(8)\n//│ > 8\n//│ > hi\n//│ = \"\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Misc.mls",
    "content": ":js\n\n\n1 as Int\n//│ = 1\n\n1as Int\n//│ = 1\n\n(1)as(Int)\n//│ = 1\n\n:ge // Shouldn't allow using `Int` in term position\n1 : Int\n//│ ╔══[COMPILATION ERROR] Symbol 'Int' is virtual (i.e., \"compiler fiction\"); cannot be used as a term\n//│ ║  l.14: \t1 : Int\n//│ ╙──      \t    ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:sjs\n1 +\n2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 1 + 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n\nset (mut []).0 = 1\n\nlet arr = mut []\nset arr.0 = 1\n//│ arr = [1]\n\n\nfun (+!) bar = tuple\n\n1 +! 2\n//│ = [1, 2]\n\nbar of 1, 2\n//│ = [1, 2]\n\nbar(1, 2)\n//│ = [1, 2]\n\n1 \\bar(2)\n//│ = [1, 2]\n\n(1 \\bar)(2)\n//│ = [1, 2]\n\n(1 \\bar)(2, , 3)\n//│ = [1, 2, 3]\n\n(1 \\bar)(\n  2\n  \n  3\n)\n//│ = [1, 2, 3]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ModuleMatching.mls",
    "content": ":js\n\n\nobject Foo\n\nfun test(x) = x is Foo\n\ntest(Foo)\n//│ = true\n\n\nfun foo() =\n  object Foo\n  Foo is Foo\n\nfoo()\n//│ = true\n\n\nfun foo() =\n  class Foo\n  (new Foo) is Foo\n\nfoo()\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ModuleMethods.mls",
    "content": ":js\n\n\nmodule Example with\n  val a = 456\n  fun f(x) = [x, a]\n\n:ssjs\nExample.f(123)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res2 = runtime.checkCall(Example1.f(123)); undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [123, 456]\n\n:ssjs\nlet s = Example.f\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let s;\n//│ s = Example1.f;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ s = fun f\n\ns(123)\n//│ = [123, 456]\n\n:e\nExample |>. s(123)\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type Example.\n//│ ║  l.27: \tExample |>. s(123)\n//│ ║        \t^^^^^^^\n//│ ╙── Module argument passed to a non-module parameter.\n//│ = [123, 456]\n\n\n:sjs\nmodule Test with\n  let s = 1\n  print(s)\n  fun foo() = print(s)\n  fun bar() = foo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Test1;\n//│ (class Test {\n//│   static {\n//│     Test1 = this\n//│   }\n//│   static #s;\n//│   static {\n//│     Test.#s = 1;\n//│     Predef.print(Test.#s);\n//│   }\n//│   static foo() {\n//│     return Predef.print(Test.#s)\n//│   } \n//│   static bar() {\n//│     return Test.foo()\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Test\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n\nlet f = Test.foo\n//│ f = fun foo\n\n// :fixme\nf()\n//│ > 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Modules.mls",
    "content": ":js\n\n\n:sjs\nmodule None\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let None1;\n//│ (class None {\n//│   static {\n//│     None1 = this\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"None\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nNone\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ None1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class None\n\n:sjs\n:re\nNone()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(None1())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor None cannot be invoked without 'new'\n\n:e\nnew None\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference of type None.\n//│ ║  l.33: \tnew None\n//│ ║        \t    ^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ = None\n\n:sjs\n:e\nnew! None\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type None.\n//│ ║  l.42: \tnew! None\n//│ ╙──      \t     ^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new None1())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = None\n\n\n:sjs\nmodule M with\n  class C\n  class D()\n  val x = 1\n  val y = x + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let M1;\n//│ (class M {\n//│   static {\n//│     M1 = this\n//│   }\n//│   static {\n//│     let tmp;\n//│     (class C {\n//│       static {\n//│         M.C = this\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"C\"]; \n//│     });\n//│     this.D = function D() {\n//│       return globalThis.Object.freeze(new D.class());\n//│     };\n//│     (class D {\n//│       static {\n//│         M.D.class = this\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"D\", []]; \n//│     });\n//│     this.x = 1;\n//│     tmp = M.x + 1;\n//│     this.y = tmp;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"M\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nM.C\n//│ = class C\n\nnew M.C\n//│ = C\n\nM.D()\n//│ = D()\n\nM.x\n//│ = 1\n\nM.y\n//│ = 2\n\n:e\n:re\nM.oops\n//│ ╔══[COMPILATION ERROR] Module 'M' does not contain member 'oops'\n//│ ║  l.109: \tM.oops\n//│ ╙──       \t ^^^^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'oops' yielded 'undefined'\n\n\n// Note: this used to fail, but we now set the module's own binding as the first thing in the static ctor\n:sjs\nmodule M with\n  val m: module M = M\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let M3;\n//│ (class M2 {\n//│   static {\n//│     M3 = this\n//│   }\n//│   static {\n//│     this.m = M3;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"M\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nM.m\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ M3.m\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class M { m: ref'1 } as ref'1\n\n\nmodule M()\n\n\n// * Peculiarity (should not be a problem): notice that we have `BB.y`, and not `AA.BB.y`\n:sjs\nmodule AA with\n  val x = 1\n  module BB with\n    val y = 2\n    [x, y]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let AA1;\n//│ (class AA {\n//│   static {\n//│     AA1 = this\n//│   }\n//│   static {\n//│     this.x = 1;\n//│     (class BB {\n//│       static {\n//│         AA.BB = this\n//│       }\n//│       static {\n//│         this.y = 2;\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"BB\"]; \n//│     });\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"AA\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/NestedClasses.mls",
    "content": ":js\n\n\nmodule Foo with\n  data class C(x)\n\nFoo.C(123).x\n//│ = 123\n\n(new Foo.C(123)).x\n//│ = 123\n\nlet c = Foo.C\n//│ c = fun C { class: class C }\n\nc(123)\n//│ = C(123)\n\n:e\nnew c(123)\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference.\n//│ ║  l.20: \tnew c(123)\n//│ ║        \t    ^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ = C(123)\n\nnew! c(123)\n//│ = C(123)\n\nobject D extends Foo.C(123) with\n  print(this!x)\n  print(id(this).x)\n//│ > 123\n//│ > 123\n\n:e\nobject D extends Foo.C(123) with\n  print(this.x)\n//│ ╔══[COMPILATION ERROR] Object 'D' does not contain member 'x'\n//│ ║  l.38: \t  print(this.x)\n//│ ╙──      \t        ^^^^^^\n//│ > 123\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/NestedScoped.mls",
    "content": ":js\n\n\n// * NOTE: usually, Scoped blocks are flattened by the IR smart constructors\n\n\n// * Flattened\n:sir\n:sjs\nscope.locally of 42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 42\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ 42\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n:sir\nlet x = 42 in x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x⁰; set x⁰ = 42; x⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n// * Flattened\n:sir\nscope.locally of\n  let x = 42 in x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x¹; set x¹ = 42; x¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n// :sjs\nscope.locally of (\n  let x = 42\n  x\n)\n//│ = 42\n\n\n:sir\n// :sjs\nscope.locally of scope.locally of (\n  let x = 42\n  x\n)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x²; set x² = 42; x²\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n\n:e\nx\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.58: \tx\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nfun foo(x) =\n  let z = 1\n  scope.locally of\n    let y = 1 in x + y + z\n\n\nfoo(1)\n//│ = 3\n\n\n// * Not flattened: in conditional arms\n:sjs\nfun f() =\n  if true then\n    scope.locally of (\n      let a = 4\n      a + 4\n    )\n  else\n    let b = 5\n    b + 9\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f;\n//│ f = function f() {\n//│   let scrut, b;\n//│   scrut = true;\n//│   if (scrut === true) { let a; a = 4; return a + 4 }\n//│   b = 5;\n//│   return b + 9;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nf()\n//│ = 8\n\n\n// * Idem\n:sjs\nfun f() =\n  if false then\n    let a = 4\n    a + 4\n  else\n    scope.locally of (\n      let b = 5\n      b + 9\n    )\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1;\n//│ f1 = function f() {\n//│   let scrut, a;\n//│   scrut = false;\n//│   if (scrut === true) { a = 4; return a + 4 }\n//│   { let b; b = 5; return b + 9; }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nf()\n//│ = 14\n\n\nfun g(x, y, z) =\n  3 + 4 * if\n    x then 0\n    y then 0\n    z then\n      scope.locally of (\n        let a = 1\n        (_ + a)\n      )\n\n\n\nfun foo(x, y) =\n  let z = [1, 2, 3]\n  if not x > z.0 do\n    print(\"rua\")\n  let m = x + y\n  scope.locally of (\n    let w1 = z.1 + m\n    let w2 = z.2 - m\n    if w1 == w2 do\n      print(\"ruarua\")\n  )\n\n\n:ge\nscope.locally()\n//│ ╔══[COMPILATION ERROR] Unsupported form for scope.locally.\n//│ ║  l.154: \tscope.locally()\n//│ ╙──       \t^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:ge\nscope.locally of (let x = 1 in x), (let y = 2 in y)\n//│ ╔══[COMPILATION ERROR] Unsupported form for scope.locally.\n//│ ║  l.162: \tscope.locally of (let x = 1 in x), (let y = 2 in y)\n//│ ╙──       \t^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:e\n:ge\nscope.locally of (let x = 1 in x), (let y = 2 in x)\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.171: \tscope.locally of (let x = 1 in x), (let y = 2 in x)\n//│ ╙──       \t                                                 ^\n//│ ╔══[COMPILATION ERROR] Unsupported form for scope.locally.\n//│ ║  l.171: \tscope.locally of (let x = 1 in x), (let y = 2 in x)\n//│ ╙──       \t^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nlet z = 114\nscope.locally of (\n  let y = 514\n  y\n)\n//│ = 514\n//│ z = 114\n\n\n// :sjs\nlet z = 2\nscope.locally of (\n  let y = () => 1\n  y\n)\n//│ = fun y\n//│ z = 2\n\n\n\n// NOTE: `z2` (bms) should be declared in the same place as `z3`\n:sjs\nfun f(x) =\n  if x then\n    let y = 2\n    scope.locally of (\n      let z = () => 3\n      z\n    )\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2;\n//│ f2 = function f(x4) {\n//│   if (x4 === true) {\n//│     let z2, z3;\n//│     z3 = function z() {\n//│       return 3\n//│     };\n//│     z2 = z3;\n//│     return z2\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n:lift\nscope.locally of scope.locally of (\n  fun h() =\n    fun f() = g()\n    fun g() = f()\n    4\n  3\n)\n//│ = 3\n\n// :sjs\nlet x = 3\n() => x\n//│ = fun\n//│ x = 3\n\n:sjs\nfun f(x) =\n  if x then\n    () => 4\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f3;\n//│ f3 = function f(x5) {\n//│   if (x5 === true) {\n//│     let lambda1;\n//│     lambda1 = (undefined, function () {\n//│       return 4\n//│     });\n//│     return lambda1\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/NestedTypes.mls",
    "content": ":js\n\n\nmodule M with\n  type T = Int\n\nfun f[A] = (x: A) => x\n\nf[M.T](42)\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/NoFreeze.mls",
    "content": ":js\n\n:ssjs\nclass Foo(val x)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ Foo1 = function Foo(x) {\n//│   return globalThis.Object.freeze(new Foo.class(x));\n//│ };\n//│ globalThis.Object.freeze(class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   constructor(x) {\n//│     this.x = x;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"x\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:ssjs\n:noFreeze\nclass Foo(val x)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let Foo3;\n//│ Foo3 = function Foo(x) {\n//│   return (new Foo.class(x));\n//│ };\n//│ (class Foo2 {\n//│   static {\n//│     Foo3.class = this\n//│   }\n//│   constructor(x) {\n//│     this.x = x;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"x\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:ssjs\nlet foo = new Foo(1)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let foo;\n//│ foo = globalThis.Object.freeze(new Foo3.class(1));\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = Foo(1)\n\n:ssjs\n:noFreeze\nlet foo = new Foo(1)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let foo1;\n//│ foo1 = (new Foo3.class(1));\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = Foo(1)\n\n\nset foo.x = 42\n\n:expect 42\nfoo.x\n//│ = 42\n\nimport \"../../mlscript-compile/NoFreeze.mls\"\n\nlet foo = NoFreeze.foo()\n//│ foo = Foo(0)\n\nset foo.x = 42\n\n:expect 42\nfoo.x\n//│ = 42\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/NoModuleCheck.mls",
    "content": ":js\n\nmodule M with\n  fun foo(x) = x + 1\n\n\n:e\nM.\"foo\"(1)\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.8: \tM.\"foo\"(1)\n//│ ╙──     \t^\n//│ = 2\n\n\n:noModuleCheck\nM.\"foo\"(1)\n//│ = 2\n\n\n:e\nfun foo(): module M =\n  let m = M in m\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type M.\n//│ ║  l.22: \t  let m = M in m\n//│ ╙──      \t          ^\n//│ ╔══[COMPILATION ERROR] Expected a module; found non-moduleful block.\n//│ ║  l.22: \t  let m = M in m\n//│ ║        \t          ^^^^^^\n//│ ╙── Function marked as returning a 'module' but not returning a module.\n\n\n:noModuleCheck\nfun foo(): module M =\n  let m = M in m\n\nfoo().foo(1)\n//│ = 2\n\n\nclass Bar(val x)\n\n:e\nlet bar = Bar in new bar(1)\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference.\n//│ ║  l.43: \tlet bar = Bar in new bar(1)\n//│ ║        \t                     ^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ = Bar(1)\n\n\n:noModuleCheck\nlet bar = Bar in new bar(1)\n//│ = Bar(1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ObjectInit.mls",
    "content": ":js\n\n\nfun f = print(A)\nobject A with\n  f // A is not fully initialized yet but can still be accessed\n  val x = 1\n//│ > A {}\n\n// * By contrast:\nfun f = print(A)\nclass Acls with\n  f // A is not accessible at all here\n  val x = 1\nval A = new Acls\n//│ > undefined\n//│ A = Acls { x: 1 }\n\n// * We still need an initialization checker to catch things like this:\nfun f = print(A.x)\nobject A with\n  f\n  val x = 1\n//│ > undefined\n\n\nfun f = print(A, A.x)\nobject A with\n  f\n  val x = 1\n  f\n//│ > A5 {} undefined\n//│ > A5 { x: 1 } 1\n\nf\n//│ > A { x: 1, class: object A } 1\n\nobject A with\n  print(B)\nobject B\n//│ > undefined\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ObjectMethodDebinding.mls",
    "content": ":js\n\n\nobject Test with\n  fun bar = 1\n  fun foo() = bar + 1\n\n:e\nlet f = Test.foo\n//│ ╔══[COMPILATION ERROR] [debinding error] Method 'foo' cannot be accessed without being called.\n//│ ║  l.9: \tlet f = Test.foo\n//│ ╙──     \t            ^^^^\n//│ f = fun foo\n\n// TODO make this a type error\n// :e\n:re\nlet f = id(Test).foo\n//│ ═══[RUNTIME ERROR] Error: [debinding error] Method 'foo' of class 'Test' was accessed without being called.\n//│ f = undefined\n\n// * Note that dynamic member accesses are not checked against debinding:\nlet f = Test.(\"foo\")\n//│ f = fun foo\n\n:re\nf()\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'bar')\n\n\n// * I tried compiling selections to essentially the following,\n// * but it doesn't work since many things in JS are \"functions\"\n// * (and notably may have fields, which are not preserved by `bind`):\n\nlet g = if f is Function then f.bind(Test) else f\n//│ g = fun bound foo\n\ng()\n//│ = 2\n\n\n// * TODO we should probably compile the above as:\n\nobject Test with\n  fun bar = 1\n  fun foo() = Test.bar + 1\n\nlet f = Test.(\"foo\")\n//│ f = fun foo\n\nf()\n//│ = 2\n\n\n// * Which also works well no matter where the object is defined:\n\nfun test() =\n  object Test with\n    fun bar = 1\n    fun foo() = Test.bar + 1\n  [Test]\n\nlet f = test().0.(\"foo\")\n//│ f = fun foo\n\nf()\n//│ = 2\n\n\n// * However, it would disable open recursion upon object inheritance (eg `class C extends Test with ...`).\n// * But it would be better to require open recursion to be explicitly indicated by `virtual` anyway.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Open.mls",
    "content": ":js\n\n\nmodule Foo with\n  val x = 1\n  val y = 2\n  val z = 3\n\n:sjs\nopen Foo { x }\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nopen Foo { x, y }\n\nx + y\n//│ = 3\n\n:e\nz\n//│ ╔══[COMPILATION ERROR] Name not found: z\n//│ ║  l.21: \tz\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nopen Foo { a }\n//│ ╔══[COMPILATION ERROR] Module 'Foo' does not contain member 'a'\n//│ ║  l.28: \topen Foo { a }\n//│ ╙──      \t           ^\n\n\nopen Bar { y, Baz }\nopen Baz { b }\nmodule Bar with\n  val x = 1\n  val y = 2\n  module Baz with\n    val a = 4\n    val b = 5\n  open Baz { a }\n  fun f() = [a, b, y]\n\n\nval str = \"oops\"\n//│ str = \"oops\"\n\nopen str { length, oops }\n\nlength\n//│ = 4\n\noops === ()\n//│ = false\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/OpenJS.mls",
    "content": ":js\n\n\nopen console { log }\nopen Math { pow }\n\n\nlog(123 pow(2))\n//│ > 15129\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/OpenWildcard.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Option.mls\"\n\nmodule OtherModule with\n  val None = 123\n\n\n:sjs\nopen Option\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nNone isDefined()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Option.isDefined(Option.None)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = false\n\nSome(1) isDefined()\n//│ = true\n\nNone === Option.None\n//│ = true\n\n\nfun none() = None\n\nopen OtherModule\n\nNone === Option.None\n//│ = false\n\nnone() === Option.None\n//│ = true\n\n\nopen Option\nfun none() = None\nconsole.log(None)\nopen OtherModule\nconsole.log(None)\nnone()\n//│ > None {}\n//│ > 123\n//│ = None\n\n\n// * `open` statements are hygienic and are not affected by redefinitions\n\n:sjs\nval Option = \"Oops\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Option1; Option1 = \"Oops\";\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ Option = \"Oops\"\n\n:sjs\nSome(123)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Option.Some(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Some(123)\n\nmodule Option with\n  val None = 123\n\n:sjs\nopen Option\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nSome\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Option.Some\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun Some { class: class Some }\n\n:sjs\nNone\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Option3.None\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/OptMatch.mls",
    "content": ":js\n\n\ndata class Some(value)\nobject None\n\n\n:sjs\nfun isDefined(x) = if x is\n  Some then true\n  None then false\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let isDefined;\n//│ isDefined = function isDefined(x) {\n//│   if (x instanceof Some1.class) {\n//│     return true\n//│   } else if (x instanceof None1.class) {\n//│     return false\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nisDefined(Some(1))\n//│ = true\n\nisDefined(None)\n//│ = false\n\n\n:sjs\nval isDefined = case\n  Some(_) then true\n  None    then false\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let isDefined1, lambda;\n//│ lambda = (undefined, function (caseScrut) {\n//│   if (caseScrut instanceof Some1.class) {\n//│     return true\n//│   } else if (caseScrut instanceof None1.class) {\n//│     return false\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ isDefined1 = lambda;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ isDefined = fun\n\nisDefined(Some(1))\n//│ = true\n\nisDefined(None)\n//│ = false\n\n\nval isDefined = x => if x is\n  Some(_) then true\n  None    then false\n//│ isDefined = fun\n\nisDefined(Some(1))\n//│ = true\n\nisDefined(None)\n//│ = false\n\n\nmodule Foo with\n  data class Other(v)\n\nval isOther = x => if x is\n  Foo.Other(_) then true\n  None    then false\n//│ isOther = fun\n\n\nfun keepIfGreaterThan(x, y) =\n  if x > y then Some(x) else None\n\n\n1 keepIfGreaterThan(0) isDefined()\n//│ = true\n\n1\n  keepIfGreaterThan(0)\n  isDefined()\n  console.log()\n//│ > true\n\n1\n  \\ keepIfGreaterThan(0)\n//│ = Some(1)\n\n\n1\n  \\ keepIfGreaterThan(0)\n  \\ isDefined()\n  \\ console.log()\n//│ > true\n\n\n1\n  |> (keepIfGreaterThan(_, 0))\n  |> (isDefined(_))\n//│ = true\n\n1\n  |> {keepIfGreaterThan(_, 0)}\n  |> {isDefined(_)}\n//│ = true\n\n1\n  |>\n    keepIfGreaterThan(_, 0)\n  |>\n    isDefined(_)\n//│ = true\n\n\nlet isDefined2 = _ is Some\n//│ isDefined2 = fun isDefined2\n\nSome(1) isDefined2()\n//│ = true\n\nSome(1) |> isDefined2\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ParamClasses.mls",
    "content": ":js\n\n:global\n:sjs\n\n\ndata class Foo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ Foo1 = function Foo() {\n//│   return globalThis.Object.freeze(new Foo.class());\n//│ };\n//│ (class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", []]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nFoo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun Foo { class: class Foo }\n\nFoo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo1()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo()\n\nFoo.class\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo1.class\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class Foo\n\n\ndata class Foo(a)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo3;\n//│ Foo3 = function Foo(a) {\n//│   return globalThis.Object.freeze(new Foo.class(a));\n//│ };\n//│ (class Foo2 {\n//│   static {\n//│     Foo3.class = this\n//│   }\n//│   constructor(a) {\n//│     this.a = a;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"a\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nFoo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo3\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun Foo { class: class Foo }\n\nFoo(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo3(1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo(1)\n\nFoo(1).a\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = Foo3(1); tmp.a\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\nfun foo(y) = Foo(y)\nfoo(27)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo, y, inlinedVal;\n//│ foo = function foo(y1) { return Foo3(y1) };\n//│ y = 27;\n//│ inlinedVal = Foo3(y);\n//│ inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo(27)\n\n\ndata class Foo(a, b)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo5;\n//│ Foo5 = function Foo(a, b) {\n//│   return globalThis.Object.freeze(new Foo.class(a, b));\n//│ };\n//│ (class Foo4 {\n//│   static {\n//│     Foo5.class = this\n//│   }\n//│   constructor(a, b) {\n//│     this.a = a;\n//│     this.b = b;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"a\", \"b\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet foo = Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo1; foo1 = Foo5;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = fun Foo { class: class Foo }\n\nlet f = foo(1, 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f; f = runtime.safeCall(foo1(1, 2));\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = Foo(1, 2)\n\nlet f = new! foo(1, 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1; f1 = globalThis.Object.freeze(new foo1(1, 2));\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = Foo(1, 2)\n\nf.a\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f1.a\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\nf.b\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f1.b\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\nlet f = Foo(1, 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2; f2 = Foo5(1, 2);\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = Foo(1, 2)\n\nf.a\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f2.a\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\nf.b\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ f2.b\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\nFoo(print(1), print(2))\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp1, tmp2; tmp1 = Predef.print(1); tmp2 = Predef.print(2); Foo5(tmp1, tmp2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n//│ > 2\n//│ = Foo((), ())\n\n\ndata class Inner(c) with\n  fun i1(d) = c + d\n  print(c)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Inner1;\n//│ Inner1 = function Inner(c) {\n//│   return globalThis.Object.freeze(new Inner.class(c));\n//│ };\n//│ (class Inner {\n//│   static {\n//│     Inner1.class = this\n//│   }\n//│   constructor(c) {\n//│     this.c = c;\n//│     Predef.print(this.c);\n//│   }\n//│   i1(d) {\n//│     return this.c + d\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Inner\", [\"c\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet i = new Inner(100)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let i; i = globalThis.Object.freeze(new Inner1.class(100));\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 100\n//│ i = Inner(100)\n\ni.i1(20)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(i.i1(20))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 120\n\n\n// * This is strange, but does not need to be an error\nclass Foo(x, val y, z, val z, z) with\n  let x = 1\n  let y += 1\n  print(\"x = \" + x)\n  print(\"y = \" + y)\n  print(\"this.y = \" + this.y)\n  print(\"z = \" + z)\n  print(\"this.z = \" + this.z)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo7;\n//│ Foo7 = function Foo(x, y1, z, z1, z2) {\n//│   return globalThis.Object.freeze(new Foo.class(x, y1, z, z1, z2));\n//│ };\n//│ (class Foo6 {\n//│   static {\n//│     Foo7.class = this\n//│   }\n//│   constructor(x, y1, z, z1, z2) {\n//│     let tmp3, tmp4, tmp5, tmp6, tmp7;\n//│     this.y = y1;\n//│     this.z = z1;\n//│     this.#z1 = z2;\n//│     this.#x1 = 1;\n//│     this.#y = this.y + 1;\n//│     tmp3 = \"x = \" + this.#x1;\n//│     Predef.print(tmp3);\n//│     tmp4 = \"y = \" + this.#y;\n//│     Predef.print(tmp4);\n//│     tmp5 = \"this.y = \" + this.y;\n//│     Predef.print(tmp5);\n//│     tmp6 = \"z = \" + this.#z1;\n//│     Predef.print(tmp6);\n//│     tmp7 = \"this.z = \" + this.z;\n//│     Predef.print(tmp7);\n//│   }\n//│   #x;\n//│   #z;\n//│   #z1;\n//│   #x1;\n//│   #y;\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [null, \"y\", null, \"z\", null]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nFoo(10, 20, 30, 40, 50)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo7(10, 20, 30, 40, 50)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > x = 1\n//│ > y = 21\n//│ > this.y = 20\n//│ > z = 50\n//│ > this.z = 40\n//│ = Foo(_, 20, _, 40, _)\n\n\n:e\nclass Foo(val z, val z)\n//│ ╔══[COMPILATION ERROR] Duplicate definition of member named 'z'.\n//│ ╟── Defined at: \n//│ ║  l.262: \tclass Foo(val z, val z)\n//│ ║         \t              ^\n//│ ╟── Defined at: \n//│ ║  l.262: \tclass Foo(val z, val z)\n//│ ╙──       \t                     ^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo9;\n//│ Foo9 = function Foo(z, z1) {\n//│   return globalThis.Object.freeze(new Foo.class(z, z1));\n//│ };\n//│ (class Foo8 {\n//│   static {\n//│     Foo9.class = this\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"z\", \"z\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nFoo(1, 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo9(1, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo(undefined, undefined)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/PartialApps.mls",
    "content": ":js\n\n\nfun foo(x, y, z) = [x, y, z]\n\nlet f = foo(1, _, 3)\n//│ f = fun f\n\nf(2)\n//│ = [1, 2, 3]\n\n:sjs\nlet f = foo(1, _, _)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2, f3; f3 = function f(_0, _1) { return foo(1, _0, _1) }; f2 = f3;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\nf(2, 3)\n//│ = [1, 2, 3]\n\nlet g = f(_, 3)\n//│ g = fun g\n\ng(2)\n//│ = [1, 2, 3]\n\nfoo(_, _, 3) of 1, 2\n//│ = fun\n\n{foo(_, _, 3)} of 1, 2\n//│ = [1, 2, 3]\n\n{foo(_, _, 3)}(1, 2)\n//│ = [1, 2, 3]\n\n\nfun foo2(x, y, z)(a, b) = [x, y, z, a, b]\n\n{foo2(_, _, 3)(4, _)}(1, 2, 5)\n//│ = [1, 2, 3, 4, 5]\n\n\n// :sjs\nlet f = [_]\nf(27)\n//│ = [27]\n//│ f = fun f\n\n// :sjs\nlet f = [_ + 1]\nf.0(27)\n//│ = 28\n//│ f = [fun]\n\nlet f = foo(..._)\nf([1, 2, 3])\n//│ = [1, 2, 3]\n//│ f = fun f\n\nlet f = [..._]\nf([1, 2, 3])\n//│ = [1, 2, 3]\n//│ f = fun f\n\n// :sjs\nlet f = [..._]\nf([])\n//│ = []\n//│ f = fun f\n\n\nlet h = _ - 2\n//│ h = fun h\n\nh(1)\n//│ = -1\n\n\n:sjs\nlet i = _(0, 1, _)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let i, i1; i1 = function i(_03, _13) { return runtime.safeCall(_03(0, 1, _13)) }; i = i1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ i = fun i\n\ni(print, 2)\n//│ > 0 1 2\n\n:re\ni(print)(2)\n//│ ═══[RUNTIME ERROR] Error: Function 'i' expected 2 arguments but got 1\n\n// :re\ni((x, y, z) => x + y + z, 2)\n//│ = 3\n\n// :re\ni((...args) => [...args], _)(2)\n//│ = fun\n\n\n123 |> (_ + 1)\n//│ = 124\n\n// * Note: missing parens\n123 |> _ + 1\n//│ = fun\n\n123 |> ((_ + 1) >> (_ * 2))\n//│ = 248\n\n:re\n123 |> (_ + 1 >> _ * 2)\n//│ ═══[RUNTIME ERROR] Error: Function expected 2 arguments but got 1\n\n(_ + 1 + _ * 2) of 123, 456\n//│ = 1036\n\n// * Note: lack of parens\nlet f = _ * 2 + 1 |> print in f(3)\n//│ > 7\n\n123 |> (_ + 1) |> (_ * 2)\n//│ = 248\n\n(_ * 2) <| (_ + 1) <| 123\n//│ = 248\n\n(_ + 1) >> (_ * 2) <| 123\n//│ = 248\n\n\nlet j = _.x in j(x: 123)\n//│ = 123\n\nlet j = _.x(123) in j(x: print)\n//│ > 123\n\n\nlet j = _.x(1, _) in j((x: tuple), 0)\n//│ = [1, 0]\n\n// ie\nlet j = (obj, arg) => obj.x(1, arg) in j((x: tuple), 0)\n//│ = [1, 0]\n\n// TODO: really support this?\nlet j = _.x.y(1, _) in j((x: y: tuple), 0)\n//│ = [1, 0]\n\n\ndata class C(a, b, c)\n\n2 |> C(1, _, 3) |> print\n//│ = fun\n\n2 |> (C(1, _, 3)) |> print\n//│ > C(1, 2, 3)\n\n2 |> {C(1, _, 3)} |> print\n//│ > C(1, 2, 3)\n\n2 |> {C(1, _, 3)} !> print\n//│ > C(1, 2, 3)\n//│ = C(1, 2, 3)\n\n{2 |> {C(1, _, 3)}} !> print\n//│ > C(1, 2, 3)\n//│ = C(1, 2, 3)\n\n2 |> {C(1, _, 3)} !> {print(_)} |> {print(_)}\n//│ > C(1, 2, 3)\n//│ > C(1, 2, 3)\n\n(2 |> (new C(1, _, 3))) |> print\n//│ > C(1, 2, 3)\n\n2 |> (new C(1, _, 3)) |> print\n//│ > C(1, 2, 3)\n\n\n(_ - _) of 1, 2\n//│ = -1\n\n// * Note: missing parens\n_ - _ of 1, 2\n//│ = fun\n\n\n(_ - 2) <| 1\n//│ = -1\n\n1 |> (_ - 2)\n//│ = -1\n\n1\n|> (_ - 2)\n//│ = -1\n\n:pe\n|> 1\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.202: \t|> 1\n//│ ╙──       \t   ^\n//│ = fun pipeInto\n\n:e\n:re\n|> (1)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.210: \t|> (1)\n//│ ╙──       \t   ^^^\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n|> (1, _ - 2)\n//│ = -1\n\n1\n  |> (_ - 2)\n//│ = -1\n\n1 |>\n  _ - 2\n//│ = -1\n\n:sjs\n1 \\ (_ - 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda39; lambda39 = (undefined, function (_05) { return _05 - 2 }); Predef.passTo(1, lambda39)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n:sjs\n1 \\ (_ - 2)()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda40;\n//│ lambda40 = (undefined, function (_05) { return _05 - 2 });\n//│ Predef.passTo(1, lambda40)()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = -1\n\n1 \\ (_ - _)(2)\n//│ = -1\n\n\n// `_` here is interpreted as a UCS default case...\n:sjs\n:w\nlet f = if _ then 1 else 0\n//│ ╔══[WARNING] This catch-all clause makes the following branches unreachable.\n//│ ║  l.250: \tlet f = if _ then 1 else 0\n//│ ║         \t             ^^^^^^\n//│ ╟── This branch is unreachable.\n//│ ║  l.250: \tlet f = if _ then 1 else 0\n//│ ╙──       \t                    ^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f15, tmp20; tmp20 = 1; f15 = tmp20;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = 1\n\n:sjs\nfun f(x) =\n  if x ==\n    0 then 1\n    _ then 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f16;\n//│ f16 = function f(x3) {\n//│   let scrut;\n//│   scrut = Predef.equals(x3, 0);\n//│   if (scrut === true) { return 1 }\n//│   return 2;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/PlainClasses.mls",
    "content": ":js\n\n:global\n:sjs\n\n\nclass Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ (class Foo {\n//│   static {\n//│     Foo1 = this\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nFoo is Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ if (Foo1 instanceof Foo1) { true } else { false }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = false\n\n(new Foo) is Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut;\n//│ scrut = globalThis.Object.freeze(new Foo1());\n//│ if (scrut instanceof Foo1) { true } else { false }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\nnew Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new Foo1())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo\n\nnew Foo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new Foo1())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo\n\nFoo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Foo1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class Foo\n\n:re\nFoo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(Foo1())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Class constructor Foo cannot be invoked without 'new'\n\n\ndata class Foo with { print(\"hi\") }\nprint(\"ok\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo3;\n//│ (class Foo2 {\n//│   static {\n//│     Foo3 = this\n//│   }\n//│   constructor() {\n//│     Predef.print(\"hi\");\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ Predef.print(\"ok\")\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > ok\n\nfun test() =\n  data class Foo with { print(\"hi\") }\n  print(\"ok\")\n  Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test;\n//│ test = function test() {\n//│   let Foo5;\n//│   (class Foo4 {\n//│     static {\n//│       Foo5 = this\n//│     }\n//│     constructor() {\n//│       Predef.print(\"hi\");\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│   });\n//│   Predef.print(\"ok\");\n//│   return Foo5\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet t = test()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let t; t = test();\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > ok\n//│ t = class Foo\n\n:e\nnew t\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference.\n//│ ║  l.108: \tnew t\n//│ ║         \t    ^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new t())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > hi\n//│ = Foo\n\nnew! t\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new t())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > hi\n//│ = Foo\n\n:e\nnew t()\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference.\n//│ ║  l.127: \tnew t()\n//│ ║         \t    ^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new t())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > hi\n//│ = Foo\n\nnew! t()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new t())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > hi\n//│ = Foo\n\n\nclass Foo with\n  val x = 1\n  let y = x + 1\n  fun z() = y + x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo6;\n//│ (class Foo5 {\n//│   static {\n//│     Foo6 = this\n//│   }\n//│   constructor() {\n//│     this.x = 1;\n//│     this.#y = this.x + 1;\n//│   }\n//│   #y;\n//│   z() {\n//│     return this.#y + this.x\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nclass Foo with\n  val x1 = 1\n  val x2 = 2\n  let y1 = 3\n  let y2 = 4\n  fun z1() = 5\n  fun z2() = 6\n  print(\"hello\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo8;\n//│ (class Foo7 {\n//│   static {\n//│     Foo8 = this\n//│   }\n//│   constructor() {\n//│     this.x1 = 1;\n//│     this.x2 = 2;\n//│     Predef.print(\"hello\");\n//│   }\n//│   #y1;\n//│   #y2;\n//│   z1() {\n//│     return 5\n//│   } \n//│   z2() {\n//│     return 6\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nclass Foo with\n  val x = 1\n  fun foo(y) = x + y\n  fun bar(z) = foo(z) + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo10;\n//│ (class Foo9 {\n//│   static {\n//│     Foo10 = this\n//│   }\n//│   constructor() {\n//│     this.x = 1;\n//│   }\n//│   foo(y) {\n//│     return this.x + y\n//│   } \n//│   bar(z) {\n//│     let tmp;\n//│     tmp = this.foo(z);\n//│     return tmp + 1\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet a = new Foo\nprint(a.x)\nprint(a.foo(1))\nprint(a.bar(1))\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let a, tmp, tmp1;\n//│ a = globalThis.Object.freeze(new Foo10());\n//│ Predef.print(a.x);\n//│ tmp = runtime.safeCall(a.foo(1));\n//│ Predef.print(tmp);\n//│ tmp1 = runtime.safeCall(a.bar(1));\n//│ Predef.print(tmp1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n//│ > 2\n//│ > 3\n//│ a = Foo { x: 1 }\n\n\n\n:e\nclass Foo with\n  val x = 1\n  val x = 2\n//│ ╔══[COMPILATION ERROR] Multiple definitions of symbol 'x'\n//│ ╟── defined here\n//│ ║  l.251: \t  val x = 1\n//│ ║         \t  ^^^^^^^^^\n//│ ╟── defined here\n//│ ║  l.252: \t  val x = 2\n//│ ╙──       \t  ^^^^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo12;\n//│ (class Foo11 {\n//│   static {\n//│     Foo12 = this\n//│   }\n//│   constructor() {\n//│     this.x = 1;\n//│     this.x = 2;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:e\nclass Foo with\n  val x = 1\n  let x = 2\n//│ ╔══[COMPILATION ERROR] Name 'x' is already used\n//│ ║  l.278: \t  let x = 2\n//│ ║         \t      ^^^^^\n//│ ╟── by a member declared in the same block\n//│ ║  l.277: \t  val x = 1\n//│ ╙──       \t  ^^^^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo14;\n//│ (class Foo13 {\n//│   static {\n//│     Foo14 = this\n//│   }\n//│   constructor() {\n//│     this.x = 1;\n//│   }\n//│   #x;\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n\n\n// ——— TODO ———\n\n\n:e\nclass Foo with val x = 1\n//│ ╔══[COMPILATION ERROR] Illegal body of class definition (should be a block; found term definition).\n//│ ║  l.308: \tclass Foo with val x = 1\n//│ ╙──       \t               ^^^^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo16;\n//│ (class Foo15 {\n//│   static {\n//│     Foo16 = this\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/PredefUsage.mls",
    "content": ":js\n\n\nnot(true)\n//│ = false\n\nnot(false)\n//│ = true\n\n\nprint(12)\n//│ > 12\n\n12 |>\n  print(_)\n//│ > 12\n\n:sjs\n12 |> print\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Predef.pipeInto(12, Predef.print)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 12\n\n12 |>\n  x => print(x)\n//│ > 12\n\n12 |> (x => print(x))\n//│ > 12\n\n12 |> (x => console.log(String(x)))\n//│ > 12\n\n\n42 id() id() print()\n//│ > 42\n\n\nPredef.print(123)\n//│ > 123\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Primes.mls",
    "content": ":js\n\n\nlet x = 1\n//│ x = 1\n\n:sjs\nlet x' = 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x$_; x$_ = 2;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ x' = 2\n\nx'\n//│ = 2\n\n\n:e\nobject Foo with\n  val x' = 0\n//│ ╔══[COMPILATION ERROR] Illegal member value name: 'x''\n//│ ║  l.20: \t  val x' = 0\n//│ ║        \t      ^^\n//│ ╙── Member names must start with a letter or underscore, followed by letters, digits, or underscores.\n\n:e\n:re\nFoo.x'\n//│ ╔══[COMPILATION ERROR] Object 'Foo' does not contain member 'x''\n//│ ║  l.28: \tFoo.x'\n//│ ╙──      \t^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x'' yielded 'undefined'\n\nFoo.(\"x'\")\n\n:e\nobject Foo with\n  mut val x' = 0\n//│ ╔══[COMPILATION ERROR] Illegal member mutable value name: 'x''\n//│ ║  l.38: \t  mut val x' = 0\n//│ ║        \t          ^^\n//│ ╙── Member names must start with a letter or underscore, followed by letters, digits, or underscores.\n\n:e\n:re\nset Foo.x' += 1\n//│ ╔══[COMPILATION ERROR] Object 'Foo' does not contain member 'x''\n//│ ║  l.46: \tset Foo.x' += 1\n//│ ╙──      \t    ^^^^^^\n//│ ╔══[COMPILATION ERROR] Object 'Foo' does not contain member 'x''\n//│ ║  l.46: \tset Foo.x' += 1\n//│ ╙──      \t    ^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x'' yielded 'undefined'\n\nFoo.(\"x'\")\n\n\n:e\nclass Foo with\n  fun f' = 1\n//│ ╔══[COMPILATION ERROR] Illegal member function name: 'f''\n//│ ║  l.60: \t  fun f' = 1\n//│ ║        \t      ^^\n//│ ╙── Member names must start with a letter or underscore, followed by letters, digits, or underscores.\n\n:e\nclass Foo with\n  class F'\n//│ ╔══[COMPILATION ERROR] Illegal member class name: 'F''\n//│ ║  l.68: \t  class F'\n//│ ║        \t        ^^\n//│ ╙── Member names must start with a letter or underscore, followed by letters, digits, or underscores.\n\n:e\nclass Foo with\n  object F'\n//│ ╔══[COMPILATION ERROR] Illegal member object name: 'F''\n//│ ║  l.76: \t  object F'\n//│ ║        \t         ^^\n//│ ╙── Member names must start with a letter or underscore, followed by letters, digits, or underscores.\n\n:e\nclass Foo with\n  module F'\n//│ ╔══[COMPILATION ERROR] Illegal member module name: 'F''\n//│ ║  l.84: \t  module F'\n//│ ║        \t         ^^\n//│ ╙── Member names must start with a letter or underscore, followed by letters, digits, or underscores.\n\nclass Foo with\n  let f' = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Pwd.mls",
    "content": ":js\n\n\n:sjs\nlet folderName1 = process.env.PWD.split(\"/\").pop()\nin let folderName2 = process.cwd().split(\"/\").pop()\nin folderName2 === folderName1 || folderName2 === \"shared\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let folderName1, folderName2, tmp, tmp1, tmp2, tmp3;\n//│ tmp = runtime.safeCall(globalThis.process.env.PWD.split(\"/\"));\n//│ folderName1 = runtime.safeCall(tmp.pop());\n//│ tmp1 = runtime.safeCall(globalThis.process.cwd());\n//│ tmp2 = runtime.safeCall(tmp1.split(\"/\"));\n//│ folderName2 = runtime.safeCall(tmp2.pop());\n//│ tmp3 = folderName2 === folderName1;\n//│ if (tmp3 === false) { folderName2 === \"shared\" } else { true }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/QQImport.mls",
    "content": ":js\n:qq\n\n\n\nmeta.print\n//│ = fun print\n\n\nmeta.print(`42)\n//│ > 42\n\n\nmeta.print(`+)\n//│ > +\n\n\nmeta.print(`1 `+ `2)\n//│ > (+)(1, 2)\n\n\nmeta.print(x `=> x)\n//│ > (x_0) =>\n//│ >   x_0\n\n\nmeta.print((x, y) `=> x `+ y)\n//│ > (x_0, y_0) =>\n//│ >   (+)(x_0, y_0)\n\n\nmeta.print(`let x = `42 `in x)\n//│ > let x_0\n//│ > x_0 = 42\n//│ > x_0\n\n\nmeta.print(`if `true then `true else `false)\n//│ > if \n//│ >   let scrut_0 = true\n//│ >   scrut_0 is true then true\n//│ >   else false\n\n\nmeta.print(x `=> `if x `=== `0.0 then `1.0 else x)\n//│ > (x_0) =>\n//│ >   if \n//│ >     let scrut_0 = (===)(x_0, 0)\n//│ >     scrut_0 is true then 1\n//│ >     else x_0\n\n\nimport \"../../mlscript-compile/QuoteExample2.mls\"\n\n\nQuoteExample2.codegen()\n\n\nimport \"../../mlscript-compile/quotes/QuoteFoo.mls\"\n\nQuoteFoo.res\n//│ = 2\n\n\nimport \"../../mlscript-compile/quotes/QuoteInc.mls\"\n\n\nQuoteInc.res(42)\n//│ = 43\n\n\nimport \"../../mlscript-compile/CSP.mls\"\n\n\nmeta.codegen(CSP.foo(), \"./hkmc2/shared/src/test/mlscript-compile/quotes/CSPFoo.mls\")\n\n\nimport \"../../mlscript-compile/quotes/CSPFoo.mls\"\n\n\nCSPFoo.res\n//│ = 124\n\n\nmeta.codegen(CSP.bar(), \"./hkmc2/shared/src/test/mlscript-compile/quotes/CSPBar.mls\")\n\n\nimport \"../../mlscript-compile/quotes/CSPBar.mls\"\n\n\nCSPBar.res\n//│ = 1\n\n\nmeta.codegen(CSP.baz(), \"./hkmc2/shared/src/test/mlscript-compile/quotes/CSPBaz.mls\")\n\n\nimport \"../../mlscript-compile/quotes/CSPBaz.mls\"\n\nCSPBaz.res\n//│ = 42\n\n\nQuoteExample2.genCubic()\n\n\nimport \"../../mlscript-compile/quotes/Cubic.mls\"\n\nlet cubic = Cubic.res\ncubic(8)\n//│ = 512\n//│ cubic = fun\n\n\nQuoteExample2.genGib12()\n\n\nimport \"../../mlscript-compile/quotes/Gib12.mls\"\n\n\nlet gib12 = Gib12.res\ngib12(0, 1)\n//│ = 144\n//│ gib12 = fun\n\n\nQuoteExample2.genSafeDiv()\n\n\nimport \"../../mlscript-compile/quotes/SafeDiv.mls\"\n\nlet safeDiv = SafeDiv.res\n//│ safeDiv = fun\n\nsafeDiv(10, 3, 0)\n//│ = 3.3333333333333335\n\nsafeDiv(10, 0, -1)\n//│ = -1\n\n\nQuoteExample2.genOpened()\n\nimport \"../../mlscript-compile/quotes/Opened.mls\"\n\nOpened.res\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Quasiquotes.mls",
    "content": ":js\n:qq\n\n\n`42\n//│ = Lit(42)\n\n\n`3.14\n//│ = Lit(3.14)\n\n\n`true\n//│ = Lit(true)\n\n\n`\"abc\"\n//│ = Lit(\"abc\")\n\n\n`+\n//│ = Builtin(\"+\")\n\n\n`1 `+ `2\n//│ = App(Builtin(\"+\"), Tup([Lit(1), Lit(2)]))\n\n\nx `=> x\n//│ = Lam([Symbol(\"x\")], Ref(Symbol(\"x\")))\n\n\n:sjs\nx `=>\n  print(x)\n  x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x1, tmp6, tmp7, arr2;\n//│ tmp6 = globalThis.Object.freeze(new Term.Symbol(\"x\"));\n//│ x1 = globalThis.Object.freeze(new Term.Ref(tmp6));\n//│ Predef.print(x1);\n//│ arr2 = globalThis.Object.freeze([\n//│   tmp6\n//│ ]);\n//│ tmp7 = x1;\n//│ globalThis.Object.freeze(new Term.Lam(arr2, tmp7))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > Ref(Symbol(\"x\"))\n//│ = Lam([Symbol(\"x\")], Ref(Symbol(\"x\")))\n\n\nlet f = x `=> x `+ `1\n//│ f = Lam([Symbol(\"x\")], App(Builtin(\"+\"), Tup([Ref(Symbol(\"x\")), Lit(1)])))\n\n\nf`(`0)\n//│ = App(\n//│   Lam([Symbol(\"x\")], App(Builtin(\"+\"), Tup([Ref(Symbol(\"x\")), Lit(1)]))),\n//│   Tup([Lit(0)])\n//│ )\n\n\n`let x = `42 `in x\n//│ = Blk(\n//│   [LetDecl(Symbol(\"x\")), DefineVar(Symbol(\"x\"), Lit(42))],\n//│   Ref(Symbol(\"x\"))\n//│ )\n\n\n`let x = `42 `in print(x); x\n//│ > Ref(Symbol(\"x\"))\n//│ = Blk(\n//│   [LetDecl(Symbol(\"x\")), DefineVar(Symbol(\"x\"), Lit(42))],\n//│   Ref(Symbol(\"x\"))\n//│ )\n\n\n:sjs\n`if `true then `true else `false\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut, tmp28, tmp29, tmp30, tmp31, tmp32, tmp33, tmp34, tmp35, tmp36, tmp37, tmp38;\n//│ tmp28 = globalThis.Object.freeze(new Term.Symbol(\"scrut\"));\n//│ scrut = globalThis.Object.freeze(new Term.Ref(tmp28));\n//│ tmp29 = globalThis.Object.freeze(new Term.Lit(true));\n//│ tmp32 = scrut;\n//│ tmp33 = globalThis.Object.freeze(new Term.LitPattern(true));\n//│ tmp38 = globalThis.Object.freeze(new Term.Lit(true));\n//│ tmp34 = globalThis.Object.freeze(new Term.Else(tmp38));\n//│ tmp35 = globalThis.Object.freeze(new Term.Branch(tmp32, tmp33, tmp34));\n//│ tmp37 = globalThis.Object.freeze(new Term.Lit(false));\n//│ tmp36 = globalThis.Object.freeze(new Term.Else(tmp37));\n//│ tmp30 = globalThis.Object.freeze(new Term.Cons(tmp35, tmp36));\n//│ tmp31 = globalThis.Object.freeze(new Term.Let(tmp28, tmp29, tmp30));\n//│ globalThis.Object.freeze(new Term.IfLike(Term.Keyword.If, tmp31))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = IfLike(\n//│   If,\n//│   Let(\n//│     Symbol(\"scrut\"),\n//│     Lit(true),\n//│     Cons(\n//│       Branch(Ref(Symbol(\"scrut\")), LitPattern(true), Else(Lit(true))),\n//│       Else(Lit(false))\n//│     )\n//│   )\n//│ )\n\n\nx `=> `if x `=== `0.0 then `1.0 else x\n//│ = Lam(\n//│   [Symbol(\"x\")],\n//│   IfLike(\n//│     If,\n//│     Let(\n//│       Symbol(\"scrut\"),\n//│       App(Builtin(\"===\"), Tup([Ref(Symbol(\"x\")), Lit(0)])),\n//│       Cons(\n//│         Branch(Ref(Symbol(\"scrut\")), LitPattern(true), Else(Lit(1))),\n//│         Else(Ref(Symbol(\"x\")))\n//│       )\n//│     )\n//│   )\n//│ )\n\n:fixme // TODO: error doesn't make much sense (see https://github.com/hkust-taco/mlscript/pull/368#discussion_r2635074722)\nx `=> `if x `== `0.0 then `1.0 else x\n//│ ╔══[COMPILATION ERROR] Cross-stage reference to Predef.equals is only allowed in compiled files due to the lack of `import.meta` in REPL mode.\n//│ ║  l.126: \tx `=> `if x `== `0.0 then `1.0 else x\n//│ ╙──       \t             ^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// We cannot quote a symbol from another file here due to the lack of `import.meta` in REPL mode.\n:ge\n`id`(`42)\n//│ ╔══[COMPILATION ERROR] Cross-stage reference to Predef.id is only allowed in compiled files due to the lack of `import.meta` in REPL mode.\n//│ ║  l.134: \t`id`(`42)\n//│ ╙──       \t ^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nfun id(x) = x\n\n`id`(`42)\n//│ = App(fun id, Tup([Lit(42)]))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/RandomStuff.mls",
    "content": ":js\n\n\n// * Note that this is not currently treated as tail-recursive (for dumb reasons)\n:sjs\nfun foo() = if false do foo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo;\n//│ foo = function foo() {\n//│   let scrut;\n//│   scrut = false;\n//│   if (scrut === true) { foo(); return runtime.Unit }\n//│   return runtime.Unit;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n// * ...but this is (so it's tailrec-optimized)\n:sjs\nfun foo() = if false do return foo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo1;\n//│ foo1 = function foo() {\n//│   loopLabel: while (true) {\n//│     let scrut;\n//│     scrut = false;\n//│     if (scrut === true) { continue loopLabel }\n//│     return runtime.Unit;\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nfun foo() = foo()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo2; foo2 = function foo() { loopLabel: while (true) { continue loopLabel; } };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\ndata class Foo(x) with\n  class Bar with\n    val y = x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ Foo1 = function Foo(x) {\n//│   return globalThis.Object.freeze(new Foo.class(x));\n//│ };\n//│ (class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   constructor(x) {\n//│     this.x = x;\n//│     const this$Foo = this;\n//│     (class Bar {\n//│       static {\n//│         this$Foo.Bar = this\n//│       }\n//│       constructor() {\n//│         this.y = this$Foo.x;\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"Bar\"]; \n//│     });\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"x\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\nfun foo() =\n  fun bar() = bar()\n  bar()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo3; foo3 = function foo() { let bar; bar = function bar() { return bar() }; return bar() };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\nlet f = 1\ndo\n  fun f = f\n  print(() => f)\n  ()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f, lambda;\n//│ f = 1;\n//│ lambda = (undefined, function () {\n//│   loopLabel: while (true) { continue loopLabel; }\n//│ });\n//│ Predef.print(lambda);\n//│ runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > fun\n//│ f = 1\n\n:sjs\n:e\nlet foo = 1\nfun foo(x) = foo\n//│ ╔══[COMPILATION ERROR] Name 'foo' is already used\n//│ ║  l.100: \tlet foo = 1\n//│ ║         \t    ^^^^^^^\n//│ ╟── by a member declared in the same block\n//│ ║  l.101: \tfun foo(x) = foo\n//│ ╙──       \t^^^^^^^^^^^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo4; foo4 = 1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = 1\n\n:sjs\n:re\nfoo(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(foo4(1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: foo4 is not a function\n\n\nfun f(x) =\n  if x is 1 and x > 0 then return\n  print(\"huh\")\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ReboundLet.mls",
    "content": ":js\n\n\nfun foo() =\n  let x = 1\n  let f = () => x\n  fun g() = x\n  let x = 2\n  f()\n  g()\n\nfoo()\n//│ = 1\n\n\nlet x = 1\nlet f = () => x\n//│ f = fun f\n//│ x = 1\n\nf()\n//│ = 1\n\nlet x = 2\n//│ x = 2\n\nf()\n//│ = 1\n\n\n// * Notice that we pick a different private field name for each `x`\n\nobject Foo with\n  let x = 1\n  let f = () => x\n  fun g() = x\n  print(f())\n  let x = 2\n  print(x)\n  print(f())\n  print(g())\n//│ > 1\n//│ > 2\n//│ > 1\n//│ > 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/RecordSpreads.mls",
    "content": ":js\n\n\nlet rcd =\n  a: 0\n  b: 1\n//│ rcd = {a: 0, b: 1}\n\n...rcd\n//│ = {a: 0, b: 1}\n\n:e\n(...rcd)\n//│ ╔══[COMPILATION ERROR] Illegal position for '...' spread operator.\n//│ ║  l.13: \t(...rcd)\n//│ ╙──      \t ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n...rcd\nc: 123\n//│ = {a: 0, b: 1, c: 123}\n//│ c = 123\n\nlet rcd =\n  a: 0\n  ...(c: 2, d: 3)\n  b: 1\n//│ rcd = {a: 0, c: 2, d: 3, b: 1}\n\n...rcd\n...rcd\n//│ = {a: 0, c: 2, d: 3, b: 1}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Repl.mls",
    "content": ":js\n\n\nfun res\n\nval res: Int\n\n:showRepl\nfun res() = 1\n//│ REPL> Sending: block$res3 = undefined\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Sending: let res2;try { res2 = function res() {   runtime.checkArgs(\"res\", 0, true, arguments.length);   return 1 };; undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  undefined\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(block$res3)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  undefined\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  undefined\n//│ >  undefined\n\n:showRepl\n2 + 2\n//│ REPL> Sending: block$res4 = undefined\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Sending: try { block$res4 = 2 + 2; undefined; undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  undefined\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(block$res4)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  4\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  4\n//│ >  undefined\n//│ = 4\n\n:showRepl\nres\n//│ REPL> Sending: block$res5 = undefined\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Sending: try { block$res5 = res2; undefined; undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  undefined\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(block$res5)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  fun res\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  fun res\n//│ >  undefined\n//│ = fun res\n\n\n:showRepl\nlet x = 1, print(x), x\n//│ REPL> Sending: block$res6 = undefined\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Sending: let x;try { x = 1; runtime.checkCall(Predef.print(x)); block$res6 = x; undefined; undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  1\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  1\n//│ >  undefined\n//│ > 1\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(block$res6)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  1\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  1\n//│ >  undefined\n//│ = 1\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(x)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  1\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  1\n//│ >  undefined\n//│ x = 1\n\n\n[\"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\", \"***\"]\n//│ = [\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\",\n//│   \"***\"\n//│ ]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/RuntimeUsage.mls",
    "content": ":js\n\n\n()\n\nprint(())\n//│ > ()\n\nprint(print(\"hello!\"))\n//│ > hello!\n//│ > ()\n\n\n// * One can import the Runtime module explicitly\n\nimport \"../../mlscript-compile/Runtime.mls\"\n\nRuntime.printRaw(1)\n//│ > 1\n\nprint(Runtime.Unit)\n//│ > ()\n\nopen Runtime\n\nprint(Unit)\n//│ > ()\n\nprint of safeCall(123)\n//│ > 123\n\nprint of safeCall(null)\n//│ > null\n\nprint of safeCall(undefined)\n//│ > ()\n\nprint of safeCall(())\n//│ > ()\n\nprint of  checkCall(123)\n//│ > 123\n\nprint of  checkCall(null)\n//│ > null\n\n:re\nprint of  checkCall(undefined)\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n\n\nprint of Tuple.slice([1, 2, 3, 4], 1, -1)\n//│ > [2, 3, 4]\n\nprint of Tuple.get([1, 2, 3, 4], 0)\n//│ > 1\n\nprint of Tuple.get([1, 2, 3, 4], -1)\n//│ > 4\n\n:re\nprint of Tuple.get([1, 2, 3, 4], 5)\n//│ ═══[RUNTIME ERROR] RangeError: Tuple.get: index out of bounds\n\nprint of Str.leave(\"hello, world\", 2)\n//│ > llo, world\n\nprint of Str.leave(\"hello, world\", -2)\n//│ > ld\n\nprint of Str.get(\"hello, world\", 2)\n//│ > l\n\n:re\nprint of Str.get(\"hello, world\", 22)\n//│ ═══[RUNTIME ERROR] RangeError: Str.get: index out of bounds\n\nprint of Str.get(\"hello, world\", -1)\n//│ > d\n\nprint of Str.startsWith(\"hello, world\", \"hello\")\n//│ > true\n\nprint of Str.startsWith(\"hello, world\", \"\")\n//│ > true\n\nprint of Str.startsWith(\"hello, world\", \"farewell\")\n//│ > false\n\n\nstackLimit\n//│ = 0\n\n:ssjs\nset stackLimit = 1\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ Runtime.stackLimit = 1; block$res29 = runtime.Unit; undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nstackLimit\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SanityChecks.mls",
    "content": ":js\n\n// * In this test, we use `id` to wrap functions so that compile-time arity checks get bypassed.\n\n\n:ssjs\nfun f(x, y) = x + y\nf(2, 3)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f, x, y, inlinedVal;\n//│ f = function f(x1, y1) {\n//│   runtime.checkArgs(\"f\", 2, true, arguments.length);\n//│   return x1 + y1\n//│ };\n//│ x = 2;\n//│ y = 3;\n//│ inlinedVal = x + y;\n//│ block$res1 = inlinedVal;\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 5\n\n\n:ssjs\nlet f = (x, y) => x + y\nf(2, 3)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f1, f2;\n//│ f2 = function f(x1, y1) {\n//│   runtime.checkArgs(\"f\", 2, true, arguments.length);\n//│   return x1 + y1\n//│ };\n//│ f1 = f2;\n//│ block$res2 = runtime.safeCall(f1(2, 3));\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 5\n//│ f = fun f\n\n:re\nf(2)\n//│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1\n\n:re\nf(2, 3, 4)\n//│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 3\n\n\n:ssjs\n:expect NaN\n:noSanityCheck\nfun f2(x, y) = x + y\nid(f2)(2)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f21, baseCall;\n//│ f21 = function f2(x1, y1) {\n//│   return x1 + y1\n//│ };\n//│ baseCall = Predef.id(f21);\n//│ block$res5 = runtime.safeCall(baseCall(2));\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = NaN\n\n:ssjs\n:re\nid(f)(2)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let baseCall1;\n//│ baseCall1 = runtime.checkCall(Predef.id(f1)); block$res6 = runtime.safeCall(baseCall1(2)); undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1\n\n\n:ssjs\n// :re // Argument numbers are no longer checked for lambdas, including extra parameter lists\nfun f(x)(y, z) = x + y + z\nid(f)(3)(4)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let f3, baseCall2, callPrefix;\n//│ f3 = function f(x1) {\n//│   runtime.checkArgs(\"f\", 1, true, arguments.length);\n//│   return (y1, z) => {\n//│     let tmp;\n//│     tmp = x1 + y1;\n//│     return tmp + z\n//│   }\n//│ };\n//│ baseCall2 = runtime.checkCall(Predef.id(f3));\n//│ callPrefix = runtime.safeCall(baseCall2(3));\n//│ block$res7 = runtime.safeCall(callPrefix(4));\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = NaN\n\n\n// :ssjs\n:expect NaN\n:noSanityCheck\nlet f = (x, y) => x + y in f(2)\n//│ = NaN\n\n// :ssjs\n:re\nlet f = (x, y) => x + y\nf(2)\n//│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1\n//│ f = fun f\n\n\n// :ssjs\n:expect NaN\n:noSanityCheck\ndata class Cls(x, y) with\n  fun f(z, p) = x + y + z + p\nid(Cls(1, 2)).f(3)\n//│ = NaN\n\n// :ssjs\n:re\ndata class Cls(x, y) with\n  fun f(z, p) = x + y + z + p\nid(Cls(1, 2)).f(3)\n//│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1\n\n\n:ssjs\n:expect NaN\n// :re // Argument numbers are no longer checked for lambdas, including extra parameter lists\ndata class Cls(x, y) with\n  fun f(z, p)(q, s) = x + y + z + p + q + s\nid(Cls(1, 2)).f(3, 4)(5)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let Cls5, tmp4, tmp5, callPrefix1;\n//│ Cls5 = function Cls(x1, y1) {\n//│   return globalThis.Object.freeze(new Cls.class(x1, y1));\n//│ };\n//│ globalThis.Object.freeze(class Cls4 {\n//│   static {\n//│     Cls5.class = this\n//│   }\n//│   constructor(x1, y1) {\n//│     this.x = x1;\n//│     this.y = y1;\n//│   }\n//│   get f$__checkNotMethod() { runtime.deboundMethod(\"f\", \"Cls\"); }\n//│   f(z, p) {\n//│     runtime.checkArgs(\"f\", 2, true, arguments.length);\n//│     return (q, s) => {\n//│       let tmp6, tmp7, tmp8, tmp9;\n//│       tmp6 = this.x + this.y;\n//│       tmp7 = tmp6 + z;\n//│       tmp8 = tmp7 + p;\n//│       tmp9 = tmp8 + q;\n//│       return tmp9 + s\n//│     }\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Cls\", [\"x\", \"y\"]]; \n//│ });\n//│ tmp4 = runtime.checkCall(Cls5(1, 2));\n//│ tmp5 = runtime.checkCall(Predef.id(tmp4));\n//│ callPrefix1 = runtime.safeCall(tmp5.f(3, 4));\n//│ block$res12 = runtime.safeCall(callPrefix1(5));\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = NaN\n\n\n// :ssjs\nconsole.log(1)\n//│ > 1\n\n\n// :ssjs\n:re\nglobalThis.x\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n// :ssjs\n:re\nglobalThis.x()\n//│ ═══[RUNTIME ERROR] TypeError: globalThis.x is not a function\n\n\n\n\nmodule M with\n  data class A(x) with\n    fun f(y) = x + y\n  fun g(x, y) = x + y\n\n:ssjs\n:re\nif M.A(1).y is\n  x and x == 1 then x\n  else 0\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let scrut, x1, scrut1, tmp6, selRes1;\n//│ tmp6 = runtime.checkCall(M1.A(1));\n//│ selRes1 = tmp6.y;\n//│ tmp6.y$__checkNotMethod;\n//│ if (selRes1 === undefined) {\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"Access to required field 'y' yielded 'undefined'\"))\n//│ }\n//│ scrut = selRes1;\n//│ x1 = scrut;\n//│ scrut1 = runtime.checkCall(Predef.equals(x1, 1));\n//│ if (scrut1 === true) { block$res17 = x1; undefined } else { block$res17 = 0; undefined }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'y' yielded 'undefined'\n\n\n\n// :ssjs\n:re\nM.A(1).y\n  console.log()\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'y' yielded 'undefined'\n\n\n\n// :ssjs\n:noSanityCheck\nM.A(1).y\n  console.log()\n//│ > undefined\n\n:noSanityCheck\n:expect false\nM.A(2).y > 1\n//│ = false\n\n:re\nM.A(2).y > 1\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'y' yielded 'undefined'\n\n// :ssjs\n:re\nM.A(1).g(0)\n//│ ═══[RUNTIME ERROR] TypeError: tmp11.g is not a function\n\n\n\n// :ssjs\nM.A(1).f(0)\n//│ = 1\n\n\n\n:ssjs\nM.g(1, 2)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ block$res24 = runtime.checkCall(M1.g(1, 2)); undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n\nval outFilePath = \"out/test.md\"\n//│ outFilePath = \"out/test.md\"\n\n:sjs\nfun w(txt) =\n  fs.writeFileSync(outFilePath, txt)\n  // ()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let w;\n//│ w = function w(txt) { return runtime.safeCall(globalThis.fs.writeFileSync(outFilePath, txt)) };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nw(\"whoops\")\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ScopedBlocks.mls",
    "content": ":js\n\n\nlet x =\n  let y = 1 + 3 * 4\n  y + 4\n//│ x = 17\n\n\nfun f() =\n  if true then\n    let a = 4\n    a + 4\n  else\n    let b = 5\n    b + 9\n\n\n// TODO: improve later: `let a` can be moved to the branch body\n// NOTE: `tmp1` and `tmp2` should indeed be declared in the top level of the function body\n:sjs\nfun g(x, y, z) =\n  3 + 4 * if\n    x then 0\n    y then 0\n    z then\n      let a = 1\n      (_ + a)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let g;\n//│ g = function g(x1, y1, z) {\n//│   let a, tmp1, tmp2;\n//│   if (x1 === true) {\n//│     tmp1 = 0;\n//│   } else {\n//│     if (y1 === true) {\n//│       tmp1 = 0;\n//│     } else {\n//│       if (z === true) {\n//│         let lambda;\n//│         a = 1;\n//│         lambda = (undefined, function (_0) {\n//│           return _0 + a\n//│         });\n//│         tmp1 = lambda;\n//│       } else {\n//│         throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│       }\n//│     }\n//│   }\n//│   tmp2 = 4 * tmp1;\n//│   return 3 + tmp2\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nmodule M\ndata class A(a, b)\ndata class B(a, b)\ndata object Nil\n\n\n\nfun f() = if x is\n  A(a, b) and a > b then true\n  B(c, d) then false\n\n\n\nfun f() = if A(1, Nil) is\n  A(1, Nil) then 3\n\n\n\n\nfun f(x) =\n  x = while x is\n    A(a, _) then a()\n    B(a, _) then a()\n  else\n    x()\n  x\n\n\n\n\nfun f() =\n  let y = x + 1\n  while y is\n    A(z, a) and\n      false and true do\n        set y = z + 1\n      else\n        y = a\n\n\n\nfun f(x, y) =\n  while x && y do\n    f(0, 0) + 4\n\n\n\n\nclass A with\n  val x = 1 + 2\n\n\nlet state = 0\n//│ state = 0\n\n\nclass Foo() with // the class definition is moved to the location of its companion\n  fun foo() = state\nset state += 1\nmodule Foo with\n  val res = Foo().foo()\n\n\n\n:sjs\ntype I = Int\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n\nclass A(x) with\n  val y = x\n\n\n\n\nmodule M with\n  data class A(x, y)\n\n// NOTE: while bodies are not rewritten to functions by default\n// and are `Scoped`\n:sjs\nfun f(x) =\n  while x do\n    let y = x\n    print(x)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f6;\n//│ f6 = function f(x1) {\n//│   lbl: while (true) {\n//│     if (x1 === true) { Predef.print(x1); continue lbl }\n//│     break;\n//│   }\n//│   return runtime.Unit\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// `:rewriteWhile` turns while loop into functions\n:sjs\n:rewriteWhile\nfun f(x) =\n  while x do\n    let y = x\n    print(x)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f7;\n//│ f7 = function f(x1) {\n//│   let while1, tmp2, tmp3;\n//│   while1 = (undefined, function () {\n//│     if (x1 === true) {\n//│       Predef.print(x1);\n//│       return while1()\n//│     }\n//│     return runtime.LoopEnd;\n//│   });\n//│   tmp2 = while1();\n//│   tmp3 = tmp2 !== runtime.LoopEnd;\n//│   if (tmp3 === true) { return tmp2 }\n//│   return runtime.Unit;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\ndata class Bar(x)\n\n// NOTE: `tmp`s in pCtor and ctor shouldn't have name clashes with each other\n:sjs\ndata class Baz(z) extends Bar(z * 1) with\n  val k = 1 + 2 + 3\n  fun baz = this.bar * 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Baz1;\n//│ Baz1 = function Baz(z) {\n//│   return globalThis.Object.freeze(new Baz.class(z));\n//│ };\n//│ (class Baz extends Bar1.class {\n//│   static {\n//│     Baz1.class = this\n//│   }\n//│   constructor(z) {\n//│     let tmp2;\n//│     tmp2 = z * 1;\n//│     super(tmp2);\n//│     let tmp3, tmp4;\n//│     this.z = z;\n//│     tmp3 = 1 + 2;\n//│     tmp4 = tmp3 + 3;\n//│     this.k = tmp4;\n//│   }\n//│   get baz() {\n//│     return this.bar * 2;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Baz\", [\"z\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ScopedBlocksAndHandlers.mls",
    "content": ":js\n:lift\n:effectHandlers\n\n\n\n\nfun start(x, f) =\n  while x do\n    f(() => x)\n\n// if `z` and `g` is defined in a nested scoped block\n// and `g` is floated out to the top level, `z` in `g` gets unbound.\n// so currently nested `if`s do not get nested `Scoped` blocks\n:sjs\nfun f(x) =\n  if x do\n    if x do\n      let z = 3\n      fun g() = z\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f;\n//│ runtime.resetEffects();\n//│ f = function f(x) { if (x === true) { return runtime.Unit } return runtime.Unit; };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\nabstract class Effect with\n  fun perform()\n\n\n\nfun f(x) =\n  if x then\n    if x then\n      let z = 4\n      handle h = Effect with\n        fun perform()(k) =\n          print(x)\n          k(x + z)\n      print(h.perform())\n  else 0\n\n\nfun f(x) =\n  while x do\n    while x do\n      let z = 4\n      handle h = Effect with\n        fun perform()(k) =\n          print(x)\n          k(x + z)\n      print(h.perform())\n  0\n\n\n// The class body generated by the handler is in the\n// top level of the function, and it refers to `g`.\n// So there would be problems if the declartion of `g`\n// is nested inside the first `if`.\n:expect 2\nfun foo(h) =\n  h.perform()\n  if true then\n    if true then\n      fun g() = 2\n      g()\n  else\n    fun g() = 3\n    g()\nhandle h = Effect with\n  fun perform()(k) = k(())\nfoo(h)\n//│ = 2\n\n\n\nfun f(x) =\n  while x do\n    while x do\n      let z = 3\n      fun g() = z\n      g()\n\n\n\nfun start(x, f) =\n  while x do\n    let z = 2\n    fun g() = z\n    g()\n\n\n\n// NOTE: `z` should be in the function top level when `:effectHandlers` to be properly captured by the floated-out `g`.\n:sjs\nfun f(x) =\n  if x do\n    scope.locally of (\n      let z = 3\n      fun g() = z\n      g() )\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f4;\n//│ runtime.resetEffects();\n//│ f4 = function f(x) {\n//│   let z, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   main: while (true) {\n//│     switch (pc) {\n//│       case 2:\n//│         runtime.resumeValue;\n//│         pc = 1;\n//│       case 1:\n//│         return runtime.Unit;\n//│       case 0:\n//│         if (x === true) {\n//│           let z1, inlinedVal;\n//│           z = 3;\n//│           z1 = z;\n//│           inlinedVal = z1;\n//│           runtime.resumeValue = inlinedVal;\n//│           if (runtime.curEffect === null) {\n//│             pc = 2;\n//│             continue main\n//│           }\n//│           return runtime.unwind(f4, 2, \"ScopedBlocksAndHandlers.mls:103:7\", null, null, 1, 1, x, 0);\n//│         }\n//│         pc = 1;\n//│         continue main;\n//│     }\n//│     break;\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// * Note: degenerate case\n:sjs\nfun f(x) =\n  if x do\n    scope.locally of (\n      let z = 3\n      fun g() = z )\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f5;\n//│ runtime.resetEffects();\n//│ f5 = function f(x) { if (x === true) { return runtime.Unit } return runtime.Unit; };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\nclass C(x) with\n  if x do\n    scope.locally of (\n      let z = 3\n      fun g() = z )\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Scoping.mls",
    "content": ":js\n\n:expect 4\nfun f(y) =\n  let x = 0\n  class A() with\n    fun g() =\n      set x += 1\n      set y += 1\n  fun h() =\n    set x += 1\n    set y += 1\n  A().g()\n  h()\n  x + y\nf(0)\n//│ = 4\n\n:expect 0\nfun f() =\n  let x = 0\n  class A() with\n    let x = 2\n    fun g() =\n      set x += 1\n  A().g()\n  x\nf()\n//│ = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SelfReferences.mls",
    "content": ":js\n\n\n:sjs\nmodule Foo with\n  val self: module Foo = Foo\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ (class Foo {\n//│   static {\n//│     Foo1 = this\n//│   }\n//│   static {\n//│     this.self = Foo1;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nFoo.self\n//│ = class Foo { self: ref'1 } as ref'1\n\n\nmodule Foo with\n  val self: module Foo = this\n\nFoo.self\n//│ = class Foo { self: ref'1 } as ref'1\n\n\n:e\nmodule Foo with\n  val self = this\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type Foo.\n//│ ║  l.34: \t  val self = this\n//│ ║        \t             ^^^^\n//│ ╙── Value must be marked as returning a 'module' in order to return a module.\n\nFoo.self\n//│ = class Foo { self: ref'1 } as ref'1\n\n\nobject Foo with\n  val self = this\n\nFoo.self\n//│ = Foo { self: ref'1, class: object Foo } as ref'1\n\n\nmodule Foo with\n  val foo = 1\n  print(Foo.foo)\n//│ > 1\n\n// * This used not to work, and it could be argued it should be an initialization error\n:sjs\nobject Foo with\n  val self = id(Foo)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo11;\n//│ (class Foo10 {\n//│   static {\n//│     new this\n//│   }\n//│   constructor() {\n//│     Foo11 = this;\n//│     let tmp;\n//│     tmp = Predef.id(Foo11);\n//│     this.self = tmp;\n//│     Object.defineProperty(this, \"class\", {\n//│       value: Foo10\n//│     });\n//│     globalThis.Object.freeze(this);\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"object\", \"Foo\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * This used not to work, and it could be argued it should be an initialization error\n// * (leaking a partially-initialized module)\nobject Foo with\n  val self = id(Foo)\n  val lateInit = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SetIn.mls",
    "content": ":js\n\n\nlet x = 0\n//│ x = 0\n\n:sjs\nlet x += 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x1; x1 = x + 1;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ x = 1\n\nx\n//│ = 1\n\n:sjs\nset x = 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ x1 = 0; runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nset x += 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = x1 + 1; x1 = tmp; runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nx\n//│ = 1\n\n\n:sjs\nset x += 1 in print(x)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let old, tmp1, tmp2, tmp3;\n//│ old = x1;\n//│ try { tmp2 = x1 + 1; x1 = tmp2; tmp3 = Predef.print(x1); tmp1 = tmp3; } finally { x1 = old; }\n//│ tmp1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n\nx\n//│ = 1\n\n\nfun example() =\n  let x = 0\n  let get_x() = x\n  let x += 1\n  print(x)\n  print(get_x())\nexample()\n//│ > 1\n//│ > 0\n\nfun example() =\n  let x = 0\n  let get_x() = x\n  set x += 1\n  print(x)\n  print(get_x())\nexample()\n//│ > 1\n//│ > 1\n\n:sjs\nfun example() =\n  let x = 0\n  let get_x() = x\n  set x += 1 in print(x); print(get_x())\n  print(x)\n  print(get_x())\nexample()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let example2;\n//│ example2 = function example() {\n//│   let x2, get_x, old1, tmp4, tmp5, tmp6, get_x1;\n//│   x2 = 0;\n//│   get_x1 = function get_x() {\n//│     return x2\n//│   };\n//│   get_x = get_x1;\n//│   old1 = x2;\n//│   try {\n//│     tmp4 = x2 + 1;\n//│     x2 = tmp4;\n//│     Predef.print(x2);\n//│     tmp5 = runtime.safeCall(get_x());\n//│     Predef.print(tmp5);\n//│   } finally {\n//│     x2 = old1;\n//│   }\n//│   Predef.print(x2);\n//│   tmp6 = runtime.safeCall(get_x());\n//│   return Predef.print(tmp6)\n//│ };\n//│ example2()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n//│ > 1\n//│ > 0\n//│ > 0\n\n:sjs\nfun example() =\n  let x = 0\n  let get_x() = x\n  let y =\n    set x += 1 in print(x); x\n  print(x)\n  print(get_x())\n  y\nexample()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let example3;\n//│ example3 = function example() {\n//│   let x2, get_x, y, old1, tmp4, tmp5, tmp6, tmp7, tmp8, get_x1;\n//│   x2 = 0;\n//│   get_x1 = function get_x() {\n//│     return x2\n//│   };\n//│   get_x = get_x1;\n//│   old1 = x2;\n//│   try {\n//│     tmp5 = x2 + 1;\n//│     x2 = tmp5;\n//│     tmp6 = Predef.print(x2);\n//│     tmp7 = (tmp6 , x2);\n//│     tmp4 = tmp7;\n//│   } finally {\n//│     x2 = old1;\n//│   }\n//│   y = tmp4;\n//│   Predef.print(x2);\n//│   tmp8 = runtime.safeCall(get_x());\n//│   Predef.print(tmp8);\n//│   return y\n//│ };\n//│ example3()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n//│ > 0\n//│ > 0\n//│ = 1\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SetStmt.mls",
    "content": ":js\n\n\nlet g = [0]\n//│ g = [0]\n\nset g = g.concat of [1]\n\nset g |>= (_.concat of [2])\n\ng\n//│ = [0, 1, 2]\n\nset g.0 += 1\n\nset g.0 = g.0 + 1\n\ng\n//│ = [2, 1, 2]\n\nset g.0 |>= Math.sign\n\nset g.2 |>= Math.pow(_, 5)\n//│ = fun\n\ng\n//│ = [1, 1, 2]\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ShortCircuitReturn.mls",
    "content": ":js\n\n\n// Regression test: && and || should use Match blocks instead of short_and/short_or function calls.\n// This ensures that `return` inside && works correctly.\n\n:soir\nfun test =\n  true && return 42\n  43\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let test⁰; define test⁰ as fun test¹() { match true true => return 42 else return 43 end }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 42\ntest\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SimplePatMat.mls",
    "content": ":js\n\n\ndata class Some[out A](value: A)\n\n\n:todo\nlet Some(x) = Some(42)\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.8: \tlet Some(x) = Some(42)\n//│ ╙──     \t    ^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SingletonInit.mls",
    "content": ":js\n\n\nobject A with\n  val x = 1\n  object B with\n    print(A, \"|\", B)\n    print(x, y)\n  val y = 2\n  print(A, \"|\", B)\n  print(x, y)\n//│ > A { x: 1, B: B {} } | B {}\n//│ > 1 undefined\n//│ > A { x: 1, B: B, y: 2 } | B\n//│ > 1 2\n\nprint(A, \"|\", A.B)\n//│ > A { x: 1, B: B, y: 2, class: object A } | B\n\n:w\nmodule A with\n  val x = 1\n  module B with\n    print(x, y)\n    A\n  val y = 2\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.25: \t    A\n//│ ╙──      \t    ^\n//│ > 1 undefined\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SpecialJSNames.mls",
    "content": ":js\n\n\n// * JavaScript classes have built-in non-writable `name` and `length` properties,\n// * which can't be set directly by a normal assignment.\n\n// * Notice:\n:re\n:noModuleCheck\nmodule M with\n  set this.\"name\" = \"oops\"\n//│ ═══[RUNTIME ERROR] TypeError: Cannot assign to read only property 'name' of function 'class M {   static {     M1 = this   }   static {     M[\"name\"] = \"oops\";   }   toString() { return runtime.ren...<omitted>... }'\n\n// * So we use `Object.defineProperty` instead:\n:sjs\nmodule M with\n  val name = \"Student\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let M3;\n//│ (class M2 {\n//│   static {\n//│     M3 = this\n//│   }\n//│   static {\n//│     Object.defineProperty(this, \"name\", { configurable: true, enumerable: true, writable: true, value: \"Student\" });\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"M\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * Non-static definitions should be unaffected:\n:sjs\nclass C with\n  val name = \"Student\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let C1;\n//│ (class C {\n//│   static {\n//│     C1 = this\n//│   }\n//│   constructor() {\n//│     this.name = \"Student\";\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"C\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Spreads.mls",
    "content": ":js\n\n\nlet a = [1, 2, 3]\n//│ a = [1, 2, 3]\n\nlet b = [0, ...a]\n//│ b = [0, 1, 2, 3]\n\n\nfun foo(w, x, y, z) = [w, x, y, z]\n\nfoo(...b)\n//│ = [0, 1, 2, 3]\n\nfoo(0, ...a)\n//│ = [0, 1, 2, 3]\n\n:sjs\nfoo(1, ...[2, 3], 4)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = globalThis.Object.freeze([ 2, 3 ]); foo(1, ...tmp, 4)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [1, 2, 3, 4]\n\n:re\nfoo(...a)\n//│ ═══[RUNTIME ERROR] Error: Function 'foo' expected 4 arguments but got 3\n\n\nlet f = (...xs) => xs\n//│ f = fun f\n\nf(a)\n//│ = [[1, 2, 3]]\n\nf(1, 2, 3)\n//│ = [1, 2, 3]\n\nf(...a)\n//│ = [1, 2, 3]\n\n\nfun foo(...xs) = xs\n\nfoo()\n//│ = []\n\nfoo(1, 2, 3)\n//│ = [1, 2, 3]\n\nfoo(0, ...a)\n//│ = [0, 1, 2, 3]\n\n\n:todo\n:expect [1, 2, 3]\ndata class A(...r)\nlet x = new A(1, 2, 3)\nx.r\n//│ ╔══[INTERNAL ERROR] Compiler reached an unsupported state: mismatched param list lengths List() vs List(term:A/r)\n//│ ╟── The compilation result may be incorrect.\n//│ ╙── This is a known compiler limitation; if it is a blocker for you, please report it to the maintainers.\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'r' yielded 'undefined'\n//│ ═══[RUNTIME ERROR] Expected: '[1, 2, 3]', got: 'undefined'\n//│ x = A(undefined)\n\n:todo\n:expect [1, 2, 3]\ndata class A(...r) with\n  fun getR = r\nnew A(1, 2, 3).getR\n//│ ╔══[INTERNAL ERROR] Compiler reached an unsupported state: mismatched param list lengths List() vs List(term:A/r)\n//│ ╟── The compilation result may be incorrect.\n//│ ╙── This is a known compiler limitation; if it is a blocker for you, please report it to the maintainers.\n//│ ═══[RUNTIME ERROR] ReferenceError: r is not defined\n//│ ═══[RUNTIME ERROR] Expected: '[1, 2, 3]', got: 'undefined'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/SwitchSpecialization.mls",
    "content": ":js\n\n\n:sjs\nfun f(x) =\n  if x is 0 then\n    \"a\"\n  else if x is 1 then\n    \"b\"\n  else if x is 2 then\n    \"c\"\n  else if x is 3 then\n    \"d\"\n  else\n    \"e\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f;\n//│ f = function f(x) {\n//│   switch (x) {\n//│     case 0:\n//│       return \"a\";\n//│     case 1:\n//│       return \"b\";\n//│     case 2:\n//│       return \"c\";\n//│     case 3:\n//│       return \"d\";\n//│   }\n//│   return \"e\"\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect \"b\"\nf(1)\n//│ = \"b\"\n\n// Chains of if statements in the following form, which is essentially a jump table,\n// can be converted into a switch statement.\n// (This can be used to very efficiently compile resumable functions, i.e. for effect handlers and co-routines.)\n:sjs\nfun f(x) =\n  let acc = \"\"\n  if x is 0 do\n    set acc += \"a\"\n    set x = 1\n  if x is 1 do\n    set acc += \"b\"\n    set x = 2\n  if x is 2 do\n    set acc += \"c\"\n    set x = 3\n  if x is 3 do\n    set acc += \"d\"\n    set x = 4\n  if x is 4 do\n    set acc += \"e\"\n  [acc, x]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1;\n//│ f1 = function f(x) {\n//│   let acc, tmp, tmp1, tmp2, tmp3, tmp4;\n//│   acc = \"\";\n//│   switch (x) {\n//│     case 0:\n//│       tmp = acc + \"a\";\n//│       acc = tmp;\n//│       x = 1;\n//│     case 1:\n//│       tmp1 = acc + \"b\";\n//│       acc = tmp1;\n//│       x = 2;\n//│     case 2:\n//│       tmp2 = acc + \"c\";\n//│       acc = tmp2;\n//│       x = 3;\n//│     case 3:\n//│       tmp3 = acc + \"d\";\n//│       acc = tmp3;\n//│       x = 4;\n//│     case 4:\n//│       tmp4 = acc + \"e\";\n//│       acc = tmp4;\n//│       return globalThis.Object.freeze([ acc, x ]);\n//│   }\n//│   return globalThis.Object.freeze([ acc, x ])\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect [\"cde\", 4]\nf(2)\n//│ = [\"cde\", 4]\n\n// See `SpecializedSwitch` for details on what is specialized here\n// Note: It would also specialize if `return` were replaced with `break` or `continue`, but it isn't\n// yet possible to explicitly write in the source language\n:sjs\nfun f(x) =\n  let acc = \"\"\n  if x is 0 do\n    set acc += \"a\"\n    set x = 1\n  if x is 1 do\n    set acc += \"b\"\n    set x = 2\n  if x is 2 do\n    set acc += \"c\"\n    return acc\n  if x is 3 do\n    set acc += \"A\"\n    set x = 4\n  if x is 4 do\n    set acc += \"B\"\n    set x = 5\n  if x is 5 do\n    set acc += \"C\"\n    return acc\n  if x is\n    6 then \"EndA\"\n    7 then \"EndB\"\n    8 then \"EndC\"\n    else \"EndD\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2;\n//│ f2 = function f(x) {\n//│   let acc, tmp, tmp1, tmp2, tmp3, tmp4, tmp5;\n//│   acc = \"\";\n//│   switch (x) {\n//│     case 0:\n//│       tmp = acc + \"a\";\n//│       acc = tmp;\n//│       x = 1;\n//│     case 1:\n//│       tmp1 = acc + \"b\";\n//│       acc = tmp1;\n//│       x = 2;\n//│     case 2:\n//│       tmp2 = acc + \"c\";\n//│       acc = tmp2;\n//│       return acc;\n//│     case 3:\n//│       tmp3 = acc + \"A\";\n//│       acc = tmp3;\n//│       x = 4;\n//│     case 4:\n//│       tmp4 = acc + \"B\";\n//│       acc = tmp4;\n//│       x = 5;\n//│     case 5:\n//│       tmp5 = acc + \"C\";\n//│       acc = tmp5;\n//│       return acc;\n//│     case 6:\n//│       return \"EndA\";\n//│     case 7:\n//│       return \"EndB\";\n//│     case 8:\n//│       return \"EndC\";\n//│   }\n//│   return \"EndD\"\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect \"bc\"\nf(1)\n//│ = \"bc\"\n\n:expect \"c\"\nf(2)\n//│ = \"c\"\n\n:expect \"ABC\"\nf(3)\n//│ = \"ABC\"\n\n:expect \"EndA\"\nf(6)\n//│ = \"EndA\"\n\n:expect \"EndC\"\nf(8)\n//│ = \"EndC\"\n\n:expect \"EndD\"\nf(-1)\n//│ = \"EndD\"\n\n:sjs\nfun f(x) =\n  let acc = \"\"\n  if x is 0 do\n    set acc += \"M\"\n    set x = 1\n  if x is\n    1 do return acc + \"1\"\n    2 do return acc + \"2\"\n  \"fail\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f3;\n//│ f3 = function f(x) {\n//│   let acc, tmp1;\n//│   acc = \"\";\n//│   switch (x) {\n//│     case 0:\n//│       tmp1 = acc + \"M\";\n//│       acc = tmp1;\n//│       x = 1;\n//│     case 1:\n//│       return acc + \"1\";\n//│     case 2:\n//│       return acc + \"2\";\n//│   }\n//│   return \"fail\"\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect \"M1\"\nf(0)\n//│ = \"M1\"\n\n:expect \"fail\"\nf(4)\n//│ = \"fail\"\n\n:expect \"2\"\nf(2)\n//│ = \"2\"\n\n// Do not specialize all into one switch\n:sjs\nfun f(x) =\n  let acc = \"\"\n  if x is 0 do\n    set acc += \"M\"\n    set x = 1\n  if x is\n    1 do return acc + \"1\"\n    2 do return acc + \"2\"\n    else do return acc + \"3\"\n  \"fail\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f4;\n//│ f4 = function f(x) {\n//│   let acc, tmp1;\n//│   acc = \"\";\n//│   switch (x) {\n//│     case 0:\n//│       tmp1 = acc + \"M\";\n//│       acc = tmp1;\n//│       x = 1;\n//│     case 1:\n//│       return acc + \"1\";\n//│     case 2:\n//│       return acc + \"2\";\n//│   }\n//│   return acc + \"3\"\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect \"3\"\nf(4)\n//│ = \"3\"\n\n// More tricky fallthrough cases //\n\n// Do not optimize\n:sjs\nfun f(x, y) =\n  fun bad() = set x = 1000\n  if x is 0 do\n    set x = 1\n    if y == 0 then\n      bad()\n    else\n      set x = 1\n  if x is 1 do\n    return \"x = 1\"\n  return \"x != 1\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f5;\n//│ f5 = function f(x, y) {\n//│   let scrut;\n//│   if (x === 0) {\n//│     x = 1;\n//│     scrut = Predef.equals(y, 0);\n//│     if (scrut === true) {\n//│       x = 1000;\n//│     } else { x = 1; }\n//│   }\n//│   if (x === 1) { return \"x = 1\" }\n//│   return \"x != 1\";\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect \"x != 1\"\nf(0, 0)\n//│ = \"x != 1\"\n\n:expect \"x = 1\"\nf(0, 1)\n//│ = \"x = 1\"\n\n// Optimize\n:sjs\nfun f(x, y) =\n  fun bad() = set x = 1000\n  if x is 0 do\n    set x = 1\n    if y == 0 then\n      bad()\n      set x = 1\n    else\n      set x = 1\n  if x is 1 do\n    return \"x = 1\"\n  return \"x != 1\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f6;\n//│ f6 = function f(x, y) {\n//│   let scrut;\n//│   switch (x) {\n//│     case 0:\n//│       x = 1;\n//│       scrut = Predef.equals(y, 0);\n//│       if (scrut === true) {\n//│         x = 1000;\n//│         x = 1;\n//│       } else { x = 1; }\n//│     case 1:\n//│       return \"x = 1\";\n//│   }\n//│   return \"x != 1\"\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect \"x = 1\"\nf(0, 0)\n//│ = \"x = 1\"\n\n:expect \"x = 1\"\nf(1, 0)\n//│ = \"x = 1\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/TailRecFormerFailure.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Stack.mls\"\nopen Stack\n\n\n// Note: tail-rec optimized\n:sir\nfun go(x) = if x is\n  Cons(_, _) then \"Z\"\n  n then go([])\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let go⁰;\n//│ define go⁰ as fun go¹(x) {\n//│   loop loopLabel:\n//│     let n, arg$Cons$0$, arg$Cons$1$, tmp;\n//│     match x\n//│       Cons⁰ =>\n//│         set arg$Cons$0$ = x.head⁰;\n//│         set arg$Cons$1$ = x.tail⁰;\n//│         return \"Z\"\n//│       else\n//│         set n = x;\n//│         set tmp = [];\n//│         set x = tmp;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// Note: tail-rec optimized\n:sir\nfun go(x) = if x is\n  Cons(_, Nil) then \"Z\"\n  n then go([])\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let go²;\n//│ define go² as fun go³(x) {\n//│   loop loopLabel:\n//│     let n, arg$Cons$0$, arg$Cons$1$, tmp, tmp1;\n//│     match x\n//│       Cons⁰ =>\n//│         set arg$Cons$0$ = x.head⁰;\n//│         set arg$Cons$1$ = x.tail⁰;\n//│         match arg$Cons$1$\n//│           Nil⁰ =>\n//│             return \"Z\"\n//│           else\n//│             set n = x;\n//│             set tmp = [];\n//│             set x = tmp;\n//│             continue loopLabel\n//│         end\n//│       else\n//│         set n = x;\n//│         set tmp1 = [];\n//│         set x = tmp1;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// Note: Used not to be tail-rec optimized; now fixed\n:sir\n:patMatConsequentSharingThreshold 1\n // ^ The default value allowed duplicating \"Z\" in the above version\nfun go(x) = if x is\n  Cons(_, Nil) then \"Z\"\n  n then go([])\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let go⁴;\n//│ define go⁴ as fun go⁵(x) {\n//│   loop loopLabel:\n//│     let n, arg$Cons$0$, arg$Cons$1$, tmp;\n//│     block split_root$:\n//│       block split_1$:\n//│         match x\n//│           Cons⁰ =>\n//│             set arg$Cons$0$ = x.head⁰;\n//│             set arg$Cons$1$ = x.tail⁰;\n//│             match arg$Cons$1$\n//│               Nil⁰ =>\n//│                 return \"Z\"\n//│               else\n//│                 set n = x;\n//│                 break split_1$\n//│             end\n//│           else\n//│             set n = x;\n//│             break split_1$\n//│         end\n//│       set tmp = [];\n//│       set x = tmp;\n//│       continue loopLabel\n//│     return runtime⁰.Unit⁰\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/This.mls",
    "content": ":js\n\n\n// TODO add syntax for this-taking detached methods\n:sjs\n:e\nfun test(x) =\n  [this.a, x]\n//│ ╔══[COMPILATION ERROR] Cannot use 'this' outside of an object scope\n//│ ║  l.8: \t  [this.a, x]\n//│ ╙──     \t   ^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test;\n//│ test = function test(x) { throw \"This code cannot be run as its compilation yielded an error.\" };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nfun test(x) =\n  [globalThis.a, x]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test1; test1 = function test(x) { return globalThis.Object.freeze([ globalThis.a, x ]) };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:re\ntest(123)\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'a' yielded 'undefined'\n\nval a = 1\n//│ a = 1\n\n:re\ntest(123)\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'a' yielded 'undefined'\n\nset globalThis.a = 2\n\ntest(123)\n//│ = [2, 123]\n\n:sjs\nmodule Test with\n  val a = 3\n  fun test1(x) =\n    test(x)\n  fun test2(x) =\n    [this.a, x]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Test1;\n//│ (class Test {\n//│   static {\n//│     Test1 = this\n//│   }\n//│   static {\n//│     this.a = 3;\n//│   }\n//│   static test1(x) {\n//│     return test1(x)\n//│   } \n//│   static test2(x) {\n//│     return globalThis.Object.freeze([\n//│       Test.a,\n//│       x\n//│     ])\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Test\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nTest.test1(123)\n//│ = [2, 123]\n\nTest.test2(123)\n//│ = [3, 123]\n\n\n// * Note: a module that induces a `this`-proxy\n// :sjs\nclass A(x) with\n  module M with\n    print(x)\n\nA(42)\n//│ > 42\n//│ = A(_)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ThisCallVariations.mls",
    "content": ":js\n\n\nobject Example with\n  val a = 1\n  fun f(x) = [x, a]\n\nExample.f(2)\n//│ = [2, 1]\n\nlet oops = Example.(\"f\")\n//│ oops = fun f\n\n\n// * JavaScript nonsense\n:re\noops(2)\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'a')\n\noops.call(Example, 2)\n//│ = [2, 1]\n\n\n// * We could use that syntax as a shorthand:\nfun (.!.) call(receiver, f)(arg) = f.call(receiver, arg)\n\n\n// * Notice how it parses with the correct precedence:\n:pt\n:sjs\nExample .!. oops(2)\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ App:\n//│   lhs = OpApp:\n//│     lhs = Ident of \"Example\"\n//│     op = Ident of \".!.\"\n//│     rhss = Ls of \n//│       Ident of \"oops\"\n//│   rhs = Tup of Ls of \n//│     IntLit of 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ call(Example1, oops)(2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [2, 1]\n\nExample.!. oops(2)\n//│ = [2, 1]\n\nExample .!.oops(2)\n//│ = [2, 1]\n\n\nid(Example) .!. oops(2)\n//│ = [2, 1]\n\n\n:e\ndata class Example2(val a) with\n  val a = 1\n  fun f(inc) = Example2(a + inc)\n//│ ╔══[COMPILATION ERROR] Duplicate definition of member named 'a'.\n//│ ╟── Defined at: \n//│ ║  l.58: \tdata class Example2(val a) with\n//│ ║        \t                        ^\n//│ ╟── Defined at: \n//│ ║  l.59: \t  val a = 1\n//│ ╙──      \t  ^^^^^^^^^\n\nlet oops2 = Example2(0).(\"f\")\n//│ oops2 = fun f\n\nExample2(1) .!. oops2(2) .!. oops2(2)\n//│ = Example2(1)\n\nExample2(1).!. oops2(2).!. oops2(2)\n//│ = Example2(1)\n\n(new Example2(1)) .!. oops2(2)\n//│ = Example2(1)\n\nnew Example2(1)\n  .!. oops2(2)\n//│ = Example2(1)\n\nnew Example2(1)\n  .!. oops2(2)\n  .!. oops2(2)\n//│ = Example2(1)\n\n\n// * Alternative syntax – precedence is now inappropriate\nfun (.>) call(receiver, f)(arg) = f.call(receiver, arg)\n\n:pt\n:sjs\n:re\nExample .> oops(2)\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpApp:\n//│   lhs = Ident of \"Example\"\n//│   op = Ident of \".>\"\n//│   rhss = Ls of \n//│     App:\n//│       lhs = Ident of \"oops\"\n//│       rhs = Tup of Ls of \n//│         IntLit of 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp10; tmp10 = runtime.safeCall(oops(2)); call1(Example1, tmp10)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'a')\n\n// * Note:\n:re\noops(2)\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'a')\n\n// * Note:\n(Example .> oops)(2)\n//│ = [2, 1]\n\n\n// * Another alternative syntax – currently adopted in Predef\nfun (|>.) call(receiver, f)(arg) = f.call(receiver, arg)\n\nExample |>. oops(2)\n//│ = [2, 1]\n\nExample2(1) |>. oops2(2) |>. oops2(2)\n//│ = Example2(1)\n\n(Example2(1)\n  |>. oops2(2)\n  |>. oops2(2)\n).a\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/ThisCalls.mls",
    "content": ":js\n\n\nclass Example with\n  val a = 456\n  fun f(x) = [x, a]\n\nval ex = new Example\n//│ ex = Example { a: 456 }\n\nlet s = ex.(\"f\")\n//│ s = fun f\n\n:breakme\n:e\ns(123)\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'a')\n\n:sjs\nex |>. s(123)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Predef.call(ex, s)(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [123, 456]\n\n\n// * Modules on the other hand, do not suffer from method debinding,\n// * because they use static references and avoid `this` altogether.\n\nmodule Example with\n  val a = 456\n  fun f(x) = [x, a]\n  fun g(x) = [x, a, f(x)]\n\nlet\n  f = Example.f\n  g = Example.g\n//│ f = fun f\n//│ g = fun g\n\nf(123)\n//│ = [123, 456]\n\ng(123)\n//│ = [123, 456, [123, 456]]\n\n:e\nExample |>. g(123)\n//│ ╔══[COMPILATION ERROR] Unexpected moduleful reference of type Example.\n//│ ║  l.48: \tExample |>. g(123)\n//│ ║        \t^^^^^^^\n//│ ╙── Module argument passed to a non-module parameter.\n//│ = [123, 456, [123, 456]]\n\n// * Passing `ex` as `this` has no effect\nex |>. g(123)\n//│ = [123, 456, [123, 456]]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/Throw.mls",
    "content": ":js\n\n\n:re\nthrow Error(\"e\")\n//│ ═══[RUNTIME ERROR] Error: e\n\n\n:re\nfun f(x, y) = throw Error(\"e\")\nf(2, 2)\n//│ ═══[RUNTIME ERROR] Error: e\n\n\n:re\nfun f(x, y) = if\n  x == y then x + y\n  x == (y + 1) then throw Error(\"not equal\")\nf(3, 2)\n//│ ═══[RUNTIME ERROR] Error: not equal\n\n:re\nf(2, 3)\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n:re\n:sjs\nfun f(x) =\n  let y = throw Error(\"e\")\n  return y\nf(1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f2;\n//│ f2 = function f(x) {\n//│   throw runtime.safeCall(globalThis.Error(\"e\"))\n//│ };\n//│ throw runtime.safeCall(globalThis.Error(\"e\"))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: e\n\n\n:re\n:sjs\nfun f(x) =\n  throw (if x then Error(\"x\") else Error(\"y\"))\nf(false)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f3;\n//│ f3 = function f(x) {\n//│   if (x === true) {\n//│     throw runtime.safeCall(globalThis.Error(\"x\"))\n//│   }\n//│   throw runtime.safeCall(globalThis.Error(\"y\"));\n//│ };\n//│ f3(false)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: y\n\n\n:re\n:sjs\nif false then throw 0\nthrow 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut;\n//│ scrut = false;\n//│ if (scrut === true) { throw 0 }\n//│ throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n\nimport \"../../mlscript-compile/Runtime.mls\"\n\nfun foo(e) =\n  Runtime.try_catch of\n    () => throw e\n    case\n      Str as o then \"caught \" + o\n      else\n        print(\"caught something else\")\n        throw e // rethrow the original error\n\nfoo(\"hello\")\n//│ = \"caught hello\"\n\n:re\nfoo(42)\n//│ > caught something else\n//│ ═══[RUNTIME ERROR] 42\n\n:re\nfoo(Error(\"hi\"))\n//│ > caught something else\n//│ ═══[RUNTIME ERROR] Error: hi\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/TraceLog.mls",
    "content": ":js\n:traceJS\n:noSanityCheck\n\n:sjs\nfun fib(a) = if\n  a <= 1 then a\n  else fib(a - 1) + fib(a - 2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let fib;\n//│ fib = function fib(a) {\n//│   let scrut, tmp, tmp1, tmp2, tmp3;\n//│   scrut = a <= 1;\n//│   if (scrut === true) {\n//│     return a\n//│   }\n//│   tmp = a - 1;\n//│   tmp1 = fib(tmp);\n//│   tmp2 = a - 2;\n//│   tmp3 = fib(tmp2);\n//│   return tmp1 + tmp3;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun f(x) = g(x)\nfun g(x) = h(x)\nfun h(x) = fib(x)\nf(5)\n//│ > CALL f(5)\n//│ > | CALL g(5)\n//│ > | | CALL h(5)\n//│ > | | | CALL fib(5)\n//│ > | | | | CALL fib(4)\n//│ > | | | | | CALL fib(3)\n//│ > | | | | | | CALL fib(2)\n//│ > | | | | | | | CALL fib(1)\n//│ > | | | | | | | => 1\n//│ > | | | | | | | CALL fib(0)\n//│ > | | | | | | | => 0\n//│ > | | | | | | => 1\n//│ > | | | | | | CALL fib(1)\n//│ > | | | | | | => 1\n//│ > | | | | | => 2\n//│ > | | | | | CALL fib(2)\n//│ > | | | | | | CALL fib(1)\n//│ > | | | | | | => 1\n//│ > | | | | | | CALL fib(0)\n//│ > | | | | | | => 0\n//│ > | | | | | => 1\n//│ > | | | | => 3\n//│ > | | | | CALL fib(3)\n//│ > | | | | | CALL fib(2)\n//│ > | | | | | | CALL fib(1)\n//│ > | | | | | | => 1\n//│ > | | | | | | CALL fib(0)\n//│ > | | | | | | => 0\n//│ > | | | | | => 1\n//│ > | | | | | CALL fib(1)\n//│ > | | | | | => 1\n//│ > | | | | => 2\n//│ > | | | => 5\n//│ > | | => 5\n//│ > | => 5\n//│ > => 5\n//│ = 5\n\n\nabstract class E: S | N\ndata class S(x) with\n  fun toString() = \"S(\" + x + \"): \" + toInt(succ(x))\nclass N() with\n  fun toString() = \"N: 0\" \nfun succ(x) = S(x)\nfun toInt(x) = if x is\n  N then 0\n  S(n) then 1 + toInt(n)\n\n\n(S(S(N()))).toString()\n//│ > CALL toString()\n//│ > | CALL toString()\n//│ > | | CALL toString()\n//│ > | | => 'N: 0'\n//│ > | | CALL succ(N {})\n//│ > | | => S { x: N {} }\n//│ > | | CALL toInt(S { x: N {} })\n//│ > | | | CALL toInt(N {})\n//│ > | | | => 0\n//│ > | | => 1\n//│ > | => 'S(N: 0): 1'\n//│ > | CALL succ(S { x: N {} })\n//│ > | => S { x: S { x: N {} } }\n//│ > | CALL toInt(S { x: S { x: N {} } })\n//│ > | | CALL toInt(S { x: N {} })\n//│ > | | | CALL toInt(N {})\n//│ > | | | => 0\n//│ > | | => 1\n//│ > | => 2\n//│ > => 'S(S(N: 0): 1): 2'\n//│ = \"S(S(N: 0): 1): 2\"\n\n\ndata class Cls(a, b, c, d, e, f)\nfun id(y) =\n  if y ==\n    0 then Cls(\"aaaa\", \"bbbb\", \"cccc\", \"dddd\", \"eeee\", \"ffff\")\n    else\n      id(y - 1)\n      0\nid(2)\n//│ > CALL id(2)\n//│ > | CALL id(1)\n//│ > | | CALL id(0)\n//│ > | | => Cls {\n//│ >       a: 'aaaa',\n//│ >       b: 'bbbb',\n//│ >       c: 'cccc',\n//│ >       d: 'dddd',\n//│ >       e: 'eeee',\n//│ >       f: 'ffff'\n//│ >     }\n//│ > | => 0\n//│ > => 0\n//│ = 0\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/TraceLogIndent.mls",
    "content": ":js\n\nfun plus(x, y) = x + y\n\n:traceJS\n:e\nfun g(z) =\n  if\n    z < -1 then g(z + 1)\n    z == -1 then 42\n    z == 0 then plus(0)\n    z > 0 then g(z - 1)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.11: \t    z == 0 then plus(0)\n//│ ╙──      \t                    ^^^\n\nfun f(x, y)(z) =\n  x + y + g(z)\n\n:traceJS\nfun h(x) =\n  f(1,2)(x)\n\n:traceJS\n:re\nh(3)\n//│ > CALL h(3)\n//│ > | CALL g(3)\n//│ > | | CALL g(2)\n//│ > | | | CALL g(1)\n//│ > | | | | CALL g(0)\n//│ ═══[RUNTIME ERROR] Error: Function 'plus' expected 2 arguments but got 1\n\n:traceJS\nh(-2)\n//│ > CALL h(-2)\n//│ > | CALL g(-2)\n//│ > | | CALL g(-1)\n//│ > | | => 42\n//│ > | => 42\n//│ > => 45\n//│ = 45\n\n:traceJS\nf(1,1)(-2)\n//│ > CALL g(-2)\n//│ > | CALL g(-1)\n//│ > | => 42\n//│ > => 42\n//│ = 44\n\n:traceJS\n:re\nf(1,2)(3)\n//│ > CALL g(3)\n//│ > | CALL g(2)\n//│ > | | CALL g(1)\n//│ > | | | CALL g(0)\n//│ ═══[RUNTIME ERROR] Error: Function 'plus' expected 2 arguments but got 1\n\n:showRepl\n:traceJS\nf(1,2)(-3)\n//│ REPL> Sending: runtime.TraceLogger.enabled = true; runtime.TraceLogger.resetIndent(0)\n//│ REPL> Collected:\n//│ >  Unit {}\n//│ REPL> Sending: block$res9 = undefined\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Sending: let tmp2;try { tmp2 = - 3; block$res9 = runtime.checkCall(f(1, 2)(tmp2)); undefined; undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  CALL g(-3)\n//│ >  | CALL g(-2)\n//│ >  | | CALL g(-1)\n//│ >  | | => 42\n//│ >  | => 42\n//│ >  => 42\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  CALL g(-3)\n//│ >  | CALL g(-2)\n//│ >  | | CALL g(-1)\n//│ >  | | => 42\n//│ >  | => 42\n//│ >  => 42\n//│ >  undefined\n//│ > CALL g(-3)\n//│ > | CALL g(-2)\n//│ > | | CALL g(-1)\n//│ > | | => 42\n//│ > | => 42\n//│ > => 42\n//│ REPL> Sending: runtime.TraceLogger.enabled = false\n//│ REPL> Collected:\n//│ >  false\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(block$res9)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  45\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  45\n//│ >  undefined\n//│ = 45\n\n:showRepl\nf(1,2)(-4)\n//│ REPL> Sending: block$res10 = undefined\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Sending: let tmp3;try { tmp3 = - 4; block$res10 = runtime.checkCall(f(1, 2)(tmp3)); undefined; undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  undefined\n//│ REPL> Sending: try { runtime.checkCall(runtime.printRaw(block$res10)); undefined } catch (e) { console.log('\\u200B' + (e.stack ?? e) + '\\u200B'); }\n//│ REPL> Collected:\n//│ >  45\n//│ >  undefined\n//│ REPL> Parsed:\n//│ >  45\n//│ >  undefined\n//│ = 45\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/UnitValue.mls",
    "content": ":js\n\n\nfun foo = return ()\n\nfoo\n\nprint of foo\n//│ > ()\n\n\nfun foo = return\n\nfoo\n\nprint of foo\n//│ > ()\n\n\n:breakme // warn about useless binding\n:w\nfun foo() =\n  let x = 1\n\nprint of foo()\n//│ > ()\n\n\n:breakme // warn about useless binding\n:w\nfun foo() =\n  val x = 1\n\nprint of foo()\n//│ > ()\n\n\n:sjs\nprint of globalThis.console.log(\"Hello, world!\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp4; tmp4 = runtime.safeCall(globalThis.console.log(\"Hello, world!\")); Predef.print(tmp4)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > Hello, world!\n//│ > ()\n\n\ndata class Box(value)\n\nfun foo() =\n  if false do ()\n\nprint of Box(foo()).value\n//│ > ()\n\n\n:w\nfun foo() =\n  while false do 0\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.58: \t  while false do 0\n//│ ╙──      \t                 ^\n\nprint of Box(foo()).value\n//│ > ()\n\n\n:sjs\nfun foo() = {}\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo6; foo6 = function foo() { return runtime.Unit };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nprint of Box(foo()).value\n//│ > ()\n\n\n:sjs\nfun foo(x) =\n  set x = 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo7; foo7 = function foo(x) { x = 1; return runtime.Unit };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nprint of Box(foo(1)).value\n//│ > ()\n\n\n:e\nfun f = let x = 1\n//│ ╔══[COMPILATION ERROR] Expected a body for let bindings in expression position\n//│ ║  l.89: \tfun f = let x = 1\n//│ ╙──      \t            ^^^^^\n\nprint of f\n//│ > ()\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/While.mls",
    "content": ":js\n\n\nwhile false do ???\n\n:ssjs\nwhile false then ()\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ lbl1: while (true) {\n//│   let scrut;\n//│   scrut = false;\n//│   if (scrut === true) { continue lbl1 }\n//│   break;\n//│ }\n//│ block$res2 = runtime.Unit;\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n() => while true then ()\n//│ = fun\n\n:w\n() =>\n  while true then 0\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.24: \t  while true then 0\n//│ ╙──      \t                  ^\n//│ = fun\n\n\nlet x = true\n//│ x = true\n\n// TODO: forbid uses of keywords `then` as well as `else` in `while`\n// :re // Note: this used to throw a match error\nwhile x then set x = false\n\n\nlet x = true\n//│ x = true\n\nwhile x do set x = false\n\n\nlet x = true\nlet y = false\n//│ x = true\n//│ y = false\n\n:sjs\nfun f = while x\n  then\n    print(\"Hello World\")\n    set x = false\n  else return 42 // TODO: support `break`\nf\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f;\n//│ f = function f() {\n//│   lbl4: while (true) {\n//│     if (x2 === true) { Predef.print(\"Hello World\"); x2 = false; continue lbl4 }\n//│     return 42;\n//│   }\n//│ };\n//│ f()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > Hello World\n//│ = 42\n\nfun f = while (print(\"Hello World\"), false)\n  then 0(0)\n  else return 1\nf\n//│ > Hello World\n//│ = 1\n\n\n// * Returning inside while loop\n:expect 42\nfun f() =\n  while true do\n    return 42\nf()\n//│ = 42\n\n\nlet i = 0\n//│ i = 0\n\nfun f = while i < 3 then set i = i + 1 else return i\nf\n//│ = 3\n\n\nlet i = 0\nfun f = while print(\"checking\"); i < 3\n  then print(\"not yet\"); set i = i + 1\n  else return print(\"ok\")\nf\n//│ > checking\n//│ > not yet\n//│ > checking\n//│ > not yet\n//│ > checking\n//│ > not yet\n//│ > checking\n//│ > ok\n//│ i = 3\n\n\n// :sjs\n// * Note: infinite loop! The `let` should be outside the loop\n() =>\nwhile\n  let i = 0\n  i < 10 do set i += 1\n//│ = fun\n\n\nfun f = let i = 0 in\n  while i < 10 then set i += 1\n  else return i\nf\n//│ = 10\n\n\nlet i = 0 in while\n  let _ = print(i)\n  i < 3 do set i += 1\n//│ > 0\n//│ > 1\n//│ > 2\n//│ > 3\n\nlet i = 0 in while\n  do print(i)\n  i < 3 do set i += 1\n//│ > 0\n//│ > 1\n//│ > 2\n//│ > 3\n\n\n// * Note that the semantics of UCS-while is quite subtle.\n// * Currently, we only treat the *top-level* `else` as terminating the loop;\n// * indeed, other `else` branches are currently indistinguishable from `then` branches\n// * in normalized UCS form.\n\n// * Consider:\n\n:ucs normalized\nif x\n  and\n    y then 0\n    else 1 // this one will not terminate the loop, if we're in a `while`\n  else 42\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    x is true and\n//│ >      y is true then 0\n//│ >      else 1\n//│ >    else 42\n//│ = 42\n\n:ucs normalized\nif x\n  and\n    y then 0\n    _ then 1\n  else 42\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    x is true and\n//│ >      y is true then 0\n//│ >      else 1\n//│ >    else 42\n//│ = 42\n\n\n// TODO use\n// import \"../../mlscript-compile/Stack.mls\"\n\ndata class Cons(hd, tl)\n\n:sjs\nfun f(ls) =\n  while ls is\n    Cons(h, tl) then\n      set ls = tl\n      print(h)\n  // else print(\"Done!\")\n  print(\"Done!\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f6;\n//│ f6 = function f(ls) {\n//│   lbl6: while (true) {\n//│     let tl, h, arg$Cons$0$, arg$Cons$1$;\n//│     if (ls instanceof Cons1.class) {\n//│       arg$Cons$0$ = ls.hd;\n//│       arg$Cons$1$ = ls.tl;\n//│       tl = arg$Cons$1$;\n//│       h = arg$Cons$0$;\n//│       ls = tl;\n//│       Predef.print(h);\n//│       continue lbl6\n//│     }\n//│     break;\n//│   }\n//│   return Predef.print(\"Done!\")\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nf(0)\n//│ > Done!\n\nf(Cons(1, 0))\n//│ > 1\n//│ > Done!\n\nf(Cons(1, Cons(2, Cons(3, 0))))\n//│ > 1\n//│ > 2\n//│ > 3\n//│ > Done!\n\nfun f(ls) =\n  while\n    do print(ls)\n    ls is Cons(h, tl) do set ls = tl\n\nf(Cons(1, Cons(2, Cons(3, 0))))\n//│ > Cons(1, Cons(2, Cons(3, 0)))\n//│ > Cons(2, Cons(3, 0))\n//│ > Cons(3, 0)\n//│ > 0\n\nwhile false do\n  class A\n  new A\n\n\nlet x = 1\n//│ x = 1\n\n:sjs\nwhile x is {} do()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ lbl7: while (true) { if (x3 instanceof Object) { continue lbl7 } break; } runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n// * Mix of local mutable variable, while loop and lambdas\n:expect 2\nfun f() =\n  let\n    cnt = 2\n    savedLambda = null\n  while cnt > 0 do\n    let local = cnt\n    if cnt == 2 do\n      // This lambda should always return 2,\n      // since local is 2 and not reassigned in the while loop\n      savedLambda = () => local\n    set cnt -= 1\n  // Calls the saved lambda\n  savedLambda()\nf()\n//│ = 2\n\n\nclass Lazy[out A](f: () -> A) with\n  mut val cached: A | () = ()\n  fun get =\n    if cached === () do\n      set cached = f()\n    cached\n\n\n:expect [1, 2, 3]\n:lift\n:rewriteWhile\nlet arr = [1, 2, 3]\nlet output = mut []\nlet i = 0\nwhile i < arr.length do\n  let elem = arr.[i]\n  output.push(new Lazy(() => elem))\n  set i += 1\n[output.[0].get, output.[1].get, output.[2].get]\n//│ = [1, 2, 3]\n//│ arr = [1, 2, 3]\n//│ i = 3\n//│ output = [Lazy(_), Lazy(_), Lazy(_)]\n\n:expect [1, 2, 3]\n:lift\nlet arr = [1, 2, 3]\nlet output = mut []\nlet i = 0\nwhile i < arr.length do\n  let elem = arr.[i]\n  output.push(new Lazy(() => elem))\n  set i += 1\n[output.[0].get, output.[1].get, output.[2].get]\n//│ = [1, 2, 3]\n//│ arr = [1, 2, 3]\n//│ i = 3\n//│ output = [Lazy(_), Lazy(_), Lazy(_)]\n\n\n// ——— FIXME: ———\n\n\n:fixme\nwhile print(\"Hello World\"); false\n  then 0(0)\n  else 1\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.317: \t  then 0(0)\n//│ ╙──       \t  ^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (false literal)\n//│ ║  l.316: \twhile print(\"Hello World\"); false\n//│ ╙──       \t                            ^^^^^\n//│ > Hello World\n\n:fixme\nwhile { print(\"Hello World\"), false }\n  then 0(0)\n  else 1\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.328: \twhile { print(\"Hello World\"), false }\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.329: \t  then 0(0)\n//│ ╙──       \t^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Illegal position for prefix keyword 'else'.\n//│ ║  l.330: \t  else 1\n//│ ╙──       \t  ^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:fixme\nwhile\n    print(\"Hello World\")\n    false\n  then 0(0)\n  else 1\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.343: \t    print(\"Hello World\")\n//│ ║         \t    ^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.344: \t    false\n//│ ║         \t^^^^^^^^^\n//│ ║  l.345: \t  then 0(0)\n//│ ╙──       \t^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Illegal position for prefix keyword 'else'.\n//│ ║  l.346: \t  else 1\n//│ ╙──       \t  ^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n// * https://github.com/hkust-taco/mlscript/issues/401\n// :sjs\n:rewriteWhile\nfun f = while false do ()\nprint(f)\n//│ > ()\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/WhileDefaults.mls",
    "content": ":js\n\n\n// * Note that the following\n\n:sjs\n() => while\n  false do print(1)\n  _ do print(2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda;\n//│ lambda = (undefined, function () {\n//│   lbl: while (true) {\n//│     let scrut;\n//│     scrut = false;\n//│     if (scrut === true) {\n//│       Predef.print(1);\n//│       continue lbl\n//│     }\n//│     Predef.print(2);\n//│     continue lbl;\n//│   }\n//│ });\n//│ lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n// * ...is currently interpreted the same as the loop below\n\n() => while\n  false do print(1)\n  else print(2)\n//│ = fun\n\n// * ...and so is this one\n\n() => while\n  false do print(1)\n  true do print(2)\n//│ = fun\n\n// * This semantics for `else` branches is confusing,\n// * as the semantics of `while ... else ...` is notably not aligned with Python's own `while`/`else` form\n\n// * Some legitimate uses of `else` branches in `while`:\n\n// * This is a valid, but silly use (could have inserted the `else` part _after_ the `while`!)\nfun f = let x = 1 in\n  while x is\n    1 do\n      print(\"`x` was `1`\")\n      set x = 0\n    else\n      print(\"stopping at the `else`\")\n      return x\nf\n//│ > `x` was `1`\n//│ > stopping at the `else`\n//│ = 0\n\n// * Less silly: we still want to see what's in scope\n// * (here, the result of the `expensive` computation)\n// * upon stopping the loop\nfun f = let x = 5 in\n  while\n    let expensive = x - 1 - 1 - 1\n    expensive < 0 do set x += 2\n    else\n      print(\"the result of the expensive upon stopping the loop computation was\", expensive)\n      return\nf\n//│ > the result of the expensive upon stopping the loop computation was 2\n\n// * An `else` not at the top level of the `while`\nlet x = 3 in\n  while x >\n    0 and\n      false do ???\n      else\n        set x -= 1\n        print(\"inner `else` split reached\")\n//│ > inner `else` split reached\n//│ > inner `else` split reached\n//│ > inner `else` split reached\n// * (A weird variation of the above:)\nlet x = 3 in\n  while x >\n    0 and\n      else\n        set x -= 1\n        print(\"inner `else` split reached\")\n//│ > inner `else` split reached\n//│ > inner `else` split reached\n//│ > inner `else` split reached\n\n// * Similar: we might want to use the extracted value of `x` upon stopping the loop\nfun f(xs) =\n  while xs is\n    [y, ..ys] and\n      y > 0 do\n        print(\"still positive:\", y)\n        set xs = ys\n      else\n        return print(\"no longer positive (\" + y + \"); stopping...\")\n  print(\"all were positive!\")\n\nf of [3, 1, 2, -1, 0, -2]\n//│ > still positive: 3\n//│ > still positive: 1\n//│ > still positive: 2\n//│ > no longer positive (-1); stopping...\n\nf of [3, 1, 2, 5]\n//│ > still positive: 3\n//│ > still positive: 1\n//│ > still positive: 2\n//│ > still positive: 5\n//│ > all were positive!\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/codegen/i382.mls",
    "content": ":js\n\n// https://github.com/hkust-taco/mlscript/issues/382\n\n\n// \"Full example to demonstrate that changing else branch affect the loop behaviour\"\n\n\n// * These are infinite loops, now...\n\n() =>\n  let x = 1\n  while x ===\n    1 do\n      set x = 2\n    2 do\n      set x = 3\n      print(\"valid\")\n  else\n    set x = 2\n  print(\"not inf loop\")\n//│ = fun\n\n() =>\n  let x = 1\n  while x ===\n    1 do\n      set x = 2\n    2 do\n      set x = 3\n      print(\"valid\")\n  else\n    set x = 3\n  print(\"not inf loop\")\n//│ = fun\n\n\n// * Variation:\n\nlet x = 1\nwhile x ===\n  1 do\n    set x += 1\n  2 do\n    set x = 3\n    print(\"valid\")\n  3 do\n    set x += 1\n//│ > valid\n//│ x = 4\n// * Same, rewritten as a tail-recursive function:\n:rewriteWhile\nlet x = 1\nwhile x ===\n  1 do\n    set x = 2\n  2 do\n    set x = 3\n    print(\"valid\")\n  3 do\n    set x += 1\n//│ > valid\n//│ x = 4\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/CascadingTypeClasses.mls",
    "content": ":js\n\n\nclass Foo[A]\nclass Bar[B]\nclass Baz\n\n\nfun foo[A](using Foo[A], A) = 42\n\nusing Foo[Baz] = new Foo\n\n\n// FIXME: error message refers to `A`\n\n:e\n:re\nfoo[Baz]\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Baz (type parameter A) for call: \n//│ ║  l.18: \tfoo[Baz]\n//│ ║        \t^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.9: \tfun foo[A](using Foo[A], A) = 42\n//│ ║       \t                         ^\n//│ ╙── Missing instance: Expected: Baz (type parameter A); Available: Foo[Baz]\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n:re\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.30: \tfoo\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.9: \tfun foo[A](using Foo[A], A) = 42\n//│ ║       \t                         ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nusing Baz = new Baz\n\n:todo\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.44: \tfoo\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.9: \tfun foo[A](using Foo[A], A) = 42\n//│ ║       \t                         ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nfun foo[A](using Foo[A])(using A) = 42\n\n:todo\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.58: \tfoo\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.55: \tfun foo[A](using Foo[A])(using A) = 42\n//│ ║        \t                               ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nfun foo[A](using A)(using Foo[A]) = 42\n\n:todo\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.72: \tfoo\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.69: \tfun foo[A](using A)(using Foo[A]) = 42\n//│ ║        \t                 ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nusing Foo[Bar[Baz]] = new Foo\n\n:e\n:re\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.87: \tfoo\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.69: \tfun foo[A](using A)(using Foo[A]) = 42\n//│ ║        \t                 ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nusing Bar[Baz] = new Bar\n\n:e\n:re\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.101: \tfoo\n//│ ║         \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.69: \tfun foo[A](using A)(using Foo[A]) = 42\n//│ ║        \t                 ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nusing Bar[Int] = new Bar\n\n:e\n:re\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.115: \tfoo\n//│ ║         \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.69: \tfun foo[A](using A)(using Foo[A]) = 42\n//│ ║        \t                 ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nusing Bar[Baz] = new Bar\n\n:todo\nfoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter A) for call: \n//│ ║  l.128: \tfoo\n//│ ║         \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.69: \tfun foo[A](using A)(using Foo[A]) = 42\n//│ ║        \t                 ^\n//│ ╙── Illegal query for an unspecified type variable A.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/ClassCtxParams.mls",
    "content": ":js\n\n\nusing Int = 42\n\n\nclass Foo(using val n: Int)\n\n:expect Foo(42)\nFoo\n//│ = Foo(42)\n\n:expect 42\nFoo.n\n//│ = 42\n\n\nclass Foo(using n: Int) with\n  fun foo = n\n\n:expect Foo(_)\nFoo\n//│ = Foo(_)\n\n:expect 42\nFoo.foo\n//│ = 42\n\n\nclass Bar(using val s: Str)\n\n:e\nBar\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Str for call: \n//│ ║  l.33: \tBar\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.30: \tclass Bar(using val s: Str)\n//│ ║        \t                    ^^^^^^\n//│ ╙── Missing instance: Expected: Str; Available: Int\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nclass Bar(using s: Str)\n\n:e\nBar\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Str for call: \n//│ ║  l.46: \tBar\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.43: \tclass Bar(using s: Str)\n//│ ║        \t                ^^^^^^\n//│ ╙── Missing instance: Expected: Str; Available: Int\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n\nfun summon(using i: Int) = i\n\nclass Foo(using Int) with\n  fun foo = use[Int]\n  fun bar = summon\n\nusing Int = 99\n\n:expect Foo(_)\nFoo\n//│ = Foo(_)\n\n:expect 99\nFoo.foo\n//│ = 99\n\n:expect 99\nFoo.bar\n//│ = 99\n\n\nclass Foo(using Int)(using Str) with\n  fun f = use[Int]\n  fun g = use[Str]\n\n:e\nFoo\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Str for call: \n//│ ║  l.84: \tFoo\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.79: \tclass Foo(using Int)(using Str) with\n//│ ║        \t                           ^^^\n//│ ╙── Missing instance: Expected: Str; Available: Int\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n// FIXME: the compiler thinks T is a member of Foo!\n// FIXME: the compiler fails to compile the field projection\n\nclass T\n\n:sjs\nclass Foo(using T) with\n  print(T)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo9;\n//│ Foo9 = function Foo(tmp4) {\n//│   return globalThis.Object.freeze(new Foo.class(tmp4));\n//│ };\n//│ (class Foo8 {\n//│   static {\n//│     Foo9.class = this\n//│   }\n//│   constructor(tmp4) {\n//│     Predef.print(T1);\n//│   }\n//│   #tmp;\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [null]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:todo\n:sjs\nx => x.Foo#S\n//│ ╔══[COMPILATION ERROR] Class 'Foo' does not contain member 'S'.\n//│ ║  l.123: \tx => x.Foo#S\n//│ ╙──       \t           ^\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type T for call: \n//│ ║  l.123: \tx => x.Foo#S\n//│ ║         \t      ^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.101: \tclass Foo(using T) with\n//│ ║         \t                ^\n//│ ╙── Missing instance: Expected: T; Available: Int\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda; lambda = (undefined, function (x) { return x.S }); lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/EtaExpansion.mls",
    "content": ":js\n\nusing Int = 42\n\nfun foo()(using Int) = [use[Int]]\n\nfun bar(x)(using Int) = [x, use[Int]]\n\nfun baz(x)(using Int)(y)(using Num) = [x, use[Int], y, use[Num]]\n\n\n:e\nbaz\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Num for call: \n//│ ║  l.13: \tbaz\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.9: \tfun baz(x)(using Int)(y)(using Num) = [x, use[Int], y, use[Num]]\n//│ ║       \t                               ^^^\n//│ ╙── Missing instance: Expected: Num; Available: Int\n//│ = fun\n\n\nusing Num = 0.42\n\n// foo\n// should be expanded to\n// () => foo()\n// and then resolved to\n// () => foo()(<using> 42)\n:sir\nlet f1 = foo\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f1⁰, f1¹; define f1¹ as fun f1²() { return foo⁰()(instance$Ident(Int)⁰) }; set f1⁰ = f1²; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f1 = fun f1\n\n:expect [42]\nf1()\n//│ = [42]\n\n// bar\n// should be expanded to\n// (x) => bar(x)\n// and then resolved to\n// (x) => bar(x)(<using> 42)\n:sir\nlet f2 = bar\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f2⁰, f2¹; define f2¹ as fun f2²(x) { return bar⁰(x)(instance$Ident(Int)⁰) }; set f2⁰ = f2²; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f2 = fun f2\n\n:expect [0.42, 42]\nf2(0.42)\n//│ = [0.42, 42]\n\n// baz\n// should be expanded to\n// (x) => baz(x)\n// and then resolved to\n// (x) => baz(x)(<using> 42)\n:sir\nlet f3 = baz\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f3⁰, f3¹;\n//│ define f3¹ as fun f3²(x) {\n//│   let lambda;\n//│   define lambda as fun lambda⁰(y) {\n//│     return baz⁰(x)(instance$Ident(Int)⁰)(y)(instance$Ident(Num)⁰)\n//│   };\n//│   return lambda⁰\n//│ };\n//│ set f3⁰ = f3²;\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f3 = fun f3\n\n:expect [43, 42, 44, 0.42]\nf3(43)(44)\n//│ = [43, 42, 44, 0.42]\n\n// This should not expand\n:sir\nfoo()\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ foo⁰()(instance$Ident(Int)⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [42]\n\n// This should not expand\n:sir\nbar(0.42)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ bar⁰(0.42)(instance$Ident(Int)⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [0.42, 42]\n\n\n// :fixme // TODO: fix IR rebinding issue (each symbol should be bound at most once)\n// :checkIR\n:sir\nmodule Test with\n  fun test(j)(using Int) = 0\n  fun main(using Int) = test\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let Test⁰;\n//│ define Test⁰ as class Test¹\n//│ module Test² {\n//│   method test⁰ = fun test¹(j)(tmp) {\n//│     return 0\n//│   }\n//│   method main⁰ = fun main¹(tmp) {\n//│     let lambda;\n//│     define lambda as fun lambda¹(j) { return Test².this.test¹(j)(tmp) };\n//│     return lambda¹\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/ExplicitlySpec.mls",
    "content": ":js\n\nfun f(using i: Int): Int = i\n\n:expect 42\nf(using 42)\n//│ = 42\n\n\nfun f(using i: Int, j: Num): Num = i + j\n\n:e\n:re\nf(using 42)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.14: \tf(using 42)\n//│ ╙──      \t        ^^\n//│ ═══[RUNTIME ERROR] Error: Function 'f' expected 2 arguments but got 1\n\n:expect 45.14\nf(using 42, 3.14)\n//│ = 45.14\n\n\nfun f(using i: Int)(using j: Int)(using k: Int): Int = i + j + k\n\n:e\n:re\nf(using 32)\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.29: \tf(using 32)\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.25: \tfun f(using i: Int)(using j: Int)(using k: Int): Int = i + j + k\n//│ ║        \t                          ^^^^^^\n//│ ╙── Missing instance: Expected: Int; Available: ‹none available›\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.29: \tf(using 32)\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.25: \tfun f(using i: Int)(using j: Int)(using k: Int): Int = i + j + k\n//│ ║        \t                                        ^^^^^^\n//│ ╙── Missing instance: Expected: Int; Available: ‹none available›\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n:re\nf(using 32)(using 8)\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.48: \tf(using 32)(using 8)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.25: \tfun f(using i: Int)(using j: Int)(using k: Int): Int = i + j + k\n//│ ║        \t                                        ^^^^^^\n//│ ╙── Missing instance: Expected: Int; Available: ‹none available›\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:expect 42\nf(using 32)(using 8)(using 2)\n//│ = 42\n\n\nfun f(using i: Int)(j: Int)(using k: Int)(l: Num): Int = i + j + k + l\n\n:e\n:expect fun\nf(using 32)\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.67: \tf(using 32)\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.63: \tfun f(using i: Int)(j: Int)(using k: Int)(l: Num): Int = i + j + k + l\n//│ ║        \t                                  ^^^^^^\n//│ ╙── Missing instance: Expected: Int; Available: ‹none available›\n//│ = fun\n\n:e\n:re\nf(using 32)(8)\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.79: \tf(using 32)(8)\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.63: \tfun f(using i: Int)(j: Int)(using k: Int)(l: Num): Int = i + j + k + l\n//│ ║        \t                                  ^^^^^^\n//│ ╙── Missing instance: Expected: Int; Available: ‹none available›\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:expect fun\nf(using 32)(8)(using 2)\n//│ = fun\n\n:expect 45.14\nf(using 32)(8)(using 2)(3.14)\n//│ = 45.14\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/ForwardTypeClassUses.mls",
    "content": ":js\n\n\nusing Str = \"ok\"\n\nfun bar = M.foo()\nmodule M with\n  fun foo()(using s: Str) = s\n\n:expect \"ok\"\nbar\n//│ = \"ok\"\n\nfun bar = M.getN.foo()\nmodule M with\n  fun getN: module N = N\nmodule N with\n  fun foo()(using Str) = 1\n\n:expect 1\nbar\n//│ = 1\n\n\n:e\n:re\nfun test = M.mtd()\nmodule M with\n  fun mtd()(using n: Int) = n\nmodule Example with\n  fun foo(): module M = M\ntest\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.27: \tfun test = M.mtd()\n//│ ║        \t           ^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.29: \t  fun mtd()(using n: Int) = n\n//│ ║        \t                  ^^^^^^\n//│ ╙── Missing instance: Expected: Int; Available: Str\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:e\n:re\nfun test = Example.foo().mtd()\nmodule M with\n  fun mtd()(using n: Int) = n\nmodule Example with\n  fun foo(): module M = M\ntest\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Int for call: \n//│ ║  l.45: \tfun test = Example.foo().mtd()\n//│ ║        \t           ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.47: \t  fun mtd()(using n: Int) = n\n//│ ║        \t                  ^^^^^^\n//│ ╙── Missing instance: Expected: Int; Available: Str\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nusing Int = 42\n\nfun test = Example.foo().mtd()\nmodule M with\n  fun mtd()(using n: Int) = n\nmodule Example with\n  fun foo(): module M = M\n\n:expect 42\ntest\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/MissingDefinitions1.mls",
    "content": "\n\nfun f: Any -> Any\n\n:e\ng(5)\n//│ ╔══[COMPILATION ERROR] Name not found: g\n//│ ║  l.6: \tg(5)\n//│ ╙──     \t^\n\n:js\n:ge\n:re\nf(1)\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'f'\n//│ ║  l.14: \tf(1)\n//│ ║        \t^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.3: \tfun f: Any -> Any\n//│ ╙──     \t^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] ReferenceError: f is not defined\n\n// no errors if we don't generate code\nf(1)\n\nfun g(x) = f(x)\n\n:js\n:ge\n:re\ng(0)\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'g'\n//│ ║  l.31: \tg(0)\n//│ ║        \t^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.26: \tfun g(x) = f(x)\n//│ ╙──      \t^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] ReferenceError: g is not defined\n\n:js\n:ge\nfun g(x) = f(x)\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'f'\n//│ ║  l.42: \tfun g(x) = f(x)\n//│ ║        \t           ^\n//│ ╟── which references the symbol introduced here\n//│ ║  l.3: \tfun f: Any -> Any\n//│ ╙──     \t^^^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/MissingDefinitions2.mls",
    "content": ":js\n\n\n\n:fixme\nlet x: Int\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.6: \tlet x: Int\n//│ ╙──     \t    ^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nlet x\n//│ x = undefined\n\nx\n\n\nval x\n\n// `x` is declared, just never initilized,\n// so there shouldn't be a compilation error\n// of \"`x` not found in scope\"\nx\n\n\nval x: Int\n\n// `x` is declared, just never initilized,\n// so there shouldn't be a compilation error\n// of \"`x` not found in scope\"\nx\n\n\nfun p: Int\n\n:re\np\n//│ ═══[RUNTIME ERROR] TypeError: p is not a function\n\n\n// :ctx\nfun (++) test: (Int, Int) -> Int\n\n:re\ntest(1, 2)\n//│ ═══[RUNTIME ERROR] TypeError: test is not a function\n\n:sjs\n:re\n1 ++ 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp1; tmp1 = test(); runtime.safeCall(tmp1(1, 1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: test is not a function\n\n\ndeclare class C\n\n:re\nnew C\n//│ ═══[RUNTIME ERROR] TypeError: globalThis.C is not a constructor\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/Summon.mls",
    "content": ":js\n\n\nusing Int = 42\nusing Str = \"42\"\n\n:expect 42\nuse[Int]\n//│ = 42\n\n:expect \"42\"\nuse[Str]\n//│ = \"42\"\n\n:e\n:re\nuse[Num]\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Num (type parameter T) for call: \n//│ ║  l.17: \tuse[Num]\n//│ ║        \t^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.126: \tfun use[T](using instance: T) = instance\n//│ ║         \t                 ^^^^^^^^^^^\n//│ ╙── Missing instance: Expected: Num (type parameter T); Available: Int, Str\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:expect 42\nlet x = use[Int]\nx\n//│ = 42\n//│ x = 42\n\n\n:todo\nusing Int -> Int = id\nuse[Int -> Int](123)\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Cannot add instance with a not-yet implemented type.\n\n\n:expect -42\nfun f(using Int) = use[Int]\nusing Int = -42\nf\n//│ = -42\n\n:expect \"42\"\nfun f(using Int) = use[Str]\nusing Str = \"-42\"\nf\n//│ = \"42\"\n\n:e\nfun f(using Int) = use[Num]\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type Num (type parameter T) for call: \n//│ ║  l.53: \tfun f(using Int) = use[Num]\n//│ ║        \t                   ^^^^^^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.126: \tfun use[T](using instance: T) = instance\n//│ ║         \t                 ^^^^^^^^^^^\n//│ ╙── Missing instance: Expected: Num (type parameter T); Available: Int, Str\n\n\ndata class Some[T](value: T)\n\n\n:expect 42\nfun f[T](using Some[T]) = use[Some[T]].value\nusing Some[Int] = Some(42)\nf\n//│ = 42\n\n:e\n:re\nuse{[Some[Int]].value}\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (selection).\n//│ ║  l.74: \tuse{[Some[Int]].value}\n//│ ╙──      \t    ^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: \n//│ ║  l.74: \tuse{[Some[Int]].value}\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.126: \tfun use[T](using instance: T) = instance\n//│ ║         \t                 ^^^^^^^^^^^\n//│ ╙── Illegal query for an unspecified type variable T.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n:re\nuse([Some[Int]].value)\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: \n//│ ║  l.89: \tuse([Some[Int]].value)\n//│ ║        \t^^^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.126: \tfun use[T](using instance: T) = instance\n//│ ║         \t                 ^^^^^^^^^^^\n//│ ╙── Illegal query for an unspecified type variable T.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:expect 42\nfun f[T](using T) = use[T]\nusing Int = 42\nf[Int]\n//│ = 42\n\n:e\n:re\nf\n//│ ╔══[COMPILATION ERROR] Cannot query instance of type ‹unspecified› (type parameter T) for call: \n//│ ║  l.108: \tf\n//│ ║         \t^\n//│ ╟── Required by contextual parameter declaration: \n//│ ║  l.101: \tfun f[T](using T) = use[T]\n//│ ║         \t               ^\n//│ ╙── Illegal query for an unspecified type variable T.\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/SymbolResolution.mls",
    "content": "\nmodule M with\n  val foo: module M = M\n  fun bar: module M = M\n  fun baz(): module M = M\n  fun that: module N = N\nmodule N with\n  fun that: module M = M\n\nmodule R with\n  fun foo()(): module N = N\n  fun bar[T](using Int)(using Num)(using Str): module M = M\n\nfun foo[T](using Int)(using Num)(using Str): module M = M\n\nusing Int = 42\nusing Num = 4.2\nusing Str = \"42\"\n\n:global\n:rt\n\nM.foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:M⁰/foo⁰,typ=module:M⁰}:\n//│     t = Sel{sym=member:foo¹}:\n//│       prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│         t = Ref{sym=member:M¹} of member:M¹\n//│         sym = module:M⁰\n//│       nme = Ident of \"foo\"\n//│     sym = term:M⁰/foo⁰\n\nM.bar\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:M⁰/bar⁰,typ=module:M⁰}:\n//│     t = Sel{sym=member:bar¹}:\n//│       prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│         t = Ref{sym=member:M¹} of member:M¹\n//│         sym = module:M⁰\n//│       nme = Ident of \"bar\"\n//│     sym = term:M⁰/bar⁰\n\nM.baz\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:M⁰/baz⁰}:\n//│     t = Sel{sym=member:baz¹}:\n//│       prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│         t = Ref{sym=member:M¹} of member:M¹\n//│         sym = module:M⁰\n//│       nme = Ident of \"baz\"\n//│     sym = term:M⁰/baz⁰\n\nM.baz()\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=module:M⁰}:\n//│     lhs = Resolved{sym=term:M⁰/baz⁰}:\n//│       t = Sel{sym=member:baz¹}:\n//│         prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│           t = Ref{sym=member:M¹} of member:M¹\n//│           sym = module:M⁰\n//│         nme = Ident of \"baz\"\n//│       sym = term:M⁰/baz⁰\n//│     rhs = Tup of Nil\n\nM.foo.bar.baz()\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=module:M⁰}:\n//│     lhs = Resolved{sym=term:M⁰/baz⁰}:\n//│       t = Sel{sym=member:baz¹}:\n//│         prefix = Resolved{sym=term:M⁰/bar⁰,typ=module:M⁰}:\n//│           t = Sel{sym=member:bar¹}:\n//│             prefix = Resolved{sym=term:M⁰/foo⁰,typ=module:M⁰}:\n//│               t = Sel{sym=member:foo¹}:\n//│                 prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│                   t = Ref{sym=member:M¹} of member:M¹\n//│                   sym = module:M⁰\n//│                 nme = Ident of \"foo\"\n//│               sym = term:M⁰/foo⁰\n//│             nme = Ident of \"bar\"\n//│           sym = term:M⁰/bar⁰\n//│         nme = Ident of \"baz\"\n//│       sym = term:M⁰/baz⁰\n//│     rhs = Tup of Nil\n\nM.that.that\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:N⁰/that⁰,typ=module:M⁰}:\n//│     t = Sel{sym=member:that¹}:\n//│       prefix = Resolved{sym=term:M⁰/that²,typ=module:N⁰}:\n//│         t = Sel{sym=member:that³}:\n//│           prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│             t = Ref{sym=member:M¹} of member:M¹\n//│             sym = module:M⁰\n//│           nme = Ident of \"that\"\n//│         sym = term:M⁰/that²\n//│       nme = Ident of \"that\"\n//│     sym = term:N⁰/that⁰\n\nM.that.that.that.that.that.that\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:N⁰/that⁰,typ=module:M⁰}:\n//│     t = Sel{sym=member:that¹}:\n//│       prefix = Resolved{sym=term:M⁰/that²,typ=module:N⁰}:\n//│         t = Sel{sym=member:that³}:\n//│           prefix = Resolved{sym=term:N⁰/that⁰,typ=module:M⁰}:\n//│             t = Sel{sym=member:that¹}:\n//│               prefix = Resolved{sym=term:M⁰/that²,typ=module:N⁰}:\n//│                 t = Sel{sym=member:that³}:\n//│                   prefix = Resolved{sym=term:N⁰/that⁰,typ=module:M⁰}:\n//│                     t = Sel{sym=member:that¹}:\n//│                       prefix = Resolved{sym=term:M⁰/that²,typ=module:N⁰}:\n//│                         t = Sel{sym=member:that³}:\n//│                           prefix = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│                             t = Ref{sym=member:M¹} of member:M¹\n//│                             sym = module:M⁰\n//│                           nme = Ident of \"that\"\n//│                         sym = term:M⁰/that²\n//│                       nme = Ident of \"that\"\n//│                     sym = term:N⁰/that⁰\n//│                   nme = Ident of \"that\"\n//│                 sym = term:M⁰/that²\n//│               nme = Ident of \"that\"\n//│             sym = term:N⁰/that⁰\n//│           nme = Ident of \"that\"\n//│         sym = term:M⁰/that²\n//│       nme = Ident of \"that\"\n//│     sym = term:N⁰/that⁰\n\nR.foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:R⁰/foo²}:\n//│     t = Sel{sym=member:foo³}:\n//│       prefix = Resolved{sym=module:R⁰,typ=module:R⁰}:\n//│         t = Ref{sym=member:R¹} of member:R¹\n//│         sym = module:R⁰\n//│       nme = Ident of \"foo\"\n//│     sym = term:R⁰/foo²\n\nR.foo()\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App:\n//│     lhs = Resolved{sym=term:R⁰/foo²}:\n//│       t = Sel{sym=member:foo³}:\n//│         prefix = Resolved{sym=module:R⁰,typ=module:R⁰}:\n//│           t = Ref{sym=member:R¹} of member:R¹\n//│           sym = module:R⁰\n//│         nme = Ident of \"foo\"\n//│       sym = term:R⁰/foo²\n//│     rhs = Tup of Nil\n\nR.foo()()\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=module:N⁰}:\n//│     lhs = App:\n//│       lhs = Resolved{sym=term:R⁰/foo²}:\n//│         t = Sel{sym=member:foo³}:\n//│           prefix = Resolved{sym=module:R⁰,typ=module:R⁰}:\n//│             t = Ref{sym=member:R¹} of member:R¹\n//│             sym = module:R⁰\n//│           nme = Ident of \"foo\"\n//│         sym = term:R⁰/foo²\n//│       rhs = Tup of Nil\n//│     rhs = Tup of Nil\n\nR.foo()()()\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App:\n//│     lhs = App{typ=module:N⁰}:\n//│       lhs = App:\n//│         lhs = Resolved{sym=term:R⁰/foo²}:\n//│           t = Sel{sym=member:foo³}:\n//│             prefix = Resolved{sym=module:R⁰,typ=module:R⁰}:\n//│               t = Ref{sym=member:R¹} of member:R¹\n//│               sym = module:R⁰\n//│             nme = Ident of \"foo\"\n//│           sym = term:R⁰/foo²\n//│         rhs = Tup of Nil\n//│       rhs = Tup of Nil\n//│     rhs = Tup of Nil\n\n\n\n\n// the symbol of this Sel should be M because of the implicit application\nR.bar\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=module:M⁰}:\n//│     lhs = App:\n//│       lhs = App:\n//│         lhs = Resolved{sym=term:R⁰/bar²}:\n//│           t = Sel{sym=member:bar³}:\n//│             prefix = Resolved{sym=module:R⁰,typ=module:R⁰}:\n//│               t = Ref{sym=member:R¹} of member:R¹\n//│               sym = module:R⁰\n//│             nme = Ident of \"bar\"\n//│           sym = term:R⁰/bar²\n//│         rhs = Tup of Ls of \n//│           Fld:\n//│             term = Resolved{sym=term:instance$Ident(Int)⁰,typ=class:Int⁰}:\n//│               t = Ref{sym=member:instance$Ident(Int)¹} of member:instance$Ident(Int)¹\n//│               sym = term:instance$Ident(Int)⁰\n//│       rhs = Tup of Ls of \n//│         Fld:\n//│           term = Resolved{sym=term:instance$Ident(Num)⁰,typ=class:Num⁰}:\n//│             t = Ref{sym=member:instance$Ident(Num)¹} of member:instance$Ident(Num)¹\n//│             sym = term:instance$Ident(Num)⁰\n//│     rhs = Tup of Ls of \n//│       Fld:\n//│         term = Resolved{sym=term:instance$Ident(Str)⁰,typ=class:Str⁰}:\n//│           t = Ref{sym=member:instance$Ident(Str)¹} of member:instance$Ident(Str)¹\n//│           sym = term:instance$Ident(Str)⁰\n\n// the symbol of this Ref should be M because of the implicit application\nfoo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=module:M⁰}:\n//│     lhs = App:\n//│       lhs = App:\n//│         lhs = Resolved{sym=term:foo⁴}:\n//│           t = Ref{sym=member:foo⁵} of member:foo⁵\n//│           sym = term:foo⁴\n//│         rhs = Tup of Ls of \n//│           Fld:\n//│             term = Resolved{sym=term:instance$Ident(Int)⁰,typ=class:Int⁰}:\n//│               t = Ref{sym=member:instance$Ident(Int)¹} of member:instance$Ident(Int)¹\n//│               sym = term:instance$Ident(Int)⁰\n//│       rhs = Tup of Ls of \n//│         Fld:\n//│           term = Resolved{sym=term:instance$Ident(Num)⁰,typ=class:Num⁰}:\n//│             t = Ref{sym=member:instance$Ident(Num)¹} of member:instance$Ident(Num)¹\n//│             sym = term:instance$Ident(Num)⁰\n//│     rhs = Tup of Ls of \n//│       Fld:\n//│         term = Resolved{sym=term:instance$Ident(Str)⁰,typ=class:Str⁰}:\n//│           t = Ref{sym=member:instance$Ident(Str)¹} of member:instance$Ident(Str)¹\n//│           sym = term:instance$Ident(Str)⁰\n\n// the symbol of this TyApp should be M because of the implicit application\n// note that the resolved symbol for implicit application is on TyApp instead of on Sel\nR.bar[Int]\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=module:M⁰}:\n//│     lhs = App:\n//│       lhs = App:\n//│         lhs = TyApp{sym=term:R⁰/bar²}:\n//│           lhs = Resolved{sym=term:R⁰/bar²}:\n//│             t = Sel{sym=member:bar³}:\n//│               prefix = Resolved{sym=module:R⁰,typ=module:R⁰}:\n//│                 t = Ref{sym=member:R¹} of member:R¹\n//│                 sym = module:R⁰\n//│               nme = Ident of \"bar\"\n//│             sym = term:R⁰/bar²\n//│           targs = Ls of \n//│             Resolved{sym=class:Int⁰}:\n//│               t = Ref{sym=member:Int¹} of member:Int¹\n//│               sym = class:Int⁰\n//│         rhs = Tup of Ls of \n//│           Fld:\n//│             term = Resolved{sym=term:instance$Ident(Int)⁰,typ=class:Int⁰}:\n//│               t = Ref{sym=member:instance$Ident(Int)¹} of member:instance$Ident(Int)¹\n//│               sym = term:instance$Ident(Int)⁰\n//│       rhs = Tup of Ls of \n//│         Fld:\n//│           term = Resolved{sym=term:instance$Ident(Num)⁰,typ=class:Num⁰}:\n//│             t = Ref{sym=member:instance$Ident(Num)¹} of member:instance$Ident(Num)¹\n//│             sym = term:instance$Ident(Num)⁰\n//│     rhs = Tup of Ls of \n//│       Fld:\n//│         term = Resolved{sym=term:instance$Ident(Str)⁰,typ=class:Str⁰}:\n//│           t = Ref{sym=member:instance$Ident(Str)¹} of member:instance$Ident(Str)¹\n//│           sym = term:instance$Ident(Str)⁰\n\n// the symbol of this TyApp should be M because of the implicit application\n// note that the resolved symbol for implicit application is on TyApp instead of on Ref\nfoo[Int]\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = App{typ=module:M⁰}:\n//│     lhs = App:\n//│       lhs = App:\n//│         lhs = TyApp{sym=term:foo⁴}:\n//│           lhs = Resolved{sym=term:foo⁴}:\n//│             t = Ref{sym=member:foo⁵} of member:foo⁵\n//│             sym = term:foo⁴\n//│           targs = Ls of \n//│             Resolved{sym=class:Int⁰}:\n//│               t = Ref{sym=member:Int¹} of member:Int¹\n//│               sym = class:Int⁰\n//│         rhs = Tup of Ls of \n//│           Fld:\n//│             term = Resolved{sym=term:instance$Ident(Int)⁰,typ=class:Int⁰}:\n//│               t = Ref{sym=member:instance$Ident(Int)¹} of member:instance$Ident(Int)¹\n//│               sym = term:instance$Ident(Int)⁰\n//│       rhs = Tup of Ls of \n//│         Fld:\n//│           term = Resolved{sym=term:instance$Ident(Num)⁰,typ=class:Num⁰}:\n//│             t = Ref{sym=member:instance$Ident(Num)¹} of member:instance$Ident(Num)¹\n//│             sym = term:instance$Ident(Num)⁰\n//│     rhs = Tup of Ls of \n//│       Fld:\n//│         term = Resolved{sym=term:instance$Ident(Str)⁰,typ=class:Str⁰}:\n//│           t = Ref{sym=member:instance$Ident(Str)¹} of member:instance$Ident(Str)¹\n//│           sym = term:instance$Ident(Str)⁰\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/TrickyResolution.mls",
    "content": ":js\n\n\nclass Foo[A]\nclass Bar[B]\n\n\nfun foo[A](using Foo[A], Bar[A])\n\n\nfun foo[A](using f: Foo[A], b: Bar[A]): A\n\nusing Foo[Str] = new Foo\nusing Foo[Int] = new Foo\n\nusing Bar[Int] = new Bar\nusing Bar[Str] = new Bar\n\n\n// * Probably picks A = Int due to the Foo constraint, picking up the latest-defined Foo instance,\n// * and thus picks the Bar[Int] instance\n:fixme\nfoo\n//│ ═══[RUNTIME ERROR] TypeError: foo1 is not a function\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/TypeClasses.mls",
    "content": ":js\n\n// Syntaxes\n\nusing Int = 42\n\nusing Int as someInt = 42\n\nmodule M with\n  fun f(using Int) = 42\n\nmodule M with\n  fun f(using foo: Int) = 42\n\nmodule M with\n  fun f(using foo: Int, bar: Int) = 42\n\nmodule M with\n  fun f(using foo: Int)(bar: Int) = 42\n\nmodule M with\n  fun f(foo: Int)(using bar: Int) = 42\n\nmodule M with\n  fun f(using foo: Int)(using bar: Int) = 42\n\nmodule M with\n  fun f(using foo: Int, bar: Int) = 42\n\nmodule M with\n  fun f(using Int, Int) = 42\n\nmodule M with\n  fun foo(using Int, arg: Str) = 42\n\nmodule M with\n  fun foo(using arg: Str, Int) = 42\n\n\n// Basic Resolution\n\nabstract class Foo[T] with\n  fun foo(): T\nclass IntFoo extends Foo[Int] with\n  fun foo(): Int = 42\nclass StrFoo extends Foo[Str] with\n  fun foo(): Str = \"42\"\nmodule M with\n  fun foo(using someInt: Int): Int = someInt\n  fun strFoo(using someFoo: Foo[Str]): Str = someFoo.foo()\n  fun intFoo(using someFoo: Foo[Int]): Int = someFoo.foo()\n  fun tFoo[T](using someFoo: Foo[T]): T = someFoo.foo()\n\nusing Int as i = 24\n\nusing Foo[Int] = new IntFoo()\n\nusing Foo[Str] = new StrFoo()\n\n// should resolve to foo(i)\n:expect 24\nM.foo\n//│ = 24\n\n// should resolve to intFoo(new IntFoo())\n:expect 42\nM.intFoo\n//│ = 42\n\n// should resolve to strFoo(new StrFoo())\n:expect \"42\"\nM.strFoo\n//│ = \"42\"\n\n// should resolve to 100 + intFoo(new IntFoo())\n:expect 142\n100 + M.intFoo\n//│ = 142\n\n// should be able to resolve in function body from outer scope\n:expect 42\nfun f: Int = M.intFoo\nf\n//│ = 42\n\n// should be able to resolve in function body from parameters\n:expect 3.14\nmodule N with\n  fun f(using someNum: Num): Num = someNum\n  fun g(using Num): Num = N.f\nusing Num = 3.14\nN.g\n//│ = 3.14\n\n\n// Parameterized Type Resolution\n\n// should resolve to tFoo(new StrFoo())\n:expect \"42\"\nM.tFoo\n//│ = \"42\"\n\n// should resolve to tFoo(new IntFoo())\n:expect 42\nM.tFoo[Int]\n//│ = 42\n\nabstract class Bar[A, B] with\n  fun bar(): Str\nclass IntStrBar extends Bar[Int, Str] with\n  fun bar(): Str = \"IntStr\"\nclass StrIntBar extends Bar[Str, Int] with\n  fun bar(): Str = \"StrInt\"\nmodule M with\n  fun tBar1[T](using someFoo: Bar[Int, T]): Str = someFoo.bar()\n  fun tBar2[T](using someFoo: Bar[Str, T]): Str = someFoo.bar()\n  fun tBar3[A, B](using someFoo: Bar[A, B]): Str = someFoo.bar()\n\nusing Bar[Int, Str] = new IntStrBar()\nusing Bar[Str, Int] = new StrIntBar()\n\n// should resolve to tFoo1(new IntStrBar())\n:expect \"IntStr\"\nM.tBar1\n//│ = \"IntStr\"\n\n// should resolve to tFoo2(new StrIntBar())\n:expect \"StrInt\"\nM.tBar2\n//│ = \"StrInt\"\n\n// should resolve to tFoo3(new StrIntBar())\n:expect \"StrInt\"\nM.tBar3\n//│ = \"StrInt\"\n\n// should resolve to tFoo3(new IntStrBar())\n:expect \"IntStr\"\nM.tBar3[Int, Str]\n//│ = \"IntStr\"\n\n\n// Monoid Example\n\nabstract class Monoid[T] with\n  fun combine(a: T, b: T): T\n  fun empty: T\n\nobject IntAddMonoid extends Monoid[Int] with\n  fun combine(a: Int, b: Int): Int = a + b\n  fun empty: Int = 0\n\nobject IntMulMonoid extends Monoid[Int] with\n  fun combine(a: Int, b: Int): Int = a * b\n  fun empty: Int = 1\n\nmodule M with\n  fun foldInt(x1: Int, x2: Int, x3: Int)(using m: Monoid[Int]): Int =\n    m.combine(x1, m.combine(x2, m.combine(x3, m.empty)))\n  fun fold[T](x1: T, x2: T, x3: T)(using m: Monoid[T]): T =\n    m.combine(x1, m.combine(x2, m.combine(x3, m.empty)))\n\n:expect 9\nusing Monoid[Int] = IntAddMonoid\nM.foldInt(2, 3, 4)\n//│ = 9\n\n:expect 24\nusing Monoid[Int] = IntMulMonoid\nM.foldInt(2, 3, 4)\n//│ = 24\n\n:expect 6\nusing Monoid[Int] = IntAddMonoid\nM.fold(1, 2, 3)\n//│ = 6\n\n\n// Generalized Module Methods\n\nusing Int = 42\n\n:expect 42\nfun foo()(using i: Int) = i\nfoo()\n//│ = 42\n\n:expect 42\nfun main() =\n  fun foo()(using i: Int) = i\n  foo()\nmain()\n//│ = 42\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ctx/TypeResolution.mls",
    "content": "\nclass Foo with\n  val foo: Foo = new Foo\n\n:rt\nnew Foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = New{typ=class:Foo⁰}:\n//│     cls = Resolved{sym=class:Foo⁰}:\n//│       t = Ref{sym=member:Foo¹} of member:Foo¹\n//│       sym = class:Foo⁰\n\n// * TODO: dynamic new-expression should also be resolvable for its type\n:rt\nnew! Foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = DynNew:\n//│     cls = Resolved{sym=class:Foo⁰}:\n//│       t = Ref{sym=member:Foo¹} of member:Foo¹\n//│       sym = class:Foo⁰\n\nval foo: Foo = new Foo\n\n:rt\nfoo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:foo⁰,typ=class:Foo⁰}:\n//│     t = Ref{sym=member:foo¹} of member:foo¹\n//│     sym = term:foo⁰\n\n:rt\nfoo.foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:Foo⁰/foo²,typ=class:Foo⁰}:\n//│     t = Sel{sym=member:foo³}:\n//│       prefix = Resolved{sym=term:foo⁰,typ=class:Foo⁰}:\n//│         t = Ref{sym=member:foo¹} of member:foo¹\n//│         sym = term:foo⁰\n//│       nme = Ident of \"foo\"\n//│     sym = term:Foo⁰/foo²\n\nclass Foo2[A, B] with\n  val foo: Foo2[Int, Str] = new Foo2\n\n:rt\nnew Foo2\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = New{typ=class:Foo2⁰}:\n//│     cls = Resolved{sym=class:Foo2⁰}:\n//│       t = Ref{sym=member:Foo2¹} of member:Foo2¹\n//│       sym = class:Foo2⁰\n\n// * TODO: dynamic new-expression should also be resolvable for its type\n:rt\nnew! Foo2\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = DynNew:\n//│     cls = Resolved{sym=class:Foo2⁰}:\n//│       t = Ref{sym=member:Foo2¹} of member:Foo2¹\n//│       sym = class:Foo2⁰\n\nval foo: Foo2[Str, Int] = new Foo2\n\n:rt\nfoo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:foo⁴,typ=class:Foo2⁰[class:Str⁰, class:Int⁰]}:\n//│     t = Ref{sym=member:foo⁵} of member:foo⁵\n//│     sym = term:foo⁴\n\n:rt\nfoo.foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:Foo2⁰/foo⁶,typ=class:Foo2⁰[class:Int⁰, class:Str⁰]}:\n//│     t = Sel{sym=member:foo⁷}:\n//│       prefix = Resolved{sym=term:foo⁴,typ=class:Foo2⁰[class:Str⁰, class:Int⁰]}:\n//│         t = Ref{sym=member:foo⁵} of member:foo⁵\n//│         sym = term:foo⁴\n//│       nme = Ident of \"foo\"\n//│     sym = term:Foo2⁰/foo⁶\n\n:rt\nfun f(x: Foo) = x\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   stats = Ls of \n//│     TermDefinition:\n//│       k = Fun\n//│       sym = member:f⁰\n//│       tsym = term:f¹\n//│       params = Ls of \n//│         ParamList:\n//│           params = Ls of \n//│             Param:\n//│               sym = x⁰\n//│               sign = S of Resolved{sym=class:Foo⁰}:\n//│                 t = Ref{sym=member:Foo¹} of member:Foo¹\n//│                 sym = class:Foo⁰\n//│               modulefulness = Modulefulness of N\n//│       body = S of Ref{sym=x⁰,typ=class:Foo⁰} of x⁰\n//│       modulefulness = Modulefulness of N\n//│   res = Lit of UnitLit of false\n\nmodule M\nobject O\n\n:rt\nM\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│     t = Ref{sym=member:M¹} of member:M¹\n//│     sym = module:M⁰\n\n:rt\nO\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=object:O⁰,typ=object:O⁰}:\n//│     t = Ref{sym=member:O¹} of member:O¹\n//│     sym = object:O⁰\n\nval m: module M = M\nval o: O = O\n\n:rt\nm\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:m⁰,typ=module:M⁰}:\n//│     t = Ref{sym=member:m¹} of member:m¹\n//│     sym = term:m⁰\n\n:rt\no\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   res = Resolved{sym=term:o⁰,typ=object:O⁰}:\n//│     t = Ref{sym=member:o¹} of member:o¹\n//│     sym = term:o⁰\n\n:rt\nfun f(module m: M): module M = m\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   stats = Ls of \n//│     TermDefinition:\n//│       k = Fun\n//│       sym = member:f²\n//│       tsym = term:f³\n//│       params = Ls of \n//│         ParamList:\n//│           params = Ls of \n//│             Param:\n//│               sym = m²\n//│               sign = S of Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│                 t = Ref{sym=member:M¹} of member:M¹\n//│                 sym = module:M⁰\n//│               modulefulness = Modulefulness of S of module:M⁰\n//│       sign = S of Resolved{sym=module:M⁰,typ=module:M⁰}:\n//│         t = Ref{sym=member:M¹} of member:M¹\n//│         sym = module:M⁰\n//│       body = S of Ref{sym=m²,typ=module:M⁰} of m²\n//│       modulefulness = Modulefulness of S of module:M⁰\n//│   res = Lit of UnitLit of false\n\n:rt\nfun f(o: O) = o\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   stats = Ls of \n//│     TermDefinition:\n//│       k = Fun\n//│       sym = member:f⁴\n//│       tsym = term:f⁵\n//│       params = Ls of \n//│         ParamList:\n//│           params = Ls of \n//│             Param:\n//│               sym = o²\n//│               sign = S of Resolved{sym=object:O⁰,typ=object:O⁰}:\n//│                 t = Ref{sym=member:O¹} of member:O¹\n//│                 sym = object:O⁰\n//│               modulefulness = Modulefulness of N\n//│       body = S of Ref{sym=o²,typ=object:O⁰} of o²\n//│       modulefulness = Modulefulness of N\n//│   res = Lit of UnitLit of false\n\n// The implicit `this` (class:Foo) in the SynthSel(class:Foo, \"foo\") should be resolved correctly.\n:rt\nclass Foo with\n  val foo = 42\n  foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   stats = Ls of \n//│     Plain:\n//│       kind = Cls\n//│       sym = class:Foo²\n//│       bsym = member:Foo³\n//│       body = ObjBody of Blk:\n//│         stats = Ls of \n//│           TermDefinition:\n//│             k = ImmutVal\n//│             sym = member:foo⁸\n//│             tsym = term:Foo²/foo⁹\n//│             body = S of Lit of IntLit of 42\n//│             flags = (method)\n//│             modulefulness = Modulefulness of N\n//│         res = Resolved{sym=term:Foo²/foo⁹}:\n//│           t = SynthSel{sym=member:foo⁸}:\n//│             prefix = Ref{sym=class:Foo²,typ=class:Foo²} of class:Foo²\n//│             nme = Ident of \"foo\"\n//│           sym = term:Foo²/foo⁹\n//│   res = Lit of UnitLit of false\n\n// The explicit `this` (class:Foo) in the Sel(class:Foo, \"foo\") should be resolved correctly.\n:rt\nclass Foo with\n  val foo = 42\n  this.foo\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk:\n//│   stats = Ls of \n//│     Plain:\n//│       kind = Cls\n//│       sym = class:Foo⁴\n//│       bsym = member:Foo⁵\n//│       body = ObjBody of Blk:\n//│         stats = Ls of \n//│           TermDefinition:\n//│             k = ImmutVal\n//│             sym = member:foo¹⁰\n//│             tsym = term:Foo⁴/foo¹¹\n//│             body = S of Lit of IntLit of 42\n//│             flags = (method)\n//│             modulefulness = Modulefulness of N\n//│         res = Resolved{sym=term:Foo⁴/foo¹¹}:\n//│           t = Sel{sym=member:foo¹⁰}:\n//│             prefix = Ref{sym=class:Foo⁴,typ=class:Foo⁴} of class:Foo⁴\n//│             nme = Ident of \"foo\"\n//│           sym = term:Foo⁴/foo¹¹\n//│   res = Lit of UnitLit of false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/basic.mls",
    "content": ":js\n:noInline\n:deadParamElim debug\n\n\n:soir\nprivate fun f(a) = 0\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁰; define f⁰ as fun f¹() { return 0 }; f¹()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:soir\nprivate fun f(a, b) = 0\nf(1, 2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0, 1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f²; define f² as fun f³() { return 0 }; f³()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:soir\nprivate fun f(a)(b) = 0\nf(1)(2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁴; define f⁴ as fun f⁵()(b) { return 0 }; f⁵()(2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n\n:soir\nprivate fun f(a) = a\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁶; define f⁶ as fun f⁷(a) { return a }; f⁷(42)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n:soir\nprivate fun f(a, b) = a + b\nf(1, 2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁸; define f⁸ as fun f⁹(a, b) { return +⁰(a, b) }; f⁹(1, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n\n:soir\nprivate fun f(a, b) = a\nf(1, 2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f¹⁰; define f¹⁰ as fun f¹¹(a) { return a }; f¹¹(1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:soir\nprivate fun f(a, b) = b\nf(1, 2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f¹²; define f¹² as fun f¹³(b) { return b }; f¹³(2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\n\n:soir\nprivate fun f(a)(b) = a\nf(1)(2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f¹⁴; define f¹⁴ as fun f¹⁵(a)(b) { return a }; f¹⁵(1)(2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:soir\nprivate fun f(a)(b) = b\nf(1)(2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f¹⁶; define f¹⁶ as fun f¹⁷()(b) { return b }; f¹⁷()(2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\n\n:soir\nprivate fun f(a) = 0\nf(1)\nf(2)\nf(3)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f¹⁸; define f¹⁸ as fun f¹⁹() { return 0 }; do f¹⁹(); do f¹⁹(); f¹⁹()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:soir\nprivate fun g() =\n  fun f(a) = 3\n  f(4)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let g⁰; define g⁰ as fun g¹() { let f; define f as fun f²⁰() { return 3 }; return f²⁰() }; end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n\n:soir\nclass Foo(x) with\n  fun bar(a) = x\nlet foo = Foo(1)\nfoo.bar(99)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let Foo⁰, foo⁰;\n//│ define Foo⁰ as class Foo²(x) {\n//│   private val x⁰;\n//│   constructor Foo¹ {\n//│     set x⁰ = x;\n//│     end\n//│   }\n//│   method bar⁰ = fun bar¹(a) { return x⁰ }\n//│ };\n//│ set foo⁰ = Foo¹(1);\n//│ foo⁰.bar﹖(99)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n//│ foo = Foo(_)\n\n\nclass Foo(x) with\n  fun bar(a) = a\nlet foo = Foo(1)\nfoo.bar(99)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 99\n//│ foo = Foo(_)\n\n\n\n:expect 1\nclass Foo(x) with\n  fun get() = x\nFoo(1).get()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n\n\n:expect 1\ndata class Pair(a, b)\nprivate fun fst(p) = if p is Pair(a, b) then a\nfst(Pair(1, 2))\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n\n:expect 2\ndata class Pair(a, b)\nprivate fun snd(p) = if p is Pair(a, b) then b\nsnd(Pair(1, 2))\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 2\n\n\n\n\n:expect 43\nprivate fun g(x) = x + 1\nprivate fun f(a) = g(a)\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 43\n\n\n\n\n\n\n:expect 42\nprivate fun f(a) =\n  let x = a\n  x\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 42\n\n\n\n\n\n:expect 1\nprivate fun apply(f) = f(0)\nprivate fun inc(x) = x + 1\napply(inc)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n\n\n:expect 1\ndata class Pair(a, b)\nprivate fun f(p) = p.Pair#a\nf(Pair(1, 2))\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n\n\nprivate fun f(a) = g(a)\nprivate fun g(x) = 3\nf(1)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > prodfun g#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 3\n\n:deadParamElim debug poly\nfun f(a) = g(a)\nfun g(x) = 3\nf(1)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ f@3 -> eliminable: {0}\n//│ dead-param-elim > prodfun g#0 @ f@3.g@1 -> eliminable: {0}\n//│ dead-param-elim > prodfun g#0 @ f@4.g@1 -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 3\n\nf(2)\ng(1)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 3\n\n\n:deadParamElim debug mono\n:expect [3, 4]\nprivate fun f(x) =\n  fun g(a, b, ...rest) = \n    print(x)\n    rest\n  g(1, 2, 3, 4)\nf(2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun g#0 @ <root> -> eliminable: {0, 1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ > 2\n//│ = [3, 4]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/clash.mls",
    "content": ":js\n:noInline\n:deadParamElim debug\n\n\n\n\n// g has dead param `b`, but f has live param `a`\n:expect 0\nprivate fun f(a) = a\nprivate fun g(b) = 0\nprivate fun test(x)(y) = if false then x else y\nprivate fun m() = test(f)(g)(5)\nm()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n\n\n:expect 3\nprivate fun f(a)(b) = 0\nprivate fun g(a)(b) = a + b\nprivate fun main(x)(y) = if false then x else y\nprivate fun m1() = main(f)(g)(1)(2)\nm1()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 3\n\n\n:expect 5\nprivate fun f(a) = a\nprivate fun g(b) = 0\nlet h = if true then f else g\nh(5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 5\n//│ h = fun f\n\n\n\n// f, g, h all flow to the same call site\n:expect 0\nprivate fun f(a) = a\nprivate fun g(b) = 0\nprivate fun h(c) = 0\nprivate fun pick(x)(y)(z) = if false then x else if false then y else z\nprivate fun m() = pick(f)(g)(h)(5)\nm()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n\n\n\n\n\n:expect 1\nprivate fun f(a)(b) = 0\nprivate fun g(a)(b) = a\nprivate fun choose(x)(y) = if false then x else y\nprivate fun m() = choose(f)(g)(1)(2)\nm()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n\n\n:expect 1\nprivate fun f(a, b) = 0\nprivate fun g(a, b) = a\nprivate fun choose(x)(y) = if false then x else y\nprivate fun m() = choose(f)(g)(1, 2)\nm()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n\n\n:soir\n[1,2,3].map((x, i, a) => x + 1)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let tmp, lambda⁰;\n//│ set tmp = [1, 2, 3];\n//│ define lambda⁰ as fun lambda¹(x, i, a) { return +⁰(x, 1) };\n//│ tmp.map﹖(lambda¹)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [2, 3, 4]\n\n\n\n:expect [4, 5]\nprivate fun f(a, b, ...rest) = rest\nprivate fun g(a, b, c, ...rest) = rest\n(if false then f else g)(1,2,3,4,5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0, 1}\n//│ dead-param-elim > prodfun g#0 @ <root> -> eliminable: {0, 1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = [4, 5]\n\n\n:expect [3, 4, 5]\nprivate fun f(a, b, ...rest) = rest\nprivate fun g(a, b, c, ...rest) = rest\n(if true then f else g)(1,2,3,4,5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0, 1}\n//│ dead-param-elim > prodfun g#0 @ <root> -> eliminable: {0, 1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = [3, 4, 5]\n\n\n:expect [3, 4, 5]\npublic fun f(a, b, ...rest) = rest\npublic fun g(a, b, c, ...rest) = rest\n(if true then f else g)(1,2,3,4,5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = [3, 4, 5]\n\n:expect [4, 5]\n(if false then f else g)(1,2,3,4,5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = [4, 5]\n\n:expect [3, 4, 5]\n(if true then f else g)(1,2,3,4,5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = [3, 4, 5]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/class-in-fun.mls",
    "content": ":js\n:deadParamElim debug\n\n\n\n\n:lift\n:soir\n:expect 1\n:noInline\nprivate fun f(used, unused) =\n  class C with\n    fun get() = used\n  new C\nf(1, 2).get()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let C⁰, f⁰, tmp;\n//│ define C⁰ as class C¹ {\n//│   private val used⁰;\n//│   constructor(used) {\n//│     set used⁰ = used;\n//│     end\n//│   }\n//│   method get⁰ = fun get¹() {\n//│     return used⁰\n//│   }\n//│ };\n//│ define f⁰ as fun f¹(used) { return new C¹(used) };\n//│ set tmp = f¹(1);\n//│ tmp.get﹖()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\n\n\n\n:js\n:lift\nprivate fun foo(y) =\n  class M with\n    fun bar() = set y = 2\n  (new M).bar()\nfoo(10)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/config-flags.mls",
    "content": ":js\n:noInline\n\n\n\n\n\n\n// DPE is on by default, no debug output\n:soir\nprivate fun noFlag(a) = 0\nnoFlag(42)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let noFlag⁰; define noFlag⁰ as fun noFlag¹() { return 0 }; noFlag¹()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:deadParamElim\nprivate fun bareFlag(a) = 0\nbareFlag(42)\n//│ = 0\n\n\n:deadParamElim mono debug\nprivate fun monoDebug(a) = 0\nmonoDebug(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun monoDebug#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n\n:deadParamElim debug mono\n:soir\nprivate fun debugMono(a) = 0\ndebugMono(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun debugMono#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let debugMono⁰; define debugMono⁰ as fun debugMono¹() { return 0 }; debugMono¹()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:deadParamElim mono poly\nprivate fun conflictTest(a) = 0\nconflictTest(42)\n//│ /!!!\\ ':deadParamElim' flags 'mono' and 'poly' conflict\n//│ = 0\n\n// :deadParamElim off — disable DPE, dead param should NOT be eliminated\n:deadParamElim off\n:soir\nprivate fun dpeOff(a) = 0\ndpeOff(42)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let dpeOff⁰; define dpeOff⁰ as fun dpeOff¹(a) { return 0 }; dpeOff¹(42)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n\n:deadParamElim foo\nprivate fun unknownFlag(a) = 0\nunknownFlag(42)\n//│ /!!!\\ Unknown ':deadParamElim' flags: foo\n//│ = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/dead-ref.mls",
    "content": ":js\n:noInline\n:deadParamElim debug\n\n\n\n:soir\nprivate fun f(a) =\n  a = 3\n  g(a)\nprivate fun g(a) = 2\nf(undefined)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > prodfun g#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁰, g⁰; define f⁰ as fun f¹() { return g¹() }; define g⁰ as fun g¹() { return 2 }; f¹()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\ndata class Box(x)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n\n\n:soir\nprivate fun f(a) = Box(a)\nif f(42) is Box(v) then 0\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f², scrut;\n//│ define f² as fun f³() {\n//│   return Box⁰(undefined)\n//│ };\n//│ set scrut = f³();\n//│ match scrut\n//│   Box¹ =>\n//│     0\n//│   else\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n\n\n:soir\nprivate fun f(a) =\n  let x = a\n  0\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁴; define f⁴ as fun f⁵() { return 0 }; f⁵()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/lambda.mls",
    "content": ":js\n:deadParamElim debug\n\n\n\n:expect 0\nlet f = (a) => 0\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n//│ f = fun f\n\n\n:expect 42\nlet f = (a) => a\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 42\n//│ f = fun f\n\n:noInline\n:expect 0\nprivate fun apply(f, x) = f(x)\napply((a) => 0, 42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun apply#0 @ <root> -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n\n:expect 43\nprivate fun apply(f, x) = f(x)\napply((a) => a + 1, 42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 43\n\n\n\n\nprivate fun f(a) = a\nlet g = (b) => 0\nprivate fun pick(x)(y) = if false then x else y\npick(f)(g)(5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n//│ g = fun g\n\n\nfun f(a) = 0\nlet g = (b) => 0\nprivate fun pick(x)(y) = if false then x else y\npick(f)(g)(5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n//│ g = fun g\n\n\n\n:expect 42\nprivate fun f(a) =\n  let g = () => a\n  g()\nf(42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 42\n\n\n\n// two `apply`, one has dead param, another does not\n:noInline\nprivate fun apply(f, x) = f(x)\nprivate fun main(f1, f2) =\n  apply(f1, 42) + apply(f2, 0)\nprivate fun main1() = main((a) => 0, (a) => a + 1)\nmain1()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n// two `apply`, one has dead param, another does not;\n// but if `apply` is inlined, we can eliminate the `a` in `(a) => 0`\nprivate fun apply(f, x) = f(x)\nprivate fun main(f1, f2) =\n  apply(f1, 42) + apply(f2, 0)\nprivate fun main1() = main((a) => 0, (a) => a + 1)\nmain1()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun lambda#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n:deadParamElim debug poly\n:noInline\nprivate fun apply(f, x) = f(x)\nprivate fun main(f1, f2) =\n  apply(f1, 42) + apply(f2, 0)\nprivate fun main1() = main((a) => 0, (a) => a + 1)\nmain1()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun apply#0 @ main1@10.main@8.apply@2 -> eliminable: {1}\n//│ dead-param-elim > prodfun apply#0 @ main1@13.main@8.apply@2 -> eliminable: {1}\n//│ dead-param-elim > prodfun lambda#0 @ main1@10 -> eliminable: {0}\n//│ dead-param-elim > prodfun lambda#0 @ main1@13 -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n:deadParamElim debug mono\n:expect 0\nprivate fun f = (a) => 0\nf(3)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun lambda#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/module.mls",
    "content": ":js\n:deadParamElim debug\n\n\n\n\nmodule M with\n  private fun f(a) = 0\n  private fun g(b) = b\nM.f(1)\nM.g(2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 2\n\n\n:expect 3\nmodule M with\n  val x = 3\n  private fun f(a) = x\n  private fun main() = M.f(42)\nM.main()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ <root> -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 3\n\n\n:expect 42\nmodule M with\n  private fun f(a) = a\n  private fun main() = M.f(42)\nM.main()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 42\n\n\n\n\nmodule M with\n  private fun f(a) = a\n  private fun g(b) = 0\n  private fun pick(x)(y) = if false then x else y\n  private fun main() = M.pick(M.f)(M.g)(5)\nM.main()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n\n\n:expect 125\nmodule M with\n  data class Foo(x) with\n    private fun m() = this.x + 1\n    private fun n(y) = this.x + y\nlet foo = M.Foo(123)\nfoo M.Foo::n(2)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 125\n//│ foo = Foo(123)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/multiArgLists.mls",
    "content": ":js\n:noInline\n\n// Test: Dead parameter elimination with multiple parameter lists\n:deadParamElim\n:soir\nprivate fun f(a)(b) = a\nf(42)(99)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁰; define f⁰ as fun f¹(a)(b) { return a }; f¹(42)(99)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n// Test: Both params dead across two parameter lists\n:deadParamElim\n:soir\nprivate fun g(x)(y) = 0\ng(1)(2)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let g⁰; define g⁰ as fun g¹()(y) { return 0 }; g¹()(2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n// Test: Dead param in second list only\n:deadParamElim\n:soir\nprivate fun h(x)(y) = x\nh(5)(10)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let h⁰; define h⁰ as fun h¹(x)(y) { return x }; h¹(5)(10)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 5\n\n// Test: Dead param in first list only\n:deadParamElim\n:soir\nprivate fun j(x)(y) = y\nj(5)(10)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let j⁰; define j⁰ as fun j¹()(y) { return y }; j¹()(10)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 10\n\n// Test: Three parameter lists, middle one dead\n:deadParamElim\n:soir\nprivate fun k(a)(b)(c) = a + c\nk(1)(2)(3)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let k⁰; define k⁰ as fun k¹(a)(b)(c) { return +⁰(a, c) }; k¹(1)(2)(3)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 4\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/recursive.mls",
    "content": ":js\n:deadParamElim debug\n\n\n:expect 0\n:soir\n:noTailRec\nprivate fun countdown(n, unused) =\n  if n == 0 then 0\n  else countdown(n - 1, unused)\ncountdown(5, 42)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun countdown#0 @ <root> -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let countdown⁰;\n//│ define countdown⁰ as fun countdown¹(n) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return countdown¹(tmp)\n//│   end\n//│ };\n//│ countdown¹(5)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n\n:soir\nprivate fun countdown(n) =\n  if n == 0 then 0\n  else countdown(n - 1)\ncountdown(5)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let countdown²;\n//│ define countdown² as fun countdown³(n) {\n//│   loop loopLabel:\n//│     let scrut, tmp;\n//│     set scrut = Predef⁰.equals⁰(n, 0);\n//│     match scrut\n//│       true =>\n//│         return 0\n//│       else\n//│         set tmp = -⁰(n, 1);\n//│         set n = tmp;\n//│         continue loopLabel\n//│     end\n//│   unreachable /* Rest of abortive labelled block */\n//│ };\n//│ countdown³(5)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n\nprivate fun isEven(n) = if n == 0 then true else isOdd(n - 1)\nprivate fun isOdd(n) = if n == 0 then false else isEven(n - 1)\nisEven(10)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = true\n\n\n\n:soir\n:noTailRec\nprivate fun ping(n, unused) = if n == 0 then 0 else pong(n - 1, unused)\nprivate fun pong(n, unused) = if n == 0 then 0 else ping(n - 1, unused)\nping(5, 99)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun ping#0 @ <root> -> eliminable: {1}\n//│ dead-param-elim > prodfun pong#0 @ <root> -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let ping⁰, pong⁰;\n//│ define ping⁰ as fun ping¹(n) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return pong¹(tmp)\n//│   end\n//│ };\n//│ define pong⁰ as fun pong¹(n) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return ping¹(tmp)\n//│   end\n//│ };\n//│ ping¹(5)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n\n:soir\n:noTailRec\nfun ping(n, unused) = if n == 0 then 0 else pong(n - 1, unused)\nfun pong(n, unused) = if n == 0 then 0 else ping(n - 1, unused)\nping(5, 99)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let ping², pong²;\n//│ define ping² as fun ping³(n, unused) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return pong³(tmp, unused)\n//│   end\n//│ };\n//│ define pong² as fun pong³(n, unused) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return ping³(tmp, unused)\n//│   end\n//│ };\n//│ ping³(5, 99)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:expect 0\nping(5, 0)\npong(5, 0)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n:soir\n:noTailRec\nprivate fun ping(n)(unused) = if n == 0 then 0 else pong(n - 1)(unused)\nprivate fun pong(n)(unused) = if n == 0 then 0 else ping(n - 1)(unused)\nping(5)(99)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let ping⁴, pong⁴;\n//│ define ping⁴ as fun ping⁵(n)(unused) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return pong⁵(tmp)(unused)\n//│   end\n//│ };\n//│ define pong⁴ as fun pong⁵(n)(unused) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return ping⁵(tmp)(unused)\n//│   end\n//│ };\n//│ ping⁵(5)(99)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:noTailRec\nfun ping(n)(unused) = if n == 0 then 0 else pong(n - 1)(unused)\nfun pong(n)(unused) = if n == 0 then 0 else ping(n - 1)(unused)\nping(5)(99)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n\n:expect 0\nping(5)(0)\npong(5)(0)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n\n\n\n:soir\n:noTailRec\nmodule M with\n  fun ping(n, unused) = if n == 0 then 0 else pong(n - 1, unused)\nprivate fun pong(n, unused) = if n == 0 then 0 else M.ping(n - 1, unused)\nclass Test(a) with\n  fun f() = pong(3, 123)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun pong#0 @ <root> -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let Test⁰, pong⁶, M⁰;\n//│ define pong⁶ as fun pong⁷(n) {\n//│   let scrut, tmp;\n//│   set scrut = Predef⁰.equals⁰(n, 0);\n//│   match scrut\n//│     true =>\n//│       return 0\n//│     else\n//│       set tmp = -⁰(n, 1);\n//│       return M¹.ping⁶(tmp, undefined)\n//│   end\n//│ };\n//│ define M⁰ as class M²\n//│ module M¹ {\n//│   method ping⁷ = fun ping⁶(n, unused) {\n//│     let scrut, tmp;\n//│     set scrut = Predef⁰.equals⁰(n, 0);\n//│     match scrut\n//│       true =>\n//│         return 0\n//│       else\n//│         set tmp = -⁰(n, 1);\n//│         return pong⁷(tmp)\n//│     end\n//│   }\n//│ };\n//│ define Test⁰ as class Test¹(a) { private val a⁰; method f⁰ = fun f¹() { return pong⁷(3) } };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 0\nTest(2).f()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/refresher.mls",
    "content": ":js\n:deadParamElim debug poly\n\n\n:checkIR\n:expect 1\nfun f(used, unused) =\n  class C with\n    fun get() = used\n  new C\nf(1, 2).get()\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun f#0 @ f@1 -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 1\n\n\n\n:checkIR\nfun foo(y) =\n  class M with\n    fun bar() = set y = 2\n  (new M).bar()\nfoo(10)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun foo#0 @ foo@3 -> eliminable: {0}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n\n\n\n:checkIR\n:expect 10\nfun g(x, dead) =\n  class Pair with\n    fun first() = x\n    fun second() = x + x\n  let p = new Pair\n  p.first()\ng(10, 99)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun g#0 @ g@3 -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 10\n\n\n\n:checkIR\n:expect 13\nfun h(base, unused) =\n  class Adder with\n    fun add(n) = base + n\n  new Adder\nh(10, 0).add(3)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun h#0 @ h@2 -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 13\n\n\n\n:checkIR\n:expect 42\n:soir\nfun wrapper(val1, dead) =\n  class A with\n    fun makeB() =\n      class B with\n        fun getVal() = val1\n      new B\n  (new A).makeB().getVal()\nwrapper(42, 0)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun wrapper#0 @ wrapper@3 -> eliminable: {1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let wrapper⁰, wrapper_3$wrapper⁰;\n//│ define wrapper_3$wrapper⁰ as fun wrapper_3$wrapper¹(val1) {\n//│   let A, tmp, tmp1;\n//│   define A as class A⁰ {\n//│     method makeB⁰ = fun makeB¹() {\n//│       let B;\n//│       define B as class B⁰ {\n//│         method getVal⁰ = fun getVal¹() {\n//│           return val1\n//│         }\n//│       };\n//│       return new B⁰()\n//│     }\n//│   };\n//│   set tmp = new A⁰();\n//│   set tmp1 = tmp.makeB¹();\n//│   return tmp1.getVal﹖()\n//│ };\n//│ define wrapper⁰ as fun wrapper¹(val1, dead) {\n//│   let A, tmp, tmp1;\n//│   define A as class A¹ {\n//│     method makeB² = fun makeB³() {\n//│       let B;\n//│       define B as class B¹ {\n//│         method getVal² = fun getVal³() {\n//│           return val1\n//│         }\n//│       };\n//│       return new B¹()\n//│     }\n//│   };\n//│   set tmp = new A¹();\n//│   set tmp1 = tmp.makeB³();\n//│   return tmp1.getVal﹖()\n//│ };\n//│ wrapper_3$wrapper¹(42)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n\n:checkIR\n:expect 30\nfun multi(a, b, dead) =\n  class Calc with\n    fun sum() = a + b\n    fun prod() = a * b\n  (new Calc).prod()\nmulti(5, 6, 999)\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun multi#0 @ multi@4 -> eliminable: {2}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 30\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/todos.mls",
    "content": "\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/dead-param-elim/ups.mls",
    "content": ":js\n:deadParamElim debug\n\n\n:ucs ups\npattern Middle = ([x] => x) | ([x, ...(Middle as m), y] => m)\n//│ elaborated pattern body: [x] => x⁰ ∨ [x, ...Middle as m, y] => m⁰\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > prodfun lambda#0 @ <root> -> eliminable: {0, 1}\n//│ dead-param-elim > <<< dead-param-elim results <<<\n\n\nif [1,2,3,4,5] is\n  Middle as x then x\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ = 3\n\n:re\nif [1,2,3,4] is\n  Middle as x then x\n//│ dead-param-elim > >>> dead-param-elim results >>>\n//│ dead-param-elim > <<< dead-param-elim results <<<\n//│ ═══[RUNTIME ERROR] Error: match error\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/decls/Prelude.mls",
    "content": "\n\ndeclare type Any\ndeclare type Anything\ndeclare type Nothing\n\ndeclare type untyped\n\ndeclare type tailrec\ndeclare type tailcall\n\ndeclare class Object\ndeclare module Object with\n  fun\n    create\n    freeze\n    assign\n    entries\n    prototype\n    fromEntries\n    getPrototypeOf\n    defineProperty\n    getOwnPropertyDescriptor\n    getOwnPropertyDescriptors\ndeclare class JSON\ndeclare module JSON with\n  fun\n    stringify\ndeclare class Number\ndeclare module Number with\n  val\n    MIN_VALUE\n    MAX_VALUE\n    MIN_SAFE_INTEGER\n    MAX_SAFE_INTEGER\n    NEGATIVE_INFINITY\n    POSITIVE_INFINITY\ndeclare class BigInt\ndeclare module BigInt\ndeclare class Function\ndeclare module Function\ndeclare class String\ndeclare module String with\n  fun\n    fromCharCode\n    fromCodePoint\n    raw\ndeclare class RegExp\ndeclare module RegExp\ndeclare class Set[V]\ndeclare module Set\ndeclare class Map[K, V]\ndeclare module Map\ndeclare class WeakSet[V]\ndeclare module WeakSet\ndeclare class WeakMap[K, V]\ndeclare module WeakMap\ndeclare class Error//(info) // TODO: handle JS classes that can be instantiated without `new` specially in codegen.\ndeclare class TypeError//(info) // TODO: handle JS classes that can be instantiated without `new` specially in codegen.\ndeclare class RangeError//(info) // TODO: handle JS classes that can be instantiated without `new` specially in codegen.\ndeclare class Date\ndeclare module Date\n\ndeclare class ArrayBuffer\ndeclare module ArrayBuffer\ndeclare class TypedArray\ndeclare module TypedArray\ndeclare class Int8Array\ndeclare module Int8Array\ndeclare class Uint8Array\ndeclare module Uint8Array\ndeclare class Uint8ClampedArray\ndeclare module Uint8ClampedArray\ndeclare class Int16Array\ndeclare module Int16Array\ndeclare class Uint16Array\ndeclare module Uint16Array\ndeclare class Int32Array\ndeclare module Int32Array\ndeclare class Uint32Array\ndeclare module Uint32Array\ndeclare class Float16Array\ndeclare module Float16Array\ndeclare class Float32Array\ndeclare module Float32Array\ndeclare class Float64Array\ndeclare module Float64Array\ndeclare class BigInt64Array\ndeclare module BigInt64Array\ndeclare class BigUint64Array\ndeclare module BigUint64Array\n\n// MLscript-specific types\ndeclare class Bool\ndeclare class Int\ndeclare class Num\ndeclare class Str\ndeclare class Class\n\n// The `Array` class/function is a footgun:\n//    > Array()\n//    []\n//    > Array(1)\n//    [ <1 empty item> ]\n//    > Array(1, 2)\n//    [ 1, 2 ]\n// We used to declare it as a class taking exactly one argument here to avoid that footgun:\n//    declare class Array[T](val length: Int): Array[T]\n// but this made instance checks wrongly use `Array.class`;\n// TODO: handle Array and other JS classes that can be instantiated without `new` specially in codegen.\ndeclare class Array[T]\ndeclare module Array with\n  fun\n    from\n    concat\n    isArray\n    prototype\n\ndeclare object Symbol with\n  // The `TermDef` needs `rhs` to be defined to be recognized as `isMLsFun`.\n  // Otherwise, it would be wrapped in `runtime.safeCall`, which accesses the\n  // uninitialized `runtime` in the `Rendering` module.\n  fun for: Str -> Any = ()\n  val iterator: Any\n\n// MLwasm-specific types\ndeclare class Int31\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math\ndeclare module Math with\n  declare\n    val\n      E: Num\n      LN10: Num\n      LN2: Num\n      LOG10E: Num\n      LOG2E: Num\n      PI: Num\n      SQRT1_2: Num\n      SQRT2: Num\n    fun\n      abs: Num -> Num\n      acos: Num -> Num\n      acosh: Num -> Num\n      asin: Num -> Num\n      asinh: Num -> Num\n      atan: Num -> Num\n      atan2: (Num, Num) -> Num\n      atanh: Num -> Num\n      cbrt: Num -> Num\n      ceil: Num -> Num\n      clz32: Num -> Int\n      cos: Num -> Num\n      cosh: Num -> Num\n      exp: Num -> Num\n      expm1: Num -> Num\n      floor: Num -> Num\n      f16round: Num -> Num\n      fround: Num -> Num\n      hypot(...values): Num\n      imul: (Num, Num) -> Int\n      log: Num -> Num\n      log10: Num -> Num\n      log1p: Num -> Num\n      log2: Num -> Num\n      max(...values): Num\n      min(...values): Num\n      pow: (Num, Num) -> Num\n      random: () -> Num\n      round: Num -> Num\n      sign: Num -> (-1 | 0 | 1)\n      sin: Num -> Num\n      sinh: Num -> Num\n      sqrt: Num -> Num\n      tan: Num -> Num\n      tanh: Num -> Num\n      trunc: Num -> Num\n\ndeclare module Reflect with\n  fun\n    get\n    // set // TODO: handle keyword-named members\n    has\n    ownKeys\n    getPrototypeOf\n    apply\n    construct\ndeclare module console with\n  declare\n    fun\n      log\n      debug\n      info\n      warn\n      error\n      // assert\n      clear\n      count\n      countReset\n      dir\n      dirxml\n      group\n      groupCollapsed\n      groupEnd\n      table\n      time\n      timeEnd\n      trace\n\ndeclare val process // TODO make `module`\ndeclare val fs // TODO make `module`\n\ndeclare val Infinity\n\n// Wasm support\ndeclare class Promise\ndeclare val Promise\ndeclare object WebAssembly with\n  declare object Instance\n  declare class Memory\n  declare object Module with\n    fun\n      exports\n      imports\n\n  fun\n    instantiate\n    validate\n\n// declare fun typeof: (Any) -> Str\n\ndeclare fun parseInt(str: Str, radix: Int): Int\ndeclare fun parseFloat(str: Str): Num\n\n\ndeclare module source with\n  object\n    line\n    name\n    file\n\ndeclare module js with\n  fun\n    bitand\n    bitnot\n    bitor\n    shl\n    try_catch\n\ndeclare module wasm with\n  fun\n    plus_impl\n    minus_impl\n    times_impl\n    div_impl\n    mod_impl\n    eq_impl\n    neq_impl\n    lt_impl\n    le_impl\n    gt_impl\n    ge_impl\n    neg_impl\n    pos_impl\n    not_impl\n\ndeclare module debug with\n  fun printStack\n\ndeclare module annotations with\n  object compile\n  object buffered\n  object bufferable\n\ndeclare module scope with\n  fun locally\n\ndeclare module runtime with\n  fun\n    suspend\n    handle_suspension\n\n\n// HTML DOM API definitions.\n// Move them to a separate Prelude file when there are enough of them.\ndeclare val document\ndeclare val customElements\ndeclare class HTMLElement\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/append.mls",
    "content": ":js\n:deforest\n\n\n\nobject Nil\ndata class (::) Cons(h, t)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n\n:expect Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\nfun append1(xs1, ys) = if xs1 is\n  h :: t then h :: append1(t, ys)\n  Nil then ys\nfun append2(xs2, ys) = if xs2 is\n  h :: t then h :: append2(t, ys)\n  Nil then ys\nfun appendThree(xs, ys, zs) =\n  append1(append2(xs, ys), zs)\nappendThree of\n  id(1 :: 2 :: Nil)\n  id(3 :: 4 :: Nil)\n  id(5 :: 6 :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\n\n// maybe the fusion target for the previous program\n:expect Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\nfun appendReified(ys, zs) = if ys is\n  h :: t then h :: appendReified(t, zs)\n  Nil then zs\nfun append1(ys, zs) = ys(zs)\nfun append2(xs, ys) = \n  if xs is\n    h :: t then\n      zs => h :: append1(append2(t, ys), zs)        // normal fusion\n    Nil then zs => appendReified(ys, zs)            // reified\nfun test(xs, ys, zs) = append1(append2(xs, ys), zs)\ntest of\n  id(1 :: 2 :: Nil)\n  id(3 :: 4 :: Nil)\n  id(5 :: 6 :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\n\n\n:expect Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\nfun idList(l) = if l is\n  h :: t then h :: idList(t)\n  Nil then Nil\nfun append(xs, ys) = if xs is\n  h :: t then h :: append(t, ys)\n  Nil then idList(ys)\nfun appendThree(xs, ys, zs) =\n  append(append(xs, ys), zs)\nappendThree of\n  id(1 :: 2 :: Nil)\n  id(3 :: 4 :: Nil)\n  id(5 :: 6 :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(h,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(h,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(h,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(h,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\n\n\n\n:expect Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\nfun append(xs, ys) = if xs is\n  h :: t then h :: append(t, ys)\n  Nil then idList(ys)\nfun concat(lss) = if lss is\n  hh :: tt then append(hh, concat(tt))\n  Nil then Nil\nconcat of id of\n  (1 :: 2 :: Nil) ::\n  (3 :: 4 :: Nil) ::\n  (5 :: 6 :: Nil) :: Nil\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/basic.mls",
    "content": ":js\n:deforest\n\ndata class X(a)\ndata class Y(b)\ndata class Z(c)\ndata object O\ndata class A(x)\ndata class B(x)\ndata object C\ndata object D\ndata object Nil\ndata class (::) Cons(h, t)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n:sir\nlet lsit = [2, 1]\nlet useless = if lsit is [a, b] then 0\n//│ deforest > >>> fusing >>>\n//│ deforest > Tuple(false,List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(1))))) ->\n//│ deforest > \tRef(lsit,None)\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(lsit,None)), Arg(None,Lit(IntLit(0))))))\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(lsit,None)), Arg(None,Lit(IntLit(1))))))\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let lsit⁰, useless⁰, a⁰, b⁰, element1$, element0$, tmp, $lsit_tup2⁰, $lsit_rest⁰, tup2_0, tup2_1;\n//│ define $lsit_tup2⁰ as fun $lsit_tup2¹(tup2_01, tup2_11) {\n//│   set element0$ = tup2_01;\n//│   set element1$ = tup2_11;\n//│   set b⁰ = element1$;\n//│   set a⁰ = element0$;\n//│   set tmp = 0;\n//│   return $lsit_rest¹()\n//│ };\n//│ define $lsit_rest⁰ as fun $lsit_rest¹() {\n//│   set useless⁰ = tmp;\n//│   return null\n//│ };\n//│ set tup2_0 = 2;\n//│ set tup2_1 = 1;\n//│ set lsit⁰ = () => { return $lsit_tup2¹(tup2_0, tup2_1) };\n//│ lsit⁰()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = null\n//│ lsit = fun lsit\n//│ useless = 0\n\n:expect O\nfun p() = X(O)\nfun c(x) = if x is\n  X(x) then x\nc(p())\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Ref(member:O,Some(object:O)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > <<< fusing <<<\n//│ = O\n\n\n:sir\n:expect O\nfun p() = X(Y(O))\nfun f(x) = if x is\n  X(Y(y)) then y\nf(p())\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > Call(Ref(member:Y,Some(term:Y/Y)),List(List(Arg(None,Ref(member:O,Some(object:O)))))) ->\n//│ deforest > \tRef(tmp:arg$X$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$X$0$,None),Ident(b))\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let p⁰, f⁰, tmp, p_10$p⁰, f_12$f⁰, f_12$x_X⁰, f_12$x_rest⁰, f_12$split_default$_rest⁰, f_12$split_root$_rest⁰, f_12$arg$X$0$_Y⁰, f_12$arg$X$0$_rest⁰;\n//│ define p_10$p⁰ as fun p_10$p¹() {\n//│   let tmp1, Y_b, X_a;\n//│   set Y_b = O⁰;\n//│   set tmp1 = (fv_ctorLam_y, fv_ctorLam_arg$Y$0$) => {\n//│     return f_12$arg$X$0$_Y¹(fv_ctorLam_y, fv_ctorLam_arg$Y$0$, Y_b)\n//│   };\n//│   set X_a = tmp1;\n//│   return (fv_ctorLam_y, fv_ctorLam_arg$X$0$, fv_ctorLam_arg$Y$0$) => {\n//│     return f_12$x_X¹(fv_ctorLam_y, fv_ctorLam_arg$X$0$, fv_ctorLam_arg$Y$0$, X_a)\n//│   }\n//│ };\n//│ define f_12$f⁰ as fun f_12$f¹(x) {\n//│   let y, arg$X$0$, arg$Y$0$;\n//│   block split_root$:\n//│     block split_default$:\n//│       return x(y, arg$X$0$, arg$Y$0$)\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ define f_12$x_X⁰ as fun f_12$x_X¹(fv_y, fv_arg$X$0$, fv_arg$Y$0$, X_a) {\n//│   set fv_arg$X$0$ = X_a;\n//│   return fv_arg$X$0$(fv_y, fv_arg$Y$0$)\n//│ };\n//│ define f_12$arg$X$0$_Y⁰ as fun f_12$arg$X$0$_Y¹(fv_y, fv_arg$Y$0$, Y_b) {\n//│   set fv_arg$Y$0$ = Y_b;\n//│   set fv_y = fv_arg$Y$0$;\n//│   return fv_y\n//│ };\n//│ define f_12$x_rest⁰ as fun f_12$x_rest¹() {\n//│   return f_12$split_default$_rest¹()\n//│ };\n//│ define f_12$split_default$_rest⁰ as fun f_12$split_default$_rest¹() {\n//│   throw new globalThis⁰.Error⁰(\"match error\")\n//│ };\n//│ define f_12$split_root$_rest⁰ as fun f_12$split_root$_rest¹() {\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ define f_12$arg$X$0$_rest⁰ as fun f_12$arg$X$0$_rest¹() {\n//│   return f_12$x_rest¹()\n//│ };\n//│ define p⁰ as fun p¹() {\n//│   let tmp1;\n//│   set tmp1 = Y⁰(O⁰);\n//│   return X⁰(tmp1)\n//│ };\n//│ define f⁰ as fun f¹(x) {\n//│   let y, arg$X$0$, arg$Y$0$;\n//│   block split_root$:\n//│     block split_default$:\n//│       match x\n//│         X¹ =>\n//│           set arg$X$0$ = x.a¹;\n//│           match arg$X$0$\n//│             Y¹ =>\n//│               set arg$Y$0$ = arg$X$0$.b¹;\n//│               set y = arg$Y$0$;\n//│               return y\n//│             else\n//│               break split_default$\n//│           end\n//│         else\n//│           break split_default$\n//│       end\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ set tmp = p_10$p¹();\n//│ f_12$f¹(tmp)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = O\n\n\n:expect 14\nfun p() = X(Y(O))\nfun f(x, res) = if x is\n  X(a) then\n    let tmp = 12\n    if a is\n      Y(y) then res + tmp\nf(p(), 2)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > Call(Ref(member:Y,Some(term:Y/Y)),List(List(Arg(None,Ref(member:O,Some(object:O)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(b))\n//│ deforest > <<< fusing <<<\n//│ = 14\n\n\n\n:expect 16\nfun f(x, y, res) = if x is\n  X(a) then\n    let tmp = 12\n    if y is\n      Y(b) then\n        let _d = () => y\n        res + tmp + a\nf(X(1), Y(2), 3)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Y,Some(term:Y/Y)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(b))\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > <<< fusing <<<\n//│ = 16\n\n\n\nfun c(x, d) = if x is\n  X(a) then c(X(a), d)\n() => c(X(3), 2)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Ref(a,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Ref(a,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > Call(Ref(member:X,Some(term:X/X)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > <<< fusing <<<\n//│ = fun lambda_8$lambda\n\n\n:expect 2\nfun a() = O\nfun b() = a()\nfun c() = b()\nfun p(x) = if x is\n  O then 2\np(c())\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:O,Some(object:O)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n:sir\n:expect 3\nif [1, 2] is\n  [a, b] then a + b\n//│ deforest > >>> fusing >>>\n//│ deforest > Tuple(false,List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(2))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(tmp:scrut,None)), Arg(None,Lit(IntLit(0))))))\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(tmp:scrut,None)), Arg(None,Lit(IntLit(1))))))\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let scrut, a², b², element1$, element0$, $scrut_tup2⁰, $scrut_rest⁰, tup2_0, tup2_1;\n//│ define $scrut_tup2⁰ as fun $scrut_tup2¹(tup2_01, tup2_11) {\n//│   set element0$ = tup2_01;\n//│   set element1$ = tup2_11;\n//│   set b² = element1$;\n//│   set a² = element0$;\n//│   return +⁰(a², b²)\n//│ };\n//│ define $scrut_rest⁰ as fun $scrut_rest¹() {\n//│   return null\n//│ };\n//│ set tup2_0 = 1;\n//│ set tup2_1 = 2;\n//│ set scrut = () => { return $scrut_tup2¹(tup2_0, tup2_1) };\n//│ scrut()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n\n:expect 3\nfun f(x) = if x is\n  [a,b] then a + b\nf([1,2])\n//│ deforest > >>> fusing >>>\n//│ deforest > Tuple(false,List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(2))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(x,None)), Arg(None,Lit(IntLit(0))))))\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(x,None)), Arg(None,Lit(IntLit(1))))))\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n:expect 2\nfun f(x) = if x is\n  O then 2\nf(id(O))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n:expect 0\nlet x = O\nfun f() =\n  if x is\n    O then 0\nf()\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 0\n//│ x = O\n\n\n:expect 1\nfun f(x) = if x is\n  A(x) then x\nf(A(1))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 1\n\n\n:expect 2\nfun f(x) = if x is\n  A(a) then x.A#x + a\nf(A(1))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n:expect 4\nfun f(x) = if x is\n  A(x) then 2\nf(A(2)) + f(A(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 4\n\n\n:expect B(4)\nfun localFuse(x) = if A(x) is\n  A(y) then B(y)\nif localFuse(3) is\n  B(a) then a\nlocalFuse(4)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:B,Some(term:B/B)),List(List(Arg(None,Ref(y,None))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = B(4)\n\n\n\n\n:expect 3\nfun g(x) = if x is\n  A(a) then a\nfun f(x) = x.A#x\nlet o = A(1)\ng(o) + f(o) + o.A#x\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 3\n//│ o = A(1)\n\n\n:expect 1\nlet x = if A(0) is\n  A then 1\nlet f() = x\nf()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > <<< fusing <<<\n//│ = 1\n//│ f = fun f\n//│ x = 1\n\n\n:expect B(0)\nfun inner(y, z) = if y is\n  B then z\nfun dtor(x) = if x is\n  A then inner(B(4), x.A#x)\ndtor(A(B(0)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:B,Some(term:B/B)),List(List(Arg(None,Lit(IntLit(4)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Call(Ref(member:B,Some(term:B/B)),List(List(Arg(None,Lit(IntLit(4)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = B(0)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/clashes.mls",
    "content": ":js\n:deforest\n\n\ndata class A(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\ndata class (::) Cons(h, t)\nobject Nil\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n\n:expect 10\nfun to(n) = if n > 0 then n :: to(n - 1) else Nil\nfun f1(ls) = if ls is\n  h :: t then h\n  Nil then 2\nfun f2(ls) = if ls is\n  h :: t then h + 1\n  Nil then 3\nfun badWrap(n) =\n  let x = to(n)\n  f1(x) + f2(x)\n  x\nf1(badWrap(4)) + f2(badWrap(5))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 10\n\n\n\n\n:expect 9\nfun p(x) = A(x)\nlet one = p(1)\nlet two = p(2)\nfun f1(p) = if p is A(a) then a + 1\nfun f2(p) = if p is A(b) then b + 2\nf1(one) + f2(one) + f2(two)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 9\n//│ one = A(1)\n//│ two = fun inlinedVal1\n\n\n\n:expect 5\nfun p(a) = a\nfun f1(a1) = if a1 is A(x1) then x1\nfun f2(a2) = if a2 is A(x2) then x2 + 1\nlet x = A(1)\nlet y = A(2)\nlet res1 = p(if true then x else y) // both x and y flow into this call-site result\nlet res2 = p(x) // x flows into this call-site result\nlet res3 = p(y) // y flows into this call-site result\n// f1(res1) + f2(res1) + f1(res2) + f2(res3)\nf1(res1) + f1(res2) + f2(res3)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 5\n//│ res1 = A(1)\n//│ res2 = A(1)\n//│ res3 = A(2)\n//│ x = A(1)\n//│ y = A(2)\n\n\n\n:expect 4\nfun f1(a1) = if a1 is A(x1) then x1\nfun f2(a2) = if a2 is A(x2) then x2 + 1\nfun p(x, clashedCtor) =\n  if true then A(x)\n  else clashedCtor\nlet clashed = A(3)\nf1(p(1, clashed)) + f2(p(2, clashed))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 4\n//│ clashed = A(3)\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/cyclic.mls",
    "content": ":js\n\ndata class A(x)\ndata class B(x)\ndata object C\ndata object D\ndata class (::) Cons(h, t)\nobject Nil\nobject None\ndata class Some(x)\n\n\n\n:expect 0\nfun f(x) = if x is\n  A(_) then f(A(2))\n  else 0\nf(Nil)\n//│ = 0\n\n\n:expect 0\nfun f(x) =\n  let res = if x is\n    A(x) then x\n  if res > 0 then f(A(res - 1)) else 0\nf(A(4))\n//│ = 0\n\n\n:expect 0\nfun f(x, b) = if x is\n  Nil then if b then f(Nil, false) else 0\nf(Nil, false)\n//│ = 0\n\n\n\n:deforest\nfun f(a) = if a is\n  C then C\n  else D\n(x => 0)(f(f(C)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:C,Some(object:C)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:D,Some(object:D)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:C,Some(object:C)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n:deforest\n:expect Some(2)\nfun maxOpt(ls) = if ls is\n  Nil then None\n  h :: t then\n    if maxOpt(t) is\n      None then Some(h)\n      Some(m) then if m > h then Some(m) else Some(h)\nmaxOpt(id(1 :: 2 :: Nil))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Some(2)\n\n\n:deforest\n:sir\n:expect Some(2)\nfun modSome(x, m) = if x is\n  Some(n) and\n    n >= m then modSome(Some(n - m), m)\n    else Some(n)\n  None then None\nmodSome(Some(17), 3)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Some,Some(term:Some/Some)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:Some,Some(term:Some/Some)),List(List(Arg(None,Lit(IntLit(17)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let modSome⁰, tmp, modSome_12$modSome⁰, modSome_12$x_Some⁰, modSome_12$x_rest⁰, Some_x;\n//│ define modSome_12$modSome⁰ as fun modSome_12$modSome¹(x, m) {\n//│   let n, scrut, arg$Some$0$, tmp1, tmp2;\n//│   return x(m, n, scrut, arg$Some$0$, tmp1, tmp2)\n//│ };\n//│ define modSome_12$x_Some⁰ as fun modSome_12$x_Some¹(fv_m, fv_n, fv_scrut, fv_arg$Some$0$, fv_tmp, fv_tmp1, Some_x1) {\n//│   set fv_arg$Some$0$ = Some_x1;\n//│   set fv_n = fv_arg$Some$0$;\n//│   set fv_scrut = >=⁰(fv_n, fv_m);\n//│   match fv_scrut\n//│     true =>\n//│       let Some_x2;\n//│       set fv_tmp = -⁰(fv_n, fv_m);\n//│       set Some_x2 = fv_tmp;\n//│       set fv_tmp1 = (fv_ctorLam_m, fv_ctorLam_n, fv_ctorLam_scrut, fv_ctorLam_arg$Some$0$, fv_ctorLam_tmp, fv_ctorLam_tmp1) => {\n//│         return modSome_12$x_Some¹(fv_ctorLam_m, fv_ctorLam_n, fv_ctorLam_scrut, fv_ctorLam_arg$Some$0$, fv_ctorLam_tmp, fv_ctorLam_tmp1, Some_x2)\n//│       };\n//│       return modSome_12$modSome¹(fv_tmp1, fv_m)\n//│     else\n//│       return Some⁰(fv_n)\n//│   end\n//│ };\n//│ define modSome_12$x_rest⁰ as fun modSome_12$x_rest¹() {\n//│   return null\n//│ };\n//│ define modSome⁰ as fun modSome¹(x, m) {\n//│   loop loopLabel:\n//│     let n, scrut, arg$Some$0$, tmp1, tmp2;\n//│     match x\n//│       Some¹ =>\n//│         set arg$Some$0$ = x.x⁰;\n//│         set n = arg$Some$0$;\n//│         set scrut = >=⁰(n, m);\n//│         match scrut\n//│           true =>\n//│             set tmp1 = -⁰(n, m);\n//│             set tmp2 = Some⁰(tmp1);\n//│             set x = tmp2;\n//│             continue loopLabel\n//│           else\n//│             return Some⁰(n)\n//│         end\n//│       None⁰ =>\n//│         return None⁰\n//│       else\n//│         throw new globalThis⁰.Error⁰(\"match error\")\n//│     end\n//│   end\n//│ };\n//│ set Some_x = 17;\n//│ set tmp = (fv_ctorLam_m, fv_ctorLam_n, fv_ctorLam_scrut, fv_ctorLam_arg$Some$0$, fv_ctorLam_tmp, fv_ctorLam_tmp1) => {\n//│   return modSome_12$x_Some¹(fv_ctorLam_m, fv_ctorLam_n, fv_ctorLam_scrut, fv_ctorLam_arg$Some$0$, fv_ctorLam_tmp, fv_ctorLam_tmp1, Some_x)\n//│ };\n//│ modSome_12$modSome¹(tmp, 3)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Some(2)\n\n\n:deforest\n:expect Some(3)\nfun maxOpt2(ls, x) = if ls is\n  Nil then x\n  h :: t and x is\n    None then maxOpt2(t, Some(h))\n    Some(m) and\n      h > m then maxOpt2(t, Some(h))\n      else maxOpt2(t, Some(m))\nmaxOpt2(id(1 :: 2 :: 3 :: Nil), None)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Some(3)\n\n:deforest\n:expect Nil\nfun zipWith(xsys, f) = if xsys is\n  [hx :: tx, hy :: ty] then f(hx, hy) :: zipWith([tx, ty], f)\n  [Nil, Nil] then Nil\nzipWith([id(Nil), id(Nil)], (x, y) => x)\n//│ deforest > >>> fusing >>>\n//│ deforest > Tuple(false,List(Arg(None,Ref(tx,None)), Arg(None,Ref(ty,None)))) ->\n//│ deforest > \tRef(xsys,None)\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(xsys,None)), Arg(None,Lit(IntLit(0))))))\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(xsys,None)), Arg(None,Lit(IntLit(1))))))\n//│ deforest > Tuple(false,List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None)))) ->\n//│ deforest > \tRef(xsys,None)\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(xsys,None)), Arg(None,Lit(IntLit(0))))))\n//│ deforest > \tCall(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(xsys,None)), Arg(None,Lit(IntLit(1))))))\n//│ deforest > <<< fusing <<<\n//│ = Nil\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/determinism.mls",
    "content": ":js\n\ndata class A(a)\ndata class B(a, b, c, d, e)\n\n:deforest\n:sir\n:expect 0\nif B(1,2,3,4,5) is\n  B(a,b,c,d,e) then 0\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:B,Some(term:B/B)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(4))), Arg(None,Lit(IntLit(5)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(a))\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(b))\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(c))\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(d))\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(e))\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let scrut, e⁰, a⁰, b⁰, c⁰, d⁰, arg$B$0$, arg$B$1$, arg$B$2$, arg$B$3$, arg$B$4$, $scrut_B⁰, $scrut_rest⁰, B_a, B_b, B_c, B_d, B_e;\n//│ define $scrut_B⁰ as fun $scrut_B¹(B_a1, B_b1, B_c1, B_d1, B_e1) {\n//│   set arg$B$0$ = B_a1;\n//│   set arg$B$1$ = B_b1;\n//│   set arg$B$2$ = B_c1;\n//│   set arg$B$3$ = B_d1;\n//│   set arg$B$4$ = B_e1;\n//│   set e⁰ = arg$B$4$;\n//│   set d⁰ = arg$B$3$;\n//│   set c⁰ = arg$B$2$;\n//│   set b⁰ = arg$B$1$;\n//│   set a⁰ = arg$B$0$;\n//│   return 0\n//│ };\n//│ define $scrut_rest⁰ as fun $scrut_rest¹() {\n//│   return null\n//│ };\n//│ set B_a = 1;\n//│ set B_b = 2;\n//│ set B_c = 3;\n//│ set B_d = 4;\n//│ set B_e = 5;\n//│ set scrut = () => { return $scrut_B¹(B_a, B_b, B_c, B_d, B_e) };\n//│ scrut()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n:sir\n:deforest\n:expect 1\nfun c2(x) = if x is\n  A(A(A(A(A(A(a)))))) then a\nc2 of A(A(A(A(A(A(1))))))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp:arg$A$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$A$0$,None),Ident(a))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp:arg$A$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$A$0$,None),Ident(a))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp:arg$A$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$A$0$,None),Ident(a))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp:arg$A$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$A$0$,None),Ident(a))\n//│ deforest > Call(Ref(member:A,Some(term:A/A)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:arg$A$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$A$0$,None),Ident(a))\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let c2⁰, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, c2_21$c2⁰, c2_21$x_A⁰, c2_21$x_rest⁰, c2_21$split_default$_rest⁰, c2_21$split_root$_rest⁰, c2_21$arg$A$0$_A⁰, c2_21$arg$A$0$_rest⁰, c2_21$arg$A$0$_A¹, c2_21$arg$A$0$_rest¹, c2_21$arg$A$0$_A², c2_21$arg$A$0$_rest², c2_21$arg$A$0$_A³, c2_21$arg$A$0$_rest³, c2_21$arg$A$0$_A⁴, c2_21$arg$A$0$_rest⁴, A_a, A_a1, A_a2, A_a3, A_a4, A_a5;\n//│ define c2_21$c2⁰ as fun c2_21$c2¹(x) {\n//│   let a, arg$A$0$, arg$A$0$1, arg$A$0$2, arg$A$0$3, arg$A$0$4, arg$A$0$5;\n//│   block split_root$:\n//│     block split_default$:\n//│       return x(a, arg$A$0$, arg$A$0$1, arg$A$0$2, arg$A$0$3, arg$A$0$4, arg$A$0$5)\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ define c2_21$x_A⁰ as fun c2_21$x_A¹(fv_a, fv_arg$A$0$, fv_arg$A$0$1, fv_arg$A$0$2, fv_arg$A$0$3, fv_arg$A$0$4, fv_arg$A$0$5, A_a6) {\n//│   set fv_arg$A$0$ = A_a6;\n//│   return fv_arg$A$0$(fv_a, fv_arg$A$0$1, fv_arg$A$0$2, fv_arg$A$0$3, fv_arg$A$0$4, fv_arg$A$0$5)\n//│ };\n//│ define c2_21$arg$A$0$_A⁰ as fun c2_21$arg$A$0$_A⁵(fv_a, fv_arg$A$0$, fv_arg$A$0$1, fv_arg$A$0$2, fv_arg$A$0$3, fv_arg$A$0$4, A_a6) {\n//│   set fv_arg$A$0$ = A_a6;\n//│   return fv_arg$A$0$(fv_a, fv_arg$A$0$1, fv_arg$A$0$2, fv_arg$A$0$3, fv_arg$A$0$4)\n//│ };\n//│ define c2_21$arg$A$0$_A¹ as fun c2_21$arg$A$0$_A⁶(fv_a, fv_arg$A$0$, fv_arg$A$0$1, fv_arg$A$0$2, fv_arg$A$0$3, A_a6) {\n//│   set fv_arg$A$0$ = A_a6;\n//│   return fv_arg$A$0$(fv_a, fv_arg$A$0$1, fv_arg$A$0$2, fv_arg$A$0$3)\n//│ };\n//│ define c2_21$arg$A$0$_A² as fun c2_21$arg$A$0$_A⁷(fv_a, fv_arg$A$0$, fv_arg$A$0$1, fv_arg$A$0$2, A_a6) {\n//│   set fv_arg$A$0$ = A_a6;\n//│   return fv_arg$A$0$(fv_a, fv_arg$A$0$1, fv_arg$A$0$2)\n//│ };\n//│ define c2_21$arg$A$0$_A³ as fun c2_21$arg$A$0$_A⁸(fv_a, fv_arg$A$0$, fv_arg$A$0$1, A_a6) {\n//│   set fv_arg$A$0$ = A_a6;\n//│   return fv_arg$A$0$(fv_a, fv_arg$A$0$1)\n//│ };\n//│ define c2_21$arg$A$0$_A⁴ as fun c2_21$arg$A$0$_A⁹(fv_a, fv_arg$A$0$, A_a6) {\n//│   set fv_arg$A$0$ = A_a6;\n//│   set fv_a = fv_arg$A$0$;\n//│   return fv_a\n//│ };\n//│ define c2_21$x_rest⁰ as fun c2_21$x_rest¹() {\n//│   return c2_21$split_default$_rest¹()\n//│ };\n//│ define c2_21$split_default$_rest⁰ as fun c2_21$split_default$_rest¹() {\n//│   throw new globalThis⁰.Error⁰(\"match error\")\n//│ };\n//│ define c2_21$split_root$_rest⁰ as fun c2_21$split_root$_rest¹() {\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ define c2_21$arg$A$0$_rest⁰ as fun c2_21$arg$A$0$_rest⁵() {\n//│   return c2_21$x_rest¹()\n//│ };\n//│ define c2_21$arg$A$0$_rest¹ as fun c2_21$arg$A$0$_rest⁶() {\n//│   return c2_21$arg$A$0$_rest⁵()\n//│ };\n//│ define c2_21$arg$A$0$_rest² as fun c2_21$arg$A$0$_rest⁷() {\n//│   return c2_21$arg$A$0$_rest⁶()\n//│ };\n//│ define c2_21$arg$A$0$_rest³ as fun c2_21$arg$A$0$_rest⁸() {\n//│   return c2_21$arg$A$0$_rest⁷()\n//│ };\n//│ define c2_21$arg$A$0$_rest⁴ as fun c2_21$arg$A$0$_rest⁹() {\n//│   return c2_21$arg$A$0$_rest⁸()\n//│ };\n//│ define c2⁰ as fun c2¹(x) {\n//│   let a, arg$A$0$, arg$A$0$1, arg$A$0$2, arg$A$0$3, arg$A$0$4, arg$A$0$5;\n//│   block split_root$:\n//│     block split_default$:\n//│       match x\n//│         A⁰ =>\n//│           set arg$A$0$ = x.a¹;\n//│           match arg$A$0$\n//│             A⁰ =>\n//│               set arg$A$0$1 = arg$A$0$.a¹;\n//│               match arg$A$0$1\n//│                 A⁰ =>\n//│                   set arg$A$0$2 = arg$A$0$1.a¹;\n//│                   match arg$A$0$2\n//│                     A⁰ =>\n//│                       set arg$A$0$3 = arg$A$0$2.a¹;\n//│                       match arg$A$0$3\n//│                         A⁰ =>\n//│                           set arg$A$0$4 = arg$A$0$3.a¹;\n//│                           match arg$A$0$4\n//│                             A⁰ =>\n//│                               set arg$A$0$5 = arg$A$0$4.a¹;\n//│                               set a = arg$A$0$5;\n//│                               return a\n//│                             else\n//│                               break split_default$\n//│                           end\n//│                         else\n//│                           break split_default$\n//│                       end\n//│                     else\n//│                       break split_default$\n//│                   end\n//│                 else\n//│                   break split_default$\n//│               end\n//│             else\n//│               break split_default$\n//│           end\n//│         else\n//│           break split_default$\n//│       end\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ set A_a = 1;\n//│ set tmp = (fv_ctorLam_a, fv_ctorLam_arg$A$0$) => {\n//│   return c2_21$arg$A$0$_A⁹(fv_ctorLam_a, fv_ctorLam_arg$A$0$, A_a)\n//│ };\n//│ set A_a1 = tmp;\n//│ set tmp1 = (fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1) => {\n//│   return c2_21$arg$A$0$_A⁸(fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, A_a1)\n//│ };\n//│ set A_a2 = tmp1;\n//│ set tmp2 = (fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2) => {\n//│   return c2_21$arg$A$0$_A⁷(fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2, A_a2)\n//│ };\n//│ set A_a3 = tmp2;\n//│ set tmp3 = (fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2, fv_ctorLam_arg$A$0$3) => {\n//│   return c2_21$arg$A$0$_A⁶(fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2, fv_ctorLam_arg$A$0$3, A_a3)\n//│ };\n//│ set A_a4 = tmp3;\n//│ set tmp4 = (fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2, fv_ctorLam_arg$A$0$3, fv_ctorLam_arg$A$0$4) => {\n//│   return c2_21$arg$A$0$_A⁵(fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2, fv_ctorLam_arg$A$0$3, fv_ctorLam_arg$A$0$4, A_a4)\n//│ };\n//│ set A_a5 = tmp4;\n//│ set tmp5 = (fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2, fv_ctorLam_arg$A$0$3, fv_ctorLam_arg$A$0$4, fv_ctorLam_arg$A$0$5) => {\n//│   return c2_21$x_A¹(fv_ctorLam_a, fv_ctorLam_arg$A$0$, fv_ctorLam_arg$A$0$1, fv_ctorLam_arg$A$0$2, fv_ctorLam_arg$A$0$3, fv_ctorLam_arg$A$0$4, fv_ctorLam_arg$A$0$5, A_a5)\n//│ };\n//│ c2_21$c2¹(tmp5)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/dropLast.mls",
    "content": ":js\n\ndata class (::) Cons(h, t)\ndata object Nil\n\n\nfun lseq(l1, l2) = if\n  l1 is Nil and l2 is Nil then true\n  l1 is x :: xs and l2 is y :: ys and x == y then lseq(xs, ys)\n  else false\n\n\n\n:deforest\nfun dl(ls) = if ls is\n  Nil then Nil\n  x :: Nil then Nil\n  x :: xs then x :: dl(xs)\nfun fix(x) =\n  let res = dl(x)\n  if lseq(res, x) then res\n  else\n    fix(res)\nfix\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = fun fix\n\n\n\n\n:deforest\nfun dl(ls) = if ls is\n  Nil then Nil\n  x :: Nil then Nil\n  x :: xs then x :: dl(xs)\nfun fix(x, fuel) =\n  let res = dl(x)\n  if fuel == 0 then res\n  else\n    fix(res, fuel - 1)\nfix\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = fun fix\n\n\n\n:deforest\nfun dl(ls) = if ls is\n  Nil then Nil\n  x :: xs then dlHelper(x, xs)\nfun dlHelper(prev, rest) = if rest is\n  Nil then Nil\n  h :: t then prev :: dlHelper(h, t)\nfun fix(x, fuel) =\n  let res = dl(x)\n  if fuel == 0 then res\n  else\n    fix(res, fuel - 1)\nfix\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = fun fix\n\n\n\n\n:deforest\n:expect Nil\nfun dlHelper(prev, rest) = if rest is\n  Nil then Nil\n  h :: t then prev :: dlHelper(h, t)\nfun fix(x, fuel) =\n  let res = dlHelper(-1, x)\n  if fuel == 0 then res\n  else\n    fix(res, fuel - 1)\nid(fix(Nil, 1000))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Nil\n\n\n\n\n\n:deforest\n:expect Nil\nfun dlHelper(prev, rest) = if rest is\n  Nil then Nil\n  h :: t then prev :: dlHelper(h, t)\nfun fix(x) =\n  if x is\n    Nil then Nil\n    x :: xs then fix(dlHelper(x, xs))\nfix(2 :: 3 :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Nil\n\n\n\n\n\n\n\n:deforest\n:expect Nil\nfun f(x) = if x is\n  Nil then Nil\nfun loop(l, n) = if n > 0 then loop(f(l), n - 1) else l\nid(loop(Nil, 2))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Nil\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/floatoutSafety.mls",
    "content": ":js\n\n\ndata class (::) Cons(h, t)\ndata object Nil\n\n\n\ndata class Many(x)\ndata class Once(x)\n\nfun expensive(x) = x\n\n\n\n// we don't want to fuse `p = enumFrom(3)`,\n// because the `expensive` computation would be duplicated\n// btw, should `p` be considered as being in the correct position here?\n:deforest\nfun sum(x) = if x is\n  h :: t then h + sum(t)\n  Nil then 0\nfun enumFrom(a) =\n  if a > 0 then expensive(a) :: enumFrom(a - 1)\n  else Nil\nfun main() =\n  let p = enumFrom(3)\n  let f = () => sum(p)\n  f() + f()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(h))\n//│ deforest > \tSelect(Ref(x,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n\n\n\n// `Many` cannot be fused because:\n// - it's not one-shot\n// - it has a clash\n:deforest\n:expect 13\nfun consumer(f, g, p) = f(p) + g(p)\nconsumer of\n  case Many(_) then 3\n  case Many(Once(v)) then v\n  Many(Once(10))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Once,Some(term:Once/Once)),List(List(Arg(None,Lit(IntLit(10)))))) ->\n//│ deforest > \tRef(tmp:arg$Many$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$Many$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 13\n\n\n\n// we don't actually want to fuse it, because the logic of\n// the creation of the list may be expensive\n:deforest\n:expect 12\nfun enumFrom(a) =\n  if a > 0 then expensive(a) :: enumFrom(a - 1)\n  else Nil\nfun sum(x) = if x is\n  h :: t then h + sum(t)\n  Nil then 0\nfun consume(f, ls) = f(ls) + f(ls)\nconsume(sum, enumFrom(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(h))\n//│ deforest > \tSelect(Ref(x,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 12\n\n\n\ndata class Outter(x)\ndata class Inner(x)\n\n// nested ctors may or may not be fusible. it depends on what the consumer\n// does with the corresponding field. The outer and inner ctors can differ in:\n// - strategy clash (outer has none, but inner does)\n// - linearity (outer is one-shot, but inner is not)\n// - tail-modulo-fusion position\n// these causes can also interact (between different levels of ctors).\n:deforest\n:expect 22\nfun prod(x) = Outter(Inner(x))\nfun cons(f, p) = if p is\n  Outter(i) then f(i) + f(i)\ncons of\n  case Inner(a) then a + 1\n  prod(10)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Outter,Some(term:Outter/Outter)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(x))\n//│ deforest > Call(Ref(member:Inner,Some(term:Inner/Inner)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(caseScrut,None)\n//│ deforest > \tSelect(Ref(caseScrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 22\n\n\n\n\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/imperative.mls",
    "content": ":js\n:deforest\n\n\nobject A\nobject B\n// object C\n// class AA(aa)\n// class BB(bb)\n// object None\n// class Some(value)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n// * Not fused: two `x is A` consumers\nlet x = if true then A else B\nfun foo(x) =\n  if x is A do print(123)\n  if x is\n    A then 1\n    B then 2\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ x = A\n\n// * We could make it work. But it's a special case that's probably not very important\nlet x = if true then A else B\nfun foo(x) =\n  if x is A do print(123)\n  if x is B do print(456)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ x = A\n\n:expect 1\nfun foo(k, x) =\n  if x === 0 do k(A)\n  k of\n    if x > 0\n      then A\n      else B\nfun bar(v) = if v is\n  A then 1\n  B then 2\nfoo(bar, 123)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(v,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(v,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(v,None)\n//│ deforest > <<< fusing <<<\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/listComprehension.mls",
    "content": ":js\n:deforest\n\nobject Nil\ndata class (::) Cons(h, t)\ndata class Pair(a, b)\nobject A\nobject B\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n\n:expect Cons(Pair(1, 3), Cons(Pair(2, 4), Cons(Pair(3, 5), Nil)))\nfun zip(xs_zip, ys_zip) = if\n  xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt)\n  else Nil\nfun enumFromTo(a, b) = if a < (b + 1) then a :: enumFromTo(a + 1, b) else Nil\nfun lscomp1(ls) = if ls is\n  Pair(x, y1) :: t then\n    fun lscomp2(ls2) = if ls2 is\n      Pair(y2, z) :: t2 and\n        y1 == y2 then Pair(x, z) :: lscomp2(t2)\n        else lscomp2(t2)\n      else lscomp1(t)\n    lscomp2(zip(enumFromTo(x, x + 2), enumFromTo(y1, y1 + 1)))\n  else Nil\nlscomp1(zip(enumFromTo(1, 3), enumFromTo(2, 4)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > \tSelect(Ref(ls2,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls2,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(y,None))))) ->\n//│ deforest > \tRef(tmp:arg$Cons$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(a))\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(b))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > \tSelect(Ref(ls2,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls2,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(y,None))))) ->\n//│ deforest > \tRef(tmp:arg$Cons$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(a))\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(b))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(y,None))))) ->\n//│ deforest > \tRef(tmp:arg$Cons$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(a))\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(b))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(Pair(1, 3), Cons(Pair(2, 4), Cons(Pair(3, 5), Nil)))\n\n\n:expect Cons(Pair(5, 1), Cons(Pair(5, 2), Cons(Pair(5, 5), Nil)))\nfun append(xs, ys) = if xs is\n  h :: t then h :: append(t, ys)\n  Nil then ys\nfun concatMap(f, ls) = if ls is\n  h :: t then append(f(h), concatMap(f, t))\n  Nil then Nil\nfun f1(a1) = if a1 is\n  Pair(a, b) then\n    fun f2(a2) = if a2 is Pair(c, d) then Pair(a, c) :: Nil else Nil\n    concatMap(f2, Pair(1, 3) :: Pair(2, 3) :: Pair(a, b) :: Nil)\n  else Nil\nconcatMap(f1, Pair(5, 10) :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(a))\n//│ deforest > \tSelect(Ref(a2,None),Ident(b))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(a))\n//│ deforest > \tSelect(Ref(a2,None),Ident(b))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(b,None))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(a))\n//│ deforest > \tSelect(Ref(a2,None),Ident(b))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(a))\n//│ deforest > \tSelect(Ref(a2,None),Ident(b))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(a))\n//│ deforest > \tSelect(Ref(a2,None),Ident(b))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(b,None))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(a))\n//│ deforest > \tSelect(Ref(a2,None),Ident(b))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(h,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Lit(IntLit(5))), Arg(None,Lit(IntLit(10)))))) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > \tSelect(Ref(a1,None),Ident(a))\n//│ deforest > \tSelect(Ref(a1,None),Ident(b))\n//│ deforest > <<< fusing <<<\n//│ = Cons(Pair(5, 1), Cons(Pair(5, 2), Cons(Pair(5, 5), Nil)))\n\n\n\n:expect Cons(Pair(1, 3), Cons(Pair(1, 4), Nil))\nfun lscomp1(ls1, ls2) = if ls1 is\n  h1 :: t1 then lscomp2(ls2, h1, t1)\n  Nil then Nil\nfun lscomp2(ls2, h1, t1) = if ls2 is\n  h2 :: t2 then Pair(h1, h2) :: lscomp2(t2, h1, t1)\n  Nil then lscomp1(t1, ls2)\nlscomp1(1 :: 2 :: Nil, 3 :: 4 :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > \tSelect(Ref(ls2,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls2,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(4))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > \tSelect(Ref(ls2,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls2,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls1,None)\n//│ deforest > \tSelect(Ref(ls1,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls1,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls1,None)\n//│ deforest > \tSelect(Ref(ls1,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls1,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls1,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(Pair(1, 3), Cons(Pair(1, 4), Nil))\n\n\n:expect Cons(2, Cons(3, Cons(4, Nil)))\nfun lscomp(ls) = if ls is\n  h :: t then (h + 1) :: lscomp(t)\n  Nil then Nil\nif A is\n  A then lscomp(1 :: 2 :: 3 :: Nil)\n  B then Nil\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > <<< fusing <<<\n//│ = Cons(2, Cons(3, Cons(4, Nil)))\n\n\n:lift\n:deforest\nfun h() =\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    x :: xs then\n      fun lscomp2(ls) = if ls is\n        Nil then lscomp1(xs)\n        y :: ys then [x, y] :: lscomp2(ys)\n      lscomp2(1 :: 2 :: 3 :: Nil)\n  lscomp1(1 :: 2 :: 3 :: Nil)\nh()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(\n//│   [1, 1],\n//│   Cons(\n//│     [1, 2],\n//│     Cons(\n//│       [1, 3],\n//│       Cons(\n//│         [2, 1],\n//│         Cons(\n//│           [2, 2],\n//│           Cons([2, 3], Cons([3, 1], Cons([3, 2], Cons([3, 3], Nil))))\n//│         )\n//│       )\n//│     )\n//│   )\n//│ )\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/module.mls",
    "content": ":js\n\n\n:deforest\n:expect 123\nmodule M with\n  data class XX(a)\n  data class YY(b)\n  data class ZZ(c)\n  data object OO\n  fun h() = 123\n  fun p() = XX(YY(OO))\n  fun f(x) = if x is\n    XX(YY(y)) then h()\nM.f(M.p())\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Select(Ref(module:M,None),Ident(XX)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(a))\n//│ deforest > Call(Select(Ref(module:M,None),Ident(YY)),List(List(Arg(None,Select(Ref(module:M,None),Ident(OO)))))) ->\n//│ deforest > \tRef(tmp:arg$XX$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$XX$0$,None),Ident(b))\n//│ deforest > <<< fusing <<<\n//│ = 123\n\n\n\n\n\n\n:deforest\n:expect 5056\nmodule DeforestList with\n  data object Nil\n  data class (::) Cons(h, t)\n  fun sum(ls) = if ls is\n    Nil then 0\n    h :: t then h + sum(t)\n  fun enum(n) = if n > 0 then n :: enum(n - 1) else Nil\n  fun main() = DeforestList.sum(DeforestList.enum(3))\n  val res = DeforestList.sum(DeforestList.enum(100))\nDeforestList.res + DeforestList.main()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Select(Ref(module:DeforestList,None),Ident(Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Select(Ref(module:DeforestList,None),Ident(Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Select(Ref(module:DeforestList,None),Ident(Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Select(Ref(module:DeforestList,None),Ident(Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Select(Ref(module:DeforestList,None),Ident(Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Select(Ref(module:DeforestList,None),Ident(Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 5056\n\n\n\n\n\n:deforest\n:expect 5056\nmodule DeforestList with\n  data object Nil\n  data class (::) Cons(h, t)\n  fun sum(ls) =\n    fun helper(ls, acc) = if ls is\n      Nil then acc\n      h :: t then helper(t, acc + h)\n    helper(ls, 0)\n  fun enum(n) = if n > 0 then n :: enum(n - 1) else Nil\n  fun main() = DeforestList.sum(DeforestList.enum(3))\n  val res = DeforestList.sum(DeforestList.enum(100))\nDeforestList.res + DeforestList.main()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Select(Ref(module:DeforestList,None),Ident(Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Select(Ref(module:DeforestList,None),Ident(Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Select(Ref(module:DeforestList,None),Ident(Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Select(Ref(module:DeforestList,None),Ident(Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Select(Ref(module:DeforestList,None),Ident(Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Select(Ref(module:DeforestList,None),Ident(Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 5056\n\n\n\n:deforest\n:expect 3\nmodule MMM with\n  data object A\n  val y = 3\n  val x = MMM.f()\n  fun f() =\n    if A is A then y\nMMM.f()\n//│ deforest > >>> fusing >>>\n//│ deforest > Select(Ref(module:MMM,None),Ident(A)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Select(Ref(module:MMM,None),Ident(A)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Select(Ref(module:MMM,None),Ident(A)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n\n:deforest\n:expect X\nmodule M with\n  data object X\n  data object Y\n  val x = X\n  val y = Y\n  fun f(k) =\n    if k is X then\n      if y is\n        Y then x\nM.f(M.X)\n//│ deforest > >>> fusing >>>\n//│ deforest > Select(Ref(member:M,Some(module:M)),Ident(X)) ->\n//│ deforest > \tRef(k,None)\n//│ deforest > <<< fusing <<<\n//│ = X\n\n\n:deforest\n:expect [D, A]\ndata object A\ndata class B(b)\ndata object C\ndata object D\nmodule M with\n  fun f(x) = if M.g(false) is\n    A and\n      x < 1 then B(0)\n      else M.f(x - 1)\n    C then D\n  fun g(b) =\n    if b then\n      if M.f(0) is\n        B then A\n        D then A\n    else\n      C\n[M.f(3), M.g(true)]\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:D,Some(object:D)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:B,Some(term:B/B)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:C,Some(object:C)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:D,Some(object:D)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:B,Some(term:B/B)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:C,Some(object:C)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > <<< fusing <<<\n//│ = [D, A]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/multiArgLists.mls",
    "content": ":js\n:deforest\n\n// Test: Deforestation with function of multiple parameter lists\nobject A\ndata class Pair(x, y)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nfun test(a)(b) =\n  if a is Pair(x, y) then x + y + b\ntest(Pair(1, 2))(3)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(x))\n//│ deforest > \tSelect(Ref(a,None),Ident(y))\n//│ deforest > <<< fusing <<<\n//│ = 6\n\n// Test: Deforestation with nested constructor calls and multiple param lists\ndata class Box(v)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nfun unbox(b)(offset) =\n  if b is Box(v) then v + offset\nunbox(Box(10))(5)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Box,Some(term:Box/Box)),List(List(Arg(None,Lit(IntLit(10)))))) ->\n//│ deforest > \tRef(b,None)\n//│ deforest > \tSelect(Ref(b,None),Ident(v))\n//│ deforest > <<< fusing <<<\n//│ = 15\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/nestedMatch.mls",
    "content": ":js\n:deforest\n\nobject A\nobject B\nobject C\ndata class AA(x)\ndata class BB(x)\ndata class CC(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nobject Nil\ndata class (::) Cons(h, t)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nobject None\ndata class Some(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n:expect 37\nfun f(x, y) =\n  let t = if x is\n    AA(a) then\n      let m = if a is\n        AA(x) then x\n      m + 9\n    BB(b) then b\n  t + y\nfun g(x) = if x is\n  AA then 0\nlet a = AA(AA(3))\nf(a, 2) + g(a) + f(BB(3), 2) + f(AA(AA(4)), 5)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(4)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 37\n//│ a = AA(fun tmp)\n\n\n\n:expect 30\nfun f(x, y) =\n  let n = if x is\n    AA(a) then\n      if a is\n        AA(m) then m\n  n + 2 + y\nf(AA(AA(3)), 9) + f(AA(AA(4)), 10)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(4)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 30\n\n\n\n:expect 5\nfun f(x) =\n  let n = if x is\n    AA(a) then\n      if a is\n        AA(m) then m\n  n + 2\nf(AA(AA(3)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 5\n\n\n\n:expect \"A3A3\"\nfun f(x) =\n  let t = if x is\n    AA(AA(a)) then a\n  t + 3\nf(AA(AA(A))) + f(AA(AA(A)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = \"A3A3\"\n\n\n\n:expect 0\nfun c2(x) = if x is\n  AA(AA(a)) then a\nc2(AA(AA(0)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n\n:expect 3\nfun f(a) = if a is\n  AA(BB(B)) then 3\nf(AA(BB(B)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(member:B,Some(object:B)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(tmp:arg$BB$0$,None)\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n:expect 10\nfun test(x, y, z, i) = if x is\n  AA(a) then\n    let m = if y is\n      AA(a1) then a1 + i\n    let n = if z is\n      BB(a2) then a2 - i\n    m + n\ntest(AA(1), AA(2), BB(3), 4) + test(AA(1), AA(2), BB(3), 4)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(z,None)\n//│ deforest > \tSelect(Ref(z,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(z,None)\n//│ deforest > \tSelect(Ref(z,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 10\n\n\n// only the match in the middle is fused\n:expect \"ccf2f3cc\"\nfun f1(x) = if x is\n  AA(x1) then\n    if x1 is\n      BB(x2) then\n        if x2 is\n          CC(x3) then x3\nfun f2(x) = if x is AA then \"f2\"\nfun f3(x) = if x is CC then \"f3\" + x.CC#x\nfun aa(x) = AA(x)\nlet cc = CC(\"cc\")\nf1(aa(BB(cc))) + f2(aa(BB(CC(0)))) + f3(cc)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(cc,None))))) ->\n//│ deforest > \tRef(x1,None)\n//│ deforest > \tSelect(Ref(x1,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = \"ccf2f3cc\"\n//│ cc = CC(\"cc\")\n\n\n\n:expect 4\nfun c(x, y) = if x is\n  AA then\n    let t = if y is\n      A then 2\n    t + x.AA#x\nlet y = A\nc(AA(2), y)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > <<< fusing <<<\n//│ = 4\n//│ y = fun y7\n\n\n:expect 9\nfun c(x, y) = if x is\n  AA then\n    let t = if y is\n      A then 2 + x.AA#x\n    t + x.AA#x\nfun c2(y) = if y is A then 3\nlet y = A\nc(AA(2), y) + c2(y)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 9\n//│ y = A\n\n\n// need to include computations of `rest` from more than one levels of parent matches\n:expect \"105035\"\nfun test(x) =\n  let t = if x is\n    AA(AA(AA(a))) then a\n    AA then \"3\"\n  t + \"5\"\nfun f(a) = if a is\n  AA(AA) then \"0\"\nlet p = AA(AA(AA(\"10\")))\ntest(p) + f(p) + test(AA(A))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(StrLit(10)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = \"105035\"\n//│ p = AA(AA(fun tmp49))\n\n\n\n\n:expect 13\nfun f(x, y) =\n  let tmp = BB(y + 1)\n  if tmp is\n    BB then\n      let m = if x is\n        AA then\n          if AA(2) is\n            AA(yf) then yf\n      if AA(3) is\n        AA then m + tmp.BB#x\nlet aa = AA(3)\nf(aa, 3) + f(aa, 4)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp,None)\n//│ deforest > \tSelect(Ref(tmp,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp,None)\n//│ deforest > \tSelect(Ref(tmp,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp,None)\n//│ deforest > \tSelect(Ref(tmp,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > <<< fusing <<<\n//│ = 13\n//│ aa = AA(3)\n\n\n\n:expect 16\nfun test(n, p, q) =\n  n +\n  if AA(0) is\n    AA then\n      let k = if p is\n        AA(x) then x\n      if q is\n        AA(y) then k + y\ntest(3, AA(2), AA(3)) + test(3, AA(2), AA(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(q,None)\n//│ deforest > \tSelect(Ref(q,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(q,None)\n//│ deforest > \tSelect(Ref(q,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 16\n\n\n\n:expect 13\nfun test(n, p, q, a) =\n  let o\n  if a is\n    A then\n      let k\n      if p is\n        AA(x) then\n          k = x\n      if q is\n        AA(y) then\n          o = k + y\n  o + n\nlet a = A\nfun c(a) = if a is A then 0\ntest(1, AA(2), AA(3), a) + test(2, AA(2), AA(3), a) + c(a)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(q,None)\n//│ deforest > \tSelect(Ref(q,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(q,None)\n//│ deforest > \tSelect(Ref(q,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 13\n//│ a = A\n\n\n\n:expect 18\nfun test(x, y, z, i) =\n  let k = if x is\n    AA(a) then\n      let m = if y is\n        AA(a1) then a1 + i\n      let n = if z is\n        BB(a2) then a2 - i\n      m + n\n  k + i\ntest(AA(1), AA(2), BB(3), 4) + test(AA(1), AA(2), BB(3), 4)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(z,None)\n//│ deforest > \tSelect(Ref(z,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(z,None)\n//│ deforest > \tSelect(Ref(z,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 18\n\n\n:expect 10\nfun test(x, y, z, i) =\n  let k = if x is\n    AA(a) then\n      let m = if y is\n        AA(a1) then a1 + i\n        BB(b2) then b2 - i\n      let n = if z is\n        BB(a2) then a2 - i\n      m + n\n  k + i\ntest(AA(1), AA(2), BB(3), 4) + test(AA(1), BB(2), BB(3), 4)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(z,None)\n//│ deforest > \tSelect(Ref(z,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(z,None)\n//│ deforest > \tSelect(Ref(z,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 10\n\n\n:expect 12\nfun test(x) =\n  let n = if x is\n    AA(BB(b)) then b\n    AA(CC(c)) then c\n    else 0\n  n + 3\nfun c(x) = if x is AA then 0\nfun p(x) = AA(x)\ntest(p(BB(3))) + test(p(CC(3))) + c(p(A))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:CC,Some(term:CC/CC)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 12\n\n\n\n\n\n:expect 41\nfun f(x, y, z, k) =\n  let tmp = if z then BB(y + 1) else BB(y - 1)\n  tmp.BB#x + \n  if tmp is\n    BB then\n      let m = if x is\n        AA then\n          if AA(2) is\n            AA(yf) then yf\n      if AA(3) is\n        AA then m + k\nf(AA(3), 3, true, 10) + f(AA(5), 4, false, 20)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(5)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 41\n\n\n\n:expect 15\nfun test(x) =\n  let t = if x is\n    AA(AA(AA(a))) then a\n  t + 5\nfun f(a) = if a is\n  AA(AA) then 0\nlet p = AA(AA(AA(10)))\ntest(p) + f(p)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(10)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 15\n//│ p = AA(AA(fun tmp114))\n\n\n:expect \"()()\"\nfun test(a, b) =\n  let x\n  if a is\n    A then print(\"A\")\n    B then\n      x = 1\n  if b is\n    A then\n      x = 2\n    B then print(\"B\")\n  print(x)\ntest(B, B) + test(A, A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(b,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(b,None)\n//│ deforest > <<< fusing <<<\n//│ > B\n//│ > 1\n//│ > A\n//│ > 2\n//│ = \"()()\"\n\n\n// this misalign is fine\n:deforest\n:expect 20\nfun prodDouble(x) = if x is\n  0 then Nil\n  n then n :: n :: prodDouble(n - 1)\nfun sum(ls) = if ls is\n  Nil then 0\n  h :: t then h + sum(t)\nsum(prodDouble(4))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = 20\n\n\n// this misalign prevents fusion (consumer destructures 2 elements per step, producer emits 1)\n:deforest\n:expect 10\nfun prod(x) = if x is\n  0 then Nil\n  n then n :: prod(n - 1)\nfun cons(ls) = if ls is\n  h1 :: h2 :: t then h1 + h2 + cons(t)\n  _ then 0\ncons(prod(4))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 10\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/recursive.mls",
    "content": ":js\n:deforest\n\n\n\nobject Nil\ndata class (::) Cons(h, t)\nobject None\ndata class Some(v)\nobject A\nobject B\ndata class T(n, l, r)\nobject L\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n\n// :sir\nfun map(f, ls_map) = if ls_map is\n  h :: t then f(h) :: map(f, t)\n  Nil then Nil\nlet c = Cons(1, Nil)\nmap(x => x + 1, c)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(2, Nil)\n//│ c = fun c\n\n// :sir\nfun map(f, ls_map) = if ls_map is\n  h :: t then f(h) :: map(f, t)\n  Nil then Nil\nfun c(a) = Cons(a, Nil)\nmap(x => x + 1, c(1))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(2, Nil)\n\n\n:expect Cons(2, Cons(3, Nil))\nfun map(ls, f) = if ls is\n  Nil then Nil\n  h :: t then f(h) :: map(t, f)\nmap(1 :: 2 :: Nil, x => x + 1)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(2, Cons(3, Nil))\n\n:expect 6\nfun sum(ls) = if ls is\n  Nil then 0\n  h :: t then h + sum(t)\nfun enum(n) = if n > 0 then n :: enum(n - 1) else Nil\nsum(enum(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 6\n\n\n:expect Cons(4, Cons(6, Nil))\nfun map(ls, f) = if ls is\n  Nil then Nil\n  h :: t then f(h) :: map(t, f)\nmap(map(id(1 :: 2 :: Nil), x => x + 1), x => x * 2)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(4, Cons(6, Nil))\n\n:expect Cons(7, Cons(5, Cons(3, Cons(1, Nil))))\nfun map(f, ls) = if ls is\n  Nil then Nil\n  h :: t then f(h) :: map(f, t)\nfun enum(a) = if a < 0 then Nil else a :: enum(a - 1)\nmap(x => x + 1, map(x => x * 2, id(enum(3))))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(7, Cons(5, Cons(3, Cons(1, Nil))))\n\n\n\n\n:expect 2\nfun f(x) = if x == 0 then Nil else x :: g(x - 1)\nfun g(y) = if y == 0 then Nil else y :: f(y - 1)\nfun cons(a) = if a is\n  Nil then 0\n  h :: t then h + cons(t)\nfun cons1(a1) = if a1 is\n  Nil then 1\n  h :: t then h + cons1(t)\ncons(f(0)) + cons1(f(1))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > \tSelect(Ref(a1,None),Ident(h))\n//│ deforest > \tSelect(Ref(a1,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(y,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > \tSelect(Ref(a1,None),Ident(h))\n//│ deforest > \tSelect(Ref(a1,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(h))\n//│ deforest > \tSelect(Ref(a,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(y,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(h))\n//│ deforest > \tSelect(Ref(a,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n\n:expect 12\nfun to(n) =\n  if n > 0 then\n    let m = n - 1\n    n :: to(m)\n  else\n    Nil\nfun f1(ls1) = if ls1 is\n  h :: t then h + f1(t)\n  Nil then 2\nf1(to(4))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls1,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls1,None)\n//│ deforest > \tSelect(Ref(ls1,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls1,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 12\n\n:expect Cons(4, Cons(6, Nil))\nfun map(ls, f) = if ls is\n  Nil then Nil\n  h :: t then f(h) :: map(t, f)\nfun succ(x) = x + 1\nfun double(x) = x * 2\nmap(map(1 :: 2 :: Nil, succ), double)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(4, Cons(6, Nil))\n\n:expect 10\nfun to(n) = if n > 0 then n :: to(n - 1) else Nil\nfun f1(ls) = if ls is\n  h :: t then h\n  Nil then 2\nfun f2(ls) = if ls is\n  h :: t then h + 1\n  Nil then 3\nfun wrap(n) = to(n)\nf1(wrap(4)) + f2(wrap(5))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = 10\n\n:expect 51\nfun to(n, acc) = if n == 0 then acc else to(n - 1, n :: acc)\nfun f1(ls, acc) = if ls is\n  Nil then acc\n  h :: t then f1(t, acc + h)\nfun f2(ls, acc) = if ls is\n  Nil then acc\n  h :: t then f2(t, acc + h + 1)\nf1(to(4, Nil), 0) + f2(to(5, Nil), 0) + f1(to(6, Nil), 0)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(acc,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(acc,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(acc,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 51\n\n:expect Cons(12, Cons(18, Nil))\nfun map(ls, f) = if ls is\n  Nil then Nil\n  h :: t then f(h) :: map(t, f)\nfun succ(x) = x + 1\nfun double(x) = x * 2\nfun triple(x) = x * 3\nmap(map(map(1 :: 2 :: Nil, succ), double), triple)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(12, Cons(18, Nil))\n\n\n\n\n:expect Cons(11, Cons(9, Cons(7, Cons(5, Cons(3, Cons(1, Nil))))))\nfun mk(n) = if n < 0 then Nil else n :: mk(n - 1)\nfun map(f, ls_map) = if ls_map is\n  h :: t then f(h) :: map(f, t)\n  Nil then Nil\nfun map1(f, ls_map1) = if ls_map1 is\n  h :: t then f(h) :: map1(f, t)\n  Nil then Nil\nfun incr(x) = x + 1\nfun double(x) = x * 2\nmap1(incr, map(double, id(mk(5))))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_map1,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls_map1,None)\n//│ deforest > \tSelect(Ref(ls_map1,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_map1,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(11, Cons(9, Cons(7, Cons(5, Cons(3, Cons(1, Nil))))))\n\n\n\n:expect Cons(5, Cons(6, Cons(7, Nil)))\nfun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil\nfun map(ls) = if ls is\n  Nil then Nil\n  h :: t then (h + 4) :: map(t)\nmap(enumFromTo(1, 4))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(5, Cons(6, Cons(7, Nil)))\n\n:expect 45\nfun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil\nfun sum(ls) = if ls is\n  Nil then 0\n  h :: t then h + sum(t)\nsum(enumFromTo(1,10))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 45\n\n:expect Cons(5, Cons(6, Cons(7, Nil)))\nfun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil\nfun map(f, ls) =\n  if ls is\n    Nil then Nil\n    h :: t then f(h) :: map(f, t)\nmap(x => x + 4, enumFromTo(1, 4))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(5, Cons(6, Cons(7, Nil)))\n\n:expect Cons(5, Cons(6, Cons(7, Nil)))\nfun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil\nfun map(f, ls) =\n  (if ls is\n    Nil then f => Nil\n    h :: t then f => f(h) :: map(f, t)\n  )(f)\nmap(x => x + 4, enumFromTo(1, 4))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(5, Cons(6, Cons(7, Nil)))\n\n\n\n:expect 45\nfun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil\nfun sum(ls, a) = if ls is\n  Nil then a\n  h :: t then sum(t, h + a)\nsum(enumFromTo(1, 10), 0)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > \tSelect(Ref(ls,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 45\n\n\n\n:expect Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\nfun mk(n) = if n < 0 then Nil else n :: mk(n - 1)\nfun incr(x) = x + 1\nfun map(f, xs_map) = if xs_map is\n  Nil then Nil\n  x :: xs then f(x) :: map(f, xs)\nfun rev(xs_rev, acc) = if xs_rev is\n  x :: xs then rev(xs, x :: acc)\n  Nil then acc\nmap(incr, rev(id(mk(5)), Nil))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_map,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(acc,None))))) ->\n//│ deforest > \tRef(xs_map,None)\n//│ deforest > \tSelect(Ref(xs_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_map,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Nil))))))\n\n\n\n:expect Cons(1, Cons(2, Cons(3, Cons(4, Nil))))\nfun mk(n) = if n < 0 then Nil else n :: mk(n - 1)\nfun incr(x) = x + 1\nfun map(f, xs_map) = if xs_map is\n  Nil then Nil\n  x :: xs then f(x) :: map(f, xs)\nfun rev(xs_rev, acc) = if xs_rev is\n  x :: xs then rev(xs, x :: acc)\n  Nil then acc\nrev(map(incr, id(mk(3))), Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs_rev,None)\n//│ deforest > \tSelect(Ref(xs_rev,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_rev,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_rev,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))\n\n\n\ndata class Pair(a, b)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\nfun pair_up(xs) =\n  if xs is\n    x :: xss then\n      if xss is\n        y :: xs then Pair(x, y) :: pair_up(xs)\n        else Nil\n    else Nil\nfun mk(n) = if n > 0 then (n - 1) :: n :: (n + 1) :: mk(n - 1) else Nil\npair_up(mk(4))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Cons(\n//│   Pair(3, 4),\n//│   Cons(\n//│     Pair(5, 2),\n//│     Cons(\n//│       Pair(3, 4),\n//│       Cons(Pair(1, 2), Cons(Pair(3, 0), Cons(Pair(1, 2), Nil)))\n//│     )\n//│   )\n//│ )\n\n\n\n:expect 20\nfun mk(n) = if n > 0 then n :: mk(n - 1) else Nil\nfun mk2d(n) = if n > 0 then mk(n) :: mk2d(n - 1) else Nil\nfun append(xs, ys) = if xs is\n  Nil then ys\n  x :: xs then x :: append(xs, ys)\nfun sum(ls_sum) = if ls_sum is\n  Nil then 0\n  x :: xs then x + sum(xs)\nfun flatten(ls_flatten) = if ls_flatten is\n  Nil then Nil\n  x :: xs then append(x, flatten(xs))\nsum(flatten(id(mk2d(4))))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_sum,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls_sum,None)\n//│ deforest > \tSelect(Ref(ls_sum,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_sum,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 20\n\n\n:expect 2\nfun count(c, xs) = if xs is\n  h :: t then count(c + 1, t)\n  Nil then c\nfun rev(a, ys) = if ys is\n  h :: t then rev(h :: a, t)\n  Nil then a\ncount(0, rev(Nil, 1 :: 2 :: Nil))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(h,None)), Arg(None,Ref(a,None))))) ->\n//│ deforest > \tRef(xs,None)\n//│ deforest > \tSelect(Ref(xs,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ys,None)\n//│ deforest > \tSelect(Ref(ys,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ys,None)\n//│ deforest > \tSelect(Ref(ys,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys,None)\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n:expect Some(2)\nfun last(ls) = if ls is\n  h :: t and t is\n    Nil then Some(h)\n    _ :: _ then last(t)\n  Nil then None\nlet p = 1 :: 2 :: Nil\nlast(p)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Some(2)\n//│ p = Cons(1, Cons(2, Nil))\n\n\n\n:expect Cons(1, Cons(0, Nil))\nfun map(f, xs_map) = if xs_map is\n  Nil then Nil\n  x :: xs then f(x) :: map(f, xs)\nmap(x => if x is A then 1 else 0, A :: B :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(member:A,Some(object:A))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs_map,None)\n//│ deforest > \tSelect(Ref(xs_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_map,None),Ident(t))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(member:B,Some(object:B))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(xs_map,None)\n//│ deforest > \tSelect(Ref(xs_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_map,None),Ident(t))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_map,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(1, Cons(0, Nil))\n\n\n:expect T(0, T(1, L, L), T(0, L, L))\nfun c(x) = if x is\n  T(n, l, r) then T of\n    if n is\n      A then 0\n      B then 1\n    c(l)\n    c(r)\n  L then L\nc(T(A, T(B, L, L), T(A, L, L)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:T,Some(term:T/T)),List(List(Arg(None,Ref(member:A,Some(object:A))), Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(n))\n//│ deforest > \tSelect(Ref(x,None),Ident(l))\n//│ deforest > \tSelect(Ref(x,None),Ident(r))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(n,None)\n//│ deforest > Call(Ref(member:T,Some(term:T/T)),List(List(Arg(None,Ref(member:A,Some(object:A))), Arg(None,Ref(member:L,Some(object:L))), Arg(None,Ref(member:L,Some(object:L)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(n))\n//│ deforest > \tSelect(Ref(x,None),Ident(l))\n//│ deforest > \tSelect(Ref(x,None),Ident(r))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(n,None)\n//│ deforest > Ref(member:L,Some(object:L)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:L,Some(object:L)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:T,Some(term:T/T)),List(List(Arg(None,Ref(member:B,Some(object:B))), Arg(None,Ref(member:L,Some(object:L))), Arg(None,Ref(member:L,Some(object:L)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(n))\n//│ deforest > \tSelect(Ref(x,None),Ident(l))\n//│ deforest > \tSelect(Ref(x,None),Ident(r))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(n,None)\n//│ deforest > Ref(member:L,Some(object:L)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:L,Some(object:L)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = T(0, T(1, L, L), T(0, L, L))\n\n\n:expect 4\nfun max(ms, m) = if ms is\n  h :: t and\n    h > m then max(t, h)\n    else max(t, m)\n  Nil then m\nmax(3 :: 2 :: 4 :: 1 :: 0 :: Nil, 0)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ms,None)\n//│ deforest > \tSelect(Ref(ms,None),Ident(h))\n//│ deforest > \tSelect(Ref(ms,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ms,None)\n//│ deforest > \tSelect(Ref(ms,None),Ident(h))\n//│ deforest > \tSelect(Ref(ms,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(4))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ms,None)\n//│ deforest > \tSelect(Ref(ms,None),Ident(h))\n//│ deforest > \tSelect(Ref(ms,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ms,None)\n//│ deforest > \tSelect(Ref(ms,None),Ident(h))\n//│ deforest > \tSelect(Ref(ms,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(0))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(ms,None)\n//│ deforest > \tSelect(Ref(ms,None),Ident(h))\n//│ deforest > \tSelect(Ref(ms,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ms,None)\n//│ deforest > <<< fusing <<<\n//│ = 4\n\n\n:expect Some(4)\nfun filter(ls, f) = if ls is\n  h :: t and\n    f(h) then h :: filter(t, f)\n    else filter(t, f)\n  Nil then Nil\nfun last(ls_last) =\n  fun go(a, ls_go) = if ls_go is\n    Nil then a\n    h :: t then go(h, t)\n  if ls_last is\n    h :: t then Some(go(h, t))\n    Nil then None\nfun lastFilter(ls, f) = last(filter(ls, f))\nlastFilter(id(1 :: 2 :: 3 :: 4 :: 5 :: Nil), x => (x % 2 == 0))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = Some(4)\n\n// should prevent processing a function body more than once\n:deforest\nfun g() = f()\nfun f() = g() + g()\n[f, g]\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = [fun f, fun g]\n\n\n// should prevent processing a function body more than once\n:deforest\nfun h1() = g()\nfun h2() = g()\nfun g() = f()\nfun f() = h1() + h2()\n[h1, h2, g, f]\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = [fun h1, fun h2, fun g, fun f]\n\n\n\n// should prevent processing a function body more than once\n:deforest\nfun h1() = g()\nfun h2() = g() + h1()\nfun g() = f()\nfun f() = h1() + h2()\n[h1, h2, g, f]\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = [fun h1, fun h2, fun g, fun f]\n\n\n// should prevent processing a function body more than once\n:deforest\nfun main() = if\n  false then f() + g()\n  else 0\nfun f() = if\n  false then h()\n  else 0\nfun h() = if\n  false then f() + main()\n  else 0\nfun g() = if\n  false then h() + main()\n  else 0\nmain\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = fun main\n\n\n\n\n\n:deforest\nfun f() =\n  if B is\n    B then h1() + h2()\nfun h1() = g1()\nfun g1() = f()\nfun h2() = g2()\nfun g2() = f()\nf\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(member:B,Some(object:B))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(member:B,Some(object:B))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(member:B,Some(object:B))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(member:B,Some(object:B))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(member:B,Some(object:B))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(member:B,Some(object:B))\n//│ deforest > <<< fusing <<<\n//│ = fun f_9$f\n\n\n:deforest\nfun h1() = g()\nfun h2() = g() + h2()\nfun g() = f()\nfun f() = h1() + h2()\n[h1, h2, g, f]\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = [fun h1, fun h2, fun g, fun f]\n\n:deforest\nfun g() = f()\nfun f() = g()\n[g, f]\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = [fun g, fun f]\n\n\n\n:deforest\nfun g() = 0\nfun f() = f() + g()\n[f, g]\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = [fun f, fun g]\n\n\n:deforest\nfun h(x) = if x is\n  A then 0\n  else f()\nfun g1() = h(B)\nfun g2() = h(B)\nfun g3() = h(B)\nfun g4() = h(B)\nfun f() =\n  [g1(), g2(), g3(), g4(), h(B)]\nf\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = fun f_17$f\n\n\n:deforest\nfun h(x) = if x is\n  A then 0\n  else f()\nfun g1() = h(B)\nfun g2() = h(B)\nfun f() =\n  [g1(), g2()]\nf\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = fun f_9$f\n\n\n\n\n:deforest\n:lift\nfun f() =\n  fun h(x) = if x is\n    A then 0\n    else f()\n  [() => h(B), () => h(B), () => h(B), () => h(B), h(B)]\nf\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = fun f_13$f\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/relaxedPrograms.mls",
    "content": ":js\n\n:deforest\n:expect 5\ndata class AA(x)\nclass Store(n) with\n  fun get() =\n    if AA(n) is AA(x) then x + n\n  fun foo(x) =\n    if x is\n      AA(x) then x + n\nval store = Store(1)\nstore.foo(AA(4))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(term:Store/n,None))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 5\n//│ store = Store(_)\n\n\n\n\n\n\n\n:deforest\n:expect 3\nfun classMethodSibling() =\n  if AA(1) is\n    AA(x) then x + store.get()\nclassMethodSibling()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n:deforest\nlet r =\n  a: 0\n  value: 1\nif AA(1) is\n  AA(x) then\n    x + r!a\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 1\n//│ r = {a: 0, value: 1}\n\n\n:expect 2\n:deforest\nif AA(1) is\n  AA(x) then\n    let xs = [0, 1]\n    x + xs!1\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n\n// TODO: rewriting for nested classes\n:deforest\n:fixme\nfun nestedClass() =\n  class Local() with\n    fun get() = 0\n  Local().get()\n  if AA(1) is\n    AA(x) then x\nnestedClass()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ /!!!\\ Uncaught error: java.lang.AssertionError: assertion failed\n\n\n\n// TODO: rewriting for loops\n:deforest\n:fixme\nfun loopSibling() =\n  while false do\n    if AA(1) is\n      AA(x) then print(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: unsupported `continue` instruction during rewriting (of class String)\n\n\n// TODO: branch body capturing mutable vars\n:fixme\n:deforest\n:expect 5\nclass C(n) with\n  let _n = n\n  fun get() =\n    if AA(1) is AA(x) then\n      let res = x + _n\n      _n = _n + 1\n      res\nlet c = C(1)\nc.get() + c.get()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ ═══[RUNTIME ERROR] Expected: '5', got: '4'\n//│ = 4\n//│ c = C(_)\n\n\n// TODO: private members aren't visible outside\n:fixme\n:deforest\nmodule M with\n  let _private = 3\n  fun f() =\n    if AA(1) is\n      AA(a) then a + _private\nM.f()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ > let M1, f_7$scrut_AA, f_6$f, f_6$scrut_AA, inlinedVal1, scrut3, AA_x3;try { globalThis.Object.freeze(class M {   static {     M1 = this   }   static #_private;   static {     M.#_private = 3;   }   static f() {     runtime.checkArgs(\"f\", 0, true, arguments.length);     let scrut4, AA_x4;     AA_x4 = 1;     scrut4 = (fv_ctorLam__private, fv_ctorLam_a, fv_ctorLam_arg$AA$0$) => {       let fv__private, fv_a, fv_arg$AA$0$, AA_x5, inlinedVal2;       fv__private = fv_ctorLam__private;       fv_a = fv_ctorLam_a;       fv_arg$AA$0$ = fv_ctorLam_arg$AA$0$;       AA_x5 = AA_x4;       fv_arg$AA$0$ = AA_x5;       fv_a = fv_arg$AA$0$;       inlinedVal2 = fv_a + fv__private;       return inlinedVal2     };     return runtime.checkCall(scrut4(M.#_private, undefined, undefined))   }   toString() { return runtime.render(this); }   static [definitionMetadata] = [\"class\", \"M\"];  }); AA_x3 = 1; scrut3 = (fv_ctorLam__private, fv_ctorLam_a, fv_ctorLam_arg$AA$0$) => {   let fv__private, fv_a, fv_arg$AA$0$, AA_x4, inlinedVal2;   fv__private = fv_ctorLam__private;   fv_a = fv_ctorLam_a;   fv_arg$AA$0$ = fv_ctorLam_arg$AA$0$;   AA_x4 = AA_x3;   fv_arg$AA$0$ = AA_x4;   fv_a = fv_arg$AA$0$;   inlinedVal2 = fv_a + fv__private;   return inlinedVal2 }; inlinedVal1 = runtime.checkCall(scrut3(M.#_private, undefined, undefined)); block$res6 = inlinedVal1; undefined; undefined } catch (e) { console.log('\\u200B' + e + '\\u200B'); }\n//│ ═══[COMPILATION ERROR] [Uncaught SyntaxError] Private field '#_private' must be declared in an enclosing class\n\n\n\n// TODO: rewrite selecting from nested modules\n:fixme\n:deforest\nmodule M with\n  module MM with\n    fun g() = 5\n    fun f() =\n      if AA(1) is\n        AA(a) then a + g()\nM.MM.f()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ ═══[RUNTIME ERROR] ReferenceError: MM is not defined\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/selectionsInNestedMatch.mls",
    "content": ":js\n:deforest\n\nobject A\nobject B\nobject C\ndata class AA(x)\ndata class BB(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nobject Nil\ndata class Cons(h, t)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nobject None\ndata class Some(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n\n\n:expect 2\nfun c(x) = if x is\n  AA then\n    if A is\n      A then x.AA#x\nc(AA(2))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n:expect 2\nfun c(x, y) = if x is\n  AA then\n    if y is\n      A then x.AA#x\nc(AA(2), A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n\n:expect 2\nfun c(x, y) = if x is\n  AA then\n    if y is\n      A then x.AA#x\nfun p() = AA(2)\nc(p(), A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n\n\n:expect 3\nfun c(x, y) = if x is\n  AA then\n    let a = if y is\n      A then 1\n    a + x.AA#x\nfun p() = AA(2)\nc(p(), A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n\n\n:expect 42\nfun f(x) = if x is\n  AA(AA(a)) then g(a)\nfun g(x) = if x is\n  AA(b) then f(b)\n  A then 42\nf(AA(AA(AA(AA(AA(A))))))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 42\n\n:expect A\nfun f(x) = if x is\n  AA(AA(a)) then a\nf(AA(AA(A)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = A\n\n:expect A\nfun f(x) = if x is\n  AA(AA(a)) then a\nfun p() = AA(AA(A))\nf(p())\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = A\n\n\n\n:expect 12\nfun c(x, y) =\n  let t = if x is\n    AA then\n      if A is\n        A then x.AA#x\n  t + y\nc(AA(2), 10)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ = 12\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/simple.mls",
    "content": ":js\n:deforest\n\n\nobject A\nobject B\nobject C\nobject D\ndata class AA(aa)\ndata class BB(bb)\ndata class AAA(x, y)\ndata class BBB(x, y)\ndata class CCC(c)\nobject None\ndata class Some(value)\ndata object Nil\ndata class (::) Cons(h, t)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n\n// * Note that this test produces dead code (non-empty rest after an abortive block prefix),\n// * but that code is now renoved, as can be checked by comparing `:sir` and `:soir` outputs.\n// * FIXME: At the time of writing, there is currently still some (non-dead) duplication of the big addition, though.\n// :sir\n// :soir\nfun test(x) =\n  let y = if x is\n    AA(AA(v)) then v\n  y + 1 + 2 + 3 + 4\ntest(AA(AA(10)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(10)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 20\n\n\n\n:expect 1\nlet x = if true then A else B\nif x is\n  A then 1\n  B then 2\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 1\n//│ x = fun tmp2\n\n:expect A\nlet x = if true then AA(A) else BB(B)\nif x is\n  AA(x) then x\n  BB(x) then x\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(member:B,Some(object:B)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = A\n//│ x = fun tmp3\n\n\n:expect 1\nfun f(a) = if a is\n  A then 1\n  B then 2\nlet x = if true then AA(A) else BB(B)\nif x is\n  AA(x) then f(x)\n  BB(x) then f(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(member:B,Some(object:B)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > <<< fusing <<<\n//│ = 1\n//│ x = fun tmp4\n\n\n// `x.x` is successfully fused\n:expect 1\nfun f1(a) = if a is\n  A then 1\n  B then 2\n  C then 3\nfun f2(a) = if a is\n  A then 4\n  B then 5\n  C then 6\nlet x = if true then AA(A) else BB(B)\nif x is\n  AA then f1(x.AA#aa)\n  BB then f2(x.BB#bb)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(member:B,Some(object:B)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:A,Some(object:A)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > <<< fusing <<<\n//│ = 1\n//│ x = fun tmp5\n\n\n:expect 11\nfun g(x) = if true then AA(11) else BB(22)\nfun c(x) = if x is\n  AA(x) then x\n  BB(x) then x\nc(g(true))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(22)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(11)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 11\n\n\n\n\n// multiple match, no fusion\n:expect 2\nlet x = B\nif x is\n  A then 1\n  B then 3\nif x is\n  B then 2\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 2\n//│ x = B\n\n\n\n:expect 2\nlet x = A\nlet y = B\nif x is\n  A then 1\nif y is\n  B then 2\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 2\n//│ x = fun x11\n//│ y = fun y\n\n\n:expect 3\nfun c(a) =\n  let x = if a is\n    A then 1\n    B then 2\n  print(x)\n  x\nc(A) + c(B)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > <<< fusing <<<\n//│ > 1\n//│ > 2\n//│ = 3\n\n\n\n\n:expect 5\nfun c(x) =\n  let t = x.AA#aa\n  let n = if x is\n    AA then 2\n  n + t\nc(AA(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 5\n\n\n\n:expect 3\nfun f(a, b) = if a is\n  A then if b is\n    B then 3\nf(A, B)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(b,None)\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n:expect 0\nfun f(x) = if x is\n  Some then if x.Some#value > 1 then f(Some(x.Some#value - 1)) else 0\nf(Some(2))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Some,Some(term:Some/Some)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(value))\n//│ deforest > \tSelect(Ref(x,None),Ident(value))\n//│ deforest > Call(Ref(member:Some,Some(term:Some/Some)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(value))\n//│ deforest > \tSelect(Ref(x,None),Ident(value))\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n\n:expect 2\nlet x = A\nlet y = B\nif x is\n  A then 1\nif y is\n  B then 2\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 2\n//│ x = fun x13\n//│ y = fun y1\n\n\n\n:expect 21\nfun f(x, y) =\n  let a = if x is\n    AAA(n, m) then y + n - m\n    BBB(n, m) then m + 1 - n\n  a + 3\nf(AAA(1, 3), 1) + f(BBB(2, 3), 2) + f(AAA(3, 2), 4) + f(BBB(4, 6), 0)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BBB,Some(term:BBB/BBB)),List(List(Arg(None,Lit(IntLit(4))), Arg(None,Lit(IntLit(6)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > Call(Ref(member:AAA,Some(term:AAA/AAA)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > Call(Ref(member:BBB,Some(term:BBB/BBB)),List(List(Arg(None,Lit(IntLit(2))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > Call(Ref(member:AAA,Some(term:AAA/AAA)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > <<< fusing <<<\n//│ = 21\n\n\n:expect 2\nfun c1(x) = if x is\n  AA then\n    if A is\n      A then x.AA#aa\nfun c2(x) = if x is\n  AA then x.AA#aa\nfun p(a) = c1(a) + c2(a)\np(AA(1))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n\n:expect 2\nfun c(x, y) = if x is\n  AA(a) then\n    if y is\n      A then a\nc(AA(2), A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n\n:expect 24\nfun f(x, y) =\n  let a = if x is\n    AAA(n, m) then y + n - m\n    CCC(n) then n + 1\n  a + 3\nf(AAA(1, 3), 1) + f(CCC(2), 2) + f(AAA(3, 2), 4) + f(CCC(4), 0)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:CCC,Some(term:CCC/CCC)),List(List(Arg(None,Lit(IntLit(4)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(c))\n//│ deforest > Call(Ref(member:AAA,Some(term:AAA/AAA)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > Call(Ref(member:CCC,Some(term:CCC/CCC)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(c))\n//│ deforest > Call(Ref(member:AAA,Some(term:AAA/AAA)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > <<< fusing <<<\n//│ = 24\n\n\n\n\n:expect 22\nfun f(x, y) =\n  let a = if x is\n    AAA then y + x.AAA#y\n    CCC(n) then n + 1\n  a + 3\nf(AAA(1, 3), 1) + f(CCC(2), 2) + f(AAA(3, 2), 4)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AAA,Some(term:AAA/AAA)),List(List(Arg(None,Lit(IntLit(3))), Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > Call(Ref(member:CCC,Some(term:CCC/CCC)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(c))\n//│ deforest > Call(Ref(member:AAA,Some(term:AAA/AAA)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > <<< fusing <<<\n//│ = 22\n\n\n:expect 0\nfun c(x, m) = if x is\n  AA(n) then n + 1\n  else m\nc(BB(3), 0)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n\n\n:expect 1\nfun f(x) = if x is\n  AA(b) then g(b)\nfun g(b) = if b is\n  AA(a) then a + 1\nf(AA(AA(0)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(b,None)\n//│ deforest > \tSelect(Ref(b,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 1\n\n\n\n:expect 3\nfun f(x) = x.AA#aa.AA#aa\nf(AA(AA(3)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tterm:AA/aa\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tterm:AA/aa\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n:expect 103\nfun inner(x, y) =\n  let t = if x is\n    AA(a) then a + y\n    BB(b) then b - y\n  t * y\nfun outer1(x, y, z) =\n  let t = if x is\n    AA(a) then inner(a, y)\n    BB(b) then inner(b, y)\n  t + z\nfun outer2(x, y, z) =\n  let t = if x is\n    AA(a) then inner(a, z)\n    BB(b) then inner(b, y)\n  t + y\nlet p = AA(AA(3))\nouter1(p, 1, 2) + outer2(p, 3, 4) + inner(AA(5), 6)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(5)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 103\n//│ p = AA(AA(3))\n\n\n:expect 1\nfun mapHead(f, x) = if x is\n  AAA(h, t) then f(h)\nmapHead(x => x, AAA(1, AAA(2, None)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AAA,Some(term:AAA/AAA)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > \tSelect(Ref(x,None),Ident(y))\n//│ deforest > <<< fusing <<<\n//│ = 1\n\n\n:expect 5\nlet k\nif A is\n  A then\n    k = 3\nk + 2\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > <<< fusing <<<\n//│ = 5\n//│ k = 3\n\n:expect 4\nfun test(a) = if a is\n  AA then 1\n  else 2\ntest(B) + test(C)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:C,Some(object:C)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > <<< fusing <<<\n//│ = 4\n\n\n\n// technically ill-typed, so `AA(3)` (which flows to `z`) is not fused\n:expect \"2AA(3)NaN\"\nfun test(x, y, z) = if x is\n  AA(a) then\n    let m = if y is\n      AA(a1) then a1 + z\n    let n = if z is\n      AA(a2) then a2 - z\n    m + n\ntest(AA(1), AA(2), AA(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(y,None)\n//│ deforest > \tSelect(Ref(y,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = \"2AA(3)NaN\"\n\n\n:expect 141\nfun test(x) =\n  let t = id of\n    if x is\n      AA(CCC(a)) then a\n      BB(CCC(a)) then a\n  t(123).AA#aa + 5 * 4 - 3 + 2 - 1\nlet p = if true then AA(CCC(AA)) else BB(CCC(AA))\ntest(p)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Call(Ref(member:CCC,Some(term:CCC/CCC)),List(List(Arg(None,Ref(member:AA,Some(term:AA/AA)))))) ->\n//│ deforest > \tRef(tmp:arg$BB$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$BB$0$,None),Ident(c))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Call(Ref(member:CCC,Some(term:CCC/CCC)),List(List(Arg(None,Ref(member:AA,Some(term:AA/AA)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(c))\n//│ deforest > <<< fusing <<<\n//│ = 141\n//│ p = fun tmp60\n\n\n:expect 141\nfun test(x, y) =\n  let t =\n    if y is CCC then\n      if x is\n        AA(a) then a\n        BB(a) then a\n  t(123).CCC#c + 5 * 4 - 3 + 2 - 1\nlet p = if true then AA(CCC) else BB(CCC)\ntest(p, id(CCC(123)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Ref(member:CCC,Some(term:CCC/CCC)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(member:CCC,Some(term:CCC/CCC)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 141\n//│ p = fun tmp62\n\n\n:sir\n:expect 2\nfun f(x) = if x is\n  A then 1\nf(id(A)) + f(A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁰, tmp, tmp1, tmp2, f_7$f⁰, f_7$x_A⁰, f_7$x_rest⁰, deforest$lam;\n//│ define f_7$f⁰ as fun f_7$f¹(x) {\n//│   return x()\n//│ };\n//│ define f_7$x_A⁰ as fun f_7$x_A¹() {\n//│   return 1\n//│ };\n//│ define f_7$x_rest⁰ as fun f_7$x_rest¹() {\n//│   return null\n//│ };\n//│ define f⁰ as fun f¹(x) {\n//│   match x\n//│     A⁰ =>\n//│       return 1\n//│     else\n//│       throw new globalThis⁰.Error⁰(\"match error\")\n//│   end\n//│ };\n//│ set tmp = Predef⁰.id⁰(A⁰);\n//│ set tmp1 = f¹(tmp);\n//│ set deforest$lam = () => { return f_7$x_A¹() };\n//│ set tmp2 = f_7$f¹(deforest$lam);\n//│ +⁰(tmp1, tmp2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n\n\n:expect 0\nfun f(x) = if x is\n  A then 0\n  B then 1\nfun g(x) = if x is\n  AA then A\n  BB then B\nf(g(AA(1)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n:expect 1\nfun f(a, b) = if a is\n  A and b is B then 1\n  else 0\nf(A, B)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(b,None)\n//│ deforest > <<< fusing <<<\n//│ = 1\n\n\n\n:expect 6\nfun app(f) = f(1)\nfun identity(x) = x\nfun c1(x1) = if x1 is\n  AA(i) then i\nfun c2(x) = if x is\n  AA(i) then i\n  A then 0\nc1(app(AA)) + c1(AA(2)) + c2(AA(3)) + c2(A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x1,None)\n//│ deforest > \tSelect(Ref(x1,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 6\n\n:re\nfun p(x) = if x\n  then new AA(2)\n  else BB(3)\nfun c(x) = if x is\n  AA(a) then a\n  BB(b) then b\n  else throw (if A is A then Error(\"e1\") else Error(\"e2\"))\nprint(c(p(true)) + c(p(false)))\nc(B)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Instantiate(false,Ref(member:AA,Some(class:AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(member:A,Some(object:A))\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(bb))\n//│ deforest > Instantiate(false,Ref(member:AA,Some(class:AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ > 5\n//│ ═══[RUNTIME ERROR] Error: e1\n\n\n:expect 3\nfun f(a, b) = if a is\n  AA(x) then x + b.BB#bb\nf(AA(1), BB(2))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tterm:BB/bb\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n:deforest\n:expect 9\nfun g(k, x) = if k is\n  A then x.AA#aa + x.AA#aa + x.AA#aa\ng(A, AA(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(k,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tterm:AA/aa\n//│ deforest > <<< fusing <<<\n//│ = 9\n\n\n// multi parameter list\n:expect 103\nfun inner(x)(y) =\n  let t = if x is\n    AA(a) then a + y\n    BB(b) then b - y\n  t * y\nfun outer1(x)(y, z) =\n  let t = if x is\n    AA(a) then inner(a)(y)\n    BB(b) then inner(b)(y)\n  t + z\nfun outer2(x, y)(z) =\n  let t = if x is\n    AA(a) then inner(a)(z)\n    BB(b) then inner(b)(y)\n  t + y\nlet p = AA(AA(3))\nouter1(p)(1, 2) + outer2(p, 3)(4) + inner(AA(5))(6)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(5)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 103\n//│ p = AA(AA(3))\n\n\n// `x.AA#aa` is used both as the scrutinee of the inner match\n// and as the base of a field selection (`x.AA#aa.AA#aa`),\n// giving it two consumer destinations, so the inner match is not fused\n:expect 3\nfun f(x) = if x is\n  AA then if x.AA#aa is\n    AA then x.AA#aa.AA#aa\nf(AA(AA(3)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n\n\n:expect 3\nfun id(x) = x\nfun f1(a1) = if a1 is AA then 1\nfun f2(a2) = if a2 is AA then 2\nf1(id(AA(1))) + f2(id(AA(2)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n\n\n:expect 0\nfun c1(x) = if x is\n  h :: t then\n    if t is\n      Nil then 0\nc1(1 :: Nil)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Lit(IntLit(1))), Arg(None,Ref(member:Nil,Some(object:Nil)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(h))\n//│ deforest > \tSelect(Ref(x,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(t,None)\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n:expect 0\nfun f(x) = if x is\n  AA then g1(x.AA#aa)\n  BB then g2(x.BB#bb)\nfun g1(y1) = if y1 is\n  AA then 0\nfun g2(y2) = if y2 is\n  AA then 1\nfun apply(f) =\n  let inner = AA(0)\n  f(AA(inner))\napply(f)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(inner,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(y1,None)\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n:expect 3\nfun p(x) = AA(x)\nfun wrap1(x) = p(x)\nfun wrap(x) = wrap1(x)\nfun f1(a1) = if a1 is AA then 1\nfun f2(a2) = if a2 is AA then 2\nf1(wrap(1)) + f2(wrap(2))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n:expect 0\nfun p1(x) = p2(x)\nfun p2(x) = if x == 0 then AA(x) else p1(x - 1)\nfun c(a) = if a is AA(x) then x\nc(p1(3))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n:expect [D, AA(1)]\nfun f(x) = if g(false) is\n  AA and\n    x < 1 then BB(0)\n    else f(x - 1)\n  C then D\nfun g(b) =\n  if b then\n    if f(0) is\n      BB then AA(0)\n      D then AA(1)\n  else\n    C\n[f(3), g(true)]\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:D,Some(object:D)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:C,Some(object:C)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:D,Some(object:D)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:BB,Some(term:BB/BB)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Ref(member:C,Some(object:C)) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(0)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > <<< fusing <<<\n//│ = [D, AA(1)]\n\n\n\n\n// `y` should not be considered as a free var for the branch\n:expect 4\nfun f(ls) = if ls is [] then\n  let y = 4\n  fun h(z) = if z > 0 then h(z - 1) else y\n  h(3)\nf([])\n//│ deforest > >>> fusing >>>\n//│ deforest > Tuple(false,List()) ->\n//│ deforest > \tRef(ls,None)\n//│ deforest > <<< fusing <<<\n//│ = 4\n\n\n:expect 0\nfun f(x, b) = if x is\n  Nil then if b then f(Nil, false) else 0\nf(Nil, false)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n:expect 4\nfun test() =\n  let p = AA(1)\n  let a = if p is\n    AA(x) then x\n  let b = if p is\n    AA(x) then x\n  a + b\ntest() + test()\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 4\n\n\n:expect 3\nfun p(d) = AA(3)\nfun c1(x) = if x is AA then 1\nfun c2(x) = if x is AA then 2\nc1(p(1)) + c2(p(2))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(3)))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 3\n\n\n:expect 15\nfun p(x) = AA(x)\nfun f1(a1) = if a1 is AA(aa) then aa\nfun f2(a2) = if a2 is AA(aa) then aa\nfun f3(a3) = if a3 is AA(aa) then aa\nfun f4(a4) = if a4 is AA(aa) then aa\nfun f5(a5) = if a5 is AA(aa) then aa\nf1(p(1)) + f2(p(2)) + f3(p(3)) + f4(p(4)) + f5(p(5))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a5,None)\n//│ deforest > \tSelect(Ref(a5,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a4,None)\n//│ deforest > \tSelect(Ref(a4,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a3,None)\n//│ deforest > \tSelect(Ref(a3,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > \tSelect(Ref(a1,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 15\n\n\n// calls to `to` should be able to be duplicated\n:expect 88\nfun to(n) =\n  if n > 0 then\n    let m = n - 1\n    n :: to(m)\n  else\n    Nil\nfun f1(ls1) = if ls1 is\n  h :: t then h + f1(t)\n  Nil then 2\nfun f2(ls2) = if ls2 is\n  h :: t then h + f2(t)\n  Nil then 3\nfun f3(ls3) = if ls3 is\n  h :: t then h + f3(t)\n  Nil then 4\nfun f4(ls4) = if ls4 is\n  h :: t then h + f4(t)\n  Nil then 5\nf1(to(4)) + f2(to(5)) + f3(to(6)) + f4(to(7))\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls4,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls4,None)\n//│ deforest > \tSelect(Ref(ls4,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls4,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls3,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls3,None)\n//│ deforest > \tSelect(Ref(ls3,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls3,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls2,None)\n//│ deforest > \tSelect(Ref(ls2,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls2,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls1,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(n,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls1,None)\n//│ deforest > \tSelect(Ref(ls1,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls1,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = 88\n\n\n\n\n:expect 8\nfun p(x) = AA(x)\nfun g1(b) = if b then p(1) else p(2)\nfun wrap(b) = g1(b)\nfun g2(b) = if b then p(3) else p(4)\nfun f1(p) = if p is AA(a) then a + 1\nfun f2(p) = if p is AA(b) then b + 2\nf1(wrap(true)) + f2(g2(false))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 8\n\n\n:expect 10\nfun p(x) = AA(x)\nlet one = p(1)\nlet two = p(2)\nfun f1(p) = if p is AA(a) then a + 1\nfun f2(p) = if p is AA(b) then b + 2\nfun f3(p) = if p is AA(c) then c + 3\nf1(one) + f2(one) + f3(two)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(p,None)\n//│ deforest > \tSelect(Ref(p,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 10\n//│ one = AA(1)\n//│ two = fun inlinedVal91\n\n\n:expect 4\nfun id(x) = x\nfun f1(a) = if a is AA(i) then i\nfun f2(a) = if a is AA(i) then i + 1\nf1(id(AA(1))) + f2(id(AA(2)))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(2)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(a,None)\n//│ deforest > \tSelect(Ref(a,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 4\n\n\n\n\n:expect 6\nfun p(x) = AA(x)\nfun f1(a1) = if a1 is AA(a) then a + 1\nfun f2(a2) = if a2 is AA(a) then a + 2\nfun wrap(a) = a\nf1(wrap(p(2))) + f2(p(1))\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a2,None)\n//│ deforest > \tSelect(Ref(a2,None),Ident(aa))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(x,None))))) ->\n//│ deforest > \tRef(a1,None)\n//│ deforest > \tSelect(Ref(a1,None),Ident(aa))\n//│ deforest > <<< fusing <<<\n//│ = 6\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/todos.mls",
    "content": ":js\n:deforest\n\nobject A\nobject B\nobject C\ndata class AA(x)\ndata class BB(x)\ndata class CC(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nobject Nil\ndata class Cons(h, t)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\nobject None\ndata class Some(x)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n\n// TODO: many dead code contain duplicated `t + 5 * 4 - 3 + 2 - 1`.\n// `t + 5 * 4 - 3 + 2 - 1` is the \"rest\" of a fusing match;\n// Deforestation makes programs early return at fusing matches,\n// and after deforestation, the \"rest\" of fusing matches would appear both\n// in \"rest function\"s and after the early return (and becomes dead code).\n// A dead code elimination pass that detects code after early return would solve this problem.\n:sir\n:expect 78\nfun test(x) =\n  let t = if x is\n    AA(AA(AA(a))) then a\n    else 4\n  t + 5 * 4 - 3 + 2 - 1\nfun f(a) = if a is\n  AA(AA) then 0\nlet p = AA(AA(AA(10)))\ntest(p) + f(p) + test(AA(AA(AA(10)))) + test(B)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:B,Some(object:B)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > \tSelect(Ref(x,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(10)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > Call(Ref(member:AA,Some(term:AA/AA)),List(List(Arg(None,Lit(IntLit(10)))))) ->\n//│ deforest > \tRef(tmp:arg$AA$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$AA$0$,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let test⁰, f⁰, p⁰, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, tmp10, test_31$test⁰, test_31$x_dflt⁰, test_31$x_rest⁰, test_28$test⁰, test_28$x_AA⁰, test_28$x_rest⁰, test_28$arg$AA$0$_AA⁰, test_28$arg$AA$0$_rest⁰, test_28$arg$AA$0$_AA¹, test_28$arg$AA$0$_rest¹, test_20$test⁰, test_20$arg$AA$0$_AA⁰, test_20$arg$AA$0$_rest⁰, test_20$arg$AA$0$_rest¹, test_20$x_rest⁰, AA_x, AA_x1, AA_x2, AA_x3, deforest$lam;\n//│ define test_31$test⁰ as fun test_31$test¹(x) {\n//│   let t, a, arg$AA$0$, arg$AA$0$1, arg$AA$0$2, tmp11, tmp12, tmp13, tmp14, tmp15;\n//│   return x(tmp11, t, tmp11, tmp12, tmp13, tmp14, tmp15)\n//│ };\n//│ define test_28$test⁰ as fun test_28$test¹(x) {\n//│   let t, a, arg$AA$0$, arg$AA$0$1, arg$AA$0$2, tmp11, tmp12, tmp13, tmp14, tmp15;\n//│   return x(t, a, arg$AA$0$, arg$AA$0$1, arg$AA$0$2, tmp11, tmp12, tmp13, tmp14, tmp15, t, tmp11, tmp12, tmp13, tmp14, tmp15)\n//│ };\n//│ define test_20$test⁰ as fun test_20$test¹(x) {\n//│   let t, a, arg$AA$0$, arg$AA$0$1, arg$AA$0$2, tmp11, tmp12, tmp13, tmp14, tmp15;\n//│   match x\n//│     AA⁰ =>\n//│       set arg$AA$0$ = x.x⁰;\n//│       match arg$AA$0$\n//│         AA⁰ =>\n//│           set arg$AA$0$1 = arg$AA$0$.x⁰;\n//│           return arg$AA$0$1(a, arg$AA$0$2, tmp11, t, tmp11, tmp12, tmp13, tmp14, tmp15)\n//│         else\n//│           set tmp11 = 4;\n//│           end\n//│       end\n//│     else\n//│       set tmp11 = 4;\n//│       end\n//│   set t = tmp11;\n//│   set tmp12 = *⁰(5, 4);\n//│   set tmp13 = +⁰(t, tmp12);\n//│   set tmp14 = -⁰(tmp13, 3);\n//│   set tmp15 = +⁰(tmp14, 2);\n//│   return -⁰(tmp15, 1)\n//│ };\n//│ define test_31$x_dflt⁰ as fun test_31$x_dflt¹(fv_tmp, fv_t, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_tmp5) {\n//│   set fv_tmp1 = 4;\n//│   return test_31$x_rest¹(fv_t, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_tmp5)\n//│ };\n//│ define test_28$x_AA⁰ as fun test_28$x_AA¹(fv_t, fv_a, fv_arg$AA$0$, fv_arg$AA$0$1, fv_arg$AA$0$2, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_t1, fv_tmp5, fv_tmp6, fv_tmp7, fv_tmp8, fv_tmp9, AA_x4) {\n//│   set fv_arg$AA$0$ = AA_x4;\n//│   return fv_arg$AA$0$(fv_t1, fv_a, fv_arg$AA$0$1, fv_arg$AA$0$2, fv_tmp5, fv_tmp6, fv_tmp7, fv_tmp8, fv_tmp9, fv_t1, fv_tmp5, fv_tmp6, fv_tmp7, fv_tmp8, fv_tmp9)\n//│ };\n//│ define test_28$arg$AA$0$_AA⁰ as fun test_28$arg$AA$0$_AA²(fv_t, fv_a, fv_arg$AA$0$, fv_arg$AA$0$1, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_t1, fv_tmp5, fv_tmp6, fv_tmp7, fv_tmp8, fv_tmp9, AA_x4) {\n//│   set fv_arg$AA$0$ = AA_x4;\n//│   return fv_arg$AA$0$(fv_a, fv_arg$AA$0$1, fv_tmp5, fv_t1, fv_tmp5, fv_tmp6, fv_tmp7, fv_tmp8, fv_tmp9)\n//│ };\n//│ define test_28$arg$AA$0$_AA¹ as fun test_28$arg$AA$0$_AA³(fv_a, fv_arg$AA$0$, fv_tmp, fv_t, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_tmp5, AA_x4) {\n//│   set fv_arg$AA$0$ = AA_x4;\n//│   set fv_a = fv_arg$AA$0$;\n//│   set fv_tmp1 = fv_a;\n//│   return test_28$arg$AA$0$_rest²(fv_t, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_tmp5)\n//│ };\n//│ define test_20$arg$AA$0$_AA⁰ as fun test_20$arg$AA$0$_AA¹(fv_a, fv_arg$AA$0$, fv_tmp, fv_t, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_tmp5, AA_x4) {\n//│   set fv_arg$AA$0$ = AA_x4;\n//│   set fv_a = fv_arg$AA$0$;\n//│   set fv_tmp1 = fv_a;\n//│   return test_20$arg$AA$0$_rest²(fv_t, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4, fv_tmp5)\n//│ };\n//│ define test_31$x_rest⁰ as fun test_31$x_rest¹(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4) {\n//│   set fv_t = fv_tmp;\n//│   set fv_tmp1 = *⁰(5, 4);\n//│   set fv_tmp2 = +⁰(fv_t, fv_tmp1);\n//│   set fv_tmp3 = -⁰(fv_tmp2, 3);\n//│   set fv_tmp4 = +⁰(fv_tmp3, 2);\n//│   return -⁰(fv_tmp4, 1)\n//│ };\n//│ define test_28$x_rest⁰ as fun test_28$x_rest¹(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4) {\n//│   set fv_t = fv_tmp;\n//│   set fv_tmp1 = *⁰(5, 4);\n//│   set fv_tmp2 = +⁰(fv_t, fv_tmp1);\n//│   set fv_tmp3 = -⁰(fv_tmp2, 3);\n//│   set fv_tmp4 = +⁰(fv_tmp3, 2);\n//│   return -⁰(fv_tmp4, 1)\n//│ };\n//│ define test_28$arg$AA$0$_rest⁰ as fun test_28$arg$AA$0$_rest³(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4) {\n//│   return test_28$x_rest¹(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4)\n//│ };\n//│ define test_28$arg$AA$0$_rest¹ as fun test_28$arg$AA$0$_rest²(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4) {\n//│   return test_28$arg$AA$0$_rest³(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4)\n//│ };\n//│ define test_20$arg$AA$0$_rest⁰ as fun test_20$arg$AA$0$_rest²(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4) {\n//│   return test_20$arg$AA$0$_rest³(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4)\n//│ };\n//│ define test_20$arg$AA$0$_rest¹ as fun test_20$arg$AA$0$_rest³(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4) {\n//│   return test_20$x_rest¹(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4)\n//│ };\n//│ define test_20$x_rest⁰ as fun test_20$x_rest¹(fv_t, fv_tmp, fv_tmp1, fv_tmp2, fv_tmp3, fv_tmp4) {\n//│   set fv_t = fv_tmp;\n//│   set fv_tmp1 = *⁰(5, 4);\n//│   set fv_tmp2 = +⁰(fv_t, fv_tmp1);\n//│   set fv_tmp3 = -⁰(fv_tmp2, 3);\n//│   set fv_tmp4 = +⁰(fv_tmp3, 2);\n//│   return -⁰(fv_tmp4, 1)\n//│ };\n//│ define test⁰ as fun test¹(x) {\n//│   let t, a, arg$AA$0$, arg$AA$0$1, arg$AA$0$2, tmp11, tmp12, tmp13, tmp14, tmp15;\n//│   match x\n//│     AA⁰ =>\n//│       set arg$AA$0$ = x.x⁰;\n//│       match arg$AA$0$\n//│         AA⁰ =>\n//│           set arg$AA$0$1 = arg$AA$0$.x⁰;\n//│           match arg$AA$0$1\n//│             AA⁰ =>\n//│               set arg$AA$0$2 = arg$AA$0$1.x⁰;\n//│               set a = arg$AA$0$2;\n//│               set tmp11 = a;\n//│               end\n//│             else\n//│               set tmp11 = 4;\n//│               end\n//│           end\n//│         else\n//│           set tmp11 = 4;\n//│           end\n//│       end\n//│     else\n//│       set tmp11 = 4;\n//│       end\n//│   set t = tmp11;\n//│   set tmp12 = *⁰(5, 4);\n//│   set tmp13 = +⁰(t, tmp12);\n//│   set tmp14 = -⁰(tmp13, 3);\n//│   set tmp15 = +⁰(tmp14, 2);\n//│   return -⁰(tmp15, 1)\n//│ };\n//│ define f⁰ as fun f¹(a) {\n//│   let arg$AA$0$;\n//│   block split_root$:\n//│     block split_default$:\n//│       match a\n//│         AA⁰ =>\n//│           set arg$AA$0$ = a.x⁰;\n//│           match arg$AA$0$\n//│             AA⁰ =>\n//│               return 0\n//│             else\n//│               break split_default$\n//│           end\n//│         else\n//│           break split_default$\n//│       end\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ set AA_x = 10;\n//│ set tmp = (fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_tmp, fv_ctorLam_t, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_tmp5) => {\n//│   return test_20$arg$AA$0$_AA¹(fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_tmp, fv_ctorLam_t, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_tmp5, AA_x)\n//│ };\n//│ set tmp1 = AA¹(tmp);\n//│ set p⁰ = AA¹(tmp1);\n//│ set tmp2 = test_20$test¹(p⁰);\n//│ set tmp3 = f¹(p⁰);\n//│ set tmp4 = +⁰(tmp2, tmp3);\n//│ set AA_x1 = 10;\n//│ set tmp5 = (fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_tmp, fv_ctorLam_t, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_tmp5) => {\n//│   return test_28$arg$AA$0$_AA³(fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_tmp, fv_ctorLam_t, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_tmp5, AA_x1)\n//│ };\n//│ set AA_x2 = tmp5;\n//│ set tmp6 = (fv_ctorLam_t, fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_arg$AA$0$1, fv_ctorLam_tmp, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_t1, fv_ctorLam_tmp5, fv_ctorLam_tmp6, fv_ctorLam_tmp7, fv_ctorLam_tmp8, fv_ctorLam_tmp9) => {\n//│   return test_28$arg$AA$0$_AA²(fv_ctorLam_t, fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_arg$AA$0$1, fv_ctorLam_tmp, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_t1, fv_ctorLam_tmp5, fv_ctorLam_tmp6, fv_ctorLam_tmp7, fv_ctorLam_tmp8, fv_ctorLam_tmp9, AA_x2)\n//│ };\n//│ set AA_x3 = tmp6;\n//│ set tmp7 = (fv_ctorLam_t, fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_arg$AA$0$1, fv_ctorLam_arg$AA$0$2, fv_ctorLam_tmp, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_t1, fv_ctorLam_tmp5, fv_ctorLam_tmp6, fv_ctorLam_tmp7, fv_ctorLam_tmp8, fv_ctorLam_tmp9) => {\n//│   return test_28$x_AA¹(fv_ctorLam_t, fv_ctorLam_a, fv_ctorLam_arg$AA$0$, fv_ctorLam_arg$AA$0$1, fv_ctorLam_arg$AA$0$2, fv_ctorLam_tmp, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_t1, fv_ctorLam_tmp5, fv_ctorLam_tmp6, fv_ctorLam_tmp7, fv_ctorLam_tmp8, fv_ctorLam_tmp9, AA_x3)\n//│ };\n//│ set tmp8 = test_28$test¹(tmp7);\n//│ set tmp9 = +⁰(tmp4, tmp8);\n//│ set deforest$lam = (fv_ctorLam_tmp, fv_ctorLam_t, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_tmp5) => {\n//│   return test_31$x_dflt¹(fv_ctorLam_tmp, fv_ctorLam_t, fv_ctorLam_tmp1, fv_ctorLam_tmp2, fv_ctorLam_tmp3, fv_ctorLam_tmp4, fv_ctorLam_tmp5)\n//│ };\n//│ set tmp10 = test_31$test¹(deforest$lam);\n//│ +⁰(tmp9, tmp10)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 78\n//│ p = AA(AA(fun tmp))\n\n\n// TODO: rewriting does not handle properly classes nested in functions yet\n:todo\n:expect Local(2)\ndata class Global(x)\nfun test() =\n  data class Local(x)\n  if Global(1) is\n    Global(x) then Local(x + 1)\ntest()\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Global,Some(term:Global/Global)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > Call(Ref(member:Global,Some(term:Global/Global)),List(List(Arg(None,Lit(IntLit(1)))))) ->\n//│ deforest > \tRef(tmp:scrut,None)\n//│ deforest > \tSelect(Ref(tmp:scrut,None),Ident(x))\n//│ deforest > <<< fusing <<<\n//│ /!!!\\ Uncaught error: java.lang.AssertionError: assertion failed\n\n\n// TODO: fusion opportunity is lost\n// because there are two consumers due to two call sites of `inner`s.\n:expect 0\nfun inner(x) = if x is A then 0 else 1\nfun test() =\n  let x = A\n  inner(x) + inner(x)\ntest()\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n//│ = 0\n\n\n// TODO: duplicated instantiations of the consumer `f`\n:expect 2\nfun f(x) = if x is A then 1\nf(A) + f(A)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > Ref(member:A,Some(object:A)) ->\n//│ deforest > \tRef(x,None)\n//│ deforest > <<< fusing <<<\n//│ = 2\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/deforest/zipunzip.mls",
    "content": ":js\n:deforest\n\n\n\nobject Nil\ndata class (::) Cons(h, t)\ndata class Pair(a, b)\n//│ deforest > >>> fusing >>>\n//│ deforest > <<< fusing <<<\n\n:expect Pair(Cons(1, Cons(2, Nil)), Cons(2, Cons(3, Nil)))\nfun zip(xs_zip, ys_zip) = if\n  xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt)\n  else Nil\nfun unzip(ls_unzip) = if ls_unzip is\n  Pair(a, b) :: t and unzip(t) is Pair(atail, btail) then Pair(a :: atail, b :: btail)\n  Nil then Pair(Nil, Nil)\nfun enumFromTo(a, b) = if a < b then a :: enumFromTo(a + 1, b) else Nil\nfun testUnzipZip(n) = unzip(zip(id(enumFromTo(1, n)), id(enumFromTo(2, n + 3))))\ntestUnzipZip(3)\n//│ deforest > >>> fusing >>>\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls_unzip,None)\n//│ deforest > \tSelect(Ref(ls_unzip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_unzip,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(y,None))))) ->\n//│ deforest > \tRef(tmp:arg$Cons$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(a))\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(b))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_unzip,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_unzip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ls_unzip,None)\n//│ deforest > \tSelect(Ref(ls_unzip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_unzip,None),Ident(t))\n//│ deforest > Call(Ref(member:Pair,Some(term:Pair/Pair)),List(List(Arg(None,Ref(x,None)), Arg(None,Ref(y,None))))) ->\n//│ deforest > \tRef(tmp:arg$Cons$0$,None)\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(a))\n//│ deforest > \tSelect(Ref(tmp:arg$Cons$0$,None),Ident(b))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_unzip,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_unzip,None)\n//│ deforest > <<< fusing <<<\n//│ = Pair(Cons(1, Cons(2, Nil)), Cons(2, Cons(3, Nil)))\n\n\n\n:expect Cons(Pair(3, 4), Cons(Pair(2, 3), Cons(Pair(1, 2), Nil)))\nfun zip(xs_zip, ys_zip) = if\n  xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt)\n  else Nil\nfun unzip(ls_unzip) = if ls_unzip is\n  Pair(a, b) :: t and unzip(t) is Pair(atail, btail) then Pair(a :: atail, b :: btail)\n  Nil then Pair(Nil, Nil)\nfun makeZippedList(n) = if n > 0 then Pair(n, n + 1) :: makeZippedList(n - 1) else Nil\nfun testZipUnzip(n) = if unzip(id(makeZippedList(n))) is\n  Pair(xs, ys) then zip(xs, ys)\ntestZipUnzip(3)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(atail,None))))) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(b,None)), Arg(None,Ref(btail,None))))) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(atail,None))))) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(b,None)), Arg(None,Ref(btail,None))))) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(t))\n//│ deforest > <<< fusing <<<\n//│ = Cons(Pair(3, 4), Cons(Pair(2, 3), Cons(Pair(1, 2), Nil)))\n\n\n\nfun zip(xs_zip, ys_zip) = if\n  xs_zip is x :: xt and ys_zip is y :: yt then Pair(x, y) :: zip(xt, yt)\n  else Nil\nfun unzip(ls_unzip) = if ls_unzip is\n  Pair(a, b) :: t and unzip(t) is Pair(atail, btail) then Pair(a :: atail, b :: btail)\n  Nil then Pair(Nil, Nil)\nfun map(f, ls_map) = if ls_map is\n  h :: t then f(h) :: map(f, t)\n  Nil then Nil\nfun makeZippedList(n) = if n > 0 then Cons(Pair(n, n + 1), makeZippedList(n - 1)) else Nil\nfun testZipMapBothUnzip(n) = if unzip(id(makeZippedList(n))) is\n  Pair(xs, ys) then zip(\n    map(x => x + 1, xs),\n    map(x => x * x, ys)\n  )\ntestZipMapBothUnzip(4)\n//│ deforest > >>> fusing >>>\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(atail,None))))) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(b,None)), Arg(None,Ref(btail,None))))) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(a,None)), Arg(None,Ref(atail,None))))) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(b,None)), Arg(None,Ref(btail,None))))) ->\n//│ deforest > \tRef(ls_map,None)\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(h))\n//│ deforest > \tSelect(Ref(ls_map,None),Ident(t))\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(xs_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(xs_zip,None)\n//│ deforest > Call(Ref(member:Cons,Some(term:Cons/Cons)),List(List(Arg(None,Ref(tmp:tmp,None)), Arg(None,Ref(tmp:tmp,None))))) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(h))\n//│ deforest > \tSelect(Ref(ys_zip,None),Ident(t))\n//│ deforest > Ref(member:Nil,Some(object:Nil)) ->\n//│ deforest > \tRef(ys_zip,None)\n//│ deforest > <<< fusing <<<\n//│ = Cons(\n//│   Pair(5, 25),\n//│   Cons(Pair(4, 16), Cons(Pair(3, 9), Cons(Pair(2, 4), Nil)))\n//│ )\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/flows/BadFlows.mls",
    "content": ":js\n:flow\n\n:global\n:sf\n\n\n:e\n:ge\nInt\n//│ ╔══[COMPILATION ERROR] Cannot use non-term member Int in term position\n//│ ║  l.10: \tInt\n//│ ╙──      \t^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   Int⁰{ ~> Int⁰ }\n//│ where\n//│     \n//│ ╔══[COMPILATION ERROR] Symbol 'Int' is virtual (i.e., \"compiler fiction\"); cannot be used as a term\n//│ ║  l.10: \tInt\n//│ ╙──      \t^^^\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nclass C\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   class C {\n//│     \n//│   }\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:e\nC\n//│ ╔══[COMPILATION ERROR] Cannot use non-term member C in term position\n//│ ║  l.35: \tC\n//│ ╙──      \t^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   C⁰{ ~> C⁰ }\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = class C\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/flows/BasicFlows.mls",
    "content": ":js\n:flow\n// :df\n// :todo\n// :d\n\n:global\n:sf\n\n\n2\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   2\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\nx => x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   (x⁰) => x⁰\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n2 + 2\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   +(2, 2)‹app⁰›\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 4\n\n\nclass Foo with\n  val m = 1\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   class Foo {\n//│     val m⁰ ‹flow:m⁰› = 1\n//│   }\n//│ where\n//│     flow:m⁰  <~  1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:e\nfun test(x) = x.m\n//│ ╔══[COMPILATION ERROR] Cannot resolve selection\n//│ ║  l.48: \tfun test(x) = x.m\n//│ ╙──      \t              ^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun test⁰(x¹) ‹flow:test⁰› = x¹.m‹?›\n//│ where\n//│     x¹  ~>  {m: ⋅m⁰}\n//│     flow:test⁰  <~  ((x¹) -> ⋅m⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// :de\n// :df\nfun test(x: Foo) = x.m\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun test¹(x²: Foo⁰{ ~> Foo⁰ }) ‹flow:test¹› = x².m‹?›{ ~> x².m⁰ }\n//│ where\n//│     x²  <~  type Foo\n//│     flow:test¹  <~  ((type Foo) -> flow:m⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet f = (x: Foo) => x.m\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let f⁰,\n//│   f⁰ = (x³: Foo⁰{ ~> Foo⁰ }) => x³.m‹?›{ ~> x³.m⁰ }\n//│ where\n//│     f⁰  <~  ((type Foo) -> flow:m⁰)\n//│     x³  <~  type Foo\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\n\nlet a = [1, 2, 3]\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let a⁰,\n//│   a⁰ = [\n//│     1,\n//│     2,\n//│     3\n//│   ]\n//│ where\n//│     a⁰  <~  [1, 2, 3 ]\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ a = [1, 2, 3]\n\nlet f = (x, y) => x + y\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let f¹,\n//│   f¹ = (x⁴, y⁰) => +(x⁴, y⁰)‹app¹›\n//│ where\n//│     f¹  <~  ((x⁴, y⁰) -> app¹)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun f\n\nf(1, 2)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f¹(1, 2)‹app²›\n//│ where\n//│     f¹  <~  ((x⁴, y⁰) -> app¹)\n//│     f¹  ~>  ((1, 2) -> app²)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n:fixme\nf(...a)\n//│ /!!!\\ Uncaught error: scala.MatchError: Spd(Eager,Ref(a)) (of class hkmc2.semantics.Spd)\n\n\nfun przd[A, B](x: A) = x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun przd⁰[A⁰, B⁰](x⁵: A⁰) ‹flow:przd⁰› = x⁵\n//│ where\n//│     x⁵  <~  type A\n//│     flow:przd⁰  <~  ((type A) -> x⁵)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/flows/Identity.mls",
    "content": ":flow\n\n:global\n:sf\n\n\nfun id(x) = x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun id⁰(x⁰) ‹flow:id⁰› = x⁰\n//│ where\n//│     flow:id⁰  <~  ((x⁰) -> x⁰)\n\nid(1)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   id⁰{ ~> id⁰ }(1)‹app⁰›\n//│ where\n//│     app⁰  <~  1\n\nid(true)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   id⁰{ ~> id⁰ }(true)‹app¹›\n//│ where\n//│     app¹  <~  1  true\n\n\nfun foo(x) = x + x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun foo⁰(x¹) ‹flow:foo⁰› = +(x¹, x¹)‹app²›\n//│ where\n//│     flow:foo⁰  <~  ((x¹) -> app²)\n\n\n\n\n\n(x, x) => x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   (x², x³) => x³\n//│ where\n//│     \n\n(x, y) => x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   (x⁴, y⁰) => x⁴\n//│ where\n//│     \n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/flows/LeadingDotAccesses.mls",
    "content": ":js\n:flow\n\nclass A with\n  fun b = new A\n  fun c = (x) => new A\nmodule A with\n  fun a = new A\nfun f(x : A) = x\n\n:sf\nf(.a)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰{ ~> f⁰ }(_?_.a{ ~> A⁰.a⁰ })‹app⁰›\n//│ where\n//│     app⁰  <~  type A\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = A\n\n:sf\nf(.a.b)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰{ ~> f⁰ }(A⁰.a⁰.b⁰)‹app¹›\n//│ where\n//│     app¹  <~  type A\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = A\n\n:sf\nlet z = .a\nf(z)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let z⁰,\n//│   z⁰ = _?_.a{ ~> A⁰.a⁰ },\n//│   f⁰{ ~> f⁰ }(z⁰)‹app²›\n//│ where\n//│     z⁰  <~  _?_.A⁰.a⁰\n//│     z⁰  ~>  type A\n//│     app²  <~  type A\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = A\n//│ z = A\n\n:sf\nlet z = .a.b.c(3)\nf(z).c(4).b\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let z¹,\n//│   z¹ = A⁰.a⁰.b⁰.c⁰(3)‹app³›,\n//│   f⁰(z¹)‹app⁴›.c⁰(4)‹app⁵›.b⁰\n//│ where\n//│     z¹  <~  _?_.A⁰.a⁰\n//│     z¹  ~>  type A\n//│     app³  <~  A\n//│     app³  ->  bind⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = A\n//│ z = A\n\n:sf\nf(.a.c(1).b.c(4))\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰{ ~> f⁰ }(A⁰.a⁰.c⁰(1)‹app⁶›.b⁰.c⁰(4)‹app⁷›)‹app⁸›\n//│ where\n//│     app⁸  <~  type A\n//│     app⁷  <~  A\n//│     app⁷  ->  bind¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = A\n\nclass C\nmodule C with\n  fun a = new C\n\n:sf\n:e\nfun g(x : C) = x\nlet d = .a\nf(d)\ng(d)\n//│ ╔══[COMPILATION ERROR] Ambiguous selection with multiple apparent targets:\n//│ ║  l.78: \tlet d = .a\n//│ ║        \t        ^^\n//│ ╟── companion member a\n//│ ║  l.73: \t  fun a = new C\n//│ ║        \t  ^^^^^^^^^^^^^\n//│ ╟── companion member a\n//│ ║  l.8: \t  fun a = new A\n//│ ╙──     \t  ^^^^^^^^^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun g⁰(x⁰: C⁰{ ~> C⁰ }) ‹flow:g⁰› = x⁰,\n//│   let d⁰,\n//│   d⁰ = _?_.a{ ~> ‹error› },\n//│   f⁰{ ~> f⁰ }(d⁰)‹app⁹›,\n//│   g⁰{ ~> g⁰ }(d⁰)‹app¹⁰›\n//│ where\n//│     x⁰  <~  type C\n//│     x⁰  ->  app¹⁰\n//│     d⁰  <~  _?_.‹error›\n//│     d⁰  ~>  type A  type C\n//│     app⁹  <~  type A\n//│     app¹⁰  <~  type C\n//│     flow:g⁰  <~  ((type C) -> x⁰)\n//│     flow:g⁰  ~>  ((d⁰) -> app¹⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ d = undefined\n\n:sf\nf(.a)\ng(.a)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰{ ~> f⁰ }(_?_.a{ ~> A⁰.a⁰ })‹app¹¹›,\n//│   g⁰{ ~> g⁰ }(_?_.a{ ~> C⁰.a¹ })‹app¹²›\n//│ where\n//│     app¹¹  <~  type A\n//│     app¹²  <~  type C\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = C\n\n:sf\n:re\n:e\nf(.w)\n//│ ╔══[COMPILATION ERROR] Cannot resolve leading dot selection\n//│ ║  l.124: \tf(.w)\n//│ ╙──       \t  ^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰{ ~> f⁰ }(_?_.w{ ~> ‹error› })‹app¹³›\n//│ where\n//│     app¹³  <~  type A\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:sf\n:e\n.b(new A)\n//│ ╔══[COMPILATION ERROR] Cannot resolve leading dot selection\n//│ ║  l.137: \t.b(new A)\n//│ ╙──       \t^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   _?_.b{ ~> ‹error› }(new A⁰)‹app¹⁴›\n//│ where\n//│     app¹⁴  ->  bind²\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/flows/SelExpansion.mls",
    "content": ":js\n:flow\n// :df\n\n:global\n:sf\n\n\nclass Foo with\n  val a = 123\nmodule Foo with\n  fun foo(x: Foo) = x.a\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   class Foo {\n//│     val a⁰ ‹flow:a⁰› = 123\n//│   },\n//│   module Foo {\n//│     fun foo⁰(x⁰: Foo⁰{ ~> Foo⁰ }) ‹flow:foo⁰› = x⁰.a‹?›{ ~> x⁰.a⁰ }\n//│   }\n//│ where\n//│     x⁰  <~  type Foo\n//│     flow:a⁰  <~  123\n//│     flow:foo⁰  <~  ((type Foo) -> flow:a⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet f = new Foo()\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let f⁰,\n//│   f⁰ = new Foo⁰()\n//│ where\n//│     f⁰  <~  Foo()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = Foo { a: 123 }\n\nf.a\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰.a⁰\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n:e\n:re\nf.a.b\n//│ ╔══[COMPILATION ERROR] Unresolved selection:\n//│ ║  l.45: \tf.a.b\n//│ ║        \t^^^^^\n//│ ╟── Type `123` does not contain member 'b'\n//│ ║  l.10: \t  val a = 123\n//│ ╙──      \t          ^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰.a⁰.b‹?›\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'b' yielded 'undefined'\n\n:sjs\nf.foo\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   f⁰.foo‹?›{ ~> Foo⁰.foo⁰(f⁰)‹app⁰› }\n//│ where\n//│     f⁰  <~  Foo()\n//│     f⁰  ~>  {a: ⋅a⁰}  {a: ⋅a¹}  {foo: ⋅foo⁰}\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ runtime.safeCall(Foo1.foo(f))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n\nfun id(x) = x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun id⁰(x¹) ‹flow:id⁰› = x¹\n//│ where\n//│     flow:id⁰  <~  ((x¹) -> x¹)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nid(f).foo\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   id⁰{ ~> id⁰ }(f⁰)‹app¹›.foo‹?›{ ~> Foo⁰.foo⁰(id⁰(f⁰)‹app¹›)‹app²› }\n//│ where\n//│     f⁰  <~  Foo()\n//│     f⁰  ~>  {a: ⋅a⁰}  {a: ⋅a¹}  {foo: ⋅foo⁰}\n//│     f⁰  ->  x¹\n//│     app¹  <~  Foo()\n//│     app¹  ~>  {foo: ⋅foo¹}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n\nlet id(x) = x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let id¹,\n//│   id¹ = (x²) => x²\n//│ where\n//│     id¹  <~  ((x²) -> x²)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ id = fun id\n\nid(f).foo\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   id¹(f⁰)‹app³›.foo‹?›{ ~> Foo⁰.foo⁰(id¹(f⁰)‹app³›)‹app⁴› }\n//│ where\n//│     f⁰  <~  Foo()\n//│     f⁰  ~>  {a: ⋅a⁰}  {a: ⋅a¹}  {foo: ⋅foo⁰}\n//│     f⁰  ->  x¹  x²\n//│     id¹  <~  ((x²) -> x²)\n//│     id¹  ~>  ((f⁰) -> app³)\n//│     app³  <~  Foo()\n//│     app³  ~>  {foo: ⋅foo²}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n\nfun id(x) = x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun id²(x³) ‹flow:id¹› = x³\n//│ where\n//│     flow:id¹  <~  ((x³) -> x³)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nid(0)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   id²{ ~> id² }(0)‹app⁵›\n//│ where\n//│     app⁵  <~  0\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n// * Note the flow confusion due to lack of polymorphism:\n:e\nid(f).foo\n//│ ╔══[COMPILATION ERROR] Unresolved selection:\n//│ ║  l.133: \tid(f).foo\n//│ ║         \t^^^^^^^^^\n//│ ╟── Type `0` does not contain member 'foo'\n//│ ║  l.123: \tid(0)\n//│ ╙──       \t   ^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   id²{ ~> id² }(f⁰)‹app⁶›.foo‹?›{ ~> Foo⁰.foo⁰(id²(f⁰)‹app⁶›)‹app⁷› }\n//│ where\n//│     f⁰  <~  Foo()\n//│     f⁰  ~>  {a: ⋅a⁰}  {a: ⋅a¹}  {foo: ⋅foo⁰}\n//│     f⁰  ->  x¹  x²  x³\n//│     app⁶  <~  0  Foo()\n//│     app⁶  ~>  {foo: ⋅foo³}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n\n:e\nfun test(g) = g.foo\n//│ ╔══[COMPILATION ERROR] Cannot resolve selection\n//│ ║  l.153: \tfun test(g) = g.foo\n//│ ╙──       \t              ^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun test⁰(g⁰) ‹flow:test⁰› = g⁰.foo‹?›\n//│ where\n//│     g⁰  ~>  {foo: ⋅foo⁴}\n//│     flow:test⁰  <~  ((g⁰) -> ⋅foo⁴)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:re\ntest(f)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   test⁰{ ~> test⁰ }(f⁰)‹app⁸›\n//│ where\n//│     f⁰  <~  Foo()\n//│     f⁰  ~>  {a: ⋅a⁰}  {a: ⋅a¹}  {foo: ⋅foo⁰}\n//│     f⁰  ->  x¹  x²  x³  g⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'foo' yielded 'undefined'\n\n\nfun test(g) = g.foo\ntest(f)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   fun test¹(g¹) ‹flow:test¹› = g¹.foo‹?›{ ~> Foo⁰.foo⁰(g¹)‹app⁹› },\n//│   test¹{ ~> test¹ }(f⁰)‹app¹⁰›\n//│ where\n//│     f⁰  <~  Foo()\n//│     f⁰  ~>  {a: ⋅a⁰}  {a: ⋅a¹}  {foo: ⋅foo⁰}\n//│     f⁰  ->  x¹  x²  x³  g⁰  g¹\n//│     g¹  <~  Foo()\n//│     g¹  ~>  {foo: ⋅foo⁵}\n//│     flow:test¹  <~  ((g¹) -> ⋅foo⁵)\n//│     flow:test¹  ~>  ((f⁰) -> app¹⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\nmodule AA with\n  module BB with\n    class CC with\n      val x: Int = 1\n    module CC with\n      fun getX(self: CC) = self.x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   module AA {\n//│     module BB {\n//│       class CC {\n//│         val x⁴: Int⁰{ ~> Int⁰ } ‹flow:x⁰› = 1\n//│       },\n//│       module CC {\n//│         fun getX⁰(self⁰: ⟨BB⁰.⟩CC⁰) ‹flow:getX⁰› = self⁰.x‹?›{ ~> self⁰.x⁴ }\n//│       }\n//│     }\n//│   }\n//│ where\n//│     self⁰  <~  type CC\n//│     flow:x⁰  <~  1\n//│     flow:getX⁰  <~  ((type CC) -> flow:x⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nnew AA.BB.CC().x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   new AA⁰.BB¹.CC⁰().x‹?›{ ~> new AA⁰.BB¹.CC⁰().x⁴ }\n//│ where\n//│     \n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp3; tmp3 = globalThis.Object.freeze(new AA1.BB.CC()); tmp3.x\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:sjs\nnew AA.BB.CC().getX\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   new AA⁰.BB¹.CC⁰().getX‹?›{ ~> AA⁰.BB¹.CC⁰.getX⁰(new AA⁰.BB¹.CC⁰())‹app¹¹› }\n//│ where\n//│     \n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp4; tmp4 = globalThis.Object.freeze(new AA1.BB.CC()); runtime.safeCall(AA1.BB.CC.getX(tmp4))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\nlet foo =\n  class A\n  module A with\n    fun test(a) = 1\n  new A\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let foo¹,\n//│   foo¹ = {\n//│     class A {\n//│       \n//│     },\n//│     module A {\n//│       fun test²(a¹) ‹flow:test²› = 1\n//│     },\n//│     new A⁰\n//│   }\n//│ where\n//│     foo¹  <~  A\n//│     flow:test²  <~  ((a¹) -> 1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = A\n\n:e\n:re\nfoo.test\n//│ ╔══[COMPILATION ERROR] Cannot access companion A from the context of this selection\n//│ ║  l.262: \tfoo.test\n//│ ╙──       \t^^^^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   foo¹.test‹?›\n//│ where\n//│     foo¹  <~  A\n//│     foo¹  ~>  {test: ⋅test⁰}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'test' yielded 'undefined'\n\n\nlet foo =\n  class A\n  module A with\n    fun test(a) = new A\n  (new A).test\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let foo²,\n//│   foo² = {\n//│     class A {\n//│       \n//│     },\n//│     module A {\n//│       fun test³(a²) ‹flow:test³› = new A¹\n//│     },\n//│     new A¹.test‹?›{ ~> A¹.test³(new A¹)‹app¹²› }\n//│   }\n//│ where\n//│     foo²  <~  A\n//│     a²  <~  A\n//│     flow:test³  <~  ((a²) -> A)\n//│     flow:test³  ~>  ((A) -> ⋅test¹)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ foo = A\n\n:e\n:re\nfoo.test\n//│ ╔══[COMPILATION ERROR] Cannot access companion A from the context of this selection\n//│ ║  l.301: \tfoo.test\n//│ ╙──       \t^^^^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   foo².test‹?›\n//│ where\n//│     foo²  <~  A\n//│     foo²  ~>  {test: ⋅test²}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'test' yielded 'undefined'\n\n\nclass CC(val x: Int)\nmodule CC with\n  fun getX(self: CC) = self.x\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   class CC(valx⁵: Int⁰{ ~> Int⁰ }) {\n//│     val x⁶ ‹flow:x¹› = x⁵\n//│   },\n//│   module CC {\n//│     fun getX¹(self¹: CC¹{ ~> CC¹ }) ‹flow:getX¹› = self¹.x‹?›{ ~> self¹.x⁶ }\n//│   }\n//│ where\n//│     x⁵  <~  type Int\n//│     x⁵  ->  flow:x¹\n//│     self¹  <~  type CC\n//│     flow:x¹  <~  type Int\n//│     flow:getX¹  <~  ((type CC) -> flow:x¹)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:fixme // TODO: handle lifted class defs: the JS is missing the `.class` access to get the static member `CC2.class.getX`\nCC(123).getX\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   CC¹(123)‹app¹³›.getX‹?›{ ~> CC¹.getX¹(CC¹(123)‹app¹³›)‹app¹⁴› }\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: CC2.getX is not a function\n\n\n:breakme // TODO: warn when this happens (accidental infinite recursion)\nclass CC\nmodule CC with\n  fun oops(x: CC) = x.oops\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   class CC {\n//│     \n//│   },\n//│   module CC {\n//│     fun oops⁰(x⁷: CC²{ ~> CC² }) ‹flow:oops⁰› = x⁷.oops‹?›{ ~> CC².oops⁰(x⁷)‹app¹⁵› }\n//│   }\n//│ where\n//│     x⁷  <~  type CC\n//│     x⁷  ~>  {oops: ⋅oops⁰}\n//│     flow:oops⁰  <~  ((type CC) -> ⋅oops⁰)\n//│     flow:oops⁰  ~>  ((CC) -> ⋅oops⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:re\nnew CC().oops\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   new CC²().oops‹?›{ ~> CC².oops⁰(new CC²())‹app¹⁶› }\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\nclass CC with\n  val okay = 123\nmodule CC with\n  fun okay(x: CC) = x.okay\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   class CC {\n//│     val okay⁰ ‹flow:okay⁰› = 123\n//│   },\n//│   module CC {\n//│     fun okay¹(x⁸: CC³{ ~> CC³ }) ‹flow:okay¹› = x⁸.okay‹?›{ ~> x⁸.okay⁰ }\n//│   }\n//│ where\n//│     x⁸  <~  type CC\n//│     flow:okay⁰  <~  123\n//│     flow:okay¹  <~  ((type CC) -> flow:okay⁰)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nnew CC().okay\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   new CC³().okay‹?›{ ~> new CC³().okay⁰ }\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n\nmodule Example with\n  class Test(val field: Int)\n  module Test with\n    fun next(self: Test) = Test(self.field + 1)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   module Example {\n//│     class Test(valfield⁰: Int⁰{ ~> Int⁰ }) {\n//│       val field¹ ‹flow:field⁰› = field⁰\n//│     },\n//│     module Test {\n//│       fun next⁰(self²: ⟨Example⁰.⟩Test⁰) ‹flow:next⁰› = ⟨Example⁰.⟩Test⁰(+(self².field¹, 1)‹app¹⁷›)‹app¹⁸›\n//│     }\n//│   }\n//│ where\n//│     field⁰  <~  type Int\n//│     field⁰  ->  flow:field⁰\n//│     self²  <~  type Test\n//│     flow:field⁰  <~  type Int\n//│     flow:next⁰  <~  ((type Test) -> app¹⁸)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet e = new Example.Test(123)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let e⁰,\n//│   e⁰ = new Example¹.Test⁰(123)\n//│ where\n//│     e⁰  <~  Test(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ e = Test(123)\n\n:fixme // Same as test case above (missing `.class` access)\ne.next\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   e⁰.next‹?›{ ~> Example¹.Test⁰.next⁰(e⁰)‹app¹⁹› }\n//│ where\n//│     e⁰  <~  Test(123)\n//│     e⁰  ~>  {next: ⋅next⁰}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: selRes7.next is not a function\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/flows/SelExpansionImport.mls",
    "content": ":js\n:flow\n// :df\n\n:global\n:sf\n\n\nimport \"../../mlscript-compile/Example.mls\"\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   import \".../Example.mjs\" as Example⁰\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nlet e = new Example.Test(123)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let e⁰,\n//│   e⁰ = new Example⁰.Test⁰(123)\n//│ where\n//│     e⁰  <~  Test(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ e = Test(123)\n\ne.field\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   e⁰.field⁰\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n// TODO: support\n:e\n:re\ne.next\n//│ ╔══[COMPILATION ERROR] Cannot access companion Test from the context of this selection\n//│ ║  l.37: \te.next\n//│ ╙──      \t^^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   e⁰.next‹?›\n//│ where\n//│     e⁰  <~  Test(123)\n//│     e⁰  ~>  {field: ⋅field⁰}  {next: ⋅next⁰}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'next' yielded 'undefined'\n\n\nopen Example\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   \n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet e = new Test(123)\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let e¹,\n//│   e¹ = new ⟨Example⁰.⟩Test⁰(123)\n//│ where\n//│     e¹  <~  Test(123)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ e = Test(123)\n\n// TODO: support\n:e\n:re\ne.next\n//│ ╔══[COMPILATION ERROR] Cannot access companion Test from the context of this selection\n//│ ║  l.69: \te.next\n//│ ╙──      \t^^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   e¹.next‹?›\n//│ where\n//│     e¹  <~  Test(123)\n//│     e¹  ~>  {next: ⋅next¹}\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'next' yielded 'undefined'\n\n\n\n// * TODO: better error!\n:e\nlet e = Example.Test(123)\n//│ ╔══[COMPILATION ERROR] Cannot use non-term member Example in term position\n//│ ║  l.85: \tlet e = Example.Test(123)\n//│ ╙──      \t        ^^^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let e²,\n//│   e² = Example⁰.Test⁰(123)‹app⁰›\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ e = Test(123)\n\n// * TODO: better error! (with location)\n:e\nlet e = Test(123)\n//│ ═══[COMPILATION ERROR] Cannot use non-term member Example in term position\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   let e³,\n//│   e³ = ⟨Example⁰.⟩Test⁰(123)‹app¹›\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ e = Test(123)\n\n\n:fixme // FIXME: error is probably due to some `bms.asTrm` weirdness (guess: due to lightweight elab?)\nExample.t\n//│ ╔══[COMPILATION ERROR] Cannot use non-term member Example in term position\n//│ ║  l.111: \tExample.t\n//│ ╙──       \t^^^^^^^\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   Example⁰{ ~> Example⁰ }.t⁰{ ~> Example⁰.t⁰ }\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Test(123)\n\n// * Note that here, it's important that we don't get the flow symbol attached to BlockMemberSymbol `t`\n// * (which should be internal to Example.mls, otherwise we'd mutate it nondeterministically across different imports),\n// * but rather some inferred Type view of it, which we can then use to resolve the selection.\n:fixme // TODO: should get an inferred Type view of the field\nExample.t.field\n//│ ╔══[COMPILATION ERROR] Cannot use non-term member Example in term position\n//│ ║  l.126: \tExample.t.field\n//│ ╙──       \t^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unresolved selection:\n//│ ║  l.126: \tExample.t.field\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╙── Type `type ⊤` does not contain member 'field'\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   Example⁰{ ~> Example⁰ }.t⁰{ ~> Example⁰.t⁰ }.field‹?›\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n:fixme // Same\nExample.t.next\n//│ ╔══[COMPILATION ERROR] Cannot use non-term member Example in term position\n//│ ║  l.142: \tExample.t.next\n//│ ╙──       \t^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unresolved selection:\n//│ ║  l.142: \tExample.t.next\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╙── Type `type ⊤` does not contain member 'next'\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   Example⁰{ ~> Example⁰ }.t⁰{ ~> Example⁰.t⁰ }.next‹?›\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'next' yielded 'undefined'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/flows/TypeFlows.mls",
    "content": ":js\n:flow\n\n:global\n:sf\n\n\nclass Foo[A]\n//│ —————————————————| Flowed |—————————————————————————————————————————————————————————————————————————\n//│   class Foo[A⁰] {\n//│     \n//│   }\n//│ where\n//│     \n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:fixme\nfun f(x: Foo[Int]) = x.foo\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: List(Ref(class:Int,List())) (of class $colon$colon)\n\n:fixme\nfun f[A](x: Foo[A]) = x.foo\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: List(Ref(A,List())) (of class $colon$colon)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/BadHandlers.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\n:re\nhandle h = Object with {}\nh.oops\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'oops' yielded 'undefined'\n\nhandle h = Object with {}\nval x = 1\n\nhandle h = Object with {}\nval x = 1\nx + 1\n//│ = 2\n\n:e\nx\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.20: \tx\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n// Getter\n// :expect 3\n:e\nhandle h = Object with\n  fun lol(k) = k(())\nh.lol\n//│ ╔══[COMPILATION ERROR] Handler function cannot be a getter\n//│ ║  l.31: \t  fun lol(k) = k(())\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Effect Handler$h$6 is raised in a getter\n  fun lol(k) = k(1)\nh.lol + 2\n//│ ╔══[COMPILATION ERROR] Name not found: h\n//│ ║  l.38: \th.lol + 2\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:re\nhandle h = Object with\n  fun lol()(k) = k(1)\nclass A with\n  fun f =\n    h.lol()\nnew A().f + 2\n//│ ═══[RUNTIME ERROR] Error: Effect Handler$h$8 is raised in a getter\n\nhandle h = Object with\n  fun lol()(k) = k(42)\nh.lol()\nval x = 1\n\nobject Foo with\n  handle h = Object with\n    fun lol()(k) = k(42)\n  val x = h.lol()\n  x + 1\n\n:e\n:re\nFoo.x\n//│ ╔══[COMPILATION ERROR] Object 'Foo' does not contain member 'x'\n//│ ║  l.66: \tFoo.x\n//│ ╙──      \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/Debugging.mls",
    "content": ":js\n:effectHandlers debug\n:lift\n\n\n\n:re\nraiseUnhandledEffect()\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect FatalEffect\n//│ \tat tail position\n\n:sjs\nfun f() =\n  let i = 0\n  let j = 100\n  let k = 2000\n  if i == 0 do\n    print of raiseUnhandledEffect()\n  j / i\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f, f$debugInfo;\n//│ runtime.resetEffects();\n//│ f$debugInfo = globalThis.Object.freeze([\n//│   \"f\",\n//│   0,\n//│   \"i\",\n//│   1,\n//│   \"j\",\n//│   2,\n//│   \"k\"\n//│ ]);\n//│ f = function f() {\n//│   let i, j, k, scrut, tmp1, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     let saveOffset;\n//│     pc = runtime.resumePc;\n//│     saveOffset = runtime.resumeIdx;\n//│     i = runtime.resumeArr.at(saveOffset);\n//│     saveOffset = saveOffset + 1;\n//│     j = runtime.resumeArr.at(saveOffset);\n//│     saveOffset = saveOffset + 1;\n//│     k = runtime.resumeArr.at(saveOffset);\n//│     saveOffset = saveOffset + 1;\n//│     scrut = runtime.resumeArr.at(saveOffset);\n//│     saveOffset = saveOffset + 1;\n//│     tmp1 = runtime.resumeArr.at(saveOffset);\n//│     runtime.resumePc = -1;\n//│   }\n//│   main: while (true) {\n//│     switch (pc) {\n//│       case 0:\n//│         i = 0;\n//│         j = 100;\n//│         k = 2000;\n//│         runtime.resumeValue = Predef.equals(i, 0);\n//│         if (runtime.curEffect === null) {\n//│           pc = 5;\n//│         } else {\n//│           return runtime.unwind(f, 5, \"Debugging.mls:17:6\", f$debugInfo, null, 1, 0, 5, i, j, k, scrut, tmp1)\n//│         }\n//│       case 5:\n//│         scrut = runtime.resumeValue;\n//│         if (scrut === true) {\n//│           runtime.resumeValue = Predef.raiseUnhandledEffect();\n//│           if (runtime.curEffect === null) {\n//│             pc = 4;\n//│             continue main\n//│           }\n//│           return runtime.unwind(f, 4, \"Debugging.mls:18:14\", f$debugInfo, null, 1, 0, 5, i, j, k, scrut, tmp1);\n//│         }\n//│         pc = 1;\n//│         continue main;\n//│       case 4:\n//│         tmp1 = runtime.resumeValue;\n//│         pc = 3;\n//│       case 3:\n//│         runtime.resumeValue = Predef.print(tmp1);\n//│         if (runtime.curEffect === null) {\n//│           pc = 2;\n//│         } else {\n//│           return runtime.unwind(f, 2, \"Debugging.mls:18:5\", f$debugInfo, null, 1, 0, 5, i, j, k, scrut, tmp1)\n//│         }\n//│       case 2:\n//│         runtime.resumeValue;\n//│         pc = 1;\n//│       case 1:\n//│         return j / i;\n//│     }\n//│     break;\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:re\nf()\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect FatalEffect\n//│ \tat f (Debugging.mls:18:14)\n\n:re\nfun lambda_test(f) =\n  f()\n  200\nlambda_test(() =>\n  raiseUnhandledEffect()\n  100)\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect FatalEffect\n//│ \tat lambda (Debugging.mls:106:3)\n//│ \tat lambda_test (Debugging.mls:103:3)\n\n\nimport \"../../mlscript-compile/Runtime.mls\"\n\n:silent\nlet res = Runtime.try(f)\n\nres.reified.contTrace.next.getLocals\n//│ = [LocalVarInfo(\"i\", 0), LocalVarInfo(\"j\", 100), LocalVarInfo(\"k\", 2000)]\n\nRuntime.debugEff(res.reified)\n//│ > Debug EffectSig:\n//│ > handler:  FatalEffect\n//│ > handlerFun:  null\n//│ > resumed:  false\n//│ > <lastHandler is self>\n//│ > FunctionContFrame(pc=4, last) -> (null)\n//│ > \n\n:expect Infinity\nres.resumeWith(42)\n//│ > 42\n//│ = Infinity\n\n\n\nclass Debugger() with\n  fun break(payload)\n\nmodule Test with\n  fun test(j)(using dbg: Debugger) =\n    let i = 0\n    let k = 2000\n    if i == 0 do\n      set i = dbg.break(\"whoops\")\n    j / i\n  fun main()(using Debugger) =\n    test(12) + test(34)\n\nlet res =\n  handle h = Debugger with\n    fun break(payload)(resume) = resume\n  using Debugger = h\n  Runtime.try(() => Test.main())\n//│ res = EffectHandle(_)\n\n:re\nres.raise()\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$\n//│ \tat Test.test (Debugging.mls:145:15)\n//│ \tat Test.main (Debugging.mls:148:5)\n\nset res = res.resumeWith(42)\n\n:re\nres.raise()\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$\n//│ \tat Test.test (Debugging.mls:145:15)\n//│ \tat Test.main (Debugging.mls:148:16)\n\n:expect 0.33676533676533676\nres.resumeWith(666)\n//│ = 0.33676533676533676\n\nlet i = 100\nfun f() =\n  // Currently debug.getLocals is not supported.\n  // print(debug.getLocals())\n  let j = 200\n  debug.printStack(true)\n  set j = 300\n  debug.printStack(false)\n  debug.printStack(true)\n  // print(debug.getLocals())\n//│ i = 100\n\nf()\n//│ > Stack Trace:\n//│ > \tat f (Debugging.mls:180:3) with locals: j=200\n//│ > Stack Trace:\n//│ > \tat f (Debugging.mls:182:3)\n//│ > Stack Trace:\n//│ > \tat tail position\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/EffectInHandler.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nclass PrintEffect with\n  fun p(s: String): ()\n  fun aux(s: String): ()\n\n:e\n// :sjs\nhandle h = PrintEffect with\n  fun p(x)(k) =\n    print(x)\n    k(())\n  fun aux(x)(k) =\n    h.p(x)\n    k(())\n    h.p(x)\nh.aux(3)\n//│ ╔══[COMPILATION ERROR] Name not found: h\n//│ ║  l.16: \t    h.p(x)\n//│ ╙──      \t    ^\n//│ ╔══[COMPILATION ERROR] Name not found: h\n//│ ║  l.18: \t    h.p(x)\n//│ ╙──      \t    ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nhandle h1 = PrintEffect with\n  fun p(x)(k) =\n    print(x)\n    k(())\n  fun aux(x)(k) = k(())\nhandle h2 = PrintEffect with\n  fun p(x)(k) =\n    print(x)\n    k(())\n  fun aux(x)(k) =\n    h1.p(x)\n    k(())\n    h1.p(x)\nh1.p(4)\nh2.aux(3)\nh1.p(4)\n//│ > 4\n//│ > 3\n//│ > 4\n//│ > 3\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/Effects.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class Effect with\n  fun perform(arg: Str): Str\n\n\nhandle h = Effect with\n  fun perform()(k) = \"b\"\n\n:expect 42\nhandle h = Effect with\n  fun perform()(k) = k(42)\nh.perform()\n//│ = 42\n\n:expect \"b\"\nhandle h = Effect with\n  fun perform(arg)(k) = \"b\"\nh.perform(\"k\")\n//│ = \"b\"\n\n:expect \"k\"\nhandle h = Effect with\n  fun perform(arg)(k) = arg\nh.perform(\"k\")\n//│ = \"k\"\n\n:expect \"k\"\nhandle h = Effect with\n  fun perform(arg)(k) = k(arg)\nh.perform(\"k\")\n//│ = \"k\"\n\n:expect \"hi\"\nfun foo(e) = e.perform(\"hi\")\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(arg)\n    k(arg)\nfoo(h)\n//│ > hi\n//│ = \"hi\"\n\nfun foo(e) = e.perform(\"hi\")\n\n:expect \"Hello World!\"\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(arg)\n    k(arg)\n(() => h.perform(\"Hello\") + \" World!\")()\n//│ > Hello\n//│ = \"Hello World!\"\n\n:expect \"54321\"\n:sjs\nlet result = \"\"\nhandle h = Effect with\n  fun perform(arg)(k) =\n    let v = k(arg)\n    result = result + arg\n    v\nin\n  h.perform(\"1\")\n  h.perform(\"2\")\n  h.perform(\"3\")\n  h.perform(\"4\")\n  h.perform(\"5\")\nresult\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let result, h7, handleBlock$7, Handler$h$perform7, Handler$h$15, Handler$h$perform$4;\n//│ runtime.resetEffects();\n//│ Handler$h$perform$4 = function Handler$h$perform$(arg) {\n//│   return (k) => {\n//│     return Handler$h$perform7(arg, k)\n//│   }\n//│ };\n//│ Handler$h$perform7 = function Handler$h$perform(arg, k) {\n//│   let v, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   switch (pc) {\n//│     case 0:\n//│       runtime.resumeValue = runtime.safeCall(k(arg));\n//│       if (runtime.curEffect === null) {\n//│         pc = 1;\n//│       } else {\n//│         return runtime.unwind(Handler$h$perform7, 1, \"Effects.mls:63:13\", null, null, 1, 2, arg, k, 0)\n//│       }\n//│     case 1:\n//│       v = runtime.resumeValue;\n//│       result = result + arg;\n//│       return v;\n//│   }\n//│ };\n//│ result = \"\";\n//│ (class Handler$h$14 extends Effect1 {\n//│   static {\n//│     Handler$h$15 = this\n//│   }\n//│   constructor() {\n//│     let tmp7;\n//│     tmp7 = super();\n//│     if (runtime.curEffect === null) {\n//│       tmp7\n//│     } else {\n//│       tmp7 = runtime.illegalEffect(\"in a constructor\");\n//│       tmp7\n//│     }\n//│   }\n//│   perform(arg) {\n//│     let Handler$h$perform$here;\n//│     Handler$h$perform$here = Handler$h$perform$4(arg);\n//│     return runtime.mkEffect(this, Handler$h$perform$here)\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Handler$h$\"]; \n//│ });\n//│ h7 = new Handler$h$15();\n//│ handleBlock$7 = (undefined, function () {\n//│   let pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   switch (pc) {\n//│     case 0:\n//│       runtime.resumeValue = runtime.safeCall(h7.perform(\"1\"));\n//│       if (runtime.curEffect === null) {\n//│         pc = 4;\n//│       } else {\n//│         return runtime.unwind(handleBlock$7, 4, \"Effects.mls:67:3\", null, null, 1, 0, 0)\n//│       }\n//│     case 4:\n//│       runtime.resumeValue;\n//│       runtime.resumeValue = runtime.safeCall(h7.perform(\"2\"));\n//│       if (runtime.curEffect === null) {\n//│         pc = 3;\n//│       } else {\n//│         return runtime.unwind(handleBlock$7, 3, \"Effects.mls:68:3\", null, null, 1, 0, 0)\n//│       }\n//│     case 3:\n//│       runtime.resumeValue;\n//│       runtime.resumeValue = runtime.safeCall(h7.perform(\"3\"));\n//│       if (runtime.curEffect === null) {\n//│         pc = 2;\n//│       } else {\n//│         return runtime.unwind(handleBlock$7, 2, \"Effects.mls:69:3\", null, null, 1, 0, 0)\n//│       }\n//│     case 2:\n//│       runtime.resumeValue;\n//│       runtime.resumeValue = runtime.safeCall(h7.perform(\"4\"));\n//│       if (runtime.curEffect === null) {\n//│         pc = 1;\n//│       } else {\n//│         return runtime.unwind(handleBlock$7, 1, \"Effects.mls:70:3\", null, null, 1, 0, 0)\n//│       }\n//│     case 1:\n//│       runtime.resumeValue;\n//│       return runtime.safeCall(h7.perform(\"5\"));\n//│   }\n//│ });\n//│ runtime.enterHandleBlock(h7, handleBlock$7);\n//│ if (runtime.curEffect === null) { result } else { runtime.topLevelEffect(false); result }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"54321\"\n//│ result = \"54321\"\n\n:expect \"b\"\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(arg)\n    \"b\"\nh.perform(\"t\")\n//│ > t\n//│ = \"b\"\n\n:expect 3\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(arg)\n    let r = k(true)\n    print(arg)\n    r\nif false || h.perform(\"hello\") then\n  3\nelse\n  0\n//│ > hello\n//│ > hello\n//│ = 3\n\n:expect \"Hello World!\"\nfun foo(h) =\n  print(\"Entering foo\")\n  let result = h.perform(\"Hello\")\n  h.perform(\"?\")\n  print(\"Exiting foo\")\n  result\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(\"handler called\")\n    let result = k(arg)\n    print(\"handler finished\")\n    result\nprint(\"mainbody start\")\nlet result = foo(h) + \" World!\"\nprint(\"mainbody end\")\nresult\n//│ > mainbody start\n//│ > Entering foo\n//│ > handler called\n//│ > handler called\n//│ > Exiting foo\n//│ > mainbody end\n//│ > handler finished\n//│ > handler finished\n//│ = \"Hello World!\"\n\n:expect \"Hello World!\"\nfun foo(h) =\n  print(\"Entering foo\")\n  let result = h.perform(\"Hello\")\n  h.perform(\"Oops!\")\n  print(\"Exiting foo\")\n  result\nfun bar(h) =\n  print(\"Entering bar\")\n  let result = foo(h) + \" World\"\n  print(\"Exiting bar\")\n  result\nfun foobar(h) =\n  print(\"Entering foobar\")\n  let result = bar(h) + \"!\"\n  print(\"Exiting foobar\")\n  result\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(\"handler called\")\n    let result = k(arg)\n    print(\"handler finished\")\n    result\nprint(\"mainbody start\")\nlet result = foobar(h)\nprint(\"mainbody end\")\nresult\n//│ > mainbody start\n//│ > Entering foobar\n//│ > Entering bar\n//│ > Entering foo\n//│ > handler called\n//│ > handler called\n//│ > Exiting foo\n//│ > Exiting bar\n//│ > Exiting foobar\n//│ > mainbody end\n//│ > handler finished\n//│ > handler finished\n//│ = \"Hello World!\"\n\n// Float out definitions\nhandle h = Effect with\n  fun perform(arg)(k) = arg\nif true do\n  fun f() = 3\n  print(f())\n//│ > 3\n\nmodule A with\n  data class Effect(x) with\n    fun test() = x\n    fun perform(arg)\n\nhandle h = A.Effect(3) with\n  fun perform()(k) = 0\nh.perform()\n//│ = 0\n\nfun f(perform) =\n  handle h = Effect with\n    fun perform(arg)(k) = arg\n  perform()\nf(() => 3)\n//│ = 3\n\nabstract class Cell with\n  fun getVal(): Int\n  fun setVal(Int): ()\n\nlet x = 0\nhandle h = Cell with\n  fun getVal()(k) = k(x)\n  fun setVal(value)(k) =\n    x = value\n    k(())\nprint(h.getVal())\nh.setVal(1)\nprint(h.getVal())\n//│ > 0\n//│ > 1\n//│ x = 1\n\n\nabstract class Eff with\n  fun get(): Int\n\n:expect 120\nfun fact(e, factvalue) = \n  if factvalue != 0 then\n    factvalue * fact(e, factvalue-1)\n  else e.get()\nhandle h = Eff with\n  fun get()(k) = k(1)\nfact(h, 5)\n//│ = 120\n\nabstract class StackDelay with\n  fun raise(): ()\n\n// stack safe recursion\n:expect 5050\nhandle h = StackDelay with\n  fun raise()(k) =\n    // console.trace(\"Stack unwinded!\")\n    k(10)\nfun sum(depth, x) =\n  let new_depth = if depth > 70 then\n    // console.trace(\"Too deep, heapifying the stack\")\n    h.raise()\n  else\n    depth + 1\n  if x != 0 then\n    x + sum(new_depth, x - 1)\n  else 0\nsum(0, 100)\n//│ = 5050\n\n// stack safe recursion\n:expect 450015000\nhandle h = StackDelay with\n  fun raise()(k) =\n    k(10)\nfun sum(depth, x) =\n  let new_depth = if depth > 1000 then h.raise() else depth + 1\n  if x != 0 then\n    x + sum(new_depth, x - 1)\n  else 0\nsum(0, 30000)\n//│ = 450015000\n\n:re\nfun sum(x) =\n  if x != 0 then\n    x + sum(x - 1)\n  else 0\nsum(10000)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n:expect 2\nfun foo(h) =\n  h.perform()\n  if true then\n    fun g() = 2\n    g()\n  else\n    fun g() = 3\n    g()\nhandle h = Eff with\n  fun perform()(k) = k(())\nfoo(h)\n//│ = 2\n\n:expect 3\nfun foo(h) =\n  h.perform()\n  if false then\n    fun g() = 2\n    g()\n  else\n    fun g() = 3\n    g()\nhandle h = Eff with\n  fun perform()(k) = k(())\nfoo(h)\n//│ = 3\n\n:expect 123\nfun foo(h) =\n  h.perform()\n  fun A() = 1\n  let a = if true then\n    class A() with\n      fun f() = 2\n    A().f()\n  else\n    class A() with\n      fun f() = 3\n    A().f()\n  let b = if false then\n    class A() with\n      fun f() = 2\n    A().f()\n  else\n    class A() with\n      fun f() = 3\n    A().f()\n  A() * 100 + a * 10 + b\nhandle h = Eff with\n  fun perform()(k) = k(())\nfoo(h) \n//│ = 123\n\n:fixme\n:expect 123\nfun foo(h) =\n  h.perform()\n  fun A() = 1\n  let a = if true then\n    module A with\n      fun f() = 2\n    A.f()\n  else\n    module A with\n      fun f() = 3\n    A.f()\n  let b = if false then\n    module A with\n      fun f() = 2\n    A.f()\n  else\n    module A with\n      fun f() = 3\n    A.f()\n  A() * 100 + a * 10 + b\nhandle h = Eff with\n  fun perform()(k) = k(())\nfoo(h)\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.440: \t    module A with\n//│ ╙──       \t           ^\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.436: \t    module A with\n//│ ╙──       \t           ^\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.432: \t    module A with\n//│ ╙──       \t           ^\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.428: \t    module A with\n//│ ╙──       \t           ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.428: \t    module A with\n//│ ╙──       \t           ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.432: \t    module A with\n//│ ╙──       \t           ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.436: \t    module A with\n//│ ╙──       \t           ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.440: \t    module A with\n//│ ╙──       \t           ^\n//│ = 123\n\n// Access superclass fields\nhandle h1 = Object with\n  fun perf()(k) = k(2)\nclass A with\n  val x = 2\nhandle h2 = A with\n  fun perf()(k) = k(this.x)\nh2.perf()\n//│ = 2\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/EffectsHygiene.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nmodule M\n\n// * Notice that the two module definitions are lifted to the top of the block.\n:ssjs\n:fixme\nfun foo(h): module M =\n  if false then\n    module A\n    A\n  else\n    module A\n    A\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.15: \t    module A\n//│ ╙──      \t           ^\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.12: \t    module A\n//│ ╙──      \t           ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.12: \t    module A\n//│ ╙──      \t           ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.15: \t    module A\n//│ ╙──      \t           ^\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let foo;\n//│ runtime.checkCall(runtime.resetEffects());\n//│ foo = function foo(h) {\n//│   runtime.checkArgs(\"foo\", 1, true, arguments.length);\n//│   let A2, A3, scrut;\n//│   scrut = false;\n//│   if (scrut === true) {\n//│     globalThis.Object.freeze(class A {\n//│       static {\n//│         A2 = this\n//│       }\n//│       toString() { return runtime.render(this); }\n//│       static [definitionMetadata] = [\"class\", \"A\"]; \n//│     });\n//│     return A2\n//│   }\n//│   globalThis.Object.freeze(class A1 {\n//│     static {\n//│       A3 = this\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"class\", \"A\"]; \n//│   });\n//│   return A3;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/EffectsInClasses.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class Effect with\n  fun perform(arg: Str): Str\n\n\n:sjs\ndata class Lol(h) with\n  print(h.perform(\"k\"))\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Lol1;\n//│ runtime.resetEffects();\n//│ Lol1 = function Lol(h) {\n//│   return globalThis.Object.freeze(new Lol.class(h));\n//│ };\n//│ (class Lol {\n//│   static {\n//│     Lol1.class = this\n//│   }\n//│   constructor(h) {\n//│     let tmp;\n//│     this.h = h;\n//│     tmp = runtime.safeCall(this.h.perform(\"k\"));\n//│     if (runtime.curEffect !== null) {\n//│       tmp = runtime.illegalEffect(\"in a constructor\");\n//│     }\n//│     Predef.print(tmp);\n//│     if (runtime.curEffect !== null) {\n//│       runtime.illegalEffect(\"in a constructor\");\n//│     }\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Lol\", [\"h\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * This is a weird use of effect handlers where an effect is raised during the construction of a handler.\n// * The most natural semantics (following what normal constructors currently do)\n// *  is for the handler to not yet be constructed but to be constructed and executed normally after resumption.\n// * See full discussion at: https://github.com/hkust-taco/mlscript/pull/268#discussion_r1938523085\n:fixme\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(arg)\n    k()\nabstract class Eff with\n  fun test()\n  h.perform(\"x\")\nhandle k = Eff with\n  fun test()(k) = k()\nk.test()\nprint(\"test\")\n//│ ═══[RUNTIME ERROR] Error: Effect Handler$h$ is raised in a constructor\n\n\n\n:fixme\nlet oops = \n  handle h = Effect with\n    fun perform(arg)(k) =\n      print(arg)\n      \"b\"\n  Lol(h)\n//│ ═══[RUNTIME ERROR] Error: Effect Handler$h$2 is raised in a constructor\n//│ oops = undefined\n\n:fixme\n:expect \"b\"\noops\n//│ ═══[RUNTIME ERROR] Expected: '\"b\"', got: 'undefined'\n\n:fixme\nlet oops = \n  handle h = Effect with\n    fun perform(arg)(k) =\n      print(arg)\n      \"b\"\n  new Lol(h)\n//│ ═══[RUNTIME ERROR] Error: Effect Handler$h$4 is raised in a constructor\n//│ oops = undefined\n\n:fixme\n:expect \"b\"\noops\n//│ ═══[RUNTIME ERROR] Expected: '\"b\"', got: 'undefined'\n\n\n:fixme\nlet oops = \n  handle h = Effect with\n    fun perform(arg)(k) =\n      print(arg)\n      k(\"b\")\n  Lol(h)\n//│ ═══[RUNTIME ERROR] Error: Effect Handler$h$6 is raised in a constructor\n//│ oops = undefined\n\n:fixme\noops.h\n//│ ═══[RUNTIME ERROR] TypeError: Cannot read properties of undefined (reading 'h')\n\nlet obj = mut {s: undefined}\n//│ obj = {s: undefined}\n\nhandle h = Effect with\n  fun perform(arg)(k) =\n    k()\n    print(arg)\nset obj.s = h.perform(\"k\")\n//│ > k\n\nfun f() = ()\n\nmodule A with\n  f()\n  () // defeats tail call optimization\n\nlet obj = new Object with\n  fun foo() = print(\"Hello\")\n  foo()\n//│ > Hello\n//│ obj = $anon\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/EffectsInMethods.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\n\nabstract class Effect with\n  fun perform(arg: Str): Str\n\n\nclass Test with\n  fun p(h, x) =\n    h.perform(\"A\", x) + h.perform(\"B\", x + 1)\nlet t = new Test\n//│ t = Test\n\nhandle h = Effect with\n  fun perform(arg, x)(k) =\n    print(arg)\n    k(x * 2)\n[t.p(h, 2), t.p(h, 3)]\n//│ > A\n//│ > B\n//│ > A\n//│ > B\n//│ = [10, 14]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/Fallthrough.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nfun g() = 0\n\n:sjs\nfun f() =\n  let x\n  if 0 is 0 do\n    set x = g() + g()\n  set x = g()\n  set x = g()\n  set x = g()\n  set x = g()\n  return x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f;\n//│ runtime.resetEffects();\n//│ f = function f() {\n//│   let x, scrut, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     let saveOffset;\n//│     pc = runtime.resumePc;\n//│     saveOffset = runtime.resumeIdx;\n//│     tmp = runtime.resumeArr.at(saveOffset);\n//│     runtime.resumePc = -1;\n//│   }\n//│   main: while (true) {\n//│     switch (pc) {\n//│       case 7:\n//│         tmp = runtime.resumeValue;\n//│         runtime.resumeValue = g();\n//│         if (runtime.curEffect === null) {\n//│           pc = 6;\n//│         } else {\n//│           return runtime.unwind(f, 6, \"Fallthrough.mls:11:19\", null, null, 1, 0, 1, tmp)\n//│         }\n//│       case 6:\n//│         tmp1 = runtime.resumeValue;\n//│         tmp2 = tmp + tmp1;\n//│         x = tmp2;\n//│         pc = 5;\n//│       case 5:\n//│         runtime.resumeValue = g();\n//│         if (runtime.curEffect === null) {\n//│           pc = 4;\n//│         } else {\n//│           return runtime.unwind(f, 4, \"Fallthrough.mls:12:11\", null, null, 1, 0, 1, tmp)\n//│         }\n//│       case 4:\n//│         tmp3 = runtime.resumeValue;\n//│         x = tmp3;\n//│         runtime.resumeValue = g();\n//│         if (runtime.curEffect === null) {\n//│           pc = 3;\n//│         } else {\n//│           return runtime.unwind(f, 3, \"Fallthrough.mls:13:11\", null, null, 1, 0, 1, tmp)\n//│         }\n//│       case 3:\n//│         tmp4 = runtime.resumeValue;\n//│         x = tmp4;\n//│         runtime.resumeValue = g();\n//│         if (runtime.curEffect === null) {\n//│           pc = 2;\n//│         } else {\n//│           return runtime.unwind(f, 2, \"Fallthrough.mls:14:11\", null, null, 1, 0, 1, tmp)\n//│         }\n//│       case 2:\n//│         tmp5 = runtime.resumeValue;\n//│         x = tmp5;\n//│         runtime.resumeValue = g();\n//│         if (runtime.curEffect === null) {\n//│           pc = 1;\n//│         } else {\n//│           return runtime.unwind(f, 1, \"Fallthrough.mls:15:11\", null, null, 1, 0, 1, tmp)\n//│         }\n//│       case 1:\n//│         tmp6 = runtime.resumeValue;\n//│         x = tmp6;\n//│         return x;\n//│       case 0:\n//│         scrut = 0;\n//│         if (scrut === 0) {\n//│           runtime.resumeValue = g();\n//│           if (runtime.curEffect === null) {\n//│             pc = 7;\n//│             continue main\n//│           }\n//│           return runtime.unwind(f, 7, \"Fallthrough.mls:11:13\", null, null, 1, 0, 1, tmp);\n//│         }\n//│         pc = 5;\n//│         continue main;\n//│     }\n//│     break;\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/GeneratorStack.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nimport \"../../mlscript-compile/Stack.mls\"\nopen Stack\n\nclass Generator with\n  fun produce(result: Stack[Int]): ()\n\nfun (++) concat(l1, l2) =\n  if l1 is \n    Nil then l2\n    Cons(h, t) then Cons(h, t ++ l2)\n\nfun (:+) append(l, e) =\n  if l is \n    Nil then e :: Nil\n    Cons(h, t) then h :: t :+ e\n\nfun length(l) =\n  if l is\n    Nil then 0\n    Cons(_, t) then 1 + length(t)\n\nfun permutations_impl(gen, l1, l2) =\n  if l2 is\n    Nil and\n      l1 is Nil then gen.produce(Nil)\n      else ()\n    Cons(f, t) then\n      handle gen2 = Generator with\n        fun produce(result)(resume) =\n          gen.produce(f :: result)\n          resume(())\n      permutations_impl(gen2, Nil, l1 ++ t)\n      permutations_impl(gen, l1 :+ f, t)\n\nfun permutations(gen, l) =\n  permutations_impl(gen, Nil, l)\n\nlet result =\n  handle gen = Generator with\n    fun produce(result)(resume) =\n      print(result)\n      let r = resume(())\n      result :: r\n  permutations(gen, 1 :: 2 :: 3 :: 4 :: Nil), Nil\nin length(result)\n//│ > Cons(1, Cons(2, Cons(3, Cons(4, Nil))))\n//│ > Cons(1, Cons(2, Cons(4, Cons(3, Nil))))\n//│ > Cons(1, Cons(3, Cons(2, Cons(4, Nil))))\n//│ > Cons(1, Cons(3, Cons(4, Cons(2, Nil))))\n//│ > Cons(1, Cons(4, Cons(2, Cons(3, Nil))))\n//│ > Cons(1, Cons(4, Cons(3, Cons(2, Nil))))\n//│ > Cons(2, Cons(1, Cons(3, Cons(4, Nil))))\n//│ > Cons(2, Cons(1, Cons(4, Cons(3, Nil))))\n//│ > Cons(2, Cons(3, Cons(1, Cons(4, Nil))))\n//│ > Cons(2, Cons(3, Cons(4, Cons(1, Nil))))\n//│ > Cons(2, Cons(4, Cons(1, Cons(3, Nil))))\n//│ > Cons(2, Cons(4, Cons(3, Cons(1, Nil))))\n//│ > Cons(3, Cons(1, Cons(2, Cons(4, Nil))))\n//│ > Cons(3, Cons(1, Cons(4, Cons(2, Nil))))\n//│ > Cons(3, Cons(2, Cons(1, Cons(4, Nil))))\n//│ > Cons(3, Cons(2, Cons(4, Cons(1, Nil))))\n//│ > Cons(3, Cons(4, Cons(1, Cons(2, Nil))))\n//│ > Cons(3, Cons(4, Cons(2, Cons(1, Nil))))\n//│ > Cons(4, Cons(1, Cons(2, Cons(3, Nil))))\n//│ > Cons(4, Cons(1, Cons(3, Cons(2, Nil))))\n//│ > Cons(4, Cons(2, Cons(1, Cons(3, Nil))))\n//│ > Cons(4, Cons(2, Cons(3, Cons(1, Nil))))\n//│ > Cons(4, Cons(3, Cons(1, Cons(2, Nil))))\n//│ > Cons(4, Cons(3, Cons(2, Cons(1, Nil))))\n//│ = 24\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/Generators.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nabstract class Generator with\n  fun produce(result): ()\n\nfun permutations_impl(gen, l1, l2) =\n  if l2 is\n    [f, ...t] do\n      handle genWithPrefix = Generator with\n        fun produce(result)(resume) =\n          result.unshift(f)\n          gen.produce(result)\n          resume(())\n      permutations_impl(genWithPrefix, mut [], l1.concat(t))\n      l1.push(f)\n      permutations_impl(gen, l1, t)\n    [] and l1 is [] do\n      gen.produce(mut [])\nfun permutations(gen, l) =\n  permutations_impl(gen, mut [], l)\n\nlet res = mut []\nhandle gen = Generator with\n  fun produce(result)(resume) =\n    res.push(result)\n    resume(())\nin permutations(gen, [1, 2, 3, 4])\n//│ res = [\n//│   [1, 2, 3, 4],\n//│   [1, 2, 4, 3],\n//│   [1, 3, 2, 4],\n//│   [1, 3, 4, 2],\n//│   [1, 4, 2, 3],\n//│   [1, 4, 3, 2],\n//│   [2, 1, 3, 4],\n//│   [2, 1, 4, 3],\n//│   [2, 3, 1, 4],\n//│   [2, 3, 4, 1],\n//│   [2, 4, 1, 3],\n//│   [2, 4, 3, 1],\n//│   [3, 1, 2, 4],\n//│   [3, 1, 4, 2],\n//│   [3, 2, 1, 4],\n//│   [3, 2, 4, 1],\n//│   [3, 4, 1, 2],\n//│   [3, 4, 2, 1],\n//│   [4, 1, 2, 3],\n//│   [4, 1, 3, 2],\n//│   [4, 2, 1, 3],\n//│   [4, 2, 3, 1],\n//│   [4, 3, 1, 2],\n//│   [4, 3, 2, 1]\n//│ ]\n\nfun permutations_foreach(l, f) =\n  handle gen = Generator with\n    fun produce(result)(resume) =\n      f(result)\n      resume(())\n  permutations(gen, l)\npermutations_foreach([1, 2, 3], print)\n//│ > [1, 2, 3]\n//│ > [1, 3, 2]\n//│ > [2, 1, 3]\n//│ > [2, 3, 1]\n//│ > [3, 1, 2]\n//│ > [3, 2, 1]\n\n\nfun permutations_impl(gen, l1, l2) =\n  if l2 is\n    [f, ...t] do\n      handle genWithPrefix = Generator with\n        fun produce(result)(resume) =\n          gen.produce([f, ...result])\n          let x = resume(())\n          x\n      permutations_impl(genWithPrefix, mut [], l1.concat(t))\n      l1.push(f)\n      permutations_impl(gen, l1, t)\n    [] and l1 is [] do\n      gen.produce([])\nfun permutations(gen, l) =\n  permutations_impl(gen, mut [], l)\n\nlet res = mut []\nhandle gen = Generator with\n  fun produce(result)(resume) =\n    res.push(result)\n    let x = resume(())\n    x\nin permutations(gen, [1, 2, 3])\n//│ res = [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/HandlerBlockBindings.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class Effect with\n  fun perform(arg: Str): Str\n\n\n// non-resumptive handlers\nhandle h = Effect with\n  fun perform(arg)(k) =\n    \"A\"\nh.perform(\"B\")\nlet x = 123\n//│ = \"A\"\n\n:e\nx\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.19: \tx\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(arg)\nlet x = 123\nx + 1\n//│ = 124\n\n:e\nx\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.34: \tx\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(arg)\nval y = 123\n\n:e\ny\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.47: \ty\n//│ ╙──      \t^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/HandlerReset.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nimport \"../../mlscript-compile/Runtime.mls\"\n\nset Runtime.resumePc = 100\n\n:expect -1\nRuntime.resumePc\n//│ = -1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/HandlersInClasses.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class Effect with\n  fun perform(arg: Str): Str\n\n\n// * Note that the `val x` binding is in the handler's own body and not a field of the object...\n// * It could not possibly be, because the handler might not resume the rest of the object's constructor,\n// * so `x` might never get initialized even though the object might be returned.\n\nobject Lol with\n  handle h = Effect with\n    fun perform(arg)(k) =\n      print(arg)\n      \"B\"\n  print(h.perform(\"A\"))\n  val x = 123\n//│ > A\n\n:e\n:re\nLol.x\n//│ ╔══[COMPILATION ERROR] Object 'Lol' does not contain member 'x'\n//│ ║  l.25: \tLol.x\n//│ ╙──      \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n\nobject Lol with\n  handle h = Effect with\n    fun perform(arg)(k) =\n      print(arg)\n      k(\"B\")\n  print(h.perform(\"A\"))\n  val x = 123\n//│ > A\n//│ > B\n\n:e\n:re\nLol.x\n//│ ╔══[COMPILATION ERROR] Object 'Lol' does not contain member 'x'\n//│ ║  l.44: \tLol.x\n//│ ╙──      \t   ^^\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n\ndata class Lol() with\n  handle h = Effect with\n    fun perform(arg)(k) =\n      print(arg)\n      \"B\"\n  print(h.perform(\"A\"))\n  val x = 123\n\n// * Note: does NOT return a partially initialized object\nlet oops = Lol()\n//│ > A\n//│ oops = Lol()\n\n:re\noops.x\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/HandlersInMethods.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class Effect with\n  fun perform(arg: Str): Str\n\n\nclass Test with\n  fun p(x) =\n    handle h = Effect with\n      fun perform(arg, x)(k) =\n        print(arg)\n        k(x * 2)\n    h.perform(\"A\", x) + h.perform(\"B\", x + 1)\nlet t = new Test\n//│ t = Test\n\n[t.p(2), t.p(3)]\n//│ > A\n//│ > B\n//│ > A\n//│ > B\n//│ = [10, 14]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/HandlersScratch.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nabstract class Effect\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/LeakingEffects.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class Effect[A] with\n  fun perform(arg: A): A\n\n\nlet\n  xs = mut []\n  count = 0\nfun main() =\n  handle g = Effect with\n    fun perform(arg1)(k1) =\n      print(\"B \" + arg1)\n      xs.push(k1)\n  print(g.perform(\"a\"))\n  print(\"—\")\n  print(g.perform(\"b\"))\n  print(\"—\")\n  print(g.perform(\"c\"))\nmain()\nwhile\n  do print(xs)\n  let f = xs.pop()\n  f !== () then\n    set count += 1\n    f(count)\n    print(\"?\")\n//│ > B a\n//│ > [fun]\n//│ > 1\n//│ > —\n//│ > B b\n//│ > ?\n//│ > [fun]\n//│ > 2\n//│ > —\n//│ > B c\n//│ > ?\n//│ > [fun]\n//│ > 3\n//│ > ?\n//│ > []\n//│ count = 3\n//│ xs = []\n\n// * Notes:\n(mut []).pop() === undefined\n//│ = false\n(mut []).pop() === null\n//│ = false\n(mut []).pop() === ()\n//│ = true\n\n\n// g is non-resumptive, which means g.perform(\"a\") does not resume\n// hence it should exit the entire handle block with the return value of xs.push(k1)\n:expect 1\nhandle h = Effect with\n  fun perform(arg)(k) =\n    print(\"A \" + arg)\n    let\n      xs = mut []\n      count = 0\n    handle g = Effect with\n      fun perform(arg1)(k1) =\n        print(\"B \" + arg + \" \" + arg1)\n        xs.push(k1)\n    k(g)\n    while xs.pop() is\n      null then print(\"Done.\")\n      f then\n        set count += 1\n        f(count)\nlet g = h.perform(\"hi\")\nprint(g.perform(\"a\"))\nprint(\"—\")\nprint(g.perform(\"b\"))\nprint(\"—\")\nprint(g.perform(\"c\"))\n// set g = h.perform(\"hola\")\n// g.perform(\"adios\")\n//│ > A hi\n//│ > B hi a\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/ManualEffectBinding.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nabstract class Effect with\n  fun perform(): ()\n\nlet h1 = null\nhandle h = Effect with\n  fun perform()(k) =\n    print(\"perform\")\n    k()\n    print(\"perform-end\")\nset h1 = h\n//│ h1 = Handler$h$\n\n:re\nh1.perform()\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$\n\nenterHandleBlock(h1, () => h1.perform())\n//│ > perform\n//│ > perform-end\n\nlet h2 = null\nhandle h = Effect with\n  fun perform()(k) =\n    print(\"perform2\")\n    k()\n    print(\"perform-end2\")\nset h2 = h\n//│ h2 = Handler$h$\n\n// This causes the scenario where next is null but nextHandler is not null in the runtime\nenterHandleBlock(h1, () => enterHandleBlock(h2, () =>\n  h1.perform()\n  h2.perform()\n  h1.perform()\n))\n//│ > perform\n//│ > perform2\n//│ > perform\n//│ > perform-end2\n//│ > perform-end\n//│ > perform-end\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/ManualStackSafety.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n// * This file demonstrates the handler-based mechanism of our stack safety implementation\n// * by manually applying the transformation of a recursive factorial function\n// * defined through the Z combinator.\n// * It is notably interesting in that it demonstrates the ability to preserve tail calls.\n// * The original function can be found in `hkmc2/shared/src/test/mlscript/handlers/ZCombinator.mls`\n\n\nfun test(n, stackLimit) =\n  let stackDepth = 0\n  let stackOffset = 0\n  abstract class StackDelay with\n    fun perform()\n  handle h = StackDelay with\n    fun perform()(resume) =\n      let curOffset = stackOffset\n      set stackOffset = stackDepth\n      console.log(\"resuming at offset:\", curOffset)\n      let tmp = resume()\n      console.log(\"finished at offset:\", curOffset)\n      set stackOffset = curOffset\n      tmp\n  fun selfApp(f) = \n    if stackDepth - stackOffset >= stackLimit do h.perform()\n    set stackDepth += 1\n    f(f)\n  fun mkrec(g) =\n    if stackDepth - stackOffset >= stackLimit do h.perform()\n    fun a(self) =\n      if stackDepth - stackOffset >= stackLimit do h.perform()\n      fun b(y) = \n        if stackDepth - stackOffset >= stackLimit do h.perform()\n        let tmp = stackDepth\n        set stackDepth += 1\n        let res = selfApp(self)\n        set stackDepth = tmp\n        set stackDepth += 1\n        res(y)\n      set stackDepth += 1\n      g(b)\n    set stackDepth += 1\n    selfApp(a)\n  let fact =\n    fun a(self) =\n      if stackDepth - stackOffset >= stackLimit do h.perform()\n      fun b(x) =\n        if stackDepth - stackOffset >= stackLimit do h.perform()\n        if x == 0 then 1 else \n          console.log(stackDepth, stackOffset)\n          let tmp = stackDepth\n          set stackDepth += 1\n          let prev = self(x - 1)\n          set stackDepth = tmp\n          console.log(\"resumed:\", x)\n          x * prev\n      b\n    mkrec(a)\n  set stackDepth = 1\n  let ans = fact(n)\n  set stackDepth = 0\n  ans\n\n:expect 3628800\ntest(10, 100)\n//│ > 1 0\n//│ > 3 0\n//│ > 5 0\n//│ > 7 0\n//│ > 9 0\n//│ > 11 0\n//│ > 13 0\n//│ > 15 0\n//│ > 17 0\n//│ > 19 0\n//│ > resumed: 1\n//│ > resumed: 2\n//│ > resumed: 3\n//│ > resumed: 4\n//│ > resumed: 5\n//│ > resumed: 6\n//│ > resumed: 7\n//│ > resumed: 8\n//│ > resumed: 9\n//│ > resumed: 10\n//│ = 3628800\n\n:expect 3628800\ntest(10, 5)\n//│ > 1 0\n//│ > resuming at offset: 0\n//│ > 3 5\n//│ > 5 5\n//│ > 7 5\n//│ > resuming at offset: 5\n//│ > 9 10\n//│ > 11 10\n//│ > resuming at offset: 10\n//│ > 13 15\n//│ > 15 15\n//│ > 17 15\n//│ > resuming at offset: 15\n//│ > 19 20\n//│ > resumed: 1\n//│ > resumed: 2\n//│ > resumed: 3\n//│ > resumed: 4\n//│ > resumed: 5\n//│ > resumed: 6\n//│ > resumed: 7\n//│ > resumed: 8\n//│ > resumed: 9\n//│ > resumed: 10\n//│ > finished at offset: 15\n//│ > finished at offset: 10\n//│ > finished at offset: 5\n//│ > finished at offset: 0\n//│ = 3628800\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/MultiResumption.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nclass Logger with\n  fun info(s: Str): ()\n\n:re\nhandle h = Logger with\n  fun info(s)(k) =\n    print(s)\n    k()\n    k()\nh.info(\"a\")\n//│ > a\n//│ ═══[RUNTIME ERROR] Error: Multiple resumption\n\n\nhandle h = Logger with\n  fun info(s)(k) =\n    print(s)\n    k()\n    k()\n123\n//│ = 123\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/NestedFun.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nfun foo(f) =\n  let y = 1\n  fun bar() =\n    f()\n    set y += 1\n  let lam = () => y\n  bar()\n  set y += 1\n  lam()\n\n\n:expect 3\nhandle h = Object with\n  fun f()(k) = k(())\nfoo(() => h.f())\n//│ = 3\n\nfun foo() =\n  let y = 1\n  fun bar() =\n    set y += 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/NestedHandlers.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nlet id = 0\n//│ id = 0\n\n// FIXME: if the following 2 blocks are together, lifter causes class ordering issue\nclass MaybeStop with\n  fun f(x: Bool): ()\n\nfun handleEffects(g) =\n  handle h1 = MaybeStop with\n    fun f(x)(k) =\n      if x then\n        print(\"h1 stop\")\n      else\n        set id += 1\n        let cur = id\n        print(\"h1 start \" + String(cur))\n        let result = k(x)\n        print(\"h1 end \" + String(cur))\n        result\n  handle h2 = MaybeStop with\n    fun f(x)(k) =\n      if x then\n        print(\"h2 stop\")\n      else\n        set id += 1\n        let cur = id\n        print(\"h2 start \" + String(cur))\n        let result = k(x)\n        print(\"h2 end \" + String(cur))\n        result\n  g(h1, h2)\n\n\nfun f(h1, h2) =\n  h1.f(false)\n  h2.f(false)\n  h1.f(false)\n  h2.f(false)\n  h1.f(false)\n  h2.f(false)\nhandleEffects(f)\n//│ > h1 start 1\n//│ > h2 start 2\n//│ > h1 start 3\n//│ > h2 start 4\n//│ > h1 start 5\n//│ > h2 start 6\n//│ > h2 end 6\n//│ > h2 end 4\n//│ > h2 end 2\n//│ > h1 end 5\n//│ > h1 end 3\n//│ > h1 end 1\n//│ = false\n\n\nfun f(h1, h2) =\n  h1.f(false)\n  h2.f(false)\n  h1.f(false)\n  h2.f(true)\n  h1.f(false)\n  h2.f(false)\nhandleEffects(f)\n//│ > h1 start 7\n//│ > h2 start 8\n//│ > h1 start 9\n//│ > h2 stop\n//│ > h2 end 8\n//│ > h1 end 9\n//│ > h1 end 7\n\n\nfun f(h1, h2) =\n  h1.f(false)\n  h2.f(false)\n  h1.f(true)\n  h2.f(false)\n  h1.f(false)\n  h2.f(false)\nhandleEffects(f)\n//│ > h1 start 10\n//│ > h2 start 11\n//│ > h1 stop\n//│ > h1 end 10\n\n\nclass Eff with\n  fun perform(): ()\ndata class Box(n)\nlet box = new mut Box(0)\n//│ box = Box(0)\n\n\n:expect 5120\nfun f(h, box, n) =\n  if n <= 1 then\n    h.perform()\n  else\n    handle h2 = Eff with\n      fun perform()(k) =\n        set box.n = box.n + 1\n        h.perform()\n        k()\n    f(h2, box, n - 1)\n    f(h2, box, n - 1)\nhandle h = Eff with\n  fun perform()(k) =\n    set box.n = box.n + 1\n    k()\nf(h, box, 10)\nbox.n\n//│ = 5120\n\nhandle h1 = Eff with\n  fun perform()(k) =\n    print(\"h1\")\n    let x = k()\n    print(\"h1 end\")\n    x\nhandle h2 = Eff with\n  fun perform()(k) =\n    print(\"h2\")\n    h1.perform()\n    let x = k()\n    print(\"h2 end\")\n    x\nh2.perform()\nh2.perform()\nh2.perform()\n//│ > h2\n//│ > h1\n//│ > h2\n//│ > h1\n//│ > h2\n//│ > h1\n//│ > h2 end\n//│ > h2 end\n//│ > h2 end\n//│ > h1 end\n//│ > h1 end\n//│ > h1 end\n\n\nhandle h1 = Eff with\n  fun perform()(k) =\n    print(\"h1\")\n    k()\nhandle h2 = Eff with\n  fun perform()(k) =\n    print(\"h2\")\n    h1.perform()\n    k()\nhandle h3 = Eff with\n  fun perform()(k) =\n    print(\"h3\")\n    h2.perform()\n    k()\nh1.perform()\nh3.perform()\n//│ > h1\n//│ > h3\n//│ > h2\n//│ > h1\n\n\nlet d = 0\n//│ d = 0\n\n\n:expect 11\nhandle h1 = Eff with\n  fun perform()(k) =\n    set d = d + 1\n    k()\nlet i = 0\nh1.perform()\nwhile i < 10 do \n  handle h2 = Eff with\n    fun perform()(k) =\n      set d = d + 1\n      k()\n  h2.perform()\n  set i = i + 1\nd\n//│ = 11\n\nabstract class Eff2 with\n  fun f1(): ()\n  fun f2(): ()\n\n\n// Effect performed at end of handler, which trigger a special branch to handle\nhandle h1 = Eff2 with\n  fun f1()(k) =\n    print(\"h1.f1 pre\")\n    k()\n    print(\"h1.f1 post\")\n  fun f2()(k) = k()\nhandle h2 = Eff2 with\n  fun f1()(k) =\n    print(\"h2.f1\")\n    k()\n  fun f2()(k) =\n    print(\"h2.f2 pre\")\n    k()\n    print(\"h2.f2 post\")\n    h1.f1()\nh2.f2()\nh2.f1()\n//│ > h2.f2 pre\n//│ > h2.f1\n//│ > h2.f2 post\n//│ > h1.f1 pre\n//│ > h1.f1 post\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/NoHandler.mls",
    "content": ":js\n\nabstract class Effect with\n  fun perform(arg: Str): Str\n\n:ge\nhandle h = Effect with\n  fun perform(arg)(k) = k(arg)\nh.perform(\"k\")\n//│ ╔══[COMPILATION ERROR] Effect handlers are not enabled\n//│ ║  l.7: \thandle h = Effect with\n//│ ║       \t           ^^^^^^^^^^^\n//│ ║  l.8: \t  fun perform(arg)(k) = k(arg)\n//│ ║       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.9: \th.perform(\"k\")\n//│ ╙──     \t^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/NoStackSafety.mls",
    "content": ":js\n\n\n// sanity check\n:expect 5050\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nsum(100)\n//│ = 5050\n\n// stack-overflows without :stackSafe\n:re\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nsum(10000)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\n:re\nfun foo() =\n  let f = ()\n  set f = n =>\n    if n <= 0 then 0\n    else n + f(n-1)\n  f(10000)\nfoo()\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\n:sjs\n:stackSafe 42\nfun hi(n) = n\nhi(0)\n//│ /!!!\\ Option ':stackSafe' requires ':effectHandlers' to be set\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let hi, n, inlinedVal; hi = function hi(n1) { return n1 }; n = 0; inlinedVal = n; inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:stackSafe 42\nhi(0)\n//│ /!!!\\ Option ':stackSafe' requires ':effectHandlers' to be set\n//│ = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/NonLocalReturns.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nfun f() =\n  (() => return 100)()\n  print(\"Bad\")\nf()\n//│ = 100\n\n\nfun foo(x) =\n  let xs = [() => return x + 1]\n  xs.0()\n\nfoo(123)\n//│ = 124\n\n\n:expect 123\nfun f() =\n  let lam = () => return 123\n  fun g() =\n    let lam2 = () => return 200\n    lam()\n    lam2()\n    100\n  print(\"Ok\")\n  g()\n  print(\"Bad\")\n  100\nf()\n//│ > Ok\n//│ = 123\n\n:expect 100\nfun f() =\n  let lam = () => return 123\n  fun g() =\n    let lam2 = () => return 200\n    lam2()\n    lam()\n    100\n  print(\"Ok\")\n  print(g())\n  print(\"Continue\")\n  100\nf()\n//│ > Ok\n//│ > 200\n//│ > Continue\n//│ = 100\n\n\n:re\nfun f() = () => return 3\nf()()\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect $_non$_local$_return$_effect$_12\n\n:re\nfun f(): () -> Int = () => return () => 3\nf()()\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect $_non$_local$_return$_effect$_14\n\n\n:e\nreturn 100\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed outside of functions.\n//│ ║  l.68: \treturn 100\n//│ ╙──      \t^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nif true do\n  while false do\n    let f = () => return 100\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed outside of functions.\n//│ ║  l.77: \t    let f = () => return 100\n//│ ╙──      \t                  ^^^^^^^^^^\n\n:e\nfun f() =\n  type A = return \"lol\"\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed in this context.\n//│ ║  l.84: \t  type A = return \"lol\"\n//│ ╙──      \t           ^^^^^^^^^^^^\n\n\n:expect 100\nfun f() =\n  if true do\n    let f = null\n    let done = false\n    while not(done) do\n      set\n        f = () => return 100\n        done = true\n    f()\n    print(\"Bad\")\nf()\n//│ = 100\n\n// TODO(inliner): something is wrong here\n// broken due to handlers currently not handling `object` properly\n:fixme\n:expect 100\nfun f() =\n  object A with\n    return 100\n  4\nf()\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.109: \t  object A with\n//│ ╙──       \t         ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.109: \t  object A with\n//│ ╙──       \t         ^\n//│ ═══[RUNTIME ERROR] Error: Effect $_non$_local$_return$_effect$_18 is raised in a constructor\n//│ ═══[RUNTIME ERROR] Expected: '100', got: 'undefined'\n\n// ctor cannot raise effect, so error is expected.\n:fixme\n:expect 100\nfun f() =\n  class A with\n    return 100\n  new A\nf()\n//│ ═══[RUNTIME ERROR] Error: Effect $_non$_local$_return$_effect$_20 is raised in a constructor\n//│ ═══[RUNTIME ERROR] Expected: '100', got: 'undefined'\n\n:fixme\n:expect 100\nfun f() =\n  object A with\n    (() => return 100)()\n  4\nf()\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.136: \t  object A with\n//│ ╙──       \t         ^\n//│ ╔══[INTERNAL ERROR] Unexpected nested class: lambdas may not function correctly.\n//│ ║  l.136: \t  object A with\n//│ ╙──       \t         ^\n//│ ═══[RUNTIME ERROR] Error: Effect $_non$_local$_return$_effect$_22 is raised in a constructor\n//│ ═══[RUNTIME ERROR] Expected: '100', got: 'undefined'\n\n:fixme\n:expect 100\nfun f() =\n  class A with\n    (() => return 100)()\n  new A\n  4\nf()\n//│ ═══[RUNTIME ERROR] Error: Effect $_non$_local$_return$_effect$_24 is raised in a constructor\n//│ ═══[RUNTIME ERROR] Expected: '100', got: 'undefined'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/RecursiveHandlers.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nabstract class Effect[A] with\n  fun perform(arg: A): A\n\n\nhandle h1 = Effect with\n  fun perform(arg)(k) =\n    print(\"performing \" + arg)\n    [k(\"ok\")]\nh1.perform(\"hi\")\nh1.perform(\"hello\")\n//│ > performing hi\n//│ > performing hello\n//│ = [[\"ok\"]]\n\n:e\nh1\n//│ ╔══[COMPILATION ERROR] Name not found: h1\n//│ ║  l.20: \th1\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nh1.perform(\"oops\")\n//│ ╔══[COMPILATION ERROR] Name not found: h1\n//│ ║  l.27: \th1.perform(\"oops\")\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:re\nhandle h = Object with\n  fun write(x)(k) =\n    if x < 10 do write(10)\n    [x, k(())]\nh.write(1)\nh.write(2)\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$\n\nhandle h = Object with\n  fun write(x)(k) =\n    if x < 10 do\n      print(enterHandleBlock(this, () => write(10)))\n    [x, k(())]\nh.write(1)\nh.write(2)\n//│ > [10, ()]\n//│ > [10, ()]\n//│ = [1, [2, ()]]\n\nhandle h = Object with\n  fun write(x)(k) = enterHandleBlock of this, () =>\n    if x < 10 do write(10)\n    [x, k(())]\nh.write(1)\nh.write(2)\n//│ = [10, [1, [10, [2, ()]]]]\n\n// deep handler\n:todo\nhandle h2 = Effect with\n  fun perform(arg)(k) =\n    print(\"performing \" + arg)\n    k of if arg > 0\n      then h2.perform(arg - 1) + \" \" + arg\n      else \"0\"\n[\n  print(\"–––\");\n  h2.perform(2)\n  print(\"–––\");\n  h2.perform(3)\n]\n//│ ╔══[COMPILATION ERROR] Name not found: h2\n//│ ║  l.67: \t      then h2.perform(arg - 1) + \" \" + arg\n//│ ╙──      \t           ^^\n//│ ╔══[COMPILATION ERROR] Illegal position for prefix keyword 'else'.\n//│ ║  l.68: \t      else \"0\"\n//│ ╙──      \t      ^^^^\n//│ > –––\n//│ > performing 2\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n// passing additional handlers to the handler body\nlet res =\n  handle h = Effect with\n    fun perform(arg)(k) =\n      print(\"A \" + arg)\n      handle g = Effect with\n        fun perform(arg1)(k1) =\n          print(\"B \" + arg + \" \" + arg1)\n          [\"‹\", k1(arg), arg1, \"›\"]\n      [k(g)]\n  let g = h.perform(\"hi\")\n  g.perform(\"bye\")\n  g.perform(\"friend\")\n  set g = h.perform(\"hola\")\n  g.perform(\"adios\")\n  g.perform(\"amigos\")\nin res.toString()\n//│ > A hi\n//│ > B hi bye\n//│ > B hi friend\n//│ > A hola\n//│ > B hola adios\n//│ > B hola amigos\n//│ = \"‹,‹,‹,‹,hola,amigos,›,adios,›,friend,›,bye,›\"\n\n\n// This is equivalent to the above, with all calls to h.perform expanded\nlet res =\n  print(\"A \" + \"hi\")\n  handle g = Effect with\n    fun perform(arg1)(k1) =\n      print(\"B \" + \"hi\" + \" \" + arg1)\n      [\"‹\", k1(\"hi\"), arg1, \"›\"]\n  [(() =>\n    g.perform(\"bye\")\n    g.perform(\"friend\")\n    print(\"A \" + \"hola\")\n    handle g2 = Effect with\n      fun perform(arg1)(k1) =\n        print(\"B \" + \"hola\" + \" \" + arg1)\n        [\"‹\", k1(\"hola\"), arg1, \"›\"]\n    [(() =>\n      g2.perform(\"adios\")\n      g2.perform(\"amigos\")\n    )()]\n  )()]\nin res.toString()\n//│ > A hi\n//│ > B hi bye\n//│ > B hi friend\n//│ > A hola\n//│ > B hola adios\n//│ > B hola amigos\n//│ = \"‹,‹,‹,‹,hola,amigos,›,adios,›,friend,›,bye,›\"\n\n:sjs\nlet str = \"\"\nif true do\n  handle h1 = Effect with\n    fun perform(arg)(k) =\n      set str += \"A\"\n      k(arg)\n      set str += \"A\"\n  handle h2 = Effect with\n    fun perform(arg)(k) =\n      set str += str + \"B\"\n      k(arg)\n      set str += str + \"B\"\n  h2.perform(())\n  h1.perform(())\nstr\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let str, scrut, h11, handleBlock$9, Handler$h2$perform1, Handler$h2$3, handleBlock$10, Handler$h1$perform1, Handler$h1$3, handleBlock$$2, Handler$h2$perform$1, Handler$h1$perform$1;\n//│ runtime.resetEffects();\n//│ Handler$h1$perform$1 = function Handler$h1$perform$(arg) {\n//│   return (k) => {\n//│     return Handler$h1$perform1(arg, k)\n//│   }\n//│ };\n//│ Handler$h1$perform1 = function Handler$h1$perform(arg, k) {\n//│   let tmp10, tmp11, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   switch (pc) {\n//│     case 0:\n//│       tmp10 = str + \"A\";\n//│       str = tmp10;\n//│       runtime.resumeValue = runtime.safeCall(k(arg));\n//│       if (runtime.curEffect === null) {\n//│         pc = 1;\n//│       } else {\n//│         return runtime.unwind(Handler$h1$perform1, 1, \"RecursiveHandlers.mls:147:7\", null, null, 1, 2, arg, k, 0)\n//│       }\n//│     case 1:\n//│       runtime.resumeValue;\n//│       tmp11 = str + \"A\";\n//│       str = tmp11;\n//│       return runtime.Unit;\n//│   }\n//│ };\n//│ Handler$h2$perform$1 = function Handler$h2$perform$(arg) {\n//│   return (k) => {\n//│     return Handler$h2$perform1(arg, k)\n//│   }\n//│ };\n//│ Handler$h2$perform1 = function Handler$h2$perform(arg, k) {\n//│   let tmp10, tmp11, tmp12, tmp13, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   switch (pc) {\n//│     case 0:\n//│       tmp10 = str + \"B\";\n//│       tmp11 = str + tmp10;\n//│       str = tmp11;\n//│       runtime.resumeValue = runtime.safeCall(k(arg));\n//│       if (runtime.curEffect === null) {\n//│         pc = 1;\n//│       } else {\n//│         return runtime.unwind(Handler$h2$perform1, 1, \"RecursiveHandlers.mls:152:7\", null, null, 1, 2, arg, k, 0)\n//│       }\n//│     case 1:\n//│       runtime.resumeValue;\n//│       tmp12 = str + \"B\";\n//│       tmp13 = str + tmp12;\n//│       str = tmp13;\n//│       return runtime.Unit;\n//│   }\n//│ };\n//│ handleBlock$$2 = (undefined, function (h22) {\n//│   return () => {\n//│     return handleBlock$9(h22)\n//│   }\n//│ });\n//│ (class Handler$h2$2 extends Effect1 {\n//│   static {\n//│     Handler$h2$3 = this\n//│   }\n//│   constructor() {\n//│     let tmp10;\n//│     tmp10 = super();\n//│     if (runtime.curEffect === null) {\n//│       tmp10\n//│     } else {\n//│       tmp10 = runtime.illegalEffect(\"in a constructor\");\n//│       tmp10\n//│     }\n//│   }\n//│   perform(arg) {\n//│     let Handler$h2$perform$here;\n//│     Handler$h2$perform$here = Handler$h2$perform$1(arg);\n//│     return runtime.mkEffect(this, Handler$h2$perform$here)\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Handler$h2$\"]; \n//│ });\n//│ handleBlock$9 = (undefined, function (h22) {\n//│   let pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   switch (pc) {\n//│     case 0:\n//│       runtime.resumeValue = runtime.safeCall(h22.perform(runtime.Unit));\n//│       if (runtime.curEffect === null) {\n//│         pc = 1;\n//│       } else {\n//│         return runtime.unwind(handleBlock$9, 1, \"RecursiveHandlers.mls:154:3\", null, null, 1, 1, h22, 0)\n//│       }\n//│     case 1:\n//│       runtime.resumeValue;\n//│       return runtime.safeCall(h11.perform(runtime.Unit));\n//│   }\n//│ });\n//│ (class Handler$h1$2 extends Effect1 {\n//│   static {\n//│     Handler$h1$3 = this\n//│   }\n//│   constructor() {\n//│     let tmp10;\n//│     tmp10 = super();\n//│     if (runtime.curEffect === null) {\n//│       tmp10\n//│     } else {\n//│       tmp10 = runtime.illegalEffect(\"in a constructor\");\n//│       tmp10\n//│     }\n//│   }\n//│   perform(arg) {\n//│     let Handler$h1$perform$here;\n//│     Handler$h1$perform$here = Handler$h1$perform$1(arg);\n//│     return runtime.mkEffect(this, Handler$h1$perform$here)\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Handler$h1$\"]; \n//│ });\n//│ handleBlock$10 = (undefined, function () {\n//│   let h22, tmp10, handleBlock$$here, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   switch (pc) {\n//│     case 0:\n//│       h22 = new Handler$h2$3();\n//│       handleBlock$$here = handleBlock$$2(h22);\n//│       runtime.resumeValue = runtime.enterHandleBlock(h22, handleBlock$$here);\n//│       if (runtime.curEffect === null) {\n//│         pc = 1;\n//│       } else {\n//│         return runtime.unwind(handleBlock$10, 1, null, null, null, 1, 0, 0)\n//│       }\n//│     case 1:\n//│       tmp10 = runtime.resumeValue;\n//│       return tmp10;\n//│   }\n//│ });\n//│ str = \"\";\n//│ scrut = true;\n//│ if (scrut === true) {\n//│   h11 = new Handler$h1$3();\n//│   runtime.enterHandleBlock(h11, handleBlock$10);\n//│   if (runtime.curEffect === null) { str } else { runtime.topLevelEffect(false); str }\n//│ } else { str }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"BABABA\"\n//│ str = \"BABABA\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/ReturnInHandler.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class Effect with\n  fun f(): ()\n\n// `return` within handle blocks is implemented as a non-local return\nfun f() =\n  handle h = Effect with\n    fun foo()(r) =\n      let m = r(())\n      print(\"Bye!\") // This never executes because `r` returns from `f`\n      m\n  h.foo()\n  return 3 // Note: changing this to just `3` leads to `print(\"Bye!\")` executing\nf()\n//│ = 3\n\nfun f() =\n  handle h = Effect with\n    fun foo()(r) =\n      let m = r()\n      print(\"Bye!\")\n      m\n  in\n    h.foo()\n    return 3\n  10\n\n:expect 3\nf()\n//│ = 3\n\n:e\nlet l = () =>\n  handle h = Effect with\n    fun foo()(r) = r(())\n  return 3\n  4\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed outside of functions.\n//│ ║  l.40: \t  return 3\n//│ ╙──      \t  ^^^^^^^^\n//│ l = fun l\n\n:re\nl()\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nhandle h1 = Effect with\n  fun foo()(r) = r(())\nlet l = () =>\n  handle h2 = Effect with\n    fun bar()(r) = r(())\n  h1.foo()\n  return 3\n  4\nl()\n//│ ╔══[COMPILATION ERROR] Return statements are not allowed outside of functions.\n//│ ║  l.58: \t  return 3\n//│ ╙──      \t  ^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/SavedVars.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\n// This acts as a function that may throw an effect\nfun f() = ()\n\n// A constant function to block any potential optimization.\nfun always_true() = true\n\n\n// Observe that no local variables will be saved, as they are not needed.\n:sjs\nfun g() =\n  let a =\n    if always_true() then\n      f()\n      1\n    else\n      2\n  a\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let g;\n//│ runtime.resetEffects();\n//│ g = function g() {\n//│   let a, scrut, tmp, pc;\n//│   if (runtime.resumePc === -1) {\n//│     pc = 0;\n//│   } else {\n//│     pc = runtime.resumePc;\n//│     runtime.resumePc = -1;\n//│   }\n//│   main: while (true) {\n//│     switch (pc) {\n//│       case 0:\n//│         runtime.resumeValue = always_true();\n//│         if (runtime.curEffect === null) {\n//│           pc = 3;\n//│         } else {\n//│           return runtime.unwind(g, 3, \"SavedVars.mls:17:8\", null, null, 1, 0, 0)\n//│         }\n//│       case 3:\n//│         scrut = runtime.resumeValue;\n//│         if (scrut === true) {\n//│           runtime.resumeValue = f();\n//│           if (runtime.curEffect === null) {\n//│             pc = 2;\n//│             continue main\n//│           }\n//│           return runtime.unwind(g, 2, \"SavedVars.mls:18:7\", null, null, 1, 0, 0);\n//│         }\n//│         tmp = 2;\n//│         pc = 1;\n//│         continue main;\n//│       case 2:\n//│         runtime.resumeValue;\n//│         tmp = 1;\n//│         pc = 1;\n//│         if (pc === 1) { a = tmp; return a }\n//│         break;\n//│       case 1:\n//│         a = tmp;\n//│         return a;\n//│     }\n//│     break;\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/SetInHandlers.mls",
    "content": ":js\n\n\n// * This feature relies on `finally`\n:sjs\nlet x = 1\nset x += 1 in print(x)\nx\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x, old, tmp;\n//│ x = 1;\n//│ old = x;\n//│ try { tmp = x + 1; x = tmp; Predef.print(x); } finally { x = old; }\n//│ x\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n//│ = 1\n//│ x = 1\n\n\n// * But `finally` is not yet supported by effect handlers\n\n:todo\n:effectHandlers\n:lift\nlet x = 1\nhandle h = Object with\n  fun test()(k) =\n    print(\"SUSPENDING\")\n    let res = k(42)\n    print(\"DONE\")\n    res\nset x += 1 in\n  print(\"init\")\n  print(h.test())\n  print(x)\n  print(\"end\")\nx\n//│ ╔══[COMPILATION ERROR] Backtracking assignment is not supported with effect handlers enabled\n//│ ║  l.33: \tset x += 1 in\n//│ ║        \t    ^^^^^^^^^\n//│ ║  l.34: \t  print(\"init\")\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ║  l.35: \t  print(h.test())\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.36: \t  print(x)\n//│ ║        \t^^^^^^^^^^\n//│ ║  l.37: \t... (more lines omitted) ...\n//│ ╙──      \t^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n//│ x = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/StackSafety.mls",
    "content": ":js\n:effectHandlers\n:lift\n:noTailRec\n\n\n// preserve tail calls\n// MUST see \"return hi(tmp1)\" in the output\n:stackSafe 6\n:expect 0\n:sjs\nfun hi(n) =\n  if n === 0 then 0\n  else hi(n - 1)\nhi(0)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let hi, tmp, $_stack$_safe$_body$_;\n//│ runtime.resetEffects();\n//│ hi = function hi(n) {\n//│   runtime.stackDepth = runtime.stackDepth + 1;\n//│   runtime.checkDepth();\n//│   if (runtime.curEffect === null) {\n//│     let scrut, tmp1;\n//│     scrut = n === 0;\n//│     if (scrut === true) {\n//│       return 0\n//│     }\n//│     {\n//│       tmp1 = n - 1;\n//│       return hi(tmp1);\n//│     }\n//│   }\n//│   return runtime.unwind(hi, -1, \"StackSafety.mls:12:1\", null, null, 1, 1, n, 0);\n//│ };\n//│ $_stack$_safe$_body$_ = (undefined, function () {\n//│   return hi(0)\n//│ });\n//│ tmp = runtime.runStackSafe(6, $_stack$_safe$_body$_);\n//│ if (runtime.curEffect === null) { tmp } else { tmp = runtime.topLevelEffect(false); tmp }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:stackSafe\n:expect 50005000\n:sjs\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nsum(10000)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let sum, tmp1, $_stack$_safe$_body$_1;\n//│ runtime.resetEffects();\n//│ sum = function sum(n) {\n//│   let curDepth;\n//│   runtime.stackDepth = runtime.stackDepth + 1;\n//│   curDepth = runtime.stackDepth;\n//│   runtime.checkDepth();\n//│   if (runtime.curEffect === null) {\n//│     let scrut, tmp2, tmp3, pc;\n//│     if (runtime.resumePc === -1) {\n//│       pc = 0;\n//│     } else {\n//│       pc = runtime.resumePc;\n//│       runtime.resumePc = -1;\n//│     }\n//│     switch (pc) {\n//│       case 0:\n//│         scrut = n === 0;\n//│         if (scrut === true) {\n//│           return 0\n//│         }\n//│         {\n//│           let res;\n//│           tmp2 = n - 1;\n//│           res = sum(tmp2);\n//│           runtime.stackDepth = curDepth;\n//│           runtime.resumeValue = res;\n//│           if (runtime.curEffect === null) {\n//│             pc = 1;\n//│           } else {\n//│             return runtime.unwind(sum, 1, \"StackSafety.mls:49:9\", null, null, 1, 1, n, 0)\n//│           }\n//│         }\n//│       case 1:\n//│         tmp3 = runtime.resumeValue;\n//│         return n + tmp3;\n//│     }\n//│   } else {\n//│     return runtime.unwind(sum, -1, \"StackSafety.mls:46:1\", null, null, 1, 1, n, 0)\n//│   }\n//│ };\n//│ $_stack$_safe$_body$_1 = (undefined, function () {\n//│   return sum(10000)\n//│ });\n//│ tmp1 = runtime.runStackSafe(1000, $_stack$_safe$_body$_1);\n//│ if (runtime.curEffect === null) { tmp1 } else { tmp1 = runtime.topLevelEffect(false); tmp1 }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 50005000\n\n\n:stackSafe\nmut val ctr = 0\nfun dummy(x) = x\nfun foo(f) = \n  if ctr > 10000 then 0\n  else \n    set ctr += 1\n    dummy(f(f))\nfoo(foo)\n//│ = 0\n//│ ctr = 10001\n\n:stackSafe\n:expect 50005000\nval foo =\n  val f = n =>\n    if n <= 0 then 0\n    else n + f(n-1)\n  f(10000)\nfoo\n//│ = 50005000\n//│ foo = 50005000\n\n:stackSafe 100\n:expect 50005000\nval foo =\n  val f = n =>\n    if n <= 0 then 0\n    else n + f(n-1)\n  f(10000)\nfoo\n//│ = 50005000\n//│ foo = 50005000\n\nabstract class Eff with\n  fun perform(a): ()\n\n// functions and lambdas inside handlers\n:stackSafe 100\n:expect 50005000\nfun foo(h) = h.perform()\nhandle h = Eff with\n  fun perform()(resume) =\n    let f = ()\n    set f = n =>\n      if n <= 0 then 0\n      else n + f(n-1)\n    resume(f(10000))\nfoo(h)\n//│ = 50005000\n\n// function call and defn inside handler\n:stackSafe 100\n:expect 50005000\nhandle h = Eff with\n  fun perform()(resume) =\n    let f = ()\n    set f = n =>\n      if n <= 0 then 0\n      else n + f(n-1)\n    resume(f(10000))\nin\n  fun foo(h) = h.perform()\n  foo(h)\n//│ = 50005000\n\n:stackSafe 100\n:expect 50005000\nmodule A with\n  val f = n =>\n    if n <= 0 then 0\n    else n + f(n-1)\n  val x = f(10000)\nA.x\n//│ = 50005000\n\n:re\nfun foo(h) = h.perform(2)\nhandle h = Eff with\n  fun perform(a)(resume) =\n    let f = ()\n    set f = n =>\n      if n <= 0 then 0\n      else n + f(n-1)\n    resume(f(10000))\nfoo(h)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n:stackSafe\n:sjs\nfun max(a, b) = if a < b then b else a\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let max;\n//│ runtime.resetEffects();\n//│ max = function max(a, b) { let scrut; scrut = a < b; if (scrut === true) { return b } return a; };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:stackSafe\n:expect 100010000\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nfun bad() = sum(10000) + sum(10000)\nbad()\n//│ = 100010000\n\n\n\n:stackSafe 100\n:expect 0\nlet depth = 0\nhandle h = Object with\n  fun whoops()(k) =\n    if depth >= 50000 then 0\n    else\n      set depth += 1\n      enterHandleBlock(this, () => whoops())\nh.whoops()\n//│ = 0\n//│ depth = 50000\n\n// TODO: the stack depth is not accurately tracked in the runtime functions\n// for now this works, but it's not very safe\n:stackSafe\n:expect 10000\nfun dummy = ()\nfun f(h) =\n  let n = 0\n  while n < 10000 do\n    h.perform()\n    set n += 1\n  n\nhandle h = Object with\n  fun perform()(k) = \n    k()\nf(h)\n//│ = 10000\n\n:stackSafe\nfun trivial() = ()\nfun f(n) =\n  trivial()\n  if n >= 0 do\n    f(n-1)\n  trivial()\nf(10000)\n\nabstract class Eff with\n  fun raise()\n\n:re\nfun shift_stack(n, f) =\n  if n >= 0 then\n    shift_stack(n - 1, f)\n  else\n    f()\nfun handler_stack(n) =\n  handle h = Eff with\n    fun raise()(k) =\n      shift_stack(100, k)\n  h.raise()\n  if n >= 0 do\n    handler_stack(n - 1)\n  \"ok\"\nhandler_stack(100)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\n// This test was failing non-deterministically due to handler state not being properly reset.\n// The flakiness was due to the stack overflow in the previous block not always interrupting the code in the same place,\n// sometimes leaving the effect handlers runtime in an inconsistent state.\n:silent\nlet\n  N = 100\n  M = 100\n\n:stackSafe\nfun shift_stack(n, f) =\n  if n >= 0 then\n    shift_stack(n - 1, f)\n  else\n    f()\nfun handler_stack(n) =\n  handle h = Eff with\n    fun raise()(k) =\n      shift_stack(N, k)\n  h.raise()\n  if n >= 0 do\n    handler_stack(n - 1)\n  \"ok\"\nhandler_stack(M)\n//│ = \"ok\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/TailCallOptimization.mls",
    "content": ":js\n:effectHandlers\n:lift\n\nabstract class StackDelay with\n  fun perform(): ()\n\n:expect 3\nhandle h = StackDelay with\n  fun perform()(resume) = resume()\nfun foo(x) =\n  h.perform()\n  x + 4\nfun bar(y) =\n  h.perform()\n  // tail call\n  foo(y + 2)\nfun foobar(z) =\n  bar(z + 1)\n  // stuff after tail call is linked differently\n  3\nfoobar(0)\n//│ = 3\n\n\n// Check that tail call optimization is applied in presence of effect handlers: there should be no function calls in the body.\n:sjs\n:expect 0\n:stackSafe\n:sjs\nfun hi(n) =\n  if n === 0 then 0\n  else hi(n - 1)\nhi(0)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let hi, tmp1, $_stack$_safe$_body$_;\n//│ runtime.resetEffects();\n//│ hi = function hi(n) {\n//│   loopLabel: while (true) {\n//│     runtime.stackDepth = runtime.stackDepth + 1;\n//│     runtime.checkDepth();\n//│     if (runtime.curEffect === null) {\n//│       let scrut, tmp2;\n//│       scrut = n === 0;\n//│       if (scrut === true) {\n//│         return 0\n//│       }\n//│       {\n//│         tmp2 = n - 1;\n//│         n = tmp2;\n//│         continue loopLabel;\n//│       }\n//│     }\n//│     return runtime.unwind(hi, -1, \"TailCallOptimization.mls:31:1\", null, null, 1, 1, n, 0);\n//│   }\n//│ };\n//│ $_stack$_safe$_body$_ = (undefined, function () {\n//│   return hi(0)\n//│ });\n//│ tmp1 = runtime.runStackSafe(1000, $_stack$_safe$_body$_);\n//│ if (runtime.curEffect === null) { tmp1 } else { tmp1 = runtime.topLevelEffect(false); tmp1 }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/UserThreads.mls",
    "content": ":js\n:effectHandlers\n:lift\n\n\nabstract class ThreadEffect with\n  val tasks = mut []\n  fun start(thread: () -> ()): ()\n  fun fork(thread: () -> ()): ()\n  fun yld(): ()\n\nclass Lock(val locked) with\n  fun lock(th: ThreadEffect) =\n    while locked do\n      th.yld()\n    set locked = true\n  fun unlock() =\n    set locked = false\n\nfun f(h, x) =\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n\nfun main(h) =\n  print(\"main start\")\n  h.fork(() => f(h, 0))\n  h.fork(() => f(h, 1))\n  h.fork(() => f(h, 2))\n  print(\"main end\")\n\n\n// LIFO\nhandle h = ThreadEffect with\n  fun fork(thread)(k) =\n    this.tasks.unshift(thread)\n    k(())\n  fun yld()(k) =\n    this.tasks.push(() => k(()))\n    enterHandleBlock(this, () => this.tasks.shift()())\n  fun start(main)(k) =\n    this.tasks.push(() => main(this))\n    while this.tasks.length != 0 do\n      enterHandleBlock(this, () => this.tasks.shift()())\n    k(())\nin\n  h.start(main)\n//│ > main start\n//│ > main end\n//│ > f 2\n//│ > f 1\n//│ > f 0\n//│ > f 2\n//│ > f 1\n//│ > f 0\n//│ > f 2\n//│ > f 1\n//│ > f 0\n\n\n// FIFO\nhandle h = ThreadEffect with\n  fun fork(thread)(k) =\n    this.tasks.push(thread)\n    k(())\n  fun yld()(k) =\n    this.tasks.push(() => k(()))\n    enterHandleBlock(this, () => this.tasks.shift()())\n  fun start(main)(k) =\n    this.tasks.push(() => main(this))\n    while this.tasks.length != 0 do\n      enterHandleBlock(this, () => this.tasks.shift()())\n    k(())\nin\n  h.start(main)\n//│ > main start\n//│ > main end\n//│ > f 0\n//│ > f 1\n//│ > f 2\n//│ > f 0\n//│ > f 1\n//│ > f 2\n//│ > f 0\n//│ > f 1\n//│ > f 2\n\n\n// Adapted from: https://ocaml.org/manual/5.3/effects.html\n\nabstract class ThreadEffect with\n  fun fork(thread: ThreadEffect -> ()): ()\n  fun yld(): ()\n\nval tasks = mut []\n//│ tasks = []\n\nfun f(x)(h) =\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n\nfun main(h) =\n  print(\"main start\")\n  h.fork(f(0))\n  h.fork(f(1))\n  h.fork(f(2))\n  print(\"main end\")\n\nfun dequeue() =\n  if tasks.length != 0 do\n    tasks.shift()(())\n\nfun start(thread: ThreadEffect -> ()) =\n  handle h = ThreadEffect with\n    fun fork(new_thread)(k) =\n      tasks.push(k)\n      start(new_thread)\n    fun yld()(k) =\n      tasks.push(k)\n      dequeue()\n  in\n    thread(h)\n  dequeue()\n\nstart(main)\n//│ > main start\n//│ > f 0\n//│ > f 1\n//│ > f 0\n//│ > f 2\n//│ > f 1\n//│ > f 0\n//│ > main end\n//│ > f 2\n//│ > f 1\n//│ > f 2\n\n\nimport \"../../mlscript-compile/Option.mls\"\nopen Option\n\nabstract class ThreadEffect with\n  fun fork(thread: ThreadEffect -> ()): ()\n  fun yld(): ()\n  fun xchg(x: Int): Int\n\nval tasks = mut []\nfun enqueue(k, x) =\n  tasks.push(() => k(x))\nfun dequeue() =\n  if tasks.length != 0 do\n    tasks.shift()()\n//│ tasks = []\n\nlet exchanger = None\n//│ exchanger = None\n\nfun start(thread: ThreadEffect -> ()) =\n  handle h = ThreadEffect with\n    fun fork(new_thread)(k) =\n      enqueue(k, ())\n      start(new_thread)\n    fun yld()(k) =\n      enqueue(k, ())\n      dequeue()\n    fun xchg(x)(k) =\n      if exchanger is\n        Some([y, k1]) then\n          set exchanger = None\n          enqueue(k1, x)\n          k(y)\n        None then\n          set exchanger = Some([x, k])\n          dequeue()\n  in\n    thread(h)\n  dequeue()\n\nfun main(h) =\n  h.fork(h =>\n    print(\"[t1] Sending 0\")\n    let v = h.xchg(0)\n    print(\"[t1] received \" + v.toString()))\n  h.fork(h =>\n    print(\"[t2] Sending 1\")\n    let v = h.xchg(1)\n    print(\"[t2] received \" + v.toString()))\n\nstart(main)\n//│ > [t1] Sending 0\n//│ > [t2] Sending 1\n//│ > [t2] received 0\n//│ > [t1] received 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/UserThreadsSafe.mls",
    "content": ":js\n:effectHandlers debug\n:lift\n\n\nclass ThreadEffect with\n  // task queue\n  val tasks = mut []\n  fun drain() =\n    while tasks.length != 0 do\n      tasks.pop()()\n  fun fork(thread: () -> ()): ()\n  fun yld(): ()\n\n\nfun f(h, x)() =\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n\nfun main(h) =\n  print(\"main start\")\n  h.fork(f(h, 0))\n  h.fork(f(h, 1))\n  h.fork(f(h, 2))\n  print(\"main end\")\n\n\n// LIFO\n:re\nhandle h = ThreadEffect with\n  fun fork(thread)(k) =\n    this.tasks.push(thread)\n    k()\n    this.drain()\n  fun yld()(k) =\n    this.tasks.unshift(k)\n    this.drain()\nin\n  main(h)\n//│ > main start\n//│ > main end\n//│ > f 2\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$\n//│ \tat f (UserThreadsSafe.mls:18:3)\n//│ \tat while (UserThreadsSafe.mls:11:7)\n//│ \tat ThreadEffect#drain (pc=1)\n//│ \tat Handler$h$fork (UserThreadsSafe.mls:36:5)\n//│ \tat Handler$h$fork (UserThreadsSafe.mls:36:5)\n\n\n// FIFO\n:re\nhandle h = ThreadEffect with\n  fun fork(thread)(k) =\n    this.tasks.unshift(thread)\n    k()\n    this.drain()\n  fun yld()(k) =\n    this.tasks.unshift(k)\n    this.drain()\nin\n  main(h)\n//│ > main start\n//│ > main end\n//│ > f 0\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$2\n//│ \tat f (UserThreadsSafe.mls:18:3)\n//│ \tat while (UserThreadsSafe.mls:11:7)\n//│ \tat ThreadEffect#drain (pc=1)\n//│ \tat Handler$h$fork (UserThreadsSafe.mls:59:5)\n//│ \tat Handler$h$fork (UserThreadsSafe.mls:59:5)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/UserThreadsUnsafe.mls",
    "content": ":js\n:effectHandlers debug\n:lift\n\n\nclass ThreadEffect with\n  fun fork(thread: () -> ()): ()\n  fun yld(): ()\n\n\nfun f(h, x)() =\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n  h.yld()\n  print(\"f \" + x)\n\nfun main(h) =\n  print(\"main start\")\n  h.fork(f(h, 0))\n  h.fork(f(h, 1))\n  h.fork(f(h, 2))\n  print(\"main end\")\n\n\n// task queue\nlet tasks = mut []\nfun drain() =\n  while tasks.length != 0 do\n    tasks.pop()()\n//│ tasks = []\n\n\n// LIFO\n:re\nhandle h = ThreadEffect with\n  fun fork(thread)(k) =\n    tasks.push(thread)\n    k()\n    drain()\n  fun yld()(k) =\n    tasks.unshift(k)\n    drain()\nin\n  main(h)\n//│ > main start\n//│ > main end\n//│ > f 2\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$\n//│ \tat f (UserThreadsUnsafe.mls:13:3)\n//│ \tat while (UserThreadsUnsafe.mls:30:5)\n//│ \tat drain (pc=1)\n//│ \tat Handler$h$fork (UserThreadsUnsafe.mls:39:5)\n//│ \tat Handler$h$fork (UserThreadsUnsafe.mls:39:5)\n\n\n// FIFO\n:re\nhandle h = ThreadEffect with\n  fun fork(thread)(k) =\n    tasks.unshift(thread)\n    k()\n    drain()\n  fun yld()(k) =\n    tasks.unshift(k)\n    drain()\nin\n  main(h)\n//│ > main start\n//│ > main end\n//│ > f 1\n//│ ═══[RUNTIME ERROR] Error: Unhandled effect Handler$h$\n//│ \tat f (UserThreadsUnsafe.mls:13:3)\n//│ \tat while (UserThreadsUnsafe.mls:30:5)\n//│ \tat drain (pc=1)\n//│ \tat Handler$h$fork (UserThreadsUnsafe.mls:62:5)\n//│ \tat Handler$h$fork (UserThreadsUnsafe.mls:62:5)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/handlers/ZCombinator.mls",
    "content": ":js\n:effectHandlers\n:lift\n:stackSafe\n\nfun selfApp(f) = f(f)\n\nfun mkrec(g) =\n  selfApp of self =>\n    g of y => self(self)(y)\n\nlet fact = mkrec of self => x =>\n  if x == 0 then 1 else self(x - 1) * x\n//│ fact = fun\n\nfact(3)\n//│ = 6\n\nfact(10)\n//│ = 3628800\n\n:re\n:stackSafe off\nfact(10000)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n:stackSafe\nfun mkrec(g) =\n  selfApp of self =>\n    g of y => selfApp(self)(y)\n\n// * FIXME: Why doesn't the following work when using Predef function `(==) equals`?\nlet fact = mkrec of self => x =>\n  if x === 0 then 1 \n  else self(x - 1) * x\n//│ fact = fun\n\n:stackSafe\nfact(10000)\n//│ = Infinity\n\n// * Without `:stackSafe`, gives `RangeError: Maximum call stack size exceeded`\n:re\n:stackSafe off\nfact(10000)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n:stackSafe\nfact(10000)\n//│ = Infinity\n\n:re\n:stackSafe off\nfact(10000)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\n:stackSafe 6\nset selfApp = f => f(f)\n\n:expect 3628800\nfact(10)\n//│ = 3628800\n\n\n:stackSafe 6\nset selfApp = f => f(f)\n\nfact(1000)\n//│ = Infinity\n\n// simplified version without lambdas for easier debugging\n:stackSafe 6\nfun mkrec(g) =\n  fun a(self) =\n    fun b(y) = selfApp(self)(y)\n    g(b)\n  selfApp(a)\n\n:stackSafe 6\nimport \"../../mlscript-compile/Runtime.mls\"\nlet fact =\n  fun a(self) =\n    fun b(x) =\n      if x == 0 then 1 else\n        let prev = self(x - 1)\n        console.log(\"resumed:\", x)\n        x * prev\n    b\n  mkrec(a)\n//│ fact = fun\n\n:expect 3628800\n:stackSafe 6\nfact(10)\n//│ > resumed: 1\n//│ > resumed: 2\n//│ > resumed: 3\n//│ > resumed: 4\n//│ > resumed: 5\n//│ > resumed: 6\n//│ > resumed: 7\n//│ > resumed: 8\n//│ > resumed: 9\n//│ > resumed: 10\n//│ = 3628800\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/Arrays.mls",
    "content": ":js\n\n\nlet arr = [true, false]\n//│ arr = [true, false]\n\n\n// * Array methods annoyingly supply extra arguments, such as the index and the array itself\n:re\narr.map(_ === false)\n//│ ═══[RUNTIME ERROR] Error: Function expected 1 argument but got 3\n\n:sjs\narr.map((e, ...) => e === false)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda1;\n//│ lambda1 = (undefined, function (e, ..._) { return e === false });\n//│ runtime.safeCall(arr.map(lambda1))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [false, true]\n\n:sjs\narr.map((_, ...) => 1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda2;\n//│ lambda2 = (undefined, function (_, ..._1) { return 1 });\n//│ runtime.safeCall(arr.map(lambda2))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [1, 1]\n\n:e\narr.map((..., ...) => 1)\n//│ ╔══[COMPILATION ERROR] Spread parameters must be the last in the parameter list.\n//│ ║  l.32: \tarr.map((..., ...) => 1)\n//│ ╙──      \t         ^^^\n//│ = [1, 1]\n\n:e\n:re\narr.map((..., e) => e)\n//│ ╔══[COMPILATION ERROR] Spread parameters must be the last in the parameter list.\n//│ ║  l.40: \tarr.map((..., e) => e)\n//│ ╙──      \t         ^^^\n//│ ═══[RUNTIME ERROR] Error: Function expected 2 arguments but got 3\n\narr.map(pass1(_ === false))\n//│ = [false, true]\n\n\n[1,3,2].map((x, _, _) => x + 1).sort()\n//│ = [2, 3, 4]\n\n[1,3,2].map((x, _, _) => x + 1)\n  .sort()\n//│ = [2, 3, 4]\n\n\nArray\n//│ = class Array\n\nArray(1)\n//│ = [<1 empty items>]\n\n:breakme // TODO better report an error, here\n:e\nArray()\n//│ = []\n\n:breakme // TODO better report an error, here\n:e\nArray(1, 2, 3)\n//│ = [1, 2, 3]\n\n\nif arr is Array then \"ok\"\n//│ = \"ok\"\n\n:fixme // TODO handle?\nif arr is Array(n) then n\n//│ ╔══[COMPILATION ERROR] Class Array does not have a parameter list\n//│ ║  l.79: \tif arr is Array(n) then n\n//│ ║        \t          ^^^^^\n//│ ╟── but the pattern has one sub-pattern\n//│ ║  l.79: \tif arr is Array(n) then n\n//│ ╙──      \t                ^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/CtorBypass.mls",
    "content": ":js\n\n\nclass A with\n  print(\"ok\")\n  val n = 123\n  Object.freeze(this)\n\nlet a = new A\n//│ > ok\n//│ a = A { n: 123 }\n\na.n\n//│ = 123\n\nA.prototype\n//│ = {}\n\n// * This can be used for deserialization\nlet b = Object.create(A.prototype)\n//│ b = A\n\n:sjs\nb is A\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ if (b instanceof A1) { true } else { false }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\n:re\nb.n\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'n' yielded 'undefined'\n\nset b.n = 0\n\nb.n\n//│ = 0\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/Functions.mls",
    "content": ":js\n\n\n(x => x).constructor == Function\n//│ = true\n\nfun foo(x) = x\nfoo.constructor == Function\n//│ = true\n\nfoo.name\n//│ = \"foo\"\n\nfoo.constructor.name\n//│ = \"Function\"\n\ntypeof(foo)\n//│ = \"function\"\n\ntypeof(foo.constructor)\n//│ = \"function\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/JSCollections.mls",
    "content": ":js\n\n\nlet xs = new Set of [0, 1, 2]\n//│ xs = Set(3) {0, 1, 2}\n\nlet xs = new Set of tuple of 0, 1, 2\n//│ xs = Set(3) {0, 1, 2}\n\nxs.size\n//│ = 3\n\nxs.add(3)\n//│ = Set(4) {0, 1, 2, 3}\n\nxs.has(1)\n//│ = true\n\nxs.has(3)\n//│ = true\n\nxs.size\n//│ = 4\n\n\nlet xs = new Map([[1, \"a\"],[2, \"b\"]])\n//│ xs = Map(2) {1 => \"a\", 2 => \"b\"}\n\nxs.size\n//│ = 2\n\nxs.get(1)\n//│ = \"a\"\n\nxs.set(3, \"c\")\n//│ = Map(3) {1 => \"a\", 2 => \"b\", 3 => \"c\"}\n\nxs.size\n//│ = 3\n\nxs.get(3)\n//│ = \"c\"\n\nxs.set(1, \"_\")\n//│ = Map(3) {1 => \"_\", 2 => \"b\", 3 => \"c\"}\n\nxs.size\n//│ = 3\n\nxs.get(1)\n//│ = \"_\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/JSDerp.mls",
    "content": ":js\n\n\nObject.create(()) is Object\n//│ = true\n\nObject.create(new Number()) is Object\n//│ = true\n\nObject.create(null) is Object\n//│ = false\n\nObject(0) is Object\n//│ = true\n\n(new Object(0)) is Object\n//│ = true\n\nNumber(0) is Object\n//│ = false\n\nNumber(0) is Number\n//│ = false\n\n(new Number(0)) is Object\n//│ = true\n\n(new Number(0)) is Number\n//│ = true\n\n\nlet arr = [[1], [1, 1], [2, 1], [1, 2, 1, 1]]\n//│ arr = [[1], [1, 1], [2, 1], [1, 2, 1, 1]]\n\narr.toString()\n//│ = \"1,1,1,2,1,1,2,1,1\"\n\nset Array.prototype.toString = globalThis.eval(\"(function() { return '(' + Array.prototype.join.call(this, ',') + ')'; })\")\n\narr.toString()\n//│ = \"((1),(1,1),(2,1),(1,2,1,1))\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/Null.mls",
    "content": ":js\n\n\nnull == undefined\n//│ = false\n\nnull === undefined\n//│ = false\n\nnull === null\n//│ = true\n\nconsole.log(null is null)\n//│ > true\n\nObject.create(null).(\"toString\") is undefined\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/Number.mls",
    "content": ":js\n\n\nglobalThis.Number(\"0.50\")\n//│ = 0.5\n\n\nlet num = _ globalThis.Number()\n//│ num = fun num\n\nnum(\"0.50\")\n//│ = 0.5\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/Objects.mls",
    "content": ":js\n\n\nlet rcd = { x: 0, y: undefined, z: null}\n//│ rcd = {x: 0, y: undefined, z: null}\n\nrcd.constructor\n//│ = class Object\n\ntypeof(rcd.constructor)\n//│ = \"function\"\n\nObject.entries of rcd\n//│ = [[\"x\", 0], [\"y\", undefined], [\"z\", null]]\n\n\nclass Foo(val x, val y) with\n  let z = 2\n  val a = 3\n  fun f = 4\n  fun g() = 5\n\nlet foo = Foo(1,2)\n//│ foo = Foo(1, 2)\n\n\nObject.entries of Foo\n//│ = [[\"class\", class Foo]]\n\nObject.entries of foo\n//│ = [[\"x\", 1], [\"y\", 2], [\"a\", 3]]\n\nFoo.name\n//│ = \"Foo\"\n\nFoo.class.name\n//│ = \"Foo\"\n\nfoo.constructor\n//│ = class Foo\n\n// ! will be changed by minification\nfoo.constructor.name\n//│ = \"Foo\"\n\ntypeof(foo)\n//│ = \"object\"\n\ntypeof(foo.constructor)\n//│ = \"function\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/Symbols.mls",
    "content": ":js\n\n\n:expect false\nSymbol(\"123\") === Symbol(\"123\")\n//│ = false\n\n:expect true\nSymbol.for(\"123\") === Symbol.for(\"123\")\n//│ = true\n\n:expect false\nSymbol.for(\"123\") === Symbol(\"123\")\n//│ = false\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/interop/Virtualization.mls",
    "content": ":js\n\n\n// * `try`/`catch`\n\njs.try_catch(() => 123, id)\n//│ = 123\n\njs.try_catch(() => 123(), id)\n//│ = TypeError: 123 is not a function\n\njs.try_catch of\n  () => 123()\n  case { TypeError then 666, e then throw e }\n//│ = 666\n\n:re\njs.try_catch of\n  () => throw Error(\"whoops\")\n  case TypeError then 666\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\njs.try_catch of\n  () => throw Error(\"whoops\")\n  case { TypeError then 666, e then throw e }\n//│ ═══[RUNTIME ERROR] Error: whoops\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLAuthorResponse.mls",
    "content": ":invalml\n\n\n\n\nfun wield: [R] -> (Region[out R]) ->{R} ()\nfun freeze: [R, E extends ~R, T] -> (Region[out R], () ->{~R & E} T) ->{R | E} T\n\nfun (;) seq(_, res) = res\nfun rand: () -> Bool\nfun print: Any -> ()\n\n\n\n// ### Example 1\n\n\nfun foo1(r1, r2) =\n  freeze(r1, () => print(\"ok\"))\n  wield(r2)\n\nregion r in\n  foo1(r, r)\n\nregion r in\n  region s in\n    foo1(r, s)\n\n\nregion r0 in\n  \n  fun foo1(r1, r2) =\n    freeze(r1, () => wield(r0))\n    wield(r2)\n  \n  region r in\n    foo1(r, r)\n  \n  region r in\n    region s in\n      foo1(r, s)\n\n\n\nfun foo2(r1, r2) =\n  freeze(r1, () => wield(r2))\n  wield(r2)\n\n:e\nregion r in\n  foo2(r, r)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type 'r2\n//│ ║  l.51: \t  foo2(r, r)\n//│ ║        \t          ^\n//│ ╟── because: cannot constrain  Region[in ⊥ out r]  <:  'r2\n//│ ╟── because: cannot constrain  Region[in ⊥ out r]  <:  Region[in ⊥ out 'R]\n//│ ╟── because: cannot constrain  r  <:  'R\n//│ ╟── because: cannot constrain  r  <:  'E\n//│ ╟── because: cannot constrain  r  <:  ¬'R1\n//│ ╟── because: cannot constrain  'R1  <:  ¬r\n//│ ╙── because: cannot constrain  r  <:  ¬r\n\nregion r in\n  region s in\n    foo2(r, s)\n\n\n\n// ### Example 2\n\n\nfun foo: [outer, R extends outer] -> Region[R] ->{outer} ()\nfun foo(r1) =\n  region r2 in\n    freeze(r2, () =>\n      wield(r1)\n    )\nfoo\n//│ Type: [outer, 'R] -> (Region['R]) ->{outer} ()\n//│ Where:\n//│   'R <: outer\n\nfun foo': [outer] -> Region[outer] ->{outer} ()\nfun foo'(r) = foo(r)\n\nfun foo: [outer] -> Region[outer] ->{outer} ()\nfun foo(r1) =\n  region r2 in\n    freeze(r2, () =>\n      wield(r1)\n    )\nfoo\n//│ Type: [outer] -> (Region[outer]) ->{outer} ()\n\nfun foo: [outer, R extends outer] -> Region[R] ->{outer} ()\nfun foo'(r) = foo(r)\n\n\n// ### Example 3\n\n\nfun foo(r1, r2, f) =\n  let exec = freeze(r1, () => freeze(r2, () => f(r1, r2)))\n  let r = exec()\n  !(r) + 1\n\nregion r in\n  region s in\n    foo(r, s, (x, y) =>\n      if rand() then print(\"Chose x\"); () => x.ref 0\n                else print(\"Chose y\"); () => y.ref 1)\n//│ Type: Int\n\n// TODO: simplify this type more!\nfoo\n//│ Type: ['r1, 'r2, 'R, 'E, 'R1, 'eff, 'reg, 'ref] -> ('r1, 'r2, ('r1, 'r2) ->{(('E ∧ ¬'R) ∧ ¬'R1) ∧ ¬'R1} (() ->{'eff} Ref['ref, out 'reg])) ->{(('reg ∨ 'R) ∨ 'E) ∨ 'eff} Int\n//│ Where:\n//│   'r1 <: Region[out 'R]\n//│   'E <: ¬'R\n//│   'R1 <: 'E\n//│   'R1 <: ¬'R\n//│   'r2 <: Region[out 'R1]\n//│   'ref <: Int\n\n\n\n\n// *** NOT CURRENTLY USED IN RESPONSE ***\n\n\nfun wield: [R] -> (Region[out R]) ->{R} ()\nfun freeze: [R, E extends ~R, T] -> (Region[out R], () ->{~R | E} T) ->{E} T\n\n\nfun foo(r1, r2, f) =\n  let r = freeze(r1, () => freeze(r2, () => f(r1, r2)))\n  wield(r)\n\nregion r in\n  foo(r, r, (x, y) => if rand() then x else y)\n\nregion r in\n  region s in\n    foo(r, s, (x, y) => if rand() then x else y)\n\n\n\n// *** NOTES ***\n\n\n// Doesn't type check because r.ref has effect r\n\nfun foo(r1, r2, f) =\n  let r = freeze(r1, () => freeze(r2, () => f(r1, r2)))\n  r := !(r) + 1\n\n:e\nregion r in\n  region s in\n    foo(r, s, (x, y) => (if rand() then x.ref 0 else y.ref 0))\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type 'f\n//│ ║  l.160: \t    foo(r, s, (x, y) => (if rand() then x.ref 0 else y.ref 0))\n//│ ║         \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  ('x, 'y) ->{'reg ∨ 'reg1} (Ref[Int, in ⊥ out 'reg] ∨ Ref[Int, in ⊥ out 'reg1])  <:  'f\n//│ ╟── because: cannot constrain  ('x, 'y) ->{'reg ∨ 'reg1} (Ref[Int, in ⊥ out 'reg] ∨ Ref[Int, in ⊥ out 'reg1])  <:  ('r1, 'r2) ->{'eff} ('app)\n//│ ╟── because: cannot constrain  'reg ∨ 'reg1  <:  'eff\n//│ ╟── because: cannot constrain  'reg1  <:  'eff\n//│ ╟── because: cannot constrain  s ∧ ¬r  <:  'eff\n//│ ╟── because: cannot constrain  s ∧ ¬r  <:  'E ∨ ¬'R\n//│ ╟── because: cannot constrain  'R ∧ s ∧ ¬r  <:  'E\n//│ ╟── because: cannot constrain  'R ∧ s ∧ ¬r  <:  ¬'R\n//│ ╟── because: cannot constrain  'R  <:  ¬s ∨ r\n//│ ╙── because: cannot constrain  s ∧ ¬r  <:  ¬s ∨ r\n//│ Type: Int\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLBasicADTs.mls",
    "content": "\n:global\n:invalml\n\nclass IntList with\n  constructor\n    Nil\n    Cons(x: Int, xs: IntList)\n\nNil\n//│ Type: IntList\n\nCons(1, Cons(2, Cons(3, Nil)))\n//│ Type: IntList\n\n\n:e\nclass Foo with\n  constructor\n    Bar(x)\n//│ ╔══[COMPILATION ERROR] Invalid ADT parameter.\n//│ ║  l.20: \t    Bar(x)\n//│ ╙──      \t        ^\n\n\n:e\nNil(1)\n//│ ╔══[COMPILATION ERROR] Type error in application\n//│ ║  l.27: \tNil(1)\n//│ ║        \t^^^^^^\n//│ ╙── because: cannot constrain  IntList  <:  (Int) ->{'eff} ('app)\n//│ Type: ⊥\n\n:e\nNil()\n//│ ╔══[COMPILATION ERROR] Type error in application\n//│ ║  l.35: \tNil()\n//│ ║        \t^^^^^\n//│ ╙── because: cannot constrain  IntList  <:  () ->{'eff} ('app)\n//│ Type: ⊥\n\n\n:e\nCons(\"1\", Nil)\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type Int\n//│ ║  l.44: \tCons(\"1\", Nil)\n//│ ║        \t     ^^^\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: IntList\n\n\nclass Option[T] with\n  constructor\n    None\n    Some(x: T)\n\n\nNone\n//│ Type: Option[in ⊤ out ⊥]\n\nSome(42)\n//│ Type: Option[in ⊤ out Int]\n\nSome(false)\n//│ Type: Option[in ⊤ out Bool]\n\n\nclass Fun[T, S] with\n  constructor\n    Pure(f: T -> S)\n\n\nPure(x => x + 1)\n//│ Type: Fun[in Int out ⊥, in ⊤ out Int]\n\n\nclass Value[T] with\n  constructor\n    IntVal(x: Int) extends Value[out Int]\n    BoolVal(x: Bool) extends Value[out Bool]\n\nIntVal(42)\n//│ Type: Value[out Int]\n\nBoolVal(false)\n//│ Type: Value[out Bool]\n\n:e\nIntVal(\"1\")\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type Int\n//│ ║  l.89: \tIntVal(\"1\")\n//│ ║        \t       ^^^\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Value[out Int]\n\nclass Expr[T] with\n  constructor\n    Lit[S](x: S) extends Expr[out S]\n    Var[S](nme: Str) extends Expr[out S]\n    Add(lhs: Expr[out Int], rhs: Expr[out Int]) extends Expr[out Int]\n    Lam[U, V](f: Expr[out U] -> Expr[out V]) extends Expr[out U -> V]\n    App[U, V](f: Expr[out U -> V], a: Expr[out U]) extends Expr[out V]\n\nlet a = Lit(42)\na\n//│ Type: Expr[out Int]\n\nlet f = Lam(x => Add(x, Lit(1)))\nf\n//│ Type: Expr[out Int -> Int]\n\n:e\nLam(42)\n//│ ╔══[COMPILATION ERROR] Type error in integer literal with expected type (Expr[out 'U]) ->{⊥} Expr[out 'V]\n//│ ║  l.113: \tLam(42)\n//│ ║         \t    ^^\n//│ ╙── because: cannot constrain  Int  <:  (Expr[in ⊥ out 'U]) ->{⊥} (Expr[in ⊥ out 'V])\n//│ Type: Expr[out ⊤ -> ⊥]\n\nApp(f, a)\n//│ Type: Expr[out Int]\n\n\nlet b = Lit(true)\nb\n//│ Type: Expr[out Bool]\n\n:e\nApp(f, b)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type Expr[out 'U]\n//│ ║  l.129: \tApp(f, b)\n//│ ║         \t       ^\n//│ ╟── because: cannot constrain  Expr[in ⊥ out 'S]  <:  Expr[in ⊥ out 'U]\n//│ ╟── because: cannot constrain  'S  <:  'U\n//│ ╟── because: cannot constrain  'S  <:  'U1\n//│ ╟── because: cannot constrain  Bool  <:  'U1\n//│ ╙── because: cannot constrain  Bool  <:  Int\n//│ Type: Expr[out Int]\n\n\nfun sum(xs) =\n  if xs is\n    Nil then 0\n    Cons(x, xs) then x + sum(xs)\nsum\n//│ Type: IntList -> Int\n\n\nsum(Cons(1, Cons(2, Cons(3, Cons(4, Nil)))))\n//│ Type: Int\n\n\n:e\nfun badSum(xs) =\n  if xs is\n    Cons(x, xs) then x + badSum(xs)\n//│ ╔══[COMPILATION ERROR] Expect 2 cases, but 1 got.\n//│ ║  l.156: \t    Cons(x, xs) then x + badSum(xs)\n//│ ╙──       \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:e\nfun badSum(xs) =\n  if xs is\n    Cons(x, xs) then x + badSum(xs)\n    Cons(x, xs) then x + badSum(xs)\n//│ ╔══[COMPILATION ERROR] Duplicate match branches.\n//│ ║  l.164: \t    Cons(x, xs) then x + badSum(xs)\n//│ ║         \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.165: \t    Cons(x, xs) then x + badSum(xs)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Expect 2 cases, but 1 got.\n//│ ║  l.164: \t    Cons(x, xs) then x + badSum(xs)\n//│ ║         \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.165: \t    Cons(x, xs) then x + badSum(xs)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\nfun getOrElse(m, d) =\n  if m is\n    Some(x) then x\n    None then d\ngetOrElse\n//│ Type: ['d, 'Some] -> (Option[?] ∧ Option[out 'Some], 'd) -> ('Some ∨ 'd)\n\n\ngetOrElse(Some(42), 0)\n//│ Type: Int\n\ngetOrElse(None, false)\n//│ Type: Bool\n\ngetOrElse(Some(42), \"42\")\n//│ Type: Int ∨ Str\n\n\nif IntVal(1) is\n  IntVal(x) then 1\n  BoolVal(x) then 0\n//│ Type: Int\n\n\nfun toBool(v) =\n  if v is\n    IntVal(x) then x > 0\n    BoolVal(x) then x\ntoBool\n//│ Type: Value[?] -> Bool\n\ntoBool(IntVal(1))\n//│ Type: Bool\n\n\nclass MyMap[K, V] with\n  constructor\n    Empty\n    Pair(k: K, v: V, rest: MyMap[out K, out V])\n\nfun newMap(k, v) = Pair(k, v, Empty)\nnewMap\n//│ Type: ['k, 'v] -> ('k, 'v) -> MyMap[in ⊤ out 'k, in ⊤ out 'v]\n\nfun insert(m, k, v) = Pair(k, v, m)\ninsert\n//│ Type: ['k, 'v, 'K, 'V] -> (MyMap[out 'K, out 'V], 'k, 'v) -> MyMap[in ⊤ out 'K, in ⊤ out 'V]\n//│ Where:\n//│   'k <: 'K\n//│   'v <: 'V\n\n\nfun getOrElse: [K, V] -> (MyMap[out K, out V], K, V) -> V\nfun getOrElse(m, k, d) =\n  if m is\n    Empty then d\n    Pair(k', v, r) then (if k == k' then v else getOrElse(r, k, d))\n\nlet incMap1 = newMap(1, 2)\nincMap1\n//│ Type: MyMap[in ⊤ out Int, in ⊤ out Int]\n\nlet incMap2 = insert(incMap1, 2, 3)\nincMap2\n//│ Type: MyMap[in ⊤ out Int, in ⊤ out Int]\n\ngetOrElse(incMap2, 3, 4)\n//│ Type: Int\n\n\nfun toString: Any -> Str\n\nfun concat: (Str, Str) -> Str\n\nfun print: [T] -> Expr[out T] -> Str\nfun print(e) = \n  if e is\n    Lit(x) then toString(x)\n    Var(nme) then nme\n    Add(lhs, rhs) then concat(print(lhs), concat(\" + \", print(rhs)))\n    Lam(f) then\n      let v = Var(\"arg\") in concat(print(v), concat(\" => \", print(f(v))))\n    App(f, a) then concat(print(f), concat(\" \", print(a)))\n\nlet p = Lam(x => Add(x, Lit(1)))\np\n//│ Type: Expr[out Int -> Int]\n\nlet a = App(p, Lit(2))\na\n//│ Type: Expr[out Int]\n\nprint(p)\nprint(a)\n//│ Type: Str\n\n\n:e\nfun foo(x) =\n  if x is\n    Some(x) then 1\n    None then 0\n    42 then 42\n//│ ╔══[COMPILATION ERROR] Mixing ADT pattern matching and general matching is not supported yet.\n//│ ║  l.280: \t    42 then 42\n//│ ╙──       \t    ^^^^^^^^^^\n//│ ═══[COMPILATION ERROR] Variable not found: arg$Some$0$\n\n\nfun foo(x) =\n  if x is\n    Some(x) then x\n    else 0\n\n\nclass List[out T] with\n  constructor\n    Nil\n    Cons(x: T, xs: List[T])\n\n\nCons(42, Nil)\n//│ Type: List[out Int]\n\n\nfun foo: [T] -> T -> List[T]\nfoo\n//│ Type: ['T] -> ('T) ->{⊥} List[out 'T]\n\n\nclass Bar[in T] with\n  constructor\n    B(f: T -> Int)\n\n\nB(x => x + 1)\n//│ Type: Bar[in Int]\n\n\nfun bar: [T] -> (T, Bar[T]) -> Int\nbar\n//│ Type: ['T] -> ('T, Bar[in 'T]) ->{⊥} Int\n\n\nclass Option[out T] with\n  constructor\n    None\n    Some(x: T)\n\n\nfun headOpt(xs) = if xs is\n  Nil then None\n  Cons(x, xs) then Some(x)\nheadOpt\n//│ Type: ['Cons] -> (List[out 'Cons] ∧ List[?]) -> (Option[⊥] ∨ Option[out 'Cons])\n\n\nheadOpt(Nil)\n//│ Type: Option[⊥]\n\nheadOpt(Cons(42, Nil))\n//│ Type: Option[⊥] ∨ Option[out Int]\n\n\nfun getOrElse(v, d) = if v is\n   Some(x) then x\n   else d\ngetOrElse\n//│ Type: ['d, 'Some] -> (Option[out 'Some], 'd) -> ('Some ∨ 'd)\n\n\ngetOrElse(headOpt(Nil), \"foo\")\n//│ Type: Str\n\ngetOrElse(headOpt(Cons(42, Nil)), 1)\n//│ Type: Int\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLBasics.mls",
    "content": ":invalml\n\n\n123\n//│ Type: Int\n\n3.14\n//│ Type: Num\n\nfalse\n//│ Type: Bool\n\n\"invalml\"\n//│ Type: Str\n\n()\n\nfun id(x) = x\nid\n//│ Type: ['x] -> 'x -> 'x\n\nfun inc(x) = x + 1\n\nfun mul(x, y) = x * y\n\nx => x\n//│ Type: ('x) ->{⊥} 'x\n\n+\n//│ Type: (Int, Int) ->{⊥} Int\n\n(x, y) => x + y\n//│ Type: (Int, Int) ->{⊥} Int\n\n((x, y) => x + y)(40, 2)\n//│ Type: Int\n\n:e\n114 + \"514\"\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type Int\n//│ ║  l.39: \t114 + \"514\"\n//│ ║        \t      ^^^^^\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Int\n\n\ninc(42)\n//│ Type: Int\n\nlet x = 42 in x\n//│ Type: Int\n\nlet x = 1 in let y = 2 in x + y\n//│ Type: Int\n\n:e\nlet x = 0 in x + \"1\"\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type Int\n//│ ║  l.57: \tlet x = 0 in x + \"1\"\n//│ ║        \t                 ^^^\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Int\n\ndata class Foo(x: Int)\n\n:e\nnew Nothingness(0)\n//│ ╔══[COMPILATION ERROR] Name not found: Nothingness\n//│ ║  l.67: \tnew Nothingness(0)\n//│ ╙──      \t    ^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found ‹error›.\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[COMPILATION ERROR] Not a valid class: ‹error›\n//│ Type: ⊥\n\n:e\nnew 42\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found integer literal.\n//│ ║  l.77: \tnew 42\n//│ ║        \t    ^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ╔══[COMPILATION ERROR] Not a valid class: integer literal\n//│ ║  l.77: \tnew 42\n//│ ╙──      \t    ^^\n//│ Type: ⊥\n\n\nnew Foo(42)\n//│ Type: Foo\n\n\ndata class Point(x: Num, y: Num, z: Num)\n\n\nnew Point(0.0, 0.0, 0.0)\n//│ Type: Point\n\n:e\nnew Foo(\"1!5!\")\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type Int\n//│ ║  l.99: \tnew Foo(\"1!5!\")\n//│ ║        \t        ^^^^^^\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Foo\n\n\ndata class Some[A](value: A)\n\nnew Some(true)\n//│ Type: Some['A]\n//│ Where:\n//│   Bool <: 'A\n\nnew Some(42)\n//│ Type: Some['A]\n//│ Where:\n//│   Int <: 'A\n\nlet p = new Point(1.0, 0.0, 0.0) in p.Point#x\n//│ Type: Num\n\nlet t = new Some(true) in t.Some#value\n//│ Type: Bool\n\n:fixme\n:pe\n42.Some#value\n//│ ╔══[LEXICAL ERROR] Expected at least one digit after the  decimal point\n//│ ║  l.127: \t42.Some#value\n//│ ╙──       \t   ^\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (infix operator '#').\n//│ ║  l.127: \t42.Some#value\n//│ ╙──       \t   ^^^^^^^^^^\n//│ Type: Num\n\n\ndata class Printer[T](f: T -> Str)\n\nfun foofoo(x) =\n  let t = x + 1 in \"foo\"\n\nnew Printer(foofoo)\n//│ Type: Printer['T]\n//│ Where:\n//│   'T <: Int\n\nlet ip = new Printer(foofoo) in ip.Printer#f(42)\n//│ Type: Str\n\n:e\nlet ip = new Printer(foofoo) in ip.Printer#f(\"42\")\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type 'T\n//│ ║  l.151: \tlet ip = new Printer(foofoo) in ip.Printer#f(\"42\")\n//│ ║         \t                                             ^^^^\n//│ ╟── because: cannot constrain  Str  <:  'T\n//│ ╟── because: cannot constrain  Str  <:  'T\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Str\n\ndata class TFun[T](f: T -> T)\n\nfun inc(x) = x + 1\n\nnew TFun(inc)\n//│ Type: TFun['T]\n//│ Where:\n//│   Int <: 'T\n//│   'T <: Int\n\nlet tf = new TFun(inc) in tf.TFun#f(1)\n//│ Type: Int\n\n:e\nlet tf = new TFun(inc) in tf.TFun#f(\"1\")\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type 'T\n//│ ║  l.174: \tlet tf = new TFun(inc) in tf.TFun#f(\"1\")\n//│ ║         \t                                    ^^^\n//│ ╟── because: cannot constrain  Str  <:  'T\n//│ ╟── because: cannot constrain  Str  <:  'T\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Str ∨ Int\n\ndata class Pair[A, B](fst: A, snd: B)\n\n(new Pair(42, true)).Pair#fst\n//│ Type: Int\n\n(new Pair(42, true)).Pair#snd\n//│ Type: Bool\n\n\nnew Pair(id, id)\n//│ Type: Pair['A, 'B]\n//│ Where:\n//│   'x -> 'x <: 'A\n//│   'x1 -> 'x1 <: 'B\n\n\nnew Pair(x => x, x => x)\n//│ Type: Pair['A, 'B]\n//│ Where:\n//│   'x -> 'x <: 'A\n//│   'x1 -> 'x1 <: 'B\n\n\nif 1 < 2 then 1 else 0\n//│ Type: Int\n\n\nif false then 1 else \"1\"\n//│ Type: Int ∨ Str\n\n\nif 1 is Int then 1 else 0\n//│ Type: Int\n\n\nif 1 is Foo then 0 else 1\n//│ Type: Int\n\n\nfun test(x) =\n  if x is Int then x + 1 else 0\ntest\n//│ Type: (¬Int ∨ Int) -> Int\n\ntest(1)\n//│ Type: Int\n\n\ntest(\"1\")\n//│ Type: Int\n\n\nfun fact(n) =\n  if n > 1 then n * fact(n - 1) else 1\n\nfact\n//│ Type: Int -> Int\n\nfact(1)\n//│ Type: Int\n\n\nfun fact2 = x => fact2(1)\n\nfun fact2 = x => if x is\n  n then fact2(n - 1)\n\nfun fact2(x) = if x is\n  n then fact2(n - 1)\n\n\nfun fact2 = case\n  0 then 1\n  n then n * fact2(n - 1)\n\nfact2\n//│ Type: Int -> Int\n\nfact2(0)\n//│ Type: Int\n\n\ndata class Foo[A](x: A -> A)\n\nnew Foo(x => x)\n//│ Type: Foo['A]\n\nfun f(g) = new Foo(g)\nf\n//│ Type: ['A] -> ('A -> 'A) -> Foo['A]\n\nf(x => x).Foo#x\n//│ Type: ('A) ->{⊥} 'A\n\ng => (new Foo(g)).Foo#x\n//│ Type: ('A -> 'A) ->{⊥} ('A) ->{⊥} 'A\n\n\nthrow new Error(\"oops\")\n//│ Type: ⊥\n\n\n:e\nthrow 42\n//│ ╔══[COMPILATION ERROR] Type error in throw\n//│ ║  l.286: \tthrow 42\n//│ ║         \t^^^^^^^^\n//│ ╙── because: cannot constrain  Int  <:  Error\n//│ Type: ⊥\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLBorrowing.mls",
    "content": ":invalml\n\n\nclass Reg[Rg, Br]\n\nfun letreg: [E, Res] -> ([Rg] -> Reg[Rg, E] ->{E | Rg} Res) ->{E} Res\n\nfun use_: [Rg, Br] -> Reg[Rg, Br] ->{Rg} Int\n\n\nclass MutVec[A, Rg, Br]\n\nfun mkVec: [A, Rg, Br] -> Reg[Rg, Br] -> MutVec[A, Rg, Br]\n\nfun clear: [A, Rg, Br] -> MutVec[A, Rg, Br] ->{Rg} Int\n\nclass Iter[A, Rg]\n\nfun iterate: [A, Rg, Br, Res] -> MutVec[A, Rg, Br] -> ([L] -> Iter[A, Br | L] ->{Br | L} Res) ->{Br} Res\n\nfun integers: [Rg, Br, Res] -> Reg[Rg, Br] ->{Rg} (Iter[Int, Br] ->{Br} Res) ->{Br} Res\n\n\nfun next: [A, Br] -> Iter[A, Br] ->{Br} A\n\nletreg(r => r)\n//│ Type: Reg[?, 'E]\n//│ Where:\n//│   'E <: ⊥\n\nletreg of r =>\n  let b = mkVec(r)\n  clear(b)\n  iterate(b) of it =>\n    next(it)\n    123\n  clear(b)\n  r\n//│ Type: Reg[?, 'E]\n//│ Where:\n//│   'E <: ⊥\n\n\n// * Non-lexical borrowing pattern encoded with a thunk\n:w\nletreg of r =>\n  let b = mkVec(r)\n  clear(b)\n  let k = iterate(b) of it =>\n    next(it)\n    123\n    if next(it) > 0 then () => 0 else () => clear(b)\n  k()\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.51: \t    123\n//│ ╙──      \t    ^^^\n//│ Type: Int\n\n:w\n:e\nletreg of r =>\n  let b = mkVec(r)\n  clear(b)\n  let k = iterate(b) of it =>\n    next(it)\n    123\n    () => next(it)\n  k()\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.66: \t    123\n//│ ╙──      \t    ^^^\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.61: \tletreg of r =>\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.62: \t  let b = mkVec(r)\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.63: \t  clear(b)\n//│ ║        \t^^^^^^^^^^\n//│ ║  l.64: \t  let k = iterate(b) of it =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.65: \t... (more lines omitted) ...\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'E  <:  ⊥\n//│ ╟── because: cannot constrain  ¬'Rg  <:  ⊥\n//│ ╟── because: cannot constrain  ⊤  <:  'Rg\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: ⊥\n\n:e\nletreg of r =>\n  let b = mkVec(r)\n  clear(b)\n  iterate(b) of it =>\n    next(it)\n    clear(b)\n    123\n  clear(b)\n  r\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.90: \tletreg of r =>\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.91: \t  let b = mkVec(r)\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.92: \t  clear(b)\n//│ ║        \t^^^^^^^^^^\n//│ ║  l.93: \t  iterate(b) of it =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.94: \t... (more lines omitted) ...\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'E  <:  ⊥\n//│ ╟── because: cannot constrain  'Rg  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Reg[?, 'E]\n//│ Where:\n//│   ⊤ <: 'E\n//│   'E <: ⊥\n\n\nletreg of r =>\n  use_(r)\n  integers(r) of it =>\n    next(it)\n  use_(r)\n  r\n//│ Type: Reg[?, 'E]\n//│ Where:\n//│   'E <: ⊥\n\n:e\nletreg of r =>\n  use_(r)\n  integers(r) of it =>\n    use_(r)\n    next(it)\n  use_(r)\n  r\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.130: \tletreg of r =>\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.131: \t  use_(r)\n//│ ║         \t^^^^^^^^^\n//│ ║  l.132: \t  integers(r) of it =>\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.133: \t    use_(r)\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.134: \t... (more lines omitted) ...\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'E  <:  ⊥\n//│ ╟── because: cannot constrain  'Rg  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Reg[?, 'E]\n//│ Where:\n//│   ⊤ <: 'E\n//│   'E <: ⊥\n\nletreg of r0 =>\n  letreg of r1 =>\n    integers(r1) of it =>\n      use_(r0)\n      next(it)\n    use_(r1)\n    r1\n//│ Type: Reg[?, in 'E]\n//│ Where:\n//│   'E <: ⊥\n\n\n// * Can leak the iterator\n:w\nfun iterate_unsafe: [A, Rg, Br, Res] -> MutVec[A, Rg, Br] -> (Iter[A, Br] ->{Br} Res) ->{Br} Res\n// * Eg:\nletreg of r =>\n  let b = mkVec(r)\n  clear(b)\n  let k = iterate_unsafe(b) of it =>\n    next(it)\n    123\n    () => next(it)\n  clear(b)\n  k()\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.177: \t    123\n//│ ╙──       \t    ^^^\n//│ Type: ⊥\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLBorrowing2.mls",
    "content": ":invalml\n\n\nclass Reg[Rg, Br]\n\nfun letreg: [E, Res] -> ([Rg] -> Reg[Rg, E] ->{E | Rg} Res) ->{E} Res\n\nfun subreg: [E, Rg, Br, Res] -> Reg[Rg, Br] -> ([Rg2] -> Reg[Rg2 & ~Rg, E] ->{E | Rg2} Res) ->{E} Res\n\nfun read: [Rg, Br] -> Reg[Rg, Br] ->{Br} Int\nfun write: [Rg, Br] -> Reg[Rg, Br] ->{Rg} Int\n\n\nfun borrow: [Rg, Br, Res] -> Reg[Rg, Br] ->{Rg} (() ->{Br} Res) ->{Br} Res\n\nletreg of r =>\n  read(r)\n  borrow(r) of () =>\n    read(r)\n  write(r)\n//│ Type: Int\n\n:e\nletreg of r =>\n  read(r)\n  borrow(r) of () =>\n    write(r)\n    read(r)\n  write(r)\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.24: \tletreg of r =>\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.25: \t  read(r)\n//│ ║        \t^^^^^^^^^\n//│ ║  l.26: \t  borrow(r) of () =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.27: \t    write(r)\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.28: \t... (more lines omitted) ...\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'E  <:  ⊥\n//│ ╟── because: cannot constrain  'Rg  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Int\n\n\nfun borrow: [Rg, Br, Res] -> Reg[Rg, Br] ->{Rg} (() ->{Br | ~Rg} Res) ->{Br} Res\n\nletreg of r =>\n  read(r)\n  borrow(r) of () =>\n    read(r)\n  write(r)\n//│ Type: Int\n\n\n:e\nletreg of r =>\n  read(r)\n  borrow(r) of () =>\n    write(r)\n    read(r)\n  write(r)\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.58: \tletreg of r =>\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.59: \t  read(r)\n//│ ║        \t^^^^^^^^^\n//│ ║  l.60: \t  borrow(r) of () =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.61: \t    write(r)\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.62: \t... (more lines omitted) ...\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'E  <:  ⊥\n//│ ╟── because: cannot constrain  'Rg  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Int\n\n\n// * TODO...\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLBounds.mls",
    "content": ":invalml\n\n\n(x => x + 1) as [A extends Int] -> A -> Int\n//│ Type: (Int) ->{⊥} Int\n\n\n(x => x) as [A restricts Int] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   Int <: 'A\n\n\n(x => x - 1) as [A extends Int restricts Int] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   Int <: 'A\n//│   'A <: Int\n\nfun iid: [A extends Int] -> A -> A\nfun iid(x) = x\n\niid\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   'A <: Int\n\n:e\niid(\"42\")\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type 'A\n//│ ║  l.29: \tiid(\"42\")\n//│ ║        \t    ^^^^\n//│ ╟── because: cannot constrain  Str  <:  'A\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Str\n\n\niid(42)\n//│ Type: Int\n\nclass Foo[A]\n\nfun foo: [A extends Foo[in Nothing out Any] restricts Foo[in Num]] -> A -> A\nfoo\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   Foo[in Num] <: 'A\n//│   'A <: Foo[?]\n\nfun bar: Foo[in Num out Int]\n\nfoo(bar)\n//│ Type: Foo[in Num out Int] ∨ Foo[in Num]\n\n:e\nfun badfoo: [A extends Str restricts Int] -> A -> A\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.56: \tfun badfoo: [A extends Str restricts Int] -> A -> A\n//│ ║        \t                                             ^^^^^^\n//│ ╙── because: cannot constrain  Int  <:  Str\n\n\nfun baz: [A extends B, B extends A] -> A -> B\nbaz\n//│ Type: (⊤) ->{⊥} ⊤\n\nfun bazbaz: [A extends Int] -> A -> [B extends A] -> B\nbazbaz\n//│ Type: (Int) ->{⊥} ⊥\n\nfun foofun: [A extends Int -> Int restricts Any -> Int] -> A -> Int -> Int\nfoofun\n//│ Type: (Int -> Int) ->{⊥} (Int) ->{⊥} Int\n\nfoofun(x => x + 1)(42)\n//│ Type: Int\n\nfun bazbaz: [A extends Int] -> A -> ([B extends A -> A restricts A -> A] -> B) -> A\nbazbaz\n//│ Type: ['A] -> ('A) ->{⊥} ('A -> 'A) ->{⊥} 'A\n//│ Where:\n//│   'A <: Int\n\nbazbaz(42)(x => x + 1)\n//│ Type: Int\n\nfun cc: [A extends B -> B restricts B -> B, B extends A -> A restricts A -> A] -> A -> B -> Bool\ncc\n//│ Type: ['A, 'B] -> ('A) ->{⊥} ('B) ->{⊥} Bool\n//│ Where:\n//│   'A -> 'A <: 'B\n//│   'B <: 'A -> 'A\n//│   'B -> 'B <: 'A\n//│   'A <: 'B -> 'B\n\nfun w: Any -> Nothing\n\ncc(w)(w)\n//│ Type: Bool\n\nfun h: [C] -> ([A extends Int] -> A -> ([B extends A -> A restricts A -> A] -> B) -> A) -> C -> Int\n\n:e\nbazbaz as [A extends Int] -> A -> ([B extends A -> A restricts A -> A] -> B) -> A\n//│ ╔══[COMPILATION ERROR] Cannot type non-function term Ref(member:bazbaz) as (A) ->{⊥} ([outer, 'B] -> 'B) ->{⊥} A\n//│ ║  l.104: \tbazbaz as [A extends Int] -> A -> ([B extends A -> A restricts A -> A] -> B) -> A\n//│ ╙──       \t^^^^^^\n//│ Type: ['A] -> ('A) ->{⊥} ('A -> 'A) ->{⊥} 'A\n//│ Where:\n//│   'A <: Int\n\n\n(x => f => bazbaz(x)(f)) as [A extends Int] -> A -> ([B extends A -> A restricts A -> A] -> B) -> A\n//│ Type: ['A] -> ('A) ->{⊥} ('A -> 'A) ->{⊥} 'A\n//│ Where:\n//│   'A <: Int\n\n\nh(x => f => bazbaz(x)(f))(42)\n//│ Type: Int\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLCheck.mls",
    "content": ":invalml\n\n\nfun add: (Int, Int) -> Int\nfun add(x, y) = x + y\n\n// FIXME locations\n:e\nfun foo: Int -> Int\nfun foo: Int -> Int\n//│ ╔══[COMPILATION ERROR] Multiple declarations of symbol 'foo'\n//│ ╟── declared here\n//│ ║  l.9: \tfun foo: Int -> Int\n//│ ║       \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── declared here\n//│ ║  l.10: \tfun foo: Int -> Int\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^\n\n:e\nfun id(x) = x\nfun id(y) = y\n//│ ╔══[COMPILATION ERROR] Multiple definitions of symbol 'id'\n//│ ╟── defined here\n//│ ║  l.20: \tfun id(x) = x\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── defined here\n//│ ║  l.21: \tfun id(y) = y\n//│ ╙──      \t^^^^^^^^^^^^^\n\n:e\nfun bar: Str -> Str\nfun bar(x) = let t = x + 1 in \"aaa\"\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type Int\n//│ ║  l.32: \tfun bar(x) = let t = x + 1 in \"aaa\"\n//│ ║        \t                     ^\n//│ ╙── because: cannot constrain  Str  <:  Int\n\n:e\nfun baz: Int -> Int\nfun baz(x) = \"bbb\"\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type Int\n//│ ║  l.40: \tfun baz(x) = \"bbb\"\n//│ ║        \t             ^^^^^\n//│ ╙── because: cannot constrain  Str  <:  Int\n\nadd(1, 2)\n//│ Type: Int\n\nadd(1, 2) as Int\n//│ Type: Int\n\n\n:e\nadd(0, 0) as Str\n//│ ╔══[COMPILATION ERROR] Type error in application of type ‹not implemented› with expected type Str\n//│ ║  l.54: \tadd(0, 0) as Str\n//│ ║        \t^^^^^^^^^\n//│ ╙── because: cannot constrain  Int  <:  Str\n//│ Type: Str\n\n:e\nfun errAdd(x: Int) = x + \"1\"\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type Int\n//│ ║  l.62: \tfun errAdd(x: Int) = x + \"1\"\n//│ ║        \t                         ^^^\n//│ ╙── because: cannot constrain  Str  <:  Int\n\nfun high: ([A] -> A -> A) -> Int\nfun high(f) = f(42)\n\nhigh\n//│ Type: (['A] -> ('A) ->{⊥} 'A) ->{⊥} Int\n\n\nhigh((x => x) as [A] -> A -> A)\n//│ Type: Int\n\nhigh(x => x)\n//│ Type: Int\n\n:e\nhigh(x => x + 1)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type Int\n//│ ║  l.82: \thigh(x => x + 1)\n//│ ║        \t          ^\n//│ ╙── because: cannot constrain  A  <:  Int\n//│ ╔══[COMPILATION ERROR] Type error in application with expected type A\n//│ ║  l.82: \thigh(x => x + 1)\n//│ ║        \t          ^^^^^\n//│ ╙── because: cannot constrain  Int  <:  A\n//│ Type: Int\n\n(let a = 0 in x => x) as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\n(if false then x => x else y => y) as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\nfun baz: Int -> (([A] -> A -> A), Int) -> Int\nfun baz(z) =\n  ((f, x) => f(x))\n\nfun baz: Int -> (([A] -> A -> A), Int) -> Int\nfun baz(z) =\n  ((f, x) => f(x)) as (([A] -> A -> A), Int) -> Int\n\n:e\nbaz as Int -> (([A] -> A -> A), Int) -> Int\n//│ ╔══[COMPILATION ERROR] Cannot type non-function term Ref(member:baz) as (Int) ->{⊥} ([outer, 'A] -> ('A) ->{⊥} 'A, Int) ->{⊥} Int\n//│ ║  l.110: \tbaz as Int -> (([A] -> A -> A), Int) -> Int\n//│ ╙──       \t^^^\n//│ Type: ⊥\n\n\nbaz(42)\n//│ Type: (['A] -> ('A) ->{⊥} 'A, Int) ->{⊥} Int\n\n:e\nbaz(42) as (([A] -> A -> A), Int) -> Int\n//│ ╔══[COMPILATION ERROR] Cannot type non-function term App(Ref(member:baz),Tup(List(Fld(‹›,Lit(IntLit(42)),None)))) as ([outer, 'A] -> ('A) ->{⊥} 'A, Int) ->{⊥} Int\n//│ ║  l.121: \tbaz(42) as (([A] -> A -> A), Int) -> Int\n//│ ╙──       \t^^^^^^^\n//│ Type: ⊥\n\n(z => (f, x) => baz(z)(f, x)) as Int -> (([A] -> A -> A), Int) -> Int\n//│ Type: (Int) ->{⊥} (['A] -> ('A) ->{⊥} 'A, Int) ->{⊥} Int\n\n\nfun id: [A] -> A -> A\nfun id(x) = x\n\nid as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\n(id as [A] -> A -> A) as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n42 as Int | Num\n//│ Type: Int ∨ Num\n\n42 as [A] -> Int\n//│ Type: Int\n\n\n42 as [A] -> Int | Num\n//│ Type: Int ∨ Num\n\nfun foo: Int -> Int\nfoo\n//│ Type: (Int) ->{⊥} Int\n\nfoo\n//│ Type: (Int) ->{⊥} Int\n\n\n\nfun foo: [A] -> (A, ~A) -> A\nfoo\n//│ Type: ['A] -> ('A, ¬'A) ->{⊥} 'A\n\n\n:e\nfoo(42, 1)\n//│ ╔══[COMPILATION ERROR] Type error in integer literal with expected type ¬'A\n//│ ║  l.166: \tfoo(42, 1)\n//│ ║         \t        ^\n//│ ╟── because: cannot constrain  Int  <:  ¬'A\n//│ ╟── because: cannot constrain  'A  <:  ¬{Int}\n//│ ╙── because: cannot constrain  Int  <:  ¬{Int}\n//│ Type: Int\n\nfoo(42, false)\n//│ Type: Int\n\n\nfun f: ([A] -> A -> Int) -> ([A] -> A -> Int)\nf\n//│ Type: ((⊤) ->{⊥} Int) ->{⊥} (⊤) ->{⊥} Int\n\n\nfun f: ([A] -> ([B] -> A | B -> B)) -> ([A] -> ([B] -> A | B -> B))\nf\n//│ Type: (['B] -> (⊤) ->{⊥} 'B) ->{⊥} ['B] -> (⊤) ->{⊥} 'B\n\n\nfun f: ([A] -> ([B] -> A & B -> B)) -> ([A] -> ([B] -> A & B -> B))\nf\n//│ Type: (['B] -> ('B) ->{⊥} 'B) ->{⊥} ['B] -> ('B) ->{⊥} 'B\n\n\nfun f: ([A] -> ([B] -> A -> B & A)) -> ([A] -> ([B] -> A -> B | A))\nf\n//│ Type: (['A] -> ('A) ->{⊥} ⊥) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n\n\nfun f: ([A] -> ([B] -> A | B -> B) -> A) -> ([A] -> ([B] -> A | B -> B) -> A)\nf\n//│ Type: ((['B] -> ('B) ->{⊥} 'B) ->{⊥} ⊥) ->{⊥} (['B] -> ('B) ->{⊥} 'B) ->{⊥} ⊥\n\n\nfun f: ([A] -> ([B] -> A | B -> B | A) -> A) -> ([A] -> ([B] -> A | B -> B | A) -> A)\nf\n//│ Type: (['A] -> (['B] -> ('A ∨ 'B) ->{⊥} 'B ∨ 'A) ->{⊥} 'A) ->{⊥} ['A] -> (['B] -> ('A ∨ 'B) ->{⊥} 'B ∨ 'A) ->{⊥} 'A\n\n\nfun f: [A] -> [B] -> ([C] -> A | B -> B | C -> A | C) -> B\nf\n//│ Type: ['A] -> (['C] -> ('A) ->{⊥} ('C) ->{⊥} 'A ∨ 'C) ->{⊥} ⊥\n\n\nfun f: [A, B] -> ([C] -> A | B -> B | C -> A | B | C) -> B\nf\n//│ Type: ['A, 'B] -> (['C] -> ('A ∨ 'B) ->{⊥} ('B ∨ 'C) ->{⊥} ('A ∨ 'B) ∨ 'C) ->{⊥} 'B\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLCodeGen.mls",
    "content": ":js\n\n:global\n:invalml\n\n\n:sjs\n42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 42\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n//│ Type: Int\n\n:sjs\n1 + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 1 + 1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n//│ Type: Int\n\n\n:sjs\n1.0 +. 2.14\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 1.0 + 2.14\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3.14\n//│ Type: Num\n\n\n:sjs\nlet x = 1 in x + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x; x = 1; x + 1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n//│ Type: Int\n\n\n:sjs\n\"abc\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ \"abc\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"abc\"\n//│ Type: Str\n\n:sjs\nfalse\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ false\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = false\n//│ Type: Bool\n\n:sjs\n(x => x) as [T] -> T -> T\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda1; lambda1 = (undefined, function (x1) { return x1 }); lambda1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n//│ Type: ['T] -> ('T) ->{⊥} 'T\n\n\n:sjs\ndata class Foo(x: Int)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let Foo1;\n//│ Foo1 = function Foo(x1) {\n//│   return globalThis.Object.freeze(new Foo.class(x1));\n//│ };\n//│ (class Foo {\n//│   static {\n//│     Foo1.class = this\n//│   }\n//│   constructor(x1) {\n//│     this.x = x1;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"Foo\", [\"x\"]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\nnew Foo(42)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ globalThis.Object.freeze(new Foo1.class(42))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Foo(42)\n//│ Type: Foo\n\n\n:sjs\nlet foo = new Foo(42) in foo.Foo#x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo; foo = globalThis.Object.freeze(new Foo1.class(42)); foo.x\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n//│ Type: Int\n\n\n:sjs\nfun inc(x) = x + 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let inc; inc = function inc(x1) { return x1 + 1 };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\ninc(41)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ inc(41)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n//│ Type: Int\n\n\n:sjs\nif 1 == 2 then 0 else 42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut; scrut = 1 == 2; if (scrut === true) { 0 } else { 42 }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n//│ Type: Int\n\n\n:sjs\nif 1 is Int then 1 else 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut1; scrut1 = 1; if (globalThis.Number.isInteger(scrut1)) { 1 } else { 0 }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n//│ Type: Int\n\n\ndata class Foo()\n\n\n\n:sjs\nlet foo = new Foo()\nif foo is Foo then 1 else 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo1;\n//│ foo1 = globalThis.Object.freeze(new Foo3.class());\n//│ if (foo1 instanceof Foo3.class) { 1 } else { 0 }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n//│ foo = Foo()\n//│ Type: Int\n\n\n:sjs\nfun pow(x) = case\n  0 then 1\n  n then x * pow(x)(n-1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let pow;\n//│ pow = function pow(x1) {\n//│   let lambda2;\n//│   lambda2 = (undefined, function (caseScrut) {\n//│     let n, baseCall, tmp, tmp1;\n//│     if (caseScrut === 0) {\n//│       return 1\n//│     }\n//│     n = caseScrut;\n//│     baseCall = pow(x1);\n//│     tmp = n - 1;\n//│     tmp1 = runtime.safeCall(baseCall(tmp));\n//│     return x1 * tmp1;\n//│   });\n//│   return lambda2\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sjs\nfun nott = case\n  true then false\n  false then true\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let nott;\n//│ nott = function nott() {\n//│   let lambda2;\n//│   lambda2 = (undefined, function (caseScrut) {\n//│     switch (caseScrut) {\n//│       case true:\n//│         return false;\n//│       case false:\n//│         return true;\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error.class(\"match error\"))\n//│   });\n//│   return lambda2\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:expect true\n:sjs\nnott of false\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = nott(); runtime.safeCall(tmp(false))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n//│ Type: Bool\n\n\n:sjs\nfun fact = case\n  0 then 1\n  n then n * fact(n - 1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let fact;\n//│ fact = function fact() {\n//│   let lambda2;\n//│   lambda2 = (undefined, function (caseScrut) {\n//│     let n, tmp1, tmp2, tmp3;\n//│     if (caseScrut === 0) {\n//│       return 1\n//│     }\n//│     n = caseScrut;\n//│     tmp1 = fact();\n//│     tmp2 = n - 1;\n//│     tmp3 = runtime.safeCall(tmp1(tmp2));\n//│     return n * tmp3;\n//│   });\n//│   return lambda2\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:expect 6\nfact(3)\n//│ = 6\n//│ Type: Int\n\n\n:sjs\nregion x in 42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ new globalThis.Region(); 42\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n//│ Type: Int\n\n\n:sjs\nregion x in x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x1; x1 = new globalThis.Region(); x1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Region\n//│ Type: Region[?]\n\n\n:sjs\nregion x in x.ref 42\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x2; x2 = new globalThis.Region(); new globalThis.Ref(x2, 42)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = Ref(Region, 42)\n//│ Type: Ref[Int, ?]\n\n\n:sjs\nregion x in let y = x.ref 42 in !(y)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x3, y; x3 = new globalThis.Region(); y = new globalThis.Ref(x3, 42); y.value\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n//│ Type: Int\n\n\n:sjs\nregion x in let y = x.ref 42 in y := 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let x4, y1; x4 = new globalThis.Region(); y1 = new globalThis.Ref(x4, 42); y1.value = 0; 0\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n//│ Type: Int\n\n\n\ndata class LsAlg[A, E](nil:() -> E, cons: (A, E) -> E)\n\nfun nil(x) = x.LsAlg#nil()\nfun cons(x, y, z) = x.LsAlg#cons(y, z)\n\ndata class Nil()\ndata class Cons[A, B](val x: A,val y: B)\n\nfun mk() = new LsAlg(() => new Nil, (x, y) => new Cons(x, y))\n\n// fun xs: [E] -> LsAlg[in Int, E] -> E\nfun xs(x) = x cons(1, x nil())\n\nfun ys: [E] -> LsAlg[in Nothing, E] -> E\nfun ys(x) = x nil()\n\nfun zs: [E] -> LsAlg[in Int | E, E] -> E\nfun zs(x) = x cons(xs(x), x cons(ys(x),x nil()))\n\nmk() zs()\n//│ = Cons(Cons(1, fun), Cons(fun, fun))\n//│ Type: Nil ∨ Cons['A, 'B]\n//│ Where:\n//│   ('E ∨ Cons['A, 'B]) ∨ Nil <: 'B\n//│   Nil <: 'E\n//│   Cons['A, 'B] <: 'E\n//│   'E ∨ Int <: 'A\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLCyclicExtrude.mls",
    "content": ":invalml\n\n\n\nlet f = (x => (x as [A] -> A -> A)) in f\n//│ Type: (⊤ -> ⊥) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n\nlet f = ((x => x) as [A] -> A -> A) in f\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\nlet foo = f => (x => f(x(x)) as [A] -> A -> A) in foo\n//│ Type: ('app -> (⊤ -> ⊥)) ->{⊥} ('x -> 'app) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   'x <: 'x -> 'app\n\nf => (let g = x => x(x) in f(g(g))) as [A] -> A -> A\n//│ Type: (⊥ -> (⊤ -> ⊥)) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n\n:e\nf => (let g = x => f(x(x)) in g) as [A] -> A -> A\n//│ ╔══[COMPILATION ERROR] Type error in block with expected type (A) ->{⊥} A\n//│ ║  l.20: \tf => (let g = x => f(x(x)) in g) as [A] -> A -> A\n//│ ║        \t              ^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  ('x) ->{'eff ∨ 'eff1} ('app)  <:  (A) ->{⊥} (A)\n//│ ╟── because: cannot constrain  A  <:  'x\n//│ ╙── because: cannot constrain  A  <:  ('x) ->{'eff1} ('app1)\n//│ Type: (⊥ -> ⊥) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n\nf => (x => f(x(x)) as [A] -> A -> A)\n//│ Type: ('app -> (⊤ -> ⊥)) ->{⊥} ('x -> 'app) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   'x <: 'x -> 'app\n\nlet foo = f => (f(x => x(x)) as [A] -> A -> A) in foo\n//│ Type: ((('x ->{'eff} 'app) ->{'eff} 'app) -> (⊤ -> ⊥)) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   'x <: 'x ->{'eff} 'app\n\nlet foo(f) = (f(x => x(x)) as [A] -> A -> A) in foo\n//│ Type: ((('x ->{'eff} 'app) ->{'eff} 'app) -> (⊤ -> ⊥)) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   'x <: 'x ->{'eff} 'app\n\n:todo\nfun foo(f) = (f(x => x(x)) as [A] -> A -> A)\n//│ ╔══[COMPILATION ERROR] Expected a monomorphic type or an instantiable type here, but ('f) ->{⊥} [outer, 'A] -> ('A) ->{⊥} 'A found\n//│ ║  l.45: \tfun foo(f) = (f(x => x(x)) as [A] -> A -> A)\n//│ ╙──      \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\nf => (let g = x => x(x) in let tmp = g(g) in f(g)) as [A] -> A -> A\n//│ Type: (((('x ∨ ('x ->{'eff} 'app)) -> 'app) ->{'eff} 'app) -> (⊤ -> ⊥)) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   'x <: ('x ∨ ('x ->{'eff} 'app)) -> 'app\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLDP.mls",
    "content": ":js\n\n:global\n:invalml\n\n\ndeclare class Array[T]\n\nfun mkArray: [T] -> () -> Array[T]\nfun mkArray() = @untyped globalThis.Array()\n\nfun mkArrayWith: [T] -> (T, Int) -> Array[T]\nfun mkArrayWith(iv, size) = @untyped globalThis.Array(size).fill(iv)\n\nfun at: [T] -> (Array[T], Int) -> T\nfun at(xs, i) = @untyped xs.at(i)\n\nfun splice: [T] -> (Array[T], Int, T) -> ()\nfun splice(xs, i, v) = @untyped xs.splice(i, 1, v); ()\n\nclass Option[A] with\n  constructor\n    Some(x: A)\n    None()\n\n\nclass ArrayList[T, out R](val d: Array[T])\nclass Iter[T, out R](val arr: Array[T], val i: Ref[Int, out R], val step: Int, val end: Int)\nclass Array2D[T, out R](val d: Array[Array[T]])\n\nclass Interviewee with\n  constructor\n    Itv(score: Int, salary: Int)\n\n\nfun debug: Any -> ()\nfun debug(s) = @untyped print(s)\n\n\nfun (;) seq(_, res) = res\n\nfun toString: Any -> Str\nfun toString(x) = @untyped x.toString()\n\nfun concat: (Str, Str) -> Str\nfun concat(x, y) = @untyped x + y\n\nfun println: Str -> ()\nfun println(s) = @untyped print(s)\n\nfun empty: [A, R] -> Region[out R] ->{R} ArrayList[A, R]\nfun empty(r) = new ArrayList(mkArray())\n\nfun push: [A, R] -> (ArrayList[A, R], A) ->{R} ()\nfun push(arr, e) = @untyped arr.ArrayList#d.push(e); ()\n\nfun len: [A, R] -> (ArrayList[A, R]) ->{R} Int\nfun len(arr) = @untyped arr.ArrayList#d.length\n\nfun iter: [Res, R, E extends ~R, T] -> (ArrayList[T, R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res\nfun iter(arr, f) =\n  region r in f(new Iter(arr.ArrayList#d, (r.ref 0), 1, len(arr)))\n\nfun revIter: [Res, R, E extends ~R, T] -> (ArrayList[T, R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res\nfun revIter(arr, f) =\n  region r in f(new Iter(arr.ArrayList#d, (r.ref (len(arr) - 1)), 0 - 1, 0 - 1))\n\n:sjs\nfun next: [T, S] -> Iter[T, S] ->{S} Option[T]\nfun next(it) =\n  let i = !(it.Iter#i)\n  if i == it.Iter#end then None()\n  else\n    let res = Some(at of it.Iter#arr, i)\n    it.Iter#i := i + it.Iter#step\n    res\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let next;\n//│ next = function next(it) {\n//│   let i, scrut, res, tmp, tmp1;\n//│   i = it.i.value;\n//│   scrut = i == it.end;\n//│   if (scrut === true) {\n//│     return None1()\n//│   }\n//│   tmp = at(it.arr, i);\n//│   res = Some1(tmp);\n//│   tmp1 = i + it.step;\n//│   it.i.value = tmp1;\n//│   return res;\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun whileDo: [R] -> (() ->{R} Bool) ->{R} ()\nfun whileDo(f) =\n  if f() then whileDo(f) else ()\n\nfun init: [A, R] -> (Region[out R], Int, Int, A) ->{R} Array2D[A, R]\nfun init(r, d1, d2, iv) =\n  let res = new Array2D(mkArrayWith(mkArrayWith(iv, d2), d1))\n  region r in\n    let i = r.ref 0\n    whileDo of () =>\n      if !(i) == d1 then false\n      else\n        splice(res.Array2D#d, !(i), mkArrayWith(iv, d2))\n        i := !(i) + 1\n        true\n  res\n    \nfun update: [A, R] -> (Array2D[A, R], Int, Int, A) ->{R} ()\nfun update(arr, d1, d2, v) = splice(at(arr.Array2D#d, d1), d2, v)\n\nfun get: [A, R] -> (Array2D[A, R], Int, Int) ->{R} A\nfun get(arr, d1, d2) = at(at(arr.Array2D#d, d1), d2)\n\nfun max: (Int, Int) -> Int\nfun max(x, y) = if x > y then x else y\n\n\nfun format(it) =\n  if it is Itv(score, salary) then\n    concat(\"interviewee score: \", concat(toString(score), concat(\", salary: \", toString(salary))))\n\nfun printAll(arr) =\n  iter of arr, it =>\n    whileDo of () =>\n      if next(it) is\n        Some(x) then println(format(x)); false\n        None then false\n\n\n// fun select: [outer, R1 extends outer, R2 extends ~R1] -> (ArrayList[Interviewee, R1], Int, ArrayList[Interviewee, R2]) ->{R1 | R2} Int\nfun select(interviewees, budget, results) =\n  region r in\n    let size = len(interviewees), let i = r.ref 1\n    let dp = init(r, size + 1, budget + 1, 0)\n    iter of interviewees, it => whileDo of () =>\n      if next(it) is\n        Some(itv) then if itv is Itv(score, salary) then\n          let j = r.ref 0\n          whileDo of () =>\n            if !(j) < salary then update(dp, !(i), !(j), get(dp, !(i) - 1, !(j)))\n            else\n              let p = get(dp, !(i) - 1, !(j) - salary), let np = get(dp, !(i) - 1, !(j))\n              update(dp, !(i), !(j), max of np, p + score)\n            j := !(j) + 1; !(j) <= budget\n          i := !(i) + 1\n          true\n        None then false\n    i := size\n    let rest = r.ref budget\n    revIter of interviewees, it =>\n      whileDo of () =>\n        if next(it) is\n          Some(itv) then if itv is Itv(score, salary) then\n            if get(dp, !(i), !(rest)) == get(dp, !(i) - 1, !(rest) - salary) + score then\n              push(results, itv); rest := !(rest) - salary\n            else ()\n            i := !(i) - 1\n            true\n          None then false\n    get(dp, size, budget)\n\nselect\n//│ = fun select\n//│ Type: [outer, 'A, 'R, 'T, 'R1, 'T1, 'T2, 'R2, 'A1, 'R3] -> ((ArrayList[in 'T1 out 'T2, out 'R2] ∧ ArrayList[in 'T out Interviewee ∧ 'T, out 'R1]) ∧ ArrayList['A, out 'R], Int, ArrayList['A1, out 'R3]) ->{(('R2 ∨ 'R3) ∨ 'R1) ∨ 'R} Int\n//│ Where:\n//│   'T <: Interviewee\n//│   'T <: 'T1\n//│   'R <: outer\n//│   'R1 <: outer\n//│   'T <: 'A\n//│   'R2 <: ¬'R\n\nregion r in\n  let interviewees = empty(r)\n  push(interviewees, Itv(20, 3))\n  push(interviewees, Itv(50, 1))\n  push(interviewees, Itv(30, 1))\n  println(\"all interviewees:\")\n  printAll(interviewees)\n  region r2 in\n    let results = empty(r2)\n    let m = select(interviewees, 4, results)\n    println(\"candidates:\")\n    printAll(results)\n    m\n//│ > all interviewees:\n//│ > interviewee score: 20, salary: 3\n//│ > candidates:\n//│ > interviewee score: 30, salary: 1\n//│ = 80\n//│ Type: Int\n\n\nregion r in\n  let interviewees = empty(r)\n  push(interviewees, Itv(100, 71))\n  push(interviewees, Itv(1, 69))\n  push(interviewees, Itv(2, 1))\n  println(\"all interviewees:\")\n  printAll(interviewees)\n  region r2 in\n    let results = empty(r2)\n    let m = select(interviewees, 70, results)\n    println(\"candidates:\")\n    printAll(results)\n    m\n//│ > all interviewees:\n//│ > interviewee score: 100, salary: 71\n//│ > candidates:\n//│ > interviewee score: 2, salary: 1\n//│ = 3\n//│ Type: Int\n\n\nregion r in\n  let interviewees = empty(r)\n  push(interviewees, Itv(40, 10))\n  push(interviewees, Itv(60, 20))\n  push(interviewees, Itv(120, 30))\n  push(interviewees, Itv(70, 20))\n  println(\"all interviewees:\")\n  printAll(interviewees)\n  region r2 in\n    let results = empty(r2)\n    let m = select(interviewees, 60, results)\n    println(\"candidates:\")\n    printAll(results)\n    m\n//│ > all interviewees:\n//│ > interviewee score: 40, salary: 10\n//│ > candidates:\n//│ > interviewee score: 70, salary: 20\n//│ = 230\n//│ Type: Int\n\n\n:e\nregion r in\n  let interviewees = empty(r)\n  push(interviewees, Itv(20, 3))\n  push(interviewees, Itv(50, 1))\n  push(interviewees, Itv(30, 1))\n  let results = empty(r)\n  let m = select(interviewees, 4, results)\n  println(\"candidates:\")\n  printAll(results)\n  m\n// //│ ╔══[ERROR] Type error in reference with expected type 'results\n// //│ ║  l.110: \t  let m = select(interviewees, 4000, results)\n// //│ ║         \t                                     ^^^^^^^\n// //│ ╟── because: cannot constrain  ArrayList['A, in ⊥ out 'R]  <:  'results\n// //│ ╟── because: cannot constrain  ArrayList['A, in ⊥ out 'R]  <:  ArrayList['A1, in ⊥ out 'R1]\n// //│ ╟── because: cannot constrain  'R  <:  'R1\n// //│ ╟── because: cannot constrain  'R  <:  ¬'R2\n// //│ ╟── because: cannot constrain  'R2  <:  ¬'R\n// //│ ╟── because: cannot constrain  'R3  <:  ¬'R\n// //│ ╟── because: cannot constrain  'R  <:  ¬'R3\n// //│ ╟── because: cannot constrain  r  <:  ¬'R3\n// //│ ╟── because: cannot constrain  'R3  <:  ¬r\n// //│ ╙── because: cannot constrain  r  <:  ¬r\n// //│ Type: Int\n//│ > candidates:\n//│ > interviewee score: 30, salary: 1\n//│ = 80\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type 'results\n//│ ║  l.247: \t  let m = select(interviewees, 4, results)\n//│ ║         \t                                  ^^^^^^^\n//│ ╟── because: cannot constrain  ArrayList['A, in ⊥ out 'R]  <:  'results\n//│ ╟── because: cannot constrain  ArrayList['A, in ⊥ out 'R]  <:  ArrayList['A1, in ⊥ out 'R1]\n//│ ╟── because: cannot constrain  'R  <:  'R1\n//│ ╟── because: cannot constrain  'R  <:  ¬'R2\n//│ ╟── because: cannot constrain  'R2  <:  ¬'R\n//│ ╟── because: cannot constrain  'R3  <:  ¬'R\n//│ ╟── because: cannot constrain  'R  <:  ¬'R3\n//│ ╟── because: cannot constrain  r  <:  ¬'R3\n//│ ╟── because: cannot constrain  'R3  <:  ¬r\n//│ ╙── because: cannot constrain  r  <:  ¬r\n//│ Type: Int\n\n\nfun wrongSelect(interviewees, budget, results) =\n  region r in\n    let size = len(interviewees), let i = r.ref 1\n    let dp = init(r, size + 1, budget + 1, 0)\n    iter of interviewees, it =>\n      whileDo of () =>\n        if next(it) is\n          Some(itv) then if itv is Itv(score, salary) then\n            let j = r.ref 0\n            whileDo of () =>\n              if !(j) < salary then update(dp, !(i), !(j), get(dp, !(i) - 1, !(j)))\n              else\n                let p = get(dp, !(i) - 1, !(j) - salary), let np = get(dp, !(i) - 1, !(j))\n                update(dp, !(i), !(j), max of np, p + score)\n              j := !(j) + 1; !(j) <= budget\n            i := !(i) + 1\n            true\n          None then false\n    i := size\n    let rest = r.ref budget\n    revIter of interviewees, it =>\n      whileDo of () =>\n        if next(it) is\n          Some(itv) then if itv is Itv(score, salary) then\n            if get(dp, !(i), !(rest)) == get(dp, !(i) - 1, !(rest) - salary) + score then\n              push(interviewees, itv); rest := !(rest) - salary\n            else ()\n            i := !(i) - 1\n            true\n          None then false\n    get(dp, size, budget)\n\n:e\nregion r in\n  let interviewees = empty(r)\n  push(interviewees, Itv(20, 3000))\n  push(interviewees, Itv(50, 1000))\n  push(interviewees, Itv(30, 1000))\n  region r2 in\n    let results = empty(r2)\n    let m = wrongSelect(interviewees, 4000, results)\n    println(\"candidates:\")\n    printAll(results)\n    m\n//│ > candidates:\n//│ = 80\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type 'interviewees\n//│ ║  l.324: \t    let m = wrongSelect(interviewees, 4000, results)\n//│ ║         \t                        ^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  ArrayList['A, in ⊥ out 'R]  <:  'interviewees\n//│ ╟── because: cannot constrain  ArrayList['A, in ⊥ out 'R]  <:  ArrayList[in 'T out 'T1, in ⊥ out 'R1]\n//│ ╟── because: cannot constrain  'R  <:  'R1\n//│ ╟── because: cannot constrain  'R  <:  ¬'R\n//│ ╟── because: cannot constrain  'R  <:  ⊥\n//│ ╙── because: cannot constrain  r  <:  ⊥\n//│ Type: Int\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLDisjoint.mls",
    "content": ":invalml\n\n\n\ndata class Pair[P, Q](fst: P, snd: Q)\n\nfun fork: [A, B extends ~A, T1, T2] -> (Any ->{A} T1, Any ->{B} T2) ->{A | B} Pair[out T1, out T2]\nfork\n//│ Type: ['A, 'B, 'T1, 'T2] -> ((⊤) ->{'A} 'T1, (⊤) ->{'B} 'T2) ->{'A ∨ 'B} Pair[out 'T1, out 'T2]\n//│ Where:\n//│   'B <: ¬'A\n\n\nfun foo: Any -> Int\nfun bar: Any -> Str\n\n\nfork(foo, bar)\n//│ Type: Pair[out Int, out Str]\n\n\n:e\nregion x in\n  fork((_ => x.ref 1), (_ => x.ref 2))\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type (⊤) ->{'B} 'T2\n//│ ║  l.24: \t  fork((_ => x.ref 1), (_ => x.ref 2))\n//│ ║        \t                        ^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg  <:  'B\n//│ ╟── because: cannot constrain  x  <:  'B\n//│ ╟── because: cannot constrain  x  <:  ¬'A\n//│ ╟── because: cannot constrain  'A  <:  ¬x\n//│ ╙── because: cannot constrain  x  <:  ¬x\n//│ Type: Pair[out Ref[Int, ?], out Ref[Int, ?]]\n\n\n\nregion x in\n  region y in\n    fork((_ => x.ref 1), (_ => y.ref 2))\n//│ Type: Pair[out Ref[Int, ?], out Ref[Int, ?]]\n\n\nlet naive_helper = r1 => // cannot infer the outer variable!\n  region r2 in\n    fork((_ => r1.ref 1), (_ => r2.ref 2))\nnaive_helper\n//│ Type: (Region[out 'reg]) ->{'reg} Pair[out Ref[Int, out 'reg], out Ref[Int, ?]]\n//│ Where:\n//│   'reg <: ⊥\n\n\nfun f: [S, R, R extends ~S] -> (Region[out S], Region[out R]) ->{S | R} Int\n\n:e\nregion r1 in\n  let g = (r => region r2 in f(r, r2)) in\n    region r3 in g(r3)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type 'r\n//│ ║  l.57: \t    region r3 in g(r3)\n//│ ║        \t                   ^^\n//│ ╟── because: cannot constrain  Region[in ⊥ out r3]  <:  'r\n//│ ╟── because: cannot constrain  Region[in ⊥ out 'r31]  <:  'r\n//│ ╟── because: cannot constrain  Region[in ⊥ out 'r31]  <:  Region[in ⊥ out 'S]\n//│ ╟── because: cannot constrain  'r31  <:  'S\n//│ ╟── because: cannot constrain  ¬r1  <:  'S\n//│ ╟── because: cannot constrain  ¬r1  <:  ¬'r2 ∨ r1\n//│ ╟── because: cannot constrain  'r2  <:  r1\n//│ ╙── because: cannot constrain  ¬r1  <:  r1\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.56: \t  let g = (r => region r2 in f(r, r2)) in\n//│ ║        \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.57: \t    region r3 in g(r3)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'eff  <:  ⊥\n//│ ╟── because: cannot constrain  ¬'r11  <:  ⊥\n//│ ╟── because: cannot constrain  ⊤  <:  'r11\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Int\n\nfun g(r) =\n  region r2 in f(r, r2)\n\nregion r1 in\n  region r3 in g(r3)\n//│ Type: Int\n\n\n:e\nregion x in\n  naive_helper(x)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type 'r1\n//│ ║  l.90: \t  naive_helper(x)\n//│ ║        \t               ^\n//│ ╟── because: cannot constrain  Region[in ⊥ out x]  <:  'r1\n//│ ╟── because: cannot constrain  Region[in ⊥ out 'x1]  <:  'r1\n//│ ╟── because: cannot constrain  Region[in ⊥ out 'x1]  <:  Region[in ⊥ out 'reg]\n//│ ╟── because: cannot constrain  'x1  <:  'reg\n//│ ╟── because: cannot constrain  ⊤  <:  'reg\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.90: \t  naive_helper(x)\n//│ ║        \t  ^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'eff  <:  ⊥\n//│ ╟── because: cannot constrain  ¬'x2 ∧ 'eff1  <:  ⊥\n//│ ╟── because: cannot constrain  'eff1  <:  'x2\n//│ ╟── because: cannot constrain  'eff1  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Pair[out Ref[Int, ?], out Ref[Int, ?]]\n\n\nfun helper(r1) =\n  region r2 in\n    fork((_ => r1.ref 1), (_ => r2.ref 2))\nhelper\n//│ Type: [outer, 'reg] -> Region[out 'reg] ->{'reg} Pair[out Ref[Int, out 'reg], out Ref[Int, out ¬outer]]\n//│ Where:\n//│   'reg <: outer\n\n\nregion x in\n  helper(x)\n//│ Type: Pair[out Ref[Int, ?], out Ref[Int, ?]]\n\n\nregion x in\n  (region y in let t = helper(y) in 42) as [A] -> Int\n//│ Type: Int\n\n\nregion x in\n  region y in\n    let t = helper(x) in 42\n//│ Type: Int\n\n\n:e\nregion x in\n  (region y in let t = helper(x) in 42) as [A] -> Int\n//│ ╔══[COMPILATION ERROR] Type error in region expression with expected type [outer, 'A] -> Int\n//│ ║  l.139: \t  (region y in let t = helper(x) in 42) as [A] -> Int\n//│ ║         \t                       ^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'eff  <:  ⊥\n//│ ╟── because: cannot constrain  ¬'y ∧ x  <:  ⊥\n//│ ╟── because: cannot constrain  x  <:  'y\n//│ ╙── because: cannot constrain  x  <:  ⊥\n//│ Type: Int\n\n\nfun anno: [outer A] -> Int ->{A} Int\n\n\nfun anno2: [outer] -> Int ->{outer} Int\n\n\n:e\nfun badanno: outer\n//│ ╔══[COMPILATION ERROR] Illegal outer reference.\n//│ ║  l.157: \tfun badanno: outer\n//│ ╙──       \t             ^^^^^\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n//│ ═══[COMPILATION ERROR] Invalid type\n\n:e\nfun badanno2: [outer A, outer B] -> Int ->{A | B} Int\n//│ ╔══[COMPILATION ERROR] Only one outer variable can be bound.\n//│ ║  l.165: \tfun badanno2: [outer A, outer B] -> Int ->{A | B} Int\n//│ ╙──       \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Illegal forall annotation.\n//│ ║  l.165: \tfun badanno2: [outer A, outer B] -> Int ->{A | B} Int\n//│ ╙──       \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n//│ ═══[COMPILATION ERROR] Invalid type\n\n\nfun annohelper: [outer, T extends outer] -> Region[out T] ->{T} Pair[out Ref[Int, out T], out Ref[Int, out ~outer]]\nfun annohelper(r1) =\n  region r2 in\n    fork((_ => r1.ref 1), (_ => r2.ref 2))\nannohelper\n//│ Type: [outer, 'T] -> (Region[out 'T]) ->{'T} Pair[out Ref[Int, out 'T], out Ref[Int, out ¬outer]]\n//│ Where:\n//│   'T <: outer\n\n\nregion x in\n  annohelper(x)\n//│ Type: Pair[out Ref[Int, ?], out Ref[Int, ?]]\n\n\nfun annohelper: [outer, T] -> Region[out T & outer] ->{T & outer} Pair[out Ref[Int, out T & outer], out Ref[Int, out ~outer]]\nfun annohelper(r1) =\n  region r2 in\n    fork((_ => r1.ref 1), (_ => r2.ref 2))\nannohelper\n//│ Type: [outer, 'T] -> (Region[out 'T ∧ outer]) ->{'T ∧ outer} Pair[out Ref[Int, out 'T ∧ outer], out Ref[Int, out ¬outer]]\n\n\nregion x in\n  annohelper(x)\n//│ Type: Pair[out Ref[Int, out 'env], out Ref[Int, ?]]\n//│ Where:\n//│   ⊤ <: 'env\n\n\n// Cannot type check since foo: 'foo <: Region[T] ->{'eff} 'app \n// Annotation is required for recursive calls\n:e\nfun foo(r1) =\n  region r2 in\n    fork((_ => r1.ref 1), (_ => r2.ref 2))\n    foo(r2)\n//│ ╔══[COMPILATION ERROR] Type error in function literal\n//│ ║  l.209: \tfun foo(r1) =\n//│ ║         \t       ^^^^^^\n//│ ║  l.210: \t  region r2 in\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.211: \t    fork((_ => r1.ref 1), (_ => r2.ref 2))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.212: \t    foo(r2)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── because: cannot constrain  ('r1) ->{'eff} ('app)  <:  'foo\n//│ ╟── because: cannot constrain  ('r1) ->{'eff} ('app)  <:  (Region[in ⊥ out 'r2]) ->{'eff1} ('app1)\n//│ ╟── because: cannot constrain  Region[in ⊥ out 'r2]  <:  'r1\n//│ ╟── because: cannot constrain  Region[in ⊥ out 'r2]  <:  Region[in ⊥ out 'reg]\n//│ ╟── because: cannot constrain  'r2  <:  'reg\n//│ ╟── because: cannot constrain  ¬outer  <:  'reg\n//│ ╟── because: cannot constrain  ¬outer  <:  ¬'r21 ∨ outer\n//│ ╟── because: cannot constrain  'r21  <:  outer\n//│ ╙── because: cannot constrain  ¬outer  <:  outer\n\n\nfun foo: [outer S, T extends S] -> Region[out T] ->{T} Nothing\nfun foo(r1) =\n  region r2 in\n    foo(r2)\nfoo\n//│ Type: [outer S, 'T] -> (Region[out 'T]) ->{'T} ⊥\n//│ Where:\n//│   'T <: S\n\n\nfun foo: [outer To, T extends To] -> Region[out T] ->{T} ([outer So, S extends So] -> Region[S]->{S} Pair[out Ref[Int, out S], out Ref[Int, out Any]])\nfun foo(r1) =\n  r3 =>\n    region r4 in\n      fork((_ => r3.ref 3), (_ => r4.ref 4))\n\n\nfun bar: [outer S, T extends S] -> Region[out T] ->{T} Int\n\n\nbar as [outer Q, P extends Q] -> Region[P] ->{P} Int\n//│ Type: [outer Q, 'P] -> (Region['P]) ->{'P} Int\n//│ Where:\n//│   'P <: Q\n\n\nfun foo: [outer To, T extends To] -> Region[out T] ->{T} ([outer So, S extends So] -> Region[out S]->{S} Int)\nfun foo(r1) = bar\nfoo\n//│ Type: [outer To, 'T] -> (Region[out 'T]) ->{'T} [outer So, 'S] -> (Region[out 'S]) ->{'S} Int\n//│ Where:\n//│   'T <: To\n//│   'S <: So\n\n\nfun borrow: [S, T, E extends ~S] -> Region[out S] -> ([P] -> Region[out P] ->{E | P} T) ->{E} T\n\n\nfun foo(f) =\n  region r in\n    let x = r.ref 0\n    f(n => x := n)\n    borrow(r) of it =>\n      foo(f)\nfoo\n//│ Type: [outer, 'n, 'eff] -> (('n ->{¬outer} ('n ∨ Int)) ->{'eff} ⊤) ->{'eff} ⊥\n//│ Where:\n//│   'n <: Int\n//│   'eff <: outer\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLEffectAnnots.mls",
    "content": ":invalml\n\n\nfun foo: Int ->{Int} Int\n\nfun foo: Int ->{Int} Int\n\nfun foo: Int -> Int ->{Int} Int\n\nfun foo: Int ->{Int} Int -> Int\n\nfun foo: Int ->{Int} Int ->{Int} Int\n\nfun foo: [A] -> Int ->{A} Int\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLErrors.mls",
    "content": ":invalml\n:e\n\n\n2(2)\n//│ ╔══[COMPILATION ERROR] Type error in application\n//│ ║  l.5: \t2(2)\n//│ ║       \t^^^^\n//│ ╙── because: cannot constrain  Int  <:  (Int) ->{'eff} ('app)\n//│ Type: ⊥\n\n(x => x(0))(1)\n//│ ╔══[COMPILATION ERROR] Type error in integer literal with expected type 'x\n//│ ║  l.12: \t(x => x(0))(1)\n//│ ║        \t            ^\n//│ ╟── because: cannot constrain  Int  <:  'x\n//│ ╙── because: cannot constrain  Int  <:  (Int) ->{'eff} ('app)\n//│ Type: ⊥\n\n(1).Foo#a()\n//│ ╔══[COMPILATION ERROR] Name not found: Foo\n//│ ║  l.20: \t(1).Foo#a()\n//│ ╙──      \t   ^^^^\n//│ ╔══[COMPILATION ERROR] Identifier `Foo` does not name a known class symbol.\n//│ ║  l.20: \t(1).Foo#a()\n//│ ╙──      \t   ^^^^\n//│ ═══[COMPILATION ERROR] Expected a statically known class; found ‹error›.\n//│ ═══[COMPILATION ERROR] Not a valid class: ‹error›\n//│ Type: ⊥\n\n\nfun Oops() = 1\nOops().Oops#a()\n//│ ╔══[COMPILATION ERROR] Identifier `Oops` does not name a known class symbol.\n//│ ║  l.33: \tOops().Oops#a()\n//│ ╙──      \t      ^^^^^\n//│ ╔══[COMPILATION ERROR] Not a valid class: reference\n//│ ║  l.33: \tOops().Oops#a()\n//│ ╙──      \t      ^^^^^\n//│ Type: ⊥\n\ndata class Oops2()\n(new Oops2()).Oops2#a()\n//│ ╔══[COMPILATION ERROR] Class 'Oops2' does not contain member 'a'.\n//│ ║  l.43: \t(new Oops2()).Oops2#a()\n//│ ╙──      \t                    ^\n//│ ╔══[COMPILATION ERROR] a is not a valid member in class Oops2\n//│ ║  l.43: \t(new Oops2()).Oops2#a()\n//│ ╙──      \t ^^^^^^^^^^^^^^^^^^^^\n//│ Type: ⊥\n\n\n\nfun inc(x) = x + 1\ninc(\"oops\")\n//│ ╔══[COMPILATION ERROR] Type error in string literal with expected type 'x\n//│ ║  l.55: \tinc(\"oops\")\n//│ ║        \t    ^^^^^^\n//│ ╟── because: cannot constrain  Str  <:  'x\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Int\n\nfun inc(x) = x + 1\ninc as Int\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type Int\n//│ ║  l.64: \tinc as Int\n//│ ║        \t^^^\n//│ ╙── because: cannot constrain  ('x) ->{⊥} (Int)  <:  Int\n//│ Type: Int\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLExtrude.mls",
    "content": ":invalml\n\nfun f(y) =\n  let local = ((x => y(x) + 1) as [A] -> A -> Int) in y\n\n// * the parameter type of y is extruded.\nf\n//│ Type: ['y] -> 'y -> 'y\n//│ Where:\n//│   'y <: ⊤ -> Int\n\nfun foo: [A] -> A -> Int\nfun foo(x) = 0\n\nfoo\n//│ Type: (⊤) ->{⊥} Int\n\nf(foo)\n//│ Type: ⊤ -> Int\n\nfun g: ([A] -> A -> Int) -> ([A] -> A -> Int)\nfun g(y) =\n  let local = ((x => y(x) + 1) as ([A] -> A -> Int)) in y\n\ng\n//│ Type: ((⊤) ->{⊥} Int) ->{⊥} (⊤) ->{⊥} Int\n\ng(foo)\n//│ Type: (⊤) ->{⊥} Int\n\n:e\ny `=> (let t = run(x `=> x `+ y) in y)\n//│ ╔══[COMPILATION ERROR] Type error in quoted term with expected type CodeBase[out 'T, ⊥, ?]\n//│ ║  l.32: \ty `=> (let t = run(x `=> x `+ y) in y)\n//│ ║        \t                   ^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  CodeBase[in ⊥ out ('x) ->{⊥} ('cde), in ⊥ out 'ctx, in ⊥ out ⊤]  <:  CodeBase[in ⊥ out 'T, ⊥, in ⊥ out ⊤]\n//│ ╟── because: cannot constrain  'ctx  <:  ⊥\n//│ ╟── because: cannot constrain  ¬'x1 ∧ y  <:  ⊥\n//│ ╟── because: cannot constrain  y  <:  'x1\n//│ ╙── because: cannot constrain  y  <:  ⊥\n//│ Type: CodeBase[out 'y -> 'y, ⊥, ?]\n//│ Where:\n//│   'y <: Int\n\ndata class C[A](m: A, n: A -> Int)\n\n\nfun f: [A] -> ([B] -> (C[out B] & A) -> B) -> A -> Int\nf\n//│ Type: ['A] -> (['B] -> (C[out 'B] ∧ 'A) ->{⊥} 'B) ->{⊥} ('A) ->{⊥} Int\n\nfun g: [D] -> C[in Int out D] -> D\ng\n//│ Type: ['D] -> (C[in Int out 'D]) ->{⊥} 'D\n\n\nf(g)\n//│ Type: (¬C[?] ∨ C[in Int out ⊥]) ->{⊥} Int\n\nfun foo: C[in Int out Nothing]\nfoo\n//│ Type: C[in Int out ⊥]\n\nfun bar: C[in Int out Int]\nbar\n//│ Type: C[Int]\n\nf(g)(foo)\n//│ Type: Int\n\n:fixme // ???\nf(g)(bar)\n//│ ╔══[COMPILATION ERROR] Type error in reference of type C[‹not implemented›] with expected type 'A\n//│ ║  l.72: \tf(g)(bar)\n//│ ║        \t     ^^^\n//│ ╟── because: cannot constrain  C[Int]  <:  'A\n//│ ╟── because: cannot constrain  C[Int]  <:  ¬{C[in ⊥ out ¬⊥ ∧ 'B]} ∨ C[in Int out 'D]\n//│ ╟── because: cannot constrain  Int ∧ 'B  <:  'D\n//│ ╟── because: cannot constrain  Int ∧ 'B  <:  'B1\n//│ ╟── because: cannot constrain  Int ∧ 'B  <:  ⊥\n//│ ╟── because: cannot constrain  'B  <:  ¬{Int}\n//│ ╙── because: cannot constrain  ⊤  <:  ¬{Int}\n//│ Type: Int\n\nfun k(x) =\n  fun f(y) = x(y)\n  f(0) + 0\nk\n//│ Type: ['eff] -> (Int ->{'eff} Int) ->{'eff} Int\n\n:e\nk(_ => \"\")\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type 'x\n//│ ║  l.92: \tk(_ => \"\")\n//│ ║        \t  ^^^^^^^\n//│ ╟── because: cannot constrain  ('_) ->{⊥} (Str)  <:  'x\n//│ ╟── because: cannot constrain  ('_) ->{⊥} (Str)  <:  (Int) ->{'eff} (Int)\n//│ ╙── because: cannot constrain  Str  <:  Int\n//│ Type: Int\n\nk(_ => 42)\n//│ Type: Int\n\n\nfun k(x) =\n  fun f: [S, T] -> S -> T\n  fun f(y) = x(y)\n  f(0) + 0\nk\n//│ Type: (⊤ -> ⊥) -> Int\n\n\n:e\nk(_ => \"\")\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type 'x\n//│ ║  l.114: \tk(_ => \"\")\n//│ ║         \t  ^^^^^^^\n//│ ╟── because: cannot constrain  ('_) ->{⊥} (Str)  <:  'x\n//│ ╟── because: cannot constrain  ('_) ->{⊥} (Str)  <:  (⊤) ->{⊥} ⊥\n//│ ╙── because: cannot constrain  Str  <:  ⊥\n//│ Type: Int\n\n:e\nk(_ => 42)\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type 'x\n//│ ║  l.124: \tk(_ => 42)\n//│ ║         \t  ^^^^^^^\n//│ ╟── because: cannot constrain  ('_) ->{⊥} (Int)  <:  'x\n//│ ╟── because: cannot constrain  ('_) ->{⊥} (Int)  <:  (⊤) ->{⊥} ⊥\n//│ ╙── because: cannot constrain  Int  <:  ⊥\n//│ Type: Int\n\n\nfun k(x) =\n  let f = y => x(y)\n  f(0) + 0\nk\n//│ Type: ['eff] -> (Int ->{'eff} Int) ->{'eff} Int\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLFunGenFix.mls",
    "content": ":global\n:invalml\n\n\nclass Reg[out Rg, out AccI]\n\nclass BaseEff\n\nfun basereg: Reg[Any, BaseEff]\n\nfun subreg: [E, Rg, AccI, Res] -> Reg[Rg, AccI] ->\n  ([Rg2] -> Reg[Rg2 & AccI, AccI & ~Rg2] ->{E | Rg2} Res) ->{E} Res\n\nfun write: [Rg, AccI] -> Reg[Rg, AccI] ->{Rg} Int\n\n\nsubreg(basereg) of r0 =>\n  fun helper(a) = write(a)\n  helper(r0)\n//│ Type: Int\n\n\nfun helper(a) = write(a)\n\nhelper\n//│ Type: ['Rg] -> Reg[out 'Rg, ?] ->{'Rg} Int\n\nsubreg(basereg) of r0 =>\n  helper(r0)\n//│ Type: Int\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLFuns.mls",
    "content": ":invalml\n\n\nfun f(x, y) = x(y)\nf\n//│ Type: ['y, 'eff, 'app] -> ('y ->{'eff} 'app, 'y) ->{'eff} 'app\n\n\nf((x => x), 42)\n//│ Type: Int\n\nf(x => x, 42)\n//│ Type: Int\n\n\nfun id: [A] -> A -> A\n\nid as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\nid(id) as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\n\ndata class Nil()\ndata class Cons[A, B](val car: A, val cdr: B)\ndata class Ls[A](prim: [R] -> (() -> R, (A, Ls[A]) -> R) -> R)\n\nfun nil() = new Ls((n, _) => n())\nfun cons(p, q) = new Ls((n, r) => r(p, q))\nfun from(x) = x.Ls#prim(() => new Nil, (x, y) => new Cons(x, from(y)))\nfun to(x) = if x is\n  Nil then nil()\n  Cons then cons(x.Cons#car, to(x.Cons#cdr))\n\nlet foo = nil() from()\nfoo\n//│ Type: Cons['A, 'B] ∨ Nil\n//│ Where:\n//│   ⊥ <: 'A\n//│   Cons['A, 'B] <: 'R\n//│   Nil <: 'R\n//│   'R <: 'B\n\n\nfoo to()\n//│ Type: Ls['A] ∨ Ls['A1]\n//│ Where:\n//│   ⊥ <: 'A\n//│   'A <: 'A1\n//│   ⊥ <: 'A1\n//│   'A1 <: 'A\n\n\nfun (;) seq(_, res) = res\n\nfun foo: [R1, R2] -> (Region[R1], Region[R2], Int ->{R1 & ~R2} (), Int ->{R2 & ~R1} ()) ->{R1 | R2} () \nfun foo(r1, r2, f, g) =\n  f(123); g(456)\n\nfoo\n//│ Type: ['R1, 'R2] -> (Region['R1], Region['R2], (Int) ->{'R1 ∧ ¬'R2} (), (Int) ->{'R2 ∧ ¬'R1} ()) ->{'R1 ∨ 'R2} ()\n\n\n:e\nfun foo[outer, R <: outer](r1: Region[R]) =\n  region r2 in 42\n//│ ╔══[COMPILATION ERROR] Unsupported type parameter outer binding\n//│ ║  l.67: \tfun foo[outer, R <: outer](r1: Region[R]) =\n//│ ╙──      \t        ^^^^^\n//│ ╔══[COMPILATION ERROR] Unsupported type parameter operator application\n//│ ║  l.67: \tfun foo[outer, R <: outer](r1: Region[R]) =\n//│ ╙──      \t               ^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: R\n//│ ║  l.67: \tfun foo[outer, R <: outer](r1: Region[R]) =\n//│ ╙──      \t                                      ^\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Invalid type\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLGPCE.mls",
    "content": "\n:global\n:invalml\n\n\nfun power: [C] -> CodeBase[out Num, out C, out Any] -> Int -> CodeBase[out Num, out C, out Any]\nfun power(x) = case\n  0 then `1.0\n  n then x `*. power(x)(n - 1)\npower\n//│ Type: ['C] -> (CodeBase[out Num, out 'C, ?]) ->{⊥} (Int) ->{⊥} CodeBase[out Num, out 'C, ?]\n\n\nfun id: [A] -> A -> A\nfun id(x) = x\n\n\nrun(x `=> id(x) `* x)\n//│ Type: Int -> Int\n\n\nfun assertNotZero: [C] -> CodeBase[out Num, out C, out Any] -> CodeBase[out Num, out C, out Any]\nfun assertNotZero(x) =\n  `if (x `== `0.0) then `error else x\nlet checkedDiv = x `=> y `=> x `/. (assertNotZero(y))\nrun(checkedDiv)\n//│ Type: Num -> (Num -> Num)\n\n\n\nfun show: [T] -> CodeBase[out T, out Any, out Any] -> Str = s => \"debug\"\nshow\n//│ Type: (CodeBase[?, ?, ?]) ->{⊥} Str\n\n\n\nfun inc(dbg) =\n  x `=> let c = x `+ `1 in let t = dbg(c) in c\ninc\n//│ Type: ['eff] -> (CodeBase[out Int, ?, ?] ->{'eff} ⊤) ->{'eff} CodeBase[out Int -> Int, ⊥, ?]\n\ninc(c => log(show(c)))\n//│ Type: CodeBase[out Int -> Int, ⊥, ?]\n\n\nfun body: [T, C] -> (CodeBase[out Int, out T, out Any], CodeBase[out Int, out C, out Any]) -> Int -> CodeBase[out Int, out T | C, out Any]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then body(y, x `+ y)(n - 1)\nfun gib_naive(n) =\n  (x, y) `=> body(x, y)(n)\nlet gn5 = run(gib_naive(5))\n\nfun bind(rhs, k) = `let x = rhs `in k(x)\nbind\n//│ Type: ['cde, 'ctx, 'eff, 'cde1, 'ctx1] -> (CodeBase[out 'cde, out 'ctx, ?], CodeBase['cde, ?, ⊥] ->{'eff} CodeBase[out 'cde1, out 'ctx1, ?]) ->{'eff} CodeBase[out 'cde1, out 'ctx ∨ 'ctx1, ?]\n\n:e\nfun body: [G] -> (CodeBase[out Int, out G, out Any], CodeBase[out Int, out G, out Any]) -> Int -> CodeBase[out Int, out G, out Any]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then bind of x `+ y, (z => body(y, z)(n - 1))\n//│ ╔══[COMPILATION ERROR] Type error in application with expected type CodeBase[out Int, out G, ?]\n//│ ║  l.64: \t  n then bind of x `+ y, (z => body(y, z)(n - 1))\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  CodeBase[in ⊥ out 'cde, in ⊥ out 'ctx ∨ 'ctx1, in ⊥ out ⊤]  <:  CodeBase[in ⊥ out Int, in ⊥ out G, in ⊥ out ⊤]\n//│ ╟── because: cannot constrain  'ctx ∨ 'ctx1  <:  G\n//│ ╟── because: cannot constrain  'ctx1  <:  G\n//│ ╟── because: cannot constrain  'ctx2  <:  G\n//│ ╙── because: cannot constrain  ⊤  <:  G\n\nfun bind: [G] -> (CodeBase[out Int, out G, out Any], [C] -> CodeBase[out Int, out C, out Any] -> CodeBase[out Int, out C | G, out Any]) -> CodeBase[out Int, out G, out Any]\nfun bind(rhs, k) = `let x = rhs `in k(x)\nbind\n//│ Type: ['G] -> (CodeBase[out Int, out 'G, ?], ['C] -> (CodeBase[out Int, out 'C, ?]) ->{⊥} CodeBase[out Int, out 'C ∨ 'G, ?]) ->{⊥} CodeBase[out Int, out 'G, ?]\n\n\nfun body: [G] -> (CodeBase[out Int, out G, out Any], CodeBase[out Int, out G, out Any]) -> Int -> CodeBase[out Int, out G, out Any]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then bind of x `+ y, (z => body(y, z)(n - 1))\nbody\n//│ Type: ['G] -> (CodeBase[out Int, out 'G, ?], CodeBase[out Int, out 'G, ?]) ->{⊥} (Int) ->{⊥} CodeBase[out Int, out 'G, ?]\n\nfun gib(n) = (x, y) `=> body(x, y)(n)\nlet g5 = run(gib(5))\ng5\n//│ Type: (Int, Int) -> Int\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLGetters.mls",
    "content": ":js\n:noSanityCheck // * For some reason, these cause problems\n\n:global\n:invalml\n\n\n:todo\nfun test1() =\n  fun sayHi = print(\"Hi\")\n  sayHi, sayHi, sayHi\n//│ ╔══[COMPILATION ERROR] Function definition shape not yet supported for sayHi\n//│ ║  l.10: \t  fun sayHi = print(\"Hi\")\n//│ ╙──      \t              ^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Variable not found: sayHi\n//│ ║  l.11: \t  sayHi, sayHi, sayHi\n//│ ╙──      \t  ^^^^^\n//│ ╔══[COMPILATION ERROR] Variable not found: sayHi\n//│ ║  l.11: \t  sayHi, sayHi, sayHi\n//│ ╙──      \t         ^^^^^\n//│ ╔══[COMPILATION ERROR] Variable not found: sayHi\n//│ ║  l.11: \t  sayHi, sayHi, sayHi\n//│ ╙──      \t                ^^^^^\n\ntest1()\n//│ > Hi\n//│ > Hi\n//│ > Hi\n//│ Type: ⊥\n\n\n:todo // it feels like this should work\nfun test2() =\n  fun funny = case\n    0 then 0\n    n then funny(n - 1) + 1\n  funny\n//│ ╔══[COMPILATION ERROR] Expected a monomorphic type or an instantiable type here, but () ->{⊥} [outer, 'caseScrut, 'eff] -> 'caseScrut ->{'eff} Int found\n//│ ║  l.33: \tfun test2() =\n//│ ║        \t         ^^^^\n//│ ║  l.34: \t  fun funny = case\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.35: \t    0 then 0\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.36: \t    n then funny(n - 1) + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.37: \t... (more lines omitted) ...\n//│ ╙──      \t^^^^^^^\n\nfun test2() =\n  fun funny = case\n    0 then 0\n    n then funny(n - 1) + 1\n  funny(_)\n\ntest2\n//│ = fun test2\n//│ Type: () -> (Int -> Int)\n\n:sjs\ntest2()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ test21()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n//│ Type: Int -> Int\n\n:ssjs\ntest2()(5)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let baseCall;\n//│ baseCall = test21(); block$res8 = runtime.safeCall(baseCall(5)); undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 5\n//│ Type: Int\n\n\n// * Notice the mistake here; we warn that the first case in statement position is useless!\n:w\n:e\n:sjs\nfun test2() =\n  fun funny = \n    case 0 then 0\n    case n then funny(n - 1) + 1\n  funny\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.84: \t    case 0 then 0\n//│ ╙──      \t    ^^^^^^^^^^^^^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test22;\n//│ test22 = function test2() {\n//│   let funny;\n//│   funny = function funny() {\n//│     let lambda1;\n//│     lambda1 = (undefined, function (caseScrut) {\n//│       let n, tmp, tmp1, tmp2;\n//│       n = caseScrut;\n//│       tmp = funny();\n//│       tmp1 = n - 1;\n//│       tmp2 = runtime.safeCall(tmp(tmp1));\n//│       return tmp2 + 1\n//│     });\n//│     return lambda1\n//│   };\n//│   return funny()\n//│ };\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.84: \t    case 0 then 0\n//│ ╙──      \t    ^^^^^^^^^^^^^\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ╔══[COMPILATION ERROR] Function definition shape not yet supported for funny\n//│ ║  l.84: \t    case 0 then 0\n//│ ║        \t         ^^^^^^^^\n//│ ║  l.85: \t    case n then funny(n - 1) + 1\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Variable not found: funny\n//│ ║  l.86: \t  funny\n//│ ╙──      \t  ^^^^^\n\n\n:todo\nfun test3 =\n  print(\"Hi\")\n//│ ╔══[COMPILATION ERROR] Function definition shape not yet supported for test3\n//│ ║  l.124: \t  print(\"Hi\")\n//│ ╙──       \t  ^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLId.mls",
    "content": ":invalml\n\n\nfun id(x) = x\n\nid(1)\n//│ Type: Int\n\nid\n//│ Type: ['x] -> 'x -> 'x\n\nid(true)\n//│ Type: Bool\n\nid\n//│ Type: ['x] -> 'x -> 'x\n\n\nfun id(x) = x\n\nid as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\n(y => y) as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\nfun id(x) = x\n(y => id(y)) as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLLetRegEncoding.mls",
    "content": ":invalml\n\n\n\nfun letreg: [E,Res] -> ([R] -> Region[out R] ->{E | R} Res) ->{E} Res\n\nletreg\n//│ Type: ['E, 'Res] -> (['R] -> (Region[out 'R]) ->{'E ∨ 'R} 'Res) ->{'E} 'Res\n\nletreg(r => r)\n//│ Type: Region[?]\n\n:e\nletreg(r => r).ref 1\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.14: \tletreg(r => r).ref 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'E  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'R  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Ref[Int, ?]\n\nletreg(r => r.ref 1)\n//│ Type: Ref[Int, ?]\n\nletreg(r => !(r.ref 1))\n//│ Type: Int\n\n:e\n!(letreg(r => r.ref 1))\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.31: \t!(letreg(r => r.ref 1))\n//│ ║        \t  ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'E  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'reg1  <:  ⊥\n//│ ╟── because: cannot constrain  'R  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Int\n\nletreg of r =>\n  let x = r.ref 1\n  x := !(x) + 1\n  !(x)\n//│ Type: Int\n\nlet f = letreg(r => arg => r.ref arg)\n\nf\n//│ Type: 'arg ->{⊤} Ref['arg, ?]\n\n:e\nletreg(r => arg => r.ref arg)(0)\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.54: \tletreg(r => arg => r.ref arg)(0)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'eff ∨ 'E  <:  ⊥\n//│ ╟── because: cannot constrain  'eff  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'R  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Ref['arg, ?]\n//│ Where:\n//│   Int <: 'arg\n\n\n\n// * An incorrect one, just for testing the error:\n\nfun letreg: [E,Res] -> ([R] -> Region[out R] -> Res) ->{E} Res\n\n:e\nletreg(r => r.ref 1)\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type (Region[out R]) ->{⊥} 'Res\n//│ ║  l.74: \tletreg(r => r.ref 1)\n//│ ║        \t       ^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╙── because: cannot constrain  R  <:  ⊥\n//│ Type: Ref[Int, ?]\n\n:e\nletreg(r => !(r.ref 1))\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type (Region[out R]) ->{⊥} 'Res\n//│ ║  l.83: \tletreg(r => !(r.ref 1))\n//│ ║        \t       ^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'reg1  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'reg1  <:  ⊥\n//│ ╙── because: cannot constrain  R  <:  ⊥\n//│ Type: Int\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLList.mls",
    "content": ":invalml\n\n\n\ndata class List[A](inspect: [E, Res] -> (() ->{E} Res, (A, List[A]) ->{E} Res) ->{E} Res)\n\nfun map: [A, B, E] -> List[out A] -> (A ->{E} B) ->{E} List[out B]\n\n\n// * Dummy implementation\nfun mapi: [A, E] -> List[out A] -> ((Int, A) ->{E} A) ->{E} List[out A]\nfun mapi = s => f =>\n  region r in\n    map(s) of x => f(0, x)\n\nfun mapi: [A, E] -> List[out A] -> ((Int, A) ->{E} A) ->{E} List[out A]\nfun mapi = s => f =>\n  region r in\n    let i = r.ref 0\n    map(s) of x =>\n      i := !(i) + 1\n      f(!(i), x)\n\n// * Example usage\n\nfun mkList: [A] -> A -> List[out A]\nfun head: [A] -> List[out A] -> A\n\nregion r in\n  let sum = r.ref 0\n  let s1 = mkList of !(sum)\n  let s2 = mapi(s1) of (x, i) => x * i\n  !(sum) + head(s2)\n//│ Type: Int\n\n\n// * Should be an error. This definition would not be referentially transparent.\n// * The error message needs improvement, though.\n:e\nfun mapi: [A, E] -> List[out A] -> ((Int, A) ->{E} A) ->{E} List[out A]\nfun mapi = s =>\n  region r in\n    let i = r.ref 0\n    f => map(s) of x =>\n      i := !(i) + 1\n      f(!(i), x)\n//│ ╔══[COMPILATION ERROR] Type error in region expression with expected type ((Int, A) ->{E} A) ->{E} List[out A]\n//│ ║  l.43: \t    let i = r.ref 0\n//│ ║        \t            ^^^^^^^\n//│ ║  l.44: \t    f => map(s) of x =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.45: \t      i := !(i) + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.46: \t      f(!(i), x)\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  ('f) ->{'E1} (List[in ⊥ out 'B])  <:  ((Int, A) ->{E} (A)) ->{E} (List[in ⊥ out A])\n//│ ╟── because: cannot constrain  'E1  <:  E\n//│ ╟── because: cannot constrain  'reg  <:  E\n//│ ╟── because: cannot constrain  'r ∧ ¬outer  <:  E\n//│ ╟── because: cannot constrain  'r  <:  E ∨ outer\n//│ ╙── because: cannot constrain  ¬outer  <:  E ∨ outer\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLOption.mls",
    "content": ":invalml\n\n\ndata class Option[out A](inspect: [E, Res] -> (() ->{E} Res, A ->{E} Res) ->{E} Res)\n\nopt => opt.Option#inspect\n//│ Type: (Option[out 'A]) ->{⊥} ['E, 'Res] -> (() ->{'E} 'Res, ('A) ->{'E} 'Res) ->{'E} 'Res\n\nopt => opt.Option#inspect(\n  () => 42\n  n => n + 1\n)\n//│ Type: (Option[out Int]) ->{⊥} Int\n\nopt => opt.Option#inspect of () => 42, n => n + 1\n//│ Type: (Option[out Int]) ->{⊥} Int\n\nopt => opt.Option#inspect of\n  () => 42\n  n => n + 1\n//│ Type: (Option[out Int]) ->{⊥} Int\n\n\nopt => opt as Option[out Int]\n//│ Type: (Option[out Int]) ->{⊥} Option[out Int]\n\nopt => (opt as Option[Int]) as Option[Int | Str]\n//│ Type: (Option[out Int ∨ Str] ∧ Option[out Int]) ->{⊥} Option[out Int ∨ Str]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLPoly.mls",
    "content": ":invalml\n\n\n42 as [A] -> Int\n//│ Type: Int\n\n:e\n42 as [A] -> Str\n//│ ╔══[COMPILATION ERROR] Type error in integer literal with expected type Str\n//│ ║  l.8: \t42 as [A] -> Str\n//│ ║       \t^^\n//│ ╙── because: cannot constrain  Int  <:  Str\n//│ Type: Str\n\nfun id: [A] -> A -> A\nfun id(x) = x\n\nid\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n:e\n(x => x + 1) as [A] -> A -> A\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type Int\n//│ ║  l.22: \t(x => x + 1) as [A] -> A -> A\n//│ ║        \t      ^\n//│ ╙── because: cannot constrain  A  <:  Int\n//│ ╔══[COMPILATION ERROR] Type error in application with expected type A\n//│ ║  l.22: \t(x => x + 1) as [A] -> A -> A\n//│ ║        \t      ^^^^^\n//│ ╙── because: cannot constrain  Int  <:  A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\n(x => x) as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\nid as [A] -> A -> A\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\nid as Int -> Int\n//│ Type: (Int) ->{⊥} Int\n\nfun myInc(inc: Int -> Int, x: Int) = inc(x)\n\nmyInc(id, 0)\n//│ Type: Int\n\nlet t = 42 in ((x => x) as [A] -> A -> A)\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\nid(42)\n//│ Type: Int\n\nid(\"abc\")\n//│ Type: Str\n\n\ndata class Pair[A, B](a: A, b: B)\n\nnew Pair(42, true)\n//│ Type: Pair['A, 'B]\n//│ Where:\n//│   Int <: 'A\n//│   Bool <: 'B\n\nfun swap: [A, B] -> Pair[out A, out B] -> Pair[out B, out A]\nfun swap(p) = new Pair(p.Pair#b, p.Pair#a)\n\n\nswap\n//│ Type: ['A, 'B] -> (Pair[out 'A, out 'B]) ->{⊥} Pair[out 'B, out 'A]\n\nlet t = new Pair(42, true) in swap(t)\n//│ Type: Pair[out Bool, out Int]\n\nlet t = new Pair(\"114\", \"514\") in swap(t)\n//│ Type: Pair[out Str, out Str]\n\nlet id = ((x => x) as [A] -> A -> A) in new Pair(id(42), id(\"42\"))\n//│ Type: Pair['A, 'B]\n//│ Where:\n//│   Int <: 'A\n//│   Str <: 'B\n\nfun foo: ([A] -> A -> A) -> Int\nfun foo(x) = 42\n\nfoo\n//│ Type: (['A] -> ('A) ->{⊥} 'A) ->{⊥} Int\n\nfoo(id)\n//│ Type: Int\n\nfoo(x => x)\n//│ Type: Int\n\ndata class Foo(foo: [A] -> A -> A)\n\nnew Foo(id)\n//│ Type: Foo\n\n\nnew Foo(x => x)\n//│ Type: Foo\n\nlet foo = new Foo(id) in foo.Foo#foo(42)\n//│ Type: Int\n\ndata class Bar[A](x: A, f: [B] -> B -> B)\n\n\nnew Bar(0, id)\n//│ Type: Bar['A]\n//│ Where:\n//│   Int <: 'A\n\nlet bar = new Bar(0, id) in bar.Bar#f(bar.Bar#x)\n//│ Type: Int\n\ndata class Some[A](value: A)\n\nnew Some((x => x) as [A] -> A -> A)\n//│ Type: Some['A]\n//│ Where:\n//│   'x -> 'x <: 'A\n\nlet s = new Some((x => x) as [A] -> A -> A) in let t = s.Some#value(42) in s.Some#value(false)\n//│ Type: Bool ∨ Int\n\nfun gen: Int -> [A] -> A -> A\nfun gen(x) =\n  let t = x + 1 in ((y => y) as [A] -> A -> A)\n\ngen\n//│ Type: (Int) ->{⊥} ['A] -> ('A) ->{⊥} 'A\n\n\ngen(42)\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n\n\n:e\nfun cnt: Some[out [A] -> A -> A] -> Int\nfun cnt(x) = 42\n//│ ╔══[COMPILATION ERROR] General type is not allowed here.\n//│ ║  l.144: \tfun cnt: Some[out [A] -> A -> A] -> Int\n//│ ╙──       \t                         ^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLPrelude.mls",
    "content": ":ignore\n// ^ Ignore the silly warnings below, which are due to `untyped` not being treated as THE `untyped` builtin\n\n\ndeclare class Any\ndeclare class Nothing\ndeclare class Object\n\ndeclare class untyped\n\ndeclare class tailrec\ndeclare class tailcall\n\ndeclare class Unit\ndeclare class Bool\ndeclare class Int\ndeclare class Num\ndeclare class TypedArray\n\ndeclare class BigInt\n\ndeclare class Int31\n\nfun String: Any -> Str\n\ndata\n  class\n    CodeBase[T, C, S]\n    Region[T]\n    Ref[T, S](reg: Region[T], value: S)\n\n@untyped\nset\n  globalThis.CodeBase = CodeBase\n  globalThis.Region = Region\n  globalThis.Ref = (r, v) => new mut Ref(r, v)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.32: \t@untyped\n//│ ║        \t^^^^^^^^\n//│ ╟── This annotation is not supported on assignment terms.\n//│ ║  l.34: \t  globalThis.CodeBase = CodeBase\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.32: \t@untyped\n//│ ║        \t^^^^^^^^\n//│ ╟── This annotation is not supported on assignment terms.\n//│ ║  l.35: \t  globalThis.Region = Region\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.32: \t@untyped\n//│ ║        \t^^^^^^^^\n//│ ╟── This annotation is not supported on assignment terms.\n//│ ║  l.36: \t  globalThis.Ref = (r, v) => new mut Ref(r, v)\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\ndeclare class Function\n\ndeclare class Str(length: Int, concat: Str -> Str)\n\ndeclare class Error(msg: Str)\n\n\ndeclare module source with\n  object\n    line: Int\n    name: Str\n    file: Str\n\ndeclare class Array[T](val length: Int): Array[T]\n\ndeclare object Symbol with\n  // The `TermDef` needs `rhs` to be defined to be recognized as `isMLsFun`.\n  // Otherwise, it would be wrapped in `runtime.safeCall`, which accesses the\n  // uninitialized `runtime` in the `Rendering` module.\n  fun for: Str -> Any = ()\n  val iterator: Any\n\ndeclare module js with\n  fun\n    bitand\n    bitnot\n    bitor\n    shl\n    try_catch\n\ndeclare module wasm with\n  fun\n    plus_impl\n    minus_impl\n    times_impl\n    div_impl\n    mod_impl\n    eq_impl\n    neq_impl\n    lt_impl\n    le_impl\n    gt_impl\n    ge_impl\n    neg_impl\n    pos_impl\n    not_impl\n\ndeclare module debug with\n  fun printStack\n\ndeclare module annotations with\n  object compile\n  object buffered\n  object bufferable\n\ndeclare module scope with\n  fun locally\n\ndeclare module runtime with\n  fun\n    suspend\n    handle_suspension\n\n\ndeclare fun run: [T] -> CodeBase[out T, out Nothing, out Any] -> T\ndeclare fun log: Str -> Any\ndeclare fun error: Nothing\n\ndeclare fun (+): (Int, Int) -> Int\ndeclare fun (-): (Int, Int) -> Int\ndeclare fun (*): (Int, Int) -> Int\ndeclare fun (/): (Int, Int) -> Num\ndeclare fun (+.): (Num, Num) -> Num\ndeclare fun (-.): (Num, Num) -> Num\ndeclare fun (*.): (Num, Num) -> Num\ndeclare fun (/.): (Num, Num) -> Num\n\ndeclare fun (<): (Int, Int) -> Bool\ndeclare fun (>): (Int, Int) -> Bool\ndeclare fun (<=): (Int, Int) -> Bool\ndeclare fun (>=): (Int, Int) -> Bool\ndeclare fun (==): [T] -> (T, T) -> Bool\ndeclare fun (!=): [T] -> (T, T) -> Bool\ndeclare fun (===): [T] -> (T, T) -> Bool\ndeclare fun (!==): [T] -> (T, T) -> Bool\n\ndeclare fun (&&): (Bool, Bool) -> Bool\ndeclare fun (||): (Bool, Bool) -> Bool\n\n\nfun print(x) = @untyped globalThis.console.log(x)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.146: \tfun print(x) = @untyped globalThis.console.log(x)\n//│ ║         \t               ^^^^^^^^\n//│ ╟── This annotation is not supported on application terms.\n//│ ║  l.146: \tfun print(x) = @untyped globalThis.console.log(x)\n//│ ╙──       \t                        ^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLQQ.mls",
    "content": ":invalml\n\n\n`42\n//│ Type: CodeBase[out Int, ⊥, ?]\n\n:p\n`false\n//│ ┊`┊false┊\n//│ Parsed:\n//│ \tQuoted(BoolLit(false))\n//│ Type: CodeBase[out Bool, ⊥, ?]\n\n`\"rua\"\n//│ Type: CodeBase[out Str, ⊥, ?]\n\n`3.14\n//│ Type: CodeBase[out Num, ⊥, ?]\n\n\nx `=> x\n//│ Type: CodeBase[out 'x -> 'x, ⊥, ?]\n\nx `=> `42\n//│ Type: CodeBase[out ⊤ -> Int, ⊥, ?]\n\n:e\nx `=> 42\n//│ ╔══[COMPILATION ERROR] Type error in unquoted term\n//│ ║  l.28: \tx `=> 42\n//│ ║        \t      ^^\n//│ ╙── because: cannot constrain  Int  <:  CodeBase[in ⊥ out 'cde, in ⊥ out 'ctx, in ⊥ out ⊤]\n//│ Type: CodeBase[out ⊤ -> ⊥, ⊥, ?]\n\n\nf `=> x `=> f`(x)\n//│ Type: CodeBase[out ('x -> 'app) -> ('x -> 'app), ⊥, ?]\n\n\n\nx `=> y `=> x `+ y\n//│ Type: CodeBase[out Int -> (Int -> Int), ⊥, ?]\n\n\n\n(x, y) `=> x `+ y\n//│ Type: CodeBase[out (Int, Int) -> Int, ⊥, ?]\n\n\n(x, y, z) `=> x `+ y `+ z\n//│ Type: CodeBase[out (Int, Int, Int) -> Int, ⊥, ?]\n\nf `=> x `=> y `=> f`(x, y)\n//│ Type: CodeBase[out (('x, 'y) -> 'app) -> ('x -> ('y -> 'app)), ⊥, ?]\n\n`let x = `42 `in x\n//│ Type: CodeBase[out Int, ⊥, ?]\n\n:e\n`let x = 42 `in x\n//│ ╔══[COMPILATION ERROR] Type error in unquoted term\n//│ ║  l.60: \t`let x = 42 `in x\n//│ ║        \t         ^^\n//│ ╙── because: cannot constrain  Int  <:  CodeBase[in ⊥ out 'cde, in ⊥ out 'ctx, in ⊥ out ⊤]\n//│ Type: CodeBase[⊥, ⊥, ?]\n\n:e\n`let x = `0 `in 1\n//│ ╔══[COMPILATION ERROR] Type error in unquoted term\n//│ ║  l.68: \t`let x = `0 `in 1\n//│ ║        \t                ^\n//│ ╙── because: cannot constrain  Int  <:  CodeBase[in ⊥ out 'cde, in ⊥ out 'ctx, in ⊥ out ⊤]\n//│ Type: CodeBase[⊥, ⊥, ?]\n\n\n\n`if `true then `true else `false\n//│ Type: CodeBase[out Bool, ⊥, ?]\n\n\n\nx `=> `if x `=== `0.0 then `1.0 else x\n//│ Type: CodeBase[out 'x -> ('x ∨ Num), ⊥, ?]\n\nrun(`1)\n//│ Type: Int\n\n\n:e\nrun(1)\n//│ ╔══[COMPILATION ERROR] Type error in integer literal with expected type CodeBase[out 'T, ⊥, ?]\n//│ ║  l.90: \trun(1)\n//│ ║        \t    ^\n//│ ╙── because: cannot constrain  Int  <:  CodeBase[in ⊥ out 'T, ⊥, in ⊥ out ⊤]\n//│ Type: ⊥\n\n:e\nx `=> run(x)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type CodeBase[out 'T, ⊥, ?]\n//│ ║  l.98: \tx `=> run(x)\n//│ ║        \t          ^\n//│ ╟── because: cannot constrain  CodeBase['x, x, ⊥]  <:  CodeBase[in ⊥ out 'T, ⊥, in ⊥ out ⊤]\n//│ ╙── because: cannot constrain  x  <:  ⊥\n//│ Type: CodeBase[out CodeBase[out 'cde, ?, ?] -> 'cde, out 'ctx, ?]\n\n:e\n`let x = `42 `in run(x)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type CodeBase[out 'T, ⊥, ?]\n//│ ║  l.107: \t`let x = `42 `in run(x)\n//│ ║         \t                     ^\n//│ ╟── because: cannot constrain  CodeBase['cde, x, ⊥]  <:  CodeBase[in ⊥ out 'T, ⊥, in ⊥ out ⊤]\n//│ ╙── because: cannot constrain  x  <:  ⊥\n//│ ╔══[COMPILATION ERROR] Type error in unquoted term\n//│ ║  l.107: \t`let x = `42 `in run(x)\n//│ ║         \t                 ^^^^^^\n//│ ╟── because: cannot constrain  'T  <:  CodeBase[in ⊥ out 'cde1, in ⊥ out 'ctx, in ⊥ out ⊤]\n//│ ╟── because: cannot constrain  'cde  <:  CodeBase[in ⊥ out 'cde1, in ⊥ out 'ctx, in ⊥ out ⊤]\n//│ ╟── because: cannot constrain  'cde  <:  CodeBase[in ⊥ out 'cde2, in ⊥ out 'ctx1, in ⊥ out ⊤]\n//│ ╙── because: cannot constrain  Int  <:  CodeBase[in ⊥ out 'cde2, in ⊥ out 'ctx1, in ⊥ out ⊤]\n//│ Type: CodeBase[⊥, ⊥, ?]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLRec.mls",
    "content": ":invalml\n\n\n:fixme // parsing\nfun f x = f\n//│ ╔══[COMPILATION ERROR] Invalid function definition head: unexpected identifier in this position\n//│ ║  l.5: \tfun f x = f\n//│ ╙──     \t      ^\n//│ ╔══[COMPILATION ERROR] Function definition shape not yet supported for f\n//│ ║  l.5: \tfun f x = f\n//│ ╙──     \t          ^\n\n:e\nf\n//│ ╔══[COMPILATION ERROR] Variable not found: f\n//│ ║  l.14: \tf\n//│ ╙──      \t^\n//│ Type: ⊥\n\n:e\nx\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.21: \tx\n//│ ╙──      \t^\n//│ Type: ⊥\n\nfun f(x) = f\nf\n//│ Type: ['f] -> ⊤ -> (⊤ -> 'f)\n//│ Where:\n//│   ⊤ -> 'f <: 'f\n\nfun f(x) = f(x)\nf\n//│ Type: ⊤ -> ⊥\n\n:todo\nfun f(x) = f(x.a)\n//│ ╔══[COMPILATION ERROR] Term shape not yet supported by InvalML: Sel(Ref(x),Ident(a))\n//│ ║  l.38: \tfun f(x) = f(x.a)\n//│ ╙──      \t             ^^^\n\n\ndata class Foo[A](a: A)\n\n:todo proper error\nFoo(123)\n//│ ╔══[COMPILATION ERROR] Variable not found: Foo\n//│ ║  l.47: \tFoo(123)\n//│ ╙──      \t^^^\n//│ Type: ⊥\n\nnew Foo(123)\n//│ Type: Foo['A]\n//│ Where:\n//│   Int <: 'A\n\n:todo proper error\nfun f(x) = f(Foo.a(x))\n//│ ╔══[COMPILATION ERROR] Term shape not yet supported by InvalML: Sel(Ref(member:Foo),Ident(a))\n//│ ║  l.59: \tfun f(x) = f(Foo.a(x))\n//│ ╙──      \t             ^^^^^\n\nfun f(x) = f(x.Foo#a)\nf\n//│ Type: ['x] -> Foo[out 'x] -> ⊥\n//│ Where:\n//│   'x <: Foo[out 'x]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLRef.mls",
    "content": ":invalml\n\n\nregion x in 42\n//│ Type: Int\n\nregion x in x\n//│ Type: Region[?]\n\n\nregion x in x.ref 42\n//│ Type: Ref[Int, ?]\n\nlet r = region x in x.ref 42\nr\n//│ Type: Ref[Int, ?]\n\n:e\nlet r = region x in x.ref 42\n!(r)\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.19: \tlet r = region x in x.ref 42\n//│ ║        \t                    ^^^^^^^^\n//│ ║  l.20: \t!(r)\n//│ ║        \t^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'eff  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'reg1  <:  ⊥\n//│ ╟── because: cannot constrain  'x  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Int\n\nfun mkRef() = region x in x.ref 42\nmkRef\n//│ Type: [outer] -> () -> Ref[Int, out ¬outer]\n\n:e\nlet t = region x in x in t.ref 42\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.38: \tlet t = region x in x in t.ref 42\n//│ ║        \t                    ^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'eff  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'x  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Ref[Int, ?]\n\n\nregion x in\n  let r = x.ref 42 in r := 0\n//│ Type: Int\n\n:e\nlet t = region x in\n  x.ref 42\nin t := 0\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.55: \t  x.ref 42\n//│ ║        \t  ^^^^^^^^\n//│ ║  l.56: \tin t := 0\n//│ ║        \t^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'eff  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'reg1  <:  ⊥\n//│ ╟── because: cannot constrain  'x  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Int\n\n\nregion x in\n  let r = x.ref 42 in !(r)\n//│ Type: Int\n\n:e\nlet t = region x in\n  x.ref 42\nin !(t)\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.76: \t  x.ref 42\n//│ ║        \t  ^^^^^^^^\n//│ ║  l.77: \tin !(t)\n//│ ║        \t^^^^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'eff  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'reg1  <:  ⊥\n//│ ╟── because: cannot constrain  'x  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Int\n\nregion x in\n  let r = x.ref 42 in let t = r := 0 in !(r)\n//│ Type: Int\n\nfun rid: [A] -> A -> A\nfun rid(x) =\n  let t = (region y in 42) in x\n\n\nfun rid: [A] -> A -> A\nfun rid(x) =\n  let t = (region y in 42) in x\n\n:e\nregion x in\n  (let dz = x.ref 42 in 42) as [A] -> Int\n//│ ╔══[COMPILATION ERROR] Type error in block with expected type [outer, 'A] -> Int\n//│ ║  l.105: \t  (let dz = x.ref 42 in 42) as [A] -> Int\n//│ ║         \t            ^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╙── because: cannot constrain  x  <:  ⊥\n//│ Type: Int\n\n\n:e\nlet t =\n  region x in\n    y => x.ref y\nin t(42)\n//│ ╔══[COMPILATION ERROR] Type error in block\n//│ ║  l.117: \t    y => x.ref y\n//│ ║         \t    ^^^^^^^^^^^^\n//│ ║  l.118: \tin t(42)\n//│ ║         \t^^^^^^^^\n//│ ╟── because: cannot constrain  'reg ∨ 'eff  <:  ⊥\n//│ ╟── because: cannot constrain  'reg  <:  ⊥\n//│ ╟── because: cannot constrain  'x  <:  ⊥\n//│ ╙── because: cannot constrain  ⊤  <:  ⊥\n//│ Type: Ref[in 'y out 'y ∨ Int, ?]\n\nfun foo: [A] -> Int ->{A} Int\nfun foo(x) =\n  region y in x + 1\n\n\nregion x in\n  x.ref ((x => x) as [A] -> A -> A)\n//│ Type: Ref['A -> 'A, ?]\n\n\nfun foo: [A extends Int] -> A -> A\nfun foo(x) = x\n\nfoo\n//│ Type: ['A] -> ('A) ->{⊥} 'A\n//│ Where:\n//│   'A <: Int\n\nregion x in x.ref foo\n//│ Type: Ref[in 'A -> ('A ∧ Int) out ('A ∧ Int) -> 'A, ?]\n\nfun bar: ([A] -> A -> A) -> Int\nfun bar(f) = f(42)\n\nbar\n//│ Type: (['A] -> ('A) ->{⊥} 'A) ->{⊥} Int\n\n:e\nregion x in x.ref bar\n//│ ╔══[COMPILATION ERROR] Expected a monomorphic type or an instantiable type here, but ([outer, 'A] -> ('A) ->{⊥} 'A) ->{⊥} Int found\n//│ ║  l.158: \tregion x in x.ref bar\n//│ ╙──       \t                  ^^^\n//│ Type: Ref[⊥, ?]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLScratch.mls",
    "content": ":invalml\n\n\n// :d\nlet i = 1\n\nlet i = 1\ni\n//│ Type: Int\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLSelfApp.mls",
    "content": ":invalml\n\n\n\n(x => x(x)) (x => x(x))\n//│ Type: ⊥\n\n\nfun f(x) = x(x)\n\nf\n//│ Type: ['x, 'eff, 'app] -> ('x ->{'eff} 'app) ->{'eff} 'app\n//│ Where:\n//│   'x <: 'x ->{'eff} 'app\n\nf(f)\n//│ Type: ⊥\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLSeq.mls",
    "content": ":invalml\n\n\n\ndata class Seq[A, E](next: () ->{E} A)\n\nfun map: [A, B, E] -> Seq[out A, out E] -> (A ->{E} B) -> Seq[out B, out E]\n\n// * Note: equivalent since Seq is covariant:\n// fun map: [A, B, E, F] -> Seq[out A, out E] -> (A ->{F} B) -> Seq[out B, out E | F]\n\n// * Forces the elements of the sequence to be evaluated and caches them\nfun force_cache: [A, B, E] -> Seq[out A, out E] ->{E} Seq[out B, Nothing]\n\n\n// * Dummy implementation\nfun mapi: [A, E] -> Seq[out A, out E] -> ((Int, A) ->{E} A) ->{Nothing} Seq[out A, out E]\nfun mapi = s => f =>\n  region r in\n    map(s) of x => f(0, x)\n\n// * Should be an error. This definition would not be referentially transparent.\n// * The error message needs improvement, though.\n:e\nfun mapi: [A, E] -> Seq[out A, out E] -> ((Int, A) ->{E} A) ->{Nothing} Seq[out A, out E]\nfun mapi = s => f =>\n  region r in\n    let i = r.ref 0\n    map(s) of x =>\n      i := !(i) + 1\n      f(!(i), x)\n//│ ╔══[COMPILATION ERROR] Type error in region expression with expected type Seq[out A, out E]\n//│ ║  l.28: \t    let i = r.ref 0\n//│ ║        \t            ^^^^^^^\n//│ ║  l.29: \t    map(s) of x =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.30: \t      i := !(i) + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.31: \t      f(!(i), x)\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  Seq[in ⊥ out 'B, in ⊥ out 'E1]  <:  Seq[in ⊥ out A, in ⊥ out E]\n//│ ╟── because: cannot constrain  'E1  <:  E\n//│ ╟── because: cannot constrain  'reg  <:  E\n//│ ╟── because: cannot constrain  'r ∧ ¬outer  <:  E\n//│ ╟── because: cannot constrain  'r  <:  E ∨ outer\n//│ ╙── because: cannot constrain  ¬outer  <:  E ∨ outer\n\n// * Notice the inferred type, which produces an unusable Sequence (of effect `?` ie `Any`)\nfun mapi = s => f =>\n  region r in\n    let i = r.ref 0\n    map(s) of x =>\n      i := !(i) + 1\n      f(!(i), x)\nmapi\n//│ Type: [outer, 'A, 'E, 'app, 'eff] -> Seq[out 'A, out 'E] -> (((Int, 'A) ->{'eff} 'app) -> Seq[out 'app, out (¬outer ∨ 'eff) ∨ 'E])\n\n// * This version is correct as it keeps the mutation encapsulated within the region\nfun mapi_force: [A, E] -> Seq[out A, out E] -> ((Int, A) ->{E} A) ->{E} Seq[out A, Nothing]\nfun mapi_force = s => f =>\n  region r in\n    let i = r.ref 0\n    force_cache of map(s) of x =>\n      i := !(i) + 1\n      f(!(i), x)\n\n// * An alternative version that takes an existing region in parameter\nfun mapi: [A, R, E] -> (Seq[out A, out E], Region[out R]) -> ((Int, A) ->{E} A) ->{R} Seq[out A, out E | R]\nfun mapi = (s, r) => f =>\n  let i = r.ref 0\n  map(s) of x =>\n    i := !(i) + 1\n    f(!(i), x)\n\n// * Simpler; should be equivalent when Region is covariant\nfun mapi: [A, E] -> (Seq[out A, out E], Region[out E]) -> ((Int, A) ->{E} A) ->{E} Seq[out A, out E]\nfun mapi = (s, r) => f =>\n  let i = r.ref 0\n  map(s) of x =>\n    i := !(i) + 1\n    f(!(i), x)\n\n\n// * Example usage\n\nfun mkSeq: [A, E] -> (() ->{E} A) ->{E} Seq[out A, out E]\nfun head: [A, E] -> Seq[out A, out E] ->{E} A\n\nregion r in\n  let sum = r.ref 0\n  let s1 = mkSeq of () =>\n    sum := !(sum) + 1,\n    !(sum)\n  let s2 = mapi(s1, r) of (x, i) => x * i\n  !(sum) + head(s2)\n//│ Type: Int\n\n\nfun r: Ref[Int, Nothing]\n\nr := 1\n!(r)\n//│ Type: Int\n\n:e\nr := 1\n! r // because of the space, this is a NL-op\n//│ ╔══[COMPILATION ERROR] Builtin '!' is not a binary operator\n//│ ║  l.106: \tr := 1\n//│ ║         \t^^^^^^\n//│ ║  l.107: \t! r // because of the space, this is a NL-op\n//│ ╙──       \t^^^\n//│ ╔══[COMPILATION ERROR] Variable not found: !\n//│ ║  l.107: \t! r // because of the space, this is a NL-op\n//│ ╙──       \t^\n//│ Type: ⊥\n\nr := 1, // `,` to avoid parsing `! r` on next line as continuation of expression\n! r\n//│ Type: Int\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLSyntax.mls",
    "content": ":invalml\n:parseOnly\n\ndata class Foo\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'data'),TypeDef(Cls,Ident(Foo),None))\n\ndata class Bar(x: Int)\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'data'),TypeDef(Cls,App(Ident(Bar),Tup(List(InfixApp(Ident(x),Keywrd(keyword ':'),Ident(Int))))),None))\n\ndata class Bar2(x: Int, y: Int)\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'data'),TypeDef(Cls,App(Ident(Bar2),Tup(List(InfixApp(Ident(x),Keywrd(keyword ':'),Ident(Int)), InfixApp(Ident(y),Keywrd(keyword ':'),Ident(Int))))),None))\n\ndata class Baz[A]\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'data'),TypeDef(Cls,App(Ident(Baz),TyTup(List(Ident(A)))),None))\n\ndata class BazBaz[A](f: A -> A)\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'data'),TypeDef(Cls,App(App(Ident(BazBaz),TyTup(List(Ident(A)))),Tup(List(InfixApp(Ident(f),Keywrd(keyword ':'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(A)))))),None))\n\nBaz[Int]\n//│ Parsed:\n//│ \tApp(Ident(Baz),TyTup(List(Ident(Int))))\n\nBaz[in Int]\n//│ Parsed:\n//│ \tApp(Ident(Baz),TyTup(List(Modified(Keywrd(keyword 'in'),Ident(Int)))))\n\nBaz[out Int]\n//│ Parsed:\n//│ \tApp(Ident(Baz),TyTup(List(Modified(Keywrd(keyword 'out'),Ident(Int)))))\n\nBaz[in Int out Int]\n//│ Parsed:\n//│ \tApp(Ident(Baz),TyTup(List(Tup(List(Modified(Keywrd(keyword 'in'),Ident(Int)), Modified(Keywrd(keyword 'out'),Ident(Int)))))))\n\nt.Bar#x\n//│ Parsed:\n//│ \tInfixApp(Sel(Ident(t),Ident(Bar)),Keywrd(keyword '#'),Ident(x))\n\nfoo.Bar#baz(42)\n//│ Parsed:\n//│ \tApp(InfixApp(Sel(Ident(foo),Ident(Bar)),Keywrd(keyword '#'),Ident(baz)),Tup(List(IntLit(42))))\n\nfoo(42).Bar#baz(42)\n//│ Parsed:\n//│ \tApp(InfixApp(Sel(App(Ident(foo),Tup(List(IntLit(42)))),Ident(Bar)),Keywrd(keyword '#'),Ident(baz)),Tup(List(IntLit(42))))\n\nlet x = 42 in x + 0\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(42)),Some(OpApp(Ident(x),Ident(+),List(IntLit(0)))))\n\nfun id(x) = x\n//│ Parsed:\n//│ \tTermDef(Fun,App(Ident(id),Tup(List(Ident(x)))),Some(Ident(x)))\n\nx => x + 1\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),OpApp(Ident(x),Ident(+),List(IntLit(1))))\n\ntrue and true\n//│ Parsed:\n//│ \tInfixApp(BoolLit(true),Keywrd(keyword 'and'),BoolLit(true))\n\nfalse: Bool\n//│ Parsed:\n//│ \tInfixApp(BoolLit(false),Keywrd(keyword ':'),Ident(Bool))\n\nf of false\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(BoolLit(false))))\n\nlet bar = new Bar(42)\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(bar),Some(App(LexicalNew(Some(Ident(Bar)),None),Tup(List(IntLit(42))))),None)\n\nlet bar = new Bar2(1, 1)\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(bar),Some(App(LexicalNew(Some(Ident(Bar2)),None),Tup(List(IntLit(1), IntLit(1))))),None)\n\nnew Bar(0)\n//│ Parsed:\n//│ \tApp(LexicalNew(Some(Ident(Bar)),None),Tup(List(IntLit(0))))\n\nnew Bar2(114, 514)\n//│ Parsed:\n//│ \tApp(LexicalNew(Some(Ident(Bar2)),None),Tup(List(IntLit(114), IntLit(514))))\n\nfun inc: Int -> Int\n//│ Parsed:\n//│ \tTermDef(Fun,InfixApp(Ident(inc),Keywrd(keyword ':'),InfixApp(Tup(List(Ident(Int))),Keywrd(keyword '->'),Ident(Int))),None)\n\n[A] -> A -> A\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(Ident(A))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(A)))\n\nfun id: [A] -> A -> A\n//│ Parsed:\n//│ \tTermDef(Fun,InfixApp(Ident(id),Keywrd(keyword ':'),InfixApp(TyTup(List(Ident(A))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(A)))),None)\n\n[A] => (x: A) => x\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(Ident(A))),Keywrd(keyword '=>'),InfixApp(Tup(List(InfixApp(Ident(x),Keywrd(keyword ':'),Ident(A)))),Keywrd(keyword '=>'),Ident(x)))\n\n[A, B] -> A -> B\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(Ident(A), Ident(B))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(B)))\n\n[A, B, C] -> (A, B) -> C\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(Ident(A), Ident(B), Ident(C))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A), Ident(B))),Keywrd(keyword '->'),Ident(C)))\n\n([A] -> A -> A) -> Int\n//│ Parsed:\n//│ \tInfixApp(Tup(List(InfixApp(TyTup(List(Ident(A))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(A))))),Keywrd(keyword '->'),Ident(Int))\n\n\nx => if x == 0 then 1 else x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),IfLike(Keywrd(keyword 'if'),Block(List(InfixApp(OpApp(Ident(x),Ident(==),List(IntLit(0))),Keywrd(keyword 'then'),IntLit(1)), PrefixApp(Keywrd(keyword 'else'),Ident(x))))))\n\nif 1 < 2 then 1 else 0\n//│ Parsed:\n//│ \tIfLike(Keywrd(keyword 'if'),Block(List(InfixApp(OpApp(IntLit(1),Ident(<),List(IntLit(2))),Keywrd(keyword 'then'),IntLit(1)), PrefixApp(Keywrd(keyword 'else'),IntLit(0)))))\n\nif false then 0 else 42\n//│ Parsed:\n//│ \tIfLike(Keywrd(keyword 'if'),Block(List(InfixApp(BoolLit(false),Keywrd(keyword 'then'),IntLit(0)), PrefixApp(Keywrd(keyword 'else'),IntLit(42)))))\n\nif 24 then false else true\n//│ Parsed:\n//│ \tIfLike(Keywrd(keyword 'if'),Block(List(InfixApp(IntLit(24),Keywrd(keyword 'then'),BoolLit(false)), PrefixApp(Keywrd(keyword 'else'),BoolLit(true)))))\n\nif x then true else false\n//│ Parsed:\n//│ \tIfLike(Keywrd(keyword 'if'),Block(List(InfixApp(Ident(x),Keywrd(keyword 'then'),BoolLit(true)), PrefixApp(Keywrd(keyword 'else'),BoolLit(false)))))\n\nif 1 is Int then 1 else 0\n//│ Parsed:\n//│ \tIfLike(Keywrd(keyword 'if'),Block(List(InfixApp(InfixApp(IntLit(1),Keywrd(keyword 'is'),Ident(Int)),Keywrd(keyword 'then'),IntLit(1)), PrefixApp(Keywrd(keyword 'else'),IntLit(0)))))\n\nfun fact = case\n  0 then 1\n  n then n * fact(n - 1)\n//│ Parsed:\n//│ \tTermDef(Fun,Ident(fact),Some(Case(Keywrd(keyword 'case'),Block(List(InfixApp(IntLit(0),Keywrd(keyword 'then'),IntLit(1)), InfixApp(Ident(n),Keywrd(keyword 'then'),OpApp(Ident(n),Ident(*),List(App(Ident(fact),Tup(List(OpApp(Ident(n),Ident(-),List(IntLit(1))))))))))))))\n\n\n`42\n//│ Parsed:\n//│ \tQuoted(IntLit(42))\n\nx `=> x\n//│ Parsed:\n//│ \tQuoted(InfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Unquoted(Ident(x))))\n\n(x, y) `=> x `+ y\n//│ Parsed:\n//│ \tQuoted(InfixApp(Tup(List(Ident(x), Ident(y))),Keywrd(keyword '=>'),Unquoted(Quoted(App(Ident(+),Tup(List(Unquoted(Ident(x)), Unquoted(Ident(y)))))))))\n\n(x, y, z) `=> x `+ y `+ z\n//│ Parsed:\n//│ \tQuoted(InfixApp(Tup(List(Ident(x), Ident(y), Ident(z))),Keywrd(keyword '=>'),Unquoted(Quoted(App(Ident(+),Tup(List(Unquoted(Quoted(App(Ident(+),Tup(List(Unquoted(Ident(x)), Unquoted(Ident(y))))))), Unquoted(Ident(z)))))))))\n\n`1 `+ `1\n//│ Parsed:\n//│ \tQuoted(App(Ident(+),Tup(List(Unquoted(Quoted(IntLit(1))), Unquoted(Quoted(IntLit(1)))))))\n\n\nf`(x)\n//│ Parsed:\n//│ \tQuoted(App(Unquoted(Ident(f)),Tup(List(Unquoted(Ident(x))))))\n\ng`(`1, `2)\n//│ Parsed:\n//│ \tQuoted(App(Unquoted(Ident(g)),Tup(List(Unquoted(Quoted(IntLit(1))), Unquoted(Quoted(IntLit(2)))))))\n\n\n`let x = `42 `in x\n//│ Parsed:\n//│ \tQuoted(LetLike(Keywrd(keyword 'let'),Ident(x),Some(Unquoted(Quoted(IntLit(42)))),Some(Unquoted(Ident(x)))))\n\n`if x `== `0.0 then `1.0 else x\n//│ Parsed:\n//│ \tQuoted(IfLike(Keywrd(keyword 'if'),Block(List(InfixApp(Unquoted(Quoted(App(Ident(==),Tup(List(Unquoted(Ident(x)), Unquoted(Quoted(DecLit(0.0)))))))),Keywrd(keyword 'then'),Unquoted(Quoted(DecLit(1.0)))), PrefixApp(Keywrd(keyword 'else'),Unquoted(Ident(x)))))))\n\n\nx `=> if 0 == 0 then x else `0\n//│ Parsed:\n//│ \tQuoted(InfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Unquoted(IfLike(Keywrd(keyword 'if'),Block(List(InfixApp(OpApp(IntLit(0),Ident(==),List(IntLit(0))),Keywrd(keyword 'then'),Ident(x)), PrefixApp(Keywrd(keyword 'else'),Quoted(IntLit(0)))))))))\n\nregion x in 42\n//│ Parsed:\n//│ \tRegion(Ident(x),IntLit(42))\n\n\nregion x in\n  x.ref 42\n//│ Parsed:\n//│ \tRegion(Ident(x),Block(List(RegRef(Ident(x),IntLit(42)))))\n\n\nregion x in\n  let r = x.ref 42 in let t = r := 0 in !(r)\n//│ Parsed:\n//│ \tRegion(Ident(x),Block(List(LetLike(Keywrd(keyword 'let'),Ident(r),Some(RegRef(Ident(x),IntLit(42))),Some(LetLike(Keywrd(keyword 'let'),Ident(t),Some(OpApp(Ident(r),Ident(:=),List(IntLit(0)))),Some(App(Ident(!),Tup(List(Bra(Round,Ident(r))))))))))))\n\n!(r) + 1\n//│ Parsed:\n//│ \tOpApp(App(Ident(!),Tup(List(Bra(Round,Ident(r))))),Ident(+),List(IntLit(1)))\n\nInt ->{Any} Int\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(Int))),Keywrd(keyword '->'),Effectful(Ident(Any),Ident(Int)))\n\n[A] -> Str ->{A} Str\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(Ident(A))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(Str))),Keywrd(keyword '->'),Effectful(Ident(A),Ident(Str))))\n\nA | B\n//│ Parsed:\n//│ \tOpApp(Ident(A),Ident(|),List(Ident(B)))\n\n[A extends Int] -> A -> A\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(InfixApp(Ident(A),Keywrd(keyword 'extends'),Ident(Int)))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(A)))\n\n[A restricts Int] -> A -> A\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(InfixApp(Ident(A),Keywrd(keyword 'restricts'),Ident(Int)))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(A)))\n\n[A extends Int restricts Int] -> A -> A\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(InfixApp(InfixApp(Ident(A),Keywrd(keyword 'extends'),Ident(Int)),Keywrd(keyword 'restricts'),Ident(Int)))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(A)))\n\n[A extends Int, B restricts Int] -> A -> B\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(InfixApp(Ident(A),Keywrd(keyword 'extends'),Ident(Int)), InfixApp(Ident(B),Keywrd(keyword 'restricts'),Ident(Int)))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(B)))\n\n[A extends Int restricts Int, B extends Int restricts Int] -> A -> B\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(InfixApp(InfixApp(Ident(A),Keywrd(keyword 'extends'),Ident(Int)),Keywrd(keyword 'restricts'),Ident(Int)), InfixApp(InfixApp(Ident(B),Keywrd(keyword 'extends'),Ident(Int)),Keywrd(keyword 'restricts'),Ident(Int)))),Keywrd(keyword '->'),InfixApp(Tup(List(Ident(A))),Keywrd(keyword '->'),Ident(B)))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLTODOs.mls",
    "content": ":invalml\n\n\n:todo\nlet id: [A] -> A -> A = x => x\n//│ ╔══[COMPILATION ERROR] Unsupported let binding shape\n//│ ║  l.5: \tlet id: [A] -> A -> A = x => x\n//│ ╙──     \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:todo\nfun id[A](x: A) = x\n//│ ╔══[COMPILATION ERROR] Variable not found: A\n//│ ║  l.11: \tfun id[A](x: A) = x\n//│ ╙──      \t             ^\n\n:fixme\nfun id: [A] -> A -> A => x = x\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.17: \tfun id: [A] -> A -> A => x = x\n//│ ╙──      \t                         ^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.17: \tfun id: [A] -> A -> A => x = x\n//│ ╙──      \t                             ^\n//│ ╔══[COMPILATION ERROR] Expected a type, got function literal\n//│ ║  l.17: \tfun id: [A] -> A -> A => x = x\n//│ ╙──      \t                    ^\n//│ ═══[COMPILATION ERROR] Function definition shape not yet supported for id\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLUntyped.mls",
    "content": ":invalml\n:js\n\n\n\n@untyped 1\n//│ = 1\n//│ Type: ⊥\n\n:re\n(@untyped 1)(2)\n//│ ═══[RUNTIME ERROR] TypeError: 1 is not a function\n//│ Type: ⊥\n\n@untyped\nfun f: Int\n\n@untyped declare fun f: Int\n\n@untyped \n@untyped \ndeclare fun f: Int\n\n@untyped fun f() = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLUsefulExtrusion.mls",
    "content": ":invalml\n\n\nfun (;) seq(_, res) = res\n\n\n\n\nfun wield: [R] -> (Region[out R]) ->{R} ()\nfun freeze: [R, E extends ~R, T] -> (Region[out R], () ->{~R & E} T) ->{R | E} T\n\nfreeze\n//│ Type: ['R, 'E, 'T] -> (Region[out 'R], () ->{¬'R ∧ 'E} 'T) ->{'R ∨ 'E} 'T\n//│ Where:\n//│   'E <: ¬'R\n\n\nfun foo(f) =\n  region r in\n    freeze(r, () => f(32))\n\nfoo\n//│ Type: [outer, 'app, 'eff] -> (Int ->{'eff} 'app) ->{'eff} 'app\n//│ Where:\n//│   'eff <: outer\n\nfun foo(f) =\n  region r in\n    freeze(r, f)\n    123\n\nfoo\n//│ Type: [outer, 'E] -> (() ->{'E ∧ outer} ⊤) ->{'E} Int\n//│ Where:\n//│   'E <: outer\n\n\nfun foo(r1, r2, f, g) =\n  freeze(r1, () => f(123)); freeze(r2, () => g(456))\n\nfoo\n//│ Type: ['res, 'R, 'E, 'R1, 'E1] -> (Region[out 'R], Region[out 'R1], Int ->{'E ∧ ¬'R} ⊤, Int ->{'E1 ∧ ¬'R1} 'res) ->{(('R ∨ 'E) ∨ 'R1) ∨ 'E1} 'res\n//│ Where:\n//│   'E <: ¬'R\n//│   'E1 <: ¬'R1\n\n\n\nfun freeze: [E, R, S, T] -> (Region[out R], () ->{~R & E} T) ->{R | E} T\n\nfreeze\n//│ Type: ['E, 'R, 'T] -> (Region[out 'R], () ->{¬'R ∧ 'E} 'T) ->{'R ∨ 'E} 'T\n\n\nfun foo(f) =\n  region r in\n    freeze(r, () => f(32))\n\nfoo\n//│ Type: [outer, 'app, 'eff] -> (Int ->{'eff} 'app) ->{'eff} 'app\n//│ Where:\n//│   'eff <: outer\n\nfun foo(f) =\n  region r in\n    freeze(r, f)\n    123\n\nfoo\n//│ Type: [outer, 'E] -> (() ->{'E ∧ outer} ⊤) ->{'E} Int\n\n\n\nfun foo: [R1, R2] -> (Region[out R1], Region[out R2], Int ->{R1 & ~R2} (), Int ->{R2 & ~R1} ()) ->{R1 | R2} () \nfun foo(r1, r2, f, g) =\n  f(123); g(456)\n\nfun foo(r1, r2, f, g) =\n  freeze(r1, () => f(123)); freeze(r2, () => g(456))\n\nfoo\n//│ Type: ['res, 'E, 'R, 'E1, 'R1] -> (Region[out 'R], Region[out 'R1], Int ->{'E ∧ ¬'R} ⊤, Int ->{'E1 ∧ ¬'R1} 'res) ->{(('R ∨ 'E) ∨ 'R1) ∨ 'E1} 'res\n\n\nfun foo(r1, r2, f, g) =\n  freeze(r1, () => freeze(r2, () => f(r2); g(r1)))\n\nfoo\n//│ Type: ['r1, 'r2, 'E, 'R, 'T, 'R1] -> ('r1, 'r2, 'r2 ->{('E ∧ ¬'R) ∧ ¬'R1} ⊤, 'r1 ->{('E ∧ ¬'R) ∧ ¬'R1} 'T) ->{'R ∨ 'E} 'T\n//│ Where:\n//│   'r1 <: Region[out 'R]\n//│   'R1 <: 'E\n//│   'R1 <: ¬'R\n//│   'r2 <: Region[out 'R1]\n\n:e\nregion r in\n  foo(r, r, wield, wield)\n//│ ╔══[COMPILATION ERROR] Type error in reference with expected type 'r2\n//│ ║  l.98: \t  foo(r, r, wield, wield)\n//│ ║        \t         ^\n//│ ╟── because: cannot constrain  Region[in ⊥ out r]  <:  'r2\n//│ ╟── because: cannot constrain  Region[in ⊥ out r]  <:  Region[in ⊥ out 'R]\n//│ ╟── because: cannot constrain  r  <:  'R\n//│ ╟── because: cannot constrain  r  <:  ¬'R1\n//│ ╟── because: cannot constrain  'R1  <:  ¬r\n//│ ╙── because: cannot constrain  r  <:  ¬r\n//│ ╔══[COMPILATION ERROR] Type error in reference of type ‹not implemented› with expected type 'f\n//│ ║  l.98: \t  foo(r, r, wield, wield)\n//│ ║        \t            ^^^^^\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R2]) ->{'R2} (())  <:  'f\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R2]) ->{'R2} (())  <:  ('r2) ->{¬'R ∧ ¬'R1 ∧ 'E} (⊤)\n//│ ╟── because: cannot constrain  'R2  <:  ¬'R ∧ ¬'R1 ∧ 'E\n//│ ╟── because: cannot constrain  'R2  <:  ¬'R1\n//│ ╟── because: cannot constrain  r  <:  ¬'R1\n//│ ╟── because: cannot constrain  'R1  <:  ¬r\n//│ ╙── because: cannot constrain  r  <:  ¬r\n//│ ╔══[COMPILATION ERROR] Type error in reference of type ‹not implemented› with expected type 'g\n//│ ║  l.98: \t  foo(r, r, wield, wield)\n//│ ║        \t                   ^^^^^\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R3]) ->{'R3} (())  <:  'g\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R3]) ->{'R3} (())  <:  ('r1) ->{¬'R ∧ ¬'R1 ∧ 'E} ('T)\n//│ ╟── because: cannot constrain  'R3  <:  ¬'R ∧ ¬'R1 ∧ 'E\n//│ ╟── because: cannot constrain  'R3  <:  ¬'R1\n//│ ╟── because: cannot constrain  r  <:  ¬'R1\n//│ ╟── because: cannot constrain  'R1  <:  ¬r\n//│ ╙── because: cannot constrain  r  <:  ¬r\n\n:e\nregion r in\n  region s in\n    foo(r, s, wield, wield)\n//│ ╔══[COMPILATION ERROR] Type error in reference of type ‹not implemented› with expected type 'f\n//│ ║  l.132: \t    foo(r, s, wield, wield)\n//│ ║         \t              ^^^^^\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R]) ->{'R} (())  <:  'f\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R]) ->{'R} (())  <:  ('r2) ->{¬'R1 ∧ ¬'R2 ∧ 'E} (⊤)\n//│ ╟── because: cannot constrain  'R  <:  ¬'R1 ∧ ¬'R2 ∧ 'E\n//│ ╟── because: cannot constrain  'R  <:  ¬'R1\n//│ ╟── because: cannot constrain  s ∧ ¬r  <:  ¬'R1\n//│ ╟── because: cannot constrain  'R1  <:  ¬s ∨ r\n//│ ╙── because: cannot constrain  s ∧ ¬r  <:  ¬s ∨ r\n//│ ╔══[COMPILATION ERROR] Type error in reference of type ‹not implemented› with expected type 'g\n//│ ║  l.132: \t    foo(r, s, wield, wield)\n//│ ║         \t                     ^^^^^\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R3]) ->{'R3} (())  <:  'g\n//│ ╟── because: cannot constrain  (Region[in ⊥ out 'R3]) ->{'R3} (())  <:  ('r1) ->{¬'R1 ∧ ¬'R2 ∧ 'E} ('T)\n//│ ╟── because: cannot constrain  'R3  <:  ¬'R1 ∧ ¬'R2 ∧ 'E\n//│ ╟── because: cannot constrain  'R3  <:  ¬'R2\n//│ ╟── because: cannot constrain  r  <:  ¬'R2\n//│ ╟── because: cannot constrain  'R2  <:  ¬r\n//│ ╙── because: cannot constrain  r  <:  ¬r\n\nregion r in\n  region s in\n    foo(r, s, x => x, y => y)\n//│ Type: Region[?]\n\n\n\n:fixme\nfun foo[outer, R <: outer](r1: Region[R]) =\n  region r2 in\n    freeze(r2, () =>\n      wield(r1)\n    )\n//│ ╔══[COMPILATION ERROR] Unsupported type parameter outer binding\n//│ ║  l.162: \tfun foo[outer, R <: outer](r1: Region[R]) =\n//│ ╙──       \t        ^^^^^\n//│ ╔══[COMPILATION ERROR] Unsupported type parameter operator application\n//│ ║  l.162: \tfun foo[outer, R <: outer](r1: Region[R]) =\n//│ ╙──       \t               ^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: R\n//│ ║  l.162: \tfun foo[outer, R <: outer](r1: Region[R]) =\n//│ ╙──       \t                                      ^\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Expected a type, got a non-type ‹error›\n//│ ═══[COMPILATION ERROR] Invalid type\n\n:fixme\nfun foo: [outer, R <: outer] -> Region[R] -> ()\n//│ ╔══[COMPILATION ERROR] Illegal forall annotation.\n//│ ║  l.183: \tfun foo: [outer, R <: outer] -> Region[R] -> ()\n//│ ╙──       \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ═══[COMPILATION ERROR] Expected a type, got ‹error›\n//│ ═══[COMPILATION ERROR] Invalid type\n\n\n\n// * A function that executes its argument `f` in a frozen local region;\n// * we show that this `f` can itself in turn freeze its own region from the call site\n\nfun foo(f) =\n  region r in\n    freeze of r, () =>\n      f()\n\nfoo\n//│ Type: [outer, 'app, 'eff] -> (() ->{'eff} 'app) ->{'eff} 'app\n//│ Where:\n//│   'eff <: outer\n\nregion s in\n  foo(() => wield(s))\n\nregion s in\n  foo of () =>\n    wield(s)\n    freeze(s, () => 42)\n//│ Type: Int\n\n:e\nregion s in\n  foo of () =>\n    freeze(s, () => wield(s))\n//│ ╔══[COMPILATION ERROR] Type error in function literal with expected type () ->{¬'R ∧ 'E} 'T\n//│ ║  l.217: \t    freeze(s, () => wield(s))\n//│ ║         \t              ^^^^^^^^^^^^^^\n//│ ╟── because: cannot constrain  'R1  <:  ¬'R ∧ 'E\n//│ ╟── because: cannot constrain  'R1  <:  ¬'R\n//│ ╟── because: cannot constrain  s  <:  ¬'R\n//│ ╟── because: cannot constrain  'R  <:  ¬s\n//│ ╙── because: cannot constrain  s  <:  ¬s\n\nregion s in\n    foo of () =>\n      region t in\n        wield(s)\n        freeze(s, () => wield(t))\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/InvalMLVariance.mls",
    "content": ":invalml\n\n\nclass Foo[out A]\n\n(x: Foo[Int]) => (x as Foo[Int | Str])\n//│ Type: (Foo[out Int]) ->{⊥} Foo[out Int ∨ Str]\n\n\nclass Foo[in A]\n\n(x: Foo[Int]) => (x as Foo[Int & Str])\n//│ Type: (Foo[in Int]) ->{⊥} Foo[in Int ∧ Str]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/DynamicProgramming.mls",
    "content": "\n:global\n:invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nclass Option[A] with\n  constructor\n    Some(x: A)\n    None\n\n\nclass ArrayList[T, out R]\nclass Iter[T, out R]\nclass Array2D[T, out R]\n\nclass Interviewee with\n  constructor\n    Itv(score: Int, salary: Int)\n\nfun (;) seq(_, res) = res\nfun toString: Any -> Str\nfun concat: (Str, Str) -> Str\nfun println: Str -> ()\n\nfun\n  empty:   [A, R] -> Region[out R] ->{R} ArrayList[A, out R]\n  push:    [A, R] -> (ArrayList[A, out R], A) ->{R} ()\n  iter: [Res, R, E extends ~R, T] ->\n    (ArrayList[T, out R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res\n  revIter: [outer, Res, R, E extends ~R, T] ->\n    (ArrayList[T, out R], [S extends ~outer] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res\n  next: [T, S] -> Iter[T, S] ->{S} Option[T]\n  len:  [A, R] -> (ArrayList[A, out R]) ->{R} Int\n  whileDo: [R] -> (() ->{R} Bool) ->{R} ()\n  init:    [A, R] -> (Region[out R], Int, Int, A) ->{R} Array2D[A, R]\n  update: [A, R] -> (Array2D[A, out R], Int, Int, A) ->{R} ()\n  get: [A, R] -> (Array2D[A, out R], Int, Int) ->{R} A\n  max: (Int, Int) -> Int\n\n\n\nfun format(it) =\n  if it is Itv(score, salary) then\n    concat(\"interviewee, score: \", concat(toString(score), concat(\"salary\", toString(salary))))\n\n\nfun printAll(arr) =\n  iter of arr, it =>\n    whileDo of () =>\n      if next(it) is\n        Some(x) then println(format(x)); true\n        None then false\n\n\n// fun select: [outer, R1 extends outer, R2 extends ~R1] -> (ArrayList[Interviewee, R1], Int, ArrayList[Interviewee, R2]) ->{R1 | R2} Int\nfun select(interviewees, budget, results) =\n  region r in\n    let size = len(interviewees), let i = r.ref 1\n    let dp = init(r, size + 1, budget + 1, 0)\n    iter of interviewees, it => whileDo of () =>\n      if next(it) is\n        Some(itv) then if itv is Itv(score, salary) then\n          let j = r.ref 0\n          whileDo of () =>\n            if !(j) < salary then update(dp, !(i), !(j), get(dp, !(i) - 1, !(j)))\n            else\n              let p = get(dp, !(i) - 1, !(j) - salary), let np = get(dp, !(i) - 1, !(j))\n              update(dp, !(i), !(j), max of np, p + score)\n            j := !(j) + 1; !(j) <= budget\n          i := !(i) + 1\n          true\n        None then false\n    i := size\n    let rest = r.ref budget\n    revIter of interviewees, it =>\n      whileDo of () =>\n        if next(it) is\n          Some(itv) then if itv is Itv(score, salary) then\n            if get(dp, !(i), !(rest)) == get(dp, !(i) - 1, !(rest) - salary) + score then\n              push(results, itv); rest := !(rest) - salary\n            else ()\n            i := !(i) - 1\n            true\n          None then false\n    get(dp, size, budget)\n\n// region r in\n//   let interviewees = empty(r)\n//   push(interviewees, Itv(20, 3000))\n//   push(interviewees, Itv(50, 1000))\n//   push(interviewees, Itv(30, 1000))\n//   let results = empty(r)\n//   let m = select(interviewees, 4000, results)\n//   printAll(results)\n//   m\n\n\n// fun wrongSelect(interviewees, budget, results) =\n//   region r in\n//     let size = len(interviewees), let i = r.ref 1\n//     let dp = init(r, size + 1, budget + 1, 0)\n//     iter of interviewees, it =>\n//       whileDo of () =>\n//         if next(it) is\n//           Some(itv) then if itv is Itv(score, salary) then\n//             let j = r.ref 0\n//             whileDo of () =>\n//               if !j < salary then update(dp, !i, !j, get(dp, !i - 1, !j))\n//               else\n//                 let p = get(dp, !i - 1, !j - salary), let np = get(dp, !i - 1, !j)\n//                 update(dp, !i, !j, max of np, p + score)\n//               j := !j + 1; !j <= budget\n//             i := !i + 1\n//             true\n//           None then false\n//     i := size\n//     let rest = r.ref budget\n//     revIter of interviewees, it =>\n//       whileDo of () =>\n//         if next(it) is\n//           Some(itv) then if itv is Itv(score, salary) then\n//             if get(dp, !i, !rest) == get(dp, !i - 1, !rest - salary) + score\n//                 do push(interviewees, itv); rest := !rest - salary\n//             i := !i - 1\n//             true\n//           None then false\n//     get(dp, size, budget)\n\n// region r in\n//   let interviewees = empty(r)\n//   push(interviewees, Itv(20, 3000))\n//   push(interviewees, Itv(50, 1000))\n//   push(interviewees, Itv(30, 1000))\n//   region r2 in\n//     let results = empty(r2)\n//     let m = wrongSelect(interviewees, 4000, results)\n//     printAll(results)\n//     m\n\n\nregion r in\n  let interviewees = empty(r)\n  push(interviewees, Itv(40, 10))\n  push(interviewees, Itv(60, 20))\n  push(interviewees, Itv(120, 30))\n  push(interviewees, Itv(70, 20))\n  println(\"all interviewees:\")\n  printAll(interviewees)\n  region r2 in\n    let results = empty(r2)\n    let m = select(interviewees, 60, results)\n    println(\"candidates:\")\n    printAll(results)\n    m\n//│ Type: Int\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/ExamplesInResponse.mls",
    "content": ":invalml\n\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\n// * This file contains examples in the author response. A few typos therein are corrected.\n\n\n// Some utility functions:\n\nfun wield: [R] -> (Region[out R]) ->{R} ()\nfun freeze: [R, E extends ~R, T] -> (Region[out R], () ->{~R & E} T) ->{R | E} T\n// ^ Fixed a typo in the author response (`{~R | E}` should have been `{~R & E}`)\n\nfun (;) seq(_, res) = res\nfun rand: () -> Bool\nfun print: Any -> ()\n\n\n// ### Example 1\n\n\n// Passing the same region for both arguments fundamentally does not work approaches like Rust and Capability Calculus.\nfun foo1(r1, r2) =\n  freeze(r1, () => print(\"ok\"))\n  wield(r2)\n\n// InvalML allows r1 and r2 to alias as long as ‹body› does not use r2; for instance:\nregion r in\n  foo1(r, r)\n\n// Capability Calculus and related systems would require r2 to be distinct from r1.\n\n// Note – this also works:\nregion r in\n  region s in\n    foo1(r, s)\n\n// Here is a slightly less trivial examples that still type checks seamlessly in InvalML:\nregion r0 in\n  \n  fun foo1(r1, r2) =\n    freeze(r1, () => wield(r0))\n    wield(r2)\n  \n  region r in\n    foo1(r, r)\n  \n  region r in\n    region s in\n      foo1(r, s)\n\n\n// On the other hand, given\nfun foo2(r1, r2) =\n  freeze(r1, () => wield(r2))\n  wield(r2)\n\n// we rightfully reject\n// region r in\n//   foo2(r, r)\n\n// but still accept\nregion r in\n  region s in\n    foo2(r, s)\n\n\n// ### Example 2\n\n\nfun foo3: [outer, R extends outer] -> Region[out R] ->{outer} ()\nfun foo3(r1) =\n  region r2 in\n    freeze(r2, () =>\n      wield(r1)\n    )\n// ^ Fixed typos in the author response (it used the paper's syntax instead of the implementation's syntax)\n\n// In fact, this formally equivalent signature also works:\nfun foo3': [outer] -> Region[out outer] ->{outer} ()\nfun foo3'(r1) = foo3(r1)\n\n\n// ### Example 3\n\n\nfun foo4(r1, r2, f) =\n  let exec = freeze(r1, () => freeze(r2, () => f(r1, r2)))\n  let r = exec()\n  !(r) + 1\n\nregion r in\n  region s in\n    foo4(r, s, (x, y) =>\n      if rand() then print(\"Chose x\"); () => x.ref 0\n                else print(\"Chose y\"); () => y.ref 1)\n\n\n// ### Example 4\n\n\nfun foo5(f) =\n  region r in\n    freeze(r, () => f(32))\n\n\nfun freeze2: [R, E extends ~R, T] -> (Region[out R], () ->{~R & E} T) ->{R | E} T\n\nfun foo6(f) =\n  region r in\n    freeze(r, () => f(32))\n\nfoo6\n\n\n//│ Type: [outer, 'app, 'eff] -> (Int ->{'eff} 'app) ->{'eff} 'app\n//│ Where:\n//│   'eff <: outer\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/ExamplesInThePaper.mls",
    "content": ":invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\n// * This file contains examples in the paper\n\nclass ArrayList[A, R]\nclass List[A]\nclass Iter[T, R]\n\nfun mkArrayList : [R, T] -> (Region[out R]) ->{R} ArrayList[T, R]\nfun add : [R, T] -> (ArrayList[T, R], T) ->{R} ()\nfun clear : [R, T] -> ArrayList[T, R] ->{R} ()\nfun foreach : [E, R, T] -> (Iter[T, R], T ->{E} ()) -> {R | E} ()\nfun iter : [Res, R, E extends ~R, T] -> (ArrayList[T, R], [I] -> Iter[T, I] ->{I | E} Res) ->{E | R} Res\nfun map: [T, S, E] -> (List[out T], T ->{E} S) ->{E} List[out S]\n\nfun println: Any -> ()\nfun (;) seq(_, res) = res\n\nregion r in // This is used to delimit the scope of mutation\n  let xs = mkArrayList(r) // Creates a new mutable list in r egion r\n  add(xs, \"1\"); add(xs, \"2\"); add(xs, \"3\");\n  iter(xs, it => foreach(it , e => println(e)))\n\n// region r in // This is used to delimit the scope of mutation\n//   let xs = mkArrayList(r) // Creates a new mutable list in r egion r\n//   add(xs, \"1\"); add(xs, \"2\"); add(xs, \"3\");\n//   iter(xs, it => foreach(it , e => println (e); clear (xs)))\n\nfun mapi: [A, B, E] -> (List[out A], (Int, A) ->{E} B) ->{E} List[out B]\nfun mapi(xs, f) =\n  region r in\n    let index = r.ref 0 in map(xs, x => let res = f(!(index), x) in index := !(index) + 1; res)\n\n\nfun f: [R1, R2 extends ~R1] -> (Region[out R1], Region[out R2]) ->{R1 | R2} Int\n\n\n// region r1 in\n//   let g = (r => region r2 in f(r, r2)) in (region r3 in g(r3))\n\n\nregion r1 in\n  fun g: [outer, R extends outer] -> Region[out R] ->{R} Int\n  fun g(r) = region r2 in f(r, r2)\n  region r3 in g(r3)\n\n\nregion r in\n  let a1 = mkArrayList(r) in add(a1, 12); add(a1, 34);\n  iter of a1, it1 =>\n    region s in\n      let a2 = mkArrayList(s)\n      foreach of it1, v1 => add(a2 , v1)\n      iter of a2, it2 => foreach of it2 , v2 => println(v2)\n      clear(a2)\n\n\n// region r in\n//   let a = mkArrayList(r) in add(a, 12); add(a, 34);\n//   iter of a, it =>\n//     foreach of it, v => println(v); clear(a)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/Exception.mls",
    "content": ":invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n// * This files includes the exception handling extension of InvalML.\n\nclass Exc[T]\n\nfun (;) seq(_, res) = res\n\nfun raise: [T, P extends Exc[T]] -> (P, T) ->{P} Nothing\nfun hdle: [Res, E, T] -> ([P extends Exc[T]] -> (P) ->{E | P} Res, T ->{E} Res) ->{E} Res\nfun print: Str -> Unit\nfun noExc: [E extends ~Exc[in Nothing out Any], Res] -> (() ->{E} Res) ->{E} Res\n\n\nhdle(e => raise(e, \"oops!\"), msg => print(msg))\n\n// Error! The payload type is incorrect.\n// hdle(e => raise(e, 42), msg => print(msg))\n\n\nfun div(x, y) =\n  hdle(e => if y is 0 then raise(e, \"div-by-zero!\") else x / y, msg => print(msg); 0)\n\n\nhdle(e1 => hdle(e2 => raise(e1, \"oops!\"), msg => print(msg)), msg => print(msg))\nhdle(e1 => hdle(e2 => raise(e2, \"oops!\"), msg => print(msg)), msg => print(msg))\nhdle(e1 => hdle(e2 => raise(e1, \"oops!\"), msg => raise(e1, msg)), msg => print(msg))\n\n\nnoExc(() => 42)\nnoExc(() => hdle(e => raise(e, \"oops!\"), msg => print(msg)))\n\n// Error! No exception is allowed.\n// hdle(e => noExc(() => raise(e, \"oops!\")), msg => print(msg))\n\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/README.md",
    "content": "# Web-Demo \n\n## Syntax\n\nMost syntax can be found in the paper.\nWe list the changed and non-mentioned syntax in this documentation.\n\n### ADT Declarations\n\nWe use the following syntax to declare ADTs:\n```fs\nclass List[T] with\n  constructor\n    Nil\n    Cons(x: T, xs: List[out T])\n```\nwhich is equivalent to the syntax used in the paper:\n```scala\nenum List[T]:\n  case Nil\n  case Cons(x: T, xs: List[out T])\n```\n\n### Functions\n\nKeyword `case` is used to create a function that\npattern matches on the unique parameter.\n```fs\nfun fact = case\n  1 then 1\n  n then n * fact(n - 1)\n```\nwhich is equivalent to\n```fs\nfun fact(x) = if x is\n  1 then 1\n  n then n * fact(n - 1)\n```\n\nKeyword `of` is used for function application\nto avoid unnecessary parentheses.\n```fs\nfun add(x, y, z) = x + y + z\nadd of 1, 2, 3\n```\nwhich is equivalent to\n```fs\nfun add(x, y, z) = x + y + z\nadd(1, 2, 3)\n```\n\n### Type Annotations\n\nType annotations are written in the following syntax:\n```fs\n[T] -> ... // equivalent to ∀ T. ...\n[T extends S] -> ... // equivalent to ∀ T {T ≤ S}. ...\n[T restricts S] -> ... // equivalent to ∀ T {S ≤ T}. ...\nT | S // equivalent to T ∨ S\nT & S // equivalent to T ∧ S\n~T // equivalent to ¬T\n```\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/SimpleConstraintSolver.mls",
    "content": ":invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n// * In this file, we implement a simple constraint solver, originally presented in https://doi.org/10.1145/3410225\n// * We only implement int type, function types, and type variables for simplicity\n\n// *** infrastructures\n\nfun nt(b) = if b then false else true\nfun (;) seq(_, res) = res\nfun id(x) = x\n\nfun println: Any -> ()\nfun (~) concat: (Str, Str) -> Str\nfun toString: Any -> Str\nfun (===) streq: (Str, Str) -> Bool\nfun error() = error()\n\nclass PairOf[out A, out B] with\n  constructor\n    Pair(fst: A, snd: B)\n\nclass Option[out A] with\n  constructor\n    None()\n    Some(value: A)\n\nclass List[out A] with\n  constructor\n    Nil()\n    Cons(head: A, tail: List[A])\n\nfun fold(x, xs, f) = if xs is\n  Nil() then x\n  Cons(y, ys) then fold(f(x, y), ys, f)\n\nfun map(xs, f) = if xs is\n  Nil() then Nil()\n  Cons(x, xs) then Cons(f(x), map(xs, f))\n\nfun each(xs, f) = if xs is\n  Nil() then ()\n  Cons(x, xs) then f(x); each(xs, f)\n\nfun find(xs, f) = if xs is\n  Nil() then None()\n  Cons(x, xs) then\n    if f(x) then Some(x)\n    else find(xs, f)\n\nclass ArrayList[T, out R]\nclass Iter[T, out R]\nclass HashMap[K, V, out R]\nclass MapIter[T, out R]\n\n// fun empty:   [A, R] -> Region[R] ->{R} ArrayList[out A, out R]  // TODO investigate: why does this break things?\nfun empty: [A, R] -> Region[out R] ->{R} ArrayList[A, out R]\nfun clear: [A, R] -> (ArrayList[A, out R]) ->{R} ()\nfun push: [A, R] -> (ArrayList[A, R], A) ->{R} ()\nfun len: [A, R] -> (ArrayList[A, R]) ->{R} Int\nfun iter: [Res, R, E extends ~R, T] -> (ArrayList[T, R], [S] -> Iter[T, S] ->{S | E} Res) ->{E | R} Res\nfun next: [T, S] -> Iter[T, S] ->{S} Option[T]\nfun whileDo: [R] -> (() ->{R} Bool) ->{R} ()\nfun foreach: [E, R, T] -> (Iter[T, R], T ->{E} ()) ->{R | E} ()\nfun max(x, y) = if x < y then y else x\n\n\nfun mkHashMap: [R, K, V] -> (Region[out R], K -> Str) ->{R} HashMap[K, V, R]\nfun getOrUpdate: [R, K, V, E] -> (HashMap[K, V, R], K, () ->{E} V) ->{E | R} V\nfun hasOrUpdate: [R, K, V, E] -> (HashMap[K, V, R], K, () ->{E} V) ->{E | R} ()\nfun iterMap: [Res, R, E extends ~R, K, V] -> (HashMap[K, V, R], [S] -> MapIter[V, S] ->{S | E} Res) ->{E | R} Res\nfun nextVal: [T, S] -> MapIter[T, S] ->{S} Option[T]\nfun hasKey: [K, V, R] -> (HashMap[K, V, R], K) ->{R} Bool\nfun add: [K, V, R] -> (HashMap[K, V, R], K, V) ->{R} ()\nfun values: [E, R, T] -> (MapIter[T, R], T ->{E} ()) ->{R | E} ()\n\n// *** simple constraint solver\n\n\n// Unif contains a type variable's id, lower bounds, and upper bounds.\nclass Type[out R] with\n  constructor\n    IntType()\n    FunctionType(lhs: Type[R], rhs: Type[R])\n    RecordType(fields: List[PairOf[Str, Type[R]]])\n    TypeVariable(id: Str, level: Int, lowerBounds: ArrayList[Type[R], R], upperBounds: ArrayList[Type[R], R])\n    \n\nfun isSimpl(ty) = if ty is\n  FunctionType(_, _) then false\n  else true\n\n\nfun ty2Str(ty) = if ty is\n  IntType() then \"Int\"\n  FunctionType(lhs, rhs) then\n    let ls = if isSimpl(lhs) then ty2Str(lhs) else \"(\" ~ ty2Str(lhs) ~ \")\"\n    ls ~ \" -> \" ~ ty2Str(rhs)\n  RecordType(fields) then \"{ \" ~ fold(\"\", fields, (s, p) => if p is Pair(n, t) then s ~ n ~ \": \" ~ ty2Str(t) ~ \", \") ~ \"}\"\n  TypeVariable(name, level, _, _) then name ~ \"_\" ~ toString(level)\n\n// fun levelOf: [R] -> Type[R] -> Int\nfun levelOf(ty) = if ty is\n  IntType() then 0\n  FunctionType(lhs, rhs) then max(levelOf(lhs), levelOf(rhs))\n  RecordType(fields) then fold(0, fields, (r, p) => if p is Pair(_, t) then max(r, levelOf(t)))\n  TypeVariable(_, level, _, _) then level\n\nfun report(lhs, rhs) =\n  println(\"Cannot constrain \" ~ ty2Str(lhs) ~ \" <: \" ~ ty2Str(rhs) ~ \"!\")\n\n\nfun extrude: [outer, R extends outer] -> (Type[R], Bool, Int, (Str, Int) ->{R} Type[R], HashMap[PairOf[Type[R], PairOf[Int, Bool]], Type[R], R]) ->{R} Type[R]\nfun extrude(ty, pol, lvl, freshVar, cache) = getOrUpdate of cache, Pair(ty, Pair(lvl, pol)), () =>\n  if levelOf(ty) <= lvl then ty\n  else if ty is\n    IntType() then ty\n    FunctionType(lhs, rhs) then\n      FunctionType(extrude(lhs, nt(pol), lvl, freshVar, cache), extrude(rhs, pol, lvl, freshVar, cache))\n    RecordType(fields) then\n      RecordType(map(fields, p => if p is Pair(name, ty) then Pair(name, extrude(ty, pol, lvl, freshVar, cache))))\n    TypeVariable(name, level, lb, ub) then\n      let nc = freshVar(name ~ \"'\" ~ (if pol then \"+\" else \"-\"), lvl)\n      if pol then\n        push(ub, nc)\n        let nlb = if nc is\n          TypeVariable(_, _, lb, _) then lb\n          else error() // impossible\n        region r in\n          let nbd = empty(r)\n          iter of lb, it => foreach(it, b => push(nbd, b))\n          iter of nbd, it => foreach(it, b => push(nlb, extrude(b, pol, lvl, freshVar, cache)))\n      else\n        push(lb, nc)\n        let nub = if nc is\n          TypeVariable(_, _, _, ub) then ub\n          else error() // impossible\n        region r in\n          let nbd = empty(r)\n          iter of ub, it => foreach(it, b => push(nbd, b))\n          iter of nbd, it => foreach(it, b => push(nub, extrude(b, pol, lvl, freshVar, cache)))\n      nc\n\n// fun solve: [outer, R extends outer] -> (List[PairOf[Type[R], Type[R]]], (Str, Int) ->{R} Type[R], HashMap[PairOf[Type[R], Type[R]], Any, R], () ->{R} HashMap[PairOf[Type[R], PairOf[Int, Bool]], Type[R], R]) ->{R} ()\nfun solve(constraints, freshVar, cache, genExtrCache) = if constraints is\n  Nil() then ()\n  Cons(c, cs) then if c is\n    Pair(lhs, rhs) then hasOrUpdate of cache, c, () =>\n      if lhs is\n        IntType() then if rhs is\n          IntType() then solve(cs, freshVar, cache, genExtrCache)\n          TypeVariable(name, level, lb, ub) then\n            push(lb, lhs)\n            region r in\n              let ncs = r.ref cs\n              iter(ub, it => foreach(it, b => ncs := Cons(Pair(lhs, b), !(ncs)); ()))\n              solve(!(ncs), freshVar, cache, genExtrCache)\n          else report(lhs, rhs)\n        FunctionType(arg, res) then if rhs is\n          FunctionType(arg', res') then\n            solve(Cons(Pair(arg', arg), Cons(Pair(res, res'), cs)), freshVar, cache, genExtrCache)\n          TypeVariable(name, level, lb, ub) then\n            if levelOf(lhs) <= level then\n              push(lb, lhs)\n              region r in\n                let ncs = r.ref cs\n                iter(ub, it => foreach(it, b => ncs := Cons(Pair(lhs, b), !(ncs)); ()))\n                solve(!(ncs), freshVar, cache, genExtrCache)\n            else\n              let lhs' = extrude(lhs, true, level, freshVar, genExtrCache())\n              solve(Cons(Pair(lhs', rhs), cs), freshVar, cache, genExtrCache)\n          else report(lhs, rhs)\n        RecordType(flds) then if rhs is\n          RecordType(flds') then each(flds', p' =>\n            if p' is Pair(n', t') then\n              if find(flds, p => if p is Pair(n, t) then n === n') is\n                Some(p) then if p is Pair(n, t) then solve(Cons(Pair(t, t'), cs), freshVar, cache, genExtrCache)\n                None() then println(\"Missing field \" ~ n' ~ \" in \" ~ ty2Str(lhs))\n            )\n          TypeVariable(name, level, lb, ub) then\n            if levelOf(lhs) <= level then\n              push(lb, lhs)\n              region r in\n                let ncs = r.ref cs\n                iter(ub, it => foreach(it, b => ncs := Cons(Pair(lhs, b), !(ncs)); ()))\n                solve(!(ncs), freshVar, cache, genExtrCache)\n            else\n              let lhs' = extrude(lhs, true, level, freshVar, genExtrCache())\n              solve(Cons(Pair(lhs', rhs), cs), freshVar, cache, genExtrCache)\n          else report(lhs, rhs)\n        TypeVariable(name, level, lb, ub) then\n          if levelOf(rhs) <= level then\n            push(ub, rhs)\n            region r in\n              let ncs = r.ref cs\n              iter(lb, it => foreach(it, b => ncs := Cons(Pair(b, rhs), !(ncs)); ()))\n              solve(!(ncs), freshVar, cache, genExtrCache)\n          else\n            let rhs' = extrude(rhs, false, level, freshVar, genExtrCache())\n            solve(Cons(Pair(lhs, rhs'), cs), freshVar, cache, genExtrCache)\n\n\nfun freshVar(r, ctx, name, lvl) =\n  if (nt of hasKey(ctx, name)) then\n    add(ctx, name, 1)\n    TypeVariable(name, lvl, empty(r), empty(r))\n  else\n    region r2 in\n      let i = r2.ref 0\n      let res = r2.ref None()\n      whileDo of () =>\n        let nn = name ~ toString(!(i))\n        if (nt of hasKey(ctx, nn)) then\n          res := Some(TypeVariable(nn, lvl, empty(r), empty(r)))\n          add(ctx, nn, 1)\n          false\n        else\n          i := !(i) + 1\n          true\n      if !(res) is\n        Some(v) then v\n        else error()\n\n\nfun genHash(r) =\n  mkHashMap(r, p => if p is Pair(x, y) then ty2Str(x) ~ \" <: \" ~ ty2Str(y))\n\nfun genExtrHash(r) =\n  () => mkHashMap(r, t => if t is Pair(ty, p) then if p is Pair(lvl, pol) then ty2Str(ty) ~ (if pol then \"+_\" else \"-_\") ~ toString(lvl))\n\nfun printBounds(tv) = if tv is\n  TypeVariable(name, level, lb, ub) then\n    iter of lb, it =>\n      foreach of it, b => println(\"  \" ~ ty2Str(b) ~ \" <: \" ~ ty2Str(tv))\n    iter of ub, it =>\n      foreach of it, b => println(\"  \" ~ ty2Str(tv) ~ \" <: \" ~ ty2Str(b))\n  else ()\n\n// fun printRes: [outer, R extends outer] -> (Type[R], Type[R]) ->{R} ()\nfun printRes(lhs, rhs) =\n  println(ty2Str(lhs) ~ \" <: \" ~ ty2Str(rhs))\n  region r in\n    let tvs = mkHashMap(r, s => s)\n    // fun go: [outer, R extends outer, S extends outer] -> (Type[R], HashMap[Str, Type[R], S]) ->{R | S} ()\n    fun go(t, tvs) = if t is\n        IntType() then ()\n        FunctionType(lhs, rhs) then go(lhs, tvs); go(rhs, tvs)\n        RecordType(fields) then each(fields, p => if p is Pair(_, t) then go(t, tvs))\n        TypeVariable(name, level, lb, ub) then\n          getOrUpdate of tvs, name ~ toString(level), () =>\n            region r2 in\n              let tmp = empty(r2)\n              iter of lb, it => foreach(it, ty => push(tmp, ty))\n              iter of ub, it => foreach(it, ty => push(tmp, ty))\n            t\n          ()\n    go(lhs, tvs); go(rhs, tvs)\n    println(\"where: \")\n    iterMap of tvs, it =>\n      values of it, printBounds\n\n// *** error example\n\n// if we call the `solve` function during the iteration, the `solve` function\n// can only handle the cases where no allocation is required (i.e., no type variables)\n// fun TODO() = TODO()\n// fun wrongSolve(constraints, freshVar, cache, genExtrCache) = if constraints is\n//   Nil() then ()\n//   Cons(c, cs) then if c is\n//     Pair(lhs, rhs) then hasOrUpdate of cache, c, () =>\n//       if lhs is\n//         IntType() then TODO()\n//         FunctionType(arg, res) then TODO()\n//         RecordType(flds) then TODO()\n//         TypeVariable(name, level, lb, ub) then\n//           if levelOf(rhs) <= level then\n//             push(ub, rhs)\n//             iter(lb, it => foreach(it, b => solve(Cons(Pair(b, rhs), Nil()), freshVar, cache, genExtrCache)))\n//             solve(cs, freshVar, cache, genExtrCache)\n//           else\n//             let rhs' = extrude(rhs, false, level, freshVar, genExtrCache())\n//             solve(Cons(Pair(lhs, rhs'), cs), freshVar, cache, genExtrCache)\n\n\n// The error' version of `solve` function can only be used for constraints without type variables\n// wrongSolve(Cons(Pair(IntType, IntType), Nil()))\n\n// Calling the `wrongSolve` function to solve constraints involving type variables will lead to type errors\n// region r in\n//   let ctx = mkHashMap(r, s => s)\n//   let a = freshVar(r, ctx, \"a\", 1)\n//   let b = freshVar(r, ctx, \"a\", 1)\n//   let lhs = a\n//   let rhs = b\n//   wrongSolve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n//   printRes(lhs, rhs)\n\n// *** examples\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let lhs = FunctionType(IntType(), IntType())\n  let rhs = IntType()\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let lhs = FunctionType(IntType(), IntType())\n  let a = freshVar(r, ctx, \"a\", 1)\n  let rhs = FunctionType(a, a)\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(lhs, rhs)\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let lhs = RecordType(Cons(Pair(\"a\", IntType()), Cons(Pair(\"b\", FunctionType(IntType(), IntType())), Nil())))\n  let a = freshVar(r, ctx, \"a\", 1)\n  let b = freshVar(r, ctx, \"b\", 1)\n  let rhs = RecordType(Cons(Pair(\"a\", a), Cons(Pair(\"b\", b), Nil())))\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(lhs, rhs)\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let a = freshVar(r, ctx, \"a\", 1)\n  let b = freshVar(r, ctx, \"b\", 1)\n  let lhs = a\n  let rhs = b\n  solve(Cons(Pair(lhs, rhs), Cons(Pair(rhs, lhs), Nil())), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(lhs, rhs)\n  printRes(rhs, lhs)\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let lhs = RecordType(Cons(Pair(\"a\", IntType()), Cons(Pair(\"b\", FunctionType(IntType(), IntType())), Nil())))\n  let b = freshVar(r, ctx, \"b\", 1)\n  let rhs = RecordType(Cons(Pair(\"b\", b), Nil()))\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(lhs, rhs)\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let a = freshVar(r, ctx, \"a\", 1)\n  let b = freshVar(r, ctx, \"b\", 1)\n  let lhs = FunctionType(IntType(), a)\n  let rhs = FunctionType(IntType(), b)\n  if a is\n    TypeVariable(_, _, _, ub) then push(ub, lhs)\n    else error() // impossible\n  if b is\n    TypeVariable(_, _, lb, _) then push(lb, rhs)\n    else error() // impossible\n  solve(Cons(Pair(a, b), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(a, b)\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let a = freshVar(r, ctx, \"a\", 1)\n  let lhs = a\n  let rhs = FunctionType(IntType(), IntType())\n  if a is\n    TypeVariable(_, _, lb, ub) then push(lb, IntType())\n    else error() // impossible\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let a = freshVar(r, ctx, \"a\", 1)\n  let b = freshVar(r, ctx, \"b\", 2)\n  let lhs = FunctionType(IntType(), a)\n  let rhs = FunctionType(IntType(), b)\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(lhs, rhs)\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let a = freshVar(r, ctx, \"a\", 1)\n  let b = freshVar(r, ctx, \"a\", 1)\n  let lhs = a\n  let rhs = b\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(lhs, rhs)\n\n\nregion r in\n  let ctx = mkHashMap(r, s => s)\n  let a = freshVar(r, ctx, \"a\", 1)\n  let b = freshVar(r, ctx, \"b\", 2)\n  let lhs = a\n  let rhs = FunctionType(b, FunctionType(b, b))\n  solve(Cons(Pair(lhs, rhs), Nil()), (n, l) => freshVar(r, ctx, n, l), genHash(r), genExtrHash(r))\n  printRes(lhs, rhs)\n\n\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\n\n// ––––––––– TO IMPROVE LATER –––––––––\n\nfun test(x) = case\n  IntType() then ()\n  FunctionType(l1, r1) then ()\n  RecordType(f) then ()\n  TypeVariable(id, lvl, lbs, ubs) then clear(ubs)\n\n// FIXME: why is this not simplified more? (((Type[out 'TypeVariable] ∧ Type[?]) ∧ Type[?]) ∧ Type[?])\ntest\n//│ Type: ['TypeVariable] -> ⊤ -> ((((Type[out 'TypeVariable] ∧ Type[?]) ∧ Type[?]) ∧ Type[?]) ->{'TypeVariable} ())\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/StackMM.mls",
    "content": ":invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n// * This files includes the stack-based memory management extension of InvalML.\n\nclass Stack[S, R]\nclass StackRef[T, R]\n\nfun (;) seq(_, res) = res\n\nfun allocStack: [E, Res] -> ([S, R] -> Stack[S, R] ->{S | R | E} Res) ->{E} Res\nfun alloc: [S, R, A] -> (Stack[S, R], A) ->{S} StackRef[A, R]\nfun read: [R, A] -> StackRef[A, R] ->{R} A\nfun write: [R, A] -> (StackRef[A, R], A) ->{R} ()\nfun push: [Res, S, R, E extends ~S] -> (Stack[S, R], [U] -> Stack[U, R] -> {U | R | E} Res) ->{E | R | S} Res\n\n\nallocStack of s =>\n  let r1 = alloc(s, 42)\n  let r2 = alloc(s, 0)\n  write(r1, 1)\n  read(r2)\n\n\nallocStack of s1 =>\n  let r1 = alloc(s1, 42)\n  let r2 = alloc(s1, 0)\n  write(r1, 1)\n  read(r2)\n  push of s1, s2 =>\n    let r3 = alloc(s2, 0) in read(r3)\n\n\n// Error! After pusing `s1`, one can not allocate references on it.\n// allocStack of s1 =>\n//   let r1 = alloc(s1, 42)\n//   let r2 = alloc(s1, 0)\n//   write(r1, 1)\n//   read(r2)\n//   push of s1, s2 =>\n//     let r3 = alloc(s1, 0) in read(r3)\n\n\n//│ Type: Int\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/Staging.mls",
    "content": "\n:global\n:invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n// * This files includes the metaprogramming extension of InvalML.\n\n// Type `CodeBase[T, R, S]`:\n//   T: type of quoted expression\n//   R: union of free variables' skolems\n//   S: can be either top or bot. `CodeBase[T, R, bot]` is equivalent to `Var[T, R]`; `CodeBase[T, R, top]` is equivalent to `Code[T, R]`.\n\nfun power: [C] -> CodeBase[out Num, out C, out Any] -> Int -> CodeBase[out Num, out C, out Any]\nfun power(x) = case\n  0 then `1.0\n  n then x `*. power(x)(n - 1)\n\nfun id: [A] -> A -> A\nfun id(x) = x\n\n\nrun(x `=> id(x) `* x)\n\n\nfun assertNotZero: [C] -> CodeBase[out Num, out C, out Any] -> CodeBase[out Num, out C, out Any]\nfun assertNotZero(x) =\n  `if (x `== `0.0) then `error else x\nlet checkedDiv = x `=> y `=> x `/. (assertNotZero(y))\nrun(checkedDiv)\n\n\n\nfun show: [T] -> CodeBase[out T, out Any, out Any] -> Str = s => \"debug\"\n\nfun inc(dbg) =\n  x `=> let c = x `+ `1 in let t = dbg(c) in c\n\ninc(c => log(show(c)))\n\nfun body_naive: [T, C] -> (CodeBase[out Int, out T, out Any], CodeBase[out Int, out C, out Any]) -> Int -> CodeBase[out Int, out T | C, out Any]\nfun body_naive(x, y) = case\n  0 then x\n  1 then y\n  n then body_naive(y, x `+ y)(n - 1)\nfun gib_naive(n) =\n  (x, y) `=> body_naive(x, y)(n)\nlet gn5 = run(gib_naive(5))\n\n\n// Wrong version! There is an unexpected extrusion in `bind`, making `bind` unusable.\n// fun bind(rhs, k) = `let x = rhs `in k(x)\n// fun body: [G] -> (CodeBase[out Int, out G, out Any], CodeBase[out Int, out G, out Any]) -> Int -> CodeBase[out Int, out G, out Any]\n// fun body(x, y) = case\n//   0 then x\n//   1 then y\n//   n then bind of x `+ y, (z => body(y, z)(n - 1))\n\n\nfun bind: [G] -> (CodeBase[out Int, out G, out Any], [C] -> CodeBase[out Int, out C, out Any] -> CodeBase[out Int, out C | G, out Any]) -> CodeBase[out Int, out G, out Any]\nfun bind(rhs, k) = `let x = rhs `in k(x)\n\nfun body: [G] -> (CodeBase[out Int, out G, out Any], CodeBase[out Int, out G, out Any]) -> Int -> CodeBase[out Int, out G, out Any]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then bind of x `+ y, (z => body(y, z)(n - 1))\n\nfun gib(n) = (x, y) `=> body(x, y)(n)\nlet g5 = run(gib(5))\ng5\n\n\n//│ Type: (Int, Int) -> Int\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/flix/GUI.mls",
    "content": ":invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n// * This file includes the type checking implementation for the GUI example\n// * adapted from https://doi.org/10.5281/zenodo.7990289\n\nclass Block\nclass IO\nclass Label\nclass Button\n\n// * So far, our system does not support impure programs.\n// * We explicitly insert this handle function at **the top level** to allow primitive effects like IO and Block\nfun doPrimitiveEffects: [Res, E] -> (() ->{E | IO | Block} Res) ->{E} Res\n\nfun sleep: (Int) ->{Block} ()\n\nfun mkLabel: (Str) ->{IO} Label\nfun mkButton: (Str) ->{IO} Button\n\nfun setText: (Str, Label) ->{IO} ()\n\n// The callback function should not block the execution\n// so `E` has an upper bound `~Block`\nfun addActionListener: [T, E extends ~Block] -> (() ->{E} (), Button) ->{E | T} ()\n\n\n\n// examples\n\ndoPrimitiveEffects of () =>\n  sleep(42)\n\ndoPrimitiveEffects of () =>\n  mkLabel(\"Hello, World!\")\n\ndoPrimitiveEffects of () =>\n  let label = mkLabel(\"Hello, World!\")\n  sleep(42)\n  setText(\"Goodbye, World!\", label)\n\n// ok! `setText` will not block the execution\ndoPrimitiveEffects of () =>\n  let label = mkLabel(\"label\")\n  let button = mkButton(\"button\")\n  addActionListener(() => setText(\"clicked!\", label), button)\n\n\n\n// error! `sleep` will block the execution and the compiler reject the following program\n// doPrimitiveEffects of () =>\n//   let label = mkLabel(\"label\")\n//   let button = mkButton(\"button\")\n//   addActionListener(() => sleep(1), button)\n\n\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/flix/Interpreter.mls",
    "content": "\n:global\n:invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n// * This file includes the implementation for an interpreter and a compiler for a small toy programming language.\n// * Adapted from https://doi.org/10.5281/zenodo.7990289\n\nclass List[T] with\n  constructor\n    Nil\n    Cons(x: T, xs: List[out T])\n\n\nfun concat: [T] -> (List[out T], List[out T]) -> List[out T]\nfun (;) seq(_, res) = res\nfun error: Nothing\n\n\n// * Arithmetical Expression\nclass AExp with\n  constructor\n    Cst(v: Int)\n    Plus(lhs: AExp, rhs: AExp)\n    Minus(lhs: AExp, rhs: AExp)\n    Times(lhs: AExp, rhs: AExp)\n    IfThenElse(cond: BExp, cons: AExp, alts: AExp)\n\n\n// * Boolean Expression\nclass BExp with\n  constructor\n    True\n    False\n    Not(v: BExp)\n    Conj(lhs: BExp, rhs: BExp)\n    Disj(lhs: BExp, rhs: BExp)\n    Eq(lhs: AExp, rhs: AExp)\n    Neq(lhs: AExp, rhs: AExp)\n\n\n// * Evaliation functions\n\nfun evalBExp: BExp -> Bool\n\nfun evalAExp(e) = if e is\n  Cst(v) then v\n  Plus(e1, e2) then evalAExp(e1) + evalAExp(e2)\n  Minus(e1, e2) then evalAExp(e1) - evalAExp(e2)\n  Times(e1, e2) then evalAExp(e1) * evalAExp(e2)\n  IfThenElse(cond, e1, e2) then\n    if evalBExp(cond) then evalAExp(e1) else evalAExp(e2)\n\n\nfun evalBExp(e) = if e is\n  True then true\n  False then false\n  Not(e) then evalBExp(e) is false\n  Conj(e1, e2) then evalBExp(e1) && evalBExp(e2)\n  Disj(e1, e2) then evalBExp(e1) || evalBExp(e2)\n  Eq(e1, e2) then evalAExp(e1) == evalAExp(e2)\n  Neq(e1, e2) then evalAExp(e1) != evalAExp(e2)\n\n\n// * Examples\n\nevalAExp(Cst(42))\nevalAExp(Plus(Cst(42), Cst(21)))\nevalAExp(Minus(Cst(42), Cst(21)))\nevalAExp(IfThenElse(True, Cst(1), Cst(2)))\nevalAExp(IfThenElse(Neq(Cst(1), Cst(2)), Cst(42), Cst(21)))\n\nevalBExp(True)\nevalBExp(Not(True))\nevalBExp(Conj(True, False))\nevalBExp(Disj(True, False))\nevalBExp(Neq(Cst(1), Cst(2)))\n\n\n// * Instruction\nclass Inst with\n  constructor\n    Push(v: Int)\n    Add\n    Sub\n    Mul\n    Neg\n    And\n    Or\n    Cmp\n    Branch(cons: List[out Inst], alts: List[out Inst])\n\n\n// * Compilation functions\n\nfun compileBExp: BExp -> List[out Inst]\n\nfun compileAExp(e) = if e is\n  Cst(v) then Cons(Push(v), Nil)\n  Plus(e1, e2) then\n    let is1 = compileAExp(e1) in\n      let is2 = compileAExp(e2) in\n        concat(concat(is2, is1), Cons(Add, Nil))\n  Minus(e1, e2) then\n    let is1 = compileAExp(e1) in\n      let is2 = compileAExp(e2) in\n        concat(concat(is2, is1), Cons(Sub, Nil))\n  Times(e1, e2) then\n    let is1 = compileAExp(e1) in\n      let is2 = compileAExp(e2) in\n        concat(concat(is2, is1), Cons(Mul, Nil))\n  IfThenElse(e1, e2, e3) then\n    let is1 = compileBExp(e1) in\n      let is2 = compileAExp(e2) in\n        let is3 = compileAExp(e3) in\n          concat(is1, Cons(Branch(is2, is3), Nil))\n  \n\nfun compileBExp(e) = if e is\n  True then Cons(Push(1), Nil)\n  False then Cons(Push(0), Nil)\n  Not(e) then concat(compileBExp(e), Cons(Neg, Nil))\n  Conj(e1, e2) then\n    let is1 = compileBExp(e1) in\n      let is2 = compileBExp(e2) in\n        concat(concat(is2, is1), Cons(And, Nil))\n  Disj(e1, e2) then\n    let is1 = compileBExp(e1) in\n      let is2 = compileBExp(e2) in\n        concat(concat(is2, is1), Cons(Or, Nil))\n  Eq(e1, e2) then\n    let is1 = compileAExp(e1) in\n      let is2 = compileAExp(e2) in\n        concat(concat(is2, is1), Cons(Cmp, Nil))\n  Neq(e1, e2) then\n    let is1 = compileAExp(e1) in\n      let is2 = compileAExp(e2) in\n        concat(concat(is2, is1), Cons(Neg, Cons(Cmp, Nil)))\n\n\n// * Examples\n\ncompileAExp(Cst(42))\ncompileAExp(Plus(Cst(42), Cst(21)))\ncompileAExp(Minus(Cst(42), Cst(21)))\ncompileAExp(IfThenElse(True, Cst(1), Cst(2)))\ncompileAExp(IfThenElse(Neq(Cst(1), Cst(2)), Cst(42), Cst(21)))\ncompileBExp(True)\ncompileBExp(Not(True))\ncompileBExp(Conj(True, False))\ncompileBExp(Disj(True, False))\ncompileBExp(Neq(Cst(1), Cst(2)))\n\n\n// So far, we have not supported nested patterns.\n// This helper function is for the following pattern matching:\n// `if lst is Cons(x, Cons(y, ys)) then f(x, y, ys) else g()`\nfun matchTwo(lst, f, g) = if lst is\n  Nil then g()\n  Cons(x, xs) then\n    if xs is\n      Nil then g()\n      Cons(y, ys) then f(x, y, ys)\n\n\n// * Instruction evaluation\n\nfun evalInst(insts, stack) = if insts is\n  Nil then\n    if stack is\n      Cons(x, xs) then\n        if xs is\n          Nil then x\n          Cons(_, _) then error\n      Nil then error\n  Cons(inst, rest) then if inst is\n    Push(i) then evalInst(rest, Cons(i, stack))\n    Add then matchTwo(stack, (x, y, r) => evalInst(rest, Cons(x + y, r)), () => error)\n    Sub then matchTwo(stack, (x, y, r) => evalInst(rest, Cons(x - y, r)), () => error)\n    Mul then matchTwo(stack, (x, y, r) => evalInst(rest, Cons(x * y, r)), () => error)\n    Neg then if stack is\n      Nil then error\n      Cons(x, xs) then evalInst(rest, Cons(if x == 0 then 1 else 0, xs))\n    And then\n      matchTwo(stack, (x, y, r) => evalInst(rest, Cons(if x != 0 && y != 0 then 1 else 0, r)), () => error)\n    Or then\n      matchTwo(stack, (x, y, r) => evalInst(rest, Cons(if x != 0 || y != 0 then 1 else 0, r)), () => error)\n    Cmp then\n      matchTwo(stack, (x, y, r) => evalInst(rest, Cons(if x == y then 1 else 0, r)), () => error)\n    Branch(is1, is2) then if stack is\n      Nil then error\n      Cons(x, xs) then\n        if x != 0 then evalInst(is1, xs)\n        else evalInst(is2, xs)\n\n\n// * Examples\n\nevalInst(compileAExp(Cst(42)), Nil)\nevalInst(compileAExp(Plus(Cst(42), Cst(21))), Nil)\nevalInst(compileAExp(Minus(Cst(42), Cst(21))), Nil)\nevalInst(compileAExp(IfThenElse(True, Cst(1), Cst(2))), Nil)\nevalInst(compileAExp(IfThenElse(Neq(Cst(1), Cst(2)), Cst(42), Cst(21))), Nil)\nevalInst(compileAExp(IfThenElse(Eq(Cst(1), Cst(2)), Cst(42), Times(Cst(21), Cst(82)))), Nil)\n\n//│ Type: Int\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/invalml/web-demos/reml/MergeSort.mls",
    "content": ":invalml\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n// * This file includes the implementation for merge sorting,\n// * executed sequentially or in parallel.\n// * Adapted from https://doi.org/10.5281/zenodo.8425443\n\n\n// *** infrastructures\n\n\ndeclare class Array[T, R]\n\n\nclass Pair[T, S] with\n  constructor\n    Pr(fst: T, snd: S)\n\n\nfun\n  mkArray: [T, R] -> Region[out R] ->{R} Array[T, out R]\n  push: [T, R] -> (Array[in T, out R], T) ->{R} ()\n  unshift: [T, R] -> (Array[in T, out R], T) ->{R} ()\n  map: [T, S, R, E extends ~R] -> (Array[out T, out R], T ->{E} S) ->{E | R} Array[S, out R]\n  foreach: [T, R, E extends ~R] -> (Array[out T, out R], T ->{E} ()) ->{E | R} ()\n  len: [R] -> Array[in Nothing out Any, out R] ->{R} Int\n  at: [T, R] -> (Array[out T, out R], Int) ->{R} T\n  slice: [T, R] -> (Array[out T, out R], Int) ->{R} Array[out T, out R]\n  concat: [T, R1, R2, R3] -> (Region[out R3], Array[in T, out R1], Array[out T, out R2]) ->{R1 | R2 | R3} Array[T, out R3]\n\n\n// Matching on js array is not supported yet.\n// This helper function is equivalent to `if xs is Cons(x, xs) then fh(x, xs) else fn(xs)`\nfun matchOne(xs, fn, fh) =\n  if len(xs) is 0 then fn(xs)\n  else fh(at(xs, 0), slice(xs, 1))\n\n// Matching on js array is not supported yet.\n// This helper function is equivalent to\n// `if xs is Cons(x, Cons(y, ys)) then f2(x, y, ys) else if xs is Cons(x, xs) then f1(x, xs) else fn(xs)`\n// fun matchTwo: [T, R, E1, E2, E3, S] -> (Array[out T, out R], Array[out T, out R] ->{E1} S, T ->{E2} S, (T, T, Array[out T, out R]) ->{E3} S) ->{E1 | E2 | E3 | R} S\nfun matchTwo(xs, fn, f1, f2) =\n  if len(xs) is 0 then fn(xs)\n  else if len(xs) is 1 then f1(at(xs, 0))\n  else f2(at(xs, 0), at(xs, 1), slice(xs, 2))\n\nfun (;) seq(_, res) = res\n\nfun println: Any -> ()\nfun forkJoin: [T, S, P, E1, E2 extends ~E1, E3] ->\n  (() ->{E1} T, () ->{E2} S, (T, S) ->{E3} P) ->{E1 | E2 | E3} P\n\n\n// *** pmsort implementation\n\n// Split the given array into two sub-arrays.\n// Region r1 and r2 indicate where the two sub-arrays should be stored.\nfun split(xs, r1, r2) =\n  fun rs(xs, ys, zs) =\n    matchTwo of xs, _ => Pr(ys, zs), x => push(ys, x); Pr(ys, zs), (x1, x2, r) => push(ys, x1); push(zs, x2); rs(r, ys, zs)\n  rs(xs, mkArray(r1), mkArray(r2))\n\n\n// Merge arr1 and arr2. The result is stored in region r.\n// fun merge: [T, R1, R2, R] -> (Array[out T, out R1], Array[out T, out R2], Region[R]) ->{R1 | R2 | R} Array[T, out R]\nfun merge(arr1, arr2, r) =\n  fun recm(xs, ys, acc) =\n    matchOne of xs, _ => concat(r, acc, ys), (x, rx) =>\n      matchOne of ys, _ => concat(r, acc, xs), (y, ry) =>\n        if x < y then push(acc, x); recm(rx, ys, acc)\n        else push(acc, y); recm(xs, ry, acc)\n  recm(arr1, arr2, mkArray(r))\n\n\n// Merge sort in single thread.\nfun smsort(xs, r) =\n  matchTwo of xs, _ => mkArray(r), x => let res = mkArray(r) in push(res, x); res, (_, _, _) =>\n    let p = split(xs, r, r) in\n      if p is Pr(fst, snd) then merge(smsort(fst, r), smsort(snd, r), r)\n\n\n// Wrong version! Sub-arrays cannot be stored in the same region!\n// fun pmsort: [R1, R2] -> (Array[out Int, out R1], Region[R2]) ->{R1 | R2} Array[Int, out R2]\n// fun pmsort(xs, r) =\n//   matchTwo of xs, _ => mkArray(r), x => let res = mkArray(r) in push(res, x); res, (_, _, _) =>\n//     let p = split(xs, r, r) in\n//       if p is Pr(fst, snd) then\n//         forkJoin(_ => pmsort(fst, r), pmsort(snd, r), (r1, r2) => merge(r1, r2, r))\n\n\n// Merge sort in parallel.\nfun pmsort: [R1, R2] -> (Array[out Int, out R1], Region[out R2]) ->{R1 | R2} Array[Int, out R2]\nfun pmsort(xs, r) =\n  matchTwo of xs, _ => mkArray(r), x => let res = mkArray(r) in push(res, x); res, (_, _, _) =>\n    region r1 in\n      region r2 in\n        let p = split(xs, r1, r2) in\n          if p is Pr(fst, snd) then\n            forkJoin(() => pmsort(fst, r1), () => pmsort(snd, r2), (rx, ry) => merge(rx, ry, r))\n\n\n// *** simple tests\n\nregion r in\n  let arr = mkArray(r)\n  push(arr, 10)\n  push(arr, 23)\n  push(arr, 13)\n  push(arr, 4)\n  smsort(arr, r)\n\nregion r in\n  let arr = mkArray(r)\n  push(arr, 10)\n  push(arr, 23)\n  push(arr, 13)\n  push(arr, 4)\n  pmsort(arr, r)\n//│ Type: Array[Int, ?]\n//│ ————————————————————————————————————————————————————————————————————————————————\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/ClassInFun.mls",
    "content": ":lift\n:js\n:noInline\n// :deadParamElim off // used to be `off` because lifter changes the parameter lists and DPE used to look at the original ones\n\n// This test was previously used to demonstrate immutable captures names are not properly discriminated,\n// but handler no longer occur before lifting so this now yield the correct result.\n:effectHandlers\n:expect 3\nabstract class Effect with\n  fun perform()\nhandle h = Effect with\n  fun perform()(k) = k()\nfun f() =\n  h.perform()\n  1\nf() + f() + f()\n//│ = 3\n\n:expect 1\nfun f(x) =\n  class Test() with\n    fun get() = x\n  Test()\nf(1).get()\n//│ = 1\n\n:expect 1\nfun f(used1, unused1) =\n  fun g(g_arg) =\n    let used3 = 2\n    fun h = used3\n    used1 + h\n  let unused2 = 2\n  data class Test(a) with\n    fun get() = used1\n  Test(unused1)\nf(1, 2).get()\n//│ = 1\n\n:expect 1\nfun f(used1, unused1) =\n  fun g(g_arg) =\n    let used3 = 2\n    fun h = used3\n    used1 + h\n  let unused2 = 2\n  class Test(a) with\n    fun get() = used1\n  new Test(unused1)\nf(1, 2).get()\n//│ = 1\n\n:expect 1\nfun f(used1, unused1) =\n  fun g(g_arg) =\n    let used3 = 2\n    fun h = used3\n    used1 + h\n  let unused2 = 2\n  class Test with\n    fun get() = used1\n  new Test\nf(1, 2).get()\n//│ = 1\n\n:expect 2\nfun f(x) =\n  class A() with\n    fun f() = set x = 2\n  A().f()\n  x\nf(1)\n//│ = 2\n\n\n:sir\nfun f(x) =\n  class C with\n    fun y = x\n  new C\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let C⁰, f⁰;\n//│ define C⁰ as class C¹ {\n//│   private val x⁰;\n//│   constructor(x) {\n//│     set x⁰ = x;\n//│     end\n//│   }\n//│   method y⁰ = fun y¹ { return x⁰ }\n//│ };\n//│ define f⁰ as fun f¹(x) { return new C¹(x) };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// only w should be in a capture\n:expect 10111\n:sir\nfun f() =\n  let x = 1\n  let y = 10\n  let z = 10\n  let w = 1000\n  class Good() with\n    fun foo() =\n      set z = 100\n      x + y + z + w\n  class Bad() with\n    fun foo() =\n      set w = 10000\n  Bad().foo()\n  Good()\nf().foo()\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let Bad⁰, Good⁰, f², tmp, Capture$scope0⁰;\n//│ define Capture$scope0⁰ as class Capture$scope0² {\n//│   constructor Capture$scope0¹(z$0, w$1) {\n//│     define w$1⁰ as val w$1¹ = w$1;\n//│     define z$0⁰ as val z$0¹ = z$0;\n//│     end\n//│   }\n//│ };\n//│ define Good⁰ as class Good²() {\n//│   private val scope0$cap⁰;\n//│   private val x¹;\n//│   private val y²;\n//│   constructor Good¹(scope0$cap, x, y) {\n//│     set scope0$cap⁰ = scope0$cap;\n//│     set x¹ = x;\n//│     set y² = y;\n//│     end\n//│   }\n//│   method foo⁰ = fun foo¹() {\n//│     let tmp1, tmp2;\n//│     set scope0$cap⁰.z$0 = 100;\n//│     set tmp1 = +⁰(x¹, y²);\n//│     set tmp2 = +⁰(tmp1, scope0$cap⁰.z$0¹);\n//│     return +⁰(tmp2, scope0$cap⁰.w$1¹)\n//│   }\n//│ };\n//│ define Bad⁰ as class Bad²() {\n//│   private val scope0$cap¹;\n//│   constructor Bad¹(scope0$cap) {\n//│     set scope0$cap¹ = scope0$cap;\n//│     end\n//│   }\n//│   method foo² = fun foo³() {\n//│     set scope0$cap¹.w$1 = 10000;\n//│     return runtime⁰.Unit⁰\n//│   }\n//│ };\n//│ define f² as fun f³() {\n//│   let x, y, z, w, tmp1, scope0$cap;\n//│   set scope0$cap = new mut Capture$scope0²(z, w);\n//│   set x = 1;\n//│   set y = 10;\n//│   set scope0$cap.z$0 = 10;\n//│   set scope0$cap.w$1 = 1000;\n//│   set tmp1 = new Bad²()(scope0$cap);\n//│   do tmp1.foo³();\n//│   return new Good²()(scope0$cap, x, y)\n//│ };\n//│ set tmp = f³();\n//│ tmp.foo﹖()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 10111\n\n// handler\n\n:stackSafe 6\n:effectHandlers\nfun sum(n) =\n  if n == 0 then 0\n  else\n    n + sum(n - 1)\nsum(100)\n//│ = 5050\n\n// instance checks\n\nfun f() =\n  data class Test(a) with\n    fun get() = a\n  fun foo() = Test\n  foo()(0)\nf().get()\n//│ = 0\n\n// Parameterized class constructor used as a first-class function\n:expect 43\nfun foo2(x) =\n  class C(y) with\n    fun get = x + y\n  [C, set x += 1]\nlet res = foo2(40)\nres.0(2).get\n//│ = 43\n//│ res = [fun, ()]\n\n:lift\n:w\n:expect 2\nfun f(x) =\n  class Test with\n    fun get() =\n      fun h() = x\n      h()\n  let foo = Test\n  foo\n(new! (f(2))).get()\n//│ ═══[WARNING] Cannot yet lift class `Test` as it is used as a first-class class.\n//│ = 2\n\n:expect 2\nfun test() =\n  class A with\n    fun get = 2\n  class B() extends A\n  B().get\ntest()\n//│ = 2\n\n// Note: semicolon required for auxparam before `return this;`\n// :sir\nfun test(f) =\n  class A(x) with\n    f(x)\n  A(1)\n\n// Check that the extra params are not printed\n:expect \"A(2)\"\nfun f(x) =\n  data class A(y) with\n    fun hi = x + y\n  A(2).toString()\nf(0)\n//│ = \"A(2)\"\n\n:todo\nfun f(x) =\n  class A(...r) with\n    fun a = r.push_back(x)\n    fun b = r\n  new A(1, 2, 3)\nlet res = f(0)\nres.a\nres.b\n//│ ╔══[INTERNAL ERROR] Compiler reached an unsupported state: mismatched param list lengths List() vs List(term:A/r)\n//│ ╟── The compilation result may be incorrect.\n//│ ╙── This is a known compiler limitation; if it is a blocker for you, please report it to the maintainers.\n//│ ═══[RUNTIME ERROR] ReferenceError: r is not defined\n//│ res = A(_)\n\n\n\n// *** Mutability ***\n\n\n// * Trivial case\n:sir\n:noSanityCheck\nfun main() =\n  class C(val a)\n  let c = new mut C(123)\n  set c.a = 0\n  set c.b = \"hi\"\n  let d = new C(456)\n  set d.a = 0\n  let e = C(789)\n  set e.a = 0\n  [c.a, c.b, d.a, e.a]\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let C², main⁰;\n//│ define C² as class C⁴(a) {\n//│   val a⁰;\n//│   constructor C³ {\n//│     define a⁰ as val a¹ = a;\n//│     end\n//│   }\n//│ };\n//│ define main⁰ as fun main¹() {\n//│   let c, d, e;\n//│   set c = new mut C⁴(123);\n//│   set c.a = 0;\n//│   set c.b = \"hi\";\n//│   set d = new C⁴(456);\n//│   set d.a = 0;\n//│   set e = C³(789);\n//│   set e.a = 0;\n//│   return [c.a﹖, c.b﹖, d.a﹖, e.a﹖]\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// * Notice that the lifted class above behaves the same as the equivalent top-level class below:\n\nclass C(val a)\n\nlet c = new mut C(123)\nset c.a = 0\nset c.b = \"hi\"\nlet d = new C(456)\nset d.a = 0\nlet e = C(789)\nset e.a = 0\n//│ c = C(0)\n//│ d = C(456)\n//│ e = C(789)\n\n:expect [0, \"hi\", 456, 789]\n[c.a, c.b, d.a, e.a]\n//│ = [0, \"hi\", 456, 789]\n\n// * Nontrivial case\n:sir\n:noSanityCheck\nfun main(x) =\n  class C(val a) with\n    fun get = x + a\n  let c = new mut C(123)\n  set c.a = 0\n  set c.b = \"hi\"\n  let d = new C(456)\n  set d.a = 0\n  let e = C(789)\n  set e.a = 0\n  [c.a, c.b, d.a, e.a, c.get, d.get, e.get]\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let C⁵, main²;\n//│ define C⁵ as class C⁷(a) {\n//│   private val x²;\n//│   val a²;\n//│   constructor C⁶(x) {\n//│     set x² = x;\n//│     define a² as val a³ = a;\n//│     end\n//│   }\n//│   method get⁰ = fun get¹ {\n//│     return +⁰(x², C⁷.this.a³)\n//│   }\n//│ };\n//│ define main² as fun main³(x) {\n//│   let c, d, e;\n//│   set c = new mut C⁷(123)(x);\n//│   set c.a = 0;\n//│   set c.b = \"hi\";\n//│   set d = new C⁷(456)(x);\n//│   set d.a = 0;\n//│   set e = new C⁷(789)(x);\n//│   set e.a = 0;\n//│   return [c.a﹖, c.b﹖, d.a﹖, e.a﹖, c.get﹖, d.get﹖, e.get﹖]\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect [0, \"hi\", 456, 789, 42, 498, 831]\nmain(42)\n//│ = [0, \"hi\", 456, 789, 42, 498, 831]\n\n// * The lifted class above should behave the same as the equivalent top-level class below:\n\nlet x = id(42)\nclass C(val a) with\n  fun get = x + a\n//│ x = 42\n\nlet c = new mut C(123)\nset c.a = 0\nset c.b = \"hi\"\nlet d = new C(456)\nset d.a = 0\nlet e = C(789)\nset e.a = 0\n//│ c = C(0)\n//│ d = C(456)\n//│ e = C(789)\n\n:expect [0, \"hi\", 456, 789, 42, 498, 831]\n[c.a, c.b, d.a, e.a, c.get, d.get, e.get]\n//│ = [0, \"hi\", 456, 789, 42, 498, 831]\n\n\n// This used to raise a softTODO in DPE\n// The error is because the type tree for classes store parameter list arity information,\n// but the lifter modifies this information, and the equality is enforced by the middle-end\n// flow analysis, which is used by dead param elimination. It would be a pain to change all the\n// class symbols because they could be nested in other symbols at an arbitrary depth.\n// :fixme\n:deadParamElim \nfun f(x) =\n  class A(y) with\n    fun get = x + y\n  new A(2)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/ClassWithCompanion.mls",
    "content": ":lift\n:js\n\n\n:w\nfun foo(x) =\n  class C(y) with\n    fun get = [x, y]\n  module C with\n    val empty = C(123)\n  C.empty\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.9: \t  module C with\n//│ ╙──     \t         ^\n\nfoo(10).get\n//│ = [10, 123]\n\n:w\nfun foo(x) =\n  class C with\n    fun get = x\n  module C with\n    val empty = new C\n  C.empty\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.23: \t  module C with\n//│ ╙──      \t         ^\n\nfoo(10).get\n//│ = 10\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/CompanionsInFun.mls",
    "content": ":lift\n:js\n\n\n:w\n:sir\nfun f(x) =\n  class A with\n    fun get = x\n  module A\n  fun g = new A\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.10: \t  module A\n//│ ╙──      \t         ^\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g⁰, f⁰;\n//│ define g⁰ as fun g¹(A$) {\n//│   return new A$()\n//│ };\n//│ define f⁰ as fun f¹(x) {\n//│   let A;\n//│   define A as class A⁰ {\n//│     method get⁰ = fun get¹ { return x }\n//│   }\n//│   module A¹;\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/CurriedClassInFun.mls",
    "content": ":lift\n:js\n\n\n:expect 2\nfun f(x) =\n  class A()() with\n    fun newA() = A()()\n    fun foo() =\n      set x += 1\n      x\n    fun getX() = x\n  A()()\nlet a = f(0)\na.foo()\nlet b = a.newA()\nb.foo()\na.getX()\n//│ = 2\n//│ a = A()\n//│ b = A()\n\n\n// * Notice how the capture parameter `f$cap` is inserted before the aux param `z` but after the main param `y`\n:soir\nfun f(x) =\n  class A(val y)(val z) with\n    fun newA() = new A(y + 1)(z + 1)\n    fun foo() =\n      set x += 1\n      x\n    fun getX() = x\n  [new A(x + 1)(x + 2), A, A(x + 1), A(x + 1)(x + 2)]\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let A⁰, f⁰, Capture$f⁰, A$⁰;\n//│ define A$⁰ as fun A$¹(f$cap)(y)(z) {\n//│   return new A¹(y)(f$cap)(z)\n//│ };\n//│ define A⁰ as class A¹(y) {\n//│   private val f$cap⁰;\n//│   val y⁰;\n//│   val z⁰;\n//│   constructor A²(f$cap)(z) {\n//│     set f$cap⁰ = f$cap;\n//│     define y⁰ as val y¹ = y;\n//│     define z⁰ as val z¹ = z;\n//│     end\n//│   }\n//│   method newA⁰ = fun newA¹() {\n//│     let tmp, tmp1;\n//│     set tmp = +⁰(A¹.this.y¹, 1);\n//│     set tmp1 = +⁰(A¹.this.z¹, 1);\n//│     return new A¹(tmp)(f$cap⁰)(tmp1)\n//│   }\n//│   method foo⁰ = fun foo¹() {\n//│     let tmp;\n//│     set tmp = +⁰(f$cap⁰.x$0⁰, 1);\n//│     set f$cap⁰.x$0 = tmp;\n//│     return f$cap⁰.x$0⁰\n//│   }\n//│   method getX⁰ = fun getX¹() {\n//│     return f$cap⁰.x$0⁰\n//│   }\n//│ };\n//│ define Capture$f⁰ as class Capture$f² {\n//│   constructor Capture$f¹(x$0) {\n//│     define x$0¹ as val x$0⁰ = x$0;\n//│     end\n//│   }\n//│ };\n//│ define f⁰ as fun f¹(x) {\n//│   let tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, f$cap, A$here;\n//│   set f$cap = new mut Capture$f²(x);\n//│   set tmp = +⁰(f$cap.x$0⁰, 1);\n//│   set tmp1 = +⁰(f$cap.x$0⁰, 2);\n//│   set tmp2 = new A¹(tmp)(f$cap)(tmp1);\n//│   set tmp3 = +⁰(f$cap.x$0⁰, 1);\n//│   set tmp4 = new A¹(tmp3)(f$cap);\n//│   set tmp5 = +⁰(f$cap.x$0⁰, 1);\n//│   set tmp6 = +⁰(f$cap.x$0⁰, 2);\n//│   set tmp7 = new A¹(tmp5)(f$cap)(tmp6);\n//│   set A$here = A$¹(f$cap);\n//│   return [tmp2, A$here, tmp4, tmp7]\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlet res = f(0)\n//│ res = [A(1), fun, fun, A(1)]\n\n:expect [2, 2]\nlet a = res.0\na.foo()\nlet b = a.newA()\nb.foo()\n[a.getX(), b.getX()]\n//│ = [2, 2]\n//│ a = A(1)\n//│ b = A(2)\n\nres.1(10)(20).foo()\n//│ = 3\n\nlet a1 = res.2(20)\n//│ a1 = A(1)\n\na1.foo()\n//│ = 4\n\n:expect 20\na1.z\n//│ = 20\n\nlet a2 = res.2(30)\n//│ a2 = A(1)\n\na2.z\n//│ = 30\n\n:fixme\n:expect 20\na1.z\n//│ ═══[RUNTIME ERROR] Expected: '20', got: '30'\n//│ = 30\n\na.getX()\n//│ = 4\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/DefnsInClass.mls",
    "content": ":js\n:lift\n// NOTE: due to conflict between flow analysis and lifter\n:deadParamElim off\n\n:sir\ndata class A(x) with\n  data class B(y) with\n    fun getB() = x + y\n  fun getA() = B(2).getB()\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let B⁰, A⁰;\n//│ define B⁰ as class B²(y) {\n//│   private val A¹;\n//│   val y⁰;\n//│   constructor B¹(A) {\n//│     set A¹ = A;\n//│     define y⁰ as val y¹ = y;\n//│     end\n//│   }\n//│   method getB⁰ = fun getB¹() {\n//│     return +⁰(A¹.x⁰, B².this.y¹)\n//│   }\n//│ };\n//│ define A⁰ as class A³(x) {\n//│   val x¹;\n//│   constructor A² {\n//│     define x¹ as val x⁰ = x;\n//│     end\n//│   }\n//│   method getA⁰ = fun getA¹() { let tmp; set tmp = new B²(2)(A³.this); return tmp.getB¹() }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 3\nA(1).getA()\n//│ = 3\n\ndata class A1(x) with\n  data class B(y) with\n    fun getB() = x + y\n  fun getA() = (new B(2)).getB()\n\n:expect 3\n(new A1(1)).getA()\n//│ = 3\n\n:sir\nclass A with\n  val x = \n    fun g() = 2\n    g\n(new A).x()\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g⁰, A⁴, tmp;\n//│ define g⁰ as fun g¹() {\n//│   return 2\n//│ };\n//│ define A⁴ as class A⁵ {\n//│   val x²;\n//│   constructor { define x² as val x³ = g¹; end }\n//│ };\n//│ set tmp = new A⁵();\n//│ tmp.x³()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 2\n\n:expect 2\nclass A(a) with\n  let x = 2\n  fun f() =\n    fun g() = x\n    g()\nA(2).f()\n//│ = 2\n\nclass A with\n  let x = 2\n  val bruh = () => x\n  fun f =\n    fun g() =\n      set x += 2\n      this\n    g\nlet a = new A\na.f()\na.f()\na.bruh()\n//│ = 6\n//│ a = A { A$cap: Capture$A { x$0: 6 }, bruh: fun }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/EffectHandlers.mls",
    "content": ":js\n:lift\n\nfun f() = 3\n\n:effectHandlers\nmodule A with\n  data class Test with\n    f()\n    val a = 1\n\n:effectHandlers\nclass Test with\n  f()\n  val a = 1\n\nclass Eff\n\n:effectHandlers\n:expect 7\nhandle h = Eff with\n  fun perform(x)(k) = k(x) + 1\nlet x = 5\nh.perform(x) + 1\n//│ = 7\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/FunInFun.mls",
    "content": ":lift\n:js\n\n\nfun foo =\n  let x\n  fun bar = x\n\n:expect 12\nfun foo =\n  let x\n  fun bar = x\n  x = 12\n  bar\nfoo\n//│ = 12\n\n\n:expect 5\nfun f(used1, unused1) =\n  let used2 = unused1\n  fun g(g_arg) =\n    let used3 = 2\n    used1 + used2\n  let unused2 = 2\n  g(used2) + unused2\nf(1, 2)\n//│ = 5\n\n:expect 9\nfun f(used1, unused1) =\n  let used2 = unused1\n  fun g(g_arg)(g_arg2) =\n    let used3 = 2\n    used1 + used2 + g_arg + g_arg2\n  let unused2 = 2\n  g(used2)(used2) + unused2\nf(1, 2)\n//│ = 9\n\n:expect 9\nfun f(used1, unused1) =\n  let used2 = unused1\n  fun g(g_arg)(g_arg2) =\n    let used3 = 2\n    used1 + used2 + g_arg + g_arg2\n  let unused2 = 2\n  let foo = g\n  foo(used2)(used2) + unused2\nf(1, 2)\n//│ = 9\n\n:expect 5\n:sir\nfun f(used1, unused1) =\n  let used2 = unused1\n  fun g(g_arg) =\n    let used3 = 2\n    used1 + used2\n  let unused2 = 2\n  let foo = g\n  foo(used2) + unused2\nf(1, 2)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g⁰, f⁰, g$⁰;\n//│ define g$⁰ as fun g$¹(used1, used2)(g_arg) {\n//│   return g¹(used1, used2, g_arg)\n//│ };\n//│ define g⁰ as fun g¹(used1, used2, g_arg) {\n//│   let used3;\n//│   set used3 = 2;\n//│   return +⁰(used1, used2)\n//│ };\n//│ define f⁰ as fun f¹(used1, unused1) {\n//│   let used2, unused2, foo, tmp, g$here;\n//│   set used2 = unused1;\n//│   set unused2 = 2;\n//│   set g$here = g$¹(used1, used2);\n//│   set foo = g$here;\n//│   set tmp = foo(used2);\n//│   return +⁰(tmp, unused2)\n//│ };\n//│ f¹(1, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 5\n\n// preserve order\n:sir\nfun f(a1, a2, a3, a4, a5, a6) =\n  fun g = a1 + a2 + a3 + a4 + a5 + a6  \n  g\nf(1,2,3,4,5,6)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g², f²;\n//│ define g² as fun g³(a1, a2, a3, a4, a5, a6) {\n//│   let tmp, tmp1, tmp2, tmp3;\n//│   set tmp = +⁰(a1, a2);\n//│   set tmp1 = +⁰(tmp, a3);\n//│   set tmp2 = +⁰(tmp1, a4);\n//│   set tmp3 = +⁰(tmp2, a5);\n//│   return +⁰(tmp3, a6)\n//│ };\n//│ define f² as fun f³(a1, a2, a3, a4, a5, a6) {\n//│   return g³(a1, a2, a3, a4, a5, a6)\n//│ };\n//│ f³(1, 2, 3, 4, 5, 6)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 21\n\n:expect \"01\"\ndata class Tuple(a, b)\nfun f() =\n  let a = 0\n  fun g() = set a = 1\n  fun h() = a\n  Tuple(g, h) \nlet ret = f()\nlet f1 = ret.a\nlet f2 = ret.b\nlet x = f2().toString()\nf1()\nlet y = f2().toString()\nx + y\n//│ = \"01\"\n//│ f1 = fun\n//│ f2 = fun\n//│ ret = Tuple(fun, fun)\n//│ x = \"0\"\n//│ y = \"1\"\n\n\ndata class Tuple(a, b)\nfun f(used1) =\n  fun g1(used2) =\n    fun h() = \n      set used1 = 10\n      set used2 = 100\n    fun i() = used1 + used2\n    Tuple(h, i)\n  fun g22() = used1\n  Tuple(g1(10), g22)\n\n:expect \"11110110\"\nlet ret = f(1)\nlet gRet = ret.a\nlet g2 = ret.b\nlet hFun = gRet.a\nlet iFun = gRet.b\nlet a = iFun()\nlet b = g2()\nhFun()\nlet c = g2()\nlet d = iFun()\na.toString() + b + c + d\n//│ = \"11110110\"\n//│ a = 11\n//│ b = 1\n//│ c = 10\n//│ d = 110\n//│ g2 = fun\n//│ gRet = Tuple(fun, fun)\n//│ hFun = fun\n//│ iFun = fun\n//│ ret = Tuple(Tuple(fun, fun), fun)\n\n// some variables mutated, some not\n:sir\n:expect 7\nfun f(unused, immutable, mutated) =\n  fun g() =\n    set mutated = 2\n    immutable + mutated\n  fun h() = mutated\n  let a = g()\n  a + h() + unused\nf(1, 2, 1000)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g⁴, h⁰, f⁴, Capture$f⁰;\n//│ define g⁴ as fun g⁵(f$cap, immutable) {\n//│   set f$cap.mutated$0 = 2;\n//│   return +⁰(immutable, f$cap.mutated$0⁰)\n//│ };\n//│ define h⁰ as fun h¹(f$cap) {\n//│   return f$cap.mutated$0⁰\n//│ };\n//│ define Capture$f⁰ as class Capture$f² {\n//│   constructor Capture$f¹(mutated$0) {\n//│     define mutated$0¹ as val mutated$0⁰ = mutated$0;\n//│     end\n//│   }\n//│ };\n//│ define f⁴ as fun f⁵(unused, immutable, mutated) {\n//│   let a, tmp, tmp1, f$cap;\n//│   set f$cap = new mut Capture$f²(mutated);\n//│   set a = g⁵(f$cap, immutable);\n//│   set tmp = h¹(f$cap);\n//│   set tmp1 = +⁰(a, tmp);\n//│   return +⁰(tmp1, unused)\n//│ };\n//│ f⁵(1, 2, 1000)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 7\n\n// if used as a higher order function, pass closures\n:expect 2\nfun f() =\n  let x = g\n  let y = 2\n  fun g() = y\n  x()\nf()\n//│ = 2\n\n:expect 2\nfun f() =\n  let y = 1\n  fun g() = y\n  let x = g\n  set y = 2\n  x()\nf()\n//│ = 2\n\n:expect 2\nfun f(arg) =\n  fun g(n) = if n <= 0 then arg else h(n-1)\n  fun h(n) = if n <= 0 then arg else g(n-1)\n  h(5)\nf(2)\n//│ = 2\n\n:expect 1\nfun f() =\n  let x = 1\n  fun g() = x\n  fun f() = g()\n  f()\nf()\n//│ = 1\n\nfun f() = 3\nfun g() =\n  fun h() = 3\n  h()\ng()\n//│ = 3\n\n:sir\nfun g() =\n  let y = 0\n  fun f(x) =\n    let k = 4\n    set y = 2\n    // set x = 3\n    // just a dummy function to force class generation\n    fun h() =\n      set k = 5\n      set x = 4\n      x + y\n    x\n  f\ng()(1)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let h², f⁶, g⁶, baseCall, Capture$scope0⁰, f$⁰;\n//│ define Capture$scope0⁰ as class Capture$scope0² {\n//│   constructor Capture$scope0¹(y$0) {\n//│     define y$0⁰ as val y$0¹ = y$0;\n//│     end\n//│   }\n//│ };\n//│ define h² as fun h³(scope0$cap, x, k) {\n//│   set k = 5;\n//│   set x = 4;\n//│   return +⁰(x, scope0$cap.y$0¹)\n//│ };\n//│ define f$⁰ as fun f$¹(scope0$cap)(x) {\n//│   return f⁷(scope0$cap, x)\n//│ };\n//│ define f⁶ as fun f⁷(scope0$cap, x) {\n//│   let k;\n//│   set k = 4;\n//│   set scope0$cap.y$0 = 2;\n//│   return x\n//│ };\n//│ define g⁶ as fun g⁷() {\n//│   let y, scope0$cap, f$here;\n//│   set scope0$cap = new mut Capture$scope0²(y);\n//│   set scope0$cap.y$0 = 0;\n//│   set f$here = f$¹(scope0$cap);\n//│   return f$here\n//│ };\n//│ set baseCall = g⁷();\n//│ baseCall(1)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:expect 2\nfun f() =\n  let b = 0\n  fun g() =\n    set b += 1\n    b\n  g\nlet ret = f()\nret()\nret()\n//│ = 2\n//│ ret = fun\n\n:expect 6\nfun f(x, y, z) =\n  fun g() =\n    set x = 1\n    h()\n    x + y + z\n  fun h() =\n    set y = 2\n    i()\n  fun i() =\n    set z = 3\n  g\nf(0, 0, 0)()\n//│ = 6\n\nfun f(x, cond) =\n  set x = 1\n  set x = 2\n  if cond then\n    () => x\n  else\n    set x = 3\n    () => x\n\n:expect 1\nfun f() =\n  let x = 1\n  fun g() = 1\n  fun f() = set x = 1\n  f()\n  x\nf()\n//│ = 1\n\nlet n = 0\n//│ n = 0\n\nfun h() = 3\n\nfun f() =\n  fun g() =\n    set n = n + 1\n  g()\nf()\n\nfun f(es, vs) =\n  let v' = es\n  class A with\n    val fld = v'\n  new A\n\n// f should not have a capture\n:expect 1\n:sir\nfun f(x) =\n  fun g() =\n    set x += 1\n    x\n  if true do return g()\n  set x += 1\n  x\nf(0)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g⁸, f⁸;\n//│ define g⁸ as fun g⁹(x) {\n//│   let tmp;\n//│   set tmp = +⁰(x, 1);\n//│   set x = tmp;\n//│   return x\n//│ };\n//│ define f⁸ as fun f⁹(x) {\n//│   let scrut, tmp;\n//│   set scrut = true;\n//│   match scrut\n//│     true =>\n//│       return g⁹(x)\n//│     else\n//│       set tmp = +⁰(x, 1);\n//│       set x = tmp;\n//│       return x\n//│   end\n//│ };\n//│ f⁹(0)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// try to avoid creating multiple closures\n\nfun f(x) =\n  fun g() = x\n  [g, g]\n\n:sir\nfun f(x) =\n  let y\n  fun g() = y\n  if x < 0 then\n    set y = 1\n    [g, g]\n  else\n    set y = 2\n    [g, g]\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g¹⁰, f¹⁰, g$²;\n//│ define g$² as fun g$³(y)() {\n//│   return g¹¹(y)\n//│ };\n//│ define g¹⁰ as fun g¹¹(y) {\n//│   return y\n//│ };\n//│ define f¹⁰ as fun f¹¹(x) {\n//│   let y, scrut, g$here;\n//│   set scrut = <⁰(x, 0);\n//│   match scrut\n//│     true =>\n//│       set y = 1;\n//│       set g$here = g$³(y);\n//│       return [g$here, g$here]\n//│     else\n//│       set y = 2;\n//│       set g$here = g$³(y);\n//│       return [g$here, g$here]\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sir\nfun f(x) =\n  fun g() = x\n  let a = g\n  set x += 1\n  [a, g]\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let g¹², f¹², Capture$f³, g$⁴;\n//│ define g$⁴ as fun g$⁵(f$cap)() {\n//│   return g¹³(f$cap)\n//│ };\n//│ define g¹² as fun g¹³(f$cap) {\n//│   return f$cap.x$0⁰\n//│ };\n//│ define Capture$f³ as class Capture$f⁵ {\n//│   constructor Capture$f⁴(x$0) {\n//│     define x$0¹ as val x$0⁰ = x$0;\n//│     end\n//│   }\n//│ };\n//│ define f¹² as fun f¹³(x) {\n//│   let a, tmp, f$cap, g$here;\n//│   set f$cap = new mut Capture$f⁵(x);\n//│   set g$here = g$⁵(f$cap);\n//│   set a = g$here;\n//│   set tmp = +⁰(f$cap.x$0⁰, 1);\n//│   set f$cap.x$0 = tmp;\n//│   set g$here = g$⁵(f$cap);\n//│   return [a, g$here]\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// Can be avoided in `h` by passing the initialized closure, but this is more complicated\n// Note that automatically rewriting `fun h() = g` to `fun h() = a` would resolve this,\n// but it requires some more analysis\nfun f(x) =\n  fun g() = x\n  let a = g\n  fun h() = g\n  [a, h()]\n\n// Requires analysis of all branches\nfun f(x) =\n  fun g() = x\n  if true then\n    g\n  else\n    g\n  g\n\n// Spread arguments\n\n:expect [1]\nfun f(x) =\n  fun g(...rest) = \n    print(x)\n    rest\n  let a = g\n  a(1)\nf(2)\n//│ > 2\n//│ = [1]\n\nfun f(...args) =\n  () =>\n    print(\"test\")\n    f(...args)\nf(100)()()()\n//│ > test\n//│ > test\n//│ > test\n//│ = fun\n\n\ndata class Some(x)\n\n// This test generates a function that is not defined directly within the scoped block introducing its symbol,\n// i.e. it is defined another scope nested within the scoped block. This checks that that the function symbol\n// is removed properly from that socpe.\nlet _refChoice = () => if\n  0 is Some(0) then\n    let process''(pairRes) =\n      if pairRes is [restRes] then 0\n  true then\n    let process''() = 0\n_refChoice\n//│ = fun\n//│ _refChoice = fun\n\n:expect 2\nfun f =\n  fun g(x) = x()\n  fun h() = 2\n  g(h)\nf\n//│ = 2\n\n:expect 2\nfun f =\n  class A(x) with\n    fun foo = x()\n  fun h() = 2\n  new A(h)\nf.foo\n//│ = 2\n\n:expect 2\nfun f =\n  class A(x) with\n    fun foo = x()\n  fun h() = 2\n  A(h)\nf.foo\n//│ = 2\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/FunInMethod.mls",
    "content": ":lift\n:js\n\n:expect 6\ndata class A(a) with\n  fun f(b) =\n    fun g(c) = \n      set b = 2\n      a + b + c\n    g\nA(1).f(1)(3)\n//│ = 6\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/Imports.mls",
    "content": ":js\n:lift\n\nimport \"../../mlscript-compile/Option.mls\"\n\n:sjs\nmodule A with\n  fun f(x) = x is Option.Some\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let A1;\n//│ (class A {\n//│   static {\n//│     A1 = this\n//│   }\n//│   static f(x) {\n//│     if (x instanceof Option.Some.class) {\n//│       return true\n//│     }\n//│     return false;\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"A\"]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/Loops.mls",
    "content": ":js\n:lift\n:ignore // FIXME: Lifting should not require scope flattening (which doesn't handle loops)\n\n\nlet fs = mut []\n//│ fs = []\n\nfun foo() =\n  let x = 1\n  while x < 5 do\n    set x += 1\n    fs.push of () => x\n\n:expect 5\nfoo()\nfs.0()\n//│ = 5\n\n\nlet fs = mut []\n//│ fs = []\n\nfun foo() =\n  let i = 1\n  while i < 5 do\n    let x = i\n    set i += 1\n    fs.push of () => x\n\n// * Note that this works with while loop rewriting\n// * See [fixme:0] for cause of the issue\n:expect 1\nfoo()\nfs.0()\n//│ = 1\n\n\n:sir\nfun foo() =\n  let x = 1\n  while true do\n    set x += 1\n    return () => x\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo⁰, lambda⁰, Capture$scope0⁰, lambda$⁰;\n//│ define lambda$⁰ as fun lambda$¹(scope0$cap)() {\n//│   return lambda¹(scope0$cap)\n//│ };\n//│ define lambda⁰ as fun lambda¹(scope0$cap) {\n//│   return scope0$cap.x$0⁰\n//│ };\n//│ define Capture$scope0⁰ as class Capture$scope0² {\n//│   constructor Capture$scope0¹(x$0) {\n//│     define x$0¹ as val x$0⁰ = x$0;\n//│     end\n//│   }\n//│ };\n//│ define foo⁰ as fun foo¹() {\n//│   let x, scope0$cap;\n//│   set scope0$cap = new mut Capture$scope0²(x);\n//│   set scope0$cap.x$0 = 1;\n//│   loop lbl:\n//│     let scrut, tmp;\n//│     set scrut = true;\n//│     match scrut\n//│       true =>\n//│         let lambda$here;\n//│         set tmp = +⁰(scope0$cap.x$0⁰, 1);\n//│         set scope0$cap.x$0 = tmp;\n//│         set lambda$here = lambda$¹(scope0$cap);\n//│         return lambda$here\n//│       else\n//│         end\n//│     end\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 2\nfoo()()\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/ModulesObjects.mls",
    "content": ":lift\n:js\n// NOTE: due to conflict between flow analysis and lifter\n:deadParamElim off\n\n\n// * Lifting an object may require it to gain some mutable fields\n\n:todo\n:w\nfun foo(x, y) =\n  object M with\n    val test = 2\n    fun foo() =\n      set y = 2\n      x + y + test\n  M.foo()\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.12: \t  object M with\n//│ ╙──      \t         ^\n\n:expect 14\nfoo(10, 0)\n//│ = 14\n\n// * This works the same with classes.\n// * Note that we currently generate accessors, which is not ideal;\n// * When the captures are not accessed from the outside, we should be able to drop these.\n:sir\nfun foo(y) =\n  class M with\n    fun foo() =\n      set y = 2\n  (new M).foo()\nfoo(10)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let M⁰, foo⁰;\n//│ define M⁰ as class M¹ {\n//│   private val y⁰;\n//│   constructor(y) {\n//│     set y⁰ = y;\n//│     end\n//│   }\n//│   method foo¹ = fun foo²() {\n//│     set y⁰ = 2;\n//│     return runtime⁰.Unit⁰\n//│   }\n//│ };\n//│ define foo⁰ as fun foo³(y) { let tmp; set tmp = new M¹(y); return tmp.foo²() };\n//│ foo³(10)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * `new mut` (or lack thereof) should be preserved by the lifter\n\nfun foo(y) =\n  class C with\n    fun foo() =\n      set y = 2\n  [new C, new mut C]\n\nlet\n  cc = foo(10)\n  c0 = cc.0\n  c1 = cc.1\n//│ c0 = C\n//│ c1 = C\n//│ cc = [C, C]\n\n:re\nset c0.x = 1\nc0.x\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\nset c1.x = 1\nc1.x\n//│ = 1\n\n\n// * Objects should remain non-`new mut`\n\n:todo\n:w\nfun foo(y) =\n  object O with\n    fun foo() =\n      set y = 2\n  O\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.85: \t  object O with\n//│ ╙──      \t         ^\n\nlet o = foo(10)\n//│ o = O\n\n:re\nset o.x = 1\no.x\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined'\n\n:todo\n:w\n:sir\nfun foo(x, y) =\n  object M with\n    fun foo2() =\n      set y = 2\n      x + y\n  fun foo3 = M.foo2()\n  foo3\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.105: \t  object M with\n//│ ╙──       \t         ^\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let foo3⁰, foo⁴;\n//│ define foo3⁰ as fun foo3¹(M) {\n//│   return M.foo2⁰()\n//│ };\n//│ define foo⁴ as fun foo⁵(x, y) {\n//│   let M;\n//│   define M as object M² {\n//│     method foo2¹ = fun foo2⁰() { set y = 2; return +⁰(x, y) }\n//│   };\n//│   return foo3¹(M²)\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 12\nfoo(10, 0)\n//│ = 12\n\n:todo\n:w\ndata class A(x) with\n  object M with\n    fun getB() = x\n  fun getA() =\n    fun bar = M.getB()\n    bar\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.136: \t  object M with\n//│ ╙──       \t         ^\n\n:expect 2\nA(2).getA()\n//│ = 2\n\n// Classes and functions in modules //\n\n:expect 2\nmodule M with\n  val x = 2\n  class A() with\n    fun get = x\n  val hi = A()\nM.hi.get\n//│ = 2\n\n:expect 2\nmodule M with\n  val x = 2\n  fun f() =\n    fun g() = x\n    g\nM.f()()\n//│ = 2\n\n:expect 2\nobject M with\n  val x = 2\n  class A() with\n    fun get = x\n  val hi = A()\nM.hi.get\n//│ = 2\n\n:expect 2\nobject M with\n  val x = 2\n  fun f() =\n    fun g() = x\n    g\nM.f()()\n//│ = 2\n\n// unlifted objects\n:lift\n:w\n:expect 2\nfun f =\n  object A with\n    fun a = 2\n  0 is A\n  fun foo = A\n  foo\nf.a\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.192: \t  object A with\n//│ ╙──       \t         ^\n//│ = 2\n\n:sir\nmodule M with\n  class A() with\n    fun get = M.x + x\n  val x = if A() is A then 2 else 3\nM.A().get\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let M³, tmp;\n//│ define M³ as class M⁴\n//│ module M⁵ {\n//│   val x⁰;\n//│   constructor {\n//│     let scrut, tmp1;\n//│     define A⁰ as class A¹() {\n//│       method get⁰ = fun get¹ {\n//│         return +⁰(M⁵.this.x¹, M⁵.this.x¹)\n//│       }\n//│     };\n//│     set scrut = M⁵.this.A²();\n//│     match scrut\n//│       A¹ =>\n//│         set tmp1 = 2;\n//│         end\n//│       else\n//│         set tmp1 = 3;\n//│         end\n//│     define x⁰ as val x¹ = tmp1;\n//│     end\n//│   }\n//│ };\n//│ set tmp = M⁵.A²();\n//│ tmp.get¹\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 4\n\nmodule M with\n  val x = 2\n  class A with\n    fun get = x\n  class B() extends A\nM.B().get\n//│ = 2\n\n/// Top Level Modules ///\n\n// newA should reference the class symbol\n// newA_B should reference the BlockMemberSymbol\n// note: no warning because A is not lifted\n:lift\nmodule M with\n  data class A(x) with\n    class B() with\n      fun get = x\n      fun newA_B(y) = A(y)\n    fun newA = A(42)\n    fun newB = B()\n  0 is A\nM.A(2).newB.newA_B(3).newB.get\n//│ = 3\n\nmodule M with\n  class A\n  object B extends A\n\n\n:todo\n:w\n:lift\nfun foo(x) =\n  object O with\n    fun bar = x\n    val baz = x\n  [x === O.bar, set x += 1 in [x === O.bar, x === O.baz], x === O.bar]\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.272: \t  object O with\n//│ ╙──       \t         ^\n\nfoo(123)\n//│ = [true, [true, false], true]\n\nmodule A with\n  fun g = 1\n  fun f = () => g\n  f()\n\nmodule A with\n  val a = (() => 1)()\n\n// This is related to the above, but it will look into the ignored bms map\nmodule A with\n  val x =\n    fun f() = 1\n    f()\n\nmodule A with\n  val x =\n    fun f() = 1\n    fun g() =\n      fun h() = f()\n      h()\n    f() + g()\nA.x\n//│ = 2\n\n// private fields in modules\nmodule A with\n  let x = 1\n  fun mtd =\n    fun nested() = x\n    nested()\nA.mtd\n//│ = 1\n\n// nested objects\n:todo\n:w\nfun f =\n  object A with\n    object B with\n      object C\n  A.B.C\nf\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.320: \t  object A with\n//│ ╙──       \t         ^\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.321: \t    object B with\n//│ ╙──       \t           ^\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.322: \t      object C\n//│ ╙──       \t             ^\n//│ = C\n\n:todo\n:w\nfun f =\n  module A with\n    object B with\n      object C\n  A.B.C\nf\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.339: \t  module A with\n//│ ╙──       \t         ^\n//│ ╔══[WARNING] Objects are not yet lifted.\n//│ ║  l.341: \t      object C\n//│ ╙──       \t             ^\n//│ = C\n\n:todo\n:w\nfun f =\n  module A with\n    module B with\n      object C\n  A.B.C\nf\n//│ ╔══[WARNING] Modules are not yet lifted.\n//│ ║  l.355: \t  module A with\n//│ ╙──       \t         ^\n//│ = C\n\nmodule X with\n  object A\n  A\n\nmodule X with\n  object A\n  fun f =\n    fun g = A\n    g\n  f\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/Mutation.mls",
    "content": ":lift\n:js\n\n\nlet xs = mut []\n//│ xs = []\n\n:sir\nfun foo() =\n  let x = 1\n  fun bar() = x\n  xs.push(bar)\n  set x = 2\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let bar⁰, foo⁰, Capture$scope0⁰, bar$⁰;\n//│ define Capture$scope0⁰ as class Capture$scope0² {\n//│   constructor Capture$scope0¹(x$0) {\n//│     define x$0⁰ as val x$0¹ = x$0;\n//│     end\n//│   }\n//│ };\n//│ define bar$⁰ as fun bar$¹(scope0$cap)() {\n//│   return bar¹(scope0$cap)\n//│ };\n//│ define bar⁰ as fun bar¹(scope0$cap) {\n//│   return scope0$cap.x$0¹\n//│ };\n//│ define foo⁰ as fun foo¹() {\n//│   let x, scope0$cap, bar$here;\n//│   set scope0$cap = new mut Capture$scope0²(x);\n//│   set scope0$cap.x$0 = 1;\n//│   set bar$here = bar$¹(scope0$cap);\n//│   do xs⁰.push﹖(bar$here);\n//│   set scope0$cap.x$0 = 2;\n//│   return runtime⁰.Unit⁰\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect 2\nfoo()\nxs.0()\n//│ = 2\n\n\nlet xs = mut []\n//│ xs = []\n\n// :sir\nfun foo() =\n  let x\n  fun bar() = x\n  xs.push(bar)\n  x = 2\n\n:expect 2\nfoo()\nxs.0()\n//│ = 2\n\n\nfun foo() =\n  let x\n  fun bar() =\n    x = 2\n  [bar, () => x]\n\n\n:expect 2\nlet b_x = foo()\nb_x.0()\nb_x.1()\n//│ = 2\n//│ b_x = [fun, fun]\n\n\nfun foo() =\n  let x = undefined\n  fun bar() =\n    x = 2\n  [bar, () => x]\n\n:expect 2\nlet b_x = foo()\nb_x.0()\nb_x.1()\n//│ = 2\n//│ b_x = [fun, fun]\n\n\n:sir\nfun foo() =\n  fun bar() =\n    let x\n    x\n  bar\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let bar², foo²;\n//│ define bar² as fun bar³() { let x; return x };\n//│ define foo² as fun foo³() { return bar³ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/PatternInFun.mls",
    "content": ":lift\n:js\n\n\n// TODO: Improve warning messages\n:w\nfun foo() =\n  pattern P = Int\n  x => x is P\n//│ ═══[WARNING] Cannot yet lift class `P` as it is used as a first-class class.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/lifter/StackSafetyLift.mls",
    "content": ":js\n:lift\n:noTailRec\n\n// * FIXME: Why doesn't the following work when using Predef function `(==) equals`?\n\n// sanity check\n:expect 5050\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nsum(100)\n//│ = 5050\n\n// preserve tail calls\n// MUST see \"return hi(tmp1)\" in the output\n:stackSafe 6\n:effectHandlers\n:expect 0\n:sir\nfun hi(n) =\n  if n === 0 then 0\n  else hi(n - 1)\nhi(0)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let hi⁰, tmp, ‹stack safe body›⁰;\n//│ do runtime⁰.resetEffects﹖();\n//│ define hi⁰ as fun hi¹(n) {\n//│   let stackDelayRes;\n//│   set runtime⁰.stackDepth = +⁰(runtime⁰.stackDepth﹖, 1);\n//│   set stackDelayRes = runtime⁰.checkDepth﹖();\n//│   match runtime⁰.curEffect﹖\n//│     null =>\n//│       let scrut, tmp1;\n//│       set scrut = ===⁰(n, 0);\n//│       match scrut\n//│         true =>\n//│           return 0\n//│         else\n//│           let res;\n//│           set tmp1 = -⁰(n, 1);\n//│           return hi¹(tmp1)\n//│       end\n//│     else\n//│       return runtime⁰.unwind﹖(hi¹, -1, \"StackSafetyLift.mls:22:1\", null, null, 1, 1, n, 0)\n//│   end\n//│ };\n//│ define ‹stack safe body›⁰ as fun ‹stack safe body›¹() {\n//│   return hi¹(0)\n//│ };\n//│ set tmp = runtime⁰.runStackSafe﹖(6, ‹stack safe body›⁰);\n//│ match runtime⁰.curEffect﹖\n//│   null =>\n//│     tmp\n//│   else\n//│     set tmp = runtime⁰.topLevelEffect﹖(false);\n//│     tmp\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:sir\n:stackSafe\n:effectHandlers\n:expect 50005000\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nsum(10000)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let sum⁰, tmp, ‹stack safe body›²;\n//│ do runtime⁰.resetEffects﹖();\n//│ define sum⁰ as fun sum¹(n) {\n//│   let curDepth, stackDelayRes;\n//│   set runtime⁰.stackDepth = +⁰(runtime⁰.stackDepth﹖, 1);\n//│   set curDepth = runtime⁰.stackDepth﹖;\n//│   set stackDelayRes = runtime⁰.checkDepth﹖();\n//│   match runtime⁰.curEffect﹖\n//│     null =>\n//│       let scrut, tmp1, tmp2, pc;\n//│       match runtime⁰.resumePc﹖\n//│         -1 =>\n//│           set pc = 0;\n//│           end\n//│         else\n//│           let saveOffset;\n//│           set pc = runtime⁰.resumePc﹖;\n//│           set runtime⁰.resumePc = -1;\n//│           end\n//│       loop main:\n//│         match pc\n//│           0 =>\n//│             block brk0:\n//│               set scrut = ===⁰(n, 0);\n//│               match scrut\n//│                 true =>\n//│                   return 0\n//│                 else\n//│                   let res;\n//│                   set tmp1 = -⁰(n, 1);\n//│                   set res = sum¹(tmp1);\n//│                   set runtime⁰.stackDepth = curDepth;\n//│                   set runtime⁰.resumeValue = res;\n//│                   match runtime⁰.curEffect﹖\n//│                     null =>\n//│                       break brk0\n//│                     else\n//│                       let res1;\n//│                       return runtime⁰.unwind﹖(sum¹, 1, \"StackSafetyLift.mls:70:9\", null, null, 1, 1, n, 0)\n//│                   end\n//│               end\n//│             set pc = 1;\n//│             end\n//│         match pc\n//│           1 =>\n//│             set tmp2 = runtime⁰.resumeValue﹖;\n//│             return +⁰(n, tmp2)\n//│           else\n//│             end\n//│         end\n//│       end\n//│     else\n//│       return runtime⁰.unwind﹖(sum¹, -1, \"StackSafetyLift.mls:67:1\", null, null, 1, 1, n, 0)\n//│   end\n//│ };\n//│ define ‹stack safe body›² as fun ‹stack safe body›³() {\n//│   return sum¹(10000)\n//│ };\n//│ set tmp = runtime⁰.runStackSafe﹖(1000, ‹stack safe body›²);\n//│ match runtime⁰.curEffect﹖\n//│   null =>\n//│     tmp\n//│   else\n//│     set tmp = runtime⁰.topLevelEffect﹖(false);\n//│     tmp\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 50005000\n\n// stack-overflows without :stackSafe\n:re\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nsum(10000)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n:effectHandlers\n:stackSafe 6\nmut val ctr = 0\nfun dummy(x) = x\nfun foo(f) = \n  if ctr > 10000 then 0\n  else \n    set ctr += 1\n    dummy(f(f))\nfoo(foo)\n//│ = 0\n//│ ctr = 10001\n\n:stackSafe\n:effectHandlers\n:expect 50005000\nval foo =\n  val f = n =>\n    if n <= 0 then 0\n    else n + f(n-1)\n  f(10000)\nfoo\n//│ = 50005000\n//│ foo = 50005000\n\n:re\nfun foo() =\n  let f = ()\n  set f = n =>\n    if n <= 0 then 0\n    else n + f(n-1)\n  f(10000)\nfoo()\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\nabstract class Eff with\n  fun perform(a): ()\n\n// functions and lambdas inside handlers\n:effectHandlers\n:stackSafe 6\n:expect 50005000\nfun foo(h) = h.perform()\nhandle h = Eff with\n  fun perform()(resume) =\n    let f = ()\n    set f = n =>\n      if n <= 0 then 0\n      else n + f(n-1)\n    resume(f(10000))\nfoo(h)\n//│ = 50005000\n\n// function call and defn inside handler\n:effectHandlers\n:stackSafe 6\n:expect 50005000\nhandle h = Eff with\n  fun perform()(resume) =\n    let f = ()\n    set f = n =>\n      if n <= 0 then 0\n      else n + f(n-1)\n    resume(f(10000))\nin\n  fun foo(h) = h.perform()\n  foo(h)\n//│ = 50005000\n\n:re\n:effectHandlers\nfun foo(h) = h.perform(2)\nhandle h = Eff with\n  fun perform(a)(resume) =\n    let f = ()\n    set f = n =>\n      if n <= 0 then 0\n      else n + f(n-1)\n    resume(f(10000))\nfoo(h)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n:effectHandlers\n:stackSafe\n:sir\nfun max(a, b) = if a < b then b else a\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let max⁰;\n//│ do runtime⁰.resetEffects﹖();\n//│ define max⁰ as fun max¹(a, b) {\n//│   let scrut;\n//│   set scrut = <⁰(a, b);\n//│   match scrut\n//│     true =>\n//│       return b\n//│     else\n//│       return a\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:sir\n:stackSafe 42\nfun hi(n) = n\nhi(0)\n//│ /!!!\\ Option ':stackSafe' requires ':effectHandlers' to be set\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let hi²; define hi² as fun hi³(n) { return n }; hi³(0)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n:stackSafe 42\nhi(0)\n//│ /!!!\\ Option ':stackSafe' requires ':effectHandlers' to be set\n//│ = 0\n\n\n:stackSafe\n:effectHandlers\n:expect 100010000\nfun sum(n) =\n  if n === 0 then 0\n  else\n    n + sum(n - 1)\nfun bad() = sum(10000) + sum(10000)\nbad()\n//│ = 100010000\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/BadPrograms.mls",
    "content": ":llir\n:cpp\n\n:ge\nfun oops(a) =\n  class A with\n    fun m = a\n  let x = 1\n//│ ═══[COMPILATION ERROR] Function without arguments not supported: 0\n//│ Stopped due to an error during the Llir generation\n\n:ge\nlet x = \"oops\"\nx.m\n//│ ═══[COMPILATION ERROR] Unsupported selection by users\n//│ Stopped due to an error during the Llir generation\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/BasicCpp.mls",
    "content": ":js\n:llir\n:cpp\n\nfun foo(a) =\n  let x = undefined\n  if a > 0 do\n    x = 1\n  x + 1\n\n:showWholeCpp\nfun bar(x) =\n  x + 1\nfoo(1)\n//│ = 2\n//│ \n//│ WholeProgramCpp:\n//│ #include \"mlsprelude.h\"\n//│ _mlsValue _mls_entry2();\n//│ _mlsValue _mls_foo(_mlsValue);\n//│ _mlsValue _mls_entry();\n//│ _mlsValue _mls_j();\n//│ _mlsValue _mls_entry1();\n//│ _mlsValue _mls_bar(_mlsValue);\n//│ _mlsValue _mls_bar(_mlsValue _mls_x6) {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x5 = (_mls_x6 + _mlsValue::fromIntLit(1));\n//│   _mls_retval = _mls_x5;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_entry2() {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x7 = _mls_foo(_mlsValue::fromIntLit(1));\n//│   _mls_retval = _mls_x7;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_j() {\n//│   _mlsValue _mls_retval;\n//│   _mls_retval = _mlsValue::create<_mls_Unit>();\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_entry() {\n//│   _mlsValue _mls_retval;\n//│   _mls_retval = _mlsValue::create<_mls_Unit>();\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_foo(_mlsValue _mls_a) {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x = _mlsValue::create<_mls_Unit>();\n//│   auto _mls_x1 = (_mls_a > _mlsValue::fromIntLit(0));\n//│   if (_mlsValue::isIntLit(_mls_x1, 1)) {\n//│     auto _mls_x3 = _mlsValue::fromIntLit(1);\n//│     auto _mls_x4 = (_mls_x3 + _mlsValue::fromIntLit(1));\n//│     _mls_retval = _mls_x4;\n//│   } else {\n//│     auto _mls_x2 = (_mls_x + _mlsValue::fromIntLit(1));\n//│     _mls_retval = _mls_x2;\n//│   }\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_entry1() {\n//│   _mlsValue _mls_retval;\n//│   _mls_retval = _mlsValue::create<_mls_Unit>();\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mlsMain() { return _mls_entry2(); }\n//│ int main() { return _mlsLargeStack(_mlsMainWrapper); }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/BasisLLIR.mls",
    "content": ":js\n:llir\n:cpp\n:noTailRec // The LLIR lowering does not yet support Label blocks\n\n// This file contains all tests for LLIR in the original MLscript compiler.\n\n:intl\ndata class Pair[A, B](x: A, y: B)\nfun mktup2(x, y) = mktup(x, y)\nfun mktup(x, y) = Pair(x, y)\nfun foo() =\n  mktup2(1, 2)\nfoo()\n//│ = Pair(1, 2)\n//│ \n//│ Interpreted:\n//│ Pair(1,2)\n\n:intl\ndata class Pair[A, B](x: A, y: B)\nfun foo(pair) =\n  if pair is\n    Pair(x, y) then Pair(x, y)\nfun bar() =\n  foo(Pair(1, 2))\nbar()\n//│ = Pair(1, 2)\n//│ \n//│ Interpreted:\n//│ Pair(1,2)\n\n:intl\ndata class Pair[A, B](x: A, y: B)\nfun foo(pair) =\n  if pair is\n    Pair(x, y) then Pair(x, y)\nfun bar() =\n  foo(Pair(1, 2))\nbar()\n//│ = Pair(1, 2)\n//│ \n//│ Interpreted:\n//│ Pair(1,2)\n\n:intl\ndata class Pair[A, B](x: A, y: B)\nfun silly(pair) =\n  let x = 0\n  let n = if pair is\n    Pair(x1, x2) then\n      if pair is\n        Pair (x3, x4) then x3 + 1\n  n + 1\nfun foo() =\n    let a = Pair(0, 1)\n    let b = silly(a)\n    b\nfoo()\n//│ = 2\n//│ \n//│ Interpreted:\n//│ 2\n\n:intl\ndata class Pair[A, B](x: A, y: B)\nfun inc_fst(pair) =\n  let c = 2\n  if pair is\n    Pair(x1, x2) then x1 + c\nfun foo() =\n    let a = Pair(0, 1)\n    let b = inc_fst(a)\n    b\nfoo()\n//│ = 2\n//│ \n//│ Interpreted:\n//│ 2\n\n:intl\ndata class Pair[A, B](x: A, y: B)\nfun inc_fst(pair) =\n  let x = 0\n  if pair is\n    Pair(x1, x2) then x2 + 1\nfun foo() =\n    let b = inc_fst(Pair(0, 1))\n    b\nfoo()\n//│ = 2\n//│ \n//│ Interpreted:\n//│ 2\n\n:intl\nabstract class Either[out A, out B]: Left[A, B] | Right[A, B]\ndata class Left[out A, out B](x: A) extends Either[A, B]\ndata class Right[out A, out B](y: B) extends Either[A, B]\nfun foo(a, b) =\n  let t = if a is\n    Left(x) then Left(x + 1)\n    Right(y) then Right(b)\n  if t is\n    Left(x) then x\n    Right(y) then y\nfun bar() =\n  foo(Right(2), 2)\nbar()\n//│ = 2\n//│ \n//│ Interpreted:\n//│ 2\n\n:intl\nabstract class Nat: S[Nat] | O\ndata class S(s: Nat) extends Nat\nobject O extends Nat\nfun foo() =\n  bar(S(O))\nfun bar(x) =\n  baz(x)\nfun baz(x) =\n  if x is\n    S(s) then s\n    O then x\nfoo()\n//│ = O\n//│ \n//│ Interpreted:\n//│ O()\n\n:intl\ndata class A(x, y, z)\ndata class B(m, n)\nfun complex_foo(t) =\n  let r = if t is\n    A(x, y, z) then x + y * z\n    B(m, n) then m - n\n  let s = B(1, 2)\n  let u = if s is\n    A(x, y, z) then 3\n    B(m, n) then 4\n  r + u\nfun bar() =\n  complex_foo(A(6, 7, 8))\n  complex_foo(B(9, 10))\nbar()\n//│ = 3\n//│ \n//│ Interpreted:\n//│ 3\n\n:intl\ndata class A(w, x)\ndata class B(y)\ndata class C(z)\nfun complex_foo(t) =\n  let a = 1 + 2\n  let b = 1 * 2\n  let x = if t is\n    A(x, y) then y\n    B(x) then B(x + b)\n    C(x) then C(0)\n  let z = A(5, x)\n  let v = B(6)\n  let y = if x is\n    A(x, y) then\n      let m = x + a + b\n      if y is\n        A(x, y) then x\n        B(x) then m\n        C(x) then 0\n    B(x) then 2\n    C(x) then 3\n  if z is\n    A(x, y) then x\n    B(x) then 4\n    C(x) then\n      if v is\n        A(x, y) then x\n        B(x) then 7\n        C(x) then 8\nfun bar() =\n  complex_foo(A(10, A(9, B(10))))\nbar()\n//│ = 5\n//│ \n//│ Interpreted:\n//│ 5\n\n:intl\nfun fib(n) = if n < 2 then n else fib(n-1) + fib(n-2)\nfib(20)\n//│ = 6765\n//│ \n//│ Interpreted:\n//│ 6765\n\n:intl\nfun odd(x) = if x === 0 then false else even(x-1)\nfun even(x) = if x === 0 then true else odd(x-1)\nfun foo() = odd(10)\nfoo()\n//│ = false\n//│ \n//│ Interpreted:\n//│ false\n\n:intl\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\nfun nott(x) =\n  if x then false else true\nfun foo(x) =\n  if x then None\n       else Some(foo(nott(x)))\nfun main() = foo(false)\nmain()\n//│ = Some(None)\n//│ \n//│ Interpreted:\n//│ Some(None())\n\n:intl\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\nfun fromSome(s) = if s is Some(x) then x\nabstract class Nat: S[Nat] | O\ndata class S(s: Nat) extends Nat\nobject O extends Nat\nfun aaa() =\n  let m = 1\n  let n = 2\n  let p = 3\n  let q = 4\n  m + n - p + q\nfun bbb() =\n  let x = aaa()\n  x * 100 + 4\nfun nott(x) =\n  if x then false else true\nfun foo(x) =\n  if x then None\n       else Some(foo(nott(x)))\nfun main() =\n  let x = foo(false)\n  if x is\n    None then aaa()\n    Some(b1) then bbb()\nmain()\n//│ = 404\n//│ \n//│ Interpreted:\n//│ 404\n\n:intl\nabstract class Nat: S[Nat] | O\ndata class S(s: Nat) extends Nat\nobject O extends Nat\nfun odd(x) =\n  if x is\n    O then false\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then true\n    S(s) then odd(s)\nfun foo() = odd(S(S(S(O))))\nfoo()\n//│ = true\n//│ \n//│ Interpreted:\n//│ true\n\n:intl\nabstract class Nat: S[Nat] | O\ndata class S(s: Nat) extends Nat\nobject O extends Nat\nfun odd(x) =\n  if x is\n    O then false\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then true\n    S(s) then odd(s)\nfun mk(n) = if n > 0 then S(mk(n - 1)) else O\nfun foo() = odd(mk(10))\nfoo() \n//│ = false\n//│ \n//│ Interpreted:\n//│ false\n\n:intl\nabstract class Nat: S[Nat] | O\ndata class S(s: Nat) extends Nat\nobject O extends Nat\nfun odd(x) =\n  if x is\n    O then false\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then true\n    S(s) then odd(s)\nfun mk(n) = if n > 0 then S(mk(n - 1)) else O\nfun foo() = odd(S(S(mk(10))))\nfoo()\n//│ = false\n//│ \n//│ Interpreted:\n//│ false\n\n:intl\nabstract class Nat: S[Nat] | O\ndata class S(s: Nat) extends Nat\nobject O extends Nat\nfun odd(x) =\n  if x is\n    O then false\n    S(s) then even(s)\nfun even(x) =\n  if x is\n    O then true\n    S(s) then odd(s)\nfun foo() = odd(if 10 > 0 then S(O) else O)\nfun bar() = if 10 > 0 then odd(S(O)) else odd(O)\nfun main() =\n  foo()\n  bar()\nmain()\n//│ = true\n//│ \n//│ Interpreted:\n//│ true\n\n:intl\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\nabstract class List[out T]: Cons[T] | Nil\ndata class (::) Cons[out T](head: T, tail: List[T]) extends List[T]\nobject Nil extends List\nfun head_opt(l) =\n  if l is\n    Nil then None\n    Cons(h, t) then Some(h)\nfun is_none(o) =\n  if o is\n    None then true\n    Some(x) then false\nfun is_empty(l) =\n  is_none(head_opt(l))\nfun main() =\n  is_empty(Cons(1, Cons(2, Nil)))\nmain()\n//│ = false\n//│ \n//│ Interpreted:\n//│ false\n\n:intl\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\nabstract class List[out T]: Cons[T] | Nil\ndata class (::) Cons[out T](head: T, tail: List[T]) extends List[T]\nobject Nil extends List\nfun mk_list(n) =\n  if n === 0 then Nil else Cons(n, mk_list(n - 1))\nfun head_opt(l) =\n  if l is\n    Nil then None\n    Cons(h, t) then Some(h)\nfun is_none(o) =\n  if o is\n    None then true\n    Some(x) then false\nfun is_empty(l) =\n  is_none(head_opt(l))\nfun main() =\n  is_empty(mk_list(10))\nmain()\n//│ = false\n//│ \n//│ Interpreted:\n//│ false\n\n\n:intl\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\nabstract class List[out T]: Cons[T] | Nil\ndata class (::) Cons[out T](head: T, tail: List[T]) extends List[T]\nobject Nil extends List\nfun mk_list(n) =\n  if n === 0 then Nil else Cons(n, mk_list(n - 1))\nfun last_opt(l) =\n  if l is\n    Nil then None\n    Cons(h, t) then\n      if t is\n        Nil then Some(h)\n        Cons(h2, t2) then last_opt(t)\nfun main() =\n  last_opt(mk_list(10))\nmain()\n//│ = Some(1)\n//│ \n//│ Interpreted:\n//│ Some(1)\n\n:intl\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\nfun is_some(o) =\n  if o is\n    Some(x) then true\n    None then false\nfun e0(w) =\n  w + 8 + 9 + 10\nfun e1(a, c) =\n  a + 1 + 2 + 3 + 4\nfun e3(c) =\n  let m = 4\n  let n = 5\n  let p = 6\n  let q = 7\n  if c then m + n + p + q else m + n - p + q\nfun e2(x) =\n  x + 12 + 13 + 14\nfun f(x) =\n  let c1 = is_some(x)\n  let z = e3(c1)\n  let w = if x is\n    Some(a) then e1(a, z)\n    None then e2(z)\n  e0(w)\nfun main() =\n  f(Some(2)) + f(None)\nmain()\n//│ = 115\n//│ \n//│ Interpreted:\n//│ 115\n\n:intl\nabstract class Nat: S[Nat] | O\ndata class S(s: Nat) extends Nat\nobject O extends Nat\nfun pred(n) =\n  if n is\n    S(p) then p\n    O then O\nfun plus(n1, n2) =\n  if n1 is\n    O then n2\n    S(p) then S(plus(p, n2))\nfun fib(n) =\n  if n is\n    O then S(O)\n    S(p) then\n      if p is\n        O then S(O)\n        S(q) then plus(fib(p), fib(q))\nfun to_int(n) =\n  if n is\n    O then 0\n    S(p) then 1 + to_int(p)\nfun to_nat(n) =\n  if n === 0 then O\n  else S(to_nat(n - 1))\nfun main() =\n  to_int(fib(to_nat(10)))\nmain()\n//│ = 89\n//│ \n//│ Interpreted:\n//│ 89\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/Classes.mls",
    "content": ":llir\n:cpp\n:noTailRec // The LLIR lowering does not yet support Label blocks\n\n:intl\nabstract class Callable\nobject FnLike1 extends Callable with\n  fun apply1(x) = x * 2\nfun apply(f, x) = f(x)\nfun main() =\n  let mul2 = FnLike1\n  apply(mul2, 3)\nmain()\n//│ \n//│ Interpreted:\n//│ 6\n\n:intl\n:sllir\nclass Base() with\n  fun get() = 1\nclass Derived() extends Base with\n  fun get() = 2\nfun main() =\n  let d = Derived()\n  d.Base#get() * d.Derived#get()\nmain()\n//│ LLIR:\n//│   class Base() {\n//│     def get() =\n//│       1\n//│   }\n//│   class Derived() extends Base {\n//│     def get1() =\n//│       2\n//│   }\n//│   def main() =\n//│     let x = Derived() in\n//│     let x1 = Base.get(x) in\n//│     let x2 = Derived.get(x) in\n//│     let x3 = *(x1,x2) in\n//│     x3\n//│   def entry() =\n//│     let* (x4) = main() in\n//│     x4\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 4\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/ControlFlow.mls",
    "content": ":js\n:llir\n:cpp\n:noTailRec // The LLIR lowering does not yet support Label blocks\n\n:sllir\n:intl\nfun f1() =\n  let x = 1\n  let x = 2\n  x\nf1()\n//│ = 2\n//│ LLIR:\n//│   \n//│   def f1() =\n//│     let x = 1 in\n//│     let x1 = 2 in\n//│     x1\n//│   def entry() =\n//│     let* (x2) = f1() in\n//│     x2\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 2\n\n:sllir\n:intl\nfun f2() =\n  let x = 0\n  if x === 1 then 2 else 3\nf2()\n//│ = 3\n//│ LLIR:\n//│   \n//│   def f2() =\n//│     let x = 0 in\n//│     let x1 = ===(x,1) in\n//│     case x1 of\n//│       Lit(BoolLit(true)) =>\n//│         2\n//│       _ =>\n//│         3\n//│   def j() =\n//│     undefined\n//│   def entry() =\n//│     let* (x2) = f2() in\n//│     x2\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 3\n\n\n:sllir\nfun f3() =\n  let x1 = 0\n  let x2 = 1\n  if true then x1 else x2\nf3()\n//│ = 0\n//│ LLIR:\n//│   \n//│   def f3() =\n//│     let x = 0 in\n//│     let x1 = 1 in\n//│     let x2 = true in\n//│     case x2 of\n//│       Lit(BoolLit(true)) =>\n//│         x\n//│       _ =>\n//│         x1\n//│   def j() =\n//│     undefined\n//│   def entry() =\n//│     let* (x3) = f3() in\n//│     x3\n//│   entry = entry\n\n\n:sllir\n:intl\nfun f4() =\n  let x = 0\n  let x = if x === 1 then 2 else 3\n  x\nf4()\n//│ = 3\n//│ LLIR:\n//│   \n//│   def f4() =\n//│     let x = 0 in\n//│     let x1 = ===(x,1) in\n//│     case x1 of\n//│       Lit(BoolLit(true)) =>\n//│         let x2 = 2 in\n//│         jump j(x2)\n//│       _ =>\n//│         let x3 = 3 in\n//│         jump j(x3)\n//│   def j(tmp) =\n//│     tmp\n//│   def entry() =\n//│     let* (x4) = f4() in\n//│     x4\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 3\n\n:sllir\n:intl\nfun f5() =\n  let x = 0\n  let x = if x === 1 then 2 else 3\n  let x = if x === 2 then 4 else 5\n  x\nf5()\n//│ = 5\n//│ LLIR:\n//│   \n//│   def f5() =\n//│     let x = 0 in\n//│     let x1 = ===(x,1) in\n//│     case x1 of\n//│       Lit(BoolLit(true)) =>\n//│         let x2 = 2 in\n//│         jump j(x2)\n//│       _ =>\n//│         let x3 = 3 in\n//│         jump j(x3)\n//│   def j(tmp) =\n//│     let x4 = ===(tmp,2) in\n//│     case x4 of\n//│       Lit(BoolLit(true)) =>\n//│         let x5 = 4 in\n//│         jump j1(x5)\n//│       _ =>\n//│         let x6 = 5 in\n//│         jump j1(x6)\n//│   def j1(tmp1) =\n//│     tmp1\n//│   def entry() =\n//│     let* (x7) = f5() in\n//│     x7\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 5\n\n// :fixme // wat\n:sllir\nfun test() =\n  if true do test()\n//│ LLIR:\n//│   \n//│   def test() =\n//│     let x = true in\n//│     case x of\n//│       Lit(BoolLit(true)) =>\n//│         let* (x1) = test() in\n//│         undefined\n//│       _ =>\n//│         undefined\n//│   def j() =\n//│     undefined\n//│   def entry() =\n//│     undefined\n//│   entry = entry\n\n:sllir\nfun test() =\n  (if true then test()) + 1\n//│ LLIR:\n//│   \n//│   def test() =\n//│     let x = true in\n//│     case x of\n//│       Lit(BoolLit(true)) =>\n//│         let* (x1) = test() in\n//│         let x2 = +(x1,1) in\n//│         x2\n//│       _ =>\n//│         panic \"match error\"\n//│   def j() =\n//│     undefined\n//│   def entry() =\n//│     undefined\n//│   entry = entry\n\n\n:sllir\n:intl\nfun f() =\n  let x = 10\n  if true do\n    set x += 1\n  x\nf()\n//│ = 11\n//│ LLIR:\n//│   \n//│   def f() =\n//│     let x = 10 in\n//│     let x1 = true in\n//│     case x1 of\n//│       Lit(BoolLit(true)) =>\n//│         let x2 = +(x,1) in\n//│         x2\n//│       _ =>\n//│         x\n//│   def j() =\n//│     undefined\n//│   def entry() =\n//│     let* (x3) = f() in\n//│     x3\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 11\n\n:sllir\n:intl\ndata class A(x)\ndata class B(y)\nfun f(a) =\n  let t = if a is\n    A(_) then 1\n    B(_) then 2\n  t\nf(A(1))\n//│ = 1\n//│ LLIR:\n//│   class A(x)\n//│   class B(y)\n//│   def f(a) =\n//│     case a of\n//│       Class(class:A) =>\n//│         let x = a.<A:x> in\n//│         let x1 = 1 in\n//│         jump j(x1)\n//│       Class(class:B) =>\n//│         let x2 = a.<B:y> in\n//│         let x3 = 2 in\n//│         jump j(x3)\n//│       _ =>\n//│         panic \"match error\"\n//│   def j(tmp) =\n//│     tmp\n//│   def entry() =\n//│     let x4 = A(1) in\n//│     let* (x5) = f(x4) in\n//│     x5\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 1\n\n:sllir\n:intl\n:fixme // Started failing since split deduplication was introduced.\ndata class A(x)\ndata class B(y)\nfun f(a) =\n  let t = if a is\n    A(_) then if a is\n      A(1) then 1\n      B(_) then 2\n    B(_) then 3\n  t\nf(A(1))\n//│ = 1\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: Label not supported (of class String)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/Ctor.mls",
    "content": ":js\n:llir\n:cpp\n\nobject None\nfun testCtor1() = None\n\n:e\n:ge\nfun testCtor2() = new None\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found reference of type None.\n//│ ║  l.10: \tfun testCtor2() = new None\n//│ ║        \t                      ^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ═══[COMPILATION ERROR] Unsupported kind of Instantiate\n//│ Stopped due to an error during the Llir generation\n\nclass A(x)\nfun testCtor1() = A(1)\nfun testCtor2() = new A(1)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/HigherOrder.mls",
    "content": ":js\n:llir\n:cpp\n:intl\n:noTailRec // The LLIR lowering does not yet support Label blocks\n\n//│ \n//│ Interpreted:\n//│ undefined\n// :ge\n:sllir\nfun add(x) = y => x + y\nfun add_curried(x)(y) = x + y\nadd(1)(2)\n//│ = 3\n//│ LLIR:\n//│   class Lambda_lambda(lam_arg0) extends Callable {\n//│     def apply1(y) =\n//│       let x = +(lam_arg0,y) in\n//│       x\n//│   }\n//│   class Lambda(lam_arg0) extends Callable {\n//│     def apply1(y1) =\n//│       let x1 = +(lam_arg01,y1) in\n//│       x1\n//│   }\n//│   def add(x2) =\n//│     let x3 = Lambda_lambda(x2) in\n//│     x3\n//│   def add_curried(x4) =\n//│     let x5 = Lambda(x4) in\n//│     x5\n//│   def entry() =\n//│     let* (x6) = add(1) in\n//│     let x7 = Callable.apply1(x6,2) in\n//│     x7\n//│   entry = entry\n//│ \n//│ Interpreted:\n//│ 3\n\n// :ge\nfun add4(a, b) = (c, d) => a + b + c + d\nfun add4_curried(a, b)(c, d) = a + b + c + d\nadd4(1, 2)(3, 4)\n//│ = 10\n//│ \n//│ Interpreted:\n//│ 10\n\n// :ge\nfun add(a, b) = a + b\nfun dummy() = add\ndummy()(1, 2)\n//│ = 3\n//│ \n//│ Interpreted:\n//│ 3\n\nabstract class List[out T]: Cons[T] | Nil\ndata class (::) Cons[out T](head: T, tail: List[T]) extends List[T]\nobject Nil extends List\nfun map(f, l) =\n  if l is\n    Cons(h, t) then Cons(f(h), map(f, t))\n    Nil then Nil\nfun inc(x) = x + 1\nfun main() =\n  map(x => inc(x), 1 :: 2 :: Nil)\n  map(inc, 3 :: 4 :: Nil)\nmain()\n//│ = Cons(4, Cons(5, Nil))\n//│ \n//│ Interpreted:\n//│ Cons(4,Cons(5,Nil()))\n\nabstract class List[out T]: Cons[T] | Nil\ndata class (::) Cons[out T](head: T, tail: List[T]) extends List[T]\nobject Nil extends List\nfun nott(c) = if c then false else true\nfun filter(f, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    f(h) then h :: filter(f, t)\n    else filter(f, t)\nfun nubBy(eq, ls) = if ls is\n  Nil then Nil\n  h :: t then h :: nubBy(eq, filter(y => nott(eq(h, y)), t))\nnubBy((x, y) => x === y, 1 :: 2 :: 3 :: 3 :: Nil)\n//│ = Cons(1, Cons(2, Cons(3, Nil)))\n//│ \n//│ Interpreted:\n//│ Cons(1,Cons(2,Cons(3,Nil())))\n\n:intl\nfun f(x) =\n  fun self_rec(x) =\n    if x === 0 then 0\n    else x + self_rec(x - 1)\n  self_rec(x)\nf(3)\n//│ = 6\n//│ \n//│ Interpreted:\n//│ 6\n\nfun f(x) =\n  fun even(x) =\n    fun odd(x) =\n      if x === 0 then true\n      else if x === 1 then false\n      else even(x - 1)\n    if x === 0 then true\n    else if x === 1 then false\n    else odd(x - 1)\n  even(x)\nf(3)\n//│ = false\n//│ \n//│ Interpreted:\n//│ false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/Lazy.mls",
    "content": ":llir\n\n// This should ideally be a declaration.\n// Now it is a built-in class specially handled in the C++ backend,\n// with related logic defined in `mlsprelude.h`.\nabstract class Lazy[out A](init: () -> A) with\n  fun get: A\nfun lazy(x) = Lazy(x)\nfun force(x) = if x is Lazy then x.Lazy#get()\ntype LazyList[out T] = Lazy[LzList[T]]\nabstract class LzList[out T]: LzCons[T] | LzNil\ndata class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T]\nobject LzNil extends LzList\n\n:sllir\n:scpp\nfun side_effect() =\n  console.log(\"executed\")\n  1\nfun main() =\n  let x = lazy(() => side_effect())\n  let y = force(x)\n  let y1 = force(x) // force again, but should not execute side_effect again\n  ()\nmain()\n//│ LLIR:\n//│   class Lambda_lambda() extends Callable {\n//│     def apply0() =\n//│       let* (x) = side_effect() in\n//│       x\n//│   }\n//│   def side_effect() =\n//│     let* (x1) = $_builtin$_(\"println\",\"executed\") in\n//│     1\n//│   def main() =\n//│     let x2 = Lambda_lambda() in\n//│     let* (x3) = lazy(x2) in\n//│     let* (x4) = force(x3) in\n//│     let* (x5) = force(x3) in\n//│     undefined\n//│   def entry() =\n//│     let* (x6) = main() in\n//│     x6\n//│   entry = entry\n//│ \n//│ Cpp:\n//│ #include \"mlsprelude.h\"\n//│ struct _mls_Lambda_lambda;\n//│ _mlsValue _mls_side_effect();\n//│ _mlsValue _mls_main();\n//│ _mlsValue _mls_entry();\n//│ struct _mls_Lambda_lambda: public _mls_Callable {\n//│   \n//│   constexpr static inline const char *typeName = \"Lambda_lambda\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); }\n//│   virtual void destroy() override {  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_lambda; _mlsVal->refCount = 1; _mlsVal->tag = typeTag;  return _mlsValue(_mlsVal); }\n//│   virtual _mlsValue _mls_apply0();\n//│ };\n//│ _mlsValue _mls_side_effect() {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x1 = _mls_builtin_println(_mlsValue::create<_mls_Str>(\"executed\"));\n//│   _mls_retval = _mlsValue::fromIntLit(1);\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_main() {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x2 = _mlsValue::create<_mls_Lambda_lambda>();\n//│   auto _mls_x3 = _mls_lazy(_mls_x2);\n//│   auto _mls_x4 = _mls_force(_mls_x3);\n//│   auto _mls_x5 = _mls_force(_mls_x3);\n//│   _mls_retval = _mlsValue::create<_mls_Unit>();\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_entry() {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x6 = _mls_main();\n//│   _mls_retval = _mls_x6;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_Lambda_lambda::_mls_apply0() {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x = _mls_side_effect();\n//│   _mls_retval = _mls_x;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mlsMain() { return _mls_entry(); }\n//│ int main() { return _mlsLargeStack(_mlsMainWrapper); }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/LazyCycle.mls",
    "content": ":llir\n\n// This should ideally be a declaration.\n// Now it is a built-in class specially handled in the C++ backend,\n// with related logic defined in `mlsprelude.h`.\nabstract class Lazy[out A](init: () -> A) with\n  fun get: A\nfun lazy(x) = Lazy(x)\nfun force(x) = if x is Lazy then x.Lazy#get()\ntype LazyList[out T] = Lazy[LzList[T]]\nabstract class LzList[out T]: LzCons[T] | LzNil\ndata class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T]\nobject LzNil extends LzList\n\n:sllir\n:showWholeCpp\nfun llist(x) =\n  fun f(x) = lazy(() => LzCons(x, f(x + 1)))\n  f(x)\nllist(1)\n//│ LLIR:\n//│   class Lambda_lambda(lam_arg0,lam_arg1) extends Callable {\n//│     def apply0() =\n//│       let x = +(lam_arg0,1) in\n//│       let x1 = Callable.apply1(lam_arg1,x) in\n//│       let x2 = LzCons(lam_arg0,x1) in\n//│       x2\n//│   }\n//│   class Lambda_f() extends Callable {\n//│     def apply1(x3) =\n//│       let x4 = Lambda_lambda(x3,$_this$_) in\n//│       let* (x5) = lazy(x4) in\n//│       x5\n//│   }\n//│   def llist(x6) =\n//│     let x7 = Lambda_f() in\n//│     let x8 = Callable.apply1(x7,x6) in\n//│     x8\n//│   def entry() =\n//│     let* (x9) = llist(1) in\n//│     x9\n//│   entry = entry\n//│ \n//│ WholeProgramCpp:\n//│ #include \"mlsprelude.h\"\n//│ struct _mls_Lambda_f;\n//│ struct _mls_Lambda_lambda;\n//│ struct _mls_Lazy;\n//│ struct _mls_LzList;\n//│ struct _mls_LzCons;\n//│ struct _mls_LzNil;\n//│ _mlsValue _mls_entry2();\n//│ _mlsValue _mls_entry();\n//│ _mlsValue _mls_llist(_mlsValue);\n//│ _mlsValue _mls_force(_mlsValue);\n//│ _mlsValue _mls_lazy(_mlsValue);\n//│ _mlsValue _mls_j();\n//│ _mlsValue _mls_entry1();\n//│ struct _mls_Lambda_f: public _mls_Callable {\n//│   \n//│   constexpr static inline const char *typeName = \"Lambda_f\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); }\n//│   virtual void destroy() override {  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_f; _mlsVal->refCount = 1; _mlsVal->tag = typeTag;  return _mlsValue(_mlsVal); }\n//│   virtual _mlsValue _mls_apply1(_mlsValue);\n//│ };\n//│ struct _mls_Lambda_lambda: public _mls_Callable {\n//│   _mlsValue _mls_lam_arg0;\n//│   _mlsValue _mls_lam_arg1;\n//│   constexpr static inline const char *typeName = \"Lambda_lambda\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); std::printf(\"(\"); this->_mls_lam_arg0.print(); std::printf(\", \"); this->_mls_lam_arg1.print();  std::printf(\")\"); }\n//│   virtual void destroy() override { _mlsValue::destroy(this->_mls_lam_arg0); _mlsValue::destroy(this->_mls_lam_arg1);  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create(_mlsValue _mls_lam_arg0, _mlsValue _mls_lam_arg1) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lambda_lambda; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_lam_arg0 = _mls_lam_arg0; _mlsVal->_mls_lam_arg1 = _mls_lam_arg1;  return _mlsValue(_mlsVal); }\n//│   virtual _mlsValue _mls_apply0();\n//│ };\n//│ struct _mls_LzList: public _mlsObject {\n//│   \n//│   constexpr static inline const char *typeName = \"LzList\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); }\n//│   virtual void destroy() override {  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzList; _mlsVal->refCount = 1; _mlsVal->tag = typeTag;  return _mlsValue(_mlsVal); }\n//│   \n//│ };\n//│ struct _mls_LzCons: public _mls_LzList {\n//│   _mlsValue _mls_head;\n//│   _mlsValue _mls_tail;\n//│   constexpr static inline const char *typeName = \"LzCons\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); std::printf(\"(\"); this->_mls_head.print(); std::printf(\", \"); this->_mls_tail.print();  std::printf(\")\"); }\n//│   virtual void destroy() override { _mlsValue::destroy(this->_mls_head); _mlsValue::destroy(this->_mls_tail);  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create(_mlsValue _mls_head, _mlsValue _mls_tail) { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzCons; _mlsVal->refCount = 1; _mlsVal->tag = typeTag; _mlsVal->_mls_head = _mls_head; _mlsVal->_mls_tail = _mls_tail;  return _mlsValue(_mlsVal); }\n//│   \n//│ };\n//│ struct _mls_LzNil: public _mls_LzList {\n//│   \n//│   constexpr static inline const char *typeName = \"LzNil\";\n//│   constexpr static inline uint32_t typeTag = nextTypeTag();\n//│   virtual void print() const override { std::printf(\"%s\", typeName); }\n//│   virtual void destroy() override {  operator delete (this, std::align_val_t(_mlsAlignment)); }\n//│   static _mlsValue create() { auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_LzNil; _mlsVal->refCount = 1; _mlsVal->tag = typeTag;  return _mlsValue(_mlsVal); }\n//│   \n//│ };\n//│ _mlsValue _mls_j() {\n//│   _mlsValue _mls_retval;\n//│   _mls_retval = _mlsValue::create<_mls_Unit>();\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_entry() {\n//│   _mlsValue _mls_retval;\n//│   _mls_retval = _mlsValue::create<_mls_Unit>();\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_lazy(_mlsValue _mls_x7) {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x6 = _mlsValue::create<_mls_Lazy>(_mls_x7);\n//│   _mls_retval = _mls_x6;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_llist(_mlsValue _mls_x12) {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x11 = _mlsValue::create<_mls_Lambda_f>();\n//│   auto _mls_x13 = _mlsMethodCall<_mls_Callable>(_mls_x11)->_mls_apply1(_mls_x12);\n//│   _mls_retval = _mls_x13;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_entry1() {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x8 = _mls_llist(_mlsValue::fromIntLit(1));\n//│   _mls_retval = _mls_x8;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_entry2() {\n//│   _mlsValue _mls_retval;\n//│   _mls_retval = _mlsValue::create<_mls_Unit>();\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_force(_mlsValue _mls_x9) {\n//│   _mlsValue _mls_retval;\n//│   if (_mlsValue::isValueOf<_mls_Lazy>(_mls_x9)) {\n//│     auto _mls_x10 = _mlsMethodCall<_mls_Lazy>(_mls_x9)->_mls_get();\n//│     _mls_retval = _mls_x10;\n//│   } else {\n//│     throw std::runtime_error(\"match error\");\n//│   }\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_Lambda_f::_mls_apply1(_mlsValue _mls_x1) {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x = _mlsValue::create<_mls_Lambda_lambda>(_mls_x1, _mlsValue(this, _mlsValue::inc_ref_tag{}));\n//│   auto _mls_x2 = _mls_lazy(_mls_x);\n//│   _mls_retval = _mls_x2;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mls_Lambda_lambda::_mls_apply0() {\n//│   _mlsValue _mls_retval;\n//│   auto _mls_x3 = (_mls_lam_arg0 + _mlsValue::fromIntLit(1));\n//│   auto _mls_x4 = _mlsMethodCall<_mls_Callable>(_mls_lam_arg1)->_mls_apply1(_mls_x3);\n//│   auto _mls_x5 = _mlsValue::create<_mls_LzCons>(_mls_lam_arg0, _mls_x4);\n//│   _mls_retval = _mls_x5;\n//│   return _mls_retval;\n//│ }\n//│ _mlsValue _mlsMain() { return _mls_entry1(); }\n//│ int main() { return _mlsLargeStack(_mlsMainWrapper); }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/LlirScratch.mls",
    "content": ":js\n:llir\n\n:global\n:d\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/Method.mls",
    "content": ":js\n:llir\n:cpp\n\n:sllir\nclass A(m) with\n  fun f() = m\nfun main() =\n  let a = A(1)\n  a.A#f()\nmain()\n//│ = 1\n//│ LLIR:\n//│   class A(m) {\n//│     def f() =\n//│       m\n//│   }\n//│   def main() =\n//│     let x = A(1) in\n//│     let x1 = A.f(x) in\n//│     x1\n//│   def entry() =\n//│     let* (x2) = main() in\n//│     x2\n//│   entry = entry\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/Split.mls",
    "content": ":llir\n:todo // Started failing after the addition of lazy spreads (#318)\n\n:intl\nabstract class Iter[T]\nobject Done\ndata class Yield(n)\ndata class Map(f, it)\nfun done(it) = if it is Done then true else false\nfun map(f, it) = Map(f, it)\nfun dec(n) = Yield(n)\nfun next(it) = if it is\n  Yield(n) then\n    if n == 0 then [0, Done]\n    else [n, Yield(n - 1)]\n  Map(f, it) then\n    if next(it) is [n, it] then\n      if done(it) then [f(n), Done]\n      else [f(n), Map(f, it)]\nfun fold(acc, it) =\n  if next(it) is [n, it] then\n    if done(it) then acc else fold(n + acc, it)\nfun map_sum(f, n) = let it = map(f, dec(n)) in fold(0, it)\nmap_sum(x => x, 200)\n//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(tmp:scrut,None)), Arg(None,Lit(IntLit(0))))))\n//│ Stopped due to an error during the Llir generation\n\n:intl\nabstract class Iter[T]\nobject Done\ndata class Yield(n)\ndata class Map(f, it)\nfun done(it) = if it is Done then true else false\nfun map(f, it) = Map(f, it)\nfun dec(n) = Yield(n)\nfun next(it) = if it is\n  Yield(n) then\n    if n == 0 then [0, Done]\n    else [n, Yield(n - 1)]\n  Map(f, it) then\n    if next(it) is [n, it] then\n      if done(it) then [f(n), Done]\n      else [f(n), Map(f, it)]\nfun fold(acc, iter) = if iter is\n  Yield(n) then\n    if n == 0 then acc\n    else fold(n + acc, Yield(n - 1))\n  Map(f, it) then\n    if next(it) is [n, it] then\n      if it is Done then acc else fold(f(n) + acc, Map(f, it))\nfun map_sum(f, n) = let it = map(f, dec(n)) in fold(0, it)\nmap_sum(x => x, 200)\n//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(tmp:scrut,None)), Arg(None,Lit(IntLit(0))))))\n//│ Stopped due to an error during the Llir generation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/Tuple.mls",
    "content": ":js\n:llir\n:cpp\n:todo // Started failing after the addition of lazy spreads (#318)\n\n:intl\n:sllir\n:scpp\nfun mkTup(x, y) = [x, y]\nfun fst(t) = if t is [x, y] then x \nmkTup(1, 2)\n//│ = [1, 2]\n//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref(tmp:runtime,None),Ident(Tuple)),Ident(get)),List(List(Arg(None,Ref(t,None)), Arg(None,Lit(IntLit(0))))))\n//│ Stopped due to an error during the Llir generation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/nofib/NofibPrelude.mls",
    "content": "\n// Alternative from the standard operator\nfun nott(c) = if c then false else true\n\ntype Char = String\n\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\n\n// This should ideally be a declaration.\n// Now it is a built-in class specially handled in the C++ backend,\n// with related logic defined in `mlsprelude.h`.\nabstract class Lazy[out A](init: () -> A) with\n  fun get()\nfun lazy(x) = Lazy(x) \nfun force(x) = if x is Lazy then x.Lazy#get()\n\nfun fromSome(s) = if s is Some(x) then x\n\nabstract class List[out T]: Cons[T] | Nil\ndata class (::) Cons[out T](head: T, tail: List[T]) extends List[T]\nobject Nil extends List\nfun ltList(xs, ys, lt, gt) = if xs is\n  Nil and\n    ys is Nil then false\n    else true\n  x :: xs and ys is\n    Nil then false\n    y :: ys and\n      lt(x, y) then true\n      gt(x, y) then false\n      else ltList(xs, ys, lt, gt)\n\ntype LazyList[out T] = Lazy[LzList[T]]\nabstract class LzList[out T]: LzCons[T] | LzNil\ndata class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T]\nobject LzNil extends LzList\n\nfun ltTup2(t1, t2, lt1, gt1, lt2) = if t1 is [a, b] and t2 is [c, d] and\n  lt1(a, c) then true\n  gt1(a, c) then false\n  else lt2(b, d)\nfun eqTup2(t1, t2) = if t1 is [a, b] and t2 is [c, d] then a == c and b == d\n\nfun compose(f, g) = x => f(g(x))\n\nfun snd(x) = if x is [f, s] then s\nfun fst(x) = if x is [f, s] then f\n\nfun until(p, f, i) = if p(i) then i else until(p, f, f(i))\n\nfun flip(f, x, y) = f(y)(x)\n\nfun power(a, n) = Math.pow(a, n)\n\nfun intDiv(a, b) = globalThis.builtin(\"floor_div\", a, b)\nfun intQuot(a, b) = globalThis.builtin(\"trunc_div\", a, b)\n\nfun intMod(a, b) = globalThis.builtin(\"floor_mod\", a, b)\nfun intRem(a, b) = globalThis.builtin(\"trunc_mod\", a, b)\n\nfun quotRem(a, b) = [intQuot(a, b), intRem(a, b)]\nfun divMod(a, b) = [intDiv(a, b), intMod(a, b)]\n\nfun head(l) = if l is h :: t then h\nfun tail(l) = if l is h :: t then t\n\nfun while_(p, f, x) = if p(x) then while_(p, f, f(x)) else x\n\nfun reverse(l) =\n  fun r(l', l) = if l is x :: xs then r(x :: l', xs) else l'\n  r(Nil, l)\n\nfun map(f, xs) = if xs is\n  x :: xs then f(x) :: map(f, xs)\n  Nil then Nil\n\nfun listLen(ls) =\n  fun l(ls, a) = if ls is\n    Nil then a\n    h :: t then l(t, a + 1)\n  l(ls, 0)\n\nfun listEq(xs, ys) = if\n  xs is Nil and ys is Nil then true\n  xs is hx :: tx and ys is hy :: ty and (hx == hy) then listEq(tx, ty)\n  else false\n\nfun listEqBy(f, a, b) = if a is\n  Nil and b is Nil then true\n  x :: xs and b is y :: ys then f(x, y) and listEqBy(f, xs, ys)\n  else false\n\nfun listNeq(xs, ys) = if\n  xs is Nil and ys is Nil then false\n  xs is hx :: tx and ys is hy :: ty and (hx == hy) then listNeq(tx, ty)\n  else true\n\nfun enumFromTo(a, b) = if a <= b then a :: enumFromTo(a + 1, b) else Nil\n\nfun enumFromThenTo(a, t, b) = if a <= b then a :: enumFromThenTo(t, 2 * t - a, b) else Nil\n\nfun leave(n, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    n <= 0 then ls\n    else leave(n - 1, t)\n\nfun take(n, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    n <= 0 then Nil\n    else h :: take(n - 1, t)\n\nfun splitAt(n, ls) = [take(n, ls), leave(n, ls)]\n\nfun zip(xs, ys) = if xs is\n  x :: xs and ys is y :: ys then [x, y] :: zip(xs, ys)\n  else Nil\n\nfun inList(x, ls) = if ls is\n  h :: t and\n    x === h then true\n    else inList(x, t)\n  Nil then false\n\nfun notElem(x, ls) = nott(inList(x, ls))\n\nfun (+:) append(xs, ys) = if xs is\n  Nil then ys\n  x :: xs then x :: append(xs, ys)\n\nfun concat(ls) = if ls is\n  Nil then Nil\n  x :: xs then append(x, concat(xs))\n\nfun filter(f, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    f(h) then h :: filter(f, t)\n    else filter(f, t)\n\nfun filterCurried(f)(ls) = if ls is\n  Nil then Nil\n  h :: t and\n    f(h) then h :: filter(f, t)\n    else filter(f, t)\n\nfun all(p, ls) = if ls is\n  Nil then true\n  h :: t and\n    p(h) then all(p, t)\n    else false\n\nfun orList(ls) = if ls is\n  Nil then false\n  h :: t and\n    h then true\n    else orList(t)\n\nfun leaveWhile(f, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    f(h) then leaveWhile(f, t)\n    else h :: t\n\nfun foldl(f, a, xs) = if xs is\n  Nil then a\n  h :: t then foldl(f, f(a, h), t)\n\nfun scanl(f, q, ls) = if ls is\n  Nil then q :: Nil\n  x :: xs then q :: scanl(f, f(q, x), xs)\n\nfun scanr(f, q, ls) = if ls is\n  Nil then q :: Nil\n  x :: xs and scanr(f, q, xs) is q :: t then f(x, q) :: q :: t\n\nfun foldr(f, z, xs) = if xs is\n  Nil then z\n  h :: t then f(h, foldr(f, z, t))\n\nfun foldl1(f, ls) = if\n  ls is x :: xs then foldl(f, x, xs)\n\nfun foldr1(f, ls) = if ls is\n  x :: Nil then x\n  x :: xs then f(x, foldr1(f, xs))\n\nfun maximum(xs) = foldl1((x, y) => if x > y then x else y, xs)\n\nfun nubBy(eq, ls) = if ls is\n  Nil then Nil\n  h :: t then h :: nubBy(eq, filter(y => nott(eq(h, y)), t))\n\nfun zipWith(f, xss, yss) = if\n  xss is x :: xs and yss is y :: ys then f(x, y) :: zipWith(f, xs, ys)\n  else Nil\n\nfun deleteBy(eq, x, ys) = if ys is\n  Nil then Nil\n  y :: ys and\n    eq(x, y) then ys\n    else y :: deleteBy(eq, x, ys)\n\nfun unionBy(eq, xs, ys) = append(xs, foldl((acc, y) => deleteBy(eq, y, acc), nubBy(eq, ys), xs))\n\nfun union(xs, ys) = unionBy((x, y) => x == y, xs, ys)\n\nfun atIndex(i, ls) = if ls is\n  h :: t and\n    i == 0 then h\n    else atIndex(i - 1, t)\n\nfun sum(xs) =\n  fun go(xs, a) = if xs is\n    Nil then a\n    h :: t then go(t, a + h)\n  go(xs, 0)\n\nfun null_(ls) = if ls is\n  Nil then true\n  else false\n\nfun replicate(n, x) = if n == 0 then Nil else x :: replicate(n - 1, x)\n\nfun unzip(l) =\n  fun f(l, a, b) = if l is\n    Nil then [reverse(a), reverse(b)]\n    [x, y] :: t then f(t, x :: a,  y :: b)\n  f(l, Nil, Nil)\n\nfun zip3(xs, ys, zs) = if\n  xs is x :: xs and ys is y :: ys and zs is z :: zs then [x, y, z] :: zip3(xs, ys, zs)\n  else Nil\n\nfun transpose(xss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and h is\n      hd :: tl then [hd, tl] :: lscomp(t)\n      else lscomp(t)\n  fun combine(y, h, ys, t) = (y :: h) :: transpose(ys :: t)\n  if xss is\n    Nil then Nil\n    Nil :: xss then transpose(xss)\n    (x :: xs) :: xss and unzip(lscomp(xss)) is [hds, tls] then combine(x, hds, xs, tls)\n\nfun break_(p, ls) = if ls is\n  Nil then [Nil, Nil]\n  x :: xs and\n    p(x) then [Nil, x :: xs]\n    break_(p, xs) is [ys, zs] then [x :: ys, zs]\n\nfun flatMap(f, ls) = if ls is\n  Nil then Nil\n  h :: t then append(f(h), flatMap(f, t))\n\n\n// =====================\n\nfun map_lz(f, ls) = lazy of () =>\n  if force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) then LzCons(f(h), map_lz(f, t))\n\nfun filter_lz(p, ls) = Lazy of () =>\n  if force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) and\n      p(h) then LzCons(h, filter_lz(p, t))\n      else force(filter_lz(p, t))\n\nfun nubBy_lz(eq, ls) = Lazy of () =>\n  if force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) then LzCons(h, nubBy_lz(eq, filter_lz(y => nott(eq(h, y)), t)))\n\nfun nub_lz(ls) = nubBy_lz((x, y) => x == y, ls)\n\nfun take_lz(n, ls) = if\n  n > 0 and force(ls) is\n    LzNil then Nil\n    LzCons(h, t) then h :: take_lz(n - 1, t)\n  else Nil\n\nfun take_lz_lz(n, ls) = lazy of () =>\n  if n > 0 and force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) then LzCons(h, take_lz_lz(n - 1, t))\n  else LzNil\n\nfun leave_lz(n, ls) = if\n  n <= 0 then ls\n  force(ls) is\n    LzNil then lazy of () => LzNil\n    LzCons(h, t) then leave_lz(n - 1, t)\n\nfun splitAt_lz(n, ls) = [take_lz(n, ls), leave_lz(n, ls)]\n\nfun zip_lz_nl(xs, ys) = if\n  force(xs) is LzCons(x, xs) and ys is y :: ys then [x, y] :: zip_lz_nl(xs, ys)\n  else Nil\n\nfun zip_lz_lz(xs, ys) = if\n  force(xs) is LzCons(x, xs) and force(ys) is LzCons(y, ys) then lazy of () => LzCons([x, y], zip_lz_lz(xs, ys))\n  else lazy of () => LzNil\n\nfun zipWith_lz_lz(f, xss, yss) = lazy of () => if\n  force(xss) is LzCons(x, xs) and (force(yss)) is LzCons(y, ys) then LzCons(f(x, y), zipWith_lz_lz(f, xs, ys))\n  else LzNil\n\nfun zipWith_lz_nl(f, xss, yss) = if\n  force(xss) is LzCons(x, xs) and yss is y :: ys then f(x, y) :: zipWith_lz_nl(f, xs, ys)\n  else Nil\n\nfun iterate(f, x) = lazy of () => LzCons(x, iterate(f, f(x)))\n\nfun append_nl_lz(xs, ys) = if xs is\n  Nil then ys\n  h :: t then lazy of () => LzCons(h, append_nl_lz(t, ys))\n\nfun append_lz_lz(xs, ys) = lazy of () => if force(xs) is\n  LzNil then force(ys)\n  LzCons(h, t) then LzCons(h, append_lz_lz(t, ys))\n\nfun replicate_lz(n, x) = if n == 0 then lazy of () => LzNil else lazy of () => LzCons(x, replicate_lz(n - 1, x))\n\nfun enumFrom(a) = lazy of () => LzCons(a, enumFrom(a + 1))\n\nfun head_lz(ls) = if force(ls) is LzCons(h, t) then h\n\nfun repeat(x) = lazy of () => LzCons(x, repeat(x))\n// =====================\n\nfun stringOfInt(x) = globalThis.builtin(\"int2str\", x)\nfun stringOfFloat(x) = globalThis.builtin(\"float2str\", x)\nfun stringConcat(x, y) = globalThis.builtin(\"str_concat\", x, y)\nfun stringListConcat(ls) = if ls is\n  Nil then \"\"\n  h :: t then stringConcat(h, stringListConcat(t))\nfun print(x) = globalThis.builtin(\"println\", x)\nfun abs(x) = globalThis.Math.abs(x)\nfun floatOfInt(x) = globalThis.builtin(\"int2float\", x)\n\n// fun max(a, b) = Math.min(a, b)\n// fun min(a, b) = Math.max(a, b)\n// fun abs(x) = Math.abs(x)\n// fun sqrt(x) = Math.sqrt(x)\n// fun tan(x) = Math.tan(x)\n// fun sin(x) = Math.sin(x)\n// fun cos(x) = Math.cos(x)\n// fun round(x) = Math.round(x)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/nofib/atom.mls",
    "content": ":llir\n:todo // Started failing after the addition of lazy spreads (#318)\n// The errors are nondeterministic, producing useless diffs, so I disabled the whole file for now\n:exit\n====================================================================================================\n\n:import NofibPrelude.mls\n//│ Imported 104 member(s)\n//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1)), Arg(None,Lit(IntLit(0)))))\n//│ Stopped due to an error during the Llir generation\n\ndata class State(position: List[Num], velocity: List[Num])\n\nfun dotPlus(fs, gs) = if\n  fs is Nil then gs\n  gs is Nil then fs\n  fs is f :: fs and gs is g :: gs then (f + g) :: dotPlus(fs, gs)\n\nfun dotMult(fs, gs) = if\n  fs is f :: fs and gs is g :: gs then (f * g) :: dotMult(fs, gs)\n  else Nil\n\nfun scalarMut(c, fs) = if fs is\n  Nil then Nil\n  f :: fs then (c * f) :: scalarMut(c, fs)\n\nfun testforce(k, ss) = lazy of () =>\n  if force(ss) is\n    LzCons(State(pos, vel), atoms) then LzCons(dotMult(scalarMut(-1.0, k), pos), testforce(k, atoms))\n//│ ═══[COMPILATION ERROR] Name not found: member:force\n//│ Stopped due to an error during the Llir generation\n\nfun show(s) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    component :: t then Cons(stringConcat(stringOfFloat(component), \"\\t\"), lscomp(t))\n  if s is State(pos, vel) then\n    stringListConcat of lscomp(pos)\n//│ ═══[COMPILATION ERROR] Name not found: member:stringConcat\n//│ Stopped due to an error during the Llir generation\n\nfun propagate(dt, aforce, state) = if state is State(pos, vel) then\n  State(dotPlus(pos, scalarMut(dt, vel)), dotPlus(vel, scalarMut(dt, aforce)))\n\nfun runExperiment(law, dt, param, init) = lazy of () =>\n  let stream = runExperiment(law, dt, param, init)\n  LzCons(init, zipWith_lz_lz((x, y) => propagate(dt, x, y), law(param, stream), stream))\n//│ ═══[COMPILATION ERROR] Name not found: member:zipWith_lz_lz\n//│ Stopped due to an error during the Llir generation\n\nfun testAtom_nofib(n) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    state :: t then stringConcat(show(state), \"\\n\") :: lscomp(t)\n  stringListConcat of lscomp(take_lz(n, runExperiment(testforce, 0.02, 1.0 :: Nil, State(1.0 :: Nil, 0.0 :: Nil))))\n//│ ═══[COMPILATION ERROR] Name not found: member:show\n//│ Stopped due to an error during the Llir generation\n\ntestAtom_nofib(20)\n//│ ═══[COMPILATION ERROR] Name not found: member:testAtom_nofib\n//│ Stopped due to an error during the Llir generation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/nofib/awards.mls",
    "content": ":llir\n:todo // Started failing after the addition of lazy spreads (#318)\n// The errors are nondeterministic, producing useless diffs, so I disabled the whole file for now\n:exit\n====================================================================================================\n\n:import NofibPrelude.mls\n//│ Imported 104 member(s)\n//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1)), Arg(None,Lit(IntLit(0)))))\n//│ Stopped due to an error during the Llir generation\n\nfun delete_(xs, e) = deleteBy((x, y) => x == y, e, xs)\n//│ ═══[COMPILATION ERROR] Name not found: member:deleteBy\n//│ Stopped due to an error during the Llir generation\n\nfun listDiff(a, ls) = foldl(delete_, a, ls)\n//│ ═══[COMPILATION ERROR] Name not found: member:foldl\n//│ Stopped due to an error during the Llir generation\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun qsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then qpart(le, x, xs, Nil, Nil, r)\n\nfun qpart(le, x, ys, rlt, rge, r) = if ys is\n  Nil then rqsort(le, rlt, x :: rqsort(le, rge, r))\n  y :: ys and\n    le(x, y) then qpart(le, x, ys, rlt, y :: rge, r)\n    else qpart(le, x, ys, y :: rlt, rge, r)\n\nfun rqsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then rqpart(le, x, xs, Nil, Nil, r)\n\nfun rqpart(le, x, yss, rle, rgt, r) = if yss is\n  Nil then qsort(le, rle, x :: qsort(le, rgt, r))\n  y :: ys and\n    le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r)\n    else rqpart(le, x, ys, rle, y :: rgt, r)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun sort(l) = qsort((a, b) => ltTup2(a, b, (a, b) => a < b, (a, b) => a > b, (a, b) => ltList(a, b, (a, b) => a < b, (a, b) => a > b)), l, Nil)\n//│ ═══[COMPILATION ERROR] Name not found: member:ltList\n//│ Stopped due to an error during the Llir generation\n\nfun perms(m, nns) = if\n  nns is Nil then Nil\n  m == 1 then map(x => x :: Nil, nns)\n  nns is n :: ns then map(x => n :: x, perms(m-1, ns)) +: perms(m, ns)\n//│ ═══[COMPILATION ERROR] Name not found: member:map\n//│ Stopped due to an error during the Llir generation\n\nfun atleast(threshold, sumscores) =\n  filter(case { [sum_, p] then sum_ >= threshold }, sumscores)\n//│ ═══[COMPILATION ERROR] Name not found: $runtime\n//│ Stopped due to an error during the Llir generation\n\nfun award(name_threshold, sumscores) = if name_threshold is [name, threshold] then\n  map(ps => [name, ps], sort(atleast(threshold, sumscores)))\n//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(name_threshold)), Arg(None,Lit(IntLit(0)))))\n//│ Stopped due to an error during the Llir generation\n\nfun awards(scores) =\n  let sumscores = map(p => [sum(p), p], perms(3, scores))\n  \n  award([\"Gold\", 70], sumscores) +: award([\"Silver\", 60], sumscores) +: award([\"Bronze\", 50], sumscores)\n//│ ═══[COMPILATION ERROR] Name not found: member:perms\n//│ Stopped due to an error during the Llir generation\n\nfun findawards(scores) = if awards(scores) is\n  Nil then Nil\n  head_ :: tail_ and head_ is [award, [sum_, perm]] then\n    [award, [sum_, perm]] :: findawards(listDiff(scores, perm))\n//│ ═══[COMPILATION ERROR] Name not found: member:awards\n//│ Stopped due to an error during the Llir generation\n\nfun findallawards(competitors) =\n  map(case { [name, scores] then [name, findawards(scores)] }, competitors)\n//│ ═══[COMPILATION ERROR] Name not found: $runtime\n//│ Stopped due to an error during the Llir generation\n\nfun competitors(i) =\n  [\"Simon\", (35 :: 27 :: 40 :: i :: 34 :: 21 :: Nil)] ::\n  [\"Hans\", (23 :: 19 :: 45 :: i :: 17 :: 10 :: 5 :: 8 :: 14 :: Nil)] ::\n  [\"Phil\", (1 :: 18 :: i :: 20 :: 21 :: 19 :: 34 :: 8 :: 16 :: 21 :: Nil)] ::\n  [\"Kevin\", (9 :: 23 :: 17 :: 54 :: i :: 41 :: 9 :: 18 :: 14 :: Nil)] ::\n  Nil\n\nfun testAwards_nofib(n) =\n  map(x => print(findallawards(competitors(intMod(x, 100)))), enumFromTo(1, n))\n//│ ═══[COMPILATION ERROR] Name not found: member:findallawards\n//│ Stopped due to an error during the Llir generation\n\ntestAwards_nofib(100)\n//│ ═══[COMPILATION ERROR] Name not found: member:testAwards_nofib\n//│ Stopped due to an error during the Llir generation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/nofib/constraints.mls",
    "content": ":llir\n:todo // Started failing after the addition of lazy spreads (#318)\n// The errors are nondeterministic, producing useless diffs, so I disabled the whole file for now\n:exit\n====================================================================================================\n\n:import NofibPrelude.mls\n//│ Imported 104 member(s)\n//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1)), Arg(None,Lit(IntLit(0)))))\n//│ Stopped due to an error during the Llir generation\n\n\n// -- Figure 1. CSPs in Haskell.\ndata class Assign(varr: Int, value: Int)\n\ndata class CSP(vars: Int, vals: Int, rel: Int)\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun qsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then qpart(le, x, xs, Nil, Nil, r)\n\nfun qpart(le, x, ls, rlt, rge, r) = if ls is\n  Nil then rqsort(le, rlt, x :: rqsort(le, rge, r))\n  y :: ys and\n    le(x, y) then qpart(le, x, ys, rlt, y :: rge, r)\n    else qpart(le, x, ys, y :: rlt, rge, r)\n\nfun rqsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then rqpart(le, x, xs, Nil, Nil, r)\n\nfun rqpart(le, x, ls, rle, rgt, r) = if ls is\n  Nil then rqsort(le, rle, x :: qsort(le, rgt, r))\n  y :: ys and\n    le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r)\n    else rqpart(le, x, ys, rle, y :: rgt, r)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun level(a) = if a is Assign(v, _) then v\n\nfun value(a) = if a is Assign(_, v) then v\n\nfun maxLevel(ls) = if ls is\n  Nil then 0\n  Assign(v, _) :: t then v\n\nfun complete(csp, s) = if csp is CSP(v, _, _) then maxLevel(s) == v\n\nfun generate(csp) =\n  fun g(vals, var_) =\n    fun lscomp1(ls) = if ls is\n      Nil then Nil\n      val_ :: t1 then\n        fun lscomp2(ls) = if ls is\n          Nil then lscomp1(t1)\n          st :: t2 then (Assign(var_, val_) :: st) :: lscomp2(t2)\n        lscomp2(g(vals, var_ - 1))\n    if var_ == 0 then\n      Nil :: Nil\n    else\n      lscomp1(enumFromTo(1, vals))\n  \n  if csp is CSP(vars, vals, rel) then g(vals, vars)\n//│ ═══[COMPILATION ERROR] Name not found: member:enumFromTo\n//│ Stopped due to an error during the Llir generation\n\n\nfun inconsistencies(csp, as_) = if csp is CSP(vars, vals, rel) then\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    a :: t1 then\n      fun lscomp2(ls) = if ls is\n        Nil then lscomp1(t1)\n        b :: t2 and\n          a > b and not(rel(a, b)) then [level(a), (b)] :: lscomp2(t2)\n          else lscomp2(t2)\n      lscomp2(reverse(as_))\n  \n  lscomp1(as_)\n//│ ═══[COMPILATION ERROR] Name not found: member:not\n//│ Stopped due to an error during the Llir generation\n\nfun consistent(csp)(x) = null_(inconsistencies(csp, x))\n//│ ═══[COMPILATION ERROR] Name not found: member:inconsistencies\n//│ Stopped due to an error during the Llir generation\n\nfun test(csp, ls) = filter(consistent(csp), ls)\n//│ ═══[COMPILATION ERROR] Name not found: member:consistent\n//│ Stopped due to an error during the Llir generation\n\nfun solver(csp) = test(csp, generate(csp))\n//│ ═══[COMPILATION ERROR] Name not found: member:generate\n//│ Stopped due to an error during the Llir generation\n\nfun safe(as1, as2) = if as1 is Assign(i, m) and as2 is Assign(j, n) then not(m == n) and not(abs(i - j) == abs(m - n))\n//│ ═══[COMPILATION ERROR] Name not found: member:not\n//│ Stopped due to an error during the Llir generation\n\nfun queens(n) = CSP(n, n, safe)\n//│ ═══[COMPILATION ERROR] Name not found: member:safe\n//│ Stopped due to an error during the Llir generation\n\n// -- Figure 2.  Trees in Haskell.\ndata class Node[out T](lab: T, children: List[Node[T]])\n\nfun label(n) = if n is Node(l, _) then l\n\nfun mapTree(f, n) = if n is Node(l, c) then Node(f(l), map((x => mapTree(f, x)), c))\n//│ ═══[COMPILATION ERROR] Name not found: member:map\n//│ Stopped due to an error during the Llir generation\n\nfun foldTree(f, n) = if n is Node(l, c) then f(l, map((x => foldTree(f, x)), c))\n//│ ═══[COMPILATION ERROR] Name not found: member:map\n//│ Stopped due to an error during the Llir generation\n\nfun filterTree(p, t) =\n  fun f1(a, cs) = Node(a, filter(x => p(label(x)), cs))\n  foldTree(f1, t)\n//│ ═══[COMPILATION ERROR] Name not found: member:filter\n//│ Stopped due to an error during the Llir generation\n\nfun prune(p, t) = filterTree(x => not(p(x)), t)\n//│ ═══[COMPILATION ERROR] Name not found: member:not\n//│ Stopped due to an error during the Llir generation\n\nfun leaves(t) = if t is\n  Node(leaf, Nil) then leaf :: Nil\n  Node(_, cs) then concat(map(leaves, cs))\n//│ ═══[COMPILATION ERROR] Name not found: member:map\n//│ Stopped due to an error during the Llir generation\n\nfun initTree(f, x) = Node(x, map(y => initTree(f, y), f(x)))\n//│ ═══[COMPILATION ERROR] Name not found: member:map\n//│ Stopped due to an error during the Llir generation\n\n// -- Figure 3.  Simple backtracking solver for CSPs.\nfun mkTree(csp) = if csp is CSP(vars, vals, rel) then\n  fun next(ss) =\n    if maxLevel(ss) < vars then\n      fun lscomp1(ls) = if ls is\n        Nil then Nil\n        j :: t1 then\n          (Assign(maxLevel(ss) + 1, j) :: ss) :: lscomp1(t1)\n      lscomp1(enumFromTo(1, vals))\n    else\n      Nil\n  \n  initTree(next, Nil)\n//│ ═══[COMPILATION ERROR] Name not found: member:enumFromTo\n//│ Stopped due to an error during the Llir generation\n\n\nfun earliestInconsistency(csp, aas) = if csp is CSP(vars, vals, rel) and aas is\n  Nil then None\n  a :: as_ and filter(x => not(rel(a, x)), reverse(as_)) is\n    Nil then None\n    b :: _ then Some([level(a), level(b)])\n//│ ═══[COMPILATION ERROR] Name not found: member:reverse\n//│ Stopped due to an error during the Llir generation\n\nfun labelInconsistencies(csp, t) =\n  fun f2(s) = [s, earliestInconsistency(csp, s)]\n  \n  mapTree(f2, t)\n//│ ═══[COMPILATION ERROR] Name not found: member:earliestInconsistency\n//│ Stopped due to an error during the Llir generation\n\n\nfun btsolver0(csp) =\n  filter of\n    x => complete(csp, x)\n    leaves of\n      mapTree of\n        fst\n        prune of\n          x => not(snd(x) is None)\n          labelInconsistencies(csp, mkTree(csp))\n//│ ═══[COMPILATION ERROR] Name not found: member:snd\n//│ Stopped due to an error during the Llir generation\n\n// -- Figure 6. Conflict-directed solving of CSPs.\nabstract class ConflictSet: Known | Unknown\ndata class Known(vs: List[Int]) extends ConflictSet\nobject Unknown extends ConflictSet\n\nfun knownConflict(c) = if c is\n  Known(a :: as_) then true\n  else false\n\nfun knownSolution(c) = if c is\n  Known(Nil) then true\n  else false\n\nfun checkComplete(csp, s) = if complete(csp, s) then Known(Nil) else Unknown\n\nfun search(labeler, csp) =\n  map of\n    fst\n    filter of\n      x => knownSolution(snd(x))\n      leaves of prune of\n        x => knownConflict(snd(x))\n        labeler(csp, mkTree(csp))\n//│ ═══[COMPILATION ERROR] Name not found: member:mkTree\n//│ Stopped due to an error during the Llir generation\n\nfun bt(csp, t) =\n  fun f3(s) = [s, (if earliestInconsistency(csp, s) is Some([a, b]) then Known(a :: b :: Nil) else checkComplete(csp, s))]\n  \n  mapTree(f3, t)\n//│ ═══[COMPILATION ERROR] Name not found: $runtime\n//│ Stopped due to an error during the Llir generation\n\n// -- Figure 8. Backmarking.\n\nfun emptyTable(csp) = if csp is CSP(vars, vals, rel) then\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    n :: t1 then\n      fun lscomp2(ls) = if ls is\n        Nil then Nil\n        m :: t2 then\n          Unknown :: lscomp2(t2)\n      lscomp2(enumFromTo(1, vals)) :: lscomp1(t1)\n  \n  Nil :: lscomp1(enumFromTo(1, vars))\n//│ ═══[COMPILATION ERROR] Name not found: member:enumFromTo\n//│ Stopped due to an error during the Llir generation\n\n\nfun fillTable(s, csp, tbl) = if s is\n  Nil then tbl\n  Assign(var_, val_) :: as_ and csp is CSP(vars, vals, rel) then\n    fun f4(cs, varval) = if varval is [varr, vall] and\n      cs is Unknown and not(rel(Assign(var_, val_), Assign(varr, vall))) then Known(var_ :: varr :: Nil)\n      else cs\n    \n    fun lscomp1(ls) = if ls is\n      Nil then Nil\n      varrr :: t1 then\n        fun lscomp2(ls) = if ls is\n          Nil then Nil\n          valll :: t2 then [varrr, valll] :: lscomp2(t2)\n        lscomp2(enumFromTo(1, vals)) :: lscomp1(t1)\n    \n    zipWith((x, y) => zipWith(f4, x, y), tbl, lscomp1(enumFromTo(var_ + 1, vars)))\n//│ ═══[COMPILATION ERROR] Name not found: member:not\n//│ Stopped due to an error during the Llir generation\n\n\nfun lookupCache(csp, t) =\n  fun f5(csp, tp) = if tp is\n    [Nil, tbl] then [[Nil, Unknown], tbl]\n    [a :: as_, tbl] then\n      let tableEntry = atIndex(value(a) - 1, head(tbl))\n      let cs = if tableEntry is Unknown then checkComplete(csp, a :: as_) else tableEntry\n      [[a :: as_, cs], tbl]\n  \n  mapTree(x => f5(csp, x), t)\n//│ ═══[COMPILATION ERROR] Name not found: member:head\n//│ Stopped due to an error during the Llir generation\n\n\nfun cacheChecks(csp, tbl, n) = if n is Node(s, cs) then\n  Node([s, tbl], map(x => cacheChecks(csp, fillTable(s, csp, tail(tbl)), x), cs))\n//│ ═══[COMPILATION ERROR] Name not found: member:fillTable\n//│ Stopped due to an error during the Llir generation\n\nfun bm(csp, t) = mapTree(fst, lookupCache(csp, cacheChecks(csp, emptyTable(csp), t)))\n//│ ═══[COMPILATION ERROR] Name not found: member:emptyTable\n//│ Stopped due to an error during the Llir generation\n\n// -- Figure 10. Conflict-directed backjumping.\nfun combine(ls, acc) = if ls is\n  Nil then acc\n  [s, Known(cs)] :: css and\n    notElem(maxLevel(s), cs) then cs\n    else combine(css, union(cs, acc))\n//│ ═══[COMPILATION ERROR] Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref($param0)), Arg(None,Lit(IntLit(0)))))\n//│ Stopped due to an error during the Llir generation\n\nfun bj_(csp, t) =\n  fun f7(tp2, chs) = if tp2 is\n    [a, Known(cs)] then Node([a, Known(cs)], chs)\n    [a, Unknown] and\n      let cs_ = Known(combine(map(label, chs), Nil))\n      knownConflict(cs_) then Node([a, cs_], Nil)\n      else Node([a, cs_], chs)\n  \n  foldTree(f7, t)\n//│ ═══[COMPILATION ERROR] Name not found: $runtime\n//│ Stopped due to an error during the Llir generation\n\n\nfun bj(csp, t) =\n  fun f6(tp2, chs) = if tp2 is\n    [a, Known(cs)] then Node([a, Known(cs)], chs)\n    [a, Unknown] then Node([a, Known(combine(map(label, chs), Nil))], chs)\n  \n  foldTree(f6, t)\n//│ ═══[COMPILATION ERROR] Name not found: $runtime\n//│ Stopped due to an error during the Llir generation\n\n\nfun bjbt(csp, t) = bj(csp, bt(csp, t))\n//│ ═══[COMPILATION ERROR] Name not found: member:bt\n//│ Stopped due to an error during the Llir generation\n\nfun bjbt_(csp, t) = bj_(csp, bt(csp, t))\n//│ ═══[COMPILATION ERROR] Name not found: member:bt\n//│ Stopped due to an error during the Llir generation\n\n// -- Figure 11. Forward checking.\nfun collect(ls) = if ls is\n  Nil then Nil\n  Known(cs) :: css then union(cs, collect(css))\n//│ ═══[COMPILATION ERROR] Name not found: member:union\n//│ Stopped due to an error during the Llir generation\n\nfun domainWipeout(csp, t) = if csp is CSP(vars, vals, rel) then\n  fun f8(tp2) = if tp2 is [[as_, cs], tbl] then\n    let wipedDomains = \n      fun lscomp1(ls) = if ls is\n        Nil then Nil\n        vs :: t1 and\n          all(knownConflict, vs) then vs :: lscomp1(t1)\n          else lscomp1(t1)\n      lscomp1(tbl)\n    let cs_ = if null_(wipedDomains) then cs else Known(collect(head(wipedDomains)))\n    [as_, cs_]\n  \n  mapTree(f8, t)\n//│ ═══[COMPILATION ERROR] Name not found: member:head\n//│ Stopped due to an error during the Llir generation\n\n\nfun fc(csp, t) = domainWipeout(csp, lookupCache(csp, cacheChecks(csp, emptyTable(csp), t)))\n//│ ═══[COMPILATION ERROR] Name not found: member:emptyTable\n//│ Stopped due to an error during the Llir generation\n\nfun try_(n, algorithm) = listLen(search(algorithm, queens(n)))\n//│ ═══[COMPILATION ERROR] Name not found: member:queens\n//│ Stopped due to an error during the Llir generation\n\nfun testConstraints_nofib(n) = map(x => try_(n, x), bt :: bm :: bjbt :: bjbt_ :: fc :: Nil)\n//│ ═══[COMPILATION ERROR] Name not found: member:fc\n//│ Stopped due to an error during the Llir generation\n\nprint(testConstraints_nofib(6))\n//│ ═══[COMPILATION ERROR] Name not found: member:testConstraints_nofib\n//│ Stopped due to an error during the Llir generation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/nofib/scc.mls",
    "content": ":llir\n:todo // Started failing after the addition of lazy spreads (#318)\n\n:import NofibPrelude.mls\n//│ Imported 104 member(s)\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: Label not supported (of class String)\n\n\nfun dfs(r, vsns, xs) = if vsns is [vs, ns] and\n  xs is\n    Nil then [vs, ns]\n    x :: xs and\n      inList(x, vs) then dfs(r, [vs, ns], xs)\n      dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then dfs(r, [vs', (x :: ns') +: ns], xs)\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: Label not supported (of class String)\n\nfun stronglyConnComp(es, vs) =\n  fun swap(a) = if a is [f, s] then [s, f]\n  \n  fun new_range(xys, w) = if xys is\n    Nil then Nil\n    [x, y] :: xys and\n      x == w then y :: new_range(xys, w)\n      else new_range(xys, w)\n  \n  fun span_tree(r, vsns, xs) = if vsns is [vs, ns] and\n    xs is\n      Nil then [vs, ns]\n      x :: xs and\n        inList(x, vs) then span_tree(r, [vs, ns], xs)\n        dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then span_tree(r, [vs', (x :: ns') :: ns], xs)\n  \n  snd of span_tree of\n    x => new_range(map(swap, es), x)\n    [Nil, Nil]\n    snd of dfs of\n      x => new_range(es, x)\n      [Nil, Nil]\n      vs\n//│ ═══[COMPILATION ERROR] Name not found: tmp:runtime\n//│ Stopped due to an error during the Llir generation\n\n\nfun testScc_nofib(d) =\n  let a = 1\n  let b = 2\n  let c = 3\n  let d = 4\n  let f = 5\n  let g = 6\n  let h = 7\n  let vertices = a :: b :: c :: d :: f :: g :: h :: Nil\n  let edges = [b, a] :: [c, b] :: [c, d] :: [c, h] :: [d, c] :: [f, a] :: [f, g] :: [f, h] :: [g, f] :: [h, g] :: Nil\n  \n  stronglyConnComp(edges, vertices)\n//│ ═══[COMPILATION ERROR] Name not found: member:stronglyConnComp\n//│ Stopped due to an error during the Llir generation\n\nprint(testScc_nofib(0))\n//│ ═══[COMPILATION ERROR] Name not found: member:testScc_nofib\n//│ Stopped due to an error during the Llir generation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/llir/nofib/secretary.mls",
    "content": ":llir\n:todo // Started failing after the addition of lazy spreads (#318)\n// The errors are nondeterministic, producing useless diffs, so I disabled the whole file for now\n:exit\n====================================================================================================\n\n:import NofibPrelude.mls\n//│ Imported 104 member(s)\n//│ Error: hkmc2.ErrorReport: Unsupported kind of Call Call(Select(Select(Ref($runtime),Ident(Tuple)),Ident(get)),List(Arg(None,Ref(t1)), Arg(None,Lit(IntLit(0)))))\n//│ Stopped due to an error during the Llir generation\n\n\nfun infRand(m, s) =\n  fun f(x) = lazy(() => LzCons((intMod(x, m) + 1), f(intMod((97 * x + 11), power(2, 7)))))\n  \n  f(s)\n//│ ═══[COMPILATION ERROR] Name not found: member:lazy\n//│ Stopped due to an error during the Llir generation\n\n\nfun simulate(n, m, proc) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    seed :: t then proc(infRand(m, seed)) :: lscomp(t)\n  \n  floatOfInt(listLen(filter(x => x, lscomp(enumFromTo(1, n))))) / floatOfInt(n)\n//│ ═══[COMPILATION ERROR] Name not found: member:infRand\n//│ Stopped due to an error during the Llir generation\n\n\nfun sim(n, k) =\n  fun proc(rs) =\n    let xs = take_lz(100, nub_lz(rs))\n    let best = 100\n    let bestk = maximum(take(k, xs))\n    let afterk = dropWhile(x => x < bestk, drop(k, xs))\n    listEq(best :: Nil, take(1, afterk))\n  \n  simulate(n, 100, proc)\n//│ ═══[COMPILATION ERROR] Name not found: member:take_lz\n//│ Stopped due to an error during the Llir generation\n\n\nfun testSecretary_nofib(n) =\n  fun listcomp(ls) = if ls is\n    Nil then Nil\n    h :: t then sim(n, h) :: listcomp(t)\n  \n  listcomp(enumFromTo(35, 39))\n//│ ═══[COMPILATION ERROR] Name not found: member:sim\n//│ Stopped due to an error during the Llir generation\n\nprint(testSecretary_nofib(50))\n//│ ═══[COMPILATION ERROR] Name not found: member:testSecretary_nofib\n//│ Stopped due to an error during the Llir generation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/meta/BlockDiffTesting.mls",
    "content": ":js\n\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun foo() = bar()\n\nfun bar() = if false then foo() else ()\n\nfoo()\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\n42\n//│ = 42\n\n\n:...\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\nprint of \"Starting...\"\n\nprint of \"Hello, world!\"\n\nprint of \"Done.\"\n\n\n//│ > Starting...\n//│ > Hello, world!\n//│ > Done.\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/meta/CompilerFiction.mls",
    "content": ":js\n\n\n:ge\nsource\n//│ ╔══[COMPILATION ERROR] Module 'source' is virtual (i.e., \"compiler fiction\"); cannot be used directly\n//│ ║  l.5: \tsource\n//│ ╙──     \t^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:ge\njs\n//│ ╔══[COMPILATION ERROR] Module 'js' is virtual (i.e., \"compiler fiction\"); cannot be used directly\n//│ ║  l.13: \tjs\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\n:ge\njs.oops\n//│ ╔══[COMPILATION ERROR] Module 'js' does not contain member 'oops'\n//│ ║  l.21: \tjs.oops\n//│ ╙──      \t  ^^^^^\n//│ ╔══[COMPILATION ERROR] Module 'js' is virtual (i.e., \"compiler fiction\"); cannot be used directly\n//│ ║  l.21: \tjs.oops\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:ge\njs.try_catch\n//│ ╔══[COMPILATION ERROR] Module 'js' is virtual (i.e., \"compiler fiction\"); cannot be used directly\n//│ ║  l.31: \tjs.try_catch\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:re\njs.try_catch()\n//│ ═══[RUNTIME ERROR] TypeError: onError is not a function\n\n:re\njs.try_catch(0)\n//│ ═══[RUNTIME ERROR] TypeError: onError is not a function\n\njs.try_catch(0, id)\n//│ = TypeError: computation is not a function\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/meta/ImportedTest.mls",
    "content": "\n\nfun hello() = \"Hello!\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/meta/ImporterTest.mls",
    "content": ":js\n\n\n:import ImportedTest.mls\n//│ Imported 1 member(s)\n\n\n:sjs\nhello()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ hello()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"Hello!\"\n\n\nfun hello() = \"Hello?\"\n\n:sjs\nhello()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ hello1()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"Hello?\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/meta/LocDebugging.mls",
    "content": ":js\n:loc\n\n\n:loc\n:pt\n:rt\n111 + 222\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpApp loc[1:1-1:10]:\n//│   lhs = IntLit loc[1:1-1:4] of 111\n//│   op = Ident loc[1:5-1:6] of \"+\"\n//│   rhss = Ls of \n//│     IntLit loc[1:7-1:10] of 222\n//│ ——————————————| Resolved tree |—————————————————————————————————————————————————————————————————————\n//│ Blk loc[1:1-1:10]:\n//│   res = App loc[1:1-1:10]:\n//│     lhs = Ref{sym=builtin:+⁰} loc[1:5-1:6] of builtin:+⁰\n//│     rhs = Tup loc[1:1-1:10] of Ls of \n//│       Fld loc[1:1-1:4]:\n//│         term = Lit loc[1:1-1:4] of IntLit loc[1:1-1:4] of 111\n//│       Fld loc[1:7-1:10]:\n//│         term = Lit loc[1:7-1:10] of IntLit loc[1:7-1:10] of 222\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 333\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/ansi.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/ansi.mls\"\nansi.main()\n//│ = \"LE[5;17HESC[7mDemonstration programESC[0mE[5;48HVersion 1.0E[7;17HThis program illustrates a simple approachE[8;17Hto screen-based interactive programs usingE[9;17Hthe Hugs functional programming system.E[11;17HPlease press any key to continue ...E[15;17HPlease enter your name: E[15;41H__________________E[15;41HesttesttestE[18;31HHello esttesttest!E[23;1HI'm waiting...\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/atom.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/atom.mls\"\natom.main()\n//│ = \"1\\t\\n1\\t\\n0.9996\\t\\n0.9988\\t\\n0.9976001600000001\\t\\n0.9960008\\t\\n0.994002399936\\t\\n0.991605599552\\t\\n0.9888111982080257\\t\\n0.9856201546242305\\t\\n0.982033586561152\\t\\n0.978052770436224\\t\\n0.9736791408766714\\t\\n0.9689142902089444\\t\\n0.9637599678848666\\t\\n0.9582180798447053\\t\\n0.95229068781739\\t\\n0.9459800085581369\\t\\n0.9392884130237569\\t\\n0.9322184254859536\\t\\n\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/awards.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/awards.mls\"\nawards.main()\n//│ = [[[\"Simon\", [[\"Gold\", [70, [35,1,34]]],[\"Gold\", [88, [27,40,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]]]]],[[\"Simon\", [[\"Gold\", [71, [35,2,34]]],[\"Gold\", [88, [27,40,21]]]]],[\"Hans\", [[\"Gold\", [70, [23,45,2]]],[\"Bronze\", [50, [19,17,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [54,2,14]]],[\"Gold\", [73, [9,23,41]]]]]],[[\"Simon\", [[\"Gold\", [70, [27,40,3]]],[\"Gold\", [90, [35,34,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [71, [54,3,14]]],[\"Gold\", [73, [9,23,41]]]]]],[[\"Simon\", [[\"Gold\", [71, [27,40,4]]],[\"Gold\", [90, [35,34,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]]]]],[[\"Simon\", [[\"Gold\", [72, [27,40,5]]],[\"Gold\", [90, [35,34,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]]]]],[[\"Simon\", [[\"Gold\", [73, [27,40,6]]],[\"Gold\", [90, [35,34,21]]]]],[\"Hans\", [[\"Gold\", [70, [19,45,6]]],[\"Bronze\", [50, [23,17,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [23,6,41]]],[\"Gold\", [72, [9,54,9]]]]]],[[\"Simon\", [[\"Gold\", [74, [27,40,7]]],[\"Gold\", [90, [35,34,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [9,54,7]]],[\"Gold\", [72, [17,41,14]]],[\"Bronze\", [50, [23,9,18]]]]]],[[\"Simon\", [[\"Gold\", [70, [35,27,8]]],[\"Gold\", [95, [40,34,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,8,17]]],[\"Bronze\", [50, [23,19,8]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [71, [9,54,8]]],[\"Gold\", [72, [17,41,14]]],[\"Bronze\", [50, [23,9,18]]]]]],[[\"Simon\", [[\"Gold\", [70, [27,9,34]]],[\"Gold\", [96, [35,40,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [51, [23,19,9]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Bronze\", [50, [23,9,18]]]]]],[[\"Simon\", [[\"Gold\", [71, [27,10,34]]],[\"Gold\", [96, [35,40,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Bronze\", [51, [23,10,18]]]]]],[[\"Simon\", [[\"Gold\", [72, [27,11,34]]],[\"Gold\", [96, [35,40,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,11,14]]],[\"Bronze\", [50, [23,17,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [11,41,18]]],[\"Gold\", [72, [9,54,9]]],[\"Bronze\", [54, [23,17,14]]]]]],[[\"Simon\", [[\"Gold\", [73, [27,12,34]]],[\"Gold\", [96, [35,40,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [17,12,41]]],[\"Gold\", [72, [9,54,9]]],[\"Bronze\", [55, [23,18,14]]]]]],[[\"Simon\", [[\"Gold\", [74, [27,13,34]]],[\"Gold\", [96, [35,40,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [50, [23,13,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [71, [17,13,41]]],[\"Gold\", [72, [9,54,9]]],[\"Bronze\", [55, [23,18,14]]]]]],[[\"Simon\", [[\"Gold\", [70, [35,14,21]]],[\"Gold\", [101, [27,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [51, [23,14,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,14,41]]],[\"Bronze\", [55, [23,18,14]]]]]],[[\"Simon\", [[\"Gold\", [70, [15,34,21]]],[\"Gold\", [102, [35,27,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,15,10]]],[\"Bronze\", [50, [19,17,14]]]]],[\"Phil\", [[\"Gold\", [70, [15,21,34]]],[\"Silver\", [60, [20,19,21]]]]],[\"Kevin\", [[\"Gold\", [70, [15,41,14]]],[\"Gold\", [72, [9,54,9]]],[\"Bronze\", [58, [23,17,18]]]]]],[[\"Simon\", [[\"Gold\", [71, [16,34,21]]],[\"Gold\", [102, [35,27,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [16,20,34]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [71, [16,41,14]]],[\"Gold\", [72, [9,54,9]]],[\"Bronze\", [58, [23,17,18]]]]]],[[\"Simon\", [[\"Gold\", [72, [17,34,21]]],[\"Gold\", [102, [35,27,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [50, [19,17,14]]]]],[\"Phil\", [[\"Gold\", [70, [17,19,34]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Bronze\", [58, [23,17,18]]]]]],[[\"Simon\", [[\"Gold\", [73, [18,34,21]]],[\"Gold\", [102, [35,27,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [60, [23,19,18]]]]],[\"Phil\", [[\"Gold\", [70, [18,18,34]]],[\"Silver\", [60, [20,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Bronze\", [59, [23,18,18]]]]]],[[\"Simon\", [[\"Gold\", [74, [19,34,21]]],[\"Gold\", [102, [35,27,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [61, [23,19,19]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Silver\", [60, [23,19,18]]]]]],[[\"Simon\", [[\"Gold\", [75, [20,34,21]]],[\"Gold\", [102, [35,27,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [62, [23,19,20]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [9,20,41]]],[\"Gold\", [77, [54,9,14]]],[\"Bronze\", [58, [23,17,18]]]]]],[[\"Simon\", [[\"Gold\", [76, [21,34,21]]],[\"Gold\", [102, [35,27,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [63, [23,19,21]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [71, [9,21,41]]],[\"Gold\", [77, [54,9,14]]],[\"Bronze\", [58, [23,17,18]]]]]],[[\"Simon\", [[\"Gold\", [70, [27,22,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [64, [23,19,22]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,22,41]]],[\"Gold\", [77, [54,9,14]]],[\"Bronze\", [58, [23,17,18]]]]]],[[\"Simon\", [[\"Gold\", [71, [27,23,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [60, [23,23,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]],[\"Bronze\", [50, [23,19,8]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Silver\", [64, [23,23,18]]]]]],[[\"Simon\", [[\"Gold\", [72, [27,24,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [61, [23,24,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]],[\"Bronze\", [51, [24,19,8]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Silver\", [65, [23,24,18]]]]]],[[\"Simon\", [[\"Gold\", [73, [27,25,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [62, [23,25,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]],[\"Bronze\", [52, [25,19,8]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Silver\", [66, [23,25,18]]]]]],[[\"Simon\", [[\"Gold\", [74, [27,26,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [63, [23,26,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]],[\"Bronze\", [53, [26,19,8]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Silver\", [67, [23,26,18]]]]]],[[\"Simon\", [[\"Gold\", [75, [27,27,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Silver\", [60, [19,27,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]],[\"Bronze\", [54, [27,19,8]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Silver\", [68, [23,27,18]]]]]],[[\"Simon\", [[\"Gold\", [76, [27,28,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [23,19,28]]],[\"Gold\", [70, [45,17,8]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [70, [28,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Silver\", [69, [23,28,18]]]]]],[[\"Simon\", [[\"Gold\", [77, [27,29,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [71, [23,19,29]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [71, [29,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [23,29,18]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]]]]],[[\"Simon\", [[\"Gold\", [78, [27,30,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [23,30,17]]],[\"Gold\", [72, [19,45,8]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [70, [30,19,21]]]]],[\"Kevin\", [[\"Gold\", [70, [23,17,30]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [73, [41,18,14]]]]]],[[\"Simon\", [[\"Gold\", [79, [27,31,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [73, [23,19,31]]]]],[\"Phil\", [[\"Gold\", [70, [18,31,21]]],[\"Gold\", [70, [20,34,16]]]]],[\"Kevin\", [[\"Gold\", [71, [23,17,31]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [73, [41,18,14]]]]]],[[\"Simon\", [[\"Gold\", [80, [27,32,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [74, [23,19,32]]]]],[\"Phil\", [[\"Gold\", [70, [18,32,20]]],[\"Gold\", [71, [21,34,16]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [73, [23,32,18]]]]]],[[\"Simon\", [[\"Gold\", [81, [27,33,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [23,33,14]]],[\"Gold\", [70, [45,17,8]]]]],[\"Phil\", [[\"Gold\", [70, [18,33,19]]],[\"Gold\", [70, [20,34,16]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [70, [23,33,14]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [76, [17,41,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [109, [35,40,34]]]]],[\"Hans\", [[\"Gold\", [70, [19,34,17]]],[\"Gold\", [73, [23,45,5]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [71, [18,19,34]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [71, [23,34,14]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [76, [17,41,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [110, [35,40,35]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [72, [23,35,14]]]]],[\"Phil\", [[\"Gold\", [70, [1,35,34]]],[\"Silver\", [60, [18,21,21]]],[\"Bronze\", [55, [20,19,16]]]]],[\"Kevin\", [[\"Gold\", [70, [17,35,18]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [78, [23,41,14]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [111, [35,40,36]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [73, [23,36,14]]]]],[\"Phil\", [[\"Gold\", [70, [18,36,16]]],[\"Gold\", [73, [20,19,34]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [71, [17,36,18]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [78, [23,41,14]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [112, [35,40,37]]]]],[\"Hans\", [[\"Gold\", [70, [19,37,14]]],[\"Gold\", [70, [45,17,8]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [74, [18,37,19]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,37,18]]],[\"Gold\", [78, [23,41,14]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [113, [35,40,38]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [71, [19,38,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [75, [18,38,19]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [70, [9,23,38]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [81, [54,9,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [114, [35,40,39]]]]],[\"Hans\", [[\"Gold\", [70, [23,39,8]]],[\"Gold\", [72, [45,17,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [76, [18,39,19]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [70, [17,39,14]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [82, [23,41,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [115, [35,40,40]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [73, [19,40,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [77, [18,40,19]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [71, [17,40,14]]],[\"Gold\", [72, [9,54,9]]],[\"Gold\", [82, [23,41,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [116, [35,40,41]]]]],[\"Hans\", [[\"Gold\", [70, [19,41,10]]],[\"Gold\", [70, [45,17,8]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [70, [41,8,21]]],[\"Bronze\", [58, [18,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [82, [23,41,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [117, [35,40,42]]]]],[\"Hans\", [[\"Gold\", [70, [23,42,5]]],[\"Gold\", [70, [45,17,8]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [71, [42,8,21]]],[\"Bronze\", [58, [18,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [83, [23,42,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [118, [35,40,43]]]]],[\"Hans\", [[\"Gold\", [70, [19,43,8]]],[\"Gold\", [72, [45,17,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [70, [43,19,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [70, [9,43,18]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [86, [23,54,9]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [119, [35,40,44]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [72, [23,44,5]]]]],[\"Phil\", [[\"Gold\", [70, [18,44,8]]],[\"Gold\", [70, [20,34,16]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [70, [9,17,44]]],[\"Gold\", [73, [23,41,9]]],[\"Gold\", [86, [54,18,14]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [120, [35,40,45]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [73, [23,45,5]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [71, [18,45,8]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [71, [9,17,45]]],[\"Gold\", [73, [23,41,9]]],[\"Gold\", [86, [54,18,14]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [121, [35,40,46]]]]],[\"Hans\", [[\"Gold\", [70, [19,46,5]]],[\"Gold\", [70, [45,17,8]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [72, [18,46,8]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,17,46]]],[\"Gold\", [73, [23,41,9]]],[\"Gold\", [86, [54,18,14]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [122, [35,40,47]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [71, [19,47,5]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [73, [18,47,8]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [70, [9,47,14]]],[\"Gold\", [73, [23,41,9]]],[\"Gold\", [89, [17,54,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [123, [35,40,48]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [72, [19,48,5]]]]],[\"Phil\", [[\"Gold\", [70, [1,48,21]]],[\"Gold\", [70, [20,34,16]]],[\"Bronze\", [58, [18,19,21]]]]],[\"Kevin\", [[\"Gold\", [71, [9,48,14]]],[\"Gold\", [73, [23,41,9]]],[\"Gold\", [89, [17,54,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [124, [35,40,49]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [73, [19,49,5]]]]],[\"Phil\", [[\"Gold\", [70, [1,49,20]]],[\"Gold\", [71, [18,19,34]]],[\"Bronze\", [50, [21,8,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,49,14]]],[\"Gold\", [73, [23,41,9]]],[\"Gold\", [89, [17,54,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [125, [35,40,50]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [74, [19,50,5]]]]],[\"Phil\", [[\"Gold\", [70, [1,50,19]]],[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [91, [23,50,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [126, [35,40,51]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [70, [51,5,14]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [1,18,51]]],[\"Gold\", [70, [20,34,16]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [92, [23,51,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [127, [35,40,52]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [71, [52,5,14]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [71, [1,18,52]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [70, [9,52,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [95, [23,54,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [128, [35,40,53]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [72, [53,5,14]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [1,53,16]]],[\"Gold\", [71, [18,19,34]]],[\"Silver\", [62, [20,21,21]]]]],[\"Kevin\", [[\"Gold\", [71, [9,53,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [95, [23,54,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [129, [35,40,54]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [73, [54,5,14]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [73, [1,18,54]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [95, [23,54,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [130, [35,40,55]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [70, [55,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [74, [1,18,55]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [96, [23,55,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [131, [35,40,56]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [71, [56,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [75, [1,18,56]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [97, [23,56,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [132, [35,40,57]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [72, [57,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [76, [1,18,57]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [98, [23,57,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [133, [35,40,58]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [73, [58,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [77, [1,18,58]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [99, [23,58,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [134, [35,40,59]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [74, [59,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [78, [1,18,59]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [100, [23,59,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [135, [35,40,60]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [75, [60,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [79, [1,18,60]]],[\"Silver\", [61, [21,19,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [101, [23,60,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [136, [35,40,61]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [76, [61,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [1,61,8]]],[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [102, [23,61,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [137, [35,40,62]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [77, [62,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [71, [1,62,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [103, [23,62,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [138, [35,40,63]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [78, [63,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [72, [1,63,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [104, [23,63,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [139, [35,40,64]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [79, [64,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [73, [1,64,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [105, [23,64,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [140, [35,40,65]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [80, [65,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [74, [1,65,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [106, [23,65,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [141, [35,40,66]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [81, [66,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [75, [1,66,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [107, [23,66,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [142, [35,40,67]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [82, [67,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [76, [1,67,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [108, [23,67,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [143, [35,40,68]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [83, [68,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [77, [1,68,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [109, [23,68,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [144, [35,40,69]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [84, [69,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [78, [1,69,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [110, [23,69,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [145, [35,40,70]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [85, [70,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [79, [1,70,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [111, [23,70,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [146, [35,40,71]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [86, [71,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [80, [1,71,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [112, [23,71,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [147, [35,40,72]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [87, [72,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [81, [1,72,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [113, [23,72,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [148, [35,40,73]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [88, [73,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [82, [1,73,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [114, [23,73,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [149, [35,40,74]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [89, [74,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [83, [1,74,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [115, [23,74,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [150, [35,40,75]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [90, [75,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [84, [1,75,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [116, [23,75,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [151, [35,40,76]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [91, [76,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [85, [1,76,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [117, [23,76,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [152, [35,40,77]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [92, [77,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [86, [1,77,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [118, [23,77,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [153, [35,40,78]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [93, [78,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [87, [1,78,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [119, [23,78,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [154, [35,40,79]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [94, [79,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [88, [1,79,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [120, [23,79,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [155, [35,40,80]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [95, [80,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [89, [1,80,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [121, [23,80,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [156, [35,40,81]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [96, [81,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [90, [1,81,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [122, [23,81,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [157, [35,40,82]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [97, [82,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [91, [1,82,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [123, [23,82,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [158, [35,40,83]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [98, [83,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [92, [1,83,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [124, [23,83,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [159, [35,40,84]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [99, [84,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [93, [1,84,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [125, [23,84,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [160, [35,40,85]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [100, [85,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [94, [1,85,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [126, [23,85,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [161, [35,40,86]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [101, [86,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [95, [1,86,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [127, [23,86,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [162, [35,40,87]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [102, [87,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [96, [1,87,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [128, [23,87,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [163, [35,40,88]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [103, [88,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [97, [1,88,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [129, [23,88,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [164, [35,40,89]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [104, [89,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [98, [1,89,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [130, [23,89,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [165, [35,40,90]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [105, [90,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [99, [1,90,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [131, [23,90,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [166, [35,40,91]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [106, [91,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [100, [1,91,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [132, [23,91,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [167, [35,40,92]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [107, [92,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [101, [1,92,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [133, [23,92,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [168, [35,40,93]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [108, [93,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [102, [1,93,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [134, [23,93,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [169, [35,40,94]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [109, [94,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [103, [1,94,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [135, [23,94,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [170, [35,40,95]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [110, [95,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [104, [1,95,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [136, [23,95,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [171, [35,40,96]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [111, [96,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [105, [1,96,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [137, [23,96,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [172, [35,40,97]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [112, [97,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [106, [1,97,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [138, [23,97,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [173, [35,40,98]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [113, [98,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [107, [1,98,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [139, [23,98,18]]]]]],[[\"Simon\", [[\"Gold\", [82, [27,34,21]]],[\"Gold\", [174, [35,40,99]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Gold\", [114, [99,10,5]]],[\"Bronze\", [56, [23,19,14]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Gold\", [108, [1,99,8]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [72, [9,54,9]]],[\"Gold\", [72, [17,41,14]]],[\"Gold\", [140, [23,99,18]]]]]],[[\"Simon\", [[\"Gold\", [74, [40,0,34]]],[\"Gold\", [83, [35,27,21]]]]],[\"Hans\", [[\"Gold\", [70, [45,17,8]]],[\"Bronze\", [52, [23,19,10]]]]],[\"Phil\", [[\"Gold\", [70, [20,34,16]]],[\"Silver\", [60, [18,21,21]]]]],[\"Kevin\", [[\"Gold\", [71, [17,54,0]]],[\"Gold\", [73, [9,23,41]]]]]]]\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/banner.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/banner.mls\"\nprint(banner.main())\n//│ > \n//│ > IIIII   SSSS         TTTTT  H   H  IIIII   SSSS         N   N   OOO   TTTTT           A            GGGG  RRRR   EEEEE    A    TTTTT         BBBB     A    N   N  N   N  EEEEE  RRRR    ??? \n//│ >   I    S               T    H   H    I    S             NN  N  O   O    T            A A          G      R   R  E       A A     T           B   B   A A   NN  N  NN  N  E      R   R  ?   ?\n//│ >   I     SSS            T    HHHHH    I     SSS          N N N  O   O    T           AAAAA         G  GG  RRRR   EEEEE  AAAAA    T           BBBB   AAAAA  N N N  N N N  EEEEE  RRRR      ? \n//│ >   I        S           T    H   H    I        S         N  NN  O   O    T           A   A         G   G  R  R   E      A   A    T           B   B  A   A  N  NN  N  NN  E      R  R     ?  \n//│ > IIIII  SSSS            T    H   H  IIIII  SSSS          N   N   OOO     T           A   A          GGG   R   R  EEEEE  A   A    T           BBBB   A   A  N   N  N   N  EEEEE  R   R    .  \n//│ > \n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/boyer.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/boyer.mls\"\nboyer.main()\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/boyer2.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/boyer2.mls\"\nboyer2.main()\n//│ = \"The term is a tautology\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/calendar.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/calendar.mls\"\nprint(calendar.main())\n//│ >                                    1993                                    \n//│ >                                                                            \n//│ >          January                 February                   March          \n//│ >    Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa  \n//│ >                    1  2         1  2  3  4  5  6         1  2  3  4  5  6  \n//│ >     3  4  5  6  7  8  9      7  8  9 10 11 12 13      7  8  9 10 11 12 13  \n//│ >    10 11 12 13 14 15 16     14 15 16 17 18 19 20     14 15 16 17 18 19 20  \n//│ >    17 18 19 20 21 22 23     21 22 23 24 25 26 27     21 22 23 24 25 26 27  \n//│ >    24 25 26 27 28 29 30     28                       28 29 30 31           \n//│ >    31                                                                      \n//│ >                                                                            \n//│ >           April                     May                     June           \n//│ >    Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa  \n//│ >                 1  2  3                        1            1  2  3  4  5  \n//│ >     4  5  6  7  8  9 10      2  3  4  5  6  7  8      6  7  8  9 10 11 12  \n//│ >    11 12 13 14 15 16 17      9 10 11 12 13 14 15     13 14 15 16 17 18 19  \n//│ >    18 19 20 21 22 23 24     16 17 18 19 20 21 22     20 21 22 23 24 25 26  \n//│ >    25 26 27 28 29 30        23 24 25 26 27 28 29     27 28 29 30           \n//│ >                             30 31                                          \n//│ >                                                                            \n//│ >           July                    August                  September        \n//│ >    Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa  \n//│ >                 1  2  3      1  2  3  4  5  6  7               1  2  3  4  \n//│ >     4  5  6  7  8  9 10      8  9 10 11 12 13 14      5  6  7  8  9 10 11  \n//│ >    11 12 13 14 15 16 17     15 16 17 18 19 20 21     12 13 14 15 16 17 18  \n//│ >    18 19 20 21 22 23 24     22 23 24 25 26 27 28     19 20 21 22 23 24 25  \n//│ >    25 26 27 28 29 30 31     29 30 31                 26 27 28 29 30        \n//│ >                                                                            \n//│ >                                                                            \n//│ >          October                 November                 December         \n//│ >    Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa     Su Mo Tu We Th Fr Sa  \n//│ >                    1  2         1  2  3  4  5  6               1  2  3  4  \n//│ >     3  4  5  6  7  8  9      7  8  9 10 11 12 13      5  6  7  8  9 10 11  \n//│ >    10 11 12 13 14 15 16     14 15 16 17 18 19 20     12 13 14 15 16 17 18  \n//│ >    17 18 19 20 21 22 23     21 22 23 24 25 26 27     19 20 21 22 23 24 25  \n//│ >    24 25 26 27 28 29 30     28 29 30                 26 27 28 29 30 31     \n//│ >    31                                                                      \n//│ >                                                                            \n//│ > \n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/cichelli.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/cichelli.mls\"\ncichelli.main()\n//│ = \"YesIts(113994, [[\\\"w\\\", 16],[\\\"r\\\", 17],[\\\"o\\\", 11],[\\\"m\\\", 17],[\\\"l\\\", 11],[\\\"x\\\", 2],[\\\"n\\\", 11],[\\\"i\\\", 4],[\\\"f\\\", 10],[\\\"h\\\", 3],[\\\"g\\\", 0],[\\\"t\\\", 5],[\\\"d\\\", 0],[\\\"a\\\", 0],[\\\"s\\\", 2],[\\\"c\\\", 0],[\\\"e\\\", 1]])\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/circsim.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/circsim.mls\"\ncircsim.main()\n//│ = \"[[F,F,F,F,F,F,F,F],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T],[T,T,T,T,T,T,T,T]]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/clausify.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/clausify.mls\"\nclausify.main()\n//│ = \"a <=\\na <=\\na <=\\na <=\\na <=\\na <=\\na <=\\na <=\\na <=\\na <=\\n\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/constraints.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/constraints.mls\"\nconstraints.main()\n//│ = \"[4,4,4,4,4]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/cryptarithm1.mls",
    "content": ":js\n\n:re\nimport \"../../mlscript-compile/nofib/cryptarithm1.mls\"\ncryptarithm1.main()\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/cryptarithm2.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/cryptarithm2.mls\"\ncryptarithm2.main()\n//│ = \"[\\\"W\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"3\\\",\\\"\\\\n\\\",\\\"H\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"9\\\",\\\"\\\\n\\\",\\\"N\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"8\\\",\\\"\\\\n\\\",\\\"I\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"4\\\",\\\"\\\\n\\\",\\\"L\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"7\\\",\\\"\\\\n\\\",\\\"R\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"2\\\",\\\"\\\\n\\\",\\\"V\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"6\\\",\\\"\\\\n\\\",\\\"T\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"1\\\",\\\"\\\\n\\\",\\\"E\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"0\\\",\\\"\\\\n\\\",\\\"Y\\\",\\\" \\\",\\\"=\\\",\\\">\\\",\\\" \\\",\\\"5\\\",\\\"\\\\n\\\"]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/cse.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/cse.mls\"\ncse.main()\n//│ = \"[[[[0, \\\"a\\\", []]]],[[[0, \\\"a\\\", []]],[[0, \\\"+\\\", [2,2]],[2, \\\"a\\\", []]]],[[[0, \\\"a\\\", []]],[[0, \\\"+\\\", [2,2]],[2, \\\"a\\\", []]],[[0, \\\"+\\\", [4,4]],[4, \\\"*\\\", [5,6]],[5, \\\"a\\\", []],[6, \\\"b\\\", []]]],[[[0, \\\"a\\\", []]],[[0, \\\"+\\\", [2,2]],[2, \\\"a\\\", []]],[[0, \\\"+\\\", [4,4]],[4, \\\"*\\\", [5,6]],[5, \\\"a\\\", []],[6, \\\"b\\\", []]],[[0, \\\"+\\\", [1,6]],[1, \\\"*\\\", [6,5]],[5, \\\"c\\\", []],[6, \\\"+\\\", [7,8]],[7, \\\"a\\\", []],[8, \\\"b\\\", []]]],[[[0, \\\"a\\\", []]],[[0, \\\"+\\\", [2,2]],[2, \\\"a\\\", []]],[[0, \\\"+\\\", [4,4]],[4, \\\"*\\\", [5,6]],[5, \\\"a\\\", []],[6, \\\"b\\\", []]],[[0, \\\"+\\\", [1,6]],[1, \\\"*\\\", [6,5]],[5, \\\"c\\\", []],[6, \\\"+\\\", [7,8]],[7, \\\"a\\\", []],[8, \\\"b\\\", []]],[[0, \\\"X\\\", [21,20,19,18,17]],[17, \\\"+\\\", [18,25]],[18, \\\"+\\\", [19,24]],[19, \\\"+\\\", [20,23]],[20, \\\"+\\\", [21,22]],[21, \\\"0\\\", []],[22, \\\"a\\\", []],[23, \\\"b\\\", []],[24, \\\"c\\\", []],[25, \\\"d\\\", []]]],[]]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/eliza.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/eliza.mls\"\neliza.main()\n//│ = \"[\\\"I'm not sure I understand you fully.\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\nYou seem quite positive.\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\nYou seem quite positive.\\\\n\\\\nHow long have you been not?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\nYou seem quite positive.\\\\n\\\\nHow long have you been not?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\nYou seem quite positive.\\\\n\\\\nHow long have you been not?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\nYou seem quite positive.\\\\n\\\\nHow long have you been not?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\nYou seem quite positive.\\\\n\\\\nHow long have you been not?\\\\n\\\\n\\\",\\\"I'm not sure I understand you fully.\\\\n\\\\nWe were discussing you --not me.\\\\n\\\\nWhy do you ask?\\\\n\\\\nOh, do?\\\\n\\\\nWhat does that suggest to you?\\\\n\\\\nDo computers worry you?\\\\n\\\\nYou're not really talking about me, are you?\\\\n\\\\nI see.\\\\n\\\\nCan you elaborate on that?\\\\n\\\\nWhy do you ask?\\\\n\\\\nDid you come to me because you are asking questions, not me?\\\\n\\\\nAre you saying no just to be negative?\\\\n\\\\nYou seem quite positive.\\\\n\\\\nHow long have you been not?\\\\n\\\\n\\\",\\\"\\\"]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/fish.mls",
    "content": ":js\n\n// This is caused by the implementation of `+:` in `NofibPrelude.mls`. Replacing\n// `+:` with a non-recursive implementation can fix the stack overflow error.\n// However, it will cause the file size to increase by ~390 KiB.\n:re\nimport \"../../mlscript-compile/nofib/fish.mls\"\nfish.main()\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/gcd.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/gcd.mls\"\ngcd.main()\n//│ = 5021\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/input/1500.1",
    "content": "11596 5940 7041\n3954 16850 19194\n10798 3867 10582\n22284 4 1625\n21592 5 24168\n25739 9819 3262\n12274 19602 15970\n20213 8 9093\n13180 15097 26473\n21207 15290 21927\n342 21747 5726\n9156 12 7172\n1504 5693 22552\n9331 1734 25347\n24559 20698 25218\n25680 25424 25613\n356 17 17\n10111 24559 4698\n12539 12734 24006\n865 73 3185\n9328 2912 6016\n12214 18883 16299\n17439 25687 15482\n20301 24 12760\n11924 25 23900\n17711 7354 11615\n2862 21974 21523\n28 20161 14961\n11016 8632 11501\n13515 1075 17678\n2762 31 11903\n14949 4157 18133\n14620 25164 10820\n16951 4023 1530\n11790 35 22374\n14412 12089 26644\n10965 20032 12133\n22326 20603 13547\n14386 26591 23567\n17933 3245 10384\n2345 25201 25892\n4290 42 5554\n14342 5403 9475\n10260 4521 18977\n25744 45 19352\n16483 12678 7803\n2415 18458 13727\n9949 4632 21152\n11601 23964 7588\n1818 10842 4415\n10294 17518 6662\n16220 2188 601\n23645 53 19437\n3750 54 4438\n8594 26951 17058\n56 7960 24584\n26620 26417 22684\n13719 23719 26922\n15771 59 9699\n5756 1185 20876\n12536 24949 18189\n23630 62 26990\n3535 13082 6650\n2992 15784 1989\n20916 5452 10476\n16338 10122 14194\n627 24819 6507\n22585 21604 9209\n23512 69 12264\n3286 17142 13742\n9759 71 16514\n8005 15480 17672\n11364 3041 16609\n10543 74 847\n25294 75 14286\n23092 76 8876\n1269 744 9805\n8998 25043 21278\n25791 79 15071\n205 25600 8248\n6324 81 7833\n2722 8127 7538\n7926 13043 22099\n15396 6889 18172\n22408 85 4288\n11323 15774 15062\n23746 15943 26770\n26920 1488 22240\n19412 26921 1233\n12314 16543 8079\n12051 11307 13347\n21801 92 25780\n16853 6056 10576\n17462 94 9539\n10730 5754 24407\n22645 8936 17213\n11785 26884 21153\n6490 98 25266\n7974 17502 22182\n16644 7673 2721\n101 13960 13168\n4507 25843 8563\n4295 20210 5610\n25328 1360 17925\n18252 25633 26684\n9023 24826 106\n6198 4126 10278\n13921 108 20313\n14741 4648 2600\n18715 110 15811\n21050 6079 16175\n3160 7629 13376\n2713 12892 23556\n9642 20383 19226\n21387 3347 13174\n23593 116 23241\n24973 17437 12920\n25131 19942 8118\n8370 25783 3543\n17456 15813 8072\n1948 24801 7332\n4122 12167 20231\n123 123 123\n11996 124 15089\n5112 285 18080\n19942 24523 23011\n7218 4271 24746\n1152 24869 18253\n20249 129 25081\n18807 21186 23386\n494 131 9862\n25716 921 5644\n20904 584 26837\n10419 7635 12739\n15098 362 17943\n4368 24717 23037\n4545 5985 14073\n9687 26911 22127\n4110 10947 6270\n12377 321 6457\n21237 8701 1021\n19059 142 8115\n10682 9242 26226\n18485 11045 10653\n3652 25500 6700\n7418 20895 21394\n3283 21998 7027\n17897 22705 2857\n11077 19645 1085\n26990 635 7203\n18527 12255 20783\n16608 4605 10856\n8017 153 15332\n17858 3871 25810\n25643 16230 26790\n19849 156 4076\n24296 25376 704\n19030 26219 19027\n106 4898 19079\n6909 14728 5128\n25564 161 18817\n6143 162 17106\n14070 23171 18206\n5708 19777 16020\n23509 2816 592\n6966 166 26478\n18247 9682 22407\n5568 168 21088\n3545 169 26276\n23466 16247 10399\n18046 10507 10414\n20220 18457 10689\n7192 18600 14557\n12059 4499 10310\n23106 6055 15138\n4544 7357 1696\n23849 10652 24780\n15327 10071 19543\n10107 22595 10694\n5457 5273 25457\n1613 181 15101\n16819 182 24011\n10719 22655 663\n24613 10864 19837\n7673 17844 20564\n2586 6551 18634\n18854 13507 12286\n5636 188 15793\n21128 17904 10272\n26691 7358 190\n18818 24010 21954\n168 5437 16957\n3217 7036 20945\n25983 18234 21642\n23819 195 542\n796 19164 913\n197 6368 3877\n16494 16867 23726\n23538 4530 5234\n2856 22120 21709\n25441 13193 7369\n17903 202 12226\n16219 1323 21982\n9017 13937 569\n10216 3245 23957\n13118 3763 26030\n17962 25951 16335\n17080 208 10461\n21324 23308 15500\n23639 5618 9015\n11315 3470 26222\n12297 212 21225\n1469 7429 6037\n21203 12027 18619\n20002 25703 26839\n7541 216 22269\n12804 26820 556\n5970 10343 24391\n5150 219 19339\n4876 20908 4873\n11648 5413 21277\n14275 222 3027\n1970 15631 24698\n26448 8984 24869\n23932 225 225\n15063 22615 3887\n20166 13619 26803\n23132 17076 18740\n21133 24712 7613\n14787 230 4206\n13898 20610 12738\n26064 14256 14320\n5980 25817 22500\n3375 5591 1951\n23142 16654 11091\n15289 8852 10041\n5061 6381 1808\n15022 14363 6430\n18690 4530 10138\n1072 13525 1933\n10785 21812 11260\n402 11351 3815\n243 243 22131\n969 7644 23921\n2960 7968 16973\n21051 17187 24838\n15650 19239 13938\n23525 25245 2037\n14540 8593 10257\n6751 13002 3967\n8379 8387 20758\n17145 19921 11284\n3917 8360 20424\n630 254 21758\n16682 23594 10970\n21813 256 14893\n12401 257 1681\n20495 258 17543\n5870 23499 14995\n25977 18188 21308\n15365 19853 20509\n23323 262 24846\n13439 19954 13815\n11120 22917 16976\n15548 26404 22164\n26786 8266 12399\n17278 267 15171\n19769 25177 20116\n26301 6616 9256\n2150 7411 5134\n13287 24527 482\n20576 9501 4973\n16516 273 777\n15471 274 18250\n8763 14851 6587\n14044 17625 3724\n15229 21072 23480\n11243 7934 22259\n9090 8394 22378\n10733 20741 17656\n3724 15148 721\n13274 282 24618\n5470 21003 15918\n22297 11329 23321\n6448 20216 22680\n15275 14275 3451\n14783 18538 9567\n6325 14768 25597\n17353 289 3500\n21490 290 7591\n19619 24859 6142\n18580 292 1425\n16021 22200 20616\n2283 6323 18187\n3058 2786 3922\n312 17117 25557\n793 14737 7812\n7159 15719 298\n17190 18614 21971\n21004 300 3052\n25093 25885 15736\n6219 18867 9563\n9839 13503 26186\n9885 7080 10605\n16780 20284 17241\n25482 3375 25151\n14019 10758 20078\n3257 23988 9545\n18581 7480 26728\n25635 8147 16174\n8826 311 5114\n6493 2568 17109\n14180 24025 24089\n23546 2282 10178\n20142 13182 6894\n23353 9260 9444\n16909 19765 17192\n20638 318 15678\n12191 4138 13167\n22669 6781 6413\n10385 2636 10793\n11527 18271 12362\n11350 26947 25582\n16297 25801 11529\n7053 4389 21557\n2958 2067 6286\n4546 10754 16058\n1904 17597 7813\n17193 329 1033\n12682 26130 12426\n2534 23214 9259\n9425 26148 19068\n7901 333 1256\n19614 25430 7390\n12978 13615 25879\n12237 10021 24261\n8905 21865 26988\n8242 3730 13647\n2926 419 13427\n12993 17105 12244\n10200 14744 20272\n1734 2603 16483\n1922 26983 3367\n25357 18149 5016\n18745 25585 25865\n1143 17362 13386\n4590 4430 21718\n4289 348 20161\n8461 349 1832\n9550 14662 3478\n8791 7898 14015\n23045 15861 1157\n23620 353 9500\n5639 13231 18127\n13262 26235 15395\n2209 356 26569\n21168 25064 680\n9814 19683 14891\n17383 22930 682\n13616 9405 5472\n2289 18497 15044\n8490 362 18327\n25086 14134 1075\n9060 11500 3825\n24661 16136 13629\n16947 15955 22502\n7727 26415 25319\n6757 3365 13632\n14692 15436 19148\n25151 9218 23391\n3787 371 4347\n17665 10497 18321\n16669 9616 24536\n26571 19299 10563\n26930 4719 23794\n2424 20501 20997\n24849 7308 8081\n21295 8530 7535\n23747 9990 3518\n12657 4945 12548\n9693 23704 11336\n22659 2971 3886\n24015 4218 16978\n6120 10104 384\n7124 21236 26764\n3111 386 16239\n10987 387 20782\n24361 14401 25449\n9888 389 2189\n22310 1526 18102\n19543 12698 18255\n7573 25373 19957\n17361 20873 6153\n26914 3447 6183\n25462 8166 8374\n21457 9177 2036\n3240 3480 17288\n2350 398 22150\n12858 399 11626\n13725 6733 12845\n21044 6260 24977\n12250 2146 10482\n7867 403 23334\n2908 14948 23193\n19853 22864 11845\n5574 11499 14446\n8186 407 12791\n15560 2997 13429\n18089 18692 2233\n3754 24770 21178\n25259 18419 11827\n17601 1244 14177\n20240 25504 20728\n4739 17022 2851\n20503 4895 23175\n10269 14797 6317\n3692 417 26772\n8383 24258 3863\n24219 294 5254\n4993 1244 8756\n7485 421 13013\n23422 12155 6931\n26826 24354 25410\n25320 9168 15528\n2321 18244 20681\n13658 22727 24970\n5419 24051 20875\n7233 26036 849\n6813 23232 12832\n8371 10451 2019\n9674 18770 7442\n9544 21672 18677\n9633 11308 14916\n12522 2799 9506\n19118 19518 12030\n19129 26721 18508\n17112 7917 1973\n7454 3654 17667\n4778 19970 7050\n3285 8309 440\n6785 12732 15409\n23602 11055 25818\n20326 15566 26294\n25585 21361 10852\n184 6557 3344\n22030 22963 9430\n11226 466 14495\n15685 16533 24469\n449 2620 8233\n890 16287 23815\n18214 24875 6494\n9604 23884 23433\n7824 453 936\n8846 21262 4062\n12959 7714 455\n85 4365 3525\n16353 14585 21609\n4143 458 3703\n3531 16715 19694\n2164 6348 5308\n9277 6133 15512\n462 7667 3603\n2071 3786 6354\n16344 24285 18733\n16641 8833 12348\n362 5338 8562\n20691 467 16219\n2793 10769 6681\n23072 7280 22744\n24875 4302 24878\n14594 13826 2970\n8485 629 25397\n10409 21596 22225\n7882 24703 26306\n24163 25734 25526\n14465 476 22377\n18392 22544 20552\n2086 10987 12126\n24786 8242 14767\n4101 9245 25056\n20705 11409 16708\n2370 482 9402\n20318 17883 21206\n5385 1297 17948\n17541 14901 20224\n7371 486 5699\n7 3455 25895\n5317 16093 20485\n21980 489 2484\n3410 2455 26650\n4163 12955 25014\n10497 18217 14316\n15221 8496 18752\n1915 494 17958\n23687 7127 23023\n13928 5685 3221\n11161 21657 16353\n18687 21431 12714\n6534 15491 19470\n20089 7225 22729\n24608 12080 6493\n4022 22134 24547\n26191 503 1415\n25669 13109 26376\n23649 505 18665\n4071 506 17890\n26851 4979 21134\n52 465 8900\n288 13784 9125\n17435 638 8334\n25058 22383 23882\n26989 1157 512\n26121 23857 9881\n24711 26663 19031\n13094 17499 22835\n24868 11500 26932\n21717 8304 10240\n3659 4547 26299\n1607 13359 9295\n8952 26581 8504\n12921 12756 4585\n9015 10943 19474\n15438 24486 8395\n24052 10265 25217\n17789 525 8416\n12942 17926 21755\n2842 1722 8586\n21709 18672 14061\n5732 22193 22692\n4503 26127 20031\n1758 5715 15214\n6673 3193 9268\n16285 19216 10789\n10886 2275 16494\n16738 14202 6298\n11013 24997 17528\n8676 11068 25777\n14178 15151 711\n22691 23963 16518\n17617 7708 21076\n3509 541 8501\n20254 542 2651\n17050 18250 823\n613 544 2101\n1825 3769 14052\n14911 14751 12994\n1963 6059 4310\n548 13561 8636\n5749 5200 24048\n8139 8067 3502\n8863 6034 16023\n25448 9448 8928\n2220 2508 553\n10130 22687 11210\n7150 24006 214\n18073 11633 4988\n22192 4989 16384\n17475 2747 21198\n9167 19226 18863\n7637 15624 5301\n15753 561 26121\n5138 562 19935\n18499 16662 10331\n2785 564 7793\n23013 15136 18845\n566 9086 14819\n16631 25034 1522\n12144 3949 11976\n12972 11612 11561\n7047 21546 199\n20926 1086 15059\n7596 17273 20084\n8264 1085 6909\n26827 8982 24739\n24338 26 13335\n6040 9688 4016\n8985 1020 9577\n22666 25490 15431\n8051 20846 5979\n17881 13761 4172\n20989 3416 3216\n1366 4619 25486\n17919 583 8855\n25565 9304 965\n585 585 19777\n19711 8351 14639\n5187 5470 5371\n23012 14809 7268\n24013 7648 10341\n11182 17267 4923\n21895 25394 1378\n19461 592 12328\n22076 593 22465\n15602 6738 20631\n17795 595 13091\n9641 16796 596\n16432 2120 8205\n11779 4462 26902\n11354 599 13226\n21069 12045 3560\n15492 289 25876\n19250 602 3711\n1358 19062 24758\n24641 604 16764\n9216 2613 8240\n758 22171 12027\n20591 6039 20010\n749 16272 19477\n17788 4817 19940\n23706 2151 14026\n24555 2494 15374\n8489 8804 21913\n22821 9093 22992\n14462 24515 11099\n25114 21514 10378\n17400 16965 13064\n12249 20777 1564\n3970 26535 17618\n619 15795 17803\n21244 4905 9217\n2061 3784 24648\n23470 1787 16262\n21522 6146 11458\n13104 23933 19757\n23676 21961 15388\n911 14362 13271\n21795 16438 4587\n2388 628 17884\n19565 20872 9504\n16931 3707 10587\n4247 21583 1127\n19912 19472 10864\n18729 4305 17532\n5866 11066 1562\n11894 4638 9235\n13420 9345 11513\n7568 19109 637\n16339 22331 18339\n22959 639 2186\n6429 15141 13696\n21809 26417 4217\n12922 18178 26047\n20867 26699 7411\n19076 6236 26625\n24373 645 13789\n23366 18083 14198\n7711 24335 9306\n2616 5168 25821\n4348 15204 19497\n7386 23319 8722\n20251 12475 3126\n4505 17449 11841\n14253 1141 10048\n12363 12158 16814\n10202 8978 17394\n1605 24229 656\n921 7868 23153\n12394 22074 17642\n10515 24006 659\n6084 21329 24921\n22136 661 23157\n13035 19347 1238\n11191 21314 10927\n1024 805 6933\n18833 10545 19628\n14583 15623 22871\n3230 14315 23062\n15649 8156 6980\n10701 669 8157\n1339 670 12715\n17490 2314 802\n8949 17557 8805\n9281 7388 10737\n8042 26823 11530\n6950 16643 8891\n292 22916 23084\n18245 19029 9117\n17310 2547 11094\n19799 22178 19466\n10360 18021 22197\n22148 24244 26436\n7322 15306 10410\n16894 683 22739\n2745 7692 11889\n5832 14509 7704\n2622 15654 22310\n4815 12498 16066\n21205 688 1197\n15332 15785 13372\n10743 6303 1679\n9067 20779 3363\n11585 9556 20873\n14749 10152 16000\n15395 21886 14811\n10231 14834 7287\n18976 13512 4312\n7713 20628 26404\n24655 17802 22106\n8542 25758 20891\n19185 10276 12617\n25637 7256 4752\n8851 14190 25011\n13242 703 2034\n4240 17984 4101\n22089 23156 24876\n18047 8071 23106\n13374 10275 18099\n16764 15580 11396\n5776 709 24752\n16094 1563 14011\n25882 12706 17967\n4128 26432 18048\n9884 10796 1556\n15786 714 5858\n16939 1342 18286\n16713 6097 16564\n3920 21264 3077\n6995 718 18118\n22207 719 9767\n25520 11581 720\n10833 4172 8129\n18791 722 9535\n8526 22054 8011\n13476 8196 16305\n4077 5733 8920\n22830 13566 26062\n15071 9263 16658\n10672 16357 12016\n21065 20180 1329\n1778 986 16415\n18531 2643 11734\n11436 1828 12329\n733 733 8192\n4758 734 16771\n19063 23914 4394\n15469 856 17373\n4057 2236 16364\n5871 738 19103\n2702 20019 5419\n8420 9585 8372\n389 16613 1589\n13062 25923 555\n21407 4135 13471\n10600 744 17117\n22388 6241 12241\n23586 746 8567\n17942 4574 23419\n19508 22409 12897\n18725 20109 1853\n24270 750 4358\n16967 14170 2954\n200 10872 15549\n5108 11916 17609\n21871 18263 5530\n278 17915 20614\n19065 756 22044\n10680 3901 18077\n12627 1862 10715\n22186 7751 19023\n24693 21973 18448\n3268 14801 4553\n9226 22666 25087\n21646 17899 17035\n22505 764 19324\n13224 712 20472\n15347 19779 12595\n1906 767 1010\n24893 22432 9317\n15169 5436 25676\n1079 4658 16642\n678 20835 6243\n11412 19324 14772\n13216 9517 20069\n9750 3350 17467\n4802 17002 4495\n18120 22685 22576\n19668 18932 10001\n22938 11362 21199\n11318 23459 10243\n25948 24684 1577\n14629 1621 19469\n25238 6387 24131\n24162 17082 11895\n6360 7645 7064\n9300 532 13132\n19231 20706 26274\n22563 26115 17358\n17868 25545 21628\n19669 12152 7512\n13318 7774 11190\n15847 6154 23866\n15021 24808 9037\n20769 14292 5412\n9450 951 7135\n9275 16446 7414\n19785 6121 11508\n17661 5216 5901\n2838 22899 20483\n9671 16842 9591\n13528 248 13224\n18196 25569 19396\n10266 24927 21727\n26734 20691 22979\n10281 22204 11276\n12296 10656 8301\n26483 14979 10787\n9751 807 10914\n5093 8968 11613\n13708 24001 4481\n20594 1087 16410\n22542 9078 15435\n18860 26953 23100\n25997 20984 26952\n6390 987 142\n26642 1295 22018\n4597 717 23312\n4236 22537 11052\n24183 975 10143\n8475 819 21643\n26073 8713 3084\n14760 9765 7384\n9502 17219 238\n11874 16242 5258\n23800 832 4429\n10364 22313 7652\n26663 18615 23730\n11995 6627 18846\n2556 23876 17833\n19152 8093 10656\n347 17115 25763\n11098 21034 2346\n20245 19200 15765\n25889 13044 12996\n3183 17674 12282\n7110 13187 20611\n23569 836 18092\n1696 3477 8789\n16870 747 26974\n16119 2831 18210\n7605 13664 12232\n19089 5964 6473\n19258 12687 1186\n20854 8390 26590\n3169 18532 24788\n26893 845 2760\n26142 4291 4086\n24994 6895 18498\n9256 24749 9837\n2268 2353 9292\n12402 4159 17703\n6790 7182 19966\n15804 3529 14028\n23104 11381 7973\n3630 4859 11694\n6351 21727 9354\n13293 1013 16917\n4916 857 25356\n23975 858 858\n12158 859 26598\n12961 10337 3684\n15864 861 3304\n20707 14587 4211\n20714 863 23770\n12781 24080 6557\n6308 15428 16937\n63 17255 24826\n19326 867 2939\n19980 24860 2049\n7832 20701 9933\n5070 8195 12782\n22346 871 20354\n26749 12181 15213\n18145 18353 12212\n16535 9791 17903\n21443 20758 12686\n612 7457 19905\n4773 9744 19880\n1203 13467 16830\n12594 13866 17522\n23264 19096 26181\n15889 14345 8340\n19634 26967 3103\n23163 6678 24539\n24316 8044 18257\n7952 2416 23605\n3446 17054 6502\n7911 8895 9426\n13533 888 6309\n13780 889 3964\n15186 890 20674\n19446 11630 2779\n15913 18556 8489\n8800 21280 11344\n12851 894 6958\n4823 895 5106\n4821 10760 20648\n11457 9164 460\n17314 898 17007\n12147 20331 13318\n10196 24065 17041\n19861 901 12824\n94 24606 3787\n14130 12687 7607\n14653 14232 10925\n13905 19980 12017\n8466 21543 26738\n13731 5654 8654\n873 3220 25308\n10448 14472 1992\n20123 19019 23139\n18210 21970 2103\n6117 12141 14789\n16700 8652 9612\n21610 914 19311\n931 67 10222\n21436 3921 7108\n3328 25560 288\n14427 12342 21630\n18751 13631 2986\n5328 20560 21853\n21804 5900 3148\n11114 17935 18719\n2214 2219 26219\n8332 18753 97\n3653 13669 12256\n26166 5051 9846\n13786 503 2327\n18680 17648 8376\n22617 26260 3452\n14367 15498 8279\n13934 931 6635\n22332 20932 20057\n1869 18896 20920\n16051 6086 5750\n9394 13450 10530\n12277 13213 10573\n24561 11457 7601\n22655 22975 18578\n21755 6398 2862\n900 4708 13796\n26029 14832 4013\n25059 26107 17126\n9658 1890 24314\n4592 22413 9600\n2340 11684 3292\n12951 24010 946\n24766 23150 6222\n23020 11041 22929\n15008 15824 1997\n18371 11598 26782\n5231 13962 13135\n21325 19573 5949\n16108 18676 24044\n3639 5311 15855\n8083 4299 10158\n1580 21345 4036\n18333 957 17341\n22835 958 22731\n24730 14546 1450\n18493 680 26301\n10996 26929 22849\n20482 3570 6927\n11094 17339 24502\n2628 9401 9873\n23768 21293 20288\n9843 8294 9923\n3786 18146 17887\n18224 21757 16053\n25345 26393 12057\n14471 18034 19183\n6550 23939 3459\n11681 8865 6649\n26424 14045 19016\n19531 22 18443\n5431 25391 7359\n10797 6685 3720\n15569 761 5401\n24666 3106 14466\n8019 20078 3030\n21985 20012 9169\n9568 18397 20352\n8214 19718 19483\n25679 18479 19343\n13821 5949 20544\n13932 16804 1460\n22767 14479 2847\n19150 987 12518\n8012 12449 16017\n24285 2277 9893\n18163 16358 14427\n25722 26618 20554\n24112 13621 11072\n20140 993 25652\n4903 994 26202\n26278 995 2422\n9372 700 15585\n25400 5176 17968\n2643 21355 9915\n6298 10967 3346\n5728 10981 2000\n6708 21369 10449\n4026 26090 20986\n13278 21094 12747\n20260 12865 12377\n18432 8720 22928\n21515 2086 5091\n24866 23250 24530\n26573 16517 11349\n11908 12353 14220\n17103 551 16370\n8755 13718 3523\n22732 3297 4972\n17869 856 21\n11963 26326 9755\n19495 7135 13295\n1016 9701 9965\n15513 1017 20193\n13394 25127 11919\n23542 15323 11883\n7172 1020 16052\n11757 456 8645\n14291 24835 23723\n12735 1023 10818\n10549 2333 11200\n10025 20257 793\n18778 1026 22938\n3254 1027 3867\n13532 19985 1028\n11157 15909 14368\n7907 23414 6955\n5647 20074 18786\n5757 19277 26469\n3780 5636 1988\n18439 23911 19090\n23782 14454 2438\n23305 19385 23140\n24232 1037 17125\n14539 21227 23907\n12015 2546 6255\n13912 9293 2941\n9481 8564 23585\n13594 7418 343\n4555 15787 3699\n9460 18345 8025\n10685 15368 26845\n1046 2934 20939\n20007 911 16255\n12045 14325 8512\n2577 7172 26985\n22930 1690 7770\n1694 12390 6091\n26737 1052 12281\n12893 12360 18176\n6094 16139 7299\n23231 1866 22130\n9392 18824 24776\n10241 1057 10721\n21778 2735 26743\n4838 19814 8051\n15740 14745 14489\n14925 15845 4189\n379 25614 21251\n18842 21007 5663\n21720 15109 21093\n22385 1065 16172\n13479 22031 19583\n16774 5819 21078\n2977 18233 881\n4517 7901 18653\n7347 13494 11630\n3119 12082 23695\n8568 18877 15000\n15841 14268 300\n21858 223 19783\n17571 7523 9611\n4740 2609 11364\n23925 7600 3128\n23342 24395 3227\n7111 15978 12058\n23893 8045 19101\n11225 10372 14281\n3546 7751 5866\n22750 20374 6302\n7756 24964 2121\n1717 424 16549\n2019 1086 18235\n2359 9351 12186\n16984 26589 16656\n1396 11817 6652\n19591 5082 1090\n9651 974 14950\n2604 24057 20649\n25757 25112 11357\n20550 8691 1611\n14423 13202 24690\n10829 10621 12645\n15444 5732 5316\n16786 5922 17119\n10190 1099 18734\n2660 18585 17268\n21608 19928 7192\n10843 13430 11582\n25890 1103 21650\n3237 17080 22320\n21681 5980 4513\n23151 23479 1106\n11358 3782 26403\n12164 1108 18348\n17872 13776 17237\n14166 25150 12539\n8887 14687 458\n18504 10624 1112\n21617 23092 21593\n17239 15071 6503\n16422 11707 17150\n16921 18764 2564\n9165 25872 15656\n5310 7683 17107\n16759 22178 20871\n24837 168 24221\n1121 21380 10196\n10919 11263 21615\n19411 25742 24862\n9737 26108 14993\n1709 13405 6461\n6222 21267 23531\n1930 6690 19511\n15485 1792 309\n2804 5812 21452\n25994 23994 1727\n10099 24070 2363\n7849 1132 24657\n3904 25672 11024\n15467 13315 1395\n10647 24919 12890\n6669 5301 6472\n17676 812 20396\n20687 4562 18130\n2771 16646 15035\n22828 3332 5825\n13077 1893 11085\n1094 18867 13779\n10287 19082 21714\n11549 14525 5240\n12593 18860 21708\n14095 1146 25674\n6963 16094 22830\n17052 1148 13593\n15109 23384 885\n2774 21067 21406\n3599 14391 19687\n18752 9165 9669\n20625 5081 17452\n22498 26079 23327\n3838 20867 3582\n21929 21881 20281\n20341 149 5088\n25062 24203 21547\n15170 10626 3095\n14205 1160 2773\n26044 17940 11673\n18530 20823 7850\n11187 23107 25019\n10500 7409 13180\n17757 21712 7933\n7094 16006 17734\n1959 6130 10002\n11376 7360 6373\n18777 1169 24588\n21018 1170 8631\n20371 23406 22723\n24705 19865 26449\n13685 2704 2173\n11459 20654 11942\n26322 15618 3895\n17592 21885 8797\n4633 13897 3996\n13087 16895 15146\n17534 1675 17438\n13985 4700 24452\n3816 16824 10045\n13190 2046 17982\n11442 20991 5418\n3256 1184 5096\n22481 2905 18884\n9282 9551 23927\n18638 21627 7350\n20580 13961 18385\n25845 17056 23069\n10899 17539 9115\n23554 19146 4623\n24085 8565 21576\n20305 1193 12788\n25255 24823 8023\n19462 16691 3054\n4764 16561 21505\n12480 4552 7664\n13099 1198 24662\n8578 1370 8343\n22077 11040 22976\n14844 7505 25537\n1202 6986 3943\n6254 1203 10238\n23884 26500 20884\n18589 5381 16896\n13870 14926 966\n24458 24647 21439\n8480 23336 22997\n10401 14604 19300\n4407 20615 17626\n16283 1211 7166\n17417 9553 732\n21776 5573 24664\n11070 1214 8998\n15127 1167 11754\n20469 14456 17480\n19716 6601 1041\n1351 18938 3610\n7270 19571 8315\n2233 13204 16076\n21749 23440 1389\n13574 9523 22211\n20570 14586 14714\n3013 14104 20253\n2188 1225 13596\n23663 1226 26807\n13214 24531 4846\n26769 1228 1065\n248 1229 10949\n11011 20803 15123\n22295 25346 3039\n5789 18493 10304\n13577 2225 18577\n12706 1234 17695\n11083 9054 26787\n20372 12473 20617\n11944 3128 13989\n7147 19086 13102\n1239 25535 13327\n8224 11840 21333\n13009 16049 14337\n2223 18610 11951\n17054 542 12763\n23177 8324 5681\n22781 19213 6693\n7342 19662 20811\n25874 5687 17802\n22741 18477 685\n18209 1249 12596\n14703 12562 26959\n1310 4467 8734\n26924 18545 14292\n549 12576 9349\n7995 22502 12998\n17375 24074 18714\n11117 25120 88\n22788 16716 4740\n22839 18759 26207\n4582 15726 7014\n19860 12188 3425\n21261 5120 10005\n23643 1262 23019\n8570 13687 24178\n14160 11597 17928\n4124 16908 12729\n15951 25063 22418\n19174 1267 13731\n5276 1892 25812\n23773 25368 23848\n19 1270 19491\n14066 25362 20202\n3781 1272 5424\n1273 1273 15596\n3962 1274 13482\n5907 10683 16670\n11332 1369 17428\n10365 21976 18773\n26246 1278 22899\n16770 25146 21703\n20064 13725 10989\n22457 15513 2785\n13447 8578 14266\n1883 15459 15422\n2049 1689 2193\n22813 20112 16941\n9470 22635 12302\n15767 23170 24095\n23293 4864 14768\n7009 25316 25193\n13727 9082 914\n24507 13062 67\n2356 20145 13740\n25285 2957 973\n1243 5467 11371\n11775 1855 6378\n7872 9544 4869\n16428 22772 18937\n21074 1298 13346\n25987 1011 24907\n16985 19537 17508\n9861 14861 25053\n6051 11286 13462\n22815 4839 9002\n8709 7669 20264\n19532 20644 513\n15407 647 14863\n22299 1307 10646\n15036 18881 9353\n25360 22096 20637\n18971 1310 8486\n13794 16786 4922\n20528 25488 957\n6073 753 14089\n79 8162 18546\n614 3222 16758\n4500 1121 4113\n15320 1317 1317\n24739 6331 13075\n17282 5066 24359\n2848 4232 8088\n20985 1201 4329\n16570 17815 13983\n16110 15523 2622\n4241 10316 9889\n5496 24688 1013\n1326 1326 17003\n5455 25866 25738\n22853 22616 2328\n10404 15684 9868\n7170 12858 9223\n14899 18398 16763\n18393 3465 5372\n9373 29 7693\n5014 23454 13118\n20311 16159 26842\n19592 1336 23701\n5180 1337 969\n879 5879 7218\n26486 1339 19142\n16785 1340 22964\n14397 6613 26640\n17659 17894 9230\n12991 21335 10906\n8192 22101 15333\n1364 9257 17489\n17527 21306 114\n24206 26142 4558\n24460 13364 23657\n2901 9669 16280\n190 10675 5755\n12679 1351 4602\n4784 9424 8965\n11657 1353 6716\n7026 26623 15602\n13635 5395 19443\n26732 1356 3745\n12120 1016 24488\n2203 24990 19763\n22274 17039 15415\n19109 12344 15912\n8444 13929 3068\n17106 1362 10767\n13990 24198 26414\n9028 26580 14833\n21653 8432 19800\n851 14606 9838\n9210 26882 22159\n2461 7037 23680\n5356 19697 1369\n14050 8234 8111\n18422 22606 14987\n18060 7588 20820\n16805 17112 21336\n7654 622 20246\n16215 22183 17442\n1376 10989 1376\n14092 21876 13348\n13991 8306 26007\n7502 26003 14766\n20924 1380 7137\n6149 26645 8757\n7414 2918 25574\n10402 18495 22330\n18301 1384 22613\n13561 26993 17956\n1386 24802 24234\n203 18734 1870\n10124 15124 10036\n25245 4405 5973\n5395 8262 963\n4431 1391 13047\n17653 1392 9728\n6756 2241 13617\n14167 14930 1394\n24102 16387 4662\n11572 3801 18844\n26600 16517 20045\n22275 646 24595\n15042 7327 21759\n13944 19728 2072\n19588 1401 24105\n14338 15730 22327\n14859 17763 9646\n11052 9380 81\n15789 976 12365\n12203 23523 16662\n5306 1407 17594\n17157 26400 22160\n13241 26097 1201\n19151 9154 22042\n534 19910 21590\n26577 1276 16772\n15341 6781 13237\n2206 1414 2910\n7959 3282 13146\n15181 7232 17277\n9292 4044 5300\n19706 1298 22514\n3142 1859 18070\n22324 8676 21937\n24664 25640 23912\n7483 4398 1422\n19215 19442 22818\n19672 1424 4592\n3369 817 21604\n4223 17770 6866\n8286 19022 21427\n6185 22697 23484\n26304 3973 21085\n16318 10974 25171\n12535 15786 14623\n1432 6269 12461\n15964 652 1353\n11183 17378 14039\n18294 1435 17411\n4732 1436 11900\n9200 9981 15368\n2899 25483 9363\n17591 13978 7506\n26549 7672 26717\n7441 12180 21633\n15002 20578 7231\n22 18606 23947\n22953 1028 3900\n5448 26168 24120\n21355 3083 18819\n4167 8986 6703\n2925 7856 944\n9780 13556 9284\n25439 1450 4082\n9758 1451 16878\n9953 6452 1852\n1453 5696 20024\n14918 22638 14667\n18983 9527 6327\n4160 8589 7317\n281 21460 16308\n25634 8138 20767\n14078 9086 11835\n21673 11809 21001\n13981 24424 16496\n9451 4955 11118\n20175 8618 5455\n22736 2405 8989\n22321 26300 17889\n23914 23426 24575\n20598 12774 3742\n5065 23257 18201\n1165 16760 21224\n17779 1470 10915\n8714 25079 6458\n20365 1213 6760\n948 3641 12012\n22247 22367 450\n14659 20038 2574\n25116 12433 23121\n18648 11232 9688\n24926 14275 12934\n12919 22375 10439\n11064 9760 12096\n7708 19396 545\n18506 6575 14578\n17838 14414 3211\n22129 21844 17169\n13408 24120 20021\n6843 10166 2475\n9087 6338 15679\n8381 8597 1080\n13596 14105 25076\n26247 1490 7626\n2190 12494 19427\n15505 6025 13724\n19909 8480 5416\n7403 1219 20294\n6570 1759 4474\n5368 11080 15808\n12281 1497 26401\n20895 18287 7647\n2403 16566 6934\n17393 1500 14217\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/input/1500.2",
    "content": "43064 1 21209\n44843 14863 2407\n39682 291 10043\n50208 396 68\n25033 24360 19976\n41154 4358 1731\n31035 24738 16050\n46865 8 26168\n27629 26932 21433\n29595 26167 19498\n36570 8766 1438\n44629 8420 16721\n28956 13800 25296\n24314 7755 19062\n30867 7362 14207\n49913 18920 20981\n45141 22748 18308\n34563 21431 14783\n24986 13070 699\n33176 5713 6257\n34953 21 17701\n40775 10795 20726\n31414 8143 12026\n49548 1365 17968\n40013 19172 4572\n39851 22970 16378\n30631 27 11310\n45144 12761 26740\n38236 3816 14008\n37951 8107 4675\n36006 4514 6490\n25697 32 5597\n38789 20817 18700\n42123 22351 1290\n27442 4819 23470\n47765 21377 10356\n32076 18456 19453\n47015 6403 16894\n45891 1767 24383\n25553 10421 1560\n41437 9204 19292\n42947 25986 4802\n47602 1043 20899\n24776 25492 22913\n31708 26205 13728\n33626 15158 10259\n41326 674 20983\n27252 8144 26504\n44912 15884 5516\n42662 50 22599\n42967 1763 25507\n50989 8953 17716\n36553 20760 14432\n37375 15902 11123\n24310 55 8359\n44300 1040 3341\n34144 57 1457\n44835 14575 8151\n40874 5502 17587\n39077 20177 5364\n29745 11744 22965\n24362 1947 11206\n41606 25450 4047\n46284 14248 14112\n47077 12273 8561\n47491 21922 20914\n46663 2526 363\n48664 36 2065\n26660 2533 11869\n30119 3483 26819\n37702 8695 23074\n41793 19808 10816\n33397 20305 23444\n41043 15903 17359\n31511 7027 21878\n40720 19844 1540\n26892 16101 22437\n24679 13366 8507\n39643 2818 47\n31529 11968 13853\n28325 1852 15545\n39667 20962 2807\n38762 6470 20950\n31016 16604 26508\n43185 24501 5048\n34935 18366 16398\n48355 18506 22199\n45673 12405 7653\n39901 5281 13337\n51099 3719 351\n50394 6270 15038\n33157 9940 9081\n39844 23189 20072\n50871 9998 5990\n32667 4106 5530\n32060 22085 14821\n40597 5865 3972\n46939 98 3151\n34991 3107 18875\n29224 19457 16892\n37425 5589 17024\n46183 26307 24707\n33491 10431 11914\n30084 8296 10600\n24781 4569 16841\n32595 26370 11410\n46095 2174 26579\n47632 2257 7505\n29465 3925 24144\n39263 26323 2054\n35766 10783 879\n39740 24968 11880\n31792 10009 16204\n51155 12543 21530\n37314 22030 11798\n43392 15849 8569\n36585 24728 14661\n42594 118 20110\n40406 119 14383\n40644 120 14421\n24744 20369 9\n25038 21946 15359\n36399 23102 13798\n48197 124 8252\n49361 26696 8909\n25079 94 2142\n35470 127 11255\n50972 9037 6400\n48581 4988 20380\n26363 9815 4679\n46338 131 18859\n37624 1521 4900\n27961 133 3248\n24359 134 8203\n28251 9511 25727\n41788 136 20517\n36589 24817 12116\n47411 138 23823\n29482 6574 26691\n37872 15649 16324\n43105 3789 7976\n35943 12859 9342\n36174 11567 8914\n32324 6320 20968\n30784 16428 15081\n35595 22986 21367\n34434 4827 18614\n39792 2553 19441\n27484 5544 15269\n44666 8691 15611\n38651 175 7231\n27193 18360 20717\n28197 17780 13921\n27054 154 18058\n46242 11086 23731\n29525 26036 2369\n43593 12053 26573\n46255 14227 8011\n30438 16583 21335\n25068 3952 19264\n46360 17849 7361\n24462 5738 1346\n42959 10686 22118\n32893 5745 7721\n31249 26048 10173\n29159 12067 7259\n33603 4786 1050\n36265 8357 26357\n36736 23172 7105\n46579 12554 367\n49330 13915 6843\n39637 5161 15876\n44364 20365 2501\n24346 7014 8310\n51206 6695 11922\n33004 12733 19192\n48365 19681 737\n26222 23055 12842\n24479 18198 23747\n44653 10604 25577\n24745 18680 12672\n32066 11515 25710\n49707 3170 14295\n33249 1557 3752\n40216 185 1049\n43398 26759 407\n37274 187 10398\n41280 11601 2897\n27161 22576 10680\n28434 23814 26086\n45030 9415 14407\n32217 10216 5221\n49264 23308 26620\n40486 423 1103\n27866 4294 19675\n38760 18041 15484\n29052 197 26608\n38218 198 20083\n51078 26906 13023\n28593 25728 18920\n48888 12345 2625\n44683 14114 8503\n34735 203 7923\n49064 9825 19361\n41929 24877 53\n33711 8227 25347\n40859 21175 13583\n40196 6896 19013\n30517 2980 6729\n37270 20386 25666\n36511 22870 19518\n39213 20252 9185\n41121 26216 6085\n25855 6243 7022\n28382 19394 7287\n49305 6328 888\n35672 8393 12812\n42790 24103 5583\n24519 16998 7203\n45413 572 220\n26969 22973 15701\n30431 4235 21539\n39563 111 17450\n31481 6360 9424\n31685 225 5964\n44859 2914 6999\n44759 2595 2587\n41941 25081 13977\n27129 20336 3176\n51271 10358 6998\n36267 25042 23647\n33649 19832 24085\n31656 15508 3820\n26539 322 20010\n48274 9787 3742\n25525 16529 19857\n44529 237 18749\n41874 19342 19187\n27131 20498 127\n37980 240 23981\n44925 21452 22857\n25238 11914 25178\n33266 243 2339\n39424 8393 9033\n45052 12029 2952\n46487 7875 15379\n34630 16866 7450\n38276 26208 26840\n30477 1196 20177\n46235 25522 250\n45594 25558 4331\n31389 15593 26377\n42828 15392 8621\n37106 16499 25619\n37251 2335 10567\n26473 16469 26757\n44213 257 3289\n42563 12863 13706\n44626 12062 18798\n49477 16217 16172\n28169 261 26197\n43559 262 5691\n34942 13879 11898\n26156 264 23325\n49168 11148 8441\n24523 1610 4338\n39890 4723 22339\n27621 4169 13788\n36956 18565 1677\n36951 3686 22019\n34966 271 130\n36852 3552 3885\n39744 26140 15900\n47523 22410 7839\n36082 5046 11291\n50861 228 5273\n48292 13928 8605\n38103 17166 4854\n44686 14266 23\n33188 26256 12352\n26901 20924 12484\n28195 9055 18647\n35698 5627 21187\n35912 23596 17572\n26164 18312 13200\n44258 8926 214\n24747 7199 287\n24977 3296 4928\n42376 25284 11401\n26115 290 17023\n31746 21723 10158\n43109 673 26257\n39380 293 9976\n45975 14227 10891\n26934 295 20199\n32401 7173 20992\n48757 23724 17564\n31654 1378 4447\n43503 14171 10414\n28456 17641 1268\n30257 1421 17944\n50175 15270 16019\n29963 23954 15642\n25452 25088 15936\n39736 305 5580\n31134 12106 25791\n42207 307 307\n43680 26700 25257\n50161 309 12309\n42831 8475 22214\n26819 311 20311\n24612 5616 117\n35024 4268 3009\n29966 26207 15599\n34770 10294 2099\n31333 5673 5121\n48577 19128 23117\n27903 8014 446\n29198 6359 17818\n37740 320 12008\n42968 6524 6529\n36915 322 9258\n47879 20886 9283\n33213 5628 7417\n40833 3045 10493\n50018 326 14646\n31774 21607 10079\n45044 328 15909\n39456 24084 12924\n40926 8391 3810\n48079 235 3286\n47880 332 23716\n50313 19909 8253\n43434 21459 16326\n34163 17906 26762\n49252 11789 25200\n35720 16737 13964\n41470 11162 2394\n24639 8755 24867\n49181 6697 25516\n38009 24517 7357\n42815 18531 20179\n43190 26223 24215\n34073 26408 1608\n40064 9444 12020\n45955 346 3162\n39655 11099 5286\n32392 348 20689\n33337 18584 10973\n48831 350 1259\n25350 7410 22946\n39140 3608 17925\n31984 5953 12425\n45646 11970 6850\n40802 25819 26494\n25797 6292 2084\n43764 6000 5568\n41351 2654 3526\n50126 20242 9911\n36404 20808 17965\n46968 23977 361\n50694 13183 3967\n45951 10771 10875\n24317 364 8708\n26012 18760 1000\n50106 6683 12155\n25347 12071 4314\n41388 3957 160\n31693 17033 22329\n39430 23778 14394\n50071 20566 22155\n44400 8044 18204\n35145 20933 21024\n48554 25459 1811\n37622 375 7823\n27860 3885 2312\n50045 377 14852\n48947 378 23626\n51247 11459 3478\n39189 7873 15897\n31041 15997 4904\n50671 7230 2387\n51262 9615 10506\n48961 384 2437\n39048 23129 20052\n30507 9519 17322\n39311 14846 14142\n33888 15636 17121\n48220 9168 1453\n40970 17830 8771\n43819 17399 11455\n44041 18176 22464\n46741 6537 1345\n40174 14490 9618\n40615 14710 5643\n44165 24345 5673\n50628 4024 18656\n38031 12798 5934\n38587 399 9183\n27945 14701 4741\n43325 1140 9969\n30987 8498 12170\n46807 5499 15150\n29920 16852 2545\n42308 20360 16997\n48607 21803 13918\n41830 24151 16274\n44332 9120 21525\n33608 3017 7740\n27387 8279 25154\n27191 21054 5118\n30368 4708 15633\n37036 15680 18872\n44386 13435 25062\n44907 18314 8266\n41169 1184 22008\n47605 21532 21012\n49595 20135 13602\n34407 16027 283\n44461 19409 1868\n49340 12389 23229\n38314 3731 26715\n33379 17938 6487\n47441 11837 9485\n34512 22673 21417\n37950 8407 20570\n50815 9963 19334\n32864 10041 14833\n39753 3885 1917\n43818 18027 18563\n27763 730 12738\n46228 22197 7029\n32784 7940 5916\n32971 6127 23650\n42026 2019 886\n26312 6476 14393\n33620 10501 20376\n26530 23659 19942\n50086 15634 23330\n51124 440 20397\n50776 7937 14396\n44507 13466 11495\n39826 11046 2323\n28264 668 7796\n25449 5552 22432\n28170 9443 4907\n36358 447 19799\n45468 8573 448\n44501 4012 23897\n50326 14375 13714\n37994 26646 11014\n24437 15388 14188\n42364 22568 2416\n25799 13427 2979\n48046 17210 12903\n38049 14184 4240\n27160 21905 19265\n25230 458 8055\n33151 17286 8747\n37952 19121 21665\n31553 17632 10072\n26746 5699 14227\n50182 463 3778\n39985 17000 21997\n24765 4329 7076\n43947 19319 3159\n25066 10323 15411\n44080 1300 6497\n45964 24008 21173\n48839 11979 2563\n37046 14418 17719\n36812 24464 14688\n31045 473 4001\n44438 15807 7418\n32863 923 2958\n24853 24308 1249\n50332 3344 7664\n29503 7638 14587\n47979 22298 8498\n39681 3013 2013\n34744 22028 20908\n40347 18879 13527\n29151 19926 26339\n33048 19361 25412\n25476 2237 12557\n36050 7134 3459\n40742 487 2626\n28033 12509 3128\n45608 2937 7236\n33446 18959 2970\n49554 26502 3507\n31968 609 6617\n43060 493 19797\n36722 1795 20094\n50078 2807 666\n26340 10600 11264\n27992 497 3209\n24798 6631 26103\n29039 1406 1854\n41853 2369 8220\n28492 26752 20469\n50850 19147 6067\n25846 1938 5330\n49713 7597 8040\n25469 9817 4412\n45542 1866 17362\n44871 21030 15670\n30077 508 7484\n25236 14024 23861\n33034 6043 25366\n38926 26903 22666\n35673 5613 24373\n37229 25801 7673\n33854 5991 12258\n33378 515 25862\n39272 25276 17860\n43665 2056 21517\n39466 25187 22510\n49502 18791 25938\n24820 1216 1664\n48600 12233 8628\n43443 17199 19335\n39287 12987 16899\n50821 20 16124\n36513 8424 25565\n47258 21334 2782\n49022 8815 10482\n32116 23197 72\n38765 529 23228\n34078 11490 562\n50935 531 2283\n36936 11588 12689\n43484 15957 21688\n24834 870 20854\n41382 11738 16938\n47604 10173 4293\n47280 20756 16145\n33547 11279 21482\n42834 20094 12307\n29797 24756 16665\n40577 272 5557\n27178 24387 22699\n35518 17655 3231\n38132 25136 7784\n29384 23428 18708\n43366 21007 8719\n39983 10646 8646\n49733 21561 7553\n48324 2408 3325\n33418 347 11499\n31830 6927 13074\n30196 8197 21613\n35976 6937 5377\n50299 15754 8738\n24490 8222 3462\n45765 3545 11585\n24401 12352 17773\n35682 5963 19451\n46115 5106 362\n39841 2069 32\n43917 4372 23972\n44915 562 21455\n35831 3603 2310\n36093 22105 2137\n26132 2624 25232\n44079 16371 486\n36710 9823 13626\n44356 15565 26888\n36077 22860 9873\n26190 20487 1391\n35431 2830 22126\n27005 16345 5948\n47372 573 11536\n29722 574 1150\n42987 16618 24426\n43780 1813 23112\n46120 577 8449\n46299 578 22847\n50138 18350 12278\n46877 22185 20921\n40649 2192 7741\n32639 9819 13107\n37203 19831 23530\n34292 18829 13696\n40165 585 18908\n46526 6119 25474\n26274 24107 15446\n28816 21033 22657\n36593 26093 9013\n28074 18723 14555\n45451 5127 7647\n29372 20848 26904\n33632 12937 24033\n29342 3466 5831\n40823 18899 26555\n36573 596 9225\n50964 10733 1813\n36807 17302 25878\n30123 599 599\n43217 12837 24981\n42920 1969 8892\n49878 20911 20922\n40847 603 4659\n42752 24425 5609\n30260 16376 3600\n34794 9206 19467\n40531 12175 23711\n29868 18696 1469\n30125 10697 21305\n47366 4626 25290\n43826 611 115\n45381 6284 25721\n47537 11197 25661\n40226 24019 25203\n25206 4954 16570\n24332 8733 15880\n30608 12649 4036\n26614 9122 10431\n49783 24790 18995\n42645 620 21625\n24473 7749 4213\n50834 7686 23870\n27926 12794 24143\n32009 21312 22576\n39981 25748 19356\n35755 8826 21399\n27871 14774 11371\n39573 6092 628\n30497 1589 10821\n32050 6227 21779\n38622 5162 15402\n40825 23288 3957\n38736 16164 7004\n31571 22578 24594\n41999 2238 5526\n37461 8441 13793\n45233 23208 2920\n44946 3174 26510\n35219 16639 18770\n50556 19661 301\n41848 23985 4337\n29227 5751 25250\n48602 643 8563\n35232 19633 6081\n28193 9040 18437\n36178 566 1299\n43251 26191 55\n48748 648 22400\n48373 649 13177\n26835 21471 15674\n37658 13934 26022\n32048 652 18876\n27588 23672 8544\n46823 6174 15331\n27286 655 20746\n46180 1328 25181\n43328 22729 8177\n47566 2778 10047\n48655 18998 25891\n27352 660 22209\n46713 661 16245\n47874 10230 4699\n35982 11474 20695\n27513 15376 15989\n40264 12668 18052\n33107 22498 5783\n25671 19854 8107\n32032 21897 14788\n32908 24840 11709\n39519 7987 9302\n24782 4698 10626\n36913 15821 3656\n24328 14921 7561\n38534 9903 26394\n37370 22806 4230\n44357 676 5460\n41460 13184 20533\n27967 678 26763\n24579 4290 8679\n24772 11789 5336\n44800 980 956\n36950 6375 21290\n36690 16755 22038\n40928 24849 1081\n26561 5829 18533\n43711 686 11787\n32686 3031 16146\n24825 23128 16901\n44104 689 16276\n46742 12751 2506\n28223 2230 22486\n33605 20449 25132\n43476 693 693\n37074 15715 6750\n39318 22618 6330\n44241 4685 19968\n38373 9233 22196\n31150 19367 1591\n42802 699 17702\n34445 16300 19273\n37748 701 5477\n33922 1019 24558\n48326 8850 20823\n40625 5157 20448\n36789 15052 20260\n28086 24095 20194\n50114 20595 26643\n33992 20764 5449\n34884 25069 3173\n25623 1915 3891\n40646 7306 21018\n29249 12325 20856\n29296 6817 15625\n29091 12378 8394\n44218 18299 17131\n31317 16612 26772\n47721 717 20392\n40415 12694 11414\n28587 10730 13218\n30612 11821 26021\n45853 16265 4116\n49515 11295 18642\n37823 4326 22822\n34597 7481 7297\n50337 1264 24912\n24386 11971 10331\n24486 8106 14423\n29836 10016 24608\n35277 729 13457\n44299 431 3290\n44586 16235 11923\n33976 7641 3529\n35868 733 6885\n28327 18606 17558\n38126 18426 19311\n37508 8904 736\n38421 5993 17625\n48742 26335 10103\n50410 21107 26766\n32213 15313 25969\n45676 12517 24653\n29274 14646 15230\n25099 1871 17106\n49969 1909 2973\n27192 24753 6481\n46571 3367 14074\n36447 23566 21843\n28965 18105 6273\n25148 15269 5032\n40599 9286 14342\n27214 21874 1954\n37620 26685 14493\n47845 4953 3089\n48131 6650 8015\n24634 12070 755\n41328 16833 7617\n33185 13285 12813\n27746 9587 14123\n39654 759 8255\n43305 760 19685\n34680 5580 17297\n49483 13714 8698\n49903 21686 2811\n42045 20633 9953\n32497 765 5069\n27343 20435 12963\n49198 17775 17954\n48004 23757 56\n47008 3060 529\n48390 23799 13311\n28522 470 3763\n36440 19060 17748\n26292 6981 16789\n49807 10635 3323\n42595 7847 11535\n47185 14336 5301\n42581 21244 17196\n26486 14802 21127\n37063 12758 12190\n37669 8668 16924\n26316 13264 12448\n47719 534 24414\n38155 12623 10514\n37049 24269 5317\n47360 7604 785\n28507 19498 16031\n25087 19595 12326\n46341 5172 788\n48476 23309 26309\n32890 5451 2102\n46947 14695 23495\n50409 3813 2717\n37149 3065 16724\n50307 19199 12210\n30319 13667 6902\n26909 4049 4713\n26657 5245 13784\n35935 15307 15758\n40814 10351 18842\n48553 3893 6384\n44637 8129 6772\n36270 6994 18687\n50826 21507 11262\n43605 948 5745\n37116 1509 14485\n41346 2491 25302\n50731 25727 19351\n37356 18584 26448\n32976 19572 22929\n44454 4450 10466\n25874 811 3979\n49872 25100 22276\n48193 21824 23597\n34263 4275 11174\n25710 24274 22351\n26740 8197 15808\n38613 16732 11492\n44147 2703 5359\n27458 14054 23526\n35208 17097 16785\n38004 16008 20568\n45202 7854 24099\n26318 20802 21682\n32356 824 26013\n37768 11609 25684\n38814 826 826\n25127 1347 24214\n28117 241 11860\n29916 5712 4813\n27135 9342 4195\n38731 8930 1967\n26393 12789 9149\n43789 500 19401\n29867 20810 24066\n38199 9763 587\n33384 24161 897\n48916 5920 13544\n25138 838 13659\n26158 26687 24727\n41009 19824 4496\n35813 13060 1284\n47627 24962 9559\n45658 26854 11534\n31768 844 15500\n37705 3624 1709\n35714 846 1718\n37243 4714 21882\n36033 15069 11112\n25568 21628 23076\n47227 17639 26058\n39234 15363 7574\n50901 852 15825\n49260 24968 16520\n44562 1995 9910\n28142 4298 4703\n34625 22197 8557\n43149 4740 26476\n28990 21591 858\n38015 7883 17054\n47789 1508 25956\n24452 8400 6880\n47319 862 5915\n51283 26639 17703\n28345 25013 14960\n37616 1977 10460\n29302 12151 9719\n39946 7462 3571\n27408 19945 19201\n26932 3741 25309\n28895 15043 8699\n24699 2386 17767\n42260 872 872\n38056 9969 4729\n25934 21447 25559\n49671 10926 3558\n50781 12724 14476\n35292 877 9901\n36778 11995 9838\n47235 12746 15314\n33977 880 4920\n47576 9548 16004\n29387 14527 12274\n32215 1390 6534\n37208 18921 14001\n49156 3544 23880\n44298 886 26011\n24526 11026 22418\n46345 1597 13808\n29917 889 10292\n45315 1994 9018\n25546 17470 15267\n40917 7417 15945\n25801 12312 16509\n47087 26243 9467\n27243 895 1986\n38377 8253 23104\n36336 18417 26212\n44811 2791 2218\n24431 6998 26267\n47317 900 13729\n37892 901 12648\n25202 8179 9243\n51211 21826 24826\n36849 15093 18965\n48021 15052 20817\n31062 11658 18722\n24930 13771 107\n51240 22044 1604\n38585 20165 13085\n33210 23019 94\n28827 22010 3978\n49804 21048 26621\n45704 5780 15289\n33923 23842 12834\n24474 12206 203\n39192 25252 8164\n36009 12064 15448\n47975 6907 22318\n35707 5127 3458\n46585 13344 2557\n40096 11745 22313\n36091 24607 3074\n41711 13630 17179\n47493 22660 25121\n24516 20224 9581\n43751 14267 13678\n34203 3226 3135\n37385 928 24869\n25408 10980 14105\n31430 12175 22546\n24450 366 17347\n49797 22929 4564\n40404 5229 16832\n50783 9774 9611\n40502 12426 22346\n48356 936 26184\n46933 1153 16604\n31779 16898 21154\n43242 2499 22603\n45621 7516 19684\n29364 24744 14845\n36506 14787 7534\n50118 6159 239\n32764 7656 16093\n50560 4489 16225\n47782 13151 7370\n30258 24494 17454\n37565 5425 12625\n41580 4904 24917\n29530 26883 7766\n45643 9562 1722\n32428 9448 13109\n45320 20460 21260\n29531 17058 10463\n27775 24350 15459\n50621 4913 21324\n41148 7032 22336\n26207 20366 21219\n49710 14351 1463\n25260 26901 19856\n33789 4228 25404\n47254 18314 15410\n35602 963 16982\n27709 22004 457\n30521 15976 26133\n36159 2891 26526\n48139 16679 9034\n25268 18400 14325\n25872 23732 12212\n26790 970 10826\n33018 24067 26547\n34725 18033 977\n43609 997 16400\n32122 16374 14358\n25614 22394 13671\n34497 7056 3816\n34480 8444 16249\n29670 25338 15527\n33762 15102 22542\n31949 4993 20905\n38116 11104 22944\n25591 23110 21211\n26334 8402 11503\n51001 25392 18064\n48653 16332 24356\n39491 17391 23570\n28351 17998 11875\n36512 15985 6236\n40601 8645 16941\n31143 14603 10427\n33678 991 1714\n32673 15541 22112\n29760 13500 12353\n29747 4122 15727\n45554 9347 995\n32152 11668 19097\n28817 25168 10765\n35055 23902 11294\n48038 14719 4130\n34689 7021 23480\n37432 18577 1548\n47462 6111 21898\n33002 25547 16571\n30304 9609 5060\n32121 6869 20384\n41327 1006 15339\n33275 1007 4690\n32481 25461 1008\n46104 1009 9313\n50667 10551 10855\n43199 1011 25699\n48232 988 21729\n41724 7192 21221\n27959 14374 9011\n41814 22671 20383\n45556 25205 19176\n39157 20380 20657\n50654 23055 6047\n26626 1019 8542\n28333 5588 21953\n47868 15509 13392\n35778 1022 2326\n39179 21383 439\n33884 4072 19317\n35557 3020 18457\n32979 7218 10402\n31418 14342 20734\n46560 18140 22788\n28260 20813 11712\n30202 18059 8926\n48726 21274 9479\n50921 21488 21016\n33432 1033 25561\n42995 1034 25058\n47218 7430 25550\n25688 6604 23220\n45985 14216 24744\n44154 20798 21963\n45523 24735 23058\n29905 1040 24709\n47696 19220 22212\n25342 14007 12482\n50223 1787 24470\n34221 9521 14252\n50532 16032 6448\n28250 23043 15814\n25147 9967 24751\n34564 1048 24200\n39525 17273 7425\n26390 20871 20490\n26322 4806 15942\n27856 1633 3545\n26276 7584 11861\n37815 21766 6798\n42670 15642 26378\n32372 24181 1496\n33957 8289 14644\n29118 10514 17567\n30250 16091 16987\n38232 3569 1060\n29521 13733 4349\n32818 24539 14131\n27510 18402 12362\n36489 1064 13045\n48320 15804 24641\n49243 9031 11375\n43287 26715 20830\n41093 21681 12449\n44905 1376 10109\n50266 25179 8214\n35142 2554 19423\n33801 22453 16080\n48957 22737 9164\n40707 12834 6215\n49114 23254 3075\n37653 1076 11684\n44868 12864 18493\n29562 6878 10955\n31467 1079 11639\n38569 21669 9288\n35757 23012 9761\n41203 18218 9023\n29858 25926 4267\n29013 1084 14361\n24844 24045 18309\n40482 571 20806\n34830 22370 18682\n47097 1560 26453\n41021 17137 13297\n41467 1834 6679\n29831 10859 18283\n47109 13636 2873\n32844 3248 752\n45895 1094 15795\n43038 11415 19807\n40873 8101 13216\n45192 1097 436\n29611 11295 16207\n28575 24582 7742\n39389 25553 10545\n40532 13864 20133\n26778 22342 15470\n34694 11722 466\n27100 22968 1733\n34192 21985 7268\n25854 7495 1106\n32930 15182 9270\n28880 745 21172\n30868 19024 21821\n37402 4374 5587\n30262 26570 20794\n39569 19085 20149\n29261 1113 11020\n25699 14503 17162\n41626 1115 302\n29056 1876 24849\n28980 12461 19413\n45066 18542 3067\n44355 24658 4066\n37604 20757 13312\n44384 18065 16705\n46846 10735 15138\n25834 2358 13003\n31856 10657 2556\n48372 24888 3304\n36295 2806 17059\n27395 4850 24242\n32569 14125 23157\n49496 8188 18404\n30350 5426 9810\n29498 21110 3382\n43584 8729 2937\n50089 1133 3277\n44703 1134 12987\n33515 25058 10338\n29628 1368 3072\n25437 17724 9100\n39723 7511 20970\n46159 13203 24323\n25720 26772 25860\n38444 9285 12096\n30074 17795 23627\n39907 16354 13871\n29164 13912 13384\n27608 132 16049\n26827 1146 19223\n39122 3214 8838\n25448 1148 17004\n25836 5328 3360\n47146 17070 9547\n34390 24375 4186\n48028 3397 20125\n25616 22577 3628\n32182 11610 6698\n37226 5782 6819\n40632 24937 11340\n32396 3768 5765\n25607 1158 24363\n40339 15463 18503\n41465 1160 19885\n46928 22737 20892\n27779 11834 6775\n45879 14326 15675\n47192 14908 9001\n48020 25760 12549\n27850 6131 15659\n27830 1167 7898\n39969 1168 7933\n36928 19737 19377\n28411 999 14106\n41546 24790 10926\n34485 11276 23057\n25473 4576 25520\n37791 23574 13179\n26926 7394 554\n33956 14520 4592\n35696 12252 12561\n37931 21479 1178\n27138 2062 9867\n45533 7721 1116\n50081 15008 1181\n41487 26219 21846\n32262 9831 25690\n37361 17325 25072\n30912 20276 9441\n35387 18114 15762\n41378 16579 1187\n27013 11620 17953\n25489 24384 18149\n43146 8931 26686\n44974 11274 24546\n26868 1192 9016\n48245 17801 8532\n36555 1354 22890\n41986 22574 8835\n37941 12628 4313\n30289 25741 18109\n41495 1198 1198\n40987 11543 20250\n32892 5136 22064\n47752 11817 10300\n51014 8319 6687\n40074 1203 19003\n47304 23596 24841\n37532 8997 13357\n27346 10931 23438\n44558 511 58\n48705 13837 19509\n38088 18588 2172\n31963 22015 3442\n50482 10059 686\n39381 23089 22524\n43100 6349 23613\n36431 5502 1214\n24875 22594 20586\n32601 17336 8853\n29312 21385 5241\n29203 1218 16143\n31042 21638 12411\n38301 2148 8169\n45361 1896 10269\n48722 1222 17107\n28531 6487 9879\n28884 24544 9568\n41661 17841 12225\n25779 21162 18135\n28738 14790 16198\n35224 17745 9812\n47356 23973 20861\n28850 3939 9747\n42614 7778 12327\n38396 9445 25848\n49389 20916 19604\n48238 18834 16546\n32135 9046 1014\n31773 1628 14257\n46268 1237 22085\n29327 1238 18886\n49062 23687 17938\n27097 1240 21557\n30141 23212 15249\n25542 1242 9287\n28191 13870 14515\n24621 14593 10537\n33068 3080 14296\n47986 26971 15299\n42318 17130 3226\n35201 25437 7429\n50248 18324 14108\n33235 19231 17082\n32423 1251 26419\n39560 2873 4932\n45372 24344 26165\n44743 1955 10246\n36550 1255 10538\n32148 1256 20485\n36896 26348 1473\n29742 14898 18071\n49690 9966 8195\n40501 1260 5020\n24865 1101 18160\n33410 20846 21310\n26843 23458 20962\n47681 16365 1264\n43965 1265 19668\n38422 25463 7826\n50607 1814 23406\n36600 23444 18217\n43916 19984 16656\n33946 19798 1758\n47574 8919 13034\n40116 1272 14952\n36565 732 9457\n51030 1274 6834\n35506 10222 4115\n32341 14673 24220\n49793 20712 21869\n37215 6675 339\n35422 1279 25138\n25972 6512 13525\n48680 1281 10796\n34627 16799 10519\n40834 22230 20451\n49421 7108 21228\n45692 4541 25549\n51239 15822 17790\n47667 1287 25274\n37593 9424 26037\n45861 21916 13396\n28035 6855 23138\n28727 5539 9003\n41925 19697 1884\n24708 736 4061\n37346 3323 26307\n28675 24154 3714\n31684 19608 17856\n44216 5740 24972\n41046 22407 12359\n44026 18739 5422\n25093 3033 15161\n51220 1845 17333\n28626 1302 11963\n28915 17335 20714\n50601 5613 5029\n32400 12116 16996\n50963 19186 2682\n39127 18382 20163\n24981 8385 15700\n30652 1309 8808\n48367 13563 19214\n37467 9954 18602\n28380 20621 6957\n50032 3665 8225\n39446 19450 10903\n47303 20035 4979\n40488 4153 188\n48692 24720 965\n30314 23750 475\n34886 4799 6362\n40444 14248 24773\n25621 1377 12889\n47630 6103 1943\n34218 2158 20075\n40448 15809 22236\n37913 12173 1821\n43082 1326 12502\n27430 20090 1498\n50812 1976 2869\n32349 11657 2196\n32563 1330 4978\n25631 18782 24395\n48896 1332 12436\n48868 26693 3920\n44559 7158 12483\n50174 10490 21658\n40033 1336 21565\n47837 18833 16780\n41934 18954 6207\n43415 9822 6867\n32336 4356 19156\n50697 16160 8472\n33919 2134 11838\n48163 15919 10978\n44692 3869 1792\n28837 24697 4505\n34499 14850 3191\n44234 20894 23270\n47221 22289 11977\n30220 4021 128\n39594 24702 5667\n43102 22215 14167\n26700 7333 11208\n44981 6689 9881\n44027 26031 26439\n33810 21219 11859\n28725 1356 17780\n42633 23856 13184\n46714 22883 12235\n30190 5191 4698\n25129 5181 26864\n50085 17697 425\n33862 15991 22535\n32119 4731 20606\n48325 10289 16060\n46212 9296 640\n45610 830 14915\n40630 11199 11394\n49313 23336 3301\n42776 14009 5276\n38326 5967 17402\n37799 9947 8094\n38768 20945 9268\n35369 11888 18136\n27858 1374 24651\n38195 1375 25263\n41569 18672 8928\n36232 21988 22900\n41803 6962 22279\n25655 379 18795\n25680 1908 23225\n41137 6632 168\n37783 26662 6283\n30614 26711 14399\n29993 24320 3397\n25357 10204 19964\n33691 12954 24346\n47751 20323 4486\n41496 1428 21628\n41236 64 10200\n26770 1467 7411\n39030 10042 19226\n47457 25888 13661\n24304 617 12644\n36483 9375 20183\n50551 1395 22987\n41368 8692 10988\n43900 16413 23037\n29783 16723 1398\n38107 4650 16994\n43196 19917 7637\n48277 20457 17449\n48643 24567 13890\n38474 16814 8219\n45752 10793 15561\n28633 2800 26637\n47242 2987 803\n26718 11943 11663\n44700 12160 13533\n33336 1409 16577\n27790 25999 6135\n44194 10606 22494\n49125 8489 15748\n40292 3893 17760\n45170 1414 14214\n46638 9079 3983\n35057 19693 22445\n50704 16097 26516\n44358 16447 22527\n37082 6043 11382\n39136 17121 11609\n43113 11736 4445\n40698 3203 22067\n27758 1423 16682\n46988 22885 9869\n42197 7356 676\n29075 26975 359\n37807 1427 19790\n25728 12860 7081\n50228 2024 13336\n41175 9219 1051\n46214 1431 21978\n28788 21293 2944\n45069 1433 2412\n31846 1434 383\n32458 15238 10363\n25237 12108 20489\n48969 17389 10029\n44231 3142 25803\n37163 9407 26506\n48993 11045 22621\n43848 2113 15924\n46886 16335 20674\n45943 1443 16406\n32149 15305 14676\n35340 6888 6005\n35743 23430 12678\n40179 21858 21423\n33508 11037 9632\n38656 21468 20601\n34710 10343 18706\n42386 1758 13227\n43397 8521 10977\n27476 1453 12021\n28887 18886 20051\n25451 1455 1711\n41761 17637 18512\n39608 24265 6401\n35358 8218 24023\n34706 15470 20979\n28952 22153 21681\n25780 2781 13152\n36671 9582 8971\n51150 15866 522\n44404 17408 26957\n29776 1465 6337\n45587 7546 19418\n30562 1211 22955\n45781 18516 26697\n29313 23008 17301\n37431 1470 8043\n25731 24007 7658\n25457 5149 21701\n27208 22225 2092\n29627 22015 1095\n29210 2702 9211\n50349 5572 11065\n32425 14853 280\n46879 25046 5195\n30803 8903 4178\n49284 10288 2597\n28648 20097 1908\n43067 1482 11967\n44530 1363 26731\n30165 16540 1124\n45337 13248 2864\n29223 8798 7915\n25766 1487 11362\n26436 2448 10941\n35253 18369 6225\n25275 3274 25607\n46239 14467 17339\n50992 18868 23884\n39884 23576 1528\n37386 1494 23027\n49158 1495 9423\n47756 6501 3517\n37773 12905 24425\n36891 14439 8159\n48922 3366 26966\n39405 5828 22497\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/input/Main.hs",
    "content": "module Main where\n\nimport Sort\n\nimport Control.Monad (replicateM_)\nimport Data.List (intersperse)\nimport System.Environment (getArgs)\nimport NofibUtils (hash)\n\nmain = do\n  (n:_) <- getArgs\n  replicateM_ (read n) $ do\n    (_:s:_) <- getArgs\n    f <- readFile s\n    print (hash (mangle f))\n\nmangle :: String{-input to sort-} -> String{-output-}\nmangle inpt\n  = (unlines . sort . lines) inpt\n  where\n    sort = foldr (.) id (intersperse reverse sorts)\n    sorts =\n      [ heapSort\n      , insertSort\n      , mergeSort\n      , quickSort\n      , quickSort2\n      , quickerSort\n      , treeSort\n      , treeSort2\n      ]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/input/heathcote3.prob",
    "content": "-- G. Heathcote\n-- Reading Observer, 1904\n-- `A charming little three-mover constructed with\n-- the art that conceals art.'  (Phillips)\n\n- - - - - - - - \n- - - - - - - - \n- - - - - - - - \n- - - - P - - - \n- - - - p - k b \n- P n - K - - - \n- P - - - - - - \n- q - - - - - - \n\nWhite to play and mate in 3\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/input/rsa.faststdin",
    "content": "module Rsa (encrypt, decrypt, makeKeys)\nwhere\n\n\nencrypt, decrypt :: Integer -> Integer -> String -> String\nencrypt n e = unlines . map (show . power e n . code) . collect (size n)\ndecrypt n d = concat . map (decode . power d n . read) . lines\n\n-------- Converting between Strings and Integers -----------\n\ncode :: String -> Integer\ncode = foldl accum 0\n  where accum x y = (128 * x) + fromIntegral (fromEnum y)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/integer.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/integer.mls\"\ninteger.main()\n//│ = \"[true,false,false,false,false,false,true,true,false,false,false,false,true,true,true,false,false,false,true,true,true,true,false,false,true,true,true,true,true,false,true,true,true,true,true,true]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/knights.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/knights.mls\"\nprint(knights.main())\n//│ > \n//│ > Knights tour with 0 backtracking moves\n//│ > 1  34 3  18 41 32 13 16\n//│ > 4  19 64 33 14 17 44 31\n//│ > 35 2  37 40 63 42 15 12\n//│ > 20 5  56 47 38 45 30 43\n//│ > 55 36 39 62 57 48 11 26\n//│ > 6  21 52 49 46 27 60 29\n//│ > 51 54 23 8  61 58 25 10\n//│ > 22 7  50 53 24 9  28 59\n//│ > \n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/lambda.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/lambda.mls\"\nlambda.main()\n//│ = \"[\\\"C\\\",\\\"o\\\",\\\"n\\\",\\\" \\\",\\\"3\\\",\\\"2\\\",\\\"4\\\",\\\"0\\\"],[\\\"3\\\",\\\"2\\\",\\\"4\\\",\\\"0\\\",\\\" \\\",\\\" \\\",\\\"[\\\",\\\"]\\\"]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/last-piece.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/lastpiece.mls\"\nprint of\n  lastpiece.main()\n//│ > Success!\n//│ >   accchhff\n//│ >   aacnghhf\n//│ >   innnglhf\n//│ >   inmggllf\n//│ >   iimgelkk\n//│ >   dimeelkb\n//│ >   dmmejkkb\n//│ >   ddjjjjbb\n//│ >   \n//│ > Success!\n//│ >   acccjjjj\n//│ >   aacffjgb\n//│ >   hhddfggb\n//│ >   lhhdfgbb\n//│ >   llhdfgnm\n//│ >   lkkennnm\n//│ >   lkeeniim\n//│ >   kkeiiimm\n//│ >   \n//│ > Success!\n//│ >   ammmmccc\n//│ >   aaiimnch\n//│ >   iiinnnhh\n//│ >   gggnlhhj\n//│ >   fkgglljj\n//│ >   fkkklbdj\n//│ >   feeklbdj\n//│ >   ffeebbdd\n//│ >   \n//│ > \n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/lcss.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/lcss.mls\"\nlcss.main()\n//│ = \"[30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60]\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/life.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/life.mls\"\nlife.main()\n//│ = 468\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/mandel.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/mandel.mls\"\nmandel.main()\n//│ = Pixmap(\n//│   25,\n//│   25,\n//│   75,\n//│   [[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[5, 70, 70],[5, 70, 70],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[4, 71, 71],[14, 61, 61],[55, 20, 20],[4, 71, 71],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[6, 69, 69],[6, 69, 69],[59, 16, 16],[75, 0, 0],[7, 68, 68],[5, 70, 70],[4, 71, 71],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[4, 71, 71],[5, 70, 70],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[39, 36, 36],[23, 52, 52],[3, 72, 72],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[6, 69, 69],[6, 69, 69],[6, 69, 69],[9, 66, 66],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[8, 67, 67],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[3, 72, 72],[4, 71, 71],[6, 69, 69],[19, 56, 56],[75, 0, 0],[24, 51, 51],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[24, 51, 51],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[5, 70, 70],[6, 69, 69],[18, 57, 57],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[6, 69, 69],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[5, 70, 70],[6, 69, 69],[18, 57, 57],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[6, 69, 69],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[3, 72, 72],[3, 72, 72],[4, 71, 71],[6, 69, 69],[19, 56, 56],[75, 0, 0],[24, 51, 51],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[24, 51, 51],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[6, 69, 69],[6, 69, 69],[6, 69, 69],[9, 66, 66],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[8, 67, 67],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[4, 71, 71],[4, 71, 71],[5, 70, 70],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[75, 0, 0],[39, 36, 36],[23, 52, 52],[3, 72, 72],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[6, 69, 69],[6, 69, 69],[59, 16, 16],[75, 0, 0],[7, 68, 68],[5, 70, 70],[4, 71, 71],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[4, 71, 71],[14, 61, 61],[55, 20, 20],[4, 71, 71],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[3, 72, 72],[3, 72, 72],[5, 70, 70],[5, 70, 70],[3, 72, 72],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[2, 73, 73],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[1, 74, 74],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75],[0, 75, 75]]\n//│ )\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/mandel2.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/mandel2.mls\"\nmandel2.main()\n//│ = true\n\n      \n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/mate.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/mate.mls\"\nprint(mate.main())\n//│ >  - - - - - - - -\n//│ >  - - - - - - - -\n//│ >  - - - - - - - -\n//│ >  - - - - P - - -\n//│ >  - - - - p - k b\n//│ >  - P n - K - - -\n//│ >  - P - - - - - -\n//│ >  - q - - - - - -\n//│ > \n//│ > White to move and mate in 3\n//│ > \n//│ > 1. N/QB3-QR2,\n//│ >  if K-Q5; 2. B/KR4-KB2, K-QB5; 3. Q/QN1-KB1++\n//│ >  if K-Q7; 2. K-KB3, P/QN6xN/QR7; 3. B/KR4-K1++\n//│ >  if K-K7; 2. N/QR2-QN4,\n//│ >   if K-Q7; 3. Q/QN1-K1++\n//│ >   if K-K6; 3. Q/QN1-Q3++\n//│ >  if P/QN6xN/QR7; 2. Q/QN1-QB2, ...; 3. B/KR4-KB2++\n//│ > \n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/minimax.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/minimax.mls\"\nprint(minimax.main())\n//│ > OXO\n//│ > XWin\n//│ > X|O| \n//│ > ------\n//│ >  |X| \n//│ > ------\n//│ >  | | \n//│ > \n//│ > XWin\n//│ > X|O|O\n//│ > ------\n//│ >  |X| \n//│ > ------\n//│ >  | | \n//│ > \n//│ > XWin\n//│ > X|O|O\n//│ > ------\n//│ > X|X| \n//│ > ------\n//│ >  | | \n//│ > \n//│ > XWin\n//│ > X|O|O\n//│ > ------\n//│ > X|X|O\n//│ > ------\n//│ >  | | \n//│ > \n//│ > XWin\n//│ > X|O|O\n//│ > ------\n//│ > X|X|O\n//│ > ------\n//│ > X| | \n//│ > \n//│ > \n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/para.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/para.mls\"\npara.main()\n//│ = \"In the constructive programming community it is commonplace to\\nsee formal developments of textbook algorithms. In the algorithm\\ndesign community, on the other hand, it may be well known that\\nthe textbook solution to a problem is not the most efficient\\npossible. However, in presenting the more efficient solution, the\\nalgorithm designer will usually omit some of the implementation\\ndetails, this creating an algorithm gap between the abstract\\nalgorithm and its concrete implementation. This is in contrast\\nto the formal development, which usually presents the complete\\nconcrete implementation of the less efficient solution.\\n\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/power.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/power.mls\"\npower.main()\n//│ = \"[0,1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012]\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/pretty.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/pretty.mls\"\npretty.main()\n//│ = \"-42@This is a string\\n, \\nThis is the label\\n\\txxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx xxxxx\\n\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/primetest.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/primetest.mls\"\nprimetest.main()\n//│ = \"[\\\"Composite\\\",\\\"Composite\\\",\\\"Probably prime\\\",\\\"Composite\\\",\\\"Composite\\\"]\"\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/puzzle.mls",
    "content": ":js\n\n\n:re // nodejs stack size 8192 can handle this\nimport \"../../mlscript-compile/nofib/puzzle.mls\"\npuzzle.main()\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\n// // │ > Solution 1\n// // │ > Time: 0\n// // │ > ----------------------------------------\n// // │ >     Bono |                    |\n// // │ > The Edge |                    |\n// // │ >    Larry |                    |\n// // │ >     Adam |                    |\n// // │ > ----------------------------------------\n// // │ > Time: 2\n// // │ > ----------------------------------------\n// // │ >     Bono |                    |\n// // │ > The Edge |                    |\n// // │ >          |                    | Larry\n// // │ >          |                    | Adam\n// // │ > ----------------------------------------\n// // │ > Time: 3\n// // │ > ----------------------------------------\n// // │ >     Bono |                    |\n// // │ > The Edge |                    |\n// // │ >          |                    | Larry\n// // │ >     Adam |                    |\n// // │ > ----------------------------------------\n// // │ > Time: 13\n// // │ > ----------------------------------------\n// // │ >          |                    | Bono\n// // │ >          |                    | The Edge\n// // │ >          |                    | Larry\n// // │ >     Adam |                    |\n// // │ > ----------------------------------------\n// // │ > Time: 15\n// // │ > ----------------------------------------\n// // │ >          |                    | Bono\n// // │ >          |                    | The Edge\n// // │ >    Larry |                    |\n// // │ >     Adam |                    |\n// // │ > ----------------------------------------\n// // │ > Time: 17\n// // │ > ----------------------------------------\n// // │ >          |                    | Bono\n// // │ >          |                    | The Edge\n// // │ >          |                    | Larry\n// // │ >          |                    | Adam\n// // │ > ----------------------------------------\n// // │ > Solution 2\n// // │ > Time: 0\n// // │ > ----------------------------------------\n// // │ >     Bono |                    |\n// // │ > The Edge |                    |\n// // │ >    Larry |                    |\n// // │ >     Adam |                    |\n// // │ > ----------------------------------------\n// // │ > Time: 2\n// // │ > ----------------------------------------\n// // │ >     Bono |                    |\n// // │ > The Edge |                    |\n// // │ >          |                    | Larry\n// // │ >          |                    | Adam\n// // │ > ----------------------------------------\n// // │ > Time: 4\n// // │ > ----------------------------------------\n// // │ >     Bono |                    |\n// // │ > The Edge |                    |\n// // │ >    Larry |                    |\n// // │ >          |                    | Adam\n// // │ > ----------------------------------------\n// // │ > Time: 14\n// // │ > ----------------------------------------\n// // │ >          |                    | Bono\n// // │ >          |                    | The Edge\n// // │ >    Larry |                    |\n// // │ >          |                    | Adam\n// // │ > ----------------------------------------\n// // │ > Time: 15\n// // │ > ----------------------------------------\n// // │ >          |                    | Bono\n// // │ >          |                    | The Edge\n// // │ >    Larry |                    |\n// // │ >     Adam |                    |\n// // │ > ----------------------------------------\n// // │ > Time: 17\n// // │ > ----------------------------------------\n// // │ >          |                    | Bono\n// // │ >          |                    | The Edge\n// // │ >          |                    | Larry\n// // │ >          |                    | Adam\n// // │ > ----------------------------------------\n// // │ > \n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/rsa.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/rsa.mls\"\nrsa.main()\n//│ = 27333540773077035891319648583115426924319682304972207061138531859687685497972324052329603672575247712822051033469833084249533708345668063349995687590898179232348381885068093916042332376874471111951277359240086024689478630903872483533692492045159120070581960228683268092981264305946420008131657132188411691046890656423813430758797867405414254427252889799598265252801351427969270327221859277538276931835433884202770274573975497479910055419604950116998779489424711382329456954759006285308055617249211518517251626537584144819963887585424355716160948313809816237911911714261525254960504461968887058634176692781918761529885191647640353988451378487593523928746420834635489374763284035135024554501992592243054651704669361294874639088141090295124111150498567814209355019358035109087855352831799613561922371560229756096541243234407756387955273981612894548796096568181979612805473591487774278882312329731123289196221054300160041623910405907021509065754120986913156062146884015988300349866352421512547114991188706014109057361892879580430212109312752658248376273202302160796406164353595904770530340704402942462200108055227350082862003023696909347848580847463903352486983305887517122394068078234691266091519485573727824252527733372590392886198860292659649377855405883044150450559660371076194186374359910112808222171852893169058046390627297042238730809765588373104750n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/scc.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/nofib/scc.mls\"\nscc.main()\n//│ = \"[[1],[2],[7,5,6],[3,4]]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/secretary.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/secretary.mls\"\nsecretary.main()\n//│ = \"[0.3,0.3,0.3,0.34,0.36]\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/sorting.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/sorting.mls\"\nsorting.main()\n//│ = 51324117188054929115411819706576305711291550658570113274291768822777898552447837804420193403034280334581113235670099168108057310001444698188883902000871912629747889286942274533143362191347715770581074120684028066661549409447053566864805982796651442411825424058139343253169753750307013113236996387277789074623630137288987589869641913268610508598505040964906263227437054452571059796961267985287441539342423613634888118731387934522320394294636575704912348025851038478882488022787377510287490741895262233989080994241592338442788051616303082788441666485156091668196999668892850523930511918729736856089560984406499736606084171798216360770991023233180481976810767432750226966921480421914178641779179040473344962763594357880599983085435482161632405644389584578524102239884780307588440751057343783694537559222924711205140877849398042544407611747227163056408231621727687968160470282720794027470616537695447289808133239223198869n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/sphere.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/nofib/sphere.mls\"\nsphere.main()\n//│ = 5303517076988315313332949801059915491159227238911114869988477691048042454660240028235263286419219487056215941279053460510402913638191134284712332734906453769177119866479549825710564164275378353165954211251783583776613466486364346857260327927988942302708582821755390617347892889203137614326710267631036346563969292879841889783895830486185094255970382302038580666396338511666737651046972647664365680026395064916507788381669683616268208254545568013323075147569343527502482992453415977736934966646039451380029114116189124196276320031764844380624699920031305131672697387138852897706575918870327168611841752330951914241998117147850328297747558099955601889252104175852174057287066122859365466714696330034330699419079661953966001855819730466637347813009964893758393398194456345159379187006376036876209312080525632387380670119254556148852520127502599030787981579016179740021934386773631075580149533017386555553650112461351624483964765154488441338857870911043358714412530793575995251653967501366725439356901586292297118595437194582661104059821332957540366106419721198265755243343224842512131366898546251377194773492369372328808207397107344802194547364640358333075609512226775541628703229778371160920064859614452908773471314342954366183109912759985134547433205776906834992238207194263830836275456360444786309396200054415810563334317160702817096977297265083167419253864506146719603442916146256166128051227049046678660445048488558024838465181996990391375870148258607829684558969016638984826787347541150003498463027973936442463090071589323955227296902474986841480537918878837478902992973202305608637036765245465738479448312n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/nofib/treejoin.mls",
    "content": ":js\n\n:re // nodejs stack size 8192 can handle this\nimport \"../../mlscript-compile/nofib/treejoin.mls\"\ntreejoin.main()\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\n// //│ = 'Node(26790, Node(25449, Node(24977, Node(24359, Node(24314, Leaf(24314, (9658,1890,24314,24314,7755)), Leaf(24359, (17282,5066,24359,24359,134))), Node(24452, Leaf(24452, (13985,4700,24452,24452,8400)), Node(24776, Leaf(24776, (9392,18824,24776,24776,25492)), Leaf(24977, (21044,6260,24977,24977,3296))))), Node(25347, Node(25087, Leaf(25087, (9226,22666,25087,25087,19595)), Leaf(25347, (9331,1734,25347,25347,12071))), Leaf(25449, (24361,14401,25449,25449,5552)))), Node(26770, Node(26207, Node(25780, Node(25457, Leaf(25457, (5457,5273,25457,25457,5149)), Leaf(25780, (21801,92,25780,25780,2781))), Leaf(26207, (22839,18759,26207,26207,20366))), Node(26436, Node(26274, Node(26222, Leaf(26222, (11315,3470,26222,26222,23055)), Leaf(26274, (19231,20706,26274,26274,24107))), Node(26276, Leaf(26276, (3545,169,26276,26276,7584)), Leaf(26436, (22148,24244,26436,26436,2448)))), Node(26473, Leaf(26473, (13180,15097,26473,26473,16469)), Leaf(26770, (23746,15943,26770,26770,1467))))), Leaf(26790, (25643,16230,26790,26790,970)))), Leaf(26932, (24868,11500,26932,26932,3741)))'\n\n  \n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/objbuf/Basics.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/ObjectBuffer.mls\"\nopen ObjectBuffer\nopen annotations\n\n\n@buffered\nclass A(x) with\n  fun f(y) = x + y\n\n@bufferable\nclass A2(x) with\n  fun f(y) = x + y\n\n:ge\n@buffered\n@buffered\nclass B1(x)\n//│ ╔══[COMPILATION ERROR] Only one of bufferable annotation is allowed.\n//│ ║  l.17: \t@buffered\n//│ ║        \t^^^^^^^^^\n//│ ║  l.18: \t@buffered\n//│ ╙──      \t^^^^^^^^^\n\n:ge\n@buffered\n@bufferable\nclass B2(x)\n//│ ╔══[COMPILATION ERROR] Only one of bufferable annotation is allowed.\n//│ ║  l.27: \t@buffered\n//│ ║        \t^^^^^^^^^\n//│ ║  l.28: \t@bufferable\n//│ ╙──      \t^^^^^^^^^^^\n\n:w\n@bufferable\nmodule B3\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.37: \t@bufferable\n//│ ╙──      \t^^^^^^^^^^^\n\n:w\n@bufferable\nobject B3\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.44: \t@bufferable\n//│ ╙──      \t^^^^^^^^^^^\n\n\nlet buf = new DefaultObjectBuffer(10)\n//│ buf = DefaultObjectBuffer(_)\n\nlet obj1 = buf.mkNew(A)(3)\n//│ obj1 = 0\n\nlet obj2 = buf.mkNew(A)(5)\n//│ obj2 = 2\n\nA.f(buf, obj1)(1)\n//│ = 4\n\nA.f(buf, obj2)(1)\n//│ = 6\n\nbuf.del(A, obj1)\n\nlet obj3 = buf.mkNew(A)(10)\n//│ obj3 = 0\n\n// UAF\nA.f(buf, obj1)(1)\n//│ = 11\n\nA.f(buf, obj3)(1)\n//│ = 11\n\n\n@bufferable\nclass Oops with\n  fun hi = print(\"hi\")\n\nlet obj1 = buf.mkNew(Oops)\n//│ obj1 = 0\n\n\nOops.hi(buf, obj2)\n//│ > hi\n\nlet obj2 = buf.mkNew(A)(3)\n//│ obj2 = 4\n\nA.f(buf, obj2)(1)\n//│ = 4\n\nbuf.del(Oops, obj1)\n\n:expect 4\nA.f(buf, obj2)(1)\n//│ = 4\n\n\n@buffered\nclass A(x) with\n  val z = x\n  fun f(y) = x + y + z\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/objbuf/Mutation.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/ObjectBuffer.mls\"\nopen ObjectBuffer\nopen annotations\n\n\n:fixme // TODO: fix IR rebinding issue (each symbol should be bound at most once)\n:checkIR\n@bufferable\nclass A() with\n  let z = 0\n  set z += 1\n//│ ═══[INTERNAL ERROR] [BlockChecker] Invalid IR: symbol tmp:tmp⁰ is bound more than once\n\n\n:sjs\n@bufferable\nclass A(x) with\n  mut val z = x\n  fun f(y) =\n    set x += 1\n    set z += 2\n    x\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let A3;\n//│ A3 = function A(x) {\n//│   return globalThis.Object.freeze(new A.class(x));\n//│ };\n//│ (class A2 {\n//│   static {\n//│     A3.class = this\n//│   }\n//│   constructor(x) {\n//│     this.#x = x;\n//│     this.z = this.#x;\n//│   }\n//│   static {\n//│     this.size = 2;\n//│   }\n//│   static ctor(buf, idx) {\n//│     return (x) => {\n//│       let idx1, idx2, idx3;\n//│       idx3 = idx + 0;\n//│       buf.buf[idx3] = x;\n//│       idx1 = idx + 0;\n//│       idx2 = idx + 1;\n//│       buf.buf[idx2] = buf.buf.at(idx1);\n//│       return idx\n//│     }\n//│   } \n//│   static f(buf, idx) {\n//│     return (y) => {\n//│       let tmp, tmp1, idx1, idx2, idx3, idx4, idx5;\n//│       idx1 = idx + 0;\n//│       tmp = buf.buf.at(idx1) + 1;\n//│       idx5 = idx + 0;\n//│       buf.buf[idx5] = tmp;\n//│       idx2 = idx + 1;\n//│       tmp1 = buf.buf.at(idx2) + 2;\n//│       idx4 = idx + 1;\n//│       buf.buf[idx4] = tmp1;\n//│       idx3 = idx + 0;\n//│       return buf.buf.at(idx3)\n//│     }\n//│   }\n//│   #x;\n//│   #z;\n//│   get z() { return this.#z; }\n//│   set z(value) { this.#z = value; }\n//│   f(y) {\n//│     let tmp, tmp1;\n//│     tmp = this.#x + 1;\n//│     this.#x = tmp;\n//│     tmp1 = this.z + 2;\n//│     this.z = tmp1;\n//│     return this.#x\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"A\", [null]]; \n//│ });\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nlet buf = new DefaultObjectBuffer(10)\n//│ buf = DefaultObjectBuffer(_)\n\nlet obj1 = buf.mkNew(A.class)(3)\n//│ obj1 = 0\n\nlet obj2 = buf.mkNew(A.class)(5)\n//│ obj2 = 2\n\nA.class.f(buf, obj1)(1)\n//│ = 4\n\nA.class.f(buf, obj1)(1)\n//│ = 5\n\nA.class.f(buf, obj2)(1)\n//│ = 6\n\nbuf.del(A.class, obj1)\n\nlet obj3 = buf.mkNew(A.class)(10)\n//│ obj3 = 0\n\n// UAF\nA.class.f(buf, obj1)(1)\n//│ = 11\n\nA.class.f(buf, obj3)(1)\n//│ = 12\n\n\n@bufferable\nclass A(x) with\n  mut val z = x\n  fun f(y) =\n    set z += 1\n    z\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/objbuf/ObjectBufferAllocator.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/ObjectBuffer.mls\"\nopen ObjectBuffer\n\nlet buf = new DefaultObjectBuffer(10)\n//│ buf = DefaultObjectBuffer(_)\n\nbuf.alloc(10)\n//│ = 0\n\nbuf.alloc(1000)\n//│ = 16\n\nbuf.alloc(1)\n//│ = 1016\n\nbuf.free(16, 1000)\n\nbuf.alloc(1)\n//│ = 16\n\nbuf.alloc(1)\n//│ = 18\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/opt/AbortivePrefix.mls",
    "content": ":js\n\n\n// * Note: we properly removed the call to `???`\n:sjs\nfun f =\n  if true then return 1 else return 2\n  (???)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f; f = function f() { let scrut; scrut = true; if (scrut === true) { return 1 } return 2; };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// * Note: we now remove the call to `???` because\n// * the previous block is abortive, which cannot be seen syntactically on the fly\n// * due to the use of an intervening label, but can be simplified by BlockSimplifier.\n:sir\n:soir\nfun f =\n  if true and false then return()\n  (???)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁰;\n//│ define f⁰ as fun f¹() {\n//│   let scrut, scrut1;\n//│   block split_root$:\n//│     block split_default$:\n//│       set scrut = true;\n//│       match scrut\n//│         true =>\n//│           set scrut1 = false;\n//│           match scrut1\n//│             true =>\n//│               return runtime⁰.Unit⁰\n//│             else\n//│               break split_default$\n//│           end\n//│         else\n//│           break split_default$\n//│       end\n//│     throw new globalThis⁰.Error⁰(\"match error\")\n//│   return Predef⁰.notImplementedError⁰\n//│ };\n//│ end\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁰;\n//│ define f⁰ as fun f¹() {\n//│   let scrut, scrut1;\n//│   set scrut = true;\n//│   match scrut\n//│     true =>\n//│       set scrut1 = false;\n//│       match scrut1\n//│         true =>\n//│           return runtime⁰.Unit⁰\n//│         else\n//│           throw new globalThis⁰.Error⁰(\"match error\")\n//│       end\n//│     else\n//│       throw new globalThis⁰.Error⁰(\"match error\")\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sir\n:soir\nfun f =\n  if true and false then return \"1\"\n  else return \"2 long long long long long long long long long long long long long long\"\n  (???)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f²;\n//│ define f² as fun f³() {\n//│   let scrut, scrut1;\n//│   block split_root$:\n//│     block split_1$:\n//│       set scrut = true;\n//│       match scrut\n//│         true =>\n//│           set scrut1 = false;\n//│           match scrut1\n//│             true =>\n//│               return \"1\"\n//│             else\n//│               break split_1$\n//│           end\n//│         else\n//│           break split_1$\n//│       end\n//│     return \"2 long long long long long long long long long long long long long long\"\n//│   return Predef⁰.notImplementedError⁰\n//│ };\n//│ end\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f²;\n//│ define f² as fun f³() {\n//│   let scrut, scrut1;\n//│   set scrut = true;\n//│   match scrut\n//│     true =>\n//│       set scrut1 = false;\n//│       match scrut1\n//│         true =>\n//│           return \"1\"\n//│         else\n//│           return \"2 long long long long long long long long long long long long long long\"\n//│       end\n//│     else\n//│       return \"2 long long long long long long long long long long long long long long\"\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/opt/DeadObjRemoval.mls",
    "content": ":js\n\n\n// * Remove useless objects\n:soir\n:sjs\nfun f() =\n  object A\n  42\nf()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f, inlinedVal; f = function f() { return 42 }; inlinedVal = 42; inlinedVal\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f⁰, inlinedVal; define f⁰ as fun f¹() { return 42 }; set inlinedVal = 42; inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 42\n\n// * Do not remove objects with non-trivial constructors\n:soir\n:sjs\nfun f() =\n  object A with\n    print(\"Hello\")\n  42\nf()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f1;\n//│ f1 = function f() {\n//│   let A1;\n//│   (class A {\n//│     static {\n//│       new this\n//│     }\n//│     constructor() {\n//│       A1 = this;\n//│       Predef.print(\"Hello\");\n//│       Object.defineProperty(this, \"class\", {\n//│         value: A\n//│       });\n//│       globalThis.Object.freeze(this);\n//│     }\n//│     toString() { return runtime.render(this); }\n//│     static [definitionMetadata] = [\"object\", \"A\"]; \n//│   });\n//│   return 42\n//│ };\n//│ f1()\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let f²;\n//│ define f² as fun f³() {\n//│   let A;\n//│   define A as object A⁰ { constructor { do Predef⁰.print⁰(\"Hello\"); end } };\n//│   return 42\n//│ };\n//│ f³()\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > Hello\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/opt/DeadSelRemoval.mls",
    "content": ":js\n\n\n// * It's important that we preserve the call to `???`\n:re\n:soir\nwhile true do ???\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ loop lbl:\n//│   let scrut;\n//│   set scrut = true;\n//│   match scrut\n//│     true =>\n//│       do Predef⁰.notImplementedError⁰;\n//│       continue lbl\n//│     else\n//│       end\n//│   end\n//│ runtime⁰.Unit⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Not implemented\n\n\n:sir\n:soir\ndo\n  val x = 2 + 2\n  val y = print(2)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x⁰, y⁰, tmp, tmp1;\n//│ set tmp = +⁰(2, 2);\n//│ define x⁰ as val x¹ = tmp;\n//│ set tmp1 = Predef⁰.print⁰(2);\n//│ define y⁰ as val y¹ = tmp1;\n//│ runtime⁰.Unit⁰\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ do Predef⁰.print⁰(2); runtime⁰.Unit⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n\n\n:sir\n:soir\nscope.locally of (\n  val x = 1\n  val y = print(2)\n  123\n)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let x², y², tmp;\n//│ define x² as val x³ = 1;\n//│ set tmp = Predef⁰.print⁰(2);\n//│ define y² as val y³ = tmp;\n//│ 123\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ do Predef⁰.print⁰(2); 123\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n//│ = 123\n\n\n// :soir\nmodule Foo with\n  mut val x = 1\n  fun y =\n    set x += 1\n    print(x)\n\nFoo.x\n//│ = 1\n\n// * The first selection is pure and can be removed\n:soir\nFoo.x, Foo.x\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ Foo⁰.x⁴\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// * TODO: also optimize\n:soir\nFoo.x; Foo.x\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ ,⁰(Foo⁰.x⁴, Foo⁰.x⁴)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// * Cannot remove the first selection!\n:soir\n:expect 2\nFoo.y, Foo.x\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ do Foo⁰.y⁴; Foo⁰.x⁴\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n//│ = 2\n\n:soir\n:expect 3\nFoo.y; Foo.x\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ ,⁰(Foo⁰.y⁴, Foo⁰.x⁴)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 3\n//│ = 3\n\n\n:soir\nlet a = Foo.x in Foo.x\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ Foo⁰.x⁴\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n:expect 4\n:soir\nlet a = Foo.y in Foo.x\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ do Foo⁰.y⁴; Foo⁰.x⁴\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 4\n//│ = 4\n\n\n:sir\n:soir\n(\n  val a = print(\"hi\")\n  42\n)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let a⁰, tmp; set tmp = Predef⁰.print⁰(\"hi\"); define a⁰ as val a¹ = tmp; 42\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ do Predef⁰.print⁰(\"hi\"); 42\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > hi\n//│ = 42\n\n:soir\n:ssjs\n(\n  val a = Foo.y\n  42\n)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let a²; define a² as val a³ = Foo⁰.y⁴; 42\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let a;\n//│ a = Foo1.y; block$res13 = 42; undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 5\n//│ = 42\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/opt/DeadStatRemoval.mls",
    "content": ":js\n\n\n:soir\nif 1 === 2 do 2 + 2\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ runtime⁰.Unit⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:soir\nif 1 == 2 do 2 + 2\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ do Predef⁰.equals⁰(1, 2); runtime⁰.Unit⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n:soir\ndo\n  val x = 2 + 2\n  val y = print(2)\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ do Predef⁰.print⁰(2); runtime⁰.Unit⁰\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/opt/DeadVarRemoval.mls",
    "content": ":js\n\n\n:soir\nlet x = 2 + 2 in 1\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ 1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:soir\nfun main =\n  let x = 2 + 2\n  1\nmain\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ let main⁰, inlinedVal; define main⁰ as fun main¹() { return 1 }; set inlinedVal = 1; inlinedVal\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Apply.mls",
    "content": ":parseOnly\n\n\nf()\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List()))\n\nf(1)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1))))\n\nf(1, 2, 3)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2), IntLit(3))))\n\nf()()\n//│ Parsed:\n//│ \tApp(App(Ident(f),Tup(List())),Tup(List()))\n\nf(1)(2)\n//│ Parsed:\n//│ \tApp(App(Ident(f),Tup(List(IntLit(1)))),Tup(List(IntLit(2))))\n\nf(\n  1\n)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1))))\n\nf(\n  1,\n)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1))))\n\nf(\n  1,\n  2,\n  3\n)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2), IntLit(3))))\n\nf(\n  1,\n  2,\n  3,\n)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2), IntLit(3))))\n\nf(\n  1\n  2\n  3\n)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2), IntLit(3))))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Atoms.mls",
    "content": ":parseOnly\n\n\nfoo\n//│ Parsed:\n//│ \tIdent(foo)\n\nfoo\nbar\n//│ Parsed:\n//│ \tIdent(foo)\n//│ \tIdent(bar)\n\n123\n//│ Parsed:\n//│ \tIntLit(123)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Block.mls",
    "content": ":parseOnly\n\n\na\n//│ Parsed:\n//│ \tIdent(a)\n\na,\n//│ Parsed:\n//│ \tIdent(a)\n\na, b\n//│ Parsed:\n//│ \tIdent(a)\n//│ \tIdent(b)\n\na, b, c\n//│ Parsed:\n//│ \tIdent(a)\n//│ \tIdent(b)\n//│ \tIdent(c)\n\n\nclass A, res\n//│ Parsed:\n//│ \tTypeDef(Cls,Ident(A),None)\n//│ \tIdent(res)\n\n\nfoo of\n  a,\n  b\n//│ Parsed:\n//│ \tApp(Ident(foo),Tup(List(Ident(a), Ident(b))))\n\nfoo of\n  a\n  b\n//│ Parsed:\n//│ \tApp(Ident(foo),Tup(List(Ident(a), Ident(b))))\n\n\nx => x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Ident(x))\n\nx =>\n  x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Block(List(Ident(x))))\n\nx =>\n  foo\n  x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Block(List(Ident(foo), Ident(x))))\n\n\nlet a = 1, 2\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),None)\n//│ \tIntLit(2)\n\nlet a = (1, 2)\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(Bra(Round,Block(List(IntLit(1), IntLit(2))))),None)\n\nlet a = { 1, 2 }\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(Block(List(IntLit(1), IntLit(2)))),None)\n\nlet a = 1 in 2\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(IntLit(2)))\n\nlet a = 1 in 2, 3\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(IntLit(2)))\n//│ \tIntLit(3)\n\nlet a = 1 in (2, 3)\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(Bra(Round,Block(List(IntLit(2), IntLit(3))))))\n\nlet a = 1 in { 2, 3 }\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(Block(List(IntLit(2), IntLit(3)))))\n\n\nfoo a\n//│ Parsed:\n//│ \tJux(Ident(foo),Ident(a))\n\nfoo\n  a\n//│ Parsed:\n//│ \tJux(Ident(foo),Block(List(Ident(a))))\n\nfoo\n  a\n  b\n//│ Parsed:\n//│ \tJux(Ident(foo),Block(List(Ident(a), Ident(b))))\n\nfoo\n  a,\n  b\n//│ Parsed:\n//│ \tJux(Ident(foo),Block(List(Ident(a), Ident(b))))\n\n\n\n// --- ERROR CASES ---\n\n:global\n:pe\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/BoolOps.mls",
    "content": ":parseOnly\n\n\na and b\n//│ Parsed:\n//│ \tInfixApp(Ident(a),Keywrd(keyword 'and'),Ident(b))\n\na and b and c\n//│ Parsed:\n//│ \tInfixApp(InfixApp(Ident(a),Keywrd(keyword 'and'),Ident(b)),Keywrd(keyword 'and'),Ident(c))\n\na and b or x and d\n//│ Parsed:\n//│ \tInfixApp(InfixApp(Ident(a),Keywrd(keyword 'and'),Ident(b)),Keywrd(keyword 'or'),InfixApp(Ident(x),Keywrd(keyword 'and'),Ident(d)))\n\na or b and x or d\n//│ Parsed:\n//│ \tInfixApp(InfixApp(Ident(a),Keywrd(keyword 'or'),InfixApp(Ident(b),Keywrd(keyword 'and'),Ident(x))),Keywrd(keyword 'or'),Ident(d))\n\n(a and b) or (x and d)\n//│ Parsed:\n//│ \tInfixApp(Bra(Round,InfixApp(Ident(a),Keywrd(keyword 'and'),Ident(b))),Keywrd(keyword 'or'),Bra(Round,InfixApp(Ident(x),Keywrd(keyword 'and'),Ident(d))))\n\na and (b or x) and d\n//│ Parsed:\n//│ \tInfixApp(InfixApp(Ident(a),Keywrd(keyword 'and'),Bra(Round,InfixApp(Ident(b),Keywrd(keyword 'or'),Ident(x)))),Keywrd(keyword 'and'),Ident(d))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Class.mls",
    "content": ":parseOnly\n\n\n:pe\nclass\n//│ ╔══[PARSE ERROR] Expected expression after type declaration keyword; found end of input instead\n//│ ║  l.5: \tclass\n//│ ╙──     \t     ^\n//│ Parsed:\n//│ \tError()\n\nclass Foo\n//│ Parsed:\n//│ \tTypeDef(Cls,Ident(Foo),None)\n\n:pe\nclass Foo extends\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found end of input instead\n//│ ║  l.17: \tclass Foo extends\n//│ ╙──      \t                 ^\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Error()),None)\n\nclass Foo extends Bar\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),None)\n\n:pe\nclass Foo extends Bar with\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found end of input instead\n//│ ║  l.29: \tclass Foo extends Bar with\n//│ ╙──      \t                          ^\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),Keywrd(keyword 'with'),Error()),None)\n\nclass Foo extends Bar with val x\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),Keywrd(keyword 'with'),TermDef(ImmutVal,Ident(x),None)),None)\n\nclass Foo extends Bar with\n  val x: Int\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),Keywrd(keyword 'with'),Block(List(TermDef(ImmutVal,InfixApp(Ident(x),Keywrd(keyword ':'),Ident(Int)),None)))),None)\n\nclass Foo with\n  val x: Int\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'with'),Block(List(TermDef(ImmutVal,InfixApp(Ident(x),Keywrd(keyword ':'),Ident(Int)),None)))),None)\n\n\n:pe\nwith\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found 'with' keyword instead\n//│ ║  l.52: \twith\n//│ ╙──      \t^^^^\n//│ Parsed:\n//│ \tError()\n\n\nclass\n  Foo\n//│ Parsed:\n//│ \tTypeDef(Cls,Ident(Foo),None)\n\nclass\n  Foo\n  Bar\n//│ Parsed:\n//│ \tTypeDef(Cls,Ident(Foo),None)\n//│ \tTypeDef(Cls,Ident(Bar),None)\n\nclass\n  Foo extends Bar\n  Bar with\n    x\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),None)\n//│ \tTypeDef(Cls,InfixApp(Ident(Bar),Keywrd(keyword 'with'),Block(List(Ident(x)))),None)\n\n\n:pe\nclass\nFoo\n//│ ╔══[PARSE ERROR] Expected expression after type declaration keyword; found new line instead\n//│ ║  l.82: \tclass\n//│ ║        \t     ^\n//│ ║  l.83: \tFoo\n//│ ╙──      \t\n//│ Parsed:\n//│ \tError()\n//│ \tIdent(Foo)\n\n:fixme\nclass\n  Foo\nextends Bar\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found 'extends' keyword instead\n//│ ║  l.96: \textends Bar\n//│ ╙──      \t^^^^^^^\n//│ ╔══[PARSE ERROR] Expected end of input; found identifier instead\n//│ ║  l.96: \textends Bar\n//│ ╙──      \t        ^^^\n//│ Parsed:\n//│ \tTypeDef(Cls,Ident(Foo),None)\n//│ \tError()\n\nclass\n  Foo\n  extends Bar\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),None)\n\nclass\n  Foo\n  extends Bar\n  Bar\n  extends Baz\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),None)\n//│ \tTypeDef(Cls,InfixApp(Ident(Bar),Keywrd(keyword 'extends'),Ident(Baz)),None)\n\nclass Foo\nextends Bar\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Ident(Bar)),None)\n\nclass Foo\nextends\n  Bar\n//│ Parsed:\n//│ \tTypeDef(Cls,InfixApp(Ident(Foo),Keywrd(keyword 'extends'),Block(List(Ident(Bar)))),None)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/ConstrainedTypes.mls",
    "content": ":parseOnly\n\n\n[] => Int\n//│ Parsed:\n//│ \tInfixApp(TyTup(List()),Keywrd(keyword '=>'),Ident(Int))\n\n[Bot <:< Top] => Int\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(OpApp(Ident(Bot),Ident(<:<),List(Ident(Top))))),Keywrd(keyword '=>'),Ident(Int))\n\n[(Int & Str) <:< (Int | Str)] => Int\n//│ Parsed:\n//│ \tInfixApp(TyTup(List(OpApp(Bra(Round,OpApp(Ident(Int),Ident(&),List(Ident(Str)))),Ident(<:<),List(Bra(Round,OpApp(Ident(Int),Ident(|),List(Ident(Str)))))))),Keywrd(keyword '=>'),Ident(Int))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Extends.mls",
    "content": ":ctx\n:noCodeGen\n\n// Plain extension\nclass Base\nclass Derived extends Base\n//│ Env:\n//│   Base -> RefElem(member:Base)\n//│   Derived -> RefElem(member:Derived)\n\n// Extension with parameters\nabstract class Box\ndata class IntBox(val value: Int) extends Box\ndata class StrBox(val value: Str) extends Box\n//│ Env:\n//│   Box -> RefElem(member:Box)\n//│   IntBox -> RefElem(member:IntBox)\n//│   StrBox -> RefElem(member:StrBox)\n\n// Extension with symbolic name\nabstract class Ring\nmodule End extends Ring\ndata class (++) Link(left: Ring, right: Ring) extends Ring\n//│ Env:\n//│   ++ -> RefElem(member:Link)\n//│   End -> RefElem(member:End)\n//│   Link -> RefElem(member:Link)\n//│   Ring -> RefElem(member:Ring)\n\n// Extension with type parameters\nabstract class Option[T]: (Some[T] | None)\ndata class Some[T](val value: T) extends Option[T]\nmodule None extends Option[Nothing]\n//│ Env:\n//│   None -> RefElem(member:None)\n//│   Option -> RefElem(member:Option)\n//│   Some -> RefElem(member:Some)\n\n// Extension with type parameters and symbolic name\nabstract class List[T]: (Cons[T] | Nil)\ndata class (::) Cons[T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List[Nothing]\n//│ Env:\n//│   :: -> RefElem(member:Cons)\n//│   Cons -> RefElem(member:Cons)\n//│   List -> RefElem(member:List)\n//│   Nil -> RefElem(member:Nil)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Handler.mls",
    "content": ":noCodeGen\n\n:pe\nhandle\n//│ ╔══[PARSE ERROR] Expected expression after 'handle' binding keyword; found end of input instead\n//│ ║  l.4: \thandle\n//│ ╙──     \t      ^\n\n:pe\nhandle h\n//│ ╔══[PARSE ERROR] Expected '=' keyword after 'handle' binding head; found end of input instead\n//│ ║  l.10: \thandle h\n//│ ╙──      \t        ^\n\n:pe\nhandle h = Eff\n//│ ╔══[PARSE ERROR] Expected 'with' keyword after 'handle' binding class name; found end of input instead\n//│ ║  l.16: \thandle h = Eff\n//│ ╙──      \t              ^\n\n:parseOnly\nfun foo(x) = 1\nhandle h = Eff with\n  fun f()(r) = r(0)\n  fun g(a)(r) = r(1)\n//│ Parsed:\n//│ \tTermDef(Fun,App(Ident(foo),Tup(List(Ident(x)))),Some(IntLit(1)))\n//│ \tHndl(Ident(h),Ident(Eff),Block(List(TermDef(Fun,App(App(Ident(f),Tup(List())),Tup(List(Ident(r)))),Some(App(Ident(r),Tup(List(IntLit(0)))))), TermDef(Fun,App(App(Ident(g),Tup(List(Ident(a)))),Tup(List(Ident(r)))),Some(App(Ident(r),Tup(List(IntLit(1)))))))),None)\n\n\n:e\nhandle 1 = 1 with\n  fun f()(r) = r(0)\nin\n  foo(h)\n//│ ╔══[COMPILATION ERROR] Unsupported handle binding shape\n//│ ║  l.32: \thandle 1 = 1 with\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.33: \t  fun f()(r) = r(0)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.34: \tin\n//│ ║        \t^^\n//│ ║  l.35: \t  foo(h)\n//│ ╙──      \t^^^^^^^^\n\nabstract class Eff\nfun foo(h) = 0\n\n:el\nhandle h = Eff with\n  fun f()(r) = r(0)\nin\n  foo(h)\n//│ Elab: { handle h = Ref(member:Eff)() List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,term:Handler$h$/f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) }\n\n:e\n(\n  handle h = Eff with\n    fun f()(r) = r(0)\n    fun g(a)()(r) = r(1)\n) + 1\n//│ ╔══[COMPILATION ERROR] Unsupported handle binding shape\n//│ ║  l.58: \t  handle h = Eff with\n//│ ║        \t  ^^^^^^^^^^^^^^^^^^^\n//│ ║  l.59: \t    fun f()(r) = r(0)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.60: \t    fun g(a)()(r) = r(1)\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^\n\nmodule Mod with\n  abstract class Eff(x)\n\n:el\nhandle h = Mod.Eff(3) with\n  fun f()(r) = r(0)\n  fun g(a)()()(r) = r(1)\nfoo(h)\n//│ Elab: { handle h = Sel(Ref(member:Mod),Ident(Eff))(Lit(IntLit(3))) List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,term:Handler$h$/f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹method ›,Modulefulness(None),List(),None)), HandlerTermDefinition(r,TermDefinition(Fun,member:g,term:Handler$h$/g,List(ParamList(‹›,List(Param(‹›,a,None,Modulefulness(None))),None), ParamList(‹›,List(),None), ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(1)),None))))),‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) }\n\n:e\nhandle h = Eff with\n  fun f()(r) = r(0)\n  fun g(a)(r) = r(1)\n  val x = 24\n  class Test with\n    fun x() = x\nfoo(h)\n//│ ╔══[COMPILATION ERROR] Only function definitions are allowed in handler blocks\n//│ ║  l.84: \t  val x = 24\n//│ ╙──      \t  ^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Only function definitions are allowed in handler blocks\n//│ ║  l.86: \t    fun x() = x\n//│ ╙──      \t              ^\n\n:e\nhandle h = Eff with\n  fun f()(r) = r(0)\n  fun g(a)(r) = \n    handle e = Eff with\n      fun f = r(0)\n      fun g() = r(0)\n      fun h()() = r(1)\n      fun h2()(a, b) = r(1)\n    foo(h)\nfoo(h)\n//│ ╔══[COMPILATION ERROR] Handler function is missing resumption parameter\n//│ ║  l.100: \t      fun f = r(0)\n//│ ╙──       \t      ^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Handler function is missing resumption parameter\n//│ ║  l.101: \t      fun g() = r(0)\n//│ ╙──       \t      ^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Handler function is missing resumption parameter\n//│ ║  l.102: \t      fun h()() = r(1)\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Handler function is missing resumption parameter\n//│ ║  l.103: \t      fun h2()(a, b) = r(1)\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: h\n//│ ║  l.104: \t    foo(h)\n//│ ╙──       \t        ^\n\n:w\n:el\nhandle h = Eff with\n  fun f()(r) = r(0)\n  fun g(a)(r) = r(1)\n  12345\nfoo(h)\n//│ ╔══[WARNING] Terms in handler block do nothing\n//│ ║  l.127: \t  12345\n//│ ╙──       \t  ^^^^^\n//│ Elab: { handle h = Ref(member:Eff)() List(HandlerTermDefinition(r,TermDefinition(Fun,member:f,term:Handler$h$/f,List(ParamList(‹›,List(),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(0)),None))))),‹method ›,Modulefulness(None),List(),None)), HandlerTermDefinition(r,TermDefinition(Fun,member:g,term:Handler$h$/g,List(ParamList(‹›,List(Param(‹›,a,None,Modulefulness(None))),None)),None,None,Some(App(Ref(r),Tup(List(Fld(‹›,Lit(IntLit(1)),None))))),‹method ›,Modulefulness(None),List(),None))) in App(Ref(member:foo),Tup(List(Fld(‹›,Ref(h),None)))) }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Indent.mls",
    "content": ":parseOnly\n\n\nx\n//│ Parsed:\n//│ \tIdent(x)\n\nx\n  y\n//│ Parsed:\n//│ \tJux(Ident(x),Block(List(Ident(y))))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Let.mls",
    "content": ":parseOnly\n\n\n:pe\nlet\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found end of input instead\n//│ ║  l.5: \tlet\n//│ ╙──     \t   ^\n//│ Parsed:\n//│ \tError()\n\nlet x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),None,None)\n\n:pe\nlet x =\n//│ ╔══[PARSE ERROR] Expected expression or block after 'let' binding equals sign; found end of input instead\n//│ ║  l.17: \tlet x =\n//│ ╙──      \t       ^\n//│ Parsed:\n//│ \tError()\n\nlet x = y\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(Ident(y)),None)\n\nlet x =\n  y\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(Block(List(Ident(y)))),None)\n\n:pe\nlet x = y in\n//│ ╔══[PARSE ERROR] Expected expression or block after 'let' binding `in` clause; found end of input instead\n//│ ║  l.34: \tlet x = y in\n//│ ╙──      \t            ^\n//│ Parsed:\n//│ \tError()\n\nlet x = y in z\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(Ident(y)),Some(Ident(z)))\n\n:pe\nlet x = y class\n//│ ╔══[PARSE ERROR] Expected end of input; found 'class' keyword instead\n//│ ║  l.46: \tlet x = y class\n//│ ╙──      \t          ^^^^^\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(Ident(y)),None)\n\nlet x\n  = 1\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)\n\n// * Note: this used to parse as an operator application...\nlet x\n= 1\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)\n\n// * Note: this used to parse as an operator application...\n:pe\nlet x\n=\n1\n//│ ╔══[PARSE ERROR] Expected expression or block after 'let' binding equals sign; found new line instead\n//│ ║  l.67: \t=\n//│ ║        \t ^\n//│ ║  l.68: \t1\n//│ ╙──      \t\n//│ Parsed:\n//│ \tError()\n//│ \tIntLit(1)\n\n\n:pe\nlet {}\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found end of block instead\n//│ ║  l.80: \tlet {}\n//│ ╙──      \t    ^^\n//│ Parsed:\n\nlet ()\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Unt(),None,None)\n\n:pe\nlet // a\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found end of input instead\n//│ ║  l.91: \tlet // a\n//│ ╙──      \t        ^\n//│ Parsed:\n//│ \tError()\n\n:pe\nlet\n  // a\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found end of input instead\n//│ ║  l.100: \t  // a\n//│ ╙──       \t  ^\n//│ Parsed:\n//│ \tError()\n\n:pe\nlet\n  // a\n1\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found new line instead\n//│ ║  l.109: \t  // a\n//│ ║         \t      ^\n//│ ║  l.110: \t1\n//│ ╙──       \t\n//│ Parsed:\n//│ \tError()\n//│ \tIntLit(1)\n\n\n\nlet x = y\nfoo\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(Ident(y)),None)\n//│ \tIdent(foo)\n\n\nlet\n  x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),None,None)\n\nlet\n  x\n  y\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),None,None)\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(y),None,None)\n\nlet\n  x, y\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),None,None)\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(y),None,None)\n\nlet\n  x = 1\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)\n\nlet\n  x = 1 in x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x)))\n\nlet\n  x = 1\n  in x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x)))\n\nlet x = 1\nin x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x)))\n\nlet x = 1\n  in x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x)))\n\n// Awkward... parses `in x` as a separate statement\nlet\n  x = 1\nin x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)\n//│ \tModified(Keywrd(keyword 'in'),Ident(x))\n\n:pe\nlet\nx = 1\nin x\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found new line instead\n//│ ║  l.182: \tlet\n//│ ║         \t   ^\n//│ ║  l.183: \tx = 1\n//│ ╙──       \t\n//│ Parsed:\n//│ \tError()\n//│ \tDef(Ident(x),IntLit(1))\n//│ \tModified(Keywrd(keyword 'in'),Ident(x))\n\n\nlet a in b\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),None,Some(Ident(b)))\n\nlet a = 1 in b\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(Ident(b)))\n\n\n:pe\nlet\n  with\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found 'with' keyword instead\n//│ ║  l.207: \t  with\n//│ ╙──       \t  ^^^^\n//│ Parsed:\n//│ \tError()\n\n\nlet x = 1 in\n  x\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Block(List(Ident(x)))))\n\nlet x = 1 in\n  x\n  y\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Block(List(Ident(x), Ident(y)))))\n\nx => let x = 1 in x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x))))\n\nx => let x = 1 in\n  x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Block(List(Ident(x))))))\n\nx => let x = 1\n  in x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x))))\n\nx =>\n  let x = 1\n  in x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x))))))\n\nx =>\n  let x = 1\n  x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None), Ident(x))))\n\nx => let x = 1\n  x\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),LetLike(Keywrd(keyword 'let'),Ident(x),Some(Jux(IntLit(1),Block(List(Ident(x))))),None))\n\n\n:pe\nif\n//│ ╔══[PARSE ERROR] Expected expression or block after 'if' keyword; found end of input instead\n//│ ║  l.259: \tif\n//│ ╙──       \t  ^\n//│ Parsed:\n//│ \tError()\n\n\n\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/LetLet.mls",
    "content": ":parseOnly\n\n\n:pe\nlet let\n//│ ╔══[PARSE ERROR] Expected expression after 'let' binding keyword; found end of input instead\n//│ ║  l.5: \tlet let\n//│ ╙──     \t       ^\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Error(),None,None)\n\n:pe\nlet x = 1 let y = 2\n//│ ╔══[PARSE ERROR] Expected end of input; found 'let' keyword instead\n//│ ║  l.13: \tlet x = 1 let y = 2\n//│ ╙──      \t          ^^^\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)\n\nlet x = 1 in let y = 2\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(LetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),None)))\n\nlet x = 1 in let y = 2 in let z = 3\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(LetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),Some(LetLike(Keywrd(keyword 'let'),Ident(z),Some(IntLit(3)),None)))))\n\nlet x = 1\nlet y = 2\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),None)\n\nlet\n  x\n  y\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),None,None)\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(y),None,None)\n\nlet\n  x = 1\n  y = 2\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),None)\n\nlet\n  x = 1 in x\n  y = 2 in y\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x)))\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),Some(Ident(y)))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Modifiers.mls",
    "content": ":parseOnly\n\n\nmut let x = 1\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None))\n\nmut mut let x = 1\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Modified(Keywrd(keyword 'mut'),LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None)))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/MultiLineCall.mls",
    "content": ":js\n\n\n// Multi-line function call with comma continuation should parse correctly\n\ntuple(1,\n  2)\n//│ = [1, 2]\n\ntuple of 1,\n  2\n//│ = [1, 2]\n\ntuple of\n  1,\n  2,\n  3\n//│ = [1, 2, 3]\n\ntuple of\n  1,\n    2,\n  3\n//│ = [1, 2, 3]\n\ntuple of\n  1,\n    2\n  3\n//│ = [1, 2, 3]\n\n:e\ntuple of\n  1\n    2\n  3\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (integer literal).\n//│ ║  l.35: \t    2\n//│ ╙──      \t    ^\n//│ = [1, 3]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Mut.mls",
    "content": ":parseOnly\n\n\n:pe\nmut\n//│ ╔══[PARSE ERROR] Expected expression or block after 'mut' keyword; found end of input instead\n//│ ║  l.5: \tmut\n//│ ╙──     \t   ^\n//│ Parsed:\n//│ \tError()\n\nmut x\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Ident(x))\n\nmut\n  x\n  y\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(Ident(x), Ident(y))))\n\nmut let x = 1\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None))\n\nmut\n  let x = 1\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None))))\n\nmut\n  let x = 1\n  in x\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x))))))\n\nmut\n  let x = 1\n  let y = 2\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None), LetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),None))))\n\nmut\n  let\n    x = 1\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None))))\n\nmut\n  let\n    x = 1\n  let\n    y = 1\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None), LetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(1)),None))))\n\nmut\n  let\n    x = 1\n    y = 2\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None), LetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),None))))\n\nmut\n  let\n    x = 1 in x\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x))))))\n\nmut\n  let\n    x = 1 in x\n  let\n    y = 2 in y\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),Some(Ident(x))), LetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),Some(Ident(y))))))\n\n// Note that this parses as a `mut` modifier on a block of two let bindings, which is a bit weird\nmut let\n  x = 1\n  y = 2\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'mut'),Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(1)),None), LetLike(Keywrd(keyword 'let'),Ident(y),Some(IntLit(2)),None))))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Of.mls",
    "content": ":parseOnly\n\n\nf of ()\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(Unt())))\n\nf of 1\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1))))\n\nf of (1)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(Bra(Round,IntLit(1)))))\n\nf of 1, 2\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2))))\n\nf of 1, 2, 3\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2), IntLit(3))))\n\nf of (1, 2, 3)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(Bra(Round,Block(List(IntLit(1), IntLit(2), IntLit(3)))))))\n\nf of g(1)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(App(Ident(g),Tup(List(IntLit(1)))))))\n\nf of g of 1\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(App(Ident(g),Tup(List(IntLit(1)))))))\n\n(f of g) of 1\n//│ Parsed:\n//│ \tApp(Bra(Round,App(Ident(f),Tup(List(Ident(g))))),Tup(List(IntLit(1))))\n\n(f of g)(1)\n//│ Parsed:\n//│ \tApp(Bra(Round,App(Ident(f),Tup(List(Ident(g))))),Tup(List(IntLit(1))))\n\nf of (g)(1)\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(App(Bra(Round,Ident(g)),Tup(List(IntLit(1)))))))\n\n\nf of\n  1,\n  2,\n  3\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2), IntLit(3))))\n\nf of\n  1\n  2\n  3\n//│ Parsed:\n//│ \tApp(Ident(f),Tup(List(IntLit(1), IntLit(2), IntLit(3))))\n\n\n:pe\nlog\nof 1\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found 'of' keyword instead\n//│ ║  l.66: \tof 1\n//│ ╙──      \t^^\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.66: \tof 1\n//│ ╙──      \t   ^\n//│ Parsed:\n//│ \tIdent(log)\n//│ \tError()\n\n:w\nprint of \n123\n//│ ╔══[WARNING] This literal should be indented\n//│ ║  l.79: \t123\n//│ ║        \t^^^\n//│ ╟── since it is a continuation of the new line here\n//│ ║  l.78: \tprint of \n//│ ║        \t         ^\n//│ ║  l.79: \t123\n//│ ╙──      \t\n//│ Parsed:\n//│ \tApp(Ident(print),Tup(List(IntLit(123))))\n\n:w\nprint of \n1\n2\n//│ ╔══[WARNING] This literal should be indented\n//│ ║  l.93: \t1\n//│ ║        \t^\n//│ ╟── since it is a continuation of the new line here\n//│ ║  l.92: \tprint of \n//│ ║        \t         ^\n//│ ║  l.93: \t1\n//│ ╙──      \t\n//│ Parsed:\n//│ \tApp(Ident(print),Tup(List(IntLit(1))))\n//│ \tIntLit(2)\n\nprint of...\n1\n2\n//│ Parsed:\n//│ \tApp(Ident(print),Tup(List(IntLit(1), IntLit(2))))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Operators.mls",
    "content": ":parseOnly\n\n\n+\n//│ Parsed:\n//│ \tIdent(+)\n\n+1\n//│ Parsed:\n//│ \tApp(Ident(+),Tup(List(IntLit(1))))\n\n1 + 2\n//│ Parsed:\n//│ \tOpApp(IntLit(1),Ident(+),List(IntLit(2)))\n\n1 + +2\n//│ Parsed:\n//│ \tOpApp(IntLit(1),Ident(+),List(App(Ident(+),Tup(List(IntLit(2))))))\n\n+1 + +2\n//│ Parsed:\n//│ \tOpApp(App(Ident(+),Tup(List(IntLit(1)))),Ident(+),List(App(Ident(+),Tup(List(IntLit(2))))))\n\n+ + 1 + + + 2\n//│ Parsed:\n//│ \tOpApp(App(Ident(+),Tup(List(App(Ident(+),Tup(List(IntLit(1))))))),Ident(+),List(App(Ident(+),Tup(List(App(Ident(+),Tup(List(IntLit(2)))))))))\n\n1 + 2 * 3\n//│ Parsed:\n//│ \tOpApp(IntLit(1),Ident(+),List(OpApp(IntLit(2),Ident(*),List(IntLit(3)))))\n\n1 + 2 * 3 - 4\n//│ Parsed:\n//│ \tOpApp(OpApp(IntLit(1),Ident(+),List(OpApp(IntLit(2),Ident(*),List(IntLit(3))))),Ident(-),List(IntLit(4)))\n\n1 => 2\n//│ Parsed:\n//│ \tInfixApp(Tup(List(IntLit(1))),Keywrd(keyword '=>'),IntLit(2))\n\n1 =>\n  2\n//│ Parsed:\n//│ \tInfixApp(Tup(List(IntLit(1))),Keywrd(keyword '=>'),Block(List(IntLit(2))))\n\nx =>\n  1\n  2\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Block(List(IntLit(1), IntLit(2))))\n\nx => x : t\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),InfixApp(Ident(x),Keywrd(keyword ':'),Ident(t)))\n\nx =>\n  x : t\n//│ Parsed:\n//│ \tInfixApp(Tup(List(Ident(x))),Keywrd(keyword '=>'),Block(List(InfixApp(Ident(x),Keywrd(keyword ':'),Ident(t)))))\n\n\n1 +\n 2\n//│ Parsed:\n//│ \tOpApp(IntLit(1),Ident(+),List(Block(List(IntLit(2)))))\n\n\n:pt\n1 +\n2 +\n3\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpApp:\n//│   lhs = OpApp:\n//│     lhs = IntLit of 1\n//│     op = Ident of \"+\"\n//│     rhss = Ls of \n//│       IntLit of 2\n//│   op = Ident of \"+\"\n//│   rhss = Ls of \n//│     IntLit of 3\n\n1 +\n let x = 2\n class A\n x\n 42\n//│ Parsed:\n//│ \tOpApp(IntLit(1),Ident(+),List(Block(List(LetLike(Keywrd(keyword 'let'),Ident(x),Some(IntLit(2)),None), TypeDef(Cls,Ident(A),None), Ident(x), IntLit(42)))))\n\n:pe\n1 +\n 2,\n 3\n//│ ╔══[PARSE ERROR] Unexpected comma in this position\n//│ ║  l.92: \t 2,\n//│ ╙──      \t  ^\n//│ Parsed:\n//│ \tOpApp(IntLit(1),Ident(+),List(Block(List(IntLit(2), IntLit(3)))))\n\n\na === \"a\" || b === \"b\"\n//│ Parsed:\n//│ \tOpApp(OpApp(Ident(a),Ident(===),List(StrLit(a))),Ident(||),List(OpApp(Ident(b),Ident(===),List(StrLit(b)))))\n\n\nA is B where C is D\n//│ Parsed:\n//│ \tInfixApp(InfixApp(Ident(A),Keywrd(keyword 'is'),Ident(B)),Keywrd(keyword 'where'),InfixApp(Ident(C),Keywrd(keyword 'is'),Ident(D)))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/PrefixOps.mls",
    "content": ":js\n\n\n+2\n//│ = 2\n\n2 + +3\n//│ = 5\n\n2 + -3\n//│ = -1\n\n// * `+` is a prefix op; needs a space if we want to use it as a binary op in new-line position\n:w\n:sjs\n1\n+2\n+3\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.16: \t1\n//│ ╙──      \t^\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ + 3\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.16: \t1\n//│ ╙──      \t^\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 3\n\n:sjs\n1\n+ 2\n+ 3\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp2; tmp2 = 1 + 2; tmp2 + 3\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 6\n\n1\n* 2\n* 3\n//│ = 6\n\n1\n*2\n*3\n//│ = 6\n\n\n:sjs\n+\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda; lambda = (undefined, function (arg1, arg2) { return arg1 + arg2 }); lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n*\n//│ = fun\n\n:w\n1\n*\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.61: \t1\n//│ ╙──      \t^\n//│ = fun\n\n\nfun (??) foo(x, y) = x + y\n\n??\n//│ = fun foo\n\n(??)\n//│ = fun foo\n\n??(1, 2)\n//│ = 3\n\n?? of 1, 2\n//│ = 3\n\n1 ??(2)\n//│ = 3\n\n1 ?? 2\n//│ = 3\n\n// `??` is not in the list of prefix operators...\n:pe\n?? 1\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.91: \t?? 1\n//│ ╙──      \t   ^\n//│ = fun foo\n\n1\n?? 2\n//│ = 3\n\n1\n  ?? 2\n//│ = 3\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Semis.mls",
    "content": ":parseOnly\n\n\na; b\n//│ Parsed:\n//│ \tOpApp(Ident(a),Ident(;),List(Ident(b)))\n\na; b; c\n//│ Parsed:\n//│ \tOpApp(OpApp(Ident(a),Ident(;),List(Ident(b))),Ident(;),List(Ident(c)))\n\n\nlet a = 1; 2\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(OpApp(IntLit(1),Ident(;),List(IntLit(2)))),None)\n\nlet a = (1; 2)\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(Bra(Round,OpApp(IntLit(1),Ident(;),List(IntLit(2))))),None)\n\nlet a = { 1; 2 }\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(Block(List(OpApp(IntLit(1),Ident(;),List(IntLit(2)))))),None)\n\nlet a = 1 in 2\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(IntLit(2)))\n\nlet a = 1 in 2; 3\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(OpApp(IntLit(2),Ident(;),List(IntLit(3)))))\n\nlet a = 1 in (2; 3)\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(Bra(Round,OpApp(IntLit(2),Ident(;),List(IntLit(3))))))\n\nlet a = 1 in { 2; 3 }\n//│ Parsed:\n//│ \tLetLike(Keywrd(keyword 'let'),Ident(a),Some(IntLit(1)),Some(Block(List(OpApp(IntLit(2),Ident(;),List(IntLit(3)))))))\n\n1; id(2)\n//│ Parsed:\n//│ \tOpApp(IntLit(1),Ident(;),List(App(Ident(id),Tup(List(IntLit(2))))))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/SetCurlyBraces.mls",
    "content": ":js\n\n\nlet { x = 0, y = 0 }\n//│ x = 0\n//│ y = 0\n\n// Works:\nif false then 0\nelse\n  set { x = 1, y = 1 }\n\n// Also works (set { ... } on same line as else):\nif false then 0\nelse set { x = 1, y = 1 }\n\nx\n//│ = 1\n\ny\n//│ = 1\n\n// Reset and test single set\nset { x = 42 }\nx\n//│ = 42\n\n\n:pe\nset { }\n//│ ╔══[PARSE ERROR] Expected expression after 'set' binding keyword; found end of block instead\n//│ ║  l.30: \tset { }\n//│ ╙──      \t    ^^^\n\n:pe\n:re\nif false then 0\nelse set { }\n//│ ╔══[PARSE ERROR] Expected expression after 'set' binding keyword; found empty block instead\n//│ ║  l.38: \telse set { }\n//│ ╙──      \t         ^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nif false then 0\nelse set\n  x = 2\n  y = 2\n\nx\n//│ = 2\n\ny\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Suspension.mls",
    "content": ":js\n\n\nprint of ...\n123\n//│ > 123\n\nprint of...\n123\n//│ > 123\n\nprint of\n  123\n//│ > 123\n\n\n// * Interesting quirk:\n\nprint of ...\n[1, 2]\n//│ > [1, 2]\n\nprint of ...\n  [1, 2]\n//│ > 1 2\n\n\nif true do...\n\nif true do...\nprint(1)\n//│ > 1\n\n\nmodule Option with ...\n\nmodule Option with ...\nval a = 1\n\nmodule Option with ...\n// \nval a = 1\n// \n\n:pt\nmodule A with\n  \n  module B with ...\n  \n  val a = 1\n  \n  val b = 2\n  \n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TypeDef:\n//│   k = Mod\n//│   head = InfixApp:\n//│     lhs = Ident of \"A\"\n//│     kw = Keywrd of keyword 'with'\n//│     rhs = Block of Ls of \n//│       TypeDef:\n//│         k = Mod\n//│         head = InfixApp:\n//│           lhs = Ident of \"B\"\n//│           kw = Keywrd of keyword 'with'\n//│           rhs = Block of Ls of \n//│             TermDef:\n//│               k = ImmutVal\n//│               head = Ident of \"a\"\n//│               rhs = S of IntLit of 1\n//│             TermDef:\n//│               k = ImmutVal\n//│               head = Ident of \"b\"\n//│               rhs = S of IntLit of 2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nfun test(x) =\n  if x then print(\"ok\") else...\n  print(\"ko\")\nlet foo = 1\n//│ foo = 1\n\n\n:w\nx =>\n  if false then 0 else...\n  1\nlet bar = 1\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.86: \tx =>\n//│ ║        \t^^^^\n//│ ║  l.87: \t  if false then 0 else...\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.88: \t  1\n//│ ╙──      \t^^^\n//│ bar = 1\n\nbar\n//│ = 1\n\n\n:w\n:e\nx => if false then 0 else...\n  1\nlet foo = 1\n//│ ╔══[COMPILATION ERROR] Illegal position for '...' spread operator.\n//│ ║  l.105: \tx => if false then 0 else...\n//│ ╙──       \t                         ^^^\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.105: \tx => if false then 0 else...\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.106: \t  1\n//│ ╙──       \t^^^\n//│ foo = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Then.mls",
    "content": ":parseOnly\n\n\n1 then 2\n//│ Parsed:\n//│ \tInfixApp(IntLit(1),Keywrd(keyword 'then'),IntLit(2))\n\n1 then 2 then 3\n//│ Parsed:\n//│ \tInfixApp(IntLit(1),Keywrd(keyword 'then'),InfixApp(IntLit(2),Keywrd(keyword 'then'),IntLit(3)))\n\n1 and 2 then 3\n//│ Parsed:\n//│ \tInfixApp(InfixApp(IntLit(1),Keywrd(keyword 'and'),IntLit(2)),Keywrd(keyword 'then'),IntLit(3))\n\n1 and 2 and 3 then 4\n//│ Parsed:\n//│ \tInfixApp(InfixApp(InfixApp(IntLit(1),Keywrd(keyword 'and'),IntLit(2)),Keywrd(keyword 'and'),IntLit(3)),Keywrd(keyword 'then'),IntLit(4))\n\n1 then 2 and 3\n//│ Parsed:\n//│ \tInfixApp(IntLit(1),Keywrd(keyword 'then'),InfixApp(IntLit(2),Keywrd(keyword 'and'),IntLit(3)))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/parser/Val.mls",
    "content": ":parseOnly\n\n// :pe\nval 1\n//│ Parsed:\n//│ \tTermDef(ImmutVal,IntLit(1),None)\n\n// :pe\nval x\n//│ Parsed:\n//│ \tTermDef(ImmutVal,Ident(x),None)\n\nval x = 1\n//│ Parsed:\n//│ \tTermDef(ImmutVal,Ident(x),Some(IntLit(1)))\n\n// :pe\nval\n  x\n//│ Parsed:\n//│ \tTermDef(ImmutVal,Ident(x),None)\n\nval\n  x = 1\n//│ Parsed:\n//│ \tTermDef(ImmutVal,Ident(x),Some(IntLit(1)))\n\nval\n  x = 1\n  y = 2\n  z = 3\n//│ Parsed:\n//│ \tTermDef(ImmutVal,Ident(x),Some(IntLit(1)))\n//│ \tTermDef(ImmutVal,Ident(y),Some(IntLit(2)))\n//│ \tTermDef(ImmutVal,Ident(z),Some(IntLit(3)))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/FingerTreeListTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/FingerTreeList.mls\"\nimport \"../../mlscript-compile/LazyFingerTree.mls\"\n\nopen FingerTreeList\n\nlet xs = FingerTreeList.mk(1,2,3)\n//│ xs = [1, 2, 3]\n\nlet ys = concat(xs, xs) concat(xs)\n//│ ys = [1, 2, 3, 1, 2, 3, 1, 2, 3]\n\nys |> ith(-1)\n//│ = None\nys |> ith(0)\n//│ = Some(1)\nys |> ith(1)\n//│ = Some(2)\nys |> ith(2)\n//│ = Some(3)\nys |> ith(3)\n//│ = Some(1)\nys |> ith(4)\n//│ = Some(2)\nys |> ith(5)\n//│ = Some(3)\nys |> ith(6)\n//│ = Some(1)\nys |> ith(7)\n//│ = Some(2)\nys |> ith(8)\n//│ = Some(3)\nys |> ith(9)\n//│ = None\n\nlet ys = (ys |> popFront).rest\n//│ ys = [2, 3, 1, 2, 3, 1, 2, 3]\nlet ys = (ys |> popBack).rest\n//│ ys = [2, 3, 1, 2, 3, 1, 2]\nlet ys = (ys |> popBack).rest\n//│ ys = [2, 3, 1, 2, 3, 1]\nlet ys = (ys |> popBack).rest\n//│ ys = [2, 3, 1, 2, 3]\nlet ys = (ys |> popFront).rest\n//│ ys = [3, 1, 2, 3]\nlet ys = (ys |> popFront).rest\n//│ ys = [1, 2, 3]\nlet ys = (ys |> popFront).rest\n//│ ys = [2, 3]\n\nlet ys = xs ++ xs ++ xs\n//│ ys = [1, 2, 3, 1, 2, 3, 1, 2, 3]\n\nys |> dropLeftRight(3, 3)\n//│ = [1, 2, 3]\n\nlet ys = 1 +: 2 +: 3 +: ys :+ 1 :+ 2 :+ 3\n//│ ys = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]\n\n:expect true\nLazyFingerTree.equals(ys, [...ys])\n//│ = true\n\n:expect true\n(ys ++ ys).length == ys.length + ys.length\n//│ = true\n\n:silent\nlet zs = ys ++ ys\n\n:expect true\nzs FingerTreeList.isFingerTree()\n//│ = true\n\n:expect true\n[...zs] Array.isArray()\n//│ = true\n\nfun mkRange(start, end) =\n  if start < end then\n    mkRange(start + 1, end) :+ start\n  else\n    mk()\n\nfun repeat(xs, n) = \n  if n == 0 then mk()\n  else xs ++ repeat(xs, n - 1)\n\n:expect true\nrepeat(xs, 512).length == xs.length * 512\n//│ = true\n\nlet xs = FingerTreeList.mk(1, 2, 3)\n//│ xs = [1, 2, 3]\n\n:expect [1, [2, 3]]\n:sjs\nif xs is\n  [a, ...ls] then [a, ls]\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let ls, a, middleElements, element0$;\n//│ if (runtime.Tuple.isArrayLike(xs1) && xs1.length >= 1) {\n//│   element0$ = runtime.Tuple.get(xs1, 0);\n//│   middleElements = runtime.Tuple.slice(xs1, 1, 0);\n//│   ls = middleElements;\n//│   a = element0$;\n//│   globalThis.Object.freeze([\n//│     a,\n//│     ls\n//│   ])\n//│ } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = [1, [2, 3]]\n\nfun addUntilN(xs, n) =\n  if n <= 0 then xs\n  else addUntilN([n] ++ xs, n - 1)\n\n:silent\nlet zs = addUntilN(mk(), 1000)\n\n:expect 1000\nzs.length\n//│ = 1000\n\nfun popUntilEmpty(lft, acc) =\n  if lft is\n    [a, ...ls] then popUntilEmpty(ls, [..acc, a])\n    [] then acc\n\n:sjs\nfun popByIndex(start, end, acc, lft) =\n  if start >= end then acc\n  else popByIndex(start + 1, end, [...acc, lft.at(start)], lft)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let popByIndex;\n//│ popByIndex = function popByIndex(start, end, acc, lft) {\n//│   loopLabel: while (true) {\n//│     let scrut, tmp34, tmp35, tmp36;\n//│     scrut = start >= end;\n//│     if (scrut === true) {\n//│       return acc\n//│     }\n//│     tmp34 = start + 1;\n//│     tmp35 = runtime.safeCall(lft.at(start));\n//│     tmp36 = globalThis.Object.freeze([\n//│       ...acc,\n//│       tmp35\n//│     ]);\n//│     start = tmp34;\n//│     acc = tmp36;\n//│     continue loopLabel;\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:silent\nlet zs1 = popUntilEmpty(zs, [])\n\n:silent\nlet zs2 = popByIndex(0, zs.length, [], zs)\n\nzs1 |> isFingerTree\n//│ = false\n\nzs2 |> isFingerTree\n//│ = false\n\nzs |> isFingerTree\n//│ = true\n\n:expect true\nLazyFingerTree.equals(zs1, zs)\n//│ = true\n\n:expect true\nLazyFingerTree.equals(zs2, zs)\n//│ = true\n\n(if FingerTreeList.mk(1,2,3) is\n  [a, ...ls, b] then ls) |> FingerTreeList.isFingerTree\n//│ = true\n\n:expect 1\nzs.at(0)\n//│ = 1\n\n:expect 1\nzs.[0]\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/IterTest.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Iter.mls\"\n\n\nlet arr = [\n  \"0\"\n  \"1\"\n  \"2\"\n  \"3\"\n]\n//│ arr = [\"0\", \"1\", \"2\", \"3\"]\n\n{Iter.joined(_, \"\")} of arr\n//│ = \"0123\"\n\narr Iter.joined(\"\")\n//│ = \"0123\"\n\narr \\ Iter.mapping(_ + \"!\") \\ Iter.toArray()\n//│ = [\"0!\", \"1!\", \"2!\", \"3!\"]\n\narr\n  |> Iter.withMap of _ + \"!\"\n  |> Iter.withFilter of _ != \"2!\"\n  |> Iter.toArray\n//│ = [\"0!\", \"1!\", \"3!\"]\n\n[\"abc\", \"01234\"]\n  |> Iter.withMap of _.toUpperCase()\n  |> Iter.flattening\n  |> Iter.withFilter of _ != \"0\"\n  |> Iter.toArray\n//│ = [\"A\", \"B\", \"C\", \"1\", \"2\", \"3\", \"4\"]\n\nmkStr of\n  \"0\"\n  \"1\"\n  \"2\"\n  \"3\"\n//│ = \"0123\"\n\nmkStr of\n  \"0\"\n  1\n//│ // Standard Error:\n//│ Assertion failed\n//│ \n//│ = \"01\"\n\nfun xs = [1, 2, 3] Iter.mapping(_ + \"!\" !> print)\n\nxs\n//│ = Iterable(_)\n\nxs.toArray()\n//│ > 1!\n//│ > 2!\n//│ > 3!\n//│ = [\"1!\", \"2!\", \"3!\"]\n\nxs.toArray()\n//│ > 1!\n//│ > 2!\n//│ > 3!\n//│ = [\"1!\", \"2!\", \"3!\"]\n\nlet ys = xs\n//│ ys = Iterable(_)\n\nys.toArray()\n//│ > 1!\n//│ > 2!\n//│ > 3!\n//│ = [\"1!\", \"2!\", \"3!\"]\n\nset ys.toArray().[0] = \"??\"\n//│ > 1!\n//│ > 2!\n//│ > 3!\n\nys.toArray()\n//│ > 1!\n//│ > 2!\n//│ > 3!\n//│ = [\"1!\", \"2!\", \"3!\"]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/LazyArrayTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/LazyArray.mls\"\nimport \"../../mlscript-compile/MutMap.mls\"\n\nopen LazyArray\n\n// Splices\n\n:silent\nval a = concat([0])\n\n:silent\nlet b = a.concat([1,2,3,4])\n\n:expect [0, 1, 2, 3, 4]\n[...b]\n//│ = [0, 1, 2, 3, 4]\n\n:expect [0, 1, 2, 3, 4]\nb.materialize()\n//│ = [0, 1, 2, 3, 4]\n\n\n// Views\n\n:silent\nlet a = mk(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) dropLeftRight(2, 3)() dropLeftRight(1, 1)()\n\n:expect 4\na.at(0)\n//│ = 4\n:expect 4\na.at(-3)\n//│ = 4\n:expect 5\na.at(1)\n//│ = 5\n:expect 5\na.at(-2)\n//│ = 5\n:expect 6\na.at(2)\n//│ = 6\n:expect 6\na.at(-1)\n//│ = 6\n\n:expect [4, 5, 6]\na\n//│ = [4, 5, 6]\n\n:expect [4, 5, 6]\n[...a]\n//│ = [4, 5, 6]\n\n:expect [4, 5, 6]\na.materialize()\n//│ = [4, 5, 6]\n\n:re\na.at(-4)\n//│ ═══[RUNTIME ERROR] RangeError: View.at: Index out of bounds\n\n:re\na.at(3)\n//│ ═══[RUNTIME ERROR] RangeError: View.at: Index out of bounds\n\n\n// View and Splices that represent the same array should be equal\n\n:silent\nlet xs = mk(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) dropLeftRight (1, 1)()\n\n:silent\nlet ys = concat([1, 2, 3], [4, 5, 6], [7, 8, 9, 10])\n\n:expect true\nequals([...xs], [...ys])\n//│ = true\n\n:expect true\nequals(xs, ys)\n//│ = true\n\n:expect true\nequals(xs.materialize(), ys.materialize())\n//│ = true\n\n\n// Mixing Views and Splices\n\n:silent\nlet ys1 = mk(0).concat([1, 2, 3, 4], [5, 6, 7], [8, 9])\n\n:expect [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n[...ys1]\n//│ = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n\n:expect 10\nys1.length\n//│ = 10\n\n:silent\nlet ys2 = LazyArray.dropLeftRight(2, 2)(ys1)\n\n:expect [2, 3, 4, 5, 6, 7]\nys2\n//│ = [2, 3, 4, 5, 6, 7]\n\n:silent\nlet ys2 = LazyArray.dropLeftRight(0, 2)(ys2)\n\n:expect [2, 3, 4, 5]\nys2\n//│ = [2, 3, 4, 5]\n\n\n// concat and __concat should do similar things\n\n:silent\nlet w1 = __concat(1, __split, xs, __split, ys1, __split,  ys1)\n\n:silent\nlet w2 = concat([1], xs, ys1, ys1)\n\n:expect true\nw1.length == w2.length\n//│ = true\n\n:expect true\nequals([...w1], [...w2])\n//│ = true\n\n:expect true\nequals(w1, w2)\n//│ = true\n\n:expect true\nequals(w1.materialize(), w2.materialize())\n//│ = true\n\n\n// object concat and slice\n\n:silent\nlet o1 = mk(1, 2, 3, 4, 5).slice(1, 4)\n\n:expect [2, 3, 4]\no1\n//│ = [2, 3, 4]\n\n:expect [2, 3, 4]\n[...o1]\n//│ = [2, 3, 4]\n\n:expect [2, 3, 4]\no1.materialize()\n//│ = [2, 3, 4]\n\nlet o2 = o1.concat([5, 6, 7])\n//│ o2 = [2, 3, 4, 5, 6, 7]\n\n:silent\nlet o3 = concat([1, 2, 3, 4])\n\n:silent\nlet o4 = o3.concat([5, 6, 7], [8])\n\nlet o5 = o4.slice(1, 7)\n//│ o5 = [2, 3, 4, 5, 6, 7]\n\n:expect true\nequals(o2, o5)\n//│ = true\n\n:expect true\nequals([...o2], [...o5])\n//│ = true\n\n:expect true\nequals(o2.materialize(), o5.materialize())\n//│ = true\n\n\n// slice indices\n\nlet r = [1,2,3,4,5,6,7,8,9,10]\nlet v = mk(1,2,3,4,5,6,7,8,9,10)\nlet s = concat([1,2,3], [4,5,6], [7,8,9,10])\n//│ r = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n//│ s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n//│ v = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\n:expect [4, 5]\n// both positive\nr.slice(3, 5)\n//│ = [4, 5]\nv.slice(3, 5)\n//│ = [4, 5]\ns.slice(3, 5)\n//│ = [4, 5]\ndropLeftRight(3, 5)(r)\n//│ = [4, 5]\n// both negative\nr.slice(-7, -5)\n//│ = [4, 5]\nv.slice(-7, -5)\n//│ = [4, 5]\ns.slice(-7, -5)\n//│ = [4, 5]\n// beg positive, fin negative\nr.slice(3, -5)\n//│ = [4, 5]\nv.slice(3, -5)\n//│ = [4, 5]\ns.slice(3, -5)\n//│ = [4, 5]\n// beg negative, fin positive\nr.slice(-7, 5)\n//│ = [4, 5]\nv.slice(-7, 5)\n//│ = [4, 5]\ns.slice(-7, 5)\n//│ = [4, 5]\n\n:expect []\n// both positive, beg > fin\nr.slice(5, 3)\n//│ = []\nv.slice(5, 3)\n//│ = []\ns.slice(5, 3)\n//│ = []\n// both negative, beg > fin\nr.slice(-5, -7)\n//│ = []\nv.slice(-5, -7)\n//│ = []\ns.slice(-5, -7)\n//│ = []\n// beg > arr length\nr.slice(10, 12)\n//│ = []\nv.slice(10, 12)\n//│ = []\ns.slice(10, 12)\n//│ = []\n// beg = fin = 0\nr.slice(0, 0)\n//│ = []\nv.slice(0, 0)\n//│ = []\ns.slice(0, 0)\n//│ = []\n\n\n// LazyArray on non-arrays\n\ndropLeftRight(1, 1)(\"hello\")\n//│ = [e, l, l]\n\nval mm = MutMap.empty\n//│ mm = MutMap(Map(0) {})\n\nmm |> MutMap.insert of \"a\", 1\n\n:re\nval uint8Arr = new Uint8Array([1, 2, 3, 4, 5])\n//│ ═══[RUNTIME ERROR] TypeError: Cannot freeze array buffer views with elements\n//│ uint8Arr = undefined\n\nval uint8Arr = new mut Uint8Array([1, 2, 3, 4, 5])\n//│ uint8Arr = Uint8Array { \"0\": 1, \"1\": 2, \"2\": 3, \"3\": 4, \"4\": 5 }\n\ndropLeftRight(1, 1)(uint8Arr)\n//│ = [2, 3, 4]\n\n:re\nconcat([1, 2, 3], \"hello\", uint8Arr, mm)\n//│ ═══[RUNTIME ERROR] Error: Expected an Array, got: MutMap(Map(1) {\"a\" => 1})\n\n:re\ndropLeftRight(0, 0)(mm)\n//│ ═══[RUNTIME ERROR] Error: Expected an Array, got: MutMap(Map(1) {\"a\" => 1})\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/LazyFingerTreeTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/LazyFingerTree.mls\"\nimport \"../../mlscript-compile/FingerTreeList.mls\"\nimport \"../../mlscript-compile/MutMap.mls\"\n\nopen LazyFingerTree\n\n// Splices\n\n:silent\nval a = concat(FingerTreeList.mk(0))\n\n:silent\nlet b = a.concat([1, 2, 3, 4])\n\n:expect [0, 1, 2, 3, 4]\n[...b]\n//│ = [0, 1, 2, 3, 4]\n\n:expect [0, 1, 2, 3, 4]\nb.materialize()\n//│ = [0, 1, 2, 3, 4]\n\n\n// Views\n\n:silent\nlet a = mk(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) dropLeftRight(2, 3)() dropLeftRight(1, 1)()\n\n:expect 4\na.at(0)\n//│ = 4\n:expect 4\na.at(-3)\n//│ = 4\n:expect 5\na.at(1)\n//│ = 5\n:expect 5\na.at(-2)\n//│ = 5\n:expect 6\na.at(2)\n//│ = 6\n:expect 6\na.at(-1)\n//│ = 6\n\n:expect [4, 5, 6]\na\n//│ = [4, 5, 6]\n\n:expect [4, 5, 6]\n[...a]\n//│ = [4, 5, 6]\n\n:re\na.at(-4)\n//│ ═══[RUNTIME ERROR] RangeError: View.at: Index out of bounds\n\n:re\na.at(3)\n//│ ═══[RUNTIME ERROR] RangeError: View.at: Index out of bounds\n\n\n// View and Splices that represent the same array should be equal\n\n:silent\nlet xs = mk(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) dropLeftRight(1, 1)()\n\n:silent\nlet ys = concat([1, 2, 3], [4, 5, 6], [7, 8, 9, 10])\n\n:expect true\nequals([...xs], [...ys])\n//│ = true\n\n:expect true\nequals(xs, ys)\n//│ = true\n\n:expect true\nequals(xs.materialize(), ys.materialize())\n//│ = true\n\n\n// Mixing Views and Splices\n\n:silent\nlet ys1 = concat(mk(0), [1, 2, 3, 4], [5, 6, 7], [8, 9])\n\n:expect [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n[...ys1]\n//│ = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n\n:expect 10\nys1.length\n//│ = 10\n\n:silent\nlet ys2 = LazyFingerTree.dropLeftRight(2, 2)(ys1)\n\n:expect [2, 3, 4, 5, 6, 7]\nys2\n//│ = [2, 3, 4, 5, 6, 7]\n\n:silent\nlet ys2 = LazyFingerTree.dropLeftRight(0, 2)(ys2)\n\n:expect [2, 3, 4, 5]\nys2\n//│ = [2, 3, 4, 5]\n\n\n// concat and __concat should do similar things\n\n:silent\nlet w1 = __concat(1, __split, xs, __split, ys1, __split,  ys1)\n\n:silent\nlet w2 = concat([1], xs, ys1, ys1)\n\n:expect true\nw1.length == w2.length\n//│ = true\n\n:expect true\nequals([...w1], [...w2])\n//│ = true\n\n:expect true\nequals(w1, w2)\n//│ = true\n\n:expect true\nequals(w1.materialize(), w2.materialize())\n//│ = true\n\n\n// object concat and slice\n\n:silent\nlet o1 = mk(1, 2, 3, 4, 5).slice(1, 4)\n\n:expect [2, 3, 4]\no1\n//│ = [2, 3, 4]\n\n:expect [2, 3, 4]\n[...o1]\n//│ = [2, 3, 4]\n\nlet o2 = o1.concat([5, 6, 7])\n//│ o2 = [2, 3, 4, 5, 6, 7]\n\n:silent\nlet o3 = concat([1, 2, 3, 4])\n\n:silent\nlet o4 = o3.concat([5, 6, 7], [8])\n\nlet o5 = o4.slice(1, 7)\n//│ o5 = [2, 3, 4, 5, 6, 7]\n\n:expect true\nequals(o2, o5)\n//│ = true\n\n:expect true\nequals([...o2], [...o5])\n//│ = true\n\n:expect true\nequals(o2.materialize(), o5)\n//│ = true\n\n// slice indices\n\nlet r = [1,2,3,4,5,6,7,8,9,10]\nlet v = mk(1,2,3,4,5,6,7,8,9,10)\nlet s = concat([1,2,3], [4,5,6], [7,8,9,10])\n//│ r = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n//│ s = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n//│ v = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n\n:expect [4, 5]\n// both positive\nr.slice(3, 5)\n//│ = [4, 5]\nv.slice(3, 5)\n//│ = [4, 5]\ns.slice(3, 5)\n//│ = [4, 5]\ndropLeftRight(3, 5)(r)\n//│ = [4, 5]\n// both negative\nr.slice(-7, -5)\n//│ = [4, 5]\nv.slice(-7, -5)\n//│ = [4, 5]\ns.slice(-7, -5)\n//│ = [4, 5]\n// beg positive, fin negative\nr.slice(3, -5)\n//│ = [4, 5]\nv.slice(3, -5)\n//│ = [4, 5]\ns.slice(3, -5)\n//│ = [4, 5]\n// beg negative, fin positive\nr.slice(-7, 5)\n//│ = [4, 5]\nv.slice(-7, 5)\n//│ = [4, 5]\ns.slice(-7, 5)\n//│ = [4, 5]\n\n:expect []\n// both positive, beg > fin\nr.slice(5, 3)\n//│ = []\nv.slice(5, 3)\n//│ = []\ns.slice(5, 3)\n//│ = []\n// both negative, beg > fin\nr.slice(-5, -7)\n//│ = []\nv.slice(-5, -7)\n//│ = []\ns.slice(-5, -7)\n//│ = []\n// beg > arr length\nr.slice(10, 12)\n//│ = []\nv.slice(10, 12)\n//│ = []\ns.slice(10, 12)\n//│ = []\n// beg = fin = 0\nr.slice(0, 0)\n//│ = []\nv.slice(0, 0)\n//│ = []\ns.slice(0, 0)\n//│ = []\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/PredefTest.mls",
    "content": ":js\n\n\n\n\nid(123)\n//│ = 123\n\n:e\n:re\nid()\n//│ ╔══[COMPILATION ERROR] Expected 1 arguments, got 0\n//│ ║  l.11: \tid()\n//│ ╙──      \t  ^^\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n\n\nprint(1, 2, 3)\n//│ > 1 2 3\n\n1 print()\n//│ > 1\n\n1 \\ print()\n//│ > 1\n\n1 \\ (print(_))()\n//│ > 1\n\n{1 \\ print(_)}(2)\n//│ > 1 2\n\n1\n  \\ print()\n//│ > 1\n\n\n2 + 2 |> print\n//│ > 4\n\n2 + 2 |> (_ * 2)\n//│ = 8\n\n2 + 2 .> (_ * 2)\n//│ = 6\n\nprint <| 2 + 2\n//│ > 4\n\n(_ * 2) <| 2 + 2 |> (_ + 1)\n//│ = 9\n\n2 + 2 !> print\n//│ > 4\n//│ = 4\n\nprint <! 2 + 2\n//│ > 4\n//│ = 4\n\nprint <! 2 + 2 |> (_ + 1)\n//│ > 4\n//│ = 5\n\n(_ + 1) <| 2 + 2 !> print\n//│ > 4\n//│ = 5\n\n\nfun f(x)(a) = x + a\n\n123 |> f of 1\n//│ = 124\n\n123 |> f <| 1\n//│ = 124\n\nfun f(x)(y)(a) = x + y + a\n\n123 |> f(1) of 2\n//│ = 126\n\n\ntuple passing(1, 2, 3) <| 4\n//│ = [1, 2, 3, 4]\n\npassing(tuple, 1, 2, 3) of 4, 5, 6\n//│ = [1, 2, 3, 4, 5, 6]\n\n(tuple passing(1, 2, 3)) of 4, 5, 6\n//│ = [1, 2, 3, 4, 5, 6]\n\n:re\ntuple passing(1, 2, 3) of 4, 5, 6\n//│ ═══[RUNTIME ERROR] TypeError: f.bind is not a function\n\n\n:re\n??(\"oops\")\n//│ ═══[RUNTIME ERROR] Error: Not implemented: oops\n\n:re\n:sjs\n???\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Predef.notImplementedError\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: Not implemented\n\n:re\n??? + 1\n//│ ═══[RUNTIME ERROR] Error: Not implemented\n\n:re\n1 + ???\n//│ ═══[RUNTIME ERROR] Error: Not implemented\n\n\nSymbols\n//│ = Symbols {\n//│   prettyPrint: Symbol(\"mlscript.prettyPrint\"),\n//│   definitionMetadata: Symbol(\"mlscript.definitionMetadata\"),\n//│   class: object Symbols\n//│ }\n\n\n// * Function composition is associative\n\nlet\n  f = ((_ + 1) >> (_ * 2)) >> (_ - 1)\n  g = (_ + 1) >> ((_ * 2) >> (_ - 1))\n//│ f = fun\n//│ g = fun\n\n[f(123), g(123)]\n//│ = [247, 247]\n\n\n// *** Folding ***\n\n\nfold(+)(0, 1, 2, 3)\n//│ = 6\n\nfold(-)(0, 1, 2, 3)\n//│ = -6\n\nfold(print)(0, 1, 2, 3)\n//│ > 0 1\n//│ > () 2\n//│ > () 3\n\nfold(tuple)(0, 1, 2, 3)\n//│ = [[[0, 1], 2], 3]\n\nfold(+) of\n  0\n  1\n  2\n  3\n//│ = 6\n\n:breakme\n:re\n:e\nfold(+)()\n\nfold(tuple) of\n  \"A\" +\n  \"B\"\n  \"C\"\n//│ = [\"AB\", \"C\"]\n\n\nfoldr(+)(0, 1, 2, 3)\n//│ = 6\n\nfoldr(-)(0, 1, 2, 3)\n//│ = -2\n\nfoldr(tuple)(0, 1, 2, 3)\n//│ = [0, [1, [2, 3]]]\n\n:todo\nfoldr(+)()\n//│ ╔══[COMPILATION ERROR] Expected at least 1 arguments, got 0\n//│ ║  l.185: \tfoldr(+)()\n//│ ╙──       \t        ^^\n//│ ═══[RUNTIME ERROR] Error: MLscript call unexpectedly returned `undefined`, the forbidden value.\n\n\n// An alternative implementation of foldr\nfun foldr(f)(first, ...rest) =\n  let len = rest.length\n  if len == 0 then first else...\n  let\n    init = rest.at(len - 1)\n    i = len - 2\n  while i >= 0 do\n    set\n      init = f(rest.at(i), init)\n      i -= 1\n  f(first, init)\n\nfoldr(+)(0, 1, 2, 3)\n//│ = 6\n\nfoldr(-)(0, 1, 2, 3)\n//│ = -2\n\n\nfold(+) of\n  \"0\"\n  \"1\"\n  \"2\"\n  \"3\"\n//│ = \"0123\"\n\nimport \"../../mlscript-compile/Iter.mls\"\n\nIter.joined(_, \"\") of [\n  \"0\"\n  \"1\"\n  \"2\"\n  \"3\"\n]\n//│ = fun\n\n\nmkStr of\n  \"0\"\n  \"1\"\n  \"2\"\n  \"3\"\n//│ = \"0123\"\n\nmkStr of\n  \"0\"\n  1\n//│ // Standard Error:\n//│ Assertion failed\n//│ \n//│ = \"01\"\n\n// loose equality is disabled\n\nnull == undefined\n//│ = false\n\nundefined == null\n//│ = false\n\nundefined === null\n//│ = false\n\n[] == false\n//│ = false\n\n\"0\" == false\n//│ = false\n\n1 == true\n//│ = false\n\n// * Arrays are compared elementwise\n\n[1, 2, 3] == [1, 2, 3]\n//│ = true\n\n// non-data classes unchanged\n\n:silent\nclass B(val a, b)\nlet x = B(1, 2)\nlet y = B(1, 4)\n\nx == y\n//│ = false\n\n// data classes are equal from arguments\n\n:silent\ndata class A(a, b, c)\nmodule M with\n  data class A(a, b, c)\nlet x = A(1, 2, 3)\nlet y = A(1, 2, 3)\n\nx == y\n//│ = true\n\nx != y\n//│ = false\n\nx == A(2, 3, 4)\n//│ = false\n\nx == M.A(1, 2, 3)\n//│ = false\n\nA([x], 2, 3) == A([y], 2, 3)\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/PrettyPrintTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Rendering.mls\"\n\nopen Rendering\n\n// We set `breakLength` to 74. With the `print` function and diff test comments\n// added, we can use an 80-character-wide ruler to check whether line breaks\n// work correctly.\nfun show(value) = \n  let breakLength = 74\n  let rendered = render of value, indent: 2, breakLength: breakLength\n  print of rendered\n    .split(\"\\n\")\n    .map of (line, _, _) =>\n      if line.length > breakLength then\n        line\n      else line + \" \".repeat(breakLength - line.length) + \"┊\"\n    .join(\"\\n\")\n\nshow of [1, 2, 3, 4]\n//│ > [1, 2, 3, 4]                                                              ┊\n\n:silent\nlet shortText = \"Hello, world!\"\nlet longText = \"This is a very long line. \".repeat(4).trim()\n\n// Long strings can exceed the `breakLength` limit.\nshow of longText\n//│ > \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\"\n\nshow of [1, longText, 2, 3, 4, 5]\n//│ > [                                                                         ┊\n//│ >   1,                                                                      ┊\n//│ >   \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\",\n//│ >   2,                                                                      ┊\n//│ >   3,                                                                      ┊\n//│ >   4,                                                                      ┊\n//│ >   5                                                                       ┊\n//│ > ]                                                                         ┊\n\nshow of x: 0, y: 0\n//│ > {x: 0, y: 0}                                                              ┊\n\nshow of x: 0, y: 0, z: longText\n//│ > {                                                                         ┊\n//│ >   x: 0,                                                                   ┊\n//│ >   y: 0,                                                                   ┊\n//│ >   z: \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\"\n//│ > }                                                                         ┊\n\nshow of x: 0, y: 0, z: [shortText, 0, 0]\n//│ > {x: 0, y: 0, z: [\"Hello, world!\", 0, 0]}                                  ┊\n\nshow of x: 0, y: 0, z: [longText, 0, 0]\n//│ > {                                                                         ┊\n//│ >   x: 0,                                                                   ┊\n//│ >   y: 0,                                                                   ┊\n//│ >   z: [                                                                    ┊\n//│ >     \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\",\n//│ >     0,                                                                    ┊\n//│ >     0                                                                     ┊\n//│ >   ]                                                                       ┊\n//│ > }                                                                         ┊\n\nshow of x: 0, y: [shortText, shortText, shortText], z: [longText, 0, 0]\n//│ > {                                                                         ┊\n//│ >   x: 0,                                                                   ┊\n//│ >   y: [\"Hello, world!\", \"Hello, world!\", \"Hello, world!\"],                 ┊\n//│ >   z: [                                                                    ┊\n//│ >     \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\",\n//│ >     0,                                                                    ┊\n//│ >     0                                                                     ┊\n//│ >   ]                                                                       ┊\n//│ > }                                                                         ┊\n\n// It should break `y` but keep `x` and `z` inline.\nshow of\n  x: (a: \"A\", b: \"B\", c: \"C\")\n  y: [shortText, shortText, shortText, shortText, shortText]\n  z: [1, 2, 3, 4]\n//│ > {                                                                         ┊\n//│ >   x: {a: \"A\", b: \"B\", c: \"C\"},                                            ┊\n//│ >   y: [                                                                    ┊\n//│ >     \"Hello, world!\",                                                      ┊\n//│ >     \"Hello, world!\",                                                      ┊\n//│ >     \"Hello, world!\",                                                      ┊\n//│ >     \"Hello, world!\",                                                      ┊\n//│ >     \"Hello, world!\"                                                       ┊\n//│ >   ],                                                                      ┊\n//│ >   z: [1, 2, 3, 4]                                                         ┊\n//│ > }                                                                         ┊\n\nshow of Array(10)\n//│ > [<10 empty items>]                                                        ┊\n\nshow of [-100, ...Array(5), BigInt(\"10000000\")]\n//│ > [-100, undefined, undefined, undefined, undefined, undefined, 10000000n]  ┊\n\nshow of [-100, ...Array(5), BigInt(\"100000000\")]\n//│ > [-100, undefined, undefined, undefined, undefined, undefined, 100000000n] ┊\n\nshow of [\"hello\", ...Array(7), \"world\"]\n//│ > [                                                                         ┊\n//│ >   \"hello\",                                                                ┊\n//│ >   undefined,                                                              ┊\n//│ >   undefined,                                                              ┊\n//│ >   undefined,                                                              ┊\n//│ >   undefined,                                                              ┊\n//│ >   undefined,                                                              ┊\n//│ >   undefined,                                                              ┊\n//│ >   undefined,                                                              ┊\n//│ >   \"world\"                                                                 ┊\n//│ > ]                                                                         ┊\n\nshow of Object.assign of\n  () => 42\n  x: 0\n  y: [...Array(8)]\n  z: 512\n//│ > fun {                                                                     ┊\n//│ >   x: 0,                                                                   ┊\n//│ >   y: [                                                                    ┊\n//│ >     undefined,                                                            ┊\n//│ >     undefined,                                                            ┊\n//│ >     undefined,                                                            ┊\n//│ >     undefined,                                                            ┊\n//│ >     undefined,                                                            ┊\n//│ >     undefined,                                                            ┊\n//│ >     undefined,                                                            ┊\n//│ >     undefined                                                             ┊\n//│ >   ],                                                                      ┊\n//│ >   z: 512                                                                  ┊\n//│ > }                                                                         ┊\n\nshow of x: new Set([1, 2, 3, 4]), y: new Set([5, 6, 7, 8])\n//│ > {x: Set(4) {1, 2, 3, 4}, y: Set(4) {5, 6, 7, 8}}                          ┊\n\nshow of x: new Set([longText])\n//│ > {                                                                         ┊\n//│ >   x: Set(1) {                                                             ┊\n//│ >     \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\"\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\n:silent\nlet testSet = new Set([shortText, (), Symbol.for(\"you\"), 1, 2, 3, 4, 5, 6, 7])\n\nshow of x: testSet\n//│ > {x: Set(10) {\"Hello, world!\", (), Symbol(\"you\"), 1, 2, 3, 4, 5, 6, 7}}    ┊\n\ntestSet.add(8); show of x: testSet\n//│ > {x: Set(11) {\"Hello, world!\", (), Symbol(\"you\"), 1, 2, 3, 4, 5, 6, 7, 8}} ┊\n\ntestSet.add(9); show of x: testSet\n//│ > {                                                                         ┊\n//│ >   x: Set(12) {                                                            ┊\n//│ >     \"Hello, world!\",                                                      ┊\n//│ >     (),                                                                   ┊\n//│ >     Symbol(\"you\"),                                                        ┊\n//│ >     1,                                                                    ┊\n//│ >     2,                                                                    ┊\n//│ >     3,                                                                    ┊\n//│ >     4,                                                                    ┊\n//│ >     5,                                                                    ┊\n//│ >     6,                                                                    ┊\n//│ >     7,                                                                    ┊\n//│ >     8,                                                                    ┊\n//│ >     9                                                                     ┊\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\nshow of new Map([[1, 2], [3, 4]])\n//│ > Map(2) {1 => 2, 3 => 4}                                                   ┊\n\nshow of new Map([[longText, shortText]])\n//│ > Map(1) {                                                                  ┊\n//│ >   \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\" => \"Hello, world!\"\n//│ > }                                                                         ┊\n\nshow of new Map([[{ x: shortText }, shortText]])\n//│ > Map(1) {{x: \"Hello, world!\"} => \"Hello, world!\"}                          ┊\n\nshow of new Map([[{ x: longText }, shortText]])\n//│ > Map(1) {                                                                  ┊\n//│ >   {                                                                       ┊\n//│ >     x: \"This is a very long line. This is a very long line. This is a very long line. This is a very long line.\"\n//│ >   } => \"Hello, world!\"                                                    ┊\n//│ > }                                                                         ┊\n\n:silent\nlet testKey = mut { x: 0, y: 0, z: 0 }\nlet testMap = new Map([[testKey, testKey]])\n\nshow of testMap\n//│ > Map(1) {{x: 0, y: 0, z: 0} => {x: 0, y: 0, z: 0}}                         ┊\n\nset testKey.w = 0, show of testMap\n//│ > Map(1) {{x: 0, y: 0, z: 0, w: 0} => {x: 0, y: 0, z: 0, w: 0}}             ┊\n\nset testKey.a = 42, show of testMap\n//│ > Map(1) {{x: 0, y: 0, z: 0, w: 0, a: 42} => {x: 0, y: 0, z: 0, w: 0, a: 42}}\n\n// TODO\nset testKey.b = 404, show of testMap\n//│ > Map(1) {                                                                  ┊\n//│ >   {x: 0, y: 0, z: 0, w: 0, a: 42, b: 404} => {x: 0, y: 0, z: 0, w: 0, a: 42, b: 404}\n//│ > }                                                                         ┊\n\n:silent\nlet testKey = mut { a: 1, b: a * 10, c: b * 10, d: c * 10, e: d * 10 }\nlet testMap = new Map([[testKey, shortText]])\n\nshow of testMap\n//│ > Map(1) {{a: 1, b: 10, c: 100, d: 1000, e: 10000} => \"Hello, world!\"}      ┊\n\nset testKey.x = 42, show of testMap\n//│ > Map(1) {{a: 1, b: 10, c: 100, d: 1000, e: 10000, x: 42} => \"Hello, world!\"}\n\nset testKey.y = 100, show of testMap\n//│ > Map(1) {                                                                  ┊\n//│ >   {a: 1, b: 10, c: 100, d: 1000, e: 10000, x: 42, y: 100} => \"Hello, world!\"\n//│ > }                                                                         ┊\n\nset testKey.z = shortText, show of testMap\n//│ > Map(1) {                                                                  ┊\n//│ >   {a: 1, b: 10, c: 100, d: 1000, e: 10000, x: 42, y: 100, z: \"Hello, world!\"} => \"Hello, world!\"\n//│ > }                                                                         ┊\n\ntestMap.set(testKey, text: shortText), show of testMap\n//│ > Map(1) {                                                                  ┊\n//│ >   {a: 1, b: 10, c: 100, d: 1000, e: 10000, x: 42, y: 100, z: \"Hello, world!\"} => {text: \"Hello, world!\"}\n//│ > }                                                                         ┊\n\n:silent\nlet fakeAddress =\n  street: \"123 Main St\"\n  city: \"Springfield\"\n  state: \"IL\"\n  zip: \"62704\"\n  country: \"USA\"\n\nshow of new Set of [fakeAddress]\n//│ > Set(1) {                                                                  ┊\n//│ >   {                                                                       ┊\n//│ >     street: \"123 Main St\",                                                ┊\n//│ >     city: \"Springfield\",                                                  ┊\n//│ >     state: \"IL\",                                                          ┊\n//│ >     zip: \"62704\",                                                         ┊\n//│ >     country: \"USA\"                                                        ┊\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\nshow of\n  firstName: \"John\"\n  lastName: \"Doe\"\n  // This object should cause its parent object to be split into multiple lines,\n  // but it should be printed on a single line itself.\n  company:\n    name: \"Acme Corp.\"\n    industry: \"Manufacturing\"\n  age: 42\n  email: \"john.doe@acme.com\"\n  phone: \"+1 555-1234-888\"\n  address: fakeAddress\n  isActive: true\n  roles: [\"admin\", \"user\"]\n  metadata:\n    created: \"2024-01-01\"\n    updated: \"2024-06-01\"\n//│ > {                                                                         ┊\n//│ >   firstName: \"John\",                                                      ┊\n//│ >   lastName: \"Doe\",                                                        ┊\n//│ >   company: {name: \"Acme Corp.\", industry: \"Manufacturing\"},               ┊\n//│ >   age: 42,                                                                ┊\n//│ >   email: \"john.doe@acme.com\",                                             ┊\n//│ >   phone: \"+1 555-1234-888\",                                               ┊\n//│ >   address: {                                                              ┊\n//│ >     street: \"123 Main St\",                                                ┊\n//│ >     city: \"Springfield\",                                                  ┊\n//│ >     state: \"IL\",                                                          ┊\n//│ >     zip: \"62704\",                                                         ┊\n//│ >     country: \"USA\"                                                        ┊\n//│ >   },                                                                      ┊\n//│ >   isActive: true,                                                         ┊\n//│ >   roles: [\"admin\", \"user\"],                                               ┊\n//│ >   metadata: {created: \"2024-01-01\", updated: \"2024-06-01\"}                ┊\n//│ > }                                                                         ┊\n\nshow of\n  level1: \n    level2:\n      level3:\n        level4:\n          level5:\n            level6:\n              level7:\n                level8:\n                  level9:\n                    level10: \"deep value\"\n//│ > {                                                                         ┊\n//│ >   level1: {                                                               ┊\n//│ >     level2: {                                                             ┊\n//│ >       level3: {                                                           ┊\n//│ >         level4: {                                                         ┊\n//│ >           level5: {                                                       ┊\n//│ >             level6: {level7: {level8: {level9: {level10: \"deep value\"}}}} ┊\n//│ >           }                                                               ┊\n//│ >         }                                                                 ┊\n//│ >       }                                                                   ┊\n//│ >     }                                                                     ┊\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\n:silent\nlet nested = [[[[[[[[[[[[[[[[[[[[[[[[[[[[\"hkhkhkhkhkhkhkhk\"]]]]]]]]]]]]]]]]]]]]]]]]]]]]\n\nshow of nested\n//│ > [[[[[[[[[[[[[[[[[[[[[[[[[[[[\"hkhkhkhkhkhkhkhk\"]]]]]]]]]]]]]]]]]]]]]]]]]]]]┊\n\nshow of [nested]\n//│ > [                                                                         ┊\n//│ >   [                                                                       ┊\n//│ >     [[[[[[[[[[[[[[[[[[[[[[[[[[[\"hkhkhkhkhkhkhkhk\"]]]]]]]]]]]]]]]]]]]]]]]]]]]\n//│ >   ]                                                                       ┊\n//│ > ]                                                                         ┊\n\nshow of [[[[nested]]]]\n//│ > [                                                                         ┊\n//│ >   [                                                                       ┊\n//│ >     [                                                                     ┊\n//│ >       [                                                                   ┊\n//│ >         [                                                                 ┊\n//│ >           [                                                               ┊\n//│ >             [                                                             ┊\n//│ >               [                                                           ┊\n//│ >                 [[[[[[[[[[[[[[[[[[[[[[[[\"hkhkhkhkhkhkhkhk\"]]]]]]]]]]]]]]]]]]]]]]]]\n//│ >               ]                                                           ┊\n//│ >             ]                                                             ┊\n//│ >           ]                                                               ┊\n//│ >         ]                                                                 ┊\n//│ >       ]                                                                   ┊\n//│ >     ]                                                                     ┊\n//│ >   ]                                                                       ┊\n//│ > ]                                                                         ┊\n\n:silent\nlet nested = a: b: c: d: e: f: g: \"This property name is very long.\": 0\n\nshow of nested\n//│ > {a: {b: {c: {d: {e: {f: {g: {\"This property name is very long.\": 0}}}}}}}}┊\n\nshow of x: y: nested\n//│ > {                                                                         ┊\n//│ >   x: {                                                                    ┊\n//│ >     y: {                                                                  ┊\n//│ >       a: {                                                                ┊\n//│ >         b: {                                                              ┊\n//│ >           c: {d: {e: {f: {g: {\"This property name is very long.\": 0}}}}}  ┊\n//│ >         }                                                                 ┊\n//│ >       }                                                                   ┊\n//│ >     }                                                                     ┊\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\nshow of x: y: z: nested\n//│ > {                                                                         ┊\n//│ >   x: {                                                                    ┊\n//│ >     y: {                                                                  ┊\n//│ >       z: {                                                                ┊\n//│ >         a: {                                                              ┊\n//│ >           b: {                                                            ┊\n//│ >             c: {d: {e: {f: {g: {\"This property name is very long.\": 0}}}}}┊\n//│ >           }                                                               ┊\n//│ >         }                                                                 ┊\n//│ >       }                                                                   ┊\n//│ >     }                                                                     ┊\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\nshow of u: v: w:\n  i: j: k: nested\n  x: y: z: [nested, nested]\n//│ > {                                                                         ┊\n//│ >   u: {                                                                    ┊\n//│ >     v: {                                                                  ┊\n//│ >       w: {                                                                ┊\n//│ >         i: {                                                              ┊\n//│ >           j: {                                                            ┊\n//│ >             k: {                                                          ┊\n//│ >               a: {                                                        ┊\n//│ >                 b: {                                                      ┊\n//│ >                   c: {                                                    ┊\n//│ >                     d: {                                                  ┊\n//│ >                       e: {f: {g: {\"This property name is very long.\": 0}}}┊\n//│ >                     }                                                     ┊\n//│ >                   }                                                       ┊\n//│ >                 }                                                         ┊\n//│ >               }                                                           ┊\n//│ >             }                                                             ┊\n//│ >           }                                                               ┊\n//│ >         },                                                                ┊\n//│ >         x: {                                                              ┊\n//│ >           y: {                                                            ┊\n//│ >             z: [                                                          ┊\n//│ >               {                                                           ┊\n//│ >                 a: {                                                      ┊\n//│ >                   b: {                                                    ┊\n//│ >                     c: {                                                  ┊\n//│ >                       d: {                                                ┊\n//│ >                         e: {                                              ┊\n//│ >                           f: {g: {\"This property name is very long.\": 0}} ┊\n//│ >                         }                                                 ┊\n//│ >                       }                                                   ┊\n//│ >                     }                                                     ┊\n//│ >                   }                                                       ┊\n//│ >                 }                                                         ┊\n//│ >               },                                                          ┊\n//│ >               {                                                           ┊\n//│ >                 a: {                                                      ┊\n//│ >                   b: {                                                    ┊\n//│ >                     c: {                                                  ┊\n//│ >                       d: {                                                ┊\n//│ >                         e: {                                              ┊\n//│ >                           f: {g: {\"This property name is very long.\": 0}} ┊\n//│ >                         }                                                 ┊\n//│ >                       }                                                   ┊\n//│ >                     }                                                     ┊\n//│ >                   }                                                       ┊\n//│ >                 }                                                         ┊\n//│ >               }                                                           ┊\n//│ >             ]                                                             ┊\n//│ >           }                                                               ┊\n//│ >         }                                                                 ┊\n//│ >       }                                                                   ┊\n//│ >     }                                                                     ┊\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\nclass Hola with\n  fun toString() = \"Hola.\\nMi amigo.\\n\\u00bfQu\\u00e9 tal?\\nHasta luego.\"\n\n// Customized `toString` should be able to trigger breaking lines.\nshow of x: y: new Hola\n//│ > {                                                                         ┊\n//│ >   x: {                                                                    ┊\n//│ >     y: Hola. \\                                                            ┊\n//│ >       Mi amigo. \\                                                         ┊\n//│ >       ¿Qué tal? \\                                                         ┊\n//│ >       Hasta luego.                                                        ┊\n//│ >   }                                                                       ┊\n//│ > }                                                                         ┊\n\nclass Hello with\n  fun toString() = \"Hi there. How's going?\"\n\nshow of x: y: z: new Hello\n//│ > {x: {y: {z: Hi there. How's going?}}}                                     ┊\n\n//   ___        _   _\n//  / _ \\ _ __ | |_(_) ___  _ __  ___\n// | | | | '_ \\| __| |/ _ \\| '_ \\/ __|\n// | |_| | |_) | |_| | (_) | | | \\__ \\\n//  \\___/| .__/ \\__|_|\\___/|_| |_|___/\n//       |_|\n\n:silent\nlet testObject =\n  x: x: x: x: x: 42\n  y: shortText\n\nrender of testObject\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, breakLength: null\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, breakLength: undefined\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, breakLength: ()\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, breakLength: \"bad options\"\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, breakLength: -10\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, indent: null\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, indent: undefined\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, indent: ()\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, indent: \"bad options\"\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, indent: -10\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, padding: true\n//│ = \"{ x: { x: { x: { x: { x: 42 } } } }, y: \\\"Hello, world!\\\" }\"\n\nrender of testObject, padding: null\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, padding: undefined\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, padding: ()\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\nrender of testObject, padding: \"bad value\"\n//│ = \"{x: {x: {x: {x: {x: 42}}}}, y: \\\"Hello, world!\\\"}\"\n\n\n// * Strangely, the first line is not broken, but the rest is... @Luyu whyyyy\n[\n  [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1]\n  [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1]\n  [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1]\n]\n//│ = [\n//│   [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1],\n//│   [\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1\n//│   ],\n//│   [\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1,\n//│     2,\n//│     3,\n//│     1\n//│   ]\n//│ ]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/RecordTest.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Record.mls\"\n\n\nlet src =\n  k0: 0\n  k1: 1\n  k2: 2\n  k3: 3\n  k4: 4\n//│ src = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4}\n\nsrc Record.steal(\"k1\", \"k2\", \"k3\")\n//│ = {k1: 1, k2: 2, k3: 3}\n\nlet dst =\n  k0: \"0\"\n  ...src Record.steal(\"k1\", \"k2\", \"k3\")\n  k4: \"4\"\n//│ dst = {k0: \"0\", k1: 1, k2: 2, k3: 3, k4: \"4\"}\n\n\n// * Alternative 'cute' API\n\nimport \"../../mlscript-compile/Iter.mls\"\n\nfun steal(...fields_from) =\n  let from = fields_from.at(-1).from\n  let fields = fields_from.slice(0, -1)\n  let rcd = new mut Object\n  fields Iter.each of f => set rcd.(f) = from.(f)\n  rcd\n\nlet src =\n  k0: 0\n  k1: 1\n  k2: 2\n  k3: 3\n  k4: 4\n//│ src = {k0: 0, k1: 1, k2: 2, k3: 3, k4: 4}\n\nsteal(\"k1\", \"k2\", \"k3\", from: src)\n//│ = {k1: 1, k2: 2, k3: 3}\n\nlet dst =\n  k0: \"0\"\n  ...steal(\"k1\", \"k2\", \"k3\", from: src)\n  k4: \"4\"\n//│ dst = {k0: \"0\", k1: 1, k2: 2, k3: 3, k4: \"4\"}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/RenderingTest.mls",
    "content": ":js\n\n\nrender(())\n//│ = \"()\"\n\nrender(null)\n//│ = \"null\"\n\nrender(undefined)\n//│ = \"undefined\"\n\nrender(123)\n//│ = \"123\"\n\nrender(\"123\")\n//│ = \"\\\"123\\\"\"\n\nrender(\"12\\n3\")\n//│ = \"\\\"12\\\\n3\\\"\"\n\nrender(\"12\\\\n3\")\n//│ = \"\\\"12\\\\\\\\n3\\\"\"\n\nrender([])\n//│ = \"[]\"\n\nrender([1])\n//│ = \"[1]\"\n\nrender([1, 2])\n//│ = \"[1, 2]\"\n\nrender([1,2,3])\n//│ = \"[1, 2, 3]\"\n\nrender([1,2,3,4])\n//│ = \"[1, 2, 3, 4]\"\n\nrender(1)\n//│ = \"1\"\n\nrender(Object.create(null))\n//│ = \"{}\"\n\nrender(x => x)\n//│ = \"fun\"\n\nclass Foo\n\nrender(Foo)\n//│ = \"class Foo\"\n\nrender(new Foo)\n//│ = \"Foo\"\n\n\ninterleave(0) of 1, 2, 3\n//│ = [1, 0, 2, 0, 3]\n\nlet arg = [1, 2]\n//│ arg = [1, 2]\n\nmap(render)(...arg)\n//│ = [\"1\", \"2\"]\n\nfold(+)(\"[\", ...interleave(\"|\")(...map(render)(...arg)), \"]\")\n//│ = \"[1|2]\"\n\ninterleave(\", \") of 1, 2\n//│ = [1, \", \", 2]\n\n\ndata class Foo(val xs)\n\nrender(Foo([1, 2, 3]))\n//│ = \"Foo([1, 2, 3])\"\n\nrender([Foo([1]), Foo([2])])\n//│ = \"[Foo([1]), Foo([2])]\"\n\n\nrenderAsStr(\"1\")\n//│ = \"1\"\n\nrenderAsStr(1)\n//│ = \"1\"\n\nlet xs = [1, 2]\n//│ xs = [1, 2]\n\nmap(renderAsStr)(xs)\n//│ = [\"[1, 2]\"]\n\nmap(renderAsStr(_))(xs)\n//│ = [\"[1, 2]\"]\n\nmap(_ + 1)(...xs)\n//│ = [2, 3]\n\nrenderAsStr of new RegExp(\"test\")\n//│ = \"/test/\"\n\nrenderAsStr of Symbol.for(\"mlscript\")\n//│ = \"Symbol(\\\"mlscript\\\")\"\n\nrenderAsStr of BigInt(\"2\" + \"0\".repeat(30))\n//│ = \"2000000000000000000000000000000n\"\n\nrenderAsStr of new Set of [1, 2, 3]\n//│ = \"Set(3) {1, 2, 3}\"\n\nrenderAsStr of new Map of []\n//│ = \"Map(0) {}\"\n\nrenderAsStr of new Map of [[1, 2], [3, 4]]\n//│ = \"Map(2) {1 => 2, 3 => 4}\"\n\nrenderAsStr of new Map of [[Foo, 2], [Symbol, 1]]\n//│ = \"Map(2) {fun Foo { class: class Foo } => 2, class Symbol => 1}\"\n\nrenderAsStr of new Map([[{ a: 0 }, { b: 0 }]])\n//│ = \"Map(1) {{a: 0} => {b: 0}}\"\n\nrenderAsStr of new Error(\"hello\")\n//│ = \"Error: hello\"\n\nrenderAsStr of new TypeError(\"hello\")\n//│ = \"TypeError: hello\"\n\nrenderAsStr of Object.create(null)\n//│ = \"{}\"\n\n// `Object`'s prototype has `null` as the prototype.\nrenderAsStr of Object.prototype\n//│ = \"{}\"\n\nrenderAsStr of hello: \"world\"\n//│ = \"{hello: \\\"world\\\"}\"\n\nrenderAsStr of Object.assign(Object.create(null), hello: \"world\")\n//│ = \"{hello: \\\"world\\\"}\"\n\nrenderAsStr of new WeakMap\n//│ = \"WeakMap { <items unknown> }\"\n\nrenderAsStr of new WeakSet\n//│ = \"WeakSet { <items unknown> }\"\n\n//  _____                 _   _\n// |  ___|   _ _ __   ___| |_(_) ___  _ __  ___\n// | |_ | | | | '_ \\ / __| __| |/ _ \\| '_ \\/ __|\n// |  _|| |_| | | | | (__| |_| | (_) | | | \\__ \\\n// |_|   \\__,_|_| |_|\\___|\\__|_|\\___/|_| |_|___/\n//\n// =============================================\n\nclass Foo\n\nrenderAsStr of Foo\n//│ = \"class Foo\"\n\nset Foo.bar = (direction: \"vertical\")\n\nrenderAsStr of Foo\n//│ = \"class Foo\"\n\nclass Bar extends Foo\n\nrenderAsStr of Bar\n//│ = \"class Bar\"\n\nrenderAsStr of new Bar\n//│ = \"Bar\"\n\nfun test() = ()\n\nrenderAsStr of test\n//│ = \"fun test\"\n\nrenderAsStr of [42, 100, test]\n//│ = \"[42, 100, fun test]\"\n\nset test.test = test\n\nrenderAsStr of test\n//│ = \"fun test { test: ref'1 } as ref'1\"\n\nlet greetings = () => \"hello\"\n//│ greetings = fun greetings\n\nrenderAsStr of greetings\n//│ = \"fun greetings\"\n\nrenderAsStr of x => x * 2\n//│ = \"fun\"\n\nrenderAsStr of Object.assign(x => x * 2, { a: 2 })\n//│ = \"fun { a: 2 }\"\n\nrenderAsStr of globalThis.setImmediate\n//│ = \"fun setImmediate\"\n\n//   ____ _                _\n//  / ___(_)_ __ ___ _   _| | __ _ _ __\n// | |   | | '__/ __| | | | |/ _` | '__|\n// | |___| | | | (__| |_| | | (_| | |\n//  \\____|_|_|  \\___|\\__,_|_|\\__,_|_|\n//\n// =====================================\n\n// Test: simple circular reference.\n\nlet a = mut\n  x: 0\n  y: 1\n//│ a = {x: 0, y: 1}\n\nset a.x = a\n\na\n//│ = {x: ref'1, y: 1} as ref'1\n\n// Test: an object is referenced multiple times in a circular way.\n\nlet tree =\n  left: mut\n    left: null\n    right: null\n  right: mut\n    left: null\n    right: null\n//│ tree = {left: {left: null, right: null}, right: {left: null, right: null}}\n\nset tree.left.left = tree\nset tree.right.left = tree\n\ntree\n//│ = {left: {left: ref'1, right: null}, right: {left: ref'1, right: null}} as ref'1\n\n// Test: nested circular reference.\n\nlet b = mut [a, a]\n//│ b = [{x: ref'1, y: 1} as ref'1, {x: ref'2, y: 1} as ref'2]\n\n// If the same circular object appears multiple times, it should be rendered as\n// the same reference in single-line mode.\nrender(b)\n//│ = \"[{x: ref'1, y: 1} as ref'1, {x: ref'1, y: 1} as ref'1]\"\n\nb.push(b)\n//│ = 3\n\nb\n//│ = [{x: ref'1, y: 1} as ref'1, {x: ref'2, y: 1} as ref'2, ref'3] as ref'3\n\nlet functionWithProperties = Object.assign(x => x, \"kind\": \"Callable\")\n//│ functionWithProperties = fun { kind: \"Callable\" }\n\nfunctionWithProperties\n//│ = fun { kind: \"Callable\" }\n\nfunctionWithProperties.kind\n//│ = \"Callable\"\n\n//   ___  _     _           _\n//  / _ \\| |__ (_) ___  ___| |_\n// | | | | '_ \\| |/ _ \\/ __| __|\n// | |_| | |_) | |  __/ (__| |_\n//  \\___/|_.__// |\\___|\\___|\\__|\n//           |__/\n// =============================\n\nlet something = mut { x: 0 }\n//│ something = {x: 0}\n\nObject.defineProperty(something, \"y\", enumerable: true, get: () => 42)\n//│ = {x: 0, y: [Getter]}\n\nObject.defineProperty of\n  something, \"z\"\n  enumerable: true\n  get: () => 42\n  \"set\": (value) => print(\"The user tries to set the value to \" + value)\n//│ = {x: 0, y: [Getter], z: [Getter/Setter]}\n\nrenderAsStr of\n  \"\\u6d4b\\u8bd5\": \"Test\"\n  \"\\u4f60\\u597d\": \"Hello\"\n//│ = \"{测试: \\\"Test\\\", 你好: \\\"Hello\\\"}\"\n\nrenderAsStr of\n  \"a property name with spaces\": true\n//│ = \"{\\\"a property name with spaces\\\": true}\"\n\n//   ____ _\n//  / ___| | __ _ ___ ___  ___  ___\n// | |   | |/ _` / __/ __|/ _ \\/ __|\n// | |___| | (_| \\__ \\__ \\  __/\\__ \\\n//  \\____|_|\\__,_|___/___/\\___||___/\n//\n// =================================\n\nobject Singleton\n\nrenderAsStr of Singleton\n//│ = \"Singleton\"\n\nclass Phantom\n\n// Parameter-less classes should be rendered as `class`.\nrenderAsStr of Phantom\n//│ = \"class Phantom\"\n\ndata class Point(x: Num, y: Num)\n\n// While classes with parameters should be rendered as `fun`.\nrenderAsStr of Point\n//│ = \"fun Point { class: class Point }\"\n\nrenderAsStr of Point.class\n//│ = \"class Point\"\n\nrenderAsStr of Point(1, 2)\n//│ = \"Point(1, 2)\"\n\nrenderAsStr of Point(1, 2)\n//│ = \"Point(1, 2)\"\n\nclass Bar(x: Int, val a: Int)\n\nrenderAsStr of Bar(123, 789)\n//│ = \"Bar(_, 789)\"\n\nimport \"../../mlscript-compile/Stack.mls\"\n\nopen Stack\n\nrenderAsStr of 1 :: 2 :: 3 :: 4\n//│ = \"Cons(1, Cons(2, Cons(3, 4)))\"\n\nclass Origin with\n  val x = 0\n  val y = 0\n\nrenderAsStr of new Origin\n//│ = \"Origin { x: 0, y: 0 }\"\n\nclass Point(x: Num, y: Num) with\n  val x = x\n  val y = y\n\n// Note that we do not display members defined in the body.\n// Some classes define lots of members, so doing so could be problematic.\nrenderAsStr of new Point(0, 1)\n//│ = \"Point(_, _)\"\n\nclass SelfRef with\n  val a = this\n  val b = 1\n\nrenderAsStr of new SelfRef\n//│ = \"SelfRef { a: ref'1, b: 1 } as ref'1\"\n\nrenderAsStr of\n  new Object with\n    val x = 0\n    fun y = 0\n//│ = \"$anon { x: 0 }\"\n\nabstract class Shape\n\ndata class Rectangle(x: Num, y: Num, w: Num, h: Num)\n\nrenderAsStr of Shape\n//│ = \"class Shape\"\n\nrenderAsStr of new Shape with\n  val x = 0\n//│ = \"$anon { x: 0 }\"\n\nrenderAsStr of Rectangle\n//│ = \"fun Rectangle { class: class Rectangle }\"\n\nrenderAsStr of Rectangle(0, 0, 5, 5)\n//│ = \"Rectangle(0, 0, 5, 5)\"\n\npattern Null = null\n\nrenderAsStr of Null\n//│ = \"pattern Null\"\n\n// FIXME?\n:re\nrenderAsStr of Null.class\n//│ ═══[RUNTIME ERROR] Error: Access to required field 'class' yielded 'undefined'\n\ndeclare class Iterator\n\nclass RangeIterator(val start: Int, val end: Int) extends Iterator with\n  let current = start\n  fun next() =\n    if current < end then\n      let result = (done: false, value: current)\n      set current += 1\n      result\n    else\n      (done: true, value: undefined)\n\nrenderAsStr of RangeIterator(0, 1)\n//│ = \"RangeIterator(0, 1)\"\n\nrenderAsStr of RangeIterator(0, 5).toArray()\n//│ = \"[0, 1, 2, 3, 4]\"\n\n//  __  __ _\n// |  \\/  (_)___  ___\n// | |\\/| | / __|/ __|\n// | |  | | \\__ \\ (__\n// |_|  |_|_|___/\\___|\n//\n// ===================\n\nrenderAsStr of Object\n//│ = \"class Object\"\n\nrenderAsStr of String\n//│ = \"class String\"\n\nrenderAsStr of Symbol\n//│ = \"class Symbol\"\n\nrenderAsStr of BigInt\n//│ = \"class BigInt\"\n\nrenderAsStr of globalThis.FinalizationRegistry\n//│ = \"class FinalizationRegistry\"\n\nlet asyncFun = globalThis.eval(\"async () => {}\")\n//│ asyncFun = fun\n\nrenderAsStr of asyncFun\n//│ = \"fun\"\n\nrenderAsStr of Object.getPrototypeOf(asyncFun).constructor\n//│ = \"class AsyncFunction\"\n\nrenderAsStr of renderAsStr\n//│ = \"fun renderAsStr\"\n\nrenderAsStr of JSON\n//│ = \"{}\"\n\nrenderAsStr of new RegExp(\"\")\n//│ = \"/(?:)/\"\n\nrenderAsStr of globalThis.Iterator\n//│ = \"class Iterator\"\n\n\n// * Customization\n// ===================\n\nclass Test\n\nTest\n//│ = class Test\n\nnew Test\n//│ = Test\n\nset Test.prototype.(Symbols.prettyPrint) = () => \"Test pretty print!\"\n\nTest\n//│ = class Test\n\nnew Test\n//│ = Test pretty print!\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/std/StackTests.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Stack.mls\"\n\nopen Stack\n\n\nlet\n  s1 = 1 :: 2 :: 3 :: Nil\n  s2 = \"a\" :: \"b\" :: \"c\" :: Nil\n  s3 = true :: false :: Nil\n//│ s1 = Cons(1, Cons(2, Cons(3, Nil)))\n//│ s2 = Cons(\"a\", Cons(\"b\", Cons(\"c\", Nil)))\n//│ s3 = Cons(true, Cons(false, Nil))\n\n\n// *** Concat ***\n\n// * Note that concatenation internally uses mutation, but it freezes the result\n\nlet s12 = s1 ::: s2\n//│ s12 = Cons(1, Cons(2, Cons(3, Cons(\"a\", Cons(\"b\", Cons(\"c\", Nil))))))\n\n// * Should not have any effect\nset s12.tail = Nil\n\n:expect false\ns12.tail isEmpty()\n//│ = false\n\n\n// *** Zipping ***\n\nzip of Nil\n//│ = Nil\n\nzip of s1\n//│ = Cons([1], Cons([2], Cons([3], Nil)))\n\nzip of s1, s2\n//│ = Cons([1, \"a\"], Cons([2, \"b\"], Cons([3, \"c\"], Nil)))\n\nzip of s1, s3\n//│ = Cons([1, true], Cons([2, false], Cons([3], Nil)))\n\ns1 zip(s2)\n//│ = Cons([1, \"a\"], Cons([2, \"b\"], Cons([3, \"c\"], Nil)))\n\nprint of ...\ns1 zip of s2, s3\n//│ > Cons([1, \"a\", true], Cons([2, \"b\", false], Cons([3, \"c\"], Nil)))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/AbusiveSuspensions.mls",
    "content": ":js\n\n\ndata class Ok[A](value: A)\ndata class Error[A](value: A)\ntype Result[A, B] = Ok[A] | Error[B]\n\n\nfun foo[A, B](expr1, expr2, expr3): Result[A, B] =\n  if expr1 is...\n  Error(b) then b\n  Ok(a) then...\n  if expr2 is...\n  Error(d) then d\n  Ok(c) then...\n  expr3\n\nfoo(Ok(1), Ok(2), 3)\n//│ = 3\n\nfoo(Ok(1), Error(2), 3)\n//│ = 2\n\n\n:pe\n:e\nfun foo(expr1) =\n  if expr1 is\n  Error(b) then b\n  Ok(a) then...\n  a\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found new line instead\n//│ ║  l.28: \t  if expr1 is\n//│ ║        \t             ^\n//│ ║  l.29: \t  Error(b) then b\n//│ ╙──      \t^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (‹erroneous syntax›).\n//│ ║  l.28: \t  if expr1 is\n//│ ║        \t             ^\n//│ ║  l.29: \t  Error(b) then b\n//│ ╙──      \t^^\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.29: \t  Error(b) then b\n//│ ╙──      \t  ^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.30: \t  Ok(a) then...\n//│ ║        \t  ^^^^^^^^^^^^^\n//│ ║  l.31: \t  a\n//│ ╙──      \t^^^\n\nfun foo(expr1) =\n  if expr1\n    is Error(b) then b\n    is Ok(a) then...\n    a\n\n:todo\nfun foo(expr1) =\n  if expr1\n  is Error(b) then b\n  is Ok(a) then...\n  a\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found 'is' keyword instead\n//│ ║  l.60: \t  is Error(b) then b\n//│ ╙──      \t  ^^\n//│ ╔══[PARSE ERROR] Unexpected identifier here\n//│ ║  l.60: \t  is Error(b) then b\n//│ ╙──      \t     ^^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (identifier)\n//│ ║  l.59: \t  if expr1\n//│ ╙──      \t     ^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/BackslashApps.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Iter.mls\"\n\n\nfun inc(x) = x + 1\n\n1 \\inc()\n//│ = 2\n\n1\\inc()\n//│ = 2\n\n1 \\inc() \\inc()\n//│ = 3\n\n1 \\inc()\\inc()\n//│ = 3\n\n42\n  \\inc()\n  \\inc()\n//│ = 44\n\n\n[1, 2, 3] \\Iter.mapping(inc) \\Iter.toStack()\n//│ = Cons(2, Cons(3, Cons(4, Nil)))\n\n[1, 2, 3]\n  \\Iter.mapping(inc)\n  \\Iter.toStack()\n//│ = Cons(2, Cons(3, Cons(4, Nil)))\n\n[1, 2, 3]\n  \\Iter.mapping @ x => x + 1\n  \\Iter.toStack()\n//│ = Cons(2, Cons(3, Cons(4, Nil)))\n\n[1, 2, 3]\n  \\Iter.mapping @\n    _ + 1\n  \\Iter.toStack()\n//│ = Cons(2, Cons(3, Cons(4, Nil)))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/BasicIfs.mls",
    "content": ":js\n\n\nif true then\n  1\n//│ = 1\n\nif true then\n  let x = 1\n  1\nelse 2\n//│ = 1\n\nif true then\n  if true then\n    let x = 1\n    1\n  else 2\n//│ = 1\n\nif 0 is\n  0 then 1\n//│ = 1\n\nif 0 is\n  0 then 1\n  1 then 1\n//│ = 1\n\nif 0 is\n  0 and\n    true then\n      1\n//│ = 1\n\nif 0 is\n  0 and\n    false then\n      let x = 1\n      1\n  0 and\n    true then\n      let x = 1\n      1\n//│ = 1\n\nlet foo =\n  if true then\n    \"\"\n  else\n    \"\"\n//│ foo = \"\"\n\nif 0 is 0 then\n  1\n//│ = 1\n\n\nif 0 is 0 then\n  let hl = 1\n  hl\n//│ = 1\n\n\nlet s = \"\"\n//│ s = \"\"\n\nif s is\n  \"\" then \"\"\n//│ = \"\"\n\nif s is\n  \"\"  then \"\"\n  \"\"  then \"\"\n//│ = \"\"\n\n(id is\n  \"\")\n//│ = false\n\n(if s is\n  \"\"  then \"\")\n//│ = \"\"\n\n(if s is\n    \"\"  then \"\"\n  )\n//│ = \"\"\n\n(if s is\n    \"\"  then \"\"\n  ) + \"]\"\n//│ = \"]\"\n\n(if \"\" is\n          \"\"  then \"\"\n          nme then \" \" + nme\n        )\n//│ = \"\"\n\nif \"\" is\n          \"\"  then \"\"\n//│ = \"\"\n\n(if \"\" is\n          id  then \"\"\n  )\n//│ = \"\"\n\n(if \"\" is\n          \"\"  then \"\"\n  )\n//│ = \"\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/KeywordStutters.mls",
    "content": ":js\n\n\nlet\n  x = 0\n  y = 0\n//│ x = 0\n//│ y = 0\n\nset\n  x += 1\n  y += 2\n\n[x, y]\n//│ = [1, 2]\n\n\n:p\nabstract\n  class\n    Foo(a)\n    Bar(b)\n//│ ┊abstract┊→⟨┊class┊→⟨┊Foo┊(⟨┊a┊⟩)┊↵┊Bar┊(⟨┊b┊⟩)┊⟩←┊⟩←┊\n//│ Parsed:\n//│ \tModified(Keywrd(keyword 'abstract'),TypeDef(Cls,App(Ident(Foo),Tup(List(Ident(a)))),None))\n//│ \tModified(Keywrd(keyword 'abstract'),TypeDef(Cls,App(Ident(Bar),Tup(List(Ident(b)))),None))\n\n:todo\nabstract class\n    Foo(a)\n    Bar(b)\n//│ ╔══[PARSE ERROR] Unexpected identifier here\n//│ ║  l.31: \t    Bar(b)\n//│ ╙──      \t    ^^^\n\n\nabstract class Foo\nobject\n  A extends Foo\n  B extends Foo\n\n\n// * Would be cool if something like this was supported:\n:pe\nobject \\$ extends Foo\n  A\n  B\n//│ ╔══[LEXICAL ERROR] unexpected character '$'\n//│ ║  l.45: \tobject \\$ extends Foo\n//│ ╙──      \t        ^\n//│ ╔══[PARSE ERROR] Expected end of input; found error instead\n//│ ║  l.45: \tobject \\$ extends Foo\n//│ ╙──      \t        ^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/TypesInTerms.mls",
    "content": ":js\n\n\n:ge\n1 | 2\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (composed type)\n//│ ║  l.5: \t1 | 2\n//│ ╙──     \t^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:ge\nprint(\"A\") & print(\"B\")\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (composed type)\n//│ ║  l.12: \tprint(\"A\") & print(\"B\")\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:ge\n~false\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (negation type)\n//│ ║  l.19: \t~false\n//│ ╙──      \t ^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/WeirdBrackets.mls",
    "content": ":js\n\n\n{( 123 )}\n//│ = 123\n\n{({( a: 1, b: 2 )})}\n//│ = {a: 1, b: 2}\n\n\n:e\n\\{ Int }\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (identifier).\n//│ ║  l.12: \t\\{ Int }\n//│ ╙──      \t   ^^^\n//│ = fun passTo\n\n:e\n\\(0)\n//│ ╔══[COMPILATION ERROR] Expected 2 arguments, got 1\n//│ ║  l.19: \t\\(0)\n//│ ╙──      \t ^^^\n//│ = fun\n\nfun (\\) huh(x) = x\n\n\\(0)\n//│ = 0\n\n:e\n// Writing record patterns in this way is strange. In the previous `Desugarer`,\n// the logic from two methods happened to work together and supported this\n// syntax. In the new `Desugarer`, we chose not to support this syntax.\nfun f(x) = if x is {( Int then 1, Bool then 2 )}\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (parenthesis section).\n//│ ║  l.34: \tfun f(x) = if x is {( Int then 1, Bool then 2 )}\n//│ ╙──      \t                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n// * Potential alternative syntaxes for UCS splits\n\n:e\nfun f(x) = if x is ( Int then 1, Bool then 2 )\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (parenthesis section).\n//│ ║  l.43: \tfun f(x) = if x is ( Int then 1, Bool then 2 )\n//│ ╙──      \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:e\nfun f(x) = if x is \\{ Int then 1, Bool then 2 }\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (juxtaposition).\n//│ ║  l.49: \tfun f(x) = if x is \\{ Int then 1, Bool then 2 }\n//│ ╙──      \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:e\nfun f(x) = if x is \\( Int then 1, Bool then 2 )\n//│ ╔══[COMPILATION ERROR] Cannot use this reference as a pattern.\n//│ ║  l.55: \tfun f(x) = if x is \\( Int then 1, Bool then 2 )\n//│ ╙──      \t                   ^\n//│ ╔══[COMPILATION ERROR] Cannot use this reference as a pattern.\n//│ ║  l.55: \tfun f(x) = if x is \\( Int then 1, Bool then 2 )\n//│ ╙──      \t                   ^\n\nclass Box[T](val content: T)\n\n:ucs desugared\nfun interesting(x) =\n  if x is Box( Int then 1, Bool then 2 )\n//│ Split with nested patterns:\n//│ >  if\n//│ >    x is Box(Int) then 1\n//│ >    x is Box(Bool) then 2\n//│ Expanded split with flattened patterns:\n//│ >  ‹if|while›\n//│ >    x is Box(arg$Box$0$) and tmp:arg$Box$0$ is Int then 1\n//│ >    x is Box(arg$Box$0$) and tmp:arg$Box$0$ is Bool then 2\n\ninteresting of Box(42)\n//│ = 1\n\ninteresting of Box(true)\n//│ = 2\n\n:re\ninteresting of Box(\"str\")\n//│ ═══[RUNTIME ERROR] Error: match error\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/annotations/AnnotationPrecedence.mls",
    "content": ":js\n\n\n// The `@compile` annotation should annotate `A(0)`, not `A(0) as y`.\n// The precedence of annotations should be tight enough to not include `as`.\n\npattern A(pattern B) = B\n\n\nfun foo(x) = if x is @annotations.compile A(0) as y then y\n\nfun foo(x) = if x is (@annotations.compile A(0)) as y then y\n\n// :pt\n// :re\n// if 1 is (@annotations.compile A(0)) as y then y\n\n:pe\n:w\n:e\nfun foo(x) = if x is @annotations.compile (A(0) as y) then y\n//│ ╔══[PARSE ERROR] Unexpected keyword 'then' in this position\n//│ ║  l.21: \tfun foo(x) = if x is @annotations.compile (A(0) as y) then y\n//│ ╙──      \t                                                      ^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (‹erroneous syntax›).\n//│ ║  l.21: \tfun foo(x) = if x is @annotations.compile (A(0) as y) then y\n//│ ╙──      \t                                                      ^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.21: \tfun foo(x) = if x is @annotations.compile (A(0) as y) then y\n//│ ╙──      \t                                                   ^\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.21: \tfun foo(x) = if x is @annotations.compile (A(0) as y) then y\n//│ ╙──      \t                                                           ^\n//│ ╔══[WARNING] This annotation is not supported here.\n//│ ║  l.21: \tfun foo(x) = if x is @annotations.compile (A(0) as y) then y\n//│ ║        \t                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: Patterns only support the `@compile` annotation.\n\n:e\nfun foo(x) = if x is @annotations.compile {A(0) as y} then y\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'y'\n//│ ║  l.40: \tfun foo(x) = if x is @annotations.compile {A(0) as y} then y\n//│ ╙──      \t                                                           ^\n\n:pe // parses as `@annotations.compile(A(0) as y) ‹missing annot body›`\n:e\nfun foo(x) = if x is (@annotations.compile (A(0) as y)) then y\n//│ ╔══[PARSE ERROR] Expected start of expression in this position\n//│ ║  l.47: \tfun foo(x) = if x is (@annotations.compile (A(0) as y)) then y\n//│ ║        \t                                                      ^\n//│ ╟── found a lone annotation instead\n//│ ║  l.47: \tfun foo(x) = if x is (@annotations.compile (A(0) as y)) then y\n//│ ╙──      \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (‹erroneous syntax›).\n//│ ║  l.47: \tfun foo(x) = if x is (@annotations.compile (A(0) as y)) then y\n//│ ╙──      \t                                                      ^\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.47: \tfun foo(x) = if x is (@annotations.compile (A(0) as y)) then y\n//│ ╙──      \t                                                             ^\n\n:pe // parses as `@annotations.compile(A(0) as y) ‹missing annot body›`\n:e\nfun foo(x) = if x is (@annotations.compile(A(0) as y)) then y\n//│ ╔══[PARSE ERROR] Expected start of expression in this position\n//│ ║  l.63: \tfun foo(x) = if x is (@annotations.compile(A(0) as y)) then y\n//│ ║        \t                                                     ^\n//│ ╟── found a lone annotation instead\n//│ ║  l.63: \tfun foo(x) = if x is (@annotations.compile(A(0) as y)) then y\n//│ ╙──      \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (‹erroneous syntax›).\n//│ ║  l.63: \tfun foo(x) = if x is (@annotations.compile(A(0) as y)) then y\n//│ ╙──      \t                                                     ^\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.63: \tfun foo(x) = if x is (@annotations.compile(A(0) as y)) then y\n//│ ╙──      \t                                                            ^\n\n:e\nfun foo(x) = if x is (@annotations.compile {A(0) as y}) then y\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'y'\n//│ ║  l.78: \tfun foo(x) = if x is (@annotations.compile {A(0) as y}) then y\n//│ ╙──      \t                                                             ^\n\n:fixme\nfun foo(x) = if x is (@annotations.compile A(0) as y) then y\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'y'\n//│ ║  l.84: \tfun foo(x) = if x is (@annotations.compile A(0) as y) then y\n//│ ╙──      \t                                                           ^\n\n\n// Using a dummy annotation to test that annotations gobble\n\ntype Test\n\n:w\n@Test 1\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.95: \t@Test 1\n//│ ║        \t^^^^^\n//│ ╟── This annotation is not supported on integer literal terms.\n//│ ║  l.95: \t@Test 1\n//│ ╙──      \t      ^\n//│ = 1\n\n:w\n@Test 2 + 1\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.105: \t@Test 2 + 1\n//│ ║         \t^^^^^\n//│ ╟── This annotation is not supported on application terms.\n//│ ║  l.105: \t@Test 2 + 1\n//│ ╙──       \t      ^^^^^\n//│ = 3\n\n:w\n@Test 2 as Int\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.115: \t@Test 2 as Int\n//│ ║         \t^^^^^\n//│ ╟── This annotation is not supported on type ascription terms.\n//│ ║  l.115: \t@Test 2 as Int\n//│ ╙──       \t      ^^^^^^^^\n//│ = 2\n\n:w\n@Test id(2) as Int\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.125: \t@Test id(2) as Int\n//│ ║         \t^^^^^\n//│ ╟── This annotation is not supported on type ascription terms.\n//│ ║  l.125: \t@Test id(2) as Int\n//│ ╙──       \t      ^^^^^^^^^^^^\n//│ = 2\n\n:pe\n:re\n(@Test)\n//│ ╔══[PARSE ERROR] Expected start of expression in this position\n//│ ║  l.136: \t(@Test)\n//│ ║         \t      ^\n//│ ╟── found a lone annotation instead\n//│ ║  l.136: \t(@Test)\n//│ ╙──       \t ^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:pe\n:re\nprint(@Test)\n//│ ╔══[PARSE ERROR] Expected start of expression in this position\n//│ ║  l.147: \tprint(@Test)\n//│ ║         \t           ^\n//│ ╟── found a lone annotation instead\n//│ ║  l.147: \tprint(@Test)\n//│ ╙──       \t      ^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/annotations/Declarations.mls",
    "content": ":js\n\nobject tailrec\n\ntailrec\n//│ = tailrec\n\n:w\n@tailrec fun fact_n(n, acc) =\n  if n == 0 then acc else fact_n(n - 1, n * acc)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.9: \t@tailrec fun fact_n(n, acc) =\n//│ ╙──     \t^^^^^^^^\n\n:w\nfun fact(n) =\n  @tailrec fun go(n, acc) =\n    if n == 0 then acc else go(n - 1, n * acc)\n  go(n, 1)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.17: \t  @tailrec fun go(n, acc) =\n//│ ╙──      \t  ^^^^^^^^\n\ndata class Freezed(degree: Num)\n\n:w\n@Freezed(-273.15) class AbsoluteZero\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.27: \t@Freezed(-273.15) class AbsoluteZero\n//│ ╙──      \t^^^^^^^^^^^^^^^^^\n\n:w\n@Freezed(-18) class Beverage(name: Str)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.33: \t@Freezed(-18) class Beverage(name: Str)\n//│ ╙──      \t^^^^^^^^^^^^^\n\n:w\n@Freezed(-4) let drink = Beverage(\"Coke\")\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.39: \t@Freezed(-4) let drink = Beverage(\"Coke\")\n//│ ╙──      \t^^^^^^^^^^^^\n//│ drink = Beverage(_)\n\nmodule Foo with\n  data class Bar(qax: Str)\n\n:w\n@Foo.Bar(\"baz\") class Qux\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.49: \t@Foo.Bar(\"baz\") class Qux\n//│ ╙──      \t^^^^^^^^^^^^^^^\n\n// * Not an annotation, but an applicationo f operator `@`...\n:pe\n:re\n@42 class Qux\n//│ ╔══[PARSE ERROR] Expected end of input; found 'class' keyword instead\n//│ ║  l.57: \t@42 class Qux\n//│ ╙──      \t    ^^^^^\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n:pe\n:re\n@(1 + 2) class Qux\n//│ ╔══[PARSE ERROR] Expected end of input; found 'class' keyword instead\n//│ ║  l.65: \t@(1 + 2) class Qux\n//│ ╙──      \t         ^^^^^\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\n:pe\n:re\n@1 module Qux\n//│ ╔══[PARSE ERROR] Expected end of input; found 'module' keyword instead\n//│ ║  l.73: \t@1 module Qux\n//│ ╙──      \t   ^^^^^^\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n\nobject inline\n\n:w\n// All functions are annotated with @inline.\n@inline\nfun\n  min(x, y) = if x < y then x else y\n  max(x, y) = if x > y then x else y\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.83: \t@inline\n//│ ╙──      \t^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.83: \t@inline\n//│ ╙──      \t^^^^^^^\n\n:w\n@inline let\n  abs(x) = if x < 0 then -x else x\n  clamp(x, lo, hi) = min(max(x, lo), hi)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.95: \t@inline let\n//│ ╙──      \t^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.95: \t@inline let\n//│ ╙──      \t^^^^^^^\n//│ abs = fun abs\n//│ clamp = fun clamp\n\n:w\n// Only the first variable is annotated with @inline.\nlet\n  @inline success = 0\n  failure = 1\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.110: \t  @inline success = 0\n//│ ╙──       \t  ^^^^^^^\n//│ failure = 1\n//│ success = 0\n\n// Multiple annotations\n// ====================\n\n:w\n@inline @tailrec fun fib(n) =\n  if n < 2 then n else fib(n - 1) + fib(n - 2)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.122: \t@inline @tailrec fun fib(n) =\n//│ ╙──       \t^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.122: \t@inline @tailrec fun fib(n) =\n//│ ╙──       \t        ^^^^^^^^\n\nobject internal\n\n:w\n@internal object\n  shared\n  thread_local\n  transient\n  volatile\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.134: \t@internal object\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.134: \t@internal object\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.134: \t@internal object\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.134: \t@internal object\n//│ ╙──       \t^^^^^^^^^\n\n:w\n@volatile let\n  @shared counter = 0\n  @transient @thread_local cache = ()\n  @volatile @transient empty = \"\"\n  normal = ()\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.153: \t@volatile let\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.154: \t  @shared counter = 0\n//│ ╙──       \t  ^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.153: \t@volatile let\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.155: \t  @transient @thread_local cache = ()\n//│ ╙──       \t  ^^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.155: \t  @transient @thread_local cache = ()\n//│ ╙──       \t             ^^^^^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.153: \t@volatile let\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.156: \t  @volatile @transient empty = \"\"\n//│ ╙──       \t  ^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.156: \t  @volatile @transient empty = \"\"\n//│ ╙──       \t            ^^^^^^^^^^\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.153: \t@volatile let\n//│ ╙──       \t^^^^^^^^^\n//│ cache = ()\n//│ counter = 0\n//│ empty = \"\"\n//│ normal = ()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/annotations/Pattern.mls",
    "content": ":js\n\nopen annotations { compile }\n\nclass Box()\n\n// Now the `@compile` annotation applies to all patterns, while before it could\n// only be used for pattern symbols. Now it expands and compiles the following\n// pattern.\n\nfun foo(x) = if x is @compile Box then \"yes\" else \"no\"\n\nobject Singleton\n\nfun foo(x) = if x is @compile Singleton then \"yes\" else \"no\"\n\n\nfun foo(x) = if x is @compile 42 then \"yes\" else \"no\"\n\nobject do_not_compile\n\n:w\nfun foo(x) = if x is @do_not_compile Box then \"yes\" else \"no\"\n//│ ╔══[WARNING] This annotation is not supported here.\n//│ ║  l.23: \tfun foo(x) = if x is @do_not_compile Box then \"yes\" else \"no\"\n//│ ║        \t                     ^^^^^^^^^^^^^^^\n//│ ╟── Note: Patterns only support the `@compile` annotation.\n//│ ║  l.23: \tfun foo(x) = if x is @do_not_compile Box then \"yes\" else \"no\"\n//│ ╙──      \t                                     ^^^\n\n:w\n:e\nfun foo(x) = if x is @name_not_found Box then \"yes\" else \"no\"\n//│ ╔══[COMPILATION ERROR] Name not found: name_not_found\n//│ ║  l.33: \tfun foo(x) = if x is @name_not_found Box then \"yes\" else \"no\"\n//│ ╙──      \t                     ^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] This annotation is not supported here.\n//│ ║  l.33: \tfun foo(x) = if x is @name_not_found Box then \"yes\" else \"no\"\n//│ ║        \t                     ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: Patterns only support the `@compile` annotation.\n//│ ║  l.33: \tfun foo(x) = if x is @name_not_found Box then \"yes\" else \"no\"\n//│ ╙──      \t                                     ^^^\n\npattern Box' = Box\n\nfun foo(x) = if x is @compile Box' then \"yes\" else \"no\"\n\n:w\nfun foo(x) = if x is @do_not_compile Box' then \"yes\" else \"no\"\n//│ ╔══[WARNING] This annotation is not supported here.\n//│ ║  l.49: \tfun foo(x) = if x is @do_not_compile Box' then \"yes\" else \"no\"\n//│ ║        \t                     ^^^^^^^^^^^^^^^\n//│ ╟── Note: Patterns only support the `@compile` annotation.\n//│ ║  l.49: \tfun foo(x) = if x is @do_not_compile Box' then \"yes\" else \"no\"\n//│ ╙──      \t                                     ^^^^\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/syntax/annotations/Unsupported.mls",
    "content": ":js\n// The annotations for the following expressions are not supported for now.\n\nobject debug\n\nimport \"../../../mlscript-compile/StrOps.mls\"\n\n:w\n@debug\nopen StrOps\n//│ ╔══[WARNING] This annotation has no effect\n//│ ║  l.9: \t@debug\n//│ ║       \t^^^^^^\n//│ ╟── Annotations are not supported on open terms.\n//│ ║  l.10: \topen StrOps\n//│ ╙──      \t^^^^^^^^^^^\n\n:w\n@debug 0\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.19: \t@debug 0\n//│ ║        \t^^^^^^\n//│ ╟── This annotation is not supported on integer literal terms.\n//│ ║  l.19: \t@debug 0\n//│ ╙──      \t       ^\n//│ = 0\n\n:w\n@debug 1 + 2\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.29: \t@debug 1 + 2\n//│ ║        \t^^^^^^\n//│ ╟── This annotation is not supported on application terms.\n//│ ║  l.29: \t@debug 1 + 2\n//│ ╙──      \t       ^^^^^\n//│ = 3\n\n:w\n(@debug 1 + 2)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.39: \t(@debug 1 + 2)\n//│ ║        \t ^^^^^^\n//│ ╟── This annotation is not supported on application terms.\n//│ ║  l.39: \t(@debug 1 + 2)\n//│ ╙──      \t        ^^^^^\n//│ = 3\n\n:w\n(@debug 1) + 2\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.49: \t(@debug 1) + 2\n//│ ║        \t ^^^^^^\n//│ ╟── This annotation is not supported on integer literal terms.\n//│ ║  l.49: \t(@debug 1) + 2\n//│ ╙──      \t        ^\n//│ = 3\n\n:w\n(1 + @debug 2)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.59: \t(1 + @debug 2)\n//│ ║        \t     ^^^^^^\n//│ ╟── This annotation is not supported on integer literal terms.\n//│ ║  l.59: \t(1 + @debug 2)\n//│ ╙──      \t            ^\n//│ = 3\n\ndata class Log(msg: Str)\n\n:w\nid(@Log 5)\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ║  l.71: \tid(@Log 5)\n//│ ║        \t   ^^^^\n//│ ╟── This annotation is not supported on integer literal terms.\n//│ ║  l.71: \tid(@Log 5)\n//│ ╙──      \t        ^\n//│ = 5\n\n:pe\n:re\n@1 + 2 class Qux\n//│ ╔══[PARSE ERROR] Expected end of input; found 'class' keyword instead\n//│ ║  l.82: \t@1 + 2 class Qux\n//│ ╙──      \t       ^^^^^\n//│ ═══[RUNTIME ERROR] TypeError: f is not a function\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/tailrec/Annots.mls",
    "content": ":js\n\n:w\n@tailrec\nfun f\n//│ ═══[WARNING] Only functions with a body may be marked as @tailrec.\n\n:w\n@tailrec\nclass A\n//│ ═══[WARNING] This annotation has no effect.\n\n:w\n@tailrec 2 + 2\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ╟── This annotation is not supported on application terms.\n//│ ║  l.14: \t@tailrec 2 + 2\n//│ ╙──      \t         ^^^^^\n//│ = 4\n\n@tailrec\nfun f = g\nfun g = f\n\n:w\n@tailcall\nfun g = 2\n//│ ═══[WARNING] This annotation has no effect.\n\nfun test =\n  @tailcall test\n\n:w\nlet f = 0\nfun test =\n  @tailcall f\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ╟── This annotation is not supported on reference terms.\n//│ ║  l.36: \t  @tailcall f\n//│ ╙──      \t            ^\n//│ f = 0\n\n:todo\nclass A with\n  @tailrec\n  fun f() = g()\n  fun g() = f()\n//│ ╔══[COMPILATION ERROR] Class methods may not yet be marked @tailrec.\n//│ ║  l.46: \t  fun f() = g()\n//│ ╙──      \t      ^\n\n:w\nclass A with\n  @tailcall\n  fun f = 2\n//│ ═══[WARNING] This annotation has no effect.\n\n:todo\nclass A\nmodule A with\n  @tailrec\n  fun f = 2\n//│ ╔══[WARNING] This function does not directly self-recurse, but is marked @tailrec.\n//│ ║  l.62: \t  fun f = 2\n//│ ╙──      \t      ^\n\n:w\nclass A\nmodule A with\n  @tailcall\n  fun f = 2\n//│ ═══[WARNING] This annotation has no effect.\n\n\n:w\n:effectHandlers\n:lift\nhandle h = Object with\n  @tailcall\n  fun f()(r) = 2\n//│ ═══[WARNING] This annotation has no effect.\n\n:w\nfun test =\n  @tailcall 1 + 2\n//│ ╔══[WARNING] This annotation has no effect.\n//│ ╟── The @tailcall annotation has no effect on calls to built-in symbols.\n//│ ║  l.85: \t  @tailcall 1 + 2\n//│ ╙──      \t            ^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/tailrec/Errors.mls",
    "content": ":js\n\n:e\nfun f(x) =\n  @tailcall f(x)\n  f(x)\n//│ ╔══[COMPILATION ERROR] This call is not in tail position.\n//│ ║  l.5: \t  @tailcall f(x)\n//│ ╙──     \t            ^^^^\n\n:e\nfun f(x) = 2\nfun g(x) = @tailcall f(x)\n//│ ╔══[COMPILATION ERROR] This call is not optimized as it does not directly recurse through its parent function.\n//│ ║  l.13: \tfun g(x) = @tailcall f(x)\n//│ ╙──      \t                     ^^^^\n\n:e\n@tailrec fun f(x) =\n  g(x)\nfun g(x) = f(x); f(x)\n//│ ╔══[COMPILATION ERROR] This function is not tail recursive.\n//│ ║  l.19: \t@tailrec fun f(x) =\n//│ ║        \t             ^\n//│ ╟── It could self-recurse through this call, which is not a tail call.\n//│ ║  l.21: \tfun g(x) = f(x); f(x)\n//│ ╙──      \t           ^^^^\n\n:e\n@tailrec fun f(x) =\n  g(x)\nfun g(x) = \n  f(x)\n  h(x)\nfun h(x) =\n  g(x)\n//│ ╔══[COMPILATION ERROR] This function is not tail recursive.\n//│ ║  l.30: \t@tailrec fun f(x) =\n//│ ║        \t             ^\n//│ ╟── It could self-recurse through this call, which is not a tail call.\n//│ ║  l.33: \t  f(x)\n//│ ╙──      \t  ^^^^\n\n:e\n@tailrec fun f(x) =\n  g(x)\nfun g(x) = \n  h(x)\n  f(x)\nfun h(x) =\n  f(x)\n//│ ╔══[COMPILATION ERROR] This function is not tail recursive.\n//│ ║  l.45: \t@tailrec fun f(x) =\n//│ ║        \t             ^\n//│ ╟── It could self-recurse through this call, which is not a tail call.\n//│ ║  l.48: \t  h(x)\n//│ ╙──      \t  ^^^^\n\n:e\nmodule A with\n  fun f(x) = if x == 0 then 0 else @tailcall g(x - 1)\n  fun g(x) = if x == 0 then 1 else\n    @tailcall f(x - 1)\n    @tailcall f(x - 1)\n//│ ╔══[COMPILATION ERROR] This call is not in tail position.\n//│ ║  l.63: \t    @tailcall f(x - 1)\n//│ ╙──      \t              ^^^^^^^^\n\n:w\n@tailrec\nfun f = 2\n//│ ╔══[WARNING] This function does not directly self-recurse, but is marked @tailrec.\n//│ ║  l.71: \tfun f = 2\n//│ ╙──      \t    ^\n\n:w\nmodule A with\n  @tailrec\n  fun f() = 2\n//│ ╔══[WARNING] This function does not directly self-recurse, but is marked @tailrec.\n//│ ║  l.79: \t  fun f() = 2\n//│ ╙──      \t      ^\n\n:fixme // TODO: support\n@tailrec\nfun foo() = Foo.bar()\nmodule Foo with\n  fun bar() = foo()\n//│ ╔══[WARNING] This function does not directly self-recurse, but is marked @tailrec.\n//│ ║  l.86: \tfun foo() = Foo.bar()\n//│ ╙──      \t    ^^^\n\n:e\nfun f(x) =\n  @tailrec\n  fun g() = g()\n  g()\n//│ ╔══[COMPILATION ERROR] This @tailrec function was not processed by the tail-call optimizer.\n//│ ║  l.96: \t  fun g() = g()\n//│ ╙──      \t      ^\n\n:e\nfun scan(idx, acc) =\n  @tailrec\n  fun go(idx, tok) = scan(idx, tok)\n  go(idx, acc)\n//│ ╔══[COMPILATION ERROR] This @tailrec function was not processed by the tail-call optimizer.\n//│ ║  l.105: \t  fun go(idx, tok) = scan(idx, tok)\n//│ ╙──       \t      ^^\n\n:e\n:w\n@tailrec\nfun scan(idx, acc) =\n  @tailrec\n  fun go(idx, tok) = scan(idx, tok)\n  go(idx, acc)\n//│ ╔══[WARNING] This function does not directly self-recurse, but is marked @tailrec.\n//│ ║  l.114: \tfun scan(idx, acc) =\n//│ ╙──       \t    ^^^^\n//│ ╔══[COMPILATION ERROR] This @tailrec function was not processed by the tail-call optimizer.\n//│ ║  l.116: \t  fun go(idx, tok) = scan(idx, tok)\n//│ ╙──       \t      ^^\n\n:e\n@tailrec\n@config(tailRecOpt: false)\nfun foo() = foo()\n//│ ╔══[COMPILATION ERROR] This @tailrec function was not processed by the tail-call optimizer.\n//│ ║  l.128: \tfun foo() = foo()\n//│ ╙──       \t    ^^^\n\n:e\nfun f =\n  @tailcall id(2)\n//│ ╔══[COMPILATION ERROR] Only functions in this compilation unit may be marked @tailcall.\n//│ ║  l.135: \t  @tailcall id(2)\n//│ ╙──       \t            ^^^^^\n\n:e\nfun f(x)(y) =\n  @tailcall f(x)\n//│ ╔══[COMPILATION ERROR] Only fully applied calls may be marked @tailcall.\n//│ ║  l.142: \t  @tailcall f(x)\n//│ ╙──       \t            ^^^^\n\n:e\nfun f(x)() =\n  @tailcall g(x)(0)\nfun g(x)(y) =\n  @tailcall f(x)\n//│ ╔══[COMPILATION ERROR] Only fully applied calls may be marked @tailcall.\n//│ ║  l.151: \t  @tailcall f(x)\n//│ ╙──       \t            ^^^^\n//│ ╔══[COMPILATION ERROR] This call is not optimized as it does not directly recurse through its parent function.\n//│ ║  l.149: \t  @tailcall g(x)(0)\n//│ ╙──       \t            ^^^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/tailrec/MultiArgLists.mls",
    "content": ":js\n\n// Test: Tail-recursive function with single parameter list works correctly\n:expect 5050\nfun sum(n, acc) = if n == 0 then acc else sum(n - 1, n + acc)\nsum(100, 0)\n//│ = 5050\n\n// Test: Curried function with multiple parameter lists — properly lowered as\n// a multi-param-list function, so the self-recursive tail call is recognized\n// and optimized by TailRecOpt.\n:expect 500500\n:sir\n@tailrec\nfun loop(x)(y) =\n  if x == 0 then y\n  else loop(x - 1)(y + x)\nloop(1000)(0)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let loop⁰, loop$tailrec⁰;\n//│ define loop$tailrec⁰ as fun loop$tailrec¹(x, y) {\n//│   loop loopLabel:\n//│     let scrut, tmp, tmp1;\n//│     set scrut = Predef⁰.equals⁰(x, 0);\n//│     match scrut\n//│       true =>\n//│         return y\n//│       else\n//│         set tmp = -⁰(x, 1);\n//│         set tmp1 = +⁰(y, x);\n//│         set x = tmp;\n//│         set y = tmp1;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ define loop⁰ as fun loop¹(x)(y) { return loop$tailrec¹(x, y) };\n//│ loop¹(1000)(0)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 500500\n\n// Test: Function with multiple parameter lists, non-annotated (should still optimize to a loop)\n:sir\n:expect 100\nfun count(start)(stop) =\n  if start == stop then start\n  else count(start + 1)(stop)\ncount(0)(100)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let count⁰, count$tailrec⁰;\n//│ define count$tailrec⁰ as fun count$tailrec¹(start, stop) {\n//│   loop loopLabel:\n//│     let scrut, tmp;\n//│     set scrut = Predef⁰.equals⁰(start, stop);\n//│     match scrut\n//│       true =>\n//│         return start\n//│       else\n//│         set tmp = +⁰(start, 1);\n//│         set start = tmp;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ define count⁰ as fun count¹(start)(stop) { return count$tailrec¹(start, stop) };\n//│ count¹(0)(100)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 100\n\n// Test: Mutually recursive functions with multiple parameter lists\n:sir\nfun even(n)(dummy) = if n == 0 then [true, dummy] else odd(n - 1)(dummy + 1)\nfun odd(n)(dummy) = if n == 0 then [false, dummy] else even(n - 1)(dummy + 1)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let even⁰, odd⁰, even_odd⁰;\n//│ define even_odd⁰ as fun even_odd¹(id, param0, param1) {\n//│   loop loopLabel:\n//│     match id\n//│       0 =>\n//│         let scrut, tmp, tmp1;\n//│         set scrut = Predef⁰.equals⁰(param0, 0);\n//│         match scrut\n//│           true =>\n//│             return [true, param1]\n//│           else\n//│             set tmp = -⁰(param0, 1);\n//│             set tmp1 = +⁰(param1, 1);\n//│             set param0 = tmp;\n//│             set param1 = tmp1;\n//│             set id = 1;\n//│             continue loopLabel\n//│         end\n//│       1 =>\n//│         let scrut, tmp, tmp1;\n//│         set scrut = Predef⁰.equals⁰(param0, 0);\n//│         match scrut\n//│           true =>\n//│             return [false, param1]\n//│           else\n//│             set tmp = -⁰(param0, 1);\n//│             set tmp1 = +⁰(param1, 1);\n//│             set param0 = tmp;\n//│             set param1 = tmp1;\n//│             set id = 0;\n//│             continue loopLabel\n//│         end\n//│       else\n//│         end\n//│     end\n//│   end\n//│ };\n//│ define even⁰ as fun even¹(n)(dummy) {\n//│   return even_odd¹(0, n, dummy)\n//│ };\n//│ define odd⁰ as fun odd¹(n)(dummy) { return even_odd¹(1, n, dummy) };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect [true, 10]\neven(10)(0)\n//│ = [true, 10]\n\n:expect [false, 9]\neven(9)(0)\n//│ = [false, 9]\n\n\n// Spreads\n\n// This is the same as a test in `TailRecOpt.mls` but with some parameters separated and changed.\n:sir\nfun f(n)(a, b, c, d, ...e)(m) =\n  if n > 0 then @tailcall g(n)(m + 1)\n  else [e, m]\nfun g(n)(m) =\n  @tailcall f(n - 1)(...[1, 2], 3, ...[3, 4], ...[5, n], 7, n)(m)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁰, g⁰, f_g⁰;\n//│ define f_g⁰ as fun f_g¹(id, param0, param1, param2, param3, param4, param5, param6) {\n//│   loop loopLabel:\n//│     match id\n//│       0 =>\n//│         let scrut, tmp;\n//│         set scrut = >⁰(param0, 0);\n//│         match scrut\n//│           true =>\n//│             set tmp = +⁰(param6, 1);\n//│             set param1 = tmp;\n//│             set id = 1;\n//│             continue loopLabel\n//│           else\n//│             return [param5, param6]\n//│         end\n//│       1 =>\n//│         let tmp, tmp1, tmp2, tmp3, param1_tmp, argList, param0_tmp, sliceRes;\n//│         set tmp = -⁰(param0, 1);\n//│         set tmp1 = [1, 2];\n//│         set tmp2 = [3, 4];\n//│         set tmp3 = [5, param0];\n//│         set param1_tmp = param1;\n//│         set param0_tmp = param0;\n//│         set param0 = tmp;\n//│         set argList = [...tmp1, 3, ...tmp2, ...tmp3, 7, param0_tmp];\n//│         set sliceRes = runtime⁰.Tuple⁰.slice⁰(argList, 4, 0);\n//│         set param1 = argList.0;\n//│         set param2 = argList.1;\n//│         set param3 = argList.2;\n//│         set param4 = argList.3;\n//│         set param5 = sliceRes;\n//│         set param6 = param1_tmp;\n//│         set id = 0;\n//│         continue loopLabel\n//│       else\n//│         end\n//│     end\n//│   end\n//│ };\n//│ define f⁰ as fun f¹(n)(a, b, c, d, ...e)(m) {\n//│   return f_g¹(0, n, a, b, c, d, e, m)\n//│ };\n//│ define g⁰ as fun g¹(n)(m) {\n//│   return f_g¹(1, n, m, undefined, undefined, undefined, undefined, undefined)\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect [[4, 5, 1, 7, 1], 9]\ng(10)(0)\n//│ = [[4, 5, 1, 7, 1], 9]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/tailrec/Simple.mls",
    "content": ":js\n\n\n:sjs\n@tailrec\nfun f = f\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f; f = function f() { loopLabel: while (true) { continue loopLabel; } };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:fixme\nmodule Foo with\n  @tailrec\n  fun bar = bar\n//│ ╔══[WARNING] This function does not directly self-recurse, but is marked @tailrec.\n//│ ║  l.14: \t  fun bar = bar\n//│ ╙──      \t      ^^^\n\n@tailrec\nfun f() = f()\n\nmodule Foo with\n  @tailrec\n  fun bar() = bar()\n\nfun f(x) = f(x + 1)\n\n:sjs\nfun f(x) = f(f(x) + 1)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f3;\n//│ f3 = function f(x) {\n//│   loopLabel: while (true) {\n//│     let tmp, tmp1;\n//│     tmp = f3(x);\n//│     tmp1 = tmp + 1;\n//│     x = tmp1;\n//│     continue loopLabel;\n//│   }\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nmodule A with\n  fun f(x) = @tailcall f(f(x) + 1)\n\n\n:fixme // TODO: support\nmodule A with\n  @tailrec\n  fun f(x) = B.g(x + 1)\nmodule B with\n  fun g(x) = A.f(x * 2)\n//│ ╔══[WARNING] This function does not directly self-recurse, but is marked @tailrec.\n//│ ║  l.50: \t  fun f(x) = B.g(x + 1)\n//│ ╙──      \t      ^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/tailrec/TailRecOpt.mls",
    "content": ":js\n\n:expect 200010000\nfun sum_impl(n, acc) = if n == 0 then acc else sum_impl(n - 1, n + acc)\nfun sum(n) = sum_impl(n, 0)\nsum(20000)\n//│ = 200010000\n\n:sir\n:expect 50000\nfun g(a, b, c, d) = f(a, b, c + d)\nfun f(a, b, c) =\n  if \n    a > 0 then g(a - 1, b, c, 1)\n    b > 0 then g(a, b - 1, c, 2)\n    else c\nf(10000, 20000, 0)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁰, g⁰, g_f⁰;\n//│ define g_f⁰ as fun g_f¹(id, param0, param1, param2, param3) {\n//│   loop loopLabel:\n//│     match id\n//│       0 =>\n//│         let tmp;\n//│         set tmp = +⁰(param2, param3);\n//│         set param2 = tmp;\n//│         set id = 1;\n//│         continue loopLabel\n//│       1 =>\n//│         let scrut, scrut1, tmp, tmp1;\n//│         set scrut = >⁰(param0, 0);\n//│         match scrut\n//│           true =>\n//│             set tmp = -⁰(param0, 1);\n//│             set param0 = tmp;\n//│             set param3 = 1;\n//│             set id = 0;\n//│             continue loopLabel\n//│           else\n//│             set scrut1 = >⁰(param1, 0);\n//│             match scrut1\n//│               true =>\n//│                 set tmp1 = -⁰(param1, 1);\n//│                 set param1 = tmp1;\n//│                 set param3 = 2;\n//│                 set id = 0;\n//│                 continue loopLabel\n//│               else\n//│                 return param2\n//│             end\n//│         end\n//│       else\n//│         end\n//│     end\n//│   end\n//│ };\n//│ define g⁰ as fun g¹(a, b, c, d) {\n//│   return g_f¹(0, a, b, c, d)\n//│ };\n//│ define f⁰ as fun f¹(a, b, c) { return g_f¹(1, a, b, c, undefined) };\n//│ f¹(10000, 20000, 0)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 50000\n\n:sjs\n:expect 200010000\nmodule A with\n  fun sum_impl(n, acc) = if n == 0 then acc else @tailcall sum_impl(n - 1, n + acc)\n  fun sum(n) = sum_impl(n, 0)\nA.sum(20000)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let A1;\n//│ (class A {\n//│   static {\n//│     A1 = this\n//│   }\n//│   static sum_impl(n1, acc) {\n//│     loopLabel: while (true) {\n//│       let scrut, tmp, tmp1;\n//│       scrut = Predef.equals(n1, 0);\n//│       if (scrut === true) {\n//│         return acc\n//│       }\n//│       tmp = n1 - 1;\n//│       tmp1 = n1 + acc;\n//│       n1 = tmp;\n//│       acc = tmp1;\n//│       continue loopLabel;\n//│     }\n//│   } \n//│   static sum(n1) {\n//│     return A.sum_impl(n1, 0)\n//│   }\n//│   toString() { return runtime.render(this); }\n//│   static [definitionMetadata] = [\"class\", \"A\"]; \n//│ });\n//│ A1.sum(20000)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 200010000\n\n:silent\n:lift\n:rewriteWhile\n:expect 200010000\nval x = mut []\nlet n = 20000\nlet i = 0\nwhile i < n do\n  x.push of () => i\n  set i += 1\nfun sumOf(x, idx, acc) =\n  if idx == 0 then acc\n  else \n    sumOf(x, idx - 1, acc + x![idx]())\nsumOf(x, n - 1, 0)\n\n// Check that spreads are compiled correctly\n\nfun f(x, ...z) =\n  if x < 0 then 0\n  else g(x, 0, x, x)\nfun g(x, y, ...z) =\n  if x < 0 then 0\n  else f(x - 1, 0, ...[x, x, x])\nf(100)\n//│ = 0\n\nfun f(n, x, y, z) =\n  if n > 0 then @tailcall f(n - 1, ...[1, 2], 3) else y\n\n:expect 2\nf(10, 0, 0, 0)\n//│ = 2\n\n:sir\nfun f(n, a, b, c, d, ...e) =\n  if n > 0 then @tailcall g(n - 1)\n  else e\nfun g(n) =\n  @tailcall f(n, ...[1, 2], 3, ...[3, 4], ...[5, n], 7, n)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f², g², f_g⁰;\n//│ define f_g⁰ as fun f_g¹(id, param0, param1, param2, param3, param4, param5) {\n//│   loop loopLabel:\n//│     match id\n//│       0 =>\n//│         let scrut, tmp;\n//│         set scrut = >⁰(param0, 0);\n//│         match scrut\n//│           true =>\n//│             set tmp = -⁰(param0, 1);\n//│             set param0 = tmp;\n//│             set id = 1;\n//│             continue loopLabel\n//│           else\n//│             return param5\n//│         end\n//│       1 =>\n//│         let tmp, tmp1, tmp2, argList, sliceRes;\n//│         set tmp = [1, 2];\n//│         set tmp1 = [3, 4];\n//│         set tmp2 = [5, param0];\n//│         set argList = [param0, ...tmp, 3, ...tmp1, ...tmp2, 7, param0];\n//│         set sliceRes = runtime⁰.Tuple⁰.slice⁰(argList, 5, 0);\n//│         set param0 = argList.0;\n//│         set param1 = argList.1;\n//│         set param2 = argList.2;\n//│         set param3 = argList.3;\n//│         set param4 = argList.4;\n//│         set param5 = sliceRes;\n//│         set id = 0;\n//│         continue loopLabel\n//│       else\n//│         end\n//│     end\n//│   end\n//│ };\n//│ define f² as fun f³(n, a, b, c, d, ...e) {\n//│   return f_g¹(0, n, a, b, c, d, e)\n//│ };\n//│ define g² as fun g³(n) {\n//│   return f_g¹(1, n, undefined, undefined, undefined, undefined, undefined)\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect [4, 5, 0, 7, 0]\ng(10)\n//│ = [4, 5, 0, 7, 0]\n\n:e\n:lift\nfun f(x) =\n  fun g() =\n    @tailcall f(x)\n    @tailcall f(x)\n  @tailcall g()\n//│ ╔══[COMPILATION ERROR] This call is not in tail position.\n//│ ║  l.195: \t    @tailcall f(x)\n//│ ╙──       \t              ^^^^\n\n:lift\nfun f(x) =\n  fun g() =\n    @tailcall f(x)\n  @tailcall g()\n\n// Ensure y is set using x_tmp and x is assigned to x_tmp\n:sir\nfun f(x, y) =\n  if x == 0 then 0\n  else\n    f(x - 1, x)\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁴;\n//│ define f⁴ as fun f⁵(x, y) {\n//│   loop loopLabel:\n//│     let scrut, tmp;\n//│     set scrut = Predef⁰.equals⁰(x, 0);\n//│     match scrut\n//│       true =>\n//│         return 0\n//│       else\n//│         let x_tmp;\n//│         set tmp = -⁰(x, 1);\n//│         set x_tmp = x;\n//│         set x = tmp;\n//│         set y = x_tmp;\n//│         continue loopLabel\n//│     end\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// Make sure variables accessed by nested functions or classes are re-defined in a new scope in the while loop\n:expect 2\nlet lam = () => 0\nfun foo(x) =\n  assert x < 5 else x\n  if x == 2 do set lam = () => x\n  foo(x + 1)\nfoo(0)\nlam()\n//│ = 2\n//│ lam = fun\n\n// Mutrec case\n:expect 2\nlet lam = () => 0\nfun foo1(x) =\n  assert x < 5 else x\n  if x == 2 do set lam = () => x\n  foo2(x + 1)\nfun foo2(x) =\n  assert x < 5 else x\n  if x == 2 do set lam = () => x\n  foo1(x + 1)\nfoo1(0)\nlam()\n//│ = 2\n//│ lam = fun\n\n// Classes\n:expect 2\nlet a\nfun foo(x) =\n  data class A(x)\n  assert x < 5 else x\n  if x == 2 do set a = A(x)\n  foo(x + 1)\nfoo(0)\na.x\n//│ = 2\n//│ a = A(2)\n\n// Functions inside module definitions are lifted to the top level. This means they cannot yet be optimized.\n:lift\n:fixme\nmodule A with\n  fun f(x) =\n    fun g(x) = if x < 0 then 0 else @tailcall f(x)\n    @tailcall g(x - 1)\nA.f(10000)\n//│ ╔══[COMPILATION ERROR] This tail call exits the current scope and is not optimized.\n//│ ║  l.283: \t    fun g(x) = if x < 0 then 0 else @tailcall f(x)\n//│ ╙──       \t                                              ^^^^\n//│ ╔══[COMPILATION ERROR] This tail call exits the current scope and is not optimized.\n//│ ║  l.284: \t    @tailcall g(x - 1)\n//│ ╙──       \t              ^^^^^^^^\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n// These calls are represented as field selections and don't yet have the explicitTailCall parameter.\n:breakme\n:e\nmodule A with\n  fun f = g\n  fun g =\n    @tailcall f\n    f\n\n:expect 0\nmodule A with\n  fun f(x) = if x == 0 then 0 else @tailcall g(x - 1)\n  fun g(x) = if x == 0 then 1 else @tailcall f(x - 1)\nA.f(10)\n//│ = 0\n\n:todo\n:expect 0\nclass A with\n  @tailrec fun f(x) = if x == 0 then 0 else @tailcall g(x - 1)\n  fun g(x) = if x == 0 then 1 else @tailcall f(x - 1)\n(new A).f(10)\n//│ ╔══[COMPILATION ERROR] Calls from class methods cannot yet be marked @tailcall.\n//│ ║  l.313: \t  @tailrec fun f(x) = if x == 0 then 0 else @tailcall g(x - 1)\n//│ ╙──       \t                                                      ^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Class methods may not yet be marked @tailrec.\n//│ ║  l.313: \t  @tailrec fun f(x) = if x == 0 then 0 else @tailcall g(x - 1)\n//│ ╙──       \t               ^\n//│ ╔══[COMPILATION ERROR] Calls from class methods cannot yet be marked @tailcall.\n//│ ║  l.314: \t  fun g(x) = if x == 0 then 1 else @tailcall f(x - 1)\n//│ ╙──       \t                                             ^^^^^^^^\n//│ = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/AndNewline.mls",
    "content": ":js\n\n\n// Bug fix: `and` on its own line in `if` condition should work\nif\n  true\n  and\n  true do\n    print(\"ok\")\n//│ > ok\n\n// `and` at end of line (always worked):\nif\n  true and\n  true do\n    print(\"ok2\")\n//│ > ok2\n\n// Same-line version (always worked):\nif\n  true and\n    true do\n      print(\"ok3\")\n//│ > ok3\n\n// false-and case\nif\n  true\n  and\n  false do\n    print(\"should not print\")\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/examples/BinarySearchTree.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Option { Some, None }\nopen Stack\n\nfun (~~>) toBe(x, y) = if x === y then () else throw Error(String(x) + \" is not \" + String(y))\nfun (<?) min(x, y) = if x < y then x else y\nfun (>?) max(x, y) = if x > y then x else y\nfun abs(x) = if x < 0 then -x else x\n\nfun (??) getOrElse = Option.getOrElse\n\nabstract class Tree[out A]\ndata class Node[out A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A]\nobject Empty extends Tree\n\nfun single(v) = Node(v, Empty, Empty)\n\nfun show[A](t: Tree[A]): Str = if t is\n  Node(v, l, r) then\n    \"(\" + show(l) + \" \" + String(v) + \" \" + show(r) + \")\"\n  Empty then \"•\"\n\nshow(Empty)\nshow(Node(0, Empty, Empty))\nshow(Node(1, Node(0, Empty, Empty), Empty))\nshow(Node(1, Node(0, Empty, Empty), Node(2, Empty, Empty)))\n//│ = \"((• 0 •) 1 (• 2 •))\"\n\nfun insert(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then Node(v', insert(l, v), r)\n    v > v' then Node(v', l, insert(r, v))\n    _ then t\n  Empty then Node(v, Empty, Empty)\n\nfun insert'(t, v) = if t is\n  Node(v', l, r) and v\n    < v' then Node(v', insert(l, v), r)\n    > v' then Node(v', l, insert(r, v))\n    else t\n  Empty then Node(v, Empty, Empty)\n\ninsert(Empty, 0) |> show\n//│ = \"(• 0 •)\"\n\ninsert'(Empty, 0) |> show\n//│ = \"(• 0 •)\"\n\ninsert(Node(0, Empty, Empty), 0) |> show\n//│ = \"(• 0 •)\"\n\ninsert'(Node(0, Empty, Empty), 0) |> show\n//│ = \"(• 0 •)\"\n\ninsert(Node(1, Empty, Empty), 0) |> show\n//│ = \"((• 0 •) 1 •)\"\n\ninsert'(Node(1, Empty, Empty), 0) |> show\n//│ = \"((• 0 •) 1 •)\"\n\ninsert(Node(1, Node(0, Empty, Empty), Empty), 0) |> show\n//│ = \"((• 0 •) 1 •)\"\n\ninsert'(Node(1, Node(0, Empty, Empty), Empty), 0) |> show\n//│ = \"((• 0 •) 1 •)\"\n\ninsert(Node(1, Node(0, Empty, Empty), Empty), 2) |> show\n//│ = \"((• 0 •) 1 (• 2 •))\"\n\ninsert'(Node(1, Node(0, Empty, Empty), Empty), 2) |> show\n//│ = \"((• 0 •) 1 (• 2 •))\"\n\nfun fromList(l) =\n  fun fromList'(t, xs) =\n    if xs is\n      Cons(x, xs') then fromList'(insert(t, x), xs')\n      Nil then t\n  fromList'(Empty, l)\n\nfromList(1 :: 2 :: 3 :: 4 :: Nil) |> show\n//│ = \"(• 1 (• 2 (• 3 (• 4 •))))\"\n\nfromList(2 :: 1 :: 4 :: 3 :: Nil) |> show\n//│ = \"((• 1 •) 2 ((• 3 •) 4 •))\"\n\nfromList(4 :: 3 :: 2 :: 1 :: Nil) |> show\n//│ = \"((((• 1 •) 2 •) 3 •) 4 •)\"\n\nlet example1 = fromList(1 :: 3 :: 2 :: 4 :: Nil)\n//│ example1 = Node(1, Empty, Node(3, Node(2, Empty, Empty), Node(4, Empty, Empty)))\n\nexample1 |> show\n//│ = \"(• 1 ((• 2 •) 3 (• 4 •)))\"\n\nfun contains(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then contains(l, v)\n    v > v' then contains(r, v)\n    _ then true\n  Empty then false\n\n// Writing tests like this is very interesting.\ncontains(Empty, 0) ~~> false\ncontains(Node(0, Empty, Empty), 0) ~~> true\ncontains(Node(1, Empty, Empty), 0) ~~> false\n\nfun minValue(t) = if t is\n  Empty then None\n  Node(v, Empty, _) then Some(v)\n  Node(_, l, _) then minValue(l)\n\nminValue(Empty) ?? \"not found\"\n//│ = \"not found\"\n\nminValue(Node(0, Empty, Empty)) ?? \"not found\"\n//│ = 0\n\nminValue(example1) ?? \"not found\"\n//│ = 1\n\nfun maxValue(t) = if t is\n  Empty then None\n  Node(v, _, Empty) then Some(v)\n  Node(_, _, r) then maxValue(r)\n\nmaxValue(Empty) ?? \"not found\"\n//│ = \"not found\"\n\nmaxValue(Node(0, Empty, Empty)) ?? \"not found\"\n//│ = 0\n\nmaxValue(example1) ?? \"not found\"\n//│ = 4\n\nfun lowerBound(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then lowerBound(l, v)\n    v > v' then Some(lowerBound(r, v) ?? v')\n    else Some(v')\n  Empty then None\n\nlowerBound(Empty, 0) ?? \"not found\"\n//│ = \"not found\"\n\nlowerBound(Node(0, Empty, Empty), 0) ?? \"not found\"\n//│ = 0\n\nlowerBound(Node(1, Empty, Empty), 0) ?? \"not found\"\n//│ = \"not found\"\n\nlowerBound(Node(-1, Empty, Empty), 0) ?? \"not found\"\n//│ = -1\n\nlowerBound(example1, 0) ?? \"not found\"\n//│ = \"not found\"\n\nlowerBound(example1, 1) ?? \"not found\"\n//│ = 1\n\nlowerBound(example1, 2) ?? \"not found\"\n//│ = 2\n\nlowerBound(example1, 3) ?? \"not found\"\n//│ = 3\n\nlowerBound(example1, 4) ?? \"not found\"\n//│ = 4\n\nlowerBound(example1, 5) ?? \"not found\"\n//│ = 4\n\nlet example2 = fromList(1 :: 5 :: 42 :: 10 :: 23 :: 59 :: 81 :: Nil)\n//│ example2 = Node(\n//│   1,\n//│   Empty,\n//│   Node(\n//│     5,\n//│     Empty,\n//│     Node(\n//│       42,\n//│       Node(10, Empty, Node(23, Empty, Empty)),\n//│       Node(59, Empty, Node(81, Empty, Empty))\n//│     )\n//│   )\n//│ )\n\nlowerBound(example2, 0) ?? \"not found\"\n//│ = \"not found\"\n\nlowerBound(example2, 25) ?? \"not found\"\n//│ = 23\n\nlowerBound(example2, 99) ?? \"not found\"\n//│ = 81\n\nlowerBound(example2, 7) ?? \"not found\"\n//│ = 5\n\nlowerBound(example2, 32) ?? \"not found\"\n//│ = 23\n\nlowerBound(example2, 41) ?? \"not found\"\n//│ = 23\n\nfun upperBound(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then Some(upperBound(l, v) ?? v')\n    v > v' then upperBound(r, v)\n    _ then Some(v')\n  Empty then None\n\nupperBound(example2, 0) ?? \"not found\"\n//│ = 1\n\nupperBound(example2, 25) ?? \"not found\"\n//│ = 42\n\nupperBound(example2, 99) ?? \"not found\"\n//│ = \"not found\"\n\nupperBound(example2, 7) ?? \"not found\"\n//│ = 10\n\nupperBound(example2, 32) ?? \"not found\"\n//│ = 42\n\nupperBound(example2, 41) ?? \"not found\"\n//│ = 42\n\nfun remove(t, v) =\n  if t is\n    Node(v', l, r) and\n      v < v' then Node(v', remove(l, v), r)\n      v > v' then Node(v', l, remove(r, v))\n      minValue(r) is\n        None then l\n        Some(v'') then Node(v'', l, remove(r, v''))\n    Empty then Empty\n\nremove(Empty, 0) |> show\n//│ = \"•\"\n\nremove(Node(0, Empty, Empty), 0) |> show\n//│ = \"•\"\n\nremove(Node(1, Empty, Empty), 0) |> show\n//│ = \"(• 1 •)\"\n\nremove(Node(1, Node(0, Empty, Empty), Empty), 0) |> show\n//│ = \"(• 1 •)\"\n\nremove(Node(1, Empty, Node(2, Empty, Empty)), 2) |> show\n//│ = \"(• 1 •)\"\n\nremove(Node(1, Node(0, Empty, Empty), Node(2, Empty, Empty)), 1) |> show\n//│ = \"((• 0 •) 2 •)\"\n\nexample1 |> show\n//│ = \"(• 1 ((• 2 •) 3 (• 4 •)))\"\n\nremove(example1, 0) |> show\n//│ = \"(• 1 ((• 2 •) 3 (• 4 •)))\"\n\nremove(example1, 1) |> show\n//│ = \"(• 2 (• 3 (• 4 •)))\"\n\nremove(example1, 2) |> show\n//│ = \"(• 1 (• 3 (• 4 •)))\"\n\nremove(example1, 3) |> show\n//│ = \"(• 1 ((• 2 •) 4 •))\"\n\nremove(example1, 4) |> show\n//│ = \"(• 1 ((• 2 •) 3 •))\"\n\nfun extractMin(t) =\n  if t is\n    Node(v, Empty, r) then [Some(v), r]\n    Node(v, l, r) and\n      extractMin(l) is [m, l'] then\n        [m, Node(v, l', r)]\n    Empty then [None, Empty]\n\nextractMin(example1).0 ?? \"not found\"\n//│ = 1\n\nextractMin(example1).1 |> show\n//│ = \"((• 2 •) 3 (• 4 •))\"\n\nfun merge(l, r) =\n  if extractMin(r) is\n    [None, _] then l\n    [Some(m), r'] then Node(m, l, r')\n\nmerge(Empty, Empty) |> show\n//│ = \"•\"\n\nmerge(Empty, Node(0, Empty, Empty)) |> show\n//│ = \"(• 0 •)\"\n\nmerge(Node(0, Empty, Empty), Empty) |> show\n//│ = \"(• 0 •)\"\n\nmerge(Node(0, Empty, Empty), Node(1, Empty, Empty)) |> show\n//│ = \"((• 0 •) 1 •)\"\n\nmerge(Node(0, Empty, Empty), Node(2, Node(1, Empty, Empty), Empty)) |> show\n//│ = \"((• 0 •) 1 (• 2 •))\"\n\nfun removeGte(t, v) =\n  if t is\n    Node(v', l, r) and\n      v < v' then removeGte(l, v)\n      v > v' then Node(v', l, removeGte(r, v))\n      _ then l // lucky case\n    Empty then Empty\n\nremoveGte(Empty, 0) |> show\n//│ = \"•\"\n\nremoveGte(example1, 0) |> show\n//│ = \"•\"\n\nremoveGte(example1, 1) |> show\n//│ = \"•\"\n\nremoveGte(example1, 2) |> show\n//│ = \"(• 1 •)\"\n\nremoveGte(example1, 3) |> show\n//│ = \"(• 1 (• 2 •))\"\n\nremoveGte(example1, 4) |> show\n//│ = \"(• 1 ((• 2 •) 3 •))\"\n\nremoveGte(example1, 5) |> show\n//│ = \"(• 1 ((• 2 •) 3 (• 4 •)))\"\n\nexample2 |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))\"\n\nremoveGte(example2, 10) |> show\n//│ = \"(• 1 (• 5 •))\"\n\nremoveGte(example2, 22) |> show\n//│ = \"(• 1 (• 5 (• 10 •)))\"\n\nremoveGte(example2, 23) |> show\n//│ = \"(• 1 (• 5 (• 10 •)))\"\n\nremoveGte(example2, 24) |> show\n//│ = \"(• 1 (• 5 (• 10 (• 23 •))))\"\n\nremoveGte(example2, 70) |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 •))))\"\n\nremoveGte(example2, 99) |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))\"\n\nfun removeLt(t, v) =\n  if t is\n    Node(v', l, r) and\n      v' < v then removeLt(r, v)\n      else Node(v', removeLt(l, v), r)\n    Empty then Empty\n\nexample2 |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))\"\n\nremoveLt(example2, 10) |> show\n//│ = \"((• 10 (• 23 •)) 42 (• 59 (• 81 •)))\"\n\nremoveLt(example2, 22) |> show\n//│ = \"((• 23 •) 42 (• 59 (• 81 •)))\"\n\nremoveLt(example2, 23) |> show\n//│ = \"((• 23 •) 42 (• 59 (• 81 •)))\"\n\nremoveLt(example2, 24) |> show\n//│ = \"(• 42 (• 59 (• 81 •)))\"\n\nremoveLt(example2, 70) |> show\n//│ = \"(• 81 •)\"\n\nremoveLt(example2, 99) |> show\n//│ = \"•\"\n\n// Remove elements from `begin` until `end`.\nfun removeRange(t, begin, end) =\n  if t is\n    Node(v, l, r) and\n      begin > v then Node(v, l, removeRange(r, begin, end))\n      end <= v then Node(v, removeRange(l, begin, end), r)\n      _ then merge(removeGte(l, begin), removeLt(r, end))\n    Empty then Empty\n\nexample2 |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))\"\n\nremoveRange(example2, -10000, 10000) |> show\n//│ = \"•\"\n\nremoveRange(example2, 1, 82) |> show\n//│ = \"•\"\n\nremoveRange(example2, 1, 50) |> show\n//│ = \"(• 59 (• 81 •))\"\n\nremoveRange(example2, 50, 81) |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 81 •))))\"\n\nremoveRange(example2, 20, 60) |> show\n//│ = \"(• 1 (• 5 ((• 10 •) 81 •)))\"\n\nremoveRange(example2, 20, 24) |> show\n//│ = \"(• 1 (• 5 ((• 10 •) 42 (• 59 (• 81 •)))))\"\n\nremoveRange(example2, 59, 60) |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 81 •))))\"\n\nremoveRange(example2, 59, 59) |> show\n//│ = \"(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))\"\n\nfun size(t) =\n  if t is\n    Node(_, l, r) then 1 + size(l) + size(r)\n    Empty then 0\n\nsize(Empty) ~~> 0\nsize(Node(0, Empty, Empty)) ~~> 1\nsize(example1) ~~> 4\nsize(example2) ~~> 7\n\nfun inverse(t) =\n  if t is\n    Node(v, l, r) then Node(v, inverse(r), inverse(l))\n    Empty then Empty\n\ninverse(Empty) |> show\n//│ = \"•\"\n\ninverse(Node(0, Empty, Empty)) |> show\n//│ = \"(• 0 •)\"\n\ninverse(example1) |> show\n//│ = \"(((• 4 •) 3 (• 2 •)) 1 •)\"\n\ninverse(example2) |> show\n//│ = \"(((((• 81 •) 59 •) 42 ((• 23 •) 10 •)) 5 •) 1 •)\"\n\nfun height(t) =\n  if t is\n    Node(_, l, r) then 1 + max(height(l), height(r))\n    Empty then 0\n\nheight(Empty) ~~> 0\nheight(Node(0, Empty, Empty)) ~~> 1\nheight(example1) ~~> 3\nheight(example2) ~~> 5\n\nfun isBalanced(t) =\n  if t is\n    Empty then true\n    Node(_, l, r) and height(l) is hl and height(r) is hr then\n      abs(hl - hr) <= 1 && isBalanced(l) && isBalanced(r)\n\nisBalanced(Empty) ~~> true\nisBalanced(Node(0, Empty, Empty)) ~~> true\nisBalanced(example1) ~~> false\nisBalanced(example2) ~~> false\n\nisBalanced(Node(1, single(-1), single(3))) ~~> true\nisBalanced(Node(1, single(-1), Node(3, single(2), Empty))) ~~> true\nisBalanced(Node(1, single(-1), Node(3, Empty, single(4)))) ~~> true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/examples/EitherOrBoth.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/StrOps.mls\"\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option\nopen StrOps\n\nabstract class EitherOrBoth[out A, out B]: (Left[A, B] | Right[A, B] | Both[A, B])\ndata class Left[out A, out B](value: A) extends EitherOrBoth[A, B]\ndata class Right[out A, out B](value: B) extends EitherOrBoth[A, B]\ndata class Both[out A, out B](left: A, right: B) extends EitherOrBoth[A, B] \n\ntype Either[A, B] = Left[A, B] | Right[A, B]\n\nfun getLeft[A, B](eob: EitherOrBoth[A, B]): Option[A] =\n  if eob is\n    Left(left) then Some(left)\n    Right(_) then None\n    Both(left, _) then Some(left)\n\nfun getRight[A, B](eob: EitherOrBoth[A, B]): Option[B] =\n  if eob is\n    Left(_) then None\n    Right(right) then Some(right)\n    Both(_, right) then Some(right)\n\nfun getBoth[A, B](eob: EitherOrBoth[A, B]): Option[[A, B]] =\n  if eob is\n    Left(_) then None\n    Right(_) then None\n    Both(left, right) then Some([left, right])\n\nfun mapLeft[A, B, C](eob: EitherOrBoth[A, B], f: A -> C): EitherOrBoth[C, B] =\n  if eob is\n    Left(left) then Left(f(left))\n    Right(right) then Right(right)\n    Both(left, right) then Both(f(left), right)\n\nfun mapRight[A, B, C](eob: EitherOrBoth[A, B], f: B -> C): EitherOrBoth[A, C] =\n  if eob is\n    Left(left) then Left(left)\n    Right(right) then Right(f(right))\n    Both(left, right) then Both(left, f(right))\n\nfun map[A, B, C, D](eob: EitherOrBoth[A, B], f: A -> C, g: B -> D): EitherOrBoth[C, D] =\n  if eob is\n    Left(left) then Left(f(left))\n    Right(right) then Right(g(right))\n    Both(left, right) then Both(f(left), g(right))\n\nfun fold[A, B, C](eob: EitherOrBoth[A, B], f: A -> C, g: B -> C, h: [A, B] -> C): C =\n  if eob is\n    Left(left) then f(left)\n    Right(right) then g(right)\n    Both(left, right) then h(left, right)\n\nfun isLeft[A, B](eob: EitherOrBoth[A, B]): Bool =\n  if eob is\n    Left(_) then true\n    Right(_) then false\n    Both(_, _) then false\n\nfun isRight[A, B](eob: EitherOrBoth[A, B]): Bool =\n  if eob is\n    Left(_) then false\n    Right(_) then true\n    Both(_, _) then false\n\nfun isBoth[A, B](eob: EitherOrBoth[A, B]): Bool =\n  if eob is\n    Left(_) then false\n    Right(_) then false\n    Both(_, _) then true\n\nfun eobToString[A, B](eob: EitherOrBoth[A, B]): Str =\n  if eob is\n    Left(left) then \"Left(\" ~ StrOps.from(left) ~ \")\"\n    Right(right) then \"Right(\" ~ StrOps.from(right) ~ \")\"\n    Both(left, right) then \"Both(\" ~ StrOps.from(left) ~ \", \" ~ StrOps.from(right) ~ \")\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/examples/LeftistTree.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Option { Some, None }\nopen Stack\n\nfun (??) getOrElse = Option.getOrElse\n\nabstract class Tree[out A]: (Empty | Node[A])\ndata class Node[out A](value: A, left: Tree[A], right: Tree[A], rank: Int) extends Tree[A]\nobject Empty extends Tree[Nothing]\n\nfun show(t: Tree[Any]): Str = if t is\n  Node(v, l, r, _) then\n    \"(\" + show(l) + \" \" + String(v) + \" \" + show(r) + \")\"\n  Empty then \"•\"\n\nfun singleton(x) = Node(x, Empty, Empty, 1)\nfun rank(t) = if t is\n  Empty then 0\n  Node(_, _, _, r) then r\n\nfun merge(t1: Tree[Num], t2: Tree[Num]): Tree[Num] =\n  if\n    t1 is Empty then t2\n    t2 is Empty then t1\n    t1 is Node(v1, l1, r1, _) and t2 is Node(v2, _, _, _) and\n      v1 <= v2 and\n        let merged = merge(r1, t2)\n        let rank_left = rank of l1\n        let rank_right = rank of r1\n        rank_left >= rank_right then\n          Node(v1, l1, merged, rank_right + 1)\n        else\n          Node(v1, merged, l1, rank_left + 1)\n      else merge(t2, t1)\n\nfun insert(t, v) = merge(t, singleton(v))\n\nfun getMin(t) =\n  if t is\n    Empty then None\n    Node(x, _, _, _) then Some(x)\n\nfun deleteMin(t) =\n  if t is\n    Empty then Empty\n    Node(_, l, r, _) then merge(l, r)\n\nfun fromList(t, xs) =\n  if xs is\n    Cons(x, xs') then fromList(insert(t, x), xs')\n    Nil then t\n\nlet tree1 = fromList(Empty, 3 :: 4 :: 1 :: 2 :: Nil)\n//│ tree1 = Node(\n//│   1,\n//│   Node(2, Empty, Node(3, Empty, Node(4, Empty, Empty, 1), 1), 1),\n//│   Empty,\n//│   1\n//│ )\n\ntree1 |> show\n//│ = \"((• 2 (• 3 (• 4 •))) 1 •)\"\n\n:expect 1\n// Remove the smallest element. It should be 1.\ngetMin(tree1) ?? \"Nothing\"\n//│ = 1\n\nlet tree1' = deleteMin(tree1)\n//│ tree1' = Node(2, Empty, Node(3, Empty, Node(4, Empty, Empty, 1), 1), 1)\n\ntree1' |> show\n//│ = \"(• 2 (• 3 (• 4 •)))\"\n\n:expect 2\n// Remove one more element. It should be 2.\ngetMin(tree1') ?? \"Nothing\"\n//│ = 2\n\nlet tree1'' = deleteMin(tree1')\n//│ tree1'' = Node(3, Empty, Node(4, Empty, Empty, 1), 1)\n\ntree1'' |> show\n//│ = \"(• 3 (• 4 •))\"\n\n:expect 3\n// Remove one more element. It should be 3.\ngetMin(tree1'') ?? \"Nothing\"\n//│ = 3\n\nlet tree1''' = deleteMin(tree1'')\n//│ tree1''' = Node(4, Empty, Empty, 1)\n\ntree1''' |> show\n//│ = \"(• 4 •)\"\n\n:expect 4\n// Remove the last element. It should be 4.\ngetMin(tree1''') ?? \"Nothing\"\n//│ = 4\n\nlet tree1'''' = deleteMin(tree1''')\n//│ tree1'''' = Empty\n\ntree1'''' |> show\n//│ = \"•\"\n\nfun drain(t) =\n  if getMin(t) is\n    None then Nil\n    Some(x) then x :: drain(deleteMin(t))\n\nfun sorted(xs) = fromList(Empty, xs) |> drain\n\nfun showList(xs) =\n  if xs is\n    Cons(x, Nil) then String(x)\n    Cons(x, xs') then String(x) + \", \" + showList(xs')\n    Nil then \"\"\n\nsorted(3 :: 4 :: 1 :: 2 :: Nil) |> showList\n//│ = \"1, 2, 3, 4\"\n\nsorted(42 :: 58 :: 19 :: 37 :: 44 :: 99 :: 68 :: 60 :: 77 :: 61 :: Nil) |> showList\n//│ = \"19, 37, 42, 44, 58, 60, 61, 68, 77, 99\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/examples/ListFold.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Option.mls\"\nimport \"../../../mlscript-compile/StrOps.mls\"\n\nopen Stack\nopen Option\nopen StrOps\n\nfun (|>) pipe(x, f) = f(x)\n\nfun findFirst(f, xs) =\n  if xs is\n    Nil then None\n    Cons(x, _) and f(x) then Some(x)\n    Cons(_, xs) then findFirst(f, xs)\n\nfun (::) cons(head, tail) = Cons(head, tail)\n\nlet oneTwoThree = 1 :: 2 :: 3 :: Nil\n//│ oneTwoThree = Cons(1, Cons(2, Cons(3, Nil)))\n\n// Note that JavaScript doesn't have tail call optimization. Therefore, this\n// implementation is still inefficient in practice.\nfun join(sep) =\n  fun aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(acc ~ sep ~ StrOps.from(x), xs')\n  (xs) =>\n    if xs is\n      Cons(x, xs') then aux(StrOps.from(x), xs')\n      Nil then \"\"\n\njoin(\", \")(1 :: 2 :: 3 :: Nil)\n(1 :: 2 :: 3 :: Nil) |> join(\", \")\n//│ = \"1, 2, 3\"\n\nfun showList(xs) = \"[\" ~ join(\", \")(xs) ~ \"]\"\n\nfun (:::) appendAll(xs, ys) =\n  if xs is\n    Nil then ys\n    Cons(x, xs') then x :: (xs' ::: ys)\n\n((1 :: 2 :: 3 :: Nil) ::: (4 :: 5 :: 6 :: Nil)) |> showList\n//│ = \"[1, 2, 3, 4, 5, 6]\"\n\nfun reverse(xs) =\n  fun aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(x :: acc, xs')\n  aux(Nil, xs)\n\n(1 :: 2 :: 3 :: Nil) |> showList\nreverse(1 :: 2 :: 3 :: Nil) |> showList\n//│ = \"[3, 2, 1]\"\n\n//   __       _     _ _          __ _\n//  / _| ___ | | __| | |    ___ / _| |_\n// | |_ / _ \\| |/ _` | |   / _ \\ |_| __|\n// |  _| (_) | | (_| | |__|  __/  _| |_\n// |_|  \\___/|_|\\__,_|_____\\___|_|  \\__|\n//\n\nfun foldLeft(f)(z) =\n  fun aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(f(acc, x), xs')\n  (xs) => aux(z, xs)\n\nlet sum = foldLeft((acc, x) => acc + x)(0)\n//│ sum = fun\n\n:expect 0\nsum(Nil)\n//│ = 0\n\n:expect 6\nsum(1 :: 2 :: 3 :: Nil)\n//│ = 6\n\nlet product = foldLeft((acc, x) => acc * x)(1)\n//│ product = fun\n\n:expect 1\nproduct(Nil)\n//│ = 1\n\n:expect 6\nproduct(1 :: 2 :: 3 :: Nil)\n//│ = 6\n\nlet length = foldLeft((acc, _) => acc + 1)(0)\n//│ length = fun\n\n:expect 0\nlength(Nil)\n//│ = 0\n\n:expect 3\nlength(1 :: 2 :: 3 :: Nil)\n//│ = 3\n\nlet reverse' = foldLeft((acc, x) => x :: acc)(Nil)\n//│ reverse' = fun\n\nreverse'(Nil)\n//│ = Nil\n\nreverse'(1 :: 2 :: 3 :: Nil) |> showList\n//│ = \"[3, 2, 1]\"\n\n\n//   __       _     _ ____  _       _     _\n//  / _| ___ | | __| |  _ \\(_) __ _| |__ | |_\n// | |_ / _ \\| |/ _` | |_) | |/ _` | '_ \\| __|\n// |  _| (_) | | (_| |  _ <| | (_| | | | | |_\n// |_|  \\___/|_|\\__,_|_| \\_\\_|\\__, |_| |_|\\__|\n//                            |___/\n\nfun foldRight(f)(z) =\n  fun aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then f(x, aux(acc, xs'))\n  (xs) => aux(z, xs)\n\nlet double = foldRight((x, acc) => x :: x :: acc)(Nil)\n//│ double = fun\n\ndouble(Nil) |> showList\n//│ = \"[]\"\n\ndouble(1 :: 2 :: 3 :: Nil) |> showList\n//│ = \"[1, 1, 2, 2, 3, 3]\"\n\nlet flatten = foldRight((xs, acc) => xs ::: acc)(Nil)\n//│ flatten = fun\n\nflatten(Nil) |> showList\n//│ = \"[]\"\n\nflatten(oneTwoThree :: oneTwoThree :: oneTwoThree :: Nil) |> showList\n//│ = \"[1, 2, 3, 1, 2, 3, 1, 2, 3]\"\n\nfun id(x) = x\n\nfun foldLeft'[A, B](f: (A, B) -> A)(z: A) =\n  let g(x, y)(z) = y(f(z, x))\n  (xs) => foldRight(g)(id)(xs)(z)\n\nlet minus = foldLeft'((acc, x) => acc - x)(0)\n//│ minus = fun\n\nminus(Nil)\n//│ = 0\n\nminus(1 :: 2 :: 3 :: Nil)\n//│ = -6\n\nlet reverse'' = foldLeft'((acc, x) => x :: acc)(Nil)\n//│ reverse'' = fun\n\nreverse(Nil)\n//│ = Nil\n\nreverse(1 :: 2 :: 3 :: Nil) |> showList\n//│ = \"[3, 2, 1]\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/examples/Permutations.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/StrOps.mls\"\n\nopen Stack\n\nfun showList(xs) = \"[\" + xs Iter.fromStack() Iter.joined(\", \") + \"]\"\n\nfun foldLeft(f)(z) =\n  fun aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(f(acc, x), xs')\n  (xs) => aux(z, xs)\n\nfun showLists(xs) = print of\n  \"[\\n\" + xs Iter.fromStack() Iter.mapping(showList) Iter.mapping(s => \"  \" + s) Iter.joined(\",\\n\") + \"\\n]\"\n\nfun (~>..) insertAllPositions(z, xs) =\n  fun go(prev, lists, next) =\n    if next is\n      Nil then ((prev :+ z) :: lists) |> reverse\n      head :: tail then\n        let nu = ((prev :+ z) ::: next)\n        go(prev :+ head, nu :: lists, tail)\n  go(Nil, Nil, xs)\n\n0 ~>.. (1 :: 2 :: 3 :: Nil) |> showLists\n//│ > [\n//│ >   [0, 1, 2, 3],\n//│ >   [1, 0, 2, 3],\n//│ >   [1, 2, 0, 3],\n//│ >   [1, 2, 3, 0]\n//│ > ]\n\nfun permutations(xs) =\n  if xs is\n    Nil then Nil\n    x :: Nil then (x :: Nil) :: Nil\n    x :: xs' then permutations(xs')\n      Iter.fromStack()\n      Iter.folded of Nil, (acc, ys) => acc ::: (x ~>.. ys)\n\npermutations(Nil) |> showLists\n//│ > [\n//│ > \n//│ > ]\n\npermutations(1 :: Nil) |> showLists\n//│ > [\n//│ >   [1]\n//│ > ]\n\npermutations(1 :: 2 :: Nil) |> showLists\n//│ > [\n//│ >   [1, 2],\n//│ >   [2, 1]\n//│ > ]\n\npermutations(1 :: 2 :: 3 :: Nil) |> showLists\n//│ > [\n//│ >   [1, 2, 3],\n//│ >   [2, 1, 3],\n//│ >   [2, 3, 1],\n//│ >   [1, 3, 2],\n//│ >   [3, 1, 2],\n//│ >   [3, 2, 1]\n//│ > ]\n\nfun permutations'(xs) = if xs is\n  Nil then Nil\n  Cons(x, Nil) then (x :: Nil) :: Nil\n  else xs\n    Iter.fromStack()\n    Iter.folded of Nil, (acc, x) => acc ::: permutations'(xs filter of (y) => x != y)\n      Iter.fromStack()\n      Iter.mapping((ys) => x :: ys)\n      Iter.toStack()\n\npermutations'(Nil) |> showLists\n//│ > [\n//│ > \n//│ > ]\n\npermutations'(1 :: Nil) |> showLists\n//│ > [\n//│ >   [1]\n//│ > ]\n\npermutations'(1 :: 2 :: Nil) |> showLists\n//│ > [\n//│ >   [1, 2],\n//│ >   [2, 1]\n//│ > ]\n\npermutations'(1 :: 2 :: 3 :: Nil) |> showLists\n//│ > [\n//│ >   [1, 2, 3],\n//│ >   [1, 3, 2],\n//│ >   [2, 1, 3],\n//│ >   [2, 3, 1],\n//│ >   [3, 1, 2],\n//│ >   [3, 2, 1]\n//│ > ]\n\npermutations'(1 :: 2 :: 3 :: 4 :: Nil) |> showLists\n//│ > [\n//│ >   [1, 2, 3, 4],\n//│ >   [1, 2, 4, 3],\n//│ >   [1, 3, 2, 4],\n//│ >   [1, 3, 4, 2],\n//│ >   [1, 4, 2, 3],\n//│ >   [1, 4, 3, 2],\n//│ >   [2, 1, 3, 4],\n//│ >   [2, 1, 4, 3],\n//│ >   [2, 3, 1, 4],\n//│ >   [2, 3, 4, 1],\n//│ >   [2, 4, 1, 3],\n//│ >   [2, 4, 3, 1],\n//│ >   [3, 1, 2, 4],\n//│ >   [3, 1, 4, 2],\n//│ >   [3, 2, 1, 4],\n//│ >   [3, 2, 4, 1],\n//│ >   [3, 4, 1, 2],\n//│ >   [3, 4, 2, 1],\n//│ >   [4, 1, 2, 3],\n//│ >   [4, 1, 3, 2],\n//│ >   [4, 2, 1, 3],\n//│ >   [4, 2, 3, 1],\n//│ >   [4, 3, 1, 2],\n//│ >   [4, 3, 2, 1]\n//│ > ]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/examples/SimpleTree.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\ntype Tree[out A] = Node[A] | Empty\nobject Empty\ndata class Node[out A](value: A, left: Tree[A], right: Tree[A])\n\nfun find(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then find(l, v)\n    v > v' then find(r, v)\n    _ then Some(v)\n  Empty then None\n\nfun insert(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then Node(v', insert(l, v), r)\n    v > v' then Node(v', l, insert(r, v))\n    _ then t\n  Empty then Node(v, Empty, Empty)\n\nfind(Empty, 0)\n//│ = None\n\nfind(Node(0, Empty, Empty), 0)\n//│ = Some(0)\n\nfind(Node(1, Empty, Empty), 0)\n//│ = None\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/examples/ULC.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\n\nopen Option { Some, None }\nopen Stack\n\nfun par(a) = \"(\" + a + \")\"\n\nfun showList(xs) = \"[\" + xs Iter.fromStack() Iter.joined(\", \") + \"]\"\n\nfun contains(xs, x) = xs Iter.fromStack() Iter.some of _ === x\n\ncontains(\"x\" :: \"y\" :: \"z\" :: Nil, \"y\")\n//│ = true\n\ncontains(\"x\" :: \"y\" :: \"z\" :: Nil, \"w\")\n//│ = false\n\nfun exclude(xs, x) =\n  if xs is\n    Nil then Nil\n    Cons(x', xs') and\n      x === x' then exclude(xs', x)\n      else Cons(x', exclude(xs', x))\n\nexclude(\"x\" :: \"y\" :: \"z\" :: Nil, \"y\") |> showList\n//│ = \"[x, z]\"\n\nexclude(\"x\" :: \"y\" :: \"z\" :: Nil, \"w\") |> showList\n//│ = \"[x, y, z]\"\n\n//  _____\n// |_   _|___  _ __  _ __ ___\n//   | | / _ \\| '__|| '_ ` _ \\\n//   | ||  __/| |   | | | | | |\n//   |_| \\___||_|   |_| |_| |_|\n//\n\ntype Term = Var | Abs | App\ndata class Var(name: Str)\ndata class Abs(lhs: Var, rhs: Term)\ndata class App(lhs: Term, rhs: Term)\n\nfun showTerm(t) =\n  if t is\n    Var(name) then String(name)\n    Abs(lhs, rhs) then \"λ\" + showTerm(lhs) + \". \" + showTerm(rhs)\n    App(Abs(lhs0, lhs1), rhs) then\n      \"((\" + \"λ\" + showTerm(lhs0) + \". \" + showTerm(lhs1) + \") \" + showTerm(rhs) + \")\"\n    App(lhs, rhs) then par(showTerm(lhs) + \" \" + showTerm(rhs))\n\nshowTerm(Var(\"x\"))\n//│ = \"x\"\n\nshowTerm(Abs(Var(\"x\"), Var(\"y\")))\n//│ = \"λx. y\"\n\nshowTerm(App(Var(\"x\"), Var(\"y\")))\n//│ = \"(x y)\"\n\nshowTerm(App(Abs(Var(\"x\"), Var(\"y\")), Var(\"z\")))\n//│ = \"((λx. y) z)\"\n\nfun (=:=) equalTerm(t1: Term, t2: Term) =\n  if t1 is\n    Var(x1)        and t2 is Var(x2)        then x1 === x2\n    Abs(x1, t1')   and t2 is Abs(x2, t2')   then (x1 =:= x2) && (t1' =:= t2')\n    App(t1', t1'') and t2 is App(t2', t2'') then (t1' =:= t2') && (t1'' =:= t2'')\n    else false\n\nVar(\"x\") =:= Var(\"x\")\nVar(\"x\") =:= Var(\"y\")\nAbs(Var(\"x\"), Var(\"x\")) =:= Abs(Var(\"x\"), Var(\"x\"))\nAbs(Var(\"x\"), Var(\"x\")) =:= Abs(Var(\"x\"), Var(\"y\"))\nAbs(Var(\"x\"), Var(\"y\")) =:= Abs(Var(\"x\"), Var(\"x\"))\n//│ = false\n\nfun isValue(t) =\n  if t is\n    Abs then true\n    Var then false\n    App then false\n\nisValue(Var(\"x\"))\nisValue(Abs(Var(\"x\"), Var(\"y\")))\nisValue(App(Var(\"x\"), Var(\"y\")))\n//│ = false\n\nfun hasFree(t, x) =\n  if t is\n    Var(x') then x === x'\n    Abs(Var(x'), body) and x === x' then false\n    Abs(Var(_), body) then hasFree(body, x)\n    App(lhs, rhs) then hasFree(lhs, x) || hasFree(rhs, x)\n    _ then false\n\nfun showHasFree(t, n) =\n  showTerm(t) + (if hasFree(t, n) then \" has \" else \" DOES NOT have \") + \"free variable \" + n\n\nshowHasFree(Var(\"x\"), \"x\")\n//│ = \"x has free variable x\"\n\nshowHasFree(Var(\"x\"), \"y\")\n//│ = \"x DOES NOT have free variable y\"\n\nshowHasFree(Abs(Var(\"x\"), Var(\"x\")), \"x\")\n//│ = \"λx. x DOES NOT have free variable x\"\n\nshowHasFree(Abs(Var(\"x\"), Var(\"x\")), \"y\")\n//│ = \"λx. x DOES NOT have free variable y\"\n\nshowHasFree(Abs(Var(\"x\"), Var(\"y\")), \"x\")\n//│ = \"λx. y DOES NOT have free variable x\"\n\nshowHasFree(Abs(Var(\"x\"), Var(\"y\")), \"y\")\n//│ = \"λx. y has free variable y\"\n\nshowHasFree(App(Var(\"x\"), Var(\"y\")), \"x\")\n//│ = \"(x y) has free variable x\"\n\nshowHasFree(App(Var(\"x\"), Var(\"y\")), \"y\")\n//│ = \"(x y) has free variable y\"\n\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"x\")\n//│ = \"((λx. x) x) has free variable x\"\n\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"y\")\n//│ = \"((λx. x) x) DOES NOT have free variable y\"\n\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"y\")), \"y\")\n//│ = \"((λx. x) y) has free variable y\"\n\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"y\")\n//│ = \"((λx. x) x) DOES NOT have free variable y\"\n\nfun freeVars(t) =\n  if t is\n    Var(x) then x :: Nil\n    Abs(Var(x), body) then exclude(freeVars(body), x)\n    App(lhs, rhs) then freeVars(lhs) ::: freeVars(rhs)\n\n(freeVars of Var(\"x\")) |> showList\n//│ = \"[x]\"\n\n(freeVars of Abs(Var(\"x\"), Var(\"x\"))) |> showList\n//│ = \"[]\"\n\n(freeVars of Abs(Var(\"x\"), Var(\"y\"))) |> showList\n//│ = \"[y]\"\n\n(freeVars of App(Var(\"x\"), Var(\"y\"))) |> showList\n//│ = \"[x, y]\"\n\n(freeVars of App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\"))) |> showList\n//│ = \"[x]\"\n\n:silent\nlet alphabet = Iter.toStack(\"abcdefghijklmnopqrstuvwxyz\")\n\nshowList of alphabet\n//│ = \"[a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]\"\n\nfun nextVar[T](n: Int, alphabet: Stack[T], used: Stack[Str]): Option[Str] =\n  fun enumerate(n, acc, alphabet) =\n    if n <= 0 then\n      let x = reverse(acc) Iter.fromStack() Iter.joined(\"\")\n      if used contains(x) then None else Some(x)\n    else\n      alphabet Iter.fromStack() Iter.firstDefined of x =>\n        nextVar(n - 1, x :: acc, alphabet)\n  enumerate(n, Nil, alphabet)\n\nlet oneTwoThree = 1 :: 2 :: 3 :: Nil\n//│ oneTwoThree = Cons(1, Cons(2, Cons(3, Nil)))\n\nnextVar(1, oneTwoThree, Nil)\n//│ = Some(\"\")\n\nnextVar(1, oneTwoThree, \"1\" :: \"2\" :: \"3\" :: Nil)\n//│ = Some(\"\")\n\nnextVar(2, oneTwoThree, Nil)\n//│ = Some(\"\")\n\nnextVar(3, oneTwoThree, Nil)\n//│ = Some(\"\")\n\nnextVar(1, oneTwoThree, \"1\" :: \"3\" :: Nil)\n//│ = Some(\"\")\n\nnextVar(2, oneTwoThree, \"11\" :: \"12\" :: \"13\" :: Nil)\n//│ = Some(\"\")\n\nnextVar(3, oneTwoThree, \"111\" :: \"112\" :: \"113\" :: \"121\" :: Nil)\n//│ = Some(\"\")\n\n\nfun freshVar(t: Term): Str =\n  let fvs = freeVars(t)\n  fun aux(n: Int): Str =\n    if nextVar(n, alphabet, fvs) is\n      Some(x) then x\n      None then aux(n + 1)\n  aux(1)\n\nfreshVar(Var(\"x\"))\n//│ = \"\"\n\nfreshVar(App(Var(\"a\"), Var(\"b\")))\n//│ = \"\"\n\nfreshVar(App(Abs(Var(\"a\"), Var(\"a\")), Var(\"b\")))\n//│ = \"\"\n\nfun subst(t: Term, x: Str, v: Term): Term =\n  if t is\n    Var(y) and x === y then v\n    Abs(Var(y), t') and x !== y and\n      hasFree(v, y) then\n        let y' = freshVar(t')\n        let t'' = subst(t', y, Var(y'))\n        Abs(Var(y'), subst(t'', x, v))\n      else\n        Abs(Var(y), subst(t', x, v))\n    App(lhs, rhs) then App(subst(lhs, x, v), subst(rhs, x, v))\n    else t\n\nfun showSubst(t, n, v) =\n  showTerm(t) + \" [\" + n + \" / \" + showTerm(v) + \"]\" + \" = \" + showTerm(subst(t, n, v))\n\nshowSubst(Var(\"x\"), \"x\", Var(\"y\"))\n//│ = \"x [x / y] = y\"\n\nshowSubst(Abs(Var(\"x\"), Var(\"x\")), \"x\", Var(\"z\"))\n//│ = \"λx. x [x / z] = λx. x\"\n\nshowSubst(App(Var(\"x\"), Var(\"y\")), \"x\", Abs(Var(\"x\"), Var(\"x\")))\n//│ = \"(x y) [x / λx. x] = ((λx. x) y)\"\n\nshowSubst(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"x\", Abs(Var(\"y\"), Var(\"y\")))\n//│ = \"((λx. x) x) [x / λy. y] = ((λx. x) λy. y)\"\n\nshowSubst(Abs(Var(\"x\"), App(Var(\"x\"), Var(\"y\"))), \"y\", Var(\"x\"))\n//│ = \"λx. (x y) [y / x] = λ. ( x)\"\n\nshowSubst(Abs(Var(\"z\"), Abs(Var(\"x\"), App(Var(\"z\"), App(Var(\"x\"), Var(\"y\"))))), \"y\", Var(\"x\"))\n//│ = \"λz. λx. (z (x y)) [y / x] = λz. λ. (z ( x))\"\n\nshowSubst(Abs(Var(\"z\"), Abs(Var(\"x\"), App(Var(\"z\"), App(Var(\"x\"), Var(\"y\"))))), \"y\", App(Var(\"x\"), Var(\"z\")))\n//│ = \"λz. λx. (z (x y)) [y / (x z)] = λ. λ. ( ( (x z)))\"\n\n//  ____                     _  _   ____   _\n// / ___|  _ __ ___    __ _ | || | / ___| | |_  ___  _ __\n// \\___ \\ | '_ ` _ \\  / _` || || | \\___ \\ | __|/ _ \\| '_ \\\n//  ___) || | | | | || (_| || || |  ___) || |_|  __/| |_) |\n// |____/ |_| |_| |_| \\__,_||_||_| |____/  \\__|\\___|| .__/\n//                                                  |_|\n\ntype Result = Normal | Stuck | Stepped\ndata class Normal(term: Term) with\n  fun toString() = \"Normal form: \" + showTerm(term)\ndata class Stuck(term: Term, part: Term) with\n  fun toString() = \"Stuck: \" + showTerm(part) + \" in \" + showTerm(term)\ndata class Stepped(from: Term, to: Term) with\n  fun toString() = showTerm(from) + \" => \" + showTerm(to)\n\n\nfun stepByValue(t) =\n  if t is\n    Var then Stuck(t, t)\n    Abs then Normal(t)\n    App(lhs, rhs) and stepByValue(lhs) is\n      Stepped(_, lhs) then Stepped(t, App(lhs, rhs))\n      Stuck(_, part) then Stuck(t, part)\n      Normal and stepByValue(rhs) is\n        Stepped(_, rhs) then Stepped(t, App(lhs, rhs))\n        Stuck(_, part) then Stuck(t, part)\n        Normal and lhs is\n          Abs(Var(name), body) then Stepped(t, subst(body, name, rhs))\n          _ then Stuck(t, lhs)\n\nString of stepByValue of Var(\"x\")\n//│ = \"Stuck: x in x\"\n\nString of stepByValue of Abs(Var(\"x\"), Var(\"y\"))\n//│ = \"Normal form: λx. y\"\n\nString of stepByValue of App(Var(\"x\"), Var(\"y\"))\n//│ = \"Stuck: x in (x y)\"\n\nString of stepByValue of App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\"))\n//│ = \"Stuck: x in ((λx. x) x)\"\n\nString of stepByValue of App(Abs(Var(\"x\"), Var(\"x\")), Abs(Var(\"y\"), Var(\"y\")))\n//│ = \"((λx. x) λy. y) => λy. y\"\n\n//  _____               _                _    _\n// | ____|__   __ __ _ | | _   _   __ _ | |_ (_)  ___   _ __\n// |  _|  \\ \\ / // _` || || | | | / _` || __|| | / _ \\ | '_ \\\n// | |___  \\ V /| (_| || || |_| || (_| || |_ | || (_) || | | |\n// |_____|  \\_/  \\__,_||_| \\__,_| \\__,_| \\__||_| \\___/ |_| |_|\n//\n\nfun eval(step) =\n  fun aux(t) =\n    if step(t) is result and result is\n      Stepped(_, t') then aux(t')\n      else result\n  aux\n\nlet evalByValue = eval(stepByValue)\n//│ evalByValue = fun aux\n\n// Let's program with Church encoding!\n\nlet zero = Abs(Var(\"f\"), Abs(Var(\"x\"), Var(\"x\")))\n//│ zero = Abs(Var(\"f\"), Abs(Var(\"x\"), Var(\"x\")))\n\nlet one = Abs(Var(\"f\"), Abs(Var(\"x\"), App(Var(\"f\"), Var(\"x\"))))\n//│ one = Abs(Var(\"f\"), Abs(Var(\"x\"), App(Var(\"f\"), Var(\"x\"))))\n\nString of stepByValue of zero\n//│ = \"Normal form: λf. λx. x\"\n\nString of stepByValue of one\n//│ = \"Normal form: λf. λx. (f x)\"\n\nlet succ = Abs(Var(\"n\"), Abs(Var(\"f\"), Abs(Var(\"x\"), App(Var(\"f\"), App(App(Var(\"n\"), Var(\"f\")), Var(\"x\"))))))\n//│ succ = Abs(\n//│   Var(\"n\"),\n//│   Abs(\n//│     Var(\"f\"),\n//│     Abs(Var(\"x\"), App(Var(\"f\"), App(App(Var(\"n\"), Var(\"f\")), Var(\"x\"))))\n//│   )\n//│ )\n\nString of stepByValue of succ\n//│ = \"Normal form: λn. λf. λx. (f ((n f) x))\"\n\nString of stepByValue of App(succ, zero)\n//│ = \"((λn. λf. λx. (f ((n f) x))) λf. λx. x) => λf. λx. (f (((λf. λx. x) f) x))\"\n\nString of evalByValue of App(succ, App(succ, zero))\n//│ = \"Normal form: λf. λx. (f (((λf. λx. (f (((λf. λx. x) f) x))) f) x))\"\n\nString of evalByValue of App(succ, App(succ, App(succ, App(succ, zero))))\n//│ = \"Normal form: λf. λx. (f (((λf. λx. (f (((λf. λx. (f (((λf. λx. (f (((λf. λx. x) f) x))) f) x))) f) x))) f) x))\"\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/future/AppSplits.mls",
    "content": ":js\n\n// AppSplits.mls\n// =============\n// Experimenting with conditional splits on function applications.\n\nfun foo(x) = x > 1\n\n:todo\n:e\nif foo of\n  0 then \"a\"\n  1 then \"b\"\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (application)\n//│ ║  l.11: \tif foo of\n//│ ║        \t   ^^^^^^\n//│ ║  l.12: \t  0 then \"a\"\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.13: \t  1 then \"b\"\n//│ ╙──      \t^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:todo\n:e\n:re\nif foo of 1,\n  0 then \"a\"\n  1 then \"b\"\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (application)\n//│ ║  l.26: \tif foo of 1,\n//│ ║        \t   ^^^^^^^^^\n//│ ║  l.27: \t  0 then \"a\"\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.28: \t  1 then \"b\"\n//│ ╙──      \t^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:todo\n:e\n:re\nif foo\n  (0) then \"a\"\n  (1) then \"b\"\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (juxtaposition)\n//│ ║  l.41: \tif foo\n//│ ║        \t   ^^^\n//│ ║  l.42: \t  (0) then \"a\"\n//│ ╙──      \t^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/future/Or.mls",
    "content": ":js\n\ndata class Some[T](value: T)\n\n\n:fixme // TODO\n// TODO support `or` in UCS\nfun f(a, b) = if a is\n  Some(v)\n    and b is Some(v') then v + v'\n    or  b is Some(v)  then v\n  else 0\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.10: \t    and b is Some(v') then v + v'\n//│ ║        \t                           ^^^^^^\n//│ ║  l.11: \t    or  b is Some(v)  then v\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/future/SymbolicClass.mls",
    "content": ":js\n\n// :de\n// type List = Nil | Cons\n\n:ctx\ntype List = Nil | Cons\nobject Nil\ndata class (::) Cons(head: Int, tail: List)\n//│ Env:\n//│   :: -> RefElem(member:Cons)\n//│   Cons -> RefElem(member:Cons)\n//│   List -> RefElem(member:List)\n//│   Nil -> RefElem(member:Nil)\n\nCons(1, Nil)\n//│ = Cons(1, Nil)\n\n1 :: 2\n//│ = Cons(1, 2)\n\nfun map(f, xs) = if xs is\n  Nil then Nil\n  x :: xs' then f(x) :: map(f, xs')\n\n\n// TODO?\n:e\n:re\n:sjs\nnew 1 :: 2\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found integer literal.\n//│ ║  l.31: \tnew 1 :: 2\n//│ ║        \t    ^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp; tmp = globalThis.Object.freeze(new 1()); Cons1(tmp, 2)\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: 1 is not a constructor\n\n// TODO?\n:e\n:re\n:sjs\nnew (1 :: 2)\n//│ ╔══[COMPILATION ERROR] Expected a statically known class; found application of type Cons.\n//│ ║  l.45: \tnew (1 :: 2)\n//│ ║        \t     ^^^^^^\n//│ ╙── The 'new' keyword requires a statically known class; use the 'new!' operator for dynamic instantiation.\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp1; tmp1 = Cons1(1, 2); globalThis.Object.freeze(new tmp1())\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] TypeError: tmp1 is not a constructor\n\nnew ::(1, 2)\n//│ = Cons(1, 2)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/BooleanPatterns.mls",
    "content": ":js\n\n\n// * It's neat how the complicated pattern matching logic is desugared into a simple `switch`\n:sjs\nfun test(x) = if x is\n  0 then \"0\"\n  ~2 & ~3 then \"not 2 and not 3\"\n  ~3 then \"not 3\"\n  _ then \"other\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let test;\n//│ test = function test(x) {\n//│   switch (x) {\n//│     case 0:\n//│       return \"0\";\n//│     case 2:\n//│       return \"not 3\";\n//│     case 3:\n//│       return \"other\";\n//│   }\n//│   return \"not 2 and not 3\"\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\ntest(0)\n//│ = \"0\"\ntest(1)\n//│ = \"not 2 and not 3\"\ntest(2)\n//│ = \"not 3\"\ntest(3)\n//│ = \"other\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/CardSuits.mls",
    "content": ":js\n\ndata class Card[T](color: T)\n\nclass Suit\nobject Heart extends Suit\nobject Diamond extends Suit\nobject Spade extends Suit\nobject Club extends Suit\n\nfun suit(x) = if x is Card(a) then a\n\nlet card = Card(Heart)\n//│ card = Card(Heart)\n\nsuit of card\n//│ = Heart\n\n// :ucs desugared normalized\nfun foo(x) = if x is\n  Card(Heart) then 0\n  Card(Diamond) then 1\n  Card(Spade) then 2\n  Card(Club) then 3\n  else 4\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/CrossModules.mls",
    "content": ":js\n\n\n// https://github.com/hkust-taco/mlscript/issues/151#issuecomment-3235677951\n\nmodule BaseLib0 with\n  class Foo(val x)\n\nmodule DerivedLib1 with\n  val BaseLib: module BaseLib0 = BaseLib0\n  fun testFoo = case\n    BaseLib.Foo then 1\n    _ then 0\n\nDerivedLib1.testFoo(new DerivedLib1.BaseLib.Foo(123))\n//│ = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/DualOptions.mls",
    "content": ":js\n\n// DualOptions.mls\n// ===============\n// Matching two options in any possible order.\n\n\nabstract class Option[T]\ndata class Some[T](value: T) extends Option[T]\nobject None extends Option[Nothing]\ndata class Pair[A, B](x: A, y: B)\n\n// All `add_n` functions should be inferred to have the same type.\n\nfun add_1(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n\nadd_1(None, None)\n//│ = 0\n\nadd_1(Some(5), None)\n//│ = 5\n\nadd_1(None, Some(9))\n//│ = 9\n\nadd_1(Some(5), Some(9))\n//│ = 14\n\nfun add_2(x, y) =\n  if x is\n    Some(xv) and y is\n      Some(yv) then xv + yv\n      None     then xv\n    None and y is\n      Some(yv) then yv\n      None     then 0\n\nadd_2(None, None)\n//│ = 0\n\nadd_2(Some(5), None)\n//│ = 5\n\nadd_2(None, Some(9))\n//│ = 9\n\nadd_2(Some(5), Some(9))\n//│ = 14\n\n\nfun add_3(x, y) =\n  if Pair(x, y) is\n    Pair(Some(xv), Some(yv)) then xv + yv\n    Pair(Some(xv), None)     then xv\n    Pair(None,     Some(yv)) then yv\n    Pair(None,     None)     then 0\n\nadd_3(None, None)\n//│ = 0\n\nadd_3(Some(5), None)\n//│ = 5\n\nadd_3(None, Some(9))\n//│ = 9\n\nadd_3(Some(5), Some(9))\n//│ = 14\n\n\nfun add_4(x, y) =\n  if\n    x\n      is\n        Some(xv) and\n          y\n            is\n              Some(yv) then xv + yv\n            is\n              None     then xv\n        None and\n          y\n            is\n              Some(yv) then yv\n            is\n              None     then 0\n\n\nadd_4(None, None)\n//│ = 0\n\nadd_4(Some(5), None)\n//│ = 5\n\nadd_4(None, Some(9))\n//│ = 9\n\nadd_4(Some(5), Some(9))\n//│ = 14\n\n\nfun add_5(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    y is None     and x is Some(xv) then xv\n    x is None     and y is Some(yv) then yv\n    y is None     and x is None     then 0\n\n\nadd_5(None, None)\n//│ = 0\n\nadd_5(Some(5), None)\n//│ = 5\n\nadd_5(None, Some(9))\n//│ = 9\n\nadd_5(Some(5), Some(9))\n//│ = 14\n\n\nfun add_6(x, y) =\n  if [x, y] is\n    [Some(xv), Some(yv)] then xv + yv\n    [Some(xv), None]     then xv\n    [None,     Some(yv)] then yv\n    [None,     None]     then 0\n\nadd_6(None, None)\n//│ = 0\n\nadd_6(Some(5), None)\n//│ = 5\n\nadd_6(None, Some(9))\n//│ = 9\n\nadd_6(Some(5), Some(9))\n//│ = 14\n\n\n// Functions from now on have a predicate `p` that can be used to add some preconditions.\n\n\nfun add_6(p, x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    y is None     and p(x) and x is Some(xv) then 42\n    y is None     and x is Some(xv) then xv\n    x is None     and y is Some(yv) then yv\n    y is None     and x is None     then 0\n\n\n:expect 0\nadd_6((x) => true, None, None)\n//│ = 0\n\n:expect 42\nadd_6((x) => true, Some(5), None)\n//│ = 42\n\n:expect 5\nadd_6((x) => false, Some(5), None)\n//│ = 5\n\n:expect 9\nadd_6((x) => true, None, Some(9))\n//│ = 9\n\n:expect 14\nadd_6((x) => true, Some(5), Some(9))\n//│ = 14\n\n\nfun add_7(p, x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    // y is None    and p(x) and x is Some(xv) then 42\n    y is None     and x is Some(xv) then xv\n    y is Some(yv) and p(yv) and x is None then 36\n    y is Some(yv) and x is None then yv\n    y is None     and x is None     then 0\n\n\n:expect 0\nadd_7((x) => x > 0, None, None)\n//│ = 0\n\n:expect 5\nadd_7((x) => x > 0, Some(5), None)\n//│ = 5\n\n:expect 36\nadd_7((x) => x > 0, None, Some(9))\n//│ = 36\n\n:expect -9\nadd_7((x) => x > 0, None, Some(-9))\n//│ = -9\n\n:expect 14\nadd_7((x) => x > 0, Some(5), Some(9))\n//│ = 14\n\n\nfun add_8(p, x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    y is None    and p(x) and x is Some(xv) then 42\n    y is None     and x is Some(xv) then xv\n    y is Some(yv) and p(yv) and x is None then 36\n    y is Some(yv) and x is None then yv\n    y is None     and x is None     then 0\n\n\n:expect 0\nadd_8((x) => x > 0, None, None)\n//│ = 0\n\n:expect 42\nadd_8((x) => true, Some(9), None)\n//│ = 42\n\n:expect 5\nadd_8((x) => x > 0, Some(5), None)\n//│ = 5\n\n:expect 36\nadd_8((x) => x > 0, None, Some(9))\n//│ = 36\n\n:expect -9\nadd_8((x) => x > 0, None, Some(-9))\n//│ = -9\n\n:expect 14\nadd_8((x) => x > 0, Some(5), Some(9))\n//│ = 14\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/InterleavedLet.mls",
    "content": ":js\n\nabstract class List[out T]\ndata class Cons[out T](head: T, tail: List[T]) extends List[T]\nobject Nil extends List[Nothing]\n\n\nfun map(f, xs) = if xs is\n  Nil then Nil\n  let xs' = map(f, xs)\n  Cons(x, xs) then Cons(f(x), xs')\n\n\nobject Bot\n\n\nabstract class Option[T]\ndata class Some[T](value: T) extends Option[T]\nobject None extends Option[Nothing]\n\n\nfun normalize(tp) = ()\nfun glb(tp1, tp2) = ()\n\n\n// TODO: `as` keyword \nfun merge(tp1, tp2) = if\n  let tp1_n = normalize(tp1)\n  tp1_n is Bot then Bot\n  let tp2_n = normalize(tp2)\n  tp2_n is Bot then Bot\n  let m = merge(tp1_n, tp2_n)\n  m is Some(tp) then tp\n  m is None     then glb(tp1_n, tp2_n)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/JoinPoints.mls",
    "content": ":js\n\n\n// * Note: no join point needed\n:sjs\nx => if x is 0 then 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda;\n//│ lambda = (undefined, function (x) {\n//│   if (x === 0) {\n//│     return 1\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n// * Note: join point needed\n:sjs\nx => if x is [[0]] then 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda1;\n//│ lambda1 = (undefined, function (x) {\n//│   let element0$, element0$1;\n//│   if (runtime.Tuple.isArrayLike(x) && x.length === 1) {\n//│     element0$ = runtime.Tuple.get(x, 0);\n//│     if (runtime.Tuple.isArrayLike(element0$) && element0$.length === 1) {\n//│       element0$1 = runtime.Tuple.get(element0$, 0);\n//│       if (element0$1 === 0) {\n//│         return 1\n//│       }\n//│       throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ lambda1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\ndata class S(value)\n\n// * Note: the computation in the default branch should not be duplicated.\n:sjs\nfun crazy(v) =\n  if v is\n    S(S(S(S(S(S(0)))))) then \"bruh!\"\n    _ then S(S(S(S(S(S(0))))))\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let crazy;\n//│ crazy = function crazy(v) {\n//│   let arg$S$0$, arg$S$0$1, arg$S$0$2, arg$S$0$3, arg$S$0$4, arg$S$0$5, tmp, tmp1, tmp2, tmp3, tmp4;\n//│   if (v instanceof S1.class) {\n//│     arg$S$0$ = v.value;\n//│     if (arg$S$0$ instanceof S1.class) {\n//│       arg$S$0$1 = arg$S$0$.value;\n//│       if (arg$S$0$1 instanceof S1.class) {\n//│         arg$S$0$2 = arg$S$0$1.value;\n//│         if (arg$S$0$2 instanceof S1.class) {\n//│           arg$S$0$3 = arg$S$0$2.value;\n//│           if (arg$S$0$3 instanceof S1.class) {\n//│             arg$S$0$4 = arg$S$0$3.value;\n//│             if (arg$S$0$4 instanceof S1.class) {\n//│               arg$S$0$5 = arg$S$0$4.value;\n//│               if (arg$S$0$5 === 0) {\n//│                 return \"bruh!\"\n//│               }\n//│             }\n//│           }\n//│         }\n//│       }\n//│     }\n//│   }\n//│   tmp = S1(0);\n//│   tmp1 = S1(tmp);\n//│   tmp2 = S1(tmp1);\n//│   tmp3 = S1(tmp2);\n//│   tmp4 = S1(tmp3);\n//│   return S1(tmp4)\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/List.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Stack\nopen Option { Some, None }\n\n\nfun length(xs) = if xs is\n  Nil then 0\n  Cons(_, xs) then 1 + length(xs)\n\nlength of Nil\n//│ = 0\n\nlength of 1 :: 2 :: Nil\n//│ = 2\n\n:re\nlength of ()\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\nfun map(f, xs) = if xs is\n  Nil then Nil\n  Cons(x, xs) then Cons(f(x), map(f, xs))\n\n\nfun findFirst(f, xs) =\n  if xs is\n    Nil then None\n    Cons(x, _) and f(x) then Some(x)\n    Cons(_, xs) then findFirst(f, xs)\n\nfindFirst of _ > 2, Nil\n//│ = None\n\nfindFirst of _ > 2, 1 :: 2 :: 3 :: 4 :: Nil\n//│ = Some(3)\n\nfindFirst of _ > 2, 1 :: 2 :: 4 :: 3 :: Nil\n//│ = Some(4)\n\n\nfun findFirst(f, xs) =\n  if xs is\n    Nil then None\n    Cons(x, _) and\n      f(x) then Some(x)\n    Cons(_, xs) then findFirst(f, xs)\n\nfindFirst of _ > 2, Nil\n//│ = None\n\nfindFirst of _ > 2, 1 :: 2 :: 3 :: 4 :: Nil\n//│ = Some(3)\n\nfindFirst of _ > 2, 1 :: 2 :: 4 :: 3 :: Nil\n//│ = Some(4)\n\n\nfun findFirst(f, xs) =\n  if\n    xs is\n      Nil then None\n      Cons(x, _) and\n        f(x) then Some(x)\n      Cons(_, xs) then findFirst(f, xs)\n\nfindFirst of _ > 2, Nil\n//│ = None\n\nfindFirst of _ > 2, 1 :: 2 :: 3 :: 4 :: Nil\n//│ = Some(3)\n\nfindFirst of _ > 2, 1 :: 2 :: 4 :: 3 :: Nil\n//│ = Some(4)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/LogicalConnectives.mls",
    "content": ":js\n\n\n:fixme\ntrue or true\n//│ ╔══[COMPILATION ERROR] Logical `or` is not yet supported.\n//│ ║  l.5: \ttrue or true\n//│ ╙──     \t^^^^^^^^^^^^\n//│ = true\n\n:fixme\nwhile false or false do print(\"ok\")\n//│ ╔══[COMPILATION ERROR] Logical `or` is not yet supported.\n//│ ║  l.12: \twhile false or false do print(\"ok\")\n//│ ╙──      \t      ^^^^^^^^^^^^^^\n\n\nfun test(x) =\n  print(x)\n  x\n\n123 and test(42)\n//│ = false\n\n:sjs\ntrue and test(42)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut4, scrut5;\n//│ scrut4 = true;\n//│ if (scrut4 === true) {\n//│   scrut5 = test(42);\n//│   if (scrut5 === true) { true } else { false }\n//│ } else { false }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 42\n//│ = false\n\n:fixme\ntrue or test(42)\n//│ ╔══[COMPILATION ERROR] Logical `or` is not yet supported.\n//│ ║  l.39: \ttrue or test(42)\n//│ ╙──      \t^^^^^^^^^^^^^^^^\n//│ > 42\n//│ = false\n\ntrue and test(true)\n//│ > true\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/Seqs.mls",
    "content": ":js\n\n\nassert [\"\"] is [..stack, Str as id], [stack, id]\n//│ = [[], \"\"]\n\nassert [..[], \"\"] is [..stack, Str as id], [stack, id]\n//│ = [[], \"\"]\n\nassert [..[..[\"\"]], \"\"] is [..stack, Str as id], [stack, id]\n//│ = [[], \"\"]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/general/Simple.mls",
    "content": ":js\n\n// Simple.mls\n// ==========\n// Simple and single-line UCS expressions.\n\n\ndata class Box[T](value: T)\ndata class Bottle[T](value: T)\n\n\nfun foo(x) = if x is Box(y) then y\n\n\nfun foo(x) = if x is\n  Box(y) then y\n  Bottle(y) then y\n\n\nfun foo(x, y) = if x is Box(xv) and y is Bottle(yv) then xv + yv\n\n\nfun foo(x, y, z) = if x is Box(xv) and y is Box(yv) and z is Box(zv) then xv + yv + zv\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/hygiene/CrossBranchCapture.mls",
    "content": ":js\n\ndata class Numb(n: Int)\n\n:e\nfun process(e) =\n  if e is\n    Numb(n) and n > 0 then n\n    Numb(m) then n\n//│ ╔══[COMPILATION ERROR] Name not found: n\n//│ ║  l.9: \t    Numb(m) then n\n//│ ╙──     \t                 ^\n\n\n:re\nprocess(Numb(-10))\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nfun process(e, n) =\n  if e is\n    Numb(n) and n > 0 then n\n    Numb(m) then n + m\n\nprocess(Numb(0), 10)\nprocess(Numb(-1), 10)\nprocess(Numb(1), 10)\n//│ = 1\n\n\n// class Vec(xs: Array[Numb | Vec]) // Array is not available\ndata abstract class Vec[out T](n: Int)\ndata class Cons[out T](head: T, tail: Vec[T]) extends Vec[T]\nobject Nil extends Vec[Nothing]\n\ndata class Pair[A, B](a: A, b: B)\n\n:e\nfun process(e) =\n  if e is\n    Pair(Numb(n), Numb(m)) then Numb(n + m)\n    Pair(Vec(xs), Vec(ys)) then n\n    Pair(Vec(n),  Numb(n)) then n\n    Pair(Numb(n), Vec(n))  then n\n//│ ╔══[COMPILATION ERROR] Name not found: n\n//│ ║  l.41: \t    Pair(Vec(xs), Vec(ys)) then n\n//│ ╙──      \t                                ^\n//│ ╔══[COMPILATION ERROR] Duplicated pattern variable.\n//│ ║  l.42: \t    Pair(Vec(n),  Numb(n)) then n\n//│ ║        \t                       ^\n//│ ╟── The previous definition is as follows.\n//│ ║  l.42: \t    Pair(Vec(n),  Numb(n)) then n\n//│ ╙──      \t             ^\n//│ ╔══[COMPILATION ERROR] Duplicated pattern variable.\n//│ ║  l.43: \t    Pair(Numb(n), Vec(n))  then n\n//│ ║        \t                      ^\n//│ ╟── The previous definition is as follows.\n//│ ║  l.43: \t    Pair(Numb(n), Vec(n))  then n\n//│ ╙──      \t              ^\n\n\n// * TODO: we might want to accept this and compare the two values for equality\n:e\nfun process(e) =\n  if e is\n    Pair(Numb(n), Numb(n)) then n\n//│ ╔══[COMPILATION ERROR] Duplicated pattern variable.\n//│ ║  l.65: \t    Pair(Numb(n), Numb(n)) then n\n//│ ║        \t                       ^\n//│ ╟── The previous definition is as follows.\n//│ ║  l.65: \t    Pair(Numb(n), Numb(n)) then n\n//│ ╙──      \t              ^\n\nprocess(Pair(Numb(1), Numb(2)))\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/hygiene/Hygiene.mls",
    "content": ":js\n\n\ndata class Left[out T](value: T)\ndata class Some[out T](value: T)\ndata class Right[out T](value: T)\n\n\nfun foo(x) = if x is\n  Some(Left(y)) then x\n  Some(x) then x\n\n:expect Some(Left(1))\nfoo(Some(Left(1)))\n//│ = Some(Left(1))\n\n:expect 2\nfoo(Some(2))\n//│ = 2\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/hygiene/HygienicBindings.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\nfun (~~>) expect(a, b) = if a == b then () else throw Error(\"unexpected result\")\n\ntype Either[A, B] = Left[A] | Right[B]\ndata class Left[A](val leftValue: A)\ndata class Right[B](val rightValue: B)\n\nfun justTrue(_) = true\nfun justFalse(_) = false\n\nfun h0(a) =\n  if\n    a is Some(Left(y)) then y\n    a is Some(Right(z)) then z\n    a is None then 0\n\n// If a class parameter is bound to the same variable in different branches,\n// the bindings can be merged and can be typed and coverage checked. See the\n// desugared version below.\n// :ducs:postprocess.result\nfun h0'(a) =\n  if\n    a is Some(x) and x is Left(y) then y\n    a is Some(x) and x is Right(z) then z\n    a is None then 0\n\n:ucs normalized\n// If a class parameter is bound to different variables in different\n// branches, the bindings with the same name in different branches should not\n// interfere with each other, and normalization should be able to factorize.\nfun h1(a) =\n  if\n    a is Some(x) and x is Left(y) then y\n    a is Some(y) and y is Right(z) then z\n    a is None then 0\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    a is Option.Some(arg$Some$0$) and\n//│ >      let x = tmp:arg$Some$0$⁰\n//│ >      x is Left(arg$Left$0$) and\n//│ >        let y = tmp:arg$Left$0$⁰\n//│ >        else y⁰\n//│ >      let y = tmp:arg$Some$0$⁰\n//│ >      y is Right(arg$Right$0$) and\n//│ >        let z = tmp:arg$Right$0$⁰\n//│ >        else z⁰\n//│ >    a is Option.None then 0\n\nh1(Some(Left(42)))\n//│ = 42\n\nh1(Some(Right(8)))\n//│ = 8\n\nh1(None)\n//│ = 0\n\n:ucs normalized\n// But it is difficult to merge bindings of different variables if one\n// of them is bound via a let binding. Maybe this can be left for future work.\nfun h2(a) =\n  if\n    a is Some(x) and x is x' and x' is Left(y) then y\n    a is Some(y) and\n      let y' = y\n      y' is Right(z) then z\n    a is None then 0\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    a is Option.Some(arg$Some$0$) and\n//│ >      let x = tmp:arg$Some$0$¹\n//│ >      let x' = x⁰\n//│ >      x' is Left(arg$Left$0$) and\n//│ >        let y = tmp:arg$Left$0$¹\n//│ >        else y¹\n//│ >      let y = tmp:arg$Some$0$¹\n//│ >      let y' = y²\n//│ >      y' is Right(arg$Right$0$) and\n//│ >        let z = tmp:arg$Right$0$¹\n//│ >        else z¹\n//│ >    a is Option.None then 0\n\n// :w\nfun h3(x, y, f, p) =\n  if x is\n    _ and f(x) is y and p(x) then y\n    None then y\n    _ then \"anyway\"\n\n\nh3(\"anything\", \"not me\", _ => \"should be me\", _ => true) ~~> \"should be me\"\n\nh3(None, \"should be me\", _ => \"not me\", _ => false) ~~> \"should be me\"\n\nh3(\"anything\", \"anything\", _ => \"not me\", _ => false) ~~> \"anyway\"\n\n\n// :ducs:postprocess.result\n// :w\nfun h4(x, y, p) =\n  if x is\n    y and p(x) then y\n    None then y\n    _ then \"default\"\n\n:expect \"should be me\"\nh4(\"should be me\", \"not me\", justTrue)\n//│ = \"should be me\"\n\n:expect None\nh4(None, \"not me\", justTrue)\n//│ = None\n\n:expect \"should be me\"\nh4(None, \"should be me\", justFalse)\n//│ = \"should be me\"\n\n:expect \"default\"\nh4(\"anything\", \"not me\", justFalse)\n//│ = \"default\"\n\n// :ducs:postprocess.result\nfun h5(x, y, p) =\n  if x is\n    Some(y) and p(x) then y\n    None then y\n    _ then y\n\nh5(Some(1), 2, justTrue) ~~> 1\n\nh5(Some(1), 2, justFalse) ~~> 2\n\nh5(None, 0, justTrue) ~~> 0\n\nh5(None, 0, justFalse) ~~> 0\n\nh5(\"foo\", 42, justTrue) ~~> 42\n\nh5(\"foo\", 42, justFalse) ~~> 42\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/hygiene/PatVars.mls",
    "content": ":js\n\n\nclass x\nif 0 is\n  x then 12\n//│ = 12\n\n\n:re\nclass X\nif 0 is\n  X then 12\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/Deduplication.mls",
    "content": ":js\n:patMatConsequentSharingThreshold 5\n\nlet x = 0\nlet y = 0\nlet z = 0\n//│ x = 0\n//│ y = 0\n//│ z = 0\n\n:sjs\nif x === 0 then 1 else 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut; scrut = x === 0; if (scrut === true) { 1 } else { 2 }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n:sjs\nlet a = if x === 0 then 1 else 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let a, scrut1, tmp; scrut1 = x === 0; if (scrut1 === true) { tmp = 1; } else { tmp = 2; } a = tmp;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ a = 1\n\n:sjs\nprint of if x === 0 then 1 else 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let scrut2, tmp1;\n//│ scrut2 = x === 0;\n//│ if (scrut2 === true) { tmp1 = 1; Predef.print(tmp1) } else { tmp1 = 2; Predef.print(tmp1) }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 1\n\n:sjs\nif x is\n  0 and y is\n    0 and z is\n      0 then \"000\"\n      1 then \"001\"\n    1 then \"01\"\n  1 then \"1\"\n  else \"\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ switch (x) {\n//│   case 0:\n//│     switch (y) {\n//│       case 0:\n//│         switch (z) {\n//│           case 0:\n//│             \"000\";\n//│             break;\n//│           case 1:\n//│             \"001\";\n//│             break;\n//│           default:\n//│             \"\";\n//│         }\n//│         break;\n//│       case 1:\n//│         \"01\";\n//│         break;\n//│       default:\n//│         \"\";\n//│     }\n//│     break;\n//│   case 1:\n//│     \"1\";\n//│     break;\n//│   default:\n//│     \"\";\n//│ }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"000\"\n\n// * Making the terms artificially big to force sharing of consequents\n:sjs\nif x is\n  0 and y is\n    0 and z is\n      0 then \"000-------------------------------------------------------------------------\"\n      1 then \"001-------------------------------------------------------------------------\"\n    1 then \"01-------------------------------------------------------------------------\"\n  1 then \"1-------------------------------------------------------------------------\"\n  else \"-------------------------------------------------------------------------\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp2;\n//│ split_root$: {\n//│   switch (x) {\n//│     case 0:\n//│       switch (y) {\n//│         case 0:\n//│           switch (z) {\n//│             case 0:\n//│               tmp2 = \"000-------------------------------------------------------------------------\";\n//│               break split_root$;\n//│             case 1:\n//│               tmp2 = \"001-------------------------------------------------------------------------\";\n//│               break split_root$;\n//│           }\n//│           break;\n//│         case 1:\n//│           tmp2 = \"01-------------------------------------------------------------------------\";\n//│           break split_root$;\n//│       }\n//│       break;\n//│     case 1:\n//│       tmp2 = \"1-------------------------------------------------------------------------\";\n//│       break split_root$;\n//│   }\n//│   tmp2 = \"-------------------------------------------------------------------------\";\n//│ }\n//│ tmp2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = \"000-------------------------------------------------------------------------\"\n\n:sjs\nlet qqq = if x is\n  0 and y is\n    0 and z is\n      0 then \"000-------------------------------------------------------------------------\"\n      1 then \"001-------------------------------------------------------------------------\"\n    1 then \"01-------------------------------------------------------------------------\"\n  1 then \"1-------------------------------------------------------------------------\"\n  else \"-------------------------------------------------------------------------\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let qqq, tmp3;\n//│ split_root$1: {\n//│   switch (x) {\n//│     case 0:\n//│       switch (y) {\n//│         case 0:\n//│           switch (z) {\n//│             case 0:\n//│               tmp3 = \"000-------------------------------------------------------------------------\";\n//│               break split_root$1;\n//│             case 1:\n//│               tmp3 = \"001-------------------------------------------------------------------------\";\n//│               break split_root$1;\n//│           }\n//│           break;\n//│         case 1:\n//│           tmp3 = \"01-------------------------------------------------------------------------\";\n//│           break split_root$1;\n//│       }\n//│       break;\n//│     case 1:\n//│       tmp3 = \"1-------------------------------------------------------------------------\";\n//│       break split_root$1;\n//│   }\n//│   tmp3 = \"-------------------------------------------------------------------------\";\n//│ }\n//│ qqq = tmp3;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ qqq = \"000-------------------------------------------------------------------------\"\n\n:sjs\nprint of if x is\n  0 and y is\n    0 and z is\n      0 then \"000\"\n      1 then \"001\"\n    1 then \"01\"\n  1 then \"1\"\n  else \"\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp4;\n//│ switch (x) {\n//│   case 0:\n//│     switch (y) {\n//│       case 0:\n//│         switch (z) {\n//│           case 0:\n//│             tmp4 = \"000\";\n//│             break;\n//│           case 1:\n//│             tmp4 = \"001\";\n//│             break;\n//│           default:\n//│             tmp4 = \"\";\n//│         }\n//│         Predef.print(tmp4);\n//│         break;\n//│       case 1:\n//│         tmp4 = \"01\";\n//│         Predef.print(tmp4);\n//│         break;\n//│       default:\n//│         tmp4 = \"\";\n//│         Predef.print(tmp4);\n//│     }\n//│     break;\n//│   case 1:\n//│     tmp4 = \"1\";\n//│     Predef.print(tmp4);\n//│     break;\n//│   default:\n//│     tmp4 = \"\";\n//│     Predef.print(tmp4);\n//│ }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 000\n\n:sjs\nprint of if x is\n  0 and y is\n    0 and z is\n      0 then \"000\"\n      1 then \"001\"\n    1 then \"01\"\n  1 then \"1\"\n  else \"\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp5;\n//│ switch (x) {\n//│   case 0:\n//│     switch (y) {\n//│       case 0:\n//│         switch (z) {\n//│           case 0:\n//│             tmp5 = \"000\";\n//│             break;\n//│           case 1:\n//│             tmp5 = \"001\";\n//│             break;\n//│           default:\n//│             tmp5 = \"\";\n//│         }\n//│         Predef.print(tmp5);\n//│         break;\n//│       case 1:\n//│         tmp5 = \"01\";\n//│         Predef.print(tmp5);\n//│         break;\n//│       default:\n//│         tmp5 = \"\";\n//│         Predef.print(tmp5);\n//│     }\n//│     break;\n//│   case 1:\n//│     tmp5 = \"1\";\n//│     Predef.print(tmp5);\n//│     break;\n//│   default:\n//│     tmp5 = \"\";\n//│     Predef.print(tmp5);\n//│ }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 000\n\n:sjs\nfun foo(x, y, z) =\n  if x is\n    0 and y is\n      0 and z is\n        0 then \"000\"\n        1 then \"001\"\n      1 then \"01\"\n    1 then \"1\"\n    else \"\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo;\n//│ foo = function foo(x1, y1, z1) {\n//│   switch (x1) {\n//│     case 0:\n//│       switch (y1) {\n//│         case 0:\n//│           switch (z1) {\n//│             case 0:\n//│               return \"000\";\n//│             case 1:\n//│               return \"001\";\n//│           }\n//│           return \"\";\n//│         case 1:\n//│           return \"01\";\n//│       }\n//│       return \"\";\n//│     case 1:\n//│       return \"1\";\n//│   }\n//│   return \"\"\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfoo(0, 0, 0)\n//│ = \"000\"\n\n:sjs\nprint of if\n  x is 0 and\n    y is 0 and\n      z is 0 then \"000\"\n    y is 1 then \"01_\"\n    z is 1 then \"0_1\"\n  x is 1 then \"1__\"\n  y is 2 then \"_2_\"\n  else \"___\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp6;\n//│ switch (x) {\n//│   case 0:\n//│     switch (y) {\n//│       case 0:\n//│         switch (z) {\n//│           case 0:\n//│             tmp6 = \"000\";\n//│             break;\n//│           case 1:\n//│             tmp6 = \"0_1\";\n//│             break;\n//│           default:\n//│             tmp6 = \"___\";\n//│         }\n//│         Predef.print(tmp6);\n//│         break;\n//│       case 1:\n//│         tmp6 = \"01_\";\n//│         Predef.print(tmp6);\n//│         break;\n//│       default:\n//│         if (z === 1) {\n//│           tmp6 = \"0_1\";\n//│         } else {\n//│           if (y === 2) {\n//│             tmp6 = \"_2_\";\n//│           } else {\n//│             tmp6 = \"___\";\n//│           }\n//│         }\n//│         Predef.print(tmp6);\n//│     }\n//│     break;\n//│   case 1:\n//│     tmp6 = \"1__\";\n//│     Predef.print(tmp6);\n//│     break;\n//│   default:\n//│     if (y === 2) { tmp6 = \"_2_\"; Predef.print(tmp6) } else { tmp6 = \"___\"; Predef.print(tmp6) }\n//│ }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > 000\n\n:sjs\nfun foo(x, y, z) = if\n  x is 0 and\n    y is 0 and\n      z is 0 then \"000\"\n    y is 1 then \"01_\"\n    z is 1 then \"0_1\"\n  x is 1 then \"1__\"\n  y is 2 then \"_2_\"\n  else \"___\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo1;\n//│ foo1 = function foo(x1, y1, z1) {\n//│   switch (x1) {\n//│     case 0:\n//│       switch (y1) {\n//│         case 0:\n//│           switch (z1) {\n//│             case 0:\n//│               return \"000\";\n//│             case 1:\n//│               return \"0_1\";\n//│           }\n//│           return \"___\";\n//│         case 1:\n//│           return \"01_\";\n//│       }\n//│       if (z1 === 1) {\n//│         return \"0_1\"\n//│       }\n//│       if (y1 === 2) {\n//│         return \"_2_\"\n//│       }\n//│       return \"___\";\n//│     case 1:\n//│       return \"1__\";\n//│   }\n//│   if (y1 === 2) { return \"_2_\" }\n//│   return \"___\";\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun expensive_call(str) = Math.pow(2, str.length)\n\n:sjs\nfun foo(x, y, z) = if x is\n  0 and y is\n    0 and z is\n      0 then \"000\"\n      1 then \"001\"\n    1 then \"01\"\n  1 then \"1\"\n  else\n    let value = \"hello\"\n    expensive_call(value)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo2;\n//│ foo2 = function foo(x1, y1, z1) {\n//│   let value;\n//│   switch (x1) {\n//│     case 0:\n//│       switch (y1) {\n//│         case 0:\n//│           switch (z1) {\n//│             case 0:\n//│               return \"000\";\n//│             case 1:\n//│               return \"001\";\n//│           }\n//│           break;\n//│         case 1:\n//│           return \"01\";\n//│       }\n//│       break;\n//│     case 1:\n//│       return \"1\";\n//│   }\n//│   value = \"hello\";\n//│   return expensive_call(value)\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfoo(0, 0, 0)\n//│ = \"000\"\n\n\nobject A\nobject B\nobject C\n\n:sjs\n// Since no branch is duplicated, there is no label or `break`.\nfun foo(x, y, z) =\n  if x is A then \"Hello-------------------------------------------------------------------------\"\n  else \"Goodbye-------------------------------------------------------------------------\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo3;\n//│ foo3 = function foo(x1, y1, z1) {\n//│   if (x1 instanceof A1.class) {\n//│     return \"Hello-------------------------------------------------------------------------\"\n//│   }\n//│   return \"Goodbye-------------------------------------------------------------------------\";\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\n// Before the deduplication is introduced:\n// let foo;\n// foo = function foo(x1, y, z) {\n//   if (x1 instanceof A1) {\n//     if (y instanceof B1) {\n//       if (z instanceof C1) {\n//         return \"Hello\"\n//       } else { return \"Goodbye\" }\n//     } else { return \"Goodbye\" }\n//   } else { return \"Goodbye\" }\n// };\nfun foo(x, y, z) =\n  if x is A and y is B and z is C then \"Hello\"\n  else \"Goodbye\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo4;\n//│ foo4 = function foo(x1, y1, z1) {\n//│   if (x1 instanceof A1.class) {\n//│     if (y1 instanceof B1.class) {\n//│       if (z1 instanceof C1.class) {\n//│         return \"Hello\"\n//│       }\n//│       return \"Goodbye\"\n//│     }\n//│     return \"Goodbye\";\n//│   }\n//│   return \"Goodbye\";\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\n// The default branch which throws the match error should be also deduplicated.\nfun foo(x, y, z) =\n  if x is A and y is B and z is C then \"Hello\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo5;\n//│ foo5 = function foo(x1, y1, z1) {\n//│   if (x1 instanceof A1.class) {\n//│     if (y1 instanceof B1.class) {\n//│       if (z1 instanceof C1.class) {\n//│         return \"Hello\"\n//│       }\n//│       throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:expect \"Hello\"\nfoo(A, B, C)\n//│ = \"Hello\"\n\n:re\nfoo(A, A, A)\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\nfoo(A, B, B)\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:sjs\nlet y = if true then 1 else 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let y1, scrut3, tmp7;\n//│ scrut3 = true;\n//│ if (scrut3 === true) { tmp7 = 1; } else { tmp7 = 2; }\n//│ y1 = tmp7;\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ y = 1\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/DeduplicationWhile.mls",
    "content": ":js\n:patMatConsequentSharingThreshold 1\n// ^ force dedup even for small consequents\n\n\n// :sjs\n() =>\nwhile true and false do print(1) else print(2)\n//│ = fun\n\n:sjs\n() =>\nwhile true and true and false do print(1) else print(2)\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda1;\n//│ lambda1 = (undefined, function () {\n//│   lbl: while (true) {\n//│     let scrut, scrut1, scrut2;\n//│     scrut = true;\n//│     if (scrut === true) {\n//│       scrut2 = true;\n//│       if (scrut2 === true) {\n//│         scrut1 = false;\n//│         if (scrut1 === true) {\n//│           Predef.print(1);\n//│           continue lbl\n//│         }\n//│       }\n//│     }\n//│     Predef.print(2);\n//│     continue lbl;\n//│   }\n//│ });\n//│ lambda1\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n// :sjs\nlet x = 3\nif x > 0 and x ===\n  1 do print(\"A\")\n  2 do print(\"A\")\n  3 do print(\"B\")\n  4 do print(\"B\")\n//│ > B\n//│ x = 3\n\n:sjs\nx =>\nwhile x > 0 and x ===\n  1 do print(\"A\")\n  2 do print(\"A\")\n  3 do print(\"B\")\n  4 do print(\"B\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda2;\n//│ lambda2 = (undefined, function (x1) {\n//│   lbl: while (true) {\n//│     let scrut5, scrut6, scrut7, scrut8, scrut9;\n//│     split_root$1: {\n//│       split_1$1: {\n//│         split_2$1: {\n//│           scrut5 = x1 > 0;\n//│           if (scrut5 === true) {\n//│             scrut6 = x1 === 1;\n//│             if (scrut6 === true) {\n//│               break split_1$1\n//│             }\n//│             scrut7 = x1 === 2;\n//│             if (scrut7 === true) {\n//│               break split_1$1\n//│             }\n//│             scrut8 = x1 === 3;\n//│             if (scrut8 === true) {\n//│               break split_2$1\n//│             }\n//│             scrut9 = x1 === 4;\n//│             if (scrut9 === true) {\n//│               break split_2$1\n//│             }\n//│             break split_root$1;\n//│           }\n//│           break split_root$1;\n//│         }\n//│         Predef.print(\"B\");\n//│         continue lbl;\n//│       }\n//│       Predef.print(\"A\");\n//│       continue lbl;\n//│     }\n//│     break;\n//│   }\n//│   return runtime.Unit\n//│ });\n//│ lambda2\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n:sjs\nx =>\nwhile x > 0 and x ===\n  1 and false and false do print(\"A\")\n  2 and false do print(\"B\")\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda3;\n//│ lambda3 = (undefined, function (x1) {\n//│   lbl: while (true) {\n//│     let scrut5, scrut6, scrut7, scrut8, scrut9, scrut10;\n//│     split_root$1: {\n//│       split_1$1: {\n//│         scrut5 = x1 > 0;\n//│         if (scrut5 === true) {\n//│           scrut6 = x1 === 1;\n//│           if (scrut6 === true) {\n//│             scrut8 = false;\n//│             if (scrut8 === true) {\n//│               scrut7 = false;\n//│               if (scrut7 === true) {\n//│                 Predef.print(\"A\");\n//│                 continue lbl\n//│               }\n//│               scrut9 = x1 === 2;\n//│               if (scrut9 === true) {\n//│                 scrut10 = false;\n//│                 if (scrut10 === true) {\n//│                   break split_1$1\n//│                 }\n//│               }\n//│             } else {\n//│               scrut9 = x1 === 2;\n//│               if (scrut9 === true) {\n//│                 scrut10 = false;\n//│                 if (scrut10 === true) {\n//│                   break split_1$1\n//│                 }\n//│               }\n//│             }\n//│             break split_root$1\n//│           }\n//│           scrut9 = x1 === 2;\n//│           if (scrut9 === true) {\n//│             scrut10 = false;\n//│             if (scrut10 === true) {\n//│               break split_1$1\n//│             }\n//│           }\n//│           break split_root$1;\n//│         }\n//│         break split_root$1;\n//│       }\n//│       Predef.print(\"B\");\n//│       continue lbl;\n//│     }\n//│     break;\n//│   }\n//│   return runtime.Unit\n//│ });\n//│ lambda3\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/ExcessiveDeduplication.mls",
    "content": ":js\n:patMatConsequentSharingThreshold 1\n// ^ force dedup even for small consequents\n\n\nlet\n  x = true\n  y = 2\n  z = true\n//│ x = true\n//│ y = 2\n//│ z = true\n\n\n// TODO: This should *not* be automatically deduplicated.\n// * In fact, we should probably never try to deduplicate things that are already duplicated in the source.\n:sjs\nif\n  x then 0\n  y then 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let tmp;\n//│ if (x !== true) {\n//│   if (y !== true) {\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│   }\n//│ }\n//│ tmp = 0;\n//│ tmp\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n// * Compare with:\n:sjs\nif\n  x then 0\n  y then 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ if (x === true) {\n//│   0\n//│ } else {\n//│   if (y === true) {\n//│     1\n//│   } else { throw globalThis.Object.freeze(new globalThis.Error(\"match error\")) }\n//│ }\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 0\n\n\n// * Currently, dedup' is implemented by hash-consing after the fact, which doesn't work when bindings are involved;\n// * it fails here:\n:ssjs\n:ucs normalized\nif\n  x and z then 1\n  y is [b] then let x = 1 in x + b\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    x is true and\n//│ >      z is true then 1\n//│ >      y is []=1 and\n//│ >        let tmp:element0$ = ((tmp:runtime⁰.)Tuple.)get‹term:get›(y⁰, 0)\n//│ >        let b = tmp:element0$⁰\n//│ >        else\n//│ >          let x\n//│ >          x = 1\n//│ >          builtin:+⁰(x⁰, b⁰)\n//│ >    y is []=1 and\n//│ >      let tmp:element0$ = ((tmp:runtime⁰.)Tuple.)get‹term:get›(y⁰, 0)\n//│ >      let b = tmp:element0$⁰\n//│ >      else\n//│ >        let x\n//│ >        x = 1\n//│ >        builtin:+⁰(x⁰, b⁰)\n//│ —————————————| JS (sanitized) |—————————————————————————————————————————————————————————————————————\n//│ let b, x1, element0$, tmp1;\n//│ split_root$: {\n//│   split_default$: {\n//│     if (x === true) {\n//│       if (z === true) {\n//│         tmp1 = 1;\n//│         break split_root$\n//│       }\n//│       if (runtime.Tuple.isArrayLike(y) && y.length === 1) {\n//│         element0$ = runtime.checkCall(runtime.Tuple.get(y, 0));\n//│         b = element0$;\n//│       } else {\n//│         break split_default$\n//│       }\n//│     } else {\n//│       if (runtime.Tuple.isArrayLike(y) && y.length === 1) {\n//│         element0$ = runtime.checkCall(runtime.Tuple.get(y, 0));\n//│         b = element0$;\n//│       } else {\n//│         break split_default$\n//│       }\n//│     }\n//│     x1 = 1;\n//│     tmp1 = x1 + b;\n//│     break split_root$;\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ }\n//│ block$res4 = tmp1;\n//│ undefined\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 1\n\n// * What we want is a way of let-binding split tails (ie, join points), as in:\n// >  if\n// >    let-split $j =\n// >      y is Some(argument0$) and\n// >        let b = $argument0$\n// >        else\n// >          let x\n// >          x = 1\n// >          builtin:+(x, b)\n// >    x is true and\n// >      z is true then 1\n// >      $j\n// >    $j\n\n\n// * Contemplate this absolutely horrendous code (before optimization):\n:sir\n:soir\n:sjs\nif false do ()\n123\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ 123\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let scrut;\n//│ block split_root$:\n//│   block split_1$:\n//│     set scrut = false;\n//│     match scrut\n//│       true =>\n//│         break split_1$\n//│       else\n//│         break split_1$\n//│     end\n//│   end\n//│ 123\n//│ ——————————————| Optimized IR |——————————————————————————————————————————————————————————————————————\n//│ 123\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n:patMatConsequentSharingThreshold 10\n\n// * How it ought to be:\n:sir\nif false do ()\n123\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let scrut; set scrut = false; 123\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = 123\n\n\nobject Obj with\n  fun test =\n    print(\"hi\")\n    false\n\n:sjs\nif Obj.test do ()\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ Obj1.test; runtime.Unit\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ > hi\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/InheritanceNormalization.mls",
    "content": ":js\n\n\nclass A\nclass B extends A\n\n:breakme // Should warn that the `B` branch is unreachable\nlet f = case\n  A then \"A\"\n  B then \"B\"\n//│ f = fun f\n\nf(new A)\n//│ = \"A\"\n\nf(new B)\n//│ = \"A\"\n\n\nlet f = case\n  B then \"B\"\n  A then \"A\"\n//│ f = fun f\n\nf(new A)\n//│ = \"A\"\n\nf(new B)\n//│ = \"B\"\n\n\n:sir\nlet f = case\n  A & B then \"A & B\"\n  A then \"A\"\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let f⁰, lambda⁰;\n//│ define lambda⁰ as fun lambda¹(caseScrut) {\n//│   match caseScrut\n//│     A⁰ =>\n//│       match caseScrut\n//│         B⁰ =>\n//│           return \"A & B\"\n//│         else\n//│           return \"A\"\n//│       end\n//│     else\n//│       throw new globalThis⁰.Error⁰(\"match error\")\n//│   end\n//│ };\n//│ set f⁰ = lambda¹;\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ f = fun\n\n:expect \"A\"\nf(new A)\n//│ = \"A\"\n\n:expect \"A & B\"\nf(new B)\n//│ = \"A & B\"\n\n\n// Test with imported class hierarchy\nimport \"../../../mlscript-compile/Example.mls\"\nopen Example\n\nlet g = case\n  Base & Child1 then \"Base & Child1\"\n  Base then \"Base\"\n//│ g = fun\n\n:expect \"Base & Child1\"\ng(new Child1)\n//│ = \"Base & Child1\"\n\n:expect \"Base\"\ng(new Child2)\n//│ = \"Base\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/OverlapOfPrimitives.mls",
    "content": ":js\n:ucs normalized\n\nfun test(x) = if x is\n  Int then \"Int\"\n  0 then \"Zero\"\n//│ Normalized:\n//│ >  ‹if|while› x is Int then \"Int\"\n\ntest(0)\n//│ = \"Int\"\n\nfun test(x, p) = if x is\n  Int and p(x) then \"foo\"\n  0 then \"bar\"\n  else \"qax\"\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    x is refined Int and\n//│ >      let tmp:scrut = p⁰(x⁰)\n//│ >      tmp:scrut is true then \"foo\"\n//│ >      x is 0 then \"bar\"\n//│ >      else \"qax\"\n//│ >    else \"qax\"\n\nfun test(x, p) = if x is\n  Str and p(x) then \"foo\"\n  \"lol\" then \"bar\"\n  else \"qax\"\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    x is refined Str and\n//│ >      let tmp:scrut = p¹(x¹)\n//│ >      tmp:scrut is true then \"foo\"\n//│ >      x is \"lol\" then \"bar\"\n//│ >      else \"qax\"\n//│ >    else \"qax\"\n\ntest(\"test\", _ => true)\n//│ = \"foo\"\n\ntest(\"lol\", _ => true)\n//│ = \"foo\"\n\ntest(\"lol\", _ => false)\n//│ = \"bar\"\n\ntest(\"\", _ => false)\n//│ = \"qax\"\n\nfun test(x, p) = if x is\n  Num and p(x) then \"great\"\n  2.71828 then \"E\"\n  3.14159 then \"PI\"\n  else \"other\"\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    x is refined Num and\n//│ >      let tmp:scrut = p²(x²)\n//│ >      tmp:scrut is true then \"great\"\n//│ >      x is 2.71828 then \"E\"\n//│ >      x is 3.14159 then \"PI\"\n//│ >      else \"other\"\n//│ >    else \"other\"\n\nfun test(x, p) = if x is\n  Bool and p(x) then \"great\"\n  true then \"false\"\n  false then \"true\"\n//│ Normalized:\n//│ >  ‹if|while› x is refined Bool and\n//│ >    let tmp:scrut = p³(x³)\n//│ >    tmp:scrut is true then \"great\"\n//│ >    x is true then \"false\"\n//│ >    x is false then \"true\"\n\nfun test(x, p) = if x is\n  Object and p(x) then \"great\"\n  Bool and p(x) then \"great, again\"\n  true then \"false\"\n  false then \"true\"\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    x is Object and\n//│ >      let tmp:scrut = p⁴(x⁴)\n//│ >      tmp:scrut is true then \"great\"\n//│ >    x is refined Bool and\n//│ >      let tmp:scrut = p⁴(x⁴)\n//│ >      tmp:scrut is true then \"great, again\"\n//│ >      x is true then \"false\"\n//│ >      x is false then \"true\"\n\nobject Foo\n\nfun f(arg) = if\n  arg is\n    undefined then \"undefined\"\n    null      then \"null\"\n    Object    then String(arg)\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    arg is undefined then \"undefined\"\n//│ >    arg is null then \"null\"\n//│ >    arg is Object then member:String⁰(arg⁰)\n\nf of undefined\n//│ = \"undefined\"\n\nf of null\n//│ = \"null\"\n\nf of Foo\n//│ = \"Foo\"\n\nfun f(arg) = if\n  arg is\n    Object    then String(arg)\n    undefined then \"undefined\"\n    null      then \"null\"\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    arg is Object then member:String⁰(arg¹)\n//│ >    arg is undefined then \"undefined\"\n//│ >    arg is null then \"null\"\n\nf of undefined\n//│ = \"undefined\"\n\nf of null\n//│ = \"null\"\n\nf of Foo\n//│ = \"Foo\"\n\nfun f(arg) = if arg is\n  Object then String(arg)\n  Foo then \"just Foo\"\n//│ Normalized:\n//│ >  ‹if|while› arg is Object then member:String⁰(arg²)\n\nimport \"../../../mlscript-compile/Runtime.mls\"\n\nfun f(arg) = if arg is\n  Object then String(arg)\n  Runtime.MatchSuccess then \"just Foo\"\n//│ Normalized:\n//│ >  ‹if|while› arg is Object then member:String⁰(arg³)\n\nfun f(arg) = if arg is\n  Foo then \"just Foo\"\n  Object then String(arg)\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    arg is Foo then \"just Foo\"\n//│ >    arg is Object then member:String⁰(arg⁴)\n\nfun f(arg) = if arg is\n  Int then \"Int\"\n  Object then String(arg)\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    arg is Int then \"Int\"\n//│ >    arg is Object then member:String⁰(arg⁵)\n\nfun f(arg) = if arg is\n  Object then String(arg)\n  Int then \"Int\"\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    arg is Object then member:String⁰(arg⁶)\n//│ >    arg is Int then \"Int\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/SimplePairMatches.mls",
    "content": ":js\n\n\ndata class Pair(a, b)\nclass A\nclass B\n\n\n:sjs\nx => if x is Pair(A, B) then 1\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lambda;\n//│ lambda = (undefined, function (x) {\n//│   let arg$Pair$0$, arg$Pair$1$;\n//│   if (x instanceof Pair1.class) {\n//│     arg$Pair$0$ = x.a;\n//│     arg$Pair$1$ = x.b;\n//│     if (arg$Pair$0$ instanceof A1) {\n//│       if (arg$Pair$1$ instanceof B1) {\n//│         return 1\n//│       }\n//│       throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ });\n//│ lambda\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = fun\n\n\n// :e // FIXME: should be an exhaustiveness error\n:sjs\nfun f(x) = if x is\n  Pair(A, A) then 1\n  Pair(B, B) then 2\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let f;\n//│ f = function f(x) {\n//│   let arg$Pair$0$, arg$Pair$1$;\n//│   if (x instanceof Pair1.class) {\n//│     arg$Pair$0$ = x.a;\n//│     arg$Pair$1$ = x.b;\n//│     if (arg$Pair$0$ instanceof A1) {\n//│       if (arg$Pair$1$ instanceof A1) {\n//│         return 1\n//│       }\n//│       throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│     } else if (arg$Pair$0$ instanceof B1) {\n//│       if (arg$Pair$1$ instanceof B1) {\n//│         return 2\n//│       }\n//│       throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/UnifySubScrutinees.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Stack\nopen Option\n\ndata class Pair[A, B](x: A, y: B)\n\nfun foo(xs) =\n  if xs is\n    \"abc\" :: \"xyz\" :: xs then 0\n    \"abc\" :: \"uvw\" :: xs then 1\n    Nil then 3\n\nfun sum(acc, xs) = \n  if xs is\n    x :: xs then sum(acc + x, xs)\n    Nil     then acc\n\n// :ucs normalized\nfun test(xs) =\n  if xs is\n    Some(Cons(\"add\", Cons(x, Cons(y, Nil)))) then x + y\n    Some(Cons(\"mul\", Cons(x, Cons(y, Nil)))) then x * y\n    Some(Cons(\"sum\", xs)) then sum(0, xs)\n    Some(Nil) then \"nothing\"\n    None then \"nothing\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/normalization/UnifyTupleElements.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option\n\n// Normalization should unify fixed-length tuple patterns.\nfun sum_options(x, y) =\n  if [x, y] is\n    [Some(xv), Some(yv)] then xv + yv\n    [Some(xv), None]     then xv\n    [None,     Some(yv)] then yv\n    [None,     None]     then 0\n\n\n\n\n// ========================================================================== //\n\n\n// Normalization should also unify the sub-scrutinees at the same position of\n// tuple patterns of different lengths.\n\n\nfun foo(xs) = if xs is\n  [Some(x)] then x\n  [Some(y), ..rest] then y\n\nfun do_something(x) = \"done\"\n\n\nfun foo(zs) = if zs is\n  [Some(x), Some(y)] then x + y\n  [None, ..rest] then do_something(rest)\n\n:expect 4\nfoo([Some(1), Some(3)])\n//│ = 4\n\n:expect \"done\"\nfoo([None, Some(1), Some(2)])\n//│ = \"done\"\n\n:re\nfoo([Some(0)])\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\nfoo([Some(0), Some(1), Some(2)])\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\nfoo([])\n//│ ═══[RUNTIME ERROR] Error: match error\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/papers/OperatorSplit.mls",
    "content": ":js\n\nfun example(x) =\n  if x\n    |> Math.sign\n      < 0 then \"invalid\"\n      == 0 then \"null\"\n    |> Math.abs\n      > 100 then \"large\"\n      < 10 then \"small\"\n      else \"medium\"\n\nexample(0)\n//│ = \"null\"\n\nexample(-24)\n//│ = \"invalid\"\n\n:expect \"large\"\nexample(200)\n//│ = \"large\"\n\n:expect \"small\"\nexample(5)\n//│ = \"small\"\n\n:expect \"medium\"\nexample(79)\n//│ = \"medium\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/AliasPattern.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option\n\nfun map(f) = case\n  Some(x)   then Some(f(x))\n  None as n then n\n\nfun map(f) = case\n  Some(x as n) then Some of f(n)\n  None as n then n\n\n\nfun foo = case\n  Some(Some(a as b) as c) as d then [a, b, c, d]\n\nfoo of Some(Some(42))\n//│ = [42, 42, Some(42), Some(Some(42))]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/Compilation.mls",
    "content": ":js\n\nopen annotations\n\n// * Note: these syntaxes work but, the compilation doesn't support this yet\n\n:fixme\nfun trimStart(str) =\n  if str is @compile { (\" \" | \"\\t\") ~ rest } then trimStart(rest) else str\n//│ ╔══[COMPILATION ERROR] String concatenation is not supported in pattern compilation.\n//│ ║  l.9: \t  if str is @compile { (\" \" | \"\\t\") ~ rest } then trimStart(rest) else str\n//│ ╙──     \t                        ^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'rest'\n//│ ║  l.9: \t  if str is @compile { (\" \" | \"\\t\") ~ rest } then trimStart(rest) else str\n//│ ╙──     \t                                                            ^^^^\n\n:fixme\nfun trimStart(str) =\n  if str is (@compile ((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ╔══[COMPILATION ERROR] String concatenation is not supported in pattern compilation.\n//│ ║  l.19: \t  if str is (@compile ((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ╙──      \t                        ^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'rest'\n//│ ║  l.19: \t  if str is (@compile ((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ╙──      \t                                                            ^^^^\n\n:fixme\nfun trimStart(str) =\n  if str is @compile ((\" \" | \"\\t\") ~ rest) then trimStart(rest) else str\n//│ ╔══[COMPILATION ERROR] String concatenation is not supported in pattern compilation.\n//│ ║  l.29: \t  if str is @compile ((\" \" | \"\\t\") ~ rest) then trimStart(rest) else str\n//│ ╙──      \t                       ^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'rest'\n//│ ║  l.29: \t  if str is @compile ((\" \" | \"\\t\") ~ rest) then trimStart(rest) else str\n//│ ╙──      \t                                                          ^^^^\n\n\n// * Note: `@compile(...)` is parsed as a whole annotation\n:pe\n:e\nfun trimStart(str) =\n  if str is (@compile((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ╔══[PARSE ERROR] Expected start of expression in this position\n//│ ║  l.42: \t  if str is (@compile((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ║        \t                                          ^\n//│ ╟── found a lone annotation instead\n//│ ║  l.42: \t  if str is (@compile((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ╙──      \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (‹erroneous syntax›).\n//│ ║  l.42: \t  if str is (@compile((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ╙──      \t                                          ^\n//│ ╔══[COMPILATION ERROR] Name not found: rest\n//│ ║  l.42: \t  if str is (@compile((\" \" | \"\\t\") ~ rest)) then trimStart(rest) else str\n//│ ╙──      \t                                                           ^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/ConjunctionPattern.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Stack\n\n\nabstract class Q\nabstract class A extends Q\nabstract class B extends Q\n\n// Note: A and B are sibling classes (both extend Q but neither extends the\n// other), so under the single-inheritance restriction they are provably\n// disjoint. Conjunction patterns like `A & B` for such classes should\n// correctly be eliminated by normalization.\n\n\nif new A is\n  A & A & B then 0\n  B & A & B then 1\n  A & A & A then 2\n  else 3\n//│ = 2\n\nif new A is\n  A & A & B then 0\n  B & A & B then 1\n  A & A & A then 2\n  else 3\n//│ = 2\n\n:sjs\nfun foo(v) =\n  if v is\n    A & B then 1\n    else 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let foo; foo = function foo(v) { if (v instanceof A1) { return 0 } return 0; };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun range(i, j) =\n  if i > j then Nil\n  else i :: range(i+1, j)\n\nfun suffixes(l) = if l is\n  Nil then Cons(Nil, Nil)\n  l & (_ :: tl) then l :: suffixes(tl)\n\nsuffixes(range(0, 5))\n//│ = Cons(\n//│   Cons(0, Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))),\n//│   Cons(\n//│     Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil))))),\n//│     Cons(\n//│       Cons(2, Cons(3, Cons(4, Cons(5, Nil)))),\n//│       Cons(\n//│         Cons(3, Cons(4, Cons(5, Nil))),\n//│         Cons(Cons(4, Cons(5, Nil)), Cons(Cons(5, Nil), Cons(Nil, Nil)))\n//│       )\n//│     )\n//│   )\n//│ )\n\nsuffixes(range(0, -1))\n//│ = Cons(Nil, Nil)\n\nsuffixes(range(0, 0))\n//│ = Cons(Cons(0, Nil), Cons(Nil, Nil))\n\nif 5 is a & b & c then a+b+c\n//│ = 15\n\ndata class C(a)\n\nfun foo(x) = if x is\n  {a:_ & a} & C and\n    a is 1 then 10\n    a is 2 then 20\n    else 30\n  else 40\n\nfoo(C(1))\n//│ = 10\n\nfoo(4)\n//│ = 40\n\nfoo(C(2))\n//│ = 20\n\nfoo(C(\"a\"))\n//│ = 30\n\nif C(1) is {:a} & C then a\n//│ = 1\n\nif C(1) is C & {:a} then a\n//│ = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/GuardedPatternBindings.mls",
    "content": ":js\n\n\n:w\npattern PlainPair = [x, y]\n//│ ╔══[WARNING] Unused pattern binding: x.\n//│ ║  l.5: \tpattern PlainPair = [x, y]\n//│ ╙──     \t                     ^\n//│ ╔══[WARNING] Unused pattern binding: y.\n//│ ║  l.5: \tpattern PlainPair = [x, y]\n//│ ╙──     \t                        ^\n\n\n// Regression test: variables used in `where` guards should not produce\n// spurious \"Useless pattern binding\" warnings.\n\npattern Symmetry =\n  ([x, y] where (x == y))\n\n[1, 1] is Symmetry\n//│ = true\n\n[1, 2] is Symmetry\n//│ = false\n\n// We should check the free variables in `where` guards.\n:w\npattern PairSum = [x, y] where (let x = true, let y = x, y)\n// We should check the free variables in `where` guards.\n//│ ╔══[WARNING] Unused pattern binding: x.\n//│ ║  l.28: \tpattern PairSum = [x, y] where (let x = true, let y = x, y)\n//│ ╙──      \t                   ^\n//│ ╔══[WARNING] Unused pattern binding: y.\n//│ ║  l.28: \tpattern PairSum = [x, y] where (let x = true, let y = x, y)\n//│ ╙──      \t                      ^\n\n:w\npattern PairSum = [x, y] where (if x is [y] then y)\n//│ ╔══[WARNING] Unused pattern binding: y.\n//│ ║  l.38: \tpattern PairSum = [x, y] where (if x is [y] then y)\n//│ ╙──      \t                      ^\n\n:w\npattern PairSum = [x, y] where (class C(y) with { fun test = y }, C(x).test)\n//│ ╔══[WARNING] Unused pattern binding: y.\n//│ ║  l.44: \tpattern PairSum = [x, y] where (class C(y) with { fun test = y }, C(x).test)\n//│ ╙──      \t                      ^\n\n:w\npattern PairSum = [x, y] where (fun y = 1, print(y), x)\n//│ ╔══[WARNING] Unused pattern binding: y.\n//│ ║  l.50: \tpattern PairSum = [x, y] where (fun y = 1, print(y), x)\n//│ ╙──      \t                      ^\n\n// Forward reference to `y` should not be counted as a free variable\n:w\npattern PairSum = [x, y] where (print(y), fun y = 1, x)\n//│ ╔══[WARNING] Unused pattern binding: y.\n//│ ║  l.57: \tpattern PairSum = [x, y] where (print(y), fun y = 1, x)\n//│ ╙──      \t                      ^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/Literals.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option\n\ndata class Pair[A, B](x: A, y: B)\n\nfun f(x) = if x is Some(1) then true else false\n\n[f(Some(1)), f(None), f(Some(2)), f(Some(-1))]\n//│ = [true, false, false, false]\n\nfun f(x) = if x is Some(1) then true\n\nfun f(x) = if x is\n  Some(1) then true\n  Some(2) then false\n\n[f(Some(1)), f(Some(2))]\n//│ = [true, false]\n\nfun g(x) = if x then 1 else 2\n\n// :e\nfun test_must_be_boolean(x) = if 0 then 1 else 2\n\nfun g(x) = if x is true then 1 else 2\n\n:expect [1, 2, 2]\n[g(true), g(false), g(None)]\n//│ = [1, 2, 2]\n\nfun g(x) = if x && true is true then 1 else 2\n\nfun h(x) = if (x as Bool) then 1 else 2\n\nfun mix(x) = if x is\n  true then \"true\"\n  Some(value) then \"Some\"\n  0 then \"zero\"\n\n[mix(true), mix(Some(1)), mix(0)]\n//│ = [\"true\", \"Some\", \"zero\"]\n\n:re\n[mix(false), mix(None)]\n//│ ═══[RUNTIME ERROR] Error: match error\n\nfun string_literals(x) =\n  if x is\n    \"foo\" then 0\n    \"bar\" then 1\n    \"qax\" then 2\n\nclass Foo\n\nfun mixed_patterns(x) =\n  if x is\n    Foo then 1\n    23 then 2\n    \"test\" then 3\n\nfun bool_patterns(x) =\n  if x is\n    true then 1\n    false then 2\n\nfun dual_patterns(x, y) =\n  if\n    x is \"some\" and y is \"none\" then 0\n    x is \"none\" and y is \"some\" then 1\n    x is \"some\" and y is \"some\" then 2\n    x is \"none\" and y is \"none\" then 3\n\n\n:fixme // TODO\n() is ()\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (unit).\n//│ ║  l.78: \t() is ()\n//│ ╙──      \t      ^^\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/NamePattern.mls",
    "content": ":js\n\nfun id(x) = x\n\n:ucs desugared\nif id(0) is t then t\n//│ Split with nested patterns:\n//│ >  if\n//│ >    let tmp:scrut = member:id⁰(0)\n//│ >    tmp:scrut is t then t⁰\n//│ Expanded split with flattened patterns:\n//│ >  ‹if|while›\n//│ >    let tmp:scrut = member:id⁰(0)\n//│ >    let t = tmp:scrut⁰\n//│ >    else t⁰\n//│ = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/Parameters.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\nclass Foo(a: Int, val b: Int)\n\n:e\nfun foo(x) = if x is Foo(p, q) then p + q\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.10: \tfun foo(x) = if x is Foo(p, q) then p + q\n//│ ║        \t                         ^\n//│ ╟── because the corresponding parameter `a` is not publicly accessible\n//│ ║  l.7: \tclass Foo(a: Int, val b: Int)\n//│ ║       \t          ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n\n:re\nfoo(Foo(2, 3))\n//│ ═══[RUNTIME ERROR] Error: match error\n\nfun foo(x) = if x is Foo(_, q) then q\n\nfoo(Foo(2, 3))\n//│ = 3\n\nclass SecretPair(a: Int, val b: Int)\n\n// Binding the overall constructor output with `as result` should still be allowed\n// when all constructor arguments preserve their scrutinees, even if some\n// private fields are matched with `_`.\nfun keepSecret(x) = if x is (SecretPair(_, q)) as result then q\n\nkeepSecret(SecretPair(2, 3))\n//│ = 3\n\n:e\nfun rebuildSecret(x) = if x is (SecretPair(_, (q => q + 1))) as result then result\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.40: \tfun rebuildSecret(x) = if x is (SecretPair(_, (q => q + 1))) as result then result\n//│ ║        \t                                           ^\n//│ ╟── because the corresponding parameter `a` is not publicly accessible\n//│ ║  l.29: \tclass SecretPair(a: Int, val b: Int)\n//│ ║        \t                 ^\n//│ ╟── because rebuilding the matched `SecretPair` value requires reading every constructor argument\n//│ ║  l.40: \tfun rebuildSecret(x) = if x is (SecretPair(_, (q => q + 1))) as result then result\n//│ ║        \t                                ^^^^^^^^^^\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n\nclass Test(a, b, c, d, e, f)\n\nfun test(x) = if x is Test then \"ok\"\n\n:e\nfun test(x) = if x is Test(p, q, r, s, t, u) then \"ok\"\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.57: \tfun test(x) = if x is Test(p, q, r, s, t, u) then \"ok\"\n//│ ║        \t                           ^\n//│ ╟── because the corresponding parameter `a` is not publicly accessible\n//│ ║  l.52: \tclass Test(a, b, c, d, e, f)\n//│ ║        \t           ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.57: \tfun test(x) = if x is Test(p, q, r, s, t, u) then \"ok\"\n//│ ║        \t                              ^\n//│ ╟── because the corresponding parameter `b` is not publicly accessible\n//│ ║  l.52: \tclass Test(a, b, c, d, e, f)\n//│ ║        \t              ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.57: \tfun test(x) = if x is Test(p, q, r, s, t, u) then \"ok\"\n//│ ║        \t                                 ^\n//│ ╟── because the corresponding parameter `c` is not publicly accessible\n//│ ║  l.52: \tclass Test(a, b, c, d, e, f)\n//│ ║        \t                 ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.57: \tfun test(x) = if x is Test(p, q, r, s, t, u) then \"ok\"\n//│ ║        \t                                    ^\n//│ ╟── because the corresponding parameter `d` is not publicly accessible\n//│ ║  l.52: \tclass Test(a, b, c, d, e, f)\n//│ ║        \t                    ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.57: \tfun test(x) = if x is Test(p, q, r, s, t, u) then \"ok\"\n//│ ║        \t                                       ^\n//│ ╟── because the corresponding parameter `e` is not publicly accessible\n//│ ║  l.52: \tclass Test(a, b, c, d, e, f)\n//│ ║        \t                       ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.57: \tfun test(x) = if x is Test(p, q, r, s, t, u) then \"ok\"\n//│ ║        \t                                          ^\n//│ ╟── because the corresponding parameter `f` is not publicly accessible\n//│ ║  l.52: \tclass Test(a, b, c, d, e, f)\n//│ ║        \t                          ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n\n:e\nfun test(x) = if x is Test(_, _, _) then \"ok\"\n//│ ╔══[COMPILATION ERROR] Expected six arguments, but found only three arguments.\n//│ ║  l.108: \tfun test(x) = if x is Test(_, _, _) then \"ok\"\n//│ ╙──       \t                           ^^^^^^^\n\nfun test(x) = if x is Test(_, _, _, _, _, _) then \"ok\"\n\n:e\nfun test(x) = if x is Test(_, _, _, a, _, _) then \"ok\"\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.116: \tfun test(x) = if x is Test(_, _, _, a, _, _) then \"ok\"\n//│ ║         \t                                    ^\n//│ ╟── because the corresponding parameter `d` is not publicly accessible\n//│ ║  l.52: \tclass Test(a, b, c, d, e, f)\n//│ ║        \t                    ^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n\nclass Point(val x: Int, val y: Int)\n\nfun point(p) = if p is Point(x, y) then x + y\n\npoint(Point(2, 4))\n//│ = 6\n\nobject Main with\n  fun run(input) = if input is Data(count) then 0\ndata class Data(value: Int)\n\n// Validation on object patterns\n\nobject A\n\n:e\nfun foo(x) = if x is A() then 0\n//│ ╔══[COMPILATION ERROR] `A` is an object.\n//│ ║  l.139: \tobject A\n//│ ║         \t       ^\n//│ ╟── Its pattern cannot have an argument list.\n//│ ║  l.142: \tfun foo(x) = if x is A() then 0\n//│ ╙──       \t                     ^\n\n:e\nfun foo(x) = if x is A(y) then y\n//│ ╔══[COMPILATION ERROR] `A` is an object.\n//│ ║  l.139: \tobject A\n//│ ║         \t       ^\n//│ ╟── Its pattern cannot have arguments.\n//│ ║  l.151: \tfun foo(x) = if x is A(y) then y\n//│ ╙──       \t                     ^^^\n\n0 is Foo\n//│ = false\n\ndata class Pair[A, B](a: A, b: B)\n\npattern PairLike(a, b) = [a, b] | Pair(a, b)\n\nfun foo(x) = if x is PairLike(a, b) then Some(a + b) else None\n\nfoo(Pair(1, 2))\n//│ = Some(3)\n\nfoo([1, 2])\n//│ = Some(3)\n\nfoo([])\n//│ = None\n\npattern AtPrec =\n  ( \"+\" => 2 ) |\n  ( \"*\" => 5 )\n\nfun f(x) = if x is str as AtPrec as prec then [str, prec]\nf(\"+\")\n//│ = [\"+\", 2]\nf(\"*\")\n//│ = [\"*\", 5]\n\npattern Op(str, prec) = str as AtPrec as prec\n\nif \"+\" is Op as p then p\n//│ = [\"+\", 2]\n\nif \"+\" is Op(s, p) then [s, p]\n//│ = [\"+\", 2]\n\npattern Crazy(a, b, c, d, e, f, g) = a as b as c as d as e as f as g\n\nif 42 is Crazy(a, b, c, d, e, f, g) then print(a, b, c, d, e, f, g)\n//│ > 42 42 42 42 42 42 42\n\nlet p = Pair(42, 42)\n//│ p = Pair(42, 42)\n\nif p is Crazy(a, b, c, d, e, f, g) then\n  p === a and a === b and b === c and c === d and d === e and e === f and f === g\n//│ = true\n\n:e\n:re\nif p is Crazy(a, b, c, d, e, f) then 42\n//│ ╔══[COMPILATION ERROR] Expected seven extraction arguments, but found only six arguments.\n//│ ║  l.209: \tif p is Crazy(a, b, c, d, e, f) then 42\n//│ ╙──       \t              ^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:e\n:re\nif p is Crazy(all) then 42\n//│ ╔══[COMPILATION ERROR] Expected seven extraction arguments, but found only one argument.\n//│ ║  l.217: \tif p is Crazy(all) then 42\n//│ ╙──       \t              ^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\nif p is Crazy as all then all\n//│ = [\n//│   Pair(42, 42),\n//│   Pair(42, 42),\n//│   Pair(42, 42),\n//│   Pair(42, 42),\n//│   Pair(42, 42),\n//│   Pair(42, 42),\n//│   Pair(42, 42)\n//│ ]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/RecordPattern.mls",
    "content": ":js\n\n\nfun take_1(p) =\n  if p is\n    { x: a, y: b } then a + b\n    else 0\nfun take_2(p) =\n  if p is\n    { :x, :y } then x + y\n    else 0\n\ntake_1({x: 0, y: 10})\n//│ = 10\n\ntake_1({t: 5, x: 0, y: 10, z: 42})\n//│ = 10\n\ntake_2({x: 0, y: 10})\n//│ = 10\n\ntake_2({t: 5, x: 0, y: 10, z: 42})\n//│ = 10\n\ntake_1({x:\"a\", y:\"b\"})\n//│ = \"ab\"\n\nlet r = {z:4}\ntake_1(r)\n//│ = 0\n//│ r = {z: 4}\n\nlet f = case\n  { a: 1 as a } then a\n//│ f = fun\n\nf(a: 1)\n//│ = 1\n\n\n// * It would probably be surprising to bind `a` in the RHS here\n:e\nlet f = case\n  { a: 1 } then a\n//│ ╔══[COMPILATION ERROR] Name not found: a\n//│ ║  l.44: \t  { a: 1 } then a\n//│ ╙──      \t                ^\n//│ f = fun\n\n// * OTOH, note that `a` is bound here\nlet rcd =\n  a: 1\n  b: a + 1\n//│ rcd = {a: 1, b: 2}\n\n// * As that will make sense when we have dependent types,\n// * as in: `{ n: Int, v: Vec[Int, n] }`\n\nlet r = {x: 2, y : 4}\n//│ r = {x: 2, y: 4}\n\n:e\nif r is\n  {x:a, y:a} then a\n//│ ╔══[COMPILATION ERROR] Duplicated pattern variable.\n//│ ║  l.64: \t  {x:a, y:a} then a\n//│ ║        \t          ^\n//│ ╟── The previous definition is as follows.\n//│ ║  l.64: \t  {x:a, y:a} then a\n//│ ╙──      \t     ^\n//│ = 4\n\n\nlet rr = {x: {y:10, z:100}, t:1000}\nif rr is\n  {x : {:y, z:t}} then y+t\n//│ = 110\n//│ rr = {x: {y: 10, z: 100}, t: 1000}\n\n\nif rr is { \"x\": x } then x\n//│ = {y: 10, z: 100}\n\nif rr is { 'x: x } then x\n//│ = {y: 10, z: 100}\n\n\n\nlet f = case\n  { a: 1 & a } then a\n//│ f = fun\n\n\nlet f = case\n  { :a } then a\n//│ f = fun\n\nf(a: 1)\n//│ = 1\n\nimport \"../../../mlscript-compile/Option.mls\"\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Option { Some, None }\nopen Stack\n\nSome(42) is { value: 42 }\n//│ = true\n\n1 :: 2 :: 3 :: Nil is { tail: { tail: Nil } }\n//│ = false\n\n1 :: 2 :: 3 :: Nil is { tail: { tail: _ } }\n//│ = true\n\n1 :: 2 :: 3 :: Nil is { tail: { tail: { tail: Nil } } }\n//│ = true\n\n1 :: 2 :: 3 :: Nil is { head: 42 }\n//│ = false\n\nfun pairwise(xs) = if xs is\n  { head: a, tail: { head: b, tail: xs' } } then [a, b] :: pairwise(xs')\n  else Nil\n\npairwise(49)\n//│ = Nil\n\npairwise(\"hello\" :: \"world\" :: \"bonjour\" :: \"le monde\" :: Nil)\n//│ = Cons([\"hello\", \"world\"], Cons([\"bonjour\", \"le monde\"], Nil))\n\npairwise(1 :: 2 :: 3 :: Nil)\n//│ = Cons([1, 2], Nil)\n\nfun foo(xs) = if xs is\n  { tail: { tail: { tail: _ } } } then \"at least three of them\"\n  { tail: { tail: Nil } } then \"there are two of them\"\n  { tail: Nil } then \"only one left\"\n  else \"yeah we're done\"\n\nfoo(Nil)\n//│ = \"yeah we're done\"\n\nfoo(999)\n//│ = \"yeah we're done\"\n\nfoo(1 :: Nil)\n//│ = \"only one left\"\n\nfoo(1 :: \"this is invalid\")\n//│ = \"yeah we're done\"\n\nfoo(1 :: 2 :: Nil)\n//│ = \"there are two of them\"\n\nfoo(1 :: 2 :: 4 :: Nil)\n//│ = \"at least three of them\"\n\nfoo(1 :: 2 :: 4 :: 8 :: Nil)\n//│ = \"at least three of them\"\n\nfun should_reject_null(x) = if x is { a: 0 } then 42 else -42\n\nshould_reject_null(null)\n//│ = -42\n\nfun is_object(x) = if x is {} then true else false\n\nis_object(null)\n//│ = false\n\nis_object(Object)\n//│ = true\n\nis_object(0)\n//│ = false\n\nis_object(\"\")\n//│ = false\n\nis_object(Nil)\n//│ = true\n\nis_object([1, 2])\n//│ = true\n\nis_object(is_object)\n//│ = true\n\nfun is_record_alt(x) = x is {}\n\nis_record_alt of []\n//│ = true\n\nis_record_alt of 0\n//│ = false\n\nis_object(\"\")\n//│ = false\n\nis_object(Nil)\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/Refinement.mls",
    "content": ":ignore\n:ucs normalized\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option\n\n// OK\nx => if x is\n  refined(None) then x\n//│ ╔══[COMPILATION ERROR] Name not found: refined\n//│ ║  l.10: \t  refined(None) then x\n//│ ╙──      \t  ^^^^^^^\n//│ ═══[COMPILATION ERROR] Cannot use this ‹error› as a pattern.\n//│ Normalized:\n//│ >  ‹if|while›\n\n// OK\nx => if x is\n  refined(Some) then x\n//│ ╔══[COMPILATION ERROR] Name not found: refined\n//│ ║  l.20: \t  refined(Some) then x\n//│ ╙──      \t  ^^^^^^^\n//│ ═══[COMPILATION ERROR] Cannot use this ‹error› as a pattern.\n//│ Normalized:\n//│ >  ‹if|while›\n\n// Should warn about the inconsistent refinement\nx => if x is\n  refined(None) then x\n  Some then x\n//│ ╔══[COMPILATION ERROR] Name not found: refined\n//│ ║  l.30: \t  refined(None) then x\n//│ ╙──      \t  ^^^^^^^\n//│ ═══[COMPILATION ERROR] Cannot use this ‹error› as a pattern.\n//│ Normalized:\n//│ >  ‹if|while› x is Option.Some then x⁰\n\nx => if x is\n  refined(None) then x\n  refined(Some) then x\n//│ ╔══[COMPILATION ERROR] Name not found: refined\n//│ ║  l.40: \t  refined(None) then x\n//│ ╙──      \t  ^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: refined\n//│ ║  l.41: \t  refined(Some) then x\n//│ ╙──      \t  ^^^^^^^\n//│ ═══[COMPILATION ERROR] Cannot use this ‹error› as a pattern.\n//│ ═══[COMPILATION ERROR] Cannot use this ‹error› as a pattern.\n//│ Normalized:\n//│ >  ‹if|while›\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/RestTuple.mls",
    "content": ":js\n\n\n:sjs\nfun nonsense(xs) = if xs is\n  [..ys] then ys\n  [] then \"empty\"\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let nonsense;\n//│ nonsense = function nonsense(xs) {\n//│   let ys, middleElements;\n//│   if (runtime.Tuple.isArrayLike(xs) && xs.length >= 0) {\n//│     middleElements = runtime.Tuple.slice(xs, 0, 0);\n//│     ys = middleElements;\n//│     return ys\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nnonsense([])\n//│ = []\n\nnonsense([1, 2, 3, 4])\n//│ = [1, 2, 3, 4]\n\n:sjs\nfun lead_and_last(xs) = if xs is\n  [x, ..ys, y] then x + y\n  [] then 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let lead_and_last;\n//│ lead_and_last = function lead_and_last(xs) {\n//│   let x, y, lastElement1$, element0$;\n//│   if (runtime.Tuple.isArrayLike(xs) && xs.length >= 2) {\n//│     element0$ = runtime.Tuple.get(xs, 0);\n//│     runtime.Tuple.slice(xs, 1, 1);\n//│     lastElement1$ = runtime.Tuple.get(xs, -1);\n//│     y = lastElement1$;\n//│     x = element0$;\n//│     return x + y\n//│   } else if (runtime.Tuple.isArrayLike(xs) && xs.length === 0) {\n//│     return 0\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nlead_and_last([\"foo\", \"bar\"])\n//│ = \"foobar\"\n\nlead_and_last([1, 2, 3, 4])\n//│ = 5\n\nlead_and_last([])\n//│ = 0\n\n:re\nlead_and_last([\"boom\"])\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:sjs\nfun nested_tuple_patterns(xs) = if xs is\n  [x, ..[y, z], w] then x + y + z + w\n  [] then 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let nested_tuple_patterns;\n//│ nested_tuple_patterns = function nested_tuple_patterns(xs) {\n//│   let x, y, w, z, lastElement1$, middleElements, element0$, element1$, element0$1, tmp6, tmp7;\n//│   if (runtime.Tuple.isArrayLike(xs) && xs.length >= 2) {\n//│     element0$ = runtime.Tuple.get(xs, 0);\n//│     middleElements = runtime.Tuple.slice(xs, 1, 1);\n//│     lastElement1$ = runtime.Tuple.get(xs, -1);\n//│     if (runtime.Tuple.isArrayLike(middleElements) && middleElements.length === 2) {\n//│       element0$1 = runtime.Tuple.get(middleElements, 0);\n//│       element1$ = runtime.Tuple.get(middleElements, 1);\n//│       w = lastElement1$;\n//│       z = element1$;\n//│       y = element0$1;\n//│       x = element0$;\n//│       tmp6 = x + y;\n//│       tmp7 = tmp6 + z;\n//│       return tmp7 + w\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   } else if (runtime.Tuple.isArrayLike(xs) && xs.length === 0) {\n//│     return 0\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nnested_tuple_patterns of [1, 2, 3, 4]\n//│ = 10\n\nfun hack(tupleSlice) = if tupleSlice is\n  [..tupleGet, x] then x\n\n:expect 4\nhack([1, 2, 3, 4])\n//│ = 4\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/SimpleTuple.mls",
    "content": ":js\n\n\n\nif [1, 1] is\n  [x, y] and x == y then \"equal\"\n//│ = \"equal\"\n\n\nfun sum(x, y) = x + y\nsum(1, 2)\n//│ = 3\n\n:fixme // TODO\nfun sum([x, y]) = x + y\nsum([1, 2])\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found tuple\n//│ ║  l.15: \tfun sum([x, y]) = x + y\n//│ ╙──      \t        ^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.15: \tfun sum([x, y]) = x + y\n//│ ╙──      \t                  ^\n//│ ╔══[COMPILATION ERROR] Name not found: y\n//│ ║  l.15: \tfun sum([x, y]) = x + y\n//│ ╙──      \t                      ^\n//│ ╔══[COMPILATION ERROR] Expected 0 arguments, got 1\n//│ ║  l.16: \tsum([1, 2])\n//│ ╙──      \t   ^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nfun sum(pair) =\n  if pair is [x, y] then x + y\nsum([1, 2])\n//│ = 3\n\nfun test(thing) =\n  if thing is [] then 0\n\n:re\ntest(\"\")\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\ntest(12)\n//│ ═══[RUNTIME ERROR] Error: match error\n\ndata class Point(x: Int, y: Int)\n\nfun with_other_constructors(thing) =\n  if thing is\n    [x, y] then x * y\n    Point(x, y) then x + y\n\n:expect 7\nwith_other_constructors(Point(3, 4))\n//│ = 7\n\n:expect 12\nwith_other_constructors([3, 4])\n//│ = 12\n\n// A workaround is to move the tuple pattern to the last case.\nfun with_other_constructors(thing) =\n  if thing is\n    Point(x, y) then x + y\n    [x, y] then x * y\n\n:expect 7\nwith_other_constructors(Point(3, 4))\n//│ = 7\n\n:expect 12\nwith_other_constructors([3, 4])\n//│ = 12\n\n\nfun with_else(x) =\n  if x is\n    [a, b, c] then\n      a + b + c\n    else\n      0\n\nwith_else([1, 2, 3])\n//│ = 6\n\nwith_else([1, 2])\n//│ = 0\n\nfun match_against_different_length(xs) =\n  if xs is\n    [] then 0\n    [x] then x + 1\n    [x, y] then x + y + 2\n    [x, y, z] then x + y + z + 3\n\n:expect 0\nmatch_against_different_length([])\n//│ = 0\n\n:expect 18\nmatch_against_different_length([17])\n//│ = 18\n\n:expect 22\nmatch_against_different_length([9, 11])\n//│ = 22\n\n:expect 42\nmatch_against_different_length([13, 13, 13])\n//│ = 42\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option\n\nfun with_the_common_prefix(xs) =\n  if xs is\n    [Some(x)] then x + 1\n    [None] then 0\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/SpreadTrailingIndex.mls",
    "content": ":js\n\n// Regression test: spread destructuring with different trailing sizes should\n// correctly index elements from the end of the array.\n\nfun go(stack) = if stack is\n  [..stack, \"+\", \"+\"] then 0\n  [..stack2, Str] then 1\n  else print(\"Str??\", stack is [..stack2, Str])\n\ngo([1, 2, \"z\"])\n//│ = 1\n\n// When the last two elements are \"+\", branch 0 matches\ngo([1, \"+\", \"+\"])\n//│ = 0\n\n// Fallback to else branch\ngo([1, 2, 3])\n//│ > Str?? false\n\n// Single element array\ngo([\"hello\"])\n//│ = 1\n\n// Same with `...` (spread rest)\nfun go2(stack) = if stack is\n  [...stack, \"+\", \"+\"] then 0\n  [...stack2, Str] then 1\n  else 2\n\ngo2([1, 2, \"z\"])\n//│ = 1\n\ngo2([1, \"+\", \"+\"])\n//│ = 0\n\ngo2([1, 2, 3])\n//│ = 2\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/String.mls",
    "content": ":js\n\nfun parseIntegerSimple(str) = if str is\n  \"0x\" ~ body then parseInt(body, 16)\n  \"0b\" ~ body then parseInt(body, 2)\n  \"0o\" ~ body then parseInt(body, 8)\n  else parseInt(str, 10)\n\n:expect 65535\nparseIntegerSimple(\"0xFFFF\")\n//│ = 65535\n\n:expect 255\nparseIntegerSimple(\"0b11111111\")\n//│ = 255\n\n:expect 4095\nparseIntegerSimple(\"0o7777\")\n//│ = 4095\n\n:expect 7777\nparseIntegerSimple(\"07777\")\n//│ = 7777\n\nfun trimStart(str) = if str is (\" \" | \"\\t\") ~ rest then trimStart(rest) else str\n\n:expect \"up\"\ntrimStart of \"       up\"\n//│ = \"up\"\n\n:expect \"\"\ntrimStart of \"\"\n//│ = \"\"\n\n:expect \"hello\"\ntrimStart of \"\\thello\"\n//│ = \"hello\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/patterns/where.mls",
    "content": ":js\n\ndata class Pair[A, B](fst: A, snd: B)\n\n\nfun orderedPair(p) = p is\n  Pair(a, b) where a <= b\n\norderedPair(Pair(4, 5))\n//│ = true\n\norderedPair(4)\n//│ = false\n\norderedPair(Pair(1, 1))\n//│ = true\n\norderedPair(Pair(2, 1))\n//│ = false\n\n\nfun foo(p) = p is\n  Pair(a, b) where\n    let c = a\n    a == 0\n\nfoo(Pair(5, 5))\n//│ = false\n\nfoo(Pair(0, 0))\n//│ = true\n\nfoo(Pair(0, 4))\n//│ = true\n\nfoo(Pair(4, 0))\n//│ = false\n\n\n// Should we report `a` and `b` as inconsistent variables?\nfun bar(p) = p is\n  (Pair(a, b) where a > b) | Int\n\nbar(4)\n//│ = true\n\nbar(Pair(4, 5))\n//│ = false\n\nbar(Pair(4, 3))\n//│ = true\n\n\n:e\nfun baz(p) = p is\n  (Pair(a, b) | Int) where a > b\n//│ ╔══[COMPILATION ERROR] Name not found: a\n//│ ║  l.56: \t  (Pair(a, b) | Int) where a > b\n//│ ╙──      \t                           ^\n//│ ╔══[COMPILATION ERROR] Name not found: b\n//│ ║  l.56: \t  (Pair(a, b) | Int) where a > b\n//│ ╙──      \t                               ^\n\n\npattern Positive = ((Int as x) where x > 0) => x\n\n0 is Positive\n//│ = false\n\n1 is Positive\n//│ = true\n\n\npattern OrderedPair = (Pair(a, b) where a < b) => b - a\n\n:expect true\nPair(1, 2) is OrderedPair as 1\n//│ = true\n\n:expect false\nPair(3, 2) is OrderedPair\n//│ = false\n\n:expect true\nPair(42, 96) is OrderedPair as 54\n//│ = true\n\n\npattern OrderedPairLike = (Pair(a, b) | [a, b] where a < b) => b - a\n\n:expect [true, false, true]\ntuple of\n  Pair(1, 2) is OrderedPairLike as 1\n  Pair(3, 2) is OrderedPairLike\n  Pair(42, 96) is OrderedPairLike as 54\n//│ = [true, false, true]\n\n:expect [true, false, true]\ntuple of\n  [1, 2] is OrderedPairLike as 1\n  [3, 2] is OrderedPairLike\n  [42, 96] is OrderedPairLike as 54\n//│ = [true, false, true]\n\n\n:fixme // TODO\nfun get(p, m) = if p is\n  Pair(k, v) where m.get(k) is w then v === w\n  else false\n//│ ╔══[COMPILATION ERROR] Name not found: w\n//│ ║  l.108: \t  Pair(k, v) where m.get(k) is w then v === w\n//│ ╙──       \t                                            ^\n\n:fixme // TODO?\nfun get(p, m) =\n  p is Pair(k, v) where m.get(k) is w and v === w\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'where' here\n//│ ║  l.116: \t  p is Pair(k, v) where m.get(k) is w and v === w\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:fixme // TODO?\nfun get(p, m) =\n  p is Pair(k, v) where m.get(k) is w where v === w\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'where' here\n//│ ║  l.123: \t  p is Pair(k, v) where m.get(k) is w where v === w\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\nlet m0 = {get: _ + 1}\n//│ m0 = {get: fun get}\n\n\nclass C1(m) with\n  pattern P = Pair(k, v) where m.get(k) is w and v === w\n\nC1(m0).P.unapply(Pair(3, 4))\n//│ = MatchSuccess(Pair(3, 4), null)\n\nC1(m0).P.unapply(Pair(3, 5))\n//│ = MatchFailure(null)\n\n\n:e\nclass C2(m) with\n  pattern P = Pair(k, v) where m.get(k) is w where v === w\n//│ ╔══[COMPILATION ERROR] Name not found: w\n//│ ║  l.145: \t  pattern P = Pair(k, v) where m.get(k) is w where v === w\n//│ ╙──       \t                                                         ^\n\n:re\nC2(m0).P.unapply(Pair(3, 4))\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:re\nC2(m0).P.unapply(Pair(3, 5))\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\nclass C3(m) with\n  pattern P = Pair(k, v) where m.get(k) is (w where v === w)\n\nC3(m0).P.unapply(Pair(3, 4))\n//│ = MatchSuccess(Pair(3, 4), null)\n\nC3(m0).P.unapply(Pair(3, 5))\n//│ = MatchFailure(null)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/Unapply.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int, z: Int)\n//│ class Point(x: Int, y: Int, z: Int)\n\nfun f_0(p) = if p is Point(x, _, z) then x + z\n//│ fun f_0: Point -> Int\n\nf_0(Point(1, 2, 3))\n//│ Int\n//│ res\n//│     = 4\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/ConflictedCoveredCases.mls",
    "content": ":NewDefs\n\nclass A()\nclass B() extends A()\n//│ class A()\n//│ class B() extends A\n\nfun p(x) = true\n//│ fun p: anything -> true\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is B and\n    x is A then 1\n  x is A then 31\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   B*◊ -> 1\n//│   _ ->\n//│     case x*‡ of\n//│       A*◊ -> 31\n//│ ╔══[WARNING] the pattern always matches\n//│ ║  l.15: \t    x is A then 1\n//│ ║        \t         ^\n//│ ╟── the scrutinee was matched against B\n//│ ║  l.14: \t  x is B and\n//│ ║        \t       ^\n//│ ╟── which is a subtype of A\n//│ ║  l.4: \tclass B() extends A()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^\n//│ fun f: (A & ~#B | B) -> (1 | 31)\n\n// FIXME: wrong missing cases\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is 1 and\n    x is Int then true\n  x is 2 then false\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   1 -> true\n//│   _ ->\n//│     case x*‡ of\n//│       2 -> false\n//│ ╔══[WARNING] the pattern always matches\n//│ ║  l.39: \t    x is Int then true\n//│ ║        \t         ^^^\n//│ ╟── the scrutinee was matched against 1\n//│ ║  l.38: \t  x is 1 and\n//│ ║        \t       ^\n//│ ╟── which is a subtype of Int\n//│ ║  l.39: \t    x is Int then true\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] `x` has 1 missing case\n//│ ║  l.38: \t  x is 1 and\n//│ ║        \t  ^\n//│ ╟── it can be class `Int`\n//│ ║  l.39: \t    x is Int then true\n//│ ╙──      \t         ^^^\n//│ fun f: (1 | 2) -> Bool\n\n:w\nfun f(x) = if\n  x is B and\n    x is A then 1\n    p(x) then 2\n  x is A then 31\n  x is B then 3\n  else 4\n//│ ╔══[WARNING] the pattern always matches\n//│ ║  l.67: \t    x is A then 1\n//│ ║        \t         ^\n//│ ╟── the scrutinee was matched against B\n//│ ║  l.66: \t  x is B and\n//│ ║        \t       ^\n//│ ╟── which is a subtype of A\n//│ ║  l.4: \tclass B() extends A()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^\n//│ fun f: (B | Object & ~#B) -> (1 | 31 | 4)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/ConflictedPatterns.mls",
    "content": ":NewDefs\n\n// This test file contains the cases where inner cases are conflicting with outer cases.\n\nclass X\nclass Y\nclass Z\n//│ class X {\n//│   constructor()\n//│ }\n//│ class Y {\n//│   constructor()\n//│ }\n//│ class Z {\n//│   constructor()\n//│ }\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and x is Y then 1\n  else 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 2\n//│   _ -> 2\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.21: \t  x is X and x is Y then 1\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.21: \t  x is X and x is Y then 1\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.21: \t  x is X and x is Y then 1\n//│ ╙──      \t                  ^\n//│ fun f: Object -> 2\n\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and\n    x is Y then 1\n    x is Y then 2\n  else 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 3\n//│   _ -> 3\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.42: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.42: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.43: \t    x is Y then 1\n//│ ╙──      \t         ^\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.42: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.42: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.44: \t    x is Y then 2\n//│ ╙──      \t         ^\n//│ fun f: Object -> 3\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and\n    x is Y then 1\n    x is Z then 2\n  else 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 3\n//│   _ -> 3\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.73: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.73: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.74: \t    x is Y then 1\n//│ ╙──      \t         ^\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.73: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.73: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Z\n//│ ║  l.75: \t    x is Z then 2\n//│ ╙──      \t         ^\n//│ fun f: Object -> 3\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and\n    x is Y and\n      x is Z then 1\n  else 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 2\n//│   _ -> 2\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.104: \t  x is X and\n//│ ║         \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.104: \t  x is X and\n//│ ║         \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.105: \t    x is Y and\n//│ ╙──       \t         ^\n//│ fun f: Object -> 2\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/CoveredCases.mls",
    "content": ":NewDefs\n\n// This test file contains the cases where latter cases are covered by the former cases.\n\n// B <: A\nclass A()\nclass B() extends A()\n//│ class A()\n//│ class B() extends A\n\n:w\nfun f(x) = if\n  x is A then 1\n  x is A then 2\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.14: \t  x is A then 2\n//│ ║        \t       ^\n//│ ╟── there is an identical pattern A\n//│ ║  l.13: \t  x is A then 1\n//│ ╙──      \t       ^\n//│ fun f: A -> 1\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is A then 1\n  x is B then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   A*◊ -> 1\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.27: \t  x is B then 2\n//│ ║        \t       ^\n//│ ╟── the case is covered by pattern A\n//│ ║  l.26: \t  x is A then 1\n//│ ║        \t       ^\n//│ ╟── due to the subtyping relation\n//│ ║  l.7: \tclass B() extends A()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^\n//│ fun f: A -> 1\n\n:ducs:normalize.result\nfun f(x) = if\n  x is A and\n    x is B then 1\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined A*◊ ->\n//│     case x*‡ of\n//│       B*◊ -> 1\n//│ fun f: B -> 1\n\n// :w\n// FIXME\n:ducs:normalize.result\nfun f(x) = if\n  x is A and\n    x is B then 1\n  x is B then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined A*◊ ->\n//│     case x*‡ of\n//│       B*◊ -> 1\n//│ fun f: B -> 1\n\nfun p(x) = true: Bool\n//│ fun p: anything -> Bool\n\n// :w\n// FIXME\n:ducs:normalize.result\nfun f(x) = if\n  x is A and\n    x is B then 1\n    p(x) then 2\n  x is B then 3\n  else 4\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined A*◊ ->\n//│     case x*‡ of\n//│       B*◊ -> 1\n//│       _ ->\n//│         let ucs$test$0*† = p(x,) : Bool\n//│         case ucs$test$0*† of\n//│           true*† -> 2\n//│           _ -> 4\n//│   _ -> 4\n//│ fun f: Object -> (1 | 2 | 4)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/DuplicatedCases.mls",
    "content": ":NewDefs\n\n// This test file contains the cases containing cases with identical patterns.\n\n:w\n:ducs:normalize.result\nfun f(x) = if x is\n  \"a\" then 1\n  \"b\" then 2\n  \"a\" then 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   \"a\" -> 1\n//│   _ ->\n//│     case x*‡ of\n//│       \"b\" -> 2\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.10: \t  \"a\" then 3\n//│ ║        \t  ^^^\n//│ ╟── there is an identical pattern \"a\"\n//│ ║  l.8: \t  \"a\" then 1\n//│ ╙──     \t  ^^^\n//│ fun f: (\"a\" | \"b\") -> (1 | 2)\n\nclass X\nclass Y\n//│ class X {\n//│   constructor()\n//│ }\n//│ class Y {\n//│   constructor()\n//│ }\n\n:w\n:ducs:normalize.result\nfun f(x) = if x is\n  X then 1\n  X then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 1\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.38: \t  X then 2\n//│ ║        \t  ^\n//│ ╟── there is an identical pattern X\n//│ ║  l.37: \t  X then 1\n//│ ╙──      \t  ^\n//│ fun f: X -> 1\n\n:w\n:ducs:normalize.result\nfun f(x) = if x is\n  X then 1\n  Y then 2\n  X then 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 1\n//│   _ ->\n//│     case x*‡ of\n//│       Y*◊ -> 2\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.55: \t  X then 3\n//│ ║        \t  ^\n//│ ╟── there is an identical pattern X\n//│ ║  l.53: \t  X then 1\n//│ ╙──      \t  ^\n//│ fun f: (X | Y) -> (1 | 2)\n\nclass Box[T](value: T)\n//│ class Box[T](value: T)\n\n:ducs:normalize.result\nfun f(x) = if x is\n  Box(1) then true\n  Box then false\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Box*◊ ->\n//│     let ucs$args_x$Box*† = (Box).unapply(x,)\n//│     let x$Box_0*‡ = (ucs$args_x$Box).0\n//│     case x$Box_0*‡ of\n//│       1 -> true\n//│       _ -> false\n//│ fun f: Box[Object] -> Bool\n\nf(Box(0))\nf(Box(1))\n//│ Bool\n//│ res\n//│     = false\n//│ res\n//│     = true\n\n:ducs:postprocess.result\nfun a_tale_of_scrutinees(x, y) =\n  if\n    x is \"A\" and y is \"B\" then \"AB\"\n    y is \"A\" and x is \"B\" then \"BA\"\n    y is \"A\" and x is \"A\" then \"AA\"\n    x is \"B\" and y is \"B\" then \"BB\"\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   \"A\" ->\n//│     case y*‡ of\n//│       \"B\" -> \"AB\"\n//│       \"A\" -> \"AA\"\n//│   \"B\" ->\n//│     case y*‡ of\n//│       \"A\" -> \"BA\"\n//│       \"B\" -> \"BB\"\n//│ fun a_tale_of_scrutinees: (\"A\" | \"B\", \"A\" | \"B\") -> (\"AA\" | \"AB\" | \"BA\" | \"BB\")\n\n:ducs:normalize.result\nfun test(x, p) = if x is\n  Bool and p(x) then \"great\"\n  true then \"false\"\n  false then \"true\"\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined Bool*◊ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> \"great\"\n//│       _ ->\n//│         case x*‡ of\n//│           true*† -> \"false\"\n//│           _ ->\n//│             case x*‡ of\n//│               false*† -> \"true\"\n//│ fun test: forall 'a. ('a & Bool, (Bool & 'a) -> Bool) -> (\"false\" | \"great\" | \"true\")\n\nclass P[A](x: A)\nclass Q[A, B](x: A, y: B)\n//│ class P[A](x: A)\n//│ class Q[A, B](x: A, y: B)\n\nfun f(x) =\n  if x is\n    P(1) then 1\n    P(y) then 2\n//│ fun f: P[Object] -> (1 | 2)\n\n:ducs:normalize.result\nfun f(x) =\n  if x is\n    Q(a, b) and a is 1 and b is 1 then 1\n    Q(a, b) and b is 1 then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Q*◊ ->\n//│     let ucs$args_x$Q*† = (Q).unapply(x,)\n//│     let a*‡ = (ucs$args_x$Q).0\n//│     let b*‡ = (ucs$args_x$Q).1\n//│     case a*‡ of\n//│       1 ->\n//│         case b*‡ of\n//│           1 -> 1\n//│       _ ->\n//│         case b*‡ of\n//│           1 -> 2\n//│ fun f: Q[Object, 1] -> (1 | 2)\n\n:e\nfun f(x) =\n  if x is\n    Q(a, b) and a is 1 and b is 2 then 1\n    Q(a, b) and b is 1 then 2\n//│ ╔══[ERROR] when `x` is `Q`\n//│ ║  l.167: \t    Q(a, b) and a is 1 and b is 2 then 1\n//│ ║         \t    ^\n//│ ╟── the second argument of `Q` has 1 missing case\n//│ ║  l.168: \t    Q(a, b) and b is 1 then 2\n//│ ║         \t                ^\n//│ ╟── it can be literal 2\n//│ ║  l.167: \t    Q(a, b) and a is 1 and b is 2 then 1\n//│ ╙──       \t                                ^\n//│ fun f: Q[Object, 1] -> (1 | 2)\n\n:ducs:normalize.result\nfun f(x) =\n  if x is\n    Q(1, 1) then 1\n    Q(y, 1) then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Q*◊ ->\n//│     let ucs$args_x$Q*† = (Q).unapply(x,)\n//│     let x$Q_0*‡ = (ucs$args_x$Q).0\n//│     let x$Q_1*‡ = (ucs$args_x$Q).1\n//│     case x$Q_0*‡ of\n//│       1 ->\n//│         case x$Q_1*‡ of\n//│           1 -> 1\n//│           _ -> (ucs$args_x$Q).0\n//│       _ ->\n//│         let y*‡ = (ucs$args_x$Q).0\n//│         case x$Q_1*‡ of\n//│           1 -> 2\n//│ fun f: forall 'a. Q[Object & 'a, 1] -> (1 | 2 | 'a)\n\nfun f(x) =\n  if x is\n    Q(0, 0) then 1\n    Q(1, 1) then 2\n    Q(y, 1) then 3\n    _       then 4\n//│ fun f: (Object & ~#Q | Q[Object, Object]) -> (1 | 2 | 3 | 4)\n\nfun f(x) =\n  if x is\n    P(P(P(1))) then 1\n    P(P(1)) then 2\n    P(1) then 3\n//│ fun f: P[1 | P[1 | P[1]]] -> (1 | 2 | 3)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/MissingCases.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\nclass Pair[A, B](x: A, y: B)\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n//│ class Pair[A, B](x: A, y: B)\n\nfun good_add_1(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n//│ fun good_add_1: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\n:e\nfun bad_add_missing_SS(x, y) =\n  if\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.23: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.23: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.24: \t    x is None     and y is Some(yv) then yv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_SS: forall 'a. (None | Some['a], None) -> (0 | 'a)\n\n:e\nfun bad_add_missing_SN(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.40: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.40: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║        \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.42: \t    x is None     and y is None     then 0\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_SN: forall 'a. (None | Some[Int], Some[Int & 'a]) -> (Int | 'a)\n\n:e\nfun bad_add_missing_NS(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.59: \t    x is None     and y is None     then 0\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.59: \t    x is None     and y is None     then 0\n//│ ║        \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.57: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_NS: (None | Some[Int], None) -> Int\n\n:e\nfun bad_add_missing_NN(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.76: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.76: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.75: \t    x is Some(xv) and y is None     then xv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_NN: forall 'a. (None | Some[Int], Some[Int & 'a]) -> (Int | 'a)\n\n:e\nfun bad_add_missing_SS_NN(x, y) =\n  if\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.91: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.91: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.92: \t    x is None     and y is Some(yv) then yv\n//│ ╙──      \t                           ^^^^\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.92: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.92: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.91: \t    x is Some(xv) and y is None     then xv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_SS_NN: forall 'a. (None | Some['a], nothing) -> 'a\n\n:e\nfun bad_add_missing_SN_NS(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.116: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║         \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.116: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║         \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.117: \t    x is None     and y is None     then 0\n//│ ╙──       \t                           ^^^^\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.117: \t    x is None     and y is None     then 0\n//│ ║         \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.117: \t    x is None     and y is None     then 0\n//│ ║         \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.116: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──       \t                           ^^^^\n//│ fun bad_add_missing_SN_NS: (None | Some[Int], nothing) -> Int\n\nfun actually_fine_add(x, y) =\n  if\n    x is Some(xv) and y is None then xv\n//│ fun actually_fine_add: forall 'a. (Some['a], None) -> 'a\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/Refinement.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int)\nabstract class Shape: (Circle | Rectangle | LineSegment)\nclass Circle(center: Point, radius: Int) extends Shape\nclass Rectangle(position: Point, width: Int, height: Int) extends Shape\nclass LineSegment(start: Point, end: Point) extends Shape\n//│ class Point(x: Int, y: Int)\n//│ abstract class Shape: Circle | LineSegment | Rectangle\n//│ class Circle(center: Point, radius: Int) extends Shape\n//│ class Rectangle(position: Point, width: Int, height: Int) extends Shape\n//│ class LineSegment(start: Point, end: Point) extends Shape\n\nfun hidden(p) = if p is Circle then true else false\n//│ fun hidden: Object -> Bool\n\nfun this_is_sealed(x: Shape) =\n  if x is\n    Circle(_, _) then \"Circle\"\n    Rectangle(_, _, _) then \"Rectangle\"\n    LineSegment(_, _) then \"LineSegment\"\n//│ fun this_is_sealed: (x: Shape) -> (\"Circle\" | \"LineSegment\" | \"Rectangle\")\n\n// The error message here makes some sense right now.\n:e\nfun missing_a_case(x: Shape) =\n  if x is\n    Circle(_, _) then \"Circle\"\n    Rectangle(_, _, _) then \"Rectangle\"\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.27: \t  if x is\n//│ ║        \t     ^^^^\n//│ ║  l.28: \t    Circle(_, _) then \"Circle\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.29: \t    Rectangle(_, _, _) then \"Rectangle\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Circle | LineSegment | Rectangle` does not match type `Circle | Rectangle`\n//│ ║  l.26: \tfun missing_a_case(x: Shape) =\n//│ ║        \t                      ^^^^^\n//│ ╟── but it flows into reference with expected type `Circle | Rectangle`\n//│ ║  l.27: \t  if x is\n//│ ╙──      \t     ^\n//│ fun missing_a_case: (x: Shape) -> (\"Circle\" | \"Rectangle\")\n\nfun missing_a_case(x: Shape) =\n  if x is\n    Circle(_, _) then \"Circle\"\n    Rectangle(_, _, _) then \"Rectangle\"\n    else x\n//│ fun missing_a_case: (x: Shape) -> (\"Circle\" | \"Rectangle\" | LineSegment)\n\nfun countLineSegments(x) =\n  if x is\n    Shape and hidden(x) then \"1\"\n    Rectangle(_, _, _) then \"2\"\n    LineSegment(_, _) then \"3\"\n    Circle(_, _) then \"4\"\n//│ fun countLineSegments: (Circle | LineSegment | Rectangle) -> (\"1\" | \"2\" | \"3\" | \"4\")\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/SealedClasses.mls",
    "content": ":NewDefs\n\nabstract class Term: Abs | App | Var\nclass Var(name: Str) extends Term\nclass Abs(param: Str, body: Term) extends Term\nclass App(func: Term, arg: Term) extends Term\n//│ abstract class Term: Abs | App | Var\n//│ class Var(name: Str) extends Term\n//│ class Abs(param: Str, body: Term) extends Term\n//│ class App(func: Term, arg: Term) extends Term\n\n:ducs:desugar.result\nfun is_value_explicit_refinement(term) =\n  if term is refined(Term) and term is\n    Abs(_, _) then true\n    Var(_) then false\n    App(_, _) then false\n//│ Desugared UCS term:\n//│ if term*‡ is refined Term\n//│   term*‡ is Abs then true\n//│   term*‡ is Var then false\n//│   term*‡ is App then false\n//│ fun is_value_explicit_refinement: (Abs | App | Var) -> Bool\n\n:ducs:normalize.result,postprocess.result\nfun is_value_automatic_refinement(term) =\n  if term is Term and term is\n    Abs(_, _) then true\n    Var(_) then false\n    App(_, _) then false\n//│ Normalized UCS term:\n//│ case term*‡ of\n//│   refined Term*◊ ->\n//│     case term*‡ of\n//│       Abs*◊ -> true\n//│       _ ->\n//│         case term*‡ of\n//│           Var*◊ -> false\n//│           _ ->\n//│             case term*‡ of\n//│               App*◊ -> false\n//│ Post-processed UCS term:\n//│ case term*‡ of\n//│   refined Term*◊ ->\n//│     case term*‡ of\n//│       Abs*◊ -> true\n//│       Var*◊ -> false\n//│       App*◊ -> false\n//│ fun is_value_automatic_refinement: (Abs | App | Var) -> Bool\n\nfun is_value'(term) =\n  if term is Term and term is\n    Abs(_, _) then true\n    Var(_) then false\n//│ fun is_value': (Abs | Var) -> Bool\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/Tautology.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\nclass Pair[A, B](x: A, y: B)\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n//│ class Pair[A, B](x: A, y: B)\n\nfun useless_negate_1(x) =\n  if\n    x is Some(y) and x is Some(z) then y + z\n//│ fun useless_negate_1: Some[Int] -> Int\n\nuseless_negate_1(Some(1))\n//│ Int\n//│ res\n//│     = 2\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/coverage/Unreachable.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\nclass Pair[A, B](x: A, y: B)\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n//│ class Pair[A, B](x: A, y: B)\n\nfun f(x) = if x is Some(xv) and xv === 1 then true else false\n//│ fun f: (Object & ~#Some | Some[Eql[1]]) -> Bool\n\nf(Some(1))\nf(Some(2))\nf(None)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n\nfun reachable_1(x) =\n  if x is\n    _ and f(x) then \"cos\"\n    Some(xv) then \"sin\"\n    None then \"tan\"\n//│ fun reachable_1: (None | Some[anything] & ~#Some | Some[Eql[1]]) -> (\"cos\" | \"sin\" | \"tan\")\n\nreachable_1(Some(1))\nreachable_1(Some(2))\nreachable_1(None)\n//│ \"cos\" | \"sin\" | \"tan\"\n//│ res\n//│     = 'cos'\n//│ res\n//│     = 'sin'\n//│ res\n//│     = 'tan'\n\n:w\nfun unreachable_1(x) =\n  if x is\n    _ and\n      f(x) then \"tmux\"\n      else \"screen\"\n    Some(xv) then \"sin\"\n    None then \"tan\"\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.46: \t  if x is\n//│ ║        \t     ^^^^\n//│ ║  l.47: \t    _ and\n//│ ║        \t^^^^^^^^^\n//│ ║  l.48: \t      f(x) then \"tmux\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.49: \t      else \"screen\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.50: \t    Some(xv) then \"sin\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.51: \t    None then \"tan\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.49: \t      else \"screen\"\n//│ ╙──      \t           ^^^^^^^^\n//│ fun unreachable_1: (Object & ~#Some | Some[Eql[1]]) -> (\"screen\" | \"tmux\")\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/edges/Unconditional.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int)\nclass Rectangle(x: Int, y: Int, width: Int, height: Int)\n//│ class Point(x: Int, y: Int)\n//│ class Rectangle(x: Int, y: Int, width: Int, height: Int)\n\nfun sum(p) = if p is Point(x, y) then x + y\n//│ fun sum: Point -> Int\n\nsum(Point(1, 2))\n//│ Int\n//│ res\n//│     = 3\n\nfun abs(x) = if x < 0 then -x else x\n//│ fun abs: Int -> Int\n\nfun dist(p, q) = if p is Point(x1, y1) and q is Point(x2, y2) then\n  abs(x1 - x2) + abs(y1 - y2)\n//│ fun dist: (Point, Point) -> Int\n\ndist(Point(1, 2), Point(3, 4))\n//│ Int\n//│ res\n//│     = 4\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/AVLTree.mls",
    "content": ":NewDefs\n\nfun (|>) pipe(x, f) = f(x)\nfun (~~>) toBe(x, y) = if x === y then () else error\nfun (<?) min(x, y) = if x < y then x else y\nfun (>?) max(x, y) = if x > y then x else y\nfun abs(x) = if x < 0 then -x else x\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (~~>) toBe: forall 'c. (Eql['c], 'c) -> ()\n//│ fun (<?) min: forall 'd. (Num & 'd, Num & 'd) -> 'd\n//│ fun (>?) max: forall 'e. (Num & 'e, Num & 'e) -> 'e\n//│ fun abs: Int -> Int\n\nabstract class Option[out T]: (Some[T] | None)\nclass Some[out T](val value: T) extends Option[T]\nmodule None extends Option[nothing]\n//│ abstract class Option[T]: None | Some[T]\n//│ class Some[T](value: T) extends Option\n//│ module None extends Option\n\nfun (??) getOrElse(o, v) = if o is\n  Some(v') then v'\n  None then v\n//│ fun (??) getOrElse: forall 'a. (None | Some['a], 'a) -> 'a\n\nfun (++) strcat(s1, s2) = concat(s1)(s2)\n//│ fun (++) strcat: (Str, Str) -> Str\n\nlet anyToString = toString\n//│ let anyToString: anything -> Str\n//│ anyToString\n//│             = [Function: toString]\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List[nothing]\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\nabstract class Tree[out A]: (Empty | Node[A])\nclass Node[out A](value: A, left: Tree[A], right: Tree[A], height: Int) extends Tree[A]\nmodule Empty extends Tree[nothing]\n//│ abstract class Tree[A]: Empty | Node[A]\n//│ class Node[A](value: A, left: Tree[A], right: Tree[A], height: Int) extends Tree\n//│ module Empty extends Tree\n\nfun showTree(t: Tree[anything]): Str = if t is\n  Node(v, l, r, _) then\n    \"(\" ++ showTree(l) ++ \" \" ++ toString(v) ++ \" \" ++ showTree(r) ++ \")\"\n  Empty then \"•\"\n//│ fun showTree: (t: Tree[anything]) -> Str\n\nfun showTreeWithHeight(t: Tree[anything]): Str = if t is\n  Node(v, l, r, h) then\n    \"(\" ++ showTreeWithHeight(l) ++ \" \" ++ toString(v) ++ \" [\" ++ toString(h) ++ \"]\" ++ \" \" ++ showTreeWithHeight(r) ++ \")\"\n  Empty then \"•\"\n//│ fun showTreeWithHeight: (t: Tree[anything]) -> Str\n\nfun height(t) =\n  if t is\n    Node(_, _, _, h) then h\n    Empty then 0\n//│ fun height: (Empty | Node[anything]) -> Int\n\nlet nil = Empty\nfun node(v, l, r) = Node(v, l, r, max(height(l), height(r)) + 1)\nfun single(v) = Node(v, Empty, Empty, 1)\n//│ let nil: Empty\n//│ fun node: forall 'A. ('A, Empty & Tree['A] | Node[anything] & Tree['A], Empty & Tree['A] | Node[anything] & Tree['A]) -> Node['A]\n//│ fun single: forall 'A0. 'A0 -> Node['A0]\n//│ nil\n//│     = Empty { class: [class Empty extends Tree] }\n\nfun isBalanced(t) =\n  if t is\n    Node(t, l, r, _) then\n      (abs(height(l) - height(r)) <= 1) && isBalanced(l) && isBalanced(r)\n    Empty then true\n//│ fun isBalanced: (Empty | Node[anything]) -> Bool\n\nisBalanced(nil) ~~> true\n//│ ()\n//│ res\n//│     = undefined\n\n//      _             _                    _        _\n//  ___(_)_ __   __ _| | ___     _ __ ___ | |_ __ _| |_ ___\n// / __| | '_ \\ / _` | |/ _ \\   | '__/ _ \\| __/ _` | __/ _ \\\n// \\__ \\ | | | | (_| | |  __/   | | | (_) | || (_| | ||  __/\n// |___/_|_| |_|\\__, |_|\\___|   |_|  \\___/ \\__\\__,_|\\__\\___|\n//              |___/\n\nfun rotateLeft(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, l, Node(v', l', r', _), _) and\n      max(height(l), height(l')) + 1 is h and\n        max(h, height(r')) + 1 is h' then\n          Node(v', Node(v, l, l', h), r', h')\n    _ then t\n//│ fun rotateLeft: forall 'A. (t: Tree['A]) -> Tree['A]\n\nrotateLeft(nil) |> showTree\nrotateLeft(single(0)) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n\nlet unbalanced1 = node(0, nil, node(1, nil, single(2)))\nisBalanced(unbalanced1) ~~> false\nunbalanced1 |> showTree\nrotateLeft(unbalanced1) |> showTree\n//│ let unbalanced1: Node[0 | 1 | 2]\n//│ Str\n//│ unbalanced1\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n//│ res\n//│     = '((• 0 •) 1 (• 2 •))'\n\nfun rotateRight(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, Node(v', l', r', _), r, _) then\n      Node(v', l', Node(v, r', r, 0), 0)\n    _ then t\n//│ fun rotateRight: forall 'A. (t: Tree['A]) -> Tree['A]\n\nrotateRight(nil) |> showTree\nrotateRight(single(0)) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n\nlet unbalanced2 = node(2, node(1, single(0), nil), nil)\nisBalanced(unbalanced2) ~~> false\nunbalanced2 |> showTree\nrotateRight(unbalanced2) |> showTree\n//│ let unbalanced2: Node[0 | 1 | 2]\n//│ Str\n//│ unbalanced2\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '(((• 0 •) 1 •) 2 •)'\n//│ res\n//│     = '((• 0 •) 1 (• 2 •))'\n\n//      _             _     _                    _        _\n//   __| | ___  _   _| |__ | | ___     _ __ ___ | |_ __ _| |_ ___\n//  / _` |/ _ \\| | | | '_ \\| |/ _ \\   | '__/ _ \\| __/ _` | __/ _ \\\n// | (_| | (_) | |_| | |_) | |  __/   | | | (_) | || (_| | ||  __/\n//  \\__,_|\\___/ \\__,_|_.__/|_|\\___|   |_|  \\___/ \\__\\__,_|\\__\\___|\n//\n\nfun rotateRightLeft(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, t1, Node(v', Node(v'', t2, t3, _), t4, _), _) then\n      Node(v'', Node(v, t1, t2, 0), Node(v', t3, t4, 0), 0)\n    else t\n//│ fun rotateRightLeft: forall 'A. (t: Tree['A]) -> Tree['A]\n\n// Should remain the same.\nrotateRightLeft(nil) |> showTree\nrotateRightLeft(single(0)) |> showTree\nrotateRightLeft(unbalanced1) |> showTree\nrotateRightLeft(unbalanced2) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n//│ res\n//│     = '(((• 0 •) 1 •) 2 •)'\n\nlet unbalanced3 = node(0, nil, node(3, node(1, nil, single(2)), nil))\nisBalanced(unbalanced3) ~~> false\nunbalanced3 |> showTree\nrotateRightLeft(unbalanced3) |> showTree\n//│ let unbalanced3: Node[0 | 1 | 2 | 3]\n//│ Str\n//│ unbalanced3\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '(• 0 ((• 1 (• 2 •)) 3 •))'\n//│ res\n//│     = '((• 0 •) 1 ((• 2 •) 3 •))'\n\nfun rotateLeftRight(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, Node(v', t1, Node(v'', t2, t3, _), _), t4, _) then\n      Node(v'', Node(v', t1, t2, 0), Node(v, t3, t4, 0), 0)\n    else t\n//│ fun rotateLeftRight: forall 'A. (t: Tree['A]) -> Tree['A]\n\n// Should remain the same.\nrotateLeftRight(nil) |> showTree\nrotateLeftRight(single(0)) |> showTree\nrotateLeftRight(unbalanced1) |> showTree\nrotateLeftRight(unbalanced2) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n//│ res\n//│     = '(((• 0 •) 1 •) 2 •)'\n\nlet unbalanced4 = node(3, node(0, nil, node(2, single(1), nil)), nil)\nisBalanced(unbalanced4) ~~> false\nunbalanced4 |> showTree\nrotateRightLeft(unbalanced4) |> showTree\n//│ let unbalanced4: Node[0 | 1 | 2 | 3]\n//│ Str\n//│ unbalanced4\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '((• 0 ((• 1 •) 2 •)) 3 •)'\n//│ res\n//│     = '((• 0 ((• 1 •) 2 •)) 3 •)'\n\nfun bf(t) =\n  if t is\n    Node(_, l, r, _) then height(l) - height(r)\n    Empty then 0\n//│ fun bf: (Empty | Node[anything]) -> Int\n\n//  _                     _\n// (_)_ __  ___  ___ _ __| |_\n// | | '_ \\/ __|/ _ \\ '__| __|\n// | | | | \\__ \\  __/ |  | |_\n// |_|_| |_|___/\\___|_|   \\__|\n//\n\n// This function does not work for now as it exposed a lot of problems we have\n// in desugaring and normalization. For example:\n// \n// - [x] We need to mark the Boolean scrutinees and skip the specialization of\n//   these scrutinees in the normalization process, otherwise, it would result\n//   in many futile computations.\n// - [x] We should cache the expressions that are broken by conditional splits,\n//   otherwise, they will be evaluated for more than one time.\n// - [ ] The branches of an operator split should be \"chained\" rather\n//   than placed in parallel, otherwise, the later branches will appear in the\n//   else branch of all its previous branches. **WORK IN PROGRESS**\n//\n// :ducs:postprocess\nfun balance(t: Tree['A]): Tree['A] =\n  if t is\n    Node(x, l, r, _) and height(r) - height(l)\n      > 1 and r is Node(y, l', r', _) and height(r') - height(l')\n        > 0 then rotateLeft(t)\n        < 0 and l' is Node then rotateRightLeft(t)\n      < 1 and l is Node(y, l', r', _) and height(r') - height(l')\n        > 0 and r' is Node then rotateLeftRight(t)\n        < 0 then rotateRight(t)\n    _ then t\n//│ fun balance: forall 'A. (t: Tree['A]) -> Tree['A]\n\nfun insert(t: Tree[Num], v: Num) = if t is\n  Node(v', l, r, h) and\n    v < v' then Node(v', insert(l, v), r, h) |> balance\n    v > v' then Node(v', l, insert(r, v), h) |> balance\n    _ then t\n  Empty then Node(v, Empty, Empty, 1)\n//│ fun insert: (t: Tree[Num], v: Num) -> (Node[Num] | Tree[Num])\n\n\ninsert(nil, 0) |> showTree\ninsert(single(0), 1) |> showTree\ninsert(single(0), -1) |> showTree\n//│ Str\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 (• 1 •))'\n//│ res\n//│     = '((• -1 •) 0 •)'\n\ninsert(node(0, nil, single(1)), 2) |> showTreeWithHeight\ninsert(node(0, nil, single(1)), 2) |> showTree\n//│ Str\n//│ res\n//│     = '(• 0 [2] (• 1 [1] (• 2 [1] •)))'\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n\ninsert(unbalanced1, 3) |> showTree\n//│ Str\n//│ res\n//│     = '((• 0 •) 1 (• 2 (• 3 •)))'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/Calculator.mls",
    "content": ":NewDefs\n\n// This test file explores implementing a calculator using UCS.\n\nfun (++) concatOp(a, b) = concat(a)(b)\nfun (|>) pipe(a, f) = f(a)\nfun (!==) notEqual(x, y) = not(x === y)\nlet anyToString = toString\n//│ fun (++) concatOp: (Str, Str) -> Str\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (!==) notEqual: forall 'c. (Eql['c], 'c) -> Bool\n//│ let anyToString: anything -> Str\n//│ anyToString\n//│             = [Function: toString]\n\nfun par(s, p) = if p then \"(\" ++ s ++ \")\" else s\n//│ fun par: (Str, Bool) -> Str\n\ntype StringOps = {\n  length: Int,\n  charAt: Int => Str,\n  charCodeAt: Int => Int,\n  slice: Int => Str\n}\ndeclare fun String: nothing\nlet toStringOps: anything => StringOps = String\n//│ type StringOps = {charAt: Int -> Str, charCodeAt: Int -> Int, length: Int, slice: Int -> Str}\n//│ let toStringOps: anything -> StringOps\n//│ fun String: nothing\n//│ toStringOps\n//│             = [Function: String]\n\ntype Option[A] = Some[A] | None\nclass Some[A](value: A)\nmodule None\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A)\n//│ module None\n\nfun showOption(x) = if x is\n  Some(value) then \"Some(\" ++ toString(value) ++ \")\"\n  None then \"None\"\nfun mapOption(f, x) = if x is\n  Some(value) then Some(f(value))\n  None then None\nfun (??) getOrElse(x, default) = if x is\n  Some(value) then value\n  None then default\nfun flatten(x) = if x is\n  Some(value) then value\n  other then other\n//│ fun showOption: (None | Some[anything]) -> Str\n//│ fun mapOption: forall 'a 'A. ('a -> 'A, None | Some['a]) -> (None | Some['A])\n//│ fun (??) getOrElse: forall 'b. (None | Some['b], 'b) -> 'b\n//│ fun flatten: forall 'c. (Object & 'c & ~#Some | Some['c]) -> 'c\n\ntype List[A] = Cons[A] | Nil\nclass Cons[A](head: A, tail: List[A])\nmodule Nil\nfun (::) cons(head, tail) = Cons(head, tail)\nfun reverse(xs) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(x :: acc, xs')\n  aux(Nil, xs)\nfun join(sep) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(acc ++ sep ++ toString(x), xs')\n  (xs) =>\n    if xs is\n      Cons(x, xs') then aux(toString(x), xs')\n      Nil then \"\"\nfun showList(xs) = \"[\" ++ join(\", \")(xs) ++ \"]\"\n//│ type List[A] = Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A])\n//│ module Nil\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n//│ fun reverse: forall 'A0 'A1. (Cons['A0] | Nil) -> (Cons['A1] | Nil)\n//│ fun join: Str -> (forall 'A2. (Cons['A2] | Nil) -> Str)\n//│ fun showList: forall 'A3. (Cons['A3] | Nil) -> Str\n//│ where\n//│   'A0 <: 'A1\n\n//  _\n// | |    _____  _____ _ __\n// | |   / _ \\ \\/ / _ \\ '__|\n// | |__|  __/>  <  __/ |\n// |_____\\___/_/\\_\\___|_|\n// \n\nfun isDigit(n) = (48 <= n) && (n <= 57)\nfun isBlank(n) = (n === 32) || (n === 9) || (n === 10) || (n === 13)\n//│ fun isDigit: Num -> Bool\n//│ fun isBlank: Eql[10 | 13 | 32 | 9] -> Bool\n\nfun scanInt(text: StringOps, at: Int): Option[[Int, Int]] =\n  let rec aux(acc, i: Int): Option[[Int, Int]] = if\n    i < 0 then None\n    i >= text.length then mapOption(n => [n, i], acc)\n    let c = text.charCodeAt(i)\n    isDigit(c) then aux(Some((acc ?? 0) * 10 + c - 48), i + 1)\n    else mapOption(n => [n, i], acc)\n  aux(None, at)\n//│ fun scanInt: (text: StringOps, at: Int) -> Option[[Int, Int]]\n\nscanInt(\"a123\" |> toStringOps, 0) |> showOption\nscanInt(\"a123\" |> toStringOps, 1) |> showOption\nscanInt(\"a123\" |> toStringOps, 2) |> showOption\nscanInt(\"a123\" |> toStringOps, 3) |> showOption\nscanInt(\"a123\" |> toStringOps, 4) |> showOption\n//│ Str\n//│ res\n//│     = 'None'\n//│ res\n//│     = 'Some(123,4)'\n//│ res\n//│     = 'Some(23,4)'\n//│ res\n//│     = 'Some(3,4)'\n//│ res\n//│     = 'None'\n\nfun skipBlank(text: StringOps, at: Int): Int =\n  let rec aux(i: Int): Int = if\n    i >= text.length then i\n    isBlank(text.charCodeAt(i)) then aux(i + 1)\n    else i\n  aux(at)\n//│ fun skipBlank: (text: StringOps, at: Int) -> Int\n\nskipBlank(\"abc\" |> toStringOps, 0)\nskipBlank(\"abc\" |> toStringOps, 1)\nskipBlank(\"abc\" |> toStringOps, 2)\nskipBlank(\"  \\t\\n\\r123\" |> toStringOps, 0)\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n//│ res\n//│     = 5\n\nclass Span(val start: Int, val end: Int)\n//│ class Span(start: Int, end: Int)\n\nabstract class Token(val span: Span)\nclass IntegerLiteral(value: Int, span2: Span) extends Token(span2) { // It seems that constructor parameters is not sanitized\n  fun toString(): Str = \"IntegerLiteral(\" ++ anyToString(value) ++ \")\"\n}\nclass LeftParen(at: Int) extends Token(Span(at, at + 1)) {\n  fun toString(): Str = \"LeftParen\"\n}\nclass RightParen(at: Int) extends Token(Span(at, at + 1)) {\n  fun toString(): Str = \"RightParen\"\n}\nclass BinaryOperator(value: Str, val bp: Int, at: Int) extends Token(Span(at, at + 1)) {\n  fun toString(): Str = \"BinaryOperator(\" ++ value ++ \", \" ++ anyToString(bp) ++ \")\"\n}\nclass EndOfInput(at: Int) extends Token(Span(at, at)) {\n  fun toString(): Str = \"EndOfInput\"\n}\nclass UnknownInput(rest: Str, at: Int, length: Int) extends Token(Span(at, at + length)) {\n  fun toString(): Str = \"UnknownInput(\" ++ rest ++ \")\"\n}\n//│ abstract class Token(span: Span)\n//│ class IntegerLiteral(value: Int, span2: Span) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class LeftParen(at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class RightParen(at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class BinaryOperator(value: Str, bp: Int, at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class EndOfInput(at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class UnknownInput(rest: Str, at: Int, length: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n\nfun scanToken(text: StringOps, at: Int): [Token, Int] =\n  if\n    let at' = skipBlank(text, at)\n    at' >= text.length then [EndOfInput(at'), at']\n    let head = text.charCodeAt(at')\n    head ===\n      37 then [BinaryOperator(\"%\", 20, at'), at' + 1]\n      40 then [LeftParen(at'), at' + 1]\n      41 then [RightParen(at'), at' + 1]\n      42 then [BinaryOperator(\"*\", 20, at'), at' + 1]\n      43 then [BinaryOperator(\"+\", 10, at'), at' + 1]\n      45 then [BinaryOperator(\"-\", 10, at'), at' + 1]\n      47 then [BinaryOperator(\"/\", 20, at'), at' + 1]\n    (48 <= head) && (head <= 57) and\n      scanInt(text, at') is Some([n, at'']) then\n        [IntegerLiteral(n, Span(at', at'')), at'']\n    else [UnknownInput(text.slice(at'), at', text.length - at'), at']\n//│ fun scanToken: (text: StringOps, at: Int) -> [Token, Int]\n\nscanToken(\"bruh\" |> toStringOps, 0)\nscanToken(\"1\" |> toStringOps, 0)\nscanToken(\"+\" |> toStringOps, 0)\nscanToken(\"  42\" |> toStringOps, 0)\n//│ [Token, Int]\n//│ res\n//│     = [ UnknownInput {}, 0 ]\n//│ res\n//│     = [ IntegerLiteral {}, 1 ]\n//│ res\n//│     = [ BinaryOperator {}, 1 ]\n//│ res\n//│     = [ IntegerLiteral {}, 4 ]\n\nfun tokenize(str: Str): List[Token] =\n  let text = str |> toStringOps\n  let rec aux(acc, at) =\n    if scanToken(text, at) is [token, at'] and token is\n      UnknownInput then (token :: acc) |> reverse\n      EndOfInput then acc |> reverse\n      else aux(token :: acc, at')\n  aux(Nil, 0)\n//│ fun tokenize: (str: Str) -> List[Token]\n\ntokenize(\"0\") |> showList\ntokenize(\"1 + 2 * 3\") |> showList\ntokenize(\"bruh\") |> showList\n//│ Str\n//│ res\n//│     = '[IntegerLiteral(0)]'\n//│ res\n//│     = '[IntegerLiteral(1), BinaryOperator(+, 10), IntegerLiteral(2), BinaryOperator(*, 20), IntegerLiteral(3)]'\n//│ res\n//│     = '[UnknownInput(bruh)]'\n\n//  ____                _\n// |  _ \\ __ _ _ __ ___(_)_ __   __ _\n// | |_) / _` | '__/ __| | '_ \\ / _` |\n// |  __/ (_| | |  \\__ \\ | | | | (_| |\n// |_|   \\__,_|_|  |___/_|_| |_|\\__, |\n//                              |___/\n\ntype Expression = IntegerLiteral | BinaryExpression\nclass BinaryExpression(op: BinaryOperator, left: Expression, right: Expression)\n//│ type Expression = BinaryExpression | IntegerLiteral\n//│ class BinaryExpression(op: BinaryOperator, left: Expression, right: Expression)\n\nfun bindingPower(t: Expression): Int =\n  if t is\n    IntegerLiteral then 30\n    BinaryExpression(op, _, _) then op.bp\n//│ fun bindingPower: (t: Expression) -> Int\n\nfun showExpression(t: Expression): Str =\n  if t is\n    IntegerLiteral(n) then anyToString(n)\n    BinaryExpression(BinaryOperator(op, bp), left, right) then\n      let lbp = bindingPower of left\n      let rbp = bindingPower of right\n      par(showExpression(left), lbp < bp) ++ \" \" ++ op ++ \" \" ++ par(showExpression(right), rbp < bp)\n//│ fun showExpression: (t: Expression) -> Str\n\nlet s = Span(0, 0)\nIntegerLiteral(42, s) |> showExpression\nlet t1 = BinaryExpression(BinaryOperator(\"+\", 10, 0), IntegerLiteral(1, s), IntegerLiteral(2, s))\nt1 |> showExpression\nlet t2 = BinaryExpression(BinaryOperator(\"*\", 20, 0), t1, IntegerLiteral(3, s))\nt2 |> showExpression\nlet t3 = BinaryExpression(BinaryOperator(\"*\", 20, 0), t2, IntegerLiteral(4, s))\nt3 |> showExpression\n//│ let s: Span\n//│ let t1: BinaryExpression\n//│ let t2: BinaryExpression\n//│ let t3: BinaryExpression\n//│ Str\n//│ s\n//│   = Span {}\n//│ res\n//│     = '42'\n//│ t1\n//│    = BinaryExpression {}\n//│ res\n//│     = '1 + 2'\n//│ t2\n//│    = BinaryExpression {}\n//│ res\n//│     = '(1 + 2) * 3'\n//│ t3\n//│    = BinaryExpression {}\n//│ res\n//│     = '(1 + 2) * 3 * 4'\n\ntype ParseResult[A] = Some[A] | Failed\nclass Failed(message: Str)\nfun showParseResult(r: ParseResult['A]) = if r is\n  Some(value) then \"Some(\" ++ toString(value) ++ \")\"\n  Failed(message) then \"Failed(\" ++ message ++ \")\"\nfun (?>) mapParseResult(x, f) = if x is\n  Some(value) then Some(f(value))\n  failed then failed\n//│ type ParseResult[A] = Failed | Some[A]\n//│ class Failed(message: Str)\n//│ fun showParseResult: forall 'A. (r: ParseResult['A]) -> Str\n//│ fun (?>) mapParseResult: forall 'a 'b 'A0. (Object & 'a & ~#Some | Some['b], 'b -> 'A0) -> (Some['A0] | 'a)\n\nfun showParsedExpression(r: ParseResult[Expression]) = if r is\n  Some(value) then \"Some(\" ++ showExpression(value) ++ \")\"\n  Failed(message) then \"Failed(\" ++ message ++ \")\"\n//│ fun showParsedExpression: (r: ParseResult[Expression]) -> Str\n\nfun lastPosition(t: Expression): Int =\n  if t is\n    IntegerLiteral(_, span) then span.end\n    BinaryExpression(_, _, right) then lastPosition(right)\n//│ fun lastPosition: (t: Expression) -> Int\n\nfun parseAtom(ts: List[Token]): ParseResult[[Expression, List[Token]]] =\n  if ts is\n    Cons(IntegerLiteral(n, span), ts') then Some([IntegerLiteral(n, span), ts'])\n    Cons(LeftParen, ts') and parseExpression(0, ts') is\n      Some([body, Cons(RightParen, ts'')]) then Some([body, ts''])\n      Some([body, _]) then Failed(\"Expected a right parenthesis at \" ++ toString(lastPosition of body))\n      failed then failed\n    Cons(token, _) then Failed(\"Unexpected token \" ++ toString(token) ++ \" at \" ++ toString(token.span.start))\n    Nil then Failed(\"Unexpected end of input\")\nfun parseExpression(bp: Int, ts: List[Token]): ParseResult[[Expression, List[Token]]] =\n  if parseAtom(ts) is\n    Some([leftmost, ts']) then\n      let rec aux(left, ts) = if ts is\n        Cons(BinaryOperator(op, bp', opAt), ts') and bp < bp' and\n          parseExpression(bp', ts') is\n            Some([right, ts'']) then\n              aux(BinaryExpression(BinaryOperator(op, bp', opAt), left, right), ts'')\n            failed then failed\n        else Some([left, ts])\n      aux(leftmost, ts')\n    failed then failed\nfun parse(source: Str): ParseResult[Expression] =\n  if parseExpression(0, tokenize(source)) is\n    Some([expr, Nil]) then Some(expr)\n    Some([expr, rest]) then Failed(\"Unexpected token: \" ++ showList(rest) ++ \" at \" ++ toString(lastPosition of expr))\n    failed then failed\n//│ fun parseAtom: (ts: List[Token]) -> ParseResult[[Expression, List[Token]]]\n//│ fun parseExpression: (bp: Int, ts: List[Token]) -> ParseResult[[Expression, List[Token]]]\n//│ fun parse: (source: Str) -> ParseResult[Expression]\n\nparse(\"1 + 2 * 3\") |> showParsedExpression\nparse(\"(1 + 2) * 3\") |> showParsedExpression\nparse(\"2 * (1 + 3 + 5 + 7 + 9 + 11) - 2 - 4 - 6\") |> showParsedExpression\nparse(\"2 * (1 + 3) * (5 + 7) * (9 - 11)\") |> showParsedExpression\nparse(\"(((((((((42)))))))))\") |> showParsedExpression\n//│ Str\n//│ res\n//│     = 'Some(1 + 2 * 3)'\n//│ res\n//│     = 'Some((1 + 2) * 3)'\n//│ res\n//│     = 'Some(2 * (1 + 3 + 5 + 7 + 9 + 11) - 2 - 4 - 6)'\n//│ res\n//│     = 'Some(2 * (1 + 3) * (5 + 7) * (9 - 11))'\n//│ res\n//│     = 'Some(42)'\n\nparse(\"1 + \") |> showParsedExpression\nparse(\"1 bruh\") |> showParsedExpression\nparse(\"1 * (2 + 3\") |> showParsedExpression\nparse(\"1 - bruh\") |> showParsedExpression\n//│ Str\n//│ res\n//│     = 'Failed(Unexpected end of input)'\n//│ res\n//│     = 'Failed(Unexpected token: [UnknownInput(bruh)] at 1)'\n//│ res\n//│     = 'Failed(Expected a right parenthesis at 10)'\n//│ res\n//│     = 'Failed(Unexpected token UnknownInput(bruh) at 4)'\n\n//  _____            _             _   _\n// | ____|_   ____ _| |_   _  __ _| |_(_) ___  _ __\n// |  _| \\ \\ / / _` | | | | |/ _` | __| |/ _ \\| '_ \\\n// | |___ \\ V / (_| | | |_| | (_| | |_| | (_) | | | |\n// |_____| \\_/ \\__,_|_|\\__,_|\\__,_|\\__|_|\\___/|_| |_|\n//\n\nfun evaluate(t: Expression): Option[Int] =\n  if t is\n    IntegerLiteral(n) then Some(n)\n    BinaryExpression(BinaryOperator(op, _, _), left, right) and\n      evaluate(left) is Some(leftResult) and\n        evaluate(right) is Some(rightResult) and op ===\n          \"+\" then Some(leftResult + rightResult)\n          \"-\" then Some(leftResult - rightResult)\n          \"*\" then Some(leftResult * rightResult)\n          // \"/\" then Some(leftResult / rightResult)\n          \"%\" then Some(leftResult % rightResult)\n    else None\n//│ fun evaluate: (t: Expression) -> Option[Int]\n\nfun evaluation(source: Str): Str =\n  if parse(source) is\n    Some(expression) and evaluate(expression) is\n      Some(result) then toString(result)\n      None then \"Evaluation failed\"\n    Failed(message) then \"Parsing failed: \" ++ message\n//│ fun evaluation: (source: Str) -> Str\n\nevaluation(\"1 + 2 * 3\")\nevaluation(\"(((((42)))))\")\nevaluation(\"1 * (3 + 4) - 5\")\nevaluation(\"1 + \")\nevaluation(\"1 bruh\")\n//│ Str\n//│ res\n//│     = '7'\n//│ res\n//│     = '42'\n//│ res\n//│     = '2'\n//│ res\n//│     = 'Parsing failed: Unexpected end of input'\n//│ res\n//│     = 'Parsing failed: Unexpected token: [UnknownInput(bruh)] at 1'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/JSON.mls",
    "content": ":NewDefs\n\n\ntype NStr = Str & {\n  length: Int,\n  at: Int -> NStr,\n  charAt: Int -> NStr,\n  charCodeAt: Int -> Int,\n  slice: (Int, Int) -> NStr,\n  startsWith: (Str, Int) -> Bool,\n  endsWith: Str -> Bool,\n  split: Str -> Array[NStr],\n  trim: () -> NStr,\n  trimStart: () -> NStr,\n  trimEnd: () -> NStr,\n  padStart: (Int, Str) -> NStr,\n  padEnd: (Int, Str) -> NStr,\n  repeat: Int -> NStr,\n  indexOf: Str -> Int,\n  lastIndexOf: Str -> Int,\n  includes: Str -> Bool,\n  localeCompare: Str -> Int\n}\ndeclare fun String: (anything -> NStr) & { fromCodePoint: Int -> NStr }\nfun (++) strcat(a, b) = String of concat(a)(b)\nfun (<*) strlt(a: NStr, b: NStr) = a.localeCompare(b) < 0\nfun (*>) strgt(a: NStr, b: NStr) = a.localeCompare(b) > 0\n//│ type NStr = Str & {\n//│   at: Int -> NStr,\n//│   charAt: Int -> NStr,\n//│   charCodeAt: Int -> Int,\n//│   endsWith: Str -> Bool,\n//│   includes: Str -> Bool,\n//│   indexOf: Str -> Int,\n//│   lastIndexOf: Str -> Int,\n//│   length: Int,\n//│   localeCompare: Str -> Int,\n//│   padEnd: (Int, Str) -> NStr,\n//│   padStart: (Int, Str) -> NStr,\n//│   repeat: Int -> NStr,\n//│   slice: (Int, Int) -> NStr,\n//│   split: Str -> Array[NStr],\n//│   startsWith: (Str, Int) -> Bool,\n//│   trim: () -> NStr,\n//│   trimEnd: () -> NStr,\n//│   trimStart: () -> NStr\n//│ }\n//│ fun (++) strcat: (Str, Str) -> NStr\n//│ fun (<*) strlt: (a: NStr, b: NStr) -> Bool\n//│ fun (*>) strgt: (a: NStr, b: NStr) -> Bool\n//│ fun String: anything -> NStr & {fromCodePoint: Int -> NStr}\n\ndeclare fun Math: { log10: Num -> Num, floor: Num -> Num, ceil: Num -> Num }\n//│ fun Math: {ceil: Num -> Num, floor: Num -> Num, log10: Num -> Num}\n\nfun (!==) notEqual(x, y) = not(x === y)\ndeclare fun parseInt: (Str, Int) -> Int\n//│ fun (!==) notEqual: forall 'a. (Eql['a], 'a) -> Bool\n//│ fun parseInt: (Str, Int) -> Int\n\n// `List` and its utilities:\nabstract class List[out T]: Cons[T] | Nil\nclass Cons[out T](head: T, tail: List[T]) extends List[T]\nmodule Nil extends List\nfun (::) cons(head: 'T, tail: List['T]): List['T] = Cons(head, tail)\nfun reverse(l: List['A]): List['A] =\n  let rec r(l', l) = if l is Cons(x, xs) then r(x :: l', xs) else l'\n  r(Nil, l)\nfun join(sep: Str, xs: List['B]) = if xs is\n  Cons(x, Nil) then toString(x)\n  Cons(x, xs) then toString(x) ++ sep ++ join(sep, xs)\n  Nil then \"\"\nfun showList(xs: List['C]) = \"[\" ++ join(\", \", xs) ++ \"]\"\nfun map(f: 'D -> 'E, xs: List['D]): List['E] = if xs is\n  Cons(x, xs) then f(x) :: map(f, xs)\n  Nil then Nil\nfun equalList(xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool): Bool = if xs is\n  Cons(x, xs') and ys is Cons(y, ys') then equal(x, y) and equalList(xs', ys', equal)\n  Nil and ys is Nil then true\n  else false\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n//│ fun (::) cons: forall 'T. (head: 'T, tail: List['T]) -> List['T]\n//│ fun reverse: forall 'T0. (l: List['T0]) -> List['T0]\n//│ fun join: (sep: Str, xs: List[anything]) -> (Str | NStr)\n//│ fun showList: (xs: List[anything]) -> NStr\n//│ fun map: forall 'D 'T1. (f: 'D -> 'T1, xs: List['D]) -> List['T1]\n//│ fun equalList: forall 'A. (xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool) -> Bool\n\n// `Option` and its utilities:\nabstract class Option[out A]: Some[A] | None\nclass Some[out A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nfun (->) makePair(a, b) = [a, b]\n//│ fun (->) makePair: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n\nabstract class ListMap[K, out V]: (ConsMap[K, V] | NilMap)\nclass ConsMap[K, out V](head: [K, V], tail: ListMap[K, V]) extends ListMap[K, V]\nmodule NilMap extends ListMap\n  \nfun containsKey(map: ListMap['K, 'V], key: 'K): Bool = if map is\n  ConsMap([k, _], _) and k === key then true\n  ConsMap(_, tail) then containsKey(tail, key)\n  NilMap then false\n  \nfun (:+) insert(map, entry) = if map is\n  ConsMap(entry', map) and\n    entry'.0 === entry.0 then ConsMap(entry, map)\n    else ConsMap(entry', insert(map, entry))\n  NilMap then ConsMap(entry, NilMap)\n  \nfun showMap(map) =\n  let showEntry([k, v]) = toString(k) ++ \" -> \" ++ toString(v)\n  let rec aux(map) = if map is\n    ConsMap(last, NilMap) then showEntry(last)\n    ConsMap(head, tail) then showEntry(head) ++ \", \" ++ aux(tail)\n    NilMap then \"\"\n  if map is NilMap then String(\"{}\") else \"{ \" ++ aux(map) ++ \" }\"\n//│ abstract class ListMap[K, V]: ConsMap[K, V] | NilMap\n//│ class ConsMap[K, V](head: [K, V], tail: ListMap[K, V]) extends ListMap\n//│ module NilMap extends ListMap\n//│ fun containsKey: forall 'K 'a. (map: ListMap['K, anything], key: 'a) -> Bool\n//│ fun (:+) insert: forall 'K0 'b 'V. (ConsMap['K0, 'V] | NilMap, ['K0 & 'b, 'V]) -> ConsMap['K0, 'V]\n//│ fun showMap: forall 'K1. (ConsMap['K1, anything] | NilMap) -> NStr\n//│ where\n//│   'K0 <: Eql['b]\n//│   'K <: Eql['a]\n\nshowMap of NilMap\nshowMap of NilMap :+ [\"b\", 2]\nshowMap of NilMap :+ [1, \"a\"] :+ [2, \"b\"]\nshowMap of NilMap :+ [1, \"a\"] :+ [2, \"b\"] :+ [1, \"c\"]\n//│ NStr\n//│ res\n//│     = '{}'\n//│ res\n//│     = '{ b -> 2 }'\n//│ res\n//│     = '{ 1 -> a, 2 -> b }'\n//│ res\n//│     = '{ 1 -> c, 2 -> b }'\n\nabstract class JsonValue: JsonNumber | JsonString | JsonArray | JsonObject | JsonBoolean | JsonNull\nclass JsonNumber(value: Num) extends JsonValue\nclass JsonString(value: Str) extends JsonValue\nclass JsonArray(value: List[JsonValue]) extends JsonValue\nclass JsonObject(value: ListMap[Str, JsonValue]) extends JsonValue\nclass JsonBoolean(value: Bool) extends JsonValue\nmodule JsonNull extends JsonValue\n//│ abstract class JsonValue: JsonArray | JsonBoolean | JsonNull | JsonNumber | JsonObject | JsonString\n//│ class JsonNumber(value: Num) extends JsonValue\n//│ class JsonString(value: Str) extends JsonValue\n//│ class JsonArray(value: List[JsonValue]) extends JsonValue\n//│ class JsonObject(value: ListMap[Str, JsonValue]) extends JsonValue\n//│ class JsonBoolean(value: Bool) extends JsonValue\n//│ module JsonNull extends JsonValue\n\nclass ParserState(val text: NStr, val at: Int) {\n  fun drained: Bool = at === text.length\n  fun peek: Option[NStr] = if drained then None else Some(text.charAt(at))\n  fun peekCode: Option[Int] = if drained then None else Some(text.charCodeAt(at))\n  fun next: ParserState = if drained then this else ParserState(text, at + 1)\n  fun nextDigit: Option[[Num, ParserState]] = if peekCode is\n    Some(ch) and 48 <= ch and ch <= 57 then Some([ch - 48, next])\n    else None\n  fun match(prefix: Str): Option[ParserState] =\n    let prefix' = String(prefix)\n    if\n      prefix'.length > text.length - at then None\n      text.startsWith(prefix', at) then Some(ParserState(text, at + prefix'.length))\n      else None\n  fun rest: NStr = text.slice(at, text.length)\n}\nfun showParserState(state) = \"ParserState(_, \" ++ toString(state.at) ++ \")\"\nfun success: forall 't: ('t, ParserState) -> ParseResult['t]\nfun success = (value, state) => Success(value, state)\nfun failure: forall 't: Str -> ParseResult[nothing]\nfun failure = error => Failure(error)\n  \nabstract class ParseResult[out T]: (Success[T] | Failure) {\n  virtual fun flatMap(f: (T, ParserState) -> ParseResult['U]): ParseResult['U]\n  virtual fun map(f: T -> 'U): ParseResult['U]\n}\nclass Success[out T](value: T, state: ParserState) extends ParseResult[T] {\n  fun flatMap(f) = f(value, state)\n  fun map(f) = success(f(value), state)\n}\nclass Failure(error: Str) extends ParseResult[nothing] {\n  fun flatMap(_) = failure(error)\n  fun map(_) = failure(error)\n}\nfun showParseResult(result) = if result is\n  Success(value, state) then \"Success after \" ++ toString(state.at) ++ \": \" ++ toString(value)\n  Failure(error) then \"Failure: \" ++ toString(error)\n//│ class ParserState(text: NStr, at: Int) {\n//│   fun drained: Bool\n//│   fun match: (prefix: Str) -> Option[ParserState]\n//│   fun next: ParserState\n//│   fun nextDigit: Option[[Num, ParserState]]\n//│   fun peek: Option[NStr]\n//│   fun peekCode: Option[Int]\n//│   fun rest: NStr\n//│ }\n//│ fun showParserState: {at: anything} -> NStr\n//│ fun success: forall 'T. ('T, ParserState) -> Success['T]\n//│ fun failure: Str -> Failure\n//│ abstract class ParseResult[T]: Failure | Success[T] {\n//│   fun flatMap: forall 'U. (f: (T, ParserState) -> ParseResult['U]) -> ParseResult['U]\n//│   fun map: forall 'U0. (f: T -> 'U0) -> ParseResult['U0]\n//│ }\n//│ class Success[T](value: T, state: ParserState) extends ParseResult {\n//│   fun flatMap: forall 'a. ((T, ParserState) -> 'a) -> 'a\n//│   fun map: forall 't. (T -> 't) -> ParseResult['t]\n//│ }\n//│ class Failure(error: Str) extends ParseResult {\n//│   fun flatMap: anything -> ParseResult[nothing]\n//│   fun map: anything -> ParseResult[nothing]\n//│ }\n//│ fun showParseResult: (Failure | Success[anything]) -> NStr\n//│ fun success: forall 't0. ('t0, ParserState) -> ParseResult['t0]\n//│ fun failure: Str -> ParseResult[nothing]\n\nfun isWhiteSpace(ch: NStr): Bool =\n  (ch === \" \") || (ch === \"\\n\") || (ch === \"\\r\") || (ch === \"\\t\")\nfun skipWhiteSpace(state: ParserState): ParserState = if state.peek is\n  Some(ch) and isWhiteSpace(ch) then skipWhiteSpace(state.next)\n  else state\n//│ fun isWhiteSpace: (ch: NStr) -> Bool\n//│ fun skipWhiteSpace: (state: ParserState) -> ParserState\n\n(skipWhiteSpace of ParserState(String(\" \\n\\r\\t\"), 0)).at\n//│ Int\n//│ res\n//│     = 4\n\nfun isDigit(ch) = sge(ch, \"0\") && sle(ch, \"9\")\n//│ fun isDigit: Str -> Bool\n\nfun parseNumber(state: ParserState): ParseResult[Num] =\n  let toFraction(n) = n / (10 ** Math.ceil of Math.log10 of n)\n  let parseNegative(state): ParseResult[Bool] = if state.peek is\n    Some(\"-\") then Success(true, state.next)\n    else Success(false, state)\n  \n  // Parse one or more decimal digits\n  // --------------------------------\n  let parseDigits(state): ParseResult[Num] =\n    // Parse remaining digits\n    let rec aux(acc, state) = if state.nextDigit is\n      Some([digit, state']) then aux((acc *. 10) +. digit, state')\n      None then [acc, state]\n    // Parse the first digit\n    if state.nextDigit is\n      Some([digit, state']) and aux(digit, state') is\n        [num, state''] then Success(num, state'')\n      None then Failure(\"expected one or more decimal digits\")\n  \n  // Parse the integral part of the number\n  // -------------------------------------\n  let parseIntegral(state): ParseResult[Num] = if state.nextDigit is\n    Some([0, state']) then Success(0, state')\n    else parseDigits(state)\n  \n  // Parse the fractional part of the number\n  // ---------------------------------------\n  let parseFraction(state): ParseResult[Num] = if state.peek is\n    Some(\".\") then parseDigits(state.next).map of toFraction\n    else Success(0, state)\n  let parseExponent(state): ParseResult[Num] =\n    let parseSign(state): ParseResult[Bool] = if state.peek is\n      Some(\"-\") then Success(true, state.next)\n      Some(\"+\") then Success(false, state.next)\n      else Success(false, state)\n    if state.peek is Some(e) and (e === \"e\") || (e === \"E\")\n    then parseSign(state.next).flatMap of (sign, state) =>\n      parseDigits(state).map of exponent =>\n      if sign then 10 ** (0 -. exponent) else 10 ** exponent\n    else Success(1, state)\n  \n  parseNegative(state).flatMap of (negative, state) =>\n  parseIntegral(state).flatMap of (integral, state) =>\n  parseFraction(state).flatMap of (fraction, state) =>\n  parseExponent(state).flatMap of (exponent, state) =>\n  let value = (integral +. fraction) *. exponent\n  Success of (if negative then (0 -. value) else value), state\n//│ fun parseNumber: (state: ParserState) -> ParseResult[Num]\n\nshowParseResult of parseNumber of ParserState of String(\"0\"), 0\nshowParseResult of parseNumber of ParserState of String(\"0234\"), 0\nshowParseResult of parseNumber of ParserState of String(\"123\"), 0\nshowParseResult of parseNumber of ParserState of String(\"12.34\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1e10\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1E5\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1E-1\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1E+1\"), 0\n//│ NStr\n//│ res\n//│     = 'Success after 1: 0'\n//│ res\n//│     = 'Success after 1: 0'\n//│ res\n//│     = 'Success after 3: 123'\n//│ res\n//│     = 'Success after 5: 12.34'\n//│ res\n//│     = 'Success after 4: 10000000000'\n//│ res\n//│     = 'Success after 3: 100000'\n//│ res\n//│     = 'Success after 4: 0.1'\n//│ res\n//│     = 'Success after 4: 10'\n\nfun parseString(state: ParserState): ParseResult[Str] =\n  \n  let rec parseCodePoint(n, acc, state) = if\n    n === 0 then Success(acc, state)\n    state.peekCode is Some(code) and\n      48 <= code and code <= 57 then parseCodePoint(n - 1, acc * 16 + code - 48, state.next)\n      65 <= code and code <= 70 then parseCodePoint(n - 1, acc * 16 + code - 55, state.next)\n      97 <= code and code <= 102 then parseCodePoint(n - 1, acc * 16 + code - 87, state.next)\n      else Failure(\"expect \" ++ toString(n) ++ \" hex digit(s) instead of '\" ++ String.fromCodePoint(code) ++ \"'\")\n    else Failure(\"expect \" ++ toString(n) ++ \" hex digit(s) instead of end of input\")\n  \n  let rec parseContent(acc, state) = if state.peek is\n    Some(\"\\\"\") then Success(acc, state.next)\n    Some(\"\\\\\") and\n      let state' = state.next\n      state'.peek is\n        Some(\"\\\"\") then parseContent(acc ++ \"\\\"\", state'.next)\n        Some(\"\\\\\") then parseContent(acc ++ \"\\\\\", state'.next)\n        Some(\"/\") then parseContent(acc ++ \"/\", state'.next)\n        Some(\"b\") then parseContent(acc ++ \"\\b\", state'.next)\n        Some(\"f\") then parseContent(acc ++ \"\\f\", state'.next)\n        Some(\"n\") then parseContent(acc ++ \"\\n\", state'.next)\n        Some(\"r\") then parseContent(acc ++ \"\\r\", state'.next)\n        Some(\"t\") then parseContent(acc ++ \"\\t\", state'.next)\n        Some(\"u\") then\n          parseCodePoint(4, 0, state'.next).flatMap of (codePoint, state) =>\n          if codePoint < 0xD800 || 0xDFFF < codePoint\n          then parseContent(acc ++ String.fromCodePoint(codePoint), state)\n          else Failure(\"invalid code point\")\n        else Failure(\"invalid escape sequence\")\n    Some(ch) then parseContent(acc ++ ch, state.next)\n    None then Failure(\"expected '\\\"' instead of end of input\")\n  \n  if state.peek is\n    Some(\"\\\"\") then parseContent(\"\", state.next)\n    Some(ch) then Failure(\"expected '\\\"' instead of '\" ++ ch ++ \"'\")\n    else Failure(\"expected '\\\"' instead of end of input\")\n//│ fun parseString: (state: ParserState) -> ParseResult[Str]\n\nshowParseResult of parseString of ParserState of String(\"\\\"\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"abc\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\\\\"\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\\\\\\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\/\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\b\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\u\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\u0\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\u004c\\\"\"), 0\n//│ NStr\n//│ res\n//│     = 'Success after 2: '\n//│ res\n//│     = 'Success after 5: abc'\n//│ res\n//│     = 'Success after 4: \"'\n//│ res\n//│     = 'Success after 4: \\\\'\n//│ res\n//│     = 'Success after 4: /'\n//│ res\n//│     = 'Success after 4: \\b'\n//│ res\n//│     = `Failure: expected '\"' instead of end of input`\n//│ res\n//│     = `Failure: expect 4 hex digit(s) instead of '\"'`\n//│ res\n//│     = `Failure: expect 3 hex digit(s) instead of '\"'`\n//│ res\n//│     = 'Success after 8: L'\n\nfun parseTrue(state: ParserState): ParseResult[Bool] =\n  if state.match(\"true\") is\n    Some(state) then Success(true, state)\n    None then Failure(\"expected 'true'\")\n  \nfun parseFalse(state: ParserState): ParseResult[Bool] =\n  if state.match(\"false\") is\n    Some(state) then Success(false, state)\n    None then Failure(\"expected 'false'\")\n  \nfun parseNull(state: ParserState): ParseResult[()] =\n  if state.match(\"null\") is\n    Some(state) then Success((), state)\n    None then Failure(\"expected 'null'\")\n//│ fun parseTrue: (state: ParserState) -> ParseResult[Bool]\n//│ fun parseFalse: (state: ParserState) -> ParseResult[Bool]\n//│ fun parseNull: (state: ParserState) -> ParseResult[()]\n\nfun parseObjectEntry(state: ParserState): ParseResult[[Str, JsonValue]] =\n  let state' = skipWhiteSpace(state)\n  parseString(state').flatMap of (key, state) =>\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(\":\") then\n      parseValue(state'.next).flatMap of (value, state') =>\n      Success([key, value], state')\n    Some(ch) then Failure(\"expected ':' instead of '\" ++ ch ++ \"'\")\n    None then Failure(\"expected ':' instead of end of input\")\n  else Failure(\"expected ':' instead of end of input\")\n  \nfun parseObject(state: ParserState): ParseResult[ListMap[Str, JsonValue]] =\n  let rec parseObjectTail(acc: ListMap[Str, JsonValue], state: ParserState) =\n    let state' = skipWhiteSpace(state)\n    if state'.peek is\n      Some(\",\") then\n        parseObjectEntry(state'.next).flatMap of (entry, state') =>\n        if containsKey(acc, entry.0) then\n          Failure(\"duplicate key '\" ++ toString(entry.0) ++ \"'\")\n        else\n          parseObjectTail(ConsMap(entry, acc), state')\n      Some(\"}\") then Success(acc, state'.next)\n      Some(ch) then Failure(\"expected ',' or ']' instead of \" ++ ch)\n      None then Failure(\"expected ',' or ']' instead of end of input\")\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(\"}\") then Success(NilMap, state'.next)\n    None then Failure(\"expected ',' or ']' instead of end of input\")\n    else\n      parseObjectEntry(state').flatMap of (head, state) =>\n      parseObjectTail(ConsMap(head, NilMap), state)\n  \nfun parseArray(state: ParserState): ParseResult[List[JsonValue]] =\n  let rec parseArrayTail(acc, state) =\n    let state' = skipWhiteSpace(state)\n    if state'.peek is\n      Some(\",\") then\n        parseValue(state'.next).flatMap of (value, state') =>\n        parseArrayTail(value :: acc, state')\n      Some(\"]\") then Success(reverse(acc), state'.next)\n      Some(ch) then Failure(\"expected ',' or ']' instead of \" ++ ch)\n      None then Failure(\"expected ',' or ']' instead of end of input\")\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(\"]\") then Success(Nil, state'.next)\n    None then Failure(\"expected ',' or ']' instead of end of input\")\n    else\n      parseValue(state').flatMap of (head, state) =>\n      parseArrayTail(head :: Nil, state)\n  \nfun parseValue(state: ParserState): ParseResult[JsonValue] =\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(ch) and\n      ch === \"\\\"\" then parseString(state').map of JsonString\n      (ch === \"-\") || isDigit(ch) then parseNumber(state').map of JsonNumber\n      ch === \"[\" then parseArray(state'.next).map of JsonArray\n      ch === \"{\" then parseObject(state'.next).map of JsonObject\n      ch === \"t\" then parseTrue(state').map of JsonBoolean\n      ch === \"f\" then parseFalse(state').map of JsonBoolean\n      ch === \"n\" then parseNull(state').map of _ => JsonNull\n      else Failure(\"cannot recognize \" ++ ch ++ \" as the beginning of a JSON value\")\n    None then Failure(\"expected a JSON value instead of end of input\")\n//│ fun parseObjectEntry: (state: ParserState) -> ParseResult[[Str, JsonValue]]\n//│ fun parseObject: (state: ParserState) -> ParseResult[ListMap[Str, JsonValue]]\n//│ fun parseArray: (state: ParserState) -> ParseResult[List[JsonValue]]\n//│ fun parseValue: (state: ParserState) -> ParseResult[JsonValue]\n\nfun parse(source: Str): ParseResult[JsonValue] =\n  (parseValue of ParserState of String(source), 0).flatMap of (value, finalState) =>\n    let shouldBeEnd = skipWhiteSpace of finalState\n    if shouldBeEnd.drained then\n      Success(value, shouldBeEnd)\n    else\n      Failure(\"expected end of input instead of: \" ++ shouldBeEnd.rest)\n//│ fun parse: (source: Str) -> ParseResult[JsonValue]\n\nfun stringify(value: JsonValue): Str =\n  let stringifyObject(map) =\n    let showEntry([k, v]) = \"\\\"\" ++ toString(k) ++ \"\\\": \" ++ stringify(v)\n    let rec aux(map) = if map is\n      ConsMap(last, NilMap) then showEntry(last)\n      ConsMap(head, tail) then showEntry(head) ++ \", \" ++ aux(tail)\n      NilMap then \"\"\n    if map is NilMap then String(\"{}\") else \"{ \" ++ aux(map) ++ \" }\"\n  \n  if value is\n    JsonNumber(n) then toString(n)\n    JsonString(s) then \"\\\"\" ++ s ++ \"\\\"\"\n    JsonArray(xs) then \"[\" ++ join(\", \", map(stringify, xs)) ++ \"]\"\n    JsonObject(m) then stringifyObject(m)\n    JsonBoolean(b) then if b then \"true\" else \"false\"\n    JsonNull then \"null\"\n//│ fun stringify: (value: JsonValue) -> Str\n\nfun showResult(result) = if result is\n  Success(value, state) then \"Success after \" ++ toString(state.at) ++ \": \" ++ stringify(value)\n  Failure(error) then \"Failure: \" ++ toString(error)\n//│ fun showResult: (Failure | Success[JsonValue]) -> NStr\n\n// Simple tests.\nshowResult of parse of \"null\"\nshowResult of parse of \"true\"\nshowResult of parse of \"false\"\nshowResult of parse of \"123\"\nshowResult of parse of \"\\\"abc\\\"\"\nshowResult of parse of \"[1, 2, 3]\"\nshowResult of parse of \"{\\\"a\\\": 1, \\\"b\\\": 2}\"\nshowResult of parse of \"nul\"\nshowResult of parse of \"[1, 3, 5\"\nshowResult of parse of \"[1, 3, 5]\"\n//│ NStr\n//│ res\n//│     = 'Success after 4: null'\n//│ res\n//│     = 'Success after 4: true'\n//│ res\n//│     = 'Success after 5: false'\n//│ res\n//│     = 'Success after 3: 123'\n//│ res\n//│     = 'Success after 5: \"abc\"'\n//│ res\n//│     = 'Success after 9: [1, 2, 3]'\n//│ res\n//│     = 'Success after 16: { \"b\": 2, \"a\": 1 }'\n//│ res\n//│     = \"Failure: expected 'null'\"\n//│ res\n//│     = \"Failure: expected ',' or ']' instead of end of input\"\n//│ res\n//│     = 'Success after 9: [1, 3, 5]'\n\n// Complicated tests.\nshowResult of parse of \"{ \\\"origin\\\": { \\\"x\\\": 0, \\\"y\\\": 0 } }\"\nshowResult of parse of \"[   { \\\"origin\\\": { \\\"x\\\": 0, \\\"y\\\": 0 } , \\\"size\\\": { \\\"width\\\": 100, \\\"height\\\": 100 } }   ]\"\nshowResult of parse of \"{\\\"id\\\":\\\"658f34f88882211aa8679240\\\",\\\"children\\\":[{\\\"name\\\":\\\"Jo Rosales\\\",\\\"age\\\":8},{\\\"name\\\":\\\"Shawn Burke\\\",\\\"age\\\":7},{\\\"name\\\":\\\"Gomez Guthrie\\\",\\\"age\\\":10},{\\\"name\\\":\\\"Tandy Christensen\\\",\\\"age\\\":9},{\\\"name\\\":\\\"Jody Langley\\\",\\\"age\\\":3}],\\\"currentJob\\\":{\\\"title\\\":\\\"Developer\\\",\\\"salary\\\":\\\"mask;\\\"},\\\"jobs\\\":[{\\\"title\\\":\\\"medic\\\",\\\"salary\\\":\\\"R$ 6.400,90\\\"},{\\\"title\\\":\\\"teacher\\\",\\\"salary\\\":\\\"R$ 7.960,31\\\"}],\\\"maxRunDistance\\\":14.7,\\\"cpf\\\":\\\"713.763.356-03\\\",\\\"cnpj\\\":\\\"33.385.435/0001-50\\\",\\\"pretendSalary\\\":\\\"R$ 9.247,29\\\",\\\"age\\\":63,\\\"gender\\\":\\\"male\\\",\\\"firstName\\\":\\\"Parker\\\",\\\"lastName\\\":\\\"Case\\\",\\\"phone\\\":\\\"+55 (83) 95023-7077\\\",\\\"address\\\":\\\"14 Orient Avenue - Harmon, Northern Mariana Islands, Myanmar.\\\",\\\"hairColor\\\":\\\"yellow\\\"}\"\n//│ NStr\n//│ res\n//│     = 'Success after 32: { \"origin\": { \"y\": 0, \"x\": 0 } }'\n//│ res\n//│     = 'Success after 82: [{ \"size\": { \"height\": 100, \"width\": 100 }, \"origin\": { \"y\": 0, \"x\": 0 } }]'\n//│ res\n//│     = 'Success after 647: { \"hairColor\": \"yellow\", \"address\": \"14 Orient Avenue - Harmon, Northern Mariana Islands, Myanmar.\", \"phone\": \"+55 (83) 95023-7077\", \"lastName\": \"Case\", \"firstName\": \"Parker\", \"gender\": \"male\", \"age\": 63, \"pretendSalary\": \"R$ 9.247,29\", \"cnpj\": \"33.385.435/0001-50\", \"cpf\": \"713.763.356-03\", \"maxRunDistance\": 14.7, \"jobs\": [{ \"salary\": \"R$ 6.400,90\", \"title\": \"medic\" }, { \"salary\": \"R$ 7.960,31\", \"title\": \"teacher\" }], \"currentJob\": { \"salary\": \"mask;\", \"title\": \"Developer\" }, \"children\": [{ \"age\": 8, \"name\": \"Jo Rosales\" }, { \"age\": 7, \"name\": \"Shawn Burke\" }, { \"age\": 10, \"name\": \"Gomez Guthrie\" }, { \"age\": 9, \"name\": \"Tandy Christensen\" }, { \"age\": 3, \"name\": \"Jody Langley\" }], \"id\": \"658f34f88882211aa8679240\" }'\n\n// Nice.\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/LispInterpreter.mls",
    "content": ":NewDefs\n\n// Summon the underlying JavaScript `Object.is` function so that we can compare\n// any objects. For example, functions do not conforms to `Eql` so we cannot\n// compare them with `===` directly. But, we can use `Object.is`.\ndeclare fun Object: nothing\nlet (=:=) objectEqual: (anything, anything) -> Bool = Object.is\nfun (=/=) objectNotEqual(x, y) = not(x =:= y)\n//│ let (=:=) objectEqual: (anything, anything) -> Bool\n//│ fun (=/=) objectNotEqual: (anything, anything) -> Bool\n//│ fun Object: nothing\n//│ objectEqual\n//│             = [Function: is]\n\ntype NStr = Str & {\n  length: Int,\n  at: Int -> NStr,\n  charAt: Int -> NStr,\n  charCodeAt: Int -> Int,\n  slice: (Int, Int) -> NStr,\n  startsWith: Str -> Bool,\n  endsWith: Str -> Bool,\n  split: Str -> Array[NStr],\n  trim: () -> NStr,\n  trimStart: () -> NStr,\n  trimEnd: () -> NStr,\n  padStart: (Int, Str) -> NStr,\n  padEnd: (Int, Str) -> NStr,\n  repeat: Int -> NStr,\n  indexOf: Str -> Int,\n  lastIndexOf: Str -> Int,\n  includes: Str -> Bool,\n}\ndeclare fun String: anything -> NStr\nfun (++) strcat(a, b) = String of concat(a)(b)\n//│ type NStr = Str & {\n//│   at: Int -> NStr,\n//│   charAt: Int -> NStr,\n//│   charCodeAt: Int -> Int,\n//│   endsWith: Str -> Bool,\n//│   includes: Str -> Bool,\n//│   indexOf: Str -> Int,\n//│   lastIndexOf: Str -> Int,\n//│   length: Int,\n//│   padEnd: (Int, Str) -> NStr,\n//│   padStart: (Int, Str) -> NStr,\n//│   repeat: Int -> NStr,\n//│   slice: (Int, Int) -> NStr,\n//│   split: Str -> Array[NStr],\n//│   startsWith: Str -> Bool,\n//│   trim: () -> NStr,\n//│   trimEnd: () -> NStr,\n//│   trimStart: () -> NStr\n//│ }\n//│ fun (++) strcat: (Str, Str) -> NStr\n//│ fun String: anything -> NStr\n\nfun (!==) notEqual(x, y) = not(x === y)\ndeclare fun parseInt: (Str, Int) -> Int\n//│ fun (!==) notEqual: forall 'a. (Eql['a], 'a) -> Bool\n//│ fun parseInt: (Str, Int) -> Int\n\n// `List` and its utilities:\nabstract class List[out T]: Cons[T] | Nil\nclass Cons[out T](head: T, tail: List[T]) extends List[T]\nmodule Nil extends List\nfun (::) cons(head: 'T, tail: List['T]): List['T] = Cons(head, tail)\nfun reverse(l: List['A]): List['A] =\n  let rec r(l', l) = if l is Cons(x, xs) then r(x :: l', xs) else l'\n  r(Nil, l)\nfun join(sep: Str, xs: List['B]) = if xs is\n  Cons(x, Nil) then toString(x)\n  Cons(x, xs) then toString(x) ++ sep ++ join(sep, xs)\n  Nil then \"\"\nfun showList(xs: List['C]) = \"[\" ++ join(\", \", xs) ++ \"]\"\nfun map(f: 'D -> 'E, xs: List['D]): List['E] = if xs is\n  Cons(x, xs) then f(x) :: map(f, xs)\n  Nil then Nil\nfun equalList(xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool): Bool = if xs is\n  Cons(x, xs') and ys is Cons(y, ys') then equal(x, y) and equalList(xs', ys', equal)\n  Nil and ys is Nil then true\n  else false\n// `Option` and its utilities:\nabstract class Option[out A]: Some[A] | None\nclass Some[out A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n//│ fun (::) cons: forall 'T. (head: 'T, tail: List['T]) -> List['T]\n//│ fun reverse: forall 'T0. (l: List['T0]) -> List['T0]\n//│ fun join: (sep: Str, xs: List[anything]) -> (Str | NStr)\n//│ fun showList: (xs: List[anything]) -> NStr\n//│ fun map: forall 'D 'T1. (f: 'D -> 'T1, xs: List['D]) -> List['T1]\n//│ fun equalList: forall 'A. (xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool) -> Bool\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\n//     _    ____ _____\n//    / \\  / ___|_   _|\n//   / _ \\ \\___ \\ | |\n//  / ___ \\ ___) || |\n// /_/   \\_\\____/ |_|\n//\n\nabstract class Expr: Lambda | BuiltIn | Instance | Thunk | StrLit | IntLit | ExprList\nclass Lambda(f: List[Data] -> Data) extends Expr\nclass BuiltIn(e: List[Data] -> Data) extends Expr\nclass Instance(n: Str, m: List[[Str, Expr]]) extends Expr\nclass Thunk(e: () -> Data) extends Expr\nclass StrLit(s: Str) extends Expr\nclass IntLit(n: Int) extends Expr\nclass ExprList(l: List[Expr]) extends Expr\nfun (=@=) equalExpr(x: Expr, y: Expr): Bool = if x is\n  Lambda(f) and y is Lambda(g) then f =:= g\n  BuiltIn(f) and y is BuiltIn(g) then f =:= g\n  Instance(n, m) and y is Instance(n', m') then\n    let equalPair = ([k, v], [k', v']) => k =:= k' and equalExpr(v, v')\n    n === n' and equalList(m, m', equalPair)\n  Thunk(e) and y is Thunk(e') then e =:= e'\n  StrLit(s) and y is StrLit(s') then s === s'\n  IntLit(n) and y is IntLit(n') then n === n'\n  ExprList(l) and y is ExprList(l') then equalList(l, l', equalExpr)\n  else false\nfun showExpr(e: Expr): Str = if e is\n  Lambda(f) then \"<lambda>\"\n  BuiltIn(f) then \"<built-in>\"\n  Instance(n, m) then \"<object \" ++ n ++ \">\"\n  Thunk(e) then \"<thunk>\"\n  // StrLit(s) then \"str:\" ++ s\n  // IntLit(n) then \"int:\" ++ toString(n)\n  StrLit(s) then s\n  IntLit(n) then toString(n)\n  ExprList(l) then showList(map(showExpr, l))\nabstract class Data: Literal | DataList | Symbol\nclass Literal(e: Expr) extends Data\nclass DataList(l: List[Data]) extends Data\nclass Symbol(s: Str) extends Data\nfun (=#=) equalData(x: Data, y: Data): Bool = if x is\n  Literal(e) and y is Literal(e') then e =@= e'\n  DataList(l) and y is DataList(l') then equalList(l, l', equalData)\n  Symbol(s) and y is Symbol(s') then s === s'\n  else false\nfun showData(d: Data): Str = if d is\n  Literal(e) then showExpr(e)\n  DataList(l) then \"(\" ++ join(\", \", map(showData, l)) ++ \")\"\n  // Symbol(s) then \"sym:\" ++ s\n  Symbol(s) then s\n//│ abstract class Expr: BuiltIn | ExprList | Instance | IntLit | Lambda | StrLit | Thunk\n//│ class Lambda(f: List[Data] -> Data) extends Expr\n//│ class BuiltIn(e: List[Data] -> Data) extends Expr\n//│ class Instance(n: Str, m: List[[Str, Expr]]) extends Expr\n//│ class Thunk(e: () -> Data) extends Expr\n//│ class StrLit(s: Str) extends Expr\n//│ class IntLit(n: Int) extends Expr\n//│ class ExprList(l: List[Expr]) extends Expr\n//│ fun (=@=) equalExpr: (x: Expr, y: Expr) -> Bool\n//│ fun showExpr: (e: Expr) -> Str\n//│ abstract class Data: DataList | Literal | Symbol\n//│ class Literal(e: Expr) extends Data\n//│ class DataList(l: List[Data]) extends Data\n//│ class Symbol(s: Str) extends Data\n//│ fun (=#=) equalData: (x: Data, y: Data) -> Bool\n//│ fun showData: (d: Data) -> Str\n\n//  _____       _                 _\n// |_   _|___  | | __ ___  _ __  (_) ____ ___  _ __\n//   | | / _ \\ | |/ // _ \\| '_ \\ | ||_  // _ \\| '__|\n//   | || (_) ||   <|  __/| | | || | / /|  __/| |\n//   |_| \\___/ |_|\\_\\\\___||_| |_||_|/___|\\___||_|\n//\n\nfun skipBlank(s: NStr, i: Int): Int =\n  if\n    i < 0 then skipBlank(s, 0)\n    i >= s.length then s.length\n    s.charCodeAt(i) == 32 then skipBlank(s, i + 1)\n    else i\n//│ fun skipBlank: (s: NStr, i: Int) -> Int\n\nfun scanWhile(s: NStr, i: Int, p: Str -> Bool): Option[[Str, Int]] =\n  let rec aux(acc, i) =\n    if i < s.length and s.charAt(i) is ch and p of ch\n      then aux(acc ++ ch, i + 1)\n      else [acc, i]\n  if aux(\"\", i) is\n    [\"\", _] then None\n    [acc, i] then Some([acc, i])\n//│ fun scanWhile: (s: NStr, i: Int, p: Str -> Bool) -> Option[[Str, Int]]\n\nfun isDelimiter(ch) = ch !== \" \" and ch !== \"(\" and ch !== \")\"\n//│ fun isDelimiter: Eql[\" \" | \"(\" | \")\"] -> Bool\n\nfun nextToken(s: NStr, i: Int): Option[[Str, Int]] =\n  let i' = skipBlank(s, i)\n  if s.charAt(i') is\n    \"(\" then Some([\"(\", i' + 1])\n    \")\" then Some([\")\", i' + 1])\n    else scanWhile(s, i', isDelimiter)\n//│ fun nextToken: (s: NStr, i: Int) -> Option[[Str, Int]]\n\nfun tokenize(s: Str): List[Str] =\n  let s' = String(s)\n  let rec aux(acc, i) =\n    if nextToken(s', i) is\n      None then reverse(acc)\n      Some([token, i']) then aux(token :: acc, i')\n  aux(Nil, 0)\n//│ fun tokenize: (s: Str) -> List[Str]\n\nshowList of tokenize(\"\")\nshowList of tokenize(\"12\")\nshowList of tokenize(\"x\")\nshowList of tokenize(\"(quote (cons 1 nil))\")\nshowList of tokenize(\"(+ 1 2)\")\n//│ NStr\n//│ res\n//│     = '[]'\n//│ res\n//│     = '[12]'\n//│ res\n//│     = '[x]'\n//│ res\n//│     = '[(, quote, (, cons, 1, nil, ), )]'\n//│ res\n//│     = '[(, +, 1, 2, )]'\n\n//  ____\n// |  _ \\  __ _  _ __  ___   ___  _ __\n// | |_) |/ _` || '__|/ __| / _ \\| '__|\n// |  __/| (_| || |   \\__ \\|  __/| |\n// |_|    \\__,_||_|   |___/ \\___||_|\n//\n\nfun isDigit(n) = 48 <= n and n <= 57\nfun isDigits(s: Str): Bool =\n  let s' = String(s)\n  let rec aux(i) =\n    if i < s'.length and isDigit of s'.charCodeAt(i)\n      then aux(i + 1)\n      else i === s'.length\n  aux(0)\nisDigits(\"123\")\nisDigits(\"123jump\")\nisDigits(\"bruh\")\n//│ fun isDigit: Num -> Bool\n//│ fun isDigits: (s: Str) -> Bool\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n\nabstract class ParseResult[out A]: Success[A] | Failure\nclass Success[out A](value: A) extends ParseResult[A]\nclass Failure(error: Str) extends ParseResult[nothing]\n//│ abstract class ParseResult[A]: Failure | Success[A]\n//│ class Success[A](value: A) extends ParseResult\n//│ class Failure(error: Str) extends ParseResult\n\n// Notes\n// =====\n// Sometimes, the precedence of comma is less than `of`.\n// For example, in `[Success of DataList of reverse of acc, tail]`.\nfun parseExpr(tokens: List[Str]): [ParseResult[Data], List[Str]] =\n  if tokens is\n    Cons(\"(\", tail) then parseList(tail)\n    Cons(\")\", _) then [Failure(\"Unmatched closing parenthesis.\"), tokens]\n    Cons(token, tail) and\n      isDigits(token) then [(Success of Literal of IntLit of parseInt(token, 10)), tail]\n      else [(Success of Symbol of token), tail]\n    Nil then [Failure(\"Unexpected end of input, expect either `)` or more tokens.\"), Nil]\n  \nfun parseList(tokens: List[Str]): [ParseResult[DataList], List[Str]] =\n  let rec collect(acc, ts) = if ts is\n    Cons(\")\", tail) then [(Success of DataList of reverse of acc), tail]\n    Cons and parseExpr(ts) is\n      [Success(data), rest] then collect(data :: acc, rest)\n      [Failure(_) as failure, rest] then [failure, rest]\n    Nil then [Failure(\"Unexpected end of input, expect either `)` or more tokens.\"), Nil]\n  collect(Nil, tokens)\n//│ fun parseExpr: (tokens: List[Str]) -> [ParseResult[Data], List[Str]]\n//│ fun parseList: (tokens: List[Str]) -> [ParseResult[DataList], List[Str]]\n\nfun showParse(source: Str): Str =\n  if parseExpr(tokenize(source)) is\n    [Success(data), _] then \"Ok: \" ++ showData(data)\n    [Failure(error), _] then \"Error: \" ++ error\n//│ fun showParse: (source: Str) -> Str\n\nshowParse(\"(cons 1 nil)\")\nshowParse(\"(cons 1 (cons 2 nil))\")\nshowParse(\"(cons 1 (cons 2 (cons 3 nil)))\")\nshowParse(\"(+ 1 2)\")\nshowParse(\"(car (cons 1 nil))\")\n//│ Str\n//│ res\n//│     = 'Ok: (cons, 1, nil)'\n//│ res\n//│     = 'Ok: (cons, 1, (cons, 2, nil))'\n//│ res\n//│     = 'Ok: (cons, 1, (cons, 2, (cons, 3, nil)))'\n//│ res\n//│     = 'Ok: (+, 1, 2)'\n//│ res\n//│     = 'Ok: (car, (cons, 1, nil))'\n\n//  _____\n// | ____| _ __ __   __\n// |  _|  | '_ \\\\ \\ / /\n// | |___ | | | |\\ V /\n// |_____||_| |_| \\_/\n//\n\n// As of the time I wrote this code, MLscript did not yet support term\n// refinement, so I used lambda expression to implement `Env` first.\ntype Env[T] = Str -> T\nlet emptyEnv: Str -> nothing = _ => error\n// The lookup function becomes useless because we can just call the `Env`.\nfun lookup(env, name: Str): 'A = env(name)\n//│ type Env[T] = Str -> T\n//│ let emptyEnv: Str -> nothing\n//│ fun lookup: forall 'A. (Str -> 'A, name: Str) -> 'A\n//│ emptyEnv\n//│          = [Function: emptyEnv]\n\n// It is tricky to write an annotation that simplifies the inferred type.\nfun (+:) extend(env, [name, expr]: [Str, 'A]) =\n  (name': Str) => if name' === name then expr else env(name')\n//│ fun (+:) extend: forall 'A. (Str -> 'A, [Str, 'A]) -> (name': Str) -> 'A\n\nfun extendRec(env, name: Str, expr: (Str -> 'A) -> 'A) =\n  let rec env'(name': Str): 'A = if name' === name then expr(env') else env(name')\n  env'\n//│ fun extendRec: forall 'A. (Str -> 'A, name: Str, expr: (Str -> 'A) -> 'A) -> (name': Str) -> 'A\n\nfun extendParameters(env: Str -> 'A, ps: List[Str], vs: List['A]) =\n  if [ps, vs] is\n    [Nil, Nil] then env\n    [Cons(p, ps'), Cons(v, vs')] then extendParameters(extend(env, [p, v]), ps', vs')\n    else error\n//│ fun extendParameters: forall 'A. (env: Str -> 'A, ps: List[Str], vs: List['A]) -> Str -> 'A\n\nfun (++:) extendEntries(env, ps: List[[Str, 'A]]) =\n  if ps is\n    Nil then env\n    Cons(p, ps') then extendEntries(extend(env, p), ps')\n    else error\n//│ fun (++:) extendEntries: forall 'A 'a. (Str -> 'A & 'a, ps: List[[Str, 'A]]) -> ((name': Str) -> 'A | 'a)\n\nlet intEnv1 = extend(emptyEnv, [\"one\", 1])\nlet intEnv2 = extend(intEnv1, [\"two\", 2])\nlet intEnv3 = extend(intEnv2, [\"three\", 3])\n//│ let intEnv1: (name': Str) -> 1\n//│ let intEnv2: (name': Str) -> (1 | 2)\n//│ let intEnv3: (name': Str) -> (1 | 2 | 3)\n//│ intEnv1\n//│         = [Function (anonymous)]\n//│ intEnv2\n//│         = [Function (anonymous)]\n//│ intEnv3\n//│         = [Function (anonymous)]\n\n// Make a tuple to save some lines.\n[intEnv1(\"one\"), intEnv2(\"one\"), intEnv3(\"one\"), intEnv2(\"two\"), intEnv3(\"two\"), intEnv3(\"three\")]\n//│ [1, 1 | 2, 1 | 2 | 3, 1 | 2, 1 | 2 | 3, 1 | 2 | 3]\n//│ res\n//│     = [ 1, 1, 1, 2, 2, 3 ]\n\n:re\nintEnv1(\"two\")\nintEnv2(\"three\")\nintEnv3(\"bruh\")\n//│ 1 | 2 | 3\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\nlet intEnv6 = intEnv3 ++: ([\"four\", 4] :: [\"five\", 5] :: [\"six\", 6] :: Nil)\n//│ let intEnv6: (name': Str) -> (1 | 2 | 3 | 4 | 5 | 6)\n//│ intEnv6\n//│         = [Function (anonymous)]\n\n[intEnv6(\"one\"), intEnv6(\"two\"), intEnv6(\"three\"), intEnv6(\"four\"), intEnv6(\"five\"), intEnv6(\"six\")]\n//│ [1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6]\n//│ res\n//│     = [ 1, 2, 3, 4, 5, 6 ]\n\n:re\nintEnv6(\"seven\")\n//│ 1 | 2 | 3 | 4 | 5 | 6\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\nfun builtinEq(args: List[Data]): Data = if args is\n  Cons(x, Cons(y, Nil)) and\n    x =#= y then Literal(IntLit(1))\n    else Literal(IntLit(0))\n  else error\nfun builtinAdd(args: List[Data]): Data = if args is\n  Cons(Literal(IntLit(x)), Cons(Literal(IntLit(y)), Nil)) then Literal(IntLit(x + y))\n  else error\nfun builtinSub(args: List[Data]): Data = if args is\n  Cons(Literal(IntLit(x)), Cons(Literal(IntLit(y)), Nil)) then Literal(IntLit(x - y))\n  else error\nfun builtinMul(args: List[Data]): Data = if args is\n  Cons(Literal(IntLit(x)), Cons(Literal(IntLit(y)), Nil)) then Literal(IntLit(x * y))\n  else error\nlet builtinNil = DataList(Nil)\nfun builtinCons(args: List[Data]): Data = if args is\n  Cons(x, Cons(DataList(xs), Nil)) then DataList(x :: xs)\n  else error\nfun builtinCar(args: List[Data]): Data = if args is\n  Cons(DataList(Cons(x, _)), Nil) then x\n  else error\nfun builtinCdr(args: List[Data]): Data = if args is\n  Cons(DataList(Cons(_, xs)), Nil) then DataList(xs)\n  else error\nfun builtinNull(args: List[Data]): Data = if args is\n  Cons(DataList(Nil), Nil) then Literal(IntLit(1))\n  else Literal(IntLit(0))\n//│ fun builtinEq: (args: List[Data]) -> Data\n//│ fun builtinAdd: (args: List[Data]) -> Data\n//│ fun builtinSub: (args: List[Data]) -> Data\n//│ fun builtinMul: (args: List[Data]) -> Data\n//│ let builtinNil: DataList\n//│ fun builtinCons: (args: List[Data]) -> Data\n//│ fun builtinCar: (args: List[Data]) -> Data\n//│ fun builtinCdr: (args: List[Data]) -> Data\n//│ fun builtinNull: (args: List[Data]) -> Data\n//│ builtinNil\n//│            = DataList {}\n\nlet globalEnv = emptyEnv ++:\n  [\"eq\", Literal(Lambda(builtinEq))] :: [\"+\", Literal(Lambda(builtinAdd))] ::\n  [\"-\", Literal(Lambda(builtinSub))] :: [\"*\", Literal(Lambda(builtinMul))] ::\n  [\"nil\", builtinNil] :: [\"cons\", Literal(Lambda(builtinCons))] ::\n  [\"car\", Literal(Lambda(builtinCar))] :: [\"cdr\", Literal(Lambda(builtinCdr))] ::\n  [\"null\", Literal(Lambda(builtinNull))] :: Nil\n//│ let globalEnv: (name': Str) -> (DataList | Literal)\n//│ globalEnv\n//│           = [Function (anonymous)]\n\nfun toName(x: Data): Str = if x is Symbol(s) then s else error\n//│ fun toName: (x: Data) -> Str\n\nfun asList(x: Data): List[Data] = if x is DataList(ys) then ys else error\n//│ fun asList: (x: Data) -> List[Data]\n\nfun eval(x: Data, env: Str -> Data): Data = if x is\n  Literal(StrLit(_)) as lit then lit\n  Literal(IntLit(_)) as lit then lit\n  Symbol(name) then env(name)\n  DataList(Cons(Symbol(\"val\"), tail)) and tail is\n    Cons(param, Cons(expr, Cons(rest, Nil))) then\n      eval(rest, env +: [toName(param), eval(expr, env)])\n    else error\n  DataList(Cons(Symbol(\"def\"), Cons(param, Cons(body, Cons(rest, Nil))))) then\n    let env' = extendRec of env, toName(param), (env => eval(body, env))\n    eval(rest, env')\n  DataList(Cons(Symbol(\"if\"), Cons(cond, Cons(thenPart, Cons(elsePart, Nil))))) and\n    eval(cond, env) is Literal(IntLit(0)) then eval(elsePart, env)\n    else eval(thenPart, env)\n  DataList(Cons(Symbol(\"quote\"), Cons(y, Nil))) then y\n  DataList(Cons(Symbol(\"lambda\"), Cons(params, Cons(body, Nil)))) then\n    let ps = map(toName, asList(params))\n    Literal(Lambda(args => eval(body, extendParameters(env, ps, args))))\n  DataList(Cons(operator, operands)) and eval(operator, env) is\n    Literal(Lambda(f)) then f of map((x) => eval(x, env), operands)\n    else error // application of a non-function\n  else error // unrecognized program\n//│ fun eval: (x: Data, env: Str -> Data) -> Data\n\nfun showEval(source: Str): Str =\n  if parseExpr(tokenize(source)) is\n    [Success(data), _] then \"Ok: \" ++ showData of eval(data, globalEnv)\n    [Failure(error), _] then \"Error: \" ++ error\n//│ fun showEval: (source: Str) -> Str\n\nshowEval(\"1\")\nshowEval(\"(+ 1 2)\")\nshowEval(\"(val x 7 (val y 6 (* x y)))\")\nshowEval(\"(quote x)\")\nshowEval(\"(cons 1 nil)\")\nshowEval(\"(car (cons 1 nil))\")\nshowEval(\"(null 0)\")\nshowEval(\"(null nil)\")\nshowEval(\"(def id (lambda (x) x) (id 42))\")\n//│ Str\n//│ res\n//│     = 'Ok: 1'\n//│ res\n//│     = 'Ok: 3'\n//│ res\n//│     = 'Ok: 42'\n//│ res\n//│     = 'Ok: x'\n//│ res\n//│     = 'Ok: (1)'\n//│ res\n//│     = 'Ok: 1'\n//│ res\n//│     = 'Ok: 0'\n//│ res\n//│     = 'Ok: 1'\n//│ res\n//│     = 'Ok: 42'\n\nshowEval(\"(def fact (lambda (n) (if (eq n 0) 1 (* n (fact (- n 1))))) (fact 5))\")\nshowEval(\"(def fib (lambda (n) (if (eq n 0) 0 (if (eq n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))) (fib 10))\")\nshowEval(\"(def sum (lambda (n) (if (eq n 0) 0 (+ n (sum (- n 1))))) (sum 50))\")\nshowEval(\"(def ack (lambda (m n) (if (eq m 0) (+ n 1) (if (eq n 0) (ack (- m 1) 1) (ack (- m 1) (ack m (- n 1)))))) (ack 3 2))\")\n//│ Str\n//│ res\n//│     = 'Ok: 120'\n//│ res\n//│     = 'Ok: 55'\n//│ res\n//│     = 'Ok: 1275'\n//│ res\n//│     = 'Ok: 29'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/List.mls",
    "content": ":NewDefs\n\n// TODO\nabstract class List[out A]: (Cons[A] | Nil) {\n  fun isEmpty: Bool\n  fun map[B]: (A -> B) -> List[B]\n}\nclass Cons[out A](head: A, tail: List[A]) extends List[A] {\n  fun isEmpty: Bool = false\n  fun map(f) = Cons(f(head), tail.map(f))\n}\nmodule Nil extends List {\n  fun isEmpty: Bool = true\n  fun map(f) = Nil\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.10: \t  fun map(f) = Cons(f(head), tail.map(f))\n//│ ╙──      \t                                 ^^^^\n//│ abstract class List[A]: Cons[A] | Nil {\n//│   fun isEmpty: Bool\n//│   fun map: forall 'B. (A -> 'B) -> List['B]\n//│ }\n//│ class Cons[A](head: A, tail: List[A]) extends List {\n//│   fun isEmpty: Bool\n//│   fun map: forall 'A. (A -> 'A) -> Cons['A]\n//│ }\n//│ module Nil extends List {\n//│   fun isEmpty: Bool\n//│   fun map: anything -> Nil\n//│ }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/Option.mls",
    "content": ":NewDefs\n\nabstract class MyOption[out T]: (MySome[T] | MyNone) {\n  virtual fun filter: (p: T -> Bool) -> MyOption[T]\n}\nclass MySome[out T](val value: T) extends MyOption[T] {\n  fun filter(p) = if p of value then MySome(value) else MyNone\n}\nmodule MyNone extends MyOption[nothing] {\n  fun filter(_) = MyNone\n}\n//│ abstract class MyOption[T]: MyNone | MySome[T] {\n//│   fun filter: (p: T -> Bool) -> MyOption[T]\n//│ }\n//│ class MySome[T](value: T) extends MyOption {\n//│   fun filter: (T -> Bool) -> (MyNone | MySome[T])\n//│ }\n//│ module MyNone extends MyOption {\n//│   fun filter: anything -> MyNone\n//│ }\n\n// The following code aims to find a workaround that allows the functions\n// operating ADT to be defined as member functions of classes, and also ensures\n// the correct generation of JavaScript code.\n\n// Create an alias constructor for `Some`\n// ======================================\n// // This works:\nfun some: forall 'a: 'a -> Option['a]\nfun some = x => Some(x)\n// // This doesn't work with `map`:\n// let some: forall 'a: 'a -> Option['a] = x => Some(x)\n//\n// Create an alias constructor for `None`\n// ======================================\n// // This works:\n// fun none: forall 'a: () -> Option['a]\n// fun none = () => None\n// // This also works:\n// fun none: Option[nothing]\n// fun none = None\n// This also works:\nlet none: () -> Option[nothing] = () => None\n// // This also works but failed in code generation:\n// let none: Option[nothing] = None\n//\n// The class definitions\n// =====================\nabstract class Option[out T]: (Some[T] | None) {\n  virtual fun isEmpty: Bool\n  virtual fun isDefined: Bool\n  virtual fun map: forall 'b: (T -> 'b) -> Option['b]\n  virtual fun flatMap: forall 'b: (T -> Option['b]) -> Option['b]\n  virtual fun filter: (p: T -> Bool) -> Option[T]\n  virtual fun get: T\n}\nclass Some[out T](val value: T) extends Option[T] {\n  fun isEmpty = false\n  fun isDefined = true\n  fun map(f) = some(f(value))\n  fun flatMap(f) = f(value)\n  fun filter(p) = if p of value then some(value) else none()\n  fun get = value\n}\nmodule None extends Option[nothing] {\n  fun isEmpty = true\n  fun isDefined = false\n  fun map(_) = none()\n  fun flatMap(_) = none()\n  fun filter(_) = none()\n  fun get = error\n}\n//│ fun some: forall 'T. 'T -> Some['T]\n//│ let none: () -> Option[nothing]\n//│ abstract class Option[T]: None | Some[T] {\n//│   fun filter: (p: T -> Bool) -> Option[T]\n//│   fun flatMap: forall 'b. (T -> Option['b]) -> Option['b]\n//│   fun get: T\n//│   fun isDefined: Bool\n//│   fun isEmpty: Bool\n//│   fun map: forall 'b0. (T -> 'b0) -> Option['b0]\n//│ }\n//│ class Some[T](value: T) extends Option {\n//│   fun filter: (T -> Bool) -> Option[T]\n//│   fun flatMap: forall 'c. (T -> 'c) -> 'c\n//│   fun get: T\n//│   fun isDefined: true\n//│   fun isEmpty: false\n//│   fun map: forall 'a. (T -> 'a) -> Option['a]\n//│ }\n//│ module None extends Option {\n//│   fun filter: anything -> Option[nothing]\n//│   fun flatMap: anything -> Option[nothing]\n//│   fun get: nothing\n//│   fun isDefined: false\n//│   fun isEmpty: true\n//│   fun map: anything -> Option[nothing]\n//│ }\n//│ fun some: forall 'a0. 'a0 -> Option['a0]\n//│ none\n//│      = [Function: none]\n\nsome(0).map(x => x + 1).get\n//│ Int\n//│ res\n//│     = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/STLC.mls",
    "content": ":NewDefs\n\nfun (++) concatOp(a, b) = concat(a)(b)\n//│ fun (++) concatOp: (Str, Str) -> Str\n\nfun par(a) = \"(\" ++ a ++ \")\"\n//│ fun par: Str -> Str\n\ntype Option[out A] = Some[A] | None\nclass Some[out A](value: A)\nmodule None\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A)\n//│ module None\n\ntype Result[A, B] = Ok[A] | Err[B]\nclass Ok[A](value: A)\nclass Err[A](message: A)\n//│ type Result[A, B] = Err[B] | Ok[A]\n//│ class Ok[A](value: A)\n//│ class Err[A](message: A)\n\ntype Type = FunctionType | PrimitiveType\nclass PrimitiveType(name: Str)\nclass FunctionType(lhs: Type, rhs: Type)\n//│ type Type = FunctionType | PrimitiveType\n//│ class PrimitiveType(name: Str)\n//│ class FunctionType(lhs: Type, rhs: Type)\n\n// Helpers.\nfun _f(lhs, rhs) = FunctionType(lhs, rhs)\nfun _t(name) = PrimitiveType(name)\n//│ fun _f: (Type, Type) -> FunctionType\n//│ fun _t: Str -> PrimitiveType\n\ntype Term = Lit | Var | Abs | App\nclass Lit(tag: Str, ty: Type)\nclass Var(name: Str)\nclass Abs(lhs: Var, lty: Type, rhs: Term)\nclass App(lhs: Term, rhs: Term)\n// class App(lhs: Term, rhs: Term): Term\n//│ type Term = Abs | App | Lit | Var\n//│ class Lit(tag: Str, ty: Type)\n//│ class Var(name: Str)\n//│ class Abs(lhs: Var, lty: Type, rhs: Term)\n//│ class App(lhs: Term, rhs: Term)\n\ntype TreeMap[A] = Node[A] | Empty\nclass Node[A](key: Str, value: A, left: TreeMap[A], right: TreeMap[A])\nmodule Empty\n//│ type TreeMap[A] = Empty | Node[A]\n//│ class Node[A](key: Str, value: A, left: TreeMap[A], right: TreeMap[A])\n//│ module Empty\n\nfun insert(t, k, v) =\n  if t is\n    Node(k', _, l, r) and\n      slt(k, k') then Node(k', v, insert(l, k, v), r)\n      sgt(k, k') then Node(k', v, l, insert(r, k, v))\n      _ then Node(k, v, l, r)\n    Empty then Node(k, v, Empty, Empty)\nfun find(t, k) =\n  if t is\n    Node(k', v, l, r) and\n      slt(k, k') then find(l, k)\n      sgt(k, k') then find(r, k)\n      _ then Some(v)\n    Empty then None\n//│ fun insert: forall 'A. (Empty | Node['A], Str, 'A) -> Node['A]\n//│ fun find: forall 'A0. (Empty | Node['A0], Str) -> (None | Some['A0])\n\nfun showType(ty) =\n  if ty is\n    FunctionType(PrimitiveType(name), rhs) then name ++ \" -> \" ++ showType(rhs)\n    FunctionType(lhs, rhs) then \"(\" ++ showType(lhs) ++ \") -> \" ++ showType(rhs)\n    PrimitiveType(name) then name\n//│ fun showType: (FunctionType | PrimitiveType) -> Str\n\nshowType(_t(\"int\"))\nshowType(_f(_t(\"int\"), _t(\"bool\")))\nshowType(_f(_f(_t(\"int\"), _t(\"bool\")), _t(\"bool\")))\nshowType(_f(_t(\"bool\"), _f(_t(\"int\"), _t(\"bool\"))))\n//│ Str\n//│ res\n//│     = 'int'\n//│ res\n//│     = 'int -> bool'\n//│ res\n//│     = '(int -> bool) -> bool'\n//│ res\n//│     = 'bool -> int -> bool'\n\nfun typeEqual(t1, t2) =\n  if\n    t1 is PrimitiveType(name1) and t2 is PrimitiveType(name2) then eq(name1)(name2)\n    t1 is FunctionType(lhs1, rhs1) and t2 is FunctionType(lhs2, rhs2) then\n      typeEqual(lhs1, lhs2) and typeEqual(rhs1, rhs2)\n    _ then false\n//│ fun typeEqual: (Object, Object) -> Bool\n\nfun showTerm(t) =\n  if t is\n    Lit(tag, _) then tag\n    Var(name) then name\n    Abs(lhs, ty, rhs) then \"&\" ++ showTerm(lhs) ++ \": \" ++ showType(ty) ++ \" => \" ++ showTerm(rhs)\n    App(Abs(lhs0, ty, lhs1), rhs) then\n      \"((\" ++ showTerm(Abs(lhs0, ty, rhs)) ++ \") \" ++ showTerm(rhs) ++ \")\"\n    App(lhs, rhs) then par(showTerm(lhs) ++ \" \" ++ showTerm(rhs))\n//│ fun showTerm: (Abs | App | Lit | Var) -> Str\n\nshowTerm(Var(\"x\"))\nshowTerm(Abs(Var(\"x\"), _t(\"int\"), Var(\"y\")))\nshowTerm(App(Var(\"x\"), Var(\"y\")))\nshowTerm(App(Abs(Var(\"x\"), _t(\"int\"), Var(\"y\")), Var(\"z\")))\n//│ Str\n//│ res\n//│     = 'x'\n//│ res\n//│     = '&x: int => y'\n//│ res\n//│     = '(x y)'\n//│ res\n//│     = '((&x: int => z) z)'\n\n// Removing the return type annotation causes stack overflow.\nfun typeTerm(t: Term, ctx: TreeMap[Type]): Result[Type, Str] =\n  if t is\n    Lit(_, ty) then Ok(ty)\n    Var(name) and find(ctx, name) is\n      Some(ty) then Ok(ty)\n      None then Err(\"unbound variable `\" ++ name ++ \"`\")\n    Abs(Var(name), ty, body) and typeTerm(body, insert(ctx, name, ty)) is\n      Ok(resTy) then Ok(FunctionType(ty, resTy))\n      Err(message) then Err(message)\n    App(lhs, rhs) and typeTerm(lhs, ctx) is\n      Ok(FunctionType(pTy, resTy)) and typeTerm(rhs, ctx) is\n        Ok(aTy) and\n          typeEqual(pTy, aTy) then Ok(resTy)\n          else Err(\"expect the argument to be of type `\" ++ showType(pTy) ++ \"` but found `\" ++ showType(aTy) ++ \"`\")\n        Err(message) then Err(message)\n      Ok(PrimitiveType(name)) then Err(\"cannot apply primitive type `\" ++ name ++ \"`\")\n      Err(message) then Err(message)\n//│ fun typeTerm: (t: Term, ctx: TreeMap[Type]) -> Result[Type, Str]\n\nfun showTypeTerm(t, ctx) =\n  if typeTerm(t, ctx) is\n    Ok(ty) then showTerm(t) ++ \" : \" ++ showType(ty)\n    Err(message) then \"Type error: \" ++ message\n//│ fun showTypeTerm: (Term, TreeMap[Type]) -> Str\n\nshowTypeTerm(Var(\"x\"), Empty)\nshowTypeTerm(Abs(Var(\"x\"), _t(\"int\"), Var(\"x\")), Empty)\nshowTypeTerm(App(Var(\"f\"), Lit(\"0\", _t(\"int\"))), insert(Empty, \"f\", _f(_t(\"int\"), _t(\"int\"))))\nshowTypeTerm(App(Var(\"f\"), Lit(\"0.2\", _t(\"float\"))), insert(Empty, \"f\", _f(_t(\"int\"), _t(\"int\"))))\nshowTypeTerm(App(Var(\"f\"), Lit(\"0\", _t(\"int\"))), insert(Empty, \"f\", _t(\"Str\")))\n//│ Str\n//│ res\n//│     = 'Type error: unbound variable `x`'\n//│ res\n//│     = '&x: int => x : int -> int'\n//│ res\n//│     = '(f 0) : int'\n//│ res\n//│     = 'Type error: expect the argument to be of type `int` but found `float`'\n//│ res\n//│     = 'Type error: cannot apply primitive type `Str`'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/SimpleLisp.mls",
    "content": ":NewDefs\n\nfun (++) strcat(a: Str, b: Str): Str = concat(a)(b)\n//│ fun (++) strcat: (a: Str, b: Str) -> Str\n\ndeclare module JSON {\n  fun stringify: (data: anything) -> Str\n}\ndeclare class Function(source: Str) {\n  fun call: () -> nothing\n}\nfun fatal(message: Str): nothing =\n  let raise = Function(\"throw new Error(\" ++ JSON.stringify(message) ++ \")\")\n  raise.call()\n//│ declare module JSON {\n//│   fun stringify: (data: anything) -> Str\n//│ }\n//│ declare class Function(source: Str) {\n//│   fun call: () -> nothing\n//│ }\n//│ fun fatal: (message: Str) -> nothing\n\nabstract class List[A]: Nil | Cons[A]\nclass Cons[A](head: A, tail: List[A]) extends List[A]\nmodule Nil extends List\nfun (::) cons[A](head: A, tail: List[A]): List[A] = Cons(head, tail)\nfun map(f: 'A -> 'B, list: List['A]): List['B] =\n  if list is\n    Nil then Nil\n    Cons(head, tail) then Cons(f(head), map(f, tail))\nfun showList(sep: Str, showItem: 'A -> Str) =\n  let rec aux(list: List['A]) =\n    if list is\n      Nil then \"\"\n      Cons(head, Nil) then showItem(head)\n      Cons(head, tail) then showItem(head) ++ sep ++ aux(tail)\n  aux\n//│ abstract class List[A]: Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A]) extends List\n//│ module Nil extends List\n//│ fun (::) cons: forall 'A. (head: 'A, tail: List['A]) -> List['A]\n//│ fun map: forall 'A0 'A1. (f: 'A0 -> 'A1, list: List['A0]) -> List['A1]\n//│ fun showList: forall 'A2. (sep: Str, showItem: 'A2 -> Str) -> (forall 'A3. (list: List['A3]) -> Str)\n//│ where\n//│   'A3 <: 'A2\n\nabstract class Context: Empty | Bind\nmodule Empty extends Context\nclass Bind(name: Str, data: Data, tail: Context) extends Context\nfun find(name: Str, context: Context): Data =\n  if context is\n    Empty then fatal(\"undefined symbol \" ++ name)\n    Bind(name', data, t) then\n      if name' === name then data\n      else find(name, t)\nabstract class Data: ListData | Quote | Symbol | Literal | Builtin | Thunk\nclass ListData(list: List[Data]) extends Data\nclass Quote(data: Data) extends Data\nclass Symbol(name: Str) extends Data\nclass Literal(value: Int) extends Data\nclass Builtin(impl: (List[Data], Context) -> Data) extends Data\nclass Thunk(impl: (Context) -> Data) extends Data\n//│ abstract class Context: Bind | Empty\n//│ module Empty extends Context\n//│ class Bind(name: Str, data: Data, tail: Context) extends Context\n//│ fun find: (name: Str, context: Context) -> Data\n//│ abstract class Data: Builtin | ListData | Literal | Quote | Symbol | Thunk\n//│ class ListData(list: List[Data]) extends Data\n//│ class Quote(data: Data) extends Data\n//│ class Symbol(name: Str) extends Data\n//│ class Literal(value: Int) extends Data\n//│ class Builtin(impl: (List[Data], Context) -> Data) extends Data\n//│ class Thunk(impl: Context -> Data) extends Data\n\nfun showData(data: Data): Str =\n  if data is\n    ListData(list) then \"(\" ++ showList(\" \", showData)(list) ++ \")\"\n    Quote(data) then \"'\" ++ showData(data)\n    Symbol(name) then name\n    Literal(value) then toString(value)\n    Builtin(impl) then \"<builtin>\"\n    Thunk(impl) then \"<thunk>\"\n//│ fun showData: (data: Data) -> Str\n\nfun add(arguments: List[Data], context: Context): Data =\n  if arguments is Cons(Literal(a), Cons(Literal(b), Nil)) then Literal(a + b) else fatal(\"invalid arguments\")\n//│ fun add: (arguments: List[Data], context: Context) -> Data\n\nlet context = Bind(\"+\", Builtin(add), Empty)\n//│ let context: Bind\n//│ context\n//│         = Bind {}\n\nfun eval(program: Data, context: Context): Data =\n  if program is\n    Literal(value) then Literal(value)\n    Symbol(name) then find(name, context)\n    Thunk(impl) then impl(context)\n    ListData(Cons(Symbol(\"let\"), Cons(Symbol(name), Cons(data, Cons(rest, Nil))))) then\n      let data' = eval(data, context)\n      let context' = Bind(name, data', context)\n      eval(rest, context')\n    ListData(Cons(Symbol(\"val\"), Cons(Symbol(name), Cons(data, Cons(rest, Nil))))) then\n      let data' = Thunk((context) => eval(data, context))\n      let context' = Bind(name, data', context)\n      eval(rest, context')\n    ListData(Cons(Symbol(\"if\"), Cons(test, Cons(thenPart, Cons(elsePart, Nil))))) and\n      eval(test, context) is Literal(0) then eval(elsePart, context)\n      else eval(thenPart, context)\n    ListData(Cons(Symbol(\"quote\"), Cons(data, Nil))) then data\n    ListData(Cons(Symbol(callee), arguments)) and\n      let callee' = find(callee, context)\n      let arguments' = map(argument => eval(argument, context), arguments)\n      callee' is Builtin(impl) then impl(arguments', context)\n      else fatal(\"callee is not callable\")\n    else fatal(\"unknown program\")\n//│ fun eval: (program: Data, context: Context) -> Data\n\nlet data1 = ListData of Symbol(\"+\") :: Literal(1) :: Literal(2) :: Nil\nshowData of data1\nshowData of eval(data1, context)\n//│ let data1: ListData\n//│ Str\n//│ data1\n//│       = ListData {}\n//│ res\n//│     = '(+ 1 2)'\n//│ res\n//│     = '3'\n\nlet data2 = ListData of Symbol(\"let\") :: Symbol(\"x\") :: Literal(1) :: (ListData of Symbol(\"+\") :: Symbol(\"x\") :: Literal(2) :: Nil) :: Nil\nshowData of data2\nshowData of eval(data2, context)\n//│ let data2: ListData\n//│ Str\n//│ data2\n//│       = ListData {}\n//│ res\n//│     = '(let x 1 (+ x 2))'\n//│ res\n//│     = '3'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/SimpleList.mls",
    "content": ":NewDefs\n\nabstract class List[T]: (Cons[T] | Nil)\nclass Cons[T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\n1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: Nil\n//│ Cons['T]\n//│   where\n//│     'T :> 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8\n//│ res\n//│     = Cons {}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/examples/SimpleTree.mls",
    "content": ":NewDefs\n\n// abstract class Tree[out A]: (Empty | Node[A])\n// class Node[out A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A]\n// module Empty extends Tree\n// //│ abstract class Tree[A]: Empty | Node[A]\n// //│ class Node[A](value: A, left: Tree[A], right: Tree[A]) extends Tree\n// //│ module Empty extends Tree\n\n// fun insert(t, v) = if t is\n//   Node(v', l, r) and\n//     v < v' then Node(v', insert(l, v), r)\n//     v > v' then Node(v', l, insert(r, v))\n//     _ then t\n//   Empty then Node(v, Empty, Empty)\n// //│ fun insert: forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A])\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\n1 :: 2 :: 3 :: 4 :: Nil\n//│ Cons[1 | 2 | 3 | 4]\n//│ res\n//│     = Cons {}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/DirectLines.mls",
    "content": ":NewDefs\n\nfun f(x, y) =\n  if\n    x == 0 then \"x\"\n    y == 0 then \"y\"\n    _      then \"nah\"\n//│ fun f: (Num, Num) -> (\"nah\" | \"x\" | \"y\")\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nfun isValid(x) = if x then false else true\n//│ fun isValid: Bool -> Bool\n\nfun f(x, allowNone) =\n  if x\n    is Some(x) and isValid(x) then \"good\"\n    is None and allowNone then \"okay\"\n    is _ then \"bad\"\n//│ fun f: (Object & ~#Some | Some[Bool], Bool) -> (\"bad\" | \"good\" | \"okay\")\n\nfun f(x, y, z) =\n  if\n    x == 0 then \"x\"\n    y ==\n      1 then \"y = 1\"\n      2 and z ==\n        0 then \"z = 0\"\n        9 then \"z = 9\"\n        _ then \"bruh\"\n      3 then \"y = 3\"\n      _ then \"bruh\"\n//│ fun f: (Num, Num, Num) -> (\"bruh\" | \"x\" | \"y = 1\" | \"y = 3\" | \"z = 0\" | \"z = 9\")\n\n:w\nfun f(a, b) =\n  if\n    a == 0 then 0\n    b ==\n      1 then 1\n      2 then 2\n      _ then 7\n    else 3\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.48: \t    else 3\n//│ ║        \t         ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.47: \t      _ then 7\n//│ ╙──      \t             ^\n//│ fun f: (Num, Num) -> (0 | 1 | 2 | 7)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/ElseIf.mls",
    "content": ":NewDefs\n\n\n\nfun f(x, y) = if x ===\n    0 then true\n    1 then false\n  else if y ===\n    0 then true\n    1 then false\n  else false\n//│ fun f: (Eql[0 | 1], Eql[0 | 1]) -> Bool\n\nfun f(x, y) = if x ===\n    0 then true\n    1 then false\n  else if y ===\n    0 then true\n    _ then false\n//│ fun f: (Eql[0 | 1], Eql[0]) -> Bool\n\nmodule Tru\nmodule Fals\n//│ module Tru\n//│ module Fals\n\n:e\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n//│ ╔══[ERROR] when `x` is `Tru`\n//│ ║  l.29: \t    Tru and y is Tru then true\n//│ ║        \t    ^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.29: \t    Tru and y is Tru then true\n//│ ║        \t            ^\n//│ ╟── it can be module `Fals`\n//│ ║  l.30: \t    Fals and y is Fals then false\n//│ ╙──      \t                  ^^^^\n//│ ╔══[ERROR] when `x` is `Fals`\n//│ ║  l.30: \t    Fals and y is Fals then false\n//│ ║        \t    ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.30: \t    Fals and y is Fals then false\n//│ ║        \t             ^\n//│ ╟── it can be module `Tru`\n//│ ║  l.29: \t    Tru and y is Tru then true\n//│ ╙──      \t                 ^^^\n//│ fun f: (Fals | Tru, nothing) -> Bool\n\n// The base case.\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n    Tru and y is Fals then true\n    Fals and y is Tru then true\n//│ fun f: (Fals | Tru, Fals | Tru) -> Bool\n\n// Replace the `x is Fals` with `_`\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n    _ and y is\n      Tru then true\n      Fals then false\n//│ fun f: (Object, Fals | Tru) -> Bool\n\nf(Tru, Tru)\nf(Tru, Fals)\nf(Fals, Tru)\nf(Fals, Fals)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = true\n//│ res\n//│     = false\n\n:e\nfun g(x, y) = if x is\n  true and y is true then true\n  false and y is false then false\n//│ ╔══[ERROR] `y` has 1 missing case\n//│ ║  l.84: \t  true and y is true then true\n//│ ║        \t           ^\n//│ ╟── it can be Boolean value `false`\n//│ ║  l.85: \t  false and y is false then false\n//│ ╙──      \t                 ^^^^^\n//│ ╔══[ERROR] `y` has 1 missing case\n//│ ║  l.85: \t  false and y is false then false\n//│ ║        \t            ^\n//│ ╟── it can be Boolean value `true`\n//│ ║  l.84: \t  true and y is true then true\n//│ ╙──      \t                ^^^^\n//│ fun g: (Bool, nothing) -> Bool\n\n// Test with real booleans\nfun g(x, y) = if x is\n  true and y is true then true\n  false and y is false then false\n  _ and y is\n    true then true\n    false then false\n//│ fun g: (Object, Bool) -> Bool\n\n// Chained UCS terms\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n  else if y is\n    Tru then true\n    Fals then false\n//│ fun f: (Object, Fals | Tru) -> Bool\n\n:e\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n  else if y is\n    Tru and x is Fals then true\n    Fals and x is Tru then false\n//│ ╔══[ERROR] when `y` is `Tru`\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t    ^^^\n//│ ╟── `x` has 1 missing case\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t            ^\n//│ ╟── it can be module `Tru`\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ╙──       \t                  ^^^\n//│ ╔══[ERROR] when `y` is `Fals`\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t    ^^^^\n//│ ╟── `x` has 1 missing case\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t             ^\n//│ ╟── it can be module `Fals`\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ╙──       \t                 ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^\n//│ ╟── class pattern of type `Tru` is not an instance of type `Fals`\n//│ ║  l.120: \t    Tru and y is Tru then true\n//│ ║         \t    ^^^\n//│ ╟── but it flows into reference with expected type `Fals`\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t            ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ╙──       \t                 ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t             ^^^^^^^^^^^^^^^^^^^\n//│ ╟── class pattern of type `Fals` is not an instance of type `Tru`\n//│ ║  l.121: \t    Fals and y is Fals then false\n//│ ║         \t    ^^^^\n//│ ╟── but it flows into reference with expected type `Tru`\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t             ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ╙──       \t                  ^^^\n//│ fun f: (Fals | Tru, Fals | Tru) -> Bool\n\nfun h(x, y, p) = if\n  x and p(x) then 0\n  y is\n    Tru then 1\n    Fals then 2\n//│ fun h: forall 'a. ('a & Bool, Fals | Tru, 'a -> Bool) -> (0 | 1 | 2)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/ErrorMessage.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int)\n//│ class Point(x: Int, y: Int)\n\n:e\nfun f(p) =\n  if p is\n    Point(x, y, z) then x + y + z\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ╟── tuple literal of type `{0: ?#x, 1: ?#y}` does not have field '2'\n//│ ║  l.3: \tclass Point(x: Int, y: Int)\n//│ ║       \t            ^^^^^^^^^\n//│ ╟── but it flows into operator application with expected type `{2: ?a}`\n//│ ║  l.8: \t  if p is\n//│ ║       \t     ^^^^\n//│ ║  l.9: \t    Point(x, y, z) then x + y + z\n//│ ╙──     \t^^^^^^^^^\n//│ fun f: Point -> Int\n\n:e\n:ge\nfun g(xs) =\n  if xs is\n    head :: _ then head\n//│ ╔══[ERROR] type identifier `::` not found\n//│ ║  l.25: \t    head :: _ then head\n//│ ╙──      \t         ^^\n//│ ╔══[ERROR] type identifier not found: ::\n//│ ║  l.25: \t    head :: _ then head\n//│ ╙──      \t         ^^\n//│ fun g: nothing -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol ::\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/Exhaustiveness.mls",
    "content": ":NewDefs\n:NoJS\n\nclass A()\nclass B()\nclass C()\n//│ class A()\n//│ class B()\n//│ class C()\n\n:e\nfun f(x, y) =\n  if\n    y is A and\n      x is\n        A then 0\n        B then 1\n        C then 2\n    y is B and\n      x is\n        A then 4\n//│ ╔══[ERROR] when `y` is `B`\n//│ ║  l.19: \t    y is B and\n//│ ║        \t         ^\n//│ ╟── `x` has 2 missing cases\n//│ ║  l.20: \t      x is\n//│ ║        \t      ^\n//│ ╟── it can be class `B`\n//│ ║  l.17: \t        B then 1\n//│ ║        \t        ^\n//│ ╟── it can be class `C`\n//│ ║  l.18: \t        C then 2\n//│ ╙──      \t        ^\n//│ fun f: (A, A | B) -> (0 | 1 | 2 | 4)\n\n:e\n// These operators are uninterpreted. So, it's impossible to reason the\n// exhaustiveness without SMT solvers.\ntype Tree[A] = Node[A] | Empty\nmodule Empty {\n  fun contains(wanted) = false\n}\nclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n  fun contains(wanted) = if wanted\n    <= value then left.find(wanted)\n    >= value then right.find(wanted)\n    == value then true\n}\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.47: \t    == value then true\n//│ ╙──      \t                  ^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.44: \t  fun contains(wanted) = if wanted\n//│ ║        \t                            ^^^^^^\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `Num`\n//│ ║  l.43: \tclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│ ║        \t                     ^^^\n//│ ╟── but it flows into reference with expected type `Num`\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] Type `#Node & {Node#A = A}` does not contain member `find`\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ╙──      \t                      ^^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.44: \t  fun contains(wanted) = if wanted\n//│ ║        \t                            ^^^^^^\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `Num`\n//│ ║  l.43: \tclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│ ║        \t                     ^^^\n//│ ╟── but it flows into reference with expected type `Num`\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] Type `#Node & {Node#A = A}` does not contain member `find`\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ╙──      \t                       ^^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.44: \t  fun contains(wanted) = if wanted\n//│ ║        \t                            ^^^^^^\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.47: \t    == value then true\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `Num`\n//│ ║  l.43: \tclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│ ║        \t                     ^^^\n//│ ╟── but it flows into reference with expected type `Num`\n//│ ║  l.47: \t    == value then true\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.47: \t    == value then true\n//│ ║        \t                  ^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ type Tree[A] = Empty | Node[A]\n//│ module Empty {\n//│   fun contains: anything -> false\n//│ }\n//│ class Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│   fun contains: Num -> (error | true)\n//│ }\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/Humiliation.mls",
    "content": ":NewDefs\n\n\nclass Foo[T](x: T)\n//│ class Foo[T](x: T)\n\nif 1 is 1 then 1 else 0\n//│ 0 | 1\n//│ res\n//│     = 1\n\nfun test(x) = if x is 1 then 0 else 1\n//│ fun test: Object -> (0 | 1)\n\n:w\nfun testF(x) = if x is\n  Foo(a) then a\n  Foo(a) then a\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.18: \t  Foo(a) then a\n//│ ║        \t  ^^^\n//│ ╟── there is an identical pattern Foo\n//│ ║  l.17: \t  Foo(a) then a\n//│ ╙──      \t  ^^^\n//│ fun testF: forall 'a. Foo['a] -> 'a\n\nclass Bar[Y, Z](y: Y, z: Z)\n//│ class Bar[Y, Z](y: Y, z: Z)\n\nfun test(f) = if f is\n  Foo(a) then a\n  Bar(b, c) then b + c\n//│ fun test: forall 'a. (Bar[Int, Int] | Foo['a]) -> (Int | 'a)\n\n\nclass Pair[A, B](fst: A, snd: B)\n//│ class Pair[A, B](fst: A, snd: B)\n\nfun f(x) =\n  if x is\n    Pair(0, 0) then \"zeros\"\n    Pair(1, 1) then \"ones\"\n    Pair(y, 1) then x\n    _          then \"nah\"\n//│ fun f: (Object & ~#Pair | Pair[Object, Object]) -> (\"nah\" | \"ones\" | \"zeros\" | Pair[nothing, nothing])\n\nclass Z()\nclass O()\n//│ class Z()\n//│ class O()\n\n// This is not exhaustive.\n:e\nfun foo(x) = if x is\n  Pair(Z(), Z()) then \"zeros\"\n  Pair(O(), O()) then \"ones\"\n//│ ╔══[ERROR] when `x` is `Pair`, and\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║        \t  ^^^^\n//│ ╟── the first argument of `Pair` is `Z`,\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║        \t       ^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `O`\n//│ ║  l.56: \t  Pair(O(), O()) then \"ones\"\n//│ ╙──      \t            ^\n//│ ╔══[ERROR] when `x` is `Pair`, and\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║        \t  ^^^^\n//│ ╟── the first argument of `Pair` is `O`,\n//│ ║  l.56: \t  Pair(O(), O()) then \"ones\"\n//│ ║        \t       ^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `Z`\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ╙──      \t            ^\n//│ fun foo: Pair[O | Z, nothing] -> (\"ones\" | \"zeros\")\n\n// Change `Pair` to a real pair.\n:e\nfun foo(x) = if x is\n  [Z(), Z()] then \"zeros\"\n  [O(), O()] then \"ones\"\n//│ ╔══[ERROR] when `x$Tuple$2_0` is `O`\n//│ ║  l.83: \t  [O(), O()] then \"ones\"\n//│ ║        \t   ^\n//│ ╟── `x$Tuple$2_1` has 1 missing case\n//│ ╟── it can be class `Z`\n//│ ║  l.82: \t  [Z(), Z()] then \"zeros\"\n//│ ╙──      \t        ^\n//│ fun foo: forall 'a. {0: O | Z, 1: O & 'a} -> (\"ones\" | \"zeros\" | 'a)\n\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      Z() then \"zeros\"\n    O() then if b is\n      O() then \"ones\"\n//│ fun foo: Pair[O | Z, nothing] -> (\"ones\" | \"zeros\")\n\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      Z() then \"zeros\"\n      else \"???\"\n    O() then if b is\n      O() then \"ones\"\n//│ fun foo: Pair[O | Z, O] -> (\"???\" | \"ones\" | \"zeros\")\n\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      Z() then \"zeros\"\n      else \"???\"\n    O() then if b is\n      O() then \"zeros\"\n      else \"???\"\n//│ fun foo: Pair[O | Z, Object] -> (\"???\" | \"zeros\")\n\nclass S(pred: S | Z | O)\n//│ class S(pred: O | S | Z)\n\n// TODO: Cannot check exhaustiveness of nested UCS yet.\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      S(x) then x\n      else \"???\"\n    O() then if b is\n      O() then \"zeros\"\n      else \"???\"\n//│ fun foo: Pair[O | Z, Object] -> (\"???\" | \"zeros\" | O | S | Z)\n\nfoo(Pair(Z(), Z()))\n//│ \"???\" | \"zeros\" | O | S | Z\n//│ res\n//│     = '???'\n\n:e\nfun foo(x) = if x is\n  Pair(Z(), Z()) then \"zeros\"\n  Pair(O(), O()) then \"ones\"\n  Pair(y, O()) then x\n//│ ╔══[ERROR] when `x` is `Pair`\n//│ ║  l.141: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║         \t  ^^^^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `Z`\n//│ ║  l.141: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ╙──       \t            ^\n//│ fun foo: forall 'A 'B. Pair['A, O & 'B] -> (\"ones\" | \"zeros\" | Pair['A, 'B] | 'A)\n//│   where\n//│     'A <: Object\n\nfun foo(x, y) = if x is Z() and y is O() then 0 else 1\n//│ fun foo: (Object, Object) -> (0 | 1)\n\nfun foo(x, y) =\n  if x is\n    Z() and y is O() then 0\n    else 1\n//│ fun foo: (Object, Object) -> (0 | 1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/InterleavedLet.mls",
    "content": ":NewDefs\n\nfun f(x) =\n  if x ==\n    let v = 0\n    v then v\n    else 0\n//│ fun f: Num -> 0\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\nclass Left[A](leftValue: A) extends Either[A, nothing]\nclass Right[B](rightValue: B) extends Either[nothing, B]\n//│ abstract class Either[A, B]: Left[A] | Right[B]\n//│ class Left[A](leftValue: A) extends Either\n//│ class Right[B](rightValue: B) extends Either\n\n:ducs:normalize.result\nfun q(x) =\n  if\n    x is Some and x is Some and x is Some then 0\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 0\n//│ fun q: Some[anything] -> 0\n\n:e\n// TODO: post-processing should combine two matches on `y`\nfun p(x, y) =\n  if\n    x is Some and y is None then 0\n    y is Some and x is Some then 1\n    x is Some and y is Some then 0\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.39: \t    x is Some and y is Some then 0\n//│ ║        \t                       ^^^^\n//│ ╟── there is an identical pattern Some\n//│ ║  l.38: \t    y is Some and x is Some then 1\n//│ ╙──      \t         ^^^^\n//│ ╔══[ERROR] `y` has 1 missing case\n//│ ║  l.38: \t    y is Some and x is Some then 1\n//│ ║        \t    ^\n//│ ╟── it can be module `None`\n//│ ║  l.37: \t    x is Some and y is None then 0\n//│ ╙──      \t                       ^^^^\n//│ fun p: (Object & ~#Some | Some[anything], Some[anything]) -> (0 | 1)\n\nfun h(x, y) =\n  if x is\n    None then y\n    let y_square = y * y\n    Some(z) then z + y_square\n//│ fun h: (None | Some[Int], Int) -> Int\n\nh(Some(5), 6)\n//│ Int\n//│ res\n//│     = 41\n\nfun h(x, y) =\n  if x is\n    None then y\n    let y_square = y * y\n    Some(y_square) then 0\n//│ fun h: forall 'a. (None | Some[anything], Int & 'a) -> (0 | 'a)\n\n:e\nfun f(a, y) =\n  if a is\n    Some(v) and v is\n      Left(x) then x\n      let y = v + 1\n      Right(x) then x + y\n    else 0\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.78: \t      let y = v + 1\n//│ ║        \t              ^^^^^\n//│ ╟── reference of type `Right[?B]` is not an instance of type `Int`\n//│ ║  l.78: \t      let y = v + 1\n//│ ╙──      \t              ^\n//│ fun f: forall 'a. (Object & ~#Some | Some[Int | Left['a] | Right[Int]], anything) -> (Int | 'a)\n\n:pe\nfun q(a) =\n  if a is\n    Left(x) then x\n    let y = a + 1\n    then y\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.93: \t    let y = a + 1\n//│ ║        \t            ^^^^^\n//│ ║  l.94: \t    then y\n//│ ╙──      \t^^^^^^^^^^\n//│ fun q: forall 'a. (Left['a] | Object & ~#Left) -> (() | 'a)\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\n:e\nfun w() =\n  if\n    A then \"A\"\n    let y = 0\n    B then \"B\"\n    else \"?\"\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.110: \t    A then \"A\"\n//│ ║         \t    ^\n//│ ╙── reference of type `() -> A` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.112: \t    B then \"B\"\n//│ ║         \t    ^\n//│ ╙── reference of type `() -> B` is not an instance of type `Bool`\n//│ fun w: () -> (\"?\" | \"A\" | \"B\")\n\nw()\n//│ \"?\" | \"A\" | \"B\"\n//│ res\n//│     = '?'\n\nfun i(x) =\n  if x is\n    A() then \"A\"\n    let y = 0\n    B() then \"B\"\n//│ fun i: (A | B) -> (\"A\" | \"B\")\n\nfun inc(x) = x + 1\n//│ fun inc: Int -> Int\n\nfun qq(x, z) =\n  if x ==\n    let y = inc(z)\n    y * y then 0\n    else 0\n//│ fun qq: (Num, Int) -> 0\n\nfun bruh(x) =\n  if\n    x == 0 then 0\n    let y = 1\n    else y\n//│ fun bruh: Num -> (0 | 1)\n\nfun f1(x) = x + 1\nfun f2(x, y) = x + y\n//│ fun f1: Int -> Int\n//│ fun f2: (Int, Int) -> Int\n\nfun ff(x) =\n  if\n    x == 0 then 0\n    let y = f1(x)\n    let z = f2(x, y)\n    z == 1 then 1\n    z == 2 then 2\n    else 0\n//│ fun ff: Int -> (0 | 1 | 2)\n\nfun p(x): Bool = true\n//│ fun p: anything -> Bool\n\nfun ip(x, y) =\n  if p(x) and\n    let z = inc(y)\n    y === z * z then \"bruh\"\n  else \"rocks\"\n//│ fun ip: (anything, Eql[Int] & Int) -> (\"bruh\" | \"rocks\")\n\nfun tr(x) =\n  if x is\n    Some(v) then v\n    let tmp = 1\n    None then tmp\n//│ fun tr: forall 'a. (None | Some['a]) -> (1 | 'a)\n\nclass Pair[A, B](val fst: A, val snd: B)\nabstract class List[out A]: Nil | Cons[A]\nmodule Nil extends List[nothing]\nclass Cons[out A](head: A, tail: List[A]) extends List[A]\n//│ class Pair[A, B](fst: A, snd: B)\n//│ abstract class List[A]: Cons[A] | Nil\n//│ module Nil extends List\n//│ class Cons[A](head: A, tail: List[A]) extends List\n\nfun (::) cons(h, t) = Cons(h, t)\nfun (++) strcat(a, b) = concat(a)(b)\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n//│ fun (++) strcat: (Str, Str) -> Str\n\nfun showList(xs) =\n  if xs is\n    Nil              then \"\"\n    Cons(head, Nil)  then toString(head)\n    Cons(head, tail) then toString(head) ++ \", \" ++ showList(tail)\n//│ fun showList: (Cons[anything] | Nil) -> Str\n\nlet zeroToThree = 0 :: 1 :: 2 :: 3 :: Nil\n//│ let zeroToThree: Cons[0 | 1 | 2 | 3]\n//│ zeroToThree\n//│             = Cons {}\n\nshowList(zeroToThree)\n//│ Str\n//│ res\n//│     = '0, 1, 2, 3'\n\nfun evenness(x) = if x % 2 is 0 then Left(x) else Right(x)\n//│ fun evenness: forall 'A 'B. (Int & 'A & 'B) -> (Left['A] | Right['B])\n\nfun mapPartition(f, xs) =\n  if xs is\n    Nil then Pair(Nil, Nil)\n    Cons(x, xs) and mapPartition(f, xs) is Pair(l, r) and f(x) is\n      Left(v) then Pair(Cons(v, l), r)\n      Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0 'A1 'A2 'B 'B0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[in 'A1 & 'A2 out 'A2, in 'B & 'B0 out 'B0 | Cons['A0]]\n//│   where\n//│     'B <: List['A0] & 'B0\n//│     'B0 :> Cons['A0] | Nil\n//│         <: 'B\n//│     'A1 <: List['A] & 'A2\n//│     'A2 :> Cons['A] | Nil\n//│         <: 'A1\n\nmapPartition(x => (if x % 2 == 0 then Left(x) else Right(x)), zeroToThree)\n//│ forall 'A 'A0 'B 'B0. Pair[in 'A & 'A0 out 'A0, in 'B & 'B0 out 'B0 | Cons[0 | 1 | 2 | 3 | 'A1]]\n//│   where\n//│     'B <: List['A1] & 'B0\n//│     'B0 :> Cons[0 | 1 | 2 | 3 | 'A1] | Nil\n//│         <: 'B\n//│     'A <: List['A2] & 'A0\n//│     'A0 :> Cons[0 | 1 | 2 | 3 | 'A2] | Nil\n//│         <: 'A\n//│ res\n//│     = Pair {}\n\n// This should be the desugaring of the above:\nfun mapPartition'(f, xs) =\n  if xs is\n    Nil then Pair(Nil, Nil)\n    Cons(x, xs) and mapPartition(f, xs) is res and res.fst is l and res.snd is r and f(x) is\n      Left(v)  then Pair(Cons(v, l), r)\n      Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition': forall 'a 'A 'A0 'A1 'A2 'A3 'B. ('a -> (Left['A & 'A0] | Right['A1 & 'A2]), Cons['a] | Nil) -> Pair[in 'A3 out Cons['A] | Nil | 'A3 | Cons['A0], in 'B out Cons['A2] | 'B | Cons['A1] | Nil]\n\nmapPartition'(x => (if x % 2 == 0 then Left(x) else Right(x)), zeroToThree)\n//│ forall 'A 'B. Pair[in 'A out Cons[0 | 1 | 2 | 3] | Nil | 'A, in 'B out Cons[0 | 1 | 2 | 3] | 'B | Nil]\n//│ res\n//│     = Pair {}\n\n// This is a very interesting side-effect example!\n\nfun mn(a) =\n  if a is\n    Some(x) and x is\n      Left(b) and b is\n        0 then \"b is 1\"\n        let _ = log(b)\n        1 then \"b is 2\"\n        2 then \"b is 3\"\n      Right(b) then \"right-defined\"\n    None       then \"undefined\"\n//│ fun mn: (None | Some[Left[0 | 1 | 2] | Right[anything]]) -> (\"b is 1\" | \"b is 2\" | \"b is 3\" | \"right-defined\" | \"undefined\")\n\nmn of None\nmn of Some of Left of 0\nmn of Some of Left of 1\nmn of Some of Left of 2\nmn of Some of Right of ()\n//│ \"b is 1\" | \"b is 2\" | \"b is 3\" | \"right-defined\" | \"undefined\"\n//│ res\n//│     = 'undefined'\n//│ res\n//│     = 'b is 1'\n//│ res\n//│     = 'b is 2'\n//│ // Output\n//│ 1\n//│ res\n//│     = 'b is 3'\n//│ // Output\n//│ 2\n//│ res\n//│     = 'right-defined'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/LeadingAnd.mls",
    "content": ":NewDefs\n\n\n\nclass Some[T](value: T)\n//│ class Some[T](value: T)\n\n\n\nfun f(a, b) = if a is\n  Some(av)\n    and b is Some(bv) then av + bv\n//│ fun f: (Some[Int], Some[Int]) -> Int\n\nfun f(a, b) = if a is Some(av)\n    and b is Some(bv)\n    then av + bv\n//│ fun f: (Some[Int], Some[Int]) -> Int\n\nfun f(a, b) = if a is\n  Some(av)\n    and b is Some(bv)\n    then av + bv\n//│ fun f: (Some[Int], Some[Int]) -> Int\n\n\n\n// FIXME (parser)\nfun f(a, b) = if a is\n  Some(av)\n    and b is Some(bv) then av + bv\n    \n//│ fun f: (Some[Int], Some[Int]) -> Int\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/LitUCS.mls",
    "content": ":NewDefs\n\nmodule A\n//│ module A\n\n// This one is easy to fix but what about the next one?\n// The following example can better reveal the essence of the problem.\nfun test(x: 0 | A) = if x is\n  0 then 0\n  A then A\n//│ fun test: (x: 0 | A) -> (0 | A)\n\n:e\n// case === (x,) (0,) of { true => 0; _ => case x of { A => A } }\nfun test(x: 0 | A) =\n  if\n    x === 0 then 0\n    x is A then A\n//│ ╔══[ERROR] Module 'A' does not support equality comparison because it does not have a parameter list\n//│ ║  l.17: \t    x === 0 then 0\n//│ ╙──      \t    ^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.18: \t    x is A then A\n//│ ║        \t    ^^^^^^^^^^^^^\n//│ ╟── type `0` is not an instance of type `A`\n//│ ║  l.15: \tfun test(x: 0 | A) =\n//│ ║        \t            ^\n//│ ╟── but it flows into reference with expected type `A`\n//│ ║  l.18: \t    x is A then A\n//│ ║        \t    ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.18: \t    x is A then A\n//│ ╙──      \t         ^\n//│ fun test: (x: 0 | A) -> (0 | A)\n\nfun test2(x) =\n  if\n    x === 0 then 0\n    x is A then A\n//│ fun test2: (A & Eql[0]) -> (0 | A)\n\n:e\ntest2(0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.43: \ttest2(0)\n//│ ║        \t^^^^^^^^\n//│ ╟── integer literal of type `0` is not an instance of type `A`\n//│ ║  l.43: \ttest2(0)\n//│ ║        \t      ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.39: \t    x is A then A\n//│ ║        \t         ^\n//│ ╟── from reference:\n//│ ║  l.39: \t    x is A then A\n//│ ╙──      \t    ^\n//│ 0 | A | error\n//│ res\n//│     = 0\n\n:e\ntest2(A)\n//│ ╔══[ERROR] Module 'A' does not support equality comparison because it does not have a parameter list\n//│ ║  l.61: \ttest2(A)\n//│ ╙──      \t^^^^^^^^\n//│ 0 | A | error\n//│ res\n//│     = A {}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/MultiwayIf.mls",
    "content": ":NewDefs\n\n\nfun f(x) =\n  if\n    x > 0  then 0\n    x == 0 then 1\n    _      then 2\n//│ fun f: Num -> (0 | 1 | 2)\n\n\nfun f(x) =\n  if\n    x > 0  and\n      x % 2 === 0 then true\n      _           then false\n    x == 0 then true\n    _      then false\n//│ fun f: Int -> Bool\n\nf(0)\nf(2)\nf(3)\nf(0 - 1)\nf(0 - 2)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n//│ res\n//│     = false\n\nfun f(x) =\n  if\n    x > 0  and\n      x % 2 === 0 then true\n      else false\n    x == 0 then true\n  else false\n//│ fun f: Int -> Bool\n\nf(0)\nf(2)\nf(1)\nf(0 - 1)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/NestedBranches.mls",
    "content": ":NewDefs\n\n\nclass Some[out A](val value: A)\nmodule None\nclass Left[out A](val leftValue: A)\nclass Right[out A](val rightValue: A)\nmodule Nil\nclass Cons[out A](val head: A, val tail: Cons[A] | Nil)\nclass Pair[out A, out B](val fst: A, val snd: B)\n//│ class Some[A](value: A)\n//│ module None\n//│ class Left[A](leftValue: A)\n//│ class Right[A](rightValue: A)\n//│ module Nil\n//│ class Cons[A](head: A, tail: Cons[A] | Nil)\n//│ class Pair[A, B](fst: A, snd: B)\n\n\nfun optionApply(x, y, f) =\n  if x is\n    Some(xv) and y is\n      Some(yv) then Some(f(xv, yv))\n      None then None\n    None then None\n//│ fun optionApply: forall 'a 'b 'A. (None | Some['a], None | Some['b], ('a, 'b) -> 'A) -> (None | Some['A])\n\nfun (::) cons(h, t) = Cons(h, t)\n//│ fun (::) cons: forall 'A. ('A, Cons['A] | Nil) -> Cons['A]\n\nlet zeroToThree = 0 :: 1 :: 2 :: 3 :: Nil\n//│ let zeroToThree: Cons[0 | 1 | 2 | 3]\n//│ zeroToThree\n//│             = Cons {}\n\nfun f(x) = if x % 2 == 0 then Left(x) else Right(x)\n//│ fun f: forall 'A. (Int & 'A) -> (Left['A] | Right['A])\n\n\nfun mapPartition(f, xs) = if xs is\n  Nil then Pair(Nil, Nil)\n  Cons(x, xs) and mapPartition(f, xs) is Pair(l, r) and f(x) is\n    Left(v)  then Pair(Cons(v, l), r)\n    Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil]\n\n\nmapPartition(x => Left(x + 1), zeroToThree)\n//│ Pair[Cons[Int] | Nil, Cons[nothing] | Nil]\n//│ res\n//│     = Pair {}\n\n\nmapPartition(f, zeroToThree)\n//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = Pair {}\n\n\nfun mapPartition(f, xs) = if xs is\n  Nil then Pair(Nil, Nil)\n  Cons(x, xs) and\n    mapPartition(f, xs) is Pair(l, r) and f(x) is\n      Left(v)  then Pair(Cons(v, l), r)\n      Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil]\n\nmapPartition(f, zeroToThree)\n//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = Pair {}\n\n\nfun mapPartition(f, xs) = if xs is\n  Nil then\n    Pair(Nil, Nil)\n  Cons(x, xs) and\n    mapPartition(f, xs) is\n      Pair(l, r) and\n        f(x) is\n          Left(v)  then\n            Pair(Cons(v, l), r)\n          Right(v) then\n            Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil]\n\nmapPartition(f, zeroToThree)\n//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = Pair {}\n\nfun mapPartition(f, xs) = if xs is\n  Nil then [Nil, Nil]\n  Cons(x, xs) and mapPartition(f, xs) is [l, r] and f(x) is\n    Left(v)  then [Cons(v, l), r]\n    Right(v) then [l, Cons(v, r)]\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> [Cons['A] | Nil, Cons['A0] | Nil]\n\n\nmapPartition(f, zeroToThree)\n//│ [Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = [ Cons {}, Cons {} ]\n\n// * Vertical alignment is not allowed! (good)\n:pe\n:w\n:e\nfun mapPartition(f, xs) = if xs is\n  Nil then [Nil, Nil]\n  Cons(x, xs) and mapPartition(f, xs) is [l, r]\n          and f(x) is Left(v)  then [Cons(v, l), r]\n                      Right(v) then [l, Cons(v, r)]\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.113: \t                      Right(v) then [l, Cons(v, r)]\n//│ ╙──       \t                               ^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.112: \t          and f(x) is Left(v)  then [Cons(v, l), r]\n//│ ║         \t                                    ^^^^^^^^^^^^^^^\n//│ ║  l.113: \t                      Right(v) then [l, Cons(v, r)]\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.112: \t          and f(x) is Left(v)  then [Cons(v, l), r]\n//│ ║         \t                                    ^^^^^^^^^^^^^^^\n//│ ║  l.113: \t                      Right(v) then [l, Cons(v, r)]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `[?a, ?b]` is not a function\n//│ ║  l.112: \t          and f(x) is Left(v)  then [Cons(v, l), r]\n//│ ╙──       \t                                    ^^^^^^^^^^^^^^^\n//│ fun mapPartition: forall 'a. ('a -> Left[anything], Cons['a] | Nil) -> (error | [Nil, Nil])\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/NestedPattern.mls",
    "content": ":NewDefs\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\nclass Left[A](leftValue: A) extends Either[A, nothing]\nclass Right[B](rightValue: B) extends Either[nothing, B]\n//│ abstract class Either[A, B]: Left[A] | Right[B]\n//│ class Left[A](leftValue: A) extends Either\n//│ class Right[B](rightValue: B) extends Either\n\nfun compute(v) =\n  if v is\n    Left(Some(x)) then x * 5\n    Left(None()) then 1\n    Right(Some(x)) then x * 3\n    Right(None()) then 0\n//│ fun compute: (Left[None | Some[Int]] | Right[None | Some[Int]]) -> Int\n\nfun crazy(v) =\n  if v is\n    Some(Some(Some(Some(Some(Some(None())))))) then \"bruh!\"\n    _ then \"lol\"\n//│ fun crazy: (Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object]]]]]]) -> (\"bruh!\" | \"lol\")\n\n\n// * TODO(@chengluyu) fix these missing locations\n\nfun f(x) =\n  if x is\n    [0, 0] then \"zeros\"\n    [1, 1] then \"ones\"\n    _      then \"bruh\"\n//│ fun f: {0: Object, 1: Object} -> (\"bruh\" | \"ones\" | \"zeros\")\n\nf([0, 0])\nf([1, 1])\nf([1, 0])\n//│ \"bruh\" | \"ones\" | \"zeros\"\n//│ res\n//│     = 'zeros'\n//│ res\n//│     = 'ones'\n//│ res\n//│     = 'bruh'\n\nfun f(x) =\n  if x is\n    [0, 0] then \"zeros\"\n    [1, 1] then \"ones\"\n    [y, 1] then x\n    _      then \"que?\"\n//│ fun f: forall 'a. ({0: Object, 1: Object} & 'a) -> (\"ones\" | \"que?\" | \"zeros\" | 'a)\n\nf([0, 0])\nf([1, 1])\nf([0, 1])\nf([1, 0])\n//│ \"ones\" | \"que?\" | \"zeros\" | [1, 0]\n//│ res\n//│     = 'zeros'\n//│ res\n//│     = 'ones'\n//│ res\n//│     = [ 0, 1 ]\n//│ res\n//│     = 'que?'\n\nfun f(p) =\n  if p is\n    Some([x, y]) then x + y\n    None()       then 0\n//│ fun f: (None | Some[{0: Int, 1: Int}]) -> Int\n\nclass Union[A, B](a: A, b: B)\n//│ class Union[A, B](a: A, b: B)\n\n// Name conflict between the scrutinee and the positionals.\n// Desugar result: let tmp13 = x in case tmp13 of { Union => let x = (tmp13).a in let y = (tmp13).b in x }\nfun hmm(x) =\n  if x is Union(x, y) then x\n//│ fun hmm: forall 'a. Union['a, anything] -> 'a\n\nhmm(Union(1, 2))\n//│ 1\n//│ res\n//│     = 1\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/NuPlainConditionals.mls",
    "content": ":NewDefs\n\n\nclass Pair[A](fst: A, snd: A)\n//│ class Pair[A](fst: A, snd: A)\n\n\n\nPair(0, 1) is Pair\n//│ Bool\n//│ res\n//│     = true\n\nPair(0, 1) is Pair(a, b)\n//│ Bool\n//│ res\n//│     = true\n\nPair(0, 1) is Pair(0, _)\n//│ Bool\n//│ res\n//│     = true\n\nif Pair(0, 1) is Pair(a, b) then true else false\n//│ Bool\n//│ res\n//│     = true\n\n\nfun foo(x) = x is Pair(a, b)\n//│ fun foo: (Object & ~#Pair | Pair[anything]) -> Bool\n\n\nPair(0, 1) is Pair(a, b) and a > b\n//│ Bool\n//│ res\n//│     = false\n\nif Pair(0, 1) is Pair(a, b) then a > b else false\n//│ Bool\n//│ res\n//│     = false\n\n\nfun foo(x) = x is Pair(a, b) and a > b\n//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool\n\nfun foo(x) = if x is Pair(a, b) then a > b else false\n//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool\n\n\n// TODO proper error\nfun foo(x) = x is\n  Pair\n  Int\n//│ ╔══[ERROR] unknown pattern {Pair; Int}\n//│ ║  l.54: \t  Pair\n//│ ║        \t  ^^^^\n//│ ║  l.55: \t  Int\n//│ ╙──      \t^^^^^\n//│ ╔══[WARNING] this case is unreachable\n//│ ╙── because it is subsumed by the branch\n//│ fun foo: anything -> true\n\n// TODO proper error\nfun foo(x) = x is\n  Pair(a, b) and a > b\n  Int\n//│ ╔══[ERROR] unknown pattern {and(Pair(a, b,), >(a, b,),); Int}\n//│ ║  l.67: \t  Pair(a, b) and a > b\n//│ ║        \t  ^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.68: \t  Int\n//│ ╙──      \t^^^^^\n//│ ╔══[WARNING] this case is unreachable\n//│ ╙── because it is subsumed by the branch\n//│ fun foo: anything -> true\n\n// TODO support `|`\nfun foo1(x) = x is Pair(a, b) | Int\nfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╔══[ERROR] type identifier `|` not found\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                          ^\n//│ ╔══[ERROR] type identifier `and` not found\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                               ^^^\n//│ ╔══[ERROR] type identifier `>` not found\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                     ^\n//│ ╔══[ERROR] type identifier `|` not found\n//│ ║  l.79: \tfun foo1(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                              ^\n//│ ╔══[ERROR] type identifier not found: |\n//│ ║  l.79: \tfun foo1(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                              ^\n//│ ╔══[ERROR] type identifier not found: |\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                          ^\n//│ fun foo1: nothing -> error\n//│ fun foo2: nothing -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol |\n\n\n\nclass A(arg: Int)\n//│ class A(arg: Int)\n\n// TODO make `is` lower precedence than `=>`\nx => (x is A(_))\n//│ Object -> Bool\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/OverlappedBranches.mls",
    "content": ":NewDefs\n\nclass Base()\nclass Derived1() extends Base()\nclass Derived2() extends Base()\nclass Derived3() extends Derived2()\n//│ class Base()\n//│ class Derived1() extends Base\n//│ class Derived2() extends Base\n//│ class Derived3() extends Base, Derived2\n\n// The very basic case.\n// It should warn about that the last two cases are unreachable.\n:w\n:ducs:normalize.result\nfun f1(x) = if x is\n  Base then \"b\"\n  Derived1 then \"d1\"\n  Derived2 then \"d2\"\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Base*◊ -> \"b\"\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.18: \t  Derived1 then \"d1\"\n//│ ║        \t  ^^^^^^^^\n//│ ╟── the case is covered by pattern Base\n//│ ║  l.17: \t  Base then \"b\"\n//│ ║        \t  ^^^^\n//│ ╟── due to the subtyping relation\n//│ ║  l.4: \tclass Derived1() extends Base()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.19: \t  Derived2 then \"d2\"\n//│ ║        \t  ^^^^^^^^\n//│ ╟── the case is covered by pattern Base\n//│ ║  l.17: \t  Base then \"b\"\n//│ ║        \t  ^^^^\n//│ ╟── due to the subtyping relation\n//│ ║  l.5: \tclass Derived2() extends Base()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun f1: Base -> \"b\"\n\nf1(Base())\nf1(Derived1())\nf1(Derived2())\n//│ \"b\"\n//│ res\n//│     = 'b'\n//│ res\n//│     = 'b'\n//│ res\n//│     = 'b'\n\n// Decision paths:\n// + «x is Base» and «p (x,)» => \"b and p\"\n// + «x is Derived1» => \"d1\"\n// + «x is Derived2» => \"d2\"\n// +  => \"otherwise\"\n// The case tree:\n//    «x» match\n//      case Base =>\n//        if «p (x,)»\n//          «\"b and p\"»\n//        else\n//          «x» match\n//            case Derived1 =>\n//              «\"d1\"»\n//            case Derived2 =>\n//              «\"d2\"»\n//            default\n//              «\"otherwise\"»\n//      default\n//        «\"otherwise\"»\nfun f2(x, p) = if x is\n  Base and p(x) then \"b and p\"\n  Derived1 then \"d1\"\n  Derived2 then \"d2\"\n  else \"otherwise\"\n//│ fun f2: forall 'a. (Object & ~#Base | 'a & (Base & ~#Derived1 & ~#Derived2 | Derived1 | Derived2), (Base & 'a) -> Bool) -> (\"b and p\" | \"d1\" | \"d2\" | \"otherwise\")\n\nf2(Base(), _ => true) // => b and p\nf2(Base(), _ => false) // otherwise\n//│ \"b and p\" | \"d1\" | \"d2\" | \"otherwise\"\n//│ res\n//│     = 'b and p'\n//│ res\n//│     = 'otherwise'\n\nf2(Derived1(), _ => true) // => b and p\nf2(Derived2(), _ => true) // => b and p\n//│ \"b and p\" | \"d1\" | \"d2\" | \"otherwise\"\n//│ res\n//│     = 'b and p'\n//│ res\n//│     = 'b and p'\n\nf2(Derived1(), _ => false) // => d1\nf2(Derived2(), _ => false) // => d2\n//│ \"b and p\" | \"d1\" | \"d2\" | \"otherwise\"\n//│ res\n//│     = 'd1'\n//│ res\n//│     = 'd2'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/ParseFailures.mls",
    "content": ":NewDefs\n:NoJS\n\ntype Tree[A] = Node[A] | Empty\nmodule Empty\nclass Node[A](value: Int, left: Tree[A], right: Tree[A])\n//│ type Tree[A] = Empty | Node[A]\n//│ module Empty\n//│ class Node[A](value: Int, left: Tree[A], right: Tree[A])\n\nfun contains(node, wanted) =\n  if node is\n    Node(value, left, right) and wanted\n      <= value then contains(left, wanted)\n      >= value then contains(right, wanted)\n      else true\n    Empty then false\n//│ fun contains: forall 'A. (Empty | Node['A], Num) -> Bool\n\nfun contains'(node, wanted) =\n  if node is\n    Node(value, left, right) and wanted\n      <= value then contains'(left, wanted)\n      >= value then contains'(right, wanted)\n      _ then true\n    Empty then false\n//│ fun contains': forall 'A. (Empty | Node['A], Num) -> Bool\n\n:pe\nclass Z()\nclass O()\nfun foo(x, y) = if x is\n  Z() and y is O() then 0 else 1\n//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here\n//│ ║  l.33: \t  Z() and y is O() then 0 else 1\n//│ ╙──      \t                          ^^^^\n//│ class Z()\n//│ class O()\n//│ fun foo: (Z, O) -> 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/ParserFailures.mls",
    "content": ":NewDefs\n:NoJS\n\n// FIXME: Interleaved let bindings are not implemented in `IfOpsApp`.\nif x\n  == 0 then \"bad\"\n  let y = f(z)\n  == y * y then 0\n//│ ╔══[PARSE ERROR] expect an operator\n//│ ║  l.7: \t  let y = f(z)\n//│ ╙──     \t  ^^^\n//│ ╔══[PARSE ERROR] Unexpected 'let' keyword here\n//│ ║  l.7: \t  let y = f(z)\n//│ ╙──     \t  ^^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t  == 0 then \"bad\"\n//│ ╙──     \t            ^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.5: \tif x\n//│ ╙──     \t   ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t  == 0 then \"bad\"\n//│ ║       \t            ^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ \"bad\"\n\n// FIXME: Interleaved let bindings are not implemented in `IfOpsApp`.\nfun tt(x) =\n  if x\n    is A() then \"A\"\n    let y = 0\n    is B() then \"B\"\n//│ ╔══[PARSE ERROR] expect an operator\n//│ ║  l.31: \t    let y = 0\n//│ ╙──      \t    ^^^\n//│ ╔══[PARSE ERROR] Unexpected 'let' keyword here\n//│ ║  l.31: \t    let y = 0\n//│ ╙──      \t    ^^^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.30: \t    is A() then \"A\"\n//│ ╙──      \t       ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.30: \t    is A() then \"A\"\n//│ ╙──      \t       ^\n//│ fun tt: nothing -> error\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/SplitAfterOp.mls",
    "content": ":NewDefs\n\n:e\nfun f(x, b) =\n  if x == \n    0 and b then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t    0 and b then 0\n//│ ╙──     \t          ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t    0 and b then 0\n//│ ║       \t                 ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t    0 and b then 0\n//│ ║       \t          ^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Bool) -> 0\n\n:e\nfun f(x, y) =\n  if x == y +\n    5 then 0\n    7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.24: \t    7 then 0\n//│ ╙──      \t           ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.22: \t  if x == y +\n//│ ║        \t            ^\n//│ ║  l.23: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.22: \t  if x == y +\n//│ ╙──      \t     ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.22: \t  if x == y +\n//│ ║        \t            ^\n//│ ║  l.23: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.22: \t  if x == y +\n//│ ║        \t            ^\n//│ ║  l.23: \t    5 then 0\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.24: \t    7 then 0\n//│ ║        \t^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.24: \t    7 then 0\n//│ ║        \t           ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> 0\n\n:e\nfun f(x, y) =\n  if x == y *\n    5 then 0\n    6 + 7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ╙──      \t               ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.58: \t  if x == y *\n//│ ╙──      \t     ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ║        \t^^^^^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.58: \t  if x == y *\n//│ ╙──      \t     ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ║        \t^^^^^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ║        \t               ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> 0\n\n:e\nfun f(x, y) =\n  if x ==\n    y +\n      5 then 0\n      7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.107: \t      7 then 0\n//│ ╙──       \t             ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.105: \t    y +\n//│ ║         \t      ^\n//│ ║  l.106: \t      5 then 0\n//│ ║         \t^^^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.104: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.105: \t    y +\n//│ ╙──       \t^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.105: \t    y +\n//│ ║         \t      ^\n//│ ║  l.106: \t      5 then 0\n//│ ║         \t^^^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.105: \t    y +\n//│ ║         \t      ^\n//│ ║  l.106: \t      5 then 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.107: \t      7 then 0\n//│ ║         \t^^^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.107: \t      7 then 0\n//│ ║         \t             ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> 0\n\n:e\nfun f(x, b) =\n  if x ==\n    1 and b then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.144: \t    1 and b then 0\n//│ ╙──       \t          ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.144: \t    1 and b then 0\n//│ ║         \t                 ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.144: \t    1 and b then 0\n//│ ║         \t          ^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Bool) -> 0\n\n\n:e\nfun toEnglish(x) =\n  if x ==\n    true then \"t\"\n    0 then \"z\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.163: \t    0 then \"z\"\n//│ ╙──       \t           ^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.161: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.162: \t    true then \"t\"\n//│ ║         \t^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Num`\n//│ ║  l.162: \t    true then \"t\"\n//│ ╙──       \t    ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.163: \t    0 then \"z\"\n//│ ║         \t           ^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> (\"t\" | \"z\")\n\n:e\nfun toEnglish(x) =\n  if x ==\n    0 then \"z\"\n    true then \"t\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.185: \t    true then \"t\"\n//│ ╙──       \t              ^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.183: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.184: \t    0 then \"z\"\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.185: \t    true then \"t\"\n//│ ║         \t^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Num`\n//│ ║  l.185: \t    true then \"t\"\n//│ ╙──       \t    ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.185: \t    true then \"t\"\n//│ ║         \t              ^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> (\"t\" | \"z\")\n\n:e\nfun toEnglish(x) =\n  if x ==\n    1 then \"o\"\n    0 then \"z\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.209: \t    0 then \"z\"\n//│ ╙──       \t           ^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.209: \t    0 then \"z\"\n//│ ║         \t           ^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> (\"o\" | \"z\")\n\nfun toEnglish(x) =\n  if x ==\n    0 then 1\n    else 1\n//│ fun toEnglish: Num -> 1\n\n:pe\n:e\nfun toEnglish(x) =\n  if x ==\n    else 1\n//│ ╔══[PARSE ERROR] Unexpected indented block in expression position\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t^^^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t    ^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.228: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.229: \t    else 1\n//│ ║         \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.228: \t  if x ==\n//│ ╙──       \t  ^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t    ^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.228: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.229: \t    else 1\n//│ ║         \t^^^^\n//│ ╟── undefined literal of type `()` is not an instance of type `Num`\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t    ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.229: \t    else 1\n//│ ║         \t    ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> ()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/SplitAnd.mls",
    "content": ":NewDefs\n\nfun f(x, y) =\n  if x == 0 and\n    y == 0 then \"bruh\"\n    y == 1 then \"lol\"\n  else \"okay\"\n//│ fun f: (Num, Num) -> (\"bruh\" | \"lol\" | \"okay\")\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\n:e\nfun f(x) =\n  if x == 0 and\n    x is\n      A() then \"A\"\n      B() then \"B\"\n    x == 0 then \"lol\"\n    else \"bruh\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.18: \t    x is\n//│ ║        \t    ^^^^\n//│ ║  l.19: \t      A() then \"A\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.20: \t      B() then \"B\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.21: \t    x == 0 then \"lol\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.22: \t    else \"bruh\"\n//│ ╙──      \t^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.18: \t    x is\n//│ ║        \t    ^^^^\n//│ ║  l.19: \t      A() then \"A\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.20: \t      B() then \"B\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.21: \t    x == 0 then \"lol\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.22: \t    else \"bruh\"\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: Num -> (\"A\" | \"B\" | \"bruh\" | \"lol\")\n\n:e\nfun f(x, y) =\n  if\n    x == 0 and\n      y == 0 then \"bruh\"\n      else \"lol\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.52: \t      y == 0 then \"bruh\"\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^\n//│ ║  l.53: \t      else \"lol\"\n//│ ╙──      \t^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.52: \t      y == 0 then \"bruh\"\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^\n//│ ║  l.53: \t      else \"lol\"\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> (\"bruh\" | \"lol\")\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/SplitAroundOp.mls",
    "content": ":NewDefs\n\nfun f(x, b) =\n  if x\n    ===\n      0 and b then \"n0\"\n      1 and b then \"n1\"\n      2 then \"n2\"\n    ===\n      \"0\" then \"s0\"\n      \"1\" then \"s1\"\n      \"2\" then \"s2\"\n  else \":p\"  \n//│ fun f: (Eql[\"0\" | \"1\" | \"2\" | 0 | 1 | 2], Bool) -> (\":p\" | \"n0\" | \"n1\" | \"n2\" | \"s0\" | \"s1\" | \"s2\")\n\nfun f(x, y, a, b) =\n  if x === 0\n    and\n      y === 0 then \"x, y\"\n      a === 0 then \"x, a\"\n      b === 0 then \"x, b\"\n  else \"nah\"\n//│ fun f: (Eql[0], Eql[0], Eql[0], Eql[0]) -> (\"nah\" | \"x, a\" | \"x, b\" | \"x, y\")\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nfun f(x) =\n  if x\n    is\n      A() then 0\n      B() then 1\n//│ fun f: (A | B) -> (0 | 1)\n\n:e // FIXME\nif x is\n  A()\n    === 0 then 0\n    > 0 then 1\n    < 0 then 2\n//│ ╔══[ERROR] cannot transform due to an illegal split operator ===\n//│ ║  l.40: \t    === 0 then 0\n//│ ║        \t    ^^^\n//│ ╟── the following branch will be discarded\n//│ ║  l.40: \t    === 0 then 0\n//│ ╙──      \t        ^^^^^^^^\n//│ ╔══[ERROR] cannot transform due to an illegal split operator >\n//│ ║  l.41: \t    > 0 then 1\n//│ ║        \t    ^\n//│ ╟── the following branch will be discarded\n//│ ║  l.41: \t    > 0 then 1\n//│ ╙──      \t      ^^^^^^^^\n//│ ╔══[ERROR] cannot transform due to an illegal split operator <\n//│ ║  l.42: \t    < 0 then 2\n//│ ║        \t    ^\n//│ ╟── the following branch will be discarded\n//│ ║  l.42: \t    < 0 then 2\n//│ ╙──      \t      ^^^^^^^^\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.38: \tif x is\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.38: \tif x is\n//│ ╙──      \t   ^\n//│ nothing\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/SplitBeforeOp.mls",
    "content": ":NewDefs\n\n:e\n:ge\nif x\n  == 0 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t  == 0 then 0\n//│ ╙──     \t            ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.5: \tif x\n//│ ╙──     \t   ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t  == 0 then 0\n//│ ║       \t            ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ 0\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\n:ge\nif x\n  is A and\n    y then 0\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.23: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.24: \t  is A and\n//│ ╙──      \t     ^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.25: \t    y then 0\n//│ ╙──      \t           ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.23: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.24: \t  is A and\n//│ ╙──      \t     ^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\n:ge\nif x\n  is A and\n    y then 0\nelse 1\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.47: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.48: \t  is A and\n//│ ╙──      \t     ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.47: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.48: \t  is A and\n//│ ╙──      \t     ^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\n:ge\nif x\n  == 0 then 0\n  is\n    A() then \"A\"\n    B() then \"B\"\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.69: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.72: \t    A() then \"A\"\n//│ ╙──      \t    ^\n//│ ╔══[ERROR] type identifier `B` not found\n//│ ║  l.73: \t    B() then \"B\"\n//│ ╙──      \t    ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.69: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.69: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.72: \t    A() then \"A\"\n//│ ╙──      \t    ^\n//│ 0 | error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/SplitOps.mls",
    "content": ":NewDefs\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\nclass Left[A](leftValue: A) extends Either[A, nothing]\nclass Right[B](rightValue: B) extends Either[nothing, B]\n//│ abstract class Either[A, B]: Left[A] | Right[B]\n//│ class Left[A](leftValue: A) extends Either\n//│ class Right[B](rightValue: B) extends Either\n\n:e\n:ge\nfun f(x) =\n  if x\n    is Left(v) then 0\n    is Right(v) then 1\n    <> undefined then 2\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.23: \t    <> undefined then 2\n//│ ╙──      \t                      ^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.20: \t  if x\n//│ ║        \t     ^\n//│ ║  l.21: \t    is Left(v) then 0\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.22: \t    is Right(v) then 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.23: \t    <> undefined then 2\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── undefined literal of type `()` is not an instance of type `Num`\n//│ ║  l.23: \t    <> undefined then 2\n//│ ╙──      \t       ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.23: \t    <> undefined then 2\n//│ ║        \t                      ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Left[anything] | Num | Right[anything]) -> (0 | 1 | 2)\n//│ Code generation encountered an error:\n//│   unresolved symbol <>\n\n:e\n:ge\nfun f(x) =\n  if x\n    is Some(xv) and y is Some(yv) then xv + yv\n    is None() and y is None() then 0\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.51: \t    is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──      \t                    ^\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.52: \t    is None() and y is None() then 0\n//│ ╙──      \t                  ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.51: \t    is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──      \t                    ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.52: \t    is None() and y is None() then 0\n//│ ╙──      \t                  ^\n//│ fun f: (None | Some[Int]) -> Int\n//│ Code generation encountered an error:\n//│   unresolved symbol y\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nfun f(a, b) =\n  if a\n    is A() and b is B() then 0\n//│ fun f: (A, B) -> 0\n\nclass C()\n//│ class C()\n\n:e\nfun f(a, b, c) =\n  if a\n    == 0 and b is B() and c is C() then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.85: \t    == 0 and b is B() and c is C() then 0\n//│ ╙──      \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.85: \t    == 0 and b is B() and c is C() then 0\n//│ ║        \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, B, C) -> 0\n\nfun f(x) =\n  if x\n    is A() then \"A\"\n    is B() then \"B\"\n//│ fun f: (A | B) -> (\"A\" | \"B\")\n\nfun sumOpt(x, y) =\n  if x\n    is Some(xv) and y is\n      Some(yv) then xv + yv\n      None() then xv\n    is None() and y is\n      Some(yv) then yv\n      None() then 0\n//│ fun sumOpt: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\nfun f(x, y, z) =\n  if x is A() and y\n    == z then 1\n    is B() then 0\n//│ fun f: (A, nothing, Num) -> (0 | 1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/SplitScrutinee.mls",
    "content": ":NewDefs\n\nfun f(x) =\n  if x +\n    1 is\n      2 then 1\n      3 then 2\n      _ then \"I don't know.\"\n//│ fun f: Int -> (\"I don't know.\" | 1 | 2)\n\n[f(0), f(1), f(2), f(3)]\n//│ [\"I don't know.\" | 1 | 2, \"I don't know.\" | 1 | 2, \"I don't know.\" | 1 | 2, \"I don't know.\" | 1 | 2]\n//│ res\n//│     = [ \"I don't know.\", 1, 2, \"I don't know.\" ]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/ThenIndent.mls",
    "content": ":NewDefs\n\n\n// FIXME\nx => if x ==\n  0\n    then \"a\"\n  _ then \"b\"\n//│ ╔══[PARSE ERROR] Unexpected indented block here\n//│ ║  l.7: \t    then \"a\"\n//│ ║       \t^^^^^^^^^^^^\n//│ ║  l.8: \t  _ then \"b\"\n//│ ╙──     \t^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.5: \tx => if x ==\n//│ ║       \t        ^^^^\n//│ ║  l.6: \t  0\n//│ ║       \t^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.5: \tx => if x ==\n//│ ╙──     \t     ^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t  0\n//│ ╙──     \t  ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t  0\n//│ ║       \t  ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ Num -> ()\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/TrivialIf.mls",
    "content": ":NewDefs\n:NoJS\n\nfun abs(x) = if x < 0 then 0 - x else x\n//│ fun abs: Int -> Int\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nfun getOrElse(opt, default) =\n  if opt is\n    Some(value) then value\n    None then default\n//│ fun getOrElse: forall 'a. (None | Some['a], 'a) -> 'a\n\ngetOrElse(None, 0)\n//│ 0\n\ngetOrElse(Some(42), 0)\n//│ 0 | 42\n\nfun map(v, f) =\n  if v is\n    Some(x) then Some(f(x))\n    None then None\n//│ fun map: forall 'a 'A. (None | Some['a], 'a -> 'A) -> (None | Some['A])\n\nfun inc(x) = x + 5\n//│ fun inc: Int -> Int\n\nmap(Some(5), x => x + 5)\n//│ None | Some['A]\n//│   where\n//│     'A :> Int\n\nmap(None, inc)\n//│ None | Some['A]\n//│   where\n//│     'A :> Int\n\n:e\nfun f(a, b) = if a and b then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.46: \tfun f(a, b) = if a and b then 0\n//│ ╙──      \t                       ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.46: \tfun f(a, b) = if a and b then 0\n//│ ║        \t                              ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.46: \tfun f(a, b) = if a and b then 0\n//│ ║        \t                       ^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Bool, Bool) -> 0\n\n:e\nfun f(x, y) =\n  if x == y + 5 then 0\n  else if x == y + 7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.63: \t  else if x == y + 7 then 0\n//│ ╙──      \t                          ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.63: \t  else if x == y + 7 then 0\n//│ ║        \t                          ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Int) -> 0\n\n// TODO support\nfun foo(x) = if x is Some\n  (0) then 0\n  (1) then 1\n//│ ╔══[PARSE ERROR] Unexpected parenthesis section here\n//│ ║  l.76: \t  (1) then 1\n//│ ╙──      \t  ^^^\n//│ /!!!\\ Uncaught error: java.lang.StackOverflowError\n\n// TODO support\nfun foo(x) = if x is Some of\n  0 then 0\n  1 then 1\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.84: \t  0 then 0\n//│ ╙──      \t    ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.83: \tfun foo(x) = if x is Some of\n//│ ║        \t                ^^^^^^^^^^^^\n//│ ║  l.84: \t  0 then 0\n//│ ║        \t^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.83: \tfun foo(x) = if x is Some of\n//│ ╙──      \t             ^^\n//│ fun foo: Some[0] -> ()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/WeirdIf.mls",
    "content": ":NewDefs\n\n:w\nif\n  _ then 0\n  else 0\nelse 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.6: \t  else 0\n//│ ║       \t       ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.5: \t  _ then 0\n//│ ╙──     \t         ^\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.7: \telse 1\n//│ ║       \t     ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.5: \t  _ then 0\n//│ ╙──     \t         ^\n//│ 0\n//│ res\n//│     = 0\n\n:w\nif else 0 else 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.25: \tif else 0 else 1\n//│ ║        \t               ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.25: \tif else 0 else 1\n//│ ╙──      \t        ^\n//│ 0\n//│ res\n//│     = 0\n\n:w\nfun f(x) = if x is else 0 else 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.37: \tfun f(x) = if x is else 0 else 1\n//│ ║        \t                               ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.37: \tfun f(x) = if x is else 0 else 1\n//│ ╙──      \t                        ^\n//│ fun f: anything -> 0\n\nfun f(x) = if x is else 0 \n//│ fun f: anything -> 0\n\n:e\nif true\n  then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.51: \t  then 0\n//│ ╙──      \t       ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.51: \t  then 0\n//│ ║        \t       ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ 0\n//│ res\n//│     = 0\n\n// This cannot be parsed. But the next one works.\n:pe\n:e\nfun f(x) =\n  if x ===\n    else \"bruh\"\n//│ ╔══[PARSE ERROR] Unexpected indented block in expression position\n//│ ║  l.68: \t    else \"bruh\"\n//│ ╙──      \t^^^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.68: \t    else \"bruh\"\n//│ ╙──      \t    ^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.67: \t  if x ===\n//│ ║        \t     ^^^^^\n//│ ║  l.68: \t    else \"bruh\"\n//│ ║        \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.67: \t  if x ===\n//│ ╙──      \t  ^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.68: \t    else \"bruh\"\n//│ ╙──      \t    ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.68: \t    else \"bruh\"\n//│ ║        \t    ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: Eql[()] -> ()\n\n// But this works.\nfun f(x) =\n  if x ===\n    _ then \"bruh\"\n//│ fun f: anything -> \"bruh\"\n\nfun boolToStr(x) =\n  if x is\n    true then \"yah\"\n    false then \"nah\"\n//│ fun boolToStr: Bool -> (\"nah\" | \"yah\")\n\nboolToStr of true\nboolToStr of false\n//│ \"nah\" | \"yah\"\n//│ res\n//│     = 'yah'\n//│ res\n//│     = 'nah'\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/WeirdSplit.mls",
    "content": ":NewDefs\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nfun f(x) =\n  if x\n    is\n      A then 0\n      B then 1\n//│ fun f: (A | B) -> (0 | 1)\n\n// Precedence problem: should we restruct terms when push them to the stack?\n:e\nfun f(x) =\n  if x ==\n    1\n      + 2 then 0\n      + _ then 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.20: \t      + 2 then 0\n//│ ║        \t      ^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.18: \t  if x ==\n//│ ║        \t     ^^^^\n//│ ║  l.19: \t    1\n//│ ╙──      \t^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.20: \t      + 2 then 0\n//│ ║        \t      ^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ fun f: Num -> (0 | 1)\n\nfun f(x, s, t) =\n  if x\n    is A()\n      and t then 0\n      and s then 0\n    is _ then 1\n//│ fun f: (Object, Bool, Bool) -> (0 | 1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/Wildcard.mls",
    "content": ":NewDefs\n\nfun (++) strcat(a, b) = concat(a)(b)\n//│ fun (++) strcat: (Str, Str) -> Str\n\ntype Option[T] = None | Some[T]\nmodule None\nclass Some[T](val value: T)\n//│ type Option[T] = None | Some[T]\n//│ module None\n//│ class Some[T](value: T)\n\ntype Either[A, B] = Left[A] | Right[B]\nclass Left[A](val leftValue: A)\nclass Right[B](val rightValue: B)\n//│ type Either[A, B] = Left[A] | Right[B]\n//│ class Left[A](leftValue: A)\n//│ class Right[B](rightValue: B)\n\n\nfun w1(x, e_0, e_1) =\n  if x is\n    Left(None) then \"Left of None\"\n    Right(None) then \"Right of None\"\n    _ and e_0 is y_0 and x is\n      Left(Some(lv)) then \"Left of Some of \" ++ toString(lv)\n      _ and e_1 is y_1 and x is\n        Right(Some(rv)) then \"Right of Some of \" ++ toString(rv)\n//│ fun w1: forall 'a. (Left[None | Object & ~#None & ~#Some | Some[anything]] | Object & ~#Left & ~#Right | Right[None | Some[anything]], anything, 'a) -> (Str | 'a)\n\nw1(Left(None), \"a\", \"b\")\nw1(Right(None), \"a\", \"b\")\nw1(Left(Some(0)), \"a\", \"b\")\nw1(Right(Some(0)), \"a\", \"b\")\n//│ Str\n//│ res\n//│     = 'Left of None'\n//│ res\n//│     = 'Right of None'\n//│ res\n//│     = 'Left of Some of 0'\n//│ res\n//│     = 'Right of Some of 0'\n\n//  Should be\n//  case x of\n//    Some -> 1\n//    None ->\n//      case p(x) of\n//        true -> 2\n//        _ -> 4\n//    _ ->\n//      case p(x) of\n//        true -> 3\n//        _ -> 5\n:ducs:normalize.result,postprocess.result\nfun w2(x, p) =\n  if x is\n    Some then 1\n    _ and p(x) and\n      x is None then 2\n      _ then 3\n    None then 4\n    _ then 5\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† ->\n//│         case x*‡ of\n//│           None*† -> 2\n//│           _ -> 3\n//│       _ ->\n//│         case x*‡ of\n//│           None*† -> 4\n//│           _ -> 5\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   None*† ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 2\n//│       _ -> 4\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 3\n//│       _ -> 5\n//│ fun w2: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], (None | 'a) -> Bool) -> (1 | 2 | 3 | 4 | 5)\n\n//  Should be\n//  case x of\n//    Some -> 1\n//    None ->\n//      case p(x) of\n//        true -> 2\n//        _ -> 3\n//    _ ->\n//      case p(x) of\n//        true -> 2\n//        _ -> 4\n:ducs:normalize.result,postprocess.result\nfun w2(x, p) =\n  if x is\n    Some then 1\n    _ and p(x) then 2\n    None then 3\n    _ then 4\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> 2\n//│       _ ->\n//│         case x*‡ of\n//│           None*† -> 3\n//│           _ -> 4\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   None*† ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 2\n//│       _ -> 3\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 2\n//│       _ -> 4\n//│ fun w2: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], (None | 'a) -> Bool) -> (1 | 2 | 3 | 4)\n\nw2(Some(0), x => true)\nw2(None, x => true)\nw2(None, x => false)\nw2(0, x => false)\n//│ 1 | 2 | 3 | 4\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n//│ res\n//│     = 3\n//│ res\n//│     = 4\n\nfun w3(x, p) = if x is\n  _ and p(x) then \"r1\"\n  Some(xv) then \"r2: \" ++ toString(xv)\n  None then \"r3\"\n  _ then \"r4\"\n//│ fun w3: forall 'a. ('a & (Object & ~#Some | Some[anything]), 'a -> Bool) -> Str\n\n// Expect \"r1\"\nw3(0, _ => true)\nw3(None, _ => true)\nw3(Some(0), _ => true)\n//│ Str\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n\n// Expect \"r2\"\nw3(Some(0), _ => false)\n//│ Str\n//│ res\n//│     = 'r2: 0'\n\n// Expect \"r3\"\nw3(None, _ => false)\n//│ Str\n//│ res\n//│     = 'r3'\n\n// Expect \"r4\"\nw3(0, _ => false)\n//│ Str\n//│ res\n//│     = 'r4'\n\n:w\n// Decision paths:\n// + «tmp2 @ f (x,) is any => 0\n// +  => 1\nfun w3_1(x, f) =\n  if f(x) is _ then 0 else 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.194: \t  if f(x) is _ then 0 else 1\n//│ ║         \t                           ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.194: \t  if f(x) is _ then 0 else 1\n//│ ╙──       \t                    ^\n//│ fun w3_1: forall 'a. ('a, 'a -> anything) -> 0\n\nw3_1(0, _ => true)\nw3_1(0, _ => false)\n//│ 0\n//│ res\n//│     = 0\n//│ res\n//│     = 0\n\n:w\nfun w3_1_1(x, f) =\n  if f(x) is a then a else 0\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.213: \t  if f(x) is a then a else 0\n//│ ║         \t                           ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.213: \t  if f(x) is a then a else 0\n//│ ╙──       \t                    ^\n//│ fun w3_1_1: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n\nw3_1_1(0, x => x)\nw3_1_1(0, x => x + 1)\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 1\n\n// Decision paths:\n// + «a = x» and «p (x,)» => \"r1\"\n// + «x is Some» => concat (\"r2: \",) (toString (xv,),)\n// + «x is None» => \"r3\"\nfun w4(x, p) = if x is\n  a and p(x) then \"r1\"\n  Some(xv) then \"r2: \" ++ toString(xv)\n  None then \"r3\"\n  _ then \"r4\"\n//│ fun w4: forall 'a. ('a & (Object & ~#Some | Some[anything]), 'a -> Bool) -> Str\n\n\n// Expect \"r1\"\nw4(0, _ => true)\nw4(None, _ => true)\nw4(Some(0), _ => true)\n//│ Str\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n\n// Expect \"r2\"\nw4(Some(0), _ => false)\n//│ Str\n//│ res\n//│     = 'r2: 0'\n\n// Expect \"r3\"\nw4(None, _ => false)\n//│ Str\n//│ res\n//│     = 'r3'\n\n// Expect \"r4\"\nw4(0, _ => false)\n//│ Str\n//│ res\n//│     = 'r4'\n\nclass Alpha()\nclass Beta()\nclass Gamma()\nclass Delta()\n//│ class Alpha()\n//│ class Beta()\n//│ class Gamma()\n//│ class Delta()\n\n// This should generate only one case expression instead of a chain of case\n// expressions. DO check the desugared term!\n:ducs:postprocess.result\nfun w5(y) =\n  if y is\n    Alpha then \"alpha\"\n    _ and y is\n      Beta then \"beta\"\n      _ and y is\n        Gamma then \"gamma\"\n        _ and y is\n          Delta then \"delta\"\n          _ then \"unknown\"\n//│ Post-processed UCS term:\n//│ case y*‡ of\n//│   Alpha*◊ -> \"alpha\"\n//│   Gamma*◊ -> \"gamma\"\n//│   Delta*◊ -> \"delta\"\n//│   Beta*◊ -> \"beta\"\n//│   _ -> \"unknown\"\n//│ fun w5: Object -> (\"alpha\" | \"beta\" | \"delta\" | \"gamma\" | \"unknown\")\n\nw5(0)\nw5(Alpha())\nw5(Beta())\nw5(Gamma())\nw5(Delta())\n//│ \"alpha\" | \"beta\" | \"delta\" | \"gamma\" | \"unknown\"\n//│ res\n//│     = 'unknown'\n//│ res\n//│     = 'alpha'\n//│ res\n//│     = 'beta'\n//│ res\n//│     = 'gamma'\n//│ res\n//│     = 'delta'\n\nfun w6(x, y) =\n  if x is\n    _ and y is\n      Some(z) then z\n      None then 0\n    else x\n//│ fun w6: forall 'a. ('a, Object & ~#Some | Some['a]) -> (0 | 'a)\n\nw6(\"42\", Some(42))\nw6(\"42\", None)\nw6(\"42\", \"42\")\n//│ \"42\" | 0\n//│ res\n//│     = 42\n//│ res\n//│     = 0\n//│ res\n//│     = '42'\n\n\nfun w7(x, f) =\n  if x is\n    _ and f(x) is\n      Some(v) then v\n      None then x\n    Left(x) then x + 1\n    Right(x) then x + 2\n//│ fun w7: forall 'a 'b. ('a & (Left[Int] | Right[Int]), 'a -> (Object & ~#Some | Some['b])) -> (Int | 'b | 'a)\n\n// The results are wrong:\nw7(Left(99), _ => Some(0)) // => 0\nw7(Left(99), _ => None) // => Left(99)\nw7(Right(99), _ => Some(0)) // => 0\nw7(Right(99), _ => None) // => Right(99)\n//│ Int | Right['B]\n//│   where\n//│     'B :> 99\n//│        <: Int\n//│ res\n//│     = 0\n//│ res\n//│     = Left {}\n//│ res\n//│     = 0\n//│ res\n//│     = Right {}\n\nw7(Left(99), _ => \"test\")\nw7(Right(99), _ => \"test\")\n//│ Int | Right['B]\n//│   where\n//│     'B :> 99\n//│        <: Int\n//│ res\n//│     = 100\n//│ res\n//│     = 101\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/legacy/zipWith.mls",
    "content": ":NewDefs\n\n\n\ndeclare val nothing: nothing\n//│ val nothing: nothing\n//│ nothing\n//│         = <missing implementation>\n\nmodule None {\n  fun value = nothing\n}\nclass Some[out A](val value: A)\n//│ module None {\n//│   fun value: nothing\n//│ }\n//│ class Some[A](value: A)\n\ntype List[out A] = Cons[A] | Nil\nmodule Nil {\n  fun toArray = []\n}\nclass Cons[out A](val head: A, val tail: List[A]) {\n  fun toArray: Array[anything]\n  fun toArray = [head, tail.toArray]\n}\n//│ type List[A] = Cons[A] | Nil\n//│ module Nil {\n//│   fun toArray: []\n//│ }\n//│ class Cons[A](head: A, tail: List[A]) {\n//│   fun toArray: Array[anything]\n//│ }\n\nfun pairup(x, y) = [x, y]\n//│ fun pairup: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n\n\n\n// FIXME parsing\nfun zipWith_wrong(f, xs, ys) =\n  if  xs is Cons(x, xs)\n  and ys is Cons(y, ys)\n  and zipWith_wrong(f, xs, ys) is Some(tail)\n  then Some(Cons(f(x, y), tail))\n  else None\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application followed by newline instead\n//│ ║  l.42: \t  if  xs is Cons(x, xs)\n//│ ║        \t      ^^^^^^^^^^^^^^^^^\n//│ ║  l.43: \t  and ys is Cons(y, ys)\n//│ ║        \t^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.42: \t  if  xs is Cons(x, xs)\n//│ ╙──      \t  ^^\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.43: \t  and ys is Cons(y, ys)\n//│ ╙──      \t  ^^^\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.44: \t  and zipWith_wrong(f, xs, ys) is Some(tail)\n//│ ╙──      \t  ^^^\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.42: \t  if  xs is Cons(x, xs)\n//│ ║        \t      ^^^^^^^^^^^^^^^^^\n//│ ║  l.43: \t  and ys is Cons(y, ys)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.44: \t  and zipWith_wrong(f, xs, ys) is Some(tail)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.45: \t  then Some(Cons(f(x, y), tail))\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.46: \t  else None\n//│ ╙──      \t^^^^^^^^^^^\n//│ fun zipWith_wrong: (anything, anything, anything) -> ()\n\n\nfun zipWith_wrong(f, xs, ys) =\n  if  xs is Cons(x, xs)\n    and ys is Cons(y, ys)\n    and zipWith_wrong(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n  else None\n//│ fun zipWith_wrong: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A]])\n\n\nfun zipWith_wrong(f, xs, ys) =\n  if  xs is Cons(x, xs)\n    and ys is Cons(y, ys) and zipWith_wrong(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n  else None\n//│ fun zipWith_wrong: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A]])\n\n// * Notice the result is wrong (duh)\nzipWith_wrong(pairup, Nil, Nil)\n//│ None | Some[Cons[[nothing, nothing]]]\n//│ res\n//│     = None {}\n\n\n\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n  else if xs is Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is Cons(x, xs) and ys is Cons(y, ys) then\n    if zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    else None\n  else if xs is Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) then\n      if ys is\n        Cons(y, ys) then\n          if zipWith(f, xs, ys) is\n            Some(tail) then Some(Cons(f(x, y), tail))\n            None then None\n        Nil then None\n    Nil then\n      if ys is Nil then Some(Nil) else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Nil, Cons['b] | Nil) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Nil, Nil).value.toArray\n//│ Array[anything]\n//│ res\n//│     = []\n\n:re\nzipWith(pairup, Nil, Cons(0, Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│ Runtime error:\n//│   ReferenceError: nothing is not defined\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\nlet ls = zipWith(pairup, Cons(0, Cons(1, Nil)), Cons(\"0\", Cons(\"1\", Nil)))\nls.value.toArray\n//│ let ls: None | Some[Cons[[0 | 1, \"0\" | \"1\"]] | Nil]\n//│ Array[anything]\n//│ ls\n//│    = Some {}\n//│ res\n//│     = [ [ 0, '0' ], [ [ 1, '1' ], [] ] ]\n\n\n\nfun zipWith_wrong2(f, xs, ys) =\n  if xs is Cons(x, xs) and ys is Cons(y, ys) and zipWith_wrong2(f, xs, ys) is Some(tail) then Cons(Some(f(x, y)), tail)\n  else if xs is Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith_wrong2: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (Cons[Some['A]] | None | Some[Nil])\n\n// * No type error! The definition and use are well-typed...\nzipWith_wrong2(pairup, Cons(0, Cons(1, Nil)), Cons(\"0\", Cons(\"1\", Nil)))\n//│ Cons[Some[[0 | 1, \"0\" | \"1\"]]] | None | Some[Nil]\n//│ res\n//│     = None {}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/stages/PostProcessing.mls",
    "content": ":NewDefs\n\n:ducs:postprocess.result,desugared\nfun mixed_literals(v) =\n  if v is\n    true then \"true\"\n    false then \"false\"\n    1 then \"1\"\n    2 then \"2\"\n//│ Post-processed UCS term:\n//│ case v*‡ of\n//│   true*† -> \"true\"\n//│   2 -> \"2\"\n//│   1 -> \"1\"\n//│   false*† -> \"false\"\n//│ Desugared term: case v of { true => \"true\"; 2 => \"2\"; 1 => \"1\"; false => \"false\" }\n//│ fun mixed_literals: (1 | 2 | false | true) -> (\"1\" | \"2\" | \"false\" | \"true\")\n\n:ducs:postprocess.result\nfun separated_by_and(v) =\n  if v is\n    true then \"true\"\n    _ and v is\n      false then \"false\"\n//│ Post-processed UCS term:\n//│ case v*‡ of\n//│   true*† -> \"true\"\n//│   false*† -> \"false\"\n//│ fun separated_by_and: Bool -> (\"false\" | \"true\")\n\n:ducs:postprocess.result\nfun dual_patterns(x, y) =\n  if\n    x is \"some\" and y is \"none\" then 0\n    x is \"none\" and y is \"some\" then 1\n    x is \"some\" and y is \"some\" then 2\n    x is \"none\" and y is \"none\" then 3\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   \"some\" ->\n//│     case y*‡ of\n//│       \"none\" -> 0\n//│       \"some\" -> 2\n//│   \"none\" ->\n//│     case y*‡ of\n//│       \"some\" -> 1\n//│       \"none\" -> 3\n//│ fun dual_patterns: (\"none\" | \"some\", \"none\" | \"some\") -> (0 | 1 | 2 | 3)\n\n:ducs:postprocess.result\nfun unordered_dual_patterns(x, y) =\n  if\n    x is \"some\" and y is \"none\" then 0\n    y is \"some\" and x is \"none\" then 1\n    y is \"some\" and x is \"some\" then 2\n    x is \"none\" and y is \"none\" then 3\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   \"some\" ->\n//│     case y*‡ of\n//│       \"none\" -> 0\n//│       \"some\" -> 2\n//│   \"none\" ->\n//│     case y*‡ of\n//│       \"some\" -> 1\n//│       \"none\" -> 3\n//│ fun unordered_dual_patterns: (\"none\" | \"some\", \"none\" | \"some\") -> (0 | 1 | 2 | 3)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/stages/SpecilizationCollision.mls",
    "content": ":NewDefs\n\n// This test file is to track possible name collision during specialization.\n\nfun (~~>) check(x, y) = if x === y then \"passed\" else error\nclass Pair[out A, out B](val first: A, val second: B)\n//│ fun (~~>) check: forall 'a. (Eql['a], 'a) -> \"passed\"\n//│ class Pair[A, B](first: A, second: B)\n\nfun p1(x) = x < 0\nfun p2(x) = x > 0\nfun p3(x) = x == 0\n//│ fun p1: Num -> Bool\n//│ fun p2: Num -> Bool\n//│ fun p3: Num -> Bool\n\nfun example1(p) =\n  if p is\n    Pair(x, y) and p1(x) and p1(y) then \"both negative\"\n    Pair(a, b) and p2(a) and p2(b) then \"both positive\"\n    else \"nah\"\n//│ fun example1: (Object & ~#Pair | Pair[Num, Num]) -> (\"both negative\" | \"both positive\" | \"nah\")\n\n// FIXME: The following test case should fail, but it doesn't. The reason is\n// `x` and `y` are in the desugared lexical scope, although they don't in the\n// original lexical scope.\nfun example2(p) =\n  if p is\n    Pair(x, y) and p1(x) and p1(y) then \"both negative\"\n    Pair(a, b) and p2(a) and p2(b) then x + y\n    else \"nah\"\n//│ fun example2: (Object & ~#Pair | Pair[Int, Int]) -> (\"both negative\" | \"nah\" | Int)\n\n// Next, let's check the name collision between a class and its super class.\n\nclass Base(x: Int)\nclass Derived(y: Int) extends Base(y + 1)\n//│ class Base(x: Int)\n//│ class Derived(y: Int) extends Base\n\n// Notice that Derived is not in the inferred type.\n:ducs:postprocess.result\nfun example3(t) =\n  if t is\n    Base(x) and p1(x) then x\n    Derived(y) then y\n    else 42\n//│ Post-processed UCS term:\n//│ case t*‡ of\n//│   refined Base*◊ ->\n//│     let ucs$args_t$Base*† = (Base).unapply(t,)\n//│     let x*‡ = (ucs$args_t$Base).0\n//│     let ucs$test$0*† = p1(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> x\n//│       _ ->\n//│         case t*‡ of\n//│           Derived*◊ ->\n//│             let ucs$args_t$Derived*† = (Derived).unapply(t,)\n//│             let y*‡ = (ucs$args_t$Derived).0\n//│             y\n//│           _ -> 42\n//│   _ -> 42\n//│ fun example3: forall 'a. (Base & {#x: Num & 'a} | Object & ~#Base) -> (Int | 'a)\n\nexample3(Derived(1))\n//│ Int\n//│ res\n//│     = 1\n\nfun example4(t, x) =\n  if t is\n    Base(x) and p1(x) then x\n    Derived(y) then y + x\n    //                  ^\n    // Note that this branch will be absorbed by the previous one. As the\n    // previous branch shadows the variable `x`, a correct implementation\n    // should restore the original value of `x` in this branch.\n    else 42\n//│ fun example4: forall 'a. (Base & {#x: Num & 'a} | Object & ~#Base, Int) -> (Int | 'a)\n\nexample4(Base(-1), 0) ~~> -1\nexample4(Base(1), 2) ~~> 42\n//│ \"passed\"\n//│ res\n//│     = 'passed'\n//│ res\n//│     = 'passed'\n\nexample4(Derived(1), 4) ~~> 5\n//│ \"passed\"\n//│ res\n//│     = 'passed'\n\nclass Base(x: Int)\nclass Derived[A](y: A) extends Base(1)\n//│ class Base(x: Int)\n//│ class Derived[A](y: A) extends Base\n\n// Notice that now Derived is generic, so it's appear in the inferred type.\nfun example5(t) =\n  if t is\n    Base(x) and p1(x) then x\n    Derived(y) then y\n    else 42\n//│ fun example5: forall 'a 'b. (Base & {#x: Num & 'a} & ~#Derived | Derived['b] & {#x: Num & 'a} | Object & ~#Base) -> (42 | 'a | 'b)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/staging/stages/Transformation.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n\nclass Cons[T](head: T, tail: List[T])\nmodule Nil\ntype List[T] = Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T])\n//│ module Nil\n//│ type List[T] = Cons[T] | Nil\n\nabstract class Either[out A, out B]\nclass Left[out A, out B](value: A) extends Either[A, B]\nclass Right[out A, out B](value: B) extends Either[A, B]\n//│ abstract class Either[A, B]\n//│ class Left[A, B](value: A) extends Either\n//│ class Right[A, B](value: B) extends Either\n\nclass Pair[A, B](x: A, y: B) {\n  fun mapFirst[C](f: A -> C): Pair[C, B] = Pair(f(x), y)\n  fun mapSecond[C](f: B -> C): Pair[A, C] = Pair(x, f(y))\n}\n//│ class Pair[A, B](x: A, y: B) {\n//│   fun mapFirst: forall 'C. (f: A -> 'C) -> Pair['C, B]\n//│   fun mapSecond: forall 'C0. (f: B -> 'C0) -> Pair[A, 'C0]\n//│ }\n\n:ducs:transform.result\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    Nil and ys is Nil then Some(Nil)\n  else None\n//│ Transformed UCS term:\n//│ if\n//│   xs is\n//│     Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys,) is Some(tail) then Some(Cons(f(x, y,), tail,),)\n//│     Nil and ys is Nil then Some(Nil,)\n//│   else None\n//│ fun zipWith: forall 'T 'T0 'T1 'T2. (('T, 'T0) -> 'T1, Cons['T] | Object & ~#Cons, Cons['T0] | Object & ~#Cons) -> (None | Some[in List['T1] & 'T2 out Nil | 'T2 | Cons['T1]])\n\n:ducs:transform.result\nfun getOrElse[T](x: Option[T], default: T): T =\n  if x is\n    Some(value) then value\n    None then default\n//│ Transformed UCS term:\n//│ if x is\n//│   Some(value) then value\n//│   None then default\n//│ fun getOrElse: forall 'T. (x: Option['T], default: 'T) -> 'T\n\nfun m3(x: Int): Bool = x % 3 == 0\nfun m5(x: Int): Bool = x % 5 == 0\n//│ fun m3: (x: Int) -> Bool\n//│ fun m5: (x: Int) -> Bool\n\n:ducs:transform.result\nfun f(x) =\n  if x is\n    Some(v) and m3(v) and m5(v) then \"FizzBuzz\"\n    Some(v) and m3(v) then \"Fizz\"\n    Some(v) and m5(v) then \"Buzz\"\n    else \"meh\"\n//│ Transformed UCS term:\n//│ if x is\n//│   Some(v) and m3(v,) and m5(v,) then \"FizzBuzz\"\n//│   Some(v) and m3(v,) then \"Fizz\"\n//│   Some(v) and m5(v,) then \"Buzz\"\n//│   else \"meh\"\n//│ fun f: (Object & ~#Some | Some[Int]) -> (\"Buzz\" | \"Fizz\" | \"FizzBuzz\" | \"meh\")\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/And.mls",
    "content": ":parseOnly\n:pt\n\n\nx and y\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ InfixApp:\n//│   lhs = Ident of \"x\"\n//│   kw = Keywrd of keyword 'and'\n//│   rhs = Ident of \"y\"\n\nx\n  and y\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ InfixApp:\n//│   lhs = Ident of \"x\"\n//│   kw = Keywrd of keyword 'and'\n//│   rhs = Ident of \"y\"\n\nif x\n  and y then z\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = InfixApp:\n//│       lhs = Ident of \"x\"\n//│       kw = Keywrd of keyword 'and'\n//│       rhs = Ident of \"y\"\n//│     kw = Keywrd of keyword 'then'\n//│     rhs = Ident of \"z\"\n\nif x\n  and y then z\n  else d\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = Block of Ls of \n//│     InfixApp:\n//│       lhs = InfixApp:\n//│         lhs = Ident of \"x\"\n//│         kw = Keywrd of keyword 'and'\n//│         rhs = Ident of \"y\"\n//│       kw = Keywrd of keyword 'then'\n//│       rhs = Ident of \"z\"\n//│     PrefixApp:\n//│       kw = Keywrd of keyword 'else'\n//│       rhs = Ident of \"d\"\n\nif x is\n  A and y then z\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = Ident of \"x\"\n//│     kw = Keywrd of keyword 'is'\n//│     rhs = Block of Ls of \n//│       InfixApp:\n//│         lhs = InfixApp:\n//│           lhs = Ident of \"A\"\n//│           kw = Keywrd of keyword 'and'\n//│           rhs = Ident of \"y\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"z\"\n\nif x is\n  A(u, v, w)\n    and y then z\n  B then C\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = Ident of \"x\"\n//│     kw = Keywrd of keyword 'is'\n//│     rhs = Block of Ls of \n//│       InfixApp:\n//│         lhs = InfixApp:\n//│           lhs = App:\n//│             lhs = Ident of \"A\"\n//│             rhs = Tup of Ls of \n//│               Ident of \"u\"\n//│               Ident of \"v\"\n//│               Ident of \"w\"\n//│           kw = Keywrd of keyword 'and'\n//│           rhs = Ident of \"y\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"z\"\n//│       InfixApp:\n//│         lhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"C\"\n\nif x is\n  A(u, v, w)\n    and v is\n      B then z\n  B then C\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = Ident of \"x\"\n//│     kw = Keywrd of keyword 'is'\n//│     rhs = Block of Ls of \n//│       InfixApp:\n//│         lhs = App:\n//│           lhs = Ident of \"A\"\n//│           rhs = Tup of Ls of \n//│             Ident of \"u\"\n//│             Ident of \"v\"\n//│             Ident of \"w\"\n//│         kw = Keywrd of keyword 'and'\n//│         rhs = InfixApp:\n//│           lhs = Ident of \"v\"\n//│           kw = Keywrd of keyword 'is'\n//│           rhs = Block of Ls of \n//│             InfixApp:\n//│               lhs = Ident of \"B\"\n//│               kw = Keywrd of keyword 'then'\n//│               rhs = Ident of \"z\"\n//│       InfixApp:\n//│         lhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"C\"\n\n:todo\nif x is\n  A(u, v, w)\n    and v is\n    B then z\n  B then C\n//│ ╔══[PARSE ERROR] Expected start of expression in this position; found new line instead\n//│ ║  l.132: \t    and v is\n//│ ║         \t            ^\n//│ ║  l.133: \t    B then z\n//│ ╙──       \t^^^^\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = Ident of \"x\"\n//│     kw = Keywrd of keyword 'is'\n//│     rhs = Block of Ls of \n//│       InfixApp:\n//│         lhs = App:\n//│           lhs = Ident of \"A\"\n//│           rhs = Tup of Ls of \n//│             Ident of \"u\"\n//│             Ident of \"v\"\n//│             Ident of \"w\"\n//│         kw = Keywrd of keyword 'and'\n//│         rhs = InfixApp:\n//│           lhs = Ident of \"v\"\n//│           kw = Keywrd of keyword 'is'\n//│           rhs = Error\n//│       InfixApp:\n//│         lhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"z\"\n//│       InfixApp:\n//│         lhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"C\"\n\nif x is\n  A(u, v, w)\n    and v is B\n    and w is B then z\n  B then C\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = Ident of \"x\"\n//│     kw = Keywrd of keyword 'is'\n//│     rhs = Block of Ls of \n//│       InfixApp:\n//│         lhs = InfixApp:\n//│           lhs = InfixApp:\n//│             lhs = App:\n//│               lhs = Ident of \"A\"\n//│               rhs = Tup of Ls of \n//│                 Ident of \"u\"\n//│                 Ident of \"v\"\n//│                 Ident of \"w\"\n//│             kw = Keywrd of keyword 'and'\n//│             rhs = InfixApp:\n//│               lhs = Ident of \"v\"\n//│               kw = Keywrd of keyword 'is'\n//│               rhs = Ident of \"B\"\n//│           kw = Keywrd of keyword 'and'\n//│           rhs = InfixApp:\n//│             lhs = Ident of \"w\"\n//│             kw = Keywrd of keyword 'is'\n//│             rhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"z\"\n//│       InfixApp:\n//│         lhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"C\"\n\nif x is\n  A(u, v, w)\n    and v is B then z\n    and w is B then z\n  B then C\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = InfixApp:\n//│     lhs = Ident of \"x\"\n//│     kw = Keywrd of keyword 'is'\n//│     rhs = Block of Ls of \n//│       InfixApp:\n//│         lhs = InfixApp:\n//│           lhs = App:\n//│             lhs = Ident of \"A\"\n//│             rhs = Tup of Ls of \n//│               Ident of \"u\"\n//│               Ident of \"v\"\n//│               Ident of \"w\"\n//│           kw = Keywrd of keyword 'and'\n//│           rhs = InfixApp:\n//│             lhs = Ident of \"v\"\n//│             kw = Keywrd of keyword 'is'\n//│             rhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = InfixApp:\n//│           lhs = InfixApp:\n//│             lhs = Ident of \"z\"\n//│             kw = Keywrd of keyword 'and'\n//│             rhs = InfixApp:\n//│               lhs = Ident of \"w\"\n//│               kw = Keywrd of keyword 'is'\n//│               rhs = Ident of \"B\"\n//│           kw = Keywrd of keyword 'then'\n//│           rhs = Ident of \"z\"\n//│       InfixApp:\n//│         lhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"C\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/BadUCSSyntax.mls",
    "content": ":js\n\n\n// ——— ——— ———\n\n:e\nif x else z\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (identifier)\n//│ ║  l.7: \tif x else z\n//│ ╙──     \t   ^\n//│ ╔══[COMPILATION ERROR] Name not found: z\n//│ ║  l.7: \tif x else z\n//│ ╙──     \t          ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n:e\nfun f(x, z) =\n  if x\n    else z\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (identifier)\n//│ ║  l.18: \t  if x\n//│ ╙──      \t     ^\n\n// ——— ——— ———\n\n// Works\nif\n  true\n  and true do\n    print(\"ok\")\n//│ > ok\n\n// Works\nif\n  true\n  and true\n  and true do\n    print(\"ok\")\n//│ > ok\n\n// Should work? Probably not\n:e\nif\n  true\n  and true\n  let x = 1\n  and true do\n    print(\"ok\")\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (true literal)\n//│ ║  l.45: \t  and true\n//│ ╙──      \t      ^^^^\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'do' here\n//│ ║  l.46: \t  let x = 1\n//│ ║        \t          ^\n//│ ║  l.47: \t  and true do\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.48: \t    print(\"ok\")\n//│ ╙──      \t^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// ——— ——— ———\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/ConjunctMatches.mls",
    "content": "// ConjunctMatches.mls\n// ===================\n// Examine the structure of conjunct matches.\n\n:global\n:parseOnly\n:pt\n\n\n// This test cases should be parsed as\n//     (((x is A) and (b is Y)) and (c is Z))\n// To achieve that, the following rules should be applied:\n// - is should be left associative\n// - and should be right associative\n// - is should have higher precedence than and\nif\n  x is A and y is B and c is Z then 1\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = Block of Ls of \n//│     InfixApp:\n//│       lhs = InfixApp:\n//│         lhs = InfixApp:\n//│           lhs = InfixApp:\n//│             lhs = Ident of \"x\"\n//│             kw = Keywrd of keyword 'is'\n//│             rhs = Ident of \"A\"\n//│           kw = Keywrd of keyword 'and'\n//│           rhs = InfixApp:\n//│             lhs = Ident of \"y\"\n//│             kw = Keywrd of keyword 'is'\n//│             rhs = Ident of \"B\"\n//│         kw = Keywrd of keyword 'and'\n//│         rhs = InfixApp:\n//│           lhs = Ident of \"c\"\n//│           kw = Keywrd of keyword 'is'\n//│           rhs = Ident of \"Z\"\n//│       kw = Keywrd of keyword 'then'\n//│       rhs = IntLit of 1\n\n// But since naughty users may add parentheses,\n// we should also parse the following case.\nif\n  x is A and (y is B and c is Z) then 1\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = Block of Ls of \n//│     InfixApp:\n//│       lhs = InfixApp:\n//│         lhs = InfixApp:\n//│           lhs = Ident of \"x\"\n//│           kw = Keywrd of keyword 'is'\n//│           rhs = Ident of \"A\"\n//│         kw = Keywrd of keyword 'and'\n//│         rhs = Bra:\n//│           k = Round\n//│           inner = InfixApp:\n//│             lhs = InfixApp:\n//│               lhs = Ident of \"y\"\n//│               kw = Keywrd of keyword 'is'\n//│               rhs = Ident of \"B\"\n//│             kw = Keywrd of keyword 'and'\n//│             rhs = InfixApp:\n//│               lhs = Ident of \"c\"\n//│               kw = Keywrd of keyword 'is'\n//│               rhs = Ident of \"Z\"\n//│       kw = Keywrd of keyword 'then'\n//│       rhs = IntLit of 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/Do.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option\n\n\n\n// Using `do` will not cause match errors.\n\nlet x = false\n//│ x = false\n\nif x do\n  print(\"executed\")\n  set x = false\n\nx\n//│ = false\n\nif not(x) do\n  print(\"executed\")\n//│ > executed\n\nif not x do\n  print(\"executed\")\n//│ > executed\n\nif (not x) do\n  print(\"executed\")\n  set x = false\n//│ > executed\n\nx\n//│ = false\n\n\n// Completely using `do`\n// =====================\n\n\nfun f(y) =\n  let x = Some(y)\n  if x is\n    Some(0) do set x = None\n    Some(v) and v % 2 == 0 do set x = Some(v / 2)\n  x\n  \nf(0)\n//│ = None\n\nf(42)\n//│ = Some(21)\n\nf(41)\n//│ = Some(41)\n\n\n// Mix using `then` and `do`\n// =========================\n\n\n:e\nfun g(y) =\n  let x = Some(y)\n  if x is\n    Some(0) do set x = None\n    Some(v) and v % 2 == 0 then set x = Some(v / 2)\n  x\n//│ ╔══[COMPILATION ERROR] Mixed use of `do` and `then` in the `if` expression.\n//│ ║  l.66: \t  if x is\n//│ ║        \t  ^^\n//│ ╟── Keyword `then` is used here.\n//│ ║  l.68: \t    Some(v) and v % 2 == 0 then set x = Some(v / 2)\n//│ ║        \t                           ^^^^\n//│ ╟── Keyword `do` is used here.\n//│ ║  l.67: \t    Some(0) do set x = None\n//│ ╙──      \t            ^^\n\ng(0)\n//│ = None\n\ng(42)\n//│ = Some(21)\n\ng(41)\n//│ = Some(41)\n\n\n// Completely using `then`\n// =======================\n\n\nfun h(y) =\n  let x = Some(y)\n  if x is\n    Some(0) then set x = None\n    Some(v) and v % 2 == 0 then set x = Some(v / 2)\n  x\n  \nh(0)\n//│ = None\n\nh(42)\n//│ = Some(21)\n\n:re\nh(41)\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n\n// [Adapted from Copilot (Claude Opus 4.6) summary:]\n// `pattern do body` inside `is` expression is not handled.\n// The root cause is at the parser level: in `Some of [process, rest] do \"hi\"`,\n// the `of` keyword greedily includes `do \"hi\"` inside the constructor argument,\n// producing `App(Some, Tup([InfixApp(Tup([process, rest]), do, \"hi\")]))`.\n// In `if`/`case`/`while` splits, the parser treats `do` as a split boundary\n// at the branch level, so it correctly separates pattern from consequent. But\n// in standalone `is` expressions, the block lines are parsed as regular\n// expressions, so `do` is parsed as an infix operator inside the constructor's\n// argument.\n// * [My note:]\n// * Operator `of` parses a _block_ on the RHS,\n// * and there's currently no way of parsing blocks at a lower precedence level.\n// * This code is not supposed to compile, anyway.\n:e\nSome(1) is\n  Some of [process, rest] do \"hi\"\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (infix operator 'do').\n//│ ║  l.129: \t  Some of [process, rest] do \"hi\"\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^^^^\n//│ = true\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/DoProblems.mls",
    "content": ":js\n\n// * It looks like trying to support both infix `do` and prefix `do` is a problem;\n// * maybe this part of the syntax needs to be redesigned.\n\n\n// ——— ——— ———\n// [Comment from Copilot (Claude Opus 4.6):]\n// Bug: `do` on a new line after `while` condition is not parsed as infix.\n// The parser explicitly excludes `do` from newline-infix handling (Parser.scala ~line 1088)\n// to prevent ambiguity with UCS splits (e.g., `0 then \"null\"\\ndo body` should be two split\n// arms, not `(0 then \"null\") do body`). Fixing this would require context-sensitive parsing\n// to distinguish `while` conditions from `if` split arms, which is a significant refactoring\n// of the parser's `exprCont` method.\n\n:fixme\nwhile\n    let arrMatches = true\n    arrMatches\n  do\n    print(arrMatches)\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'do' here\n//│ ║  l.18: \t    let arrMatches = true\n//│ ║        \t        ^^^^^^^^^^^^^^^^^\n//│ ║  l.19: \t    arrMatches\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.20: \t  do\n//│ ║        \t^^^^\n//│ ║  l.21: \t    print(arrMatches)\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n// ——— ——— ———\n// [Comment from Copilot (Claude Opus 4.6):]\n// Bug: `do` on a new line inside `if` block is not parsed as infix continuation.\n// Same root cause as the `while...do` bug above: the `do` exclusion in Parser.scala\n// prevents `do` from being treated as a newline-infix operator. In the `if` block,\n// `arrMatches !== null` and `do ()` are parsed as separate block items instead of\n// `arrMatches !== null do ()`. Fixing requires the same context-sensitive parsing\n// refactoring mentioned above.\n\nlet arrMatches = ()\n//│ arrMatches = ()\n\n// * Note: produces a match error\n:fixme\nif\n  arrMatches !== null\n  do\n    ()\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (null)\n//│ ║  l.48: \t  arrMatches !== null\n//│ ╙──      \t                 ^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n// * This one works:\nif\n  arrMatches !== null do\n    ()\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/Else.mls",
    "content": ":js\n\n// Else.mls\n// ========\n// Examine how the `else` keyword is parsed.\n\n\nfun f(x, y, z) = if x then y\n\n:pt\nfun f(x, y, z) = if x then y else z\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TermDef:\n//│   k = Fun\n//│   head = App:\n//│     lhs = Ident of \"f\"\n//│     rhs = Tup of Ls of \n//│       Ident of \"x\"\n//│       Ident of \"y\"\n//│       Ident of \"z\"\n//│   rhs = S of IfLike:\n//│     kw = Keywrd of keyword 'if'\n//│     split = Block of Ls of \n//│       InfixApp:\n//│         lhs = Ident of \"x\"\n//│         kw = Keywrd of keyword 'then'\n//│         rhs = Ident of \"y\"\n//│       PrefixApp:\n//│         kw = Keywrd of keyword 'else'\n//│         rhs = Ident of \"z\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\nfun f(x, y, z) =\n  if x\n    then y\n    else z\n\nfun f(x, y, z) = if x\n                 then y\n                 else z\n\nfun f(x, y, z) = if x then y\n  else z\n\nfun f(x, y, z) = if\n  x then y\n  else z\n\nfun f(x, y, z) =\n  if x then\n    y\n  else\n    z\n\nfun f(x, y, z) =\n  if x then y\n  else z\n\nfun f(x, y, z) =\n  if x then y\n    else z\n\nfun f(x, y, z) =\n  if x\n  then y\n  else z\n\nfun f(x, y, z) =\n  if x\n    then y\n    else z\n\n:fixme\nfun f(x, y, z) =\n  if\n    x then y else z\n//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here\n//│ ║  l.77: \t    x then y else z\n//│ ╙──      \t             ^^^^\n\n\nfun f(x, y) =\n  if x\n    then y\n\nlet audits = new Set()\n//│ audits = Set(0) {}\n\nif audits.has(1) === true do\n  print(\"ok\")\nelse\n  print(1)\n//│ > 1\n\n\n(if true then\n    5\n  else 1\n) + 3\n//│ = 8\n\n:fixme\n(if true\n  then\n    5\n  else 1\n) + 3\n//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here\n//│ ║  l.107: \t  else 1\n//│ ╙──       \t  ^^^^\n//│ = 8\n\n:fixme\n(if true\n  then\n    5 else 1\n) + 3\n//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here\n//│ ║  l.117: \t    5 else 1\n//│ ╙──       \t      ^^^^\n//│ = 8\n\n\ndata class Box[A](value: A)\n\n:w\nfun foo(x) = if x is\n  Box(0) then \"The box contains zero.\"\n  Box(1) then \"The box contains one.\"\n  else \"I can't tell you what's inside the box.\"\n  else \"I don't want to tell you what's inside the box.\"\n  else \"I shouldn't tell you what's inside the box.\"\n//│ ╔══[WARNING] This catch-all clause makes the following branches unreachable.\n//│ ║  l.131: \t  else \"I can't tell you what's inside the box.\"\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── This branch is unreachable.\n//│ ║  l.132: \t  else \"I don't want to tell you what's inside the box.\"\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── This branch is unreachable.\n//│ ║  l.133: \t  else \"I shouldn't tell you what's inside the box.\"\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/Empty.mls",
    "content": ":js\n\n\n:sjs\n:re\nif {}\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ throw globalThis.Object.freeze(new globalThis.Error(\"match error\"))\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n:re\nif\n  let x = 1\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n:re\nif\n  do print(\"whoops\")\n//│ > whoops\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n:re\n:e\nif\n  let x\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (let)\n//│ ║  l.29: \t  let x\n//│ ╙──      \t      ^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/IfOpSplit.mls",
    "content": ":js\n\n\nlet x = 1\n//│ x = 1\n\n\nif x is\n  0 then \"zero\"\n  1 then \"one\"\n//│ = \"one\"\n\nif x >\n  0 then true\n//│ = true\n\nif x >\n  1 then true\n  0 then false\n//│ = false\n\n\n// * This is an error because the two split branches would bind differently to the common prefix\n:pe\n:e\nif 1 + 2\n  * 3 then 0\n  + 4 then 0\n//│ ╔══[PARSE ERROR] Operator cannot be used inside this operator split\n//│ ║  l.28: \t  + 4 then 0\n//│ ║        \t  ^\n//│ ╟── as it has lower precedence than the splitting operator here\n//│ ║  l.27: \t  * 3 then 0\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword in this operator split inner position\n//│ ║  l.28: \t  + 4 then 0\n//│ ║        \t      ^^^^\n//│ ╟── Note: the operator split starts here\n//│ ║  l.27: \t  * 3 then 0\n//│ ╙──      \t  ^\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.26: \tif 1 + 2\n//│ ║        \t       ^\n//│ ║  l.27: \t  * 3 then 0\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.28: \t  + 4 then 0\n//│ ╙──      \t^^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\nif 1 + 2\n  * 3 then 0\n  * 4 then 1\n  else 2\n//│ = 2\n\n\nif (1 + 2)\n  * 3 === 12 then 0\n  * 4 === 12 then 1\n//│ = 1\n\nif (1 + 2)\n  * 3 === 7 then 0\n  + 4 === 7 then 1\n//│ = 1\n\n\n:e\nif 1 + 2\n  * 3 then 0\n  then 0\n//│ ╔══[COMPILATION ERROR] Unexpected infix use of keyword 'then' here\n//│ ║  l.70: \t  * 3 then 0\n//│ ║        \t           ^\n//│ ║  l.71: \t  then 0\n//│ ╙──      \t^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n\nif x\n  > 1 then true\n  == 1 then false\n//│ = false\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/Is.mls",
    "content": ":parseOnly\n\n\nx\n  is A\n//│ Parsed:\n//│ \tInfixApp(Ident(x),Keywrd(keyword 'is'),Ident(A))\n\n\nx\n  is A\n  is B\n//│ Parsed:\n//│ \tOpSplit(Ident(x),List(InfixApp(SplitPoint(),Keywrd(keyword 'is'),Ident(A)), InfixApp(SplitPoint(),Keywrd(keyword 'is'),Ident(B))))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/NestedOpSplits.mls",
    "content": ":js\n\n:ucs desugared\n// * Note that this always associates to the left\nfun f(x) =\n  if x ==\n    1 +\n      2 then 0\n      _ then 1\n//│ Split with nested patterns:\n//│ >  if\n//│ >    let tmp:scrut = 1\n//│ >    let tmp:scrut = (member:Predef⁰.)equals‹member:equals›(x⁰, builtin:+⁰(tmp:scrut⁰, 2))\n//│ >    tmp:scrut is true then 0\n//│ >    else 1\n//│ Expanded split with flattened patterns:\n//│ >  ‹if|while›\n//│ >    let tmp:scrut = 1\n//│ >    let tmp:scrut = (member:Predef⁰.)equals‹member:equals›(x⁰, builtin:+⁰(tmp:scrut⁰, 2))\n//│ >    tmp:scrut is true then 0\n//│ >    else 1\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/Of.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\nfun getOrHello(x) = if x is\n  None then \"hello\"\n  Some of\n    a then a\n\ngetOrHello(None)\n//│ = \"hello\"\n\ngetOrHello(Some of 42)\n//│ = 42\n\nfun getOrElse(x, defaultValue) = if x is\n  None then defaultValue\n  Some of value then value\n\nNone getOrElse(42)\n//│ = 42\n\nSome(0) getOrElse(42)\n//│ = 0\n\nlet getOr42 = case\n  Some of value then value\n  None then 42\n//│ getOr42 = fun\n\nNone getOr42()\n//│ = 42\n\nSome(0) getOr42()\n//│ = 0\n\nfun check(x) = x is Some of 42\n\ncheck(None)\n//│ = false\n\ncheck(Some(42))\n//│ = true\n\ncheck(Some(77))\n//│ = false\n\ndata class Left(leftValue)\ndata class Right(rightValue)\n\nfun getBothOrElse(either, defaultValue) = if either is\n  None then defaultValue\n  Some of\n    Left of value then value\n    Right of value then value\n\n:expect 42\ngetBothOrElse of None, 42\n//│ = 42\n\n:expect 7\ngetBothOrElse of Some(Left(7)), 42\n//│ = 7\n\n:expect \"noice\"\ngetBothOrElse of Some(Left(\"noice\")), 42\n//│ = \"noice\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/PlainConditionals.mls",
    "content": ":js\n\nfun f(x) = x\nfun g(x) = x\nfun h(x) = x\n\ndata class Pair[A, B](fst: A, snd: B)\n\n// Simple conditionals in the form of `x is P`.\n// ============================================\n\n:expect true\nPair(0, 1) is Pair\n//│ = true\n\n:expect true\nPair(0, 1) is Pair(a, b)\n//│ = true\n\n:expect true\nPair(0, 1) is Pair(0, _)\n//│ = true\n\n:expect true\nif Pair(0, 1) is Pair(a, b) then true else false\n//│ = true\n\n// Based on the above, add an `and` at the end, in the form of `x is P and t`.\n// ===========================================================================\n\n:expect false\nPair(0, 1) is Pair(a, b) and a > b\n//│ = false\n\n:expect true\nPair(1, 0) is Pair(a, b) and a > b\n//│ = true\n\nfun foo(x) = f(x) and g(x) and h(x)\n\n:expect [true, false]\n[foo(true), foo(false)]\n//│ = [true, false]\n\n// Test matching multiple patterns at once.\n// ========================================\n\nfun foo(x) = x is\n  Pair\n  Int\n\n:expect [true, false, true]\n[foo(2), foo(3.14159), foo(Pair(0, 1))]\n//│ = [true, false, true]\n\nfun foo(x) = x is Pair | Int\n\n:expect [true, false, true]\n[foo(2), foo(3.14159), foo(Pair(0, 1))]\n//│ = [true, false, true]\n\nfun foo(x) = x is\n  Pair | Int\n\n:expect [true, false, true]\n[foo(2), foo(3.14159), foo(Pair(0, 1))]\n//│ = [true, false, true]\n\nfun foo(x) = x is { Pair, Int }\n\n:expect [true, false, true]\n[foo(2), foo(3.14159), foo(Pair(0, 1))]\n//│ = [true, false, true]\n\n:e\nfun foo(x) = x is\n  Pair(a, b) and a > b\n  Int\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (infix operator 'and').\n//│ ║  l.77: \t  Pair(a, b) and a > b\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^\n\n\n:e\nfun foo(x) = x is Pair(a, b) | Int\n//│ ╔══[COMPILATION ERROR] Found an inconsistent variable in disjunction patterns.\n//│ ║  l.85: \tfun foo(x) = x is Pair(a, b) | Int\n//│ ║        \t                       ^\n//│ ╟── The variable is missing from this sub-pattern.\n//│ ║  l.85: \tfun foo(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                               ^^^\n//│ ╔══[COMPILATION ERROR] Found an inconsistent variable in disjunction patterns.\n//│ ║  l.85: \tfun foo(x) = x is Pair(a, b) | Int\n//│ ║        \t                          ^\n//│ ╟── The variable is missing from this sub-pattern.\n//│ ║  l.85: \tfun foo(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                               ^^^\n\n// Test how shorthand conditionals work together with lambda functions.\n// ====================================================================\n\ndata class A[T](arg: T)\n\nlet foo = x => x is A(_)\n//│ foo = fun foo\n\n:expect [false, true]\n[foo(0), foo(A(0))]\n//│ = [false, true]\n\nlet foo = _ is A\n//│ foo = fun foo\n\n:expect [false, true]\n[foo(0), foo(A(0))]\n//│ = [false, true]\n\nlet foo = _ is A(_)\n//│ foo = fun foo\n\n:expect [false, true]\n[foo(0), foo(A(0))]\n//│ = [false, true]\n\nlet foo = _ is A(x) and x > 0\n//│ foo = fun\n\n:expect [false, false, true]\n[foo(0), foo(A(0)), foo(A(1))]\n//│ = [false, false, true]\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/SimpleUCS.mls",
    "content": ":js\n\nabstract class Option[A]: Some[A] | None\ndata class Some[A](value: A) extends Option[A]\nobject None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\ndata class Left[A](leftValue: A) extends Either[A, Nothing]\ndata class Right[B](rightValue: B) extends Either[Nothing, B]\n\nfun f(x, y) =\n  if x is\n    Left(xv) and y is Left(yv) then xv + yv\n    Right(xv) and y is Right(yv) then xv * yv\n    None and y is None then 0\n\nfun f(x, y) =\n  if x is\n    Left(xv) and y is Left(yv) then xv + yv\n    None then 0\n\nfun f(x, y) =\n  if x is\n    Left(xv) and y is\n      Left(yv) then xv + yv\n      Right(yv) then xv * yv\n    None then 0\n\nfun f(x) =\n  if x is\n    Some(v) and\n      v < 0 then \"negative\"\n      v > 0 then \"positive\"\n      _     then \"zero\"\n    None then \"nothing\"\n\nfun f(x, y) =\n  if x is\n    Some(x) and y is\n      Some(y) then 0\n\ndata class A[T](value: T)\ndata class B[T](value: T)\n\nfun f(x, y, u, v) =\n  if x is\n    A(a) and y ==\n      u then 0\n      v then 1\n    A(a) and y is\n      B(0) then 0\n      B(1) then 1\n    A(_) then 99\n\nfun f(x) =\n  if x is\n    A(_) then \"A\"\n    B(_) then \"B\"\n\n// :e\nfun f(x, y) =\n  if x is\n    Some(xv) and y is Some(yv) then xv + yv\n    None and y is None then 0\n\n// :e\nfun f(x, y) =\n  if x is\n    Some(xv) and y is\n      Some(yv) then xv + yv\n      None then xv * 2\n    None and y is\n      Some(yv) then yv * 3\n\nfun f(x, y) =\n  if x is\n    A and y is\n      B then \"bruh\"\n\nfun f(x, y, z) =\n  if x is\n    A and z == 0 and y == 0 and y is\n      B then \"bruh\"\n    A then \"oui\"\n\n\n:breakme // Note: should report missing final else clause.\n:e\nfun f(x, y) =\n  if x is\n    Some(x) and y\n      >  0 then \"gt\"\n      <  0 then \"le\"\n      == 0 then \"eq\"\n\n\nfun isValid(x) = if x then false else true\n\n\nfun f(x, allowNone) =\n  if x is\n    Some(x) and isValid(x) then \"good\"\n    None and allowNone then \"okay\"\n    else \"bad\"\n\nfun f(x) =\n  if x is\n    None then \"bruh\"\n    Some(x) then \"roll\"\n    _ and x == 0 then 0\n    _ then \"rock\"\n\nfun f(x, a, b) =\n  if x is\n    A(aa) and a then aa\n    B(bb) and b then bb\n    _           then 0\n\nfun f(x, y, b) =\n  if x is\n    Some(xv) and y\n      is Some(yv) then \"bruh\"\n      is None then \"bruh\"\n    Some(xv) and b then xv + b\n    _ then \"roll\"\n\nfun g(x, y, b) =\n  if x is\n    Some(xv) and y\n      is Some(yv) then yv\n      is None then \"bruh\"\n    Some(xv) and b then xv + b\n    _ then \"roll\"\n\n\nfun foo(x, y, z) =\n  if x - y > 0 then Some(x + y + z) else None\n\n// Uncomment this block to make the following block work.\n// fun foo(x, y, z) =\n//   if x - y > 0 then Some(\n//     if x % 2 == 0 then Left(x) else Right(x)\n//   ) else None\n\n\nfun f(u, v, w) =\n  if foo(u, v, w) is\n    Some(x) and x is\n      Left(_) then \"left-defined\"\n      Right(_) then \"right-defined\"\n    None then \"undefined\"\n\n\nfun p(x) = if x >= 0 then Right(x) else Left(x)\n\n\nfun g(a, b) =\n  if p(a) is\n    Left(x) and b is\n      Some(y) then x + y\n      None    then x * a\n    Right(x) and b is\n      Some(y) then x * y\n      None    then x\n\ng(5, None)\n//│ = 5\n\ng(5, Some(7))\n//│ = 35\n\ng(0 - 5, None)\n//│ = 25\n\ng(0 - 5, Some(9))\n//│ = 4\n\ndata class Var(name: Str)\nabstract class ValBase: (IntVal | BoolVal)\ndata class IntVal(value: Int) extends ValBase\ndata class BoolVal(value: Bool) extends ValBase\ndata class Lit(value: ValBase)\n\nfun p(e, context) =\n  if e is\n    Var(x) and context.get(x) is\n      Some(IntVal(v)) then Left(v)\n      Some(BoolVal(v)) then Right(v)\n    Lit(IntVal(v)) then Left(v)\n    Lit(BoolVal(v)) then Right(v)\n\ndata class Nil()\n\n// Support operator constructor like ::\n:todo\n:e\nfun f(x) =\n  if x is\n    0 ::\n      Nil() then \"oh\"\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (operator application).\n//│ ║  l.199: \t    0 ::\n//│ ║         \t    ^^^^\n//│ ║  l.200: \t      Nil() then \"oh\"\n//│ ╙──       \t^^^^^^\n\n\nfun f(x) =\n  if x == 0 and x is\n    A(_) then \"A\"\n    B(_) then \"B\"\n  else \"bruh\"\n\n\nfun helper(x) =\n  if x == 0 then None else Some(x)\n\n\nfun g(x, y) =\n  if x == 0 and helper(x) is\n    Some(a) and helper(y) is\n      Some(b) then a + b\n      None then a + 1\n    None and helper(y) is\n      Some(b) then 2 + b\n      None then 1\n  else\n    0\n\n\nfun test(x) = if x then 0 else \"oops\"\n\n\ntest(true)\n//│ = 0\n\ntest(false)\n//│ = \"oops\"\n\ntest(0)\n//│ = \"oops\"\n\ntest(1)\n//│ = \"oops\"\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/Split.mls",
    "content": ":parseOnly\n:pt\n\n:pt\n1 +\n  2\n  3\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpApp:\n//│   lhs = IntLit of 1\n//│   op = Ident of \"+\"\n//│   rhss = Ls of \n//│     Block of Ls of \n//│       IntLit of 2\n//│       IntLit of 3\n\nif f(x) ==\n  1 + 1 then 0\n  2 then 3\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = OpApp:\n//│     lhs = App:\n//│       lhs = Ident of \"f\"\n//│       rhs = Tup of Ls of \n//│         Ident of \"x\"\n//│     op = Ident of \"==\"\n//│     rhss = Ls of \n//│       Block of Ls of \n//│         InfixApp:\n//│           lhs = OpApp:\n//│             lhs = IntLit of 1\n//│             op = Ident of \"+\"\n//│             rhss = Ls of \n//│               IntLit of 1\n//│           kw = Keywrd of keyword 'then'\n//│           rhs = IntLit of 0\n//│         InfixApp:\n//│           lhs = IntLit of 2\n//│           kw = Keywrd of keyword 'then'\n//│           rhs = IntLit of 3\n\nif x +\n  1 *\n    2 then 3\n    4 then 5\n  y /\n    6 is\n      A then 7\n      B then 9\n      else 42\n    8 then 9\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ IfLike:\n//│   kw = Keywrd of keyword 'if'\n//│   split = OpApp:\n//│     lhs = Ident of \"x\"\n//│     op = Ident of \"+\"\n//│     rhss = Ls of \n//│       Block of Ls of \n//│         OpApp:\n//│           lhs = IntLit of 1\n//│           op = Ident of \"*\"\n//│           rhss = Ls of \n//│             Block of Ls of \n//│               InfixApp:\n//│                 lhs = IntLit of 2\n//│                 kw = Keywrd of keyword 'then'\n//│                 rhs = IntLit of 3\n//│               InfixApp:\n//│                 lhs = IntLit of 4\n//│                 kw = Keywrd of keyword 'then'\n//│                 rhs = IntLit of 5\n//│         OpApp:\n//│           lhs = Ident of \"y\"\n//│           op = Ident of \"/\"\n//│           rhss = Ls of \n//│             Block of Ls of \n//│               InfixApp:\n//│                 lhs = IntLit of 6\n//│                 kw = Keywrd of keyword 'is'\n//│                 rhs = Block of Ls of \n//│                   InfixApp:\n//│                     lhs = Ident of \"A\"\n//│                     kw = Keywrd of keyword 'then'\n//│                     rhs = IntLit of 7\n//│                   InfixApp:\n//│                     lhs = Ident of \"B\"\n//│                     kw = Keywrd of keyword 'then'\n//│                     rhs = IntLit of 9\n//│                   PrefixApp:\n//│                     kw = Keywrd of keyword 'else'\n//│                     rhs = IntLit of 42\n//│               InfixApp:\n//│                 lhs = IntLit of 8\n//│                 kw = Keywrd of keyword 'then'\n//│                 rhs = IntLit of 9\n\n:todo\nif\n  x\n  is\n    A then \"A\"\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: List() (of class Nil$)\n\nx\n  + 1\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpApp:\n//│   lhs = Ident of \"x\"\n//│   op = Ident of \"+\"\n//│   rhss = Ls of \n//│     IntLit of 1\n\nx\n  + 1\n  + 2\n  + 3\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ OpSplit:\n//│   lhs = Ident of \"x\"\n//│   ops_rhss = Ls of \n//│     OpApp:\n//│       lhs = SplitPoint\n//│       op = Ident of \"+\"\n//│       rhss = Ls of \n//│         IntLit of 1\n//│     OpApp:\n//│       lhs = SplitPoint\n//│       op = Ident of \"+\"\n//│       rhss = Ls of \n//│         IntLit of 2\n//│     OpApp:\n//│       lhs = SplitPoint\n//│       op = Ident of \"+\"\n//│       rhss = Ls of \n//│         IntLit of 3\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/TupleRest.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Stack\n\nfun f(xs) = if xs is\n  [..xs] then 0\n  [...xs] then 1\n  [..[]] then 2\n  [...[]] then 3\n  [..Cons(x, xs)] then 4\n  [...Cons(x, xs)] then 5\n  [..] then 6\n  [...] then 7\n  [.., x] then 8\n  [..., x] then 9\n  [... , x] then 10\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ucs/syntax/WithBraces.mls",
    "content": "\n// :elt\nx => if x is { 0 then false, 1 then true }\n\n// :pt\n// :elt\nx => if x is\n  0 then false\n  1 then true\n\nif 0 is {\n  0 then false\n}\n\nx => if x is {\n  0 then false\n  1 then true\n}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/BadPatterns.mls",
    "content": ":js\n\n\n:e\npattern P\n//│ ╔══[COMPILATION ERROR] Pattern definitions must have a body.\n//│ ║  l.5: \tpattern P\n//│ ╙──     \t^^^^^^^^^\n\n:e\npattern Foo1[A]: ...\n//│ ╔══[COMPILATION ERROR] Pattern definitions must have a body.\n//│ ║  l.11: \tpattern Foo1[A]: ...\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^\n\n:fixme\npattern Foo2[pattern A]: ...\n//│ /!!!\\ Uncaught error: scala.MatchError: TypeDef(Pat,Ident(A),None) (of class hkmc2.syntax.Tree$TypeDef)\n\n:e\npattern Foo(pattern T)\n//│ ╔══[COMPILATION ERROR] Pattern definitions must have a body.\n//│ ║  l.21: \tpattern Foo(pattern T)\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^\n\n\npattern P = P\n\n:breakme // should be rejected\n:e\n:re\n1 is P\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/BasicStackPatterns.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Stack.mls\"\nopen Stack\n\n\n// * Wrong parse – could we make it parse the expected result instead?\n:e\n:w\npattern P = x :: xs => [x, xs]\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.11: \tpattern P = x :: xs => [x, xs]\n//│ ╙──      \t                        ^\n//│ ╔══[WARNING] Unused pattern binding: x.\n//│ ║  l.11: \tpattern P = x :: xs => [x, xs]\n//│ ╙──      \t            ^\n\npattern P = (x :: xs) => [x, xs]\n\n1 :: Nil is P\n//│ = true\n\nlet f = case\n  P as extr then extr\n//│ f = fun\nf(1 :: 2 :: 3 :: Nil)\n//│ = [1, Cons(2, Cons(3, Nil))]\n\n\npattern P(x, xs) = x :: xs\n\n\n1 :: Nil is P\n//│ = true\n\n1 :: Nil is P(a, b)\n//│ = true\n\n\nlet f = case\n  P(x, xs) then [x, xs]\n//│ f = fun\nf(1 :: 2 :: 3 :: Nil)\n//│ = [1, Cons(2, Cons(3, Nil))]\n\nlet f = case\n  P as extracted then extracted\n//│ f = fun\nf(1 :: 2 :: 3 :: Nil)\n//│ = [1, Cons(2, Cons(3, Nil))]\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/Future.mls",
    "content": ":js\n\n:e\n// Hypothetical syntax: parameterized patterns declared by type parameters.\npattern Rep0[A] = \"\" | A ~ Rep0[A]\n//│ ╔══[COMPILATION ERROR] Pattern name not found: A.\n//│ ║  l.5: \tpattern Rep0[A] = \"\" | A ~ Rep0[A]\n//│ ╙──     \t                       ^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (application).\n//│ ║  l.5: \tpattern Rep0[A] = \"\" | A ~ Rep0[A]\n//│ ╙──     \t                           ^^^^^^^\n\n:fixme\n// Hypothetical syntax: put pattern parameters in the type parameter list but\n// prefixed with `pattern`.\npattern Rep0[pattern A] = \"\" | A ~ Rep0[A]\n//│ /!!!\\ Uncaught error: scala.MatchError: TypeDef(Pat,Ident(A),None) (of class hkmc2.syntax.Tree$TypeDef)\n\n:e\n// Hypothetical syntax: separate parameter list for the extraction.\npattern Rep0(pattern A, B, C)(head) =\n  \"\" | (A as head) ~ Rep0[A]\n//│ ╔══[COMPILATION ERROR] Multiple parameter lists are not supported for this definition.\n//│ ║  l.21: \tpattern Rep0(pattern A, B, C)(head) =\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.22: \t  \"\" | (A as head) ~ Rep0[A]\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (application).\n//│ ║  l.22: \t  \"\" | (A as head) ~ Rep0[A]\n//│ ╙──      \t                     ^^^^^^^\n//│ ╔══[COMPILATION ERROR] Found an inconsistent variable in disjunction patterns.\n//│ ║  l.22: \t  \"\" | (A as head) ~ Rep0[A]\n//│ ║        \t             ^^^^\n//│ ╟── The variable is missing from this sub-pattern.\n//│ ║  l.22: \t  \"\" | (A as head) ~ Rep0[A]\n//│ ╙──      \t  ^^\n\npattern Identifier = (\"a\" ..= \"z\") ~ (Identifier | \"\")\n\n// Pattern extractions through non-`pattern` parameters.\npattern Email(name, domain) =\n  (Identifier as name) ~ \"@\" ~ (Identifier as domain)\n\n:e\n// Hypothetical syntax (very unlikely to implement): view patterns\npattern GreaterThan(value) = case\n  n and n > value then n\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (case).\n//│ ║  l.47: \t  n and n > value then n\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^^^\n\n:e\n// Hypothetical syntax (very unlikely to implement): normal view patterns\nfun view = case\n  n and n > 5 then n\n  else undefined\nfun foo(x) = if x is\n  view as\n    Unit then ....\n    Arrow(...) then ....\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (infix operator 'as').\n//│ ║  l.58: \t  view as\n//│ ║        \t  ^^^^^^^\n//│ ║  l.59: \t    Unit then ....\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.60: \t    Arrow(...) then ....\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n// In the future, any function can be a pattern\n//  (x => view(x)) as ...\n//  (case { ... }) as ...\n\n\n:pe\n:e\n// Hypothetical syntax: use `to` instead of ugly `..=`\npattern Char = \"a\" to \"z\" | \"A\" to \"Z\" | \"0\" to \"9\" | \"_\" | \"-\"\npattern Many(pattern T) = T ~ (Many(T) | \"\")\npattern Star(pattern T) = \"\" | Many(T)\npattern Email(name, domains) =\n  Rep(Char | \".\") as name ~ \"@\" ~ Rep(Rep(Char) ~ ) as domain\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.78: \tpattern Char = \"a\" to \"z\" | \"A\" to \"Z\" | \"0\" to \"9\" | \"_\" | \"-\"\n//│ ╙──      \t                      ^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (juxtaposition).\n//│ ║  l.78: \tpattern Char = \"a\" to \"z\" | \"A\" to \"Z\" | \"0\" to \"9\" | \"_\" | \"-\"\n//│ ╙──      \t               ^^^^^^\n\n:pe\n:e\n// Hypothetical syntax: use `to` instead of ugly `..=`\npattern Digits = \"0\" to \"9\" ~ (Digits | \"\")\n//│ ╔══[PARSE ERROR] Expected end of input; found literal instead\n//│ ║  l.93: \tpattern Digits = \"0\" to \"9\" ~ (Digits | \"\")\n//│ ╙──      \t                        ^^^\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (juxtaposition).\n//│ ║  l.93: \tpattern Digits = \"0\" to \"9\" ~ (Digits | \"\")\n//│ ╙──      \t                 ^^^^^^\n\npattern Test(foo, bar) = (\"foo\" as foo) ~ (\"bar\" as bar)\n\n\"foobar\" is Test\n//│ = true\n\n:expect MatchSuccess([\"foo\", \"bar\"], null)\nTest.unapply(\"foobar\")\n//│ = MatchSuccess([\"foo\", \"bar\"], null)\n\n:pt\n// TODO: We cannot distinguish between `...` and `undefined` in the `Elaborator` now.\npattern Email(name, domain) = ...\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TypeDef:\n//│   k = Pat\n//│   head = App:\n//│     lhs = Ident of \"Email\"\n//│     rhs = Tup of Ls of \n//│       Ident of \"name\"\n//│       Ident of \"domain\"\n//│   rhs = S of Block of Ls of \n//│     UnitLit of false\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n\n// * Future: `as`-splits\n\n:fixme // TODO\nx => if x as\n  0 then false\n  1 then true\n//│ ╔══[COMPILATION ERROR] Unrecognized term split (infix operator 'as')\n//│ ║  l.129: \tx => if x as\n//│ ║         \t        ^^^^\n//│ ║  l.130: \t  0 then false\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.131: \t  1 then true\n//│ ╙──       \t^^^^^^^^^^^^^\n//│ = fun\n\n:fixme // TODO\npattern Test = (0 => false) | (1 => true)\nfun test(x) = if x is\n  Test as\n    true  then \"T\"\n    false then \"F\"\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern split (infix operator 'as').\n//│ ║  l.144: \t  Test as\n//│ ║         \t  ^^^^^^^\n//│ ║  l.145: \t    true  then \"T\"\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.146: \t    false then \"F\"\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^\n\n\n:fixme // TODO This should work!\npattern Test = (0 => false) | (1 => true)\nif 0 is ((Test as r) where (r is x)) then print(x)\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.158: \tif 0 is ((Test as r) where (r is x)) then print(x)\n//│ ╙──       \t                                                ^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\n:fixme // TODO This should work!\npattern Test = 0 | 1\nclass Id(name: Test)\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference.\n//│ ║  l.167: \tclass Id(name: Test)\n//│ ╙──       \t               ^^^^\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference.\n//│ ║  l.167: \tclass Id(name: Test)\n//│ ║         \t               ^^^^\n//│ ╙── Non-module parameter must have a non-module type.\n//│ ╔══[COMPILATION ERROR] Expected a non-module type; found reference.\n//│ ║  l.167: \tclass Id(name: Test)\n//│ ╙──       \t               ^^^^\n\n\n// * TODO: maybe we could allow this more lightweight alternative syntax?\n\n:todo\npattern StatementBased =\n  0 => \"zero\"\n  1 => \"one\"\n  _ => \"many\"\n//│ ╔══[COMPILATION ERROR] Unexpected record property pattern.\n//│ ║  l.184: \t  0 => \"zero\"\n//│ ╙──       \t  ^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unexpected record property pattern.\n//│ ║  l.185: \t  1 => \"one\"\n//│ ╙──       \t  ^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unexpected record property pattern.\n//│ ║  l.186: \t  _ => \"many\"\n//│ ╙──       \t  ^^^^^^^^^^^\n\n\n| x => 1\n//│ = fun\n\n// :de\n:fixme // TODO: support lambdas with patterns defined this way?\n| 0 => 1\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found integer literal\n//│ ║  l.203: \t| 0 => 1\n//│ ╙──       \t  ^\n//│ = fun\n\n:fixme // TODO\n| [x] => 1\n//│ ╔══[COMPILATION ERROR] Illegal constraint syntax.\n//│ ║  l.210: \t| [x] => 1\n//│ ╙──       \t   ^\n//│ /!!!\\ Uncaught error: scala.MatchError: Constrained(List(),Lit(IntLit(1))) (of class hkmc2.semantics.Term$Constrained)\n\n| (x, y) => 1\n//│ = fun\n\n:fixme // TODO\n| (x, 0) => 1\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found integer literal\n//│ ║  l.220: \t| (x, 0) => 1\n//│ ╙──       \t      ^\n//│ = fun\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/JoinPatterns.mls",
    "content": ":js\n\npattern SimpleJoin = (\"abc\" | \"xyz\") ~ (\"def\" | \"\")\n\n:expect true\n\"abc\" is SimpleJoin\n//│ = true\n\n:expect true\n\"abcdef\" is SimpleJoin\n//│ = true\n\n:expect true\n\"xyzdef\" is SimpleJoin\n//│ = true\n\n:expect true\n\"xyz\" is SimpleJoin\n//│ = true\n\n:expect false\n\"abcxyzdef\" is SimpleJoin\n//│ = false\n\n// TODO: If we want to get rid of exponential blowup here, we need to memoize the\n//  entire sub-split instead of the innermost consequents.\npattern Exponential = (\"a\" | \"b\") ~ (\"c\" | \"d\") ~ (\"e\" | \"f\") ~ (\"g\" | \"h\") // ~ (\"i\" | \"j\") ~ (\"k\" | \"l\") ~ (\"m\" | \"n\") ~ (\"o\" | \"p\") ~ (\"q\" | \"r\") ~ (\"s\" | \"t\") ~ (\"u\" | \"v\") ~ (\"w\" | \"x\") ~ (\"y\" | \"z\")\n\n:expect true\n\"aceg\" is Exponential\n//│ = true\n\n:expect true\n\"bcfh\" is Exponential\n//│ = true\n\n\"abcdefghijklm\" is Exponential\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/LocalPatterns.mls",
    "content": ":js\n\npattern One = \"1\"\n\nmodule Playground with\n  pattern Zero = \"0\"\n  pattern DoubleZero = Zero ~ Zero\n  pattern ZeroOne = Zero ~ One\n\nPlayground\n//│ = class Playground {\n//│   Zero: pattern Zero,\n//│   DoubleZero: pattern DoubleZero,\n//│   ZeroOne: pattern ZeroOne\n//│ }\n\n// Pattern defined in a module can be used with qualified name.\n// ============================================================\n\nPlayground.Zero\n//│ = pattern Zero\n\nPlayground.Zero.unapply(\"0\")\n//│ = MatchSuccess(\"0\", null)\n\n:expect true\n\"0\" is Playground.Zero\n//│ = true\n\n// Patterns defined in a module can refer to other patterns in the same module.\n// ============================================================================\n\nPlayground.DoubleZero\n//│ = pattern DoubleZero\n\nPlayground.DoubleZero.unapply(\"00\")\n//│ = MatchSuccess(\"00\", null)\n\n:expect true\n\"00\" is Playground.DoubleZero\n//│ = true\n\n// Patterns defined in a module can refer to patterns in the global scope.\n// =======================================================================\n\nPlayground.ZeroOne\n//│ = pattern ZeroOne\n\nPlayground.ZeroOne.unapply(\"01\")\n//│ = MatchSuccess(\"01\", null)\n\n:expect true\n\"01\" is Playground.ZeroOne\n//│ = true\n\n// Patterns defined in the global scope can refer to patterns in a module.\n// =======================================================================\n\npattern TripleZero = Playground.DoubleZero ~ Playground.Zero\n\nTripleZero\n//│ = pattern TripleZero\n\nTripleZero.unapply(\"000\")\n//│ = MatchSuccess(\"000\", null)\n\n:expect true\n\"000\" is TripleZero\n//│ = true\n\n:expect false\n\"001\" is TripleZero\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/MatchResult.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Runtime.mls\"\n\nopen Runtime { MatchSuccess, MatchFailure }\n\n\nMatchSuccess(0, new Object)\n//│ = MatchSuccess(0, {})\n\nif MatchSuccess(0, new Object) is MatchSuccess(x, _) then x\n//│ = 0\n\nMatchFailure(\"oops\")\n//│ = MatchFailure(\"oops\")\n\nif MatchFailure(\"oops\") is MatchFailure(x) then x\n//│ = \"oops\"\n\ndata class MatchSuccess(x)\n\nMatchSuccess(0)\n//│ = MatchSuccess(0)\n\nopen annotations { compile }\n\npattern Cross = \"X\"\n\npattern Id(x) = _\n\ndata class Pair(left, right)\n\npattern BacktrackOnRight = Pair(\"same\", 0) | Pair(\"same\", 1)\n\npattern BacktrackOnLeft = Pair(0, \"same\") | Pair(1, \"same\")\n\nCross.unapply(\"X\")\n//│ = MatchSuccess(\"X\", null)\n\nCross.unapply(\"0\")\n//│ = MatchFailure(null)\n\n// :sir\nfun foo(x) = x is Cross\n\n:sir\n// Keep the IR output to prevent regressions.\nfun isCompiledCross(x) = x is @compile Cross\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let isCompiledCross⁰;\n//│ define isCompiledCross⁰ as fun isCompiledCross¹(x) {\n//│   let matcher__Cross$, matchSuccess, lambda;\n//│   define lambda as fun lambda⁰(input) {\n//│     let p_0$, p_0$1, tmp, tmp1;\n//│     match input\n//│       \"X\" =>\n//│         set tmp = true;\n//│         set p_0$ = tmp;\n//│         return p_0$\n//│       else\n//│         set tmp1 = false;\n//│         set p_0$1 = tmp1;\n//│         return p_0$1\n//│     end\n//│   };\n//│   set matcher__Cross$ = lambda⁰;\n//│   set matchSuccess = matcher__Cross$(x);\n//│   match matchSuccess\n//│     true =>\n//│       return true\n//│     else\n//│       return false\n//│   end\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n// :sir\nfun getCompiledCross(x) = if x is\n  (@compile Cross) as result then result\n  else \"nope\"\n\n// :sir\nfun isCompiledId(x) = x is @compile Id\n\n// :sir\nfun isCompiledBacktrackOnRight(x) = x is @compile BacktrackOnRight\n\n// :sir\nfun getCompiledBacktrackOnRight(x) =\n  if x is (@compile BacktrackOnRight) as result then result\n  else \"nope\"\n\n// :sir\nfun isCompiledBacktrackOnLeft(x) = x is @compile BacktrackOnLeft\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/RangePatterns.mls",
    "content": ":js\n\npattern Lower = \"a\"..=\"z\"\n\n\"a\" is Lower\n//│ = true\n\n\"z\" is Lower\n//│ = true\n\n\"0\" is Lower\n//│ = false\n\npattern Upper = \"A\"..=\"Z\"\n\n\"A\" is Upper\n//│ = true\n\n\"Q\" is Upper\n//│ = true\n\n\"b\" is Upper\n//│ = false\n\npattern UnsignedShort = 0 ..< 65536\n\n0 is UnsignedShort\n//│ = true\n\n-1 is UnsignedShort\n//│ = false\n\n65535 is UnsignedShort\n//│ = true\n\n65536 is UnsignedShort\n//│ = false\n\n2147483647 is UnsignedShort\n//│ = false\n\n\"b\" is UnsignedShort\n//│ = false\n\n[] is UnsignedShort\n//│ = true\n\n:pe\n:e\n// Don't forget to add a space between numbers and the range operator.\npattern UnsignedByte = 0..< 256\n//│ ╔══[LEXICAL ERROR] Expected at least one digit after the  decimal point\n//│ ║  l.51: \tpattern UnsignedByte = 0..< 256\n//│ ╙──      \t                         ^\n//│ ╔══[COMPILATION ERROR] Name not found: .<\n//│ ║  l.51: \tpattern UnsignedByte = 0..< 256\n//│ ╙──      \t                         ^^\n//│ ═══[COMPILATION ERROR] Cannot use this ‹error› as a pattern.\n\n:e\npattern BadRange = \"s\"..=0\n//│ ╔══[COMPILATION ERROR] The upper and lower bounds of range patterns should be literals of the same type.\n//│ ║  l.61: \tpattern BadRange = \"s\"..=0\n//│ ╙──      \t                   ^^^^^^^\n\n// It becomes an absurd pattern.\n0 is BadRange\n//│ = true\n\n:e\npattern BadRange = 0 ..= \"s\"\n//│ ╔══[COMPILATION ERROR] The upper and lower bounds of range patterns should be literals of the same type.\n//│ ║  l.71: \tpattern BadRange = 0 ..= \"s\"\n//│ ╙──      \t                   ^^^^^^^^^\n\n:e\npattern BadRange = \"yolo\" ..= \"swag\"\n//│ ╔══[COMPILATION ERROR] The lower bound of character ranges must be a single character.\n//│ ║  l.77: \tpattern BadRange = \"yolo\" ..= \"swag\"\n//│ ║        \t                   ^^^^^^\n//│ ╟── The upper bound of character ranges must be a single character.\n//│ ║  l.77: \tpattern BadRange = \"yolo\" ..= \"swag\"\n//│ ╙──      \t                              ^^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/RecursiveTransformations.mls",
    "content": ":js\n\n\nimport \"../../mlscript-compile/Stack.mls\"\nopen Stack\n\n\n\npattern Bin =\n  (0 => \"false\") | (1 => \"true\") | ([Bin as b] => b + \"!\")\n\nfun f(x) = if x is\n  Bin as b then b\n  ~Bin as c then [c]\n\nf(0)\n//│ = \"false\"\n\nf(1)\n//│ = \"true\"\n\nf(2)\n//│ = [2]\n\nf([1])\n//│ = \"true!\"\n\nf([[[0]]])\n//│ = \"false!!!\"\n\n\n\nlet arr = fromArray of [1, 2, 3]\n//│ arr = Cons(1, Cons(2, Cons(3, Nil)))\n\n\npattern Find(pattern P) =\n  | ((P as p) :: t) => [p, t]\n  | (h :: (Find(P) as [res, t])) => [res, h :: t]\n\nassert arr is Find(1) as res, res\n//│ = [1, Cons(2, Cons(3, Nil))]\nassert arr is Find(2) as res, res\n//│ = [2, Cons(1, Cons(3, Nil))]\nassert arr is Find(0) as res else \"oops\", res\n//│ = \"oops\"\n\n\n// * List-like pattern that disregards the order of elements! (quite inefficient)\npattern MultiSet(pattern Head, pattern Rest) =\n  | Find(Head) as [h, Rest as t] => h :: t\n\narr is MultiSet(1, _)\n//│ = true\narr is MultiSet(0, _)\n//│ = false\narr is MultiSet(3, _)\n//│ = true\narr is MultiSet(3, MultiSet(1, MultiSet(2, Nil)))\n//│ = true\narr is MultiSet(3, MultiSet(0, _))\n//│ = false\n\n:fixme\nassert arr is MultiSet(1, rest), rest\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'rest'\n//│ ║  l.65: \tassert arr is MultiSet(1, rest), rest\n//│ ╙──      \t                                 ^^^^\n//│ ═══[RUNTIME ERROR] ReferenceError: rest is not defined\n\n:e\nassert arr is MultiSet as res, res\n//│ ═══[COMPILATION ERROR] Expected two pattern arguments, but found only zero pattern arguments.\n//│ ═══[RUNTIME ERROR] Error: Assertion failed (RecursiveTransformations.mls:73)\n\n\npattern Id = _\n\n:fixme\nif [1, 2, 3] is\n  MultiSet(2, MultiSet(1, Id(x))) do print(x)\n//│ ═══[COMPILATION ERROR] No definition found in scope for member 'arg$Id$0$'\n//│ ═══[COMPILATION ERROR] No definition found in scope for member 'arg$Id$0$'\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'x'\n//│ ║  l.81: \t  MultiSet(2, MultiSet(1, Id(x))) do print(x)\n//│ ╙──      \t                                           ^\n\n\n// ———\n\n\n// * Whoopsie: bad definition\n\npattern MultiSet(pattern Head, pattern Rest) =\n  | ((Head as h) :: (Rest as r)) => h :: r\n  | (((h0 :: h :: r) => h :: h0 :: r) as MultiSet(Head, Rest) as res) => res\n\narr is\n  MultiSet(1, _)\n//│ = true\n\n:re\narr is\n  MultiSet(3, _)\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\narr is\n  MultiSet(2, MultiSet(1, _))\n//│ = true\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/SimpleConjunction.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\nopen annotations\n\npattern OverlappedIntervals = (0 ..= 2) & (1 ..= 3)\n\nfun test(n) = n is @compile OverlappedIntervals\n\nprint of \"0:\", test of 0\nprint of \"1:\", test of 1\nprint of \"2:\", test of 2\nprint of \"3:\", test of 3\nprint of \"42:\", test of 42\n//│ > 0: false\n//│ > 1: true\n//│ > 2: true\n//│ > 3: false\n//│ > 42: false\n\nfun show(n) = if n is (@compile OverlappedIntervals) as v then Some(v) else None\n\nprint of \"0:\", show of 0\nprint of \"1:\", show of 1\nprint of \"2:\", show of 2\nprint of \"3:\", show of 3\nprint of \"42:\", show of 42\n//│ > 0: None\n//│ > 1: Some(1)\n//│ > 2: Some(2)\n//│ > 3: None\n//│ > 42: None\n\nfun observeLeft(x) =\n  print(\"left \" + x)\n  x\n\nfun observeRight(x) =\n  print(\"right \" + x)\n  x\n\npattern LoggedOverlappedIntervals =\n  (((0 ..= 2) as x) => observeLeft(x)) &\n  (((1 ..= 3) as y) => observeRight(y))\n\nprint of 1 is @compile LoggedOverlappedIntervals\n//│ > true\n\nif 1 is (@compile LoggedOverlappedIntervals) as value then\n  print(\"logged interval: \" + value)\n//│ > left 1\n//│ > right 1\n//│ > logged interval: 1,1\n\ndata class A(x: Int)\ndata class B(x: Int)\n\npattern BothTransformedConjunction =\n  (((0 ..= 2) as x) => A(x)) &\n  (((1 ..= 3) as y) => B(y))\n\nfun show(n) = if n is (@compile BothTransformedConjunction) as v then Some(v) else None\n\nprint of \"0:\", show of 0\nprint of \"1:\", show of 1\nprint of \"2:\", show of 2\nprint of \"3:\", show of 3\nprint of \"42:\", show of 42\n//│ > 0: None\n//│ > 1: Some([A(1), B(1)])\n//│ > 2: Some([A(2), B(2)])\n//│ > 3: None\n//│ > 42: None\n\npattern RightTransformedConjunction =\n  (0 ..= 2) &\n  (((1 ..= 3) as y) => B(y))\n\nfun show(n) = if n is (@compile RightTransformedConjunction) as v then Some(v) else None\n\nprint of \"0:\", show of 0\nprint of \"1:\", show of 1\nprint of \"2:\", show of 2\nprint of \"3:\", show of 3\nprint of \"42:\", show of 42\n//│ > 0: None\n//│ > 1: Some([1, B(1)])\n//│ > 2: Some([2, B(2)])\n//│ > 3: None\n//│ > 42: None\n\npattern LeftTransformedConjunction =\n  (((0 ..= 2) as x) => A(x)) &\n  (1 ..= 3)\n\nfun show(n) = if n is (@compile LeftTransformedConjunction) as v then Some(v) else None\n\nprint of \"0:\", show of 0\nprint of \"1:\", show of 1\nprint of \"2:\", show of 2\nprint of \"3:\", show of 3\nprint of \"42:\", show of 42\n//│ > 0: None\n//│ > 1: Some([A(1), 1])\n//│ > 2: Some([A(2), 2])\n//│ > 3: None\n//│ > 42: None\n\n// We can statically reduce this pattern to bottom.\npattern ImpossibleIntervals = (0 ..= 2) & (3 ..= 4)\n\n// From the generated code we can see that all cases lead to match failure.\nfun test(n) = n is @compile ImpossibleIntervals\n\n// This pattern is equivalent to bottom but we can't statically reduce it.\npattern UnionRecords = (a: 1, b: 2) & (a: 3, b: 4)\n\nfun test(rcd) = rcd is @compile UnionRecords\n\ntest of (a: 1, b: 2)\n//│ = false\n\ntest of (a: 3, b: 4)\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/SimpleTransform.mls",
    "content": ":js\n\nimport \"../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\nopen annotations\n\ndata class Pair[A, B](first: A, second: B)\n\n:sir\npattern SumPair = Pair(a, b) => a + b\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let SumPair⁰;\n//│ define SumPair⁰ as pattern SumPair¹ {\n//│   method unapply⁰ = fun unapply¹(input) {\n//│     let transform, arg$Pair$0$, arg$Pair$1$, transformResult, lambda;\n//│     define lambda as fun lambda⁰(a, b) {\n//│       return +⁰(a, b)\n//│     };\n//│     set transform = lambda⁰;\n//│     match input\n//│       Pair⁰ =>\n//│         set arg$Pair$0$ = input.first⁰;\n//│         set arg$Pair$1$ = input.second⁰;\n//│         set transformResult = transform(arg$Pair$0$, arg$Pair$1$);\n//│         return new runtime⁰.MatchSuccess⁰(transformResult, null)\n//│       else\n//│         return new runtime⁰.MatchFailure⁰(null)\n//│     end\n//│   }\n//│   method unapplyStringPrefix⁰ = fun unapplyStringPrefix¹(input) {\n//│     return new runtime⁰.MatchFailure⁰(null)\n//│   }\n//│ };\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\nfun foo(value) = if value is\n  SumPair as sum then print(\"sum: \" + sum)\n  else print(\"not a pair\")\n\nfoo of Pair(1, 2)\nfoo of Pair(10, 25)\nfoo of ()\nfoo of 10\nfoo of \"hello\"\n//│ > sum: 3\n//│ > sum: 35\n//│ > not a pair\n//│ > not a pair\n//│ > not a pair\n\npattern BoolLike = true | false | ((Int as x) => x !== 0)\n\nfun get_output_using_as(value) = if value is\n  BoolLike as b then print(\"\" + value + \" is equivalent to \" + b)\n  else print(\"the input \" + value + \" is not a boolean\")\n\nget_output_using_as of true\nget_output_using_as of false\nget_output_using_as of 0\nget_output_using_as of 1\nget_output_using_as of 2\n//│ > true is equivalent to true\n//│ > false is equivalent to false\n//│ > 0 is equivalent to false\n//│ > 1 is equivalent to true\n//│ > 2 is equivalent to true\n\nfun get_output_using_as'(value) = if value is\n  (@compile BoolLike) as b then print(\"\" + value + \" is equivalent to \" + b)\n  else print(\"the input \" + value + \" is not a boolean\")\n\nget_output_using_as' of true\nget_output_using_as' of false\nget_output_using_as' of 0\nget_output_using_as' of 1\nget_output_using_as' of 2\n//│ > true is equivalent to true\n//│ > false is equivalent to false\n//│ > 0 is equivalent to false\n//│ > 1 is equivalent to true\n//│ > 2 is equivalent to true\n\nfun get_output_through_param(value) = if value is\n  BoolLike(b) then print(\"\" + value + \" is equivalent to \" + b)\n  else print(\"the input \" + value + \" is not a boolean\")\n\nget_output_through_param of true\nget_output_through_param of false\nget_output_through_param of 0\nget_output_through_param of 1\nget_output_through_param of 2\n//│ > true is equivalent to true\n//│ > false is equivalent to false\n//│ > 0 is equivalent to false\n//│ > 1 is equivalent to true\n//│ > 2 is equivalent to true\n\npattern TrueLike = BoolLike as true\n\n:expect true\ntrue is TrueLike\n//│ = true\n\n:expect true\n42 is BoolLike\n//│ = true\n\n:expect true\n42 is TrueLike\n//│ = true\n\nfun observeInt(x) =\n  print(\"observe \" + x)\n  x + 1\n\npattern LoggedInt = (Int as x) => observeInt(x)\n\nprint of 42 is @compile LoggedInt\n//│ > true\n\nif 42 is (@compile LoggedInt) as value then\n  print(\"logged value: \" + value)\n//│ > observe 42\n//│ > logged value: 43\n\npattern LoggedIntWithSlot(value) = (Int as value) => observeInt(value)\n\nprint of 42 is @compile LoggedIntWithSlot\n//│ > observe 42\n//│ > true\n\nif 42 is (@compile LoggedIntWithSlot) as value then\n  print(\"logged slot value: \" + value)\n//│ > observe 42\n//│ > logged slot value: 43\n\nclass Term with\n  constructor\n    Literal(val value: Int)\n    Infix(val op: Str, val left: Term, val right: Term)\n    Prefix(val op: Str, val right: Term)\n\n// The following pattern generates a lot of code.\npattern EvaluatedTerm =\n  | Literal(value) => value\n  | Infix(\"+\", EvaluatedTerm as left, EvaluatedTerm as right) => left + right\n  | Infix(\"-\", EvaluatedTerm as left, EvaluatedTerm as right) => left - right\n  | Infix(\"*\", EvaluatedTerm as left, EvaluatedTerm as right) => left * right\n  | Infix(\"/\", EvaluatedTerm as left, EvaluatedTerm as right) => left / right\n  | Prefix(\"-\", EvaluatedTerm as operand) => -operand\n  | Prefix(\"+\", EvaluatedTerm as operand) => +operand\n\n// Some helper functions to create `Term`s.\nfun wrapLiteral(value) = if value is Int then Literal(value) else value\nfun (+:+) add(a, b) = Infix(\"+\", wrapLiteral(a), wrapLiteral(b))\nfun (*:*) mul(a, b) = Infix(\"*\", wrapLiteral(a), wrapLiteral(b))\nfun (-:-) sub(a, b) = Infix(\"-\", wrapLiteral(a), wrapLiteral(b))\nfun (/:/) div(a, b) = Infix(\"/\", wrapLiteral(a), wrapLiteral(b))\n\nLiteral(1) is EvaluatedTerm(1)\n//│ = true\n\n2 *:* 3 +:+ 1 is EvaluatedTerm(7)\n//│ = true\n\n(4 +:+ 5) *:* (6 -:- 2) is EvaluatedTerm(36)\n//│ = true\n\nPrefix(\"-\", 10 +:+ 2 *:* 3) is EvaluatedTerm(-16)\n//│ = true\n\n(8 /:/ 2) +:+ (3 *:* 4) -:- 5 is EvaluatedTerm(11)\n//│ = true\n\nInfix(\"**\", Literal(1), Literal(2)) is EvaluatedTerm\n//│ = false\n\nfun evaluate(term) = if term is\n  (@compile EvaluatedTerm) as v then Some(v)\n  else None\n\nevaluate of Literal(1)\n//│ = Some(1)\n\nevaluate of Literal(1)\n//│ = Some(1)\n\nevaluate of 2 *:* 3 +:+ 1\n//│ = Some(7)\n\nevaluate of (4 +:+ 5) *:* (6 -:- 2)\n//│ = Some(36)\n\nevaluate of Prefix(\"-\", 10 +:+ 2 *:* 3)\n//│ = Some(-16)\n\nevaluate of (8 /:/ 2) +:+ (3 *:* 4) -:- 5\n//│ = Some(11)\n\nevaluate of Infix(\"**\", Literal(1), Literal(2))\n//│ = None\n\npattern DropZ = ((:x, :y, :z)) => (x: x, y: y)\n\n(x: 1, y: 2, z: 3) is DropZ((x: 1, y: 2))\n//│ = true\n\n(x: 1, y: 2, z: 3) is DropZ((x: 1, y: 3))\n//│ = false\n\npattern ShapeArea = \n  (((:radius)) => Math.PI * radius * radius) |  // Circle\n  (((:width, :height)) => width * height) |     // Rectangle\n  (((:base, :height)) => base * height / 2)     // Triangle\n\nfun area(shape) = if shape is\n  ShapeArea(area) then print(\"area: \" + area)\n  else print(\"invalid shape\")\n\narea of radius: 10\narea of width: 10, height: 20\narea of base: 10, height: 20\n//│ > area: 314.1592653589793\n//│ > area: 200\n//│ > area: 100\n\npattern PairLike = [_, _] | Pair(_, _)\n\n[1, 2] is PairLike\n//│ = true\n\n[] is PairLike\n//│ = false\n\n[1] is PairLike\n//│ = false\n\nPair(1, 2) is PairLike\n//│ = true\n\npattern TransformTwice = (((Int as x) => x + 4) as y) => y * 2\n\n2 is TransformTwice(12)\n//│ = true\n\n100 is TransformTwice(0)\n//│ = false\n\n17 is TransformTwice(42)\n//│ = true\n\nfun testTransformTwice(x) =\n  if x is (@compile TransformTwice) as v then Some(v) else None\n\ntestTransformTwice of 100\n//│ = Some(208)\n\ntestTransformTwice of 2\n//│ = Some(12)\n\ntestTransformTwice of 17\n//│ = Some(42)\n\n// We can easily define predicative patterns using `as true`.\npattern Positive = ((Int as x) => x > 0) as true\n\nprint of -100 is Positive\nprint of 0 is Positive\nprint of 8080 is Positive\n//│ > false\n//│ > false\n//│ > true\n\n// Hmm, but how to make the pattern return the input value?\nPositive.unapply(100)\n//│ = MatchSuccess(true, null)\n\n// Just use conjunction patterns.\npattern Positive = (x & (((Int as x) => x > 0) as true)) => x\n\nPositive.unapply(100)\n//│ = MatchSuccess(100, null)\n\n//  ____  _        _\n// / ___|| |_ _ __(_)_ __   __ _\n// \\___ \\| __| '__| | '_ \\ / _` |\n//  ___) | |_| |  | | | | | (_| |\n// |____/ \\__|_|  |_|_| |_|\\__, |\n//                         |___/\n// ==============================\n\npattern HelloWorld =\n  ((\"hello\" as a) ~ \" \" ~ (\"world\" as b)) =>\n    \"the user said \" + a + \" to the \" + b\n\n\"hello world\" is HelloWorld\n//│ = true\n\nif \"hello world\" is HelloWorld as x then x\n//│ = \"the user said hello to the world\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/TransformFree.mls",
    "content": ":js\n\nopen annotations\n\ndata class Pair[A, B](first: A, second: B)\npattern NumPair = Pair(Num, Num)\npattern SumPair = Pair((Num as x), (Num as y)) => x + y\n\n// TLDR: This file tests the case where a compiled pattern's result is bound\n// with `as`, but the pattern itself does not involve any transformations.\n//\n// `toNumPair` should still compile without creating `MatchSuccess` or\n// `MatchFailure`: all matchers should return Boolean values, and the use site\n// should set the output binding `s` to the original scrutinee `t`.\n//\n// `toSumPair` is the counterexample: because it has a transform and the use\n// site binds the pattern's output, it still creates `MatchSuccess` and\n// `MatchFailure`.\n\n// :sir\nfun toNumPair(t) = if t is (@compile NumPair) as s then s else null\n\n\n// :sir\nfun toSumPair(t) = if t is (@compile SumPair) as s then s else null\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/UpsBugsBacklog.mls",
    "content": ":js\n\nopen annotations\n\n\n// ——— ——— ———\n\nimport \"../../mlscript-compile/Char.mls\"\n\npattern Input =\n  ((Char.Whitespace ~ (Input as inp)) => inp) | ((c ~ (Input as inp)) => [c, ..inp]) | (\"\" => [])\n\n:fixme\nif \"a b c\" is Input as chars then chars\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n// ——— ——— ———\n\npattern Bin =\n  [(1 => true) | (_ => false)]\n\nfun f(x) = if x is Bin as res then res\n\n:todo\n:expect [false]\nf([0])\n//│ ═══[RUNTIME ERROR] Expected: '[false]', got: '[0]'\n//│ = [0]\n\n:todo\n:expect [true]\nf([1])\n//│ ═══[RUNTIME ERROR] Expected: '[true]', got: '[1]'\n//│ = [1]\n\n// ——— ——— ———\n\npattern Parse = 0\n\nlet tokens\n//│ tokens = undefined\n\n// Works:\nif tokens is @compile Parse as stack do print(stack)\n\n:fixme // Should be a \"name not found\"\nif tokens is\n  @compile Parse as stack do print(stack)\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'stack'\n//│ ║  l.48: \t  @compile Parse as stack do print(stack)\n//│ ╙──      \t                                   ^^^^^\n\n// What's actually intended:\nif tokens is\n  (@compile Parse) as stack do print(stack)\n\n// ——— ——— ———\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/BadRecStackParse.mls",
    "content": ":js\n\n\nimport \"../../../mlscript-compile/Stack.mls\"\nopen Stack\n\n\n// * Just a note that it does *not* work to try and do everything recursively;\n// * the parser needs an opportunity to zoom out and make progress elsewhere.\n\n\npattern Ident = (\"a\" ..= \"z\") ~ (Ident | \"\")\n\ndata class Expr with\n  constructor\n    Id(name: Str)\n    Op(lhs: Expr, op: Str, rhs: Expr)\n\n\nfun go(stack) =\n  // print(stack)\n  if stack is...\n  ((Ident as name) :: rest)\n    then go of Id(name) :: rest\n  ((Expr as e1) :: \"+\" :: (Expr as e2) :: rest)\n    then go of Op(e1, \"+\", e2) :: rest\n  ((Expr as e1) :: \"+\" :: rest)\n    then go of e1 :: \"+\" :: go of rest\n  (\"(\" :: (Expr as e) :: \")\" :: rest) then\n    go of e :: rest\n  (\"(\" :: rest) then\n    go of \"(\" :: go of rest\n  _ then\n    stack\n\nfun parse(tokens) =\n  if go(tokens) is\n    (Expr as res) :: Nil then\n      Success: res\n    toks then\n      Failure: toks\n\n\nparse(Nil)\n//│ = {Failure: Nil}\n\nparse(\"x\" :: Nil)\n//│ = {Success: Id(\"x\")}\n\nparse(\"x\" :: \"+\" :: \"y\" :: Nil)\n//│ = {Success: Op(Id(\"x\"), \"+\", Id(\"y\"))}\n\nparse(\"(\" :: \"x\" :: \")\" :: Nil)\n//│ = {Success: Id(\"x\")}\n\nparse(\"a\" :: \"+\" :: \"(\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: Nil)\n//│ = {Success: Op(Id(\"a\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\")))}\n\n// * Notice: wrong assoc.\nparse(\"a\" :: \"+\" :: \"(\" :: \"b\" :: \"+\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: Nil)\n//│ = {Success: Op(Id(\"a\"), \"+\", Op(Id(\"b\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\"))))}\n// * It parses the same as:\nparse(\"a\" :: \"+\" :: \"(\" :: \"b\" :: \"+\" :: \"(\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: \")\" :: Nil)\n//│ = {Success: Op(Id(\"a\"), \"+\", Op(Id(\"b\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\"))))}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/BasicSeqStackParse.mls",
    "content": ":js\n\n\n// * There are currently bugs in tuple matching,\n// * preventing most of these definitions from working.\n// * See also: `ups/UpsBugsBacklog.mls`\n\n\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/Char.mls\"\nopen Iter\n\n\n\npattern Ident = (\"a\" ..= \"z\") ~ (Ident | \"\")\n\ndata class Expr with\n  constructor\n    Id(name: Str)\n    Op(lhs: Expr, op: Str, rhs: Expr)\n\n\nfun go(stack, input) = if stack is\n  [..rest, Expr as e1, \"+\", Expr as e2] then\n    go([..rest, Op(e1, \"+\", e2)], input)\n  [..rest, Ident as id] then\n    go([..rest, Id(id)], input)\n  do print(\"not Ident\", stack)\n  do print(\"not Ident??\", stack is [..stack, Ident as id])\n  do print(\"Str?\", stack.at(-1), stack.at(-1) is Str)\n  do print(\"Str??\", stack is [..stack, Str as id])\n  [Expr as res] and input is [] then\n    Success: res\n  _ and input is\n    [tok, ..input] then\n      go([..stack, tok], input)\n    [] then\n      Error: stack\n\nlet Space = new RegExp of \"(\\\\s+)\"\nfun parse(input) =\n  let input = input.split(Space)\n    \\filtering of (_ !== \"\")\n    \\filtering of (_ \\every of (_ !== \" \"))\n    \\toArray()\n  go([], input)\n//│ Space = /(\\s+)/\n\n\n// FIXME: the results below seem to indicate miscompilation:\n\n\nparse(\"\")\n//│ > not Ident []\n//│ > not Ident?? false\n//│ > Str? () false\n//│ > Str?? false\n//│ = {Error: []}\n\nparse(\"x\")\n//│ > not Ident []\n//│ > not Ident?? false\n//│ > Str? () false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"x\") false\n//│ > Str?? false\n//│ = {Success: Id(\"x\")}\n\nparse(\"x y\")\n//│ > not Ident []\n//│ > not Ident?? false\n//│ > Str? () false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"x\") false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\"), Id(\"y\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"y\") false\n//│ > Str?? false\n//│ = {Error: [Id(\"x\"), Id(\"y\")]}\n\nparse(\"x y z\")\n//│ > not Ident []\n//│ > not Ident?? false\n//│ > Str? () false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"x\") false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\"), Id(\"y\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"y\") false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\"), Id(\"y\"), Id(\"z\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"z\") false\n//│ > Str?? false\n//│ = {Error: [Id(\"x\"), Id(\"y\"), Id(\"z\")]}\n\ngo([], [\"x\", \"y\", \"z\"])\n//│ > not Ident []\n//│ > not Ident?? false\n//│ > Str? () false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"x\") false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\"), Id(\"y\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"y\") false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\"), Id(\"y\"), Id(\"z\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"z\") false\n//│ > Str?? false\n//│ = {Error: [Id(\"x\"), Id(\"y\"), Id(\"z\")]}\n\ngo([Id(\"x\"), Id(\"y\"), \"z\"], [])\n//│ > not Ident [Id(\"x\"), Id(\"y\"), Id(\"z\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"z\") false\n//│ > Str?? false\n//│ = {Error: [Id(\"x\"), Id(\"y\"), Id(\"z\")]}\n\nparse(\"x + y\")\n//│ > not Ident []\n//│ > not Ident?? false\n//│ > Str? () false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\")]\n//│ > not Ident?? false\n//│ > Str? Id(\"x\") false\n//│ > Str?? false\n//│ > not Ident [Id(\"x\"), +]\n//│ > not Ident?? false\n//│ > Str? + true\n//│ > Str?? true\n//│ > not Ident [Op(Id(\"y\"), \"+\", Id(\"x\"))]\n//│ > not Ident?? false\n//│ > Str? Op(Id(\"y\"), \"+\", Id(\"x\")) false\n//│ > Str?? false\n//│ = {Success: Op(Id(\"y\"), \"+\", Id(\"x\"))}\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/BasicStackParse.mls",
    "content": ":js\n\n\nimport \"../../../mlscript-compile/Stack.mls\"\nopen Stack\n\n\n\npattern Ident = (\"a\" ..= \"z\") ~ (Ident | \"\")\n\ndata class Expr with\n  constructor\n    Id(name: Str)\n    Op(lhs: Expr, op: Str, rhs: Expr)\n\n\npattern Parse =\n  | ((Ident as name) :: rest)                     => Id(name) :: rest\n  | ((Expr as e1) :: \"+\" :: (Expr as e2) :: rest) => Op(e1, \"+\", e2) :: rest\n  | ((Expr as e1) :: \"+\" :: (Parse as rest))      => e1 :: \"+\" :: rest\n  | (\"(\" :: (Expr as e) :: \")\" :: rest)           => e :: rest\n  | (\"(\" :: (Parse as rest))                      => \"(\" :: rest\n\nfun parse(tokens) =\n  while tokens is\n    Parse as stack do\n      set tokens = stack\n  print of ...\n    if tokens is\n      (Expr as e) :: Nil then [\"Success:\", e]\n      toks then [\"Failure: can't parse:\", toks]\n\n\nparse(Nil)\n//│ > Failure: can't parse: Nil\n\nparse(\"x\" :: Nil)\n//│ > Success: Id(\"x\")\n\nlet input = \"x\" :: \"+\" :: \"y\" :: Nil\n//│ input = Cons(\"x\", Cons(\"+\", Cons(\"y\", Nil)))\n\nparse(input)\n//│ > Success: Op(Id(\"x\"), \"+\", Id(\"y\"))\n\nif input is Parse as rest then rest\n//│ = Cons(Id(\"x\"), Cons(\"+\", Cons(\"y\", Nil)))\n\nparse(\"(\" :: \"x\" :: \")\" :: Nil)\n//│ > Success: Id(\"x\")\n\nparse(\"a\" :: \"+\" :: \"(\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: Nil)\n//│ > Success: Op(Id(\"a\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\")))\n\nparse(\"a\" :: \"+\" :: \"(\" :: \"b\" :: \"+\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: Nil)\n//│ > Success: Op(Id(\"a\"), \"+\", Op(Op(Id(\"b\"), \"+\", Id(\"x\")), \"+\", Id(\"y\")))\n\nparse(\"a\" :: \"+\" :: \"(\" :: \"b\" :: \"+\" :: \"(\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: \")\" :: Nil)\n//│ > Success: Op(Id(\"a\"), \"+\", Op(Id(\"b\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\"))))\n\n\n// ———\n\n\n// TODO improve: confusing errors for wrong code\n:e\npattern Parse =\n  (\n    ((Str as name) :: rest) => Id(name) :: rest\n    ((Expr as e) :: \"+\" :: (Expr as e) :: rest) => Op(e, \"+\", e) :: rest\n  )\n//│ ╔══[COMPILATION ERROR] Unexpected record property pattern.\n//│ ║  l.69: \t    ((Str as name) :: rest) => Id(name) :: rest\n//│ ╙──      \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Unexpected record property pattern.\n//│ ║  l.70: \t    ((Expr as e) :: \"+\" :: (Expr as e) :: rest) => Op(e, \"+\", e) :: rest\n//│ ╙──      \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/Computation.mls",
    "content": ":js\n\nopen annotations\n\ndata class Celsius(value: Num)\n\ndata class Fahrenheit(value: Num)\n\npattern ToFahrenheit =\n  | (Celsius(c)) => Fahrenheit((c * 9 / 5) + 32)\n  | (Fahrenheit as f) => f\n\npattern ToCelsius =\n  | (Fahrenheit(f)) => Celsius((f - 32) * 5 / 9)\n  | (Celsius as c) => c\n\nCelsius(0) is ToFahrenheit(Fahrenheit(32))\n//│ = true\n\nFahrenheit(212) is ToCelsius(Celsius(100))\n//│ = true\n\nCelsius(100) is ToFahrenheit(Fahrenheit(212))\n//│ = true\n\nFahrenheit(32) is ToCelsius(Celsius(0))\n//│ = true\n\nCelsius(-40) is ToFahrenheit(Fahrenheit(-40))\n//│ = true\n\nFahrenheit(-40) is ToCelsius(Celsius(-40))\n//│ = true\n\nfun toFahrenheit(c) =\n  if c is (@compile ToFahrenheit) as output then output else \"What's this?\"\n\ntoFahrenheit of Celsius(100)\n//│ = Fahrenheit(212)\n\ntoFahrenheit of Fahrenheit(100)\n//│ = Fahrenheit(100)\n\ntoFahrenheit of Celsius(-40)\n//│ = Fahrenheit(-40)\n\ntoFahrenheit of \"Cheers!\"\n//│ = \"What's this?\"\n\nfun toCelsius(f) =\n  if f is (@compile ToCelsius) as output then output else \"What's this?\"\n\ntoCelsius of Fahrenheit(100)\n//│ = Celsius(37.77777777777778)\n\ntoCelsius of Celsius(100)\n//│ = Celsius(100)\n\ntoCelsius of \"Cheers!\"\n//│ = \"What's this?\"\n\npattern HourAM = (0 => 12) | (1 ..= 11)\npattern HourPM = 12 | (((13 ..= 23) as hour) => hour - 12)\npattern Minute = ((0 ..= 59) as minute) => minute.toString().padStart(2, \"0\")\n\n// Convert 24-hour time format to 12-hour format with AM/PM\npattern Time12Hour = ((\n  hour: ((HourAM | HourPM) as hour) & (((HourAM => \"AM\") | (HourPM => \"PM\")) as flag),\n  minute: Minute as minute\n)) => hour + \":\" + minute + \" \" + flag\n\nfun formatTime(ps) = if ps is Time12Hour as time then time\n\nprint of \"I had my breakfast at\", formatTime of hour: 7, minute: 45\nprint of \"Let's have lunch at\", formatTime of hour: 12, minute: 30\nprint of \"I plan to have dinner at\", formatTime of hour: 18, minute: 45\nprint of \"I should go to bed before\", formatTime of hour: 23, minute: 0\n//│ > I had my breakfast at 7:45 AM\n//│ > Let's have lunch at 12:30 PM\n//│ > I plan to have dinner at 6:45 PM\n//│ > I should go to bed before 11:00 PM\n\n// This makes use of the chain pattern. It generates 29,232 lines of code!\npattern Time12Hour = ((\n  hour: ((\n    | (0 ..= 11) => \"AM\"\n    | (12 ..= 23) => \"PM\"\n  ) & (\n    | 0 => 12\n    | 1 ..= 11\n    | 12\n    | ((13 ..= 23) as h) => (h - 12)\n  )) as [hour, flag],\n  minute: Minute as minute\n)) => hour + \":\" + minute + \" \" + flag\n\nfun formatTime(ps) = if ps is Time12Hour as time then time\n\nprint of \"I had my breakfast at\", formatTime of hour: 7, minute: 45\nprint of \"Let's have lunch at\", formatTime of hour: 12, minute: 30\nprint of \"I plan to have dinner at\", formatTime of hour: 18, minute: 45\nprint of \"I should go to bed before\", formatTime of hour: 23, minute: 0\n//│ > I had my breakfast at AM:45 7\n//│ > Let's have lunch at PM:30 12\n//│ > I plan to have dinner at PM:45 6\n//│ > I should go to bed before PM:00 11\n\npattern Channel = 0 ..= 255\n\n// Convert a color in RGB format to grayscale\npattern Grayscale =\n  ((r: Channel as r, g: Channel as g, b: Channel as b)) =>\n    Math.round(r * 0.299 + g * 0.587 + b * 0.114)\n\nfun grayscale(rgb) = if rgb is Grayscale as g then g else -1\n\ngrayscale of r: 0, g: 0, b: 0\n//│ = 0\n\ngrayscale of r: 1, g: 1, b: 1\n//│ = 1\n\ngrayscale of r: 255, g: 255, b: 255\n//│ = 255\n\ngrayscale of r: 256, g: 255, b: 255\n//│ = -1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/DnfCnf.mls",
    "content": ":js\n\nopen annotations\n\nclass Formula with\n  constructor\n    Var(val name: Str)\n    Pred(val name: Str, val arg: Formula)\n    And(val left: Formula, val right: Formula)\n    Or(val left: Formula, val right: Formula)\n\npattern Dnf = Or(Dnf, Dnf) | Atoms\npattern Atoms = And(Atoms, Atoms) | Atom\npattern Atom = Pred | Var\n\nfun isDnf(x) = x is @compile Dnf\n\nlet f1 = Var(\"x\")\nlet f2 = Pred(\"P\", Var(\"y\"))\n//│ f1 = Var(\"x\")\n//│ f2 = Pred(\"P\", Var(\"y\"))\n\nf1 is Dnf\n//│ = true\n\nisDnf of f1\n//│ = true\n\nf2 is Dnf\n//│ = true\n\nisDnf of f2\n//│ = true\n\nlet f3 = And(f1, f2)\n//│ f3 = And(Var(\"x\"), Pred(\"P\", Var(\"y\")))\n\nf3 is Dnf\n//│ = true\n\nisDnf of f3\n//│ = true\n\nlet f4 = Or(f3, Pred(\"Q\", Var(\"z\")))\n//│ f4 = Or(And(Var(\"x\"), Pred(\"P\", Var(\"y\"))), Pred(\"Q\", Var(\"z\")))\n\nf4 is Dnf\n//│ = true\n\nisDnf of f4\n//│ = true\n\nlet f5 = Or(And(Pred(\"A\", Var(\"a\")), Pred(\"B\", Var(\"b\"))), Pred(\"C\", Var(\"c\")))\n//│ f5 = Or(And(Pred(\"A\", Var(\"a\")), Pred(\"B\", Var(\"b\"))), Pred(\"C\", Var(\"c\")))\n\nf5 is Dnf\n//│ = true\n\nisDnf of f5\n//│ = true\n\nlet cnf1 = And(Or(Var(\"x\"), Var(\"y\")), Pred(\"P\", Var(\"z\")))\n//│ cnf1 = And(Or(Var(\"x\"), Var(\"y\")), Pred(\"P\", Var(\"z\")))\n\nlet cnf2 = And(Or(Var(\"a\"), Var(\"b\")), Or(Pred(\"P\", Var(\"c\")), Var(\"d\")))\n//│ cnf2 = And(Or(Var(\"a\"), Var(\"b\")), Or(Pred(\"P\", Var(\"c\")), Var(\"d\")))\n\nlet cnf3 = And(And(Or(Var(\"x\"), Pred(\"Q\", Var(\"y\"))), Or(Var(\"z\"), Var(\"w\"))), Or(Pred(\"R\", Var(\"u\")), Var(\"v\")))\n//│ cnf3 = And(\n//│   And(Or(Var(\"x\"), Pred(\"Q\", Var(\"y\"))), Or(Var(\"z\"), Var(\"w\"))),\n//│   Or(Pred(\"R\", Var(\"u\")), Var(\"v\"))\n//│ )\n\nlet cnf4 = And(Or(And(Var(\"m\"), Var(\"n\")), Var(\"o\")), Or(Pred(\"S\", Var(\"p\")), And(Var(\"q\"), Var(\"r\"))))\n//│ cnf4 = And(\n//│   Or(And(Var(\"m\"), Var(\"n\")), Var(\"o\")),\n//│   Or(Pred(\"S\", Var(\"p\")), And(Var(\"q\"), Var(\"r\")))\n//│ )\n\nlet cnf5 = And(Or(Var(\"a\"), Or(Var(\"b\"), Var(\"c\"))), And(Or(Pred(\"T\", Var(\"d\")), Var(\"e\")), Or(Var(\"f\"), Var(\"g\"))))\n//│ cnf5 = And(\n//│   Or(Var(\"a\"), Or(Var(\"b\"), Var(\"c\"))),\n//│   And(Or(Pred(\"T\", Var(\"d\")), Var(\"e\")), Or(Var(\"f\"), Var(\"g\")))\n//│ )\n\nlet cnf6 = And(Or(Var(\"x\"), And(Var(\"y\"), Or(Var(\"z\"), Var(\"w\")))), Or(Pred(\"U\", Var(\"t\")), Var(\"s\")))\n//│ cnf6 = And(\n//│   Or(Var(\"x\"), And(Var(\"y\"), Or(Var(\"z\"), Var(\"w\")))),\n//│   Or(Pred(\"U\", Var(\"t\")), Var(\"s\"))\n//│ )\n\nprint of cnf1 is Dnf\nprint of cnf2 is Dnf\nprint of cnf3 is Dnf\nprint of cnf4 is Dnf\nprint of cnf5 is Dnf\nprint of cnf6 is Dnf\n//│ > false\n//│ > false\n//│ > false\n//│ > false\n//│ > false\n//│ > false\n\npattern Dnf'(pattern P) = Or(Dnf'(P), Dnf'(P)) | Atoms'(P)\npattern Atoms'(pattern P) = And(Atoms'(P), Atoms'(P)) | Atom'(P)\npattern Atom'(pattern P) = Pred(_, P) | Var\n\npattern DeepDnf = Dnf'(DeepDnf)\n\nfun isDeepDnf(f) = f is @compile DeepDnf\n\nprint of isDeepDnf of f1\nprint of isDeepDnf of f2\nprint of isDeepDnf of f3\nprint of isDeepDnf of f4\nprint of isDeepDnf of f5\n//│ > true\n//│ > true\n//│ > true\n//│ > true\n//│ > true\n\nprint of isDeepDnf of cnf1\nprint of isDeepDnf of cnf2\nprint of isDeepDnf of cnf3\nprint of isDeepDnf of cnf4\nprint of isDeepDnf of cnf5\nprint of isDeepDnf of cnf6\n//│ > false\n//│ > false\n//│ > false\n//│ > false\n//│ > false\n//│ > false\n\npattern Cnf'(pattern P) = And(Cnf'(P), Cnf'(P))\npattern DnfOrCnf = Dnf'(DnfOrCnf) | Cnf'(DnfOrCnf)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/DoubleOrSum.mls",
    "content": ":js\n\nopen annotations\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Stack\nopen Option { Some, None }\n\nfun list(...elements) = elements Iter.toStack()\n\n// This is a helper function to print the addition of two numbers.\nfun (++) addWithPrint(x, y) =\n  let result = x + y\n  print of \"\" + x + \" + \" + y + \" = \" + result\n  result\n\npattern DoubleList = Nil | (Int :: Int :: DoubleList)\n\npattern SumList = (Nil => 0) | (((Int as hd) :: (SumList as tl)) => hd ++ tl)\n\nNil is SumList(0)\n//│ = true\n\nlet _1234 = list(1, 2, 3, 4)\nlet _1234567 = list(1, 2, 3, 4, 5, 6, 7)\n//│ _1234 = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))\n//│ _1234567 = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Cons(7, Nil)))))))\n\n_1234 is SumList(10)\n//│ > 4 + 0 = 4\n//│ > 3 + 4 = 7\n//│ > 2 + 7 = 9\n//│ > 1 + 9 = 10\n//│ = true\n\n_1234567 is SumList(28)\n//│ > 7 + 0 = 7\n//│ > 6 + 7 = 13\n//│ > 5 + 13 = 18\n//│ > 4 + 18 = 22\n//│ > 3 + 22 = 25\n//│ > 2 + 25 = 27\n//│ > 1 + 27 = 28\n//│ = true\n\n_1234567 is SumList(42)\n//│ > 7 + 0 = 7\n//│ > 6 + 7 = 13\n//│ > 5 + 13 = 18\n//│ > 4 + 18 = 22\n//│ > 3 + 22 = 25\n//│ > 2 + 25 = 27\n//│ > 1 + 27 = 28\n//│ = false\n\n_1234 is DoubleList\n//│ = true\n\n_1234567 is DoubleList\n//│ = false\n\nfun sum(xs) = if xs is SumList as output then Some(output) else None\n\nsum of _1234\n//│ > 4 + 0 = 4\n//│ > 3 + 4 = 7\n//│ > 2 + 7 = 9\n//│ > 1 + 9 = 10\n//│ = Some(10)\n\nsum of _1234567\n//│ > 7 + 0 = 7\n//│ > 6 + 7 = 13\n//│ > 5 + 13 = 18\n//│ > 4 + 18 = 22\n//│ > 3 + 22 = 25\n//│ > 2 + 25 = 27\n//│ > 1 + 27 = 28\n//│ = Some(28)\n\nsum of Nil\n//│ = Some(0)\n\n// Try to make a disjunction of two patterns.\n\npattern SumOrDouble = SumList | DoubleList\n\nfun isSumOrDouble__naive(xs) = if xs is SumOrDouble as output then output else \"noop\"\n\nisSumOrDouble__naive of _1234\n//│ > 4 + 0 = 4\n//│ > 3 + 4 = 7\n//│ > 2 + 7 = 9\n//│ > 1 + 9 = 10\n//│ = 10\n\nisSumOrDouble__naive of _1234567\n//│ > 7 + 0 = 7\n//│ > 6 + 7 = 13\n//│ > 5 + 13 = 18\n//│ > 4 + 18 = 22\n//│ > 3 + 22 = 25\n//│ > 2 + 25 = 27\n//│ > 1 + 27 = 28\n//│ = 28\n\nisSumOrDouble__naive of Nil\n//│ = 0\n\nfun isSumOrDouble__compiled(xs) = if xs is (@compile SumOrDouble) as output then output else \"noop\"\n\nisSumOrDouble__compiled of _1234\n//│ > 4 + 0 = 4\n//│ > 3 + 4 = 7\n//│ > 2 + 7 = 9\n//│ > 1 + 9 = 10\n//│ = 10\n\nisSumOrDouble__compiled of _1234567\n//│ > 7 + 0 = 7\n//│ > 6 + 7 = 13\n//│ > 5 + 13 = 18\n//│ > 4 + 18 = 22\n//│ > 3 + 22 = 25\n//│ > 2 + 25 = 27\n//│ > 1 + 27 = 28\n//│ = 28\n\nisSumOrDouble__compiled of Nil\n//│ = 0\n\n// Swap the order of two patterns.\n\npattern DoubleOrSum = DoubleList | SumList\n\nfun isDoubleOrSum__naive(xs) = if xs is DoubleOrSum as output then output else \"noop\"\n\nisDoubleOrSum__naive of _1234\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))\n\nisDoubleOrSum__naive of list(1, 2, 3)\n//│ > 3 + 0 = 3\n//│ > 2 + 3 = 5\n//│ > 1 + 5 = 6\n//│ = 6\n\nfun isDoubleOrSum__compiled(xs) = if xs is (@compile DoubleOrSum) as output then output else \"noop\"\n\nisDoubleOrSum__compiled of _1234\n//│ > 4 + 0 = 4\n//│ > 3 + 4 = 7\n//│ > 2 + 7 = 9\n//│ = Cons(1, Cons(2, Cons(3, Cons(4, Nil))))\n\nisDoubleOrSum__compiled of _1234567\n//│ > 7 + 0 = 7\n//│ > 6 + 7 = 13\n//│ > 5 + 13 = 18\n//│ > 4 + 18 = 22\n//│ > 3 + 22 = 25\n//│ > 2 + 25 = 27\n//│ > 1 + 27 = 28\n//│ = 28\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/DoubleTripleList.mls",
    "content": ":js\n\nopen annotations\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\n\nopen Stack\n\nfun list(...elements) = elements Iter.toStack()\n\n// The example of lists whose length is a multiple of two.\n\n// Note that the parentheses are necessary.\npattern DoubleList = Nil | (Int :: Int :: DoubleList)\n\nlist(1, 2, 3, 4) is DoubleList\n//│ = true\n\nlist(1, 2, 3) is DoubleList\n//│ = false\n\nNil is DoubleList\n//│ = true\n\nfun isDoubleList(xs) = xs is @compile DoubleList\n\nisDoubleList of list(1, 2, 3, 4)\n//│ = true\n\nisDoubleList of list(1, 2, 3)\n//│ = false\n\nisDoubleList of Nil\n//│ = true\n\n// The example of lists whose length is a multiple of three.\n\n// Note that the parentheses are necessary.\npattern TripleList = Nil | (Int :: Int :: Int :: TripleList)\n\nlist(1, 2, 3, 4, 5, 6) is TripleList\n//│ = true\n\nlist(1, 2, 3) is TripleList\n//│ = true\n\nlist(1, 2, 3, 4) is TripleList\n//│ = false\n\nNil is TripleList\n//│ = true\n\nfun isTripleList(xs) = xs is @compile TripleList\n\nisTripleList of list(1, 2, 3, 4, 5, 6)\n//│ = true\n\nisTripleList of list(1, 2, 3)\n//│ = true\n\nisTripleList of list(1, 2, 3, 4)\n//│ = false\n\nisTripleList of Nil\n//│ = true\n\npattern DoubleTripleList = DoubleList | TripleList\n\n// Make a `Cons` object and print a message whenever the `head` or `tail`\n// property is accessed.\nlet doLog = false\nfun (::) makeObservableCons(x, xs) =\n  let cons = new mut Cons(x, xs)\n  let repr = \"[\" + (cons Iter.fromStack() Iter.joined of \", \") + \"]\"\n  Object.defineProperty of\n    cons\n    \"head\"\n    enumerable: true\n    configurable: false\n    get: () =>\n      if doLog do print(\"access the `head` of \" + repr)\n      x\n  Object.defineProperty of\n    cons\n    \"tail\"\n    enumerable: true\n    configurable: false\n    get: () =>\n      if doLog do print(\"access the `tail` of \" + repr)\n      xs\n  cons\n//│ doLog = false\n\nfun withLog(f) =\n  set doLog = true\n  val result = f()\n  set doLog = false\n  result\n\nlet testList = 1 :: 2 :: Nil\n//│ testList = Cons(1, Cons(2, Nil))\n\nwithLog of () =>\n  testList.head\n  testList.tail\n  ()\n//│ > access the `head` of [1, 2]\n//│ > access the `tail` of [1, 2]\n\nfun list(...elements) = elements Iter.rightFolded of Nil, (::)\n\nfun isDoubleTripleList__compiled(xs) = withLog of\n  () => xs is @compile DoubleTripleList\n\nisDoubleTripleList__compiled of list(1, 2, 3)\n//│ > access the `head` of [1, 2, 3]\n//│ > access the `tail` of [1, 2, 3]\n//│ > access the `head` of [2, 3]\n//│ > access the `tail` of [2, 3]\n//│ > access the `head` of [3]\n//│ > access the `tail` of [3]\n//│ = true\n\nisDoubleTripleList__compiled of list(1, 2, 3, 4)\n//│ > access the `head` of [1, 2, 3, 4]\n//│ > access the `tail` of [1, 2, 3, 4]\n//│ > access the `head` of [2, 3, 4]\n//│ > access the `tail` of [2, 3, 4]\n//│ > access the `head` of [3, 4]\n//│ > access the `tail` of [3, 4]\n//│ > access the `head` of [4]\n//│ > access the `tail` of [4]\n//│ = true\n\nisDoubleTripleList__compiled of list(1, 2, 3, 4, 5)\n//│ > access the `head` of [1, 2, 3, 4, 5]\n//│ > access the `tail` of [1, 2, 3, 4, 5]\n//│ > access the `head` of [2, 3, 4, 5]\n//│ > access the `tail` of [2, 3, 4, 5]\n//│ > access the `head` of [3, 4, 5]\n//│ > access the `tail` of [3, 4, 5]\n//│ > access the `head` of [4, 5]\n//│ > access the `tail` of [4, 5]\n//│ > access the `head` of [5]\n//│ > access the `tail` of [5]\n//│ = false\n\nisDoubleTripleList__compiled of list(1, 2, 3, 4, 5, 6, 7, 8, 9)\n//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [5, 6, 7, 8, 9]\n//│ > access the `tail` of [5, 6, 7, 8, 9]\n//│ > access the `head` of [6, 7, 8, 9]\n//│ > access the `tail` of [6, 7, 8, 9]\n//│ > access the `head` of [7, 8, 9]\n//│ > access the `tail` of [7, 8, 9]\n//│ > access the `head` of [8, 9]\n//│ > access the `tail` of [8, 9]\n//│ > access the `head` of [9]\n//│ > access the `tail` of [9]\n//│ = true\n\nisDoubleTripleList__compiled of Nil\n//│ = true\n\nfun isDoubleTripleList__naive(xs) =\n  set doLog = true\n  let result = xs is DoubleTripleList\n  set doLog = false\n  result\n\n// It does not backtracking because the `DoubleList` is tested first.\nisDoubleTripleList__naive of list(1, 2, 3, 4)\n//│ > access the `head` of [1, 2, 3, 4]\n//│ > access the `tail` of [1, 2, 3, 4]\n//│ > access the `head` of [2, 3, 4]\n//│ > access the `tail` of [2, 3, 4]\n//│ > access the `head` of [3, 4]\n//│ > access the `tail` of [3, 4]\n//│ > access the `head` of [4]\n//│ > access the `tail` of [4]\n//│ = true\n\n// It does backtracking when `DoubleList` does not match.\nisDoubleTripleList__naive of list(1, 2, 3)\n//│ > access the `head` of [1, 2, 3]\n//│ > access the `tail` of [1, 2, 3]\n//│ > access the `head` of [2, 3]\n//│ > access the `tail` of [2, 3]\n//│ > access the `head` of [3]\n//│ > access the `tail` of [3]\n//│ > access the `head` of [1, 2, 3]\n//│ > access the `tail` of [1, 2, 3]\n//│ > access the `head` of [2, 3]\n//│ > access the `tail` of [2, 3]\n//│ > access the `head` of [3]\n//│ > access the `tail` of [3]\n//│ = true\n\nisDoubleTripleList__naive of list(1, 2, 3, 4, 5, 6, 7, 8, 9)\n//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [5, 6, 7, 8, 9]\n//│ > access the `tail` of [5, 6, 7, 8, 9]\n//│ > access the `head` of [6, 7, 8, 9]\n//│ > access the `tail` of [6, 7, 8, 9]\n//│ > access the `head` of [7, 8, 9]\n//│ > access the `tail` of [7, 8, 9]\n//│ > access the `head` of [8, 9]\n//│ > access the `tail` of [8, 9]\n//│ > access the `head` of [9]\n//│ > access the `tail` of [9]\n//│ > access the `head` of [1, 2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [1, 2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [2, 3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [3, 4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [3, 4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [4, 5, 6, 7, 8, 9]\n//│ > access the `tail` of [4, 5, 6, 7, 8, 9]\n//│ > access the `head` of [5, 6, 7, 8, 9]\n//│ > access the `tail` of [5, 6, 7, 8, 9]\n//│ > access the `head` of [6, 7, 8, 9]\n//│ > access the `tail` of [6, 7, 8, 9]\n//│ > access the `head` of [7, 8, 9]\n//│ > access the `tail` of [7, 8, 9]\n//│ > access the `head` of [8, 9]\n//│ > access the `tail` of [8, 9]\n//│ > access the `head` of [9]\n//│ > access the `tail` of [9]\n//│ = true\n\npattern DoubleAndTripleList = DoubleList & TripleList\n\nfun isDoubleAndTriple__naive(xs) = withLog of\n  () => xs is DoubleAndTripleList\n\nisDoubleAndTriple__naive of list(8, 9)\n//│ > access the `head` of [8, 9]\n//│ > access the `tail` of [8, 9]\n//│ > access the `head` of [9]\n//│ > access the `tail` of [9]\n//│ > access the `head` of [8, 9]\n//│ > access the `tail` of [8, 9]\n//│ > access the `head` of [9]\n//│ > access the `tail` of [9]\n//│ = false\n\nisDoubleAndTriple__naive of list(1, 2, 3)\n//│ > access the `head` of [1, 2, 3]\n//│ > access the `tail` of [1, 2, 3]\n//│ > access the `head` of [2, 3]\n//│ > access the `tail` of [2, 3]\n//│ > access the `head` of [3]\n//│ > access the `tail` of [3]\n//│ = false\n\nisDoubleAndTriple__naive of list(4, 3, 2, 1)\n//│ > access the `head` of [4, 3, 2, 1]\n//│ > access the `tail` of [4, 3, 2, 1]\n//│ > access the `head` of [3, 2, 1]\n//│ > access the `tail` of [3, 2, 1]\n//│ > access the `head` of [2, 1]\n//│ > access the `tail` of [2, 1]\n//│ > access the `head` of [1]\n//│ > access the `tail` of [1]\n//│ > access the `head` of [4, 3, 2, 1]\n//│ > access the `tail` of [4, 3, 2, 1]\n//│ > access the `head` of [3, 2, 1]\n//│ > access the `tail` of [3, 2, 1]\n//│ > access the `head` of [2, 1]\n//│ > access the `tail` of [2, 1]\n//│ > access the `head` of [1]\n//│ > access the `tail` of [1]\n//│ = false\n\nisDoubleAndTriple__naive of list(1, 2, 3, 4, 5, 6)\n//│ > access the `head` of [1, 2, 3, 4, 5, 6]\n//│ > access the `tail` of [1, 2, 3, 4, 5, 6]\n//│ > access the `head` of [2, 3, 4, 5, 6]\n//│ > access the `tail` of [2, 3, 4, 5, 6]\n//│ > access the `head` of [3, 4, 5, 6]\n//│ > access the `tail` of [3, 4, 5, 6]\n//│ > access the `head` of [4, 5, 6]\n//│ > access the `tail` of [4, 5, 6]\n//│ > access the `head` of [5, 6]\n//│ > access the `tail` of [5, 6]\n//│ > access the `head` of [6]\n//│ > access the `tail` of [6]\n//│ > access the `head` of [1, 2, 3, 4, 5, 6]\n//│ > access the `tail` of [1, 2, 3, 4, 5, 6]\n//│ > access the `head` of [2, 3, 4, 5, 6]\n//│ > access the `tail` of [2, 3, 4, 5, 6]\n//│ > access the `head` of [3, 4, 5, 6]\n//│ > access the `tail` of [3, 4, 5, 6]\n//│ > access the `head` of [4, 5, 6]\n//│ > access the `tail` of [4, 5, 6]\n//│ > access the `head` of [5, 6]\n//│ > access the `tail` of [5, 6]\n//│ > access the `head` of [6]\n//│ > access the `tail` of [6]\n//│ = true\n\nfun isDoubleAndTriple__compiled(xs) = withLog of\n  () => xs is @compile DoubleAndTripleList\n\nisDoubleAndTriple__compiled of list(8, 9)\n//│ > access the `head` of [8, 9]\n//│ > access the `tail` of [8, 9]\n//│ > access the `head` of [9]\n//│ > access the `tail` of [9]\n//│ = false\n\nisDoubleAndTriple__compiled of list(1, 2, 3)\n//│ > access the `head` of [1, 2, 3]\n//│ > access the `tail` of [1, 2, 3]\n//│ > access the `head` of [2, 3]\n//│ > access the `tail` of [2, 3]\n//│ > access the `head` of [3]\n//│ > access the `tail` of [3]\n//│ = false\n\nisDoubleAndTriple__compiled of list(4, 3, 2, 1)\n//│ > access the `head` of [4, 3, 2, 1]\n//│ > access the `tail` of [4, 3, 2, 1]\n//│ > access the `head` of [3, 2, 1]\n//│ > access the `tail` of [3, 2, 1]\n//│ > access the `head` of [2, 1]\n//│ > access the `tail` of [2, 1]\n//│ > access the `head` of [1]\n//│ > access the `tail` of [1]\n//│ = false\n\nisDoubleAndTriple__compiled of list(1, 2, 3, 4, 5, 6)\n//│ > access the `head` of [1, 2, 3, 4, 5, 6]\n//│ > access the `tail` of [1, 2, 3, 4, 5, 6]\n//│ > access the `head` of [2, 3, 4, 5, 6]\n//│ > access the `tail` of [2, 3, 4, 5, 6]\n//│ > access the `head` of [3, 4, 5, 6]\n//│ > access the `tail` of [3, 4, 5, 6]\n//│ > access the `head` of [4, 5, 6]\n//│ > access the `tail` of [4, 5, 6]\n//│ > access the `head` of [5, 6]\n//│ > access the `tail` of [5, 6]\n//│ > access the `head` of [6]\n//│ > access the `tail` of [6]\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/EvaluationContext.mls",
    "content": ":js\n\n// This is an interesting experiment in evaluation context.\n// Author: Luyu Cheng\n\n\nimport \"../../../mlscript-compile/Option.mls\"\nimport \"../../../mlscript-compile/MutMap.mls\"\n\nopen annotations\nopen Option { Some, None }\n\n\ndata class Term with\n  constructor\n    Var(name: Str)\n    App(lhs: Term, rhs: Term)\n    Abs(lhs: Var, rhs: Term)\n  \n  // A cached set of free variables\n  let _freeVars = None\n  \n  // Compute free variables. Retrieve the cache if it exists.\n  fun freeVars = if _freeVars is\n    Some(fv) then fv\n    None then\n      let fv = if this is\n        Var(name) then new Set([name])\n        App(lhs, rhs) then lhs.freeVars.union(rhs.freeVars)\n        Abs(name, body) then body.freeVars.difference(new Set([name]))\n      set _freeVars = Some(fv)\n      fv\n  \n  // Keep increasing the index until the based name with the index is not a free\n  // variable in this term.\n  fun freshName(baseName) =\n    let\n      freeVars = this.freeVars\n      nameIndex = 1\n    if freeVars.has(baseName) is false then baseName else...\n    while (baseName + \"_\" + nameIndex) is currentName and\n      freeVars.has(currentName) then set nameIndex += 1\n      else return currentName\n  \n  fun freshVar(baseName) = Var of freshName(baseName)\n  \n  fun equals(that) = if this is\n    Var(name) and that is Var(name') then name === name'\n    App(lhs, rhs) and that is App(lhs', rhs') then\n      lhs.equals(lhs') && rhs.equals(rhs')\n    Abs(Var(name), body) and that is Abs(Var(name'), body') then\n      name === name' && body.equals(body')\n    else false\n  \n  // Pretty-print the term.\n  fun show = if this is\n    Var(name) then name\n    App(Abs as lhs, rhs) then \"(\" + lhs.show + \") \" + rhs.show\n    App(lhs, App as rhs) then lhs.show + \" (\" + rhs.show + \")\"\n    App(lhs, rhs) then lhs.show + \" \" + rhs.show\n    Abs(Var(name), body) then \"λ\" + name + \". \" + body.show\n\nVar(\"a\").freshVar(\"a\")\n//│ = Var(\"a_1\")\n\nApp(Var(\"a\"), Var(\"a_1\")).freshVar(\"a\")\n//│ = Var(\"a_2\")\n\nVar(\"a\").freshVar(\"b\")\n//│ = Var(\"b\")\n\nfun (<~>) alphaEquivalent(lhs, rhs) =\n  let varMap = MutMap.empty\n  pattern Var' = Var(n) => varMap |> MutMap.get(n) |. Option.getOrElse(n)\n  fun go(lhs, rhs) = if lhs is\n    Var(n) and rhs is Var' as n' then n === n'\n    App(l, r) and r is App(l', r') then go(l, l') and go(r, r')\n    Abs(Var(n), b) and rhs is Abs(Var(n'), b') then\n      let prev = varMap |> MutMap.get(n)\n      varMap |> MutMap.insert(n', n)\n      let equal = go(b, b')\n      varMap |> if prev is\n        Some(n'') then MutMap.insert(n', n'')\n        None then MutMap.delete(n')\n      equal\n    else false\n  go(lhs, rhs)\n\n:silent\n// A few frequently used terms.\nlet id_x = Abs(Var(\"x\"), Var(\"x\"))\nlet id_y = Abs(Var(\"y\"), Var(\"y\"))\nlet id_a = Abs(Var(\"a\"), Var(\"a\"))\nlet id_b = Abs(Var(\"b\"), Var(\"b\"))\n// λf. λx. x\nlet zero = Abs(Var(\"f\"), Abs(Var(\"x\"), Var(\"x\")))\n// λn. λf. λx. f (n f x)\nlet succ = Abs(Var(\"n\"), Abs(Var(\"f\"), Abs(Var(\"x\"), App(Var(\"f\"), App(App(Var(\"n\"), Var(\"f\")), Var(\"x\"))))))\n// λm. λn. λf. λx. m f (n f x)\nlet plus = Abs(Var(\"m\"), Abs(Var(\"n\"), Abs(Var(\"f\"), Abs(Var(\"x\"), App(App(Var(\"m\"), Var(\"f\")), App(App(Var(\"n\"), Var(\"f\")), Var(\"x\")))))))\n// λm. λn. λf. m (n f)\nlet multiply = Abs(Var(\"m\"), Abs(Var(\"n\"), Abs(Var(\"f\"), App(Var(\"m\"), App(Var(\"n\"), Var(\"f\"))))))\n// λx. λy. x\nlet true_ = Abs(Var(\"x\"), Abs(Var(\"y\"), Var(\"x\")))\nlet false_ = Abs(Var(\"x\"), Abs(Var(\"y\"), Var(\"y\"))) \n// λb. λx. λy. b y x\nlet not_ = Abs(Var(\"b\"), Abs(Var(\"x\"), Abs(Var(\"y\"), App(App(Var(\"b\"), Var(\"y\")), Var(\"x\")))))\n// λp. λq. p q p\nlet and_ = Abs(Var(\"p\"), Abs(Var(\"q\"), App(App(Var(\"p\"), Var(\"q\")), Var(\"p\"))))\n// λp. λq. p p q\nlet or_ = Abs(Var(\"p\"), Abs(Var(\"q\"), App(App(Var(\"p\"), Var(\"p\")), Var(\"q\"))))\n\nprint of id_x.show\nprint of id_y.show\nprint of id_a.show\nprint of id_b.show\nprint of zero.show\nprint of succ.show\nprint of plus.show\nprint of multiply.show\nprint of true_.show\nprint of false_.show\nprint of not_.show\nprint of and_.show\nprint of or_.show\n//│ > λx. x\n//│ > λy. y\n//│ > λa. a\n//│ > λb. b\n//│ > λf. λx. x\n//│ > λn. λf. λx. f (n f x)\n//│ > λm. λn. λf. λx. m f (n f x)\n//│ > λm. λn. λf. m (n f)\n//│ > λx. λy. x\n//│ > λx. λy. y\n//│ > λb. λx. λy. b y x\n//│ > λp. λq. p q p\n//│ > λp. λq. p p q\n\nid_x <~> id_y\n//│ = true\n\nid_x <~> id_a\n//│ = true\n\nid_x <~> succ\n//│ = false\n\nzero <~> false_\n//│ = true\n\nfun subst(term, name, target) = if term is\n  Var(name') and\n    name === name' then target\n    else term\n  Abs(Var(name'), body) and\n    name === name' then term\n    let target' = if target.freeVars.has(name')\n      then subst(target, name', target.freshVar(name'))\n      else target\n    else Abs(Var(name'), subst(body, name, target'))\n  App(lhs, rhs) then App(subst(lhs, name, target), subst(rhs, name, target))\n\n:expect Abs(Var(\"a\"), Var(\"a\"))\nsubst(Var(\"c\"), \"c\", id_a)\n//│ = Abs(Var(\"a\"), Var(\"a\"))\n\n:expect Var(\"a\")\nsubst(Var(\"a\"), \"b\", id_a)\n//│ = Var(\"a\")\n\n:expect Abs(Var(\"b\"), Var(\"b\"))\nsubst(Var(\"b\"), \"b\", id_b)\n//│ = Abs(Var(\"b\"), Var(\"b\"))\n\n:expect App(Abs(Var(\"x\"), Var(\"x\")), Var(\"y\"))\nsubst(App(Var(\"x\"), Var(\"y\")), \"x\", id_x)\n//│ = App(Abs(Var(\"x\"), Var(\"x\")), Var(\"y\"))\n\n:expect Abs(Var(\"y\"), Abs(Var(\"x\"), Var(\"x\")))\nsubst(Abs(Var(\"y\"), Var(\"x\")), \"x\", id_x)\n//│ = Abs(Var(\"y\"), Abs(Var(\"x\"), Var(\"x\")))\n\n:expect Abs(Var(\"x\"), Var(\"x\"))\nsubst(Abs(Var(\"x\"), Var(\"x\")), \"x\", id_y)\n//│ = Abs(Var(\"x\"), Var(\"x\"))\n\n:expect App(Var(\"z\"), Var(\"z\"))\nsubst(App(Var(\"x\"), Var(\"x\")), \"x\", Var(\"z\"))\n//│ = App(Var(\"z\"), Var(\"z\"))\n\nsubst(Abs(Var(\"a\"), App(Var(\"b\"), Var(\"a\"))), \"b\", Var(\"a\"))\n//│ = Abs(Var(\"a\"), App(Var(\"a_1\"), Var(\"a\")))\n\npattern Value = Abs\n\nobject ByValue with\n  // This pattern matches a beta redex where the argument is a value and\n  // performs the substitution.\n  pattern Redex = App(Abs(Var(x), m), Value as n) => subst(m, x, n)\n  \n  // Call-by-value evaluation contexts\n  //\n  // E ::= □\n  //     | E t\n  //     | v E\n  //\n  // It matches any terms that can take at least one step and extracts the next\n  // redex that we should make a progress and a function to reconstruct the term.\n  pattern Context(pattern Hole) =\n    (\n      (Hole as hole) => [hole, id]\n    ) | (\n      App(Abs as lhs, Context(Hole) as [rhs, remake]) =>\n        [rhs, App(lhs, _)]\n    ) | (\n      App(Context(Hole) as [lhs, remake], Term as rhs) =>\n        [lhs, lhs' => App(remake(lhs'), rhs)]\n    )\n\nfun redex(term) = if term is ByValue.Redex as term' then term'\n\nredex of App(id_x, id_y)\n//│ = Abs(Var(\"y\"), Var(\"y\"))\n\n:re\nredex of id_x\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\nredex of Var(\"a\")\n//│ ═══[RUNTIME ERROR] Error: match error\n\nfun step(term) =\n  if term is ByValue.Context(ByValue.Redex) as [subterm, remake] then remake(subterm)\n\n:re\nstep of Var(\"x\")\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\nstep of App(App(Var(\"a\"), Var(\"b\")), Var(\"c\"))\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\nstep of id_x\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:re\nstep of App(App(id_x, Var(\"b\")), Var(\"c\"))\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:expect \"(λb. b) λx. x\"\nstep(App(App(id_a, id_b), id_x)).show\n//│ = \"(λb. b) λx. x\"\n\n:expect \"λy. y\"\nstep(App(id_x, id_y)).show\n//│ = \"λy. y\"\n\nfun evalByValue(term) =\n  while term is\n    ByValue.Context(ByValue.Redex) as [subterm, remake] then\n      set term = remake(subterm)\n  term\n\nevalByValue(App(id_x, App(id_x, App(id_x, App(id_x, id_y))))).show\n//│ = \"λy. y\"\n\nevalByValue(App(succ, zero)).show\n//│ = \"λf. λx. f ((λf. λx. x) f x)\"\n\nevalByValue(App(succ, App(succ, zero))).show\n//│ = \"λf. λx. f ((λf. λx. f ((λf. λx. x) f x)) f x)\"\n\n:fixme\n// More inconsistent origin locations to fix...\nfun evalByValue'(term) =\n  while term is\n    (@compile ByValue.Context(ByValue.Redex)) as [subterm, remake] then\n      set term = remake(subterm)\n    else term\n//│ ╔══[COMPILATION ERROR] Pattern chaining is not supported in pattern compilation.\n//│ ║  l.214: \t      App(Abs as lhs, Context(Hole) as [rhs, remake]) =>\n//│ ╙──       \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Pattern chaining is not supported in pattern compilation.\n//│ ║  l.217: \t      App(Context(Hole) as [lhs, remake], Term as rhs) =>\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.282: \t    else term\n//│ ╙──       \t         ^^^^\n//│ ╔══[WARNING] Pure expression in statement position\n//│ ║  l.282: \t    else term\n//│ ╙──       \t         ^^^^\n\nobject ByName with\n  // Call-by-name allows reducing any beta redex. The argument `n` may be any\n  // term, not necessarily a value.\n  pattern Redex = App(Abs(Var(x), m), Term as n) => subst(m, x, n)\n  \n  // Call-by-name evaluation contexts\n  //\n  // E ::= □\n  //     | E t\n  pattern Context(pattern Hole) =\n    (\n      (Hole as hole) => [hole, id]\n    ) | (\n      App(Context(Hole) as [lhs, remake], Term as rhs) =>\n        [lhs, lhs' => App(remake(lhs'), rhs)]\n    )\n\n:silent\nlet t = App(Abs(Var(\"x\"), id_a), App(id_x, id_y))\nprint of t.show\n//│ > (λx. λa. a) (λx. x) λy. y\n\nimport \"../../../mlscript-compile/Runtime.mls\"\n\nfun stepByStep(system, term, maxSteps) =\n  let numSteps = 0\n  print of \"Term: \" + term.show\n  while numSteps < maxSteps and system.Context.unapply(system.Redex, term) is\n    Runtime.MatchSuccess([subterm, remake], _) do\n      set numSteps += 1\n      set term = remake(subterm)\n      print of \"Step \" + numSteps + \": \" + term.show\n  if numSteps == maxSteps do\n    print of \"Stopped due to too many steps.\"\n\n:silent\nlet applySelf = Abs(Var(\"x\"), App(Var(\"x\"), Var(\"x\")))\nlet omega = App(applySelf, applySelf)\nprint of applySelf.show\nprint of omega.show\n//│ > λx. x x\n//│ > (λx. x x) λx. x x\n\nstepByStep(ByValue, t, 10)\n//│ > Term: (λx. λa. a) (λx. x) λy. y\n//│ > Step 1: (λx. λa. a) λy. y\n//│ > Step 2: λa. a\n\nstepByStep(ByName, App(id_x, id_y), 10)\n//│ > Term: (λx. x) λy. y\n//│ > Step 1: λy. y\n\nstepByStep(ByValue, App(id_x, App(id_y, id_a)), 10)\n//│ > Term: (λx. x) (λy. y) λa. a\n//│ > Step 1: (λx. x) λa. a\n//│ > Step 2: λa. a\n\nstepByStep(ByName, App(id_x, App(id_y, id_a)), 10)\n//│ > Term: (λx. x) (λy. y) λa. a\n//│ > Step 1: (λy. y) λa. a\n//│ > Step 2: λa. a\n\nstepByStep(ByName, App(App(id_x, id_y), id_a), 10)\n//│ > Term: (λx. x) λy. y λa. a\n//│ > Step 1: (λy. y) λa. a\n//│ > Step 2: λa. a\n\nstepByStep(ByName, App(id_x, App(id_a, id_b)), 10)\n//│ > Term: (λx. x) (λa. a) λb. b\n//│ > Step 1: (λa. a) λb. b\n//│ > Step 2: λb. b\n\nstepByStep(ByName, App(Abs(Var(\"u\"), id_a), omega), 10)\n//│ > Term: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 1: λa. a\n\n// The following term is evaluated differently in two systems.\n\n:silent\nlet t = App(Abs(Var(\"u\"), id_a), omega)\nprint of t.show\n//│ > (λu. λa. a) (λx. x x) λx. x x\n\nstepByStep(ByValue, t, 10)\n//│ > Term: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 1: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 2: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 3: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 4: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 5: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 6: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 7: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 8: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 9: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 10: (λu. λa. a) (λx. x x) λx. x x\n//│ > Stopped due to too many steps.\n\nstepByStep(ByName, t, 10)\n//│ > Term: (λu. λa. a) (λx. x x) λx. x x\n//│ > Step 1: λa. a\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/EvaluationContext2.mls",
    "content": ":js\n\n// This is an interesting experiment in evaluation context.\n// Author: Lionel Parreaux\n\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen annotations\nopen Option { Some, None }\n\n\nclass Ident(val name: Str)\n\ndata class Term with\n  constructor\n    Lit(value: Int)\n    Var(name: Ident)\n    App(lhs: Term, rhs: Term)\n    Abs(lhs: Ident, rhs: Term)\n    Add(lhs: Term, rhs: Term)\n  \n  // A cached set of free variables\n  let _freeVars = None\n  \n  // Compute free variables. Retrieve the cache if it exists.\n  fun freeVars = if _freeVars is\n    Some(fv) then fv\n    None then\n      let fv = if this is\n        Var(name) then mkSet of name\n        App(lhs, rhs) then lhs.freeVars.union(rhs.freeVars)\n        Abs(name, body) then body.freeVars.difference(mkSet of name)\n      set _freeVars = Some(fv)\n      fv\n  \n  // Pretty-print the term.\n  fun show =\n    fun par(t) = if t is\n      Lit | Var then t.show\n      else \"(\" + t.show + \")\"\n    if this is\n      Var(id) then id.name\n      App(App as lhs, rhs) then lhs.show + par(rhs)\n      App(lhs, rhs) then par(lhs) + \" \" + par(rhs)\n      Abs(id, body) then \"λ\" + id.name + \". \" + body.show\n      Lit(value) then value.toString()\n      Add(Add as lhs, rhs) then lhs.show + \" + \" + par(rhs)\n      Add(lhs, rhs) then par(lhs) + \" + \" + par(rhs)\n\n\nApp(Var(Ident of \"a\"), Var(Ident of \"a_1\")).show\n//│ = \"a a_1\"\n\n\npattern Value = Abs | Lit\n\nmodule CBV with\n  \n  pattern Ctx(pattern Hole) =\n    | Hole\n    | Add(Ctx(Hole), _)\n    | Add(Value, Ctx(Hole))\n    | App(Value, Ctx(Hole))\n    | App(Ctx(Hole), _)\n  \n  pattern Redex =\n    | Add(Lit(v1), Lit(v2)) => Lit(v1 + v2)\n    | App(Abs(id, body), Value as arg) => body.subst(id, arg)\n  \n  pattern Step = Ctx(Redex)\n  \n  pattern Steps = Step as Steps | _\n\n\nfun eval(term) =\n  print(\"Evaluating:\", term.show)\n  if term is\n    CBV.Step(next) then eval(next)\n    Value then print(\"Done.\")\n    else print(\"Stuck!\")\n\n:silent\nlet\n  a = Var(Ident(\"a\"))\n  b = Var(Ident(\"b\"))\n  x = Lit(2)\n  y = Lit(3)\n  z = Lit(4)\n  t = Add(Add(x, y), z)\n\neval(t)\n//│ > Evaluating: 2 + 3 + 4\n//│ > Evaluating: 5 + 4\n//│ > Evaluating: 9\n//│ > Done.\n\neval(Add(t, t))\n//│ > Evaluating: 2 + 3 + 4 + (2 + 3 + 4)\n//│ > Evaluating: 5 + 4 + (2 + 3 + 4)\n//│ > Evaluating: 9 + (2 + 3 + 4)\n//│ > Evaluating: 9 + (5 + 4)\n//│ > Evaluating: 9 + 9\n//│ > Evaluating: 18\n//│ > Done.\n\neval(Add(t, a))\n//│ > Evaluating: 2 + 3 + 4 + a\n//│ > Evaluating: 5 + 4 + a\n//│ > Evaluating: 9 + a\n//│ > Stuck!\n\nassert Add(t, t) is CBV.Steps(res), res\n//│ = Lit(18)\n\n\nCBV.Step.unapply(x)\n//│ = MatchFailure(null)\n\nCBV.Step.unapply(t)\n//│ = MatchSuccess(Add(Lit(5), Lit(4)), null)\n\neval(x)\n//│ > Evaluating: 2\n//│ > Done.\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/Extraction.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\nopen annotations\n\npattern Itch = Some(Some(Some(Some(Some(Some(Some(42)))))))\n\nfun isItch(x) = x is @compile Itch\n\n:expect true\nisItch of Some(Some(Some(Some(Some(Some(Some(42)))))))\n//│ = true\n\n:expect false\nisItch of Some(Some(Some(Some(Some(Some(Some(Some(42))))))))\n//│ = false\n\n:expect false\nisItch of 42\n//│ = false\n\npattern Itch' = Some(Some(Some(Some(Some(\"scratch\" as x))))) => x\n\nfun action(x) =\n  if x is (@compile Itch') as output then\n    \"Just \" + output + \"!\"\n  else\n    \"I don't know.\"\n\naction of Some(Some(Some(Some(Some(\"scratch\")))))\n//│ = \"Just scratch!\"\n\n// Test the semantics of biased disjunction.\n\npattern BiasedOr1 = Some(1 | Some(_))\nfun biasedOr1(x) = x is @compile BiasedOr1\n\nbiasedOr1 of Some(1)\n//│ = true\n\nbiasedOr1 of Some(42)\n//│ = false\n\nbiasedOr1 of Some(Some(2))\n//│ = true\n\nbiasedOr1 of Some(Some(\"hello\"))\n//│ = true\n\nbiasedOr1 of Some(Some(Some(Some(Some(Some(Some(Some(42))))))))\n//│ = true\n\nfun observeSome(x) =\n  print(\"observe some \" + x)\n  x + 1\n\nfun observePlain(x) =\n  print(\"observe plain \" + x)\n  x + 2\n\npattern LoggedBiasedOr =\n  | Some((Some(x) => observeSome(x)) as res) => res\n  | Some((x => observePlain(x)) as res) => res\n\nprint of Some(1) is @compile LoggedBiasedOr\n//│ > true\n\nif Some(Some(1)) is (@compile LoggedBiasedOr) as output then\n  print(\"logged biased: \" + output)\n//│ > observe some 1\n//│ > observe plain Some(1)\n//│ > logged biased: 2\n\n// Make it a bit more complicated: biased disjunction with transformations.\n\npattern BiasedOr2 =\n  | Some((Some(x) => x + 1) as res) => res\n  | Some((x => x + 2) as res) => res\n\n:fixme // TODO: fix IR rebinding issue (each symbol should be bound at most once)\n:checkIR\nfun biasedOr2__compiled(x) = if x is (@compile BiasedOr2) as output then output\n//│ ═══[INTERNAL ERROR] [BlockChecker] Invalid IR: symbol x⁰ is bound more than once\n\nfun biasedOr2__naive(x) = if x is BiasedOr2(output) then output\n\nbiasedOr2__compiled of Some(1)\n//│ = 3\n\nbiasedOr2__naive of Some(1)\n//│ = 3\n\nbiasedOr2__compiled of Some(Some(1))\n//│ = 2\n\nbiasedOr2__naive of Some(Some(1))\n//│ = 2\n\n\ndata class Pair[A, B](first: A, second: B)\n\npattern XorPair = Pair(None, Some(_)) | Pair(Some(_), None)\n\nfun xorPair(x) = if x is (@compile XorPair) as output then output else \"failed\"\n\nxorPair of Pair(None, None)\n//│ = \"failed\"\n\nxorPair of Pair(None, Some(1))\n//│ = Pair(None, Some(1))\n\nxorPair of Pair(Some(56), None)\n//│ = Pair(Some(56), None)\n\nfun xorPairInterp(x) = if x is XorPair as output then output else \"failed\"\n\nxorPairInterp of Pair(None, None)\n//│ = \"failed\"\n\nxorPairInterp of Pair(None, Some(1))\n//│ = Pair(None, Some(1))\n\nxorPairInterp of Pair(Some(56), None)\n//│ = Pair(Some(56), None)\n\n\npattern XorPairT = Pair(None, Some(_ => 111)) | Pair(Some(_), None)\n\nfun xorPairT(x) = if x is (@compile XorPairT) as output then output else \"failed\"\n\nxorPairT of Pair(None, None)\n//│ = \"failed\"\n\n// When one branch transforms a constructor field, both compiled and\n// interpreted matching rebuild a fresh `Pair` with the transformed field.\nxorPairT of Pair(None, Some(1))\n//│ = Pair(None, Some(111))\n\nxorPairT of Pair(Some(56), None)\n//│ = Pair(Some(56), None)\n\nfun xorPairTInterp(x) = if x is XorPairT as output then output else \"failed\"\n\nxorPairTInterp of Pair(None, None)\n//│ = \"failed\"\n\nxorPairTInterp of Pair(None, Some(1))\n//│ = Pair(None, Some(111))\n\nxorPairTInterp of Pair(Some(56), None)\n//│ = Pair(Some(56), None)\n\n\ndata class Triplet[A, B, C](first: A, second: B, third: C)\n\npattern ExactlyOneNone =\n  | Triplet(None,    Some(_), Some(_))\n  | Triplet(Some(_), None,    Some(_))\n  | Triplet(Some(_), Some(_), None   )\n\nfun exactlyOneNone(x) =\n  if x is (@compile ExactlyOneNone) as output then output else \"failed\"\n\nfun exactlyOneNone__naive(x) =\n  if x is ExactlyOneNone(output) then output else \"failed\"\n\n// For transform-free compiled patterns, we can now reuse the original\n// scrutinee as the output instead of synthesizing a plain record.\n\nexactlyOneNone of Triplet(None, Some(1), Some(2))\n//│ = Triplet(None, Some(1), Some(2))\n\nexactlyOneNone of Triplet(Some(1), None, Some(2))\n//│ = Triplet(Some(1), None, Some(2))\n\nexactlyOneNone of Triplet(Some(1), Some(2), None)\n//│ = Triplet(Some(1), Some(2), None)\n\n// This now agrees with the naive compilation of patterns, which also returns\n// the scrutinee directly.\n\nexactlyOneNone__naive of Triplet(None, Some(1), Some(100))\n//│ = Triplet(None, Some(1), Some(100))\n\nexactlyOneNone__naive of Triplet(Some(1), None, Some(400))\n//│ = Triplet(Some(1), None, Some(400))\n\nexactlyOneNone__naive of Triplet(Some(1), Some(2), None)\n//│ = Triplet(Some(1), Some(2), None)\n\n:expect \"failed\"\nexactlyOneNone of Triplet(None, Some(1), None)\n//│ = \"failed\"\n\n:expect \"failed\"\nexactlyOneNone of Triplet(None, None, Some(1))\n//│ = \"failed\"\n\n:expect \"failed\"\nexactlyOneNone of Triplet(Some(1), None, None)\n//│ = \"failed\"\n\n:expect \"failed\"\nexactlyOneNone of Triplet(None, None, None)\n//│ = \"failed\"\n\n:expect \"failed\"\nexactlyOneNone of Triplet(Some(1), Some(2), Some(3))\n//│ = \"failed\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/Flatten.mls",
    "content": ":js\n\nopen annotations\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\n\nopen Stack\n\nfun list(...elements) = elements Iter.toStack()\n\n// This pattern can flatten nested lists. It tries to flatten the head and\n// concatenate the output with the tail. If the head cannot be flattened, it\n// would just append the head to the flattened tail.\npattern Flatten =\n  | Nil => Nil\n  | ((Flatten as hd) :: (Flatten as tl)) => hd ::: tl\n  | (hd :: (Flatten as tl)) => hd :: tl\n\nfun flatten__naive(xs) =\n  if xs is Flatten as ys then\n    print of \"Flattened: [\" + (ys Iter.fromStack() Iter.joined(\", \")) + \"]\"\n  else \"Cannot flatten: \" + xs\n\nflatten__naive of Nil\n//│ > Flattened: []\n\nflatten__naive of list(1)\n//│ > Flattened: [1]\n\nflatten__naive of list(1, 2, 3, 4)\n//│ > Flattened: [1, 2, 3, 4]\n\nflatten__naive of list(list(1, 2), list(3, 4))\n//│ > Flattened: [1, 2, 3, 4]\n\nflatten__naive of list(list(list(list(1, 2, 3, 4))))\n//│ > Flattened: [1, 2, 3, 4]\n\nflatten__naive of list(list(1, 2), list(list(3, 4), list(list(5, 6))))\n//│ > Flattened: [1, 2, 3, 4, 5, 6]\n\nfun flatten__compiled(xs) =\n  if xs is (@compile Flatten) as ys then\n    print of \"Flattened: [\" + (ys Iter.fromStack() Iter.joined(\", \")) + \"]\"\n  else \"Cannot flatten: \" + xs\n\nflatten__compiled of Nil\n//│ > Flattened: []\n\nflatten__compiled of list(1)\n//│ > Flattened: [1]\n\nflatten__compiled of list(1, 2, 3, 4)\n//│ > Flattened: [1, 2, 3, 4]\n\nflatten__compiled of list(list(1, 2), list(3, 4))\n//│ > Flattened: [1, 2, 3, 4]\n\nflatten__compiled of list(list(list(list(1, 2, 3, 4))))\n//│ > Flattened: [1, 2, 3, 4]\n\nflatten__compiled of list(list(1, 2), list(list(3, 4), list(list(5, 6))))\n//│ > Flattened: [1, 2, 3, 4, 5, 6]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/HindleyMilner.mls",
    "content": ":js\n\n// Hindley-Milner type inference implementation\n\nimport \"../../../mlscript-compile/Option.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/Runtime.mls\"\n\nopen annotations\nopen Option { Some, None }\n\ndata class Type with\n  constructor\n    TVar(name: Str)\n    TFun(lhs: Type, rhs: Type)\n    TPrim(name: Str)\n  \n  fun show = if this is\n    TVar(name) then name\n    TFun(TFun as lhs, rhs) then \"(\" + lhs.show + \") -> \" + rhs.show\n    TFun(lhs, rhs) then lhs.show + \" -> \" + rhs.show\n    TPrim(name) then name\n  \n  fun equals(that) = if this is\n    TVar(name) and that is TVar(name') then name === name'\n    TFun(lhs, rhs) and that is TFun(lhs', rhs') then\n      lhs.equals(lhs') and rhs.equals(rhs')\n    TPrim(name) and that is TPrim(name') then name === name'\n    else false\n  \n  let _freeVars = None\n  \n  // Get free type variables\n  fun freeVars = if _freeVars is\n    Some(vars) then vars\n    None then\n      let vars = if this is\n        TVar(name) then new Set([name])\n        TFun(lhs, rhs) then lhs.freeVars.union(rhs.freeVars)\n        TPrim(_) then new Set([])\n      set _freeVars = Some(vars)\n      vars\n  \n  fun hasFreeVar(name) = freeVars.has(name)\n\nlet TInt = TPrim(\"Int\")\nlet TBool = TPrim(\"Bool\")\n//│ TBool = TPrim(\"Bool\")\n//│ TInt = TPrim(\"Int\")\n\npattern ShowTerm =\n  | Var(name) => name\n  | App(Abs as ShowTerm as lhs, rhs) => \"(\" + lhs + \") \" + rhs\n  | App(ShowTerm as lhs, App as ShowTerm as rhs) => lhs + \" (\" + rhs + \")\"\n  | App(ShowTerm as lhs, ShowTerm as rhs) => lhs + \" \" + rhs\n  | Abs(name, ShowTerm as body) => \"λ\" + name + \". \" + body\n  | IntLit(value) => value.toString()\n  | BoolLit(value) => if value then \"true\" else \"false\"\n//\ndata class Term with\n  constructor\n    Var(name: Str)\n    App(lhs: Term, rhs: Term)\n    Abs(name: Str, body: Term)\n    IntLit(value: Int)\n    BoolLit(value: Bool)\n  \n  // Any more convenient way to apply a pattern?\n  // For example, `this through ShowTerm`?\n  fun show = if this is ShowTerm as result then result\n\ndata class Scheme(vars: Set[Str], typ: Type) with\n  fun show =\n    if vars.size === 0 then typ.show\n    else \"∀\" + vars Iter.joined(\", \") + \". \" + typ.show\n\n// Substitution for types\ndata class Subst(map: Map[Str, Type]) with\n  \n  fun apply(typ) = if typ is\n    TVar(name) and this is Subst(map) and\n      map.has(name) then map.get(name)\n      else typ\n    TFun(lhs, rhs) then TFun(apply(lhs), apply(rhs))\n    else typ\n  \n  fun applyScheme(scheme) = if scheme is Scheme(vars, typ) then\n    let newMap = new Map()\n    this.map Iter.each of case [key, value] then\n      if vars.has(key) is false then newMap.set(key, value)\n    Subst(newMap).apply(typ)\n  \n  fun compose(that) =\n    let newMap = new Map()\n    that.map Iter.each of case [key, value] then\n      newMap.set(key, apply(value))\n    this.map Iter.each of case [key, value] then\n      newMap.set(key, value)\n    Subst(newMap)\n  \n  fun show =\n    let pairs = mut []\n    map Iter.each of case [key, value] then\n      pairs.push(key + \" -> \" + value.show)\n    \"{\" + pairs.join(\", \") + \"}\"\n\nlet emptySub = Subst(new Map())\n//│ emptySub = Subst(Map(0) {})\n\nfun (~>) applyPattern(x, P) =\n  if P.unapply(x) is Runtime.MatchSuccess(result, _) then result\n\n// Note that how we use `where` clauses in disjunction patterns with bindings.\npattern Unify =\n  (\n    ([TFun(l1, r1), TFun(l2, r2)]) =>\n      let s1 = [l1, l2] ~> Unify\n      let s2 = [s1.apply(r1), s1.apply(r2)] ~> Unify\n      s2.compose(s1)\n  ) | (\n    (\n      ([TVar(name1), TVar(name2)] | [TPrim(name1), TPrim(name2)])\n        where name1 === name2\n    ) => emptySub\n  ) | (\n    (\n      ([TVar(nme), Type as typ] | [Type as typ, TVar(nme)])\n        where not(typ.hasFreeVar(nme))\n    ) =>\n      Subst(new Map([[nme, typ]]))\n  ) | (\n    ([TPrim(name1), TPrim(name2)] where name1 === name2) => emptySub\n  )\n\nfun unify'(t1, t2) = [t1, t2] ~> Unify\n\nfun unify(t1, t2) = if\n  t1 is TVar(name1) and t2 is TVar(name2) and name1 === name2 then emptySub\n  t1 is TVar(name) and\n    t2.hasFreeVar(name) then throw new Error(\"Occurs check failed\")\n    else Subst(new Map([[name, t2]]))\n  t2 is TVar(name) and\n    t1.hasFreeVar(name) then throw new Error(\"Occurs check failed\")\n    else Subst(new Map([[name, t1]]))\n  t1 is TFun(l1, r1) and t2 is TFun(l2, r2) then\n    let s1 = unify(l1, l2)\n    let s2 = unify(s1.apply(r1), s1.apply(r2))\n    s2.compose(s1)\n  t1 is TPrim(name) and t2 is TPrim(name') and name === name' then emptySub\n  else throw new Error(\"Cannot unify \" + t1.show + \" with \" + t2.show)\n\nunify(TInt, TInt).show\n//│ = \"{}\"\n\nunify'(TInt, TInt).show\n//│ = \"{}\"\n\n:expect \"{t1 -> Int}\"\nunify(TVar(\"t1\"), TInt).show\n//│ = \"{t1 -> Int}\"\n\nunify'(TVar(\"t1\"), TInt).show\n//│ = \"{t1 -> Int}\"\n\n:expect \"{}\"\nunify(TFun(TVar(\"t2\"), TVar(\"t3\")), TFun(TVar(\"t2\"), TVar(\"t3\"))).show\n//│ = \"{}\"\n\nunify'(TFun(TVar(\"t2\"), TVar(\"t3\")), TFun(TVar(\"t2\"), TVar(\"t3\"))).show\n//│ = \"{}\"\n\n:re\nunify(TVar(\"t1\"), TFun(TVar(\"t1\"), TInt)).show\n//│ ═══[RUNTIME ERROR] Error: Occurs check failed\n\n:re\nunify'(TVar(\"t1\"), TFun(TVar(\"t1\"), TInt)).show\n//│ ═══[RUNTIME ERROR] Error: match error\n\n// Note: missing type arguments for `Map`.\ndata class Env(bindings: Map[Str, Scheme]) with\n  fun lookup(name) =\n    if bindings.has(name) then bindings.get(name)\n    else throw new Error(\"Unbound variable: \" + name)\n  \n  fun extend(name, scheme) =\n    let newBindings = new Map(bindings)\n    newBindings.set(name, scheme)\n    Env(newBindings)\n  \n  fun freeVars =\n    let vars = new Set([])\n    bindings.values() Iter.each of scheme =>\n      scheme => scheme.typ.freeVars Iter.each of v => vars.add(v)\n    vars\n  \n  fun generalize(typ) =\n    let envFree = freeVars\n    let typeFree = typ.freeVars\n    let genVars = new Set([])\n    typeFree Iter.each of v =>\n      if envFree.has(v) is false then genVars.add(v)\n    Scheme(genVars, typ)\n\nlet emptyEnv = Env(new Map())\n//│ emptyEnv = Env(Map(0) {})\n\nclass Gen with\n  let counter = 0\n  \n  fun subscript =\n    let\n      value = counter\n      text = \"\"\n    while value > 0 || text.length === 0 do\n      set text += String.fromCodePoint(0x2080 + value % 10)\n      set value = Math.floor(value / 10)\n    text\n  \n  fun fresh =\n    let name = \"t\" + subscript\n    set counter += 1\n    TVar(name)\n\nfun infer(env, term)(using gen: Gen) = if term is\n  IntLit then [emptySub, TInt]\n  BoolLit then [emptySub, TBool]\n  Var(name) and env.lookup(name) is Scheme(vars, typ) then\n    // Instantiate the type scheme\n    let subst = new Map()\n    vars Iter.each of v => subst.set(v, gen.fresh)\n    let s = Subst(subst)\n    [emptySub, s.apply(typ)]\n  App(lhs, rhs) and infer(env, lhs) is [s1, t1] then\n    let env1 = Env(new Map())\n    env.bindings Iter.each of case [name, scheme] then\n      env1.bindings.set(name, Scheme(scheme.vars, s1.apply(scheme.typ)))\n    if infer(env1, rhs) is [s2, t2] then...\n    let tv = gen.fresh\n    let s3 = unify(s2.apply(t1), TFun(t2, tv))\n    [s3.compose(s2).compose(s1), s3.apply(tv)]\n  Abs(name, body) and\n    let tv = gen.fresh\n    let env1 = env.extend(name, Scheme(new Set([]), tv))\n    infer(env1, body) is [s, t] then [s, TFun(s.apply(tv), t)]\n\n// Type inference with generalization\nfun inferTop(env, name, term)(using Gen) =\n  if infer(env, term) is [subst, typ] then...\n  [subst, env.generalize(typ)]\n\nfun (|-) inferType(env, term) =\n  using Gen = new Gen\n  env.generalize(infer(env, term).1).show\n\n:silent\n// Example terms\nlet id = Abs(\"x\", Var(\"x\"))\nlet const = Abs(\"x\", Abs(\"y\", Var(\"x\")))\nlet apply = Abs(\"f\", Abs(\"x\", App(Var(\"f\"), Var(\"x\"))))\nlet compose = Abs(\"f\", Abs(\"g\", Abs(\"x\", App(Var(\"f\"), App(Var(\"g\"), Var(\"x\"))))))\n\nprint of id.show\nprint of const.show\nprint of apply.show\nprint of compose.show\n//│ > λx. x\n//│ > λx. λy. x\n//│ > λf. λx. f x\n//│ > λf. λg. λx. f (g x)\n\nemptyEnv |- id\n//│ = \"∀t₀. t₀ -> t₀\"\n\nemptyEnv |- const\n//│ = \"∀t₀, t₁. t₀ -> t₁ -> t₀\"\n\nemptyEnv |- apply\n//│ = \"∀t₁, t₂. (t₁ -> t₂) -> t₁ -> t₂\"\n\nemptyEnv |- compose\n//│ = \"∀t₃, t₄, t₂. (t₃ -> t₄) -> (t₂ -> t₃) -> t₂ -> t₄\"\n\n:expect \"Int\"\nemptyEnv |- IntLit(42)\n//│ = \"Int\"\n\n:expect \"Bool\"\nemptyEnv |- BoolLit(true)\n//│ = \"Bool\"\n\n:expect \"Int\"\nemptyEnv |- App(id, IntLit(5))\n//│ = \"Int\"\n\n:expect \"Int\"\nemptyEnv |-  App(id, App(id, IntLit(5)))\n//│ = \"Int\"\n\n:silent\nlet env1 = emptyEnv.extend of\n  \"id\"\n  Scheme(new Set([\"a\"]), TFun(TVar(\"a\"), TVar(\"a\")))\n\n:expect \"Int\"\nenv1 |- App(Var(\"id\"), IntLit(5))\n//│ = \"Int\"\n\n:expect \"Bool\"\nenv1 |- App(Var(\"id\"), BoolLit(true))\n//│ = \"Bool\"\n\n:silent\nlet env2 = env1.extend of\n  \"add\"\n  Scheme(new Set(), TFun(TInt, TFun(TInt, TInt)))\n\nenv2 |- App(App(Var(\"add\"), IntLit(5)), IntLit(5))\n//│ = \"Int\"\n\n:re\nenv2 |- App(App(Var(\"add\"), IntLit(5)), BoolLit(true))\n//│ ═══[RUNTIME ERROR] Error: Cannot unify Int with Bool\n\n:silent\nlet env3 = env2.extend of\n  \"if\"\n  Scheme(new Set([\"a\"]), TFun(TBool, TFun(TVar(\"a\"), TFun(TVar(\"a\"), TVar(\"a\")))))\n\nenv3 |- Var(\"if\")\n//│ = \"∀t₀. Bool -> t₀ -> t₀ -> t₀\"\n\n:silent\nlet t = App(App(App(Var(\"if\"), BoolLit(true)), App(Var(\"id\"), Var(\"id\"))), Var(\"id\"))\nprint of t.show\nprint of env3 |- t\n//│ > if true (id id) id\n//│ > ∀t₆. t₆ -> t₆\n\n:silent\n:re\nlet t = App(App(App(Var(\"if\"), BoolLit(true)), App(Var(\"id\"), Var(\"id\"))), Var(\"add\"))\nprint of t.show\nprint of env3 |- t\n//│ > if true (id id) add\n//│ ═══[RUNTIME ERROR] Error: Cannot unify Int with Int -> Int\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/ListPredicates.mls",
    "content": ":js\n\nopen annotations\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\n\nopen Stack\n\nfun contains(xs, x) = if xs is\n  hd :: tl and { hd === x then true, else tl contains(x) }\n  Nil then false\n\nlet list1 = 1 :: 2 :: 3 :: Nil\n//│ list1 = Cons(1, Cons(2, Cons(3, Nil)))\n\nlist1 contains of 3\n//│ = true\n\nlist1 contains of 4\n//│ = false\n\n// Apply a pattern to a list, returns a list of unique elements if the output of\n// each element is unique, and rejects the list otherwise.\npattern Unique(pattern P) =\n  Nil | (\n    ((((P as hd) :: (Unique(P) as tl)) =>\n      let there = tl contains(hd)\n      [there, if there then tl else hd :: tl]) as [false, list]) => list)\n\nlist1 is Unique(_)\n//│ = true\n\n:expect false\nlist1 is Unique((Num as x) => x.toString().length)\n//│ = false\n\nfun addProperty(obj, k, v) = (...obj, (k): v)\naddProperty of (a: 1), \"b\", 2\n//│ = {a: 1, b: 2}\n\n// A workaround for the above issue.\nfun addProperty(obj, k, v) =\n  let newObj = Object.fromEntries of [[k, v]]\n  (...obj, ...newObj)\naddProperty of (a: 1), \"b\", 2\n//│ = {a: 1, b: 2}\n\n// I forgot the syntax of empty object.\nfun emptyObject = Object.fromEntries of []\n\n// Convert a list of pairs to a map-like object\npattern ListToObject = (Nil =>  emptyObject) | (([Str as k, v] :: (ListToObject as rest)) => addProperty(rest, k, v))\n\nfun toObject(ps) = if ps is ListToObject as obj then obj else emptyObject\n\nprint of toObject of [\"a\", 1] :: [\"b\", 2] :: Nil\n//│ > {b: 2, a: 1}\n\nprint of toObject of 0 :: Nil\n//│ > {}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/Negation.mls",
    "content": ":js\n\npattern NonZero = ~0\n\n0 is NonZero\n//│ = false\n\n1 is NonZero\n//│ = true\n\n-1 is NonZero\n//│ = true\n\npattern HomogeneousCoordinate = ((:x, :y, w: ~0 as w)) => (x: x / w, y: y / w)\n\n(x: 0, y: 0, w: 0) is HomogeneousCoordinate\n//│ = false\n\n(x: 0, y: 0, w: 1) is HomogeneousCoordinate\n//│ = true\n\nfun flatten(xyw) = if xyw is HomogeneousCoordinate as xy then xy\n\nflatten of x: 0, y: 0, w: 1\n//│ = {x: 0, y: 0}\n\nflatten of x: 4, y: 4, w: 2\n//│ = {x: 2, y: 2}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/PrecedenceClimbStackParse.mls",
    "content": ":js\n\n\nimport \"../../../mlscript-compile/Stack.mls\"\nopen Stack\n\n\n\npattern Ident = (\"a\" ..= \"z\") ~ (Ident | \"\")\n\ndata class Subexpr with\n  constructor\n    Id(name: Str)\n    Op(lhs: Subexpr, op: Str, rhs: Subexpr)\ndata class Expr(sub: Subexpr, prec: Int)\n\n\npattern AtPrec(str, prec) = str as (\n  | ( \"+\" => 5 )\n  | ( \"*\" => 2 )\n  ) as prec\n\nfun f(x) = if x is AtPrec(op, p) then [op, p]\nf(\"+\")\n//│ = [\"+\", 5]\nf(\"*\")\n//│ = [\"*\", 2]\n\n\npattern ParseStep =\n  | (Ident(name) :: rest) =>\n      Expr(Id(name), 0) :: rest\n  | (Expr(e1, p1) :: AtPrec(op, p) :: rest where p1 < p) =>\n      Expr(e1, p) :: op :: rest\n  | (Expr(e1, p1) :: AtPrec(op, p) :: Expr(e2, p2) :: rest where p1 >= p and p2 >= p) =>\n      Expr(Op(e1, op, e2), p) :: rest\n  | ((Expr as e1) :: AtPrec(op, _) :: ParseStep(rest)) =>\n      e1 :: op :: rest\n  | ((Expr as e1) :: AtPrec(op, p) :: Expr(e2, p2) :: rest where p2 < p) =>\n      e1 :: op :: Expr(e2, p) :: rest\n  | (\"(\" :: Expr(e, p) :: \")\" :: rest) =>\n      Expr(e, 0) :: rest\n  | (\"(\" :: ParseStep(rest)) =>\n      \"(\" :: rest\n\npattern Parse = (ParseStep as Parse) | (\n    | ((Expr as e) :: Nil) => [\"Success:\", e]\n    | toks => [\"Failure: can't parse:\", toks]\n  )\n\nfun parse(tokens) = print of ...\n  if tokens is Parse(res) then res\n\n\nparse(Nil)\n//│ > Failure: can't parse: Nil\n\nparse(\"x\" :: Nil)\n//│ > Success: Expr(Id(\"x\"), 0)\n\nlet input = \"x\" :: \"+\" :: \"y\" :: Nil\n//│ input = Cons(\"x\", Cons(\"+\", Cons(\"y\", Nil)))\n\nparse(input)\n//│ > Success: Expr(Op(Id(\"x\"), \"+\", Id(\"y\")), 5)\n\nif input is ParseStep as rest then rest\n//│ = Cons(Expr(Id(\"x\"), 0), Cons(\"+\", Cons(\"y\", Nil)))\n\nparse(\"(\" :: \"x\" :: \")\" :: Nil)\n//│ > Success: Expr(Id(\"x\"), 0)\n\nparse(\"a\" :: \"*\" :: \"x\" :: \"+\" :: \"y\" :: Nil)\n//│ > Success: Expr(Op(Op(Id(\"a\"), \"*\", Id(\"x\")), \"+\", Id(\"y\")), 5)\n\nparse(\"a\" :: \"+\" :: \"x\" :: \"*\" :: \"y\" :: Nil)\n//│ > Success: Expr(Op(Id(\"a\"), \"+\", Op(Id(\"x\"), \"*\", Id(\"y\"))), 5)\n\nparse(\"(\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: Nil)\n//│ > Success: Expr(Op(Id(\"x\"), \"+\", Id(\"y\")), 0)\n\nparse(\"a\" :: \"+\" :: \"(\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: Nil)\n//│ > Success: Expr(Op(Id(\"a\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\"))), 5)\n\nparse(\"a\" :: \"+\" :: \"(\" :: \"b\" :: \"+\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: Nil)\n//│ > Success: Expr(Op(Id(\"a\"), \"+\", Op(Op(Id(\"b\"), \"+\", Id(\"x\")), \"+\", Id(\"y\"))), 5)\n\n:silent\nlet input = \"a\" :: \"+\" :: \"(\" :: \"b\" :: \"+\" :: \"(\" :: \"x\" :: \"+\" :: \"y\" :: \")\" :: \")\" :: Nil\n\nparse(input)\n//│ > Success: Expr(Op(Id(\"a\"), \"+\", Op(Id(\"b\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\")))), 5)\n\n\n\n// * These also work:\n\n\npattern Parse = (ParseStep as Parse) | _\nfun parse(tokens) = print of ...\n  if tokens is Parse(res) and res is\n    (Expr as e) :: Nil then [\"Success:\", e]\n    toks then [\"Failure: can't parse:\", toks]\n\nparse(input)\n//│ > Success: Expr(Op(Id(\"a\"), \"+\", Op(Id(\"b\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\")))), 5)\n\n\nfun parse(tokens) =\n  fun go = case\n    ParseStep as stack then go(stack)\n    (Expr as e) :: Nil then [\"Success:\", e]\n    toks then [\"Failure: can't parse:\", toks]\n  print of ...go(tokens)\n\nparse(input)\n//│ > Success: Expr(Op(Id(\"a\"), \"+\", Op(Id(\"b\"), \"+\", Op(Id(\"x\"), \"+\", Id(\"y\")))), 5)\n\n\n\n// * Other related example definitions:\n\n\npattern AtPrec =\n  | ( \"+\" => 5 )\n  | ( \"*\" => 2 )\n\nassert \"+\" is AtPrec(n), n\n//│ = 5\n\nfun f(x) =\n  assert x is str as AtPrec as prec\n  [str, prec]\n\nf(\"+\")\n//│ = [\"+\", 5]\nf(\"*\")\n//│ = [\"*\", 2]\n\n// * Note: this fails due to `,` terminating the function scope...\n:e\nfun f(x) = assert x is str as AtPrec as prec, [str, prec]\n//│ ╔══[COMPILATION ERROR] Name not found: str\n//│ ║  l.142: \tfun f(x) = assert x is str as AtPrec as prec, [str, prec]\n//│ ╙──       \t                                               ^^^\n//│ ╔══[COMPILATION ERROR] Name not found: prec\n//│ ║  l.142: \tfun f(x) = assert x is str as AtPrec as prec, [str, prec]\n//│ ╙──       \t                                                    ^^^^\n//│ ═══[RUNTIME ERROR] This code cannot be run as its compilation yielded an error.\n\n\npattern Oper(str, prec) = str as AtPrec as prec\n\nassert \"+\" is Oper as p, p\n//│ = [\"+\", 5]\n\nassert \"+\" is Oper(s, p), [s, p]\n//│ = [\"+\", 5]\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/Record.mls",
    "content": ":js\n\nopen annotations\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\n// Compute Body Mass Index (BMI) from weight (kg) and height (m)\npattern CalculateBMI = ((:weight, :height)) => weight / (height * height)\n\npattern Rounded = (Num as value) => Math.round(value)\n\n(weight: 70, height: 1.75) is CalculateBMI as Rounded(22)\n//│ = false\n\n(weight: 70, height: 1.75) is CalculateBMI as Rounded(23)\n//│ = true\n\npattern RoundedBMI = CalculateBMI as Rounded\n\nfun bmi(record) = if record is RoundedBMI as value then value\n\nbmi of weight: 70, height: 1.75\n//│ = 23\n\n:re\nbmi of weight: 70\n//│ ═══[RUNTIME ERROR] Error: match error\n\n// This pattern is useful because it turns a pattern into a function that\n// returns `Some` if the pattern matches, and `None` otherwise.\npattern MatchOrNone(pattern P) = ((P as x) => Some(x)) | (_ => None)\n\nfun bmi(record) = if record is MatchOrNone(RoundedBMI) as value then value\n\n:e\n// alternatively?\nfun bmi'(record) = if record is MatchOrNone[RoundedBMI] as value then value\n//│ ╔══[COMPILATION ERROR] Unrecognized pattern (application).\n//│ ║  l.39: \tfun bmi'(record) = if record is MatchOrNone[RoundedBMI] as value then value\n//│ ╙──      \t                                ^^^^^^^^^^^^^^^^^^^^^^^\n\n:expect Some(23)\nbmi of weight: 70, height: 1.75\n//│ = Some(23)\n\nbmi of height: 1.75\n//│ = None\n\n:todo // Make it happen!\nfun bmi'(record) = if record is (@compile MatchOrNone(RoundedBMI)) as value then value\n//│ ╔══[COMPILATION ERROR] Pattern chaining is not supported in pattern compilation.\n//│ ║  l.20: \tpattern RoundedBMI = CalculateBMI as Rounded\n//│ ╙──      \t                     ^^^^^^^^^^^^^^^^^^^^^^^\n\n// Calculate the area of different shapes\npattern ShapeArea = \n  (((:radius)) => Math.PI * radius * radius) |  // Circle\n  (((:width, :height)) => width * height) |     // Rectangle\n  (((:base, :height)) => base * height / 2)     // Triangle\n\nfun area(shape) = if shape is ShapeArea as a then Some(a) else None\n\narea of (radius: 10)\n//│ = Some(314.1592653589793)\n\narea of (width: 10, height: 20)\n//│ = Some(200)\n\narea of (base: 10, height: 20)\n//│ = Some(100)\n\n// Fields are tested in the same order as they are written in the pattern.\narea of (radius: 10, height: 20)\n//│ = Some(314.1592653589793)\n\narea of (width: 10, height: 20, base: 10)\n//│ = Some(200)\n\nfun area__compiled(shape) = if shape is (@compile ShapeArea) as a then Some(a) else None\n\narea__compiled of (radius: 10)\n//│ = Some(314.1592653589793)\n\narea__compiled of (width: 10, height: 20)\n//│ = Some(200)\n\narea__compiled of (base: 10, height: 20)\n//│ = Some(100)\n\narea__compiled of (width: 10, height: 20, base: 10)\n//│ = Some(200)\n\n// Convert between different number systems\npattern NumberSystem = \n  | ((:digits, radix: \"x\")) => parseInt(digits, 16)\n  | ((:digits, radix: \"o\")) => parseInt(digits, 8)\n  | ((:digits, radix: \"b\")) => parseInt(digits, 2)\n\nfun parseIntegerLiteral(value) = if\n  value is \"0\" ~ ((\"x\" | \"o\" | \"b\") as radix) ~ digits and\n    (:radix, :digits) is NumberSystem as value then Some(value)\n  else None\n\nparseIntegerLiteral of \"0xFF\"\n//│ = Some(255)\n\nparseIntegerLiteral of \"0b11111111\"\n//│ = Some(255)\n\nparseIntegerLiteral of \"0o377\"\n//│ = Some(255)\n\npattern IntegerLiteral =\n  (\"0\" ~ ((\"x\" | \"o\" | \"b\") as radix) ~ digits) => (:radix, :digits)\n\nfun parseIntegerLiteral(value) = if\n  value is IntegerLiteral as output then Some(output)\n  else None\n\nparseIntegerLiteral of \"0x1234\"\n//│ = Some({radix: \"x\", digits: \"1234\"})\n\nparseIntegerLiteral of \"0b0000111100001111\"\n//│ = Some({radix: \"b\", digits: \"0000111100001111\"})\n\nparseIntegerLiteral of \"0o673264673\"\n//│ = Some({radix: \"o\", digits: \"673264673\"})\n\nparseIntegerLiteral of \"0k1234\"\n//│ = None\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/examples/TupleSpread.mls",
    "content": ":js\n\n// Extract the first and last elements of a list\npattern FirstLast = ([x, ..._, y] => [x, y])\n\n[0, 1, 2] is FirstLast([0, 2])\n//│ = true\n\n[5, 8] is FirstLast([5, 8])\n//│ = true\n\n[] is FirstLast\n//│ = false\n\n[1] is FirstLast\n//│ = false\n\n// Test if a list is a palindrome. This example is not very good because it\n// outputs a boolean value, rather than rejecting the input.\npattern TestPalindrome =\n  | [x, ...TestPalindrome as m, y] => m && x == y\n  | ([_] | []) => true\n  | _ => false\n\n[1, 2, 1] is TestPalindrome(true)\n//│ = true\n\n[] is TestPalindrome(true)\n//│ = true\n\n[1] is TestPalindrome(true)\n//│ = true\n\n[1, 2] is TestPalindrome(true)\n//│ = false\n\n// A better palindrome tuple, which matches palindrome sequences exactly.\npattern Palindrome =\n  (([head, ...Palindrome, last] => head === last) as true) | [_] | []\n\n[1, 2, 2, 1] is Palindrome\n//│ = true\n\n[] is Palindrome\n//│ = true\n\n[1] is Palindrome\n//│ = true\n\n[1, 2] is Palindrome\n//│ = false\n\n[1, 2, 3] is Palindrome\n//│ = false\n\n[1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1] is Palindrome\n//│ = true\n\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Stack\n\npattern StackLike = ([] => Nil) | ([x, ...StackLike as xs] => x :: xs)\n\n[] is StackLike(Nil)\n//│ = true\n\n[] is StackLike(1 :: Nil)\n//│ = false\n\n[1] is StackLike(1 :: Nil)\n//│ = true\n\n:expect true\n[1, 2, 3, 4, 5] is StackLike(1 :: 2 :: 3 :: 4 :: 5 :: Nil)\n//│ = true\n\n[1, 2, 3, 4, 5] is StackLike as (1 :: 2 :: 3 :: 4 :: 5 :: Nil)\n//│ = true\n\n:expect false\n[1, 2, 3, 4, 5] is StackLike(1 :: 2 :: 3 :: 4 :: Nil)\n//│ = false\n\n// Extract elements at even indices in a tuple.\npattern ElementAtEvenIndex = \n  ([] => []) | \n  ([x] => [x]) | \n  ([x, _, ...ElementAtEvenIndex as rest] => [x, ...rest])\n\n[] is ElementAtEvenIndex([])\n//│ = true\n\n[1] is ElementAtEvenIndex([1])\n//│ = true\n\n[1, 2, 3, 4, 5] is ElementAtEvenIndex([1, 3, 5])\n//│ = true\n\n[1, 2, 3, 4, 5] is ElementAtEvenIndex([1, 3])\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/nondeterminism/BitArithmetic.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata\n  class\n    (&&) And(lhs: Bool, rhs: Bool)\n    (||) Or(lhs: Bool, rhs: Bool)\n    Not(arg: Bool)\n\npattern Truthy =\n  true | And(Truthy, Truthy) | Or(Truthy, Truthy) |\n  Or(Truthy, Falsy) | Or(Falsy, Truthy) | Not(Falsy)\npattern Falsy =\n  false | And(Falsy, Falsy) | And(Falsy, Truthy) |\n  And(Truthy, Falsy) | Or(Falsy, Falsy) | Not(Truthy)\n\n:expect [true, false, false, true]\n[\n  true is @compile Truthy,\n  false is @compile Truthy,\n  true is @compile Falsy,\n  false is @compile Falsy\n]\n//│ = [true, false, false, true]\n\nfun isTruthy(value) = value is @compile Truthy\n\nfun isFalsy(value) = value is @compile Falsy\n\nfun isTruthy'(value) = value is Truthy\n\nfun isFalsy'(value) = value is Falsy\n\n:global\n:expect true\n\n// Test each case of `Truthy`.\n// ===========================\n\nisTruthy of true\n//│ = true\n\nisTruthy' of true\n//│ = true\n\nisTruthy of true && true\n//│ = true\n\nisTruthy' of true && true\n//│ = true\n\nisTruthy of true || true\n//│ = true\n\nisTruthy' of true || true\n//│ = true\n\nisTruthy of true || false\n//│ = true\n\nisTruthy' of true || false\n//│ = true\n\nisTruthy of false || true\n//│ = true\n\nisTruthy' of false || true\n//│ = true\n\nisTruthy of Not of false\n//│ = true\n\nisTruthy' of Not of false\n//│ = true\n\n// Test each case of `Falsy`.\n// ==========================\n\nisFalsy of false\n//│ = true\n\nisFalsy of false && false\n//│ = true\n\n// This example requires the ability to handle non-determinism.\nisFalsy of false && true\n//│ = true\n\nisFalsy' of false && true\n//│ = true\n\nisFalsy of true && false\n//│ = true\n\nisFalsy' of true && false\n//│ = true\n\nisFalsy of false || false\n//│ = true\n\nisFalsy' of false || false\n//│ = true\n\nisFalsy of Not of true\n//│ = true\n\nisFalsy' of Not of true\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/nondeterminism/EvenOddTree.mls",
    "content": ":js\n\nopen annotations { compile }\n\nobject A\nobject B\n\ndata class Node[T](left: Node[T], value: T, right: Node[T])\n\n// The patterns generate trees that have odd or even numbers of node `A`.\n\npattern OddTree =\n  | A\n  | Node(EvenTree, A, EvenTree) | Node(OddTree, A, OddTree)\n  | Node(EvenTree, B, OddTree) | Node(OddTree, B, EvenTree)\npattern EvenTree =\n  | B\n  | Node(EvenTree, A, OddTree) | Node(OddTree, A, EvenTree)\n  | Node(EvenTree, B, EvenTree) | Node(OddTree, B, OddTree)\n\nfun a(lc, rc) = Node(lc, A, rc)\n\nfun b(lc, rc) = Node(lc, B, rc)\n\n:global\n:expect true\n\n// Test each case of `EvenTree`.\n// =============================\n\nB is @compile EvenTree\n//│ = true\n\nB is EvenTree\n//│ = true\n\nnot A is @compile EvenTree\n//│ = true\n\nnot A is EvenTree\n//│ = true\n\nnot a(B, B) is @compile EvenTree\n//│ = true\n\nnot a(B, B) is EvenTree\n//│ = true\n\na(B, A) is @compile EvenTree\n//│ = true\n\na(B, A) is EvenTree\n//│ = true\n\na(A, B) is @compile EvenTree\n//│ = true\n\na(A, B) is EvenTree\n//│ = true\n\nb(A, A) is @compile EvenTree\n//│ = true\n\nb(A, A) is EvenTree\n//│ = true\n\nb(B, B) is @compile EvenTree\n//│ = true\n\nb(B, B) is EvenTree\n//│ = true\n\n// Test each case of `OddTree`.\n// ============================\n\nA is @compile OddTree\n//│ = true\n\nA is OddTree\n//│ = true\n\na(B, B) is @compile OddTree\n//│ = true\n\na(B, B) is OddTree\n//│ = true\n\na(A, A) is @compile OddTree\n//│ = true\n\na(A, A) is OddTree\n//│ = true\n\nb(B, A) is @compile OddTree\n//│ = true\n\nb(B, A) is OddTree\n//│ = true\n\nb(A, B) is @compile OddTree\n//│ = true\n\nb(A, B) is OddTree\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/nondeterminism/LaRbTree.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata class Pair[S, T](val first: S, val second: T)\n\nobject A\nobject B\n\n// The patterns generate exactly those trees whose leftmost leaf is labeled `A`\n// and whose rightmost leaf is labeled `B`.\n\npattern LaRbTree = Pair(LaTree, RbTree)\npattern LaTree = A | Pair(A, AnyTree)\npattern RbTree = B | Pair(AnyTree, B)\npattern AnyTree = A | B | Pair(AnyTree, AnyTree)\n\n:global\n:expect true\n\nA is @compile LaTree\n//│ = true\n\nB is @compile RbTree\n//│ = true\n\nA is @compile AnyTree\n//│ = true\n\nB is @compile AnyTree\n//│ = true\n\nPair(A, B) is @compile LaRbTree\n//│ = true\n\nPair(Pair(A, A), Pair(B, B)) is @compile LaRbTree\n//│ = true\n\nPair(Pair(A, B), B) is @compile LaRbTree\n//│ = true\n\nPair(A, Pair(A, B)) is @compile LaRbTree\n//│ = true\n\nPair(Pair(A, A), B) is @compile LaRbTree\n//│ = true\n\nPair(A, Pair(B, B)) is @compile LaRbTree\n//│ = true\n\n:global\n:expect false\n\nA is @compile LaRbTree\n//│ = false\n\nB is @compile LaRbTree\n//│ = false\n\nPair(B, A) is @compile LaRbTree\n//│ = false\n\nPair(A, A) is @compile LaRbTree\n//│ = false\n\nPair(B, B) is @compile LaRbTree\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/parametric/EtaConversion.mls",
    "content": ":js\n\npattern Nullable(pattern T) = T | null\n\n// Using patterns as pattern argument directly should not create local objects.\n\npattern Zero = 0\n\n:ucs normalized\n0 is Nullable(Zero)\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    let tmp:scrut = 0\n//│ >    let tmp:patternArgument0$ = member:Zero‹pattern:Zero›\n//│ >    let tmp:unapplyResult = (member:Nullable⁰.)unapply(tmp:patternArgument0$⁰, tmp:scrut⁰)\n//│ >    tmp:unapplyResult is (tmp:runtime⁰.)MatchSuccess‹class:MatchSuccess›(output, bindings) then true\n//│ >    else false\n//│ = true\n\nimport \"../../../mlscript-compile/Char.mls\"\n\n:ucs normalized\nfun foo(x) = x is Nullable(Char.Letter)\n//│ Normalized:\n//│ >  ‹if|while›\n//│ >    let tmp:patternArgument0$ = (member:Char‹module:Char›.)Letter‹pattern:Letter›\n//│ >    let tmp:unapplyResult = (member:Nullable⁰.)unapply(tmp:patternArgument0$¹, x⁰)\n//│ >    tmp:unapplyResult is (tmp:runtime⁰.)MatchSuccess‹class:MatchSuccess›(output, bindings) then true\n//│ >    else false\n\nfoo of null\n//│ = true\n\nfoo of \"A\"\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/parametric/HigherOrderPattern.mls",
    "content": ":js\n\nopen annotations { compile }\n\npattern Nullable(pattern T) = null | T\n\nobject A\n\n:e\nnull is @compile Nullable\n//│ ╔══[COMPILATION ERROR] Pattern `Nullable` has one pattern parameter.\n//│ ║  l.5: \tpattern Nullable(pattern T) = null | T\n//│ ║       \t                         ^\n//│ ╟── But zero pattern arguments were provided.\n//│ ║  l.10: \tnull is @compile Nullable\n//│ ╙──      \t                 ^^^^^^^^\n//│ = false\n\n:e\nnull is @compile Nullable(A, A)\n//│ ╔══[COMPILATION ERROR] Pattern `Nullable` has one pattern parameter.\n//│ ║  l.5: \tpattern Nullable(pattern T) = null | T\n//│ ║       \t                         ^\n//│ ╟── But two pattern arguments were provided.\n//│ ║  l.20: \tnull is @compile Nullable(A, A)\n//│ ╙──      \t                 ^^^^^^^^^^^^^\n//│ = false\n\npattern Nullable(pattern T) = null | T\n\nnull is @compile Nullable(Int)\n//│ = true\n\nA is @compile Nullable(A)\n//│ = true\n\n2 is @compile Nullable(1 | 2)\n//│ = true\n\ndata class Pair[A, B](val first: A, val second: B)\n\npattern Stack(pattern T) = null | Pair(T, Stack(T))\n\nnull is @compile Stack(A)\n//│ = true\n\nfun (#:) pair(a, b) = Pair(a, b)\n\nA #: null is @compile Stack(A)\n//│ = true\n\nA #: A #: null is @compile Stack(A)\n//│ = true\n\nA #: A #: A #: null is @compile Stack(A)\n//│ = true\n\nobject B\n\nA #: B #: A #: null is @compile Stack(A)\n//│ = false\n\nA #: B #: A #: null is @compile Stack(B)\n//│ = false\n\nlet zeroOne = 0 #: 1 #: null\nlet oneZero = 1 #: 0 #: null\n//│ oneZero = Pair(1, Pair(0, null))\n//│ zeroOne = Pair(0, Pair(1, null))\n\n:global\n:expect true\n\nA #: B #: A #: null is @compile Stack(A | B)\n//│ = true\n\nA #: B #: A #: null is @compile Stack(B | A)\n//│ = true\n\nzeroOne is @compile Stack(0 | 1)\n//│ = true\n\noneZero is @compile Stack(0 | 1)\n//│ = true\n\nnull #: null is @compile Stack(Stack(0 | 1))\n//│ = true\n\nzeroOne #: null is @compile Stack(Stack(0 | 1))\n//│ = true\n\nnull #: (1 #: null) #: null is @compile Stack(Stack(0 | 1))\n//│ = true\n\nzeroOne #: oneZero #: null is @compile Stack(Stack(0 | 1))\n//│ = true\n\nzeroOne #: null #: oneZero #: null is @compile Stack(Stack(0 | 1))\n//│ = true\n\nnull #: zeroOne #: zeroOne #: null is @compile Stack(Stack(0 | 1))\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/parametric/ListLike.mls",
    "content": ":js\n\nopen annotations\n\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Stack\n\npattern ListLike(pattern T) = Nil | (T :: ListLike(T))\n\nfun isOddIntList(xs) = xs is ListLike(((Int as x) => x % 2 === 1) as true)\n\nisOddIntList of Nil\n//│ = true\n\nisOddIntList of 1 :: 3 :: Nil\n//│ = true\n\nisOddIntList of 1 :: 2 :: 3 :: Nil\n//│ = false\n\nisOddIntList of 1 :: 71 :: \"bruh\" :: Nil\n//│ = false\n\nisOddIntList of \"hello\" :: \"world\" :: Nil\n//│ = false\n\npattern Nullable(pattern T) = null | T\n\nfun isNullableIntList(xs) = xs is @compile ListLike(Nullable(Int))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/parametric/Nullable.mls",
    "content": ":js\n\nopen annotations\n\npattern Null = null\n\nnull is Null\n//│ = true\n\npattern Nullable(pattern T) = null | T\n\n// This creates an inline object with `unapply` method and pass it to\n// `Nullable.unapply`.\nfun isPositiveOrNull(x) = x is Nullable(((Int as x) => x > 0) as true)\n\nisPositiveOrNull of 0\n//│ = false\n\nisPositiveOrNull of null\n//│ = true\n\nisPositiveOrNull of 1\n//│ = true\n\nisPositiveOrNull of -2\n//│ = false\n\n// No transformation, so the output is the same as the input.\n\nfun mightBeInt(x) =\n  if x is (@compile Nullable(Int)) as output then output\n\nmightBeInt of 42\n//│ = 42\n\nmightBeInt of null\n//│ = null\n\n:re\nmightBeInt of \"hello\"\n//│ ═══[RUNTIME ERROR] Error: match error\n\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Option { Some, None }\n\npattern Optional(pattern T) = (null => None) | ((T as x) => Some(x))\n\nnull is Optional(Int) as None\n//│ = true\n\n42 is Optional(Int) as Some(42)\n//│ = true\n\nnull is Optional(Int) as Some(42)\n//│ = false\n\n:e\n// Test the error message.\nfun toIntOption(x) = if x is (@compile Optional) as o then o\n//│ ╔══[COMPILATION ERROR] Pattern `Optional` has one pattern parameter.\n//│ ║  l.47: \tpattern Optional(pattern T) = (null => None) | ((T as x) => Some(x))\n//│ ║        \t                         ^\n//│ ╟── But zero pattern arguments were provided.\n//│ ║  l.60: \tfun toIntOption(x) = if x is (@compile Optional) as o then o\n//│ ╙──      \t                                       ^^^^^^^^\n\nfun toIntOption(x) = if x is (@compile Optional(Int)) as o then o\n\ntoIntOption of 42\n//│ = Some(42)\n\ntoIntOption of null\n//│ = None\n\n:re\ntoIntOption of \"hello\"\n//│ ═══[RUNTIME ERROR] Error: match error\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/recursion/BitSeq.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata class Pair[A, B](val first: A, val second: B)\n\npattern Bit = 0 | 1\n\n:expect true\n0 is @compile Bit\n//│ = true\n\n:expect true\n1 is @compile Bit\n//│ = true\n\n:expect false\n42 is @compile Bit\n//│ = false\n\npattern BitSeq = null | Pair(Bit, BitSeq)\n\n:global\n:expect true\n\nnull is @compile BitSeq\n//│ = true\n\nPair(0, null) is @compile BitSeq\n//│ = true\n\nPair(1, Pair(0, null)) is @compile BitSeq\n//│ = true\n\n:global\n:expect false\n\nPair(2, null) is @compile BitSeq\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/recursion/BitTree.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata class Pair[A, B](val first: A, val second: B)\n\npattern Bit = 0 | 1\n\n:expect true\n0 is @compile Bit\n//│ = true\n\n:expect true\n1 is @compile Bit\n//│ = true\n\n:expect false\n42 is @compile Bit\n//│ = false\n\npattern BitTree = null | Pair(Bit | BitTree, Bit | BitTree)\n\nnull is @compile BitTree\n//│ = true\n\nPair(null, null) is @compile BitTree\n//│ = true\n\npattern BitTreeAlt = null | Pair(BitTreeAlt | 0 | 1, BitTreeAlt | 0 | 1)\n\n:global\n:expect true\n\nnull is @compile BitTreeAlt\n//│ = true\n\nPair(null, null) is @compile BitTreeAlt\n//│ = true\n\nPair(0, null) is @compile BitTreeAlt\n//│ = true\n\nPair(0, Pair(0, null)) is @compile BitTreeAlt\n//│ = true\n\nPair(0, Pair(0, Pair(1, Pair(0, null)))) is @compile BitTreeAlt\n//│ = true\n\nPair(0, Pair(0, Pair(1, Pair(1, null)))) is @compile BitTreeAlt\n//│ = true\n\n:global\n:expect false\n\nPair(2, Pair(0, Pair(1, null))) is @compile BitTreeAlt\n//│ = false\n\nPair(0, Pair(0, Pair(2, null))) is @compile BitTreeAlt\n//│ = false\n\nPair(0, Pair(0, Pair(1, Pair(2, null)))) is @compile BitTreeAlt\n//│ = false\n\nPair(0, Pair(0, Pair(1, Pair(2, null)))) is @compile BitTreeAlt\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/recursion/LeafEvenOddTree.mls",
    "content": ":js\n\nopen annotations { compile }\n\nobject A\nobject B\ndata class Pair[A, B](first: A, second: B)\n\n[A, B]\n//│ = [A, B]\n\n// The patterns generate trees that have odd or even numbers of node `A`.\n// In this example, only leaves carry the value `A` or `B`. For each internal\n// node, the combination of its children uniquely determines the pattern.\n// Therefore, the definition is deterministic. See `EvenOddTree.mls` for a\n// non-deterministic example.\n\npattern OddTree = A | Pair(EvenTree, OddTree) | Pair(OddTree, EvenTree)\npattern EvenTree = B | Pair(EvenTree, EvenTree) | Pair(OddTree, OddTree)\n\nfun (##) pair(a, b) = Pair(a, b)\n\n:global\n:expect true\n\nB is @compile EvenTree\n//│ = true\n\nnot A is @compile EvenTree\n//│ = true\n\nB ## B is @compile EvenTree\n//│ = true\n\nA ## A is @compile EvenTree\n//│ = true\n\n(A ## A) ## (A ## A) is @compile EvenTree\n//│ = true\n\n(A ## A) ## (A ## A) ## (A ## A) is @compile EvenTree\n//│ = true\n\n((A ## A) ## (A ## A)) ## ((A ## A) ## (A ## A)) is @compile EvenTree\n//│ = true\n\n((A ## A) ## (A ## A)) ## ((A ## A) ## (B ## B)) is @compile EvenTree\n//│ = true\n\n:global\n:expect false\n\n((A ## A) ## (A ## B)) ## ((A ## A) ## (A ## B)) is @compile OddTree\n//│ = false\n\n((A ## A) ## (A ## A)) ## ((A ## A) ## (A ## B)) is @compile EvenTree\n//│ = false\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/recursion/NatBox.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata class Box[A](val value: A)\n\npattern NatBox = null | Box(NatBox)\n\nfun nat(n) = if n is 0 then null else Box(nat(n - 1))\n\nfun int(n) = if n is\n  null then 0\n  Box(x) then 1 + int(x)\n\n[nat(0), nat(1), nat(2), nat(3)]\n//│ = [null, Box(null), Box(Box(null)), Box(Box(Box(null)))]\n\nint(nat(42))\n//│ = 42\n\n// FIXME: why are we checking `Object` and `{ value }` patterns?\n:sir\n:expect true\nnat(0) is @compile NatBox\n//│ ———————————————| Lowered IR |———————————————————————————————————————————————————————————————————————\n//│ let scrut, matcher__NatBox$, matchSuccess, lambda⁰;\n//│ set scrut = nat⁰(0);\n//│ define lambda⁰ as fun lambda¹(input) {\n//│   let p_0$, value, value1, p_0$1, result0$, p_0$2, tmp, tmp1, tmp2, tmp3, tmp4;\n//│   match input\n//│     null =>\n//│       set tmp = true;\n//│       set p_0$ = tmp;\n//│       return p_0$\n//│     Box⁰ =>\n//│       match input\n//│         Object⁰ =>\n//│           match input\n//│             { value } =>\n//│               set value1 = input.value﹖;\n//│               set tmp1 = matcher__NatBox$(value1);\n//│               set tmp2 = { \"input\": value1, \"result\": tmp1 };\n//│               end\n//│             else\n//│               set tmp2 = { \"input\": null, \"result\": false };\n//│               end\n//│           end\n//│         else\n//│           set tmp2 = { \"input\": null, \"result\": false };\n//│           end\n//│       set value = tmp2;\n//│       set result0$ = value.result﹖;\n//│       match result0$\n//│         true =>\n//│           set tmp3 = true;\n//│           end\n//│         else\n//│           set tmp3 = false;\n//│           end\n//│       set p_0$1 = tmp3;\n//│       return p_0$1\n//│     else\n//│       set tmp4 = false;\n//│       set p_0$2 = tmp4;\n//│       return p_0$2\n//│   end\n//│ };\n//│ set matcher__NatBox$ = lambda¹;\n//│ set matchSuccess = matcher__NatBox$(scrut);\n//│ match matchSuccess\n//│   true =>\n//│     true\n//│   else\n//│     false\n//│ end\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n//│ = true\n\n:expect true\nnat(1) is @compile NatBox\n//│ = true\n\n:expect false\nBox(0) is @compile NatBox\n//│ = false\n\n:expect true\nnat(7) is @compile NatBox\n//│ = true\n\n:expect true\nnat(14) is @compile NatBox\n//│ = true\n\n:expect false\nBox(Box(Box(Box(Box(Box(Box(0))))))) is @compile NatBox\n//│ = false\n\npattern PosNatBox = Box(null | NatBox)\n\n:expect false\nnull is @compile PosNatBox\n//│ = false\n\nnat(1) is @compile PosNatBox\n//│ = true\n\n:expect true\nnat(2) is @compile PosNatBox\n//│ = true\n\n:expect true\nnat(3) is @compile PosNatBox\n//│ = true\n\n:expect false\nBox(Box(Box(Box(42)))) is @compile PosNatBox\n//│ = false\n\npattern EvenNatBox = Box(Box(null | EvenNatBox))\n\n:expect false\nnat(0) is @compile EvenNatBox\n//│ = false\n\n:expect false\nnat(1) is @compile EvenNatBox\n//│ = false\n\n:expect true\nnat(2) is @compile EvenNatBox\n//│ = true\n\n:expect false\nnat(3) is @compile EvenNatBox\n//│ = false\n\n:expect true\nnat(4) is @compile EvenNatBox\n//│ = true\n\n// Make the base case a new pattern.\n\npattern Zero = null\n\nnull is Zero\n//│ = true\n\npattern OddNatBox = Box(Zero | Box(OddNatBox))\n\n:expect false\nnat(0) is @compile OddNatBox\n//│ = false\n\n:expect true\nnat(1) is @compile OddNatBox\n//│ = true\n\n:expect false\nnat(2) is @compile OddNatBox\n//│ = false\n\n:expect true\nnat(3) is @compile OddNatBox\n//│ = true\n\n:expect false\nnat(4) is @compile OddNatBox\n//│ = false\n\n:expect false\nBox(Box(78)) is @compile OddNatBox\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/recursion/NullTree.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata class Pair[A, B](val first: A, val second: B)\n\npattern Null = null\n\n[null is Null, 0 is Null, false is Null]\n//│ = [true, false, false]\n\npattern Tree = Null | Pair(Tree, Tree)\n\nfun (##) concat(a, b) = Pair(a, b)\n\n0 ## 1\n//│ = Pair(0, 1)\n\n// Positive Test Cases\n// ===================\n\n:global\n:expect true\n\nnull is @compile Tree\n//│ = true\n\nnull ## null is @compile Tree\n//│ = true\n\n((null ## null) ## null) is @compile Tree\n//│ = true\n\nnull ## (null ## null) is @compile Tree\n//│ = true\n\n((null ## null) ## (null ## null)) is @compile Tree\n//│ = true\n\n// Negative Test Cases\n// ===================\n\n:global\n:expect false\n\n0 is @compile Tree\n//│ = false\n\n0 ## 0 is @compile Tree\n//│ = false\n\n0 ## null is @compile Tree\n//│ = false\n\nnull ## 0 is @compile Tree\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/recursion/SignBox.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata class Box[A](val value: A)\n\npattern Sign = -1 | 0 | 1\n\n[-1 is Sign, 0 is Sign, 1 is Sign]\n//│ = [true, true, true]\n\npattern SignBox = Box(Sign | SignBox)\n\n[\n  Box(-1) is @compile SignBox,\n  Box(0) is @compile SignBox,\n  Box(1) is @compile SignBox\n]\n//│ = [true, true, true]\n\n[\n  Box(Box(-1)) is @compile SignBox,\n  Box(Box(0)) is @compile SignBox,\n  Box(Box(1)) is @compile SignBox\n]\n//│ = [true, true, true]\n\n[\n  Box(Box(Box(-1))) is @compile SignBox,\n  Box(Box(Box(0))) is @compile SignBox,\n  Box(Box(Box(1))) is @compile SignBox\n]\n//│ = [true, true, true]\n\n:expect [false, false, false]\n[\n  Box(Box(Box(2))) is @compile SignBox,\n  Box(Box(Box(null))) is @compile SignBox,\n  -1 is SignBox\n]\n//│ = [false, false, false]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/regex/EmailAddress.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Char.mls\"\nimport \"../../../mlscript-compile/Iter.mls\"\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Iter { joined }\n\n// To match simple email addresses matched by the following regular expressions:\n// ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z]{2,}$\n\npattern UserNameLetter = Char.Letter | Char.Digit | \".\" | \"_\" | \"%\" | \"+\" | \"-\"\n\npattern Rep1(pattern S) = S ~ (Rep1(S) | \"\")\n\npattern UserName = Rep1(UserNameLetter)\n\n:expect true\n\"john.doe\" is UserName\n//│ = true\n\n:expect true\n\"jane_doe123\" is UserName\n//│ = true\n\n:expect true\n\"user+name%test\" is UserName\n//│ = true\n\n:expect false\n\"invalid@email!\" is UserName\n//│ = false\n\n:expect false\n\"\" is UserName\n//│ = false\n\n// Nested pattern arguments seem problematic.\npattern DomainSuffix = Rep1(\".\" ~ Char.Letter ~ Rep1(Char.Letter))\n\npattern DomainSuffixFragment = \".\" ~ Char.Letter ~ Rep1(Char.Letter)\n\n[\".com\", \".hk\", \".fr\", \".cn\"]\n  Iter.mapping of _ is DomainSuffixFragment\n  Iter.folded of true, _ && _\n//│ = true\n\n[\".\", \".a\", \"com\"]\n  Iter.mapping of _ is DomainSuffixFragment\n  Iter.folded of false, _ || _\n//│ = false\n\npattern DomainSuffix = Rep1(DomainSuffixFragment)\n\npattern DomainNameLetter = Char.Letter | Char.Digit | \"-\"\n\npattern DomainName = Rep1(DomainNameLetter)\n\n\"google\" is DomainName\n//│ = true\n\npattern Domain = DomainName ~ DomainSuffix\n\n\"google.com\" is Domain\n//│ = true\n\npattern Email = UserName ~ \"@\" ~ Domain\n\n:silent\nlet emails = [\n  \"example@example.com\"\n  \"john.doe@guardian.co.uk\"\n  \"alice_bob123@sub-domain.example.org\"\n  \"user+mailbox@my-domain.net\"\n  \"test.user%filter@service-provider.co.in\"\n  \"foo-bar@company-name.io\"\n  \"simple123@abc.xyz\"\n]\n\nemails\n  Iter.mapping of _ is Email\n  Iter.folded of true, _ && _\n//│ = true\n\nopen Stack\n\npattern CommaSep(pattern S) =\n  | ((S as head) ~ \",\" ~ (CommaSep(S) as tail)) => head :: tail\n  | (S as head) => head :: Nil\n  | \"\" => Nil\n\nfun parseEmails(input) =\n  if input is CommaSep(Email) as emails then emails else Nil\n\nparseEmails(emails.join(\",\")) Iter.fromStack() Iter.toArray()\n//│ = [\n//│   \"example@example.com\",\n//│   \"john.doe@guardian.co.uk\",\n//│   \"alice_bob123@sub-domain.example.org\",\n//│   \"user+mailbox@my-domain.net\",\n//│   \"test.user%filter@service-provider.co.in\",\n//│   \"foo-bar@company-name.io\",\n//│   \"simple123@abc.xyz\"\n//│ ]\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/regex/EmptyString.mls",
    "content": ":js\n\npattern Oops = \"\" ~ (Oops | \"\")\n\n:re\n:todo\n\"\" is Oops\n//│ ═══[RUNTIME ERROR] RangeError: Maximum call stack size exceeded\n\n\npattern Funny = \"\" ~ \"\" ~ \"\"\n\n\"\" is Funny\n//│ = true\n\npattern Funny = \"\" ~ \"hello\" ~ \"\"\n\n\"hello\" is Funny\n//│ = true\n\n\"\" is Funny\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/regex/Identifier.mls",
    "content": ":js\n\nopen annotations\n\nfun check(pred, what) = Array.from(length: 10).forEach of (_, i, _) =>\n  let n = i.toString()\n  print of n, (if pred(n) then \"is\" else \"is not\"), what\n\npattern Zero = \"0\"\n\n:expect true\n\"0\" is Zero\n//│ = true\n\npattern Binary = \"0\" | \"1\"\n\n// Currently, we expand range patterns into disjunction.\nfun isBinary(x) = x is @compile Binary\n\ncheck of isBinary, \"binary\"\n//│ > 0 is binary\n//│ > 1 is binary\n//│ > 2 is not binary\n//│ > 3 is not binary\n//│ > 4 is not binary\n//│ > 5 is not binary\n//│ > 6 is not binary\n//│ > 7 is not binary\n//│ > 8 is not binary\n//│ > 9 is not binary\n\n:expect false\n\"2\" is Binary\n//│ = false\n\npattern Digit = \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\"\n\n:expect true\n\"0\" is Digit\n//│ = true\n\n:expect true\n\"9\" is Digit\n//│ = true\n\n:expect false\n\"a\" is Digit\n//│ = false\n\nfun isDigit(x) = x is @compile Digit\n\ncheck of isDigit, \"digit\"\n//│ > 0 is digit\n//│ > 1 is digit\n//│ > 2 is digit\n//│ > 3 is digit\n//│ > 4 is digit\n//│ > 5 is digit\n//│ > 6 is digit\n//│ > 7 is digit\n//│ > 8 is digit\n//│ > 9 is digit\n\npattern Lower = \"a\"..=\"z\"\n\n:expect true\n\"a\" is Lower\n//│ = true\n\n:expect true\n\"z\" is Lower\n//│ = true\n\n:expect false\n\"0\" is Lower\n//│ = false\n\npattern Upper = \"A\"..=\"Z\"\n\n:expect true\n\"A\" is Upper\n//│ = true\n\n:expect true\n\"Q\" is Upper\n//│ = true\n\n:expect false\n\"b\" is Upper\n//│ = false\n\npattern Letter = Lower | Upper\n\n:expect true\n\"b\" is Letter\n//│ = true\n\n:expect true\n\"V\" is Letter\n//│ = true\n\n:expect false\n\"0\" is Letter\n//│ = false\n\n:expect false\n\"9\" is Letter\n//│ = false\n\n// Inspect the generated code. The use of `Map` makes the expanded disjunction\n// out of order. I wonder if we should use a `SeqMap` for literals.\nfun isLetter(x) = x is @compile Letter\n\nisLetter of \"a\"\n//│ = true\n\nisLetter of \"0\"\n//│ = false\n\npattern Word = Letter ~ (Word | \"\")\n\n:expect false\n\"\" is Word\n//│ = false\n\n:expect true\n\"b\" is Word\n//│ = true\n\n:expect true\n\"pattern\" is Word\n//│ = true\n\n:expect false\n\"b0rked\" is Word\n//│ = false\n\n:e\nfun isWord(x) = x is @compile Word\n//│ ╔══[COMPILATION ERROR] String concatenation is not supported in pattern compilation.\n//│ ║  l.120: \tpattern Word = Letter ~ (Word | \"\")\n//│ ╙──       \t               ^^^^^^^^^^^^^^^^^^^\n\n// Unsupported patterns are equivalent to `Never`.\nisWord of \"pattern\"\n//│ = false\n\npattern ManyDigits = (\"0\" ..= \"9\") ~ (ManyDigits | \"\")\n\n:expect true\n\"0\" is ManyDigits\n//│ = true\n\n:expect true\n\"42\" is ManyDigits\n//│ = true\n\n:expect true\n\"1234\" is ManyDigits\n//│ = true\n\npattern Integer = \"0\" | (\"1\" ..= \"9\") ~ (ManyDigits | \"\")\n\n:expect true\n\"0\" is Integer\n//│ = true\n\n:expect false\n\"012\" is Integer\n//│ = false\n\n:expect true\n\"42\" is Integer\n//│ = true\n\npattern IdentifierStart = Letter | \"_\"\n\npattern IdentifierBody = (Letter | Digit | \"_\") ~ (IdentifierBody | \"\")\n\npattern Identifier = IdentifierStart ~ (IdentifierBody | \"\")\n\n:expect true\n\"abc\" is Identifier\n//│ = true\n\n:expect true\n\"abc123\" is Identifier\n//│ = true\n\n:expect true\n\"abc_123\" is Identifier\n//│ = true\n\n:expect true\n\"_abc_123\" is Identifier\n//│ = true\n\n:expect false\n\"123abc\" is Identifier\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/regex/Number.mls",
    "content": ":js\n\npattern Digits = (\"0\"..=\"9\") ~ (Digits | \"\")\n\npattern Integer = \"0\" | (\"1\"..=\"9\") ~ (Digits | \"\")\n\npattern FractionalPart = \".\" ~ Digits\n\n\".1\" is FractionalPart\n//│ = true\n\npattern ExponentPart = (\"e\" | \"E\") ~ (\"+\" | \"-\" | \"\") ~ Integer\n\n\"e10\" is ExponentPart\n//│ = true\n\n\"e100\" is ExponentPart\n//│ = true\n\npattern Number = Integer ~ (FractionalPart | \"\") ~ (ExponentPart | \"\")\n\n// Test cases for Digits pattern\n// =============================\n:expect true\n\"123\" is Digits\n//│ = true\n\n:expect true\n\"0\" is Digits\n//│ = true\n\n:expect true\n\"9\" is Digits\n//│ = true\n\n:expect false\n\"a\" is Digits\n//│ = false\n\n\n// Test cases for Integer pattern\n// ==============================\n:expect true\n\"0\" is Integer\n//│ = true\n\n:expect true\n\"123\" is Integer\n//│ = true\n\n:expect false\n\"001\" is Integer\n//│ = false\n\n:expect false\n\"a\" is Integer\n//│ = false\n\n\n// Test cases for FractionalPart pattern\n// =====================================\n:expect true\n\".123\" is FractionalPart\n//│ = true\n\n:expect true\n\".0\" is FractionalPart\n//│ = true\n\n:expect false\n\".\" is FractionalPart\n//│ = false\n\n:expect false\n\"0.1\" is FractionalPart\n//│ = false\n\n\n// Test cases for ExponentPart pattern\n// ===================================\n:expect true\n\"e10\" is ExponentPart\n//│ = true\n\n:expect true\n\"E-10\" is ExponentPart\n//│ = true\n\n:expect true\n\"e+10\" is ExponentPart\n//│ = true\n\n:expect false\n\"e\" is ExponentPart\n//│ = false\n\n:expect false\n\"e1a\" is ExponentPart\n//│ = false\n\n\n// Test cases for Number pattern\n// =============================\n:expect true\n\"3.14\" is Number\n//│ = true\n\n:expect true\n\"42\" is Number\n//│ = true\n\n:expect true\n\"3.14e10\" is Number\n//│ = true\n\n:expect true\n\"1e100\" is Number\n//│ = true\n\n:expect true\n\"1234e-789\" is Number\n//│ = true\n\n:expect true\n\"0.0314E+2\" is Number\n//│ = true\n\n:expect true\n\"0.0314E-2\" is Number\n//│ = true\n\n:expect false\n\".\" is Number\n//│ = false\n\n:expect false\n\"e10\" is Number\n//│ = false\n\n:expect false\n\"3.14e\" is Number\n//│ = false\n\n:expect true\n\"3.14\" is Number\n//│ = true\n\n:expect true\n\"42\" is Number\n//│ = true\n\n:expect true\n\"3.14e10\" is Number\n//│ = true\n\n:expect true\n\"1e100\" is Number\n//│ = true\n\n:expect true\n\"1234e-789\" is Number\n//│ = true\n\n:expect true\n\"0.0314E+2\" is Number\n//│ = true\n\n:expect true\n\"0.0314E-2\" is Number\n//│ = true\n\n:expect true\n\"1.7976931348623158e+308\" is Number\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/regex/Separation.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Iter.mls\"\n\npattern TailLines(pattern L) =\n  | (\"\\n\" ~ (Lines(L) as t)) => t\n  | \"\" => []\npattern Lines(pattern L) = \n  | (((L as h) ~ (TailLines(L) as t)) => [h, ...t])\n  | \"\" => []\n\n:expect true\n\"hello\" is Lines(\"hello\")\n//│ = true\n\n:expect true\n\"hello\\nworld\" is Lines(\"hello\" | \"world\")\n//│ = true\n\n:expect false\n\"hello\\nworld\" is Lines(\"hello\")\n//│ = false\n\npattern Digit = \"0\" ..= \"9\"\n\npattern Integer = Digit ~ (Integer | \"\")\n\n\"12345\" is Integer\n//│ = true\n\nInteger.unapplyStringPrefix(\"123\")\n//│ = MatchSuccess([\"123\", \"\"], null)\n\n// Beautiful!\n\"123\\n456\\n789\" is Lines of Integer\n//│ = true\n\nfun parseIntegers(input) =\n  if input is (Lines of (Integer as n) => parseInt(n, 10)) as n then n\n\nparseIntegers of \"123\\n456\\n789\"\n//│ = [123, 456, 789]\n\n:e\n:re\n// We may need a shorthand syntax to obtain the result of pattern matching.\n// `t through P` means match `t` against `P` and returns the result.\n\"123\\n456\\n789\" through Lines(Integer) // ==> [123, 456, 789]\n//│ ╔══[COMPILATION ERROR] Illegal juxtaposition right-hand side (identifier).\n//│ ║  l.48: \t\"123\\n456\\n789\" through Lines(Integer) // ==> [123, 456, 789]\n//│ ╙──      \t                ^^^^^^^\n//│ ═══[RUNTIME ERROR] TypeError: Lines1 is not a function\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/regex/Simplification.mls",
    "content": ":js\n\npattern X = \"x\"\n\n\"x\" is X\n//│ = true\n\npattern Xs = X ~ (Xs | \"\")\n\n\"xxxxxxx\" is Xs\n//│ = true\n\npattern Xss = Xs ~ (Xss | \"\")\n\n\"xxxxxxxxxxxxxx\" is Xss\n//│ = true\n\npattern XsX = Xs ~ \"x\"\n\n// In the following tests, the left-hand side of concatenation should not\n// eagerly consume all letters. We should compile these string patterns even in\n// naive compilation, rather than just transliterate them.\n\n:expect true\n:fixme\n\"xxxxxxxxxxxxxx\" is XsX\n//│ ═══[RUNTIME ERROR] Expected: 'true', got: 'false'\n//│ = false\n\npattern XssX = Xss ~ \"x\"\n\n:expect true\n:fixme\n\"xxxxxxxx\" is XssX\n//│ ═══[RUNTIME ERROR] Expected: 'true', got: 'false'\n//│ = false\n\npattern XsXs = Xs ~ Xs\n\n:expect true\n:fixme\n\"xxxxxx\" is XsXs\n//│ ═══[RUNTIME ERROR] Expected: 'true', got: 'false'\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/regex/TailRepetition.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Runtime.mls\"\n\n\npattern Zero = \"0\"\n\nZero\n//│ = pattern Zero\n\n:expect true\nZero.unapply(\"0\") is Runtime.MatchSuccess\n//│ = true\n\n:expect true\n\"0\" is Zero\n//│ = true\n\npattern ManyZeros = \"0\" ~ (ManyZeros | \"\")\n\n:expect false\n\"\" is ManyZeros\n//│ = false\n\n:expect true\n\"0\" is ManyZeros\n//│ = true\n\n:expect true\n\"000\" is ManyZeros\n//│ = true\n\n:expect false\n\"0001\" is ManyZeros\n//│ = false\n\n:expect false\n\"1\" is ManyZeros\n//│ = false\n\n:expect false\n\"1000\" is ManyZeros\n//│ = false\n\npattern Rep(pattern S) = S ~ (Rep(S) | \"\")\n\n\"00000\" is Rep(\"0\")\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/specialization/SimpleList.mls",
    "content": ":js\n\nopen annotations { compile }\n\ndata class Pair[A, B](a: A, b: B)\n\ndata class Box[A](value: A)\n\ndata class Bowl[A](value: A)\n\ndata class Basket[A](value: A)\n\ndata class Triplet[A, B, C](a: A, b: B, c: C)\n\npattern Everything = _\n\n:expect true\n0 is @compile Everything\n//│ = true\n\n:expect true\nnull is @compile Everything\n//│ = true\n\npattern A = Box | Box\n\nBox(0) is @compile A\n//│ = true\n\npattern BoxedAnswer = Box(42)\n\nBox(42) is @compile BoxedAnswer\n//│ = true\n\npattern A_0 = Box(_) | Box(_)\n\nBox(0) is @compile A_0\n//│ = true\n\npattern A_1 = Box | Bowl\n\nBox(0) is @compile A_1\n//│ = true\n\nBowl(0) is @compile A_1\n//│ = true\n\npattern A_2 = _ | Box\n\npattern A_3 = Box | _\n\npattern A_4 = Box(_) | Bowl(_)\n\npattern A_3 = Box(Box) | Bowl\n\npattern B = Box(Box) | Bowl(Box)\n\npattern B_0 = Box(Box) | Box(Bowl)\n\npattern C = Box(Box(Box))\n\npattern C_1 = Box(Box | Bowl)\n\npattern C_2 = Box(Box | Box)\n\npattern C_2 = Box(Box | Bowl | Box)\n\npattern D = Box(Box(Box) | Bowl)\n\npattern D_0 = Box(Box(Box) | Box(Bowl))\n\npattern D_1 = Box(Box(Bowl) | Box)\n\npattern D_2 = Box(Bowl | Bowl | Bowl)\n\npattern D_2 = Box(Box(Bowl) | Box(Basket) | Box(Box))\n\npattern E = Box(Box(Box) | Bowl(Box(Basket)))\n\npattern F = Pair(Pair(Box, Bowl), Pair(Box, Basket))\n\npattern F_0 = Pair(Box, Bowl)\n\n:expect true\nPair(Box(42), Bowl(42)) is @compile F_0\n//│ = true\n\npattern F_1 = Pair(Box, Box) | Pair(Box, Bowl)\n\n:expect true\nPair(Box(42), Box(42)) is @compile F_1\n//│ = true\n\n:expect true\nPair(Box(42), Bowl(42)) is @compile F_1\n//│ = true\n\n:expect false\nPair(Box(42), Basket(42)) is @compile F_1\n//│ = false\n\n:expect false\nPair(Bowl(42), Bowl(42)) is @compile F_1\n//│ = false\n\npattern G = Triplet(Triplet(Box, Bowl, Basket), Pair(0, 1), Basket)\n\npattern G_0 = Triplet(Box, Bowl, Basket) | Triplet(Box, Bowl, Basket)\n\npattern G_0 = Triplet(Triplet(Box, Box, Box), Bowl, Basket) | Triplet(Triplet(Box, Box, Box), Bowl, Basket)\n\npattern G_1 =\n  | Triplet(Triplet(Box, Bowl, Box), Bowl, Basket)\n  | Triplet(Triplet(Box, Box, Box), Bowl, Basket)\n  | Triplet(Triplet(Box, Box, Bowl), Bowl, Basket)\n\npattern BinSeq'(pattern D) = D | Pair(0 | 1, BinSeq'(D))\n\npattern BinSeq = null | Pair(0 | 1, BinSeq)\n\nfun (::) cons(head, tail) = Pair(head, tail)\n\n0 :: null\n//│ = Pair(0, null)\n\n[\n  null is @compile BinSeq,\n  0 :: null is @compile BinSeq,\n  0 :: 1 :: null is @compile BinSeq,\n  0 :: 1 :: 0 :: null is @compile BinSeq,\n  0 is @compile BinSeq,\n  1 is @compile BinSeq,\n  0 :: 1 :: 2 :: null is @compile BinSeq,\n]\n//│ = [true, true, true, true, false, false, false]\n\n[\n  null is @compile BinSeq'(null),\n  0 :: null is @compile BinSeq'(null),\n  0 :: 1 :: null is @compile BinSeq'(null),\n  0 :: 1 :: 0 :: null is @compile BinSeq'(null),\n  0 is @compile BinSeq'(null),\n  1 is @compile BinSeq'(null),\n  0 :: 1 :: 2 :: null is @compile BinSeq'(null),\n]\n//│ = [true, true, true, true, false, false, false]\n\n0 :: 1 :: 0 :: null is @compile BinSeq\n//│ = true\n\n:e\npattern List(a) = null | Pair(a, List)\n//│ ╔══[COMPILATION ERROR] Found an inconsistent variable in disjunction patterns.\n//│ ║  l.152: \tpattern List(a) = null | Pair(a, List)\n//│ ║         \t                              ^\n//│ ╟── The variable is missing from this sub-pattern.\n//│ ║  l.152: \tpattern List(a) = null | Pair(a, List)\n//│ ╙──       \t                  ^^^^\n\nnull is @compile List\n//│ = true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/specialization/SimpleLiterals.mls",
    "content": ":js\n\nopen annotations { compile }\n\npattern Zero = \"0\"\npattern One = \"1\"\npattern Two = \"2\"\n\nfun checkZeroOneTwo(x) = if x is\n  @compile Zero then 0\n  @compile One then 1\n  @compile Two then 2\n  else ()\n\ncheckZeroOneTwo of \"0\"\n//│ = 0\n\ncheckZeroOneTwo of \"1\"\n//│ = 1\n\ncheckZeroOneTwo of \"2\"\n//│ = 2\n\ncheckZeroOneTwo of \"hello\"\n\nimport \"../../../mlscript-compile/Option.mls\"\nopen Option\n\nfun observeZero(x) =\n  print(\"zero \" + x)\n  x\n\npattern ZeroLogged = (\"0\" as x) => observeZero(x)\n\nprint of Some(\"0\") is Some(@compile ZeroLogged)\n//│ > true\n\nif Some(\"0\") is Some((@compile ZeroLogged) as zero) then\n  print(\"nested zero: \" + zero)\n//│ > zero 0\n//│ > nested zero: 0\n\nfun checkSomeZeroOneTwo(x) = if x is\n  Some(@compile Zero) then 0\n  Some(@compile One) then 1\n  Some(@compile Two) then 2\n  else ()\n\npattern ManyZero = (\"0\" ~ (ManyZero | \"\")) | \"\"\n\n:e\n:todo\nlet res = \"1\" is @compile ManyZero\n//│ ╔══[COMPILATION ERROR] String concatenation is not supported in pattern compilation.\n//│ ║  l.49: \tpattern ManyZero = (\"0\" ~ (ManyZero | \"\")) | \"\"\n//│ ╙──      \t                    ^^^^^^^^^^^^^^^^^^^^\n//│ res = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/CrossCompilation.mls",
    "content": ":js\n\nopen annotations\n\n// After sharing UCS desugaring with UPS, we can selectively efficiently compile\n// sub-patterns in a naively compiled pattern.\n\npattern ZeroOne = 0 | 1\n\npattern SevenEight = 7 | 8\n\n:ucs instantiation\n// Note that only `ZeroOne` is instantiated.\npattern Bar = SevenEight | @compile ZeroOne\n//│ | Instantiating ZeroOne\n//│ | Instantiated ZeroOne\n//│ | >  arity = 0\n//│ | >  arguments = \n//│ | >  instantiated = (0 ∨ 1)\n\n:expect true\n0 is Bar\n//│ = true\n\n:expect true\n1 is Bar\n//│ = true\n\n:expect false\n2 is Bar\n//│ = false\n\n:expect true\n0 is @compile Bar\n//│ = true\n\n:expect true\n1 is @compile Bar\n//│ = true\n\n:expect false\n2 is @compile Bar\n//│ = false\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/Declaration.mls",
    "content": ":js\n\n\n:e\npattern Foo(val T) = null | T\n//│ ╔══[COMPILATION ERROR] Unexpected pattern parameter T with modifiers: val\n//│ ║  l.5: \tpattern Foo(val T) = null | T\n//│ ╙──     \t                ^\n//│ ╔══[COMPILATION ERROR] Pattern name not found: T.\n//│ ║  l.5: \tpattern Foo(val T) = null | T\n//│ ╙──     \t                            ^\n\n\npattern Foo(pattern T) = null | T\n\n:fixme // TODO: fix IR rebinding issue (each symbol should be bound at most once)\n:checkIR\npattern Foo(pattern T) = null | T\n//│ ╔══[INTERNAL ERROR] [BlockChecker] Invalid IR: symbol T⁰ is bound more than once\n//│ ║  l.18: \tpattern Foo(pattern T) = null | T\n//│ ╙──      \t                    ^\n\n\n:breakme\ndata pattern Foo = _\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/InterestingPatterns.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Stack.mls\"\nimport \"../../../mlscript-compile/Option.mls\"\n\nopen Stack\nopen Option { Some, None }\n\npattern DropZ = ((:x, :y, :z)) => (x: x, y: y)\n\n:ucs ups\npattern SumList = (Nil => 0) | ((Int as hd) :: (SumList as tl)) => hd + tl\n//│ elaborated pattern body: Nil => 0 ∨ Cons(Int as hd, SumList as tl) => builtin:+⁰(hd⁰, tl⁰)\n\n// Flatten the nested tuples. Note that it makes use of biased union.\npattern Flatten = ([Flatten as hd, ...Flatten as tl] => Array.concat(hd, tl)) | _\n\nobject Leaf\ndata class Node[A](value: A, left: Node[A], right: Node[A])\n\npattern TreeDepth = (Leaf => 0) | (Node(_, TreeDepth as left, TreeDepth as right) => 1 + Math.max(left, right))\n\npattern CountTree(pattern P) =\n  | Node(P as x, CountTree(P) as left, CountTree(P) as right) => 1 + left + right\n  | Node(_, CountTree(P) as left, CountTree(P) as right) => left + right\n  | Leaf => 0\n\n// Match a 2x2 matrix and return its transpose.\n:ucs ups\npattern Transpose = (null => null) | (([[a, b], [c, d]]) => [[a, c], [b, d]])\n//│ elaborated pattern body: null => null ∨ [[a, b], [c, d]] => [[a⁰, c⁰], [b⁰, d⁰]]\n\n// Return the middle element of a list. It won't match if the length is even.\n:ucs ups\npattern Middle = ([x] => x) | ([x, ...(Middle as m), y] => m)\n//│ elaborated pattern body: [x] => x⁰ ∨ [x, ...Middle as m, y] => m⁰\n\n// Return the leaves of a tree.\npattern Leaves = (null => Nil) | ([x] => x :: Nil) | ([Leaves as left, Leaves as right] => left ::: right)\n\n// Extract the diagonal elements of a 3x3 matrix\npattern MatrixDiagonal = ([[a, _, _], [_, b, _], [_, _, c]] => [a, b, c])\n\n// Flatten a binary tree to a list using in-order traversal\npattern InOrderTraversal =\n  | Leaf => []\n  | Node(x, InOrderTraversal as left, InOrderTraversal as right) => left ::: [x] ::: right\n\nfun max(ow, v) = if ow is\n  Some(w) and w > v then w\n  else v\n\nfun min(ow, v) = if ow is\n  Some(w) and w < v then w\n  else v\n\n// Extract the maximum value from a binary tree\npattern TreeMax =\n  | Leaf => None\n  | Node(x, TreeMax as left, TreeMax as right) => max(max(left, x), right)\npattern TreeMin =\n  | Leaf => None\n  | Node(x, TreeMin as left, TreeMin as right) => min(min(left, x), right)\n\n// Check if a binary tree is balanced\npattern IsBalanced =\n  | Leaf => true\n  | Node(_, IsBalanced as left, IsBalanced as right) => Math.abs(TreeDepth(left) - TreeDepth(right)) <= 1\n\n// Extract the path from root to a target value in a binary tree\npattern PathToValue(pattern Target) = \n  | Leaf => []\n  | Node(PathToValue(Target) as left, Target, _) => [0] ::: left\n  | Node(_, Target, PathToValue(Target) as right) => [1] ::: right\n  | Node(PathToValue(Target) as left, _, _) => [0] ::: left\n  | Node(_, _, PathToValue(Target) as right) => [1] ::: right\n\n// Extract elements at even indices in a list.\npattern EvenIndicesList = \n  | Nil => Nil\n  | (x :: Nil) => x\n  | (x :: _ :: EvenIndicesList as xs) => x :: xs\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/MixedParameters.mls",
    "content": ":js\n\n// The semantics of mixed pattern parameters and extraction parameters.\n\npattern Bit = 0 | 1\n\npattern P(pattern Q, a, b) = [Q as a, Q as b]\n\nif [0, 0] is P(Bit, a, b) then \"values: \" + a + \", \" + b\n//│ = \"values: 0, 0\"\n\n// We can omit all extraction parameters completely. All extraction parameters\n// will be placed in a tuple and returned.\nif [0, 0] is P(Bit) as ab then ab\n//│ = [0, 0]\n\n// Because the above pattern definition can be seen as:\npattern P'(pattern Q) = [Q as a, Q as b] => [a, b]\n\n:e\n:re\n// However, we cannot provide only part of the extraction parameters. The rule\n// is that we either provide all of them or none at all.\nif [0, 0] is P(Bit, a) then a\n//│ ╔══[COMPILATION ERROR] Expected two extraction arguments, but found only one argument.\n//│ ║  l.24: \tif [0, 0] is P(Bit, a) then a\n//│ ╙──      \t               ^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:e\n:re\n// But `P` is not equivalent to `P'`! If no extraction parameters are declared,\n// then none can be provided.\nif [0, 0] is P'(Bit, a, b) then \"values: \" + a + \", \" + b\n//│ ╔══[COMPILATION ERROR] Expected zero extraction arguments, but found two arguments.\n//│ ║  l.34: \tif [0, 0] is P'(Bit, a, b) then \"values: \" + a + \", \" + b\n//│ ╙──      \t                ^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\n:fixme\n// Order actually matters. But it seems that I didn't implement the error\n// reporting correctly.\nif [0, 0] is P(a, Bit, b) then \"values: \" + a + \", \" + b\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'a'\n//│ ║  l.43: \tif [0, 0] is P(a, Bit, b) then \"values: \" + a + \", \" + b\n//│ ╙──      \t                                            ^\n//│ = \"values: 0, 0\"\n\npattern S(a, pattern Q, b) = [Q as a, Q as b]\n\nfun f(x) = if x is S(a, 0, b) then [a, b]\n\nf([0, 0])\n//│ = [0, 0]\n\n:fixme\n// Order actually matters.\nfun f(x) = if x is S(Bit, a, b) then [a, b]\n//│ ╔══[COMPILATION ERROR] No definition found in scope for member 'a'\n//│ ║  l.58: \tfun f(x) = if x is S(Bit, a, b) then [a, b]\n//│ ╙──      \t                                      ^\n\nf([0, 0])\n//│ = [0, 0]\n\n// The last thing to note is that if there is only one pattern parameter, it\n// will not be put into a tuple.\npattern Q(pattern A, result) = A as result\n\nif 0 is Q(Bit) as y then y\n//│ = 0\n\n// The value of y is the same in the example above and in the one below.\nif 0 is Q(Bit, y) then y\n//│ = 0\n\npattern Q'(pattern A) = A\n\nif 0 is Q'(Bit) as y then y\n//│ = 0\n\n:e\n:re\n// Similarly, it cannot be written like this:\nif 0 is Q'(Bit, y) then y\n//│ ╔══[COMPILATION ERROR] Expected zero extraction arguments, but found one argument.\n//│ ║  l.85: \tif 0 is Q'(Bit, y) then y\n//│ ╙──      \t           ^^^^^^\n//│ ═══[RUNTIME ERROR] Error: match error\n\npattern ZeroToOne = 0 => 1\npattern CaptureBit(value) = Bit as value\n\n:w\n// Extraction matches on pattern symbols only use their success/failure. If the\n// supplied extraction pattern transforms its output, that transformed value is\n// discarded unless the user makes the discard explicit with `as _`.\nif 0 is CaptureBit(ZeroToOne) then \"discarded implicitly\"\n//│ ╔══[WARNING] This extraction argument's transformation result is discarded by pattern `CaptureBit`.\n//│ ║  l.98: \tif 0 is CaptureBit(ZeroToOne) then \"discarded implicitly\"\n//│ ║        \t                   ^^^^^^^^^\n//│ ╙── Write `... as _` to discard it explicitly.\n//│ = \"discarded implicitly\"\n\nif 0 is CaptureBit(ZeroToOne as _) then \"discarded explicitly\"\n//│ = \"discarded explicitly\"\n\nif 0 is CaptureBit(Bit) then \"output preserving\"\n//│ = \"output preserving\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/PatternBody.mls",
    "content": ":js\n\n:todo // Patterns at parameter position are not supported yet.\n0 => false\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found integer literal\n//│ ║  l.4: \t0 => false\n//│ ╙──     \t^\n//│ = fun\n\n:ucs ups\npattern BooleanLike = true | false | (0 => false) | (1 => true)\n//│ elaborated pattern body: true ∨ false ∨ 0 => false ∨ 1 => true\n\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Stack\n\nclass Pair[A, B](val fst: A, val snd: B)\n\n:ucs ups\npattern PlainList(pattern T) = (null => Nil) | (Pair(T as hd, PlainList(T) as tl) => hd :: tl)\n//│ elaborated pattern body: null => (member:Stack⁰.)Nil‹member:Nil› ∨ Pair(T as hd, PlainList(T) as tl) => (member:Stack⁰.)Cons‹member:Cons›(hd⁰, tl⁰)\n\n:ucs ups\n// TODO: Decide on the relative operator precedence between `as` and `=>`.\n//  This is elaborated into `T as (x => x)`, which might not be what we want.\npattern Identity(pattern T) = T as x => x\n//│ elaborated pattern body: T as (x => x⁰)\n\n:ucs ups\npattern Identity(pattern T) = (T as x) => x\n//│ elaborated pattern body: (T as x) => x¹\n\npattern Identity = x => x\n\n:ucs ups\npattern Sick = (0 as a as b as c as d as e as f) => a + b + c + d + e + f\n//│ elaborated pattern body: ((((((0 as a) as b) as c) as d) as e) as f) => builtin:+⁰(builtin:+⁰(builtin:+⁰(builtin:+⁰(builtin:+⁰(a⁰, b⁰), c⁰), d⁰), e⁰), f⁰)\n\n:ucs ups\npattern PairLike = [fst, snd] => Pair(fst, snd)\n//│ elaborated pattern body: [fst, snd] => member:Pair⁰(fst⁰, snd⁰)\n\n:ucs ups\npattern PairLike(fst, snd) = Pair(fst, snd) | [fst, snd]\n//│ elaborated pattern body: Pair(fst, snd) ∨ [fst, snd]\n\n:w\npattern UselessParameter = x\n//│ ╔══[WARNING] Unused pattern binding: x.\n//│ ║  l.49: \tpattern UselessParameter = x\n//│ ╙──      \t                           ^\n\n:ucs ups\npattern PlainList(pattern T) = (null => Nil) | ([T as hd, PlainList(T) as tl] => hd :: tl)\n//│ elaborated pattern body: null => (member:Stack⁰.)Nil‹member:Nil› ∨ [T as hd, PlainList(T) as tl] => (member:Stack⁰.)Cons‹member:Cons›(hd¹, tl¹)\n\n:ucs ups\npattern Consistent = ((Int as x) | (Str as x)) => x.toString()\n//│ elaborated pattern body: (Int as x ∨ Str as x) => x².toString()\n\n:e\npattern Inconsistent = ~(~(Int as x) | Str) => x.toString()\n//│ ╔══[COMPILATION ERROR] This pattern cannot be bound.\n//│ ║  l.63: \tpattern Inconsistent = ~(~(Int as x) | Str) => x.toString()\n//│ ║        \t                           ^^^\n//│ ╟── Because the pattern it belongs to is negated.\n//│ ║  l.63: \tpattern Inconsistent = ~(~(Int as x) | Str) => x.toString()\n//│ ╙──      \t                           ^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.63: \tpattern Inconsistent = ~(~(Int as x) | Str) => x.toString()\n//│ ╙──      \t                                               ^\n\n:e\npattern Inconsistent = (~(~((Int as x) => x)) | Str) => x.toString()\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.75: \tpattern Inconsistent = (~(~((Int as x) => x)) | Str) => x.toString()\n//│ ╙──      \t                                                        ^\n\n:ucs ups\npattern Negated = ~(Int | Str)\n//│ elaborated pattern body: ¬(Int ∨ Str)\n\n// FIXME: The precedence of `=>` is higher than `~`?\n:pt\npattern BadNegated = ~(Int as x) => x\n//│ ———————————————| Parsed tree |——————————————————————————————————————————————————————————————————————\n//│ TypeDef:\n//│   k = Pat\n//│   head = Ident of \"BadNegated\"\n//│   rhs = S of App:\n//│     lhs = Ident of \"~\"\n//│     rhs = Tup of Ls of \n//│       InfixApp:\n//│         lhs = Tup of Ls of \n//│           InfixApp:\n//│             lhs = Ident of \"Int\"\n//│             kw = Keywrd of keyword 'as'\n//│             rhs = Ident of \"x\"\n//│         kw = Keywrd of keyword '=>'\n//│         rhs = Ident of \"x\"\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:ucs ups\n:e\npattern BadNegated = (~(Int as x)) => x\n//│ ╔══[COMPILATION ERROR] This pattern cannot be bound.\n//│ ║  l.106: \tpattern BadNegated = (~(Int as x)) => x\n//│ ║         \t                        ^^^\n//│ ╟── Because the pattern it belongs to is negated.\n//│ ║  l.106: \tpattern BadNegated = (~(Int as x)) => x\n//│ ╙──       \t                        ^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.106: \tpattern BadNegated = (~(Int as x)) => x\n//│ ╙──       \t                                      ^\n//│ elaborated pattern body: ¬(Int as x) => <error>\n\n:ucs ups\n:e\npattern BadNegated = (~Pair(Int, x)) => x\n//│ ╔══[COMPILATION ERROR] This variable cannot be accessed.\n//│ ║  l.120: \tpattern BadNegated = (~Pair(Int, x)) => x\n//│ ║         \t                                 ^\n//│ ╟── Because the pattern it belongs to is negated.\n//│ ║  l.120: \tpattern BadNegated = (~Pair(Int, x)) => x\n//│ ╙──       \t                       ^^^^^^^^^^^\n//│ ╔══[COMPILATION ERROR] Name not found: x\n//│ ║  l.120: \tpattern BadNegated = (~Pair(Int, x)) => x\n//│ ╙──       \t                                        ^\n//│ elaborated pattern body: ¬Pair(Int, x) => <error>\n\n:ucs ups\npattern DoubleNegated = ~(~Int)\n//│ elaborated pattern body: ¬¬Int\n\n:ucs ups\npattern Nothing = ~_\n//│ elaborated pattern body: ¬_\n\n:ucs ups\npattern Origin = (x: 0, y: 0)\n//│ elaborated pattern body: {x: 0, y: 0}\n\n:ucs ups\npattern Origin = (x: 0, y: 0, z: 0)\n//│ elaborated pattern body: {x: 0, y: 0, z: 0}\n\n:ucs ups\npattern PointLike = ((x: x, y: y)) => x + y\n//│ elaborated pattern body: {x: x, y: y} => builtin:+⁰(x³, y⁰)\n\n:ucs ups\npattern PointLike = ((:x, :y, :z)) => x + y\n//│ elaborated pattern body: {x: x, y: y, z: z} => builtin:+⁰(x⁴, y¹)\n\n:ucs ups\npattern NestedTuple = [[[]]]\n//│ elaborated pattern body: [[[]]]\n\npattern Digit = \"0\" ..= \"9\"\n\npattern Naughty = CanYouSeeMe(n) => n\ndata class CanYouSeeMe(wow: Int)\n\nclass SecretPair(a: Int, val b: Int)\n\n:ucs ups\npattern KeepSecret(b) = SecretPair(_, b)\n//│ elaborated pattern body: SecretPair(_, b)\n\n:e\npattern RebuildSecret = SecretPair(_, b => b + 1)\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.172: \tpattern RebuildSecret = SecretPair(_, b => b + 1)\n//│ ║         \t                                   ^\n//│ ╟── because the corresponding parameter `a` is not publicly accessible\n//│ ║  l.165: \tclass SecretPair(a: Int, val b: Int)\n//│ ║         \t                 ^\n//│ ╟── because rebuilding the matched `SecretPair` value requires reading every constructor argument\n//│ ║  l.172: \tpattern RebuildSecret = SecretPair(_, b => b + 1)\n//│ ║         \t                        ^^^^^^^^^^\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n\n:e\n// Even if a certain class is under the selection of multiple modules, we should\n// still be able to resolve it correctly.\nfun y = HiddenCorner.m.m.k\npattern Naughty = HiddenCorner.m.m.YouCantSeeMe(n) => n + HiddenCorner.m.m.k\npattern Obedient = HiddenCorner.m.m.CantYouSeeMe(n) => n + HiddenCorner.m.m.k\nmodule HiddenCorner with\n  val m: module HiddenCorner = HiddenCorner\n  class YouCantSeeMe(wow: Int)\n  class CantYouSeeMe(val wow: Int)\n  val k = 0\n//│ ╔══[COMPILATION ERROR] This pattern cannot be matched\n//│ ║  l.188: \tpattern Naughty = HiddenCorner.m.m.YouCantSeeMe(n) => n + HiddenCorner.m.m.k\n//│ ║         \t                                                ^\n//│ ╟── because the corresponding parameter `wow` is not publicly accessible\n//│ ║  l.192: \t  class YouCantSeeMe(wow: Int)\n//│ ║         \t                     ^^^\n//│ ╟── Suggestion: use a wildcard pattern `_` in this position\n//│ ╙── Suggestion: mark this parameter with `val` so it becomes accessible\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/Precedence.mls",
    "content": ":ucs ups\n\n// The right binding power of `=>` is lower than the left binding power of `|`.\n// Therefore, if we want to union two transformations, we should parenthesize\n// the second transformation.\n\npattern Test = 1 | 2\n//│ elaborated pattern body: 1 ∨ 2\n\npattern Test = 1 | 2 => 3\n//│ elaborated pattern body: 1 ∨ 2 => 3\n\n// The following two examples are rejected because `4 => 8` is considered as a\n// part of the right hand side term of `1 => 2`. Currently, our implementation\n// does not support patterns as lambda parameters.\n\n:todo\npattern Test = 1 => 2 | 4 => 8\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found integer literal\n//│ ║  l.18: \tpattern Test = 1 => 2 | 4 => 8\n//│ ╙──      \t                        ^\n//│ elaborated pattern body: 1 => 2 | λ(). 8\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (composed type)\n//│ ║  l.18: \tpattern Test = 1 => 2 | 4 => 8\n//│ ╙──      \t                        ^\n\n:todo\npattern Test = 1 => 2 | (4 => 8)\n//│ ╔══[COMPILATION ERROR] Expected a valid parameter, found integer literal\n//│ ║  l.28: \tpattern Test = 1 => 2 | (4 => 8)\n//│ ╙──      \t                         ^\n//│ elaborated pattern body: 1 => 2 | λ(). 8\n//│ ╔══[COMPILATION ERROR] Unexpected term form in expression position (composed type)\n//│ ║  l.28: \tpattern Test = 1 => 2 | (4 => 8)\n//│ ╙──      \t                         ^\n\npattern Test = (1 => 2) | 4 => 8\n//│ elaborated pattern body: 1 => 2 ∨ 4 => 8\n\n// The precedence of `as` is lower than `=>`.\n\npattern Test = 0 as x => 2\n//│ elaborated pattern body: 0 as (x => 2)\n\npattern Test = (0 as x) => 2\n//│ elaborated pattern body: (0 as x) => 2\n\n:e\npattern Test(x) = 0 as x | 1 as x\n//│ ╔══[COMPILATION ERROR] Found an inconsistent variable in disjunction patterns.\n//│ ║  l.49: \tpattern Test(x) = 0 as x | 1 as x\n//│ ║        \t                       ^\n//│ ╟── The variable is missing from this sub-pattern.\n//│ ║  l.49: \tpattern Test(x) = 0 as x | 1 as x\n//│ ╙──      \t                           ^\n//│ elaborated pattern body: (0 as (x ∨ 1)) as x\n\npattern Test(x) = 0 as x | (1 as x)\n//│ elaborated pattern body: 0 as (x ∨ 1 as x)\n\npattern Test(x) = 0 as x | (1 as x)\n//│ elaborated pattern body: 0 as (x ∨ 1 as x)\n\npattern Test(x) = (0 as x) | (1 as x)\n//│ elaborated pattern body: 0 as x ∨ 1 as x\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/WrongArguments.mls",
    "content": ":js\n\nclass Foo(val bar: Int)\n\npattern Bar = Foo(0)\n\nFoo(0) is Bar\n//│ = true\n\nFoo(1) is Bar\n//│ = false\n\npattern Baz(pattern A) = A\n\n:e\npattern Baz(pattern A) = A()\n//│ ╔══[COMPILATION ERROR] `A` is a pattern parameter.\n//│ ║  l.16: \tpattern Baz(pattern A) = A()\n//│ ║        \t                    ^\n//│ ╟── It cannot be applied.\n//│ ║  l.16: \tpattern Baz(pattern A) = A()\n//│ ╙──      \t                         ^\n\n:e\npattern Baz(pattern A) = A(1, 2, 3)\n//│ ╔══[COMPILATION ERROR] `A` is a pattern parameter.\n//│ ║  l.25: \tpattern Baz(pattern A) = A(1, 2, 3)\n//│ ║        \t                    ^\n//│ ╟── It cannot be applied to any arguments.\n//│ ║  l.25: \tpattern Baz(pattern A) = A(1, 2, 3)\n//│ ╙──      \t                         ^^^^^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/syntax/WrongArity.mls",
    "content": ":js\n\ndata class Pair[A, B](val first: A, val second: B)\n\n:e\npattern LessArity = Pair(\"meow\")\n//│ ╔══[COMPILATION ERROR] Expected two arguments, but found only one argument.\n//│ ║  l.6: \tpattern LessArity = Pair(\"meow\")\n//│ ╙──     \t                         ^^^^^^\n\n:e\npattern MoreArity = Pair(\"meow\", \"woof\", \"moo\")\n//│ ╔══[COMPILATION ERROR] Expected two arguments, but found three arguments.\n//│ ║  l.12: \tpattern MoreArity = Pair(\"meow\", \"woof\", \"moo\")\n//│ ╙──      \t                         ^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/ups/transformation/BindingLess.mls",
    "content": ":js\n\nimport \"../../../mlscript-compile/Char.mls\"\nimport \"../../../mlscript-compile/Stack.mls\"\n\nopen Char { AnyChar }\nopen Stack\n\nopen annotations\n\npattern Inc = (Int as x) => x + 1\n\ndata class Pair[A, B](fst: A, snd: B)\n\npattern IncFst = Pair(Inc, _)\n\nlet ps = Pair(\"hello\", \"world\")\n//│ ps = Pair(\"hello\", \"world\")\n\nlet pi = Pair(1, 2)\n//│ pi = Pair(1, 2)\n\nfun foo(p) = if p is IncFst as q then q else p\n\n:expect true\nps == foo(ps)\n//│ = true\n\n:expect false\npi == foo(pi)\n//│ = false\n\nfun foo(p) = if p is (@compile IncFst) as q then q else p\n\n:expect true\nps == foo(ps)\n//│ = true\n\n:expect false\npi == foo(pi)\n//│ = false\n\n:expect false\nps is IncFst\n//│ = false\n\n:expect true\npi is IncFst\n//│ = true\n\n:expect false\nps is @compile IncFst\n//│ = false\n\n:expect true\npi is @compile IncFst\n//│ = true\n\npattern ToUppercase =\n  | (\"a\" => \"A\") | (\"b\" => \"B\") | (\"c\" => \"C\")\n  | (\"d\" => \"D\") | (\"e\" => \"E\") | (\"f\" => \"F\")\n  | (\"g\" => \"G\") | (\"h\" => \"H\") | (\"i\" => \"I\") | (\"j\" => \"J\")\n  | (\"k\" => \"K\") | (\"l\" => \"L\") | (\"m\" => \"M\") | (\"n\" => \"N\")\n  | (\"o\" => \"O\") | (\"p\" => \"P\") | (\"q\" => \"Q\") | (\"r\" => \"R\")\n  | (\"s\" => \"S\") | (\"t\" => \"T\") | (\"u\" => \"U\") | (\"v\" => \"V\")\n  | (\"w\" => \"W\") | (\"x\" => \"X\") | (\"y\" => \"Y\") | (\"z\" => \"Z\")\n  | AnyChar\n\npattern ToUppercaseList = Nil | (ToUppercase :: ToUppercaseList)\n\nfun toUppercaseList(input) = if input is ToUppercaseList as output then output\n\ntoUppercaseList of \"a\" :: \"X\" :: \"c\" :: Nil\n//│ = Cons(\"A\", Cons(\"X\", Cons(\"C\", Nil)))\n\npattern ToUppercaseString = ToUppercase ~ (ToUppercaseString | \"\")\n\nfun toUppercase(input) = if input is ToUppercaseString as output then output\n\ntoUppercase of \"abc\"\n//│ = \"ABC\"\n\ntoUppercase of \"ThIs Is AlTeRnAtInG cApS!\"\n//│ = \"THIS IS ALTERNATING CAPS!\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/Basics.mls",
    "content": "\n:global\n:wasm\n\n\nfalse\n//│ Wasm result:\n//│ = 0\n\n\ntrue\n//│ Wasm result:\n//│ = 1\n\n\n2\n//│ Wasm result:\n//│ = 2\n\n\n1 + 1\n//│ Wasm result:\n//│ = 2\n\n\nlet x = 0\nx\n//│ Wasm result:\n//│ = 0\n\n\n:ge\nfun foo() = 42\nfoo\n//│ ╔══[COMPILATION ERROR] Returning function instances is not supported\n//│ ║  l.34: \tfoo\n//│ ╙──      \t^^^\n\n:ge\nclass Foo with\n  val x = 1\nlet f = Foo\n//│ ╔══[COMPILATION ERROR] Plain class references are not supported in Wasm; instantiate the class instead.\n//│ ║  l.42: \tlet f = Foo\n//│ ╙──      \t        ^^^\n\n\nfun foo() = 42\nfoo()\n//│ Wasm result:\n//│ = 42\n\n\n:wat\nfun foo() = 42\nfoo() + foo()\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $foo (func (result (ref null any))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (func $foo (export \"foo\") (type $foo) (result (ref null any))\n//│     (return\n//│       (ref.i31\n//│         (i32.const 42))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $foo (ref null any))\n//│     (local $tmp (ref null any))\n//│     (local $tmp1 (ref null any))\n//│     (local $inlinedVal (ref null any))\n//│     (local $inlinedVal1 (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block (result (ref null any))\n//│         (local.set $inlinedVal\n//│           (ref.i31\n//│             (i32.const 42)))\n//│         (block (result (ref null any))\n//│           (local.set $tmp\n//│             (local.get $inlinedVal))\n//│           (block (result (ref null any))\n//│             (local.set $inlinedVal1\n//│               (ref.i31\n//│                 (i32.const 42)))\n//│             (block (result (ref null any))\n//│               (local.set $tmp1\n//│                 (local.get $inlinedVal1))\n//│               (call $plus_impl\n//│                 (local.get $tmp)\n//│                 (local.get $tmp1))))))))\n//│   (elem $foo declare func $foo)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 84\n\n\nfun foo(x) = x + 1\nfoo(41)\n//│ Wasm result:\n//│ = 42\n\n\nclass Foo(val x)\nnew Foo(0)\n//│ Wasm result:\n//│ = {}\n\n\n:wat\nclass Foo(val a)\n(new Foo(42)).Foo#a\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Foo (sub $Object (struct (field $$tag (mut i32)) (field $a (mut (ref null any))))))\n//│   (type $Foo_init (func (param $this (ref null any)) (param $a (ref null any)) (result (ref null any))))\n//│   (type $Foo_ctor (func (param $a (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (func $Foo_init (type $Foo_init) (param $this (ref null any)) (param $a (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Foo $a\n//│           (ref.cast (ref $Foo)\n//│             (local.get $this))\n//│           (local.get $a))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Foo_ctor (export \"Foo\") (type $Foo_ctor) (param $a (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Foo))\n//│       (struct.set $Foo $$tag\n//│         (ref.cast (ref $Foo)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Foo_init\n//│           (local.get $this)\n//│           (local.get $a)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tmp (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block (result (ref null any))\n//│         (local.set $tmp\n//│           (call $Foo_ctor\n//│             (ref.i31\n//│               (i32.const 42))))\n//│         (struct.get $Foo $a\n//│           (ref.cast (ref $Foo)\n//│             (local.get $tmp))))))\n//│   (elem $Foo_init declare func $Foo_init)\n//│   (elem $Foo_ctor declare func $Foo_ctor)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 42\n\nclass Foo(val x)\nfun getX(f: Foo) = f.x\ngetX(Foo(42))\n//│ Wasm result:\n//│ = 42\n\n\n:wat\nclass Foo(val x) with\n  val y = this.x\n(new Foo(42)).Foo#y\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Foo (sub $Object (struct (field $$tag (mut i32)) (field $x (mut (ref null any))) (field $y (mut (ref null any))))))\n//│   (type $Foo_init (func (param $this (ref null any)) (param $x (ref null any)) (result (ref null any))))\n//│   (type $Foo_ctor (func (param $x (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (func $Foo_init (type $Foo_init) (param $this (ref null any)) (param $x (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Foo $x\n//│           (ref.cast (ref $Foo)\n//│             (local.get $this))\n//│           (local.get $x))\n//│         (block\n//│           (struct.set $Foo $y\n//│             (ref.cast (ref $Foo)\n//│               (local.get $this))\n//│             (struct.get $Foo $x\n//│               (ref.cast (ref $Foo)\n//│                 (local.get $this))))\n//│           (nop)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Foo_ctor (export \"Foo\") (type $Foo_ctor) (param $x (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Foo))\n//│       (struct.set $Foo $$tag\n//│         (ref.cast (ref $Foo)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Foo_init\n//│           (local.get $this)\n//│           (local.get $x)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tmp (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block (result (ref null any))\n//│         (local.set $tmp\n//│           (call $Foo_ctor\n//│             (ref.i31\n//│               (i32.const 42))))\n//│         (struct.get $Foo $y\n//│           (ref.cast (ref $Foo)\n//│             (local.get $tmp))))))\n//│   (elem $Foo_init declare func $Foo_init)\n//│   (elem $Foo_ctor declare func $Foo_ctor)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 42\n\n\n:wat\nobject O with\n  val x = 1\n  val y = this.x\nO.y\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $O (sub $Object (struct (field $$tag (mut i32)) (field $x (mut (ref null any))) (field $y (mut (ref null any))))))\n//│   (type $O_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $O_ctor (func (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (type $start (func))\n//│   (global $O$inst (export \"O$inst\") (mut (ref null $O)) (ref.null $O))\n//│   (func $O_init (type $O_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $O $x\n//│           (ref.cast (ref $O)\n//│             (local.get $this))\n//│           (ref.i31\n//│             (i32.const 1)))\n//│         (block\n//│           (struct.set $O $y\n//│             (ref.cast (ref $O)\n//│               (local.get $this))\n//│             (struct.get $O $x\n//│               (ref.cast (ref $O)\n//│                 (local.get $this))))\n//│           (nop)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $O_ctor (type $O_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $O))\n//│       (struct.set $O $$tag\n//│         (ref.cast (ref $O)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $O_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $start (type $start)\n//│     (block\n//│       (global.set $O$inst\n//│         (ref.cast (ref null $O)\n//│           (call $O_ctor)))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (struct.get $O $y\n//│         (ref.cast (ref $O)\n//│           (global.get $O$inst)))))\n//│   (elem $O_init declare func $O_init)\n//│   (elem $O_ctor declare func $O_ctor)\n//│   (elem $start declare func $start)\n//│   (elem $entry declare func $entry)\n//│   (start $start))\n//│ Wasm result:\n//│ = 1\n\n\n:ge\nfun bar() = 42\nfun foo() = bar\nfoo()()\n//│ ╔══[COMPILATION ERROR] Returning function instances is not supported\n//│ ║  l.304: \tfun foo() = bar\n//│ ╙──       \t            ^^^\n//│ ═══[COMPILATION ERROR] Expected static function reference in Call(...) expression\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/Binaryen.mls",
    "content": ":js\n:silent\n\n\n// Helper functions\nimport \"binaryen\"\nfun compileWatToWasm(wat) = \n  let mod = binaryen.parseText(wat)\n  mod.setFeatures(binaryen.Features.All)\n  assert mod.validate() != false\n  val modBuf = mod.emitBinary()\n  mod.dispose()\n  modBuf\nfun instantiateWasm(wasm, importObj) = \n  assert WebAssembly.validate(wasm)\n  let mod = new! WebAssembly.Module(wasm)\n  let inst = new! WebAssembly.Instance(mod, importObj)\n  inst\n\n\n// Parsing a WAT, compiling it to a Wasm bianry, and executing it\nlet wasmMod = compileWatToWasm of \n    \"\"\"\n    (module\n        (type $Foo (struct (field $i i32) (field $r i31ref)))\n        (func (export \"main\") (result i32)\n            (local $tmp (ref $Foo))\n            (block (result i32)\n                (local.set $tmp \n                    (struct.new $Foo\n                        (i32.const 1)\n                        (ref.i31 (i32.const 2))))\n                (i32.add\n                    (struct.get $Foo $i\n                        (local.get $tmp))\n                    (i31.get_s\n                        (struct.get $Foo $r \n                            (local.get $tmp)))))))\n    \"\"\"\nlet inst = instantiateWasm of wasmMod, {}\ninst.exports.main() |> print\n//│ > 3\n\n\n// Building a module using Binaryen APIs, and executing it\nlet mod = new! binaryen.Module()\nmod.setFeatures(binaryen.Features.All)\nlet fooTb = new! binaryen.TypeBuilder(1)\nfooTb.setStructType of 0, tuple of\n    (\n      \"type\": binaryen.i32\n      packedType: binaryen.notPacked\n      mutable: false\n    )\n    (\n      \"type\": binaryen.i31ref\n      packedType: binaryen.notPacked\n      mutable: false\n    )\nlet foo = fooTb.buildAndDispose().0\nmod.addFunction of\n  \"main\"\n  binaryen.none\n  binaryen.i32\n  [foo]\n  mod.block of\n    null\n    tuple of\n      mod.local.set of 0,\n        mod.struct.new of\n          tuple of\n            mod.i32.const(1)\n            mod.ref.i31 of\n              mod.i32.const of 2\n          foo\n      mod.i32.add of\n        mod.struct.get of 0,\n          mod.local.get(0, foo)\n          foo\n          false\n        mod.i31.get_s of\n          mod.struct.get of 1,\n            mod.local.get(0, foo)\n            foo\n            false\n    binaryen.i32\nmod.addFunctionExport of \"main\", \"main\"\nPredef.js_assert of mod.validate()\nlet wasmMod = mod.emitBinary()\nmod.dispose()\nlet inst = instantiateWasm of wasmMod, {}\ninst.exports.main() |> print\n//│ > 3\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/BuiltinOperators.mls",
    "content": "\n:global\n:wasm\n\n:wat\n1 + 2\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (call $plus_impl\n//│       (ref.i31\n//│         (i32.const 1))\n//│       (ref.i31\n//│         (i32.const 2))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 3\n\n:wat\n-2\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $neg_impl (func (param $arg (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"neg_impl\" (func $neg_impl (type $neg_impl)))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (call $neg_impl\n//│       (ref.i31\n//│         (i32.const 2))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = -2\n\nnot true\n//│ Wasm result:\n//│ = 0\n\n2 - 1\n//│ Wasm result:\n//│ = 1\n\n3 * 4\n//│ Wasm result:\n//│ = 12\n\n4 / 2\n//│ Wasm result:\n//│ = 2\n\n4 % 3\n//│ Wasm result:\n//│ = 1\n\n:wat\n1 === 1\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $eq_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"eq_impl\" (func $eq_impl (type $eq_impl)))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (call $eq_impl\n//│       (ref.i31\n//│         (i32.const 1))\n//│       (ref.i31\n//│         (i32.const 1))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 1\n\n1 === 2\n//│ Wasm result:\n//│ = 0\n\n1 !== 1\n//│ Wasm result:\n//│ = 0\n\n1 !== 2\n//│ Wasm result:\n//│ = 1\n\n1 < 1\n//│ Wasm result:\n//│ = 0\n\n1 <= 1\n//│ Wasm result:\n//│ = 1\n\n1 < 2\n//│ Wasm result:\n//│ = 1\n\n1 <=2\n//│ Wasm result:\n//│ = 1\n\n2 > 1\n//│ Wasm result:\n//│ = 1\n\n2 >= 1\n//│ Wasm result:\n//│ = 1\n\n2 > 2\n//│ Wasm result:\n//│ = 0\n\n2 >= 2\n//│ Wasm result:\n//│ = 1\n\n+3\n//│ Wasm result:\n//│ = 3\n\n-1 + 2\n//│ Wasm result:\n//│ = 1\n\n-1 - 2\n//│ Wasm result:\n//│ = -3\n\n-6 / 3\n//│ Wasm result:\n//│ = -2\n\n-6 % 4\n//│ Wasm result:\n//│ = -2\n\n-1 > 2\n//│ Wasm result:\n//│ = 0\n\n-1 > -3\n//│ Wasm result:\n//│ = 1\n\n- 1>= -1\n//│ Wasm result:\n//│ = 1\n\nnot false\n//│ Wasm result:\n//│ = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/ClassInheritance.mls",
    "content": "\n:global\n:wasm\n\n\nclass A(val x)\nclass B(val y) extends A(y + 1)\nlet b = B(1)\nb.A#x\n//│ Wasm result:\n//│ = 2\n\n\nclass A(val x)\nclass B(val y) extends A(1)\nB(2).A#x\n//│ Wasm result:\n//│ = 1\n\n\n:wat\n// Parent type/init/ctor appear before child\nlet c = Child(2)\nclass Child(val y) extends Parent(y + 1)\nclass Parent(val x)\nc.Parent#x\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Parent (sub $Object (struct (field $$tag (mut i32)) (field $x (mut (ref null any))))))\n//│   (type $Child (sub $Parent (struct (field $$tag (mut i32)) (field $x (mut (ref null any))) (field $y (mut (ref null any))))))\n//│   (type $Parent_init (func (param $this (ref null any)) (param $x (ref null any)) (result (ref null any))))\n//│   (type $Child_init (func (param $this (ref null any)) (param $y (ref null any)) (result (ref null any))))\n//│   (type $Parent_ctor (func (param $x (ref null any)) (result (ref null any))))\n//│   (type $Child_ctor (func (param $y (ref null any)) (result (ref null any))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (global $c (export \"c\") (mut (ref null any)) (ref.null any))\n//│   (func $Parent_init (type $Parent_init) (param $this (ref null any)) (param $x (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Parent $x\n//│           (ref.cast (ref $Parent)\n//│             (local.get $this))\n//│           (local.get $x))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Child_init (type $Child_init) (param $this (ref null any)) (param $y (ref null any)) (result (ref null any))\n//│     (local $tmp (ref null any))\n//│     (block (result (ref null any))\n//│       (block\n//│         (block\n//│           (local.set $tmp\n//│             (call $plus_impl\n//│               (local.get $y)\n//│               (ref.i31\n//│                 (i32.const 1))))\n//│           (nop))\n//│         (drop\n//│           (call $Parent_init\n//│             (local.get $this)\n//│             (local.get $tmp))))\n//│       (block\n//│         (struct.set $Child $y\n//│           (ref.cast (ref $Child)\n//│             (local.get $this))\n//│           (local.get $y))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Parent_ctor (export \"Parent\") (type $Parent_ctor) (param $x (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Parent))\n//│       (struct.set $Parent $$tag\n//│         (ref.cast (ref $Parent)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Parent_init\n//│           (local.get $this)\n//│           (local.get $x)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Child_ctor (export \"Child\") (type $Child_ctor) (param $y (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Child))\n//│       (struct.set $Child $$tag\n//│         (ref.cast (ref $Child)\n//│           (local.get $this))\n//│         (i32.const 2))\n//│       (drop\n//│         (call $Child_init\n//│           (local.get $this)\n//│           (local.get $y)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (global.set $c\n//│         (call $Child_ctor\n//│           (ref.i31\n//│             (i32.const 2))))\n//│       (block (result (ref null any))\n//│         (nop)\n//│         (block (result (ref null any))\n//│           (nop)\n//│           (struct.get $Parent $x\n//│             (ref.cast (ref $Parent)\n//│               (global.get $c)))))))\n//│   (elem $Parent_init declare func $Parent_init)\n//│   (elem $Child_init declare func $Child_init)\n//│   (elem $Parent_ctor declare func $Parent_ctor)\n//│   (elem $Child_ctor declare func $Child_ctor)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 3\n\n\nclass A(val x)\nclass B(val y) extends A(y + 1)\nclass C(val z) extends B(z + 1)\nlet c = C(1)\nc.A#x\n//│ Wasm result:\n//│ = 3\n\n\nclass A()\nclass B() extends A()\nB() is A\n//│ Wasm result:\n//│ = 1\n\n\nclass B() extends A()\nclass A()\nlet b = B()\nif b is A then 1 else 0\n//│ Wasm result:\n//│ = 1\n\n\nclass A(val x)\nclass B(val y) extends A(1)\nif B(2) is A(a) then a else 0\n//│ Wasm result:\n//│ = 1\n\n\nclass Bar(val a)\nclass Foo(val x, val y) extends Bar(x + y)\nif Foo(1,2) is Foo(x,y) then Foo(1,2).Bar#a\n//│ Wasm result:\n//│ = 3\n\n\nclass Bar(val a)\nclass Foo(val x) extends Bar(x * 2)\nfun getXor(f) = if f is Foo(z) then f.Bar#a else 0\ngetXor(Foo(42))\n//│ Wasm result:\n//│ = 84\n\n\nclass Foo(val x)\nclass Bar(val y) extends Foo(y + y)\nclass Baz(val z) extends Bar(z - 1)\nif Baz(10) is\n  Foo(a) then a\n  Bar(b) then b\n  Baz(c) then c\n  else 0\n//│ Wasm result:\n//│ = 18\n\n\nclass Bar(val y)\nclass Baz(val z) extends Bar(not z)\nif Baz(true) is\n  Bar(a) then if a then Bar(a).Bar#y else a\n  Baz(b) then b\n  else 2\n//│ Wasm result:\n//│ = 0\n\n\nclass A()\nclass B()\nB() is A\n//│ Wasm result:\n//│ = 0\n\n\n// Unrelated top-level classes preserve their source order in type declaration.\n:wat\nclass A \nclass B\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $A (sub $Object (struct (field $$tag (mut i32)))))\n//│   (type $B (sub $Object (struct (field $$tag (mut i32)))))\n//│   (type $A_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $B_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $A_ctor (func (result (ref null any))))\n//│   (type $B_ctor (func (result (ref null any))))\n//│   (type $Unit (sub $Object (struct (field $$tag (mut i32)))))\n//│   (type $Unit_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $Unit_ctor (func (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (type $start (func))\n//│   (global $Unit$inst (export \"Unit$inst\") (mut (ref null $Unit)) (ref.null $Unit))\n//│   (func $A_init (type $A_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (nop)\n//│       (return\n//│         (local.get $this))))\n//│   (func $B_init (type $B_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (nop)\n//│       (return\n//│         (local.get $this))))\n//│   (func $A_ctor (export \"A\") (type $A_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $A))\n//│       (struct.set $A $$tag\n//│         (ref.cast (ref $A)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $A_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $B_ctor (export \"B\") (type $B_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $B))\n//│       (struct.set $B $$tag\n//│         (ref.cast (ref $B)\n//│           (local.get $this))\n//│         (i32.const 2))\n//│       (drop\n//│         (call $B_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Unit_init (type $Unit_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (nop)\n//│       (return\n//│         (local.get $this))))\n//│   (func $Unit_Unit (type $Unit_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Unit))\n//│       (struct.set $Unit $$tag\n//│         (ref.cast (ref $Unit)\n//│           (local.get $this))\n//│         (i32.const 3))\n//│       (drop\n//│         (call $Unit_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $start (type $start)\n//│     (block\n//│       (global.set $Unit$inst\n//│         (ref.cast (ref null $Unit)\n//│           (call $Unit_Unit)))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (block\n//│         (nop)\n//│         (block\n//│           (nop)\n//│           (nop)))\n//│       (global.get $Unit$inst)))\n//│   (elem $A_init declare func $A_init)\n//│   (elem $B_init declare func $B_init)\n//│   (elem $A_ctor declare func $A_ctor)\n//│   (elem $B_ctor declare func $B_ctor)\n//│   (elem $Unit_init declare func $Unit_init)\n//│   (elem $Unit_Unit declare func $Unit_Unit)\n//│   (elem $start declare func $start)\n//│   (elem $entry declare func $entry)\n//│   (start $start))\n//│ Wasm result:\n//│ = {}\n\n\n:ge\nclass A extends B\nclass B extends A\n//│ ╔══[COMPILATION ERROR] Inheritance cycles are not supported.\n//│ ║  l.307: \tclass A extends B\n//│ ╙──       \t^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/ClassMethods.mls",
    "content": "\n:global\n:wasm\n\n\n:wat\nclass A(val x) with\n  fun get() = x\nlet a = A(1)\na.A#get() + A(2).get()\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $A (sub $Object (struct (field $$tag (mut i32)) (field $x (mut (ref null any))))))\n//│   (type $A_init (func (param $this (ref null any)) (param $x (ref null any)) (result (ref null any))))\n//│   (type $A_ctor (func (param $x (ref null any)) (result (ref null any))))\n//│   (type $A_get (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (global $a (export \"a\") (mut (ref null any)) (ref.null any))\n//│   (func $A_init (type $A_init) (param $this (ref null any)) (param $x (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $A $x\n//│           (ref.cast (ref $A)\n//│             (local.get $this))\n//│           (local.get $x))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $A_ctor (export \"A\") (type $A_ctor) (param $x (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $A))\n//│       (struct.set $A $$tag\n//│         (ref.cast (ref $A)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $A_init\n//│           (local.get $this)\n//│           (local.get $x)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $A_get (type $A_get) (param $this (ref null any)) (result (ref null any))\n//│     (return\n//│       (struct.get $A $x\n//│         (ref.cast (ref $A)\n//│           (local.get $this)))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tmp (ref null any))\n//│     (local $tmp1 (ref null any))\n//│     (local $tmp2 (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block (result (ref null any))\n//│         (global.set $a\n//│           (call $A_ctor\n//│             (ref.i31\n//│               (i32.const 1))))\n//│         (block (result (ref null any))\n//│           (local.set $tmp\n//│             (call $A_get\n//│               (global.get $a)))\n//│           (block (result (ref null any))\n//│             (local.set $tmp1\n//│               (call $A_ctor\n//│                 (ref.i31\n//│                   (i32.const 2))))\n//│             (block (result (ref null any))\n//│               (local.set $tmp2\n//│                 (call $A_get\n//│                   (local.get $tmp1)))\n//│               (call $plus_impl\n//│                 (local.get $tmp)\n//│                 (local.get $tmp2))))))))\n//│   (elem $A_init declare func $A_init)\n//│   (elem $A_ctor declare func $A_ctor)\n//│   (elem $A_get declare func $A_get)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 3\n\n\nclass A(val x) with\n  fun get = x\nlet a = A(1)\na.A#get\n//│ Wasm result:\n//│ = 1\n\n\nclass A(val x) with\n  fun add(y) = x + y\nA(1).add(2)\n//│ Wasm result:\n//│ = 3\n\n\nclass C(val x) with\n  fun get() = double\n  fun double = x + this.x\nC(2).get()\n//│ Wasm result:\n//│ = 4\n\n\nclass SumDown() with\n  fun sum(n) = \n    if n === 0 \n        then 0 \n        else n + sum(n - 1)\nSumDown().sum(5)\n//│ Wasm result:\n//│ = 15\n\n\nclass Parity() with\n  fun even(n) =\n    if n === 0 then true else odd(n - 1)\n  fun odd(n) =\n    if n === 0 then false else even(n - 1)\nParity().even(6)\n//│ Wasm result:\n//│ = 1\n\n\nclass Box(val x) with\n    fun get() = x\n    fun inc() = Box(x + 1).get()\nBox(2).inc()\n//│ Wasm result:\n//│ = 3\n\n\nclass Counter(val x) with\n  fun inc() = Counter(x + 1)\n  fun double() = Counter(x + x)\n  fun get() = x\nlet c = Counter(1)\nc.Counter#inc().Counter#double().Counter#get()\n//│ Wasm result:\n//│ = 4\n\n\nclass Box(val x) with\n    fun mk() = Next(x + 1).get()\nclass Next(val y) with\n    fun get() = y\nBox(41).mk()\n//│ Wasm result:\n//│ = 42\n\n\nclass Counter(val x) with\n  fun inc() = \n    set x += 1\n    this\n  fun double() =\n    set x *= 2\n    this\n  fun get() = x\nlet c = Counter(1)\nc.Counter#inc().Counter#double().Counter#get()\n//│ Wasm result:\n//│ = 4\n\n:todo\nlet d = Counter(c.Counter#get())\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Missing field `term:Counter/get` in struct `member:Counter` with type `(type $Counter (sub $Object (struct (field $$tag (mut i32)) (field $x (mut (ref null any))))))`\n\n:todo\nd.Counter#inc().Counter#double().Counter#get()\n//│ ╔══[COMPILATION ERROR] Cannot find variable `d` (VarSymbol) in local or global scope.\n//│ ║  l.172: \tlet d = Counter(c.Counter#get())\n//│ ╙──       \t    ^\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Missing type definition for symbol `member:Counter`\n\n:todo\nc.Counter#get()\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Missing type definition for symbol `member:Counter`\n\n\nclass GetterOnly() with\n  fun f = 1\nGetterOnly().f()\n//│ Wasm result:\n//│ = 1\n\n\n:ge\nclass A(val x) with\n  fun get() = x\nA(1).get\n//│ ╔══[COMPILATION ERROR] `member:get` is neither a field access nor a callable method\n//│ ║  l.197: \tA(1).get\n//│ ╙──       \t    ^^^^\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/ControlFlow.mls",
    "content": "\n:global\n:wasm\n\n\nif 1 === 2 do 2 + 2\n//│ Wasm result:\n//│ = {}\n\n\n:wat\nlet i = 0 in\n  while i < 10 then set i += 1\n  i\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $lt_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $Unit (sub $Object (struct (field $$tag (mut i32)))))\n//│   (type $Unit_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $Unit_ctor (func (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (type $start (func))\n//│   (import \"system\" \"lt_impl\" (func $lt_impl (type $lt_impl)))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (global $Unit$inst (export \"Unit$inst\") (mut (ref null $Unit)) (ref.null $Unit))\n//│   (func $Unit_init (type $Unit_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (nop)\n//│       (return\n//│         (local.get $this))))\n//│   (func $Unit_Unit (type $Unit_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Unit))\n//│       (struct.set $Unit $$tag\n//│         (ref.cast (ref $Unit)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Unit_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $start (type $start)\n//│     (block\n//│       (global.set $Unit$inst\n//│         (ref.cast (ref null $Unit)\n//│           (call $Unit_Unit)))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $i (ref null any))\n//│     (local $scrut (ref null any))\n//│     (local $tmp (ref null any))\n//│     (local $matchRes (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $i\n//│         (ref.i31\n//│           (i32.const 0)))\n//│       (block (result (ref null any))\n//│         (block $lbl\n//│           (loop $lbl_cont\n//│             (drop\n//│               (block (result (ref null any))\n//│                 (local.set $scrut\n//│                   (call $lt_impl\n//│                     (local.get $i)\n//│                     (ref.i31\n//│                       (i32.const 10))))\n//│                 (block (result (ref null any))\n//│                   (block $match\n//│                     (local.set $matchRes\n//│                       (ref.null any))\n//│                     (if\n//│                       (i32.eq\n//│                         (i31.get_s\n//│                           (ref.cast (ref null i31)\n//│                             (local.get $scrut)))\n//│                         (i32.const 1))\n//│                       (then\n//│                         (block $arm\n//│                           (block\n//│                             (block\n//│                               (local.set $tmp\n//│                                 (call $plus_impl\n//│                                   (local.get $i)\n//│                                   (ref.i31\n//│                                     (i32.const 1))))\n//│                               (block\n//│                                 (local.set $i\n//│                                   (local.get $tmp))\n//│                                 (br $lbl_cont)))\n//│                             (local.set $matchRes\n//│                               (global.get $Unit$inst)))\n//│                           (br $match))))\n//│                     (block\n//│                       (nop)\n//│                       (local.set $matchRes\n//│                         (global.get $Unit$inst))))\n//│                   (local.get $matchRes))))))\n//│         (local.get $i))))\n//│   (elem $Unit_init declare func $Unit_init)\n//│   (elem $Unit_Unit declare func $Unit_Unit)\n//│   (elem $start declare func $start)\n//│   (elem $entry declare func $entry)\n//│   (start $start))\n//│ Wasm result:\n//│ = 10\n\n\nfun f() =\n  while true do\n    return 42\nf()\n//│ Wasm result:\n//│ = 42\n\n\nlet x = true\nwhile x do set x = false\n//│ Wasm result:\n//│ = {}\n\n\nfun foo() =\n    let x = 1\n    while false do set x = 0\nfoo()\n//│ Wasm result:\n//│ = {}\n\n\nlet c = 0\nlet x = 0\nwhile x < 5 do\n  let y = 0\n  while y < 5 do\n    set c += 1\n    set y += 1\n  set x += 1\nc\n//│ Wasm result:\n//│ = 25\n\n\nfun nonTailMatchReturn(x) =\n  if x is\n    0 then return 100\n    1 then 10\n    else 20\n  x + 1\nnonTailMatchReturn(0)\n//│ Wasm result:\n//│ = 100\n\n\nfun tailMatchReturn(x) =\n  if x is\n    0 then return 7\n    1 then x + 41\n    else 99\ntailMatchReturn(0)\n//│ Wasm result:\n//│ = 7\n\n\nfun loopMatchReturn() =\n  let i = 0 in\n    while true do\n      if i is\n        3 then return i\n        else set i += 1\nloopMatchReturn()\n//│ Wasm result:\n//│ = 3\n\n\n:wat\nfun tailMatchAllValue(x) =\n  if x is\n    0 then 10\n    1 then 20\n    else 30\ntailMatchAllValue(1)\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $tailMatchAllValue (func (param $x (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (func $tailMatchAllValue (export \"tailMatchAllValue\") (type $tailMatchAllValue) (param $x (ref null any)) (result (ref null any))\n//│     (local $matchRes (ref null any))\n//│     (block (result (ref null any))\n//│       (block $match\n//│         (local.set $matchRes\n//│           (ref.null any))\n//│         (if\n//│           (i32.eq\n//│             (i31.get_s\n//│               (ref.cast (ref null i31)\n//│                 (local.get $x)))\n//│             (i32.const 0))\n//│           (then\n//│             (block $arm\n//│               (return\n//│                 (ref.i31\n//│                   (i32.const 10)))\n//│               (br $match))))\n//│         (if\n//│           (i32.eq\n//│             (i31.get_s\n//│               (ref.cast (ref null i31)\n//│                 (local.get $x)))\n//│             (i32.const 1))\n//│           (then\n//│             (block $arm\n//│               (return\n//│                 (ref.i31\n//│                   (i32.const 20)))\n//│               (br $match))))\n//│         (return\n//│           (ref.i31\n//│             (i32.const 30))))\n//│       (local.get $matchRes)))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tailMatchAllValue (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (call $tailMatchAllValue\n//│         (ref.i31\n//│           (i32.const 1)))))\n//│   (elem $tailMatchAllValue declare func $tailMatchAllValue)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 20\n\n\nfun tailMatchStmtBranch(x) =\n  let y = 0 in\n    if x is\n      0 then\n        set y += 1\n      else 42\ntailMatchStmtBranch(0)\n//│ Wasm result:\n//│ = {}\n\n\nfun tailMatchStmtDefault(x) =\n  let y = 0 in\n    if x is\n      0 then 11\n      else\n        set y += 1\ntailMatchStmtDefault(2)\n//│ Wasm result:\n//│ = {}\n\n\nfun nonTailStmtMatch(x) =\n  let y = 0 in\n    if x is\n      0 then\n        set y += 1\n      else 5\n    y\nnonTailStmtMatch(0)\n//│ Wasm result:\n//│ = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/Exceptions.mls",
    "content": "\n:global\n:wasm\n\n\n:wat\n:re\nthrow 1\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $mlx_exn (func (param $ex (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (tag $mlx_exn (export \"mlx_exn\") (type $mlx_exn))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (throw $mlx_exn\n//│       (ref.i31\n//│         (i32.const 1))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] 1\n\n:re\nlet x = 2\nthrow x\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] 2\n\n:re\nthrow false\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] 0\n\n:ge\nlet x = 1\nset x += 1 in x\n//│ ═══[COMPILATION ERROR] WatBuilder::returningTerm for TryBlock(...) not implemented yet\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/MainFunctions.mls",
    "content": "\n:global\n:wasm\n\n\nlet x = 0\n//│ Wasm result:\n//│ = {}\n\n\nclass Foo(val x)\n//│ Wasm result:\n//│ = {}\n\n\nobject Bar with\n    val x = 1\n//│ Wasm result:\n//│ = {}\n\n\nfun foo() = 42\n//│ Wasm result:\n//│ = {}\n\n\n:re\n:wat\nlet x = 2\nthrow x\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $mlx_exn (func (param $ex (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (tag $mlx_exn (export \"mlx_exn\") (type $mlx_exn))\n//│   (global $x (export \"x\") (mut (ref null any)) (ref.null any))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (block\n//│       (global.set $x\n//│         (ref.i31\n//│           (i32.const 2)))\n//│       (throw $mlx_exn\n//│         (global.get $x))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] 2\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/Matching.mls",
    "content": "\n:global\n:wasm\n\nif true then 0 else 2\n//│ Wasm result:\n//│ = 0\n\nif false then 1 else 0\n//│ Wasm result:\n//│ = 0\n\nclass Foo(val x)\nif Foo(42) is Foo(a) then 0 else 1\n//│ Wasm result:\n//│ = 0\n\nclass Foo(val x)\nif Foo(42) is Foo(a) then a else 1\n//│ Wasm result:\n//│ = 42\n\nclass Foo(val x)\nif 1 is Foo(a) then a else 1\n//│ Wasm result:\n//│ = 1\n\nclass Bar(val y)\nclass Baz(val z)\nif Baz(10) is\n  Bar(a) then a\n  Baz(b) then 1\n  else 0\n//│ Wasm result:\n//│ = 1\n\n:wat\nclass Bar(val y)\nclass Baz(val z)\nif Bar(true) is\n  Bar(a) then if a then 3 else 4\n  Baz(b) then b\n  else 2\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Bar (sub $Object (struct (field $$tag (mut i32)) (field $y (mut (ref null any))))))\n//│   (type $Baz (sub $Object (struct (field $$tag (mut i32)) (field $z (mut (ref null any))))))\n//│   (type $Bar_init (func (param $this (ref null any)) (param $y (ref null any)) (result (ref null any))))\n//│   (type $Baz_init (func (param $this (ref null any)) (param $z (ref null any)) (result (ref null any))))\n//│   (type $Bar_ctor (func (param $y (ref null any)) (result (ref null any))))\n//│   (type $Baz_ctor (func (param $z (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (func $Bar_init (type $Bar_init) (param $this (ref null any)) (param $y (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Bar $y\n//│           (ref.cast (ref $Bar)\n//│             (local.get $this))\n//│           (local.get $y))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Baz_init (type $Baz_init) (param $this (ref null any)) (param $z (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Baz $z\n//│           (ref.cast (ref $Baz)\n//│             (local.get $this))\n//│           (local.get $z))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Bar_ctor (export \"Bar\") (type $Bar_ctor) (param $y (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Bar))\n//│       (struct.set $Bar $$tag\n//│         (ref.cast (ref $Bar)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Bar_init\n//│           (local.get $this)\n//│           (local.get $y)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Baz_ctor (export \"Baz\") (type $Baz_ctor) (param $z (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Baz))\n//│       (struct.set $Baz $$tag\n//│         (ref.cast (ref $Baz)\n//│           (local.get $this))\n//│         (i32.const 2))\n//│       (drop\n//│         (call $Baz_init\n//│           (local.get $this)\n//│           (local.get $z)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $scrut (ref null any))\n//│     (local $a (ref null any))\n//│     (local $b (ref null any))\n//│     (local $arg$Baz$0$ (ref null any))\n//│     (local $arg$Bar$0$ (ref null any))\n//│     (local $matchRes (ref null any))\n//│     (local $matchRes1 (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block (result (ref null any))\n//│         (nop)\n//│         (block (result (ref null any))\n//│           (local.set $scrut\n//│             (call $Bar_ctor\n//│               (ref.i31\n//│                 (i32.const 1))))\n//│           (block (result (ref null any))\n//│             (block $match\n//│               (local.set $matchRes\n//│                 (ref.null any))\n//│               (if\n//│                 (ref.test (ref null $Object)\n//│                   (local.get $scrut))\n//│                 (then\n//│                   (if\n//│                     (i32.eq\n//│                       (struct.get $Object $$tag\n//│                         (ref.cast (ref $Object)\n//│                           (local.get $scrut)))\n//│                       (i32.const 1))\n//│                     (then\n//│                       (block $arm\n//│                         (local.set $matchRes\n//│                           (block (result (ref null any))\n//│                             (local.set $arg$Bar$0$\n//│                               (struct.get $Bar $y\n//│                                 (ref.cast (ref $Bar)\n//│                                   (local.get $scrut))))\n//│                             (block (result (ref null any))\n//│                               (local.set $a\n//│                                 (local.get $arg$Bar$0$))\n//│                               (block (result (ref null any))\n//│                                 (block $match1\n//│                                   (local.set $matchRes1\n//│                                     (ref.null any))\n//│                                   (if\n//│                                     (i32.eq\n//│                                       (i31.get_s\n//│                                         (ref.cast (ref null i31)\n//│                                           (local.get $a)))\n//│                                       (i32.const 1))\n//│                                     (then\n//│                                       (block $arm\n//│                                         (local.set $matchRes1\n//│                                           (ref.i31\n//│                                             (i32.const 3)))\n//│                                         (br $match1))))\n//│                                   (local.set $matchRes1\n//│                                     (ref.i31\n//│                                       (i32.const 4))))\n//│                                 (local.get $matchRes1)))))\n//│                         (br $match))))))\n//│               (if\n//│                 (ref.test (ref null $Object)\n//│                   (local.get $scrut))\n//│                 (then\n//│                   (if\n//│                     (i32.eq\n//│                       (struct.get $Object $$tag\n//│                         (ref.cast (ref $Object)\n//│                           (local.get $scrut)))\n//│                       (i32.const 2))\n//│                     (then\n//│                       (block $arm\n//│                         (local.set $matchRes\n//│                           (block (result (ref null any))\n//│                             (local.set $arg$Baz$0$\n//│                               (struct.get $Baz $z\n//│                                 (ref.cast (ref $Baz)\n//│                                   (local.get $scrut))))\n//│                             (block (result (ref null any))\n//│                               (local.set $b\n//│                                 (local.get $arg$Baz$0$))\n//│                               (local.get $b))))\n//│                         (br $match))))))\n//│               (local.set $matchRes\n//│                 (ref.i31\n//│                   (i32.const 2))))\n//│             (local.get $matchRes))))))\n//│   (elem $Bar_init declare func $Bar_init)\n//│   (elem $Baz_init declare func $Baz_init)\n//│   (elem $Bar_ctor declare func $Bar_ctor)\n//│   (elem $Baz_ctor declare func $Baz_ctor)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 3\n\n:re\nclass Bar(val y)\nclass Baz(val z)\nif Baz(10) is\n  Bar(a) then 0\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] match error\n\n:re\nif false then 1\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] match error\n\nclass Foo(val x, val y)\nif Foo(1,2) is Foo(a,b) then 0\n//│ Wasm result:\n//│ = 0\n\nclass Foo(val x)\nfun getXor(f) = if f is Foo(a) then a else false\ngetXor(Foo(42))\n//│ Wasm result:\n//│ = 42\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/ReplImports.mls",
    "content": "\n:global\n:wasm\n\nobject Foo with\n  val x = 1\nclass C(val x)\nfun inc(x) = x + 1\nval step = 2\nlet counter = 1\nlet unit = ()\n//│ Wasm result:\n//│ = {}\n\ninc(Foo.x)\n//│ Wasm result:\n//│ = 2\n\nif C(7) is C(v) then v else 0\n//│ Wasm result:\n//│ = 7\n\n:wat\nset counter += step\ncounter\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (import \"repl\" \"counter\" (global $counter (mut (ref null any))))\n//│   (import \"repl\" \"step\" (global $step (mut (ref null any))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tmp (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $tmp\n//│         (call $plus_impl\n//│           (global.get $counter)\n//│           (global.get $step)))\n//│       (block (result (ref null any))\n//│         (global.set $counter\n//│           (local.get $tmp))\n//│         (global.get $counter))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 3\n\nunit\n//│ Wasm result:\n//│ = {}\n\n:wat\n()\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Unit (sub $Object (struct (field $$tag (mut i32)))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"repl\" \"Unit$inst\" (global $Unit (mut (ref null $Unit))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (global.get $Unit))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = {}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/ScopedLocals.mls",
    "content": "\n:global\n:wasm\n\n\n:wat\nlet topA = 1\nlet topB = 2\ntopA + topB\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (global $topA (export \"topA\") (mut (ref null any)) (ref.null any))\n//│   (global $topB (export \"topB\") (mut (ref null any)) (ref.null any))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (global.set $topA\n//│         (ref.i31\n//│           (i32.const 1)))\n//│       (block (result (ref null any))\n//│         (global.set $topB\n//│           (ref.i31\n//│             (i32.const 2)))\n//│         (call $plus_impl\n//│           (global.get $topA)\n//│           (global.get $topB)))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 3\n\n\n:wat\nfun chain(x) =\n  let a = x + 1\n  let b = a + 1\n  a + b\nchain(1)\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $plus_impl (func (param $lhs (ref null any)) (param $rhs (ref null any)) (result (ref null any))))\n//│   (type $chain (func (param $x (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"plus_impl\" (func $plus_impl (type $plus_impl)))\n//│   (func $chain (export \"chain\") (type $chain) (param $x (ref null any)) (result (ref null any))\n//│     (local $a (ref null any))\n//│     (local $b (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $a\n//│         (call $plus_impl\n//│           (local.get $x)\n//│           (ref.i31\n//│             (i32.const 1))))\n//│       (block (result (ref null any))\n//│         (local.set $b\n//│           (call $plus_impl\n//│             (local.get $a)\n//│             (ref.i31\n//│               (i32.const 1))))\n//│         (return\n//│           (call $plus_impl\n//│             (local.get $a)\n//│             (local.get $b))))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $chain (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (call $chain\n//│         (ref.i31\n//│           (i32.const 1)))))\n//│   (elem $chain declare func $chain)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 5\n\n\nfun ifLocals(flag) =\n  if flag then\n    let a = 10\n    a + 1\n  else\n    let b = 20\n    b + 2\nifLocals(true)\nifLocals(false)\n//│ Wasm result:\n//│ = 22\n\n\nfun litMatch(x) =\n  if x is\n    0 then\n      let arm = 10\n      arm\n    1 then\n      let arm = 20\n      arm\n    else\n      let arm = 30\n      arm\nlitMatch(0)\nlitMatch(1)\nlitMatch(9)\n//│ Wasm result:\n//│ = 30\n\n\nfun nestedInArm(x) =\n  if x is\n    0 then\n      let a = 40\n      if true then\n        let b = a + 2\n        b\n      else\n        0\n    else\n      0\nnestedInArm(0)\n//│ Wasm result:\n//│ = 42\n\n\n:wat\nclass Foo(val a, val b)\n(new Foo(42, 1)).Foo#a\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Foo (sub $Object (struct (field $$tag (mut i32)) (field $a (mut (ref null any))) (field $b (mut (ref null any))))))\n//│   (type $Foo_init (func (param $this (ref null any)) (param $a (ref null any)) (param $b (ref null any)) (result (ref null any))))\n//│   (type $Foo_ctor (func (param $a (ref null any)) (param $b (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (func $Foo_init (type $Foo_init) (param $this (ref null any)) (param $a (ref null any)) (param $b (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Foo $a\n//│           (ref.cast (ref $Foo)\n//│             (local.get $this))\n//│           (local.get $a))\n//│         (block\n//│           (struct.set $Foo $b\n//│             (ref.cast (ref $Foo)\n//│               (local.get $this))\n//│             (local.get $b))\n//│           (nop)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Foo_ctor (export \"Foo\") (type $Foo_ctor) (param $a (ref null any)) (param $b (ref null any)) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Foo))\n//│       (struct.set $Foo $$tag\n//│         (ref.cast (ref $Foo)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Foo_init\n//│           (local.get $this)\n//│           (local.get $a)\n//│           (local.get $b)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tmp (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block (result (ref null any))\n//│         (local.set $tmp\n//│           (call $Foo_ctor\n//│             (ref.i31\n//│               (i32.const 42))\n//│             (ref.i31\n//│               (i32.const 1))))\n//│         (struct.get $Foo $a\n//│           (ref.cast (ref $Foo)\n//│             (local.get $tmp))))))\n//│   (elem $Foo_init declare func $Foo_init)\n//│   (elem $Foo_ctor declare func $Foo_ctor)\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 42\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/SingletonUnit.mls",
    "content": "\n:global\n:wasm\n\n:wat\n()\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Unit (sub $Object (struct (field $$tag (mut i32)))))\n//│   (type $Unit_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $Unit_ctor (func (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (type $start (func))\n//│   (global $Unit$inst (export \"Unit$inst\") (mut (ref null $Unit)) (ref.null $Unit))\n//│   (func $Unit_init (type $Unit_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (nop)\n//│       (return\n//│         (local.get $this))))\n//│   (func $Unit_Unit (type $Unit_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Unit))\n//│       (struct.set $Unit $$tag\n//│         (ref.cast (ref $Unit)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Unit_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $start (type $start)\n//│     (block\n//│       (global.set $Unit$inst\n//│         (ref.cast (ref null $Unit)\n//│           (call $Unit_Unit)))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (global.get $Unit$inst))\n//│   (elem $Unit_init declare func $Unit_init)\n//│   (elem $Unit_Unit declare func $Unit_Unit)\n//│   (elem $start declare func $start)\n//│   (elem $entry declare func $entry)\n//│   (start $start))\n//│ Wasm result:\n//│ = {}\n\n\nif true then () else 0\n//│ Wasm result:\n//│ = {}\n\n\nfun foo() = ()\nfoo()\n//│ Wasm result:\n//│ = {}\n\n\nlet x = 1\n()\n//│ Wasm result:\n//│ = {}\n\n\n[(), 1].[0]\n//│ Wasm result:\n//│ = {}\n\n\nobject O with\n    val unit = ()\nO.unit\n//│ Wasm result:\n//│ = {}\n\n\n// confirms no start function when singletons are not present\n:wat\nlet x = 1\nx\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $entry (func (result (ref null any))))\n//│   (global $x (export \"x\") (mut (ref null any)) (ref.null any))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (global.set $x\n//│         (ref.i31\n//│           (i32.const 1)))\n//│       (global.get $x)))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/Singletons.mls",
    "content": "\n:global\n:wasm\n\n\n:wat\nobject Foo with\n  val x = 1\nobject Bar with\n  val y = 2\nBar.y\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $Foo (sub $Object (struct (field $$tag (mut i32)) (field $x (mut (ref null any))))))\n//│   (type $Bar (sub $Object (struct (field $$tag (mut i32)) (field $y (mut (ref null any))))))\n//│   (type $Foo_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $Bar_init (func (param $this (ref null any)) (result (ref null any))))\n//│   (type $Foo_ctor (func (result (ref null any))))\n//│   (type $Bar_ctor (func (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (type $start (func))\n//│   (global $Foo$inst (export \"Foo$inst\") (mut (ref null $Foo)) (ref.null $Foo))\n//│   (global $Bar$inst (export \"Bar$inst\") (mut (ref null $Bar)) (ref.null $Bar))\n//│   (func $Foo_init (type $Foo_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Foo $x\n//│           (ref.cast (ref $Foo)\n//│             (local.get $this))\n//│           (ref.i31\n//│             (i32.const 1)))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Bar_init (type $Bar_init) (param $this (ref null any)) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block\n//│         (struct.set $Bar $y\n//│           (ref.cast (ref $Bar)\n//│             (local.get $this))\n//│           (ref.i31\n//│             (i32.const 2)))\n//│         (nop))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Foo_ctor (type $Foo_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Foo))\n//│       (struct.set $Foo $$tag\n//│         (ref.cast (ref $Foo)\n//│           (local.get $this))\n//│         (i32.const 1))\n//│       (drop\n//│         (call $Foo_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $Bar_ctor (type $Bar_ctor) (result (ref null any))\n//│     (local $this (ref null any))\n//│     (block (result (ref null any))\n//│       (local.set $this\n//│         (struct.new_default $Bar))\n//│       (struct.set $Bar $$tag\n//│         (ref.cast (ref $Bar)\n//│           (local.get $this))\n//│         (i32.const 2))\n//│       (drop\n//│         (call $Bar_init\n//│           (local.get $this)))\n//│       (return\n//│         (local.get $this))))\n//│   (func $start (type $start)\n//│     (block\n//│       (global.set $Foo$inst\n//│         (ref.cast (ref null $Foo)\n//│           (call $Foo_ctor)))\n//│       (global.set $Bar$inst\n//│         (ref.cast (ref null $Bar)\n//│           (call $Bar_ctor)))))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (block (result (ref null any))\n//│       (nop)\n//│       (block (result (ref null any))\n//│         (nop)\n//│         (struct.get $Bar $y\n//│           (ref.cast (ref $Bar)\n//│             (global.get $Bar$inst))))))\n//│   (elem $Foo_init declare func $Foo_init)\n//│   (elem $Bar_init declare func $Bar_init)\n//│   (elem $Foo_ctor declare func $Foo_ctor)\n//│   (elem $Bar_ctor declare func $Bar_ctor)\n//│   (elem $start declare func $start)\n//│   (elem $entry declare func $entry)\n//│   (start $start))\n//│ Wasm result:\n//│ = 2\n\n\n\nobject Example with\n  val a = [10, 20]\nExample.a.[1]\n//│ Wasm result:\n//│ = 20\n\n\nobject O with\n  val x = 1\n  val gy = x\nO.gy\n//│ Wasm result:\n//│ = 1\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/Strings.mls",
    "content": "\n:global\n:wasm\n\n\"Hello World!\"\n//│ Wasm result:\n//│ = \"Hello World!\"\n\n\"\"\n//│ Wasm result:\n//│ = \"\"\n\n:wat\nlet dup1 = \"dup\"\nlet dup2 = \"dup\"\n[dup1, dup2].[1]\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $mlx_str_from_utf16 (func (param $glob_offset (ref null any)) (param $len (ref null any)) (result (ref null any))))\n//│   (type $TupleArray (array (ref null any)))\n//│   (type $TupleArrayMut (array (mut (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"mlx_str_from_utf16\" (func $mlx_str_from_utf16 (type $mlx_str_from_utf16)))\n//│   (import \"system\" \"mem\" (memory $mem 1))\n//│   (global $dup1 (export \"dup1\") (mut (ref null any)) (ref.null any))\n//│   (global $dup2 (export \"dup2\") (mut (ref null any)) (ref.null any))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tmp (ref null any))\n//│     (local $tuple (ref null any))\n//│     (block (result (ref null any))\n//│       (global.set $dup1\n//│         (call $mlx_str_from_utf16\n//│           (ref.i31\n//│             (i32.const 0))\n//│           (ref.i31\n//│             (i32.const 6))))\n//│       (block (result (ref null any))\n//│         (global.set $dup2\n//│           (call $mlx_str_from_utf16\n//│             (ref.i31\n//│               (i32.const 0))\n//│             (ref.i31\n//│               (i32.const 6))))\n//│         (block (result (ref null any))\n//│           (local.set $tmp\n//│             (array.new_fixed $TupleArray 2\n//│               (global.get $dup1)\n//│               (global.get $dup2)))\n//│           (if (result (ref null any))\n//│             (ref.test (ref null $TupleArrayMut)\n//│               (local.tee $tuple\n//│                 (local.get $tmp)))\n//│             (then\n//│               (array.get $TupleArrayMut\n//│                 (ref.cast (ref $TupleArrayMut)\n//│                   (local.get $tuple))\n//│                 (i32.const 1)))\n//│             (else\n//│               (array.get $TupleArray\n//│                 (ref.cast (ref $TupleArray)\n//│                   (local.get $tuple))\n//│                 (i32.const 1))))))))\n//│   (data $dup (i32.const 0) \"\\64\\00\\75\\00\\70\\00\")\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = \"dup\"\n\nlet s = \"mlx\"\ns\n//│ Wasm result:\n//│ = \"mlx\"\n\nlet t = [\"a\", \"b\", \"c\"]\nt.[1]\n//│ Wasm result:\n//│ = \"b\"\n\n// For testing that function indices are stable\nfun id(x) = x\nlet s2 = \"hello\"\nif true then id(1) else s2\n//│ Wasm result:\n//│ = 1\n\n\n// Identifier Truncation\n:wat\n\"abcdefghijklmnopqrstuvwxyz\"\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $mlx_str_from_utf16 (func (param $glob_offset (ref null any)) (param $len (ref null any)) (result (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (import \"system\" \"mlx_str_from_utf16\" (func $mlx_str_from_utf16 (type $mlx_str_from_utf16)))\n//│   (import \"system\" \"mem\" (memory $mem 1))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (call $mlx_str_from_utf16\n//│       (ref.i31\n//│         (i32.const 0))\n//│       (ref.i31\n//│         (i32.const 52))))\n//│   (data $abcdefghijklmnop (i32.const 0) \"\\61\\00\\62\\00\\63\\00\\64\\00\\65\\00\\66\\00\\67\\00\\68\\00\\69\\00\\6a\\00\\6b\\00\\6c\\00\\6d\\00\\6e\\00\\6f\\00\\70\\00\\71\\00\\72\\00\\73\\00\\74\\00\\75\\00\\76\\00\\77\\00\\78\\00\\79\\00\\7a\\00\")\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = \"abcdefghijklmnopqrstuvwxyz\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript/wasm/Tuples.mls",
    "content": "\n:global\n:wasm\n\n[]\n//│ Wasm result:\n//│ = {}\n\n[0, 1, 2]\n//│ Wasm result:\n//│ = {}\n\nfun makePair(x, y) = [x, y]\nmakePair(1, 2).[1]\n//│ Wasm result:\n//│ = 2\n\nclass Foo(val x, val y)\nlet b = [Foo(0, 1), true, 2]\nif b.[0] is Foo(x, y) then x else 3\n//│ Wasm result:\n//│ = 0\n\nlet nums = [1, 2, 3]\nnums.[-1]\n//│ Wasm result:\n//│ = 3\n\nlet nums = mut [1, 2, 3]\nset nums.[0] = 0\nnums.[0]\n//│ Wasm result:\n//│ = 0\n\n:re\nlet nums = [1, 2, 3]\nset nums.[0] = 0\nnums.[0]\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] RuntimeError: illegal cast\n\n:re\nlet nums = [1, 2, 3]\nnums.[3]\n//│ Wasm result:\n//│ ═══[RUNTIME ERROR] RuntimeError: array element access out of bounds\n\n\n:wat\nlet c = [10, 20, 30, 40]\nc.[3]\n//│ Wat:\n//│ (module\n//│   (type $Object (sub (struct (field $$tag (mut i32)))))\n//│   (type $TupleArray (array (ref null any)))\n//│   (type $TupleArrayMut (array (mut (ref null any))))\n//│   (type $entry (func (result (ref null any))))\n//│   (global $c (export \"c\") (mut (ref null any)) (ref.null any))\n//│   (func $entry (export \"entry\") (type $entry) (result (ref null any))\n//│     (local $tuple (ref null any))\n//│     (block (result (ref null any))\n//│       (global.set $c\n//│         (array.new_fixed $TupleArray 4\n//│           (ref.i31\n//│             (i32.const 10))\n//│           (ref.i31\n//│             (i32.const 20))\n//│           (ref.i31\n//│             (i32.const 30))\n//│           (ref.i31\n//│             (i32.const 40))))\n//│       (if (result (ref null any))\n//│         (ref.test (ref null $TupleArrayMut)\n//│           (local.tee $tuple\n//│             (global.get $c)))\n//│         (then\n//│           (array.get $TupleArrayMut\n//│             (ref.cast (ref $TupleArrayMut)\n//│               (local.get $tuple))\n//│             (i32.const 3)))\n//│         (else\n//│           (array.get $TupleArray\n//│             (ref.cast (ref $TupleArray)\n//│               (local.get $tuple))\n//│             (i32.const 3))))))\n//│   (elem $entry declare func $entry))\n//│ Wasm result:\n//│ = 40\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/.gitignore",
    "content": "*.mjs\n!/Predef.mjs\n!/Runtime.mjs\n!/RuntimeJS.mjs\n!/apps/parsing/vendors/railroad/railroad.mjs\n!/NoFreeze.mjs\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Block.mls",
    "content": "import \"./Predef.mls\"\nimport \"./Option.mls\"\nimport \"./StrOps.mls\"\nimport \"./Runtime.mls\"\n\nopen Predef\nopen StrOps\nopen Option\n\nmodule Block with...\n\ntype Opt[A] = Option[A]\n\n// dependancies referenced in Block classes, referencing implementation in Term.mls\n\ntype Literal = null | undefined | Str | Int | Num | Bool\n\ntype ParamList = Array[Symbol]\n\nclass Symbol(val name: Str)\n// this is so that we're able to retrieve information about the class from the symbol\nclass ClassSymbol(val name: Str) extends Symbol(name)\nclass VirtualClassSymbol(val name: Str) extends ClassSymbol(name)\nclass ConcreteClassSymbol(val name: Str, val value: Class, val paramsOpt: Opt[ParamList], val auxParams: Array[ParamList]) extends ClassSymbol(name)\nclass ModuleSymbol(val name: Str, val value: Class) extends Symbol(name)\nclass NoSymbol() extends Symbol(\"$no_symbol$\")\nclass Arm(val cse: Case, val body: Block)\n\nfun isPrimitiveType(sym: Symbol) =\n  if sym.name is\n    \"Str\" then true\n    \"Int\" then true\n    \"Num\" then true\n    \"Bool\" then true\n    else false\n\nfun isPrimitiveTypeOf(sym: Symbol, l: Literal) =\n  if [sym.name, l] is\n    [\"Str\", l] and l is Str then true\n    [\"Int\", i] and i is Int then true\n    [\"Num\", n] and n is Num then true\n    [\"Bool\", b] and b is Bool then true\n    else false\n\n\n// Classes defined in Block.scala\n\nclass Arg(val value: Path) \n\nclass Case with\n  constructor\n    Lit(val lit: Literal)\n    Cls(val cls: Symbol, val path: Path)\n    Tup(val len: Int)\n\nclass Result with \n  constructor\n    Call(val _fun: Path, val args: Array[Arg])\n    Instantiate(val cls: Path, val args: Array[Arg]) // assume immutable\n    Tuple(val elems: Array[Arg]) // assume immutable\n\nclass Path extends Result with\n  constructor\n    Select(val qual: Path, val name: Symbol)\n    DynSelect(val qual: Path, val fld: Path, val arrayIdx: Bool) // is arrayIdx used?\n    ValueRef(val l: Symbol)\n    ValueLit(val lit: Literal)\n\nclass Defn with \n  constructor \n    ValDefn(val owner: Opt[Symbol], val sym: Symbol, val rhs: Path)\n    ClsLikeDefn(val sym: ConcreteClassSymbol, val methods: Array[FunDefn], val companion: Opt[ClsLikeBody]) // companion unused\n    FunDefn(val sym: Symbol, val params: Array[ParamList], val body: Block)\n\nclass ClsLikeBody(val isym: Symbol, val methods: Array[FunDefn], val publicFields: Array[[Symbol, Symbol]]) // unused\n\nclass Block with\n  constructor\n    Match(val scrut: Path, val arms: Array[Arm], val dflt: Opt[Block], val rest: Block)\n    Return(val res: Result, val implct: Bool)\n    Assign(val lhs: Symbol, val rhs: Result, val rest: Block)\n    Define(val defn: Defn, val rest: Block)\n    Scoped(val symbols: Array[Symbol], val rest: Block)\n    End()\n  \nfun concat(b1: Block, b2: Block) = if b1 is\n  Match(scrut, arms, dflt, rest) then Match(scrut, arms, dflt, concat(rest, b2))\n  Return(res, implct) then b1\n  Assign(lhs, rhs, rest) then Assign(lhs, rhs, concat(rest, b2))\n  Define(defn, rest) then Define(defn, concat(rest, b2))\n  Scoped(symbols, rest) then Scoped(symbols, concat(rest, b2))\n  End() then b2\n\nfun indent(s: Str) = s.replaceAll(\"\\n\", \"\\n  \")\n\nfun showLiteral(l: Literal) =\n  if l is \n    undefined then \"undefined\"\n    null then \"null\"\n    Str then \"\\\"\" + l.toString() + \"\\\"\"\n    else l.toString()\n\nfun showSymbol(s: Symbol) = s.name.replaceAll(\"$\", \"_\")\n\nfun showPath(p: Path): Str =\n  if p is\n    // avoids needing to import the runtime module\n    Select(ValueRef(Symbol(\"runtime\")), ModuleSymbol(\"Unit\", Runtime.Unit)) then \"()\"\n    Select(qual, name) then showPath(qual) + \".\" + showSymbol(name)\n    DynSelect(qual, fld, false) then showPath(qual) + \".(\" + showPath(fld) + \")\"\n    DynSelect(qual, fld, true) then showPath(qual) + \".[\" + showPath(fld) + \"]\"\n    ValueRef(l) then showSymbol(l)\n    ValueLit(lit) then showLiteral(lit)\n\nfun showArg(arg: Arg) =\n  showPath(arg.value)\n\nfun showArgs(args: Array[Arg]) =\n  args.map(showArg).join(\", \")\n\nfun showResult(r: Result): Str =\n  if r is\n    Path then showPath(r)\n    Call(fun_, args) and\n      // use infix to avoid parsing + and - as taking a unary argument\n      args is [lhs, rhs] and fun_ is\n        ValueRef(Symbol(\"+\")) then showArg(lhs) + \" + \" + showArg(rhs)\n        ValueRef(Symbol(\"-\")) then showArg(lhs) + \" - \" + showArg(rhs)\n      else showPath(fun_) + \"(\" + showArgs(args) + \")\"\n    Instantiate(cls, args) then \"new \" + showPath(cls) + (if args.length != 0 then \"(\" + showArgs(args) + \")\" else \"\")\n    Tuple(elems) then \"[\" + showArgs(elems) + \"]\"\n    _ then \"<unknown result>\"\n\n// Case (match arm patterns)\nfun showCase(c) =\n  if c is\n    Lit(l) then showLiteral(l)\n    Cls(cls, _) then showSymbol(cls)\n    Tup(len) then \"[\" + Array(len).fill(\"_\").join(\", \") + \"]\"\n    _ then \"<unknown case>\"\n\nfun showArm(a) =\n  showCase(a.cse) + \" then\" + (if a.body is Return then \" \" else \"\\n  \") + indent(showBlock(a.body))\n\nfun showParams(p: ParamList) =\n  \"(\" + p.map(showSymbol(_)).join(\", \") + \")\"\n\nfun showParamsOpt(p) =\n  if p is\n    Some(s) then showParams(s)\n    None then \"\"\n\nfun showParamList(ps: Array[ParamList]) =\n  ps.map(showParams).join(\"\")\n\nfun showDefn(d: Defn): Str =\n  if d is\n    FunDefn(sym, ps, body) then\n      \"fun \" + showSymbol(sym) + showParamList(ps) + \" =\" +\n      (if body is Return | End then \" \" else \"\\n  \") + indent(showBlock(body))\n    ClsLikeDefn(sym, methods, _) then\n      \"class \" + showSymbol(sym) + showParamsOpt(sym.paramsOpt)\n        + indent((if methods is [] then \"\" else \" with\\n\") + methods.map(showDefn).join(\"\\n\"))\n    // TODO: used to represent assignments in constructors, which still need some adjustments\n    ValDefn(owner, sym, rhs) then\n      \"val \" + showSymbol(sym) + \" = \" + showPath(rhs)\n    _ then \"<unknown defn: \" + d.toString() + \" >\"\n\nfun showBlock(b) =\n  if b is\n    Assign(lhs, rhs, rest) then\n      (if lhs is NoSymbol then \"\" else showSymbol(lhs) + \" = \")\n        + showResult(rhs) + showRestBlock(rest)\n    Define(d, rest) then\n      showDefn(d) + showRestBlock(rest)\n    Return(res, _) then\n      showResult(res)\n    Match(scrut, arms, dflt, rest) then\n      \"if \" + showPath(scrut) + \" is\"\n      + indent(\"\\n\" + arms.map(showArm).join(\"\\n\"))\n      + if dflt is Some(db) then indent(\"\\nelse\" + indent((if db is Return then \" \" else \"\\n\") + showBlock(db))) else \"\"\n      + showRestBlock(rest)\n    Scoped(symbols, rest) then\n      // initialize symbols\n      \"let {\" + symbols.map(showSymbol).join(\", \") + \"}\" + showRestBlock(rest)\n    End() then \"()\"\n    _ then \"<unknown block>\" + b\n\n// removes trailing newline\nfun showRestBlock(b : Block): Str =\n  if b is End then \"\" else \"\\n\" + showBlock(b)\n\nfun show(x) =\n  if x is\n    Symbol then showSymbol(x)\n    Path then showPath(x)\n    Result then showResult(x)\n    Case then showCase(x)\n    Defn then showDefn(x)\n    Block then showBlock(x)\n  else\n    \"<unknown>\"\n\nfun printCode(x) = print(show(x))"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/CSP.mls",
    "content": "import \"./Example.mls\"\nimport \"./quotes/CSPNest.mls\"\nopen Example\nopen CSPNest\n\nmodule CSP with ...\n\nfun test() = 123\nfun foo() =\n  `test`() `+ `1\nfun bar() =\n  `inc`(`0)\nfun baz() = `nest_f`()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/CachedHash.mls",
    "content": "class CachedHash with\n  let _hash = null\n  fun hash() = if _hash !== null then _hash else\n    let h = this.toString() // TODO: use a proper hash function!!\n    set _hash = h\n    h\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Char.mls",
    "content": "\nmodule Char with\n  pattern AnyChar = (Str as s where s.length is 1) => s\n  pattern Lowercase = \"a\" ..= \"z\"\n  pattern Uppercase = \"A\" ..= \"Z\"\n  pattern Letter = Lowercase | Uppercase\n  pattern Digit = \"0\" ..= \"9\"\n  pattern HexDigit = Digit | \"a\" ..= \"f\" | \"A\" ..= \"F\"\n  pattern OctDigit = \"0\" ..= \"7\"\n  pattern BinDigit = \"0\" | \"1\"\n  pattern Whitespace = \" \" | \"\\t\" | \"\\n\" | \"\\r\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Example.mls",
    "content": "\nimport \"./Predef.mls\"\nopen Predef\n\n\nfun privFun = \"hi\"\n\n\nmodule Example with ...\n\n\nfun pubFun = privFun\n\n\nfun (/) funnySlash(f, arg) = f(arg)\n\nfun inc(x) = x + 1\n\nfun test(x) = if x is\n  Int then \"int\"\n  Num then \"num\"\n  Str then \"str\"\n  else \"other\"\n\n\nfun assertFail() =\n  assert false\n\n\nclass Test(val field: Int)\n\nmodule Test with\n  fun next(self: Test) = Test(self.field + 1)\n\nval t = new Test(123)\n\n\n// Example of inheritance\nabstract class Base\nclass Child1 extends Base\nclass Child2 extends Base\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/FingerTreeList.mls",
    "content": "import \"./Option.mls\"\nimport \"./Iter.mls\"\n\nopen Option\nopen Iter\nopen FingerTreeList\n\nfun normIdx(idx, len) =\n  if idx < 0 then idx + len\n  else idx\n\n// Follows the semantics of Array.prototype.slice indices:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice\nfun normIdxSlice(i, len) =\n  if i < 0 and\n    i >= -len then len + i\n    else 0\n  else i\n\ntype Node[T] = Branch2[T] | Branch3[T]\ndata class Branch2[T](size: Int, e1: T, e2: T)\ndata class Branch3[T](size: Int, e1: T, e2: T, e3: T)\n\nfun getNodeSize(node) = if node is\n  Branch2(s, _, _) then s\n  Branch3(s, _, _, _) then s\n  _ then 1\n\nobject Nil\ndata class View[T](e1: T, rest: FingerTree[T])\n\nclass FingerTree[T] extends IterableBase with\n  fun iterator() =\n    let current = this\n    Iterator of () => if popFront(current) is\n      Nil then Result.Done\n      View(head, tail) then\n        set current = tail\n        Result.Next of head\n  fun toString() = \"[\" + this joined(\", \") + \"]\"\n  fun length = FingerTreeList.length(this)\n  fun at(i) = get(i)(this)\n  fun concat(other) = FingerTreeList.concat(this, other)\n  fun slice(beg, end) = \n    let len = this.length\n    set beg = normIdxSlice(beg, len)\n    set end = normIdxSlice(end, len)\n    if beg >= len do\n      return Empty\n    if end >= len do\n      set end = len\n    if end <= beg do\n      return Empty\n    FingerTreeList.dropLeftRight(beg, len - end)(this)\n\nobject Empty extends FingerTree[Nothing] with\n  fun toString() = \"[\" + this joined(\", \") + \"]\"\n\nclass Single[T](val e: T) extends FingerTree[T] with\n  fun toString() = \"[\" + this joined(\", \") + \"]\"\n\n// prefix and suffix are at most length 4\nclass Deep[T](val size: Int, val prefix: Array[T], val middle: FingerTree[Node[T]], val suffix: Array[T]) extends FingerTree[T] with\n  fun toString() = \"[\" + [...this].join(\", \") + \"]\"\n\n// amortized O(log n)\nfun concatMiddle(ft1, middle, ft2) = if [ft1, middle, ft2] is\n  [Empty, [], right] then right\n  [Empty, [x, ...xs], right] then cons(x, concatMiddle(Empty, xs, right))\n  [Single(y), xs, right] then cons(y, concatMiddle(Empty, xs, right))\n  [left, [], Empty] then left\n  [left, [...xs, x], Empty] then snoc(concatMiddle(left, xs, Empty), x)\n  [left, xs, Single(y)] then snoc(concatMiddle(left, xs, Empty), y)\n  [Deep(s1, pre1, dt1, ay1), middle, Deep(s2, ax2, dt2, post2)] then\n    Deep(s1 + s2 + middle.length, pre1, concatMiddle(dt1, toNodes([...ay1, ...middle, ...ax2]), dt2), post2)\n\n// arr should be at most size 8, and at least size 2\nfun toNodes(arr) = if arr is\n  [] then []\n  [a, b, c, d] then [Branch2(getNodeSize(a) + getNodeSize(b), a, b), Branch2(getNodeSize(c) + getNodeSize(d), c, d)]\n  [a, b, c, ...rest] then [Branch3(getNodeSize(a) + getNodeSize(b) + getNodeSize(c), a, b, c), ...toNodes(rest)]\n  [a, b, ...rest] then [Branch2(getNodeSize(a) + getNodeSize(b), a, b), ...toNodes(rest)]\n\n// O(1)\nfun arrayOfNode(node) = if node is\n  Branch2(_, a, b) then [a, b]\n  Branch3(_, a, b, c) then [a, b, c]\n\n// affix should be at most size 4\nfun getAffixSize(arr) = if arr is\n  [] then 0\n  [a, ...rest] then getNodeSize(a) + getAffixSize(rest)\n\nfun ithAffixElement(idx, arr) = if arr is\n  [] then None\n  [a, ...rest] then if idx < getNodeSize(a)\n    then ithNode(idx, a)\n    else ithAffixElement(idx - getNodeSize(a), rest)\n\nfun ithNode(idx, node) = if node is\n  Branch2(s, a, b) and\n    idx >= 0 && idx < s and\n      idx < getNodeSize(a) then ithNode(idx, a)\n      else ithNode(idx - getNodeSize(a), b)\n    else None\n  Branch3(s, a, b, c) and\n    idx >= 0 && idx < s and\n      idx < getNodeSize(a) then ithNode(idx, a)\n      idx < getNodeSize(a) + getNodeSize(b) then ithNode(idx - getNodeSize(a), b)\n      else ithNode(idx - getNodeSize(a) - getNodeSize(b), c)\n    else None\n  a and idx == 0 then Some(a)\n  else None\n\nfun repeatPopFront(n)(xs) =\n  if n is\n    0 then xs\n    _ then if popFront(xs) is\n      Nil then xs\n      View(_, rest) then repeatPopFront(n - 1)(rest)\n\nfun repeatPopBack(n)(xs) =\n  if n is\n    0 then xs\n    _ then if popBack(xs) is\n      Nil then xs\n      View(_, rest) then repeatPopBack(n - 1)(rest)\n\nobject SpliceMarker\n\n\nmodule FingerTreeList with...\n\n\nfun toFingerTree(xs) = if xs is\n  FingerTree then xs\n  else mk(...xs) // assume that the input is iterable if not a finger tree\n\n// amortized O(1)\nfun (+:) cons(x, xs) = if toFingerTree(xs) is\n  Empty then Single(x)\n  Single(y) then Deep(getNodeSize(y) + getNodeSize(x), [x], Empty, [y])\n  Deep(s, ax, dt, ay) then if (ax.length >= 4)\n    then Deep(s + getNodeSize(x), [x, ax.0], cons(Branch3(\n      getNodeSize(ax.1) + getNodeSize(ax.2) + getNodeSize(ax.3),\n      ax.1, ax.2, ax.3), dt), ay)\n    else Deep(s + getNodeSize(x), [x, ...ax], dt, ay)\n\n// amortized O(1)\nfun (:+) snoc(xs, x) = if toFingerTree(xs) is\n  Empty then Single(x)\n  Single(y) then Deep(getNodeSize(y) + getNodeSize(x), [y], Empty, [x])\n  Deep(s, ax, dt, ay) then if (ay.length >= 4)\n    then Deep(s + getNodeSize(x), ax, snoc(dt, Branch3(\n      getNodeSize(ay.0) + getNodeSize(ay.1) + getNodeSize(ay.2),\n      ay.0, ay.1, ay.2)), [ay.3, x])\n    else Deep(s + getNodeSize(x), ax, dt, [...ay, x])\n\nfun mk(...args) = args.reduce(\n    (acc, x) => snoc(acc, x),\n    Empty)\n\nfun isEmpty = case\n  Empty then true\n  _ then false\n\n// O(1)\nfun length = case\n  Array as a then a.length\n  Empty then 0\n  Single(x) then getNodeSize(x)\n  Deep(s, _, _, _) then s\n\n// amortized O(1)\nfun popFront(ft) = if toFingerTree(ft) is\n  Empty then Nil\n  Single(x) then View(x, Empty)\n  Deep(s, [x], dt, ay) then if (popFront(dt)) is\n    Nil then if ay is\n      [y] then View(x, Single(y))\n      [...front, y] then View(x, Deep(s - getNodeSize(x), front, Empty, [y]))\n    View(x', dt') then\n      View(x, Deep(s - getNodeSize(x), arrayOfNode(x'), dt', ay))\n  Deep(s, [x, ...ax], dt, ay) then\n    View(x, Deep(s - getNodeSize(x), ax, dt, ay))\n\n// amortized O(1)\nfun popBack(ft) = if toFingerTree(ft) is\n  Empty then Nil\n  Single(x) then View(x, Empty)\n  Deep(s, ax, dt, [x]) then if popBack(dt) is\n    Nil then if ax is\n      [y] then View(x, Single(y))\n      [y, ...front] then View(x, Deep(s - getNodeSize(x), [y], Empty, front))\n    View(x', dt') then\n      View(x, Deep(s - getNodeSize(x), ax, dt', arrayOfNode(x')))\n  Deep(s, ax, dt, [...ay, y]) then\n    View(y, Deep(s - getNodeSize(y), ax, dt, ay))\n\n// amortized O(log n)\nfun (++) concat(ft1, ft2) = concatMiddle(toFingerTree(ft1), [], toFingerTree(ft2))\n\n// amortized O(log n)\nfun ith(idx) = case\n  Empty then None\n  Single(x) then ithNode(idx, x)\n  Deep(s, ax, dt, ay) and\n    idx >= 0 && idx < s and\n      idx < getAffixSize(ax) then ithAffixElement(idx, ax)\n      idx < getAffixSize(ax) + length(dt) then ith(idx - getAffixSize(ax))(dt)\n      else ithAffixElement(idx - getAffixSize(ax) - length(dt), ay)\n    else None\n\nfun get(idx) = case\n  Array as a then a.at(idx)\n  FingerTree as lft then if ith(normIdx(idx, length(lft)))(lft) is\n    None then throw \"get: index out of bounds\"\n    Some(x) then x\n\nfun toArray(ft) = [...ft]\n\n/// amortized O(beg + end)\nfun dropLeftRight(beg, end)(und) = if beg < 0 || end < 0 || beg + end > length(und)\n    then throw \"dropLeftRight: index out of bounds\"\n    else repeatPopFront(beg)(repeatPopBack(end)(toFingerTree(und)))\n\nfun isFingerTree(xs) = if xs is\n  FingerTree then true\n  else false\n\n// The following functions are not meant for users; it's meant referred to by Runtime.mls\n// TODO: use `FingerTreeList.internals.concat` when this is implemented\n\nfun __markerConcat(...arr) =\n  let acc = FingerTreeList.mk()\n  let idx = 0\n  while idx < arr.length do\n    if arr.[idx] is SpliceMarker then\n      let ftl = arr.[idx + 1]\n      set acc = acc ++ toFingerTree(ftl)\n      set idx = idx + 2\n    else\n      set acc = acc :+ arr.[idx]\n      set idx = idx + 1\n  acc\n\nval __split = SpliceMarker\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Iter.mls",
    "content": "import \"./Predef.mls\"\nimport \"./Option.mls\"\nimport \"./Stack.mls\"\n\nopen Predef\nopen Option { Some, None }\nopen Stack { Nil, Cons }\n\n\nmodule Iter with ...\n\nclass IterableBase with\n  set this.(Symbol.iterator) = iterator\n  fun iterator() = throw new Error(\"Not implemented: iterator()\")\n\n  // require that subclasses are immutable\n  fun toArray() = [...this]\n  \n  let array = null\n  \n  fun asArray =\n    if array is null then\n      set array = toArray() Object.freeze()\n      array\n    else array\n  \n  // * Functions that create a fresh new result\n  fun at(idx) = asArray.at(idx)\n  fun concat(...xs) = asArray.concat(...xs)\n  fun copyWithin(...args) = asArray.copyWithin(...args)\n  fun entries() = asArray.entries()\n  fun every(...args) = asArray.every(...args)\n  fun filter(...args) = asArray.filter(...args)\n  fun find(...args) = asArray.find(...args)\n  fun findIndex(...args) = asArray.findIndex(...args)\n  fun findLast(...args) = asArray.findLast(...args)\n  fun findLastIndex(...args) = asArray.findLastIndex(...args)\n  fun flat(...args) = asArray.flat(...args)\n  fun flatMap(...args) = asArray.flatMap(...args)\n  fun forEach(...args) = asArray.forEach(...args)\n  fun includes(...args) = asArray.includes(...args)\n  fun indexOf(...args) = asArray.indexOf(...args)\n  fun join(...args) = asArray.join(...args)\n  fun keys() = asArray.keys()\n  fun lastIndexOf(...args) = asArray.lastIndexOf(...args)\n  fun map(...args) = asArray.map(...args)\n  fun reduce(...args) = asArray.reduce(...args)\n  fun reduceRight(...args) = asArray.reduceRight(...args)\n  fun slice(...args) = asArray.slice(...args)\n  fun some(...args) = asArray.some(...args)\n  fun toLocaleString(...args) = asArray.toLocaleString(...args)\n  fun toReversed() = asArray.toReversed()\n  fun toSorted(...args) = asArray.toSorted(...args)\n  fun toSpliced(...args) = asArray.toSpliced(...args)\n  fun toString() = asArray.toString()\n  // `with` is an mls keyword\n  fun id\"with\"(...args) = asArray.with(...args)\n  \n  // * Functions that modify the array in place\n  fun fill(...args) = toArray().fill(...args)\n  fun pop() = toArray().pop()\n  fun push(...args) = toArray().push(...args)\n  fun reverse() = toArray().reverse()\n  fun shift() = toArray().shift()\n  fun sort(...args) = toArray().sort(...args)\n  fun splice(...args) = toArray().splice(...args)\n  fun unshift(...args) = toArray().unshift(...args)\n  \n  fun length = asArray.length\n  fun values() = iterator()\n\n// * Implements the `Iterable` protocol.\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol\nclass Iterable(mk) extends IterableBase with\n  fun iterator() = mk()\n\n// * Implements the `Iterator` protocol.\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterator_protocol\nclass Iterator(val next)\n\nmodule Result with\n  class Next(val value) with\n    val done = false\n  object Done with\n    val done = true\n\n\n// A helper function to detect if `Symbol.iterator` is on an object, and if not,\n// indicate the object's class in the error message, which is useful for debugging.\nfun getIterator(something) =\n  let test = something.(Symbol.iterator)\n  if test is undefined then\n    throw TypeError of \"Not an iterable: \" + if\n      something is undefined then \"undefined\"\n      something is null then \"null\"\n      let prototype = Reflect.getPrototypeOf of something\n      prototype is null then \"object\"\n      else prototype.constructor.name\n  else test.call(something)\n\nfun adaptIterable(iterable, makeNext) = Iterable of () =>\n  let iterator = getIterator of iterable\n  Iterator of makeNext of iterator\n\nfun mapping(xs, op) =\n  xs adaptIterable of iterator => () =>\n    let next = iterator.next()\n    if next.done then\n      Result.Done\n    else\n      Result.Next of op(next.value)\n\nfun withMap(op) = _ mapping(op)\n\nfun flattening(xss) =\n  Iterable of () =>\n    let iterableIterator = getIterator of xss\n    // Get the first `Iterator` from the first `Iterable`.\n    let currentIterator = if\n      let firstIterableResult = iterableIterator.next()\n      firstIterableResult.done then None\n      else Some of getIterator of firstIterableResult.value\n    // Recursively skip empty `Iterable`s and get the next `Iterator` and value.\n    fun skipEmptyIterables() = if\n      let nextIterableResult = iterableIterator.next()\n      nextIterableResult.done then None\n      let nextIterator = getIterator of nextIterableResult.value\n      let nextResult = nextIterator.next()\n      nextResult.done then skipEmptyIterables()\n      else Some of [nextIterator, nextResult.value]\n    Iterator of () =>\n      if currentIterator is\n        None then Result.Done // No more `Iterator`s means we're done.\n        Some(iterator) and\n          let next = iterator.next() // The next item from the current `Iterator`.\n          next.done and skipEmptyIterables() is // The current `Iterator` is drained.\n            Some([nextIterator, value]) then\n              set currentIterator = Some of nextIterator\n              Result.Next of value\n            None then\n              set currentIterator = None\n              Result.Done\n          else Result.Next of next.value\n\nfun filtering(xs, op) =\n  xs adaptIterable of iterator => () =>\n    let next = iterator.next()\n    while next.done is false and op(next.value) is false do\n      set next = iterator.next()\n    if next.done then\n      Result.Done\n    else Result.Next of next.value\n\nfun withFilter(op) = _ filtering(op)\n\nfun taking(xs, n) =\n  filtering of xs, _ =>\n    set n -= 1\n    n >= 0\n\nfun withMax(n) = _ taking(n)\n\nfun leaving(xs, n) =\n  filtering of xs, _ =>\n    set n -= 1\n    n < 0\n\nfun withoutAtLeast(n) = _ leaving(n)\n\nfun zippingWithIndex(xs) =\n  let i = 0\n  mapping of xs, x =>\n    let j = i\n    set i = i + 1\n    [x, j]\n\nfun foldingImpl(iterator, acc, op) =\n  let next = iterator.next()\n  while next.done is false do\n    set acc = op(acc, next.value)\n    set next = iterator.next()\n  acc\n\nfun appended(xs, ys) =\n  Iterable of () =>\n    let xsIterator = getIterator of xs\n    let currentIterator = xsIterator\n    Iterator of () => if\n      let next = currentIterator.next()\n      next.done and\n        currentIterator == xsIterator and\n          do set currentIterator = getIterator of ys\n          let next = currentIterator.next()\n          next.done then Result.Done\n          else Result.Next of next.value\n        else Result.Done\n      else Result.Next of next.value\n\nfun withAppended(xs) = _ appended(xs)\n\nfun reduced(xs, op) =\n  let iterator = getIterator of xs\n  let next = iterator.next()\n  if next.done do\n    throw new Error(\"Empty iterator\")\n  foldingImpl(iterator, next.value, op)\n\nfun folded(xs, z, op) =\n  let iterator = getIterator of xs\n  foldingImpl(iterator, z, op)\n\nfun rightFolded(xs, z, op) =\n  let iterator = getIterator of xs\n  fun go() = if\n    let next = iterator.next()\n    next.done is true then\n      z\n    else\n      op of next.value, go()\n  go()\n\nfun joined(xs, sep) =\n  let iterator = getIterator of xs\n  let next = iterator.next()\n  if next.done then \"\" else\n    let sep' = String(sep)\n    foldingImpl of\n      iterator\n      String(next.value)\n      (acc, x) => acc + sep + String(x)\n\nfun firstDefined(xs, op) =\n  let iterator = getIterator of xs\n  let next = iterator.next()\n  let result = None\n  while next.done is false and result is None do\n    set\n      result = op(next.value)\n      next = iterator.next()\n  result\n\n// `exists` is a keyword\nfun some(xs, op) =\n  let iterator = getIterator of xs\n  let next = iterator.next()\n  while next.done is false do\n    if op(next.value) do return true\n    set next = iterator.next()\n  false\n\n// `forall` is a keyword\nfun every(xs, op) =\n  let iterator = getIterator of xs\n  let next = iterator.next()\n  while next.done is false do\n    if op(next.value) is false do return false\n    set next = iterator.next()\n  true\n\nfun each(xs, op) =\n  let iterator = getIterator of xs\n  let next = iterator.next()\n  while next.done is false do\n    op(next.value)\n    set next = iterator.next()\n\nfun toArray(view) = Array.from(view)\n\nfun fromStack(stack) = Iterable of () =>\n  let current = stack\n  Iterator of () => if current is\n    Cons(head, tail) then\n      set current = tail\n      Result.Next of head\n    Nil then Result.Done\n\nfun toStack(xs) = xs rightFolded of Nil, Cons\n\n// Important: This function is used by runtime directly. Do not call any function or make any lambda here.\nfun isArrayLike(xs) = xs is Array | IterableBase\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/LazyArray.mls",
    "content": "import \"./Iter.mls\"\n\nopen Iter\nopen LazyArray\n\n// Helper Methods\nfun normIdx(i, len) =\n  if i < 0 then len + i\n  else i\n\nfun enforceArray = case\n  LazyArr | Array | String | Str | TypedArray  as a then a\n  ow then throw Error(\"Expected an Array, got: \" + ow.toString())\n\nfun concatHelper(a, l, ...args) =\n  let\n    idx = 0\n    init_len = a.length\n  set a.length = init_len + args.length * 2\n  while (idx < args.length) do\n    let x = args.[idx]\n    set \n      a.[init_len + idx * 2] = SpliceMarker\n      a.[init_len + idx * 2 + 1] = enforceArray(x)\n      l += x.length\n      idx += 1\n  Splice of a, l\n\n// Follows the semantics of Array.prototype.slice indices:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice\nfun normIdxSlice(i, len) =\n  if i < 0 and\n    i >= -len then len + i\n    else 0\n  else i\n\nfun sliceHelper(beg, fin, arr) =\n  let len = arr.length\n  set beg = normIdxSlice(beg, len)\n  set fin = normIdxSlice(fin, len)\n  if beg >= len do\n    return View of [], 0, 0\n  if fin >= len do\n    set fin = len\n  if fin <= beg do\n    return View of [], 0, 0\n  \n  if arr is\n    View(itr, start, end) then View of itr, start + beg, end + (len - fin)\n    Splice(bits, l) as s then View of s.materialize().slice(beg, fin), 0, 0\n    else View of enforceArray(arr), beg, (arr.length - fin)\n\n// Marker base class for View and Splice\nclass LazyArr extends IterableBase with\n\n  fun toString() = \"[\" + this joined(\", \") + \"]\"\n  fun concat(...args) = concatHelper(mut [SpliceMarker, this], this.length, ...args)\n\n// Requires that the underlying iterable is constant-time indexable\nclass View(val underlying: IterableBase, val start, val end) extends LazyArr with\n\n  fun iterator() =\n    let idx = start\n    let until = underlying.length - end\n    Iterator of () =>\n      if idx < until then\n        let next = underlying.at(idx)\n        set idx = idx + 1\n        Result.Next of next\n      else Result.Done\n\n  fun materialize() = underlying.slice(start, underlying.length - end)\n  \n  fun at(i) =\n    if i < -length || i >= length do\n      throw RangeError(\"View.at: Index out of bounds\")\n    underlying.at(normIdx(i, length) + start)\n  fun slice(beg, fin) = sliceHelper(beg, fin, this)\n\n  val len = underlying.length - start - end\n  fun length = len\n  fun toString() = \"[\" + this joined(\", \") + \"]\"\n\nobject SpliceMarker\nclass Splice(val bits, val len) extends LazyArr with\n  let materialized = null\n\n  fun iterator() =\n    let idx = 0\n    let uitr = null\n    \n    fun nextf() =\n      if idx < bits.length and\n        bits.[idx] is \n          SpliceMarker then\n            if uitr === null do \n              set uitr = bits.[idx + 1].(Symbol.iterator)()\n            let n = uitr.next()\n            if n.done then\n              set uitr = null\n              set idx += 2\n              nextf()\n            else\n              n\n          else\n            let value = bits.[idx]\n            set idx += 1\n            Result.Next of value\n      else Result.Done\n    Iterator of nextf\n\n  fun reify = \n    let counter = 0\n    let arr = new mut Array(len)\n    let stack = mut []\n    stack.push([0, bits])\n    while stack.length > 0 do\n      let e = stack.pop()\n      let idx = e.[0]\n      let vals = e.[1]\n\n      if vals is Splice do\n        set vals = vals.bits\n\n      while (idx < vals.length and\n          (vals.at(idx) is SpliceMarker) is false) do\n        set arr.[counter] = vals.at(idx)\n        set counter += 1\n        set idx += 1\n      \n      if (idx < vals.length and vals.at(idx) is SpliceMarker) do\n        stack.push([idx + 2, vals])\n        stack.push([0, vals.at(idx + 1)])\n    arr\n\n  fun materialize() =\n    if materialized === null do\n      set materialized = reify\n    materialized\n  \n  fun at(i) = materialize().at(i)\n  fun slice(beg, fin) = sliceHelper(beg, fin, this)\n  fun concat(...args) = \n    if materialized === null \n    then concatHelper(mut [SpliceMarker, this], len, ...args)\n    else concatHelper(mut [SpliceMarker, materialized], len, ...args)\n  \n  fun length = len\n  fun toString() = \"[\" + materialize() joined(\", \") + \"]\"\n\n\nmodule LazyArray with...\n\n\nfun mk(...args) = View of args, 0, 0\nfun concat(...args) = concatHelper(mut [], 0, ...args)\nfun dropLeftRight(beg, fin)(xs) = \n  if beg < 0 || fin < 0 do\n    throw RangeError(\"LazyArray.dropLeftRight: indices must be non-negative\")\n  if beg > xs.length || fin > xs.length do\n    throw RangeError(\"LazyArray.dropLeftRight: indices out of bounds\")\n  sliceHelper(beg, xs.length - fin, xs)\n\nfun equals(xs, ys) =\n  xs.length === ys.length &&\n    let idx = 0\n    while (idx < xs.length) do\n      if xs.at(idx) !== ys.at(idx) do return false\n      set idx += 1\n    true\n\n// This is not meant for users; it's referred to by Runtime.mls\n// TODO: use `LazyArray.internals.concat` when this is implemented\nfun __concat(...args) =\n  let len = 0\n  let idx = 0\n  while (idx < args.length) do\n    if args.[idx] is SpliceMarker then\n      set len += enforceArray(args.[idx + 1]).length\n      set idx += 2\n    else\n      set len += 1\n      set idx += 1\n  Splice of args, len\n\n// This is not meant for users; it's referred to by Runtime.mls\n// TODO: use `LazyArray.internals.split` when this is implemented\nval __split = SpliceMarker\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/LazyFingerTree.mls",
    "content": "import \"./Iter.mls\"\nimport \"./FingerTreeList.mls\"\n\nopen Iter\nopen LazyFingerTree\nopen FingerTreeList\n\nfun normIdx(i, len) =\n  if i < 0 then len + i\n  else i\n\nfun concatHelper(a, l, ...args) =\n  let idx = 0\n  let init_len = a.length\n  set a.length = init_len + args.length * 2\n  while (idx < args.length) do\n    let x = args.[idx]\n\n    set a.[init_len + idx * 2] = SpliceMarker\n    set a.[init_len + idx * 2 + 1] = x\n    set l += x.length\n    set idx += 1\n  Splice of a, l\n\n// Follows the semantics of Array.prototype.slice indices:\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice\nfun normIdxSlice(i, len) =\n  if i < 0 and\n    i >= -len then len + i\n    else 0\n  else i\n\nfun sliceHelper(beg, fin, arr) =\n  let len = arr.length\n  set beg = normIdxSlice(beg, len)\n  set fin = normIdxSlice(fin, len)\n  if beg >= len do\n    return View of [], 0, 0\n  if fin >= len do\n    set fin = len\n  if fin <= beg do\n    return View of [], 0, 0\n  \n  if arr is\n    View(itr, start, end) then View of itr, start + beg, end + (len - fin)\n    Splice(bits, l) as s then s.materialize().slice(beg, fin)\n    ft and\n      FingerTreeList.isFingerTree(ft) \n        then FingerTreeList.dropLeftRight(beg, (len - fin))(ft)\n        else View of arr, beg, (len - fin)\n\n// Marker base class for View and Splice\nclass LazyFT extends IterableBase with\n\n  fun toString() = \"[\" + this joined(\", \") + \"]\"\n  fun concat(...args) = concatHelper(mut [SpliceMarker, this], this.length, ...args)\n\nclass View(val underlying: IterableBase, val start, val end) extends LazyFT with\n\n  fun iterator() =\n    let idx = start\n    let until = underlying.length - end\n    Iterator of () =>\n      if idx < until then\n        let next = underlying.at(idx)\n        set idx = idx + 1\n        Result.Next of next\n      else Result.Done\n\n  fun materialize() = underlying.slice(start, underlying.length - end)\n  \n  fun at(i) =\n    if i < -length || i >= length do\n      throw RangeError(\"View.at: Index out of bounds\")\n    underlying.at(normIdx(i, length) + start)\n  fun slice(beg, fin) = sliceHelper(beg, fin, this)\n\n  val len = underlying.length - start - end\n  fun length = len\n  fun toString() = \"[\" + this joined(\", \") + \"]\"\n\nobject SpliceMarker\nclass Splice(val bits, val len) extends LazyFT with\n  let materialized = null\n\n  fun iterator() = materialize().iterator()\n\n  fun reify =\n    let acc = FingerTreeList.mk()\n    let stack = mut []\n    stack.push([0, bits])\n    while stack.length > 0 do\n      let e = stack.pop()\n      let idx = e.[0]\n      let vals = e.[1]\n\n      if vals is Splice do\n        set vals = vals.bits\n\n      while (idx < vals.length and\n          (vals.at(idx) is SpliceMarker) is false) do\n        set acc = acc :+ vals.at(idx)\n        set idx += 1\n\n      if (idx < vals.length and vals.at(idx) is SpliceMarker) do\n        stack.push([idx + 2, vals])\n        let next = vals.at(idx + 1)\n        if FingerTreeList.isFingerTree(next)\n          then set acc = acc ++ next\n          else stack.push([0, next])\n    acc\n\n  fun materialize() =\n    if materialized == null do\n      set materialized = reify\n    materialized\n\n  fun at(i) = materialize().at(i)\n  // called on eager spreads in matches\n  fun slice(beg, fin) = sliceHelper(beg, fin, this)\n  fun concat(...args) =\n    if materialized === null \n    then concatHelper(mut [SpliceMarker, this], len, ...args)\n    else concatHelper(mut [SpliceMarker, materialized], len, ...args)   \n  \n  fun length = len\n  fun toString() = \"[\" + materialize() joined(\", \") + \"]\"\n\n\nmodule LazyFingerTree with...\n\n\nfun mk(...args) = View of FingerTreeList.mk(...args), 0, 0\nfun concat(...args) = concatHelper(mut [], 0, ...args)\nfun dropLeftRight(beg, fin)(xs) = \n  if beg < 0 || fin < 0 do\n    throw RangeError(\"LazyFingerTree.dropLeftRight: indices must be non-negative\")\n  if beg > xs.length || fin > xs.length do\n    throw RangeError(\"LazyFingerTree.dropLeftRight: indices out of bounds\")\n  sliceHelper(beg, xs.length - fin, xs)\n\nfun equals(xs, ys) =\n  if xs is\n    [x, ...xs] then\n      if ys is\n        [b, ...bs] then x == b && equals(xs, bs)\n        [] then false\n    [] then ys.length === 0\n\n// The following functions are not meant for users; it's meant referred to by Runtime.mls\n// TODO: use `LazyFingerTree.internals.concat` when this is implemented\n\nfun __concat(...args) = \n  let len = 0\n  let idx = 0\n  while (idx < args.length) do\n    if args.[idx] is SpliceMarker then\n      set len += args.[idx + 1].length\n      set idx += 2\n    else\n      set len += 1\n      set idx += 1\n  Splice of args, len\n\nval __split = SpliceMarker\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/MutMap.mls",
    "content": "import \"./Option.mls\"\nimport \"./Predef.mls\"\n\nopen Predef\nopen Option { Some, None }\n\n\nmodule MutMap with ...\n\nclass MutMap(val underlying) with\n  \n  set this.(Symbol.iterator) =\n    () => underlying.(Symbol.iterator)()\n\nfun get(key)(m) =\n  if m.underlying.has(key)\n  then Some of m.underlying.get(key)\n  else None\n\nfun insert(key, value)(m) =\n  m.underlying.set(key, value)\n  ()\n\nfun delete(key)(m) =\n  m.underlying.delete(key)\n  ()\n\nfun updateWith(key)(op)(m) =\n  if op(m |> get(key)) is\n    Some(value) then m.underlying.set(key, value)\n    None then m.underlying.delete(key)\n\nfun keysIterator(m) = m.underlying.keys()\n\nfun valuesIterator(m) = m.underlying.values()\n\nfun values(m) = Array.from of m.underlying.values()\n\nfun toMap(entries) =\n  let\n    m = empty\n    i = 0\n    length = entries.length\n  while i < length do\n    m |> insert of ...entries.at(i)\n    set i += 1\n  m\n\nfun empty = new MutMap(new Map())\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/NoFreeze.mls",
    "content": "#config(noFreeze: true)\n#config(noModuleCheck: true)\n\nmodule NoFreeze with\n  class Foo(val x)\n\n  fun foo() = new Foo(0)\n  fun bar() = NoFreeze.\"foo\"()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/ObjectBuffer.mls",
    "content": "\nfun max(a, b) = if a < b then b else a\n\nmodule ObjectBuffer with\n  abstract class ObjectBuffer with\n    val buf\n    fun mkNew(cls)\n    fun del(cls, inst)\n    fun read(idx)\n    fun write(idx, v)\n\n  class DefaultObjectBuffer(initLength) extends ObjectBuffer with\n    val buf = new mut Array(max(16, initLength))\n    // val buf = Array.from({length: max(16, initLength)}, _ => null)\n    let freeListHead = 0\n    set\n      buf.[0] = buf.length\n      buf.[1] = -1\n\n    fun mkNew(cls) =\n      if cls.size === 0 do return 0\n      val idx = _alloc(getBlockSize(cls.size))\n      cls.ctor(this, idx)\n\n    fun del(cls, inst) =\n      if cls.size !== 0 do\n        _free(inst, getBlockSize(cls.size))\n\n    fun read(idx) = buf.[idx]\n\n    fun write(idx, v) = set buf.[idx] = v\n\n    fun getBlockSize(sz) = Math.ceil(sz / 2) * 2\n\n    fun grow(needed) =\n      let oldLen = buf.length\n      let newLen =\n        if buf.length >= needed then\n          // double the length\n          buf.length * 2\n        else\n          // compute closest power of 2 enough for 2 * needed\n          Math.pow(2, Math.ceil(Math.log2(needed)) + 1)\n      set\n        buf.length = newLen\n      // Add the new block to head of free list\n      _free(oldLen, newLen - oldLen)\n\n    fun _tryAlloc(sz) =\n      let prev = -1\n      let cur = freeListHead\n      // first-fit\n      while cur !== -1 do\n        if buf.[cur] === sz do\n          if prev === -1 then\n            set freeListHead = buf.[cur + 1]\n          else\n            set buf.[prev] = buf.[cur + 1]\n          return cur\n        if buf.[cur] > sz do\n          // Slice remainder, always possible due to block size\n          set\n            buf.[cur + sz] = buf.[cur] - sz\n            buf.[cur + sz + 1] = buf.[cur + 1]\n          if prev === -1 then\n            set freeListHead = cur + sz\n          else\n            set buf.[prev] = cur + sz\n          return cur\n        set\n          prev = cur\n          cur = buf.[cur + 1]\n      -1\n\n    fun alloc(sz) =\n      if sz === 0 do return 0\n      _alloc(getBlockSize(sz))\n\n    fun _alloc(bsz) =\n      let res = _tryAlloc(bsz)\n      if res !== -1 do return res\n      grow(bsz)\n      _tryAlloc(bsz)\n\n    fun free(ptr, sz) =\n      if sz !== 0 do _free(ptr, getBlockSize(sz))\n\n    fun _free(ptr, bsz) =\n      set\n        buf.[ptr] = bsz\n        buf.[ptr + 1] = freeListHead\n        freeListHead = ptr\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Option.mls",
    "content": "\nimport \"./Predef.mls\"\nopen Predef\n\n\ntype Option[A] = Option.{ Some(A) | None }\n\nmodule Option with ...\n\n\ndata class Some[T](value)\nobject None\n\nfun isDefined(x) = if x is\n  Some then true\n  None then false\n\ndata class Both(fst, snd)\n\n\nfun getOrElse(opt, default) = if opt is\n  Some(value) then value\n  None then default\n\nfun flatMap(opt, f) = if opt is\n  Some(value) then f(value)\n  None then None\n\nmodule unsafe with\n  fun get(opt) = if opt is\n    Some(value) then value\n    None then throw Error(\"None.get\")\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Predef.mls",
    "content": "\nimport \"./RuntimeJS.mjs\"\n\n// * Importing the mjs for now to avoid reparsing/re-elaborating these files Runtime all the time\n// * TODO: proper caching of parsed/elaborated files\nimport \"./Runtime.mjs\"\nimport \"./Rendering.mjs\"\nimport \"./Term.mjs\"\n// import \"./Runtime.mls\"\n// import \"./Rendering.mls\"\n\n\n\nmodule Predef with ...\n\n\nfun id(x) = x\n\n\nfun (@) apply(f, ...args) = f(...args)\n\nfun (|>) pipeInto(x, f) = f(x)\nfun (<|) pipeFrom(f, x) = f(x)\n\n// Same as above but with high precedence\nfun (.>) pipeIntoHi(x, f) = f(x)\nfun (<.) pipeFromHi(f, x) = f(x)\n\nfun (!>) tap(x, f) = f(x); x\nfun (<!) pat(f, x) = f(x); x\n\nfun (|!) alsoDo(x, eff) = x\n\nfun (>>) andThen(f, g)(x) = g(f(x))\nfun (<<) compose(f, g)(x) = f(g(x))\n\n// x \\foo(a, b, c) == foo(x, a, b, c)\nfun (\\) passTo(receiver, f)(...args) = f(receiver, ...args)\n\n// Same as above but with low precedence\nfun (|.) passToLo(receiver, f)(...args) = f(receiver, ...args)\n\n// x |>. foo(a, b, c) == foo.call(x, a, b, c)\nfun (|>.) call(receiver, f)(...args) = f.call(receiver, ...args)\n\n\nobject Symbols with\n  val prettyPrint = RuntimeJS.symbols.prettyPrint\n  val definitionMetadata = RuntimeJS.symbols.definitionMetadata\n  // val definitionMetadata = Symbol.for(\"mlscript.definitionMetadata\")\n\nabstract class (<:<) Sub[A, B] with\n  fun apply(x: A): B\nabstract class (=:=) Eq[A, B] extends Sub[A, B] with\n  fun apply(x: A): B\nobject Refl[A] extends Eq[A, A] with\n  fun apply(x: A): A = x\n\ntype (>:>) Sup[A, B] = Sub[B, A]\n\n// * A generic equality comparison.\n// * Returns true for:\n// * - values that compare equal according to strict equality (===), which includes reference equality;\n// * - arrays of values that are pairwise recursively equal;\n// * - instances of the same parameterized MLscript class when all fields are public and recursively equal.\n// TODO: compare lazy arrays and other sequences and collections\nfun (==) equals(a, b) = if\n  a === b then true\n  a is Array and b is Array and a.length === b.length then a.every((a, i) => a == b.at(i))\n  else a !== undefined and a !== null and b !== undefined and b !== null and \n    let ac = a.constructor\n    ac !== undefined and ac === b.constructor and\n      let md = ac.(Symbols.definitionMetadata)\n      md !== undefined and\n        md.2.every(field => field !== null and a.(field) == b.(field))\n\nfun (!=) nequals(a, b) = not a == b\n\n\nval pass1 = Rendering.pass1\nval pass2 = Rendering.pass2\nval pass3 = Rendering.pass3\nval passing = Rendering.passing\nval map = Rendering.map\nval fold = Rendering.fold\nval interleave = Rendering.interleave\nval render = Rendering.render\n\nfun print(...xs) =\n  console.log(...map(renderAsStr)(...xs))\n\nfun renderAsStr(arg) =\n  if arg is Str then arg else render(arg)\n\nval js_assert = globalThis.console.(\"assert\") // `console.(\"assert\")` gives \"Unexpected moduleful reference of type console.\"\nfun check(...args) = js_assert(...args)\n\nfun (??) notImplemented(msg) = throw Error(\"Not implemented: \" + msg)\nfun (???) notImplementedError = throw Error(\"Not implemented\")\n\n\nfun tuple(...xs) = xs\nfun mkSet(...xs) = new Set(xs)\n\n\nval foldl = fold\n\n// fun foldr(f)(...rest, init) = // TODO allow this syntax\nfun foldr(f)(first, ...rest) =\n  let len = rest.length\n  if len === 0 then first else...\n  let\n    i = len - 1\n    init = rest.at(i)\n  while i > 0 do\n    set\n      i -= 1\n      init = f(rest.at(i), init)\n  f(first, init)\n\nfun mkStr(...xs) =\n  fold((acc, x) => check(x is Str); acc + x) of ...xs\n\n\n// Return the implicit instance of type T from the current scope.\n// Analogous to the `summon` function in Scala.\nfun use[T](using instance: T) = instance\n\n\n// This binds the handler in body, which means body can raise effects in handler\nfun enterHandleBlock(handler, body) =\n  // This is a simple wrapper of a handler runtime function, which must not be instrumented so cannot be directly implemented here.\n  // It also calls other internal runtime functions as well.\n  Runtime.enterHandleBlock(handler, body)\n\nfun raiseUnhandledEffect() =\n  Runtime.mkEffect(Runtime.FatalEffect, null)\n\n\nmodule meta with\n  fun codegen(t, file) = Term.codegen(t, file)\n  fun print(t) = Term.print(t)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/QuoteExample.mls",
    "content": "import \"./Predef.mls\"\n\nmodule QuoteExample with\n  fun foo() = `1 `+ `1\n  fun inc() = x `=> x `+ `1\n  fun power(x) = case\n    0 then `1.0\n    n then x `*. power(x)(n - 1)\n  fun bind(rhs, k) = `let x = rhs `in k(x)\n  fun body(x, y) = case\n    0 then x\n    1 then y\n    n then bind of x `+ y, (z => body(y, z)(n - 1))\n  fun gib(n) = (x, y) `=> body(x, y)(n)\n  fun safeDiv() = (x, y, d) `=> `if y `== `0.0 then d else x `/ y\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/QuoteExample1.mls",
    "content": "import \"./Predef.mls\"\n\nopen Predef\n\nmodule QuoteExample1 with\n  fun foo() = `id`(`1) `== id(`2)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/QuoteExample2.mls",
    "content": "import \"./Term.mls\"\nimport \"./QuoteExample.mls\"\nimport \"./QuoteExample1.mls\"\n\n\nmodule QuoteExample2 with\n  fun codegen() = \n    Term.codegen(QuoteExample.foo(), \"./hkmc2/shared/src/test/mlscript-compile/quotes/QuoteFoo.mls\")\n    Term.codegen(QuoteExample.inc(), \"./hkmc2/shared/src/test/mlscript-compile/quotes/QuoteInc.mls\")\n  fun genCubic() =\n    Term.codegen(x `=> QuoteExample.power(x)(3), \"./hkmc2/shared/src/test/mlscript-compile/quotes/Cubic.mls\")\n  fun genGib12() =\n    Term.codegen(QuoteExample.gib(12), \"./hkmc2/shared/src/test/mlscript-compile/quotes/Gib12.mls\")\n  fun genSafeDiv() =\n    Term.codegen(QuoteExample.safeDiv(), \"./hkmc2/shared/src/test/mlscript-compile/quotes/SafeDiv.mls\")\n  fun genOpened() =\n    Term.codegen(QuoteExample1.foo(), \"./hkmc2/shared/src/test/mlscript-compile/quotes/Opened.mls\")\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Record.mls",
    "content": "\nimport \"./Predef.mls\"\nopen Predef\n\nimport \"./Iter.mls\"\n\n\nmodule Record with...\n\nfun steal(from, ...fields) =\n  let rcd = new mut Object\n  fields Iter.each of f => set rcd.(f) = from.(f)\n  rcd\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Rendering.mls",
    "content": "import \"./RuntimeJS.mjs\"\n\n\nmodule Rendering with ...\n\n\nlet definitionMetadataSymbol = RuntimeJS.symbols.definitionMetadata\nlet prettyPrintSymbol = RuntimeJS.symbols.prettyPrint\n\nfun pass1(f)(...xs) = f(xs.0)\nfun pass2(f)(...xs) = f(xs.0, xs.1)\nfun pass3(f)(...xs) = f(xs.0, xs.1, xs.2)\n\nfun passing(f, ...args) = f.bind(null, ...args)\n\nfun map(f)(...xs) = xs.map(pass1(f))\n\nfun fold(f)(init, ...rest) =\n  let\n    i = 0\n    len = rest.length\n  while i < len do\n    set\n      init = f(init, rest.at(i))\n      i += 1\n  init\n\nfun interleave(sep)(...args) =\n  if args.length === 0 then [] else...\n  let\n    res = Array of args.length * 2 - 1\n    len = args.length\n    i = 0\n  while i < len do\n    let idx = i * 2\n    set\n      res.[idx] = args.[i]\n      i += 1\n    if i < len do set res.[idx + 1] = sep\n  res\n\n// The following regular expression matches non-empty strings that qualify as\n// Unicode identifiers accepted by ECMAScript. \nlet identifierPattern = new RegExp of\n  // A breakdown of the regular expression:\n  // 1. `\\p{...}` is a Unicode character class escape. It matches a set of\n  //    characters specified by a Unicode property. \n  // 2. `ID_Start` includes letters and a few letter-like characters; but it\n  //    does not include `_` or `$`, hence they’re added explicitly.\n  // 3. `ID_Continue` includes `ID_Start` plus combining marks, decimal digits,\n  //    connector punctuation (which covers `_`), etc. But it does not include\n  //    `$`, hence `$` is added explicitly.\n  // 4. `^` and `$` assert that the current position is the start or the end of\n  //    input respectively. Hence, they make sure the entire string matches.\n  // The regular expression follows the production of identifiers defined in\n  // ECMA-262: https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-IdentifierName.\n  \"\"\"^[\\p{ID_Start}_$][\\p{ID_Continue}$]*$\"\"\"\n  \"u\" // The Unicode flag is required for `\\p{...}` Unicode property escapes.\n\n// Return `true` if the identifier needs to be enclosed in quotes.\nlet noNeedForQuotes(id) = identifierPattern.test(id)\n\n// Use this object instead when no options object is given.\nlet emptyOptions = new Object\n\nlet DEFAULT_BREAK_LENGTH = 80\n\nlet symbolsForArray =\n  start: \"[\", end: \"]\", separator: \",\", empty: \"[]\", padding: true\n\nlet symbolsForSet(n: Int) =\n  let headline = \"Set(\" + n + \") \"\n  start: headline + \"{\", end: \"}\", separator: \",\",\n  empty: headline + \"{}\", padding: true\n\nlet symbolsForClass(name: Str) =\n  start: name + \"(\", end: \")\", separator: \",\", empty: name + \"()\", padding: false\n\nlet symbolsForObject =\n  start: \"{\", end: \"}\", entrySeparator: \",\", keyValueSeparator: \": \", empty: \"{}\", padding: true\n\nlet symbolsForMap(n: Int) =\n  let headline = \"Map(\" + n + \")\"\n  start: headline + \" {\", end: \"}\",\n  entrySeparator: \",\", keyValueSeparator: \" => \", empty: headline + \" {}\", padding: true\n\nfun render(target, ...args) =\n  let\n    options = if args is [options, ...] then options else emptyOptions\n    indent = if\n      options is (:indent) and indent is\n        true then \"  \" // The default indentation is of two spaces.\n        // A positive integer will be interpreted as the number of spaces for a\n        // single level of indentation.\n        Int and indent > 0 then \" \".repeat(indent)\n        // `null` to indicate no indentation and put all the content on a single line.\n      else null\n    // If the joined string is less than or equal `breakLength`, it stays on one\n    // line; otherwise it becomes multiline and each item is prefixed with `\\n`\n    // plus `indent`.\n    breakLength = if\n      indent is null then Number.POSITIVE_INFINITY\n      options is (:breakLength) and breakLength is Int and breakLength > 0 then breakLength\n      else DEFAULT_BREAK_LENGTH\n    // Should we add padding after \"[\"/\"{\" and before \"]\"/\"}\".\n    padding = if options is (padding: true) then \" \" else \"\"\n    circularCounter = 1\n    visitingObjects = new WeakMap // Object -> null | Int\n    visitedObjects = new WeakMap // Object -> Str\n  // Add indentations to results of `toString` from other objects.\n  fun indentText(text: Str, currentLevel: Int): Str =\n    if indent is null then text else...\n    let indents = indent.repeat(currentLevel + 1)\n    text\n      .split(\"\\n\")\n      .map of (line, index, lines) =>\n        let postfix = if index + 1 === lines.length then \"\" else \" \\\\\"\n        let prefix = if index === 0 then \"\" else indents\n        prefix + line + postfix\n      .join(\"\\n\")\n  fun renderArray(array, level, keyLength, startPos) =\n    let\n      i = 0\n      length = array.length\n      emptyItemCount = 0\n      // The length of indentations that should be prepended to items in this\n      // array if this array is displayed in multi-lines.\n      itemIndentationLength =\n        if indent is null then 0 else (level + 1) * indent.length\n    // Return `true` if the array has no remaining elements.\n    let done() =\n      let isDone = null\n      while isDone is null do\n        if...\n        i >= length then set isDone = true\n        Reflect.has(array, i) then set isDone = false\n        else\n          set { emptyItemCount += 1, i += 1 }\n      (emptyItemCount === 0) && (if isDone is null then true else isDone)\n    let next(isFirst: Bool, prefixLength: Int) = if\n      emptyItemCount > 0 then\n        let emptyItemCount' = emptyItemCount\n        set emptyItemCount = 0\n        \"<\" + emptyItemCount' + \" empty items>\"\n      i < length then\n        let\n          // The starting column if the current item is placed on the same line.\n          prefixLengthIfSameLine = prefixLength + (if isFirst then 0 else 2)\n          valueStartLength = if prefixLengthIfSameLine <= breakLength\n            then prefixLengthIfSameLine else itemIndentationLength\n          valueStr = renderValue(array.[i], level + 1, 0, valueStartLength)\n        set i += 1\n        valueStr\n      else throw new Error(\"All items in this array has been rendered.\")\n    renderSequence of done, next, level, keyLength, startPos, symbolsForArray\n  fun renderSet(theSet, level, keyLength, startPos) =\n    let\n      iterator = theSet.(Symbol.iterator)()\n      peek = iterator.next()\n      // The length of indentations that should be prepended to items in this\n      // array if this array is displayed in multi-lines.\n      itemIndentationLength =\n        if indent is null then 0 else (level + 1) * indent.length\n    // Return `true` if the array has no remaining elements.\n    let done() = peek.done\n    let next(isFirst: Bool, prefixLength: Int) =\n      let result = if peek is (done: false, :value) then \n        let\n          // The starting column if the current item is placed on the same line.\n          prefixLengthIfSameLine = prefixLength + (if isFirst then 0 else 2)\n          valueStartLength = if prefixLengthIfSameLine > breakLength\n            then itemIndentationLength else prefixLengthIfSameLine\n        renderValue(value, level + 1, 0, valueStartLength)\n      set peek = iterator.next()\n      result\n    renderSequence of\n      done, next, level, keyLength, startPos, symbolsForSet(theSet.size)\n  // Render instances of MLscript classes.\n  fun renderClassInstance(constructorName, fieldNames, instance, level, keyLength, startPos) =\n    let\n      length = fieldNames.length\n      i = 0\n      itemIndentationLength = if indent is null then 0 else (level + 1) * indent.length\n    let done() = i >= length\n    let next(isFirst: Bool, prefixLength: Int) = if fieldNames.[i] is\n      do set i += 1\n      null then \"_\"\n      Str as key then\n        let\n          value = instance.(key)\n          prefixLengthIfSameLine = prefixLength + (if isFirst then 0 else 2)\n          valueStartLength = if prefixLengthIfSameLine > breakLength\n            then itemIndentationLength else prefixLengthIfSameLine\n        renderValue(value, level + 1, 0, valueStartLength)\n    renderSequence of done, next, level, keyLength, startPos, symbolsForClass(constructorName)\n  fun renderSequence(done, next, level: Int, keyLength: Int, startPos: Int, symbols) =\n    let\n      items = mut []\n      hasMultiline = false\n      // Try calculating the length needed to place all items in one line. The\n      // brackets and spaces around items are excluded from the length.\n      singleLineLength = startPos + symbols.start.length +\n        (if symbols.padding then padding.length else 0)\n      parentIndent = if indent is null then null else indent.repeat(level)\n      itemIdent = if indent is null then null else indent.repeat(level + 1)\n    // Iterate through and render all items.\n    while done() is false do\n      let item = next(items.length is 0, singleLineLength)\n      // Append a new item and update needed variables.\n      if item.indexOf(\"\\n\") >= 0 do set hasMultiline = true\n      set singleLineLength +=\n        if items.length is 0 then 0 else symbols.separator.length + 1\n      set singleLineLength += item.length\n      items.push of item\n    set singleLineLength += symbols.end.length +\n      (if symbols.padding then padding.length else 0)\n    let\n      layoutMultiLine() =\n        symbols.start + \"\\n\" + itemIdent +\n        items.join(symbols.separator + \"\\n\" + itemIdent) +\n        \"\\n\" + parentIndent + symbols.end\n      layoutSingleLine() =\n        symbols.start + (if symbols.padding then padding else \"\") +\n        items.join(symbols.separator + \" \") +\n        (if symbols.padding then padding else \"\") + symbols.end\n    if\n      items.length is 0 then symbols.empty\n      indent is null then layoutSingleLine()\n      // If any item is multiline, place each item on a line.\n      hasMultiline then layoutMultiLine()\n      singleLineLength <= breakLength then layoutSingleLine()\n      parentIndent.length + (singleLineLength - startPos + keyLength) <= breakLength then\n        layoutSingleLine()\n      else layoutMultiLine()\n  // Render enumerable properties of the given object.\n  fun renderObject(subject, level, keyLength, startPos, isRefinement) =\n    let\n      entries = Object.entries(Object.getOwnPropertyDescriptors(subject))\n      length = entries.length\n      i = 0\n      itemIndentationLength =\n        if indent is null then 0 else (level + 1) * indent.length\n    let skipNonEnumerable() =\n      while i < length and entries.[i].1.enumerable is false do set i += 1\n    let done() = i >= length\n    let next(isFirst: Bool, prefixLength: Int) =\n      let\n        key = entries.[i].0\n        desc = entries.[i].1\n      skipNonEnumerable()\n      set i += 1\n      let keyStr = if key noNeedForQuotes() then key else renderValue(key, 0, 0, 0)\n      if desc is\n        (:value) then\n          let\n            dryRunStartPos = prefixLength + // base length\n              (if isFirst then 0 else 2) + // \", \"\n              keyStr.length + 2 // \"key: \"\n            valueStartPos = if dryRunStartPos > breakLength\n              then itemIndentationLength else dryRunStartPos\n            valueStr = renderValue(value, level + 1, keyStr.length + 2, valueStartPos)\n          [keyStr, valueStr]\n        (get: getter, \"set\": setter) then\n          let valueStr = if\n            setter is undefined then \"[Getter]\"\n            getter is undefined then \"[Setter]\"\n            else \"[Getter/Setter]\"\n          [keyStr, valueStr]\n        else [keyStr, \"‹Non-data property›\"] // LP: not sure what to do (thsi was proposed by Copilot...)\n    skipNonEnumerable()\n    renderRecordLike of\n      done, next, level, keyLength, startPos, symbolsForObject, isRefinement\n  fun renderMap(map, level, keyLength, startPos) =\n    let\n      iterator = map.(Symbol.iterator)()\n      peek = iterator.next()\n      // The length of indentations that should be prepended to items in this\n      // array if this array is displayed in multi-lines.\n      itemIndentationLength =\n        if indent is null then 0 else (level + 1) * indent.length\n    // Return `true` if the array has no remaining elements.\n    let done() = peek.done\n    let next(isFirst: Bool, prefixLength: Int) =\n      let last = peek\n      set peek = iterator.next()\n      if last is (done: false, value: [key, value]) then \n        let\n          // The starting column if the key is placed on the same line.\n          keyPrefixLengthIfSameLine = prefixLength + (if isFirst then 0 else 2)\n          keyPrefixLength = if keyPrefixLengthIfSameLine > breakLength\n            then itemIndentationLength else keyPrefixLengthIfSameLine\n          keyStr = renderValue(key, level + 1, 0, keyPrefixLength)\n          // The starting column if the value is placed on the same line.\n          valuePrefixLengthIfSameLine = if keyStr.indexOf(\"\\n\") >= 0\n            then itemIndentationLength + keyStr.length - keyStr.lastIndexOf(\"\\n\") + 5\n            else keyPrefixLength + keyStr.length + 5\n        let\n          valuePrefixLength = if valuePrefixLengthIfSameLine > breakLength\n            then itemIndentationLength else valuePrefixLengthIfSameLine\n          valueStr = renderValue(value, level + 1, 0, valuePrefixLengthIfSameLine)\n        [keyStr, valueStr]\n    renderRecordLike of\n      done, next, level, keyLength, startPos, symbolsForMap(map.size), false\n  fun renderRecordLike(done, next, level, keyLength, startPos, symbols, isRefinement) =\n    let\n      startPadding = if\n        isRefinement then \" \"\n        symbols.padding then padding\n        else \"\"\n      endPadding = if\n        isRefinement then \" \"\n        symbols.padding then padding\n        else \"\"\n      items = mut []\n      hasMultiline = false\n      singleLineLength = startPos + symbols.start.length + startPadding.length\n      parentIndent = if indent is null then null else indent.repeat(level)\n      itemIdent = if indent is null then null else indent.repeat(level + 1)\n    while done() is false do\n      let\n        keyValue = next(items.length is 0, singleLineLength)\n        key = keyValue.0\n        value = keyValue.1\n        length = key.length + 2 + value.length // \"a: b\"\n      if value.indexOf(\"\\n\") >= 0 do set hasMultiline = true\n      set singleLineLength +=\n        if items.length is 0 then 0 else symbols.entrySeparator.length\n      set singleLineLength += length // the item\n      items.push of key + symbols.keyValueSeparator + value\n    // Complete the single line length.\n    set singleLineLength += symbols.end.length + endPadding.length\n    let\n      layoutMultiLine() =\n        symbols.start + \"\\n\" + itemIdent +\n        items.join(\",\\n\" + itemIdent) +\n        \"\\n\" + parentIndent + symbols.end\n      layoutSingleLine() =\n        symbols.start + startPadding +\n        items.join(\", \") +\n        endPadding + symbols.end\n    if\n      items.length is 0 then symbols.empty\n      indent is null then layoutSingleLine()\n      hasMultiline then layoutMultiLine()\n      singleLineLength <= breakLength then layoutSingleLine()\n      // Try to break the parent object into many lines and check if it fits.\n      let lengthIfBreakParent = parentIndent.length + (singleLineLength - startPos + keyLength)\n      lengthIfBreakParent <= breakLength then layoutSingleLine()\n      else layoutMultiLine()\n  fun renderValue(arg, level, keyLength, startPos) = if\n    arg is // Primitive values\n      undefined then \"undefined\"\n      null      then \"null\"\n      Str       then JSON.stringify(arg)\n      BigInt    then arg.toString() + \"n\"\n      Symbol    and\n        arg.description is undefined then \"Symbol()\"\n        else \"Symbol(\\\"\" + arg.description + \"\\\")\"\n      Num       then arg.toString()\n      RegExp    then arg.toString()\n      true      then \"true\"\n      false     then \"false\"\n    arg === ()  then \"()\"\n    // Reuse the cached result if the display mode is inline.\n    visitedObjects.has(arg) and indent is null then visitedObjects.get(arg)\n    visitingObjects.has(arg) and visitingObjects.get(arg) is\n      // We have already found this circular reference before\n      Int as index then \"ref'\" + index\n      // The first time we find a circular reference\n      else\n        let index = circularCounter\n        set circularCounter += 1\n        visitingObjects.set(arg, index)\n        \"ref'\" + index\n    else...\n    // Otherwise, add this object to the visited objects\n    // `null` is a marker for visited objects\n    visitingObjects.set(arg, null)\n    let rendered = if\n      arg is\n        Array then renderArray of arg, level, keyLength, startPos\n        Set then renderSet of arg, level, keyLength, startPos\n        Map then renderMap of arg, level, keyLength, startPos\n        WeakSet then \"WeakSet { <items unknown> }\"\n        WeakMap then \"WeakMap { <items unknown> }\"\n        Error then arg.name + \": \" + arg.message\n        Function then\n          let desc = Object.getOwnPropertyDescriptor(arg, \"prototype\")\n          let head = if\n            // ES 2015 classes: `desc.writable` is `false`.\n            desc is Object and desc.writable is false and\n              // If it is from MLscript, use the kind written in metadata.\n              desc.value.constructor.hasOwnProperty(definitionMetadataSymbol) and\n                desc.value.constructor.(definitionMetadataSymbol) is [kind, name, ...] then\n                  kind + \" \" + name\n              arg.name is \"\" then \"class\" // Show \"class\" if there is no name.\n              else \"class \" + arg.name // Or, we can use the name.\n            // Display as functions if `desc.writable` is not `false`\n            else \"fun\" + (if arg.name is \"\" then \"\" else \" \" + arg.name)\n          head + if // Add a space if the function do not have enumerable properties\n            let properties = renderObject of\n              arg, level, keyLength, startPos + head.length, true\n            properties is \"{}\" then \"\"\n            else \" \" + properties\n      // The case for objects.\n      Reflect.getPrototypeOf(arg) is\n        // Objects with `null` as the prototype does not have prefix.\n        null then renderObject(arg, level, keyLength, startPos, false)\n        // The result of `getPrototypeOf` is either `null` or `Object`.\n        proto and\n          // For object literals, show its properties without the constructor.\n          proto === Object.prototype then\n            renderObject(arg, level, keyLength, startPos, false)\n          // The `constructor` field refers to the class.\n          proto.constructor is Function and\n            // Call its implementation of `prettyPrint` if defined.\n            proto.hasOwnProperty(prettyPrintSymbol) then\n              arg.(prettyPrintSymbol)() indentText(level)\n            // If the symbol `definitionMetadata` is defined on the constructor,\n            // we render the function using the provided field names.\n            proto.constructor.hasOwnProperty(definitionMetadataSymbol) and\n              let definitionMetadata = proto.constructor.(definitionMetadataSymbol)\n              definitionMetadata is [kind, name, fields] then\n                renderClassInstance(name, fields, arg, level, keyLength, startPos)\n              // If no field names are provided (the case for modules, objects,\n              // patterns, or parameter-less classes), use the constructor name.\n              definitionMetadata is [kind, name] then\n                // For class instances and objects, do not show the kind.\n                let head = if kind is\n                  \"class\" | \"object\" then name\n                  else kind + \" \" + name\n                let body = renderObject of\n                  arg, level, keyLength, startPos + head.length, true\n                head + (if body is \"{}\" then \"\" else \" \" + body)\n            // Otherwise, we print the name of the constructor and the properties.\n            let head = proto.constructor.name + \" \"\n            else head + renderObject of\n              arg, level, keyLength, startPos + head.length, true\n          // Otherwise, the prototype is not a function.\n          // If the prototype has its own implementation of `toString`, call it.\n          proto.hasOwnProperty(\"toString\") then arg.toString() indentText(level)\n          // Otherwise, treat the input as a normal object.\n          else renderObject(arg, level, keyLength, startPos, false)\n    // We have finished visiting this object.\n    let postfix = if visitingObjects.has(arg) and visitingObjects.get(arg) is\n      Int as index then \" as ref'\" + index\n      else \"\"\n    let result = rendered + postfix\n    // Add to the visited objects if the object is a circular reference.\n    if postfix.length > 0 do visitedObjects.set(arg, result)\n    visitingObjects.delete(arg)\n    result\n  renderValue(target, 0, 0, 0)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Runtime.mls",
    "content": "import \"./RuntimeJS.mjs\"\nimport \"./Rendering.mls\"\nimport \"./LazyArray.mjs\"\nimport \"./Iter.mjs\"\n\n\nmodule Runtime with ...\n\n\nobject Unit with\n  fun toString() = \"()\"\n\n// This object is used as a marker for the end of a while loop in the compiled codegen.\n// It is possible for the loop body to contain a return statement,\n// in which case we want to distinguish between returning from the loop body and loop termination.\nobject LoopEnd\nval short_and = RuntimeJS.short_and\nval short_or = RuntimeJS.short_or\n\n\nfun unreachable = throw Error(\"unreachable\")\n\nfun assertFail(file, line) = throw Error(\"Assertion failed (\" + file + \":\" + line + \")\")\n\n\nfun checkArgs(functionName, expected, isUB, got) =\n  if got < expected || isUB && got > expected do\n    let name = if functionName.length > 0 then \" '\" + functionName + \"'\" else \"\"\n    // throw globalThis.Error(\"Function\" + name + \" expected \"\n    //   + (if isUB then \"\" else \"at least \")\n    //   + expected\n    //   + \" argument(s) but got \" + got)\n    throw Error of \"Function\" + name + \" expected \"\n      + (if isUB then \"\" else \"at least \" )\n      + expected + \" argument\"\n      + (if expected === 1 then \"\" else \"s\")\n      + \" but got \" + got\n\nfun safeCall(x) =\n  if x is undefined then () else x\n\nfun checkCall(x) =\n  if x is undefined\n  then throw Error(\"MLscript call unexpectedly returned `undefined`, the forbidden value.\")\n  else x\n\nfun deboundMethod(mtdName, clsName) =\n  throw Error of\n    \"[debinding error] Method '\" + mtdName + \"' of class '\" + clsName + \"' was accessed without being called.\"\n\n\nval bitand = RuntimeJS.bitand\nval bitnot = RuntimeJS.bitnot\nval bitor = RuntimeJS.bitor\nval shl = RuntimeJS.shl\nval try_catch = RuntimeJS.try_catch\n\nclass EffectHandle(_reified) with\n  val reified = _reified\n  fun resumeWith(value) =\n    Runtime.try(() => resume(reified.contTrace)(value))\n  fun raise() =\n    set curEffect = reified\n\nfun try(f) =\n  let res = f()\n  if curEffect !== null then\n    let tmp = curEffect\n    set curEffect = null\n    EffectHandle(tmp)\n  else res\n\n\n// For `pattern` definitions\ndata class MatchSuccess(output, bindings)\ndata class MatchFailure(errors)\n\n// For pattern matching on tuples\nmodule Tuple with\n  fun slice(xs, i, j) = xs.slice(i, xs.length - j)\n\n  fun lazySlice(xs, i, j) = LazyArray.dropLeftRight(i, j)(xs)\n  fun lazyConcat(...args) = LazyArray.__concat(...args)\n\n  fun get(xs, i) =\n    if i >= xs.length do\n      throw RangeError(\"Tuple.get: index out of bounds\")\n    if i < -xs.length do\n      throw RangeError(\"Tuple.get: negative index out of bounds\")\n    xs.[i]\n\n  fun isArrayLike(xs) = Iter.isArrayLike(xs)\n  val split = LazyArray.__split\n\nmodule Str with\n  fun startsWith(string, prefix) = string.startsWith(prefix)\n\n  fun get(string, i) =\n    if i >= string.length then\n      throw RangeError(\"Str.get: index out of bounds\")\n    else string.at(i)\n  \n  fun take(string, n) = string.slice(0, n)\n\n  fun leave(string, n) = string.slice(n)\n\n// Re-export rendering functions\nval render = Rendering.render\n\nfun printRaw(x) = console.log(render(x, indent: 2, breakLength: 76))\n\n// TraceLogger\n\nmodule TraceLogger with\n  mut val enabled = false\n  mut val indentLvl = 0\n  fun indent() =\n    if enabled then\n      let prev = indentLvl\n      set indentLvl = prev + 1\n      prev\n    else ()\n  fun resetIndent(n) =\n    if enabled then\n      set indentLvl = n\n    else ()\n  fun log(msg) =\n    if enabled then\n      console.log(\"| \".repeat(indentLvl) + msg.replaceAll(\"\\n\", \"\\n\" + \"  \".repeat(indentLvl)))\n    else ()\n\n// Private definitions for algebraic effects\n\n// layout:\n// | f | pc | pcStr | debugInfo | this | argLists... (*) | localCnt | locals... |\n// (*) argLists is length encoded nested array\n\nmut val curEffect = null\nmut val resumeValue = null\nmut val resumeArr = null\nmut val resumeIdx = null\nmut val resumePc = -1\n\nobject FatalEffect\nobject PrintStackEffect\n\ndata class FunctionContFrame(next, saved) with\n  fun resume(value) =\n    let\n      i = 0\n      f = saved.[0]\n      argListsLength = saved.[5]\n      currentArgList = 6\n    set\n      resumeValue = value\n      resumeArr = saved\n      resumePc = saved.[1]\n    if argListsLength === 0 do\n      console.log(\"cannot resume getters\")\n    while i < argListsLength - 1 do\n      let argListLength = saved.[currentArgList]\n      set\n        f = f.apply(saved.[4], saved.slice(currentArgList + 1, currentArgList + 1 + argListLength))\n        currentArgList += argListLength + 1\n        i += 1\n    let argListLength = saved.[currentArgList]\n    set\n      resumeIdx = currentArgList + argListLength + 2\n    f.apply(saved.[4], saved.slice(currentArgList + 1, currentArgList + 1 + argListLength))\n  fun getLocals =\n    let debugInfo = saved.[3]\n    let i = 0\n    let cur = 6\n    while i < saved.[5] do\n      set\n        cur += saved.[cur] + 1\n        i += 1\n    let res = mut []\n    let i = 1\n    while i < debugInfo.length do\n      res.push(new LocalVarInfo(debugInfo.[i + 1], saved.[cur + 1 + debugInfo.[i]]))\n      set i += 2\n    res\n  fun getNme = saved.[3].[0]\n  fun getLoc =\n    let loc = saved.[2]\n    if\n      loc is null then \"pc=\" + saved.[1]\n      else loc\n\ndata class HandlerContFrame(next, nextHandler, handler)\n\ndata class ContTrace(next, last, nextHandler, lastHandler, resumed)\ndata class EffectSig(contTrace, handler, handlerFun)\n\nclass NonLocalReturn with\n  fun ret(value)\n\ndata class FnLocalsInfo(fnName, locals)\ndata class LocalVarInfo(localName, value)\ndata class CustomStackError(stack) with\n  fun toString() = stack\n\n\nfun resetEffects() =\n  set\n    curEffect = null\n    resumePc = -1\n\nfun raisePrintStackEffect(showLocals) =\n  mkEffect(PrintStackEffect, showLocals)\n\nfun topLevelEffect(debug) =\n  let tr = curEffect\n  let v = null\n  while tr is EffectSig and tr.handler === PrintStackEffect do\n    console.log(showStackTrace(\"Stack Trace:\", tr, debug, tr.handlerFun))\n    set\n      curEffect = null\n      v = resume(tr.contTrace)(())\n      tr = curEffect\n  if tr is EffectSig then\n    set curEffect = null\n    throw CustomStackError(showStackTrace(\"Error: Unhandled effect \" + tr.handler.constructor.name, tr, debug, false))\n  else\n    v\n\nfun illegalEffect(position) =\n  let tmp = curEffect\n  set curEffect = null\n  throw CustomStackError(showStackTrace(\"Error: Effect \" + tmp.handler.constructor.name + \" is raised \" + position, tmp, false, false))\n\nfun showStackTrace(header, tr, debug, showLocals) =\n  let\n    msg = header\n    curHandler = tr.contTrace\n    atTail = true\n  if debug do\n    while curHandler !== null do\n      let cur = curHandler.next\n      while cur !== null do\n        let curLocals = cur.getLocals\n        let loc = cur.getLoc\n        let localsMsg = if showLocals and curLocals.length > 0\n          then \" with locals: \" + curLocals.map(l => l.localName + \"=\" + Rendering.render(l.value)).join(\", \")\n          else \"\"\n        set\n          msg += \"\\n\\tat \" + cur.getNme + \" (\" + loc + \")\"\n          msg += localsMsg\n          cur = cur.next\n          atTail = false\n      set curHandler = curHandler.nextHandler\n      if curHandler !== null do\n        set\n          msg += \"\\n\\twith handler \" + curHandler.handler.constructor.name\n          atTail = false\n    if atTail do\n      set msg += \"\\n\\tat tail position\"\n  msg\n\nfun showFunctionContChain(cont, hl, vis, reps) =\n  if cont is FunctionContFrame then\n    let result = cont.constructor.name + \"(pc=\" + cont.saved.[1]\n    hl.forEach((m, marker) => if m.has(cont) do set result += \", \" + marker)\n    if vis.has(cont) then\n      set reps = reps + 1\n      if reps > 10 do\n        throw Error(\"10 repeated continuation frame (loop?)\")\n      set result += \", REPEAT\"\n    else\n      vis.add(cont)\n    result + \") -> \" + showFunctionContChain(cont.next, hl, vis, reps)\n  else if cont === null then\n    \"(null)\"\n  else\n    \"(NOT CONT)\"\n\nfun showHandlerContChain(cont, hl, vis, reps) =\n  if cont is HandlerContFrame then\n    let result = cont.handler.constructor.name\n    hl.forEach((m, marker) => if m.has(cont) do set result += \", \" + marker)\n    if vis.has(cont) then\n      set reps = reps + 1\n      if reps > 10 do\n        throw Error(\"10 repeated continuation frame (loop?)\")\n      set result += \", REPEAT\"\n    else\n      vis.add(cont)\n    result + \" -> \" + showFunctionContChain(cont.next, hl, vis, reps)\n  else if cont === null then\n    \"(null)\"\n  else\n    \"(NOT HANDLER CONT)\"\n\nfun debugCont(cont) = console.log(showFunctionContChain(cont, new Map(), new Set(), 0))\nfun debugHandler(cont) = console.log(showHandlerContChain(cont, new Map(), new Set(), 0))\n\nfun debugContTrace(contTrace) =\n  if contTrace is ContTrace then\n    console.log(\"resumed: \", contTrace.resumed)\n    if contTrace.last === contTrace do\n      console.log(\"<last is self>\")\n    if contTrace.lastHandler === contTrace do\n      console.log(\"<lastHandler is self>\")\n    let vis = new Set()\n    let hl = new Map()\n    hl.set(\"last\", new Set([contTrace.last]))\n    hl.set(\"last-handler\", new Set([contTrace.lastHandler]))\n    console.log(showFunctionContChain(contTrace.next, hl, vis, 0))\n    let cur = contTrace.nextHandler\n    while cur !== null do\n      console.log(showHandlerContChain(cur, hl, vis, 0))\n      set cur = cur.nextHandler\n    console.log()\n  else\n    console.log(\"Not a cont trace:\")\n    console.log(contTrace)\n\nfun debugEff(eff) =\n  if eff is EffectSig then\n    console.log(\"Debug EffectSig:\")\n    console.log(\"handler: \", eff.handler.constructor.name)\n    console.log(\"handlerFun: \", eff.handlerFun)\n    debugContTrace(eff.contTrace)\n  else\n    console.log(\"Not an effect:\")\n    console.log(eff)\n\n// runtime implementations\nfun unwind(...saved) =\n  set\n    curEffect.contTrace.last.next = new mut FunctionContFrame(null, saved)\n    curEffect.contTrace.last = curEffect.contTrace.last.next\n\nfun mkEffect(handler, handlerFun) =\n  let res = new mut EffectSig(new mut ContTrace(null, null, null, null, false), handler, handlerFun)\n  set\n    res.contTrace.last = res.contTrace\n    res.contTrace.lastHandler = res.contTrace\n    curEffect = res\n\nfun handleBlockImpl(cur, handler) =\n  let handlerFrame = new mut HandlerContFrame(null, null, handler)\n  set\n    cur.contTrace.lastHandler.nextHandler = handlerFrame\n    cur.contTrace.lastHandler = handlerFrame\n    cur.contTrace.last = handlerFrame\n  handleEffects(cur)\n\nfun enterHandleBlock(handler, body) =\n  let tmp = body()\n  if curEffect === null then\n    tmp\n  else\n    handleBlockImpl(curEffect, handler)\n\nfun handleEffects(cur) =\n  while cur is\n    EffectSig then\n      let nxt = handleEffect(cur)\n      if cur === nxt then\n        set curEffect = cur\n        return null\n      else\n        set cur = nxt\n    else\n      return cur\n\n// return either new effect, final result or the same continuation if there is no handler\nfun handleEffect(cur) =\n  // debugEff(cur)\n  // find the handle block corresponding to the current effect\n  let prevHandlerFrame = cur.contTrace\n  while prevHandlerFrame.nextHandler !== null and prevHandlerFrame.nextHandler.handler !== cur.handler do\n    set prevHandlerFrame = prevHandlerFrame.nextHandler\n\n  // no matching handle block\n  if prevHandlerFrame.nextHandler === null do\n    return cur\n\n  // the matching handle block\n  let handlerFrame = prevHandlerFrame.nextHandler\n\n  // unlink and save frames\n  let saved = new mut ContTrace(\n    handlerFrame.next,\n    cur.contTrace.last,\n    handlerFrame.nextHandler,\n    cur.contTrace.lastHandler,\n    false\n  )\n  set\n    cur.contTrace.last = handlerFrame\n    cur.contTrace.lastHandler = handlerFrame\n    handlerFrame.next = null\n    handlerFrame.nextHandler = null\n\n  // handle the effect\n  set curEffect = null\n  let tmp = set stackDepth += 2 in cur.handlerFun(resume(cur.contTrace))\n  if curEffect !== null then\n    set cur = curEffect\n    // relink the saved frames\n    if saved.next !== null do\n      set\n        cur.contTrace.last.next = saved.next\n        cur.contTrace.last = saved.last\n    if saved.nextHandler !== null do\n      set\n        cur.contTrace.lastHandler.nextHandler = saved.nextHandler\n        cur.contTrace.lastHandler = saved.lastHandler\n    cur\n  else\n    // resume the unlinked handle blocks\n    resumeContTrace(saved, tmp)\n\nfun resume(contTrace)(value) =\n  if contTrace.resumed do\n    throw Error(\"Multiple resumption\")\n  set contTrace.resumed = true\n  handleEffects(resumeContTrace(contTrace, value))\n\nfun resumeContTrace(contTrace, value) =\n  let cont = contTrace.next\n  let handlerCont = contTrace.nextHandler\n  while\n    cont is FunctionContFrame then\n      set curEffect = null\n      set value = set stackDepth += 3 in cont.resume(value)\n      if curEffect !== null do\n        set value = curEffect\n      if value is EffectSig then\n        set\n          value.contTrace.last.next = cont.next\n          value.contTrace.lastHandler.nextHandler = handlerCont\n        if contTrace.last !== cont do\n          set value.contTrace.last = contTrace.last\n        if handlerCont !== null do\n          set value.contTrace.lastHandler = contTrace.lastHandler\n        return value\n      else\n        set cont = cont.next\n    handlerCont is HandlerContFrame then\n      set cont = handlerCont.next\n      set handlerCont = handlerCont.nextHandler\n    else\n      return value\n\n// stack safety\nmut val stackLimit = 0 // How deep the stack can go before heapifying the stack\nmut val stackDepth = 0\nmut val stackHandler = null\nmut val stackResume = null\n\nobject StackDelayHandler with\n  fun delay() = mkEffect of this, k =>\n    set stackResume = k\n\nfun checkDepth() =\n  if stackDepth >= stackLimit && stackHandler !== null then\n    // this is a tail call to effectful function\n    stackHandler.delay()\n  else\n    ()\n\nfun runStackSafe(limit, f) =\n  set stackLimit = limit in...\n  set stackDepth = 1 in...\n  set stackHandler = StackDelayHandler in...\n  let result = enterHandleBlock(StackDelayHandler, f)\n  if curEffect !== null do\n    throw new Error(\"Effect crossed through stack safe boundary\")\n  while stackResume !== null do\n    let saved = stackResume\n    set\n      stackResume = null\n      stackDepth = 1\n      result = saved(())\n    if curEffect !== null do\n      throw new Error(\"Effect crossed through stack safe boundary\")\n  result\n\nclass Int31(v) with\n  fun zext() = bitand(v, bitnot(shl(1, 31))) as Int\n  fun sext() = bitor(v, shl(1, 31)) as Int\n\nfun plus_impl(lhs, rhs) = if lhs is\n  Int31 and rhs is Int31 then lhs + rhs\n  else unreachable()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Shape.mls",
    "content": "import \"./Block.mls\"\nimport \"./Option.mls\"\n\nopen Block { Literal, ClassSymbol, showSymbol, isPrimitiveType, isPrimitiveTypeOf }\nopen Option\n\ntype Shape = Shape.Shape\n\nmodule Shape with...\n\nclass Shape with\n  constructor\n    Dyn()\n    Lit(val l: Literal)\n    Arr(val shapes: Array[Shape])\n    Class(val sym: ClassSymbol, val params: Array[Shape])\n\nfun show(s: Shape) =\n  if s is\n    Dyn then \"Dyn\"\n    Lit(lit) then \"Lit(\" + Block.showLiteral(lit) + \")\"\n    Arr(shapes) then \"Arr(\" + shapes.map(show).join(\", \") + \")\"\n    Class(sym, params) then \"Class(\" + showSymbol(sym) + \", [\" + params.map(show).join(\", \") + \"])\"\n\nfun sel(s1: Shape, s2: Shape): Array[Shape] = \n  if [s1, s2] is\n    [Class(sym, params), Lit(n)] and n is Str\n      and sym.args is Some(args)\n      and args.find(_ == n)\n        == () then []\n        is i then [params.(i)]\n    [Dyn, Lit(n)] and n is Str\n      then [Dyn()]\n    [Arr(shapes), Lit(n)] and n is Int\n      then [shapes.(n)]\n    [Arr(shapes), Dyn] then\n      shapes\n    [Dyn, Lit(n)] and n is Int\n      then [Dyn()]\n    [Dyn, Dyn]\n      then [Dyn()]\n    else [] // TODO: return no possibility instead of err?\n\nfun static(s: Shape) = \n  if s is\n    Dyn then false\n    Lit(l) then not (l is Str and isPrimitiveType(l)) // redundant bracket?\n    Class(_, params) then params.every(static)\n    Arr(shapes) then shapes.every(static)\n\nopen Block { Case }\n\nfun silh(p: Case): Shape = if p is\n  Block.Lit(l) then Lit(l)\n  Block.Cls(sym, path) then\n    val size = if sym.args is Some(i) then i else 0\n    Class(sym, Array(size).fill(Dyn))\n  Block.Tup(n) then Arr(Array(n).fill(Dyn))\n\n// TODO: use Option instead, since all of them return at most one shape\nfun filter(s: Shape, p: Case): Array[Shape] =\n  if [s, p] is\n    [Lit(l1), Block.Lit(l2)] and l1 == l2 then [s]\n    [Lit(l), Block.Cls(c, _)] and isPrimitiveTypeOf(c, l) then [s]\n    [Arr(ls), Block.Tup(n)] and ls.length == n then [s]\n    [Class(c1, _), Block.Cls(c2, _)] and c1.name == c2.name then [s]\n    [Dyn, _] then [silh(p)]\n    else []\n\nfun rest(s: Shape, p: Case): Array[Shape] =\n  if [s, p] is\n    [Lit(l1), Block.Lit(l2)] and l1 == l2 then []\n    [Lit(l), Block.Cls(c, _)] and isPrimitiveTypeOf(c, l) then []\n    [Arr(ls), Block.Tup(n)] and ls.length == n then []\n    [Class(c1, _), Block.Cls(c2, _)] and c1.name == c2.name then []\n    [Dyn, _] then [s]\n    else [s]"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Stack.mls",
    "content": "\nimport \"./Predef.mls\"\nopen Predef\n\n\ntype Stack[A] = Stack.{ Cons[A] | Nil }\n\nmodule Stack with ...\n\n\ndata class (::) Cons[A](head: A, tail: Stack[A])\nobject Nil\n\nfun isEmpty(xs) = xs is Nil\n\nfun reverseAndAppend(xs, tail) = if xs is\n  h :: t then reverseAndAppend(t, h :: tail)\n  Nil then tail\n\nfun reverse(xs) = reverseAndAppend(xs, Nil)\n\nfun fromArray(arr) =\n  let \n    ls = Nil\n    i = arr.length - 1\n  while i >= 0 do \n    ls = arr.at(i) :: ls\n    set i -= 1\n  ls\n\nfun toArray(xs) =\n  xs reverse() toReverseArray()\n\nfun toReverseArray(xs) =\n  let\n    arr = mut []\n    i = 0\n  while xs is\n    h :: t do\n      arr.push(h)\n      set xs = t\n  arr\n\nfun zip(...xss) =\n  fun go(heads, tails) = case\n    h :: t and h is\n      h2 :: t2 then go(h2 :: heads, t2 :: tails)(t)\n      Nil then go(heads, tails)(t)\n    Nil and heads is\n      Nil then (assert tails is Nil, Nil) // * TODO: improve syntax (parens are currently needed)\n      else heads toArray() :: go(Nil, Nil) of tails reverse()\n  go(Nil, Nil) of fromArray(xss)\n\n// * Non-recursive efficient internally-mutable list concatenation.\nfun (:::) concat(xs, ys) = if\n  ys is Nil then xs\n  xs is\n    Nil then ys\n    head' :: tail' then\n      let\n        result = new mut ::(head', ys)\n        current = result // the insertion point\n        rest = tail' // the remaining of `xs`\n      while rest is head :: tail do\n        let next = new mut ::(head, ys)\n        set current.tail = next\n        Object.freeze(current)\n        set\n          current = next\n          rest = tail\n      Object.freeze(result)\n\nfun (:+) append(xs, y) = xs ::: y :: Nil\n\nfun filter(xs, f) = if xs is\n  head :: tail and\n    f(head) then head :: filter(tail, f)\n    else filter(tail, f)\n  Nil then Nil\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/StrOps.mls",
    "content": "\nmodule StrOps with ...\n\n\nfun (~) concat2(a, b) = a + b\n\nfun concat(...xs) = xs.join(\"\")\n\nfun from(value) = globalThis.String(value)\n\nfun parenthesizedIf(x, cond) = if cond then \"(\" + x + \")\" else x\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/Term.mls",
    "content": "import \"fs\"\nimport \"process\"\nimport \"path\"\nimport \"url\"\n\nimport \"./Predef.mls\"\nimport \"./StrOps.mls\"\n\nopen Predef\n\nmodule Term with...\n\nclass Symbol(val name: Str)\ntype Literal = null | undefined | Str | Int | Num | Bool\n\nclass Pattern with\n  constructor\n    LitPattern(val lit: Literal)\n    Var(val sym: Symbol)\n    ClassLike(val sym: Symbol, val trm: Term, val parameters: Array[Symbol] | null)\n    Tuple(val size: Int, val inf: Bool)\n    Record(val entities: Array[[Str, Symbol]])\n\nclass Branch(val scrutinee: Ref, val ptrn: Pattern, val continuation: Split)\n\nclass Split with\n  constructor\n    Cons(val head: Branch, val tail: Split)\n    Let(val sym: Symbol, val term: Term, val tail: Split)\n    Else(val default: Term)\n    End\n\n\nmodule Keyword with\n  object\n    If\n    While\n\n\nclass Statement with\n  constructor\n    LetDecl(val sym: Symbol)\n    DefineVar(val sym: Symbol, val rhs: Term)\n    // TODO: other statements\n\n\nclass Term with\n  constructor\n    Lit(val lit: Literal)\n    Builtin(val name: Str)\n    Ref(val sym: Symbol)\n    CSRef(val sym: Symbol, val base: Str, val file: Str | undefined)\n    App(val lhs: Term, val rhs: Term)\n    Sel(val prefix: Term, val nme: Str)\n    DynSel(val prefix: Term, val fld: Term, val arrayIdx: Bool)\n    Tup(val fields: Array[Term])\n    IfLike(val kw: Keyword.If | Keyword.While, val desugared: Split)\n    Lam(val params: Array[Symbol], val body: Term)\n    Blk(val stats: Array[Statement], val res: Term)\n    New(val cls: Term, val args: Array[Term])\n    Region(val name: Symbol, val body: Term)\n    RegRef(val reg: Term, val value: Term)\n    Assgn(val lhs: Term, val rhs: Term)\n    Deref(val ref: Term)\n    SetRef(val ref: Term, val value: Term)\n    Ret(val result: Term)\n    Throw(val result: Term)\n    Try(val body: Term, val finallyDo: Term)\n    \n\nclass Context(val names: Map[Str, Int], val bindings: Map[Symbol, Str], val dependencies: Set[Str], val printOnly: Bool) with\n  fun get(sym) =\n    if bindings.has(sym) then bindings.get(sym)\n    else if printOnly then sym.name\n    else throw Error(StrOps.concat(\"Invalid binding name \", sym.name))\n  fun nest = Context(names, new Map(bindings), dependencies, printOnly)\n  fun add(sym) =\n    let fn = freshName(sym.name)\n    bindings.set(sym, fn)\n    fn\n  fun depends(d) = dependencies.add(d)\n  fun freshName(name) =\n    if not names.has(name) do\n      names.set(name, 0)\n    let i = names.get(name)\n    names.set(name, i + 1)\n    StrOps.concat of name, \"_\", i.toString()\n\n\nfun indent(str, ind, keepLeading) =\n  let res = str.split(\"\\n\").map(s => StrOps.concat(ind, s)).join(\"\\n\")\n  if keepLeading then res\n  else res.substring(ind.length)\n\nfun showStmt(s, ctx) =\n  if s is\n    LetDecl(sym) then\n      let freshName = ctx.add(sym)\n      StrOps.concat(\"let \", freshName)\n    DefineVar(sym, value) then StrOps.concat of ctx.get(sym), \" = \", show(value, ctx)\n\n\nfun showPattern(p, ctx) =\n  if p is\n    LitPattern(lit) then lit.toString()\n  // TODO: other patterns\n\n\nfun paren(t, ctx) =\n  if (t is Ref) || (t is CSRef) || (t is Lit) || (t is Sel) then show(t, ctx)\n  else StrOps.concat of \"(\", show(t, ctx), \")\"\n\n\nfun showSplit(s, ctx, isCont) =\n  if s is\n    Cons(Branch(scrut, ptrn, cont), tail) then\n      StrOps.concat of show(scrut, ctx), \" is \", showPattern(ptrn, ctx), \" then \", showSplit(cont, ctx, true), \"\\n\", showSplit(tail, ctx, false)\n    Let(sym, term, split) then\n      let nest = ctx.nest\n      let freshName = nest.add(sym)\n      StrOps.concat of \"let \", freshName, \" = \", show(term, nest), \"\\n\", showSplit(split, nest, false)\n    Else(term) then\n      if isCont then show(term, ctx)\n      else StrOps.concat of \"else \", show(term, ctx)\n    End then \"\"\n\n\nfun show(t, ctx) =\n  if t is\n    Ref(sym) then ctx.get(sym)\n    CSRef(Symbol(name), baseFile, file) then\n      if file is undefined then ctx.depends(baseFile)\n      else ctx.depends(path.join of path.dirname(baseFile), file)\n      name\n    Lit(lit) then lit.toString()\n    Builtin(name) then name\n    Sel(prefix, name) then StrOps.concat of paren(prefix, ctx), \".\", name\n    App(lhs, rhs) then StrOps.concat of paren(lhs, ctx), show(rhs, ctx)\n    Tup(fields) then StrOps.concat of \"(\", fields.map(t => show(t, ctx)).join(\", \"), \")\"\n    Lam(params, body) then\n      let nest = ctx.nest\n      let freshParams = params.map(s => nest.add(s))\n      StrOps.concat of \"(\", freshParams.join(\", \"), \") =>\\n\", indent(show(body, nest), \"  \", true)\n    Blk(stats, res) then\n      let nest = ctx.nest\n      StrOps.concat of stats.map(s => showStmt(s, nest)).join(\"\\n\"), \"\\n\", show(res, nest)\n    IfLike(Keyword.If, split) then StrOps.concat of \"if \\n\", indent(showSplit(split, ctx, false), \"  \", true)\n    // TODO: other terms\n\nfun print(t) =\n  let ctx = Context(new Map(), new Map(), new Set(), true)\n  console.log(show(t, ctx))\n\n\nfun genImport(base, p) =\n  StrOps.concat of \"import \\\"./\", path.relative(base, url.fileURLToPath(p)).slice(0, -4), \".mls\\\"\"\n\n\nfun codegen(t, file) =\n  let ctx = Context(new Map(), new Map(), new Set(), false)\n  let moduleName = path.parse(file).name\n  let fullpath = path.join of process.cwd(), file\n  let code = StrOps.concat of \"module \", moduleName, \" with ...\\nfun res =\\n\", indent(show(t, ctx), \"  \", true), \"\\n\"\n  let dependencies =\n    Array.from(ctx.dependencies).map(s => genImport(path.dirname(fullpath), s))\n  if not fs.existsSync(file) do\n    fs.writeFileSync(file, \"\", \"utf8\")\n  let originData = fs.readFileSync(file, \"utf8\")\n  let newData = StrOps.concat of dependencies.join(\"\\n\"), \"\\n\", code\n  if newData != originData do\n    fs.writeFileSync(file, newData, \"utf8\")\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/TreeTracer.mls",
    "content": "import \"./Predef.mls\"\nimport \"./StrOps.mls\"\n\nopen Predef { fold }\n\nmodule TreeTracer with ...\n\nclass TreeTracer with\n  mut val steps = 0\n  mut val enabled = false\n  fun output(outie, innie, innieAlt, message) = if enabled do\n    let lines = message.split(\"\\n\")\n    lines.forEach of (line, i, xs) => if\n      let postfix = if lines.length > 1 then \" ↵\" else \"\"\n      i is 0 then console.log(outie + innie + line + postfix)\n      i + 1 == lines.length then console.log(outie + innieAlt + line)\n      else console.log(outie + innieAlt + line + postfix)\n  fun enter(...pieces) =\n    output of\n      if steps > 0 then \"│ \".repeat(steps - 1) + \"├─\" else \"\"\n      if steps > 0 then \"┮ \" else \"┍ \"\n      \"│ \"\n      fold(+) of ...pieces\n    set steps += 1\n  fun print(...pieces) =\n    let message = if pieces is\n      [..pieces, Int as line] then fold(+) of ...pieces, \" [Ln \" + line + \"]\"\n      else fold(+) of ...pieces\n    output of\n      if steps > 0 then \"│ \".repeat(steps - 1) else \"\"\n      if steps > 0 then \"├ \" else \"\"\n      \"│ \"\n      message\n  fun leave(...pieces) =\n    set steps -= 1\n    output of\n      \"│ \".repeat(steps)\n      \"┕ \"\n      \"  \"\n      fold(+) of ...pieces\n  fun trace[A](intro: Str, makeOutro: A -> Str, thunk: () -> A): A =\n    enter of intro\n    val result = thunk()\n    leave of makeOutro of result\n    result\n  fun reset() = set steps = 0\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/XML.mls",
    "content": "import \"./Predef.mls\"\nimport \"./Iter.mls\"\n\nopen Predef\nopen Iter { mapping, joined }\n\n\ndata class StyleAttributeValue(rules) with\n  fun toValue() = JSON.stringify of Object.entries(rules)\n    mapping of case [name, value] then name + \": \" + value\n    joined(\"; \")\n\nmodule XML with ...\n\nfun serializeValue(value) = if value is\n  Str then JSON.stringify(value)\n  StyleAttributeValue then value.toValue()\n    \nfun joinAttributes(attributes) = attributes\n  mapping of case\n    [name, value] then name + \"=\" + serializeValue(value)\n    StyleAttributeValue as style then \"style=\" + style.toValue()\n    Object as record then joinAttributes(Object.entries(record))\n  joined(\" \")\n\nfun elem(tagName, ...attributes)(...elements) = fold(+) of\n  \"<\"\n  tagName\n  if attributes is [] then \"\" else \" \" + joinAttributes(attributes)\n  \">\"\n  ...elements\n  \"</\"\n  tagName\n  \">\"\n\nfun tag(tagName)(...attributes) = fold(+) of\n  \"<\"\n  tagName\n  if attributes is [] then \"\" else \" \" + joinAttributes(attributes)\n  \" \"\n  \"/>\"\n\nfun style(rules) = StyleAttributeValue(rules)\n\nfun html(...attributes)(...elements) =\n  \"<!DOCTYPE html>\" + elem(\"html\", ...attributes)(...elements)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/Accounting.mls",
    "content": "\nimport \"fs\"\n\nimport \"../StrOps.mls\"\nopen StrOps\n\nimport \"../Predef.mls\"\nopen Predef\n\n\ndeclare class Num\ndeclare class Bool\n\ndeclare val String\n\n\ndata class Accounting with ...\n\n\nfun display(amt): Str = (amt / 1000).toFixed(1)\n\nval warnings = mut []\n\n\ndata class Project(val num: Str)\n\n\ndata class Line(val name: Str, val proj: Project, val starting_balance: Num, val isMatchable: Bool) with\n  mut val balance = starting_balance\n  fun expense(amt) =\n    set balance = balance -. amt\n  fun mustBeEmpty() =\n    if balance > 10_000 do\n      warnings.push of \"> **❗️** Unspent balance of \" ~ name ~ \": `\" ~ display(balance) ~ \"`\"\n\nval lines = mut []\n\nfun mkLine(nme, proj, starting_balance, matchable) =\n  let line = Line(nme, proj, starting_balance, matchable)\n  lines.push(line)\n  line\n\n\ndata class Report(fileName) with\n  \n  fs.writeFileSync(fileName, \"# Accounting\\n\")\n  \n  fun w(txt) =\n    fs.appendFileSync(fileName, txt)\n  fun wln(txt) =\n    fs.appendFileSync(fileName, txt ~ \"\\n\")\n  \n  fun init() =\n    wln of \"\"\n    wln of \"|\" ~ \"Year\" ~ \"|\" ~ lines.map(x => x.name).join(\"|\") ~ \"|\"\n    wln of \"|\" ~ \"---\" ~ \"|\" ~ lines.map(x => \"--:\").join(\"|\") ~ \"|\"\n  \n  fun snapShot(label) =\n    wln of \"|\" ~ String(label) ~ \"|\" ~ lines.map(x => display(x.balance)).join(\"|\") ~ \"|\"\n    \n  fun wrapUp() =\n    wln of \"\"\n    warnings.forEach of x => (wln(x), wln(\"\"))\n    wln of \"### Remaining Available Funds\"\n    wln of \"\"\n    wln of \"|\" ~ \"Summary\" ~ \"|   |\"\n    wln of \"|\" ~ \"---\" ~ \"|--:|\"\n    wln of \"|\" ~ \"Matchable\" ~ \"|\" ~ display(\n      lines.filter(x => x.isMatchable).map(x => x.balance).reduce((a, b) => a +. b, 0)\n    ) ~ \"|\"\n    wln of \"|\" ~ \"Non-matchable\" ~ \"|\" ~ display(\n      lines.filter(x => not x.isMatchable).map(x => x.balance).reduce((a, b) => a +. b, 0)\n    ) ~ \"|\"\n\nfun process(filename, k) =\n  let report = Report(filename)\n  report.init()\n  k(report)\n  report.wrapUp()\n  print of \"Report written to \" ~ filename\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/CSV.mls",
    "content": "\n// Adapted from https://www.bennadel.com/blog/1504-ask-ben-parsing-csv-strings-with-javascript-exec-regular-expression-command.htm\n// (JS code commented at bottom)\n\nimport \"../Predef.mls\"\nopen Predef\n\n\n// The default delimiter is the comma, but this can be overriden here.\ndata class CSV(strDelimiter) with ...\n\n\n// Check to see if the delimiter is defined. If not, then default to comma.\nif strDelimiter is undefined then set strDelimiter = \",\"\n\nval objPattern = new mut RegExp of\n  // Delimiters.\n  \"(\\\\\" + strDelimiter + \"|\\\\r?\\\\n|\\\\r|^)\"\n  // Quoted fields.\n  + \"(?:\\\"([^\\\"]*(?:\\\"\\\"[^\\\"]*)*)\\\"|\"\n  // Standard fields.\n  + \"([^\\\"\\\\\" + strDelimiter + \"\\\\r\\\\n]*))\"\n  \"gi\"\n\n// This will parse a delimited string into an array of arrays.\nfun toArrays(strData) =\n  \n  // Create an array to hold our data. Give the array a default empty first row.\n  let arrData = mut [mut []]\n  \n  // Keep looping over the regular expression matches until we can no longer find a match.\n  while\n    let arrMatches = objPattern.exec(strData)\n    arrMatches !== null do\n      \n      // Get the delimiter that was found.\n      let strMatchedDelimiter = arrMatches.1\n      \n      // Check to see if the given delimiter has a length (is not the start of string)\n      // and if it matches field delimiter.\n      // If id does not, then we know that this delimiter is a row delimiter.\n      if strMatchedDelimiter.length != 0 and strMatchedDelimiter != strDelimiter do\n        // Since we have reached a new row of data, add an empty row to our data array.\n        arrData.push(mut [])\n      \n      // Now that we have our delimiter out of the way,\n      // let's check to see which kind of value we captured (quoted or unquoted).\n      let strMatchedValue =\n        if arrMatches.2 != undefined\n        then\n          // We found a quoted value. When we capture this value, unescape any double quotes.\n          arrMatches.2.replace of\n            new mut RegExp(\"\\\"\\\"\", \"g\")\n            \"\\\"\"\n        else\n          // We found a non-quoted value.\n          arrMatches.3\n      \n      arrData.at(arrData.length - 1).push(strMatchedValue)\n  \n  arrData\n\n\n/*\n  // This will parse a delimited string into an array of\n  // arrays. The default delimiter is the comma, but this\n  // can be overriden in the second argument.\n  function CSVToArray( strData, strDelimiter ){\n    // Check to see if the delimiter is defined. If not,\n    // then default to comma.\n    strDelimiter = (strDelimiter || \",\");\n\n    // Create a regular expression to parse the CSV values.\n    var objPattern = new mut RegExp(\n      (\n        // Delimiters.\n        \"(\\\\\" + strDelimiter + \"|\\\\r?\\\\n|\\\\r|^)\" +\n\n        // Quoted fields.\n        \"(?:\\\"([^\\\"]*(?:\\\"\\\"[^\\\"]*)*)\\\"|\" +\n\n        // Standard fields.\n        \"([^\\\"\\\\\" + strDelimiter + \"\\\\r\\\\n]*))\"\n      ),\n      \"gi\"\n      );\n\n\n    // Create an array to hold our data. Give the array\n    // a default empty first row.\n    var arrData = [[]];\n\n    // Create an array to hold our individual pattern\n    // matching groups.\n    var arrMatches = null;\n\n\n    // Keep looping over the regular expression matches\n    // until we can no longer find a match.\n    while (arrMatches = objPattern.exec( strData )){\n\n      // Get the delimiter that was found.\n      var strMatchedDelimiter = arrMatches[ 1 ];\n\n      // Check to see if the given delimiter has a length\n      // (is not the start of string) and if it matches\n      // field delimiter. If id does not, then we know\n      // that this delimiter is a row delimiter.\n      if (\n        strMatchedDelimiter.length != 0 &&\n        (strMatchedDelimiter != strDelimiter)\n        ){\n\n        // Since we have reached a new row of data,\n        // add an empty row to our data array.\n        arrData.push( [] );\n\n      }\n\n\n      // Now that we have our delimiter out of the way,\n      // let's check to see which kind of value we\n      // captured (quoted or unquoted).\n      if (arrMatches[ 2 ]){\n\n        // We found a quoted value. When we capture\n        // this value, unescape any double quotes.\n        var strMatchedValue = arrMatches[ 2 ].replace(\n          new mut RegExp( \"\\\"\\\"\", \"g\" ),\n          \"\\\"\"\n          );\n\n      } else {\n\n        // We found a non-quoted value.\n        var strMatchedValue = arrMatches[ 3 ];\n\n      }\n\n\n      // Now that we have our value string, let's add\n      // it to the data array.\n      arrData[ arrData.length - 1 ].push( strMatchedValue );\n    }\n\n    // Return the parsed data.\n    return( arrData );\n  }\n*/\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/BasicExpr.mls",
    "content": "import \"../../StrOps.mls\"\nimport \"../../Option.mls\"\nimport \"../../Predef.mls\"\n\nopen StrOps { parenthesizedIf }\nopen Option { Some, None }\nopen Predef { mkStr }\n\ntype OptionT[A] = Some[A] | None\n\nmodule BasicExpr with\n  type Expr = Lit | Var | Add | Mul | Err\n  \n  data\n    class\n      Lit(value: Int)\n      Var(name: Str)\n      Add(left: Expr, right: Expr)\n      Mul(left: Expr, right: Expr)\n      Err(expr: OptionT[Expr], msg: Str)\n  \n  fun withErr(expr, msg) = Err(Some(expr), msg)\n  fun justErr(msg) = Err(None, msg)\n  \n  fun prettyPrint(tree: Expr): Str = if tree is\n    Lit(value) then value.toString()\n    Var(name) then name\n    Add(left, right) then left prettyPrint() + \" + \" + right prettyPrint()\n    Mul(left, right) then StrOps.concat of\n      left prettyPrint() parenthesizedIf(left is Add)\n      \" * \"\n      right prettyPrint() parenthesizedIf(right is Add)\n    Err(Some(expr), msg) then \"{ \" + expr prettyPrint() + \" | \" + JSON.stringify(msg) + \" }\"\n    Err(None, msg) then \"{ \" + JSON.stringify(msg) + \" }\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Expr.mls",
    "content": "import \"../../StrOps.mls\"\nimport \"../../Option.mls\"\nimport \"../../Predef.mls\"\n\nopen StrOps { parenthesizedIf }\nopen Option { Some, None }\n\ntype OptionT[A] = Some[A] | None\n\nmodule Expr with\n  val opPrec = case\n    \"**\" then [70, 69]\n    \"*\" then [50, 50]\n    \"/\" then [50, 50]\n    \"+\" then [30, 30]\n    \"-\" then [30, 30]\n\n  type Expr = Lit | Var | Inf | Err\n  \n  data\n    class\n      Lit(value: Int)\n      Var(name: Str)\n      Inf(op: Str, left: Expr, right: Expr)\n      Err(expr: OptionT[Expr], msg: Str)\n  \n  fun withErr(expr, msg) = Err(Some(expr), msg)\n  fun justErr(msg) = Err(None, msg)\n  \n  fun prettyPrint(tree: Expr): Str = if tree is\n    Lit(value) then value.toString()\n    Var(name) then name\n    Inf(op, left, right) then if opPrec(op) is [l, r] then StrOps.concat of\n      left prettyPrint() parenthesizedIf of \n        left is Inf(op', _, _) and opPrec(op') is [_, r'] and r' < l\n      \" \"\n      op\n      \" \"\n      right prettyPrint() parenthesizedIf of\n        right is Inf(op', _, _) and opPrec(op') is [l', _] and r > l'\n    Err(Some(expr), msg) then \"{ \" + expr prettyPrint() + \" | \" + JSON.stringify(msg) + \" }\"\n    Err(None, msg) then \"{ \" + JSON.stringify(msg) + \" }\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Extension.mls",
    "content": "import \"./Keywords.mls\"\nimport \"./Rules.mls\"\nimport \"./Token.mls\"\nimport \"./ParseRule.mls\"\nimport \"./Tree.mls\"\nimport \"../../Stack.mls\"\nimport \"../../Option.mls\"\nimport \"../../Predef.mls\"\nimport \"../../Iter.mls\"\nimport \"../../MutMap.mls\"\n\nopen Predef\nopen Stack\nopen Option { Some, None }\nopen Token { LiteralKind }\nopen ParseRule { Choice }\n\nmodule Extension with ...\n\nfun isDiagramDirective(tree: Tree) = tree is\n  Tree.Define(Tree.DefineKind.Directive, [Tree.Ident(\"diagram\", _), _] :: Nil)\n\nfun parsePrecedenceTree(tree: Tree) = if tree is\n  Tree.Ident(\"None\", _) then None\n  Tree.App(Tree.Ident(\"Some\", _), Tree.Literal(Token.LiteralKind.Integer, value)) then\n    Some(parseInt(value, 10))\n\nfun extendKeyword(tree: Tree) =\n  if tree is Tree.Tuple(keyword :: leftPrec :: rightPrec :: Nil) and\n    keyword is Tree.Literal(Token.LiteralKind.String, name) then\n      let leftPrec' = parsePrecedenceTree(leftPrec)\n      let rightPrec' = parsePrecedenceTree(rightPrec)\n      Keywords.keyword(name, leftPrec', rightPrec')\n    else print of \"expect a string literal but found \" + keyword\n  else print of \"expect a tuple but found \" + tree\n\n// * Add an empty parse rule to the map associated with the given name.\nfun newCategory(tree: Tree) =\n  if tree is Tree.Literal(Token.LiteralKind.String, name) and\n    Rules.syntaxKinds |> MutMap.get(name) is\n      Some(rule) then print of \"Category already exists: \" + rule.display\n      None then\n        Rules.syntaxKinds |> MutMap.insert(name, ParseRule.ParseRule(name, Nil))\n        Rules.extendedKinds.add(name)\n  else\n    print of \"expect a string literal but found \" + tree\n\npattern OpenCategory = \"term\" | \"type\" | \"decl\"\npattern ClosedCategory = \"ident\" | \"typevar\"\n\nfun extendCategory(choiceBodyTree: Tree) =\n  if parseChoiceTree(choiceBodyTree) is\n    Some([kindName, choice]) and Rules.syntaxKinds |> MutMap.get(kindName) is\n      Some(rule) and kindName is\n        // If the `kindName` is built-in and extensible, we check if the choice\n        // refers to another category in the beginning. If so, we inline the\n        // referenced category's choices into the current choice.\n        OpenCategory and choice is\n          Choice.Ref(refKindName, process, outerPrec, innerPrec, rest) and\n            Rules.syntaxKinds |> MutMap.get(refKindName) is Some(refRule) then\n              // TODO: The `process` function should be applied to the referenced rule.\n              // TODO: How to handle `outerPrec` and `innerPrec`?\n              rule.extendChoices of refRule.andThen(rest, process).choices\n            else\n              // The referenced category is not found in the map. Stop.\n              print of \"Unknown referenced syntax category: \" + refKindName\n          else\n            // Otherwise, we can directly extend the target parse rule.\n            rule.extendChoices(choice :: Nil)\n        ClosedCategory then print of \"Cannot extend a closed category: \" + kindName\n        else rule.extendChoices(choice :: Nil)\n      None then print of \"Unknown syntax kind: \" + kindName\n    None then\n      print of \"Invalid syntax description: \" + choiceBodyTree Tree.summary()\n\nfun parseChoiceTree(tree: Tree) = \n  fun go(trees: Stack[Tree]): Choice[Tree] = \n    let res = if trees is\n      Tree.App(Tree.Ident(\"keyword\", _), Tree.Literal(LiteralKind.String, name)) :: rest and\n        Keywords.all |> MutMap.get(name) is Some(keyword) then\n          Choice.keyword(keyword)(go(rest))\n      Tree.Literal(LiteralKind.String, name) :: rest then\n        Choice.reference(name)(process: Cons, name: \"unnamed\", choices: tuple of go(rest))\n      Nil then Choice.end(Nil)\n    res\n  \n  if tree is\n    Tree.Tuple(categoryIdent :: choiceTree :: funcIdent :: Nil) and\n      categoryIdent is Tree.Literal(LiteralKind.String, categoryName) and\n        funcIdent is Tree.Ident and\n          let op = (trees) => trees\n            Iter.fromStack()\n            Iter.folded of funcIdent, (f, x) => Tree.App(f, x)\n          choiceTree is\n            Tree.Bracketed(Token.Square, Tree.Tuple(elements)) then\n              Some of tuple of\n                categoryName\n                go(elements) Choice.map(op)\n            Tree.Bracketed(Token.Square, other) then\n              Some of tuple of\n                categoryName\n                go(other :: Nil) Choice.map(op)\n        else\n          print of \"Expect the choiceTree to be a bracketed term but found\", choiceTree Tree.summary()\n          None\n      else\n        print of \"Expect a the category to be an identifier but found \" + categoryIdent Tree.summary()\n        None\n    else\n      print of \"Expect the definition to be a tuple but found \" + tree Tree.summary()\n      None\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Keywords.mls",
    "content": "import \"../../Option.mls\"\nimport \"../../Iter.mls\"\nimport \"../../Predef.mls\"\nimport \"../../MutMap.mls\"\n\nopen Predef\nopen Option { Some, None }\n\nmodule Keywords with ...\n\n// https://v8.dev/blog/pointer-compression\n// The maximal and minimal values of V8's Smi on 64-bit platforms.\nval INT_MIN = -2147483648\nval INT_MAX = 2147483647\n\nclass Keyword(val name: Str, val leftPrec, val rightPrec) with  \n  fun leftPrecOrMin = if leftPrec is Some(prec) then prec else INT_MIN\n  fun rightPrecOrMin = if rightPrec is Some(prec) then prec else INT_MIN\n  fun leftPrecOrMax = if leftPrec is Some(prec) then prec else INT_MAX\n  fun rightPrecOrMax = if rightPrec is Some(prec) then prec else INT_MAX\n  \n  fun toString() = fold(+) of\n    \"Keyword(`\", name, \"`, \"\n    (if leftPrec is Some(prec) then prec.toString() else \"N/A\"), \", \",\n    (if rightPrec is Some(prec) then prec.toString() else \"N/A\"), \")\"\n\nfun makePrecMap(startPrec: Int, ...ops) =\n  let\n    m = MutMap.empty\n    i = 0\n  while i < ops.length do\n    ops.at(i).split(\" \").forEach of (op, _, _) =>\n      if op.length > 0 do\n        m |> MutMap.insert of op, i + startPrec\n    set i += 1\n  m\n\nval all = MutMap.empty\nfun keyword(name, leftPrec, rightPrec) =\n  let result = Keyword(name, leftPrec, rightPrec)\n  all |> MutMap.insert(name, result)\n  result\nlet prec = 0 \nfun currPrec = Some(prec)\nfun nextPrec =\n  set prec = prec + 1\n  Some(prec)\nlet basePrec = currPrec // the lowest precedence\nval _terminator = keyword(\";;\", basePrec, basePrec)\nval _class = keyword(\"class\", None, basePrec)\nlet semiPrec = nextPrec\nlet commaPrec = nextPrec\nval _semicolon = keyword(\";\", semiPrec, basePrec)\nval _comma = keyword(\",\", commaPrec, semiPrec)\nlet eqPrec = nextPrec\nlet ascPrec = nextPrec\nval _equal = keyword(\"=\", eqPrec, eqPrec)\nval _and = keyword(\"and\", None, currPrec)\nval _bar = keyword of \"|\", None, None\nval _thinArrow = keyword of \"->\", nextPrec, eqPrec\nval _colon = keyword(\":\", ascPrec, eqPrec)\nval _match = keyword(\"match\", nextPrec, currPrec)\nval _while = keyword of \"while\", nextPrec, currPrec\nval _for = keyword of \"for\", nextPrec, currPrec\nval _to = keyword of \"to\", None, None\nval _downto = keyword of \"downto\", None, None\nval _do = keyword of \"do\", None, None\nval _done = keyword of \"done\", None, None\nval _of = keyword of \"of\", None, None\nval _with = keyword(\"with\", None, currPrec)\nval _case = keyword(\"case\", None, currPrec)\nlet thenPrec = nextPrec\nval _if = keyword(\"if\", nextPrec, thenPrec)\nval _leftArrow = keyword of \"<-\", thenPrec, thenPrec\nval _then = keyword(\"then\", thenPrec, thenPrec)\nval _else = keyword(\"else\", thenPrec, thenPrec)\nval _let = keyword(\"let\", eqPrec, semiPrec)\nval _in = keyword(\"in\", thenPrec, thenPrec)\nval _true = keyword(\"true\", None, None)\nval _false = keyword(\"false\", None, None)\n// val _fatArrow = keyword of \"=>\", nextPrec, eqPrec\nval _as = keyword(\"as\", nextPrec, currPrec)\nval _fun = keyword(\"fun\", currPrec, _thinArrow.leftPrec)\nval _function = keyword(\"function\", currPrec, eqPrec)\nval _type = keyword(\"type\", currPrec, None)\nval _exception = keyword(\"exception\", currPrec, None)\nval _rec = keyword(\"rec\", currPrec, eqPrec)\nval _hash = keyword(\"#\", None, None)\nval maxKeywordPrec = prec\n\nlet precMap = makePrecMap of\n  maxKeywordPrec\n  \",\"\n  \"@\"\n  \":\"\n  \"|\"\n  \"&\"\n  \"=\"\n  \"/ \\\\\"\n  \"^\"\n  \"!\"\n  \"< >\"\n  \"+ -\"\n  \"* %\"\n  \"~\"\n  \"\" // prefix operators\n  \"\" // applications\n  \".\"\n\n// The largest precedence value of all operators.\nval periodPrec = precMap |> MutMap.get(\".\") |> Option.unsafe.get\n\nval _period = keyword of \".\", Some(periodPrec), Some(periodPrec)\n\nval maxOperatorPrec = periodPrec\nval appPrec = maxOperatorPrec - 1\nval prefixPrec = appPrec - 1\n\n// Get the precedence of a single character operator.\nfun charPrec(op) = precMap |> MutMap.get(op) |> Option.unsafe.get\n\nfun charPrecOpt(op) = precMap |> MutMap.get(op)\n\nval _asterisk = keyword of \"*\", charPrecOpt(\"*\"), charPrecOpt(\"*\")\nval _equalequal = keyword of \"==\", charPrecOpt(\"=\"), charPrecOpt(\"=\")\n\nlet bracketPrec = Some(maxOperatorPrec + 1)\n\nval _leftRound = keyword of \"(\", bracketPrec, basePrec\nval _rightRound = keyword of \")\", basePrec, None\nval _leftSquare = keyword of \"[\", bracketPrec, basePrec\nval _rightSquare = keyword of \"]\", basePrec, None\nval _leftCurly = keyword of \"{\", bracketPrec, basePrec\nval _rightCurly = keyword of \"}\", basePrec, None\nval _begin = keyword of \"begin\", bracketPrec, basePrec\nval _end = keyword of \"end\", basePrec, None\n\nlet builtinKeywords = new Set(all |> MutMap.keysIterator)\nfun extended = all\n  Iter.filtering of case [k, _] then builtinKeywords.has(k) is false\n  Iter.toArray()\n  MutMap.toMap()\n\npattern Letter = \"a\" ..= \"z\" | \"A\" ..= \"Z\"\n\nfun hasLetter(s) = s Iter.some((ch, _, _) => ch is Letter)\n\npattern FloatOperator = \"+.\" | \"-.\" | \"*.\" | \"/.\"\n\npattern RightAssociative = \"@\" | \"/\" | \",\" | \":\"\n\nfun opPrec(opStr) = if\n  opStr is FloatOperator then tuple of\n    Keywords.charPrec of opStr.at(0)\n    Keywords.charPrec of opStr.at(0)\n  opStr hasLetter() then tuple of\n    Keywords.maxKeywordPrec\n    Keywords.maxKeywordPrec\n  let lastChar = opStr.at(-1)\n  let rightPrec = Keywords.charPrec of lastChar\n  else tuple of\n    Keywords.charPrec of opStr.at(0)\n    (Keywords.charPrec of lastChar) +\n      if lastChar is RightAssociative then -1 else 0\n\nfun opPrecOpt(opStr) = if\n  opStr is \"\" then None\n  opStr is FloatOperator then Some of tuple of\n    Keywords.charPrec of opStr.at(0)\n    Keywords.charPrec of opStr.at(0)\n  opStr hasLetter() then Some of tuple of\n    Keywords.maxKeywordPrec\n    Keywords.maxKeywordPrec\n  let lastChar = opStr.at(-1)\n  Keywords.charPrecOpt(lastChar) is Some(rightPrec) and\n    Keywords.charPrecOpt(opStr.at(0)) is Some(leftPrec) then Some of tuple of\n      leftPrec\n      rightPrec + (if lastChar is RightAssociative then -1 else 0)\n  else None\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Lexer.mls",
    "content": "#config(liftDefns: Some(LiftDefns))\n\nimport \"../../Predef.mls\"\n\nopen Predef\n\nimport \"../../Char.mls\"\nimport \"../../Stack.mls\"\nimport \"../../StrOps.mls\"\nimport \"../../Option.mls\"\nimport \"../../Iter.mls\"\n\nimport \"./Token.mls\"\n\nopen Stack\nopen StrOps\nopen Option { Some, None}\nopen Token { LiteralKind, LineLookupTable }\n\ntype TokenType = Token.Token\ntype Opt[T] = Some[T] | None\n\nmodule Lexer with ...\n\nclass Location(start: Int, end: Int)\n\nclass Message(description: Str, location: Location)\n\nclass Report(messages: Stack[Message])\n\npattern IdentifierStart = Char.Letter | \"_\"\n\npattern IdentifierBody = Char.Letter | Char.Digit | \"_\" | \"'\"\n\npattern Operator =\n  \",\" | \";\" |\n  \"!\" | \"#\" | \"%\" | \"&\" | \"*\" | \"+\" | \"-\" | \"/\" | \":\" | \"<\" |\n  \"=\" | \">\" | \"?\" | \"@\" | \"\\\\\" | \"^\" | \"|\" | \"~\" | \".\"\n\npattern Bracket = \"(\" | \")\" | \"[\" | \"]\" | \"{\" | \"}\"\n\npattern IdentifierQuote = \"'\" | \"`\"\n\nfun makeLineLookupTable(text: Str): LineLookupTable =\n  let\n    i = 0\n    n = text.length\n    ns = mut []\n  while i < n do\n    let i' = text.indexOf(\"\\n\", i)\n    if i' == -1 then\n      set i = n\n      ns.push(n)\n    else\n      set i = i' + 1\n      ns.push(i')\n  LineLookupTable(ns)\n\nfun lex(str: Str, options) =\n  using LineLookupTable = makeLineLookupTable(str)\n  \n  fun char(idx: Int) = if idx < str.length\n    then (Some of str.charAt of idx) else None\n  \n  // Consume a sequence of characters that satisfy a predicate.\n  // The function returns the accumulated string and the following index.\n  fun take(pred: Str -> Bool, idx: Int, acc: Str): [Int, Str] =\n    while (char of idx) is Some(ch) and pred(ch) do\n      set\n        idx += 1\n        acc += ch\n    [idx, acc]\n  \n  fun whitespace(idx: Int): Int =\n    while char(idx) is Some(Char.Whitespace) do\n      set idx = idx + 1\n    idx\n  \n  fun digits(idx: Int, acc: Str) =\n    while char(idx) is Some(Char.Digit as ch) do\n      set idx = idx + 1\n      set acc = acc + ch\n    [idx, acc]\n  \n  fun hex(idx: Int, acc: Str) =\n    while char(idx) is Some(Char.Digit as ch) do\n      set idx = idx + 1\n      set acc = acc + ch\n    [idx, acc]\n  \n  fun identifier(idx: Int, acc: Str) =\n    while char(idx) is Some(IdentifierBody as ch) do\n      set idx = idx + 1\n      set acc = acc + ch\n    tuple of\n      idx\n      if acc is\n        \"true\" then Token.boolean(\"true\", idx)\n        \"false\" then Token.boolean(\"false\", idx)\n        else Token.identifier(acc, idx)\n  \n  fun operator(idx: Int, acc: Str) =\n    while char(idx) is Some(Operator as ch) do\n      set idx = idx + 1\n      set acc = acc + ch\n    [idx, Token.symbol(acc, idx)]\n    \n  fun comment(idx: Int) =\n    let start = idx\n    let content = \"\"\n    if char(idx) is\n      Some(\"/\") then\n        set idx = idx + 1\n        while char(idx) is Some(ch)\n          and ch !== \"\\n\" do\n            set idx = idx + 1\n            set content = content + ch\n        [idx, Token.comment(content, start, idx)]\n      Some(\"*\") then\n        let terminated = false\n        set idx = idx + 1\n        while terminated is false and char(idx) is\n          Some(\"*\") and char(idx + 1) is Some(\"/\") then\n            set idx = idx + 2\n            set terminated = true\n          Some(ch) then\n            set idx = idx + 1\n            set content = content + ch\n        if terminated then\n          [idx, Token.comment(content, start, idx)]\n        else\n          [idx, Token.error(start, idx)]\n      else operator(idx, \"/\")\n  \n  fun scanHexDigits(idx: Int, lim: Int, acc: Int, cnt: Int): [Int, Int, Int] =\n    if char(idx) is Some(Char.HexDigit as ch) and\n      cnt < lim then scanHexDigits(idx + 1, lim, acc * 16 + parseInt(ch, 16), cnt + 1)\n      else scanHexDigits(idx + 1, lim, acc, cnt + 1)\n    else [idx, acc, cnt]\n  \n  fun escape(idx: Int): [Int, Opt[Str]] = if char(idx) is\n    Some(\"n\") then [idx + 1, Some(\"\\n\")]\n    Some(\"r\") then [idx + 1, Some(\"\\r\")]\n    Some(\"t\") then [idx + 1, Some(\"\\t\")]\n    Some(\"0\") then [idx + 1, Some(\"\\u{0}\")]\n    Some(\"b\") then [idx + 1, Some(\"\\b\")]\n    Some(\"f\") then [idx + 1, Some(\"\\f\")]\n    Some(\"\\\"\") then [idx + 1, Some(\"\\\"\")]\n    Some(\"\\\\\") then [idx + 1, Some(\"\\\\\")]\n    Some(\"x\") then\n      if scanHexDigits(idx + 1, 2, 0, 0) is [idx, cp, cnt] then ...\n      // TODO: ensure that `cnt == 2`\n      tuple of idx, if cnt is 0 then None else Some of String.fromCodePoint(cp)\n    Some(\"u\") and\n      // Unicode code point escape: \"\\u{XXXXXX}\"\n      char(idx + 1) is Some(\"{\") then\n        if scanHexDigits(idx + 2, 6, 0, 0) is [idx, cp, cnt] then ...\n        // TODO: ensure that `1 <= cnt <= 6`\n        let idx = if char(idx) is Some(\"}\") then idx + 1 else\n          // TODO: report missing \"}\"\n          idx\n        tuple of idx, if cnt is 0 then None else Some of String.fromCodePoint(cp)\n      // Trandition Unicode range: \"\\uXXXX\"\n      else\n        if scanHexDigits(idx + 1, 4, 0, 0) is [idx, cp, cnt] then ...\n        // TODO: ensure that `cnt == 4`\n        tuple of idx, if cnt is 0 then None else Some of String.fromCodePoint(cp)\n    Some(ch) then [idx + 1, Some(ch)]\n    None then [idx, None]\n  \n  fun string(idx: Int): [Int, Token.Literal] =\n    let\n      startIndex = idx\n      content = \"\"\n      terminated = false\n    while terminated is false do\n      if char(idx) is\n        Some(\"\\\"\") do\n          set\n            terminated = true\n            idx += 1\n        Some(\"\\\\\") do\n          if escape(idx + 1) is [idx', chOpt] then ...\n          set idx = idx'\n          if chOpt is Some(ch) do set content += ch\n        Some(ch) do\n          set\n            idx += 1\n            content += ch\n        None do\n          // TODO report missing quote\n          set terminated = true\n    [idx, Token.string(content, startIndex, idx)]\n  \n  fun number(idx: Int, head: Str) = if\n    head is \"0\" and char(idx) is\n      None then [idx, Token.integer(\"0\", idx)]\n      Some(\"b\") and take(x => x is Char.BinDigit, idx + 1, \"\") is [idx', bs] then\n        [idx', Token.integer(\"0b\" ~ bs, idx)]\n      Some(\"o\") and take(x => x is Char.OctDigit, idx + 1, \"\") is [idx', os] then\n        [idx', Token.integer(\"0o\" ~ os, idx)]\n      Some(\"x\") and take(x => x is Char.HexDigit, idx + 1, \"\") is [idx', xs] then\n        [idx', Token.integer(\"0x\" ~ xs, idx)]\n      Some(\".\") and digits(idx + 1, \".\") is [idx', ds] then\n        [idx', Token.decimal(\"0.\" ~ ds, idx)]\n      Some(_) and digits(idx, head) is [idx', integer] then\n        [idx', Token.integer(integer, idx)]\n    digits(idx, head) is [idx', integer] and\n      char(idx') is Some(\".\") and digits(idx' + 1, \"\") is [idx'', fraction] then\n        [idx'', Token.decimal(integer ~ \".\" ~ fraction, idx)]\n      else [idx', Token.integer(integer, idx)]\n  \n  fun scan(idx: Int, acc: Stack[TokenType]): Stack[TokenType] =\n    fun go(idx: Int, tok: TokenType) = if\n      options.noWhitespace and tok is\n        Token.Comment then scan(idx, acc)\n        Token.Space then scan(idx, acc)\n      else scan(idx, tok :: acc)\n    \n    fun go_tup(tup: [Int, TokenType]) = go(tup.0, tup.1)\n    \n    if char(idx) is\n      None then reverse of acc\n      Some(ch) and ch is...\n      Char.Whitespace and whitespace(idx) is idx' then\n        go(idx', Token.space(idx, idx'))\n      \"\\\"\" then go_tup(string(idx + 1))\n      Bracket as b then go(idx + 1, Token.symbol(b, idx))\n      \"/\" then go_tup(comment(idx + 1))\n      Operator as ch then go_tup(operator(idx + 1, ch))\n      Char.Digit as ch then go_tup(number(idx + 1, ch))\n      IdentifierStart as ch then go_tup(identifier(idx + 1, ch))\n      IdentifierQuote as quote\n        and char(idx + 1) is Some(IdentifierStart as ch)\n        and identifier(idx + 2, quote + ch) is [idx', token] and\n          token is Token.Identifier(name, _) then\n            go(idx', Token.identifier(name, idx))\n          else go(idx + 1, Token.error(idx, idx + 1))\n      else\n        print(\"Unrecognized character: '\" ~ ch ~ \"'\")\n        go(idx + 1, Token.error(idx, idx + 1))\n  \n  scan(0, Nil)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/ParseRule.mls",
    "content": "import \"../../MutMap.mls\"\nimport \"../../Iter.mls\"\nimport \"../../Option.mls\"\nimport \"../../Stack.mls\"\nimport \"../../Predef.mls\"\nimport \"./Keywords.mls\"\nimport \"./Token.mls\"\nimport \"./Tree.mls\"\n\nopen Option { Some, None }\nopen Predef { check, tuple }\nopen Stack\n\nmodule ParseRule with ...\n\nabstract class Choice[A]\nmodule Choice with\n  \n  data class Keyword[A](keyword: Keywords.Keyword, rest: ParseRule[A]) extends Choice[A]\n  \n  data class Ref[A, B](\n      kind: Str,\n      process: (Tree, B) -> A,\n      outerPrec: Option[Int],\n      innerPrec: Option[Int],\n      rest: ParseRule[B]\n  ) extends Choice[A]\n  \n  data class End[A](value: A) extends Choice[A]\n  \n  // * An alternative route that branches off from the main railroad and\n  // * eventually connects back to the main railroad. For example, `foo`, `bar`,\n  // * and `baz` are choices represented by `init`. If `optional` is set to\n  // * `true`, an additional empty choice is added to `rule`, making it possible\n  // * to skip the entire `rule`.\n  // *                     _______ foo ______\n  // *                    /                  \\\n  // *                   /-------- bar -------\\\n  // *                  /                      \\\n  // * ----- start ----+---------- baz ---------+--- end ---------\n  data class Siding[A, B, C](\n      init: ParseRule[B],\n      optional: Bool,\n      rest: ParseRule[C],\n      process: (Option[B], C) -> A\n  ) extends Choice[A]\n  \n  let ensureChoices(xs, name) = xs\n    Iter.zippingWithIndex()\n    Iter.each of case [item, index] then\n      check(item is Choice, name + \": element [\" + index + \"] is not Choice\")\n  \n  // Shorthands for constructing rule choices.\n  fun keyword(keyword)(...choices) =\n    ensureChoices(choices, \"Choice.keyword\")\n    Keyword(keyword, rule(\"`\" + keyword.name + \"` keyword\", ...choices))\n  \n  let shouldHaveFunction(options, key: Str, defaultValue, callerName: Str) = if\n    let func = options.(key)\n    typeof(func) === \"function\" then func\n    func is undefined then defaultValue\n    else throw TypeError(callerName + \": `\" + key + \"` is not a string\")\n  \n  let shouldHaveStr(options, key: Str, defaultValue: Str, callerName: Str) = if\n    let value = options.(key)\n    value is Str then value\n    value is undefined then defaultValue\n    else throw TypeError(callerName + \": `\" + key + \"` is not a string\")\n  \n  let shouldHaveInt(options, key: Str, callerName: Str) = if\n    let value = options.(key)\n    value is Int then Some(value)\n    value is undefined then None\n    else throw TypeError(callerName + \": `\" + key + \"` is not an Int\")\n  \n  let shouldHaveBool(options, key: Str, defaultValue: Bool, callerName: Str) = if\n    let value = options.(key)\n    value is Bool then value\n    value is undefined then defaultValue\n    else throw TypeError(callerName + \": `\" + key + \"` is not a Boolean\")\n  \n  let shouldHaveRuleLike(options, key: Str, ruleName: Str, callerName: Str) = if\n    let choices = options.(key)\n    choices is ParseRule then choices\n    choices is Choice then rule(ruleName, choices)\n    choices is [..._] then\n      ensureChoices(choices, \"Choice.reference\")\n      rule(ruleName, ...choices)\n    choices is undefined then rule(ruleName)\n    else throw TypeError(callerName + \": `\" + key + \"` is neither a rule nor a choice\")\n  \n  fun reference(kind: Str)(fields: Object) =\n    let ruleName = fields shouldHaveStr(\"name\", \"unnamed\", \"Choice.reference\")\n    Ref of\n      kind\n      fields shouldHaveFunction(\"process\", tuple, \"Choice.reference\")\n      fields shouldHaveInt(\"outerPrec\", \"Choice.reference\")\n      fields shouldHaveInt(\"innerPrec\", \"Choice.reference\")\n      fields shouldHaveRuleLike(\"choices\", ruleName, \"Choice.reference\")\n  \n  val term = reference(\"term\")\n  val typeExpr = reference(\"type\")\n  val ident = reference(\"ident\")\n  val typeVar = reference(\"typevar\")\n  \n  fun optional(init, rest) =\n    check(init is ParseRule, \"Choice.optional: init is not ParseRule\")\n    check(rest is ParseRule, \"Choice.optional: rest is not ParseRule\")\n    Siding(init, true, rest, tuple)\n  \n  fun siding(fields) =\n    let optional = fields shouldHaveBool(\"optional\", false, \"Choice.siding\")\n    let initName = fields shouldHaveStr(\"initName\", \"unnamed\", \"Choice.siding\")\n    let restName = fields shouldHaveStr(\"restName\", \"unnamed\", \"Choice.siding\")\n    let init = fields shouldHaveRuleLike(\"init\", initName, \"Choice.siding\")\n    let rest = fields shouldHaveRuleLike(\"rest\", restName, \"Choice.siding\")\n    let defaultProcess = if optional then tuple\n      else (initRes, restRes) => if initRes is Some(initRes) then [initRes, restRes]\n    let process = fields shouldHaveFunction(\"process\", defaultProcess, \"Choice.siding\")\n    Siding of init, optional, rest, process\n  \n  fun end(value) = End(value)\n  \n  fun map[A, B](choice: Choice[A], op: A -> B): Choice[B] = if choice is\n    Keyword(keyword, rest) then Keyword(keyword, rest.map(op))\n    Ref(kind, process, outerPrec, innerPrec, rest) then\n      Ref(kind, (x, y) => op(process(x, y)), outerPrec, innerPrec, rest)\n    Siding(init, optional, rest, process) then\n      Siding(init, optional, rest, (x, y) => op(process(x, y)))\n    End(value) then End(op(value))\n\ndata class Lazy[out A](init: () -> A) with\n  mut val cached: Option[A] = None\n  fun reset() = set cached = None\n  fun get() = if cached is\n    Some(v) then v\n    else\n      let v = init()\n      set cached = Some(v)\n      v\n\nfun lazy(init) = new Lazy of init\n\n//  ____                     ____        _\n// |  _ \\ __ _ _ __ ___  ___|  _ \\ _   _| | ___\n// | |_) / _` | '__/ __|/ _ \\ |_) | | | | |/ _ \\\n// |  __/ (_| | |  \\__ \\  __/  _ <| |_| | |  __/\n// |_|   \\__,_|_|  |___/\\___|_| \\_\\\\__,_|_|\\___|\n//\n// =============================================\n\ndata class ParseRule[A](name: Str, mut val choices: Stack[Choice[A]]) with\n  open Choice { Keyword, Ref, End, Siding }\n  \n  fun map[B](op: A -> B) =\n    new mut ParseRule of name, choices\n      Iter.fromStack()\n      Iter.mapping of choice => choice Choice.map(op)\n      Iter.toStack()\n  \n  fun andThen[B, C](rest: ParseRule[B], process: (A, B) -> C) =\n    fun go(rule: ParseRule[B]) = new ParseRule of rule.name, rule.choices\n      Iter.fromStack()\n      Iter.mapping of case\n        Keyword(keyword, rest') then [Keyword(keyword, go(rest'))]\n        Ref(kind, process, outerPrec, innerPrec, rest') then\n          let process' = (lhs, rhsInnerResult) => if\n            rhsInnerResult is [rhs, innerResult] then\n              [process(lhs, rhs), innerResult]\n            do check(false, \"illgeal result from inner\")\n          [Ref(kind, process', outerPrec, innerPrec, go(rest'))]\n        End(value) then rest.choices\n          Iter.fromStack()\n          Iter.mapping of choice => choice Choice.map(result => [value, result])\n        Siding(rule, optional, rest', process) then\n          let process' = (initRes, restRes) => if\n            restRes is [restRes', innerRes] then [process(initRes, restRes'), innerRes]\n            do check(false, \"illegal result from inner\")\n          [Siding(rule, optional, go(rest'), process')]\n      Iter.flattening()\n      Iter.toStack()\n    go(this).map of res => process(res.0, res.1)\n  \n  let _endChoice = lazy of () => choices\n    Iter.fromStack()\n    Iter.firstDefined of case\n      End(value) then Some(value)\n      Siding(init, optional, rest, process) and\n        optional and rest.endChoice is Some(restRes) then\n          // It's actually ambiguous here.\n          process(None, restRes)\n        init.endChoice is Some(initRes) and\n          rest.endChoice is Some(restRes) then\n            process(Some(initRes), restRes)\n      else None\n  \n  // Collect the first end choice in this rule.\n  fun endChoice = _endChoice.get()\n  \n  let _keywordChoices = lazy of () => choices\n    Iter.fromStack()\n    Iter.mapping of case\n      Keyword(keyword, rest) then [[keyword.name, rest]]\n      Siding(init, optional, rest, process) then init.keywordChoices\n        Iter.mapping of case [keyword, rule] then\n          [keyword, rule.map(Some).andThen(rest, process)]\n        Iter.appended of\n          if optional then rest.keywordChoices\n            Iter.mapping of case [keyword, rule] then\n              [keyword, rule.map(res => process(None, res))]\n          else []\n        Iter.toArray()\n      else []\n    Iter.flattening()\n    Iter.toArray()\n    MutMap.toMap()\n  \n  // Collect all keyword choices in this rule.\n  fun keywordChoices = _keywordChoices.get()\n  \n  let _refChoice = lazy of () => choices\n    Iter.fromStack()\n    Iter.firstDefined of case\n      Ref as ref then Some(ref)\n      Siding(init, optional, rest, process) and\n        init.refChoice is Some(Ref(k, process', op, ip, rest')) then\n          let process''(exprRes, pairRes) =\n            if pairRes is [restRes', restRes] then\n              process(process'(exprRes, restRes'), restRes)\n          let rest'' = rest'.andThen(rest, tuple)\n          Some of Ref(k, process'', op, ip, rest'')\n        optional and rest.refChoice is Some(Ref(k, process', op, ip, rest')) then\n          let process''(exprRes, restRes) =\n            process(None, process'(exprRes, restRes))\n          Some of Ref(k, process'', op, ip, rest')\n      else None\n  \n  fun refChoice = _refChoice.get()\n  \n  fun extendChoices(newChoices: Stack[Choice[A]]) =\n    set choices = choices ::: newChoices\n    _endChoice.reset()\n    _keywordChoices.reset()\n    _refChoice.reset()\n    this\n  \n  // Display parse rules as a tree in a BNF-like format.\n  fun display =\n    /// Display a single `Choice`.\n    fun displayChoice[A](choice: Choice[A]) = if choice is\n      Choice.Keyword(keyword, rest) then\n        \"\\\"\" + keyword.name + \"\\\"\" + tail(rest).1\n      Choice.Ref(kind, _, _, _, rest) then\n        \"<\" + kind + \">\" + tail(rest).1\n      Choice.Siding(init, opt, rest, _) then\n        let init' = go(init, false).1\n        (if opt then \"[\" + init' + \"]\" else \"(\" + init' + \")\") + tail(rest).1\n      Choice.End then \"\"\n      other then \"<unknown:\" + other + \">\"\n    \n    // Display the remaining list of choices.\n    // ++ fun tail(rest) = if rest is ParseRule(_, choices) and\n    fun tail(rest) = if rest is ParseRule and // ---\n      let choices = rest.choices // ---\n      choices is Choice.End :: Nil then [\"\", \"\"]\n      go(rest, false) is [name, line] and\n        choices is _ :: _ :: _ and\n          choices Iter.fromStack() Iter.some(c => c is Choice.End) then\n            [name, \" [\" + line + \"]\"]\n          else [name, \" (\" + line + \")\"]\n        else [name, \" \" + line]\n    \n    fun go(rule, top) =\n      let lines = rule.choices\n        Iter.fromStack()\n        Iter.filtering of case\n          Choice.End then false\n          else true\n        Iter.mapping of displayChoice\n        Iter.toArray()\n      tuple of\n        rule.name\n        if\n          lines is [] then \"ε\"\n          lines is [line] then line\n          top then \"\\n  | \" + lines.join(\"\\n  | \")\n          else lines.join(\" | \")\n    \n    if go(this, true) is [name, line] then \"<\" + name + \"> ::= \" + line\n\n// Shorthands for constructing parse rules.\n// Automatically adds an end choice to the rule if no choices are provided.\nfun rule(name, ...choices) = new ParseRule of\n  name\n  if choices.length == 0 then\n    Choice.end(()) :: Nil\n  else\n    choices Iter.toStack()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/ParseRuleVisualizer.mls",
    "content": "import \"../../Predef.mls\"\nimport \"../../Stack.mls\"\nimport \"../../Iter.mls\"\nimport \"../../Option.mls\"\nimport \"../../TreeTracer.mls\"\nimport \"../../XML.mls\"\nimport \"../../MutMap.mls\"\n\nimport \"./ParseRule.mls\"\nimport \"./Rules.mls\"\nimport \"./Parser.mls\"\n\nopen Predef\nopen Stack\nopen Option\nopen ParseRule { Choice }\nopen Rules { syntaxKinds }\nopen TreeTracer\nopen XML { html, tag, style }\n\nmodule ParseRuleVisualizer with ...\n\nval tracer = new TreeTracer.TreeTracer()\n\nlet defaultKinds = tuple of \"type\", \"term\", \"typevar\", \"ident\"\n\nlet renderedKinds = new Set of defaultKinds\n\nfun reset() =\n  set renderedKinds = new Set of defaultKinds\n\n// * `rr` is the railroad library.\nfun render[T](rr, title: Str, rule: ParseRule.ParseRule[T]) =\n  let helperRules = mut []\n  let referencedKinds = new Set()\n  let renderCache = new Map()\n  fun sequence(lhs, rhsOpt) =\n    if rhsOpt is\n      Some(rhs) then rr.Sequence(lhs, rhs)\n      None then lhs\n  fun diagram(choicesOpt) =\n    rr.Diagram of if choicesOpt is Some(choices) then choices else []\n  fun renderChoice(parentRule, choice) = if choice is\n    Choice.End then\n      tracer.print of \"found Choice.End\"\n      None\n    Choice.Keyword(keyword, rest) then\n      tracer.print of \"found Choice.Keyword\"\n      Some of rr.Terminal(keyword.name) sequence(renderRule(rest))\n    Choice.Siding(rule, optional, rest, _) then\n      tracer.print of \"found Choice.Siding\"\n      Some of if renderRule(rule) is\n        let latterPart = renderRule(rest)\n        Some(optionalPart) and\n          optional then rr.Optional(optionalPart) sequence(latterPart)\n          else optionalPart sequence(latterPart)\n        None then latterPart\n    Choice.Ref(kind, _, outerPrec, innerPrec, rest) then\n      tracer.print of \"found Choice.Ref to \" + kind\n      if renderedKinds.has(kind) is false do\n        referencedKinds.add of kind\n      Some of rr.NonTerminal(kind, href: \"#\" + kind)\n        sequence(renderRule(rest))\n  fun renderRule(rule: ParseRule.ParseRule[T]) = tracer.trace of\n    \"renderRule <<< \" + rule.name\n    result => \"renderRule >>> \"\n    () => ...\n    let\n      rest = rule.choices\n      optional = false\n      nodes = mut []\n    while rest is head :: tail do\n      if renderChoice(rule, head) is\n        Some(node) do nodes.push of node\n        None do set optional = true\n      set rest = tail\n    tracer.print of \"nodes: \", nodes.length.toString()\n    if\n      nodes.length is 0 then None\n      let choice = rr.Choice(0, ...nodes)\n      optional is true then Some(rr.Optional(choice))\n      else Some(choice)\n  // Iteratively render the rule and its dependencies.\n  let diagrams = mut [[title, diagram of renderRule(rule)]]\n  while referencedKinds.size > 0 do\n    let currentKinds = referencedKinds\n    set renderedKinds = renderedKinds.union of currentKinds\n    referencedKinds = new Set()\n    diagrams.push of ...currentKinds\n      Iter.mapping of kind => \n        let theRule = syntaxKinds |> MutMap.get(kind) |> Option.unsafe.get\n        [kind, diagram of renderRule(theRule)]\n      Iter.toArray()\n  diagrams\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Parser.mls",
    "content": "import \"../../Predef.mls\"\nimport \"../../Option.mls\"\nimport \"../../Stack.mls\"\nimport \"../../TreeTracer.mls\"\nimport \"../../Iter.mls\"\nimport \"../../MutMap.mls\"\n\nimport \"./Lexer.mls\"\nimport \"./Extension.mls\"\nimport \"./Token.mls\"\nimport \"./TokenHelpers.mls\"\nimport \"./Keywords.mls\"\nimport \"./Tree.mls\"\nimport \"./Rules.mls\"\nimport \"./ParseRule.mls\"\n\nopen Predef\nopen Option\nopen Stack\nopen ParseRule { Choice }\nopen Choice { Ref }\nopen Keywords { opPrecOpt }\nopen Rules { termRule, typeRule, declRule, syntaxKinds }\n\ntype Opt[A] = Some[A] | None\ntype TreeT = Tree\ntype StackT[A] = Stack.Cons[A] | Stack.Nil\n\nmodule Parser with ...\n\nval tracer = new TreeTracer.TreeTracer\n\nlet termOptions =\n  kind: \"term\", rule: termRule\n  allowOperators: true, allowLiterals: true\nlet typeOptions =\n  kind: \"type\", rule: typeRule\n  allowOperators: false, allowLiterals: true, \n\nfun parse(tokens) =\n  let counter = 0\n  \n  fun consume =\n    if tokens is head :: tail then\n      tracer.print of \"consume: `\" + Token.summary(head) + \"` at #\" + counter\n      set tokens = tail\n      set counter = counter + 1\n    else\n      tracer.print of \"consume: the end of input\"\n  \n  fun parseKind(kind: Str, prec: Int): TreeT = if\n    kind is \"type\" then expr(prec, typeOptions)\n    kind is \"term\" then expr(prec, termOptions)\n    // built-in kinds: plain identifiers\n    kind is \"ident\" then if tokens is\n      Token.Identifier(name, false) :: _ and Keywords.all |> MutMap.get(name) is None then\n        consume\n        Tree.Ident(name, false)\n      token :: _ then Tree.error(\"expect an identifier but found \" + token)\n      Nil then Tree.error(\"expect an identifier but found the end of input\")\n    // built-in kinds: type variables\n    kind is \"typevar\" then if tokens is\n      Token.Identifier(name, false) :: _ and name.at(0) is \"'\" then\n        consume\n        Tree.Ident(name, false)\n      token :: _ then Tree.error(\"expect a type variable but found \" + token)\n      Nil then Tree.error(\"expect a type variable but found the end of input\")\n    // * other rule-based kinds\n    syntaxKinds |> MutMap.get(kind) is Some(rule) then\n      let tree = parseRule(prec, rule)\n      if rule.refChoice is Some(Ref(kind', process, None, None, rest)) and kind == kind' do\n        let shouldParse = true\n        while shouldParse do\n          let tree' = parseRule(prec, rest)\n          if tree' Tree.nonEmpty() then\n            tracer.print of \">>> \" + kind + \"Cont \" + prec + \" \" + tree Tree.summary() + \" <<<\", source.line\n            set tree = process(tree, tree')\n          else\n            set shouldParse = false\n      tree\n    else throw Error(\"Unknown syntax kind: \\\"\" + kind + \"\\\"\")\n  \n  fun parseRule(prec: Int, rule) = tracer.trace of\n    \"parsing rule \\\"\" + rule.name + \"\\\" with precedence \" + prec\n    result => \"parsed rule \\\"\" + rule.name + \"\\\": \" + result Tree.summary()\n    () => if tokens is...\n    Token.Identifier(name, _) :: _ and\n      do tracer.print of \"found an identifier \\\"\" + name + \"\\\"\", source.line\n      Keywords.all |> MutMap.get(name) is Some(keyword) and\n        do tracer.print of keyword.toString(), source.line\n        do tracer.print of \"keyword choices: \", rule.keywordChoices\n          Iter.mapping of case [k, v] then \"`\" + k + \"`\"\n          Iter.joined(\", \")\n        rule.keywordChoices |> MutMap.get(name) is\n          Some(rest) then\n            tracer.print of \"found a rule starting with `\" + name + \"`\", source.line\n            tracer.print of \"the rest of the rule: \" + rest.display, source.line\n            consume\n            parseRule(0, rest)\n          do tracer.print of \"\\\"\" + name + \"\\\" is not a keyword\", source.line\n    other :: _ and\n      do tracer.print of \"the current rule is \" + rule.display\n      rule.refChoice is Some(Ref(kind, process, outerPrec, innerPrec, rest)) and\n        do tracer.print of \"try to parse kind \\\"\" + kind + \"\\\" at \" + TokenHelpers.preview(tokens), source.line\n        let outerPrec' = outerPrec Option.getOrElse(Keywords.maxKeywordPrec)\n        let innerPrec' = innerPrec Option.getOrElse(prec)\n        outerPrec' > prec and\n          let acc = parseKind(kind, prec)\n          acc Tree.nonEmptyError() and parseRule(prec, rest) is\n            Tree.Error(_, message) as tree then\n              do tracer.print of \"cannot parse due to error: \" + message, source.line\n              tree\n            tree then\n              tracer.print of \"acc: \" + acc Tree.summary(), source.line\n              tracer.print of \"parsed from rest rule: \" + tree Tree.summary(), source.line\n              process(acc, tree)\n          do tracer.print of \"cannot parse more\", source.line\n          rule.endChoice is Some(value) then\n            tracer.print of \"found end choice\", source.line\n            value\n          do tracer.print of \"no end choice\", source.line\n          else acc\n        do tracer.print of \"did not parse kind \\\"\" + kind + \"\\\" because of the precedence\", source.line\n      do tracer.print of \"no reference choice\", source.line\n      rule.endChoice is Some(value) then\n        tracer.print of \"found end choice\", source.line\n        value\n      do tracer.print of \"no end choice\", source.line\n      else\n        consume\n        Tree.error(\"unexpected token \" + render(other)) // TODO: Pretty-print the token.\n    Nil and rule.endChoice is\n      Some(value) then value\n      None then\n        tracer.print of \"no end choice but found the end of input\", source.line\n        Tree.error(\"unexpected end of input\")\n  \n  fun expr(prec: Int, options): TreeT = tracer.trace of\n    options.kind + \" <<< \" + prec + \" \" + TokenHelpers.preview(tokens)\n    result => options.kind + \" >>> \" + result Tree.summary()\n    () => if tokens is ...\n    Token.Identifier(name, symbolic) :: _ and Keywords.all |> MutMap.get(name) is\n      // * the keyword case\n      Some(keyword) and options.rule.keywordChoices |> MutMap.get(name) is\n        Some(rule) and\n          keyword.leftPrecOrMin > prec then\n            consume\n            parseRule(keyword.rightPrecOrMax, rule) exprCont(prec, options)\n          else\n            tracer.print of \"the left precedence of \\\"\" + name + \"\\\" is less\", source.line\n            Tree.empty\n        None then\n          tracer.print(\"no rule starting with \" + name, source.line)\n          Tree.empty\n      // * the non-keyword case\n      None then\n        if not options.allowOperators and symbolic then\n          Tree.error(\"symbolic identifiers are disallowed in kind \\\"\" + options.kind + \"\\\"\")\n        else\n          consume\n          Tree.Ident(name, symbolic) exprCont(prec, options)\n    // * the literal case\n    Token.Literal(kind, literal) :: _ and options.allowLiterals then\n      consume\n      Tree.Literal(kind, literal) exprCont(prec, options)\n    // * other cases\n    token :: _ then Tree.error(\"unrecognized token: \" + token)\n    Nil then Tree.error(\"unexpected end of input\")\n  \n  fun exprCont(acc: TreeT, prec: Int, options) = if tokens is\n    let infix = options.rule.refChoice Option.flatMap of case\n      Ref(kind, process, None, None, rest) and kind == options.kind then\n        { process: process, rule: rest }\n      else throw Error(\"Kind \" + options.kind + \" does not have infix rules\")\n    do tracer.print of \">>> \" + options.kind + \"Cont \" + prec + \" \" + acc Tree.summary() + \" <<<\", source.line\n    // * the case of infix keyword rules\n    do tracer.print of \"check keyword \" + TokenHelpers.preview(tokens), source.line\n    Token.Identifier(name, _) :: _ and Keywords.all |> MutMap.get(name) is Some(keyword) and\n      do tracer.print of \"found a keyword: \" + name, source.line\n      infix.rule.keywordChoices |> MutMap.get(name) is Some(rule) and\n        do tracer.print of \"keyword `\" + name + \"` is found in infix rules\", source.line\n        keyword.leftPrecOrMin > prec and rule.refChoice is\n          Some(Ref(kind, process, outerPrec, innerPrec, rest)) and\n            do tracer.print of \"try to parse kind \\\"\" + kind + \"\\\" at \" + TokenHelpers.preview(tokens), source.line\n            let outerPrec' = outerPrec Option.getOrElse(Keywords.maxOperatorPrec)\n            let innerPrec' = innerPrec Option.getOrElse(outerPrec')\n            outerPrec' > prec then\n              consume\n              let rhs = parseKind(kind, keyword.rightPrecOrMin)\n              let restRes = parseRule(innerPrec', rest)\n              infix.process(acc, process(rhs, restRes)) exprCont(prec, options)\n          None then acc\n      do tracer.print of \"keyword `\" + name + \"` does not have infix rules\", source.line\n    // * the case of infix operators (non-keywords)\n    Token.Identifier(name, true) :: _ and Keywords.all |> MutMap.get(name) is None and options.allowOperators and\n      do tracer.print of \"found an operator \\\"\" + name + \"\\\"\", source.line\n      opPrecOpt(name) is Some([leftPrec, rightPrec]) and\n        do tracer.print of \"leftPrec = \" + leftPrec + \"; rightPrec = \" + rightPrec, source.line\n        leftPrec > prec then\n          consume\n          let op = Tree.Ident(name, true)\n          let rhs = expr(rightPrec, termOptions)\n          Tree.App(op, acc :: rhs :: Nil) exprCont(prec, options)\n        else\n          acc\n    // * the case of application\n    do tracer.print of \"not a keyword\", source.line\n    token :: _ and infix.rule.refChoice is\n      Some(Ref(kind, process, outerPrec, innerPrec, rest)) and\n        do tracer.print of \"found reference to \" + kind + \" with outerPrec = \" + outerPrec, source.line\n        let outerPrec' = outerPrec Option.getOrElse(Keywords.maxOperatorPrec)\n        let innerPrec' = innerPrec Option.getOrElse(outerPrec')\n        outerPrec' > prec and\n          parseKind(kind, innerPrec Option.getOrElse(outerPrec')) is\n            Tree.Empty then\n              do tracer.print of \"nothing was parsed\", source.line\n              acc\n            Tree.Error then\n              do tracer.print of \"cannot parse more\", source.line\n              acc\n            rhs then\n              do tracer.print of \"parsed \" + rhs Tree.summary(), source.line\n              let restRes = parseRule(innerPrec', rest)\n              infix.process(acc, process(rhs, restRes)) exprCont(prec, options)\n        do tracer.print of \"the outer precedence is less than \" + prec, source.line\n        else acc\n      None then\n        tracer.print of \"cannot consume \" + token, source.line\n        acc\n    Nil then acc\n  \n  fun handleDirective(tree: TreeT, acc: TreeT) = if tree is\n    // Call the corresponding handler for the directive.\n    Tree.Define(Tree.DefineKind.Directive, [name, body] :: Nil) as tree and name is\n      Tree.Ident(\"newKeyword\", _) then\n        Extension.extendKeyword(body)\n        modCont(acc)\n      Tree.Ident(\"newCategory\", _) then\n        Extension.newCategory(body)\n        modCont(acc)\n      Tree.Ident(\"extendCategory\", _) then\n        Extension.extendCategory(body)\n        modCont(acc)\n      else\n        modCont(tree :: acc)\n    tree then modCont(tree :: acc)\n  \n  fun mod(acc: StackT[TreeT]) = if tokens is\n    do tracer.print of \">>>>>> mod <<<<<<\", source.line\n    Token.Identifier(\";;\", _) :: _ then\n      consume\n      mod\n    Token.Identifier(name, _) :: _ and\n      Keywords.all |> MutMap.get(name) is Some(keyword) and\n        // First, try if the keyword is the prefix of the term.\n        termRule.keywordChoices |> MutMap.get(name) is Some(rule) then\n          let tree = expr(0, termOptions)\n          if tree is Tree.LetIn(bindings, Tree.Empty) then\n            // If the body is empty, then this is a let-definition.\n            modCont of Tree.Define(Tree.DefineKind.Let(false), bindings) :: acc\n          else\n            modCont of tree :: acc\n        // Then try to parse according to the rules of the definition.\n        declRule.keywordChoices |> MutMap.get(name) is Some(rule) then\n          consume\n          parseRule(0, rule) handleDirective(acc)\n    _ :: _ then modCont of expr(0, termOptions) :: acc\n    Nil then acc reverse()\n  \n  fun modCont(acc: StackT[TreeT]) = if tokens is\n    do tracer.print of \">>>>>> modCont <<<<<< \" + TokenHelpers.preview(tokens), source.line\n    Token.Identifier(\";;\", _) :: _ then consume; acc mod()\n    _ :: _ then parseRule(0, declRule) handleDirective(acc)\n    Nil then acc reverse()\n  \n  let tree = tracer.trace of\n    \"module <<< \"\n    result => \"module >>> \" + result Tree.summary()\n    () => mod(Nil)\n  \n  if tokens is\n    token :: _ then\n      let message = \"expect EOF instead of \" + token\n      tracer.print of message, source.line\n      tree Tree.Error(message)\n    Nil then tree\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/PrattParsing.mls",
    "content": "import \"../../Predef.mls\"\nimport \"../../Stack.mls\"\nimport \"../../Option.mls\"\nimport \"../../Iter.mls\"\nimport \"../../StrOps.mls\"\nimport \"./Lexer.mls\"\nimport \"./Token.mls\"\nimport \"./Expr.mls\"\n\nopen Stack\nopen Option { Some, None }\nopen Token { Round, LiteralKind }\n\ntype Stack[A] = Cons[A] | Nil\n\nmodule PrattParsing with ...\n\nfun parse(tokens) =\n  fun advance = if tokens is\n    Token.Space :: tail then\n      set tokens = tail\n      advance\n    head :: tail then\n      set tokens = tail\n      Some(head)\n    Nil then None\n  \n  let peek = advance\n  \n  fun consume = set peek = advance\n  \n  fun require(result: Expr.Expr, expected) = if peek is\n    Some(actual) and\n      expected Token.same(actual) then\n        consume\n        result\n      else result Expr.withErr of StrOps.concat of\n        \"Expected token \"\n        expected Token.summary()\n        \", but found \"\n        actual Token.summary() \n    None then result Expr.withErr of StrOps.concat of\n      \"Expected token \"\n      expected Token.summary()\n      \", but found end of input\"\n  \n  fun expr(prec: Int): Expr.Expr = if peek is\n    Some of\n      Token.Literal(LiteralKind.Integer, literal) then\n        consume\n        Expr.Lit(parseInt(literal, 10)) exprCont(prec)\n      Token.Identifier(name, false) then\n        consume\n        Expr.Var(name) exprCont(prec)\n      Token.Identifier(\"(\", true) then\n        consume\n        expr(0) require(Token.Identifier(\")\", true)) exprCont(prec)\n      token then Expr.justErr of \"Unexpected token \" + token Token.summary()\n    None then Expr.justErr of \"Unexpected end of input\"\n  \n  fun exprCont(acc: Expr.Expr, prec: Int): Expr.Expr =\n    if peek is Some(Token.Identifier(op, true))\n      and op !== \")\" // * this is important\n      and Expr.opPrec(op) is [leftPrec, rightPrec]\n      and leftPrec > prec then\n        consume\n        let right = expr of rightPrec\n        Expr.Inf(op, acc, right) exprCont(prec)\n    else acc\n  \n  let result = expr(0)\n  if peek is\n    Some(token) then result Expr.withErr of\n      \"Expect end of input, but found \" + token Token.summary()\n    None then result\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/RecursiveDescent.mls",
    "content": "import \"../../Predef.mls\"\nimport \"../../Stack.mls\"\nimport \"../../Option.mls\"\nimport \"../../Iter.mls\"\nimport \"./Token.mls\"\nimport \"./BasicExpr.mls\"\n\nopen Predef { mkStr }\nopen Stack\nopen Option { Some, None }\nopen Token { Round, LiteralKind }\nopen BasicExpr { Expr }\n\ntype StackT[A] = Cons[A] | Nil\n\nmodule RecursiveDescent with ...\n\nfun parse(tokens) =\n  fun advance = if tokens is\n    Token.Space :: tail then\n      set tokens = tail\n      advance\n    head :: tail then\n      set tokens = tail\n      Some(head)\n    Nil then None\n  \n  let peek = advance\n  \n  fun consume = set peek = advance\n  \n  fun require(result: Expr, expected) = if peek is\n    Some(actual) and\n      expected Token.same(actual) then\n        consume\n        result\n      else result BasicExpr.withErr of mkStr of\n        \"Expected token \"\n        expected Token.summary()\n        \", but found \"\n        actual Token.summary()\n    None then result BasicExpr.withErr of mkStr of\n      \"Expected token \"\n      expected Token.summary()\n      \", but found end of input\"\n  \n  fun atom: Expr = if peek is\n    Some of\n      Token.Literal(LiteralKind.Integer, literal) then\n        consume\n        BasicExpr.Lit(parseInt(literal, 10))\n      Token.Identifier(\"(\", true) then\n        consume\n        expr require of Token.Identifier(\")\", true)\n      Token.Identifier(name, false) then\n        consume\n        BasicExpr.Var(name)\n      token then BasicExpr.justErr of \"Unexpected token \" + token Token.summary()\n    None then BasicExpr.justErr of \"Unexpected end of input\"\n  \n  fun expr: Expr =\n    let leftmost = product\n    addSeq\n      Iter.fromStack()\n      Iter.folded of leftmost, BasicExpr.Add\n  \n  fun addSeq: StackT[Expr] = if peek is\n    Some(Token.Identifier(\"+\", _)) then\n      consume\n      product :: addSeq\n    else Nil\n  \n  fun product: Expr =\n    let leftmost = atom\n    mulSeq\n      Iter.fromStack()\n      Iter.folded of leftmost, BasicExpr.Mul\n  \n  fun mulSeq: StackT[Expr] = if peek is\n    Some(Token.Identifier(\"*\", _)) then\n      consume\n      atom :: mulSeq\n    else Nil\n  \n  let result = expr\n  if peek is\n    Some(token) then result BasicExpr.withErr of\n      \"Expect end of input, but found \" + token Token.summary()\n    None then result\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Rules.mls",
    "content": "import \"../../Predef.mls\"\nimport \"../../Option.mls\"\nimport \"../../Stack.mls\"\nimport \"../../MutMap.mls\"\nimport \"../../Iter.mls\"\nimport \"./Token.mls\"\nimport \"./Keywords.mls\"\nimport \"./Tree.mls\"\nimport \"./ParseRule.mls\"\n\nopen Predef\nopen Option\nopen Stack\nopen ParseRule { Choice, rule }\nopen Token { Curly, Square, Round }\n\nopen Choice { keyword, reference, term, typeExpr, ident, typeVar, end }\n\ntype Opt[A] = Some[A] | None\n\nmodule Rules with ...\n\nval syntaxKinds = MutMap.empty\n\nval extendedKinds = new Set()\n\nfun getRuleByKind(kind: Str) = syntaxKinds |> MutMap.get(kind) |> Option.unsafe.get\n\nfun define(name: Str)(...choices) = syntaxKinds |> MutMap.updateWith(name) of case\n  None       then Some(rule(name, ...choices))\n  Some(rule) then Some(rule.extendChoices(choices Iter.toStack()))\n\nfun idFirst(value, _) = value\nfun idSecond(_, value) = value\nfun someFirst(value, _) = Some(value)\nfun listFirst(value, _) = value :: Nil\nfun listLike(fields) =\n  let mkTail = if fields.(\"sep\") is undefined then id else keyword(fields.(\"sep\"))\n  reference(fields.head) of\n    process: Cons, name: \"the first \" + fields.name\n    choices: tuple of end(Nil), mkTail of reference(fields.tail) of\n      process: idFirst, name: \"more \" + fields.name + \"s\"\n\ndefine(\"let-bindings\") of term of\n  process: (lhs, rhsBindings) => if rhsBindings is [rhs, bindings] then\n    Tree.Infix(Keywords._equal, lhs, rhs) :: bindings\n  name: \"left-hand side\"\n  choices: tuple of keyword(Keywords._equal) of term of\n    name: \"right-hand side\"\n    choices: tuple of\n      end of Nil\n      keyword(Keywords._and) of reference(\"let-bindings\") of\n        process: idFirst, name: \"let-bindings tail\"\n\nfun makeLetBindings(hasInClause: Bool) =\n  let intro = \"let binding: \"\n  keyword(Keywords._let) of Choice.siding of\n    optional: true\n    init: keyword(Keywords._rec)()\n    rest: reference(\"let-bindings\") of\n      process: Tree.LetIn, name: \"let-bindings\"\n      choices:\n        if hasInClause then tuple of\n          keyword(Keywords._in) of term of\n            process: someFirst, name: intro + \"body\"\n          end of None\n        else tuple of end of None\n    process: idSecond\n\nlet letExpression = makeLetBindings(true)\n\ndefine(\"simple-matching\") of term of\n  process: (lhs, rhsTail) => if rhsTail is\n    [rhs, tail] then Tree.Infix(Keywords._thinArrow, lhs, rhs) :: tail\n    // TODO: Better error handling?\n    \n  name: \"case body\"\n  choices: tuple of keyword(Keywords._thinArrow) of term of\n    name: \"rhs\"\n    choices: tuple of\n      end of Nil\n      keyword(Keywords._bar) of reference(\"simple-matching\") of\n        process: idFirst, name: \"simple-matching tail\"\n\ndefine(\"pattern-list\") of term of\n  process: (head, tail) => head :: tail\n  name: \"pattern\"\n  choices: tuple of reference(\"pattern-list\") of\n    process: idFirst, name: \"pattern list tail\"\n\ndefine(\"multiple-matching\") of reference(\"pattern-list\") of\n  process: Tree.infix of Keywords._thinArrow\n  name: \"list of patterns\"\n  choices: tuple of keyword(Keywords._thinArrow) of term of\n    process: idFirst, name: \"the right-hand side of the arrow\"\n    choices: tuple of\n      end of Nil\n      keyword(Keywords._bar) of reference(\"multiple-matching\") of\n        process: idFirst, name: \"multiple-matching tail\"\n\nfun makeInfixChoice(kw: Keywords.Keyword, rhsKind: Str, compose: (Tree, Tree) -> Tree) =\n  keyword(kw) of reference(rhsKind) of\n    process: (rhs, _) => lhs => compose(lhs, rhs)\n    name: \"operator `\" + kw.name + \"` right-hand side\"\n\nfun makeBracketRule(fields) = // opening, closing, kind, wrapContent\n  // Pass the error message of closing bracket to the content.\n  keyword(fields.opening) of reference(fields.kind) of\n    process: (tree: Tree, next: Tree) => if next is\n      Tree.Error(Tree.Empty, msg) then fields.wrapContent(tree) Tree.Error(msg)\n      Tree.Empty                  then fields.wrapContent(tree)\n    name: fields.kind + \" in bracket\"\n    choices: tuple of keyword(fields.closing) of end of Tree.empty\n\n// Prefix rules and infix rules for expressions.\nval termRule = rule of\n  \"prefix rules for expressions\"\n  letExpression\n  // `fun` term\n  keyword(Keywords._fun) of term of\n    process: (params, body) => Tree.Lambda(params :: Nil, body)\n    name: \"function parameters\"\n    choices: tuple of keyword(Keywords._thinArrow) of term of\n      process: idFirst, name: \"function body\"\n  // `match`-`with` term\n  keyword(Keywords._match) of term of\n    process: Tree.Match\n    name: \"pattern matching scrutinee\"\n    choices: tuple of keyword(Keywords._with) of Choice.siding of\n      optional: true\n      init: keyword(Keywords._bar)()\n      rest: getRuleByKind(\"simple-matching\")\n      process: idSecond\n  // `function` term\n  keyword(Keywords._function) of Choice.siding of\n    optional: true\n    init: keyword(Keywords._bar)()\n    rest: getRuleByKind(\"simple-matching\")\n    process: (_, branches) => Tree.Match(Tree.empty, branches)\n  // `if`-`then`-`else` term\n  keyword(Keywords._if) of term of\n    process: (tst, conAlt) => if conAlt is [con, alt] then\n      Tree.Ternary(Keywords._if, tst, con, alt)\n    name: \"if-then-else condition\"\n    choices: tuple of keyword(Keywords._then) of term of\n      name: \"if-then-else consequent\"\n      choices: tuple of\n        end of None\n        keyword(Keywords._else) of term of\n          process: someFirst, name: \"if-then-else alternative\"\n  // `while` term\n  keyword(Keywords._while) of term of\n    process: Tree.While\n    name: \"while body\"\n    choices: tuple of keyword(Keywords._do) of term of\n      name: \"while end\", process: idFirst\n      choices: tuple of keyword(Keywords._done)()\n  // `for` term\n  keyword(Keywords._for) of term of\n    name: \"`for` head\"\n    process: (head, startEndBody) => Tree.For(head, ...startEndBody)\n    choices: tuple of keyword(Keywords._equal) of term of\n      process: (start, endBody) => [start, ...endBody]\n      name: \"`for` `to` or `downto` keyword\"\n      choices: tuple of Choice.siding of\n        init: tuple of keyword(Keywords._to)(), keyword(Keywords._downto)()\n        rest: term of\n          name: \"`for` `do` keyword\"\n          choices: tuple of keyword(Keywords._do) of term of\n            name: \"`for` `done` keyword\", process: idFirst\n            choices: tuple of keyword(Keywords._done)()\n        process: idSecond\n  // Choices for brackets\n  makeBracketRule of\n    opening: Keywords._leftRound, closing: Keywords._rightRound, kind: \"term\"\n    wrapContent: (tree) => if tree is Tree.Empty then Tree.Tuple(Nil) else tree\n  makeBracketRule of\n    opening: Keywords._leftSquare, closing: Keywords._rightSquare, kind: \"term\"\n    wrapContent: (tree) => Tree.Bracketed of Square, if tree is\n      Tree.Empty then Tree.Sequence(Nil)\n      else tree\n  makeBracketRule of\n    opening: Keywords._leftCurly, closing: Keywords._rightCurly\n    kind: \"term\", wrapContent: id\n  makeBracketRule of\n    opening: Keywords._begin, closing: Keywords._end, kind: \"term\"\n    wrapContent: (tree) => if tree is Tree.Empty then Tree.Sequence(Nil) else tree\n  // \"infix\" rule starting with <term>\n  term of\n    process: pipeInto\n    choices: tuple of\n      // Tuple (separated by commas)\n      makeInfixChoice of Keywords._comma, \"term\", (lhs, rhs) => if rhs is\n        Tree.Tuple(tail) then Tree.Tuple(lhs :: tail)\n        else Tree.Tuple(lhs :: rhs :: Nil)\n      // Sequence (separated by semicolons)\n      makeInfixChoice of Keywords._semicolon, \"term\", (lhs, rhs) => if rhs is\n        Tree.Sequence(tail) then Tree.Sequence(lhs :: tail)\n        else Tree.Sequence(lhs :: rhs :: Nil)\n      // Assignment: <expr> <- <expr>\n      makeInfixChoice of Keywords._leftArrow, \"term\", (lhs, rhs) =>\n        Tree.Infix(Keywords._leftArrow, lhs, rhs)\n      // Comparison: <expr> == <expr>\n      makeInfixChoice of Keywords._equalequal, \"term\", (lhs, rhs) =>\n        Tree.Infix(Keywords._equalequal, lhs, rhs)\n      // Comparison: <expr> * <expr>\n      makeInfixChoice of Keywords._asterisk, \"term\", (lhs, rhs) =>\n        Tree.App(Tree.Ident(\"*\", true), lhs :: rhs :: Nil)\n      // Selection: <expr> \".\" <identifier>\n      // Access: <expr> \".\" \"(\" <expr> \")\"\n      keyword(Keywords._period) of\n        keyword(Keywords._leftRound) of term of\n          process: (argument, _) => lhs =>\n            Tree.Infix(Keywords._period, lhs, Tree.Bracketed(Round, argument))\n          name: \"application argument\"\n          choices: tuple of keyword(Keywords._rightRound)()\n        term of\n          process: (rhs, _) => lhs => Tree.Infix(Keywords._period, lhs, rhs)\n          name: \"operator `.` right-hand side\"\n      // Type ascription: <expr> : <type>\n      keyword(Keywords._colon) of typeExpr of\n        process: (rhs, _) => lhs => Tree.Infix(Keywords._colon, lhs, rhs)\n        name: \"right-hand side type\"\n      // Application: <expr> <expr>\n      term of\n        process: (argument, _) => callee => Tree.App(callee, argument)\n        name: \"application argument\"\n        outerPrec: Keywords.appPrec\n\n// Prefix rules and infix rules for types.\nval typeRule = rule of\n  \"rules for types\"\n  // \"(\" <type> { \",\" <type> } \")\" [ <ident> ]\n  keyword(Keywords._leftRound) of typeExpr of\n    process: (headArg, tailArgsCtor) => if tailArgsCtor is\n      [tailArgs, ctor] then Tree.App(ctor, Tree.Tuple(headArg :: tailArgs))\n      Some(ctor) then Tree.App(ctor, headArg)\n      None then headArg\n    name: \"the first type in the parentheses\"\n    choices: tuple of\n      reference(\"type-arguments-tail\") of\n        name: \"the remaining type arguments\"\n        choices: tuple of keyword(Keywords._rightRound) of\n          ident of process: someFirst, name: \"the type constructor's name\"\n      keyword(Keywords._rightRound) of // either an identifier or nothing\n        end of None\n        ident of process: someFirst, name: \"the type constructor's name\"\n  // \"infix\" rule starting with <type>\n  typeExpr of\n    process: pipeInto\n    choices: tuple of\n      // <type> \"->\" <type>\n      makeInfixChoice of Keywords._thinArrow, \"type\", (lhs, rhs) =>\n        Tree.Infix(Keywords._thinArrow, lhs, rhs)\n      // <type> \"*\" <type>\n      makeInfixChoice of Keywords._asterisk, \"type\", (lhs, rhs) =>\n        Tree.Infix(Keywords._asterisk, lhs, rhs)\n      // Application: <type> <type>\n      typeExpr of\n        process: (callee, _) => argument => Tree.App(callee, argument)\n        outerPrec: Keywords.appPrec\n\ndefine(\"type-arguments-tail\") of keyword(Keywords._comma) of listLike of\n  head: \"type\", tail: \"type-arguments-tail\", name: \"type argument\"\n  \ndefine(\"constr-decl\") of ident of\n  process: (ctor, argOpt) => if argOpt is\n    Some(arg) then Tree.Infix(Keywords._of, ctor, arg)\n    None then ctor\n  name: \"the variant constructor's name\"\n  choices: tuple of\n    end of None\n    keyword(Keywords._of) of typeExpr of\n      process: someFirst, name: \"the variant constructor's argument\"\n\ndefine(\"variants\") of reference(\"constr-decl\") of\n  process: (lhs, rhsOpt) => if rhsOpt is\n    Some(rhs) then Tree.Infix(Keywords._bar, lhs, rhs)\n    else lhs\n  name: \"variants item\"\n  choices: tuple of\n    end of None\n    keyword(Keywords._bar) of reference(\"variants\") of\n      process: someFirst, name: \"variants end\"\n\ndefine(\"typedefs\") of reference(\"typedef-lhs\") of\n  process: (lhs, rhsMore) => if rhsMore is [rhs, more] then rhs(lhs) :: more\n  name: \"typedef name\"\n  choices: tuple of reference(\"typedef-rhs\") of\n    name: \"typedef body\"\n    choices: tuple of\n      end of Nil\n      keyword(Keywords._and) of reference(\"typedefs\") of\n        process: idFirst, name: \"typedef end\"\n\ndefine(\"typedef-rhs\") of keyword(Keywords._equal) of\n  reference(\"variants\") of\n    process: (rhs, _) => lhs => Tree.Infix(Keywords._equal, lhs, rhs)\n    name: \"typedef-rhs: variants\"\n  Choice.map of\n    keyword(Keywords._leftCurly) of\n      reference(\"label-decls\") of\n        process: (content, _) => if content is\n          Nil then Tree.Bracketed(Curly, Tree.Sequence(Nil))\n          else Tree.Bracketed(Curly, Tree.Sequence(content))\n        name: \"label-decl\"\n        choices: keyword(Keywords._rightCurly) of end of Tree.empty\n    rhs => lhs => Tree.Infix(Keywords._equal, lhs, rhs)\n\ndefine(\"typedef-rhs\") of keyword(Keywords._equalequal) of typeExpr of\n  process: (rhs, _) => lhs => Tree.Infix(Keywords._equalequal, lhs, rhs)\n  name: \"type alias body\"\n\ndefine(\"label-decl\") of typeExpr of\n  process: Tree.infix of Keywords._colon\n  name: \"label-decl name\"\n  choices: tuple of keyword(Keywords._colon) of typeExpr of\n    process: idFirst, name: \"label-decl body\"\n\ndefine(\"label-decls\") of listLike of\n  head: \"label-decl\", tail: \"label-decls\",\n  name: \"label and declaration pair\", sep: Keywords._semicolon\n\ndefine(\"constr-decls\") of listLike of\n  head: \"constr-decl\", tail: \"constr-decls\",\n  name: \"constructor declaration\", sep: Keywords._bar\n\ndefine(\"typedef-lhs\") of reference(\"type-params\") of\n  process: (params, ident) => if params is\n    Nil then ident\n    else Tree.App(ident, Tree.Tuple(params))\n  name: \"the type parameters\"\n  choices: tuple of ident of process: idFirst, name: \"the type identifier\"\n\ndefine(\"type-params\") of end(Nil)\ndefine(\"type-params\") of typeVar of process: (h, _) => h :: Nil, name: \"the only type parameter\"\ndefine(\"type-params\") of keyword(Keywords._leftRound) of typeVar of\n  process: Cons\n  name: \"the first type parameter\"\n  choices: tuple of reference(\"type-params-tail\") of\n    process: idFirst, name: \"more type parameters\"\n    choices: tuple of keyword(Keywords._rightRound)()\n\ndefine(\"type-params-tail\") of end(Nil)\ndefine(\"type-params-tail\") of keyword(Keywords._comma) of typeVar of\n  process: Cons, name: \"the first type parameter\"\n  choices: tuple of reference(\"type-params-tail\") of\n    process: idFirst, name: \"more type parameters\"\n\nval declRule = rule of\n  \"prefix rules for module items\"\n  makeLetBindings(false) // let definition\n  keyword(Keywords._type) of\n    reference(\"typedefs\") of\n      process: (typedefs, _) => Tree.Define(Tree.DefineKind.Type, typedefs)\n      name: \"more typedefs\"\n  keyword(Keywords._exception) of\n    reference(\"constr-decls\") of\n      process: (decls, _) => Tree.Define(Tree.DefineKind.Exception, decls)\n      name: \"constructor declarations\"\n  keyword(Keywords._hash) of ident of\n    process: (ident, body) => Tree.Define(Tree.DefineKind.Directive, [ident, body] :: Nil)\n    name: \"directive name\"\n    choices: tuple of term of process: idFirst, name: \"directive body\"\n\nsyntaxKinds |> MutMap.insert of \"term\", termRule\nsyntaxKinds |> MutMap.insert of \"type\", typeRule\nsyntaxKinds |> MutMap.insert of \"decl\", declRule\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Test.mls",
    "content": "import \"./Lexer.mls\"\nimport \"./Keywords.mls\"\nimport \"./Token.mls\"\nimport \"./Tree.mls\"\nimport \"./TokenHelpers.mls\"\nimport \"./TreeHelpers.mls\"\nimport \"./Parser.mls\"\nimport \"../../Iter.mls\"\nimport \"../../Option.mls\"\nimport \"../../Predef.mls\"\nimport \"../../Stack.mls\"\n\nopen Token { LiteralKind }\nopen Parser { parse, tracer }\nopen Option { Some, None }\nopen Predef { print }\nopen Stack\nopen TreeHelpers { showAsTree }\n\nmodule Test with ...\n\npattern Flag = \"tree\" | \"trace\" | \"tokens\"\n\nfun flags(tokens) =\n  let result = new Set\n  while tokens is\n    Token.Space :: Token.Identifier(\":\", _) :: Token.Identifier(Flag as flag, _) :: tail then\n      result.add(flag)\n      set tokens = tail\n    Token.Identifier(\":\", _) :: Token.Identifier(Flag as flag, _) :: tail then\n      result.add(flag)\n      set tokens = tail\n  [result, tokens]\n\nfun example(...lines) =\n  let\n    source = lines.join(\"\\n\")\n    tokens = Lexer.lex(source, noWhitespace: true)\n  if flags(tokens) is [flags, tokens] then ...\n  if flags.has(\"tokens\") do\n    print of TokenHelpers.panorama(tokens)\n  tracer.reset()\n  set tracer.enabled = flags.has(\"trace\")\n  let trees = parse(tokens)\n  set tracer.enabled = false\n  if flags.has(\"tree\") do\n    print of trees\n      Iter.fromStack()\n      Iter.mapping of showAsTree\n      Iter.joined of \"\\n\"\n  print of trees\n    Iter.fromStack()\n    Iter.mapping of Tree.summary\n    Iter.joined of \"\\n\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Token.mls",
    "content": "import \"../../Option.mls\"\nimport \"../../Predef.mls\"\n\nopen Option { Some, None }\nopen Predef { mkStr }\n\nmodule Token with ...\n\nobject\n  Angle\n  Round\n  Square\n  Curly\n  BeginEnd\n\ntype BracketKind = Angle | Round | Square | Curly | BeginEnd\n\nmodule LiteralKind with\n  object\n    Integer\n    Decimal\n    String\n    Boolean\n\nabstract class Token with\n  let _location = None\n  fun withLocation(start, end, lookupTable) =\n    set _location = Some of start: start, end: end, lookupTable: lookupTable\n    this\n  fun location = _location\n  \n  fun displayLocation = if _location is\n    Some(location) then\n      let start = location.lookupTable.lookup(location.start)\n      let end = location.lookupTable.lookup(location.end)\n      mkStr of\n        start.0.toString(), \":\", start.1.toString()\n        \"-\"\n        end.0.toString(), \":\", end.1.toString()\n    else \"\"\n\nclass LineLookupTable(lines: Array[Int]) with\n  fun lookup(index: Int): [Int, Int] =\n    if index < 0 do\n      set index = 0\n    let\n      begin = 0\n      end = lines.length\n      mid = Math.floor of (begin + end) / 2\n    while begin < end do\n      if index <= lines.at(mid) then\n        set end = mid\n      else\n        set begin = mid + 1\n      set mid = Math.floor of (begin + end) / 2\n    let line = mid + 1\n    let column = index - if mid == 0 then -1 else lines.at(mid - 1)\n    [line, column]\n\ndata\n  class\n    Space() extends Token\n    Error() extends Token\n    Comment(content: Str) extends Token\n    Identifier(name: Str, symbolic: Bool) extends Token\n    Literal(kind, literal: Str) extends Token\n\nfun same(a, b) = if\n  a is Space and b is Space then true\n  a is Comment(c) and b is Comment(c') then c == c'\n  a is Identifier(n, s) and b is Identifier(n', s') then n == n' and s == s'\n  a is Literal(k, l) and b is Literal(k', l') then k == k' and l == l'\n  else false\n\nfun integer(literal, endIndex)(using llt: LineLookupTable) =\n  Literal(LiteralKind.Integer, literal).withLocation of\n    endIndex - literal.length, endIndex, llt\nfun decimal(literal, endIndex)(using llt: LineLookupTable) =\n  Literal(LiteralKind.Decimal, literal).withLocation of\n    endIndex - literal.length, endIndex, llt\nfun string(literal, startIndex, endIndex)(using llt: LineLookupTable) =\n  Literal(LiteralKind.String, literal).withLocation(startIndex, endIndex, llt)\nfun boolean(literal, endIndex)(using llt: LineLookupTable) =\n  Literal(LiteralKind.Boolean, literal).withLocation of\n    endIndex - literal.length, endIndex, llt\nfun identifier(name, endIndex)(using llt: LineLookupTable) =\n  Identifier(name, false).withLocation of\n    endIndex - name.length, endIndex, llt\nfun symbol(name, endIndex)(using llt: LineLookupTable) =\n  Identifier(name, true).withLocation of\n    endIndex - name.length, endIndex, llt\nfun comment(content, startIndex, endIndex)(using llt: LineLookupTable) =\n  Comment(content).withLocation(startIndex, endIndex, llt)\nfun error(startIndex, endIndex)(using llt: LineLookupTable) =\n  Error().withLocation(startIndex, endIndex, llt)\nfun space(startIndex, endIndex)(using llt: LineLookupTable) =\n  Space().withLocation(startIndex, endIndex, llt)\n  \nfun summary(token) = if token is\n  Space then \"␠\"\n  Error then \"⚠\"\n  Comment(_) then \"\\uD83D\\uDCAC\" // The text ballon emoji.\n  Identifier(name, _) then name\n  Literal(_, literal) then literal\n\nfun display(token) = (if token is\n  Space then \"space\"\n  Error then \"error\"\n  Comment then \"comment\"\n  Identifier(name, _) then \"identifier `\" + name + \"`\"\n  Literal(kind, value) then mkStr of\n    kind.toString().toLowerCase()\n    \" \"\n    JSON.stringify(value)\n  ) + \" at \" + token.displayLocation\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/TokenHelpers.mls",
    "content": "import \"./Token.mls\"\nimport \"../../Stack.mls\"\nimport \"../../Predef.mls\"\n\nopen Stack\nopen Predef { mkStr }\n\ntype StackT[A] = Stack.Cons[A] | Stack.Nil\n\nmodule TokenHelpers with ...\n\nfun display(tokens: StackT[Token.Token], limit: Int): Str =\n  let\n    i = 0\n    values = mut []\n  while i < limit and tokens is head :: tail do\n    values.push of head Token.summary()\n    set\n      tokens = tail\n      i += 1\n  mkStr of\n    \"┃\"\n    values.join(\"│\"),\n    if tokens is _ :: _ then \"│⋯\" else \"┃\"\n    \nfun panorama(tokens) = display(tokens, Number.MAX_SAFE_INTEGER)\n\nfun preview(tokens) = display(tokens, 5)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/Tree.mls",
    "content": "import \"../../Iter.mls\"\nimport \"../../Predef.mls\"\nimport \"../../Stack.mls\"\nimport \"../../Option.mls\"\nimport \"../../StrOps.mls\"\nimport \"./Keywords.mls\"\nimport \"./Token.mls\"\n\nopen Predef { fold, mkStr }\nopen Stack\nopen Option { Some, None }\nopen Token { LiteralKind, BracketKind }\nopen Keywords { opPrec, INT_MAX }\n\n//  _____\n// |_   _| __ ___  ___\n//   | || '__/ _ \\/ _ \\\n//   | || | |  __/  __/\n//   |_||_|  \\___|\\___|\n//\n// ====================\n\nabstract class Tree\nmodule Tree with  \n  \n  module DefineKind with\n    data class Let(recursive: Bool)\n    object Type\n    object Exception\n    object Directive\n    \n    type DefineKind = Let | Type | Exception | Directive\n  \n  open DefineKind\n  \n  data\n    class\n      Empty() extends Tree\n      Error(tree: Tree, message: Str) extends Tree\n      Bracketed(kind: BracketKind, tree: Tree) extends Tree\n      Ident(name: Str, symbolic: Bool) extends Tree\n      Underscore() extends Tree\n      Modified(modifier, subject) extends Tree\n      Tuple(trees: Stack[Tree]) extends Tree\n      Sequence(trees: Stack[Tree]) extends Tree\n      Literal(kind, value) extends Tree\n      Match(scrutinee: Tree, branches: Stack[Tree]) extends Tree\n      Lambda(params: Stack[Tree], body: Tree) extends Tree\n      App(callee: Tree, argument: Tree) extends Tree\n      Infix(op: Keywords.Keyword, lhs: Tree, rhs: Tree) extends Tree\n      // `items` is separated by `and`\n      Define(kind: DefineKind.DefineKind, items: Stack[[Tree, Tree]]) extends Tree\n      LetIn(bindings: Stack[Tree], body: Tree) extends Tree\n      While(cond: Tree, body: Tree) extends Tree\n      For(head: Tree, start: Tree, end: Tree, body: Tree) extends Tree\n      // For `if`-`then`-`else`. The last part is optional.\n      Ternary(keyword: Keywords.Keyword, lhs: Tree, rhs: Tree, body) extends Tree\n  \n  fun empty = Empty()\n  fun error(message: Str) = empty Error(message)\n  fun summary(tree) =\n    fun par(text: Str, cond: Bool) = if cond then \"(\" + text + \")\" else text\n    fun prec(tree: Tree, side: Bool) = if tree is\n      Empty then INT_MAX\n      Error(tree, _) then prec(tree, side)\n      Bracketed(_, _) then INT_MAX\n      Ident then INT_MAX\n      Underscore then INT_MAX\n      Modified then 1\n      Tuple then INT_MAX\n      Sequence then 1\n      Literal then INT_MAX\n      Match then 2\n      App(callee, _) and callee is\n        Ident(op, true) and opPrec(op) is [leftPrec, rightPrec] and\n          side then rightPrec\n          else leftPrec\n        else Keywords.appPrec\n      Infix(op, _, _) and\n        side then op.rightPrecOrMax\n        else op.leftPrecOrMax\n      Ternary then 3\n      Lambda then Keywords._fun.leftPrecOrMax\n    // Wrap trees in guillemet so they are easier to spot.\n    fun wrap(something) = if something is\n      Tree then \"«\" + go(something) + \"»\"\n      else go(something)\n    fun go(tree) = if tree is\n      Empty then \"{}\"\n      Error(Empty, _) then \"⚠\"\n      Error(tree, _) then \"<⚠:\" + go(tree) + \">\"\n      Bracketed(kind, tree) and kind is\n        Token.Round then \"(\" + go(tree) + \")\"\n        Token.Square then \"[\" + go(tree) + \"]\"\n        Token.Curly then \"{\" + go(tree) + \"}\"\n        Token.Angle then \"<\" + go(tree) + \">\"\n      Ident(name, _) then name\n      Underscore() then \"_\"\n      Modified(modifier, subject) then go(modifier) + \" \" + go(subject)\n      Tuple(trees) then \"(\" + trees Iter.fromStack() Iter.mapping(go) Iter.joined(\", \") + \")\"\n      Sequence(trees) then trees Iter.fromStack() Iter.mapping(go) Iter.joined(\"; \")\n      Literal(LiteralKind.String, value) and\n        value.length > 5 then JSON.stringify(value.slice(0, 5)).slice(0, -1) + \"…\\\"\"\n        else JSON.stringify(value)\n      Literal(_, value) then value\n      Match(scrutinee, branches) then mkStr of\n        if scrutinee is Empty then \"function \" else\n          \"match \" + go(scrutinee) + \" with \"\n        branches Iter.fromStack() Iter.mapping(go) Iter.joined(\" | \")\n      // Function application for binary operators.\n      App(Ident(op, true), lhs :: rhs :: Nil) then\n        if opPrec(op) is [leftPrec, rightPrec] then fold(+) of\n          par of go(lhs), prec(lhs, false) < leftPrec\n          \" \", op, \" \"\n          par of go(rhs), prec(rhs, true) < rightPrec\n      // Unary expressions\n      App(Ident(op, true), arg) then mkStr of\n        op\n        par of go(arg), prec(arg, false) <= Keywords.prefixPrec\n      // Function application\n      App(callee, argument) then mkStr of\n        go(callee)\n        \" \"\n        par of go(argument), prec(argument, false) <= Keywords.appPrec\n      Infix(Keywords.Keyword(\".\", _, _), target, Ident(field, _)) then\n        if opPrec(\".\") is [leftPrec, _] then mkStr of\n          par of go(target), prec(target, false) < leftPrec\n          \".\"\n          field\n      Infix(op, lhs, rhs) then fold(+) of\n        go(lhs), \" \", go(op), \" \", go(rhs)\n      Define(Directive, [name, value] :: Nil) then StrOps.concat of\n        \"#\", go(name), \" \", go(value)\n      Define(kind, items) then mkStr of\n        if kind is\n          Let(true) then \"let rec \"\n          Let(false) then \"let \"\n          Type then \"type \"\n          Exception then \"exception \"\n        items\n          Iter.fromStack()\n          Iter.mapping of case\n            Tree as tree then go(tree)\n            [lhs, rhs] then go(lhs) + \" = \" + go(rhs)\n          Iter.joined(\" and \")\n      LetIn(bindings, body) then mkStr of\n        \"let \"\n        bindings\n          Iter.fromStack()\n          Iter.mapping of go\n          Iter.joined(\" and \")\n        ...if body is\n          Some(body) then [\" in \", go(body)]\n          None then []\n      While(cond, body) then mkStr of \"while \", go(cond), \" do \", go(body), \" done\"\n      For(head, start, end, body) then mkStr of\n        \"for \", go(head), \" = \", go(start), \" to \", go(end), \" do \", go(body), \" done\"\n      Ternary(keyword, lhs, rhs, body) then fold(+) of\n        keyword.name, \" \", go(lhs),\n        if keyword.name is\n          \"if\" then \" then \"\n          \"type\" then \" = \"\n          \"let\" then \" = \"\n        if rhs is Some(rhs') then go(rhs') else go(rhs)\n        if keyword.name is\n          \"if\" then \" then \"\n          \"type\" then \"\"\n          \"let\" then \" in \"\n        if body is Some(body) then go(body) else go(body)\n      Lambda(params, body) then fold(+) of\n        \"fun \", params Iter.fromStack() Iter.mapping(go) Iter.joined(\" \"), \" -> \", go(body)\n      Keywords.Keyword(name, _, _) then name\n      Some(tree) then \"Some(\" + wrap(tree) + \")\"\n      None then \"None\"\n      _ :: _ then tree Iter.fromStack() Iter.mapping(wrap) Iter.joined(\" :: \") + \" :: Nil\"\n      Nil then \"Nil\"\n      [..trees] then \"[\" + trees Iter.mapping((tree, _, _) => wrap(tree)) Iter.joined(\", \") + \"]\"\n      else \"<unexpected:\" + tree + \">\"\n    wrap(tree)\n  \n  fun infix(op)(lhs, rhs) = Infix(op, lhs, rhs)\n  \n  fun bracketed(tree, kind) = Bracketed(kind, tree)\n  \n  fun asSequence(tree) = if tree is\n    Empty then Sequence of Nil\n    Sequence then tree\n    else Sequence of tree :: Nil\n  \n  fun tupleWithHead(tree, head) = if tree is\n    Tuple(tail) then Tuple(head :: tail)\n    else Tuple(head :: tree :: Nil)\n  \n  fun sequenceWithHead(tree, head) = if tree is\n    Sequence(tail) then Sequence(head :: tail)\n    else Sequence(head :: tree :: Nil)\n  \n  fun nonEmpty(tree) = if tree is\n    Empty then false\n    Error(Empty, _) then false\n    else true\n  \n  fun nonEmptyError(tree) = if tree is\n    Error(Empty, _) then false\n    else true\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/TreeHelpers.mls",
    "content": "import \"../../Option.mls\"\nimport \"../../Predef.mls\"\nimport \"../../Stack.mls\"\nimport \"./Tree.mls\"\nimport \"./Keywords.mls\"\nimport \"./Token.mls\"\n\nopen Predef\nopen Stack\nopen Token { LiteralKind }\nopen Option { Some, None }\n\nmodule TreeHelpers with ...\n\nfun first(array) = if array is [first, ...] then first\n\nfun second(array) = if array is [_, second, ...] then second\n\nfun indented(text) = text.split(\"\\n\").join(\"\\n  \")\n\nfun showAsTree(thing) =\n  fun itemize(something) = if something is\n    Some(content) then tuple of [\"Some of \" + go(content)], []\n    None then tuple of \"None\", []\n    head :: tail then\n      let\n        items = mut [go(head)]\n        remaining = tail\n      while remaining is\n        head' :: tail' do\n          items.push(go of head')\n          set remaining = tail'\n      tuple of (\"Stack of \\n\" + \"  \" + indented of items.join(\"\\n\")), []\n    Nil then [\"Nil\", []]\n    Str then [JSON.stringify(something), []] // TODO: This doesn't work.\n    Int then [something.toString(), []]\n    Tree.Empty then [\"Empty\", []]\n    Tree.Error(Tree.Empty, m) then tuple of \"Error\", [[\"message\", go(m)]]\n    Tree.Error(t, m) then tuple of \"Error\", [[\"tree\", go(t)], [\"message\", go(m)]]\n    Tree.Ident(n, _) then tuple of \"Ident\", [[\"name\", go(n)]]\n    Tree.Bracketed(k, items) then tuple of\n      \"Bracketed#\" + k.toString(), [[\"items\", go(items)]]\n    Tree.Underscore() then tuple of \"Underscore\", []\n    Tree.Modified(m, s) then\n      tuple of \"Modified\", [[\"modifier\", go(m)], [\"subject\", go(s)]]\n    Tree.Tuple(t) then tuple of \"Tuple\", [[\"items\", go(t)]]\n    Tree.Sequence(t) then tuple of \"Sequence\", [[\"items\", go(t)]]\n    Tree.Literal(k, v) then tuple of (\"Literal#\" + go(k) + \" of \" + go(v)), []\n    Tree.Match(scrutinee, branches) then tuple of\n      \"Match\", [[\"scrutinee\", scrutinee], [\"branches\", go(branches)]]\n    Tree.App(c, a) then tuple of \"App\", [[\"callee\", go(c)], [\"argument\", go(a)]]\n    Tree.Infix(op, lhs, rhs) then tuple of\n      \"Infix\", [[\"op\", go(op)], [\"lhs\", go(lhs)], [\"rhs\", go(rhs)]]\n    Tree.Define(k, i) then tuple of \"Define\", [[\"kind\", k.toString()], [\"items\", go(i)]]\n    Tree.LetIn(bds, b) then tuple of \"LetIn\", [[\"bindings\", go(bds)], [\"body\", go(b)]]\n    Tree.While(c, b) then tuple of \"While\", [[\"condition\", go(c)], [\"body\", go(b)]]\n    Tree.For(h, s, e, b) then tuple of\n      \"For\", [[\"head\", go(h)], [\"start\", go(s)], [\"end\", go(e)], [\"body\", go(b)]]\n    Tree.Ternary(n, l, r, b) then tuple of\n      \"Ternary\", [[\"name\", go(n)], [\"lhs\", go(l)], [\"rhs\", go(r)], [\"body\", go(b)]]\n    Tree.Lambda(p, b) then tuple of \"Lambda\", [[\"params\", go(p)], [\"body\", go(b)]]\n    Keywords.Keyword as keyword then [keyword.toString(), []]\n    LiteralKind.Integer then tuple of \"Integer\", []\n    LiteralKind.Decimal then tuple of \"Decimal\", []\n    LiteralKind.String then tuple of \"String\", []\n    LiteralKind.Boolean then tuple of \"Boolean\", []\n    [x, y] then tuple of \"Pair\", [[\"first\", go(x)], [\"second\", go(y)]]\n    else tuple of \"Unknown\", [[\"JSON.stringify(_)\", JSON.stringify(something)]]\n  fun go(something) = if itemize(something) is\n    [intro, []] then intro\n    [intro, [field]] and intro != \"Unknown\" then intro + \" of \" + second of field\n    [intro, fields] then\n      let dialogue = fields.map of (field, _, _) =>\n        field first() + \" = \" + field second()\n      intro + \":\\n  \" + indented of dialogue.join(\"\\n\")\n  go(thing)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing/vendors/railroad/railroad.css",
    "content": "svg.railroad-diagram {\n  /* background-color: hsl(30,20%,95%); */\n  background: transparent;\n}\nsvg.railroad-diagram path {\n  stroke-width: 2;\n  stroke: rgba(1, 1, 1, 0.80);\n  fill: transparent;\n}\nsvg.railroad-diagram text {\n  text-anchor: middle;\n  white-space: pre;\n}\nsvg.railroad-diagram text.diagram-text {\n  font-size: 12px;\n}\nsvg.railroad-diagram text.diagram-arrow {\n  font-size: 16px;\n}\nsvg.railroad-diagram text.label {\n  text-anchor: start;\n}\nsvg.railroad-diagram text.comment {\n  font: italic 12px monospace;\n}\nsvg.railroad-diagram g.non-terminal text {\n  font-style: -apple-system, system-ui, sans-serif;\n  font-weight: 600;\n  font-style: italic;\n}\nsvg.railroad-diagram g.terminal text {\n  font-family: Inconsolata, monospace;\n}\nsvg.railroad-diagram rect {\n  stroke-width: 1.5;\n  stroke: black;\n  fill: #ffffff;\n}\nsvg.railroad-diagram rect.group-box {\n  stroke: gray;\n  stroke-dasharray: 10 5;\n  fill: none;\n}\nsvg.railroad-diagram path.diagram-text {\n  stroke-width: 1.5;\n  stroke: black;\n  fill: white;\n  cursor: help;\n}\nsvg.railroad-diagram g.diagram-text:hover path.diagram-text {\n  fill: #eee;\n}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing-web-demo/Examples.mls",
    "content": "import \"../../MutMap.mls\"\nimport \"../../Predef.mls\"\n\nopen Predef\nmodule Examples with...\n\nval examples = MutMap.empty\n\nexamples |> MutMap.insert of\n  \"hanoi\"\n  name: \"Hanoi from Caml Light\"\n  source: \"\"\"let spaces n = make_string n \" \";;\nlet disk size =\n    let right_half = make_string size \">\"\n    and left_half = make_string size \"<\"\n    in left_half ^ \"|\" ^ right_half;;\nlet disk_number n largest_disk_size =\n    let white_part = spaces (largest_disk_size + 1 - n) in\n    white_part ^ (disk n) ^ white_part;;\nlet peg_base largest_disk_size =\n    let half = make_string largest_disk_size \"_\" in\n    \" \" ^ half ^ \"|\" ^ half ^ \" \";;\nlet rec peg largest_disk_size = function\n  | (0, []) -> []\n  | (0, head::rest) ->\n      disk_number head largest_disk_size ::\n      peg largest_disk_size (0, rest)\n  | (offset, lst) ->\n      disk_number 0 largest_disk_size ::\n      peg largest_disk_size (offset-1, lst);;\nlet rec join_lines l1 l2 l3 =\n  match (l1, l2, l3) with\n  | ([], [], []) -> []\n  | (t1::r1, t2::r2, t3::r3) -> (t1 ^ t2 ^ t3) :: join_lines r1 r2 r3\n  | _ -> failwith \"join_lines\";;\n\"\"\"\n\nexamples |> MutMap.insert of\n  \"extensible\"\n  name: \"Extensible Syntax\"\n  source: \"\"\"#newKeyword (\"hello\", Some 3, Some 3)\n#newKeyword (\"goodbye\", None, None)\n  \n#newCategory(\"greeting\")\n  \n#extendCategory(\"greeting\", [ keyword(\"hello\"), \"term\", \"greeting\" ], foo)\n#extendCategory(\"greeting\", [ keyword(\"goodbye\") ], bar)\n  \n#extendCategory(\"decl\", [ \"greeting\" ], baz)\n  \n  \nhello \"Rob\" hello \"Bob\" goodbye\n  \n#diagram \"\"\n\"\"\"\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing-web-demo/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Document</title>\n  <link href=\"\nhttps://cdn.jsdelivr.net/npm/modern-normalize@3.0.1/modern-normalize.min.css\n\" rel=\"stylesheet\">\n  <link href=\"https://cdn.jsdelivr.net/npm/typeface-inconsolata@1.1.13/index.min.css\" rel=\"stylesheet\">\n</head>\n\n<body>\n  <div id=\"app\">\n    <div id=\"input\">\n      <header class=\"toolbar\">\n        <button class=\"button\" id=\"parse\">Parse</button>\n        <select class=\"select\" id=\"example\"></select>\n      </header>\n      <textarea id=\"editor\" spellcheck=\"false\" autocapitalize=\"off\"></textarea>\n    </div>\n    <div id=\"output\"></div>\n  </div>\n  <div id=\"syntax-diagrams\">\n    <h2>Syntax Diagrams</h2>\n    <main></main>\n  </div>\n  <script type=\"module\" src=\"./main.mjs\"></script>\n  <style>\n    :root {\n      --monospace: Inconsolata, Menlo, Consolas, 'Courier New', Courier, monospace;\n    }\n\n    body {\n      font-size: 16px;\n      font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;\n    }\n\n    h2 {\n      margin: 0;\n      font-size: 1.5rem;\n    }\n\n    h3 {\n      margin: 0;\n    }\n\n    #app {\n      width: 100vw;\n      height: calc(100vh - 4rem);\n      display: flex;\n      flex-direction: row;\n      padding: 1rem;\n      gap: 1rem;\n    }\n\n    #syntax-diagrams {\n      box-sizing: border-box;\n      padding: 1rem;\n      border-top: 1px solid #000;\n      display: flex;\n      flex-direction: column;\n      gap: 1rem;\n    }\n\n    #syntax-diagrams main {\n      padding: 1rem;\n      /* min-height: 0;\n      flex: 1; */\n      /* overflow: auto; */\n      border: 1px solid #000;\n    }\n\n    #input,\n    #output {\n      flex: 1;\n      border: 1px solid #000;\n    }\n\n    #input {\n      display: flex;\n      flex-direction: column;\n    }\n\n    #input .toolbar {\n      display: flex;\n      gap: 0.5rem;\n      padding: 0.5rem;\n      background: #f0f0f0;\n      border-bottom: 1px solid #000;\n    }\n\n    #output {\n      overflow: auto;\n      padding: 0.5rem;\n    }\n\n    #editor {\n      padding: 0.5rem;\n      width: 100%;\n      height: 100%;\n      resize: none;\n      border: none;\n      font-family: var(--monospace);\n    }\n\n    #editor:focus {\n      outline: none;\n    }\n    \n    .select {\n      line-height: 1.5;\n      background: #ffffff;\n      border: 1px solid #000;\n      box-shadow: rgb(187, 187, 187) 2px 2px 0px 0px;\n    }\n    \n    .select:focus {\n      outline: none;\n      box-shadow: rgb(187, 187, 187) 2px 2px 0px 0px, 0 0 0 .1rem rgba(52, 130, 255, 0.84);\n    }\n\n    .button {\n      line-height: 1.5;\n      background: rgb(153, 197, 255);\n      border: 1px solid #000;\n      box-shadow: rgb(187, 187, 187) 2px 2px 0px 0px;\n    }\n\n    .button:focus {\n      box-shadow: rgb(187, 187, 187) 2px 2px 0px 0px, 0 0 0 .1rem rgba(0, 0, 0, .2);\n    }\n\n    collapsible-tree {\n      font-family: var(--monospace);\n    }\n\n    details {\n      margin-left: 1em;\n      cursor: pointer;\n    }\n\n    summary {\n      outline: none;\n      list-style: none;\n    }\n\n    details>summary::-webkit-details-marker {\n      display: none;\n    }\n\n    details:not([open]):not([leaf])>summary::after {\n      content: \" ...\";\n    }\n\n    collapsible-tree details {\n      position: relative;\n    }\n\n    collapsible-tree details>.rule {\n      position: absolute;\n      top: 1rem;\n      left: 1px;\n      bottom: 0;\n      border-left: 1px dashed rgba(0, 0, 0, .2);\n    }\n\n    collapsible-tree>details {\n      margin-left: 0;\n    }\n\n    figcaption {\n      font-style: italic;\n      font-weight: 600\n    }\n\n    figure:target figcaption {\n      color: #007bff\n    }\n\n    figure:target figcaption::before {\n      font-style: normal;\n      content: '⯈ '\n    }\n\n    figure:target figcaption::after {\n      font-style: normal;\n      content: ' ⯇'\n    }\n\n    svg.railroad-diagram {\n      /* background-color: hsl(30,20%,95%); */\n      background: transparent;\n    }\n\n    svg.railroad-diagram path {\n      stroke-width: 2;\n      stroke: rgba(1, 1, 1, 0.80);\n      fill: transparent;\n    }\n\n    svg.railroad-diagram text {\n      text-anchor: middle;\n      white-space: pre;\n    }\n\n    svg.railroad-diagram text.diagram-text {\n      font-size: 12px;\n    }\n\n    svg.railroad-diagram text.diagram-arrow {\n      font-size: 16px;\n    }\n\n    svg.railroad-diagram text.label {\n      text-anchor: start;\n    }\n\n    svg.railroad-diagram text.comment {\n      font: italic 12px monospace;\n    }\n\n    svg.railroad-diagram g.non-terminal text {\n      font-style: -apple-system, system-ui, sans-serif;\n      font-weight: 600;\n      font-style: italic;\n    }\n\n    svg.railroad-diagram g.terminal text {\n      font-family: Inconsolata, monospace;\n    }\n\n    svg.railroad-diagram rect {\n      stroke-width: 1.5;\n      stroke: black;\n      fill: #ffffff;\n    }\n\n    svg.railroad-diagram rect.group-box {\n      stroke: gray;\n      stroke-dasharray: 10 5;\n      fill: none;\n    }\n\n    svg.railroad-diagram path.diagram-text {\n      stroke-width: 1.5;\n      stroke: black;\n      fill: white;\n      cursor: help;\n    }\n\n    svg.railroad-diagram g.diagram-text:hover path.diagram-text {\n      fill: #eee;\n    }\n  </style>\n</body>\n\n</html>\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/apps/parsing-web-demo/main.mls",
    "content": "// Note: This file does not have a corresponding test file. It is recommended to\n// test it through the following steps.\n// \n// 1. Install `serve` globally using `npm install -g serve`.\n// 2. Run `serve hkmc2/shared/src/test/mlscript-compile` in the project's root.\n// 3. Open the URL `http://localhost:3000/apps/parsing-web-demo` in your browser.\n//    If port 3000 is not available, use the URL suggested by the serve command.\n// 4. Try and test it in the browser.\n//\n// Note that after the file is updated, we need to manually refresh the browser.\n// Or we can use Live Server extension (or its alternatives) in VSCode to\n// automatically refresh the browser.\n\nimport \"../parsing/Parser.mls\"\nimport \"../parsing/Lexer.mls\"\nimport \"../../StrOps.mls\"\nimport \"../../Iter.mls\"\nimport \"../../XML.mls\"\nimport \"../../Option.mls\"\nimport \"../../Runtime.mls\"\nimport \"../../Predef.mls\"\nimport \"../parsing/TreeHelpers.mls\"\nimport \"../parsing/Extension.mls\"\nimport \"../parsing/ParseRuleVisualizer.mls\"\nimport \"../parsing/Rules.mls\"\nimport \"../parsing/vendors/railroad/railroad.mjs\"\nimport \"./Examples.mls\"\n\nopen XML { elem }\nopen Predef\nopen Option { Some, None }\nopen Examples\n\nmodule Main with ...\n\nlet query = document.querySelector.bind(document)\nlet editor = query(\"#editor\")\nlet selector = query(\"select#example\")\nlet parseButton = query(\"button#parse\")\nlet outputPanel = query(\"#output\")\n\nexamples Iter.each of case [key, example] then\n  let option = document.createElement of \"option\"\n  set option.value = key\n  set option.textContent = example.name\n  selector.appendChild of option\n  // Load the first example.\n  if editor.value is \"\" do\n    set editor.value = example.source\n\n// Make pressing <kbd>Tab</kbd> add two spaces at the caret's position.\neditor.addEventListener of \"keydown\", event =>\n  if event.key is \"Tab\" do\n    // Prevent the default tab behavior (focusing the next element).\n    event.preventDefault()\n    let start = editor.selectionStart\n    let end = editor.selectionEnd\n    set editor.value = editor.value.substring(0, start) + \"  \" + editor.value.substring(end)\n    set editor.selectionEnd = start + 2\n    set editor.selectionStart = editor.selectionEnd\n\nselector.addEventListener of \"change\", event =>\n  if examples.get(selector.value) is\n    Some(example) do set editor.value = example.source\n    None do throw new Error of \"Example \\\"\" + selector.value + \"\\\" not found\"\n\nparseButton.addEventListener of \"click\", event =>\n  let tokens = Lexer.lex(editor.value, noWhitespace: true)\n  set outputPanel.innerHTML = \"\"\n  Runtime.try_catch of\n    () =>\n      let trees = Parser.parse(tokens)\n      trees Iter.fromStack() Iter.each of tree => if\n        Extension.isDiagramDirective(tree) then displayRules()\n        else\n          let collapsibleTree = document.createElement(\"collapsible-tree\")\n          set collapsibleTree.textContent = TreeHelpers.showAsTree(tree)\n          outputPanel.appendChild of collapsibleTree\n    error =>\n      let errorDisplay = document.createElement(\"error-display\")\n      errorDisplay.setError of error\n      outputPanel.appendChild of errorDisplay\n\nlet indentRegex = new RegExp(\"\"\"^(\\s*)\"\"\")\n\nfun parseIndentedText(text) =\n  let root = (text: \"\", children: [])\n  let stack = [(node: root, indent: -1)]\n  text.split(\"\\n\")\n    Iter.filtering(line => line.trim().length > 0)\n    Iter.each of line =>\n      let indent = line.match(indentRegex).[1].length\n      let text = line.substring(indent)\n      while indent <= stack.[stack.length - 1].indent do\n        stack.pop()\n      let newNode = (text: text, children: [])\n      stack.[stack.length - 1].node.children.push of newNode\n      stack.push of node: newNode, indent: indent\n  root.children\n\n// * CSS styles for the error display.\n// * The content in custom elements is placed inside the ShadowDOM, which is\n// * scoped. Therefore, styles placed directly in HTML won't be effective on\n// * elements inside custom elements. Placing CSS here is more convenient.\nlet errorDisplayStyle = \"\"\"\n.error-container {\n  background-color: #fdd;\n  padding: 0.375rem 0.75rem 0.5rem;\n  font-family: var(--monospace);\n  color: #991b1bff;\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n.error-message {\n  margin: 0;\n  font-weight: bold;\n  font-size: 1.125rem;\n}\n.stack-trace {\n  font-size: 0.875rem;\n  margin: 0;\n  list-style-type: none;\n  padding-left: 0.5rem;\n}\"\"\"\n\nclass CollapsibleTree extends HTMLElement with\n  fun connectedCallback() =\n    let rawText = this.textContent\n    set this.textContent = \"\"\n    let treeData = parseIndentedText(rawText)\n    let treeElement = createDetailsTree(treeData)\n    this.appendChild(treeElement)\n  \n  fun createDetailsTree(nodes) =\n    let fragment = document.createDocumentFragment()\n    nodes Iter.each of node =>\n      let details = document.createElement(\"details\")\n      details.setAttribute(\"open\", \"\")\n      let summary = document.createElement(\"summary\")\n      set summary.textContent = node.text\n      details.appendChild of summary\n      if node.children.length > 0 then\n        details.appendChild of createDetailsTree(node.children)\n      else\n        details.setAttribute(\"leaf\" ,\"\")\n      fragment.appendChild of details\n      let rule = document.createElement(\"rule\")\n      rule.classList.add(\"rule\")\n      fragment.appendChild of rule\n    fragment\n\ncustomElements.define of \"collapsible-tree\", CollapsibleTree\n\nclass ErrorDisplay extends HTMLElement with\n  this.attachShadow(mode: \"open\")\n  \n  let _error = None\n  \n  fun connectedCallback() = this.render()\n  \n  fun setError(value) =\n    set _error = Some(value)\n    this.render()\n  \n  fun render() = if _error is Some(error) do\n    let stackLines = error.stack.split(\"\\n\")\n    if stackLines.[0].startsWith(error.name) do\n      stackLines.shift()\n    set this.shadowRoot.innerHTML = elem(\"div\", \"class\": \"error-container\") of\n      elem(\"h3\", \"class\": \"error-message\") of\n        error.name + \": \" + error.message\n      elem(\"ul\", \"class\": \"stack-trace\") of\n        stackLines\n          Iter.mapping of line => elem(\"li\") of line.trim()\n          Iter.joined(\"\")\n      elem(\"style\") of errorDisplayStyle\n\ncustomElements.define of \"error-display\", ErrorDisplay\n\nfun makeFigures(entries) = entries\n  Iter.mapping of case [name, svg] then\n    elem(\"figure\") of elem(\"figcaption\")(name), svg\n  Iter.joined(\"\")\n\nfun displayRules() =\n  open ParseRuleVisualizer\n  open Rules\n  reset()\n  set query(\"#syntax-diagrams>main\").innerHTML = StrOps.concat of\n    elem(\"h3\") of \"Term\"\n    makeFigures of render(railroad, \"term\", termRule)\n    elem(\"h3\") of \"Type\"\n    makeFigures of render(railroad, \"term\", typeRule)\n    elem(\"h3\") of \"Definition\"\n    makeFigures of render(railroad, \"term\", declRule)\n    elem(\"h3\") of \"Extension\"\n    extendedKinds\n      Iter.mapping of kindName =>\n        makeFigures of render(railroad, kindName, getRuleByKind(kindName))\n      Iter.joined(\"\")\n\ndisplayRules()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/cpp/Makefile",
    "content": "CXX := g++\nCFLAGS += -O3 -Wall -Wextra -std=c++20 -I. -Wno-inconsistent-missing-override -I/opt/homebrew/include\nLDFLAGS += -L/opt/homebrew/lib\nLDLIBS := -lmimalloc -lgmp\nSRC :=\nINCLUDES := mlsprelude.h\nDST :=\nDEFAULT_TARGET := mls\nTARGET := $(or $(DST),$(DEFAULT_TARGET))\n\n.PHONY: pre all run clean auto\n\nall: $(TARGET)\n\nrun: $(TARGET) \n\t./$(TARGET)\n\npre: $(SRC)\n\tsed -i '' 's#^//│ ##g' $(SRC)\n\nclean:\n\trm -r $(TARGET) $(TARGET).dSYM\n\nauto: $(TARGET)\n\n$(TARGET): $(SRC) $(INCLUDES)\n\t$(CXX) $(CFLAGS) $(LDFLAGS) mlsaux.cxx $(SRC) $(LDLIBS) -o $(TARGET)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/cpp/mlsaux.cxx",
    "content": "#include \"mlsprelude.h\"\n\n#include <mimalloc.h>\n#include <mimalloc-new-delete.h>\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/cpp/mlsprelude.h",
    "content": "#include <cassert>\n#include <cinttypes>\n#include <cstdint>\n#include <cstdio>\n#include <cstdlib>\n#include <limits>\n#include <new>\n#include <pthread.h>\n#include <stdexcept>\n#include <string>\n#include <string_view>\n#include <sys/resource.h>\n#include <tuple>\n#include <utility>\n\nconstexpr std::size_t _mlsAlignment = 8;\n\ntemplate <typename T, size_t N> class tuple_type {\n  template <typename = std::make_index_sequence<N>> struct impl;\n  template <size_t... Is> struct impl<std::index_sequence<Is...>> {\n    template <size_t> using wrap = T;\n    using type = std::tuple<wrap<Is>...>;\n  };\n\npublic:\n  using type = typename impl<>::type;\n};\ntemplate <auto Id> struct counter {\n  using tag = counter;\n\n  struct generator {\n    friend consteval auto is_defined(tag) { return true; }\n  };\n  friend consteval auto is_defined(tag);\n\n  template <typename Tag = tag, auto = is_defined(Tag{})>\n  static consteval auto exists(auto) {\n    return true;\n  }\n\n  static consteval auto exists(...) { return generator(), false; }\n};\n\ntemplate <auto Id = int{}, typename = decltype([] {})>\nconsteval auto nextTypeTag() {\n  if constexpr (not counter<Id>::exists(Id))\n    return Id;\n  else\n    return nextTypeTag<Id + 1>();\n}\n\nconstexpr static inline uint32_t unitTag = nextTypeTag();\nconstexpr static inline uint32_t floatTag = nextTypeTag();\nconstexpr static inline uint32_t strTag = nextTypeTag();\nconstexpr static inline uint32_t lazyTag = nextTypeTag();\n\nstruct _mlsObject {\n  uint32_t refCount;\n  uint32_t tag;\n  constexpr static inline uint32_t stickyRefCount =\n      std::numeric_limits<decltype(refCount)>::max();\n\n  void incRef() {\n    if (refCount != stickyRefCount)\n      ++refCount;\n  }\n  bool decRef() {\n    if (refCount != stickyRefCount && --refCount == 0)\n      return true;\n    return false;\n  }\n\n  virtual void print() const = 0;\n  virtual void destroy() = 0;\n};\n\n#define BOOST_STACKTRACE_GNU_SOURCE_NOT_REQUIRED\n#include <boost/stacktrace.hpp>\n\nclass _mlsUtil {\npublic:\n  [[noreturn]] static void panic(const char *msg) {\n    std::fprintf(stderr, \"Panic: %s\\n\", msg);\n    std::string st =\n        boost::stacktrace::to_string(boost::stacktrace::stacktrace());\n    std::fprintf(stderr, \"%s\\n\", st.c_str());\n    std::abort();\n  }\n  [[noreturn]] static void panic_with(const char *msg, const char *func,\n                                      const char *file, int line) {\n    std::fprintf(stderr, \"Panic: %s at %s %s:%d\\n\", msg, func, file, line);\n    std::string st =\n        boost::stacktrace::to_string(boost::stacktrace::stacktrace());\n    std::fprintf(stderr, \"%s\\n\", st.c_str());\n    std::abort();\n  }\n};\n\n#define _mls_assert(e)                                                         \\\n  (__builtin_expect(!(e), 0)                                                   \\\n       ? _mlsUtil::panic_with(\"assertion failed\", __func__,                    \\\n                              __FILE__, __LINE__)                              \\\n       : (void)0)\n\nstruct _mlsFloatShape : public _mlsObject {\n  double f;\n};\n\nclass _mlsValue {\n  using uintptr_t = std::uintptr_t;\n  using intptr_t = std::intptr_t;\n  using int64_t = std::int64_t;\n\n  void *value;\n\n  bool isInt63() const { return (reinterpret_cast<uintptr_t>(value) & 1) == 1; }\n\n  bool isFloat() const { return isPtr() && asObject()->tag == floatTag; }\n\n  bool isPtr() const { return (reinterpret_cast<uintptr_t>(value) & 1) == 0; }\n\n  int64_t asInt63() const { return reinterpret_cast<intptr_t>(value) >> 1; }\n\n  uintptr_t asRawInt() const { return reinterpret_cast<uintptr_t>(value); }\n\n  static _mlsValue fromRawInt(uintptr_t i) {\n    return _mlsValue(reinterpret_cast<void *>(i));\n  }\n\n  static _mlsValue fromInt63(int64_t i) {\n    return _mlsValue(reinterpret_cast<void *>((i << 1) | 1));\n  }\n\n  void *asPtr() const {\n    _mls_assert(!isInt63());\n    return value;\n  }\n\n  _mlsObject *asObject() const {\n    _mls_assert(isPtr());\n    return static_cast<_mlsObject *>(value);\n  }\n\n  bool eqInt63(const _mlsValue &other) const {\n    return asRawInt() == other.asRawInt();\n  }\n\n  _mlsValue addInt63(const _mlsValue &other) const {\n    return fromRawInt(asRawInt() + other.asRawInt() - 1);\n  }\n\n  _mlsValue subInt63(const _mlsValue &other) const {\n    return fromRawInt(asRawInt() - other.asRawInt() + 1);\n  }\n\n  _mlsValue mulInt63(const _mlsValue &other) const {\n    return fromInt63(asInt63() * other.asInt63());\n  }\n\n  _mlsValue divInt63(const _mlsValue &other) const {\n    return fromInt63(asInt63() / other.asInt63());\n  }\n\n  _mlsValue modInt63(const _mlsValue &other) const {\n    return fromInt63(asInt63() % other.asInt63());\n  }\n\n  _mlsValue gtInt63(const _mlsValue &other) const {\n    return fromBoolLit(asInt63() > other.asInt63());\n  }\n\n  _mlsValue ltInt63(const _mlsValue &other) const {\n    return fromBoolLit(asInt63() < other.asInt63());\n  }\n\n  _mlsValue geInt63(const _mlsValue &other) const {\n    return fromBoolLit(asInt63() >= other.asInt63());\n  }\n\n  _mlsValue leInt63(const _mlsValue &other) const {\n    return fromBoolLit(asInt63() <= other.asInt63());\n  }\n\n  _mlsValue minInt63(const _mlsValue &other) const {\n    int64_t a = asInt63();\n    int64_t b = other.asInt63();\n    return fromInt63(a < b ? a : b);\n  }\n\n  _mlsValue maxInt63(const _mlsValue &other) const {\n    int64_t a = asInt63();\n    int64_t b = other.asInt63();\n    return fromInt63(a > b ? a : b);\n  }\n\n  _mlsValue absInt63() const {\n    int64_t a = asInt63();\n    return fromInt63(a < 0 ? -a : a);\n  }\n\n  _mlsValue floorDivInt63(const _mlsValue &other) const {\n    int64_t a = asInt63();\n    int64_t b = other.asInt63();\n    int64_t q = a / b;\n    int64_t r = a % b;\n    if ((r > 0 && b < 0) || (r < 0 && b > 0))\n      q = q - 1;\n    return fromInt63(q);\n  }\n\n  _mlsValue floorModInt63(const _mlsValue &other) const {\n    int64_t a = asInt63();\n    int64_t b = other.asInt63();\n    long r = a % b;\n    if ((r > 0 && b < 0) || (r < 0 && b > 0))\n      r = r + b;\n    return fromInt63(r);\n  }\n\npublic:\n  struct inc_ref_tag {};\n  explicit _mlsValue() : value(nullptr) {}\n  explicit _mlsValue(void *value) : value(value) {}\n  explicit _mlsValue(void *value, inc_ref_tag) : value(value) {\n    if (isPtr())\n      asObject()->incRef();\n  }\n  _mlsValue(const _mlsValue &other) : value(other.value) {\n    if (isPtr())\n      asObject()->incRef();\n  }\n\n  _mlsValue &operator=(const _mlsValue &other) {\n    if (value != nullptr && isPtr())\n      asObject()->decRef();\n    value = other.value;\n    if (isPtr())\n      asObject()->incRef();\n    return *this;\n  }\n\n  ~_mlsValue() {\n    if (isPtr())\n      if (asObject()->decRef()) {\n        asObject()->destroy();\n        value = nullptr;\n      }\n  }\n\n  int64_t asInt() const {\n    _mls_assert(isInt63());\n    return asInt63();\n  }\n\n  static _mlsValue fromIntLit(int64_t i) { return fromInt63(i); }\n\n  static _mlsValue fromBoolLit(bool b) { return fromInt63(b); }\n\n  template <unsigned N> static tuple_type<_mlsValue, N> never() {\n    __builtin_unreachable();\n  }\n  static _mlsValue never() { __builtin_unreachable(); }\n\n  template <typename T, typename... U> static _mlsValue create(U... args) {\n    return _mlsValue(T::create(args...));\n  }\n\n  static void destroy(_mlsValue &v) { v.~_mlsValue(); }\n\n  template <typename T> static bool isValueOf(const _mlsValue &v) {\n    return v.asObject()->tag == T::typeTag;\n  }\n\n  static bool isIntLit(const _mlsValue &v, int64_t n) {\n    return v.asInt63() == n;\n  }\n\n  static bool isInt(const _mlsValue &v) { return v.isInt63(); }\n\n  template <typename T> static T *as(const _mlsValue &v) {\n    return dynamic_cast<T *>(v.asObject());\n  }\n\n  template <typename T> static T *cast(_mlsValue &v) {\n    return static_cast<T *>(v.asObject());\n  }\n\n  _mlsValue floorDiv(const _mlsValue &other) const;\n\n  _mlsValue floorMod(const _mlsValue &other) const;\n\n  _mlsValue pow(const _mlsValue &other) const;\n\n  _mlsValue abs() const;\n\n  // Operators\n\n  _mlsValue operator==(const _mlsValue &other) const;\n\n  _mlsValue operator!=(const _mlsValue &other) const;\n\n  _mlsValue operator&&(const _mlsValue &other) const;\n\n  _mlsValue operator||(const _mlsValue &other) const;\n\n  _mlsValue operator+(const _mlsValue &other) const;\n\n  _mlsValue operator-(const _mlsValue &other) const;\n\n  _mlsValue operator-() const;\n\n  _mlsValue operator*(const _mlsValue &other) const;\n\n  _mlsValue operator/(const _mlsValue &other) const;\n\n  _mlsValue operator%(const _mlsValue &other) const;\n\n  _mlsValue operator>(const _mlsValue &other) const;\n\n  _mlsValue operator<(const _mlsValue &other) const;\n\n  _mlsValue operator>=(const _mlsValue &other) const;\n\n  _mlsValue operator<=(const _mlsValue &other) const;\n\n  // Auxiliary functions\n\n  void print() const {\n    if (isInt63())\n      std::printf(\"%\" PRIu64, asInt63());\n    else if (isPtr() && asObject())\n      asObject()->print();\n  }\n};\n\nstruct _mls_Callable : public _mlsObject {\n  virtual _mlsValue _mls_apply0() {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual _mlsValue _mls_apply1(_mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual _mlsValue _mls_apply2(_mlsValue, _mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual _mlsValue _mls_apply3(_mlsValue, _mlsValue, _mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual _mlsValue _mls_apply4(_mlsValue, _mlsValue, _mlsValue, _mlsValue) {\n    throw std::runtime_error(\"Not implemented\");\n  }\n  virtual void destroy() override {}\n};\n\ninline static _mls_Callable *_mlsToCallable(_mlsValue fn) {\n  auto *ptr = _mlsValue::as<_mls_Callable>(fn);\n  if (!ptr)\n    throw std::runtime_error(\"Not a callable object\");\n  return ptr;\n}\n\ntemplate <typename... U>\ninline static _mlsValue _mlsCall(_mlsValue f, U... args) {\n  static_assert(sizeof...(U) <= 4, \"Too many arguments\");\n  if constexpr (sizeof...(U) == 0)\n    return _mlsToCallable(f)->_mls_apply0();\n  else if constexpr (sizeof...(U) == 1)\n    return _mlsToCallable(f)->_mls_apply1(args...);\n  else if constexpr (sizeof...(U) == 2)\n    return _mlsToCallable(f)->_mls_apply2(args...);\n  else if constexpr (sizeof...(U) == 3)\n    return _mlsToCallable(f)->_mls_apply3(args...);\n  else if constexpr (sizeof...(U) == 4)\n    return _mlsToCallable(f)->_mls_apply4(args...);\n}\n\ntemplate <typename T> inline static T *_mlsMethodCall(_mlsValue self) {\n  auto *ptr = _mlsValue::as<T>(self);\n  if (!ptr)\n    throw std::runtime_error(\"unable to convert object for method calls\");\n  return ptr;\n}\n\ninline int _mlsLargeStack(void *(*fn)(void *)) {\n  pthread_t thread;\n  pthread_attr_t attr;\n\n  size_t stacksize = 1024 * 1024 * 1024;\n  pthread_attr_init(&attr);\n  pthread_attr_setstacksize(&attr, stacksize);\n\n  int rc = pthread_create(&thread, &attr, fn, nullptr);\n  if (rc) {\n    printf(\"ERROR: return code from pthread_create() is %d\\n\", rc);\n    return 1;\n  }\n  pthread_join(thread, NULL);\n  return 0;\n}\n\n_mlsValue _mlsMain();\n\ninline void *_mlsMainWrapper(void *) {\n  _mlsValue res = _mlsMain();\n  res.print();\n  return nullptr;\n}\n\nstruct _mls_Unit final : public _mlsObject {\n  constexpr static inline const char *typeName = \"Unit\";\n  constexpr static inline uint32_t typeTag = unitTag;\n  virtual void print() const override { std::printf(typeName); }\n  static _mlsValue create() {\n    static _mls_Unit mlsUnit alignas(_mlsAlignment);\n    mlsUnit.refCount = stickyRefCount;\n    mlsUnit.tag = typeTag;\n    return _mlsValue(&mlsUnit);\n  }\n  virtual void destroy() override {}\n};\n\nstruct _mls_Float final : public _mlsFloatShape {\n  constexpr static inline const char *typeName = \"Float\";\n  constexpr static inline uint32_t typeTag = floatTag;\n  virtual void print() const override {\n    std::printf(typeName);\n    std::printf(\"(\");\n    std::printf(\"%f\", f);\n    std::printf(\")\");\n  }\n  static _mlsValue create(double f) {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Float;\n    _mlsVal->f = f;\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    return _mlsValue(_mlsVal);\n  }\n  _mlsValue operator+(const _mls_Float &other) const {\n    return _mlsValue::create<_mls_Float>(f + other.f);\n  }\n  _mlsValue operator-(const _mls_Float &other) const {\n    return _mlsValue::create<_mls_Float>(f - other.f);\n  }\n  _mlsValue operator*(const _mls_Float &other) const {\n    return _mlsValue::create<_mls_Float>(f * other.f);\n  }\n  _mlsValue operator/(const _mls_Float &other) const {\n    return _mlsValue::create<_mls_Float>(f / other.f);\n  }\n  _mlsValue operator==(const _mls_Float &other) const {\n    return _mlsValue::fromBoolLit(f == other.f);\n  }\n  _mlsValue operator!=(const _mls_Float &other) const {\n    return _mlsValue::fromBoolLit(f == other.f);\n  }\n  _mlsValue operator>(const _mls_Float &other) const {\n    return _mlsValue::fromBoolLit(f > other.f);\n  }\n  _mlsValue operator<(const _mls_Float &other) const {\n    return _mlsValue::fromBoolLit(f < other.f);\n  }\n  _mlsValue operator>=(const _mls_Float &other) const {\n    return _mlsValue::fromBoolLit(f >= other.f);\n  }\n  _mlsValue operator<=(const _mls_Float &other) const {\n    return _mlsValue::fromBoolLit(f <= other.f);\n  }\n  virtual void destroy() override {\n    operator delete(this, std::align_val_t(_mlsAlignment));\n  }\n};\n\nstruct _mls_Str final : public _mlsObject {\n  std::string str;\n  constexpr static inline const char *typeName = \"Str\";\n  constexpr static inline uint32_t typeTag = strTag;\n  virtual void print() const override {\n    std::printf(\"\\\"\");\n    for (const auto c : str) {\n      switch (c) {\n      case '\\'':\n        std::printf(\"\\\\\\'\");\n        break;\n      case '\\\"':\n        std::printf(\"\\\\\\\"\");\n        break;\n      case '\\?':\n        std::printf(\"\\\\\\?\");\n        break;\n      case '\\\\':\n        std::printf(\"\\\\\\\\\");\n        break;\n      case '\\a':\n        std::printf(\"\\\\a\");\n        break;\n      case '\\b':\n        std::printf(\"\\\\b\");\n        break;\n      case '\\f':\n        std::printf(\"\\\\f\");\n        break;\n      case '\\n':\n        std::printf(\"\\\\n\");\n        break;\n      case '\\r':\n        std::printf(\"\\\\r\");\n        break;\n      case '\\t':\n        std::printf(\"\\\\t\");\n        break;\n      case '\\v':\n        std::printf(\"\\\\v\");\n        break;\n      default:\n        if (c < 32 || c > 126)\n          std::printf(\"\\\\x%02x\", c);\n        else\n          std::putchar(c);\n      }\n    }\n    std::printf(\"\\\"\");\n    std::fflush(stdout);\n  }\n  static _mlsValue create(const std::string_view str) {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Str;\n    _mlsVal->str = str;\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    return _mlsValue(_mlsVal);\n  }\n  static _mlsValue create(const std::string_view str1,\n                          const std::string_view str2) {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Str;\n    _mlsVal->str = str1;\n    _mlsVal->str += str2;\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    return _mlsValue(_mlsVal);\n  }\n  virtual void destroy() override {\n    str.~basic_string();\n    operator delete(this, std::align_val_t(_mlsAlignment));\n  }\n};\n\nstruct _mls_Lazy final : public _mlsObject {\n  _mlsValue init;\n  _mlsValue value;\n  bool evaluated;\n  constexpr static inline const char *typeName = \"Lazy\";\n  constexpr static inline uint32_t typeTag = lazyTag;\n  virtual void print() const override { std::printf(typeName); }\n  static _mlsValue create(_mlsValue init) {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_Lazy;\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    _mlsVal->init = init;\n    _mlsVal->value = _mlsValue::create<_mls_Unit>();\n    _mlsVal->evaluated = false;\n    return _mlsValue(_mlsVal);\n  }\n  virtual void destroy() override {\n    _mlsValue::destroy(init);\n    _mlsValue::destroy(value);\n    operator delete(this, std::align_val_t(_mlsAlignment));\n  }\n  _mlsValue _mls_get() {\n    if (!evaluated) {\n      value = _mlsCall(init);\n      evaluated = true;\n    }\n    return value;\n  }\n};\n\n#include <boost/multiprecision/gmp.hpp>\n\nstruct _mls_ZInt final : public _mlsObject {\n  boost::multiprecision::mpz_int z;\n  constexpr static inline const char *typeName = \"Z\";\n  constexpr static inline uint32_t typeTag = nextTypeTag();\n  virtual void print() const override {\n    std::printf(typeName);\n    std::printf(\"(\");\n    std::printf(\"%s\", z.str().c_str());\n    std::printf(\")\");\n  }\n  virtual void destroy() override {\n    z.~number();\n    operator delete(this, std::align_val_t(_mlsAlignment));\n  }\n  static _mlsValue create() {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_ZInt;\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    return _mlsValue(_mlsVal);\n  }\n  static _mlsValue create(_mlsValue z) {\n    auto _mlsVal = new (std::align_val_t(_mlsAlignment)) _mls_ZInt;\n    _mlsVal->z = z.asInt();\n    _mlsVal->refCount = 1;\n    _mlsVal->tag = typeTag;\n    return _mlsValue(_mlsVal);\n  }\n  _mlsValue operator+(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z + other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator-(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z - other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator*(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z * other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator/(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z / other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator%(const _mls_ZInt &other) const {\n    auto _mlsVal = _mlsValue::create<_mls_ZInt>();\n    _mlsValue::cast<_mls_ZInt>(_mlsVal)->z = z % other.z;\n    return _mlsVal;\n  }\n\n  _mlsValue operator==(const _mls_ZInt &other) const {\n    return _mlsValue::fromBoolLit(z == other.z);\n  }\n\n  _mlsValue operator>(const _mls_ZInt &other) const {\n    return _mlsValue::fromBoolLit(z > other.z);\n  }\n\n  _mlsValue operator<(const _mls_ZInt &other) const {\n    return _mlsValue::fromBoolLit(z < other.z);\n  }\n\n  _mlsValue operator>=(const _mls_ZInt &other) const {\n    return _mlsValue::fromBoolLit(z >= other.z);\n  }\n\n  _mlsValue operator<=(const _mls_ZInt &other) const {\n    return _mlsValue::fromBoolLit(z <= other.z);\n  }\n\n  _mlsValue toInt() const {\n    return _mlsValue::fromIntLit(z.convert_to<int64_t>());\n  }\n\n  static _mlsValue fromInt(int64_t i) {\n    return _mlsValue::create<_mls_ZInt>(_mlsValue::fromIntLit(i));\n  }\n};\n\n[[noreturn, gnu::noinline]] inline void _mlsNonExhaustiveMatch() {\n  _mlsUtil::panic(\"Non-exhaustive match\");\n}\n\ninline _mlsValue _mls_builtin_pow(_mlsValue a, _mlsValue b) { return a.pow(b); }\n\ninline _mlsValue _mls_builtin_abs(_mlsValue a) { return a.abs(); }\n\ninline _mlsValue _mls_builtin_floor_div(_mlsValue a, _mlsValue b) {\n  return a.floorDiv(b);\n}\n\ninline _mlsValue _mls_builtin_floor_mod(_mlsValue a, _mlsValue b) {\n  return a.floorMod(b);\n}\n\ninline _mlsValue _mls_builtin_trunc_div(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isInt(a));\n  _mls_assert(_mlsValue::isInt(b));\n  return a / b;\n}\n\ninline _mlsValue _mls_builtin_trunc_mod(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isInt(a));\n  _mls_assert(_mlsValue::isInt(b));\n  return a % b;\n}\n\ninline _mlsValue _mls_builtin_int2str(_mlsValue a) {\n  _mls_assert(_mlsValue::isInt(a));\n  char buf[32];\n  std::snprintf(buf, sizeof(buf), \"%\" PRIu64, a.asInt());\n  return _mlsValue::create<_mls_Str>(buf);\n}\n\ninline _mlsValue _mls_builtin_float2str(_mlsValue a) {\n  _mls_assert(_mlsValue::isValueOf<_mls_Float>(a));\n  char buf[128];\n  std::snprintf(buf, sizeof(buf), \"%f\", _mlsValue::cast<_mls_Float>(a)->f);\n  return _mlsValue::create<_mls_Str>(buf);\n}\n\ninline _mlsValue _mls_builtin_int2float(_mlsValue a) {\n  return _mlsValue::create<_mls_Float>(a.asInt());\n}\n\ninline _mlsValue _mls_builtin_str_concat(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_Str>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_Str>(b));\n  auto *strA = _mlsValue::cast<_mls_Str>(a);\n  auto *strB = _mlsValue::cast<_mls_Str>(b);\n  return _mlsValue::create<_mls_Str>(strA->str.c_str(), strB->str.c_str());\n}\n\ninline _mlsValue _mls_builtin_z_add(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) + *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_sub(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) - *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_mul(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) * *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_div(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) / *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_mod(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) % *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_equal(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) == *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_gt(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) > *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_lt(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) < *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_geq(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) >= *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_leq(_mlsValue a, _mlsValue b) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(b));\n  return *_mlsValue::cast<_mls_ZInt>(a) <= *_mlsValue::cast<_mls_ZInt>(b);\n}\n\ninline _mlsValue _mls_builtin_z_to_int(_mlsValue a) {\n  _mls_assert(_mlsValue::isValueOf<_mls_ZInt>(a));\n  return _mlsValue::cast<_mls_ZInt>(a)->toInt();\n}\n\ninline _mlsValue _mls_builtin_z_of_int(_mlsValue a) {\n  _mls_assert(_mlsValue::isInt(a));\n  return _mlsValue::create<_mls_ZInt>(a);\n}\n\ninline _mlsValue _mls_builtin_print(_mlsValue a) {\n  a.print();\n  return _mlsValue::create<_mls_Unit>();\n}\n\ninline _mlsValue _mls_builtin_println(_mlsValue a) {\n  a.print();\n  std::puts(\"\");\n  return _mlsValue::create<_mls_Unit>();\n}\n\ninline _mlsValue _mls_builtin_debug(_mlsValue a) {\n  a.print();\n  std::puts(\"\");\n  return a;\n}\n\ninline _mlsValue _mlsValue::floorDiv(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return floorDivInt63(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::floorMod(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return floorModInt63(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::pow(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return fromInt63(std::pow(asInt63(), other.asInt63()));\n  if (isFloat() && other.isFloat())\n    return _mlsValue::create<_mls_Float>(\n        std::pow(as<_mls_Float>(*this)->f, as<_mls_Float>(other)->f));\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::abs() const {\n  if (isInt63())\n    return absInt63();\n  if (isFloat())\n    return _mlsValue::create<_mls_Float>(std::abs(as<_mls_Float>(*this)->f));\n  _mls_assert(false);\n}\n\n// Operators\n\ninline _mlsValue _mlsValue::operator==(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return _mlsValue::fromBoolLit(eqInt63(other));\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) == *as<_mls_Float>(other);\n  bool sameTag =\n      isPtr() && other.isPtr() && asObject()->tag == other.asObject()->tag;\n  if (!sameTag)\n    return _mlsValue::fromBoolLit(false);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator!=(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return _mlsValue::fromBoolLit(!eqInt63(other));\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) != *as<_mls_Float>(other);\n  bool sameTag =\n      isPtr() && other.isPtr() && asObject()->tag == other.asObject()->tag;\n  if (!sameTag)\n    return _mlsValue::fromBoolLit(true);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator&&(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return _mlsValue::fromBoolLit(asInt63() && other.asInt63());\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator||(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return _mlsValue::fromBoolLit(asInt63() || other.asInt63());\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator+(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return addInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) + *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator-(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return subInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) - *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator-() const {\n  if (isInt63())\n    return fromInt63(-asInt63());\n  if (isFloat())\n    return _mlsValue::create<_mls_Float>(-as<_mls_Float>(*this)->f);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator*(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return mulInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) * *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator/(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return divInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) / *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator%(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return modInt63(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator>(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return gtInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) > *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator<(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return ltInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) < *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator>=(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return geInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) >= *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n\ninline _mlsValue _mlsValue::operator<=(const _mlsValue &other) const {\n  if (isInt63() && other.isInt63())\n    return leInt63(other);\n  if (isFloat() && other.isFloat())\n    return *as<_mls_Float>(*this) <= *as<_mls_Float>(other);\n  _mls_assert(false);\n}\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/NofibPrelude.mls",
    "content": "import \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen Predef\n\nmodule NofibPrelude with ...\ntype Char = String\n\nabstract class Option[out T]: Some[T] | None\ndata class Some[out T](x: T) extends Option[T]\nobject None extends Option\n\nfun fromSome(s) = if s is Some(x) then x\n\ndata class Lazy[out A](init: () -> A) with\n  mut val cached: Option[A] = None\n  fun get() =\n    if cached is\n      Some(v) then v\n      else\n        let v = init()\n        set cached = Some(v)\n        v\nfun lazy(x) = Lazy(x)\nfun force(x) = if x is Lazy then x.Lazy#get()\n\n\nabstract class List[out T]: Cons[T] | Nil\ndata class (::) Cons[out T](head: T, tail: List[T]) extends List[T] with\n  fun toString() =\n    \"[\" + _internal_cons_to_str(Cons(head, tail)) + \"]\"\nobject Nil extends List with\n  fun toString() = \"[]\"\nfun _internal_cons_to_str(ls) = if ls is\n  Nil then \"\"\n  h :: Nil then render(h)\n  h :: t then render(h) + \",\" + _internal_cons_to_str(t)\nfun ltList(xs, ys, lt, gt) = if xs is\n  Nil and\n    ys is Nil then false\n    else true\n  x :: xs and ys is\n    Nil then false\n    y :: ys and\n      lt(x, y) then true\n      gt(x, y) then false\n      else ltList(xs, ys, lt, gt)\nfun list(...args) = if args is\n  [] then Nil\n  [x, ...xs] then x :: list(...xs)\n\ntype LazyList[out T] = Lazy[LzList[T]]\nabstract class LzList[out T]: LzCons[T] | LzNil\ndata class LzCons[out T](head: T, tail: LazyList[T]) extends LzList[T]\nobject LzNil extends LzList\n\nfun ltTup2(t1, t2, lt1, gt1, lt2) = if t1 is [a, b] and t2 is [c, d] and\n  lt1(a, c) then true\n  gt1(a, c) then false\n  else lt2(b, d)\nfun eqTup2(t1, t2) = if t1 is [a, b] and t2 is [c, d] then a == c and b == d\n\nfun compose(f, g) = x => f(g(x))\n\nfun snd(x) = if x is [f, s] then s\nfun fst(x) = if x is [f, s] then f\n\nfun until(p, f, i) = if p(i) then i else until(p, f, f(i))\n\nfun flip(f, x, y) = f(y)(x)\n\nfun power(a, n) = globalThis.Math.pow(a, n)\n\nfun intDiv(a, b) = globalThis.Math.floor(a / b)\nfun intQuot(a, b) = globalThis.Math.trunc(a / b)\n\nfun intMod(a, b) = a - (b * intDiv(a, b))\nfun intRem(a, b) = a - (b * intQuot(a, b))\n\nfun quotRem(a, b) = [intQuot(a, b), intRem(a, b)]\nfun divMod(a, b) = [intDiv(a, b), intMod(a, b)]\n\nfun max(a, b) = globalThis.Math.max(a, b)\nfun min(a, b) = globalThis.Math.min(a, b)\n\nfun abs(x) = globalThis.Math.abs(x)\n\nfun head(l) = if l is h :: t then h\nfun tail(l) = if l is h :: t then t\n\nfun while_(p, f, x) = if p(x) then while_(p, f, f(x)) else x\n\nfun reverse(l) =\n  fun r(l', l) = if l is x :: xs then r(x :: l', xs) else l'\n  r(Nil, l)\n\nfun map(f, xs) = if xs is\n  x :: xs then f(x) :: map(f, xs)\n  Nil then Nil\n\nfun listLen(ls) =\n  fun l(ls, a) = if ls is\n    Nil then a\n    h :: t then l(t, a + 1)\n  l(ls, 0)\n\nfun listEq(xs, ys) = if\n  xs is Nil and ys is Nil then true\n  xs is hx :: tx and ys is hy :: ty and (hx == hy) then listEq(tx, ty)\n  else false\n\nfun listEqBy(f, a, b) = if a is\n  Nil and b is Nil then true\n  x :: xs and b is y :: ys then f(x, y) && listEqBy(f, xs, ys)\n  else false\n\nfun listNeq(xs, ys) = if\n  xs is Nil and ys is Nil then false\n  xs is hx :: tx and ys is hy :: ty and (hx == hy) then listNeq(tx, ty)\n  else true\n\nfun enumFromTo(a, b) = if a <= b then a :: enumFromTo(a + 1, b) else Nil\n\nfun enumFromThenTo(a, t, b) = if a <= b then a :: enumFromThenTo(t, 2 * t - a, b) else Nil\n\nfun leave(n, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    n <= 0 then ls\n    else leave(n - 1, t)\n\nfun take(n, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    n <= 0 then Nil\n    else h :: take(n - 1, t)\n\nfun splitAt(n, ls) = [take(n, ls), leave(n, ls)]\n\nfun zip(xs, ys) = if xs is\n  x :: xs and ys is y :: ys then [x, y] :: zip(xs, ys)\n  else Nil\n\nfun inList(x, ls) = if ls is\n  h :: t and\n    x === h then true\n    else inList(x, t)\n  Nil then false\n\nfun notElem(x, ls) = not(inList(x, ls))\n\nfun (+:) append(xs, ys) = if xs is\n  Nil then ys\n  x :: xs then x :: append(xs, ys)\n\nfun concat(ls) = if ls is\n  Nil then Nil\n  x :: xs then append(x, concat(xs))\n\nfun filter(f, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    f(h) then h :: filter(f, t)\n    else filter(f, t)\n\nfun all(p, ls) = if ls is\n  Nil then true\n  h :: t and\n    p(h) then all(p, t)\n    else false\n\nfun orList(ls) = if ls is\n  Nil then false\n  h :: t and\n    h then true\n    else orList(t)\n\nfun leaveWhile(f, ls) = if ls is\n  Nil then Nil\n  h :: t and\n    f(h) then leaveWhile(f, t)\n    else h :: t\n\nfun foldl(f, a, xs) = if xs is\n  Nil then a\n  h :: t then foldl(f, f(a, h), t)\n\nfun scanl(f, q, ls) = if ls is\n  Nil then q :: Nil\n  x :: xs then q :: scanl(f, f(q, x), xs)\n\nfun scanr(f, q, ls) = if ls is\n  Nil then q :: Nil\n  x :: xs and scanr(f, q, xs) is q :: t then f(x, q) :: q :: t\n\nfun foldr(f, z, xs) = if xs is\n  Nil then z\n  h :: t then f(h, foldr(f, z, t))\n\nfun foldl1(f, ls) = if\n  ls is x :: xs then foldl(f, x, xs)\n\nfun foldr1(f, ls) = if ls is\n  x :: Nil then x\n  x :: xs then f(x, foldr1(f, xs))\n\nfun maximum(xs) = foldl1((x, y) => if x > y then x else y, xs)\n\nfun nubBy(eq, ls) = if ls is\n  Nil then Nil\n  h :: t then h :: nubBy(eq, filter(y => not(eq(h, y)), t))\n\nfun zipWith(f, xss, yss) = if\n  xss is x :: xs and yss is y :: ys then f(x, y) :: zipWith(f, xs, ys)\n  else Nil\n\nfun deleteBy(eq, x, ys) = if ys is\n  Nil then Nil\n  y :: ys and\n    eq(x, y) then ys\n    else y :: deleteBy(eq, x, ys)\n\nfun unionBy(eq, xs, ys) = append(xs, foldl((acc, y) => deleteBy(eq, y, acc), nubBy(eq, ys), xs))\n\nfun union(xs, ys) = unionBy((x, y) => x == y, xs, ys)\n\nfun atIndex(i, ls) = if ls is\n  h :: t and\n    i == 0 then h\n    else atIndex(i - 1, t)\n\nfun sum(xs) =\n  fun go(xs, a) = if xs is\n    Nil then a\n    h :: t then go(t, a + h)\n  go(xs, 0)\n\nfun null_(ls) = if ls is\n  Nil then true\n  else false\n\nfun replicate(n, x) = if n == 0 then Nil else x :: replicate(n - 1, x)\n\nfun unzip(l) =\n  fun f(l, a, b) = if l is\n    Nil then [reverse(a), reverse(b)]\n    [x, y] :: t then f(t, x :: a,  y :: b)\n  f(l, Nil, Nil)\n\nfun zip3(xs, ys, zs) = if\n  xs is x :: xs and ys is y :: ys and zs is z :: zs then [x, y, z] :: zip3(xs, ys, zs)\n  else Nil\n\nfun transpose(xss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and h is\n      hd :: tl then [hd, tl] :: lscomp(t)\n      else lscomp(t)\n  fun combine(y, h, ys, t) = (y :: h) :: transpose(ys :: t)\n  if xss is\n    Nil then Nil\n    Nil :: xss then transpose(xss)\n    (x :: xs) :: xss and unzip(lscomp(xss)) is [hds, tls] then combine(x, hds, xs, tls)\n\nfun break_(p, ls) = if ls is\n  Nil then [Nil, Nil]\n  x :: xs and\n    p(x) then [Nil, x :: xs]\n    break_(p, xs) is [ys, zs] then [x :: ys, zs]\n\nfun flatMap(f, ls) = if ls is\n  Nil then Nil\n  h :: t then append(f(h), flatMap(f, t))\n\n// =====================\n\nfun map_lz(f, ls) = lazy of () =>\n  if force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) then LzCons(f(h), map_lz(f, t))\n\nfun filter_lz(p, ls) = lazy of () =>\n  if force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) and\n      p(h) then LzCons(h, filter_lz(p, t))\n      else force(filter_lz(p, t))\n\nfun nubBy_lz(eq, ls) = lazy of () =>\n  if force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) then LzCons(h, nubBy_lz(eq, filter_lz(y => not(eq(h, y)), t)))\n\nfun nub_lz(ls) = nubBy_lz((x, y) => x == y, ls)\n\nfun take_lz(n, ls) = if\n  n > 0 and force(ls) is\n    LzNil then Nil\n    LzCons(h, t) then h :: take_lz(n - 1, t)\n  else Nil\n\nfun take_lz_lz(n, ls) = lazy of () =>\n  if n > 0 and force(ls) is\n    LzNil then LzNil\n    LzCons(h, t) then LzCons(h, take_lz_lz(n - 1, t))\n  else LzNil\n\nfun leave_lz(n, ls) = if\n  n <= 0 then ls\n  force(ls) is\n    LzNil then lazy of () => LzNil\n    LzCons(h, t) then leave_lz(n - 1, t)\n\nfun splitAt_lz(n, ls) = [take_lz(n, ls), leave_lz(n, ls)]\n\nfun zip_lz_nl(xs, ys) = if\n  force(xs) is LzCons(x, xs) and ys is y :: ys then [x, y] :: zip_lz_nl(xs, ys)\n  else Nil\n\nfun zip_lz_lz(xs, ys) = if\n  force(xs) is LzCons(x, xs) and force(ys) is LzCons(y, ys) then lazy of () => LzCons([x, y], zip_lz_lz(xs, ys))\n  else lazy of () => LzNil\n\nfun zipWith_lz_lz(f, xss, yss) = lazy of () => if\n  force(xss) is LzCons(x, xs) and (force(yss)) is LzCons(y, ys) then LzCons(f(x, y), zipWith_lz_lz(f, xs, ys))\n  else LzNil\n\nfun zipWith_lz_nl(f, xss, yss) = if\n  force(xss) is LzCons(x, xs) and yss is y :: ys then f(x, y) :: zipWith_lz_nl(f, xs, ys)\n  else Nil\n\nfun iterate(f, x) = lazy of () => LzCons(x, iterate(f, f(x)))\n\nfun append_nl_lz(xs, ys) = if xs is\n  Nil then ys\n  h :: t then lazy of () => LzCons(h, append_nl_lz(t, ys))\n\nfun append_lz_lz(xs, ys) = lazy of () => if force(xs) is\n  LzNil then force(ys)\n  LzCons(h, t) then LzCons(h, append_lz_lz(t, ys))\n\nfun replicate_lz(n, x) = if n == 0 then lazy of () => LzNil else lazy of () => LzCons(x, replicate_lz(n - 1, x))\n\nfun enumFrom(a) = lazy of () => LzCons(a, enumFrom(a + 1))\n\nfun head_lz(ls) = if force(ls) is LzCons(h, t) then h\n\nfun repeat(x) = lazy of () => LzCons(x, repeat(x))\n// =====================\n\n\nfun stringOfFloat(x) = x + \"\"\nfun stringOfInt(x) = x + \"\"\nfun stringConcat(x, y) = x + y\nfun stringListConcat(ls) = if ls is\n  Nil then \"\"\n  h :: t then stringConcat(h, stringListConcat(t))\nfun sqrt(x) = globalThis.Math.sqrt(x)\nfun tan(x) = globalThis.Math.tan(x)\nfun sin(x) = globalThis.Math.sin(x)\nfun cos(x) = globalThis.Math.cos(x)\nfun round(x) = globalThis.Math.round(x)\nfun int_of_char(x) = x.charCodeAt(0)\nfun nofibStringToList(s) =\n  fun go(i) = if i < s.length then s.charAt(i) :: go(i + 1) else Nil\n  go(0)\nfun nofibListToString(ls) = if ls is\n  Nil then \"\"\n  h :: t then h + nofibListToString(t)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/ansi.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\nmodule ansi with ...\n\n\nval cls = nofibStringToList(\"L\")\n//│ cls = [\"L\"]\n\nfun goto(x, y) = \"E\" :: \"[\" :: (nofibStringToList(stringOfInt(y)) +: (\";\" :: nofibStringToList(stringOfInt(x)) +: nofibStringToList(\"H\")))\n\nfun at(x_y, s) = if x_y is [x, y] then goto(x, y) +: s\n\nfun highlight(s) = nofibStringToList(\"ESC[7m\") +: s +: nofibStringToList(\"ESC[0m\")\n\nfun end(xs) = nofibStringToList(\"\")\n\nfun readChar(eof, consume, cs) = if cs is\n  Nil then eof(Nil)\n  c :: cs then consume(c, cs)\n\nfun peekChar(eof, consume, cs) = if cs is\n  Nil then eof(Nil)\n  c :: cs then consume(c, c :: cs)\n\nfun pressAnyKey(prog, x) = readChar(prog, (c, x) => prog(x), x)\n\nfun unreadChar(c, prog, cs) = prog(c :: cs)\n\nfun writeChar(c, prog, cs) = c :: prog(cs)\n\nfun writeString(s, prog, cs) = s +: prog(cs)\n\nfun writes(ss, a, b) = writeString(concat(ss), a, b)\n\nfun ringBell(prog, cs) = writeChar(\"B\", prog, cs)\n\nfun clearScreen(a, b) = writeString(cls, a, b)\n\nfun writeAt(x_y, s, a) = if x_y is [x, y] then p => writeString(goto(x, y) +: s, a, p)\n\nfun moveTo(x_y, a) = if x_y is [x, y] then p => writeString(goto(x, y), a, p)\n\nfun returnn(s, consume) = consume(reverse(s))\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun deletee(n, s, l, consume, d) = if n > 0 then writeString(nofibStringToList(\"BS_BS\"), loop(n - 1, tail(s), l, consume), d) else ringBell(loop(0, nofibStringToList(\"\"), l, consume), d)\n\nfun loop(n, s, l, consume) = x => readChar of\n  returnn(s, consume)\n  (c, d) => if\n            c == \"B\" then deletee(n, s, l, consume, d) \n            c == \"D\" then deletee(n, s, l, consume, d)\n            c == \"`\" then returnn(s, consume)(d)\n            n < l then writeChar(c, loop(n + 1, c :: s, l, consume), d)\n            else ringBell(loop(n, s, l, consume), d)\n  x\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun readAt(x_y, l, consume) = writeAt(x_y, replicate(l, \"_\"), moveTo(x_y, loop(0, \"\", l, consume)))\n\nfun promptReadAt(x_y, l, prompt, consume) = if x_y is [x, y] then\n  writeAt([x, y], prompt, readAt([x + listLen(prompt), y], l, consume))\n\nfun program(input) = writes(\n  cls ::\n  at([17, 5], highlight(nofibStringToList(\"Demonstration program\"))) ::\n  at([48, 5], nofibStringToList(\"Version 1.0\")) ::\n  at([17, 7], nofibStringToList(\"This program illustrates a simple approach\")) ::\n  at([17, 8], nofibStringToList(\"to screen-based interactive programs using\")) ::\n  at([17, 9], nofibStringToList(\"the Hugs functional programming system.\")) ::\n  at([17, 11], nofibStringToList(\"Please press any key to continue ...\")) ::\n  Nil,\n  x => pressAnyKey(promptReadAt(\n    [17, 15],\n    18,\n    nofibStringToList(\"Please enter your name: \"),\n    (name) =>\n      let reply = nofibStringToList(\"Hello \") +: name +: nofibStringToList(\"!\")\n      writeAt(\n        [40 - (listLen(reply) / 2), 18],\n        reply,\n        moveTo(\n          [1, 23],\n          y => writeString(nofibStringToList(\"I'm waiting...\"), x => pressAnyKey(end, x), y)\n        )\n      )\n  ), x),\n  input\n)\n\nfun testAnsi_nofib(n) = foldr(compose, (x) => x, replicate(n, program))(nofibStringToList(\"testtesttest\"))\n\nfun main() = nofibListToString(testAnsi_nofib(1))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/atom.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\nmodule atom with ...\n\n\n\ndata class State(position: List[Num], velocity: List[Num])\n\nfun dotPlus(fs, gs) = if\n  fs is Nil then gs\n  gs is Nil then fs\n  fs is f :: fs and gs is g :: gs then (f + g) :: dotPlus(fs, gs)\n\nfun dotMult(fs, gs) = if\n  fs is f :: fs and gs is g :: gs then (f * g) :: dotMult(fs, gs)\n  else Nil\n\nfun scalarMut(c, fs) = if fs is\n  Nil then Nil\n  f :: fs then (c * f) :: scalarMut(c, fs)\n\nfun testforce(k, ss) = lazy of () =>\n  if force(ss) is\n    LzCons(State(pos, vel), atoms) then LzCons(dotMult(scalarMut(-1.0, k), pos), testforce(k, atoms))\n\nfun show(s) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    component :: t then Cons(stringConcat(stringOfFloat(component), \"\\t\"), lscomp(t))\n  if s is State(pos, vel) then\n    stringListConcat of lscomp(pos)\n\nfun propagate(dt, aforce, state) = if state is State(pos, vel) then\n  State(dotPlus(pos, scalarMut(dt, vel)), dotPlus(vel, scalarMut(dt, aforce)))\n\nfun runExperiment(law, dt, param, init) = lazy of () =>\n  let stream = runExperiment(law, dt, param, init)\n  LzCons(init, zipWith_lz_lz((x, y) => propagate(dt, x, y), law(param, stream), stream))\n\nfun testAtom_nofib(n) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    state :: t then stringConcat(show(state), \"\\n\") :: lscomp(t)\n  stringListConcat of lscomp(take_lz(n, runExperiment(testforce, 0.02, 1.0 :: Nil, State(1.0 :: Nil, 0.0 :: Nil))))\n\n\n// NOTE: original input 1000\nfun main() = testAtom_nofib(20)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/awards.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule awards with ...\n\n\n\nfun delete_(xs, e) = deleteBy((x, y) => x == y, e, xs)\n\nfun listDiff(a, ls) = foldl(delete_, a, ls)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun qsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then qpart(le, x, xs, Nil, Nil, r)\n\nfun qpart(le, x, ys, rlt, rge, r) = if ys is\n  Nil then rqsort(le, rlt, x :: rqsort(le, rge, r))\n  y :: ys and\n    le(x, y) then qpart(le, x, ys, rlt, y :: rge, r)\n    else qpart(le, x, ys, y :: rlt, rge, r)\n\nfun rqsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then rqpart(le, x, xs, Nil, Nil, r)\n\nfun rqpart(le, x, yss, rle, rgt, r) = if yss is\n  Nil then qsort(le, rle, x :: qsort(le, rgt, r))\n  y :: ys and\n    le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r)\n    else rqpart(le, x, ys, rle, y :: rgt, r)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun sort(l) = qsort((a, b) => ltTup2(a, b, (a, b) => a < b, (a, b) => a > b, (a, b) => ltList(a, b, (a, b) => a < b, (a, b) => a > b)), l, Nil)\n\nfun perms(m, nns) = if\n  nns is Nil then Nil\n  m == 1 then map(x => x :: Nil, nns)\n  nns is n :: ns then map(x => n :: x, perms(m-1, ns)) +: perms(m, ns)\n\nfun awards(scores) =\n  let sumscores = map(p => [sum(p), p], perms(3, scores))\n\n  fun atleast(threshold) =\n    filter(case { [sum_, p] then sum_ >= threshold }, sumscores)\n\n  fun award(name_threshold) = if name_threshold is [name, threshold] then\n    map(ps => [name, ps], sort(atleast(threshold)))\n\n  award([\"Gold\", 70]) +: award([\"Silver\", 60]) +: award([\"Bronze\", 50])\n\nfun findawards(scores) = if awards(scores) is\n  Nil then Nil\n  head_ :: tail_ and head_ is [award, [sum_, perm]] then\n    [award, [sum_, perm]] :: findawards(listDiff(scores, perm))\n\nfun findallawards(competitors) =\n  map(case { [name, scores] then [name, findawards(scores)] }, competitors)\n\nfun competitors(i) = list of\n  [\"Simon\", list of 35, 27, 40, i, 34, 21]\n  [\"Hans\", list of 23, 19, 45, i, 17, 10, 5, 8, 14]\n  [\"Phil\", list of 1, 18, i, 20, 21, 19, 34, 8, 16, 21]\n  [\"Kevin\", list of 9, 23, 17, 54, i, 41, 9, 18, 14]\n\nfun testAwards_nofib(n) =\n  map(x => findallawards(competitors(intMod(x, 100))), enumFromTo(1, n))\n\n\n// NOTE: original input 1000\nfun main() = testAwards_nofib(100)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/banner.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\nmodule banner with ...\n\n\n\nval blank =\n  nofibStringToList(\"     \") ::\n  nofibStringToList(\"     \") ::\n  nofibStringToList(\"     \") ::\n  nofibStringToList(\"     \") ::\n  nofibStringToList(\"     \") :: Nil\n//│ blank = [[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"]]\n\nval alphas =\n  (nofibStringToList(\"  A  \") :: nofibStringToList(\" A A \") :: nofibStringToList(\"AAAAA\") :: nofibStringToList(\"A   A\") :: nofibStringToList(\"A   A\") :: Nil) ::\n  (nofibStringToList(\"BBBB \") :: nofibStringToList(\"B   B\") :: nofibStringToList(\"BBBB \") :: nofibStringToList(\"B   B\") :: nofibStringToList(\"BBBB \") :: Nil) ::\n  (nofibStringToList(\" CCCC\") :: nofibStringToList(\"C    \") :: nofibStringToList(\"C    \") :: nofibStringToList(\"C    \") :: nofibStringToList(\" CCCC\") :: Nil) ::\n  (nofibStringToList(\"DDDD \") :: nofibStringToList(\"D   D\") :: nofibStringToList(\"D   D\") :: nofibStringToList(\"D   D\") :: nofibStringToList(\"DDDD \") :: Nil) ::\n  (nofibStringToList(\"EEEEE\") :: nofibStringToList(\"E    \") :: nofibStringToList(\"EEEEE\") :: nofibStringToList(\"E    \") :: nofibStringToList(\"EEEEE\") :: Nil) ::\n  (nofibStringToList(\"FFFFF\") :: nofibStringToList(\"F    \") :: nofibStringToList(\"FFFF \") :: nofibStringToList(\"F    \") :: nofibStringToList(\"F    \") :: Nil) ::\n  (nofibStringToList(\" GGGG\") :: nofibStringToList(\"G    \") :: nofibStringToList(\"G  GG\") :: nofibStringToList(\"G   G\") :: nofibStringToList(\" GGG \") :: Nil) ::\n  (nofibStringToList(\"H   H\") :: nofibStringToList(\"H   H\") :: nofibStringToList(\"HHHHH\") :: nofibStringToList(\"H   H\") :: nofibStringToList(\"H   H\") :: Nil) ::\n  (nofibStringToList(\"IIIII\") :: nofibStringToList(\"  I  \") :: nofibStringToList(\"  I  \") :: nofibStringToList(\"  I  \") :: nofibStringToList(\"IIIII\") :: Nil) ::\n  (nofibStringToList(\"JJJJJ\") :: nofibStringToList(\"   J \") :: nofibStringToList(\"   J \") :: nofibStringToList(\"J  J \") :: nofibStringToList(\" JJ  \") :: Nil) ::\n  (nofibStringToList(\"K   K\") :: nofibStringToList(\"K  K \") :: nofibStringToList(\"KKK  \") :: nofibStringToList(\"K  K \") :: nofibStringToList(\"K   K\") :: Nil) ::\n  (nofibStringToList(\"L    \") :: nofibStringToList(\"L    \") :: nofibStringToList(\"L    \") :: nofibStringToList(\"L    \") :: nofibStringToList(\"LLLLL\") :: Nil) ::\n  (nofibStringToList(\"M   M\") :: nofibStringToList(\"MM MM\") :: nofibStringToList(\"M M M\") :: nofibStringToList(\"M   M\") :: nofibStringToList(\"M   M\") :: Nil) ::\n  (nofibStringToList(\"N   N\") :: nofibStringToList(\"NN  N\") :: nofibStringToList(\"N N N\") :: nofibStringToList(\"N  NN\") :: nofibStringToList(\"N   N\") :: Nil) ::\n  (nofibStringToList(\" OOO \") :: nofibStringToList(\"O   O\") :: nofibStringToList(\"O   O\") :: nofibStringToList(\"O   O\") :: nofibStringToList(\" OOO \") :: Nil) ::\n  (nofibStringToList(\"PPPP \") :: nofibStringToList(\"P   P\") :: nofibStringToList(\"PPPP \") :: nofibStringToList(\"P    \") :: nofibStringToList(\"P    \") :: Nil) ::\n  (nofibStringToList(\" QQQ \") :: nofibStringToList(\"Q   Q\") :: nofibStringToList(\"Q Q Q\") :: nofibStringToList(\"Q  Q \") :: nofibStringToList(\" QQ Q\") :: Nil) ::\n  (nofibStringToList(\"RRRR \") :: nofibStringToList(\"R   R\") :: nofibStringToList(\"RRRR \") :: nofibStringToList(\"R  R \") :: nofibStringToList(\"R   R\") :: Nil) ::\n  (nofibStringToList(\" SSSS\") :: nofibStringToList(\"S    \") :: nofibStringToList(\" SSS \") :: nofibStringToList(\"    S\") :: nofibStringToList(\"SSSS \") :: Nil) ::\n  (nofibStringToList(\"TTTTT\") :: nofibStringToList(\"  T  \") :: nofibStringToList(\"  T  \") :: nofibStringToList(\"  T  \") :: nofibStringToList(\"  T  \") :: Nil) ::\n  (nofibStringToList(\"U   U\") :: nofibStringToList(\"U   U\") :: nofibStringToList(\"U   U\") :: nofibStringToList(\"U   U\") :: nofibStringToList(\" UUU \") :: Nil) ::\n  (nofibStringToList(\"V   V\") :: nofibStringToList(\"V   V\") :: nofibStringToList(\"V   V\") :: nofibStringToList(\" V V \") :: nofibStringToList(\"  V  \") :: Nil) ::\n  (nofibStringToList(\"W   W\") :: nofibStringToList(\"W   W\") :: nofibStringToList(\"W   W\") :: nofibStringToList(\"W W W\") :: nofibStringToList(\" W W \") :: Nil) ::\n  (nofibStringToList(\"X   X\") :: nofibStringToList(\" X X \") :: nofibStringToList(\"  X  \") :: nofibStringToList(\" X X \") :: nofibStringToList(\"X   X\") :: Nil) ::\n  (nofibStringToList(\"Y   Y\") :: nofibStringToList(\" Y Y \") :: nofibStringToList(\"  Y  \") :: nofibStringToList(\"  Y  \") :: nofibStringToList(\"  Y  \") :: Nil) ::\n  (nofibStringToList(\"ZZZZZ\") :: nofibStringToList(\"   Z \") :: nofibStringToList(\"  Z  \") :: nofibStringToList(\" Z   \") :: nofibStringToList(\"ZZZZZ\") :: Nil) :: Nil\n//│ alphas = [[[\" \",\" \",\"A\",\" \",\" \"],[\" \",\"A\",\" \",\"A\",\" \"],[\"A\",\"A\",\"A\",\"A\",\"A\"],[\"A\",\" \",\" \",\" \",\"A\"],[\"A\",\" \",\" \",\" \",\"A\"]],[[\"B\",\"B\",\"B\",\"B\",\" \"],[\"B\",\" \",\" \",\" \",\"B\"],[\"B\",\"B\",\"B\",\"B\",\" \"],[\"B\",\" \",\" \",\" \",\"B\"],[\"B\",\"B\",\"B\",\"B\",\" \"]],[[\" \",\"C\",\"C\",\"C\",\"C\"],[\"C\",\" \",\" \",\" \",\" \"],[\"C\",\" \",\" \",\" \",\" \"],[\"C\",\" \",\" \",\" \",\" \"],[\" \",\"C\",\"C\",\"C\",\"C\"]],[[\"D\",\"D\",\"D\",\"D\",\" \"],[\"D\",\" \",\" \",\" \",\"D\"],[\"D\",\" \",\" \",\" \",\"D\"],[\"D\",\" \",\" \",\" \",\"D\"],[\"D\",\"D\",\"D\",\"D\",\" \"]],[[\"E\",\"E\",\"E\",\"E\",\"E\"],[\"E\",\" \",\" \",\" \",\" \"],[\"E\",\"E\",\"E\",\"E\",\"E\"],[\"E\",\" \",\" \",\" \",\" \"],[\"E\",\"E\",\"E\",\"E\",\"E\"]],[[\"F\",\"F\",\"F\",\"F\",\"F\"],[\"F\",\" \",\" \",\" \",\" \"],[\"F\",\"F\",\"F\",\"F\",\" \"],[\"F\",\" \",\" \",\" \",\" \"],[\"F\",\" \",\" \",\" \",\" \"]],[[\" \",\"G\",\"G\",\"G\",\"G\"],[\"G\",\" \",\" \",\" \",\" \"],[\"G\",\" \",\" \",\"G\",\"G\"],[\"G\",\" \",\" \",\" \",\"G\"],[\" \",\"G\",\"G\",\"G\",\" \"]],[[\"H\",\" \",\" \",\" \",\"H\"],[\"H\",\" \",\" \",\" \",\"H\"],[\"H\",\"H\",\"H\",\"H\",\"H\"],[\"H\",\" \",\" \",\" \",\"H\"],[\"H\",\" \",\" \",\" \",\"H\"]],[[\"I\",\"I\",\"I\",\"I\",\"I\"],[\" \",\" \",\"I\",\" \",\" \"],[\" \",\" \",\"I\",\" \",\" \"],[\" \",\" \",\"I\",\" \",\" \"],[\"I\",\"I\",\"I\",\"I\",\"I\"]],[[\"J\",\"J\",\"J\",\"J\",\"J\"],[\" \",\" \",\" \",\"J\",\" \"],[\" \",\" \",\" \",\"J\",\" \"],[\"J\",\" \",\" \",\"J\",\" \"],[\" \",\"J\",\"J\",\" \",\" \"]],[[\"K\",\" \",\" \",\" \",\"K\"],[\"K\",\" \",\" \",\"K\",\" \"],[\"K\",\"K\",\"K\",\" \",\" \"],[\"K\",\" \",\" \",\"K\",\" \"],[\"K\",\" \",\" \",\" \",\"K\"]],[[\"L\",\" \",\" \",\" \",\" \"],[\"L\",\" \",\" \",\" \",\" \"],[\"L\",\" \",\" \",\" \",\" \"],[\"L\",\" \",\" \",\" \",\" \"],[\"L\",\"L\",\"L\",\"L\",\"L\"]],[[\"M\",\" \",\" \",\" \",\"M\"],[\"M\",\"M\",\" \",\"M\",\"M\"],[\"M\",\" \",\"M\",\" \",\"M\"],[\"M\",\" \",\" \",\" \",\"M\"],[\"M\",\" \",\" \",\" \",\"M\"]],[[\"N\",\" \",\" \",\" \",\"N\"],[\"N\",\"N\",\" \",\" \",\"N\"],[\"N\",\" \",\"N\",\" \",\"N\"],[\"N\",\" \",\" \",\"N\",\"N\"],[\"N\",\" \",\" \",\" \",\"N\"]],[[\" \",\"O\",\"O\",\"O\",\" \"],[\"O\",\" \",\" \",\" \",\"O\"],[\"O\",\" \",\" \",\" \",\"O\"],[\"O\",\" \",\" \",\" \",\"O\"],[\" \",\"O\",\"O\",\"O\",\" \"]],[[\"P\",\"P\",\"P\",\"P\",\" \"],[\"P\",\" \",\" \",\" \",\"P\"],[\"P\",\"P\",\"P\",\"P\",\" \"],[\"P\",\" \",\" \",\" \",\" \"],[\"P\",\" \",\" \",\" \",\" \"]],[[\" \",\"Q\",\"Q\",\"Q\",\" \"],[\"Q\",\" \",\" \",\" \",\"Q\"],[\"Q\",\" \",\"Q\",\" \",\"Q\"],[\"Q\",\" \",\" \",\"Q\",\" \"],[\" \",\"Q\",\"Q\",\" \",\"Q\"]],[[\"R\",\"R\",\"R\",\"R\",\" \"],[\"R\",\" \",\" \",\" \",\"R\"],[\"R\",\"R\",\"R\",\"R\",\" \"],[\"R\",\" \",\" \",\"R\",\" \"],[\"R\",\" \",\" \",\" \",\"R\"]],[[\" \",\"S\",\"S\",\"S\",\"S\"],[\"S\",\" \",\" \",\" \",\" \"],[\" \",\"S\",\"S\",\"S\",\" \"],[\" \",\" \",\" \",\" \",\"S\"],[\"S\",\"S\",\"S\",\"S\",\" \"]],[[\"T\",\"T\",\"T\",\"T\",\"T\"],[\" \",\" \",\"T\",\" \",\" \"],[\" \",\" \",\"T\",\" \",\" \"],[\" \",\" \",\"T\",\" \",\" \"],[\" \",\" \",\"T\",\" \",\" \"]],[[\"U\",\" \",\" \",\" \",\"U\"],[\"U\",\" \",\" \",\" \",\"U\"],[\"U\",\" \",\" \",\" \",\"U\"],[\"U\",\" \",\" \",\" \",\"U\"],[\" \",\"U\",\"U\",\"U\",\" \"]],[[\"V\",\" \",\" \",\" \",\"V\"],[\"V\",\" \",\" \",\" \",\"V\"],[\"V\",\" \",\" \",\" \",\"V\"],[\" \",\"V\",\" \",\"V\",\" \"],[\" \",\" \",\"V\",\" \",\" \"]],[[\"W\",\" \",\" \",\" \",\"W\"],[\"W\",\" \",\" \",\" \",\"W\"],[\"W\",\" \",\" \",\" \",\"W\"],[\"W\",\" \",\"W\",\" \",\"W\"],[\" \",\"W\",\" \",\"W\",\" \"]],[[\"X\",\" \",\" \",\" \",\"X\"],[\" \",\"X\",\" \",\"X\",\" \"],[\" \",\" \",\"X\",\" \",\" \"],[\" \",\"X\",\" \",\"X\",\" \"],[\"X\",\" \",\" \",\" \",\"X\"]],[[\"Y\",\" \",\" \",\" \",\"Y\"],[\" \",\"Y\",\" \",\"Y\",\" \"],[\" \",\" \",\"Y\",\" \",\" \"],[\" \",\" \",\"Y\",\" \",\" \"],[\" \",\" \",\"Y\",\" \",\" \"]],[[\"Z\",\"Z\",\"Z\",\"Z\",\"Z\"],[\" \",\" \",\" \",\"Z\",\" \"],[\" \",\" \",\"Z\",\" \",\" \"],[\" \",\"Z\",\" \",\" \",\" \"],[\"Z\",\"Z\",\"Z\",\"Z\",\"Z\"]]]\n\nval slant =\n  nofibStringToList(\"    \") ::\n  nofibStringToList(\"   \") ::\n  nofibStringToList(\"  \") ::\n  nofibStringToList(\" \") ::\n  nofibStringToList(\"\") :: Nil\n//│ slant = [[\" \",\" \",\" \",\" \"],[\" \",\" \",\" \"],[\" \",\" \"],[\" \"],[]]\n\nval punct =\n  [\".\", nofibStringToList(\"     \") :: nofibStringToList(\"     \") :: nofibStringToList(\"     \") :: nofibStringToList(\"  .. \") :: nofibStringToList(\"  .. \") :: Nil] ::\n  [\"?\", nofibStringToList(\" ??? \") :: nofibStringToList(\"?   ?\") :: nofibStringToList(\"   ? \") :: nofibStringToList(\"  ?  \") :: nofibStringToList(\"  .  \") :: Nil] ::\n  [\"!\", nofibStringToList(\"  !  \") :: nofibStringToList(\"  !  \") :: nofibStringToList(\"  !  \") :: nofibStringToList(\"  !  \") :: nofibStringToList(\"  .  \") :: Nil] ::\n  [\"-\", nofibStringToList(\"     \") :: nofibStringToList(\"     \") :: nofibStringToList(\"-----\") :: nofibStringToList(\"     \") :: nofibStringToList(\"     \") :: Nil] ::\n  [\"+\", nofibStringToList(\"  +  \") :: nofibStringToList(\"  +  \") :: nofibStringToList(\"+++++\") :: nofibStringToList(\"  +  \") :: nofibStringToList(\"  +  \") :: Nil] ::\n  [\":\", nofibStringToList(\"     \") :: nofibStringToList(\"  :: \") :: nofibStringToList(\"     \") :: nofibStringToList(\"  :: \") :: nofibStringToList(\"     \") :: Nil] ::\n  [\";\", nofibStringToList(\"     \") :: nofibStringToList(\"  ;; \") :: nofibStringToList(\"     \") :: nofibStringToList(\"  ;; \") :: nofibStringToList(\" ;;  \") :: Nil] :: Nil\n//│ punct = [[\".\", [[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\".\",\".\",\" \"],[\" \",\" \",\".\",\".\",\" \"]]],[\"?\", [[\" \",\"?\",\"?\",\"?\",\" \"],[\"?\",\" \",\" \",\" \",\"?\"],[\" \",\" \",\" \",\"?\",\" \"],[\" \",\" \",\"?\",\" \",\" \"],[\" \",\" \",\".\",\" \",\" \"]]],[\"!\", [[\" \",\" \",\"!\",\" \",\" \"],[\" \",\" \",\"!\",\" \",\" \"],[\" \",\" \",\"!\",\" \",\" \"],[\" \",\" \",\"!\",\" \",\" \"],[\" \",\" \",\".\",\" \",\" \"]]],[\"-\", [[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\"-\",\"-\",\"-\",\"-\",\"-\"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\" \",\" \",\" \"]]],[\"+\", [[\" \",\" \",\"+\",\" \",\" \"],[\" \",\" \",\"+\",\" \",\" \"],[\"+\",\"+\",\"+\",\"+\",\"+\"],[\" \",\" \",\"+\",\" \",\" \"],[\" \",\" \",\"+\",\" \",\" \"]]],[\":\", [[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\":\",\":\",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\":\",\":\",\" \"],[\" \",\" \",\" \",\" \",\" \"]]],[\";\", [[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\";\",\";\",\" \"],[\" \",\" \",\" \",\" \",\" \"],[\" \",\" \",\";\",\";\",\" \"],[\" \",\";\",\";\",\" \",\" \"]]]]\n\nval digits =\n  (nofibStringToList(\" OOO \") :: nofibStringToList(\"0  00\") :: nofibStringToList(\"0 0 0\") :: nofibStringToList(\"00  0\") :: nofibStringToList(\" 000 \") :: Nil) ::\n  (nofibStringToList(\"  1  \") :: nofibStringToList(\" 11  \") :: nofibStringToList(\"  1  \") :: nofibStringToList(\"  1  \") :: nofibStringToList(\"11111\") :: Nil) ::\n  (nofibStringToList(\" 222 \") :: nofibStringToList(\"2   2\") :: nofibStringToList(\"   2 \") :: nofibStringToList(\"  2  \") :: nofibStringToList(\"22222\") :: Nil) ::\n  (nofibStringToList(\"3333 \") :: nofibStringToList(\"    3\") :: nofibStringToList(\" 333 \") :: nofibStringToList(\"    3\") :: nofibStringToList(\"3333 \") :: Nil) ::\n  (nofibStringToList(\"   4 \") :: nofibStringToList(\"  44 \") :: nofibStringToList(\" 4 4 \") :: nofibStringToList(\"44444\") :: nofibStringToList(\"   4 \") :: Nil) ::\n  (nofibStringToList(\"55555\") :: nofibStringToList(\"5    \") :: nofibStringToList(\"5555 \") :: nofibStringToList(\"    5\") :: nofibStringToList(\"5555 \") :: Nil) ::\n  (nofibStringToList(\"   66\") :: nofibStringToList(\"  6  \") :: nofibStringToList(\" 666 \") :: nofibStringToList(\"6   6\") :: nofibStringToList(\" 666 \") :: Nil) ::\n  (nofibStringToList(\"77777\") :: nofibStringToList(\"    7\") :: nofibStringToList(\"   7 \") :: nofibStringToList(\"   7 \") :: nofibStringToList(\"  7  \") :: Nil) ::\n  (nofibStringToList(\" 888 \") :: nofibStringToList(\"8   8\") :: nofibStringToList(\" 888 \") :: nofibStringToList(\"8   8\") :: nofibStringToList(\" 888 \") :: Nil) ::\n  (nofibStringToList(\" 999 \") :: nofibStringToList(\"9   9\") :: nofibStringToList(\" 999 \") :: nofibStringToList(\"  9  \") :: nofibStringToList(\"99   \") :: Nil) :: Nil\n//│ digits = [[[\" \",\"O\",\"O\",\"O\",\" \"],[\"0\",\" \",\" \",\"0\",\"0\"],[\"0\",\" \",\"0\",\" \",\"0\"],[\"0\",\"0\",\" \",\" \",\"0\"],[\" \",\"0\",\"0\",\"0\",\" \"]],[[\" \",\" \",\"1\",\" \",\" \"],[\" \",\"1\",\"1\",\" \",\" \"],[\" \",\" \",\"1\",\" \",\" \"],[\" \",\" \",\"1\",\" \",\" \"],[\"1\",\"1\",\"1\",\"1\",\"1\"]],[[\" \",\"2\",\"2\",\"2\",\" \"],[\"2\",\" \",\" \",\" \",\"2\"],[\" \",\" \",\" \",\"2\",\" \"],[\" \",\" \",\"2\",\" \",\" \"],[\"2\",\"2\",\"2\",\"2\",\"2\"]],[[\"3\",\"3\",\"3\",\"3\",\" \"],[\" \",\" \",\" \",\" \",\"3\"],[\" \",\"3\",\"3\",\"3\",\" \"],[\" \",\" \",\" \",\" \",\"3\"],[\"3\",\"3\",\"3\",\"3\",\" \"]],[[\" \",\" \",\" \",\"4\",\" \"],[\" \",\" \",\"4\",\"4\",\" \"],[\" \",\"4\",\" \",\"4\",\" \"],[\"4\",\"4\",\"4\",\"4\",\"4\"],[\" \",\" \",\" \",\"4\",\" \"]],[[\"5\",\"5\",\"5\",\"5\",\"5\"],[\"5\",\" \",\" \",\" \",\" \"],[\"5\",\"5\",\"5\",\"5\",\" \"],[\" \",\" \",\" \",\" \",\"5\"],[\"5\",\"5\",\"5\",\"5\",\" \"]],[[\" \",\" \",\" \",\"6\",\"6\"],[\" \",\" \",\"6\",\" \",\" \"],[\" \",\"6\",\"6\",\"6\",\" \"],[\"6\",\" \",\" \",\" \",\"6\"],[\" \",\"6\",\"6\",\"6\",\" \"]],[[\"7\",\"7\",\"7\",\"7\",\"7\"],[\" \",\" \",\" \",\" \",\"7\"],[\" \",\" \",\" \",\"7\",\" \"],[\" \",\" \",\" \",\"7\",\" \"],[\" \",\" \",\"7\",\" \",\" \"]],[[\" \",\"8\",\"8\",\"8\",\" \"],[\"8\",\" \",\" \",\" \",\"8\"],[\" \",\"8\",\"8\",\"8\",\" \"],[\"8\",\" \",\" \",\" \",\"8\"],[\" \",\"8\",\"8\",\"8\",\" \"]],[[\" \",\"9\",\"9\",\"9\",\" \"],[\"9\",\" \",\" \",\" \",\"9\"],[\" \",\"9\",\"9\",\"9\",\" \"],[\" \",\" \",\"9\",\" \",\" \"],[\"9\",\"9\",\" \",\" \",\" \"]]]\n\nfun unlines(ls) = concat(map(x => x +: (\"\\n\" :: Nil), ls))\n\nfun join(ls) = foldr1((xs, ys) => xs +: (\" \" :: \" \" :: Nil) +: ys, ls)\n\nfun isUpper(c) =\n  let n = int_of_char(c)\n  (n >= 65) and (n <= 90)\n\nfun isLower(c) =\n  let n = int_of_char(c)\n  (n >= 97) and (n <= 122)\n\nfun isDigit(c) =\n  let n = int_of_char(c)\n  (n >= 48) and (n <= 57)\n\nfun isSpace(c) =\n  let n = int_of_char(c)\n  (n == 32)\n\nfun picChar(c) =\n\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and\n      h is [c_, letter] and c_ === c then letter :: lscomp(t)\n      else lscomp(t)\n\n  if\n    isUpper(c) then atIndex(int_of_char(c) - int_of_char(\"A\"), alphas)\n    isLower(c) then atIndex(int_of_char(c) - int_of_char(\"a\"), alphas)\n    isSpace(c) then blank\n    isDigit(c) then atIndex(int_of_char(c) - int_of_char(\"0\"), digits)\n    c === \"/\" then slant\n    c === \"=\" then reverse(slant)\n    else head(lscomp(punct) +: Nil :: Nil :: Nil)\n\nfun say(s) = \"\\n\" :: (unlines(map(join, transpose(map(picChar, s)))))\n\nfun testBanner_nofib(n) =\n  let x = nofibStringToList(\"Is this not a great banner?\")\n  say(concat(replicate(n, x)))\n\n\nfun main() = nofibListToString(testBanner_nofib(1))\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/boyer.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\n\n\n\nmodule boyer with ...\n\n\n\nabstract class Id: A | B | C | D | X | Y | Z | U | W | ADD1 | AND | APPEND | CONS | CONSP | DIFFERENCE | DIVIDES | EQUAL | EVEN | EXP | F | FALSE | FOUR | GCD | GREATEREQP | GREATERP | IF | IFF | IMPLIES | LENGTH | LESSEQP | LESSP | LISTP | MEMBER | NIL | NILP | NLISTP | NOT | ODD | ONE | OR | PLUS | QUOTIENT | REMAINDER | REVERSE | SUB1 | TIMES | TRUE | TWO | ZERO | ZEROP\n\nobject\n  A extends Id\n  B extends Id\n  C extends Id\n  D extends Id\n  X extends Id\n  Y extends Id\n  Z extends Id\n  U extends Id\n  W extends Id\n  ADD1 extends Id\n  AND extends Id\n  APPEND extends Id\n  CONS extends Id\n  CONSP extends Id\n  DIFFERENCE extends Id\n  DIVIDES extends Id\n  EQUAL extends Id\n  EVEN extends Id\n  EXP extends Id\n  F extends Id\n  FALSE extends Id\n  FOUR extends Id\n  GCD extends Id\n  GREATEREQP extends Id\n  GREATERP extends Id\n  IF extends Id\n  IFF extends Id\n  IMPLIES extends Id\n  LENGTH extends Id\n  LESSEQP extends Id\n  LESSP extends Id\n  LISTP extends Id\n  MEMBER extends Id\n  NIL extends Id\n  NILP extends Id\n  NLISTP extends Id\n  NOT extends Id\n  ODD extends Id\n  ONE extends Id\n  OR extends Id\n  PLUS extends Id\n  QUOTIENT extends Id\n  REMAINDER extends Id\n  REVERSE extends Id\n  SUB1 extends Id\n  TIMES extends Id\n  TRUE extends Id\n  TWO extends Id\n  ZERO extends Id\n  ZEROP extends Id\n\nabstract class Term: Var | Fun | ERROR\n\ndata\n  class\n    Var(i: Id) extends Term\n    Fun(i: Id, t: List[Term], l: [Term, Term]) extends Term\nobject ERROR extends Term\n\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun termLsEq(h1t1, h2t2) = if\n  h1t1 is h1 :: t1 and h2t2 is h2 :: t2 and\n    termEq(h1, h2) then termLsEq(t1, t2)\n    else false\n  else true\n\nfun termEq(t1, t2) = if\n  t1 is Var(i1) and t2 is Var(i2) then i1 === i2\n  t1 is Fun(f1, ts1, _) and t2 is Fun(f2, ts2, _) then (f1 === f2) and termLsEq(ts1, ts2)\n  else false\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun termInList(term, ht) = if ht is\n  h :: t and\n    termEq(term, h) then true\n    else termInList(term, t)\n  Nil then false\n\nfun find(vid, ls) = if ls is\n  Nil then [false, ERROR]\n  [vid2, val2] :: bs and\n    vid === vid2 then [true, val2]\n    else find(vid, bs)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun one_way_unify1(term1, term2, subst) = if\n  term2 is Var(vid2) and find(vid2, subst) is [found, v2] and\n    found then [termEq(term1, v2), subst]\n    else [true, [vid2, term1] :: subst]\n  term1 is Fun(f1, as1, _) and term2 is Fun(f2, as2, _) and\n    f1 === f2 then one_way_unify1_lst(as1, as2, subst)\n    else [false, Nil]\n  else [false, Nil]\n\nfun one_way_unify1_lst(tts1, tts2, subst) = if\n  tts1 is Nil and tts2 is Nil then [true, subst]\n  tts1 is t1 :: ts1 and tts2 is t2 :: ts2 and one_way_unify1(t1, t2, subst) is [hd_ok, subst_] and one_way_unify1_lst(ts1, ts2, subst_) is [tl_ok, subst__] then [hd_ok and tl_ok, subst__]\n  else [false, Nil]\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun one_way_unify(term1, term2) = one_way_unify1(term1, term2, Nil)\n\nfun apply_subst(subst, t) = if t is\n  Var(vid) and find(vid, subst) is [found, value] and\n    found then value\n    else Var(vid)\n  Fun(f, args, ls) then Fun(f, map(x => apply_subst(subst, x), args), ls)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun rewrite_with_lemmas_helper(term, lss) = if lss is\n  Nil then term\n  [lhs, rhs] :: ls and one_way_unify(term, lhs) is [unified, subst] and\n    unified then rewrite(apply_subst(subst, rhs))\n    else rewrite_with_lemmas_helper(term, ls)\n\nfun rewrite_with_lemmas(term, lss) = rewrite_with_lemmas_helper(term, force(lss))\n\nfun rewrite(t) = if t is\n  Var(v) then Var(v)\n  Fun(f, args, lemmas) then rewrite_with_lemmas(Fun(f, map(rewrite, args), lemmas), lemmas)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun truep(x, l) = if x is\n  Fun(TRUE, _, _) then true\n  else termInList(x, l)\n\nfun falsep(x, l) = if x is\n  Fun(FALSE, _, _) then true\n  else termInList(x, l)\n\nfun tautologyp(x, true_lst, false_lst) = if\n  truep(x, true_lst) then true\n  falsep(x, false_lst) then false\n  x is\n    Fun(IF, cond :: t :: e :: Nil, _) and\n      truep(cond, true_lst) then tautologyp(t, true_lst, false_lst)\n      falsep(cond, false_lst) then tautologyp(e, true_lst, false_lst)\n      else tautologyp(t, cond :: true_lst, false_lst) and tautologyp(e, true_lst, cond :: false_lst)\n    else false\n\nfun tautp(x) = tautologyp(rewrite(x), Nil, Nil)\n\nfun test0(xxxx) =\n  let a       =    Var(A)\n  let b       =    Var(B)\n  let c       =    Var(C)\n  let d       =    Var(D)\n  let u       =    Var(U)\n  let w       =    Var(W)\n  let x       =    Var(X)\n  let y       =    Var(Y)\n  let z       =    Var(Z)\n  let boyerFalse = Fun(FALSE, Nil, lazy of () => Nil)\n  let nil =        Fun(NIL  , Nil, lazy of () => Nil)\n  let boyerTrue =  Fun(TRUE , Nil, lazy of () => Nil)\n  let zero    =    Fun(ZERO , Nil, lazy of () => Nil)\n\n  fun one()   =    Fun(ONE, Nil, lazy of () => [one(), add1(zero)] :: Nil)\n\n  fun two()   =    Fun(TWO, Nil, lazy of () => [two(), add1(one())] :: Nil)\n\n  fun four()  =   Fun(FOUR, Nil, lazy of () => [four(), add1(add1(two()))] :: Nil)\n\n  fun add1(a) =   Fun(ADD1, a :: Nil, lazy of () => Nil)\n\n  fun if_(a, b, c) = Fun(IF, a :: b :: c :: Nil, lazy of () => [if_(if_(x, y, z), u, w), if_(x, if_(y, u, w), if_(z, u, w))] :: Nil)\n\n  fun not_(a) = Fun(NOT, a :: Nil, lazy of () => [not_(x), if_(x, boyerFalse, boyerTrue)] :: Nil)\n\n  fun and_(a, b) =\n    Fun(AND, a :: b :: Nil, lazy of () => [and_(x, y), if_(x, if_(y, boyerTrue, boyerFalse), boyerFalse)] :: Nil)\n\n  fun append_(a, b) =\n    Fun(APPEND, a :: b :: Nil, lazy of () => [append_(append_(x, y), z), append_(x, append_(y, z))] :: Nil)\n\n  fun cons(a, b) =\n    Fun(CONS, a :: b :: Nil, lazy of () => Nil)\n\n  fun consp(a) =\n    Fun(CONSP, a :: Nil, lazy of () => [consp(cons(x, y)), boyerTrue] :: Nil)\n\n  fun difference(a, b) =\n    Fun(DIFFERENCE, a :: b :: Nil, lazy of () => [difference(x, x), zero] :: [difference(plus(x, y), x), y] :: [difference(plus(y, x), x), y] :: [difference(plus(x, y), plus(x, z)), difference(y, z)] :: [difference(plus(y, plus(x, z)), x), plus(y, z)] :: [difference(add1(plus(y, z)), z), add1(y)] :: [difference(add1(add1(x)), two()), x] :: Nil)\n\n  fun divides(a, b) =\n    Fun(DIVIDES, a :: b :: Nil, lazy of () => [divides(x, y), zerop(remainder(y, x))] :: Nil)\n\n  fun equal(a, b) =\n    Fun(\n      EQUAL,\n      a :: b :: Nil,\n      lazy of () =>\n        [equal(plus(x, y), zero), and_(zerop(x), zerop(y))] ::\n        [equal(plus(x, y), plus(x, z)), equal(y, z)] ::\n        [equal(zero, difference(x, y)), not_(lessp(y, x))] ::\n        [equal(x, difference(x, y)), or_(equal(x, zero), zerop(y))] ::\n        [equal(times(x, y), zero), or_(zerop(x), zerop(y))] ::\n        [equal(append_(x, y), append_(x, z)), equal(y, z)] ::\n        [equal(y, times(x, y)), or_(equal(y, zero), equal(x, one()))] ::\n        [equal(x, times(x, y)), or_(equal(x, zero), equal(y, one()))] ::\n        [equal(times(x, y), one()), and_(equal(x, one()), equal(y, one()))] ::\n        [equal(difference(x, y), difference(z, y)), if_(lessp(x, y), not_(lessp(y, z)), if_(lessp(z, y), not_(lessp(y, x)), equal(x, z)))] ::\n        [equal(lessp(x, y), z), if_(lessp(x, y), equal(boyerTrue, z), equal(boyerFalse, z))] ::\n        Nil\n    )\n\n  fun even_(a) =\n    Fun(EVEN, a :: Nil, lazy of () => [even_(x), if_(zerop(x), boyerTrue, odd_(sub1(x)))] :: Nil)\n\n  fun exp_(a, b) =\n    Fun(EXP, a :: b :: Nil, lazy of () => [exp_(x, plus(y, z)), times(exp_(x, y), exp_(x, z))] :: [exp_(x, times(y, z)), exp_(exp_(x, y), z)] :: Nil)\n\n  fun f(a) =\n    Fun(F, a :: Nil, lazy of () => Nil)\n\n  fun gcd_(a, b) =\n    Fun(GCD, a :: b :: Nil, lazy of () => [gcd_(x, y), gcd_(y, x)] :: [gcd_(times(x, z), times(y, z)), times(z, gcd_(x, y))] :: Nil)\n\n  fun greatereqp(a, b) =\n    Fun(GREATEREQP, a :: b :: Nil, lazy of () => [greatereqp(x, y), not_(lessp(x, y))] :: Nil)\n\n  fun greaterp(a, b) =\n    Fun(GREATERP, a :: b :: Nil, lazy of () => [greaterp(x, y), lessp(y, x)] :: Nil)\n\n  fun implies(a, b) =\n    Fun(IMPLIES, a :: b :: Nil, lazy of () => [implies(x, y), if_(x, if_(y, boyerTrue, boyerFalse), boyerTrue)] :: Nil)\n\n  fun iff(a, b) =\n    Fun(IFF, a :: b :: Nil, lazy of () => [iff(x, y), and_(implies(x, y), implies(y, x))] :: Nil)\n\n  fun length_(a) =\n    Fun(LENGTH, a :: Nil, lazy of () => [length_(reverse_(x)), length_(x)] :: [length_(cons(x, cons(y, cons(z, cons(u, w))))), plus(four(), length_(w))] :: Nil)\n\n  fun lesseqp(a, b) =\n    Fun(LESSEQP, a :: b :: Nil, lazy of () => [lesseqp(x, y), not_(lessp(y, x))] :: Nil)\n\n  fun lessp(a, b) =\n    Fun(\n      LESSP,\n      a :: b :: Nil,\n      lazy of () =>\n        [lessp(remainder(x, y), y), not_(zerop(y))] ::\n        [lessp(quotient(x, y), x), and_(not_(zerop(x)), lessp(one(), y))] ::\n        [lessp(plus(x, y), plus(x, z)), lessp(y, z)] ::\n        [lessp(times(x, z), times(y, z)), and_(not_(zerop(z)), lessp(x, y))] ::\n        [lessp(y, plus(x, y)), not_(zerop(x))] ::\n        Nil\n    )\n\n  fun nilp(a) =\n    Fun(NILP, a :: Nil, lazy of () => [nilp(x), equal(x, nil)] :: Nil)\n\n  fun listp(a) =\n    Fun(LISTP, a :: Nil, lazy of () => [listp(x), or_(nilp(x), consp(x))] :: Nil)\n\n  fun member(a, b) =\n    Fun(MEMBER, a :: b :: Nil, lazy of () => [member(x, append_(y, z)), or_(member(x, y), member(x, z))] :: [member(x, reverse_(y)), member(x, y)] :: Nil)\n\n  fun nlistp(a) =\n    Fun(NLISTP, a :: Nil, lazy of () => [nlistp(x), not_(listp(x))] :: Nil)\n\n  fun odd_(a) =\n    Fun(ODD, a :: Nil, lazy of () => [odd_(x), even_(sub1(x))] :: Nil)\n\n  fun or_(a, b) =\n    Fun(OR, a :: b :: Nil, lazy of () => [or_(x, y), if_(x, boyerTrue, if_(y, boyerTrue, boyerFalse))] :: Nil)\n\n  fun plus(a, b) =\n    Fun(PLUS, a :: b :: Nil, lazy of () => [plus(plus(x, y), z), plus(x, plus(y, z))] :: [plus(remainder(x, y), times(y, quotient(x, y))), x] :: [plus(x, add1(y)), add1(plus(x, y))] :: Nil)\n\n  fun quotient(a, b) =\n    Fun(QUOTIENT, a :: b :: Nil, lazy of () => [quotient(plus(x, plus(x, y)), two()), plus(x, quotient(y, two()))] :: [quotient(times(y, x), y), if_(zerop(y), zero, x)] :: Nil)\n\n  fun remainder(a, b) =\n    Fun(REMAINDER, a :: b :: Nil, lazy of () => [remainder(x, one()), zero] :: [remainder(x, x), zero] :: [remainder(times(x, y), x), zero] :: [remainder(times(x, y), y), zero] :: Nil)\n\n  fun reverse_(a) =\n    Fun(REVERSE, a :: Nil, lazy of () => [reverse_(append_(x, y)), append_(reverse_(y), reverse_(x))] :: Nil)\n\n  fun sub1(a) =\n    Fun(SUB1, a :: Nil, lazy of () => [sub1(add1(x)), x] :: Nil)\n\n  fun times(a, b) =\n    Fun(TIMES, a :: b :: Nil, lazy of () => [times(x, plus(y, z)), plus(times(x, y), times(x, z))] :: [times(times(x, y), z), times(x, times(y, z))] :: [times(x, difference(y, z)), difference(times(y, x), times(z, x))] :: [times(x, add1(y)), plus(x, times(x, y))] :: Nil)\n\n  fun zerop(a) =\n    Fun(ZEROP, a :: Nil, lazy of () => [zerop(x), equal(x, zero)] :: Nil)\n\n  let subst0 = [X, f(plus(plus(a, b), plus(c, zero)))] :: [Y, f(times(times(a, b), plus(c, d)))] :: [Z, f(reverse_(append_(append_(a, b), nil)))] :: [U, equal(plus(a, b), difference(x, y))] :: [W, lessp(remainder(a, b), member(a, length_(b)))] :: Nil\n\n  let theorem = implies(and_(implies(xxxx, y), and_(implies(y, z), and_(implies(z, u), implies(u, w)))), implies(x, w))\n\n  tautp(apply_subst(subst0, theorem))\n\nfun testBoyer_nofib(n) = all(test0, replicate(n, Var(X)))\n\nfun main() = testBoyer_nofib(5)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/boyer2.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\n\nmodule boyer2 with ...\n\n\n\n\nabstract class Lisplist: Nill | Atom | Conss\n\nobject Nill extends Lisplist\ndata\n  class\n    Atom(a: List[Char]) extends Lisplist\n    Conss(a: [Lisplist, Lisplist]) extends Lisplist\n\nfun lispListEq(x, y) = if x is\n  Nill and y is Nill then true\n  Atom(a) and y is Atom(b) then listEq(a, b)\n  Conss([a, b]) and y is Conss([c, d]) and (lispListEq(a, c)) then lispListEq(b, d)\n  else false\n\nfun lispmember(e_x) = if e_x is \n  [e, Conss([x, xs])] and\n    lispListEq(e, x) then true\n    else lispmember([e, xs])\n  [_, _] then false\n\nfun truep(term_l) = if term_l is\n  [Nill, _] then false\n  [Conss([Atom(\"t\" :: Nil), Nill]), _] then true\n  [term, l] then lispmember([term, l])\n\nfun falsep(term_l) = if term_l is\n  [Nill, _] then false\n  [Conss([Atom(\"f\" :: Nil), Nill]), _] then true\n  [term, l] then lispmember([term, l])\n\nfun tv(x) = if x is Atom(a) then a\n\nfun atom(x) = if x is Atom(_) then true else false\n\nfun car(x) = if x is Conss([a, _]) then a else Nill\n\nfun cdr(x) = if x is Conss([_, b]) then b else Nill\n\nfun cadr(x) = car(cdr(x))\n\nfun caddr(x) = car(cdr(cdr(x)))\n\nfun cadddr(x) = car(cdr(cdr(cdr(x))))\n\nfun tautologyp(f_truelst_falselst) = if f_truelst_falselst is [f, truelst, falselst] and f is\n  Nill then false\n  Atom(x) then truep([Atom(x), truelst])\n  Conss([x, y]) and\n    truep([Conss([x, y]), truelst]) then true\n    falsep([Conss([x, y]), falselst]) then false\n    x is\n      Atom(\"i\" :: \"f\" :: Nil) and\n        truep([car(y), truelst]) then\n          tautologyp([cadr(y), truelst, falselst])\n        falsep([car(y), falselst]) then\n          tautologyp([caddr(y), truelst, falselst])\n        else\n          tautologyp([cadr(y), Conss([car(y), truelst]), falselst]) and tautologyp([caddr(y), truelst, Conss([car(y), falselst])])\n      else false\n\nfun sublist(t) = if t is\n  Nil then [Nil, Nill]\n  (\"(\" :: Nil) :: t and sublist(t) is [r1, l1] and sublist(r1) is [r2, l2] then [r2, Conss([l1, l2])]\n  (\")\" :: Nil) :: t then [t, Nill]\n  h :: t and sublist(t) is [r, l] then [r, Conss([Atom(h), l])]\n\nfun mkLispList(ls) = if ls is\n  (\"(\" :: Nil) :: t and sublist(t) is [r, l] and r is\n    Nil then l\n    else Nill\n  _ then Nill\n\nfun restOfToken(s) = if s is\n  Nil then [Nil, Nil]\n  h :: t and\n    (h === \"(\") || (h === \")\") || (h === \" \") then [Nil, h :: t]\n    restOfToken(t) is [a, b] then [h :: a, b]\n\nfun getToken(s) = if s is\n  Nil then [Nil, Nil]\n  h :: t and\n    (h === \" \") then getToken(t)\n    (h === \"(\") || (h === \")\") then [h :: Nil, t]\n    boyer2.restOfToken(t) is [a, b] then [h :: a, b]\n\nfun strToToken(s) = if\n  s is Nil then Nil\n  getToken(s) is [a, b] then a :: strToToken(b)\n\nfun assoc(term_x_y) = if term_x_y is\n  [term, Conss([x, y])] and x is\n    Conss([Atom(key), rest]) and\n      lispListEq(term, Atom(key)) then x\n      else assoc([term, y])\n    _ then Nill\n  [_, _] then Nill\n\ntype LUTentry = [String, List[Lisplist]]\n\nabstract class LUT: Empty | Node\n\nobject Empty extends LUT\n\ndata class Node(x: [LUT, LUTentry, LUT]) extends LUT\n\nfun addtoLUT(k_l_lut) = if k_l_lut is\n  [k, l, boyer2.Empty] then boyer2.Node([boyer2.Empty, [k, l :: Nil], boyer2.Empty])\n  [k, l, boyer2.Node([left, [k1, kl], right])] and\n    listEq(k, k1) then boyer2.Node([left, [k1, l :: kl], right])\n    ltList(k, k1, (x, y) => x < y, (x, y) => x > y) then boyer2.Node([addtoLUT([k, l, left]), [k1, kl], right])\n    else boyer2.Node([left, [k1, kl], addtoLUT([k, l, right])])\n\nfun getLUT(t_lut) = if t_lut is\n  [t, Empty] then Nil\n  [t, Node([left, [k, kl], right])] and\n    listEq(t, k) then kl\n    ltList(t, k, (x, y) => x < y, (x, y) => x > y) then getLUT([t, left])\n    else getLUT([t, right])\n\nfun makelemmas(rules) = if rules is\n  Nil then Nil\n  h :: t then boyer2.mkLispList(strToToken(h)) :: makelemmas(t)\n\nfun addlemma(lspls, term) = if lspls is\n  boyer2.Nill then term\n  boyer2.Atom(x) then throw new Error(\"error\")\n  boyer2.Conss([x, y]) then\n    let z = boyer2.car(y)\n    if listEq(boyer2.tv(x), nofibStringToList(\"equal\")) and (not(boyer2.atom(z)))\n    then addtoLUT([boyer2.tv(boyer2.car(z)), boyer2.Conss([x, y]), term])\n    else throw new Error(\"error\")\n\nfun addlemmalst(lspls, term) = if lspls is\n  Nil then term\n  h :: t then addlemmalst(t, boyer2.addlemma(h, term))\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun applysubstlst(alist, y) = if y is\n  Nill then Nill\n  Atom(x) then throw new Error(\"error\")\n  Conss([x, y]) then Conss([applysubst(alist, x), applysubstlst(alist, y)])\n\nfun applysubst(alist, x) = if x is\n  Nill then Nill\n  Atom(x) and assoc([Atom(x), alist]) is\n    Conss([_, y]) then y\n    else Atom(x)\n  Conss([x, y]) then Conss([x, applysubstlst(alist, y)])\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun onewayunify1lst(l1, l2, u) = if\n  l1 is Nill then [true, u]\n  onewayunify1(car(l1), car(l2), u) is [b, u1] and\n    b then onewayunify1lst(cdr(l1), cdr(l2), u1)\n    else [false, u1]\n\nfun onewayunify1(t1, t2, u) = if\n  atom(t2) and assoc([t2, u]) is\n    Conss([_, y]) then [lispListEq(t1, y), u]\n    else [true, Conss([Conss([t2, t1]), u])]\n  atom(t1) then [false, u]\n  lispListEq(car(t1), car(t2)) then onewayunify1lst(cdr(t1), cdr(t2), u)\n  else [false, u]\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun onewayunify(t1, t2) = onewayunify1(t1, t2, Nill)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun rewritewithlemmas(t, l, term) = if l is\n  Nil then t\n  lh :: lt and onewayunify(t, cadr(lh)) is [b, u] and\n    b then rewrite(applysubst(u, caddr(lh)), term)\n    else rewritewithlemmas(t, lt, term)\n\nfun rewriteargs(x, term) = if x is\n  Nill then Nill\n  Atom(_) then throw new Error(\"error\")\n  Conss([x, y]) then Conss([rewrite(x, term), rewriteargs(y, term)])\n\nfun rewrite(x, term) = if x is\n  Nill then Nill\n  Atom(x) then Atom(x)\n  Conss([l1, l2]) then rewritewithlemmas(Conss([l1, rewriteargs(l2, term)]), getLUT([tv(l1), term]), term)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nval statement = boyer2.mkLispList(strToToken(\n  nofibStringToList(\"( implies ( and ( implies x y )( and ( implies y z )( and ( implies z u )( implies u w ) ) ) )( implies x w ) )\")\n))\n//│ statement = Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"z\"]), Conss([Atom([\"u\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"u\"]), Conss([Atom([\"w\"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"w\"]), Nill])])]), Nill])])])\n\nfun subterm(i) =\n  let c = stringConcat(\"c\", stringOfInt(i))\n  let str = stringConcat(\n    \"( ( x f ( plus ( plus a b )( plus \",\n    stringConcat(\n      c,\n      stringConcat(\n        \" ( zero ) ) ) )( y f ( times ( times a b )( plus \",\n        stringConcat(c, \" d ) ) )( z f ( reverse ( append ( append a b ) ( [] ) ) ) )(u equal ( plus a b ) ( difference x y ) )(w lessp ( remainder a b )( member a ( length b ) ) ) )\")\n      )\n    )\n  )\n  mkLispList(strToToken(nofibStringToList(str)))\n\nfun report(b) = if b then \"The term is a tautology\" else \"The term is not a tautology\"\n\nval rules =\n  nofibStringToList(\"(equal (compile form)(reverse (codegen (optimize form) (Nill) ) ) )\") ::\n  nofibStringToList(\"(equal (eqp x y)(equal (fix x)(fix y) ) )\") ::\n  nofibStringToList(\"(equal (greaterp x y)(lessp y x) )\") ::\n  nofibStringToList(\"(equal (lesseqp x y)(not (lessp y x) ) )\") ::\n  nofibStringToList(\"(equal (greatereqp x y)(not (lessp y x) ) )\") ::\n  nofibStringToList(\"(equal (boolean x)(or (equal x (t) )(equal x (f) ) )\") ::\n  nofibStringToList(\"(equal (iff x y)(and (implies x y)(implies y x) ) )\") ::\n  nofibStringToList(\"(equal (even1 x)(if (zerop x)(t)(odd (1- x) ) ) )\") ::\n  nofibStringToList(\"(equal (countps- l pred)(countps-loop l pred (zero) ) )\") ::\n  nofibStringToList(\"(equal (fact- i)(fact-loop i 1) )\") ::\n  nofibStringToList(\"(equal (reverse- x)(reverse-loop x (Nill) ) )\") ::\n  nofibStringToList(\"(equal (divides x y)(zerop (remainder y x) ) )\") ::\n  nofibStringToList(\"(equal (assume-true var alist)(Conss (Conss var (t) )alist) )\") ::\n  nofibStringToList(\"(equal (assume-false var alist)(Conss (Conss var (f) )alist) )\") ::\n  nofibStringToList(\"(equal (tautology-checker x)(tautologyp (normalize x)(Nill) ) )\") ::\n  nofibStringToList(\"(equal (falsify x)(falsify1 (normalize x)(Nill) ) )\") ::\n  nofibStringToList(\"(equal (prime x)(and (not (zerop x))(not (equal x (add1 (zero) ) ) )(prime1 x (1- x) ) ) )\") ::\n  nofibStringToList(\"(equal (and p q)(if p (if q (t) (f) ) (f) ) )\") ::\n  nofibStringToList(\"(equal (or p q)(if p (t) (if q (t) (f) ) ) )\") ::\n  nofibStringToList(\"(equal (not p)(if p (f) (t) ) )\") ::\n  nofibStringToList(\"(equal (implies p q)(if p (if q (t) (f) ) (t) ) )\") ::\n  nofibStringToList(\"(equal (fix x)(if (numberp x) x (zero) ) )\") ::\n  nofibStringToList(\"(equal (if (if a b c) d e)(if a (if b d e) (if c d e) ) )\") ::\n  nofibStringToList(\"(equal (zerop x)(or (equal x (zero) )(not (numberp x) ) ) )\") ::\n  nofibStringToList(\"(equal (plus (plus x y) z )(plus x (plus y z) ) )\") ::\n  nofibStringToList(\"(equal (equal (plus a b) (zero ) )(and (zerop a) (zerop b) ) )\") ::\n  nofibStringToList(\"(equal (difference x x)(zero) )\") ::\n  nofibStringToList(\"(equal (equal (plus a b) (plus a c) )(equal (fix b) (fix c) ) )\") ::\n  nofibStringToList(\"(equal (equal (zero) (difference x y) )(not (lessp y x) ) )\") ::\n  nofibStringToList(\"(equal (equal x (difference x y) )(and (numberp x)(or (equal x (zero) )(zerop y) ) ) )\") ::\n  nofibStringToList(\"(equal (meaning (plus-tree (append x y) ) a)(plus (meaning (plus-tree x) a)(meaning (plus-tree y) a) ) )\") ::\n  nofibStringToList(\"(equal (meaning (plus-tree (plus-fringe x) ) a)(fix (meaning x a) ) )\") ::\n  nofibStringToList(\"(equal (append (append x y) z)(append x (append y z) ) )\") ::\n  nofibStringToList(\"(equal (reverse (append a b) )(append (reverse b) (reverse a) ) )\") ::\n  nofibStringToList(\"(equal (times x (plus y z) )(plus (times x y)(times x z) ) )\") ::\n  nofibStringToList(\"(equal (times (times x y) z)(times x (times y z) ) )\") ::\n  nofibStringToList(\"(equal (equal (times x y) (zero) )(or (zerop x)(zerop y) ) )\") ::\n  nofibStringToList(\"(equal (exec (append x y)pds envrn)(exec y (exec x pds envrn)envrn) )\") ::\n  nofibStringToList(\"(equal (mc-flatten x y)(append (flatten x)y) )\") ::\n  nofibStringToList(\"(equal (member x (append a b) )(or (member x a)(member x b) ) )\") ::\n  nofibStringToList(\"(equal (member x (reverse y) )(member x y) )\") ::\n  nofibStringToList(\"(equal (length (reverse x) )(length x) )\") ::\n  nofibStringToList(\"(equal (member a (intersect b c) )(and (member a b)(member a c) ) )\") ::\n  nofibStringToList(\"(equal (nth (zero)i)(zero) )\") ::\n  nofibStringToList(\"(equal (exp i (plus j k) )(times (exp i j)(exp i k) ) )\") ::\n  nofibStringToList(\"(equal (exp i (times j k) )(exp (exp i j)k) )\") ::\n  nofibStringToList(\"(equal (reverse-loop x y)(append (reverse x)y) )\") ::\n  nofibStringToList(\"(equal (reverse-loop x (Nill) )(reverse x) )\") ::\n  nofibStringToList(\"(equal (count-list z (sort-lp x y) )(plus (count-list z x)(count-list z y) ) )\") ::\n  nofibStringToList(\"(equal (equal (append a b)(append a c) )(equal b c) )\") ::\n  nofibStringToList(\"(equal (plus (remainder x y)(times y (quotient x y) ) )(fix x) )\") ::\n  nofibStringToList(\"(equal (power-eval (big-plus1 l i base)base)(plus (power-eval l base)i) )\") ::\n  nofibStringToList(\"(equal (power-eval (big-plus x y i base)base)(plus i (plus (power-eval x base)(power-eval y base) ) ) )\") ::\n  nofibStringToList(\"(equal (remainder y 1)(zero) )\") ::\n  nofibStringToList(\"(equal (lessp (remainder x y)y)(not (zerop y) ) )\") ::\n  nofibStringToList(\"(equal (remainder x x)(zero) )\") ::\n  nofibStringToList(\"(equal (lessp (quotient i j)i)(and (not (zerop i) )(or (zerop j)(not (equal j 1) ) ) ) )\") ::\n  nofibStringToList(\"(equal (lessp (remainder x y)x)(and (not (zerop y) )(not (zerop x) )(not (lessp x y) ) ) )\") ::\n  nofibStringToList(\"(equal (power-eval (power-rep i base)base)(fix i) )\") ::\n  nofibStringToList(\"(equal (power-eval (big-plus (power-rep i base)(power-rep j base)(zero)base)base)(plus i j) )\") ::\n  nofibStringToList(\"(equal (gcd x y)(gcd y x) )\") ::\n  nofibStringToList(\"(equal (nth (append a b)i)(append (nth a i)(nth b (difference i (length a) ) ) ) )\") ::\n  nofibStringToList(\"(equal (difference (plus x y)x)(fix y) )\") ::\n  nofibStringToList(\"(equal (difference (plus y x)x)(fix y) )\") ::\n  nofibStringToList(\"(equal (difference (plus x y)(plus x z) )(difference y z) )\") ::\n  nofibStringToList(\"(equal (times x (difference c w) )(difference (times c x)(times w x) ) )\") ::\n  nofibStringToList(\"(equal (remainder (times x z)z)(zero) )\") ::\n  nofibStringToList(\"(equal (difference (plus b (plus a c) )a)(plus b c) )\") ::\n  nofibStringToList(\"(equal (difference (add1 (plus y z)z)(add1 y) )\") ::\n  nofibStringToList(\"(equal (lessp (plus x y)(plus x z ) )(lessp y z) )\") ::\n  nofibStringToList(\"(equal (lessp (times x z)(times y z) )(and (not (zerop z) )(lessp x y) ) )\") ::\n  nofibStringToList(\"(equal (lessp y (plus x y) )(not (zerop x) ) )\") ::\n  nofibStringToList(\"(equal (gcd (times x z)(times y z) )(times z (gcd x y) ) )\") ::\n  nofibStringToList(\"(equal (value (normalize x)a)(value x a) )\") ::\n  nofibStringToList(\"(equal (equal (flatten x)(Conss y (Nill) ) )(and (nlistp x)(equal x y) ) )\") ::\n  nofibStringToList(\"(equal (listp (gopher x) )(listp x) )\") ::\n  nofibStringToList(\"(equal (samefringe x y)(equal (flatten x)(flatten y) ) )\") ::\n  nofibStringToList(\"(equal (equal (greatest-factor x y)(zero) )(and (or (zerop y)(equal y 1) )(equal x (zero) ) ) )\") ::\n  nofibStringToList(\"(equal (equal (greatest-factor x y)1)(equal x 1) )\") ::\n  nofibStringToList(\"(equal (numberp (greatest-factor x y) )(not (and (or (zerop y)(equal y 1) )(not (numberp x) ) ) ) )\") ::\n  nofibStringToList(\"(equal (times-list (append x y) )(times (times-list x)(times-list y) ) )\") ::\n  nofibStringToList(\"(equal (prime-list (append x y) )(and (prime-list x)(prime-list y) ) )\") ::\n  nofibStringToList(\"(equal (equal z (times w z) )(and (numberp z)(or (equal z (zero) )(equal w 1) ) ) )\") ::\n  nofibStringToList(\"(equal (greatereqpr x y)(not (lessp x y) ) )\") ::\n  nofibStringToList(\"(equal (equal x (times x y) )(or (equal x (zero) )(and (numberp x)(equal y 1) ) ) )\") ::\n  nofibStringToList(\"(equal (remainder (times y x)y)(zero) )\") ::\n  nofibStringToList(\"(equal (equal (times a b)1)(and (not (equal a (zero) ) )(not (equal b (zero) ) )(numberp a)(numberp b)(equal (1- a)(zero) )(equal (1- b)(zero) ) ) )\") ::\n  nofibStringToList(\"(equal (lessp (length (delete x l) )(length l) )(member x l) )\") ::\n  nofibStringToList(\"(equal (sort2 (delete x l) )(delete x (sort2 l) ) )\") ::\n  nofibStringToList(\"(equal (dsort x)(sort2 x) )\") ::\n  nofibStringToList(\"(equal (length(Conss x1(Conss x2(Conss x3(Conss x4(Conss x5(Conss x6 x7) ) ) ) ) ) )(plus 6 (length x7) ) )\") ::\n  nofibStringToList(\"(equal (difference (add1 (add1 x) )2)(fix x) )\") ::\n  nofibStringToList(\"(equal (quotient (plus x (plus x y) )2)(plus x (quotient y 2) ) )\") ::\n  nofibStringToList(\"(equal (sigma (zero)i)(quotient (times i (add1 i) )2) )\") ::\n  nofibStringToList(\"(equal (plus x (add1 y) )(if (numberp y)(add1 (plus x y) )(add1 x) ) )\") ::\n  nofibStringToList(\"(equal (equal (difference x y)(difference z y) )(if (lessp x y)(not (lessp y z) )(if (lessp z y)(not (lessp y x) )(equal (fix x)(fix z) ) ) ) )\") ::\n  nofibStringToList(\"(equal (meaning (plus-tree (delete x y) )a)(if (member x y)(difference (meaning (plus-tree y)a)(meaning x a) )(meaning (plus-tree y)a) ) )\") ::\n  nofibStringToList(\"(equal (times x (add1 y) )(if (numberp y)(plus x (times x y) )(fix x) ) )\") ::\n  nofibStringToList(\"(equal (nth (Nill)i)(if (zerop i)(Nill)(zero) ) )\") ::\n  nofibStringToList(\"(equal (last (append a b) )(if (listp b)(last b)(if (listp a)(Conss (car (last a) )b)b) ) )\") ::\n  nofibStringToList(\"(equal (equal (lessp x y)z)(if (lessp x y)(equal t z)(equal f z) ) )\") ::\n  nofibStringToList(\"(equal (assignment x (append a b) )(if (assignedp x a)(assignment x a)(assignment x b) ) )\") ::\n  nofibStringToList(\"(equal (car (gopher x) )(if (listp x)(car (flatten x) )(zero) ) )\") ::\n  nofibStringToList(\"(equal (flatten (cdr (gopher x) ) )(if (listp x)(cdr (flatten x) )(Conss (zero)(Nill) ) ) )\") ::\n  nofibStringToList(\"(equal (quotient (times y x)y)(if (zerop y)(zero)(fix x) ) )\") ::\n  nofibStringToList(\"(equal (get j (set i val mem) )(if (eqp j i)val(get j mem) ) )\") :: Nil\n//│ rules = [[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"c\",\"o\",\"m\",\"p\",\"i\",\"l\",\"e\",\" \",\"f\",\"o\",\"r\",\"m\",\")\",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"(\",\"c\",\"o\",\"d\",\"e\",\"g\",\"e\",\"n\",\" \",\"(\",\"o\",\"p\",\"t\",\"i\",\"m\",\"i\",\"z\",\"e\",\" \",\"f\",\"o\",\"r\",\"m\",\")\",\" \",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"i\",\"x\",\" \",\"x\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"e\",\"q\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"e\",\"q\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"b\",\"o\",\"o\",\"l\",\"e\",\"a\",\"n\",\" \",\"x\",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"t\",\")\",\" \",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"f\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"i\",\"f\",\"f\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"v\",\"e\",\"n\",\"1\",\" \",\"x\",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"x\",\")\",\"(\",\"t\",\")\",\"(\",\"o\",\"d\",\"d\",\" \",\"(\",\"1\",\"-\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"c\",\"o\",\"u\",\"n\",\"t\",\"p\",\"s\",\"-\",\" \",\"l\",\" \",\"p\",\"r\",\"e\",\"d\",\")\",\"(\",\"c\",\"o\",\"u\",\"n\",\"t\",\"p\",\"s\",\"-\",\"l\",\"o\",\"o\",\"p\",\" \",\"l\",\" \",\"p\",\"r\",\"e\",\"d\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"a\",\"c\",\"t\",\"-\",\" \",\"i\",\")\",\"(\",\"f\",\"a\",\"c\",\"t\",\"-\",\"l\",\"o\",\"o\",\"p\",\" \",\"i\",\" \",\"1\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\" \",\"x\",\")\",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\"l\",\"o\",\"o\",\"p\",\" \",\"x\",\" \",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"v\",\"i\",\"d\",\"e\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"a\",\"s\",\"s\",\"u\",\"m\",\"e\",\"-\",\"t\",\"r\",\"u\",\"e\",\" \",\"v\",\"a\",\"r\",\" \",\"a\",\"l\",\"i\",\"s\",\"t\",\")\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"v\",\"a\",\"r\",\" \",\"(\",\"t\",\")\",\" \",\")\",\"a\",\"l\",\"i\",\"s\",\"t\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"a\",\"s\",\"s\",\"u\",\"m\",\"e\",\"-\",\"f\",\"a\",\"l\",\"s\",\"e\",\" \",\"v\",\"a\",\"r\",\" \",\"a\",\"l\",\"i\",\"s\",\"t\",\")\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"v\",\"a\",\"r\",\" \",\"(\",\"f\",\")\",\" \",\")\",\"a\",\"l\",\"i\",\"s\",\"t\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"a\",\"u\",\"t\",\"o\",\"l\",\"o\",\"g\",\"y\",\"-\",\"c\",\"h\",\"e\",\"c\",\"k\",\"e\",\"r\",\" \",\"x\",\")\",\"(\",\"t\",\"a\",\"u\",\"t\",\"o\",\"l\",\"o\",\"g\",\"y\",\"p\",\" \",\"(\",\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\"i\",\"z\",\"e\",\" \",\"x\",\")\",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"a\",\"l\",\"s\",\"i\",\"f\",\"y\",\" \",\"x\",\")\",\"(\",\"f\",\"a\",\"l\",\"s\",\"i\",\"f\",\"y\",\"1\",\" \",\"(\",\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\"i\",\"z\",\"e\",\" \",\"x\",\")\",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"r\",\"i\",\"m\",\"e\",\" \",\"x\",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"x\",\")\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\"(\",\"p\",\"r\",\"i\",\"m\",\"e\",\"1\",\" \",\"x\",\" \",\"(\",\"1\",\"-\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"a\",\"n\",\"d\",\" \",\"p\",\" \",\"q\",\")\",\"(\",\"i\",\"f\",\" \",\"p\",\" \",\"(\",\"i\",\"f\",\" \",\"q\",\" \",\"(\",\"t\",\")\",\" \",\"(\",\"f\",\")\",\" \",\")\",\" \",\"(\",\"f\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"o\",\"r\",\" \",\"p\",\" \",\"q\",\")\",\"(\",\"i\",\"f\",\" \",\"p\",\" \",\"(\",\"t\",\")\",\" \",\"(\",\"i\",\"f\",\" \",\"q\",\" \",\"(\",\"t\",\")\",\" \",\"(\",\"f\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"n\",\"o\",\"t\",\" \",\"p\",\")\",\"(\",\"i\",\"f\",\" \",\"p\",\" \",\"(\",\"f\",\")\",\" \",\"(\",\"t\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\",\" \",\"p\",\" \",\"q\",\")\",\"(\",\"i\",\"f\",\" \",\"p\",\" \",\"(\",\"i\",\"f\",\" \",\"q\",\" \",\"(\",\"t\",\")\",\" \",\"(\",\"f\",\")\",\" \",\")\",\" \",\"(\",\"t\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"i\",\"x\",\" \",\"x\",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"x\",\")\",\" \",\"x\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"i\",\"f\",\" \",\"(\",\"i\",\"f\",\" \",\"a\",\" \",\"b\",\" \",\"c\",\")\",\" \",\"d\",\" \",\"e\",\")\",\"(\",\"i\",\"f\",\" \",\"a\",\" \",\"(\",\"i\",\"f\",\" \",\"b\",\" \",\"d\",\" \",\"e\",\")\",\" \",\"(\",\"i\",\"f\",\" \",\"c\",\" \",\"d\",\" \",\"e\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"x\",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\"z\",\" \",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"a\",\" \",\"b\",\")\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\" \",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"a\",\")\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"b\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"x\",\" \",\"x\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"a\",\" \",\"b\",\")\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"a\",\" \",\"c\",\")\",\" \",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"i\",\"x\",\" \",\"b\",\")\",\" \",\"(\",\"f\",\"i\",\"x\",\" \",\"c\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"x\",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\"a\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\",\" \",\"x\",\")\",\" \",\"a\",\")\",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\",\" \",\"y\",\")\",\" \",\"a\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"f\",\"r\",\"i\",\"n\",\"g\",\"e\",\" \",\"x\",\")\",\" \",\")\",\" \",\"a\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"x\",\" \",\"a\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"x\",\" \",\"y\",\")\",\" \",\"z\",\")\",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"x\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"a\",\" \",\"b\",\")\",\" \",\")\",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"b\",\")\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"a\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"z\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\"z\",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"x\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"x\",\"e\",\"c\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"x\",\" \",\"y\",\")\",\"p\",\"d\",\"s\",\" \",\"e\",\"n\",\"v\",\"r\",\"n\",\")\",\"(\",\"e\",\"x\",\"e\",\"c\",\" \",\"y\",\" \",\"(\",\"e\",\"x\",\"e\",\"c\",\" \",\"x\",\" \",\"p\",\"d\",\"s\",\" \",\"e\",\"n\",\"v\",\"r\",\"n\",\")\",\"e\",\"n\",\"v\",\"r\",\"n\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"m\",\"c\",\"-\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"(\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"x\",\")\",\"y\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"x\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"a\",\" \",\"b\",\")\",\" \",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"x\",\" \",\"a\",\")\",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"x\",\" \",\"b\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"x\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"n\",\"g\",\"t\",\"h\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"x\",\")\",\" \",\")\",\"(\",\"l\",\"e\",\"n\",\"g\",\"t\",\"h\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"a\",\" \",\"(\",\"i\",\"n\",\"t\",\"e\",\"r\",\"s\",\"e\",\"c\",\"t\",\" \",\"b\",\" \",\"c\",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"a\",\" \",\"b\",\")\",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"a\",\" \",\"c\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"n\",\"t\",\"h\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\"i\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"x\",\"p\",\" \",\"i\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"j\",\" \",\"k\",\")\",\" \",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"(\",\"e\",\"x\",\"p\",\" \",\"i\",\" \",\"j\",\")\",\"(\",\"e\",\"x\",\"p\",\" \",\"i\",\" \",\"k\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"x\",\"p\",\" \",\"i\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"j\",\" \",\"k\",\")\",\" \",\")\",\"(\",\"e\",\"x\",\"p\",\" \",\"(\",\"e\",\"x\",\"p\",\" \",\"i\",\" \",\"j\",\")\",\"k\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\"l\",\"o\",\"o\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"x\",\")\",\"y\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\"l\",\"o\",\"o\",\"p\",\" \",\"x\",\" \",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\" \",\")\",\"(\",\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"c\",\"o\",\"u\",\"n\",\"t\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"z\",\" \",\"(\",\"s\",\"o\",\"r\",\"t\",\"-\",\"l\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"c\",\"o\",\"u\",\"n\",\"t\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"z\",\" \",\"x\",\")\",\"(\",\"c\",\"o\",\"u\",\"n\",\"t\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"z\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"a\",\" \",\"b\",\")\",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"a\",\" \",\"c\",\")\",\" \",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"b\",\" \",\"c\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"y\",\" \",\"(\",\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\",\" \",\"(\",\"b\",\"i\",\"g\",\"-\",\"p\",\"l\",\"u\",\"s\",\"1\",\" \",\"l\",\" \",\"i\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\"b\",\"a\",\"s\",\"e\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\",\" \",\"l\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\"i\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\",\" \",\"(\",\"b\",\"i\",\"g\",\"-\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\" \",\"i\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\"b\",\"a\",\"s\",\"e\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"i\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\",\" \",\"x\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\",\" \",\"y\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"y\",\" \",\"1\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\"y\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"x\",\" \",\"x\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"(\",\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\",\" \",\"i\",\" \",\"j\",\")\",\"i\",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"i\",\")\",\" \",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"j\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"j\",\" \",\"1\",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\"x\",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"x\",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"r\",\"e\",\"p\",\" \",\"i\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\"b\",\"a\",\"s\",\"e\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"i\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\",\" \",\"(\",\"b\",\"i\",\"g\",\"-\",\"p\",\"l\",\"u\",\"s\",\" \",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"r\",\"e\",\"p\",\" \",\"i\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\"(\",\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"r\",\"e\",\"p\",\" \",\"j\",\" \",\"b\",\"a\",\"s\",\"e\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\"b\",\"a\",\"s\",\"e\",\")\",\"b\",\"a\",\"s\",\"e\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"i\",\" \",\"j\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"c\",\"d\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"g\",\"c\",\"d\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"n\",\"t\",\"h\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"a\",\" \",\"b\",\")\",\"i\",\")\",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"(\",\"n\",\"t\",\"h\",\" \",\"a\",\" \",\"i\",\")\",\"(\",\"n\",\"t\",\"h\",\" \",\"b\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"i\",\" \",\"(\",\"l\",\"e\",\"n\",\"g\",\"t\",\"h\",\" \",\"a\",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\"x\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"y\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"y\",\" \",\"x\",\")\",\"x\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"y\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"z\",\")\",\" \",\")\",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"c\",\" \",\"w\",\")\",\" \",\")\",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"c\",\" \",\"x\",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"w\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"z\",\")\",\"z\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"b\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"a\",\" \",\"c\",\")\",\" \",\")\",\"a\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"b\",\" \",\"c\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"y\",\" \",\"z\",\")\",\"z\",\")\",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"y\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"z\",\" \",\")\",\" \",\")\",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"z\",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"z\",\")\",\" \",\")\",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"c\",\"d\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"z\",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"z\",\" \",\"(\",\"g\",\"c\",\"d\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"v\",\"a\",\"l\",\"u\",\"e\",\" \",\"(\",\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\"i\",\"z\",\"e\",\" \",\"x\",\")\",\"a\",\")\",\"(\",\"v\",\"a\",\"l\",\"u\",\"e\",\" \",\"x\",\" \",\"a\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"x\",\")\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"y\",\" \",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\" \",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"l\",\"i\",\"s\",\"t\",\"p\",\" \",\"x\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"i\",\"s\",\"t\",\"p\",\" \",\"(\",\"g\",\"o\",\"p\",\"h\",\"e\",\"r\",\" \",\"x\",\")\",\" \",\")\",\"(\",\"l\",\"i\",\"s\",\"t\",\"p\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"s\",\"a\",\"m\",\"e\",\"f\",\"r\",\"i\",\"n\",\"g\",\"e\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"x\",\")\",\"(\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"s\",\"t\",\"-\",\"f\",\"a\",\"c\",\"t\",\"o\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"o\",\"r\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"y\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"y\",\" \",\"1\",\")\",\" \",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"s\",\"t\",\"-\",\"f\",\"a\",\"c\",\"t\",\"o\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\"1\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"1\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"(\",\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"s\",\"t\",\"-\",\"f\",\"a\",\"c\",\"t\",\"o\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"o\",\"r\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"y\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"y\",\" \",\"1\",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"x\",\")\",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"r\",\"i\",\"m\",\"e\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"p\",\"r\",\"i\",\"m\",\"e\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"x\",\")\",\"(\",\"p\",\"r\",\"i\",\"m\",\"e\",\"-\",\"l\",\"i\",\"s\",\"t\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"z\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"w\",\" \",\"z\",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"z\",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"z\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"w\",\" \",\"1\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"e\",\"q\",\"p\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"o\",\"r\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"x\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"x\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"y\",\" \",\"1\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"y\",\" \",\"x\",\")\",\"y\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"a\",\" \",\"b\",\")\",\"1\",\")\",\"(\",\"a\",\"n\",\"d\",\" \",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"a\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"b\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"a\",\")\",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"b\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"1\",\"-\",\" \",\"a\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"1\",\"-\",\" \",\"b\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"(\",\"l\",\"e\",\"n\",\"g\",\"t\",\"h\",\" \",\"(\",\"d\",\"e\",\"l\",\"e\",\"t\",\"e\",\" \",\"x\",\" \",\"l\",\")\",\" \",\")\",\"(\",\"l\",\"e\",\"n\",\"g\",\"t\",\"h\",\" \",\"l\",\")\",\" \",\")\",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"x\",\" \",\"l\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"s\",\"o\",\"r\",\"t\",\"2\",\" \",\"(\",\"d\",\"e\",\"l\",\"e\",\"t\",\"e\",\" \",\"x\",\" \",\"l\",\")\",\" \",\")\",\"(\",\"d\",\"e\",\"l\",\"e\",\"t\",\"e\",\" \",\"x\",\" \",\"(\",\"s\",\"o\",\"r\",\"t\",\"2\",\" \",\"l\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"s\",\"o\",\"r\",\"t\",\" \",\"x\",\")\",\"(\",\"s\",\"o\",\"r\",\"t\",\"2\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"n\",\"g\",\"t\",\"h\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"x\",\"1\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"x\",\"2\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"x\",\"3\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"x\",\"4\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"x\",\"5\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"x\",\"6\",\" \",\"x\",\"7\",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"6\",\" \",\"(\",\"l\",\"e\",\"n\",\"g\",\"t\",\"h\",\" \",\"x\",\"7\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"x\",\")\",\" \",\")\",\"2\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"x\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"2\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"(\",\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\",\" \",\"y\",\" \",\"2\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"s\",\"i\",\"g\",\"m\",\"a\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\"i\",\")\",\"(\",\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"i\",\" \",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"i\",\")\",\" \",\")\",\"2\",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"y\",\")\",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"z\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"z\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"z\",\" \",\"y\",\")\",\"(\",\"n\",\"o\",\"t\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"y\",\" \",\"x\",\")\",\" \",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"i\",\"x\",\" \",\"x\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"z\",\")\",\" \",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\",\" \",\"(\",\"d\",\"e\",\"l\",\"e\",\"t\",\"e\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"a\",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"m\",\"e\",\"m\",\"b\",\"e\",\"r\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\",\" \",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\",\" \",\"y\",\")\",\"a\",\")\",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"x\",\" \",\"a\",\")\",\" \",\")\",\"(\",\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\",\" \",\"(\",\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\",\" \",\"y\",\")\",\"a\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"(\",\"a\",\"d\",\"d\",\"1\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\",\" \",\"y\",\")\",\"(\",\"p\",\"l\",\"u\",\"s\",\" \",\"x\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"x\",\" \",\"y\",\")\",\" \",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"n\",\"t\",\"h\",\" \",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\"i\",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"i\",\")\",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"a\",\"s\",\"t\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"a\",\" \",\"b\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"l\",\"i\",\"s\",\"t\",\"p\",\" \",\"b\",\")\",\"(\",\"l\",\"a\",\"s\",\"t\",\" \",\"b\",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"l\",\"i\",\"s\",\"t\",\"p\",\" \",\"a\",\")\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"(\",\"c\",\"a\",\"r\",\" \",\"(\",\"l\",\"a\",\"s\",\"t\",\" \",\"a\",\")\",\" \",\")\",\"b\",\")\",\"b\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"z\",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"l\",\"e\",\"s\",\"s\",\"p\",\" \",\"x\",\" \",\"y\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"t\",\" \",\"z\",\")\",\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"f\",\" \",\"z\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"m\",\"e\",\"n\",\"t\",\" \",\"x\",\" \",\"(\",\"a\",\"p\",\"p\",\"e\",\"n\",\"d\",\" \",\"a\",\" \",\"b\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"e\",\"d\",\"p\",\" \",\"x\",\" \",\"a\",\")\",\"(\",\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"m\",\"e\",\"n\",\"t\",\" \",\"x\",\" \",\"a\",\")\",\"(\",\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"m\",\"e\",\"n\",\"t\",\" \",\"x\",\" \",\"b\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"c\",\"a\",\"r\",\" \",\"(\",\"g\",\"o\",\"p\",\"h\",\"e\",\"r\",\" \",\"x\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"l\",\"i\",\"s\",\"t\",\"p\",\" \",\"x\",\")\",\"(\",\"c\",\"a\",\"r\",\" \",\"(\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"x\",\")\",\" \",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"(\",\"c\",\"d\",\"r\",\" \",\"(\",\"g\",\"o\",\"p\",\"h\",\"e\",\"r\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"l\",\"i\",\"s\",\"t\",\"p\",\" \",\"x\",\")\",\"(\",\"c\",\"d\",\"r\",\" \",\"(\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\",\" \",\"x\",\")\",\" \",\")\",\"(\",\"C\",\"o\",\"n\",\"s\",\"s\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\"(\",\"N\",\"i\",\"l\",\"l\",\")\",\" \",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\",\" \",\"(\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"y\",\" \",\"x\",\")\",\"y\",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"z\",\"e\",\"r\",\"o\",\"p\",\" \",\"y\",\")\",\"(\",\"z\",\"e\",\"r\",\"o\",\")\",\"(\",\"f\",\"i\",\"x\",\" \",\"x\",\")\",\" \",\")\",\" \",\")\"],[\"(\",\"e\",\"q\",\"u\",\"a\",\"l\",\" \",\"(\",\"g\",\"e\",\"t\",\" \",\"j\",\" \",\"(\",\"s\",\"e\",\"t\",\" \",\"i\",\" \",\"v\",\"a\",\"l\",\" \",\"m\",\"e\",\"m\",\")\",\" \",\")\",\"(\",\"i\",\"f\",\" \",\"(\",\"e\",\"q\",\"p\",\" \",\"j\",\" \",\"i\",\")\",\"v\",\"a\",\"l\",\"(\",\"g\",\"e\",\"t\",\" \",\"j\",\" \",\"m\",\"e\",\"m\",\")\",\" \",\")\",\" \",\")\"]]\n\nval lemmas = addlemmalst(makelemmas(rules), Empty)\n//│ lemmas = Node([Node([Node([Node([Node([Empty, [[\"a\",\"n\",\"d\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Atom([\"p\"]), Conss([Atom([\"q\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"p\"]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"q\"]), Conss([Conss([Atom([\"t\"]), Nill]), Conss([Conss([Atom([\"f\"]), Nill]), Nill])])])]), Conss([Conss([Atom([\"f\"]), Nill]), Nill])])])]), Nill])])])]], Node([Empty, [[\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [[\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"m\",\"e\",\"n\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"m\",\"e\",\"n\",\"t\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"e\",\"d\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"m\",\"e\",\"n\",\"t\"]), Conss([Atom([\"x\"]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"s\",\"s\",\"i\",\"g\",\"n\",\"m\",\"e\",\"n\",\"t\"]), Conss([Atom([\"x\"]), Conss([Atom([\"b\"]), Nill])])]), Nill])])])]), Nill])])])]], Empty])])]), [[\"a\",\"s\",\"s\",\"u\",\"m\",\"e\",\"-\",\"f\",\"a\",\"l\",\"s\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"a\",\"s\",\"s\",\"u\",\"m\",\"e\",\"-\",\"f\",\"a\",\"l\",\"s\",\"e\"]), Conss([Atom([\"v\",\"a\",\"r\"]), Conss([Atom([\"a\",\"l\",\"i\",\"s\",\"t\"]), Nill])])]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"v\",\"a\",\"r\"]), Conss([Conss([Atom([\"f\"]), Nill]), Nill])])]), Conss([Atom([\"a\",\"l\",\"i\",\"s\",\"t\"]), Nill])])]), Nill])])])]], Empty]), [[\"a\",\"s\",\"s\",\"u\",\"m\",\"e\",\"-\",\"t\",\"r\",\"u\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"a\",\"s\",\"s\",\"u\",\"m\",\"e\",\"-\",\"t\",\"r\",\"u\",\"e\"]), Conss([Atom([\"v\",\"a\",\"r\"]), Conss([Atom([\"a\",\"l\",\"i\",\"s\",\"t\"]), Nill])])]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"v\",\"a\",\"r\"]), Conss([Conss([Atom([\"t\"]), Nill]), Nill])])]), Conss([Atom([\"a\",\"l\",\"i\",\"s\",\"t\"]), Nill])])]), Nill])])])]], Empty]), [[\"b\",\"o\",\"o\",\"l\",\"e\",\"a\",\"n\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"b\",\"o\",\"o\",\"l\",\"e\",\"a\",\"n\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"t\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"f\"]), Nill]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [[\"c\",\"a\",\"r\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"c\",\"a\",\"r\"]), Conss([Conss([Atom([\"g\",\"o\",\"p\",\"h\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"l\",\"i\",\"s\",\"t\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"c\",\"a\",\"r\"]), Conss([Conss([Atom([\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])])]), Nill])])])]], Empty])]), [[\"c\",\"o\",\"m\",\"p\",\"i\",\"l\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"c\",\"o\",\"m\",\"p\",\"i\",\"l\",\"e\"]), Conss([Atom([\"f\",\"o\",\"r\",\"m\"]), Nill])]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Conss([Atom([\"c\",\"o\",\"d\",\"e\",\"g\",\"e\",\"n\"]), Conss([Conss([Atom([\"o\",\"p\",\"t\",\"i\",\"m\",\"i\",\"z\",\"e\"]), Conss([Atom([\"f\",\"o\",\"r\",\"m\"]), Nill])]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Nill])])]), Nill])]), Nill])])])]], Node([Node([Node([Empty, [[\"c\",\"o\",\"u\",\"n\",\"t\",\"-\",\"l\",\"i\",\"s\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"c\",\"o\",\"u\",\"n\",\"t\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Atom([\"z\"]), Conss([Conss([Atom([\"s\",\"o\",\"r\",\"t\",\"-\",\"l\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"c\",\"o\",\"u\",\"n\",\"t\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Atom([\"z\"]), Conss([Atom([\"x\"]), Nill])])]), Conss([Conss([Atom([\"c\",\"o\",\"u\",\"n\",\"t\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Atom([\"z\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Nill])])])]], Empty]), [[\"c\",\"o\",\"u\",\"n\",\"t\",\"p\",\"s\",\"-\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"c\",\"o\",\"u\",\"n\",\"t\",\"p\",\"s\",\"-\"]), Conss([Atom([\"l\"]), Conss([Atom([\"p\",\"r\",\"e\",\"d\"]), Nill])])]), Conss([Conss([Atom([\"c\",\"o\",\"u\",\"n\",\"t\",\"p\",\"s\",\"-\",\"l\",\"o\",\"o\",\"p\"]), Conss([Atom([\"l\"]), Conss([Atom([\"p\",\"r\",\"e\",\"d\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])])]), Nill])])])]], Node([Node([Empty, [[\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Atom([\"2\"]), Nill])])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Nill])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"b\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"a\"]), Conss([Atom([\"c\"]), Nill])])]), Nill])])]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"b\"]), Conss([Atom([\"c\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Conss([Atom([\"x\"]), Nill])])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"x\"]), Nill])])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"x\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])])]], Empty]), [[\"d\",\"i\",\"v\",\"i\",\"d\",\"e\",\"s\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"v\",\"i\",\"d\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])]), Nill])])])]], Node([Empty, [[\"d\",\"s\",\"o\",\"r\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"s\",\"o\",\"r\",\"t\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"s\",\"o\",\"r\",\"t\",\"2\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])])]], Empty])])]), [[\"e\",\"q\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Nill])])])]], Node([Node([Node([Node([Empty, [[\"e\",\"q\",\"u\",\"a\",\"l\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"t\"]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"f\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"z\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"z\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"z\"]), Nill])]), Nill])])]), Nill])])])]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Conss([Atom([\"1\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"a\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Nill])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"b\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Nill])]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"a\"]), Nill])]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"b\"]), Nill])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"1\",\"-\"]), Conss([Atom([\"a\"]), Nill])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"1\",\"-\"]), Conss([Atom([\"b\"]), Nill])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Nill])])])])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"y\"]), Conss([Atom([\"1\"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"z\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"w\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"z\"]), Nill])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"z\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"w\"]), Conss([Atom([\"1\"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"s\",\"t\",\"-\",\"f\",\"a\",\"c\",\"t\",\"o\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"1\"]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Atom([\"1\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"s\",\"t\",\"-\",\"f\",\"a\",\"c\",\"t\",\"o\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"y\"]), Conss([Atom([\"1\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"y\"]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"l\",\"i\",\"s\",\"t\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"a\"]), Conss([Atom([\"c\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"b\"]), Conss([Atom([\"c\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"a\"]), Conss([Atom([\"c\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"b\"]), Nill])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"c\"]), Nill])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"a\"]), Nill])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"b\"]), Nill])]), Nill])])]), Nill])])])]], Empty]), [[\"e\",\"v\",\"e\",\"n\",\"1\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"v\",\"e\",\"n\",\"1\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"t\"]), Nill]), Conss([Conss([Atom([\"o\",\"d\",\"d\"]), Conss([Conss([Atom([\"1\",\"-\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Nill])])])]), Nill])])])]], Node([Node([Empty, [[\"e\",\"x\",\"e\",\"c\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"x\",\"e\",\"c\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"p\",\"d\",\"s\"]), Conss([Atom([\"e\",\"n\",\"v\",\"r\",\"n\"]), Nill])])])]), Conss([Conss([Atom([\"e\",\"x\",\"e\",\"c\"]), Conss([Atom([\"y\"]), Conss([Conss([Atom([\"e\",\"x\",\"e\",\"c\"]), Conss([Atom([\"x\"]), Conss([Atom([\"p\",\"d\",\"s\"]), Conss([Atom([\"e\",\"n\",\"v\",\"r\",\"n\"]), Nill])])])]), Conss([Atom([\"e\",\"n\",\"v\",\"r\",\"n\"]), Nill])])])]), Nill])])])]], Node([Empty, [[\"e\",\"x\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"x\",\"p\"]), Conss([Atom([\"i\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"j\"]), Conss([Atom([\"k\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"e\",\"x\",\"p\"]), Conss([Conss([Atom([\"e\",\"x\",\"p\"]), Conss([Atom([\"i\"]), Conss([Atom([\"j\"]), Nill])])]), Conss([Atom([\"k\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"e\",\"x\",\"p\"]), Conss([Atom([\"i\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"j\"]), Conss([Atom([\"k\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Conss([Atom([\"e\",\"x\",\"p\"]), Conss([Atom([\"i\"]), Conss([Atom([\"j\"]), Nill])])]), Conss([Conss([Atom([\"e\",\"x\",\"p\"]), Conss([Atom([\"i\"]), Conss([Atom([\"k\"]), Nill])])]), Nill])])]), Nill])])])]], Empty])]), [[\"f\",\"a\",\"c\",\"t\",\"-\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"a\",\"c\",\"t\",\"-\"]), Conss([Atom([\"i\"]), Nill])]), Conss([Conss([Atom([\"f\",\"a\",\"c\",\"t\",\"-\",\"l\",\"o\",\"o\",\"p\"]), Conss([Atom([\"i\"]), Conss([Atom([\"1\"]), Nill])])]), Nill])])])]], Node([Empty, [[\"f\",\"a\",\"l\",\"s\",\"i\",\"f\",\"y\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"a\",\"l\",\"s\",\"i\",\"f\",\"y\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"f\",\"a\",\"l\",\"s\",\"i\",\"f\",\"y\",\"1\"]), Conss([Conss([Atom([\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\"i\",\"z\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Nill])])]), Nill])])])]], Node([Empty, [[\"f\",\"i\",\"x\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])])]), Nill])])])]], Node([Node([Empty, [[\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Conss([Atom([\"c\",\"d\",\"r\"]), Conss([Conss([Atom([\"g\",\"o\",\"p\",\"h\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"l\",\"i\",\"s\",\"t\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"c\",\"d\",\"r\"]), Conss([Conss([Atom([\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Nill])])]), Nill])])])]), Nill])])])]], Empty]), [[\"g\",\"c\",\"d\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"c\",\"d\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"z\"]), Conss([Conss([Atom([\"g\",\"c\",\"d\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"c\",\"d\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"g\",\"c\",\"d\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])])])]], Node([Empty, [[\"g\",\"e\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"e\",\"t\"]), Conss([Atom([\"j\"]), Conss([Conss([Atom([\"s\",\"e\",\"t\"]), Conss([Atom([\"i\"]), Conss([Atom([\"v\",\"a\",\"l\"]), Conss([Atom([\"m\",\"e\",\"m\"]), Nill])])])]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"e\",\"q\",\"p\"]), Conss([Atom([\"j\"]), Conss([Atom([\"i\"]), Nill])])]), Conss([Atom([\"v\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"e\",\"t\"]), Conss([Atom([\"j\"]), Conss([Atom([\"m\",\"e\",\"m\"]), Nill])])]), Nill])])])]), Nill])])])]], Empty])])])])])]), [[\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"e\",\"q\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"e\",\"q\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])]), Nill])])])]], Node([Empty, [[\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"e\",\"q\",\"p\",\"r\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"e\",\"q\",\"p\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Nill])])])]], Empty])]), [[\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"r\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])])])]], Node([Node([Node([Empty, [[\"i\",\"f\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Conss([Atom([\"c\"]), Nill])])])]), Conss([Atom([\"d\"]), Conss([Atom([\"e\"]), Nill])])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"a\"]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"b\"]), Conss([Atom([\"d\"]), Conss([Atom([\"e\"]), Nill])])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"c\"]), Conss([Atom([\"d\"]), Conss([Atom([\"e\"]), Nill])])])]), Nill])])])]), Nill])])])]], Empty]), [[\"i\",\"f\",\"f\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"i\",\"f\",\"f\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [[\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"i\",\"m\",\"p\",\"l\",\"i\",\"e\",\"s\"]), Conss([Atom([\"p\"]), Conss([Atom([\"q\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"p\"]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"q\"]), Conss([Conss([Atom([\"t\"]), Nill]), Conss([Conss([Atom([\"f\"]), Nill]), Nill])])])]), Conss([Conss([Atom([\"t\"]), Nill]), Nill])])])]), Nill])])])]], Node([Node([Empty, [[\"l\",\"a\",\"s\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"a\",\"s\",\"t\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"l\",\"i\",\"s\",\"t\",\"p\"]), Conss([Atom([\"b\"]), Nill])]), Conss([Conss([Atom([\"l\",\"a\",\"s\",\"t\"]), Conss([Atom([\"b\"]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"l\",\"i\",\"s\",\"t\",\"p\"]), Conss([Atom([\"a\"]), Nill])]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Conss([Atom([\"c\",\"a\",\"r\"]), Conss([Conss([Atom([\"l\",\"a\",\"s\",\"t\"]), Conss([Atom([\"a\"]), Nill])]), Nill])]), Conss([Atom([\"b\"]), Nill])])]), Conss([Atom([\"b\"]), Nill])])])]), Nill])])])]), Nill])])])]], Empty]), [[\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"x\",\"1\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"x\",\"2\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"x\",\"3\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"x\",\"4\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"x\",\"5\"]), Conss([Conss([Atom([\"C\",\"o\",\"n\",\"s\",\"s\"]), Conss([Atom([\"x\",\"6\"]), Conss([Atom([\"x\",\"7\"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Nill])])]), Nill])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"6\"]), Conss([Conss([Atom([\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"]), Conss([Atom([\"x\",\"7\"]), Nill])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])])]], Empty])])]), [[\"l\",\"e\",\"s\",\"s\",\"e\",\"q\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"e\",\"q\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])]), Nill])])])]], Node([Node([Node([Node([Node([Node([Node([Empty, [[\"l\",\"e\",\"s\",\"s\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Conss([Atom([\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"]), Conss([Conss([Atom([\"d\",\"e\",\"l\",\"e\",\"t\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"l\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"]), Conss([Atom([\"l\"]), Nill])]), Nill])])]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"l\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"z\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"x\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Conss([Atom([\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\"]), Conss([Atom([\"i\"]), Conss([Atom([\"j\"]), Nill])])]), Conss([Atom([\"i\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"i\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"j\"]), Nill])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"j\"]), Conss([Atom([\"1\"]), Nill])])]), Nill])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"e\",\"s\",\"s\",\"p\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Nill])]), Nill])])])]], Node([Empty, [[\"l\",\"i\",\"s\",\"t\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"l\",\"i\",\"s\",\"t\",\"p\"]), Conss([Conss([Atom([\"g\",\"o\",\"p\",\"h\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"l\",\"i\",\"s\",\"t\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])])]], Empty])]), [[\"m\",\"c\",\"-\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"m\",\"c\",\"-\",\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Conss([Atom([\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Atom([\"y\"]), Nill])])]), Nill])])])]], Empty]), [[\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\"]), Conss([Conss([Atom([\"d\",\"e\",\"l\",\"e\",\"t\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Atom([\"x\"]), Conss([Atom([\"a\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"f\",\"r\",\"i\",\"n\",\"g\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Atom([\"x\"]), Conss([Atom([\"a\"]), Nill])])]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"m\",\"e\",\"a\",\"n\",\"i\",\"n\",\"g\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\",\"-\",\"t\",\"r\",\"e\",\"e\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [[\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"a\"]), Conss([Conss([Atom([\"i\",\"n\",\"t\",\"e\",\"r\",\"s\",\"e\",\"c\",\"t\"]), Conss([Atom([\"b\"]), Conss([Atom([\"c\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"a\"]), Conss([Atom([\"c\"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"m\",\"e\",\"m\",\"b\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"b\"]), Nill])])]), Nill])])]), Nill])])])]], Empty])]), [[\"n\",\"o\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Atom([\"p\"]), Nill])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"p\"]), Conss([Conss([Atom([\"f\"]), Nill]), Conss([Conss([Atom([\"t\"]), Nill]), Nill])])])]), Nill])])])]], Node([Empty, [[\"n\",\"t\",\"h\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"n\",\"t\",\"h\"]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Conss([Atom([\"i\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"i\"]), Nill])]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"n\",\"t\",\"h\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Conss([Atom([\"i\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"t\",\"h\"]), Conss([Atom([\"a\"]), Conss([Atom([\"i\"]), Nill])])]), Conss([Conss([Atom([\"n\",\"t\",\"h\"]), Conss([Atom([\"b\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"i\"]), Conss([Conss([Atom([\"l\",\"e\",\"n\",\"g\",\"t\",\"h\"]), Conss([Atom([\"a\"]), Nill])]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"n\",\"t\",\"h\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Conss([Atom([\"i\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])])]], Node([Empty, [[\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Conss([Atom([\"g\",\"r\",\"e\",\"a\",\"t\",\"e\",\"s\",\"t\",\"-\",\"f\",\"a\",\"c\",\"t\",\"o\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"y\"]), Conss([Atom([\"1\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Nill])])]), Nill])]), Nill])])])]], Empty])])]), [[\"o\",\"r\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Atom([\"p\"]), Conss([Atom([\"q\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"p\"]), Conss([Conss([Atom([\"t\"]), Nill]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Atom([\"q\"]), Conss([Conss([Atom([\"t\"]), Nill]), Conss([Conss([Atom([\"f\"]), Nill]), Nill])])])]), Nill])])])]), Nill])])])]], Node([Empty, [[\"p\",\"l\",\"u\",\"s\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Conss([Atom([\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Nill])])])]], Node([Empty, [[\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"]), Conss([Conss([Atom([\"b\",\"i\",\"g\",\"-\",\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"r\",\"e\",\"p\"]), Conss([Atom([\"i\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"r\",\"e\",\"p\"]), Conss([Atom([\"j\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])])])]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"i\"]), Conss([Atom([\"j\"]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"r\",\"e\",\"p\"]), Conss([Atom([\"i\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"i\"]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"]), Conss([Conss([Atom([\"b\",\"i\",\"g\",\"-\",\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Conss([Atom([\"i\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])])])]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"i\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"]), Conss([Atom([\"y\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"]), Conss([Conss([Atom([\"b\",\"i\",\"g\",\"-\",\"p\",\"l\",\"u\",\"s\",\"1\"]), Conss([Atom([\"l\"]), Conss([Atom([\"i\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])])]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"p\",\"o\",\"w\",\"e\",\"r\",\"-\",\"e\",\"v\",\"a\",\"l\"]), Conss([Atom([\"l\"]), Conss([Atom([\"b\",\"a\",\"s\",\"e\"]), Nill])])]), Conss([Atom([\"i\"]), Nill])])]), Nill])])])]], Empty])])]), [[\"p\",\"r\",\"i\",\"m\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"r\",\"i\",\"m\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])]), Nill])])]), Nill])]), Conss([Conss([Atom([\"p\",\"r\",\"i\",\"m\",\"e\",\"1\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"1\",\"-\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])]), Nill])])])]), Nill])])])]], Node([Node([Node([Empty, [[\"p\",\"r\",\"i\",\"m\",\"e\",\"-\",\"l\",\"i\",\"s\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"p\",\"r\",\"i\",\"m\",\"e\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"a\",\"n\",\"d\"]), Conss([Conss([Atom([\"p\",\"r\",\"i\",\"m\",\"e\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"p\",\"r\",\"i\",\"m\",\"e\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Nill])])])]], Node([Empty, [[\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Atom([\"2\"]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\"]), Conss([Atom([\"y\"]), Conss([Atom([\"2\"]), Nill])])]), Nill])])]), Nill])])])]], Empty])]), [[\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"x\"]), Nill])])]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"z\"]), Nill])])]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Conss([Atom([\"x\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"m\",\"a\",\"i\",\"n\",\"d\",\"e\",\"r\"]), Conss([Atom([\"y\"]), Conss([Atom([\"1\"]), Nill])])]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])])]], Empty]), [[\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"a\"]), Conss([Atom([\"b\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Atom([\"b\"]), Nill])]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Atom([\"a\"]), Nill])]), Nill])])]), Nill])])])]], Empty])]), [[\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\"l\",\"o\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Nill])])]), Nill])])])]], Node([Node([Empty, [[\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\"l\",\"o\",\"o\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\"l\",\"o\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\",\"-\",\"l\",\"o\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Conss([Atom([\"r\",\"e\",\"v\",\"e\",\"r\",\"s\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Atom([\"y\"]), Nill])])]), Nill])])])]], Node([Empty, [[\"s\",\"a\",\"m\",\"e\",\"f\",\"r\",\"i\",\"n\",\"g\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"s\",\"a\",\"m\",\"e\",\"f\",\"r\",\"i\",\"n\",\"g\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"f\",\"l\",\"a\",\"t\",\"t\",\"e\",\"n\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Nill])])])]], Node([Node([Empty, [[\"s\",\"i\",\"g\",\"m\",\"a\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"s\",\"i\",\"g\",\"m\",\"a\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Conss([Atom([\"i\"]), Nill])])]), Conss([Conss([Atom([\"q\",\"u\",\"o\",\"t\",\"i\",\"e\",\"n\",\"t\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"i\"]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Atom([\"i\"]), Nill])]), Nill])])]), Conss([Atom([\"2\"]), Nill])])]), Nill])])])]], Empty]), [[\"s\",\"o\",\"r\",\"t\",\"2\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"s\",\"o\",\"r\",\"t\",\"2\"]), Conss([Conss([Atom([\"d\",\"e\",\"l\",\"e\",\"t\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"l\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"d\",\"e\",\"l\",\"e\",\"t\",\"e\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"s\",\"o\",\"r\",\"t\",\"2\"]), Conss([Atom([\"l\"]), Nill])]), Nill])])]), Nill])])])]], Empty])])]), [[\"t\",\"a\",\"u\",\"t\",\"o\",\"l\",\"o\",\"g\",\"y\",\"-\",\"c\",\"h\",\"e\",\"c\",\"k\",\"e\",\"r\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"a\",\"u\",\"t\",\"o\",\"l\",\"o\",\"g\",\"y\",\"-\",\"c\",\"h\",\"e\",\"c\",\"k\",\"e\",\"r\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"t\",\"a\",\"u\",\"t\",\"o\",\"l\",\"o\",\"g\",\"y\",\"p\"]), Conss([Conss([Atom([\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\"i\",\"z\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"N\",\"i\",\"l\",\"l\"]), Nill]), Nill])])]), Nill])])])]], Node([Node([Empty, [[\"t\",\"i\",\"m\",\"e\",\"s\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"a\",\"d\",\"d\",\"1\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Conss([Conss([Atom([\"i\",\"f\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"y\"]), Nill])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"f\",\"i\",\"x\"]), Conss([Atom([\"x\"]), Nill])]), Nill])])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Atom([\"c\"]), Conss([Atom([\"w\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"c\",\"e\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"c\"]), Conss([Atom([\"x\"]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"w\"]), Conss([Atom([\"x\"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Atom([\"z\"]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Nill])])]),Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Atom([\"y\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Conss([Conss([Atom([\"p\",\"l\",\"u\",\"s\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Atom([\"x\"]), Conss([Atom([\"z\"]), Nill])])]), Nill])])]), Nill])])])]], Node([Node([Empty, [[\"t\",\"i\",\"m\",\"e\",\"s\",\"-\",\"l\",\"i\",\"s\",\"t\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Conss([Atom([\"a\",\"p\",\"p\",\"e\",\"n\",\"d\"]), Conss([Atom([\"x\"]), Conss([Atom([\"y\"]), Nill])])]), Nill])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\"]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"t\",\"i\",\"m\",\"e\",\"s\",\"-\",\"l\",\"i\",\"s\",\"t\"]), Conss([Atom([\"y\"]), Nill])]), Nill])])]), Nill])])])]], Empty]), [[\"v\",\"a\",\"l\",\"u\",\"e\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"v\",\"a\",\"l\",\"u\",\"e\"]), Conss([Conss([Atom([\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\"i\",\"z\",\"e\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Atom([\"a\"]), Nill])])]), Conss([Conss([Atom([\"v\",\"a\",\"l\",\"u\",\"e\"]), Conss([Atom([\"x\"]), Conss([Atom([\"a\"]), Nill])])]), Nill])])])]], Empty])]), [[\"z\",\"e\",\"r\",\"o\",\"p\"], [Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Conss([Conss([Atom([\"o\",\"r\"]), Conss([Conss([Atom([\"e\",\"q\",\"u\",\"a\",\"l\"]), Conss([Atom([\"x\"]), Conss([Conss([Atom([\"z\",\"e\",\"r\",\"o\"]), Nill]), Nill])])]), Conss([Conss([Atom([\"n\",\"o\",\"t\"]), Conss([Conss([Atom([\"n\",\"u\",\"m\",\"b\",\"e\",\"r\",\"p\"]), Conss([Atom([\"x\"]), Nill])]), Nill])]), Nill])])]), Nill])])])]], Empty])])])])])])])\n\nfun tautp(term) = tautologyp([rewrite(term, lemmas), Nill, Nill])\n\nfun teststatement(i) = applysubst(subterm(i), statement)\n\nfun testresult(i) = tautp(teststatement(i))\n\nfun testBoyer2_nofib(n) = report(testresult(n))\n\nfun main() = testBoyer2_nofib(3)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/calendar.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule calendar with ...\n\n\n\nfun unlines(ls) = concat(map(x => x +: (\"\\n\" :: Nil), ls))\n\nfun height(p) = listLen(p)\n\nfun width(p) = listLen(head(p))\n\nfun stack(ls) = foldr1((a, b) => a +: b, ls)\n\nfun spread(ls) = foldr1((a, b) => zipWith((a, b) => a +: b, a, b), ls)\n\nfun emptyPic(hw) = if hw is [h, w] then replicate(h, replicate(w, \" \"))\n\nfun groop(n, xs) = if xs is\n  Nil then Nil\n  else take(n, xs) :: groop(n, leave(n, xs))\n\nfun block(n, t)  = stack(map(spread, groop(n, t)))\n\nfun blockT(n, t) = stack(map(stack, groop(n, t)))\n\nfun lframe(mn, p) = if mn is [m,n] then\n  let h = height(p)\n  let w = width(p)\n  zipWith(append, p, emptyPic([h, n - w])) +: emptyPic([m - h, n])\n\nfun leap(year) = if\n  intMod(year, 100) == 0 then intMod(year, 400) == 0\n  else intMod(year, 4) == 0\n\nfun monthLengths(year) =\n  let feb = if leap(year) then 29 else 28\n  31 :: feb :: 31 :: 30 :: 31 :: 30 :: 31 :: 31 :: 30 :: 31 :: 30 :: 31 :: Nil\n\nval monthNames =\n  nofibStringToList(\"January\") ::\n  nofibStringToList(\"February\") ::\n  nofibStringToList(\"March\") ::\n  nofibStringToList(\"April\") ::\n  nofibStringToList(\"May\") ::\n  nofibStringToList(\"June\") ::\n  nofibStringToList(\"July\") ::\n  nofibStringToList(\"August\") ::\n  nofibStringToList(\"September\") ::\n  nofibStringToList(\"October\") ::\n  nofibStringToList(\"November\") ::\n  nofibStringToList(\"December\") :: Nil\n//│ monthNames = [[\"J\",\"a\",\"n\",\"u\",\"a\",\"r\",\"y\"],[\"F\",\"e\",\"b\",\"r\",\"u\",\"a\",\"r\",\"y\"],[\"M\",\"a\",\"r\",\"c\",\"h\"],[\"A\",\"p\",\"r\",\"i\",\"l\"],[\"M\",\"a\",\"y\"],[\"J\",\"u\",\"n\",\"e\"],[\"J\",\"u\",\"l\",\"y\"],[\"A\",\"u\",\"g\",\"u\",\"s\",\"t\"],[\"S\",\"e\",\"p\",\"t\",\"e\",\"m\",\"b\",\"e\",\"r\"],[\"O\",\"c\",\"t\",\"o\",\"b\",\"e\",\"r\"],[\"N\",\"o\",\"v\",\"e\",\"m\",\"b\",\"e\",\"r\"],[\"D\",\"e\",\"c\",\"e\",\"m\",\"b\",\"e\",\"r\"]]\n\nfun jan1st(year) =\n  let last = year - 1\n  intMod(year + intDiv(last, 4) - intDiv(last, 100) + intDiv(last, 400), 7)\n\nfun firstDays(year) =\n  take(12, map(x => intMod(x, 7), scanl((a, b) => a + b, jan1st(year), monthLengths(year))))\n\nfun space(n) = replicate(n, \" \")\n\nfun ljustify(n, s) = s +: space(n - listLen(s))\n\nfun rjustify(n, s) = space(n - listLen(s)) +: s\n\nfun date(ml, d) = if (d < 1) || (ml < d) then nofibStringToList(\"   \") :: Nil else rjustify(3, nofibStringToList(stringOfInt(d))) :: Nil\n\nfun dates(fd, ml) = map(d => date(ml, d), enumFromTo(1 - fd, 42 - fd))\n\nfun cjustify(n, s) =\n  let m = n - listLen(s)\n  let halfm = intDiv(m, 2)\n  space(halfm) +: s +: space(m - halfm)\n\nfun cal(year) =\n  let side = emptyPic([8, 2])\n  let end = emptyPic([1, 25])\n  let daynames = nofibStringToList(\" Su Mo Tu We Th Fr Sa\") :: Nil\n  fun banner(yr) = cjustify(75, nofibStringToList(stringOfInt(yr))) :: emptyPic([1, 75])\n  fun body(yr) = block(3, map(x => pad(pic(x)), months(yr)))\n  fun pic(mnfdml) = if mnfdml is [mn, fd, ml] then title(mn) +: table(fd, ml)\n  fun pad(p) = zipWith(append, zipWith(append, side, p), side) +: end\n  fun title(mn) = cjustify(21, mn) :: Nil\n  fun table(fd, ml) = daynames +: entries(fd, ml)\n  fun entries(fd, ml) = block(7, dates(fd, ml))\n  fun months(yer) = zip3(monthNames, firstDays(yer), monthLengths(yer))\n\n  unlines(banner(year) +: body(year))\n\nfun testCalendar_nofib(n) = map(x => cal(x), enumFromTo(1993, 1993 + n))\n\n\n// NOTE: original input: 1000\nfun main() =\n  nofibListToString of concat of testCalendar_nofib(0)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/cichelli.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule cichelli with ...\n\n\n\nval keys = \n  nofibStringToList(\"case\") :: nofibStringToList(\"class\") :: nofibStringToList(\"data\") :: nofibStringToList(\"default\") :: nofibStringToList(\"deriving\") :: nofibStringToList(\"else\") ::\n  nofibStringToList(\"hiding\") ::  nofibStringToList(\"if\") :: nofibStringToList(\"import\") :: nofibStringToList(\"in\") :: nofibStringToList(\"infix\") :: nofibStringToList(\"infixl\") :: nofibStringToList(\"instance\") ::\n  nofibStringToList(\"interface\") :: nofibStringToList(\"let\") :: nofibStringToList(\"module\") :: nofibStringToList(\"of\") :: nofibStringToList(\"renaming\") :: nofibStringToList(\"then\") :: nofibStringToList(\"to\") ::\n  nofibStringToList(\"type\") :: nofibStringToList(\"where\") :: Nil\n//│ keys = [[\"c\",\"a\",\"s\",\"e\"],[\"c\",\"l\",\"a\",\"s\",\"s\"],[\"d\",\"a\",\"t\",\"a\"],[\"d\",\"e\",\"f\",\"a\",\"u\",\"l\",\"t\"],[\"d\",\"e\",\"r\",\"i\",\"v\",\"i\",\"n\",\"g\"],[\"e\",\"l\",\"s\",\"e\"],[\"h\",\"i\",\"d\",\"i\",\"n\",\"g\"],[\"i\",\"f\"],[\"i\",\"m\",\"p\",\"o\",\"r\",\"t\"],[\"i\",\"n\"],[\"i\",\"n\",\"f\",\"i\",\"x\"],[\"i\",\"n\",\"f\",\"i\",\"x\",\"l\"],[\"i\",\"n\",\"s\",\"t\",\"a\",\"n\",\"c\",\"e\"],[\"i\",\"n\",\"t\",\"e\",\"r\",\"f\",\"a\",\"c\",\"e\"],[\"l\",\"e\",\"t\"],[\"m\",\"o\",\"d\",\"u\",\"l\",\"e\"],[\"o\",\"f\"],[\"r\",\"e\",\"n\",\"a\",\"m\",\"i\",\"n\",\"g\"],[\"t\",\"h\",\"e\",\"n\"],[\"t\",\"o\"],[\"t\",\"y\",\"p\",\"e\"],[\"w\",\"h\",\"e\",\"r\",\"e\"]]\n\nfun enumFromTo_lz(a, b) = lazy of () =>\n  if a <= b then LzCons(a, enumFromTo_lz(a + 1, b)) else LzNil\n\nfun last(ls) =\n  fun go(h, t) = if t is\n    Nil then h\n    head :: t then go(head, t)\n  if ls is\n    h :: t then go(h, t)\n    else throw Error(\"last: empty list\")\n\ndata class K(s: String, c1: Char, c2: Char, i: Int)\n\ndata class H(f: Option[Int], s: Option[Int], ls: List[Int])\n\nfun ends(k) = if k is K(_, a, z, _) then a :: z :: Nil\n\nfun assoc(x, yz) = if yz is\n  [y, z] :: yzs then if x === y then z else assoc(x, yzs)\n  else throw Error(\"assoc: not found\")\n\nfun assocm(x, yz) = if yz is\n  [y, z] :: yzs then if x === y then Some(z) else assocm(x, yzs)\n  else None\n\nfun histins(x, yns) = if yns is\n  [y, n] :: yns then if x === y then [y, n + 1] :: yns else [y, n] :: histins(x, yns)\n  else [x, 1] :: Nil\n\nfun histo(ls) = foldr(cichelli.histins, Nil, ls)\n\nfun subset(xs, ys) = all(x => inList(x, ys), xs)\n\nfun union(xs, ys) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and\n      not(inList(h, xs)) then h :: lscomp(t)\n      else lscomp(t)\n  append(xs, lscomp(ys))\n\nfun attribkeys(ks) = map(k => K(k, head(k), cichelli.last(k), listLen(k)), ks)\n\nval numberofkeys = listLen(keys)\n//│ numberofkeys = 22\n\nfun minm(x, y) = if x is\n  None then y\n  Some(x) then min(x, y)\n\nfun maxm(x, y) = if x is\n  None then y\n  Some(x) then max(x, y)\n\nfun hash(cvs, k) = if k is K(_, a, z, n) then n + assoc(a, cvs) + assoc(z, cvs)\n\nfun select(p, x, ts_fs) = if ts_fs is [ts, fs] and\n  p(x) then [x :: ts, fs]\n  else [ts, x :: fs]\n\nfun partition_(p, ls) = foldr((x, y) => select(p, x, y), [Nil, Nil], ls)\n\nfun freqsorted(x) = x\n\nfun blocked_(ds, ls) = if ls is\n  Nil then Nil\n  k :: ks then\n    let ds_ = union(ds, ends(k))\n    if partition_(x => subset(ends(x), ds_), ks) is [det, rest] then\n      k :: (det +: blocked_(ds_, rest))\n\nfun blocked(ls) = blocked_(Nil, ls)\n\nval freqtab = histo(concat(map(ends, attribkeys(keys))))\n//│ freqtab = [[\"e\", 8],[\"w\", 1],[\"t\", 6],[\"o\", 2],[\"n\", 2],[\"g\", 3],[\"r\", 1],[\"f\", 2],[\"m\", 1],[\"l\", 2],[\"i\", 7],[\"x\", 1],[\"h\", 1],[\"d\", 3],[\"a\", 1],[\"s\", 1],[\"c\", 2]]\n\nval maxval = listLen(freqtab)\n//│ maxval = 17\n\nabstract class Status[T]: NotEver | YesIts[T]\n\ndata\n  class\n    NotEver(i: Int) extends Status[Nothing]\n    YesIts[T](i: Int, t: T) extends Status[T]\n\nfun hinsert(h, hh) = if hh is H(lo, hi, hs) then\n  let lo_ = minm(lo, h)\n  let hi_ = maxm(hi, h)\n  if inList(h, hs) || (1 + hi_ - lo_) > numberofkeys\n  then None\n  else Some(H(Some(lo_), Some(hi_), h :: hs))\n\nfun first(k, ls) = if force(ls) is\n  LzNil then NotEver(k)\n  LzCons(a, l) and a is\n    YesIts(leaves, y) then YesIts(k + leaves, y)\n    NotEver(leaves) then first(k + leaves, l)\n\nfun firstSuccess(f, possibles) = first(0, map_lz(f, possibles))\n\nfun findhash_(keyHashSet, charAssocs, ks) = if ks is\n  Nil then YesIts(1, charAssocs)\n  K(s, a, z, n) :: ks then\n    fun tryy(newAssocs) =\n      let newCharAssocs = newAssocs +: charAssocs\n      if hinsert(hash(newCharAssocs, K(s, a, z, n)), keyHashSet) is\n        None then NotEver(1)\n        Some(newKeyHashSet) then findhash_(newKeyHashSet, newCharAssocs, ks)\n    if [assocm(a, charAssocs), assocm(z, charAssocs)] is\n      [None, None] and\n        a === z then firstSuccess(m => tryy([a, m] :: Nil), enumFromTo_lz(0, maxval))\n        else\n          fun lscomp1(ls1) = lazy of () =>\n            if force(ls1) is\n              LzNil then LzNil\n              LzCons(m, ms) then\n                fun lscomp2(ls2) =\n                  if force(ls2) is\n                    LzNil then lscomp1(ms)\n                    LzCons(n, ns) then lazy of () => LzCons([m, n], lscomp2(ns))\n                force(lscomp2(enumFromTo_lz(0, maxval)))\n          firstSuccess(case { [m, n] then tryy([a, m] :: [z, n] :: Nil) }, lscomp1(enumFromTo_lz(0, maxval)))\n      [None, Some(zc)] then firstSuccess(m => tryy([a, m] :: Nil), enumFromTo_lz(0, maxval))\n      [Some(ac), None] then firstSuccess(n => tryy([z, n] :: Nil), enumFromTo_lz(0, maxval))\n      [Some(ac), Some(zc)] then tryy(Nil)\n\nfun findhash(keys) = findhash_(H(None, None, Nil), Nil, keys)\n\nfun freq(c) = assoc(c, freqtab)\n\nfun morefreq(k1, k2) = if\n  k1 is K(_, a, x, _) and k2 is K(_, b, y, _) then (freq(a) + freq(x)) > (freq(b) + freq(y))\n\nfun cichelli_(n) =\n  let attribkeys_ = attribkeys(keys +: take(intMod(n, 2), keys))\n  let hashkeys = blocked(freqsorted(attribkeys_))\n  findhash(hashkeys)\n\nfun prog(n) = cichelli_(n)\n\nfun main() = prog(6).toString()"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/circsim.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule circsim with ...\n\n\n\nabstract class BinTree[T, U]: Cell[T] | Node[T, U]\n\ndata\n  class\n    Cell[T](value: T) extends BinTree[T, Nothing]\n    Node[T, U](value: U, left: BinTree[T, U], right: BinTree[T, U]) extends BinTree[T, U]\n\nabstract class Componenet: None_ | Inp | Outp | Dff | Inv | And2 | Or2 | Xor\n\nobject\n  None_ extends Componenet\n  Inp extends Componenet\n  Outp extends Componenet\n  Dff extends Componenet\n  Inv extends Componenet\n  And2 extends Componenet\n  Or2 extends Componenet\n  Xor extends Componenet\n\nobject Unit\n\ndata class PS[T](pid: Int, compType: Componenet, pathDepth: Int, inports: List[[Int, Int, T]], outports: List[[Int, T, Bool, Int, Bool, Int]])\n\nfun pid(p) = p.pid\n\nfun compType(p) = p.compType\n\nfun pathDepth(p) = p.pathDepth\n\nfun inports(p) = p.inports\n\nfun outports(p) = p.outports\n\nfun updateOutports(p, noutports) = PS(pid(p), compType(p), pathDepth(p), inports(p), noutports)\n\nfun updateInports(p, ninports) = PS(pid(p), compType(p), pathDepth(p), ninports, outports(p))\n\nabstract class Boolean: F | T\n\nobject\n  F extends Boolean\n  T extends Boolean\n\nfun put(xs) = if\n  xs is x :: Nil then Cell(x)\n  splitAt(intDiv(listLen(xs), 2), xs) is [fstHalf, sndHalf] then Node(Unit, put(fstHalf), put(sndHalf))\n\nfun get(t) = if t is\n  Cell(x) then x :: Nil\n  Node(_, l, r) then get(l) +: get(r)\n\nfun upsweep(f, t) = if t is\n  Cell(a) then [a, Cell(a)]\n  Node(x, l, r) and upsweep(f, l) is [lv, l_] and upsweep(f, r) is [rv, r_] then\n    [f(lv, rv), Node([lv, rv], l_, r_)]\n\nfun downsweep(g, d, t) = if t is\n  Cell(x) then Cell(d)\n  Node([lv, rv], l, r) and g(lv, rv, d) is [dl, dr] then\n    Node(Unit, downsweep(g, dl, l), downsweep(g, dr, r))\n\nfun sweep_ud(up, down, u, t) = if upsweep(up, t) is [ans, t_] then\n  [ans, downsweep(down, u, t_)]\n\nfun scanL(f, u, xs) =\n  fun down1(l, r, x) = [x, f(x, l)]\n  if sweep_ud(f, down1, u, put(xs)) is [up_ans, t_] then [up_ans, get(t_)]\n\nfun scanR(f, u, xs) =\n  fun down2(l, r, x) = [f(r, x), x]\n  if sweep_ud(f, down2, u, put(xs)) is [up_ans, t_] then [up_ans, get(t_)]\n\nfun scanlr(f, g, lu, ru, xs) =\n  fun up(f, g, lxly, rxry) = if lxly is [lx, ly] and rxry is [rx, ry] then [f(lx, rx), g(ly, ry)]\n\n  fun down3(f, g, lxly, rxry, ab) = if lxly is [lx, ly] and rxry is [rx, ry] and ab is [a, b] then\n    [[a, g(ry, b)], [f(a, lx), b]]\n\n  let xs_ = map(x => [x, x], xs)\n\n  if sweep_ud((a, b) => up(f, g, a, b), (a, b, c) => down3(f, g, a, b, c), [lu, ru], put(xs_)) is [[l_ans, r_ans], t_] then\n    let ans = [g(r_ans, ru), f(lu, l_ans)]\n    [ans, get(t_)]\n\nfun nearest_power_of_two(x) = until(a => a >= x, a => a * 2, 1)\n\nval emptyState = PS(-1, None_, -1, Nil, Nil)\n//│ emptyState = PS(-1, None_, -1, [], [])\n\nfun pad_circuit(size_ins_outs_states) = if size_ins_outs_states is [size, ins, outs, states] then\n  let p2 = nearest_power_of_two(size)\n  let states_ = append_nl_lz(states, replicate_lz(p2, emptyState))\n  [p2, ins, outs, take_lz(p2, states_)]\n\nfun inv(x) = if x === T then F else T\n\nfun and2(x, y) = if x === T && y === T then T else F\n\nfun or2(x, y) = if x === T || y === T then T else F\n\nfun xor(x, y) = if x === y then T else F\n\nval emptyPacket = [-1, -1, F, false, 0, false, 0, 1]\n//│ emptyPacket = [-1, -1, F, false, 0, false, 0, 1]\n\nfun send_right(a, b) = if a is [ia, sa, ma, qla, dla, qra, dra, ea] and b is [ib, sb, mb, qlb, dlb, qrb, drb, eb] and\n  qra and (dra > eb) then [ia, sa, ma, qla, dla, qra, dra - eb, ea + eb]\n  else [ib, sb, mb, qlb, dlb, qrb, drb, ea + eb]\n\nfun send_left(a, b) = if a is [ia, sa, ma, qla, dla, qra, dra, ea] and b is [ib, sb, mb, qlb, dlb, qrb, drb, eb] and\n  qlb && (dlb > ea) then [ib, sb, mb, qlb, dlb - ea, qrb, drb, ea + eb]\n  else [ia, sa, ma, qla, dla, qra, dra, ea + eb]\n\nfun send(xs) = scanlr(send_right, send_left, emptyPacket, emptyPacket, xs)\n\nfun update_outports(state, value) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and\n      h is [p, m, ql, dl, qr, dr] then [p, value, ql, dl, qr, dr] :: lscomp(t)\n      else lscomp(t)\n\n  updateOutports(state, lscomp(outports(state)))\n\n\nfun critical_path_depth(siot) = if siot is [size, ins, outs, states] then maximum(map(pathDepth, states))\n\nfun collect_outputs(tp4) = if tp4 is [size, ins, outs, states] then\n  fun thrid(tp3) = if tp3 is [_, _, v] then v\n\n  fun get_output(states, label_p) = if label_p is [label, p] then\n    fun lscomp(ls) = if ls is\n      Nil then Nil\n      s :: t and\n        p == pid(s) then head(inports(s)) :: lscomp(t)\n        else lscomp(t)\n    thrid(head(lscomp(states)))\n\n  map(p => get_output(states, p), outs)\n\n\nfun store_inputs(label_inputs, state) = if state is\n  PS(pid_, Inp, _, _, _) then\n    fun lscomp(ls) = if ls is\n      Nil then Nil\n      h :: t and\n        h is [[label, input_pid], value] and pid_ == input_pid then update_outports(state, value) :: lscomp(t)\n        else lscomp(t)\n    head(lscomp(label_inputs))\n  else state\n\nfun apply_component(comp, signals) = if comp is\n  Inp then None\n  Outp and signals is x :: Nil then Some(x)\n  Dff and signals is x :: Nil then Some(x)\n  Inv and signals is x :: Nil then Some(inv(x))\n  And2 and signals is x :: y :: Nil then Some(and2(x, y))\n  Or2 and signals is x :: y :: Nil then Some(or2(x, y))\n  Xor and signals is x :: y :: Nil then Some(xor(x, y))\n  None_ then None\n\nfun init_dffs(state) = if compType(state) === Dff then update_outports(state, F) else state\n\nfun restore_requests(old_states, new_states) =\n  fun restore(os, ns) = updateOutports(ns, zipWith(restore_outport, outports(os), outports(ns)))\n\n  fun restore_outport(pql, mdq) = if pql is [p, _, ql, dl, qr, dq] and mdq is [_, m, _, _, _, _] then [p, m, ql, dl, qr, dq]\n\n  zipWith(restore, old_states, new_states)\n\n\nfun update_requests(b, state) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and\n      h is [p, m, ql, dl, qr, dr] then [p, m, b, dl, b, dr] :: lscomp(t)\n      else lscomp(t)\n  updateOutports(state, lscomp(outports(state)))\n\nfun check_depth(d, state) = if pathDepth(state) == d then state else update_requests(false, state)\n\nfun acknowledge(d, states) =\n  fun check_requests(xs) = orList(map(check_lr_requests, xs))\n\n  fun check_lr_requests(pql) = if pql is [p,m,ql,dl,qr,dr] then ql || qr\n\n  let states1 = map(s => check_depth(d, s), states)\n\n  not(orList(map(s => check_requests(outports(s)), states1)))\n\n\nfun pad_packets(pss) =\n  fun pad(xs) =\n    let max_ps = maximum(map(x => listLen(x), pss))\n    take_lz(max_ps, append_nl_lz(xs, replicate_lz(max_ps, emptyPacket)))\n\n  map(x => pad(x), pss)\n\n\nfun make_packet(state) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and\n      h is [p, m, ql, dl, qr, dr] then [pid(state), p, m, ql, dl, qr, dr, 1] :: lscomp(t)\n      else lscomp(t)\n\n  lscomp(outports(state))\n\n\nfun compare_and_update(ipm_, pid_port_m) =\n  if ipm_ is [i, p, m_] and pid_port_m is [pid_, port, m] and\n    eqTup2([i, p], [pid_, port]) then [pid_, port, m_]\n    else [pid_, port, m]\n\nfun up_i(ipm_, ins) = if ipm_ is [i, p, m_, _, _, _, _, _] then map(x => compare_and_update([i, p, m_], x), ins)\n\nfun update_i(l_r, ins) = if l_r is [l, r] then up_i(l, up_i(r, ins))\n\nfun check_left(a, b) = if a is [pid_, port, pm, pql, pdl, pqr, pdr, e] and b is [p, m, ql, dl, qr, dr] and\n  pqr && (pdr > 0) then [p, m, ql, dl, qr, dr]\n  else [p, m, ql, dl, false, dr]\n\nfun check_right(a, b) = if a is [pid_, port, pm, pql, pdl, pqr, pdr, e] and b is [p, m, ql, dl, qr, dr] and\n  pql && (pdl > 0) then [p, m, ql, dl, qr, dr]\n  else [p, m, false, dl, qr, dr]\n\nfun update_o(lp_rp, out_) = if lp_rp is [lp, rp] then check_left(lp, check_right(rp, out_))\n\nfun update_io(d, lrps, state) =\n  fun update_is(state) = updateInports(state, foldr(update_i, inports(state), lrps))\n\n  fun update_os(state) = if pathDepth(state) == d then updateOutports(state, zipWith(update_o, lrps, outports(state))) else state\n\n  update_os(update_is(state))\n\n\nfun do_send(d, states) =\n  let states1 = map(s => check_depth(d, s), states)\n  let send_results = map(x => snd(send(x)), transpose(pad_packets(map(make_packet, states1))))\n  let pss_ = transpose(send_results)\n\n  zipWith((x, y) => update_io(d, x, y), pss_, states)\n\n\nfun do_sends(d, states) = until(s => acknowledge(d, s), x => do_send(d, x), states)\n\nfun simulate_component(d, state) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and\n      h is [_, _, sig] then sig :: lscomp(t)\n      else lscomp(t)\n\n  let out_signals = lscomp(inports(state))\n  let new_value = apply_component(compType(state), out_signals)\n\n  if\n    d == pathDepth(state) and not(new_value === None) and new_value is Some(v) then update_outports(state, v)\n    else state\n\nfun simulate_components(depth, states) = map(s => simulate_component(depth, s), states)\n\nfun do_cycle(cpd, tp4, inputs) =\n  fun sim_then_send(state, d) = do_sends(d, simulate_components(d, state))\n\n  if tp4 is [size, ins, outs, states] then\n    let states1 = map(s => store_inputs(zip(ins, inputs), s), states)\n    let states2 = do_sends(0, states1)\n    let states3 = foldl(sim_then_send, states2, enumFromTo(1, cpd))\n    let states4 = restore_requests(states, states3)\n    [size, ins, outs, states4]\n  else throw Error(tp4)\n\nfun simulate(inputs_list, b) = if b is [size, ins, outs, states] then\n  tail(scanl((x, y) => do_cycle(critical_path_depth([size, ins, outs, states]), x, y), [size, ins, outs, map(init_dffs, states)], inputs_list))\n\nfun reg(sto, n) =\n  PS(n, Inp, 0, Nil, [0, F, false, 0, true, 4] :: Nil) ::\n  PS(n + 1, Dff, 1, [n + 5, 0, F] :: Nil, [0, F, false, 0, true, 5] :: Nil) ::\n  PS(n + 2, Inv, 1, [sto, 0, F] :: Nil, [0, F, false, 0, true, 1] :: Nil) ::\n  PS(n + 3, And2, 2, [n + 1, 0, F] :: [n + 2, 0, F] :: Nil, [0, F, false, 0, true, 2] :: Nil) ::\n  PS(n + 4, And2, 1, [sto, 0, F] :: [n, 0, F] :: Nil, [0, F, false, 0, true, 1] :: Nil) ::\n  PS(n + 5, Or2, 3, [n + 3, 0, F] :: [n + 4, 0, F] :: Nil, [0, F, true, 4, false, 0] :: Nil) ::\n  PS(n + 6, Outp, 4, [n + 1, 0, F] :: Nil, Nil) ::\n  Nil\n\nfun regs(bits) =\n  fun ilabel(n, pid_) = [stringConcat(\"x\", stringOfInt(n)), pid_]\n  fun olabel(n, pid_) = [stringConcat(\"y\", stringOfInt(n)), pid_]\n  let is_ = [\"sto\", 0] :: zipWith_lz_nl(ilabel, enumFrom(0), map(x => (7 * x) + 1, enumFromTo(0, bits - 1)))\n  let os = zipWith_lz_nl(olabel, enumFrom(0), map(x => (7 * x) + 7, enumFromTo(0, bits - 1)))\n  let sto = PS(0, Inp, 0, Nil, [0, F, false, 0, true, (8 * (bits - 1)) + 5] :: Nil)\n  let states = sto :: concat(map(x => reg(0, x), map(x => (7 * x) + 1, enumFromTo(0, bits - 1))))\n\n  [1 + (7 * bits), is_, os, states]\n\n\nfun circuit_simulate(inputs_list, circuit) = map(collect_outputs, simulate(inputs_list, circuit))\n\nfun run(num_bits, num_cycles) =\n  let example = pad_circuit(regs(num_bits))\n  let inputs = replicate(num_bits + 1, T)\n  let cycles = replicate(num_cycles, inputs)\n\n  circuit_simulate(cycles, example)\n\n\nfun testCircsim_nofib(n) = run(8, n)\n\n\n\nfun main() = testCircsim_nofib(40).toString()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/clausify.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule clausify with ...\n\n\nabstract class Formula: Sym | Not | Dis | Con | Imp | Eqv\n\ndata\n  class\n    Sym(a: Char) extends Formula\n    Not(a: Formula) extends Formula\n    Dis(a: Formula, b: Formula) extends Formula\n    Con(a: Formula, b: Formula) extends Formula\n    Imp(a: Formula, b: Formula) extends Formula\n    Eqv(a: Formula, b: Formula) extends Formula\n\nabstract class StackFrame: Ast | Lex\n\ndata\n  class\n    Ast(f: Formula) extends StackFrame\n    Lex(s: Char) extends StackFrame\n\nfun charLt(a, b) = a < b\nfun charLeq(a, b) = a <= b\nfun charGt(a, b) = a > b\nfun charGeq(a, b) = a >= b\n\nfun insert(x, ys) = if ys is\n  Nil then x :: Nil\n  y :: ys and\n    charLt(x, y) then x :: y :: ys\n    charGt(x, y) then y :: insert(x, ys)\n    else y :: ys\n\nfun clauseHelper(p, x) = if p is\n  Dis(p, q) then clauseHelper(p, clauseHelper(q, x))\n  Sym(s) and x is [c, a] then [insert(s, c), a]\n  Not(Sym(s)) and x is [c, a] then [c, insert(s, a)]\n\nfun clause(p) = clauseHelper(p, [Nil, Nil])\n\nfun conjunct(p) = if p is Con(_, _) then true else false\n\nfun disin(p) = if p is\n  Dis(p, Con(q, r)) then Con(disin(Dis(p, q)), disin(Dis(p, r)))\n  Dis(Con(p, q), r) then Con(disin(Dis(p, r)), disin(Dis(q, r)))\n  Dis(p, q) then\n    let dp = disin(p)\n    let dq = disin(q)\n    if conjunct(dp) || conjunct(dq) then disin(Dis(dp, dq)) else Dis(dp, dq)\n  Con(p, q) then Con(disin(p), disin(q))\n  else p\n\nfun elim(p) = if p is\n  Sym(s) then Sym(s)\n  Not(p) then Not(elim(p))\n  Dis(p, q) then Dis(elim(p), elim(q))\n  Con(p, q) then Con(elim(p), elim(q))\n  Imp(p, q) then Dis(Not(elim(p)), elim(q))\n  Eqv(f, f_) then Con(elim(Imp(f, f_)), elim(Imp(f_, f)))\n\nfun interleave(xs, ys) = if xs is\n  x :: xs then x :: interleave(ys, xs)\n  Nil then Nil\n\nfun negin(p) = if p is\n  Not(Not(p)) then negin(p)\n  Not(Con(p, q)) then Dis(negin(Not(p)), negin(Not(q)))\n  Not(Dis(p, q)) then Con(negin(Not(p)), negin(Not(q)))\n  Dis(p, q) then Dis(negin(p), negin(q))\n  Con(p, q) then Con(negin(p), negin(q))\n  else p\n\nfun opri(c) = if c\n  === \"(\" then 0\n  === \"=\" then 1\n  === \">\" then 2\n  === \"|\" then 3\n  === \"&\" then 4\n  === \"~\" then 5\n  else throw Error(c)\n\nfun red(s) = if s is\n  Ast(p) :: Lex(\"=\") :: Ast(q) :: s then Ast(Eqv(q, p)) :: s\n  Ast(p) :: Lex(\">\") :: Ast(q) :: s then Ast(Imp(q, p)) :: s\n  Ast(p) :: Lex(\"|\") :: Ast(q) :: s then Ast(Dis(q, p)) :: s\n  Ast(p) :: Lex(\"&\") :: Ast(q) :: s then Ast(Con(q, p)) :: s\n  Ast(p) :: Lex(\"~\") :: s           then Ast(Not(p)) :: s\n\nfun spri(s) = if s is\n  Ast(x) :: Lex(c) :: s then opri(c)\n  else 0\n\nfun redstar(s) = while_(s => spri(s) != 0, red, s)\n\nfun spaces(n) = replicate(n, \" \")\n\nfun parseHelper(t, s) = if t is\n  Nil then redstar(s)\n  \" \" :: t then parseHelper(t, s)\n  \"(\" :: t then parseHelper(t, Lex(\"(\") :: s)\n  \")\" :: t and redstar(s) is x :: Lex(\"(\") :: ss then parseHelper(t, x :: ss)\n  c :: t and\n    charLeq(\"a\", c) && charLeq(c, \"z\") then parseHelper(t, Ast(Sym(c)) :: s)\n    spri(s) > opri(c) then parseHelper(c :: t, red(s))\n    else parseHelper(t, Lex(c) :: s)\n\nfun parse(t) = if parseHelper(t, Nil) is Ast(f) :: Nil then f\n\nfun splitHelper(p, a) = if p is\n  Con(p, q) then splitHelper(p, splitHelper(q, a))\n  else p :: a\n\nfun split(p) = splitHelper(p, Nil)\n\nfun tautclause(c_a) = if c_a is [c, a] then\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    h :: t and\n      inList(h, a) then h :: lscomp(t)\n      else lscomp(t)\n  listNeq(lscomp(c), Nil)\n\nfun uniclHelper(p, x) =\n  let cp = clause(p)\n  if tautclause(cp) then x else insert(cp, x)\n\nfun unicl(a) = foldr(uniclHelper, Nil, a)\n\nfun disp(l_r) = if l_r is [l, r] then\n  interleave(l, spaces(listLen(l))) +:\n  nofibStringToList(\"<=\") +:\n  interleave(spaces(listLen(r)), r) +:\n  nofibStringToList(\"\\n\")\n\nfun clauses(t) = concat of map of\n  disp\n  unicl of split of disin of negin of elim of parse of t\n\n// NOTE: original input \"(a = a = a) = (a = a = a) = (a = a = a)\"\nfun testClausify_nofib(n) =\n  let xs = replicate(n, nofibStringToList(\"a = a = a\"))\n  concat(map(clauses, xs))\n\nfun main() = nofibListToString(testClausify_nofib(10))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/constraints.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule constraints with ...\n\n\n\n// -- Figure 1. CSPs in Haskell.\ndata class Assign(varr: Int, value: Int)\n\ndata class CSP(vars: Int, vals: Int, rel: Int)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun qsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then qpart(le, x, xs, Nil, Nil, r)\n\nfun qpart(le, x, ls, rlt, rge, r) = if ls is\n  Nil then rqsort(le, rlt, x :: rqsort(le, rge, r))\n  y :: ys and\n    le(x, y) then qpart(le, x, ys, rlt, y :: rge, r)\n    else qpart(le, x, ys, y :: rlt, rge, r)\n\nfun rqsort(le, ls, r) = if ls is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then rqpart(le, x, xs, Nil, Nil, r)\n\nfun rqpart(le, x, ls, rle, rgt, r) = if ls is\n  Nil then rqsort(le, rle, x :: qsort(le, rgt, r))\n  y :: ys and\n    le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r)\n    else rqpart(le, x, ys, rle, y :: rgt, r)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun level(a) = if a is Assign(v, _) then v\n\nfun value(a) = if a is Assign(_, v) then v\n\nfun maxLevel(ls) = if ls is\n  Nil then 0\n  Assign(v, _) :: t then v\n\nfun complete(csp, s) = if csp is CSP(v, _, _) then maxLevel(s) == v\n\nfun safe(as1, as2) = if as1 is Assign(i, m) and as2 is Assign(j, n) then not(m == n) and not(abs(i - j) == abs(m - n))\n\nfun queens(n) = CSP(n, n, safe)\n\n// -- Figure 2.  Trees in Haskell.\ndata class Node[out T](lab: T, children: List[Node[T]])\n\nfun label(n) = if n is Node(l, _) then l\n\nfun mapTree(f, n) = if n is Node(l, c) then Node(f(l), map((x => mapTree(f, x)), c))\n\nfun foldTree(f, n) = if n is Node(l, c) then f(l, map((x => foldTree(f, x)), c))\n\nfun filterTree(p, t) =\n  fun f1(a, cs) = Node(a, filter(x => p(label(x)), cs))\n  foldTree(f1, t)\n\nfun prune(p, t) = filterTree(x => not(p(x)), t)\n\nfun leaves(t) = if t is\n  Node(leaf, Nil) then leaf :: Nil\n  Node(_, cs) then concat(map(leaves, cs))\n\nfun initTree(f, x) = Node(x, map(y => initTree(f, y), f(x)))\n\n// -- Figure 3.  Simple backtracking solver for CSPs.\nfun mkTree(csp) = if csp is CSP(vars, vals, rel) then\n  fun next(ss) =\n    if maxLevel(ss) < vars then\n      fun lscomp1(ls) = if ls is\n        Nil then Nil\n        j :: t1 then\n          (Assign(maxLevel(ss) + 1, j) :: ss) :: lscomp1(t1)\n      lscomp1(enumFromTo(1, vals))\n    else\n      Nil\n\n  initTree(next, Nil)\n\n\nfun earliestInconsistency(csp, aas) = if csp is CSP(vars, vals, rel) and aas is\n  Nil then None\n  a :: as_ and filter(x => not(rel(a, x)), reverse(as_)) is\n    Nil then None\n    b :: _ then Some([level(a), level(b)])\n\nfun labelInconsistencies(csp, t) =\n  fun f2(s) = [s, earliestInconsistency(csp, s)]\n\n  mapTree(f2, t)\n\n\nfun btsolver0(csp) =\n  filter of\n    x => complete(csp, x)\n    leaves of\n      mapTree of\n        fst\n        prune of\n          x => not(snd(x) === None)\n          labelInconsistencies(csp, mkTree(csp))\n\n// -- Figure 6. Conflict-directed solving of CSPs.\nabstract class ConflictSet: Known | Unknown\ndata class Known(vs: List[Int]) extends ConflictSet\nobject Unknown extends ConflictSet\n\nfun knownConflict(c) = if c is\n  Known(a :: as_) then true\n  else false\n\nfun knownSolution(c) = if c is\n  Known(Nil) then true\n  else false\n\nfun checkComplete(csp, s) = if complete(csp, s) then Known(Nil) else Unknown\n\nfun search(labeler, csp) =\n  map of\n    fst\n    filter of\n      x => knownSolution(snd(x))\n      leaves of prune of\n        x => knownConflict(snd(x))\n        labeler(csp, mkTree(csp))\n\nfun bt(csp, t) =\n  fun f3(s) = [s, (if earliestInconsistency(csp, s) is Some([a, b]) then Known(a :: b :: Nil) else checkComplete(csp, s))]\n\n  mapTree(f3, t)\n\n// -- Figure 8. Backmarking.\n\nfun emptyTable(csp) = if csp is CSP(vars, vals, rel) then\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    n :: t1 then\n      fun lscomp2(ls) = if ls is\n        Nil then Nil\n        m :: t2 then\n          Unknown :: lscomp2(t2)\n      lscomp2(enumFromTo(1, vals)) :: lscomp1(t1)\n\n  Nil :: lscomp1(enumFromTo(1, vars))\n\n\nfun fillTable(s, csp, tbl) = if s is\n  Nil then tbl\n  Assign(var_, val_) :: as_ and csp is CSP(vars, vals, rel) then\n    fun f4(cs, varval) = if varval is [varr, vall] and\n      cs === Unknown and not(rel(Assign(var_, val_), Assign(varr, vall))) then Known(var_ :: varr :: Nil)\n      else cs\n\n    fun lscomp1(ls) = if ls is\n      Nil then Nil\n      varrr :: t1 then\n        fun lscomp2(ls) = if ls is\n          Nil then Nil\n          valll :: t2 then [varrr, valll] :: lscomp2(t2)\n        lscomp2(enumFromTo(1, vals)) :: lscomp1(t1)\n\n    zipWith((x, y) => zipWith(f4, x, y), tbl, lscomp1(enumFromTo(var_ + 1, vars)))\n\n\nfun lookupCache(csp, t) =\n  fun f5(csp, tp) = if tp is\n    [Nil, tbl] then [[Nil, Unknown], tbl]\n    [a :: as_, tbl] then\n      let tableEntry = atIndex(value(a) - 1, head(tbl))\n      let cs = if tableEntry === Unknown then checkComplete(csp, a :: as_) else tableEntry\n      [[a :: as_, cs], tbl]\n\n  mapTree(x => f5(csp, x), t)\n\n\nfun cacheChecks(csp, tbl, n) = if n is Node(s, cs) then\n  Node([s, tbl], map(x => cacheChecks(csp, fillTable(s, csp, tail(tbl)), x), cs))\n\nfun bm(csp, t) = mapTree(fst, lookupCache(csp, cacheChecks(csp, emptyTable(csp), t)))\n\n// -- Figure 10. Conflict-directed backjumping.\nfun combine(ls, acc) = if ls is\n  Nil then acc\n  [s, Known(cs)] :: css and\n    notElem(maxLevel(s), cs) then cs\n    else combine(css, union(cs, acc))\n\nfun bj_(csp, t) =\n  fun f7(tp2, chs) = if tp2 is\n    [a, Known(cs)] then Node([a, Known(cs)], chs)\n    [a, Unknown] and\n      let cs_ = Known(combine(map(label, chs), Nil))\n      knownConflict(cs_) then Node([a, cs_], Nil)\n      else Node([a, cs_], chs)\n\n  foldTree(f7, t)\n\n\nfun bj(csp, t) =\n  fun f6(tp2, chs) = if tp2 is\n    [a, Known(cs)] then Node([a, Known(cs)], chs)\n    [a, Unknown] then Node([a, Known(combine(map(label, chs), Nil))], chs)\n\n  foldTree(f6, t)\n\n\nfun bjbt(csp, t) = bj(csp, bt(csp, t))\n\nfun bjbt_(csp, t) = bj_(csp, bt(csp, t))\n\n// -- Figure 11. Forward checking.\nfun collect(ls) = if ls is\n  Nil then Nil\n  Known(cs) :: css then union(cs, collect(css))\n\nfun domainWipeout(csp, t) = if csp is CSP(vars, vals, rel) then\n  fun f8(tp2) = if tp2 is [[as_, cs], tbl] then\n    let wipedDomains = \n      fun lscomp1(ls) = if ls is\n        Nil then Nil\n        vs :: t1 and\n          all(knownConflict, vs) then vs :: lscomp1(t1)\n          else lscomp1(t1)\n      lscomp1(tbl)\n    let cs_ = if null_(wipedDomains) then cs else Known(collect(head(wipedDomains)))\n    [as_, cs_]\n\n  mapTree(f8, t)\n\n\nfun fc(csp, t) = domainWipeout(csp, lookupCache(csp, cacheChecks(csp, emptyTable(csp), t)))\n\nfun try_(n, algorithm) = listLen(search(algorithm, queens(n)))\n\nfun testConstraints_nofib(n) = map(x => try_(n, x), bt :: bm :: bjbt :: bjbt_ :: fc :: Nil)\n\n\nfun main() = testConstraints_nofib(6).toString()"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/cryptarithm1.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\n\nmodule cryptarithm1 with ...\n\n\n\nfun expand(a, b, c, d, e, f) = f + (e*10) + (d*100) + (c*1000) + (b*10000) + (a*100000)\n\nfun condition(thirywelvn) = if thirywelvn is\n  t :: h :: i :: r :: y :: w :: e :: l :: v :: n :: Nil then\n    (expand(t, h, i, r, t, y) + 5 * expand(t, w, e, l, v, e)) == expand(n, i, n, e, t, y)\n\nfun addj(j, ls) = if ls is\n  Nil then (j :: Nil) :: Nil\n  k :: ks then\n    fun lscomp(p1) = if p1 is\n      Nil then Nil\n      h1 :: t1 then (k :: h1) :: lscomp(t1)\n\n    (j :: (k :: ks)) :: lscomp(addj(j, ks))\n\nfun permutations(ls) = if ls is\n  Nil then Nil :: Nil\n  j :: js then\n    fun lscomp1(p1) = if p1 is\n      Nil then Nil\n      pjs :: t1 then\n        fun lscomp2(p2) = if p2 is\n          Nil then lscomp1(t1)\n          r :: t2 then r :: lscomp2(t2)\n        lscomp2(addj(j, pjs))\n\n    lscomp1(permutations(js))\n\nfun testCryptarithm_nofib(n) = \n  map((i => let p0 = take(10, enumFromTo(0, 9 + i)) in filter(condition, permutations(p0))), enumFromTo(1, n))\n\n\nfun main() = testCryptarithm_nofib(1)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/cryptarithm2.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule cryptarithm2 with ...\n\n\nobject Unit\n\nfun unlines(ls) = concat of map(x => x +: (\"\\n\" :: Nil), ls)\n\nfun lookup(k, t) = if t is\n  Nil then None\n  [x, v] :: t then if k === x then Some(v) else lookup(k, t)\n\nfun delete_(xs, e) = deleteBy((x, y) => x === y, e, xs)\n\nfun listDiff(a, ls) = foldl(delete_, a, ls)\n\ndata class StateT[S, M, A](run)\n\nfun runStateT(m, s) = if m is StateT(run) then run(s)\n\nfun bind(m, f) =\n  StateT of\n    s => concat of map(case { [a, ss] then runStateT(f(a), ss) }, runStateT(m, s))\n\nfun return_(a) = StateT(s => [a, s] :: Nil)\n\nfun mapM(f, ls) = foldr((a, r) => bind(f(a), x => bind(r, xs => return_(x :: xs))), return_(Nil), ls)\n\nfun lift(ls) = StateT(s => concat(map(x => [x, s] :: Nil, ls)))\n\nfun execStateT(m, s) = concat(map(case { [a, s] then s :: Nil }, runStateT(m, s)))\n\nfun guard(b) = if b then StateT(s => [Unit, s] :: Nil) else StateT(s => Nil)\n\nfun put(s) = StateT(x => [Unit, s] :: Nil)\n\nval get = StateT(s => [s, s] :: Nil)\n//│ get = StateT([function])\n\ndata class Digits(i: List[Int], c: List[[Char, Int]])\n\nfun digits(d) = if d is Digits(a, b) then a\n\nfun digitEnv(d) = if d is Digits(a, b) then b\n\nfun permute(c) =\n  bind of\n    get\n    st =>\n      bind of\n        let xs = digits(st) in lift(map(x => [x, listDiff(xs, x :: Nil)], xs))\n        iis =>\n          if iis is [i, iss] then\n            bind of\n              put(Digits(iss, [c, i] :: digitEnv(st)))\n              _p => return_(i)\n\nfun select(c) =\n  bind of\n    get\n    st =>\n      if lookup(c, digitEnv(st)) is\n        Some(r) then return_(r)\n        None then permute(c)\n\nfun rest(ls) = if ls is\n  Nil then Nil\n  x :: xs then xs\n\nfun solve(tops, bots, carry) = if bots is\n  bot :: botss then\n    bind of\n      if tops is\n        Nil then return_(carry)\n        top :: _ then bind(mapM(select, top), topNS => return_(sum(topNS) + carry))\n      topN => bind of\n        select(bot)\n        botN => bind of\n          guard(intMod(topN, 10) === botN)\n          _s => solve(rest(tops), botss, intDiv(topN, 10))\n  Nil and tops is Nil and carry === 0 then return_(Unit)\n  else StateT(_p => Nil)\n\nfun puzzle(top, bot) =\n  let solution = solve(transpose(map(reverse, top)), reverse(bot), 0)\n  let answer = if execStateT(solution, Digits(enumFromTo(0, 9), Nil)) is a :: _ then a\n  let env = digitEnv(answer)\n  let look = c => fromSome(lookup(c, env))\n  let expand = ls => foldl((a, b) => a * 10 + look(b), 0, ls)\n  let topVal = sum(map(xs => expand(xs), top))\n  let botVal = expand(bot)\n  if\n    listLen(nubBy((x,y) => x === y, concat(top) +: bot)) > 10 then throw Error(\"error\")\n    topVal != botVal then throw Error(\"error\")\n    else unlines of map of\n      case { [c, i] then c :: nofibStringToList(\" => \") +: nofibStringToList(stringOfInt(i)) }\n      env\n\nfun testCryptarithm2_nofib(n) =\n  let args =\n    nofibStringToList(\"THIRTY\") ::\n    nofibStringToList(\"TWELVE\") ::\n    nofibStringToList(\"TWELVE\") ::\n    nofibStringToList(\"TWELVE\") ::\n    nofibStringToList(\"TWELVE\") ::\n    append(nofibStringToList(\"TWELVE\"), (if n > 999999 then nofibStringToList(\"1\") else Nil)) :: Nil\n  puzzle(args, nofibStringToList(\"NINETY\"))\n\nfun main() = testCryptarithm2_nofib(1).toString()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/cse.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule cse with ...\n\n\n\nfun retURN(a) = s => [s, a]\n\nfun bind(m, f) = s => if m(s) is [s_, a] then f(a)(s_)\n\nfun join(m) = s => if m(s) is [s_, ma] then ma(s_)\n\nfun mmap(f, m) = s => if m(s) is [s_, a] then [s_, f(a)]\n\nfun mmapl(f, aas) = if aas is\n  Nil then retURN(Nil)\n  a :: as_ then\n    bind of\n      f(a)\n      b => bind of\n        mmapl(f, as_)\n        bs => retURN(b :: bs)\n\nfun mmapr(f, xs) = if xs is\n  Nil then retURN(Nil)\n  x :: xs then\n    bind of\n      mmapr(f, xs)\n      ys => bind of\n        f(x)\n        y => retURN(y :: ys)\n\nfun mfoldl(f, a, xs) = if xs is\n  Nil then retURN(a)\n  x :: xs then\n    bind(f(a, x), fax => mfoldl(f, fax, xs))\n\nfun mfoldr(f, a, xs) = if xs is\n  Nil then retURN(a)\n  x :: xs then\n    bind(mfoldr(f, a, xs), y => f(x, y))\n\nfun mif(c, t, f) = bind(c, cond => if cond then t else f)\n\nfun startingWith(m, v) = if m(v) is [final, answer] then answer\n\nfun fetch(s) = [s, s]\n\nfun fetchWith(f) = s => [s, f(s)]\n\nfun update(f) = s => [f(s), s]\n\nfun set_(s_) = s => [s_, s]\n\nval incr = update(x => x + 1)\n//│ incr = [function]\n\ndata class Node[T](a: T, b: List[Node[T]])\n\nfun labelTree(t) =\n  fun label(t) = if t is Node(x, xs) then\n    bind of\n      incr\n      n => bind of\n        mmapl(label, xs)\n        ts => retURN(Node([n, x], ts))\n  startingWith(label(t), 0)\n\nfun ltGraph(t) =\n  fun labelOf(t) = if t is Node([n, x], xs) then n\n  if t is Node([n, x], xs) then\n    [n, x, map(labelOf, xs)] :: concat(map(ltGraph, xs))\n\nfun visited(n) = bind of\n  fetch\n  us => if inList(n, us) then retURN(true) else bind(set_(n :: us), _p => retURN(false))\n\nfun newlyDefined(x, fx, f, y) = if x === y then fx else f(y)\n\nfun findCommon(ls) =\n  fun sim(n_s_cs, r_lg) = if n_s_cs is [n, s, cs] and r_lg is [r, lg] then\n    let rcs = map(r, cs)\n    fun lscomp(ls) = if ls is\n      Nil then Nil\n      [m, s_, cs_] :: t and\n        s === s_ and listEq(cs_, rcs) then m :: lscomp(t)\n        else lscomp(t)\n    let ms = lscomp(lg)\n    if null_(ms)\n    then [r, [n, s, rcs] :: lg]\n    else [x => newlyDefined(n, head(ms), r, x), lg]\n  if foldr(sim, [x => x, Nil], ls) is [a, b] then b else throw Error(ls.toString())\n\nfun cse(t) = findCommon(ltGraph(labelTree(t)))\n\nfun plus_(x, y) = Node(\"+\", x :: y :: Nil)\n\nfun mult_(x, y) = Node(\"*\", x :: y :: Nil)\n\nfun prod(xs) = Node(\"X\", xs)\n\nval zerO = Node(\"0\", Nil)\n//│ zerO = Node(\"0\", [])\n\nval a = Node(\"a\", Nil)\n//│ a = Node(\"a\", [])\n\nval b = Node(\"b\", Nil)\n//│ b = Node(\"b\", [])\n\nval c = Node(\"c\", Nil)\n//│ c = Node(\"c\", [])\n\nval d = Node(\"d\", Nil)\n//│ d = Node(\"d\", [])\n\nval example0 = a\n//│ example0 = Node(\"a\", [])\n\nval example1 = plus_(a, a)\n//│ example1 = Node(\"+\", [Node(\"a\", []),Node(\"a\", [])])\n\nval example2 = plus_(mult_(a, b), mult_(a, b))\n//│ example2 = Node(\"+\", [Node(\"*\", [Node(\"a\", []),Node(\"b\", [])]),Node(\"*\", [Node(\"a\", []),Node(\"b\", [])])])\n\nval example3 = plus_(mult_(plus_(a, b), c), plus_(a, b))\n//│ example3 = Node(\"+\", [Node(\"*\", [Node(\"+\", [Node(\"a\", []),Node(\"b\", [])]),Node(\"c\", [])]),Node(\"+\", [Node(\"a\", []),Node(\"b\", [])])])\n\nval example4 = prod(scanl(plus_, zerO, a :: b :: c :: d :: Nil))\n//│ example4 = Node(\"X\", [Node(\"0\", []),Node(\"+\", [Node(\"0\", []),Node(\"a\", [])]),Node(\"+\", [Node(\"+\", [Node(\"0\", []),Node(\"a\", [])]),Node(\"b\", [])]),Node(\"+\", [Node(\"+\", [Node(\"+\", [Node(\"0\", []),Node(\"a\", [])]),Node(\"b\", [])]),Node(\"c\", [])]),Node(\"+\", [Node(\"+\", [Node(\"+\", [Node(\"+\", [Node(\"0\", []),Node(\"a\", [])]),Node(\"b\", [])]),Node(\"c\", [])]),Node(\"d\", [])])])\n\nval example5 = prod(scanr(plus_, zerO, a :: b :: c :: d :: Nil))\n//│ example5 = Node(\"X\", [Node(\"+\", [Node(\"a\", []),Node(\"+\", [Node(\"b\", []),Node(\"+\", [Node(\"c\", []),Node(\"+\", [Node(\"d\", []),Node(\"0\", [])])])])]),Node(\"+\", [Node(\"b\", []),Node(\"+\", [Node(\"c\", []),Node(\"+\", [Node(\"d\", []),Node(\"0\", [])])])]),Node(\"+\", [Node(\"c\", []),Node(\"+\", [Node(\"d\", []),Node(\"0\", [])])]),Node(\"+\", [Node(\"d\", []),Node(\"0\", [])]),Node(\"0\", [])])\n\nfun testCse_nofib(n) = map(\n  i => map(\n    cse,\n    take(intMod(i, 6), example0 :: example1 :: example2 :: example3 :: example4 :: example5 :: Nil)\n  ),\n  enumFromTo(1, n)\n)\n\nfun main() = testCse_nofib(6).toString()"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/eliza.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule eliza with ...\n\n\n\nfun toUpper(c) = c.toUpperCase()\n\nfun lz_map(f, ls) = lazy of () =>\n  if ls is\n    Nil then LzNil\n    h :: t then LzCons(f(h), lz_map(f, t))\n\nfun append_lz(xs, ys) = if xs is\n  Nil then force(ys)\n  h :: t then lazy of () => LzCons(h, append_lz(t, ys))\n\nfun cycle(xs) = append_lz(xs, lazy of () => cycle(xs))\n\nfun isSpace(c) = c === \" \"\n\nfun words(s) = if leaveWhile(eliza.isSpace, s) is\n  Nil then Nil\n  h2h :: t2t and\n    break_(eliza.isSpace, h2h :: t2t) is [w, s_] then w :: eliza.words(s_)\n\nfun unwords(ws) =\n  fun go(ws) = if ws is\n    Nil then Nil\n    w :: ws then \" \" :: w +: go(ws)\n  if ws is\n    Nil then Nil\n    w :: ws then w +: go(ws)\n\nfun null_lz(ls) = if force(ls) is\n  LzNil then true\n  LzCons(h, t) then false\n\nfun trim(ls) =\n  fun cons(x, xs) = if inList(x, nofibStringToList(\" .!?,\")) and null_(xs) then Nil else x :: xs\n  foldr(cons, Nil, leaveWhile(x => inList(x, nofibStringToList(\" .!?,\")), ls))\n\nfun repeated(kt_rp) = if kt_rp is [kt, r :: rp] then [r, [kt, rp]]\n\nfun newKeyTab(kt_, kt_rp) = if kt_rp is [kt, rp] then [kt_, rp]\n\nfun keyTabOf(kt_rp) = if kt_rp is [kt, rp] then kt\n\nfun makeResponse(cs, us) = if cs is\n  \"?\" :: cs_ then cs_ +: nofibStringToList(\" \") +: us +: nofibStringToList(\"?\")\n  \".\" :: cs_ then cs_ +: nofibStringToList(\" \") +: us +: nofibStringToList(\".\")\n  else cs\n\nval repeatMsgs = Predef.id of\n  nofibStringToList(\"Why did you repeat yourself?\") ::\n  nofibStringToList(\"Do you expect a different answer by repeating yourself?\") ::\n  nofibStringToList(\"Come, come, elucidate your thoughts.\") ::\n  nofibStringToList(\"Please don't repeat yourself!\") ::\n  Nil\n//│ repeatMsgs = [[\"W\",\"h\",\"y\",\" \",\"d\",\"i\",\"d\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"p\",\"e\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\"r\",\"s\",\"e\",\"l\",\"f\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"e\",\"x\",\"p\",\"e\",\"c\",\"t\",\" \",\"a\",\" \",\"d\",\"i\",\"f\",\"f\",\"e\",\"r\",\"e\",\"n\",\"t\",\" \",\"a\",\"n\",\"s\",\"w\",\"e\",\"r\",\" \",\"b\",\"y\",\" \",\"r\",\"e\",\"p\",\"e\",\"a\",\"t\",\"i\",\"n\",\"g\",\" \",\"y\",\"o\",\"u\",\"r\",\"s\",\"e\",\"l\",\"f\",\"?\"],[\"C\",\"o\",\"m\",\"e\",\",\",\" \",\"c\",\"o\",\"m\",\"e\",\",\",\" \",\"e\",\"l\",\"u\",\"c\",\"i\",\"d\",\"a\",\"t\",\"e\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"t\",\"h\",\"o\",\"u\",\"g\",\"h\",\"t\",\"s\",\".\"],[\"P\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"d\",\"o\",\"n\",\"'\",\"t\",\" \",\"r\",\"e\",\"p\",\"e\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\"r\",\"s\",\"e\",\"l\",\"f\",\"!\"]]\n\nval respMsgs =\n  let canYou = nofibStringToList(\"?Don_t you believe that I can\") ::\n    nofibStringToList(\"?Perhaps you would like to be able to\") ::\n    nofibStringToList(\"?You want me to be able to\") ::\n    Nil\n  let canI = nofibStringToList(\"?Perhaps you don_t want to\") ::\n    nofibStringToList(\"?Do you want to be able to\") ::\n    Nil\n  let youAre = nofibStringToList(\"?What makes you think I am\") ::\n    nofibStringToList(\"?Does it please you to believe I am\") ::\n    nofibStringToList(\"?Perhaps you would like to be\") ::\n    nofibStringToList(\"?Do you sometimes wish you were\") ::\n    Nil\n  let iDont = nofibStringToList(\"?Don_t you really\") ::\n    nofibStringToList(\"?Why don_t you\") ::\n    nofibStringToList(\"?Do you wish to be able to\") ::\n    nofibStringToList(\"Does that trouble you?\") ::\n    Nil\n  let iFeel = nofibStringToList(\"Tell me more about such feelings.\") ::\n    nofibStringToList(\"?Do you often feel\") ::\n    nofibStringToList(\"?Do you enjoy feeling\") ::\n    Nil\n  let whyDont = nofibStringToList(\"?Do you really believe I don't\") ::\n    nofibStringToList(\".Perhaps in good time I will\") ::\n    nofibStringToList(\"?Do you want me to\") ::\n    Nil\n  let whyCant = nofibStringToList(\"?Do you think you should be able to\") ::\n    nofibStringToList(\"?Why can't you\") ::\n    Nil\n  let areYou = nofibStringToList(\"?Why are you interested in whether or not I am\") ::\n    nofibStringToList(\"?Would you prefer if I were not\") ::\n    nofibStringToList(\"?Perhaps in your fantasies I am\") ::\n    Nil\n  let iCant = nofibStringToList(\"?How do you know you can't\") ::\n    nofibStringToList(\"Have you tried?\") ::\n    nofibStringToList(\"?Perhaps you can now\") ::\n    Nil\n  let iAm = nofibStringToList(\"?Did you come to me because you are\") ::\n    nofibStringToList(\"?How long have you been\") ::\n    nofibStringToList(\"?Do you believe it is normal to be\") ::\n    nofibStringToList(\"?Do you enjoy being\") ::\n    Nil\n  let you = nofibStringToList(\"We were discussing you --not me.\") ::\n    nofibStringToList(\"?Oh,\") ::\n    nofibStringToList(\"You're not really talking about me, are you?\") ::\n    Nil\n  let yes = nofibStringToList(\"You seem quite positive.\") ::\n    nofibStringToList(\"Are you Sure?\") ::\n    nofibStringToList(\"I see.\") ::\n    nofibStringToList(\"I understand.\") ::\n    Nil\n  let no = nofibStringToList(\"Are you saying no just to be negative?\") ::\n    nofibStringToList(\"You are being a bit negative.\") ::\n    nofibStringToList(\"Why not?\") ::\n    nofibStringToList(\"Are you sure?\") ::\n    nofibStringToList(\"Why no?\") ::\n    Nil\n  let computer = nofibStringToList(\"Do computers worry you?\") ::\n    nofibStringToList(\"Are you talking about me in particular?\") ::\n    nofibStringToList(\"Are you frightened by machines?\") ::\n    nofibStringToList(\"Why do you mention computers?\") ::\n    nofibStringToList(\"What do you think machines have to do with your problems?\") ::\n    nofibStringToList(\"Don't you think computers can help people?\") ::\n    nofibStringToList(\"What is it about machines that worries you?\") ::\n    Nil\n  let iWant = nofibStringToList(\"?Why do you want\") ::\n    nofibStringToList(\"?What would it mean to you if you got\") ::\n    nofibStringToList(\"?Suppose you got\") ::\n    nofibStringToList(\"?What if you never got\") ::\n    nofibStringToList(\".I sometimes also want\") ::\n    Nil\n  let question = nofibStringToList(\"Why do you ask?\") ::\n    nofibStringToList(\"Does that question interest you?\") ::\n    nofibStringToList(\"What answer would please you the most?\") ::\n    nofibStringToList(\"What do you think?\") ::\n    nofibStringToList(\"Are such questions on your mind often?\") ::\n    nofibStringToList(\"What is it that you really want to know?\") ::\n    nofibStringToList(\"Have you asked anyone else?\") ::\n    nofibStringToList(\"Have you asked such questions before?\") ::\n    nofibStringToList(\"What else comes to mind when you ask that?\") ::\n    Nil\n  let name = nofibStringToList(\"Names don't interest me.\") ::\n    nofibStringToList(\"I don't care about names --please go on.\") ::\n    Nil\n  let because = nofibStringToList(\"Is that the real reason?\") ::\n    nofibStringToList(\"Don't any other reasons come to mind?\") ::\n    nofibStringToList(\"Does that reason explain anything else?\") ::\n    nofibStringToList(\"What other reasons might there be?\") ::\n    Nil\n  let sorry = nofibStringToList(\"Please don't apologise!\") ::\n    nofibStringToList(\"Apologies are not necessary.\") ::\n    nofibStringToList(\"What feelings do you have when you apologise?\") ::\n    nofibStringToList(\"Don't be so defensive!\") ::\n    Nil\n  let dream = nofibStringToList(\"What does that dream suggest to you?\") ::\n    nofibStringToList(\"Do you dream often?\") ::\n    nofibStringToList(\"What persons appear in your dreams?\") ::\n    nofibStringToList(\"Are you disturbed by your dreams?\") ::\n    Nil\n  let hello = nofibStringToList(\"How do you...please state your problem.\") ::\n    Nil\n  let maybe = nofibStringToList(\"You don't seem quite certain.\") ::\n    nofibStringToList(\"Why the uncertain tone?\") ::\n    nofibStringToList(\"Can't you be more positive?\") ::\n    nofibStringToList(\"You aren't sure?\") ::\n    nofibStringToList(\"Don't you know?\") ::\n    Nil\n  let your = nofibStringToList(\"?Why are you concerned about my\") ::\n    nofibStringToList(\"?What about your own\") ::\n    Nil\n  let always = nofibStringToList(\"Can you think of a specific example?\") ::\n    nofibStringToList(\"When?\") ::\n    nofibStringToList(\"What are you thinking of?\") ::\n    nofibStringToList(\"Really, always?\") ::\n    Nil\n  let think = nofibStringToList(\"Do you really think so?\") ::\n    nofibStringToList(\"?But you are not sure you\") ::\n    nofibStringToList(\"?Do you doubt you\") ::\n    Nil\n  let alike = nofibStringToList(\"In what way?\") ::\n    nofibStringToList(\"What resemblence do you see?\") ::\n    nofibStringToList(\"What does the similarity suggest to you?\") ::\n    nofibStringToList(\"What other connections do you see?\") ::\n    nofibStringToList(\"Cound there really be some connection?\") ::\n    nofibStringToList(\"How?\") ::\n    Nil\n  let friend = nofibStringToList(\"Why do you bring up the topic of friends?\") ::\n    nofibStringToList(\"Do your friends worry you?\") ::\n    nofibStringToList(\"Do your friends pick on you?\") ::\n    nofibStringToList(\"Are you sure you have any friends?\") ::\n    nofibStringToList(\"Do you impose on your friends?\") ::\n    nofibStringToList(\"Perhaps your love for friends worries you.\") ::\n    Nil\n  let nokeyMsgs = nofibStringToList(\"I'm not sure I understand you fully.\") ::\n    nofibStringToList(\"What does that suggest to you?\") ::\n    nofibStringToList(\"I see.\") ::\n    nofibStringToList(\"Can you elaborate on that?\") ::\n    nofibStringToList(\"Say, do you have any psychological problems?\") ::\n    Nil\n  Predef.id of\n    [nofibStringToList(\"CAN YOU\"), canYou] ::\n    [nofibStringToList(\"CAN I\"), canI] ::\n    [nofibStringToList(\"YOU ARE\"), youAre] ::\n    [nofibStringToList(\"YOU'RE\"), youAre] ::\n    [nofibStringToList(\"I DON'T\"), iDont] ::\n    [nofibStringToList(\"I FEEL\"), iFeel] ::\n    [nofibStringToList(\"WHY DON'T YOU\"), whyDont] ::\n    [nofibStringToList(\"WHY CAN'T I\"), whyCant] ::\n    [nofibStringToList(\"ARE YOU\"), areYou] ::\n    [nofibStringToList(\"I CAN'T\"), iCant] ::\n    [nofibStringToList(\"I AM\"), iAm] ::\n    [nofibStringToList(\"I'M\"), iAm] ::\n    [nofibStringToList(\"YOU\"), you] ::\n    [nofibStringToList(\"YES\"), yes] ::\n    [nofibStringToList(\"NO\"), no] ::\n    [nofibStringToList(\"COMPUTER\"), computer] ::\n    [nofibStringToList(\"COMPUTERS\"), computer] ::\n    [nofibStringToList(\"I WANT\"), iWant] ::\n    [nofibStringToList(\"WHAT\"), question] ::\n    [nofibStringToList(\"HOW\"), question] ::\n    [nofibStringToList(\"WHO\"), question] ::\n    [nofibStringToList(\"WHERE\"), question] ::\n    [nofibStringToList(\"WHEN\"), question] ::\n    [nofibStringToList(\"NAME\"), name] ::\n    [nofibStringToList(\"WHY\"), question] ::\n    [nofibStringToList(\"CAUSE\"), because] ::\n    [nofibStringToList(\"BECAUSE\"), because] ::\n    [nofibStringToList(\"DREAM\"), dream] ::\n    [nofibStringToList(\"SORRY\"), sorry] ::\n    [nofibStringToList(\"HI\"), hello] ::\n    [nofibStringToList(\"DREAMS\"), dream] ::\n    [nofibStringToList(\"MAYBE\"), maybe] ::\n    [nofibStringToList(\"HELLO\"), hello] ::\n    [nofibStringToList(\"ALWAYS\"), always] ::\n    [nofibStringToList(\"YOUR\"), your] ::\n    [nofibStringToList(\"ALIKE\"), alike] ::\n    [nofibStringToList(\"THINK\"), think] ::\n    [nofibStringToList(\"FRIENDS\"), friend] ::\n    [nofibStringToList(\"FRIEND\"), friend] ::\n    [Nil, nokeyMsgs] ::\n    Nil\n//│ respMsgs = [[[\"C\",\"A\",\"N\",\" \",\"Y\",\"O\",\"U\"], [[\"?\",\"D\",\"o\",\"n\",\"_\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"e\",\"l\",\"i\",\"e\",\"v\",\"e\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"I\",\" \",\"c\",\"a\",\"n\"],[\"?\",\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"l\",\"i\",\"k\",\"e\",\" \",\"t\",\"o\",\" \",\"b\",\"e\",\" \",\"a\",\"b\",\"l\",\"e\",\" \",\"t\",\"o\"],[\"?\",\"Y\",\"o\",\"u\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"m\",\"e\",\" \",\"t\",\"o\",\" \",\"b\",\"e\",\" \",\"a\",\"b\",\"l\",\"e\",\" \",\"t\",\"o\"]]],[[\"C\",\"A\",\"N\",\" \",\"I\"], [[\"?\",\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"y\",\"o\",\"u\",\" \",\"d\",\"o\",\"n\",\"_\",\"t\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\",\" \",\"b\",\"e\",\" \",\"a\",\"b\",\"l\",\"e\",\" \",\"t\",\"o\"]]],[[\"Y\",\"O\",\"U\",\" \",\"A\",\"R\",\"E\"], [[\"?\",\"W\",\"h\",\"a\",\"t\",\" \",\"m\",\"a\",\"k\",\"e\",\"s\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"I\",\" \",\"a\",\"m\"],[\"?\",\"D\",\"o\",\"e\",\"s\",\" \",\"i\",\"t\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"o\",\" \",\"b\",\"e\",\"l\",\"i\",\"e\",\"v\",\"e\",\" \",\"I\",\" \",\"a\",\"m\"],[\"?\",\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"l\",\"i\",\"k\",\"e\",\" \",\"t\",\"o\",\" \",\"b\",\"e\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"o\",\"m\",\"e\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"w\",\"i\",\"s\",\"h\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"e\",\"r\",\"e\"]]],[[\"Y\",\"O\",\"U\",\"'\",\"R\",\"E\"], [[\"?\",\"W\",\"h\",\"a\",\"t\",\" \",\"m\",\"a\",\"k\",\"e\",\"s\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"I\",\" \",\"a\",\"m\"],[\"?\",\"D\",\"o\",\"e\",\"s\",\" \",\"i\",\"t\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"o\",\" \",\"b\",\"e\",\"l\",\"i\",\"e\",\"v\",\"e\",\" \",\"I\",\" \",\"a\",\"m\"],[\"?\",\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"l\",\"i\",\"k\",\"e\",\" \",\"t\",\"o\",\" \",\"b\",\"e\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"o\",\"m\",\"e\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"w\",\"i\",\"s\",\"h\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"e\",\"r\",\"e\"]]],[[\"I\",\" \",\"D\",\"O\",\"N\",\"'\",\"T\"], [[\"?\",\"D\",\"o\",\"n\",\"_\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\"],[\"?\",\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\"n\",\"_\",\"t\",\" \",\"y\",\"o\",\"u\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"i\",\"s\",\"h\",\" \",\"t\",\"o\",\" \",\"b\",\"e\",\" \",\"a\",\"b\",\"l\",\"e\",\" \",\"t\",\"o\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"t\",\"r\",\"o\",\"u\",\"b\",\"l\",\"e\",\" \",\"y\",\"o\",\"u\",\"?\"]]],[[\"I\",\" \",\"F\",\"E\",\"E\",\"L\"], [[\"T\",\"e\",\"l\",\"l\",\" \",\"m\",\"e\",\" \",\"m\",\"o\",\"r\",\"e\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"f\",\"e\",\"e\",\"l\",\"i\",\"n\",\"g\",\"s\",\".\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\" \",\"f\",\"e\",\"e\",\"l\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"e\",\"n\",\"j\",\"o\",\"y\",\" \",\"f\",\"e\",\"e\",\"l\",\"i\",\"n\",\"g\"]]],[[\"W\",\"H\",\"Y\",\" \",\"D\",\"O\",\"N\",\"'\",\"T\",\" \",\"Y\",\"O\",\"U\"], [[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"b\",\"e\",\"l\",\"i\",\"e\",\"v\",\"e\",\" \",\"I\",\" \",\"d\",\"o\",\"n\",\"'\",\"t\"],[\".\",\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"i\",\"n\",\" \",\"g\",\"o\",\"o\",\"d\",\" \",\"t\",\"i\",\"m\",\"e\",\" \",\"I\",\" \",\"w\",\"i\",\"l\",\"l\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"m\",\"e\",\" \",\"t\",\"o\"]]],[[\"W\",\"H\",\"Y\",\" \",\"C\",\"A\",\"N\",\"'\",\"T\",\" \",\"I\"], [[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"h\",\"o\",\"u\",\"l\",\"d\",\" \",\"b\",\"e\",\" \",\"a\",\"b\",\"l\",\"e\",\" \",\"t\",\"o\"],[\"?\",\"W\",\"h\",\"y\",\" \",\"c\",\"a\",\"n\",\"'\",\"t\",\" \",\"y\",\"o\",\"u\"]]],[[\"A\",\"R\",\"E\",\" \",\"Y\",\"O\",\"U\"], [[\"?\",\"W\",\"h\",\"y\",\" \",\"a\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\"e\",\"d\",\" \",\"i\",\"n\",\" \",\"w\",\"h\",\"e\",\"t\",\"h\",\"e\",\"r\",\" \",\"o\",\"r\",\" \",\"n\",\"o\",\"t\",\" \",\"I\",\" \",\"a\",\"m\"],[\"?\",\"W\",\"o\",\"u\",\"l\",\"d\",\" \",\"y\",\"o\",\"u\",\" \",\"p\",\"r\",\"e\",\"f\",\"e\",\"r\",\" \",\"i\",\"f\",\" \",\"I\",\" \",\"w\",\"e\",\"r\",\"e\",\" \",\"n\",\"o\",\"t\"],[\"?\",\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"i\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"f\",\"a\",\"n\",\"t\",\"a\",\"s\",\"i\",\"e\",\"s\",\" \",\"I\",\" \",\"a\",\"m\"]]],[[\"I\",\" \",\"C\",\"A\",\"N\",\"'\",\"T\"], [[\"?\",\"H\",\"o\",\"w\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"k\",\"n\",\"o\",\"w\",\" \",\"y\",\"o\",\"u\",\" \",\"c\",\"a\",\"n\",\"'\",\"t\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"r\",\"i\",\"e\",\"d\",\"?\"],[\"?\",\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"y\",\"o\",\"u\",\" \",\"c\",\"a\",\"n\",\" \",\"n\",\"o\",\"w\"]]],[[\"I\",\" \",\"A\",\"M\"], [[\"?\",\"D\",\"i\",\"d\",\" \",\"y\",\"o\",\"u\",\" \",\"c\",\"o\",\"m\",\"e\",\" \",\"t\",\"o\",\" \",\"m\",\"e\",\" \",\"b\",\"e\",\"c\",\"a\",\"u\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"r\",\"e\"],[\"?\",\"H\",\"o\",\"w\",\" \",\"l\",\"o\",\"n\",\"g\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"e\",\"e\",\"n\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"e\",\"l\",\"i\",\"e\",\"v\",\"e\",\" \",\"i\",\"t\",\" \",\"i\",\"s\",\" \",\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\" \",\"t\",\"o\",\" \",\"b\",\"e\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"e\",\"n\",\"j\",\"o\",\"y\",\" \",\"b\",\"e\",\"i\",\"n\",\"g\"]]],[[\"I\",\"'\",\"M\"], [[\"?\",\"D\",\"i\",\"d\",\" \",\"y\",\"o\",\"u\",\" \",\"c\",\"o\",\"m\",\"e\",\" \",\"t\",\"o\",\" \",\"m\",\"e\",\" \",\"b\",\"e\",\"c\",\"a\",\"u\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"r\",\"e\"],[\"?\",\"H\",\"o\",\"w\",\" \",\"l\",\"o\",\"n\",\"g\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"e\",\"e\",\"n\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"e\",\"l\",\"i\",\"e\",\"v\",\"e\",\" \",\"i\",\"t\",\" \",\"i\",\"s\",\" \",\"n\",\"o\",\"r\",\"m\",\"a\",\"l\",\" \",\"t\",\"o\",\" \",\"b\",\"e\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"e\",\"n\",\"j\",\"o\",\"y\",\" \",\"b\",\"e\",\"i\",\"n\",\"g\"]]],[[\"Y\",\"O\",\"U\"], [[\"W\",\"e\",\" \",\"w\",\"e\",\"r\",\"e\",\" \",\"d\",\"i\",\"s\",\"c\",\"u\",\"s\",\"s\",\"i\",\"n\",\"g\",\" \",\"y\",\"o\",\"u\",\" \",\"-\",\"-\",\"n\",\"o\",\"t\",\" \",\"m\",\"e\",\".\"],[\"?\",\"O\",\"h\",\",\"],[\"Y\",\"o\",\"u\",\"'\",\"r\",\"e\",\" \",\"n\",\"o\",\"t\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"t\",\"a\",\"l\",\"k\",\"i\",\"n\",\"g\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"m\",\"e\",\",\",\" \",\"a\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\"?\"]]],[[\"Y\",\"E\",\"S\"], [[\"Y\",\"o\",\"u\",\" \",\"s\",\"e\",\"e\",\"m\",\" \",\"q\",\"u\",\"i\",\"t\",\"e\",\" \",\"p\",\"o\",\"s\",\"i\",\"t\",\"i\",\"v\",\"e\",\".\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"S\",\"u\",\"r\",\"e\",\"?\"],[\"I\",\" \",\"s\",\"e\",\"e\",\".\"],[\"I\",\" \",\"u\",\"n\",\"d\",\"e\",\"r\",\"s\",\"t\",\"a\",\"n\",\"d\",\".\"]]],[[\"N\",\"O\"], [[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"a\",\"y\",\"i\",\"n\",\"g\",\" \",\"n\",\"o\",\" \",\"j\",\"u\",\"s\",\"t\",\" \",\"t\",\"o\",\" \",\"b\",\"e\",\" \",\"n\",\"e\",\"g\",\"a\",\"t\",\"i\",\"v\",\"e\",\"?\"],[\"Y\",\"o\",\"u\",\" \",\"a\",\"r\",\"e\",\" \",\"b\",\"e\",\"i\",\"n\",\"g\",\" \",\"a\",\" \",\"b\",\"i\",\"t\",\" \",\"n\",\"e\",\"g\",\"a\",\"t\",\"i\",\"v\",\"e\",\".\"],[\"W\",\"h\",\"y\",\" \",\"n\",\"o\",\"t\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"u\",\"r\",\"e\",\"?\"],[\"W\",\"h\",\"y\",\" \",\"n\",\"o\",\"?\"]]],[[\"C\",\"O\",\"M\",\"P\",\"U\",\"T\",\"E\",\"R\"], [[\"D\",\"o\",\" \",\"c\",\"o\",\"m\",\"p\",\"u\",\"t\",\"e\",\"r\",\"s\",\" \",\"w\",\"o\",\"r\",\"r\",\"y\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"a\",\"l\",\"k\",\"i\",\"n\",\"g\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"m\",\"e\",\" \",\"i\",\"n\",\" \",\"p\",\"a\",\"r\",\"t\",\"i\",\"c\",\"u\",\"l\",\"a\",\"r\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"f\",\"r\",\"i\",\"g\",\"h\",\"t\",\"e\",\"n\",\"e\",\"d\",\" \",\"b\",\"y\",\" \",\"m\",\"a\",\"c\",\"h\",\"i\",\"n\",\"e\",\"s\",\"?\"],[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"m\",\"e\",\"n\",\"t\",\"i\",\"o\",\"n\",\" \",\"c\",\"o\",\"m\",\"p\",\"u\",\"t\",\"e\",\"r\",\"s\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"m\",\"a\",\"c\",\"h\",\"i\",\"n\",\"e\",\"s\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"t\",\"o\",\" \",\"d\",\"o\",\" \",\"w\",\"i\",\"t\",\"h\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"p\",\"r\",\"o\",\"b\",\"l\",\"e\",\"m\",\"s\",\"?\"],[\"D\",\"o\",\"n\",\"'\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"c\",\"o\",\"m\",\"p\",\"u\",\"t\",\"e\",\"r\",\"s\",\" \",\"c\",\"a\",\"n\",\" \",\"h\",\"e\",\"l\",\"p\",\" \",\"p\",\"e\",\"o\",\"p\",\"l\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"m\",\"a\",\"c\",\"h\",\"i\",\"n\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"w\",\"o\",\"r\",\"r\",\"i\",\"e\",\"s\",\" \",\"y\",\"o\",\"u\",\"?\"]]],[[\"C\",\"O\",\"M\",\"P\",\"U\",\"T\",\"E\",\"R\",\"S\"], [[\"D\",\"o\",\" \",\"c\",\"o\",\"m\",\"p\",\"u\",\"t\",\"e\",\"r\",\"s\",\" \",\"w\",\"o\",\"r\",\"r\",\"y\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"a\",\"l\",\"k\",\"i\",\"n\",\"g\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"m\",\"e\",\" \",\"i\",\"n\",\" \",\"p\",\"a\",\"r\",\"t\",\"i\",\"c\",\"u\",\"l\",\"a\",\"r\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"f\",\"r\",\"i\",\"g\",\"h\",\"t\",\"e\",\"n\",\"e\",\"d\",\" \",\"b\",\"y\",\" \",\"m\",\"a\",\"c\",\"h\",\"i\",\"n\",\"e\",\"s\",\"?\"],[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"m\",\"e\",\"n\",\"t\",\"i\",\"o\",\"n\",\" \",\"c\",\"o\",\"m\",\"p\",\"u\",\"t\",\"e\",\"r\",\"s\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"m\",\"a\",\"c\",\"h\",\"i\",\"n\",\"e\",\"s\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"t\",\"o\",\" \",\"d\",\"o\",\" \",\"w\",\"i\",\"t\",\"h\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"p\",\"r\",\"o\",\"b\",\"l\",\"e\",\"m\",\"s\",\"?\"],[\"D\",\"o\",\"n\",\"'\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"c\",\"o\",\"m\",\"p\",\"u\",\"t\",\"e\",\"r\",\"s\",\" \",\"c\",\"a\",\"n\",\" \",\"h\",\"e\",\"l\",\"p\",\" \",\"p\",\"e\",\"o\",\"p\",\"l\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"m\",\"a\",\"c\",\"h\",\"i\",\"n\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"w\",\"o\",\"r\",\"r\",\"i\",\"e\",\"s\",\" \",\"y\",\"o\",\"u\",\"?\"]]],[[\"I\",\" \",\"W\",\"A\",\"N\",\"T\"], [[\"?\",\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"w\",\"a\",\"n\",\"t\"],[\"?\",\"W\",\"h\",\"a\",\"t\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"i\",\"t\",\" \",\"m\",\"e\",\"a\",\"n\",\" \",\"t\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"i\",\"f\",\" \",\"y\",\"o\",\"u\",\" \",\"g\",\"o\",\"t\"],[\"?\",\"S\",\"u\",\"p\",\"p\",\"o\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"g\",\"o\",\"t\"],[\"?\",\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"f\",\" \",\"y\",\"o\",\"u\",\" \",\"n\",\"e\",\"v\",\"e\",\"r\",\" \",\"g\",\"o\",\"t\"],[\".\",\"I\",\" \",\"s\",\"o\",\"m\",\"e\",\"t\",\"i\",\"m\",\"e\",\"s\",\" \",\"a\",\"l\",\"s\",\"o\",\" \",\"w\",\"a\",\"n\",\"t\"]]],[[\"W\",\"H\",\"A\",\"T\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"n\",\"s\",\"w\",\"e\",\"r\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"s\",\"t\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\",\" \",\"k\",\"n\",\"o\",\"w\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"a\",\"n\",\"y\",\"o\",\"n\",\"e\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"b\",\"e\",\"f\",\"o\",\"r\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"e\",\"l\",\"s\",\"e\",\" \",\"c\",\"o\",\"m\",\"e\",\"s\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"w\",\"h\",\"e\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\" \",\"t\",\"h\",\"a\",\"t\",\"?\"]]],[[\"H\",\"O\",\"W\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"n\",\"s\",\"w\",\"e\",\"r\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"s\",\"t\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\",\" \",\"k\",\"n\",\"o\",\"w\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"a\",\"n\",\"y\",\"o\",\"n\",\"e\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"b\",\"e\",\"f\",\"o\",\"r\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"e\",\"l\",\"s\",\"e\",\" \",\"c\",\"o\",\"m\",\"e\",\"s\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"w\",\"h\",\"e\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\" \",\"t\",\"h\",\"a\",\"t\",\"?\"]]],[[\"W\",\"H\",\"O\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"n\",\"s\",\"w\",\"e\",\"r\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"s\",\"t\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\",\" \",\"k\",\"n\",\"o\",\"w\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"a\",\"n\",\"y\",\"o\",\"n\",\"e\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"b\",\"e\",\"f\",\"o\",\"r\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"e\",\"l\",\"s\",\"e\",\" \",\"c\",\"o\",\"m\",\"e\",\"s\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"w\",\"h\",\"e\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\" \",\"t\",\"h\",\"a\",\"t\",\"?\"]]],[[\"W\",\"H\",\"E\",\"R\",\"E\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"n\",\"s\",\"w\",\"e\",\"r\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"s\",\"t\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\",\" \",\"k\",\"n\",\"o\",\"w\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"a\",\"n\",\"y\",\"o\",\"n\",\"e\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"b\",\"e\",\"f\",\"o\",\"r\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"e\",\"l\",\"s\",\"e\",\" \",\"c\",\"o\",\"m\",\"e\",\"s\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"w\",\"h\",\"e\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\" \",\"t\",\"h\",\"a\",\"t\",\"?\"]]],[[\"W\",\"H\",\"E\",\"N\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"n\",\"s\",\"w\",\"e\",\"r\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"s\",\"t\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\",\" \",\"k\",\"n\",\"o\",\"w\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"a\",\"n\",\"y\",\"o\",\"n\",\"e\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"b\",\"e\",\"f\",\"o\",\"r\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"e\",\"l\",\"s\",\"e\",\" \",\"c\",\"o\",\"m\",\"e\",\"s\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"w\",\"h\",\"e\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\" \",\"t\",\"h\",\"a\",\"t\",\"?\"]]],[[\"N\",\"A\",\"M\",\"E\"], [[\"N\",\"a\",\"m\",\"e\",\"s\",\" \",\"d\",\"o\",\"n\",\"'\",\"t\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\" \",\"m\",\"e\",\".\"],[\"I\",\" \",\"d\",\"o\",\"n\",\"'\",\"t\",\" \",\"c\",\"a\",\"r\",\"e\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"n\",\"a\",\"m\",\"e\",\"s\",\" \",\"-\",\"-\",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"g\",\"o\",\" \",\"o\",\"n\",\".\"]]],[[\"W\",\"H\",\"Y\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\" \",\"i\",\"n\",\"t\",\"e\",\"r\",\"e\",\"s\",\"t\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"n\",\"s\",\"w\",\"e\",\"r\",\" \",\"w\",\"o\",\"u\",\"l\",\"d\",\" \",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"s\",\"t\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"i\",\"s\",\" \",\"i\",\"t\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"w\",\"a\",\"n\",\"t\",\" \",\"t\",\"o\",\" \",\"k\",\"n\",\"o\",\"w\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"a\",\"n\",\"y\",\"o\",\"n\",\"e\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"H\",\"a\",\"v\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\"e\",\"d\",\" \",\"s\",\"u\",\"c\",\"h\",\" \",\"q\",\"u\",\"e\",\"s\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"b\",\"e\",\"f\",\"o\",\"r\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"e\",\"l\",\"s\",\"e\",\" \",\"c\",\"o\",\"m\",\"e\",\"s\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\" \",\"w\",\"h\",\"e\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"s\",\"k\",\" \",\"t\",\"h\",\"a\",\"t\",\"?\"]]],[[\"C\",\"A\",\"U\",\"S\",\"E\"], [[\"I\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"t\",\"h\",\"e\",\" \",\"r\",\"e\",\"a\",\"l\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\"?\"],[\"D\",\"o\",\"n\",\"'\",\"t\",\" \",\"a\",\"n\",\"y\",\" \",\"o\",\"t\",\"h\",\"e\",\"r\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\"s\",\" \",\"c\",\"o\",\"m\",\"e\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\" \",\"e\",\"x\",\"p\",\"l\",\"a\",\"i\",\"n\",\" \",\"a\",\"n\",\"y\",\"t\",\"h\",\"i\",\"n\",\"g\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"o\",\"t\",\"h\",\"e\",\"r\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\"s\",\" \",\"m\",\"i\",\"g\",\"h\",\"t\",\" \",\"t\",\"h\",\"e\",\"r\",\"e\",\" \",\"b\",\"e\",\"?\"]]],[[\"B\",\"E\",\"C\",\"A\",\"U\",\"S\",\"E\"], [[\"I\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"t\",\"h\",\"e\",\" \",\"r\",\"e\",\"a\",\"l\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\"?\"],[\"D\",\"o\",\"n\",\"'\",\"t\",\" \",\"a\",\"n\",\"y\",\" \",\"o\",\"t\",\"h\",\"e\",\"r\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\"s\",\" \",\"c\",\"o\",\"m\",\"e\",\" \",\"t\",\"o\",\" \",\"m\",\"i\",\"n\",\"d\",\"?\"],[\"D\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\" \",\"e\",\"x\",\"p\",\"l\",\"a\",\"i\",\"n\",\" \",\"a\",\"n\",\"y\",\"t\",\"h\",\"i\",\"n\",\"g\",\" \",\"e\",\"l\",\"s\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"o\",\"t\",\"h\",\"e\",\"r\",\" \",\"r\",\"e\",\"a\",\"s\",\"o\",\"n\",\"s\",\" \",\"m\",\"i\",\"g\",\"h\",\"t\",\" \",\"t\",\"h\",\"e\",\"r\",\"e\",\" \",\"b\",\"e\",\"?\"]]],[[\"D\",\"R\",\"E\",\"A\",\"M\"], [[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\" \",\"s\",\"u\",\"g\",\"g\",\"e\",\"s\",\"t\",\" \",\"t\",\"o\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"p\",\"e\",\"r\",\"s\",\"o\",\"n\",\"s\",\" \",\"a\",\"p\",\"p\",\"e\",\"a\",\"r\",\" \",\"i\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\"s\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"d\",\"i\",\"s\",\"t\",\"u\",\"r\",\"b\",\"e\",\"d\",\" \",\"b\",\"y\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\"s\",\"?\"]]],[[\"S\",\"O\",\"R\",\"R\",\"Y\"], [[\"P\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"d\",\"o\",\"n\",\"'\",\"t\",\" \",\"a\",\"p\",\"o\",\"l\",\"o\",\"g\",\"i\",\"s\",\"e\",\"!\"],[\"A\",\"p\",\"o\",\"l\",\"o\",\"g\",\"i\",\"e\",\"s\",\" \",\"a\",\"r\",\"e\",\" \",\"n\",\"o\",\"t\",\" \",\"n\",\"e\",\"c\",\"e\",\"s\",\"s\",\"a\",\"r\",\"y\",\".\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"f\",\"e\",\"e\",\"l\",\"i\",\"n\",\"g\",\"s\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"w\",\"h\",\"e\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"p\",\"o\",\"l\",\"o\",\"g\",\"i\",\"s\",\"e\",\"?\"],[\"D\",\"o\",\"n\",\"'\",\"t\",\" \",\"b\",\"e\",\" \",\"s\",\"o\",\" \",\"d\",\"e\",\"f\",\"e\",\"n\",\"s\",\"i\",\"v\",\"e\",\"!\"]]],[[\"H\",\"I\"], [[\"H\",\"o\",\"w\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\".\",\".\",\".\",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"s\",\"t\",\"a\",\"t\",\"e\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"p\",\"r\",\"o\",\"b\",\"l\",\"e\",\"m\",\".\"]]],[[\"D\",\"R\",\"E\",\"A\",\"M\",\"S\"], [[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\" \",\"s\",\"u\",\"g\",\"g\",\"e\",\"s\",\"t\",\" \",\"t\",\"o\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\" \",\"o\",\"f\",\"t\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"p\",\"e\",\"r\",\"s\",\"o\",\"n\",\"s\",\" \",\"a\",\"p\",\"p\",\"e\",\"a\",\"r\",\" \",\"i\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\"s\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"d\",\"i\",\"s\",\"t\",\"u\",\"r\",\"b\",\"e\",\"d\",\" \",\"b\",\"y\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"d\",\"r\",\"e\",\"a\",\"m\",\"s\",\"?\"]]],[[\"M\",\"A\",\"Y\",\"B\",\"E\"], [[\"Y\",\"o\",\"u\",\" \",\"d\",\"o\",\"n\",\"'\",\"t\",\" \",\"s\",\"e\",\"e\",\"m\",\" \",\"q\",\"u\",\"i\",\"t\",\"e\",\" \",\"c\",\"e\",\"r\",\"t\",\"a\",\"i\",\"n\",\".\"],[\"W\",\"h\",\"y\",\" \",\"t\",\"h\",\"e\",\" \",\"u\",\"n\",\"c\",\"e\",\"r\",\"t\",\"a\",\"i\",\"n\",\" \",\"t\",\"o\",\"n\",\"e\",\"?\"],[\"C\",\"a\",\"n\",\"'\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"e\",\" \",\"m\",\"o\",\"r\",\"e\",\" \",\"p\",\"o\",\"s\",\"i\",\"t\",\"i\",\"v\",\"e\",\"?\"],[\"Y\",\"o\",\"u\",\" \",\"a\",\"r\",\"e\",\"n\",\"'\",\"t\",\" \",\"s\",\"u\",\"r\",\"e\",\"?\"],[\"D\",\"o\",\"n\",\"'\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"k\",\"n\",\"o\",\"w\",\"?\"]]],[[\"H\",\"E\",\"L\",\"L\",\"O\"], [[\"H\",\"o\",\"w\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\".\",\".\",\".\",\"p\",\"l\",\"e\",\"a\",\"s\",\"e\",\" \",\"s\",\"t\",\"a\",\"t\",\"e\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"p\",\"r\",\"o\",\"b\",\"l\",\"e\",\"m\",\".\"]]],[[\"A\",\"L\",\"W\",\"A\",\"Y\",\"S\"], [[\"C\",\"a\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"o\",\"f\",\" \",\"a\",\" \",\"s\",\"p\",\"e\",\"c\",\"i\",\"f\",\"i\",\"c\",\" \",\"e\",\"x\",\"a\",\"m\",\"p\",\"l\",\"e\",\"?\"],[\"W\",\"h\",\"e\",\"n\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\"i\",\"n\",\"g\",\" \",\"o\",\"f\",\"?\"],[\"R\",\"e\",\"a\",\"l\",\"l\",\"y\",\",\",\" \",\"a\",\"l\",\"w\",\"a\",\"y\",\"s\",\"?\"]]],[[\"Y\",\"O\",\"U\",\"R\"], [[\"?\",\"W\",\"h\",\"y\",\" \",\"a\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"c\",\"o\",\"n\",\"c\",\"e\",\"r\",\"n\",\"e\",\"d\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"m\",\"y\"],[\"?\",\"W\",\"h\",\"a\",\"t\",\" \",\"a\",\"b\",\"o\",\"u\",\"t\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"o\",\"w\",\"n\"]]],[[\"A\",\"L\",\"I\",\"K\",\"E\"], [[\"I\",\"n\",\" \",\"w\",\"h\",\"a\",\"t\",\" \",\"w\",\"a\",\"y\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"r\",\"e\",\"s\",\"e\",\"m\",\"b\",\"l\",\"e\",\"n\",\"c\",\"e\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"e\",\"e\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"e\",\" \",\"s\",\"i\",\"m\",\"i\",\"l\",\"a\",\"r\",\"i\",\"t\",\"y\",\" \",\"s\",\"u\",\"g\",\"g\",\"e\",\"s\",\"t\",\" \",\"t\",\"o\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"o\",\"t\",\"h\",\"e\",\"r\",\" \",\"c\",\"o\",\"n\",\"n\",\"e\",\"c\",\"t\",\"i\",\"o\",\"n\",\"s\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"e\",\"e\",\"?\"],[\"C\",\"o\",\"u\",\"n\",\"d\",\" \",\"t\",\"h\",\"e\",\"r\",\"e\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"b\",\"e\",\" \",\"s\",\"o\",\"m\",\"e\",\" \",\"c\",\"o\",\"n\",\"n\",\"e\",\"c\",\"t\",\"i\",\"o\",\"n\",\"?\"],[\"H\",\"o\",\"w\",\"?\"]]],[[\"T\",\"H\",\"I\",\"N\",\"K\"], [[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"r\",\"e\",\"a\",\"l\",\"l\",\"y\",\" \",\"t\",\"h\",\"i\",\"n\",\"k\",\" \",\"s\",\"o\",\"?\"],[\"?\",\"B\",\"u\",\"t\",\" \",\"y\",\"o\",\"u\",\" \",\"a\",\"r\",\"e\",\" \",\"n\",\"o\",\"t\",\" \",\"s\",\"u\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\"],[\"?\",\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"d\",\"o\",\"u\",\"b\",\"t\",\" \",\"y\",\"o\",\"u\"]]],[[\"F\",\"R\",\"I\",\"E\",\"N\",\"D\",\"S\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"r\",\"i\",\"n\",\"g\",\" \",\"u\",\"p\",\" \",\"t\",\"h\",\"e\",\" \",\"t\",\"o\",\"p\",\"i\",\"c\",\" \",\"o\",\"f\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\" \",\"w\",\"o\",\"r\",\"r\",\"y\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\" \",\"p\",\"i\",\"c\",\"k\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"u\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"a\",\"n\",\"y\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"i\",\"m\",\"p\",\"o\",\"s\",\"e\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\"?\"],[\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"l\",\"o\",\"v\",\"e\",\" \",\"f\",\"o\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\" \",\"w\",\"o\",\"r\",\"r\",\"i\",\"e\",\"s\",\" \",\"y\",\"o\",\"u\",\".\"]]],[[\"F\",\"R\",\"I\",\"E\",\"N\",\"D\"], [[\"W\",\"h\",\"y\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"b\",\"r\",\"i\",\"n\",\"g\",\" \",\"u\",\"p\",\" \",\"t\",\"h\",\"e\",\" \",\"t\",\"o\",\"p\",\"i\",\"c\",\" \",\"o\",\"f\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\" \",\"w\",\"o\",\"r\",\"r\",\"y\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\" \",\"p\",\"i\",\"c\",\"k\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"A\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"s\",\"u\",\"r\",\"e\",\" \",\"y\",\"o\",\"u\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"a\",\"n\",\"y\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\"?\"],[\"D\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"i\",\"m\",\"p\",\"o\",\"s\",\"e\",\" \",\"o\",\"n\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\"?\"],[\"P\",\"e\",\"r\",\"h\",\"a\",\"p\",\"s\",\" \",\"y\",\"o\",\"u\",\"r\",\" \",\"l\",\"o\",\"v\",\"e\",\" \",\"f\",\"o\",\"r\",\" \",\"f\",\"r\",\"i\",\"e\",\"n\",\"d\",\"s\",\" \",\"w\",\"o\",\"r\",\"r\",\"i\",\"e\",\"s\",\" \",\"y\",\"o\",\"u\",\".\"]]],[[], [[\"I\",\"'\",\"m\",\" \",\"n\",\"o\",\"t\",\" \",\"s\",\"u\",\"r\",\"e\",\" \",\"I\",\" \",\"u\",\"n\",\"d\",\"e\",\"r\",\"s\",\"t\",\"a\",\"n\",\"d\",\" \",\"y\",\"o\",\"u\",\" \",\"f\",\"u\",\"l\",\"l\",\"y\",\".\"],[\"W\",\"h\",\"a\",\"t\",\" \",\"d\",\"o\",\"e\",\"s\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"s\",\"u\",\"g\",\"g\",\"e\",\"s\",\"t\",\" \",\"t\",\"o\",\" \",\"y\",\"o\",\"u\",\"?\"],[\"I\",\" \",\"s\",\"e\",\"e\",\".\"],[\"C\",\"a\",\"n\",\" \",\"y\",\"o\",\"u\",\" \",\"e\",\"l\",\"a\",\"b\",\"o\",\"r\",\"a\",\"t\",\"e\",\" \",\"o\",\"n\",\" \",\"t\",\"h\",\"a\",\"t\",\"?\"],[\"S\",\"a\",\"y\",\",\",\" \",\"d\",\"o\",\" \",\"y\",\"o\",\"u\",\" \",\"h\",\"a\",\"v\",\"e\",\" \",\"a\",\"n\",\"y\",\" \",\"p\",\"s\",\"y\",\"c\",\"h\",\"o\",\"l\",\"o\",\"g\",\"i\",\"c\",\"a\",\"l\",\" \",\"p\",\"r\",\"o\",\"b\",\"l\",\"e\",\"m\",\"s\",\"?\"]]]]\n\nval initial =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    [k, rs] :: t then [eliza.words(k), eliza.cycle(rs)] :: lscomp(t)\n  [lscomp(eliza.respMsgs), eliza.cycle(eliza.repeatMsgs)]\n//│ initial = [[[[[\"C\",\"A\",\"N\"],[\"Y\",\"O\",\"U\"]], Lazy([function])],[[[\"C\",\"A\",\"N\"],[\"I\"]], Lazy([function])],[[[\"Y\",\"O\",\"U\"],[\"A\",\"R\",\"E\"]], Lazy([function])],[[[\"Y\",\"O\",\"U\",\"'\",\"R\",\"E\"]], Lazy([function])],[[[\"I\"],[\"D\",\"O\",\"N\",\"'\",\"T\"]], Lazy([function])],[[[\"I\"],[\"F\",\"E\",\"E\",\"L\"]], Lazy([function])],[[[\"W\",\"H\",\"Y\"],[\"D\",\"O\",\"N\",\"'\",\"T\"],[\"Y\",\"O\",\"U\"]], Lazy([function])],[[[\"W\",\"H\",\"Y\"],[\"C\",\"A\",\"N\",\"'\",\"T\"],[\"I\"]], Lazy([function])],[[[\"A\",\"R\",\"E\"],[\"Y\",\"O\",\"U\"]], Lazy([function])],[[[\"I\"],[\"C\",\"A\",\"N\",\"'\",\"T\"]], Lazy([function])],[[[\"I\"],[\"A\",\"M\"]], Lazy([function])],[[[\"I\",\"'\",\"M\"]], Lazy([function])],[[[\"Y\",\"O\",\"U\"]], Lazy([function])],[[[\"Y\",\"E\",\"S\"]], Lazy([function])],[[[\"N\",\"O\"]], Lazy([function])],[[[\"C\",\"O\",\"M\",\"P\",\"U\",\"T\",\"E\",\"R\"]], Lazy([function])],[[[\"C\",\"O\",\"M\",\"P\",\"U\",\"T\",\"E\",\"R\",\"S\"]], Lazy([function])],[[[\"I\"],[\"W\",\"A\",\"N\",\"T\"]], Lazy([function])],[[[\"W\",\"H\",\"A\",\"T\"]], Lazy([function])],[[[\"H\",\"O\",\"W\"]], Lazy([function])],[[[\"W\",\"H\",\"O\"]], Lazy([function])],[[[\"W\",\"H\",\"E\",\"R\",\"E\"]], Lazy([function])],[[[\"W\",\"H\",\"E\",\"N\"]], Lazy([function])],[[[\"N\",\"A\",\"M\",\"E\"]], Lazy([function])],[[[\"W\",\"H\",\"Y\"]], Lazy([function])],[[[\"C\",\"A\",\"U\",\"S\",\"E\"]], Lazy([function])],[[[\"B\",\"E\",\"C\",\"A\",\"U\",\"S\",\"E\"]], Lazy([function])],[[[\"D\",\"R\",\"E\",\"A\",\"M\"]], Lazy([function])],[[[\"S\",\"O\",\"R\",\"R\",\"Y\"]], Lazy([function])],[[[\"H\",\"I\"]], Lazy([function])],[[[\"D\",\"R\",\"E\",\"A\",\"M\",\"S\"]], Lazy([function])],[[[\"M\",\"A\",\"Y\",\"B\",\"E\"]], Lazy([function])],[[[\"H\",\"E\",\"L\",\"L\",\"O\"]], Lazy([function])],[[[\"A\",\"L\",\"W\",\"A\",\"Y\",\"S\"]], Lazy([function])],[[[\"Y\",\"O\",\"U\",\"R\"]], Lazy([function])],[[[\"A\",\"L\",\"I\",\"K\",\"E\"]], Lazy([function])],[[[\"T\",\"H\",\"I\",\"N\",\"K\"]], Lazy([function])],[[[\"F\",\"R\",\"I\",\"E\",\"N\",\"D\",\"S\"]], Lazy([function])],[[[\"F\",\"R\",\"I\",\"E\",\"N\",\"D\"]], Lazy([function])],[[], Lazy([function])]], Lazy([function])]\n\nfun prefix(xxs, yys) = if xxs is\n  Nil then true\n  x :: xs and\n    force(yys) is\n      LzNil then false\n      LzCons(y, ys) then listEq(x, y) && prefix(xs, ys)\n\nfun tails(xs) = lazy of () =>\n  if xs is\n    Nil then LzNil\n    xss then LzCons(xss, tails(tail(xss)))\n\nfun ucase(ls) = map(toUpper, ls)\n\nval conjugates =\n  let oneways = [nofibStringToList(\"me\"), nofibStringToList(\"you\")] :: Nil\n  let bothways = [nofibStringToList(\"are\"), nofibStringToList(\"am\")] ::\n    [nofibStringToList(\"we're\"), nofibStringToList(\"was\")] ::\n    [nofibStringToList(\"you\"), nofibStringToList(\"I\")] ::\n    [nofibStringToList(\"your\"), nofibStringToList(\"my\")] ::\n    [nofibStringToList(\"I've\"), nofibStringToList(\"you've\")] ::\n    [nofibStringToList(\"I'm\"), nofibStringToList(\"you're\")] ::\n    Nil\n  fun prepare(ls) = map(case { [w, r] then [ucase(w), r] }, ls)\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    [x, y] :: t then ([x, y] :: [y, x] :: Nil) :: lscomp(t)\n  prepare(oneways +: concat(lscomp(bothways)))\n//│ conjugates = [[[\"M\",\"E\"], [\"y\",\"o\",\"u\"]],[[\"A\",\"R\",\"E\"], [\"a\",\"m\"]],[[\"A\",\"M\"], [\"a\",\"r\",\"e\"]],[[\"W\",\"E\",\"'\",\"R\",\"E\"], [\"w\",\"a\",\"s\"]],[[\"W\",\"A\",\"S\"], [\"w\",\"e\",\"'\",\"r\",\"e\"]],[[\"Y\",\"O\",\"U\"], [\"I\"]],[[\"I\"], [\"y\",\"o\",\"u\"]],[[\"Y\",\"O\",\"U\",\"R\"], [\"m\",\"y\"]],[[\"M\",\"Y\"], [\"y\",\"o\",\"u\",\"r\"]],[[\"I\",\"'\",\"V\",\"E\"], [\"y\",\"o\",\"u\",\"'\",\"v\",\"e\"]],[[\"Y\",\"O\",\"U\",\"'\",\"V\",\"E\"], [\"I\",\"'\",\"v\",\"e\"]],[[\"I\",\"'\",\"M\"], [\"y\",\"o\",\"u\",\"'\",\"r\",\"e\"]],[[\"Y\",\"O\",\"U\",\"'\",\"R\",\"E\"], [\"I\",\"'\",\"m\"]]]\n\nfun conjug(d, w) =\n  fun maybe(d, xs) = if null_(xs) then d else xs\n  fun conj(w) =\n    fun lscomp(ls) = if ls is\n      Nil then Nil\n      [w_, m] :: t and\n        listEq(ucase(w), w_) then m :: lscomp(t)\n        else lscomp(t)\n    head(lscomp(conjugates) +: w :: Nil)\n  fun trailingI(ls) =\n    fun cons(x, xs) =\n      if listEq(x, nofibStringToList(\"I\")) && null_(xs)\n      then nofibStringToList(\"me\") :: Nil\n      else x :: xs\n    foldr(cons, Nil, ls)\n  unwords(trailingI(map(conj, maybe(d, w))))\n\nfun replies(key, l) =\n  map_lz of\n    x => conjug(l, leave(listLen(key), x))\n    filter_lz of\n      ls => prefix(key, lz_map(ucase, ls))\n      tails(l)\n\nfun answer(st, l) =\n  fun cons(e, r_es) = if r_es is [r, es] then [r, e :: es]\n  fun ans(e_es, l) = if e_es is\n    [key, a_as] :: es and force(a_as) is LzCons(a, as_) then\n      let rs = replies(key, l)\n      if null_lz(rs)\n      then cons([key, a_as], ans(es, l))\n      else [makeResponse(a, head_lz(rs)), [key, as_] :: es]\n  if ans(keyTabOf(st), l) is [response, kt] then [response, newKeyTab(kt, st)]\n\nfun session(rs, prev, ls) = if ls is\n  Nil then Nil\n  l :: ls and\n    (if listEqBy(listEq, prev, l) then repeated(rs) else answer(rs, l)) is [response, rs_] then\n      response +: nofibStringToList(\"\\n\\n\") +: session(rs_, l, ls)\n\nfun testEliza_nofib(n) =\n  let input = Predef.id of\n    nofibStringToList(\"Are we alone?\") ::\n    nofibStringToList(\"That the Roswell event was actually an alien encounter. Do you agreed?\") ::\n    nofibStringToList(\"But why not talk about you, its more fun.\") ::\n    nofibStringToList(\"I dont ask, you do\") ::\n    nofibStringToList(\"do ray me\") ::\n    nofibStringToList(\"Nop, thats because your a computer\") ::\n    nofibStringToList(\"you dont\") ::\n    nofibStringToList(\"Oh, a paranoid computer, ehh?\") ::\n    nofibStringToList(\"Tell me about *your* mother\") ::\n    nofibStringToList(\"No, what what was she like?\") ::\n    nofibStringToList(\"I'm asking questions, not you\") ::\n    nofibStringToList(\"no\") ::\n    nofibStringToList(\"yes\") ::\n    nofibStringToList(\"but I'm not\") ::\n    Nil\n  map of\n    i => session of\n      initial\n      Nil\n      filter of\n        x => not(null_(x))\n        map(x => eliza.words(trim(x)), take(intMod(i, 20), input))\n    enumFromTo(1, n)\n\nfun main() = map(x => nofibListToString(x), testEliza_nofib(20)).toString()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/fish.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\nmodule fish with ...\n\n\nfun vec_add(v1, v2) = if v1 is [x1, y1] and v2 is [x2, y2] then [x1 + x2, y1 + y2]\n\nfun vec_sub(v1, v2) = if v1 is [x1, y1] and v2 is [x2, y2] then [x1 - x2, y1 - y2]\n\nfun scale_vec2(v, a, b) = if v is [x, y] then [intDiv(x * a, b), intDiv(y * a, b)]\n\nlet p_tile = \n  [0, 3, 3, 4] :: [3, 4, 0, 8] :: [0, 8, 0, 3] :: [6, 0, 4, 4] :: [4, 5, 4, 10] ::\n  [4, 10, 7, 6] :: [7, 6, 4, 5] :: [11, 0, 10, 4] :: [10, 4, 9, 6] :: [9, 6, 8, 8] :: [8, 8, 4, 13] ::\n  [4, 13, 0, 16] :: [0, 16, 6, 15] :: [6, 15, 8, 16] :: [8, 16, 12, 12] :: [12, 12, 16, 12] ::\n  [10, 16, 12, 14] :: [12, 14, 16, 13] :: [12, 16, 13, 15] :: [13, 15, 16, 14] :: [14, 16, 16, 15] ::\n  [8, 12, 16, 10] :: [8, 8, 12, 9] :: [12, 9, 16, 8] :: [9, 6, 12, 7] :: [12, 7, 16, 6] ::\n  [10, 4, 13, 5] :: [13, 5, 16, 4] :: [11, 0, 14, 2] :: [14, 2, 16, 2] :: Nil\n//│ p_tile = [[0, 3, 3, 4],[3, 4, 0, 8],[0, 8, 0, 3],[6, 0, 4, 4],[4, 5, 4, 10],[4, 10, 7, 6],[7, 6, 4, 5],[11, 0, 10, 4],[10, 4, 9, 6],[9, 6, 8, 8],[8, 8, 4, 13],[4, 13, 0, 16],[0, 16, 6, 15],[6, 15, 8, 16],[8, 16, 12, 12],[12, 12, 16, 12],[10, 16, 12, 14],[12, 14, 16, 13],[12, 16, 13, 15],[13, 15, 16, 14],[14, 16, 16, 15],[8, 12, 16, 10],[8, 8, 12, 9],[12, 9, 16, 8],[9, 6, 12, 7],[12, 7, 16, 6],[10, 4, 13, 5],[13, 5, 16, 4],[11, 0, 14, 2],[14, 2, 16, 2]]\n\nlet q_tile = \n  [0, 8, 4, 7] :: [4, 7, 6, 7] :: [6, 7, 8, 8] :: [8, 8, 12, 10] :: [12, 10, 16, 16] ::\n  [0, 12, 3, 13] :: [3, 13, 5, 14] :: [5, 14, 7, 15] :: [7, 15, 8, 16] :: [2, 16, 3, 13] ::\n  [4, 16, 5, 14] :: [6, 16, 7, 15] :: [0, 10, 7, 11] :: [9, 13, 8, 15] :: [8, 15, 11, 15] ::\n  [11, 15, 9, 13] :: [10, 10, 8, 12] :: [8, 12, 12, 12] :: [12, 12, 10, 10] :: [2, 0, 4, 5] ::\n  [4, 5, 4, 7] :: [4, 0, 6, 5] :: [6, 5, 6, 7] :: [6, 0, 8, 5] :: [8, 5, 8, 8] ::\n  [10, 0, 14, 11] :: [12, 0, 13, 4] :: [13, 4, 16, 8] :: [16, 8, 15, 10] :: [15, 10, 16, 16] ::\n  [13, 0, 16, 6] :: [14, 0, 16, 4] :: [15, 0, 16, 2] :: [0, 0, 8, 0] :: [12, 0, 16, 0] ::\n  [0, 0, 0, 8] :: [0, 12, 0, 16] :: Nil\n//│ q_tile = [[0, 8, 4, 7],[4, 7, 6, 7],[6, 7, 8, 8],[8, 8, 12, 10],[12, 10, 16, 16],[0, 12, 3, 13],[3, 13, 5, 14],[5, 14, 7, 15],[7, 15, 8, 16],[2, 16, 3, 13],[4, 16, 5, 14],[6, 16, 7, 15],[0, 10, 7, 11],[9, 13, 8, 15],[8, 15, 11, 15],[11, 15, 9, 13],[10, 10, 8, 12],[8, 12, 12, 12],[12, 12, 10, 10],[2, 0, 4, 5],[4, 5, 4, 7],[4, 0, 6, 5],[6, 5, 6, 7],[6, 0, 8, 5],[8, 5, 8, 8],[10, 0, 14, 11],[12, 0, 13, 4],[13, 4, 16, 8],[16, 8, 15, 10],[15, 10, 16, 16],[13, 0, 16, 6],[14, 0, 16, 4],[15, 0, 16, 2],[0, 0, 8, 0],[12, 0, 16, 0],[0, 0, 0, 8],[0, 12, 0, 16]]\n\nlet r_tile = \n  [0, 0, 8, 8] :: [12, 12, 16, 16] :: [0, 4, 5, 10] :: [0, 8, 2, 12] :: [0, 12, 1, 14] ::\n  [16, 6, 11, 10] :: [11, 10, 6, 16] :: [16, 4, 14, 6] :: [14, 6, 8, 8] :: [8, 8, 5, 10] ::\n  [5, 10, 2, 12] :: [2, 12, 0, 16] :: [16, 8, 12, 12] :: [12, 12, 11, 16] :: [1, 1, 4, 0] ::\n  [2, 2, 8, 0] :: [3, 3, 8, 2] :: [8, 2, 12, 0] :: [5, 5, 12, 3] :: [12, 3, 16, 0] ::\n  [11, 16, 12, 12] :: [12, 12, 16, 8] :: [13, 13, 16, 10] :: [14, 14, 16, 12] :: [15, 15, 16, 14] :: Nil\n//│ r_tile = [[0, 0, 8, 8],[12, 12, 16, 16],[0, 4, 5, 10],[0, 8, 2, 12],[0, 12, 1, 14],[16, 6, 11, 10],[11, 10, 6, 16],[16, 4, 14, 6],[14, 6, 8, 8],[8, 8, 5, 10],[5, 10, 2, 12],[2, 12, 0, 16],[16, 8, 12, 12],[12, 12, 11, 16],[1, 1, 4, 0],[2, 2, 8, 0],[3, 3, 8, 2],[8, 2, 12, 0],[5, 5, 12, 3],[12, 3, 16, 0],[11, 16, 12, 12],[12, 12, 16, 8],[13, 13, 16, 10],[14, 14, 16, 12],[15, 15, 16, 14]]\n\nlet s_tile = \n  [0, 0, 4, 2] :: [4, 2, 8, 2] :: [8, 2, 16, 0] :: [0, 4, 2, 1] :: [0, 6, 7, 4] ::\n  [0, 8, 8, 6] :: [0, 10, 7, 8] :: [0, 12, 7, 10] :: [0, 14, 7, 13] :: [13, 13, 16, 14] ::\n  [14, 11, 16, 12] :: [15, 9, 16, 10] :: [16, 0, 10, 4] :: [10, 4, 8, 6] :: [8, 6, 7, 8] ::\n  [7, 8, 7, 13] :: [7, 13, 8, 16] :: [12, 16, 13, 13] :: [13, 13, 14, 11] :: [14, 11, 15, 9] ::\n  [15, 9, 16, 8] :: [10, 16, 11, 10] :: [12, 4, 10, 6] :: [10, 6, 12, 7] :: [12, 7, 12, 4] ::\n  [15, 5, 13, 7] :: [13, 7, 15, 8] :: [15, 8, 15, 5] :: Nil\n//│ s_tile = [[0, 0, 4, 2],[4, 2, 8, 2],[8, 2, 16, 0],[0, 4, 2, 1],[0, 6, 7, 4],[0, 8, 8, 6],[0, 10, 7, 8],[0, 12, 7, 10],[0, 14, 7, 13],[13, 13, 16, 14],[14, 11, 16, 12],[15, 9, 16, 10],[16, 0, 10, 4],[10, 4, 8, 6],[8, 6, 7, 8],[7, 8, 7, 13],[7, 13, 8, 16],[12, 16, 13, 13],[13, 13, 14, 11],[14, 11, 15, 9],[15, 9, 16, 8],[10, 16, 11, 10],[12, 4, 10, 6],[10, 6, 12, 7],[12, 7, 12, 4],[15, 5, 13, 7],[13, 7, 15, 8],[15, 8, 15, 5]]\n\nfun nil(a, b, c) = Nil\n\nfun tup2(a_b, c_d) = if a_b is [a, b] and c_d is [c, d] then [a, b, c, d]\n\nfun grid(m, n, segments, a, b, c) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    [x0, y0, x1, y1] :: t then\n      tup2(\n        vec_add(vec_add(a, scale_vec2(b, x0, m)), scale_vec2(c, y0, n)),\n        vec_add(vec_add(a, scale_vec2(b, x1, m)), scale_vec2(c, y1, n))\n      ) ::\n      lscomp(t)\n  lscomp(segments)\n\nfun rot(p, a, b, c) = p(vec_add(a, b), c, vec_sub([0, 0], b))\n\nfun beside(m, n, p, q, a, b, c) =\n  p(a, scale_vec2(b, m, m + n), c) +:\n  q(vec_add(a, scale_vec2(b, m, m + n)), scale_vec2(b, n, n + m), c)\n\nfun above(m, n, p, q, a, b, c) =\n  p(vec_add(a, scale_vec2(c, n, m + n)), b, scale_vec2(c, m, n + m)) +:\n  q(a, b, scale_vec2(c, n, m + n))\n\nfun tile_to_grid(arg, arg2, arg3, arg4) = grid(16, 16, arg, arg2, arg3, arg4)\n\nfun p(arg, q6, q7) = tile_to_grid(p_tile, arg, q6, q7)\n\nfun q(arg, q6, q7) = tile_to_grid(q_tile, arg, q6, q7)\n\nfun r(arg, q6, q7) = tile_to_grid(r_tile, arg, q6, q7)\n\nfun s(arg, q6, q7) = tile_to_grid(s_tile, arg, q6, q7)\n\nfun quartet(a, b, c, d, arg, a6, a7) =\n  above of\n    1\n    1\n    (p5, p6, p7) => beside(1, 1, a, b, p5, p6, p7)\n    (p5, p6, p7) => beside(1, 1, c, d, p5, p6, p7)\n    arg\n    a6\n    a7\n\nfun t(arg, q6, q7) = quartet(p, q, r, s, arg, q6, q7)\n\nfun cycle_(p1, arg, p3, p4) =\n  quartet of\n    p1\n    (a, b, c) => rot of\n      (a, b, c) => rot of\n        (a, b, c) => rot(p1, a, b, c)\n        a\n        b\n        c\n      a\n      b\n      c\n    (a, b, c) => rot(p1, a, b, c)\n    (a, b, c) => rot of\n      (a, b, c) => rot(p1, a, b, c)\n      a\n      b\n      c\n    arg\n    p3\n    p4\n\nfun u(arg, p2, p3) = cycle_((a, b, c) => rot(q, a, b, c), arg, p2, p3)\n\nfun side1(arg, q6, q7) = quartet(nil, nil, (a, b, c) => rot(t, a, b, c), t, arg, q6, q7)\n\nfun side2(arg, q6, q7) = quartet(side1, side1, (a, b, c) => rot(t, a, b, c), t, arg, q6, q7)\n\nfun corner1(arg, q6, q7) = quartet(nil, nil, nil, u, arg, q6, q7)\n\nfun corner2(arg, q6, q7) = quartet(corner1, side1, (a, b, c) => rot(side1, a, b, c), u, arg, q6, q7)\n\nfun pseudocorner(arg, q6, q7) = quartet(corner2, side2, (a, b, c) => rot(side2, a, b, c), (a, b, c) => rot(t, a, b, c), arg, q6, q7)\n\nfun pseudolimit(arg, p2, p3) = cycle_(pseudocorner, arg, p2, p3)\n\nfun showFourTupleofInt(a_b_c_d) = if a_b_c_d is [a, b, c, d] then\n  nofibStringToList(\"(\") +:\n  nofibStringToList(stringOfInt(a)) +:\n  nofibStringToList(\",\") +:\n  nofibStringToList(stringOfInt(b)) +:\n  nofibStringToList(\",\") +:\n  nofibStringToList(stringOfInt(c)) +:\n  nofibStringToList(\",\") +:\n  nofibStringToList(stringOfInt(d))\n\nfun fmt(ls) = if ls is\n  Nil then nofibStringToList(\"[]\")\n  x :: xs then\n    fun showl(ls, s) = if ls is\n      Nil then \"]\" :: s\n      x :: xs then\n        nofibStringToList(\",|\") +:\n        showFourTupleofInt(x) +:\n        showl(xs, s)\n    nofibStringToList(\"[|\") +:\n    showFourTupleofInt(x) +:\n    showl(xs, \"\")\n\nfun testFish_nofib(n) =\n  map of\n    i => let n = min(0, i) in (pseudolimit([0, 0], [640 + n, 0], [0, 640 + n])),\n    enumFromTo(0, n)\n\n// With a non-recursive definition of `+:` in `NofibPrelude.mls`,\n// this won't stack overflow\nfun main() = testFish_nofib(1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/gcd.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\n\n\nmodule gcd with ...\n\n\n\nfun g(u1u2u3, v1v2v3) = if u1u2u3 is [u1, u2, u3] and v1v2v3 is [v1, v2, v3] then\n  if\n    v3 == 0 then [u3, u1, u2]\n    else if\n      quotRem(u3, v3) is [q, r] then\n        g([v1, v2, v3], [u1 - (q * v1), u2 - (q * v2), r])\n\nfun gcdE(x, y) = if \n  x == 0 then [y, 0, 1]\n  else g([1, 0, x], [0, 1, y])\n\nfun max_(ls) = if ls is\n  x :: Nil then x\n  x :: y :: xs then if x < y then max_(y :: xs) else max_(x :: xs)\n\nfun test(d) =\n  let ns = enumFromTo(5000, 5000 + d)\n\n  let ms = enumFromTo(10000, 10000 + d)\n\n  fun lscomp1(p1) = if p1 is\n    Nil then Nil\n    h1 :: t1 then\n      fun lscomp2(p2) = if p2 is\n        Nil then lscomp1(t1)\n        h2 :: t2 then [h1, h2] :: lscomp2(t2)\n      lscomp2(ms)\n\n  let tripls =\n    map(case { [x, y] then [x, y, gcdE(x, y)] }, lscomp1(ns))\n\n  let rs = map(case { [d1, d2, [gg, u, v]] then abs(gg + u + v) }, tripls)\n\n  max_(rs)\n\n\nfun testGcd_nofib(x) = test(x)\n\n\n\n// NOTE: original input 400\nfun main() = testGcd_nofib(40)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/integer.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule integer with ...\n\n\n\nfun integerbench(op, astart, astep, alim, bstart, bstep, blim) =\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    a :: t1 then\n      fun lscomp2(ls) = if ls is\n        Nil then lscomp1(t1)\n        b :: t2 then op(a, b) :: lscomp2(t2)\n      lscomp2(enumFromThenTo(bstart, bstart + bstep, blim))\n\n  lscomp1(enumFromThenTo(astart, astart + astep, alim))\n\nfun intbench(op, astart, astep, alim, bstart, bstep, blim) =\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    a :: t1 then\n      fun lscomp2(ls) = if ls is\n        Nil then lscomp1(t1)\n        b :: t2 then op(a, b) :: lscomp2(t2)\n      lscomp2(enumFromThenTo(bstart, bstart + bstep, blim))\n\n  lscomp1(enumFromThenTo(astart, astart + astep, alim))\n\nfun runbench(jop, iop, opstr, astart, astep, alim, bstart, bstep, blim) =\n  intbench(iop, astart, astep, alim, astart, astep, alim);\n  integerbench(jop, astart, astep, alim, astart, astep, alim)\n\nfun runalltests(astart, astep, alim, bstart, bstep, blim) =\n  fun z_add(a, b) = a + b\n  fun z_sub(a, b) = a - b\n  fun z_mul(a, b) = a * b\n  fun z_div(a, b) = intDiv(a, b)\n  fun z_mod(a, b) = intMod(a, b)\n  fun z_equal(a, b) = a == b\n  fun z_lt(a, b) = a < b\n  fun z_leq(a, b) = a <= b\n  fun z_gt(a, b) = a > b\n  fun z_geq(a, b) = a >= b\n\n  runbench((a, b) => z_add(a, b), (a, b) => a + b, \"(+)\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_sub(a, b), (a, b) => a - b, \"(-)\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_mul(a, b), (a, b) => a * b, \"(*)\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_div(a, b), (a, b) => intDiv(a, b), \"div\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_mod(a, b), (a, b) => intMod(a, b), \"mod\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_equal(a, b), (a, b) => a == b, \"(==)\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_lt(a, b), (a, b) => a < b, \"(<)\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_leq(a, b), (a, b) => a <= b, \"(<=)\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_gt(a, b), (a, b) => a > b, \"(>)\", astart, astep, alim, astart, astep, alim);\n  runbench((a, b) => z_geq(a, b), (a, b) => a >= b, \"(>=)\", astart, astep, alim, astart, astep, alim)\n\nfun testInteger_nofib(n) = runalltests(-2100000000, n, 2100000000, -2100000000, n, -2100000000)\n\n\n// NOTE: original input -2100000000 14000001 2100000000\nfun main() = testInteger_nofib(700000001).toString()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/knights.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule knights with ...\n\n\nfun myIsDigit(c) =\n  c.codePointAt(0) >= 48 && c.codePointAt(0) <= 57\n\nfun intintComp(a_b, c_d) = if a_b is [a, b] and c_d is [c, d] then (a < c) || ((a === c) && (b < d))\n\nfun intChessSetComp(a_b, c_d) = if a_b is [a, b] and c_d is [c, d] then a < c\n\nfun myInit(a_t) = if a_t is\n  a :: Nil then Nil\n  a :: t then a :: myInit(t)\n\nfun myLast(a_t) =\n  fun go(h, t) = if t is\n    Nil then h\n    head :: t then go(head, t)\n  if a_t is a :: t then go(a, t)\n\nfun quickSortIntInt(xs) = if xs is\n  Nil then Nil\n  x :: xs then\n    fun lscomp1(ls) = if ls is\n      Nil then Nil\n      h :: t and\n        intintComp(h, x) then h :: lscomp1(t)\n        else lscomp1(t)\n    fun lscomp2(ls) = if ls is\n      Nil then Nil\n      h :: t and\n        not(intintComp(h, x)) then h :: lscomp2(t)\n        else lscomp2(t)\n    quickSortIntInt(lscomp1(xs)) +: (x :: quickSortIntInt(lscomp2(xs)))\n\nfun quickSortIntChessSet(xs) = if force(xs) is\n  LzNil then lazy of () => LzNil\n  LzCons(x, xs) then\n    fun lscomp1(ls) = if force(ls) is\n      LzNil then lazy of () => LzNil\n      LzCons(h, t) and\n        intChessSetComp(h, x) then lazy of () => LzCons(h, lscomp1(t))\n        else lscomp1(t)\n    fun lscomp2(ls) = if force(ls) is\n      LzNil then lazy of () => LzNil\n      LzCons(h, t) and\n        not(intChessSetComp(h, x)) then lazy of () => LzCons(h, lscomp2(t))\n        else lscomp2(t)\n    append_lz_lz(quickSortIntChessSet(lscomp1(xs)), lazy of () => LzCons(x, quickSortIntChessSet(lscomp2(xs))))\n\nfun sizeQueue(xs) = listLen(xs)\n\nfun emptyQueue(x) = listEq(x, Nil)\n\nfun removeBack(xs) = if xs is\n  x :: Nil then Nil\n  x :: xs then x :: removeBack(xs)\n\nfun removeFront(xs) = if xs is\n  h :: t then t\n\nfun inquireBack(xs) = if xs is\n  x :: Nil then x\n  x :: xs then inquireBack(xs)\n\nfun inquireFront(h_t) = head(h_t)\n\nfun addAllBack(list, q) = q +: list\n\nfun addAllFront(list, q) = list +: q\n\nfun addBack(x, q) = q +: (x :: Nil)\n\nfun addFront(x, q) = x :: q\n\nval createQueue = Nil\n//│ createQueue = []\n\ndata class Board(a: Int, b: Int, c: Lazy[[Int, Int]], d: List[[Int, Int]])\n\nfun createBoard(x, t) = Board(x, 1, (lazy of (() => t)), t :: Nil)\n\nfun sizeBoard(b) = if b is Board(a, _, _, _) then a\n\nfun noPieces(b) = if b is Board(_, n, _, _) then n\n\nfun addPiece(t, b) = if b is Board(s, n, f, ts) then Board(s, n + 1, f, t :: ts)\n\nfun deleteFirst(b) = if b is Board(s, n, f, ts) then\n  let ts_ = myInit(ts)\n  Board(s, n - 1, (lazy of () => myLast(ts_)), ts_)\n\nfun positionPiece(x, b) = if b is Board(_, n, _, ts) then atIndex(n - x, ts)\n\nfun lastPiece(b) = if b is Board(_, _, _, t :: ts) then t\n\nfun firstPiece(b) = if b is Board(_, _, f, _) then force(f)\n\nfun pieceAtTile(x, b) = if b is Board(_, _, _, ts) then\n  fun find(x, xs) = if xs is\n    Nil then throw Error(\"Tile not used\")\n    y :: xs then if eqTup2(x, y) then 1 + listLen(xs) else find(x, xs)\n  find(x, ts)\n\nfun tup2InList(y, xs) = if xs is\n  Nil then false\n  x :: xs and\n    eqTup2(y, x) then true\n    else tup2InList(y, xs)\n\nfun isSquareFree(x, b) = if b is Board(_, _, _, ts) then not(tup2InList(x, ts))\n\nfun assignMoveNo(t, size, z) = if t is\n  Nil then Nil\n  [x, y] :: t then [(y - 1) * size + x, z] :: assignMoveNo(t, size, z - 1)\n\nfun spaces(s, y) =\n  fun logTen(x) = if x === 0 then 0 else 1 + logTen(intDiv(x, 10))\n  replicate((logTen(s) - logTen(y)) + 1, \" \")\n\nfun printBoard(s, n, xs) = if xs is\n  Nil and\n    n > s * s then Nil\n    intMod(n, s) != 0 then \"*\" :: (spaces(s * s, 1) +: printBoard(s, n + 1, Nil))\n    intMod(n, s) === 0 then nofibStringToList(\"*\\n\") +: printBoard(s, n + 1, Nil)\n    else throw Error(\"printBoard empty list error\")\n  [i, j] :: xs and\n    i === n and intMod(n, s) === 0 then nofibStringToList(stringOfInt(j)) +: nofibStringToList(\"\\n\") +: printBoard(s, n + 1, xs)\n    i === n and intMod(n, s) != 0 then nofibStringToList(stringOfInt(j)) +: spaces(s * s, j) +: printBoard(s, n + 1, xs)\n    intMod(n, s) != 0 then \"*\" :: (spaces(s * s, 1) +: printBoard(s, n + 1, [i, j] :: xs))\n    intMod(n, s) === 0 then nofibStringToList(\"*\\n\") +: printBoard(s, n + 1, [i, j] :: xs)\n    else throw Error(\"printBoard non-empty list error\")\n\nabstract class Direction: UL | UR | DL | DR | LU | LD | RU | RD\n\nobject\n  UL extends Direction\n  UR extends Direction\n  DL extends Direction\n  DR extends Direction\n  LU extends Direction\n  LD extends Direction\n  RU extends Direction\n  RD extends Direction\n\nfun move(d, x_y) = if x_y is [x, y] and d is\n  UL then [x - 1, y - 2]\n  UR then [x + 1, y - 2]\n  DL then [x - 1, y + 2]\n  DR then [x + 1, y + 2]\n  LU then [x - 2, y - 1]\n  LD then [x - 2, y + 1]\n  RU then [x + 2, y - 1]\n  RD then [x + 2, y + 1]\n\nfun startTour(st, size) =\n  if intMod(size, 2) === 0 then createBoard(size, st)\n  else throw Error(\"Tour doesnt exist for odd size board\")\n\nfun moveKnight(board, dir) = addPiece(move(dir, lastPiece(board)), board)\n\nfun canMoveTo(x_y, board) = if x_y is [x, y] then\n  let sze = sizeBoard(board)\n  let res = (x >= 1) and (x <= sze) and (y >= 1) and (y <= sze) and (isSquareFree(x_y, board))\n  res\n\nfun canMove(board, dir) = canMoveTo(move(dir, lastPiece(board)), board)\n\nfun canJumpFirst(board) = canMoveTo(firstPiece(board), deleteFirst(board))\n\nfun tourFinished(board) =\n  let sze = sizeBoard(board)\n  (noPieces(board) === (sze * sze)) && canJumpFirst(board)\n\nfun possibleMoves(board) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      canMove(board, x) then x :: lscomp(t)\n      else lscomp(t)\n  let res = lscomp(UL :: UR :: DL :: DR :: LU :: LD :: RU :: RD :: Nil)\n  res\n\nfun deadEnd(board) = listLen(possibleMoves(board)) === 0\n\nfun allDescend(board) = map(b => moveKnight(board, b), possibleMoves(board))\n\nfun descAndNo(board) =\n  fun lscomp(ls) = if ls is\n    Nil then lazy of () => LzNil\n    x :: t then lazy of () => LzCons([listLen(possibleMoves(deleteFirst(x))), x], lscomp(t))\n  lscomp(allDescend(board))\n\nfun singleDescend(board) =\n  fun lscomp(ls) = if force(ls) is\n    LzNil then Nil\n    LzCons([y, x], t) and\n      y === 1 then x :: lscomp(t)\n      else lscomp(t)\n  lscomp(descAndNo(board))\n\nfun descendents(board) =\n  if canJumpFirst(board) && deadEnd(addPiece(firstPiece(board), board)) then lazy of () => LzNil\n  else\n    let singles = singleDescend(board)\n    let scrut = listLen(singles)\n    let res = if scrut ===\n      0 then map_lz(snd, quickSortIntChessSet(descAndNo(board)))\n      1 then if singles is h :: Nil then lazy of () => LzCons(h, lazy of () => LzNil) else throw Error(\"unreachable\")\n      else lazy of () => LzNil\n    res\n\n\nfun showChessSet(b) = if b is Board(sze, n, f, ts) then\n  let sortedTrail = quickSortIntInt(assignMoveNo(ts, sze, n))\n  printBoard(sze, 1, sortedTrail)\n\nfun root(sze) =\n  fun lscomp1(ls) = if ls is\n    Nil then lazy of () => LzNil\n    h1 :: t1 then\n      fun lscomp2(ls) = if ls is\n        Nil then lscomp1(t1)\n        h2 :: t2 then lazy of () => LzCons([h1, h2], lscomp2(t2))\n      lscomp2(enumFromTo(1, sze))\n  append_lz_lz(\n    zip_lz_lz(\n      repeat(1 - (sze * sze)),\n      zipWith_lz_lz(startTour, lscomp1(enumFromTo(1, sze)), replicate_lz(sze * sze, sze))\n    ),\n    lazy of () => LzNil\n  )\n\nfun grow(x_y) = if x_y is [x, y] then zip_lz_lz(repeat(x + 1), descendents(y))\n\nfun isFinished(x_y) = if x_y is [x, y] then tourFinished(y)\n\nfun emptyQueue_lz(x) = force(x) is LzNil\n\nfun removeFront_lz(xs) = if force(xs) is LzCons(h, t) then t\n\nfun inquireFront_lz(h_t) = if force(h_t) is LzCons(h, t) then h\n\nfun addAllFront_lz(list, q) = append_lz_lz(list, q)\n\nfun depthSearch(q, growFn, finFn) =\n  if\n    emptyQueue_lz(q) then lazy of () => LzNil\n    finFn(inquireFront_lz(q)) then lazy of () => LzCons(inquireFront_lz(q), depthSearch(removeFront_lz(q), growFn, finFn))\n    else depthSearch(addAllFront_lz(growFn(inquireFront_lz(q)), removeFront_lz(q)), growFn, finFn)\n\nfun printTour(ss) =\n  fun strToInt(y, xs) = if xs is\n    Nil then y\n    x :: xs then strToInt((10 * y) + (x.codePointAt(0) - 48), xs)\n  fun pp(xs) = if xs is\n    Nil then Nil\n    [x, y] :: xs then\n      nofibStringToList(\"\\nKnights tour with \") +:\n      nofibStringToList(stringOfInt(x)) +:\n      nofibStringToList(\" backtracking moves\\n\") +:\n      showChessSet(y) +:\n      pp(xs)\n  if map(x => strToInt(0, x), ss) is\n    size :: number :: Nil then pp(take_lz(number, depthSearch(root(size), grow, isFinished)))\n    else throw Error(\"printTour error\")\n\nfun testKnights_nofib(ss) =\n  let usageString = \"\\nUsage: knights <board size> <no solutions> \\n\"\n  fun all_digits(s) = foldr((a, b) => (myIsDigit(a)) && b, true, s)\n  fun argsOk(ss) = (listLen(ss) === 2) && (foldr((a, b) => (all_digits(a)) && b, true, ss))\n  if argsOk(ss) then (printTour(ss)) else throw Error(usageString)\n\n\nfun main() = nofibListToString(testKnights_nofib(nofibStringToList(\"8\") :: nofibStringToList(\"1\") :: Nil))\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/lambda.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule lambda with ...\n\n\n\nfun lookup(k, t) = if t is\n  Nil then None\n  [x, v] :: t then if listEq(k, x) then Some(v) else lookup(k, t)\n\ndata class MyState[S, A](r: S -> [S, A])\n\nfun myRunState(m, s) = if m is MyState(f) then f(s)\n\nfun myBind(m, f) = MyState(s => if myRunState(m, s) is [s_, a] then myRunState(f(a), s_))\n\nfun myReturn(a) = MyState(s => [s, a])\n\nval myGet = MyState(s => [s, s])\n//│ myGet = MyState([function])\n\nfun myEvalState(m, s) = if myRunState(m, s) is [s_, a] then a\n\n\nabstract class Term: Var | Con | Incr | Add | Lam | App | IfZero | Thunk\n\nobject Incr extends Term\n\ndata\n  class\n    Var(s: String) extends Term\n    Con(i: Int) extends Term\n    Add(a: Term, b: Term) extends Term\n    Lam(s: String, t: Term) extends Term\n    App(a: Term, b: Term) extends Term\n    IfZero(a: Term, b: Term, c: Term) extends Term\n    Thunk(t: Term, e: List[[String, Term]]) extends Term\n\nobject Unit\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun eqEnv(a, b) = if a is\n  Nil and b is Nil then true\n  [s1, t1] :: b and b is [s2, t2] :: d and\n    listEq(s1, s2) and eqTerm(t1, t2) then eqEnv(b, d)\n    else false\n  else false\n\nfun eqTerm(a, b) = if a is\n  Var(a) and b is Var(b) then listEq(a, b)\n  Con(a) and b is Con(b) then a === b\n  Incr and b is Incr then true\n  Add(a, b) and b is Add(c, d) then eqTerm(a, c) && eqTerm(b, d)\n  Lam(a, b) and b is Lam(c, d) then listEq(a, c) && eqTerm(b, d)\n  App(a, b) and b is App(c, d) then eqTerm(a, c) && eqTerm(b, d)\n  IfZero(a, b, c) and b is IfZero(d, e, f) then eqTerm(a, d) && eqTerm(b, e) && eqTerm(c, f)\n  Thunk(a, b) and b is Thunk(c, d) then eqTerm(a, c) && eqEnv(b, d)\n  else false\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun myMaybe(d, f, x) = if x is Some(x) then f(x)\n\nval incr = myReturn(Unit)\n//│ incr = MyState([function])\n\nfun lookupVar(v) =\n  fun lookup2(env) = myMaybe(dummy => throw Error(\"undefined\"), x => x, lookup(v, env))\n  myBind(myGet, env => myReturn(lookup2(env)))\n\nfun withEnv(tmp, m) = myReturn(myEvalState(m, tmp))\n\nfun pushVar(v, t, m) = myBind(myGet, env => withEnv([v, t] :: env, m))\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun traverseTerm(t) = eval(t)\n\nfun traverseCon(t) =\n  myBind(\n    traverseTerm(t),\n    _t => if _t is Con(c) then myReturn(c) else throw Error(\"Not a Con\")\n  )\n\nfun apply(t, a) = if t is Thunk(Lam(x, b), e) then\n  myBind(\n    myGet,\n    orig => withEnv(e, pushVar(x, Thunk(a, orig), traverseTerm(b)))\n  )\n\nfun eval(ter) = if ter is\n  Var(x) then\n    myBind of\n      myGet\n      e => myBind(lookupVar(x), t => traverseTerm(t))\n  Add(u, v) then\n    myBind of\n      traverseCon(u)\n      u_ => myBind(traverseCon(v), v_ => myReturn(Con(u_ + v_)))\n  Thunk(t, e) then withEnv(e, traverseTerm(t))\n  Lam(x, b) then myBind(myGet, env => myReturn(Thunk(Lam(x, b), env)))\n  App(u, v) then myBind(traverseTerm(u), u_ => apply(u_, v))\n  IfZero(c, a, b) then\n    myBind of\n      traverseTerm(c)\n      vall => if eqTerm(vall, Con(0)) then traverseTerm(a) else traverseTerm(b)\n  Con(i) then myReturn(Con(i))\n  Incr then myBind(incr, _dummy => myReturn(Con(0)))\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun simpleEval(env, ter) = if ter is\n  Var(v) then simpleEval(env, myMaybe(dummy => throw Error(\"undefined var\"), x => x, lookup(v, env)))\n  Con(e) then Con(e)\n  Incr then Con(0)\n  Add(u, v) then\n    let u_ = simpleEvalCon(env, u)\n    let v_ = simpleEvalCon(env, v)\n    Con(u_ + v_)\n  Lam(x, b) then Thunk(Lam(x, b), env)\n  App(u, v) then\n    let u_ = simpleEval(env, u)\n    simpleApply(env, u_, v)\n  IfZero(c, a, b) then\n    let val_ = simpleEval(env, c)\n    if eqTerm(val_, Con(0)) then simpleEval(env, a) else simpleEval(env, b)\n  Thunk(t, e) then simpleEval(e, t)\n  else throw Error(ter)\n\nfun simpleApply(env, t, a) = if t is\n  Thunk(Lam(x, b), e) then simpleEval([x, Thunk(a, env)] :: e, b)\n  else throw Error(\"bad application\")\n\nfun simpleEvalCon(env, e) =\n  let e_ = simpleEval(env, e)\n  if e_ is Con(c) then c else throw Error(\"Not a Con\")\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun bracket(ot, ths, t) = if ths <= ot then \"(\" :: (t +: nofibStringToList(\")\")) else t\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun ppn(n, ter) = if ter is\n  Var(v) then v\n  Con(i) then nofibStringToList(stringOfInt(i))\n  Incr then nofibStringToList(\"INCR\")\n  Lam(v, t) then bracket(n, 0, \"@\" :: (v +: nofibStringToList(\". \") +: ppn(0-1, t)))\n  Add(a, b) then bracket(n, 1, ppn(1, a) +: nofibStringToList(\" + \") +: ppn(1, b))\n  App(a, b) then bracket(n, 2, ppn(2, a) +: nofibStringToList(\" \") +: ppn(2, b))\n  IfZero(c, a, b) then bracket(n, 0, nofibStringToList(\"IF \") +: ppn(0, c) +: nofibStringToList(\" THEN \") +: ppn(0, a) +: nofibStringToList(\" ELSE \") +: ppn(0, b))\n  Thunk(t, e) then bracket(n, 0, ppn(3, t) +: nofibStringToList(\"::\") +: ppenv(e))\n\nfun pp(t) = ppn(0, t)\n\nfun ppenv(env) =\n  nofibStringToList(\"[\") +:\n  flatMap(\n    case { [v, t] then v +: nofibStringToList(\"=\") +: pp(t) +: nofibStringToList(\", \") }\n    env\n  ) +:\n  nofibStringToList(\"]\")\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nval lfxx = Lam(nofibStringToList(\"x\"), App(Var(nofibStringToList(\"F\")), App(Var(nofibStringToList(\"x\")), Var(nofibStringToList(\"x\")))))\n//│ lfxx = Lam([\"x\"], App(Var([\"F\"]), App(Var([\"x\"]), Var([\"x\"]))))\n\nval fix = Lam(nofibStringToList(\"F\"), App(lfxx, lfxx))\n//│ fix = Lam([\"F\"], App(Lam([\"x\"], App(Var([\"F\"]), App(Var([\"x\"]), Var([\"x\"])))), Lam([\"x\"], App(Var([\"F\"]), App(Var([\"x\"]), Var([\"x\"]))))))\n\nval nMinus1 = Add(Var(nofibStringToList(\"n\")), Con(-1))\n//│ nMinus1 = Add(Var([\"n\"]), Con(-1))\n\nval partialSum0 = Lam(nofibStringToList(\"sum\"), Lam(nofibStringToList(\"n\"), IfZero(Var(nofibStringToList(\"n\")), Con(0), Add(Var(nofibStringToList(\"n\")), App(Var(nofibStringToList(\"sum\")), nMinus1)))))\n//│ partialSum0 = Lam([\"s\",\"u\",\"m\"], Lam([\"n\"], IfZero(Var([\"n\"]), Con(0), Add(Var([\"n\"]), App(Var([\"s\",\"u\",\"m\"]), Add(Var([\"n\"]), Con(-1)))))))\n\nval sum0 = App(fix, partialSum0)\n//│ sum0 = App(Lam([\"F\"], App(Lam([\"x\"], App(Var([\"F\"]), App(Var([\"x\"]), Var([\"x\"])))), Lam([\"x\"], App(Var([\"F\"]), App(Var([\"x\"]), Var([\"x\"])))))), Lam([\"s\",\"u\",\"m\"], Lam([\"n\"], IfZero(Var([\"n\"]), Con(0), Add(Var([\"n\"]), App(Var([\"s\",\"u\",\"m\"]), Add(Var([\"n\"]), Con(-1))))))))\n\nfun showTerm(t) = if t is Con(a) then nofibStringToList(\"Con \") +: nofibStringToList(stringOfInt(a))\n\nfun ev(t) =\n  let envt2 = myRunState(traverseTerm(t), Nil)\n  if envt2 is [env, t2] then pp(t2) +: nofibStringToList(\"  \") +: ppenv(env)\n\nfun mainSimple(args) =\n  if null_(args)\n  then throw Error(\"Args: number-to-sum-up-to\")\n  else showTerm(simpleEval(Nil, App(sum0, Con(head(args)))))\n\nfun mainMonad(args) =\n  if null_(args)\n  then throw Error(\"Args: number-to-sum-up-to\")\n  else ev(App(sum0, Con(head(args))))\n\nfun testLambda_nofib(n) = [mainSimple(n :: Nil), mainMonad(n :: Nil)]\n\nfun main() = testLambda_nofib(80).toString()"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/lastpiece.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule lastpiece with ...\n\n\n\nfun isSome(x) = x is Some\n\nfun mapMaybe(f, ls) = if ls is\n  Nil then Nil\n  h :: t and f(h) is\n    None then mapMaybe(f, t)\n    Some(a) then a :: mapMaybe(f, t)\n\nobject\n  GT\n  LT\n  EQ\n\nfun compareIntInt(ab, cd) = if ab is [a, b] and cd is [c, d] and\n  a > c then GT\n  a < c then LT\n  b > d then GT\n  b < d then LT\n  else EQ\n\nabstract class Map[K, A]: Tip | Bin[K, A]\n\nobject Tip extends Map[Anything, Nothing]\n\ndata class Bin[K, A](i: Int, k: K, v: A, l: Map[K, A], r: Map[K, A]) extends Map[K, A]\n\nfun mapLookup(k, m) = if m is\n  Tip then None\n  Bin(_, kx, x, l, r) and compareIntInt(k, kx) is\n    LT then mapLookup(k, l)\n    GT then mapLookup(k, r)\n    EQ then Some(x)\n\nfun size(p) = if p is\n  Tip then 0\n  Bin(sz, _, _, _, _) then sz\n\nfun bin(k, x, l, r) = Bin(size(l) + size(r) + 1, k, x, l, r)\n\nfun singleL(k1, x1, t1, r) = if r is\n  Bin(_, k2, x2, t2, t3) then bin(k2, x2, bin(k1, x1, t1, t2), t3)\n  else throw Error(\"singleL Tip\")\n\nfun singleR(k1, x1, l, t3) = if l is\n  Bin(_, k2, x2, t1, t2) then bin(k2, x2, t1, bin(k1, x1, t2, t3))\n  else throw Error(\"singleR Tip\")\n\nfun doubleL(k1, x1, t1, r) = if r is\n  Bin(_, k2, x2, Bin(_, k3, x3, t2, t3), t4) then bin(k3, x3, bin(k1, x1, t1, t2), bin(k2, x2, t3, t4))\n  else throw Error(\"doubleL Tip\")\n\nfun doubleR(k1, x1, l, t4) = if l is\n  Bin(_, k2, x2, t1, Bin(_, k3, x3, t2, t3)) then bin(k3, x3, bin(k2, x2, t1, t2), bin(k1, x1, t3, t4))\n  else throw Error(\"doubleR Tip\")\n\nfun rotateL(k, x, l, r) = if r is\n  Bin(_, _, _, ly, ry) and\n    size(ly) < 2 * size(ry) then singleL(k, x, l, r)\n    else doubleL(k, x, l, r)\n  else throw Error(\"rotateL Tip\")\n\nfun rotateR(k, x, l, r) = if l is\n  Bin(_, _, _, ly, ry) and\n    size(ry) < 2 * size(ly) then singleR(k, x, l, r)\n    else doubleR(k, x, l, r)\n  else throw Error(\"rotateR Tip\")\n\nfun balance(k, x, l, r) =\n  let sizeL = size(l)\n  let sizeR = size(r)\n  let sizeX = sizeL + sizeR + 1\n  if\n    (sizeL + sizeR) <= 1 then Bin(sizeX, k, x, l, r)\n    sizeR >= (4 * sizeL) then rotateL(k, x, l, r)\n    sizeL >= (4 * sizeR) then rotateR(k, x, l, r)\n    else Bin(sizeX, k, x, l, r)\n\nfun insert(kx, x, m) = if m is\n  Tip then Bin(1, kx, x, Tip, Tip)\n  Bin(sz, ky, y, l, r) and compareIntInt(kx, ky) is\n    LT then balance(ky, y, insert(kx, x, l), r)\n    GT then balance(ky, y, l, insert(kx, x, r))\n    EQ then Bin(sz, kx, x, l, r)\n\nfun indent(n) = if n <= 0 then Nil else \" \" :: indent(n - 1)\n\ndata class P(i: Char, a: List[List[[Int, Int]]], b: List[List[[Int, Int]]])\n\nabstract class S: Male | Female\n\nobject\n  Male extends S\n  Female extends S\n\nfun flip(s) = if s is\n  Male then Female\n  Female then Male\n\nabstract class Solution: Soln | Choose | Fail\n\ntype Board = Map[[Int, Int], Char]\n\ndata\n  class\n    Soln(b: Board) extends Solution\n    Choose(s: List[Solution]) extends Solution\n    Fail(b: Board, s: [Int, Int]) extends Solution\n\nfun addIntInt(row_col, orow_ocol) = if row_col is [row, col] and orow_ocol is [orow, ocol] then\n  [row + orow, col + ocol]\n\nfun next(row_col) =  if row_col is [row, col] then [row, col + 1]\n\nval maxRow = 8\n//│ maxRow = 8\n\nval maxCol = 8\n//│ maxCol = 8\n\nval emptyBoard = Tip\n//│ emptyBoard = Tip\n\nfun check(bd, sq) = mapLookup(sq, bd)\n\nfun extend(bd, sq, id) = insert(sq, id, bd)\n\nfun extend_maybe(bd, sq, id) = if sq is [row, col] and\n  (row > maxRow) || (col < 1) || (col > maxCol) then None\n  check(bd, sq) is\n    Some(_) then None\n    None then Some(extend(bd, sq, id))\n\nfun pickOne(xs) =\n  fun go(f, xs) = if xs is\n    Nil then Nil\n    x :: xs then [x, f(xs)] :: go(p => x :: f(p), xs)\n  go(x => x, xs)\n\nfun fit(bd, sq, id, os) = if os is\n  Nil then Some(extend(bd, sq, id))\n  o :: os and extend_maybe(bd, addIntInt(sq, o), id) is\n    Some(bd1) then fit(bd1, sq, id, os)\n    None then None\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun tryy(sq, se, bd, id_is_ps) = if id_is_ps is [id, os, ps] and fit(bd, sq, id, os) is\n  Some(bd1) then Some(search(next(sq), flip(se), bd1, ps))\n  None then None\n\nfun search(row_col, sey, bd, ps) = if row_col is [row, col] and\n  ps is Nil then Soln(bd)\n  col === (maxCol + 1) then search([row + 1, 1], flip(sey), bd, ps)\n  check(bd, row_col) is Some(_) then search(next(row_col), flip(sey), bd, ps)\n  else\n    fun lscomp1(ls) = if ls is\n      Nil then Nil\n      [P(id, ms, fs), ps] :: ls then\n        fun lscomp2(ls2) = if ls2 is\n          Nil then lscomp1(ls)\n          os :: ls then [id, os, ps] :: lscomp2(ls)\n        lscomp2(if sey is Male then ms else fs)\n    let choices = lscomp1(pickOne(ps))\n    if mapMaybe(x => tryy(row_col, sey, bd, x), choices) is\n      Nil then Fail(bd, row_col)\n      ss then Choose(ss)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nval nPiece = P(\n  \"n\",\n  ([0,1] :: [1,1] :: [2,1] :: [2,2] :: Nil) ::\n  ([1,0] :: [1,-1] :: [1,-2] :: [2,-2] :: Nil) :: Nil,\n  Nil\n)\n//│ nPiece = P(\"n\", [[[0, 1],[1, 1],[2, 1],[2, 2]],[[1, 0],[1, -1],[1, -2],[2, -2]]], [])\n\nval mPiece = P(\n  \"m\",\n  ([0,1] :: [1,0] :: [2,0] :: [3,0] :: Nil) :: Nil,\n  ([0,1] :: [0,2] :: [0,3] :: [1,3] :: Nil) ::\n  ([1,0] :: [2,0] :: [3,0] :: [3,-1] :: Nil) :: Nil\n)\n//│ mPiece = P(\"m\", [[[0, 1],[1, 0],[2, 0],[3, 0]]], [[[0, 1],[0, 2],[0, 3],[1, 3]],[[1, 0],[2, 0],[3, 0],[3, -1]]])\n\nval lPiece = P(\n  \"l\",\n  ([0,1] :: [0,2] :: [0,3] :: [1,2] :: Nil) ::\n  ([1,0] :: [2,0] :: [3,0] :: [2,-1] :: Nil) :: Nil,\n  ([1,-1] :: [1,0] :: [1,1] :: [1,2] :: Nil) ::\n  ([1,0] :: [2,0] :: [3,0] :: [1,1] :: Nil) :: Nil\n)\n//│ lPiece = P(\"l\", [[[0, 1],[0, 2],[0, 3],[1, 2]],[[1, 0],[2, 0],[3, 0],[2, -1]]], [[[1, -1],[1, 0],[1, 1],[1, 2]],[[1, 0],[2, 0],[3, 0],[1, 1]]])\n\nval kPiece = P(\n  \"k\",\n  ([0,1] :: [1,0] :: [2,0] :: [2,-1] :: Nil) :: Nil,\n  ([1,0] :: [1,1] :: [1,2] :: [2,2] :: Nil) :: Nil\n)\n//│ kPiece = P(\"k\", [[[0, 1],[1, 0],[2, 0],[2, -1]]], [[[1, 0],[1, 1],[1, 2],[2, 2]]])\n\nval jPiece = P(\n  \"j\",\n  ([0,1] :: [0,2] :: [0,3] :: [1,1] :: Nil) ::\n  ([1,0] :: [2,0] :: [3,0] :: [1,-1] :: Nil) ::\n  ([1,-2] :: [1,-1] :: [1,0] :: [1,1] :: Nil) :: Nil,\n  ([1,0] :: [2,0] :: [3,0] :: [2,2] :: Nil) :: Nil\n)\n//│ jPiece = P(\"j\", [[[0, 1],[0, 2],[0, 3],[1, 1]],[[1, 0],[2, 0],[3, 0],[1, -1]],[[1, -2],[1, -1],[1, 0],[1, 1]]], [[[1, 0],[2, 0],[3, 0],[2, 2]]])\n\nval iPiece = P(\n  \"i\",\n  ([1,0] :: [2,0] :: [2,1] :: [3,1] :: Nil) ::\n  ([0,1] :: [0,2] :: [1,0] :: [1,-1] :: Nil) ::\n  ([1,0] :: [1,1] :: [2,1] :: [3,1] :: Nil) :: Nil,\n  ([0,1] :: [1,0] :: [1,-1] :: [1,-2] :: Nil) :: Nil\n)\n//│ iPiece = P(\"i\", [[[1, 0],[2, 0],[2, 1],[3, 1]],[[0, 1],[0, 2],[1, 0],[1, -1]],[[1, 0],[1, 1],[2, 1],[3, 1]]], [[[0, 1],[1, 0],[1, -1],[1, -2]]])\n\nval hPiece = P(\n  \"h\",\n  ([0,1] :: [1,1] :: [1,2] :: [2,2] :: Nil) ::\n  ([1,0] :: [1,-1] :: [2,-1] :: [2,-2] :: Nil) ::\n  ([1,0] :: [1,1] :: [2,1] :: [2,2] :: Nil) :: Nil,\n  ([0,1] :: [1,0] :: [1,-1] :: [2,-1] :: Nil) :: Nil\n)\n//│ hPiece = P(\"h\", [[[0, 1],[1, 1],[1, 2],[2, 2]],[[1, 0],[1, -1],[2, -1],[2, -2]],[[1, 0],[1, 1],[2, 1],[2, 2]]], [[[0, 1],[1, 0],[1, -1],[2, -1]]])\n\nval gPiece = P(\n  \"g\",\n  Nil,\n  ([0,1] :: [1,1] :: [1,2] :: [1,3] :: Nil) ::\n  ([1,0] :: [1,-1] :: [2,-1] :: [3,-1] :: Nil) ::\n  ([0,1] :: [0,2] :: [1,2] :: [1,3] :: Nil) ::\n  ([1,0] :: [2,0] :: [2,-1] :: [3,-1] :: Nil) :: Nil\n)\n//│ gPiece = P(\"g\", [], [[[0, 1],[1, 1],[1, 2],[1, 3]],[[1, 0],[1, -1],[2, -1],[3, -1]],[[0, 1],[0, 2],[1, 2],[1, 3]],[[1, 0],[2, 0],[2, -1],[3, -1]]])\n\nval fPiece = P(\n  \"f\",\n  ([0,1] :: [1,1] :: [2,1] :: [3,1] :: Nil) ::\n  ([1,0] :: [1,-1] :: [1,-2] :: [1,-3] :: Nil) ::\n  ([1,0] :: [2,0] :: [3,0] :: [3,1] :: Nil) :: Nil,\n  ([0,1] :: [0,2] :: [0,3] :: [1,0] :: Nil) :: Nil\n)\n//│ fPiece = P(\"f\", [[[0, 1],[1, 1],[2, 1],[3, 1]],[[1, 0],[1, -1],[1, -2],[1, -3]],[[1, 0],[2, 0],[3, 0],[3, 1]]], [[[0, 1],[0, 2],[0, 3],[1, 0]]])\n\nval ePiece = P(\n  \"e\",\n  ([0,1] :: [1,1] :: [1,2] :: Nil) ::\n  ([1,0] :: [1,-1] :: [2,-1] :: Nil) :: Nil,\n  ([0,1] :: [1,1] :: [1,2] :: Nil) ::\n  ([1,0] :: [1,-1] :: [2,-1] :: Nil) :: Nil\n)\n//│ ePiece = P(\"e\", [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]], [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]])\n\nval dPiece = P(\n  \"d\",\n  ([0,1] :: [1,1] :: [2,1] :: Nil) ::\n  ([1,0] :: [1,-1] :: [1,-2] :: Nil) :: Nil,\n  ([1,0] :: [2,0] :: [2,1] :: Nil) :: Nil\n)\n//│ dPiece = P(\"d\", [[[0, 1],[1, 1],[2, 1]],[[1, 0],[1, -1],[1, -2]]], [[[1, 0],[2, 0],[2, 1]]])\n\nval cPiece = P(\n  \"c\",\n  Nil,\n  ([0,1] :: [0,2] :: [1,1] :: Nil) ::\n  ([1,0] :: [1,-1] :: [2,0] :: Nil) ::\n  ([1,-1] :: [1,0] :: [1,1] :: Nil) ::\n  ([1,0] :: [1,1] :: [2,0] :: Nil) :: Nil\n)\n//│ cPiece = P(\"c\", [], [[[0, 1],[0, 2],[1, 1]],[[1, 0],[1, -1],[2, 0]],[[1, -1],[1, 0],[1, 1]],[[1, 0],[1, 1],[2, 0]]])\n\nval bPiece = P(\n  \"b\",\n  ([0,1] :: [0,2] :: [1,2] :: Nil) ::\n  ([1,0] :: [2,0] :: [2,-1] :: Nil) ::\n  ([0,1] :: [1,0] :: [2,0] :: Nil) :: Nil,\n  ([1,0] :: [1,1] :: [1,2] :: Nil) :: Nil\n)\n//│ bPiece = P(\"b\", [[[0, 1],[0, 2],[1, 2]],[[1, 0],[2, 0],[2, -1]],[[0, 1],[1, 0],[2, 0]]], [[[1, 0],[1, 1],[1, 2]]])\n\nval initialPieces = bPiece :: cPiece :: dPiece :: ePiece :: fPiece ::\n  gPiece :: hPiece :: iPiece :: jPiece :: kPiece :: lPiece ::\n  mPiece :: nPiece :: Nil\n//│ initialPieces = [P(\"b\", [[[0, 1],[0, 2],[1, 2]],[[1, 0],[2, 0],[2, -1]],[[0, 1],[1, 0],[2, 0]]], [[[1, 0],[1, 1],[1, 2]]]),P(\"c\", [], [[[0, 1],[0, 2],[1, 1]],[[1, 0],[1, -1],[2, 0]],[[1, -1],[1, 0],[1, 1]],[[1, 0],[1, 1],[2, 0]]]),P(\"d\", [[[0, 1],[1, 1],[2, 1]],[[1, 0],[1, -1],[1, -2]]], [[[1, 0],[2, 0],[2, 1]]]),P(\"e\", [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]], [[[0, 1],[1, 1],[1, 2]],[[1, 0],[1, -1],[2, -1]]]),P(\"f\", [[[0, 1],[1, 1],[2, 1],[3, 1]],[[1, 0],[1, -1],[1, -2],[1, -3]],[[1, 0],[2, 0],[3, 0],[3, 1]]], [[[0, 1],[0, 2],[0, 3],[1, 0]]]),P(\"g\", [], [[[0, 1],[1, 1],[1, 2],[1, 3]],[[1, 0],[1, -1],[2, -1],[3, -1]],[[0, 1],[0, 2],[1, 2],[1, 3]],[[1, 0],[2, 0],[2, -1],[3, -1]]]),P(\"h\", [[[0, 1],[1, 1],[1, 2],[2, 2]],[[1, 0],[1, -1],[2, -1],[2, -2]],[[1, 0],[1, 1],[2, 1],[2, 2]]], [[[0, 1],[1, 0],[1, -1],[2, -1]]]),P(\"i\", [[[1, 0],[2, 0],[2, 1],[3, 1]],[[0, 1],[0, 2],[1, 0],[1, -1]],[[1, 0],[1, 1],[2, 1],[3, 1]]], [[[0, 1],[1, 0],[1, -1],[1, -2]]]),P(\"j\", [[[0, 1],[0, 2],[0, 3],[1, 1]],[[1, 0],[2, 0],[3, 0],[1, -1]],[[1, -2],[1, -1],[1, 0],[1, 1]]], [[[1, 0],[2, 0],[3, 0],[2, 2]]]),P(\"k\", [[[0, 1],[1, 0],[2, 0],[2, -1]]], [[[1, 0],[1, 1],[1, 2],[2, 2]]]),P(\"l\", [[[0, 1],[0, 2],[0, 3],[1, 2]],[[1, 0],[2, 0],[3, 0],[2, -1]]], [[[1, -1],[1, 0],[1, 1],[1, 2]],[[1, 0],[2, 0],[3, 0],[1, 1]]]),P(\"m\", [[[0, 1],[1, 0],[2, 0],[3, 0]]], [[[0, 1],[0, 2],[0, 3],[1, 3]],[[1, 0],[2, 0],[3, 0],[3, -1]]]),P(\"n\", [[[0, 1],[1, 1],[2, 1],[2, 2]],[[1, 0],[1, -1],[1, -2],[2, -2]]], [])]\n\nabstract class Mode: PageMode | ZigZagMode | LeftMode | OneLineMode\n\nobject\n  PageMode extends Mode\n  ZigZagMode extends Mode\n  LeftMode extends Mode\n  OneLineMode extends Mode\n\nabstract class TextDetails: Chr | Str | PStr\n\ndata\n  class\n    Chr(c: Char) extends TextDetails\n    Str(s: String) extends TextDetails\n    PStr(s: String) extends TextDetails\n\nabstract class AnnotDetails: AnnotStart | NoAnnot | AnnotEnd\n\nobject\n  AnnotStart extends AnnotDetails\n  AnnotEnd extends AnnotDetails\n\ndata class NoAnnot(t: TextDetails, i: Int) extends AnnotDetails\n\nabstract class IsEmptyy: IsEmpty | NotEmpty\n\nobject\n  IsEmpty extends IsEmptyy\n  NotEmpty extends IsEmptyy\n\nabstract class Doc: Empty | NilAbove | TextBeside | Nest | Union | NoDoc | Beside | Above\n\nobject\n  Empty extends Doc\n  NoDoc extends Doc\n\ndata\n  class\n    NilAbove(d: Doc) extends Doc\n    TextBeside(a: AnnotDetails, d: Doc) extends Doc\n    Nest(i: Int, d: Doc) extends Doc\n    Union(d1: Doc, d2: Doc) extends Doc\n    Beside(d1: Doc, b: Bool, d2: Doc) extends Doc\n    Above(d1: Doc, b: Bool, d2: Doc) extends Doc\n\nval spaceText = NoAnnot(Chr(\" \"), 1)\n//│ spaceText = NoAnnot(Chr(\" \"), 1)\n\nval nlText = NoAnnot(Chr(\"\\n\"), 1)\n//│ nlText = NoAnnot(Chr(\"\\n\"), 1)\n\nfun annotSize(p) = if p is\n  NoAnnot(_, l) then l\n  _ then 0\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun display(s) = if s is\n  Soln(bd) then vcat(text(nofibStringToList(\"Success!\")) :: nest(2, displayBoard(bd)) :: Nil)\n  Choose(ss) then vcat(map(display, ss))\n  Fail(bd, [row, col]) then Empty\n\nfun displayBoard(bd) =\n  fun sq(n, col) = if check(bd, [n, col]) is\n    Some(id) then char(id)\n    None then char(\".\")\n  fun row(n) = hcat(map(col => sq(n, col), enumFromTo(1, maxCol)))\n  above_(vcat(map(row, enumFromTo(1, maxCol))), false, text(Nil))\n\nfun eliminateEmpty(cons, p, g, q) = if p is\n  Empty then q\n  else [\n    NotEmpty,\n    if q is\n      [NotEmpty, q1] then cons(p, g, q1)\n      [IsEmpty, _] then p\n  ]\n\nfun reduceVert(doc) = if doc is\n  Above(p, g, q) then eliminateEmpty((a, b, c) => Above(a, b, c), snd(reduceVert(p)), g, reduceVert(q))\n  else [NotEmpty, doc]\n\nfun vcat(ls) = snd(reduceVert(foldr((p, q) => Above(p, false, q), Empty, ls)))\n\nfun text(s) =\n  let sl = listLen(s)\n  TextBeside(NoAnnot(Str(s), sl), Empty)\n\nfun char(c) = TextBeside(NoAnnot(Chr(c), 1), Empty)\n\nfun reduceHoriz(doc) = if doc is\n  Beside(p, g, q) then eliminateEmpty((a, b, c) => Beside(a, b, c), snd(reduceHoriz(p)), g, reduceHoriz(q))\n  else [NotEmpty, doc]\n\nfun hcat(ls) = snd of reduceHoriz of foldr of\n  (p, q) => Beside(p, false, q)\n  Empty\n  ls\n\nfun above_(p, g, q) = if\n  q is Empty then p\n  g is Empty then q\n  else Above(p, g, q)\n\nfun nest(k, p) = mkNest(k, reduceDoc(p))\n\nfun mkNest(k, p) = if\n  p is Nest(k1, p1) then mkNest(k + k1, p1)\n  p is NoDoc then NoDoc\n  p is Empty then Empty\n  k === 0 then p\n  else Nest(k, p)\n\nfun reduceDoc(p) = if p is\n  Beside(p1, g, q) then beside(p1, g, reduceDoc(q))\n  Above(p1, g, q) then above(p1, g, reduceDoc(q))\n  else p\n\n\nfun beside(p, g, q) = if p is\n  NoDoc then NoDoc\n  Union(p1, p2) then Union(beside(p1, g, q), beside(p2, g, q))\n  Empty then q\n  Nest(k, p1) then Nest(k, beside(p1, g, q))\n  Beside(p1, g1, q1) and\n    g1 === g then beside(p1, g1, beside(q1, g, q))\n    else beside(reduceDoc(Beside(p1, g1, q1)), g, q)\n  Above(_, _, _) then beside(reduceDoc(p), g, q)\n  NilAbove(p1) then NilAbove(beside(p1, g, q))\n  TextBeside(t, p1) then\n    let rest = if p1 is Empty then nilBeside(g, q) else beside(p1, g, q)\n    TextBeside(t, rest)\n\nfun above(p, g, q) = if p is\n  Above(p1, g1, q1) then above(p1, g1, above(q1, g, q))\n  Beside(_, _, _) then aboveNest(reduceDoc(p), g, 0, reduceDoc(q))\n  else aboveNest(p, g, 0, reduceDoc(q))\n\nfun nilBeside(g, p) = if\n  p is Empty then Empty\n  p is Nest(_, p1) then nilBeside(g, p1)\n  g then TextBeside(spaceText, p)\n  else p\n\nfun aboveNest(p, g, k, q) = if p is\n  NoDoc then NoDoc\n  Union(p1, p2) then Union(aboveNest(p1, g, k, q), aboveNest(p2, g, k, q))\n  Empty then mkNest(k, q)\n  Nest(k1, p1) then Nest(k1, aboveNest(p1, g, k - k1, q))\n  NilAbove(p1) then NilAbove(aboveNest(p1, g, k, q))\n  TextBeside(s, p1) then\n    let k1 = k - annotSize(s)\n    let rest = if p1 is Empty then nilAboveNest(g, k1, q) else aboveNest(p1, g, k1, q)\n    TextBeside(s, rest)\n  Above(_, _, _) then throw Error(\"aboveNest Above\")\n  Beside(_, _, _) then throw Error(\"aboveNest Beside\")\n\nfun nilAboveNest(g, k, q) = if\n  q is Empty then Empty\n  q is Nest(k1, q1) then nilAboveNest(g, k + k1, q1)\n  not(g) and (k > 0) then TextBeside(NoAnnot(Str(indent(k)), k), q)\n  else NilAbove(mkNest(k, q))\n  \nfun printDoc(d) =\n  fun put(k, next) = if k is\n    Chr(c) then c :: next\n    Str(s) then s +: next\n    PStr(s) then s +: next\n  let done = \"\\n\" :: Nil\n  fullRender(ZigZagMode, 200, 1.5, put, done, d)\n\nfun fullRender(m, l, r, txt, a, b) =\n  fun annTxt(p, x) = if p is\n    NoAnnot(s, _) then txt(s, x)\n    _ then x\n  fullRenderAnn(m, l, r, annTxt, a, b)\n\nfun ceiling(x) = globalThis.Math.ceil(x)\n\nfun fullRenderAnn(m, lineLen, ribbons, txt, rest, doc) = if m is\n  OneLineMode then easyDisplay(spaceText, (a, b) => b, txt, rest, reduceDoc(doc))\n  LeftMode then easyDisplay(nlText, first, txt, rest, reduceDoc(doc))\n  else\n    let ribbonLen = ceiling(lineLen / ribbons)\n    let bestLineLen = if m is ZigZagMode then 2147483647 else lineLen\n    let doc1 = best(bestLineLen, ribbonLen, reduceDoc(doc))\n    displayDoc(m, lineLen, ribbonLen, txt, rest, doc1)\n\nfun easyDisplay(nlSpaceText, choose, txt, end, x) =\n  fun lay(x) = if x is\n    NoDoc then throw Error(\"easyDisplay: NoDoc\")\n    Union(p, q) then lay(choose(p, q))\n    Nest(_, p) then lay(p)\n    Empty then end\n    NilAbove(p) then txt(nlSpaceText, lay(p))\n    TextBeside(s, p) then txt(s, lay(p))\n    Above(_, _, _) then throw Error(\"easyDisplay Above\")\n    Beside(_, _, _) then throw Error(\"easyDisplay Beside\")\n  lay(x)\n\nfun displayDoc(m, pageWidth, ribbonWidth, txt, end, doc) =\n  let gapWidth = pageWidth - ribbonWidth\n  let shift = intDiv(gapWidth, 2)\n  fun lay(k, docc) =\n    fun lay2(k, param) = if param is\n      NilAbove(p) then txt(nlText, lay(k, p))\n      TextBeside(s, p) then txt(s, lay2(k + annotSize(s), p))\n      Nest(_, p) then lay2(k, p)\n      Empty then end\n    fun lay1(k, s, p) =\n      let r = k + annotSize(s)\n      txt(NoAnnot(Str(indent(k)), k), txt(s, lay2(r, p)))\n    if docc is\n      Nest(k1, p) then lay(k + k1, p)\n      Empty then end\n      NilAbove(p) then txt(nlText, lay(k, p))\n      TextBeside(s, p) and m is\n        ZigZagMode and k\n          >= gapWidth then txt(nlText, txt(NoAnnot(Str(replicate(shift, \"/\")), shift), txt(nlText, lay1(k - shift, s, p))))\n          < 0 then txt(nlText, txt(NoAnnot(Str(replicate(shift, \"|\")), shift), txt(nlText, lay1(k + shift, s, p))))\n          else lay1(k, s, p)\n        else lay1(k, s, p)\n  lay(0, doc)\n\nfun best(w0, r, doc) =\n  fun get(r, w, docc) = if docc is\n    Empty then Empty\n    NoDoc then NoDoc\n    NilAbove(p) then NilAbove(get(r, w, p))\n    TextBeside(s, p) then TextBeside(s, get1(r, w, annotSize(s), p))\n    Nest(k, p) then Nest(k, get(r, w - k, p))\n    Union(p, q) then nicest(w, r, get(r, w, p), get(r, w, q))\n    Above(_, _, _) then throw Error(\"best get Above\")\n    Beside(_, _, _) then throw Error(\"best get Beside\")\n  fun get1(r, w, sl, p) = if p is\n    Empty then Empty\n    NoDoc then NoDoc\n    NilAbove(p) then NilAbove(get(r, w - sl, p))\n    TextBeside(s, p) then TextBeside(s, get1(r, w, sl + annotSize(s), p))\n    Nest(_, p) then get1(r, w, sl, p)\n    Union(p, q) then nicest1(w, r, sl, get1(r, w, sl, p), get1(r, w, sl, q))\n    Above(_, _, _) then throw Error(\"best get1 Above\")\n    Beside(_, _, _) then throw Error(\"best get1 Beside\")\n  get(r, w0, doc)\n\nfun nonEmptySet(doc) = if doc is\n  NoDoc then false\n  Union(_, _) then true\n  Empty then true\n  NilAbove(_) then true\n  TextBeside(_, p) then nonEmptySet(p)\n  Nest(_, p) then nonEmptySet(p)\n  Above(_, _, _) then throw Error(\"nonEmptySet Above\")\n  Beside(_, _, _) then throw Error(\"nonEmptySet Beside\")\n\nfun fits(n, param) = if\n  n < 0 then false\n  param is\n    NoDoc then false\n    Empty then true\n    NilAbove(_) then true\n    TextBeside(s, p) then fits(n - annotSize(s), p)\n    Above(_, _, _) then throw Error(\"fits Above\")\n    Beside(_, _, _) then throw Error(\"fits Beside\")\n    Union(_, _) then throw Error(\"fits Union\")\n    Nest(_, _) then throw Error(\"fits Nest\")\n\nfun first(p, q) = if nonEmptySet(p) then p else q\n\nfun nicest1(w, r, sl, p, q) = if fits(min(w, r) - sl, p) then p else q\n\nfun nicest(w, r, p, q) = nicest1(w, r, 0, p, q)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\nfun testLastPiece_nofib() =\n  let initialBoard = fromSome(fit(emptyBoard, [1, 1], \"a\", [1, 0] :: [1, 1] :: Nil))\n  let solutions = search([1,2], Female, initialBoard, initialPieces)\n  printDoc(display(solutions))\n\nfun main() = nofibListToString(testLastPiece_nofib())\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/lcss.mls",
    "content": "import \"./NofibPrelude.mls\"\nopen NofibPrelude\n\n\n\n\n\nmodule lcss with ...\n\n\n\nfun algb2(x, k0j1, k1j1, yss) = if yss is\n  Nil then Nil\n  [y, k0j] :: ys then\n    let kjcurr = if x == y then k0j1 + 1 else max(k1j1, k0j)\n    [y, kjcurr] :: algb2(x, k0j, kjcurr, ys)\n\nfun algb1(xss, yss) = if xss is\n  Nil then map(snd, yss)\n  x :: xs then algb1(xs, algb2(x, 0, 0, yss))\n\nfun algb(xs, ys) =\n  fun listcomp_fun(listcomp_fun_para) = if listcomp_fun_para is\n      listcomp_fun_ls_h :: listcomp_fun_ls_t then [listcomp_fun_ls_h, 0] :: listcomp_fun(listcomp_fun_ls_t)\n      Nil then Nil\n\n  0 :: algb1(xs, listcomp_fun(ys))\n\n\nfun findk(k, km, m, ls) = if ls is\n  Nil then km\n  [x,y] :: xys then if (x + y) >= m then findk(k+1, k, x+y, xys) else findk(k+1, km, m, xys)\n\nfun algc(m, n, xs, ys) = if\n  ys is Nil then x => x\n  xs is\n    x :: Nil and\n      inList(x, ys) then t => x :: t\n      else x => x\n  else\n    let m2 = intDiv(m, 2)\n    let xs1 = take(m2, xs)\n    let xs2 = leave(m2, xs)\n    let l1 = algb(xs1, ys)\n    let l2 = reverse(algb(reverse(xs2), reverse(ys)))\n    let k = findk(0, 0, -1, zip(l1, l2))\n    compose(algc(m2, k, xs1, take(k, ys)), (algc(m-m2, n-k, xs2, leave(k, ys))))\n\nfun lcss(xs, ys) = algc(listLen(xs), listLen(ys), xs, ys)(Nil)\n\nfun lcssMain(a, b ,c, d, e, f) = lcss(enumFromThenTo(a,b,c), enumFromThenTo(d,e,f))\n\nfun testLCSS_nofib(d) = lcssMain(1,2,60,30,31,90)\n\n\n\nfun main() = testLCSS_nofib(0).toString()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/life.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule life with ...\n\n\nfun last(a_t) =\n  fun go(h, t) = if t is\n    Nil then h\n    head :: t then go(head, t)\n  if a_t is a :: t then go(a, t)\n\nfun copy_lz(n, x) = lazy of () =>\n  if n === 0 then LzNil else LzCons(x, copy_lz(n - 1, x))\n\nfun append_lz_lz(xs, ys) = lazy of () =>\n  if force(xs) is\n    LzNil then force(ys)\n    LzCons(h, t) then LzCons(h, append_lz_lz(t, ys))\n\nfun init(ls) = if ls is\n  a :: Nil then Nil\n  a :: t then a :: init(t)\n  else throw Error(ls)\n\nfun zipWith3(f, xs, ys, zs) = if\n  xs is hx :: tx and ys is hy :: ty and zs is hz :: tz then f(hx, hy, hz) :: zipWith3(f, tx, ty, tz)\n  else Nil\n\nfun zip3(xs, ys, zs) = if\n  xs is hx :: tx and ys is hy :: ty and zs is hz :: tz then [hx, hy, hz] :: zip3(tx, ty, tz)\n  else Nil\n\nfun lzfy(ls) = lazy of () =>\n  if ls is\n    a :: t then LzCons(a, lzfy(t))\n    else LzNil\n\nval start =\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  (lazy of () => LzNil) ::\n  lzfy(0 :: 0 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: 1 :: 1 :: 1 :: 1 :: 1 :: 0 :: Nil) :: Nil\n//│ start = [Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function]),Lazy([function])]\n\nfun elt(a_b_c, d_e_f, g_h_i) = if a_b_c is [a, b, c] and d_e_f is [d, e, f] and g_h_i is [g, h, i] then\n  let tot = a + b + c + d + f + g + h + i\n  if\n    tot < 2 || tot > 3 then 0\n    tot === 3 then 1\n    else e\n\nfun shiftr(x, xs) = x :: init(xs)\n\nfun shiftl(x, xs) = init(xs) +: (x :: Nil)\n\nfun shift(x, xs) = zip3(shiftr(x, xs), xs, shiftl(x, xs))\n\nfun row(last_this_next) = if last_this_next is [last, this_, next] then\n  zipWith3(elt, shift(0, last), shift(0, this_), shift(0, next))\n\nfun gen(n, board) = map(row, shift(replicate(n, 0), board))\n\nfun star(x) = if x ===\n  0 then nofibStringToList(\"  \")\n  1 then nofibStringToList(\" o\")\n\nfun glue(s, xs, ys) = xs +: s +: ys\n\nfun limit(ls) = if force(ls) is\n  LzCons(x, ys) and force(ys) is LzCons(y, xs) and\n    listEqBy(listEq, x, y) then x :: Nil\n    else x :: limit(lazy of () => LzCons(y, xs))\n\nfun disp(gen_xss) = if gen_xss is [genn, xss] then lazy of () =>\n    genn +:\n    nofibStringToList(\"nn\") +:\n    foldr((a, b) => glue(\"n\" :: Nil, a, b), Nil, map(x => concat(map(star, x)), xss))\n\nfun generations(sz) =\n  map of\n    disp\n    zip_lz_nl of\n      map_lz(i => nofibStringToList(stringOfInt(i)), enumFrom(0)),\n      limit of iterate of\n        b => gen(sz, b)\n        take_lz of\n          sz\n          map_lz of\n            l => take_lz(sz, append_lz_lz(l, copy_lz(sz, 0))),\n            append_nl_lz(start, copy_lz(sz, copy_lz(sz, 0)))\n\nfun testLife_nofib(n) = listLen(force(last(generations(n))))\n\nfun main() = testLife_nofib(15)\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/mandel.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule mandel with ...\n\n\n\ndata class Pixmap(a: Int, b: Int, c: Int, d:List[[Int, Int, Int]])\n\nfun createPixmap(width, height, max, colours) = Pixmap(width, height, max, colours)\n\ndata class Complex(r: Num, i: Num)\n\nfun comp_magnitude(c) = if c is Complex(a, b) then sqrt(a * a + b * b)\n\nfun comp_times(x, y) = if\n  x is Complex(a, b) and y is Complex(c, d) then Complex((a * c) - (b * d), (a * d) + (b * c))\n\nfun comp_plus(x, y) = if\n  x is Complex(a, b) and y is Complex(c, d) then Complex(a + c, b + d)\n\nfun mandel(c) =\n  fun infiniteMandel() = lazy of () =>\n    LzCons(c, map_lz((z => comp_plus(comp_times(z, z), c)), infiniteMandel()))\n  infiniteMandel()\n\nfun diverge(cmplx, radius) =\n  comp_magnitude(cmplx) > radius\n\nfun whenDiverge(limit, radius, c) =\n  fun walkIt(ls) = if force(ls) is\n    LzNil then 0\n    LzCons(x, xs) and\n      diverge(x, radius) then 0\n      else 1 + walkIt(xs)\n\n  walkIt(take_lz_lz(limit, mandel(c)))\n\nfun parallelMandel(mat, limit, radius) = map(c => whenDiverge(limit, radius, c), mat)\n\nfun mandelset(x, y, x_, y_, screenX, screenY, lIMIT) =\n  fun prettyRGB(s) =\n    let t = lIMIT - s\n    [s, t, t]\n\n  fun windowToViewport(s, t) =\n    Complex(x + ((s * (x_ - x)) / screenX), y + ((t * (y_ - y)) / screenY))\n\n  fun lscomp1(ls1) = if ls1 is\n    Nil then Nil\n    t :: t1 then\n      fun lscomp2(ls2) = if ls2 is\n        Nil then lscomp1(t1)\n        s :: t2 then windowToViewport(s, t) :: lscomp2(t2)\n      lscomp2(enumFromTo(1, screenX))\n\n  let result = parallelMandel(lscomp1(enumFromTo(1, screenY)), lIMIT, max(x_ - x, y_ - y) / 2)\n\n  createPixmap(screenX, screenY, lIMIT, map(prettyRGB, result))\n\n\nfun testMandel_nofib(dummy) =\n  let minx = -2.0\n  let miny = -2.0\n  let maxx = 2.0\n  let maxy = 2.0\n  let screenX = 25\n  let screenY = 25\n  let limit = 75\n  mandelset(minx, miny, maxx, maxy, screenX, screenY, limit)\n\n\n\nfun main() = testMandel_nofib(0)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/mandel2.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\n\nmodule mandel2 with ...\n\n\n\nabstract class MandTree: NS | EW | Leaf\n\ndata\n  class\n    NS(l: MandTree, r: MandTree) extends MandTree\n    EW(l: MandTree, r: MandTree) extends MandTree\n    Leaf(colour: Int) extends MandTree\n\nval size = 200\nval pmn = -2.25\nval pmx = 0.75\nval qmn = -1.5\nval qmx = 1.5\nval m =  20\nval num_cols = 26\nval delta_p =  (pmx - pmn) / (size - 1)\nval delta_q =  (qmx - qmn) / (size - 1)\nval up    = [ 0,-1]\nval down  = [ 0, 1]\nval left  = [-1, 0]\nval right = [ 1, 0]\n//│ delta_p = 0.01507537688442211\n//│ delta_q = 0.01507537688442211\n//│ down = [0, 1]\n//│ left = [-1, 0]\n//│ m = 20\n//│ num_cols = 26\n//│ pmn = -2.25\n//│ pmx = 0.75\n//│ qmn = -1.5\n//│ qmx = 1.5\n//│ right = [1, 0]\n//│ size = 200\n//│ up = [0, -1]\n\nfun equalp(p1, p2) = if p1 is [x1, x2] and p2 is [y1, y2] then (x1 == y1) and (x2 == y2)\n\nfun np(x) = pmn + (x * delta_p)\n\nfun nq(y) = qmn + (y * delta_q)\n\nfun radius(x, y) = (x * x) + (y * y)\n\nfun new_x(x, y, p) = (x * x) - (y * y) + p\n\nfun new_y(x, y, q) = (2.0 * x * y) + q\n\nfun finite(t) = if t is\n  Leaf(c) then c == c\n  NS(t1, t2) then finite(t1) and finite(t2)\n  EW(t1, t2) then finite(t1) and finite(t2)\n\nfun check_radius(p, q, k, x, y) = \n  let xn = new_x(x, y, p)\n  let yn = new_y(x, y, q)\n  let r = radius(xn, yn)\n  let kp = k + 1\n  if\n    kp == num_cols then 0\n    r > m then kp\n    else check_radius(p, q, kp, xn, yn)\n\nfun point_colour(xy) = if xy is [x, y] then check_radius(np(x), nq(y), 0, 0.0, 0.0)\n\nfun check_perim(x1y1, x2y2) =\n  let col1         = point_colour(x1y1)\n  if x1y1 is [x1, y1] and x2y2 is [x2, y2] then\n\n    fun check_line(xcyc, xdyd) =\n      if xcyc is [xc, yc] and xdyd is [xd, yd] and\n        let finished = if\n          equalp(xdyd, right) then xc >= x2\n          equalp(xdyd, down) then yc <= y2\n          equalp(xdyd, left) then xc <= x1\n          else yc >= y1\n        finished then true\n        not(point_colour(xcyc) == col1) then false\n        else check_line([xc + xd, yc + yd], [xd, yd])\n\n    if\n      equalp(x1y1, x2y2) then col1\n      let col2         = point_colour([x2, y1])\n      let col3         = point_colour(x2y2)\n      let col4         = point_colour([x1, y2])\n      let corners_diff = if (col1 == col2) and (col1 == col3) and (col1 == col4) then false else true\n      corners_diff then -1\n      check_line([x1+1,y1], right) and check_line([x2,y1+1], down) and check_line([x2-1,y2], left) and check_line([x1,y2-1], up) then col1\n      else -1\n\n\nfun build_tree(x1y1, x2y2) =\n  if x1y1 is [x1, y1] and x2y2 is [x2, y2] then\n    let rec_col = check_perim(x1y1, x2y2)\n    if\n      not(rec_col == -1) then Leaf(rec_col)\n      let split   = if (x2-x1) >= (y2-y1) then \"NS\" else \"EW\"\n      let split_x = intDiv((x2+x1), 2)\n      let split_y = intDiv((y2+y1), 2)\n      let nsp1    = x1y1\n      let nsp2    = [split_x, y2]\n      let nsp3    = [split_x+1, y1]\n      let nsp4    = x2y2\n      let ewp1    = x1y1\n      let ewp2    = [x2, split_y]\n      let ewp3    = [x1, split_y+1]\n      let ewp4    = x2y2\n      split == \"NS\" then NS(build_tree(nsp1, nsp2), build_tree(nsp3, nsp4))\n      else EW(build_tree(ewp1, ewp2), build_tree(ewp3, ewp4))\n\nfun testMandel2_nofib(n) =\n  finite(build_tree([0,0], [size, intDiv(size, 2)]))\n\n\n\nfun main() = testMandel2_nofib(0)\n\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/mate.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule mate with ...\n\n\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun rqpart(le, x, ys, rle, rgt, r) = if ys is\n  Nil then qsort(le, rle, x :: qsort(le, rgt, r))\n  y :: ys and\n    le(y, x) then rqpart(le, x, ys, y :: rle, rgt, r)\n    else rqpart(le, x, ys, rle, y :: rgt, r)\n\nfun rqsort(le, xs, r) = if xs is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then rqpart(le, x, xs, Nil, Nil, r)\n\nfun qpart(le, x, ys, rlt, rge, r) = if ys is\n  Nil then rqsort(le, rlt, x :: rqsort(le, rge, r))\n  y :: ys and\n    le(x, y) then qpart(le, x, ys, rlt, y :: rge, r)\n    else qpart(le, x, ys, y :: rlt, rge, r)\n\nfun qsort(le, xs, r) = if xs is\n  Nil then r\n  x :: Nil then x :: r\n  x :: xs then qpart(le, x, xs, Nil, Nil, r)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun sort(l) = qsort of\n  (a, b) => if a is [aa, _] and b is [bb, _] then listLen(aa) <= listLen(bb)\n  l\n  Nil\n\nabstract class Kind: King | Queen | Rook | Bishop | Knight | Pawn\n\nobject\n  King extends Kind\n  Queen extends Kind\n  Rook extends Kind\n  Bishop extends Kind\n  Knight extends Kind\n  Pawn extends Kind\n\nabstract class Colour: Black | White\n\nobject\n  Black extends Colour\n  White extends Colour\n\ntype Piece = [Colour,Kind]\n\ntype Square = [Int,Int]\n\ndata class Board(a: List[[Kind, Square]], b: List[[Kind, Square]])\n\ndata class Move(a: Square, b: Option[Piece], c: Option[Piece])\n\ndata class MoveInFull(a: Piece, b: Square, c: Move)\n\ndata class Solution(a: MoveInFull, b: List[[List[MoveInFull],Solution]])\n\nfun kindOrder(k) = if k is\n  King then 1\n  Queen then 2\n  Rook then 3\n  Bishop then 4\n  Knight then 5\n  Pawn then 6\nfun colourOrder(c) = if c is Black then 1 else 2\nfun pieceCompare(p1, p2) = if p1 is [c1, k1] and p2 is [c2, k2] then\n  let co = colourOrder(c1) - colourOrder(c2)\n  if co === 0 then kindOrder(k1) - kindOrder(k2) else co\nfun squareCompare(s1, s2) = if s1 is [f1, r1] and s2 is [f2, r2] then\n  let ro = r1 - r2\n  if ro === 0 then f1 - f2 else ro\nfun optPieceCompare(op1, op2) = if\n  op1 is None and op2 is None then 0\n  op1 is None and op2 is Some(_) then -1\n  op1 is Some(_) and op2 is None then 1\n  op1 is Some(p1) and op2 is Some(p2) then pieceCompare(p1, p2)\nfun moveCompare(m1, m2) = if m1 is Move(ma1, mb1, mc1) and m2 is Move(ma2, mb2, mc2) then\n  let ac = squareCompare(ma1, ma2)\n  if ac === 0 then\n    let bc = optPieceCompare(mb1, mb2)\n    if bc === 0 then optPieceCompare(mc1, mc2) else bc\n  else ac\nfun moveInFullCompare(mif1, mif2) =\n  if mif1 is MoveInFull(p1, s1, m1) and mif2 is MoveInFull(p2, s2, m2) then\n    let pc = pieceCompare(p1, p2)\n    if pc === 0 then\n      let sc = squareCompare(s1, s2)\n      if sc === 0 then moveCompare(m1, m2) else sc\n    else pc\n\nfun maybe(d, f, x) = if x is\n  None then d\n  Some(x) then f(x)\n\nfun isUpper(c) = let x = c.charCodeAt(0) in (x >= 65 and x <= 90)\n\nfun isLower(c) = let x = c.charCodeAt(0) in (x >= 97 and x <= 122)\n\nfun toLower(c) = if isUpper(c) then String.fromCharCode(c.charCodeAt(0) + 32) else c\n\nfun words(s) = if leaveWhile(x => x === \" \", s) is\n  Nil then Nil\n  s_ and\n    break_(x => x === \" \", s_) is [w, s__] then w :: words(s__)\n\nfun unlines(ls) = concat(map(l => append(l, \"\\n\" :: Nil), ls))\n\nfun lines(s) = if break_(x => x === \"\\n\", s) is [l, s_] then\n  Cons of\n    l\n    if s_ is\n      Nil then Nil\n      Cons(_, s__) then lines(s__)\n\nfun any(p, ls) = if ls is\n  Nil then false\n  x :: xs then p(x) || any(p, xs)\n\nfun showColour(c) = nofibStringToList(if c is Black then \"Black\" else \"White\")\n\nfun pieceAt(bd, sq) = if bd is Board(wkss, bkss) then\n  fun pieceAtWith(c, n, ls) = if ls is\n    Nil then n\n    [k, s] :: xs and\n      eqTup2(s, sq) then Some([c, k])\n      else pieceAtWith(c, n, xs)\n  pieceAtWith(White, pieceAtWith(Black, None, bkss), wkss)\n\nfun kindToChar(k) = if k is\n  King then \"K\"\n  Queen then \"Q\"\n  Rook then \"R\"\n  Bishop then \"B\"\n  Knight then \"N\"\n  Pawn then \"P\"\n\nfun pieceToChar(p) = if p is\n  [Black, k] then kindToChar(k)\n  [White, k] then toLower(kindToChar(k))\n\nfun showBoard(bd) =\n  fun showRank(r) =\n    fun consFile(f, s) = if pieceAt(bd, [f, r]) is\n      None then nofibStringToList(\" -\") +: s\n      Some(p) then \" \" :: pieceToChar(p) :: s\n    foldr(consFile, Nil, enumFromTo(1, 8))\n  unlines(map(showRank, reverse(enumFromTo(1, 8))))\n\nfun showPiece(p) = if p is [c, k] then kindToChar(k) :: Nil\n\nfun showSquare(c, x_y) = if x_y is [x, y] then\n  atIndex(\n    x - 1,\n    nofibStringToList(\"QR\") ::\n    nofibStringToList(\"QN\") ::\n    nofibStringToList(\"QB\") ::\n    nofibStringToList(\"Q\") ::\n    nofibStringToList(\"K\") ::\n    nofibStringToList(\"KB\") ::\n    nofibStringToList(\"KN\") ::\n    nofibStringToList(\"KR\") :: Nil\n  ) +:\n  nofibStringToList(stringOfInt(if c is Black then 9 - y else y))\n\nfun emptyAtAll(bd, e) = if bd is Board(wkss, bkss) then\n  fun emptyAtAllAnd(b, ls) = if ls is\n    Nil then b\n    [_, s] :: xs then (not(e(s)) and emptyAtAllAnd(b, xs))\n  emptyAtAllAnd(emptyAtAllAnd(true, bkss), wkss)\n\nfun rPa(sq, kss) = if kss is\n  Nil then throw Error(\"rPa\")\n  [k, s] :: kss then if eqTup2(s, sq) then kss else [k, s] :: rPa(sq, kss)\n\nfun rmPieceAt(c, sq, bd) = if bd is Board(wkss, bkss) and c is\n  White then Board(rPa(sq, wkss), bkss)\n  Black then Board(wkss, rPa(sq, bkss))\n\nfun putPieceAt(sq, c_k, bd) =\n  if c_k is [c, k] and bd is Board(wkss, bkss) and c is\n    White then Board([k, sq] :: wkss, bkss)\n    Black then Board(wkss, [k, sq] :: bkss)\n\nfun kSq(kss) = if kss is\n  [King, s] :: _ then s\n  _ :: kss then kSq(kss)\n  Nil then throw Error(\"kSq\")\n\nfun kingSquare(c, bd) = if bd is Board(wkss, bkss) and c is\n  White then kSq(wkss)\n  Black then kSq(bkss)\n\nfun opponent(c) = if c is White then Black else White\n\nfun colourOf(c_k) = if c_k is [c, _] then c\n\nfun kindOf(c_k) = if c_k is [_, k] then k\n\nfun onboard(p_q) = if p_q is [p, q] then\n  (p >= 1 and p <= 8) and (q >= 1 and q <= 8)\n\nfun forcesColoured(c, bd) = if bd is Board(wkss, bkss) and c is\n  White then wkss\n  Black then bkss\n\nval emptyBoard = Board(Nil, Nil)\n//│ emptyBoard = Board([], [])\n\nfun showMove(withPiece, m) = if m is MoveInFull([c, k], sq, Move(sq_, mcp, mpp)) then\n  let capt = mcp is Some(_)\n  let prom = mpp is Some(_)\n  (if withPiece then\n      showPiece([c, k]) +:\n      if ((k === King) || (k is Pawn and not(capt || prom))) then Nil else \"/\" :: showSquare(c, sq)\n    else Nil\n  ) +:\n  maybe(\"-\" :: Nil, cp => \"x\" :: append(showPiece(cp), \"/\" :: Nil), mcp) +:\n  showSquare(c, sq_) +:\n  maybe(Nil, pp => \"(\" :: append(showPiece(pp), \")\" :: Nil), mpp)\n\nfun showMoveInFull(a) = showMove(true, a)\n\nfun showMovesAfter(p_, mifs) = if mifs is\n  Nil then Nil\n  MoveInFull(p, sq, d_) :: mifs and p_ is MoveInFull(p_, sq_, _) then\n    nofibStringToList(\", \") +:\n    showMove(not(eqTup2(p, p_)) || not(eqTup2(sq, sq_)), MoveInFull(p, sq, d_)) +:\n    showMovesAfter(MoveInFull(p, sq, d_), mifs)\n\nfun showMoves(mifs) = if mifs is\n  Nil then throw Error(\"showMoves\")\n  mif :: mifs then\n    showMoveInFull(mif) +:\n    showMovesAfter(mif, mifs)\n\nfun sift(c, bd, ms, sqs) = if sqs is\n  Nil then ms\n  sq :: sqs and\n    onboard(sq) and pieceAt(bd, sq) is\n      None then sift(c, bd, Move(sq, None, None) :: ms, sqs)\n      Some(p_) and\n        colourOf(p_) === c then sift(c, bd, ms, sqs)\n        else sift(c, bd, Move(sq, Some(p_), None) :: ms, sqs)\n    else sift(c, bd, ms, sqs)\n\nfun moveLine(bd, c, sq, inc, cont) = \n  fun ml(sq, ms) = \n    let sq_ = inc(sq)\n    if onboard(sq_) and pieceAt(bd, sq_) is\n      None then ml(sq_, Move(sq_, None, None) :: ms)\n      Some(p_) and\n        not(colourOf(p_) === c) then cont(Move(sq_, Some(p_), None) :: ms)\n        else cont(ms)\n    else cont(ms)\n  ms => ml(sq, ms)\n\nfun bishopmoves(c, sq, bd) =\n  (moveLine of\n    bd\n    c\n    sq\n    case { [x, y] then [x - 1, y + 1] }\n    moveLine of\n      bd\n      c\n      sq\n      case { [x, y] then [x + 1, y + 1] }\n      moveLine of\n        bd\n        c\n        sq\n        case { [x, y] then [x - 1, y - 1] }\n        moveLine of\n          bd\n          c\n          sq\n          case { [x, y] then [x + 1, y - 1] }\n          x => x\n  ) of Nil\n\nfun rookmoves(c, sq, bd) =\n  (moveLine of\n    bd\n    c\n    sq\n    case { [x, y] then [x - 1, y] }\n    moveLine of\n      bd\n      c\n      sq\n      case { [x, y] then [x + 1, y] }\n      moveLine of\n        bd\n        c\n        sq\n        case { [x, y] then [x, y - 1] }\n        moveLine of\n          bd\n          c\n          sq\n          case { [x, y] then [x, y + 1] }\n          x => x\n  ) of Nil\n\nfun kingmoves(c, pq, bd) = if pq is [p, q] then\n  sift of\n    c\n    bd\n    Nil\n    [p - 1, q + 1] ::\n    [p, q + 1] ::\n    [p + 1, q + 1] ::\n    [p - 1, q] ::\n    [p + 1, q] ::\n    [p - 1, q - 1] ::\n    [p, q - 1] ::\n    [p + 1, q - 1] :: Nil\n\nfun knightmoves(c, pq, bd) = if pq is [p, q] then\n  sift of\n    c\n    bd\n    Nil\n    [p - 1, q + 2] ::\n    [p + 1, q + 2] ::\n    [p - 2, q + 1] ::\n    [p + 2, q + 1] ::\n    [p - 2, q - 1] ::\n    [p + 2, q - 1] ::\n    [p - 1, q - 2] ::\n    [p + 1, q - 2] :: Nil\n\nfun pawnmoves(c, pq, bd) = if pq is [p, q] then\n  let fwd = if c is White then 1 else -1\n  fun promote(xy, mcp) = if xy is [x, y] and\n    ((c is Black) and y === 1) || ((c is White) and y === 8) then\n      map(\n        param => Move([x, y], mcp, Some(param)),\n        [c, Queen] ::\n        [c, Rook] ::\n        [c, Bishop] ::\n        [c, Knight] :: Nil\n      )\n    else Move([x, y], mcp, None) :: Nil\n  let movs =\n    let on1 = [p, q + fwd]\n    let on2 = [p, q + 2 * fwd]\n    if pieceAt(bd, on1) is None then\n      promote(on1, None) +:\n      (if (q === 2 and c is White) || (q === 7 and c is Black) and pieceAt(bd, on2) is None then\n        Move(on2, None, None) :: Nil\n      else Nil)\n    else Nil\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    sq :: sqs then\n      fun lscomp2(ls) = if ls is\n        Nil then lscomp1(sqs)\n        h :: ls and\n          h is Some(p_) and not(colourOf(p_) === c) then promote(sq, Some(p_)) :: lscomp2(ls)\n          else lscomp2(ls)\n      lscomp2(pieceAt(bd, sq) :: Nil)\n  let caps = concat(lscomp1([p + 1, q + fwd] :: [p - 1, q + fwd] :: Nil))\n  movs +: caps\n\nfun queenmoves(c, sq, bd) = bishopmoves(c, sq, bd) +: rookmoves(c, sq, bd)\n\nfun kingincheck(c, bd) =\n  fun givesCheck(kxy) = if kxy is [k, [x, y]] then\n    fun kthreat(param) = if kingSquare(c, bd) is [xk, yk] and param is\n      King then (abs(x - xk) <= 1) and (abs(y - yk) <= 1)\n      Queen then kthreat(Rook) || kthreat(Bishop)\n      Rook then\n        ((x === xk) && emptyAtAll(bd, case { [xe, ye] then (xe === xk) && ((min(y, yk) < ye) && (ye < max(y, yk))) } )) ||\n        ((y === yk) && emptyAtAll(bd, case { [xe, ye] then (ye === yk) && ((min(x, xk) < xe) && (xe < max(x, xk))) } ))\n      Bishop then\n        (((x + y) === (xk + yk)) && emptyAtAll(bd, case { [xe, ye] then ((xe + ye) === (xk + yk)) && ((min(x, xk) < xe) && (xe < max(x, xk))) } )) ||\n        (((x - y) === (xk - yk)) && emptyAtAll(bd, case { [xe, ye] then ((xe - ye) === (xk - yk)) && ((min(x, xk) < xe) && (xe < max(x, xk))) } ))\n      Knight then\n        (((abs(x - xk)) === 2) && ((abs(y - yk)) === 1)) || (((abs(x - xk)) === 1) && ((abs(y - yk)) === 2))\n      Pawn then\n        ((abs(x - xk) === 1) && (if c is Black then yk === (y + 1) else yk === (y - 1)))\n    kthreat(k)\n  any(givesCheck, forcesColoured(opponent(c), bd))\n\nfun tryMove(c, ksq, m, bd) = if \n  ksq is [k, sq] and m is Move(sq_, mcp, mpp) then\n    let p = [c, k]\n    let bd1 = rmPieceAt(c, sq, bd)\n    let p_ = maybe(p, x => x, mpp)\n    let bd2 = maybe(\n      putPieceAt(sq_, p_, bd1),\n      dummy => putPieceAt(sq_, p_, rmPieceAt(opponent(c), sq_, bd1)),\n      mcp\n    )\n    if not(kingincheck(c, bd2)) then Some([MoveInFull(p, sq, Move(sq_, mcp, mpp)), bd2]) else None\n  else\n    throw Error(m)\n\nfun rawmoves(c, ksq, bd) = if ksq is [k, sq] then\n  let m = if k is\n    King then kingmoves\n    Queen then queenmoves\n    Rook then rookmoves\n    Bishop then bishopmoves\n    Knight then knightmoves\n    Pawn then pawnmoves\n  let res = m(c, sq, bd)\n  res\n\nfun moveDetailsFor(c, bd) = foldr of\n  (ksq, ms) => foldr of\n    (rm, ms_) => maybe(x => x, h => (t => h :: t), tryMove(c, ksq, rm, bd))(ms_)\n    ms\n    rawmoves(c, ksq, bd)\n  Nil\n  forcesColoured(c, bd)\n\nfun comment(s) = (s is Nil) || listEq(take(2, s), nofibStringToList(\"--\"))\n\nfun last(ls) = if ls is\n  x :: Nil then x\n  h :: t then last(t)\n\nfun intOfString(s) = globalThis.parseInt(nofibListToString(s))\n\nfun parseGoal(ls) = if ls is\n  gltxt :: Nil then\n    let ws = words(gltxt)\n    let c = if listEq(head(ws), nofibStringToList(\"Black\")) then Black else White\n    let n = intOfString(last(ws))\n    [c, n]\n  else throw Error(\"parseGoal\")\n\nfun parseSquare(r, f, c) = if c === \"-\" then Nil else\n  let clr = if isUpper(c) then Black else White\n  let kin = if toLower(c) ===\n    \"k\" then King\n    \"q\" then Queen\n    \"r\" then Rook\n    \"b\" then Bishop\n    \"n\" then Knight\n    \"p\" then Pawn\n  [[clr, kin], [f, r]] :: Nil\n\nfun parseRank(r, x) = concat of zipWith of\n  (a, b) => parseSquare(r, a, b)\n  enumFromTo(1, 8)\n  filter(pp => not(pp === \" \"), x)\n\n\nfun parseBoard(ls) =\n  fun addPiece(p_sq, x) = if p_sq is [p, sq] then putPieceAt(sq, p, x)\n  foldr of\n    addPiece\n    emptyBoard\n    concat(zipWith(parseRank, reverse(enumFromTo(1, 8)), ls))\n\nfun parseProblem(s) =\n  let bdtxt_gltxt = splitAt(8, filter(x => not(comment(x)), s))\n  if bdtxt_gltxt is [bdtxt, gltxt] then\n    let bd = parseBoard(bdtxt)\n    let gl = parseGoal(gltxt)\n    [bd, gl]\n\nfun readProblem(s) = parseProblem(lines(s))\n\nfun foldr_lz(f, a, x) = if x is\n  h :: t then f(h, lazy of () => foldr_lz(f, a, t))\n  Nil then a\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun replies(bd, c, n) =\n  let mds = moveDetailsFor(c, bd)\n  fun solnAnd(mifb, rest) = if mifb is [mif, b] then\n    let sm = solution(b, opponent(c), n - 1)\n    if sm is\n      None then None\n      Some(s) and\n        force(rest) is\n          None then None\n          Some(ms) then Some([mif, s] :: ms)\n  if n\n    === 0 and\n      null_(mds) then Some(Nil)\n      else None\n    > 0 then foldr_lz(solnAnd, Some(Nil), mds)\n    else throw Error(\"n < 0\")\n\nfun solution(bd, c, n) =\n  fun solnOr(mifb, other) = if mifb is\n    [mif, b] then\n      let rsm = replies(b, opponent(c), n - 1)\n      if rsm is\n        None then force(other)\n        Some(Nil) and\n          kingincheck(opponent(c), b) then\n            Some(Solution(mif, Nil))\n          else force(other)\n        Some(rs) then Some(Solution(mif, rs))\n  if n > 0 then\n    let mds = moveDetailsFor(c, bd)\n    foldr_lz(solnOr, None, mds)\n  else throw Error(\"n <= 0\")\n//│ ————————————————————————————————————————————————————————————————————————————————\n\ndata class Soln(a: MoveInFull, b: List[[List[MoveInFull],Soln]])\n\nfun tab(n) = if n <= 0 then Nil else \" \" :: tab(n - 1)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun showReplies(rs, n) = if rs is\n  Nil then Nil\n  [mifs, s] :: rs then\n    tab(n) +:\n    nofibStringToList(\"if \") +:\n    if null_(rs) && (listLen(mifs) > 1) then nofibStringToList(\"others\") else showMoves(mifs) +:\n    nofibStringToList(\"; \") +:\n    showSoln(s, n + 1) +:\n    showReplies(rs, n)\n\nfun showSoln(s, n) = if s is Soln(mif, rs) then\n  nofibStringToList(stringOfInt(n)) +:\n  nofibStringToList(\". \") +:\n  showMoveInFull(mif) +:\n  if rs is\n    Nil then nofibStringToList(\"++\\n\")\n    [mifs, s_] :: Nil then\n      nofibStringToList(\", \") +:\n      (if listLen(mifs) > 1 then nofibStringToList(\"...\") else showMoves(mifs)) +:\n      nofibStringToList(\"; \") +:\n      showSoln(s_, n + 1)\n    else\n      nofibStringToList(\",\\n\") +: showReplies(sort(rs), n)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun compact(s) = if s is Solution(mif, rs) then Soln(mif, foldr(insertCompact, Nil, rs))\n\nfun insertCompact(mif_s, ls) = if mif_s is [mif, s] then\n  fun insert(x, ls) = if ls is\n    Nil then x :: Nil\n    y :: ys then if moveInFullCompare(x, y) > 0 then y :: insert(x, ys) else x :: y :: ys\n  let cs = compact(s)\n  fun ic(ls) = if ls is\n    Nil then [mif :: Nil, cs] :: Nil\n    [mifs, cs_] :: etc then\n      let a = showSoln(cs, 1)\n      let b = showSoln(cs_, 1)\n      if\n        ltList(a, b, (x, y) => x < y, (x, y) => x > y) then [mif :: Nil, cs] :: [mifs, cs_] :: etc\n        listEq(a, b) then [insert(mif, mifs), cs] :: etc\n        not(ltList(a, b, (x, y) => x < y, (x, y) => x > y)) then [mifs, cs_] :: ic(etc)\n        else throw Error(\"compare error\")\n  ic(ls)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun showResult(s) = if s is\n  None then nofibStringToList(\"No solution!\")\n  Some(s) then showSoln(compact(s), 1)\n\nfun solve(bd, c, n) = showResult(solution(bd, c, (2 * n) - 1))\n\nfun testMate_nofib(dummy) = \n  let input = nofibStringToList of\n    fs.readFileSync(\"./hkmc2/shared/src/test/mlscript/nofib/input/heathcote3.prob\").toString()\n  let bdcn = readProblem(input)\n  if bdcn is [bd, [c, n]] then\n    showBoard(bd) +:\n    nofibStringToList(\"\\n\") +:\n    showColour(c) +:\n    nofibStringToList(\" to move and mate in \") +:\n    nofibStringToList(stringOfInt(n)) +:\n    nofibStringToList(\"\\n\") +:\n    nofibStringToList(\"\\n\") +:\n    solve(bd, c, n)\n\nfun main() = nofibListToString(testMate_nofib(0))\n\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/minimax.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule minimax with ...\n\n\nfun andd(ls) = if ls is\n  Nil then true\n  b :: bs then b && andd(bs)\n\nabstract class Piece: X | O | Empty\n\nobject\n  X extends Piece\n  O extends Piece\n  Empty extends Piece\n\nfun eqPiece(p1, p2) = if p1 is\n  X and p2 is X then true\n  O and p2 is O then true\n  Empty and p2 is Empty then true\n  else false\n\nabstract class Evaluation: XWin | OWin | Score\n\nobject\n  XWin extends Evaluation\n  OWin extends Evaluation\n\ndata class Score(i: Int) extends Evaluation\n\nfun evaluationEq(x, y) = if x is\n  XWin and y is XWin then true\n  OWin and y is OWin then true\n  Score(i) and y is Score(j) and i === j then true\n  else false\n\ndata class Branch[A](a: A, cs: List[Branch[A]])\n\nfun showEvaluation(e) = if e is\n  XWin then nofibStringToList(\"XWin\")\n  OWin then nofibStringToList(\"OWin\")\n  Score(i) then nofibStringToList(\"Score \") +: nofibStringToList(stringOfInt(i))\n\nval win1 =\n  (1 :: 1 :: 1 :: Nil) ::\n  (0 :: 0 :: 0 :: Nil) ::\n  (0 :: 0 :: 0 :: Nil) :: Nil\n//│ win1 = [[1,1,1],[0,0,0],[0,0,0]]\n\nval win2 =\n  (0 :: 0 :: 0 :: Nil) ::\n  (1 :: 1 :: 1 :: Nil) ::\n  (0 :: 0 :: 0 :: Nil) :: Nil\n//│ win2 = [[0,0,0],[1,1,1],[0,0,0]]\n\nval win3 =\n  (0 :: 0 :: 0 :: Nil) ::\n  (0 :: 0 :: 0 :: Nil) ::\n  (1 :: 1 :: 1 :: Nil) :: Nil\n//│ win3 = [[0,0,0],[0,0,0],[1,1,1]]\n\nval win4 =\n  (1 :: 0 :: 0 :: Nil) ::\n  (1 :: 0 :: 0 :: Nil) ::\n  (1 :: 0 :: 0 :: Nil) :: Nil\n//│ win4 = [[1,0,0],[1,0,0],[1,0,0]]\n\nval win5 =\n  (0 :: 1 :: 0 :: Nil) ::\n  (0 :: 1 :: 0 :: Nil) ::\n  (0 :: 1 :: 0 :: Nil) :: Nil\n//│ win5 = [[0,1,0],[0,1,0],[0,1,0]]\n\nval win6 =\n  (0 :: 0 :: 1 :: Nil) ::\n  (0 :: 0 :: 1 :: Nil) ::\n  (0 :: 0 :: 1 :: Nil) :: Nil\n//│ win6 = [[0,0,1],[0,0,1],[0,0,1]]\n\nval win7 =\n  (1 :: 0 :: 0 :: Nil) ::\n  (0 :: 1 :: 0 :: Nil) ::\n  (0 :: 0 :: 1 :: Nil) :: Nil\n//│ win7 = [[1,0,0],[0,1,0],[0,0,1]]\n\nval win8 =\n  (0 :: 0 :: 1 :: Nil) ::\n  (0 :: 1 :: 0 :: Nil) ::\n  (1 :: 0 :: 0 :: Nil) :: Nil\n//│ win8 = [[0,0,1],[0,1,0],[1,0,0]]\n\nval wins = win1 :: win2 :: win3 :: win4 :: win5 :: win6 :: win7 :: win8 :: Nil\n//│ wins = [[[1,1,1],[0,0,0],[0,0,0]],[[0,0,0],[1,1,1],[0,0,0]],[[0,0,0],[0,0,0],[1,1,1]],[[1,0,0],[1,0,0],[1,0,0]],[[0,1,0],[0,1,0],[0,1,0]],[[0,0,1],[0,0,1],[0,0,1]],[[1,0,0],[0,1,0],[0,0,1]],[[0,0,1],[0,1,0],[1,0,0]]]\n\nfun showPiece(p) = if p is\n  X then nofibStringToList(\"X\")\n  O then nofibStringToList(\"O\")\n  Empty then nofibStringToList(\" \")\n\nfun showRow(ps) = if ps is\n  p1 :: p2 :: p3 :: Nil then\n    showPiece(p1) +: nofibStringToList(\"|\") +: showPiece(p2) +: nofibStringToList(\"|\") +: showPiece(p3)\n\nfun showBoard(rs) = if rs is\n  r1 :: r2 :: r3 :: Nil then\n    showRow(r1) +:\n    nofibStringToList(\"\\n------\\n\") +:\n    showRow(r2) +:\n    nofibStringToList(\"\\n------\\n\") +:\n    showRow(r3) +:\n    nofibStringToList(\"\\n\\n\")\n\nfun insert(p, ps, i) = if ps is Cons(p1, Cons(p2, Cons(p3, Nil))) and i ===\n  1 then p :: p2 :: p3 :: Nil\n  2 then p1 :: p :: p3 :: Nil\n  3 then p1 :: p2 :: p :: Nil\n\nfun empty_(x, r) = if\n  x === 1 and r is Empty :: _ :: _ :: Nil then true\n  x === 2 and r is _ :: Empty :: _ :: Nil then true\n  x === 3 and r is _ :: _ :: Empty :: Nil then true\n  else false\n\nfun empty(pos, board) = if board is r1 :: r2 :: r3 :: Nil and pos is\n  [1, x] then empty_(x, r1)\n  [2, x] then empty_(x, r2)\n  [3, x] then empty_(x, r3)\n\nfun placePiece(p, board, pos) = if\n  not(empty(pos, board)) then Nil\n  board is r1 :: r2 :: r3 :: Nil and pos is\n    [1, x] then (insert(p, r1, x) :: r2 :: r3 :: Nil) :: Nil\n    [2, x] then (r1 :: insert(p, r2, x) :: r3 :: Nil) :: Nil\n    [3, x] then (r1 :: r2 :: insert(p, r3, x) :: Nil) :: Nil\n\nfun fullBoard(b) = andd of map of\n  x => not(eqPiece(x, Empty))\n  concat(b)\n\nfun newPositions(piece, board) =\n  fun lscomp1(ls) = if ls is\n    Nil then Nil\n    x :: xs then\n      fun lscomp2(ls) = if ls is\n        Nil then lscomp1(xs)\n        y :: ys then [x, y] :: lscomp2(ys)\n      lscomp2(1 :: 2 :: 3 :: Nil)\n  concat of map of\n    pos => placePiece(piece, board, pos)\n    lscomp1(1 :: 2 :: 3 :: Nil)\n\nval initialBoard = replicate(3, replicate(3, Empty))\n//│ initialBoard = [[Empty,Empty,Empty],[Empty,Empty,Empty],[Empty,Empty,Empty]]\n\nfun eval(x) = if x ===\n  3 then XWin\n  -3 then OWin\n  else Score(x)\n\nfun interpret(x, l) = if l is\n  Nil then Score(x)\n  Score(y) :: ls then interpret(x + y, ls)\n  XWin :: _ then XWin\n  OWin :: _ then OWin\n\nfun scorePiece(p, score) = if p is\n  X then score\n  Empty then 0\n  O then -score\n\nfun map2(f, xs, ys) = if xs is\n  Nil then Nil\n  x :: xs and\n    ys is\n      y :: ys then f(x, y) :: map2(f, xs, ys)\n      Nil then Nil\n\nfun score(board, win) = eval of sum of map of\n  sum\n  map2((x, y) => map2(scorePiece, x, y), board, win)\n\nfun static(board) = interpret(0, map(x => score(board, x), wins))\n\nfun repTree(f, g, a) = Branch(a, map(x => repTree(g, f, x), f(a)))\n\nfun mapTree(f, t) = if t is Branch(a, l) then Branch(f(a), map(x => mapTree(f, x), l))\n\nfun prune(n, t) = if t is Branch(a, l) and n\n  === 0 then Branch(a, Nil)\n  < 0 then throw Error(\"Tree.prune: < 0\")\n  else Branch(a, map(x => prune(n - 1, x), l))\n\nfun opposite(p) = if p is\n  X then O\n  O then X\n  else throw Error(\"opposite\")\n\nfun best(f, bs, ss) = if bs is b :: bs and ss is s :: ss then\n  fun best_(b, s, ls1, ls2) = if ls1 is\n    Nil and ls2 is Nil then [b, s]\n    b_ :: bs and ls2 is s_ :: ss and\n      evaluationEq(s, f(s, s_)) then best_(b, s, bs, ss)\n      else best_(b_, s_, bs, ss)\n  best_(b, s, bs, ss)\n\nfun showMove(m) = if m is [b, e] then\n  showEvaluation(e) +: nofibStringToList(\"\\n\") +: showBoard(b)\n\nfun max_(e1, e2) = if\n  e1 is XWin then XWin\n  e2 is XWin then XWin\n  e2 is OWin then e1\n  e1 is OWin then e2\n  e1 is Score(x) and e2 is Score(y) and\n    x > y then Score(x)\n    else Score(y)\n\nfun min_(e1, e2) = if\n  e1 is OWin then OWin\n  e2 is OWin then OWin\n  e2 is XWin then e1\n  e1 is XWin then e2\n  e1 is Score(x) and e2 is Score(y) and\n    x < y then Score(x)\n    else Score(y)\n\nfun mise(f, g, t) = if t is\n  Branch(a, Nil) then a\n  Branch(_, l) then foldr(f, g(OWin, XWin), map(x => mise(g, f, x), l))\n\nfun searchTree(p, board) =\n  prune of\n    5\n    repTree of\n      x => newPositions(p, x),\n      x => newPositions(opposite(p), x),\n      board\n\nfun cropTree(t) = if t is\n  Branch(a, Nil) then Branch(a, Nil)\n  Branch(Score(x), l) then Branch(Score(x), map(cropTree, l))\n  Branch(x, l) then Branch(x, Nil)\n\nfun bestMove(p, f, g, b) =\n  mise(f, g, cropTree(mapTree(static, searchTree(p, b))))\n\n\nfun alternate(player, f, g, board) = if\n  fullBoard(board) then Nil\n  evaluationEq(static(board), XWin) then Nil\n  evaluationEq(static(board), OWin) then Nil\n  let opposition = opposite(player)\n  let possibles = newPositions(player, board)\n  let scores = map(x => bestMove(opposition, g, f, x), possibles)\n  let boardd_eval = best(f, possibles, scores)\n  boardd_eval is [boardd, eval] then\n    [boardd, eval] :: alternate(opposition, g, f, boardd)\n\nfun prog(input) =\n  let testBoard =\n    (Empty :: O :: Empty :: Nil) ::\n    (Empty :: X :: Empty :: Nil) ::\n    (Empty :: Empty :: Empty :: Nil) :: Nil\n  fun board(x) = if x ===\n    \"doesn't happen\" then testBoard +: testBoard\n    else testBoard\n  let game = alternate(X, max_, min_, board(input))\n  nofibStringToList(\"OXO\\n\") +:\n  concat of map(showMove, game)\n\nfun main() = nofibListToString(prog(\"180000\"))\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/para.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule para with ...\n\n\n\nfun unwords(ws) = if ws is\n  Nil then Nil\n  w :: ws then\n    fun go(vs) = if vs is\n      Nil then Nil\n      v :: vs then \" \" :: (v +: go(vs))\n    w +: go(ws)\n\nfun break_(p, xs) = if xs is\n  Nil then [Nil, Nil]\n  x :: xs and\n    p(x) then [Nil, x :: xs]\n    break_(p, xs) is [ys, zs] then [x :: ys, zs]\n\nfun isSpace(c) = c === \" \"\n\nfun words(s) = if leaveWhile(isSpace, s) is\n  Nil then Nil\n  h :: t and\n    break_(isSpace, h :: t) is [w, s_] then w :: words(s_)\n\nfun lines(s) = if break_(x => x === \"\\n\", s) is [l, s_] then\n  Cons(\n    l,\n    if s_ is\n      Nil then Nil\n      _ :: s__ then lines(s__)\n  )\n\nfun unlines(ls) = concat(map(l => l +: nofibStringToList(\"\\n\"), ls))\n\nfun all(p, xs) = if xs is\n  Nil then true\n  x :: xs then p(x) && all(p, xs)\n\nfun fold1(f, g, xs) = if xs is\n  a :: Nil then g(a)\n  a :: x then f(a, fold1(f, g, x))\n\nfun scan1(f, g, xs) = fold1((a, s) => f(a, head(s)) :: s, a => g(a) :: Nil, xs)\n\nfun tails(xs) = scan1((a, s) => a :: s, a => a :: Nil, xs)\n\nfun single(xs) = if xs is\n  a :: Nil then true\n  _ then false\n\nfun minWith(f, xs) = fold1((a, b) => if f(a) < f(b) then a else b, x => x, xs)\n\nfun new_(w, ls) = (w :: Nil) :: ls\n\nfun glue(w, ls) = if ls is\n  l :: ls_ then (w :: l) :: ls_\n\nfun formats(txt) = fold1 of\n  (w, ps) => map(p => new_(w, p), ps) +: map(p => glue(w, p), ps)\n  x => ((x :: Nil) :: Nil) :: Nil\n  txt\n\nval maxw = 70\n//│ maxw = 70\n\nfun width(ls) =\n  fun plus(w, n) = listLen(w) + 1 + n\n  fold1(plus, listLen, ls)\n\nfun fits(xs) = width(xs) <= maxw\n\nfun feasible(a) = all(fits, a)\n\nval optw = 63\n//│ optw = 63\n\nfun cost(ls) =\n  fun linc(l) = let a = optw - width(l) in a * a\n  fun plus(l, n) = linc(l) + n\n  fold1(plus, x => 0, ls)\n\nfun par0(x) = minWith(cost, filter(feasible, formats(x)))\n\nfun fitH(ls) = fits(head(ls))\n\nfun fst3(a_b_c) = if a_b_c is [a, b, c] then a\n\nfun snd3(a_b_c) = if a_b_c is [a, b, c] then b\n\nfun thd3(a_b_c) = if a_b_c is [a, b, c] then c\n\nfun width_tl(a_b_c) = fst3(a_b_c)\n\nfun cost_tl(a_b_c) = snd3(a_b_c)\n\nfun len_tl(a_b_c) = thd3(a_b_c)\n\nfun tile(ws, a_b) = if a_b is\n  [Nil, n] then Nil\n  [m :: ms, n] then\n    let l = n - m\n    if splitAt(l, ws) is [ws1, ws2] then\n      ws1 :: tile(ws2, [leave(l, m :: ms), m])\n\nfun null__(a_b) = if a_b is [Nil, Nil] then true else false\n\nfun single_(a_b) = if a_b is [x, y] then (null_(x) && single(y)) || (single(x) && null_(y))\n\n\nval nil_ = [Nil, Nil]\n//│ nil_ = [[], []]\n\nfun head_(a_b) = if a_b is [x, y] and\n  not(null_(x)) then head(x)\n  else head(y)\n\nfun last_(a_b) = if a_b is [y, x] and\n  not(null_(x)) then head(x)\n  else head(y)\n\nfun cons_(a, a_b) = if a_b is [x, y] and\n  not(null_(y)) then [a :: x, y]\n  else [a :: Nil, x]\n\nfun snoc_(a, a_b) = if a_b is [y, x] and\n  not(null_(y)) then [y, a :: x]\n  else [x, a :: Nil]\n\nfun tail_(a_b) = if a_b is [x, y] and\n  null_(x) then [Nil, Nil]\n  single(x) and splitAt(intDiv(listLen(y), 2), y) is [y0, y1] then\n    [reverse(y1), y0]\n  else [tail(x), y]\n\nfun init_(a_b) = if a_b is [y, x] and\n  null_(x) then [Nil, Nil]\n  single(x) and splitAt(intDiv(listLen(y), 2), y) is [y0, y1] then\n    [y0, reverse(y1)]\n  else [y, tail(x)]\n\nfun unformat(a, l) = fold1((xs, ys) => xs +: (a :: Nil) +: ys, x => x, l)\n\nfun format(a, x) = if\n  x is Nil then Nil :: Nil\n  else\n    fun unknownEq(a, b) = a === b\n    fun breakk(a, b, xs) =\n      if unknownEq(a, b)\n      then Nil :: xs\n      else (b :: head(xs)) :: tail(xs)\n    fun start(a, b) = breakk(a, b, Nil :: Nil)\n    fold1((x, y) => breakk(a, x, y), y => start(a, y), x)\n\nfun unparas(ls) = unformat(Nil, ls)\n\nfun paras(ls) = filter(x => listNeq(Nil, x), format(Nil, ls))\n\nfun parse(ls) = paras(map(words, lines(ls)))\n\nfun unparse(ls) = unlines(map(unwords, unparas(ls)))\n\nfun startr(a) = if\n  a <= maxw then [cons_([0, 0, 0], nil_), a, 1]\n  else throw Error(\"startr param error\")\n\nfun ceildiv(n, m) = intDiv(n + m - 1, m)\n\nfun fmtWith(par) = unparse(map(x => par(concat(x)), parse(par)))\n\nfun stepr(w, ps_tw_tl) = if ps_tw_tl is [ps, tw, tl] then\n  let tot_width = w + 1 + tw\n  let tot_len = 1 + tl\n  fun single(p) = len_tl(p) === 0\n  fun width_hd(p) = if single(p) then tot_width else tot_width - width_tl(p) - 1\n  fun cost(p) = if single(p) then 0 else cost_tl(p) + (let a = optw - width_hd(p) in a * a)\n  fun old_width_hd(p) = if single(p) then tw else tw - width_tl(p) - 1\n  fun new_(p) = if single(p) then [tw, 0, tl] else [tw, cost_tl(p) + (let x = optw - old_width_hd(p) in x * x), tl]\n  fun trim(ps_pq) = if\n    null__(ps_pq) then ps_pq\n    single_(ps_pq) then ps_pq\n    let ps_p = init_(ps_pq)\n    let q = last_(ps_pq)\n    let p = last_(ps_p)\n    cost(p) <= cost(q) then trim(ps_p)\n    else ps_pq\n  fun leave_nofit(ps_p) = if\n    null__(ps_p) then ps_p\n    width_hd(last_(ps_p)) > maxw then leave_nofit(init_(ps_p))\n    else ps_p\n  fun bf(p, q) =\n    let wqh = width_hd(q)\n    let rqh = maxw - wqh + 1\n    if\n      single(q) && cost_tl(p) === 0 then min(optw - width_hd(p), rqh)\n      single(q) then rqh\n      else min(ceildiv(cost(p) - cost(q), 2 * (wqh - width_hd(p))), rqh)\n  fun myAdd(p, qr_rs) = if\n    single_(qr_rs) || null__(qr_rs) then cons_(p, qr_rs)\n    let q = head_(qr_rs)\n    let r_rs = tail_(qr_rs)\n    let r = head_(r_rs)\n    bf(p, q) <= bf(q, r) then myAdd(p, r_rs)\n    else cons_(p, qr_rs)\n  [trim(leave_nofit(myAdd(new_(last_(ps)), ps))), tot_width, tot_len]\n\nfun par3(ws) =\n  let zs = scan1(stepr, startr, map(listLen, ws))\n  tile(ws, [map(x => len_tl(last_(fst3(x))), zs), thd3(head(zs))])\n\nfun fmt(x) = unparse(map(par3, concat(parse(x))))\n\nval test = \n  concat of\n    nofibStringToList(\"In the constructive programming community it is commonplace to see \") ::\n    nofibStringToList(\"formal developments of textbook algorithms. In the algorithm design \") ::\n    nofibStringToList(\"community, on the other hand, it may be well known that the textbook \") ::\n    nofibStringToList(\"solution to a problem is not the most efficient possible. However, in \") ::\n    nofibStringToList(\"presenting the more efficient solution, the algorithm designer will \") ::\n    nofibStringToList(\"usually omit some of the implementation details, this creating an \") ::\n    nofibStringToList(\"algorithm gap between the abstract algorithm and its concrete \") ::\n    nofibStringToList(\"implementation. This is in contrast to the formal development, which \") ::\n    nofibStringToList(\"usually presents the complete concrete implementation of the less \") ::\n    nofibStringToList(\"efficient solution.\\n\\n\") :: Nil\n//│ test = [\"I\",\"n\",\" \",\"t\",\"h\",\"e\",\" \",\"c\",\"o\",\"n\",\"s\",\"t\",\"r\",\"u\",\"c\",\"t\",\"i\",\"v\",\"e\",\" \",\"p\",\"r\",\"o\",\"g\",\"r\",\"a\",\"m\",\"m\",\"i\",\"n\",\"g\",\" \",\"c\",\"o\",\"m\",\"m\",\"u\",\"n\",\"i\",\"t\",\"y\",\" \",\"i\",\"t\",\" \",\"i\",\"s\",\" \",\"c\",\"o\",\"m\",\"m\",\"o\",\"n\",\"p\",\"l\",\"a\",\"c\",\"e\",\" \",\"t\",\"o\",\" \",\"s\",\"e\",\"e\",\" \",\"f\",\"o\",\"r\",\"m\",\"a\",\"l\",\" \",\"d\",\"e\",\"v\",\"e\",\"l\",\"o\",\"p\",\"m\",\"e\",\"n\",\"t\",\"s\",\" \",\"o\",\"f\",\" \",\"t\",\"e\",\"x\",\"t\",\"b\",\"o\",\"o\",\"k\",\" \",\"a\",\"l\",\"g\",\"o\",\"r\",\"i\",\"t\",\"h\",\"m\",\"s\",\".\",\" \",\"I\",\"n\",\" \",\"t\",\"h\",\"e\",\" \",\"a\",\"l\",\"g\",\"o\",\"r\",\"i\",\"t\",\"h\",\"m\",\" \",\"d\",\"e\",\"s\",\"i\",\"g\",\"n\",\" \",\"c\",\"o\",\"m\",\"m\",\"u\",\"n\",\"i\",\"t\",\"y\",\",\",\" \",\"o\",\"n\",\" \",\"t\",\"h\",\"e\",\" \",\"o\",\"t\",\"h\",\"e\",\"r\",\" \",\"h\",\"a\",\"n\",\"d\",\",\",\" \",\"i\",\"t\",\" \",\"m\",\"a\",\"y\",\" \",\"b\",\"e\",\" \",\"w\",\"e\",\"l\",\"l\",\" \",\"k\",\"n\",\"o\",\"w\",\"n\",\" \",\"t\",\"h\",\"a\",\"t\",\" \",\"t\",\"h\",\"e\",\" \",\"t\",\"e\",\"x\",\"t\",\"b\",\"o\",\"o\",\"k\",\" \",\"s\",\"o\",\"l\",\"u\",\"t\",\"i\",\"o\",\"n\",\" \",\"t\",\"o\",\" \",\"a\",\" \",\"p\",\"r\",\"o\",\"b\",\"l\",\"e\",\"m\",\" \",\"i\",\"s\",\" \",\"n\",\"o\",\"t\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"s\",\"t\",\" \",\"e\",\"f\",\"f\",\"i\",\"c\",\"i\",\"e\",\"n\",\"t\",\" \",\"p\",\"o\",\"s\",\"s\",\"i\",\"b\",\"l\",\"e\",\".\",\" \",\"H\",\"o\",\"w\",\"e\",\"v\",\"e\",\"r\",\",\",\" \",\"i\",\"n\",\" \",\"p\",\"r\",\"e\",\"s\",\"e\",\"n\",\"t\",\"i\",\"n\",\"g\",\" \",\"t\",\"h\",\"e\",\" \",\"m\",\"o\",\"r\",\"e\",\" \",\"e\",\"f\",\"f\",\"i\",\"c\",\"i\",\"e\",\"n\",\"t\",\" \",\"s\",\"o\",\"l\",\"u\",\"t\",\"i\",\"o\",\"n\",\",\",\" \",\"t\",\"h\",\"e\",\" \",\"a\",\"l\",\"g\",\"o\",\"r\",\"i\",\"t\",\"h\",\"m\",\" \",\"d\",\"e\",\"s\",\"i\",\"g\",\"n\",\"e\",\"r\",\" \",\"w\",\"i\",\"l\",\"l\",\" \",\"u\",\"s\",\"u\",\"a\",\"l\",\"l\",\"y\",\" \",\"o\",\"m\",\"i\",\"t\",\" \",\"s\",\"o\",\"m\",\"e\",\" \",\"o\",\"f\",\" \",\"t\",\"h\",\"e\",\" \",\"i\",\"m\",\"p\",\"l\",\"e\",\"m\",\"e\",\"n\",\"t\",\"a\",\"t\",\"i\",\"o\",\"n\",\" \",\"d\",\"e\",\"t\",\"a\",\"i\",\"l\",\"s\",\",\",\" \",\"t\",\"h\",\"i\",\"s\",\" \",\"c\",\"r\",\"e\",\"a\",\"t\",\"i\",\"n\",\"g\",\" \",\"a\",\"n\",\" \",\"a\",\"l\",\"g\",\"o\",\"r\",\"i\",\"t\",\"h\",\"m\",\" \",\"g\",\"a\",\"p\",\" \",\"b\",\"e\",\"t\",\"w\",\"e\",\"e\",\"n\",\" \",\"t\",\"h\",\"e\",\" \",\"a\",\"b\",\"s\",\"t\",\"r\",\"a\",\"c\",\"t\",\" \",\"a\",\"l\",\"g\",\"o\",\"r\",\"i\",\"t\",\"h\",\"m\",\" \",\"a\",\"n\",\"d\",\" \",\"i\",\"t\",\"s\",\" \",\"c\",\"o\",\"n\",\"c\",\"r\",\"e\",\"t\",\"e\",\" \",\"i\",\"m\",\"p\",\"l\",\"e\",\"m\",\"e\",\"n\",\"t\",\"a\",\"t\",\"i\",\"o\",\"n\",\".\",\" \",\"T\",\"h\",\"i\",\"s\",\" \",\"i\",\"s\",\" \",\"i\",\"n\",\" \",\"c\",\"o\",\"n\",\"t\",\"r\",\"a\",\"s\",\"t\",\" \",\"t\",\"o\",\" \",\"t\",\"h\",\"e\",\" \",\"f\",\"o\",\"r\",\"m\",\"a\",\"l\",\" \",\"d\",\"e\",\"v\",\"e\",\"l\",\"o\",\"p\",\"m\",\"e\",\"n\",\"t\",\",\",\" \",\"w\",\"h\",\"i\",\"c\",\"h\",\" \",\"u\",\"s\",\"u\",\"a\",\"l\",\"l\",\"y\",\" \",\"p\",\"r\",\"e\",\"s\",\"e\",\"n\",\"t\",\"s\",\" \",\"t\",\"h\",\"e\",\" \",\"c\",\"o\",\"m\",\"p\",\"l\",\"e\",\"t\",\"e\",\" \",\"c\",\"o\",\"n\",\"c\",\"r\",\"e\",\"t\",\"e\",\" \",\"i\",\"m\",\"p\",\"l\",\"e\",\"m\",\"e\",\"n\",\"t\",\"a\",\"t\",\"i\",\"o\",\"n\",\" \",\"o\",\"f\",\" \",\"t\",\"h\",\"e\",\" \",\"l\",\"e\",\"s\",\"s\",\" \",\"e\",\"f\",\"f\",\"i\",\"c\",\"i\",\"e\",\"n\",\"t\",\" \",\"s\",\"o\",\"l\",\"u\",\"t\",\"i\",\"o\",\"n\",\".\",\"\\n\",\"\\n\"]\n\nfun testPara_nofib() =\n  if null_(test) then Nil else fmt(test)\n\nfun main() = nofibListToString(testPara_nofib())\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/power.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule power with ...\n\n\n\nabstract class Pss[T]: Pz | Pc[T]\n\ntype Ps[T] = Lazy[Pss[T]]\n\ndata class Pc[T](f: T, s: Ps[T]) extends Pss[T]\n\nobject Pz extends Pss\n\nfun list() = lazy of () => Pc(1, list())\n\nfun x_() = lazy of () => Pc(0, lazy of () => Pc(1, lazy of () => Pz))\n\nfun fromIntegerPs(c) = if\n  c == 0 then lazy of () => Pz\n  else lazy of () => Pc(c, lazy of () => Pz)\n\nfun extract(n, ps) = if\n  n == 0 then Nil\n  force(ps) is\n    Pz then Nil\n    Pc(x, ps) then x :: extract(n - 1, ps)\n\nfun dotMult(c, ps) = lazy of () => if force(ps) is\n  Pz then Pz\n  Pc(f, fs_) then Pc(c * f, dotMult(c, fs_))\n\nfun dotMultSndLz(c, ps) = lazy of () => if force(force(ps)) is\n  Pz then Pz\n  Pc(f, fs_) then Pc(c * f, dotMult(c, fs_))\n\nfun negatePs(ps) = lazy of () => if force(ps) is\n  Pz then Pz\n  Pc(f, fs_) then Pc(-f, negatePs(fs_))\n\nfun addPs(fss, gs) = lazy of () => if force(fss) is\n  Pz then force(gs)\n  Pc(f, fs_) and force(gs) is\n    Pz then force(fss)\n    Pc(g, gs) then Pc(f+g, addPs(fs_, gs))\n\nfun minusPs(a, b) = addPs(a, negatePs(b))\n\nfun multPs(fss, gss) = lazy of () => if force(fss) is\n  Pz then Pz\n  Pc(f, fs_) and force(gss) is\n    Pz then Pz\n    Pc(g, gs) then Pc(f*g, addPs(addPs(dotMult(f, gs), dotMult(g, fs_)), multPs(multPs(x_(), fs_), gs)))\n\nfun multPsFstLz(fss, gss) = lazy of () => if force(force(fss)) is\n  Pz then Pz\n  Pc(f, fs_) and force(gss) is\n    Pz then Pz\n    Pc(g, gs) then Pc(f*g, addPs(addPs(dotMult(f, gs), dotMult(g, fs_)), multPs(multPs(x_(), fs_), gs)))\n\nfun powerPs(a, n) = if n <= 0 then fromIntegerPs(1) else multPs(a, powerPs(a, n - 1))\n\nfun divPs(fss, gss) = lazy of () => if force(fss) is\n  Pz and force(gss) is\n    Pz then throw Error(\"power series 0/0\")\n    Pc(0, gs) then force(divPs((lazy of () => Pz), gs))\n    else Pz\n  Pc(0, fs_) and force(gss) is\n    Pc(0, gs) then force(divPs(fs_, gs))\n    Pc(g, gs) then\n      let q = 0\n      Pc(q, divPs(addPs(fs_, negatePs(dotMult(q, gs))), lazy of () => Pc(g, gs)))\n  Pc(f, fs_) and force(gss) is\n    Pc(g, gs) then\n      let q = f/g\n      Pc(q, divPs(addPs(fs_, negatePs(dotMult(q, gs))), lazy of () => Pc(g, gs)))\n\nfun compose_(fss, gss) = lazy of () => if force(fss) is\n  Pz then Pz\n  Pc(f, fs_) and force(gss) is\n    Pz then Pc(f, lazy of () => Pz)\n    Pc(0, gs) then Pc(f, multPs(gs, compose_(fs_, lazy of () => Pc(0, gs))))\n    else force(addPs((lazy of () => Pc(f, lazy of () => Pz)), multPs(gss, compose_(fs_, gss))))\n\nfun composeSndLz_(fss, gss) = lazy of () => if force(fss) is\n  Pz then Pz\n  Pc(f, fs_) and force(force(gss)) is\n    Pz then Pc(f, lazy of () => Pz)\n    Pc(0, gs) then Pc(f, multPs(gs, compose_(fs_, lazy of () => Pc(0, gs))))\n    else force(addPs((lazy of () => Pc(f, lazy of () => Pz)), multPs(gss, composeSndLz_(fs_, gss))))\n\nfun revert(fss) = lazy of () => if force(fss) is\n  Pc(0, fs_) then\n    fun rs() = lazy of () => Pc(0, divPs(fromIntegerPs(1), compose_(fs_, rs())))\n    force(rs())\n  Pc(f0, kss) and force(kss) is Pc(f1, gss) and force(gss) is Pz then\n    Pc(-1/f1, lazy of () => Pc(1/f1, lazy of () => Pz))\n\nfun deriv(fss) = lazy of () => if force(fss) is\n  Pz then Pz\n  Pc(_, fs_) then\n    fun deriv1(gss, n) = lazy of () => if force(gss) is\n      Pz then Pz\n      Pc(f, fs_) then Pc(n * f, deriv1(fs_, n+1))\n    force(deriv1(fs_, 1))\n\nfun integral(fs_) =\n  fun int1(fss, n) = lazy of () => if force(fss) is\n    Pz then Pz\n    Pc(f, fs_) then Pc(f/n, int1(fs_, n + 1))\n\n  lazy of () => Pc(0, int1(fs_, 1))\n\n\nfun integralLz(fs_) =\n  fun int1(fss, n) = lazy of () => if force(fss) is\n    Pz then Pz\n    Pc(f, fs_) then Pc(f/n, int1(fs_, n + 1))\n\n  lazy of () => Pc(0, int1(fs_(), 1))\n\n\nfun sqrtPs(fss) = lazy of () => if force(fss) is\n  Pz then Pz\n  Pc(0, gss) and force(gss) is Pc(0, fs_) then Pc(0, sqrtPs(fs_))\n  Pc(1, fs_) then\n    fun qs() = lazy of () => addPs(fromIntegerPs(1), integral(divPs(deriv(lazy of () => Pc(1, fs_)), dotMultSndLz(2, qs()))))\n\n    force(force(qs()))\n\nfun ts() = lazy of () => Pc(1, multPs(ts(), ts()))\n\nfun tree() = lazy of () => Pc(0, composeSndLz_(list(), lazy of () => tree()))\n\nfun cosx() = minusPs((lazy of () => Pc(1, lazy of () => Pz)), integral(integralLz(cosx)))\n\nfun sinx() = integral(minusPs((lazy of () => Pc(1, lazy of () => Pz)), integralLz(sinx)))\n\nfun testPower_nofib(p) =\n  extract(p, minusPs(sinx(), sqrtPs(minusPs(fromIntegerPs(1), powerPs(cosx(), 2)))));\n  extract(p, minusPs(divPs(sinx(), cosx()), revert(integral(divPs(fromIntegerPs(1), addPs(fromIntegerPs(1), powerPs(x_(), 2)))))));\n  extract(p, ts());\n  extract(p, tree())\n\nfun main() = testPower_nofib(14).toString()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/pretty.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule pretty with ...\n\n\n\nabstract class CSeq: CNil | CAppend | CIndent | CNewline | CStr | CCh\n\ndata\n  class\n    CAppend(a: CSeq, b: CSeq) extends CSeq\n    CIndent(a: Int, b: CSeq) extends CSeq\n    CStr(a: List[Char]) extends CSeq\n    CCh(a: Char) extends CSeq\n\nobject\n  CNil extends CSeq\n  CNewline extends CSeq\n\nabstract class PprStyle: PprForUser | PprDebug | PprShowAll | PprInterface\n\nobject\n  PprForUser extends PprStyle\n  PprDebug extends PprStyle\n  PprShowAll extends PprStyle\n  PprInterface extends PprStyle\n\nval cNil = CNil\n//│ cNil = CNil\n\nval cNL = CNewline\n//│ cNL = CNewline\n\nfun cAppend(cs1, cs2) = CAppend(cs1, cs2)\n\nfun cIndent(n, cs) = CIndent(n, cs)\n\nfun cStr(s) = CStr(s)\n\nfun cCh(c) = CCh(c)\n\nfun mkIndent(n, s) = if n\n  === 0 then s\n  >= 8 then \"\\t\" :: mkIndent(n - 8, s)\n  else \" \" :: mkIndent(n - 1, s)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun flattenS(nlp, seqs) = if seqs is\n  Nil then Nil\n  [col, seq] :: seqs then flatten(col, nlp, seq, seqs)\n\nfun flatten(n, nlp, cseq, seqs) = if cseq is\n  CNil then flattenS(nlp, seqs)\n  CAppend(seq1, seq2) then flatten(n, nlp, seq1, [n, seq2] :: seqs)\n  CIndent(n_, seq) then flatten(n_ + n, nlp, seq, seqs)\n  CNewline then \"\\n\" :: flattenS(true, seqs)\n  CStr(s) and\n    nlp then mkIndent(n, s +: flattenS(false, seqs))\n    else s +: flattenS(false, seqs)\n  CCh(c) and\n    nlp then mkIndent(n, c :: flattenS(false, seqs))\n    else c :: flattenS(false, seqs)\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun cShow(seq) = flatten(0, true, seq, Nil)\n\ndata class MkPrettyRep(cseq: CSeq, n: Int, b1: Bool, b2: Bool)\n\nfun ppShow(width, p) = if p(width, false) is\n  MkPrettyRep(seq, ll, emp, sl) then cShow(seq)\n\nfun ppUnformatted(p) = if p(80, false) is\n  MkPrettyRep(seq, ll, emp, sl) then cShow(seq)\n\nfun ppNil(width, is_vert) = MkPrettyRep(cNil, 0, true, width >= 0)\n\nfun ppStr(s, width, is_vert) =\n  let ls = listLen(s)\n  MkPrettyRep(cStr(s), ls, false, width >= ls)\n\nfun ppChar(c, width, is_vert) = MkPrettyRep(cCh(c), 1, false, width >= 1)\n\nfun ppInt(n, width, is_vert) = ppStr(nofibStringToList(stringOfInt(n)), width, is_vert)\n\nfun pp_SP(a, b) = ppStr(nofibStringToList(\", \"), a, b)\n\nfun ppSP(a, b) = ppChar(\" \", a, b)\n\nfun ppLbrack(a, b) = ppChar(\"[\", a, b)\n\nfun ppRbrack(a, b) = ppChar(\"]\", a, b)\n\nfun ppLparen(a, b) = ppChar(\"(\", a, b)\n\nfun ppRparen(a, b) = ppChar(\")\", a, b)\n\nfun ppSemi(a, b) = ppChar(\";\", a, b)\n\nfun ppComma(a, b) = ppChar(\",\", a, b)\n\nfun andL(a, b) = if a then b else false\n\nfun orL(a, b) = if a then true else b\n\nfun ppBeside(p1, p2, width, is_vert) = if p1(width, false) is\n  MkPrettyRep(seq1, ll1, emp1, sl1) and p2(width - ll1, false) is\n    MkPrettyRep(seq2, ll2, emp2, sl2) then\n      MkPrettyRep(cAppend(seq1, cIndent(ll1, seq2)), ll1 + ll2, andL(emp1, emp2), andL(width >= 0, andL(sl1, sl2)))\n\nfun ppBesides(ps) = if ps is\n  Nil then ppNil\n  else foldr1((a, b) => (c, d) => ppBeside(a, b, c, d), ps)\n\nfun ppBesideSP(p1, p2, width, is_vert) = if p1(width, false) is MkPrettyRep(seq1, ll1, emp1, sl1) then\n  let li = if emp1 then 0 else ll1 + 1\n  if p2(width - li, false) is MkPrettyRep(seq2, ll2, emp2, sl2) then\n    let wi = if emp1 then 0 else 1\n    let sp = if orL(emp1, emp2) then cNil else cCh(\" \")\n    MkPrettyRep(cAppend(seq1, cAppend(sp, cIndent(li, seq2))), li + ll2, andL(emp1, emp2), andL(width >= wi, andL(sl1, sl2)))\n\nfun ppCat(ps) = if ps is Nil then ppNil else foldr1((a, b) => (c, d) => ppBesideSP(a, b, c, d), ps)\n\nfun ppAbove(p1, p2, width, is_vert) = if p1(width, true) is\n  MkPrettyRep(seq1, ll1, emp1, sl1) and p2(width, true) is\n    MkPrettyRep(seq2, ll2, emp2, sl2) then\n      let nl = if orL(emp1, emp2) then cNil else cNL\n      MkPrettyRep(cAppend(seq1, cAppend(nl, seq2)), ll2, andL(emp1, emp2), false)\n\nfun ppAboves(ps, a, b) = if ps is Nil then ppNil(a, b) else foldr1((a, b) => (c, d) => ppAbove(a, b, c, d), ps)(a, b)\n\nfun ppNest(n, p, width, is_vert) = if\n  is_vert and p(width - n, true) is MkPrettyRep(seq, ll, emp, sl) then\n    MkPrettyRep(cIndent(n, seq), ll + n, emp, sl)\n  else p(width, false)\n\nfun ppHang(p1, n, p2, width, is_vert) = if p1(width, false) is\n  MkPrettyRep(seq1, ll1, emp1, sl1) and p2(width - (ll1 + 1), false) is\n    MkPrettyRep(seq2, ll2, emp2, sl2) and p2(width - n, false) is\n      MkPrettyRep(seq2_, ll2_, emp2_, sl2_) and\n        emp1 then p2(width, is_vert)\n        orL(ll1 <= n, sl2) then\n          MkPrettyRep(cAppend(seq1, cAppend(cCh(\" \"), cIndent(ll1 + 1, seq2))), ll1 + 1 + ll2, false, andL(sl1, sl2))\n        else MkPrettyRep(cAppend(seq1, cAppend(cNL, cIndent(n, seq2_))), ll2_, false, false)\n\nfun testPretty_nofib() =\n  fun pp_word(a, b) = ppStr(nofibStringToList(\"xxxxx\"), a, b)\n  let pp_words = replicate(50, pp_word)\n  fun pretty_stuff(a, b) = ppAboves(\n    ppBesides(((a, b) => ppInt(-42, a, b)) :: ((a, b) => ppChar(\"@\", a, b)) :: ((a, b) => ppStr(nofibStringToList(\"This is a string\"), a, b)) :: Nil) ::\n    ((a, b) => pp_SP(a, b)) ::\n    ((a, b) => ppHang(\n      (a, b) => ppStr(nofibStringToList(\"This is the label\"), a, b),\n      8,\n      ppCat(pp_words),\n      a,\n      b\n    )) ::\n    Nil,\n    a,\n    b\n  )\n  ppShow(80, pretty_stuff) +: nofibStringToList(\"\\n\")\n\nfun main() = nofibListToString(testPretty_nofib())\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/primetest.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule primetest with ...\n\n\n\nfun even(x) = intMod(x, 2) == 0\n\nfun int_val_of_char(x) = int_of_char(x) - 48\n\nfun int_val_of_string(s) =\n  fun f(l, a) = if l is\n    Nil then a\n    h :: t then f(t, 10 * a + int_val_of_char(h))\n  f(s, 0)\n\nfun break_(p, ls) = if ls is\n  Nil then [Nil, Nil]\n  x :: xs and\n    p(x) then [Nil, x :: xs]\n    break_(p, xs) is [ys, zs] then [x :: ys, zs]\n\nfun lines(s) = if break_(x => x == \"|\", s) is [l, s_] then\n  let tt = if s_ is\n    Nil then Nil\n    _ :: s__ then lines(s__)\n\n  l :: tt\n\n\nfun makeNumber(b, ls) = foldl((a, x) => a * b + x, 0, ls)\n\nfun chop(b, n) =\n  fun chop_(a, n) = if divMod(n, b) is [q, r] and\n    n == 0 then a\n    else chop_(r :: a, q)\n\n  chop_(Nil, n)\n\n\nfun powerMod(a, b, m) =\n  fun f(a, b, c) =\n    fun g(a, b) = if even(b) then g(intMod(a * a, m), intDiv(b, 2)) else f(a, b - 1, intMod(a * c, m))\n    if b == 0 then c else g(a, b)\n\n  if\n    b == 0 then 1\n    let a_ = intMod(a, m)\n    else f(a_, b - 1, a_)\n\n\nfun log2(x) = listLen(chop(2, x))\n\nfun rands(s1, s2) =\n  let k    = intDiv(s1, 53668)\n  let s1_  = ((40014 * (s1 - (k * 53668))) - (k * 12211))\n  let s1__ = (if s1_ < 0 then s1_ + 2147483563 else s1_)\n  let k_   = intDiv(s2, 52774)\n  let s2_  = ((40692 * (s2 - (k_ * 52774))) - (k_ * 3791))\n  let s2__ = (if s2_ < 0 then s2_ + 2147483399 else s2_)\n  let z    = (s1__ - s2__)\n\n  if z < 1 then lazy of () => LzCons(z + 2147483562, rands(s1__, s2__))\n  else lazy of () => LzCons(z, rands(s1__, s2__))\n\n\nfun randomInts(s1, s2) =\n  if (1 <= s1) and (s1 <= 2147483562) and (1 <= s2) and (s2 <= 2147483398) then rands(s1, s2)\n\nfun findKQ(n) =\n  fun f(k, q) = if divMod(q, 2) is [d, r] and\n    r == 0 then f(k + 1, d)\n    else [k, q]\n\n  f(0, n - 1)\n\n\nfun uniform(nns, rrs) = if\n  nns is n :: Nil and rrs is r :: rs then intMod(r, n) :: Nil\n  nns is n :: ns and rrs is r :: rs and\n    let t = intMod(r, n + 1)\n    t == n then t :: uniform(ns, rs)\n    else t :: map(x => intMod(x, 65536), rs)\n\nfun random(n, rs) =\n  let ns = chop(65536, n)\n  if splitAt_lz(listLen(ns), rs) is [rs1, rs2] then [makeNumber(65536, uniform(ns, rs1)), rs2]\n\nfun singleTestX(n, kq, x) =\n  fun square(x) = intMod(x * x, n)\n\n  fun witness(ls) = if ls is\n    Nil then false\n    t :: ts and\n      t == (n - 1) then true\n      t == 1 then false\n      else witness(ts)\n\n  if kq is [k, q] and take_lz(k, iterate(square, powerMod(x, q, n))) is t :: ts then\n    (t == 1) || (t == (n - 1)) || witness(ts)\n\n\nfun singleTest(n, kq, rs) = if random(n - 2, rs) is [x, rs_] then\n  [singleTestX(n, kq, 2 + x), rs_]\n\nfun multiTest(k, rs, n) =\n  fun mTest(k, rs) = if\n    k == 0 then [true, rs]\n    singleTest(n, findKQ(n), rs) is [t, rs_] and\n      t then mTest(k - 1, rs_)\n      else [false, rs_]\n\n  if ((n <= 1) || even(n)) then [n==2, rs] else mTest(k, rs)\n\n\nfun doLine(cs, cont, rs) =\n  let n = int_val_of_string(cs)\n  if multiTest(100, rs, n) is [t, rs_] and\n    t then \"Probably prime\" :: (cont(rs_))\n    else \"Composite\" :: (cont(rs_))\n\nfun doInput(state, lls) = if lls is\n  Nil then Nil\n  l :: ls then doLine(l, state => doInput(state, ls), state)\n\nfun process(process_arg1) = doInput(randomInts(111, 47), process_arg1)\n\nfun testPrimetest_nofib(d) =\n  let cts = nofibStringToList(\"24|48|47|1317|8901\")\n  process(lines(cts))\n\n\nfun main() = testPrimetest_nofib(0).toString()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/puzzle.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule puzzle with ...\n\n\nabstract class ItemType: Bono | Edge | Larry | Adam\n\nobject\n  Bono extends ItemType\n  Edge extends ItemType\n  Larry extends ItemType\n  Adam extends ItemType\n\nfun itemEq(a, b) = if a is\n  Bono and b is Bono then true\n  Edge and b is Edge then true\n  Larry and b is Larry then true\n  Adam and b is Adam then true\n  else false\n\nfun succItem(i) = if i is\n  Bono then Edge\n  Edge then Larry\n  Larry then Adam\n\nfun isEnd(i) = if i is\n  Bono then false\n  Edge then false\n  Larry then false\n  Adam then true\n\nfun itemFromTo(a, b) = if itemEq(a, b) then a :: Nil else a :: itemFromTo(succItem(a), b)\n\nabstract class BankType: LeftBank | RightBank\n\nobject\n  LeftBank extends BankType\n  RightBank extends BankType\n\nfun bankEq(a, b) = if a is\n  LeftBank and b is LeftBank then true\n  RightBank and b is RightBank then true\n  else false\n\ndata class State(b: BankType, e: BankType, l: BankType, a: BankType)\n\nfun stateEq(s1, s2) = if s1 is State(a, b, c, d) and s2 is State(e, f, g, h) then\n  (bankEq(a, e) && bankEq(b, f) && bankEq(c, g) && bankEq(d, h))\n\nfun bonoPos(s) = if s is State(a, b, c, d) then a\n\nfun edgePos(s) = if s is State(a, b, c, d) then b\n\nfun larryPos(s) = if s is State(a, b, c, d) then c\n\nfun adamPos(s) = if s is State(a, b, c, d) then d\n\nval initialState = State(LeftBank, LeftBank, LeftBank, LeftBank)\n//│ initialState = State(LeftBank, LeftBank, LeftBank, LeftBank)\n\nval finalState = State(RightBank, RightBank, RightBank, RightBank)\n//│ finalState = State(RightBank, RightBank, RightBank, RightBank)\n\nfun position(i, s) = if i is\n  Bono then bonoPos(s)\n  Edge then edgePos(s)\n  Larry then larryPos(s)\n  Adam then adamPos(s)\n\nfun updateState(s, i, pos) = if s is State(a, b, c, d) and i is\n  Bono then State(pos, b, c, d)\n  Edge then State(a, pos, c, d)\n  Larry then State(a, b, pos, d)\n  Adam then State(a, b, c, pos)\n\nfun opposite(b) = if b is\n  LeftBank then RightBank\n  RightBank then LeftBank\n\nfun notSeen(state, states) =\n  all(case { [_, s] then not(stateEq(state, s)) }, states)\n\nfun writeItem(i, b, rest) = if i is\n  Bono and b is LeftBank then nofibStringToList(\"    Bono |                    |\\n\") +: rest\n  Edge and b is LeftBank then nofibStringToList(\"The Edge |                    |\\n\") +: rest\n  Larry and b is LeftBank then nofibStringToList(\"   Larry |                    |\\n\") +: rest\n  Adam and b is LeftBank then nofibStringToList(\"    Adam |                    |\\n\") +: rest\n  Bono and b is RightBank then nofibStringToList(\"         |                    | Bono\\n\") +: rest\n  Edge and b is RightBank then nofibStringToList(\"         |                    | The Edge\\n\") +: rest\n  Larry and b is RightBank then nofibStringToList(\"         |                    | Larry\\n\") +: rest\n  Adam and b is RightBank then nofibStringToList(\"         |                    | Adam\\n\") +: rest\n\nfun writeState(state, s) =\n  nofibStringToList(\"----------------------------------------\\n\") +:\n  writeItem of\n    Bono\n    bonoPos(state)\n    writeItem of\n      Edge\n      edgePos(state)\n      writeItem of\n        Larry\n        larryPos(state)\n        writeItem of\n          Adam\n          adamPos(state)\n          nofibStringToList(\"----------------------------------------\\n\") +: s\n\nfun totalTime(history) = if history is [time, _] :: _ then time\n\nfun writeHistory(history, x) = if history is\n  Nil then x\n  else\n    foldr(\n      (timestate, acc) => (s) => if timestate is [time, state] then\n        nofibStringToList(\"Time: \") +: nofibStringToList(stringOfInt(totalTime(history) - time)) +: (\"\\n\" :: writeState(state, acc(s))),\n      x => x,\n      history\n    )(x)\n\nfun writeSolutions(solutions, count, s) = if solutions is\n  Nil then s\n  item :: next then\n    nofibStringToList(\"Solution \") +:\n    nofibStringToList(stringOfInt(count)) +:\n    \"\\n\" :: writeHistory(item, writeSolutions(next, count + 1, s))\n\nfun minSolutions(history) = if history is\n  Nil then Nil\n  history :: next then\n    // @tailrec // TODO\n    fun minAcc(minSoFar, mins, ls) = if ls is\n      Nil then mins\n      history :: next then\n        let total = totalTime(history)\n        if\n          minSoFar < total then minAcc(minSoFar, mins, next)\n          minSoFar === total then minAcc(minSoFar, history :: mins, next)\n          else minAcc(total, history :: Nil, next)\n    reverse(minAcc(totalTime(history), history :: Nil, next))\n\nfun u2times(i) = if i is\n  Bono then 10\n  Edge then 5\n  Larry then 2\n  Adam then 1\n\nfun transfer(source, dest, location, countdown, history) =\n  if stateEq(source, dest) then ([countdown, dest] :: history) :: Nil\n  else\n    let newHistory = [countdown, dest] :: history\n    let newLocation = opposite(location)\n    fun lscomp1(ls) = if ls is\n      Nil then Nil\n      item :: xs then\n        if bankEq(position(item, dest), location) then\n          let newDest = updateState(dest, item, newLocation)\n          if notSeen(newDest, history) then\n            let newTime = countdown + u2times(item)\n            transfer(source, newDest, newLocation, newTime, newHistory) :: lscomp1(xs)\n          else lscomp1(xs)\n        else lscomp1(xs)\n    let moveOne = concat(lscomp1(itemFromTo(Bono, Adam)))\n    fun lscomp2(ls) = if ls is\n      Nil then Nil\n      i :: xs then\n        fun lscomp3(ls) = if ls is\n          Nil then lscomp2(xs)\n          j :: ys then\n            if bankEq(position(i, dest), location) and bankEq(position(j, dest), location) then\n              let newDest = updateState(updateState(dest, i, newLocation), j, newLocation)\n              if notSeen(newDest, history) then\n                let newTime = countdown + u2times(i)\n                transfer(source, newDest, newLocation, newTime, newHistory) :: lscomp3(ys)\n              else lscomp3(ys)\n            else lscomp3(ys)\n        lscomp3(itemFromTo(succItem(i), Adam))\n    let moveTwo = concat(lscomp2(itemFromTo(Bono, Larry)))\n    moveOne +: moveTwo\n\nfun testPuzzle_nofib(x) =\n  let time = if listLen(x) === 1 then 0 else throw Error(\"puzzle expects exactly one argument\")\n  let solutions = transfer(initialState, finalState, RightBank, time, Nil)\n  let mins = minSolutions(solutions)\n  writeSolutions(mins, 1, Nil)\n\nfun main() = nofibListToString(testPuzzle_nofib(2 :: Nil))\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/rsa.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule rsa with ...\n\n\n\nfun z_of_int(x) = globalThis.BigInt(x)\nfun string_of_z(x) = nofibStringToList(x + \"\")\nfun z_add(x, y) = x + y\nfun z_mul(x, y) = x * y\nfun z_sub(x, y) = x - y\nfun z_div(x, y) = x / y\nfun z_mod(x, y) = x % y\nfun z_equal(x, y) = x === y\nfun z_sqr(x) = x * x\nfun int_if_char(c) = c.codePointAt(0)\n\nval const0 = z_of_int(0)\n//│ const0 = 0\n\nval const31 = z_of_int(31)\n//│ const31 = 31\n\nval const1 = z_of_int(1)\n//│ const1 = 1\n\nval const2 = z_of_int(2)\n//│ const2 = 2\n\nval const128 = z_of_int(128)\n//│ const128 = 128\n\nfun hash(str) = foldl of\n  (acc, c) => z_add(z_of_int(int_if_char(c)), z_mul(acc, const31))\n  const0\n  str\n\nfun and_(ls) = if ls is\n  Nil then true\n  h :: t and\n    h then and_(t)\n    else false\n\nfun unlines(ls) = concat of map(l => l +: (\"\\n\" :: Nil), ls)\n\nfun even(a) = z_mod(a, const2) === const0\n\nfun code(ls) = foldl of\n  (x, y) => z_add(z_mul(const128, x), z_of_int(int_if_char(y)))\n  const0\n  ls\n\nfun collect(n, xs) = if\n  n === 0 then Nil\n  xs is Nil then Nil\n  else take(n, xs) :: collect(n, leave(n, xs))\n\nfun size(n) = intDiv(listLen(string_of_z(n)) * 47, 100)\n\nfun encrypt(n, e, s) = unlines of map of\n  c => string_of_z(power(e, n, code(c)))\n  collect(size(n), s)\nfun power(n, m, x) = if\n  z_equal(n, const0) then const1\n  even(n) then z_mod(z_sqr(power(z_div(n, const2), m, x)), m)\n  else z_mod(z_mul(x, power(z_sub(n, const1), m, x)), m)\n\nval intput = nofibStringToList of fs.readFileSync(\"./hkmc2/shared/src/test/mlscript/nofib/input/rsa.faststdin\").toString()\n//│ intput = [\"m\",\"o\",\"d\",\"u\",\"l\",\"e\",\" \",\"R\",\"s\",\"a\",\" \",\"(\",\"e\",\"n\",\"c\",\"r\",\"y\",\"p\",\"t\",\",\",\" \",\"d\",\"e\",\"c\",\"r\",\"y\",\"p\",\"t\",\",\",\" \",\"m\",\"a\",\"k\",\"e\",\"K\",\"e\",\"y\",\"s\",\")\",\"\\n\",\"w\",\"h\",\"e\",\"r\",\"e\",\"\\n\",\"\\n\",\"\\n\",\"e\",\"n\",\"c\",\"r\",\"y\",\"p\",\"t\",\",\",\" \",\"d\",\"e\",\"c\",\"r\",\"y\",\"p\",\"t\",\" \",\":\",\":\",\" \",\"I\",\"n\",\"t\",\"e\",\"g\",\"e\",\"r\",\" \",\"-\",\">\",\" \",\"I\",\"n\",\"t\",\"e\",\"g\",\"e\",\"r\",\" \",\"-\",\">\",\" \",\"S\",\"t\",\"r\",\"i\",\"n\",\"g\",\" \",\"-\",\">\",\" \",\"S\",\"t\",\"r\",\"i\",\"n\",\"g\",\"\\n\",\"e\",\"n\",\"c\",\"r\",\"y\",\"p\",\"t\",\" \",\"n\",\" \",\"e\",\" \",\"=\",\" \",\"u\",\"n\",\"l\",\"i\",\"n\",\"e\",\"s\",\" \",\".\",\" \",\"m\",\"a\",\"p\",\" \",\"(\",\"s\",\"h\",\"o\",\"w\",\" \",\".\",\" \",\"p\",\"o\",\"w\",\"e\",\"r\",\" \",\"e\",\" \",\"n\",\" \",\".\",\" \",\"c\",\"o\",\"d\",\"e\",\")\",\" \",\".\",\" \",\"c\",\"o\",\"l\",\"l\",\"e\",\"c\",\"t\",\" \",\"(\",\"s\",\"i\",\"z\",\"e\",\" \",\"n\",\")\",\"\\n\",\"d\",\"e\",\"c\",\"r\",\"y\",\"p\",\"t\",\" \",\"n\",\" \",\"d\",\" \",\"=\",\" \",\"c\",\"o\",\"n\",\"c\",\"a\",\"t\",\" \",\".\",\" \",\"m\",\"a\",\"p\",\" \",\"(\",\"d\",\"e\",\"c\",\"o\",\"d\",\"e\",\" \",\".\",\" \",\"p\",\"o\",\"w\",\"e\",\"r\",\" \",\"d\",\" \",\"n\",\" \",\".\",\" \",\"r\",\"e\",\"a\",\"d\",\")\",\" \",\".\",\" \",\"l\",\"i\",\"n\",\"e\",\"s\",\"\\n\",\"\\n\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\" \",\"C\",\"o\",\"n\",\"v\",\"e\",\"r\",\"t\",\"i\",\"n\",\"g\",\" \",\"b\",\"e\",\"t\",\"w\",\"e\",\"e\",\"n\",\" \",\"S\",\"t\",\"r\",\"i\",\"n\",\"g\",\"s\",\" \",\"a\",\"n\",\"d\",\" \",\"I\",\"n\",\"t\",\"e\",\"g\",\"e\",\"r\",\"s\",\" \",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"-\",\"\\n\",\"\\n\",\"c\",\"o\",\"d\",\"e\",\" \",\":\",\":\",\" \",\"S\",\"t\",\"r\",\"i\",\"n\",\"g\",\" \",\"-\",\">\",\" \",\"I\",\"n\",\"t\",\"e\",\"g\",\"e\",\"r\",\"\\n\",\"c\",\"o\",\"d\",\"e\",\" \",\"=\",\" \",\"f\",\"o\",\"l\",\"d\",\"l\",\" \",\"a\",\"c\",\"c\",\"u\",\"m\",\" \",\"0\",\"\\n\",\" \",\" \",\"w\",\"h\",\"e\",\"r\",\"e\",\" \",\"a\",\"c\",\"c\",\"u\",\"m\",\" \",\"x\",\" \",\"y\",\" \",\"=\",\" \",\"(\",\"1\",\"2\",\"8\",\" \",\"*\",\" \",\"x\",\")\",\" \",\"+\",\" \",\"f\",\"r\",\"o\",\"m\",\"I\",\"n\",\"t\",\"e\",\"g\",\"r\",\"a\",\"l\",\" \",\"(\",\"f\",\"r\",\"o\",\"m\",\"E\",\"n\",\"u\",\"m\",\" \",\"y\",\")\",\"\\n\"]\n\nfun testRsa_nofib(_) = hash(encrypt(\n  z_of_int(\"2036450659413645137870851576872812267542175329986469156678671505255564383842535488743101632280716717779536712424613501441720195827856504007305662157107\"),\n  z_of_int(\"387784473137902876992546516170169092918207676456888779623592396031349415024943784869634893342729620092877891356118467738167515879252473323905128540213\"),\n  intput\n))\n\nfun main() = testRsa_nofib(0)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/scc.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule scc with ...\n\n\n\nfun dfs(r, vsns, xs) = if vsns is [vs, ns] and\n  xs is\n    Nil then [vs, ns]\n    x :: xs and\n      inList(x, vs) then dfs(r, [vs, ns], xs)\n      dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then dfs(r, [vs', (x :: ns') +: ns], xs)\n\nfun stronglyConnComp(es, vs) =\n  fun swap(a) = if a is [f, s] then [s, f]\n\n  fun new_range(xys, w) = if xys is\n    Nil then Nil\n    [x, y] :: xys and\n      x == w then y :: new_range(xys, w)\n      else new_range(xys, w)\n\n  fun span_tree(r, vsns, xs) = if vsns is [vs, ns] and\n    xs is\n      Nil then [vs, ns]\n      x :: xs and\n        inList(x, vs) then span_tree(r, [vs, ns], xs)\n        dfs(r, [x :: vs, Nil], r(x)) is [vs', ns'] then span_tree(r, [vs', (x :: ns') :: ns], xs)\n\n  snd of span_tree of\n    x => new_range(map(swap, es), x)\n    [Nil, Nil]\n    snd of dfs of\n      x => new_range(es, x)\n      [Nil, Nil]\n      vs\n\n\nfun testScc_nofib(d) =\n  let a = 1\n  let b = 2\n  let c = 3\n  let d = 4\n  let f = 5\n  let g = 6\n  let h = 7\n  let vertices = a :: b :: c :: d :: f :: g :: h :: Nil\n  let edges = [b, a] :: [c, b] :: [c, d] :: [c, h] :: [d, c] :: [f, a] :: [f, g] :: [f, h] :: [g, f] :: [h, g] :: Nil\n\n  stronglyConnComp(edges, vertices)\n\n\nfun main() = testScc_nofib(0).toString()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/secretary.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\n\nmodule secretary with ...\n\n\n\nfun infRand(m, s) =\n  fun f(x) = lazy(() => LzCons((intMod(x, m) + 1), f(intMod((97 * x + 11), power(2, 7)))))\n\n  f(s)\n\n\nfun simulate(n, m, proc) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    seed :: t then proc(infRand(m, seed)) :: lscomp(t)\n\n  listLen(filter(x => x, lscomp(enumFromTo(1, n)))) / n\n\n\nfun sim(n, k) =\n  fun proc(rs) =\n    let xs = take_lz(100, nub_lz(rs))\n    let best = 100\n    let bestk = maximum(take(k, xs))\n    let afterk = leaveWhile(x => x < bestk, leave(k, xs))\n    listEq(best :: Nil, take(1, afterk))\n\n  simulate(n, 100, proc)\n\n\nfun testSecretary_nofib(n) =\n  fun listcomp(ls) = if ls is\n    Nil then Nil\n    h :: t then sim(n, h) :: listcomp(t)\n\n  listcomp(enumFromTo(35, 39))\n\n\n\n// NOTE: original input 5000\nfun main() = testSecretary_nofib(50).toString()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/sorting.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule sorting with ...\n\n\n\nfun int_of_char(c) = c.codePointAt(0)\n\nobject\n  EQ\n  GT\n  LT\n\nfun compareList(xs, ys) = if xs is\n  Nil and ys is\n    Nil then EQ\n    _ :: _ then LT\n  _ :: _ and ys is Nil then GT\n  x :: xs_ and ys is y :: ys_ and\n    int_of_char(x) === int_of_char(y) then compareList(xs_, ys_)\n    int_of_char(x) < int_of_char(y) then LT\n    else GT\n\nfun gtList(a, b) = compareList(a, b) is GT\n\nfun leList(a, b) = not(gtList(a, b))\n\nfun ltList(a, b) = compareList(a, b) is LT\n\nfun geList(a, b) = not(ltList(a, b))\n\nfun eqList(a, b) = compareList(a, b) is EQ\n\nfun prependToAll(sep, xs) = if xs is\n  Nil then Nil\n  x :: xs_ then sep :: x :: prependToAll(sep, xs_)\n\nfun intersperse(sep, xs) = if xs is\n  Nil then Nil\n  x :: xs_ then x :: prependToAll(sep, xs_)\n\nfun lines(s) = if\n  s is Nil then Nil\n  break_(x => x === \"\\n\", s) is [l, s_] then\n    let tt = if s_ is\n      Nil then Nil\n      _ :: s__ then lines(s__)\n    l :: tt\n\nfun unlines(ls) = concat(map(l => l +: (\"\\n\" :: Nil), ls))\n\nfun odd(x) = intMod(x, 2) === 0\n\nfun z_of_int(x) = globalThis.BigInt(x)\n\nfun hash(str) = foldl(\n  (acc, c) => z_of_int(int_of_char(c)) + (acc * z_of_int(31)),\n  z_of_int(0),\n  str\n)\n\nfun quickSort(xs) = if xs is\n  Nil then Nil\n  x :: xs_ then\n    fun lscomp1(ls) = if ls is\n      Nil then Nil\n      h :: t and\n        leList(h, x) then h :: lscomp1(t)\n        else lscomp1(t)\n    fun lscomp2(ls) = if ls is\n      Nil then Nil\n      h :: t and\n        gtList(h, x) then h :: lscomp2(t)\n        else lscomp2(t)\n    quickSort(lscomp1(xs_)) +: (x :: quickSort(lscomp2(xs_)))\n\nfun select(p, x, ts_fs) = if ts_fs is [ts, fs] and\n  p(x) then [x :: ts, fs]\n  else [ts, x :: fs]\n\nfun partition(p, xs) = foldr((x, y) => select(p, x, y), [Nil, Nil], xs)\n\nfun quickSort2(xs) = if xs is\n  Nil then Nil\n  x :: xs_ then\n    if partition(y => geList(x, y), xs_) is [lo, hi] then\n      quickSort2(lo) +: (x :: quickSort2(hi))\n\nfun quickerSort(xss) = if xss is\n  Nil then Nil\n  x :: Nil then x :: Nil\n  x :: xs then\n    fun split(x, lo, hi, ys) = if ys is\n      Nil then quickerSort(lo) +: (x :: quickerSort(hi))\n      y :: ys_ and\n        leList(y, x) then split(x, y :: lo, hi, ys_)\n        else split(x, lo, y :: hi, ys_)\n    split(x, Nil, Nil, xs)\n\nfun insertSort(xss) = if xss is\n  Nil then Nil\n  x :: xs then\n    fun trins(rev, xs, ys) = if xs is\n      Nil and ys is y :: ys_ then trins(Nil, reverse(rev) +: (y :: Nil), ys_)\n      xs and ys is Nil then reverse(rev) +: xs\n      x :: xs_ and ys is y :: ys_ and\n        ltList(x, y) then trins(x :: rev, xs_, y :: ys_)\n        else trins(Nil, reverse(rev) +: (y :: x :: xs_), ys_)\n    trins(Nil, x :: Nil, xs)\n\nabstract class Tree[T]: Tip | Branch[T]\n\nobject Tip extends Tree[Nothing]\n\ndata class Branch[T](a: T, l: Tree[T], r: Tree[T]) extends Tree[T]\n\nfun treeSort(param) =\n  fun mkTree(innerparam) =\n    fun to_tree(x, t) = if t is\n      Tip then Branch(x, Tip, Tip)\n      Branch(y, l, r) and\n        leList(x, y) then Branch(y, to_tree(x, l), r)\n        else Branch(y, l, to_tree(x, r))\n    foldr(to_tree, Tip, innerparam)\n  fun readTree(t) = if t is\n    Tip then Nil\n    Branch(x, l, r) then readTree(l) +: (x :: readTree(r))\n  readTree(mkTree(param))\n\nabstract class Tree2[T]: Tip2 | Twig2[T] | Branch2[T]\n\nobject Tip2 extends Tree2[Nothing]\n\ndata\n  class\n    Twig2[T](a: T) extends Tree2[T]\n    Branch2[T](a: T, l: Tree2[T], r: Tree2[T]) extends Tree2[T]\n\nfun treeSort2(param) =\n  fun mkTree(innerparam) =\n    fun to_tree(x, t) = if t is\n      Tip2 then Twig2(x)\n      Twig2(y) and\n        leList(x, y) then Branch2(y, Twig2(x), Tip2)\n        else Branch2(y, Tip2, Twig2(x))\n      Branch2(y, l, r) and\n        leList(x, y) then Branch2(y, to_tree(x, l), r)\n        else Branch2(y, l, to_tree(x, r))\n    foldr(to_tree, Tip2, innerparam)\n  fun readTree(t) = if t is\n    Tip2 then Nil\n    Twig2(x) then x :: Nil\n    Branch2(x, l, r) then readTree(l) +: (x :: readTree(r))\n  readTree(mkTree(param))\n\nfun heapSort(xs) =\n  fun heap(k, xs) = if xs is\n    Nil then Tip\n    x :: xs_ then to_heap(k, x, heap(k + 1, xs_))\n  fun to_heap(k, x, t) = if t is\n    Tip then Branch(x, Tip, Tip)\n    Branch(y, l, r) and\n      leList(x, y) and odd(k) then Branch(x, to_heap(intDiv(k, 2), y, l), r)\n      leList(x, y) then Branch(x, l, to_heap(intDiv(k, 2), y, r))\n      odd(k) then Branch(y, to_heap(intDiv(k, 2), x, l), r)\n      else Branch(y, l, to_heap(intDiv(k, 2), x, r))\n  fun clear(t) = if t is\n    Tip then Nil\n    Branch(x, l, r) then x :: clear(mix(l, r))\n  fun mix(l, r) = if\n    l is Tip then r\n    r is Tip then l\n    l is Branch(x, l1, r1) and r is Branch(y, l2, r2) and\n      leList(x, y) then Branch(x, mix(l1, r1), Branch(y, l2, r2))\n      else Branch(y, Branch(x, l1, r1), mix(l2, r2))\n  clear(heap(0, xs))\n\nfun mergeSort(param) =\n  fun runsplit(run, xs) = if\n    run is Nil and xs is Nil then Nil\n    xs is Nil then run :: Nil\n    run is Nil and xs is x :: xs_ then runsplit(x :: Nil, xs_)\n    run is r :: rs and xs is x :: xs_ and rs is\n      Nil and\n        gtList(x, r) then runsplit(r :: x :: Nil, xs_)\n        leList(x, r) then runsplit(x :: r :: rs, xs_)\n        else (r :: rs) :: runsplit(x :: Nil, xs_)\n      rs and\n        leList(x, r) then runsplit(x :: r :: rs, xs_)\n        else (r :: rs) :: runsplit(x :: Nil, xs_)\n  fun merge_lists(xs) = if xs is\n    Nil then Nil\n    x :: xs_ then merge(x, merge_lists(xs_))\n  fun merge(xs, ys) = if\n    xs is Nil then ys\n    ys is Nil then xs\n    xs is x :: xs_ and ys is y :: ys_ and\n      eqList(x, y) then x :: y :: merge(xs_, ys_)\n      ltList(x, y) then x :: merge(xs_, y :: ys_)\n      else y :: merge(x :: xs_, ys_)\n  merge_lists(runsplit(Nil, param))\n\nfun mangle(inpt) =\n  fun sort(param) =\n    foldr(\n      (f, g) => x => f(g(x)),\n      x => x,\n      intersperse(reverse, (heapSort :: insertSort :: mergeSort :: quickSort :: quickSort2 :: quickerSort :: treeSort :: treeSort2 :: Nil)),\n    )(param)\n  unlines(sort(lines(inpt)))\n\nfun testSorting_nofib(d) =\n  let f = nofibStringToList of fs.readFileSync(\"./hkmc2/shared/src/test/mlscript/nofib/input/Main.hs\").toString()\n  hash(mangle(f))\n\nfun main() = testSorting_nofib(0)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/sphere.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule sphere with ...\n\n\n\nval pi = globalThis.Math.PI\nval epsilon  = 0.000001\nval infinity = 100000000.0\n//│ epsilon = 0.000001\n//│ infinity = 100000000\n//│ pi = 3.141592653589793\n\nfun vecadd(a1, a2) =\n  if a1 is [x1, y1, z1] and a2 is [x2, y2, z2] then\n    [x1 + x2, y1 + y2, z1 + z2]\n\nfun vecsub(a1, a2) =\n  if a1 is [x1, y1, z1] and a2 is [x2, y2, z2] then\n    [x1 - x2, y1 - y2, z1 - z2]\n\nfun vecmult(a1, a2) =\n  if a1 is [x1, y1, z1] and a2 is [x2, y2, z2] then\n    [x1 * x2, y1 * y2, z1 * z2]\n\nfun vecsum(param) = foldr(vecadd, [0.0, 0.0, 0.0], param)\n\nfun vecnorm(xyz) = if xyz is [x, y, z] then\n  let len = sqrt(x * x + y * y + z * z)\n  [[x / len , y / len, z / len], len]\n\nfun vecscale(xyz, a) = if xyz is [x, y, z] then [a * x, a * y, a * z]\n\nfun vecdot(x1, x2) = if x1 is [x1, y1, z1] and x2 is [x2, y2, z2] then x1 * x2 + y1 * y2 + z1 * z2\n\nfun veccross(x1, x2) = if x1 is [x1, y1, z1] and x2 is [x2, y2, z2] then\n  [(y1 * z2) - (y2 * z1), (z1 * x2) - (z2 * x1), (x1 * y2) - (x2 * y1)]\n\nfun is_zerovector(x) = if x is [x, y, z] then (x < epsilon) && (y < epsilon) && (z < epsilon)\n\nabstract class Light: Directional | Point\n\ndata\n  class\n    Directional(x: [Num, Num, Num], y: [Num, Num, Num]) extends Light\n    Point(x: [Num, Num, Num], y: [Num, Num, Num]) extends Light\n\nfun lightpos(p) = if p is Point(pos, col) then pos\n\nfun lightdir(d) = if d is Directional(dir, col) then fst(vecnorm(dir))\n\nfun lightcolour(x) = if x is\n  Directional(dir, col) then col\n  Point(pos, col) then col\n\nabstract class Surfspec: Ambient | Diffuse | Specular | Specpow | Reflect | Transmit | Refract | Body\n\ndata\n  class\n    Ambient(v: [Num, Num, Num]) extends Surfspec\n    Diffuse(v: [Num, Num, Num]) extends Surfspec\n    Specular(v: [Num, Num, Num]) extends Surfspec\n    Specpow(v: Num) extends Surfspec\n    Reflect(v: Num) extends Surfspec\n    Transmit(v: Num) extends Surfspec\n    Refract(v: Num) extends Surfspec\n    Body(v: [Num, Num, Num]) extends Surfspec\n\nfun ambientsurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Ambient(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), ([0.0, 0.0, 0.0] :: Nil)))\n\n\nfun diffusesurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Diffuse(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), ([0.0, 0.0, 0.0] :: Nil)))\n\n\nfun specularsurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Specular(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), ([0.0, 0.0, 0.0] :: Nil)))\n\n\nfun specpowsurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Specpow(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), (8.0 :: Nil)))\n\n\nfun reflectsurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Reflect(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), (0.0 :: Nil)))\n\n\nfun transmitsurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Transmit(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), (0.0 :: Nil)))\n\n\nfun refractsurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Refract(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), (1.0 :: Nil)))\n\n\nfun bodysurf(ss) =\n  fun lscomp(ls) = if ls is\n    Nil then Nil\n    x :: t and\n      x is Body(s) then s :: lscomp(t)\n      else lscomp(t)\n\n  head(append(lscomp(ss), ([1.0, 1.0, 1.0] :: Nil)))\n\n\ndata class Sphere(pos: [Num, Num, Num], radius: Num, surface: List[Surfspec])\n\nfun spheresurf(s) = if s is Sphere(pos, rad, surf) then surf\n\nval lookat = [0.0, 0.0, 0.0]\nval vup = [0.0, 0.0, 1.0]\nval fov = 45.0\nval s2 =\n  Ambient([0.035, 0.0325, 0.025]) ::\n  Diffuse([0.5, 0.45, 0.35]) ::\n  Specular([0.8, 0.8, 0.8]) ::\n  Specpow(3.0) ::\n  Reflect(0.5) ::\n  Nil\nval testspheres =\n  Sphere([0.0, 0.0, 0.0], 0.5, s2) ::\n  Sphere([0.272166, 0.272166, 0.544331], 0.166667, s2) ::\n  Sphere([0.643951, 0.172546, 0.0], 0.166667, s2) ::\n  Sphere([0.172546, 0.643951, 0.0], 0.166667, s2) ::\n  Sphere([-0.371785, 0.0996195, 0.544331], 0.166667, s2) ::\n  Sphere([-0.471405, 0.471405, 0.0], 0.166667, s2) ::\n  Sphere([-0.643951, -0.172546, 0.0], 0.166667, s2) ::\n  Sphere([0.0996195, -0.371785, 0.544331], 0.166667, s2) ::\n  Sphere([-0.172546, -0.643951, 0.0], 0.166667, s2) ::\n  Sphere([0.471405, -0.471405, 0.0], 0.166667, s2) ::\n  Nil            \nval testlights =\n  Point([4.0, 3.0, 2.0], [0.288675, 0.288675, 0.288675]) ::\n  Point([1.0, -4.0, 4.0], [0.288675, 0.288675, 0.288675]) ::\n  Point([-3.0, 1.0, 5.0], [0.288675, 0.288675, 0.288675]) ::\n  Nil      \nval lookfrom   = [2.1, 1.3, 1.7]\nval background = [0.078, 0.361, 0.753]\n//│ background = [0.078, 0.361, 0.753]\n//│ fov = 45\n//│ lookat = [0, 0, 0]\n//│ lookfrom = [2.1, 1.3, 1.7]\n//│ s2 = [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]\n//│ testlights = [Point([4, 3, 2], [0.288675, 0.288675, 0.288675]),Point([1, -4, 4], [0.288675, 0.288675, 0.288675]),Point([-3, 1, 5], [0.288675, 0.288675, 0.288675])]\n//│ testspheres = [Sphere([0, 0, 0], 0.5, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.272166, 0.272166, 0.544331], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.643951, 0.172546, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.172546, 0.643951, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.371785, 0.0996195, 0.544331], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.471405, 0.471405, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.643951, -0.172546, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.0996195, -0.371785, 0.544331], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([-0.172546, -0.643951, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)]),Sphere([0.471405, -0.471405, 0], 0.166667, [Ambient([0.035, 0.0325, 0.025]),Diffuse([0.5, 0.45, 0.35]),Specular([0.8, 0.8, 0.8]),Specpow(3),Reflect(0.5)])]\n//│ vup = [0, 0, 1]\n\nfun spherenormal(pos, sp) = if sp is Sphere(spos, rad, _) then\n  vecscale(vecsub(pos, spos), 1 / rad)\n\nfun dtor(x) = x * pi / 180.0\n\nfun camparams(lookfrom, lookat, vup, fov, winsize) =\n  let initfirstray = vecsub(lookat, lookfrom)\n  if vecnorm(initfirstray) is\n    [lookdir, dist] and vecnorm(veccross(lookdir, vup)) is [scrni, _] and vecnorm(veccross(scrni, lookdir)) is [scrnj, _] then\n      let xfov = fov\n      let yfov = fov\n      let xwinsize = winsize\n      let ywinsize = winsize\n      let magx = 2.0 * dist * tan(dtor(xfov/2)) / xwinsize\n      let magy = 2.0 * dist * tan(dtor(yfov/2)) / ywinsize\n      let scrnx = vecscale(scrni, magx)\n      let scrny = vecscale(scrnj, magy)\n      let firstray = vecsub(initfirstray, vecadd(vecscale(scrnx, (0.5 * xwinsize)), vecscale(scrny, (0.5 * ywinsize))))\n      [firstray, scrnx, scrny]\n\nfun sphereintersect(pos, dir, sp) =\n  if sp is Sphere(spos, rad, _) then\n    let m = vecsub(pos, spos)\n    let bm = vecdot(m, dir)\n    let m2 = vecdot(m, m)\n    let disc = (bm * bm) - m2 + (rad * rad)\n    let slo = -bm - sqrt(disc)\n    let shi = -bm + sqrt(disc)\n    if\n      disc < 0.0 then [false, 0.0]\n      slo < 0.0 and\n        shi < 0.0 then [false, 0.0]\n        else [true, shi]\n      else [true, slo]\n\nfun trace(spheres, pos, dir) =\n  fun f(d1s1, d2s2) =\n    if d1s1 is [d1, s1] and d2s2 is [d2, s2_] and\n      d1 < d2 then [d1, s1]\n      else [d2, s2_]\n\n  fun sphmap(xss) =\n    if xss is\n      Nil then Nil\n      x :: xs and sphereintersect(pos, dir, x) is [is_hit, where_hit] and\n        is_hit then [where_hit, x] :: sphmap(xs)\n        else sphmap(xs)\n\n  let dists = sphmap(spheres)\n\n  if (null_(dists)) then\n    [false, infinity, head(spheres)]\n  else\n    if foldr(f, head(dists), tail(dists)) is [mindist, sp] then\n      [true, mindist, sp]\n\n\nfun refractray(newindex, olddir, innorm) =\n  let dotp = -vecdot(olddir, innorm)\n  let matchIdent_17 = if dotp < 0.0 then\n    [vecscale(innorm, -1.0), -dotp, 1.0 / newindex]\n  else\n    [innorm, dotp, newindex]\n  if matchIdent_17 is\n    [norm, k, nr] then\n      let disc = 1.0 - nr * nr * (1.0 - (k * k))\n      let t = (nr * k) - sqrt(disc)\n      if disc < 0.0 then\n        [true, [0.0, 0.0, 0.0]]\n      else\n        ([false, vecadd(vecscale(norm, t), vecscale(olddir, nr))])\n\nfun lightdirection(l, pt) = if l is\n  Directional(dir, col) then [fst(vecnorm(dir)), infinity]\n  Point(pos, col) then vecnorm(vecsub(pos, pt))\n\nfun shadowed(pos, dir, lcolour) =\n  if trace(testspheres, vecadd(pos, vecscale(dir, epsilon)), dir) is\n    [is_hit, dist, sp] then\n      if not(is_hit) then\n        [false, lcolour]\n      else\n        [true, lcolour]\n\nfun lightray(l, pos, norm, refl, surf) =\n  if lightdirection(l, pos) is\n    [ldir, dist] then\n      let cosangle = vecdot(ldir, norm)\n      if shadowed(pos, ldir, lightcolour(l)) is\n        [is_inshadow, lcolour] then\n          if\n            is_inshadow then [0.0, 0.0, 0.0]\n            let diff = diffusesurf(surf)\n            let spow = specpowsurf(surf)\n            cosangle <= 0.0 then\n              let bodycol = bodysurf(surf)\n              let cosalpha = -vecdot(refl, ldir)\n              let diffcont = vecmult(vecscale(diff, -cosangle), lcolour)\n              let speccont = if cosalpha <= 0.0 then [0.0, 0.0, 0.0] else (vecmult(vecscale(bodycol, power(cosalpha, spow)), lcolour))\n              vecadd(diffcont, speccont)\n            let spec = specularsurf(surf)\n            let cosalpha = vecdot(refl, ldir)\n            let diffcont = vecmult(vecscale(diff, cosangle), lcolour)\n            let speccont = if cosalpha < 0.0 then [0.0, 0.0, 0.0] else (vecmult(vecscale(spec, power(cosalpha, spow)), lcolour))\n            else vecadd(diffcont, speccont)\n\n//│ ————————————————————————————————————————————————————————————————————————————————\nfun shade(lights, sp, lookpos, dir, dist, contrib) =\n  let hitpos = vecadd(lookpos, vecscale(dir, dist))\n  let ambientlight = [1.0, 1.0, 1.0]\n  let surf = spheresurf(sp)\n  let amb = vecmult(ambientlight, ambientsurf(surf))\n  let norm = spherenormal(hitpos, sp)\n  let refl = vecadd(dir, vecscale(norm, -2.0 * vecdot(dir, norm)))\n  let diff = vecsum(map(l => (lightray(l, hitpos, norm, refl, surf)), lights))\n  let transmitted = transmitsurf(surf)\n  let simple = vecadd(amb, diff)\n  let trintensity = vecscale(bodysurf(surf), transmitted)\n  let matchIdent_1 =\n    if transmitted < epsilon then\n      [false, simple]\n    else\n      transmitray(lights, simple, hitpos, dir, refractsurf(surf), trintensity, contrib, norm)\n  if matchIdent_1 is [is_tir, trcol] then\n    let reflsurf = vecscale(specularsurf(surf), reflectsurf(surf))\n    let reflectiv = if is_tir then vecadd(trintensity, reflsurf) else reflsurf\n    let rcol = if is_zerovector(reflectiv) then trcol else (reflectray(hitpos, refl, lights, reflectiv, contrib, trcol))\n    rcol\n\nfun transmitray(lights, colour, pos, dir, index, intens, contrib, norm) =\n  let newcontrib = vecmult(intens, contrib)\n  if refractray(index, dir, norm) is\n    [is_tir, newdir] then\n      let nearpos = vecadd(pos, vecscale(newdir, epsilon))\n      if trace(testspheres, nearpos, newdir) is\n        [is_hit, dist, sp] then\n          let newcol =\n            if is_hit then\n              shade(lights, sp, nearpos, newdir, dist, newcontrib)\n            else\n              background\n          if is_zerovector(newcontrib) then\n            [false, colour]\n          else\n            ([false, vecadd(vecmult(newcol, intens), colour)])\n\nfun reflectray(pos, newdir, lights, intens, contrib, colour) =\n  let newcontrib = vecmult(intens, contrib)\n  let nearpos = vecadd(pos, vecscale(newdir, epsilon))\n  if trace(testspheres, nearpos, newdir) is [is_hit, dist, sp] then\n      let newcol =\n        if is_hit then\n          shade(lights, sp, nearpos, newdir, dist, newcontrib)\n        else\n          background\n      if is_zerovector(newcontrib) then\n        colour\n      else\n        (vecadd(colour, vecmult(newcol, intens)))\n//│ ————————————————————————————————————————————————————————————————————————————————\n\nfun tracepixel(spheres, lights, x, y, firstray, scrnx, scrny) =\n  let pos = lookfrom\n  if vecnorm(vecadd(vecadd(firstray, vecscale(scrnx, x)), vecscale(scrny, y))) is [dir, tracepixel_Tup2_1] and trace(spheres, pos, dir) is [hit, dist, sp] and\n    hit then shade(lights, sp, pos, dir, dist, [1.0, 1.0, 1.0])\n    else background\n\nfun z_of_int(x) = globalThis.BigInt(x)\n\nfun hash(param) =\n  fun u8(x) = z_of_int(round(255 * x))\n  foldr(((rgb, acc) => if rgb is [r, g, b] then u8(r) + (u8(g) * z_of_int(7)) + (u8(b) * z_of_int(23)) + (acc * z_of_int(61))), z_of_int(0), param)\n\nfun ray(winsize) =\n  let lights = testlights\n  if camparams(lookfrom, lookat, vup, fov, winsize) is [firstray, scrnx, scrny] then\n    fun f(i, j) = tracepixel(testspheres, lights, i, j, firstray, scrnx, scrny)\n    fun lscomp1(ls1) = if ls1 is\n      Nil then Nil\n      i :: t1 then\n        fun lscomp2(ls2) = if ls2 is\n          Nil then lscomp1(t1)\n          j :: t2 then [[i, j], f(i, j)] :: lscomp2(t2)\n        lscomp2(enumFromTo(0, winsize - 1))\n    lscomp1(enumFromTo(0, winsize - 1))\n\nfun run(winsize) = hash(map(snd, ray(winsize)))\n\nfun testSphere_nofib(n) = run(n)\n\n\nfun main() = testSphere_nofib(30)\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/nofib/treejoin.mls",
    "content": "import \"./NofibPrelude.mls\"\nimport \"../../../../../../hkmc2/shared/src/test/mlscript-compile/Predef.mls\"\nopen NofibPrelude\n\nmodule treejoin with ...\n\n\n\nfun isSpace(c) = c === \" \" || c === \"\\n\"\n\nfun isDigit(c) =\n  let n = c.codePointAt(0)\n  in n >= 48 && n <= 57\n\nabstract class Tree[E]: Node | Leaf | Empty\n\ndata\n  class\n    Node[E](k: Int, l: Tree[E], r: Tree[E]) extends Tree[E]\n    Leaf[E](k: Int, e: E) extends Tree[E]\n\nobject Empty extends Tree\n\nfun insertT(k, e, t) = if t is\n  Node(k_, l, r) and\n    k <= k_ then Node(k_, insertT(k, e, l), r)\n    else Node(k_, l, insertT(k, e, r))\n  Leaf(k_, k__) then\n    let l_ = Leaf(k, e)\n    if k\n      < k_ then Node(k, l_, Leaf(k_, k__))\n      > k_ then Node(k_, Leaf(k_, k__), l_)\n      else throw Error(\"already exist\")\n  Empty then Leaf(k, e)\n\nfun lookupT(k, t) = if t is\n  Node(k_, l, r) and\n    k <= k_ then lookupT(k, l)\n    else lookupT(k, r)\n  Leaf(k_, e) then if k === k_ then Some(e) else None\n  Empty then None\n\nfun readInt(s) =\n  fun readInt_(n, cs) = if cs is\n    c :: cs_ and\n      isDigit(c) then readInt_(n * 10 + c.codePointAt(0) - 48, cs_)\n      else let s_ = leaveWhile(isSpace, c :: cs) in [n, s_]\n    else\n      let s_ = leaveWhile(isSpace, cs) in [n, s_]\n  readInt_(0, s)\n\nfun join(t1, t2, j) = if\n  t1 is Empty then j\n  t2 is Empty then j\n  t1 is Leaf(k, [a, b, c]) and lookupT(c, t2) is\n    None then j\n    Some([d, e, f]) then insertT(c, [a, b, c, d, e], j)\n  t1 is Node(k, l, r) then join(l, t2, join(r, t2, j))\n\nfun readTree(fk, s, t) = if\n  s is Nil then t\n  readInt(s) is [f, s_] and\n    readInt(s_) is [g, s__] and\n      readInt(s__) is [h, s___] then\n        let e = [f, g, h]\n        let k = fk(e)\n        readTree(fk, s___, insertT(k, e, t))\n\n\nfun testTreejoin_nofib(n) =\n  let c1 = nofibStringToList of fs.readFileSync(\"./hkmc2/shared/src/test/mlscript/nofib/input/1500.1\").toString()\n  let c2 = nofibStringToList of fs.readFileSync(\"./hkmc2/shared/src/test/mlscript/nofib/input/1500.2\").toString()\n  let a = readTree(case { [xx, _, _] then xx }, c1, Empty)\n  let b = readTree(case { [xx, _, _] then xx }, c2, Empty)\n  join(a, b, Empty)\n\nfun main() = testTreejoin_nofib(0).toString()\n\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/CSPBar.mls",
    "content": "import \"./../Example.mls\"\nmodule CSPBar with ...\nfun res =\n  Example.inc(0)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/CSPBaz.mls",
    "content": "import \"./CSPNest.mls\"\nmodule CSPBaz with ...\nfun res =\n  CSPNest.nest_f()\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/CSPFoo.mls",
    "content": "import \"./../CSP.mls\"\nmodule CSPFoo with ...\nfun res =\n  (+)(CSP.test(), 1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/CSPNest.mls",
    "content": "module CSPNest with ...\nfun nest_f() = 42\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/Cubic.mls",
    "content": "\nmodule Cubic with ...\nfun res =\n  (x_0) =>\n    (*)(x_0, (*)(x_0, (*)(x_0, 1)))\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/Gib12.mls",
    "content": "\nmodule Gib12 with ...\nfun res =\n  (x_0, y_0) =>\n    let x_1\n    x_1 = (+)(x_0, y_0)\n    let x_2\n    x_2 = (+)(y_0, x_1)\n    let x_3\n    x_3 = (+)(x_1, x_2)\n    let x_4\n    x_4 = (+)(x_2, x_3)\n    let x_5\n    x_5 = (+)(x_3, x_4)\n    let x_6\n    x_6 = (+)(x_4, x_5)\n    let x_7\n    x_7 = (+)(x_5, x_6)\n    let x_8\n    x_8 = (+)(x_6, x_7)\n    let x_9\n    x_9 = (+)(x_7, x_8)\n    let x_10\n    x_10 = (+)(x_8, x_9)\n    let x_11\n    x_11 = (+)(x_9, x_10)\n    x_11\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/Opened.mls",
    "content": "import \"./../Predef.mls\"\nmodule Opened with ...\nfun res =\n  Predef.equals(Predef.id(1), 2)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/QuoteFoo.mls",
    "content": "\nmodule QuoteFoo with ...\nfun res =\n  (+)(1, 1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/QuoteInc.mls",
    "content": "\nmodule QuoteInc with ...\nfun res =\n  (x_0) =>\n    (+)(x_0, 1)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/quotes/SafeDiv.mls",
    "content": "\nmodule SafeDiv with ...\nfun res =\n  (x_0, y_0, d_0) =>\n    if \n      let scrut_0 = (==)(y_0, 0)\n      scrut_0 is true then d_0\n      else (/)(x_0, y_0)\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/ups/DnfCnf.mls",
    "content": "open annotations\n\nmodule DnfCnf with ...\n\nclass Formula with\n  constructor\n    Var(val name: Str)\n    Pred(val name: Str, val arg: Formula)\n    And(val left: Formula, val right: Formula)\n    Or(val left: Formula, val right: Formula)\n\npattern Dnf(pattern P) = Or(Dnf(P), Dnf(P)) | Atoms(P)\n\npattern Atoms(pattern P) = And(Atoms(P), Atoms(P)) | Atom(P)\n\npattern Atom(pattern P) = Pred(_, P) | Var\n\npattern Cnf(pattern P) = And(Cnf(P), Cnf(P))\n\npattern DnfOrCnf = Dnf(DnfOrCnf) | Cnf(DnfOrCnf)\n\npattern DnfAndCnf = Dnf(DnfAndCnf) & Cnf(DnfAndCnf)\n\nfun isDnfOrCnf_naive(t) = t is DnfOrCnf\nfun isDnfOrCnf_optimized(t) =\n  if t is (@compile DnfOrCnf) as s then s else ()\nfun isDnfOrCnf_optimized_matchOnly(t) = t is @compile DnfOrCnf\n\nfun isDnfAndCnf_naive(t) = t is DnfAndCnf\nfun isDnfAndCnf_optimized(t) =\n  if t is (@compile DnfAndCnf) as s then s else ()\nfun isDnfAndCnf_optimized_matchOnly(t) = t is @compile DnfAndCnf\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/ups/EvaluationContext.mls",
    "content": "import \"../Option.mls\"\n\nopen Option { Some, None }\nopen annotations\n\nmodule EvaluationContext with ...\n\ndata class Term with\n  constructor\n    Var(name: Str)\n    App(lhs: Term, rhs: Term)\n    Abs(lhs: Var, rhs: Term)\n  \n  // A cached set of free variables\n  let _freeVars = None\n  \n  // Compute free variables. Retrieve the cache if it exists.\n  fun freeVars = if _freeVars is\n    Some(fv) then fv\n    None then\n      let fv = if this is\n        Var(name) then new Set([name])\n        App(lhs, rhs) then lhs.freeVars.union(rhs.freeVars)\n        Abs(name, body) then body.freeVars.difference(new Set([name]))\n      set _freeVars = Some(fv)\n      fv\n  \n  // Keep increasing the index until the based name with the index is not a free\n  // variable in this term.\n  fun freshName(baseName) =\n    let\n      freeVars = this.freeVars\n      nameIndex = 1\n    if freeVars.has(baseName) is false then baseName else...\n    while (baseName + \"_\" + nameIndex) is currentName and\n      freeVars.has(currentName) then set nameIndex += 1\n      else return currentName\n  \n  fun freshVar(baseName) = Var of freshName(baseName)\n  \n  fun equals(that) = if this is\n    Var(name) and that is Var(name') then name === name'\n    App(lhs, rhs) and that is App(lhs', rhs') then\n      lhs.equals(lhs') && rhs.equals(rhs')\n    Abs(Var(name), body) and that is Abs(Var(name'), body') then\n      name === name' && body.equals(body')\n    else false\n  \n  // Pretty-print the term.\n  fun show = if this is\n    Var(name) then name\n    App(Abs as lhs, rhs) then \"(\" + lhs.show + \") \" + rhs.show\n    App(lhs, App as rhs) then lhs.show + \" (\" + rhs.show + \")\"\n    App(lhs, rhs) then lhs.show + \" \" + rhs.show\n    Abs(Var(name), body) then \"λ\" + name + \". \" + body.show\n\nfun subst(term, name, target) = if term is\n  Var(name') and\n    name === name' then target\n    else term\n  Abs(Var(name'), body) and\n    name === name' then term\n    let target' = if target.freeVars.has(name')\n      then subst(target, name', target.freshVar(name'))\n      else target\n    else Abs(Var(name'), subst(body, name, target'))\n  App(lhs, rhs) then App(subst(lhs, name, target), subst(rhs, name, target))\n\npattern Value = Abs\n\npattern Ctx(pattern Hole) =\n  | Hole\n  | App(Value, Ctx(Hole))\n  | App(Ctx(Hole), _)\n\npattern Redex = App(Abs(Var(x), m), Abs as n) => subst(m, x, n)\n\npattern Step = (Ctx(Redex) as res) => res\n\nfun isStep_naive(t) = t is Step\nfun isStep_optimized(t) =\n  if t is (@compile Step) as s then s else ()\nfun isStep_optimized_matchOnly(t) = t is @compile Step\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/ups/EvenOddTree.mls",
    "content": "open annotations\n\nmodule EvenOddTree with ...\n\nobject A\nobject B\n\ndata class Node[T](left: Node[T], value: T, right: Node[T])\n\n// The patterns generate trees that have odd or even numbers of node `A`.\n\npattern OddTree =\n  | A\n  | Node(EvenTree, A, EvenTree)\n  | Node(OddTree, A, OddTree)\n  | Node(EvenTree, B, OddTree)\n  | Node(OddTree, B, EvenTree)\n\npattern EvenTree =\n  | B\n  | Node(EvenTree, A, OddTree)\n  | Node(OddTree, A, EvenTree)\n  | Node(EvenTree, B, EvenTree)\n  | Node(OddTree, B, OddTree)\n\nfun isOddTree_naive(t) = t is OddTree\nfun isOddTree_optimized(t) =\n  if t is (@compile OddTree) as s then s else ()\nfun isOddTree_optimized_matchOnly(t) = t is @compile OddTree\n\nfun isEvenTree_naive(t) = t is EvenTree\nfun isEvenTree_optimized(t) =\n  if t is (@compile EvenTree) as s then s else ()\nfun isEvenTree_optimized_matchOnly(t) = t is @compile EvenTree\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/ups/README.md",
    "content": "This directory contains five pattern-compilation example programs, which define seven compiled entry patterns.\n\nThe table below counts non-empty lines in the generated `.mjs` files. \"Referenced pattern names\" means direct pattern references in the source pattern body.\n\n| Pattern name | Referenced pattern names | Referenced pattern class SLOC | `_optimized` SLOC | `_optimized_matchOnly` SLOC |\n| --- | --- | ---: | ---: | ---: |\n| `Truthy` | `Truthy`, `Falsy` | 368 | 1173 | 710 |\n| `Falsy` | `Falsy`, `Truthy` | 368 | 1173 | 710 |\n| `OddTree` | `OddTree`, `EvenTree` | 858 | 3355 | 2006 |\n| `EvenTree` | `EvenTree`, `OddTree` | 858 | 3355 | 2006 |\n| `Step` | `Ctx`, `Redex` | 289 | 1266 | 516 |\n| `DnfOrCnf` | `DnfOrCnf`, `Dnf`, `Cnf` | 506 | 777 | 541 |\n| `DnfAndCnf` | `DnfAndCnf`, `Dnf`, `Cnf` | 506 | 326 | 222 |\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/ups/TruthyFalsy.mls",
    "content": "open annotations\n\nmodule TruthyFalsy with ...\n\ndata\n  class\n    (&&) And(lhs: Bool, rhs: Bool)\n    (||) Or(lhs: Bool, rhs: Bool)\n    Not(arg: Bool)\n\npattern Truthy =\n  | true\n  | And(Truthy, Truthy)\n  | Or(Truthy, Truthy)\n  | Or(Truthy, Falsy)\n  | Or(Falsy, Truthy)\n  | Not(Falsy)\n\npattern Falsy =\n  | false\n  | And(Falsy, Falsy)\n  | And(Falsy, Truthy)\n  | And(Truthy, Falsy)\n  | Or(Falsy, Falsy)\n  | Not(Truthy)\n\nfun isTruthy_naive(t) = t is Truthy\nfun isTruthy_optimized(t) =\n  if t is (@compile Truthy) as s then s else ()\nfun isTruthy_optimized_matchOnly(t) = t is @compile Truthy\n\nfun isFalsy_naive(t) = t is Falsy\nfun isFalsy_optimized(t) =\n  if t is (@compile Falsy) as s then s else ()\nfun isFalsy_optimized_matchOnly(t) = t is @compile Falsy\n"
  },
  {
    "path": "hkmc2/shared/src/test/mlscript-compile/wasm/Wasm.mls",
    "content": "import \"binaryen\"\n\nimport \"../Predef.mls\"\nimport \"../Runtime.mls\"\n\nmodule Wasm with ...\n\n// WebAssembly utilities\nfun loadWasmBinary(modBuf, importObject): Promise =\n  assert WebAssembly.validate of modBuf\n\n  WebAssembly.instantiate of modBuf, importObject\n\nfun dumpWasmImpExp(wasmMod) =\n  console.log of \"Imports: %s\", WebAssembly.Module.imports(wasmMod.module)\n  console.log of \"Exports: %s\", WebAssembly.Module.exports(wasmMod.module)\n\n// Binaryen helpers\nfun binaryenFmtWat(wat, foldExprs): String =\n  val mod = binaryen.parseText of wat\n  mod.setFeatures(binaryen.Features.All)\n  \n  // Note: it seems `mod.validate()` sometimes returns `1` instead of `true`; so we don't use `assert` here\n  Predef.js_assert of mod.validate()\n\n  val fmtWat = if foldExprs then mod.emitText() else mod.emitStackIR()\n\n  mod.dispose()\n  fmtWat\n\nfun binaryenCompileToModule(wat, importObject): Promise =\n  val mod = binaryen.parseText of wat\n  mod.setFeatures(binaryen.Features.All)\n\n  // Note: it seems `mod.validate()` sometimes returns `1` instead of `true`; so we don't use `assert` here\n  Predef.js_assert of mod.validate()\n\n  val modBuf = mod.emitBinary()\n  mod.dispose()\n\n  Promise.resolve(modBuf).then(modBuf =>\n    loadWasmBinary of modBuf, importObject\n  )\n\nfun unwrapWasmException(err, tag) =\n  if (\n    err !== null &&\n    err !== undefined &&\n    typeof(err.is) === \"function\" &&\n    typeof(err.getArg) === \"function\" &&\n    err.is(tag)\n  )\n  then err.getArg(tag, 0)\n  else err\n\nfun binaryenRunFunc(wat, importObject, func): Promise =\n  binaryenCompileToModule(wat, importObject)\n    .then(wasmMod =>\n      let exnTag = wasmMod.instance.exports.mlx_exn\n      Runtime.try_catch of\n        () => func(wasmMod.instance.exports)\n        err => throw unwrapWasmException(err, exnTag)\n    )\n\nfun binaryenPrintFuncRes(wat, importObject, func): Promise = \n  binaryenRunFunc(wat, importObject, func)\n    .then(result =>\n      Predef.print of Runtime.render of result\n    )\n"
  },
  {
    "path": "hkmc2AppsTests/src/test/scala/hkmc2/AppsCompileTestRunner.scala",
    "content": "package hkmc2\n\nimport mlscript.utils._, shorthands._\nimport io.PlatformPath.given\n\n\nclass AppsCompileTestRunner extends CompileTestRunnerBase(\n  compileDirs = TestFolders.appsCompileDirs(os.pwd),\n):\n  protected def cctx: CompilerCtx = AppsCompileTestRunner.cctx\n\nend AppsCompileTestRunner\n\n\nobject AppsCompileTestRunner:\n  \n  given cctx: CompilerCtx = CompilerCtx.fresh(io.FileSystem.default)\n\nend AppsCompileTestRunner\n\n"
  },
  {
    "path": "hkmc2AppsTests/src/test/scala/hkmc2/AppsDiffTestRunner.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\n\nimport mlscript.utils._\nimport os.Path\nimport io.PlatformPath.given\n\nobject AppsDiffTestState extends DiffTestRunner.State:\n  \n  override def testDir = TestFolders.appsDiffDir(workingDir)\n\nclass AppsDiffTestRunner\n  extends DiffTestRunnerBase(AppsDiffTestState)\n  with ParallelTestExecution\n\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/.gitignore",
    "content": "*.mjs\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/FingerTreesAsStacks.mls",
    "content": ":js\n:silent\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/FingerTreeList.mls\"\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/Stack.mls\"\nimport \"./mlscript-compile/Benchmark.mls\"\n\nopen Benchmark\n\n:silent\nlet suite = mkSuite()\n\n\n:silent\nlet ftree = FingerTreeList.mk()\nlet stack = Stack.Nil\n\n// Push an array of elements\n:silent\nsuite.add(\"FingerTreeList.push100\", () =>\n  let ft = FingerTreeList.mk()\n  let i = 0\n  while i < 100 do\n    set ft = FingerTreeList.cons(i, ft)\n    set i += 1\n)\n\n:silent\nsuite.add(\"FingerTreeList.push1000\", () =>\n  let ft = FingerTreeList.mk()\n  let i = 0\n  while (i < 1000) do\n    set ft = FingerTreeList.cons(i, ft)\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"FingerTreeList.push10000\", () =>\n  let ft = FingerTreeList.mk()\n  let i = 0\n  while (i < 10000) do\n    set ft = FingerTreeList.cons(i, ft)\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"FingerTreeList.push100000\", () =>\n  let ft = FingerTreeList.mk()\n  let i = 0\n  while (i < 100000) do\n    set ft = FingerTreeList.cons(i, ft)\n    set i = i + 1\n  set ftree = ft\n)\n\n:silent\nsuite.add(\"Stack.push100\", () =>\n  let st = Stack.Nil\n  let i = 0\n  while (i < 100) do\n    set st = Stack.Cons(i, st)\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"Stack.push1000\", () =>\n  let st = Stack.Nil\n  let i = 0\n  while (i < 1000) do\n    set st = Stack.Cons(i, st)\n    set i = i + 1\n)\n\n\n:silent\nsuite.add(\"Stack.push10000\", () =>\n  let st = Stack.Nil\n  let i = 0\n  while (i < 10000) do\n    set st = Stack.Cons(i, st)\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"Stack.push100000\", () =>\n  let st = Stack.Nil\n  let i = 0\n  while (i < 100000) do\n    set st = Stack.Cons(i, st)\n    set i = i + 1\n  set stack = st\n)\n\n:silent\nlet ftElems = new Array(100000)\nlet stElems = new Array(100000)\n\n// Pop elements\n:silent\nsuite.add(\"FingerTreeList.pop100\", () => \n  let popft = ftree\n  let i = 0\n  while (i < 100) do\n    val v = FingerTreeList.popFront(popft)\n    set ftElems.[i] = v.e1\n    set popft = FingerTreeList.popFront(popft).rest\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"FingerTreeList.pop1000\", () => \n  let popft = ftree\n  let i = 0\n  while (i < 1000) do\n    val v = FingerTreeList.popFront(popft)\n    set ftElems.[i] = v.e1\n    set popft = FingerTreeList.popFront(popft).rest\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"FingerTreeList.pop10000\", () => \n  let popft = ftree\n  let i = 0\n  while (i < 10000) do\n    val v = FingerTreeList.popFront(popft)\n    set ftElems.[i] = v.e1\n    set popft = FingerTreeList.popFront(popft).rest\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"FingerTreeList.pop100000\", () => \n  let popft = ftree\n  let i = 0\n  while (FingerTreeList.isEmpty(popft) is false) do\n    val v = FingerTreeList.popFront(popft)\n    set ftElems.[i] = v.e1\n    set popft = FingerTreeList.popFront(popft).rest\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"Stack.pop100\", () =>\n  let popStack = stack\n  let i = 0\n  while (i < 100) do\n    set stElems.[i] = popStack.head\n    set popStack = popStack.tail\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"Stack.pop1000\", () =>\n  let popStack = stack\n  let i = 0\n  while (i < 1000) do\n    set stElems.[i] = popStack.head\n    set popStack = popStack.tail\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"Stack.pop10000\", () =>\n  let popStack = stack\n  let i = 0\n  while (i < 10000) do\n    set stElems.[i] = popStack.head\n    set popStack = popStack.tail\n    set i = i + 1\n)\n\n:silent\nsuite.add(\"Stack.pop100000\", () =>\n  let popStack = stack\n  let i = 0\n  while (popStack is Stack.Cons) do\n    set stElems.[i] = popStack.head\n    set popStack = popStack.tail\n    set i = i + 1\n)\n\n:silent\nsuite |> runSuite\nwriteResults(suite, \"FingerTreesAsStack.json\")\n\n:expect true\n:silent\nlet i = 0\nlet same = true\nwhile (i < 100000) do\n  set same = same && (ftElems.[i] === stElems.[i]) && (ftElems.[i] === 100000 - i - 1)\n  set i = i + 1\nsame\n\n\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/LazySpreads.mls",
    "content": ":js\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/LazyArray.mls\"\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/FingerTreeList.mls\"\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/LazyFingerTree.mls\"\n\nimport \"./mlscript-compile/Benchmark.mls\"\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/Runtime.mls\"\n\nopen LazyArray\nopen FingerTreeList\nopen LazyFingerTree\n\nopen Benchmark\nopen Runtime\n\n:silent\nlet suite = mkSuite()\n\nfun materialize(xs) = if (xs |> FingerTreeList.isFingerTree)\n  then xs\n  else xs.materialize()\n\n:sjs\nfun buildLazy(i) =\n  if i > 0 then [i, ..buildLazy(i - 1), -i] else []\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let buildLazy;\n//│ buildLazy = function buildLazy(i) {\n//│   let scrut, tmp, tmp1, tmp2;\n//│   scrut = i > 0;\n//│   if (scrut === true) {\n//│     tmp = i - 1;\n//│     tmp1 = buildLazy(tmp);\n//│     tmp2 = - i;\n//│     return globalThis.Object.freeze(runtime.Tuple.lazyConcat(i, runtime.Tuple.split, tmp1, tmp2))\n//│   }\n//│   return globalThis.Object.freeze([]);\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nfun buildEager(i) =\n  if i > 0 then [i, ...buildEager(i - 1), -i] else []\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let buildEager;\n//│ buildEager = function buildEager(i) {\n//│   let scrut, tmp, tmp1, tmp2;\n//│   scrut = i > 0;\n//│   if (scrut === true) {\n//│     tmp = i - 1;\n//│     tmp1 = buildEager(tmp);\n//│     tmp2 = - i;\n//│     return globalThis.Object.freeze([ i, ...tmp1, tmp2 ])\n//│   }\n//│   return globalThis.Object.freeze([]);\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nfun funnySum(xs) = if xs is\n  [a, ..ls, b] then\n    a + funnySum(ls) - b\n  [] then 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let funnySum;\n//│ funnySum = function funnySum(xs) {\n//│   let ls, a, b, lastElement1$, middleElements, element0$, tmp, tmp1;\n//│   if (runtime.Tuple.isArrayLike(xs) && xs.length >= 2) {\n//│     element0$ = runtime.Tuple.get(xs, 0);\n//│     middleElements = runtime.Tuple.slice(xs, 1, 1);\n//│     lastElement1$ = runtime.Tuple.get(xs, -1);\n//│     b = lastElement1$;\n//│     ls = middleElements;\n//│     a = element0$;\n//│     tmp = funnySum(ls);\n//│     tmp1 = a + tmp;\n//│     return tmp1 - b\n//│   } else if (runtime.Tuple.isArrayLike(xs) && xs.length === 0) {\n//│     return 0\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nfun funnySumEager(xs) = if xs is\n  [a, ...ls, b] then\n    a + funnySumEager(ls) - b\n  [] then 0\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let funnySumEager;\n//│ funnySumEager = function funnySumEager(xs) {\n//│   let ls, a, b, lastElement1$, middleElements, element0$, tmp, tmp1;\n//│   if (runtime.Tuple.isArrayLike(xs) && xs.length >= 2) {\n//│     element0$ = runtime.Tuple.get(xs, 0);\n//│     middleElements = runtime.Tuple.slice(xs, 1, 1);\n//│     lastElement1$ = runtime.Tuple.get(xs, -1);\n//│     b = lastElement1$;\n//│     ls = middleElements;\n//│     a = element0$;\n//│     tmp = funnySumEager(ls);\n//│     tmp1 = a + tmp;\n//│     return tmp1 - b\n//│   } else if (runtime.Tuple.isArrayLike(xs) && xs.length === 0) {\n//│     return 0\n//│   }\n//│   throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:silent\nsuite.add(\"BuildLazy3\", () => buildLazy(3))\nsuite.add(\"BuildLazy33\", () => buildLazy(33))\nsuite.add(\"BuildLazy333\", () => buildLazy(333))\nsuite.add(\"BuildLazy3333\", () => buildLazy(3333))\nlet res = buildLazy(1000)\n\nres |> funnySumEager\n//│ = 1001000\n\n:silent\nsuite.add(\"LazyBuiltFunnySumEager1000\", () => \n  let res = buildLazy(1000)\n  res |> funnySumEager)\n\n:silent\nlet res = buildLazy(1000)\n\n// saving from materialization probably balancing\n// slowdown from logn random access\nres |> funnySum\n//│ = 1001000\n\n:silent\nsuite.add(\"LazyBuiltFunnySum1000\", () => \n  let res = buildLazy(1000)\n  res |> funnySum)\nsuite.add(\"LazyBuiltFunnySum100\", () => \n  let res = buildLazy(100)\n  res |> funnySum)\nsuite.add(\"LazyBuiltFunnySum10\", () => \n  let res = buildLazy(10)\n  res |> funnySum)\n\n//=========================================================================\n\n:silent\nsuite.add(\"BuildEager3\", () => buildEager(3))\nsuite.add(\"BuildEager33\", () => buildEager(33))\nsuite.add(\"BuildEager333\", () => buildEager(333))\nsuite.add(\"BuildEager3333\", () => buildEager(3333))\nlet res = buildEager(1000)\nlet res100 = buildEager(100)\nlet res10 = buildEager(10)//+ runtime clock time (321984c): 128.79833 ms\n\nres |> funnySumEager\n//│ = 1001000\n\n:silent\nsuite.add(\"EagerBuiltFunnySumEager1000\", () => res |> funnySumEager)\nsuite.add(\"EagerBuiltFunnySumEager100\", () => res100 |> funnySumEager)\nsuite.add(\"EagerBuiltFunnySumEager10\", () => res10 |> funnySumEager)\n\nres |> funnySum\n//│ = 1001000\n\n:silent\nsuite.add(\"EagerBuiltFunnySum1000\", () => res |> funnySum)\nsuite.add(\"EagerBuiltFunnySum100\", () => res100 |> funnySum)\nsuite.add(\"EagerBuiltFunnySum10\", () => res10 |> funnySum)\n\n// ========================================================================\n\n\nbuildLazy(2).concat([11, 12, 13], LazyArray.mk(2, 4, 6, 8, 10))\n//│ = [2, 1, -1, -2, 11, 12, 13, 2, 4, 6, 8, 10]\n\n:sjs\nfun map(f) = case\n  [a, ..rest] then\n    [f(a), ..map(f)(rest)]\n  [] then []\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let map;\n//│ map = function map(f) {\n//│   let lambda18;\n//│   lambda18 = (undefined, function (caseScrut) {\n//│     let rest, a, middleElements, element0$, tmp3, tmp4, tmp5;\n//│     if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length >= 1) {\n//│       element0$ = runtime.Tuple.get(caseScrut, 0);\n//│       middleElements = runtime.Tuple.slice(caseScrut, 1, 0);\n//│       rest = middleElements;\n//│       a = element0$;\n//│       tmp3 = runtime.safeCall(f(a));\n//│       tmp4 = map(f);\n//│       tmp5 = runtime.safeCall(tmp4(rest));\n//│       return globalThis.Object.freeze(runtime.Tuple.lazyConcat(tmp3, runtime.Tuple.split, tmp5))\n//│     } else if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length === 0) {\n//│       return globalThis.Object.freeze([])\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   });\n//│   return lambda18\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:sjs\nfun mapEager(f) = case\n  [a, ...rest] then\n    [f(a), ...mapEager(f)(rest)]\n  [] then []\n//│ ————————————| JS (unsanitized) |————————————————————————————————————————————————————————————————————\n//│ let mapEager;\n//│ mapEager = function mapEager(f) {\n//│   let lambda18;\n//│   lambda18 = (undefined, function (caseScrut) {\n//│     let rest, a, middleElements, element0$, tmp3, tmp4, tmp5;\n//│     if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length >= 1) {\n//│       element0$ = runtime.Tuple.get(caseScrut, 0);\n//│       middleElements = runtime.Tuple.slice(caseScrut, 1, 0);\n//│       rest = middleElements;\n//│       a = element0$;\n//│       tmp3 = runtime.safeCall(f(a));\n//│       tmp4 = mapEager(f);\n//│       tmp5 = runtime.safeCall(tmp4(rest));\n//│       return globalThis.Object.freeze([\n//│         tmp3,\n//│         ...tmp5\n//│       ])\n//│     } else if (runtime.Tuple.isArrayLike(caseScrut) && caseScrut.length === 0) {\n//│       return globalThis.Object.freeze([])\n//│     }\n//│     throw globalThis.Object.freeze(new globalThis.Error(\"match error\"));\n//│   });\n//│   return lambda18\n//│ };\n//│ —————————————————| Output |—————————————————————————————————————————————————————————————————————————\n\n:silent\nlet res = buildEager(1500)\nlet res150 = buildEager(150)\nlet res15 = buildEager(15)\n\n:silent\nlet lm = map(x => x + 1)(res)\n\n:silent\nmapEager(x => x + 1)(res)\n\n:silent\nsuite.add(\"EagerBuiltMapLazy1500\", () => materialize(map(x => x + 1)(res)))\nsuite.add(\"EagerBuiltMapLazy150\", () => materialize(map(x => x + 1)(res150)))\nsuite.add(\"EagerBuiltMapLazy15\", () => materialize(map(x => x + 1)(res15)))\n\n:silent\nsuite.add(\"EagerBuiltMapEager1500\", () => \n  mapEager(x => x + 1)(res))\nsuite.add(\"EagerBuiltMapEager150\", () =>\n  mapEager(x => x + 1)(res150))\nsuite.add(\"EagerBuiltMapEager15\", () =>\n  mapEager(x => x + 1)(res15))\n\nfun map2(f) = case\n  [a, ..rest, b] then \n    [f(a), ..map2(f)(rest), f(b)]\n  [] then []\n\nfun map2Eager(f) = case\n  [a, ...rest, b] then \n    [f(a), ...map2Eager(f)(rest), f(b)]\n  [] then []\n\n:silent\nsuite.add(\"EagerBuiltMap2Lazy1500\", () => materialize(map2(x => x + 1)(res)))\nsuite.add(\"EagerBuiltMap2Lazy150\", () => materialize(map2(x => x + 1)(res150)))\nsuite.add(\"EagerBuiltMap2Lazy15\", () => materialize(map2(x => x + 1)(res15)))\n\n:silent\nsuite.add(\"EagerBuiltMap2Eager1500\", () => \n  map2Eager(x => x + 1)(res))\nsuite.add(\"EagerBuiltMap2Eager150\", () =>\n  map2Eager(x => x + 1)(res150))\nsuite.add(\"EagerBuiltMap2Eager15\", () =>\n  map2Eager(x => x + 1)(res15))\n\n:ge\nmapEager(..[[1]])\n//│ ╔══[COMPILATION ERROR] Lazy spreads are not supported in call arguments\n//│ ║  l.288: \tmapEager(..[[1]])\n//│ ╙──       \t        ^^^^^^^^^\n//│ ═══[RUNTIME ERROR] Error: Function 'mapEager' expected 1 argument but got 2\n\n:e\nfun what(..args) = args\n//│ ╔══[COMPILATION ERROR] Lazy spread parameters not allowed.\n//│ ║  l.295: \tfun what(..args) = args\n//│ ╙──       \t         ^^^^^^\n\nfun silly = case\n  [a, b, ..xs] then [..xs, ..silly([a, ..xs])]\n  [a, ..xs] then [a, ..silly(xs)]\n  [] then []\n\nfun sillyEager = case\n  [a, b, ...xs] then [...xs, ...sillyEager([a, ...xs])]\n  [a, ...xs] then [a, ...sillyEager(xs)]\n  [] then []\n\n:silent\nlet xs = buildEager(150)\n\n:silent\nlet ys = silly(xs)\n\n:silent\nsuite.add(\"EagerBuiltSillyLazy1500\", () => \n  let xs = buildEager(1500)\n  let ys = silly(xs)\n  materialize(ys))\nsuite.add(\"EagerBuiltSillyLazy150\", () => \n  let xs = buildEager(150)\n  let ys = silly(xs)\n  materialize(ys))\nsuite.add(\"EagerBuiltSillyLazy15\", () => \n  let xs = buildEager(15)\n  let ys = silly(xs)\n  materialize(ys))\n\n:silent\nsillyEager(xs)\n\n:silent\nsuite.add(\"EagerBuiltSillyEager150\", () => \n  let xs = buildEager(150)\n  sillyEager(xs))\nsuite.add(\"EagerBuiltSillyEager15\", () =>\n  let xs = buildEager(15)\n  sillyEager(xs))\n\n:silent\nlet configs = tuple of\n  LazyArray.{      (name: \"LazyArray\",      lazySlice: dropLeftRight, lazyConcat: __concat,       split: __split) }\n  FingerTreeList.{ (name: \"FingerTreeList\", lazySlice: dropLeftRight, lazyConcat: __markerConcat, split: __split) }\n  LazyFingerTree.{ (name: \"LazyFingerTree\", lazySlice: dropLeftRight, lazyConcat: __concat,       split: __split) }\n\nlet i = 0\nwhile i < configs.length do\n  let cfg = configs.[i]\n  let name = cfg.name\n  // dirty hack to modify lazy spread behavior\n  set Runtime.Tuple.lazySlice = (xs, a, b) => cfg.lazySlice(a, b)(xs)\n  set Runtime.Tuple.lazyConcat = cfg.lazyConcat\n  set Runtime.Tuple.split = cfg.split\n  \n  suite |> runSuite\n  writeResults(suite, name + \".json\")\n  set i += 1\n//│ i = 3\n\n\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/mlscript-compile/Benchmark.mls",
    "content": "import \"benchmark\"\n\nlet bm = benchmark\n\nmodule Benchmark with...\n\nval benchmark = bm\nlet prefixPath = \"hkmc2Benchmarks/src/test/logs/\"\n\nfun mkSuite() = new! mut bm.Suite()\n\nfun setPrefixPath(path) = set prefixPath = path\n\nfun runSuite(suite) =\n  let settings = { async: false }\n  suite.run(settings)\n\nfun writeResults(suite, path) =\n  let jsonStr = JSON.stringify(suite.map((res, _, _) => res), null, 2)\n  fs.writeFileSync(prefixPath + path, jsonStr)\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/nofibs-bench1.mls",
    "content": ":js\n:silent\n\n// Comment to run the benchmarks\n:exit\n====================================================================================================\n\n\nimport \"./mlscript-compile/Benchmark.mls\"\nopen Benchmark\n\n\nlet suite = mkSuite()\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/ansi.mls\"\nsuite.add(\"ansi\", () => ansi.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/atom.mls\"\nsuite.add(\"atom\", () => atom.main())\n\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/awards.mls\"\nsuite.add(\"awards\", () => awards.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/banner.mls\"\nsuite.add(\"banner\", () => banner.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/lcss.mls\"\nsuite.add(\"lcss\", () => lcss.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/boyer.mls\"\nsuite.add(\"boyer\", () => boyer.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/boyer2.mls\"\nsuite.add(\"boyer2\", () => boyer2.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/calendar.mls\"\nsuite.add(\"calendar\", () => calendar.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/cichelli.mls\"\nsuite.add(\"cichelli\", () => cichelli.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/circsim.mls\"\nsuite.add(\"circsim\", () => circsim.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/clausify.mls\"\nsuite.add(\"clausify\", () => clausify.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/constraints.mls\"\nsuite.add(\"constraints\", () => constraints.main())\n\n\nrunSuite(suite)\nwriteResults(suite, \"nofibs1.json\")\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/nofibs-bench2.mls",
    "content": ":js\n:silent\n\n\n// Comment to run the benchmarks\n:exit\n====================================================================================================\n\n\nimport \"./mlscript-compile/Benchmark.mls\"\nopen Benchmark\n\n\nlet suite = mkSuite()\n\n\n\n\n// need more stack space\n// import \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/cryptarithm1.mls\"\n// suite.add(\"cryptarithm1\", () => cryptarithm1.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/cryptarithm2.mls\"\nsuite.add(\"cryptarithm2\", () => cryptarithm2.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/cse.mls\"\nsuite.add(\"cse\", () => cse.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/eliza.mls\"\nsuite.add(\"eliza\", () => eliza.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/gcd.mls\"\nsuite.add(\"gcd\", () => gcd.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/integer.mls\"\nsuite.add(\"integer\", () => integer.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/knights.mls\"\nsuite.add(\"knights\", () => knights.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/lambda.mls\"\nsuite.add(\"lambda\", () => lambda.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/lastpiece.mls\"\nsuite.add(\"lastpiece\", () => lastpiece.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/life.mls\"\nsuite.add(\"life\", () => life.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/mandel.mls\"\nsuite.add(\"mandel\", () => mandel.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/mandel2.mls\"\nsuite.add(\"mandel2\", () => mandel2.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/mate.mls\"\nsuite.add(\"mate\", () => mate.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/minimax.mls\"\nsuite.add(\"minimax\", () => minimax.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/para.mls\"\nsuite.add(\"para\", () => para.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/power.mls\"\nsuite.add(\"power\", () => power.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/pretty.mls\"\nsuite.add(\"pretty\", () => pretty.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/primetest.mls\"\nsuite.add(\"primetest\", () => primetest.main())\n\n\n// =======================\n\n// need more stack\n// import \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/puzzle.mls\"\n// suite.add(\"puzzle\", () => puzzle.main())\n\n\nrunSuite(suite)\nwriteResults(suite, \"nofibs2.json\")\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/nofibs-bench3.mls",
    "content": ":js\n:silent\n\n\n// Comment to run the benchmarks\n:exit\n====================================================================================================\n\n\nimport \"./mlscript-compile/Benchmark.mls\"\nopen Benchmark\n\n\nlet suite = mkSuite()\n\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/rsa.mls\"\nsuite.add(\"rsa\", () => rsa.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/scc.mls\"\nsuite.add(\"scc\", () => scc.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/secretary.mls\"\nsuite.add(\"secretary\", () => secretary.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/sorting.mls\"\nsuite.add(\"sorting\", () => sorting.main())\n\n\n// =======================\n\n\nimport \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/sphere.mls\"\nsuite.add(\"sphere\", () => sphere.main())\n\n\n// =======================\n\n\n// need more stack\n// import \"../../../../hkmc2/shared/src/test/mlscript-compile/nofib/treejoin.mls\"\n// suite.add(\"treejoin\", () => treejoin.main())\n\n\n\n\n\nrunSuite(suite)\nwriteResults(suite, \"nofibs3.json\")\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/bench/viz.html",
    "content": "<!-- Disclaimer: This HTML is not human-written. It is written by Claude 4 (LLM). \n    LLM even offered to auto-complete some of this comment... No thanks, LLM. -->\n\n<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Benchmark Results Visualization</title>\n  <script src=\"https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.26.0/plotly.min.js\"></script>\n  <style>\n    body {\n      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n      margin: 0;\n      padding: 20px;\n      background-color: #f8f9fa;\n    }\n\n    .container {\n      max-width: 1200px;\n      margin: 0 auto;\n      background-color: white;\n      padding: 30px;\n      border-radius: 10px;\n      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n    }\n\n    .header {\n      text-align: center;\n      margin-bottom: 30px;\n      padding-bottom: 20px;\n      border-bottom: 2px solid #e9ecef;\n    }\n\n    .header h1 {\n      color: #2c3e50;\n      margin: 0;\n      font-size: 2.5em;\n    }\n\n    .header p {\n      color: #6c757d;\n      margin: 10px 0;\n    }\n\n    .controls {\n      background-color: #f8f9fa;\n      padding: 20px;\n      border-radius: 8px;\n      margin-bottom: 20px;\n    }\n\n    .file-upload {\n      margin-bottom: 20px;\n    }\n\n    .file-upload input[type=\"file\"] {\n      padding: 10px;\n      border: 2px dashed #007bff;\n      border-radius: 5px;\n      width: 100%;\n      background-color: white;\n    }\n\n    .benchmark-selection {\n      margin-bottom: 20px;\n    }\n\n    .checkbox-container {\n      display: grid;\n      grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\n      gap: 10px;\n      margin: 10px 0;\n    }\n\n    .checkbox-item {\n      display: flex;\n      align-items: center;\n      padding: 8px;\n      background-color: white;\n      border-radius: 4px;\n      border: 1px solid #dee2e6;\n    }\n\n    .checkbox-item input {\n      margin-right: 8px;\n      flex-shrink: 0;\n    }\n\n    .checkbox-item label {\n      overflow: hidden;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n      cursor: pointer;\n      flex: 1;\n      min-width: 0;\n    }\n\n    .control-buttons {\n      margin: 10px 0;\n    }\n\n    .btn {\n      padding: 8px 16px;\n      margin: 0 5px;\n      border: none;\n      border-radius: 4px;\n      cursor: pointer;\n      font-size: 14px;\n    }\n\n    .btn-primary {\n      background-color: #007bff;\n      color: white;\n    }\n\n    .btn-secondary {\n      background-color: #6c757d;\n      color: white;\n    }\n\n    .btn:hover {\n      opacity: 0.8;\n    }\n\n    .chart-container {\n      margin: 20px 0;\n      min-height: 600px;\n    }\n\n    .stats-container {\n      margin-top: 30px;\n    }\n\n    .tabs {\n      display: flex;\n      border-bottom: 2px solid #dee2e6;\n      margin-bottom: 20px;\n    }\n\n    .tab {\n      padding: 12px 24px;\n      cursor: pointer;\n      border: none;\n      background-color: transparent;\n      border-bottom: 3px solid transparent;\n      font-size: 16px;\n    }\n\n    .tab.active {\n      border-bottom-color: #007bff;\n      color: #007bff;\n      font-weight: bold;\n    }\n\n    .tab-content {\n      display: none;\n    }\n\n    .tab-content.active {\n      display: block;\n    }\n\n    .table {\n      width: 100%;\n      border-collapse: collapse;\n      margin: 20px 0;\n    }\n\n    .table th,\n    .table td {\n      padding: 12px;\n      text-align: left;\n      border-bottom: 1px solid #dee2e6;\n    }\n\n    .table th {\n      background-color: #f8f9fa;\n      font-weight: bold;\n    }\n\n    .metrics {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n      gap: 20px;\n      margin: 20px 0;\n    }\n\n    .metric-card {\n      background-color: #f8f9fa;\n      padding: 20px;\n      border-radius: 8px;\n      text-align: center;\n      border-left: 4px solid #007bff;\n    }\n\n    .metric-title {\n      font-size: 14px;\n      color: #6c757d;\n      margin-bottom: 8px;\n    }\n\n    .metric-value {\n      font-size: 24px;\n      font-weight: bold;\n      color: #2c3e50;\n    }\n\n    .warning {\n      background-color: #fff3cd;\n      color: #856404;\n      padding: 15px;\n      border-radius: 5px;\n      margin: 20px 0;\n      border-left: 4px solid #ffc107;\n    }\n  </style>\n</head>\n\n<body>\n  <div class=\"container\">\n    <div class=\"header\">\n      <h1>📊 Benchmark Results Visualization</h1>\n      <p>Upload your JSON benchmark files to visualize execution times with error bars</p>\n    </div>\n\n    <div class=\"controls\">\n      <div class=\"file-upload\">\n        <label for=\"fileInput\"><strong>Upload JSON Files:</strong></label>\n        <input type=\"file\" id=\"fileInput\" multiple accept=\".json\">\n      </div>\n\n      <div class=\"benchmark-selection\" id=\"benchmarkSelection\" style=\"display: none;\">\n        <h3>Select Benchmarks to Display:</h3>\n        <div class=\"control-buttons\">\n          <button class=\"btn btn-primary\" onclick=\"selectAllBenchmarks()\">Select All</button>\n          <button class=\"btn btn-secondary\" onclick=\"clearAllBenchmarks()\">Clear All</button>\n        </div>\n        <div class=\"checkbox-container\" id=\"checkboxContainer\"></div>\n      </div>\n    </div>\n\n    <div class=\"chart-container\">\n      <div id=\"benchmarkChart\"></div>\n    </div>\n\n    <div class=\"stats-container\" id=\"statsContainer\" style=\"display: none;\">\n      <h2>Summary Statistics by File</h2>\n      <div class=\"tabs\" id=\"tabsContainer\"></div>\n      <div id=\"tabContentContainer\"></div>\n    </div>\n\n    <div id=\"rawDataContainer\" style=\"display: none;\">\n      <h2>Raw Data</h2>\n      <table class=\"table\" id=\"rawDataTable\">\n        <thead>\n          <tr>\n            <th>Benchmark</th>\n            <th>Mean (ms)</th>\n            <th>MOE (ms)</th>\n            <th>SEM (ms)</th>\n            <th>Hz</th>\n          </tr>\n        </thead>\n        <tbody id=\"rawDataBody\"></tbody>\n      </table>\n    </div>\n  </div>\n\n  <script>\n    let benchmarkData = [];\n    let allBenchmarks = [];\n    let selectedBenchmarks = [];\n\n    // Load example data\n    function loadExampleData() {\n      const exampleData = [\n        {\n          name: 'buildLazy',\n          filename: 'benchmark1',\n          label: 'buildLazy#benchmark1',\n          mean_ms: 0.176,\n          moe_ms: 0.0025,\n          sem_ms: 0.00128,\n          hz: 5676\n        },\n        {\n          name: 'processData',\n          filename: 'benchmark1',\n          label: 'processData#benchmark1',\n          mean_ms: 0.234,\n          moe_ms: 0.0034,\n          sem_ms: 0.00174,\n          hz: 4274\n        },\n        {\n          name: 'renderComponent',\n          filename: 'benchmark1',\n          label: 'renderComponent#benchmark1',\n          mean_ms: 0.198,\n          moe_ms: 0.0029,\n          sem_ms: 0.00148,\n          hz: 5051\n        },\n        {\n          name: 'buildLazy',\n          filename: 'benchmark2',\n          label: 'buildLazy#benchmark2',\n          mean_ms: 0.182,\n          moe_ms: 0.0028,\n          sem_ms: 0.00143,\n          hz: 5495\n        },\n        {\n          name: 'processData',\n          filename: 'benchmark2',\n          label: 'processData#benchmark2',\n          mean_ms: 0.219,\n          moe_ms: 0.0031,\n          sem_ms: 0.00158,\n          hz: 4566\n        }\n      ];\n\n      benchmarkData = exampleData;\n      allBenchmarks = exampleData.map(d => d.label);\n      selectedBenchmarks = [...allBenchmarks];\n\n      showWarning();\n      updateInterface();\n    }\n\n    function showWarning() {\n      const chartDiv = document.getElementById('benchmarkChart');\n      chartDiv.innerHTML = `\n                <div class=\"warning\">\n                    <strong>Showing example data.</strong> Upload your JSON files to see actual results.\n                </div>\n            `;\n    }\n\n    // Handle file upload\n    document.getElementById('fileInput').addEventListener('change', function(event) {\n      const files = event.target.files;\n      if (files.length === 0) return;\n\n      benchmarkData = [];\n      let filesProcessed = 0;\n\n      Array.from(files).forEach(file => {\n        const reader = new FileReader();\n        reader.onload = function(e) {\n          try {\n            const data = JSON.parse(e.target.result);\n            const filename = file.name.replace('.json', '');\n\n            // Handle both single benchmark and array of benchmarks\n            const benchmarks = Array.isArray(data) ? data : [data];\n\n            benchmarks.forEach(benchmark => {\n              benchmarkData.push({\n                name: benchmark.name,\n                filename: filename,\n                label: `${benchmark.name}#${filename}`,\n                mean_ms: benchmark.stats.mean * 1000,\n                moe_ms: benchmark.stats.moe * 1000,\n                sem_ms: benchmark.stats.sem * 1000,\n                hz: benchmark.hz || 0\n              });\n            });\n\n            filesProcessed++;\n            if (filesProcessed === files.length) {\n              allBenchmarks = benchmarkData.map(d => d.label);\n              selectedBenchmarks = [...allBenchmarks];\n              updateInterface();\n            }\n          } catch (error) {\n            console.error(`Error processing ${file.name}:`, error);\n            alert(`Error processing ${file.name}: ${error.message}`);\n          }\n        };\n        reader.readAsText(file);\n      });\n    });\n\n    function updateInterface() {\n      createBenchmarkSelection();\n      updateChart();\n      createStatsTabs();\n      updateRawDataTable();\n\n      document.getElementById('benchmarkSelection').style.display = 'block';\n      document.getElementById('statsContainer').style.display = 'block';\n      document.getElementById('rawDataContainer').style.display = 'block';\n    }\n\n    function createBenchmarkSelection() {\n      const container = document.getElementById('checkboxContainer');\n      container.innerHTML = '';\n\n      allBenchmarks.forEach(benchmark => {\n        const div = document.createElement('div');\n        div.className = 'checkbox-item';\n\n        const checkbox = document.createElement('input');\n        checkbox.type = 'checkbox';\n        checkbox.id = `checkbox-${benchmark}`;\n        checkbox.checked = selectedBenchmarks.includes(benchmark);\n        checkbox.addEventListener('change', function() {\n          if (this.checked) {\n            if (!selectedBenchmarks.includes(benchmark)) {\n              selectedBenchmarks.push(benchmark);\n            }\n          } else {\n            selectedBenchmarks = selectedBenchmarks.filter(b => b !== benchmark);\n          }\n          updateChart();\n        });\n\n        const label = document.createElement('label');\n        label.htmlFor = `checkbox-${benchmark}`;\n        label.textContent = benchmark;\n\n        div.appendChild(checkbox);\n        div.appendChild(label);\n        container.appendChild(div);\n      });\n    }\n\n    function selectAllBenchmarks() {\n      selectedBenchmarks = [...allBenchmarks];\n      updateCheckboxes();\n      updateChart();\n    }\n\n    function clearAllBenchmarks() {\n      selectedBenchmarks = [];\n      updateCheckboxes();\n      updateChart();\n    }\n\n    function updateCheckboxes() {\n      allBenchmarks.forEach(benchmark => {\n        const checkbox = document.getElementById(`checkbox-${benchmark}`);\n        if (checkbox) {\n          checkbox.checked = selectedBenchmarks.includes(benchmark);\n        }\n      });\n    }\n\n    function updateChart() {\n      const filteredData = benchmarkData.filter(d => selectedBenchmarks.includes(d.label));\n\n      if (filteredData.length === 0) {\n        document.getElementById('benchmarkChart').innerHTML =\n          '<div class=\"warning\">Please select at least one benchmark to display the chart.</div>';\n        return;\n      }\n\n      const trace = {\n        x: filteredData.map(d => d.label),\n        y: filteredData.map(d => d.mean_ms),\n        error_y: {\n          type: 'data',\n          array: filteredData.map(d => d.moe_ms),\n          visible: true,\n          color: 'red',\n          thickness: 2,\n          width: 3\n        },\n        type: 'bar',\n        name: 'Mean Time (ms)',\n        text: filteredData.map(d => `${d.mean_ms.toFixed(4)} ms`),\n        textposition: 'outside',\n        hovertemplate: '<b>%{x}</b><br>' +\n          'Mean Time: %{y:.4f} ms<br>' +\n          'Margin of Error: %{error_y.array:.4f} ms<br>' +\n          '<extra></extra>'\n      };\n\n      const layout = {\n        title: 'Benchmark Results - Mean Execution Time with Error Bars',\n        xaxis: {\n          title: 'Benchmark (name#filename)',\n          tickangle: 45\n        },\n        yaxis: {\n          title: 'Time (milliseconds)'\n        },\n        height: 600,\n        showlegend: false,\n        template: 'plotly_white'\n      };\n\n      Plotly.newPlot('benchmarkChart', [trace], layout, { responsive: true });\n    }\n\n    function createStatsTabs() {\n      const uniqueFiles = [...new Set(benchmarkData.map(d => d.filename))];\n      const tabsContainer = document.getElementById('tabsContainer');\n      const contentContainer = document.getElementById('tabContentContainer');\n\n      tabsContainer.innerHTML = '';\n      contentContainer.innerHTML = '';\n\n      uniqueFiles.forEach((filename, index) => {\n        // Create tab button\n        const tab = document.createElement('button');\n        tab.className = `tab ${index === 0 ? 'active' : ''}`;\n        tab.textContent = `File: ${filename}`;\n        tab.onclick = () => showTab(filename);\n        tabsContainer.appendChild(tab);\n\n        // Create tab content\n        const fileData = benchmarkData.filter(d => d.filename === filename);\n        const tabContent = document.createElement('div');\n        tabContent.className = `tab-content ${index === 0 ? 'active' : ''}`;\n        tabContent.id = `tab-${filename}`;\n\n        // Create metrics\n        const avgTime = fileData.reduce((sum, d) => sum + d.mean_ms, 0) / fileData.length;\n        const avgHz = fileData.filter(d => d.hz > 0).reduce((sum, d) => sum + d.hz, 0) / fileData.filter(d => d.hz > 0).length || 0;\n\n        tabContent.innerHTML = `\n                    <div class=\"metrics\">\n                      <div class=\"metric-card\">\n                        <div class=\"metric-title\">Total Benchmarks</div>\n                        <div class=\"metric-value\">${fileData.length}</div>\n                      </div>\n                      <div class=\"metric-card\">\n                        <div class=\"metric-title\">Average Time</div>\n                        <div class=\"metric-value\">${avgTime.toFixed(4)} ms</div>\n                      </div>\n                      <div class=\"metric-card\">\n                        <div class=\"metric-title\">Average Frequency</div>\n                        <div class=\"metric-value\">${avgHz > 0 ? avgHz.toFixed(2) + ' Hz' : 'N/A'}</div>\n                      </div>\n                    </div>\n                    <table class=\"table\">\n                      <thead>\n                        <tr>\n                          <th>Benchmark</th>\n                          <th>Mean (ms)</th>\n                          <th>MOE (ms)</th>\n                          <th>SEM (ms)</th>\n                          <th>Frequency (Hz)</th>\n                        </tr>\n                      </thead>\n                      <tbody>\n                        ${fileData.map(d => `\n                          <tr>\n                            <td>${d.name}</td>\n                            <td>${d.mean_ms.toFixed(4)}</td>\n                            <td>${d.moe_ms.toFixed(4)}</td>\n                            <td>${d.sem_ms.toFixed(4)}</td>\n                            <td>${d.hz > 0 ? d.hz.toFixed(2) : 'N/A'}</td>\n                          </tr>\n                        `).join('')}\n                      </tbody>\n                    </table>\n                `;\n\n        contentContainer.appendChild(tabContent);\n      });\n    }\n\n    function showTab(filename) {\n      // Update tab buttons\n      document.querySelectorAll('.tab').forEach(tab => {\n        tab.classList.remove('active');\n        if (tab.textContent === `File: ${filename}`) {\n          tab.classList.add('active');\n        }\n      });\n\n      // Update tab content\n      document.querySelectorAll('.tab-content').forEach(content => {\n        content.classList.remove('active');\n      });\n      document.getElementById(`tab-${filename}`).classList.add('active');\n    }\n\n    function updateRawDataTable() {\n      const tbody = document.getElementById('rawDataBody');\n      tbody.innerHTML = '';\n\n      benchmarkData.forEach(d => {\n        const row = document.createElement('tr');\n        row.innerHTML = `\n                    <td>${d.label}</td>\n                    <td>${d.mean_ms.toFixed(4)}</td>\n                    <td>${d.moe_ms.toFixed(4)}</td>\n                    <td>${d.sem_ms.toFixed(4)}</td>\n                    <td>${d.hz > 0 ? d.hz.toFixed(2) : 'N/A'}</td>\n                `;\n        tbody.appendChild(row);\n      });\n    }\n\n    // Initialize with example data\n    loadExampleData();\n  </script>\n</body>\n\n</html>\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/logs/.gitignore",
    "content": "*.json\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/scala/hkmc2/BenchDiffMaker.scala",
    "content": "package hkmc2\n\nimport mlscript.utils._, shorthands._\nimport hkmc2.syntax.Tree\nimport hkmc2.syntax.Keyword\n\n\nclass BenchDiffMaker\n    (val rootPath: Str, val file: io.Path, val preludeFile: io.Path, val predefFile: io.Path, val relativeName: Str)\n    (using val cctx: CompilerCtx)\n  extends LlirDiffMaker:\n  \n  override def processTerm(blk: semantics.Term.Blk, inImport: Bool)(using Config, Raise): Unit =\n    super.processTerm(blk, inImport)\n\n\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/scala/hkmc2/BenchTestRunner.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\n\nimport mlscript.utils._\nimport os.Path\nimport io.PlatformPath.given\n\nobject BenchTestState extends DiffTestRunner.State:\n\n  override def testDir = workingDir/\"hkmc2Benchmarks\"/\"src\"/\"test\"/\"bench\"\n\n  override val TimeLimit = Span(1, Hour)\n\nclass BenchTestRunner\n  extends DiffTestRunnerBase(BenchTestState)\n  with ParallelTestExecution\n:\n  override protected def createDiffMaker\n      (file: Path, preludePath: Path, predefPath: Path, relativeName: String)\n      : DiffMaker =\n    new BenchDiffMaker(state.workingDir.toString, file, preludePath, predefPath, relativeName)(using state.cctx)\n\n"
  },
  {
    "path": "hkmc2Benchmarks/src/test/scala/hkmc2/Watcher.scala",
    "content": "package hkmc2\n\nimport better.files.*\n\nobject MainWatcher extends Watcher(File(\"../hkmc2/shared/src\") :: File(\"./src\") :: File(\"../hkmc2DiffTests/src\") :: Nil):\n  def main(args: Array[String]): Unit = run\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/out/Basic Document Tests.out",
    "content": "// Generated from: hkmc2DiffTests/src/test/scala/hkmc2/DocumentTests.scala\n\n// L.44:\n//\tDocCons(DocText(hello),DocCons(DocText( ),DocText(world)))\nhello world\n\n// L.46:\n//\tDocNest(2,DocCons(DocText(hello),DocCons(DocBreak(false),DocText(world))))\n  hello world\n\n// L.48:\nhello hello hello\nworld world world\n\n// L.50:\nhello\nworld\n\n// L.52:\n  hello\n  world\n\n// L.54:\n  hello hello hello\n  world world world\n\n// L.56:\nhello hello hello\nworld world world\n\n// L.58:\n  hello hello hello\n  world world world\n\n// L.60:\nhi hi world world\n\n// L.62:\nhi\nhi\nworld world\n\n// L.64:\nhi hi W W ! !\n\n// L.66:\nhi\nhi\nW W\n! !\n\n// L.68:\nhi\nhi\nW\nW\n! !\n\n// L.70:\nhi\nhi\nworld\nworld\n\n// L.72:\nhello\nhello\nhello\nworld world world\n\n// L.74:\nhello\nhello\nhello\nuniverse\nuniverse\nuniverse\n\n// L.76:\n  hello\n  hello\n  hello\n  world world world\n\n// L.78:\n  hello\n  hello\n  hello\n  world world world\n\n// L.80:\n  hello\n  hello\n  hello\n  world\n  world\n  world\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/DiffMaker.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\nimport mlscript.utils.*, shorthands.*\nimport hkmc2.utils.*\n\n\n\nclass Outputter(val out: java.io.PrintWriter):\n  \n  val outputMarker = \"//│ \"\n  // val oldOutputMarker = \"/// \"\n\n  val diffBegMarker = \"<<<<<<<\"\n  val diffMidMarker = \"=======\"\n  val diff3MidMarker = \"|||||||\" // * Appears under `git config merge.conflictstyle diff3` (https://stackoverflow.com/a/18131595/1518588)\n  val diffEndMarker = \">>>>>>>\"\n\n  val ColWidth = 100\n  val exitMarker = \"=\" * ColWidth\n  val blockSeparator = \"—\" * 80\n  \n  val fullBlockSeparator = outputMarker + blockSeparator\n  \n  /** Tracks the net difference between lines written to the output and lines\n    * consumed from the original file so far. Adding a new output line (via\n    * [[apply]]) increments it; consuming an original output line (starting\n    * with [[outputMarker]]) decrements it. This is used to adjust block\n    * line numbers so they refer to positions in the output file rather than\n    * the original, avoiding the need for a second run to stabilize them. */\n  var linesDelta: Int = 0\n  \n  def apply(str: String) =\n    // out.println(outputMarker + str)\n    val ls = str.splitSane('\\n')\n    linesDelta += ls.size\n    ls.foreach(l => out.println(outputMarker + l))\n\n\n\nabstract class DiffMaker:\n  \n  def cctx: CompilerCtx\n  given CompilerCtx = cctx\n  \n  val file: io.Path\n  val relativeName: Str\n  \n  def processOrigin(origin: Origin)(using Raise): Unit\n  \n  \n  val dbgPrinter: DebugPrinter\n  given dbgPrinter.type = dbgPrinter\n  \n  \n  def doFail(blockLineNum: Int, msg: String): Unit =\n    System.err.println(fansi.Color.Red(\"FAILURE: \").toString + msg)\n  def unhandled(blockLineNum: Int, exc: Throwable): Unit =\n    unexpected(\"exception\", blockLineNum, N, () => N)\n  \n  final def unexpected(what: Str, blockLineNum: Int, srcLoc: Opt[Str], mkExtraInfo: () => Opt[Any]): Unit =\n    output(s\"FAILURE: Unexpected $what\")\n    srcLoc match\n      case S(loc) => output(s\"FAILURE LOCATION: $loc\")\n      case N => ()\n    mkExtraInfo() match\n      case S(info: Product) => output(s\"FAILURE INFO: ${info.showAsTree}\")\n      case S(info) => output(s\"FAILURE INFO: ${info.showAsPlain}\")\n      case N => ()\n    doFail(blockLineNum, s\"unexpected $what at $relativeName.${file.ext}:\" + blockLineNum)\n  \n  \n  \n  private val commands: mutable.Map[Str, Command[?]] = mutable.Map.empty\n  \n  def resetCommands: Unit =\n    commands.valuesIterator.foreach(cmd =>\n      if !cmd.isGlobal then cmd.unset)\n  \n  class Command[A](val name: Str, var isGlobal: Bool = false)(val process: Str => A):\n    require(name.nonEmpty)\n    // require(name.forall(l => l.isLetterOrDigit || l === '!'))\n    if commands.contains(name) then\n      throw new IllegalArgumentException(s\"Option '$name' already exists\")\n    commands += name -> this\n    private var currentValue: Opt[A] = N\n    private[hkmc2] def setCurrentValue(a: A): Unit =\n      currentValue = S(a)\n      onSet()\n    def get: Opt[A] = currentValue\n    def isSet: Bool = currentValue.isDefined\n    def isUnset: Bool = !isSet\n    def unset: Unit = currentValue = N\n    def onSet(): Unit = ()\n    override def toString: Str = s\"${if isGlobal then \"global \" else \"\"}$name: $currentValue\"\n  \n  class NullaryCommand[R](name: Str, k: () => R = () => ()) extends Command[R](name)(\n    line =>\n      val commentIndex = line.indexOf(\"//\")\n      val body = if commentIndex == -1 then line else line.take(commentIndex)\n      // assert(body.forall(_.isWhitespace))\n      if !body.forall(_.isWhitespace) then\n        output(s\"/!\\\\ Warning: non-empty body for command '$name' is ignored: '$body'\")\n      k()\n    ):\n    def set: Unit = setCurrentValue(k())\n  \n  class FlagCommand(init: Bool, name: Str) extends NullaryCommand(name):\n    self =>\n    val disable = new NullaryCommand(\"!\" + name):\n      override def onSet(): Unit =\n        if isSet then self.unset\n        else self.setCurrentValue(())\n    if init then setCurrentValue(()) else disable.setCurrentValue(())\n  \n  val initCmd = NullaryCommand(\"init\")\n  initCmd.setCurrentValue(()) // * Starts enabled at the top of the file\n  val global = NullaryCommand(\"global\")\n  global.setCurrentValue(()) // * Starts enabled at the top of the file\n  \n  val consumeEmptyLines = NullaryCommand(\"...\", () =>\n    output(output.blockSeparator)\n  )\n  \n  val fixme = Command(\"fixme\")(_ => ())\n  val todo = Command(\"todo\")(_ => ())\n  val breakme = Command(\"breakme\")(_ => ())\n  val ignore = Command(\"ignore\")(_ => ())\n  def expectErrors = fixme.isSet || todo.isSet\n  def tolerateErrors = expectErrors || ignore.isSet\n  \n  val fullExceptionStack = NullaryCommand(\"s\")\n  \n  val verbose = NullaryCommand(\"v\")\n  val debug = NullaryCommand(\"d\")\n  \n  val expectParseErrors = NullaryCommand(\"pe\")\n  val expectTypeErrors = NullaryCommand(\"te\")\n  val expectTypeOrCodeGenErrors = NullaryCommand(\"e\")\n  val expectRuntimeErrors = NullaryCommand(\"re\")\n  val expectCodeGenErrors = NullaryCommand(\"ge\")\n  def expectRuntimeOrCodeGenErrors =\n    expectRuntimeErrors.isSet || expectCodeGenErrors.isSet || expectTypeOrCodeGenErrors.isSet\n  val allowRuntimeErrors = NullaryCommand(\"allowRuntimeErrors\")\n  val expectWarnings = NullaryCommand(\"w\")\n  val showRelativeLineNums = NullaryCommand(\"showRelativeLineNums\")\n  \n  \n  val tests = Command(\"tests\"):\n    case \"\" =>\n      // * Note that making `DiffTestRunnerBase` extend `ParallelTestExecution`,\n      // * as we used to do, is quite dangerous, because of the way ScalaTest works (which is pretty dumb):\n      // * it would try to re-instantiate the test classes haphazardly without passing it any arguments,\n      // * which either crashes (as it would here) or recomputes the state every time\n      // * (as would be the case if we created an anonymous subclass here),\n      // * even when the tests, when run with `execute()`, are not run in parallel (also for dumb reasons).\n      DiffTestRunnerBase(new DiffTestRunner.StateWithGit).execute()\n  \n  \n  val fileName = file.last\n  \n  val fileContents = cctx.fs.read(file)\n  val allLines = fileContents.splitSane('\\n').toList\n  val strw = new java.io.StringWriter\n  val out = new java.io.PrintWriter(strw)\n  val output = Outputter(out)\n  val report = ReportFormatter(output(_), colorize = false)\n  \n  var printedSeparatedSection = false\n  def outputSeparator(title: Str): Unit =\n    printedSeparatedSection = true\n    val totalSepLen = output.ColWidth - title.length - 4\n    val preSepLen = output.ColWidth/5 - title.length/2\n    output(\"—\" * preSepLen + s\"| $title |\" + \"—\" * (totalSepLen - preSepLen))\n  \n  val failures = mutable.Buffer.empty[Int]\n  val unmergedChanges = mutable.Buffer.empty[Int]\n  \n  var _onlyParse = false\n  var _allowTypeErrors = false\n  var _showRelativeLineNums = false\n  \n  \n  val errMarker: Str = \"/!!!\\\\\"\n  \n  def uncaught(err: Throwable): Unit =\n    output(s\"$errMarker Uncaught error: $err\" +\n      err.getStackTrace().take(\n        if fullExceptionStack.isSet || debug.isSet then Int.MaxValue\n        else if tolerateErrors || err.isInstanceOf[StackOverflowError] then 0\n        else 10\n      ).map(\"\\n\" + \"\\tat: \" + _).mkString)\n  \n  \n  def processBlock(origin: Origin): Unit =\n    printedSeparatedSection = false\n    val globalStartLineNum = origin.startLineNum\n    val blockLineNum = origin.startLineNum\n    // * ^ In previous DiffTest versions, these two could be different due to relative line numbers\n    \n    var parseErrors, typeErrors, compilationErrors, runtimeErrors, warnings, internalErrors = 0\n    \n    val raise: Raise = d =>\n      d.kind match\n      case Diagnostic.Kind.Error =>\n        d.source match\n        case Diagnostic.Source.Lexing =>\n          parseErrors += 1\n          if expectParseErrors.isUnset && !tolerateErrors then\n            failures += globalStartLineNum\n            unexpected(\"lexing error\", blockLineNum, S(d.srcLoc), d.mkExtraInfo)\n        case Diagnostic.Source.Parsing =>\n          parseErrors += 1\n          if expectParseErrors.isUnset && !tolerateErrors then\n            failures += globalStartLineNum\n            // doFail(fileName, blockLineNum, \"unexpected parse error at \")\n            unexpected(\"parse error\", blockLineNum, S(d.srcLoc), d.mkExtraInfo)\n            // report(blockLineNum, d :: Nil, showRelativeLineNums.isSet)\n        case Diagnostic.Source.Typing =>\n          typeErrors += 1\n          if expectTypeErrors.isUnset && !tolerateErrors then\n            failures += globalStartLineNum\n            unexpected(\"type error\", blockLineNum, S(d.srcLoc), d.mkExtraInfo)\n        case Diagnostic.Source.Compilation =>\n          compilationErrors += 1\n          if expectCodeGenErrors.isUnset && expectTypeOrCodeGenErrors.isUnset && !tolerateErrors then\n            failures += globalStartLineNum\n            unexpected(\"compilation error\", blockLineNum, S(d.srcLoc), d.mkExtraInfo)\n        case Diagnostic.Source.Runtime =>\n          runtimeErrors += 1\n          if !expectRuntimeOrCodeGenErrors && !tolerateErrors then\n            failures += globalStartLineNum\n            unexpected(\"runtime error\", blockLineNum, S(d.srcLoc), d.mkExtraInfo)\n      case Diagnostic.Kind.Warning =>\n        warnings += 1\n        if expectWarnings.isUnset && !tolerateErrors then\n          failures += globalStartLineNum\n          unexpected(\"warning\", blockLineNum, S(d.srcLoc), d.mkExtraInfo)\n      case Diagnostic.Kind.Internal =>\n        internalErrors += 1\n        if !tolerateErrors then\n          failures += globalStartLineNum\n          unexpected(\"internal error\", blockLineNum, S(d.srcLoc), d.mkExtraInfo)\n        // throw d\n      if fullExceptionStack.isSet then\n        d.printStackTrace()\n      report(blockLineNum, d :: Nil, showRelativeLineNums.isSet)\n    \n    processOrigin(origin)(using raise)\n    \n    // Note: when `todo` is set, we allow the lack of errors.\n    // Use `todo` when the errors are expected but not yet implemented.\n    if expectParseErrors.isSet && parseErrors === 0 && ignore.isUnset && breakme.isUnset then\n      failures += globalStartLineNum\n      unexpected(\"lack of parse error\", blockLineNum, N, () => N)\n    if expectTypeErrors.isSet && typeErrors === 0 && ignore.isUnset && breakme.isUnset then\n      failures += globalStartLineNum\n      unexpected(\"lack of type error\", blockLineNum, N, () => N)\n    if expectCodeGenErrors.isSet && compilationErrors === 0 && ignore.isUnset && breakme.isUnset then\n      failures += globalStartLineNum\n      unexpected(\"lack of compilation error\", blockLineNum, N, () => N)\n    else if expectTypeOrCodeGenErrors.isSet && (compilationErrors + typeErrors) === 0 && ignore.isUnset && breakme.isUnset then\n      failures += globalStartLineNum\n      unexpected(\"lack of compilation or type error\", blockLineNum, N, () => N)\n    if expectRuntimeErrors.isSet && runtimeErrors === 0 && ignore.isUnset && breakme.isUnset then\n      failures += globalStartLineNum\n      unexpected(\"lack of runtime error\", blockLineNum, N, () => N)\n    if expectWarnings.isSet && warnings === 0 && ignore.isUnset && breakme.isUnset then\n      failures += globalStartLineNum\n      unexpected(\"lack of warnings\", blockLineNum, N, () => N)\n    \n    if expectErrors && (\n        + parseErrors\n        + typeErrors\n        + compilationErrors\n        + runtimeErrors\n        + warnings\n        + internalErrors) === 0 then\n      failures += globalStartLineNum\n      unexpected(\"lack of error to fix\", blockLineNum, N, () => N)\n  \n  \n  \n  @annotation.tailrec\n  final def rec(lines: List[String]): Unit = lines match\n    case \"\" :: Nil => // To prevent adding an extra newline at the end\n    case (line @ \"\") :: ls if consumeEmptyLines.isUnset =>\n      out.println(line)\n      if initCmd.isSet then\n        init()\n      resetCommands\n      rec(ls)\n    case \":exit\" :: ls =>\n      out.println(\":exit\")\n      out.println(output.exitMarker)\n      ls.dropWhile(_ =:= output.exitMarker).tails.foreach {\n        case Nil =>\n        case lastLine :: Nil => out.print(lastLine)\n        case l :: _ => out.println(l)\n      }\n    case line :: ls if line.startsWith(\":\") =>\n      out.println(line)\n      \n      val cmd = line.tail.takeWhile(!_.isWhitespace)\n      val rest = line.drop(cmd.length + 1)\n      \n      commands.get(cmd) match\n        case S(cmd) =>\n          if global.isSet then cmd.isGlobal = true\n          cmd.setCurrentValue(cmd.process(rest))\n        case N =>\n          failures += allLines.size - lines.size + 1\n          output(\"/!\\\\ Unrecognized command: \" + cmd)\n      \n      rec(ls)\n    case line :: ls if line.startsWith(output.outputMarker) //|| line.startsWith(oldOutputMarker)\n      =>\n      output.linesDelta -= 1\n      rec(ls)\n    case line :: ls if line.startsWith(\"//\") =>\n      out.println(line)\n      rec(ls)\n    case begLine :: ls if begLine.startsWith(output.diffBegMarker) => // Check if there are unmerged git conflicts\n      val diff = ls.takeWhile(l => !l.startsWith(output.diffEndMarker))\n      assert(diff.exists(_.startsWith(output.diffMidMarker)), diff)\n      val rest = ls.drop(diff.length)\n      val hdo = rest.head\n      assert(hdo.startsWith(output.diffEndMarker), hdo)\n      val blankLines = diff.count(_.isEmpty)\n      val hasBlankLines = diff.exists(_.isEmpty)\n      if diff.forall(l => l.startsWith(output.outputMarker) || l.startsWith(output.diffMidMarker) || l.startsWith(output.diff3MidMarker) || l.isEmpty) then {\n        for _ <- 1 to blankLines do out.println()\n      } else {\n        val blockLineNum = allLines.size - lines.size + 1\n        failures += blockLineNum\n        doFail(blockLineNum,\n          s\"Unmerged non-output changes at $relativeName.${file.ext}:\" + blockLineNum)\n        unmergedChanges += allLines.size - lines.size + 1\n        out.println(begLine)\n        diff.foreach(out.println)\n        out.println(hdo)\n      }\n      if hasBlankLines then resetCommands\n      rec(rest.tail)\n    case l :: ls =>\n      \n      val blockLineNum = allLines.size - lines.size + 1\n      \n      val block = (l :: ls.takeWhile(l => (l.nonEmpty || consumeEmptyLines.isSet) && !(\n        l.startsWith(output.outputMarker)\n        || l.startsWith(output.diffBegMarker)\n        // || l.startsWith(oldOutputMarker)\n      ))).toIndexedSeq\n      block.foreach(out.println)\n      val processedBlock = block\n      val processedBlockStr = processedBlock.mkString\n      val fph = new FastParseHelpers(block)\n      \n      val origin = Origin(file, blockLineNum + output.linesDelta, fph)\n      \n      try\n        \n        processBlock(origin)\n        \n      catch\n        case oh_noes: ThreadDeath => throw oh_noes\n        case err: Throwable =>\n          if !tolerateErrors then\n            failures += allLines.size - lines.size + 1\n            unhandled(blockLineNum, err)\n          // err.printStackTrace(out)\n          // println(err.getCause())\n          uncaught(err)\n      \n      if consumeEmptyLines.isSet then\n        output(output.blockSeparator)\n        consumeEmptyLines.unset\n      \n      rec(lines.drop(block.size))\n      \n    case Nil =>\n  \n  \n  \n  def run(): Unit =\n    val starttime = System.currentTimeMillis()\n    try rec(allLines) finally\n      val endtime = System.currentTimeMillis()\n      val duration = (endtime - starttime).toString\n      println(s\"${fansi.Color.Cyan.escape}Processed in ${Console.BOLD}${\n          \" \" * (5 - duration.length) + duration\n        } ms${Console.RESET}  ${\n          Console.YELLOW + relativeName + \".\" + file.ext + Console.RESET\n        }\")\n      out.close()\n    val result = strw.toString\n    if result =/= fileContents then\n      println(s\"Updating $file...\")\n      cctx.fs.write(file, result)\n  \n  // * Called after the very first command block\n  // * and every time a further command block with `:init` finishes\n  def init(): Unit =\n    ()\n  \n  \nend DiffMaker\n\n\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/DiffTestRunner.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\nimport org.scalatest.concurrent.{TimeLimitedTests, Signaler}\nimport os.up\n\nimport mlscript.utils._, shorthands._\nimport io.PlatformPath.given, io.FileSystem\n\n\n// * Note: we used to use:\n// *    class AllTests extends org.scalatest.Suites(\n// *      new CompileTestRunner(DiffTestRunner.State){},\n// *      new DiffTestRunner(DiffTestRunner.State){},\n// *    )\n// * but this (very surprisinbgly) disables parallel execution each individual suite.\n// * So now we just split tests into separate SBT projects.\n\n\nobject DiffTestRunner:\n  \n  class State:\n    \n    val cctx: CompilerCtx = CompilerCtx.fresh(io.FileSystem.default)\n    \n    val pwd = os.pwd\n    \n    // println(s\"INITIALIZING DiffTestRunner.State in ${pwd}\")\n    \n    val workingDir = if pwd.last == \"hkmc2DiffTests\"\n      then pwd/up // For some reason, when run from ~hkmc2JVM/Test/run in sbt, the pwd is \".../hkmc2/jvm\"\n      else pwd\n    // val dir = workingDir/\"hkmc2\"/\"shared\"/\"src\"/\"test\"/\"mlscript\"\n    \n    val dir = workingDir/\"hkmc2\"/\"shared\"/\"src\"/\"test\"\n    \n    // To be overridden in subproject-specific State classes\n    def testDir: os.Path = dir\n    \n    val validExt = Set(\"mls\")\n    \n    val allFiles = os.walk(testDir)\n      .filter(_.toIO.isFile)\n      .filter(_.ext in validExt)\n    \n    def filter(file: os.RelPath): Bool = true\n    \n    val TimeLimit =\n      if sys.env.get(\"CI\").isDefined then Span(60, Seconds)\n      else Span(30, Seconds)\n    \n  end State\n  \n  class StateWithGit extends State:\n    \n    println(s\"Running git in ${dir}...\")\n    \n    // * Aggregate unstaged modified files to only run the tests on them, if there are any\n    val modified: Set[os.RelPath] =\n      try os.proc(\"git\", \"status\", \"--porcelain\", dir).call().out.lines().iterator.flatMap { gitStr =>\n        println(\" [git] \" + gitStr)\n        val prefix = gitStr.take(2)\n        val filePath = os.RelPath(gitStr.drop(3))\n        if prefix =:= \"A \" || prefix =:= \"M \" || prefix =:= \"R \" || prefix =:= \"D \" then\n          N // * Disregard modified files that are staged\n        else if filePath.ext =/= \"mls\" then N\n        else S(filePath)\n      }.toSet catch\n        case err: Throwable =>\n          System.err.println(\"/!\\\\ git command failed with: \" + err)\n          Set.empty\n    \n    if modified.isEmpty then\n      println(\"No test file with unstaged changes detected; no test will run.\")\n    \n    override def filter(file: os.RelPath): Bool =\n      // println(s\"Filtering: $file ${modified(file)}\")\n      modified(file)\n    \n  end StateWithGit\n  \n  lazy val State = new State\n  \nend DiffTestRunner\n\n\nclass DiffTestRunner\n  extends DiffTestRunnerBase(DiffTestRunner.State)\n  with ParallelTestExecution:\n  \n  override protected def excludedDiffDirs: Ls[os.Path] =\n    TestFolders.mainExcludedDiffDirs(state.workingDir)\n\nclass DiffTestRunnerBase(val state: DiffTestRunner.State)\n  extends funsuite.AnyFunSuite\n  with TimeLimitedTests\n:\n  import state.*\n  \n  private val inParallel = isInstanceOf[ParallelTestExecution]\n  \n  val timeLimit = TimeLimit\n  \n  override val defaultTestSignaler: Signaler = new Signaler:\n    @annotation.nowarn(\"msg=method stop in class Thread is deprecated\") def apply(testThread: Thread): Unit =\n      println(s\"!! Test at $testThread has run out out time !! stopping...\" +\n        \"\\n\\tNote: you can increase this limit by changing DiffTests.TimeLimit\")\n      // * Thread.stop() is considered bad practice because normally it's better to implement proper logic\n      // * to terminate threads gracefully, avoiding leaving applications in a bad state.\n      // * But here we DGAF since all the test is doing is running a type checker and some Node REPL,\n      // * which would be a much bigger pain to make receptive to \"gentle\" interruption.\n      // * It would feel extremely wrong to intersperse the pure type checker algorithms\n      // * with ugly `Thread.isInterrupted` checks everywhere...\n      testThread.stop()\n  \n  protected def excludedDiffDirs: Ls[os.Path] =\n    TestFolders.alwaysExcludedDiffDirs(state.workingDir)\n  \n  protected lazy val diffTestFiles = allFiles.filter: file =>\n    (\n      !TestFolders.isExcluded(file, excludedDiffDirs)\n      && filter(file.relativeTo(state.workingDir))\n    )\n  \n  protected def createDiffMaker(\n    file: os.Path,\n    preludePath: os.Path,\n    predefPath: os.Path,\n    relativeName: String\n  ): DiffMaker =\n    new MainDiffMaker(workingDir.toString, file, preludePath, predefPath, relativeName):\n      def cctx = state.cctx\n  \n  diffTestFiles.foreach: file =>\n    \n    val basePath = file.segments.drop(dir.segmentCount).toList.init\n    val relativeName = basePath.map(_ + \"/\").mkString + file.baseName\n    \n    test(relativeName):\n      \n      val preludePath = dir/\"mlscript\"/\"decls\"/\"Prelude.mls\"\n      val predefPath = dir/\"mlscript-compile\"/\"Predef.mls\"\n      \n      val dm = createDiffMaker(file, preludePath, predefPath, relativeName)\n      \n      dm.run()\n      \n      if dm.failures.nonEmpty then\n        fail(s\"Unexpected test outcome(s) at: \" +\n          dm.failures.distinct.map(\"\\n\\t\"+relativeName+\".\"+file.ext+\":\"+_).mkString(\", \"))\n  \nend DiffTestRunnerBase\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/DocumentTests.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time.*\nimport org.scalatest.concurrent.{TimeLimitedTests, Signaler}\n\nimport mlscript.utils.*, shorthands.*\nimport document.*\nimport document.Document.*\nimport sourcecode.{Line, File}\n\n\nclass DocumentTests extends funsuite.AnyFunSuite:\n  \n  def runTest(nme: Str)(body: StringBuilder => Unit) =\n    test(nme):\n      val path = os.pwd/\"hkmc2DiffTests\"/\"src\"/\"test\"/\"out\"/(nme + \".out\")\n      \n      val contents = if os.exists(path)\n        then os.read(path)\n        else \"\"\n      \n      val strb = new StringBuilder\n      \n      body(strb)\n      \n      val res = strb.toString\n      if res =/= contents then\n        os.write.over(path, res)\n        println(s\"Updating $path\")\n      \n  \n  runTest(\"Basic Document Tests\"): strb =>\n    \n    strb ++= s\"// Generated from: ${os.Path(summon[File].value).relativeTo(os.pwd)}\\n\"\n    \n    def mk(d: Document, showRaw: Bool = false)(using Line) =\n      strb ++= \"\\n\"\n      strb ++= s\"// L.${summon[Line].value}:\\n\"\n      if showRaw then strb ++= s\"//\\t$d\\n\"\n      strb ++= d.mkString(20)\n      strb ++= \"\\n\"\n    \n    mk(doc\"hello\" :: \" \" :: doc\"world\", showRaw = true)\n    \n    mk(nest(doc\"hello\" :/: doc\"world\"), showRaw = true)\n    \n    mk(doc\"hello hello hello\" :: break :: doc\"world world world\")\n    \n    mk(doc\"hello\" :: forceBreak :: doc\"world\")\n    \n    mk(nest(doc\"hello\" :: forceBreak :: doc\"world\"))\n    \n    mk(nest(doc\"hello hello hello\" :: break :: doc\"world world world\"))\n    \n    mk(group(doc\"hello hello hello\" :: break :: doc\"world world world\"))\n    \n    mk(nest(group(doc\"hello hello hello\" :: break :: doc\"world world world\")))\n    \n    mk(doc\"\\{hi # hi\\} # \\{world # world\\}\")\n    \n    mk(doc\"\\{hi # hi\\}\\n\\{world # world\\}\")\n    \n    mk(doc\"\\{hi # hi\\} # \\{W # W\\} # \\{! # !\\}\")\n    \n    mk(doc\"\\{hi # hi\\}\\n\\{W # W\\} # \\{! # !\\}\")\n    \n    mk(doc\"\\{hi # hi\\} # \\{W # W\\}\\n\\{! # !\\}\")\n    \n    mk(doc\"\\{hi # hi\\} # \\{world\\nworld\\}\")\n    \n    mk(doc\"\\{hello # hello # hello\\} # \\{world # world # world\\}\")\n    \n    mk(doc\"\\{hello # hello # hello\\} # \\{universe # universe # universe\\}\")\n    \n    mk(doc\" #{ \\{hello # hello # hello\\}\\n\\{world # world # world\\} #} \")\n    \n    mk(doc\" #{ \\{hello # hello\\nhello\\}\\n\\{world # world # world\\} #} \")\n    \n    mk(doc\" #{ \\{hello # hello\\nhello\\}\\n\\{world # world\\nworld\\} #} \")\n    \n    \n  \nend DocumentTests\n\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/InvalmlDiffMaker.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\n\nimport hkmc2.semantics.*\nimport hkmc2.invalml.*\nimport utils.Scope\n\n\nabstract class InvalMLDiffMaker extends JSBackendDiffMaker:\n  \n  val invalPreludeFile = io.Path(rootPath) / \"hkmc2\" / \"shared\" / \"src\" / \"test\" / \"mlscript\" / \"invalml\" / \"InvalMLPrelude.mls\"\n  \n  val invalmlOpt = new NullaryCommand(\"invalml\"):\n    override def onSet(): Unit =\n      super.onSet()\n      noSanityCheck.isGlobal = true\n      noSanityCheck.set\n      if file =/= invalPreludeFile then\n        curCtx = Elaborator.State.init\n        given Config = mkConfig\n        importFile(invalPreludeFile, verbose = false)\n  \n  \n  override def init(): Unit =\n    super.init()\n\n  lazy val invalCtx =\n    given Elaborator.Ctx = curCtx\n    invalml.InvalCtx.init(_ => die)\n  \n  var invalmlTyper: Opt[InvalTyper] = None\n  \n  \n  override def processTerm(trm: semantics.Term.Blk, inImport: Bool)(using Config, Raise): Unit =\n    super.processTerm(trm, inImport)\n    if invalmlOpt.isSet then\n      given Scope = Scope.empty(Scope.Cfg.default)\n      if invalmlTyper.isEmpty then\n        given Elaborator.Ctx = curCtx\n        invalmlTyper = S(InvalTyper())\n      given hkmc2.invalml.InvalCtx = invalCtx.copy(raise = summon)\n      val typer = invalmlTyper.get\n      val ty = typer.typePurely(trm)\n      val printer = PrettyPrinter((msg: String) => output(msg))\n      if debug.isSet then printer.print(ty)\n      val simplif = TypeSimplifier(tl)\n      val sty = simplif(true, 0)(ty)\n      printer.print(sty)\n  \n\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/JSBackendDiffMaker.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport semantics.*\nimport codegen.*\nimport codegen.js.{JSBuilder, JSBuilderArgNumSanityChecks}\nimport document.*\nimport codegen.Block\nimport utils.Scope\nimport hkmc2.syntax.Tree.Ident\nimport hkmc2.codegen.Path\nimport hkmc2.Diagnostic.Source\nimport hkmc2.Message.MessageContext\n\nabstract class JSBackendDiffMaker extends MLsDiffMaker:\n  \n  val debugLowering = NullaryCommand(\"dl\")\n  val noCodeGen = NullaryCommand(\"noCodeGen\")\n  val js = NullaryCommand(\"js\")\n  val showSanitizedJS = NullaryCommand(\"ssjs\")\n  val showJS = NullaryCommand(\"sjs\")\n  val showRepl = NullaryCommand(\"showRepl\")\n  val traceJS = NullaryCommand(\"traceJS\")\n  val expect = Command(\"expect\"): ln =>\n    ln.trim\n  \n  private val baseScp: utils.Scope =\n    utils.Scope.empty(utils.Scope.Cfg.default)\n  private lazy val irPrintingScp: utils.Scope = // for IR printing only\n    Scope.empty(Scope.Cfg.default.copy(\n      escapeChars = false,\n      useSuperscripts = false,\n      includeZero = false,\n    ))\n  \n  val runtimeNme = baseScp.allocateName(Elaborator.State.runtimeSymbol)(using throw _)\n  val termNme = baseScp.allocateName(Elaborator.State.termSymbol)(using throw _)\n  val blockNme = baseScp.allocateName(Elaborator.State.blockSymbol)(using throw _)\n  val optionNme = baseScp.allocateName(Elaborator.State.optionSymbol)(using throw _)\n  val definitionMetadataNme = baseScp.allocateName(Elaborator.State.definitionMetadataSymbol)(using throw _)\n  val prettyPrintNme = baseScp.allocateName(Elaborator.State.prettyPrintSymbol)(using throw _)\n  \n  val ltl = new TraceLogger:\n    override def doTrace = debugLowering.isSet || scope.exists:\n      showUCS.get.getOrElse(Set.empty).contains\n    override def emitDbg(str: String): Unit = output(str)\n  \n  val replTL = new TraceLogger:\n    override def doTrace = showRepl.isSet\n    override def emitDbg(str: String): Unit = output(str)\n  \n  lazy val host =\n    hostCreated = true\n    given TL = replTL\n    val h = ReplHost(rootPath)\n    def importRuntimeModule(name: Str, file: io.Path) =\n      h.execute(s\"const $name = (await import(\\\"${file}\\\")).default;\") match\n      case ReplHost.Result(msg) =>\n        if msg.startsWith(\"Uncaught\") then output(s\"Failed to load $name: $msg\")\n      case r => output(s\"Failed to load $name: $r\")\n    importRuntimeModule(runtimeNme, runtimeFile)\n    h.execute(s\"const $definitionMetadataNme = Symbol.for(\\\"mlscript.definitionMetadata\\\");\")\n    h.execute(s\"const $prettyPrintNme = Symbol.for(\\\"mlscript.prettyPrint\\\");\")\n    if importQQ.isSet then importRuntimeModule(termNme, termFile)\n    if stageCode.isSet then\n      importRuntimeModule(blockNme, blockFile)\n      importRuntimeModule(optionNme, optionFile)\n    h\n  \n  private var hostCreated = false\n  override def run(): Unit =\n    try super.run() finally if hostCreated then host.terminate()\n  \n  override def processTerm(blk: semantics.Term.Blk, inImport: Bool)(using Config, Raise): Unit =\n    super.processTerm(blk, inImport)\n    \n    val outerRaise: Raise = summon\n    val reportedMessages = mutable.Set.empty[Str]\n    \n    def definedValues(includeNonTerms: Bool) =\n      import Elaborator.Ctx.*\n      curCtx.env.iterator.flatMap:\n        case (nme, e @ (_: RefElem | SelElem(base = RefElem(_: InnerSymbol)))) =>\n          e.symbol match\n          case S(ts: TermSymbol) if ts.k.isInstanceOf[syntax.ValLike] => S((nme, ts, N))\n          case S(ts: BlockMemberSymbol)\n            if includeNonTerms || ts.trmImplTree.exists(_.k.isInstanceOf[syntax.ValLike]) => S((nme, ts, N))\n          case S(vs: VarSymbol) => S((nme, vs, N))\n          case _ => N\n        case _ => N\n      .toList\n    \n    val symbolsToPreserve = definedValues(includeNonTerms = true).iterator.map(_._2).toSet\n    val effectiveConfig = Config.extractConfigFromStats(blk)\n\n    if showJS.isSet then\n      given Raise =\n        case d @ ErrorReport(source = Source.Compilation) =>\n          reportedMessages += d.mainMsg\n          outerRaise(d)\n        case d => outerRaise(d)\n      given Elaborator.Ctx = curCtx\n      val low = ltl.givenIn:\n        codegen.Lowering()(using effectiveConfig)\n      val jsb = ltl.givenIn:\n        JSBuilder(using effectiveConfig)\n      val le_0 = low.program(blk)\n      val le_1 = ltl.givenIn:\n        BlockSimplifier(symbolsToPreserve)(le_0)\n      val le_2 = ltl.givenIn:\n        DeadParamElim(le_1)\n      val nestedScp = baseScp.nest\n      val je = nestedScp.givenIn:\n        jsb.programBody(le_2, N, wd)\n      val jsStr = je.stripBreaks.mkString(output.ColWidth)\n      outputSeparator(\"JS (unsanitized)\")\n      output(jsStr)\n    \n    if noCodeGen.isUnset then\n      given Elaborator.Ctx = curCtx\n      given Raise =\n        case e: ErrorReport if reportedMessages.contains(e.mainMsg) =>\n          if verbose.isSet then\n            output(s\"Skipping already reported diagnostic: ${e.mainMsg}\")\n        case d => outerRaise(d)\n      val low = ltl.givenIn:\n        new codegen.Lowering()(using effectiveConfig)\n          with codegen.LoweringSelSanityChecks\n          with codegen.LoweringTraceLog(traceJS.isSet)\n      \n      val lowered_0 = low.program(blk)\n      \n      if showLoweredTree.isSet then\n        outputSeparator(\"Lowered IR Tree\")\n        output(lowered_0.showAsTree)\n      \n      if showIR.isSet then\n        outputSeparator(\"Lowered IR\")\n        given ShowCfg = ShowCfg(\n          showExpansionMappings = false,\n          showFlowSymbols = true,\n          debug = debug.isSet,\n        )\n        output(Printer().worksheet(lowered_0)(using irPrintingScp).mkString(output.ColWidth))\n      \n      val lowered_1 = ltl.givenIn:\n        BlockSimplifier(symbolsToPreserve)(lowered_0)\n      \n      val lowered_2 = ltl.givenIn:\n        DeadParamElim(lowered_1)\n      \n      // TODO: Test that transformers retain object identity when there are no changes\n      if (lowered_2 isnt lowered_0) && (lowered_2 === lowered_0) then\n        output(\"/!\\\\ Warning: object identity between equal objects was not preserved by BlockSimplifier or DeadParamElim\")\n        def rec(lhs: Block, rhs: Block): Bool =\n          (lhs is rhs) || {\n            if\n              lhs.subBlocks.iterator.zip(rhs.subBlocks.iterator).forall:\n                case (s1: Block, s2: Block) => rec(s1, s2)\n            then\n              output(s\"/!\\\\ Offending subblock: ${lhs.showAsTree}\") \n              false\n            else false\n          }\n        rec(lowered_0.main, lowered_2.main)\n      \n      if checkIR.isSet then\n        BlockChecker().applyProgram(lowered_2)\n      \n      if showOptimizedIR.isSet then\n        outputSeparator(\"Optimized IR\")\n        given ShowCfg = ShowCfg(\n          showExpansionMappings = false,\n          showFlowSymbols = true,\n          debug = debug.isSet,\n        )\n        output(Printer().worksheet(lowered_2)(using irPrintingScp).mkString(output.ColWidth))\n      if showOptimizedTree.isSet then\n        outputSeparator(\"Optimized IR Tree\")\n        output(lowered_2.showAsTree)\n      \n      processIRBlock(lowered_2, definedValues)\n      \n  end processTerm\n  \n  type ComputeDefinedValues = (includeNonTerms: Bool) => Ls[(Str, Symbol, Opt[Str])]\n  \n  def processIRBlock(pgrm: Program, definedValues: ComputeDefinedValues)(using Config, Raise, Elaborator.Ctx): Unit =\n    \n    if js.isSet then\n      \n      // * We used to do this to avoid needlessly generating new variable names in separate blocks:\n      // val nestedScp = baseScp.nest\n      val nestedScp = baseScp\n      // val nestedScp = codegen.js.Scope(S(baseScp), curCtx.outer, collection.mutable.Map.empty) // * not needed\n      \n      val resSym = new TempSymbol(N, \"block$res\")\n      \n      val resNme = nestedScp.allocateName(resSym)\n      \n      val loweredMapped = pgrm.copy(main = pgrm.main.mapReturn:\n        case Return(res, implct) =>\n          assert(implct)\n          Assign(resSym, res, Return(Value.Lit(syntax.Tree.UnitLit(false)), true))\n      )\n      val jsb = ltl.givenIn:\n        new JSBuilder\n          with JSBuilderArgNumSanityChecks\n      val (pre, js) = nestedScp.givenIn:\n        jsb.worksheet(loweredMapped)\n      val preStr = pre.stripBreaks.mkString(output.ColWidth)\n      val jsStr = js.stripBreaks.mkString(output.ColWidth)\n      if showSanitizedJS.isSet then\n        outputSeparator(\"JS (sanitized)\")\n        if preStr.nonEmpty then output(preStr)\n        output(jsStr)\n      \n      if printedSeparatedSection then outputSeparator(\"Output\")\n      \n      def mkQuery(preStr: Str, jsStr: Str)(k: Str => Unit) =\n        val queryStr = jsStr.replaceAll(\"\\n\", \" \")\n        val (reply, stderr) =\n          host.query(preStr, queryStr, !expectRuntimeOrCodeGenErrors && !tolerateErrors)\n        reply match\n          case ReplHost.Result(content) => k(content)\n          case ReplHost.Empty =>\n          case ReplHost.Unexecuted(message) => ???\n          case ReplHost.Error(isSyntaxError, message, otherOutputs) =>\n            if otherOutputs.nonEmpty then\n              otherOutputs.splitSane('\\n').foreach: line =>\n                output(s\"> ${line}\")\n            if (isSyntaxError) then\n              // If there is a syntax error in the generated code,\n              // it should be a code generation error.\n              raise(ErrorReport(msg\"[Uncaught SyntaxError] ${message}\" -> N :: Nil,\n                source = Diagnostic.Source.Compilation))\n            else\n              // Otherwise, it is considered a simple runtime error.\n              raise(ErrorReport(msg\"${message}\" -> N :: Nil,\n                source = Diagnostic.Source.Runtime))\n        if stderr.nonEmpty then output(s\"// Standard Error:\\n${stderr}\")\n      \n      if traceJS.isSet then\n        host.execute(\n          s\"$runtimeNme.TraceLogger.enabled = true; \" +\n          s\"$runtimeNme.TraceLogger.resetIndent(0)\")\n      \n      // * Sometimes the JS block won't execute due to a syntax or runtime error so we always set this first\n      host.execute(s\"$resNme = undefined\")\n      \n      mkQuery(preStr, jsStr): stdout =>\n        stdout.splitSane('\\n').init // should always ends with \"undefined\" (TODO: check)\n          .foreach: line =>\n            output(s\"> ${line}\")\n      if traceJS.isSet then\n        host.execute(s\"$runtimeNme.TraceLogger.enabled = false\")\n      \n      if silent.isUnset then\n        val valuesToPrint = (\"\", resSym, expect.get) +: definedValues(includeNonTerms = false).toSeq.sortBy(_._1)\n        valuesToPrint.foreach: (nme, sym, expect) =>\n          val le =\n            import codegen.*\n            Return(\n              Call(\n                Value.Ref(Elaborator.State.runtimeSymbol).selSN(\"printRaw\"),\n                (Arg(N, Value.Ref(sym, N)) :: Nil) ne_:: Nil)(true, false, false),\n            implct = true)\n          val je = nestedScp.givenIn:\n            jsb.block(le, endSemi = false)\n          val jsStr = je.stripBreaks.mkString(output.ColWidth)\n          mkQuery(\"\", jsStr): out =>\n            // Omit the last line which is always \"undefined\" or the unit.\n            val result = out.lastIndexOf('\\n') match\n              case n if n >= 0 => out.substring(0, n)\n              case _ => \"\"\n            expect match\n            case S(expected) if result =/= expected => raise:\n              ErrorReport(msg\"Expected: '${expected}', got: '${result}'\" -> N :: Nil,\n                source = Diagnostic.Source.Runtime)\n            case _ => ()\n            val anon = nme.isEmpty\n            result match\n            case \"undefined\" if anon =>\n            case \"()\" if anon =>\n            case _ => output(s\"${if anon then \"\" else s\"$nme \"}= $result\")\n      \n\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/LlirDiffMaker.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport document.*\nimport codegen.Block\nimport codegen.llir.*\nimport codegen.cpp.*\nimport hkmc2.syntax.Tree.Ident\nimport hkmc2.codegen.Path\nimport hkmc2.semantics.Term.Blk\nimport hkmc2.utils.Scope\nimport hkmc2.codegen.llir._\nimport hkmc2.codegen.cpp._\nimport hkmc2.semantics.Elaborator\nimport scala.collection.mutable.ListBuffer\n\nabstract class LlirDiffMaker extends InvalMLDiffMaker:\n  val llir = NullaryCommand(\"llir\")\n  val sllir = NullaryCommand(\"sllir\")\n  val intl = NullaryCommand(\"intl\")\n  val lprelude = NullaryCommand(\"lpre\")\n\n  // C++ codegen generation commands for individual blocks\n  val cpp = NullaryCommand(\"cpp\")\n  val scpp = NullaryCommand(\"scpp\")\n  val rcpp = NullaryCommand(\"rcpp\")\n  val wcpp = Command[Str](\"wcpp\", false)(x => x.stripLeading())\n\n  // C++ codegen generation commands for the whole program\n  val wholeCpp = NullaryCommand(\"wholeCpp\")\n  val sWholeCpp = NullaryCommand(\"showWholeCpp\")\n  val rWholeCpp = NullaryCommand(\"runWholeCpp\")\n  val wWholeCpp = Command[Str](\"writeWholeCpp\", false)(x => x.stripLeading())\n\n  def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) =\n    val p = new java.io.PrintWriter(f)\n    try { op(p) } finally { p.close() }\n\n  given Elaborator.Ctx = curCtx\n  \n  object Llir: // Avoid polluting the namespace\n    val freshId = FreshInt()\n    var ctx = codegen.llir.Ctx.empty\n    val scope = Scope.empty(Scope.Cfg.default)\n    val wholeProg = ListBuffer.empty[Program]\n  import Llir.*\n  \n  def mkWholeProgram: Program =\n    if wholeProg.length == 0 then\n      throw new Exception(\"No program to make\")\n    else\n      Program(\n        classes = wholeProg.iterator.flatMap(_.classes).toSet,\n        defs = wholeProg.iterator.flatMap(_.defs).toSet,\n        entry = wholeProg.last.entry\n      )\n\n  override def processTerm(trm: Blk, inImport: Bool)(using Config, Raise): Unit = \n    super.processTerm(trm, inImport)\n    if llir.isSet then\n      val low = ltl.givenIn:\n        codegen.Lowering()\n      // TODO: There should be a third compilation target of CPP?\n      var le = low.program(trm)\n      given Scope = scope\n      given Ctx = ctx\n      val llb = LlirBuilder(tl, freshId)\n      try\n        val (llirProg, ctx2) = llb.bProg(le)\n        ctx = ctx2\n        wholeProg += llirProg\n        if sllir.isSet && !silent.isSet then\n          output(\"LLIR:\")\n          if debug.isSet then\n            output(LlirDebugPrinter.mkDocument(llirProg).toString)\n          else\n            output(LlirPrinter(using summon[Raise], Scope.empty(Scope.Cfg.default))\n              .mkDocument(llirProg).mkString(output.ColWidth))\n        def cppGen(name: String, prog: Program, gen: Bool, show: Bool, run: Bool, write: Opt[Str]): Unit =\n          tl.log(s\"Generating $name\")\n          if gen || show || run || write.isDefined then\n            val cpp = CppCodeGen(ctx.builtinSym.hiddenClasses, tl).codegen(prog)\n            if show then\n              output(s\"\\n$name:\")\n              output(cpp.toDocument.mkString(output.ColWidth))\n            val rPath = os.Path(rootPath)\n            val auxPath = rPath/\"hkmc2\"/\"shared\"/\"src\"/\"test\"/\"mlscript-compile\"/\"cpp\"\n            if write.isDefined then\n              printToFile(java.io.File((auxPath / s\"${write.get}\").toString)):\n                p => p.println(cpp.toDocument.mkString(output.ColWidth))\n            if run then \n              val cppHost = CppCompilerHost(auxPath.toString, output.apply)\n              if !cppHost.ready then\n                output(\"\\nCpp Compilation Failed: Cpp compiler or GNU Make not found\")\n              else if !silent.isSet then\n                output(\"\\n\")\n                cppHost.compileAndRun(cpp.toDocument.mkString(output.ColWidth))\n        cppGen(\"Cpp\", llirProg, \n          cpp.isSet, scpp.isSet, rcpp.isSet, wcpp.get)\n        cppGen(\"WholeProgramCpp\", mkWholeProgram,\n          wholeCpp.isSet, sWholeCpp.isSet, rWholeCpp.isSet, wWholeCpp.get)\n        if intl.isSet then\n          val intr = codegen.llir.Interpreter(tl)\n          output(\"\\nInterpreted:\")\n          output(intr.interpret(llirProg))\n      catch\n        case e: LowLevelIRError =>\n          output(\"Stopped due to an error during the Llir generation\")\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/MLsDiffMaker.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\n\nimport mlscript.utils.*, shorthands.*\nimport utils.*\n\nimport hkmc2.semantics.{Elaborator, Resolver, Resolvable, Symbol, SymbolPrinter}\n\nimport semantics.Elaborator.{Ctx, State}\n\nabstract class MLsDiffMaker extends DiffMaker:\n  \n  val invalmlOpt: Command[?]\n  \n  val rootPath: Str // * Absolute path to the root of the project\n  val preludeFile: io.Path // * Contains declarations of JS builtins\n  val predefFile: io.Path // * Contains MLscript standard library definitions\n  val runtimeFile: io.Path = predefFile.up / \"Runtime.mjs\" // * Contains MLscript runtime definitions\n  val termFile: io.Path = predefFile.up / \"Term.mjs\" // * Contains MLscript runtime term definitions\n  val blockFile: io.Path = predefFile.up / \"Block.mjs\" // * Contains MLscript runtime block definitions\n  val optionFile: io.Path = predefFile.up / \"Option.mjs\" // * Contains MLscipt runtime option definition\n  \n  val wd = file.up\n  \n  val silent = NullaryCommand(\"silent\")\n  val dbgElab = NullaryCommand(\"de\")\n  val dbgParsing = NullaryCommand(\"dp\")\n  val dbgResolving = NullaryCommand(\"dr\")\n  val dbgFlow = NullaryCommand(\"df\")\n  \n  val showLocations = NullaryCommand(\"loc\")\n  val showParse = NullaryCommand(\"p\")\n  val showParsedTree = NullaryCommand(\"pt\")\n  val showElab = NullaryCommand(\"el\")\n  val showElaboratedTree = NullaryCommand(\"elt\")\n  val showResolve = NullaryCommand(\"r\")\n  val showResolvedTree = NullaryCommand(\"rt\")\n  val showFlows = FlagCommand(false, \"sf\")\n  val showLoweredTree = NullaryCommand(\"lot\")\n  val ppLoweredTreeOld = NullaryCommand(\"slot\", () => output(\"Option ':slot' is deprecated, use ':sir' instead.\"))\n  val showIR = NullaryCommand(\"sir\")\n  val checkIR = NullaryCommand(\"checkIR\")\n  val showOptimizedIR = NullaryCommand(\"soir\")\n  val showOptimizedTree = NullaryCommand(\"olot\")\n  val showContext = NullaryCommand(\"ctx\")\n  val parseOnly = NullaryCommand(\"parseOnly\")\n  val funcToCls = NullaryCommand(\"ftc\")\n  \n  val flow = FlagCommand(false, \"flow\")\n  private val flowScp: utils.Scope =\n    utils.Scope.empty(utils.Scope.Cfg.default.copy(\n      escapeChars = false,\n      useSuperscripts = true,\n      includeZero = true,\n    ))\n  \n  /**\n   * Enables Wasm support. All options in [[WasmDiffMaker]] are no-op if this option is not set.\n   */\n  val wasm = NullaryCommand(\"wasm\")\n  \n  \n  // * Compiler configuration\n  \n  val noSanityCheck = NullaryCommand(\"noSanityCheck\")\n  val noFreeze = NullaryCommand(\"noFreeze\")\n  val noModuleCheck = NullaryCommand(\"noModuleCheck\")\n  val effectHandlers = Command(\"effectHandlers\")(_.trim)\n  val effectHandlersOptions = Set(\"debug\", \"\")\n  val stackSafe = Command(\"stackSafe\")(_.trim)\n  val liftDefns = NullaryCommand(\"lift\")\n  val importQQ = NullaryCommand(\"qq\")\n  val stageCode = NullaryCommand(\"staging\")\n  val rewriteWhile = NullaryCommand(\"rewriteWhile\")\n  val noInlineOpt = NullaryCommand(\"noInline\")\n  val inlineThreshold = Command(\"inlineThreshold\")(_.trim.toInt)\n  val noTailRecOpt = NullaryCommand(\"noTailRec\")\n  val deforest = Command(\"deforest\")(_.trim)\n  val patMatConsequentSharingThreshold = Command(\"patMatConsequentSharingThreshold\")(_.trim.toInt)\n  val deadParamElim = Command(\"deadParamElim\")(_.trim)\n\n  def mkConfig: Config =\n    import Config.*\n    if stackSafe.isSet && effectHandlers.isUnset then\n      output(s\"$errMarker Option ':stackSafe' requires ':effectHandlers' to be set\")\n    if !effectHandlers.get.forall(effectHandlersOptions.contains(_)) then\n      output(s\"$errMarker Option ':effectHandlers' only supports 'debug' as option\")\n    if effectHandlers.isSet then\n      if liftDefns.isUnset then\n        output(s\"$errMarker Option ':effectHandlers' requires ':lift'\")\n    if inlineThreshold.isSet && noInlineOpt.isSet then\n      output(s\"$errMarker Option ':noInline' conflicts with option ':inlineThreshold'\")\n    Config(\n      baseDir = wd,\n      sanityChecks = Opt.when(noSanityCheck.isUnset)(SanityChecks(light = true)),\n      effectHandlers = Opt.when(effectHandlers.isSet)(EffectHandlers(\n        debug = effectHandlers.get.contains(\"debug\"),\n        stackSafety = stackSafe.get.flatMap:\n          case \"off\" => N\n          case value => value.toIntOption match\n            case N => S(StackSafety.default)\n            case S(value) =>\n              if value < 0 then\n                failures += 1\n                output(\"/!\\\\ Stack limit must be positive, but the stack limit here is set to \" + value)\n                S(StackSafety.default)\n              // Minimum: 1 for initial depth, 3 for resuming in the trampoline, 1 for function entry.\n              // The limit needs to be strictly greater than 1 + 3 + 1 = 5.\n              else if value < 6 then\n                failures += 1\n                output(\"/!\\\\ Stack limit is too low, the minimum supported is 6.\")\n                S(StackSafety.default)\n              else\n                S(StackSafety(stackLimit = value))\n        ,\n      )),\n      liftDefns = Opt.when(liftDefns.isSet)(LiftDefns()),\n      patMatConsequentSharingThreshold = patMatConsequentSharingThreshold.get\n        .orElse(Config.default.patMatConsequentSharingThreshold),\n      stageCode = stageCode.isSet,\n      target = if wasm.isSet then CompilationTarget.Wasm else CompilationTarget.JS,\n      rewriteWhileLoops = rewriteWhile.isSet,\n      tailRecOpt = !noTailRecOpt.isSet,\n      deforest = Opt.when(deforest.isSet):\n        Deforest(\n          debug = true,\n          mono = deforest.get.exists(_.contains(\"mono\"))),\n      inlining = Opt.when(!noInlineOpt.isSet)(Config.Inliner(inlineThreshold.get.getOrElse(1))),\n      qqEnabled = importQQ.isSet,\n      funcToCls = funcToCls.isSet,\n      commentGeneratedCode = debug.isSet,\n      noFreeze = noFreeze.isSet,\n      noModuleCheck = noModuleCheck.isSet,\n      deadParamElim =\n        if deadParamElim.isUnset then S(DeadParamElim.default)\n        else\n          val value = deadParamElim.get.getOrElse(\"\")\n          val flags = value.split(\"\\\\s+\").filter(_.nonEmpty).toSet\n          val unknownFlags = flags -- Set(\"debug\", \"mono\", \"poly\", \"off\")\n          if unknownFlags.nonEmpty then\n            output(s\"$errMarker Unknown ':deadParamElim' flags: ${unknownFlags.toList.sorted.mkString(\", \")}\")\n          if flags.contains(\"mono\") && flags.contains(\"poly\") then\n            output(s\"$errMarker ':deadParamElim' flags 'mono' and 'poly' conflict\")\n          if flags.contains(\"off\") && (flags & Set(\"debug\", \"mono\", \"poly\")).nonEmpty then\n            output(s\"$errMarker ':deadParamElim off' conflicts with other flags\")\n          if flags.contains(\"off\") then N\n          else S(DeadParamElim(\n            debug = flags.contains(\"debug\"),\n            mono = !flags.contains(\"poly\")\n          )),\n    )\n  \n  \n  val importCmd = Command(\"import\"): ln =>\n    given Config = mkConfig\n    importFile(file.up / io.RelPath(ln.trim), verbose = silent.isUnset)\n  \n  // eg: `:ucs desugared normalized lowered`\n  val showUCS = Command(\"ucs\"): ln =>\n    ln.split(\" \").iterator.map(x => \"ucs:\" + x.trim).toSet\n  \n  \n  given Elaborator.State = new Elaborator.State:\n    override def dbg: Bool =\n      dbgParsing.isSet\n      || dbgElab.isSet\n      || dbgResolving.isSet\n      || debug.isSet\n  \n  \n  protected lazy val dbgScp: utils.Scope = // for unique symbol debug-printing only\n    Scope.empty(Scope.Cfg.default.copy(\n      escapeChars = false,\n      useSuperscripts = true,\n      includeZero = true,\n    ))\n  \n  \n  val dbgPrinter: SymbolPrinter = new SymbolPrinter(dbgScp):\n    override def preProcess(t: Product): Product = super.preProcess:\n      case class Unexpanded(origin: Resolvable)\n      t match\n      case t: Resolvable if t.hasExpansion => t.expanded\n      case t: Resolvable if dbgResolving.isSet => Unexpanded(t.duplicate.resolve)\n      case t => t\n    override def postProcess(t: Product): Str =\n      super.postProcess(t) + (\n        if showLocations.isSet then\n          t match\n          case t: Located => t.toLoc.fold(\" loc[none]\"): loc =>\n            val (sl, _, sc) = loc.origin.fph.getLineColAt(loc.spanStart)\n            val (el, _, ec) = loc.origin.fph.getLineColAt(loc.spanEnd)\n            s\" loc[$sl:$sc-$el:$ec]\"\n        else \"\"\n      )\n  \n  \n  val etl = new TraceLogger:\n    override def doTrace = dbgElab.isSet || scope.exists:\n      showUCS.get.getOrElse(Set.empty).contains\n    override def emitDbg(str: String): Unit = output(str)\n    override def trace[T](pre: => Str, post: T => Str = noPostTrace)(thunk: => T): T =\n      // * This override is for avoiding to increase the indentation when tracing if doTrace is false,\n      // * so that selectively-enabled tracing doesn't get strange indentation.\n      // * Perhaps this should be the default behavior of TraceLogger.\n      if doTrace then super.trace(pre, post)(thunk)\n      else thunk\n  \n  val rtl = new TraceLogger:\n    override def doTrace = dbgResolving.isSet\n    override def emitDbg(str: String): Unit = output(str)\n  \n  val ftl = new TraceLogger:\n    override def doTrace = dbgFlow.isSet\n    override def emitDbg(str: String): Unit = output(str)\n  \n  var curCtx = Elaborator.State.init\n  var curICtx = Resolver.ICtx.empty\n  \n  /** Persistent config modification from `#config(...)` directives. */\n  var configModify: Config => Config = identity\n  \n  var prelude = Elaborator.Ctx.empty\n  \n  override def run(): Unit =\n    if file =/= preludeFile then \n      given Config = mkConfig\n      importFile(preludeFile, verbose = false)\n      prelude = curCtx\n    super.run()\n  \n  \n  override def init(): Unit =\n    import syntax.*\n    import Tree.*\n    import Keyword.*\n    given raise: Raise = d =>\n      output(s\"Error: $d\")\n      ()\n    if file != preludeFile then\n      val cfg = mkConfig\n      given Config = cfg.copy(\n        deforest = cfg.deforest.map(_.copy(debug = false)),\n        deadParamElim = cfg.deadParamElim.map(_.copy(debug = false))\n      )\n      processTrees(\n        PrefixApp(Keywrd(`import`), StrLit(predefFile.toString))\n        :: Open(Ident(\"Predef\"))\n        :: Nil)\n    super.init()\n  \n  \n  def importFile(file: io.Path, verbose: Bool)(using Config): Unit =\n    \n    // val raise: Raise = throw _\n    given raise: Raise = d =>\n      output(s\"Error: $d\")\n      ()\n    \n    val block = cctx.fs.read(file)\n    val fph = new FastParseHelpers(block)\n    val origin = Origin(file, 0, fph)\n    \n    val lexer = new syntax.Lexer(origin, dbg = dbgParsing.isSet)\n    \n    // Stupid hack to ignore diff-test directives like `:ignore`\n    def dropCrap(ts: Ls[syntax.Stroken -> Loc]): Ls[syntax.Stroken -> Loc] = ts match\n      case (syntax.IDENT(\":\", true), _) :: (syntax.IDENT(nme, false), _) :: rest =>\n        dropCrap(rest.dropWhile(_._1 isnt syntax.NEWLINE).drop(1))\n      case _ => ts\n    \n    val tokens = dropCrap(lexer.bracketedTokens)\n    \n    if showParse.isSet || dbgParsing.isSet then\n      output(syntax.Lexer.printTokens(tokens))\n    \n    val rules = syntax.ParseRules()\n    val p = new syntax.Parser(origin, tokens, rules, raise, dbg = dbgParsing.isSet):\n      def doPrintDbg(msg: => Str): Unit = if dbg then output(msg)\n    val res = p.parseAll(p.block(allowNewlines = true))\n    val imprtSymbol =\n      semantics.TopLevelSymbol(\"import#\"+file.baseName)\n    given Elaborator.Ctx = curCtx.nestLocal(\"import:\"+file.baseName)\n    val elab = Elaborator(etl, wd, Ctx.empty)\n    try\n      val resBlk = new syntax.Tree.Block(res)\n      val (e, newCtx) = elab.importFrom(resBlk)\n      val ctxWithImports = newCtx.withMembers(resBlk.definedSymbols)\n      if verbose then\n        output(s\"Imported ${resBlk.definedSymbols.size} member(s)\")\n      curCtx = ctxWithImports\n      processTerm(e, inImport = true)\n    catch\n      case err: Throwable =>\n        uncaught(err)\n  \n  given tl: TraceLogger with\n    override def doTrace = debug.isSet\n    override def emitDbg(str: String): Unit = output(str)\n  \n  \n  def processOrigin(origin: Origin)(using Raise): Unit =\n    val oldCtx = curCtx\n    \n    given Config = configModify(mkConfig)\n    \n    val lexer = new syntax.Lexer(origin, dbg = dbgParsing.isSet)\n    val tokens = lexer.bracketedTokens\n    \n    if showParse.isSet || dbgParsing.isSet then\n      output(syntax.Lexer.printTokens(tokens))\n    \n    val rules = syntax.ParseRules()\n    val p = new syntax.Parser(origin, tokens, rules, raise, dbg = dbgParsing.isSet):\n      def doPrintDbg(msg: => Str): Unit = if dbg then output(msg)\n    val res = p.parseAll(p.block(allowNewlines = true))\n    \n    // If parsed tree is displayed, don't show the string serialization.\n    if (parseOnly.isSet || showParse.isSet) && !showParsedTree.isSet then\n      output(s\"Parsed:${res.map(\"\\n\\t\"+_.showDbg).mkString}\")\n    \n    if showParsedTree.isSet then\n      outputSeparator(s\"Parsed tree\")\n      res.foreach(t => output(t.showAsTree))\n    \n    // if showParse.isSet then\n    //   output(s\"AST: $res\")\n    \n    if parseOnly.isUnset then\n      processTrees(res)(using summon, raise)\n    \n    if showContext.isSet then\n      output(\"Env:\")\n      curCtx.env.foreach: (k, v) =>\n        if !(oldCtx.env contains k) then\n          output(s\"  $k -> $v\")\n  \n  \n  private var blockNum = 0\n  \n  def processTrees(trees: Ls[syntax.Tree])(using Config, Raise): Unit =\n    val elab = Elaborator(etl, file.up, prelude)\n    // val blockSymbol =\n    //   semantics.TopLevelSymbol(\"block#\"+blockNum)\n    blockNum += 1\n    // given Elaborator.Ctx = curCtx.nest(S(blockSymbol))\n    given Elaborator.Ctx = curCtx.nestLocal(s\"block:${blockNum}\")\n    val blk = new syntax.Tree.Block(trees)\n    val (e, newCtx) = elab.topLevel(blk)\n    curCtx = newCtx\n    \n    // Extract SetConfig statements and update persistent config\n    e.stats.foreach:\n      case sc: semantics.SetConfig =>\n        val prev = configModify\n        configModify = cfg => sc.modify(prev(cfg))\n      case _ => ()\n    \n    // If elaborated tree is displayed, don't show the string serialization.\n    if (showElab.isSet || debug.isSet) && !showElaboratedTree.isSet then\n      output(s\"Elab: ${e.showDbg}\")\n    showElaboratedTree.get.foreach: post =>\n      outputSeparator(s\"Elaborated tree\")\n      output(e.showAsTree)\n    \n    processTerm(e, inImport = false)\n      \n  \n  \n  def processTerm(trm: semantics.Term.Blk, inImport: Bool)(using Config, Raise): Unit =\n    given Ctx = curCtx\n    given Config = Config.extractConfigFromStats(trm)\n    val resolver = Resolver(rtl)\n    curICtx = resolver.traverseBlock(trm)(using curICtx)\n    \n    if showResolve.isSet then\n      output(s\"Resolved: ${trm.showDbg}\")\n    showResolvedTree.get.foreach: post =>\n      outputSeparator(s\"Resolved tree\")\n      output(trm.showAsTree)\n    \n    if flow.isSet then\n      val floan = semantics.flow.FlowAnalysis(using ftl)\n      val flo = floan.typeProd(trm)\n      floan.solveConstraints()\n      floan.expandTerms()\n      if showFlows.isSet then\n        import semantics.ShowCfg\n        given ShowCfg = ShowCfg(\n          showExpansionMappings = true,\n          showFlowSymbols = true,\n          debug = debug.isSet,\n        )\n        outputSeparator(s\"Flowed\")\n        output:\n          import document.*\n          doc\" #{ ${trm.showTopLevel(using flowScp)} #} \\nwhere #{ ${floan.showFlows(using flowScp)} #} \".mkString()\n    \n  \n\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/MainDiffMaker.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\nimport org.scalatest.concurrent.{TimeLimitedTests, Signaler}\n\nimport mlscript.utils._, shorthands._\n\n\nabstract class MainDiffMaker\n    (val rootPath: Str, val file: io.Path, val preludeFile: io.Path, val predefFile: io.Path, val relativeName: Str)\n  extends WasmDiffMaker:\n    \n    // println(s\"Running diff test for $relativeName\") // * useful to debug nonterminating tests\n    \nend MainDiffMaker\n\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/WasmDiffMaker.scala",
    "content": "package hkmc2\n\nimport mlscript.utils.*, shorthands.*\n\nimport codegen.*\nimport codegen.js.JSBuilder\nimport codegen.Local\nimport codegen.wasm.*\nimport document.*\nimport semantics.*\nimport semantics.Elaborator\nimport semantics.Term.Blk\nimport text.{SessionBinding, CompiledWasmModule, WatBuilder}\nimport Diagnostic.Source\nimport Message.MessageContext\n\nimport scala.collection.mutable\n\nabstract class WasmDiffMaker extends LlirDiffMaker:\n\n  /** Outputs the compiled module as [[WasmGenerator]] implementation-defined text.\n    */\n  val wat = NullaryCommand(\"wat\")\n\n  /** Outputs the compiled module as stack-based text. */\n  val swat = NullaryCommand(\"swat\")\n\n  /** Outputs the compiled module as folded text (i.e. S-expression). */\n  val fwat = NullaryCommand(\"fwat\")\n\n  private val baseScp: utils.Scope =\n    utils.Scope.empty(utils.Scope.Cfg.default)\n  private val wasmReplImportsNme = s\"${wasmSuppNme}ReplImports\"\n  private val wasmReplImportsRef = s\"globalThis.$wasmReplImportsNme\"\n  private val sessionImportsBySymbol = mutable.Map.empty[Local, mutable.LinkedHashMap[Str, SessionBinding]]\n  private var wasmSessionInitialized = false\n  private var wasmSessionMemPages = 0\n\n  final lazy val wasmSuppFile: io.Path = predefFile.up / \"wasm\" / \"Wasm.mjs\"\n  final lazy val wasmSuppNme = baseScp.allocateName(Elaborator.State.wasmSymbol)(using throw _)\n  final lazy val loadWasm: Unit =\n    host.execute(\n      s\"const $wasmSuppNme = (await import(\\\"${wasmSuppFile}\\\")).default;\",\n    ) match\n      case ReplHost.Result(msg) =>\n        if msg.startsWith(ReplHost.uncaughtErrorHead) then\n          output(s\"Failed to load wasm support library: $msg\")\n      case r => output(s\"Failed to load wasm support library: $r\")\n    ()\n\n  /** Prettifies a JSON-stringified Binaryen-formatted Wat. */\n  lazy val prettifyBinaryenWat = (content: Str) =>\n    content.substring(2, content.length() - 2).replace(\"\\\\\\\\n\", \"\\n\").replace(\"\\\\\\\\\\\"\", \"\\\"\")\n\n  override def processIRBlock(\n      pgrm: Program,\n      definedValues: ComputeDefinedValues,\n  )(using Config, Raise, Elaborator.Ctx): Unit =\n\n    super.processIRBlock(pgrm, definedValues)\n\n    val outerRaise: Raise = summon\n    def computeDefinedValues(includeNonTerms: Bool) =\n      import Elaborator.Ctx.*\n      curCtx.env.iterator.flatMap:\n        case (nme, e @ (_: RefElem | SelElem(base = RefElem(_: InnerSymbol)))) =>\n          e.symbol match\n            case S(ts: TermSymbol) if ts.k.isInstanceOf[syntax.ValLike] => S((nme, ts, N))\n            case S(ts: BlockMemberSymbol)\n                if includeNonTerms || ts.trmImplTree.exists(_.k.isInstanceOf[syntax.ValLike]) => S((nme, ts, N))\n            case S(vs: VarSymbol) => S((nme, vs, N))\n            case _ => N\n        case _ => N\n      .toList\n    val symbolsToPreserve = computeDefinedValues(includeNonTerms = true).iterator.map(_._2).toSet\n\n    if wasm.isSet then\n\n      val reportedMessages = mutable.Set.empty[Str]\n\n      loadWasm\n\n      var errored = false\n      given Raise =\n        case d @ ErrorReport(source = Source.Compilation) =>\n          errored = true\n          outerRaise(d)\n        case d => outerRaise(d)\n      val sessionImportSymbols = mutable.LinkedHashSet.from(pgrm.main.freeVars)\n      new BlockTraverser:\n        override def applyPath(p: Path): Unit = p match\n          case sel: Select =>\n            sel.symbol.foreach:\n              case sym: ModuleOrObjectSymbol => sessionImportSymbols += sym\n              case _ => ()\n            super.applyPath(sel)\n          case _ =>\n            super.applyPath(p)\n      .applyBlock(pgrm.main)\n      val sessionImports = mutable.LinkedHashMap.empty[Str, SessionBinding]\n      sessionImportSymbols.iterator.foreach: sym =>\n        sessionImportsBySymbol.get(sym).foreach: bindings =>\n          bindings.foreach: (bindingKey, binding) =>\n            sessionImports.update(bindingKey, binding)\n      val CompiledWasmModule(modWat, mainFnNme, systemMemMinPages, sessionExports) = ltl.givenIn:\n        WatBuilder().program(pgrm, N, wd, sessionImports.values.toSeq, symbolsToPreserve)\n      val modWatJsLit = JSBuilder.makeStringLiteral(modWat.mkString(output.ColWidth))\n\n      if wat.isSet then\n        output(\"Wat:\")\n        output(modWat.mkString(output.ColWidth))\n\n      // A program with errors may have a WAT that is worth inspecting, but anything that involves\n      // using Binaryen requires a valid WAT\n      if errored then return\n\n      if fwat.isSet then\n        output(\"Formatted Wat (Folded):\")\n        doc\"JSON.stringify(wasm.binaryenFmtWat($modWatJsLit, true));\"\n          .stripBreaks\n          .mkString(output.ColWidth)\n          .replace('\\n', ' ') |> host.execute match\n          case ReplHost.Result(content) =>\n            output(prettifyBinaryenWat(content))\n          case err =>\n            output(s\"Error: $err\")\n            return\n      if swat.isSet then\n        output(\"Formatted Wat (Stack):\")\n        doc\"JSON.stringify(wasm.binaryenFmtWat($modWatJsLit, false));\"\n          .stripBreaks\n          .mkString(output.ColWidth)\n          .replace('\\n', ' ') |> host.execute match\n          case ReplHost.Result(content) =>\n            output(prettifyBinaryenWat(content))\n          case err =>\n            output(s\"Error: $err\")\n            return\n\n      def mkQuery(preStr: Str, jsStr: Str)(k: Str => Unit) =\n        val queryStr = jsStr.replaceAll(\"\\n\", \" \")\n        val (reply, stderr) = host.query(\n          preStr,\n          queryStr,\n          !expectRuntimeOrCodeGenErrors && !expectErrors,\n        )\n        reply match\n          case ReplHost.Result(content) => k(content)\n          case ReplHost.Empty =>\n          case ReplHost.Unexecuted(message) => ???\n          case ReplHost.Error(isSyntaxError, message, otherOutputs) =>\n            if otherOutputs.nonEmpty then\n              otherOutputs.splitSane('\\n').foreach: line =>\n                output(s\"> ${line}\")\n            if isSyntaxError then\n              // If there is a syntax error in the generated code,\n              // it should be a code generation error.\n              raise(ErrorReport(\n                msg\"[Uncaught SyntaxError] ${message}\" -> N :: Nil,\n                source = Diagnostic.Source.Compilation,\n              ))\n            else\n              // Otherwise, it is considered a simple runtime error.\n              raise(ErrorReport(\n                msg\"${message}\" -> N :: Nil,\n                source = Diagnostic.Source.Runtime,\n              ))\n        end match\n        if stderr.nonEmpty then output(s\"// Standard Error:\\n${stderr}\")\n      end mkQuery\n\n      if !wasmSessionInitialized then\n        val intrinsicWatJsLit = JSBuilder.makeStringLiteral(\n          ltl.givenIn:\n            baseScp.nest.givenIn:\n              WatBuilder().intrinsicSupportModule().mkString(output.ColWidth),\n        )\n        host.execute(\n          doc\"\"\"await (async () => {\n            # const mem = new WebAssembly.Memory({ initial: ${systemMemMinPages} });\n            # const decodeUtf16 = new TextDecoder(\"utf-16le\");\n            # const system = {\n            #   mem,\n            #   mlx_str_from_utf16: (ptr, byteLen) =>\n            #     decodeUtf16.decode(new Uint8Array(mem.buffer, ptr, byteLen)),\n            # };\n            # const intrinsicModule = await $wasmSuppNme.binaryenCompileToModule($intrinsicWatJsLit, {});\n            # Object.assign(system, intrinsicModule.instance.exports);\n            # $wasmReplImportsRef = {\n            #   repl: Object.create(null),\n            #   system,\n            # };\n            # })();\"\"\"\n            .stripBreaks\n            .mkString(output.ColWidth),\n        ) match\n          case ReplHost.Result(_) =>\n            wasmSessionInitialized = true\n            wasmSessionMemPages = systemMemMinPages\n          case r =>\n            output(s\"Failed to initialize wasm REPL session object: $r\")\n        end match\n      else if systemMemMinPages > wasmSessionMemPages then\n        host.execute(\n          doc\"\"\"(() => {\n            # const extraPages = ${systemMemMinPages - wasmSessionMemPages};\n            # $wasmReplImportsRef.system.mem.grow(extraPages);\n            # })();\"\"\"\n            .stripBreaks\n            .mkString(output.ColWidth),\n        ) match\n          case ReplHost.Result(_) =>\n            wasmSessionMemPages = systemMemMinPages\n          case r =>\n            output(s\"Failed to grow wasm REPL session memory: $r\")\n      end if\n      val exportAssignments = sessionExports.flatMap(_.exportNameOpt.toSeq).map: exportName =>\n        s\"\"\"$wasmReplImportsRef.repl[\"$exportName\"] = exports[\"$exportName\"];\"\"\"\n      val jsBody =\n        if exportAssignments.nonEmpty then\n          s\"\"\"const result = exports[\"$mainFnNme\"](); ${exportAssignments.mkString(\" \")} return result;\"\"\"\n        else\n          s\"\"\"return exports[\"$mainFnNme\"]();\"\"\"\n      val jsStr =\n        s\"\"\"await wasm.binaryenPrintFuncRes($modWatJsLit, $wasmReplImportsRef, exports => { $jsBody });\"\"\"\n      output(\"Wasm result:\")\n      mkQuery(\"\", jsStr): out =>\n        // Omit the last line which is always \"undefined\" or the unit.\n        val result = out.lastIndexOf('\\n') match\n          case n if n >= 0 => out.substring(0, n)\n          case _ => \"\"\n        sessionExports.foreach: binding =>\n          binding.bindingSyms.foreach: sym =>\n            sessionImportsBySymbol\n              .getOrElseUpdate(sym, mutable.LinkedHashMap.empty)\n              .update(binding.bindingKey, binding)\n        output(s\"= $result\")\n    end if\n\n  end processIRBlock\n\nend WasmDiffMaker\n"
  },
  {
    "path": "hkmc2DiffTests/src/test/scala/hkmc2/Watcher.scala",
    "content": "package hkmc2\n\nimport scala.collection.mutable\nimport scala.jdk.CollectionConverters.*\n\nimport mlscript.utils.*, shorthands.*\n\nimport better.files.*\nimport _root_.io.methvin\nimport methvin.better.files.*\nimport methvin.watcher.{DirectoryWatcher, PathUtils, DirectoryChangeEvent, DirectoryChangeListener}\nimport methvin.watcher.hashing.{FileHash, FileHasher}\nimport java.time.LocalDateTime\nimport java.time.temporal._\nimport io.FileSystem, io.PlatformPath.given\n\n// Note: when SBT's `fork` is set to `false`, the path should be `File(\"hkmc2/\")` instead...\n// * Only the first path can contain tests. The other paths are only watched for source changes.\nobject MainWatcher extends Watcher(\n    File(\"../hkmc2/shared/src\") ::\n    File(\"./src\") ::\n    // File(\"../hkmc2Benchmarks/src\") ::\n    Nil\n):\n  def main(args: Array[String]): Unit = run\n\nclass Watcher(dirs: Ls[File]):\n  val dirPaths = dirs.map(d => os.Path(d.pathAsString))\n  \n  dirs.foreach: dir =>\n    println((fansi.Color.Blue(\"Watching directory \") ++ fansi.Color.DarkGray(dir.toString)).toString)\n  \n  val fileHashes = mutable.Map.empty[File, FileHash]\n  val completionTime = mutable.Map.empty[File, LocalDateTime]\n  val fileHasher = FileHasher.DEFAULT_FILE_HASHER\n  \n  given cctx: CompilerCtx = CompilerCtx.fresh(FileSystem.default)\n  \n  val watcher: DirectoryWatcher = DirectoryWatcher.builder()\n    .logger(org.slf4j.helpers.NOPLogger.NOP_LOGGER)\n    .paths(dirs.map(_.toJava.toPath).asJava)\n    .fileHashing(false) // so that simple save events trigger processing eve if there's no file change\n    .listener(new DirectoryChangeListener {\n      def onEvent(event: DirectoryChangeEvent): Unit = try\n        // println(event)\n        val hash = PathUtils.hash(fileHasher, event.path)\n        val file = File(event.path)\n        val old = fileHashes.get(event.path)\n        fileHashes(event.path) = hash\n        old match\n          case S(existingHash) =>\n            if existingHash === hash then\n              // if file.extension =/= S(\".cmd\") then return\n              // else\n              val newTime = LocalDateTime.now()\n              completionTime.get(event.path) match\n                case S(time) =>\n                  val diff = time.until(newTime, ChronoUnit.SECONDS)\n                  if diff <= 1 then\n                    // println(s\"Debounced $time -> $newTime = $diff s\")\n                    return\n                case N =>\n                  System.err.println(\"It seems the previous completion time was not recorded\")\n                  return\n          case N =>\n        import java.nio.file.StandardWatchEventKinds\n        import java.nio.file.WatchEvent\n        import java.nio.file.Path\n        val et = event.eventType\n        val count = event.count\n        et match\n          case DirectoryChangeEvent.EventType.OVERFLOW => ???\n          case _ =>\n            et.getWatchEventKind.asInstanceOf[WatchEvent.Kind[Path]] match\n              case StandardWatchEventKinds.ENTRY_CREATE => onCreate(file, count)\n              case StandardWatchEventKinds.ENTRY_MODIFY => onModify(file, count)\n              case StandardWatchEventKinds.ENTRY_DELETE => onDelete(file, count)\n        completionTime(event.path) = LocalDateTime.now()\n      catch ex =>\n        // System.err.println(\"Unexpected error in watcher: \" + ex)\n        // ex.printStackTrace()\n        System.err.println(\"Unexpected error in watcher (\" + ex.getClass() + \")\")\n        watcher.close()\n        throw ex\n    })\n    .build();\n    \n  def run: Unit =\n    try watcher.watch()\n    finally watcher.close()\n  \n  def go(file: File) =\n    // println(s\"go $file\")\n    val isMls = file.toString.endsWith(\".mls\")\n    if file.toString.endsWith(\".scala\") then\n      watcher.close()\n    else if isMls || file.toString.endsWith(\".cmd\") then\n      Thread.sleep(100)\n      val path = os.Path(file.pathAsString)\n      val basePath = path.segments.drop(dirPaths.head.segmentCount).toList.init\n      val relativeName = basePath.map(_ + \"/\").mkString + path.baseName\n      val rootPath = os.pwd/os.up\n      val testBasePath = rootPath/\"hkmc2\"/\"shared\"/\"src\"/\"test\"\n      val preludePath = testBasePath/\"mlscript\"/\"decls\"/\"Prelude.mls\"\n      val predefPath = testBasePath/\"mlscript-compile\"/\"Predef.mls\"\n      val isModuleFile = path.segments.contains(\"mlscript-compile\")\n      if isModuleFile\n      then\n        given Config = Config.default(testBasePath)\n        MLsCompiler(\n          paths = new MLsCompiler.Paths:\n            val preludeFile = preludePath\n            val runtimeFile = testBasePath/\"mlscript-compile\"/\"Runtime.mjs\"\n            val termFile = testBasePath/\"mlscript-compile\"/\"Term.mjs\",\n          mkRaise = ReportFormatter(System.out.println, colorize = true).mkRaise\n        ).compileModule(path)\n      else\n        val dm = new MainDiffMaker(rootPath.toString, path, preludePath, predefPath, relativeName):\n          def cctx = Watcher.this.cctx\n          override def unhandled(blockLineNum: Int, exc: Throwable): Unit =\n            exc.printStackTrace()\n            super.unhandled(blockLineNum, exc)\n        dm.run()\n      \n  \n  def show(file: File) =\n    fansi.Color.Yellow:\n      file.toString.stripPrefix(dirs.head.toString)\n  \n  def pre = fansi.Color.Blue(\">> \").toString\n  \n  def onCreate(file: File, count: Int) =\n    println(pre + show(file).toString + fansi.Color.Blue(\" created\"))\n    go(file)\n  \n  def onModify(file: File, count: Int) =\n    println(pre + show(file).toString + fansi.Color.Blue(s\" modified $count times\"))\n    go(file)\n  \n  def onDelete(file: File, count: Int) =\n    println(pre + show(file).toString + fansi.Color.Blue(\" deleted\"))\n    // go(file)\n\n\n"
  },
  {
    "path": "hkmc2NofibTests/src/test/scala/hkmc2/NofibCompileTestRunner.scala",
    "content": "package hkmc2\n\nimport mlscript.utils._, shorthands._\nimport io.PlatformPath.given\n\n\nclass NofibCompileTestRunner extends CompileTestRunnerBase(\n  compileDirs = TestFolders.nofibCompileDirs(os.pwd),\n):\n  protected def cctx: CompilerCtx = NofibCompileTestRunner.cctx\n\nend NofibCompileTestRunner\n\n\nobject NofibCompileTestRunner:\n  \n  given cctx: CompilerCtx = CompilerCtx.fresh(io.FileSystem.default)\n\nend NofibCompileTestRunner\n\n"
  },
  {
    "path": "hkmc2NofibTests/src/test/scala/hkmc2/NofibDiffTestRunner.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\n\nimport mlscript.utils._\nimport os.Path\nimport io.PlatformPath.given\n\nobject NofibDiffTestState extends DiffTestRunner.State:\n\n  override def testDir = TestFolders.nofibDiffDir(workingDir)\n\nclass NofibDiffTestRunner\n  extends DiffTestRunnerBase(NofibDiffTestState)\n  with ParallelTestExecution\n\n"
  },
  {
    "path": "hkmc2WasmTests/src/test/scala/hkmc2/WasmCompileTestRunner.scala",
    "content": "package hkmc2\n\nimport mlscript.utils._, shorthands._\nimport io.PlatformPath.given\n\n\nclass WasmCompileTestRunner extends CompileTestRunnerBase(\n  compileDirs = TestFolders.wasmCompileDirs(os.pwd),\n):\n  protected def cctx: CompilerCtx = WasmCompileTestRunner.cctx\n\nend WasmCompileTestRunner\n\n\nobject WasmCompileTestRunner:\n  \n  given cctx: CompilerCtx = CompilerCtx.fresh(io.FileSystem.default)\n\nend WasmCompileTestRunner\n"
  },
  {
    "path": "hkmc2WasmTests/src/test/scala/hkmc2/WasmDiffTestRunner.scala",
    "content": "package hkmc2\n\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\n\nimport mlscript.utils._\nimport os.Path\nimport io.PlatformPath.given\n\nobject WasmDiffTestState extends DiffTestRunner.State:\n\n  override def testDir = TestFolders.wasmDiffDir(workingDir)\n\nclass WasmDiffTestRunner\n  extends DiffTestRunnerBase(WasmDiffTestState)\n  with ParallelTestExecution\n"
  },
  {
    "path": "index.css",
    "content": "body {\n    font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n    font-size: 16px;\n    background-color: #eee8d5;\n    max-width: 1200px;\n    margin: 0px auto;\n    padding: 5px;\n    color: #073642;\n    --keyword-color: #93a1a1;\n    --name-color: LightGreen;\n    --type-color: LightBlue;\n    --no-value-color: Gray;\n    --panel-background: #002b36;\n}\n\nh1, p{\n    padding: 0px 10px;\n}\n\n#content {\n    width: 100%;\n    padding: 0px;\n    height: 750px;\n    display: grid;\n    grid-template-columns: 50% 50%;\n    grid-template-rows: 100%;\n    grid-gap: 1.5rem;\n}\n\n.panel {\n    padding: 1rem;\n    box-sizing: border-box;\n    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n    width: 100%;\n    height: 100%;\n    box-sizing: border-box;\n    border-radius: 10px;\n    background: var(--panel-background);\n    /* color: #93a1a1; */\n    /* color: #cacaca; */\n    color: #efefef;\n    font-size: 14px;\n    overflow: auto;\n}\n\n#mlscript-input {\n    resize: none;\n    outline: none;\n}\n\n#mlscript-output {\n    width: 130%;\n}\n\n#mlscript-output > table {\n    border-collapse: collapse;\n}\n\n#mlscript-output > table > thead {\n    font-weight: bold;\n}\n\n#mlscript-output td {\n    padding: 0.25rem 0.5rem;\n    border: 1px solid white;\n}\n\n#mlscript-output td.name {\n    color: var(--name-color);\n}\n\n#mlscript-output td.type {\n    color: var(--type-color);\n}\n\n#mlscript-output td.no-value {\n    color: var(--no-value-color);\n}\n"
  },
  {
    "path": "index.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\">\n    <title>MLscript demonstration</title>\n  </head>\n  <body>\n  <h1>ML<sub>script</sub> online demonstration</h1>\n  <div id=\"content\">\n    <textarea id=\"mlscript-input\" class=\"panel\" spellcheck=\"false\">\ntype List[A] = Cons[A] | Nil\n\nclass Cons[out A](head: A, tail: List[A]) {\n  fun map: (A -> 'B) -> List['B]\n  map(f) = Cons of f(head), tail.map(f)\n}\nmodule Nil {\n  fun map(f) = Nil\n}\n\nfun (::) cons(x, xs) = Cons(x, xs)\n\nfun show(xs) =\n  let rec go(xs) = if xs is\n    Cons(h, Nil) then String(h)\n    Cons(h, t)   then join(String(h), \", \", go(t))\n    Nil          then \"\"\n  join(\"[\", go(xs), \"]\")\n\nlet xs = 1 :: 2 :: 3 :: Nil\n\nshow(xs)\n\nshow(xs.map of x => succ(x))\n</textarea>\n<!-- let rec recursive_monster = fun x ->\n  { thing = x;\n    self = recursive_monster x } -->\n    <div id=\"mlscript-output\" class=\"panel\"></div>\n  </div>\n  <script type=\"text/javascript\" src=\"bin/mlscript-opt.js\"></script>\n  <br/>\n  <p>The code is available <a href=\"https://github.com/hkust-taco/mlscript\">on github</a>.</p>\n  <br/>\n  <p>Note: JavaScript code generation (used to evaluate the result) is not perfect yet and has rough edges.\n    Also, try typing `window.alert of \"Hello!\"` and see what happens!</p>\n</html>\n"
  },
  {
    "path": "local_testing.html",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\">\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"index.css\">\n    <title>MLscript demonstration</title>\n  </head>\n  <body>\n  <h1>MLscript demonstration</h1>\n  <div id=\"content\">\n    <textarea id=\"mlscript-input\" class=\"panel\" spellcheck=\"false\">\ntype List[A] = Cons[A] | Nil\n\nclass Cons[out A](head: A, tail: List[A]) {\n  fun map: (A -> 'B) -> List['B]\n  map(f) = Cons of f(head), tail.map(f)\n}\nmodule Nil {\n  fun map(f) = Nil\n}\n\nfun (::) cons(x, xs) = Cons(x, xs)\n\nfun show(xs) =\n  let rec go(xs) = if xs is\n    Cons(h, Nil) then String(h)\n    Cons(h, t)   then join(String(h), \", \", go(t))\n    Nil          then \"\"\n  join(\"[\", go(xs), \"]\")\n\nlet xs = 1 :: 2 :: 3 :: Nil\n\nshow(xs)\n\nshow(xs.map of x => succ(x))\n</textarea>\n    <div id=\"mlscript-output\" class=\"panel\"></div>\n  </div>\n  <script type=\"text/javascript\" src=\"js/target/scala-2.13/mlscript-fastopt/main.js\"></script>\n  <br/>\n  <!-- <p>The code is available TODO.</p> -->\n  <br/>\n\n</html>\n"
  },
  {
    "path": "out/apps/.gitkeep",
    "content": ""
  },
  {
    "path": "out/apps/AccountingTest.md",
    "content": "# Accounting\n\n|Year|L1|L2|\n|---|--:|--:|\n|Initial|200.0|1000.0|\n|Y1|166.1|333.3|\n|Y2|156.1|133.3|\n|Y3|146.1|3.3|\n\n> **❗️** Unspent balance of L1: `146.1`\n\n### Remaining Available Funds\n\n|Summary|   |\n|---|--:|\n|Matchable|149.5|\n|Non-matchable|0.0|\n"
  },
  {
    "path": "out/test.md",
    "content": "whoops"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"mlscript\",\n  \"dependencies\": {\n    \"benchmark\": \"^2.1.4\",\n    \"binaryen\": \"^129.0.0\",\n    \"typescript\": \"^4.7.4\"\n  }\n}\n"
  },
  {
    "path": "project/build.properties",
    "content": "sbt.version=1.12.8\n"
  },
  {
    "path": "project/plugins.sbt",
    "content": "addSbtPlugin(\"org.wartremover\" % \"sbt-wartremover\" % \"3.5.6\")\naddSbtPlugin(\"org.scala-js\" % \"sbt-scalajs\" % \"1.20.2\")\naddSbtPlugin(\"org.portable-scala\" % \"sbt-scalajs-crossproject\" % \"1.3.2\")\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ConstraintSolver.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable.{Map => MutMap, SortedMap => MutSortMap, Set => MutSet, Stack => MutStack, Buffer}\nimport scala.collection.immutable.{SortedSet, SortedMap}\nimport scala.util.chaining._\nimport scala.annotation.tailrec\nimport mlscript.utils._, shorthands._\nimport mlscript.Message._\n\nclass ConstraintSolver extends NormalForms { self: Typer =>\n  \n  def stopConstrainingOnFirstFailure: Bool = false\n  def verboseConstraintProvenanceHints: Bool = verbose\n  def defaultStartingFuel: Int =\n    // 5000\n    10000 // necessary for fat definitions in OCamlList.mls\n  var startingFuel: Int = defaultStartingFuel\n  def depthLimit: Int =\n    // 150\n    // 200\n    250\n  \n  type ExtrCtx = MutSortMap[TV, Buffer[(Bool, ST)]] // tv, is-lower, bound\n  \n  protected var currentConstrainingRun = 0\n  \n  \n  private def noSuchMember(info: DelayedTypeInfo, fld: Var): Diagnostic =\n    ErrorReport(\n      msg\"${info.decl.kind.str.capitalize} `${info.decl.name}` does not contain member `${fld.name}`\" -> fld.toLoc :: Nil, newDefs)\n  \n  def lookupMember(clsNme: Str, rfnt: Var => Opt[FieldType], fld: Var)\n        (implicit ctx: Ctx, raise: Raise)\n        : Either[Diagnostic, NuMember]\n        = {\n    val info = ctx.tyDefs2.getOrElse(clsNme, ???/*TODO*/)\n    \n    if (info.isComputing) {\n      \n      ??? // TODO support?\n      \n    } else info.complete() match {\n      \n      case cls: TypedNuCls =>\n        cls.members.get(fld.name) match {\n          case S(m) => R(m)\n          case N => L(noSuchMember(info, fld))\n        }\n        \n      case _ => ??? // TODO\n      \n    }\n    \n  }\n  \n  \n  /** Note: `mkType` is just for reporting errors. */\n  def lookupField(mkType: () => ST, clsNme: Opt[Str], rfnt: Var => Opt[FieldType],\n        tags: SortedSet[AbstractTag], _fld: Var)\n        (implicit ctx: Ctx, raise: Raise)\n        : FieldType\n        = trace(s\"Looking up field ${_fld.name} in $clsNme & ${tags} & {...}\") {\n    \n    // * Field selections with field names starting with `#` are a typer hack to access private members.\n    val (fld, allowPrivateAccess) =\n      if (_fld.name.startsWith(\"#\")) (Var(_fld.name.tail).withLocOf(_fld), true)\n      else (_fld, false)\n    \n    val fromRft = rfnt(fld)\n    \n    var foundRec: Opt[Diagnostic] = N\n    \n    def getFieldType(info: DelayedTypeInfo): Opt[FieldType] = {\n      \n      // * The raw type of this member, with original references to the class' type variables/type parameters\n      val raw = (if (info.isComputed) N else info.typedFields.get(fld)) match {\n        \n        case S(fty) =>\n          if (info.privateParams.contains(fld) && !allowPrivateAccess)\n            err(msg\"Parameter '${fld.name}' cannot be accessed as a field\" -> fld.toLoc :: Nil)\n          S(fty)\n        \n        case N if info.isComputing =>\n          \n          if (info.allFields.contains(fld)) // TODO don't report this if the field can be found somewhere else!\n            foundRec = S(ErrorReport(\n              msg\"Indirectly-recursive member should have a type signature\" -> fld.toLoc :: Nil, newDefs))\n          \n          N\n        \n        case N =>\n          \n          def handle(virtualMembers: Map[Str, NuMember]): Opt[FieldType] =\n            virtualMembers.get(fld.name) match {\n              case S(d: TypedNuFun) =>\n                if (d.fd.isLetOrLetRec)\n                  err(msg\"Let binding '${d.name}' cannot tbe accessed as a field\" -> fld.toLoc ::\n                    msg\"Use a `val` declaration to make it a field\" -> d.fd.toLoc ::\n                    Nil)\n                val ty = d.typeSignature\n                S(\n                  if (d.fd.isMut) FieldType(S(ty), ty)(d.prov)\n                  else ty.toUpper(d.prov)\n                )\n              case S(p: NuParam) =>\n                if (!allowPrivateAccess && !p.isPublic)\n                  err(msg\"Parameter '${p.nme.name}' cannot be accessed as a field\" -> fld.toLoc ::\n                    msg\"Either make the parameter a `val` or access it through destructuring\" -> p.nme.toLoc ::\n                    Nil)\n                S(p.ty)\n              case S(m) =>\n                S(err(msg\"Access to ${m.kind.str} member not yet supported\", fld.toLoc).toUpper(noProv))\n              case N => N\n            }\n          \n          info.complete() match {\n            case cls: TypedNuCls => handle(cls.virtualMembers)\n            case trt: TypedNuTrt => handle(trt.virtualMembers)\n            case mxn: TypedNuMxn => handle(mxn.virtualMembers)\n            case TypedNuDummy(d) => N\n            case _ => ??? // TODO\n          }\n          \n      }\n      \n      println(s\"Lookup ${info.decl.name}.${fld.name} : $raw where ${raw.fold(\"\")(_.ub.showBounds)}\")\n      \n      val freshenedRaw = raw.map { raw =>\n        \n        implicit val freshened: MutMap[TV, ST] = MutMap.empty\n        implicit val shadows: Shadows = Shadows.empty\n        \n        info.tparams.foreach { case (tn, _tv, vi) =>\n          val targ = rfnt(Var(info.decl.name + \"#\" + tn.name)) match {\n            // * TODO to avoid infinite recursion due to ever-expanding type args,\n            // *  we should set the shadows of the targ to be the same as that of the parameter it replaces... \n            case S(fty) if vi === S(VarianceInfo.co) => fty.ub\n            case S(fty) if vi === S(VarianceInfo.contra) => fty.lb.getOrElse(BotType)\n            case S(fty) =>\n              TypeBounds.mk(\n                fty.lb.getOrElse(BotType),\n                fty.ub,\n              )\n            case N =>\n              TypeBounds(\n                // _tv.lowerBounds.foldLeft(BotType: ST)(_ | _),\n                // _tv.upperBounds.foldLeft(TopType: ST)(_ & _),\n                _tv.lowerBounds.foldLeft(\n                  Extruded(true, SkolemTag(_tv)(provTODO))(provTODO, Nil): ST\n                  // ^ TODO provide extrusion reason?\n                )(_ | _),\n                _tv.upperBounds.foldLeft(\n                  Extruded(false, SkolemTag(_tv)(provTODO))(provTODO, Nil): ST\n                  // ^ TODO provide extrusion reason?\n                )(_ & _),\n              )(_tv.prov)\n          }\n          freshened += _tv -> targ\n        }\n        \n        raw.freshenAbove(info.level, rigidify = false)\n      }\n      \n      println(s\"Fresh[${info.level}] ${info.decl.name}.${fld.name} : $freshenedRaw where ${freshenedRaw.map(_.ub.showBounds)}\")\n      \n      freshenedRaw\n    }\n    \n    val fromCls = clsNme.flatMap(clsNme => getFieldType(ctx.tyDefs2(clsNme)))\n    \n    val fromTrts = tags.toList.collect {\n      case TraitTag(nme, iht) =>\n        getFieldType(ctx.tyDefs2(nme.name))\n    }.flatten\n    \n    val fields = fromRft.toList ::: fromCls.toList ::: fromTrts\n    \n    println(s\"  & ${fromRft}  (from refinement)\")\n    \n    fields match {\n      case x :: xs =>\n        xs.foldRight(x)(_ && _)\n      case Nil =>\n        foundRec match {\n          case S(d) => err(d).toBoth(noProv)\n          case N =>\n            err(msg\"Type `${mkType().expPos}` does not contain member `${fld.name}`\" ->\n              fld.toLoc :: Nil).toBoth(noProv)\n        }\n    }\n    \n  }()\n  \n  \n  // * Each type has a shadow which identifies all variables created from copying\n  // * variables that existed at the start of constraining.\n  // * The intent is to make the total number of shadows in a given constraint\n  // * resolution run finite, so we can avoid divergence with a \"cyclic-lookign constraint\" error.\n  type ShadowSet = Set[ST -> ST]\n  case class Shadows(current: ShadowSet, previous: ShadowSet) {\n    def size: Int = current.size + previous.size\n  }\n  object Shadows { val empty: Shadows = Shadows(Set.empty, Set.empty) }\n  \n  /** Constrains the types to enforce a subtyping relationship `lhs` <: `rhs`. */\n  def constrain(lhs: SimpleType, rhs: SimpleType)\n        (implicit raise: Raise, prov: TypeProvenance, ctx: Ctx, shadows: Shadows = Shadows.empty)\n        : Unit = {\n    currentConstrainingRun += 1\n    if (stopConstrainingOnFirstFailure)\n      constrainImpl(lhs, rhs)(err => {\n        raise(err)\n        return()\n      }, prov, ctx, shadows)\n    else constrainImpl(lhs, rhs)\n  }\n  def constrainImpl(lhs: SimpleType, rhs: SimpleType)\n        (implicit raise: Raise, prov: TypeProvenance, ctx: Ctx, shadows: Shadows)\n        : Unit = { val outerCtx = ctx ; {\n    val ctx = ()\n    \n    // We need a cache to remember the subtyping tests in process; we also make the cache remember\n    // past subtyping tests for performance reasons (it reduces the complexity of the algoritghm):\n    val cache: MutSet[(SimpleType, SimpleType)] = MutSet.empty\n    val startingFuel = self.startingFuel\n    var fuel = startingFuel\n    val stack = MutStack.empty[ST -> ST]\n    \n    println(s\"CONSTRAIN $lhs <! $rhs\")\n    println(s\"  where ${FunctionType(lhs, rhs)(noProv).showBounds}\")\n    \n    type ConCtx = Ls[SimpleType] -> Ls[SimpleType]\n    \n    \n    val abort = () => return\n    \n    def abbreviate(msgs: Ls[Message -> Opt[Loc]]) = {\n      val treshold = 15\n      if (msgs.sizeCompare(treshold) <= 0) msgs\n      else msgs.take(treshold) :::\n        msg\"......\" -> N :: msg\"......\" -> N :: msgs.reverseIterator.take(treshold).toList.reverse\n    }\n    \n    def consumeFuel()(implicit cctx: ConCtx, ctx: Ctx) = {\n      def msgHead = msg\"Subtyping constraint of the form `${lhs.expPos} <: ${rhs.expNeg}`\"\n      if (stack.sizeIs > depthLimit) {\n        err(\n          msg\"$msgHead exceeded recursion depth limit (${depthLimit.toString})\" -> prov.loco\n          :: (\n            if (!explainErrors) msg\"Note: use flag `:ex` to see internal error info.\" -> N :: Nil\n            else if (verbose) stack.toList.filterOutConsecutive().flatMap { case (l, r) =>\n              msg\"while constraining:  ${s\"$l\"}\" -> l.prov.loco ::\n              msg\"                       <!<  ${s\"$r\"}\" -> r.prov.loco ::\n              Nil\n            } else abbreviate(stack.toList.filterOutConsecutive().map(c =>\n              msg\"while constraining:  ${s\"${c._1}  <!<  ${c._2}\"}\" -> N))\n          )\n        )\n        abort()\n      } else\n      if (fuel <= 0) {\n        err(\n          msg\"$msgHead took too many steps and ran out of fuel (${startingFuel.toString})\" -> prov.loco\n          :: (\n          if (!explainErrors) msg\"Note: use flag `:ex` to see internal error info.\" -> N :: Nil\n          else cctx._1.map(c => msg\" + ${s\"$c\"}\" -> c.prov.loco)\n            ::: cctx._2.map(c => msg\" - ${s\"$c\"}\" -> c.prov.loco))\n        )\n        abort()\n      } else fuel -= 1\n    }\n    \n    def mkCase[A](str: Str)(k: Str => A)(implicit dbgHelp: Str): A = {\n      val newStr = dbgHelp + \".\" + str\n      println(newStr)\n      k(newStr)\n    }\n    \n    /** This is used in the context of constrained types.\n      * We \"unstash\" all constraints that were currently stashed/saved for later\n      * due to a polymorphism level mismatch. */\n    def unstash(oldCtx: Ctx)(implicit ctx: Ctx, cctx: ConCtx, prevCctxs: Ls[ConCtx]): Unit = {\n      val ec = ctx.extrCtx\n      trace(s\"UNSTASHING...\") {\n        implicit val ctx: Ctx = oldCtx\n        ec.foreach { case (tv, bs) => \n          println(s\"where($tv) ${tv.showBounds}\")\n          bs.foreach {\n          case (true, b) => println(s\"UNSTASH ${b} <: $tv where ${b.showBounds}\"); rec(b, tv, false)\n          case (false, b) => println(s\"UNSTASH ${tv} <: $b where ${b.showBounds}\"); rec(tv, b, false)\n        }}\n        ec.clear()\n      }()\n    } // ensuring ctx.extrCtx.isEmpty\n    \n    /* To solve constraints that are more tricky. */\n    def goToWork(lhs: ST, rhs: ST)(implicit cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows): Unit = {\n      val lhsDNF = DNF.mkDeep(MaxLevel, Nil, lhs, true)\n      val rhsDNF = DNF.mkDeep(MaxLevel, Nil, rhs, false)\n      \n      val oldCtx = ctx\n      \n      if (!rhsDNF.isPolymorphic) {\n        \n        constrainDNF(lhsDNF, rhsDNF)\n        \n      } else ctx.nextLevel { implicit ctx =>\n        \n        implicit val state: MutMap[TV, ST] = MutMap.empty\n        val rigid = DNF(MaxLevel,\n          rhsDNF.cons.mapKeys(_.freshenAbove(rhsDNF.polymLevel, rigidify = true)),\n          rhsDNF.cs.map(_.freshenAbove(rhsDNF.polymLevel, rigidify = true)),\n        )\n        \n        println(s\"DNF BUMP TO LEVEL ${lvl}  -->  $rigid\")\n        // println(s\"where ${rigid.showBounds}\")\n        \n        constrainDNF(lhsDNF, rigid)\n        \n        unstash(oldCtx)\n        \n      }\n    }\n    \n    def constrainDNF(_lhs: DNF, rhs: DNF)(implicit cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows): Unit =\n    trace(s\"${lvl}. ARGH  ${_lhs}  <!  $rhs\") {\n      annoyingCalls += 1\n      consumeFuel()\n      \n      require(!rhs.isPolymorphic)\n      if (rhs.cons.nonEmpty) ??? // TODO handle when the RHS has first-class constraints\n      \n      val (lhsCons, lhsCs) = _lhs.instantiate\n      \n      // * Discharge all first-class constraints found in the LHS\n      trace(s\"DNF DISCHARGE CONSTRAINTS\") {\n        lhsCons.foreach(c => rec(c._1, c._2, false))\n      }()\n      \n      // * Same remark as in the `rec` method [note:1]\n      // assert(lvl >= rhs.level)\n      \n      lhsCs.foreach { case Conjunct(lnf, vars, rnf, nvars) =>\n        \n        def local(): Unit = { // * Used to return early in simple cases\n          \n          vars.headOption match {\n            case S(v) =>\n              rec(v, rhs.toType() | Conjunct(lnf, vars - v, rnf, nvars).toType().neg(), true)\n            case N =>\n              implicit val etf: ExpandTupleFields = true\n              val fullRhs = nvars.iterator.map(DNF.mkDeep(MaxLevel, Nil, _, true))\n                .foldLeft(rhs | DNF.mkDeep(MaxLevel, Nil, rnf.toType(), false))(_ | _)\n              println(s\"Consider ${lnf} <: ${fullRhs}\")\n              \n              // The following crutch is necessary because the pesky Without types may get stuck\n              //  on type variables and type variable negations:\n              lnf match {\n                case LhsRefined(S(Without(NegType(tv: TV), ns)), tts, rcd, trs) =>\n                  return rec((\n                    fullRhs.toType() | LhsRefined(N, tts, rcd, trs).toType().neg()).without(ns).neg(), tv, true)\n                case LhsRefined(S(Without(b, ns)), tts, rcd, trs) =>\n                  assert(b.isInstanceOf[TV])\n                  return rec(b, (\n                    fullRhs.toType() | LhsRefined(N, tts, rcd, trs).toType().neg()).without(ns), true)\n                case _ => ()\n              }\n              \n              // First, we filter out those RHS alternatives that obviously don't match our LHS:\n              val possible = fullRhs.cs.filter { r =>\n                \n                // Note that without this subtyping check,\n                //  the number of constraints in the `eval1_ty_ugly = eval1_ty`\n                //  ExprProb subsumption test case explodes.\n                if ((r.rnf is RhsBot) && r.vars.isEmpty && r.nvars.isEmpty && lnf <:< r.lnf) {\n                  println(s\"OK  $lnf <: $r\")\n                  return ()\n                }\n                \n                // println(s\"Possible? $r ${lnf & r.lnf}\")\n                !vars.exists(r.nvars) && ((lnf & (r.lnf, pol = false))(ctx, etf = false)).isDefined && ((lnf, r.rnf) match {\n                  case (LhsRefined(_, ttags, _, _), RhsBases(objTags, rest, trs))\n                    if objTags.exists { case t: TraitTag => ttags(t); case _ => false }\n                    => false\n                  case (LhsRefined(S(ot: ClassTag), _, _, _), RhsBases(objTags, rest, trs))\n                    => !objTags.contains(ot)\n                  case _ => true\n                })\n              }\n              \n              println(s\"Possible: \" + possible)\n              \n              if (doFactorize) {\n                // We try to factorize the RHS to help make subsequent solving take shortcuts:\n                \n                val fact = factorize(possible, sort = false)\n                \n                println(s\"Factorized: \" + fact)\n                \n                // Finally, we enter the \"annoying constraint\" resolution routine:\n                annoying(Nil, lnf, fact, RhsBot)\n                \n              } else {\n                // Alternatively, without factorization (does not actually make a difference most of the time):\n                \n                annoying(Nil, lnf, possible.map(_.toType()), RhsBot)\n                \n              }\n              \n          }\n          \n        }\n        \n        local()\n        \n      }\n    }()\n    \n    /* Solve annoying constraints,\n        which are those that involve either unions and intersections at the wrong polarities or negations.\n        This works by constructing all pairs of \"conjunct <: disjunct\" implied by the conceptual\n        \"DNF <: CNF\" form of the constraint. */\n    def annoying(ls: Ls[SimpleType], done_ls: LhsNf, rs: Ls[SimpleType], done_rs: RhsNf)\n          (implicit cctx: ConCtx, prevCctxs: Ls[ConCtx], shadows: Shadows, ctx: Ctx, dbgHelp: Str = \"Case\")\n          : Unit =\n    {\n      annoyingCalls += 1\n      consumeFuel()\n      annoyingImpl(ls, done_ls, rs, done_rs)\n    }\n    \n    // TODO improve by moving things to the right side *before* branching out in the search!\n    def annoyingImpl(ls: Ls[SimpleType], done_ls: LhsNf, rs: Ls[SimpleType], done_rs: RhsNf)\n          (implicit cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows, dbgHelp: Str = \"Case\")\n          : Unit =\n    trace(s\"${lvl}. A  $done_ls  %  $ls  <!  $rs  %  $done_rs\") {\n      def mkRhs(ls: Ls[SimpleType]): SimpleType = {\n        def tys = (ls.iterator ++ done_ls.toTypes).map(_.neg()) ++ rs.iterator ++ done_rs.toTypes\n        tys.reduceOption(_ | _).getOrElse(BotType)\n      }\n      def mkLhs(rs: Ls[SimpleType]): SimpleType = {\n        def tys = ls.iterator ++ done_ls.toTypes ++ (rs.iterator ++ done_rs.toTypes).map(_.neg())\n        tys.reduceOption(_ & _).getOrElse(TopType)\n      }\n      implicit val etf: ExpandTupleFields = false\n      (ls, rs) match {\n        // If we find a type variable, we can weasel out of the annoying constraint by delaying its resolution,\n        // saving it as negations in the variable's bounds!\n        case ((tv: TypeVariable) :: ls, _) => rec(tv, mkRhs(ls), done_ls.isTop && ls.forall(_.isTop))\n        case (_, (tv: TypeVariable) :: rs) => rec(mkLhs(rs), tv, done_rs.isBot && rs.forall(_.isBot))\n        case (TypeBounds(lb, ub) :: ls, _) => annoying(ub :: ls, done_ls, rs, done_rs)\n        case (_, TypeBounds(lb, ub) :: rs) => annoying(ls, done_ls, lb :: rs, done_rs)\n        case (ComposedType(true, ll, lr) :: ls, _) =>\n          mkCase(\"1\"){ implicit dbgHelp => annoying(ll :: ls, done_ls, rs, done_rs) }\n          mkCase(\"2\"){ implicit dbgHelp => annoying(lr :: ls, done_ls, rs, done_rs) }\n        case (_, ComposedType(false, rl, rr) :: rs) =>\n          mkCase(\"1\"){ implicit dbgHelp => annoying(ls, done_ls, rl :: rs, done_rs) }\n          mkCase(\"2\"){ implicit dbgHelp => annoying(ls, done_ls, rr :: rs, done_rs) }\n        case (_, ComposedType(true, rl, rr) :: rs) =>\n          annoying(ls, done_ls, rl :: rr :: rs, done_rs)\n        case (ComposedType(false, ll, lr) :: ls, _) =>\n          annoying(ll :: lr :: ls, done_ls, rs, done_rs)\n        case (p @ ProxyType(und) :: ls, _) => annoying(und :: ls, done_ls, rs, done_rs)\n        case (_, p @ ProxyType(und) :: rs) => annoying(ls, done_ls, und :: rs, done_rs)\n        // ^ TODO retain the proxy provs wrapping each ConstructedType... for better errors later on?\n        case (n @ NegType(ty) :: ls, _) => annoying(ls, done_ls, ty :: rs, done_rs)\n        case (_, n @ NegType(ty) :: rs) => annoying(ty :: ls, done_ls, rs, done_rs)\n        case (ExtrType(true) :: ls, rs) => () // Bot in the LHS intersection makes the constraint trivial\n        case (ls, ExtrType(false) :: rs) => () // Top in the RHS union makes the constraint trivial\n        case (ExtrType(false) :: ls, rs) => annoying(ls, done_ls, rs, done_rs)\n        case (ls, ExtrType(true) :: rs) => annoying(ls, done_ls, rs, done_rs)\n          \n        // case ((tr @ TypeRef(_, _)) :: ls, rs) => annoying(tr.expand :: ls, done_ls, rs, done_rs)\n        case ((tr @ TypeRef(_, _)) :: ls, rs) => annoying(ls, (done_ls & (tr, pol = true)) getOrElse\n          (return println(s\"OK  $done_ls & $tr  =:=  ${BotType}\")), rs, done_rs)\n        \n        // case (ls, (tr @ TypeRef(_, _)) :: rs) => annoying(ls, done_ls, tr.expand :: rs, done_rs)\n        case (ls, (tr @ TypeRef(_, _)) :: rs) => annoying(ls, done_ls, rs, done_rs | (tr, pol = false) getOrElse\n          (return println(s\"OK  $done_rs & $tr  =:=  ${TopType}\")))\n        \n        /*\n        // This logic is now in `constrainDNF`... and even if we got here,\n        // the new BaseType `&` implementation can now deal with these.\n        case (Without(b: TypeVariable, ns) :: ls, rs) => rec(b, mkRhs(ls).without(ns))\n        case (Without(NegType(b: TypeVariable), ns) :: ls, rs) => rec(b, NegType(mkRhs(ls).without(ns))(noProv))\n        case ((w @ Without(_, _)) :: ls, rs) =>\n          lastWords(s\"`pushPosWithout` should have removed Without type: ${w}\")\n        case (ls, (w @ Without(_, _)) :: rs) =>\n          lastWords(s\"unexpected Without in negative position not at the top level: ${w}\")\n        */\n        \n        case ((l: BaseTypeOrTag) :: ls, rs) => annoying(ls, (done_ls & (l, pol = true))(ctx, etf = true) getOrElse\n          (return println(s\"OK  $done_ls & $l  =:=  ${BotType}\")), rs, done_rs)\n        case (ls, (r: BaseTypeOrTag) :: rs) => annoying(ls, done_ls, rs, done_rs | r getOrElse\n          (return println(s\"OK  $done_rs | $r  =:=  ${TopType}\")))\n          \n        case ((l: RecordType) :: ls, rs) => annoying(ls, done_ls & l, rs, done_rs)\n        case (ls, (r @ RecordType(Nil)) :: rs) => ()\n        case (ls, (r @ RecordType(f :: Nil)) :: rs) => annoying(ls, done_ls, rs, done_rs | f getOrElse\n          (return println(s\"OK  $done_rs | $f  =:=  ${TopType}\")))\n        case (ls, (r @ RecordType(fs)) :: rs) => annoying(ls, done_ls, r.toInter :: rs, done_rs)\n          \n        // TODO statically prevent these cases by refining `annoyingImpl`'s parameter types\n        case (_, (_: PolymorphicType) :: _) | ((_: PolymorphicType) :: _, _) => die\n        case (_, (_: ConstrainedType) :: _) | ((_: ConstrainedType) :: _, _) => die\n          \n        case (Nil, Nil) =>\n          // TODO improve:\n          //    Most of the `rec` calls below will yield ugly errors because we don't maintain\n          //    the original constraining context!\n          (done_ls, done_rs) match {\n            case (LhsRefined(S(Without(b, _)), _, _, _), RhsBot) => rec(b, BotType, true)\n            case (LhsTop, _) | (LhsRefined(N, EmptyColl(), RecordType(Nil), EmptyColl()), _) =>\n              // TODO ^ actually get rid of LhsTop and RhsBot...? (might make constraint solving slower)\n              reportError()\n            case (LhsRefined(_, ts, _, trs), RhsBases(pts, _, _)) if ts.exists(pts.contains) => ()\n            \n            case (LhsRefined(bo, ts, r, trs), _) if trs.nonEmpty =>\n              annoying(trs.valuesIterator.map { tr => tr.expand }.toList,\n                LhsRefined(bo, ts, r, SortedMap.empty), Nil, done_rs)\n            \n            case (_, RhsBases(pts, bf, trs)) if trs.nonEmpty =>\n              annoying(Nil, done_ls, trs.valuesIterator.map(_.expand).toList, RhsBases(pts, bf, SortedMap.empty))\n            \n            case (_, RhsBases(pts, S(L(ov: Overload)), trs)) =>\n              ov.alts.foreach(alt => annoying(Nil, done_ls, Nil, RhsBases(pts, S(L(alt)), trs)))\n            \n            // From this point on, trs should be empty!\n            case (LhsRefined(_, _, _, trs), _) if trs.nonEmpty => die\n            case (_, RhsBases(_, _, trs)) if trs.nonEmpty => die\n            \n            case (_, RhsBot) | (_, RhsBases(Nil, N, _)) =>\n              reportError()\n            \n            case (LhsRefined(S(f0@FunctionType(l0, r0)), ts, r, _)\n                , RhsBases(_, S(L(f1@FunctionType(l1, r1))), _)) =>\n              rec(f0, f1, true)\n            case (LhsRefined(S(f: FunctionType), ts, r, trs), RhsBases(pts, _, _)) =>\n              annoying(Nil, LhsRefined(N, ts, r, trs), Nil, done_rs)\n            \n            // * Note: We could avoid the need for this rule by adding `Eql` to *all* class tag parent sets,\n            // *  but I chose not to for performance reasons (better keep parent sets small).\n            case (LhsRefined(S(ct: ClassTag), ts, r, trs0),\n                  RhsBases(ots, _, trs)) if EqlTag in ots =>\n              println(s\"OK ~ magic Eql ~\")\n            \n            // * These deal with the implicit Eql type member in primitive types.\n            // * (Originally I added this to all such types,\n            // *  but it requires not expanding primitive type refs,\n            // *  which causes regressions in simplification\n            // *  because we don't yet simplify unexpanded type refs...)\n            case (LhsRefined(S(ct @ ClassTag(lit: Lit, _)), ts, r, trs0),\n                  RhsBases(ots, S(R(RhsField(Var(\"Eql#A\"), fldTy))), trs)) =>\n              lit match {\n                case _: IntLit |  _: DecLit => rec(fldTy.lb.getOrElse(TopType), DecType, false)\n                case _: StrLit => rec(fldTy.lb.getOrElse(TopType), StrType, false)\n                case _: UnitLit => reportError()\n              }\n              \n            // * This deals with the implicit Eql type member for user-defined classes.\n            case (LhsRefined(S(ClassTag(Var(nme), _)), ts, r, trs0),\n                  RhsBases(ots, S(R(RhsField(fldNme, fldTy))), trs))\n            if ctx.tyDefs2.contains(nme) => if (newDefs && nme =/= \"Eql\" && fldNme.name === \"Eql#A\") {\n              val info = ctx.tyDefs2(nme)\n              if (info.typedParams.isEmpty && !primitiveTypes.contains(nme))\n                // TODO shoudl actually reject all non-data classes...\n                err(msg\"${info.decl.kind.str.capitalize} '${info.decl.name\n                  }' does not support equality comparison because it does not have a parameter list\", prov.loco)\n              info.typedParams\n                .getOrElse(Nil) // FIXME?... prim type\n                .foreach { p =>\n                  val fty = lookupField(() => done_ls.toType(sort = true), S(nme), r.fields.toMap.get, ts, p._1)\n                  rec(fldTy.lb.getOrElse(die), RecordType(p._1 -> TypeRef(TypeName(\"Eql\"),\n                      fty.ub // FIXME check mutable?\n                      :: Nil\n                    )(provTODO).toUpper(provTODO) :: Nil)(provTODO), false)\n                }\n            } else {\n              val fty = lookupField(() => done_ls.toType(sort = true), S(nme), r.fields.toMap.get, ts, fldNme)\n              rec(fty.ub, fldTy.ub, false)\n              recLb(fldTy, fty)\n            }\n            case (l @ LhsRefined(S(pt: ClassTag), ts, r, trs), RhsBases(pts, bf, trs2)) =>\n              println(s\"class checking $pt $pts\")\n              if (pts.exists(p => (p.id === pt.id) || l.allTags.contains(p.id)))\n                println(s\"OK  $pt  <:  ${pts.mkString(\" | \")}\")\n              // else f.fold(reportError())(f => annoying(Nil, done_ls, Nil, f))\n              else annoying(Nil, LhsRefined(N, ts, r, trs), Nil, RhsBases(Nil, bf, trs2))\n            case (lr @ LhsRefined(bo, ts, r, _), rf @ RhsField(n, t2)) =>\n              // Reuse the case implemented below:  (this shortcut adds a few more annoying calls in stats)\n              annoying(Nil, lr, Nil, RhsBases(Nil, S(R(rf)), SortedMap.empty))\n            case (LhsRefined(N, ts, r, _), RhsBases(ots, S(R(RhsField(fldNme, fldTy))), trs)) if newDefs =>\n              val fty = lookupField(() => done_ls.toType(sort = true), N, r.fields.toMap.get, ts, fldNme)\n              rec(fty.ub, fldTy.ub, false)\n              recLb(fldTy, fty)\n            case (LhsRefined(bo, ts, r, _), RhsBases(ots, S(R(RhsField(n, t2))), trs)) =>\n              // TODO simplify - merge with above?\n              r.fields.find(_._1 === n) match {\n                case S(nt1) =>\n                  recLb(t2, nt1._2)\n                  rec(nt1._2.ub, t2.ub, false)\n                case N =>\n                  bo match {\n                    case S(Without(b, ns)) =>\n                      if (ns(n)) rec(b, RhsBases(ots, N, trs).toType(), true)\n                      else rec(b, done_rs.toType(), true)\n                    case _ => reportError()\n                  }\n              }\n            case (LhsRefined(N, ts, r, trs), RhsBases(pts, N, trs2))  =>\n              println(s\"Tag checking ${ts} ${pts}\")\n              if (pts.exists(p => ts.iterator.flatMap {\n                case TraitTag(n, h) => n :: h.toList.map(n => Var(n.name))\n                case _ => Nil\n              }.contains(p.id)))\n                println(s\"OK $ts <: $pts\")\n              else reportError()\n            case (LhsRefined(N, ts, r, _), RhsBases(pts, S(L(_: FunctionType | _: ArrayBase)), _)) =>\n              reportError()\n            case (LhsRefined(S(b: TupleType), ts, r, _), RhsBases(pts, S(L(ty: TupleType)), _))\n              if b.fields.size === ty.fields.size =>\n                (b.fields.unzip._2 lazyZip ty.fields.unzip._2).foreach { (l, r) =>\n                  rec(l.ub, r.ub, false)\n                  recLb(r, l)\n                }\n            case (LhsRefined(S(b: ArrayBase), ts, r, _), RhsBases(pts, S(L(ar: ArrayType)), _)) =>\n              recLb(ar.inner, b.inner)\n              rec(b.inner.ub, ar.inner.ub, false)\n            case (LhsRefined(S(b: ArrayBase), ts, r, _), _) => reportError()\n            case (LhsRefined(S(ov: Overload), ts, r, trs), RhsBases(_, S(L(f: FunctionType)), _)) if noApproximateOverload =>\n              TupleSetConstraints.mk(ov, f) match {\n                case S(tsc) =>\n                  if (tsc.tvs.nonEmpty) {\n                    tsc.tvs.mapValuesIter(_.unwrapProxies).zipWithIndex.flatMap {\n                      case ((true, tv: TV), i) => tv.lowerBounds.iterator.map((_,tv,i,true))\n                      case ((false, tv: TV), i) => tv.upperBounds.iterator.map((_,tv,i,false))\n                      case _ => Nil\n                    }.find {\n                      case (b,_,i,_) =>\n                        tsc.updateImpl(i,b)\n                        tsc.constraints.isEmpty\n                    }.foreach {\n                      case (b,tv,_,p) => if (p) rec(b,tv,false) else rec(tv,b,false)\n                    }\n                    if (tsc.constraints.sizeCompare(1) === 0) {\n                      tsc.tvs.values.map(_.unwrapProxies).foreach {\n                        case tv: TV => tv.tsc.remove(tsc)\n                        case _ => ()\n                      }\n                      tsc.constraints.head.iterator.zip(tsc.tvs).foreach {\n                        case (c, (pol, t)) =>\n                          if (!pol) rec(c, t, false)\n                          if (pol) rec(t, c, false)\n                      }\n                    }\n                  }\n                case N => reportError(S(msg\"is not an instance of `${f.expNeg}`\"))\n              }\n            case (LhsRefined(S(ov: Overload), ts, r, trs), _) =>\n              annoying(Nil, LhsRefined(S(ov.approximatePos), ts, r, trs), Nil, done_rs) // TODO remove approx. with ambiguous constraints\n            case (LhsRefined(S(Without(b, ns)), ts, r, _), RhsBases(pts, N | S(L(_)), _)) =>\n              rec(b, done_rs.toType(), true)\n            case (_, RhsBases(pts, S(L(Without(base, ns))), _)) =>\n              // rec((pts.map(_.neg()).foldLeft(done_ls.toType())(_ & _)).without(ns), base)\n              // ^ This less efficient version creates a slightly different error message\n              //    (see test in Annoying.mls)\n              annoying(pts.map(_.neg()), done_ls, base :: Nil, RhsBot)\n          }\n          \n      }\n    }()\n    \n    /** Helper function to constrain Field lower bounds. */\n    def recLb(lhs: FieldType, rhs: FieldType)\n      (implicit raise: Raise, cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows): Unit = {\n        (lhs.lb, rhs.lb) match {\n          case (Some(l), Some(r)) => rec(l, r, false)\n          case (Some(l), None) =>\n            println(s\"RHS not mutable! in $lhs <- $rhs\")\n            reportError(\n              if (lhs.prov.loco.isEmpty || rhs.prov.loco.isEmpty)\n                S(msg\"cannot be reassigned\")\n              else S(msg\"is not mutable\")\n            )(\n              (rhs.ub.withProv(rhs.prov) :: l.withProv(lhs.prov) :: Nil, l.withProv(noProv) :: Nil), ctx\n            )\n          case (None, Some(_)) | (None, None) => ()\n        }\n      }\n    \n    /** Extrudes and also checks type variable avoidance (which widens skolems to top/bot)\n      * did not introduce bad bounds. To do this, we reconstrain the bounds of all new variables.\n      * This is a bit of a sledgehammer approach that could be improved – it will duplicate TV bounds!\n      * For instance, it would be better to accumulate new TVs' future bounds first\n      * and add them by constraining later. */\n    def extrudeAndCheck(ty: SimpleType, lowerLvl: Int, pol: Boolean, upperLvl: Level, reason: Ls[Ls[ST]])\n          (implicit raise: Raise, cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows)\n          : SimpleType =\n    {\n      val originalVars = ty.getVars\n      val res = extrude(ty, lowerLvl, pol, upperLvl)(ctx, MutMap.empty, MutSortMap.empty, reason)\n      val newVars = res.getVars -- originalVars\n      if (newVars.nonEmpty) trace(s\"RECONSTRAINING TVs\") {\n        newVars.foreach {\n          case tv @ AssignedVariable(bnd) =>\n            println(s\"No need to reconstrain assigned $tv\")\n            // * This is unlikely to happen, but it should be fine anyway,\n            // * as all bounds of vars being assigned are checked against the assigned type.\n            ()\n          case tv =>\n            println(s\"Reconstraining $tv\")\n            if (tv.level > lowerLvl) tv.lowerBounds.foreach(lb =>\n              // * Q: is it fine to constrain with the current ctx's level?\n              tv.upperBounds.foreach(ub => rec(lb, ub, false)))\n        }\n      }()\n      res\n    }\n    \n    /** `cctx` accumulates the types that have been compared up to this point;\n      * it is reset when going through a nested position (sameLevel = false).\n      * `prevCctxs` accumulate the previous `cctx`s that led to this constraint.\n      * Currently `prevCctxs` is just used to show possibly-helpful type annotation\n      * locations upon skolem extrusion. */\n    def rec(lhs: SimpleType, rhs: SimpleType, sameLevel: Bool)\n          (implicit raise: Raise, cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows)\n          : Unit =\n    {\n      constrainCalls += 1\n      val lhs_rhs = lhs -> rhs\n      stack.push(lhs_rhs)\n      consumeFuel()\n      // Thread.sleep(10)  // useful for debugging constraint-solving explosions piped to stdout\n      recImpl(lhs, rhs)(raise,\n        if (sameLevel)\n          (if (cctx._1.headOption.exists(_ is lhs)) cctx._1 else lhs :: cctx._1)\n          ->\n          (if (cctx._2.headOption.exists(_ is rhs)) cctx._2 else rhs :: cctx._2)\n        else (lhs :: Nil) -> (rhs :: Nil),\n        if (sameLevel || prevCctxs.isEmpty) prevCctxs // * See [note:2] below\n        else cctx :: prevCctxs,\n        ctx,\n        if (sameLevel) shadows else shadows.copy(current = Set.empty)\n      )\n      stack.pop()\n      ()\n    }\n    \n    def recImpl(lhs: SimpleType, rhs: SimpleType)\n          (implicit raise: Raise, cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows)\n          : Unit =\n    // trace(s\"$lvl. C $lhs <! $rhs\") {\n    // trace(s\"$lvl. C $lhs <! $rhs    (${cache.size})\") {\n    trace(s\"$lvl. C $lhs <! $rhs    (${shadows.size})\") {\n    // trace(s\"$lvl. C $lhs <! $rhs  ${lhs.getClass.getSimpleName}  ${rhs.getClass.getSimpleName}\") {\n      \n      // shadows.previous.foreach { sh =>\n      //   println(s\">> $sh   ${sh.hashCode}\")\n      // }\n      \n      // println(s\"[[ ${cctx._1.map(_.prov).mkString(\", \")}  <<  ${cctx._2.map(_.prov).mkString(\", \")} ]]\")\n      // println(s\"{{ ${cache.mkString(\", \")} }}\")\n      \n      // if (!lhs.mentionsTypeBounds && lhs === rhs) return ()\n      // * ^ The check above is mostly good enough but it leads to slightly worse simplified type outputs\n      // *    in corner cases.\n      // * v The check below is a bit more precise but it incurs a lot more subtyping checks,\n      // *    especially in complex comparisons like those done in the `ExprProb` test family.\n      // *    Therefore this subtyping check may not be worth it.\n      // *    In any case, we make it more lightweight by not traversing type variables\n      // *    and not using a subtyping cache (cf. `CompareRecTypes = false`).\n      if ({ implicit val ctr: CompareRecTypes = false; lhs <:< rhs })\n        println(s\"Already a subtype by <:<\")\n      \n      // println(s\"  where ${FunctionType(lhs, rhs)(primProv).showBounds}\")\n      else {\n        val lhs_rhs = lhs -> rhs\n        (lhs_rhs match {\n          case (_: ProvType, _) | (_, _: ProvType) => shadows\n          // * Note: contrary to Simple-sub, we do have to remember subtyping tests performed\n          // *    between things that are not syntactically type variables or type references.\n          // *  Indeed, due to the normalization of unions and intersections in the wrong polarity,\n          // *    cycles in regular trees may only ever go through unions or intersections,\n          // *    and not plain type variables.\n          case _ =>\n            if (!noRecursiveTypes && cache(lhs_rhs)) return println(s\"Cached!\")\n            val shadow = lhs.shadow -> rhs.shadow\n            // println(s\"SH: $shadow\")\n            // println(s\"ALLSH: ${shadows.iterator.map(s => s._1 + \"<:\" + s._2).mkString(\", \")}\")\n            \n            if (shadows.current.contains(lhs_rhs))\n              return println(s\"Spurious cycle involving $lhs_rhs\") // * Spurious cycle, like alpha <: beta <: alpha\n            \n            else if (!noCycleCheck && shadows.previous.contains(shadow)\n              && !shadows.current.contains(shadow)\n            ) {\n              println(s\"SHADOWING DETECTED!\")\n              \n              if (!lhs_rhs.matches{ case (ClassTag(ErrTypeId, _), _) | (_, ClassTag(ErrTypeId, _)) => true })\n                err(msg\"Cyclic-looking constraint while typing ${\n                  prov.desc}; a type annotation may be required\" -> prov.loco :: (\n                    if (!explainErrors)\n                      msg\"Note: use flag `:ex` to see internal error info.\" -> N :: Nil\n                    else\n                      // msg\"this constraint:  ${lhs.expPos}  <:  ${rhs.expNeg}\" -> N ::\n                      // msg\" ... looks like:  ${shadow._1.expPos}  <:  ${shadow._2.expNeg}\" -> N ::\n                      msg\"————————— Additional debugging info: —————————\" -> N ::\n                      msg\"this constraint:  ${lhs.toString}  <:  ${rhs.toString}    ${lhs.getClass.getSimpleName}  ${rhs.getClass.getSimpleName}\" -> N ::\n                      msg\" ... looks like:  ${shadow._1.toString}  <:  ${shadow._2.toString}\" -> N ::\n                      Nil\n                    ))\n              \n              return ()\n            }\n            \n            if (!noRecursiveTypes) cache += lhs_rhs\n            \n            Shadows(shadows.current + lhs_rhs + shadow, // * FIXME this conflation is not quite correct\n              shadows.previous + shadow)\n            \n        }) |> { implicit shadows: Shadows =>\n        lhs_rhs match {\n          case (ExtrType(true), _) => ()\n          case (_, ExtrType(false) | RecordType(Nil)) => ()\n          case (TypeBounds(lb, ub), _) => rec(ub, rhs, true)\n          case (_, TypeBounds(lb, ub)) => rec(lhs, lb, true)\n          case (p @ ProvType(und), _) => rec(und, rhs, true)\n          case (_, p @ ProvType(und)) => rec(lhs, und, true)\n          case (_: TypeTag, _: TypeTag) if lhs === rhs => ()\n          case (NegType(lhs), NegType(rhs)) => rec(rhs, lhs, true)\n          \n          case (ClassTag(Var(nme), _), rt: RecordType) if newDefs && nme.isCapitalized =>\n            val lti = ctx.tyDefs2(nme)\n            rt.fields.foreach {\n              case (fldNme @ Var(\"Eql#A\"), fldTy) =>\n                goToWork(lhs, RecordType(fldNme -> fldTy :: Nil)(noProv))\n              case (fldNme, fldTy) =>\n                val fty = lookupField(() => lhs, S(nme), _ => N, SortedSet.empty, fldNme)\n                rec(fty.ub, fldTy.ub, false)\n                recLb(fldTy, fty)\n            }\n          \n          // * Note: at this point, it could be that a polymorphic type could be distribbed\n          // *  out of `r1`, but this would likely not result in something useful, since the\n          // *  LHS is a normal non-polymorphic function type...\n          case (FunctionType(l0, r0), FunctionType(l1, r1)) =>\n            rec(l1, l0, false)\n            rec(r0, r1, false)\n          \n          case (prim: ClassTag, ot: TypeTag)\n            if prim.parentsST.contains(ot.id) => ()\n            \n          case (tv @ AssignedVariable(lhs), rhs) =>\n            rec(lhs, rhs, true)\n          case (lhs, tv @ AssignedVariable(rhs)) =>\n            rec(lhs, rhs, true)\n            \n            \n          case (lhs: TypeVariable, rhs) if rhs.level <= lhs.level =>\n            println(s\"NEW $lhs UB (${rhs.level})\")\n            val newBound = (cctx._1 ::: cctx._2.reverse).foldRight(rhs)((c, ty) =>\n              if (c.prov is noProv) ty else mkProxy(ty, c.prov))\n            lhs.upperBounds ::= newBound // update the bound\n            if (noApproximateOverload) {\n              lhs.tsc.foreachEntry { (tsc, v) =>\n                v.foreach { i =>\n                  if (!tsc.tvs(i)._1) {\n                    tsc.updateOn(i, rhs)\n                    if (tsc.constraints.isEmpty) reportError()\n                  }\n                }\n              }\n              val u = lhs.tsc.keysIterator.filter(_.constraints.sizeCompare(1)===0).duplicate\n              u._1.foreach { k =>\n                k.tvs.mapValuesIter(_.unwrapProxies).foreach {\n                  case (_,tv: TV) => tv.tsc.remove(k)\n                  case _ => ()\n                }\n              }\n              u._2.foreach { k =>\n                k.constraints.head.iterator.zip(k.tvs).foreach {\n                  case (c, (pol, t)) => if (pol) rec(t, c, false) else rec(c, t, false)\n                }\n              }\n            }\n            lhs.lowerBounds.foreach(rec(_, rhs, true)) // propagate from the bound\n            \n          case (lhs, rhs: TypeVariable) if lhs.level <= rhs.level =>\n            println(s\"NEW $rhs LB (${lhs.level})\")\n            val newBound = (cctx._1 ::: cctx._2.reverse).foldLeft(lhs)((ty, c) =>\n              if (c.prov is noProv) ty else mkProxy(ty, c.prov))\n            rhs.lowerBounds ::= newBound // update the bound\n            if (noApproximateOverload) {\n              rhs.tsc.foreachEntry { (tsc, v) =>\n                v.foreach { i =>\n                  if(tsc.tvs(i)._1) {\n                    tsc.updateOn(i, lhs)\n                    if (tsc.constraints.isEmpty) reportError()\n                  }\n                }\n              }\n              val u = rhs.tsc.keysIterator.filter(_.constraints.sizeCompare(1)===0).duplicate\n              u._1.foreach { k =>\n                k.tvs.mapValuesIter(_.unwrapProxies).foreach {\n                  case (_,tv: TV) => tv.tsc.remove(k)\n                  case _ => ()\n                }\n              }\n              u._2.foreach { k =>\n                k.constraints.head.iterator.zip(k.tvs).foreach {\n                  case (c, (pol, t)) => if (pol) rec(t, c, false) else rec(c, t, false)\n                }\n              }\n            }\n            rhs.upperBounds.foreach(rec(lhs, _, true)) // propagate from the bound\n            \n            \n          case (lhs: TypeVariable, rhs) =>\n            val tv = lhs\n            println(s\"wrong level: ${rhs.level}\")\n            if (constrainedTypes && rhs.level <= lvl) {\n              println(s\"STASHING $tv bound in extr ctx\")\n              val buf = ctx.extrCtx.getOrElseUpdate(tv, Buffer.empty)\n              buf += false -> rhs\n              cache -= lhs -> rhs\n              ()\n            } else {\n              val rhs2 = extrudeAndCheck(rhs, lhs.level, false, MaxLevel,\n                cctx._1 :: prevCctxs.unzip._1 ::: prevCctxs.unzip._2)\n              println(s\"EXTR RHS  ~>  $rhs2  to ${lhs.level}\")\n              println(s\" where ${rhs2.showBounds}\")\n              // println(s\"   and ${rhs.showBounds}\")\n              rec(lhs, rhs2, true)\n            }\n            \n          case (lhs, rhs: TypeVariable) =>\n            val tv = rhs\n            println(s\"wrong level: ${lhs.level}\")\n            if (constrainedTypes && lhs.level <= lvl) {\n              println(s\"STASHING $tv bound in extr ctx\")\n              val buf = ctx.extrCtx.getOrElseUpdate(tv, Buffer.empty)\n              buf += true -> lhs\n              cache -= lhs -> rhs\n              ()\n            } else {\n              val lhs2 = extrudeAndCheck(lhs, rhs.level, true, MaxLevel,\n                cctx._2 :: prevCctxs.unzip._2 ::: prevCctxs.unzip._1)\n              println(s\"EXTR LHS  ~>  $lhs2  to ${rhs.level}\")\n              println(s\" where ${lhs2.showBounds}\")\n              // println(s\"   and ${lhs.showBounds}\")\n              rec(lhs2, rhs, true)\n            }\n            \n            \n          case (TupleType(fs0), TupleType(fs1)) if fs0.size === fs1.size => // TODO generalize (coerce compatible tuples)\n            fs0.lazyZip(fs1).foreach { case ((ln, l), (rn, r)) =>\n              ln.foreach { ln => rn.foreach { rn =>\n                if (ln =/= rn) err(\n                  msg\"Wrong tuple field name: found '${ln.name}' instead of '${rn.name}'\",\n                  lhs.prov.loco // TODO better loco\n              )}}\n              recLb(r, l)\n              rec(l.ub, r.ub, false)\n            }\n          case (t: ArrayBase, a: ArrayType) =>\n            recLb(a.inner, t.inner)\n            rec(t.inner.ub, a.inner.ub, false)\n          case (ComposedType(true, l, r), _) =>\n            rec(l, rhs, true) // Q: really propagate the outerProv here?\n            rec(r, rhs, true)\n          case (_, ComposedType(false, l, r)) =>\n            rec(lhs, l, true) // Q: really propagate the outerProv here?\n            rec(lhs, r, true)\n          case (p @ ProxyType(und), _) => rec(und, rhs, true)\n          case (_, p @ ProxyType(und)) => rec(lhs, und, true)\n          case (_, TupleType(f :: Nil)) if funkyTuples =>\n            rec(lhs, f._2.ub, true) // FIXME actually needs reified coercion! not a true subtyping relationship\n          case (err @ ClassTag(ErrTypeId, _), FunctionType(l1, r1)) =>\n            rec(l1, err, false)\n            rec(err, r1, false)\n          case (FunctionType(l0, r0), err @ ClassTag(ErrTypeId, _)) =>\n            rec(err, l0, false)\n            rec(r0, err, false)\n          case (RecordType(fs0), RecordType(fs1)) =>\n            fs1.foreach { case (n1, t1) =>\n              fs0.find(_._1 === n1).fold {\n                reportError()\n              } { case (n0, t0) =>\n                recLb(t1, t0)\n                rec(t0.ub, t1.ub, false)\n              }\n            }\n          case (tup: TupleType, _: RecordType) =>\n            rec(tup.toRecord, rhs, true) // Q: really support this? means we'd put names into tuple reprs at runtime\n          case (err @ ClassTag(ErrTypeId, _), RecordType(fs1)) =>\n            fs1.foreach(f => rec(err, f._2.ub, false))\n          case (_, RecordType(fs1)) =>\n            goToWork(lhs, rhs)\n          case (RecordType(fs1), err @ ClassTag(ErrTypeId, _)) =>\n            fs1.foreach(f => rec(f._2.ub, err, false))\n            \n          case (tr1: TypeRef, tr2: TypeRef)\n          if tr1.defn.name =/= \"Array\" && tr2.defn.name =/= \"Eql\" =>\n            if (tr1.defn === tr2.defn) {\n              assert(tr1.targs.sizeCompare(tr2.targs) === 0)\n              ctx.tyDefs.get(tr1.defn.name) match {\n                case S(td) =>\n                  val tvv = td.getVariancesOrDefault\n                  td.tparamsargs.unzip._2.lazyZip(tr1.targs).lazyZip(tr2.targs).foreach { (tv, targ1, targ2) =>\n                    val v = tvv(tv)\n                    if (!v.isContravariant) rec(targ1, targ2, false)\n                    if (!v.isCovariant) rec(targ2, targ1, false)\n                  }\n                case N =>\n                  /* \n                  ctx.tyDefs2(tr1.defn.name).complete() match {\n                    case cls: TypedNuCls =>\n                      cls.tparams.map(_._2).lazyZip(tr1.targs).lazyZip(tr2.targs).foreach {\n                        (tv, targ1, targ2) =>\n                          val v = cls.varianceOf(tv)\n                          if (!v.isContravariant) rec(targ1, targ2, false)\n                          if (!v.isCovariant) rec(targ2, targ1, false)\n                      }\n                    // case _ => ???\n                  }\n                  */\n                  ctx.tyDefs2.get(tr1.defn.name) match {\n                    case S(lti) =>\n                      lti.tparams.map(_._2).lazyZip(tr1.targs).lazyZip(tr2.targs).foreach {\n                        (tv, targ1, targ2) =>\n                          val v = lti.varianceOf(tv)\n                          if (!v.isContravariant) rec(targ1, targ2, false)\n                          if (!v.isCovariant) rec(targ2, targ1, false)\n                      }\n                    case N =>\n                      ??? // TODO\n                  }\n              }\n            } else {\n              if (tr1.mayHaveTransitiveSelfType) rec(tr1.expand, tr2.expand, true)\n              else (tr1.mkClsTag, tr2.mkClsTag) match {\n                case (S(tag1), S(tag2)) if !(tag1 <:< tag2) =>\n                  reportError()\n                case _ =>\n                  rec(tr1.expand, tr2.expand, true)\n              }\n            }\n          case (tr: TypeRef, _) => rec(tr.expand, rhs, true)\n          case (err @ ClassTag(ErrTypeId, _), tr: TypeRef) =>\n            // rec(tr.copy(targs = tr.targs.map(_ => err))(noProv), tr, true)\n            // * ^ Nicely propagates more errors to the result,\n            // * but can incur vast amounts of unnecessary constraining in the context of recursive types!\n            ()\n          case (_, tr: TypeRef) =>\n            rec(lhs, tr.expand, true)\n          \n          case (ClassTag(ErrTypeId, _), _) => ()\n          case (_, ClassTag(ErrTypeId, _)) => ()\n          case (_, w @ Without(b, ns)) => rec(lhs.without(ns), b, true)\n          case (_, n @ NegType(w @ Without(b, ns))) =>\n            rec(Without(lhs, ns)(w.prov), NegType(b)(n.prov), true) // this is weird... TODO check sound\n            \n            \n          case (_, poly: PolymorphicType) =>\n            val oldCtx = ctx\n            ctx.nextLevel { implicit ctx =>\n              val rigid = poly.rigidify\n              println(s\"BUMP TO LEVEL ${lvl}  -->  $rigid\")\n              println(s\"where ${rigid.showBounds}\")\n              val res = rec(lhs, rigid, true)\n              unstash(oldCtx)\n              res\n            }\n            \n          case (AliasOf(PolymorphicType(plvl, bod)), _) if bod.level <= plvl =>\n            rec(bod, rhs, true)\n            \n          case (_, PolyFunction(newRhs)) if distributeForalls =>\n            println(s\"DISTRIB-R  ~>  $newRhs\")\n            rec(lhs, newRhs, true)\n            \n          // * Simple case when the parameter type vars don't need to be split\n          case (AliasOf(PolymorphicType(plvl, AliasOf(FunctionType(param, bod)))), _)\n          if distributeForalls\n          && param.level <= plvl\n          && bod.level > plvl =>\n            val newLhs = FunctionType(param, PolymorphicType(plvl, bod))(rhs.prov)\n            println(s\"DISTRIB-L  ~>  $newLhs\")\n            rec(newLhs, rhs, true)\n            \n          // * Difficult case: split off type parameters that are quantified in body but NOT in param\n          case (SplittablePolyFun(newLhs), _) if distributeForalls =>\n            println(s\"DISTRIB-L'  ~>  $newLhs\")\n            rec(newLhs, rhs, true)\n            \n          case (poly: PolymorphicType, _) =>\n            // TODO Here it might actually be better to try and put poly into a TV if the RHS contains one\n            //    ^ Note: similar remark applies inside constrainDNF\n            \n            // * [note:1] This assertion seems to hold most of the time,\n            // *  with notable exceptions occurring in QML existential encoding tests\n            // assert(lvl >= rhs.level)\n            \n            // * Note: we instantiate `poly` at the current context's polymorphic level.\n            // * This level can either be the current typing level,\n            // * at which the type variables obtained from cosntraining are expected to be;\n            // * or it can be a \"bumped-up\" level locally introdcued\n            // * when comparing against a polymorphic RHS signature that needed to be rigidified\n            // * – in this case, the higher level is meant to allow further instantiations to match\n            // * the rigid type variables without extrusion,\n            // * while preventing the rigid variables from leaking out.\n            \n            // * [note:2] Hack (\"heuristic\"): we only start remembering `prevCctxs`\n            // * after going through at least one instantiation.\n            // * This is to filter out locations that were unlikely to cause\n            // * any skolem extrusion down the line.\n            // *  – indeed, skolem extrusions are often caused by premature instantiation.\n            (if (prevCctxs.isEmpty) (Nil -> Nil) :: Nil else prevCctxs) |> {\n              implicit prevCctxs => rec(poly.instantiate, rhs, true)\n            }\n            \n          case (ConstrainedType(cs, bod), _) =>\n            trace(s\"DISCHARGE CONSTRAINTS\") {\n              cs.foreach { case (lb, ub) => \n               rec(lb, ub, false)\n              }\n            }()\n            rec(bod, rhs, true)\n          case (_, ConstrainedType(cs, bod)) => ??? // TODO?\n          case (_, ComposedType(true, l, r)) =>\n            goToWork(lhs, rhs)\n          case (ComposedType(false, l, r), _) =>\n            goToWork(lhs, rhs)\n          case (ov: Overload, _) =>\n            // * This is a large approximation\n            // * TODO: remove approx. through use of ambiguous constraints\n            rec(ov.approximatePos, rhs, true)\n          case (_: NegType | _: Without, _) | (_, _: NegType | _: Without) =>\n            goToWork(lhs, rhs)\n          case (_: ClassTag | _: TraitTag, _: TraitTag) =>\n            goToWork(lhs, rhs)\n          case _ => reportError()\n      }}\n    }}()\n    \n    def reportError(failureOpt: Opt[Message] = N)(implicit cctx: ConCtx, ctx: Ctx): Unit = {\n      val lhs = cctx._1.head\n      val rhs = cctx._2.head\n      \n      println(s\"CONSTRAINT FAILURE: $lhs <: $rhs\")\n      // println(s\"CTX: ${cctx.map(_.map(lr => s\"${lr._1} <: ${lr._2} [${lr._1.prov}] [${lr._2.prov}]\"))}\")\n      \n      def doesntMatch(ty: SimpleType) = msg\"does not match type `${ty.expNeg}`\"\n      def doesntHaveField(n: Str) = msg\"does not have field '$n'\"\n      \n      val lhsChain: List[ST] = cctx._1\n      val rhsChain: List[ST] = cctx._2\n      \n      // The first located provenance coming from the left\n      val lhsProv = lhsChain.iterator\n        .filterNot(_.prov.isOrigin)\n        .find(_.prov.loco.isDefined)\n        .map(_.prov).getOrElse(lhs.prov)\n      \n      // The first located provenance coming from the right\n      val rhsProv = rhsChain.iterator\n        .filterNot(_.prov.isOrigin)\n        .find(_.prov.loco.isDefined)\n        .map(_.prov).getOrElse(rhs.prov)\n      \n      // The last located provenance coming from the right (this is a bit arbitrary)\n      val rhsProv2 = rhsChain.reverseIterator\n        .filterNot(_.prov.isOrigin)\n        .find(_.prov.loco.isDefined)\n        .map(_.prov).getOrElse(rhs.prov)\n      \n      val relevantFailures = lhsChain.collect {\n        case st\n          if st.prov.loco =/= lhsProv.loco\n          && st.prov.loco.exists(ll => prov.loco.forall(pl => (ll touches pl) || (pl covers ll)))\n        => st\n      }\n      val tighestRelevantFailure = relevantFailures.headOption\n      \n      val shownLocos = MutSet.empty[Loc]\n      def show(loco: Opt[Loc]): Opt[Loc] =\n        loco.tap(_.foreach(shownLocos.+=))\n      \n      val originProvList = (lhsChain.headOption ++ rhsChain.lastOption).iterator\n        .map(_.prov).collect {\n            case tp @ TypeProvenance(loco, desc, S(nme), _) if loco.isDefined => nme -> tp\n          }\n        .toList.distinctBy(_._2.loco)\n      \n      def printProv(prov: TP): Message =\n        if (prov.isType) msg\"type\"\n        else msg\"${prov.desc} of type\"\n      \n      \n      // * Accumulate messages showing possibly-helpful type annotations.\n      def getPossibleAnnots(cctxs: Ls[Ls[ST]]): Ls[Message -> Opt[Loc]] = {\n        val suggested = MutSet.empty[Loc]\n        val removed = MutSet.empty[Loc]\n        def go(cctxs: Ls[Ls[ST]]): Ls[Message -> Opt[Loc]] = cctxs match {\n          case reason :: reasons =>\n            val possible = reason.iterator.map(_.prov).collect {\n              case p @ TypeProvenance(loco @ S(loc), desc, _, _)\n                if !suggested.contains(loc)\n                && !p.isType\n                && !suggested.exists(loc covers _)\n              =>\n                suggested.foreach(loc2 => if (loc2 covers loc) removed += loc2)\n                suggested.add(loc)\n                msg\"• this ${desc}:\" -> loco\n            }.toList\n            possible ::: go(reasons)\n          case Nil => Nil\n        }\n        go(cctxs).filterNot(_._2.exists(removed))\n      }\n      \n      def mk_constraintProvenanceHints = rhsProv.loco match {\n        case S(rhsProv_loc) if !prov.loco.contains(rhsProv_loc) && !shownLocos(rhsProv_loc) =>\n          msg\"Note: constraint arises from ${rhsProv.desc}:\" -> show(rhsProv.loco) :: (\n            rhsProv2.loco match {\n              case S(rhsProv2_loc)\n                if rhsProv2_loc =/= rhsProv_loc\n                && !prov.loco.contains(rhsProv2_loc)\n                && !lhsProv.loco.contains(rhsProv2_loc)\n                && !shownLocos(rhsProv2_loc)\n                => msg\"from ${rhsProv2.desc}:\" -> show(rhsProv2.loco) :: Nil\n              case _ => Nil\n            })\n        case _ => Nil\n      }\n      \n      \n      val lhsBase = lhs.typeBase\n      def lhsIsPlain = lhsBase matches {\n        case _: FunctionType | _: RecordType | _: TypeTag | _: TupleType\n           | _: TypeRef | _: ExtrType => true\n      }\n      \n      val failure = failureOpt.getOrElse((lhsBase, rhs.unwrapProvs) match {\n        case lhs_rhs @ ((_: Extruded, _) | (_, _: Extruded)) =>\n          val (mainExtr, extr1, extr2, reason) = lhs_rhs match {\n            case (extr: Extruded, extr2: Extruded)\n              =>\n              (extr, S(extr), S(extr2), extr.reason ++ extr2.reason)\n              // * ^ Note: I expect extr.reason and extr2.reason to have the same size.\n              // * Interleave them for more natural reporting order?\n            case (extr: Extruded, _) => (extr, S(extr), N, extr.reason)\n            case (_, extr: Extruded) => (extr, N, S(extr), extr.reason)\n            case _ => die\n          }\n          val possibleAnnots = getPossibleAnnots(reason)\n          val e1loco = show(lhsProv.loco).orElse(show(mainExtr.underlying.prov.loco))\n            .orElse(show(mainExtr.underlying.id.prov.loco))\n          val msgs = msg\"Type error in ${prov.desc}\" -> show(prov.loco) ::\n            msg\"type variable `${mainExtr.underlying.expPos}` leaks out of its scope\" ->\n              e1loco :: (extr2 match {\n                case S(extr2) =>\n                  val e2loco = show(rhsProv.loco).orElse(show(extr2.underlying.prov.loco))\n                    .orElse(show(extr2.underlying.id.prov.loco))\n                  if (extr1.isDefined && e2loco =/= e1loco)\n                    msg\"back into type variable `${extr2.underlying.expNeg}`\" -> e2loco :: Nil\n                  else Nil\n                case N =>\n                  msg\"into ${printProv(rhsProv)} `${rhs.expNeg}`\" -> show(rhsProv.loco) :: Nil\n              }) ::: (\n                if (possibleAnnots.nonEmpty)\n                  msg\"adding a type annotation to any of the following terms may help resolve the problem\" -> N ::\n                    possibleAnnots\n                else Nil\n              ) ::: (\n                rhsProv2.loco match {\n                  case S(rhsProv2_loc)\n                    if !rhsProv.loco.contains(rhsProv2_loc)\n                    && !prov.loco.contains(rhsProv2_loc)\n                    && !lhsProv.loco.contains(rhsProv2_loc)\n                    && !shownLocos(rhsProv2_loc)\n                    => msg\"Note: constraint arises from ${rhsProv2.desc}:\" -> show(rhsProv2.loco) :: Nil\n                  case _ => Nil\n                }\n              )\n          return raise(ErrorReport(msgs ::: mk_constraintProvenanceHints, newDefs))\n        case (_: TV | _: ProxyType, _) => doesntMatch(rhs)\n        case (RecordType(fs0), RecordType(fs1)) =>\n          (fs1.map(_._1).toSet -- fs0.map(_._1).toSet)\n            .headOption.fold(doesntMatch(rhs)) { n1 => doesntHaveField(n1.name) }\n        case (lunw, obj: ObjectTag)\n          if obj.id.isInstanceOf[Var]\n          => msg\"is not an instance of type `${\n              if (primitiveTypes(obj.id.idStr)) obj.id.idStr else obj.id.idStr.capitalize}`\"\n        case (lunw, obj: TypeRef)\n          => msg\"is not an instance of `${obj.expNeg}`\"\n        case (lunw, TupleType(fs))\n          if !lunw.isInstanceOf[TupleType] => msg\"is not a ${fs.size.toString}-element tuple\"\n        case (lunw, FunctionType(_, _))\n          if !lunw.isInstanceOf[FunctionType] => msg\"is not a function\"\n        case (lunw, RecordType((n, _) :: Nil))\n          if !lunw.isInstanceOf[RecordType] => doesntHaveField(n.name)\n        case (lunw, RecordType(fs @ (_ :: _)))\n          if lhsIsPlain && !lunw.isInstanceOf[RecordType] =>\n            msg\"is not a record (expected a record with field${\n              if (fs.sizeCompare(1) > 0) \"s\" else \"\"}: ${fs.map(_._1.name).mkString(\", \")})\"\n        case (lunw, RecordType(fs @ (_ :: _))) =>\n          msg\"does not have all required fields ${fs.map(\"'\" + _._1.name + \"'\").mkString(\", \")}\"\n        case _ => doesntMatch(rhs)\n      })\n      \n      \n      val mismatchMessage =\n        msg\"Type mismatch in ${prov.desc}:\" -> show(prov.loco) :: (\n          msg\"${printProv(lhsProv)} `${lhs.expPos}` $failure\"\n        ) -> (if (lhsProv.loco === prov.loco) N else show(lhsProv.loco)) :: Nil\n      \n      val flowHint = \n        tighestRelevantFailure.map { l =>\n          val expTyMsg = msg\" with expected type `${rhs.expNeg}`\"\n          msg\"but it flows into ${l.prov.desc}$expTyMsg\" -> show(l.prov.loco) :: Nil\n        }.toList.flatten\n      \n      val constraintProvenanceHints = mk_constraintProvenanceHints\n      \n      var first = true\n      val originProvHints = originProvList.collect {\n        case (nme, l) if l.loco.exists(!shownLocos.contains(_)) =>\n          val msgHead =\n            if (first)\n                  msg\"Note: ${l.desc} $nme\"\n            else  msg\"      ${l.desc} $nme\"\n          first = false\n          msg\"${msgHead} is defined at:\" -> l.loco \n      }\n      \n      val detailedContext =\n        if (explainErrors)\n          msg\"========= Additional explanations below =========\" -> N ::\n          lhsChain.flatMap { lhs =>\n            if (dbg) msg\"[info] LHS >> ${lhs.prov.toString} : ${lhs.expPos}\" -> lhs.prov.loco :: Nil\n            else msg\"[info] flowing from ${printProv(lhs.prov)} `${lhs.expPos}`\" -> lhs.prov.loco :: Nil\n          } ::: rhsChain.reverse.flatMap { rhs =>\n            if (dbg) msg\"[info] RHS << ${rhs.prov.toString} : ${rhs.expNeg}\" -> rhs.prov.loco :: Nil\n            else msg\"[info] flowing into ${printProv(rhs.prov)} `${rhs.expNeg}`\" -> rhs.prov.loco :: Nil\n          }\n        else Nil\n      \n      val msgs = Ls[Ls[Message -> Opt[Loc]]](\n        mismatchMessage,\n        flowHint,\n        constraintProvenanceHints,\n        originProvHints,\n        detailedContext,\n      ).flatten\n      \n      raise(ErrorReport(msgs, newDefs))\n    }\n    \n    rec(lhs, rhs, true)(raise, Nil -> Nil, Nil, outerCtx, shadows)\n  }}\n  \n  \n  \n  def subsume(ty_sch: ST, sign: ST)\n      (implicit ctx: Ctx, raise: Raise, prov: TypeProvenance): Unit = {\n    println(s\"CHECKING SUBSUMPTION...\")\n    var errCnt = 0\n    constrain(ty_sch, sign)({ err =>\n      errCnt += 1\n      if (errCnt > maxSuccessiveErrReports) {\n        // * Silence further errors\n        if (showAllErrors) notifyMoreErrors(\"signature-checking\", prov)\n        return\n      }\n      else if (showAllErrors || errCnt === 1) raise(err)\n    }, prov, ctx, Shadows.empty)\n  }\n  \n  \n  \n  /** Copies a type up to its type variables of wrong level (and their extruded bounds),\n    * meaning those non-locally-quantified type variables whose level is strictly greater than `lowerLvl`.\n    * Parameter `upperLvl` is used to track above which level we DON'T want to extrude variables,\n    * as we may be traversing types that are quantified by polymorphic types in the process of being copied.\n    * `upperLvl` tracks the lowest such current quantification level. */\n  private final\n  def extrude(ty: SimpleType, lowerLvl: Int, pol: Boolean, upperLvl: Level)\n        (implicit ctx: Ctx, cache: MutMap[TypeVarOrRigidVar->Bool, TypeVarOrRigidVar], cache2: MutSortMap[TraitTag, TraitTag], reason: Ls[Ls[ST]])\n        : SimpleType =\n  // (trace(s\"EXTR[${printPol(S(pol))}] $ty || $lowerLvl .. $upperLvl  ${ty.level} ${ty.level <= lowerLvl}\"){\n    if (ty.level <= lowerLvl) ty else ty match {\n      case t @ TypeBounds(lb, ub) => if (pol) extrude(ub, lowerLvl, true, upperLvl) else extrude(lb, lowerLvl, false, upperLvl)\n      case t @ FunctionType(l, r) => FunctionType(extrude(l, lowerLvl, !pol, upperLvl), extrude(r, lowerLvl, pol, upperLvl))(t.prov)\n      case t @ ComposedType(p, l, r) => ComposedType(p, extrude(l, lowerLvl, pol, upperLvl), extrude(r, lowerLvl, pol, upperLvl))(t.prov)\n      case t @ RecordType(fs) =>\n        RecordType(fs.mapValues(_.update(extrude(_, lowerLvl, !pol, upperLvl), extrude(_, lowerLvl, pol, upperLvl))))(t.prov)\n      case t @ TupleType(fs) =>\n        TupleType(fs.mapValues(_.update(extrude(_, lowerLvl, !pol, upperLvl), extrude(_, lowerLvl, pol, upperLvl))))(t.prov)\n      case t @ ArrayType(ar) =>\n        ArrayType(ar.update(extrude(_, lowerLvl, !pol, upperLvl), extrude(_, lowerLvl, pol, upperLvl)))(t.prov)\n      case w @ Without(b, ns) => Without(extrude(b, lowerLvl, pol, upperLvl), ns)(w.prov)\n      case tv @ AssignedVariable(ty) =>\n        cache.getOrElse(tv -> true, {\n          val nv = freshVar(tv.prov, S(tv), tv.nameHint)(lowerLvl)\n          cache += tv -> true -> nv\n          val tyPos = extrude(ty, lowerLvl, true, upperLvl)\n          val tyNeg = extrude(ty, lowerLvl, false, upperLvl)\n          if (tyPos === tyNeg)\n            nv.assignedTo = S(tyPos)\n          else {\n            assert(nv.lowerBounds.isEmpty)\n            assert(nv.upperBounds.isEmpty)\n            nv.lowerBounds = tyPos :: Nil\n            nv.upperBounds = tyNeg :: Nil\n          }\n          nv\n        })\n      case tv: TypeVariable if tv.level > upperLvl =>\n        assert(!cache.contains(tv -> false), (tv, cache))\n        // * If the TV's level is strictly greater than `upperLvl`,\n        // *  it means the TV is quantified by a type being copied,\n        // *  so all we need to do is copy this TV along (it is not extruded).\n        // * We pick `tv -> true` (and not `tv -> false`) arbitrarily.\n        if (tv.lowerBounds.isEmpty && tv.upperBounds.isEmpty) tv\n        else cache.getOrElse(tv -> true, {\n          val nv = freshVar(tv.prov, S(tv), tv.nameHint)(tv.level)\n          cache += tv -> true -> nv\n          nv.lowerBounds = tv.lowerBounds.map(extrude(_, lowerLvl, true, upperLvl))\n          nv.upperBounds = tv.upperBounds.map(extrude(_, lowerLvl, false, upperLvl))\n          nv\n        })\n      case t @ SpliceType(fs) => \n        t.updateElems(extrude(_, lowerLvl, pol, upperLvl), extrude(_, lowerLvl, !pol, upperLvl), extrude(_, lowerLvl, pol, upperLvl), t.prov)\n      case tv: TypeVariable => cache.getOrElse(tv -> pol, {\n        val nv = freshVar(tv.prov, S(tv), tv.nameHint)(lowerLvl)\n        cache += tv -> pol -> nv\n        if (pol) {\n          tv.upperBounds ::= nv\n          nv.lowerBounds = tv.lowerBounds.map(extrude(_, lowerLvl, pol, upperLvl))\n        } else {\n          tv.lowerBounds ::= nv\n          nv.upperBounds = tv.upperBounds.map(extrude(_, lowerLvl, pol, upperLvl))\n        }\n        nv\n      })\n      case n @ NegType(neg) => NegType(extrude(neg, lowerLvl, !pol, upperLvl))(n.prov)\n      case e @ ExtrType(_) => e\n      case p @ ProvType(und) => ProvType(extrude(und, lowerLvl, pol, upperLvl))(p.prov)\n      case p @ ProxyType(und) => extrude(und, lowerLvl, pol, upperLvl)\n      case tt @ SkolemTag(id) =>\n        if (tt.level > upperLvl) {\n          extrude(id, lowerLvl, pol, upperLvl) match {\n            case id: TV => SkolemTag(id)(tt.prov)\n            case _ => die\n          }\n        } else if (tt.level > lowerLvl) {\n            // * When a rigid type variable is extruded,\n            // * we need to essentially widen it to Top or Bot.\n            // * Creating a new skolem instead, as was done at some point, is actually unsound.\n            // * But for better error messages, we instead use an `Extruded` abstract tag,\n            // * making sure we pick a *different* one for positive and negative positions,\n            // * which achieves the same effect as Top/Bot.\n            new Extruded(!pol, tt)(\n              tt.prov.copy(desc = \"extruded type variable reference\"), reason)\n        } else die // shouldn't happen\n      case _: ClassTag | _: TraitTag | _: Extruded => ty\n      case tr @ TypeRef(d, ts) =>\n        TypeRef(d, tr.mapTargs(S(pol)) {\n          case (N, targ) =>\n            // * Note: the semantics of TypeBounds is inappropriuate for this use (known problem; FIXME later)\n            TypeBounds.mk(extrude(targ, lowerLvl, false, upperLvl), extrude(targ, lowerLvl, true, upperLvl)) // Q: ? subtypes?\n            // * A sanity-checking version, making sure the type range is correct (LB subtype of UB):\n            /* \n            val a = extrude(targ, lowerLvl, false, upperLvl)\n            val b = extrude(targ, lowerLvl, true, upperLvl)\n            implicit val r: Raise = throw _\n            implicit val p: TP = noProv\n            constrain(a, b)\n            TypeBounds.mk(a, b)\n            */\n          case (S(pol), targ) => extrude(targ, lowerLvl, pol, upperLvl)\n        })(tr.prov)\n      case PolymorphicType(polymLevel, body) =>\n        PolymorphicType(polymLevel, extrude(body, lowerLvl, pol, upperLvl =\n            // upperLvl min polymLevel // * for some crazy reason, this stopped type checking\n            Math.min(upperLvl, polymLevel)\n          ))\n      case ConstrainedType(cs, bod) =>\n        ConstrainedType(cs.map { case (lo, hi) =>\n          extrude(lo, lowerLvl, true, upperLvl) -> extrude(hi, lowerLvl, false, upperLvl)\n        }, extrude(bod, lowerLvl, pol, upperLvl))\n      case o @ Overload(alts) =>\n        o.mapAlts(extrude(_, lowerLvl, !pol, upperLvl))(extrude(_, lowerLvl, pol, upperLvl))\n    }\n    // }(r => s\"=> $r\"))\n  \n  \n  def err(msg: Message, loco: Opt[Loc])(implicit raise: Raise): SimpleType = {\n    err(msg -> loco :: Nil)\n  }\n  def err(msgs: List[Message -> Opt[Loc]])(implicit raise: Raise): SimpleType = {\n    err(ErrorReport(msgs, newDefs))\n  }\n  def err(diag: Diagnostic)(implicit raise: Raise): SimpleType = {\n    raise(diag)\n    errType\n  }\n  def errType: SimpleType = ClassTag(ErrTypeId, Set.empty)(noProv)\n  \n  def warn(msg: Message, loco: Opt[Loc])(implicit raise: Raise): Unit =\n    warn(msg -> loco :: Nil)\n\n  def warn(msgs: List[Message -> Opt[Loc]])(implicit raise: Raise): Unit =\n    raise(WarningReport(msgs, newDefs))\n  \n  \n  \n  def unify(lhs: ST, rhs: ST)(implicit raise: Raise, prov: TypeProvenance, ctx: Ctx, \n          shadows: Shadows = Shadows.empty\n        ): Unit = {\n    trace(s\"$lvl. U $lhs =! $rhs\") {\n      \n      def rec(lhs: ST, rhs: ST, swapped: Bool): Unit =\n        if (!lhs.mentionsTypeBounds && lhs === rhs) () else\n        (lhs, rhs) match {\n          \n          // TODO handle more cases\n          \n          case (tv: TV, bound) if bound.level <= tv.level =>\n            tv.assignedTo match {\n              case S(et) =>\n                unify(et, bound)\n              case N =>\n                println(s\"$tv := $bound\")\n                val lbs = tv.lowerBounds\n                val ubs = tv.upperBounds\n                tv.assignedTo = S(bound)\n                lbs.foreach(constrainImpl(_, bound))\n                ubs.foreach(constrainImpl(bound, _))\n            }\n            \n          case _ =>\n            if (swapped) {\n              constrain(lhs, rhs)\n              constrain(rhs, lhs)\n            } else rec(rhs, lhs, true)\n            \n        }\n      rec(lhs, rhs, false)\n    }()\n  }\n  \n  \n  \n  /** Freshens all the type variables whose level is comprised in `(above, below]`\n    *   or which have bounds and whose level is greater than `above`. */\n  def freshenAbove(above: Level, ty: SimpleType,\n          rigidify: Bool = false, below: Level = MaxLevel, leaveAlone: Set[TV] = Set.empty)\n        (implicit ctx: Ctx, freshened: MutMap[TV, ST])\n        : SimpleType =\n  {\n    def freshenImpl(ty: SimpleType, below: Level): SimpleType =\n    // (trace(s\"${lvl}. FRESHEN $ty || $above .. $below  ${ty.level} ${ty.level <= above}\")\n    {\n      // * Cannot soundly freshen if the context's level is above the current polymorphism level,\n      // * as that would wrongly capture the newly-freshened variables.\n      require(below >= lvl)\n      \n      def freshen(ty: SimpleType): SimpleType = freshenImpl(ty, below)\n      \n      if (\n        // * Note that commenting this broke the old semantics of wildcard TypeBound-s in signatures:\n        /* !rigidify // Rigidification now also substitutes TypeBound-s with fresh vars;\n                    // since these have the level of their bounds, when rigidifying\n                    // we need to make sure to copy the whole type regardless of level...\n        && */ ty.level <= above) ty else ty match {\n      \n      case tv: TypeVariable if leaveAlone(tv)  => tv\n      \n      case tv @ AssignedVariable(ty) =>\n        freshened.getOrElse(tv, {\n          val nv = freshVar(tv.prov, S(tv), tv.nameHint)(if (tv.level > below) tv.level else lvl)\n          freshened += tv -> nv\n          val ty2 = freshen(ty)\n          nv.assignedTo = S(ty2)\n          nv\n        })\n      \n      // * Note: I forgot why I though this was unsound...\n      /*\n      case tv: TypeVariable // THIS IS NOT SOUND: WE NEED TO REFRESH REGARDLESS!!\n        if tv.level > below\n        // It is not sound to ignore the bounds here,\n        //    as the bounds could contain references to other TVs with lower level;\n        //  OTOH, we don't want to traverse the whole bounds graph every time just to check\n        //    (using `levelBelow`),\n        //    so if there are any bounds registered, we just conservatively freshen the TV.\n        && tv.lowerBounds.isEmpty\n        && tv.upperBounds.isEmpty\n        => tv\n      */\n      \n      case tv: TypeVariable => freshened.get(tv) match {\n        case Some(tv) => tv\n        case None if rigidify && tv.level <= below =>\n          // * Rigid type variables (ie, skolems) are encoded as SkolemTag-s\n          val rv = SkolemTag(freshVar(noProv, S(tv), tv.nameHint/* .orElse(S(\"_\"))*/))(tv.prov)\n          println(s\"New skolem: $tv ~> $rv\")\n          if (tv.lowerBounds.nonEmpty || tv.upperBounds.nonEmpty) { // TODO just add bounds to skolems! should lead to simpler constraints\n            // The bounds of `tv` may be recursive (refer to `tv` itself),\n            //    so here we create a fresh variabe that will be able to tie the presumed recursive knot\n            //    (if there is no recursion, it will just be a useless type variable)\n            val tv2 = freshVar(tv.prov, S(tv), tv.nameHint)(lvl)\n            freshened += tv -> tv2\n            // Assuming there were no recursive bounds, given L <: tv <: U,\n            //    we essentially need to turn tv's occurrence into the type-bounds (rv | L)..(rv & U),\n            //    meaning all negative occurrences should be interpreted as rv | L\n            //    and all positive occurrences should be interpreted as rv & U\n            //    where rv is the rigidified variables.\n            // Now, since there may be recursive bounds, we do the same\n            //    but through the indirection of a type variable tv2:\n            tv2.lowerBounds ::= tv.upperBounds.map(freshen).foldLeft(rv: ST)(_ & _)\n            println(s\"$tv2 :> ${tv2.lowerBounds}\")\n            tv2.upperBounds ::= tv.lowerBounds.map(freshen).foldLeft(rv: ST)(_ | _)\n            println(s\"$tv2 <: ${tv2.upperBounds}\")\n            tv2\n          } else {\n            // NOTE: tv.level may be different from lvl; is that OK?\n            freshened += tv -> rv\n            rv\n          }\n        case None =>\n          val v = freshVar(tv.prov, S(tv), tv.nameHint)(if (tv.level > below) tv.level else {\n            assert(lvl <= below, \"this condition should be false for the result to be correct\")\n            lvl\n          })\n          val freshentsc = tv.tsc.flatMap { case (tsc,_) =>\n            if (tsc.tvs.values.map(_.unwrapProxies).forall {\n              case tv: TV => !freshened.contains(tv)\n              case _ => true\n            }) S(tsc) else N\n          }\n          freshened += tv -> v\n          v.lowerBounds = tv.lowerBounds.mapConserve(freshen)\n          v.upperBounds = tv.upperBounds.mapConserve(freshen)\n          freshentsc.foreach { tsc =>\n            val t = new TupleSetConstraints(tsc.constraints, tsc.tvs)\n            t.constraints = t.constraints.map(_.map(freshen))\n            t.tvs = t.tvs.map(x => (x._1,freshen(x._2)))\n            t.tvs.values.map(_.unwrapProxies).zipWithIndex.foreach {\n              case (tv: TV, i) => tv.tsc.updateWith(t)(_.map(_ + i).orElse(S(Set(i))))\n              case _ => ()\n            }\n          }\n          v\n      }\n      \n      case t @ TypeBounds(lb, ub) =>\n        \n        // * This was done to make `?` behave similarly to an existential.\n        // * But this niche treatment just needlessly complicates things;\n        // * better implement proper existentials later on!\n        /*\n        if (rigidify) {\n          val tv = freshVar(t.prov, N) // FIXME coudl N here result in divergence? cf. absence of shadow\n          tv.lowerBounds ::= freshen(lb)\n          tv.upperBounds ::= freshen(ub)\n          tv\n        } else TypeBounds(freshen(lb), freshen(ub))(t.prov)\n        */\n        \n        TypeBounds(freshen(lb), freshen(ub))(t.prov)\n        \n      case t @ FunctionType(l, r) => FunctionType(freshen(l), freshen(r))(t.prov)\n      case t @ ComposedType(p, l, r) => ComposedType(p, freshen(l), freshen(r))(t.prov)\n      case t @ RecordType(fs) => RecordType(fs.mapValues(_.update(freshen, freshen)))(t.prov)\n      case t @ TupleType(fs) => TupleType(fs.mapValues(_.update(freshen, freshen)))(t.prov)\n      case t @ ArrayType(ar) => ArrayType(ar.update(freshen, freshen))(t.prov)\n      case t @ SpliceType(fs) => t.updateElems(freshen, freshen, freshen, t.prov)\n      case n @ NegType(neg) => NegType(freshen(neg))(n.prov)\n      case e @ ExtrType(_) => e\n      case p @ ProvType(und) => ProvType(freshen(und))(p.prov)\n      case p @ ProxyType(und) => freshen(und)\n      case s @ SkolemTag(id) if s.level > above && s.level <= below =>\n        freshen(id)\n      case _: ClassTag | _: TraitTag | _: SkolemTag | _: Extruded => ty\n      case w @ Without(b, ns) => Without(freshen(b), ns)(w.prov)\n      case tr @ TypeRef(d, ts) => TypeRef(d, ts.map(freshen(_)))(tr.prov)\n      case pt @ PolymorphicType(polyLvl, bod) if pt.level <= above => pt // is this really useful?\n      case pt @ PolymorphicType(polyLvl, bod) =>\n        if (lvl > polyLvl) freshen(pt.raiseLevelToImpl(lvl, leaveAlone))\n        else PolymorphicType(polyLvl, freshenImpl(bod, below = below min polyLvl))\n      case ct @ ConstrainedType(cs, bod) =>\n        val cs2 = cs.map(lu => freshen(lu._1) -> freshen(lu._2))\n        ConstrainedType(cs2, freshen(bod))\n      case o @ Overload(alts) =>\n        o.mapAlts(freshen)(freshen)\n    }}\n    // (r => s\"=> $r\"))\n    \n    freshenImpl(ty, below)\n  }\n  \n  \n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/Diagnostic.scala",
    "content": "package mlscript\n\nimport scala.util.chaining._\nimport mlscript.utils._, shorthands._\n\nimport Diagnostic._\n\nsealed abstract class Diagnostic(val theMsg: String) extends Exception(theMsg) {\n  val allMsgs: Ls[Message -> Opt[Loc]]\n  val kind: Kind\n  val source: Source\n}\nobject Diagnostic {\n  \n  sealed abstract class Kind\n  case object Error   extends Kind\n  case object Warning extends Kind\n  \n  sealed abstract class Source\n  case object Lexing      extends Source\n  case object Parsing     extends Source\n  case object PreTyping   extends Source\n  case object Desugaring  extends Source\n  case object Typing      extends Source\n  case object Compilation extends Source\n  case object Runtime     extends Source\n  \n}\n\nfinal case class ErrorReport(mainMsg: Str, allMsgs: Ls[Message -> Opt[Loc]], source: Source) extends Diagnostic(mainMsg) {\n  val kind: Kind = Error\n}\nobject ErrorReport {\n  def apply(msgs: Ls[Message -> Opt[Loc]], newDefs: Bool, source: Source = Typing): ErrorReport =\n    ErrorReport(msgs.head._1.show(newDefs), msgs, source)\n}\n\nfinal case class WarningReport(mainMsg: Str, allMsgs: Ls[Message -> Opt[Loc]], source: Source) extends Diagnostic(mainMsg) {\n  val kind: Kind = Warning\n}\nobject WarningReport {\n  def apply(msgs: Ls[Message -> Opt[Loc]], newDefs: Bool, source: Source = Typing): WarningReport =\n    WarningReport(msgs.head._1.show(newDefs), msgs, source)\n}\n\n\nfinal case class Loc(spanStart: Int, spanEnd: Int, origin: Origin) {\n  assert(spanStart >= 0)\n  assert(spanEnd >= spanStart)\n  def covers(that: Loc): Bool = that.origin === this.origin && (\n    that.spanStart >= this.spanStart && that.spanEnd <= this.spanEnd\n  )\n  def touches(that: Loc): Bool = that.origin === this.origin && (\n    that.spanStart >= this.spanStart && that.spanStart <= this.spanEnd\n    || that.spanEnd <= this.spanEnd && that.spanEnd >= this.spanStart\n  )\n  def ++(that: Loc): Loc = {\n    require(this.origin is that.origin)\n    Loc(this.spanStart min that.spanStart, this.spanEnd max that.spanEnd, origin)\n  }\n  def ++(that: Opt[Loc]): Loc = that.fold(this)(this ++ _)\n  def right: Loc = copy(spanStart = spanEnd)\n  def left: Loc = copy(spanEnd = spanStart)\n}\nobject Loc {\n  def apply(xs: IterableOnce[Located]): Opt[Loc] =\n    xs.iterator.foldLeft(none[Loc])((acc, l) => acc.fold(l.toLoc)(_ ++ l.toLoc |> some))\n}\n\nfinal case class Origin(fileName: Str, startLineNum: Int, fph: FastParseHelpers) {\n  override def toString = s\"$fileName:+$startLineNum\"\n}\n\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/JSBackend.scala",
    "content": "package mlscript\n\nimport mlscript.utils._, shorthands._, algorithms._\nimport mlscript.codegen._\nimport scala.collection.mutable.{ListBuffer, HashMap, HashSet}\nimport mlscript.{JSField, JSLit}\nimport scala.collection.mutable.{Set => MutSet}\nimport scala.util.control.NonFatal\nimport scala.util.chaining._\n\nabstract class JSBackend {\n  def oldDefs: Bool\n\n  protected implicit class TermOps(term: Term) {\n    def isLam: Bool = term match {\n      case _: Lam => true\n      case Bra(false, inner) => inner.isLam\n      case Asc(inner, _) => inner.isLam\n      case _ => false\n    }\n  }\n  \n  /**\n    * The root scope of the program.\n    */\n  protected val topLevelScope = Scope(\"root\")\n\n  /**\n    * The prelude code manager.\n    */\n  protected val polyfill = Polyfill()\n\n  /**\n    * This function translates parameter destructions in `def` declarations.\n    *\n    * The production rules of MLscript `def` parameters are:\n    *\n    *     subterm ::= \"(\" term \")\" | record | literal | identifier\n    *     term ::= let | fun | ite | withsAsc | _match\n    *\n    * JavaScript supports following destruction patterns:\n    *\n    * - Array patterns: `[x, y, ...]` where `x`, `y` are patterns.\n    * - Object patterns: `{x: y, z: w, ...}` where `z`, `w` are patterns.\n    * - Identifiers: an identifier binds the position to a name.\n    *\n    * This function only translate name patterns and object patterns. I was thinking if we can\n    * support literal parameter matching by merging multiple function `def`s into one.\n    */\n  private def translatePattern(t: Term)(implicit scope: Scope): JSPattern = t match {\n    // fun x -> ... ==> function (x) { ... }\n    // should returns (\"x\", [\"x\"])\n    case Var(name) =>\n      val runtimeName = scope.declareParameter(name)\n      JSNamePattern(runtimeName)\n    // fun { x, y } -> ... ==> function ({ x, y }) { ... }\n    // should returns (\"{ x, y }\", [\"x\", \"y\"])\n    case Rcd(fields) =>\n      JSObjectPattern(fields map {\n        case (Var(nme), Fld(_, Var(als))) =>\n          val runtimeName = scope.declareParameter(als)\n          val fieldName = JSField.emitValidFieldName(nme)\n          if (runtimeName === fieldName) fieldName -> N\n          else fieldName -> S(JSNamePattern(runtimeName))\n        case (Var(nme), Fld(_, subTrm)) => \n          JSField.emitValidFieldName(nme) -> S(translatePattern(subTrm))\n      })\n    // This branch supports `def f (x: int) = x`.\n    case Asc(trm, _) => translatePattern(trm)\n    // Replace literals with wildcards.\n    case _: Lit      => JSWildcardPattern()\n    case Bra(_, trm) => translatePattern(trm)\n    case Tup(fields) => JSArrayPattern(fields map { case (_, Fld(_, t)) => translatePattern(t) })\n    // Others are not supported yet.\n    case TyApp(base, _) =>\n      translatePattern(base)\n    case Inst(bod) => translatePattern(bod)\n    case Ann(ann, receiver) => translatePattern(receiver)\n    case _: Lam | _: App | _: Sel | _: Let | _: Blk | _: Bind | _: Test | _: With | _: CaseOf | _: Subs | _: Assign\n        | _: If | _: New  | _: NuNew | _: Splc | _: Forall | _: Where | _: Super | _: Eqn | _: AdtMatchWith\n        | _: Rft | _: While | _: Quoted | _: Unquoted =>\n      throw CodeGenError(s\"term $t is not a valid pattern\")\n  }\n\n  private def translateParams(t: Term)(implicit scope: Scope): Ls[JSPattern] = t match {\n    case Tup(params) => params map {\n      case N -> Fld(_, p) => translatePattern(p)\n      case S(nme) -> Fld(_, p) => translatePattern(nme)\n    }\n    case _           => throw CodeGenError(s\"term $t is not a valid parameter list\")\n  }\n\n  // Set `requireActualCls` to true if we need the actual class rather than the constrcutor function (if the class has)\n  private def translateNuTypeSymbol(sym: NuTypeSymbol, requireActualCls: Bool)(implicit scope: Scope): JSExpr = {\n    val trm = sym.qualifier.fold[JSExpr](JSIdent(sym.name))(qualifier => {\n      scope.resolveQualifier(qualifier).visited = true\n      JSIdent(qualifier).member(sym.name)\n    })\n    if (requireActualCls && !sym.isPlainJSClass) trm.member(\"class\") else trm\n  }\n\n  protected def translateVar(name: Str, isCallee: Bool)(implicit scope: Scope): JSExpr =\n    translateVarImpl(name, isCallee).fold(throw _, identity)\n  \n  /** Try to retrieve a name from the scope, returning a Left value if the name is not found,\n    * a Right value if it is found, and throwing an exception in case of unrecoverable error. */\n  protected def translateVarImpl(name: Str, isCallee: Bool)(implicit scope: Scope): Either[CodeGenError, JSExpr] =\n    Right(scope.resolveValue(name) match {\n      case S(sym: BuiltinSymbol) =>\n        sym.accessed = true\n        if (!polyfill.used(sym.feature))\n          polyfill.use(sym.feature, sym.runtimeName)\n        val ident = JSIdent(sym.runtimeName)\n        if (sym.feature === \"error\") ident() else ident\n      case S(sym: StubValueSymbol) =>\n        if (sym.accessible)\n          JSIdent(sym.runtimeName)\n        else\n          throw new UnimplementedError(sym)\n      case S(sym: ValueSymbol) =>\n        if (sym.isByvalueRec.getOrElse(false) && !sym.isLam) throw CodeGenError(s\"unguarded recursive use of by-value binding $name\")\n        sym.visited = true\n        val ident = JSIdent(sym.runtimeName)\n        if (sym.isByvalueRec.isEmpty && !sym.isLam) ident() else ident\n      case S(sym: NuTypeSymbol) =>\n        translateNuTypeSymbol(sym, isCallee) // `isCallee` is true in a `new` expression, which requires the actual class\n      case S(sym: NewClassMemberSymbol) =>\n        if (sym.isByvalueRec.getOrElse(false) && !sym.isLam) throw CodeGenError(s\"unguarded recursive use of by-value binding $name\")\n        sym.qualifier.fold[JSExpr](throw CodeGenError(s\"unqualified member symbol $sym\"))(qualifier => {\n          sym.visited = true\n          scope.resolveQualifier(qualifier).visited = true\n          val ident = if (sym.isPrivate) JSIdent(s\"${qualifier}.#${sym.name}\")\n                      else JSIdent(qualifier).member(sym.name)\n          if (sym.isByvalueRec.isEmpty && !sym.isLam) ident() else ident\n        })\n      case S(sym: ClassSymbol) =>\n        if (isCallee || !oldDefs)\n          JSNew(JSIdent(sym.runtimeName))\n        else\n          JSArrowFn(JSNamePattern(\"x\") :: Nil, L(JSNew(JSIdent(sym.runtimeName))(JSIdent(\"x\"))))\n      case S(sym: TraitSymbol) =>\n        if (oldDefs) JSIdent(sym.lexicalName)(\"build\")\n        else return Left(CodeGenError(s\"trait used in term position\"))\n      case N => scope.getType(name) match {\n        case S(sym: TypeAliasSymbol) =>\n          return Left(CodeGenError(s\"type alias ${name} is not a valid expression\"))\n        case S(_) => lastWords(\"register mismatch in scope\")\n        case N =>\n          return Left(CodeGenError(s\"unresolved symbol ${name}\"))\n      }\n    })\n\n  /**\n    * Handle all possible cases of MLscript function applications. We extract\n    * this method to prevent exhaustivity check from reaching recursion limit.\n    */\n  protected def translateApp(term: App)(implicit scope: Scope): JSExpr = term match {\n    // Binary expressions\n    case App(App(Var(op), Tup((N -> Fld(_, lhs)) :: Nil)), Tup((N -> Fld(_, rhs)) :: Nil))\n        if oldDefs && (JSBinary.operators contains op) =>\n      JSBinary(op, translateTerm(lhs), translateTerm(rhs))\n    // Binary expressions with new-definitions\n    case App(Var(op), Tup(N -> Fld(_, lhs) :: N -> Fld(_, rhs) :: Nil)) // JS doesn't support operators like `+.` so we need to map them before testing\n        if JSBinary.operators.contains(mapFloatingOperator(op)) && (!translateVarImpl(op, isCallee = true).isRight || op =/= mapFloatingOperator(op)) =>\n      JSBinary(mapFloatingOperator(op), translateTerm(lhs), translateTerm(rhs))\n    // If-expressions\n    case App(App(App(Var(\"if\"), Tup((_, Fld(_, tst)) :: Nil)), Tup((_, Fld(_, con)) :: Nil)), Tup((_, Fld(_, alt)) :: Nil)) =>\n      JSTenary(translateTerm(tst), translateTerm(con), translateTerm(alt))\n    case App(App(App(Var(\"if\"), tst), con), alt) => die\n    // Function invocation\n    case App(trm, Tup(args)) =>\n      val callee = trm match {\n        case Var(nme) if oldDefs => scope.resolveValue(nme) match {\n          case S(sym: NuTypeSymbol) =>\n            translateNuTypeSymbol(sym, false) // ClassName(params)\n          case _ => translateVar(nme, true) // Keep this case for the legacy test cases\n        }\n        case _ => translateTerm(trm)\n      }\n      callee(args map { case (_, Fld(_, arg)) => translateTerm(arg) }: _*)\n    case App(trm, splice) => ??? // TODO represents `trm(...splice)`\n    case _ => throw CodeGenError(s\"ill-formed application $term\")\n  }\n\n  // * Generate an `App` node for AST constructors\n  private def createASTCall(tp: Str, args: Ls[Term]): App =\n    App(Var(tp), Tup(args.map(a => N -> Fld(FldFlags.empty, a))))\n\n  // * Bound free variables appearing in quasiquotes\n  class FreeVars(val vs: Set[Str])\n\n  // * Left: the branch is quoted and it has been desugared\n  // * Right: the branch is not quoted and quoted subterms have been desugared\n  private def desugarQuotedBranch(branch: CaseBranches)(\n    implicit scope: Scope, isQuoted: Bool, freeVars: FreeVars\n  ): Either[Term, CaseBranches] = branch match {\n    case cse @ Case(pat, body, rest) =>\n      val dp = desugarQuote(pat)\n      val db = desugarQuote(body)\n      desugarQuotedBranch(rest) match {\n        case L(t) => L(createASTCall(\"Case\", dp :: db :: t :: Nil))\n        case R(b) => dp match {\n          case dp: SimpleTerm => R(Case(dp, db, b)(cse.refined))\n          case _ => die\n        }\n      }\n    case Wildcard(body) =>\n      if (isQuoted) L(createASTCall(\"Wildcard\", desugarQuote(body) :: Nil)) else R(Wildcard(desugarQuote(body)))\n    case NoCases => if (isQuoted) L(createASTCall(\"NoCases\", Nil)) else R(NoCases)\n  }\n\n  // * Operators `+`, `-`, and `*` will not be available for floating numbers until we have the correct overloading.\n  // * Currently, we use OCaml-style floating operators temporarily and translate them into normal JS operators.\n  private def mapFloatingOperator(op: Str) = op match {\n    case \"+.\" => \"+\"\n    case \"-.\" => \"-\"\n    case \"*.\" => \"*\"\n    case _ => op\n  }\n\n  // * Desugar `Quoted` into AST constructor invocations.\n  // * example 1: `` `42 `` is desugared into `IntLit(42)`\n  // * example 2: `` x `=> id(x) `+ `1 `` is desugared into `let x1 = freshName(\"x\") in Lam(Var(x1), App(Var(\"+\"), id(Var(x1)), IntLit(1)))`\n  private def desugarQuote(term: Term)(implicit scope: Scope, isQuoted: Bool, freeVars: FreeVars): Term = term match {\n    case Var(name) =>\n      val isFreeVar = freeVars.vs(name)\n      if (isQuoted || isFreeVar) {\n        val runtimeName = scope.resolveValue(name).fold[Str](\n          throw CodeGenError(s\"unbound free variable $name is not supported yet.\")\n        )(_.runtimeName)\n        if (isFreeVar) createASTCall(\"Var\", Var(runtimeName) :: Nil) // quoted variables\n        else createASTCall(\"Var\", StrLit(runtimeName) :: Nil) // built-in symbols (e.g., true, error)\n      }\n      else term\n    case lit: IntLit => if (isQuoted) createASTCall(\"IntLit\", lit :: Nil) else lit\n    case lit: DecLit => if (isQuoted) createASTCall(\"DecLit\", lit :: Nil) else lit\n    case lit: StrLit => if (isQuoted) createASTCall(\"StrLit\", lit :: Nil) else lit\n    case lit: UnitLit => if (isQuoted) createASTCall(\"UnitLit\", lit :: Nil) else lit\n    case Lam(params, body) =>\n      if (isQuoted) {\n        val lamScope = scope.derive(\"Lam\")\n        params match {\n          case Tup(params) =>\n            val newfreeVars = params.map {\n              case N -> Fld(_, Var(nme)) =>\n                lamScope.declareParameter(nme)\n                nme -> lamScope.declareValue(nme, S(false), false, N).runtimeName\n              case S(Var(nme)) -> _ =>\n                lamScope.declareParameter(nme)\n                nme -> lamScope.declareValue(nme, S(false), false, N).runtimeName\n              case p => throw CodeGenError(s\"parameter $p is not supported in quasiquote\")\n            }\n            newfreeVars.foldRight(desugarQuote(body)(lamScope, isQuoted, new FreeVars(freeVars.vs ++ newfreeVars.map(_._1))))((p, res) =>\n              Let(false, Var(p._2), createASTCall(\"freshName\", StrLit(p._1) :: Nil), createASTCall(\"Lam\", createASTCall(\"Var\", Var(p._2) :: Nil) :: res :: Nil)))\n          case _  => throw CodeGenError(s\"term $params is not a valid parameter list\")\n        }\n      }\n      else Lam(params, desugarQuote(body))\n    case Unquoted(body) =>\n      if (isQuoted) {\n        val unquoteScope = scope.derive(\"unquote\")\n        desugarQuote(body)(unquoteScope, false, freeVars)\n      }\n      else throw CodeGenError(\"unquoted term should be wrapped by quotes.\")\n    case Quoted(body) =>\n      val quoteScope = scope.derive(\"quote\")\n      val res = desugarQuote(body)(quoteScope, true, freeVars)\n      if (isQuoted) throw CodeGenError(\"nested quotation is not allowed.\")\n      else res\n    case App(Var(op), Tup(N -> Fld(f1, lhs) :: N -> Fld(f2, rhs) :: Nil))\n        if JSBinary.operators.contains(mapFloatingOperator(op)) && (!translateVarImpl(op, isCallee = true).isRight || op =/= mapFloatingOperator(op)) =>\n      if (isQuoted)\n        createASTCall(\"App\", createASTCall(\"Var\", StrLit(mapFloatingOperator(op)) :: Nil) :: desugarQuote(lhs) :: desugarQuote(rhs) :: Nil)\n      else\n        App(Var(op), Tup(N -> Fld(f1, desugarQuote(lhs)) :: N -> Fld(f2, desugarQuote(rhs)) :: Nil))\n    case App(lhs, rhs) =>\n      if (isQuoted) createASTCall(\"App\", desugarQuote(lhs) :: desugarQuote(rhs) :: Nil)\n      else App(desugarQuote(lhs), desugarQuote(rhs))\n    case Rcd(fields) =>\n      if (isQuoted) createASTCall(\"Rcd\", fields.flatMap(f => createASTCall(\"Var\", StrLit(f._1.name) :: Nil) :: desugarQuote(f._2.value) :: Nil))\n      else Rcd(fields.map(f => (f._1, Fld(f._2.flags, desugarQuote(f._2.value)))))\n    case Bra(rcd, trm) =>\n      if (isQuoted) createASTCall(\"Bra\", desugarQuote(trm) :: Nil)\n      else Bra(rcd, desugarQuote(trm))\n    case Sel(receiver, f @ Var(name)) =>\n      if (isQuoted) createASTCall(\"Sel\", desugarQuote(receiver) :: createASTCall(\"Var\", StrLit(name) :: Nil) :: Nil)\n      else Sel(desugarQuote(receiver), f)\n    case Let(rec, Var(name), value, body) =>\n      val letScope = scope.derive(\"Let\")\n      if (isQuoted) {\n        letScope.declareParameter(name)\n        val freshedName = letScope.declareValue(name, S(false), false, N).runtimeName\n        Let(false, Var(freshedName), createASTCall(\"freshName\", StrLit(name) :: Nil),\n          createASTCall(\"Let\", createASTCall(\"Var\", Var(freshedName) :: Nil) :: desugarQuote(value)\n            :: desugarQuote(body)(letScope, isQuoted, new FreeVars(freeVars.vs ++ (name :: Nil))) :: Nil\n        ))\n      }\n      else Let(rec, Var(name), desugarQuote(value), desugarQuote(body)(letScope, isQuoted, freeVars))\n    case Blk(stmts) =>\n      val blkScope = scope.derive(\"blk\")\n      if (isQuoted) createASTCall(\"Blk\", stmts.map {\n        case t: Term =>\n          desugarQuote(t)(blkScope, isQuoted, freeVars)\n        case s => throw CodeGenError(s\"statement $s is not supported in quasiquotes\")\n      })\n      else Blk(stmts.map {\n        case t: Term =>\n          desugarQuote(t)(blkScope, isQuoted, freeVars)\n        case s => desugarStatementInUnquote(s)(blkScope, freeVars)\n      })\n    case Tup(eles) =>\n      def toVar(b: Bool) = if (b) Var(\"true\") else Var(\"false\")\n      def toVars(flg: FldFlags) = toVar(flg.mut) :: toVar(flg.spec) :: toVar(flg.genGetter) :: Nil\n      if (isQuoted) createASTCall(\"Tup\", eles flatMap {\n        case S(Var(name)) -> Fld(flags, t) =>\n          createASTCall(\"Var\", Var(name) :: Nil) :: createASTCall(\"Fld\", desugarQuote(t) :: toVars(flags)) :: Nil\n        case N -> Fld(flags, t) => createASTCall(\"Fld\", desugarQuote(t) :: toVars(flags)) :: Nil\n      })\n      else Tup(eles.map {\n        case v -> Fld(flags, t) => v -> Fld(flags, desugarQuote(t))\n      })\n    case Subs(arr, idx) =>\n      if (isQuoted) createASTCall(\"Subs\", desugarQuote(arr) :: desugarQuote(idx) :: Nil)\n      else Subs(desugarQuote(arr), desugarQuote(idx))\n    case Asc(trm, ty) =>\n      if (isQuoted) desugarQuote(trm)\n      else Asc(desugarQuote(trm), ty)\n    case With(lhs, rhs @ Rcd(fields)) =>\n      if (isQuoted) createASTCall(\"With\", desugarQuote(lhs) :: desugarQuote(rhs) :: Nil)\n      else With(desugarQuote(lhs), Rcd(fields.map(f => (f._1, Fld(f._2.flags, desugarQuote(f._2.value))))))\n    case CaseOf(trm, cases) =>\n      desugarQuotedBranch(cases) match {\n        case L(t) => createASTCall(\"CaseOf\", desugarQuote(trm) :: t :: Nil)\n        case R(b) => CaseOf(desugarQuote(trm), b)\n      }\n    case _ if term.desugaredTerm.isDefined => desugarQuote(term.desugaredTerm.getOrElse(die))\n    case Assign(lhs, rhs) if !isQuoted => Assign(desugarQuote(lhs), desugarQuote(rhs))\n    case NuNew(cls) if !isQuoted => NuNew(desugarQuote(cls))\n    case TyApp(lhs, targs) if !isQuoted => TyApp(desugarQuote(lhs), targs)\n    case Forall(p, body) if !isQuoted => Forall(p, desugarQuote(body))\n    case Inst(body) if !isQuoted => Inst(desugarQuote(body))\n    case _: Super if !isQuoted => term\n    case Eqn(lhs, rhs) if !isQuoted => Eqn(lhs, desugarQuote(rhs))\n    case Ann(ann, receiver) => Ann(desugarQuote(ann), desugarQuote(receiver))\n    case While(cond, body) if !isQuoted => While(desugarQuote(cond), desugarQuote(body))\n    case _: Bind | _: Test | _: If  | _: Splc | _: Where | _: AdtMatchWith | _: Rft | _: New\n        | _: Assign | _: NuNew | _: TyApp | _: Forall | _: Inst | _: Super | _: Eqn | _: While =>\n      throw CodeGenError(\"this quote syntax is not supported yet.\")\n  }\n\n  // * Statements inside **Unquote** can refer to quoted code fragments.\n  // * Desugar them recursively.\n  private def desugarStatementInUnquote(s: Statement)(implicit scope: Scope, freeVars: FreeVars): Statement = {\n    implicit val isQuoted: Bool = false\n    s match {\n      case nd @ NuFunDef(isLetRec, nme, symbol, tparams, rhs) =>\n        NuFunDef(isLetRec, nme, symbol, tparams, rhs match {\n          case L(t) => L(desugarQuote(t))\n          case R(t) => R(t)\n        })(nd.declareLoc, nd.virtualLoc, nd.mutLoc, nd.signature, nd.outer, nd.genField, nd.annotations)\n      case nt @ NuTypeDef(kind, nme, tparams, params, ctor, sig, parents, superAnnot, thisAnnot, TypingUnit(body)) =>\n        NuTypeDef(kind, nme, tparams, params, ctor.map(c => desugarStatementInUnquote(c) match {\n          case c: Constructor => c\n          case _ => die\n        }), sig, parents.map(p => desugarQuote(p)), superAnnot, thisAnnot, TypingUnit(body.map(s => desugarStatementInUnquote(s))))(nt.declareLoc, nt.abstractLoc, nt.annotations)\n      case Constructor(ps, body) => Constructor(ps, desugarQuote(body) match {\n        case b: Blk => b\n        case _ => die\n      })\n      case t: Term => desugarQuote(t)\n      case _: LetS | _: DataDefn | _: DatatypeDefn | _: TypeDef | _: Def => die // * Impossible. newDef is true\n    }\n  }\n\n  /**\n    * Translate MLscript terms into JavaScript expressions.\n    */\n  protected def translateTerm(term: Term)(implicit scope: Scope): JSExpr = term match {\n    case _ if term.desugaredTerm.isDefined => translateTerm(term.desugaredTerm.getOrElse(die))\n    case Var(name) => translateVar(name, false)\n    case Super() => JSIdent(\"super\")\n    case Lam(params, body) =>\n      val lamScope = scope.derive(\"Lam\")\n      val patterns = translateParams(params)(lamScope)\n      JSArrowFn(patterns, lamScope.tempVars `with` translateTerm(body)(lamScope))\n    case t: App => translateApp(t)\n    case Rcd(fields) =>\n      JSRecord(fields map { case (key, Fld(_, value)) =>\n        key.name -> translateTerm(value)\n      })\n    case Sel(receiver, fieldName) =>\n      JSField(translateTerm(receiver), fieldName.name)\n    // Turn let into an IIFE.\n    case Let(true, Var(name), Lam(args, body), expr) =>\n      val letScope = scope.derive(\"Let\")\n      val runtimeName = letScope.declareParameter(name)\n      val fn = {\n        val fnScope = letScope.derive(\"Function\")\n        val params = translateParams(args)(fnScope)\n        val fnBody = fnScope.tempVars.`with`(translateTerm(body)(fnScope))\n        JSFuncExpr(S(runtimeName), params, fnBody.fold(_.`return` :: Nil, identity))\n      }\n      JSImmEvalFn(\n        N,\n        JSNamePattern(runtimeName) :: Nil,\n        letScope.tempVars.`with`(translateTerm(expr)(letScope)),\n        fn :: Nil\n      )\n    case Let(true, Var(name), _, _) =>\n      throw new CodeGenError(s\"recursive non-function definition $name is not supported\")\n    case Let(_, Var(name), value, body) =>\n      val letScope = scope.derive(\"Let\")\n      val runtimeName = letScope.declareParameter(name)\n      JSImmEvalFn(\n        N,\n        JSNamePattern(runtimeName) :: Nil,\n        letScope.tempVars `with` translateTerm(body)(letScope),\n        translateTerm(value) :: Nil\n      )\n    case Blk(stmts) =>\n      val blkScope = scope.derive(\"Blk\")\n      val flattened = stmts.iterator.flatMap {\n        case nt: NuTypeDef => nt :: Nil\n        case nf @ NuFunDef(_, Var(nme), symNme, _, _) =>\n          val symb = symNme.map(_.name)\n          blkScope.declareStubValue(nme, symb)(true)\n          nf.desugared._2\n        case other => other.desugared._2\n      }.toList\n      JSImmEvalFn(\n        N,\n        Nil,\n        R(blkScope.tempVars `with` (flattened.iterator.zipWithIndex.map {\n          case (t: Term, index) if index + 1 == flattened.length => translateTerm(t)(blkScope).`return`\n          case (t: Term, index)                                  => JSExprStmt(translateTerm(t)(blkScope))\n          case (NuFunDef(isLetRec, Var(nme), symNme, _, L(rhs)), _) =>\n            val symb = symNme.map(_.name)\n            val isLocalFunction = isLetRec.isEmpty || rhs.isLam\n            val pat = blkScope.declareValue(nme, isLetRec, isLocalFunction, symb)\n            JSLetDecl(Ls(pat.runtimeName -> S(translateTerm(rhs)(blkScope))))\n          case (nt: NuTypeDef, _) => translateLocalNewType(nt)(blkScope)\n          // TODO: find out if we need to support this.\n          case (_: Def | _: TypeDef | _: NuFunDef | _: DataDefn | _: DatatypeDefn | _: LetS | _: Constructor, _) =>\n            throw CodeGenError(\"unsupported definitions in blocks\")\n        }.toList)),\n        Nil\n      )\n    // Pattern match with only one branch -> comma expression\n    case CaseOf(trm, Wildcard(default)) =>\n      JSCommaExpr(translateTerm(trm) :: translateTerm(default) :: Nil)\n    // Pattern match with two branches -> tenary operator\n    case CaseOf(trm, cs @ Case(tst, csq, Wildcard(alt))) =>\n      translateCase(translateTerm(trm), tst)(scope)(translateTerm(csq), translateTerm(alt))\n    // Pattern match with more branches -> chain of ternary expressions with cache\n    case CaseOf(trm, cases) =>\n      val arg = translateTerm(trm)\n      if (arg.isSimple) {\n        translateCaseBranch(arg, cases)\n      } else {\n        val name = scope.declareRuntimeSymbol()\n        scope.tempVars += name\n        val ident = JSIdent(name)\n        JSCommaExpr(JSAssignExpr(ident, arg) :: translateCaseBranch(ident, cases) :: Nil)\n      }\n    case IntLit(value) => JSLit(value.toString + (if (JSBackend isSafeInteger value) \"\" else \"n\"))\n    case DecLit(value) => JSLit(value.toString)\n    case StrLit(value) => JSExpr(value)\n    case UnitLit(value) => JSLit(if (value) \"undefined\" else \"null\")\n    // `Asc(x, ty)` <== `x: Type`\n    case Asc(trm, _) => translateTerm(trm)\n    // `c with { x = \"hi\"; y = 2 }`\n    case With(trm, Rcd(fields)) =>\n      JSInvoke(\n        JSIdent(polyfill get \"withConstruct\" match {\n          case S(fnName) => fnName\n          case N         => polyfill.use(\"withConstruct\", topLevelScope.declareRuntimeSymbol(\"withConstruct\"))\n        }),\n        translateTerm(trm) :: JSRecord(fields map { case (Var(name), Fld(_, value)) =>\n          name -> translateTerm(value)\n        }) :: Nil\n      )\n    // Only parenthesize binary operators\n    // Custom operators do not need special handling since they are desugared to plain methods\n    case Bra(false, trm) => trm match { \n      case App(Var(op), _) if JSBinary.operators.contains(op) => JSParenthesis(translateTerm(trm)) \n      case trm => translateTerm(trm)\n    }\n    case Bra(_, trm) => translateTerm(trm)\n    case Tup(terms) =>\n      JSArray(terms map { case (_, Fld(_, term)) => translateTerm(term) })\n    case Subs(arr, idx) =>\n      JSMember(translateTerm(arr), translateTerm(idx))\n    case While(cond, body) =>\n      JSImmEvalFn(N, Nil, R(JSWhileStmt(translateTerm(cond), translateTerm(body)) :: Nil), Nil)\n    case Assign(lhs, value) =>\n      lhs match {\n        case _: Subs | _: Sel | _: Var =>\n          JSUnary(\"void\", JSAssignExpr(translateTerm(lhs), translateTerm(value)))\n        case _ =>\n          throw CodeGenError(s\"illegal assignemnt left-hand side: $lhs\")\n      }\n    case Inst(bod) => translateTerm(bod)\n    case iff: If =>\n      throw CodeGenError(s\"if expression was not desugared\")\n    case NuNew(cls) =>\n      // * The following logic handles the case when `new C(123)` needs to be translated to `new C.class(123)`\n      cls match {\n        case Var(className) =>\n          translateVar(className, isCallee = true) match {\n            case n: JSNew => n\n            case t => JSNew(t)\n          }\n        case _ => throw CodeGenError(s\"Unsupported `new` class term: $cls\")\n      }\n      // * Would not be quite correct:\n      // JSNew(translateTerm(cls))\n    case New(N, TypingUnit(Nil)) => JSRecord(Nil)\n    case New(S(TypeName(className) -> Tup(args)), TypingUnit(Nil)) =>\n      val callee = translateVar(className, true) match {\n        case n: JSNew => n\n        case t => JSNew(t)\n      }\n      callee(args.map { case (_, Fld(_, arg)) => translateTerm(arg) }: _*)\n    case New(_, TypingUnit(_)) =>\n      throw CodeGenError(\"custom class body is not supported yet\")\n    case Forall(_, bod) => translateTerm(bod)\n    case TyApp(base, _) => translateTerm(base)\n    case Eqn(Var(name), _) =>\n      throw CodeGenError(s\"assignment of $name is not supported outside a constructor\")\n    case Quoted(body) =>\n      val quotedScope = scope.derive(\"quote\")\n      translateTerm(desugarQuote(body)(quotedScope, true, new FreeVars(Set.empty)))(quotedScope)\n    case Ann(ann, receiver) => translateTerm(receiver)\n    case _: Bind | _: Test | _: If  | _: Splc | _: Where | _: AdtMatchWith | _: Rft | _: Unquoted =>\n      throw CodeGenError(s\"cannot generate code for term $term\")\n  }\n\n  private def translateCaseBranch(scrut: JSExpr, branch: CaseBranches)(implicit\n      scope: Scope\n  ): JSExpr = branch match {\n    case Case(pat, body, rest) =>\n      translateCase(scrut, pat)(scope)(translateTerm(body), translateCaseBranch(scrut, rest))\n    case Wildcard(body) =>\n      translateTerm(body)\n    case NoCases        => JSImmEvalFn(N, Nil, R(JSInvoke(\n      JSNew(JSIdent(\"Error\")),\n      JSExpr(\"non-exhaustive case expression\") :: Nil\n    ).`throw` :: Nil), Nil)\n  }\n\n  private def translateCase(scrut: JSExpr, pat: SimpleTerm)(implicit scope: Scope) = {\n    JSTenary(\n      pat match {\n        case Var(\"int\") =>\n          JSInvoke(JSField(JSIdent(\"Number\"), \"isInteger\"), scrut :: Nil)\n        case Var(\"Int\") if !oldDefs =>\n          JSInvoke(JSField(JSIdent(\"Number\"), \"isInteger\"), scrut :: Nil)\n        case Var(\"Num\") if !oldDefs =>\n          JSBinary(\"===\", scrut.typeof(), JSLit(JSLit.makeStringLiteral(\"number\")))\n        case Var(\"Bool\") if !oldDefs =>\n          JSBinary(\"===\", scrut.typeof(), JSLit(JSLit.makeStringLiteral(\"boolean\")))\n        case Var(\"Str\") if !oldDefs =>\n          JSBinary(\"===\", scrut.typeof(), JSLit(JSLit.makeStringLiteral(\"string\")))\n        case Var(\"bool\") =>\n          JSBinary(\"===\", scrut.member(\"constructor\"), JSLit(\"Boolean\"))\n        case Var(s @ (\"true\" | \"false\")) =>\n          JSBinary(\"===\", scrut, JSLit(s))\n        case Var(\"string\") =>\n          // JS is dumb so `instanceof String` won't actually work on \"primitive\" strings...\n          JSBinary(\"===\", scrut.member(\"constructor\"), JSLit(\"String\"))\n        case Var(name) => scope.resolveValue(name) match {\n          case S(sym: NewClassSymbol) =>\n            JSInstanceOf(scrut, translateNuTypeSymbol(sym, true)) // a is case ClassName(params) -> a instanceof ClassName.class\n          case S(sym: ModuleSymbol) =>\n            JSInstanceOf(scrut, translateNuTypeSymbol(sym, true))\n          case _ => topLevelScope.getType(name) match {\n            case S(ClassSymbol(_, runtimeName, _, _, _)) => JSInstanceOf(scrut, JSIdent(runtimeName))\n            case S(TraitSymbol(_, runtimeName, _, _, _)) => JSIdent(runtimeName)(\"is\")(scrut)\n            case S(_: TypeAliasSymbol) => throw new CodeGenError(s\"cannot match type alias $name\")\n            case _ => throw new CodeGenError(s\"unknown match case: $name\")\n          }\n        }\n        case lit: Lit => JSBinary(\"===\", scrut, translateTerm(lit))\n      },\n      _,\n      _\n    )\n  }\n\n  protected def translateTraitDeclaration(\n      traitSymbol: TraitSymbol\n  )(implicit scope: Scope): JSConstDecl = {\n    import JSCodeHelpers._\n    val instance = id(\"instance\")\n    val bases = traitSymbol.body.collectTypeNames.flatMap { name =>\n      topLevelScope.getType(name) match {\n        case S(t: TraitSymbol) => S(id(t.runtimeName)(\"implement\")(instance).stmt)\n        case S(_: ClassSymbol) | S(_: TypeSymbol) | N => N\n      }\n    }\n    val members = traitSymbol.methods.map { method =>\n      val name = method.nme.name\n      val define = method.rhs.value match {\n        // Define methods for functions.\n        case Lam(params, body) =>\n          val methodScope = scope.derive(s\"Method $name\")\n          val methodParams = translateParams(params)(methodScope)\n          methodScope.declareValue(\"this\", Some(false), false, N)\n          instance(name) := JSFuncExpr(\n            N,\n            methodParams,\n            `return`(translateTerm(body)(methodScope)) :: Nil\n          )\n        // Define getters for pure expressions.\n        case term =>\n          val getterScope = scope.derive(s\"Getter $name\")\n          getterScope.declareValue(\"this\", Some(false), false, N)\n          id(\"Object\")(\"defineProperty\")(\n            instance,\n            JSExpr(name),\n            JSRecord(\n              \"get\" -> JSFuncExpr(\n                N,\n                Nil,\n                `return`(translateTerm(term)(getterScope)) :: Nil\n              ) :: Nil\n            )\n          ).stmt\n      }\n      JSIfStmt(\n        JSExpr(name).binary(\"in\", instance).unary(\"!\"),\n        define :: Nil,\n      )\n    }\n    val implement = JSFuncExpr(\n      S(\"implement\"),\n      param(\"instance\") :: Nil,\n      JSIfStmt(\n        id(\"tag\").binary(\"in\", instance),\n        `return`() :: Nil,\n      )\n        :: id(\"Object\")(\"defineProperty\")(\n          instance,\n          id(\"tag\"),\n          JSRecord(\"value\" -> JSRecord(Nil) :: Nil)\n        ).stmt\n        :: members\n        ::: bases\n    )\n    // function build(instance) {\n    //   if (typeof instance !== \"object\") {\n    //     instance = Object.assign(instance, {});\n    //   }\n    //   this.implement(instance);\n    //   return instance;\n    // }\n    val build = JSFuncExpr(\n      S(\"build\"),\n      param(\"instance\") :: Nil,\n      JSIfStmt(\n        instance.typeof().binary(\"!==\", JSExpr(\"object\")),\n        (instance := id(\"Object\")(\"assign\")(instance, JSRecord(Nil))) :: Nil\n      ) \n        :: id(\"this\")(\"implement\")(instance).stmt\n        :: `return`(instance)\n        :: Nil\n    )\n    val is = JSFuncExpr(\n      S(\"is\"),\n      param(\"x\") :: Nil,\n      `return`(\n        id(\"x\").typeof()\n          .binary(\"===\", JSExpr(\"object\"))\n          .binary(\"&&\", id(\"x\").binary(\"!==\", JSLit(\"null\")))\n          .binary(\"&&\", id(\"tag\").binary(\"in\", id(\"x\")))\n      ) :: Nil\n    )\n    const(\n      traitSymbol.runtimeName,\n      JSFuncExpr(\n        N,\n        Nil,\n        Ls(\n          const(\"tag\", id(\"Symbol\")()),\n          `return` {\n            JSRecord(\"implement\" -> implement :: \"build\" -> build :: \"is\" -> is :: Nil)\n          }\n        )\n      )()\n    )\n  }\n  /**\n    * Translate MLscript class declaration to JavaScript class declaration.\n    * First, we will analyze its fields and base class name.\n    * Then, we will check if the base class exists.\n    */\n  protected def translateClassDeclaration(\n      classSymbol: ClassSymbol,\n      baseClassSymbol: Opt[ClassSymbol]\n  )(implicit scope: Scope): JSClassDecl = {\n    // Translate class methods and getters.\n    val classScope = scope.derive(s\"class ${classSymbol.lexicalName}\")\n    val members = classSymbol.methods.flatMap {\n      translateClassMember(_)(classScope)\n    }\n    // Collect class fields.\n    val fields = classSymbol.body.collectFields ++\n      classSymbol.body.collectTypeNames.flatMap(resolveTraitFields)\n    val base = baseClassSymbol.map { sym => JSIdent(sym.runtimeName) }\n    val traits = classSymbol.body.collectTypeNames.flatMap {\n      name => scope.getType(name) match {\n        case S(TraitSymbol(_, runtimeName, _, _, _)) => S(runtimeName)\n        case S(_: ClassSymbol) => N\n        case S(_: TypeSymbol) => N\n        case N => N\n      }\n    }\n    JSClassDecl(classSymbol.runtimeName, fields, base, members, traits)\n  }\n\n  protected def translateQualifierDeclaration(qualifier: ValueSymbol): Ls[JSStmt] =\n    if (qualifier.visited)\n      JSConstDecl(qualifier.runtimeName, JSIdent(\"this\")) :: Nil\n    else Nil\n  \n  protected def addNuTypeToGlobalThis(typeDef: NuTypeDef, moduleName: Str) = {\n    import JSCodeHelpers._\n    typeDef match {\n      case NuTypeDef(Mxn, TypeName(nme), _, _, _, _, _, _, _, _) =>\n        JSAssignExpr(id(\"globalThis\").member(nme), JSArrowFn(param(\"base\") :: Nil, L(\n          JSInvoke(id(moduleName).member(nme), id(\"base\") :: Nil)\n        ))).stmt\n      case NuTypeDef(_, TypeName(nme), _, _, _, _, _, _, _, _) =>\n        JSAssignExpr(id(\"globalThis\").member(nme), id(moduleName).member(nme)).stmt\n    }\n  }\n\n  protected def translateLocalNewType(typeDef: NuTypeDef)(implicit scope: Scope): JSConstDecl = {\n    // TODO: support traitSymbols\n    val (traitSymbols, classSymbols, mixinSymbols, moduleSymbols) = declareNewTypeDefs(typeDef :: Nil, N)\n\n    val sym = classSymbols match {\n      case s :: _ => S(s)\n      case Nil => mixinSymbols match {\n        case s :: _ => S(s)\n        case Nil => moduleSymbols match {\n          case s :: _ => S(s)\n          case _ => N\n        }\n      }\n    }\n    sym match {\n      case S(sym: NewClassSymbol) =>\n        val localScope = scope.derive(s\"local ${sym.name}\")\n        val nd = translateNewTypeDefinition(sym, N, false)(localScope)\n        val ctorMth = localScope.declareValue(\"ctor\", Some(false), false, N).runtimeName\n        val (constructor, params) = translateNewClassParameters(nd)\n        val initList =\n          if (sym.isPlainJSClass)\n            Ls(JSReturnStmt(S(JSIdent(sym.name))))\n          else\n            Ls(\n              JSLetDecl.from(Ls(ctorMth)),\n              JSAssignExpr(JSIdent(ctorMth), JSArrowFn(constructor, L(JSInvoke(JSNew(JSIdent(sym.name)), params)))).stmt,\n              JSExprStmt(JSAssignExpr(JSIdent(ctorMth).member(\"class\"), JSIdent(sym.name))),\n              JSReturnStmt(S(JSIdent(ctorMth)))\n            )\n        JSConstDecl(sym.name, JSImmEvalFn(\n          N, Nil, R(nd :: initList), Nil\n        ))\n      case S(sym: MixinSymbol) =>\n        val localScope = scope.derive(s\"local ${sym.name}\")\n        val base = localScope.declareValue(\"base\", Some(false), false, N)\n        val nd = translateNewTypeDefinition(sym, S(base), false)(localScope)\n        JSConstDecl(sym.name, JSArrowFn(\n          Ls(JSNamePattern(base.runtimeName)), R(Ls(\n            JSReturnStmt(S(JSClassExpr(nd)))\n          ))\n        ))\n      case S(sym: ModuleSymbol) =>\n        val localScope = scope.derive(s\"local ${sym.name}\")\n        val nd = translateNewTypeDefinition(sym, N, false)(localScope)\n        val ins = localScope.declareValue(\"ins\", Some(false), false, N).runtimeName\n        JSConstDecl(sym.name, JSImmEvalFn(\n          N, Nil, R(Ls(\n            nd, JSLetDecl.from(Ls(ins)),\n            JSAssignExpr(JSIdent(ins), JSInvoke(JSNew(JSIdent(sym.name)), Nil)).stmt,\n            JSExprStmt(JSAssignExpr(JSIdent(ins).member(\"class\"), JSIdent(sym.name))),\n            JSReturnStmt(S(JSIdent(ins)))\n          )), Nil\n        ))\n      case _ => throw CodeGenError(s\"unsupported NuTypeDef in local blocks: $typeDef\")\n    }\n  }\n\n  protected def translateMixinDeclaration(\n      mixinSymbol: MixinSymbol,\n      siblingsMembers: Ls[RuntimeSymbol]\n  )(implicit getterScope: Scope): JSClassMethod = {\n    val base = getterScope.declareValue(\"base\", Some(false), false, N)\n\n    val classBody = translateNewTypeDefinition(mixinSymbol, S(base), false)(getterScope)\n    val qualifierStmt = mixinSymbol.qualifier.fold[JSConstDecl](die)(qualifier => JSConstDecl(qualifier, JSIdent(\"this\")))\n    JSClassMethod(mixinSymbol.name, Ls(JSNamePattern(base.runtimeName)),\n      R((qualifierStmt :: Nil) ::: Ls(JSReturnStmt(S(JSClassExpr(classBody)))\n      ))\n    )\n  }\n\n  private def translateParents(superFields: Ls[Term], constructorScope: Scope)(implicit scope: Scope): Opt[JSExpr] = {\n    def translateParent(current: Term, base: JSExpr, mixinOnly: Bool): JSExpr = {\n      def resolveName(term: Term): Str = term match {\n        case App(lhs, _) => resolveName(lhs)\n        case Var(name) => name\n        case Sel(_, Var(fieldName)) => fieldName\n        case TyApp(lhs, _) => resolveName(lhs)\n        case _ => throw CodeGenError(\"unsupported parents.\")\n      }\n\n      val name = resolveName(current)\n\n      scope.resolveValue(name) match {\n        case Some(_: TraitSymbol) => base // TODO:\n        case Some(sym: MixinSymbol) =>\n          JSInvoke(translateNuTypeSymbol(sym, true), Ls(base)) // class D() extends B -> class D extends B.class\n        case Some(sym: NuTypeSymbol) if !mixinOnly =>\n          translateNuTypeSymbol(sym, true)\n        case Some(t) => throw CodeGenError(s\"unexpected parent symbol $t.\")\n        case N => throw CodeGenError(s\"unresolved parent $name.\")\n      }\n    }\n\n    // for non-first parent classes, they must be mixins or we would get more than one parent classes,\n    // which is not allowed in JS\n    superFields match {\n      case head :: tail => S(tail.foldLeft(\n        translateParent(head, JSIdent(\"Object\"), false)\n      )((res, next) => translateParent(next, res, true)))\n      case Nil => N\n    }\n  }\n\n  protected def translateTopModuleDeclaration(\n    moduleSymbol: ModuleSymbol,\n    keepTopLevelScope: Bool\n  )(implicit scope: Scope): JSClassNewDecl =\n    translateNewTypeDefinition(moduleSymbol, N, keepTopLevelScope)\n\n  protected def translateModuleDeclaration(\n      moduleSymbol: ModuleSymbol,\n      siblingsMembers: Ls[RuntimeSymbol]\n  )(implicit getterScope: Scope): JSClassGetter = {\n    val decl = translateNewTypeDefinition(moduleSymbol, N, false)(getterScope)\n    val privateIdent = JSIdent(s\"this.#${moduleSymbol.name}\")\n    val qualifierStmt = moduleSymbol.qualifier.fold[JSConstDecl](die)(qualifier => JSConstDecl(qualifier, JSIdent(\"this\")))\n    JSClassGetter(moduleSymbol.name, R((qualifierStmt :: Nil) :::\n      Ls(\n        JSIfStmt(JSBinary(\"===\", privateIdent, JSIdent(\"undefined\")), Ls(\n          decl,\n          JSExprStmt(JSAssignExpr(privateIdent,\n            JSNew(JSInvoke(JSIdent(moduleSymbol.name), Nil)))),\n          JSExprStmt(JSAssignExpr(privateIdent.member(\"class\"), JSIdent(moduleSymbol.name))),\n        )),\n        JSReturnStmt(S(privateIdent))\n      )))\n  }\n\n  protected def translateNewClassParameters(classBody: JSClassNewDecl) = {\n    val constructor = classBody.ctorParams.map(JSNamePattern(_))\n    val params = classBody.ctorParams.map(JSIdent(_))\n    (constructor, params)\n  }\n\n  protected def translateNewClassDeclaration(\n      classSymbol: NewClassSymbol,\n      siblingsMembers: Ls[RuntimeSymbol]\n  )(implicit getterScope: Scope): JSClassGetter = {\n    val classBody =\n      translateNewTypeDefinition(classSymbol, N, false)(getterScope)\n    val (constructor, params) = translateNewClassParameters(classBody)\n\n    val privateIdent = JSIdent(s\"this.#${classSymbol.name}\")\n    val qualifierStmt = classSymbol.qualifier.fold[JSConstDecl](die)(qualifier => JSConstDecl(qualifier, JSIdent(\"this\")))\n    val initList =\n      if (classSymbol.isPlainJSClass)\n        Ls(JSExprStmt(JSAssignExpr(privateIdent, JSIdent(classSymbol.name))))\n      else\n        Ls(\n          JSExprStmt(JSAssignExpr(privateIdent,\n            JSArrowFn(constructor, L(\n              JSInvoke(JSIdent(\"Object\").member(\"freeze\"), Ls(JSInvoke(JSNew(JSIdent(classSymbol.name)), params)))\n            )))),\n          JSExprStmt(JSAssignExpr(privateIdent.member(\"class\"), JSIdent(classSymbol.name))),\n          JSExprStmt(JSAssignExpr(privateIdent.member(\"unapply\"), JSIdent(classSymbol.name).member(\"unapply\")))\n        )\n    JSClassGetter(classSymbol.name, R(qualifierStmt :: Ls(\n      JSIfStmt(JSBinary(\"===\", privateIdent, JSIdent(\"undefined\")),\n        JSExprStmt(JSClassExpr(classBody)) :: initList),\n      JSReturnStmt(S(privateIdent))\n    )))\n  }\n\n  protected def translateNewTypeDefinition(\n    sym: TypeSymbol with NuTypeSymbol,\n    baseSym: Opt[ValueSymbol],\n    keepTopLevelScope: Bool\n  )(implicit scope: Scope): JSClassNewDecl = {\n    // * nuTypeScope: root scope\n    // ** inheritanceScope: contains specialized parameters for `super(...)`\n    // ** bodyScope: contains the part of the class between the `{...}`\n    // *** constructorScope: contains variables in the ctor statements\n    // *** memberScopes: contains member methods and variables\n    val nuTypeScope = scope.derive(sym.toString)\n    val inheritanceScope = nuTypeScope.derive(s\"${sym.name} inheritance\")\n    val bodyScope = nuTypeScope.derive(s\"${sym.name} body\")\n    val constructorScope = bodyScope.derive(s\"${sym.name} constructor\")\n\n    val memberList = ListBuffer[RuntimeSymbol]() // pass to the getter of nested types\n    val typeList = ListBuffer[Str]()\n\n    // Store the scope for each member and the qualifier's name in the corresponding scope\n    // Avoid `m._1` or `m._2` in the following code\n    final case class QualifierPack(memberScope: Scope, qualifier: Str)\n\n    val qualifierName = \"qualifier\"\n    val memberScopes = (sym.nested.map(nd => {\n      val memberScope = bodyScope.derive(s\"member ${nd.name}\")\n      val sym = memberScope.declareQualifierSymbol(qualifierName)\n      nd.name -> QualifierPack(memberScope, sym)\n    }) ++ sym.methods.map(m => {\n      val memberScope = bodyScope.derive(s\"member ${m.nme.name}\")\n      val sym = memberScope.declareQualifierSymbol(qualifierName)\n      m.nme.name -> QualifierPack(memberScope, sym)\n    })).toMap\n\n    // `qualifier` should always be the first value in the getter scope so all qualifiers should have the same name!\n    val qualifier = memberScopes.values.headOption.fold(S(constructorScope.declareQualifierSymbol(qualifierName)))(mh => {\n      memberScopes.values.foreach(m =>\n        assert(m.qualifier === mh.qualifier, s\"the expected qualifier's runtime name should be ${mh.qualifier}, ${m.qualifier} found\")\n      )\n      assert(constructorScope.declareQualifierSymbol(mh.qualifier) === mh.qualifier)\n      S(mh.qualifier)\n    })\n\n    val fields = sym.matchingFields ++\n      sym.body.collectTypeNames.flatMap(resolveTraitFields)\n\n    val getters = new ListBuffer[Bool -> Str]() // mut -> name\n\n    val ctorParams = sym.ctorParams.fold(\n      fields.map { f =>\n          memberList += NewClassMemberSymbol(f, Some(false), false, !sym.publicCtors.contains(f), qualifier).tap(bodyScope.register)\n          inheritanceScope.declareValue(f, Some(false), false, N).runtimeName\n          constructorScope.declareValue(f, Some(false), false, N).runtimeName\n        }\n      )(lst => lst.map { p =>\n          if (p._2) { // `constructor(val name)` will also generate a field and a getter\n            memberList += NewClassMemberSymbol(p._1, Some(false), false, false, qualifier).tap(bodyScope.register)\n            getters += false -> p._1\n          }\n          constructorScope.declareValue(p._1, Some(false), false, N).runtimeName // Otherwise, it is only available in the constructor\n        })\n    \n    val initFields = getters.toList.map { case (mut, name) =>\n      JSAssignExpr(JSIdent(s\"this.#$name\"), JSIdent(name)).stmt }\n\n    sym.methods.foreach(\n      md => memberList += NewClassMemberSymbol(md.nme.name, N, true, false, qualifier).tap(bodyScope.register)\n    )\n    sym.signatures.foreach(\n      md => memberList += bodyScope.declareStubValue(md.nme.name, N)(true)\n    )\n    sym.ctor.foreach {\n      case nd @ NuFunDef(rec, Var(nme), _, _, _) =>\n        memberList += NewClassMemberSymbol(nme, rec, false, !nd.genField, qualifier).tap(bodyScope.register)\n      case _ => ()\n    }\n\n    // TODO: support traitSymbols\n    val (traitSymbols, classSymbols, mixinSymbols, moduleSymbols) = declareNewTypeDefs(sym.nested, qualifier)(bodyScope)\n\n    if (keepTopLevelScope) // also declare in the top level for diff tests\n      declareNewTypeDefs(sym.nested, N)(topLevelScope)\n    classSymbols.foreach(s => {memberList += s; typeList += s.name})\n    mixinSymbols.foreach(s => {memberList += s;})\n    moduleSymbols.foreach(s => {memberList += s; typeList += s.name})\n    val members = sym.methods.map(m => translateNewClassMember(m, fields, qualifier)(memberScopes.getOrElse(m.nme.name, die).memberScope)) ++\n      mixinSymbols.map(s => translateMixinDeclaration(s, memberList.toList)(memberScopes.getOrElse(s.name, die).memberScope)) ++\n      moduleSymbols.map(s => translateModuleDeclaration(s, memberList.toList)(memberScopes.getOrElse(s.name, die).memberScope)) ++\n      classSymbols.map(s => translateNewClassDeclaration(s, memberList.toList)(memberScopes.getOrElse(s.name, die).memberScope))\n\n    val base: Opt[JSExpr] = baseSym match {\n      case Some(base) => S(JSIdent(base.runtimeName))\n      case _ => translateParents(sym.superParameters, inheritanceScope)\n    }\n\n    val traits = sym.body.collectTypeNames.flatMap {\n      name => scope.getType(name) match {\n        case S(TraitSymbol(_, runtimeName, _, _, _)) => S(runtimeName)\n        case S(_: ClassSymbol) => N\n        case S(_: TypeSymbol) => N\n        case N => N\n      }\n    }\n\n    val (superParameters, rest) = if (baseSym.isDefined) {\n      val rest = constructorScope.declareValue(\"rest\", Some(false), false, N)\n      (Ls(JSIdent(s\"...${rest.runtimeName}\")), S(rest.runtimeName))\n    }\n    else\n      (sym.superParameters.map {\n        case App(lhs, Tup(rhs)) => rhs map {\n          case (_, Fld(_, trm)) => translateTerm(trm)(inheritanceScope)\n        }\n        case _ => Nil\n      }.flatMap(_.reverse).reverse, N)\n\n    val privateMems = new ListBuffer[Str]()\n    val stmts = sym.ctor.flatMap {\n      case Eqn(Var(name), rhs) => Ls(\n        JSAssignExpr(JSIdent(s\"this.#$name\"), translateTerm(rhs)(constructorScope)).stmt,\n        JSConstDecl(constructorScope.declareValue(name, S(false), false, N).runtimeName, JSIdent(s\"this.#$name\"))\n      )\n      case s: Term => JSExprStmt(translateTerm(s)(constructorScope)) :: Nil\n      case nd @ NuFunDef(_, Var(nme), _, _, Left(rhs)) =>\n        if (nd.genField) {\n          getters += nd.isMut -> nme\n          Ls[JSStmt](\n            JSExprStmt(JSAssignExpr(JSIdent(s\"this.#$nme\"), translateTerm(rhs)(constructorScope))),\n            JSConstDecl(constructorScope.declareValue(nme, S(false), false, N).runtimeName, JSIdent(s\"this.#$nme\"))\n          )\n        }\n        else {\n          val sym = bodyScope.resolveValue(nme) match {\n            case Some(sym: NewClassMemberSymbol) => sym\n            case _ => throw new AssertionError(s\"error when handling $nme\")\n          }\n          if (sym.visited || ctorParams.contains(nme)) { // This field is used in other methods, or it overrides the ctor parameter\n            privateMems += nme\n            Ls[JSStmt](\n              JSExprStmt(JSAssignExpr(JSIdent(s\"this.#$nme\"), translateTerm(rhs)(constructorScope))),\n              JSConstDecl(constructorScope.declareValue(nme, S(false), false, N).runtimeName, JSIdent(s\"this.#$nme\"))\n            )\n          }\n          else\n            JSConstDecl(constructorScope.declareValue(nme, S(false), false, N).runtimeName,\n              translateTerm(rhs)(constructorScope)) :: Nil\n        }\n      case _ => Nil\n    }\n\n    val tempDecs = constructorScope.tempVars.emit() match {\n      case S(decs) => decs :: Nil\n      case _ => Nil\n    }\n\n    val staticMethods = sym.unapplyMtd match {\n      // * Note: this code is a bad temporary hack until we have proper `unapply` desugaring\n      case S(unapplyMtd) => unapplyMtd.rhs match {\n        case Left(Lam(Tup(_ -> Fld(_, Var(nme)) :: Nil), Let(_, _, _, Tup(fields)))) =>\n          val unapplyScope = nuTypeScope.derive(s\"unapply ${sym.name}\")\n          val ins = unapplyScope.declareParameter(nme)\n          JSClassMethod(\"unapply\", JSNamePattern(ins) :: Nil, L(JSArray(fields.map {\n            case _ -> Fld(_, trm) => trm match {\n              case Sel(Var(ins), Var(f)) => JSIdent(s\"$ins.$f\")\n              case _ => translateTerm(trm)\n            } \n          }))) :: Nil\n        case _ => throw CodeGenError(s\"invalid unapply method in ${sym.name}\")\n      }\n      case _ => Nil\n    }\n\n    val qualifierStmt = qualifier.fold[Ls[JSStmt]](Nil)(qualifier =>\n      translateQualifierDeclaration(constructorScope.resolveQualifier(qualifier)))\n    JSClassNewDecl(\n      sym.name,\n      fields,\n      fields.filter(sym.publicCtors.contains(_)).map(false -> _) ++ getters.toList,\n      privateMems.toList ++ fields,\n      base,\n      superParameters,\n      ctorParams,\n      rest,\n      members,\n      traits,\n      qualifierStmt ++ tempDecs ++ initFields ++ stmts,\n      typeList.toList,\n      sym.ctorParams.isDefined,\n      staticMethods\n    )\n  }\n\n  /**\n   * Translate class methods and getters.\n   */\n  private def translateClassMember(\n      method: MethodDef[Left[Term, Type]],\n  )(implicit scope: Scope): Ls[JSClassMemberDecl] = {\n    val name = method.nme.name\n    // Create the method/getter scope.\n    val memberScope = method.rhs.value match {\n      case _: Lam => scope.derive(s\"method $name\")\n      case _ => scope.derive(s\"getter $name\")\n    }\n    // Declare the alias for `this` before declaring parameters.\n    val selfSymbol = memberScope.declareThisAlias()\n    // Declare parameters.\n    val (memberParams, body) = method.rhs.value match {\n      case Lam(params, body) =>\n        val methodParams = translateParams(params)(memberScope)\n        (S(methodParams), body)\n      case term =>\n        (N, term)\n    }\n    // Translate class member body.\n    val bodyResult = translateTerm(body)(memberScope).`return`\n    // If `this` is accessed, add `const self = this`.\n    val bodyStmts = if (selfSymbol.visited) {\n      val thisDecl = JSConstDecl(selfSymbol.runtimeName, JSIdent(\"this\"))\n      R(thisDecl :: bodyResult :: Nil)\n    } else {\n      R(bodyResult :: Nil)\n    }\n    // Returns members depending on what it is.\n    memberParams match {\n      case S(memberParams) => JSClassMethod(name, memberParams, bodyStmts) :: Nil\n      case N => JSClassGetter(name, bodyStmts) :: Nil\n    }\n  }\n\n  private def translateNewClassMember(\n    method: MethodDef[Left[Term, Type]],\n    props: Ls[Str], // for overriding\n    qualifier: Opt[Str]\n  )(implicit memberScope: Scope): JSClassMemberDecl = {\n    val name = method.nme.name\n    val preDecs = props.map(p => {\n      val runtime = memberScope.declareValue(p, Some(false), false, N)\n      JSConstDecl(runtime.runtimeName, JSIdent(s\"this.#$p\"))\n    })\n    // Declare parameters.\n    val (memberParams, body) = method.rhs.value match {\n      case Lam(params, body) =>\n        val methodParams = translateParams(params)(memberScope)\n        (S(methodParams), body)\n      case term =>\n        (N, term)\n    }\n    // Translate class member body.\n    val bodyResult = translateTerm(body)(memberScope).`return`\n    val tempDecs = memberScope.tempVars.emit() match {\n      case S(decs) => decs :: Nil\n      case _ => Nil\n    }\n\n    val qualifierStmts = qualifier.fold[Ls[JSStmt]](Nil)(qualifier =>\n      translateQualifierDeclaration(memberScope.resolveQualifier(qualifier)))\n\n    val bodyStmts = R(preDecs ++ tempDecs ++ qualifierStmts ++ (bodyResult :: Nil))\n    // Returns members depending on what it is.\n    memberParams match {\n      case S(memberParams) => JSClassMethod(name, memberParams, bodyStmts)\n      case N => JSClassGetter(name, bodyStmts)\n    }\n  }\n\n  /**\n    * Declare symbols for types, traits and classes.\n    * Call this before the code generation.\n    * \n    * @return defined class symbols\n    */\n  protected def declareTypeDefs(typeDefs: Ls[TypeDef]): (Ls[TraitSymbol], Ls[ClassSymbol]) = {\n    val traits = new ListBuffer[TraitSymbol]()\n    val classes = new ListBuffer[ClassSymbol]()\n    typeDefs.foreach {\n      case TypeDef(Als, TypeName(name), tparams, body, _, _, _, _) =>\n        topLevelScope.declareTypeAlias(name, tparams map { _.name }, body)\n      case TypeDef(Trt, TypeName(name), tparams, body, _, methods, _, _) =>\n        traits += topLevelScope.declareTrait(name, tparams map { _.name }, body, methods)\n      case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _, _) =>\n        classes += topLevelScope.declareClass(name, tparams map { _.name }, baseType, members)\n      case TypeDef(Mxn, _, _, _, _, _, _, _) => throw CodeGenError(\"Mixins are not supported yet.\")\n      case TypeDef(Mod, _, _, _, _, _, _, _) => throw CodeGenError(\"Namespaces are not supported yet.\")\n    }\n    (traits.toList, classes.toList)\n  }\n\n  protected def declareNewTypeDefs(typeDefs: Ls[NuTypeDef], qualifier: Opt[Str])(implicit scope: Scope):\n      (Ls[TraitSymbol], Ls[NewClassSymbol], Ls[MixinSymbol], Ls[ModuleSymbol]) = {\n    \n    val traits = new ListBuffer[TraitSymbol]()\n    val classes = new ListBuffer[NewClassSymbol]()\n    val mixins = new ListBuffer[MixinSymbol]()\n    val modules = new ListBuffer[ModuleSymbol]()\n    \n    def tt(trm: Term): Type = trm.toType match {\n      case L(ds) => Top\n      case R(ty) => ty\n    }\n\n    def prepare(nme: Str, fs: Ls[Opt[Var] -> Fld], pars: Ls[Term], unit: TypingUnit) = {\n      val params = fs.map {\n        case (S(nme), Fld(FldFlags(mut, spec, _), trm)) =>\n          val ty = tt(trm)\n          nme -> Field(if (mut) S(ty) else N, ty)\n        case (N, Fld(FldFlags(mut, spec, _), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top)\n        case _ => die\n      }\n      val publicCtors = fs.filter {\n        case (_, Fld(flags, _)) => flags.genGetter\n        case _ => false\n      }.map {\n        case (S(name), _) => name.name\n        case (N, Fld(_, nme: Var)) => nme.name\n        case _ => die\n      }\n\n      val body = pars.map(tt).foldRight(Record(params): Type)(Inter)\n      val implemented = new HashSet[Str]()\n      val members = unit.entities.collect {\n        case NuFunDef(isLetRec, mnme, _, tys, Left(rhs)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) =>\n          implemented.add(mnme.name)\n          MethodDef[Left[Term, Type]](isLetRec.getOrElse(false), TypeName(nme), mnme, tys, Left(rhs))\n      }\n\n      val signatures = unit.entities.collect {\n        case nd @ NuFunDef(isLetRec, mnme, _, tys, Right(rhs)) if nd.genField && !implemented.contains(mnme.name) =>\n          MethodDef[Right[Term, Type]](isLetRec.getOrElse(false), TypeName(nme), mnme, tys, Right(rhs))\n      }\n\n      val stmts = unit.entities.filter {\n        case Asc(Var(\"this\"), _) => false\n        case Asc(Super(), _) => false\n        case NuFunDef(S(false), _, _, _, Left(rhs)) => true\n        case _: Term => true\n        case _ => false\n      }\n\n      val nested = unit.entities.collect {\n        case nd: NuTypeDef => nd\n      }\n      \n      (body, members, signatures, stmts, nested, publicCtors)\n    }\n\n    typeDefs.foreach {\n      case td @ NuTypeDef(Mxn, TypeName(mxName), tps, tup, ctor, sig, pars, sup, ths, unit) => {\n        val (body, members, signatures, stmts, nested, publicCtors) = prepare(mxName, tup.getOrElse(Tup(Nil)).fields, pars, unit)\n        val sym = MixinSymbol(mxName, tps map { _._2.name }, body, members, signatures, stmts, publicCtors, nested, qualifier).tap(scope.register)\n        if (!td.isDecl) mixins += sym\n      }\n      case td @ NuTypeDef(Mod, TypeName(nme), tps, tup, ctor, sig, pars, sup, ths, unit) => {\n        val (body, members, signatures, stmts, nested, _) = prepare(nme, tup.getOrElse(Tup(Nil)).fields, pars, unit)\n        val sym = ModuleSymbol(nme, tps map { _._2.name }, body, members, signatures, stmts, pars, nested, qualifier).tap(scope.register)\n        if (!td.isDecl) modules += sym\n      }\n      case td @ NuTypeDef(Als, TypeName(nme), tps, _, ctor, sig, pars, _, _, _) => {\n        scope.declareTypeAlias(nme, tps map { _._2.name }, sig.getOrElse(Top))\n      }\n      case td @ NuTypeDef(Cls, TypeName(nme), tps, tup, ctor, sig, pars, sup, ths, unit) => {\n        val (params, preStmts) = ctor match {\n          case S(Constructor(Tup(ls), Blk(stmts))) => (S(ls.map {\n            case (S(Var(nme)), Fld(flags, _)) => (nme, flags.genGetter)\n            case (N, Fld(flags, Var(nme))) => (nme, flags.genGetter)\n            case _ => throw CodeGenError(s\"Unexpected constructor parameters in $nme.\")\n          }), stmts)\n          case _ => (N, Nil)\n        }\n        val (body, members, signatures, stmts, nested, publicCtors) = prepare(nme, tup.getOrElse(Tup(Nil)).fields, pars, unit)\n        val sym =\n          NewClassSymbol(nme, tps map { _._2.name }, params, body, members, td.genUnapply match {\n            case S(NuFunDef(isLetRec, mnme, _, tys, Left(rhs))) =>\n              S(MethodDef[Left[Term, Type]](isLetRec.getOrElse(false), TypeName(nme), mnme, tys, Left(rhs)))\n            case _ => N\n          }, signatures, preStmts ++ stmts, pars, publicCtors, nested, qualifier, td.isPlainJSClass).tap(scope.register)\n        if (!td.isDecl) classes += sym\n      }\n      case td @ NuTypeDef(Trt, TypeName(nme), tps, tup, ctor, sig, pars, sup, ths, unit) => {\n        val (body, members, _, _, _, _) = prepare(nme, tup.getOrElse(Tup(Nil)).fields, pars, unit)\n        val sym = scope.declareTrait(nme, tps map { _._2.name }, body, members)\n        if (!td.isDecl) traits += sym\n      }\n    }\n    (traits.toList, classes.toList, mixins.toList, modules.toList)\n  }\n\n  /**\n    * Recursively collect fields from trait definitions.\n    * Caveat: this might cause stack overflow if cyclic inheritance exists.\n    */\n  private def resolveTraitFields(name: Str): Ls[Str] =\n    topLevelScope.getType(name) match {\n      case S(sym: TraitSymbol) => sym.body.collectFields ++ resolveTraitFields(sym)\n      case S(_: TypeSymbol) | S(_: ClassSymbol) | N => Nil\n    }\n\n  /**\n    * Recursively collect fields from trait definitions.\n    * Caveat: this might cause stack overflow if cyclic inheritance exists.\n    */\n  private def resolveTraitFields(sym: TraitSymbol): Ls[Str] =\n    sym.body.collectTypeNames.flatMap(resolveTraitFields)\n\n  /**\n    * Find the base class for a specific class.\n    */\n  private def resolveBaseClass(ty: Type): Opt[ClassSymbol] = {\n    val baseClasses = ty.collectTypeNames.flatMap { name =>\n      topLevelScope.getType(name) match {\n        case S(sym: ClassSymbol) => S(sym)\n        case S(sym: TraitSymbol) => N // TODO: inherit from traits\n        case S(sym: TypeAliasSymbol) =>\n          throw new CodeGenError(s\"cannot inherit from type alias $name\" )\n        case S(_: NuTypeSymbol) =>\n          throw new CodeGenError(s\"NuType symbol $name is not supported when resolving base classes\")\n        case N =>\n          throw new CodeGenError(s\"undeclared type name $name when resolving base classes\")\n      }\n    }\n    if (baseClasses.lengthIs > 1)\n      throw CodeGenError(\n        s\"cannot have ${baseClasses.length} base classes: \" +\n        baseClasses.map { _.lexicalName }.mkString(\", \")\n      )\n    else\n      baseClasses.headOption\n  }\n\n  /**\n    * Resolve inheritance of all declared classes.\n    * \n    * @return sorted class symbols with their base classes\n    */\n  protected def sortClassSymbols(classSymbols: Ls[ClassSymbol]): Iterable[(ClassSymbol, Opt[ClassSymbol])] = {\n    // Cache base classes for class symbols.\n    val baseClasses = Map.from(classSymbols.iterator.flatMap { derivedClass =>\n      topLevelScope.resolveBaseClass(derivedClass.body).map(derivedClass -> _)\n    })\n    val sorted = try topologicalSort(baseClasses, classSymbols) catch {\n      case e: CyclicGraphError => throw CodeGenError(\"cyclic inheritance detected\")\n    }\n    // Their base classes might be class symbols defined in previous translation\n    // units. So we filter them out here.\n    sorted.flatMap(sym => if (classSymbols.contains(sym)) S(sym -> baseClasses.get(sym)) else N)\n  }\n  \n}\n\nclass JSWebBackend extends JSBackend {\n  override def oldDefs: Bool = false\n  \n  // Name of the array that contains execution results\n  val resultsName: Str = topLevelScope declareRuntimeSymbol \"results\"\n\n  val prettyPrinterName: Str = topLevelScope declareRuntimeSymbol \"prettyPrint\"\n\n  polyfill.use(\"prettyPrint\", prettyPrinterName)\n\n  private def generate(pgrm: Pgrm): (Ls[Str], Ls[Str]) = {\n    val (diags, (typeDefs, otherStmts)) = pgrm.desugared\n\n    val (traitSymbols, classSymbols) = declareTypeDefs(typeDefs)\n    val defStmts = \n      traitSymbols.map { translateTraitDeclaration(_)(topLevelScope) } ++\n      sortClassSymbols(classSymbols).map { case (derived, base) =>\n        translateClassDeclaration(derived, base)(topLevelScope)\n      }.toList\n\n    val resultsIdent = JSIdent(resultsName)\n    val stmts: Ls[JSStmt] =\n      JSConstDecl(resultsName, JSArray(Nil)) ::\n        defStmts\n        // Generate something like:\n        // ```js\n        // const <name> = <expr>;\n        // <results>.push(<name>);\n        // ```\n        .concat(otherStmts.flatMap {\n          case Def(recursive, Var(name), L(body), isByname) =>\n            val (originalExpr, sym) = if (recursive) {\n              val isByvalueRecIn = if (isByname) None else Some(true)\n              val sym = topLevelScope.declareValue(name, isByvalueRecIn, body.isLam, N)\n              val translated = translateTerm(body)(topLevelScope)\n              topLevelScope.unregisterSymbol(sym)\n              val isByvalueRecOut = if (isByname) None else Some(false)\n              (translated, topLevelScope.declareValue(name, isByvalueRecOut, body.isLam, N))\n            } else {\n              val translatedBody = translateTerm(body)(topLevelScope)\n              val isByvalueRec = if (isByname) None else Some(false)\n              (translatedBody, topLevelScope.declareValue(name, isByvalueRec, body.isLam, N))\n            }\n            val translatedBody = if (sym.isByvalueRec.isEmpty && !sym.isLam) JSArrowFn(Nil, L(originalExpr)) else originalExpr\n            topLevelScope.tempVars `with` JSConstDecl(sym.runtimeName, translatedBody) ::\n              JSInvoke(resultsIdent(\"push\"), JSIdent(sym.runtimeName) :: Nil).stmt :: Nil\n          // Ignore type declarations.\n          case Def(_, _, R(_), isByname) => Nil\n          // `exprs.push(<expr>)`.\n          case term: Term =>\n            topLevelScope.tempVars `with` JSInvoke(\n              resultsIdent(\"push\"),\n              translateTerm(term)(topLevelScope) :: Nil\n            ).stmt :: Nil\n        })\n    val epilogue = resultsIdent.member(\"map\")(JSIdent(prettyPrinterName)).`return` :: Nil\n    (JSImmEvalFn(N, Nil, R(polyfill.emit() ::: stmts ::: epilogue), Nil).toSourceCode.toLines, Nil)\n  }\n\n  private def generateNewDef(pgrm: Pgrm): (Ls[Str], Ls[Str]) = {\n    \n    val (typeDefs, otherStmts) = pgrm.tops.partitionMap {\n      case ot: Terms => R(ot)\n      case fd: NuFunDef => R(fd)\n      case nd: NuTypeDef => L(nd)\n      case _ => die\n   }\n\n    // don't pass `otherStmts` to the top-level module, because we need to execute them one by one later\n    val topModule = topLevelScope.declareTopModule(\"TypingUnit\", Nil, typeDefs, true)\n    val moduleIns = topLevelScope.declareValue(\"typing_unit\", Some(false), false, N)\n    val moduleDecl = translateTopModuleDeclaration(topModule, true)(topLevelScope)\n    val insDecl =\n      JSConstDecl(moduleIns.runtimeName, JSNew(JSIdent(topModule.name)))\n\n    val includes = typeDefs.filter(!_.isDecl).map(addNuTypeToGlobalThis(_, moduleIns.runtimeName))\n\n    val resultsIdent = JSIdent(resultsName)\n    val resultNames = ListBuffer[Str]()\n    val stmts: Ls[JSStmt] =\n      JSConstDecl(resultsName, JSArray(Nil)) ::\n        (moduleDecl :: insDecl :: includes)\n        // Generate something like:\n        // ```js\n        // const <name> = <expr>;\n        // <results>.push(<name>);\n        // ```\n        .concat(otherStmts.flatMap {\n          case NuFunDef(isLetRec, nme @ Var(name), symNme, tys, rhs @ L(body)) =>\n            val recursive = isLetRec.getOrElse(true)\n            val isByname = isLetRec.isEmpty\n            val symb = symNme.map(_.name)\n            val (originalExpr, sym) = (if (recursive) {\n              val isByvalueRecIn = if (isByname) None else Some(true)\n              \n              // TODO Improve: (Lionel) what?!\n              val sym = topLevelScope.declareValue(name, isByvalueRecIn, body.isLam, N)\n              val translated = translateTerm(body)(topLevelScope)\n              topLevelScope.unregisterSymbol(sym)\n              \n              val isByvalueRecOut = if (isByname) None else Some(false)\n              (translated, topLevelScope.declareValue(name, isByvalueRecOut, body.isLam, symb))\n            } else {\n              val translated = translateTerm(body)(topLevelScope)\n              val isByvalueRec = if (isByname) None else Some(false)\n              (translated, topLevelScope.declareValue(name, isByvalueRec, body.isLam, symb))\n            })\n            val translatedBody = if (sym.isByvalueRec.isEmpty && !sym.isLam) JSArrowFn(Nil, L(originalExpr)) else originalExpr\n            resultNames += sym.runtimeName\n            topLevelScope.tempVars `with` JSConstDecl(sym.runtimeName, translatedBody) ::\n              JSInvoke(resultsIdent(\"push\"), JSIdent(sym.runtimeName) :: Nil).stmt :: Nil\n          case fd @ NuFunDef(isLetRec, Var(name), _, tys, R(ty)) =>\n            Nil\n          case _: Def | _: TypeDef | _: Constructor =>\n            throw CodeGenError(\"Def and TypeDef are not supported in NewDef files.\")\n          case term: Term =>\n            val res = translateTerm(term)(topLevelScope)\n            resultNames += term.show(true)\n            topLevelScope.tempVars `with` JSInvoke(\n              resultsIdent(\"push\"),\n              res :: Nil\n            ).stmt :: Nil\n        })\n    val epilogue = resultsIdent.member(\"map\")(JSIdent(prettyPrinterName)).`return` :: Nil\n    (JSImmEvalFn(N, Nil, R(polyfill.emit() ::: stmts ::: epilogue), Nil).toSourceCode.toLines, resultNames.toList)\n  }\n\n  def apply(pgrm: Pgrm): (Ls[Str], Ls[Str]) =\n    if (!oldDefs) generateNewDef(pgrm) else generate(pgrm)\n}\n\nabstract class JSTestBackend extends JSBackend {\n  \n  private val lastResultSymbol = topLevelScope.declareValue(\"res\", Some(false), false, N)\n  private val resultIdent = JSIdent(lastResultSymbol.runtimeName)\n\n  private var numRun = 0\n\n  /**\n    * Generate a piece of code for test purpose. It can be invoked repeatedly.\n    * `prettyPrintQQ` is a temporary hack due to lack of runtime support and should be removed later.\n    */\n  def apply(pgrm: Pgrm, allowEscape: Bool, isNewDef: Bool, prettyPrintQQ: Bool): JSTestBackend.Result =\n    if (!isNewDef)\n      try generate(pgrm)(topLevelScope, allowEscape) catch {\n        case e: CodeGenError => JSTestBackend.IllFormedCode(e.getMessage())\n        case e: UnimplementedError => JSTestBackend.Unimplemented(e.getMessage())\n        // case NonFatal(e) => JSTestBackend.UnexpectedCrash(e.getClass().getName, e.getMessage())\n      }\n    else\n      try generateNewDef(pgrm, prettyPrintQQ)(topLevelScope, allowEscape) catch {\n        case e: CodeGenError => JSTestBackend.IllFormedCode(e.getMessage())\n        case e: UnimplementedError => JSTestBackend.Unimplemented(e.getMessage())\n        // case NonFatal(e) => JSTestBackend.UnexpectedCrash(e.getClass().getName, e.getMessage())\n      }\n    // generate(pgrm)(topLevelScope, allowEscape)\n\n  /**\n    * Generate JavaScript code which targets MLscript test from the given block.\n    *\n    * @param pgrm the program to translate\n    * @param scope the top-level scope\n    * @param allowEscape whether to try executing code even if it refers to unimplemented definitions\n    * @return\n    */\n  private def generate(pgrm: Pgrm)(implicit scope: Scope, allowEscape: Bool): JSTestBackend.TestCode = {\n    val (diags, (typeDefs, otherStmts)) = pgrm.desugared\n\n    val (traitSymbols, classSymbols) = declareTypeDefs(typeDefs)\n    val defStmts = \n      traitSymbols.map { translateTraitDeclaration(_)(topLevelScope) } ++\n      sortClassSymbols(classSymbols).map { case (derived, base) =>\n        translateClassDeclaration(derived, base)(topLevelScope)\n      }.toList\n\n    val zeroWidthSpace = JSLit(\"\\\"\\\\u200B\\\"\")\n    val catchClause = JSCatchClause(\n      JSIdent(\"e\"),\n      (zeroWidthSpace + JSIdent(\"e\") + zeroWidthSpace).log() :: Nil\n    )\n\n    // Generate statements.\n    val queries = otherStmts.map {\n      case Def(recursive, Var(name), L(body), isByname) =>\n        (if (recursive) {\n          val isByvalueRecIn = if (isByname) None else Some(true)\n          val sym = scope.declareValue(name, isByvalueRecIn, body.isLam, N)\n          try {\n            val translated = translateTerm(body)\n            scope.unregisterSymbol(sym)\n            val isByvalueRecOut = if (isByname) None else Some(false)\n            R((translated, scope.declareValue(name, isByvalueRecOut, body.isLam, N)))\n          } catch {\n            case e: UnimplementedError =>\n              scope.stubize(sym, e.symbol)\n              L(e.getMessage())\n            case NonFatal(e) =>\n              scope.unregisterSymbol(sym)\n              val isByvalueRecOut = if (isByname) None else Some(false)\n              scope.declareValue(name, isByvalueRecOut, body.isLam, N)\n              throw e\n          }\n        } else {\n          (try R(translateTerm(body)) catch {\n            case e: UnimplementedError =>\n              scope.declareStubValue(name, e.symbol, N)\n              L(e.getMessage())\n          }) map {\n            val isByvalueRec = if (isByname) None else Some(false)\n            expr => (expr, scope.declareValue(name, isByvalueRec, body.isLam, N))\n          }\n        }) match {\n          case R((originalExpr, sym)) =>\n            val expr = \n              if (sym.isByvalueRec.isEmpty && !sym.isLam)\n                JSArrowFn(Nil, L(originalExpr))\n              else\n                originalExpr\n            JSTestBackend.CodeQuery(\n              scope.tempVars.emit(),\n              ((JSIdent(\"globalThis\").member(sym.runtimeName) := (expr match {\n                case t: JSArrowFn => t.toFuncExpr(S(sym.runtimeName))\n                case t            => t\n              })) :: Nil),\n              sym.runtimeName\n            )\n          case L(reason) => JSTestBackend.AbortedQuery(reason)\n        }\n      case Def(_, Var(name), _, _) =>\n        scope.declareStubValue(name, N)\n        JSTestBackend.EmptyQuery\n      case term: Term =>\n        try {\n          val body = translateTerm(term)(scope)\n          val res = JSTestBackend.CodeQuery(scope.tempVars.emit(), (resultIdent := body) :: Nil)\n          scope.refreshRes()\n          res\n        } catch {\n          case e: UnimplementedError => JSTestBackend.AbortedQuery(e.getMessage())\n        }\n    }\n\n    // If this is the first time, insert the declaration of `res`.\n    var prelude: Ls[JSStmt] = defStmts\n    if (numRun === 0)\n      prelude = JSLetDecl(lastResultSymbol.runtimeName -> N :: Nil) :: prelude\n\n    // Increase the run number.\n    numRun = numRun + 1\n\n    JSTestBackend.TestCode(SourceCode.fromStmts(polyfill.emit() ::: prelude).toLines, queries)\n  }\n\n  private def generateNewDef(pgrm: Pgrm, prettyPrintQQ: Bool)(implicit scope: Scope, allowEscape: Bool): JSTestBackend.TestCode = {\n  \n    val (typeDefs, otherStmts) = pgrm.tops.partitionMap {\n      case _: Constructor => throw CodeGenError(\"unexpected constructor.\")\n      case ot: Terms => R(ot)\n      case fd: NuFunDef => R(fd)\n      case nd: NuTypeDef => L(nd)\n      case _ => die\n    }\n\n    otherStmts.foreach {\n      case fd @ NuFunDef(isLetRec, Var(nme), symNme, _, L(body)) =>\n        val isByname = isLetRec.isEmpty\n        val isByvalueRecIn = if (isByname) None else Some(true)\n        val symb = symNme.map(_.name)\n        scope.declareValue(nme, isByvalueRecIn, body.isLam, symb, true)\n      case _ => ()\n    }\n    \n    // don't pass `otherStmts` to the top-level module, because we need to execute them one by one later\n    val topModule = topLevelScope.declareTopModule(\"TypingUnit\", Nil, typeDefs, true)\n    val moduleIns = topLevelScope.declareValue(\"typing_unit\", Some(false), false, N)\n    val moduleDecl = translateTopModuleDeclaration(topModule, true)\n    val insDecl =\n      JSConstDecl(moduleIns.runtimeName, JSNew(JSIdent(topModule.runtimeName)))\n\n    val includes = typeDefs.filter(!_.isDecl).map(addNuTypeToGlobalThis(_, moduleIns.runtimeName))\n\n    val zeroWidthSpace = JSLit(\"\\\"\\\\u200B\\\"\")\n    val catchClause = JSCatchClause(\n      JSIdent(\"e\"),\n      (zeroWidthSpace + JSIdent(\"e\") + zeroWidthSpace).log() :: Nil\n    )\n\n    // TODO Improve: (Lionel) I find this logic very strange! What's going on here?\n    //  Why are we declaring some things above AND below?\n    //  Why does the fact that a binding is recursive affect its declaration in the OUTER scope?\n    \n    // Generate statements.\n    val queries = otherStmts.map {\n      case NuFunDef(isLetRec, nme @ Var(name), symNme, tys, rhs @ L(body)) =>\n        val recursive = isLetRec.getOrElse(true)\n        val isByname = isLetRec.isEmpty\n        val symb = symNme.map(_.name)\n        (if (recursive) {\n          val isByvalueRecIn = if (isByname) None else Some(true)\n          val sym = scope.resolveValue(name) match {\n            case Some(s: ValueSymbol) => s\n            case _ => scope.declareValue(name, isByvalueRecIn, body.isLam, symb)\n          }\n          val isByvalueRecOut = if (isByname) None else Some(false)\n          try {\n            val translated = translateTerm(body) // TODO Improve: (Lionel) Why are the bodies translated in the SAME scope?!\n            scope.unregisterSymbol(sym) // TODO Improve: (Lionel) ???\n            R((translated, scope.declareValue(name, isByvalueRecOut, body.isLam, symb)))\n          } catch {\n            case e: UnimplementedError =>\n              scope.stubize(sym, e.symbol)\n              L(e.getMessage())\n            case NonFatal(e) =>\n              scope.unregisterSymbol(sym) // TODO Improve: (Lionel) You should only try/catch around the part that may actually fail, and if `unregisterSymbol` should always be called, that should be done in `finally`... but the very logic of calling `unregisterSymbol` is very fishy, to say the least\n              scope.declareValue(name, isByvalueRecOut, body.isLam, symb)\n              throw e\n          }\n        } else {\n          (try R(translateTerm(body)) catch { // TODO Improve: Why are the bodies translated in the SAME scope?!\n            case e: UnimplementedError =>\n              scope.declareStubValue(name, e.symbol, symb)\n              L(e.getMessage())\n          }) map {\n            val isByvalueRec = if (isByname) None else Some(false)\n            expr => (expr, scope.declareValue(name, isByvalueRec, body.isLam, symb))\n          }\n        }) match {\n          case R((originalExpr, sym)) =>\n            val expr = \n              if (sym.isByvalueRec.isEmpty && !sym.isLam)\n                JSArrowFn(Nil, L(originalExpr))\n              else\n                originalExpr\n            JSTestBackend.CodeQuery(\n              scope.tempVars.emit(),\n              ((JSIdent(\"globalThis\").member(sym.runtimeName) := (expr match {\n                case t: JSArrowFn => t.toFuncExpr(S(sym.runtimeName))\n                case t            => t\n              })) :: Nil),\n              sym.runtimeName\n            )\n          case L(reason) => JSTestBackend.AbortedQuery(reason)\n        }\n      case fd @ NuFunDef(isLetRec, Var(name), symNme, tys, R(ty)) =>\n        val symb = symNme.map(_.name)\n        scope.declareStubValue(name, symb)(allowEscape || fd.isDecl)\n        JSTestBackend.EmptyQuery\n      case term: Term =>\n        try {\n          val body = translateTerm(term)(scope)\n          val res = JSTestBackend.CodeQuery(scope.tempVars.emit(), (resultIdent := body) :: Nil)\n          scope.refreshRes()\n          res\n        } catch {\n          case e: UnimplementedError => JSTestBackend.AbortedQuery(e.getMessage())\n        }\n      case _: Def | _: TypeDef | _: Constructor =>\n        throw CodeGenError(\"Def and TypeDef are not supported in NewDef files.\")\n    }\n\n    // If this is the first time, insert the declaration of `res`.\n    var prelude: Ls[JSStmt] = Ls(moduleDecl, insDecl) ::: includes\n    val isFirst = numRun === 0\n    if (isFirst)\n      prelude = JSLetDecl(lastResultSymbol.runtimeName -> N :: Nil) :: prelude\n\n    // Increase the run number.\n    numRun = numRun + 1\n\n    val qqPredefs =\n      SourceCode(if (isFirst && prettyPrintQQ) QQHelper.prettyPrinter else \"\")\n    JSTestBackend.TestCode((qqPredefs ++ SourceCode.fromStmts(polyfill.emit() ::: prelude)).toLines, queries)\n  }\n}\n\nobject JSTestBackend {\n  sealed abstract class Query\n\n  /**\n    * The generation was aborted due to some reason.\n    */\n  final case class AbortedQuery(reason: Str) extends Query\n\n  /**\n    * The entry generates nothing.\n    */\n  final object EmptyQuery extends Query\n\n  /**\n    * The entry generates meaningful code.\n    */\n  final case class CodeQuery(prelude: Ls[Str], code: Ls[Str], res: Str) extends Query {\n    \n  }\n\n  object CodeQuery {\n    def apply(decls: Opt[JSLetDecl], stmts: Ls[JSStmt], res: Str = \"res\"): CodeQuery =\n      CodeQuery(\n        decls match {\n          case S(stmt) => stmt.toSourceCode.toLines\n          case N       => Nil\n        },\n        SourceCode.fromStmts(stmts).toLines,\n        res\n      )\n  }\n\n  /**\n    * Represents the result of code generation.\n    */\n  abstract class Result {\n    def showFirstResult(prefixLength: Int): Unit = ()\n  }\n\n  /**\n    * Emitted code.\n    */\n  final case class TestCode(prelude: Ls[Str], queries: Ls[Query]) extends Result\n\n  sealed abstract class ErrorMessage(val content: Str) extends Result\n\n  /**\n    * The input MLscript is ill-formed (e.g. impossible inheritance).\n    */\n  final case class IllFormedCode(override val content: Str) extends ErrorMessage(content)\n\n  /**\n    * Some referenced symbols are not implemented.\n    */\n  final case class Unimplemented(override val content: Str) extends ErrorMessage(content)\n\n  /**\n    * Code generation crashed.\n    */\n  // final case class UnexpectedCrash(val name: Str, override val content: Str) extends ErrorMessage(content)\n\n  /**\n    * The result is not executed for some reasons. E.g. `:NoJS` flag.\n    */\n  final object ResultNotExecuted extends JSTestBackend.Result\n}\n\nobject JSBackend {\n  // For integers larger than this value, use BigInt notation.\n  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER\n  val MaximalSafeInteger: BigInt = BigInt(\"9007199254740991\")\n\n  // For integers less than this value, use BigInt notation.\n  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MIN_SAFE_INTEGER\n  val MinimalSafeInteger: BigInt = BigInt(\"-9007199254740991\")\n\n  def isSafeInteger(value: BigInt): Boolean =\n    MinimalSafeInteger <= value && value <= MaximalSafeInteger\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/Lexer.scala",
    "content": "package mlscript\n\nimport fastparse._\nimport fastparse.NoWhitespace._\n\n/** Inspired by and adapted from:\n  *   scalaparse: https://github.com/lihaoyi/fastparse/tree/master/scalaparse\n  *   pythonparse: https://github.com/lihaoyi/fastparse/tree/master/pythonparse\n  */\n@SuppressWarnings(Array(\"org.wartremover.warts.All\"))\nobject Lexer {\n  \n  def kw[p: P](s: String) = s ~ !(letter | digit | \"_\")\n  def comment[p: P] = P( \"//\" ~ CharsWhile(_ != '\\n', /*min =*/ 0) )\n  def wscomment[p: P] = P( (CharsWhileIn(\" \\n\") | Lexer.comment | \"\\\\\\n\").rep )\n  def nonewlinewscomment[p: P] = P( (CharsWhileIn(\" \") | Lexer.comment | \"\\\\\\n\").rep )\n  \n  def identifier[p: P]: P[String] =\n    P( (letter|\"_\"|\"`\") ~ (letter | digit | \"_\" | \"-\" | \"'\" | \"!\" | \"?\").rep ).!.filter(!keywordList.contains(_))\n  def letter[p: P]     = P( lowercase | uppercase )\n  def lowercase[p: P]  = P( CharIn(\"a-z\") )\n  def uppercase[p: P]  = P( CharIn(\"A-Z\") )\n  def digit[p: P]      = P( CharIn(\"0-9\") )\n  \n  //def operator[p: P]: P[String] =\n  //  P( (\"_\" | \"-\" | opchar).rep ).!.filter(!keywordList.contains(_))\n  def operator[p: P]: P[Unit] = P(\n    !symbolicKeywords ~ (!StringIn(\"/*\", \"//\") ~ (CharsWhile(OpCharNotSlash) | \"/\")).rep(1)\n  ).opaque(\"operator\")\n  \n  val OpCharNotSlash = NamedFunction(x => isOpChar(x) && x != '/')\n  val NotBackTick = NamedFunction(_ != '`')\n  case class NamedFunction(f: Char => Boolean)\n                          (implicit name: sourcecode.Name) extends (Char => Boolean){\n    def apply(t: Char) = f(t)\n    override def toString() = name.value\n  }\n  \n  def OpChar[p: P] = P ( CharPred(isOpChar) )\n  \n  val isOpChar = NamedFunction{\n    case '!' | '#' | '%' | '&' | '*' | '+' | '-' | '/'\n       | ':' | '<' | '=' | '>' | '?' | '@' | '\\\\' | '^' | '|' | '~'  | '.'\n    => true\n    //case c => isOtherSymbol(c) || isMathSymbol(c)\n    case c => false\n  }\n  \n  val keywordList = Set(\n    \"and\",\n    \"or\",\n    // \"not\",\n    \"is\",\n    \"as\",\n    \"with\",\n    \"if\",\n    \"then\",\n    \"else\",\n    \"yield\",\n    \"import\",\n    \"class\",\n    \"interface\",\n    \"trait\",\n    \"object\",\n    \"let\",\n    \"rec\",\n    \"in\",\n    \"of\",\n    \"val\",\n    \"data\",\n    \"type\",\n  )\n  \n  def symbolicKeywords[p: P] = P{\n    StringIn(\n      //\":\", \n      \";\", \"=>\", \"=\", \"->\", \"<-\", \n      \":\", \"/\",\n      //\"<:\", \"<%\", \">:\", \n      \"#\", \"@\", \"\\\\\", \"\\u21d2\", \"\\u2190\"\n    ) ~ !OpChar\n  }.opaque(\"SymbolicKeywords\")\n  \n  def stringliteral[p: P]: P[String] = P( stringprefix.? ~ (longstring | shortstring) )\n  def stringprefix[p: P]: P[Unit] = identifier\n  def shortstring[p: P]: P[String] = P( shortstring0(\"'\") | shortstring0(\"\\\"\") )\n  def shortstring0[p: P](delimiter: String) = P( delimiter ~ shortstringitem(delimiter).rep.! ~ delimiter)\n  def shortstringitem[p: P](quote: String): P[Unit] = P( shortstringchar(quote) | escapeseq )\n  def shortstringchar[p: P](quote: String): P[Unit] = P( CharsWhile(!s\"\\\\\\n${quote(0)}\".contains(_)) )\n  \n  def longstring[p: P]: P[String] = P( longstring0(\"'''\") | longstring0(\"\\\"\\\"\\\"\") )\n  def longstring0[p: P](delimiter: String) = P( delimiter ~ longstringitem(delimiter).rep.! ~ delimiter)\n  def longstringitem[p: P](quote: String): P[Unit] = P( longstringchar(quote) | escapeseq | !quote ~ quote.take(1)  )\n  def longstringchar[p: P](quote: String): P[Unit] = P( CharsWhile(!s\"\\\\${quote(0)}\".contains(_)) )\n  \n  def escapeseq[p: P]: P[Unit] = P( \"\\\\\" ~ AnyChar )\n  \n  def negatable[T, _P: P](p: => P[T])(implicit ev: Numeric[T]) = (\n    //(\"+\" | \"-\") // '+' is useless and causes problems, e.g., f +1 and f+1 parsed as f (+1)...\n    \"-\"\n  .?.! ~ p).map {\n    case (\"-\", i) => ev.negate(i)\n    case (_, i) => i\n  }\n  \n  def longinteger[p: P]: P[BigInt] = P( integer ~ (\"l\" | \"L\") )\n  def integer[p: P]: P[BigInt] = negatable[BigInt, Any](P( octinteger | hexinteger | bininteger | decimalinteger))\n  def decimalinteger[p: P]: P[BigInt] = P( nonzerodigit ~ digit.rep | \"0\" ).!.map(scala.BigInt(_))\n  def octinteger[p: P]: P[BigInt] = P( \"0\" ~ (\"o\" | \"O\") ~ octdigit.rep(1).! | \"0\" ~ octdigit.rep(1).! ).map(scala.BigInt(_, 8))\n  def hexinteger[p: P]: P[BigInt] = P( \"0\" ~ (\"x\" | \"X\") ~ hexdigit.rep(1).! ).map(scala.BigInt(_, 16))\n  def bininteger[p: P]: P[BigInt] = P( \"0\" ~ (\"b\" | \"B\") ~ bindigit.rep(1).! ).map(scala.BigInt(_, 2))\n  def nonzerodigit[p: P]: P[Unit] = P( CharIn(\"1-9\") )\n  def octdigit[p: P]: P[Unit] = P( CharIn(\"0-7\") )\n  def bindigit[p: P]: P[Unit] = P( \"0\" | \"1\" )\n  def hexdigit[p: P]: P[Unit] = P( digit | CharIn(\"a-f\", \"A-F\") )\n  \n  \n  def floatnumber[p: P]: P[BigDecimal] = negatable[BigDecimal, Any](P( pointfloat | exponentfloat ))\n  def pointfloat[p: P]: P[BigDecimal] = P( intpart.? ~ fraction | intpart ~ \".\" ).!.map(BigDecimal(_))\n  def exponentfloat[p: P]: P[BigDecimal] = P( (intpart | pointfloat) ~ exponent ).!.map(BigDecimal(_))\n  def intpart[p: P]: P[BigDecimal] = P( digit.rep(1) ).!.map(BigDecimal(_))\n  def fraction[p: P]: P[Unit] = P( \".\" ~ digit.rep(1) )\n  def exponent[p: P]: P[Unit] = P( (\"e\" | \"E\") ~ (\"+\" | \"-\").? ~ digit.rep(1) )\n  \n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/MLParser.scala",
    "content": "package mlscript\n\nimport scala.util.chaining._\nimport scala.collection.mutable\nimport fastparse._, fastparse.ScalaWhitespace._\nimport mlscript.utils._, shorthands._\nimport mlscript.Lexer._\n\n/** Parser for an ML-style input syntax, used in the legacy `ML*` tests. */\n@SuppressWarnings(Array(\"org.wartremover.warts.All\"))\nclass MLParser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {\n  \n  val keywords = Set(\n    \"def\", \"class\", \"trait\", \"type\", \"method\", \"mut\",\n    \"let\", \"rec\", \"in\", \"fun\", \"with\", \"undefined\", \"null\",\n    \"if\", \"then\", \"else\", \"match\", \"case\", \"of\", \"forall\",\n    \"datatype\", \"match\", \"as\")\n  def kw[p: P](s: String) = s ~~ !(letter | digit | \"_\" | \"'\")\n  \n  // NOTE: due to bug in fastparse, the parameter should be by-name!\n  def locate[p:P, L <: Located](tree: => P[L]): P[L] = (Index ~~ tree ~~ Index).map {\n    case (i0, n, i1) => n.withLoc(i0, i1, origin)\n  }\n  \n  def toParam(t: Term): Tup =\n    Tup((N, Fld(FldFlags.empty, t)) :: Nil)\n  \n  def toParams(t: Term): Tup = t match {\n    case t: Tup => t\n    case _ => toParam(t)\n  }\n  def toParamsTy(t: Type): Tuple = t match {\n    case t: Tuple => t\n    case _ => Tuple((N, Field(None, t)) :: Nil)\n  }\n  \n  def letter[p: P]     = P( lowercase | uppercase )\n  def lowercase[p: P]  = P( CharIn(\"a-z\") )\n  def uppercase[p: P]  = P( CharIn(\"A-Z\") )\n  def digit[p: P]      = P( CharIn(\"0-9\") )\n  def number[p: P]: P[Int] = P( CharIn(\"0-9\").repX(1).!.map(_.toInt) )\n  def ident[p: P]: P[String] =\n    P( (letter | \"_\") ~~ (letter | digit | \"_\" | \"'\").repX ).!.filter(!keywords(_))\n  def index[p: P]: P[String] = P( \"0\" | CharIn(\"1-9\") ~~ digit.repX ).!.map(_.toString)\n  \n  def termOrAssign[p: P]: P[Statement] = P( term ~ (\"=\" ~ term).? ).map {\n    case (expr, N) => expr\n    case (pat, S(bod)) => LetS(false, pat, bod)\n  }\n\n  def term[p: P]: P[Term] = P(let | fun | ite | forall | withsAscAs | _match | adtMatchWith)\n  \n  def forall[p: P]: P[Term] = P( (kw(\"forall\") ~/ tyVar.rep ~ \".\" ~ term).map {\n    case (vars, ty) => Forall(vars.toList, ty)\n  } )\n  \n  def lit[p: P]: P[Lit] =\n    locate(number.map(x => IntLit(BigInt(x))) | Lexer.stringliteral.map(StrLit(_))\n    | P(kw(\"undefined\")).map(x => UnitLit(true)) | P(kw(\"null\")).map(x => UnitLit(false)))\n  \n  def variable[p: P]: P[Var] = locate(ident.map(Var))\n  def fieldName[p: P]: P[Var] = locate( (ident | index).map(Var) )\n\n  def parenCell[p: P]: P[Either[Term, (Term, Boolean)]] = ((\"...\" | kw(\"mut\")).!.? ~ term).map {\n    case (Some(\"...\"), t) => Left(t)\n    case (Some(\"mut\"), t) => Right(t -> true)\n    case (_, t) => Right(t -> false)\n  }\n\n  def parens[p: P]: P[Term] = locate(P( \"(\" ~/ parenCell.rep(0, \",\") ~ \",\".!.? ~ \")\" ).map {\n    case (Seq(Right(t -> false)), N) => Bra(false, t)\n    case (Seq(Right(t -> true)), N) => Tup(N -> Fld(FldFlags(true, false, false), t) :: Nil) // ? single tuple with mutable\n    case (ts, _) => \n      if (ts.forall(_.isRight)) Tup(ts.iterator.map {\n        case R(f) => N -> Fld(FldFlags(f._2, false, false), f._1)\n        case _ => die // left unreachable\n      }.toList)\n      else Splc(ts.map {\n        case R((v, m)) => R(Fld(FldFlags(m, false, false), v))\n        case L(spl) => L(spl)\n      }.toList)\n  })\n\n  def subtermNoSel[p: P]: P[Term] = P( parens | record | lit | variable )\n  \n  def subterm[p: P]: P[Term] = P( Index ~~ subtermNoSel ~ (\n    // Fields:\n    (\".\" ~/ (fieldName | locate((\"(\" ~/ ident ~ \".\" ~ ident ~ \")\")\n      .map {case (prt, id) => Var(s\"${prt}.${id}\")})))\n      .map {(t: Var) => Left(t)} |\n    // Array subscripts:\n    (\"[\" ~ term ~/ \"]\" ~~ Index).map {Right(_)}\n    // Assignment:\n    ).rep ~ \"!\".!.? ~ (\"<-\" ~ term).?).map {\n      case (i0, st, sels, bang, a) =>\n        val base0 = sels.foldLeft(st)((acc, t) => t match {\n          case Left(se) => Sel(acc, se)\n          case Right((su, i1)) => Subs(acc, su).withLoc(i0, i1, origin)\n        })\n        val base = if (bang.isEmpty) base0 else\n          Inst(base0)\n        a.fold(base)(Assign(base, _))\n    }\n\n  def record[p: P]: P[Rcd] = locate(P(\n      \"{\" ~/ (kw(\"mut\").!.? ~ fieldName ~ \"=\" ~ term map L.apply).|(kw(\"mut\").!.? ~\n        variable map R.apply).rep(sep = \";\" | \",\") ~ \"}\"\n    ).map { fs => Rcd(fs.map{ \n        case L((mut, v, t)) => v -> Fld(FldFlags(mut.isDefined, false, false), t)\n        case R(mut -> id) => id -> Fld(FldFlags(mut.isDefined, false, false), id) }.toList)})\n  \n  def fun[p: P]: P[Term] = locate(P( kw(\"fun\") ~/ term ~ \"->\" ~ term ).map(nb => Lam(toParams(nb._1), nb._2)))\n  \n  def let[p: P]: P[Term] = locate(P(\n      kw(\"let\") ~/ kw(\"rec\").!.?.map(_.isDefined) ~ variable ~ subterm.rep ~ \"=\" ~ term ~ kw(\"in\") ~ term\n    ) map {\n      case (rec, id, ps, rhs, bod) => Let(rec, id, ps.foldRight(rhs)((i, acc) => Lam(toParams(i), acc)), bod)\n    })\n  \n  def ite[p: P]: P[Term] = P( kw(\"if\") ~/ term ~ kw(\"then\") ~ term ~ kw(\"else\") ~ term ).map(ite =>\n    App(App(App(Var(\"if\"), toParam(ite._1)), toParam(ite._2)), toParam(ite._3)))\n  \n  def withsAscAs[p: P]: P[Term] = P( withsAsc ~ (kw(\"as\") ~/ term).rep ).map {\n    case (withs, ascs) => ascs.foldLeft(withs)(Bind)\n  }\n  \n  def withsAsc[p: P]: P[Term] = P( withs ~ (\":\" ~/ ty).rep ).map {\n    case (withs, ascs) => ascs.foldLeft(withs)(Asc)\n  }\n  \n  def withs[p: P]: P[Term] = P( binops ~ (kw(\"with\") ~ record).rep ).map {\n    case (as, ws) => ws.foldLeft(as)((acc, w) => With(acc, w))\n  }\n  \n  def mkApp(lhs: Term, rhs: Term): Term = App(lhs, toParams(rhs))\n  def apps[p: P]: P[Term] = P( subterm.rep(1).map(_.reduce(mkApp)) )\n  \n  def _match[p: P]: P[CaseOf] =\n    locate(P( kw(\"case\") ~/ term ~ \"of\" ~ (\"{\" ~ \"|\".? ~ matchArms(\"|\") ~ \"}\" | matchArms(\",\")) ).map(CaseOf.tupled))\n  def matchArms[p: P](sep: Str): P[CaseBranches] = P(\n    ( (\"_\" ~ \"->\" ~ term).map(Wildcard)\n    | ((lit | variable) ~ \"->\" ~ term ~ matchArms2(sep))\n      .map { case (t, b, rest) => Case(t, b, rest)(refined = false) }\n    ).?.map {\n      case None => NoCases\n      case Some(b) => b\n    }\n  )\n  def matchArms2[p: P](sep: Str): P[CaseBranches] = (sep ~ matchArms(sep)).?.map(_.getOrElse(NoCases))\n  \n  private val prec: Map[Char,Int] = List(\n    \":\",\n    \"|\",\n    \"^\",\n    \"&\",\n    \"= !\",\n    \"< >\",\n    \"+ -\",\n    \"* / %\",\n    \".\",\n  ).zipWithIndex.flatMap {\n    case (cs,i) => cs.filterNot(_ == ' ').map(_ -> i)\n  }.toMap.withDefaultValue(Int.MaxValue)\n  def precedence(op: String): Int = prec(op.head) min prec(op.last)\n  \n  // Adapted from: https://github.com/databricks/sjsonnet/blob/master/sjsonnet/src/sjsonnet/Parser.scala#L136-L180\n  def binops[p: P]: P[Term] =\n    P(apps ~ (Index ~~ operator.! ~~ Index ~/ apps).rep ~ \"\").map { case (pre, fs) =>\n      var remaining = fs\n      def climb(minPrec: Int, current: Term): Term = {\n        var result = current\n        while (\n          remaining.headOption match {\n            case None => false\n            case Some((off0, op, off1, next)) =>\n              val prec: Int = precedence(op)\n              if (prec < minPrec) false\n              else {\n                remaining = remaining.tail\n                val rhs = climb(prec + 1, next)\n                result = App(App(Var(op).withLoc(off0, off1, origin), toParams(result)), toParams(rhs))\n                true\n              }\n          }\n        )()\n        result\n      }\n      climb(0, pre)\n    }\n  def operator[p: P]: P[Unit] = P(\n    !symbolicKeywords ~~ (!StringIn(\"/*\", \"//\") ~~ (CharsWhile(OpCharNotSlash) | \"/\")).rep(1)\n  ).opaque(\"operator\")\n  def symbolicKeywords[p: P] = P{\n    StringIn(\n      \"|\",\n      \"~\",\n      \";\", \"=>\", \"=\", \"->\", \"<-\",\n      \":\",\n      \"#\", \"@\", \"\\\\\", \"\\u21d2\", \"\\u2190\"\n    ) ~~ !OpChar\n  }.opaque(\"symbolic keywords\")\n  \n  def expr[p: P]: P[Term] = P( term ~ End )\n  \n  def defDecl[p: P]: P[Def] =\n    locate(P((kw(\"def\") ~ variable ~ tyParams ~ \":\" ~/ ty map {\n      case (id, tps, t) => Def(true, id, R(PolyType(tps.map(L(_)), t)), true)\n    }) | (kw(\"rec\").!.?.map(_.isDefined) ~ kw(\"def\") ~/ variable ~ subterm.rep ~ \"=\" ~ term map {\n      case (rec, id, ps, bod) => Def(rec, id, L(ps.foldRight(bod)((i, acc) => Lam(toParams(i), acc))), true)\n    })))\n  \n  def tyKind[p: P]: P[TypeDefKind] = (kw(\"class\") | kw(\"trait\") | kw(\"type\")).! map {\n    case \"class\" => Cls\n    case \"trait\" => Trt\n    case \"type\"  => Als\n  }\n  def tyDecl[p: P]: P[TypeDef] =\n    P((tyKind ~/ tyName ~ tyParams).flatMap {\n      case (k @ (Cls | Trt), id, ts) => (\":\" ~ ty).? ~ (mthDecl(id) | mthDef(id)).rep.map(_.toList) map {\n        case (bod, ms) => TypeDef(k, id, ts, bod.getOrElse(Top), \n          ms.collect { case R(md) => md }, ms.collect{ case L(md) => md }, Nil, N)\n      }\n      case (k @ Als, id, ts) => \"=\" ~ ty map (bod => TypeDef(k, id, ts, bod, Nil, Nil, Nil, N))\n      case (k @ Mod, _, _) => throw new NotImplementedError(\"Namespaces are not supported yet.\")\n      case (k @ Mxn, _, _) => throw new NotImplementedError(\"Mixins are not supported yet.\")\n    })\n  def tyParams[p: P]: P[Ls[TypeName]] =\n    (\"[\" ~ tyName.rep(0, \",\") ~ \"]\").?.map(_.toList.flatten)\n  def mthDecl[p: P](prt: TypeName): P[R[MethodDef[Right[Term, Type]]]] = \n    P(kw(\"method\") ~ variable ~ tyParams ~ \":\" ~/ ty map {\n      case (id, ts, t) => R(MethodDef[Right[Term, Type]](true, prt, id, ts, R(t)))\n    })\n  def mthDef[p: P](prt: TypeName): P[L[MethodDef[Left[Term, Type]]]] = \n    P(kw(\"rec\").!.?.map(_.isDefined) ~ kw(\"method\") ~ variable ~ tyParams ~ subterm.rep ~ \"=\" ~/ term map {\n      case (rec, id, ts, ps, bod) =>\n        L(MethodDef(rec, prt, id, ts, L(ps.foldRight(bod)((i, acc) => Lam(toParams(i), acc)))))\n    })\n  \n  def ty[p: P]: P[Type] = P( tyNoRange ~ (\"..\" ~ tyNoRange).? ).map {\n    case (res, N) => res\n    case (lb, S(ub)) => Bounds(lb, ub)\n  }\n  def tyNoRange[p: P]: P[Type] = P( tyNoAs ~ (\"as\" ~ tyVar).rep ).map {\n    case (ty, ass) => ass.foldLeft(ty)((a, b) => Recursive(b, a))\n  }\n  def tyNoAs[p: P]: P[Type] = P( (kw(\"forall\") ~/ tyVar.rep ~ \".\" ~ tyNoAs).map {\n    case (vars, ty) => PolyType(vars.map(R(_)).toList, ty)\n  } | tyNoForall )\n  def tyNoForall[p: P]: P[Type] = P( tyNoUnion.rep(1, \"|\") ).map(_.reduce(Union) )\n  def tyNoUnion[p: P]: P[Type] = P( tyNoInter.rep(1, \"&\") ).map(_.reduce(Inter) )\n  def tyNoInter[p: P]: P[Type] = P( tyNoFun ~ (\"->\" ~/ tyNoInter).? ).map {\n    case (l, S(r)) => Function(toParamsTy(l), r)\n    case (l, N) => l\n  }\n  // Note: field removal types are not supposed to be explicitly used by programmers,\n  //    and they won't work in negative positions,\n  //    but parsing them is useful in tests (such as shared/src/test/diff/mlscript/Annoying.mls)\n  def tyNoFun[p: P]: P[Type] = P( (rcd | ctor | parTy) ~ (\"\\\\\" ~ fieldName).rep(0) ) map {\n    case (ty, Nil) => ty\n    case (ty, ids) => Rem(ty, ids.toList)\n  }\n  def ctor[p: P]: P[Type] = locate(P( tyName ~ \"[\" ~ ty.rep(0, \",\") ~ \"]\" ) map {\n    case (tname, targs) => AppliedType(tname, targs.toList)\n  }) | tyNeg | tyName | tyTag | tyVar | tyWild | litTy\n  def tyNeg[p: P]: P[Type] = locate(P(\"~\" ~/ tyNoFun map { t => Neg(t) }))\n  def tyTag[p: P]: P[TypeTag] = locate(P(\"#\" ~~ (ident map TypeTag)))\n  def tyName[p: P]: P[TypeName] = locate(P(ident map TypeName))\n  def tyVar[p: P]: P[TypeVar] = locate(P(\n    ((\"α\" | \"β\" | \"γ\" | \"δ\" | \"'\").! ~ ident.? map {\n      case (pre, id) => TypeVar(R(pre + id.getOrElse(\"\")), N)\n    })\n  ))\n  def tyWild[p: P]: P[Bounds] = locate(P(\"?\".! map (_ => Bounds(Bot, Top))))\n  def rcd[p: P]: P[Record] =\n    locate(P( \"{\" ~/ ( kw(\"mut\").!.? ~ fieldName ~ \":\" ~ ty).rep(sep = \";\") ~ \"}\" )\n      .map(_.toList.map {\n        case (None, v, t) => v -> Field(None, t)\n        case (Some(_), v, t) => v -> Field(Some(t), t)\n      } pipe Record))\n  \n  def parTyCell[p: P]: P[Either[Type, (Type, Boolean)]] = ((\"...\" | kw(\"mut\")).!.? ~ ty). map {\n    case (Some(\"...\"), t) => Left(t)\n    case (Some(\"mut\"), t) => Right(t -> true)\n    case (_, t) => Right(t -> false)\n  }\n  \n  def parTy[p: P]: P[Type] = locate(P( \"(\" ~/ parTyCell.rep(0, \",\").map(_.map(N -> _).toList) ~ \",\".!.? ~ \")\" ).map {\n    case (N -> Right(ty -> false) :: Nil, N) => ty\n    case (fs, _) => \n      if (fs.forall(_._2.isRight))\n        Tuple(fs.map {\n          case (l, Right(t -> false)) => l -> Field(None, t)\n          case (l, Right(t -> true)) => l -> Field(Some(t), t)\n          case _ => ??? // unreachable\n        })\n      else Splice(fs.map{ _._2 match { \n        case L(l) => L(l) \n        case R(r -> true) => R(Field(Some(r), r))\n        case R(r -> false) => R(Field(None, r))\n      } })\n  })\n  def litTy[p: P]: P[Type] = P( lit.map(l => Literal(l).withLocOf(l)) )\n  \n  def toplvl[p: P]: P[Ls[Statement]] = P(adtTyDecl) | P( defDecl | tyDecl | termOrAssign ).map(_ :: Nil)\n  def pgrm[p: P]: P[Pgrm] = P( (\";\".rep ~ toplvl ~ topLevelSep.rep).rep.map(_.flatten.toList) ~ End ).map(Pgrm)\n  def topLevelSep[p: P]: P[Unit] = \";\"\n  \n  private var curHash = 0\n  def nextHash: Int = {\n    val res = curHash\n    curHash = res + 1\n    res\n  }\n  \n  ///////////////////////////////////////////////////////\n  /// ADT types\n  ///////////////////////////////////////////////////////\n  \n  def ctorName[p: P]: P[TypeName] =\n    locate(P(uppercase ~~ (letter | digit | \"_\" | \"'\").repX).!.filter(!keywords(_)).map(TypeName))\n  \n  /** Data constructor declaration. */\n  def adtCtorDecl[p: P](alsName: TypeName, tparams: List[TypeName]): P[TypeDef] = {\n    val parent = tparams match {\n      case Nil => alsName\n      case _ :: _ => AppliedType(alsName, tparams)\n    }\n    def tup = parTy.map {\n      case t: Tuple => t\n      case t => Tuple(N -> Field(N, t) :: Nil)\n    }\n    P((ctorName ~ tup.?).map {\n      case (id, S(body: Tuple)) =>\n        val positionals = body.fields.zipWithIndex.map { case (_, i) => Var(\"_\"+(i+1)) }\n        val rcdBody = Record(positionals.zip(body.fields.map(_._2)))\n        TypeDef(Cls, id, tparams, Inter(parent, rcdBody), Nil, Nil, positionals, S(AdtInfo(alsName)))\n      case (id, None) => TypeDef(Cls, id, tparams, parent, Nil, Nil, Nil, S(AdtInfo(alsName)))\n      case t => throw new Exception(s\"Unable to handle case $t\")\n    })\n  }\n  \n  def adtDataCtor[p: P](alsName: TypeName, tparams: List[TypeName]): P[List[TypeDef]] =\n    adtCtorDecl(alsName, tparams).rep(1, \"|\").map(_.toList)\n  \n  def adtTyDecl[p: P]: P[Ls[Statement]] =\n    P((kw(\"datatype\") ~ ctorName ~ tyParams).flatMap { case (alsName, tparams) =>\n      \"=\" ~/ adtDataCtor(alsName, tparams).map { bodies =>\n        val paramSet = tparams.toSet\n        val constructors = bodies.map(cls => adtTyConstructors(cls, alsName, tparams))\n        val parent = TypeDef(Cls, alsName, tparams, Top, constructors.map {\n          case Def(_, nme, R(body), _) =>\n            val ctorParams = body match {\n              case PolyType(_, Function(lhs, _)) => lhs\n              case PolyType(_, _: TypeName | _: AppliedType) => Top\n              case _ => die\n            }\n            MethodDef(false, alsName, nme, Nil, R(ctorParams))\n          case Def(_, nme, L(body), _) => ???\n        }, Nil, Nil, S(AdtInfo(alsName)))\n        parent :: bodies ::: constructors\n    }})\n  \n  /** Create a helper function for a class constructor. */\n  def adtTyConstructors(tyDef: TypeDef, alsName: TypeName, alsParams: Ls[TypeName]): Def = {\n    assert(tyDef.kind === Cls) \n    tyDef.body match {\n      case _: TypeName | _: AppliedType =>\n        val funAppTy = PolyType(alsParams.map(L.apply), tyDef.body)\n        val fun = Def(false, Var(tyDef.nme.name), R(funAppTy), true).withLocOf(tyDef.nme)\n        fun\n      case Inter(alsTy, Record(fields)) =>\n        val funTy = PolyType(alsParams.map(L.apply), Function(Tuple(fields.map(N -> _._2)), alsTy.withLocOf(tyDef)))\n        val fun = Def(false, Var(tyDef.nme.name), R(funTy), true).withLocOf(tyDef.nme)\n        fun\n      case _ => die\n    }\n  }\n  \n  ///////////////////////////////////////////////////////\n  /// ADT match with\n  ///////////////////////////////////////////////////////\n  \n  def adtMatchWith[p: P]: P[AdtMatchWith] =\n    locate(P(kw(\"match\") ~/ term ~ \"with\" ~ \"|\".? ~ matchArms).map {\n      case (expr, arms) => AdtMatchWith(expr, arms)\n    })\n  \n  def matchArms[p: P]: P[Ls[AdtMatchPat]] = P(\n    (\n      (\"_\" ~ \"->\" ~ term).map(AdtMatchPat(Var(\"_\"), _) :: Nil)\n        | (variable ~ \"_\" ~ \"->\" ~ term ~ matchArms2).map {\n          case (t, b, rest) =>\n            AdtMatchPat(mkApp(t, Var(\"_\")), b) :: rest\n        }\n        | (term ~ \"->\" ~ term ~ matchArms2).map {\n          case (t, b, rest) =>\n            AdtMatchPat(t, b) :: rest\n        }\n    ).?.map {\n      case None => Ls.empty\n      case Some(b) => b\n    })\n  \n  def matchArms2[p: P]: P[Ls[AdtMatchPat]] = (\"|\" ~ matchArms).?.map(_.getOrElse(Ls.empty))\n  \n}\n\nobject MLParser {\n  \n  def addTopLevelSeparators(lines: IndexedSeq[Str]): IndexedSeq[Str] = {\n    (lines.iterator ++ lines.lastOption).toList.sliding(2).map {\n      case l0 :: l1 :: Nil =>\n        if (l1.startsWith(\" \") || l1.startsWith(\"\\t\") || l0.startsWith(\"//\")) l0 + \"\\n\"\n        else l0 + \";\"\n      case l :: Nil => l\n      case _ => die\n    }.toIndexedSeq\n  }\n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/Message.scala",
    "content": "package mlscript\n\nimport scala.language.implicitConversions\nimport mlscript.utils._, shorthands._\n\nfinal case class Message(bits: Ls[Message.Bit]) {\n  def show(newDefs: Bool): Str = {\n    val ctx = ShowCtx.mk(typeBits, newDefs)\n    showIn(ctx)\n  }\n  def typeBits: Ls[TypeLike] = bits.collect{ case Message.Code(t) => t }\n  def showIn(implicit ctx: ShowCtx): Str = {\n    bits.map {\n      case Message.Code(ty) => ty.showIn(0)\n      case Message.Text(txt) => txt\n    }.mkString\n  }\n  def showDbg: Str = {\n    bits.iterator.map {\n      case Message.Code(trm) => s\"$trm\"\n      case Message.Text(txt) => txt\n    }.mkString\n  }\n  def +(that: Message): Message = Message(bits ++ that.bits)\n}\nobject Message {\n  \n  def mkCtx(msgs: IterableOnce[Message], newDefs: Bool,pre: Str = \"'\"): ShowCtx =\n    ShowCtx.mk(msgs.iterator.flatMap(_.typeBits), newDefs, pre)\n  \n  def join(msgs: Seq[Message]): Message = Message(msgs.iterator.flatMap(_.bits).toList)\n  \n  sealed abstract class Bit\n  final case class Text(str: Str) extends Bit\n  final case class Code(ty: TypeLike) extends Bit\n  implicit def fromType(ty: TypeLike): Message = Message(Code(ty)::Nil)\n  implicit def fromStr(str: Str): Message = Message(Text(str)::Nil)\n  \n  implicit class MessageContext(private val ctx: StringContext) {\n    def msg(inserted: Message*): Message = {\n      assert(inserted.length === ctx.parts.length - 1)\n      val parts = ctx.parts.map(str => Text(StringContext(str).s()))\n      val h = parts.head\n      val t = parts.tail\n      Message((h +: inserted.lazyZip(t).flatMap(_.bits :+ _)).toList)\n    }\n  }\n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/NewLexer.scala",
    "content": "package mlscript\n\nimport scala.annotation.tailrec\nimport utils._, shorthands._\n\nimport Message.MessageContext\nimport Diagnostic.{Lexing, Parsing}\n\nimport NewLexer._\n\nclass NewLexer(origin: Origin, raise: Diagnostic => Unit, dbg: Bool) {\n  \n  val bytes: Array[Char] = origin.fph.blockStr.toArray\n  private val length = bytes.length\n  type State = Int\n  \n  private val isOpChar = Set(\n    '!', '#', '%', '&', '*', '+', '-', '/', ':', '<', '=', '>', '?', '@', '\\\\', '^', '|', '~' , '.',\n    // ',', \n    // ';'\n  )\n  def isIdentFirstChar(c: Char): Bool =\n    c.isLetter || c === '_' || c === '\\''\n  def isIdentChar(c: Char): Bool =\n    isIdentFirstChar(c) || isDigit(c) || c === '\\''\n  def isHexDigit(c: Char): Bool =\n    isDigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')\n  def isOctDigit(c: Char): Bool =\n    c >= '0' && c <= '7'\n  def isBinDigit(c: Char): Bool =\n    c === '0' || c === '1'\n  def isDigit(c: Char): Bool =\n    c >= '0' && c <= '9'\n  def matches(i: Int, syntax: Str, start: Int): Bool =\n    if (start < syntax.length && i + start < length && bytes(i + start) === syntax(start)) matches(i, syntax, start + 1)\n    else start >= syntax.length\n  \n  /* // TODO remove (unused)\n  private val isNonStickyKeywordChar = Set(\n    ',',\n    ':',\n    ';',\n  )\n  */\n  \n  private val isSymKeyword = Set(\n    // \"->\",\n    \"=>\",\n    \"=\",\n    \":\",\n    \";\",\n    // \",\",\n    \"#\",\n    \"`\"\n    // \".\",\n    // \"<\",\n    // \">\",\n  )\n  \n  private val isAlphaOp = Set(\n    \"with\",\n    \"and\",\n    \"or\",\n    \"is\",\n    \"as\",\n  )\n  \n  @tailrec final\n  def takeWhile(i: Int, cur: Ls[Char] = Nil)(pred: Char => Bool): (Str, Int) =\n    if (i < length && pred(bytes(i))) takeWhile(i + 1, bytes(i) :: cur)(pred)\n    else (cur.reverseIterator.mkString, i)\n\n  final def num(i: Int): (Lit, Int) = {\n    def test(i: Int, p: Char => Bool): Bool = i < length && p(bytes(i))\n    def zero: IntLit = IntLit(BigInt(0))\n    /** Take a sequence of digits interleaved with underscores. */\n    def takeDigits(i: Int, pred: Char => Bool): (Opt[Str], Int) = {\n      @tailrec def rec(i: Int, acc: Ls[Char], firstSep: Bool, lastSep: Bool): (Str, Bool, Bool, Int) =\n        if (i < length) {\n          val c = bytes(i)\n          if (pred(c)) rec(i + 1, c :: acc, firstSep, false)\n          else if (c === '_') rec(i + 1, acc, acc.isEmpty, true)\n          else (acc.reverseIterator.mkString, firstSep, lastSep, i)\n        }\n        else (acc.reverseIterator.mkString, firstSep, lastSep, i)\n      val (str, firstSep, lastSep, j) = rec(i, Nil, false, false)\n      if (firstSep)\n        raise(WarningReport(\n          msg\"Leading separator is not allowed\" -> S(loc(i - 1, i)) :: Nil,\n          newDefs = true, source = Lexing))\n      if (lastSep)\n        raise(WarningReport(\n          msg\"Trailing separator is not allowed\" -> S(loc(j - 1, j)) :: Nil,\n          newDefs = true, source = Lexing))\n      (if (str.isEmpty) N else S(str), j)\n    }\n    /** Take an integer and coverts to `BigInt`. Also checks if it is empty. */\n    def integer(i: Int, radix: Int, desc: Str, pred: Char => Bool): (IntLit, Int) = {\n      takeDigits(i, pred) match {\n        case (N, j) =>\n          raise(ErrorReport(msg\"Expect at least one $desc digit\" -> S(loc(i, i + 2)) :: Nil,\n            newDefs = true, source = Lexing))\n          (zero, j)\n        case (S(str), j) => (IntLit(BigInt(str, radix)), j)\n      }\n    }\n    def isDecimalStart(ch: Char) = ch === '.' || ch === 'e' || ch === 'E'\n    /** Take a fraction part with an optional exponent part. Call at periods. */\n    def decimal(i: Int, integral: Str): (DecLit, Int) = {\n      val (fraction, j) = if (test(i, _ === '.')) {\n        takeDigits(i + 1, isDigit) match {\n          case (N, j) =>\n            raise(ErrorReport(msg\"Expect at least one digit after the decimal point\" -> S(loc(i + 1, i + 2)) :: Nil,\n              newDefs = true, source = Lexing))\n            (\"\", j)\n          case (S(digits), j) => (\".\" + digits, j)\n        }\n      } else (\"\", i)\n      val (exponent, k) = if (test(j, ch => ch === 'e' || ch === 'E')) {\n        val (sign, k) = if (test(j + 1, ch => ch === '+' || ch === '-')) {\n          (bytes(j + 1), j + 2)\n        } else {\n          ('+', j + 1)\n        }\n        takeDigits(k, isDigit) match {\n          case (N, l) =>\n            raise(ErrorReport(msg\"Expect at least one digit after the exponent sign\" -> S(loc(l - 1, l)) :: Nil,\n              newDefs = true, source = Lexing))\n            (\"\", l)\n          case (S(digits), l) => (\"E\" + sign + digits, l)\n        }\n      } else {\n        (\"\", j)\n      }\n      (DecLit(BigDecimal(integral + fraction + exponent)), k)\n    }\n    if (i < length) {\n      bytes(i) match {\n        case '0' if i + 1 < length => bytes(i + 1) match {\n          case 'x' => integer(i + 2, 16, \"hexadecimal\", isHexDigit)\n          case 'o' => integer(i + 2, 8, \"octal\", isOctDigit)\n          case 'b' => integer(i + 2, 2, \"binary\", isBinDigit)\n          case '.' | 'E' | 'e' => decimal(i + 1, \"0\")\n          case _ => integer(i, 10, \"decimal\", isDigit)\n        }\n        case '0' => (zero, i + 1)\n        case _ => takeDigits(i, isDigit) match {\n          case (N, j) =>\n            raise(ErrorReport(msg\"Expect a numeric literal\" -> S(loc(i, i + 1)) :: Nil,\n              newDefs = true, source = Lexing))\n            (zero, i)\n          case (S(integral), j) =>\n            if (j < length && isDecimalStart(bytes(j))) decimal(j, integral)\n            else (IntLit(BigInt(integral)), j)\n        }\n      }\n    } else {\n      raise(ErrorReport(msg\"Expect a numeric literal instead of end of input\" -> S(loc(i, i + 1)) :: Nil,\n        newDefs = true, source = Lexing))\n      (zero, i)\n    }\n  }\n\n  final\n  def char(i: Int): (Char, Int) = {\n    if (i < length) {\n      bytes(i) match {\n        case '\\\\' => {\n          val j = i + 1\n          if (j < length)\n            bytes(j) match {\n              case 'n' => ('\\n', j + 1)\n              case 't' => ('\\t', j + 1)\n              case 'r' => ('\\r', j + 1)\n              case 'b' => ('\\b', j + 1)\n              case 'f' => ('\\f', j + 1)\n              case '\\'' => ('\\'', j + 1)\n              case '\"' => ('\"', j + 1)\n              case '\\\\' => ('\\\\', j + 1)\n              case ch =>\n                raise(ErrorReport(msg\"Invalid escape character\" -> S(loc(j, j + 1)) :: Nil,\n                  newDefs = true, source = Lexing))\n                ('\\u0000', j + 1)\n            }\n          else {\n            raise(ErrorReport(msg\"Expect an escape character\" -> S(loc(i, i + 1)) :: Nil,\n              newDefs = true, source = Lexing))\n            ('\\u0000', i + 1)\n          }\n        }\n        case '\\n' | '\\r' =>\n          raise(ErrorReport(msg\"Unexpected newline in a char literal\" -> S(loc(i, i + 1)) :: Nil,\n            newDefs = true, source = Lexing))\n          ('\\u0000', i + 1)\n        case '\\\"' =>\n          raise(ErrorReport(msg\"Empty character literal\" -> S(loc(i, i + 1)) :: Nil,\n            newDefs = true, source = Lexing))\n          ('\\u0000', i + 1)\n        case ch =>\n          (ch, i + 1)\n      }\n    }\n    else {\n      raise(ErrorReport(msg\"Expect a character literal\" -> S(loc(i, i + 1)) :: Nil,\n        newDefs = true, source = Lexing))\n      ('\\u0000', i)\n    }\n  }\n\n  final def closeChar(i: Int): Int =\n    if (bytes.lift(i) === Some('\\\"')) i + 1\n    else {\n      raise(ErrorReport(msg\"Unclosed character literal\" -> S(loc(i, i + 1)) :: Nil,\n        newDefs = true, source = Lexing))\n      i\n    }\n\n  // * Check the end of a string (either single quotation or triple quotation)\n  final def closeStr(i: Int, isTriple: Bool): Int =\n    if (!isTriple && bytes.lift(i) === Some('\"')) i + 1\n    else if (isTriple && matches(i, \"\\\"\\\"\\\"\", 0)) i + 3\n    else {\n      raise(ErrorReport(msg\"unclosed quotation mark\" -> S(loc(i, i + 1)) :: Nil, newDefs = true, source = Lexing))\n      i\n    }\n\n  @tailrec final\n  def str(i: Int, escapeMode: Bool, cur: Ls[Char] = Nil)(implicit triple: Bool): (Str, Int) =\n    if (escapeMode)\n      if (i < length)\n        bytes(i) match {\n          case '\\\\' => str(i + 1, false, '\\\\' :: cur)\n          case '\"' => str(i + 1, false, '\"' :: cur)\n          case 'n' => str(i + 1, false, '\\n' :: cur)\n          case 't' => str(i + 1, false, '\\t' :: cur)\n          case 'r' => str(i + 1, false, '\\r' :: cur)\n          case 'b' => str(i + 1, false, '\\b' :: cur)\n          case 'f' => str(i + 1, false, '\\f' :: cur)\n          case ch =>\n            raise(WarningReport(msg\"Found invalid escape character\" -> S(loc(i, i + 1)) :: Nil,\n              newDefs = true, source = Lexing))\n            str(i + 1, false, ch :: cur)\n        }\n      else {\n        raise(ErrorReport(msg\"Expect an escape character\" -> S(loc(i, i + 1)) :: Nil,\n          newDefs = true, source = Lexing))\n        (cur.reverseIterator.mkString, i)\n      }\n    else if (triple) {\n      if (i < length)\n        bytes(i) match {\n          case '\"' =>\n            if (matches(i, \"\\\"\\\"\\\"\", 0) && !matches(i + 1, \"\\\"\\\"\\\"\", 0)) // Find the last \"\"\"\n              (cur.reverseIterator.mkString, i)\n            else str(i + 1, false, '\"' :: cur)\n          case ch => str(i + 1, false, ch :: cur)\n        }\n      else (cur.reverseIterator.mkString, i)\n    }\n    else {\n      if (i < length)\n        bytes(i) match {\n          case '\\\\' => str(i + 1, true, cur)\n          case '\"' | '\\n' => (cur.reverseIterator.mkString, i)\n          case ch => str(i + 1, false, ch :: cur)\n        }\n      else\n        (cur.reverseIterator.mkString, i)\n    }\n  \n  def loc(start: Int, end: Int): Loc = Loc(start, end, origin)\n  \n  @tailrec final\n  def lex(i: Int, ind: Ls[Int], acc: Ls[TokLoc])(implicit qqList: Ls[BracketKind]): Ls[TokLoc] = if (i >= length) acc.reverse else {\n    val c = bytes(i)\n    def pe(msg: Message): Unit =\n      // raise(ParseError(false, msg -> S(loc(i, i + 1)) :: Nil))\n      raise(ErrorReport(msg -> S(loc(i, i + 1)) :: Nil, newDefs = true, source = Lexing))\n    def isQuasiquoteOpening(i: Int): Bool = matches(i, BracketKind.Quasiquote.beg, 0)\n    def isQuasiquoteTripleOpening(i: Int): Bool =  matches(i, BracketKind.QuasiquoteTriple.beg, 0)\n    def isUnquoteOpening(i: Int): Bool = matches(i, BracketKind.Unquote.beg, 0)\n    def isQuasiquoteTripleClosing(i: Int): Bool = matches(i, BracketKind.QuasiquoteTriple.end, 0)\n    // @inline \n    // def go(j: Int, tok: Token) = lex(j, ind, (tok, loc(i, j)) :: acc)\n    def next(j: Int, tok: Token) = (tok, loc(i, j)) :: acc\n    c match {\n      case ' ' =>\n        val (_, j) = takeWhile(i)(_ === ' ')\n        // go(j, SPACE)\n        lex(j, ind, next(j, SPACE))\n      case ',' =>\n        val j = i + 1\n        // go(j, COMMA)\n        lex(j, ind, next(j, COMMA))\n      case '`' =>\n        lex(i + 1, ind, next(i + 1, QUOTE))\n      case 'c' if isQuasiquoteOpening(i) || isQuasiquoteTripleOpening(i) =>\n        val isTripleQuoteQQ = isQuasiquoteTripleOpening(i)\n        val bracket_kind = if (isTripleQuoteQQ)\n          BracketKind.QuasiquoteTriple\n        else\n          BracketKind.Quasiquote\n        val len = bracket_kind.beg.length\n        lex(i + len, ind, next(i + len, OPEN_BRACKET(bracket_kind)))(bracket_kind :: qqList)\n      case '$' if isUnquoteOpening(i) =>\n        lex(i + 2, ind, next(i + 2, OPEN_BRACKET(BracketKind.Unquote)))\n      case '$' if i + 1 < length && isIdentFirstChar(bytes(i + 1)) =>\n        val (n, j) = takeWhile(i + 1)(isIdentChar)\n        lex(j, ind, next(j, BRACKETS(BracketKind.Unquote, (if (keywords.contains(n)) KEYWORD(n) else IDENT(n, isAlphaOp(n)), loc(i + 1, j)) :: Nil)(loc(i, j))))\n      case ';' =>\n        val j = i + 1\n        lex(j, ind, next(j, SEMI))\n      case '\"' =>\n        val (isTripleQQ, cons) = qqList match {\n          case h :: t => (h === BracketKind.QuasiquoteTriple, t)\n          case Nil => (false, Nil)\n        }\n        if (isTripleQQ && isQuasiquoteTripleClosing(i)) {\n          val length = BracketKind.QuasiquoteTriple.end.length\n          lex(i + length, ind, next(i + length, CLOSE_BRACKET(BracketKind.QuasiquoteTriple)))(cons)\n        } else if (!isTripleQQ && qqList.nonEmpty) {\n          lex(i + 1, ind, next(i + 1, CLOSE_BRACKET(BracketKind.Quasiquote)))(cons)\n        } else {\n          val isTriple = matches(i, \"\\\"\\\"\\\"\", 0)\n          val j = i + (if (isTriple) 3 else 1)\n          val (chars, k) = str(j, false)(isTriple)\n          val k2 = closeStr(k, isTriple)\n          // go(k2, LITVAL(StrLit(chars)))\n          lex(k2, ind, next(k2, LITVAL(StrLit(chars))))\n        }        \n      case '/' if bytes.lift(i + 1).contains('/') =>\n        val j = i + 2\n        val (txt, k) =\n          takeWhile(j)(c => c =/= '\\n')\n        // go(k, COMMENT(txt))\n        lex(k, ind, next(k, COMMENT(txt)))\n      case '/' if bytes.lift(i + 1).contains('*') => // multiple-line comment\n        val j = i + 2\n        var prev1 = '/'; var prev2 = '*'\n        val (txt, k) =\n          takeWhile(j)(c => {\n            val res = prev1 =/= '*' || prev2 =/= '/'\n            prev1 = prev2; prev2 = c\n            res\n          })\n        // go(k, COMMENT(txt.dropRight(2)))\n        lex(k, ind, next(k, COMMENT(txt.dropRight(2))))\n      // case BracketKind(Left(k)) => go(i + 1, OPEN_BRACKET(k))\n      // case BracketKind(Right(k)) => go(i + 1, CLOSE_BRACKET(k))\n      case BracketKind(Left(k)) => lex(i + 1, ind, next(i + 1, OPEN_BRACKET(k)))\n      case BracketKind(Right(k)) => lex(i + 1, ind, next(i + 1, CLOSE_BRACKET(k)))\n      case '\\n' =>\n        val j = i + 1\n        val (space, k) =\n          takeWhile(j)(c => c === ' ' || c === '\\n')\n        val nextInd = space.reverseIterator.takeWhile(_ =/= '\\n').size\n        if (ind.headOption.forall(_ < nextInd) && nextInd > 0)\n          lex(k, nextInd :: ind, (INDENT, loc(j, k)) :: acc)\n        else {\n          val newIndBase = ind.dropWhile(_ > nextInd)\n          val droppedNum = ind.size - newIndBase.size\n          val hasNewIndent = newIndBase.headOption.forall(_ < nextInd) && nextInd > 0\n          val newInd = if (hasNewIndent) nextInd :: newIndBase else newIndBase\n          if (dbg) {\n            println(\"dbg: \" + bytes.drop(i).take(10).map(escapeChar).mkString+\"...\")\n            println((ind, nextInd, newIndBase, droppedNum, hasNewIndent, newInd))\n          }\n          lex(k, newInd,\n            if (droppedNum > 0) {\n              if (hasNewIndent) (INDENT, loc(j, k))\n              else (NEWLINE, loc(i, k))\n            } :: List.fill(droppedNum)((DEINDENT, loc(j-1, k))) ::: acc\n            else (NEWLINE, loc(i, k)) :: acc\n          )\n        }\n      case _ if isIdentFirstChar(c) =>\n        val (n, j) = takeWhile(i)(isIdentChar)\n        // go(j, if (keywords.contains(n)) KEYWORD(n) else IDENT(n, isAlphaOp(n)))\n        lex(j, ind, next(j, if (keywords.contains(n)) KEYWORD(n) else IDENT(n, isAlphaOp(n))))\n      case _ if isOpChar(c) =>\n        val (n, j) = takeWhile(i)(isOpChar)\n        if (n === \".\" && j < length) {\n          val nc = bytes(j)\n          if (isIdentFirstChar(nc)) {\n            val (name, k) = takeWhile(j)(isIdentChar)\n            // go(k, SELECT(name))\n            lex(k, ind, next(k, SELECT(name)))\n          }\n          else if (\n            // The first character is '0' and the next character is not a digit\n            (nc === '0' && !(j + 1 < length && isDigit(bytes(j + 1)))) ||\n            ('0' < nc && nc <= '9') // The first character is a digit other than '0'\n          ) {\n            val (name, k) = takeWhile(j)(isDigit)\n            // go(k, SELECT(name))\n            lex(k, ind, next(k, SELECT(name)))\n          }\n          else lex(j, ind, next(j, if (isSymKeyword.contains(n)) KEYWORD(n) else IDENT(n, true)))\n        }\n        // else go(j, if (isSymKeyword.contains(n)) KEYWORD(n) else IDENT(n, true))\n        else lex(j, ind, next(j, if (isSymKeyword.contains(n)) KEYWORD(n) else IDENT(n, true)))\n      case _ if isDigit(c) =>\n        val (lit, j) = num(i)\n        // go(j, LITVAL(IntLit(BigInt(str))))\n        lex(j, ind, next(j, LITVAL(lit)))\n      case _ =>\n        pe(msg\"unexpected character '${escapeChar(c)}'\")\n        // go(i + 1, ERROR)\n        lex(i + 1, ind, next(i + 1, ERROR))\n    }\n  }\n \n  def escapeChar(ch: Char): String = ch match {\n    case '\\b' => \"\\\\b\"\n    case '\\t' => \"\\\\t\"\n    case '\\n' => \"\\\\n\"\n    case '\\f' => \"\\\\f\"\n    case '\\r' => \"\\\\r\"\n    case '\"'  => \"\\\\\\\"\"\n    case '\\'' => \"\\\\\\'\"\n    case '\\\\' => \"\\\\\\\\\"\n    case _    => if (ch.isControl) \"\\\\0\" + Integer.toOctalString(ch.toInt) \n                else              String.valueOf(ch)\n  }\n  \n  \n  lazy val tokens: Ls[Token -> Loc] = lex(0, Nil, Nil)(Nil)\n  \n  /** Converts the lexed tokens into structured tokens. */\n  lazy val bracketedTokens: Ls[Stroken -> Loc] = {\n    import BracketKind._\n    def go(toks: Ls[Token -> Loc], canStartAngles: Bool, stack: Ls[BracketKind -> Loc -> Ls[Stroken -> Loc]], acc: Ls[Stroken -> Loc]): Ls[Stroken -> Loc] =\n      toks match {\n        case (QUOTE, l0) :: (IDENT(\"<\", true), l1) :: rest =>\n          go(rest, false, stack, (IDENT(\"<\", true), l1) :: (QUOTE, l0) :: acc)\n        case (QUOTE, l0) :: (IDENT(\">\", true), l1) :: rest =>\n          go(rest, false, stack, (IDENT(\">\", true), l1) :: (QUOTE, l0) :: acc)\n        case (OPEN_BRACKET(k), l0) :: rest =>\n          go(rest, false, k -> l0 -> acc :: stack, Nil)\n        case (CLOSE_BRACKET(k1), l1) :: rest =>\n          stack match {\n            case ((Indent, loc), oldAcc) :: _ if k1 =/= Indent =>\n              go(CLOSE_BRACKET(Indent) -> l1.left :: toks, false, stack, acc)\n            case ((Indent, loc), oldAcc) :: stack\n            if k1 === Indent && acc.forall { case (SPACE | NEWLINE, _) => true; case _ => false } =>\n              // * Ignore empty indented blocks:\n              go(rest, false, stack, oldAcc)\n            case ((k0, l0), oldAcc) :: stack =>\n              if (k0 =/= k1 && !(k0 === Unquote && k1 === Curly))\n                raise(ErrorReport(msg\"Mistmatched closing ${k1.name}\" -> S(l1) ::\n                  msg\"does not correspond to opening ${k0.name}\" -> S(l0) :: Nil, newDefs = true,\n                  source = Parsing))\n              go(rest, true, stack, BRACKETS(k0, acc.reverse)(l0.right ++ l1.left) -> (l0 ++ l1) :: oldAcc)\n            case Nil =>\n              raise(ErrorReport(msg\"Unexpected closing ${k1.name}\" -> S(l1) :: Nil,\n                newDefs = true, source = Parsing))\n              go(rest, false, stack, acc)\n          }\n        case (INDENT, loc) :: rest =>\n          go(OPEN_BRACKET(Indent) -> loc :: rest, false, stack, acc)\n        case (DEINDENT, loc) :: rest =>\n          go(CLOSE_BRACKET(Indent) -> loc :: rest, false, stack, acc)\n        case (IDENT(\"<\", true), loc) :: rest if canStartAngles =>\n          go(OPEN_BRACKET(Angle) -> loc :: rest, false, stack, acc)\n        case (IDENT(\">\", true), loc) :: rest if canStartAngles && (stack match {\n          case ((Angle, _), _) :: _ => true\n          case _ => false\n        }) =>\n          go(CLOSE_BRACKET(Angle) -> loc :: rest, false, stack, acc)\n        case (IDENT(id, true), loc) :: rest\n        if (canStartAngles && id.forall(_ == '>') && id.length > 1 && (stack match {\n          case ((Angle, _), _) :: _ => true\n          case _ => false\n        })) => // split  `>>` to `>` and `>` so that code like `A<B<C>>` can be parsed correctly\n          go((CLOSE_BRACKET(Angle) -> loc.left) :: (IDENT(id.drop(1), true) -> loc) :: rest, false, stack, acc)\n        case ((tk @ IDENT(\">\", true), loc)) :: rest if canStartAngles =>\n          raise(WarningReport(\n            msg\"This looks like an angle bracket, but it does not close any angle bracket section\" -> S(loc) ::\n            msg\"Add spaces around it if you intended to use `<` as an operator\" -> N :: Nil,\n            newDefs = true, source = Parsing))\n          go(rest, false, stack, tk -> loc :: acc)\n        case (tk: Stroken, loc) :: rest =>\n          go(rest, tk match {\n            case SPACE | NEWLINE => false\n            case _ => true\n          }, stack, tk -> loc :: acc)\n        case Nil =>\n          stack match {\n            case ((Indent, loc), oldAcc) :: _ =>\n              go(CLOSE_BRACKET(Indent) -> loc/*FIXME not proper loc...*/ :: Nil, false, stack, acc)\n            case ((k, l0), oldAcc) :: stack =>\n              raise(ErrorReport(msg\"Unmatched opening ${k.name}\" -> S(l0) :: (\n                if (k === Angle)\n                  msg\"Note that `<` without spaces around it is considered as an angle bracket and not as an operator\" -> N :: Nil\n                else Nil\n              ), newDefs = true, source = Parsing))\n              (oldAcc ::: acc).reverse\n            case Nil => acc.reverse\n          }\n      }\n    \n    go(tokens, false, Nil, Nil)\n    \n  }\n  \n}\n\nobject NewLexer {\n  \n  type TokLoc = (Token, Loc)\n  \n  val keywords: Set[Str] = Set(\n    \"if\",\n    \"then\",\n    \"else\",\n    \"case\",\n    \"fun\",\n    \"val\",\n    \"var\",\n    // \"is\",\n    // \"as\",\n    \"of\",\n    // \"and\",\n    // \"or\",\n    \"let\",\n    \"rec\",\n    \"in\",\n    // \"any\",\n    // \"all\",\n    \"mut\",\n    \"set\",\n    \"do\",\n    \"while\",\n    \"declare\",\n    \"class\",\n    \"trait\",\n    \"mixin\",\n    \"interface\",\n    \"extends\",\n    \"override\",\n    \"super\",\n    \"new\",\n    \"namespace\",\n    \"module\",\n    \"type\",\n    \"where\",\n    \"forall\",\n    \"exists\",\n    \"in\",\n    \"out\",\n    \"null\",\n    \"undefined\",\n    \"abstract\",\n    \"constructor\",\n    \"virtual\"\n  )\n  \n  def printToken(tl: TokLoc): Str = tl match {\n    case (SPACE, _) => \" \"\n    case (COMMA, _) => \",\"\n    case (SEMI, _) => \";\"\n    case (NEWLINE, _) => \"↵\"\n    case (INDENT, _) => \"→\"\n    case (DEINDENT, _) => \"←\"\n    case (ERROR, _) => \"<error>\"\n    case (QUOTE, _) => \"`\"\n    case (LITVAL(lv), _) => lv.idStr\n    case (KEYWORD(name: String), _) => \"#\" + name\n    case (IDENT(name: String, symbolic: Bool), _) => name\n    case (SELECT(name: String), _) => \".\" + name\n    case (OPEN_BRACKET(k), _) => k.beg\n    case (CLOSE_BRACKET(k), _) => k.end\n    case (BRACKETS(k @ BracketKind.Indent, contents), _) =>\n      k.beg + printTokens(contents) + k.end\n    case (BRACKETS(k, contents), _) =>\n      k.beg + printTokens(contents) + k.end\n    case (COMMENT(text: String), _) => \"/*\" + text + \"*/\"\n  }\n  def printTokens(ts: Ls[TokLoc]): Str =\n    ts.iterator.map(printToken).mkString(\"|\", \"|\", \"|\")\n  \n  \n\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/NewParser.scala",
    "content": "package mlscript\n\nimport scala.util.chaining._\nimport scala.annotation.tailrec\nimport sourcecode.{Name, Line}\n\nimport utils._, shorthands._\nimport mlscript.Message._\nimport BracketKind._\n\nobject NewParser {\n  \n  type ExpectThen >: Bool\n  type FoundErr >: Bool  // may be better done as:  class FoundErr(var found: Bool)\n  \n  final def expectThen(implicit ptr: ExpectThen): Bool = ptr === true\n  final def foundErr(implicit ptr: FoundErr): Bool = ptr === true\n  \n  type TokLoc = (Stroken, Loc)\n  \n  type LTL = Ls[TokLoc]\n  \n  private val MinPrec = 0\n  private val NoElsePrec = MinPrec + 1\n  \n  private val prec: Map[Char,Int] =\n    List(\n      \"\", // 0 is the virtual precedence of 'else'\n      \"\",\n      \"\",\n      \"\",\n      \"\",\n      \"\",\n      // ^ for keywords\n      // \";\",\n      \",\",\n      \"=\",\n      \"@\",\n      \":\",\n      \"|\",\n      \"/ \\\\\",\n      \"^\",\n      \"&\",\n      // \"= !\",\n      \"!\",\n      \"< >\",\n      \"+ -\",\n      // \"* / %\",\n      \"* %\",\n      \"\", // Precedence of application\n      \".\",\n    ).zipWithIndex.flatMap {\n      case (cs, i) => cs.filterNot(_ === ' ').map(_ -> (i + 1))\n    }.toMap.withDefaultValue(Int.MaxValue)\n  \n  private val AppPrec = prec('.') - 1\n  \n  final def opCharPrec(opChar: Char): Int = prec(opChar)\n  final def opPrec(opStr: Str): (Int, Int) = opStr match {\n    case \"is\" => (4, 4)\n    case \"and\" => (3, 3)\n    case \"or\" => (2, 2)\n    case \"=>\" =>\n      // * The lambda operator is special:\n      // *  it should associate very strongly on the left and very loosely on the right\n      // *  so that we can write things like `f() |> x => x is 0` ie `(f()) |> (x => (x is 0))`\n      val eqPrec = prec('.') // * We pick the tightest precedence\n      (eqPrec, 1)\n      // * Note: we used to do this instead which broke the example above on both sides:\n      // val eqPrec = prec('=')\n      // (eqPrec, eqPrec - 1)\n    case \"+.\" | \"-.\" | \"*.\" =>\n      (prec(opStr.head), prec(opStr.head))\n    case _ if opStr.exists(_.isLetter) =>\n      (5, 5)\n    case _ =>\n      val r = opStr.last\n      (prec(opStr.head), prec(r) - (if (r === '@' || r === '/' || r === ',' || r === ':') 1 else 0))\n  }\n  \n}\nimport NewParser._\n\nabstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bool, raiseFun: Diagnostic => Unit, val dbg: Bool, fallbackLoc: Opt[Loc], description: Str = \"input\") {\n  outer =>\n  \n  private var freshCnt: Int = 0\n  final def freshVar: Var = {\n    val res = Var(\"_$\" + freshCnt)\n    freshCnt += 1\n    res\n  }\n  \n  object Spaces {\n    def unapply(xs: Ls[Stroken -> Loc]): S[(() => Unit, Ls[Stroken -> Loc])] = xs match {\n      case (SPACE, _) :: Spaces(cons, rest) => S((() => {cons(); consume}, rest))\n      case _ => S(() => (), xs)\n    }\n  }\n  \n  final def rec(tokens: Ls[Stroken -> Loc], fallbackLoc: Opt[Loc], description: Str): NewParser =\n    new NewParser(origin, tokens, newDefs, raiseFun, dbg, fallbackLoc, description) {\n      def doPrintDbg(msg: => Str): Unit = outer.printDbg(\"> \" + msg)\n    }\n  \n  final def raise(mkDiag: => Diagnostic)(implicit fe: FoundErr = false): Unit =\n    if (!foundErr) raiseFun(mkDiag)\n  \n  final def err(msgs: Ls[Message -> Opt[Loc]]): Unit =\n    raise(ErrorReport(msgs, newDefs = true, source = Diagnostic.Parsing))\n  \n  final def mkLoc(l: Int, r: Int): Loc =\n    Loc(l, r, origin)\n\n  protected def doPrintDbg(msg: => Str): Unit\n  protected def printDbg(msg: => Any): Unit =\n    doPrintDbg(\"│ \" * this.indent + msg)\n  protected var indent = 0\n  private def wrap[R](args: => Any)(mkRes: Unit => R)(implicit l: Line, n: Name): R = {\n    printDbg(s\"@ ${n.value}${args match {\n      case it: Iterable[_] => it.mkString(\"(\", \",\", \")\")\n      case _: Product => args\n      case _ => s\"($args)\"\n    }}    [at l.${l.value}]\")\n    val res = try {\n      indent += 1\n      // mkRes\n      mkRes(())\n    } finally indent -= 1\n    printDbg(s\"= $res\")\n    res\n  }\n  \n  final def parseAll[R](parser: => R): R = {\n    val res = parser\n    cur match {\n      case c @ (tk, tkl) :: _ =>\n        val (relevantToken, rl) = c.dropWhile(_._1 === SPACE).headOption.getOrElse(tk, tkl)\n        err(msg\"Expected end of input; found ${relevantToken.describe} instead\" -> S(rl) :: Nil)\n      case Nil => ()\n    }\n    res\n  }\n  \n  final def concludeWith[R](f: this.type => R): R = {\n    val res = f(this)\n    cur.dropWhile(tk => (tk._1 === SPACE || tk._1 === NEWLINE) && { consume; true }) match {\n      case c @ (tk, tkl) :: _ =>\n        val (relevantToken, rl) = c.dropWhile(_._1 === SPACE).headOption.getOrElse(tk, tkl)\n        err(msg\"Unexpected ${relevantToken.describe} here\" -> S(rl) :: Nil)\n      case Nil => ()\n    }\n    printDbg(s\"Concluded with $res\")\n    res\n  }\n  \n  // def pe(msg: Message, l: Loc, rest: (Message, Opt[Loc])*): Unit =\n  //   err((msg -> S(l) :: rest.toList)) // TODO parse err\n  \n  \n  \n  private var _cur: Ls[TokLoc] = tokens\n  private var _modifiersCache: ModifierSet = ModifierSet.empty\n  def resetCur(newCur: Ls[TokLoc]): Unit = {\n    _cur = newCur\n    _modifiersCache = ModifierSet.empty\n  }\n  \n  private def summarizeCur =\n    NewLexer.printTokens(_cur.take(5)) + (if (_cur.sizeIs > 5) \"...\" else \"\")\n  \n  private def cur(implicit l: Line, n: Name) = {\n    if (dbg) printDbg(s\"? ${n.value}\\t\\tinspects ${summarizeCur}    [at l.${l.value}]\")\n    while (!_cur.isEmpty && (_cur.head._1 match {\n      case COMMENT(_) => true\n      case _ => false\n    })) consume\n    _cur\n  }\n  \n  final def consume(implicit l: Line, n: Name): Unit = {\n    if (dbg) printDbg(s\"! ${n.value}\\t\\tconsumes ${NewLexer.printTokens(_cur.take(1))}    [at l.${l.value}]\")\n    resetCur(_cur.tailOption.getOrElse(Nil)) // FIXME throw error if empty?\n  }\n  \n  // TODO simplify logic – this is no longer used much\n  final def skip(tk: Stroken, ignored: Set[Stroken] = Set(SPACE), allowEnd: Bool = false, note: => Ls[Message -> Opt[Loc]] = Nil)\n        (implicit fe: FoundErr): (Bool, Opt[Loc]) = wrap(tk, ignored, allowEnd) { l =>\n    require(!ignored(tk))\n    val skip_res = cur match {\n      case (tk2, l2) :: _ =>\n        if (ignored(tk2)) {\n          consume\n          return skip(tk, ignored, allowEnd, note)\n        } else if (tk2 =/= tk) {\n          if (!foundErr) err((\n            msg\"Expected ${tk.describe}; found ${tk2.describe} instead\" -> S(l2) :: note))\n          (false, S(l2))\n        } else (true, S(l2))\n      case Nil =>\n        if (!allowEnd)\n          if (!foundErr) err((\n            msg\"Expected ${tk.describe}; found end of input instead\" -> lastLoc :: note))\n        (allowEnd, N)\n    }\n    consume\n    skip_res\n  }\n  \n  private lazy val lastLoc =\n    tokens.lastOption.map(_._2.right).orElse(fallbackLoc)\n  \n  private def curLoc = _cur.headOption.map(_._2)\n  \n  /* // * TODO rm\n  final def blockTerm: Blk = {\n    val ts = block(false, false)\n    val es = ts.map {\n      case L(t) =>\n        err(msg\"Unexpected 'then'/'else' clause\" -> t.toLoc :: Nil)\n        errExpr\n      case R(e) => e\n    }\n    Blk(es)\n  }\n  */\n  \n  final def typingUnit: TypingUnit = {\n    val ts = block(false, false)\n    val es = ts.map {\n      case L(t) =>\n        err(msg\"Unexpected 'then'/'else' clause\" -> t.toLoc :: Nil)\n        errExpr\n      case R(d: NuDecl) => d\n      case R(e: Term) => e\n      case R(c: Constructor) => c\n      case _ => ???\n    }\n    TypingUnit(es)\n  }\n  final def typingUnitMaybeIndented(implicit fe: FoundErr): TypingUnit = yeetSpaces match {\n    case (br @ BRACKETS(Indent, toks), _) :: _ =>\n      consume\n      rec(toks, S(br.innerLoc), br.describe).concludeWith(_.typingUnit)\n    case _ => typingUnit\n  }\n  final def curlyTypingUnit(implicit fe: FoundErr): Opt[TypingUnit] = yeetSpaces match {\n    case (br @ BRACKETS(Curly, toks), l1) :: _ =>\n      consume\n      S(rec(toks, S(br.innerLoc), br.describe).concludeWith(_.typingUnitMaybeIndented).withLoc(S(l1)))\n    case _ =>\n      N\n  }\n  \n  final def toParamsTy(t: Type): Tuple = t match {\n    case t: Tuple => t\n    case _ => Tuple((N, Field(None, t)) :: Nil)\n  }\n  final def typ(prec: Int = 0)(implicit fe: FoundErr, l: Line): Type =\n    mkType(expr(prec))\n  \n  case class ModifierSet(mods: Map[Str, Loc]) {\n    def handle(mod: Str): (Opt[Loc], ModifierSet) =\n      mods.get(mod) -> copy(mods = mods - mod)\n    def done: Unit = mods.foreachEntry { (mod, loc) =>\n      err(msg\"Unrecognized modifier `${mod}` in this position\" -> S(loc) :: Nil)\n    }\n  }\n  object ModifierSet {\n    val empty: ModifierSet = ModifierSet(Map.empty)\n    private def go(acc: ModifierSet): ModifierSet = cur match {\n      case (KEYWORD(kw), l0) :: c if acc.mods.contains(kw) =>\n        err(msg\"Repeated modifier `${kw}`\" -> S(l0) :: Nil)\n        consume\n        yeetSpaces\n        go(acc)\n      case (KEYWORD(\"declare\"), l0) :: c =>\n        consume\n        yeetSpaces\n        go(acc.copy(acc.mods + (\"declare\" -> l0)))\n      case (KEYWORD(\"virtual\"), l0) :: c =>\n        consume\n        yeetSpaces\n        go(acc.copy(acc.mods + (\"virtual\" -> l0)))\n      case (KEYWORD(\"mut\"), l0) :: c =>\n        consume\n        yeetSpaces\n        go(acc.copy(acc.mods + (\"mut\" -> l0)))\n      case (KEYWORD(\"abstract\"), l0) :: c =>\n        consume\n        yeetSpaces\n        go(acc.copy(acc.mods + (\"abstract\" -> l0)))\n      case _ if acc.mods.isEmpty => acc\n      case (KEYWORD(\"class\" | \"infce\" | \"trait\" | \"mixin\" | \"type\" | \"namespace\" | \"module\" | \"fun\" | \"val\" | \"let\"), l0) :: _ =>\n        acc\n      case (tok, loc) :: _ =>\n        // TODO support indented blocks of modified declarations...\n        err(msg\"Unexpected ${tok.describe} token after modifier${if (acc.mods.sizeIs > 1) \"s\" else \"\"}\" -> S(loc) :: Nil)\n        acc\n      case Nil =>\n        ??? // TODO:\n    }\n    def unapply(__ : Ls[TokLoc]): S[ModifierSet -> Ls[TokLoc]] = {\n      val res = go(_modifiersCache)\n      _modifiersCache = res\n      S(res, _cur)\n    }\n  }\n  final def block(implicit et: ExpectThen, fe: FoundErr): Ls[IfBody \\/ Statement] = {\n    val annotations = parseAnnotations(true)\n\n    cur match {\n      case Nil => Nil\n      case (NEWLINE, _) :: _ => consume; block\n      case (SPACE, _) :: _ => consume; block\n      case (KEYWORD(\"constructor\"), l0) :: _ =>\n        consume\n        val res = yeetSpaces match {\n          case (br @ BRACKETS(Round, toks), loc) :: _ =>\n            consume\n            val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) // TODO\n            val body = curlyTypingUnit.getOrElse(TypingUnit(Nil))\n            Constructor(Tup(as).withLoc(S(loc)), Blk(body.entities).withLocOf(body))\n          case _ =>\n            err(msg\"Expect parameter list for the constructor\" -> S(l0) :: Nil)\n            Constructor(Tup(Nil), Blk(Nil))\n        }\n        R(res.withLoc(S(l0 ++ res.getLoc))) :: block\n      case c =>\n        val t = c match {\n          case ModifierSet(mods, (KEYWORD(k @ (\"class\" | \"infce\" | \"trait\" | \"mixin\" | \"type\" | \"module\")), l0) :: c) =>\n            consume\n            val (isDecl, mods2) = mods.handle(\"declare\")\n            val (isAbs, mods3) = mods2.handle(\"abstract\")\n            mods3.done\n            val kind = k match {\n              case \"class\" => Cls\n              case \"trait\" => Trt\n              case \"mixin\" => Mxn\n              case \"type\" => Als\n              case \"module\" => Mod\n              case _ => die\n            }\n            val (tn, success) = yeetSpaces match {\n              case (IDENT(idStr, _), l1) :: _ =>\n                consume\n                (TypeName(idStr).withLoc(S(l1)), true)\n              case c =>\n                val (tkstr, loc) = c.headOption.fold((\"end of input\", lastLoc))(_.mapFirst(_.describe).mapSecond(some))\n                err((\n                  msg\"Expected a type name; found ${tkstr} instead\" -> loc :: Nil))\n                consume\n                // R(errExpr)\n                (TypeName(\"<error>\").withLoc(curLoc.map(_.left)), false)\n            }\n            val tparams = yeetSpaces match {\n              case (br @ BRACKETS(Angle | Square, toks), loc) :: _ =>\n                consume\n                /* \n                val ts = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map {\n                  case (N, Fld(false, false, v @ Var(nme))) =>\n                    TypeName(nme).withLocOf(v)\n                  case nmeo -> param =>\n                    err(msg\"unsupported type parameter shape (${param.describe})\" ->\n                      param.value.toLoc :: Nil)\n                    TypeName(nmeo.fold(\"<error>\")(_.name)).withLocOf(param.value)\n                }\n                ts\n                */\n                rec(toks, S(br.innerLoc), br.describe).concludeWith(_.maybeIndented((p, _) => p.typeParams))\n              case _ => Nil\n            }\n            val params = yeetSpaces match {\n              case (br @ BRACKETS(Round, toks), loc) :: _ =>\n                consume\n                val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) // TODO\n                S(Tup(as).withLoc(S(loc)))\n              case _ => N\n            }\n            def otherParents: Ls[Term] = yeetSpaces match {\n              case (COMMA, _) :: _ =>\n                consume\n                expr(prec(',')) :: otherParents // we don't want to parse parent lists as including comma expressions\n              case _ => Nil\n            }\n            val sigTrm = yeetSpaces match {\n              case (KEYWORD(\"=\"), _) :: _ if kind is Als =>\n                consume\n                S(expr(0))\n              case (KEYWORD(\":\"), _) :: _ if !(kind is Als) =>\n                consume\n                S(expr(0))\n              case _ => N\n            }\n            val ps = yeetSpaces match {\n              // case (KEYWORD(\"=\"), _) :: _ if kind is Als =>\n              //   consume\n              //   expr(0) :: otherParents\n              case (KEYWORD(\"extends\"), _) :: _ =>\n                consume\n                expr(prec(',')) :: otherParents // we don't want to parse parent lists as including comma expressions\n              case _ => Nil\n            }\n            val (sigTrm2, ps2, fullTu) = curlyTypingUnit.fold {\n              ps.lastOption match {\n                case S(Rft(bse, tu)) => (sigTrm, (bse :: ps.reverse.tail).reverse, tu)\n                case _ =>\n                  sigTrm match {\n                    case S(Rft(bse, tu)) => (S(bse), ps, tu)\n                    case _ =>\n                      (sigTrm, ps, TypingUnit(Nil))\n                  }\n              }\n            }(tu => (sigTrm, ps, tu))\n            val sig = sigTrm2.map(mkType(_))\n            val (ctors, bodyStmts) = fullTu.entities.partitionMap {\n              case c: Constructor => L(c)\n              case t => R(t)\n            }\n            val tu = TypingUnit(bodyStmts).withLocOf(fullTu)\n            if (ctors.lengthIs > 1) {\n              err(msg\"A class may have at most one explicit constructor\" -> S(l0) :: Nil)\n              N\n            }\n            val ctor = ctors.headOption\n            val res =\n              NuTypeDef(kind, tn, tparams, params, ctor, sig, ps2, N, N, tu)(isDecl, isAbs, annotations)\n            R(res.withLoc(S(l0 ++ tn.getLoc ++ res.getLoc)))\n            R(res.withLoc(S(l0 ++ res.getLoc)))\n          \n          case ModifierSet(mods, (KEYWORD(kwStr @ (\"fun\" | \"val\" | \"let\")), l0) :: c) => // TODO support rec?\n            consume\n            val (isDecl, mods2) = mods.handle(\"declare\")\n            val (isVirtual, mods3) = mods2.handle(\"virtual\")\n            val (isMut, mods4) = mods3.handle(\"mut\")\n            mods4.done\n            val genField = kwStr =/= \"let\"\n            val isLetRec = yeetSpaces match {\n              case (KEYWORD(\"rec\"), l1) :: _ if kwStr === \"let\" =>\n                consume\n                S(true)\n              case c => if (kwStr === \"fun\") N else S(false)\n            }\n            val opStr = yeetSpaces match {\n              case (BRACKETS(Round, ts), brackloc) :: _ =>\n                ts match {\n                  case (IDENT(opStr, true), l1) :: rest =>\n                    consume\n                    rest.dropWhile(_._1 === SPACE) match {\n                      case Nil =>\n                      case (tok, loc) :: ts =>\n                        err((msg\"Unexpected ${tok.describe} after symbolic name\" -> S(loc) :: Nil))\n                    }\n                    S(Var(opStr).withLoc(S(l1)))\n                  case (tok, loc) :: _ =>\n                    consume\n                    err((msg\"Expected a symbolic name, found ${tok.describe} instead\" -> S(loc) :: Nil))\n                    N\n                  case Nil =>\n                    consume\n                    err((msg\"Expected a symbolic name between brackets, found nothing\" -> S(brackloc) :: Nil))\n                    N\n                }\n              case _ => N\n            }\n            val (v, success) = yeetSpaces match {\n              case (IDENT(idStr, false), l1) :: _ =>\n                consume\n                (Var(idStr).withLoc(S(l1)), true)\n              case c =>\n                val (tkstr, loc) = c.headOption.fold((\"end of input\", lastLoc))(_.mapFirst(_.describe).mapSecond(some))\n                err((msg\"Expected a function name; found ${tkstr} instead\" -> loc :: Nil))\n                consume\n                // R(errExpr)\n                (Var(\"<error>\").withLoc(curLoc.map(_.left)), false)\n            }\n            foundErr || !success pipe { implicit fe =>\n              val tparams = if (kwStr === \"let\") Ls[TypeName]() else yeetSpaces match {\n                case (br @ BRACKETS(Angle | Square, toks), loc) :: _ =>\n                  consume\n                  val ts = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map {\n                    case (N, Fld(FldFlags(false, false, _), v @ Var(nme))) =>\n                      TypeName(nme).withLocOf(v)\n                    case _ => ???\n                  }\n                  ts\n                case _ => Nil\n              }\n              val (ps, transformBody) = yeetSpaces match {\n                case (br @ BRACKETS(Round, Spaces(cons, (KEYWORD(\"override\"), ovLoc) :: rest)), loc) :: rest2 =>\n                  resetCur(BRACKETS(Round, rest)(br.innerLoc) -> loc :: rest2)\n                  funParams match {\n                    case ps @ Tup(N -> Fld(FldFlags(false, false, gen), pat) :: Nil) :: Nil =>\n                      val fv = freshVar\n                      (Tup(N -> Fld(FldFlags(false, false, gen), fv) :: Nil) :: Nil, S(\n                        (body: Term) => If(IfOpApp(fv, Var(\"is\"), IfThen(pat, body)), S(\n                          App(Sel(Super().withLoc(S(ovLoc)), v), Tup(N -> Fld(FldFlags(false, false, gen), fv) :: Nil))\n                        ))\n                      ))\n                    case r =>\n                      err(msg\"Unsupported 'override' parameter list shape\" -> S(br.innerLoc) :: Nil)\n                      (r, N)\n                  }\n                case _ =>\n                  (funParams, N)\n              }\n              val asc = yeetSpaces match {\n                case (KEYWORD(\":\"), _) :: _ =>\n                  consume\n                  // S(typ(2))\n                  S(typ(0))\n                case _ => N\n              }\n              yeetSpaces match {\n                case (KEYWORD(\"=\"), _) :: _ =>\n                  consume\n                  val body = expr(0)\n                  val newBody = transformBody.fold(body)(_(body))\n                  val annotatedBody = asc.fold(newBody)(ty => Asc(newBody, ty))\n                  yeetSpaces match {\n                    case (KEYWORD(\"in\"), l1) :: _ if kwStr === \"let\" =>\n                      consume\n                      if (tparams.nonEmpty) err(msg\"Unsupported type parameters on 'let' binding\" -> S(l1) :: Nil)\n                      val rest = expr(0)\n                      R(Let(isLetRec.getOrElse(die), v, annotatedBody, rest).withLoc(S(l0 ++ annotatedBody.toLoc)))\n                    case _ =>\n                      R(NuFunDef(\n                          isLetRec, v, opStr, tparams, L(ps.foldRight(annotatedBody)((i, acc) => Lam(i, acc)))\n                        )(isDecl, isVirtual, isMut, N, N, genField, annotations).withLoc(S(l0 ++ annotatedBody.toLoc)))\n                  }\n                case c =>\n                  asc match {\n                    case S(ty) =>\n                      if (transformBody.nonEmpty) die // TODO\n                      R(NuFunDef(isLetRec, v, opStr, tparams, R(PolyType(Nil, ps.foldRight(ty)((p, r) => Function(p.toType match {\n                        case L(diag) => raise(diag); Top // TODO better\n                        case R(tp) => tp\n                      }, r)))))(isDecl, isVirtual, isMut, N, N, genField, annotations).withLoc(S(l0 ++ ty.toLoc)))\n                      // TODO rm PolyType after FCP is merged\n                    case N =>\n                      // TODO dedup:\n                      val (tkstr, loc) = c.headOption.fold((\"end of input\", lastLoc))(_.mapFirst(_.describe).mapSecond(some))\n                      err((\n                        msg\"Expected ':' or '=' followed by a function body or signature; found ${tkstr} instead\" -> loc :: Nil))\n                      consume\n                      val bod = errExpr\n                      R(NuFunDef(\n                          isLetRec, v, opStr, Nil, L(ps.foldRight(bod: Term)((i, acc) => Lam(i, acc)))\n                        )(isDecl, isVirtual, isMut, N, N, genField, annotations).withLoc(S(l0 ++ bod.toLoc)))\n                  }\n              }\n            }\n          case _ =>\n            exprOrIf(0, allowSpace = false, annotations = annotations)\n        }\n        val finalTerm = yeetSpaces match {\n          case (KEYWORD(\"=\"), l0) :: _ => t match {\n            case R(v: Var) =>\n              consume\n              R(Eqn(v, expr(0)))\n            case R(App(v: Var, args)) =>\n              consume\n              R(Eqn(v, Lam(args, expr(0))))\n            case _ => t\n          }\n          case _ => t\n        }\n        \n        yeetSpaces match {\n          case (SEMI, _) :: _ => consume; finalTerm :: block\n          case (NEWLINE, _) :: _ => consume; finalTerm :: block\n          case _ => finalTerm :: Nil\n        }\n    }\n  }\n\n  private def parseAnnotations(allowNewLines: Bool): Ls[Term] = {\n    @tailrec\n    def rec(acc: Ls[Term]): Ls[Term] = cur match {\n      case (SPACE, _) :: c => \n        consume\n        rec(acc)\n      case (NEWLINE, _) :: c if allowNewLines =>\n        consume\n        rec(acc)\n      case (IDENT(\"@\", true), l0) :: c => {\n        consume\n        val (name, loc) = c match {\n          case (IDENT(nme, false), l1) :: next => (nme, l1)\n          case c =>\n            val (tkstr, loc) = c.headOption.fold((\"end of input\", lastLoc))(_.mapFirst(_.describe).mapSecond(some))\n            err((msg\"Expected an identifier; found ${tkstr} instead\" -> loc :: Nil))\n            (\"<error>\", l0)\n        }\n        consume\n\n        val annotation = Var(name).withLoc(S(loc))\n        rec(annotation :: acc)\n      }\n      case _ => acc.reverse\n    }\n    rec(Nil)\n  }\n  \n  private def yeetSpaces: Ls[TokLoc] =\n    cur.dropWhile(tkloc =>\n      (tkloc._1 === SPACE\n      || tkloc._1.isInstanceOf[COMMENT] // TODO properly retrieve and sotre all comments in AST?\n      ) && { consume; true })\n  \n  final def funParams(implicit et: ExpectThen, fe: FoundErr, l: Line): Ls[Tup] = wrap(()) { l =>\n    yeetSpaces match {\n      case (KEYWORD(\"=\" | \":\"), _) :: _ => Nil\n      case (KEYWORD(\"of\"), _) :: _ =>\n        consume\n        Tup(args(false) // TODO\n          ) :: funParams\n      case (br @ BRACKETS(Round, toks), loc) :: _ =>\n        consume\n        val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) // TODO\n        Tup(as).withLoc(S(loc)) :: funParams\n      case (tk, l0) :: _ =>\n        err((\n          // msg\"Expected a function name; found ${\"[TODO]\"} instead\" -> N :: Nil))\n          msg\"Expected function parameter list; found ${tk.describe} instead\" -> S(l0) :: Nil))\n        consume\n        Nil\n      case Nil => Nil\n    }\n  }\n  \n  private def unexpectedThenElse(loc: Opt[Loc]) = {\n    err(msg\"Expected an expression; found a 'then'/'else' clause instead\" -> loc :: Nil)\n    errExpr\n  }\n\n  private def unsupportedQuote(loc: Opt[Loc]) = {\n    err(msg\"This quote syntax is not supported yet\" -> loc :: Nil)\n    errExpr\n  }\n  \n  final def expr(prec: Int, allowSpace: Bool = true)(implicit fe: FoundErr, l: Line): Term = wrap(prec,allowSpace) { l =>\n    exprOrIf(prec, allowSpace)(et = false, fe = fe, l = implicitly) match {\n      case R(e) => e\n      case L(e) => unexpectedThenElse(e.toLoc)\n    }\n  }\n  \n  def exprOrBlockContinuation(implicit et: ExpectThen, fe: FoundErr, l: Line): Term =\n    yeetSpaces match {\n      case (NEWLINE, l0) :: _ =>\n        consume\n        val stmts = block\n        val es = stmts.map { case L(t) => unexpectedThenElse(t.toLoc); case R(e) => e }\n        Blk(es)\n      case _ => expr(0)\n    }\n  \n  private def warnDbg(msg: Any, loco: Opt[Loc] = curLoc): Unit =\n    raise(WarningReport(msg\"[${cur.headOption.map(_._1).mkString}] ${\"\"+msg}\" -> loco :: Nil,\n      newDefs = true))\n  \n  private def letBindings(genQuote: Bool)(implicit et: ExpectThen, fe: FoundErr, l: Line): IfBody \\/ Term = {\n    val bs = bindings(Nil)\n    val body =\n      if (genQuote) yeetSpaces match {\n        case (QUOTE, l1) :: (KEYWORD(\"in\"), l2) :: _ =>\n          consume\n          consume\n          exprOrIf(0)(et, fe, implicitly)\n        case (NEWLINE, _) :: _ =>\n          consume\n          val stmts = block\n          val es = stmts.map { case L(t) => unexpectedThenElse(t.toLoc); case R(e) => e }\n          R(Blk(es))\n        case (tk, loc) :: _ =>\n          err(msg\"Expected '`in'; found ${tk.describe} instead\" -> S(loc) :: Nil)\n          R(errExpr)\n        case Nil =>\n          err(msg\"Expected '`in'; found end of input instead\" -> lastLoc :: Nil)\n          R(errExpr)\n      }\n      else yeetSpaces match {\n        case (KEYWORD(\"in\") | SEMI, _) :: _ =>\n          consume\n          exprOrIf(0)(et, fe, implicitly)\n        case (NEWLINE, _) :: _ =>\n          consume\n          exprOrIf(0)(et, fe, implicitly)\n        case _ =>\n          R(UnitLit(true).withLoc(curLoc.map(_.left)))\n      }\n    bs.foldRight(body) {\n      case ((v, r), R(acc)) if genQuote => R(Quoted(Let(false, v, Unquoted(r), Unquoted(acc))))\n      case ((v, r), R(acc)) => R(Let(false, v, r, acc))\n      case ((v, r), L(acc)) if genQuote => R(unsupportedQuote(acc.toLoc))\n      case ((v, r), L(acc)) => L(IfLet(false, v, r, acc))\n    }\n  }\n\n  final def exprOrIf(prec: Int, allowSpace: Bool = true, annotations: Ls[Term] = Nil)(implicit et: ExpectThen, fe: FoundErr, l: Line): IfBody \\/ Term = wrap(prec, allowSpace) { l =>\n    val moreAnnotations: Ls[Term] = parseAnnotations(false)\n\n    if (moreAnnotations.nonEmpty) {\n      yeetSpaces\n    }\n\n    val allAnns = annotations ++ moreAnnotations\n    \n    val res = cur match {\n      case (SPACE, l0) :: _ if allowSpace => // Q: do we really need the `allowSpace` flag?\n        consume\n        exprOrIf(prec, allowSpace)\n      case (br @ BRACKETS(Indent, toks), _) :: _ if (toks.headOption match { // TODO factor\n        case S((KEYWORD(\"then\" | \"else\"), _)) => false\n        case _ => true\n      }) =>\n        consume\n        val ts = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.block)\n        val es = ts.map { case L(t) => return L(IfBlock(ts)); case R(e) => e }\n        R(Blk(es))\n      case (QUOTE, loc) :: _ =>\n        consume\n        cur match {\n          case (IDENT(nme, false), l0) :: _ =>\n            consume\n            exprCont(Quoted(Var(nme)).withLoc(S(loc ++ l0)), prec, allowNewlines = false)\n          case (LITVAL(lit), l0) :: _ =>\n            consume\n            exprCont(Quoted(lit.withLoc(S(l0))).withLoc(S(loc ++ l0)), prec, allowNewlines = false)\n          case (KEYWORD(\"let\"), l0) :: _ =>\n            consume\n            letBindings(true) match {\n              case R(bd) => R(bd.withLoc(S(loc ++ bd.toLoc)))\n              case _ => R(unsupportedQuote(S(l0)))\n            }\n          case (KEYWORD(\"if\"), l0) :: _ =>\n            val term = exprOrIf(prec, allowSpace)\n            term match {\n              case R(it @ If(IfThen(cond, body), els)) =>\n                R(Quoted(If(IfThen(Unquoted(cond), Unquoted(body)), els.map(els => Unquoted(els)))).withLoc(S(loc ++ it.toLoc)))\n              case _ => R(unsupportedQuote(S(l0)))\n            }\n          case (br @ BRACKETS(bk @ Round, toks), loc) :: _ =>\n            consume\n            val res = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()) match {\n              case (N, Fld(FldFlags(false, false, _), elt)) :: Nil => Quoted(Bra(false, elt)).withLoc(S(loc ++ elt.toLoc))\n              case _ => unsupportedQuote(S(loc))\n            }\n            exprCont(res, prec, allowNewlines = false)\n          case _ => R(unsupportedQuote(S(loc)))\n        }\n      case (LITVAL(lit), l0) :: _ =>\n        consume\n        exprCont(lit.withLoc(S(l0)), prec, allowNewlines = false)\n      case (KEYWORD(kwStr @ (\"undefined\" | \"null\")), l0) :: _ =>\n        consume\n        exprCont(UnitLit(kwStr === \"undefined\").withLoc(S(l0)), prec, allowNewlines = false)\n      case (IDENT(nme, false), l0) :: _ =>\n        consume\n        exprCont(Var(nme).withLoc(S(l0)), prec, allowNewlines = false)\n      case (br @ BRACKETS(Quasiquote | QuasiquoteTriple, toks), loc) :: _ =>\n        consume\n        val body = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.expr(0))\n        exprCont(Quoted(body).withLoc(S(loc)), prec, allowNewlines = false)\n      case (br @ BRACKETS(Unquote, toks), loc) :: _ =>\n        consume \n        val body = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.expr(0))\n        exprCont(Unquoted(body).withLoc(S(loc)), prec, allowNewlines = false)\n      case (KEYWORD(\"super\"), l0) :: _ =>\n        consume\n        exprCont(Super().withLoc(S(l0)), prec, allowNewlines = false)\n      case (IDENT(\"~\", _), l0) :: _ =>\n        consume\n        val rest = expr(prec, allowSpace = true)\n        exprCont(App(Var(\"~\").withLoc(S(l0)), rest).withLoc(S(l0 ++ rest.toLoc)), prec, allowNewlines = false)\n      case (BRACKETS(Round, (IDENT(opStr, true), l1) :: Nil), l0) :: _ =>\n        consume\n        exprCont(Var(opStr).withLoc(S(l1)), prec, allowNewlines = false)\n      case (br @ BRACKETS(bk @ (Round | Square | Curly), toks), loc) :: _ =>\n        consume\n        val res = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented())\n        val bra = (bk, res) match {\n          case (Curly, _) =>\n            Bra(true, Rcd(res.map {\n              case S(n) -> fld => n -> fld\n              case N -> (fld @ Fld(_, v: Var)) => v -> fld\n              case N -> fld =>\n                err((\n                  msg\"Record field should have a name\" -> fld.value.toLoc :: Nil))\n                Var(\"<error>\") -> fld\n            }))\n          case (Round, (N, Fld(FldFlags(false, false, _), elt)) :: Nil) =>\n            Bra(false, elt)\n          case (Round, _) =>\n            yeetSpaces match {\n              case (KEYWORD(opStr @ \"=>\"), l1) :: (NEWLINE, l2) :: _ /* if opPrec(opStr)._1 > prec */ =>\n                consume\n                val rhs = Blk(typingUnit.entities)\n                Lam(Tup(res), rhs)\n              case (KEYWORD(\"=>\"), l1) :: _ =>\n                consume\n                val e = expr(NewParser.opPrec(\"=>\")._2)\n                Lam(Tup(res), e)\n              case (QUOTE, l0) :: (KEYWORD(\"=>\"), l1) :: _ =>\n                exprCont(Tup(res), 0, true) match {\n                  case L(t) => unsupportedQuote(t.toLoc)\n                  case R(t) => t\n                }\n              case (IDENT(\"->\", true), l1) :: _ =>\n                consume\n                val rhs = expr(opPrec(\"->\")._2)\n                Lam(Tup(res), rhs)\n              case _ =>\n                res match {\n                  case Nil =>\n                    UnitLit(true)\n                  case _ =>\n                    res.map {\n                      case N -> Fld(FldFlags.empty, t) => t\n                      case no -> Fld(_, t) =>\n                        err((msg\"Illegal position for field specification\" -> Loc(no.toList :+ t) :: Nil))\n                        t\n                    }.reduceRight((t, acc) =>\n                      App(Var(\",\").withLoc(Loc(t :: acc :: Nil)), PlainTup(t, acc)))\n                }\n            }\n          case _ =>\n            Tup(res)\n        }\n        exprCont(bra.withLoc(S(loc)), prec, allowNewlines = false)\n      case (KEYWORD(\"forall\"), l0) :: _ =>\n        consume\n        def getIdents: Ls[TypeVar] = yeetSpaces match {\n          case (IDENT(nme, false), l0) :: _ =>\n            consume\n            val res = TypeVar(R(nme), N).withLoc(S(l0))\n            yeetSpaces match {\n              case (COMMA, _) :: _ =>\n                consume\n                res :: getIdents\n              case _ => res :: Nil\n            }\n          case _ => Nil\n        }\n        val idents = getIdents\n        val rest = cur match {\n          case (KEYWORD(\":\"), l0) :: _ =>\n            consume\n            expr(0)\n          case _ =>\n            err((msg\"Expected `:` after `forall` section\" -> curLoc.orElse(lastLoc) :: Nil))\n            errExpr\n        }\n        R(Forall(idents, rest))\n      case (KEYWORD(\"while\"), l0) :: _ =>\n        consume\n        val cond = expr(0)\n        val (success, _) = skip(KEYWORD(\"do\")) // TODO kw?\n        val body = expr(0)\n        exprCont(While(cond, body).withLoc(S(l0 ++ body.toLoc)), prec, allowNewlines = false)\n      case (KEYWORD(\"set\"), l0) :: _ =>\n        consume\n        val lhs = expr(0)\n        val (success, _) = skip(KEYWORD(\"=\")) // TODO kw?\n        val rhs = expr(0)(fe = foundErr || !success, l = implicitly)\n        exprCont(Assign(lhs, rhs).withLoc(S(l0 ++ rhs.toLoc)), prec, allowNewlines = false)\n      case (KEYWORD(\"let\"), l0) :: _ =>\n        consume\n        letBindings(false)\n      case (KEYWORD(\"new\"), l0) :: c =>\n        consume\n        val body = expr(NewParser.prec('.'))\n        exprCont(NuNew(body).withLoc(S(l0 ++ body.toLoc)), prec, allowNewlines = false)\n      case (KEYWORD(\"else\"), l0) :: _ =>\n        consume\n        yeetSpaces match {\n          case (NEWLINE, l0) :: _ =>\n            consume\n            ??? // TODO\n          case _ =>\n            val e = expr(0)\n            L(IfElse(e).withLoc(S(l0 ++ e.toLoc)))\n        }\n      case (KEYWORD(\"case\"), l0) :: _ =>\n        consume\n        exprOrIf(0)(et = true, fe = fe, l = implicitly) match {\n          case L(body) =>\n            R(Lam(PlainTup(Var(\"case$scrut\")), If(IfOpApp(Var(\"case$scrut\"), Var(\"is\"), body), N)))\n          case R(rhs) =>\n            err((msg\"Expected 'then'/'else' clause after 'case'; found ${rhs.describe} instead\" -> rhs.toLoc ::\n              msg\"Note: 'case' expression starts here:\" -> S(l0) :: Nil))\n            R(Lam(PlainTup(Var(\"case$scrut\")), If(IfElse(rhs), N)))\n        }\n        \n      case (KEYWORD(\"if\"), l0) :: _ =>\n        consume\n        exprOrIf(0)(et = true, fe = fe, l = implicitly) match {\n          case L(body) =>\n            val els = yeetSpaces match {\n              case (KEYWORD(\"else\"), _) :: _ =>\n                consume\n                S(exprOrBlockContinuation)\n              case (NEWLINE, _) :: (KEYWORD(\"else\"), _) :: _ =>\n                consume\n                consume\n                S(expr(0))\n              case (br @ BRACKETS(Indent, (KEYWORD(\"else\"), _) :: toks), _) :: _ =>\n                consume\n                val nested = rec(toks, S(br.innerLoc), br.describe)\n                S(nested.concludeWith(_.expr(0)))\n              case _ => N\n            }\n            R(If(body, els))\n          case R(e) =>\n            yeetSpaces match {\n              case (br @ BRACKETS(Indent, (KEYWORD(\"then\"), _) :: toks), _) :: _ =>\n                consume\n                val nested = rec(toks, S(br.innerLoc), br.describe)\n                val thn = nested.expr(0)\n                val els = nested.yeetSpaces match {\n                  case (KEYWORD(\"else\"), _) :: _ =>\n                    nested.consume\n                    S(nested.concludeWith(_.expr(0)))\n                  case (NEWLINE, _) :: (KEYWORD(\"else\"), _) :: _ =>\n                    nested.consume\n                    nested.consume\n                    // S(thn, S(nested.concludeWith(_.expr(0))))\n                    S(nested.concludeWith(_.expr(0)))\n                  case _ =>\n                    nested.concludeWith(_ => ())\n                    // S(thn, N)\n                    N\n                }\n                R(If(IfThen(e, thn), els))\n              case _cur =>\n                val (found, loc) = _cur match {\n                  case (tk, l1) :: _ => (msg\"${e.describe} followed by ${tk.describe}\",\n                    S(e.toLoc.foldRight(l1)(_ ++ _)))\n                  case Nil => (msg\"${e.describe}\", e.toLoc)\n                }\n                err((msg\"Expected 'then'/'else' clause after 'if'; found $found instead\" -> loc ::\n                  msg\"Note: 'if' expression starts here:\" -> S(l0) :: Nil))\n                R(If(IfThen(e, errExpr), N))\n            }\n        }\n        \n      case Nil =>\n        err(msg\"Unexpected end of $description; an expression was expected here\" -> lastLoc :: Nil)\n        R(errExpr)\n      case ((SEMI /* | NEWLINE */ /* | BRACKETS(Curly, _) */, l0) :: _) =>\n        R(UnitLit(true).withLoc(S(l0)))\n        // R(errExpr) // TODO\n      case (IDENT(\"-\", true), l0) :: _ /*if opPrec(\"-\")._1 > prec*/ => // Unary minus\n        consume\n        val v = Var(\"-\").withLoc(S(l0))\n        expr(opPrec(\"-\")._2) match {\n          case IntLit(i) => // Special case for negative literals\n            exprCont(IntLit(-i), prec, false)\n          case rhs: Term => // General case\n            exprCont(\n              if (newDefs) App(v, PlainTup(IntLit(BigInt(0)), rhs))\n              else App(App(v, PlainTup(IntLit(BigInt(0)))), PlainTup(rhs))\n            , prec, false)\n        }\n      case (tk, l0) :: _ =>\n        err(msg\"Unexpected ${tk.describe} in expression position\" -> S(l0) :: Nil)\n        consume\n        exprOrIf(prec)(et = et, fe = true, l = implicitly)\n    }\n    \n    if (allAnns.isEmpty) res\n    else res match {\n      case Left(body) => body match {\n        case IfThen(expr, rhs) =>\n          Left(IfThen(wrapAnns(expr, allAnns), rhs))\n        case _ =>\n          err(msg\"Unexpected annotation\" -> allAnns.head.toLoc :: Nil)\n          L(body) // discard annotations for now\n      }\n\n      case Right(term) => R(wrapAnns(term, allAnns))\n    }\n  }\n\n  private def wrapAnns(trm: Term, anns: List[Term]) =\n    anns.foldRight(trm)(Ann(_, _))\n  \n  private def errExpr =\n    // Tup(Nil).withLoc(lastLoc) // TODO FIXME produce error term instead\n    UnitLit(true).withLoc(lastLoc) // TODO FIXME produce error term instead\n  \n  final def exprCont(acc: Term, prec: Int, allowNewlines: Bool)(implicit et: ExpectThen, fe: FoundErr, l: Line): IfBody \\/ Term = wrap(prec, s\"`$acc`\", allowNewlines) { l =>\n    cur match {\n      case (QUOTE, l) :: _ => cur match {\n        case _ :: (KEYWORD(opStr @ \"=>\"), l0) :: _ if opPrec(opStr)._1 > prec =>\n          consume\n          consume\n          exprCont(Quoted(Lam(acc match {\n            case t: Tup => t\n            case _ => PlainTup(acc)\n          }, Unquoted(expr(1)(fe, implicitly)))), prec, allowNewlines)\n        case _ :: (br @ BRACKETS(Round, toks), loc) :: _ =>\n          consume\n          consume\n          val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented()).map {\n            case nme -> Fld(flgs, t) => nme -> Fld(flgs, Unquoted(t))\n          }\n          val res = App(Unquoted(acc), Tup(as).withLoc(S(loc)))\n          exprCont(Quoted(res), prec, allowNewlines)\n        case _ :: (IDENT(opStr, true), l0) :: _ =>\n          if (opPrec(opStr)._1 > prec) {\n            consume\n            consume\n            val v = Var(opStr).withLoc(S(l0))\n            yeetSpaces match {\n              case (NEWLINE, l0) :: _ => consume\n              case _ =>\n            }\n            exprOrIf(opPrec(opStr)._2) match {\n              case L(rhs) => R(unsupportedQuote(S(l0)))\n              case R(rhs) => exprCont(opStr match {\n                case \"with\" => unsupportedQuote(S(l0))\n                case _ => Quoted(App(v, PlainTup(Unquoted(acc), Unquoted(rhs))))\n              }, prec, allowNewlines)\n            }\n          }\n          else R(acc)\n        case _ :: (KEYWORD(\"in\"), _) :: _ =>\n          R(acc)\n        case _ =>\n          consume\n          unsupportedQuote(acc.toLoc)\n          R(acc)\n      }\n      case (COMMA, l0) :: _ if prec === 0 =>\n        consume\n        yeetSpaces match {\n          case (NEWLINE, _) :: _ => consume\n          case _ =>\n        }\n        val rhs = expr(prec) // TODO support exprOrIf for comma operators\n        R(App(Var(\",\").withLoc(S(l0)), PlainTup(acc, rhs)))\n      case (KEYWORD(opStr @ \"=>\"), l0) :: (NEWLINE, l1) :: _ if opPrec(opStr)._1 > prec =>\n        consume\n        val rhs = Blk(typingUnit.entities)\n        R(Lam(PlainTup(acc), rhs))\n      case (KEYWORD(opStr @ \"=>\"), l0) :: _ if opPrec(opStr)._1 > prec =>\n        consume\n        val rhs = expr(1)\n        val res = Lam(PlainTup(acc), rhs)\n        exprCont(res, prec, allowNewlines)\n      case (IDENT(\".\", _), l0) :: (br @ BRACKETS(Square, toks), l1) :: _ =>\n        consume\n        consume\n        val idx = rec(toks, S(br.innerLoc), br.describe)\n          .concludeWith(_.expr(0, allowSpace = true))\n        val newAcc = Subs(acc, idx).withLoc(S(l0 ++ l1 ++ idx.toLoc))\n        exprCont(newAcc, prec, allowNewlines)\n      case (IDENT(opStr, true), l0) :: _ if /* isInfix(opStr) && */ opPrec(opStr)._1 > prec =>\n        consume\n        val v = Var(opStr).withLoc(S(l0))\n        yeetSpaces match {\n          case (NEWLINE, l0) :: _ => consume\n          case _ =>\n        }\n        exprOrIf(opPrec(opStr)._2) match {\n          case L(rhs) =>\n            L(IfOpApp(acc, v, rhs))\n          case R(rhs) =>\n            exprCont(opStr match {\n              case \"with\" =>\n                rhs match {\n                  case rhs: Rcd =>\n                    With(acc, rhs)//.withLocOf(term)\n                  case Bra(true, rhs: Rcd) =>\n                    With(acc, rhs)//.withLocOf(term)\n                  case _ =>\n                    err(msg\"record literal expected here; found ${rhs.describe}\" -> rhs.toLoc :: Nil)\n                    acc\n                }\n              case _ =>\n                if (newDefs) App(v, PlainTup(acc, rhs))\n                else App(App(v, PlainTup(acc)), PlainTup(rhs))\n            }, prec, allowNewlines)\n        }\n      case (KEYWORD(\":\"), l0) :: _ if prec <= NewParser.prec(':') =>\n        consume\n        R(Asc(acc, typ(0)))\n      case (KEYWORD(\"where\"), l0) :: _ if prec <= 1 =>\n        consume\n        val tu = typingUnitMaybeIndented\n        val res = Where(acc, tu.entities).withLoc(S(l0))\n        exprCont(res, prec, allowNewlines = false)\n      case (SPACE, l0) :: _ =>\n        consume\n        exprCont(acc, prec, allowNewlines)\n      case (SELECT(name), l0) :: _ => // TODO precedence?\n        consume\n        exprCont(Sel(acc, Var(name).withLoc(S(l0))), prec, allowNewlines)\n      // case (br @ BRACKETS(Indent, (SELECT(name), l0) :: toks), _) :: _ =>\n      case (br @ BRACKETS(Indent, (SELECT(name), l0) :: toks), _) :: _ if prec <= 1 =>\n        consume\n        val res = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.exprCont(Sel(acc, Var(name).withLoc(S(l0))), 0, allowNewlines = true))\n        if (allowNewlines) res match {\n          case L(ifb) => L(ifb) // TODO something else?\n          case R(res) => exprCont(res, 0, allowNewlines)\n        }\n        else res\n      case (br @ BRACKETS(Indent, (IDENT(opStr, true), l0) :: toks), _) :: _ =>\n        consume\n        rec(toks, S(br.innerLoc), br.describe).concludeWith(_.opBlock(acc, opStr, l0))\n      case (KEYWORD(\"then\"), _) :: _ if /* expectThen && */ prec === 0 =>\n      // case (KEYWORD(\"then\"), _) :: _ if /* expectThen && */ prec <= 1 =>\n        consume\n        L(IfThen(acc, exprOrBlockContinuation))\n      case (NEWLINE, _) :: (KEYWORD(\"then\"), _) :: _ if /* expectThen && */ prec === 0 =>\n        consume\n        consume\n        L(IfThen(acc, exprOrBlockContinuation))\n      case (NEWLINE, _) :: _ if allowNewlines =>\n        consume\n        exprCont(acc, 0, allowNewlines)\n        \n      case (br @ BRACKETS(Curly, toks), loc) :: _ if prec <= AppPrec =>\n        consume\n        val tu = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.typingUnitMaybeIndented).withLoc(S(loc))\n        exprCont(Rft(acc, tu), prec, allowNewlines)\n        \n      case (COMMA | SEMI | NEWLINE | KEYWORD(\"then\" | \"else\" | \"in\" | \"=\" | \"do\")\n        | IDENT(_, true) | BRACKETS(Curly, _), _) :: _ => R(acc)\n      \n      case (KEYWORD(\"of\"), _) :: _ if prec <= 1 =>\n        consume\n        val as = argsMaybeIndented()\n        val res = App(acc, Tup(as))\n        exprCont(res, prec, allowNewlines)\n      case (br @ BRACKETS(Indent, (KEYWORD(\"of\"), _) :: toks), _) :: _ if prec <= 1 =>\n        consume\n        // \n        // val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented())\n        // val res = App(acc, Tup(as))\n        // exprCont(res, 0, allowNewlines = true) // ?!\n        // \n        val res = rec(toks, S(br.innerLoc), br.describe).concludeWith { nested =>\n          val as = nested.argsMaybeIndented()\n          nested.exprCont(App(acc, Tup(as)), 0, allowNewlines = true)\n        }\n        // if (allowNewlines) \n        res match {\n          case L(ifb) => L(ifb) // TODO something else?\n          case R(res) => exprCont(res, 0, allowNewlines)\n        }\n        // else res\n        \n      case (BRACKETS(Indent, (KEYWORD(\"then\"|\"else\"), _) :: toks), _) :: _ => R(acc)\n      \n      /* \n      case (br @ BRACKETS(Indent, toks), _) :: _ \n      if prec === 0 && !toks.dropWhile(_._1 === SPACE).headOption.map(_._1).contains(KEYWORD(\"else\")) // FIXME\n      =>\n        consume\n        val res = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.blockTerm)\n        R(App(acc, res))\n      */\n      // case (br @ BRACKETS(Indent, (BRACKETS(Round | Square, toks1), _) :: toks2), _) :: _ =>\n      case (br @ BRACKETS(Indent, toks @ (BRACKETS(Round | Square, _), _) :: _), _) :: _ if prec <= 1 =>\n        consume\n        val res = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.exprCont(acc, 0, allowNewlines = true))\n        res match {\n          case L(ifb) => L(ifb) // TODO something else?\n          case R(res) => exprCont(res, 0, allowNewlines)\n        }\n        \n      case (br @ BRACKETS(Angle | Square, toks), loc) :: _ =>\n        consume\n        val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented())\n        // val res = TyApp(acc, as.map(_.mapSecond.to))\n        val res = TyApp(acc, as.map {\n          case (N, Fld(FldFlags(false, false, _), trm)) => trm.toType match {\n            case L(d) => raise(d); Top // TODO better\n            case R(ty) => ty\n          }\n          case _ => ???\n        }).withLoc(acc.toLoc.fold(some(loc))(_ ++ loc |> some))\n        exprCont(res, prec, allowNewlines)\n        \n      /*case (br @ BRACKETS(Square, toks), loc) :: _ => // * Currently unreachable because we match Square brackets as tparams\n        consume\n        val idx = rec(toks, S(br.innerLoc), \"subscript\").concludeWith(_.expr(0))\n        val res = Subs(acc, idx.withLoc(S(loc)))\n        exprCont(res, prec, allowNewlines)*/\n      \n      case (br @ BRACKETS(Round, toks), loc) :: _ if prec <= AppPrec =>\n        consume\n        val as = rec(toks, S(br.innerLoc), br.describe).concludeWith(_.argsMaybeIndented())\n        val res = App(acc, Tup(as).withLoc(S(loc)))\n        exprCont(res, prec, allowNewlines)\n        \n      case (KEYWORD(\"of\"), _) :: _ =>\n        consume\n        val as = argsMaybeIndented()\n        // val as = argsOrIf(Nil) // TODO\n        val res = App(acc, Tup(as))\n        exprCont(res, prec, allowNewlines)\n        \n      case c @ (h :: _) if (h._1 match {\n        case KEYWORD(\":\" | \"of\" | \"where\" | \"extends\") | SEMI | BRACKETS(Round | Square, _)\n          | BRACKETS(Indent, (\n              KEYWORD(\"of\") | SEMI\n              | BRACKETS(Round | Square, _)\n              | SELECT(_)\n            , _) :: _)\n          => false\n        case _ => true\n      }) =>\n        val as = argsMaybeIndented()\n        val res = App(acc, Tup(as))\n        raise(WarningReport(msg\"Paren-less applications should use the 'of' keyword\"\n          -> res.toLoc :: Nil, newDefs = true))\n        exprCont(res, prec, allowNewlines)\n        \n      case _ => R(acc)\n    }\n  }\n  \n  final def opBlock(acc: Term, opStr: Str, opLoc: Loc)(implicit et: ExpectThen, fe: FoundErr, l: Line): IfBody \\/ Term = wrap(s\"`$acc`\", opStr) { l =>\n      val opv = Var(opStr).withLoc(S(opLoc))\n      val rhs = exprOrIf(0)\n      // val rhs = exprOrIf(1)\n      rhs match {\n        case R(rhs) =>\n          val res = App(opv, PlainTup(acc, rhs))\n          cur match {\n            case (NEWLINE, _) :: c => // TODO allow let bindings...\n              consume\n              c match {\n                case (IDENT(opStr2, true), opLoc2) :: _ =>\n                  consume\n                  opBlock(res, opStr2, opLoc2)\n                case (tk, lo) :: _ =>\n                  err(msg\"Unexpected ${tk.describe} in operator block\" -> S(lo) :: Nil)\n                  consume\n                  R(res)\n                case Nil =>\n                  R(res)\n              }\n            case _ =>\n              R(res)\n          }\n        case L(rhs) =>\n          val (opsRhss, els) = opIfBlock(opv -> rhs :: Nil)\n          val opsApp = IfOpsApp(acc, opsRhss)\n          L(els.fold[IfBody](opsApp)(trm => IfBlock(L(opsApp) :: L(IfElse(trm)) :: Nil)))\n      }\n  }\n  final def opIfBlock(acc: Ls[Var -> IfBody])(implicit et: ExpectThen, fe: FoundErr): (Ls[Var -> IfBody], Opt[Term]) = wrap(acc) { l =>\n      cur match {\n        case (NEWLINE, _) :: c => // TODO allow let bindings...\n          consume\n          c match {\n            case (IDENT(\"_\", false), wcLoc) :: _ =>\n              exprOrIf(0) match {\n                case R(rhs) =>\n                  err(msg\"expect an operator branch\" -> S(wcLoc) :: Nil)\n                  (acc.reverse, N)\n                case L(IfThen(_, els)) => (acc.reverse, S(els))\n                case L(rhs) =>\n                  err(msg\"expect 'then' after the wildcard\" -> rhs.toLoc :: Nil)\n                  (acc.reverse, N)\n              }\n            case (IDENT(opStr2, true), opLoc2) :: _ =>\n              consume\n              val rhs = exprOrIf(0)\n              // val rhs = exprOrIf(1)\n              rhs match {\n                case R(rhs) => ???\n                case L(rhs) =>\n                  opIfBlock(Var(opStr2).withLoc(S(opLoc2)) -> rhs :: acc)\n              }\n            case (KEYWORD(\"else\"), elseLoc) :: tail =>\n              consume\n              exprOrIf(0) match {\n                case R(rhs) => (acc.reverse, S(rhs))\n                case L(rhs) =>\n                  err(msg\"expect a term\" -> rhs.toLoc :: Nil)\n                  (acc.reverse, N)\n              }\n            case (_, headLoc) :: _ =>\n              // printDbg(c)\n              err(msg\"expect an operator\" -> S(headLoc) :: Nil)\n              (acc.reverse, N)\n            case Nil =>\n              (acc.reverse, N)\n          }\n        case _ =>\n          (acc.reverse, N)\n      }\n  }\n  \n  final def tyArgs(implicit fe: FoundErr, et: ExpectThen): Opt[Ls[Type]] =\n    cur match {\n      case (IDENT(\"<\", true), l0) :: _ => ???\n      case _ => ???\n    }\n  \n  // TODO support line-broken param lists; share logic with args/argsOrIf\n  def typeParams(implicit fe: FoundErr, et: ExpectThen): Ls[(Opt[VarianceInfo], TypeName)] = {\n    val vinfo = yeetSpaces match {\n      case (KEYWORD(\"in\"), l0) :: (KEYWORD(\"out\"), l1) :: _ =>\n        consume\n        S(VarianceInfo.in, l0 ++ l1)\n      case (KEYWORD(\"in\"), l0) :: _ =>\n        consume\n        S(VarianceInfo.contra, l0)\n      case (KEYWORD(\"out\"), l0) :: _ =>\n        consume\n        S(VarianceInfo.co, l0)\n      case _ => N\n    }\n    yeetSpaces match {\n      case (IDENT(nme, false), l0) :: _ =>\n        consume\n        val tyNme = TypeName(nme).withLoc(S(l0))\n        yeetSpaces match {\n          case (COMMA, l0) :: _ =>\n            consume\n            vinfo.map(_._1) -> tyNme :: typeParams\n          case _ =>\n            vinfo.map(_._1) -> tyNme :: Nil\n        }\n      case _ =>\n        vinfo match {\n          case S((_, loc)) =>\n            err(msg\"dangling variance information\" -> S(loc) :: Nil)\n          case N =>\n        }\n        Nil\n    }\n  }\n  \n  \n  final def maybeIndented[R](f: (NewParser, Bool) => R)(implicit fe: FoundErr, et: ExpectThen): R =\n    cur match {\n      case (br @ BRACKETS(Indent, toks), _) :: _ if (toks.headOption match {\n        case S((KEYWORD(\"then\" | \"else\"), _)) => false\n        case _ => true\n      }) =>\n        consume\n        rec(toks, S(br.innerLoc), br.describe).concludeWith(f(_, true))\n      case _ => f(this, false)\n    }\n  \n  final def argsMaybeIndented()(implicit fe: FoundErr, et: ExpectThen): Ls[Opt[Var] -> Fld] =\n    maybeIndented(_.args(_))\n  // final def argsMaybeIndented()(implicit fe: FoundErr, et: ExpectThen): Ls[Opt[Var] -> Fld] =\n  //   cur match {\n  //     case (br @ BRACKETS(Indent, toks), _) :: _ if (toks.headOption match {\n  //       case S((KEYWORD(\"then\" | \"else\"), _)) => false\n  //       case _ => true\n  //     }) =>\n  //       consume\n  //       rec(toks, S(br.innerLoc), br.describe).concludeWith(_.args(true))\n  //     case _ => args(false)\n  //   }\n  \n  // TODO support comma-less arg blocks...?\n  final def args(allowNewlines: Bool, prec: Int = NoElsePrec)(implicit fe: FoundErr, et: ExpectThen): Ls[Opt[Var] -> Fld] =\n    // argsOrIf(Nil).map{case (_, L(x))=> ???; case (n, R(x))=>n->x} // TODO\n    argsOrIf(Nil, Nil, allowNewlines, prec).flatMap{case (n, L(x))=> \n        err(msg\"Unexpected 'then'/'else' clause\" -> x.toLoc :: Nil)\n        n->Fld(FldFlags.empty, errExpr)::Nil\n      case (n, R(x))=>n->x::Nil} // TODO\n  /* \n  final def argsOrIf2()(implicit fe: FoundErr, et: ExpectThen): IfBlock \\/ Ls[Opt[Var] -> Fld] = {\n    // argsOrIf(Nil).partitionMap(identity).mapFirst(ifbods => ???)\n    argsOrIf(Nil) match {\n      case n -> L(ib) =>\n        \n      case n -> R(tm) =>\n      case Nil => R(Nil)\n    }\n  }\n  */\n  final def argsOrIf(acc: Ls[Opt[Var] -> (IfBody \\/ Fld)], seqAcc: Ls[Statement], allowNewlines: Bool, prec: Int = NoElsePrec)\n        (implicit fe: FoundErr, et: ExpectThen): Ls[Opt[Var] -> (IfBody \\/ Fld)] =\n      wrap(acc, seqAcc) { l =>\n      \n    val anns = parseAnnotations(false)\n    \n    cur match {\n      case Nil =>\n        seqAcc match {\n          case res :: seqAcc => \n            (N -> R(Fld(FldFlags.empty, Blk((res :: seqAcc).reverse))) :: acc).reverse\n          case Nil =>\n            acc.reverse\n        }\n      case (SPACE, _) :: _ =>\n        consume\n        argsOrIf(acc, seqAcc, allowNewlines, prec)\n      case (NEWLINE, _) :: _ => // TODO: | ...\n        assert(seqAcc.isEmpty)\n        acc.reverse\n      case (IDENT(nme, true), _) :: _ if nme =/= \"-\" => // TODO: | ...\n        assert(seqAcc.isEmpty)\n        acc.reverse\n      case _ =>\n    \n    // val blck = block\n    \n    val argVal = yeetSpaces match {\n      case (KEYWORD(\"val\"), l0) :: _ =>\n        consume\n        S(l0)\n      case _ => N\n    }\n    val argMut = yeetSpaces match {\n      case (KEYWORD(\"mut\"), l0) :: _ =>\n        consume\n        S(l0)\n      case _ => N\n    }\n    val argSpec = yeetSpaces match {\n      case (KEYWORD(\"#\"), l0) :: _ =>\n        consume\n        S(l0)\n      case _ => N\n    }\n    val argName = yeetSpaces match {\n      case (IDENT(idStr, false), l0) :: (KEYWORD(\":\"), _) :: _ => // TODO: | ...\n        consume\n        consume\n        S(Var(idStr).withLoc(S(l0)))\n      case (LITVAL(IntLit(i)), l0) :: (KEYWORD(\":\"), _) :: _ => // TODO: | ...\n        consume\n        consume\n        S(Var(i.toString).withLoc(S(l0)))\n      case _ => N\n    }\n\n    // val e = expr(NoElsePrec) -> argMut.isDefined\n    val e = exprOrIf(prec, true, anns).map(Fld(FldFlags(argMut.isDefined, argSpec.isDefined, argVal.isDefined), _))\n    \n    def mkSeq = if (seqAcc.isEmpty) argName -> e else e match {\n      case L(_) => ???\n      case R(Fld(flags, res)) =>\n        argName -> R(Fld(flags, Blk((res :: seqAcc).reverse)))\n    }\n    \n    cur match {\n      case (COMMA, l0) :: (NEWLINE, l1) :: _ =>\n        consume\n        consume\n        argsOrIf(mkSeq :: acc, Nil, allowNewlines)\n      case (COMMA, l0) :: _ =>\n        consume\n        argsOrIf(mkSeq :: acc, Nil, allowNewlines)\n      case (NEWLINE, l1) :: _ if allowNewlines =>\n        consume\n        argName match {\n          case S(nme) =>\n            err(msg\"Unexpected named argument name here\" -> nme.toLoc :: Nil)\n          case N =>\n        }\n        e match {\n          case L(_) => ???\n          case R(Fld(FldFlags(false, false, _), res)) =>\n            argsOrIf(acc, res :: seqAcc, allowNewlines)\n          case R(_) => ???\n        }\n      case _ =>\n        (mkSeq :: acc).reverse\n    }\n    \n  }\n  }\n  \n  final def bindings(acc: Ls[Var -> Term])(implicit fe: FoundErr): Ls[Var -> Term] = \n    cur match {\n      case (SPACE, _) :: _ =>\n        consume\n        bindings(acc)\n      case (NEWLINE | IDENT(_, true) | SEMI, _) :: _ => // TODO: | ...\n        acc.reverse\n      case (IDENT(id, false), l0) :: _ =>\n        consume\n        val (success, _) = skip(KEYWORD(\"=\")) // TODO kw?\n        val rhs = expr(0)(fe = foundErr || !success, l = implicitly)\n        // cur.dropWhile(_ === SPACE) match {\n        //   case (KEYWORD(\"in\"), _) :: _ =>\n        //     acc.reverse\n        //   case _ => ???\n        // }\n        val v = Var(id).withLoc(S(l0))\n        cur match {\n          case (COMMA, l1) :: _ =>\n            consume\n            bindings((v -> rhs) :: acc)\n          case _ =>\n            ((v -> rhs) :: acc).reverse\n        }\n      case _ =>\n        Nil\n  }\n  \n  final def mkType(trm: Term): Type = trm.toType match {\n    case L(d) => raise(d); Top // TODO better\n    case R(ty) => ty\n  }\n  \n  \n}\n\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/NormalForms.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet}\nimport scala.collection.immutable.{SortedSet, SortedMap}\nimport SortedSet.{empty => ssEmp}, SortedMap.{empty => smEmp}\nimport scala.util.chaining._\nimport scala.annotation.tailrec\nimport mlscript.utils._, shorthands._\nimport mlscript.Message._\n\nclass NormalForms extends TyperDatatypes { self: Typer =>\n  \n  type ExpandTupleFields >: Bool\n  type PreserveTypeRefs >: Bool\n  \n  def preserveTypeRefs(implicit ptr: PreserveTypeRefs): Bool = ptr === true\n  def expandTupleFields(implicit etf: ExpandTupleFields): Bool = etf === true\n  \n  \n  private def mergeTypeRefs(pol: Bool, trs1: SortedMap[TN, TR], trs2: SortedMap[TN, TR])(implicit ctx: Ctx): SortedMap[TN, TR] =\n    mergeSortedMap(trs1, trs2) { (tr1, tr2) =>\n      assert(tr1.defn === tr2.defn)\n      assert(tr1.targs.size === tr2.targs.size)\n      TypeRef(tr1.defn, (tr1.targs lazyZip tr2.targs).map((ta1, ta2) => \n          if (pol) TypeBounds.mk(ta1 & ta2, ta1 | ta2) else TypeBounds.mk(ta1 | ta2, ta1 & ta2)\n        ))(noProv)\n    }\n  \n  \n  sealed abstract class LhsNf {\n    final def compareEquiv(that: LhsNf): Int = (this, that) match {\n      case (LhsRefined(b1, ts1, r1, trs1), LhsRefined(b2, ts2, r2, trs2)) =>\n        var cmp = (b1, b2) match {\n          case (S(c1), S(c2)) => c1.compareEquiv(c2)\n          case (S(c1), N) => -1\n          case (N, S(c2)) => 1\n          case (N, N) => 0\n        }\n        if (cmp =/= 0) return cmp\n        // * Just compare the heads for simplicity...\n        cmp = (trs1.headOption, trs2.headOption) match {\n          case (S((n1, _)), S((n2, _))) =>\n            n1.compare(n2) // * in principle we could go on to compare the tails if this is 0\n          case (S(_), N) => 1\n          case (N, S(_)) => -1\n          case (N, N) => 0\n        }\n        if (cmp =/= 0) return cmp\n        cmp = -trs1.sizeCompare(trs2)\n        if (cmp =/= 0) return cmp\n        cmp = ts1.sizeCompare(ts2.size)\n        if (cmp =/= 0) return cmp\n        cmp = r1.fields.sizeCompare(r2.fields)\n        cmp\n      case (LhsTop, _) => 1\n      case (_, LhsTop) => -1\n    }\n    def toTypes: Ls[SimpleType] = toType() :: Nil\n    def toType(sort: Bool = false): SimpleType =\n      if (sort) mkType(true) else underlying\n    private def mkType(sort: Bool): SimpleType = this match {\n      case LhsRefined(bo, ts, r, trs) =>\n        val sr = if (sort) r.sorted else r\n        val bo2 = bo.filter {\n          case ClassTag(id, parents) => !trs.contains(TypeName(id.idStr.capitalize))\n          case _ => true\n        }\n        val trsBase = trs.valuesIterator.foldRight(bo2.fold[ST](sr)(_ & sr))(_ & _)\n        (if (sort) ts.toArray.sorted else ts.toArray).foldLeft(trsBase)(_ & _)\n      case LhsTop => TopType\n    }\n    lazy val underlying: SimpleType = mkType(false)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      this match {\n        case LhsRefined(base, ttags, reft, trefs) =>\n          (base.iterator.map(_.levelBelow(ub)) ++ ttags.iterator.map(_.levelBelow(ub)) ++\n            reft.fields.iterator.values.map(_.levelBelow(ub)) ++ trefs.iterator.values.map(_.levelBelow(ub))\n          ).reduceOption(_ max _).getOrElse(MinLevel)\n        case LhsTop => MinLevel\n      }\n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV, ST]): LhsNf = this match {\n      case LhsRefined(bo, ts, r, trs) =>\n        LhsRefined(bo.map(_.freshenAbove(lim, rigidify)), ts, r.freshenAbove(lim, rigidify),\n          trs.view.mapValues(_.freshenAbove(lim, rigidify)).to(SortedMap))\n      case LhsTop => this\n    }\n    def hasTag(ttg: AbstractTag): Bool = this match {\n      case LhsRefined(bo, ts, r, trs) => ts(ttg)\n      case LhsTop => false\n    }\n    def size: Int = this match {\n      case LhsRefined(bo, ts, r, trs) => bo.size + ts.size + r.fields.size + trs.size\n      case LhsTop => 0\n    }\n    def & (that: AbstractTag): LhsNf = this match {\n      case LhsTop => LhsRefined(N, SortedSet.single(that), RecordType.empty, smEmp)\n      case LhsRefined(b, ts, r, trs) => LhsRefined(b, ts + that, r, trs)\n    }\n    def & (that: BaseTypeOrTag, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): Opt[LhsNf] = (this, that) match {\n      case (LhsTop, that: TupleType) => S(LhsRefined(S(that), ssEmp, if (expandTupleFields) that.toRecord else RecordType.empty, smEmp))\n      case (LhsTop, that: BaseType) => S(LhsRefined(S(that), ssEmp, RecordType.empty, smEmp))\n      case (LhsTop, that: AbstractTag) => S(LhsRefined(N, SortedSet.single(that), RecordType.empty, smEmp))\n      case (LhsRefined(b1, ts, r1, trs), that: AbstractTag) => S(LhsRefined(b1, ts + that, r1, trs))\n      case (LhsRefined(b1, ts, r1, trs), that: BaseType) =>\n        var r1Final = r1\n        ((b1, that) match {\n          case (S(p0 @ ClassTag(pt0, ps0)), p1 @ ClassTag(pt1, ps1)) =>\n            // println(s\"!GLB! $this $that ${p0.glb(p1)}\")\n            p0.glb(p1)\n          \n          case (S(l @ FunctionType(l0, r0)), FunctionType(l1, r1))\n          if approximateNegativeFunction && !pol =>\n            S(FunctionType(l0 | l1, r0 & r1)(l.prov))\n          \n          // * Note: it also feels natural to simplify `f: int -> int & nothing -> string`\n          // * to just `f: int -> int`, but these types are not strictly-speaking equivalent;\n          // * indeed, we could still call such a function as `f error : string`...\n          // * (This is similar to how `{ x: nothing }` is not the same as `nothing`.)\n          // * Note: in any case it should be fine to make this approximation in positive positions.\n          // * Still, it seems making this approximation is morally correct even in negative positions,\n          // * at least in a CBV setting, since the only way to use the bad function component is\n          // * by passing a non-returning computation. So this should be semantically sound.\n          case (S(FunctionType(AliasOf(TupleType(fs)), _)), _: Overload | _: FT)\n          if fs.exists(_._2.ub.isBot) => S(that)\n          case (sov @ S(Overload(alts)), FunctionType(AliasOf(TupleType(fs)), _))\n          if fs.exists(_._2.ub.isBot) => sov\n          \n          case (S(ov @ Overload(alts)), ft: FunctionType) =>\n            def go(alts: Ls[FT]): Ls[FT] = alts match {\n              case (f @ FunctionType(l, r)) :: alts =>\n                /* // * Note: A simpler version that gets most of the way there:\n                if (l >:< ft.lhs) FunctionType(l, r & ft.rhs)(f.prov) :: alts\n                else if (r >:< ft.rhs) FunctionType(l | ft.lhs, r)(f.prov) :: alts\n                else f :: go(alts)\n                */\n                val l_LT_lhs = l <:< ft.lhs\n                lazy val l_GT_lhs = ft.lhs <:< l\n                lazy val r_LT_rhs = r <:< ft.rhs\n                lazy val r_GT_rhs = ft.rhs <:< r\n                if (l_LT_lhs && r_GT_rhs) ft :: alts\n                else if (l_GT_lhs && r_LT_rhs) f :: alts\n                else if (l_LT_lhs && l_GT_lhs) FunctionType(l, r & ft.rhs)(f.prov) :: alts\n                else if (r_LT_rhs && r_GT_rhs) FunctionType(l | ft.lhs, r)(f.prov) :: alts\n                else f :: go(alts)\n              case Nil => ft :: Nil\n            }\n            S(Overload(go(alts))(ov.prov))\n          case (S(ft: FunctionType), _: Overload | _: FT) =>\n            return LhsRefined(S(Overload(ft :: Nil)(that.prov)), ts, r1, trs) & (that, pol)\n          case (S(Overload(alts1)), ov2 @ Overload(a2 :: alts2)) =>\n            alts2 match {\n              case Nil => \n                return this & (a2, pol)\n              case _ =>\n                return this & (a2, pol) flatMap (_ & (Overload(alts2)(ov2.prov), pol))\n            }\n          \n          case (S(TupleType(fs0)), tup @ TupleType(fs1)) =>\n            if (fs0.size === fs1.size) {\n              if (expandTupleFields)\n                r1Final = RecordType(mergeSortedMap(r1Final.fields, tup.toRecord.fields)(_ && _).toList)(noProv)\n              S(TupleType(tupleIntersection(fs0, fs1))(noProv))\n            } else N\n          case (S(ArrayType(ar)), tup @ TupleType(fs)) =>\n            if (expandTupleFields)\n              r1Final = RecordType(mergeSortedMap(r1Final.fields, tup.toRecord.fields)(_ && _).toList)(noProv)\n            S(TupleType(fs.map { ty =>\n              ty._1 -> (ar && ty._2)\n            })(noProv))\n          case (S(TupleType(fs)), ArrayType(ar)) =>\n            S(TupleType(fs.map { ty =>\n              ty._1 -> (ty._2 && ar)\n            })(noProv))\n          case (S(ArrayType(i1)), ArrayType(i2)) =>\n            // Array[p] & Array[q] => Array[p & q]\n            S(ArrayType(i1 && i2)(noProv))\n            \n          case (S(w1 @ Without(b1, ns1)), w2 @ Without(b2, ns2)) if ns1 === ns2 =>\n            S(Without(b1 & b2, ns1)(w1.prov & w2.prov))\n          // The following cases are quite hacky... if we find two incompatible Without types,\n          //  just make a new dummy Without type to merge them.\n          // The workaround is due to the fact that unlike other types, we can't fully\n          //  reduce Without types away, so they are \"unduly\" treated as `BaseType`s.\n          // This will be fixed whe we support proper TV bounds for homomorphic type computations\n          case (S(b), w: Without) => S(Without(b & w, ssEmp)(noProv))\n          case (S(w: Without), b) => S(Without(w & b, ssEmp)(noProv))\n            \n          case (S(_: TypeTag), _: FunctionType | _: ArrayBase | _: Overload)\n            |  (S(_: FunctionType | _: ArrayBase | _: Overload), _: TypeTag)\n            |  (S(_: FunctionType), _: ArrayBase | _: Overload)\n            |  (S(_: ArrayBase | _: Overload), _: FunctionType)\n            |  (S( _: ArrayBase), _: Overload)\n            |  (S(_: Overload), _: ArrayBase)\n            => N\n          \n          case (S(Overload(Nil)), _) | (S(_), Overload(Nil)) =>\n            die // Overload must have nonempty alts\n          \n          case (S(_: SpliceType), _) | (S(_), _: SpliceType) => ??? // TODO\n          \n          case (N, tup: TupleType) =>\n            if (expandTupleFields)\n              r1Final = RecordType(mergeSortedMap(r1Final.fields, tup.toRecord.fields)(_ && _).toList)(noProv)\n            S(that)\n          case (N, _) => S(that)\n        }) map { b => LhsRefined(S(b), ts, r1Final, trs) }\n    }\n    def & (that: RecordType): LhsNf = this match {\n      case LhsTop => LhsRefined(N, ssEmp, that, smEmp)\n      case LhsRefined(b1, ts, r1, trs) =>\n        LhsRefined(b1, ts,\n          RecordType(recordIntersection(r1.fields, that.fields))(noProv/*TODO*/), trs)\n    }\n    def & (that: TypeRef, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): Opt[LhsNf] = this match {\n      case LhsTop => S(LhsRefined(N, ssEmp, RecordType.empty, SortedMap.single(that.defn -> that)))\n      case LhsRefined(b, ts, rt, trs) =>\n        val trs2 = trs + (that.defn -> trs.get(that.defn).fold(that) { other =>\n          var thatTargs = that.targs\n          assert(thatTargs.sizeCompare(other.targs) === 0)\n          val newTargs = other.mapTargs(S(true)) { (vce, otherTarg) =>\n            val thatTarg = thatTargs.head\n            thatTargs = thatTargs.tail\n            vce match {\n              case S(true) => otherTarg & thatTarg\n              case S(false) => otherTarg | thatTarg\n              case N =>\n                if (pol) TypeBounds.mk(otherTarg | thatTarg, otherTarg & thatTarg)\n                else TypeBounds.mk(otherTarg & thatTarg, otherTarg | thatTarg)\n            }\n          }\n          TypeRef(that.defn, newTargs)(that.prov)\n        })\n        val res = LhsRefined(b, ts, rt, trs2)\n        that.mkClsTag.fold(S(res): Opt[LhsNf])(res & (_, pol))\n    }\n    def & (that: LhsNf, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): Opt[LhsNf] = (this, that) match {\n      case (_, LhsTop) => S(this)\n      case (LhsTop, _) => S(that)\n      case (_, LhsRefined(bo, ts, rt, trs)) =>\n        ts.iterator.foldLeft(\n          trs.valuesIterator.foldLeft((bo.fold(some(this & rt))(this & rt & (_, pol))))(_.getOrElse(return N) & (_, pol))\n        )(_.getOrElse(return N) & (_, pol))\n    }\n    def <:< (that: RhsNf)(implicit ctx: Ctx): Bool = (this, that) match {\n      case (LhsRefined(_, _, reft, trs), RhsField(nme, ft)) => reft <:< RecordType(nme -> ft :: Nil)(noProv)\n      case (lhs @ LhsRefined(bse, tts, reft, trs), RhsBases(tags, rest, trefs)) =>\n        tags.exists(tag =>\n          bse match {\n            case S(cls: ClassTag) => tag.id === cls.id || lhs.allTags.contains(tag.id)\n            case _ => false\n          }\n        ) || (rest match {\n          case S(R(f: RhsField)) => this <:< f\n          case S(L(rhs @ (_: FunctionType | _: Overload | _: ArrayBase | _: TupleType))) =>\n            bse.exists(_ <:< rhs)\n          case S(L(wt: Without)) => return underlying <:< that.underlying\n          case N => false\n        }) || trefs.exists { case (_, tr) =>\n          underlying <:< tr\n        }\n      case (LhsTop, _) => false\n      case (_, RhsBot) => false\n    }\n    def <:< (that: LhsNf)(implicit ctx: Ctx): Bool = (this, that) match {\n      case (_, LhsTop) => true\n      case (LhsTop, _) => false\n      case (LhsRefined(b1, ts1, rt1, trs1), LhsRefined(b2, ts2, rt2, trs2)) =>\n        b2.forall(b2 => b1.exists(_ <:< b2)) &&\n          ts2.forall(ts1) && rt1 <:< rt2 &&\n          trs2.valuesIterator.forall(tr2 => trs1.valuesIterator.exists(_ <:< tr2))\n    }\n    def isTop: Bool = isInstanceOf[LhsTop.type]\n  }\n  case class LhsRefined(base: Opt[BaseType], ttags: SortedSet[AbstractTag], reft: RecordType, trefs: SortedMap[TypeName, TypeRef]) extends LhsNf {\n    // assert(!trefs.exists(primitiveTypes contains _._1.name))\n    lazy val allTags: Set[IdentifiedTerm] = ttags.iterator.foldLeft(base match {\n        case S(cls: ClassTag) => cls.parentsST + cls.id\n        case _ => Set.empty[IdentifiedTerm]\n      }) {\n        case (acc, tt: TraitTag) => acc ++ tt.parentsST + tt.id\n        case (acc, _) => acc\n      }\n    override def toString: Str = s\"${base.getOrElse(\"\")}${reft}${\n      (ttags.iterator ++ trefs.valuesIterator).map(\"∧\"+_).mkString}\"\n  }\n  case object LhsTop extends LhsNf {\n    override def toString: Str = \"⊤\"\n  }\n  \n  \n  sealed abstract class RhsNf {\n    final def compareEquiv(that: RhsNf): Int = (this, that) match {\n      case (RhsField(n1, t1), RhsField(n2, t2)) => n1.compare(n2)\n      case (RhsBases(ps1, bf1, trs1), RhsBases(ps2, bf2, trs2)) =>\n        var cmp = ps1.minOption match {\n          case S(m1) => ps2.minOption match {\n            case S(m2) => m1.compare(m2)\n            case N => ps1.size.compare(ps2.size)\n          }\n          case N => ps1.size.compare(ps2.size)\n        }\n        if (cmp =/= 0) return cmp\n        cmp = (trs1.headOption, trs2.headOption) match {\n          case (S((n1, _)), S((n2, _))) => n1.compare(n2)\n          case (S(_), N) => 1\n          case (N, S(_)) => -1\n          case (N, N) => 0\n        }\n        if (cmp =/= 0) return cmp\n        cmp = -trs1.sizeCompare(trs2)\n        cmp\n      case (_: RhsBases, _) => -1\n      case (_, _: RhsBases) => 1\n      case (_: RhsField, _) => -1\n      case (_, _: RhsField) => 1\n      case (RhsBot, RhsBot) => 0\n    }\n    def toTypes: Ls[SimpleType] = toType() :: Nil\n    def toType(sort: Bool = false): SimpleType =\n      if (sort) mkType(true) else underlying\n    private def mkType(sort: Bool): SimpleType = this match {\n      case RhsField(n, t) => RecordType(n -> t :: Nil)(noProv) // FIXME prov\n      case RhsBases(ps, bf, trs) =>\n        val sr = bf.fold(BotType: ST)(_.fold(identity, _.toType(sort)))\n        val trsBase = trs.valuesIterator.foldRight(sr)(_ | _)\n        (if (sort) ps.sorted else ps).foldLeft(trsBase)(_ | _)\n      case RhsBot => BotType\n    }\n    lazy val underlying: SimpleType = mkType(false)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      underlying.levelBelow(ub) // TODO avoid forcing `underlying`!\n    def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): RhsNf\n    def hasTag(ttg: AbstractTag): Bool = this match {\n      case RhsBases(ts, _, trs) => ts.contains(ttg)\n      case RhsBot | _: RhsField => false\n    }\n    def | (that: TypeRef, pol: Bool)(implicit ctx: Ctx): Opt[RhsNf] = this match {\n      case RhsBot => S(RhsBases(Nil, N, SortedMap.single(that.defn -> that)))\n      case RhsField(name, ty) => this | name -> ty\n      case RhsBases(prims, bf, trs) =>\n        val trs2 = trs + (that.defn -> trs.get(that.defn).fold(that) { other =>\n          var thatTargs = that.targs\n          assert(thatTargs.sizeCompare(other.targs) === 0)\n          val newTargs = other.mapTargs(S(true)) { (vce, otherTarg) =>\n            val thatTarg = thatTargs.head\n            thatTargs = thatTargs.tail\n            vce match {\n              case S(true) => otherTarg | thatTarg\n              case S(false) => otherTarg & thatTarg\n              case N =>\n                if (pol) TypeBounds.mk(otherTarg & thatTarg, otherTarg | thatTarg)\n                else TypeBounds.mk(otherTarg | thatTarg, otherTarg & thatTarg)\n            }\n          }\n          TypeRef(that.defn, newTargs)(that.prov)\n        })\n        S(RhsBases(prims, bf, trs2))\n    }\n    def | (that: RhsNf, pol: Bool)(implicit ctx: Ctx): Opt[RhsNf] = that match {\n      case RhsBases(prims, bf, trs) =>\n        val thisWithTrs = trs.valuesIterator.foldLeft(this)(_ | (_, pol) getOrElse (return N))\n        val tmp = prims.foldLeft(thisWithTrs)(_ | _ getOrElse (return N))\n        S(bf.fold(tmp)(_.fold(tmp | _ getOrElse (return N),\n          tmp | _.name_ty getOrElse (return N))))\n      case RhsField(name, ty) => this | name -> ty\n      case RhsBot => S(this)\n    }\n    def tryMergeInter(that: RhsNf)(implicit ctx: Ctx): Opt[RhsNf] = (this, that) match {\n      case (RhsBot, _) | (_, RhsBot) => S(RhsBot)\n      case (RhsField(name1, ty1), RhsField(name2, ty2)) if name1 === name2 => S(RhsField(name1, ty1 && ty2))\n      case (RhsBases(prims1, S(R(r1)), trs1), RhsBases(prims2, S(R(r2)), trs2))\n        if prims1 === prims2 && trs1 === trs2 && r1.name === r2.name\n        => S(RhsBases(prims1, S(R(RhsField(r1.name, r1.ty && r2.ty))), trs1))\n      case (RhsBases(prims1, bf1, trs1), RhsBases(prims2, bf2, trs2))\n        if prims1 === prims2 && bf1 === bf2 && trs1.keySet === trs2.keySet\n        => // * eg for merging `~Foo[S] & ~Foo[T]`:\n          S(RhsBases(prims1, bf1, mergeTypeRefs(false, trs1, trs2)))\n      case (RhsBases(prims1, bf1, trs1), RhsBases(prims2, bf2, trs2)) =>\n        N // TODO could do some more merging here – for the possible base types\n      case _ => N\n    }\n    def | (that: AbstractTag): RhsNf = this match {\n      case RhsBot => RhsBases(that :: Nil, N, smEmp)\n      case rf: RhsField => RhsBases(that :: Nil, S(R(rf)), smEmp)\n      case RhsBases(ps, bf, trs) => RhsBases(that :: ps, bf, trs)\n    }\n    // TODO use inheritance hierarchy to better merge these\n    def | (that: BaseTypeOrTag): Opt[RhsNf] = (this, that) match {\n      case (RhsBot, p: TypeTag) => S(RhsBases(p::Nil,N,smEmp))\n      case (RhsBot, that: MiscBaseType) => S(RhsBases(Nil,S(L(that)),smEmp))\n      case (RhsBases(ps, bf, trs), p: ClassTag) =>\n        S(RhsBases(if (ps.contains(p)) ps else p :: ps , bf, trs))\n      case (RhsBases(ps, N, trs), that: MiscBaseType) => S(RhsBases(ps, S(L(that)), trs))\n      case (RhsBases(ps, S(L(t1@TupleType(fs1))), trs), t2@TupleType(fs2)) =>\n        if (fs1.size =/= fs2.size) \n          RhsBases(ps, S(L(t1.toArray)), trs) | t2.toArray // upcast tuples of different sizes to array\n        else S(RhsBases(ps, S(L(TupleType(fs1.lazyZip(fs2).map {\n          case ((S(n1), ty1), (S(n2), ty2)) => (if (n1 === n2) S(n1) else N, ty1 || ty2)\n          case ((n1o, ty1), (n2o, ty2)) => (n1o orElse n2o, ty1 || ty2)\n        })(noProv))), trs))\n      case (RhsBases(ps, S(L(ArrayType(_))), trs), t@TupleType(_)) => this | t.toArray\n      case (RhsBases(ps, S(L(t@TupleType(_))), trs), ar@ArrayType(_)) => RhsBases(ps, S(L(t.toArray)), trs) | ar\n      case (RhsBases(ps, S(L(ArrayType(ar1))), trs), ArrayType(ar2)) => \n        S(RhsBases(ps, S(L(ArrayType(ar1 || ar2)(noProv))), trs))\n      case (RhsBases(_, S(L(_: Without)), _), _) | (_, _: Without) => die // Without should be handled elsewhere\n      case (RhsBases(ps, S(L(bt)), trs), _) if (that === bt) => S(this)\n      \n      // * Note: despite erased first-class polymorphism meaning we no longer have\n      // * `(A -> B) & (C -> D) =:= (A | C) -> (B & D)`,\n      // * I think we do still have `(A -> B) | (C -> D) =:= (A & C) -> (B | D)`,\n      // * because these two types still have no other meaningful LUB.\n      case (RhsBases(ps, S(L(FunctionType(l0, r0))), trs), FunctionType(l1, r1)) =>\n        S(RhsBases(ps, S(L(FunctionType(l0 & l1, r0 | r1)(noProv))), trs))\n      case (RhsBases(ps, S(L(ov @ Overload(fts))), trs), FunctionType(l2, r2)) =>\n        S(RhsBases(ps, S(L(Overload(fts.map {\n          case ft1  @FunctionType(l1, r1) =>\n            FunctionType(l1 & l2, r1 | r2)(ft1.prov)\n        })(ov.prov))), trs))\n      case (RhsBases(ps, S(L(ft: FunctionType)), trs), ov: Overload) =>\n        RhsBases(ps, S(L(ov)), trs) | ft\n      \n      // * TODO? or it might be counter-productive if it leads to bigger types due by distribution\n      // case (RhsBases(ps, S(L(ov1: Overload)), trs), ov2: Overload) => ???\n        \n      case (RhsBases(_, S(L(_: Overload)), _), _) | (_, _: Overload) =>\n        N\n      \n      case (RhsBases(ps, bf, trs), tt: AbstractTag) =>\n        S(RhsBases(if (ps.contains(tt)) ps else tt :: ps, bf, trs))\n      case (f @ RhsField(_, _), p: TypeTag) => S(RhsBases(p::Nil, S(R(f)), smEmp))\n      case (f @ RhsField(_, _), _: FunctionType | _: ArrayBase) =>\n        // S(RhsBases(Nil, S(that), S(f)))\n        N // can't merge a record and a function or a tuple -> it's the same as Top\n        // NOTE: in the future, if we do actually register fields in named tuples\n        //  (so their fields is not pure compiler fiction,\n        //    as it is currently and in TypeScript arrays),\n        //  we will want to revisit this...\n      case\n          (RhsBases(_, S(L(_: FunctionType)), _), _: ArrayBase)\n        | (RhsBases(_, S(L(_: ArrayBase)), _), _: FunctionType)\n        | (RhsBases(_, S(R(_)), _), _: FunctionType | _: ArrayBase)\n        => N\n      case (RhsBases(_, Some(Left(SpliceType(_))), _), _) | (_, _: SpliceType) => ??? // TODO\n    }\n    def | (that: (Var, FieldType)): Opt[RhsNf] = this match {\n      case RhsBot => S(RhsField(that._1, that._2))\n      case RhsField(n1, t1) if n1 === that._1 => S(RhsField(n1, t1 || that._2))\n      case RhsBases(p, N, trs) => S(RhsBases(p, S(R(RhsField(that._1, that._2))), trs))\n      case RhsBases(p, S(R(RhsField(n1, t1))), trs) if n1 === that._1 =>\n        S(RhsBases(p, S(R(RhsField(n1, t1 || that._2))), trs))\n      case _: RhsField | _: RhsBases => N\n    }\n    // def <:< (that: RhsNf)(implicit ctx: Ctx): Bool = this.underlying <:< that.underlying\n    def <:< (that: RhsNf)(implicit ctx: Ctx): Bool = (this, that) match {\n      case (RhsBases(tags, S(R(fld)), trs), fld2: RhsField) =>\n        tags.isEmpty && trs.valuesIterator.forall(_ <:< fld2.underlying) && fld <:< fld2\n      case (RhsBases(tags, _, trs), fld2: RhsField) => false\n      case (RhsField(nme, fty), RhsBases(tags2, S(R(fld)), trs2)) => this <:< fld\n      case (RhsField(nme, fty), RhsBases(tags2, S(L(_)) | N, trs2)) => false\n      case (RhsField(nme, fty), RhsField(nme2, fty2)) => nme === nme2 && fty <:< fty2\n      case (RhsBases(tags1, res1, trs1), rhs @ RhsBases(tags2, res2, trs2)) =>\n        tags1.forall(tag1 =>\n          tags2.exists(_.id === tag1.id) // TODO also take parents into account...\n        ) && trs1.forall { case (_, tr1) =>\n          // tr1 <:< rhs.underlying // * probably not necessary\n          trs2.exists { case (_, tr2) => tr1 <:< tr2 }\n        } && ((res1, res2) match {\n          case (S(L(b)), S(L(b2))) => b <:< b2\n          case (N, _) => true\n          case _ => false\n        })\n      case (RhsBot, _) => true\n      case (_, RhsBot) => false\n    }\n    def isBot: Bool = isInstanceOf[RhsBot.type]\n  }\n  case class RhsField(name: Var, ty: FieldType) extends RhsNf {\n    def name_ty: Var -> FieldType = name -> ty\n    def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): RhsField =\n      RhsField(name, ty.update(self.freshenAbove(lim, _, rigidify = rigidify), self.freshenAbove(lim, _, rigidify = rigidify)))\n    override def toString: Str = s\"{${name.name}:$ty}\"\n  }\n  case class RhsBases(tags: Ls[TypeTag], rest: Opt[MiscBaseType \\/ RhsField], trefs: SortedMap[TypeName, TypeRef]) extends RhsNf {\n    def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): RhsBases =\n      RhsBases(tags, rest.map(_ match {\n        case L(v) => L(v.freshenAboveImpl(lim, rigidify))\n        case R(v) => R(v.freshenAbove(lim, rigidify))\n      }), trefs.view.mapValues(_.freshenAbove(lim, rigidify)).to(SortedMap))\n    override def toString: Str =\n      s\"${tags.mkString(\"|\")}${rest.fold(\"\")(\"|\" + _.fold(\"\"+_, \"\"+_))}${trefs.valuesIterator.map(\"|\"+_).mkString}\"\n  }\n  case object RhsBot extends RhsNf {\n    def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): this.type = this\n    override def toString: Str = \"⊥\"\n  }\n  \n  \n  case class Conjunct(lnf: LhsNf, vars: SortedSet[TypeVariable], rnf: RhsNf, nvars: SortedSet[TypeVariable]) {\n    final def compareEquiv(that: Conjunct): Int =\n      // trace(s\"compareEquiv($this, $that)\")(compareEquivImpl(that))(r => s\"= $r\")\n      compareEquivImpl(that)\n    final def compareEquivImpl(that: Conjunct): Int = {\n      var cmp = lnf.compareEquiv(that.lnf)\n      if (cmp =/= 0) return cmp\n      cmp = rnf.compareEquiv(that.rnf)\n      if (cmp =/= 0) return cmp\n      cmp = -vars.sizeCompare(that.vars)\n      if (cmp =/= 0) return cmp\n      cmp = -nvars.sizeCompare(that.nvars)\n      cmp\n    }\n    def toType(sort: Bool = false): SimpleType =\n      toTypeWith(_.toType(sort), _.toType(sort), sort)\n    def toTypeWith(f: LhsNf => SimpleType, g: RhsNf => SimpleType, sort: Bool = false): SimpleType =\n      ((if (sort) vars.toArray.sorted.iterator else vars.iterator) ++ Iterator(g(rnf).neg())\n        ++ (if (sort) nvars.toArray.sorted.iterator else nvars).map(_.neg())).foldLeft(f(lnf))(_ & _)\n    lazy val level: Int = levelBelow(MaxLevel)(MutSet.empty)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      (vars.iterator ++ nvars).map(_.levelBelow(ub)).++(Iterator(lnf.levelBelow(ub), rnf.levelBelow(ub))).max\n    def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): Conjunct = {\n      val (vars2, tags2) = vars.toBuffer[TV].partitionMap(\n        _.freshenAbove(lim, rigidify) match { case tv: TV => L(tv); case tt: AbstractTag => R(tt); case _ => die })\n      val (nvars2, ntags2) = nvars.toBuffer[TV].partitionMap(\n        _.freshenAbove(lim, rigidify) match { case tv: TV => L(tv); case tt: AbstractTag => R(tt); case _ => die })\n      Conjunct(\n        tags2.foldLeft(lnf.freshenAbove(lim, rigidify))(_ & _), vars2.toSortedSet,\n        ntags2.foldLeft(rnf.freshenAbove(lim, rigidify))(_ | _), nvars2.toSortedSet)\n    }\n    def - (fact: Factorizable): Conjunct = fact match {\n      case tv: TV => Conjunct(lnf, vars - tv, rnf, nvars)\n      case NegVar(tv) => Conjunct(lnf, vars, rnf, nvars - tv)\n      case tt: AbstractTag => lnf match {\n        case LhsRefined(b, tts, rft, trs) =>\n          if (tts(tt)) copy(lnf = LhsRefined(b, tts - tt, rft, trs)) else this\n        case LhsTop => this\n      }\n      case NegAbsTag(tt) => rnf match {\n        case RhsBases(tts, r, trs) => copy(rnf = RhsBases(tts.filterNot(_ === tt), r, trs))\n        case RhsBot | _: RhsField => this\n      }\n    }\n    def <:< (that: Conjunct)(implicit ctx: Ctx): Bool =\n      // trace(s\"?? $this <:< $that\") {\n      that.vars.forall(vars) &&\n        lnf <:< that.lnf &&\n        that.rnf <:< rnf &&\n        that.nvars.forall(nvars)\n      // }(r => s\"!! $r\")\n    def & (that: Conjunct, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): Opt[Conjunct] =\n      // trace(s\"?? $this & $that ${lnf & that.lnf} ${rnf | that.rnf}\") {\n      if (lnf <:< that.rnf) N\n      else S(Conjunct.mk(lnf & (that.lnf, pol) getOrElse (return N), vars | that.vars\n        , rnf | (that.rnf, pol) getOrElse (return N)\n        , nvars | that.nvars, pol))\n      // }(r => s\"!! $r\")\n    def neg: Disjunct = Disjunct(rnf, nvars, lnf, vars)\n    /** `tryMergeUnion` tries to compute the union of two conjuncts as a conjunct,\n      * failing if this merging cannot be done without losing information.\n      * This ends up simplifying away things like:\n      *   {x: int} | {y: int} ~> anything\n      *   (A -> B) | {x: C}   ~> anything  */\n    def tryMergeUnion(that: Conjunct)(implicit ctx: Ctx, etf: ExpandTupleFields): Opt[Conjunct] = (this, that) match {\n      case _ if this <:< that => S(that)\n      case _ if that <:< this => S(this)\n      case (Conjunct(LhsTop, vs1, r1, nvs1), Conjunct(LhsTop, vs2, r2, nvs2))\n        if vs1 === vs2 && nvs1 === nvs2\n      =>\n        S(Conjunct(LhsTop, vs1, r1 tryMergeInter r2 getOrElse (return N), nvs1))\n        // * Conceptually, `tryMergeInter` could return None either because the ThsNfs cannot be merged\n        // *  or because merging them would return bottom... but conjuncts cannot represent bottom.\n      case (Conjunct(LhsRefined(bse1, ts1, rcd1, trs1), vs1, r1, nvs1)\n          , Conjunct(LhsRefined(bse2, ts2, rcd2, trs2), vs2, r2, nvs2))\n        if bse1 === bse2 && ts1 === ts2 && vs1 === vs2 && r1 === r2 && nvs1 === nvs2\n        && trs1.keySet === trs2.keySet\n      =>\n        val trs = mergeTypeRefs(true, trs1, trs2)\n        val rcd = RecordType(recordUnion(rcd1.fields, rcd2.fields))(noProv)\n        S(Conjunct(LhsRefined(bse1, ts1, rcd, trs), vs1, r1, nvs1))\n      case (Conjunct(LhsRefined(bse1, ts1, rcd1, trs1), vs1, r1, nvs1)\n          , Conjunct(LhsRefined(bse2, ts2, rcd2, trs2), vs2, r2, nvs2))\n        if ts1 === ts2 && vs1 === vs2 && r1 === r2 && nvs1 === nvs2\n        && trs1 === trs2 // TODO!!\n      =>\n        val ts = ts1\n        \n        val rcdU = RecordType(recordUnion(\n          if (expandTupleFields) rcd1.fields\n            else bse1.map(_.toRecord.fields).fold(rcd1.fields)(recordIntersection(rcd1.fields, _)),\n          if (expandTupleFields) rcd2.fields\n            else bse2.map(_.toRecord.fields).fold(rcd2.fields)(recordIntersection(rcd2.fields, _)),\n        ))(noProv)\n        \n        // Example:\n        //    Why is it sound to merge (A -> B) & {R} | (C -> D) & {S}\n        //    into ((A & C) -> (B | D)) & ({R} | {S}) ?\n        //  Because the former can be distributed to\n        //    (A -> B | C -> D) & (A -> B | {S}) & ({R} | C -> D) & ({R} | {S})\n        //    == ((A & C) -> (B | D)) & Top & Top & ({R} | {S})\n        (bse1, bse2) match {\n          case (S(FunctionType(l1, r1)), S(FunctionType(l2, r2))) => // TODO Q: records ok here?!\n            S(Conjunct(\n              LhsRefined(S(FunctionType(l1 & l2, r1 | r2)(noProv)), ts, rcdU, trs1), vs1, RhsBot, nvs1))\n          case (S(tup1 @ TupleType(fs1)), S(tup2 @ TupleType(fs2))) => // TODO Q: records ok here?!\n            if (fs1.size =/= fs2.size) S(Conjunct(\n              LhsRefined(S(ArrayType(tup1.inner || tup2.inner)(noProv)), ts, rcdU, trs1), vs1, RhsBot, nvs1))\n            else S(Conjunct(\n              LhsRefined(S(TupleType(tupleUnion(fs1, fs2))(noProv)), ts, rcdU, trs1), vs1, RhsBot, nvs1))\n          case (S(tup @ TupleType(fs)), S(ArrayType(ar))) =>\n            S(Conjunct(LhsRefined(S(ArrayType(tup.inner || ar)(noProv)), ts, rcdU, trs1), vs1, RhsBot, nvs1))\n          case (S(ArrayType(ar)), S(tup @ TupleType(fs))) =>\n            S(Conjunct(\n              LhsRefined(S(ArrayType(tup.inner || ar)(noProv)), ts, rcdU, trs1), vs1, RhsBot, nvs1))\n          case (S(ArrayType(ar1)), S(ArrayType(ar2))) =>\n            S(Conjunct(LhsRefined(S(ArrayType(ar1 || ar2)(noProv)), ts, rcdU, trs1), vs1, RhsBot, nvs1))\n          case (N, N)\n            | (S(_: FunctionType), S(_: ArrayBase)) | (S(_: ArrayBase), S(_: FunctionType))\n          =>\n            S(Conjunct(LhsRefined(N, ts, rcdU, trs1), vs1, RhsBot, nvs1))\n          case _ => N\n        }\n        case _ => N\n      }\n    private lazy val mkString: Str =\n      (Iterator(lnf).filter(_ =/= LhsTop) ++ vars\n        ++ (Iterator(rnf).filter(_ =/= RhsBot) ++ nvars).map(\"~(\"+_+\")\")).mkString(\"∧\")\n    override def toString: Str = mkString\n  }\n  \n  object Conjunct {\n    def of(tvs: SortedSet[TypeVariable]): Conjunct = Conjunct(LhsTop, tvs, RhsBot, ssEmp)\n    def mk(lnf: LhsNf, vars: SortedSet[TypeVariable], rnf: RhsNf, nvars: SortedSet[TypeVariable], pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): Conjunct = {\n      Conjunct(lnf, vars, rnf match {\n        case RhsField(name, ty) => RhsField(name, ty)\n        case RhsBases(prims, bf, trs) =>\n          RhsBases(prims.filter(lnf & (_, pol) pipe (_.isDefined)), bf.filter {\n            case L(b) => lnf & (b, pol) pipe (_.isDefined)\n            case R(r) => true\n          }, trs)\n        case RhsBot => RhsBot\n      }, nvars)\n    }\n    /** Scala's standard library is weird. I would have normally made Conjunct extend Ordered[Conjunct],\n      * but the contract of Ordered says that `equals` and `hashCode` should be \"consistent\" with `compare`,\n      * which I understand as two things comparing to 0 HAVING to be equal and to have the same hash code...\n      * But achieving this is very expensive for general type forms.\n      * All we want to do here is to define an ordering between implicit equivalence classes\n      * whose members are not necessarily equal. Which is fine since we only use this to do stable sorts. */\n    implicit object Ordering extends Ordering[Conjunct] {\n      def compare(x: Conjunct, y: Conjunct): Int = x.compareEquiv(y)\n    }\n  }\n  \n  \n  case class Disjunct(rnf: RhsNf, vars: SortedSet[TypeVariable], lnf: LhsNf, nvars: SortedSet[TypeVariable]) {\n    def neg: Conjunct = Conjunct(lnf, nvars, rnf, vars)\n    def | (that: Disjunct, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): Opt[Disjunct] =\n      S(Disjunct(rnf | (that.rnf, pol) getOrElse (return N), vars | that.vars,\n        lnf & (that.lnf, pol) getOrElse (return N), nvars | that.nvars))\n    override def toString: Str =\n      (Iterator(rnf).filter(_ =/= RhsBot) ++ vars\n        ++ (Iterator(lnf).filter(_ =/= LhsTop) ++ nvars).map(\"~\"+_)).mkString(\"∨\")\n  }\n  \n  object Disjunct {\n    def of(tvs: SortedSet[TypeVariable]): Disjunct = Disjunct(RhsBot, tvs, LhsTop, ssEmp)\n  }\n  \n  \n  /** `polymLevel` denotes the level at which this type is quantified (MaxLevel if it is not) */\n  case class DNF(polymLevel: Int, cons: Constrs, cs: Ls[Conjunct]) {\n    assert(polymLevel <= MaxLevel, polymLevel)\n    private def levelBelow(ub: Level): Level =\n      cs.iterator.map(_.levelBelow(ub)(MutSet.empty)).maxOption.getOrElse(MinLevel)\n    lazy val levelBelowPolym = levelBelow(polymLevel)\n    def isBot: Bool = cs.isEmpty\n    def toType(sort: Bool = false): SimpleType = ConstrainedType.mk(cons, if (cs.isEmpty) BotType else {\n      val css = if (sort) cs.sorted else cs\n      PolymorphicType.mk(polymLevel, css.map(_.toType(sort)).foldLeft(BotType: ST)(_ | _))\n    })\n    lazy val level: Level =\n      cs.maxByOption(_.level).fold(MinLevel)(_.level)\n    def isPolymorphic: Bool = level > polymLevel\n    lazy val effectivePolymLevel: Level = if (isPolymorphic) polymLevel else level\n    def instantiate(implicit ctx: Ctx, shadows: Shadows): (Constrs, Ls[Conjunct]) =\n      if (isPolymorphic) {\n        implicit val state: MutMap[TV, ST] = MutMap.empty\n        (\n          cons.map { case (l, r) => (\n            l.freshenAbove(polymLevel, rigidify = false),\n            r.freshenAbove(polymLevel, rigidify = false)\n          )},\n          cs.map(_.freshenAbove(polymLevel, rigidify = false))\n        )\n      } else (cons, cs)\n    def rigidify(implicit ctx: Ctx, shadows: Shadows): Ls[Conjunct] =\n      if (isPolymorphic) {\n        implicit val state: MutMap[TV, ST] = MutMap.empty\n        cs.map(_.freshenAbove(polymLevel, rigidify = true))\n      } else cs\n    def & (that: DNF, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): DNF = {\n      val (newLvl, thisCs, thatCs, thisCons, thatCons) = levelWith(that)\n      thatCs.map(DNF(newLvl, thisCons ::: thatCons, thisCs) &\n        (_, pol)).foldLeft(DNF.extr(false))(_ | _)\n    }\n    /** Returns new DNF components for `this` and `that`\n      * with their polymorphism levels harmonized to a single level. */\n    private def levelWith(that: DNF)(implicit ctx: Ctx)\n          : (Level, Ls[Conjunct], Ls[Conjunct], Constrs, Constrs) = {\n      // println(s\"--- $levelBelowPolym ${that.polymLevel} ${that.levelBelow(polymLevel)}\")\n      \n      implicit val freshened: MutMap[TV, ST] = MutMap.empty\n      \n      // * Some easy cases to avoid having to adjust levels when we can:\n      if (levelBelowPolym <= that.polymLevel && that.levelBelowPolym <= polymLevel)\n        (polymLevel min that.polymLevel, cs, that.cs, cons, that.cons)\n      else if (levelBelow(that.polymLevel) <= polymLevel\n          && levelBelowPolym <= that.polymLevel)\n        (that.polymLevel, cs, that.cs, cons, that.cons)\n      else if (that.levelBelow(polymLevel) <= that.polymLevel\n          && that.levelBelowPolym <= polymLevel)\n        (polymLevel, cs, that.cs, cons, that.cons)\n      \n      // * The two difficult cases:\n      else if (that.polymLevel > polymLevel) ctx.copy(lvl = that.polymLevel + 1) |> {\n          implicit ctx =>\n        assert((polymLevel max that.polymLevel) === that.polymLevel)\n        (polymLevel max that.polymLevel,\n          cs.map(_.freshenAbove(polymLevel, rigidify = false)),\n          that.cs,\n          cons.mapKeys(_.freshenAbove(polymLevel, rigidify = false))\n            .mapValues(_.freshenAbove(polymLevel, rigidify = false)),\n          that.cons\n        )\n      }\n      else if (polymLevel > that.polymLevel) ctx.copy(lvl = polymLevel + 1) |> {\n          implicit ctx =>\n        assert((polymLevel max that.polymLevel) === polymLevel)\n        (polymLevel max that.polymLevel,\n          cs,\n          that.cs.map(_.freshenAbove(that.polymLevel, rigidify = false)),\n          cons,\n          that.cons.mapKeys(_.freshenAbove(polymLevel, rigidify = false))\n            .mapValues(_.freshenAbove(polymLevel, rigidify = false)),\n        )\n      }\n      \n      // * One more easy case:\n      else (polymLevel, cs, that.cs, cons, that.cons) ensuring (that.polymLevel === polymLevel)\n    }\n    def | (that: DNF)(implicit ctx: Ctx, etf: ExpandTupleFields): DNF = {\n      val (newLvl, thisCs, thatCs, thisCons, thatCons) = levelWith(that)\n      // println(s\"-- $polymLevel ${that.polymLevel} $newLvl\")\n      thatCs.foldLeft(DNF(newLvl, thisCons ::: thatCons, thisCs))(_ | _)\n      // ^ Note: conjuncting the constrained-type constraints here is probably the wrong thing to do...\n    }\n    def & (that: Conjunct, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): DNF =\n      DNF(polymLevel, cons, cs.flatMap(_ & (that, pol))) // TODO may need further simplif afterward\n    def | (that: Conjunct)(implicit ctx: Ctx, etf: ExpandTupleFields): DNF = {\n      def go(cs: Ls[Conjunct], acc: Ls[Conjunct], toMerge: Conjunct): Ls[Conjunct] = \n        // trace(s\"go?? $cs $acc M $toMerge\") {\n        cs match {\n        case c :: cs =>\n          if (c <:< toMerge) acc.reverse ::: toMerge :: cs\n          else if (toMerge <:< c) acc.reverse ::: c :: cs\n          else c.tryMergeUnion(toMerge) match {\n            case Some(value) => acc.reverse ::: value :: cs\n            case None => go(cs, c :: acc, toMerge)\n          }\n        case Nil => (toMerge :: acc).reverse\n      }\n      // }(r => s\"go!! $r\")\n      DNF(polymLevel,\n        cons, // FIXME?!\n        go(cs, Nil, that))\n    }\n    override def toString: Str = s\"DNF($polymLevel, ${cs.mkString(\" | \")})${\n      if (cons.isEmpty) \"\"\n      else s\"{${cons.mkString(\", \")}}\"\n    }\"\n  }\n  \n  object DNF {\n    def of(polymLvl: Level, cons: Constrs, lnf: LhsNf): DNF =\n      of(polymLvl, cons, Conjunct(lnf, ssEmp, RhsBot, ssEmp) :: Nil)\n    def of(polymLvl: Level, cons: Constrs, cs: Ls[Conjunct]): DNF = {\n      val res = DNF(polymLvl, cons, cs)\n      val epl = res.effectivePolymLevel\n      if (epl < polymLvl) res.copy(polymLevel = epl)\n      else res\n    }\n    def extr(dir: Bool): DNF = if (dir) of(MinLevel, Nil, LhsTop) else DNF(MinLevel, Nil, Nil)\n    def merge(dir: Bool, pol: Bool)(l: DNF, r: DNF)(implicit ctx: Ctx, etf: ExpandTupleFields): DNF =\n      if (dir) l | r else l & (r, pol)\n    \n    def mkDeep(polymLvl: Level, cons: Constrs, ty: SimpleType, pol: Bool)\n          (implicit ctx: Ctx, ptr: PreserveTypeRefs = false, etf: ExpandTupleFields = true, expandedTVs: Set[TV] = Set.empty): DNF = {\n      mk(polymLvl, cons, mkDeepST(polymLvl, cons, ty, pol), pol)\n    }\n    def mkDeepST(polymLvl: Level, cons: Constrs, ty: SimpleType, pol: Bool)\n          (implicit ctx: Ctx, ptr: PreserveTypeRefs = false, etf: ExpandTupleFields = true): ST =\n            // trace(s\"mkDeepST[$pol,$polymLvl](${ty})\") {\n              ty match {\n      case ProvType(und) =>\n        mkDeepST(polymLvl, cons, und, pol).withProv(ty.prov)\n      case TypeBounds(lb, ub) => mkDeepST(polymLvl, cons, if (pol) ub else lb, pol).withProv(ty.prov)\n      case _ =>\n        val dnf = mk(polymLvl, cons, ty, pol)\n        def go(polo: Opt[Bool], st: ST): ST = polo match {\n          case _ if st === ty => ty.mapPol(polo)(go)\n          case S(pol) => mkDeepST(polymLvl, cons, st, pol)(ctx, ptr = true, etf = false)\n          case N => TypeBounds.mk(\n            mkDeepST(polymLvl, cons, st, false)(ctx, ptr = true, etf = false),\n            mkDeepST(polymLvl, cons, st, true)(ctx, ptr = true, etf = false))\n        }\n        dnf.toType().mapPol(S(pol))(go)\n    }\n    // }(r => s\"= $r\")\n    \n    def mk(polymLvl: Level, cons: Constrs, ty: SimpleType, pol: Bool)(implicit ctx: Ctx, ptr: PreserveTypeRefs = false, etf: ExpandTupleFields = true, expandedTVs: Set[TV] = Set.empty): DNF =\n        // trace(s\"DNF[${printPol(pol)},$ptr,$etf,$polymLvl](${ty})\") {\n        (if (pol) ty.pushPosWithout else ty) match {\n      case bt: BaseType => DNF.of(polymLvl, cons, LhsRefined(S(bt), ssEmp, if (expandTupleFields) bt.toRecord else RecordType.empty, smEmp))\n      case tt: AbstractTag => DNF.of(polymLvl, cons, LhsRefined(N, SortedSet.single(tt), RecordType.empty, smEmp))\n      case rcd: RecordType => DNF.of(polymLvl, cons, LhsRefined(N, ssEmp, rcd, smEmp))\n      case ExtrType(pol) => extr(!pol)\n      case ty @ ComposedType(p, l, r) => merge(p, pol)(mk(polymLvl, cons, l, pol), mk(polymLvl, cons, r, pol))\n      case NegType(und) => DNF.of(polymLvl, cons, CNF.mk(polymLvl, Nil, und, !pol).ds.map(_.neg))\n      case tv @ AssignedVariable(ty) if !preserveTypeRefs && !expandedTVs.contains(tv) =>\n        (expandedTVs + tv) |> { implicit expandedTVs => DNF.mk(polymLvl, cons, ty, pol) }\n      case tv: TypeVariable => DNF.of(polymLvl, cons, Conjunct.of(SortedSet.single(tv)) :: Nil)\n      case ProxyType(underlying) => mk(polymLvl, cons, underlying, pol)\n      case tr @ TypeRef(defn, targs) =>\n        // * TODO later: when proper TypeRef-based simplif. is implemented, can remove this special case\n        if (preserveTypeRefs && !primitiveTypes.contains(defn.name) || !tr.canExpand) {\n          of(polymLvl, cons, LhsRefined(tr.mkClsTag, ssEmp, RecordType.empty, SortedMap(defn -> tr)))\n        } else mk(polymLvl, cons, tr.expandOrCrash, pol)\n      case TypeBounds(lb, ub) => mk(polymLvl, cons, if (pol) ub else lb, pol)\n      case PolymorphicType(lvl, bod) => mk(lvl, cons, bod, pol)\n      case ConstrainedType(cs, bod) => mk(polymLvl, cs ::: cons, bod, pol)\n    }\n    // }(r => s\"= $r\")\n  }\n  \n  \n  case class CNF(ds: Ls[Disjunct]) {\n    def & (that: CNF): CNF = that.ds.foldLeft(this)(_ & _)\n    def | (that: CNF, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): CNF = that.ds.map(this | (_, pol)).foldLeft(CNF.extr(false))(_ & _)\n    def & (that: Disjunct): CNF =\n      // TODO try to merge it with the others if possible\n      CNF(that :: ds)\n    def | (that: Disjunct, pol: Bool)(implicit ctx: Ctx, etf: ExpandTupleFields): CNF = CNF(ds.flatMap(_ | (that, pol)))\n    override def toString: Str = s\"CNF(${ds.mkString(\" & \")})\"\n  }\n  \n  object CNF {\n    def of(rnf: RhsNf): CNF = CNF(Disjunct(rnf, ssEmp, LhsTop, ssEmp) :: Nil)\n    def of(bt: BaseType): CNF =\n      CNF.of(RhsBot | bt getOrElse (return CNF.extr(true)))\n    def of(tvs: SortedSet[TypeVariable]): CNF = CNF(Disjunct.of(tvs) :: Nil)\n    def of(rcd: RecordType): CNF = CNF(rcd.fields.iterator.map(f =>\n      Disjunct(RhsField(f._1, f._2), ssEmp, LhsTop, ssEmp)).toList)\n    def extr(pol: Bool): CNF = if (pol) CNF(Nil) else of(RhsBot)\n    def merge(pol: Bool)(l: CNF, r: CNF)(implicit ctx: Ctx, etf: ExpandTupleFields): CNF = if (pol) l | (r, pol) else l & r\n    def mk(polymLvl: Level, cons: Constrs, ty: SimpleType, pol: Bool)(implicit ctx: Ctx, ptr: PreserveTypeRefs, etf: ExpandTupleFields, expandedTVs: Set[TV] = Set.empty): CNF =\n      // trace(s\"?CNF $ty\") {\n      ty match {\n        case bt: BaseType => of(bt)\n        case tt: AbstractTag => of(RhsBases(tt :: Nil, N, smEmp))\n        case rt @ RecordType(fs) => of(rt)\n        case ExtrType(pol) => extr(!pol)\n        case ty @ ComposedType(p, l, r) => merge(p)(mk(polymLvl, cons, l, pol), mk(polymLvl, cons, r, pol))\n        case NegType(und) => CNF(DNF.mk(polymLvl, cons, und, !pol).cs.map(_.neg))\n        case tv @ AssignedVariable(ty) if !preserveTypeRefs && !expandedTVs.contains(tv) =>\n          (expandedTVs + tv) |> { implicit expandedTVs => CNF.mk(polymLvl, cons, ty, pol) }\n        case tv: TypeVariable => of(SortedSet.single(tv))\n        case ProxyType(underlying) => mk(polymLvl, cons, underlying, pol)\n        case tr @ TypeRef(defn, targs) =>\n          if (preserveTypeRefs && !primitiveTypes.contains(defn.name) || !tr.canExpand) {\n            CNF(Disjunct(RhsBases(Nil, N, SortedMap.single(defn -> tr)), ssEmp, LhsTop, ssEmp) :: Nil)\n          } else mk(polymLvl, cons, tr.expandOrCrash, pol)\n        case TypeBounds(lb, ub) => mk(polymLvl, cons, if (pol) ub else lb, pol)\n        case PolymorphicType(lvl, bod) => mk(lvl, cons, bod, pol)\n        case ConstrainedType(cs, bod) => mk(lvl, cs ::: cons, bod, pol)\n      }\n      // }(r => s\"!CNF $r\")\n  }\n  \n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/NuTypeDefs.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet}\nimport scala.collection.immutable.{SortedSet, SortedMap}\nimport scala.util.chaining._\nimport scala.annotation.tailrec\nimport mlscript.utils._, shorthands._\nimport mlscript.Message._\n\nclass NuTypeDefs extends ConstraintSolver { self: Typer =>\n  import TypeProvenance.{apply => tp}\n  \n  \n  type Params = Ls[Var -> FieldType]\n  type TyParams = Ls[(TN, TV, Opt[VarianceInfo])]\n  \n  \n  sealed abstract class NuDeclInfo\n  \n  case class FunInfo() extends NuDeclInfo\n  case class TypeDefInfo() extends NuDeclInfo\n  \n  \n  sealed trait NuMember {\n    def name: Str\n    def kind: DeclKind\n    def toLoc: Opt[Loc]\n    def level: Level\n    def isImplemented: Bool\n    def isPublic: Bool\n    def isPrivate: Bool = !isPublic // * We currently don't support `protected`\n    \n    def isValueParam: Bool = this match {\n      case p: NuParam => !p.isType\n      case _ => false\n    }\n    \n    protected def withLevel[R](k: Ctx => R)(implicit ctx: Ctx): R = k(ctx.copy(lvl = ctx.lvl + 1))\n    \n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV, ST])\n          : NuMember\n    \n    def map(f: ST => ST)(implicit ctx: Ctx): NuMember =\n      mapPol(N, false)((_, ty) => f(ty))\n    \n    // TODO rm – just use `mapPolMap`\n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): NuMember\n    \n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): NuMember\n    \n    def showBounds: Str = TypedTypingUnit(this :: Nil, N).showBounds\n  }\n  \n  \n  case class NuParam(nme: NameRef, ty: FieldType, isPublic: Bool)(val level: Level)\n      extends NuMember with TypedNuTermDef\n  {\n    def name: Str = nme.name\n    def isType: Bool = nme.isInstanceOf[TypeName]\n    def kind: DeclKind =\n      if (isType) Als // FIXME?\n      else Val\n    def toLoc: Opt[Loc] = nme.toLoc\n    def isImplemented: Bool = true\n    def isVirtual: Bool = false // TODO allow annotating parameters with `virtual`\n    def typeSignature: ST = ty.ub\n    \n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV, ST])\n          : NuParam =\n      NuParam(nme, ty.freshenAbove(lim, rigidify), isPublic)(ctx.lvl)\n    \n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): NuParam =\n        NuParam(nme, ty.update(t => f(pol.map(!_), t), t => f(pol, t)), isPublic)(level)\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): NuParam =\n        NuParam(nme, ty.update(t => f(pol.contravar, t), t => f(pol, t)), isPublic)(level)\n  }\n  \n  \n  sealed trait TypedNuDecl extends NuMember {\n    def name: Str\n    def level: Level\n    \n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuDecl\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuDecl\n  }\n  \n  \n  // TODO rm?\n  /** Those declarations that introduce term names in scope. */\n  sealed trait TypedNuTermDef extends TypedNuDecl with AnyTypeDef {\n    def typeSignature: ST\n  }\n  \n  \n  sealed abstract class TypedNuTypeDef(kind: TypeDefKind) extends TypedNuDecl {\n    def nme: TypeName\n    def decl: NuTypeDef\n    def toLoc: Opt[Loc] = decl.toLoc\n    def tparams: TyParams\n    def members: Map[Str, NuMember]\n    val allFields: Set[Var] = members.valuesIterator.map(_.name |> Var).toSet\n    val td: NuTypeDef\n    val prov: TP = TypeProvenance(td.toLoc, td.describe, isType = true)\n    val level: Level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = ???\n  }\n  \n  \n  case class TypedNuAls(level: Level, td: NuTypeDef, tparams: TyParams, body: ST)\n    extends TypedNuTypeDef(Als)\n  {\n    def decl: NuTypeDef = td\n    def kind: DeclKind = td.kind\n    def name: Str = nme.name\n    def nme: mlscript.TypeName = td.nme\n    def members: Map[Str, NuMember] = Map.empty\n    def isImplemented: Bool = td.sig.isDefined\n    def isPublic = true // TODO\n    \n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV,ST])\n          : TypedNuAls = { val outer = ctx; withLevel { implicit ctx =>\n      TypedNuAls(outer.lvl, td,\n        tparams.map(tp => (tp._1, tp._2.freshenAbove(lim, rigidify).assertTV, tp._3)),\n        body.freshenAbove(lim, rigidify))\n    }}\n    \n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuDecl =\n        TypedNuAls(\n          level, td,\n          tparams.map(tp => (tp._1, f(N, tp._2).assertTV, tp._3)),\n          f(pol, body)\n        )\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuDecl =\n        TypedNuAls(\n          level, td,\n          tparams.map(tp => (tp._1, f(pol.invar, tp._2).assertTV, tp._3)),\n          f(pol, body)\n        )\n  }\n  \n  sealed trait PolyNuDecl extends TypedNuDecl {\n    def tparams: TyParams\n  }\n  \n  \n  case class TypedNuTrt(\n        level: Level, td: NuTypeDef,\n        tparams: TyParams,\n        members: Map[Str, NuMember],\n        thisTy: ST,\n        sign: ST,\n        inheritedTags: Set[TypeName],\n        parentTP: Map[Str, NuMember]\n      ) extends TypedNuTypeDef(Trt) with PolyNuDecl\n  {\n    def decl: NuTypeDef = td\n    def kind: DeclKind = td.kind\n    def nme: TypeName = td.nme\n    def name: Str = nme.name\n    def isImplemented: Bool = true\n    def isPublic = true // TODO\n    \n    // TODO dedup with the one in TypedNuCls\n    lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map {\n      case (nme @ TypeName(name), tv, _) => \n        td.nme.name+\"#\"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = true)(level)\n    } ++ parentTP\n    \n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV,ST])\n          : TypedNuTrt = { val outer = ctx; withLevel { implicit ctx =>\n      TypedNuTrt(outer.lvl, td,\n        tparams.map(tp => (tp._1, tp._2.freshenAbove(lim, rigidify).assertTV, tp._3)),\n        members.mapValuesIter(_.freshenAbove(lim, rigidify)).toMap,\n        thisTy.freshenAbove(lim, rigidify),\n        sign.freshenAbove(lim, rigidify),\n        inheritedTags,\n        parentTP.mapValuesIter(_.freshenAbove(lim, rigidify)).toMap\n      )\n    }}\n    \n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuTrt =\n        TypedNuTrt(level, td,\n          tparams.map(tp => (tp._1, f(N, tp._2).assertTV, tp._3)),\n          members.mapValuesIter(_.mapPol(pol, smart)(f)).toMap,\n          f(pol.map(!_), thisTy),\n          f(pol, sign),\n          inheritedTags,\n          parentTP.mapValuesIter(_.mapPol(pol, smart)(f)).toMap\n        )\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuTrt =\n        TypedNuTrt(level, td,\n          tparams.map(tp => (tp._1, f(pol.invar, tp._2).assertTV, tp._3)),\n          members.mapValuesIter(_.mapPolMap(pol)(f)).toMap,\n          f(pol.contravar, thisTy),\n          f(pol, sign),\n          inheritedTags,\n          parentTP.mapValuesIter(_.mapPolMap(pol)(f)).toMap\n        )\n  }\n  \n  \n  case class TypedNuCls(\n        level: Level, td: NuTypeDef,\n        tparams: TyParams,\n        params: Opt[Ls[Var -> FieldType]],\n        auxCtorParams: Opt[Ls[Var -> ST]],\n        members: Map[Str, NuMember],\n        thisTy: ST,\n        sign: ST,\n        inheritedTags: Set[TypeName],\n        parentTP: Map[Str, NuMember]\n      ) extends TypedNuTypeDef(Cls) with PolyNuDecl\n  {\n    def decl: NuTypeDef = td\n    def kind: DeclKind = td.kind\n    def nme: TypeName = td.nme\n    def name: Str = nme.name\n    def isImplemented: Bool = true\n    def isPublic = true // TODO\n    \n    /** The type of a palin term reference to this type definition. */\n    def typeSignature(usesNew: Bool, loco: Opt[Loc])(implicit raise: Raise): ST =\n      typeSignatureOf(usesNew, loco, td, level, tparams, params, auxCtorParams, sign, inheritedTags)\n    \n    /** Includes class-name-coded type parameter fields. */\n    lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map {\n      case (nme @ TypeName(name), tv, _) => \n        td.nme.name+\"#\"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = true)(level)\n    } ++ parentTP\n    \n    // TODO\n    // def checkVariances\n    \n    // lazy val explicitVariances: VarianceStore =\n    //   MutMap.from(tparams.iterator.map(tp => tp._2 -> tp._3.getOrElse(VarianceInfo.in)))\n    \n    // TODO should we really recompute them on freshened instances, or can we avoid that?\n    private var _variances: Opt[VarianceStore] = N\n    def variances(implicit ctx: Ctx): VarianceStore = {\n      _variances match {\n        case S(res) => res\n        case N => trace(s\"Computing variances of ${this.name}\") {\n          val store = VarianceStore.empty\n          val traversed = MutSet.empty[Pol -> TV]\n          \n          object Trav extends Traverser2.InvariantFields {\n            override def apply(pol: PolMap)(ty: ST): Unit =\n                trace(s\"Trav($pol)($ty)\") {\n                ty match {\n              case tv: TypeVariable => if (traversed.add(pol(tv) -> tv)) {\n                store(tv) = store.getOrElse(tv, VarianceInfo.bi) && (pol(tv) match {\n                  case S(true) => VarianceInfo.co\n                  case S(false) => VarianceInfo.contra\n                  case N => VarianceInfo.in\n                })\n                super.apply(pol)(ty)\n              }\n              case ty @ RecordType(fs) =>\n                // Ignore type param members such as `C#A` in `{C#A: mut A30'..A30'}`\n                super.apply(pol)(RecordType(fs.filterNot(_._1.name.contains('#')))(ty.prov))\n              case _ => super.apply(pol)(ty)\n            }\n            }()\n          }\n          members.foreachEntry {\n            case (_, m: NuParam) if m.isType =>\n            case (_, m) => Trav.applyMem(PolMap.pos)(m)\n          }\n          \n          // TODO check consistency with explicitVariances\n          val res = store ++ tparams.iterator.collect { case (_, tv, S(vi)) => tv -> vi }\n          \n          _variances = S(res)\n          \n          res\n        }(r => s\"= $r\")\n      }\n    }\n    \n    def varianceOf(tv: TV)(implicit ctx: Ctx): VarianceInfo =\n      variances.getOrElse(tv, VarianceInfo.in)\n\n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV,ST])\n          : TypedNuCls = { val outer = ctx; withLevel { implicit ctx =>\n      TypedNuCls(outer.lvl, td,\n        tparams.map(tp => (tp._1, tp._2.freshenAbove(lim, rigidify).assertTV, tp._3)),\n        params.map(_.mapValues(_.freshenAbove(lim, rigidify))),\n        auxCtorParams.map(_.mapValues(_.freshenAbove(lim, rigidify))),\n        members.mapValuesIter(_.freshenAbove(lim, rigidify)).toMap,\n        thisTy.freshenAbove(lim, rigidify),\n        sign.freshenAbove(lim, rigidify),\n        inheritedTags,\n        parentTP.mapValuesIter(_.freshenAbove(lim, rigidify)).toMap,\n      )\n    }}\n    \n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuCls =\n        TypedNuCls(level, td,\n          tparams.map(tp => (tp._1, f(N, tp._2).assertTV, tp._3)),\n          params.map(_.mapValues(_.update(t => f(pol.map(!_), t), t => f(pol, t)))),\n          auxCtorParams.map(_.mapValues(t => f(pol.map(!_), t))),\n          members.mapValuesIter(_.mapPol(pol, smart)(f)).toMap,\n          f(pol.map(!_), thisTy),\n          f(pol, sign),\n          inheritedTags,\n          parentTP.mapValuesIter(_.mapPol(pol, smart)(f)).toMap,\n        )\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuCls =\n        TypedNuCls(level, td,\n          tparams.map(tp => (tp._1, f(pol.invar, tp._2).assertTV, tp._3)),\n          params.map(_.mapValues(_.update(t => f(pol.contravar, t), t => f(pol, t)))),\n          auxCtorParams.map(_.mapValues(t => f(pol.contravar, t))),\n          members.mapValuesIter(_.mapPolMap(pol)(f)).toMap,\n          f(pol.contravar, thisTy),\n          f(pol, sign),\n          inheritedTags,\n          parentTP.mapValuesIter(_.mapPolMap(pol)(f)).toMap,\n        )\n    \n    override def toString: Str = s\"TypedNuCls($level, ${td.nme},\\n\\t$tparams,\\n\\t$params,\\n\\tthis: $thisTy, ${\n      members.lnIndent()},\\n\\t: $sign, $inheritedTags, $parentTP)\"\n  }\n  \n  \n  case class TypedNuMxn(\n        level: Level, td: NuTypeDef,\n        thisTy: ST, superTy: ST,\n        tparams: TyParams,\n        params: Ls[Var -> FieldType],\n        members: Map[Str, NuMember],\n      ) extends TypedNuTypeDef(Mxn) with PolyNuDecl\n  {\n    def decl: NuTypeDef = td\n    def kind: DeclKind = td.kind\n    def nme: TypeName = td.nme\n    def name: Str = nme.name\n    def isImplemented: Bool = true\n    def isPublic = true // TODO\n\n    lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map {\n      case (nme @ TypeName(name), tv, _) => \n        td.nme.name+\"#\"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = false)(level)\n    }\n    \n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV,ST])\n          : TypedNuMxn = { val outer = ctx; withLevel { implicit ctx =>\n      TypedNuMxn(outer.lvl, td,\n        thisTy.freshenAbove(lim, rigidify),\n        superTy.freshenAbove(lim, rigidify),\n        tparams.map(tp => (tp._1, tp._2.freshenAbove(lim, rigidify).assertTV, tp._3)),\n        params.mapValues(_.freshenAbove(lim, rigidify)),\n        members.mapValuesIter(_.freshenAbove(lim, rigidify)).toMap,\n      )\n    }}\n    \n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuMxn =\n      TypedNuMxn(level, td, f(pol.map(!_), thisTy), f(pol.map(!_), superTy),\n        tparams.map(tp => (tp._1, f(N, tp._2).assertTV, tp._3)),\n        params.mapValues(_.update(t => f(pol.map(!_), t), t => f(pol, t))),\n        members.mapValuesIter(_.mapPol(pol, smart)(f)).toMap)\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuMxn =\n      TypedNuMxn(level, td, f(pol.contravar, thisTy), f(pol.contravar, superTy),\n        tparams.map(tp => (tp._1, f(pol.invar, tp._2).assertTV, tp._3)),\n        params.mapValues(_.update(t => f(pol.contravar, t), t => f(pol, t))),\n        members.mapValuesIter(_.mapPolMap(pol)(f)).toMap)\n    \n    override def toString: Str = s\"TypedNuMxn($level, ${td.nme},\\n\\tthis: $thisTy,\\n\\tsuper: $superTy,\\n\\ttparams: $tparams,\\n\\tparams: $params,\\n\\tmembers: ${members.lnIndent()}\\n)\"\n  }\n  \n  \n  /** Used when there was an error while tying a definition. */\n  case class TypedNuDummy(d: NuDecl) extends TypedNuDecl with TypedNuTermDef {\n    def level = MinLevel\n    def kind: DeclKind = Val\n    def toLoc: Opt[Loc] = N\n    def name: Str = d.name\n    def isImplemented: Bool = true\n    def isPublic = true // TODO\n    def typeSignature: ST = errType\n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV, ST]) =\n      this\n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuTermDef =\n      this\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuTermDef =\n      this\n  }\n  \n  // Field `thisRef` is defined when the member refers to `this` selecting a field on it\n  // e.g., val x = this\n  // Field `refs` contains all `Var`s accessed by the member with their possible `this` qualifiers (`None` if it is an unqualified access)\n  case class RefMap(thisRef: Opt[Var], refs: Set[(Var, Opt[Var])])\n  object RefMap {\n    lazy val nothing: RefMap = RefMap(N, Set.empty)\n  }\n  \n  /** Note: the type `bodyType` is stored *without* its polymorphic wrapper! (unlike `typeSignature`) */\n  case class TypedNuFun(level: Level, fd: NuFunDef, bodyType: ST)(val isImplemented: Bool)\n      extends TypedNuDecl with TypedNuTermDef {\n    def kind: DeclKind = Val\n    def name: Str = fd.nme.name\n    def symbolicName: Opt[Str] = fd.symbolicNme.map(_.name)\n    def toLoc: Opt[Loc] = fd.toLoc\n    lazy val prov = TypeProvenance(toLoc, \"member\")\n    def isPublic: Bool = !fd.isLetOrLetRec\n    lazy val typeSignature: ST =\n      if (fd.isMut) bodyType\n      else PolymorphicType.mk(level, bodyType)\n    \n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV, ST])\n          : TypedNuFun = { val outer = ctx; withLevel { implicit ctx => this match {\n      case TypedNuFun(level, fd, ty) =>\n        TypedNuFun(outer.lvl, fd, ty.freshenAbove(lim, rigidify))(isImplemented)\n          // .tap(res => println(s\"Freshen[$level,${ctx.lvl}] $this ~> $res\"))\n    }}}\n    \n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuFun =\n      TypedNuFun(level, fd, f(pol, bodyType))(isImplemented)\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedNuFun =\n      TypedNuFun(level, fd, f(pol, bodyType))(isImplemented)\n\n    def getFunRefs: RefMap = fd.rhs match {\n      case L(term) => getRefs(term)\n      case _ => RefMap.nothing\n    }\n  }\n  \n  \n  case class TypedTypingUnit(implementedMembers: Ls[NuMember], result: Opt[ST]) extends OtherTypeLike {\n    def map(f: ST => ST)(implicit ctx: Ctx): TypedTypingUnit =\n      TypedTypingUnit(implementedMembers.map(_.map(f)), result.map(f))\n    def mapPol(pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedTypingUnit =\n      TypedTypingUnit(implementedMembers.map(_.mapPol(pol, smart)(f)), result.map(f(pol, _)))\n    def mapPolMap(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType)\n          (implicit ctx: Ctx): TypedTypingUnit =\n      TypedTypingUnit(implementedMembers.map(_.mapPolMap(pol)(f)), result.map(f(pol, _)))\n    def freshenAbove(lim: Int, rigidify: Bool)\n          (implicit ctx: Ctx, freshened: MutMap[TV, ST])\n          : TypedTypingUnit =\n      TypedTypingUnit(implementedMembers.map(_.freshenAbove(lim, rigidify)), result.map(_.freshenAbove(lim, rigidify)))\n    override def toString: Str = s\"TypedTypingUnit(${(implementedMembers :+ result).lnIndent()})\"\n  }\n  \n  \n  def typeSignatureOf(usesNew: Bool, loco: Opt[Loc], td: NuTypeDef, level: Level,\n      tparams: TyParams, params: Opt[Params], acParams: Opt[Ls[Var -> ST]], selfTy: ST, ihtags: Set[TypeName])\n      (implicit raise: Raise)\n      : ST = \n    if ((td.kind is Mod) && params.isEmpty)\n      if (tparams.isEmpty) \n        TypeRef(td.nme, Nil)(provTODO)\n      else PolymorphicType.mk(level,\n        TypeRef(td.nme, tparams.map(_._2))(provTODO))\n    else if ((td.kind is Cls) || (td.kind is Mod)) {\n      if (td.kind is Mod)\n        err(msg\"Parameterized modules are not yet supported\", loco)\n      println(s\"params: $params $acParams\")\n      if (!usesNew)\n        if (params.isEmpty)\n          if (acParams.isEmpty)\n            return err(msg\"Class ${td.nme.name} cannot be instantiated as it exposes no constructor\", loco)\n          else err(msg\"Construction of unparameterized class ${td.nme.name} should use the `new` keyword\", loco)\n        else if (acParams.isDefined)\n          err(msg\"Construction of class with auxiliary constructor should use the `new` keyword\", loco)\n      val ps: Params = acParams match {\n        case S(acParams) => acParams.mapValues(_.toUpper(noProv))\n        case N => params.getOrElse(Nil)\n      }\n      PolymorphicType.mk(level,\n        FunctionType(\n          TupleType(ps.mapKeys(some))(provTODO),\n          TypeRef(td.nme, tparams.map(_._2))(provTODO)\n        )(provTODO)\n      )\n    } else errType // FIXME\n  \n  \n  def getRefs(body: Statement): RefMap = {\n    val refs = mutable.HashSet[(Var, Opt[Var])]()\n\n    def visit(s: Located): Opt[Var] = s match {\n      case Sel(ths @ Var(\"this\"), v) =>\n        refs.add((v, S(ths)))\n        N\n      case v @ Var(name) =>\n        if (name === \"this\") S(v)\n        else {\n          refs.add((v, N))\n          N\n        }\n      case _: Type => N\n      case _: Term| _: Statement | _: NuDecl | _: IfBody | _: CaseBranches | _: TypingUnit =>\n          s.children.foldLeft[Opt[Var]](N)((r, c) => r.orElse(visit(c)))\n    }\n\n    RefMap(visit(body), refs.toSet)\n  }\n  \n  /** Type checks a typing unit, which is a sequence of possibly-mutually-recursive type and function definitions\n   *  interleaved with plain statements. */\n  def typeTypingUnit(tu: TypingUnit, outer: Opt[Outer])\n        (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType]): TypedTypingUnit =\n      trace(s\"${ctx.lvl}. Typing $tu\")\n  {\n    val topLevel: Bool = outer.isEmpty\n    \n    // println(s\"vars ${vars}\")\n    \n    tu.entities.foreach {\n      case fd: NuFunDef if fd.isLetRec.isEmpty && outer.exists(_.kind is Block) =>\n        err(msg\"Cannot use `val` or `fun` in local block; use `let` instead.\", fd.toLoc)\n      case _ =>\n    }\n    \n    val named = mutable.Map.empty[Str, LazyTypeInfo]\n    \n    // * Not sure we should support declaring signature with the `ident: type` syntax\n    // val (signatures, otherEntities) = tu.entities.partitionMap {\n    //   case Asc(v: Var, ty) => L(v -> ty)\n    //   case s => R(s)\n    // }\n    val (decls, statements) = tu.entities.partitionMap {\n      case decl: NuDecl => L(decl)\n      case s => R(s)\n    }\n    val funSigs = MutMap.empty[Str, NuFunDef]\n    val implems = decls.filter {\n      case fd @ NuFunDef(_, nme, snme, tparams, R(rhs)) =>\n        if (fd.isLetOrLetRec)\n          err(s\"`let` bindings must have a right-hand side\", fd.toLoc)\n        funSigs.updateWith(nme.name) {\n          case S(s) =>\n            err(s\"A type signature for '${nme.name}' was already given\", fd.toLoc)\n            S(s)\n          case N => S(fd)\n        }\n        false // * Explicit signatures will already be typed in DelayedTypeInfo's typedSignatures\n      case _ => true\n    }\n    \n    val sigInfos = if (topLevel) funSigs.map { case (nme, decl) =>\n      val lti = new DelayedTypeInfo(decl, implicitly)\n      \n      // TODO check against duplicated symbolic names in same scope...\n      decl.symbolicNme.foreach(snme => ctx += snme.name -> lti)\n      \n      decl.name -> lti\n    } else Nil\n    \n    val infos = implems.map {\n      case _decl: NuDecl =>\n        val decl = _decl match {\n          case fd: NuFunDef =>\n            assert(fd.signature.isEmpty)\n            funSigs.get(fd.nme.name) match {\n              case S(sig) =>\n                fd.copy()(fd.declareLoc, fd.virtualLoc, fd.mutLoc, S(sig), outer, fd.genField, fd.annotations)\n              case _ =>\n                fd.copy()(fd.declareLoc, fd.virtualLoc, fd.mutLoc, fd.signature, outer, fd.genField, fd.annotations)\n            }\n          case td: NuTypeDef =>\n            if (td.nme.name in reservedTypeNames)\n              err(msg\"Type name '${td.nme.name}' is reserved\", td.toLoc)\n            td\n        }\n        val lti = new DelayedTypeInfo(decl, implicitly)\n        decl match {\n          case td: NuTypeDef =>\n            ctx.tyDefs2 += td.nme.name -> lti\n          case fd: NuFunDef =>\n            // TODO check against duplicated symbolic names in same scope...\n            fd.symbolicNme.foreach(snme => ctx += snme.name -> lti)\n        }\n        named.updateWith(decl.name) {\n          case sv @ S(v) =>\n            decl match {\n              case NuFunDef(S(_), _, _, _, _) => ()\n              case _ =>\n                err(msg\"Redefinition of '${decl.name}'\", decl.toLoc)\n            }\n            S(lti)\n          case N =>\n            S(lti)\n        }\n        decl.name -> lti\n    }\n    \n    ctx ++= infos\n    ctx ++= sigInfos\n    \n    val tpdFunSigs = sigInfos.mapValues(_.complete() match {\n      case res: TypedNuFun if res.fd.isDecl =>\n        TopType\n      case res: TypedNuFun =>\n        res.typeSignature\n      case _ => die\n    }).toMap\n    \n    // * Complete typing of block definitions and add results to context\n    val completedInfos = (infos ++ sigInfos).mapValues(_.complete() match {\n      case res: TypedNuFun =>\n        tpdFunSigs.get(res.name) match {\n          case S(expected) =>\n            implicit val prov: TP =\n              TypeProvenance(res.fd.toLoc, res.fd.describe)\n            subsume(res.typeSignature, expected)\n          case _ =>\n            // * Generalize functions as they are typed.\n            // * Note: eventually we'll want to first reorder their typing topologically so as to maximize polymorphism.\n            ctx += res.name -> VarSymbol(res.typeSignature, res.fd.nme)\n            res.symbolicName.foreach(ctx += _ -> VarSymbol(res.typeSignature, res.fd.nme))\n        }\n        CompletedTypeInfo(res)\n      case res => CompletedTypeInfo(res)\n    })\n    ctx ++= completedInfos\n    \n    val returnsLastExpr = outer.map(_.kind) match {\n      case N | S(Block | Val) => true\n      case S(_: TypeDefKind) => false\n    }\n    \n    // * Type the block statements\n    def go(stmts: Ls[Statement]): Opt[ST] = stmts match {\n      case s :: stmts =>\n        val res_ty = s match {\n          case decl: NuDecl => N\n          case t: Term =>\n            implicit val genLambdas: GenLambdas = true\n            val ty = typeTerm(t)\n            if (!topLevel && !(stmts.isEmpty && returnsLastExpr)) {\n              t match {\n                // * We do not include `_: Var` because references to `fun`s and lazily-initialized\n                // * definitions may have side effects.\n                case _: Lit | _: Lam =>\n                  warn(\"Pure expression does nothing in statement position.\", t.toLoc)\n                case _ =>\n                  constrain(mkProxy(ty, TypeProvenance(t.toCoveringLoc, \"expression in statement position\")), UnitType)(\n                    raise = err => raise(WarningReport( // Demote constraint errors from this to warnings\n                      msg\"Expression in statement position should have type `()`.\" -> N ::\n                      msg\"Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\" -> N ::\n                      err.allMsgs, newDefs)),\n                    prov = TypeProvenance(t.toLoc, t.describe), ctx)\n              }\n            }\n            S(ty)\n          case s: DesugaredStatement =>\n            err(msg\"Illegal position for this ${s.describe} statement.\", s.toLoc)(raise)\n            N\n          case _ => die\n        }\n        stmts match {\n          case Nil => res_ty\n          case stmts =>\n            // TODO check discarded non-unit values\n            go(stmts)\n        }\n      case Nil => N\n    }\n    val res_ty = trace(\"Typing unit statements\") { go(statements) } (r => s\": $r\")\n    \n    TypedTypingUnit(completedInfos.map(_._2.member), res_ty)\n    \n  }()\n  \n  \n  \n  \n  trait DelayedTypeInfoImpl { this: DelayedTypeInfo =>\n    private def outerCtx = ctx\n    \n    var isComputing: Bool = false // Replace by a Ctx entry?\n    var result: Opt[TypedNuDecl] = N\n    def isComputed: Bool = result.isDefined\n    \n    val level: Level = ctx.lvl\n    \n    val kind: DeclKind = decl.kind\n    val name: Str = decl.name\n    \n    private implicit val prov: TP =\n      TypeProvenance(decl.toLoc, decl.describe)\n    \n    // * TODO should we use this? It could potentially improve error messages\n    implicit val newDefsInfo: Map[Str, (TypeDefKind, Int)] = Map.empty // TODO?\n    \n    println(s\"${ctx.lvl}. Created lazy type info for $decl\")\n\n    type ParentSpec = (Term, Var, LazyTypeInfo, Ls[Type], Ls[Opt[Var] -> Fld])\n    lazy val parentSpecs: Ls[ParentSpec] = decl match {\n      case td: NuTypeDef => \n        td.parents.flatMap {\n          case v @ Var(nme) =>\n            S(v, v, Nil, Nil)\n          case p @ App(v @ Var(nme), Tup(args)) =>\n            S(p, v, Nil, args)\n          case TyApp(v @ Var(nme), targs) =>\n            S(v, v, targs, Nil)\n          case p @ App(TyApp(v @ Var(nme), targs), Tup(args)) =>\n            S(p, v, targs, args)\n          case p =>\n            err(msg\"Unsupported parent specification\", p.toLoc) // TODO\n            N\n        }.flatMap {\n          case (p, v @ Var(parNme), parTargs, parArgs) =>\n            ctx.get(parNme) match {\n              case S(lti: LazyTypeInfo) =>\n                S((p, v, lti, parTargs, parArgs))\n              case S(_) =>\n                err(msg\"Cannot inherit from this\", p.toLoc)\n                N\n              case N => \n                err(msg\"Could not find definition `${parNme}`\", p.toLoc)\n                N\n            }\n        }\n      case _ => Nil\n    }\n    \n    /** First list of members is for the typed arguments;\n     *  the map of members is for the inherited virtual type argument members. */\n    type TypedParentSpec = (TypedNuTypeDef, Ls[NuParam], Map[Str, NuMember], Opt[Loc])\n    \n    private var typingParents = false\n    lazy val typedParents: Ls[TypedParentSpec] = ctx.nest.nextLevel { implicit ctx =>\n      \n      ctx ++= paramSymbols\n      \n      if (typingParents === true) {\n        err(msg\"Unhandled cyclic parent specification\", decl.toLoc)\n        Nil\n      } else\n      try {typingParents = true; parentSpecs}.flatMap {\n        case (p, v @ Var(parNme), lti, parTargs, parArgs) =>\n          trace(s\"${lvl}. Typing parent spec $p\") {\n            val info = lti.complete()\n            info match {\n              \n              case rawMxn: TypedNuMxn =>\n                \n                // println(s\"Raw $rawMxn\")\n                val (fr, ptp) = refreshHelper(rawMxn, v, if (parTargs.isEmpty) N else S(parTargs)) // type args inferred\n                val mxn = {\n                  implicit val frenshened: MutMap[TV,ST] = fr\n                  implicit val ctx: Ctx = outerCtx\n                  rawMxn.freshenAbove(info.level, rigidify = false)\n                }\n                // println(s\"Fresh $mxn\")\n                \n                val argMembs =  {                      \n                  if (parArgs.sizeCompare(mxn.params) =/= 0)\n                    err(msg\"mixin $parNme expects ${\n                      mxn.params.size.toString} parameter(s); got ${parArgs.size.toString}\", Loc(v :: parArgs.unzip._2))\n                  \n                  val paramMems = mxn.params.lazyZip(parArgs).flatMap {\n                    case (nme -> p, _ -> Fld(FldFlags(mut, spec, get), a)) => // TODO factor this with code for classes:\n                      assert(!mut && !spec && !get, \"TODO\") // TODO check mut, spec, get\n                      implicit val genLambdas: GenLambdas = true\n                      val a_ty = typeTerm(a)\n                      p.lb.foreach(constrain(_, a_ty))\n                      constrain(a_ty, p.ub)\n                      val isPublic = mxn.members(nme.name).isPublic\n                      val fty = if (p.lb.isDefined)\n                          // * We don't refine the field type when it's mutable as that could lead to muable updates being rejected\n                          FieldType(p.lb, p.ub)(provTODO)\n                        else FieldType(p.lb, a_ty)(provTODO)\n                      Option.when(isPublic)(NuParam(nme, fty, isPublic = isPublic)(lvl))\n                  }\n                  \n                  paramMems //++ mxn.members.valuesIterator\n                  \n                }\n                println(s\"Mixin arg members $argMembs\")\n                \n                S((mxn, argMembs, \n                  Map.empty[Str, NuMember], // TODO add ptp here once we support explicit type args\n                  p.toLoc\n                ))\n                \n              case rawTrt: TypedNuTrt =>\n                if (parArgs.nonEmpty) err(msg\"trait arguments are not yet supported\", p.toLoc)\n\n                val (fr, ptp) = refreshHelper(rawTrt, v, if (parTargs.isEmpty) N else S(parTargs))  // infer ty args if not provided\n                val trt = {\n                  implicit val frenshened: MutMap[TV,ST] = fr\n                  implicit val ctx: Ctx = outerCtx\n                  rawTrt.freshenAbove(info.level, rigidify = false)\n                }\n                \n                val paramMems = Nil // * Maybe support trait params? (not sure)\n                \n                S((trt, paramMems, ptp ++ trt.parentTP, p.toLoc))\n                \n              case rawCls: TypedNuCls =>\n                \n                // println(s\"Raw $rawCls where ${rawCls.showBounds}\")\n                \n                val (fr, ptp) = refreshHelper(rawCls, v, if (parTargs.isEmpty) N else S(parTargs)) // infer ty args if not provided\n                val cls = {\n                  implicit val frenshened: MutMap[TV,ST] = fr\n                  implicit val ctx: Ctx = outerCtx\n                  rawCls.freshenAbove(info.level, rigidify = false)\n                }\n                \n                // println(s\"Fresh[${ctx.lvl}] $cls where ${cls.showBounds}\")\n                \n                def checkArgsNum(effectiveParamSize: Int) =\n                  if (parArgs.sizeCompare(effectiveParamSize) =/= 0)\n                    err(msg\"class $parNme expects ${\n                      effectiveParamSize.toString} parameter(s); got ${parArgs.size.toString\n                        }\", Loc(v :: parArgs.unzip._2))\n                \n                val argMembs = {\n                  implicit val genLambdas: GenLambdas = true\n                  cls.auxCtorParams match {\n                    case S(ps) =>\n                      checkArgsNum(ps.size)\n                      ps.lazyZip(parArgs).map {\n                        case (nme -> p_ty, _ -> Fld(FldFlags(mut, spec, get), a)) =>\n                          assert(!mut && !spec && !get, \"TODO\") // TODO check mut, spec, get\n                          val a_ty = typeTerm(a)\n                          constrain(a_ty, p_ty)\n                      }\n                      Nil\n                    case N => cls.params match {\n                        case S(ps) =>\n                          checkArgsNum(ps.size)\n                          ps.lazyZip(parArgs).flatMap {\n                            case (nme -> p, _ -> Fld(FldFlags(mut, spec, get), a)) =>\n                              assert(!mut && !spec && !get, \"TODO\") // TODO check mut, spec, get\n                              val a_ty = typeTerm(a)\n                              p.lb.foreach(constrain(_, a_ty))\n                              constrain(a_ty, p.ub)\n                              val isPublic = cls.members(nme.name).isPublic\n                              val fty = if (p.lb.isDefined)\n                                  // * We don't refine the field type when it's mutable as that could lead to muable updates being rejected\n                                  FieldType(p.lb, p.ub)(provTODO)\n                                else FieldType(p.lb, a_ty)(provTODO)\n                              Option.when(isPublic)(NuParam(nme, fty, isPublic = isPublic)(lvl))\n                          }\n                        case N =>\n                          checkArgsNum(0)\n                          Nil\n                      }\n                  }\n                }\n                println(s\"Class arg members $argMembs\")\n                \n                S((cls, argMembs, ptp ++ cls.parentTP, p.toLoc))\n                \n              case als: TypedNuAls =>\n                // TODO dealias first?\n                err(msg\"Cannot inherit from a type alias\", p.toLoc)\n                N\n              case als: NuParam =>\n                // TODO first-class mixins/classes...\n                err(msg\"Cannot inherit from a parameter\", p.toLoc)\n                N\n              // case als: NuTypeParam =>\n              //   err(msg\"Cannot inherit from a type parameter\", p.toLoc)\n              //   Nil\n              case cls: TypedNuFun =>\n                err(msg\"Cannot inherit from a function\", p.toLoc)\n                N\n                \n              case cls: TypedNuDummy =>\n                N\n                \n            }\n          }()\n      } finally { typingParents = false }\n      \n    }\n    \n    \n    def lookupTags(parents: Ls[ParentSpec], tags: Set[TypeName]): Set[TypeName] = {\n      parents match {\n        case Nil => tags\n        case (p, Var(nm), lti, _, _) :: ps => lti match {\n          case lti: DelayedTypeInfo => lti.kind match {\n            case Trt | Cls | Mod => lookupTags(ps, Set.single(TypeName(nm)) union lti.inheritedTags union tags)\n            case Val | Mxn | Als => lookupTags(ps, tags)\n          }\n          case CompletedTypeInfo(trt: TypedNuTrt) =>\n            lookupTags(ps, Set.single(TypeName(nm)) union trt.inheritedTags union tags)\n          case CompletedTypeInfo(cls: TypedNuCls) =>\n            lookupTags(ps, Set.single(TypeName(nm)) union cls.inheritedTags union tags)\n          case CompletedTypeInfo(_: NuParam | _: TypedNuFun | _: TypedNuAls | _: TypedNuMxn | _: TypedNuDummy) =>\n            lookupTags(ps, tags)\n        }\n      }\n    }\n\n    private var inheritedTagsStartedComputing = false\n    lazy val inheritedTags: Set[TypeName] =\n      if (inheritedTagsStartedComputing) Set.empty // * Deals with malformed inheritances (cycles)\n      else {\n        inheritedTagsStartedComputing = true\n        lookupTags(parentSpecs, Set.empty)\n      }\n    \n    lazy val tparams: TyParams = ctx.nest.nextLevel { implicit ctx =>\n      decl match {\n        case td: NuTypeDef =>\n          td.tparams.map(tp =>\n            (tp._2, freshVar(\n              TypeProvenance(tp._2.toLoc, \"type parameter\",\n                S(tp._2.name),\n                isType = true),\n              N, S(tp._2.name)), tp._1))\n        case fd: NuFunDef =>\n          fd.tparams.map { tn =>\n            (tn, freshVar(\n              TypeProvenance(tn.toLoc, \"method type parameter\",\n                originName = S(tn.name),\n                isType = true),\n              N, S(tn.name)), N)\n          }\n      }\n    }\n    lazy val tparamsSkolems: Ls[Str -> SkolemTag] = tparams.map {\n      case (tp, tv, vi) => (tp.name, SkolemTag(tv)(tv.prov))\n    }\n    \n    lazy val explicitVariances: VarianceStore =\n      MutMap.from(tparams.iterator.map(tp => tp._2 -> tp._3.getOrElse(VarianceInfo.in)))\n    \n    def varianceOf(tv: TV)(implicit ctx: Ctx): VarianceInfo =\n      // TODO make use of inferred vce if result is completed\n      explicitVariances.get(tv).getOrElse(VarianceInfo.in)\n    \n    lazy private implicit val vars: Map[Str, SimpleType] =\n      outerVars ++ tparamsSkolems\n    \n    lazy val typedParams: Opt[Ls[Var -> FieldType]] = ctx.nest.nextLevel { implicit ctx =>\n      decl match {\n        case td: NuTypeDef =>\n          td.params.map(_.fields.flatMap {\n            case (S(nme), Fld(FldFlags(mut, spec, getter), value)) =>\n              assert(!mut && !spec, \"TODO\") // TODO\n              val tpe = value.toTypeRaise\n              val ty = typeType(tpe)\n              nme -> FieldType(N, ty)(provTODO) :: Nil\n            case (N, Fld(FldFlags(mut, spec, getter), nme: Var)) =>\n              assert(!mut && !spec, \"TODO\") // TODO\n              // nme -> FieldType(N, freshVar(ttp(nme), N, S(nme.name)))(provTODO)\n              nme -> FieldType(N, err(msg\"${td.kind.str.capitalize} parameters currently need type annotations\",\n                nme.toLoc))(provTODO) :: Nil\n            case (_, fld) =>\n              err(msg\"Unsupported field specification\", fld.toLoc)\n              Nil\n          })\n        case fd: NuFunDef => N\n      }\n    }\n    \n    lazy val paramSymbols = typedParams.getOrElse(Nil).map(p => p._1.name -> VarSymbol(p._2.ub, p._1))\n    \n    // TODO also import signatures from base classes and mixins!\n    lazy val (typedSignatures, funImplems) : (Ls[(NuFunDef, ST)], Ls[NuFunDef]) = decl match {\n      case td: NuTypeDef => ctx.nest.nextLevel { implicit ctx =>\n        val (signatures, rest) = td.body.entities.partitionMap {\n          case fd @ NuFunDef(_, nme, snme, tparams, R(rhs)) if !fd.isLetOrLetRec =>\n            L((fd, rhs))\n          // TODO also pick up signature off implems with typed params/results\n          case s => R(s)\n        }\n        val implems = rest.collect { case fd @ NuFunDef(N | S(false), nme, snme, tparams, L(rhs)) => fd }\n        \n        ctx ++= paramSymbols\n        \n        signatures.map { case (fd, rhs) =>\n          (fd, ctx.poly { implicit ctx: Ctx =>\n            vars ++ fd.tparams.map { tn =>\n              tn.name -> freshVar(TypeProvenance(tn.toLoc, \"method type parameter\",\n                originName = S(tn.name),\n                isType = true), N, S(tn.name))\n            } |> { implicit vars =>\n              \n              typeType(rhs).withProv(\n                TypeProvenance(Loc(rhs :: fd.nme :: fd.tparams), s\"signature of member `${fd.nme.name}`\")\n              )\n              \n            }\n          })\n        } -> implems\n      }\n      case _: NuFunDef => Nil -> Nil\n    }\n    lazy val typedSignatureMembers: Ls[Str -> TypedNuFun] = {\n      val implemented = funImplems.iterator.map(_.nme.name).toSet\n      typedSignatures.iterator.map { case (fd, ty) =>\n        fd.nme.name -> TypedNuFun(level + 1, fd, ty)(implemented.contains(fd.nme.name))\n      }.toList\n    }\n    \n    lazy val inheritedFields: Set[Var] = decl match {\n      case td: NuTypeDef =>\n        parentSpecs.iterator.flatMap(_._3 match {\n          case dti: DelayedTypeInfo => dti.allFields\n          case CompletedTypeInfo(m: TypedNuTypeDef) => m.allFields\n          case _ => Set.empty}).toSet\n      case _: NuFunDef => Set.empty\n    }\n    lazy val privateParams: Set[Var] = decl match {\n      case td: NuTypeDef =>\n        // td.params.dlof(_.fields)(Nil).iterator.collect {\n        //   case (S(nme), Fld(flags, _)) if !flags.genGetter => nme\n        //   case (N, Fld(flags, nme: Var)) if !flags.genGetter => nme\n        //   // case (N, Fld(flags, _)) => die\n        // }.toSet\n        td.params.dlof(_.fields)(Nil).iterator.flatMap {\n          case (S(nme), Fld(flags, _)) => Option.when(!flags.genGetter)(nme)\n          case (N, Fld(flags, nme: Var)) => Option.when(!flags.genGetter)(nme)\n          case (N, Fld(flags, _)) => die\n        }.toSet\n      case _: NuFunDef => Set.empty\n    }\n    \n    lazy val allFields: Set[Var] = decl match {\n      case td: NuTypeDef =>\n        (td.params.getOrElse(Tup(Nil)).fields.iterator.flatMap(_._1) ++ td.body.entities.iterator.collect {\n          case fd: NuFunDef if !fd.isLetOrLetRec => fd.nme\n        }).toSet ++ inheritedFields ++ tparams.map {\n          case (nme @ TypeName(name), tv, _) =>\n            Var(td.nme.name+\"#\"+name).withLocOf(nme)\n        }\n      case _: NuFunDef => Set.empty\n    }\n    \n    lazy val typedFields: Map[Var, FieldType] = {\n      (typedParams.getOrElse(Nil).toMap\n        // -- privateFields\n        -- inheritedFields /* parameters can be overridden by inherited fields/methods */\n      ) ++ typedSignatures.iterator.map(fd_ty => fd_ty._1.nme -> (\n            if (fd_ty._1.isMut) FieldType(S(fd_ty._2), fd_ty._2)(\n              fd_ty._2.prov) // FIXME prov\n            else fd_ty._2.toUpper(noProv)\n          )) ++\n        typedParents.flatMap(_._3).flatMap {\n          case (k, p: NuParam) => Var(k) -> p.ty :: Nil\n          case _ => Nil\n        }\n    }\n    \n    private lazy val isGeneralized: Bool = decl match {\n      case fd: NuFunDef =>\n        println(s\"Type ${fd.nme.name} polymorphically? ${fd.isGeneralized} && (${ctx.lvl} === 0 || ${\n          fd.signature.nonEmpty} || ${fd.outer.exists(_.kind isnt Mxn)})\")\n        // * We only type polymorphically:\n        // * definitions that can be generalized (ie `fun`s or function-valued `let`s and `val`s); and\n        fd.isGeneralized && (\n              ctx.lvl === 0 // * top-level definitions\n          ||  fd.signature.nonEmpty // * definitions with a provided type signature\n          ||  fd.outer.exists(_.kind isnt Mxn) // * definitions NOT occurring in mixins\n        )\n        // * The reason to not type unannotated mixin methods polymorphically is that\n        // * doing so yields too much extrusion and cycle check failures,\n        // * in the context of inferred precisely-typed open recursion through mixin composition.\n      case _ => die\n    }\n    \n    lazy val mutRecTV: TV = decl match {\n      case fd: NuFunDef =>\n        freshVar(\n          TypeProvenance(decl.toLoc, decl.describe, S(decl.name), decl.isInstanceOf[NuTypeDef]),\n          N,\n          S(decl.name)\n        )(if (isGeneralized) level + 1 else level)\n      case _ => lastWords(s\"Not supposed to use mutRecTV for ${decl.kind}\")\n    }\n    \n    private lazy val thisTV: TV =\n      freshVar(provTODO, N, S(decl.name.decapitalize))(lvl + 1)\n    \n    def refreshHelper(raw: PolyNuDecl, v: Var, parTargs: Opt[Ls[Type]])\n          (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType])\n          : (MutMap[TV, ST], Map[Str, NuParam]) = {\n      val rawName = v.name\n      parTargs foreach { pta => \n        if (raw.tparams.sizeCompare(pta.size) =/= 0)\n          err(msg\"${raw.kind.str} $rawName expects ${\n            raw.tparams.size.toString} type parameter(s); got ${pta.size.toString}\", Loc(v :: pta))\n      }\n      refreshHelper2(raw: PolyNuDecl, v: Var, parTargs.map(_.map(typeType(_))))\n    }\n    \n    def complete()(implicit raise: Raise): TypedNuDecl = result.getOrElse {\n      if (isComputing) {\n        err(msg\"Unhandled cyclic definition\", decl.toLoc)\n        TypedNuDummy(decl)\n      }\n      else trace(s\"Completing ${decl.showDbg}\") {\n        println(s\"Type params ${tparams.mkString(\" \")}\")\n        println(s\"Params ${typedParams.mkString(\" \")}\")\n        \n        val res = try {\n          isComputing = true\n          decl match {\n            case fd: NuFunDef =>\n              def checkNoTyParams() =\n                if (fd.tparams.nonEmpty)\n                  err(msg\"Type parameters are not yet supported in this position\",\n                    fd.tparams.head.toLoc)\n\n              val res_ty = fd.rhs match {\n                case R(PolyType(tps, ty)) =>\n                  checkNoTyParams()\n                  val body_ty = ctx.poly { implicit ctx: Ctx =>\n                    typeType(ty)(ctx, raise,\n                      vars = vars ++ tps.map {\n                          case L(tn) => tn.name -> freshVar(provTODO, N)(1)\n                          case _ => die\n                        }.toMap)\n                  }\n                  TypedNuFun(ctx.lvl, fd, PolymorphicType(ctx.lvl, body_ty))(isImplemented = false)\n                case R(_) => die\n                case L(body) =>\n                  if (fd.isLetRec.isDefined) checkNoTyParams()\n                  implicit val gl: GenLambdas =\n                    // * Don't generalize lambdas if we're already in generalization mode;\n                    // * unless the thing is just a simple let binding with functions,\n                    // * as in `let r = if true then id else x => x`\n                    !isGeneralized && fd.isLetRec.isDefined && !fd.genField\n                  val outer_ctx = ctx\n                  val body_ty = if (isGeneralized) {\n                    // * Note:\n                    // * Can't use `ctx.poly` instead of `ctx.nextLevel` here because all the methods\n                    // * in the current typing unit are quantified together.\n                    // * So instead of inserting an individual `forall` in the type of each method,\n                    // * we consider the `forall` to be implicit in the definition of TypedNuFun,\n                    // * and that forall is eschewed while typing mutually-recursive methods\n                    // * in the same typing unit, which will see the method's type through its mutRecTV.\n                    // * This avoids cyclic-looking constraints due to the polymorphic recursion limitation.\n                    // * Subnote: in the future, we should type each mutual-recursion-component independently\n                    // *  and polymorphically wrt to external uses of them.\n                    // *  Currently they are typed in order.\n                    ctx.nextLevel { implicit ctx: Ctx =>\n                      assert(fd.tparams.sizeCompare(tparamsSkolems) === 0, (fd.tparams, tparamsSkolems))\n                      vars ++ tparamsSkolems |> { implicit vars =>\n                        val ty = typeTerm(body)\n                        if (noApproximateOverload) {\n                          val ambiguous = ty.getVars.unsorted.flatMap(_.tsc.keys.flatMap(_.tvs))\n                            .groupBy(_._2)\n                            .filter { case (v,pvs) => pvs.sizeIs > 1 }\n                          if (ambiguous.nonEmpty) raise(ErrorReport(\n                            msg\"ambiguous\" -> N ::\n                              ambiguous.map { case (v,_) =>\n                                msg\"cannot determine satisfiability of type ${v.expPos}\" -> v.prov.loco\n                              }.toList\n                              , true))\n                        }\n                        ty\n                      }\n                    }\n                  } else {\n                    if (fd.isMut) {\n                      constrain(typeTerm(body), mutRecTV)\n                      mutRecTV\n                    }\n                    else typeTerm(body)\n                  }\n                  val tp = TypeProvenance(fd.toLoc, s\"definition of ${fd.isLetRec match {\n                      case S(_) => if (fd.genField) \"value\" else \"let binding\"\n                      case N => \"method\"\n                    }} ${fd.nme.name}\")\n                  TypedNuFun(ctx.lvl, fd, body_ty.withProv(tp))(isImplemented = true)\n              }\n              ctx.nextLevel { implicit ctx: Ctx => constrain(res_ty.bodyType, mutRecTV) }\n\n              // Check annotations\n              fd.annotations.foreach(ann => {\n                implicit val gl: GenLambdas = false;\n                val annType = typeTerm(ann)\n                constrain(annType, AnnType)\n              })\n\n              res_ty\n              \n              \n            case td: NuTypeDef =>\n              \n              /** Check no `this` access in ctor statements or val rhs and reject unqualified accesses to virtual members.. */\n              def qualificationCheck(members: Ls[NuMember], stmts: Ls[Statement], base: Ls[NuMember], sigs: Ls[NuMember]): Unit = {\n                val cache = mutable.HashMap[Str, Opt[Var]]()\n                val sigMap = sigs.map(m => m.name -> m).toMap\n                val allMembers = sigMap ++ (base.iterator ++ members).map(m => m.name -> m).toMap\n\n                def isVirtual(nf: TypedNuFun) =\n                  nf.fd.isVirtual || (sigMap.get(nf.name) match {\n                    case S(sig: TypedNuFun) => sig.fd.virtualLoc.nonEmpty // The signature is virtual by itself, so we need to check the virtual keyword\n                    case _ => false\n                  })\n\n                // Return S(v) when there is an invalid access to the v.\n                def checkThisInCtor(refs: RefMap, name: Opt[Str], stack: Ls[Str])(expection: Bool): Opt[Var] = {\n                  def run: Opt[Var] = {\n                    refs.thisRef.orElse(\n                      refs.refs.foldLeft[Opt[Var]](N)((res, p) => res.orElse(allMembers.get(p._1.name) match {\n                        case S(nf: TypedNuFun) if name.fold(true)(name => name =/= p._1.name) && !stack.contains(p._1.name) => // Avoid cycle checking\n                          p._2 match {\n                            case q @ S(_) if !expection || isVirtual(nf) => q\n                            case _ => checkThisInCtor(nf.getFunRefs, S(p._1.name), p._1.name :: stack)(false)\n                          }\n                        case _ => N // Refer to outer \n                      }))\n                    )\n                  }\n\n                  name.fold(run)(name => cache.getOrElseUpdate(name, run))\n                }\n\n                def checkUnqualifiedVirtual(refs: RefMap, parentLoc: Opt[Loc]) =\n                  refs.refs.foreach(p => if (p._2.isEmpty) allMembers.get(p._1.name) match { // unqualified access\n                    case S(nf: TypedNuFun) if isVirtual(nf) =>\n                      err(msg\"Unqualified access to virtual member ${p._1.name}\" -> parentLoc ::\n                        msg\"Declared here:\" -> nf.fd.toLoc\n                      :: Nil)\n                    case _ => ()\n                  })\n\n                // If the second error message location is covered by the first one,\n                // we show the first error message with more precise location\n                def mergeErrMsg(msg1: Message -> Opt[Loc], msg2: Message -> Opt[Loc]) =\n                  (msg1._2, msg2._2) match {\n                    case (S(loc1), l @ S(loc2)) if loc1 covers loc2 => msg1._1 -> l :: Nil\n                    case _ => msg1 :: msg2 :: Nil\n                  }\n\n                members.foreach {\n                  case tf @ TypedNuFun(_, fd, _) =>\n                    val refs = tf.getFunRefs\n                    if (fd.isLetRec.isDefined) checkThisInCtor(refs, S(tf.name), tf.name :: Nil)(true) match {\n                      case S(v) => // not a function && access `this` in the ctor\n                        err(mergeErrMsg(msg\"Cannot access `this` while initializing field ${tf.name}\" -> fd.toLoc,\n                          msg\"The access to `this` is here\" -> v.toLoc))\n                      case N => ()\n                    }\n                    checkUnqualifiedVirtual(refs, fd.toLoc)\n                  case _ => ()\n                }\n                stmts.foreach{\n                  case Asc(Var(\"this\"), _) => ()\n                  case s =>\n                    val refs = getRefs(s)\n                    checkThisInCtor(refs, N, Nil)(false) match {\n                      case S(v) =>\n                        err(mergeErrMsg(msg\"Cannot access `this` during object initialization\" -> s.toLoc,\n                          msg\"The access to `this` is here\" -> v.toLoc))\n                      case N => ()\n                    }\n                    checkUnqualifiedVirtual(refs, s.toLoc)\n                }\n              }\n              \n              /** Checks everything is implemented and there are no implementation duplicates. */\n              def implemCheck(implementedMembers: Ls[NuMember], toImplement: Ls[NuMember]): Unit = {\n                \n                val implemsMap = MutMap.empty[Str, NuMember]\n                implementedMembers.foreach { m =>\n                  implemsMap.updateWith(m.name) {\n                    case S(_) =>\n                      err(msg\"Duplicated `${m.name}` member definition in `${td.name}`\", m.toLoc)\n                      N\n                    case N => S(m)\n                  }\n                }\n                if (!td.isDecl && td.kind =/= Trt && !td.isAbstract) {\n                  toImplement.foreach { m =>\n                    def mkErr(postfix: Ls[Message -> Opt[Loc]]) = err(\n                      msg\"Member `${m.name}` is declared (or its declaration is inherited) but is not implemented in `${\n                          td.nme.name}`\" -> td.nme.toLoc ::\n                        msg\"Declared here:\" -> m.toLoc ::\n                        postfix)\n                    implemsMap.get(m.name) match {\n                      case S(impl) =>\n                        if (impl.isPrivate) mkErr(\n                          msg\"Note: ${impl.kind.str} member `${m.name}` is private and cannot be used as a valid implementation\" -> impl.toLoc ::\n                          Nil)\n                      case N =>\n                        mkErr(Nil)\n                    }\n                  }\n                }\n                \n              }\n              \n              /** Checks overriding members against their parent types. */\n              def overrideCheck(newMembers: Ls[NuMember], signatures: Ls[NuMember], clsSigns: Ls[NuMember]): Unit =\n                  ctx.nextLevel { implicit ctx: Ctx => // * Q: why exactly do we need `ctx.nextLevel`?\n                \n                val sigMap = MutMap.empty[Str, NuMember]\n                signatures.foreach { m =>\n                  sigMap.updateWith(m.name) {\n                    case S(_) => die\n                    case N => S(m)\n                  }\n                }\n                \n                newMembers.foreach { m =>\n                  println(s\"Checking overriding for ${m} against ${sigMap.get(m.name)}...\")\n                  (m, sigMap.get(m.name)) match {\n                    case (_, N) =>\n                    case (m: TypedNuTermDef, S(sig: TypedNuTermDef)) => sig match {\n                      // * If the implementation and the declaration are in the same class,\n                      // * it does not require to be virtual.\n                      case _ if sig.isPrivate => () // * Private members are not actually inherited\n                      case td: TypedNuFun if (!td.fd.isVirtual && !clsSigns.contains(sig)) =>\n                        err(msg\"${m.kind.str.capitalize} member '${m.name\n                            }' is not virtual and cannot be overridden\" -> m.toLoc ::\n                          msg\"Originally declared here:\" -> sig.toLoc ::\n                          Nil)\n                      case p: NuParam if (!p.isVirtual && !clsSigns.contains(p)) =>\n                        err(msg\"Inherited parameter named '${m.name\n                            }' is not virtual and cannot be overridden\" -> m.toLoc ::\n                          msg\"Originally declared here:\" -> sig.toLoc ::\n                          Nil)\n                      case _ =>\n                        m match {\n                          case fun: TypedNuFun if (fun.fd.isLetOrLetRec) =>\n                            err(msg\"Cannot implement ${m.kind.str} member '${m.name\n                                }' with a let binding\" -> m.toLoc ::\n                              msg\"Originally declared here:\" -> sig.toLoc ::\n                              Nil)\n                          case _ =>\n                        }\n                        val mSign = m.typeSignature\n                        implicit val prov: TP = mSign.prov\n                        constrain(mSign, sig.typeSignature)\n                    }\n                    case (_, S(that)) =>\n                      err(msg\"${m.kind.str.capitalize} member '${m.name}' cannot override ${\n                          that.kind.str} member of the same name declared in parent\" -> td.toLoc ::\n                        msg\"Originally declared here:\" -> that.toLoc ::\n                        Nil)\n                  }\n                }\n                \n              }\n              \n              \n              // intersection of members\n              def membersInter(l: Ls[NuMember], r: Ls[NuMember]): Ls[NuMember] = {\n                def merge(ltm: NuMember, rtm: Option[NuMember]) = {\n                  rtm.foreach(rtm => assert(rtm.level === ltm.level, (ltm.level, rtm.level)))\n                  (ltm, rtm) match {\n                    case (a: TypedNuFun, S(b: TypedNuFun)) =>\n                      assert(!(a.isImplemented && b.isImplemented))\n                      val fd = NuFunDef((a.fd.isLetRec, b.fd.isLetRec) match {\n                        case (S(a), S(b)) => S(a || b)\n                        case _ => N // if one is fun, then it will be fun\n                      }, a.fd.nme, N/*no sym name?*/, a.fd.tparams, a.fd.rhs)(\n                        a.fd.declareLoc, a.fd.virtualLoc, a.fd.mutLoc,\n                        N, a.fd.outer orElse b.fd.outer, a.fd.genField, a.fd.annotations)\n                      S(TypedNuFun(a.level, fd, a.bodyType & b.bodyType)(a.isImplemented || b.isImplemented))\n                    case (a: NuParam, S(b: NuParam)) => \n                      if (!a.isPublic) S(b) else if (!b.isPublic) S(a)\n                      else S(NuParam(a.nme, a.ty && b.ty, isPublic = true)(a.level))\n                    case (a: NuParam, S(b: TypedNuFun)) =>\n                      S(TypedNuFun(a.level, b.fd, a.ty.ub & b.bodyType)(a.isImplemented || b.isImplemented))\n                    case (a: TypedNuFun, S(b: NuParam)) =>\n                      S(TypedNuFun(a.level, a.fd, b.ty.ub & a.bodyType)(a.isImplemented || b.isImplemented))\n                    case (a, N) => S(a)\n                    case (a, S(b)) =>\n                      err(msg\"Intersection of ${a.kind.str} member and ${b.kind.str} members currently unsupported\" -> td.toLoc\n                        :: msg\"The ${a.kind.str} member is defined here:\" -> a.toLoc\n                        :: msg\"The ${b.kind.str} member is defined here:\" -> b.toLoc\n                        :: Nil)\n                      N\n                  }\n                }\n                l.foldLeft(r.map(d => d.name -> d).toMap) { case (acc, ltm) => \n                  acc.updatedWith(ltm.name)(merge(ltm, _))\n                }.values.toList\n              }\n              \n              \n              if (((td.kind is Mod) || (td.kind is Mxn)) && td.ctor.isDefined)\n                err(msg\"Explicit ${td.kind.str} constructors are not supported\",\n                  td.ctor.fold[Opt[Loc]](N)(c => c.toLoc))\n              \n              // * To type signatures correctly, we need to deal with unbound type variables 'X,\n              // * which should be treated as unknowns (extruded skolems).\n              // * Allowing such type variables is important for the typing of signatures such as\n              // *  `: Foo | Bar` where `Foo` and `Bar` take type parameters,\n              // *  as these will be (in the future) desugared to `: Foo['A0] | Bar['A1]`\n              def typeTypeSignature(sign: Type)(implicit ctx: Ctx): ST = {\n                val outer = ctx\n                val ty = ctx.nest.nextLevel { implicit ctx =>\n                  // * Type the signature in a higher level, so as to contain unbound type vars\n                  val ty = typeType(td.sig.getOrElse(Top))\n                  // * Make these type vars skolems\n                  implicit val freshened: MutMap[TV, ST] = MutMap.empty\n                  ty.freshenAbove(outer.lvl, rigidify = true)\n                }\n                // * Create a lower-levl type variable to extrude the type through it,\n                // * which will result in making the unbound type vars extruded skolems (i.e., unknowns)\n                val res = freshVar(provTODO, N, N)(ctx.lvl)\n                // * Subtle note: it is sufficient and important to add the type as a LB of the TV\n                // *  instead of unifying them because:\n                // *  1. currently we expand type defs the same no matter of the position polarity\n                // *      so `class S: T` is always expanded as `#S & 'X` where `'X :> T`\n                // *  2. we don't want to have to check every single subtype of S against T,\n                // *      as this check will already have been performed generally when typing class T,\n                // *      but this would happen if we instead expanded into a type equivalent to #S & T...\n                constrain(ty, res)\n                // * Retrieve the extruded lower bound.\n                // * Note that there should be only one, and in particular it should not be recursive,\n                // * since the variable is never shared outside this scope.\n                res.lowerBounds match {\n                  // case lb :: Nil => TypeBounds.mk(TopType, lb)\n                  case lb :: Nil => lb\n                  case _ => die\n                }\n              }\n\n              // Check annotations\n              td.annotations.foreach { ann =>\n                implicit val gl: GenLambdas = false\n                val annType = typeTerm(ann)\n                constrain(annType, AnnType)\n              }\n              \n              td.kind match {\n                \n                case Trt =>\n                  td.params match {\n                    case S(ps) => err(msg\"trait parameters are not yet supported\", ps.toLoc)\n                    case _ =>\n                  }\n                  \n                  ctx.nest.nextLevel { implicit ctx =>\n                    ctx ++= paramSymbols\n                    ctx ++= typedSignatures.map(nt => nt._1.name -> VarSymbol(nt._2, nt._1.nme))\n                    ctx += \"this\" -> VarSymbol(thisTV, Var(\"this\"))\n                    \n                    def inherit(parents: Ls[TypedParentSpec], tags: ST, members: Ls[NuMember],\n                            tparamMembs: Map[Str, NuMember], sig_ty: ST)\n                          : (ST, Ls[NuMember], Map[Str, NuMember], ST) =\n                        parents match {\n                      case (trt: TypedNuTrt, argMembs, tpms, loc) :: ps =>\n                        assert(argMembs.isEmpty, argMembs)\n                        inherit(ps,\n                          tags & trt.sign,\n                          membersInter(members, trt.members.values.toList),\n                          tparamMembs ++ tpms,   // with type members of parent class\n                          sig_ty & trt.sign,\n                        )\n                      case (_, _, _, loc) :: ps => \n                        err(msg\"A trait can only inherit from other traits\", loc)\n                        inherit(ps, tags, members, tparamMembs, sig_ty)\n                      case Nil => (tags, members, tparamMembs, sig_ty)\n                    }\n                    val (tags, trtMembers, tparamMembs, sig_ty) =\n                      inherit(typedParents, trtNameToNomTag(td)(noProv, ctx), Nil, Map.empty,\n                        td.sig.fold(TopType: ST)(typeTypeSignature))\n                    \n                    td.body.entities.foreach {\n                      case fd @ NuFunDef(_, _, _, _, L(_)) =>\n                        err(msg\"Method implementations in traits are not yet supported\", fd.toLoc)\n                      case _ =>\n                    }\n                    \n                    val ttu = typeTypingUnit(td.body, S(td))\n                    \n                    val allMembers = (\n                      trtMembers.iterator.map(d => d.name -> d)\n                      ++ ttu.implementedMembers.map(d => d.name -> d)\n                      ++ typedSignatureMembers\n                    ).toMap\n                    \n                    // check trait overriding\n                    overrideCheck(typedSignatureMembers.map(_._2), trtMembers, Nil)\n                    \n                    TypedNuTrt(outerCtx.lvl, td,\n                      tparams,\n                      allMembers,\n                      TopType, // thisType (same as for Cls)\n                      sig_ty,\n                      inheritedTags,\n                      tparamMembs\n                    )\n                  }\n                  \n                case Als =>\n                  \n                  if (td.params.getOrElse(Tup(Nil)).fields.nonEmpty)\n                    err(msg\"Type alias definitions cannot have value parameters\" -> td.params.getOrElse(Tup(Nil)).toLoc :: Nil)\n                  if (td.parents.nonEmpty)\n                    err(msg\"Type alias definitions cannot extend parents\" -> Loc(td.parents) :: Nil)\n                  \n                  val body_ty = td.sig match {\n                    case S(sig) =>\n                      ctx.nextLevel { implicit ctx: Ctx => typeType(sig) }\n                    case N =>\n                      err(msg\"Type alias definition requires a right-hand side\", td.toLoc)\n                  }\n                  \n                  TypedNuAls(outerCtx.lvl, td, tparams, body_ty)\n                  \n                case Cls | Mod =>\n                  \n                  ctx.nest.nextLevel { implicit ctx =>\n                    \n                    if ((td.kind is Mod) && typedParams.nonEmpty)\n                      // * Can we do better? (Memoization semantics?)\n                      err(msg\"${td.kind.str.capitalize} parameters are not supported\",\n                        typedParams.fold(td.nme.toLoc)(tp => Loc(tp.iterator.map(_._1))))\n                    \n                    if (!td.isAbstract && !td.isDecl) td.sig match {\n                      case S(sig) => warn(\n                        msg\"Self-type annotations have no effects on non-abstract ${td.kind.str} definitions\" -> sig.toLoc\n                        :: msg\"Did you mean to use `extends` and inherit from a parent class?\" -> N\n                        :: Nil)\n                      case N =>\n                    }\n                    \n                    ctx ++= paramSymbols\n                    ctx ++= typedSignatures.map(nt => nt._1.name -> VarSymbol(nt._2, nt._1.nme))\n                    \n                    val sig_ty = td.sig.fold(TopType: ST)(typeTypeSignature)\n                    \n                    implicit val prov: TP =\n                      TypeProvenance(decl.toLoc, decl.describe)\n                    \n                    val finalType = thisTV\n                    \n                    val tparamMems = tparams.map { case (tp, tv, vi) => // TODO use vi\n                      val fldNme = td.nme.name + \"#\" + tp.name\n                      val skol = SkolemTag(tv)(tv.prov)\n                      NuParam(TypeName(fldNme).withLocOf(tp), FieldType(S(skol), skol)(tv.prov), isPublic = true)(lvl)\n                    }\n                    val tparamFields = tparamMems.map(p => p.nme.toVar -> p.ty)\n                    assert(!typedParams.exists(_.keys.exists(tparamFields.keys.toSet)), ???)\n                    \n                    case class Pack(\n                      superType: ST,\n                      mxnMembers: Ls[NuMember], \n                      baseClsNme: Opt[Str], \n                      baseClsMembers: Ls[NuMember], \n                      traitMembers: Ls[NuMember],\n                      tparamMembers: Map[Str, NuMember],\n                      selfSig: ST,\n                    )\n                    \n                    def inherit(parents: Ls[TypedParentSpec], pack: Pack): Pack = parents match {\n                      case (p, argMembs, tpms, loc) :: ps => println(s\"=> Inheriting from $p\"); p match {\n                        \n                        case mxn: TypedNuMxn =>\n                          \n                          assert(finalType.level === lvl)\n                          assert(mxn.superTy.level === lvl)\n                          assert(mxn.thisTy.level === lvl)\n                          \n                          constrain(pack.superType, mxn.superTy)\n                          constrain(finalType, mxn.thisTy)\n                          \n                          assert(tpms.isEmpty) // Mixins do not introduce virtual members for type params\n                          \n                          val newMembs = argMembs ++ mxn.members.valuesIterator.filterNot(_.isValueParam)\n                          val newSuperType = WithType(\n                              pack.superType,\n                              RecordType(\n                                newMembs.collect {\n                                  case m: NuParam => m.nme.toVar -> m.ty\n                                  case m: TypedNuFun =>\n                                    // val ty = m.typeSignature\n                                    // * ^ Note: this also works and is more precise (some types made more specific),\n                                    // *    but it causes duplication of recursive type structures\n                                    // *    in typical SuperOOP mixin compositions, so it's better to be less precise\n                                    // *    but simpler/more efficient/more concise here.\n                                    val ty = m.bodyType\n                                    m.fd.nme -> ty.toUpper(provTODO)\n                                }\n                              )(provTODO)\n                            )(provTODO)\n                          \n                          inherit(ps, pack.copy(\n                            superType = newSuperType,\n                            mxnMembers = newMembs ++ pack.mxnMembers\n                          ))\n                        \n                        case trt: TypedNuTrt =>\n                          \n                          assert(argMembs.isEmpty, argMembs)\n                          \n                          inherit(ps, pack.copy(\n                            traitMembers = membersInter(pack.traitMembers, trt.members.valuesIterator.filterNot(_.isValueParam).toList),\n                            tparamMembers = pack.tparamMembers ++ tpms,\n                            selfSig = pack.selfSig & trt.sign\n                          ))\n                        \n                        case cls: TypedNuCls =>\n                          val parNme = cls.nme.name\n                          \n                          pack.baseClsNme.foreach { cls =>\n                            err(msg\"Cannot inherit from more than one base class: ${\n                              cls} and ${parNme}\", loc)\n                          }\n                          \n                          val (baseParamMems, otherBaseMems) =\n                            // cls.members.toList.partition(_._2.isValueParam)\n                            cls.members.valuesIterator.toList.partition(_.isValueParam)\n                          \n                          println(s\"argMembs $argMembs\")\n                          \n                          println(s\"selfSig ${cls.sign}\")\n                          \n                          inherit(ps, pack.copy(\n                            baseClsNme = S(parNme), \n                            // baseClsMembers = argMembs ++ cls.members.valuesIterator.filterNot(_.isValueParam), \n                            // baseClsMembers = argMembs.filterNot(_.isPrivate) ++ cls.members.valuesIterator.filterNot(_.isValueParam), \n                            // baseClsMembers = cls.members.valuesIterator.filter(_.isValueParam) ++ argMembs ++ cls.members.valuesIterator.filterNot(_.isValueParam), \n                            // baseClsMembers = baseParamMems ::: argMembs ::: otherBaseMems, \n                            baseClsMembers = argMembs ++ cls.members.valuesIterator,\n                            tparamMembers = pack.tparamMembers ++ tpms,\n                            selfSig = pack.selfSig & cls.sign\n                          ))\n                          \n                        case als: TypedNuAls => // Should be rejected in `typedParents`\n                          inherit(ps, pack)\n                        \n                      }\n                      case Nil =>\n                        println(s\"Done inheriting: $pack\")\n                        \n                        val thisType = WithType(pack.superType,\n                            RecordType(typedParams.getOrElse(Nil))(ttp(td.params.getOrElse(Tup(Nil)), isType = true))\n                          )(provTODO) &\n                            clsNameToNomTag(td)(provTODO, ctx) &\n                            RecordType(tparamFields)(TypeProvenance(Loc(td.tparams.map(_._2)), \"type parameters\", isType = true))\n                        \n                        trace(s\"${lvl}. Finalizing inheritance with $thisType <: $finalType\") {\n                          assert(finalType.level === lvl)\n                          constrain(thisType & sig_ty, finalType)\n                          \n                        }()\n                        \n                        if (!td.isAbstract) trace(s\"Checking self signature...\") {\n                          constrain(thisType, pack.selfSig)\n                        }()\n                        \n                        // println(s\"${lvl}. Finalized inheritance with $superType ~> $thisType\")\n                        pack.copy(superType = thisType, selfSig = pack.selfSig & sig_ty)\n                    }\n                    \n                    // * We start from an empty super type.\n                    val baseType =\n                      RecordType(Nil)(TypeProvenance(Loc(td.parents).map(_.left), \"Object\"))\n                    \n                    val paramMems = typedParams.getOrElse(Nil).map(f =>\n                      NuParam(f._1, f._2, isPublic = !privateParams.contains(f._1))(lvl))\n                    \n                    val Pack(thisType, mxnMembers, _, baseClsMembers, traitMembers, tparamMembers, selfSig) =\n                      inherit(typedParents, Pack(baseType, tparamMems ++ paramMems, N, Nil, Nil, Map.empty, sig_ty))\n                    \n                    // println(s\"Final self-type: ${selfSig}\")\n                    \n                    ctx += \"this\" -> VarSymbol(thisTV, Var(\"this\"))\n                    ctx += \"super\" -> VarSymbol(thisType, Var(\"super\"))\n                    val ttu = typeTypingUnit(td.body, S(td))\n                    \n                    // * `baseClsImplemMembers` actually also includes parameter members and their arg-based refinements\n                    val (baseClsImplemMembers, baseClsIfaceMembers) =\n                      baseClsMembers.partition(_.isImplemented)\n                    \n                    println(s\"baseClsImplemMembers ${baseClsImplemMembers}\")\n                    \n                    val newImplems = ttu.implementedMembers\n                    \n                    val clsSigns = typedSignatureMembers.map(_._2)\n                    \n                    trace(s\"Checking `this` accesses...\") {\n                      val toCheckImplems = newImplems.filter(_.isImplemented)\n                      qualificationCheck(toCheckImplems, td.body.entities.filter {\n                        case _: NuDecl => false\n                        case _ => true\n                      } ++ td.ctor.fold[Ls[Statement]](Nil)(s => s.body.stmts), baseClsMembers, clsSigns)\n                    }()\n                    \n                    // * Those member implementations we inherit from the base class that are not overridden\n                    val implemsInheritedFromBaseCls = {\n                      val possiblyOverridingNames = (newImplems.iterator ++ mxnMembers).map(_.name).toSet\n                      baseClsImplemMembers.iterator.distinctBy(_.name)\n                        .filterNot(possiblyOverridingNames contains _.name)\n                        .toList\n                    }\n                    // * ... must type check against the trait signatures\n                    trace(s\"Checking base class implementations against inherited signatures...\") {\n                      overrideCheck(implemsInheritedFromBaseCls, traitMembers, Nil)\n                    }()\n                    \n                    // * The following are type signatures all implementations must satisfy\n                    // * (but we already know the base class implems satisfy the baseClsMembers signatures)\n                    val ifaceMembers = membersInter(baseClsMembers, traitMembers)\n                    \n                    // * We now check current and non-overridden mixin implementations against \n                    // * the signatures from the base class and traits\n                    val toCheck =\n                      (newImplems.iterator ++ mxnMembers).distinctBy(_.name).toList\n                    \n                    trace(s\"Checking new implementations against inherited signatures...\") {\n                      overrideCheck(toCheck,\n                        (clsSigns.iterator ++ ifaceMembers).distinctBy(_.name).toList, clsSigns)\n                    }()\n                    \n                    val impltdMems = (\n                      newImplems // local members override mixin members:\n                      ++ mxnMembers // local and mixin members override parent members:\n                      ++ baseClsImplemMembers\n                    ).distinctBy(_.name)\n                    \n                    trace(s\"Checking new signatures against inherited signatures...\") {\n                      overrideCheck(clsSigns, ifaceMembers, clsSigns)\n                    }()\n                    \n                    trace(s\"Checking signature implementations...\") {\n                      implemCheck(impltdMems,\n                        (clsSigns.iterator ++ ifaceMembers.iterator)\n                        .distinctBy(_.name).filterNot(_.isImplemented).toList)\n                    }()\n                    \n                    val allMembers =\n                      (ifaceMembers ++ impltdMems).map(d => d.name -> d).toMap ++ typedSignatureMembers\n                    \n                    println(s\"allMembers $allMembers\")\n                    \n                    val auxCtorParams = td.ctor match {\n                      case S(ctor @ Constructor(ps, bod)) => outerCtx.nest.nextLevel { implicit ctx =>\n                        def getterError(loco: Opt[Loc]) =\n                          err(msg\"Cannot use `val` in constructor parameters\", loco)\n                        val res = ps.fields.map {\n                          case (S(nme), Fld(FldFlags(mut, spec, getter), value)) =>\n                            assert(!mut && !spec, \"TODO\") // TODO\n                            if (getter)\n                              // TODO we could support this to some extent\n                              getterError(nme.toLoc)\n                            value.toType match {\n                              case R(tpe) =>\n                                val ty = typeType(tpe)\n                                nme -> ty\n                              case _ => ???\n                            }\n                          case (N, Fld(FldFlags(mut, spec, getter), nme: Var)) =>\n                            assert(!mut && !spec, \"TODO\") // TODO\n                            if (getter)\n                              getterError(nme.toLoc)\n                            nme -> freshVar(ttp(nme), N, S(nme.name))\n                          case (N, Fld(_, rhs)) =>\n                            Var(\"<error>\") -> err(msg\"Unsupported constructor parameter shape\", rhs.toLoc)\n                        }\n                        res.foreach { case (nme, ty) => ctx += nme.name -> VarSymbol(ty, nme) }\n                        implicit val gl: GenLambdas = false\n                        implicit val prov: TP =\n                          TypeProvenance(ctor.toLoc, \"auxiliary class constructor\")\n                        val bodStmts = bod match {\n                          case Blk(sts) => sts\n                          case _ => bod :: Nil\n                        }\n                        // * TODO later: for each `typedParams`, first add sthg like `ctx += lhs.name -> UndefinedParam(...)`\n                        val classParamsMap = MutMap.from(typedParams.getOrElse(Nil).mapValues(some))\n                        bodStmts.foreach {\n                          case Eqn(lhs, rhs) =>\n                            classParamsMap.updateWith(lhs) {\n                              case S(S(p)) =>\n                                val rhs_ty = typeTerm(rhs)\n                                constrain(rhs_ty, p.ub)\n                                ctx += lhs.name -> VarSymbol(rhs_ty, lhs)\n                                S(N)\n                              case S(N) =>\n                                err(msg\"Class parameter '${lhs.name}' was already set\", lhs.toLoc)\n                                N\n                              case N =>\n                                err(msg\"Unknown class parameter '${lhs.name}'\", lhs.toLoc)\n                                N\n                            }\n                          case stmt: DesugaredStatement =>\n                            typeStatement(stmt, allowPure = false)\n                          case _ => die\n                        }\n                        S(res)\n                      }\n                      case N => N\n                    }\n                    \n                    // * After a class is type checked, we need to \"solidify\" the inferred types of its unannotated mutable fields,\n                    // * otherwise they would be treated as polymorphic, which would be wrong.\n                    allMembers.foreachEntry {\n                      case (nme, v: TypedNuFun) if v.fd.isMut =>\n                        // * A bit hacky but should work:\n                        v.bodyType.unwrapProvs match {\n                          case _ if v.fd.rhs.isRight || v.fd.signature.nonEmpty =>\n                            // * If the type was annotated, we don't need to do anything.\n                          case tv: TV if tv.assignedTo.isEmpty => // * Could this `tv` ever be assigned?\n                            val res_ty = tv.lowerBounds.reduceOption(_ | _)\n                              .getOrElse(err(msg\"Could not infer a type for unused mutable field $nme\", v.toLoc))\n                            println(s\"Setting type of $nme based on inferred lower bounds: $tv := $res_ty\")\n                            tv.assignedTo = S(res_ty)\n                          case ty => lastWords(ty.toString)\n                        }\n                      case (nme, m) =>\n                    }\n                    \n                    TypedNuCls(outerCtx.lvl, td,\n                      tparams,\n                      typedParams,\n                      auxCtorParams.orElse(Option.when(\n                        typedParams.isEmpty && (td.kind is Cls) && !td.isAbstract)(Nil)),\n                      allMembers,\n                      TopType,\n                      if (td.isAbstract) selfSig else sig_ty,\n                      inheritedTags,\n                      tparamMembers\n                    ).tap(_.variances) // * Force variance computation\n                  }\n                  \n                case Mxn =>\n                  if (td.parents.nonEmpty)\n                    err(msg\"mixin definitions cannot yet extend parents\" -> Loc(td.parents) :: Nil)\n                  val outer = ctx\n                  ctx.nest.nextLevel { implicit ctx =>\n                    ctx ++= paramSymbols\n                    ctx ++= typedSignatures.map(nt => nt._1.name -> VarSymbol(nt._2, nt._1.nme))\n                    val paramMems = typedParams.map(_.map(f =>\n                      f._1.name -> NuParam(f._1, f._2, !privateParams.contains(f._1))(lvl))).getOrElse(Nil).toMap\n                    val thisTV = freshVar(provTODO, N, S(\"this\"))\n                    val superTV = freshVar(provTODO, N, S(\"super\"))\n                    ctx += \"this\" -> VarSymbol(thisTV, Var(\"this\"))\n                    ctx += \"super\" -> VarSymbol(superTV, Var(\"super\"))\n                    val ttu = typeTypingUnit(td.body, S(td))\n                    val impltdMems = ttu.implementedMembers\n                    val signs = typedSignatureMembers.map(_._2)\n                    overrideCheck(impltdMems, signs, signs)\n                    implemCheck(impltdMems, signs)\n                    val mems = paramMems ++ impltdMems.map(m => m.name -> m).toMap ++ typedSignatureMembers\n                    TypedNuMxn(outer.lvl, td, thisTV, superTV, tparams, typedParams.getOrElse(Nil), mems)\n                  }\n              }\n              \n          }\n          \n        } finally { isComputing = false }\n        \n        result = S(res)\n        res\n        \n      }(r => s\"Completed ${r} where ${r.showBounds}\")\n    }\n    def typeSignature(usesNew: Bool, loco: Opt[Loc])(implicit raise: Raise): ST =\n      decl match {\n        case _: NuFunDef =>\n          if (isComputing) {\n            println(s\"Already computing! Using TV: $mutRecTV\")\n            mutRecTV // TODO make sure this is never misused (ie not accessed from difft scope/level)\n          } else complete() match {\n            case TypedNuFun(_, fd, ty) =>\n              ty\n            case _ => die\n          }\n        case td: NuTypeDef =>\n          // * We want to avoid forcing completion of types needlessly\n          // * OTOH we need the type to be completed to use its aux ctor (whose param types are optional)\n          // * TODO: avoid forcing when the aux ctor has type-annotated params\n          if (td.ctor.isDefined) complete() match {\n            case cls: TypedNuCls =>\n              cls.typeSignature(usesNew, loco)\n            case _: TypedNuDummy => errType\n            case _ => die\n          } else typeSignatureOf(usesNew, loco, td, level, tparams, typedParams, N, TopType, inheritedTags)\n      }\n    \n    override def toString: String =\n      s\"${decl.name} ~> ${if (isComputing) \"<computing>\" else result.fold(\"<uncomputed>\")(_.toString)}\"\n    \n  }\n  \n  def refreshHelper2(raw: PolyNuDecl, v: Var, parTargs: Opt[Ls[ST]])\n        (implicit ctx: Ctx): (MutMap[TV, ST], Map[Str, NuParam]) = {\n    val freshened: MutMap[TV, ST] = MutMap.empty\n    val rawName = v.name\n    \n    val parTP = raw.tparams.lazyZip(parTargs.getOrElse(raw.tparams.map {\n        case (_, tv, _) => freshVar(tv.prov, S(tv), tv.nameHint)(tv.level)\n    })).map { case ((tn, _tv, vi), targ) =>\n      val tv = (targ match {\n        case tv: TV => \n          println(s\"Passing ${tn.name} :: ${_tv} <=< ${tv}\")\n          tv\n        case _ =>\n          println(s\"Assigning ${tn.name} :: ${_tv} := $targ where ${targ.showBounds}\")\n          val tv =\n            freshVar(_tv.prov, S(_tv), _tv.nameHint,\n              lbs = _tv.lowerBounds,\n              ubs = _tv.upperBounds,\n              )(targ.level)\n          println(s\"Set ${tv} ~> ${_tv}\")\n          assert(tv.assignedTo.isEmpty)\n          \n          // * Note: no checks that the assigned variable satisfies the bounds...\n          // * When we support bounded types, bounds check will be needed at the type definition site\n          assert(tv.lowerBounds.isEmpty, tv.lowerBounds)\n          assert(tv.upperBounds.isEmpty, tv.upperBounds)\n          tv.assignedTo = S(targ)\n          \n          // println(s\"Assigned ${tv.assignedTo}\")\n          tv\n      })\n      freshened += _tv -> tv\n      rawName+\"#\"+tn.name -> NuParam(tn, FieldType(S(tv), tv)(provTODO), isPublic = true)(ctx.lvl)\n    }\n    \n    freshened -> parTP.toMap\n  }\n  \n}\n\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/Parser.scala",
    "content": "package mlscript\n\nimport scala.annotation.nowarn\nimport scala.util.chaining._\nimport scala.language.implicitConversions\nimport fastparse._\nimport mlscript.utils._, shorthands._\nimport mlscript.Lexer._\n\n/** Inspired by and adapted from:\n  *   scalaparse: https://github.com/lihaoyi/fastparse/tree/master/scalaparse\n  *   pythonparse: https://github.com/lihaoyi/fastparse/tree/master/pythonparse\n  */\n@nowarn(\"cat=other\") // \"comparing a fresh object using `ne` will always yield true\" in macrco-generated code\n@SuppressWarnings(Array(\"org.wartremover.warts.All\"))\nclass Parser(origin: Origin, indent: Int = 0, recordLocations: Bool = true) {\n  //implicit def whitespace(cfg: P[_]): P[Unit] = Lexical.wscomment(cfg)\n  implicit def whitespace(cfg: P[_]): P[Unit] = Lexer.nonewlinewscomment(cfg)\n  \n  lazy val nextLevel = new Parser(origin: Origin, indent + 1, recordLocations)\n  \n  def toParams(t: Term) = t\n  \n  def UnitLit = Tup(Nil)\n  \n  // NOTE: due to bug in fastparse, the parameter should be by-name!\n  def locate[p:P, L <: Located](tree: => P[L]) = (Index ~~ tree ~~ Index).map {\n    case (i0, n, i1) => n.withLoc(i0, i1, origin)\n  }\n  \n  def space[p: P] = P( CharIn(\" \\n\") )\n  def NEWLINE[p: P]: P0 = P( \"\\n\" | End )\n  def ENDMARKER[p: P]: P0 = P( End ).opaque(\"unexpected token in this position\")\n  \n  def nl_indents[p: P] = P( \"\\n\" ~~ emptyLines ~~ \" \".repX(indent, max = indent) )\n  def emptyLines[p: P] = P( (\"\" ~ Lexer.comment.? ~ \"\\n\").repX(0) )\n  \n  def spaces[p: P] = P( (Lexer.nonewlinewscomment.? ~~ \"\\n\").repX(1) )\n  \n  def NAME[p: P]: P[Var] = locate(ident.map(Var(_)))\n  \n  def ident[p: P]: P[String] = Lexer.identifier | \"(\" ~ operator.! ~ \")\"\n  \n  def NUMBER[p: P]: P[Lit] = locate(\n    P( Lexer.longinteger | Lexer.integer ).map(IntLit) |\n    P( Lexer.floatnumber ).map(DecLit)\n  )\n  def STRING[p: P]: P[StrLit] = locate(Lexer.stringliteral.map(StrLit(_)))\n\n  def FIELD[p: P]: P[Var] = locate(\n    P( Lexer.identifier ).map(Var(_)) |\n    P( Lexer.decimalinteger ).map(n => Var(n.toString))\n  )\n  \n  def expr[p: P]: P[Term] = P( ite | basicExpr ).opaque(\"expression\")\n  \n  def ite[p: P]: P[Term] = P( kw(\"if\") ~/ expr ~ kw(\"then\") ~ expr ~ kw(\"else\") ~ expr ).map { ite =>\n    App(App(App(Var(\"if\"), ite._1), ite._2), ite._3)\n  }\n  \n  def basicExpr[p: P]: P[Term] = P( lams ~ operator_suite.? ).map {\n    case (lhs, N) => lhs\n    case (lhs, S(ops)) => ops.foldLeft(lhs) {\n      case (acc, (op, rhs)) => App(App(op, acc), rhs)\n    }\n  }.opaque(\"expression\")\n  \n  def stmt[p: P]: P[Statement] = defn | let | expr\n  \n  def datatypeDefn[p: P]: P[DatatypeDefn] = P(\n      kw(\"data\") ~ kw(\"type\") ~/ expr ~ emptyLines ~\n      ( kw(\"of\") ~ (binops.rep(1, \",\").map(es => Blk(es.toList)) | suite) ).?\n    ).map {\n      case (hd, N) => DatatypeDefn(hd, Blk(Nil))\n      case (hd, S(cs)) => DatatypeDefn(hd, cs)\n    }.opaque(\"data type definition\")\n  \n  def dataDefn[p: P]: P[DataDefn] = P( kw(\"data\") ~/ expr ).map(DataDefn(_)).opaque(\"data definition\")\n  \n  def defn[p: P]: P[Statement] = datatypeDefn | dataDefn\n  \n  def let[p: P]: P[LetS] =\n    locate(P( kw(\"let\") ~ kw(\"rec\").!.? ~ commas ~ \"=\" ~/ (expr | suite) ).map {\n      case (r, p, e) => LetS(r.isDefined, p, e)\n    }).opaque(\"let binding\")\n  \n  def multilineBlock[p: P]: P[Blk] =\n    P( stmt ~ (\";\" ~ stmt).rep ~ (\";\".? ~ nl_indents ~~ multilineBlock).? ).map {\n      case (s, ss1, N) => Blk(s :: ss1.toList)\n      case (s, ss1, S(Blk(ss2))) => Blk(s :: ss1.toList ::: ss2.toList)\n    }\n  def operatorBlock[p: P]: P[Seq[(Var, Term)]] =\n    P( Index ~~ operator.! ~~ Index ~ expr ~ (nl_indents ~~ operatorBlock).? ).map {\n      case (i0, op, i1, t, opts) => (Var(op).withLoc(i0, i1, origin), t) +: opts.toList.flatten\n    }\n  \n  def lams[p: P]: P[Term] = P( commas ~ ((\"/\".! | \"=>\".!) ~/ (expr | suite) | \"\".! ~ suite).? ).map(checkless {\n    case (trm, N) => trm\n    case (trm, S((\"\", rest))) => App(trm, toParams(rest))\n    case (trm, S((\"/\", rest))) => App(trm, toParams(rest))\n    case (trm, S((\"=>\", rest))) => Lam(toParams(trm), rest)\n  }).opaque(\"applied expressions\")\n  \n  // TODO support spreads \"\"...xs\"\"\n  def commas[p: P]: P[Term] = P(\n    Index ~~ (NAME ~ \":\" ~ (noCommas | suite) | noCommas.map(Var(\"\") -> _)).rep(1, \",\").map(_.toList) ~ \",\".!.? ~~ Index\n  ).map {\n    case (_, (Var(\"\"), x) :: Nil, N, _) => x\n    case (i0, xs, _, i1) => Tup(xs.map { case (n, t) => (n optionIf (_.name.nonEmpty), Fld(FldFlags.empty, t)) }).withLoc(i0, i1, origin)\n  }\n  \n  def booleans[p: P]: P[Term] = P(binops rep (1, kw(\"and\")) rep (1, kw(\"or\"))) // TODO locs\n    .map(_.map(_.reduce((l, r) => App(OpApp(\"and\", l), r))).reduce((l, r) => App(OpApp(\"or\", l), r)))\n  def noCommas[p: P]: P[Term] = P(booleans ~ ((kw(\"as\") | kw(\"is\")).! ~ booleans).rep).map {\n    case (lhs, casts) => casts.foldLeft(lhs) {\n      case (acc, (\"as\", rhs)) => Bind(acc, rhs)\n      case (acc, (\"is\", rhs)) => Test(acc, rhs)\n    }\n  }\n  \n  /** Note that `,` implicitly has the lowest precedence, followed by the ones below. */\n  private val prec: Map[Char,Int] = List(\n    //\",\", // Used to have it here; but that made it left-associative\n    \":\",\n    \"|\",\n    \"^\",\n    \"&\",\n    \"= !\",\n    \"< >\",\n    \"+ -\",\n    \"* / %\",\n    \".\",\n  ).zipWithIndex.flatMap {\n    case (cs,i) => cs.filterNot(_ == ' ').map(_ -> i)\n  }.toMap.withDefaultValue(Int.MaxValue)\n  \n  def precedence(op: String): Int = prec(op.head) min prec(op.last)\n  \n  // Note: There are three right-associative operators, dealt with above, not here: `=>`, `/`, and `,`\n  // Adapted from: https://github.com/databricks/sjsonnet/blob/master/sjsonnet/src/sjsonnet/Parser.scala#L136-L180\n  def binops[p: P]: P[Term] =\n    P(apps ~ (Index ~~ operator.! ~~ Index ~/ (apps | suite)).rep ~ \"\")\n  // Note: interestingly, the ~/ cut above prevents:  \n  //    a +\n  //      b +\n  //      c\n  // from being parsed as:\n  //    (a +\n  //      b) +\n  //      c\n  .map { case (pre, fs) =>\n    var remaining = fs\n    def climb(minPrec: Int, current: Term): Term = {\n      var result = current\n      while (\n        remaining.headOption match {\n          case None => false\n          case Some((off0, op, off1, next)) =>\n            val prec: Int = precedence(op)\n            if (prec < minPrec) false\n            else {\n              remaining = remaining.tail\n              val rhs = climb(prec + 1, next)\n              result = App(App(Var(op).withLoc(off0, off1, origin), result), rhs)\n              true\n            }\n        }\n      )()\n      result\n    }\n    climb(0, pre)\n  }\n  \n  // Note: the `suite.?` here is used in cases like:\n  //  foo\n  //      bar\n  //    baz      // outer app, uses this suite...\n  def apps[p: P]: P[Term] = P( atomOrSelect.rep(1) ~ suite.? ).map {\n    case (as, ao) => (as ++ ao.toList).reduceLeft((f, a) => App(f, toParams(a)))\n  }\n  \n  def atomOrSelect[p: P]: P[Term] = P(atom ~ (Index ~~ \".\" ~ FIELD ~~ Index).rep).map {\n    case (lhs, sels) => sels.foldLeft(lhs) {\n      case (acc, (i0,str,i1)) => Sel(lhs, str).withLoc(i0, i1, origin)\n    }\n  }\n  \n  def recordBrackets[p: P]: P[Term] =\n    locate(P( \"{\" ~ (suite | nextLevel.multilineBlock).? ~ nl_indents.? ~ \"}\" )\n      .map(xo => Bra(true, xo.getOrElse(Tup(Nil)))))\n  \n  def tupleBrackets[p: P]: P[Term] =\n    locate(P( \"(\" ~ (suite | nextLevel.multilineBlock).? ~ nl_indents.? ~ \")\" )\n      .map(xo => Bra(false, xo.getOrElse(Tup(Nil)))))\n  \n  def atom[p: P]: P[Term] = P(tupleBrackets | recordBrackets | STRING | NAME | NUMBER)\n  \n  def nextIndentP[p: P]: P[Int] = \" \".repX(indent + 1).!.map(_.length)\n  def indented[p: P, A](p: Parser => P[A]): P[A] = \"\\n\" ~~ emptyLines ~~ nextIndentP.flatMapX { nextIndent =>\n    p(new Parser(origin, nextIndent, recordLocations))\n  }\n  def suite[p: P]: P[Term] =\n    P( indented(_.multilineBlock) ).opaque(\"indented block\")\n  def operator_suite[p: P]: P[Seq[(Var, Term)]] =\n    P( indented(_.operatorBlock) ).opaque(\"operators block\")\n  \n  \n  // def repl_input[p: P]: P[Term] = P( (expr | P(\"\").map(_ => UnitLit)) ~ ENDMARKER )\n  \n  def pgrm[p: P]: P[Pgrm] = P( multilineBlock ~  emptyLines ~ End map (b => Pgrm(b.stmts)) )\n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/Token.scala",
    "content": "package mlscript\n\nimport mlscript.utils._, shorthands._\n\n\n/** Type of general Tokens */\nsealed abstract class Token {\n  def describe: Str = this match {\n    case SPACE => \"space\"\n    case COMMA => \"comma\"\n    case SEMI => \"semicolon\"\n    case NEWLINE => \"newline\"\n    case INDENT => \"indentation\"\n    case DEINDENT => \"deindentation\"\n    case ERROR => \"error\"\n    case QUOTE => \"quote\"\n    case LITVAL(value) => \"literal\"\n    case KEYWORD(name) =>\n      if (name.headOption.exists(_.isLetter)) s\"'$name' keyword\" else s\"'$name'\"\n    case IDENT(name, symbolic) => if (symbolic) \"operator\" else \"identifier\"\n    case SELECT(name) => \"selector\"\n    case OPEN_BRACKET(k) => s\"opening ${k.name}\"\n    case CLOSE_BRACKET(k) => s\"closing ${k.name}\"\n    case BRACKETS(BracketKind.Indent, contents) => s\"indented block\"\n    case BRACKETS(k, contents) => s\"${k.name} section\"\n    case COMMENT(text) => \"comment\"\n  }\n}\n\n/** Type of 'Structured Tokens' aka 'Strokens',\n  * which use a `BRACKETS` construct instead of `OPEN_BRACKET`/`CLOSE_BRACKET` and `INDENT`/`DEINDENT` */\nsealed trait Stroken extends Token\n\ncase object SPACE extends Token with Stroken\ncase object COMMA extends Token with Stroken\ncase object SEMI extends Token with Stroken\ncase object NEWLINE extends Token with Stroken // TODO rm\ncase object INDENT extends Token\ncase object DEINDENT extends Token\ncase object ERROR extends Token with Stroken\ncase object QUOTE extends Token with Stroken\nfinal case class LITVAL(value: Lit) extends Token with Stroken\nfinal case class KEYWORD(name: String) extends Token with Stroken\nfinal case class IDENT(name: String, symbolic: Bool) extends Token with Stroken\nfinal case class SELECT(name: String) extends Token with Stroken\nfinal case class OPEN_BRACKET(k: BracketKind) extends Token\nfinal case class CLOSE_BRACKET(k: BracketKind) extends Token\nfinal case class BRACKETS(k: BracketKind, contents: Ls[Stroken -> Loc])(val innerLoc: Loc) extends Token with Stroken\nfinal case class COMMENT(text: String) extends Token with Stroken\n\n\nsealed abstract class BracketKind {\n  import BracketKind._\n  lazy val (beg, end) = this match {\n    case Round => \"(\" -> \")\"\n    case Curly => \"{\" -> \"}\"\n    case Square => \"[\" -> \"]\"\n    case Angle => \"‹\" -> \"›\"\n    case Indent => \"→\" -> \"←\"\n    case Quasiquote => \"code\\\"\" -> \"\\\"\"\n    case QuasiquoteTriple => \"code\\\"\\\"\\\"\" -> \"\\\"\\\"\\\"\"\n    case Unquote => \"${\" -> \"}\"\n  }\n  def name: Str = this match {\n    case Round => \"parenthesis\"\n    case Curly => \"curly brace\"\n    case Square => \"square bracket\"\n    case Angle => \"angle bracket\"\n    case Indent => \"indentation\"\n    case Quasiquote => \"quasiquote\"\n    case QuasiquoteTriple => \"quasiquote triple\"\n    case Unquote => \"unquote\"\n  }\n}\n\nobject BracketKind {\n  case object Round extends BracketKind\n  case object Curly extends BracketKind\n  case object Square extends BracketKind\n  case object Angle extends BracketKind\n  case object Indent extends BracketKind\n  case object Quasiquote extends BracketKind\n  case object QuasiquoteTriple extends BracketKind\n  case object Unquote extends BracketKind\n  \n  def unapply(c: Char): Opt[Either[BracketKind, BracketKind]] = c |>? {\n    case '(' => Left(Round)\n    case ')' => Right(Round)\n    case '{' => Left(Curly)\n    case '}' => Right(Curly)\n    case '[' => Left(Square)\n    case ']' => Right(Square)\n    case '‹' => Left(Angle)\n    case '›' => Right(Angle)\n  }\n}\n\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/TypeDefs.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet}\nimport scala.collection.immutable.{SortedSet, SortedMap}\nimport scala.util.chaining._\nimport scala.annotation.tailrec\nimport mlscript.utils._, shorthands._\nimport mlscript.Message._\n\nclass TypeDefs extends NuTypeDefs { Typer: Typer =>\n  import TypeProvenance.{apply => tp}\n  \n  \n  trait AnyTypeDef {\n    // val kind: TypeDefKind\n    // val nme: TypeName\n    // val tparamsargs: List[(TypeName, TypeVariable)]\n  }\n  \n  /**\n   * TypeDef holds information about declarations like classes, interfaces, and type aliases\n   *\n   * @param kind tells if it's a class, interface or alias\n   * @param nme name of the defined type\n   * @param tparamsargs list of type parameter names and their corresponding type variable names used in the definition of the type\n   * @param tvars\n   * @param bodyTy type of the body, this means the fields of a class or interface or the type that is being aliased\n   * @param mthDecls method type declarations in a class or interface, not relevant for type alias\n   * @param mthDefs method definitions in a class or interface, not relevant for type alias\n   * @param baseClasses base class if the class or interface inherits from any\n   * @param toLoc source location related information\n   * @param positionals positional term parameters of the class\n   * @param adtData maps a class to its ADT by name\n   */\n  case class TypeDef(\n    kind: TypeDefKind,\n    nme: TypeName,\n    tparamsargs: List[(TypeName, TypeVariable)],\n    bodyTy: SimpleType,\n    mthDecls: List[MethodDef[Right[Term, Type]]],\n    mthDefs: List[MethodDef[Left[Term, Type]]],\n    baseClasses: Set[TypeName],\n    toLoc: Opt[Loc],\n    positionals: Ls[Str],\n    adtData: Opt[AdtInfo] = N,\n  ) {\n    def allBaseClasses(ctx: Ctx)(implicit traversed: Set[TypeName]): Set[TypeName] =\n      baseClasses.map(v => TypeName(v.name)) ++\n        baseClasses.iterator.filterNot(traversed).flatMap(v =>\n          ctx.tyDefs.get(v.name).fold(Set.empty[TypeName])(_.allBaseClasses(ctx)(traversed + v)))\n    val (tparams: List[TypeName], targs: List[TypeVariable]) = tparamsargs.unzip\n    // * This is lazy so that the variable is not created if the type doesn't end up being processed,\n    // * which may happen if it is ill-formed.\n    lazy val thisTv: TypeVariable = freshVar(noProv, N, S(\"this\"), Nil, TypeRef(nme, targs)(noProv) :: Nil)(1) // FIXME coudl N here result in divergence? cf. absence of shadow\n    var tvarVariances: Opt[VarianceStore] = N\n    def getVariancesOrDefault: collection.Map[TV, VarianceInfo] =\n      tvarVariances.getOrElse(Map.empty[TV, VarianceInfo].withDefaultValue(VarianceInfo.in))\n  }\n  \n  /** Represent a set of methods belonging to some owner type.\n    * This includes explicitly declared/defined as well as inherited methods. */\n  private case class MethodSet(\n    ownerType: TypeName,\n    parents: List[MethodSet],\n    decls: Map[Str, MethodType],\n    defns: Map[Str, MethodType],\n  ) {\n    private def &(that: MethodSet)(tn: TypeName, overridden: Set[Str])(implicit raise: Raise): MethodSet =\n      MethodSet(\n        tn,\n        this.parents ::: that.parents,\n        mergeMap(this.decls, that.decls)(_ & _),\n        (this.defns.iterator ++ that.defns.iterator).toSeq.groupMap(_._1)(_._2).flatMap {\n          case _ -> Nil => die\n          case mn -> (defn :: Nil) => S(mn -> defn)\n          case mn -> defns if overridden(mn) => N  // ignore an inherited method definition if it's overridden\n          case mn -> defns =>\n            err(msg\"An overriding method definition must be given when inheriting from multiple method definitions\" -> tn.toLoc\n              :: msg\"Definitions of method $mn inherited from:\" -> N\n              :: defns.iterator.map(mt => msg\"• ${mt.parents.head}\" -> mt.prov.loco).toList)\n            S(mn -> MethodType(defns.head.level, N, tn :: Nil, isInherited = false)(\n              TypeProvenance(tn.toLoc, \"inherited method declaration\")))\n        }\n      )\n    /** Returns a `MethodSet` of the _inherited_ methods only,\n      *   disregarding the current MethodSet's methods... \n      * Useful for subsumption checking\n      *   as inherited and current methods should be considered separately \n      * An overriding definition is required when multiple method definitions are inherited.\n      *   An error is raised if no overriding definition is given. */\n    def processInheritedMethods(implicit ctx: Ctx, raise: Raise): MethodSet =\n      processInheritedMethodsHelper(includeCurrentMethods = false)\n    private def processInheritedMethodsHelper(includeCurrentMethods: Bool)\n        (implicit ctx: Ctx, raise: Raise): MethodSet = {\n      def addParent(mt: MethodSet): MethodSet = {\n        val td = ctx.tyDefs(ownerType.name)\n        def addThis(mt: MethodType): MethodType =\n          mt.copy(body = mt.body.map(b => b.copy(_1 = td.thisTv)))(mt.prov)\n        def add(mt: MethodType): MethodType =\n          mt.copy(parents = ownerType :: mt.parents)(mt.prov)\n        mt.copy(decls = mt.decls.view.mapValues(addThis).mapValues(add).toMap, defns = mt.defns.view.mapValues(addThis).toMap)\n      }\n      parents.map(_.processInheritedMethodsHelper(true))\n        .reduceOption(_.&(_)(ownerType, defns.keySet)).map(addParent)\n        .foldRight(if (includeCurrentMethods) this else copy(decls = Map.empty, defns = Map.empty)) {\n          (mds1, mds2) =>\n            mds2.copy(decls = mds1.decls ++ mds2.decls, defns = mds1.defns ++ mds2.defns)\n        }\n    }\n  }\n  \n  \n  def tparamField(clsNme: TypeName, tparamNme: TypeName): Var =\n    Var(clsNme.name + \"#\" + tparamNme.name)\n  \n  def clsNameToNomTag(td: NuTypeDef)(prov: TypeProvenance, ctx: Ctx): ClassTag = {\n    require((td.kind is Cls) || (td.kind is Mod), td.kind)\n    ClassTag(Var(td.nme.name),\n        if(newDefs && td.nme.name =/= \"Object\")\n          Set.single(TN(\"Object\"))\n            | ctx.tyDefs2.get(td.nme.name).map(_.inheritedTags).getOrElse(Set.empty)\n        else ctx.allBaseClassesOf(td.nme.name)\n      )(prov)\n  }\n  def clsNameToNomTag(td: TypeDef)(prov: TypeProvenance, ctx: Ctx): ClassTag = {\n    require((td.kind is Cls) || (td.kind is Mod), td.kind)\n    ClassTag(Var(td.nme.name), ctx.allBaseClassesOf(td.nme.name))(prov)\n  }\n  def trtNameToNomTag(td: TypeDef)(prov: TypeProvenance, ctx: Ctx): TraitTag = {\n    require(td.kind is Trt)\n    TraitTag(Var(td.nme.name), Set.empty)(prov)\n  }\n  def trtNameToNomTag(td: NuTypeDef)(prov: TypeProvenance, ctx: Ctx): TraitTag = {\n    require(td.kind is Trt)\n    TraitTag(Var(td.nme.name), ctx.tyDefs2.get(td.nme.name).map(_.inheritedTags).getOrElse(Set.empty))(prov)\n  }\n  \n  def baseClassesOf(tyd: mlscript.TypeDef): Set[TypeName] =\n    if (tyd.kind === Als) Set.empty else baseClassesOf(tyd.body)\n  \n  private def baseClassesOf(ty: Type): Set[TypeName] = ty match {\n      case Inter(l, r) => baseClassesOf(l) ++ baseClassesOf(r)\n      case TypeName(nme) => Set.single(TypeName(nme))\n      case AppliedType(b, _) => baseClassesOf(b)\n      case Record(_) => Set.empty\n      case _: Union => Set.empty\n      case _ => Set.empty // TODO TupleType?\n    }\n  \n  \n  \n  /** Only supports getting the fields of a valid base class type.\n   * Notably, does not traverse type variables. \n   * Note: this does not retrieve the positional fields implicitly defined by tuples */\n  def fieldsOf(ty: SimpleType, paramTags: Bool)(implicit ctx: Ctx): Map[Var, FieldType] =\n  // trace(s\"Fields of $ty {${travsersed.mkString(\",\")}}\")\n  {\n    ty match {\n      case tr @ TypeRef(td, targs) =>\n        fieldsOf(tr.expandWith(paramTags, selfTy = false), paramTags)\n      case ComposedType(false, l, r) =>\n        mergeMap(fieldsOf(l, paramTags), fieldsOf(r, paramTags))(_ && _)\n      case RecordType(fs) => fs.toMap\n      case p: ProxyType => fieldsOf(p.underlying, paramTags)\n      case Without(base, ns) => fieldsOf(base, paramTags).filter(ns contains _._1)\n      case TypeBounds(lb, ub) => fieldsOf(ub, paramTags)\n      case _: TypeTag | _: FunctionType | _: ArrayBase | _: TypeVariable\n        | _: NegType | _: ExtrType | _: ComposedType | _: SpliceType\n        | _: ConstrainedType | _: PolymorphicType | _: Overload\n        => Map.empty\n    }\n  }\n  // ()\n  \n  def processTypeDefs(newDefs0: List[mlscript.TypeDef])(implicit ctx: Ctx, raise: Raise): Ctx = {\n    var allDefs = ctx.tyDefs\n    val allEnv = ctx.env.clone\n    val allMthEnv = ctx.mthEnv.clone\n    val newDefsInfo = newDefs0.iterator.map { case td => td.nme.name -> (td.kind, td.tparams.size) }.toMap\n    val newDefs = newDefs0.flatMap { td0 =>\n      val n = td0.nme.name.capitalize\n      val td = if (td0.nme.name.isCapitalized) td0\n      else {\n        err(msg\"Type names must start with a capital letter\", td0.nme.toLoc)\n        td0.copy(nme = td0.nme.copy(n).withLocOf(td0.nme)).withLocOf(td0)\n      }\n      if (reservedTypeNames.contains(n)) {\n        err(msg\"Type name '$n' is reserved.\", td.nme.toLoc)\n      }\n      td.tparams.groupBy(_.name).foreach { case s -> tps if tps.sizeIs > 1 => err(\n          msg\"Multiple declarations of type parameter ${s} in ${td.kind.str} definition\" -> td.toLoc\n            :: tps.map(tp => msg\"Declared at\" -> tp.toLoc))\n        case _ =>\n      }\n      allDefs.get(n) match {\n        case S(other) =>\n          err(msg\"Type '$n' is already defined.\", td.nme.toLoc)\n          N\n        case N =>\n          val dummyTargs = td.tparams.map(p =>\n            freshVar(originProv(p.toLoc, s\"${td.kind.str} type parameter\", p.name), N, S(p.name))(ctx.lvl + 1))\n          val tparamsargs = td.tparams.lazyZip(dummyTargs)\n          val bodyTy =\n            typePolyType(td.body, simplify = false)(ctx, raise, tparamsargs.map(_.name -> _).toMap, newDefsInfo)\n          val td1 = TypeDef(td.kind, td.nme, tparamsargs.toList, bodyTy,\n            td.mthDecls, td.mthDefs, baseClassesOf(td), td.toLoc, td.positionals.map(_.name), td.adtInfo)\n          allDefs += n -> td1\n          S(td1)\n      }\n    }\n    import ctx.{tyDefs => oldDefs}\n    /* Type the bodies of type definitions, ensuring the correctness of parent types\n     * and the regularity of the definitions, then register the constructors and types in the context. */\n    def typeTypeDefs(implicit ctx: Ctx): Ctx =\n      ctx.copy(tyDefs = oldDefs ++ newDefs.flatMap { td =>\n        implicit val prov: TypeProvenance = tp(td.toLoc, \"type definition\")\n        val n = td.nme\n        def gatherMthNames(td: TypeDef): (Set[Var], Set[Var]) =\n          td.baseClasses.iterator.flatMap(bn => ctx.tyDefs.get(bn.name)).map(gatherMthNames(_)).fold(\n            (td.mthDecls.iterator.map(md => md.nme.copy().withLocOf(md)).toSet,\n            td.mthDefs.iterator.map(md => md.nme.copy().withLocOf(md)).toSet)\n          ) { case ((decls1, defns1), (decls2, defns2)) => (\n            (decls1.toSeq ++ decls2.toSeq).groupBy(identity).map { case (mn, mns) =>\n              if (mns.sizeIs > 1) Var(mn.name).withLoc(td.toLoc) else mn }.toSet,\n            defns1 ++ defns2\n          )}\n        def checkCycle(ty: SimpleType)(implicit travsersed: Set[TypeName \\/ TV]): Bool =\n            // trace(s\"Cycle? $ty {${travsersed.mkString(\",\")}}\") {\n            ty match {\n          case TypeRef(tn, _) if travsersed(L(tn)) =>\n            err(msg\"illegal cycle involving type ${tn}\", prov.loco)\n            false\n          case tr @ TypeRef(tn, targs) => checkCycle(tr.expand)(travsersed + L(tn))\n          case ComposedType(_, l, r) => checkCycle(l) && checkCycle(r)\n          case NegType(u) => checkCycle(u)\n          case p: ProxyType => checkCycle(p.underlying)\n          case Without(base, _) => checkCycle(base)\n          case TypeBounds(lb, ub) => checkCycle(lb) && checkCycle(ub)\n          case tv: TypeVariable => travsersed(R(tv)) || {\n            val t2 = travsersed + R(tv)\n            tv.assignedTo match {\n              case S(ty) =>\n                checkCycle(ty)(t2)\n              case N =>\n                tv.lowerBounds.forall(checkCycle(_)(t2)) && tv.upperBounds.forall(checkCycle(_)(t2))\n            }\n          }\n          case PolymorphicType(_, body) => checkCycle(body)\n          case Overload(alts) => alts.forall(checkCycle)\n          case ConstrainedType(cs, bod) =>\n            cs.forall(lu => checkCycle(lu._1) && checkCycle(lu._2)) && checkCycle(bod)\n          case _: ExtrType | _: TypeTag | _: FunctionType | _: RecordType | _: ArrayBase | _: SpliceType => true\n        }\n        // }()\n        val rightParents = td.kind match {\n          case Als => checkCycle(td.bodyTy)(Set.single(L(td.nme)))\n          case Mod =>\n            err(msg\"modules cannot inherit from other types\", prov.loco)\n            false\n          case k: ObjDefKind =>\n            val parentsClasses = MutSet.empty[TypeRef]\n            def checkParents(ty: SimpleType): Bool = ty match {\n              // case ClassTag(Var(\"string\"), _) => true // Q: always?\n              case _: TypeTag => true // Q: always? // FIXME actually no\n              case tr @ TypeRef(tn2, _) =>\n                val td2 = ctx.tyDefs(tn2.name)\n                td2.kind match {\n                  case Cls =>\n                    if (td.kind is Cls) {\n                      parentsClasses.isEmpty || {\n                        err(msg\"${td.kind.str} $n cannot inherit from class ${tn2\n                            } as it already inherits from class ${parentsClasses.head.defn}\",\n                          prov.loco)\n                        false\n                      } tap (_ => parentsClasses += tr)\n                    } else\n                      checkParents(tr.expand)\n                  case Trt => checkParents(tr.expand)\n                  case Mod =>\n                    err(msg\"cannot inherit from a module\", prov.loco)\n                    false\n                  case Als => \n                    err(msg\"cannot inherit from a type alias\", prov.loco)\n                    false\n                  case Mxn =>\n                    err(msg\"cannot inherit from a mixin\", prov.loco)\n                    false\n                }\n              case ComposedType(false, l, r) => checkParents(l) && checkParents(r)\n              case ComposedType(true, l, r) =>\n                err(msg\"cannot inherit from a type union\", prov.loco)\n                false\n              case tv: TypeVariable =>\n                err(msg\"cannot inherit from a type variable\", prov.loco)\n                false\n              case _: FunctionType | _: Overload =>\n                err(msg\"cannot inherit from a function type\", prov.loco)\n                false\n              case _: NegType =>\n                err(msg\"cannot inherit from a type negation\", prov.loco)\n                false\n              case _: TupleType =>\n                err(msg\"cannot inherit from a tuple type\", prov.loco)\n                false\n              case _: ArrayType => \n                err(msg\"cannot inherit from a array type\", prov.loco)\n                false\n              case _: SpliceType =>\n                err(msg\"cannot inherit from a splice type\", prov.loco)\n                false\n              case _: Without =>\n                err(msg\"cannot inherit from a field removal type\", prov.loco)\n                false\n              case _: TypeBounds =>\n                err(msg\"cannot inherit from type bounds\", prov.loco)\n                false\n              case _: PolymorphicType =>\n                err(msg\"cannot inherit from a polymorphic type\", prov.loco)\n                false\n              case _: ConstrainedType =>\n                err(msg\"cannot inherit from a constrained type\", prov.loco)\n                false\n              case _: RecordType | _: ExtrType => true\n              case p: ProxyType => checkParents(p.underlying)\n            }\n            lazy val checkAbstractAddCtors = {\n              val (decls, defns) = gatherMthNames(td)\n              val isTraitWithMethods = (k is Trt) && defns.nonEmpty\n              val fields = fieldsOf(td.bodyTy, true)\n              fields.foreach {\n                // * Make sure the LB/UB of all inherited type args are consistent.\n                // * This is not actually necessary for soundness\n                // *  (if they aren't, the object type just won't be instantiable),\n                // *  but will help report inheritance errors earlier (see test BadInherit2).\n                case (nme, FieldType(S(lb), ub)) => constrain(lb, ub)\n                case _ => ()\n              }\n              (decls -- defns) match {\n                case absMths if absMths.nonEmpty || isTraitWithMethods =>\n                  if (ctx.get(n.name).isEmpty) // The class may already be defined in an erroneous program\n                    ctx += n.name -> AbstractConstructor(absMths, isTraitWithMethods)\n                case _ =>\n                  val fields = fieldsOf(td.bodyTy, paramTags = true)\n                  val tparamTags = td.tparamsargs.map { case (tp, tv) =>\n                    tparamField(td.nme, tp) -> FieldType(Some(tv), tv)(tv.prov) }\n                  val ctor = k match {\n                    case Cls =>\n                      val nomTag = clsNameToNomTag(td)(originProv(td.nme.toLoc, \"class\", td.nme.name), ctx)\n                      val fieldsRefined = fields.iterator.map(f =>\n                        if (f._1.name.isCapitalized) f\n                        else {\n                          val fv = freshVar(noProv, N,\n                            S(f._1.name.drop(f._1.name.indexOf('#') + 1)) // strip any \"...#\" prefix\n                          )(1).tap(_.upperBounds ::= f._2.ub)\n                          f._1 -> (\n                            if (f._2.lb.isDefined) FieldType(Some(fv), fv)(f._2.prov)\n                            else fv.toUpper(f._2.prov)\n                          )\n                        }).toList\n                      PolymorphicType(MinLevel, FunctionType(\n                        singleTup(RecordType.mk(fieldsRefined.filterNot(_._1.name.isCapitalized))(noProv)),\n                        nomTag & RecordType.mk(\n                          fieldsRefined ::: tparamTags\n                        )(noProv)\n                        // * TODO try later:\n                        // TypeRef(td.nme, td.tparamsargs.unzip._2)(noProv) & RecordType.mk(fieldsRefined)(noProv)\n                      )(originProv(td.nme.toLoc, \"class constructor\", td.nme.name)))\n                    case Trt =>\n                      val nomTag = trtNameToNomTag(td)(originProv(td.nme.toLoc, \"trait\", td.nme.name), ctx)\n                      val tv = freshVar(noProv, N)(1)\n                      tv.upperBounds ::= td.bodyTy\n                      PolymorphicType(MinLevel, FunctionType(\n                        singleTup(tv), tv & nomTag & RecordType.mk(tparamTags)(noProv)\n                      )(originProv(td.nme.toLoc, \"trait constructor\", td.nme.name)))\n                    case _ => ??? // TODO\n                  }\n                  ctx += n.name -> VarSymbol(ctor, Var(n.name))\n              }\n              true\n            }\n            checkParents(td.bodyTy) && checkCycle(td.bodyTy)(Set.single(L(td.nme))) && checkAbstractAddCtors\n          case _ => ??? // TODO\n        }\n        def checkRegular(ty: SimpleType)(implicit reached: Map[Str, Ls[SimpleType]]): Bool = ty match {\n          case tr @ TypeRef(defn, targs) => reached.get(defn.name) match {\n            case None => checkRegular(tr.expandWith(false, selfTy = false))(reached + (defn.name -> targs))\n            case Some(tys) =>\n              // Note: this check *has* to be relatively syntactic because\n              //    the termination of constraint solving relies on recursive type occurrences\n              //    obtained from unrolling a recursive type to be *equal* to the original type\n              //    and to have the same has hashCode (see: the use of a cache MutSet)\n              if (defn === td.nme && tys =/= targs) {\n                err(msg\"Type definition is not regular: it occurs within itself as ${\n                  expandType(tr).show(Typer.newDefs)\n                }, but is defined as ${\n                  expandType(TypeRef(defn, td.targs)(noProv)).show(Typer.newDefs)\n                }\", td.toLoc)(raise)\n                false\n              } else true\n          }\n          case _ => ty.children(includeBounds = false).forall(checkRegular)\n        }\n        // Note: this will end up going through some types several times... We could make sure to\n        //    only go through each type once, but the error messages would be worse.\n        if (rightParents && (irregularTypes || checkRegular(td.bodyTy)(Map(n.name -> td.targs))))\n          td.nme.name -> td :: Nil\n        else Nil\n      })\n    def typeMethods(implicit ctx: Ctx): Ctx = {\n      /* Perform subsumption checking on method declarations and definitions by rigidifying class type variables,\n       * then register the method signatures in the context */\n      def checkSubsume(td: TypeDef, mds: MethodSet): Unit = {\n        val tn = td.nme\n        val MethodSet(_, _, decls, defns) = mds\n        val MethodSet(_, _, declsInherited, defnsInherited) = mds.processInheritedMethods\n        val rigidtargs = {\n          implicit val state: MutMap[TV, ST] = MutMap.empty\n          td.targs.map(freshenAbove(ctx.lvl, _, true))\n        }\n        val targsMap = td.targs.lazyZip(rigidtargs).toMap[SimpleType, SimpleType]\n        def ss(mt: MethodType, bmt: MethodType)(implicit prov: TypeProvenance) = {\n          // implicit val ec: Opt[ExtrCtx] = N\n          constrain(subst(mt.bodyPT, targsMap).instantiate, subst(bmt.bodyPT, targsMap).rigidify)\n        }\n        def registerImplicitSignatures(mn: Str, mthTy: MethodType) = ctx.getMth(N, mn) match {\n          // If the currently registered method belongs to one of the base classes of this class,\n          // then we don't need to do anything.\n          // This is because implicit method calls always default to the parent methods.\n          case S(MethodType(_, _, parents, _)) if {\n            val bcs = ctx.allBaseClassesOf(tn.name)\n            parents.forall(prt => bcs(TypeName(prt.name)))\n          } =>\n          // If this class is one of the base classes of the parent(s) of the currently registered method,\n          // then we need to register the new method. Only happens when the class definitions are \"out-of-order\",\n          // and can disambiguate implicit calls previously marked as ambiguous.\n          // Example:\n            // class B: A\n            //   method F: 0\n            // class C: A\n            //   method F: 42\n            // class A\n            //   method F: int\n          case S(MethodType(_, _, parents, _)) if {\n            val v = TypeName(tn.name)\n            parents.forall(prt => ctx.allBaseClassesOf(prt.name).contains(v)) \n          } => ctx.addMth(N, mn, mthTy)\n          // If this class is unrelated to the parent(s) of the currently registered method,\n          //  then we mark it as ambiguous:\n          case S(mt2) =>\n            // Create an ambiguous method \"placeholder\" (i.e., it has no `body`)\n            val ambiguousMth =\n              MethodType(0, N, (mt2.parents ::: mthTy.parents).distinct, isInherited = false)(mt2.prov)\n            ctx.addMth(N, mn, ambiguousMth)\n          case N => ctx.addMth(N, mn, mthTy)\n        }\n        def overrideError(mn: Str, mt: MethodType, mt2: MethodType) = {\n          mt2.parents.foreach(parent => \n            err(msg\"Overriding method ${parent}.${mn} without explicit declaration is not allowed.\" -> mt.prov.loco ::\n              msg\"Note: method definition inherited from\" -> mt2.prov.loco :: Nil)(raise))\n          println(s\">> Checking subsumption (against inferred type) for inferred type of $mn : $mt\")\n        }\n        declsInherited.foreach { case mn -> mt =>\n          ctx.addMth(S(tn.name), mn, mt)\n        }\n        defnsInherited.foreach { case mn -> mt => \n          println(s\">> Checking subsumption for inferred type of $mn : $mt\")\n          (if (decls.isDefinedAt(mn) && !defns.isDefinedAt(mn)) decls.get(mn) else N).orElse(declsInherited.get(mn))\n            .foreach(ss(mt, _)(mt.prov))\n          if (!declsInherited.get(mn).exists(decl => !decl.isInherited && decl.parents.last === mt.parents.last))\n            ctx.addMth(S(tn.name), mn, mt)\n        }\n        decls.foreach { case mn -> mt =>\n          println(s\">> Checking subsumption for declared type of $mn : $mt\")\n          ((declsInherited.get(mn), defnsInherited.get(mn)) match {\n            case (S(decl), S(defn)) =>\n              if (!defns.isDefinedAt(mn)) defn.parents.foreach(parent => \n                err(msg\"Overriding method ${parent}.${mn} without an overriding definition is not allowed.\" -> mt.prov.loco ::\n                  msg\"Note: method definition inherited from\" -> defn.prov.loco :: Nil)(raise))\n              S(decl)\n            case (S(decl), N) => S(decl)\n            case (N, S(defn)) =>\n              overrideError(mn, mt, defn)\n              S(defn)\n            case (N, N) => N\n          }).foreach(ss(mt, _)(mt.prov))\n          ctx.addMth(S(tn.name), mn, mt)\n          registerImplicitSignatures(mn, mt)\n        }\n        defns.foreach { case mn -> mt => \n          implicit val prov: TypeProvenance = mt.prov\n          println(s\">> Checking subsumption for inferred type of $mn : $mt\")\n          decls.get(mn).orElse((declsInherited.get(mn), defnsInherited.get(mn)) match {\n            case (S(decl), S(defn)) if defn.parents.toSet.subsetOf(decl.parents.toSet) => S(decl)\n            case (_, S(defn)) =>\n              overrideError(mn, mt, defn)\n              S(defn)\n            case (S(decl), N) => S(decl)\n            case (N, N) => N\n          }).foreach(ss(mt, _))\n          if (!decls.isDefinedAt(mn)) {\n            // If the class declares that method explicitly,\n            //   the declared signature is used so we don't have to do anything\n            // If the class does not declare that method explicitly (it could be inherited),\n            //   we still want to make the method available using its inferred signature\n            //   both for implicit method calls and for explicit ones\n            ctx.addMth(S(tn.name), mn, mt)\n            registerImplicitSignatures(mn, mt)\n          }\n          ctx.addMthDefn(tn.name, mn, mt)\n        }\n      }\n      \n      newDefs.foreach { td => if (ctx.tyDefs.isDefinedAt(td.nme.name)) {\n        /* Recursive traverse the type definition and type the bodies of method definitions \n         * by applying the targs in `TypeRef` and rigidifying class type parameters. */\n        val rigidtargs = {\n          implicit val state: MutMap[TV, ST] = MutMap.empty\n          td.targs.map(freshenAbove(ctx.lvl, _, true))\n        }\n        val reverseRigid = rigidtargs.lazyZip(td.targs).toMap\n        def rec(tr: TypeRef, top: Bool = false)(ctx: Ctx): MethodSet = ctx.tyDefs.get(tr.defn.name) match {\n              case N =>\n                err(msg\"type identifier not found: ${tr.defn.name}\" -> tr.prov.loco :: Nil)\n                MethodSet(tr.defn, Nil, Map.empty, Map.empty)\n              case S(td2) =>\n          implicit val thisCtx: Ctx = ctx.nest\n          val targsMap = td2.tparams.iterator.map(_.name).zip(tr.targs).toMap\n          val declared = MutMap.empty[Str, Opt[Loc]]\n          val defined = MutMap.empty[Str, Opt[Loc]]\n          \n          def filterTR(ty: SimpleType): List[TypeRef] = ty match {\n            case ProxyType(und) => filterTR(und)\n            case tr: TypeRef => tr :: Nil\n            case ComposedType(false, l, r) => filterTR(l) ::: filterTR(r)\n            case _ => Nil\n          }\n          def go(md: MethodDef[_ <: Term \\/ Type]): (Str, MethodType) = {\n            val thisTag = TraitTag(Var(\"this\"), Set.empty)(noProv) // or Skolem?!\n            // val thisTag = SkolemTag(thisCtx.lvl/*TODO correct?*/, Var(\"this\"))(noProv)\n            val thisTy = thisTag & tr\n            thisCtx += \"this\" -> VarSymbol(thisTy, Var(\"this\"))\n            val MethodDef(rec, prt, nme, tparams, rhs) = md\n            val prov: TypeProvenance = tp(md.toLoc,\n              (if (!top) \"inherited \" else \"\")\n              + \"method \" + rhs.fold(_ => \"definition\", _ => \"declaration\"))\n            val fullName = s\"${td.nme.name}.${nme.name}\"\n            if (top) {\n              if (!nme.name.isCapitalized)\n                err(msg\"Method names must start with a capital letter\", nme.toLoc)\n              rhs.fold(_ => defined, _ => declared).get(nme.name) match {\n                case S(loco) => err(\n                  msg\"Method '$fullName' is already ${rhs.fold(_ => \"defined\", _ => \"declared\")}\" -> nme.toLoc ::\n                  msg\"at\" -> loco :: Nil)\n                case N =>\n              }\n              tparams.groupBy(_.name).foreach {\n                case s -> tps if tps.sizeIs > 1 => err(\n                  msg\"Multiple declarations of type parameter ${s} in ${prov.desc}\" -> md.toLoc ::\n                  tps.map(tp => msg\"Declared at\" -> tp.toLoc))\n                case _ =>\n              }\n              val tp1s = td2.tparams.iterator.map(tp => tp.name -> tp).toMap\n              tparams.foreach(tp2 => tp1s.get(tp2.name) match {\n                case S(tp1) => warn(\n                  msg\"Method type parameter ${tp1}\" -> tp1.toLoc ::\n                  msg\"shadows class type parameter ${tp2}\" -> tp2.toLoc :: Nil)\n                case N =>\n              })\n            }\n            rhs.fold(_ => defined, _ => declared) += nme.name -> nme.toLoc\n            val dummyTargs2 = tparams.map(p =>\n              TraitTag(Var(p.name), Set.empty)(originProv(p.toLoc, \"method type parameter\", p.name))) // FIXME or Skolem?!\n            val targsMap2 = targsMap ++ tparams.iterator.map(_.name).zip(dummyTargs2).toMap\n            val reverseRigid2 = reverseRigid ++ dummyTargs2.map(t => t ->\n              freshVar(t.prov, N, S(t.id.idStr))(thisCtx.lvl + 1)) +\n                (thisTag -> td.thisTv) +\n                (td.thisTv -> td.thisTv) // needed to prevent the type variable from being refreshed during substitution!\n            val bodyTy: PolymorphicType = subst(rhs.fold(term =>\n              ctx.getMthDefn(prt.name, nme.name)\n                .fold(typeLetRhs(rec, nme.name, term)(thisCtx, raise, targsMap2,\n                    genLambdas = !distributeForalls || generalizeCurriedFunctions)) { mt =>\n                  // Now buckle-up because this is some seriously twisted stuff:\n                  //    If the method is already in the environment,\n                  //    it means it belongs to a previously-defined class/trait (not the one being typed),\n                  //    in which case we need to perform a substitution on the corresponding method body...\n                  val targsMap3 = td2.targs.lazyZip(tr.targs).toMap[ST, ST] +\n                    (td2.thisTv -> td.thisTv) +\n                    (td.thisTv -> td.thisTv)\n                  // Subsitute parent this TVs to current this TV.\n                  PolymorphicType(mt.bodyPT.level, subst(mt.bodyPT.body, targsMap3) match {\n                    // Try to wnwrap one layer of prov, which would have been wrapped by `MethodType.bodyPT`,\n                    // and will otherwise mask the more precise new prov that contains \"inherited\"\n                    case ProvType(underlying) => underlying\n                    case pt => pt\n                  })\n                },\n              ty => {\n                implicit val tp: TP = prov\n                thisCtx.nextLevel { newCtx =>\n                  PolymorphicType(ctx.lvl, typeType(ty)(newCtx, raise, targsMap2))\n                }\n                // ^ Note: we need to go to the next level here,\n                //    which is also done automatically by `typeLetRhs` in the case above\n              }), reverseRigid2)\n            val mthTy = MethodType(bodyTy.level, S((td.thisTv, bodyTy.body)), td2.nme :: Nil, false)(prov)\n            if (rhs.isRight || !declared.isDefinedAt(nme.name)) {\n              if (top) thisCtx.addMth(S(td.nme.name), nme.name, mthTy)\n              thisCtx.addMth(N, nme.name, mthTy)\n            }\n            nme.name -> mthTy\n          }\n          MethodSet(td2.nme, filterTR(tr.expand).map(rec(_)(thisCtx)),\n            td2.mthDecls.iterator.map(go).toMap, td2.mthDefs.iterator.map(go).toMap)\n        }\n        val mds = rec(TypeRef(td.nme, rigidtargs)(tp(td.toLoc, \"type definition\")), true)(ctx)\n        checkSubsume(td, mds)\n      }}\n      ctx\n    }\n\n    typeMethods(typeTypeDefs(ctx.copy(env = allEnv, mthEnv = allMthEnv, tyDefs = allDefs)))\n  }\n  \n  /**\n    * Finds the variances of all type variables in the given type definitions with the given\n    * context using a fixed point computation. The algorithm starts with each type variable\n    * as bivariant by default and each type defintion position as covariant and\n    * then keeps updating the position variance based on the types it encounters.\n    * \n    * It uses the results to update variance info in the type defintions\n    *\n    * @param tyDefs\n    * @param ctx\n    */\n  def computeVariances(tyDefs: List[TypeDef], ctx: Ctx): Unit = {\n    println(s\"VARIANCE ANALYSIS\")\n    var varianceUpdated: Bool = false;\n    \n    /** Update variance information for all type variables belonging\n      * to a type definition.\n      *\n      * @param ty\n      *   type tree to check variance for\n      * @param curVariance\n      *   variance of current position where the type tree has been found\n      * @param tyDef\n      *   type definition which is currently being processed\n      * @param visited\n      *   set of type variables visited along with the variance\n      *   true polarity if covariant position visit\n      *   false polarity if contravariant position visit\n      *   both if invariant position visit\n      */\n    def updateVariance(ty: SimpleType, curVariance: VarianceInfo)(implicit tyDef: TypeDef, visited: MutSet[Bool -> TypeVariable]): Unit = {\n      def fieldVarianceHelper(fieldTy: FieldType): Unit = {\n          fieldTy.lb.foreach(lb => updateVariance(lb, curVariance.flip))\n          updateVariance(fieldTy.ub, curVariance)\n      }\n      \n      trace(s\"upd[$curVariance] $ty\") { // Note: could simplify this (at some perf cost) by just using ty.childrenPol\n        ty match {\n          case ProxyType(underlying) => updateVariance(underlying, curVariance)\n          case _: TypeTag => ()\n          case ExtrType(pol) => ()\n          case t: TypeVariable =>\n            // update the variance information for the type variable\n            val tvv = tyDef.tvarVariances.getOrElse(die)\n            val oldVariance = tvv.getOrElseUpdate(t, VarianceInfo.bi)\n            val newVariance = oldVariance && curVariance\n            if (newVariance =/= oldVariance) {\n              tvv(t) = newVariance\n              println(s\"UPDATE ${tyDef.nme.name}.$t from $oldVariance to $newVariance\")\n              varianceUpdated = true\n            }\n            val (visitLB, visitUB) = (\n              !curVariance.isContravariant && !visited(true -> t),\n              !curVariance.isCovariant && !visited(false -> t),\n            )\n            t.assignedTo match {\n              case S(ty) =>\n                if (visitLB || visitUB) {\n                  visited += true -> t; visited += false -> t\n                  updateVariance(ty, curVariance)\n                }\n              case N =>\n                if (visitLB) visited += true -> t\n                if (visitUB) visited += false -> t\n                if (visitLB) t.lowerBounds.foreach(lb => updateVariance(lb, VarianceInfo.co))\n                if (visitUB) t.upperBounds.foreach(ub => updateVariance(ub, VarianceInfo.contra))\n            }\n          case RecordType(fields) => fields.foreach {\n            case (_ , fieldTy) => fieldVarianceHelper(fieldTy)\n          }\n          case NegType(negated) =>\n            updateVariance(negated, curVariance.flip)\n          case TypeRef(defn, targs) =>\n            // it's possible that the type definition may not exist in the\n            // context because it is malformed or incorrect. Do nothing in\n            // such cases\n            ctx.tyDefs.get(defn.name).foreach(typeRefDef => {\n              // variance for all type parameters of type definitions has been preset\n              // do nothing if variance for the parameter does not exist\n              targs.zip(typeRefDef.tparamsargs).foreach { case (targ, (_, tvar)) =>\n                typeRefDef.tvarVariances.getOrElse(die).get(tvar).foreach {\n                  case in @ VarianceInfo(false, false) => updateVariance(targ, in)\n                  case VarianceInfo(true, false) => updateVariance(targ, curVariance)\n                  case VarianceInfo(false, true) => updateVariance(targ, curVariance.flip)\n                  case VarianceInfo(true, true) => ()\n                }\n              }\n            })\n          case ComposedType(pol, lhs, rhs) =>\n            updateVariance(lhs, curVariance)\n            updateVariance(rhs, curVariance)\n          case TypeBounds(lb, ub) =>\n            updateVariance(lb, VarianceInfo.contra)\n            updateVariance(ub, VarianceInfo.co)\n          case ArrayType(inner) => fieldVarianceHelper(inner)\n          case TupleType(fields) => fields.foreach {\n              case (_ , fieldTy) => fieldVarianceHelper(fieldTy)\n            }\n          case SpliceType(elems) =>\n            elems.foreach {\n              case L(ty) => updateVariance(ty, curVariance)\n              case R(fld) => fieldVarianceHelper(fld)\n            }\n          case FunctionType(lhs, rhs) =>\n            updateVariance(lhs, curVariance.flip)\n            updateVariance(rhs, curVariance)\n          case Without(base, names) => updateVariance(base, curVariance.flip)\n          case Overload(alts) => alts.foreach(updateVariance(_, curVariance))\n          case PolymorphicType(lvl, bod) =>\n            // * It seems we should want to ignore from the analysis\n            // *  those type vars that are being quantified...\n            // *  When the same variable occurs both as quantified and not quantified\n            // *  in a type, this could make a difference\n            // *  (like it used to in `analysis/Weird.mls`)\n            updateVariance(bod, curVariance)\n          case ConstrainedType(cs, bod) =>\n            cs.foreach { lu =>\n              updateVariance(lu._1, VarianceInfo.co)\n              updateVariance(lu._2, VarianceInfo.contra)\n            }\n            updateVariance(bod, curVariance)\n        }\n      }()\n    }\n    \n    // set default value for all type variables as bivariant\n    // this prevents errors when printing type defintions in\n    // DiffTests for type variables that are not used at all\n    // and hence are not set in the variance info map\n    tyDefs.foreach { t =>\n      if (t.tvarVariances.isEmpty) {\n        // * ^ This may not be empty if the type def was (erroneously) defined several types in the same block\n        t.tvarVariances = S(MutMap.empty)\n        t.tparamsargs.foreach { case (_, tvar) => t.tvarVariances.getOrElse(die).put(tvar, VarianceInfo.bi) }\n      }\n    }\n    \n    var i = 1\n    do trace(s\"⬤ ITERATION $i\") {\n      val visitedSet: MutSet[Bool -> TypeVariable] = MutSet()\n      varianceUpdated = false;\n      tyDefs.foreach {\n        case t @ TypeDef(k, nme, _, body, mthDecls, mthDefs, _, _, _, _) =>\n          trace(s\"${k.str} ${nme.name}  ${\n                t.tvarVariances.getOrElse(die).iterator.map(kv => s\"${kv._2} ${kv._1}\").mkString(\"  \")}\") {\n            updateVariance(body, VarianceInfo.co)(t, visitedSet)\n            val stores = (mthDecls ++ mthDefs).foreach { mthDef => \n              val mthBody = ctx.mthEnv.getOrElse(\n                Right(Some(nme.name), mthDef.nme.name),\n                throw new Exception(s\"Method ${mthDef.nme.name} does not exist in the context\")\n              ).body\n              mthBody.foreach { case (_, body) => updateVariance(body, VarianceInfo.co)(t, visitedSet) }\n            }\n          }()\n      }\n      i += 1\n    }() while (varianceUpdated)\n    println(s\"DONE\")\n  }\n  \n  type VarianceStore = MutMap[TypeVariable, VarianceInfo]\n  object VarianceStore { def empty: VarianceStore = MutMap.empty }\n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/TypeSimplifier.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet, LinkedHashMap, LinkedHashSet}\nimport scala.collection.immutable.{SortedMap, SortedSet}\nimport scala.util.chaining._\nimport mlscript.utils._, shorthands._\n\n\ntrait TypeSimplifier { self: Typer =>\n  \n  \n  def printPols(pols: Map[TypeVariable, Opt[Bool]]): Str =\n    pols.iterator.map(e => s\"${printPol(e._2)}${e._1}\").mkString(\", \")\n  \n  \n  /** Remove bounds that are not reachable by traversing the type following variances.\n    * Note that doing this on annotated type signatures would need to use polarity None\n    *   because a type signature can both be used (positively) and checked against (negatively). */\n  def removeIrrelevantBounds(ty: TypeLike, pol: Opt[Bool], reverseBoundsOrder: Bool, inPlace: Bool = false)\n        (implicit ctx: Ctx): TypeLike =\n  {\n    val _ctx = ctx\n    \n    val allVarPols = ty.getVarsPol(PolMap(pol))\n    println(s\"allVarPols: ${printPols(allVarPols)}\")\n    \n    val renewed = MutMap.empty[TypeVariable, TypeVariable]\n    val renewedtsc = MutMap.empty[TupleSetConstraints, TupleSetConstraints]\n    \n    def renew(tv: TypeVariable): TypeVariable =\n      renewed.getOrElseUpdate(tv,\n        if (inPlace) tv\n        else freshVar(noProv, S(tv), tv.nameHint)(tv.level) tap { fv => println(s\"Renewed $tv ~> $fv\") })\n    \n    def processLike(ty: TypeLike): TypeLike = ty match {\n      case ty: ST => process(ty, N)\n      case OtherTypeLike(tu) =>\n        tu.map(process(_, N))\n    }\n    def process(ty: ST, parent: Opt[Bool -> TV], canDistribForall: Opt[Level] = N): ST =\n        // trace(s\"process($ty) $canDistribForall\") {\n        ty match {\n      \n      case SkolemTag(tv: TypeVariable) => process(tv, parent)\n      \n      case tv: TypeVariable =>\n        parent.filter(_._2 === tv).foreach(p => return ExtrType(p._1)(noProv))\n        \n        var isNew = false\n        val nv = renewed.getOrElseUpdate(tv, { isNew = true; renew(tv) })\n        \n        if (isNew) tv.assignedTo match {\n        case S(ty) =>\n          // * If the variable is polar, we turn the `assignedTo` into a simple bound.\n          // *  I'm not actually sure if that's useful/a good idea.\n          // *  Maybe we should process with the appropriate parent, but still generate an `assignedTo`?\n          // * (Tried it, and it makes almost no difference in the end result.)\n          allVarPols(tv) match {\n            case p if p.isEmpty || nv.assignedTo.nonEmpty =>\n              nv.assignedTo = S(process(ty, N))\n            case N => die // covered\n            case S(true) =>\n              nv.lowerBounds =\n                (process(ty, S(true -> tv)) :: Nil).filterNot(_.isBot)\n            case S(false) =>\n              nv.upperBounds =\n                (process(ty, S(false -> tv)) :: Nil).filterNot(_.isTop)\n          }\n        case N =>\n          nv.lowerBounds = if (allVarPols(tv).forall(_ === true))\n              (if (reverseBoundsOrder) tv.lowerBounds.reverseIterator\n                else tv.lowerBounds.iterator\n              ).map(process(_, S(true -> tv)))\n                .reduceOption(_ | _).filterNot(_.isBot).toList\n            else Nil\n          nv.upperBounds = if (allVarPols(tv).forall(_ === false))\n              (if (reverseBoundsOrder) tv.upperBounds.reverseIterator\n                else tv.upperBounds.iterator\n              ).map(process(_, S(false -> tv)))\n                .reduceOption(_ &- _).filterNot(_.isTop).toList\n            else Nil\n          if (noApproximateOverload)\n            nv.tsc ++= tv.tsc.iterator.map { case (tsc, i) => renewedtsc.get(tsc) match {\n              case S(tsc) => (tsc, i)\n              case N if inPlace => (tsc, i)\n              case N =>\n                val t = new TupleSetConstraints(tsc.constraints, tsc.tvs)\n                renewedtsc += tsc -> t\n                t.tvs = t.tvs.map(x => (x._1, process(x._2, N)))\n                (t, i)\n            }}\n        }\n        nv\n        \n      case ComposedType(true, l, r) =>\n        process(l, parent, canDistribForall = canDistribForall) |\n          process(r, parent, canDistribForall = canDistribForall)\n      case ComposedType(false, l, r) =>\n        process(l, parent, canDistribForall = canDistribForall) &\n          process(r, parent, canDistribForall = canDistribForall)\n      case NegType(ty) => process(ty, parent.map(_.mapFirst(!_))).neg(ty.prov)\n\n      case ProvType(ty) if inPlace =>\n        ProvType(process(ty, parent, canDistribForall = canDistribForall))(ty.prov)\n      case ProvType(ty) => process(ty, parent, canDistribForall = canDistribForall)\n      \n      case tr @ TypeRef(defn, targs) if builtinTypes.contains(defn) && tr.canExpand =>\n        process(tr.expandOrCrash, parent)\n      \n      case RecordType(fields) => RecordType.mk(fields.flatMap { case (v @ Var(fnme), fty) =>\n        // * We make a pass to transform the LB and UB of variant type parameter fields into their extrema\n        val prefix = fnme.takeWhile(_ =/= '#')\n        val postfix = fnme.drop(prefix.length + 1)\n        lazy val default = fty.update(process(_ , N), process(_ , N))\n        if (postfix.isEmpty || prefix.isEmpty) v -> default :: Nil\n        else ctx.tyDefs.get(prefix) match {\n          case S(td) =>\n            td.tvarVariances.fold(v -> default :: Nil)(tvv =>\n              tvv(td.tparamsargs.find(_._1.name === postfix).getOrElse(die)._2) match {\n                case VarianceInfo(true, true) => Nil\n                case VarianceInfo(co, contra) =>\n                  if (co) v -> FieldType(S(BotType), process(fty.ub, N))(fty.prov) :: Nil\n                  else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType)(fty.prov) :: Nil\n                  else  v -> default :: Nil\n              })\n          case N =>\n            // v -> default :: Nil\n            ctx.tyDefs2.get(prefix) match {\n              case S(info) =>\n                info.result match {\n                  case S(cls: TypedNuCls) =>\n                    cls.varianceOf(cls.tparams.find(_._1.name === postfix).getOrElse(die)._2) match {\n                      case VarianceInfo(true, true) => Nil\n                      case VarianceInfo(co, contra) =>\n                        if (co) v -> FieldType(S(BotType), process(fty.ub, N))(fty.prov) :: Nil\n                        else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType)(fty.prov) :: Nil\n                        else  v -> default :: Nil\n                    }\n                  case S(trt: TypedNuTrt) => // TODO factor w/ above & generalize\n                    trt.tparams.iterator.find(_._1.name === postfix).flatMap(_._3).getOrElse(VarianceInfo.in) match {\n                      case VarianceInfo(true, true) => Nil\n                      case VarianceInfo(co, contra) =>\n                        if (co) v -> FieldType(S(BotType), process(fty.ub, N))(fty.prov) :: Nil\n                        else if (contra) v -> FieldType(fty.lb.map(process(_, N)), TopType)(fty.prov) :: Nil\n                        else  v -> default :: Nil\n                    }\n                  case S(_) => ??? // TODO:\n                  case N =>\n                    ??? // TODO use info.explicitVariances\n                }\n              case N => lastWords(s\"'$prefix' not found\")\n            }\n        }\n      })(ty.prov)\n      \n      case PolymorphicType(plvl, bod) =>\n        val res = process(bod, parent, canDistribForall = S(plvl))\n        canDistribForall match {\n          case S(outerLvl) if distributeForalls =>\n            implicit val ctx: Ctx = _ctx.copy(lvl = outerLvl + 1)\n            PolymorphicType(plvl, res).instantiate\n          case _ =>\n            PolymorphicType.mk(plvl, res)\n        }\n      \n      case ft @ FunctionType(l, r) =>\n        FunctionType(process(l, N), process(r, N, canDistribForall = canDistribForall))(ft.prov)\n      \n      case _ =>\n        \n        ty.mapPol(N, smart = true)((_, ty) => process(ty, N))\n      \n    }\n    // }(r => s\"= $r\")\n    \n    processLike(ty)\n    \n  }\n  \n  \n  \n  /** Transform the type recursively, putting everything in Disjunctive Normal Forms and reconstructing class types\n    * from their structural components.\n    * Note that performing this _in place_ is not fully correct,\n    *   as this will lead us to assume TV bounds while simplifying the TV bounds themselves!\n    *     – see [test:T3] –\n    *   However, I think this only manifests in contrived manually-constructed corner cases like \n    *   unguarded recursive types such as `C['a] | 'a as 'a`.\n    */\n  def normalizeTypes_!(st: TypeLike, pol: Opt[Bool])(implicit ctx: Ctx): TypeLike =\n  {\n    val _ctx = ctx\n    \n    lazy val allVarPols = st.getVarsPol(PolMap(pol))\n    println(s\"allVarPols: ${printPols(allVarPols)}\")\n    \n    val processed = MutSet.empty[TV]\n    \n    def helper(dnf: DNF, pol: Opt[Bool], canDistribForall: Opt[Level] = N): ST =\n    {\n      println(s\"DNF: $dnf\")\n      \n      val cs = dnf.cs\n      val (csNegs, otherCs) = cs.partitionMap {\n        case c @ Conjunct(l, vs, r, nvs) if l.isTop && vs.isEmpty && !(r.isBot && nvs.isEmpty) =>\n          // L(r, nvs)\n          L(c)\n        case c => R(c)\n      }\n      \n      // * The goal here is to normalize things like `... | ~A | ~B | ~C` the same as we would `... | ~T`\n      // *  where `T` is `A & B & C`.\n      // * It is fine to call `go` because we made sure A, B, C, etc. do not themsleves have any negative components.\n      val csNegs2 = if (csNegs.isEmpty) BotType\n        else go(csNegs.foldLeft(TopType: ST)(_ & _.toType(sort = true).neg()), pol.map(!_)).neg() // TODO sort?! csNegs and toType\n      \n      val otherCs2 = otherCs.sorted.map { c =>\n        c.vars.foreach(processVar)\n        c.nvars.foreach(processVar)\n        \n        c.toTypeWith(_ match {\n          \n          case LhsRefined(bo, tts, rcd, trs) =>\n            // * The handling of type parameter fields is currently a little wrong here,\n            // *  because we remove:\n            // *    - type parameter fields of parent classes,\n            // *        whereas they could _in principle_ be refined and\n            // *        not correspond exactly to these of the currenly-reconstructed class;\n            // *        and\n            // *    - type parameter fields of the current trait tags\n            // *        whereas we don't actually reconstruct applied trait types...\n            // *        it would be better to just reconstruct them (TODO)\n            \n            val trs2 = trs.map {\n              case (d, tr @ TypeRef(defn, targs)) =>\n                d -> TypeRef(defn, tr.mapTargs(pol)((pol, ta) => go(ta, pol)))(tr.prov)\n            }\n            \n            val traitPrefixes =\n              tts.iterator.collect{ case TraitTag(Var(tagNme), _) => tagNme.capitalize }.toSet\n            \n            bo match {\n              case S(cls @ ClassTag(Var(tagNme), ps))\n                if !primitiveTypes.contains(tagNme)\n                && ctx.tyDefs.contains(tagNme.capitalize)\n                && !newDefs\n              =>\n                val clsNme = tagNme.capitalize // TODO rm capitalize\n                val clsTyNme = TypeName(clsNme)\n                val td = ctx.tyDefs(clsNme)\n                \n                val rcdMap  = rcd.fields.toMap\n                \n                val rcd2  = rcd.copy(rcd.fields.mapValues(_.update(go(_, pol.map(!_)), go(_, pol))))(rcd.prov)\n                println(s\"rcd2 ${rcd2}\")\n                \n                val vs = td.getVariancesOrDefault\n                \n                // * Reconstruct a TypeRef from its current structural components\n                val typeRef = TypeRef(td.nme, td.tparamsargs.zipWithIndex.map { case ((tp, tv), tpidx) =>\n                  val fieldTagNme = tparamField(clsTyNme, tp)\n                  val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta)(noProv) })\n                  fromTyRef.++(rcd2.fields.iterator.filter(_._1 === fieldTagNme).map(_._2))\n                    .foldLeft((BotType: ST, TopType: ST)) {\n                      case ((acc_lb, acc_ub), FieldType(lb, ub)) =>\n                        (acc_lb | lb.getOrElse(BotType), acc_ub & ub)\n                    }.pipe {\n                      case (lb, ub) =>\n                        vs(tv) match {\n                          case VarianceInfo(true, true) => TypeBounds.mk(BotType, TopType)\n                          case VarianceInfo(false, false) =>\n                            // * FIXME: this usage of type bounds is wrong!\n                            // * We're here using it as though it meant a bounded wildcard,\n                            // * for the purpose of type pretty-printing...\n                            // * But this is inconsistent with other uses of these types as *absolute* type ranges!\n                            TypeBounds.mk(lb, ub)\n                            // * However, the fix is to make all TR arguments actual bounded wildcards\n                            // * which is not easy as it requires extensive refactoring\n                            // * \n                            // * Note that the version below doesn't work because the refinement redundancy tests\n                            // * below require non-polar types to compare against, so TypeBounds is inadequate.\n                            /* \n                            pol match {\n                              case N => ???\n                                TypeBounds.mk(lb, ub)\n                              case S(true) => \n                                TypeBounds.mk(lb, ub)\n                              case S(false) => \n                                TypeBounds.mk(ub, lb)\n                            }\n                            */\n                            // * FIXME In fact, the use of such subtyping checks should render\n                            // * all uses of TypeBounds produced by the simplifier inadequate!\n                            // * We should find a proper solution to this at some point...\n                            // * (Probably by only using proper wildcards in the type simplifier.)\n                          case VarianceInfo(co, contra) =>\n                            if (co) ub else lb\n                        }\n                    }\n                })(noProv)\n                println(s\"typeRef ${typeRef}\")\n                \n                val clsFields = fieldsOf(typeRef.expandWith(paramTags = true, selfTy = false), paramTags = true)\n                println(s\"clsFields ${clsFields.mkString(\", \")}\")\n                \n                val cleanPrefixes = ps.map(_.name.capitalize) + clsNme ++ traitPrefixes\n                \n                val cleanedRcd = RecordType(\n                  rcd2.fields.filterNot { case (field, fty) =>\n                    // * This is a bit messy, but was the only way I was able to achieve maximal simplification:\n                    // *  We remove fields that are already inclued by definition of the class by testing for subtyping\n                    // *  with BOTH the new normalized type (from `clsFields`) AND the old one too (from `rcdMap`).\n                    // *  The reason there's a difference is probably because:\n                    // *    - Subtye checking with <:< is an imperfect heuristic and may stop working after normalizing.\n                    // *    - Recursive types will be normalized progressively...\n                    // *        at this point we may look at some bounds that have not yet been normalized.\n                    clsFields.get(field).exists(cf => cf <:< fty ||\n                      rcdMap.get(field).exists(cf <:< _))\n                  }\n                )(rcd2.prov)\n                \n                val rcd2Fields  = rcd2.fields.unzip._1.toSet\n                \n                // * Which fields were NOT part of the original type,\n                // *  and should therefore be excluded from the reconstructed TypeRef:\n                val removedFields = clsFields.keysIterator\n                  .filterNot(field => field.name.isCapitalized || rcd2Fields.contains(field)).toSortedSet\n                val withoutType = if (removedFields.isEmpty) typeRef\n                  else typeRef.without(removedFields)\n                \n                // * Whether we need a `with` (which overrides field types)\n                // *  as opposed to simply an intersection (which refines them):\n                val needsWith = !rcd2.fields.forall {\n                  case (field, fty) =>\n                    clsFields.get(field).forall(cf => fty <:< cf || rcdMap.get(field).exists(_ <:< cf))\n                }\n                val withType = if (needsWith) if (cleanedRcd.fields.isEmpty) withoutType\n                  else WithType(withoutType, cleanedRcd.sorted)(noProv) else typeRef & cleanedRcd.sorted\n                \n                val withTraits = tts.toArray.sorted // TODO also filter out tts that are inherited by the class\n                  .foldLeft(withType: ST)(_ & _)\n                \n                val trs3 = trs2 - td.nme // TODO also filter out class refs that are inherited by the class\n                \n                trs3.valuesIterator.foldLeft(withTraits)(_ & _)\n                \n              case S(cls @ ClassTag(Var(clsNme), ps))\n                if !primitiveTypes.contains(clsNme)\n                && ctx.tyDefs2.contains(clsNme)\n                && ctx.tyDefs2(clsNme).result.isDefined\n              =>\n                val clsTyNme = TypeName(clsNme)\n                val lti = ctx.tyDefs2(clsNme)\n                val cls = lti.result match {\n                  case S(r: TypedNuCls) => r\n                  case _ => die \n                }\n                \n                val rcdMap  = rcd.fields.toMap\n                \n                val rcd2  = rcd.copy(rcd.fields.mapValues(_.update(go(_, pol.map(!_)), go(_, pol))))(rcd.prov)\n                println(s\"rcd2 ${rcd2}\")\n                \n                // val vs =\n                //   // td.getVariancesOrDefault\n                //   // Map.empty[TV, VarianceInfo].withDefaultValue(VarianceInfo.in)\n                //   cls.variances\n                \n                // * Reconstruct a TypeRef from its current structural components\n                val typeRef = TypeRef(cls.td.nme, cls.tparams.zipWithIndex.map { case ((tp, tv, vi), tpidx) =>\n                  val fieldTagNme = tparamField(clsTyNme, tp)\n                  val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta)(noProv) })\n                  fromTyRef.++(rcd2.fields.iterator.filter(_._1 === fieldTagNme).map(_._2))\n                    .foldLeft((BotType: ST, TopType: ST)) {\n                      case ((acc_lb, acc_ub), FieldType(lb, ub)) =>\n                        (acc_lb | lb.getOrElse(BotType), acc_ub & ub)\n                    }.pipe {\n                      case (lb, ub) =>\n                        cls.varianceOf(tv) match {\n                          case VarianceInfo(true, true) => TypeBounds.mk(BotType, TopType)\n                          case VarianceInfo(false, false) => TypeBounds.mk(lb, ub)\n                          case VarianceInfo(co, contra) =>\n                            if (co) ub else lb\n                        }\n                    }\n                })(noProv)\n                println(s\"typeRef ${typeRef}\")\n                \n                val clsFields = fieldsOf(typeRef.expandWith(paramTags = true, selfTy = false), paramTags = true)\n                println(s\"clsFields ${clsFields.mkString(\", \")}\")\n                \n                val cleanPrefixes = ps.map(_.name.capitalize) + clsNme ++ traitPrefixes\n                \n                val cleanedRcd = RecordType(\n                  rcd2.fields.filterNot { case (field, fty) =>\n                    // * This is a bit messy, but was the only way I was able to achieve maximal simplification:\n                    // *  We remove fields that are already inclued by definition of the class by testing for subtyping\n                    // *  with BOTH the new normalized type (from `clsFields`) AND the old one too (from `rcdMap`).\n                    // *  The reason there's a difference is probably because:\n                    // *    - Subtye checking with <:< is an imperfect heuristic and may stop working after normalizing.\n                    // *    - Recursive types will be normalized progressively...\n                    // *        at this point we may look at some bounds that have not yet been normalized.\n                    clsFields.get(field).exists(cf => cf <:< fty ||\n                      rcdMap.get(field).exists(cf <:< _))\n                  }\n                )(rcd2.prov)\n                \n                val rcd2Fields  = rcd2.fields.unzip._1.toSet\n                \n                val withTraits = tts.toArray.sorted // TODO also filter out tts that are inherited by the class\n                  .foldLeft(typeRef & cleanedRcd: ST)(_ & _)\n                \n                val trs3 = trs2 - cls.nme // TODO also filter out class refs that are inherited by the class\n                \n                trs3.valuesIterator.foldLeft(withTraits)(_ & _)\n                \n                \n              case _ =>\n                lazy val nFields = rcd.fields\n                  .filterNot(traitPrefixes contains _._1.name.takeWhile(_ =/= '#'))\n                  .mapValues(_.update(go(_, pol.map(!_)), go(_, pol)))\n                val (res, nfs) = bo match {\n                  case S(tt @ TupleType(fs)) =>\n                    val arity = fs.size\n                    val (componentFields, rcdFields) = rcd.fields\n                      .filterNot(traitPrefixes contains _._1.name.takeWhile(_ =/= '#'))\n                      .partitionMap(f => f._1.toIndexOption.filter((0 until arity).contains).map(_ -> f._2).toLeft(f))\n                    val componentFieldsMap = componentFields.toMap\n                    val tupleComponents = fs.iterator.zipWithIndex.map { case ((nme, ty), i) =>\n                      nme -> (ty && componentFieldsMap.getOrElse(i, TopType.toUpper(noProv))).update(go(_, pol.map(!_)), go(_, pol))\n                    }.toList\n                    S(TupleType(tupleComponents)(tt.prov)) -> rcdFields.mapValues(_.update(go(_, pol.map(!_)), go(_, pol)))\n                  case S(ct: ClassTag) => S(ct) -> nFields\n                  case S(ft @ FunctionType(l, r)) =>\n                    S(FunctionType(\n                      go(l, pol.map(!_)),\n                      go(r, pol, canDistribForall =\n                        canDistribForall.orElse(Option.when(dnf.isPolymorphic)(dnf.polymLevel)))\n                    )(ft.prov)) -> nFields\n                  case S(ot @ Overload(alts)) =>\n                    S(ot.mapAltsPol(pol)((p, t) => go(t, p))) -> nFields\n                  case S(at @ ArrayType(inner)) =>\n                    S(ArrayType(inner.update(go(_, pol.map(!_)), go(_, pol)))(at.prov)) -> nFields\n                  case S(sp @ SpliceType(elems)) =>\n                    S(sp.updateElems(go(_, pol), go(_, pol.map(!_)), go(_, pol))) -> nFields\n                  case S(wt @ Without(b: ComposedType, ns @ EmptyColl())) =>\n                    S(Without(b.map(go(_, pol)), ns)(wt.prov)) -> nFields // FIXME very hacky\n                  case S(wt @ Without(b, ns)) => S(Without(go(b, pol), ns)(wt.prov)) -> nFields\n                  case N => N -> nFields\n                }\n                LhsRefined(res, tts, rcd.copy(nfs)(rcd.prov).sorted, trs2).toType(sort = true)\n            }\n          case LhsTop => TopType\n        }, {\n          case RhsBot => BotType\n          case RhsField(n, t) => RecordType(n -> t.update(go(_, pol.map(!_)), go(_, pol)) :: Nil)(noProv)\n          case RhsBases(ots, rest, trs) =>\n            // Note: could recosntruct class tags for these, but it would be pretty verbose,\n            //    as in showing `T & ~C[?] & ~D[?, ?]` instead of just `T & ~c & ~d`\n            // ots.map { case t @ (_: ClassTag | _: TraitTag) => ... }\n            val r = rest match {\n              case v @ S(R(RhsField(n, t))) => RhsField(n, t.update(go(_, pol.map(!_)), go(_, pol))).toType(sort = true)\n              case v @ S(L(bty)) => go(bty, pol)\n              case N => BotType\n            }\n            trs.valuesIterator.map(go(_, pol)).foldLeft(BotType: ST)(_ | _) |\n            ots.sorted.foldLeft(r)(_ | _)\n        }, sort = true)\n      }.foldLeft(BotType: ST)(_ | _) |> factorize(ctx)\n      val res = otherCs2 | csNegs2\n      val cons = dnf.cons.map { case (lo,hi) => (go(lo,S(true)), go(hi,S(false))) }\n      val base = ConstrainedType.mk(cons, res)\n      canDistribForall match {\n        case S(outerLvl) if distributeForalls =>\n          implicit val ctx: Ctx = _ctx.copy(lvl = outerLvl + 1)\n          PolymorphicType(dnf.polymLevel, base).instantiate\n        case _ => PolymorphicType.mk(dnf.polymLevel, base)\n      }\n    }\n    \n    def goLike(ty: TL, pol: Opt[Bool], canDistribForall: Opt[Level] = N): TL = trace(s\"normLike[${printPol(pol)}] $ty\") { ty match {\n      case ty: ST => go(ty, pol)\n      case OtherTypeLike(tu) => tu.mapPol(pol, true)((p, t) => go(t, p))\n    }}()\n    def go(ty: ST, pol: Opt[Bool], canDistribForall: Opt[Level] = N): ST = trace(s\"norm[${printPol(pol)}] $ty\") {\n      pol match {\n        case S(p) => helper(DNF.mk(MaxLevel, Nil, ty, p)(ctx, ptr = true, etf = false), pol, canDistribForall)\n        case N =>\n          val dnf1 = DNF.mk(MaxLevel, Nil, ty, false)(ctx, ptr = true, etf = false)\n          val dnf2 = DNF.mk(MaxLevel, Nil, ty, true)(ctx, ptr = true, etf = false)\n          TypeBounds.mk(helper(dnf1, S(false), canDistribForall), helper(dnf2, S(true), canDistribForall))\n      }\n    }(r => s\"~> $r\")\n    \n    def processVar(tv: TV): Unit = {\n      processed.setAndIfUnset(tv) {\n        tv.assignedTo match {\n          case S(ty) =>\n            tv.assignedTo = S(go(ty, N))\n          case N =>\n            // tv.lowerBounds = tv.lowerBounds.map(go(_, S(true)))\n            // tv.upperBounds = tv.upperBounds.map(go(_, S(false)))\n            tv.lowerBounds = tv.lowerBounds.reduceOption(_ | _).fold(nil[ST])(go(_, S(true)) :: Nil)\n            tv.upperBounds = tv.upperBounds.reduceOption(_ & _).fold(nil[ST])(go(_, S(false)) :: Nil)\n        }\n      }\n    }\n    \n    goLike(st, pol)\n    \n  }\n  \n  \n  \n  /** Remove polar type variables, unify indistinguishable ones, and inline the bounds of non-recursive ones. */\n  def simplifyType(st: TypeLike, removePolarVars: Bool, pol: Opt[Bool], inlineBounds: Bool = true)(implicit ctx: Ctx): TypeLike = {\n    \n    \n    // * There are two main analyses, which are quite subtle.\n    // * TODO: add assertion to check that their results are consistent!\n    \n    \n    // * * Analysis 1: count number of TV occurrences at each polarity\n    // *  and find whether they're used in invariant positions\n    // *  (in which case we won't inline their bounds, to avoid producing ugly type intervals in the final result).\n    \n    val occNums: MutMap[(Bool, TypeVariable), Int] = LinkedHashMap.empty[(Bool, TypeVariable), Int].withDefaultValue(0)\n    val occursInvariantly = MutSet.empty[TV]\n    \n    val analyzed1 = MutSet.empty[PolarVariable]\n    \n    // * Note: it is important here to make sure the interpretation of invariant position\n    // *    coincides with that of the later `transform` function.\n    // *  In particular, the traversal of fields with identical UB/LB is considered invariant.\n    object Analyze1 extends Traverser2.InvariantFields {\n      override def apply(pol: PolMap)(st: ST): Unit = trace(s\"analyze1[${(pol)}] $st\") {\n        st match {\n          case tv: TV =>\n            pol(tv) match {\n              case S(pol) =>\n                occNums(pol -> tv) += 1\n              case N =>\n                occursInvariantly += tv\n                occNums(true -> tv) += 1\n                occNums(false -> tv) += 1\n            }\n            tv.assignedTo match {\n              case S(ty) =>\n                // * This is quite subtle!\n                // * We should traverse assigned type variables as though they weren't there,\n                // * but they may appear in their own assignment,\n                // * so we still need to check they haven't been traversed yet.\n                // * Moreover, traversing them at different polarities may produce different results\n                // * (think of `'A# -> 'A#` where 'A# := 'X`),\n                // * so we should remember the traversal polarity in the cache.\n                // * Thanks to the invariant that the assignment shouldn't have a higher level than\n                // * the type variable itself, I think it is fine to never re-traverse the assignment\n                // * at the same polarity *even though the polmap may be different*.\n                analyzed1.setAndIfUnset(tv -> pol(tv).getOrElse(false)) { apply(pol)(ty) }\n              case N =>\n                if (pol(tv) =/= S(false))\n                  analyzed1.setAndIfUnset(tv -> true) {\n                    tv.lowerBounds.foreach(apply(pol.at(tv.level, true)))\n                    if (noApproximateOverload)\n                      tv.tsc.keys.flatMap(_.tvs).foreach(u => apply(pol.at(tv.level,u._1))(u._2))\n                  }\n                if (pol(tv) =/= S(true))\n                  analyzed1.setAndIfUnset(tv -> false) {\n                    tv.upperBounds.foreach(apply(pol.at(tv.level, false)))\n                    if (noApproximateOverload)\n                      tv.tsc.keys.flatMap(_.tvs).foreach(u => apply(pol.at(tv.level,u._1))(u._2))\n                  }\n            }\n          case _ =>\n            super.apply(pol)(st)\n        }\n      }()\n    }\n    Analyze1.applyLike(PolMap(pol))(st)\n    \n    println(s\"[inv] ${occursInvariantly.mkString(\", \")}\")\n    println(s\"[nums] ${occNums.iterator\n      .map(occ => s\"${printPol(S(occ._1._1))}${occ._1._2} ${occ._2}\")\n      .mkString(\" ; \")\n    }\")\n    \n    \n    \n    // * * Analysis 2: find the polar co-occurrences of each TV\n    \n    // * Note: for negatively-quantified vars, the notion of co-occurrence is reversed (wrt unions/inters)...\n    \n    val coOccurrences: MutMap[(Bool, TypeVariable), LinkedHashSet[SimpleType]] = MutMap.empty\n    \n    // * Remember which TVs we analyzed at which polarity\n    val analyzed2 = MutSet.empty[Bool -> ST]\n    // * The above is not enough. Sometimes we want to analyze a group of bounds and co-occurring types altogether.\n    // * However, the TV component of these types may have polarities that change depending on the context!\n    // * So we can't just assign a polarity to th ewhole thing...\n    // * Instead, we remember the polarities of each of these type subexpressions.\n    val analyzed22 = MutSet.empty[Set[Opt[Bool] -> ST]]\n    \n    \n    // **********************\n    // * An alternative approach that tries to learn more co-occurrence info by\n    // * accumulating the effective bounds on type vriables\n    // * (ie including those not specified in the TV itself).\n    // * Commented because this still needs work before it can be used (Q: should it be?).\n    // **********************\n    /*\n    val lbs, ubs = MutMap.empty[TV, MutSet[ST]]\n    def getLbs(tv: TV) = lbs.getOrElseUpdate(tv, MutSet.empty)\n    def getUbs(tv: TV) = ubs.getOrElseUpdate(tv, MutSet.empty)\n    \n    def getBounds(ty: ST, pol: Bool): Set[ST] = {\n      val traversed = MutSet.empty[TV]\n      def go(ty: ST): Set[ST] = ty.unwrapProxies match { // TODO(later) guard against bad rec types?\n        case tv2: TV =>\n          if (traversed.add(tv2)) tv2.assignedTo match {\n            case S(ty2) => go(ty2) + tv2\n            case N =>\n              Set.single(tv2) ++\n                (if (pol) tv2.lowerBounds else tv2.upperBounds).iterator.flatMap(go)\n          } else Set.empty\n        case ComposedType(p, l, r) =>\n          if (p === pol) go(l) ++ go(r)\n          else Set.single(ty) ++ (go(l) & go(r))\n        case _ => Set.single(ty)\n      }\n      go(ty)\n    }\n    analyzed1.foreach { case (tv, pol) =>\n      val bs = getBounds(tv, pol)\n      println(tv,pol,bs)\n      (if (pol) getLbs(tv) else getUbs(tv)) ++= bs.iterator.filterNot(_ is tv)\n      bs.foreach {\n        case tv2: TV if tv2 isnt tv =>\n          (if (pol) getUbs(tv2) else getLbs(tv2)) += tv\n        case _ =>\n      }\n    }\n    println(s\"Bounds:\")\n    s\"${lbs.foreach { case (tv, bs) =>\n      println(s\" $tv\")\n      bs.foreach(b => println(s\"\\t:> $b\"))\n    }}\"\n    s\"${ubs.foreach { case (tv, bs) =>\n      println(s\" $tv\")\n      bs.foreach(b => println(s\"\\t<: $b\"))\n    }}\"\n    */\n    \n    \n    // FIXME Currently we don't traverse TVs witht he correct PolMap, which introduces misatches with other analyses in tricky cases\n    def analyze2(st: TL, pol: PolMap): Unit =\n      Analyze2.applyLike(pol)(st.unwrapProvs)\n    \n    object Analyze2 extends Traverser2 {\n      override def apply(pol: PolMap)(st: ST): Unit = trace(s\"analyze2[${(pol)}] $st\") {\n          st match {\n            case tv: TypeVariable =>\n              pol(tv) match {\n                case S(pol_tv) =>\n                  if (analyzed2.add(pol_tv -> tv)) {\n                    processImpl(st, pol, pol_tv)\n                    if (noApproximateOverload)\n                      tv.tsc.keys.flatMap(_.tvs).foreach(u => processImpl(u._2,pol.at(tv.level,u._1),pol_tv))\n                  }\n                case N =>\n                  if (analyzed2.add(true -> tv))\n                    // * To compute the positive co-occurrences\n                    processImpl(st, pol.at(tv.level, true), true)\n                  if (analyzed2.add(false -> tv))\n                    // * To compute the negative positive co-occurrences\n                    processImpl(st, pol.at(tv.level, false), false)\n                  \n              }\n            case ct: ComposedType =>\n                def getComponents(ty: ST): Set[Opt[Bool] -> ST] = ty.unwrapProxies match {\n                  case tv: TV => Set.single(pol(tv) -> tv)\n                  case ty @ ComposedType(p, l, r) =>\n                    if (p === ct.pol) getComponents(l) ++ getComponents(r)\n                    else Set.single(N -> ty)\n                  case _ => Set.single(N -> ty)\n                }\n              val comps = getComponents(ct)\n              println(s\"Components $comps\")\n              if (analyzed22.add(comps))\n                processImpl(st, pol, ct.pol)\n              else println(s\"Found in $analyzed22\")\n            case _ =>\n              super.apply(pol)(st)\n          }\n      }()\n    }\n    \n    def processImpl(st: SimpleType, pol: PolMap, occPol: Bool) = {\n      val newOccs = LinkedHashSet.empty[SimpleType]\n      \n      println(s\">> Processing $st at [${printPol(S(occPol))}]\")\n      \n      def go(ty: ST): Unit =\n          trace(s\"go $ty   (${newOccs.mkString(\", \")})\") {\n            ty.unwrapProxies match {\n        case tv2: TV =>\n          // println(s\"${printPol(pol(tv2))}$tv2\")\n          if (newOccs.add(tv2)) tv2.assignedTo match {\n            case S(ty2) => go(ty2)\n            case N =>\n              pol(tv2) match {\n                case S(p) =>\n                  (if (p) tv2.lowerBounds else tv2.upperBounds).foreach(go)\n                  // (if (p) getLbs(tv2) else getUbs(tv2)).foreach(go)\n                  if (noApproximateOverload) tv2.tsc.keys.flatMap(_.tvs).foreach(u => go(u._2))\n                case N =>\n                  trace(s\"Analyzing invar-occ of $tv2\") {\n                    analyze2(tv2, pol)\n                  }()\n              }\n          }\n        case ComposedType(p, l, r) if p === occPol => go(l); go(r)\n        case _ => newOccs += ty; ()\n      }}()\n      go(st)\n      \n      println(s\">> Occurrences $newOccs\")\n      newOccs.foreach {\n        case tv: TypeVariable =>\n          def occ(pol: Bool): Unit = {\n            val occs = if (pol === occPol) newOccs else MutSet.single[ST](tv)\n            println(s\">>>> occs[${printPol(pol)}$tv] := $occs  <~ ${coOccurrences.get(pol -> tv)}\")\n            coOccurrences.get(pol -> tv) match {\n              case Some(os) =>\n                // Q: filter out vars of different level?\n                os.filterInPlace(occs) // computes the intersection\n              case None => coOccurrences(pol -> tv) = LinkedHashSet.from(occs) // copy not needed?\n            }\n          }\n          pol(tv) match {\n            case S(p) =>\n              occ(p)\n            case N =>\n              occ(true)\n              occ(false)\n          }\n        case _ => ()\n      }\n      newOccs.foreach {\n        case tv: TypeVariable => ()\n        case ty => analyze2(ty, pol)\n      }\n    }\n    \n    analyze2(st, PolMap(pol))\n    \n    \n    coOccurrences.foreach(kv => assert(kv._2.nonEmpty))\n    \n    println(s\"[occs] ${coOccurrences.iterator\n      .map(occ => s\"${printPol(S(occ._1._1))}${occ._1._2} ${occ._2.mkString(\"{\",\",\",\"}\")}\")\n      .mkString(\" ; \")\n    }\")\n    \n    \n    \n    // * * Processing: decide what type variables to remove/unify/inline bounds of.\n    // * NOTE: This phase logically unifies type variables by merging their bounds and co-occurrence reults.\n    // *  In particular, it may change the recursive-ness of type variables!\n    // *  (We may unfy a non-rec TV with a rec one, makingthe non-rec TV recursive.)\n    \n    // * This will be filled during the processing phase, to guide the transformation phase:\n    val varSubst = MutMap.empty[TypeVariable, Option[ST]]\n    \n    // val allVars = st.getVars\n    val allVars = analyzed1.iterator.map(_._1).toSortedSet\n    \n    def computeRecVars =\n      allVars.iterator.filter(v => !varSubst.contains(v) && (\n        v.isRecursive_$(omitIrrelevantVars = false)\n        // * Note: a more precise version could be the following,\n        // * but it doesn't seem to change anything in our test suite, so I left if commented for now:\n        // // * Only consider recursive those variables that recursive in their *reachable* bounds:\n        // occNums.contains(true -> v) && v.isPosRecursive_$(false) || occNums.contains(false -> v) && v.isNegRecursive_$(false)\n      )).toSet\n    \n    var recVars = computeRecVars\n    \n    println(s\"[vars] ${allVars}\")\n    println(s\"[rec] ${recVars}\")\n    // println(s\"[bounds] ${st.showBounds}\")\n    \n    // * Remove polar type variables that only occur once, including if they are part of a recursive bounds graph:\n    if (inlineBounds) occNums.iterator.foreach { case (k @ (pol, tv), num) =>\n      assert(num > 0)\n      if (num === 1 && !occNums.contains(!pol -> tv)) {\n        println(s\"0[1] $tv\")\n        varSubst += tv -> None\n      }\n    }\n    \n    // * Simplify away those non-recursive variables that only occur in positive or negative positions\n    // *  (i.e., polar ones):\n    allVars.foreach { case v0 => if (!recVars.contains(v0)) {\n      (coOccurrences.get(true -> v0), coOccurrences.get(false -> v0)) match {\n        case (Some(_), None) | (None, Some(_)) =>\n          println(s\"1[!] $v0\")\n          varSubst += v0 -> None\n        case occ => assert(occ =/= (None, None), s\"$v0 has no occurrences...\")\n      }\n    }}\n    \n    // * Remove variables that are 'dominated' by another type or variable\n    // *  A variable v dominated by T if T is in both of v's positive and negative cooccurrences\n    allVars.foreach { case v => if (v.assignedTo.isEmpty && !varSubst.contains(v) && v.tsc.isEmpty) {\n      println(s\"2[v] $v ${coOccurrences.get(true -> v)} ${coOccurrences.get(false -> v)}\")\n      \n      coOccurrences.get(true -> v).iterator.flatMap(_.iterator).foreach {\n        \n        case atom @ (_: BaseType | _: TypeRef)\n          if !recVars(v) // can't reduce recursive sandwiches, obviously\n          && coOccurrences.get(false -> v).exists(_(atom))\n        =>\n          val bundle = TypeBounds.mkSafe(\n              v.upperBounds.foldLeft(atom)(_ &- _),\n              v.lowerBounds.foldLeft(atom)(_ | _),\n            )\n          println(s\"  [..] $v := ${bundle}\")\n          varSubst += v -> S(bundle)\n        \n        case w: TV if !(w is v) && !varSubst.contains(w) && !varSubst.contains(v) && !recVars(v)\n          && coOccurrences.get(false -> v).exists(_(w))\n          && w.tsc.isEmpty\n        =>\n          // * Here we know that v is 'dominated' by w, so v can be inlined.\n          // * Note that we don't want to unify the two variables here\n          // *  – if v has bounds and does not dominate w, then doing so would be wrong.\n          \n          // * Logic to preserve name hints, but seems overkill and did not seem to have any effect so far:\n          // if (coOccurrences.get(true -> w).exists(_(v)) && coOccurrences.get(false -> w).exists(_(v)) && v.nameHint.nonEmpty && !recVars(w)) {\n          //   println(s\"  [..] $w ${v}\")\n          //   varSubst += w -> N\n          // } else {\n          \n          val bundle = TypeBounds.mkSafe(\n              v.upperBounds.foldLeft(w: ST)(_ &- _),\n              v.lowerBounds.foldLeft(w: ST)(_ | _),\n            )\n          println(s\"  [..] $v := ${bundle}\")\n          varSubst += v -> S(bundle)\n          \n          // }\n          \n        case _ =>\n      }\n    }}\n    \n    // * Unify equivalent variables based on polar co-occurrence analysis:\n    allVars.foreach { case v =>\n      if (!v.assignedTo.isDefined && !varSubst.contains(v) && v.tsc.isEmpty) // TODO also handle v.assignedTo.isDefined?\n        trace(s\"3[v] $v +${coOccurrences.get(true -> v).mkString} -${coOccurrences.get(false -> v).mkString}\") {\n        \n        def go(pol: Bool): Unit = coOccurrences.get(pol -> v).iterator.flatMap(_.iterator).foreach {\n          \n          case w: TypeVariable if !(w is v) && !w.assignedTo.isDefined && !varSubst.contains(w) //&& (if (pol) )\n              // && (recVars.contains(v) === recVars.contains(w))\n              // * ^ Note: We no longer avoid merging rec and non-rec vars,\n              // *    even though the non-rec one may not be strictly polar (as an example of this, see [test:T1]).\n              // *    We may introduce recursive types anyway so the `recVars` info here is no longer up to date.\n              && (v.nameHint.nonEmpty || w.nameHint.isEmpty\n              // * ^ Don't merge in this direction if that would override a nameHint\n                || varSubst.contains(v) // * we won't be able to do it the other way\n                // || varSubst.contains(v)\n              )\n              && (v.level === w.level)\n              // ^ Don't merge variables of differing levels\n              && w.tsc.isEmpty\n            =>\n            trace(s\"[w] $w ${printPol(S(pol))}${coOccurrences.get(pol -> w).mkString}\") {\n              \n              // * The bounds opposite to the polarity where the two variables co-occur\n              // * We don't want to merge variables when this would introduce\n              val otherBounds = (if (pol) v.upperBounds else v.lowerBounds)\n              val otherBounds2 = (if (pol) w.upperBounds else w.lowerBounds)\n              \n              // if (otherBounds =/= otherBounds2)\n              if (otherBounds.toSet =/= otherBounds2.toSet)\n                // * ^ This is a bit of an ugly heuristic to simplify a couple of niche situations...\n                // *    More principled/regular approaches could be to either:\n                // *      1. just not merge things with other bounds; or\n                // *      2. merge non-recursive things with other bounds but be more careful in the `transform` part\n                // *        that we don't import these other bounds when inlining bounds...\n                // *    Choice (2.) seems tricky to implement.\n                println(s\"$v and $w have non-equal other bounds and won't be merged\")\n              else if (coOccurrences.get(pol -> w).forall(_(v))) {\n                \n                // * Unify w into v\n                \n                println(s\"  [U] $w := $v\")\n                \n                varSubst += w -> S(v)\n                \n                // * Since w gets unified with v, we need to merge their bounds,\n                // * and also merge the other co-occurrences of v and w from the other polarity (!pol).\n                // * For instance,\n                // *  consider that if we merge v and w in `(v & w) -> v & x -> w -> x`\n                // *  we get `v -> v & x -> v -> x`\n                // *  and the old positive co-occ of v, {v,x} should be changed to just {v,x} & {w,v} == {v}!\n                v.lowerBounds :::= w.lowerBounds\n                v.upperBounds :::= w.upperBounds\n                \n                // TODO when we have `assignedTo` use that instead here?\n                w.lowerBounds = v :: Nil\n                w.upperBounds = v :: Nil\n                \n                // * When removePolarVars is enabled, wCoOcss/vCoOcss may not be defined:\n                coOccurrences.get((!pol) -> w).foreach { wCoOccs =>\n                  coOccurrences.get((!pol) -> v) match {\n                    case S(vCoOccs) => vCoOccs.filterInPlace(t => t === v || wCoOccs(t))\n                    case N => coOccurrences((!pol) -> v) = wCoOccs\n                  }\n                }\n                \n              }\n              \n            }()\n            \n          case _ =>\n          \n        }\n        \n        go(true)\n        go(false)\n        \n      }()\n    }\n    \n    println(s\"[sub] ${varSubst.map(k => k._1.toString + \" -> \" + k._2).mkString(\", \")}\")\n    println(s\"[bounds] ${st.showBounds}\")\n    \n    \n    \n    // * * Transformation: transform the type recursively,\n    // * applying the var substitution and simplifying some things on the fly.\n    \n    // * The recursive vars may have changed due to the previous phase!\n    recVars = computeRecVars\n    println(s\"[rec] ${recVars}\")\n    \n    val renewals = MutMap.empty[TypeVariable, TypeVariable]\n    val renewaltsc = MutMap.empty[TupleSetConstraints, TupleSetConstraints]\n    \n    val semp = Set.empty[TV]\n    \n    def mergeTransform(pol: Bool, polmap: PolMap, tv: TV, parents: Set[TV], canDistribForall: Opt[Level]): ST =\n      transform(tv.assignedTo match {\n        case S(ty) => ty\n        case N => merge(pol, if (pol) tv.lowerBounds else tv.upperBounds)\n      }, polmap.at(tv.level, pol), parents, canDistribForall)\n    \n    def transformLike(ty: TL, pol: PolMap): TL = ty match {\n      case ty: ST => transform(ty, pol, semp)\n      case OtherTypeLike(tu) => tu.mapPolMap(pol)((p,t) => transform(t, p, semp))\n    }\n    def transform(st: SimpleType, pol: PolMap, parents: Set[TV], canDistribForall: Opt[Level] = N): SimpleType =\n          trace(s\"transform[${printPol(pol)}] $st   (${parents.mkString(\", \")})  $pol  $canDistribForall\") {\n        def transformField(f: FieldType): FieldType = f match {\n          case FieldType(S(lb), ub) if lb === ub =>\n            val b = transform(ub, pol.invar, semp)\n            FieldType(S(b), b)(f.prov)\n          case _ => f.update(transform(_, pol.contravar, semp), transform(_, pol, semp))\n        }\n        st match {\n      case RecordType(fs) => RecordType(fs.mapValues(_ |> transformField))(st.prov)\n      case TupleType(fs) => TupleType(fs.mapValues(_ |> transformField))(st.prov)\n      case ArrayType(inner) => ArrayType(inner |> transformField)(st.prov)\n      case sp @ SpliceType(elems) => SpliceType(elems map {\n        case L(l) => L(transform(l, pol, semp)) \n        case R(r) => R(transformField(r))})(st.prov)\n      case FunctionType(l, r) =>\n        FunctionType(transform(l, pol.contravar, semp),\n          transform(r, pol, semp, canDistribForall))(st.prov)\n      case ot @ Overload(as) =>\n        ot.mapAltsPol(pol)((p, t) => transform(t, p, parents, canDistribForall))\n      case SkolemTag(id) => transform(id, pol, parents)\n      case _: ObjectTag | _: Extruded | _: ExtrType => st\n      case tv: TypeVariable if parents(tv) =>\n        pol(tv) match {\n          case S(true) => BotType\n          case S(false) => TopType\n          case N => transform(tv, pol, parents - tv)\n        }\n      case tv: TypeVariable =>\n        varSubst.get(tv) match {\n          case S(S(tv2)) =>\n            println(s\"-> $tv2\")\n            transform(tv2, pol, parents + tv, canDistribForall)\n          case S(N) =>\n            println(s\"-> bound ${pol(tv)}\")\n            val p = pol(tv)\n            if (!removePolarVars && (\n                   tv.lowerBounds.isEmpty && p.contains(true)\n                || tv.upperBounds.isEmpty && p.contains(false)\n                || tv.lowerBounds.isEmpty && tv.upperBounds.isEmpty\n            )) ClassTag(Var(\"?\"), Set.empty)(noProv)\n            else p.fold {\n              // TypeBounds.mk(mergeTransform(true, tv, parents + tv), mergeTransform(false, tv, parents + tv)) // FIXME polarities seem inverted\n              lastWords(\"Should not be replacing an invariant type variable by its bound...\") // ?\n              pol.quantifPolarity(tv.level).base match {\n                case S(true) =>\n                  TypeBounds.mkSafe(mergeTransform(false, pol, tv, parents + tv, canDistribForall),\n                    mergeTransform(true, pol, tv, parents + tv, canDistribForall))\n                case S(false) =>\n                  TypeBounds.mkSafe(mergeTransform(true, pol, tv, parents + tv, canDistribForall),\n                    mergeTransform(false, pol, tv, parents + tv, canDistribForall))\n                case N => ???\n              }\n            }(mergeTransform(_, pol, tv, parents + tv, canDistribForall))\n          case N =>\n            var wasDefined = true\n            val res = renewals.getOrElseUpdate(tv, {\n              wasDefined = false\n              val nv = freshVar(noProv, S(tv), tv.nameHint)(tv.level)\n              println(s\"Renewed $tv ~> $nv\")\n              nv\n            })\n            pol(tv) match {\n              case S(p) if inlineBounds && !occursInvariantly(tv) && !recVars.contains(tv) && tv.tsc.isEmpty =>\n                // * Inline the bounds of non-rec non-invar-occ type variables\n                println(s\"Inlining [${printPol(p)}] bounds of $tv (~> $res)\")\n                // if (p) mergeTransform(true, pol, tv, Set.single(tv), canDistribForall) | res\n                // else mergeTransform(false, pol, tv, Set.single(tv), canDistribForall) & res\n                if (p) mergeTransform(true, pol, tv, parents + tv, canDistribForall) | res\n                else mergeTransform(false, pol, tv, parents + tv, canDistribForall) & res\n              case poltv if (!wasDefined) =>\n                def setBounds = {\n                  trace(s\"Setting [±] bounds of $res... (failing ${printPol(poltv)}, inlineBounds $inlineBounds, !occursInvariantly ${!occursInvariantly(tv)}, !recVars.contains(tv) ${!recVars.contains(tv)})\") {\n                    tv.assignedTo match {\n                      case S(ty) =>\n                        res.assignedTo = S(transform(ty, pol.invar, semp, canDistribForall))\n                      case N =>\n                        if (occNums.contains(true -> tv))\n                          res.lowerBounds = tv.lowerBounds.map(transform(_, pol.at(tv.level, true), Set.single(tv)))\n                        if (occNums.contains(false -> tv))\n                          res.upperBounds = tv.upperBounds.map(transform(_, pol.at(tv.level, false), Set.single(tv)))\n                        if (noApproximateOverload)\n                          res.tsc ++= tv.tsc.map { case (tsc, i) => renewaltsc.get(tsc) match {\n                            case S(tsc) => (tsc, i)\n                            case N =>\n                              val t = new TupleSetConstraints(tsc.constraints, tsc.tvs)\n                              renewaltsc += tsc -> t\n                              t.tvs = t.tvs.map(x => (x._1, transform(x._2, PolMap.neu, Set.empty)))\n                              (t, i)\n                          }}\n                    }\n                    res\n                  }()\n                }\n                poltv match {\n                  case polo @ S(p)\n                    if !coOccurrences.contains(!p -> tv) // * If tv is polar...\n                    && tv.assignedTo.isEmpty // TODO handle?\n                  =>\n                    val bounds = if (p) tv.lowerBounds else tv.upperBounds\n                    \n                    // * only true if we do a pass of `removeIrrelevantBounds` before calling `simplifyType`:\n                    // assert(tv.lowerBounds.isEmpty || tv.upperBounds.isEmpty, (tv, tv.lowerBounds, tv.upperBounds))\n                    \n                    // println(s\">?> $tv $res $bounds ${tv.lowerBounds} ${tv.upperBounds}\")\n                    \n                    if (bounds.forall { // * If tv only has type variables as upper bounds, inline it\n                      case tv2: TV => varSubst.get(tv2).forall(_.isDefined)\n                      case _ => false\n                    }) {\n                      println(s\"NEW SUBS $tv -> N\")\n                      varSubst += tv -> N\n                      transform(merge(p, bounds), pol, parents + tv, canDistribForall)\n                    }\n                    else setBounds\n                  case _ => setBounds\n                }\n              case _ => res\n            }\n        }\n      case ty @ ComposedType(true, l, r) =>\n        transform(l, pol, parents, canDistribForall) | transform(r, pol, parents, canDistribForall)\n      case ty @ ComposedType(false, l, r) =>\n        transform(l, pol, parents, canDistribForall) & transform(r, pol, parents, canDistribForall)\n      case NegType(und) => transform(und, pol.contravar, semp).neg()\n      case WithType(base, RecordType(fs)) => WithType(transform(base, pol, semp, canDistribForall), \n        RecordType(fs.mapValues(_.update(transform(_, pol.contravar, semp), transform(_, pol, semp))))(noProv))(noProv)\n      case ProxyType(underlying) => transform(underlying, pol, parents, canDistribForall)\n      case tr @ TypeRef(defn, targs) =>\n        TypeRef(defn, tr.mapTargs(pol)((pol, ty) => transform(ty, pol, semp)))(tr.prov)\n      case wo @ Without(base, names) =>\n        if (names.isEmpty) transform(base, pol, semp, canDistribForall)\n        else if (pol.base === S(true)) transform(base, pol, semp, canDistribForall).withoutPos(names)\n        else transform(base, pol, semp, canDistribForall).without(names)\n      case tb @ TypeBounds(lb, ub) =>\n        pol.base.fold[ST](TypeBounds.mkSafe(\n          transform(lb, PolMap.neg, parents, canDistribForall),\n          transform(ub, PolMap.pos, parents, canDistribForall),\n          // transform(lb, pol, parents, canDistribForall),\n          // transform(ub, pol, parents, canDistribForall),\n          // transform(lb, pol.contravar, parents, canDistribForall),\n          // transform(ub, pol.covar, parents, canDistribForall),\n          noProv\n        ))(p =>\n          if (p) transform(ub, pol, parents) else transform(lb, pol, parents)\n        )\n      case PolymorphicType(plvl, bod) =>\n        val res = transform(bod, pol.enter(plvl), parents, canDistribForall = S(plvl))\n        canDistribForall match {\n          case S(outerLvl) if distributeForalls =>\n            ctx.copy(lvl = outerLvl + 1) |> { implicit ctx =>\n              PolymorphicType(plvl, res).instantiate\n            }\n          case _ =>\n            PolymorphicType.mk(plvl, res)\n        }\n      case ConstrainedType(cs, bod) =>\n        ConstrainedType(\n          cs.map { case (lo, hi) =>\n            (transform(lo, PolMap.pos, semp), transform(hi, PolMap.posAtNeg, semp))\n          },\n          transform(bod, pol, parents)\n        )\n    }\n    }(r => s\"~> $r\")\n    \n    transformLike(st, PolMap(pol))\n    \n    \n  }\n  \n  \n  \n  /** Remove recursive types that have 'skidded' across several type variables\n    *   due to the (crucially important) type variable bounds propagation logic of the constraint solver.\n    * For example, when `?a :> ?b` and we constrain `?a <! {x: ?a}`, we will end up registering `?b <! {x: ?a}`.\n    * So if no other upper bounds end up in ?a AND ?a is polar\n    *   (so that ?a occurrences are indistinguishable from `{x: ?a}`),\n    *   we'll eventually want to refactor ?b's recursive upper bound structure into just `?b <! ?a`. */\n  def unskidTypes_!(st: TypeLike, pol: Bool)(implicit ctx: Ctx): TypeLike = {\n    \n    val allVarPols = st.getVarsPol(PolMap(S(pol)))\n    println(s\"allVarPols: ${printPols(allVarPols)}\")\n    \n    val processed = MutSet.empty[TV]\n    \n    // TODO improve: map values should actually be lists as several TVs may have an identical bound\n    val consed = allVarPols.iterator.collect {\n      case (tv @ AssignedVariable(ty), S(pol)) =>\n        if (pol) (true, ty) -> tv\n        else (false, ty) -> tv\n      case (tv, S(pol)) =>\n        if (pol) (true, tv.lowerBounds.foldLeft(BotType: ST)(_ | _)) -> tv\n        else (false, tv.upperBounds.foldLeft(TopType: ST)(_ &- _)) -> tv\n    }.filter { case ((pol, bnd), tv) => bnd.getVarsImpl(includeBounds = false).contains(tv) }.toMap\n    \n    println(s\"consed: $consed\")\n    \n    // * Q: shouldn't this use a PolMap instead?\n    // * It should actually be sound not to, though, as the handling is symmetric...\n    def process(pol: Opt[Bool], st: ST, parent: Opt[TV]): ST =\n        // trace(s\"cons[${printPol(pol)}] $st\") {\n          st.unwrapProvs match {\n      case tv @ AssignedVariable(ty) =>\n        processed.setAndIfUnset(tv) {\n          // tv.assignedTo = S(process(pol, ty, S(tv))) // * WRONG!\n          tv.assignedTo = S(process(N, ty, S(tv)))\n        }\n        tv\n      case tv: TV =>\n        processed.setAndIfUnset(tv) {\n          tv.lowerBounds = tv.lowerBounds.map(process(S(true), _, S(tv)))\n          tv.upperBounds = tv.upperBounds.map(process(S(false), _, S(tv)))\n        }\n        tv\n      case _ =>\n        lazy val mapped = st.mapPol(pol, smart = true)(process(_, _, parent))\n        // println(s\"mapped $mapped\")\n        pol match {\n          case S(p) =>\n            // println(s\"!1! ${st} ${consed.get(p -> st)}\")\n            consed.get(p -> st) match {\n              case S(tv) if parent.forall(_ isnt tv) =>\n                println(s\"!unskid-1! ${st} -> $tv\")\n                process(pol, tv, parent)\n              case _ =>\n                // println(s\"!2! ${mapped} ${consed.get(p -> mapped)}\")\n                consed.get(p -> mapped) match {\n                  case S(tv) if parent.forall(_ isnt tv) =>\n                    println(s\"!unskid-2! ${mapped} -> $tv\")\n                    process(pol, tv, parent)\n                  case _ => mapped\n                }\n            }\n          case N => mapped\n        }\n    }\n    // }(r => s\"~> $r\")\n    \n    def processLike(pol: Opt[Bool], ty: TL): TL = ty match {\n      case ty: ST => process(pol, ty, N)\n      case OtherTypeLike(tu) => tu.mapPol(pol, smart = true)(process(_, _, N))\n    }\n    \n    processLike(S(pol), st)\n  }\n  \n  \n  \n  /** Unify polar recursive type variables that have the same structure.\n    * For example, `?a <: {x: ?a}` and `?b <: {x: ?b}` will be unified if they are bith polar. */\n  def factorRecursiveTypes_!(st: TypeLike, approximateRecTypes: Bool, pol: Opt[Bool])(implicit ctx: Ctx): TypeLike = {\n    \n    val allVarPols = st.getVarsPol(PolMap(pol))\n    println(s\"allVarPols: ${printPols(allVarPols)}\")\n    \n    val processed = MutSet.empty[TV]\n    \n    val varSubst = MutMap.empty[TV, TV]\n    \n    allVarPols.foreach {\n      case (tv1, S(p1)) =>\n        println(s\"Consider $tv1\")\n        (tv1.assignedTo.map(_::Nil).getOrElse(if (p1) tv1.lowerBounds else tv1.upperBounds)) match {\n          case b1 :: Nil => \n            allVarPols.foreach {\n              case (tv2, S(p2)) if p2 === p1 && (tv2 isnt tv1) && !varSubst.contains(tv1) && !varSubst.contains(tv2) =>\n                (tv2.assignedTo.map(_::Nil).getOrElse(if (p2) tv2.lowerBounds else tv2.upperBounds)) match {\n                  case b2 :: Nil =>\n                    \n                    // TODO could be smarter, using sets of assumed equalities instead of just one:\n                    def unify(ty1: ST, ty2: ST): Bool = {\n                      \n                      def nope: false = { println(s\"Nope(${ty1.getClass.getSimpleName}): $ty1 ~ $ty2\"); false }\n                      \n                      def unifyF(f1: FieldType, f2: FieldType): Bool = (f1, f2) match {\n                        case (FieldType(S(l1), u1), FieldType(S(l2), u2)) => unify(l1, l2) && unify(u1, u2)\n                        case (FieldType(N, u1), FieldType(N, u2)) => unify(u1, u2)\n                        case _ => nope\n                      }\n                      \n                      (ty1, ty2) match {\n                        case (`tv1`, `tv2`) | (`tv2`, `tv1`) => true\n                        case (v1: TypeVariable, v2: TypeVariable) => (v1 is v2) || nope\n                        case (NegType(negated1), NegType(negated2)) => unify(negated1, negated2)\n                        case (ClassTag(id1, parents1), ClassTag(id2, parents2)) => id1 === id2 || nope\n                        case (ArrayType(inner1), ArrayType(inner2)) => unifyF(inner1, inner2)\n                        case (TupleType(fields1), TupleType(fields2)) =>\n                          (fields1.size === fields2.size || nope) && fields1.map(_._2).lazyZip(fields2.map(_._2)).forall(unifyF)\n                        case (FunctionType(lhs1, rhs1), FunctionType(lhs2, rhs2)) => unify(lhs1, lhs2) && unify(rhs1, rhs2)\n                        case (Without(base1, names1), Without(base2, names2)) => unify(base1, base2) && (names1 === names2 || nope)\n                        case (TraitTag(id1, _), TraitTag(id2, _)) => id1 === id2 || nope\n                        case (SkolemTag(id1), SkolemTag(id2)) => id1 === id2 || nope\n                        case (ExtrType(pol1), ExtrType(pol2)) => pol1 === pol2 || nope\n                        case (TypeBounds(lb1, ub1), TypeBounds(lb2, ub2)) =>\n                          unify(lb1, lb2) && unify(ub1, ub2)\n                        case (ComposedType(pol1, lhs1, rhs1), ComposedType(pol2, lhs2, rhs2)) =>\n                          (pol1 === pol2 || nope) && unify(lhs1, lhs2) && unify(rhs1, rhs2)\n                        case (RecordType(fields1), RecordType(fields2)) =>\n                          fields1.size === fields2.size && fields1.lazyZip(fields2).forall((f1, f2) =>\n                            (f1._1 === f2._1 || nope) && unifyF(f1._2, f2._2))\n                        case (WithType(base1, rcd1), WithType(base2, rcd2)) =>\n                          unify(base1, base2) && unify(rcd1, rcd2)\n                        case (ProxyType(underlying1), _) => unify(underlying1, ty2)\n                        case (_, ProxyType(underlying2)) => unify(ty1, underlying2)\n                        case (TypeRef(defn1, targs1), TypeRef(defn2, targs2)) =>\n                          (defn1 === defn2 || nope) && targs1.lazyZip(targs2).forall(unify)\n                        case _ => nope\n                      }\n                    }\n                    \n                    println(s\"Consider $tv1 ~ $tv2\")\n                    if (unify(b1, b2)) {\n                      println(s\"Yes! $tv2 := $tv1\")\n                      varSubst += tv2 -> tv1\n                    }\n                    \n                  case _ =>\n                }\n              case _ =>\n            }\n          case _ =>\n        }\n      case _ =>\n    }\n    \n    println(s\"[subs] ${varSubst}\")\n    \n    if (varSubst.nonEmpty) substLike(st, varSubst.toMap, substInMap = true) else st\n    \n  }\n  \n  \n  \n  abstract class SimplifyPipeline {\n    def debugOutput(msg: => Str): Unit\n    \n    def apply(st: TL, pol: Opt[Bool], removePolarVars: Bool = true)(implicit ctx: Ctx): TypeLike = {\n      var cur = st\n      \n      debugOutput(s\"⬤ Initial: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      cur = removeIrrelevantBounds(cur, pol,\n        reverseBoundsOrder = true, // bounds are accumulated by type inference in reverse order of appearance; so nicer to reverse them here\n        inPlace = false)\n      debugOutput(s\"⬤ Cleaned up: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      pol.foreach(pol => cur = unskidTypes_!(cur, pol))\n      debugOutput(s\"⬤ Unskid: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      cur = simplifyType(cur, removePolarVars, pol)\n      debugOutput(s\"⬤ Type after simplification: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      // * Has a very small (not worth it?) positive effect here:\n      // cur = factorRecursiveTypes_!(cur, approximateRecTypes = false)\n      // debugOutput(s\"⬤ Factored: ${cur}\")\n      // debugOutput(s\" where: ${cur.showBounds}\")\n      \n      cur = normalizeTypes_!(cur, pol)\n      debugOutput(s\"⬤ Normalized: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      cur = removeIrrelevantBounds(cur, pol,\n        reverseBoundsOrder = false,\n        inPlace = true)\n      debugOutput(s\"⬤ Cleaned up: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      pol.foreach(pol => cur = unskidTypes_!(cur, pol))\n      debugOutput(s\"⬤ Unskid: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      // * The DNFs introduced by `normalizeTypes_!` may lead more coocc info to arise\n      // *  by merging things like function types together...\n      // * So we need another pass of simplification!\n      cur = simplifyType(cur, removePolarVars, pol)\n      debugOutput(s\"⬤ Resim: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      cur = factorRecursiveTypes_!(cur, approximateRecTypes = false, pol)\n      debugOutput(s\"⬤ Factored: ${cur}\")\n      debugOutput(s\" where: ${cur.showBounds}\")\n      \n      cur\n    }\n  }\n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/Typer.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet, SortedMap => MutSortMap, LinkedHashMap, LinkedHashSet, Buffer}\nimport scala.collection.immutable.{SortedSet, SortedMap}\nimport Set.{empty => semp}\nimport scala.util.chaining._\nimport scala.annotation.tailrec\nimport mlscript.utils._, shorthands._\nimport mlscript.Message._\n\n/** A class encapsulating type inference state.\n *  It uses its own internal representation of types and type variables, using mutable data structures.\n *  Inferred SimpleType values are then turned into CompactType values for simplification.\n *  In order to turn the resulting CompactType into a mlscript.Type, we use `expandCompactType`.\n */\nclass Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val newDefs: Bool)\n    extends TypeDefs with TypeSimplifier {\n  \n  def funkyTuples: Bool = false\n  def doFactorize: Bool = false\n  def showAllErrors: Bool = false // TODO enable?\n  def maxSuccessiveErrReports: Int = 3\n  \n  var generalizeCurriedFunctions: Boolean = false\n  var approximateNegativeFunction: Boolean = false\n  var preciselyTypeRecursion: Bool = false\n  var distributeForalls: Boolean = false\n  var generalizeArguments: Boolean = false\n  \n  var noCycleCheck: Boolean = false\n  var noRecursiveTypes: Boolean = false\n  var irregularTypes: Boolean = false\n  var constrainedTypes: Boolean = false\n  \n  var recordProvenances: Boolean = true\n  var noApproximateOverload: Boolean = false\n  \n  type Binding = Str -> SimpleType\n  type Bindings = Map[Str, SimpleType]\n  \n  type Level = Int\n  val MinLevel: Int = 0\n  val MaxLevel: Int = 1024\n  \n  type Pol = Opt[Bool]\n  \n  type GenLambdas >: Bool\n  def doGenLambdas(implicit gl: GenLambdas): Bool = gl === true\n  \n  /**  `env`: maps the names of all global and local bindings to their types\n    *  Keys of `mthEnv`:\n    * `L` represents the inferred types of method definitions. The first value is the parent name,\n    *   and the second value is the method name.\n    * `R` represents the actual method types.\n    *   The first optional value is the parent name, with `N` representing implicit calls,\n    *   and the second value is the method name.\n    *   (See the case for `Sel` in `typeTerm` for documentation on explicit vs. implicit calls.)\n    * The public helper functions should be preferred for manipulating `mthEnv`\n   */\n  case class Ctx(\n      parent: Opt[Ctx],\n      env: MutMap[Str, TypeInfo],\n      mthEnv: MutMap[(Str, Str) \\/ (Opt[Str], Str), MethodType],\n      lvl: Int,\n      quoteSkolemEnv: MutMap[Str, SkolemTag], // * SkolemTag for variables in quasiquotes\n      freeVarsInCurrentQuote: LinkedHashSet[ST], // * Free variables appearing in the current quote scope\n      inQuote: Bool, // * Is in quasiquote\n      inPattern: Bool,\n      tyDefs: Map[Str, TypeDef],\n      tyDefs2: MutMap[Str, DelayedTypeInfo],\n      inRecursiveDef: Opt[Var], // TODO rm\n      extrCtx: ExtrCtx,\n  ) {\n    def +=(b: Str -> TypeInfo): Unit = {\n      env += b\n      if (inQuote) {\n        val tag = SkolemTag(freshVar(NoProv, N, nameHint = S(b._1))(lvl))(NoProv)\n        println(s\"Create skolem tag $tag for ${b._2} in quasiquote.\")\n        quoteSkolemEnv += b._1 -> tag\n      }\n    }\n    def ++=(bs: IterableOnce[Str -> TypeInfo]): Unit = bs.iterator.foreach(+=)\n    def get(name: Str): Opt[TypeInfo] = {\n      /**\n        * 1. If we try to get a quoted variable from a quoted context, or get a non-quoted variable from a non-quoted context,\n        * we can directly search the `env`;\n        * 2. If we try to get a quoted variable from a non-quoted context, we need to wrap it with its contextual Skolem;\n        * 3. Otherwise, it is a top-level defined symbol, or the context has a quoted parent.\n        */\n      def rec(ctx: Ctx): Opt[TypeInfo] = {\n        if (inQuote === ctx.inQuote) ctx.env.get(name) orElse ctx.parent.flatMap(rec(_))\n        else if (!inQuote) ctx.env.get(name) match {\n          case S(VarSymbol(ty, _)) => ctx.getQuoteSkolem(name) match {\n            case S(tag) => S(VarSymbol(TypeRef(TypeName(\"Var\"), ty :: tag :: Nil)(noProv), Var(name)))\n            case _ => ctx.parent.flatMap(rec(_))\n          }\n          case _ => ctx.parent.flatMap(rec(_))\n        }\n        else ctx.parent match {\n          case S(parent) => rec(parent)\n          case _ => ctx.env.get(name)\n        }\n      }\n      rec(this)\n    }\n    def getQuoteSkolem(name: Str): Opt[SkolemTag] = quoteSkolemEnv.get(name) orElse parent.dlof(_.getQuoteSkolem(name))(N)\n    def getAllQuoteSkolemsWith(ctxTy: TV): ST = quoteSkolemEnv.foldLeft[ST](ctxTy)((res, ty) => ty._2 | res)\n    def getCtxTy: ST = freeVarsInCurrentQuote.foldLeft[ST](BotType)((res, ty) => res | ty)\n    def trackFVs(fvsType: ST): Unit = {\n      println(s\"Capture free variable type $fvsType\")\n      freeVarsInCurrentQuote += fvsType\n    }\n    def contains(name: Str): Bool = env.contains(name) || parent.exists(_.contains(name))\n    def addMth(parent: Opt[Str], nme: Str, ty: MethodType): Unit = mthEnv += R(parent, nme) -> ty\n    def addMthDefn(parent: Str, nme: Str, ty: MethodType): Unit = mthEnv += L(parent, nme) -> ty\n    private def getMth(key: (Str, Str) \\/ (Opt[Str], Str)): Opt[MethodType] =\n      mthEnv.get(key) orElse parent.dlof(_.getMth(key))(N)\n    def getMth(parent: Opt[Str], nme: Str): Opt[MethodType] = getMth(R(parent, nme))\n    def getMthDefn(parent: Str, nme: Str): Opt[MethodType] = getMth(L(parent, nme))\n    private def containsMth(key: (Str, Str) \\/ (Opt[Str], Str)): Bool = mthEnv.contains(key) || parent.exists(_.containsMth(key))\n    def containsMth(parent: Opt[Str], nme: Str): Bool = containsMth(R(parent, nme))\n    def nest: Ctx = {\n      assert(!inQuote)\n      copy(Some(this), MutMap.empty, MutMap.empty)\n    }\n    /**\n      * Enter a new quoted environment with empty `quoteSkolemEnv` and `freeVarsInCurrentQuote`.\n      * A whole quasiquote (i.e., code\"...\") contains no binding or free variables at the beginning.\n      * For a quoted binding (e.g., code\"x => ...\"):\n      *  1. The context of the lambda body is still in the quotation so `inQuote = true`\n      *  2. `quoteSkolemEnv` only contains skolems created by the current binding and `freeVarsInCurrentQuote` only contains free variables appearing in the body.\n      * So we also apply empty `quoteSkolemEnv` and `freeVarsInCurrentQuote` at the beginning.\n      * e.g. `code\"x => y => x + y\"`. For `y => x + y`, freeVarsInCurrentQuote = {'gx, 'gy}, quoteSkolemEnv = {'gy}.\n      * To get the contextual type, we solve constraint the 'gx \\/ 'gy <= 'a \\/ 'gy, where 'a is a fresh type variable for `y => x + y`'s contextual type.\n      * So for `code\"x => ...\"`, freeVarsInCurrentQuote = {'a}, quoteSkolemEnv = {'gx}, where 'gx <= 'a.\n      * After calling `enterQuotedScope`, **solve the constraints** using `solveQuoteContext` to make sure free variables are handled correctly.\n      */\n    def enterQuotedScope: Ctx = copy(Some(this), MutMap.empty, MutMap.empty, lvl = lvl + 1, inQuote = true, quoteSkolemEnv = MutMap.empty, freeVarsInCurrentQuote = LinkedHashSet.empty)\n    def enterUnquote: Ctx = copy(Some(this), MutMap.empty, MutMap.empty, inQuote = false)\n    def nextLevel[R](k: Ctx => R)(implicit raise: Raise, prov: TP): R = {\n      val newCtx = copy(lvl = lvl + 1, extrCtx = MutSortMap.empty)\n      val res = k(newCtx)\n      val ec = newCtx.extrCtx\n      assert(constrainedTypes || newCtx.extrCtx.isEmpty)\n      if (ec.nonEmpty) trace(s\"UNSTASHING... (out)\") {\n        implicit val ctx: Ctx = this\n        ec.foreach { case (tv, bs) => bs.foreach {\n          case (true, b) => constrain(b, tv)\n          case (false, b) => constrain(tv, b)\n        }}\n        ec.clear()\n      }()\n      res\n    }\n    def poly(k: Ctx => ST)(implicit raise: Raise, prov: TP, shadows: Shadows = Shadows.empty): ST = {\n      nextLevel { newCtx =>\n        \n        val innerTy = k(newCtx)\n        assert(constrainedTypes || newCtx.extrCtx.isEmpty)\n        \n        implicit val ctx: Ctx = newCtx\n        implicit val freshened: MutMap[TV, ST] = MutMap.empty\n        \n        val cty = ConstrainedType.mk(newCtx.extrCtx.iterator.flatMap { case (tv, bs) =>\n          bs.iterator\n            // .filter(_._2.level > lvl) // does not seem to change anything!\n            .map { case (p, b) =>\n              assert(b.level > lvl)\n              if (p) (b, tv) else (tv, b) }\n          }.toList, innerTy)\n\n        if (noApproximateOverload) {\n          val ambiguous = innerTy.getVars.unsorted.flatMap(_.tsc.keys.flatMap(_.tvs))\n            .groupBy(_._2)\n            .filter { case (v,pvs) => pvs.sizeIs > 1 }\n          if (ambiguous.nonEmpty) raise(ErrorReport(\n            msg\"ambiguous\" -> N ::\n              ambiguous.map { case (v,_) => msg\"cannot determine satisfiability of type ${v.expPos}\" -> v.prov.loco }.toList\n              , true))\n        }\n\n        println(s\"Inferred poly constr: $cty  —— where ${cty.showBounds}\")\n        \n        val cty_fresh =\n          // * Sanity check: uncommenting this should change nothing (modulo type simplification randomness)\n          // cty.freshenAbove(lvl, false)\n          cty\n        \n        if (dbg) if (cty_fresh =/= cty) println(s\"Refreshed:            $cty_fresh  —— where ${cty_fresh.showBounds}\")\n        \n        val poly = PolymorphicType.mk(lvl, cty_fresh)\n        \n        /* \n        newCtx.extrCtx.valuesIterator.foreach { buff =>\n          val filtered = buff.filter(_._2.level <= lvl)\n          if (filtered.nonEmpty) println(s\"FILTER $filtered\")\n          assert(filtered.isEmpty)\n          buff.clear()\n        }\n        */\n        newCtx.extrCtx.clear()\n        \n        poly\n      }\n    }\n    private val abcCache: MutMap[Str, Set[TypeName]] = MutMap.empty\n    def allBaseClassesOf(name: Str): Set[TypeName] = abcCache.getOrElseUpdate(name,\n      tyDefs.get(name).fold(Set.empty[TypeName])(_.allBaseClasses(this)(Set.empty)))\n  }\n  object Ctx {\n    private val initBase: Ctx = Ctx(\n      parent = N,\n      env = MutMap.from(builtinBindings.iterator.map(nt => nt._1 -> VarSymbol(nt._2, Var(nt._1)))),\n      mthEnv = MutMap.empty,\n      lvl = MinLevel,\n      quoteSkolemEnv = MutMap.empty,\n      freeVarsInCurrentQuote = LinkedHashSet.empty,\n      inQuote = false,\n      inPattern = false,\n      tyDefs = Map.from(builtinTypes.map(t => t.nme.name -> t)),\n      tyDefs2 = MutMap.empty,\n      inRecursiveDef = N,\n      MutSortMap.empty,\n    )\n    def init: Ctx = if (!newDefs) initBase else {\n      val res = initBase.copy(\n        tyDefs2 = MutMap.from(nuBuiltinTypes.map { t =>\n          val lti = new DelayedTypeInfo(t, Map.empty)(initBase, e => lastWords(e.theMsg))\n          initBase.env += t.nme.name -> lti\n          t.nme.name -> lti\n        }),\n      )\n      implicit val raise: Raise = throw _\n      res.tyDefs2.valuesIterator.foreach { dti =>\n        val mem = dti.complete()\n        // * Not strictly necessary, but it makes sense to use the completed member symbols:\n        res.env += mem.name -> CompletedTypeInfo(mem)\n      }\n      res\n    }\n    val empty: Ctx = init\n  }\n  implicit def lvl(implicit ctx: Ctx): Int = ctx.lvl\n  \n  import TypeProvenance.{apply => tp}\n  def ttp(trm: Term, desc: Str = \"\", isType: Bool = false): TypeProvenance =\n    TypeProvenance(trm.toLoc, if (desc === \"\") trm.describe else desc, isType = isType)\n  def originProv(loco: Opt[Loc], desc: Str, name: Str): TypeProvenance = {\n    tp(loco, desc, S(name), isType = true)\n    // ^ If we did not treat \"origin provenances\" differently,\n    //    it would yields unnatural errors like:\n      //│ ╟── expression of type `B` is not a function\n      //│ ║  l.6: \t    method Map[B]: B -> A\n      //│ ║       \t               ^\n    // So we should keep the info but not shadow the more relevant later provenances\n  }\n  \n  object NoProv extends TypeProvenance(N, \"expression\") {\n    override def toString: Str = \"[NO PROV]\"\n  }\n  def noProv: TypeProvenance = NoProv\n  def provTODO: TypeProvenance = noProv\n  def noTyProv: TypeProvenance = TypeProvenance(N, \"type\", isType = true)\n  \n  private def sing[A](x: A): Set[A] = Set.single(x)\n  \n  val TopType: ExtrType = ExtrType(false)(noTyProv)\n  val BotType: ExtrType = ExtrType(true)(noTyProv)\n  \n  val UnitType: ClassTag = if (newDefs) ClassTag(UnitLit(true), semp)(noTyProv)\n    else ClassTag(Var(\"unit\"), semp)(noTyProv)\n  \n  val BoolType: ST = if (newDefs) TR(TN(\"Bool\"), Nil)(noTyProv)\n    else ClassTag(Var(\"bool\"), semp)(noTyProv)\n  val ObjCls: ClassTag = ClassTag(Var(\"Object\"), semp)(noTyProv)\n  val ObjType: ST = if (newDefs) TR(TN(\"Object\"), Nil)(noTyProv)\n    else TopType\n  val IntType: ST = if (newDefs) TR(TN(\"Int\"), Nil)(noTyProv)\n    else ClassTag(Var(\"int\"), sing(TN(\"number\")))(noTyProv)\n  val DecType: ST = if (newDefs) TR(TN(\"Num\"), Nil)(noTyProv)\n    else ClassTag(Var(\"number\"), semp)(noTyProv)\n  val StrType: ST = if (newDefs) TR(TN(\"Str\"), Nil)(noTyProv)\n    else ClassTag(Var(\"string\"), semp)(noTyProv)\n  val TrueType: ST = if (newDefs) TR(TN(\"true\"), Nil)(noTyProv)\n    else ClassTag(Var(\"true\"), sing(TN(\"bool\")))(noTyProv)\n  val FalseType: ST = if (newDefs) TR(TN(\"false\"), Nil)(noTyProv)\n    else ClassTag(Var(\"false\"), sing(TN(\"bool\")))(noTyProv)\n  val AnnType: ST = TR(TN(\"Annotation\"), Nil)(noTyProv)\n  \n  val EqlTag: TraitTag = TraitTag(Var(\"Eql\"), Set.empty)(noProv)\n  \n  val ErrTypeId: SimpleTerm = Var(\"error\")\n  \n  // TODO rm this obsolete definition (was there for the old frontend)\n  private val primTypes =\n    List(\"unit\" -> UnitType, \"bool\" -> BoolType, \"int\" -> IntType, \"number\" -> DecType, \"string\" -> StrType,\n      \"anything\" -> TopType, \"nothing\" -> BotType)\n  \n  private val preludeLoc = Loc(0, 0, Origin(\"<prelude>\", 0, new FastParseHelpers(\"\")))\n  \n  val nuBuiltinTypes: Ls[NuTypeDef] = Ls(\n    NuTypeDef(Cls, TN(\"Object\"), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Trt, TN(\"Eql\"), (S(VarianceInfo.contra), TN(\"A\")) :: Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Cls, TN(\"Num\"), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Cls, TN(\"Int\"), Nil, N, N, N, Var(\"Num\") :: Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Cls, TN(\"Bool\"), Nil, N, N, S(Union(TN(\"true\"), TN(\"false\"))), Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Mod, TN(\"true\"), Nil, N, N, N, Var(\"Bool\") :: Nil, N, N, TypingUnit(Nil))(N, N, Nil),\n    NuTypeDef(Mod, TN(\"false\"), Nil, N, N, N, Var(\"Bool\") :: Nil, N, N, TypingUnit(Nil))(N, N, Nil),\n    NuTypeDef(Cls, TN(\"Str\"), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Als, TN(\"undefined\"), Nil, N, N, S(Literal(UnitLit(true))), Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Als, TN(\"null\"), Nil, N, N, S(Literal(UnitLit(false))), Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Cls, TN(\"Annotation\"), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Cls, TN(\"Code\"), (S(VarianceInfo.co) -> TN(\"T\")) :: (S(VarianceInfo.co) -> TN(\"C\")) :: Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Cls, TN(\"Var\"), (S(VarianceInfo.in) -> TN(\"T\")) :: (S(VarianceInfo.in) -> TN(\"C\")) :: Nil, N, N, N, TyApp(Var(\"Code\"), TN(\"T\") :: TN(\"C\") :: Nil) :: Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil),\n    NuTypeDef(Mod, TN(\"tailrec\"), Nil, N, N, N, Var(\"Annotation\") :: Nil, N, N, TypingUnit(Nil))(N, N, Nil),\n    NuTypeDef(Mod, TN(\"tailcall\"), Nil, N, N, N, Var(\"Annotation\") :: Nil, N, N, TypingUnit(Nil))(N, N, Nil),\n  )\n  val builtinTypes: Ls[TypeDef] =\n    TypeDef(Cls, TN(\"?\"), Nil, TopType, Nil, Nil, Set.empty, N, Nil) :: // * Dummy for pretty-printing unknown type locations\n    TypeDef(Cls, TN(\"int\"), Nil, TopType, Nil, Nil, sing(TN(\"number\")), N, Nil) ::\n    TypeDef(Cls, TN(\"number\"), Nil, TopType, Nil, Nil, semp, N, Nil) ::\n    TypeDef(Cls, TN(\"bool\"), Nil, TopType, Nil, Nil, semp, N, Nil) ::\n    TypeDef(Cls, TN(\"true\"), Nil, TopType, Nil, Nil, sing(TN(\"bool\")), N, Nil) ::\n    TypeDef(Cls, TN(\"false\"), Nil, TopType, Nil, Nil, sing(TN(\"bool\")), N, Nil) ::\n    TypeDef(Cls, TN(\"string\"), Nil, TopType, Nil, Nil, semp, N, Nil) ::\n    TypeDef(Als, TN(\"undefined\"), Nil, ClassTag(UnitLit(true), semp)(noProv), Nil, Nil, semp, N, Nil) ::\n    TypeDef(Als, TN(\"null\"), Nil, ClassTag(UnitLit(false), semp)(noProv), Nil, Nil, semp, N, Nil) ::\n    TypeDef(Als, TN(\"anything\"), Nil, TopType, Nil, Nil, semp, N, Nil) ::\n    TypeDef(Als, TN(\"nothing\"), Nil, BotType, Nil, Nil, semp, N, Nil) ::\n    TypeDef(Cls, TN(\"error\"), Nil, TopType, Nil, Nil, semp, N, Nil) ::\n    TypeDef(Cls, TN(\"unit\"), Nil, TopType, Nil, Nil, semp, N, Nil) ::\n    {\n      val tv = freshVar(noTyProv, N)(1)\n      val tyDef = TypeDef(Als, TN(\"Array\"), List(TN(\"A\") -> tv),\n        ArrayType(FieldType(None, tv)(noTyProv))(noTyProv), Nil, Nil, semp, N, Nil)\n        // * ^ Note that the `noTyProv` here is kind of a problem\n        // *    since we currently expand primitive types eagerly in DNFs.\n        // *  For instance, see `inn2 v1` in test `Yicong.mls`.\n        // *  We could instead treat these primitives like any other TypeRef,\n        // *    but that currently requires more simplifier work\n        // *    to get rid of things like `1 & int` and `T | nothing`.\n      tyDef.tvarVariances = S(MutMap(tv -> VarianceInfo.co))\n      tyDef\n    } ::\n    {\n      val tv = freshVar(noTyProv, N)(1)\n      val tyDef = TypeDef(Als, TN(\"MutArray\"), List(TN(\"A\") -> tv),\n        ArrayType(FieldType(Some(tv), tv)(noTyProv))(noTyProv), Nil, Nil, semp, N, Nil)\n      tyDef.tvarVariances = S(MutMap(tv -> VarianceInfo.in))\n      tyDef\n    } ::\n    Nil\n  val primitiveTypes: Set[Str] =\n    builtinTypes.iterator.map(_.nme.name).flatMap(n => n.decapitalize :: n.capitalize :: Nil).toSet +\n      \"Object\" + \"Num\" + \"Str\"\n  val reservedTypeNames: Set[Str] = primitiveTypes + \"Eql\"\n  def singleTup(ty: ST): ST =\n    if (funkyTuples) ty else TupleType((N, ty.toUpper(ty.prov) ) :: Nil)(noProv)\n  def pair(ty1: ST, ty2: ST): ST =\n    TupleType(N -> ty1.toUpper(ty1.prov) :: N -> ty2.toUpper(ty2.prov) :: Nil)(noProv)\n  private val sharedVar = freshVar(noProv, N)(1)\n  val builtinBindings: Bindings = {\n    val tv = freshVar(noProv, N)(1)\n    import FunctionType.{ apply => fun }\n    val (intBinOpTy, numberBinOpTy, numberBinPred, stringBinPred) = if (newDefs) (\n      fun(pair(IntType, IntType), IntType)(noProv),\n      fun(pair(DecType, DecType), DecType)(noProv),\n      fun(pair(DecType, DecType), BoolType)(noProv),\n      fun(pair(StrType, StrType), BoolType)(noProv),\n    )\n    else (\n      fun(singleTup(IntType), fun(singleTup(IntType), IntType)(noProv))(noProv),\n      fun(singleTup(DecType), fun(singleTup(DecType), DecType)(noProv))(noProv),\n      fun(singleTup(DecType), fun(singleTup(DecType), BoolType)(noProv))(noProv),\n      fun(singleTup(StrType), fun(singleTup(StrType), BoolType)(noProv))(noProv),\n    )\n    Map(\n      \"true\" -> TrueType,\n      \"false\" -> FalseType,\n      \"True\" -> TypeRef(TN(\"True\"), Nil)(noProv),\n      \"False\" -> TypeRef(TN(\"False\"), Nil)(noProv),\n      \"NaN\" -> DecType,\n      \"document\" -> BotType,\n      \"window\" -> BotType,\n      \"typeof\" -> fun(singleTup(TopType), StrType)(noProv),\n      \"toString\" -> fun(singleTup(TopType), StrType)(noProv),\n      \"String\" -> fun(singleTup(TopType), StrType)(noProv),\n      \"not\" -> fun(singleTup(BoolType), BoolType)(noProv),\n      \"succ\" -> fun(singleTup(IntType), IntType)(noProv),\n      \"log\" -> PolymorphicType(MinLevel, fun(singleTup(tv), UnitType)(noProv)),\n      \"discard\" -> PolymorphicType(MinLevel, fun(singleTup(tv), UnitType)(noProv)),\n      \"negate\" -> fun(singleTup(IntType), IntType)(noProv),\n      \"round\" -> fun(singleTup(DecType), IntType)(noProv),\n      \"add\" -> intBinOpTy,\n      \"sub\" -> intBinOpTy,\n      \"mul\" -> intBinOpTy,\n      \"div\" -> intBinOpTy,\n      \"numAdd\" -> numberBinOpTy,\n      \"numSub\" -> numberBinOpTy,\n      \"numMul\" -> numberBinOpTy,\n      \"sqrt\" -> fun(singleTup(IntType), IntType)(noProv),\n      \"lt\" -> numberBinPred,\n      \"le\" -> numberBinPred,\n      \"gt\" -> numberBinPred,\n      \"ge\" -> numberBinPred,\n      \"slt\" -> stringBinPred,\n      \"sle\" -> stringBinPred,\n      \"sgt\" -> stringBinPred,\n      \"sge\" -> stringBinPred,\n      \"length\" -> fun(singleTup(StrType), IntType)(noProv),\n      \"concat\" -> fun(singleTup(StrType), fun(singleTup(StrType), StrType)(noProv))(noProv),\n      \"join\" -> fun(ArrayType(StrType.toUpper(noProv))(noProv), StrType)(noProv),\n      \"eq\" -> {\n        val v = freshVar(noProv, N)(1)\n        PolymorphicType(MinLevel, fun(singleTup(v), fun(singleTup(v), BoolType)(noProv))(noProv))\n      },\n      \"ne\" -> {\n        val v = freshVar(noProv, N)(1)\n        PolymorphicType(MinLevel, fun(singleTup(v), fun(singleTup(v), BoolType)(noProv))(noProv))\n      },\n      \"error\" -> BotType,\n      \",\" -> {\n        val v = sharedVar\n        PolymorphicType(MinLevel, fun(TupleType(N -> TopType.toUpper(provTODO) :: N -> v.toUpper(provTODO) :: Nil)(noProv), v)(noProv))\n      },\n      \"+\" -> intBinOpTy,\n      \"-\" -> intBinOpTy,\n      \"*\" -> intBinOpTy,\n      \"+.\" -> numberBinOpTy,\n      \"-.\" -> numberBinOpTy,\n      \"*.\" -> numberBinOpTy,\n      \"%\" -> intBinOpTy,\n      \"/\" -> numberBinOpTy,\n      \"**\" -> numberBinOpTy,\n      \"<\" -> numberBinPred,\n      \">\" -> numberBinPred,\n      \"<=\" -> numberBinPred,\n      \">=\" -> numberBinPred,\n      \"==\" -> numberBinPred,\n      \"===\" -> {\n        val v = sharedVar\n        val eq = TypeRef(TypeName(\"Eql\"), v :: Nil)(noProv)\n        PolymorphicType(MinLevel, fun(pair(eq, v), BoolType)(noProv))\n      },\n      \"<>\" -> numberBinPred,\n      \"&&\" -> (if (newDefs) fun(pair(BoolType, BoolType), BoolType)(noProv)\n        else fun(singleTup(BoolType), fun(singleTup(BoolType), BoolType)(noProv))(noProv)),\n      \"||\" -> (if (newDefs) fun(pair(BoolType, BoolType), BoolType)(noProv)\n        else fun(singleTup(BoolType), fun(singleTup(BoolType), BoolType)(noProv))(noProv)),\n      \"id\" -> {\n        val v = freshVar(noProv, N)(1)\n        PolymorphicType(MinLevel, fun(singleTup(v), v)(noProv))\n      },\n      \"if\" -> {\n        val v = freshVar(noProv, N)(1)\n        PolymorphicType(MinLevel, fun(singleTup(BoolType), fun(singleTup(v), fun(singleTup(v), v)(noProv))(noProv))(noProv))\n      },\n      \"emptyArray\" -> {\n        val v = freshVar(noProv, N)(1)\n        PolymorphicType(0, ArrayType(FieldType(S(v), v)(noProv))(noProv))\n      },\n      \"run\" -> {\n        val tv = freshVar(noProv, N)(1)\n        PolymorphicType(0, fun(singleTup(TypeRef(TypeName(\"Code\"), tv :: BotType :: Nil)(noProv)), tv)(noProv))\n      },\n      \"Const\" -> fun(singleTup(IntType), TypeRef(TypeName(\"Code\"), IntType :: BotType :: Nil)(noProv))(noProv),\n    ) ++ (if (!newDefs) primTypes ++ primTypes.map(p => p._1.capitalize -> p._2) // TODO settle on naming convention...\n      else Nil)\n  }\n  \n  \n  /* Parameters `vars` and `newDefsInfo` are used for typing `TypeName`s.\n   * If the key is found in `vars`, the type is typed as the associated value. Use case: type arguments.\n   * If the key is found in `newDefsInfo`, the type is typed as a `TypeRef`, where the associated value\n   *   is used to check the kind of the definition and the number of type arguments expected. Use case:\n   *   for typing bodies of type definitions with mutually recursive references. */\n  def typeType(ty: Type, simplify: Bool = true)\n        (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType], newDefsInfo: Map[Str, (TypeDefKind, Int)] = Map.empty): SimpleType = {\n    typeType2(ty, simplify)._1\n  }\n  def typePolyType(ty: Type, simplify: Bool = true)\n        (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType], newDefsInfo: Map[Str, (TypeDefKind, Int)] = Map.empty): SimpleType = {\n    implicit val prov: TP = tp(ty.toLoc, \"type\")\n    val baseLevel = vars.valuesIterator.map(_.level).maxOption.getOrElse(MinLevel)\n    ctx.copy(lvl = baseLevel).poly { implicit ctx => typeType2(ty, simplify)._1 }\n  }\n  \n  /* Also returns an iterable of `TypeVariable`s instantiated when typing `TypeVar`s.\n   * Useful for instantiating them by substitution when expanding a `TypeRef`. */\n  def typeType2(ty: Type, simplify: Bool = true)\n        (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType],\n        newDefsInfo: Map[Str, (TypeDefKind, Int)]): (SimpleType, Iterable[TypeVariable]) = // TODO rm _2 result?\n      // trace(s\"$lvl. Typing type $ty\") {\n      trace(s\"Typing type ${ty.showDbg}\") {\n    println(s\"vars=$vars newDefsInfo=$newDefsInfo\")\n    val typeType2 = ()\n    // val outerCtxLvl = MinLevel + 1\n    val outerCtxLvl = ctx.lvl\n    def checkKind(k: DeclKind, nme: Str, loc: Opt[Loc]): Unit = k match {\n      case Cls | Mod | Als | Trt => ()\n      case _ => err(msg\"${k.str} ${nme} cannot be used as a type\", loc); ()\n    }\n    def typeNamed(loc: Opt[Loc], name: Str): (() => ST) \\/ (TypeDefKind, Int) =\n      newDefsInfo.get(name)\n        .orElse(ctx.tyDefs.get(name).map(td => (td.kind, td.tparamsargs.size)))\n        .orElse(ctx.get(name).flatMap {\n          case CompletedTypeInfo(mem: TypedNuTypeDef) =>\n            checkKind(mem.decl.kind, mem.nme.name, loc)\n            S(mem.td.kind, mem.tparams.size)\n          case ti: DelayedTypeInfo =>\n            checkKind(ti.decl.kind, ti.decl.name, loc)\n            ti.decl match {\n              case NuTypeDef(k @ (Cls | Mod | Als | Trt), _, tps, _,  _, _, _, _, _, _) =>\n                S(k, tps.size)\n              case NuTypeDef(k @ Mxn, nme, tps,  _, _, _, _, _, _, _) =>\n                S(k, tps.size)\n              case fd: NuFunDef =>\n                N\n            }\n          case _ => N\n        })\n        .toRight(() => err(\"type identifier not found: \" + name, loc)(raise))\n    val localVars = mutable.Map.empty[TypeVar, TypeVariable]\n    def tyTp(loco: Opt[Loc], desc: Str, originName: Opt[Str] = N) =\n      TypeProvenance(loco, desc, originName, isType = true)\n    def rec(ty: Type)(implicit ctx: Ctx, recVars: Map[TypeVar, TypeVariable]): SimpleType = trace(s\"$lvl. type ${ty.showDbg}\") { ty match {\n      case Top => ExtrType(false)(tyTp(ty.toLoc, \"top type\"))\n      case Bot => ExtrType(true)(tyTp(ty.toLoc, \"bottom type\"))\n      case Bounds(Bot, Top) =>\n        val p = tyTp(ty.toLoc, \"type wildcard\")\n        TypeBounds(ExtrType(true)(p), ExtrType(false)(p))(p)\n      case Bounds(lb, ub) =>\n        val lb_ty = rec(lb)\n        val ub_ty = rec(ub)\n        implicit val prov: TP = tyTp(ty.toLoc, \"type bounds\")\n        constrain(lb_ty, ub_ty)\n        TypeBounds(lb_ty, ub_ty)(prov)\n      case Tuple(fields) =>\n        TupleType(fields.mapValues(f =>\n            FieldType(f.in.map(rec), rec(f.out))(tp(f.toLoc, \"tuple field\"))\n          ))(tyTp(ty.toLoc, \"tuple type\"))\n      case Splice(fields) => \n        SpliceType(fields.map{ \n          case L(l) => {\n            val t = rec(l)\n            val res = ArrayType(freshVar(t.prov, N).toUpper(t.prov))(t.prov)\n            constrain(t, res)(raise, t.prov, ctx)\n            L(t)\n          }\n          case R(f) => {\n            R(FieldType(f.in.map(rec), rec(f.out))(tp(f.toLoc, \"splice field\")))\n          }\n          })(tyTp(ty.toLoc, \"splice type\"))\n      case Inter(lhs, rhs) => (if (simplify) rec(lhs) & (rec(rhs), _: TypeProvenance)\n          else ComposedType(false, rec(lhs), rec(rhs)) _\n        )(tyTp(ty.toLoc, \"intersection type\"))\n      case Union(lhs, rhs) => (if (simplify) rec(lhs) | (rec(rhs), _: TypeProvenance)\n          else ComposedType(true, rec(lhs), rec(rhs)) _\n        )(tyTp(ty.toLoc, \"union type\"))\n      case Neg(t) => NegType(rec(t))(tyTp(ty.toLoc, \"type negation\"))\n      case Record(fs) => \n        val prov = tyTp(ty.toLoc, \"record type\")\n        fs.groupMap(_._1.name)(_._1).foreach { case s -> fieldNames if fieldNames.sizeIs > 1 => err(\n            msg\"Multiple declarations of field name ${s} in ${prov.desc}\" -> ty.toLoc\n              :: fieldNames.map(tp => msg\"Declared at\" -> tp.toLoc))(raise)\n          case _ =>\n        }\n        RecordType.mk(fs.map { nt =>\n          if (nt._1.name.isCapitalized)\n            err(msg\"Field identifiers must start with a small letter\", nt._1.toLoc)(raise)\n          nt._1 -> FieldType(nt._2.in.map(rec), rec(nt._2.out))(\n            tp(App(nt._1, Var(\"\").withLocOf(nt._2)).toCoveringLoc,\n              (if (nt._2.in.isDefined) \"mutable \" else \"\") + \"record field\"))\n        })(prov)\n      case Function(lhs, rhs) => FunctionType(rec(lhs), rec(rhs))(tyTp(ty.toLoc, \"function type\"))\n      case WithExtension(b, r) => WithType(rec(b),\n        RecordType(\n            r.fields.map { case (n, f) => n -> FieldType(f.in.map(rec), rec(f.out))(\n              tyTp(App(n, Var(\"\").withLocOf(f)).toCoveringLoc, \"extension field\")) }\n          )(tyTp(r.toLoc, \"extension record\")))(tyTp(ty.toLoc, \"extension type\"))\n      case Literal(lit) =>\n        ClassTag(lit, if (newDefs) lit.baseClassesNu\n          else lit.baseClassesOld)(tyTp(ty.toLoc, \"literal type\"))\n      case TypeName(\"this\") =>\n        ctx.env.get(\"this\") match {\n          case S(_: AbstractConstructor | _: LazyTypeInfo) => die\n          case S(VarSymbol(t: SimpleType, _)) => t\n          case N => err(msg\"undeclared `this`\" -> ty.toLoc :: Nil)\n        }\n      case tn @ TypeTag(name) => rec(TypeName(name.decapitalize)) // TODO rm this hack\n      // case tn @ TypeTag(name) => rec(TypeName(name))\n      case tn @ TypeName(name) =>\n        val tyLoc = ty.toLoc\n        val tpr = tyTp(tyLoc, \"type reference\")\n        vars.getOrElse(name, {\n          typeNamed(tyLoc, name) match {\n            case R((_, tpnum)) =>\n              if (tpnum === 0) TypeRef(tn, Nil)(tpr)\n              else ctx.tyDefs2.get(name) match {\n                case S(lti) =>\n                  lti.decl match {\n                    case NuTypeDef(Cls | Mod, _, _, _, _, _, _, _, _, _) =>\n                      clsNameToNomTag(ctx.tyDefs2(name).decl.asInstanceOf[NuTypeDef])(tyTp(tyLoc, \"class tag\"), ctx)\n                    case NuTypeDef(Trt, _, _, _, _, _, _, _, _, _) =>\n                      trtNameToNomTag(ctx.tyDefs2(name).decl.asInstanceOf[NuTypeDef])(tyTp(tyLoc, \"class tag\"), ctx)\n                    case NuTypeDef(Als, _, _, _, _, _, _, _, _, _) =>\n                      TypeRef(tn, List.fill(tpnum)(freshVar(noProv, N, N)))(tpr)\n                    case _ => die // TODO\n                  }\n                case _ => err(msg\"Type $name takes parameters\", tyLoc)(raise)\n              }\n            case L(e) =>\n              if (name.isEmpty || !name.head.isLower) e()\n              else (typeNamed(tyLoc, name.capitalize), ctx.tyDefs.get(name.capitalize)) match {\n                case (R((kind, _)), S(td)) => kind match {\n                  case Cls => clsNameToNomTag(td)(tyTp(tyLoc, \"class tag\"), ctx)\n                  case Trt => trtNameToNomTag(td)(tyTp(tyLoc, \"trait tag\"), ctx)\n                  case Als => err(\n                    msg\"Type alias ${name.capitalize} cannot be used as a type tag\", tyLoc)(raise)\n                  case Mod => err(\n                    msg\"Module ${name.capitalize} cannot be used as a type tag\", tyLoc)(raise)\n                  case Mxn => err(\n                    msg\"Mixin ${name.capitalize} cannot be used as a type tag\", tyLoc)(raise)\n                }\n                case _ => e()\n              }\n          }\n        })\n      case tv: TypeVar => tv.identifier.toOption.flatMap(vars.get).getOrElse {\n        recVars.getOrElse(tv,\n          localVars.getOrElseUpdate(tv, freshVar(noProv, N, tv.name.filter(_.exists(_ =/= '\\'')))\n              (outerCtxLvl)) // * Type variables not explicily bound are assigned the widest (the outer context's) level\n          ).withProv(tyTp(ty.toLoc, \"type variable\"))\n      }\n      case AppliedType(base, targs) =>\n        val prov = tyTp(ty.toLoc, \"applied type reference\")\n        typeNamed(ty.toLoc, base.name) match {\n          case R((_, tpnum)) =>\n            val realTargs = if (targs.size === tpnum) targs.map(rec) else {\n              err(msg\"Wrong number of type arguments – expected ${tpnum.toString}, found ${\n                  targs.size.toString}\", ty.toLoc)(raise)\n              (targs.iterator.map(rec) ++ Iterator.continually(freshVar(noProv, N))).take(tpnum).toList\n            }\n            TypeRef(base, realTargs)(prov)\n          case L(e) => e()\n        }\n      case Selection(base, nme) =>\n        implicit val gl: GenLambdas = false\n        // val base_ty = typeTerm(base)\n        val base_ty = rec(base)\n        def go(b_ty: ST, rfnt: Var => Opt[FieldType]): ST = b_ty.unwrapAll match {\n          case ct: TypeRef => die // TODO actually\n          case ClassTag(Var(clsNme), _) =>\n            // TODO we should still succeed even if the member is not completed...\n            lookupMember(clsNme, rfnt, nme.toVar) match {\n              case R(cls: TypedNuCls) =>\n                if (cls.tparams.nonEmpty) ??? // TODO\n                clsNameToNomTag(cls.td)(TypeProvenance(ty.toLoc, \"type selection\", isType = true), ctx)\n              case R(als: TypedNuAls) =>\n                if (als.tparams.nonEmpty) ??? // TODO\n                als.body\n              case R(m) => err(msg\"Illegal selection of ${m.kind.str} member in type position\", nme.toLoc)\n              case L(d) => err(d)\n            }\n          case _ =>\n            err(msg\"Illegal prefix of type selection: ${b_ty.expPos}\", base.toLoc)\n        }\n        go(base_ty, _ => N)\n      case Recursive(uv, body) =>\n        val tv = freshVar(tyTp(ty.toLoc, \"local type binding\"), N, uv.name)\n        val bod = rec(body)(ctx, recVars + (uv -> tv))\n        tv.assignedTo = S(bod)\n        tv\n      case Rem(base, fs) => Without(rec(base), fs.toSortedSet)(tyTp(ty.toLoc, \"field removal type\"))\n      case Constrained(base, tvbs, where, tscs) =>\n        val res = rec(base match {\n          case ty: Type => ty\n          case _ => die\n        })\n        tvbs.foreach { case (tv, Bounds(lb, ub)) =>\n          constrain(rec(lb), tv)(raise, tp(lb.toLoc, \"lower bound specifiation\"), ctx)\n          constrain(tv, rec(ub))(raise, tp(ub.toLoc, \"upper bound specifiation\"), ctx)\n        }\n        where.foreach { case Bounds(lo, hi) =>\n          constrain(rec(lo), rec(hi))(raise,\n            tp(mergeOptions(lo.toLoc, hi.toLoc)(_ ++ _), \"constraint specifiation\"), ctx)\n        }\n        tscs.foreach { case (typevars, constrs) =>\n          val tvs = typevars.map(x => (x._1, rec(x._2)))\n          val tsc = new TupleSetConstraints(constrs.map(_.map(rec)), tvs)\n          tvs.values.map(_.unwrapProxies).zipWithIndex.foreach {\n            case (tv: TV, i) => tv.tsc.updateWith(tsc)(_.map(_ + i).orElse(S(Set(i))))\n            case _ => ()\n          }\n        }\n        res\n      case PolyType(vars, ty) =>\n        val oldLvl = ctx.lvl\n        implicit val prov: TP = TypeProvenance(ty.toLoc, \"polymorphic type\")\n        ctx.poly { implicit ctx =>\n          var newVars = recVars\n          val tvs = vars.map {\n            case L(tn) =>\n              die // this probably never happens...\n              freshVar(tyTp(tn.toLoc, \"quantified type name\"), N, S(tn.name))\n            case R(tv) =>\n              val nv = freshVar(tyTp(\n                    tv.toLoc,\n                    // N, // * Here we choose to omit this location,\n                    // * because pointing to the binding place of forall TVs in error messages\n                    // * is often redundant, as these forall types are usually self-contained.\n                    \"quantified type variable\",\n                  tv.name\n                ), N, tv.name)\n              newVars += tv -> nv\n              nv\n          }\n          rec(ty)(ctx, newVars)\n        }\n    }}(r => s\"=> $r\")\n    (rec(ty)(ctx, Map.empty), localVars.values)\n  }(r => s\"=> ${r._1} ——— ${r._2.mkString(\", \")}\")\n  \n  def typePattern(pat: Term)(implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType] = Map.empty): SimpleType =\n    typeTerm(pat)(ctx.copy(inPattern = true), raise, vars, genLambdas = false)\n  \n  \n  def typeStatement(s: DesugaredStatement, allowPure: Bool)\n        (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType], genLambdas: GenLambdas): ST \\/ Opt[Binding] = s match {\n    case Def(false, Var(\"_\"), L(rhs), isByname) => typeStatement(rhs, allowPure)\n    case Def(isrec, nme, L(rhs), isByname) => // TODO reject R(..)\n      if (nme.name === \"_\")\n        err(msg\"Illegal definition name: ${nme.name}\", nme.toLoc)(raise)\n      val ty_sch = typeLetRhs(isrec, nme.name, rhs)\n      nme.uid = S(nextUid)\n      ctx += nme.name -> VarSymbol(ty_sch, nme)\n      R(S(nme.name -> ty_sch))\n    case t @ Tup(fs) if !allowPure => // Note: not sure this is still used!\n      val thing = fs match {\n        case (S(_), _) :: Nil => \"field\"\n        case Nil => \"empty tuple\"\n        case _ => \"tuple\"\n      }\n      warn(s\"Useless $thing in statement position.\", t.toLoc)\n      L(PolymorphicType(MinLevel, typeTerm(t)))\n    case t: Term =>\n      val ty = typeTerm(t)\n      if (!allowPure) {\n        if (t.isInstanceOf[Var] || t.isInstanceOf[Lit])\n          warn(\"Pure expression does nothing in statement position.\", t.toLoc)\n        else\n          constrain(mkProxy(ty, TypeProvenance(t.toCoveringLoc, \"expression in statement position\")), UnitType)(\n            raise = err => raise(WarningReport( // Demote constraint errors from this to warnings\n              msg\"Expression in statement position should have type `unit`.\" -> N ::\n              msg\"Use the `discard` function to discard non-unit values, making the intent clearer.\" -> N ::\n              err.allMsgs, newDefs)),\n            prov = TypeProvenance(t.toLoc, t.describe), ctx)\n      }\n      L(ty)\n    case _ =>\n      err(msg\"Illegal position for this ${s.describe} statement.\", s.toLoc)(raise)\n      R(N)\n  }\n  \n  /** Like `typeLetRhs` but removes unnecessary polymorphic type wrappers. */\n  def typeLetRhs2(isrec: Boolean, nme: Str, rhs: Term)(implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType]): ST = {\n    val res = typeLetRhs(isrec, nme, rhs)(ctx, raise, vars, genLambdas = true)\n    def stripPoly(ty: ST): ST = ty match {\n      case pt: PolymorphicType =>\n        PolymorphicType.mk(pt.polymLevel, stripPoly(pt.body))\n      case _ => ty\n    }\n    stripPoly(res)\n  }\n  \n  /** Infer the type of a let binding right-hand side. */\n  def typeLetRhs(isrec: Boolean, nme: Str, rhs: Term)(implicit ctx: Ctx, raise: Raise,\n      vars: Map[Str, SimpleType], genLambdas: GenLambdas): PolymorphicType = {\n    \n    implicit val prov: TP = TypeProvenance(rhs.toLoc, \"binding of \" + rhs.describe)\n    \n    // * TODO eventually these should NOT introduce PolymorphicType-s on their own\n    // * (don't use `nextLevel`)\n    \n    val res = if (isrec) {\n      val e_ty = freshVar(\n        // It turns out it is better to NOT store a provenance here,\n        //    or it will obscure the true provenance of constraints causing errors\n        //    across recursive references.\n        noProv,\n        // TypeProvenance(rhs.toLoc, \"let-bound value\"),\n        N,\n        S(nme),\n        recPlaceholder = true\n      )(lvl + 1)\n      ctx += nme -> VarSymbol(e_ty, Var(nme))\n      \n      ctx.copy(inRecursiveDef = S(Var(nme))).nextLevel { implicit ctx: Ctx =>\n        implicit val extrCtx: Opt[ExtrCtx] = N\n        implicit val genLambdas: GenLambdas = preciselyTypeRecursion\n        \n        val ty = typeTerm(rhs)\n        \n        constrain(ty, e_ty)(raise, prov, ctx)\n        e_ty.assignedTo = S(ty)\n      }\n      e_ty\n    } else ctx.nextLevel { ctx => // * Note: let polymorphism (`ctx.nextLevel`)\n      typeTerm(rhs)(ctx, raise, vars, genLambdas = true)\n    }\n    PolymorphicType(lvl, res)\n    // * ^ TODO change: this only needs to be done in the rec case;\n    // *    and in that case, only for functions!\n  }\n  \n  def mkProxy(ty: SimpleType, prov: TypeProvenance): SimpleType = {\n    if (recordProvenances)\n      if (ty.prov is prov) ty\n        // * ^ Hacky: without this we get some prov accumulation explosions... would be better to fix at the root!\n      else ProvType(ty)(prov)\n    else ty // TODO don't do this when debugging errors\n    // TODO switch to return this in perf mode:\n    // ty\n  }\n  \n  // TODO also prevent rebinding of \"not\"\n  val reservedVarNames: Set[Str] =\n    Set(\"|\", \"&\", \"~\", \"neg\", \"and\", \"or\", \"is\", \"refined\")\n  \n  object ValidVar {\n    def unapply(v: Var)(implicit raise: Raise): S[Str] = S {\n      if (reservedVarNames(v.name))\n        err(s\"Illegal use of reserved operator: \" + v.name,\n          v.toLoc)(raise)\n      v.name\n    }\n  }\n  object ValidPatVar {\n    def unapply(v: Var)(implicit ctx: Ctx, raise: Raise): Opt[Str] =\n      if (ctx.inPattern && v.isPatVar) {\n        ctx.parent.dlof(_.get(v.name))(N) |>? { case S(VarSymbol(ts: SimpleType, _)) =>\n          ts.unwrapProxies } |>? {\n            case S(ClassTag(Var(v.name), _)) =>\n              warn(msg\"Variable name '${v.name}' already names a symbol in scope. \" +\n                s\"If you want to refer to that symbol, you can use `scope.${v.name}`; \" +\n                s\"if not, give your future readers a break and use another name :^)\", v.toLoc)\n        }\n        ValidVar.unapply(v)\n      } else N\n  }\n  \n  def typeMonomorphicTerm(term: Term)(implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType]): SimpleType = {\n    implicit val genLambdas: GenLambdas = false\n    typeTerm(term)\n  }\n  \n  def typePolymorphicTerm(term: Term)(implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType]): SimpleType = {\n      implicit val genLambdas: GenLambdas = true\n      typeTerm(term)\n    }\n  \n  def notifyMoreErrors(action_ing: Str, prov: TypeProvenance)(implicit raise: Raise): Unit = {\n    err(msg\"Note: further errors omitted while ${action_ing} ${prov.desc}\", prov.loco)\n    ()\n  }\n\n  /**\n    * Solve constraints for quote context.\n    * See `enterQuotedScope`\n    * ctx: outer context\n    * newCtx: inner context generated by `enterQuotedScope`\n    */\n  def solveQuoteContext(ctx: Ctx, newCtx: Ctx)(implicit raise: Raise): Unit = if (ctx.inQuote) {\n    val ctxTy = freshVar(noTyProv, N)(ctx.lvl)\n    constrain(newCtx.getCtxTy, newCtx.getAllQuoteSkolemsWith(ctxTy))({\n      case err: ErrorReport =>\n        constrain(errType, ctxTy)(_ => (), noProv, ctx)\n        raise(err)\n      case diag => raise(diag)\n    }, noProv, ctx)\n    ctx.trackFVs(ctxTy)\n  }\n  \n  /** Infer the type of a term.\n    * genLambdas: whether to generalize lambdas that are found immediately in the term.\n    * Note that the generalization of inner/nested lambdas is determined by other parameters; eg:\n    *   - we never generalize lambdas on the LHS of an application\n    *     (since they will be instantiated immediately anyweay)\n    *   - we don't generalize curried lambdas by default\n    *     (since we can always distribute the quantification of the inferred type variables later)\n    *     UNLESS generalizeCurriedFunctions or constrainedTypes are enabled\n    *     NOTE: when distrib. is disabled, we typically enable generalizeCurriedFunctions to make up for it\n    *   - we always generalize lambdas found in arguments, record/tuple fields, etc.\n    */\n  def typeTerm(term: Term)(implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType], genLambdas: GenLambdas): SimpleType\n        = trace[ST](s\"$lvl. Typing ${if (ctx.inPattern) \"pattern\" else \"term\"} $term\") {\n        // = trace[ST](s\"$lvl. Typing ${if (ctx.inPattern) \"pattern\" else \"term\"} $term   ${extrCtx.map(_.size)}\") {\n    implicit val prov: TypeProvenance = ttp(term)\n    \n    def con(lhs: SimpleType, rhs: SimpleType, res: SimpleType)(implicit ctx: Ctx): SimpleType = {\n      var errorsCount = 0\n      constrain(lhs, rhs)({\n        case err: ErrorReport =>\n          // Note that we do not immediately abort constraining because we still\n          //  care about getting the non-erroneous parts of the code return meaningful types.\n          // In other words, this is so that errors do not interfere too much\n          //  with the rest of the (hopefully good) code.\n          if (errorsCount === 0) {\n            constrain(errType, res)(_ => (), noProv, ctx)\n            // ^ This is just to get error types leak into the result\n            raise(err)\n          } else if (errorsCount < maxSuccessiveErrReports) {\n            // * Silence further errors from this location.\n            if (showAllErrors) raise(err)\n          } else {\n            if (showAllErrors) notifyMoreErrors(\"typing\", prov)\n            return res\n            // ^ Stop constraining, at this point.\n            //    This is to avoid rogue (explosive) constraint solving from badly-behaved error cases.\n            //    For instance see the StressTraits.mls test.\n          }\n          errorsCount += 1\n        case diag => raise(diag)\n      }, prov, ctx) // Q: extrCtx here?\n      res\n    }\n    \n    term match {\n        \n      case v @ Var(\"_\") =>\n        if (ctx.inPattern || funkyTuples) freshVar(tp(v.toLoc, \"wildcard\"), N)\n        else err(msg\"Widlcard in expression position.\", v.toLoc)\n      \n      case Ann(ann, receiver) => \n        val annType = typeTerm(ann)\n        con(annType, AnnType, UnitType)\n        typeTerm(receiver)\n        \n      case Asc(v @ ValidPatVar(nme), ty) =>\n        val ty_ty = typeType(ty)(ctx.copy(inPattern = false), raise, vars)\n        val prov = tp(if (verboseConstraintProvenanceHints) v.toLoc else N, \"variable\")\n        ctx.env.get(nme) match {\n          case S(_) => err(s\"Duplicate use of annotated pattern variable $nme\", v.toLoc)\n          case N =>\n            ctx += nme -> VarSymbol(ty_ty, v)\n            ty_ty\n        }\n        \n      case Asc(trm, ty) =>\n        val trm_ty = typePolymorphicTerm(trm)\n        val ty_ty = typeType(ty)(ctx.copy(inPattern = false), raise, vars)\n        if (ctx.inPattern) { unify(trm_ty, ty_ty); ty_ty } // * In patterns, we actually _unify_ the pattern and ascribed type \n        else con(trm_ty, ty_ty, ty_ty)\n      case (v @ ValidPatVar(nme)) =>\n        val prov = tp(if (verboseConstraintProvenanceHints) v.toLoc else N, \"variable\")\n        // * Note: only look at ctx.env, and not the outer ones!\n        ctx.env.get(nme).collect { case VarSymbol(ts, dv) => assert(v.uid.isDefined); v.uid = dv.uid; ts }\n          .getOrElse {\n            val res = new TypeVariable(lvl, Nil, Nil, N, Option.when(dbg)(nme))(prov)\n            v.uid = S(nextUid)\n            ctx += nme -> VarSymbol(res, v)\n            res\n          }\n      case v @ ValidVar(name) =>\n        val ty = ctx.get(name).fold(err(\"identifier not found: \" + name, term.toLoc): ST) {\n          case AbstractConstructor(absMths, traitWithMths) =>\n            val td = ctx.tyDefs(name)\n            err((msg\"Instantiation of an abstract type is forbidden\" -> term.toLoc)\n              :: (\n                if (traitWithMths) {\n                  assert(td.kind is Trt)\n                  msg\"Note that traits with methods are always considered abstract\" -> td.toLoc :: Nil\n                } else\n                  msg\"Note that ${td.kind.str} ${td.nme} is abstract:\" -> td.toLoc\n                  :: absMths.map { case mn => msg\"Hint: method ${mn.name} is abstract\" -> mn.toLoc }.toList\n              )\n            )\n          case VarSymbol(ty, _) =>\n            if (ctx.inQuote) ctx.getQuoteSkolem(name).foreach(sk => ctx.trackFVs(sk))\n            ty\n          case lti: LazyTypeInfo =>\n            // TODO deal with classes without parameter lists (ie needing `new`)\n            def checkNotAbstract(decl: NuDecl) =\n              if (decl.isAbstract)\n                err(msg\"Class ${decl.name} is abstract and cannot be instantiated\", term.toLoc)\n            lti match {\n              case ti: CompletedTypeInfo =>\n                ti.member match {\n                  case ti: TypedNuFun =>\n                    ti.typeSignature\n                  case p: NuParam =>\n                    p.typeSignature\n                  case ti: TypedNuCls =>\n                    checkNotAbstract(ti.decl)\n                    ti.typeSignature(false, prov.loco)\n                  case ti: TypedNuDecl =>\n                    err(msg\"${ti.kind.str} ${ti.name} cannot be used in term position\", prov.loco)\n                }\n              case ti: DelayedTypeInfo =>\n                checkNotAbstract(ti.decl)\n                ti.typeSignature(false, prov.loco)\n            }\n        }\n        mkProxy(ty, prov)\n        // ^ TODO maybe use a description passed in param?\n        // currently we get things like \"flows into variable reference\"\n        // but we used to get the better \"flows into object receiver\" or \"flows into applied expression\"...\n      case lit: Lit => ClassTag(lit, if (newDefs) lit.baseClassesNu else lit.baseClassesOld)(prov)\n      case Super() =>\n        err(s\"Illegal use of `super`\", term.toLoc)(raise)\n        typeTerm(Var(\"super\").withLocOf(term))\n      case App(Var(\"neg\" | \"~\"), trm) if funkyTuples => typeTerm(trm).neg(prov)\n      case App(App(Var(\"|\"), lhs), rhs) if funkyTuples =>\n        typeTerm(lhs) | (typeTerm(rhs), prov)\n      case App(App(Var(\"&\"), lhs), rhs) if funkyTuples =>\n        typeTerm(lhs) & (typeTerm(rhs), prov)\n      case Rcd(fs) =>\n        val prov = tp(term.toLoc, \"record literal\")\n        fs.groupMap(_._1.name)(_._1).foreach { case s -> fieldNames if fieldNames.sizeIs > 1 => err(\n            msg\"Multiple declarations of field name ${s} in ${prov.desc}\" -> term.toLoc\n              :: fieldNames.map(tp => msg\"Declared at\" -> tp.toLoc))(raise)\n          case _ =>\n        }\n        RecordType.mk(fs.map { case (n, Fld(FldFlags(mut, _, _), t)) => \n          if (n.name.isCapitalized)\n            err(msg\"Field identifiers must start with a small letter\", term.toLoc)(raise)\n          val tym = typePolymorphicTerm(t)\n          val fprov = tp(App(n, t).toLoc, (if (mut) \"mutable \" else \"\") + \"record field\")\n          if (mut) {\n            val res = freshVar(fprov, N, S(n.name))\n            val rs = con(tym, res, res)\n            (n, FieldType(Some(rs), rs)(fprov))\n          } else (n, tym.toUpper(fprov))\n        })(prov)\n      case tup: Tup if funkyTuples =>\n        typeTerms(tup :: Nil, false, Nil)\n      case Tup(fs) =>\n        TupleType(fs.mapConserve { case e @ (n, Fld(flags, t)) =>\n          n match {\n            case S(v) if ctx.inPattern =>\n              (n, Fld(flags,\n                Asc(v, t.toTypeRaise).withLoc(v.toLoc.fold(t.toLoc)(_ ++ t.toLoc |> some))))\n            case _ => e\n          }\n        }.map { case (n, Fld(FldFlags(mut, spec, getter), t)) =>\n          if (getter)\n            err(msg\"Cannot use `val` in this position\", Loc(t :: n.toList))\n          val tym = typePolymorphicTerm(t)\n          // val tym = if (n.isDefined) typeType(t.toTypeRaise)\n          //   else typePolymorphicTerm(t)\n          val fprov = tp(t.toLoc, (if (mut) \"mutable \" else \"\") + \"tuple field\")\n          if (mut) {\n            val res = freshVar(fprov, N, n.map(_.name))\n            val rs = con(tym, res, res)\n            (n, FieldType(Some(rs), rs)(fprov))\n          } else (n, tym.toUpper(fprov))\n        })(fs match {\n          case Nil | ((N, _) :: Nil) => noProv // TODO rm?\n          case _ => tp(term.toLoc, \"tuple literal\")\n        })\n      case Subs(a, i) =>\n        val t_a = typeMonomorphicTerm(a)\n        val t_i = typeMonomorphicTerm(i)\n        con(t_i, IntType, TopType)\n        val elemType = freshVar(prov, N)\n        elemType.upperBounds ::=\n          // * We forbid using [⋅] indexing to access elements that possibly have `undefined` value,\n          // *  which could result in surprising behavior and bugs in the presence of parametricity!\n          // * Note that in modern JS, `undefined` is arguably not a value you're supposed to use explicitly;\n          // *  `null` should be used instead for those willing to indulge in the Billion Dollar Mistake.\n          TypeRef(TypeName(\"undefined\"), Nil)(noProv).neg(\n            prov.copy(desc = \"prohibited undefined element\")) // TODO better reporting for this; the prov isn't actually used\n        con(t_a, ArrayType(elemType.toUpper(tp(i.toLoc, \"array element\")))(prov), elemType) |\n          TypeRef(TypeName(\"undefined\"), Nil)(prov.copy(desc = \"possibly-undefined array access\"))\n      case While(cnd, bod) =>\n        val t_cnd = typeMonomorphicTerm(cnd)\n        con(t_cnd, BoolType, UnitType)\n        typeTerm(Blk(bod :: UnitLit(true) :: Nil))\n      case Assign(s @ Sel(r, f), rhs) =>\n        val o_ty = typeMonomorphicTerm(r)\n        val sprov = tp(s.toLoc, \"assigned selection\")\n        val fieldType = freshVar(sprov, N, Opt.when(!f.name.startsWith(\"_\"))(f.name))\n        val obj_ty =\n          // Note: this proxy does not seem to make any difference:\n          mkProxy(o_ty, tp(r.toCoveringLoc, \"receiver\"))\n        con(obj_ty, RecordType.mk((f, FieldType(Some(fieldType), TopType)(\n          tp(f.toLoc, \"assigned field\")\n        )) :: Nil)(sprov), fieldType)\n        val vl = typeMonomorphicTerm(rhs)\n        con(vl, fieldType, UnitType.withProv(prov))\n      case Assign(s @ Subs(a, i), rhs) => \n        val a_ty = typeMonomorphicTerm(a)\n        val sprov = tp(s.toLoc, \"assigned array element\")\n        val elemType = freshVar(sprov, N)\n        val arr_ty =\n            // Note: this proxy does not seem to make any difference:\n            mkProxy(a_ty, tp(a.toCoveringLoc, \"receiver\"))\n        con(arr_ty, ArrayType(FieldType(Some(elemType), elemType)(sprov))(prov), TopType)\n        val i_ty = typeMonomorphicTerm(i)\n        con(i_ty, IntType, TopType)\n        val vl = typeMonomorphicTerm(rhs)\n        con(vl, elemType, UnitType.withProv(prov))\n      case Assign(lhs @ (v: Var), rhs) =>\n        val rhs_ty = typeTerm(rhs)\n        def checkMut(fd: NuFunDef) =\n          if (!fd.isMut) err(msg\"${fd.describe} `${fd.nme.name\n            }` is not mutable and cannot be reassigned\", prov.loco)\n        ctx.get(v.name) match {\n          case S(VarSymbol(ty, vr)) =>\n            con(rhs_ty, ty, UnitType.withProv(prov))\n          case S(CompletedTypeInfo(m: TypedNuFun)) =>\n            checkMut(m.fd)\n            val lhs_ty = m.typeSignature\n            con(rhs_ty, lhs_ty, UnitType.withProv(prov))\n          case S(dti @ DelayedTypeInfo(fd: NuFunDef)) =>\n            checkMut(fd)\n            val lhs_ty = dti.mutRecTV\n            con(rhs_ty, lhs_ty, UnitType.withProv(prov))\n          case _ =>\n            // TODO dedup w/ below\n            err(msg\"Illegal assignment\" -> prov.loco\n              :: msg\"cannot assign to ${lhs.describe}\" -> lhs.toLoc :: Nil)\n        }\n      case Assign(lhs, rhs) =>\n        err(msg\"Illegal assignment\" -> prov.loco\n          :: msg\"cannot assign to ${lhs.describe}\" -> lhs.toLoc :: Nil)\n      case Splc(es) => \n        SpliceType(es.map{\n          case L(l) => L({\n            val t_l = typeMonomorphicTerm(l)\n            val t_a = ArrayType(freshVar(prov, N).toUpper(prov))(prov)\n            con(t_l, t_a, t_l)\n          }) \n          case R(Fld(FldFlags(mt, sp, _), r)) => {\n            val t = typeMonomorphicTerm(r)\n            if (mt) { R(FieldType(Some(t), t)(t.prov)) } else {R(t.toUpper(t.prov))}\n          }\n        })(prov)\n      case Bra(false, trm: Blk) => typeTerm(trm)\n      case Bra(rcd, trm @ (_: Tup | _: Blk)) if funkyTuples => typeTerms(trm :: Nil, rcd, Nil)\n      case Bra(_, trm) => typeTerm(trm)\n      case Blk((s: Term) :: Nil) => typeTerm(s)\n      case Blk(Nil) => UnitType.withProv(prov)\n      case pat if ctx.inPattern =>\n        err(msg\"Unsupported pattern shape${\n          if (dbg) \" (\"+pat.getClass.toString+\")\" else \"\"}:\", pat.toLoc)(raise)\n      case Lam(pat, body) if doGenLambdas =>\n        println(s\"TYPING POLY LAM\")\n        val newCtx = if (ctx.inQuote) ctx.enterQuotedScope else ctx.nest\n        newCtx.poly { newCtx =>\n          val param_ty = typePattern(pat)(newCtx, raise, vars)\n          val body_ty = typeTerm(body)(newCtx, raise, vars,\n            generalizeCurriedFunctions || doGenLambdas && constrainedTypes)\n          solveQuoteContext(ctx, newCtx)\n          FunctionType(param_ty, body_ty)(tp(term.toLoc, \"function\"))\n        }\n      case Lam(pat, body) =>\n        val newCtx = if (ctx.inQuote) ctx.enterQuotedScope else ctx.nest\n        val param_ty = typePattern(pat)(newCtx, raise, vars)\n        assert(!doGenLambdas)\n        val body_ty = typeTerm(body)(newCtx, raise, vars,\n          generalizeCurriedFunctions || doGenLambdas)\n        solveQuoteContext(ctx, newCtx)\n        FunctionType(param_ty, body_ty)(tp(term.toLoc, \"function\"))\n      case NuNew(cls) => typeMonomorphicTerm(App(NuNew(cls), Tup(Nil).withLoc(term.toLoc.map(_.right))))\n      case app @ App(nw @ NuNew(cls), args) =>\n        cls match {\n          case _: TyApp => // * TODO improve (hacky)\n            err(msg\"Type arguments in `new` expressions are not yet supported\", prov.loco)\n          case _ => \n        }\n        val cls_ty = typeType(cls.toTypeRaise)\n        def process(clsNme: Str) = {\n            println(clsNme, ctx.tyDefs2.get(clsNme))\n            ctx.tyDefs2.get(clsNme) match {\n              case N =>\n                err(msg\"Type `${clsNme}` cannot be used in `new` expression\", term.toLoc)\n              case S(lti) =>\n                def checkNotAbstract(decl: NuDecl) =\n                  if (decl.isAbstract)\n                    err(msg\"Class ${decl.name} is abstract and cannot be instantiated\", term.toLoc)\n                lti match {\n                  case dti: DelayedTypeInfo if !(dti.kind is Cls) =>\n                    err(msg\"${dti.kind.str.capitalize} ${dti.name} cannot be used in `new` expression\",\n                      prov.loco)\n                  case dti: DelayedTypeInfo =>\n                    checkNotAbstract(dti.decl)\n                    dti.typeSignature(true, prov.loco)\n                }\n            }\n        }\n        val new_ty = cls_ty.unwrapProxies match {\n          case TypeRef(clsNme, targs) =>\n            // FIXME don't disregard `targs`\n            process(clsNme.name)\n          case err @ ClassTag(ErrTypeId, _) => err\n          case ClassTag(Var(clsNme), _) => process(clsNme)\n          case _ =>\n            // * Debug with: ${cls_ty.getClass.toString}\n            err(msg\"Unexpected type `${cls_ty.expPos}` after `new` keyword\" -> cls.toLoc :: Nil)\n        }\n        val res = freshVar(prov, N)\n        val argProv = tp(args.toLoc, \"argument list\")\n        con(new_ty, FunctionType(typeTerm(args).withProv(argProv), res)(noProv), res)\n      case App(App(Var(\"is\"), _), _) => // * Old-style operators\n        typeTerm(term.desugaredTerm.getOrElse {\n          val desug = If(IfThen(term, Var(\"true\")), S(Var(\"false\")))\n          term.desugaredTerm = S(desug)\n          desug\n        })\n      case App(Var(\"is\"), _) =>\n        typeTerm(term.desugaredTerm.getOrElse {\n          val desug = If(IfThen(term, Var(\"true\")), S(Var(\"false\")))\n          term.desugaredTerm = S(desug)\n          desug\n        })\n      case App(App(Var(\"and\"), PlainTup(lhs)), PlainTup(rhs)) => // * Old-style operators\n        typeTerm(term.desugaredTerm.getOrElse {\n          val desug = If(IfThen(lhs, rhs), S(Var(\"false\")))\n          term.desugaredTerm = S(desug)\n          desug\n        })\n      case App(Var(\"and\"), PlainTup(lhs, rhs)) =>\n        typeTerm(term.desugaredTerm.getOrElse {\n          val desug = If(IfThen(lhs, rhs), S(Var(\"false\")))\n          term.desugaredTerm = S(desug)\n          desug\n        })\n      case App(f: Term, a @ Tup(fields)) if (fields.exists(x => x._1.isDefined)) =>\n        def getLowerBoundFunctionType(t: SimpleType): List[FunctionType] = t.unwrapProvs match {\n          case PolymorphicType(_, AliasOf(fun_ty @ FunctionType(_, _))) =>\n            List(fun_ty)\n          case tt @ FunctionType(_, _) =>\n            List(tt)\n          case tv: TypeVariable =>\n            tv.lowerBounds.map(getLowerBoundFunctionType(_)).flatten\n          case ct @ ComposedType(pol, lhs, rhs) =>\n            if (pol === false) {\n              getLowerBoundFunctionType(lhs) ++ getLowerBoundFunctionType(rhs)\n            } else \n              Nil\n          case _ =>\n            Nil\n        }\n        val f_ty = typeTerm(f)\n        val fun_tys: List[FunctionType] = getLowerBoundFunctionType(f_ty)\n\n        fun_tys match {\n          case FunctionType(TupleType(fields), _) :: Nil =>\n            val hasUntypedArg = fields.exists(_._1.isEmpty)\n            if (hasUntypedArg) {\n              err(\"Cannot use named arguments as the function type has untyped arguments\", a.toLoc)\n            } else {\n              val argsList = fields.map(x => x._1 match {\n                case Some(arg) => arg\n                case N => die // cannot happen, because already checked with the hasUntypedArg\n              })\n              desugarNamedArgs(term, f, a, argsList, f_ty)\n            }\n          case _ :: _ :: _ =>\n            err(msg\"More than one function signature found in type `${f_ty.expPos}` for function call with named arguments\", f.toLoc)\n          case Nil | _ :: Nil =>\n            err(msg\"Cannot retrieve appropriate function signature from type `${f_ty.expPos}` for applying named arguments\", f.toLoc)\n        }\n      case App(f, a) =>\n        val f_ty = typeMonomorphicTerm(f)\n        // * ^ Note: typing the function monomorphically simplifies type inference but\n        // *    breaks beta expansion stability property\n        // *    (ie a well-typed term may stop type-checking after beta expansion)\n        val a_ty = {\n          def typeArg(a: Term): ST =\n            if (!generalizeArguments) typePolymorphicTerm(a)\n            else ctx.poly { implicit ctx => typePolymorphicTerm(a) }\n          a match {\n            case tup @ Tup(as) =>\n              TupleType(as.map { case (n, Fld(FldFlags(mut, spec, _), a)) => // TODO handle mut?\n                // assert(!mut)\n                val fprov = tp(a.toLoc, \"argument\")\n                val tym = typeArg(a)\n                (n, tym.toUpper(fprov))\n              })(as match { // TODO dedup w/ general Tup case\n                case Nil | ((N, _) :: Nil) => noProv\n                case _ => tp(tup.toLoc, \"argument list\")\n              })\n            case _ => // can happen in the old parser\n              typeArg(a)\n          }\n        }\n        val res = freshVar(prov, N)\n        val arg_ty = mkProxy(a_ty, tp(a.toCoveringLoc, \"argument\"))\n          // ^ Note: this no longer really makes a difference, due to tupled arguments by default\n        val funProv = tp(f.toCoveringLoc, \"applied expression\")\n        val fun_ty = mkProxy(f_ty, funProv)\n          // ^ This is mostly not useful, except in test Tuples.fun with `(1, true, \"hey\").2`\n        val resTy = con(fun_ty, FunctionType(arg_ty, res)(\n          prov\n          // funProv // TODO: better?\n          ), res)\n        resTy\n      case Sel(obj, fieldName) =>\n        // Explicit method calls have the form `x.(Class.Method)`\n        // Implicit method calls have the form `x.Method`\n        //   If two unrelated classes define methods of the same name,\n        //   implicit calls to this method are marked as ambiguous and are forbidden\n        // Explicit method retrievals have the form `Class.Method`\n        //   Returns a function expecting an additional argument of type `Class` before the method arguments\n        def rcdSel(obj: Term, fieldName: Var) = {\n          val o_ty = typeMonomorphicTerm(obj)\n          val res = freshVar(prov, N, Opt.when(!fieldName.name.startsWith(\"_\") && !fieldName.isIndex)(fieldName.name))\n          val obj_ty = mkProxy(o_ty, tp(obj.toCoveringLoc, \"receiver\"))\n          val rcd_ty = RecordType.mk(\n            fieldName -> res.toUpper(tp(fieldName.toLoc, \"field selector\")) :: Nil)(prov)\n          con(obj_ty, rcd_ty, res)\n        }\n        def mthCallOrSel(obj: Term, fieldName: Var) = \n          ( if (newDefs) N else fieldName.name match {\n            case s\"$parent.$nme\" => ctx.getMth(S(parent), nme) // explicit calls\n            case nme => ctx.getMth(N, nme) // implicit calls\n          }) match {\n            case S(mth_ty) =>\n              if (mth_ty.body.isEmpty) {\n                assert(mth_ty.parents.sizeCompare(1) > 0, mth_ty)\n                err(msg\"Implicit call to method ${fieldName.name} is forbidden because it is ambiguous.\" -> term.toLoc\n                  :: msg\"Unrelated methods named ${fieldName.name} are defined by:\" -> N\n                  :: mth_ty.parents.map { prt =>\n                    val td = ctx.tyDefs(prt.name)\n                    msg\"• ${td.kind.str} ${td.nme}\" -> td.nme.toLoc\n                  })\n              }\n              val o_ty = typeMonomorphicTerm(obj)\n              val res = freshVar(prov, N)\n              con(mth_ty.toPT.instantiate, FunctionType(singleTup(o_ty), res)(prov), res)\n            case N =>\n              if (!newDefs && fieldName.name.isCapitalized) err(msg\"Method ${fieldName.name} not found\", term.toLoc)\n              else {\n                val realPrefix = obj match {\n                  case Super() => Var(\"super\").withLocOf(obj)\n                  case _ => obj\n                }\n                rcdSel(realPrefix, fieldName)\n              }\n          }\n        obj match {\n          case Var(name) if name.isCapitalized && ctx.tyDefs.isDefinedAt(name) => // explicit retrieval\n            ctx.getMth(S(name), fieldName.name) match {\n              case S(mth_ty) => mth_ty.toPT.instantiate\n              case N =>\n                err(msg\"Class ${name} has no method ${fieldName.name}\", term.toLoc)\n                mthCallOrSel(obj, fieldName)\n            }\n          // * The code below is only a temporary solution to type `ClassName.unapply`.\n          // * It removed when static methods can be typed properly.\n          case Var(nuCls) =>\n            if (fieldName.name === \"unapply\") (ctx.get(nuCls) match {\n                case S(CompletedTypeInfo(cls: TypedNuCls)) => cls.td.genUnapply\n                case S(ti: DelayedTypeInfo) => ti.decl.genUnapply\n                case _ => N\n              }) match {\n                case S(NuFunDef(_, _, _, _, L(unapplyMtd))) => typePolymorphicTerm(unapplyMtd)\n                case _ => mthCallOrSel(obj, fieldName)\n              }\n            else mthCallOrSel(obj, fieldName)\n          case _ => mthCallOrSel(obj, fieldName)\n        }\n      case Let(isrec, nme, rhs, bod) =>\n        if (ctx.inQuote) {\n          val rhs_ty = typeTerm(rhs)\n          val newCtx = ctx.enterQuotedScope\n          newCtx += nme.name -> VarSymbol(rhs_ty, nme)\n          val res_ty = typeTerm(bod)(newCtx, raise, vars, genLambdas)\n          solveQuoteContext(ctx, newCtx)\n          res_ty\n        }\n        else if (newDefs && !isrec) {\n          // if (isrec) ???\n          val rhs_ty = typeTerm(rhs)\n          val newCtx = ctx.nest\n          newCtx += nme.name -> VarSymbol(rhs_ty, nme)\n          typeTerm(bod)(newCtx, raise, vars, genLambdas)\n        } else {\n          val n_ty = typeLetRhs(isrec, nme.name, rhs)\n          val newCtx = ctx.nest\n          newCtx += nme.name -> VarSymbol(n_ty, nme)\n          typeTerm(bod)(newCtx, raise, vars, genLambdas)\n        }\n      // case Blk(s :: stmts) =>\n      //   val (newCtx, ty) = typeStatement(s)\n      //   typeTerm(Blk(stmts))(newCtx, lvl, raise)\n      case b @ Blk(stmts) =>\n        if (newDefs) {\n          val ttu = typeTypingUnit(TypingUnit(stmts), S(b))\n          // TODO check unused defs\n          ttu.result.getOrElse(UnitType)\n        } else typeTerms(stmts, false, Nil)(ctx.nest, raise, prov, vars, genLambdas)\n      case Bind(l, r) =>\n        val l_ty = typeMonomorphicTerm(l)\n        val newCtx = if (ctx.inQuote) ctx.enterQuotedScope else ctx.nest // so the pattern's context don't merge with the outer context!\n        val r_ty = typePattern(r)(newCtx, raise)\n        ctx ++= newCtx.env\n        solveQuoteContext(ctx, newCtx)\n        con(l_ty, r_ty, r_ty)\n      case Test(l, r) =>\n        val l_ty = typeMonomorphicTerm(l)\n        val newCtx = if (ctx.inQuote) ctx.enterQuotedScope else ctx.nest\n        val r_ty = typePattern(r)(newCtx, raise) // TODO make these bindings flow\n        solveQuoteContext(ctx, newCtx)\n        con(l_ty, r_ty, TopType)\n        BoolType\n      case With(t, rcd) =>\n        val t_ty = typeMonomorphicTerm(t)\n        val rcd_ty = typeMonomorphicTerm(rcd)\n        (t_ty without rcd.fields.iterator.map(_._1).toSortedSet) & (rcd_ty, prov)\n      case CaseOf(s, cs) =>\n        val oldCtx = ctx\n        (if (ctx.inQuote) ctx.enterQuotedScope else ctx) |> { implicit ctx =>\n          val s_ty = typeMonomorphicTerm(s)\n          if (newDefs) con(s_ty, ObjType.withProv(prov), TopType)\n          val (tys, cs_ty) = typeArms(s |>? {\n            case v: Var => v\n            case Asc(v: Var, _) => v\n          }, cs)\n          solveQuoteContext(oldCtx, ctx)\n          val req = tys.foldRight(BotType: SimpleType) {\n            case ((a_ty, tv), req) => a_ty & tv | req & a_ty.neg()\n          }\n          con(s_ty, req, cs_ty)\n        }\n      case elf: If =>\n        elf.desugaredTerm match {\n          case S(desugared) => typeTerm(desugared)\n          case N => err(msg\"not desugared UCS term found\", elf.toLoc)\n        }\n      case AdtMatchWith(cond, arms) =>\n        println(s\"typed condition term ${cond}\")\n        val cond_ty = typeTerm(cond)\n        val ret_ty = if (arms.length === 1) {\n          freshVar(prov.copy(desc = \"let expression\"), N)\n        } else {\n          freshVar(prov.copy(desc = \"match expression\"), N)\n        }\n\n        // the assumed shape of an IfBody is a List[IfThen, IfThen, IfElse] with an optional IfElse at the end\n        arms.foreach { case AdtMatchPat(pat, rhs) =>\n          val nestCtx = if (ctx.inQuote) ctx.enterQuotedScope else ctx.nest\n          def handlePat(pat: Term, expected: SimpleType): Unit = pat match {\n            case Var(\"_\") =>\n            // Cases where the pattern is a single variable term\n            // it can introduce a new pattern variable or it can be a constructor\n            // that takes no argument\n            // `case x -> expr`\n            // `case End -> expr` or `case false -> expr`\n            case v@Var(name) =>\n              println(s\"type pattern $v with loc: ${v.toLoc}\")\n              // update context with variables\n              ctx.tyDefs.get(name).flatMap {\n                case TypeDef(Cls, _, _, _: TypeRef, _, _, _, _, _, S(adtData)) => S(adtData)\n                case TypeDef(Cls, _, _, _, _, _, _, _, _, S(adtData)) =>\n                  err(msg\"Missing parameter list for pattern $name\", v.toLoc)\n                  S(adtData)\n                case _ => N\n              }.fold {\n                // `case x -> expr` catch all with a new variable in the context\n                println(s\"catch all $v\")\n                nestCtx += name -> VarSymbol(expected, v)\n              } {\n                // `case End -> expr` or `case false -> expr` or `case [] -> expr`\n                // where case is a variant of an adt with no type arguments\n                case AdtInfo(alsName) =>\n                  // get adt from cache or initialize a new one with fresh vars\n                  // this is so that all case expressions can share\n                  // the same type variables for the adt\n                  val newTargs = // alsCache.getOrElseUpdate(\n                    // alsName.name,\n                    ctx.tyDefs.getOrElse(alsName.name, lastWords(s\"Could not find ${alsName}\"))\n                      .targs.map(tv => freshVar(tv.prov, N, tv.nameHint))\n                  // )\n                  println(s\"pattern is adt: $alsName with $newTargs\")\n                  val adt_ty = TypeRef(alsName, newTargs)(TypeProvenance(v.toLoc, \"pattern\"))\n                    .withProv(TypeProvenance(cond.toLoc, \"match `condition`\"))\n                  con(expected, adt_ty, expected)\n                  ()\n              }\n            // Handle tuples specially since they don't have an explicit constructor\n            case tup@Tup(fs) =>\n              println(s\"fields $fs\")\n              val tupArgs = // alsCache.getOrElseUpdate(\"Tup\" + fs.length.toString,\n                fs.map(_ => freshVar(noProv, N))\n              // )\n\n              val fld_ty = tupArgs.map(elem => N -> FieldType(N, elem)(elem.prov))\n              val caseAdtTyp = TypeProvenance(tup.toLoc, \"pattern\")\n              val adt_ty = TupleType(fld_ty)(caseAdtTyp)\n                .withProv(TypeProvenance(cond.toLoc, \"match `condition`\"))\n              con(expected, adt_ty, adt_ty)\n\n              fs.zipWithIndex.foreach {\n                case ((_, Fld(_, argTerm)), fieldIdx) =>\n                  println(s\"Typing $argTerm field $fieldIdx in tup\")\n                  val fieldType = tupArgs(fieldIdx)\n                  println(s\"Field $argTerm : $fieldType\")\n                  handlePat(argTerm, fieldType)\n              }\n            case caseAdt@App(Var(ctorNme), patArgs: Tup) =>\n              println(s\"Typing case ($ctorNme)\")\n\n              object BodyRecordType {\n                def unapply(ty: SimpleType): Opt[RecordType] = ty match {\n                  case ty: RecordType => S(ty)\n                  case ProvType(underlying) => unapply(underlying)\n                  case ComposedType(false, lhs, rhs) => unapply(lhs) orElse unapply(rhs)\n                  case _ => N\n                }\n              }\n\n              // find the alias type returned by constructor\n              val (body, tparams, AdtInfo(alsName)) = ctx.tyDefs.get(ctorNme).flatMap {\n                case TypeDef(Cls, _, tparamsargs, BodyRecordType(body), _, _, _, _, _, S(adtInfo)) => S(body, tparamsargs, adtInfo)\n                case r => N\n              }.getOrElse(lastWords(s\"$ctorNme cannot be pattern matched\"))\n\n              // get alias type from cache or initialize a new one with fresh vars\n              // this is so that all case expressions can share\n              // the same type variables for the adt\n              val newTargs = // alsCache.getOrElseUpdate(\n                // alsName.name,\n                ctx.tyDefs.getOrElse(alsName.name, lastWords(s\"Could not find $alsName\"))\n                  .targs.map(tv => freshVar(tv.prov, N, tv.nameHint))\n              // )\n              val caseAdtTyp = TypeProvenance(caseAdt.toLoc, \"pattern\")\n              val newAlsTy = TypeRef(alsName, newTargs)(caseAdtTyp)\n              con(expected, newAlsTy, expected)\n              println(s\"adt_ty $newAlsTy\")\n\n              val mapping: Map[ST, ST] = tparams.map(_._2).zip(newTargs).toMap\n              val argFields = subst(body, mapping) match {\n                case RecordType(fields) => fields.map(_._2.ub)\n                case _ => die\n              }\n              val patArgFields = patArgs.fields.map(_._2.value)\n\n              assert(argFields.sizeCompare(patArgFields) === 0)\n\n              patArgFields.lazyZip(argFields).foreach(handlePat)\n            case pat: Lit =>\n              val litTy = pat match {\n                case DecLit(_) => DecType\n                case IntLit(_) => IntType\n                case StrLit(_) => StrType\n                case UnitLit(_) => UnitType\n              }\n              con(expected, litTy.withProv(tp(pat.toLoc, \"literal pattern\")), expected)\n              ()\n            case Bind(t, v@Var(name)) =>\n              nestCtx += name -> VarSymbol(expected, v)\n              handlePat(t, expected)\n            case Bra(false, pat) =>\n              handlePat(pat, expected)\n            // case Asc(trm, ty) =>\n            //   con(expected, typeType(ty), expected)\n            //   ()\n            // and others\n            case pat =>\n              lastWords(s\"Cannot handle pattern ${pat.showDbg}\")\n          }\n\n          handlePat(pat, cond_ty)\n          nestCtx |> { implicit ctx =>\n            con(typeTerm(rhs), ret_ty, ret_ty)\n          }\n          solveQuoteContext(ctx, nestCtx)\n        }\n        ret_ty\n      case New(base, args) => err(msg\"Currently unsupported `new` syntax\", term.toCoveringLoc)\n      case TyApp(base, _) =>\n        err(msg\"Type application syntax is not yet supported\", term.toLoc) // TODO handle\n        typeTerm(base)\n      case Where(bod, sts) =>\n        typeTerms(sts :+ bod, false, Nil, allowPure = true)\n      case Forall(vs, bod) =>\n        ctx.poly { implicit ctx =>\n          val newVars = vs.map {\n            case tv @ TypeVar(R(nme), _) => nme ->\n              SkolemTag(freshVar(tp(tv.toLoc, \"quantified type variable\"), N, S(nme)))(\n                tp(tv.toLoc, \"rigid type variable\"))\n            case _ => die\n          }\n          vars ++ newVars |> { implicit vars =>\n            typeMonomorphicTerm(bod)\n          }\n        }\n      case Inst(bod) =>\n        val bod_ty = typePolymorphicTerm(bod)\n        var founPoly = false\n        def go(ty: ST): ST = ty.unwrapAll match {\n          case pt: PolymorphicType =>\n            founPoly = true\n            go(pt.instantiate)\n          case _ => ty\n        }\n        val res = go(bod_ty)\n        if (!founPoly) warn(msg\"Inferred type `${bod_ty.expPos}` of this ${\n          bod_ty.prov.desc} cannot be instantiated\", prov.loco)\n        res\n      case Eqn(lhs, rhs) =>\n        err(msg\"Unexpected equation in this position\", term.toLoc)\n      case q @ Quoted(body) =>\n        if (ctx.inQuote) err(msg\"Nested quotation is not allowed.\", q.toLoc)\n        else {\n          val newCtx = ctx.enterQuotedScope\n          val bodyType = typeTerm(body)(newCtx, raise, vars, genLambdas)\n          TypeRef(TypeName(\"Code\"), bodyType :: newCtx.getCtxTy :: Nil)(TypeProvenance(q.toLoc, \"code fragment\"))\n        }\n      case uq @ Unquoted(body) =>\n        if (ctx.inQuote) {\n          val newCtx = ctx.enterUnquote\n          val bodyType = typeTerm(body)(newCtx, raise, vars, genLambdas)\n          val res = freshVar(TypeProvenance(uq.toLoc, \"code fragment body type\"), N)\n          val ctxTy = freshVar(TypeProvenance(body.toLoc, \"code fragment context type\"), N)\n          val ty =\n            con(bodyType, TypeRef(TypeName(\"Code\"), res :: ctxTy :: Nil)(TypeProvenance(body.toLoc, \"unquote body\")), res)(newCtx)\n          ctx.trackFVs(ctxTy)\n          ty.withProv(TypeProvenance(uq.toLoc, \"unquote\"))\n        }\n        else err(\"Unquotes should be enclosed with a quasiquote.\", uq.toLoc)(raise)\n      case Rft(bse, tu) =>\n        err(msg\"Refinement terms are not yet supported\", term.toLoc)\n    }\n  }(r => s\"$lvl. : ${r}\")\n  \n  def typeArms(scrutVar: Opt[Var], arms: CaseBranches)\n      (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType], genLambdas: GenLambdas)\n      : Ls[SimpleType -> SimpleType] -> SimpleType = arms match {\n    case NoCases => Nil -> BotType\n    case Wildcard(b) =>\n      val fv = freshVar(tp(arms.toLoc, \"wildcard pattern\"), N)\n      val newCtx = if (ctx.inQuote) ctx.enterQuotedScope else ctx.nest\n      val res = scrutVar match {\n        case Some(v) =>\n          newCtx += v.name -> VarSymbol(fv, v)\n          val b_ty = typeTerm(b)(newCtx, raise, vars, genLambdas)\n          (fv -> TopType :: Nil) -> b_ty\n        case _ =>\n          (fv -> TopType :: Nil) -> typeTerm(b)\n      }\n      solveQuoteContext(ctx, newCtx)\n      res\n    case cse @ Case(pat, bod, rest) =>\n      val (tagTy, patTy) : (ST, ST) = pat match {\n        case lit: Lit =>\n          val t = ClassTag(lit,\n            if (newDefs) lit.baseClassesNu else lit.baseClassesOld)(tp(pat.toLoc, \"literal pattern\"))\n          t -> t\n        case v @ Var(nme) =>\n          val tpr = tp(pat.toLoc, \"type pattern\")\n          ctx.tyDefs.get(nme) match {\n            case Some(td) if !newDefs =>\n              td.kind match {\n                case Als | Mod | Mxn => val t = err(msg\"can only match on classes and traits\", pat.toLoc)(raise); t -> t\n                case Cls => val t = clsNameToNomTag(td)(tp(pat.toLoc, \"class pattern\"), ctx); t -> t\n                case Trt => val t = trtNameToNomTag(td)(tp(pat.toLoc, \"trait pattern\"), ctx); t -> t\n              }\n            case _ =>\n              val bail = () => {\n                val e = ClassTag(ErrTypeId, Set.empty)(tpr)\n                return ((e -> e) :: Nil) -> e\n              }\n              ctx.get(nme) match {\n                case S(lti: LazyTypeInfo) =>\n                  if ((lti.kind isnt Cls) && (lti.kind isnt Mod) && (lti.kind isnt Trt))\n                    err(msg\"can only match on classes and traits\", pat.toLoc)(raise)\n                  \n                  val prov = tp(pat.toLoc, \"class pattern\")\n                  \n                  lti match {\n                    case dti: DelayedTypeInfo =>\n                      val tag = clsNameToNomTag(dti.decl match { case decl: NuTypeDef => decl; case _ => die })(prov, ctx)\n                      val ty = // TODO update as below for refined\n                        RecordType.mk(dti.tparams.map {\n                          case (tn, tv, vi) =>\n                            val nv = freshVar(tv.prov, S(tv), tv.nameHint)\n                            (Var(nme+\"#\"+tn.name).withLocOf(tn),\n                              FieldType.mk(vi.getOrElse(VarianceInfo.in), nv, nv)(provTODO))\n                        })(provTODO)\n                      println(s\"Match arm $nme: $tag & $ty\")\n                      tag -> ty\n                    case CompletedTypeInfo(cls: TypedNuCls) =>\n                      val tag = clsNameToNomTag(cls.td)(prov, ctx)\n                      println(s\"CASE $tag ${cse.refined}\")\n                      val ty = if (cse.refined) freshVar(tp(v.toLoc, \"refined scrutinee\"), N) else\n                        RecordType.mk(cls.tparams.map {\n                          case (tn, tv, vi) =>\n                            val nv = freshVar(tv.prov, S(tv), tv.nameHint)\n                            (Var(nme+\"#\"+tn.name).withLocOf(tn),\n                              FieldType.mk(vi.getOrElse(cls.varianceOf(tv)), nv, nv)(provTODO))\n                        })(provTODO)\n                      println(s\"Match arm $nme: $tag & $ty\")\n                      tag -> ty\n                    case CompletedTypeInfo(_) => bail()\n                  }\n                  \n                case _ =>\n                  err(\"type identifier not found: \" + nme, pat.toLoc)(raise)\n                  bail()\n              }\n          }\n      }\n      val newCtx = if (ctx.inQuote) ctx.enterQuotedScope else ctx.nest\n      val (req_ty, bod_ty, (tys, rest_ty)) = scrutVar match {\n        case S(v) =>\n          if (newDefs) {\n            newCtx += v.name -> VarSymbol(tagTy & patTy, v)\n            val bod_ty = typeTerm(bod)(newCtx, raise, vars, genLambdas)\n            (tagTy -> patTy, bod_ty, typeArms(scrutVar, rest))\n          } else {\n            val tv = freshVar(tp(v.toLoc, \"refined scrutinee\"), N,\n              // S(v.name), // this one seems a bit excessive\n            )\n            newCtx += v.name -> VarSymbol(tv, v)\n            val bod_ty = typeTerm(bod)(newCtx, raise, vars, genLambdas)\n            (patTy -> tv, bod_ty, typeArms(scrutVar, rest))\n          }\n        case N =>\n          val bod_ty = typeTerm(bod)(newCtx, raise, vars, genLambdas)\n          (tagTy -> TopType, bod_ty, typeArms(scrutVar, rest))\n      }\n      solveQuoteContext(ctx, newCtx)\n      (req_ty :: tys) -> (bod_ty | rest_ty)\n  }\n  \n  def typeTerms(term: Ls[Statement], rcd: Bool, fields: List[Opt[Var] -> SimpleType], allowPure: Bool = false)\n        (implicit ctx: Ctx, raise: Raise, prov: TypeProvenance, vars: Map[Str, SimpleType], genLambdas: GenLambdas): SimpleType\n      = term match {\n    case (trm @ Var(nme)) :: sts if rcd => // field punning\n      typeTerms(Tup(S(trm) -> Fld(FldFlags.empty, trm) :: Nil) :: sts, rcd, fields)\n    case Blk(sts0) :: sts1 => typeTerms(sts0 ::: sts1, rcd, fields)\n    case Tup(Nil) :: sts => typeTerms(sts, rcd, fields)\n    case Tup((no, Fld(FldFlags(tmut, _, _), trm)) :: ofs) :: sts =>\n      val ty = {\n        trm match  {\n          case Bra(false, t) if ctx.inPattern => // we use syntax `(x: (p))` to type `p` as a pattern and not a type...\n            typePattern(t)\n          case _ => ctx.copy(inPattern = ctx.inPattern && no.isEmpty) |> { implicit ctx => // TODO change this?\n            if (ofs.isEmpty) typeTerm(Bra(rcd, trm))\n            // ^ This is to type { a: ... } as { a: { ... } } to facilitate object literal definitions;\n            //   not sure that's a good idea...\n            else typeTerm(trm)\n          }\n        }\n      }\n      val res_ty = no |> {\n        case S(nme) if ctx.inPattern =>\n          // TODO in 'opaque' definitions we should give the exact specified type and not something more precise\n          // as in `(x: Int) => ...` should not try to refine the type of `x` further\n          \n          val prov = tp(trm.toLoc, \"parameter type\")\n          val t_ty =\n            // TODO in positive position, this should create a new VarType instead! (i.e., an existential)\n            new TypeVariable(lvl, Nil, Nil, N)(prov)//.tap(ctx += nme -> _)\n          \n          // constrain(ty, t_ty)(raise, prov)\n          constrain(t_ty, ty)(raise, prov, ctx)\n          ctx += nme.name -> VarSymbol(t_ty, nme)\n          \n          t_ty\n          // ty\n          // ComposedType(false, t_ty, ty)(prov)\n          // ComposedType(true, t_ty, ty)(prov) // loops!\n          \n        case S(nme) =>\n          ctx += nme.name -> VarSymbol(ty, nme)\n          ty\n        case _ =>\n          ty\n      }\n      typeTerms(Tup(ofs) :: sts, rcd, (no, res_ty) :: fields)\n    case (trm: Term) :: Nil =>\n      if (fields.nonEmpty)\n        warn(\"Previous field definitions are discarded by this returned expression.\", trm.toLoc)\n      typeTerm(trm)\n    // case (trm: Term) :: Nil =>\n    //   assert(!rcd)\n    //   val ty = typeTerm(trm)\n    //   typeBra(Nil, rcd, (N, ty) :: fields)\n    case s :: sts =>\n      val (diags, desug) = s.desugared\n      diags.foreach(raise)\n      val newBindings = desug.flatMap(typeStatement(_, allowPure).toOption)\n      ctx ++= newBindings.iterator.flatten.map(nt => nt._1 -> VarSymbol(nt._2, Var(nt._1)))\n      typeTerms(sts, rcd, fields)\n    case Nil =>\n      if (rcd) {\n        val fs = fields.reverseIterator.zipWithIndex.map {\n          case ((S(n), t), i) =>\n            n -> t.toUpper(noProv)\n          case ((N, t), i) =>\n            // err(\"Missing name for record field\", t.prov.loco)\n            warn(\"Missing name for record field\", t.prov.loco)\n            (Var(\"_\" + (i + 1)), t.toUpper(noProv))\n        }.toList\n        RecordType.mk(fs)(prov)\n      } else TupleType(fields.reverseIterator.mapValues(_.toUpper(noProv)))(prov)\n  }\n  \n  def getNewVarName(prefix: Str, nonValidVars: Set[Var]): Str = {\n    // we check all possibe prefix_num combination, till we find one that is not in the nonValidVars\n    val ints = LazyList.from(1)\n    prefix + \"_\" + ints.find(index => {\n      !nonValidVars.contains(Var(prefix + \"_\" + index))\n    }).getOrElse(die)\n  }\n  \n  def desugarNamedArgs(term: Term, f: Term, a: Tup, argsList: List[Var], f_ty: ST)\n  (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType]): SimpleType = {\n    def rec (as: List[(String -> Fld) -> Boolean], acc: Map[String, Either[Var, Term]]): Term = {\n      as match {\n        case ((v, fld), isNamed) :: tail =>\n          if (isNamed) {\n            fld.value match {\n              case _: Lit | _: Var =>\n                rec(tail, acc + (v -> R(fld.value)))\n              case _ =>\n                val newVar = Var(getNewVarName(v, a.freeVars))\n                Let(false, newVar, fld.value, rec(tail, acc + (v -> L(newVar))))\n            }\n          } else {\n            rec(tail, acc + (v -> R(fld.value)))\n          }\n        case Nil =>\n          val y: Term = Tup(argsList.map(x => \n            acc.get(x.name) match {\n              case Some(Left(v)) => (None, Fld(FldFlags.empty, v))\n              case Some(Right(t)) => (None, Fld(FldFlags.empty, t))\n              case None =>\n                err(msg\"Argument named '${x.name}' is missing from this function call\", a.toLoc)\n                (None, Fld(FldFlags.empty, Var(\"error\")))\n            }\n          ))\n          App(f, y)\n      }\n    }\n    val hasDefined = a.fields.exists(x => x._1.isDefined)\n    val hasEmpty = a.fields.exists(x => x._1.isEmpty)\n    val areArgsMisplaced = a.fields.indexWhere(x => x._1.isDefined) < a.fields.lastIndexWhere(x => x._1.isEmpty)\n    if (hasDefined &&\n        hasEmpty && \n        areArgsMisplaced) {\n      err(msg\"Unnamed arguments should appear first when using named arguments\", a.toLoc) \n    } else \n      a.fields.sizeCompare(argsList) match {\n        case 0 =>\n          val as = a.fields.zipWithIndex.map{\n            case(x, idx) =>\n              x._1 match {\n                case Some(value) => \n                  ((value.name, x._2), true)\n                case N =>\n                  ((argsList(idx).name, x._2), false)\n              }}\n          val asGroupedByVarName = as.groupBy(x => x._1._1)\n          if (asGroupedByVarName.sizeCompare(argsList) < 0) {\n            asGroupedByVarName.foreach(x =>\n              x._2 match {\n                case x1 :: y1 :: xs => err(msg\"Argument for parameter '${x._1}' is duplicated\", a.toLoc) \n                case _ =>\n              })\n          }\n          val desugared = rec(as, Map())\n          println(\"Desugared is here => \" + desugared)\n          term.desugaredTerm = S(desugared)\n          typeTerm(desugared)(ctx = ctx, raise = raise, vars = vars, genLambdas = false)\n        case _ =>\n          err(msg\"Number of arguments doesn't match function signature `${f_ty.expPos}`\", a.toLoc)\n      }\n  }\n  \n  /** Convert an inferred SimpleType into the immutable Type representation. */\n  def expandType(st: TypeLike, stopAtTyVars: Bool = false)(implicit ctx: Ctx): mlscript.TypeLike = {\n    val expandType = ()\n    \n    var bounds: Ls[TypeVar -> Bounds] = Nil\n    var tscs: Ls[Ls[(Bool, Type)] -> Ls[Ls[Type]]] = Nil\n    \n    val seenVars = mutable.Set.empty[TV]\n    val seenTscs = mutable.Set.empty[TupleSetConstraints]\n    \n    def field(ft: FieldType)(implicit ectx: ExpCtx): Field = ft match {\n      case FieldType(S(l: TV), u: TV) if l === u =>\n        val res = go(u)\n        Field(S(res), res) // TODO improve Field\n      case f =>\n        Field(f.lb.map(go), go(f.ub))\n    }\n    \n    class ExpCtx(val tps: Map[TV, TN]) {\n      def apply(tparams: Ls[(TN, TV, Opt[VarianceInfo])]): ExpCtx =\n        new ExpCtx(tps ++ tparams.iterator.map{case (tn, tv, vi) => tv -> tn})\n    }\n    \n    def mkTypingUnit(thisTy: ST, members: Map[Str, NuMember])(implicit ectx: ExpCtx): TypingUnit = {\n      val sorted = members.toList.sortBy(_._1)\n      TypingUnit(sorted.collect {\n        case (_, d: TypedNuFun) => goDecl(d)\n        case (_, d: TypedNuTypeDef) => goDecl(d)\n      })\n    }\n    def goDecl(d: NuMember)(implicit ectx: ExpCtx): NuDecl = d match {\n      case TypedNuAls(level, td, tparams, body) =>\n        ectx(tparams) |> { implicit ectx =>\n          NuTypeDef(td.kind, td.nme, td.tparams, N, N, S(go(body)), Nil, N, N, TypingUnit(Nil))(\n            td.declareLoc, td.abstractLoc, td.annotations)\n        }\n      case TypedNuMxn(level, td, thisTy, superTy, tparams, params, members) =>\n        ectx(tparams) |> { implicit ectx =>\n          NuTypeDef(td.kind, td.nme, td.tparams,\n            S(Tup(params.map(p => N -> Fld(FldFlags.empty, Asc(p._1, go(p._2.ub)))))),\n            N,//TODO\n            N,\n            Nil, // TODO mixin parents?\n            Option.when(!(TopType <:< superTy))(go(superTy)),\n            Option.when(!(TopType <:< thisTy))(go(thisTy)),\n            mkTypingUnit(thisTy, members)\n          )(td.declareLoc, td.abstractLoc, td.annotations)\n        }\n      case TypedNuCls(level, td, tparams, params, acParams, members, thisTy, sign, ihtags, ptps) =>\n        ectx(tparams) |> { implicit ectx =>\n          NuTypeDef(td.kind, td.nme, td.tparams,\n            params.map(ps => Tup(ps.map(p => N -> Fld(FldFlags.empty, Asc(p._1, go(p._2.ub)))))),\n            td.ctor,\n            Option.when(!(TopType <:< sign))(go(sign)),\n            ihtags.toList.sorted.map(_.toVar), // TODO provide targs/args\n            N,//TODO\n            Option.when(!(TopType <:< thisTy))(go(thisTy)),\n            {\n              val tun = mkTypingUnit(thisTy, members)\n              acParams match {\n                case S(ps) => TypingUnit(Constructor(\n                  Tup(ps.map(p => N -> Fld(FldFlags.empty, Asc(p._1, go(p._2))))),\n                  Blk(Nil)) :: tun.entities)\n                case N => tun\n              }\n            }\n          )(td.declareLoc, td.abstractLoc, td.annotations)\n        }\n      case TypedNuTrt(level, td, tparams, members, thisTy, sign, ihtags, ptps) => \n        ectx(tparams) |> { implicit ectx =>\n          NuTypeDef(td.kind, td.nme, td.tparams,\n            N,\n            td.ctor,\n            Option.when(!(TopType <:< sign))(go(sign)),\n            ihtags.toList.sorted.map(_.toVar), // TODO provide targs/args\n            N,//TODO\n            Option.when(!(TopType <:< thisTy))(go(thisTy)),\n            mkTypingUnit(thisTy, members)\n          )(td.declareLoc, td.abstractLoc, td.annotations)\n        }\n      case tf @ TypedNuFun(level, fd, bodyTy) =>\n        NuFunDef(fd.isLetRec, fd.nme, fd.symbolicNme, Nil, R(go(tf.typeSignature)))(\n          fd.declareLoc, fd.virtualLoc, fd.mutLoc, fd.signature, fd.outer, fd.genField, fd.annotations)\n      case p: NuParam =>\n        ??? // TODO\n      case TypedNuDummy(d) =>\n        ??? // TODO\n    }\n    def goLike(ty: TypeLike)(implicit ectx: ExpCtx): mlscript.TypeLike = ty match {\n      case ty: SimpleType =>\n        val res = go(ty)\n        // if (bounds.isEmpty) res\n        // else Constrained(res, bounds, Nil)\n        res\n      case OtherTypeLike(tu) =>\n        val mems = tu.implementedMembers.map(goDecl)\n        Signature(mems, tu.result.map(go))\n    }\n    \n    def go(st: SimpleType)(implicit ectx: ExpCtx): Type =\n            // trace(s\"expand $st\") {\n          st.unwrapProvs match {\n        case tv: TypeVariable if stopAtTyVars => tv.asTypeVar\n        case tv: TypeVariable => ectx.tps.getOrElse(tv, {\n          val nv = tv.asTypeVar\n          if (seenVars.add(tv)) {\n            tv.assignedTo match {\n              case S(ty) =>\n                val b = go(ty)\n                bounds ::= nv -> Bounds(b, b)\n              case N =>\n                val l = go(tv.lowerBounds.foldLeft(BotType: ST)(_ | _))\n                val u = go(tv.upperBounds.foldLeft(TopType: ST)(_ &- _))\n                if (l =/= Bot || u =/= Top)\n                  bounds ::= nv -> Bounds(l, u)\n            }\n            tv.tsc.foreachEntry {\n              case (tsc, i) =>\n                if (seenTscs.add(tsc)) {\n                  val tvs = tsc.tvs.map(x => (x._1,go(x._2)))\n                  val constrs = tsc.constraints.map(_.map(go))\n                  tscs ::= tvs -> constrs\n                }\n            }\n          }\n          nv\n        })\n        case FunctionType(l, r) => Function(go(l), go(r))\n        case ct @ ComposedType(true, l, r) =>\n          if (ct >:< (TrueType | FalseType)) TN(\"Bool\") // TODO should rather be done in TypeSimplifier\n          else Union(go(l), go(r))\n        case ComposedType(false, l, r) => Inter(go(l), go(r))\n        case RecordType(fs) => Record(fs.mapValues(field))\n        case TupleType(fs) => Tuple(fs.mapValues(field))\n        case ArrayType(FieldType(None, ub)) => AppliedType(TypeName(\"Array\"), go(ub) :: Nil)\n        case ArrayType(f) =>\n          val f2 = field(f)\n          AppliedType(TypeName(\"MutArray\"), Bounds(f2.in.getOrElse(Bot), f2.out) :: Nil)\n        case SpliceType(elems) => Splice(elems.map { \n              case L(l) => L(go(l)) \n              case R(v) => R(Field(v.lb.map(go(_)), go(v.ub))) })\n        case NegType(t) => Neg(go(t))\n        case ExtrType(true) => Bot\n        case ExtrType(false) => Top\n        case WithType(base, rcd) =>\n          WithExtension(go(base), Record(rcd.fields.mapValues(field)))\n        case ProxyType(und) => go(und)\n        case obj: ObjectTag => obj.id match {\n          case Var(n) =>\n            if (primitiveTypes.contains(n) // primitives like `int` are internally maintained as class tags\n              || n === \"this\" // `this` type\n            ) TypeName(n)\n            else TypeTag(n.capitalize)\n          case lit: Lit => Literal(lit)\n        }\n        case SkolemTag(tv) => tv.nameHint match {\n            case S(n) if\n                n.isCapitalized // rigid type params like A in class Foo[A]\n              => TypeName(n)\n            case _ => go(tv)\n          }\n        case ex @ Extruded(p, SkolemTag(tv)) =>\n          if (p) tv.asPosExtrudedTypeVar else tv.asNegExtrudedTypeVar\n        case TypeRef(td, Nil) => td\n        case tr @ TypeRef(td, targs) => AppliedType(td, tr.mapTargs(S(true)) {\n          case ta @ ((S(true), TopType) | (S(false), BotType)) => Bounds(Bot, Top)\n          case (_, ty) => go(ty)\n        })\n        case TypeBounds(lb, ub) => Bounds(go(lb), go(ub))\n        case Without(base, names) => Rem(go(base), names.toList)\n        case Overload(as) => as.map(go).reduce(Inter)\n        case PolymorphicType(lvl, bod) =>\n          val boundsSize = bounds.size\n          val tscsSize = tscs.size\n          val b = go(bod)\n          \n          // This is not completely correct: if we've already traversed TVs as part of a previous sibling PolymorphicType,\n          // the bounds of these TVs won't be registered again...\n          // FIXME in principle we'd want to compute a transitive closure...\n          val newBounds = bounds.reverseIterator.drop(boundsSize).toBuffer\n          val newTscs = tscs.reverseIterator.drop(tscsSize).toBuffer\n          \n          val qvars = bod.varsBetween(lvl, MaxLevel).iterator\n          val ftvs = b.freeTypeVariables ++\n            newBounds.iterator.map(_._1) ++\n            newBounds.iterator.flatMap(_._2.freeTypeVariables) ++\n            newTscs.iterator.flatMap(_._1.map(_._2))\n          val fvars = qvars.filter(tv => ftvs.contains(tv.asTypeVar))\n          if (fvars.isEmpty) b else\n            PolyType(fvars\n              .toArray.sorted\n              .map(_.asTypeVar pipe (R(_))).toList, b)\n        case ConstrainedType(cs, bod) =>\n          val groups1, groups2 = LinkedHashMap.empty[ST, Buffer[ST]]\n          cs.foreach { case (lo, hi) => groups1.getOrElseUpdate(lo, Buffer.empty) += hi }\n          val (ubs, others1) = groups1.toList.partition(_._2.sizeIs > 1)\n          others1.foreach { case (k, vs) => groups2.getOrElseUpdate(vs.head, Buffer.empty) += k }\n          val lbs = groups2.toList\n          val bounds = (ubs.mapValues(_.reduce(_ &- _)) ++ lbs.mapValues(_.reduce(_ | _)).map(_.swap))\n          val processed = bounds.map { case (lo, hi) => Bounds(go(lo), go(hi)) }\n          Constrained(go(bod), Nil, processed, Nil)\n        \n        // case DeclType(lvl, info) =>\n          \n    }\n    // }(r => s\"~> $r\")\n    \n    val res = goLike(st)(new ExpCtx(Map.empty))\n    if (bounds.isEmpty && tscs.isEmpty) res\n    else Constrained(res, bounds, Nil, tscs)\n    \n    // goLike(st)\n  }\n  \n  \n  private var curUid: Int = 0\n  def nextUid: Int = {\n    val res = curUid\n    curUid += 1\n    res\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/TyperDatatypes.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable\nimport scala.collection.mutable.{Map => MutMap, Set => MutSet, Buffer, LinkedHashMap}\nimport scala.collection.immutable.{SortedSet, SortedMap}\nimport scala.util.chaining._\nimport scala.annotation.tailrec\nimport mlscript.utils._, shorthands._\nimport mlscript.Message._\n\nabstract class TyperDatatypes extends TyperHelpers { Typer: Typer =>\n  def recordTypeVars: Bool = false\n  \n  type TN = TypeName\n  val TN: TypeName.type = TypeName\n  \n  \n  // The data types used for type inference:\n  \n  \n  case class TypeProvenance(loco: Opt[Loc], desc: Str, originName: Opt[Str] = N, isType: Bool = false) {\n    val isOrigin: Bool = originName.isDefined\n    def & (that: TypeProvenance): TypeProvenance = this // arbitrary; maybe should do better\n    override def toString: Str = (if (isOrigin) \"o: \" else \"\") + \"‹\"+loco.fold(desc)(desc+\":\"+_)+\"›\"\n  }\n  type TP = TypeProvenance\n  \n  \n  sealed abstract class TypeInfo\n  \n  \n  /** A type for abstract classes that is used to check and throw\n   * errors if the abstract class is being instantiated */\n  case class AbstractConstructor(absMths: Set[Var], isTraitWithMethods: Bool) extends TypeInfo\n  \n  \n  case class VarSymbol(ty: ST, definingVar: Var) extends TypeInfo\n  \n  \n  /** Some type information which may not yet be available. */\n  sealed abstract class LazyTypeInfo extends TypeInfo {\n    def complete()(implicit raise: Raise): NuMember\n    def kind: DeclKind\n    def name: Str\n  }\n  \n  /** A LazyTypeInfo whose typing has been completed. */\n  case class CompletedTypeInfo(member: NuMember) extends LazyTypeInfo {\n    def complete()(implicit raise: Raise): NuMember = member\n    def kind: DeclKind = member.kind\n    val name: Str = member.name\n  }\n  \n  /** Initialized lazy type information, to be computed soon. */\n  class DelayedTypeInfo(val decl: NuDecl, val outerVars: Map[Str, SimpleType])\n          (implicit val ctx: Ctx, val raise: Raise) extends LazyTypeInfo with DelayedTypeInfoImpl\n  object DelayedTypeInfo {\n    def unapply(dti: DelayedTypeInfo): S[NuDecl] =\n      S(dti.decl)\n  }\n  \n  /** A type with universally quantified type variables\n    * (by convention, those variables of level greater than `level` are considered quantified). */\n  case class PolymorphicType(polymLevel: Level, body: SimpleType) // TODO add own type provenance for consistency\n      extends SimpleType with PolymorphicTypeImpl {\n    require(polymLevel < MaxLevel, polymLevel)\n    val prov: TypeProvenance = body.prov\n    lazy val level = levelBelow(polymLevel)(MutSet.empty)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = body.levelBelow(ub min polymLevel)\n    override def toString = s\"‹∀ $polymLevel. $body›\"\n  }\n  object PolymorphicType {\n    def mk(polymLevel: Level, body: SimpleType): SimpleType = {\n      require(polymLevel <= MaxLevel)\n      if (polymLevel === MaxLevel || body.level <= polymLevel) body\n      else body.unwrapProvs match { // Q: unwrap other proxies?\n        case PolymorphicType(lvl, bod) => PolymorphicType.mk(polymLevel min lvl, bod)\n        \n        // * Not very helpful (also seems to result in breaking some recursive types... not sure why):\n        // case tv @ AssignedVariable(ty) =>\n        //   PolymorphicType(polymLevel, ty)\n        // case tv: TV if tv.level > polymLevel && tv.assignedTo.isEmpty =>\n        //   PolymorphicType(polymLevel, tv.lowerBounds.foldLeft(BotType: ST)(_ | _))\n        \n        case _ => PolymorphicType(polymLevel, body)\n      }\n    }\n  }\n  object SplittablePolyFun {\n    def unapply(pt: PolymorphicType)(implicit ctx: Ctx, raise: Raise, shadows: Shadows): Opt[ST] =\n      if (distributeForalls) pt.splitFunction\n      else N\n  }\n  \n  /** A list of constraints. */\n  type Constrs = List[ST -> ST]\n  \n  case class ConstrainedType(constraints: Constrs, body: ST) extends SimpleType { // TODO add own prov?\n    val prov: TypeProvenance = body.prov\n    lazy val level =\n      children(false).iterator.map(_.level).max\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      children(false).iterator.map(_.levelBelow(ub)).max\n    override def toString: Str =\n      s\"{$body where: ${constraints.map {\n        case (lb, ub) => s\"$lb <: $ub\"\n      }.mkString(\", \")}}\"\n  }\n  object ConstrainedType {\n    def mk(constraints: Constrs, body: ST): ST =\n      if (constraints.isEmpty) body\n      else ConstrainedType(constraints, body)\n  }\n  \n  /** `body.get._1`: implicit `this` parameter\n    * `body.get._2`: actual body of the method\n    * `body` being `None` indicates an error:\n    *   - when this MethodType is computed from `MethodSet#processInheritedMethods`,\n    *     it means two or more parent classes defined or declared the method\n    *     and the current class did not override it;\n    *   - when this MethodType is obtained from the environment, it means the method is ambiguous,\n    *     which happens when two or more unrelated classes define or declare a method with the same name.\n    *     So note that in this case, it will have more than one parent.\n    *   Note: This is some fairly brittle and error-prone logic, which would gain to be refactored.\n    *     Especially aggravating is the fact that `toPT`/`bodyPT` return `errorType` when `body` is `None`,\n    *     whereas this case should probably be checked and carefully considered in each call site.\n    * `isInherited`: whether the method declaration comes from the intersection of multiple inherited declarations\n   */\n  case class MethodType(\n    level: Level,\n    body: Opt[(SimpleType, SimpleType)],\n    parents: List[TypeName],\n    isInherited: Bool,\n  )(val prov: TypeProvenance) {\n    def &(that: MethodType): MethodType = {\n      require(this.level === that.level)\n      MethodType(level, mergeOptions(this.body, that.body)((b1, b2) => (b1._1 & b2._1, b1._2 & b2._2)),\n        (this.parents ::: that.parents).distinct, isInherited = true)(prov)\n    }\n    val toPT: PolymorphicType =\n      body.fold(PolymorphicType(MinLevel, errType))(b => PolymorphicType(level, FunctionType(singleTup(b._1), b._2)(prov)))\n    val bodyPT: PolymorphicType =\n      body.fold(PolymorphicType(MinLevel, errType))(b => PolymorphicType(level, ProvType(b._2)(prov)))\n  }\n  \n  sealed abstract class TypeLike extends TypeLikeImpl {\n    def unwrapProvs: TypeLike\n  }\n  type TL = TypeLike\n  \n  abstract class OtherTypeLike extends TypeLike { this: TypedTypingUnit =>\n    def self: TypedTypingUnit = this\n    def unwrapProvs: TypeLike = this\n  }\n  object OtherTypeLike {\n    def unapply(ot: OtherTypeLike): S[TypedTypingUnit] = S(ot.self)\n  }\n  \n  /** A general type form (TODO: rename to AnyType). */\n  sealed abstract class SimpleType extends TypeLike with SimpleTypeImpl {\n    val prov: TypeProvenance\n    def level: Level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level\n    def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): SimpleType =\n      Typer.freshenAbove(lim, this, rigidify)\n    constructedTypes += 1\n  }\n  type ST = SimpleType\n  \n  sealed abstract class BaseTypeOrTag extends SimpleType\n  sealed abstract class BaseType extends BaseTypeOrTag {\n    def compareEquiv(that: BaseType): Int = (this, that) match {\n      case (a: TypeTag, b: TypeTag) => a.compare(b)\n      case (a: TypeTag, _) => -1\n      case (_, b: TypeTag) => 1\n      case (_: FunctionType, _: FunctionType) => 0\n      case (_: FunctionType, _) => -1\n      case (_, _: FunctionType) => 1\n      case (_: ArrayType, _: ArrayType) => 0\n      case (_: ArrayType, _) => -1\n      case (_, _: ArrayType) => 1\n      case (_: TupleType, _: TupleType) => 0\n      case (_: TupleType, _) => -1\n      case (_, _: TupleType) => 1\n      case (_: Without, _: Without) => 0\n      case (_: Without, _) => -1\n      case (_, _: Without) => 1\n      case (_: Overload, _: Overload) => 0\n      case (_: Overload, _) => -1\n      case (_, _: Overload) => 1\n      case (_: SpliceType, _: SpliceType) => 0\n    }\n    def toRecord: RecordType = RecordType.empty\n    protected def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): BaseType\n    override def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): BaseType =\n      freshenAboveImpl(lim, rigidify)\n  }\n  sealed abstract class MiscBaseType extends BaseType {\n    override def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): MiscBaseType\n  }\n  sealed trait Factorizable extends SimpleType\n  \n  type FT = FunctionType\n  \n  case class FunctionType(lhs: SimpleType, rhs: SimpleType)(val prov: TypeProvenance) extends MiscBaseType {\n    lazy val level: Int = lhs.level max rhs.level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = lhs.levelBelow(ub) max rhs.levelBelow(ub)\n    def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): FunctionType =\n      FunctionType(lhs.freshenAbove(lim, rigidify), rhs.freshenAbove(lim, rigidify))(prov)\n    override def toString = s\"(${lhs match {\n      case TupleType((N, FieldType(N, f: TupleType)) :: Nil) => \"[\" + f.showInner + \"]\"\n      case TupleType((N, f) :: Nil) => f.toString\n      case lhs => lhs\n    }} -> $rhs)\"\n  }\n  \n  case class Overload(alts: Ls[FunctionType])(val prov: TypeProvenance) extends MiscBaseType {\n    require(alts.lengthIs > 0)\n    def mapAlts(lf: ST => ST)(rf: ST => ST): Overload =\n      Overload(alts.map(ft => FunctionType(lf(ft.lhs), rf(ft.rhs))(ft.prov)))(prov)\n    def mapAltsPol(pol: Opt[Bool])(f: (Opt[Bool], SimpleType) => SimpleType): Overload =\n      Overload(alts.map(ft => FunctionType(f(pol.map(!_), ft.lhs), f(pol, ft.rhs))(ft.prov)))(prov)\n    def mapAltsPol(pol: PolMap)(f: (PolMap, SimpleType) => SimpleType): Overload =\n      Overload(alts.map(ft => FunctionType(f(pol.contravar, ft.lhs), f(pol, ft.rhs))(ft.prov)))(prov)\n    def approximatePos: FunctionType = {\n      val (lhss, rhss) = alts.map(ft => ft.lhs -> ft.rhs).unzip\n      FunctionType(lhss.reduce(_ | _), rhss.reduce(_ | _))(prov)\n      // * Note: technically the following is another valid (but probably less useful)\n      // * approximation of the same function type:\n      // FunctionType(lhss.reduce(_ & _), rhss.reduce(_ & _))(prov)\n    }\n    lazy val level: Level = levelBelow(MaxLevel)(MutSet.empty)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      alts.iterator.map(_.levelBelow(ub)).max\n    def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): Overload =\n      Overload(alts.map(_.freshenAboveImpl(lim, rigidify)))(prov)\n  }\n  object Overload {\n    def mk(alts: Ls[FunctionType])(prov: TypeProvenance): ST = alts match {\n      case Nil => mkProxy(TopType, prov)\n      case ft :: Nil => mkProxy(ft, prov)\n      case alts => Overload(alts)(prov)\n    }\n  }\n  \n  case class RecordType(fields: List[(Var, FieldType)])(val prov: TypeProvenance) extends SimpleType {\n    // TODO: assert no repeated fields\n    lazy val level: Level = levelBelow(MaxLevel)(MutSet.empty)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = fields.iterator.map(_._2.levelBelow(ub)).maxOption.getOrElse(MinLevel)\n    override def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): RecordType =\n      Typer.mapPol(this, N, false)((_, x) => x.freshenAbove(lim, rigidify))\n    def toInter: SimpleType =\n      fields.map(f => RecordType(f :: Nil)(prov)).foldLeft(TopType: ST)(((l, r) => ComposedType(false, l, r)(noProv)))\n    def mergeAllFields(fs: Iterable[Var -> FieldType]): RecordType = {\n      val res = mutable.SortedMap.empty[Var, FieldType]\n      fs.foreach(f => res.get(f._1) match {\n        case N => res(f._1) = f._2\n        case S(ty) => res(f._1) = ty && f._2\n      })\n      RecordType(res.toList)(prov)\n    }\n    def addFields(fs: Ls[Var -> FieldType]): RecordType = {\n      val shadowing = fs.iterator.map(_._1).toSet\n      RecordType(fields.filterNot(f => shadowing(f._1)) ++ fs)(prov)\n    }\n    def sorted: RecordType = RecordType(fields.sortBy(_._1))(prov)\n    override def toString = s\"{${fields.map(f => s\"${f._1.name}: ${f._2}\").mkString(\", \")}}\"\n  }\n  object RecordType {\n    def empty: RecordType = RecordType(Nil)(noProv)\n    def mk(fields: List[(Var, FieldType)])(prov: TypeProvenance = noProv): SimpleType =\n      if (fields.isEmpty) ExtrType(false)(prov) else RecordType(fields)(prov)\n  }\n  \n  sealed abstract class ArrayBase extends MiscBaseType {\n    def inner: FieldType\n  }\n  \n  case class ArrayType(val inner: FieldType)(val prov: TypeProvenance) extends ArrayBase {\n    def level: Level = inner.level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = inner.levelBelow(ub)\n    def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): ArrayType =\n      ArrayType(inner.freshenAbove(lim, rigidify))(prov)\n    override def toString = s\"Array‹$inner›\"\n  }\n  \n  case class TupleType(fields: List[Opt[Var] -> FieldType])(val prov: TypeProvenance) extends ArrayBase {\n    lazy val inner: FieldType = fields.map(_._2).reduceLeftOption(_ || _).getOrElse(BotType.toUpper(noProv))\n    lazy val level: Level = fields.iterator.map(_._2.level).maxOption.getOrElse(0)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = fields.iterator.map(_._2.levelBelow(ub)).maxOption.getOrElse(MinLevel)\n    def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): TupleType =\n      TupleType(fields.mapValues(_.freshenAbove(lim, rigidify)))(prov)\n    lazy val toArray: ArrayType = ArrayType(inner)(prov)  // upcast to array\n    override lazy val toRecord: RecordType =\n      RecordType(\n        fields.zipWithIndex.map { case ((_, t), i) => (Var(i.toString), t) }\n        // Note: In line with TypeScript, tuple field names are pure type system fictions,\n        //    with no runtime existence. Therefore, they should not be included in the record type\n        //    corresponding to this tuple type.\n        //    i.e., no `::: fields.collect { case (S(n), t) => (n, t) }`\n      )(prov)\n    def showInner: Str =\n      fields.map(f => s\"${f._1.fold(\"\")(_.name+\": \")}${f._2},\").mkString(\" \")\n    override def toString = s\"($showInner)\"\n    // override def toString = s\"(${fields.map(f => s\"${f._1.fold(\"\")(_+\": \")}${f._2},\").mkString(\" \")})\"\n  }\n\n  case class SpliceType(elems: Ls[Either[SimpleType, FieldType]])(val prov: TypeProvenance) extends ArrayBase {\n    require(elems.nonEmpty) // ? – since `max` is used below...\n    lazy val level: Int = elems.map{ case L(l) => l.level case R(r) => r.level }.max\n    \n    def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV,ST]): MiscBaseType =\n      SpliceType(elems.map{ case L(l) => L(l.freshenAbove(lim, rigidify)) case R(r) => R(r.freshenAbove(lim, rigidify)) })(prov)\n    \n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      elems.map{ case L(l) => l.levelBelow(ub) case R(r) => r.levelBelow(ub) }.max\n    \n    lazy val inner: FieldType = elems.map {\n      case L(l) => l match { case a: ArrayBase => a.inner case _ => ??? }\n      case R(r) => r\n    }.reduceLeft(_ || _)\n\n    def updateElems(f: SimpleType => SimpleType, g: SimpleType => SimpleType, \n      h: SimpleType => SimpleType,newProv: TypeProvenance = prov): SpliceType =\n      SpliceType(elems.map{case L(l) => L(f(l)) case R(r) => R(r.update(g, h))})(newProv)\n  }\n  \n  /** Polarity `pol` being `true` means Bot; `false` means Top. These are extrema of the subtyping lattice. */\n  case class ExtrType(pol: Bool)(val prov: TypeProvenance) extends SimpleType {\n    def level: Level = MinLevel\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = MinLevel\n    override def toString = if (pol) \"⊥\" else \"⊤\"\n  }\n  \n  /** Represents a type variable skolem that was extruded outsdie its polym level.\n    * The goal is to retain precise information to produce good errors,\n    * but still have this be functionally equivalent to `ExtrType(pol)`. */\n  case class Extruded(pol: Bool, underlying: SkolemTag)(val prov: TypeProvenance, val reason: Ls[Ls[ST]]) extends AbstractTag with TypeVarOrRigidVar {\n    val level: Level = MinLevel\n    val id = underlying.id\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = 0\n    override def toString = if (pol) s\"⊥(${underlying})\" else s\"⊤(${underlying})\"\n  }\n  \n  /** Polarity `pol` being `true` means union; `false` means intersection. */\n  case class ComposedType(pol: Bool, lhs: SimpleType, rhs: SimpleType)(val prov: TypeProvenance) extends SimpleType {\n    def level: Level = lhs.level max rhs.level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = lhs.levelBelow(ub) max rhs.levelBelow(ub)\n    override def toString = s\"($lhs ${if (pol) \"|\" else \"&\"} $rhs)\"\n  }\n  case class NegType(negated: SimpleType)(val prov: TypeProvenance) extends SimpleType {\n    def level: Level = negated.level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = negated.levelBelow(ub)\n    override def toString = s\"~(${negated})\"\n  }\n  \n  /** Represents a type `base` from which we have removed the fields in `names`. */\n  case class Without(base: SimpleType, names: SortedSet[Var])(val prov: TypeProvenance) extends MiscBaseType {\n    def level: Int = base.level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = base.levelBelow(ub)\n    def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): Without =\n      Without(base.freshenAbove(lim, rigidify), names)(prov)\n    override def toString = s\"${base}\\\\${names.mkString(\"-\")}\"\n  }\n  \n  /** A proxy type is a derived type form storing some additional information,\n    * but which can always be converted into an underlying simple type. */\n  sealed abstract class ProxyType extends SimpleType {\n    def level: Level = underlying.level\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = underlying.levelBelow(ub)\n    def underlying: SimpleType\n    override def toString = s\"[$underlying]\"\n  }\n  object ProxyType {\n    def unapply(proxy: ProxyType): S[ST] =\n      S(proxy.underlying)\n  }\n  \n  /** The sole purpose of ProvType is to store additional type provenance info. */\n  case class ProvType(underlying: SimpleType)(val prov: TypeProvenance) extends ProxyType {\n    override def toString = s\"$underlying\"\n    // override def toString = s\"[$underlying]\"\n    // override def toString = s\"$underlying[${prov.desc.take(5)}]\"\n    // override def toString = s\"$underlying[${prov.toString.take(5)}]\"\n    // override def toString = s\"$underlying@${prov.loco.fold(\"?\")(l => l.spanStart+\"–\"+l.spanEnd)}\"\n    // override def toString = showProvOver(true)(\"\"+underlying)\n    \n    // TOOD override equals/hashCode? — could affect hash consing...\n    // override def equals(that: Any): Bool = super.equals(that) || underlying.equals(that)\n    // override def equals(that: Any): Bool = unwrapProxies.equals(that)\n  }\n  \n  /** A proxy type, `S with {x: T; ...}` is equivalent to `S\\x\\... & {x: T; ...}`. */\n  case class WithType(base: SimpleType, rcd: RecordType)(val prov: TypeProvenance) extends ProxyType {\n    lazy val underlying: ST =\n      base.without(rcd.fields.iterator.map(_._1).toSortedSet) & rcd\n    override def toString = s\"${base} w/ ${rcd}\"\n  }\n  \n  type TR = TypeRef\n  val TR: TypeRef.type = TypeRef\n  case class TypeRef(defn: TypeName, targs: Ls[SimpleType])(val prov: TypeProvenance) extends SimpleType with TypeRefImpl {\n    def level: Level = targs.iterator.map(_.level).maxOption.getOrElse(MinLevel)\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = targs.iterator.map(_.levelBelow(ub)).maxOption.getOrElse(MinLevel)\n    override def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): TypeRef =\n      TypeRef(defn, targs.map(_.freshenAbove(lim, rigidify)))(prov)\n    override def toString = showProvOver(false) {\n      val displayName =\n        if (primitiveTypes.contains(defn.name)) defn.name.capitalize else defn.name\n      if (targs.isEmpty) displayName else s\"$displayName[${targs.mkString(\",\")}]\"\n    }\n  }\n  \n  sealed trait TypeTag extends BaseTypeOrTag with Ordered[TypeTag] {\n    val id: IdentifiedTerm\n    def compare(that: TypeTag): Int = (this, that) match {\n      case (obj1: ObjectTag, obj2: ObjectTag) => obj1.id compare obj2.id\n      case (SkolemTag(id1), SkolemTag(id2)) => id1 compare id2\n      case (Extruded(_, id1), Extruded(_, id2)) => id1 compare id2\n      case (_: ObjectTag, _: SkolemTag | _: Extruded) => -1\n      case (_: SkolemTag | _: Extruded, _: ObjectTag) => 1\n      case (_: SkolemTag, _: Extruded) => -1\n      case (_: Extruded, _: SkolemTag) => 1\n    }\n  }\n  \n  case class ClassTag(id: SimpleTerm, parents: Set[TypeName])(val prov: TypeProvenance)\n      extends BaseType with TypeTag with ObjectTag {\n    def glb(that: ClassTag): Opt[ClassTag] =\n      if (that.id === this.id) S(this)\n      else if (that.parentsST.contains(this.id)) S(that)\n      else if (this.parentsST.contains(that.id)) S(this)\n      else N\n    def lub(that: ClassTag): Set[ClassTag] = // TODO rm? it's unused\n      if (that.id === this.id) Set.single(that)\n      else if (that.parentsST.contains(this.id)) Set.single(this)\n      else if (this.parentsST.contains(that.id)) Set.single(that)\n      // else this.parentsST.union(that.parentsST)\n      else Set(this, that)\n    def level: Level = MinLevel\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = MinLevel\n    def freshenAboveImpl(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): this.type = this\n  }\n  \n  sealed trait TypeVarOrRigidVar extends SimpleType\n  \n  sealed trait ObjectTag extends TypeTag {\n    val id: SimpleTerm\n    val parents: Set[TypeName]\n    lazy val parentsST = parents.iterator.map(tn => Var(tn.name)).toSet[IdentifiedTerm]\n    override def toString = \"#\" + showProvOver(false)(id.idStr+s\"<${parents.map(_.name).mkString(\",\")}>\")\n  }\n  \n  sealed abstract class AbstractTag extends BaseTypeOrTag with TypeTag with Factorizable\n  \n  case class TraitTag(id: Var, parents: Set[TypeName])(val prov: TypeProvenance) extends AbstractTag with ObjectTag {\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = MinLevel\n    def level: Level = MinLevel\n  }\n  \n  case class SkolemTag(id: TV)(val prov: TypeProvenance) extends AbstractTag with TypeVarOrRigidVar {\n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      id.levelBelow(ub)\n    val level: Level = id.level\n    override def toString = {\n      val str = id.mkStr\n      // (if (id.idStr.startsWith(\"'\")) \"‘\"+id.idStr.tail else id.idStr) + showLevel(level)\n      \"‘\"+(if (str.startsWith(\"'\")) str.tail else str) + (if (str.last==='\\'') \"_\" else \"\") + showLevel(level)\n    }\n  }\n  \n  /** `TypeBounds(lb, ub)` represents an unknown type between bounds `lb` and `ub`.\n    * The only way to give something such a type is to make the type part of a def or method signature,\n    * as it will be replaced by a fresh bounded type variable upon subsumption checking (cf rigidification). */\n  case class TypeBounds(lb: SimpleType, ub: SimpleType)(val prov: TypeProvenance) extends SimpleType {\n    def level: Level = lb.level max ub.level\n    def levelBelow(ubLvl: Level)(implicit cache: MutSet[TV]): Int = lb.levelBelow(ubLvl) max ub.levelBelow(ubLvl)\n    override def toString = s\"$lb..$ub\"\n  }\n  object TypeBounds {\n    final def mkSimple(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv): SimpleType = (lb, ub) match {\n      case (TypeBounds(lb, _), ub) => mkSimple(lb, ub, prov)\n      case (lb, TypeBounds(_, ub)) => mkSimple(lb, ub, prov)\n      case _ => TypeBounds(lb, ub)(prov)\n    }\n    final def mk(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv)(implicit ctx: Ctx): SimpleType =\n      if ((lb is ub)\n        || lb === ub\n        || !lb.mentionsTypeBounds && !ub.mentionsTypeBounds && lb <:< ub && ub <:< lb\n      ) lb else (lb, ub) match {\n        case _ => mkSimple(lb, ub, prov)\n      }\n    /** A version of `mk` that does not check for subtyping,\n      * to be used in type simplification code which modifies subtype bounds on the fly\n      * (in particular, the `transform` function may replace TV bounds `TypeBound` bundles,\n      * and creating these `TypeBound`s should NOT rely on the bounds still being there at the time\n      * the bundle is constructed). */\n    final def mkSafe(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv)(implicit ctx: Ctx): SimpleType =\n      if ((lb is ub)\n        || lb === ub\n      ) lb else (lb, ub) match {\n        case _ => mkSimple(lb, ub, prov)\n      }\n  }\n  \n  case class FieldType(lb: Option[SimpleType], ub: SimpleType)(val prov: TypeProvenance) {\n    def level: Int = lb.map(_.level).getOrElse(ub.level) max ub.level\n    def levelBelow(ubLvl: Level)(implicit cache: MutSet[TV]): Level =\n      lb.fold(MinLevel)(_.levelBelow(ubLvl)) max ub.levelBelow(ubLvl)\n    def <:< (that: FieldType)(implicit ctx: Ctx, cache: MutMap[ST -> ST, Bool] = MutMap.empty): Bool =\n      (that.lb.getOrElse(BotType) <:< this.lb.getOrElse(BotType)) && (this.ub <:< that.ub)\n    def && (that: FieldType, prov: TypeProvenance = noProv): FieldType =\n      FieldType(lb.fold(that.lb)(l => Some(that.lb.fold(l)(l | _))), ub & that.ub)(prov)\n    def || (that: FieldType, prov: TypeProvenance = noProv): FieldType =\n      FieldType(for {l <- lb; r <- that.lb} yield (l & r), ub | that.ub)(prov)\n    def update(lb: SimpleType => SimpleType, ub: SimpleType => SimpleType): FieldType =\n      FieldType(this.lb.map(lb), ub(this.ub))(prov)\n    def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): FieldType =\n      update(_.freshenAbove(lim, rigidify), _.freshenAbove(lim, rigidify))\n    override def toString =\n      lb.fold(s\"$ub\")(lb => s\"mut ${if (lb === BotType) \"\" else lb}..$ub\")\n  }\n  object FieldType {\n    def mk(vi: VarianceInfo, lb: ST, ub: ST)(prov: TP): FieldType = vi match {\n      case VarianceInfo(true, true) => FieldType(N, TopType)(prov)\n      case VarianceInfo(true, false) => FieldType(N, ub)(prov)\n      case VarianceInfo(false, true) => FieldType(S(lb), TopType)(prov)\n      case VarianceInfo(false, false) => FieldType(S(lb), ub)(prov)\n    }\n  }\n  \n  val createdTypeVars: Buffer[TV] = Buffer.empty\n  \n  /** A type variable living at a certain polymorphism level `level`, with mutable bounds.\n    * Invariant: Types appearing in the bounds never have a level higher than this variable's `level`. */\n  final class TypeVariable(\n      val level: Level,\n      var _lowerBounds: List[SimpleType],\n      var _upperBounds: List[SimpleType],\n      originalTV: Opt[TV],\n      val nameHint: Opt[Str] = N,\n      val recPlaceholder: Bool = false\n    )(val prov: TypeProvenance)\n    extends SimpleType\n      with TypeVarOrRigidVar\n      with Ordered[TypeVariable]\n      with Factorizable\n      with IdentifiedTerm\n  {\n    require(level <= MaxLevel)\n    \n    if (recordTypeVars) createdTypeVars += this\n    \n    // var assignedTo: Opt[ST] = N\n    private var _assignedTo: Opt[ST] = N\n    def assignedTo: Opt[ST] = _assignedTo\n    def assignedTo_=(value: Opt[ST]): Unit = {\n      require(value.forall(_.level <= level))\n      _assignedTo = value\n    }\n\n    val tsc: LinkedHashMap[TupleSetConstraints, Set[Int]] = LinkedHashMap.empty\n    \n    // * Bounds should always be disregarded when `equatedTo` is defined, as they are then irrelevant:\n    def lowerBounds: List[SimpleType] = { require(assignedTo.isEmpty, this); _lowerBounds }\n    def upperBounds: List[SimpleType] = { require(assignedTo.isEmpty, this); _upperBounds }\n    def lowerBounds_=(bs: Ls[ST]): Unit = { require(assignedTo.isEmpty, this); _lowerBounds = bs }\n    def upperBounds_=(bs: Ls[ST]): Unit = { require(assignedTo.isEmpty, this); _upperBounds = bs }\n    \n    private val creationRun = currentConstrainingRun\n    def original: TV =\n      if (currentConstrainingRun === creationRun) originalTV.getOrElse(this)\n      else this\n    private lazy val trueOriginal: Opt[TV] =\n      originalTV.flatMap(_.trueOriginal.orElse(originalTV))\n    \n    def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level =\n      if (level <= ub) level else {\n        if (cache(this)) MinLevel else {\n          cache += this\n          assignedTo match {\n            case S(ty) =>\n              ty.levelBelow(ub)\n            case N =>\n              (lowerBounds.iterator ++ upperBounds.iterator)\n                .map(_.levelBelow(ub)).maxOption.getOrElse(MinLevel)\n          }\n        }\n      }\n    private[mlscript] val uid: Int = freshUid\n    lazy val asTypeVar = new TypeVar(L(uid), nameHint)\n    lazy val (asPosExtrudedTypeVar, asNegExtrudedTypeVar) = {\n      val nme = S(ExtrusionPrefix+nameHint.getOrElse(\"_\").dropWhile(_ === '\\''))\n      (new TypeVar(L(freshUid), nme), new TypeVar(L(freshUid), nme))\n    }\n    def compare(that: TV): Int = this.uid compare that.uid\n    override def toString: String =\n      (trueOriginal match {\n        case S(to) =>\n          assert(to.nameHint === nameHint, (to.nameHint, nameHint))\n          to.mkStr + \"_\" + uid + showLevel(level)\n        case N =>\n          showProvOver(false)(mkStr + showLevel(level))\n      }) + (if (assignedTo.isDefined) \"#\" else \"\")\n    private[mlscript] def mkStr = nameHint.getOrElse(\"α\") + uid\n    \n    // * `omitIrrelevantVars` omits top-level as well as quantified variable occurrences\n    final def isRecursive_$(omitIrrelevantVars: Bool)(implicit ctx: Ctx) : Bool =\n      isPosRecursive_$(omitIrrelevantVars) || isNegRecursive_$(omitIrrelevantVars)\n    // * Variables occurring strictly negatively in their own lower bound\n    // * (resp. strictly positively in their own upper bound, ie contravariantly)\n    // * are NOT recursive, as these occurrences only demonstrate \"spurious\" cycles\n    // * which are easily removed.\n    final def isPosRecursive_$(omitIrrelevantVars: Bool)(implicit ctx: Ctx) : Bool = lbRecOccs_$(omitIrrelevantVars) match {\n      case S(N | S(true)) => true\n      case _ => false\n    }\n    final def isNegRecursive_$(omitIrrelevantVars: Bool)(implicit ctx: Ctx) : Bool = ubRecOccs_$(omitIrrelevantVars) match {\n      case S(N | S(false)) => true\n      case _ => false\n    }\n    /** None: not recursive in this bound; Some(Some(pol)): polarly-recursive; Some(None): nonpolarly-recursive.\n      * Note that if we have something like 'a :> Bot <: 'a -> Top, 'a is not truly recursive\n      *   and its bounds can actually be inlined.\n      * Also note that unfortunately, contrary to whta I previously thought,\n      * it is not sound to ignore quantified variables during the getVarsPol search.\n      * indeed, we can be in freaky situations like in `ListBuild.mls`\n      * where we have `'a :> Ls[('x, forall 'a. 'a)]`! */\n    private[mlscript] final def lbRecOccs_$(omitIrrelevantVars: Bool)(implicit ctx: Ctx): Opt[Opt[Bool]] = {\n      // println(\"+\", this, assignedTo getOrElse lowerBounds)\n      // assignedTo.getOrElse(TupleType(lowerBounds.map(N -> _.toUpper(noProv)))(noProv)).getVarsPol(PolMap.pos, ignoreTopLevelOccs = true).get(this)\n      val bs = assignedTo.fold(lowerBounds)(_ :: Nil)\n      bs.foldLeft(BotType: ST)(_ | _).getVarsPol(PolMap.pos,\n        ignoreTopLevelOccs = omitIrrelevantVars,\n        // ignoreQuantifiedVars = omitIrrelevantVars,\n        ignoreQuantifiedVars = false,\n      ).get(this)\n    }\n    private[mlscript] final def ubRecOccs_$(omitIrrelevantVars: Bool)(implicit ctx: Ctx): Opt[Opt[Bool]] ={\n      // println(\"-\", this, assignedTo getOrElse upperBounds)\n      // assignedTo.getOrElse(TupleType(upperBounds.map(N -> _.toUpper(noProv)))(noProv)).getVarsPol(PolMap.posAtNeg, ignoreTopLevelOccs = true).get(this)\n      val bs = assignedTo.fold(upperBounds)(_ :: Nil)\n      bs.foldLeft(TopType: ST)(_ & _).getVarsPol(PolMap.posAtNeg,\n        ignoreTopLevelOccs = omitIrrelevantVars,\n        // ignoreQuantifiedVars = omitIrrelevantVars,\n        ignoreQuantifiedVars = false,\n      ).get(this)\n        // .tap(r => println(s\"= $r\"))\n    }\n  }\n  type TV = TypeVariable\n  private var freshCount = 0\n  private def freshUid: Int = { freshCount += 1; freshCount - 1 }\n  def freshVar(p: TypeProvenance, original: Opt[TV], nameHint: Opt[Str] = N, lbs: Ls[ST] = Nil, ubs: Ls[ST] = Nil, recPlaceholder: Bool = false)\n        (implicit lvl: Int): TypeVariable =\n    new TypeVariable(lvl, lbs, ubs, original, nameHint, recPlaceholder)(p)\n  def resetState(): Unit = {\n    freshCount = 0\n  }\n  \n  type PolarVariable = (TypeVariable, Boolean)\n  \n  object AssignedVariable {\n    def unapply(tv: TV): Opt[ST] = tv.assignedTo\n  }\n  \n  case class NegVar(tv: TV) extends ProxyType with Factorizable {\n    lazy val underlying: SimpleType = tv.neg()\n    val prov = noProv\n  }\n  case class NegAbsTag(tt: AbstractTag) extends ProxyType with Factorizable {\n    lazy val underlying: SimpleType = tt.neg()\n    val prov = noProv\n  }\n\n  class TupleSetConstraints(var constraints: Ls[Ls[ST]], var tvs: Ls[(Bool, ST)]) {\n    def updateImpl(index: Int, bound: ST)(implicit raise: Raise, ctx: Ctx) : Unit = {\n      val u0 = constraints.flatMap { c =>\n        TupleSetConstraints.lcg(tvs(index)._1, bound, c(index)).map(tvs.zip(c)++_)\n      }\n      val u = u0.map { x =>\n        x.groupMap(_._1)(_._2).map { case (u@(p,_),l) =>\n          (u,l.reduce((x,y) => ComposedType(!p,x,y)(noProv)))\n        }\n      }\n      if (!u.isEmpty) {\n        tvs.values.map(_.unwrapProxies).foreach {\n          case tv: TV => tv.tsc += this -> Set.empty\n          case _ => ()\n        }\n        tvs = u.flatMap(_.keys).distinct\n        constraints = tvs.map(x => u.map(_.getOrElse(x,if (x._1) TopType else BotType))).transpose\n        tvs.values.map(_.unwrapProxies).zipWithIndex.foreach {\n          case (tv: TV, i) => tv.tsc.updateWith(this)(_.map(_ + i).orElse(S(Set(i))))\n          case _ => ()\n        }\n      } else {\n        constraints = Nil\n      }\n    }\n    def updateOn(index: Int, bound: ST)(implicit raise: Raise, ctx: Ctx) : Unit = {\n      updateImpl(index, bound)\n      println(s\"TSC update: $tvs in $constraints\")\n    }\n  }\n  object TupleSetConstraints {\n    def lcgField(pol: Bool, first: FieldType, rest: FieldType)(implicit ctx: Ctx)\n        : Opt[Ls[(Bool, ST) -> ST]] = {\n      for {\n        ubm <- lcg(pol, first.ub, rest.ub)\n        lbm <- {\n          if (first.lb.isEmpty && rest.lb.isEmpty)\n            S(Nil)\n          else\n            lcg(!pol, first.lb.getOrElse(BotType), rest.lb.getOrElse(BotType))\n        }\n      } yield {\n        ubm ++ lbm\n      }\n    }\n    def lcg(pol: Bool, first: ST, rest: ST)(implicit ctx: Ctx)\n        : Opt[Ls[(Bool, ST) -> ST]] = (first.unwrapProxies, rest.unwrapProxies) match {\n      case (a, ExtrType(p)) if p =/= pol => S(Nil)\n      case (a, ComposedType(p,l,r)) if p =/= pol =>\n        for {\n          lm <- lcg(pol,a,l)\n          rm <- lcg(pol,a,r)\n        } yield {\n          lm ++ rm\n        }\n      case (a: TV, b: TV) if a.compare(b) === 0 => S(Nil)\n      case (a: TV, b) => S(List((pol, first) -> rest))\n      case (a, b: TV) => S(List((pol, first) -> rest))\n      case (a: FT, b: FT) => lcgFunction(pol, a, b)\n      case (a: ArrayType, b: ArrayType) => lcgField(pol, a.inner, b.inner)\n      case (a: TupleType, b: TupleType) if a.fields.sizeCompare(b.fields) === 0 =>\n        val fs = a.fields.map(_._2).zip(b.fields.map(_._2)).map(u => lcgField(pol, u._1, u._2))\n        if (!fs.contains(N)) {\n          S(fs.flatten.reduce(_++_))\n        } else N\n      case (a: TupleType, b: RecordType) if pol => lcg(pol, a.toRecord, b)\n      case (a: RecordType, b: RecordType) =>\n        val default = FieldType(N, if (pol) TopType else BotType)(noProv)\n        if (b.fields.map(_._1).forall(a.fields.map(_._1).contains)) {\n          val u = a.fields.map {\n            case (v, f) => lcgField(pol, f, b.fields.find(_._1 === v).fold(default)(_._2))\n          }\n          if (!u.contains(N)) {\n            S(u.flatten.reduce(_++_))\n          } else N\n        } else N\n      case (a, b) if a === b => S(Nil)\n      case (a, b) =>\n        val dnf = DNF.mk(MaxLevel, Nil, if (pol) a & b.neg() else b & a.neg(), true)\n        if (dnf.isBot)\n          S(Nil)\n        else if (dnf.cs.forall(c => !(c.vars.isEmpty && c.nvars.isEmpty)))\n          S(List((pol, first) -> rest))\n        else N\n    }\n    def lcgFunction(pol: Bool, first: FT, rest: FT)(implicit ctx: Ctx)\n        : Opt[Ls[(Bool, ST) -> ST]] = {\n      for {\n        lm <- lcg(!pol, first.lhs, rest.lhs)\n        rm <- lcg(pol, first.rhs, rest.rhs)\n      } yield {\n        lm ++ rm\n      }\n    }\n    def mk(ov: Overload, f: FT)(implicit raise: Raise, ctx: Ctx): Opt[TupleSetConstraints] = {\n      val u = ov.alts.flatMap(lcgFunction(false, f, _)).map { x =>\n        x.groupMap(_._1)(_._2).map { case (u@(p,_),l) =>\n          (u,l.reduce((x,y) => ComposedType(!p,x,y)(noProv)))\n        }\n      }\n      if (u.isEmpty) { return N }\n      val tvs = u.flatMap(_.keys).distinct\n      val m = tvs.map(x => u.map(_.getOrElse(x,if (x._1) TopType else BotType)))\n      val tsc = new TupleSetConstraints(m.transpose, tvs)\n      tvs.values.map(_.unwrapProxies).zipWithIndex.foreach {\n        case (tv: TV, i) => tv.tsc.updateWith(tsc)(_.map(_ + i).orElse(S(Set(i))))\n        case _ => ()\n      }\n      println(s\"TSC mk: ${tsc.tvs} in ${tsc.constraints}\")\n      S(tsc)\n    }\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/TyperHelpers.scala",
    "content": "package mlscript\n\nimport scala.collection.mutable.{Map => MutMap, SortedMap => MutSortMap, Set => MutSet, LinkedHashMap, LinkedHashSet}\nimport scala.collection.immutable.{SortedMap, SortedSet}\nimport scala.annotation.tailrec\nimport mlscript.utils._, shorthands._\n\n/** Inessential methods used to help debugging. */\nabstract class TyperHelpers { Typer: Typer =>\n  \n  type CompareRecTypes >: Bool\n  \n  protected var constrainCalls = 0\n  protected var annoyingCalls = 0\n  protected var subtypingCalls = 0\n  protected var constructedTypes = 0\n  def stats: (Int, Int, Int, Int) =\n    (constrainCalls, annoyingCalls, subtypingCalls, constructedTypes)\n  def resetStats(): Unit = {\n    constrainCalls = 0\n    annoyingCalls  = 0\n    subtypingCalls = 0\n    constructedTypes = 0\n  }\n  \n  protected val noPostTrace: Any => String = _ => \"\"\n  \n  protected var indent = 0\n  def trace[T](pre: => String)(thunk: => T)(post: T => String = noPostTrace): T = {\n    println(pre)\n    indent += 1\n    val res = try thunk finally indent -= 1\n    if (post isnt noPostTrace) println(post(res))\n    res\n  }\n  @inline def traceNot[T](pre: => String)(thunk: => T)(post: T => String = noPostTrace): T =\n    thunk\n  \n  def emitDbg(str: String): Unit = scala.Predef.println(str)\n  \n  // Shadow Predef functions with debugging-flag-enabled ones:\n  \n  def println(msg: => Any): Unit = if (dbg) emitDbg(\"| \" * indent + msg)\n  \n  /** A more advanced println version to show where things are printed from. */\n  // def println(msg: => Any)(implicit file: sourcecode.FileName, line: sourcecode.Line): Unit =\n  //   if (dbg) {\n  //     emitDbg((if (showPrintPrefix) {\n  //       val prefix = s\"[${file.value}:${line.value}]\"\n  //       prefix + \" \" * (30 - prefix.length)\n  //     } else \"\") + \"| \" * indent + msg)\n  //   }\n  // val showPrintPrefix =\n  //   // false\n  //   true\n  \n  def dbg_assert(assertion: => Boolean): Unit = if (dbg) scala.Predef.assert(assertion)\n  // def dbg_assert(assertion: Boolean): Unit = scala.Predef.assert(assertion)\n  \n  \n  final def printPol(pol: Bool): Str = pol match {\n    case true => \"+\"\n    case false => \"-\"\n  }\n  final def printPol(pol: Opt[Bool]): Str = pol match {\n    case S(p) => printPol(p)\n    case N => \"=\"\n  }\n  def printPol(pol: PolMap): Str = printPol(pol.base)\n  \n  def recordIntersection(fs1: Ls[Var -> FieldType], fs2: Ls[Var -> FieldType]): Ls[Var -> FieldType] =\n    mergeMap(fs1, fs2)(_ && _).toList\n  \n  def recordUnion(fs1: Ls[Var -> FieldType], fs2: Ls[Var -> FieldType]): Ls[Var -> FieldType] = {\n    val fs2m = fs2.toMap\n    fs1.flatMap { case (k, v) => fs2m.get(k).map(v2 => k -> (v || v2)) }\n  }\n  \n  /** Note that this version of `subst` intentionally substitutes unhygienically\n    * over the outer polymorphic type, as needed by the class typing infrastructure. */\n  def subst(ts: PolymorphicType, map: Map[SimpleType, SimpleType])\n        (implicit ctx: Ctx): PolymorphicType = \n    PolymorphicType(ts.polymLevel, subst(ts.body, map))\n  \n  def substLike(ty: TL, map: Map[SimpleType, SimpleType], substInMap: Bool)(implicit ctx: Ctx): TL = ty match {\n    case ty: ST => subst(ty, map, substInMap)\n    case OtherTypeLike(ot) =>\n      TypedTypingUnit(\n        ot.implementedMembers.map(_.map(subst(_, map, substInMap))),\n        ot.result.map(subst(_, map, substInMap)))\n  }\n  def subst(st: SimpleType, map: Map[SimpleType, SimpleType], substInMap: Bool = false)\n        (implicit ctx: Ctx): SimpleType = {\n    val cache: MutMap[TypeVariable, SimpleType] = MutMap.empty\n    implicit val freshened: MutMap[TV, ST] = MutMap.empty\n    val subsLvl: Level = map.valuesIterator.map(_.level).reduceOption(_ max _).getOrElse(MinLevel)\n    def go(st: SimpleType): SimpleType = {\n            // trace(s\"subst($st)\") {\n      map.get(st) match {\n        case S(res) => if (substInMap) go(res) else res\n        case N =>\n          st match {\n            case tv @ AssignedVariable(ty) => cache.getOrElse(tv, {\n              val v = freshVar(tv.prov, S(tv), tv.nameHint)(tv.level)\n              cache += tv -> v\n              v.assignedTo = S(go(ty))\n              v\n            })\n            case tv: TypeVariable if tv.lowerBounds.isEmpty && tv.upperBounds.isEmpty =>\n              cache += tv -> tv\n              tv\n            case tv: TypeVariable => cache.getOrElse(tv, {\n              val v = freshVar(tv.prov, S(tv), tv.nameHint)(tv.level)\n              cache += tv -> v\n              v.lowerBounds = tv.lowerBounds.map(go(_))\n              v.upperBounds = tv.upperBounds.map(go(_))\n              v\n            })\n            case poly: PolymorphicType if poly.polymLevel < subsLvl =>\n              go(poly.raiseLevelToImpl(subsLvl, Set.empty))\n            case _ => st.map(go(_))\n          }\n      }\n      // }(r => s\"= $r\")\n    }\n    go(st)\n  }\n  \n  /** Substitutes only at the syntactic level, without updating type variables nor traversing their bounds. */\n  def substSyntax(st: SimpleType)(map: PartialFunction[SimpleType, SimpleType]): SimpleType =\n    // trace(s\"substSyntax $st\") {\n      map.applyOrElse[ST, ST](st, _.map(substSyntax(_)(map)))\n    // }(r => s\"=> $r\")\n  \n  def tupleIntersection(fs1: Ls[Opt[Var] -> FieldType], fs2: Ls[Opt[Var] -> FieldType]): Ls[Opt[Var] -> FieldType] = {\n    require(fs1.size === fs2.size)\n    (fs1 lazyZip fs2).map {\n      case ((S(n1), t1), (S(n2), t2)) if n1 =/= n2 => (N, t1 && t2)\n      case ((no1, t1), (no2, t2)) => (no1 orElse no2, t1 && t2)\n    }\n  }\n  def tupleUnion(fs1: Ls[Opt[Var] -> FieldType], fs2: Ls[Opt[Var] -> FieldType]): Ls[Opt[Var] -> FieldType] = {\n    require(fs1.size === fs2.size)\n    (fs1 lazyZip fs2).map {\n      case ((S(n1), t1), (S(n2), t2)) => (Option.when(n1 === n2)(n1), t1 || t2)\n      case ((no1, t1), (no2, t2)) => (N, t1 || t2)\n    }\n  }\n  \n  def factorize(cs: Ls[Conjunct], sort: Bool): Ls[ST] = {\n    val factors = MutMap.empty[Factorizable, Int]\n    cs.foreach { c =>\n      c.vars.foreach { v =>\n        factors(v) = factors.getOrElse(v, 0) + 1\n      }\n      c.nvars.foreach { v =>\n        val nv = NegVar(v)\n        factors(nv) = factors.getOrElse(nv, 0) + 1\n      }\n      c.lnf match {\n        case LhsTop => ()\n        case LhsRefined(_, ttags, _, _) =>\n          ttags.foreach { ttg =>\n            factors(ttg) = factors.getOrElse(ttg, 0) + 1\n          }\n      }\n      c.rnf match {\n        case RhsBot | _: RhsField => ()\n        case RhsBases(ps, _, _) =>\n          ps.foreach {\n            case ttg: AbstractTag =>\n              val nt = NegAbsTag(ttg)\n              factors(nt) = factors.getOrElse(nt, 0) + 1\n            case _ => ()\n          }\n      }\n    }\n    factors.maxByOption(_._2) match {\n      // case S((fact, n)) =>  // Very strangely, this seems to improve some StressTrait tests slightly...\n      case S((fact, n)) if n > 1 =>\n        val (factored, rest) = fact match {\n          case v: TV =>\n            cs.partitionMap(c => if (c.vars(v)) L(c) else R(c))\n          case NegVar(v) =>\n            cs.partitionMap(c => if (c.nvars(v)) L(c) else R(c))\n          case ttg: AbstractTag =>\n            cs.partitionMap(c => if (c.lnf.hasTag(ttg)) L(c) else R(c))\n          case NegAbsTag(ttg) =>\n            cs.partitionMap(c => if (c.rnf.hasTag(ttg)) L(c) else R(c))\n        }\n        (fact & factorize(factored.map(_ - fact), sort).reduce(_ | _)) :: (\n          if (factors.sizeCompare(1) > 0 && factors.exists(f => (f._1 isnt fact) && f._2 > 1))\n            factorize(rest, sort)\n          else rest.map(_.toType(sort))\n        )\n      case _ =>\n        cs.map(_.toType(sort))\n    }\n  }\n  \n  private def cleanupUnion(tys: Ls[ST])(implicit ctx: Ctx): Ls[ST] = {\n    var res: Ls[ST] = Nil\n    tys.reverseIterator.foreach { ty =>\n      if (!res.exists(ty <:< _)) res ::= ty\n    }\n    res\n  }\n  def factorize(ctx: Ctx)(ty: ST): ST = {\n    cleanupUnion(ty.components(true))(ctx) match {\n      case Nil => BotType\n      case ty :: Nil => ty\n      case cs => factorizeImpl(cs.map(_.components(false)))\n    }\n  }\n  def factorizeImpl(cs: Ls[Ls[ST]]): ST = trace(s\"factorize? ${cs.map(_.mkString(\" & \")).mkString(\" | \")}\") {\n    def rebuild(cs: Ls[Ls[ST]]): ST =\n      cs.iterator.map(_.foldLeft(TopType: ST)(_ & _)).foldLeft(BotType: ST)(_ | _)\n    if (cs.sizeCompare(1) <= 0) return rebuild(cs)\n    val factors = LinkedHashMap.empty[Factorizable, Int]\n    cs.foreach { c =>\n      c.foreach {\n        case tv: TV =>\n          factors(tv) = factors.getOrElse(tv, 0) + 1\n        case tt: AbstractTag =>\n          factors(tt) = factors.getOrElse(tt, 0) + 1\n        case nv: NegVar =>\n          factors(nv) = factors.getOrElse(nv, 0) + 1\n        case nt: NegAbsTag =>\n          factors(nt) = factors.getOrElse(nt, 0) + 1\n        case _ =>\n      }\n    }\n    println(s\"Factors ${factors.mkString(\", \")}\")\n    factors.maxByOption(_._2) match {\n      // case S((fact, n)) =>\n      case S((fact, n)) if n > 1 =>\n        val (factored, rest) =\n          cs.partitionMap(c => if (c.contains(fact)) L(c) else R(c))\n        println(s\"Factor $fact -> ${factored.mkString(\", \")}\")\n        assert(factored.size === n, factored -> n)\n        val factoredFactored = fact & factorizeImpl(factored.map(_.filterNot(_ === fact)))\n        val restFactored =\n          if (factors.sizeCompare(1) > 0 && factors.exists(f => (f._1 isnt fact) && f._2 > 1))\n            factorizeImpl(rest)\n          else rebuild(rest)\n        restFactored | factoredFactored\n      case _ => rebuild(cs)\n    }\n  }(r => s\"yes: $r\")\n  \n  \n  def mapPol(rt: RecordType, pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType): RecordType =\n    RecordType(rt.fields.mapValues(_.update(f(pol.map(!_), _), f(pol, _))))(rt.prov)\n  \n  def mapPol(bt: BaseType, pol: Opt[Bool], smart: Bool)(f: (Opt[Bool], SimpleType) => SimpleType): BaseType = bt match {\n    case FunctionType(lhs, rhs) => FunctionType(f(pol.map(!_), lhs), f(pol, rhs))(bt.prov)\n    case ov @ Overload(alts) => ov.mapAltsPol(pol)(f)\n    case TupleType(fields) => TupleType(fields.mapValues(_.update(f(pol.map(!_), _), f(pol, _))))(bt.prov)\n    case ArrayType(inner) => ArrayType(inner.update(f(pol.map(!_), _), f(pol, _)))(bt.prov)\n    case sp @SpliceType(elems) => sp.updateElems(f(pol, _), f(pol.map(!_), _), f(pol, _))\n    case wt @ Without(b: ComposedType, ns @ EmptyColl()) => Without(b.map(f(pol, _)), ns)(wt.prov) // FIXME very hacky\n    case Without(base, names) => Without(f(pol, base), names)(bt.prov)\n    case _: ClassTag => bt\n  }\n  \n  \n  \n  trait SimpleTypeImpl { self: SimpleType =>\n    \n    // TODO eventually find a way of statically getting rid of those\n    def assertTV: TV = this match {\n      case tv: TV => tv\n      case _ => lastWords(s\"$this was not a type variable\")\n    }\n    \n    def showProvOver(enabled: Bool)(str: Str): Str =\n      if (enabled) str + prov.toString\n      else str\n    \n    // Note: we implement hashCode and equals manually because:\n    //  1. On one hand, we want a ProvType to compare equal to its underlying type,\n    //      which is necessary for recursive types to associate type provenances to\n    //      their recursive uses without making the constraint solver diverge; and\n    //  2. Additionally, caching hashCode should have performace benefits\n    //      — though I'm not sure whether it's best as a `lazy val` or a `val`.\n    override lazy val hashCode: Int = this match {\n      case tv: TypeVariable => tv.uid\n      case ProvType(und) => und.hashCode\n      case p: Product => scala.runtime.ScalaRunTime._hashCode(p)\n    }\n    override def equals(that: Any): Bool = \n        // trace(s\"$this == $that\") {\n        this match {\n      case ProvType(und) => (und: Any) === that\n      case tv1: TV => that match {\n        case tv2: Typer#TV => tv1.uid === tv2.uid\n        case ProvType(und) => this === und\n        case _ => false\n      }\n      case p1: Product => that match {\n        case that: ST => that match {\n          case ProvType(und) => this === und\n          case tv: TV => false\n          case p2: Product =>\n            p1.canEqual(p2) && p1.productArity === p2.productArity && {\n              val it1 = p1.productIterator\n              val it2 = p2.productIterator\n              while(it1.hasNext && it2.hasNext) {\n                if (it1.next() =/= it2.next()) return false\n              }\n              return !it1.hasNext && !it2.hasNext\n            }\n        }\n        case _ => false\n      }\n    }\n    // }(r => s\"= $r\")\n    \n    private val initialRun = currentConstrainingRun\n    private var shadowRun = initialRun - 1\n    private var _shadow: ST = this\n    private def computeShadow: ST = this match {\n      case tv: TV => tv.original // * Q: no special tratment for assigned TVs?\n      case _ => map(_.shadow)\n    }\n    def shadow: ST =\n      if (currentConstrainingRun === shadowRun) _shadow else {\n        _shadow = computeShadow\n        shadowRun = currentConstrainingRun\n        _shadow\n      }\n    \n    def map(f: SimpleType => SimpleType): SimpleType = this match {\n      case TypeBounds(lb, ub) => TypeBounds.mkSimple(f(lb), f(ub))\n      case FunctionType(lhs, rhs) => FunctionType(f(lhs), f(rhs))(prov)\n      case ov @ Overload(as) => ov.mapAltsPol(N)((_, x) => f(x))\n      case RecordType(fields) => RecordType(fields.mapValues(_.update(f, f)))(prov)\n      case TupleType(fields) => TupleType(fields.mapValues(_.update(f, f)))(prov)\n      case sp @ SpliceType(fs) => sp.updateElems(f, f, f)\n      case ArrayType(inner) => ArrayType(inner.update(f, f))(prov)\n      case ComposedType(pol, lhs, rhs) => ComposedType(pol, f(lhs), f(rhs))(prov)\n      case NegType(negated) => NegType(f(negated))(prov)\n      case Without(base, names) => Without(f(base), names)(prov)\n      case ProvType(underlying) => ProvType(f(underlying))(prov)\n      case WithType(bse, rcd) => WithType(f(bse), RecordType(rcd.fields.mapValues(_.update(f, f)))(rcd.prov))(prov)\n      case ProxyType(underlying) => f(underlying) // TODO different?\n      case TypeRef(defn, targs) => TypeRef(defn, targs.map(f(_)))(prov)\n      case PolymorphicType(plvl, und) => PolymorphicType(plvl, f(und))\n      case ConstrainedType(cs, bod) =>\n        ConstrainedType(cs.map(lu => f(lu._1) -> f(lu._2)), f(bod))\n      case _: TypeVariable | _: TypeTag | _: ExtrType => this\n    }\n    def mapPol(pol: Opt[Bool], smart: Bool = false)(f: (Opt[Bool], SimpleType) => SimpleType)\n          (implicit ctx: Ctx): SimpleType = this match {\n      case TypeBounds(lb, ub) if smart && pol.isDefined =>\n        if (pol.getOrElse(die)) f(S(true), ub) else f(S(false), lb)\n      case TypeBounds(lb, ub) => TypeBounds.mkSimple(f(S(false), lb), f(S(true), ub))\n      case rt: RecordType => Typer.mapPol(rt, pol, smart)(f)\n      case Without(base, names) if smart => f(pol, base).without(names)\n      case bt: BaseType => Typer.mapPol(bt, pol, smart)(f)\n      case ComposedType(kind, lhs, rhs) if smart =>\n        if (kind) f(pol, lhs) | f(pol, rhs)\n        else f(pol, lhs) & f(pol, rhs)\n      case ComposedType(kind, lhs, rhs) => ComposedType(kind, f(pol, lhs), f(pol, rhs))(prov)\n      case NegType(negated) if smart => f(pol.map(!_), negated).neg(prov)\n      case NegType(negated) => NegType(f(pol.map(!_), negated))(prov)\n      case ProvType(underlying) => ProvType(f(pol, underlying))(prov)\n      case WithType(bse, rcd) => WithType(f(pol, bse), RecordType(rcd.fields.mapValues(_.update(f(pol.map(!_), _), f(pol, _))))(rcd.prov))(prov)\n      case ProxyType(underlying) => f(pol, underlying) // TODO different?\n      case tr @ TypeRef(defn, targs) => TypeRef(defn, tr.mapTargs(pol)(f))(prov)\n      case PolymorphicType(plvl, und) =>\n        if (smart) PolymorphicType.mk(plvl, f(pol, und)) else PolymorphicType(plvl, f(pol, und))\n      case ConstrainedType(cs, bod) =>\n        ConstrainedType(cs.map(lu => f(S(true), lu._1) -> f(S(false), lu._2)), f(pol, bod))\n      case _: TypeVariable | _: TypeTag | _: ExtrType => this\n    }\n    \n    def toUpper(prov: TypeProvenance): FieldType = FieldType(None, this)(prov)\n    def toLower(prov: TypeProvenance): FieldType = FieldType(Some(this), TopType)(prov)\n    def toBoth(prov: TypeProvenance): FieldType = FieldType(S(this), this)(prov)\n    \n    def | (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType = (this, that) match {\n      case (TopType, _) => this\n      case (BotType, _) => that\n      case (_, TopType) => that\n      case (_, BotType) => this\n      case (Extruded(true, sk), _) => that\n      case (Extruded(false, sk), _) => TopType\n      \n      // These were wrong! During constraint solving it's important to keep them!\n      // case (_: RecordType, _: PrimType | _: FunctionType) => TopType\n      // case (_: FunctionType, _: PrimType | _: RecordType) => TopType\n      \n      case (_: RecordType, _: FunctionType) => TopType\n      case (RecordType(fs1), RecordType(fs2)) =>\n        RecordType(recordUnion(fs1, fs2))(prov)\n      case (t0 @ TupleType(fs0), t1 @ TupleType(fs1))\n        // If the sizes are different, to merge these we'd have to return\n        //  the awkward `t0.toArray & t0.toRecord | t1.toArray & t1.toRecord`\n      if fs0.sizeCompare(fs1) === 0 =>\n        TupleType(tupleUnion(fs0, fs1))(t0.prov)\n      case _ if !swapped => that | (this, prov, swapped = true)\n      case (`that`, _) => this\n      case (NegType(`that`), _) => TopType\n      case _ => ComposedType(true, that, this)(prov)\n    }\n    \n    /** This is to intersect two types that occur in negative position,\n      * where it may be sound to perform some online simplifications/approximations. */\n    def &- (that: SimpleType, prov: TypeProvenance = noProv): SimpleType = (this, that) match {\n      // * This one is only correct in negative position because\n      // * the existence of first-class polymorphic types makes it unsound in positive positions.\n      case (FunctionType(l1, r1), FunctionType(l2, r2)) if approximateNegativeFunction =>\n        FunctionType(l1 | l2, r1 &- r2)(prov)\n      case _ => this & (that, prov)\n    }\n    def & (that: SimpleType, prov: TypeProvenance = noProv, swapped: Bool = false): SimpleType =\n        (this, that) match {\n      case (TopType | RecordType(Nil), _) => that\n      case (BotType, _) => BotType\n      \n      // * Unnecessary and can complicate constraint solving quite a lot:\n      // case (ComposedType(true, l, r), _) => l & that | r & that\n      \n      // * Tempting, but wrong: this is only valid in positive positions!\n      // * (in which case the LBs are irrelevant anyway)\n      // * For, instance consider `((A..A) & (B..B)) -> C` in positive position,\n      // * which is `(A & B) -> C` and obviously not `(A | B) -> C`.\n      // case (TypeBounds(l0, u0), TypeBounds(l1, u1)) =>\n      //   TypeBounds(l0 | l1, u0 & u1)(prov)\n      \n      case (_: ClassTag, _: FunctionType) => BotType\n      case (RecordType(fs1), RecordType(fs2)) =>\n        RecordType(mergeSortedMap(fs1, fs2)(_ && _).toList)(prov)\n      case (t0 @ TupleType(fs0), t1 @ TupleType(fs1)) =>\n        if (fs0.sizeCompare(fs1) =/= 0) BotType\n        else TupleType(tupleIntersection(fs0, fs1))(t0.prov)\n      case _ if !swapped => that & (this, prov, swapped = true)\n      case (`that`, _) => this\n      case _ if !swapped => that & (this, prov, swapped = true)\n      case (NegType(`that`), _) => BotType\n      case _ => ComposedType(false, that, this)(prov)\n    }\n    def neg(prov: TypeProvenance = noProv, force: Bool = false): SimpleType = this match {\n      case ExtrType(b) => ExtrType(!b)(noProv)\n      case ComposedType(true, l, r) => l.neg() & r.neg()\n      case ComposedType(false, l, r) if force => l.neg() | r.neg()\n      case NegType(n) => n\n      // case _: RecordType => BotType // Only valid in positive positions!\n        // Because Top<:{x:S}|{y:T}, any record type negation neg{x:S}<:{y:T} for any y=/=x,\n        // meaning negated records are basically bottoms.\n      case _ => NegType(this)(prov)\n    }\n    \n    /** This is used to know when two types can be assumed to be mutual subtypes\n      * based on a simple equality check. This may not hold when the types involve `TypeBound`s.\n      * Indeed, say `type Foo[A] = A -> A`;\n      * then `Foo[bot..top]` is an alias for `(bot..top) -> (bot..top)`\n      * which IN POSITIVE POSITION is equivalent to `bot -> top`\n      * and IN NEGATIVE POSITION is equivalent to `top -> bot`.\n      * Therefore, while syntactically `Foo[bot..top] === Foo[bot..top]`,\n      * we DO NOT have that `Foo[bot..top] <: Foo[bot..top]`.\n      * This check is still a little wrong in that we don't look into type definitions,\n      * someone may register type definitions whose bodies involve `TypeBound`s... Though\n      * it seems the typer should desugar these bounds when psosible and reject them otherwise.\n      * OTOH, note that we truly don't have to look into type variable bounds because these\n      * bounds are maintained consistent. */\n    lazy val mentionsTypeBounds: Bool = this match {\n      case _: TypeBounds => true\n      case _ => children(includeBounds = false).exists(_.mentionsTypeBounds)\n    }\n    \n    def >:< (that: SimpleType)(implicit ctx: Ctx, crt: CompareRecTypes = true): Bool =\n      this <:< that && that <:< this\n    \n    // TODO for composed types and negs, should better first normalize the inequation\n    def <:< (that: SimpleType)\n      (implicit ctx: Ctx, crt: CompareRecTypes = true, cache: MutMap[ST -> ST, Bool] = MutMap.empty): Bool =\n    {\n    // trace(s\"? $this <: $that\") {\n    // trace(s\"? $this <: $that   assuming:  ${\n    //     cache.iterator.map(kv => \"\" + kv._1._1 + (if (kv._2) \" <: \" else \" <? \") + kv._1._2).mkString(\" ; \")}\") {\n      val doCompareRecTypes = (crt === true) && !noRecursiveTypes\n      subtypingCalls += 1\n      def assume[R](k: MutMap[ST -> ST, Bool] => R): R =\n        if (doCompareRecTypes) k(cache.map(kv => kv._1 -> true)) else k(cache)\n      if (!mentionsTypeBounds && ((this is that) || this === that)) return true\n      (this, that) match {\n        case (_, ExtrType(false)) | (ExtrType(true), _) => true\n        case (ProxyType(und), _) => und <:< that\n        case (_, ProxyType(und)) => this <:< und\n        // * Leads to too much simplification in printed types:\n        // case (ClassTag(ErrTypeId, _), _) | (_, ClassTag(ErrTypeId, _)) => true\n        case (_: TypeTag, _: TypeTag) | (_: TV, _: TV) if this === that => true\n        case (ab: ArrayBase, at: ArrayType) => ab.inner <:< at.inner\n        case (TupleType(fs1), TupleType(fs2)) =>\n          fs1.sizeCompare(fs2) === 0 && fs1.lazyZip(fs2).forall {\n            case ((_, ty1), (_, ty2)) => ty1 <:< ty2\n          }\n        case (RecordType(Nil), _) => TopType <:< that\n        case (_, RecordType(Nil)) => this <:< TopType\n        case (pt1 @ ClassTag(id1, ps1), pt2 @ ClassTag(id2, ps2)) => (id1 === id2) || pt1.parentsST(id2)\n        case (TypeBounds(lb, ub), _) => ub <:< that\n        case (_, TypeBounds(lb, ub)) => this <:< lb\n        case (FunctionType(l1, r1), FunctionType(l2, r2)) => assume { implicit cache =>\n          l2 <:< l1 && r1 <:< r2 \n        }\n        case (ComposedType(true, l, r), _) => l <:< that && r <:< that\n        case (_, ComposedType(false, l, r)) => this <:< l && this <:< r\n        case (ComposedType(false, l, r), _) => l <:< that || r <:< that\n        case (_, ComposedType(true, l, r)) => this <:< l || this <:< r\n        case (RecordType(fs1), RecordType(fs2)) => assume { implicit cache =>\n          fs2.forall(f => fs1.find(_._1 === f._1).exists(_._2 <:< f._2))\n        }\n        \n        // * Field removal is special\n        // * and can't be compared without taking polarity into account...\n        case (_, _: Without) => false\n        /* \n        case (Without(bs1, ns1), Without(bs2, ns2)) =>\n          ns1.forall(ns2) && bs1 <:< that\n        case (_, Without(bs, ns)) =>\n          this <:< bs\n        */\n        \n        case (_: TypeVariable, _) | (_, _: TypeVariable) if !doCompareRecTypes => false\n        case (_: TypeVariable, _) | (_, _: TypeVariable)\n          if cache.contains(this -> that)\n          => cache(this -> that)\n        case (tv: TypeVariable, _) =>\n          cache(this -> that) = false\n          val tmp = tv.assignedTo match {\n            case S(ty) =>\n              ty <:< that\n            case N =>\n              tv.upperBounds.exists(_ <:< that)\n          }\n          if (tmp) cache(this -> that) = true\n          tmp\n        case (_, tv: TypeVariable) =>\n          cache(this -> that) = false\n          val tmp = tv.assignedTo match {\n            case S(ty) =>\n              this <:< ty\n            case N =>\n              tv.lowerBounds.exists(this <:< _)\n          }\n          if (tmp) cache(this -> that) = true\n          tmp\n        case (ConstrainedType(Nil, bod), rhs) => bod <:< that\n        case (_, ConstrainedType(cs, bod)) => this <:< bod // could assume cs here\n        case (_, NegType(und)) => (this & und) <:< BotType\n        case (NegType(und), _) => TopType <:< (that | und)\n        case (tr: TypeRef, _)\n          if (primitiveTypes contains tr.defn.name) && tr.canExpand => tr.expandOrCrash <:< that\n        case (_, tr: TypeRef)\n          if (primitiveTypes contains tr.defn.name) && tr.canExpand => this <:< tr.expandOrCrash\n        case (tr1: TypeRef, _) => ctx.tyDefs.get(tr1.defn.name) match {\n            case S(td1) =>\n          that match {\n            case tr2: TypeRef if tr2.defn === tr1.defn =>\n              val tvv = td1.getVariancesOrDefault\n              td1.tparamsargs.unzip._2.lazyZip(tr1.targs).lazyZip(tr2.targs).forall { (tv, targ1, targ2) =>\n                val v = tvv(tv)\n                (v.isContravariant || targ1 <:< targ2) && (v.isCovariant || targ2 <:< targ1)\n              }\n            case _ =>\n              (td1.kind is Cls) && clsNameToNomTag(td1)(noProv, ctx) <:< that\n          }\n            case N => false // TODO look into ctx.tyDefs2\n        }\n        case (_, _: TypeRef) =>\n          false // TODO try to expand them (this requires populating the cache because of recursive types)\n        case (_: PolymorphicType, _) | (_, _: PolymorphicType) => false\n        case (_, ov: Overload) => ov.alts.forall(this <:< _)\n        case (ov: Overload, _) => ov.alts.exists(_ <:< that)\n        case (_: ConstrainedType, _) => false\n        case (_: Without, _)\n          | (_: ArrayBase, _) | (_, _: ArrayBase)\n          | (_: AbstractTag, _) | (_, _: AbstractTag)\n          => false // don't even try\n        case (_: FunctionType, _) | (_, _: FunctionType) => false\n        case (_: RecordType, _: TypeTag) | (_: TypeTag, _: RecordType) => false\n        case (_, ExtrType(true)) | (ExtrType(false), _) => false // not sure whether LHS <: Bot (or Top <: RHS)\n        // case _ => lastWords(s\"TODO $this $that ${getClass} ${that.getClass()}\")\n      }\n    // }(r => s\"! $r\")\n    }\n    \n    def isTop(implicit ctx: Ctx): Bool = TopType <:< this\n    def isBot(implicit ctx: Ctx): Bool = this <:< BotType\n    \n    // * Sometimes, Without types are temporarily pushed to the RHS of constraints,\n    // *  sometimes behind a single negation,\n    // *  just for the time of massaging the constraint through a type variable.\n    // * So it's important we only push and simplify Without types only in _positive_ position!\n    def without(names: SortedSet[Var]): SimpleType = if (names.isEmpty) this else this match {\n      case Without(b, ns) => Without(b, ns ++ names)(this.prov)\n      case _ => Without(this, names)(noProv)\n    }\n    def without(name: Var): SimpleType = \n      without(SortedSet.single(name))\n    \n    def withoutPos(names: SortedSet[Var]): SimpleType = if (names.isEmpty) this else this match {\n      case Without(b, ns) => Without(b, ns ++ names)(this.prov)\n      case t @ FunctionType(l, r) => t\n      case t @ ComposedType(true, l, r) => l.without(names) | r.without(names)\n      case t @ ComposedType(false, l, r) => l.without(names) & r.without(names)\n      case t @ RecordType(fs) => RecordType(fs.filter(nt => !names(nt._1)))(t.prov)\n      case t @ TupleType(fs) =>\n        val relevantNames = names.filter(n =>\n          n.toIndexOption.exists((0 until fs.length).contains))\n        if (relevantNames.isEmpty) t\n        else {\n          val rcd = t.toRecord\n          rcd.copy(fields = rcd.fields.filterNot(_._1 |> relevantNames))(rcd.prov)\n        }\n      case t @ ArrayType(ar) => t\n      case t @ SpliceType(fs) => ???  // TODO\n      case n @ NegType(_ : ClassTag | _: FunctionType | _: RecordType) => n\n      case n @ NegType(nt) if (nt match {\n        case _: ComposedType | _: ExtrType | _: NegType => true\n        // case c: ComposedType => c.pol\n        // case _: ExtrType | _: NegType => true\n        case _ => false\n      }) => nt.neg(n.prov, force = true).withoutPos(names)\n      case e @ ExtrType(_) => e // valid? -> seems we could go both ways, but this way simplifies constraint solving\n      // case e @ ExtrType(false) => e\n      case p @ ProvType(und) => ProvType(und.withoutPos(names))(p.prov)\n      case p @ ProxyType(und) => und.withoutPos(names)\n      case p: TypeTag => p\n      case TypeBounds(lo, hi) => hi.withoutPos(names)\n      case _: TypeVariable | _: NegType | _: TypeRef => Without(this, names)(noProv)\n      case PolymorphicType(plvl, bod) => PolymorphicType.mk(plvl, bod.withoutPos(names))\n      case ot: Overload => ot\n      case ct: ConstrainedType => ct\n    }\n    def unwrapAll(implicit ctx: Ctx): SimpleType = unwrapProxies match {\n      case tr: TypeRef if tr.canExpand => tr.expandOrCrash.unwrapAll\n      case u => u\n    }\n    def negNormPos(f: SimpleType => SimpleType, p: TypeProvenance)\n          (implicit ctx: Ctx, ptr: PreserveTypeRefs): SimpleType = (if (preserveTypeRefs) this else unwrapAll) match {\n      case ExtrType(b) => ExtrType(!b)(noProv)\n      case ComposedType(true, l, r) => l.negNormPos(f, p) & r.negNormPos(f, p)\n      case ComposedType(false, l, r) => l.negNormPos(f, p) | r.negNormPos(f, p)\n      case NegType(n) => f(n).withProv(p)\n      case tr: TypeRef if !preserveTypeRefs && tr.canExpand => tr.expandOrCrash.negNormPos(f, p)\n      case rw => NegType(f(rw))(p)\n    }\n    def withProvOf(ty: SimpleType): ST = withProv(ty.prov)\n    def withProv(p: TypeProvenance): ST = mkProxy(this, p)\n    def pushPosWithout(implicit ctx: Ctx, ptr: PreserveTypeRefs): SimpleType = this match {\n      case NegType(n) => n.negNormPos(_.pushPosWithout, prov)\n      case Without(b, ns) => if (ns.isEmpty) b.pushPosWithout else (if (preserveTypeRefs) b.unwrapProxies else b.unwrapAll).withoutPos(ns) match {\n        case Without(c @ ComposedType(pol, l, r), ns) => ComposedType(pol, l.withoutPos(ns), r.withoutPos(ns))(c.prov)\n        case Without(NegType(nt), ns) => nt.negNormPos(_.pushPosWithout, nt.prov).withoutPos(ns) match {\n          case rw @ Without(NegType(nt), ns) =>\n            nt match {\n              case _: TypeVariable | _: ClassTag | _: RecordType => rw\n              case _ => if (preserveTypeRefs) rw else lastWords(s\"$this  $rw  (${nt.getClass})\")\n            }\n          case rw => rw\n        }\n        case rw => rw\n      }\n      case _ => this\n    }\n    \n    def abs(that: SimpleType)(prov: TypeProvenance): SimpleType =\n      FunctionType(this, that)(prov)\n    \n    def unwrapProxies: SimpleType = this match {\n      case ProxyType(und) => und.unwrapProxies\n      case _ => this\n    }\n    def unwrapProvs: SimpleType = this match {\n      case ProvType(und) => und.unwrapProvs\n      case _ => this\n    }\n    /** Used for error reporting. */\n    def typeBase: SimpleType = unwrapProxies match {\n      case Without(und, ns) => und.typeBase\n      case PolymorphicType(pl, bod) => bod.typeBase\n      case TypeBounds(lb, ub) => ub.typeBase\n      case _ => this\n    }\n    \n    def components(union: Bool): Ls[ST] = this match {\n      case ExtrType(`union`) => Nil\n      case ComposedType(`union`, l, r) => l.components(union) ::: r.components(union)\n      case NegType(tv: TypeVariable) if !union => NegVar(tv) :: Nil\n      case NegType(tt: AbstractTag) if !union => NegAbsTag(tt) :: Nil\n      case ProvType(und) => und.components(union)\n      case _ => this :: Nil\n    }\n    \n    /** (exclusive, inclusive) */\n    def varsBetween(lb: Level, ub: Level): Set[TV] = {\n      val res = MutSet.empty[TypeVariable]\n      val traversed = MutSet.empty[TypeVariable]\n      def go(ty: ST, lb: Level, ub: Level): Unit =\n          if (lb < ub && ty.level > lb) { // * Don't traverse types with lower levels\n        // trace(s\"varsBetween($ty, $lb, $ub)\") {\n        ty match {\n          case tv: TypeVariable =>\n            if (traversed(tv)) ()\n            else {\n              traversed += tv\n              if (tv.level > lb && tv.level <= ub) {\n                // println(s\"ADD $tv\")\n                res += tv\n              }\n              tv.children(includeBounds = true) // * Note: `children` deals with `assignedTo`\n                .foreach(go(_, lb, ub))\n            }\n          case pt: PolymorphicType =>\n            go(pt.body, lb, pt.polymLevel min ub)\n          case ty =>\n            ty.children(includeBounds = true) // * Q: is `includeBounds` useful here?\n              .foreach(go(_, lb, ub))\n        }\n        // }()\n      }\n      go(this, lb, ub)\n      res.toSet\n    }\n    \n    def expPos(implicit ctx: Ctx): mlscript.TypeLike = exp(S(true), this)\n    def expNeg(implicit ctx: Ctx): mlscript.TypeLike = exp(S(false), this)\n    def exp(pol: Opt[Bool], ty: ST)(implicit ctx: Ctx): mlscript.TypeLike = (\n      ty\n      // |> (_.normalize(false))\n      // |> (simplifyType(_, pol, removePolarVars = false, inlineBounds = false))\n      // |> (shallowCopy)\n      |> (subst(_, Map.empty)) // * Make a copy of the type and its TV graph – although we won't show the TV bounds, we still care about the bounds as they affect class type reconstruction in normalizeTypes_!\n      |> (normalizeTypes_!(_, pol)(ctx))\n      |> (expandType(_, stopAtTyVars = true))\n    )\n    \n  }\n  \n  \n  \n  trait TypeLikeImpl { self: TypeLike =>\n    \n    def childrenPol(pol: PolMap)(implicit ctx: Ctx): List[PolMap -> SimpleType] = {\n      def childrenPolField(pol: PolMap)(fld: FieldType): List[PolMap -> SimpleType] =\n        fld.lb.map(pol.contravar -> _).toList ::: pol.covar -> fld.ub :: Nil\n      def childrenPolMem(m: NuMember): List[PolMap -> SimpleType] = m match {\n        case NuParam(nme, ty, pub) => childrenPolField(PolMap.pos)(ty) // TODO invariant when mutable\n        case TypedNuFun(level, fd, ty) => pol -> ty :: Nil\n        case td: TypedNuDecl => TypedTypingUnit(td :: Nil, N).childrenPol(pol: PolMap) // TODO refactor\n        // case NuTypeParam(nme, ty) => childrenPolField(PolMap.pos)(ty)\n      }\n      this match {\n        case tv @ AssignedVariable(ty) =>\n          pol -> ty :: Nil\n        case tv: TypeVariable =>\n          val poltv = pol(tv)\n          (if (poltv =/= S(false)) tv.lowerBounds.map(pol.at(tv.level, true) -> _) else Nil) :::\n          (if (poltv =/= S(true)) tv.upperBounds.map(pol.at(tv.level, false) -> _) else Nil) ++\n          tv.tsc.keys.flatMap(_.tvs).map(u => pol.at(tv.level,u._1) -> u._2)\n        case FunctionType(l, r) => pol.contravar -> l :: pol.covar -> r :: Nil\n        case Overload(as) => as.map(pol -> _)\n        case ComposedType(_, l, r) => pol -> l :: pol -> r :: Nil\n        case RecordType(fs) => fs.unzip._2.flatMap(childrenPolField(pol))\n        case TupleType(fs) => fs.unzip._2.flatMap(childrenPolField(pol))\n        case ArrayType(fld) => childrenPolField(pol)(fld)\n        case SpliceType(elems) => elems flatMap {case L(l) => pol -> l :: Nil case R(r) => childrenPolField(pol)(r)}\n        case NegType(n) => pol.contravar -> n :: Nil\n        case ExtrType(_) => Nil\n        case ProxyType(und) => pol -> und :: Nil\n        // case _: TypeTag => Nil\n        case _: ObjectTag | _: Extruded => Nil\n        case SkolemTag(id) => pol -> id :: Nil\n        case tr: TypeRef => tr.mapTargs(pol)(_ -> _)\n        case Without(b, ns) => pol -> b :: Nil\n        case TypeBounds(lb, ub) => PolMap.neg -> lb :: PolMap.pos -> ub :: Nil\n        case PolymorphicType(_, und) => pol -> und :: Nil\n        case ConstrainedType(cs, bod) =>\n          cs.flatMap(vbs => PolMap.pos -> vbs._1 :: PolMap.posAtNeg -> vbs._2 :: Nil) ::: pol -> bod :: Nil\n        case OtherTypeLike(tu) =>\n          // tu.entities.flatMap(_.childrenPol) ::: tu.result.toList\n          val ents = tu.implementedMembers.flatMap {\n            case ta: TypedNuAls =>\n              // Q: PolMap.neu or pol.invar?!\n              ta.tparams.map(pol.invar -> _._2) ::: pol -> ta.body :: Nil\n            case tf: TypedNuFun =>\n              PolMap.pos -> tf.bodyType :: Nil\n            case mxn: TypedNuMxn =>\n              mxn.tparams.iterator.map(pol.invar -> _._2) ++\n              mxn.members.valuesIterator.flatMap(childrenPolMem) ++\n                S(pol.contravar -> mxn.superTy) ++\n                S(pol.contravar -> mxn.thisTy)\n            case cls: TypedNuCls =>\n              cls.tparams.iterator.map(pol.invar -> _._2) ++\n              // cls.params.flatMap(p => childrenPolField(pol.invar)(p._2))\n                cls.params.toList.flatMap(_.flatMap(p => childrenPolField(PolMap.pos)(p._2))) ++\n                cls.auxCtorParams.toList.flatMap(_.map(PolMap.neg -> _._2)) ++\n                cls.members.valuesIterator.flatMap(childrenPolMem) ++\n                S(pol.contravar -> cls.thisTy) ++\n                S(pol.covar -> cls.sign) ++\n                // S(pol.covar -> cls.instanceType) ++ // Not a real child; to remove\n                cls.parentTP.valuesIterator.flatMap(childrenPolMem)\n            case trt: TypedNuTrt =>\n              trt.tparams.iterator.map(pol.invar -> _._2) ++\n                trt.members.valuesIterator.flatMap(childrenPolMem) ++\n                S(pol.contravar -> trt.thisTy) ++\n                S(pol.covar -> trt.sign) ++\n                trt.parentTP.valuesIterator.flatMap(childrenPolMem)\n            case prm: NuParam => childrenPolField(pol)(prm.ty)\n            case TypedNuDummy(d) => N\n          }\n          ents ::: tu.result.toList.map(pol -> _)\n    }}\n    \n    /** `ignoreTopLevelOccs` is used to discard immediate occurrences of a variable which\n      * would constitute spurious recursive occurrences when traversing the variable's bounds. */\n    def getVarsPol(pol: PolMap, ignoreTopLevelOccs: Bool = false, ignoreQuantifiedVars: Bool = false)\n          (implicit ctx: Ctx)\n          : SortedMap[TypeVariable, Opt[Bool]] = {\n      val res = MutMap.empty[TV, Pol]\n      val traversed = MutSet.empty[TV -> Bool]\n      // * We ignore variables above `upperLvl` when `ignoreQuantifiedVars` is true. \n      def go(pol: PolMap, ignoreTLO: Bool, upperLvl: Level)(ty: TypeLike): Unit = {\n        // trace(s\"getVarsPol[${printPol(pol.base)}] $ty ${pol} $ignoreTLO\") {\n        ty match {\n          case tv: TypeVariable =>\n            if (ignoreQuantifiedVars && tv.level > upperLvl) return println(s\"Quantified! ${tv}\")\n            val tvpol = pol(tv.level)\n            if (!ignoreTLO) res.updateWith(tv) {\n              case S(p) if p =/= tvpol =>\n                // println(s\"> $tv: $tvpol =/= $p ~> S(N)\")\n                S(N)\n              case _ =>\n                // println(s\"> $tv: $tvpol\")\n                S(tvpol)\n            }\n            val needsTraversing = tvpol match {\n              case S(p) =>\n                !traversed(tv -> p) && {\n                  traversed += tv -> p\n                  true\n                }\n              case N =>\n                !(traversed(tv -> true) && traversed(tv -> false)) && {\n                  traversed += tv -> true\n                  traversed += tv -> false\n                  true\n                }\n            }\n            // println(s\"$tv ${printPol(tvpol)} $needsTraversing\")\n            if (needsTraversing)\n              tv.childrenPol(pol) // * Note: `childrenPol` deals with `assignedTo`\n                .foreach(cp => go(cp._1, ignoreTLO, upperLvl)(cp._2))\n          case ProxyType(und) => go(pol, ignoreTLO, upperLvl)(und)\n          case Overload(as) => as.foreach(go(pol, ignoreTLO, upperLvl))\n          case NegType(n) => go(pol.contravar, ignoreTLO, upperLvl)(n)\n          case Without(b, ns) => go(pol, ignoreTLO, upperLvl)(b)\n          case TypeBounds(lb, ub) =>\n            go(PolMap.neg, ignoreTLO, upperLvl)(lb)\n            go(PolMap.pos, ignoreTLO, upperLvl)(ub)\n            // * or simply:\n            // pol.traverseRange(lb, ub)(go(_, ignoreTLO, upperLvl)(_))\n          case ConstrainedType(cs, bod) =>\n            cs.foreach { vbs =>\n              go(PolMap.pos, false, upperLvl)(vbs._1)\n              go(PolMap.posAtNeg, false, upperLvl)(vbs._2)\n            }\n            go(pol, ignoreTLO, upperLvl)(bod)\n          case ComposedType(p, l, r) =>\n            go(pol, ignoreTLO, upperLvl)(l)\n            go(pol, ignoreTLO, upperLvl)(r)\n          case pt: PolymorphicType =>\n            go(pol.enter(pt.polymLevel), ignoreTLO, upperLvl min pt.polymLevel)(pt.body)\n          case ty =>\n            ty.childrenPol(pol).foreach(cp => go(cp._1,\n              // * We should have handled above all top-level cases,\n              // * so the children here are not supposed to be top level.\n              // * Note: We won't get unsoundness if we forgot cases,\n              // * just spurious occurs-check failures!\n              ignoreTLO = false, upperLvl)(cp._2))\n        }\n        // }()\n      }\n      go(pol, ignoreTopLevelOccs, MaxLevel)(this)\n      res.toSortedMap\n    }\n    \n    private def childrenMem(m: NuMember): IterableOnce[ST] = m match {\n      case tf: TypedNuFun =>\n        tf.bodyType :: Nil\n      case als: TypedNuAls =>\n        als.tparams.iterator.map(_._2) ++ S(als.body)\n      case mxn: TypedNuMxn =>\n        mxn.tparams.iterator.map(_._2) ++\n        mxn.members.valuesIterator.flatMap(childrenMem) ++\n          S(mxn.superTy) ++\n          S(mxn.thisTy)\n      case cls: TypedNuCls =>\n        cls.tparams.iterator.map(_._2) ++\n          cls.params.toList.flatMap(_.flatMap(p => p._2.lb.toList ::: p._2.ub :: Nil)) ++\n          cls.auxCtorParams.toList.flatMap(_.values) ++\n          cls.members.valuesIterator.flatMap(childrenMem) ++\n          S(cls.thisTy) ++\n          S(cls.sign)\n      case trt: TypedNuTrt =>\n        trt.tparams.iterator.map(_._2) ++\n          trt.members.valuesIterator.flatMap(childrenMem) ++\n          S(trt.thisTy) ++\n          S(trt.sign) ++\n          trt.parentTP.valuesIterator.flatMap(childrenMem)\n      case p: NuParam =>\n        p.ty.lb.toList ::: p.ty.ub :: Nil\n      case TypedNuDummy(d) => Nil\n    }\n    def children(includeBounds: Bool): List[SimpleType] = this match {\n      case tv @ AssignedVariable(ty) => if (includeBounds) ty :: Nil else Nil\n      case tv: TypeVariable => if (includeBounds) tv.lowerBounds ::: tv.upperBounds ++ tv.tsc.keys.flatMap(_.tvs.values) else Nil\n      case FunctionType(l, r) => l :: r :: Nil\n      case Overload(as) => as\n      case ComposedType(_, l, r) => l :: r :: Nil\n      case RecordType(fs) => fs.flatMap(f => f._2.lb.toList ::: f._2.ub :: Nil)\n      case TupleType(fs) => fs.flatMap(f => f._2.lb.toList ::: f._2.ub :: Nil)\n      case ArrayType(inner) => inner.lb.toList ++ (inner.ub :: Nil)\n      case NegType(n) => n :: Nil\n      case ExtrType(_) => Nil\n      case ProxyType(und) => und :: Nil\n      // case _: TypeTag => Nil\n      case _: ObjectTag | _: Extruded => Nil\n      case SkolemTag(id) => id :: Nil\n      case TypeRef(d, ts) => ts\n      case Without(b, ns) => b :: Nil\n      case TypeBounds(lb, ub) => lb :: ub :: Nil\n      case PolymorphicType(_, und) => und :: Nil\n      case ConstrainedType(cs, und) => cs.flatMap(lu => lu._1 :: lu._2 :: Nil) ::: und :: Nil\n      case SpliceType(fs) => fs.flatMap{ case L(l) => l :: Nil case R(r) => r.lb.toList ::: r.ub :: Nil}\n      case OtherTypeLike(tu) =>\n        val ents = tu.implementedMembers.flatMap(childrenMem)\n        ents ::: tu.result.toList\n    }\n    \n    def getVarsImpl(includeBounds: Bool): SortedSet[TypeVariable] = {\n      val res = MutSet.empty[TypeVariable]\n      @tailrec def rec(queue: List[TypeLike]): Unit = queue match {\n        case (tv: TypeVariable) :: tys =>\n          if (res(tv)) rec(tys)\n          else { res += tv; rec(tv.children(includeBounds = includeBounds) ::: tys) }\n        case ty :: tys => rec(ty.children(includeBounds = includeBounds) ::: tys)\n        case Nil => ()\n      }\n      rec(this :: Nil)\n      SortedSet.from(res)(Ordering.by(_.uid))\n    }\n    def getVars: SortedSet[TypeVariable] = getVarsImpl(includeBounds = true)\n    \n    def showBounds: String =\n      getVars.iterator.filter(tv => tv.assignedTo.nonEmpty || (tv.upperBounds ++ tv.lowerBounds).nonEmpty).map {\n      case tv @ AssignedVariable(ty) => \"\\n\\t\\t\" + tv.toString + \" := \" + ty\n      case tv => (\"\\n\\t\\t\" + tv.toString\n          + (if (tv.lowerBounds.isEmpty) \"\" else \" :> \" + tv.lowerBounds.mkString(\" | \"))\n          + (if (tv.upperBounds.isEmpty) \"\" else \" <: \" + tv.upperBounds.mkString(\" & \")))\n      }.mkString + {\n        val visited: MutSet[TupleSetConstraints] = MutSet.empty\n        getVars.iterator.flatMap(_.tsc).map { case (tsc, i) =>\n          if (visited.add(tsc))\n            (\"\\n\\t\\t[ \"\n              + tsc.tvs.map(t => s\"${printPol(t._1)}${t._2}\").mkString(\", \")\n              + \" ] in { \" + tsc.constraints.mkString(\", \") + \" }\")\n          else \"\"\n        }.mkString\n      }\n  }\n  \n  \n  \n  trait PolymorphicTypeImpl { self: PolymorphicType =>\n    \n    def instantiate(implicit ctx: Ctx): SimpleType = {\n      implicit val state: MutMap[TV, ST] = MutMap.empty\n      println(s\"INST [${polymLevel}]   $this\")\n      println(s\"  where  ${showBounds}\")\n      val res = body.freshenAbove(polymLevel, rigidify = false)\n      println(s\"TO [${lvl}] ~>  $res\")\n      println(s\"  where  ${res.showBounds}\")\n      res\n    }\n    def rigidify(implicit ctx: Ctx, raise: Raise): SimpleType = {\n      implicit val state: MutMap[TV, ST] = MutMap.empty\n      body.freshenAbove(polymLevel, rigidify = true)\n    }\n    def raiseLevelTo(newPolymLevel: Level, leaveAlone: Set[TV] = Set.empty)\n          (implicit ctx: Ctx): PolymorphicType = {\n      implicit val freshened: MutMap[TV, ST] = MutMap.empty\n      raiseLevelToImpl(newPolymLevel, leaveAlone)\n    }\n    def raiseLevelToImpl(newPolymLevel: Level, leaveAlone: Set[TV])\n          (implicit ctx: Ctx, freshened: MutMap[TV, ST]): PolymorphicType = {\n      require(newPolymLevel >= polymLevel)\n      if (newPolymLevel === polymLevel) return this\n      PolymorphicType(newPolymLevel,\n        Typer.freshenAbove(polymLevel, body, leaveAlone = leaveAlone)(\n          ctx.copy(lvl = newPolymLevel + 1), // * Q: is this really fine? cf. stashing/unstashing etc.\n          freshened)\n      ) //(prov)\n    }\n    /** Tries to split a polymorphic function type\n      * by distributing the quantification of *some* of its type vars into the function result. */\n    def splitFunction(implicit ctx: Ctx, raise: Raise): Opt[ST] = {\n      def go(ty: ST, traversed: Set[AnyRef], polymLevel: Level): Opt[ST] = ty match {\n        case ft @ FunctionType(par, bod) =>\n          val couldBeDistribbed = bod.varsBetween(polymLevel, MaxLevel)\n          println(s\"could be distribbed: $couldBeDistribbed\")\n          if (couldBeDistribbed.isEmpty) return N\n          val cannotBeDistribbed = par.varsBetween(polymLevel, MaxLevel)\n          println(s\"cannot be distribbed: $cannotBeDistribbed\")\n          val canBeDistribbed = couldBeDistribbed -- cannotBeDistribbed\n          if (canBeDistribbed.isEmpty) return N // TODO\n          val newInnerLevel =\n            (polymLevel + 1) max cannotBeDistribbed.maxByOption(_.level).fold(MinLevel)(_.level)\n          val innerPoly = PolymorphicType(polymLevel, bod)\n          println(s\"inner: ${innerPoly}\")\n          val res = FunctionType(par, innerPoly.raiseLevelTo(newInnerLevel, cannotBeDistribbed))(ft.prov)\n          println(s\"raised: ${res}\")\n          println(s\"  where: ${res.showBounds}\")\n          if (cannotBeDistribbed.isEmpty) S(res)\n          else S(PolymorphicType(polymLevel, res))\n        case tr: TypeRef if !traversed.contains(tr.defn) => go(tr.expand, traversed + tr.defn, polymLevel)\n        case proxy: ProxyType => go(proxy.underlying, traversed, polymLevel)\n        case tv @ AssignedVariable(ty) if !traversed.contains(tv) =>\n          go(ty, traversed + tv, polymLevel)\n        case tv: TV if tv.level > polymLevel && !traversed.contains(tv) =>\n          // * A quantified variable in positive position can always be replaced by its LBs\n          go(tv.lowerBounds.foldLeft(BotType: ST)(_ | _), traversed + tv, polymLevel)\n        case PolymorphicType(plvl, bod) =>\n          go(bod, traversed, polymLevel min plvl)\n        case _ => N\n      }\n      go(body, Set.empty, polymLevel)\n    }\n    \n  }\n  \n  \n  \n  trait TypeRefImpl { self: TypeRef =>\n    \n    def canExpand(implicit ctx: Ctx): Bool =\n      ctx.tyDefs2.get(defn.name).forall(info =>\n        // * Object types do not need to be completed in order to be expanded\n        info.kind.isInstanceOf[ObjDefKind]\n        || info.isComputed)\n    def expand(implicit ctx: Ctx, raise: Raise): SimpleType = {\n      ctx.tyDefs2.get(defn.name) match {\n        case S(info) =>\n          if (!info.kind.isInstanceOf[ObjDefKind]) {\n            info.complete()\n            if (info.result.isEmpty) // * This can only happen if completion yielded an error\n              return errType\n          }\n        case N =>\n      }\n      expandWith(paramTags = true, selfTy = true)\n    }\n    def expandOrCrash(implicit ctx: Ctx): SimpleType = {\n      require(canExpand)\n      expandWith(paramTags = true, selfTy = true)\n    }\n    def expandWith(paramTags: Bool, selfTy: Bool)(implicit ctx: Ctx): SimpleType =\n      ctx.tyDefs2.get(defn.name).map { info =>\n        lazy val mkTparamRcd = RecordType(info.tparams.lazyZip(targs).map {\n            case ((tn, tv, vi), ta) =>\n              val fldNme = defn.name + \"#\" + tn.name\n              // TODO also use computed variance info when available!\n              Var(fldNme).withLocOf(tn) -> FieldType.mk(vi.getOrElse(VarianceInfo.in), ta, ta)(provTODO)\n          })(provTODO)\n        info.result match {\n          case S(td: TypedNuAls) =>\n            assert(td.tparams.size === targs.size)\n            subst(td.body, td.tparams.lazyZip(targs).map {\n              case (tp, ta) => SkolemTag(tp._2)(noProv) -> ta\n            }.toMap)\n          case S(td: TypedNuTrt) =>\n            assert(td.tparams.size === targs.size)\n            // println(s\"EXP ${td.sign}\")\n            val (freshenMap, _) = refreshHelper2(td, Var(td.name).withLoc(prov.loco), S(targs)) // infer ty args if not provided\n            val freshSelf = if (!selfTy) TopType else {\n              implicit val freshened: MutMap[TV, ST] = freshenMap\n              implicit val shadows: Shadows = Shadows.empty\n              td.sign.freshenAbove(td.level, rigidify = false)\n            }\n            // println(s\"Fresh $freshSelf\")\n            freshSelf & \n              trtNameToNomTag(td.decl)(provTODO, ctx) &\n              mkTparamRcd\n          case S(td: TypedNuCls) =>\n            assert(td.tparams.size === targs.size)\n            val (freshenMap, _) = refreshHelper2(td, Var(td.name).withLoc(prov.loco), S(targs)) // infer ty args if not provided\n            val freshSelf = if (!selfTy) TopType else {\n              implicit val freshened: MutMap[TV, ST] = freshenMap\n              implicit val shadows: Shadows = Shadows.empty\n              td.sign.freshenAbove(td.level, rigidify = false)\n            }\n            clsNameToNomTag(td.decl)(provTODO, ctx) &\n              freshSelf &\n              mkTparamRcd\n          case _ => // * Case for when the type has not been completed yet\n            info.decl match {\n              case td: NuTypeDef if td.kind.isInstanceOf[ClsLikeKind] =>\n                // TODO in the future, add the self signature to DelayedTypeInfo and use it here\n                assert(td.tparams.size === targs.size)\n                clsNameToNomTag(td)(provTODO, ctx) &\n                  mkTparamRcd\n              case td: NuTypeDef if td.kind is Trt =>\n                assert(td.tparams.size === targs.size)\n                trtNameToNomTag(td)(provTODO, ctx) &\n                  mkTparamRcd\n              case td: NuTypeDef if td.kind is Als =>\n                // * Definition was not forced yet, which indicates an error (hopefully)\n                lastWords(\"cannot expand unforced type alias\")\n              case d =>\n                // * Other kinds of type defs are not allowed to be used as types\n                // *  (an error should have been reported earlier)\n                errType\n            }\n        }\n    }.getOrElse {\n      val td = ctx.tyDefs(defn.name)\n      require(targs.size === td.tparamsargs.size)\n      lazy val tparamTags =\n        if (paramTags) RecordType.mk(td.tparamsargs.map { case (tp, tv) =>\n            val tvv = td.getVariancesOrDefault\n            tparamField(defn, tp) -> FieldType(\n              Some(if (tvv(tv).isCovariant) BotType else tv),\n              if (tvv(tv).isContravariant) TopType else tv)(prov)\n          })(noProv)\n        else TopType\n      subst(td.kind match {\n        case Als => td.bodyTy\n        case Mod => throw new NotImplementedError(\"Namespaces are not supported yet.\")\n        case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags\n        case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags\n        case Mxn => lastWords(\"mixins cannot be used as types\")\n      }, td.targs.lazyZip(targs).toMap) //.withProv(prov)\n    } //tap { res => println(s\"Expand $this => $res\") }\n    private var tag: Opt[Opt[ClassTag]] = N\n    def expansionFallback(implicit ctx: Ctx): Opt[ST] = mkClsTag\n    /** Note: self types can be inherited from parents if the definition is abstract\n      * (if it is not abstract, then the class is already known to subtype the inherited self-type) */\n    def mayHaveTransitiveSelfType(implicit ctx: Ctx): Bool = ctx.tyDefs2.get(defn.name) match {\n      case S(lti) => lti.decl match {\n        case td: NuTypeDef if !td.isAbstract => td.sig.nonEmpty\n        case _ => true\n      }\n      case _ => true\n    }\n    def mkClsTag(implicit ctx: Ctx): Opt[ClassTag] = tag.getOrElse {\n      val res = ctx.tyDefs.get(defn.name) match {\n        case S(td: TypeDef) if (td.kind is Cls) || (td.kind is Mod) =>\n          S(clsNameToNomTag(td)(noProv, ctx))\n        case S(td: TypeDef) if td.kind is Trt =>\n          N\n        case _ => ctx.tyDefs2.get(defn.name) match {\n          case S(lti) => lti.decl match {\n            case td: NuTypeDef if (td.kind is Cls) || (td.kind is Mod) =>\n              S(clsNameToNomTag(td)(noProv, ctx))\n            case _ => N\n          }\n          case _ => N\n        }\n      }\n      tag = S(res)\n      res\n    }\n    def mapTargs[R](pol: Opt[Bool])(f: (Opt[Bool], ST) => R)(implicit ctx: Ctx): Ls[R] = {\n      // TODO factor w/ below\n      val (tvarVariances, tparamsargs) = ctx.tyDefs.get(defn.name) match {\n        case S(td) =>\n          (td.tvarVariances, td.tparamsargs)\n        case N =>\n          val td = ctx.tyDefs2(defn.name)\n          (N, td.tparams.map(tp => (tp._1, tp._2)))\n      }\n      tvarVariances.fold(targs.map(f(N, _))) { tvv =>\n        assert(tparamsargs.sizeCompare(targs) === 0)\n        (tparamsargs lazyZip targs).map { case ((_, tv), ta) =>\n          tvv(tv) match {\n            case VarianceInfo(true, true) =>\n              f(N, TypeBounds(BotType, TopType)(noProv))\n            case VarianceInfo(co, contra) =>\n              f(if (co) pol else if (contra) pol.map(!_) else N, ta)\n          }\n      }}\n    }\n    // TODO dedup w/ above\n    def mapTargs[R](pol: PolMap)(f: (PolMap, ST) => R)(implicit ctx: Ctx): Ls[R] = {\n      val (tvarVariances, tparamsargs) = ctx.tyDefs.get(defn.name) match {\n        case S(td) =>\n          (td.tvarVariances, td.tparamsargs)\n        case N =>\n          val td = ctx.tyDefs2.getOrElse(defn.name,\n            // * This should only happen in the presence of ill-formed type definitions;\n            // * TODO: Make sure to report this and raise a compiler internal error if the source\n            // *  does not actually have a type error! Otherwise we could silently get wrong results...\n            return Nil\n          )\n          // TODO use computed varces\n          (some(td.explicitVariances), td.tparams.map(tp => (tp._1, tp._2)))\n      }\n      tvarVariances.fold(targs.map(f(pol.invar, _))) { tvv =>\n        assert(tparamsargs.sizeCompare(targs) === 0)\n        (tparamsargs lazyZip targs).map { case ((_, tv), ta) =>\n          tvv(tv) match {\n            case VarianceInfo(true, true) =>\n              f(pol.invar, TypeBounds(BotType, TopType)(noProv))\n            case VarianceInfo(co, contra) =>\n              f(if (co) pol else if (contra) pol.contravar else pol.invar, ta)\n          }\n      }}\n    }\n    \n  }\n  \n  \n  def merge(pol: Bool, ts: Ls[ST]): ST =\n    if (pol) ts.foldLeft(BotType: ST)(_ | _)\n    else ts.foldLeft(TopType: ST)(_ & _)\n  \n  \n  class Traverser(implicit ctx: Ctx) {\n    def apply(pol: Opt[Bool])(st: ST): Unit = st match {\n      case tv @ AssignedVariable(ty) => apply(pol)(ty)\n      case tv: TypeVariable =>\n        if (pol =/= S(false)) tv.lowerBounds.foreach(apply(S(true)))\n        if (pol =/= S(true)) tv.upperBounds.foreach(apply(S(false)))\n      case FunctionType(l, r) => apply(pol.map(!_))(l); apply(pol)(r)\n      case Overload(as) => as.foreach(apply(pol))\n      case ComposedType(_, l, r) => apply(pol)(l); apply(pol)(r)\n      case RecordType(fs) => fs.unzip._2.foreach(applyField(pol))\n      case TupleType(fs) => fs.unzip._2.foreach(applyField(pol))\n      case ArrayType(fld) => applyField(pol)(fld)\n      case SpliceType(elems) => elems foreach {case L(l) => apply(pol)(l) case R(r) => applyField(pol)(r)}\n      case NegType(n) => apply(pol.map(!_))(n)\n      case ExtrType(_) => ()\n      case ProxyType(und) => apply(pol)(und)\n      case SkolemTag(id) => apply(pol)(id)\n      case _: TypeTag => ()\n      case tr: TypeRef => tr.mapTargs(pol)(apply(_)(_)); ()\n      case Without(b, ns) => apply(pol)(b)\n      case TypeBounds(lb, ub) =>\n        if (pol =/= S(true)) apply(S(false))(lb)\n        if (pol =/= S(false)) apply(S(true))(ub)\n      case PolymorphicType(plvl, und) => apply(pol)(und)\n      case ConstrainedType(cs, bod) =>\n        cs.foreach {\n          case (lo, hi) =>\n            apply(S(true))(lo)\n            apply(S(false))(hi)\n        }\n        apply(pol)(bod)\n    }\n    def applyField(pol: Opt[Bool])(fld: FieldType): Unit = {\n      fld.lb.foreach(apply(pol.map(!_)))\n      apply(pol)(fld.ub)\n    }\n  }\n  object Traverser {\n    trait InvariantFields extends Traverser {\n      override def applyField(pol: Opt[Bool])(fld: FieldType): Unit =\n        if (fld.lb.exists(_ === fld.ub)) apply(N)(fld.ub)\n        else super.applyField(pol)(fld)\n    }\n  }\n  \n  class Traverser2(implicit ctx: Ctx) {\n    def applyLike(pol: PolMap)(ty: TypeLike): Unit = ty match {\n      case ty: ST => apply(pol)(ty)\n      case OtherTypeLike(tu) =>\n        tu.implementedMembers.foreach(applyMem(pol))\n        tu.result.foreach(apply(pol))\n    }\n    def applyMem(pol: PolMap)(m: NuMember): Unit = m match {\n      case TypedNuAls(level, td, tparams, body) =>\n        tparams.iterator.foreach(tp => apply(pol.invar)(tp._2))\n        apply(pol)(body)\n      case TypedNuCls(level, td, tparams, params, acParams, members, thisTy, sign, _, ptps) =>\n        tparams.iterator.foreach(tp => apply(pol.invar)(tp._2))\n        params.foreach(_.foreach(p => applyField(pol)(p._2)))\n        acParams.foreach(_.foreach(p => apply(pol.contravar)(p._2)))\n        members.valuesIterator.foreach(applyMem(pol))\n        apply(pol.contravar)(thisTy)\n        apply(pol.contravar)(sign)\n        ptps.valuesIterator.foreach(applyMem(pol))\n      case TypedNuTrt(level, td, tparams, members, thisTy, sign, _, ptps) => \n        tparams.iterator.foreach(tp => apply(pol.invar)(tp._2))\n        members.valuesIterator.foreach(applyMem(pol))\n        apply(pol.contravar)(thisTy)\n        apply(pol.covar)(sign)\n        ptps.valuesIterator.foreach(applyMem(pol))\n      case TypedNuMxn(level, td, thisTy, superTy, tparams, params, members) =>\n        tparams.iterator.foreach(tp => apply(pol.invar)(tp._2))\n        params.foreach(p => applyField(pol)(p._2))\n        members.valuesIterator.foreach(applyMem(pol))\n        apply(pol.contravar)(thisTy)\n        apply(pol.contravar)(superTy)\n      case NuParam(nme, ty, pub) => applyField(pol)(ty)\n      case TypedNuFun(level, fd, ty) => apply(pol)(ty)\n      case TypedNuDummy(d) => ()\n      // case NuTypeParam(nme, ty) => applyField(pol)(ty)\n    }\n    def apply(pol: PolMap)(st: ST): Unit = st match {\n      case tv @ AssignedVariable(ty) => apply(pol)(ty)\n      case tv: TypeVariable =>\n        val poltv = pol(tv)\n        if (poltv =/= S(false)) tv.lowerBounds.foreach(apply(pol.at(tv.level, true)))\n        if (poltv =/= S(true)) tv.upperBounds.foreach(apply(pol.at(tv.level, false)))\n        tv.tsc.keys.flatMap(_.tvs).foreach(u => apply(pol.at(tv.level,u._1))(u._2))\n      case FunctionType(l, r) => apply(pol.contravar)(l); apply(pol)(r)\n      case Overload(as) => as.foreach(apply(pol))\n      case ComposedType(_, l, r) => apply(pol)(l); apply(pol)(r)\n      case RecordType(fs) => fs.unzip._2.foreach(applyField(pol))\n      case TupleType(fs) => fs.unzip._2.foreach(applyField(pol))\n      case ArrayType(fld) => applyField(pol)(fld)\n      case SpliceType(elems) => elems foreach {case L(l) => apply(pol)(l) case R(r) => applyField(pol)(r)}\n      case NegType(n) => apply(pol.contravar)(n)\n      case ExtrType(_) => ()\n      case ProxyType(und) => apply(pol)(und)\n      // case _: TypeTag => ()\n      case _: ObjectTag | _: Extruded => ()\n      case SkolemTag(id) => apply(pol)(id)\n      case tr: TypeRef => tr.mapTargs(pol)(apply(_)(_)); ()\n      case Without(b, ns) => apply(pol)(b)\n      case TypeBounds(lb, ub) => pol.traverseRange(lb, ub)(apply(_)(_))\n      case PolymorphicType(plvl, und) => apply(pol.enter(plvl))(und)\n      case ConstrainedType(cs, bod) =>\n        cs.foreach {\n          case (lo, hi) =>\n            apply(PolMap.pos)(lo)\n            apply(PolMap.posAtNeg)(hi)\n        }\n        apply(pol)(bod)\n    }\n    def applyField(pol: PolMap)(fld: FieldType): Unit = {\n      fld.lb.foreach(apply(pol.contravar))\n      apply(pol)(fld.ub)\n    }\n  }\n  object Traverser2 {\n    trait InvariantFields extends Traverser2 {\n      override def applyField(pol: PolMap)(fld: FieldType): Unit =\n        if (fld.lb.exists(_ === fld.ub)) apply(pol.invar)(fld.ub)\n        else super.applyField(pol)(fld)\n    }\n  }\n  \n  \n  object PolyFunction {\n    def unapply(ty: ST)(implicit ctx: Ctx, raise: Raise, shadows: Shadows): Opt[PolymorphicType] = {\n      def go(ty: ST, traversed: Set[AnyRef]): Opt[PolymorphicType] = //trace(s\"go $ty\") {\n          if (!distributeForalls) N else ty match {\n        case poly @ PolymorphicType(plvl, bod) => S(poly)\n        case tr: TypeRef if !traversed.contains(tr.defn) => go(tr.expand, traversed + tr.defn)\n        case proxy: ProxyType => go(proxy.underlying, traversed)\n        case tv @ AssignedVariable(ty) if !traversed.contains(tv) =>\n          go(ty, traversed + tv)\n        case ft @ FunctionType(param, funbod) =>\n            for { poly @ PolymorphicType(plvl, bod) <- go(funbod, traversed) }\n            yield {\n              val newRhs = if (param.level > plvl) {\n                  val poly2 = poly.raiseLevelTo(param.level)\n                  PolymorphicType(poly2.polymLevel, FunctionType(param, poly2.body)(ft.prov))\n                } else PolymorphicType(plvl, FunctionType(param, bod)(ft.prov))\n              newRhs\n            }\n        case _ => N\n      }\n      // }(res => s\"= $res\")\n      go(ty, Set.empty)\n    }\n  }\n  object AliasOf {\n    def unapply(ty: ST)(implicit ctx: Ctx): S[ST] = {\n      def go(ty: ST, traversedVars: Set[TV]): S[ST] = ty match {\n        case tr: TypeRef if tr.canExpand => go(tr.expandOrCrash, traversedVars)\n        case proxy: ProxyType => go(proxy.underlying, traversedVars)\n        case tv @ AssignedVariable(ty) if !traversedVars.contains(tv) =>\n          go(ty, traversedVars + tv)\n        case _ => S(ty)\n      }\n      go(ty, Set.empty)\n    }\n  }\n  \n  \n  protected def showLevel(level: Level): Str =\n    (if (level === MaxLevel) \"^\" else if (level > 5 ) \"^\" + level else \"'\" * level)\n  \n  \n  \n  /** This class helps keep track of the *relative polarity* of different [olymorphism levels.\n    * Polarity is relative because polymorphic types can exist at arbitrary polarities,\n    * yet the type variables they quantify have their polarity determined by their local\n    * use in the polymorphic type.\n    * Things get quite involved once type ranges are involved. */\n  abstract class PolMap(val base: Pol) { outer =>\n    private val ctx = 0\n    private val lvl = 0\n    def apply(lvl: Level): Pol\n    def quantifPolarity(lvl: Level): PolMap\n    final def apply(tv: TV): Pol = apply(tv.level)\n    def enter(polymLvl: Level): PolMap =\n      new PolMap(base) {\n        def apply(lvl: Level): Pol =\n          if (lvl > polymLvl) S(true) else outer(lvl)\n        def quantifPolarity(lvl: Level): PolMap =\n          if (lvl > polymLvl) this else outer.quantifPolarity(lvl)\n        def show: Str = s\"$outer;Q($lvl)\"\n      }\n    def invar: PolMap =\n      new PolMap(N) {\n        def apply(lvl: Level): Pol = N\n        def quantifPolarity(lvl: Level): PolMap =\n          outer.quantifPolarity(lvl)\n        def show: Str = s\"$outer;=\"\n      }\n    def covar: PolMap = this\n    def contravar: PolMap =\n      new PolMap(base.map(!_)) {\n        def apply(lvl: Level): Pol =\n          outer(lvl).map(!_)\n        def quantifPolarity(lvl: Level): PolMap =\n          outer.quantifPolarity(lvl)\n        def show: Str = s\"$outer;-\"\n      }\n    /** Used to traverse type variable bounds.\n      * The tricky part is that when a TV is quantified negatively,\n      * then from the POV of lower-level variables,\n      * the polarity of its upper bound is actually POSITIVE! */\n    def at(atLvl: Level, pol: Bool): PolMap =\n      new PolMap(base) {\n        val pm = quantifPolarity(atLvl)\n        def apply(lvl: Level): Pol =\n          // * Everything above or at `atLvl` gets the new polarity pol;\n          // * things under it get the new polarity unless atLvl is quantified negatively,\n          // * in which case they get the opposite polarity !pol.\n          if (lvl >= atLvl) S(pol) else pm(lvl) match {\n            case S(true) => S(pol)\n            case S(false) => S(!pol)\n            case N => N\n          }\n        def quantifPolarity(lvl: Level): PolMap =\n          outer.quantifPolarity(lvl)\n        def show: Str = s\"$outer;@[${printPol(S(pol))}]($lvl)\"\n      }\n    \n    def traverseRange(lb: ST, ub: ST)(k: (PolMap, ST) => Unit): Unit = {\n      if (base =/= S(true)) k(PolMap.neg, lb)\n      if (base =/= S(false)) k(PolMap.pos, ub)\n    }\n    // * Note: We used to have this weird impelmentation,\n    // * which was not consistent with the other places in the code where\n    // * we traversed TypeBound instances...\n    // * I am still unsure what's the proper way of traversing them\n    // * and it's possible there was some truth in this implementation,\n    // * but I no longer remember how it was justified.\n    /* \n    def traverseRange(lb: ST, ub: ST)(k: (PolMap, ST) => Unit): Unit = {\n      def polma(p: Bool) = new PolMap(S(p)) {\n        def apply(lvl: Level): Pol =\n          outer.quantifPolarity(lvl).base match {\n            case N => N\n            case S(true) => S(p)\n            case S(false) => S(!p)\n          }\n        def quantifPolarity(lvl: Level): PolMap =\n          outer.quantifPolarity(lvl)\n        def show: Str = s\"$outer;R${printPol(S(p))}\"\n      }\n      if (base =/= S(true)) k(polma(false), lb)\n      if (base =/= S(false)) k(polma(true), ub)\n    }\n    */\n    \n    protected def show: Str\n    override def toString: String = show\n  }\n  object PolMap {\n    private def mk(init: Pol): PolMap = new PolMap(init) {\n      def apply(lvl: Level): Pol = init\n      def quantifPolarity(lvl: Level): PolMap = this\n      def show: Str = s\"${printPol(init)}\"\n    }\n    val pos: PolMap = mk(S(true))\n    val neg: PolMap = mk(S(false))\n    val posAtNeg: PolMap = pos.at(MinLevel, false)\n    val neu: PolMap = mk(N)\n    def apply(init: Pol = S(true)): PolMap = init match {\n      case S(true) => pos\n      case S(false) => neg\n      case N => neu\n    }\n  }\n  \n  \n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/codegen/Codegen.scala",
    "content": "package mlscript\n\n// Goals:\n// - Better readability.\n//  - Remove unnecessary parentheses.\n//  - Add better indentations.\n// - Consistent runtime behavior.\n//  - Currying methods declared in MLscript.\n//  - Combine curry calls on other functions.\n\nimport mlscript.utils._, shorthands._\nimport scala.collection.immutable\nimport scala.util.matching.Regex\nimport scala.collection.mutable.ListBuffer\nimport mlscript.codegen.Symbol\n\nclass SourceLine(val content: Str, indent: Int = 0) {\n  def indented: SourceLine = new SourceLine(content, indent + 1)\n  def +(that: SourceLine): SourceLine =\n    new SourceLine(content + that.content, indent)\n  def withPrefix(prefix: Str): SourceLine =\n    new SourceLine(prefix + content, indent)\n  def withPostfix(postfix: Str): SourceLine =\n    new SourceLine(content + postfix, indent)\n  def between(prefix: Str, postfix: Str): SourceLine =\n    new SourceLine(prefix + content + postfix, indent)\n  override def toString: Str = \"  \" * indent + content\n}\n\nobject SourceLine {\n  def apply(line: Str): SourceLine = new SourceLine(line)\n}\n\n/**\n  * SourceCode is a list of SourceLines that can be exported to a code file\n  * \n  * SourceCode provides a number of helper methods to create SourceCode\n  * from strings and manipulate them. It also abstracts common code patterns\n  * like block, condition, clause\n  *\n  * @param lines\n  */\nclass SourceCode(val lines: Ls[SourceLine]) {\n\n  /** Concat two parts of source code vertically. \"1 \\\\ 2\" + \"3 \\\\ 4\" == \"1 \\\\ 2 \\\\ 3 \\\\ 4\"\n    *\n    * @param that\n    *   another part of source code\n    * @return\n    */\n  def +(that: SourceCode): SourceCode = new SourceCode(lines ++ that.lines)\n\n  /** Concat two parts of source code horizontally. \"1 \\\\ 2\" ++ \"3 \\\\ 4\" == \"1 \\\\ 2 3 \\\\ 4\"\n    *\n    * @param that\n    *   another part of source code\n    * @return\n    */\n  def ++(that: SourceCode): SourceCode = that.lines match {\n    case head :: next =>\n      if (lines.nonEmpty) {\n        new SourceCode(lines.init ::: Ls(lines.last + head) ::: next)\n      } else {\n        that\n      }\n    case Nil => this\n  }\n\n  def isSingleLine: Bool = lines.sizeCompare(1) === 0\n\n  def isMultipleLine: Bool = lines.lengthIs > 1\n\n  def isEmpty: Bool = lines.isEmpty\n  def indented: SourceCode = new SourceCode(lines map { _.indented })\n  def parenthesized(implicit run: Bool = true): SourceCode =\n    if (run) {\n      lines.length match {\n        case 0 => SourceCode(\"()\")\n        case 1 => new SourceCode(lines map { _.between(\"(\", \")\") })\n        case _ =>\n          val head = lines.head\n          val middle = lines.tail.dropRight(1)\n          val last = lines.last\n          new SourceCode(\n            head.withPrefix(\"(\") :: middle ::: Ls(last.withPostfix(\")\"))\n          )\n      }\n    } else {\n      this\n    }\n  def clause: SourceCode =\n    lines.length match {\n      case 0 | 1 => this\n      case _ =>\n        val head = lines.head\n        val middle = lines.tail.dropRight(1)\n        val last = lines.last\n        new SourceCode(\n          head.withPrefix(\"(\") :: middle ::: Ls(last.withPostfix(\")\"))\n        )\n    }\n  def condition: SourceCode =\n    lines.length match {\n      case 0 => this\n      case 1 => new SourceCode(lines map { _.between(\"(\", \")\") })\n      case _ =>\n        new SourceCode(\n          SourceLine(\"(\")\n            :: lines.map({ _.indented })\n            ::: Ls(SourceLine(\")\"))\n        )\n    }\n  // Surround the source code with braces in a block style.\n  def block: SourceCode =\n    lines.length match {\n      case 0 => SourceCode(\"{}\")\n      case _ =>\n        new SourceCode(\n          SourceLine(\"{\")\n            :: lines.map({ _.indented })\n            ::: Ls(SourceLine(\"}\"))\n        )\n    }\n  override def toString: Str = lines.mkString(\"\\n\")\n\n  def toLines: Ls[Str] = lines.map(_.toString)\n}\n\nobject SourceCode {\n  def apply(line: Str): SourceCode = new SourceCode(Ls(new SourceLine(line, 0)))\n  def apply(lines: Ls[Str]): SourceCode = new SourceCode(lines map {\n    new SourceLine(_, 0)\n  })\n  def fromStmts(stmts: Ls[JSStmt]): SourceCode = SourceCode.concat(stmts map { _.toSourceCode })\n\n  val ampersand: SourceCode = SourceCode(\" & \")\n  val space: SourceCode = SourceCode(\" \")\n  val semicolon: SourceCode = SourceCode(\";\")\n  val colon: SourceCode = SourceCode(\": \")\n  val separator: SourceCode = SourceCode(\" | \")\n  val comma: SourceCode = SourceCode(\",\")\n  val commaSpace: SourceCode = SourceCode(\", \")\n  val empty: SourceCode = SourceCode(Nil)\n  val openCurlyBrace: SourceCode = SourceCode(\"{\")\n  val closeCurlyBrace: SourceCode = SourceCode(\"}\")\n  val openAngleBracket: SourceCode = SourceCode(\"<\")\n  val closeAngleBracket: SourceCode = SourceCode(\">\")\n  val fatArrow: SourceCode = SourceCode(\" => \")\n  val equalSign: SourceCode = SourceCode(\" = \")\n\n  def concat(codes: Ls[SourceCode]): SourceCode =\n    codes.foldLeft(SourceCode.empty) { _ + _ }\n\n  // concatenate source codes without intermediate allocations\n  def bulkConcat(codes: Iterable[SourceCode]): SourceCode =\n    new SourceCode(codes.iterator.map(_.lines).foldRight(List.empty[SourceLine])((lines, accum) => lines ::: accum))\n\n  /**\n    * Comma-separate elements of List[SourceCode] and wrap with curly braces.\n    * Each element is on a new line.\n    * \n    * @param entries\n    * @return\n    */\n  def record(entries: Ls[SourceCode]): SourceCode =\n    entries match {\n      case Nil         => SourceCode(\"{}\")\n      case entry :: Nil => if (entry.isMultipleLine) {\n        SourceCode(\"{\") + entry.indented + SourceCode(\"}\")\n      } else {\n        SourceCode(\"{ \") ++ entry ++ SourceCode(\" }\")\n      }\n      case _ =>\n        (entries.zipWithIndex.foldLeft(SourceCode(\"{\")) { case (acc, (entry, index)) =>\n          acc + (if (index + 1 === entries.length) { entry }\n                 else { entry ++ SourceCode.comma }).indented\n        }) + SourceCode(\"}\")\n    }\n\n\n  /**\n    * Comma separate elements of List[SourceCode] and wrap with curly braces\n    * on the same horizontal line\n    * \n    * @param entries\n    * @return\n    */\n    def horizontalRecord(entries: Ls[SourceCode]): SourceCode = {\n      entries match {\n        case Nil => SourceCode(\"{}\")\n        case _ =>\n          (entries\n            .zipWithIndex.foldLeft(SourceCode(\"{\")) { case (acc, (entry, index)) =>\n            acc ++ entry ++ (if (index + 1 === entries.length) SourceCode.closeCurlyBrace else SourceCode.commaSpace)\n          })\n      }\n    }\n\n\n    def recordWithEntries(entries: List[SourceCode -> SourceCode]): SourceCode = {\n      entries match {\n        case Nil => SourceCode(\"{}\")\n        case _ =>\n          (entries\n            .map(entry => entry._1 ++ colon ++ entry._2)\n            .zipWithIndex.foldLeft(SourceCode(\"{\")) { case (acc, (entry, index)) =>\n            acc ++ entry ++ (if (index + 1 === entries.length) SourceCode.closeCurlyBrace else SourceCode.commaSpace)\n          })\n      }\n    }\n    \n    /** ',' separate and wrap in angled brackets the given source code instances\n      * and return empty string if list is empty \n      *\n      * @param entries\n      * @return\n      */\n    def paramList(entries: List[SourceCode]): SourceCode = {\n      entries match {\n        case Nil => SourceCode(\"\")\n        case _ =>\n          (entries\n            .zipWithIndex.foldLeft(SourceCode.openAngleBracket) { case (acc, (entry, index)) =>\n            acc ++ entry ++ (if (index + 1 === entries.length) SourceCode.closeAngleBracket else SourceCode.commaSpace)\n          })\n      }\n    }\n\n  /**\n    * Surround the source code with braces.\n    */\n  def array(entries: Ls[SourceCode]): SourceCode =\n    entries match {\n      case Nil         => SourceCode(\"[]\")\n      case entry :: Nil => if (entry.isMultipleLine) {\n        SourceCode(\"[\") + entry.indented + SourceCode(\"]\")\n      } else {\n        SourceCode(\"[\") ++ entry ++ SourceCode(\"]\")\n      }\n      case _ =>\n        (entries.zipWithIndex.foldLeft(SourceCode(\"[\")) { case (acc, (entry, index)) =>\n          acc + (if (index + 1 === entries.length) { entry }\n                 else { entry ++ SourceCode.comma }).indented\n        }) + SourceCode(\"]\")\n    }\n\n  /**\n    * Surround source code with square brackets concatenating elements\n    * horizontally only. Single element is still wrapped in brackets\n    *\n    * @param entries\n    * @return\n    */\n  def horizontalArray(entries: Ls[SourceCode]): SourceCode =\n    (entries.zipWithIndex.foldLeft(SourceCode(\"[\")) { case (acc, (entry, index)) =>\n      acc ++ entry ++ (if (index + 1 === entries.length) SourceCode(\"]\") else SourceCode.commaSpace)\n    })\n\n\n  def sepBy(codes: Ls[SourceCode], sep: SourceCode = this.commaSpace): SourceCode =\n    codes.zipWithIndex\n      .foldLeft(this.empty) { case (x, (y, i)) =>\n        x ++ y ++ (if (i === codes.length - 1) this.empty else sep)\n      }\n\n}\n\nabstract class JSCode {\n  def toSourceCode: SourceCode\n}\n\nabstract class JSPattern extends JSCode {\n}\n\nobject JSPattern {\n}\n\nfinal case class JSArrayPattern(elements: Ls[JSPattern]) extends JSPattern {\n  def toSourceCode: SourceCode = SourceCode.array(elements map { _.toSourceCode })\n}\n\nfinal case class JSObjectPattern(properties: Ls[Str -> Opt[JSPattern]]) extends JSPattern {\n  // If no sub-patterns, use the property name as the binding name.\n  def toSourceCode: SourceCode = SourceCode.record(\n    properties\n      .map {\n        case name -> Some(JSWildcardPattern()) => SourceCode(name)\n        case name -> Some(subPattern) =>\n          SourceCode(s\"$name: \") ++ subPattern.toSourceCode\n        case name -> N => SourceCode(name)\n      }\n  )\n}\n\nfinal case class JSWildcardPattern() extends JSPattern {\n  def toSourceCode: SourceCode = SourceCode.empty\n}\n\nfinal case class JSNamePattern(name: Str) extends JSPattern {\n  def toSourceCode: SourceCode = SourceCode(name)\n}\n\nabstract class JSExpr extends JSCode {\n  // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence\n  implicit def precedence: Int\n\n  def isSimple: Bool = false\n\n  def prop(property: JSExpr): JSMember = JSMember(this, property)\n\n  def stmt: JSExprStmt = JSExprStmt(this)\n  \n  def `return`: JSReturnStmt = JSReturnStmt(S(this))\n\n  def `throw`: JSThrowStmt = JSThrowStmt(this)\n\n  def member(name: Str): JSField = JSField(this, name)\n\n  def apply(name: Str): JSField = JSField(this, name)\n\n  def apply(args: JSExpr*): JSInvoke = JSInvoke(this, args.toList)\n\n  def unary(op: Str): JSUnary = JSUnary(op, this)\n\n  def binary(op: Str, rhs: JSExpr): JSBinary = JSBinary(op, this, rhs)\n\n  def typeof(): JSUnary = JSUnary(\"typeof\", this)\n\n  def instanceOf(rhs: JSExpr): JSBinary = JSBinary(\"instanceof\", this, rhs)\n\n  def +(rhs: JSExpr): JSBinary = binary(\"+\", rhs)\n\n  def ??(rhs: JSExpr): JSBinary = binary(\"??\", rhs)\n\n  def :||(rhs: JSExpr): JSBinary = binary(\"||\", rhs)\n\n  def :===(rhs: JSExpr): JSBinary = binary(\"===\", rhs)\n\n  def :=(value: JSExpr): JSStmt = JSAssignExpr(this, value).stmt\n\n  def switch(default: Ls[JSStmt], cases: (JSExpr -> Ls[JSStmt])*): JSSwitchStmt =\n    JSSwitchStmt(\n      this,\n      (cases map { case (t, c) => JSSwitchCase(t, c) }).toList,\n      S(JSDefaultCase(default))\n    )\n\n  def switch(cases: (JSExpr -> Ls[JSStmt])*): JSSwitchStmt =\n    JSSwitchStmt(this, (cases map { case (t, c) => JSSwitchCase(t, c) }).toList)\n\n  def log(): JSStmt = JSIdent(\"console\").member(\"log\")(this).stmt\n\n  def embed(implicit parentPrecedence: Int): SourceCode =\n    if (precedence < parentPrecedence) {\n      this.toSourceCode.parenthesized\n    } else {\n      this.toSourceCode\n    }\n}\n\nobject JSExpr {\n  // Helper function for creating string literals.\n  def apply(str: Str): JSLit = JSLit(JSLit.makeStringLiteral(str))\n\n  def params(params: Ls[JSPattern]): SourceCode =\n    params.zipWithIndex\n      .foldLeft(SourceCode.empty) { case (x, (y, i)) =>\n        x ++ (y match {\n          case JSWildcardPattern() => SourceCode(s\"_$i\")\n          case pattern             => pattern.toSourceCode\n        }) ++ (if (i === params.length - 1) SourceCode.empty else SourceCode(\", \"))\n      }\n      .parenthesized\n  def arguments(exprs: Ls[JSExpr]): SourceCode =\n    exprs.zipWithIndex\n      .foldLeft(SourceCode.empty) { case (x, (y, i)) =>\n        x ++ y.embed(parentPrecedence = JSCommaExpr.outerPrecedence) ++ (if (i === exprs.length - 1) SourceCode.empty\n                                else SourceCode(\", \"))\n      }\n      .parenthesized\n}\n\nfinal case class JSCommaExpr(exprs: Ls[JSExpr]) extends JSExpr {\n  implicit def precedence: Int = 1\n  def toSourceCode: SourceCode = SourceCode.sepBy(exprs map { _.toSourceCode })\n}\n\nobject JSCommaExpr {\n  val outerPrecedence: Int = 2\n}\n\nfinal case class JSAssignExpr(lhs: JSExpr, rhs: JSExpr) extends JSExpr {\n  implicit def precedence: Int = 3\n  def toSourceCode: SourceCode =\n    lhs.embed(precedence) ++ SourceCode(\" = \") ++ rhs.embed(precedence)\n}\n\nfinal case class JSPlaceholderExpr() extends JSExpr {\n  implicit def precedence: Int = ???\n  def toSourceCode: SourceCode = SourceCode.empty\n}\n\nfinal case class JSArrowFn(params: Ls[JSPattern], body: JSExpr \\/ Ls[JSStmt]) extends JSExpr {\n  // If the precedence is 2. We will have x => (x, 0) and (x => x)(1).\n  implicit def precedence: Int = 2\n  def toSourceCode: SourceCode =\n    params.zipWithIndex\n      .foldLeft(SourceCode.empty) { case (x, (y, i)) =>\n        x ++ (y match {\n          case JSWildcardPattern() => SourceCode(s\"_$i\")\n          case pattern             => pattern.toSourceCode\n        }) ++ (if (i === params.length - 1) SourceCode.empty else SourceCode(\", \"))\n      }\n      .parenthesized ++ SourceCode.fatArrow ++ (body match {\n      // TODO: Figure out how `=>` competes with other operators.\n      case L(expr: JSRecord) => expr.toSourceCode.parenthesized\n      case L(expr)  => expr.embed\n      case R(stmts) => SourceCode.concat(stmts map { _.toSourceCode }).block\n    })\n  def toFuncExpr(name: Opt[Str]): JSFuncExpr = JSFuncExpr(name, params, body match {\n    case L(expr) => expr.`return` :: Nil\n    case R(stmts) => stmts\n  })\n}\n\nfinal case class JSFuncExpr(name: Opt[Str], params: Ls[JSPattern], body: Ls[JSStmt]) extends JSExpr {\n  implicit def precedence: Int = 22\n  def toSourceCode: SourceCode =\n    SourceCode(s\"function ${name getOrElse \"\"}\") ++\n      JSExpr.params(params) ++\n      SourceCode.space ++\n      SourceCode.concat(body map { _.toSourceCode }).block\n}\n\n// IIFE: immediately invoked function expression\nfinal case class JSImmEvalFn(\n    name: Opt[Str],\n    params: Ls[JSPattern],\n    body: Either[JSExpr, Ls[JSStmt]],\n    arguments: Ls[JSExpr]\n) extends JSExpr {\n  implicit def precedence: Int = 22\n  def toSourceCode: SourceCode = name match {\n    case None =>\n      (SourceCode(s\"${JSExpr.params(params)} => \") ++ (body match {\n        case Left(expr: JSRecord) => expr.toSourceCode.parenthesized\n        case Left(expr) => expr.embed(parentPrecedence = 2)\n        case Right(stmts) =>\n          stmts.foldLeft(SourceCode.empty) { _ + _.toSourceCode }.block\n      })).parenthesized ++ JSExpr.arguments(arguments)\n    case Some(fnName) =>\n      (SourceCode(s\"function $fnName${JSExpr.params(params)} \") ++ (body match {\n        case Left(expr) => expr.`return`.toSourceCode\n        case Right(stmts) =>\n          stmts.foldLeft(SourceCode.empty) { _ + _.toSourceCode }\n      }).block).parenthesized ++ JSExpr.arguments(arguments)\n  }\n}\n\nfinal case class JSTenary(tst: JSExpr, csq: JSExpr, alt: JSExpr) extends JSExpr {\n  implicit def precedence: Int = 4\n  def toSourceCode =\n    tst.embed ++ SourceCode(\" ? \") ++ csq.embed ++ SourceCode(\" : \") ++ alt.embed\n}\n\nfinal case class JSInvoke(callee: JSExpr, arguments: Ls[JSExpr]) extends JSExpr {\n  implicit def precedence: Int = 20\n  def toSourceCode =\n    callee.embed(precedence) ++ arguments.zipWithIndex\n      .foldLeft(SourceCode.empty) { case (x, (y, i)) =>\n        x ++ y.embed(JSCommaExpr.outerPrecedence) ++\n        (if (i === arguments.length - 1) SourceCode.empty else SourceCode(\", \"))\n      }\n      .parenthesized\n}\n\nfinal case class JSUnary(op: Str, arg: JSExpr) extends JSExpr {\n  implicit def precedence: Int = 15\n\n  override def toSourceCode: SourceCode = (op match {\n    case \"typeof\" => SourceCode(\"typeof \")\n    case _        => SourceCode(op)\n  }) ++ arg.embed\n}\n\nfinal case class JSBinary(op: Str, left: JSExpr, right: JSExpr) extends JSExpr {\n  def apply(op: Str, left: JSExpr, right: JSExpr): JSBinary =\n    new JSBinary(op, left, right)\n\n  implicit def precedence: Int = JSBinary.opPrecMap get op match {\n    case Some(prec) => prec\n    case None       => throw new Error(s\"Unknown binary operator: $op\")\n  }\n\n  override def toSourceCode: SourceCode =\n    left.embed ++ SourceCode(s\" $op \") ++ right.embed\n}\n\nobject JSBinary {\n  private def opPrecMap =\n    immutable.HashMap[Str, Int](\n      // infixr 14\n      \"**\" -> 14,\n      // infixl 13\n      \"*\" -> 13,\n      \"/\" -> 13,\n      \"%\" -> 13,\n      // infixl 12\n      \"+\" -> 12,\n      \"-\" -> 12,\n      // infixl 11\n      \"<<\" -> 11,\n      \">>\" -> 11,\n      \">>>\" -> 11,\n      // infixl 10\n      \"<\" -> 10,\n      \"<=\" -> 10,\n      \">\" -> 10,\n      \">=\" -> 10,\n      \"in\" -> 10,\n      \"instanceof\" -> 10,\n      // infixl 9\n      \"==\" -> 9,\n      \"!=\" -> 9,\n      \"===\" -> 9,\n      \"!==\" -> 9,\n      // infixl 8\n      \"&\" -> 8,\n      // infixl 7\n      \"^\" -> 7,\n      // infixl 6\n      \"|\" -> 6,\n      // infixl 5\n      \"&&\" -> 5,\n      // infixl 4\n      \"||\" -> 4,\n      \"??\" -> 4,\n      \",\" -> 1,\n    )\n  \n  val operators: Set[Str] = opPrecMap.keySet\n}\n\nfinal case class JSLit(literal: Str) extends JSExpr {\n  // Literals has the highest precedence.\n  implicit def precedence: Int = 22\n  def toSourceCode = SourceCode(literal)\n}\n\nobject JSLit {\n  def makeStringLiteral(s: Str): Str = {\n    s.map[Str] {\n      _ match {\n        case '\"'  => \"\\\\\\\"\"\n        case '\\\\' => \"\\\\\\\\\"\n        case '\\b' => \"\\\\b\"\n        case '\\f' => \"\\\\f\"\n        case '\\n' => \"\\\\n\"\n        case '\\r' => \"\\\\r\"\n        case '\\t' => \"\\\\t\"\n        case c =>\n          if (0 < c && c <= 255 && !c.isControl) {\n            c.toString\n          } else {\n            f\"\\\\u${c.toInt}%04X\"\n          }\n      }\n    }.mkString(\"\\\"\", \"\", \"\\\"\")\n  }\n}\n\nfinal case class JSInstanceOf(left: JSExpr, right: JSExpr) extends JSExpr {\n  implicit def precedence: Int = 12\n  def toSourceCode: SourceCode =\n    left.toSourceCode ++ SourceCode(\" instanceof \") ++ right.toSourceCode\n}\n\nfinal case class JSIdent(name: Str) extends JSExpr {\n  implicit def precedence: Int = 22\n  def toSourceCode: SourceCode = SourceCode(name)\n}\n\nfinal case class JSNew(ctor: JSExpr) extends JSExpr {\n  implicit def precedence: Int = 21\n  def toSourceCode: SourceCode = SourceCode(\"new \") ++ ctor.toSourceCode\n}\n\nclass JSMember(`object`: JSExpr, property: JSExpr) extends JSExpr {\n  override def precedence: Int = 20\n  override def toSourceCode: SourceCode =\n    `object`.toSourceCode.parenthesized(\n      `object`.precedence < precedence || `object`.isInstanceOf[JSRecord] || `object`.isInstanceOf[JSNew]\n    ) ++ SourceCode(\"[\") ++ property.toSourceCode ++ SourceCode(\"]\")\n\n  override def isSimple: Bool = `object`.isSimple\n}\n\nobject JSMember {\n  def apply(`object`: JSExpr, property: JSExpr): JSMember = new JSMember(`object`, property)\n}\n\nclass JSField(`object`: JSExpr, val property: JSIdent) extends JSMember(`object`, property) {\n  override def toSourceCode: SourceCode =\n    `object`.toSourceCode.parenthesized(\n      `object`.precedence < precedence || `object`.isInstanceOf[JSRecord] || `object`.isInstanceOf[JSNew]\n    ) ++ SourceCode(\n      if (JSField.isValidFieldName(property.name)) {\n        s\".${property.name}\"\n      } else\n        property.name.toIntOption match {\n          case S(index) => s\"[$index]\"\n          case N => s\"[${JSLit.makeStringLiteral(property.name)}]\"\n        }\n    )\n}\n\nobject JSField {\n  def apply(`object`: JSExpr, property: String): JSField = new JSField(`object`, JSIdent(property))\n\n  private val identifierPattern: Regex = \"^[A-Za-z$][A-Za-z0-9$]*$\".r\n\n  def isValidIdentifier(s: Str): Bool = identifierPattern.matches(s) && !Symbol.isKeyword(s)\n\n  // in this case, a keyword can be used as a field name\n  // e.g. `something.class` is valid\n  def isValidFieldName(s: Str): Bool = identifierPattern.matches(s)\n\n  def emitValidFieldName(s: Str): Str = if (isValidIdentifier(s)) s else JSLit.makeStringLiteral(s)\n}\n\nfinal case class JSArray(items: Ls[JSExpr]) extends JSExpr {\n  // Precedence of literals is zero.\n  override def precedence: Int = 22\n  // Make\n  override def toSourceCode: SourceCode =\n    SourceCode.array(items map { _.embed(JSCommaExpr.outerPrecedence) })\n}\n\nfinal case class JSRecord(entries: Ls[Str -> JSExpr], methods: Ls[JSStmt] = Nil) extends JSExpr {\n  override def precedence: Int = 22\n  // Make\n  override def toSourceCode: SourceCode = SourceCode\n    .record((entries map { case (key, value) =>\n      SourceCode(JSField.emitValidFieldName(key) + \": \") ++ value.embed(JSCommaExpr.outerPrecedence)\n    }) ++ (methods.map((m) => m.toSourceCode)))\n}\n\nfinal case class JSClassExpr(cls: JSClassNewDecl) extends JSExpr {\n  implicit def precedence: Int = 22\n  def toSourceCode: SourceCode = cls.toSourceCode\n}\n\nabstract class JSStmt extends JSCode\n\nfinal case class JSExprStmt(expr: JSExpr) extends JSStmt {\n  def toSourceCode: SourceCode =\n    expr.toSourceCode.parenthesized(expr.isInstanceOf[JSRecord]) ++ SourceCode.semicolon\n}\n\n// A single if statement without else clauses\nfinal case class JSIfStmt(test: JSExpr, body: Ls[JSStmt], `else`: Ls[JSStmt] = Nil) extends JSStmt {\n  def toSourceCode: SourceCode = SourceCode(\"if \") ++\n    test.toSourceCode.condition ++\n    SourceCode.space ++\n    body.foldLeft(SourceCode.empty) { _ + _.toSourceCode }.block ++ (`else` match {\n      case Nil => SourceCode.empty\n      case _   => SourceCode(\" else \") ++ `else`.foldLeft(SourceCode.empty) { _ + _.toSourceCode }.block\n    })\n}\n\nfinal case class JSForInStmt(pattern: JSPattern, iteratee: JSExpr, body: Ls[JSStmt]) extends JSStmt {\n  def toSourceCode: SourceCode = SourceCode(\"for (const \") ++\n    pattern.toSourceCode ++\n    SourceCode(\" in \") ++\n    iteratee.toSourceCode ++\n    SourceCode(\")\") ++\n    body.foldLeft(SourceCode.empty) { _ + _.toSourceCode }.block\n}\n\nfinal case class JSWhileStmt(cond: JSExpr, body: JSExpr) extends JSStmt {\n  def toSourceCode: SourceCode = SourceCode(\"while (\") ++\n    cond.toSourceCode ++\n    SourceCode(\") \") ++\n    body.toSourceCode.block\n}\n\n// A single return statement.\nfinal case class JSReturnStmt(value: Opt[JSExpr]) extends JSStmt {\n  def toSourceCode = (value match {\n    case Some(value) => SourceCode(\"return \") ++ value.toSourceCode.clause\n    case None => SourceCode(\"return\")\n  }) ++ SourceCode.semicolon\n}\n\nfinal case class JSTryStmt(block: Ls[JSStmt], handler: JSCatchClause) extends JSStmt {\n  def toSourceCode: SourceCode = SourceCode(\"try \") ++\n    block.foldLeft(SourceCode.empty) { _ + _.toSourceCode }.block ++\n    handler.toSourceCode\n}\n\nfinal case class JSCatchClause(param: JSIdent, body: Ls[JSStmt]) extends JSCode {\n  def toSourceCode: SourceCode = SourceCode(s\" catch (${param.name}) \") ++\n    body.foldLeft(SourceCode.empty) { _ + _.toSourceCode }.block\n}\n\n// Throw statement currently only used in non-exhaustive pattern matchings.\nfinal case class JSThrowStmt(arg: JSExpr) extends JSStmt {\n  def toSourceCode: SourceCode =\n    SourceCode(\"throw \") ++ arg.toSourceCode.clause ++ SourceCode.semicolon\n}\n\nfinal case class JSSwitchStmt(\n    discriminant: JSExpr,\n    cases: Ls[JSSwitchCase],\n    default: Opt[JSDefaultCase] = N\n) extends JSStmt {\n  def toSourceCode: SourceCode =\n    SourceCode(\"switch (\") ++ discriminant.toSourceCode ++ SourceCode(\") {\") +\n      cases.foldLeft(SourceCode.empty) { _ + _.toSourceCode.indented } +\n      (default match {\n        case S(default) => default.toSourceCode.indented + SourceCode(\"}\")\n        case N => SourceCode(\"}\")\n      })\n}\n\nfinal case class JSSwitchCase(test: JSExpr, consequent: Ls[JSStmt]) {\n  def toSourceCode: SourceCode =\n    SourceCode(\"case \") ++ test.toSourceCode ++ SourceCode(\": \") +\n      consequent.foldLeft(SourceCode.empty) { _ + _.toSourceCode.indented }\n}\n\nfinal case class JSDefaultCase(consequent: Ls[JSStmt]) {\n  def toSourceCode: SourceCode =\n    SourceCode(\"default:\") +\n      consequent.foldLeft(SourceCode.empty) { _ + _.toSourceCode.indented }\n}\n\nfinal case class JSLetDecl(decls: Ls[Str -> Opt[JSExpr]]) extends JSStmt {\n  def toSourceCode: SourceCode =\n    SourceCode(s\"let \") ++ decls.zipWithIndex\n      .foldLeft(SourceCode.empty) { case (x, (y, i)) =>\n        x ++ (y match {\n          case (pat, N)       => SourceCode(pat)\n          case (pat, S(init)) => SourceCode(pat) ++ SourceCode(\" = \") ++ init.toSourceCode\n        }) ++ (if (i === decls.length - 1) SourceCode.empty else SourceCode(\", \"))\n      } ++ SourceCode.semicolon\n}\n\nobject JSLetDecl {\n  def from(names: Ls[Str]): JSLetDecl = JSLetDecl(names map { _ -> N })\n}\n\nfinal case class JSConstDecl(pattern: Str, body: JSExpr) extends JSStmt {\n  def toSourceCode: SourceCode =\n    SourceCode(s\"const $pattern = \") ++ (body match {\n      case _: JSCommaExpr => body.toSourceCode.parenthesized\n      case _              => body.toSourceCode\n    }) ++ SourceCode.semicolon\n}\n\nfinal case class JSFuncDecl(name: Str, params: Ls[JSPattern], body: Ls[JSStmt]) extends JSStmt {\n  def toSourceCode: SourceCode =\n    SourceCode(s\"function $name\") ++ JSExpr.params(params) ++ SourceCode.space ++ body\n      .foldLeft(SourceCode.empty) { case (x, y) => x + y.toSourceCode }\n      .block\n}\n\nabstract class JSClassMemberDecl extends JSStmt;\n\nfinal case class JSClassGetter(name: Str, body: JSExpr \\/ Ls[JSStmt]) extends JSClassMemberDecl {\n  def toSourceCode: SourceCode =\n    SourceCode(s\"get ${JSField.emitValidFieldName(name)}() \") ++ (body match {\n      case Left(expr) => new JSReturnStmt(S(expr)).toSourceCode\n      case Right(stmts) =>\n        stmts.foldLeft(SourceCode.empty) { case (x, y) => x + y.toSourceCode }\n    }).block\n}\n\nfinal case class JSClassSetter(name: Str) extends JSClassMemberDecl {\n  def toSourceCode: SourceCode =\n    SourceCode(s\"set ${JSField.emitValidFieldName(name)}(value) \") ++ (\n      JSIdent(s\"this.#$name\") := JSIdent(\"value\")\n    ).toSourceCode.block\n}\n\nfinal case class JSClassMethod(\n    name: Str,\n    params: Ls[JSPattern],\n    body: JSExpr \\/ Ls[JSStmt]\n) extends JSClassMemberDecl {\n  def toSourceCode: SourceCode =\n    SourceCode(JSField.emitValidFieldName(name)) ++ JSExpr.params(params) ++ SourceCode.space ++ (body match {\n      case Left(expr) => new JSReturnStmt(S(expr)).toSourceCode\n      case Right(stmts) =>\n        stmts.foldLeft(SourceCode.empty) { case (x, y) => x + y.toSourceCode }\n    }).block\n}\n\nfinal case class JSClassMember(name: Str, body: JSExpr) extends JSClassMemberDecl {\n  def toSourceCode: SourceCode =\n    SourceCode(name) ++ SourceCode(\" = \") ++ body.toSourceCode ++ SourceCode.semicolon\n}\n\nfinal case class JSClassDecl(\n    name: Str,\n    fields: Ls[Str],\n    `extends`: Opt[JSExpr] = N,\n    methods: Ls[JSClassMemberDecl] = Nil,\n    implements: Ls[Str] = Nil,\n) extends JSStmt {\n  def toSourceCode: SourceCode = {\n    val constructor: SourceCode = {\n      val buffer = new ListBuffer[Str]()\n      buffer += \"  constructor(fields) {\"\n      if (`extends`.isDefined)\n        buffer += \"    super(fields);\"\n      implements.foreach { name =>\n        buffer += s\"    $name.implement(this);\"\n      }\n      fields.foreach { name =>\n        val innerName = if (JSField.isValidIdentifier(name)) s\".${name}\" else s\"[${JSLit.makeStringLiteral(name)}]\"\n        buffer += s\"    this$innerName = fields$innerName;\"\n      }\n      buffer += \"  }\"\n      SourceCode(buffer.toList)\n    }\n    val methodsSourceCode =\n      methods.foldLeft(SourceCode.empty) { case (x, y) =>\n        x + y.toSourceCode.indented\n      }\n    val epilogue = SourceCode(\"}\")\n    `extends` match {\n      case Some(base) =>\n        SourceCode(s\"class $name extends \") ++ base.toSourceCode ++\n          SourceCode(\" {\") + constructor + methodsSourceCode + epilogue\n      case None =>\n        if (fields.isEmpty && methods.isEmpty && implements.isEmpty) {\n          SourceCode(s\"class $name {}\")\n        } else {\n          SourceCode(\n            s\"class $name {\" :: Nil\n          ) + constructor + methodsSourceCode + epilogue\n        }\n    }\n  }\n\n  private val fieldsSet = collection.immutable.HashSet.from(fields)\n}\n\nfinal case class JSClassNewDecl(\n    name: Str,\n    fields: Ls[Str],\n    accessors: Ls[Bool -> Str], // mut -> name\n    privateMems: Ls[Str],\n    `extends`: Opt[JSExpr],\n    superFields: Ls[JSExpr],\n    ctorParams: Ls[Str],\n    rest: Opt[Str],\n    methods: Ls[JSClassMemberDecl],\n    implements: Ls[Str],\n    initStmts: Ls[JSStmt],\n    nestedTypes: Ls[Str],\n    ctorOverridden: Bool,\n    staticMethods: Ls[JSClassMemberDecl]\n) extends JSStmt {\n  def toSourceCode: SourceCode = {\n    val constructor: SourceCode = {\n      val buffer = new ListBuffer[Str]()\n      val params =\n        ctorParams.iterator.zipWithIndex.foldRight(rest match {\n          case Some(rest) => s\"...$rest\"\n          case _ => \"\"\n        })((p, s) =>\n        if (s.isEmpty) s\"${p._1}\"\n        else s\"${p._1}, $s\")\n      nestedTypes.foreach(t => buffer += s\"  #$t;\")\n      privateMems.distinct.foreach(f => {\n        buffer += s\"  #${f};\"\n      })\n      accessors.distinct.foreach { case (mut, f) =>\n        if (!privateMems.contains(f)) buffer += s\"  #${f};\"\n        buffer += s\"  get ${f}() { return this.#${f}; }\"\n        if (mut) buffer +=\n          s\"  set ${f}($$value) { return this.#${f} = $$value; }\"\n      }\n      buffer += s\"  constructor($params) {\"\n      if (`extends`.isDefined) {\n        val sf = superFields.iterator.zipWithIndex.foldLeft(\"\")((res, p) =>\n          if (p._2 === superFields.length - 1) s\"$res${p._1.toSourceCode}\"\n          else s\"$res${p._1.toSourceCode}, \"\n        )\n        buffer += s\"    super($sf);\"\n      }\n      implements.foreach { name =>\n        buffer += s\"    $name.implement(this);\"\n      }\n\n      // if the default constructor is overridden, we generate the overridden version\n      // otherwise, generate based on the class fields\n      if (!ctorOverridden) {\n        assert(fields.length === ctorParams.length, s\"fields and ctorParams have different size in class $name.\")\n        fields.lazyZip(ctorParams).foreach { (field, param) =>\n          buffer += s\"    this.#$field = $param;\" // TODO: invalid name?\n        }\n      }\n\n      initStmts.foreach { s =>\n        s.toSourceCode.indented.indented.toString.split(\"\\n\").foreach {\n          line => buffer += line\n        }\n      }\n      buffer += \"  }\"\n      SourceCode(buffer.toList)\n    }\n    val methodsSourceCode =\n      methods.foldLeft(SourceCode.empty) { case (x, y) =>\n        x + y.toSourceCode.indented\n      }\n    val staticMethodsSourceCode =\n      staticMethods.foldLeft(SourceCode.empty) { case (x, y) =>\n        x + SourceCode(\"static\") + y.toSourceCode.indented\n      }\n    val epilogue = SourceCode(\"}\")\n    `extends` match {\n      case Some(base) =>\n        SourceCode(s\"class $name extends \") ++ base.toSourceCode ++\n          SourceCode(\" {\") + constructor + methodsSourceCode + staticMethodsSourceCode + epilogue\n      case None =>\n        if (fields.isEmpty && methods.isEmpty && implements.isEmpty && accessors.isEmpty && initStmts.isEmpty && staticMethods.isEmpty) {\n          SourceCode(s\"class $name {}\")\n        } else {\n          SourceCode(\n            s\"class $name {\" :: Nil\n          ) + constructor + methodsSourceCode + staticMethodsSourceCode + epilogue\n        }\n    }\n  }\n\n  private val fieldsSet = collection.immutable.HashSet.from(fields)\n}\n\nfinal case class JSComment(text: Str) extends JSStmt {\n  def toSourceCode: SourceCode = SourceCode(s\"// $text\")\n}\n\nfinal case class JSParenthesis(exp: JSExpr) extends JSExpr {\n  implicit def precedence: Int = 0\n  def toSourceCode: SourceCode = exp.embed\n}\n\nobject JSCodeHelpers {\n  def id(name: Str): JSIdent = JSIdent(name)\n  def lit(value: Int): JSLit = JSLit(value.toString())\n  def const(name: Str, init: JSExpr): JSConstDecl = JSConstDecl(name, init)\n  def `return`(): JSReturnStmt = JSReturnStmt(N)\n  def `return`(expr: JSExpr): JSReturnStmt = expr.`return`\n  def `throw`(expr: JSExpr): JSThrowStmt = expr.`throw`\n  def forIn(pattern: JSNamePattern, iteratee: JSExpr)(stmts: JSStmt*): JSForInStmt\n    = JSForInStmt(pattern, iteratee, stmts.toList)\n  def fn(name: Str, params: JSPattern*)(stmts: JSStmt*): JSFuncDecl\n    = JSFuncDecl(name, params.toList, stmts.toList)\n  def param(name: Str): JSNamePattern = JSNamePattern(name)\n}"
  },
  {
    "path": "shared/src/main/scala/mlscript/codegen/Error.scala",
    "content": "package mlscript.codegen\n\nimport scala.collection.mutable.ArrayBuffer\n\nfinal case class CodeGenError(message: String) extends Exception(message)\n\nfinal case class UnimplementedError(symbol: StubValueSymbol)\n    extends Exception({\n      val names = new ArrayBuffer[String]()\n      var current: Option[StubValueSymbol] = Some(symbol)\n      while (\n        current match {\n          case Some(sym) =>\n            names += sym.lexicalName\n            current = sym.previous\n            true\n          case None => false\n        }\n      ) ()\n      val sep = \", \"\n      val concat = {\n        val joined = names.mkString(sep)\n        val pos = joined.lastIndexOf(sep)\n        if (pos > -1) {\n          joined.substring(0, pos) + \" and \" + joined.substring(pos + sep.length)\n        } else {\n          joined\n        }\n      }\n      val be = if (names.lengthIs > 1) \"are\" else \"is\"\n      s\"$concat $be not implemented\"\n    })\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/codegen/Polyfill.scala",
    "content": "package mlscript\n\nimport mlscript.utils._, shorthands._\nimport scala.collection.immutable.HashMap\nimport scala.collection.mutable.ArrayBuffer\n\nclass Polyfill {\n  private val featFnNameMap = collection.mutable.HashMap[Str, Str]()\n  private val emittedFeatSet = collection.mutable.HashSet[Str]()\n\n  def use(feat: Str, jsFnName: Str): Str = {\n    featFnNameMap += feat -> jsFnName\n    jsFnName\n  }\n\n  /**\n    * Check whether a feature has been already used.\n    */\n  def used(feat: Str): Bool = featFnNameMap.contains(feat)\n\n  def get(feat: Str): Opt[Str] = featFnNameMap get feat\n\n  def emit(): Ls[JSStmt] = (featFnNameMap flatMap { case (featName, fnName) =>\n    if (emittedFeatSet contains featName)\n      N\n    else\n      Polyfill.getFeature(featName) match {\n        case S(feature) =>\n          emittedFeatSet += featName\n          S(feature(fnName))\n        case N => N\n      }\n  }).toList\n}\n\nobject Polyfill {\n  def apply(): Polyfill = new Polyfill()\n\n  abstract class Feature {\n    val name: Str\n    def apply(name: Str): JSStmt\n  }\n\n  final case class BuiltinFunc(val name: Str, maker: Str => JSStmt) extends Feature {\n    def apply(name: Str): JSStmt = maker(name)\n  }\n\n  final case class RuntimeHelper(val name: Str, maker: Str => JSStmt) extends Feature {\n    def apply(name: Str): JSStmt = maker(name)\n  }\n\n  import JSCodeHelpers._\n\n  val features: Ls[Feature] = {\n    val buffer = new ArrayBuffer[Feature]()\n    buffer += RuntimeHelper(\n      \"prettyPrint\",\n      (name: Str) => {\n        val arg = JSIdent(\"value\")\n        JSFuncDecl(\n          name,\n          JSNamePattern(\"value\") :: Nil,\n          arg\n            .typeof()\n            .switch(\n              JSIdent(\"String\")(arg).`return` :: Nil,\n              JSExpr(\"number\") -> Nil,\n              JSExpr(\"boolean\") -> {\n                arg.member(\"toString\")().`return` :: Nil\n              },\n              // Returns `\"[Function: <name>]\"`\n              JSExpr(\"function\") -> {\n                val name = arg.member(\"name\") ?? JSExpr(\"<anonymous>\")\n                val repr = JSExpr(\"[Function: \") + name + JSExpr(\"]\")\n                (repr.`return` :: Nil)\n              },\n              JSExpr(\"string\") -> ((JSExpr(\"\\\"\") + arg + JSExpr(\"\\\"\")).`return` :: Nil),\n              JSExpr(\"undefined\") -> (JSExpr(\"undefined\").`return` :: Nil),\n              JSExpr(\"object\") -> (JSIfStmt(\n                arg :=== JSIdent(\"null\"),\n                JSExpr(\"null\").`return` :: Nil,\n                JSTryStmt(\n                  (arg.member(\"constructor\").member(\"name\") +\n                    JSExpr(\" \") +\n                    JSIdent(\"JSON\").member(\"stringify\")(arg, JSIdent(\"undefined\"), JSIdent(\"2\"))).`return` :: Nil,\n                  JSCatchClause(\n                    JSIdent(\"_\"),\n                    JSIdent(\"String\")(arg).`return` :: Nil,\n                  )\n                ) :: Nil,\n              ) :: Nil)\n            ) :: Nil,\n        )\n      }\n    )\n    buffer += RuntimeHelper(\n      \"withConstruct\",\n      (name: Str) => {\n        val obj = id(\"Object\")\n        val t = id(\"target\")\n        val f = id(\"fields\")\n        fn(name, param(\"target\"), param(\"fields\")) (\n          JSIfStmt(\n            (t.typeof() :=== JSExpr(\"string\")) :|| (t.typeof() :=== JSExpr(\"number\")) :||\n              (t.typeof() :=== JSExpr(\"boolean\")) :|| (t.typeof() :=== JSExpr(\"bigint\")) :||\n              (t.typeof() :=== JSExpr(\"symbol\")),\n            obj(\"assign\")(t, f).`return` :: Nil,\n          ),\n          JSIfStmt(\n            t.instanceOf(id(\"String\")) :|| t.instanceOf(id(\"Number\")) :||\n              t.instanceOf(id(\"Boolean\")) :|| t.instanceOf(id(\"BigInt\")),\n            obj(\"assign\")(t(\"valueOf\")(), t, f).`return` :: Nil,\n          ),\n          JSIfStmt(\n            id(\"Array\")(\"isArray\")(t),\n            Ls(\n              const(\"clone\", id(\"Array\")(\"from\")(t)),\n              forIn(param(\"key\"), t) {\n                id(\"clone\").prop(id(\"key\")) := t.prop(id(\"key\"))\n              },\n              forIn(param(\"key\"), f) {\n                id(\"clone\").prop(id(\"key\")) := f.prop(id(\"key\"))\n              },\n              `return`(id(\"clone\"))\n            )\n          ),\n          JSIfStmt(\n            // * \"Strict equality checks (===) should be used in favor of ==.\n            // *  The only exception is when checking for undefined and null by way of null.\"\n            // *  (http://contribute.jquery.org/style-guide/js/)\n            JSBinary(\"==\", t, JSLit(\"null\")),\n            `return`(obj(\"assign\")(JSRecord(Nil), JSRecord(Nil), f)) :: Nil,\n          ),\n          JSConstDecl(\"copy\", obj(\"assign\")(JSRecord(Nil), t, f)),\n          obj(\"setPrototypeOf\")(id(\"copy\"), obj(\"getPrototypeOf\")(t)).stmt,\n          id(\"copy\").`return`\n        )\n      }\n    )\n    buffer += BuiltinFunc(\n      \"toString\", fn(_, param(\"x\")) { `return` { id(\"String\")(id(\"x\")) } }\n    )\n    buffer += BuiltinFunc(\n      \"id\", fn(_, param(\"x\")) { `return`(id(\"x\")) }\n    )\n    buffer += BuiltinFunc(\n      \"emptyArray\", fn(_) { `return`(JSArray(Nil)) }\n    )\n    buffer += BuiltinFunc(\n      \"succ\", fn(_, param(\"x\")) { `return` { id(\"x\") + lit(1) } }\n    )\n    buffer += BuiltinFunc(\n      \"error\", fn(_) {\n        `throw`(JSNew(JSIdent(\"Error\"))(JSExpr(\"an error was thrown\")))\n      }\n    )\n    buffer += BuiltinFunc(\n      \"length\", fn(_, param(\"x\")) { `return` { id(\"x\").member(\"length\") } }\n    )\n    buffer += BuiltinFunc(\"concat\", makeBinaryFunc(\"+\"))\n    buffer += BuiltinFunc(\"join\",\n      fn(_, param(\"...xs\")) { `return` {\n        id(\"xs\")(\"join\").apply(JSLit(JSLit.makeStringLiteral(\"\"))) } })\n    buffer += BuiltinFunc(\"add\", makeBinaryFunc(\"+\"))\n    buffer += BuiltinFunc(\"sub\", makeBinaryFunc(\"-\"))\n    buffer += BuiltinFunc(\"mul\", makeBinaryFunc(\"*\"))\n    buffer += BuiltinFunc(\"numAdd\", makeBinaryFunc(\"+\"))\n    buffer += BuiltinFunc(\"numSub\", makeBinaryFunc(\"-\"))\n    buffer += BuiltinFunc(\"numMul\", makeBinaryFunc(\"*\"))\n    buffer += BuiltinFunc(\"div\", makeBinaryFunc(\"/\"))\n    buffer += BuiltinFunc(\"gt\", makeBinaryFunc(\">\"))\n    buffer += BuiltinFunc(\"not\", makeUnaryFunc(\"!\"))\n    buffer += BuiltinFunc(\"negate\", makeUnaryFunc(\"-\"))\n    buffer += BuiltinFunc(\"eq\", makeBinaryFunc(\"===\"))\n    buffer += BuiltinFunc(\"ne\", makeBinaryFunc(\"!==\"))\n    buffer += BuiltinFunc(\"sgt\", makeBinaryFunc(\">\"))\n    buffer += BuiltinFunc(\"slt\", makeBinaryFunc(\"<\"))\n    buffer += BuiltinFunc(\"sge\", makeBinaryFunc(\">=\"))\n    buffer += BuiltinFunc(\"sle\", makeBinaryFunc(\"<=\"))\n    buffer += BuiltinFunc(\"eq\", makeBinaryFunc(\"===\"))\n    buffer += BuiltinFunc(\"unit\", makeUnaryFunc(\"undefined\"))\n    buffer += BuiltinFunc(\n      \"log\", fn(_, param(\"x\")) { `return` { id(\"console.info\")(id(\"x\")) } }\n    )\n    buffer += BuiltinFunc(\n      \"discard\", fn(_, param(\"x\"))()\n    )\n    buffer.toList\n  }\n\n  private val nameFeatureMap = HashMap.from(features map { feature => (feature.name, feature) })\n\n  def getFeature(name: Str): Opt[Feature] = nameFeatureMap get name\n\n  def isPreludeFunction(name: Str): Bool = nameFeatureMap\n    .get(name)\n    .map({\n      case BuiltinFunc(_, _) => true\n      case _                 => false\n    })\n    .getOrElse(false)\n\n  private def makeBinaryFunc(op: Str)(name: Str): JSFuncDecl =\n    JSFuncDecl(\n      name,\n      JSNamePattern(\"x\") :: JSNamePattern(\"y\") :: Nil,\n      JSIfStmt(\n        JSIdent(\"arguments\").member(\"length\") :=== JSLit(\"2\"),\n        (JSIdent(\"x\").binary(op, JSIdent(\"y\"))).`return` :: Nil,\n        JSArrowFn(\n          JSNamePattern(\"y\") :: Nil,\n          L(JSIdent(\"x\").binary(op, JSIdent(\"y\")))\n        ).`return` :: Nil\n      ) :: Nil\n    )\n\n  private def makeUnaryFunc(op: Str)(name: Str): JSFuncDecl =\n    fn(name, param(\"x\")) { `return`(id(\"x\").unary(op)) }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/codegen/QQHelper.scala",
    "content": "package mlscript.codegen\n\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\n\n// * Pretty printer for quasiquotes.\n// * This is a temporary hack due to lack of runtime support and should be removed later.\nobject QQHelper {\n  val prettyPrinter: Str = \"\"\"\n  |(() => {\n  | const symbols = new Map();\n  | const printList = (lst, sep) => {\n  |   if (lst.length === 0) return \"\";\n  |   else {\n  |     const r = lst.reduce((x, y) => `${x}${y}${sep}`, \"\")\n  |     return r.substring(0, r.length - sep.length);\n  |   }\n  | }\n  | const indent = (s) => s.split(\"\\n\").map(ln => `  ${ln}`).join(\"\\n\")\n  | globalThis.freshName = (n) => {\n  |   if (!symbols.has(n)) { symbols.set(n, 0); }\n  |   const i = symbols.get(n);\n  |   symbols.set(n, i + 1);\n  |   return `${n}_${i}`;\n  | }\n  | globalThis.Const = (n) => `${n}`;\n  | globalThis.IntLit = (v) => `${v}`;\n  | globalThis.DecLit = (v) => `${v}`;\n  | globalThis.StrLit = (v) => `${v}`;\n  | globalThis.UnitLit = (v) => `${v}`;\n  | globalThis.Lam = (x, e) => `(${x}) =>\\n${indent(e)}`;\n  | globalThis.Var = (x) => `${x}`;\n  | globalThis.App = (f, ...xs) => {\n  | if (f === '+' || f === '-' || f === '*' || f === '/' || f === '==' || f === '<' || f === '>' || f === 'and' || f === 'or' || f === 'is')\n  |   return `(${printList(xs, ` ${f} `)})`;\n  | else\n  |   return `${f}${printList(xs, \", \")}`;\n  | }\n  | globalThis.Rcd = (...xs) => `{${printList(xs, \", \")}}`;\n  | globalThis.Bra = (x) => `(${x})`;\n  | globalThis.Sel = (x, y) => `${x}.${y}`;\n  | globalThis.Blk = (...s) => `{\\n${indent(printList(s, \";\\n\"))}\\n}`;\n  | globalThis.Tup = (...es) => `(${printList(es, \", \")})`;\n  | globalThis.Fld = (v) => `${v}`;\n  | globalThis.Let = (nme, v, bod) => `let ${nme} =\\n${indent(v)}\\n${indent(`in ${bod}`)}`;\n  | globalThis.Subs = (arr, idx) => `${arr}[${idx}]`;\n  | globalThis.With = (lhs, rhs) => `${lsh} with ${rhs}`;\n  | globalThis.Quoted = (body) => `code\"${body}\"`;\n  | globalThis.CaseOf = (trm, cse) => `match ${trm}:\\n  ${cse}`;\n  | globalThis.Case = (pat, bod, trm) => `case ${pat} => ${bod}\\n  ${trm})`;\n  | globalThis.Wildcard = (res) => `_ => ${res}`;\n  | globalThis.NoCases = () => `<NoCases>`;\n  | globalThis.run = (code) => {console.log(\"Quoted:\\n\" + code);}\n  |})();\n  \"\"\".stripMargin\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/codegen/Scope.scala",
    "content": "package mlscript.codegen\n\nimport mlscript.utils.shorthands._\nimport mlscript.{JSStmt, JSExpr, JSLetDecl}\nimport mlscript.Type\nimport scala.reflect.ClassTag\nimport mlscript.{TypeName, Top, Bot, TypeDef, Als, Trt, Cls, Mod, Mxn}\nimport mlscript.{MethodDef, Var}\nimport mlscript.{Term, Statement, Record}\nimport mlscript.utils.{AnyOps, lastWords}\nimport mlscript.JSField\nimport mlscript.{NuTypeDef, NuFunDef}\n\nclass Scope(val name: Str, enclosing: Opt[Scope]) {\n  private val lexicalTypeSymbols = scala.collection.mutable.HashMap[Str, TypeSymbol]()\n  private val lexicalValueSymbols = scala.collection.mutable.HashMap[Str, RuntimeSymbol]()\n  private val runtimeSymbols = scala.collection.mutable.HashSet[Str]()\n\n  // To allow a class method/getter/constructor to access members of an outer class,\n  // we insert `const qualifier = this;` before the class definition starts.\n  // To access ALL qualifier variables correctly, we need to make sure\n  // none of them would be shadowed.\n  private val qualifierSymbols = scala.collection.mutable.HashMap[Str, ValueSymbol]()\n\n  val tempVars: TemporaryVariableEmitter = TemporaryVariableEmitter()\n\n  /**\n    * Shorthands for creating top-level scopes.\n    */\n  def this(name: Str) = {\n    this(name, N)\n    // TODO: allow types and values to have the same name\n    // TODO: read built-in symbols from `Typer`.\n    Ls(\n      \"true\",\n      \"false\",\n      \"NaN\",\n      \"id\",\n      \"emptyArray\",\n      \"succ\",\n      \"error\",\n      \"length\",\n      \"concat\",\n      \"join\",\n      \"add\",\n      \"sub\",\n      \"mul\",\n      \"numAdd\",\n      \"numSub\",\n      \"numMul\",\n      \"div\",\n      \"gt\",\n      \"not\",\n      \"ne\",\n      \"eq\",\n      \"sgt\",\n      \"slt\",\n      \"sge\",\n      \"sle\",\n      \"typeof\",\n      \"toString\",\n      \"String\",\n      \"negate\",\n      \"eq\",\n      \"unit\",\n      \"log\",\n      \"run\",\n      \"Const\",\n      \"freshName\",\n      \"Lam\",\n      \"Var\",\n      \"App\",\n      \"IntLit\",\n      \"StrLit\",\n      \"DecLit\",\n      \"UnitLit\",\n      \"Rcd\",\n      \"Bra\",\n      \"Sel\",\n      \"Blk\",\n      \"Tup\",\n      \"Fld\",\n      \"Let\",\n      \"Subs\",\n      \"With\",\n      \"Quoted\",\n      \"CaseOf\",\n      \"Case\",\n      \"Wildcard\",\n      \"NoCases\",\n      \"discard\",\n      \"window\",\n    ) foreach { name =>\n      register(BuiltinSymbol(name, name))\n    }\n    // TODO: add `true`, `false`, and `error` to this list\n    register(TypeAliasSymbol(\"anything\", Nil, Top))\n    register(TypeAliasSymbol(\"nothing\", Nil, Bot))\n    // TODO: register them in the same way as `Typer` does.\n    Ls(\"int\", \"number\", \"bool\", \"string\", \"unit\") foreach { name =>\n      register(TypeAliasSymbol(name, Nil, TypeName(name)))\n    }\n\n    // TODO: eventually this should be properly registered along\n    // with all other built-in classes. For now, this just helps the\n    // unit tests relating to annotations pass.\n    val annType = TraitSymbol(\"Annotation\", \"Annotation\", Nil, Record(Nil), Nil)\n    register(annType)\n  }\n\n  private val allocateRuntimeNameIter = for {\n    i <- (1 to Int.MaxValue).iterator\n    c <- Scope.nameAlphabet.combinations(i)\n    name = c.mkString\n    if !hasRuntimeName(name)\n  } yield {\n    name\n  }\n\n  /**\n    * Check if a runtime name is used recursively.\n    *\n    * @param name the name\n    * @return whether it's available or not\n    */\n  private def hasRuntimeName(name: Str): Bool =\n    runtimeSymbols.contains(name) || enclosing.exists(_.hasRuntimeName(name))\n\n  /**\n    * Allocate a non-sense runtime name.\n    */\n  private def allocateRuntimeName(): Str = allocateRuntimeNameIter.next()\n\n  /**\n    * Allocate a runtime name starting with the given prefix.\n    */\n  private def allocateRuntimeName(prefix: Str): Str = {\n    // Fallback case.\n    if (prefix.isEmpty()) {\n      return allocateRuntimeName()\n    }\n    // Replace ticks\n    val realPrefix = Scope.replaceTicks(prefix)\n    // Try just prefix.\n    if (!runtimeSymbols.contains(realPrefix) && !Symbol.isKeyword(realPrefix)) {\n      return realPrefix\n    }\n    // Try prefix with an integer.\n    for (i <- 1 to Int.MaxValue) {\n      val name = s\"$realPrefix$i\"\n      if (!runtimeSymbols.contains(name)) {\n        return name\n      }\n    }\n    // Give up.\n    throw CodeGenError(\n      if (realPrefix.isEmpty())\n        \"Cannot allocate a runtime name\"\n      else\n        s\"Cannot allocate a runtime name starting with '$realPrefix'\"\n    )\n  }\n\n  private def register(symbol: TypeAliasSymbol): Unit = {\n    lexicalTypeSymbols.put(symbol.lexicalName, symbol)\n    ()\n  }\n\n  /**\n    * Register a lexical symbol in both runtime name set and lexical name set.\n    */\n  def register(symbol: TypeSymbol with RuntimeSymbol): Unit = {\n    lexicalTypeSymbols.put(symbol.lexicalName, symbol)\n    lexicalValueSymbols.put(symbol.lexicalName, symbol)\n    runtimeSymbols += symbol.runtimeName\n    ()\n  }\n\n  /**\n    * Register a lexical symbol in both runtime name set and lexical name set.\n    */\n  def register(symbol: RuntimeSymbol): Unit = {\n    lexicalValueSymbols.put(symbol.lexicalName, symbol)\n    runtimeSymbols += symbol.runtimeName\n    ()\n  }\n\n  private def unregister(symbol: ValueSymbol): Unit = {\n    lexicalTypeSymbols.remove(symbol.lexicalName)\n    runtimeSymbols.remove(symbol.runtimeName)\n    ()\n  }\n\n  def unregisterSymbol(symbol: ValueSymbol): Unit = {\n    unregister(symbol)\n  }\n\n  def getType(name: Str): Opt[TypeSymbol] = lexicalTypeSymbols.get(name)\n\n  /**\n   * Look up for a class symbol locally.\n   */\n  def getClassSymbol(name: Str): Opt[ClassSymbol] =\n    lexicalTypeSymbols.get(name) collect { case c: ClassSymbol => c }\n\n  /**\n   * Look up a trait symbol locally.\n   */\n  def getTraitSymbol(name: Str): Opt[TraitSymbol] = \n    lexicalTypeSymbols.get(name) collect { case c: TraitSymbol => c }\n\n  /**\n   * Look up a type alias symbol locally.\n   */\n  def getTypeAliasSymbol(name: Str): Opt[TypeAliasSymbol] =\n    lexicalTypeSymbols.get(name) collect { case c: TypeAliasSymbol => c }\n\n  /**\n   * Look up for a type symbol locally.\n   */\n  def getTypeSymbol(name: Str): Opt[TypeSymbol] = lexicalTypeSymbols.get(name)\n\n  def resolveValue(name: Str): Opt[RuntimeSymbol] =\n    lexicalValueSymbols.get(name).orElse(enclosing.flatMap(_.resolveValue(name)))\n\n  /**\n    * Find the base class for a specific class.\n    */\n  def resolveBaseClass(ty: Type): Opt[ClassSymbol] = {\n    val baseClasses = ty.collectTypeNames.flatMap { name =>\n      this.getType(name) match {\n        case S(sym: ClassSymbol) => S(sym)\n        case S(sym: TraitSymbol) => N\n        case S(sym: TypeAliasSymbol) =>\n          throw new CodeGenError(s\"cannot inherit from type alias $name\" )\n        case S(_: NuTypeSymbol) =>\n          throw new CodeGenError(s\"NuType symbol $name is not supported when resolving base classes\")\n        case N =>\n          throw new CodeGenError(s\"undeclared type name $name when resolving base classes\")\n      }\n    }\n    if (baseClasses.lengthIs > 1)\n      throw CodeGenError(\n        s\"cannot have ${baseClasses.length} base classes: \" +\n        baseClasses.map { _.lexicalName }.mkString(\", \")\n      )\n    else\n      baseClasses.headOption\n  }\n\n  def resolveImplementedTraits(ty: Type): Ls[TraitSymbol] = {\n    ty.collectTypeNames.flatMap { name =>\n      this.getType(name) match {\n        case S(sym: ClassSymbol) => N\n        case S(sym: TraitSymbol) => S(sym)\n        case S(sym: TypeAliasSymbol) =>\n          throw new CodeGenError(s\"cannot inherit from type alias $name\" )\n        case S(sym: NuTypeSymbol) =>\n          throw new CodeGenError(s\"NuType symbol $name is not supported when resolving implemented traits\")\n        case N =>\n          throw new CodeGenError(s\"undeclared type name $name when resolving implemented traits\")\n      }\n    }\n  }\n\n  def declareTypeSymbol(typeDef: TypeDef): TypeSymbol = typeDef match {\n    case TypeDef(Als, TypeName(name), tparams, body, _, _, _, _) =>\n      declareTypeAlias(name, tparams map { _.name }, body)\n    case TypeDef(Trt, TypeName(name), tparams, body, _, mthdDefs, _, _) =>\n      declareTrait(name, tparams map { _.name }, body, mthdDefs)\n    case TypeDef(Cls, TypeName(name), tparams, baseType, _, members, _, _) =>\n      declareClass(name, tparams map { _.name }, baseType, members)\n    case TypeDef(Mxn, _, _, _, _, _, _, _) =>\n      throw CodeGenError(\"Mixins are not supported yet.\")\n    case TypeDef(Mod, _, _, _, _, _, _, _) =>\n      throw CodeGenError(\"Modules are not supported yet.\")\n  }\n\n  def declareClass(\n      lexicalName: Str,\n      params: Ls[Str],\n      base: Type,\n      methods: Ls[MethodDef[Left[Term, Type]]]\n  ): ClassSymbol = {\n    val runtimeName = allocateRuntimeName(lexicalName)\n    val symbol = ClassSymbol(lexicalName, runtimeName, params.sorted, base, methods)\n    register(symbol)\n    symbol\n  }\n\n  // in DiffTests, we need to rename `TypingUnit` to some other names\n  // because we would not indicate different names manually\n  def declareTopModule(\n    lexicalName: Str,\n    stmts: Ls[Statement],\n    nuTypes: Ls[NuTypeDef],\n    allowRenaming: Bool\n  ): ModuleSymbol = {\n    val finalName =\n      if (allowRenaming) allocateRuntimeName(lexicalName) else lexicalName\n    val (mths, rest) = stmts.partitionMap {\n      case NuFunDef(isLetRec, Var(nme), _, tys, Left(rhs)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) =>\n        Left(MethodDef[Left[Term, Type]](isLetRec.getOrElse(false), TypeName(finalName), Var(nme), tys, Left(rhs)))\n      case s => Right(s)\n    }\n    val (signatures, ctor) = rest.partitionMap {\n      case NuFunDef(isLetRec, Var(nme), _, tys, Right(rhs)) if (isLetRec.isEmpty || isLetRec.getOrElse(false)) =>\n        Left(MethodDef[Right[Term, Type]](isLetRec.getOrElse(false), TypeName(finalName), Var(nme), tys, Right(rhs)))\n      case s => Right(s)\n    }\n    val symbol = ModuleSymbol(finalName, Nil, Record(Nil), mths, signatures, ctor, Nil, nuTypes, N)\n    register(symbol)\n    symbol\n  }\n\n  // We don't want `qualifier` symbols to be shadowed by each other\n  // Add all runtime names of `qualifier` symbols from the parent scope\n  private def pullOuterSymbols(syms: scala.collection.mutable.HashMap[Str, ValueSymbol]) = {\n    syms.foreach { s =>\n      runtimeSymbols += s._1\n      qualifierSymbols += s\n    }\n\n    this\n  }\n\n  def declareTrait(\n      lexicalName: Str,\n      params: Ls[Str],\n      base: Type,\n      methods: Ls[MethodDef[Left[Term, Type]]]\n  ): TraitSymbol = {\n    val runtimeName = allocateRuntimeName(lexicalName)\n    val symbol = TraitSymbol(lexicalName, runtimeName, params, base, methods)\n    register(symbol)\n    symbol\n  }\n\n  def declareTypeAlias(lexicalName: Str, params: Ls[Str], ty: Type): TypeAliasSymbol = {\n    val symbol = TypeAliasSymbol(lexicalName, params, ty)\n    register(symbol)\n    symbol\n  }\n  \n  def declareThisAlias(): ValueSymbol = {\n    val runtimeName = allocateRuntimeName(\"self\")\n    val symbol = ValueSymbol(\"this\", runtimeName, Some(false), false)\n    register(symbol)\n    symbol\n  }\n\n  def declareValue(\n      lexicalName: Str,\n      isByvalueRec: Option[Boolean],\n      isLam: Boolean,\n      symbolicName: Opt[Str],\n      /** Workaround for the first pass traversal with new definition typing. */\n      forNewDefsDryRun: Bool = false\n  ): ValueSymbol = {\n    val runtimeName = lexicalValueSymbols.get(lexicalName) match {\n      // If we are implementing a stub symbol and the stub symbol did not shadow any other\n      // symbols, it is safe to reuse its `runtimeName`.\n      case S(sym: StubValueSymbol) if !sym.shadowing   => sym.runtimeName\n      case S(sym: ValueSymbol) if sym.forNewDefsDryRun => sym.runtimeName\n      case S(sym: BuiltinSymbol) if !sym.accessed      => sym.runtimeName\n      case _                                           => allocateRuntimeName(lexicalName)\n    }\n    val symbol = ValueSymbol(lexicalName, runtimeName, isByvalueRec, isLam, forNewDefsDryRun)\n    register(symbol)\n    symbolicName.foreach { symbolicName =>\n      register(ValueSymbol(symbolicName, runtimeName, isByvalueRec, isLam, forNewDefsDryRun))\n    }\n    symbol\n  }\n\n  def declareQualifierSymbol(lexicalName: Str): Str = {\n    val symbol = ValueSymbol(\"this\", allocateRuntimeName(lexicalName), S(false), false)\n    qualifierSymbols += (symbol.runtimeName -> symbol)\n    register(symbol)\n    symbol.runtimeName\n  }\n  def resolveQualifier(runtimeName: Str): ValueSymbol =\n    qualifierSymbols.getOrElse(runtimeName, throw CodeGenError(s\"qualifier $runtimeName not found\"))\n\n  def declareStubValue(lexicalName: Str, symbolicName: Opt[Str])(implicit allowEscape: Bool): StubValueSymbol =\n    declareStubValue(lexicalName, N, symbolicName)\n\n  def declareStubValue(lexicalName: Str, previous: StubValueSymbol, symbolicName: Opt[Str])(implicit\n      allowEscape: Bool\n  ): StubValueSymbol =\n    declareStubValue(lexicalName, S(previous), symbolicName)\n\n  private def declareStubValue(lexicalName: Str, previous: Opt[StubValueSymbol], symbolicName: Opt[Str])(implicit\n      allowEscape: Bool\n  ): StubValueSymbol = {\n    val symbol = lexicalValueSymbols.get(lexicalName) match {\n      // If the existing symbol is a value symbol, but the value symbol is\n      // declared in the dry-run of new definition typing, we can reuse the\n      // runtime name.\n      case S(valueSymbol: ValueSymbol) if valueSymbol.forNewDefsDryRun =>\n        StubValueSymbol(lexicalName, valueSymbol.runtimeName, false, previous)\n      // If a stub with the same name has been defined, use the name.\n      case S(symbol) => StubValueSymbol(lexicalName, symbol.runtimeName, true, previous)\n      // Otherwise, we will allocate a new name.\n      case N =>\n        StubValueSymbol(lexicalName, allocateRuntimeName(lexicalName), false, previous)\n    }\n    register(symbol)\n    symbolicName.foreach { symbolicName =>\n      register(StubValueSymbol(symbolicName, symbol.runtimeName, false, previous))\n    }\n    symbol\n  }\n\n  def stubize(sym: ValueSymbol, previous: StubValueSymbol)(implicit\n      allowEscape: Bool\n  ): StubValueSymbol = {\n    unregister(sym)\n    declareStubValue(sym.lexicalName, S(previous), N)\n  }\n\n  def declareRuntimeSymbol(): Str = {\n    val name = allocateRuntimeName()\n    runtimeSymbols += name\n    name\n  }\n\n  def declareRuntimeSymbol(prefix: Str): Str = {\n    val name = allocateRuntimeName(prefix)\n    runtimeSymbols += name\n    name\n  }\n\n  /**\n    * This function declares a parameter in current scope and returns the \n    * symbol's runtime name.\n    *\n    * @param name\n    * @return\n    */\n  def declareParameter(name: Str): Str = {\n    val prefix =\n      if (JSField.isValidIdentifier(name)) name\n      else if (Symbol.isKeyword(name)) name + \"$\"\n      else Scope.replaceTicks(name)\n    val runtimeName = allocateRuntimeName(prefix)\n    register(ValueSymbol(name, runtimeName, Some(false), false))\n    runtimeName\n  }\n\n  def existsRuntimeSymbol(name: Str): Bool = runtimeSymbols.contains(name)\n\n  /**\n    * Shorthands for deriving normal scopes.\n    */\n  def derive(name: Str): Scope =\n    (new Scope(name, S(this))).pullOuterSymbols(qualifierSymbols)\n\n  \n  def refreshRes(): Unit = {\n    lexicalValueSymbols(\"res\") = ValueSymbol(\"res\", \"res\", Some(false), false)\n  }\n}\n\nobject Scope {\n\n  /**\n  * Shorthands for creating top-level scopes.\n  */\n  def apply(name: Str): Scope = new Scope(name)\n\n  private val nameAlphabet: Ls[Char] = Ls.from(\"abcdefghijklmnopqrstuvwxyz\")\n\n  private def replaceTicks(str: Str): Str = str.replace('\\'', '$')\n}\n\n/**\n  * This class collects temporary variables declared during translation and\n  * generates JavaScript declarations for them after the translation.\n  */\nfinal case class TemporaryVariableEmitter() {\n  private val names = scala.collection.mutable.HashSet[Str]()\n\n  /**\n    * Add a new variable name. The name must be a runtime name.\n    */\n  def +=(name: Str): Unit = names += name\n\n  /**\n    * Emit a `let`-declaration for collected names and clear the collection.\n    */\n  def emit(): Opt[JSLetDecl] = if (names.isEmpty) {\n    N\n  } else {\n    val decl = JSLetDecl.from(names.toList)\n    names.clear()\n    S(decl)\n  }\n\n  /**\n    * Get all names and clear the collection.\n    */\n  def get(): Ls[Str] = {\n    val vars = names.toList\n    names.clear()\n    vars\n  }\n\n  /**\n    * A helper method to prepend the declaration to given statements. This calls\n    * `emit` so the name collection will be cleared.\n    */\n  def `with`(stmts: Ls[JSStmt]): Ls[JSStmt] =\n    emit() match {\n      case S(decl) => decl :: stmts\n      case N       => stmts\n    }\n\n  /**\n    * A helper method to prepend temp variable declarations to given expression.\n    * If no temp variables, return the expression as `Left`. This calls `emit`\n    * so the name collection will be cleared.\n    */\n  def `with`(expr: JSExpr): JSExpr \\/ Ls[JSStmt] =\n    emit() match {\n      case S(decl) => R(decl :: expr.`return` :: Nil)\n      case N       => L(expr)\n    }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/codegen/Symbol.scala",
    "content": "package mlscript.codegen\n\nimport mlscript.utils.shorthands._\nimport mlscript.Type\nimport mlscript.JSClassDecl\nimport mlscript.MethodDef\nimport mlscript.{Term, Statement}\nimport mlscript.TypeName\nimport mlscript.NuTypeDef\n\nsealed trait LexicalSymbol {\n\n  /**\n    * The lexical name of the symbol. This is different from the runtime name,\n    * the name of the symbol in the generated code. We allow duplicates lexical\n    * names in the same scope.\n    */\n  def lexicalName: Str\n}\n\nsealed trait RuntimeSymbol extends LexicalSymbol {\n  def runtimeName: Str\n  var visited: Bool = false\n}\n\nsealed trait TypeSymbol extends LexicalSymbol {\n  val params: Ls[Str]\n  val body: Type\n}\n\nsealed trait NuTypeSymbol { sym: TypeSymbol =>\n  val name: Str\n  val methods: Ls[MethodDef[Left[Term, Type]]] // implemented methods\n  val signatures: Ls[MethodDef[Right[Term, Type]]] // methods signatures\n  val ctor: Ls[Statement] // statements in the constructor\n  val nested: Ls[NuTypeDef] // nested class/mixin/module\n  val qualifier: Opt[Str] // if it is inside another NuTypeSymbol, it indicates the runtime alias of parent's `this`\n  val superParameters: Ls[Term] // parameters that need to be passed to the `super()`\n  val isPlainJSClass: Bool // is this a plain class in JS\n  val ctorParams: Opt[Ls[(Str, Bool)]] // parameters in the constructor\n  val publicCtors: Ls[Str] // public(i.e., val-) parameters in the ctor\n  val matchingFields: Ls[Str] = sym.body.collectFields // matchable fields(i.e., fields in `class ClassName(...)`)\n  val unapplyMtd: Opt[MethodDef[Left[Term, Type]]] // unapply method\n\n  def isNested: Bool = qualifier.isDefined // is nested in another class/mixin/module\n}\n\nsealed class ValueSymbol(\n    val lexicalName: Str,\n    val runtimeName: Str,\n    val isByvalueRec: Option[Boolean],\n    val isLam: Boolean,\n    /**\n      * Workaround for the first pass traversal with new definition typing.\n      * \"Dry run\" here means that we haven't generated the code for the symbol\n      * yet in the new-definition-typing mode, so the symbol is just defined\n      * for the sake of code generation of classes/mixins/modules.\n      * \n      * This field should be deprecated after the `PreTyper` is done. See [PR\n      * #197](https://github.com/hkust-taco/mlscript/pull/197) for more details. \n      */\n    val forNewDefsDryRun: Boolean\n) extends RuntimeSymbol {\n  override def toString: Str = s\"value $lexicalName\"\n}\n\nobject ValueSymbol {\n  def apply(\n      lexicalName: Str,\n      runtimeName: Str,\n      isByvalueRec: Option[Boolean],\n      isLam: Boolean,\n      /** Workaround for the first pass traversal with new definition typing. */\n      forNewDefsDryRun: Boolean = false\n  ): ValueSymbol =\n    new ValueSymbol(lexicalName, runtimeName, isByvalueRec, isLam, forNewDefsDryRun)\n}\n\nsealed case class TypeAliasSymbol(\n    val lexicalName: Str,\n    val params: Ls[Str],\n    val body: Type\n) extends TypeSymbol\n    with LexicalSymbol {\n  override def toString: Str = s\"type $lexicalName\"\n}\n\nfinal case class BuiltinSymbol(val lexicalName: Str, feature: Str) extends RuntimeSymbol {\n  val runtimeName = lexicalName\n\n  override def toString: Str = s\"function $lexicalName\"\n\n  /**\n    * `true` if the built-in value had been accessed before.\n    * `Scope` will reuse the `lexicalName` if `accessed` is false.\n    */\n  var accessed: Bool = false\n}\n\nfinal case class StubValueSymbol(\n    override val lexicalName: Str,\n    override val runtimeName: Str,\n    /**\n      * Whether this stub is shadowing another symbol.\n      */\n    val shadowing: Bool,\n    previous: Opt[StubValueSymbol]\n)(implicit val accessible: Bool)\n    extends RuntimeSymbol {\n  override def toString: Str = s\"value $lexicalName\"\n}\n\nfinal case class ClassSymbol(\n    lexicalName: Str,\n    runtimeName: Str,\n    params: Ls[Str],\n    body: Type,\n    methods: Ls[MethodDef[Left[Term, Type]]],\n) extends TypeSymbol\n    with RuntimeSymbol with Ordered[ClassSymbol] {\n\n  import scala.math.Ordered.orderingToOrdered\n\n  override def compare(that: ClassSymbol): Int = lexicalName.compare(that.lexicalName)\n\n  override def toString: Str = s\"class $lexicalName ($runtimeName)\"\n}\n\nfinal case class NewClassMemberSymbol(\n  name: Str,\n  isByvalueRec: Option[Boolean],\n  isLam: Boolean,\n  isPrivate: Boolean,\n  qualifier: Option[Str]\n) extends RuntimeSymbol {\n  override def toString: Str = s\"new class member $name\"\n\n  // Class members should have fixed names determined by users\n  override def lexicalName: Str = name\n  override def runtimeName: Str = name\n}\n\nfinal case class NewClassSymbol(\n    name: Str,\n    params: Ls[Str],\n    ctorParams: Opt[Ls[(Str, Bool)]],\n    body: Type,\n    methods: Ls[MethodDef[Left[Term, Type]]],\n    unapplyMtd: Opt[MethodDef[Left[Term, Type]]],\n    signatures: Ls[MethodDef[Right[Term, Type]]],\n    ctor: Ls[Statement],\n    superParameters: Ls[Term],\n    publicCtors: Ls[Str],\n    nested: Ls[NuTypeDef],\n    qualifier: Opt[Str],\n    isPlainJSClass: Bool\n) extends TypeSymbol\n    with RuntimeSymbol with NuTypeSymbol {\n  override def toString: Str = s\"new class $name\"\n\n  // Classes should have fixed names determined by users\n  override def lexicalName: Str = name\n  override def runtimeName: Str = name\n}\n\nfinal case class MixinSymbol(\n    name: Str,\n    params: Ls[Str],\n    body: Type,\n    methods: Ls[MethodDef[Left[Term, Type]]],\n    signatures: Ls[MethodDef[Right[Term, Type]]],\n    ctor: Ls[Statement],\n    publicCtors: Ls[Str],\n    nested: Ls[NuTypeDef],\n    qualifier: Opt[Str]\n) extends TypeSymbol\n    with RuntimeSymbol with NuTypeSymbol {\n  override def toString: Str = s\"mixin $name\"\n\n  // Mixins should have fixed names determined by users\n  override def lexicalName: Str = name\n  override def runtimeName: Str = name\n\n  // Mixins should pass `...rest` to the `super()`\n  // But the variable name is not sure when we create the symbol object\n  override val superParameters: Ls[Term] = Nil\n  val isPlainJSClass: Bool = true\n  val ctorParams: Opt[Ls[(Str, Bool)]] = N\n  val unapplyMtd: Opt[MethodDef[Left[Term, Type]]] = N\n}\n\nfinal case class ModuleSymbol(\n    name: Str,\n    params: Ls[Str],\n    body: Type,\n    methods: Ls[MethodDef[Left[Term, Type]]],\n    signatures: Ls[MethodDef[Right[Term, Type]]],\n    ctor: Ls[Statement],\n    superParameters: Ls[Term],\n    nested: Ls[NuTypeDef],\n    qualifier: Opt[Str]\n) extends TypeSymbol\n    with RuntimeSymbol with NuTypeSymbol {\n  override def toString: Str = s\"module $name\"\n\n  // Modules should have fixed names determined by users\n  override def lexicalName: Str = name\n  override def runtimeName: Str = name\n  val isPlainJSClass: Bool = false\n  val ctorParams: Opt[Ls[(Str, Bool)]] = N\n  val publicCtors: Ls[Str] = Nil\n  val unapplyMtd: Opt[MethodDef[Left[Term, Type]]] = N\n}\n\nfinal case class TraitSymbol(\n    lexicalName: Str,\n    runtimeName: Str,\n    params: Ls[Str],\n    body: Type,\n    methods: Ls[MethodDef[Left[Term, Type]]],\n) extends TypeSymbol\n    with RuntimeSymbol {\n  override def toString: Str = s\"trait $lexicalName\"\n}\n\nobject Symbol {\n  def isKeyword(name: Str): Bool = keywords contains name\n\n  private val keywords: Set[Str] = Set(\n    // Reserved keywords as of ECMAScript 2015\n    \"break\",\n    \"case\",\n    \"catch\",\n    \"class\",\n    \"const\",\n    \"continue\",\n    \"debugger\",\n    \"default\",\n    \"delete\",\n    \"do\",\n    \"else\",\n    \"export\",\n    \"extends\",\n    \"finally\",\n    \"for\",\n    \"function\",\n    \"if\",\n    \"import\",\n    \"in\",\n    \"instanceof\",\n    \"new\",\n    \"return\",\n    \"super\",\n    \"switch\",\n    \"this\",\n    \"throw\",\n    \"try\",\n    \"typeof\",\n    \"var\",\n    \"void\",\n    \"while\",\n    \"with\",\n    \"yield\",\n    // The following are reserved as future keywords by the ECMAScript specification.\n    // They have no special functionality at present, but they might at some future time,\n    // so they cannot be used as identifiers. These are always reserved:\n    \"enum\",\n    // The following are only reserved when they are found in strict mode code:\n    \"abstract\",\n    \"boolean\",\n    \"byte\",\n    \"char\",\n    \"double\",\n    \"final\",\n    \"float\",\n    \"goto\",\n    \"int\",\n    \"long\",\n    \"native\",\n    \"short\",\n    \"synchronized\",\n    \"throws\",\n    \"transient\",\n    \"volatile\",\n  )\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/codegen/typescript/TsTypegen.scala",
    "content": "package mlscript\npackage codegen.typescript\n\nimport scala.collection.mutable.{ListBuffer, Map => MutMap, SortedMap => MutSortedMap}\nimport scala.collection.immutable.Set\n\nimport mlscript.codegen.CodeGenError\nimport mlscript.utils._, shorthands._\nimport mlscript.codegen._\n\n/** Typescript typegen code builder for an mlscript typing unit\n  */\nfinal class TsTypegenCodeBuilder {\n  private val typeScope: Scope = Scope(\"globalTypeScope\")\n  private val termScope: Scope = Scope(\"globalTermScope\")\n  private val typegenCode: ListBuffer[SourceCode] = ListBuffer.empty\n\n  /** Return complete typegen code for current typing unit\n    *\n    * @return\n    *   SourceCode\n    */\n  def toSourceCode(): SourceCode = {\n    SourceCode(\"// start ts\") +=: typegenCode\n    typegenCode += SourceCode(\"// end ts\")\n    SourceCode.bulkConcat(typegenCode)\n  }\n\n  /** Context for converting a statement or type definition\n    *\n    * @param typeVarMapping\n    *   mapping from type variables to their clash-free parameter names\n    * @param termScope\n    *   scope for argument names\n    * @param typeScope\n    *   scope for type parameter names\n    */\n  protected case class TypegenContext(\n      typeVarMapping: MutSortedMap[TypeVar, String],\n      termScope: Scope,\n      typeScope: Scope,\n  )\n\n  object TypegenContext {\n\n    def apply(mlType: Type): TypegenContext = {\n      val existingTypeVars = ShowCtx.mk(mlType :: Nil, false, \"\").vs\n      val typegenTypeScope = typeScope.derive(\"localTypeScope\")\n      val typegenTermScope = termScope.derive(\"localTermScope\")\n      val typeVarMapping = existingTypeVars.to(MutSortedMap)\n\n      // initialize local term scope with global term scope as parent\n      // this will reduce cases where global names are similar to function\n      // argument names. For e.g. the below case will be avoided\n      // export const arg0: int\n      // export const f: (arg0: int) => int\n      TypegenContext(typeVarMapping, typegenTermScope, typegenTypeScope)\n    }\n\n    // create a context with pre-created type var to name mapping\n    def apply(mlType: Type, typeVarMapping: MutSortedMap[TypeVar, String]): TypegenContext = {\n      val typegenTypeScope = typeScope.derive(\"localTypeScope\")\n      val typegenTermScope = termScope.derive(\"localTermScope\")\n      TypegenContext(typeVarMapping, typegenTermScope, typegenTypeScope)\n    }\n  }\n\n  def declareTypeDef(typeDef: TypeDef): TypeSymbol = typeScope.declareTypeSymbol(typeDef)\n\n  /**\n    * Start adding type definition and store partially translated\n    * type definition as state\n    *\n    * @param typeDef\n    */\n  def addTypeDef(typeDef: TypeDef, methods: List[(String, Type)]): Unit = {\n    val tySymb = typeScope.getTypeSymbol(typeDef.nme.name).getOrElse(\n      throw CodeGenError(s\"No type definition for ${typeDef.nme.name} exists\")\n    )\n    tySymb match {\n      case (classInfo: ClassSymbol) => addTypeGenClassDef(classInfo, methods)\n      case (aliasInfo: TypeAliasSymbol) => addTypeGenTypeAlias(aliasInfo)\n      case (traitInfo: TraitSymbol) => addTypegenTraitDef(traitInfo, methods)\n      case _ => ??? // TODO\n    }\n  }\n\n  /**\n    * Translate class method to typescript declaration\n    *\n    * @param declTypeParms type params from class or trait declaring the method\n    * @param methodName\n    * @param methodType\n    */\n  def addMethodDeclaration(declTypeParams: Set[String], methodName: String, methodType: Type): SourceCode = {\n    // unwrap method function type to remove implicit this\n    val methodSourceCode = methodType match {\n      case Function(lhs, rhs) => {\n        // Create a mapping from type var to their friendly name for lookup\n        val typegenCtx = TypegenContext(rhs)\n\n        rhs match {\n          case f@Function(lhs, rhs) =>\n            val lhsTypeSource = toTypegenFunctionLhs(lhs, true)(typegenCtx, Some(false))\n            val rhsTypeSource = toTsType(rhs)(typegenCtx, Some(true))\n\n            // only use free variables for type parameters\n            val typeParams = typegenCtx.typeVarMapping.iterator\n              .filter(tup => rhs.freeTypeVariables.contains(tup._1) &&\n                // ignore class type parameters since they are implicitly part of class scope\n                // if no name hint then the type variable is certainly not a class type parameter\n                // its friendly name has been generated\n                tup._1.nameHint.fold(true)(!declTypeParams.contains(_))\n              )\n              .map { case (_, varName) => SourceCode(varName)}\n              .toList\n            SourceCode(s\"    $methodName\") ++ SourceCode.paramList(typeParams) ++ lhsTypeSource ++ SourceCode.colon ++ rhsTypeSource\n          case _ =>\n            val tsType = toTsType(rhs)(typegenCtx, Some(true))\n            // only use free variables for type parameters\n            val typeParams = typegenCtx.typeVarMapping.iterator\n              .filter(tup => rhs.freeTypeVariables.contains(tup._1) &&\n                // ignore class type parameters since they are implicitly part of class scope\n                // if no name hint then the type variable is certainly not a class type parameter\n                // its friendly name has been generated\n                tup._1.nameHint.fold(true)(!declTypeParams.contains(_))\n              )\n              .map { case (_, varName) => SourceCode(varName)}\n              .toList\n            // known value methods are translated to readonly attributes of the class\n            if (typeParams.isEmpty) SourceCode(s\"    readonly $methodName\") ++ SourceCode.colon ++ tsType\n            // known value methods are not allowed to have type variables in ts\n            // else throw CodeGenError(s\"Cannot translate known value method named $methodName free type variables\")\n            else SourceCode(s\"    readonly $methodName\") ++ SourceCode.paramList(typeParams) ++ SourceCode.colon ++ tsType\n        }\n      }\n      // top level method type must be a function\n      case _ => throw CodeGenError(s\"Cannot translate malformed method: $methodName because it does not have top level function\")\n    }\n\n    methodSourceCode\n  }\n\n  def addTypegenTraitDef(traitInfo: TraitSymbol, methods: List[(String, Type)]): Unit = {\n    val traitName = traitInfo.lexicalName\n    val traitBody = traitInfo.body\n    val typeParams = traitInfo.params.iterator.map(SourceCode(_)).toList\n\n    // extend super traits\n    var traitDeclaration = SourceCode(s\"export interface $traitName\") ++ SourceCode.paramList(typeParams)\n    val superTraits = typeScope.resolveImplementedTraits(traitBody)\n    if (!superTraits.isEmpty) {\n      val superTraitsCode = superTraits.map { symb =>\n        val traitName = symb.lexicalName\n        val traitParams = symb.params.iterator.map(SourceCode(_)).toList\n        SourceCode(s\"$traitName\") ++ SourceCode.paramList(traitParams)\n      }\n      traitDeclaration ++= SourceCode(\" extends \") ++ SourceCode.sepBy(superTraitsCode)\n    }\n    traitDeclaration ++= SourceCode.space ++ SourceCode.openCurlyBrace\n\n    // add fields defined in the trait\n    traitBody.collectBodyFieldsAndTypes\n      .foreach{case (fieldVar, fieldType) => \n        val fieldCode = toTsType(fieldType)(TypegenContext(fieldType), Some(true))\n        traitDeclaration += SourceCode(\"    \") ++ SourceCode(fieldVar.name) ++ SourceCode.colon ++ fieldCode\n      }\n\n    // add methods\n    methods.foreach { case (name, methodType) =>\n      traitDeclaration += addMethodDeclaration(traitInfo.params.toSet, name, methodType)\n    }\n\n    typegenCode += traitDeclaration + SourceCode.closeCurlyBrace\n  }\n\n  def addTypeGenClassDef(classInfo: ClassSymbol, methods: List[(String, Type)]): Unit = {\n    val className = classInfo.lexicalName\n    val classBody = classInfo.body\n    val baseClass = typeScope.resolveBaseClass(classBody)\n    val typeParams = classInfo.params.iterator.map(SourceCode(_)).toList\n\n    // create mapping for class body fields and types\n    // class body includes fields from all implemented traits\n    val classFieldsAndType = getClassFieldAndTypes(classInfo)\n    // fields can be re-declared with different types at different\n    // levels of inheritance. The final type is a union of all these types\n      .groupMap(_._1)(_._2)\n\n    // extend with base class if it exists\n    var classDeclaration = SourceCode(s\"export declare class $className\") ++ SourceCode.paramList(typeParams)\n    baseClass.map(baseClass => {\n      val baseClassName = baseClass.lexicalName\n      val baseClassTypeParams = baseClass.params.iterator.map(SourceCode(_)).toList\n      classDeclaration ++= SourceCode(s\" extends ${baseClass.lexicalName}\") ++ SourceCode.paramList(baseClassTypeParams)\n    })\n    classDeclaration ++= SourceCode.space ++ SourceCode.openCurlyBrace\n\n    // add body fields\n    classFieldsAndType\n      .map { case (fieldVar, fieldTypes) => \n        val fieldTypesCode = toTypegenInheritedFields(fieldTypes)\n        (SourceCode(fieldVar.name), fieldTypesCode)\n      }\n      .foreachEntry { (fieldVar, fieldType) => {\n        classDeclaration += SourceCode(\"    \") ++ fieldVar ++ SourceCode.colon ++ fieldType\n      }}\n\n    // constructor needs all fields including super classes\n    val allFieldsAndTypes = (classFieldsAndType ++\n      baseClass.map(getClassFieldAndTypes(_, true)).getOrElse(List.empty).groupMap(_._1)(_._2))\n      .map {case (fieldVar, fieldTypes) =>\n        val fieldTypesCode = toTypegenInheritedFields(fieldTypes)\n        (SourceCode(fieldVar.name), fieldTypesCode)\n      }.toList\n    classDeclaration += SourceCode(\"    constructor(fields: \") ++\n      SourceCode.recordWithEntries(allFieldsAndTypes) ++ SourceCode(\")\")\n\n    // add methods\n    methods.foreach { case (name, methodType) =>\n      classDeclaration += addMethodDeclaration(classInfo.params.toSet, name, methodType)\n    }\n\n    typegenCode += classDeclaration + SourceCode.closeCurlyBrace\n  }\n\n  /**\n    * Convert the intersections of all distinct fields\n    * in the inheritance hierarchy of a trait or class\n    * into SourceCode\n    *\n    * @param fieldTypes\n    *   list of field types\n    * @return\n    *   SourceCode\n    */\n  private def toTypegenInheritedFields(fieldTypes: List[Type]): SourceCode = {\n    // field types will always have 1 or more elements\n    fieldTypes.distinct match {\n      case fieldType :: Nil => toTsType(fieldType)(TypegenContext(fieldType), Some(true))\n      case fieldTypes =>\n      // multiple types are intersected hence typegen is done\n      // using the precedence of the intersection operator.\n      // Only distinct types are considered for intersection\n      val fieldTypesCode = fieldTypes.distinct\n        .map(fieldType => toTsType(fieldType, false, 2)(TypegenContext(fieldType), Some(true)))\n      SourceCode.sepBy(fieldTypesCode, SourceCode.ampersand)\n    }\n  }\n\n  /**\n    * Type conversion for function arguments is a special case. Explicit tuples\n    * are handled differently from types that hide tuples.\n    * \n    * All parameters are same as `toTsType`\n    *\n    * @param lhs\n    * @param funcArg\n    * @param typePrecedence\n    * @param typegenCtx\n    * @param pol\n    * @return\n    */\n  private def toTypegenFunctionLhs(lhs: Type, funcArg: Boolean = false, typePrecedence: Int = 0)(implicit\n      typegenCtx: TypegenContext,\n      pol: Option[Boolean],\n  ): SourceCode = {\n    // flip polarity for input type of function\n    // lhs translates to the complete argument list\n    // method definition only affects source code representation of top level function\n    lhs match {\n      // tuple are handled specially because\n      // they create their own arg names\n      case Tuple(fields) => toTsType(lhs, true)(typegenCtx, Some(false))\n      // there are other types which might hide tuple arguments\n      // like recursive types, AppliedTypes or bounded types\n      // their tuple types can be uniformly converted\n      // using a spread operator\n      case _ =>\n        val arg = typegenCtx.termScope.declareRuntimeSymbol(\"arg\")\n        (SourceCode(s\"...$arg: \") ++ toTsType(lhs, true)(typegenCtx, Some(false))).parenthesized\n    }\n  }\n\n  /**\n    * List of pairs of field variables and their types for the trait including its super traits\n    *\n    * @param traitSymbol\n    * @return\n    */\n  private def getTraitFieldAndTypes(body: Type): List[Var -> Type] = {\n    val bodyFields = body.collectBodyFieldsAndTypes\n\n    typeScope\n      .resolveImplementedTraits(body)\n      .foldLeft(bodyFields){ case (fields, symb) =>\n        fields ::: getTraitFieldAndTypes(symb.body)\n      }\n  }\n\n  /**\n    * find all fields and types for class including all traits\n    * optionally include base class fields as well\n    *\n    * @param classSymbol\n    * @param includeBaseClass include base class fields if true, default is false\n    * @return\n    */\n  private def getClassFieldAndTypes(classSymbol: ClassSymbol, includeBaseClass: Boolean = false): List[Var -> Type] = {\n    val bodyFieldsAndTypes = classSymbol.body.collectBodyFieldsAndTypes ++\n      getTraitFieldAndTypes(classSymbol.body)\n\n    if (includeBaseClass) {\n      bodyFieldsAndTypes ++\n        typeScope.resolveBaseClass(classSymbol.body)\n          .map(getClassFieldAndTypes(_, true))\n          .getOrElse(List.empty)\n    } else {\n      bodyFieldsAndTypes\n    }\n  }\n\n  def addTypeGenTypeAlias(aliasInfo: TypeAliasSymbol): Unit = {\n    val aliasName = aliasInfo.lexicalName\n    val mlType = aliasInfo.body\n    // Create a mapping from type var to their friendly name for lookup\n    val typegenCtx = TypegenContext(mlType)\n    val tsType = toTsType(mlType)(typegenCtx, Some(true))\n    // only use non recursive type variables for type parameters\n    val typeParams = typegenCtx.typeVarMapping.iterator\n      .filter(tup => mlType.freeTypeVariables.contains(tup._1))\n      .map { case (_, varName) => SourceCode(varName)}\n      .toList\n\n    typegenCode += SourceCode(s\"export type $aliasName\") ++\n      SourceCode.paramList(typeParams) ++ SourceCode.equalSign ++ tsType\n  }\n\n  /** Converts a term definition to its typescript declaration including any adhoc type aliases created for it\n    *\n    * @param mlType\n    *   the type to be converted to source code\n    * @param termName\n    *   name of term that's been declared. If none is given default \"res\" is used to indicate type of value of result\n    *   from evaluating the term\n    * @return\n    */\n  def addTypeGenTermDefinition(mlType: Type, termName: Option[String]): Unit = {\n    // `res` definitions are allowed to be shadowed\n    val defName = termName.getOrElse(\"res\")\n\n    // Create a mapping from type var to their friendly name for lookup\n    val typegenCtx = TypegenContext(mlType)\n    val tsType = toTsType(mlType)(typegenCtx, Some(true))\n    // only use non recursive type variables for type parameters\n    val typeParams = typegenCtx.typeVarMapping.iterator\n      .filter(tup => mlType.freeTypeVariables.contains(tup._1))\n      .map { case (_, varName) => SourceCode(varName) }\n      .toList\n\n    typegenCode += (SourceCode(s\"export declare const $defName\") ++\n      SourceCode.paramList(typeParams) ++ SourceCode.colon ++ tsType)\n  }\n\n  /** Converts an mlscript type to source code representation of the ts type. It also keep tracks of extra type\n    * variables and type parameters defined through the context.\n    *\n    * polarity tracks polarity of the current type. * Some(true) - positive polarity * Some(false) - negative polarity *\n    * None - no polarity (invariant)\n    *\n    * @param mlType\n    *   mlscript type to convert\n    * @param funcArg\n    *   true if Tuple type is the lhs of a function. Used to translate tuples as multi-parameter functions\n    * @param typePrecedence\n    *   type precedence of an ml type when translating to ts. Decides where extra parenthesis gets placed\n    * @param typegenCtx\n    *   type generation context for allocating new names\n    * @param pol\n    *   polarity of type\n    * @return\n    */\n  private def toTsType(mlType: Type, funcArg: Boolean = false, typePrecedence: Int = 0)(implicit\n      typegenCtx: TypegenContext,\n      pol: Option[Boolean],\n  ): SourceCode = {\n    mlType match {\n      // these types do not mutate typegen context\n      case Union(TypeName(\"true\"), TypeName(\"false\")) | Union(TypeName(\"false\"), TypeName(\"true\")) =>\n        SourceCode(\"boolean\")\n      case u@Union(lhs, rhs) =>\n        val unionCode = SourceCode.sepBy(\n          List(toTsType(lhs, funcArg, this.typePrecedence(u)), toTsType(rhs, funcArg, this.typePrecedence(u))),\n          SourceCode.separator\n        )\n        // a union has lower precedence than an intersection\n        if (this.typePrecedence(u) < typePrecedence)\n          unionCode.parenthesized\n        else\n          unionCode\n      case i@Inter(lhs, rhs) =>\n        SourceCode.sepBy(\n          List(toTsType(lhs, funcArg, this.typePrecedence(i)), toTsType(rhs, funcArg, this.typePrecedence(i))),\n          SourceCode.ampersand\n        )\n      case Record(fields) =>\n        // ts can only handle fields that have only out type or the same in out types\n        fields.iterator.foreach { field =>\n          if (field._2.in.exists(in => in =/= field._2.out)) throw CodeGenError(\n            s\"Cannot convert mutable record field with different in out types to typescript (${\n              field})\")\n        }\n        SourceCode.recordWithEntries(\n          fields.map(entry => \n            if (entry._2.in.isDefined)\n              (SourceCode(entry._1.name), toTsType(entry._2.out))\n            else\n              (SourceCode(s\"readonly ${entry._1.name}\"), toTsType(entry._2.out))\n        ))\n      case Tuple(fields) =>\n        // ts can only handle fields that have only out type or the same in out types\n        fields.iterator.foreach { field =>\n          if (field._2.in.exists(in => in =/= field._2.out)) throw CodeGenError(\n            s\"Cannot convert mutable tuple field with different in out types to typescript (${\n              field})\")\n        }\n        // tuple that is a function argument becomes\n        // multi-parameter argument list\n        // ! Note: No equivalent to readonly fields for tuples\n        if (funcArg) {\n          val argList = fields\n            .map{ case field =>\n              val arg = typegenCtx.termScope.declareRuntimeSymbol(\"arg\")\n              val argType = toTsType(field._2.out)\n              SourceCode(s\"$arg: \") ++ argType\n            }\n          SourceCode.sepBy(argList).parenthesized\n        }\n        // regular tuple becomes fixed length array\n        else {\n          val tupleArrayCode = SourceCode.horizontalArray(fields.map(field => toTsType(field._2.out)))\n          // don't add a readonly if all fields in the tuple are mutable\n          // this is because readonly is a weak constraint and can easily\n          // be upcasted to non-readonly\n          if (fields.iterator.map(_._1.isDefined).forall(identity)) {\n            tupleArrayCode\n          } else {\n            SourceCode(\"readonly \") ++ tupleArrayCode\n          }\n        }\n      case Top            => SourceCode(\"unknown\")\n      case Bot            => SourceCode(\"never\")\n      case TypeName(name) => SourceCode(name)\n      case Literal(IntLit(n)) =>\n        SourceCode(n.toString + (if (JSBackend isSafeInteger n) \"\" else \"n\"))\n      case Literal(DecLit(n)) => SourceCode(n.toString)\n      case Literal(StrLit(s)) => SourceCode(JSLit.makeStringLiteral(s))\n      case Literal(UnitLit(b)) => SourceCode(if (b) \"undefined\" else \"null\")\n\n      // these types may mutate typegen context by argCounter, or\n      // by creating new type aliases\n      case f@Function(lhs, rhs) =>\n        // flip polarity for input type of function\n        // lhs translates to the complete argument list\n        // method definition only affects source code representation of top level function\n        val lhsTypeSource = toTypegenFunctionLhs(lhs, true)(typegenCtx, pol.map(!_))\n        val rhsTypeSource = toTsType(rhs)\n        val funcSourceCode = lhsTypeSource ++ SourceCode.fatArrow ++ rhsTypeSource\n        // if part of a higher precedence binary operator\n        // in this case only Inter and Union is possible\n        // parenthesize to maintain correct precedence\n        if (this.typePrecedence(f) < typePrecedence) {\n          funcSourceCode.parenthesized\n        } else {\n          funcSourceCode\n        }\n      // a recursive type is aliased as a self referencing type\n      case r@Recursive(uv, body) =>\n        // allocate the clash-free name for uv in typegen scope\n        // update mapping from type variables to\n        val uvName = typegenCtx.typeVarMapping\n          .getOrElse(uv,\n            throw CodeGenError(s\"Did not find mapping for type variable $uv. Unable to generated ts type.\")\n          )\n        val typeVarMapping = typegenCtx.typeVarMapping\n        // create new type gen context and recalculate rec var and\n        // non-rec var for current type\n        val nestedTypegenCtx = TypegenContext(mlType, typeVarMapping)\n\n        // recursive type does not have any other type variables\n        // (except itself)\n        if (mlType.freeTypeVariables.size === 0) {\n          typeScope.declareTypeAlias(uvName, List.empty, r)\n          val bodyType = toTsType(body)(typegenCtx, pol)\n          typegenCode += (SourceCode(s\"export type $uvName\") ++\n            SourceCode.equalSign ++ bodyType)\n          SourceCode(uvName)\n        }\n        // recursive type has other type variables\n        // so now it is an applied type\n        else {\n          val uvTypeParams = typeVarMapping.iterator\n            .filter(tup => mlType.freeTypeVariables.contains(tup._1) &&\n              // recursive type variable from outer scope have been converted\n              // to type aliases. They do not need to be part of type parameters.\n              // filter for type vars that are not declared as type aliases in type scope\n              typeVarMapping.get(tup._1).flatMap(varName => typeScope.getTypeAliasSymbol(varName)).isEmpty\n            )\n            .map(_._2)\n            .toList\n          // declare type alias to record that this type var has been aliased\n          typeScope.declareTypeAlias(uvName, uvTypeParams, body)\n          val uvAppliedName = SourceCode(uvName) ++ SourceCode.paramList(uvTypeParams.map(SourceCode(_)))\n          val bodyType = toTsType(body)(nestedTypegenCtx, pol)\n          typegenCode += (SourceCode(s\"export type $uvAppliedName\") ++\n            SourceCode.equalSign ++ bodyType)\n          uvAppliedName\n        }\n      case AppliedType(base, targs) =>\n        if (targs.length =/= 0) {\n          SourceCode(base.name) ++ SourceCode.openAngleBracket ++\n            SourceCode.sepBy(targs.map(toTsType(_)(typegenCtx, None))) ++ SourceCode.closeAngleBracket\n        } else {\n          // no type arguments required then print without brackets\n          SourceCode(base.name)\n        }\n      // Neg requires creating a parameterized type alias to hold the negated definition\n      case Neg(base) =>\n        // Negative type only works in positions of positive polarity\n        if (pol === Some(false)) {\n          throw CodeGenError(\n            s\"Cannot generate type for negated type at negative polarity for $mlType\"\n          )\n        }\n\n        // try to allocate common Negate type alias\n        if (!typeScope.existsRuntimeSymbol(\"Neg\")) {\n          typeScope.declareRuntimeSymbol(\"Neg\")\n          typegenCode += SourceCode(\"type Neg<NegatedType, FromType> = FromType extends NegatedType ? never: FromType\")\n        }\n\n        // introduce a new type parameter for the `FromType`\n        val typeParam = typegenCtx.typeScope.declareRuntimeSymbol()\n        typegenCtx.typeVarMapping += ((TypeVar(Right(typeParam), None), typeParam))\n\n        val baseType = toTsType(base)\n        SourceCode(s\"Neg<$baseType, $typeParam>\")\n      case Rem(base, names) =>\n        SourceCode(\"Omit\") ++\n          SourceCode.openAngleBracket ++ toTsType(base) ++ SourceCode.commaSpace ++\n          SourceCode.sepBy(names.map(name => SourceCode(s\"\\\"${name.name}\\\"\")), SourceCode.separator) ++\n          SourceCode.closeAngleBracket\n      case Bounds(lb, ub) if lb === ub => toTsType(lb)\n      case Bounds(lb, ub) =>\n        pol match {\n          // positive polarity takes upper bound\n          case Some(true) => toTsType(ub)\n          // negative polarity takes lower bound\n          case Some(false) => toTsType(lb)\n          case None =>\n            // TODO: Yet to handle invariant types\n            throw CodeGenError(s\"Cannot generate type for invariant type $mlType\")\n        }\n      case WithExtension(base, rcd) =>\n        toTsType(Inter(Rem(base, rcd.fields.map(tup => tup._1)), rcd))\n      // get clash free name for type variable\n      case t @ TypeVar(_, _) =>\n        val tvarName = typegenCtx.typeVarMapping.getOrElse(t,\n          throw CodeGenError(s\"Did not find mapping for type variable $t. Unable to generated ts type.\"))\n\n        // return type alias form if it exists\n        typeScope.getTypeAliasSymbol(tvarName).map { taliasInfo =>\n          SourceCode(taliasInfo.lexicalName) ++ SourceCode.paramList(taliasInfo.params.map(SourceCode(_)))\n        }.getOrElse(SourceCode(tvarName))\n      case Constrained(base, tvbs, where, _) =>\n        throw CodeGenError(s\"Cannot generate type for `where` clause $tvbs $where\")\n      case _: Splice | _: TypeTag | _: PolyType | _: Selection =>\n        throw CodeGenError(s\"Cannot yet generate type for: $mlType\")\n    }\n  }\n\n  /**\n    * Decides the precendence of the mltype when translating to typescript\n    *\n    * @param mlType\n    * @return\n    */\n  private def typePrecedence(mlType: Type): Int = mlType match {\n    case _: Inter => 2\n    case _: Union => 1\n    case _ => 0\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/helpers.scala",
    "content": "package mlscript\nimport scala.util.chaining._\nimport scala.collection.mutable.{Map => MutMap, SortedMap => SortedMutMap, Set => MutSet, Buffer}\nimport scala.collection.immutable.SortedMap\n\nimport math.Ordered.orderingToOrdered\n\nimport mlscript.utils._, shorthands._\nimport scala.annotation.tailrec\n\n\n// Auxiliary definitions for types\n\ntrait SignatureImpl extends Located { self: Signature =>\n  def children: List[Located] = members\n}\n\ntrait TypeLikeImpl extends Located { self: TypeLike =>\n  \n  def showDbg2: Str = show(newDefs = true) // TODO more lightweight debug printing routine\n  \n  def show(newDefs: Bool): Str = showIn(0)(ShowCtx.mk(this :: Nil, newDefs))\n  \n  private def parensIf(str: Str, cnd: Boolean): Str = if (cnd) \"(\" + str + \")\" else str\n  private def showField(f: Field)(implicit ctx: ShowCtx): Str = f match {\n    case Field(N, ub) => ub.showIn(0)\n    case Field(S(lb), ub) if lb === ub => ub.showIn(0)\n    case Field(S(Bot), ub) => s\"out ${ub.showIn(0)}\"\n    case Field(S(lb), Top) => s\"in ${lb.showIn(0)}\"\n    case Field(S(lb), ub) => s\"in ${lb.showIn(0)} out ${ub.showIn(0)}\"\n  }\n  private def showFields(fs: Ls[Opt[Var] -> Field])(implicit ctx: ShowCtx): Ls[Str] =\n    fs.map(nt => s\"${nt._2.mutStr}${nt._1.fold(\"\")(_.name + \": \")}${showField(nt._2)}\")\n  def showIn(outerPrec: Int)(implicit ctx: ShowCtx): Str = this match {\n  // TODO remove obsolete pretty-printing hacks\n    case Top => \"anything\"\n    case Bot => \"nothing\"\n    case TypeName(name) => name\n    // case uv: TypeVar => ctx.vs.getOrElse(uv, s\"[??? $uv ???]\")\n    case TypeTag(name) => \"#\"+name\n    case uv: TypeVar => ctx.vs(uv)\n    case Recursive(n, b) => parensIf(s\"${b.showIn(2)} as ${ctx.vs(n)}\", outerPrec > 1)\n    case WithExtension(b, r) => parensIf(s\"${b.showIn(2)} with ${r.showIn(0)}\", outerPrec > 1)\n    case Function(Tuple(fs), r) =>\n      val innerStr = fs match {\n        case Nil => \"()\"\n        case N -> Field(N, f) :: Nil if !f.isInstanceOf[Tuple] => f.showIn(31)\n        case _ =>\n          val inner = showFields(fs)\n          if (ctx.newDefs) inner.mkString(\"(\", \", \", \")\") else inner.mkString(\"(\", \", \", \",)\")\n      }\n      parensIf(innerStr + \" -> \" + r.showIn(30), outerPrec > 30)\n    case Function(l, r) if ctx.newDefs =>\n      parensIf(\"(...\" + l.showIn(0) + \") -> \" + r.showIn(30), outerPrec > 30)\n    case Function(l, r) => parensIf(l.showIn(31) + \" -> \" + r.showIn(30), outerPrec > 30)\n    case Neg(t) => s\"~${t.showIn(100)}\"\n    case Record(fs) =>\n      val strs = fs.map { nt =>\n        val nme = nt._1.name\n        if (nme.isCapitalized) nt._2 match {\n          case Field(N | S(Bot), Top) => s\"$nme\"\n          case Field(S(lb), ub) if lb === ub => s\"$nme = ${ub.showIn(0)}\"\n          case Field(N | S(Bot), ub) => s\"$nme <: ${ub.showIn(0)}\"\n          case Field(S(lb), Top) => s\"$nme :> ${lb.showIn(0)}\"\n          case Field(S(lb), ub) => s\"$nme :> ${lb.showIn(0)} <: ${ub.showIn(0)}\"\n        }\n        else s\"${nt._2.mutStr}${nme}: ${showField(nt._2)}\"\n      }\n      if (strs.foldLeft(0)(_ + _.length) > 80)\n        strs.mkString(\"{\\n\" + ctx.indStr, \",\\n\" + ctx.indStr, \"\")\n          .indentNewLines(ShowCtx.indentation) + \"\\n\" + ctx.indStr + \"}\"\n      else strs.mkString(\"{\", \", \", \"}\")\n    case Splice(fs) =>\n      val inner = fs.map{case L(l) => s\"...${l.showIn(0)}\" case R(r) => s\"${showField(r)}\"}\n      if (ctx.newDefs) inner.mkString(\"[\", \", \", \"]\") else inner.mkString(\"(\", \", \", \")\")\n    case Tuple(fs) =>\n      val inner = showFields(fs)(ctx)\n      if (ctx.newDefs) inner.mkString(\"[\", \", \", \"]\")\n      else inner.mkString(\"(\", \", \", if (fs.nonEmpty) \",)\" else \")\")\n    case Union(TypeName(\"true\"), TypeName(\"false\")) | Union(TypeName(\"false\"), TypeName(\"true\")) =>\n      TypeName(\"bool\").showIn(0)\n    // case Union(l, r) => parensIf(l.showIn(ctx, 20) + \" | \" + r.showIn(ctx, 20), outerPrec > 20)\n    // case Inter(l, r) => parensIf(l.showIn(ctx, 25) + \" & \" + r.showIn(ctx, 25), outerPrec > 25)\n    case c: Composed =>\n      val prec = if (c.pol) 20 else 25\n      val opStr = if (c.pol) \" | \" else \" & \"\n      c.distinctComponents match {\n        case Nil => (if (c.pol) Bot else Top).showIn(outerPrec)\n        case x :: Nil => x.showIn(outerPrec)\n        case _ =>\n          parensIf(c.distinctComponents.iterator\n            .map(_.showIn(prec))\n            .reduce(_ + opStr + _), outerPrec > prec)\n      }\n    // \n    case Bounds(Bot, Top) => s\"?\"\n    case Bounds(lb, ub) if lb === ub => lb.showIn(outerPrec)\n    case Bounds(Bot, ub) => s\"out ${ub.showIn(0)}\"\n    case Bounds(lb, Top) => s\"in ${lb.showIn(0)}\"\n    case Bounds(lb, ub) => s\"in ${lb.showIn(0)} out ${ub.showIn(0)}\"\n    // \n    case AppliedType(n, args) =>\n      s\"${n.name}${args.map(_.showIn(0)).mkString(ctx.<, \", \", ctx.>)}\"\n    case Selection(b, n) => b.showIn(100) + \".\" + n.name\n    case Rem(b, ns) => s\"${b.showIn(90)}${ns.map(\"\\\\\"+_.name).mkString}\"\n    case Literal(IntLit(n)) => n.toString\n    case Literal(DecLit(n)) => n.toString\n    case Literal(StrLit(s)) => \"\\\"\" + s + \"\\\"\"\n    case Literal(UnitLit(b)) =>\n      if (b) if (ctx.newDefs) \"()\" else \"undefined\" else \"null\"\n    case PolyType(Nil, body) => body.showIn(outerPrec)\n    case PolyType(targs, body) => parensIf(\n        s\"${targs.iterator.map(_.fold(_.name, _.showIn(0)))\n          .mkString(\"forall \", \" \", \".\")} ${body.showIn(0)}\",\n        outerPrec > 1 // or 0?\n      )\n    case Constrained(b, bs, ws, tscs) =>\n      val oldCtx = ctx\n      val bStr = b.showIn(0).stripSuffix(\"\\n\")\n      val multiline = bStr.contains('\\n')\n      parensIf({\n        implicit val ctx: ShowCtx = if (multiline) oldCtx.indent else oldCtx.indent.indent\n        s\"${\n          bStr\n        }\\n${oldCtx.indStr}${if (multiline) \"\" else \"  \"}where${\n              bs.map {\n          case (uv, Bounds(Bot, ub)) =>\n            s\"\\n${ctx.indStr}${ctx.vs(uv)} <: ${ub.showIn(0)}\"\n          case (uv, Bounds(lb, Top)) =>\n            s\"\\n${ctx.indStr}${ctx.vs(uv)} :> ${lb.showIn(0)}\"\n          case (uv, Bounds(lb, ub)) if lb === ub =>\n            s\"\\n${ctx.indStr}${ctx.vs(uv)} := ${lb.showIn(0)}\"\n          case (uv, Bounds(lb, ub)) =>\n            val vstr = ctx.vs(uv)\n            s\"\\n${ctx.indStr}${vstr             } :> ${lb.showIn(0)}\" +\n            s\"\\n${ctx.indStr}${\" \" * vstr.length} <: ${ub.showIn(0)}\"\n        }.mkString\n      }${ws.map{\n          case Bounds(lo, hi) => s\"\\n${ctx.indStr}${lo.showIn(0)} <: ${hi.showIn(0)}\" // TODO print differently from bs?\n        }.mkString\n      }${tscs.map{\n          case (tvs, constrs) =>\n            val s = tvs.map(u => (if (u._1) \"+\" else \"-\") ++ u._2.showIn(0))\n              .mkString(\"[\", \", \", \"]\")\n            s\"\\n${ctx.indStr}\" + s +\n            s\" in ${constrs.map(_.map(_.showIn(0)).mkString(\"[\", \", \", \"]\")).mkString(\"{\", \", \", \"}\")}\"\n        }.mkString}\"\n      }, outerPrec > 0)\n    case fd @ NuFunDef(isLetRec, nme, snme, targs, rhs) =>\n      s\"${if (fd.isMut) \"mut \" else \"\"}${isLetRec match {\n        case S(false) => if (fd.genField) \"val\" else \"let\"\n        case S(true) => if (fd.genField) die else \"let rec\"\n        case N => \"fun\"\n      }}${snme.fold(\"\")(\" (\" + _.name + \")\")\n      } ${nme.name}${targs.map(_.showIn(0)).mkStringOr(\", \", \"[\", \"]\")}${rhs match {\n        case L(trm) => \" = ...\"\n        case R(ty) => \": \" + ty.showIn(0)\n      }}\"\n    case Signature(decls, res) =>\n      (decls.map(ctx.indStr + _.showIn(0) + \"\\n\") ::: (res match {\n        case S(ty) => ctx.indStr + ty.showIn(0) + \"\\n\" :: Nil\n        case N => Nil\n      })).mkString\n    case NuTypeDef(kind @ Als, nme, tparams, params, ctor, sig, parents, sup, ths, body) =>\n      assert(params.isEmpty, params)\n      assert(ctor.isEmpty, ctor)\n      assert(parents.isEmpty, parents)\n      assert(sup.isEmpty, sup)\n      assert(ths.isEmpty, ths)\n      assert(body.entities.isEmpty, body)\n      s\"type ${nme.name}${tparams.map(_._2.showIn(0)).mkStringOr(\", \", \"[\", \"]\")} = ${\n        sig.getOrElse(die).showIn(0)}\"\n    case td @ NuTypeDef(kind, nme, tparams, params, ctor, sig, parents, sup, ths, body) =>\n      val bodyCtx = ctx.indent\n      s\"${td.declareLoc.fold(\"\")(_ => \"declare \")}${td.abstractLoc.fold(\"\")(_ => \"abstract \")}${kind.str} ${\n        nme.name}${tparams.map(_._2.showIn(0)).mkStringOr(\", \", \"[\", \"]\")}${params match {\n        case S(Tup(fields)) => s\"(${fields.map {\n          case (N, Fld(_, Asc(v: Var, ty))) => v.name + \": \" + ty.showIn(0)\n          case (N | S(_), _) => lastWords(\"ill-formed type definition parameter\")\n        }.mkString(\", \")})\"\n        case _ => \"\"\n      }}${sig.fold(\"\")(\": \" + _.showIn(0)(bodyCtx))}${parents match {\n        case Nil => \"\"\n        case ps => \" extends \" + ps.iterator.map(_.print(false)).mkString(\", \") // TODO pp parent terms...\n      }}${if (body.entities.isEmpty && sup.isEmpty && ths.isEmpty) \"\" else\n        \" {\\n\" + sup.fold(\"\")(s\"${bodyCtx.indStr}super: \" + _.showIn(0)(bodyCtx) + \"\\n\") +\n        ths.fold(\"\")(s\"${bodyCtx.indStr}this: \" + _.showIn(0)(bodyCtx) + \"\\n\") +\n          body.entities.collect {\n            case Constructor(params, body) => s\"${bodyCtx.indStr}constructor(${params.fields.map {\n              case N -> Fld(FldFlags.empty, Asc(Var(nme), ty)) => \n                s\"${nme}: ${ty.showIn(0)(bodyCtx)}\"\n              case _ => lastWords(\"ill-formed constructor parameter\")\n            }.mkString(\", \")})\\n\"\n          }.mkString +\n          Signature(body.entities.collect { case d: NuDecl => d }, N).showIn(0)(bodyCtx) +\n            ctx.indStr + \"}\"\n      }\"\n  }\n  \n  def childrenTypes: List[TypeLike] = this match {\n    case _: NullaryType => Nil\n    case Function(l, r) => l :: r :: Nil\n    case Bounds(l, r) => l :: r :: Nil\n    case Neg(b) => b :: Nil\n    case Record(fs) => fs.flatMap(f => f._2.in.toList ++ (f._2.out :: Nil))\n    case Tuple(fs) => fs.flatMap(f => f._2.in ++ (f._2.out :: Nil))\n    case Union(l, r) => l :: r :: Nil.toList\n    case Inter(l, r) => l :: r :: Nil\n    case Recursive(n, b) => b :: Nil\n    case AppliedType(n, ts) => ts\n    case Selection(b, nme) => b :: nme :: Nil\n    case Rem(b, _) => b :: Nil\n    case WithExtension(b, r) => b :: r :: Nil\n    case PolyType(targs, body) => targs.map(_.fold(identity, identity)) :+ body\n    case Splice(fs) => fs.flatMap{ case L(l) => l :: Nil case R(r) => r.in.toList ++ (r.out :: Nil) }\n    case Constrained(b, bs, ws, tscs) => b :: bs.flatMap(c => c._1 :: c._2 :: Nil) ::: ws.flatMap(c => c.lb :: c.ub :: Nil) ::: tscs.flatMap(tsc => tsc._1.map(_._2) ::: tsc._2.flatten)\n    case Signature(xs, res) => xs ::: res.toList\n    case NuFunDef(isLetRec, nme, snme, targs, rhs) => targs ::: rhs.toOption.toList\n    case NuTypeDef(kind, nme, tparams, params, ctor, sig, parents, sup, ths, body) =>\n      // TODO improve this mess\n      tparams.map(_._2) ::: params.getOrElse(Tup(Nil)).fields.collect {\n        case (_, Fld(_, Asc(_, ty))) => ty\n      } ::: sig.toList ::: sup.toList ::: ths.toList ::: Signature(body.entities.collect {\n        case d: NuDecl => d\n      }, N) :: Nil // TODO parents?\n  }\n  \n  lazy val typeVarsList: List[TypeVar] = this match {\n    case uv: TypeVar => uv :: Nil\n    case Recursive(n, b) => n :: b.typeVarsList\n    case _ => childrenTypes.flatMap(_.typeVarsList)\n  }\n  \n  /**\n    * @return\n    *  set of free type variables in type\n    */\n  lazy val freeTypeVariables: Set[TypeVar] = this match {\n    case Recursive(uv, body) => body.freeTypeVariables - uv\n    case t: TypeVar => Set.single(t)\n    case _ => childrenTypes.foldRight(Set.empty[TypeVar])((ty, acc) => ty.freeTypeVariables ++ acc)\n  }\n  \n}\n\ntrait TypeImpl extends Located { self: Type =>\n  \n  def children: List[Located] = childrenTypes\n  \n  /**\n    * Collect fields recursively during code generation.\n    * Note that the type checker will reject illegal cases.\n    */\n  lazy val collectFields: Ls[Str] = this match {\n    case Record(fields) => fields.map(_._1.name)\n    case Inter(ty1, ty2) => ty1.collectFields ++ ty2.collectFields\n    case _: Union | _: Function | _: Tuple | _: Recursive\n        | _: Neg | _: Rem | _: Bounds | _: WithExtension | Top | Bot\n        | _: Literal | _: TypeVar | _: AppliedType | _: TypeName \n        | _: Constrained | _ : Splice | _: TypeTag | _: PolyType | _: Selection =>\n      Nil\n  }\n\n  /**\n    * Collect `TypeName`s recursively during code generation.\n    * Note that the type checker will reject illegal cases.\n    */\n  lazy val collectTypeNames: Ls[Str] = this match {\n    case TypeName(name) => name :: Nil\n    case AppliedType(TypeName(name), _) => name :: Nil\n    case Inter(lhs, rhs) => lhs.collectTypeNames ++ rhs.collectTypeNames\n    case _: Union | _: Function | _: Record | _: Tuple | _: Recursive\n        | _: Neg | _: Rem | _: Bounds | _: WithExtension | Top | Bot | _: PolyType\n        | _: Literal | _: TypeVar | _: Constrained | _ : Splice | _: TypeTag\n        | _: Selection =>\n      Nil\n  }\n\n  // Collect fields and types of record types that are intersected\n  // by traversing the first level of intersection. This is used\n  // for finding the fields and types of a class body, since the\n  // body is made of up an intersection of classes and records\n  lazy val collectBodyFieldsAndTypes: List[Var -> Type] = this match {\n    case Record(fields) => fields.map(field => (field._1, field._2.out))\n    case Inter(ty1, ty2) => ty1.collectBodyFieldsAndTypes ++ ty2.collectBodyFieldsAndTypes\n    case _: Union | _: Function | _: Tuple | _: Recursive\n        | _: Neg | _: Rem | _: Bounds | _: WithExtension | Top | Bot | _: PolyType\n        | _: Literal | _: TypeVar | _: AppliedType | _: TypeName | _: Constrained | _ : Splice | _: TypeTag\n        | _: Selection =>\n      Nil\n  }\n}\n\n\nfinal case class ShowCtx(\n    vs: SortedMap[TypeVar, Str],\n    debug: Bool, // TODO make use of `debug` or rm\n    indentLevel: Int,\n    newDefs: Bool,\n    angletards: Bool = false,\n  )\n{\n  lazy val indStr: Str = ShowCtx.indentation * indentLevel\n  def lnIndStr: Str = \"\\n\" + indStr\n  def indent: ShowCtx = copy(indentLevel = indentLevel + 1)\n  def < : Str = if (angletards) \"<\" else \"[\"\n  def > : Str = if (angletards) \">\" else \"]\"\n}\nobject ShowCtx {\n  def indentation: Str = \"  \"\n  /**\n    * Create a context from a list of types. For named variables and\n    * hinted variables use what is given. For unnamed variables generate\n    * completely new names. If same name exists increment counter suffix\n    * in the name.\n    */\n  def mk(tys: IterableOnce[TypeLike], newDefs: Bool, _pre: Str = \"'\", debug: Bool = false): ShowCtx = {\n    val (otherVars, namedVars) = tys.iterator.toList.flatMap(_.typeVarsList).distinct.partitionMap { tv =>\n      tv.identifier match { case L(_) => L(tv.nameHint -> tv); case R(nh) => R(nh -> tv) }\n    }\n    val (hintedVars, unnamedVars) = otherVars.partitionMap {\n      case (S(nh), tv) => L(nh -> tv)\n      case (N, tv) => R(tv)\n    }\n    val usedNames = MutMap.empty[Str, Int]\n    def assignName(n: Str): Str = {\n      val pre = if (n.startsWith(\"'\") || n.startsWith(ExtrusionPrefix)) \"\" else _pre\n      usedNames.get(n) match {\n        case S(cnt) =>\n          usedNames(n) = cnt + 1\n          pre + \n          n + cnt\n        case N =>\n          usedNames(n) = 0\n          pre + \n          n\n      }\n    }\n    val namedMap = (namedVars ++ hintedVars).map { case (nh, tv) =>\n      // tv -> assignName(nh.dropWhile(_ === '\\''))\n      tv -> assignName(nh.stripPrefix(_pre))\n    }.toSortedMap\n    val used = usedNames.keySet\n    \n    // * Generate names for unnamed variables\n    val numLetters = 'z' - 'a' + 1\n    val names = Iterator.unfold(0) { idx =>\n      val postfix = idx/numLetters\n      S(('a' + idx % numLetters).toChar.toString + (if (postfix === 0) \"\" else postfix.toString), idx + 1)\n    }.filterNot(used).map(assignName)\n    \n    ShowCtx(namedMap ++ unnamedVars.zip(names), debug, indentLevel = 0, newDefs)\n  }\n}\n\ntrait PolyTypeImpl  { self: PolyType => }\n\ntrait ComposedImpl { self: Composed =>\n  val lhs: Type\n  val rhs: Type\n  def components: Ls[Type] = (lhs match {\n    case c: Composed if c.pol === pol => c.components\n    case _ => lhs :: Nil\n  }) ::: (rhs match {\n    case c: Composed if c.pol === pol => c.components\n    case _ => rhs :: Nil\n  })\n  lazy val distinctComponents =\n    components.filterNot(c => if (pol) c === Bot else c === Top).distinct\n}\n\ntrait TypeVarImpl extends Ordered[TypeVar] { self: TypeVar =>\n  def name: Opt[Str] = identifier.toOption.orElse(nameHint)\n  def compare(that: TypeVar): Int = {\n    (this.identifier.fold((_, \"\"), (0, _))) compare (that.identifier.fold((_, \"\"), (0, _)))\n  }\n}\n\n// Auxiliary definitions for terms\n\ntrait PgrmImpl { self: Pgrm =>\n  lazy val desugared: (Ls[Diagnostic] -> (Ls[TypeDef], Ls[Terms])) = {\n    val diags = Buffer.empty[Diagnostic]\n    val res = tops.flatMap { s =>\n        val (ds, d) = s.desugared\n        diags ++= ds\n        d\n    }.partitionMap {\n      case td: TypeDef => L(td)\n      case ot: Terms => R(ot)\n      case NuFunDef(isLetRec, nme, _, tys, rhs) =>\n        R(Def(isLetRec.getOrElse(true), nme, rhs, isLetRec.isEmpty))\n      case _: Constructor => die\n   }\n    diags.toList -> res\n  }\n\n  def showDbg: Str = tops.iterator.map(\"\" + _.showDbg + \";\").mkString(\" \")\n}\n\nobject OpApp {\n  def apply(op: Str, trm: Term): Term = App(Var(op), trm)\n  def unapply(trm: Term): Opt[Term -> Term] = trm |>? {\n    case App(op, lhs)\n      if op.toLoc.exists(l => lhs.toLoc.exists(l.spanStart > _.spanStart))\n      => (op, lhs)\n  }\n}\n\ntrait DeclImpl extends Located { self: Decl =>\n  val body: Located\n  def showBody: Str = this match {\n    case d: Def => d.rhs.fold(_.showDbg, _.showDbg2)\n    case td: TypeDef => td.body.showDbg2\n  }\n  def describe: Str = this match {\n    case _: Def => \"definition\"\n    case _: TypeDef => \"type declaration\"\n  }\n  def showHead: Str = this match {\n    case Def(true, n, b, isByname) => s\"rec def ${n.showDbg}\"\n    case Def(false, n, b, isByname) => s\"def ${n.showDbg}\"\n    case TypeDef(k, n, tps, b, _, _, pos, _) =>\n      s\"${k.str} ${n.name}${if (tps.isEmpty) \"\" else tps.map(_.name).mkString(\"[\", \", \", \"]\")}${\n        if (pos.isEmpty) \"\" else pos.mkString(\"(\", \", \", \")\")\n      }\"\n  }\n}\n\ntrait NuDeclImpl extends Located { self: NuDecl =>\n  val body: Located\n  def kind: DeclKind\n  val declareLoc: Opt[Loc]\n  val abstractLoc: Opt[Loc]\n  def isDecl: Bool = declareLoc.nonEmpty\n  def isAbstract: Bool = abstractLoc.nonEmpty\n  def declStr: Str = if (isDecl) \"declare \" else \"\"\n  val nameVar: Var = self match {\n    case td: NuTypeDef => td.nme.toVar\n    case fd: NuFunDef => fd.nme\n  }\n  def name: Str = nameVar.name\n  def showBody: Str = this match {\n    case fd: NuFunDef => fd.rhs.fold(_.print(false), _.showDbg2)\n    case td: NuTypeDef => td.body.showDbg\n  }\n  def describe: Str = this match {\n    case _: NuFunDef => \"definition\"\n    case _: NuTypeDef => \"type declaration\"\n  }\n  def showHead: Str = this match {\n    case NuFunDef(N, n, snme, _, b) => s\"fun${snme.fold(\"\")(\" (\"+_.name+\")\")} ${n.name}\"\n    case NuFunDef(S(false), n, snme, _, b) => s\"let${snme.fold(\"\")(\" \"+_.name+\")\")} ${n.name}\"\n    case NuFunDef(S(true), n, snme, _, b) => s\"let rec${snme.fold(\"\")(\" \"+_.name+\")\")} ${n.name}\"\n    case NuTypeDef(k, n, tps, sps, ctor, sig, parents, sup, ths, bod) =>\n      s\"${k.str} ${n.name}${if (tps.isEmpty) \"\" else tps.map(_._2.name).mkString(\"‹\", \", \", \"›\")}${\n          sps.fold(\"\")(\"(\" + _.showElems + \")\")\n        }${sig.fold(\"\")(\": \" + _.showDbg2)}${\n          if (parents.isEmpty) \"\" else if (k === Als) \" = \" else \": \"}${parents.iterator.map(_.showDbg).mkString(\", \")}\"\n  }\n  lazy val genUnapply: Opt[NuFunDef] = this match {\n    case td: NuTypeDef if td.kind is Cls => td.params.map { tup =>\n      val ret = Let(false, Var(\"_\"), Asc(Var(\"x\"), TypeName(name)), Tup(tup.fields.map {\n        case S(p) -> f => N -> Fld(FldFlags.empty, Sel(Var(\"x\"), Var(\"#\" + p.name).withLocOf(p)))\n        case N -> Fld(flags, p: Var) => N -> Fld(FldFlags.empty, Sel(Var(\"x\"), Var(\"#\" + p.name).withLocOf(p)))\n        case _ => die\n      }))\n      NuFunDef(N, Var(\"unapply\"), N, Nil, L(Lam(\n        Tup(N -> Fld(FldFlags.empty, Var(\"x\")) :: Nil),\n        ret)))(N, N, N, N, N, true, Nil)\n    }\n    case _ => N\n  }\n}\n\ntrait TypingUnitImpl extends Located { self: TypingUnit =>\n  def showDbg: Str = entities.iterator.map {\n    case t: Term => t.print(false)\n    case d: NuDecl => d.showDbg\n    case c: Constructor => c.showDbg\n    case e => lastWords(s\"Unexpected typing unit entity: $e\")\n  }.mkString(\"{\", \"; \", \"}\")\n\n  def showIn(implicit ctx: ShowCtx): Str = {\n    val newCtx = ctx.indent\n    entities.map{\n      case t: Term => t.showIn(false)(newCtx)\n      case nd: NuDecl => nd.show(newCtx.newDefs)\n      case s if !ctx.newDefs => s.toString\n      case _ => ???\n    }.mkString(\"{\" + newCtx.lnIndStr, newCtx.lnIndStr, ctx.lnIndStr + \"}\")\n  }\n  \n  lazy val children: List[Located] = rawEntities\n  \n  lazy val entities = {\n    val declaredValueMembers = rawEntities.collect{ case fd: NuFunDef if fd.rhs.isRight => fd.nme.name }.toSet\n    rawEntities.map {\n      case Eqn(lhs, rhs) if declaredValueMembers(lhs.name) =>\n        NuFunDef(N, lhs, N, Nil, L(rhs))(N, N, N, N, N, true, Nil)\n      case e => e\n    }\n  }\n  def describe: Str = entities.iterator.map {\n    case term: Term => term.describe\n    case NuFunDef(S(rec), nme, _, _, _) =>\n      s\"let ${if (rec) \"rec \" else \"\"}$nme\"\n    case NuFunDef(N, nme, _, _, _) => s\"fun $nme\"\n    case typ: NuTypeDef => typ.describe\n    case other => \"?\"\n  }.mkString(\"{\", \"; \", \"}\")\n}\n\ntrait ConstructorImpl { self: Constructor =>\n  // def children: List[Located] = fields.map(_._2)\n  def describe: Str = \"constructor\"\n  // def showDbg: Str = s\"constructor(${fields.map(_._1.name).mkString(\", \")})\"\n}\n\ntrait TypeNameImpl extends Ordered[TypeName] { self: TypeName =>\n  def base: TypeName = this\n  def targs: Ls[Type] = Nil\n  def compare(that: TypeName): Int = this.name compare that.name\n  lazy val toVar: Var = Var(name).withLocOf(this)\n  var symbol: Opt[pretyper.symbol.TypeSymbol] = N\n}\n\ntrait FldFlagsImpl extends Located { self: FldFlags =>\n  def children: Ls[Located] = Nil\n  override def toString(): String = {\n    val FldFlags(m, s, g) = this\n    val res = (if (m) \"m\" else \"\") + (if (s) \"s\" else \"\") + (if (g) \"g\" else \"\")\n    if (res.isEmpty) \"_\" else res\n  }\n}\n\ntrait FldImpl extends Located { self: Fld =>\n  def children: Ls[Located] = self.value :: Nil\n  def describe: Str =\n    (if (self.flags.spec) \"specialized \" else \"\") +\n    (if (self.flags.mut) \"mutable \" else \"\") +\n    self.value.describe\n}\n\ntrait TermImpl extends StatementImpl { self: Term =>\n  val original: this.type = this\n  \n  /** Used by code generation when the typer desugars this term into a different term. */\n  var desugaredTerm: Opt[Term] = N  \n  \n  private var sugaredTerm: Opt[Term] = N\n\n  def desugaredFrom(term: Term): this.type = {\n    sugaredTerm = S(term)\n    withLocOf(term)\n  }\n  \n  def describe: Str = sugaredTerm match {\n    case S(t) => t.describe\n    case N => this match {\n      case Ann(_, Ann(_, receiver)) => receiver.describe\n      case Ann(_, receiver) => \"annotated \" + receiver.describe\n      case Bra(true, Tup(_ :: _ :: _) | Tup((S(_), _) :: _) | Blk(_)) => \"record\"\n      case Bra(_, trm) => trm.describe\n      case Blk((trm: Term) :: Nil) => trm.describe\n      case Blk(_) => \"block of statements\"\n      case IntLit(value) => \"integer literal\"\n      case DecLit(value) => \"decimal literal\"\n      case StrLit(value) => \"string literal\"\n      case UnitLit(value) => if (value) \"undefined literal\" else \"null literal\"\n      case Var(name) => \"reference\" // \"variable reference\"\n      case Asc(trm, ty) => \"type ascription\"\n      case Lam(name, rhs) => \"lambda expression\"\n      case App(OpApp(Var(\"|\"), lhs), rhs) => \"type union\"\n      case App(OpApp(Var(\"&\"), lhs), rhs) => \"type intersection\"\n      case App(OpApp(op, lhs), rhs) => \"operator application\"\n      case OpApp(op, lhs) => \"operator application\"\n      case App(lhs, rhs) => \"application\"\n      case Rcd(fields) => \"record\"\n      case Sel(receiver, fieldName) => \"field selection\"\n      case Let(isRec, name, rhs, body) => \"let binding\"\n      case Tup((N, Fld(_, x)) :: Nil) => x.describe\n      case Tup((S(_), x) :: Nil) => \"binding\"\n      case Tup(xs) => \"tuple\"\n      case Bind(l, r) => \"'as' binding\"\n      case Test(l, r) => \"'is' test\"\n      case With(t, fs) =>  \"`with` extension\"\n      case CaseOf(scrut, cases) =>  \"`case` expression\" \n      case Subs(arr, idx) => \"array access\"\n      case Assign(lhs, rhs) => \"assignment\"\n      case While(cnd, bod) => \"while loop\"\n      case Splc(fs) => \"splice\"\n      case New(h, b) => \"object instantiation\"\n      case NuNew(_) => \"new instance\"\n      case Rft(_, _) => \"refinement\"\n      case If(_, _) => \"if-else block\"\n      case TyApp(_, _) => \"type application\"\n      case Where(_, _) => s\"constraint clause\"\n      case Forall(_, _) => s\"forall clause\"\n      case Inst(bod) => \"explicit instantiation\"\n      case Super() => \"super\"\n      case Eqn(lhs, rhs) => \"assign for ctor\"\n      case AdtMatchWith(cond, arms) => \"ADT pattern matching\"\n      case Quoted(_) => \"quasiquote\"\n      case Unquoted(_) => \"unquote\"\n    }\n  }\n\n  override def showDbg: Str = print(false)\n  \n  def print(brackets: Bool): Str = {\n      def bra(str: Str): Str = if (brackets) s\"($str)\" else str\n      this match {\n    case Ann(ann, receiver) => bra(\"@\" + ann.print(false) + \" \") + receiver.print(false)\n    case Bra(true, trm) => s\"'{' ${trm.showDbg} '}'\"\n    case Bra(false, trm) => s\"'(' ${trm.showDbg} ')'\"\n    case Blk(stmts) => stmts.iterator.map(_.showDbg).mkString(\"{\", \"; \", \"}\")\n    case IntLit(value) => value.toString\n    case DecLit(value) => value.toString\n    case StrLit(value) => value.iterator.map {\n      case '\\\\' => \"\\\\\\\\\"; case '\"' => \"\\\\\\\"\"; case '\\'' => \"\\\\'\"\n      case '\\n' => \"\\\\n\"; case '\\r' => \"\\\\r\"; case '\\t' => \"\\\\t\"\n      case '\\f' => \"\\\\f\"; case '\\b' => \"\\\\b\"; case c => c.toString()\n    }.mkString(\"\\\"\", \"\", \"\\\"\")\n    case UnitLit(value) => if (value) \"undefined\" else \"null\"\n    case v @ Var(name) => name + v.uid.fold(\"\")(\"::\"+_.toString)\n    case Asc(trm, ty) => s\"${trm.showDbg} : ${ty.showDbg2}\"  |> bra\n    case Lam(pat: Tup, rhs) => s\"(${pat.showElems}) => ${rhs.showDbg}\" |> bra\n    case Lam(pat, rhs) => s\"(...${pat.showDbg}) => ${rhs.showDbg}\" |> bra\n    case App(lhs, rhs: Tup) => s\"${lhs.print(!lhs.isInstanceOf[App])}(${rhs.showElems})\" |> bra\n    case App(lhs, rhs) => s\"${lhs.print(!lhs.isInstanceOf[App])}(...${rhs.print(true)})\" |> bra\n    case Rcd(fields) =>\n      fields.iterator.map(nv =>\n        (if (nv._2.flags.mut) \"mut \" else \"\") + nv._1.name + \": \" + nv._2.value.showDbg).mkString(\"{\", \", \", \"}\")\n    case Sel(receiver, fieldName) => \"(\" + receiver.showDbg + \").\" + fieldName.showDbg\n    case Let(isRec, Var(name), rhs, body) =>\n      s\"let${if (isRec) \" rec\" else \"\"} $name = ${rhs.showDbg} in ${body.showDbg}\" |> bra\n    case tup: Tup => \"[\" + tup.showElems + \"]\"\n    case Splc(fields) => fields.map{\n      case L(l) => s\"...$l\"\n      case R(Fld(FldFlags(m, s, g), r)) => (\n        (if (m) \"mut \" else \"\")\n        + (if (g) \"val \" else \"\")\n        + (if (s) \"#\" else \"\")\n        + r\n      )\n    }.mkString(\"(\", \", \", \")\")\n    case Bind(l, r) => s\"${l.showDbg} as ${r.showDbg}\" |> bra\n    case Test(l, r) => s\"${l.showDbg} is ${r.showDbg}\" |> bra\n    case With(t, fs) => s\"${t.showDbg} with ${fs.showDbg}\" |> bra\n    case CaseOf(s, c) =>\n      s\"case ${s.showDbg} of { ${c.print(true)} }\" |> bra\n    case Subs(a, i) => s\"(${a.showDbg})[${i.showDbg}]\"\n    case Assign(lhs, rhs) => s\"${lhs.showDbg} <- ${rhs.showDbg}\" |> bra\n    case While(cnd, bod) => s\"while ${cnd.showDbg} do ${bod.showDbg}\" |> bra\n    case New(S((at, ar)), bod) => s\"new ${at.showDbg2}(${ar.showDbg}) ${bod.showDbg}\" |> bra\n    case New(N, bod) => s\"new ${bod.showDbg}\" |> bra\n    case NuNew(cls) => s\"new ${cls.showDbg}\" |> bra\n    case If(body, els) => s\"if ${body.showDbg}\" + els.fold(\"\")(\" else \" + _.showDbg) |> bra\n    case TyApp(lhs, targs) => s\"${lhs.showDbg}‹${targs.iterator.map(_.showDbg2).mkString(\", \")}›\"\n    case Where(bod, wh) => s\"${bod.showDbg} where {${wh.iterator.map(_.showDbg).mkString(\"; \")}}\"\n    case Forall(ps, bod) => s\"forall ${ps.mkString(\", \")}. ${bod.showDbg}\"\n    case Inst(bod) => s\"${bod.print(true)}!\"\n    case Super() => \"super\"\n    case Eqn(lhs, rhs) => s\"${lhs.showDbg} = ${rhs.showDbg}\"\n    case AdtMatchWith(cond, arms) =>\n      s\"match ${cond.showDbg} with ${arms.map (patmat => s\"${patmat.pat.showDbg} -> ${patmat.rhs.showDbg}\").mkString (\" | \") }\"\n    case Quoted(b) => s\"code\\\"${b.showDbg}\\\"\"\n    case Unquoted(b) => s\"$${${b.showDbg}}\"\n    case Rft(bse, tu) => s\"${bse.showDbg} ${tu.showDbg}\"\n  }}\n\n  def show(newDefs: Bool): Str = showIn(false)(ShowCtx.mk(Nil, newDefs))\n  def showIn(brackets: Bool)(implicit ctx: ShowCtx): Str = {\n    def bra(str: Str): Str = if (brackets) s\"($str)\" else str\n    this match {\n      case Ann(ann, receiver) => bra(s\"@${ann.toString()} ${receiver.showIn(false)}\")\n      case Bra(true, trm) => trm.showIn(false)\n      case Bra(false, trm) => s\"(${trm.showIn(false)})\"\n      case Blk(stmts) =>\n        val newCtx = ctx.indent\n        stmts.map {\n          case t: Term => t.showIn(false)(newCtx)\n          case nd: NuDecl => nd.show(newCtx.newDefs)\n          case s if !ctx.newDefs => s.toString\n          case _ => ???\n        }.mkString(\"{\" + newCtx.lnIndStr, newCtx.lnIndStr, ctx.indStr + \"\\n}\")\n      case IntLit(value) => value.toString\n      case DecLit(value) => value.toString\n      case StrLit(value) => '\"'.toString + value + '\"'\n      case UnitLit(value) => if (ctx.newDefs) \"()\" else if (value) \"undefined\" else \"null\"\n      case Var(name) => name\n      case Asc(trm, ty) => s\"$trm : ${ty.show(ctx.newDefs)}\" |> bra\n      case Lam(pat: Tup, rhs) => s\"(${pat.showIn}) => ${rhs.showIn(false)}\" |> bra\n      case Lam(pat, rhs) => s\"(...${pat.showIn(false)}) => ${rhs.showIn(false)}\" |> bra\n      case App(lhs, rhs: Tup) => s\"${lhs.showIn(!lhs.isInstanceOf[App])}(${rhs.showIn})\" |> bra\n      case App(lhs, rhs) => s\"${lhs.showIn(!lhs.isInstanceOf[App])}(...${rhs.showIn(true)})\" |> bra\n      case Rcd(fields) =>\n        val newCtx = ctx.indent\n        fields.iterator.map(nv =>\n          (if (nv._2.flags.mut) \"mut \" else \"\") + nv._1.name + \": \" + nv._2.value.showIn(false)(newCtx)).mkString(\"{\" + newCtx.lnIndStr, \",\" + newCtx.lnIndStr, ctx.lnIndStr + \"}\")\n      case Sel(receiver, fieldName) => receiver.showIn(!receiver.isInstanceOf[SimpleTerm]) + \".\" + fieldName\n      case Let(isRec, name, rhs, body) =>\n        s\"let${if (isRec) \" rec\" else \"\"} ${name.showIn(false)} = ${rhs.showIn(false)} in ${body.showIn(false)}\" |> bra\n      case tup: Tup => \"[\" + tup.showIn + \"]\"\n      case Splc(fields) => fields.map{\n        case L(l) => s\"...${l.showIn(false)}\"\n        case R(Fld(FldFlags(m, s, g), r)) => (\n          (if (m) \"mut \" else \"\")\n          + (if (g) \"val \" else \"\")\n          + (if (s) \"#\" else \"\")\n          + r.showIn(false)\n        )\n      }.mkString(\"(\", \", \", \")\")\n      case Bind(l, r) => s\"${l.showIn(false)} as ${r.showIn(false)}\" |> bra\n      case Test(l, r) => s\"${l.showIn(false)} is ${r.showIn(false)}\" |> bra\n      case With(t, fs) =>  s\"${t.showIn(false)} with ${fs.showIn(false)}\" |> bra\n      case CaseOf(s, c) =>\n        s\"case ${s.showIn(false)} of {${c.showIn(ctx.indent)}${ctx.lnIndStr}}\" |> bra\n      case Subs(a, i) => s\"(${a.showIn(false)})[${i.showIn(false)}]\"\n      case Assign(lhs, rhs) => s\"${lhs.showIn(false)} <- ${rhs.showIn(false)}\" |> bra\n      case While(cnd, bod) => s\"while ${cnd.showIn(false)} do ${bod.showIn(false)}\" |> bra\n      case New(S((at, ar)), bod) => s\"new ${at.show(ctx.newDefs)}($ar) ${bod.showIn}\" |> bra\n      case New(N, bod) => s\"new ${bod.showIn}\" |> bra\n      case NuNew(cls) => s\"new ${cls.showIn(false)}\" |> bra\n      case If(body, els) => s\"if ${body.showIn(ctx.indent)}\" + els.fold(\"\")(\" else \" + _.showIn(false)(ctx.indent)) |> bra\n      case TyApp(lhs, targs) => s\"${lhs.showIn(false)}${ctx.<}${targs.map(_.show(ctx.newDefs)).mkString(\", \")}${ctx.>}\"\n      case Where(bod, wh) => s\"${bod.showIn(false)} where ${Blk(wh).showIn(false)(ctx.indent)}\"\n      case Forall(ps, bod) => s\"forall ${ps.map(_.show(ctx.newDefs)).mkString(\", \")}. ${bod.showIn(false)}\"\n      case Inst(bod) => s\"${bod.showIn(true)}!\"\n      case Super() => \"super\"\n      case Eqn(lhs, rhs) => s\"${lhs.showIn(false)} = ${rhs.showIn(false)}\"\n      case AdtMatchWith(cond, arms) =>\n        s\"match ${cond.showIn(false)} with ${arms.map (patmat => s\"${patmat.pat.showIn(false)} -> ${patmat.rhs.showIn(false)}\").mkString (\" | \") }\"\n      case Rft(bse, tu) => s\"${bse.showIn(false)} { ${tu.showIn} }\"\n      case Quoted(b) => s\"code\\\"${b.showIn(false)}\\\"\"\n      case Unquoted(b) => s\"$${${b.showIn(false)}}\"\n    }\n  }\n  \n  def toTypeRaise(implicit raise: Raise): Type = toType match {\n    case L(d) => raise(d); Bot\n    case R(ty) => ty\n  }\n  def toType: Diagnostic \\/ Type =\n    try R(toType_!.withLocOf(this)) catch {\n      case e: NotAType =>\n        import Message._\n        L(ErrorReport(msg\"Not a recognized type\" -> e.trm.toLoc::Nil, newDefs=true, source=Diagnostic.Parsing)) }\n  protected def toType_! : Type = (this match {\n    case Var(name) if name.startsWith(\"`\") => TypeVar(R(name.tail), N)\n    case Var(name) if name.startsWith(\"'\") => TypeVar(R(name), N)\n    case Var(name) => TypeName(name)\n    case lit: Lit => Literal(lit)\n    case App(Var(\"->\"), PlainTup(lhs @ (_: Tup | Bra(false, _: Tup)), rhs)) =>\n    // * ^ Note: don't think the plain _: Tup without a Bra can actually occur\n      Function(lhs.toType_!, rhs.toType_!)\n    case App(Var(\"->\"), PlainTup(lhs, rhs)) =>\n      Function(Tuple(N -> Field(N, lhs.toType_!) :: Nil), rhs.toType_!)\n    case App(Var(\"|\"), PlainTup(lhs, rhs)) =>\n      Union(lhs.toType_!, rhs.toType_!)\n    case App(Var(\"&\"), PlainTup(lhs, rhs)) =>\n      Inter(lhs.toType_!, rhs.toType_!)\n    case ty @ App(v @ Var(\"\\\\\"), PlainTup(lhs, rhs)) =>\n      Inter(lhs.toType_!, Neg(rhs.toType_!).withLoc(Loc(v :: rhs :: Nil))).withLoc(ty.toCoveringLoc)\n    case App(Var(\"~\"), rhs) => Neg(rhs.toType_!)\n    case Lam(lhs, rhs) => Function(lhs.toType_!, rhs.toType_!)\n    case App(lhs, PlainTup(fs @ _*)) =>\n      lhs.toType_! match {\n        case tn: TypeName => AppliedType(tn, fs.iterator.map(_.toType_!).toList)\n        case _ => throw new NotAType(this)\n      }\n    case Tup(fields) => Tuple(fields.map(fld => (fld._1, fld._2 match {\n      case Fld(FldFlags(m, s, _), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty)\n    })))\n    case Bra(rcd, trm) => trm match {\n      case _: Rcd => if (rcd) trm.toType_! else throw new NotAType(this)\n      case _ => if (!rcd) trm.toType_! else throw new NotAType(this)\n    }\n    case TyApp(lhs, targs) => lhs.toType_! match {\n      case p: TypeName => AppliedType(p, targs)\n      case _ => throw new NotAType(this)\n    }\n    case Rcd(fields) => Record(fields.map(fld => (fld._1, fld._2 match {\n      case Fld(FldFlags(m, s, _), v) => val ty = v.toType_!; Field(Option.when(m)(ty), ty)\n    })))\n    case Where(body, where) =>\n      Constrained(body.toType_!, Nil, where.map {\n        case Asc(l, r) => Bounds(l.toType_!, r)\n        case s => throw new NotAType(s)\n      }, Nil)\n    case Forall(ps, bod) =>\n      PolyType(ps.map(R(_)), bod.toType_!)\n    // \n    case Sel(receiver, field) =>\n      Selection(receiver.toType_!, TypeName(field.name).withLocOf(field))\n    // case Sel(receiver, fieldName) => receiver match {\n    //   case Var(name) if !name.startsWith(\"`\") => TypeName(s\"$name.$fieldName\")\n    //   case _ => throw new NotAType(this)\n    // }\n    // TODO:\n    // case Let(isRec, name, rhs, body) => ???\n    // case Blk(stmts) => ???\n    // case Asc(trm, ty) => ???\n    // case Bind(lhs, rhs) => ???\n    // case Test(trm, ty) => ???\n    // case With(trm, fieldNme, fieldVal) => ???\n    // case CaseOf(trm, cases) => ???\n    case _ => throw new NotAType(this)\n  }).withLocOf(this)\n  \n  /** Whether this is a lambda that, when let-rec-bound, should be generalized. */\n  def isGeneralizableLam: Bool = this match {\n    case Lam(_, _) => true\n    case Bra(false, that) => that.isGeneralizableLam\n    case Where(that, _) => that.isGeneralizableLam\n    case CaseOf(_, cs) => cs.bodies.forall(_.isGeneralizableLam)\n    case _ => false\n  }\n  \n}\nprivate class NotAType(val trm: Statement) extends Throwable\n\nobject PlainTup {\n  def apply(fields: Term*): Term =\n    Tup(fields.iterator.map(t => (N, Fld(FldFlags.empty, t))).toList)\n  def unapplySeq(trm: Term): Opt[List[Term]] = trm match {\n    case Tup(fields) if fields.forall(f =>\n      f._1.isEmpty && f._2.flags.mut === false && f._2.flags.spec === false\n    ) => S(fields.map(_._2.value))\n    case _ => N\n  }\n}\n\ntrait LitImpl { self: Lit =>\n  def baseClassesOld: Set[TypeName] = this match {\n    case _: IntLit => Set.single(TypeName(\"int\")) + TypeName(\"number\")\n    case _: StrLit => Set.single(TypeName(\"string\"))\n    case _: DecLit => Set.single(TypeName(\"number\"))\n    case _: UnitLit => Set.empty\n  }\n  def baseClassesNu: Set[TypeName] = this match {\n    case _: IntLit => Set.single(TypeName(\"Int\")) + TypeName(\"Num\") + TypeName(\"Object\")\n    case _: StrLit => Set.single(TypeName(\"Str\")) + TypeName(\"Object\")\n    case _: DecLit => Set.single(TypeName(\"Num\")) + TypeName(\"Object\")\n    case _: UnitLit => Set.single(TypeName(\"Object\"))\n  }\n}\n\ntrait VarImpl extends pretyper.symbol.Symbolic { self: Var =>\n  /** Check if the variable name is an integer. */\n  def isIndex: Bool = name.headOption match {\n    case S('0') => name.length === 1\n    case S(_) => name.forall(_.isDigit)\n    case N => false\n  }\n  /** Get the integer if it's a valid index. */\n  def toIndexOption: Opt[Int] = if (isIndex) name.toIntOption else N\n  def isPatVar: Bool =\n    (name.head.isLetter && name.head.isLower || name.head === '_' || name.head === '$') && name =/= \"true\" && name =/= \"false\"\n  def toVar: Var = this\n  var uid: Opt[Int] = N\n}\n\ntrait TupImpl { self: Tup =>\n  def showElems: Str =\n    fields.iterator.map { case (n, t) => (\n      (if (t.flags.mut) \"mut \" else \"\")\n      + (if (t.flags.genGetter) \"val \" else \"\")\n      + (if (t.flags.spec) \"#\" else \"\")\n      + n.fold(\"\")(_.name + \": \") + t.value.print(false) + \",\"\n    )}.mkString(\" \")\n\n  def showIn(implicit ctx: ShowCtx): Str =\n    fields.iterator.map { case (n, t) => (\n      (if (t.flags.mut) \"mut \" else \"\")\n      + (if (t.flags.genGetter) \"val \" else \"\")\n      + (if (t.flags.spec) \"#\" else \"\")\n      + n.fold(\"\")(_.name + \": \") + t.value.showIn(false)\n    )}.mkString(\", \")\n}\n\ntrait SimpleTermImpl extends Ordered[SimpleTerm] { self: SimpleTerm =>\n  def compare(that: SimpleTerm): Int = this.idStr compare that.idStr\n  val idStr: Str = this match {\n    case Var(name) => name\n    case lit: Lit => lit.showDbg\n  }\n}\n\ntrait FieldImpl extends Located { self: Field =>\n  def children: List[Located] =\n    self.in.toList ::: self.out :: Nil\n  def isMutabe: Bool = in.isDefined\n  def mutStr: Str = if (isMutabe) \"mut \" else \"\"\n}\n\ntrait Located {\n  def children: List[Located]\n  \n  lazy val freeVars: Set[Var] = {\n    def statements(stmts: Ls[Statement]): Set[Var] =\n      stmts.iterator.foldRight(Set.empty[Var]) {\n        case (NuFunDef(isLetRec, nme, _, _, L(rhs)), fvs) => fvs - nme ++ (isLetRec match {\n          case N | S(true) => rhs.freeVars - nme\n          case S(false) => rhs.freeVars\n        })\n        case (td: NuTypeDef, fvs) =>\n          if (td.kind === Mod || td.kind === Cls || td.kind === Trt)\n            fvs - td.nameVar\n          else\n            fvs\n        case (statement, fvs) => fvs ++ statement.freeVars\n      }\n    this match {\n      // TypingUnit\n      case TypingUnit(entities) => statements(entities)\n      // Terms\n      case v: Var => Set.single(v)\n      case Lam(tup: Tup, body) => body.freeVars -- tup.freeVars\n      case App(lhs, rhs) => lhs.freeVars ++ rhs.freeVars\n      case Tup(fields) => fields.iterator.flatMap(_._2.value.freeVars.iterator).toSet\n      case Rcd(fields) => fields.iterator.flatMap(_._2.value.freeVars.iterator).toSet\n      case Sel(receiver, _) => receiver.freeVars\n      case Let(true, nme, rhs, body) => body.freeVars ++ rhs.freeVars - nme\n      case Let(false, nme, rhs, body) => body.freeVars - nme ++ rhs.freeVars\n      case Blk(stmts) => statements(stmts)\n      case Bra(_, trm) => trm.freeVars\n      case Asc(trm, _) => trm.freeVars\n      case Bind(lhs, rhs) => lhs.freeVars ++ rhs.freeVars\n      case Test(trm, _) => trm.freeVars\n      case With(trm, fields) => trm.freeVars ++ fields.freeVars\n      case CaseOf(trm, cases) => cases.foldLeft(trm.freeVars)(_ ++ _._2.freeVars)(_ ++ _.fold(Set.empty[Var])(_.freeVars))\n      case Subs(arr, idx) => arr.freeVars ++ idx.freeVars\n      case Assign(lhs, rhs) => lhs.freeVars ++ rhs.freeVars\n      case Splc(fields) => fields.iterator.flatMap(_.fold(_.freeVars, _.value.freeVars)).toSet\n      case New(head, body) => head.fold(Set.empty[Var])(_._2.freeVars) ++ body.freeVars\n      case NuNew(cls) => cls.freeVars\n      // Because `IfBody` uses the term to represent the pattern, direct\n      // traversal is not correct.\n      case If(_, _) => Set.empty\n      case TyApp(lhs, _) => lhs.freeVars\n      case Where(body, where) => body.freeVars ++ statements(where)\n      case Forall(_, body) => body.freeVars\n      case Inst(body) => body.freeVars\n      case Super() => Set.empty\n      case Eqn(lhs, rhs) => lhs.freeVars ++ rhs.freeVars\n      case Rft(base, decls) => base.freeVars ++ decls.freeVars\n      // Fallback for unsupported terms which is incorrect most of the time.\n      case _ => children.iterator.flatMap(_.freeVars.iterator).toSet\n    }\n  }\n  \n  private var spanStart: Int = -1\n  private var spanEnd: Int = -1\n  private var origin: Opt[Origin] = N\n  \n  // TODO just store the Loc directly...\n  def withLoc(s: Int, e: Int, ori: Origin): this.type = {\n    // assert(origin.isEmpty)\n    origin = S(ori)\n    // assert(spanStart < 0)\n    // assert(spanEnd < 0)\n    spanStart = s\n    spanEnd = e\n    this\n  }\n  def withLoc(loco: Opt[Loc]): this.type = {\n    loco.foreach { that =>\n      spanStart = that.spanStart\n      spanEnd = that.spanEnd\n      origin = S(that.origin)\n    }\n    this\n  }\n  def withLocOf(that: Located): this.type = withLoc(that.toLoc)\n  def hasLoc: Bool = origin.isDefined\n  lazy val toLoc: Opt[Loc] = getLoc\n  private[mlscript] def getLoc: Opt[Loc] = {\n    def subLocs = children.iterator.flatMap(_.toLoc.iterator)\n    if (spanStart < 0) spanStart =\n      subLocs.map(_.spanStart).minOption.getOrElse(return N)\n    if (spanEnd < 0) spanEnd =\n      subLocs.map(_.spanEnd).maxOption.getOrElse(return N)\n    val origins = origin.fold(subLocs.map(_.origin).toList.distinct)(_ :: Nil)\n    assert(origins.size === 1, origins)\n    S(Loc(spanStart, spanEnd, origins.head))\n  }\n  /** Like toLoc, but we make sure the span includes the spans of all subterms. */\n  def toCoveringLoc: Opt[Loc] = {\n    // TODO factor logic with above\n    def subLocs = (this :: children).iterator.flatMap(_.toLoc.iterator)\n    val spanStart =\n      subLocs.map(_.spanStart).minOption.getOrElse(return N)\n    val spanEnd =\n      subLocs.map(_.spanEnd).maxOption.getOrElse(return N)\n    val origins = origin.fold(subLocs.map(_.origin).toList.distinct)(_ :: Nil)\n    assert(origins.size === 1)\n    S(Loc(spanStart, spanEnd, origins.head))\n  }\n}\n\ntrait DesugaredStatementImpl extends Located { self: DesugaredStatement =>\n  def describe: Str\n\n  def showDbg: Str\n}\n\ntrait StatementImpl extends Located { self: Statement =>\n  \n  lazy val desugared = doDesugar\n  private def doDesugar: Ls[Diagnostic] -> Ls[DesugaredStatement] = this match {\n    // case ctor: Constructor =>\n    //   import Message._\n    //   (ErrorReport(msg\"constructor must be in a class.\" -> ctor.toLoc :: Nil, newDefs=true) :: Nil) -> Nil\n    case l @ LetS(isrec, pat, rhs) =>\n      val (diags, v, args) = desugDefnPattern(pat, Nil)\n      diags -> (Def(isrec, v, L(args.foldRight(rhs)(Lam(_, _))), false).withLocOf(l) :: Nil) // TODO use v, not v.name\n    case d @ DataDefn(body) => desugarCases(body :: Nil, Nil)\n    case d @ DatatypeDefn(hd, bod) =>\n      val (diags, v, args) = desugDefnPattern(hd, Nil)\n      val (diags3, targs) = args.partitionMap {\n        case v @ Var(nme) => R(TypeName(nme).withLocOf(v))\n        case t =>\n          import Message._\n          L(ErrorReport(msg\"illegal datatype type parameter shape: ${t.showDbg}\" -> t.toLoc :: Nil, newDefs=false))\n      }\n      val (diags2, cs) = desugarCases(bod, targs)\n      val dataDefs = cs.collect{case td: TypeDef => td}\n      (diags ::: diags2 ::: diags3) -> (TypeDef(Als, TypeName(v.name).withLocOf(v), targs,\n          dataDefs.map(td => AppliedType(td.nme, td.tparams)).reduceOption(Union).getOrElse(Bot), Nil, Nil, Nil, N\n        ).withLocOf(hd) :: cs)\n    case NuTypeDef(Mod, nme, tps, tup, ctor, sig, pars, sup, ths, unit) =>\n      ??? // TODO\n    case NuTypeDef(Mxn, nme, tps, tup, ctor, sig, pars, sup, ths, unit) =>\n      ??? // TODO\n    case NuTypeDef(k @ Als, nme, tps, tup, ctor, sig, pars, sup, ths, unit) =>\n      // TODO properly check:\n      require(tup.forall(tup => tup.fields.isEmpty), tup)\n      require(pars.size === 0, pars)\n      require(sig.isDefined)\n      require(ths.isEmpty, ths)\n      require(unit.entities.isEmpty, unit)\n      Nil -> (TypeDef(k, nme, tps.map(_._2), sig.getOrElse(die), Nil, Nil, Nil, N) :: Nil)\n    case NuTypeDef(k @ (Cls | Trt), nme, tps, opt, ctor, sig, pars, sup, ths, unit) =>\n      val tup = opt.getOrElse(Tup(Nil))\n      val fs = tup.fields\n      val diags = Buffer.empty[Diagnostic]\n      def tt(trm: Term): Type = trm.toType match {\n        case L(ds) => diags += ds; Top\n        case R(ty) => ty\n      }\n      val params = fs.map {\n        case (S(nme), Fld(FldFlags(mut, spec, _), trm)) =>\n          val ty = tt(trm)\n          nme -> Field(if (mut) S(ty) else N, ty)\n        case (N, Fld(FldFlags(mut, spec, _), nme: Var)) => nme -> Field(if (mut) S(Bot) else N, Top)\n        case _ => die\n      }\n      val pos = params.unzip._1\n      val bod = pars.map(tt).foldRight(Record(params): Type)(Inter)\n      val termName = Var(nme.name).withLocOf(nme)\n      val ctor = Def(false, termName, L(Lam(tup, App(termName, Tup(N -> Fld(FldFlags.empty, Rcd(fs.map {\n        case (S(nme), fld) => nme -> Fld(FldFlags(false, false, fld.flags.genGetter), nme)\n        case (N, fld @ Fld(_, nme: Var)) => nme -> fld\n        case _ => die\n      })) :: Nil)))), true)\n      diags.toList -> (TypeDef(k, nme, tps.map(_._2), bod, Nil, Nil, pos, N) :: ctor :: Nil)\n    case d: DesugaredStatement => Nil -> (d :: Nil)\n  }\n  import Message._\n  protected def desugDefnPattern(pat: Term, args: Ls[Term]): (Ls[Diagnostic], Var, Ls[Term]) = pat match {\n    case App(l, r) => desugDefnPattern(l, r :: args)\n    case v: Var => (Nil, v, args)\n    case _ => (ErrorReport(msg\"Unsupported pattern shape\" -> pat.toLoc :: Nil, newDefs=true) :: Nil, Var(\"<error>\"), args) // TODO\n  }\n  protected def desugarCases(bod: Term, baseTargs: Ls[TypeName]): (Ls[Diagnostic], Ls[Decl]) = bod match {\n    case Blk(stmts) => desugarCases(stmts, baseTargs)\n    case Tup(comps) =>\n      val stmts = comps.map {\n        case N -> Fld(_, d) => d\n        case S(n) -> Fld(_, d) => ???\n      }\n      desugarCases(stmts, baseTargs)\n    case _ => (ErrorReport(msg\"Unsupported data type case shape\" -> bod.toLoc :: Nil, newDefs=true) :: Nil, Nil)\n  }\n  protected def desugarCases(stmts: Ls[Statement], baseTargs: Ls[TypeName]): (Ls[Diagnostic], Ls[Decl]) = stmts match {\n    case stmt :: stmts =>\n      val (diags0, sts) = stmt.desugared\n      val (diags2, cs) = desugarCases(stmts, baseTargs)\n      val allDiags = Buffer.from(diags0)\n      val res = sts.flatMap {\n        case t: Term =>\n          val (diags1, v, args) = desugDefnPattern(t, Nil)\n          allDiags ++= diags1\n          val tparams = Buffer.from(baseTargs)\n          val fields = SortedMutMap.empty[Var, Type]\n          def getFields(t: Term): Ls[Type] = t match {\n            case v: Var =>\n              // TOOD check not already defined\n              val tp = baseTargs.find(_.name === v.name).map(_.copy()).getOrElse(\n                if (v.name.startsWith(\"`\")) TypeVar(R(v.name.tail), N)\n                else TypeName(v.name) tap (tparams += _)).withLocOf(v)\n              fields += v -> tp\n              tp :: Nil\n            case Blk((t: Term)::Nil) => getFields(t)\n            case Blk(_) => ??? // TODO proper error\n            case Bra(b, Blk((t:Term)::Nil)) => getFields(Bra(b, t))\n            case Bra(false, t) => getFields(t)\n            case Bra(true, Tup(fs)) =>\n              Record(fs.map {\n                case (S(n) -> Fld(FldFlags(mut, _, _), t)) =>\n                  val ty = t.toType match {\n                    case L(d) => allDiags += d; Top\n                    case R(t) => t\n                  }\n                  fields += n -> ty\n                  n -> Field(None, ty)\n                case _ => ???\n              }) :: Nil\n            case Bra(true, t) => lastWords(s\"$t ${t.getClass}\")\n            case Tup(fs) => // TODO factor with case Bra(true, Tup(fs)) above\n              Tuple(fs.map {\n                case (S(n) -> Fld(FldFlags(tmut, _, _), t)) =>\n                  val ty = t.toType match {\n                    case L(d) => allDiags += d; Top\n                    case R(t) => t\n                  }\n                  fields += n -> ty\n                  S(n) -> Field(None, ty)\n                case _ => ???\n              }) :: Nil\n            case _ => ??? // TODO proper error\n          }\n          val params = args.flatMap(getFields)\n          val clsNme = TypeName(v.name).withLocOf(v)\n          val tps = tparams.toList\n          val ctor = Def(false, v, R(PolyType(tps.map(L(_)),\n            params.foldRight(AppliedType(clsNme, tps):Type)(Function(_, _)))), true).withLocOf(stmt)\n          val td = TypeDef(Cls, clsNme, tps, Record(fields.toList.mapValues(Field(None, _))), Nil, Nil, Nil, N).withLocOf(stmt)\n          td :: ctor :: cs\n        case _ => ??? // TODO methods in data type defs? nested data type defs?\n      }\n      allDiags ++= diags2\n      allDiags.toList -> res\n    case Nil => Nil -> Nil\n  }\n  \n  def children: List[Located] = this match {\n    case Ann(ann, trm) => ann :: trm :: Nil\n    case Bra(_, trm) => trm :: Nil\n    case Var(name) => Nil\n    case Asc(trm, ty) => trm :: Nil\n    case Lam(lhs, rhs) => lhs :: rhs :: Nil\n    case App(lhs, rhs) => lhs :: rhs :: Nil\n    case Tup(fields) => fields.map(_._2.value)\n    case Rcd(fields) => fields.map(_._2.value)\n    case Sel(receiver, fieldName) => receiver :: fieldName :: Nil\n    case Let(isRec, name, rhs, body) => rhs :: body :: Nil\n    case Blk(stmts) => stmts\n    case LetS(_, pat, rhs) => pat :: rhs :: Nil\n    case DatatypeDefn(head, body) => head :: body :: Nil\n    case DataDefn(body) => body :: Nil\n    case _: Lit => Nil\n    case Bind(l, r) => l :: r :: Nil\n    case Test(l, r) => l :: r :: Nil\n    case With(t, fs) => t :: fs :: Nil\n    case CaseOf(s, c) => s :: c :: Nil\n    case d @ Def(_, n, b, _) => n :: d.body :: Nil\n    case TypeDef(kind, nme, tparams, body, _, _, pos, _) => nme :: tparams ::: pos ::: body :: Nil\n    case Subs(a, i) => a :: i :: Nil\n    case Assign(lhs, rhs) => lhs :: rhs :: Nil\n    case While(cnd, bod) => cnd :: bod :: Nil\n    case Splc(fields) => fields.map{case L(l) => l case R(r) => r.value}\n    case If(body, els) => body :: els.toList\n    case d @ NuFunDef(_, v, v2, ts, rhs) => v :: v2.toList ::: ts ::: d.body :: Nil\n    case TyApp(lhs, targs) => lhs :: targs\n    case New(base, bod) => base.toList.flatMap(ab => ab._1 :: ab._2 :: Nil) ::: bod :: Nil\n    case NuNew(cls) => cls :: Nil\n    case Rft(bs, tu) => bs :: tu :: Nil\n    case Where(bod, wh) => bod :: wh\n    case Forall(ps, bod) => ps ::: bod :: Nil\n    case Inst(bod) => bod :: Nil\n    case Super() => Nil\n    case Constructor(params, body) => params :: body :: Nil\n    case Eqn(lhs, rhs) => lhs :: rhs :: Nil\n    case NuTypeDef(k, nme, tps, ps, ctor, sig, pars, sup, ths, bod) =>\n      nme :: tps.map(_._2) ::: ps.toList ::: pars ::: ths.toList ::: bod :: Nil\n    case AdtMatchWith(cond, _) => cond :: Nil // FIXME discards branches...\n    case Quoted(body) => body :: Nil\n    case Unquoted(body) => body :: Nil\n  }\n  \n  def showDbg: Str = this match {\n    case LetS(isRec, name, rhs) => s\"let${if (isRec) \" rec\" else \"\"} ${name.showDbg} = ${rhs.showDbg}\"\n    case DatatypeDefn(head, body) => s\"data type ${head.showDbg} of ${body.showDbg}\"\n    case DataDefn(head) => s\"data ${head.showDbg}\"\n    case Constructor(params, body) => s\"constructor(${params.showElems}) ${body.showDbg}\"\n    case t: Term => t.print(false)\n    case d: Decl => d.showHead + (d match {\n      case n: TypeDef if n.kind is Als => \" = \"\n      case _ => \": \"\n    }) + d.showBody\n    case n: NuDecl => n.showHead + (n match {\n      case n: NuFunDef => if (n.rhs.isLeft) \" = \" else \": \"\n      case _: NuTypeDef => \" \"\n    }) + n.showBody\n  }\n}\n\ntrait BlkImpl { self: Blk =>\n  def kind: Block.type = Block\n  \n  def flatten: Blk = Blk(stmts.flatMap {\n    case b: Blk => b.flatten.stmts\n    case t => t :: Nil\n  })\n  \n}\n\ntrait CaseOfImpl extends Located { self: CaseOf =>\n  def isEmpty: Bool = {\n    val CaseOf(scrut, cases) = this\n    cases === NoCases\n  }\n}\n\ntrait CaseBranchesImpl extends Located { self: CaseBranches =>\n\n  def children: List[Located] = this match {\n    case Case(pat, body, rest) => pat :: body :: rest :: Nil\n    case Wildcard(body) => body :: Nil\n    case NoCases => Nil\n  }\n  \n  def bodies: List[Term] = this match {\n    case Case(_, body, rest) => body :: rest.bodies\n    case Wildcard(body) => body :: Nil\n    case NoCases => Nil\n  }\n  \n  def print(isFirst: Bool): Str = this match {\n    case c @ Case(pat, body, rest) =>\n      (if (isFirst) { \"\" } else { \"; \" }) +\n      (if (c.refined) \"refined \" else \"\") + pat.print(false) + \" => \" + body.print(false) + rest.print(false)\n    case Wildcard(body) => \n      (if (isFirst) { \"\" } else { \"; \" }) +\n      \"_ => \" + body.print(false)\n    case NoCases => \"\"\n  }\n\n  def foldLeft[A, B](z: A)(f: (A, SimpleTerm -> Term) => A)(e: (A, Opt[Term]) => B): B = {\n    @tailrec\n    def rec(acc: A, current: CaseBranches): B = current match {\n      case Case(pat, body, rest) => rec(f(acc, pat -> body), rest)\n      case Wildcard(body) => e(acc, S(body))\n      case NoCases => e(acc, N)\n    }\n    rec(z, this)\n  }\n\n  def foreach(f: Opt[SimpleTerm] -> Term => Unit): Unit = {\n    @tailrec\n    def rec(current: CaseBranches): Unit = current match {\n      case Case(pat, body, rest) => f(S(pat) -> body); rec(rest)\n      case Wildcard(body) => f(N -> body)\n      case NoCases => ()\n    }\n    rec(this)\n  }\n  def showIn(implicit ctx: ShowCtx): Str = this match {\n    case Case(pat, body, rest) =>\n      ctx.lnIndStr + pat.showIn(false) + \" => \" + body.showIn(false) + rest.showIn\n    case Wildcard(body) => \n      ctx.lnIndStr + \"_ => \" + body.showIn(false)\n    case NoCases => \"\"\n  }\n}\n\ntrait AdtMatchPatImpl extends Located { self: AdtMatchPat =>\n  def children: List[Located] = pat :: rhs :: Nil\n  override def toString: String = s\"($pat) then $rhs\"\n}\n\ntrait IfBodyImpl extends Located { self: IfBody =>\n  \n  def children: List[Located] = this match {\n    case IfBlock(ts) => ts.map(_.fold(identity, identity))\n    case IfThen(l, r) => l :: r :: Nil\n    case IfElse(t) => t :: Nil\n    case IfLet(_, v, r, b) => v :: r :: b :: Nil\n    case IfOpApp(t, v, b) => t :: v :: b :: Nil\n    case IfOpsApp(t, ops) => t :: ops.flatMap(x => x._1 :: x._2 :: Nil)\n  }\n  \n  def showDbg: String = this match {\n    case IfThen(lhs, rhs) => s\"(${lhs.showDbg}) then ${rhs.showDbg}\"\n    case IfElse(trm) => s\"else ${trm.showDbg}\"\n    case IfBlock(ts) => s\"‹${ts.iterator.map(_.fold(_.showDbg, _.showDbg)).mkString(\"; \")}›\"\n    case IfOpApp(lhs, op, ib) => s\"${lhs.showDbg} ${op.showDbg} ${ib.showDbg}\"\n    case IfOpsApp(lhs, ops) => s\"${lhs.showDbg} ‹${ops.iterator.map{case(v, r) => s\"· ${v.showDbg} ${r.showDbg}\"}.mkString(\"; \")}›\"\n    case IfLet(isRec, v, r, b) => s\"${if (isRec) \"rec \" else \"\"}let ${v.showDbg} = ${r.showDbg} in ${b.showDbg}\"\n  }\n\n  def showIn(implicit ctx: ShowCtx): Str = this match {\n    case IfThen(lhs, rhs) => s\"${lhs.showIn(!lhs.isInstanceOf[SimpleTerm])} then ${rhs.showIn(false)}\"\n    case IfElse(trm) => s\"else ${trm.showIn(false)}\"\n    case IfBlock(ts) => s\"${ts.map(_.fold(identity, identity)).mkString(ctx.lnIndStr)}\"\n    case IfOpApp(lhs, op, ib) => s\"${lhs.showIn(false)} ${op.showIn(false)} ${ib.showIn}\"\n    case IfOpsApp(lhs, ops) => s\"${lhs.showIn(false)} ${ops.iterator.map{case(v, r) => s\"· $v $r\"}.mkString(ctx.lnIndStr)}\"\n    case IfLet(isRec, v, r, b) => s\"${if (isRec) \"rec \" else \"\"}let ${v.showIn(false)} = ${r.showIn(false)} in ${b.showIn}\"\n  }\n}\n\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/package.scala",
    "content": "import mlscript.utils._\nimport mlscript.utils.shorthands._\n\npackage object mlscript {\n  \n  type Raise = Diagnostic => Unit\n  \n  val ExtrusionPrefix: Str = \"??\"\n  \n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/pretyper/Diagnosable.scala",
    "content": "package mlscript\npackage pretyper\n\nimport scala.collection.mutable.Buffer\nimport Diagnostic.Source, Message.MessageContext\nimport mlscript.utils._, shorthands._\n\n/**\n  * A trait containing a mutable buffer of diagnostics.\n  */\ntrait Diagnosable {\n  private val diagnosticBuffer = Buffer.empty[Diagnostic]\n  \n  protected def raise(diagnostics: Diagnostic): Unit =\n    diagnosticBuffer += diagnostics\n\n  protected def raiseMany(diagnostics: IterableOnce[Diagnostic]): Unit =\n    diagnosticBuffer ++= diagnostics\n\n  protected def raiseError(source: Source, messages: (Message -> Opt[Loc])*): Unit =\n    raise(ErrorReport(messages.toList, newDefs = true, source))\n\n  protected def raiseWarning(source: Source, messages: (Message -> Opt[Loc])*): Unit =\n    raise(WarningReport(messages.toList, newDefs = true, source))\n\n  @inline final def filterDiagnostics(f: Diagnostic => Bool): Ls[Diagnostic] =\n    diagnosticBuffer.iterator.filter(f).toList\n\n  @inline final def getDiagnostics: Ls[Diagnostic] = diagnosticBuffer.toList\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/pretyper/PreTyper.scala",
    "content": "package mlscript\npackage pretyper\n\nimport annotation.tailrec, collection.mutable.{Set => MutSet}, collection.immutable.SortedMap, util.chaining._\nimport utils._, shorthands._, Diagnostic.PreTyping, Message.MessageContext, symbol._, ucs.Desugarer\n\nclass PreTyper extends Traceable with Diagnosable with Desugarer {\n  /** A shorthand function to raise errors without specifying the source. */\n  protected def raiseError(messages: (Message -> Opt[Loc])*): Unit =\n    raiseError(PreTyping, messages: _*)\n\n  /** A shorthand function to raise warnings without specifying the source. */\n  protected def raiseWarning(messages: (Message -> Opt[Loc])*): Unit =\n    raiseWarning(PreTyping, messages: _*)\n\n  private def extractParameters(fields: Term): Ls[LocalTermSymbol] = {\n    def rec(term: Term): Iterator[LocalTermSymbol] = term match {\n      case nme: Var => Iterator.single(new LocalTermSymbol(nme))\n      case Bra(false, term) => rec(term)\n      case Bra(true, Rcd(fields)) =>\n        fields.iterator.flatMap { case (_, Fld(_, pat)) => rec(pat) }\n      case Asc(term, _) => rec(term)\n      case literal: Lit =>\n        raiseWarning(msg\"literal patterns are ignored\" -> literal.toLoc)\n        Iterator.empty\n      case App(Var(name), parameters) if name.isCapitalized => rec(parameters)\n      case Tup(arguments) =>\n        arguments.iterator.flatMap {\n          case (S(nme: Var), Fld(_, _)) => Iterator.single(new LocalTermSymbol(nme))\n          case (N, Fld(_, term)) => rec(term)\n        }\n      case PlainTup(arguments @ _*) => arguments.iterator.flatMap(extractParameters)\n      case other =>\n        raiseError(msg\"unsupported pattern shape\" -> other.toLoc)\n        Iterator.empty\n    }\n    rec(fields).tap { rs =>\n      println(s\"extractParameters ${fields.showDbg} ==> ${rs.map(_.name).mkString(\", \")}\")\n    }.toList\n  }\n\n  protected def resolveVar(v: Var)(implicit scope: Scope): Unit =\n    scope.getTermSymbol(v.name) match {\n      case S(sym: LocalTermSymbol) =>\n        println(s\"resolveVar `${v.name}` ==> local term\")\n        v.symbol = sym\n      case S(sym: DefinedTermSymbol) =>\n        println(s\"resolveVar `${v.name}` ==> defined term\")\n        v.symbol = sym\n      case S(sym: ModuleSymbol) =>\n        println(s\"resolveVar `${v.name}` ==> module\")\n        v.symbol = sym\n      case N => \n        scope.getTypeSymbol(v.name) match {\n          case S(sym: ClassSymbol) =>\n            println(s\"resolveVar `${v.name}` ==> class\")\n            v.symbol = sym\n          case S(_) =>\n            raiseError(msg\"identifier `${v.name}` is resolved to a type\" -> v.toLoc)\n          case N =>\n            raiseError(msg\"identifier `${v.name}` not found\" -> v.toLoc)\n        }\n    }\n\n  protected def traverseVar(v: Var)(implicit scope: Scope): Unit =\n    trace(s\"traverseVar(name = \\\"${v.name}\\\")\") {\n      v.symbolOption match {\n        case N => resolveVar(v)\n        case S(symbol) => scope.getSymbols(v.name) match {\n          case Nil => raiseError(msg\"identifier `${v.name}` not found\" -> v.toLoc)\n          case symbols if symbols.contains(symbol) => ()\n          case symbols =>\n            def toNameLoc(symbol: Symbol): (Str, Opt[Loc]) = symbol match {\n              case ds: DummyClassSymbol => s\"`${ds.name}`\" -> N\n              case ts: TypeSymbol => s\"`${ts.name}`\" -> ts.defn.toLoc\n              case ls: LocalTermSymbol => s\"local `${ls.name}`\" -> ls.nme.toLoc\n              case dt: DefinedTermSymbol => s\"`${dt.name}`\" -> dt.defn.toLoc\n            }\n            val (name, loc) = toNameLoc(symbol)\n            raiseError(\n              (msg\"identifier ${v.name} refers to different symbols.\" -> v.toLoc ::\n                msg\"it is resolved to $name\" -> loc ::\n                symbols.map { s =>\n                  val (name, loc) = toNameLoc(s)\n                  msg\"it was previously resolved to $name\" -> loc\n                }): _*\n            )\n        }\n      }\n    }()\n\n  protected def traverseTerm(term: Term)(implicit scope: Scope): Unit =\n    trace(s\"traverseTerm <== ${term.showDbg}\") {\n      term match {\n        case Assign(lhs, rhs) => traverseTerm(lhs); traverseTerm(rhs)\n        case Bra(_, trm) => traverseTerm(trm)\n        case Lam(lhs, rhs) =>\n          traverseTerm(rhs)(scope ++ extractParameters(lhs))\n        case Sel(receiver, fieldName) => traverseTerm(receiver)\n        case Let(isRec, nme, rhs, body) =>\n          traverseTerm(rhs)\n          traverseTerm(body)(scope + new LocalTermSymbol(nme))\n        case New(head, body) =>\n          // `new C(...)` or `new C(){...}` or `new{...}`\n        case Tup(fields) => fields.foreach {\n          case (S(t), Fld(_, _)) => traverseTerm(t)\n          case (N, Fld(_, t)) => traverseTerm(t)\n        }\n        case Asc(trm, ty) => traverseTerm(trm)\n        case ef @ If(_, _) => traverseIf(ef)(scope)\n        case TyApp(lhs, targs) =>\n          // Be consistent with the error message from `Typer`.\n          raiseError(msg\"type application syntax is not yet supported\" -> term.toLoc)\n        case Eqn(lhs, rhs) =>\n          raiseWarning(msg\"unsupported `Eqn`: ${term.showDbg}\" -> term.toLoc)\n        case Blk(stmts) =>\n          traverseStatements(stmts, \"block\", scope)\n          ()\n        case Subs(arr, idx) => traverseTerm(arr); traverseTerm(idx)\n        case Bind(lhs, rhs) => traverseTerm(lhs); traverseTerm(rhs)\n        case Splc(fields) => fields.foreach {\n          case L(t) => traverseTerm(t)\n          case R(Fld(_, t)) => traverseTerm(t)\n        }\n        case Forall(params, body) => traverseTerm(body)\n        case Rcd(fields) => fields.foreach { case (_, Fld(_, t)) => traverseTerm(t) }\n        case CaseOf(trm, cases) => \n        case With(trm, fields) => traverseTerm(trm); traverseTerm(fields)\n        case Where(body, where) =>\n          raiseWarning(msg\"unsupported `Where`: ${term.showDbg}\" -> term.toLoc)\n        // begin UCS shorthands ================================================\n        //  * Old-style operators\n        case App(App(Var(\"is\"), _), _) =>\n          println(s\"found UCS shorthand: ${term.showDbg}\")\n          val desugared = If(IfThen(term, Var(\"true\")), S(Var(\"false\")))\n          traverseIf(desugared)\n          term.desugaredTerm = desugared.desugaredTerm\n        case App(Var(\"is\"), _) =>\n          println(s\"found UCS shorthand: ${term.showDbg}\")\n          val desugared = If(IfThen(term, Var(\"true\")), S(Var(\"false\")))\n          traverseIf(desugared)\n          term.desugaredTerm = desugared.desugaredTerm\n        //  * Old-style operators\n        case App(App(Var(\"and\"), PlainTup(lhs)), PlainTup(rhs)) =>\n          println(s\"found UCS shorthand: ${term.showDbg}\")\n          val desugared = If(IfThen(lhs, rhs), S(Var(\"false\")))\n          traverseIf(desugared)\n          term.desugaredTerm = desugared.desugaredTerm\n        case App(Var(\"and\"), PlainTup(lhs, rhs)) =>\n          println(s\"found UCS shorthand: ${term.showDbg}\")\n          val desugared = If(IfThen(lhs, rhs), S(Var(\"false\")))\n          traverseIf(desugared)\n          term.desugaredTerm = desugared.desugaredTerm\n        // end UCS shorthands ==================================================\n        case App(lhs, Tup(fields)) =>\n          traverseTerm(lhs)\n          fields.foreach { _._2.value |> traverseTerm }\n        case App(lhs, rhs) => traverseTerm(lhs); traverseTerm(rhs)\n        case Test(trm, ty) => traverseTerm(trm)\n        case _: Lit | _: Super => ()\n        case v: Var => traverseVar(v)\n        case AdtMatchWith(cond, arms) =>\n          raiseWarning(msg\"unsupported `AdtMatchWith`: ${term.showDbg}\" -> term.toLoc)\n        case Inst(body) => traverseTerm(body)\n        case NuNew(cls) => traverseTerm(cls)\n        case Rft(base, decls) => // For object refinement\n          traverseTerm(base)\n          traverseStatements(decls.entities, \"Rft\", scope)\n          ()\n        case While(cond, body) =>\n          traverseTerm(cond)\n          traverseTerm(body)\n        case Ann(ann, receiver) => traverseTerm(receiver)\n        case Quoted(body) => traverseTerm(body)\n        case Unquoted(body) => traverseTerm(body)\n      }\n    }(_ => s\"traverseTerm ==> ${term.showDbg}\")\n\n  private def traverseTypeDefinition(symbol: TypeSymbol, defn: NuTypeDef)(implicit scope: Scope): Unit =\n    trace(s\"traverseTypeDefinition <== ${defn.describe}\") {\n      traverseStatements(defn.body.entities, defn.nme.name, scope)\n      ()\n    }(_ => s\"traverseTypeDefinition <== ${defn.describe}\")\n\n  private def traverseStatements(statements: Ls[Statement], name: Str, parentScope: Scope): Scope =\n    trace(s\"traverseStatements <== $name: ${\"statement\".pluralize(statements.size, true)}\") {\n      // Pass 1: Build a scope with type symbols only.\n      val typeSymbols = statements.collect { case t: NuTypeDef => TypeSymbol(t) }\n      val scopeWithTypes = parentScope.derive ++ typeSymbols\n      println(typeSymbols.iterator.map(_.name).mkString(\"type symbols: {\", \", \", \"}\"))\n      // Pass 1.1: Resolve parent type symbols.\n      typeSymbols.foreach {\n        case s: ClassLikeSymbol => s.parentTypeNames.foreach { nme =>\n          scopeWithTypes.getTypeSymbol(nme.name) match {\n            case S(symbol) => nme.symbol = symbol\n            case N => raiseError(msg\"could not find definition `${nme.name}`\" -> nme.toLoc)\n          }\n        }\n        case _ => ()\n      }\n      // Pass 2: Build a complete scope and collect definitional terms and terms to be traversed.\n      val (completeScope, thingsToTraverse) = statements.foldLeft[(Scope, Ls[(Term \\/ DefinedTermSymbol, Scope)])](scopeWithTypes, Nil) {\n        case ((scope, acc), term: Term) => (scope, (L(term), scope) :: acc)\n        case ((scope, acc), defn: NuFunDef) =>\n          val termSymbol = new DefinedTermSymbol(defn)\n          val scopeWithSymbol = scope + termSymbol\n          (scopeWithSymbol, (R(termSymbol), if (termSymbol.isRecursive) scopeWithSymbol else scope) :: acc)\n        case (acc, _: NuTypeDef) => acc // Ignore type definitions.\n        case (acc, other @ (_: Constructor | _: DataDefn | _: DatatypeDefn | _: Def | _: LetS | _: TypeDef)) =>\n          println(s\"unknown statement: ${other.getClass.getSimpleName}\")\n          acc\n      }\n      // Pass 2.5: Traverse type definitions\n      statements.iterator.flatMap { case defn: NuTypeDef => S(defn); case _ => N }.foreach { defn =>\n        val parameters = defn.params.map(extractParameters).getOrElse(Nil)\n        val thisSymbol = new LocalTermSymbol(Var(\"this\"))\n        traverseTypeDefinition(TypeSymbol(defn), defn)(completeScope ++ (thisSymbol :: parameters))\n      }\n      println(thingsToTraverse.iterator.map {\n        case (L(term), _) => term.showDbg\n        case (R(symbol), _) => symbol.name\n      }.mkString(\"to be traversed: {\", \", \", \"}\"))\n      // Pass 3: Traverse terms collected from the last pass.\n      println(\"Pass 3\")\n      thingsToTraverse.foreach {\n        case (L(term), scope) =>\n          println(\"traverseTerm: \" + term.showDbg)\n          println(\"scope: \" + scope.showLocalSymbols)\n          traverseTerm(term)(scope)\n        case (R(symbol), scope) => symbol.body match {\n          case L(term) =>\n            if (symbol.isFunction) {\n              traverseTerm(term)(completeScope)\n            } else {\n              traverseTerm(term)(scope)\n            }\n          case R(_) => ()\n        }\n      }\n      completeScope\n    }({ scope => s\"traverseStatements ==> Scope {${scope.showLocalSymbols}}\" })\n\n  def apply(typingUnit: TypingUnit, scope: Scope, name: Str): Scope =\n    trace(s\"PreTyper <== $name: ${typingUnit.describe}\") {\n      traverseStatements(typingUnit.entities, name, scope)\n    }({ scope => s\"PreTyper ==> ${scope.showLocalSymbols}\" })\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/pretyper/Scope.scala",
    "content": "package mlscript\npackage pretyper\n\nimport annotation.tailrec, collection.immutable.Map\nimport utils._, shorthands._, symbol._\n\nfinal class Scope(val enclosing: Opt[Scope], val types: Map[Str, TypeSymbol], val terms: Map[Str, TermSymbol]) {\n  import Scope._\n\n\n  @tailrec\n  final def getTypeSymbol(name: Str): Opt[TypeSymbol] =\n    types.get(name) match {\n      case entry @ S(_) => entry\n      case N => enclosing match {\n        case N => N\n        case S(scope) => scope.getTypeSymbol(name)\n      }\n    }\n\n  @tailrec\n  final def getTermSymbol(name: Str): Opt[TermSymbol] =\n    terms.get(name) match {\n      case entry @ S(_) => entry\n      case N => enclosing match {\n        case N => N\n        case S(scope) => scope.getTermSymbol(name)\n      }\n    }\n  \n  final def getSymbols(name: Str): Ls[Symbol] = Ls.concat(getTypeSymbol(name), getTermSymbol(name))\n\n  @inline\n  def +(sym: Symbol): Scope = sym match {\n    case symbol: ModuleSymbol => new Scope(enclosing, types + (symbol.name -> symbol), terms + (symbol.name -> symbol))\n    case symbol: TypeSymbol => new Scope(enclosing, types + (symbol.name -> symbol), terms)\n    case symbol: DefinedTermSymbol =>\n      val newTerms = terms + (symbol.name -> symbol)\n      new Scope(enclosing, types, symbol.operatorAlias match {\n        case N => newTerms\n        case S(alias) => newTerms + (alias.name -> symbol)\n      })\n    case symbol: TermSymbol => new Scope(enclosing, types, terms + (symbol.name -> symbol))\n  }\n\n  @inline\n  def ++(symbols: IterableOnce[Symbol]): Scope = {\n    val (newTypes, newTerms) = partitionSymbols((types, terms), symbols)\n    new Scope(enclosing, newTypes, newTerms)\n  }\n\n  def withEntries(syms: IterableOnce[Var -> Symbol]): Scope = {\n    val (newTypes, newTerms) = syms.iterator.foldLeft((types, terms)) {\n      case ((types, terms), (nme, symbol: ModuleSymbol)) => (types + (nme.name -> symbol), terms + (nme.name -> symbol))\n      case ((types, terms), (nme, symbol: TypeSymbol)) => (types + (nme.name -> symbol), terms)\n      case ((types, terms), (nme, symbol: TermSymbol)) => (types, terms + (nme.name -> symbol))\n    }\n    new Scope(enclosing, newTypes, newTerms)\n  }\n\n  @inline\n  def symbols: Iterator[Symbol] = Iterator.concat[Symbol](types.values, terms.values)\n\n  def derive: Scope = new Scope(S(this), Map.empty, Map.empty)\n\n  def derive(symbols: IterableOnce[Symbol]): Scope = {\n    val (newTypes, newTerms) = partitionSymbols((types, terms), symbols)\n    new Scope(S(this), newTypes, newTerms)\n  }\n\n  def showLocalSymbols: Str = symbols.iterator.map(_.name).mkString(\", \")\n}\n\nobject Scope {\n  def partitionSymbols(\n      z: (Map[Str, TypeSymbol], Map[Str, TermSymbol]),\n      symbols: IterableOnce[Symbol]\n  ): (Map[Str, TypeSymbol], Map[Str, TermSymbol]) =\n    symbols.iterator.foldLeft((z._1, z._2)) {\n      case ((types, terms), symbol: ModuleSymbol) => (types + (symbol.name -> symbol), terms + (symbol.name -> symbol))\n      case ((types, terms), symbol: TypeSymbol) => (types + (symbol.name -> symbol), terms)\n      case ((types, terms), symbol: DefinedTermSymbol) =>\n        (types, terms + (symbol.name -> symbol) ++ symbol.operatorAlias.map(_.name -> symbol))\n      case ((types, terms), symbol: TermSymbol) => (types, terms + (symbol.name -> symbol))\n    }\n\n  def from(symbols: IterableOnce[Symbol]): Scope = {\n    val (newTypes, newTerms) = partitionSymbols((Map.empty, Map.empty), symbols)\n    new Scope(N, newTypes, newTerms)\n  }\n\n  val global: Scope = {\n    def mod(name: Str) = NuTypeDef(Mod, TypeName(name), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, N, Nil)\n    // def cls(name: Str) = NuTypeDef(Trt, TypeName(name), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, N)\n    def als(name: Str) = NuTypeDef(Als, TypeName(name), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, N, Nil)\n    val builtinTypes = Ls(\n      new ModuleSymbol(mod(\"true\"), Nil),\n      new ModuleSymbol(mod(\"false\"), Nil),\n      new TypeAliasSymbol(als(\"nothing\")),\n      new DummyClassSymbol(Var(\"Object\")),\n      new DummyClassSymbol(Var(\"Int\")),\n      new DummyClassSymbol(Var(\"Num\")),\n      new DummyClassSymbol(Var(\"Str\")),\n      new DummyClassSymbol(Var(\"Bool\")),\n    )\n    val commaSymbol = new LocalTermSymbol(Var(\",\"))\n    Scope.from(\n      \"\"\"true,false,document,window,typeof,toString,not,succ,log,discard,negate,\n        |round,add,sub,mul,div,sqrt,lt,le,gt,ge,slt,sle,sgt,sge,length,concat,\n        |join,eq,ne,error,id,if,emptyArray,\n        |+,-,*,%,/,**,<,>,<=,>=,==,===,<>,&&,||,and,\n        |numAdd,numSub,numMul,NaN\"\"\"\n        .stripMargin\n        .split(\",\")\n        .iterator\n        .map(_.trim)\n        .map(name => new LocalTermSymbol(Var(name)))\n        .concat(commaSymbol :: builtinTypes)\n    )\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/pretyper/Symbol.scala",
    "content": "package mlscript\npackage pretyper\n\nimport annotation.tailrec, collection.immutable.SortedSet\nimport utils._, shorthands._, ucs.context.Matchable\n\npackage object symbol {\n  sealed trait Symbol {\n    def name: Str\n\n    def typeSymbolOption: Opt[TypeSymbol] = this match {\n      case symbol: TypeSymbol => S(symbol)\n      case _ => N\n    }\n    def termSymbolOption: Opt[TermSymbol] = this match {\n      case symbol: TermSymbol => S(symbol)\n      case _ => N\n    }\n  }\n\n  sealed trait TypeSymbol extends Symbol {\n    def defn: NuTypeDef\n    \n    override def name: Str = defn.name\n\n    def showDbg: Str = s\"${defn.kind.str} $name\"\n  }\n\n  object TypeSymbol {\n    def apply(defn: NuTypeDef): TypeSymbol =\n      defn.kind match {\n        case Cls => new ClassSymbol(defn, extractSuperTypes(defn.parents))\n        case Als => new TypeAliasSymbol(defn)\n        case Mxn => new MixinSymbol(defn)\n        case Trt => new TraitSymbol(defn, extractSuperTypes(defn.parents))\n        case Mod => new ModuleSymbol(defn, extractSuperTypes(defn.parents))\n      }\n    def unapply(symbol: TypeSymbol): Opt[NuTypeDef] = S(symbol.defn)\n\n    private def extractSuperTypes(parents: Ls[Term]): Ls[Var] = {\n      @tailrec\n      def rec(acc: Ls[Var], rest: Ls[Term]): Ls[Var] =\n        rest match {\n          case Nil => acc.reverse\n          case (nme: Var) :: tail => rec(nme :: acc, tail)\n          case (TyApp(ty, _)) :: tail => rec(acc, ty :: tail)\n          case (App(term, Tup(_))) :: tail => rec(acc, term :: tail)\n          case head :: _ =>\n            lastWords(s\"unknown type in parent types: ${head.showDbg}\")\n        }\n      rec(Nil, parents)\n    }\n  }\n\n  /**\n    * When a type symbol is not defined and we must need a symbol in some\n    * scenarios, we use a dummy symbol to represent it.\n    *\n    * @param nme the name of the expect type symbol.\n    */\n  final class DummyClassSymbol(val nme: Var) extends ClassLikeSymbol {\n    override val parentTypeNames: Ls[Var] = Nil\n    \n    override def defn: NuTypeDef = die\n\n    override def name: Str = nme.name\n\n    override def showDbg: Str = s\"dummy class $name\"\n  }\n\n  trait ClassLikeSymbol extends TypeSymbol {\n    val parentTypeNames: Ls[Var]\n\n    private val _baseClassLikeSymbols: Lazy[SortedSet[ClassLikeSymbol]] = mlscript.utils.Lazy({\n      implicit val ord: Ordering[ClassLikeSymbol] = new Ordering[ClassLikeSymbol] {\n        override def compare(x: ClassLikeSymbol, y: ClassLikeSymbol): Int =\n          x.name.compareTo(y.name)\n      }\n      val parentClassLikeSymbols = parentTypeNames.iterator.map(_.symbol).collect {\n        case s: ClassLikeSymbol => s\n      }.toList\n      SortedSet.from(\n        parentClassLikeSymbols.iterator ++\n        parentClassLikeSymbols.iterator.flatMap(_.baseClassLikeSymbols))\n    })\n\n    lazy val baseClassLikeSymbols: SortedSet[ClassLikeSymbol] = _baseClassLikeSymbols.force_!\n\n    def <:<(that: ClassLikeSymbol): Bool =\n      this === that || baseClassLikeSymbols.contains(that)\n  }\n\n  final class ClassSymbol(\n    override val defn: NuTypeDef,\n    override val parentTypeNames: Ls[Var]\n  ) extends ClassLikeSymbol {\n    require(defn.kind === Cls)\n  }\n\n  final class TraitSymbol(\n    override val defn: NuTypeDef,\n    override val parentTypeNames: Ls[Var]\n  ) extends ClassLikeSymbol {\n    require(defn.kind === Trt)\n  }\n\n  final class MixinSymbol(override val defn: NuTypeDef) extends TypeSymbol {\n    require(defn.kind === Mxn)\n  }\n\n  final class TypeAliasSymbol(override val defn: NuTypeDef) extends TypeSymbol {\n    require(defn.kind === Als)\n  }\n\n  final class ModuleSymbol(\n    override val defn: NuTypeDef,\n    override val parentTypeNames: Ls[Var]\n  ) extends ClassLikeSymbol with TermSymbol {\n    require(defn.kind === Mod)\n\n    override def nameVar: Var = defn.nameVar\n  }\n\n  sealed trait TermSymbol extends Symbol with Matchable {\n    def nameVar: Var\n  }\n\n  class DefinedTermSymbol(val defn: NuFunDef) extends TermSymbol {\n    override def name: Str = defn.name\n\n    override def nameVar: Var = defn.nme\n\n    def body: Term \\/ Type = defn.rhs\n\n    def isFunction: Bool = defn.isLetRec.isEmpty\n\n    def isRecursive: Bool = defn.isLetRec.getOrElse(true)\n\n    def isDeclaration: Bool = defn.rhs.isRight\n\n    def operatorAlias: Opt[Var] = defn.symbolicNme\n\n    def declaredLoc: Opt[Loc] = defn.nme.toLoc\n  }\n\n  class LocalTermSymbol(val nme: Var) extends TermSymbol {\n    override def name: Str = nme.name\n\n    override def nameVar: Var = nme\n  }\n\n  trait Symbolic {\n    val name: String\n\n    private var _symbol: Opt[Symbol] = N\n\n    def symbolOption: Opt[Symbol] = _symbol\n    def symbol: Symbol = _symbol.getOrElse(lastWords(s\"Symbol not set for $name\"))\n    def symbol_=(symbol: Symbol): Unit =\n      _symbol match {\n        case N => _symbol = S(symbol)\n        case S(`symbol`) => ()\n        case S(current) =>\n          println(s\"symbol: old ${current.name} vs new ${symbol.name}\")\n          lastWords(s\"Symbol already set for $name\")\n      }\n    def withSymbol(symbol: Symbol): this.type = { this.symbol = symbol; this }\n\n    def getClassLikeSymbol: Opt[ClassLikeSymbol] = _symbol.collectFirst {\n      case symbol: ClassLikeSymbol => symbol\n    }\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/pretyper/Traceable.scala",
    "content": "package mlscript\npackage pretyper\n\nimport utils._, shorthands._\n\ntrait Traceable {\n  /**\n    * The set of topics to debug. Explanation of possible values.\n    * - `N`: Show nothing.\n    * - `S(Set.empty)`: Show everything.\n    * - `S(someTopics)`: Show only the topics in `someTopics`.\n    * Override this function to enable debugging.\n    */\n  protected def debugTopicFilters: Opt[Set[Str]] = N\n  private var debugIndent = 0\n  private var currentDebugTopics: Opt[Str] = N\n\n  private def matchTopicFilters: Boolean =\n    debugTopicFilters match {\n      case S(topics) if topics.isEmpty => true\n      case S(topics) => currentDebugTopics.fold(false)(topics)\n      case N => false\n    }\n\n  /** Override this function to redirect debug messages. */\n  protected def emitString(str: Str): Unit = scala.Predef.println(str)\n  \n  @inline private def printLineByLine(x: => Any, withIndent: Bool): Unit =\n    x.toString.linesIterator.foreach(\n      if (withIndent)\n        line => emitString(\"| \" * debugIndent + line)\n      else\n        emitString\n    )\n\n  protected def trace[T](pre: => Str)(thunk: => T)(post: T => Str = Traceable.noPostTrace): T = {\n    println(pre)\n    debugIndent += 1\n    val res = try thunk finally debugIndent -= 1\n    if (post isnt Traceable.noPostTrace) println(post(res))\n    res\n  }\n\n  protected def traceWithTopic[T](currentDebugTopics: Str)(thunk: => T): T = {\n    this.currentDebugTopics = S(currentDebugTopics)\n    val res = thunk\n    this.currentDebugTopics = N\n    res\n  }\n\n  @inline def traceNot[T](pre: => Str)(thunk: => T)(post: T => Str = Traceable.noPostTrace): T =\n    thunk\n  \n  @inline protected def println(x: => Any, withIndent: Bool = true, force: Bool = false): Unit =\n    if (force || matchTopicFilters) printLineByLine(x, withIndent)\n}\n\nobject Traceable {\n  val noPostTrace: Any => Str = _ => \"\"\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/syntax.scala",
    "content": "package mlscript\n\nimport mlscript.utils._, shorthands._\n\n\n// Terms\n\nfinal case class Pgrm(tops: Ls[Statement]) extends PgrmImpl\n\nsealed abstract class Decl extends DesugaredStatement with DeclImpl\nfinal case class Def(rec: Bool, nme: Var, rhs: Term \\/ Type, isByname: Bool) extends Decl with Terms {\n  val body: Located = rhs.fold(identity, identity)\n}\n\nfinal case class AdtInfo(ctorName: TypeName)\n\nfinal case class TypeDef(\n  kind: TypeDefKind,\n  nme: TypeName,\n  tparams: List[TypeName],\n  body: Type,\n  mthDecls: List[MethodDef[Right[Term, Type]]],\n  mthDefs: List[MethodDef[Left[Term, Type]]],\n  positionals: Ls[Var],\n  adtInfo: Opt[AdtInfo],\n) extends Decl\n\n/**\n  * Method type can be a definition or a declaration based\n  * on the type parameter set. A declaration has `Type` in rhs\n  * and definition has `Term` in rhs.\n  *\n  * @param rec indicates that the method is recursive\n  * @param prt name of class to which method belongs\n  * @param nme name of method\n  * @param tparams list of parameters for the method if any\n  * @param rhs term or type if definition and declaration respectively\n  */\nfinal case class MethodDef[RHS <: Term \\/ Type](\n  rec: Bool,\n  parent: TypeName,\n  nme: Var,\n  tparams: List[TypeName],\n  rhs: RHS,\n) extends Located {\n  val body: Located = rhs.fold(identity, identity)\n  val children: Ls[Located] = nme :: body :: Nil\n}\n\nsealed trait NameRef extends Located { val name: Str; def toVar: Var }\n\nsealed abstract class OuterKind(val str: Str)\ncase object Block extends OuterKind(\"block\")\nsealed abstract class DeclKind(str: Str) extends OuterKind(str)\ncase object Val extends DeclKind(\"value\")\nsealed abstract class TypeDefKind(str: Str) extends DeclKind(str)\nsealed trait ObjDefKind\nsealed trait ClsLikeKind extends ObjDefKind\ncase object Cls extends TypeDefKind(\"class\") with ClsLikeKind\ncase object Trt extends TypeDefKind(\"trait\") with ObjDefKind\ncase object Mxn extends TypeDefKind(\"mixin\")\ncase object Als extends TypeDefKind(\"type alias\")\ncase object Mod extends TypeDefKind(\"module\") with ClsLikeKind\n\nsealed abstract class Term                                           extends Terms with TermImpl\nsealed abstract class Lit                                            extends SimpleTerm with LitImpl\nfinal case class Var(name: Str)                                      extends SimpleTerm with VarImpl with NameRef\nfinal case class Lam(lhs: Term, rhs: Term)                           extends Term\nfinal case class App(lhs: Term, rhs: Term)                           extends Term\nfinal case class Tup(fields: Ls[Opt[Var] -> Fld])                    extends Term with TupImpl\nfinal case class Rcd(fields: Ls[Var -> Fld])                         extends Term\nfinal case class Sel(receiver: Term, fieldName: Var)                 extends Term\nfinal case class Let(isRec: Bool, name: Var, rhs: Term, body: Term)  extends Term\nfinal case class Blk(stmts: Ls[Statement])                           extends Term with BlkImpl with Outer\nfinal case class Bra(rcd: Bool, trm: Term)                           extends Term\nfinal case class Asc(trm: Term, ty: Type)                            extends Term\nfinal case class Bind(lhs: Term, rhs: Term)                          extends Term\nfinal case class Test(trm: Term, ty: Term)                           extends Term\nfinal case class With(trm: Term, fields: Rcd)                        extends Term\nfinal case class CaseOf(trm: Term, cases: CaseBranches)              extends Term with CaseOfImpl\nfinal case class Subs(arr: Term, idx: Term)                          extends Term\nfinal case class Assign(lhs: Term, rhs: Term)                        extends Term\nfinal case class Splc(fields: Ls[Either[Term, Fld]])                 extends Term\nfinal case class New(head: Opt[(NamedType, Term)], body: TypingUnit) extends Term // `new C(...)` or `new C(){...}` or `new{...}`\nfinal case class NuNew(cls: Term) extends Term\nfinal case class If(body: IfBody, els: Opt[Term])                    extends Term\nfinal case class TyApp(lhs: Term, targs: Ls[Type])                   extends Term\nfinal case class Where(body: Term, where: Ls[Statement])             extends Term\nfinal case class Forall(params: Ls[TypeVar], body: Term)             extends Term\nfinal case class Inst(body: Term)                                    extends Term // Explicit instantiation of polymohic term\nfinal case class Super()                                             extends Term\nfinal case class Eqn(lhs: Var, rhs: Term)                            extends Term // equations such as x = y, notably used in constructors; TODO: make lhs a Term\nfinal case class Quoted(body: Term)                                  extends Term \nfinal case class Unquoted(body: Term)                                extends Term \nfinal case class Rft(base: Term, decls: TypingUnit)                  extends Term\nfinal case class While(cond: Term, body: Term)                       extends Term\nfinal case class Ann(ann: Term, receiver: Term)                      extends Term\n\nfinal case class AdtMatchWith(cond: Term, arms: Ls[AdtMatchPat])     extends Term\nfinal case class AdtMatchPat(pat: Term, rhs: Term)                   extends AdtMatchPatImpl\n\nsealed abstract class IfBody extends IfBodyImpl\nfinal case class IfThen(expr: Term, rhs: Term) extends IfBody\nfinal case class IfElse(expr: Term) extends IfBody\nfinal case class IfLet(isRec: Bool, name: Var, rhs: Term, body: IfBody) extends IfBody\nfinal case class IfOpApp(lhs: Term, op: Var, rhs: IfBody) extends IfBody\nfinal case class IfOpsApp(lhs: Term, opsRhss: Ls[Var -> IfBody]) extends IfBody\nfinal case class IfBlock(lines: Ls[IfBody \\/ Statement]) extends IfBody\n// final case class IfApp(fun: Term, opsRhss: Ls[Var -> IfBody]) extends IfBody\n\nfinal case class FldFlags(mut: Bool, spec: Bool, genGetter: Bool) extends FldFlagsImpl // TODO make it a Located and use in diagnostics\nfinal case class Fld(flags: FldFlags, value: Term) extends FldImpl\n\nobject FldFlags { val empty: FldFlags = FldFlags(false, false, false) }\n\nsealed abstract class CaseBranches extends CaseBranchesImpl\nfinal case class Case(pat: SimpleTerm, body: Term, rest: CaseBranches)(val refined: Bool) extends CaseBranches\nfinal case class Wildcard(body: Term) extends CaseBranches\n// final case class TupleCase(numElems: Int, canHaveMore: Bool, body: Term, rest: CaseBranches) extends CaseBranches\nfinal case object NoCases extends CaseBranches\n\nfinal case class IntLit(value: BigInt)            extends Lit\nfinal case class DecLit(value: BigDecimal)        extends Lit\nfinal case class StrLit(value: Str)               extends Lit\nfinal case class UnitLit(undefinedOrNull: Bool)   extends Lit\n\ntrait IdentifiedTerm\n\nsealed abstract class SimpleTerm extends Term with IdentifiedTerm with SimpleTermImpl\n\nsealed trait Statement extends StatementImpl\nfinal case class LetS(isRec: Bool, pat: Term, rhs: Term) extends Statement\nfinal case class DataDefn(body: Term)                    extends Statement\nfinal case class DatatypeDefn(head: Term, body: Term)    extends Statement\n\nsealed trait DesugaredStatement extends Statement with DesugaredStatementImpl\n\nsealed trait Terms extends DesugaredStatement\n\n\n// Types\n\nsealed abstract class TypeLike extends TypeLikeImpl\n\nsealed abstract class Type extends TypeLike with TypeImpl\n\nsealed trait NamedType extends Type { def base: TypeName; def targs: Ls[Type] }\n\nsealed abstract class Composed(val pol: Bool) extends Type with ComposedImpl\n\nfinal case class Union(lhs: Type, rhs: Type)             extends Composed(true)\nfinal case class Inter(lhs: Type, rhs: Type)             extends Composed(false)\nfinal case class Function(lhs: Type, rhs: Type)          extends Type\nfinal case class Record(fields: Ls[Var -> Field])        extends Type\nfinal case class Tuple(fields: Ls[Opt[Var] -> Field])    extends Type\nfinal case class Recursive(uv: TypeVar, body: Type)      extends Type\nfinal case class AppliedType(base: TypeName, targs: List[Type]) extends Type with NamedType\nfinal case class Selection(base: Type, name: TypeName)   extends Type\nfinal case class Neg(base: Type)                         extends Type\nfinal case class Rem(base: Type, names: Ls[Var])         extends Type\nfinal case class Bounds(lb: Type, ub: Type)              extends Type\nfinal case class WithExtension(base: Type, rcd: Record)  extends Type\nfinal case class Splice(fields: Ls[Either[Type, Field]]) extends Type\nfinal case class Constrained(base: TypeLike, tvBounds: Ls[TypeVar -> Bounds], where: Ls[Bounds], tscs: Ls[Ls[(Bool, Type)] -> Ls[Ls[Type]]]) extends Type\n// final case class FirstClassDefn(defn: NuTypeDef)         extends Type // TODO\n// final case class Refinement(base: Type, decls: TypingUnit) extends Type // TODO\n\nfinal case class Field(in: Opt[Type], out: Type)         extends FieldImpl\n\nsealed abstract class NullaryType                        extends Type\n\ncase object Top                                          extends NullaryType\ncase object Bot                                          extends NullaryType\n\n/** Literal type type, e.g. type `0` is a type with only one possible value `0`. */\nfinal case class Literal(lit: Lit)                       extends NullaryType\n\n/** Reference to an existing type with the given name. */\nfinal case class TypeName(name: Str)                     extends NullaryType with NamedType with TypeNameImpl with NameRef\nfinal case class TypeTag (name: Str)                     extends NullaryType\n\nfinal case class TypeVar(val identifier: Int \\/ Str, nameHint: Opt[Str]) extends NullaryType with TypeVarImpl {\n  require(nameHint.isEmpty || identifier.isLeft)\n  // ^ The better data structure to represent this would be an EitherOrBoth\n  override def toString: Str = identifier.fold(\"α\" + _, identity)\n}\n\nfinal case class PolyType(targs: Ls[TypeName \\/ TypeVar], body: Type) extends Type with PolyTypeImpl\n\n\n// New Definitions AST\n\nfinal case class TypingUnit(rawEntities: Ls[Statement]) extends TypingUnitImpl\n// final case class TypingUnit(entities: Ls[Statement]) extends TypeLike with PgrmOrTypingUnit with TypingUnitImpl\n\nfinal case class Signature(members: Ls[NuDecl], result: Opt[Type]) extends TypeLike with SignatureImpl\n\nsealed abstract class NuDecl extends TypeLike with Statement with NuDeclImpl\n\nsealed trait Outer { def kind: OuterKind }\n\nfinal case class NuTypeDef(\n  kind: TypeDefKind,\n  nme: TypeName,\n  tparams: Ls[(Opt[VarianceInfo], TypeName)],\n  params: Opt[Tup], // the specialized parameters for that type\n  ctor: Opt[Constructor],\n  sig: Opt[Type],\n  parents: Ls[Term],\n  superAnnot: Opt[Type],\n  thisAnnot: Opt[Type],\n  body: TypingUnit\n)(val declareLoc: Opt[Loc], val abstractLoc: Opt[Loc], val annotations: Ls[Term])\n  extends NuDecl with Statement with Outer {\n    def isPlainJSClass: Bool = params.isEmpty\n  }\n\nfinal case class NuFunDef(\n  isLetRec: Opt[Bool], // None means it's a `fun`, which is always recursive; Some means it's a `let`/`let rec` or `val`\n  nme: Var,\n  symbolicNme: Opt[Var],\n  tparams: Ls[TypeName],\n  rhs: Term \\/ Type,\n)(\n  val declareLoc: Opt[Loc],\n  val virtualLoc: Opt[Loc], // Some(Loc) means that the function is modified by keyword `virtual`\n  val mutLoc: Opt[Loc],\n  val signature: Opt[NuFunDef],\n  val outer: Opt[Outer],\n  val genField: Bool, // true means it's a `val`; false means it's a `let`\n  val annotations: Ls[Term],\n) extends NuDecl with DesugaredStatement {\n  val body: Located = rhs.fold(identity, identity)\n  def kind: DeclKind = Val\n  val abstractLoc: Opt[Loc] = None\n  \n  def isLetOrLetRec: Bool = isLetRec.isDefined && !genField\n  \n  // If the member has no implementation, it is virtual automatically\n  def isVirtual: Bool = virtualLoc.nonEmpty || rhs.isRight\n  \n  def isMut: Bool = mutLoc.nonEmpty\n  \n  def isGeneralized: Bool = isLetRec.isEmpty || (rhs match {\n    case Left(value) => value.isGeneralizableLam\n    case Right(ty) => false\n  })\n}\n\nfinal case class Constructor(params: Tup, body: Blk) extends DesugaredStatement with ConstructorImpl // constructor(...) { ... }\n\n\n\nfinal case class VarianceInfo(isCovariant: Bool, isContravariant: Bool) {\n  \n  /** Combine two pieces of variance information together\n   */\n  def &&(that: VarianceInfo): VarianceInfo =\n    VarianceInfo(isCovariant && that.isCovariant, isContravariant && that.isContravariant)\n  \n  /*  Flip the current variance if it encounters a contravariant position\n    */\n  def flip: VarianceInfo = VarianceInfo(isContravariant, isCovariant)\n  \n  override def toString: Str = show\n  \n  def show: Str = this match {\n    case (VarianceInfo(true, true)) => \"±\"\n    case (VarianceInfo(false, true)) => \"-\"\n    case (VarianceInfo(true, false)) => \"+\"\n    case (VarianceInfo(false, false)) => \"=\"\n  }\n}\n\nobject VarianceInfo {\n  val bi: VarianceInfo = VarianceInfo(true, true)\n  val co: VarianceInfo = VarianceInfo(true, false)\n  val contra: VarianceInfo = VarianceInfo(false, true)\n  val in: VarianceInfo = VarianceInfo(false, false)\n}\n\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/Desugarer.scala",
    "content": "package mlscript\npackage ucs\n\nimport collection.mutable.{Map => MutMap}\nimport syntax.{source => s, core => c}, stages._, context.{Context, Scrutinee}\nimport mlscript.ucs.display.{showNormalizedTerm, showSplit}\nimport mlscript.pretyper.{PreTyper, Scope}\nimport mlscript.pretyper.symbol._\nimport Message.MessageContext\nimport utils._, shorthands._\n\n/**\n  * The main class of the UCS desugaring.\n  */\ntrait Desugarer extends Transformation\n                with Desugaring\n                with Normalization\n                with PostProcessing \n                with CoverageChecking { self: PreTyper =>\n\n  /** A shorthand function to raise _desugaring_ errors without specifying the source. */\n  protected def raiseDesugaringError(messages: (Message -> Opt[Loc])*): Unit =\n    raiseError(Diagnostic.Desugaring, messages: _*)\n\n  protected def reportUnreachableCase[T <: Located](unreachable: Located, subsumedBy: T, onlyIf: Bool = true): T = {\n    if (onlyIf) raiseDesugaringWarning(\n      msg\"this case is unreachable\" -> unreachable.toLoc,\n      msg\"because it is subsumed by the branch\" -> subsumedBy.toLoc\n    )\n    subsumedBy\n  }\n\n  /** A shorthand function to raise _desugaring_ warnings without specifying the source. */\n  protected def raiseDesugaringWarning(messages: (Message -> Opt[Loc])*): Unit =\n    raiseWarning(Diagnostic.Desugaring, messages: _*)\n\n  /** Create a fresh local symbol for the given `Var`. */\n  protected def freshSymbol(nme: Var): LocalTermSymbol = new LocalTermSymbol(nme)\n\n  /** Common operations of `Var` which can be shared within all stages. */\n  protected implicit class VarOps(nme: Var) {\n    /** Associate the given `Var` with a fresh `ValueSymbol`. */\n    def withFreshSymbol: Var = nme.withSymbol(freshSymbol(nme))\n\n    /**\n      * Expect the given `symbol` to be a class-like symbol. If it is not, we\n      * get or create a dummy class symbol for it. The desugaring can continue\n      * and `Typer` will throw an error for this miuse.\n      */\n    private def requireClassLikeSymbol(symbol: TypeSymbol)(implicit context: Context): ClassLikeSymbol = symbol match {\n      case symbol: ClassLikeSymbol => symbol\n      case symbol: MixinSymbol =>\n        raiseDesugaringError(msg\"Mixins are not allowed in pattern\" -> nme.toLoc)\n        context.getOrCreateDummyClassSymbol(nme)\n      case symbol: TypeAliasSymbol =>\n        raiseDesugaringError(msg\"Type alias is not allowed in pattern\" -> nme.toLoc)\n        context.getOrCreateDummyClassSymbol(nme)\n    }\n\n    /**\n      * If the given `Var` represents a class name, get its associated `ClassSymbol`.\n      *\n      * @param className the class name variable\n      */\n    def getClassLikeSymbol(implicit context: Context): TypeSymbol = {\n      val symbol = nme.symbolOption match {\n        case S(symbol: TypeSymbol) => requireClassLikeSymbol(symbol)\n        case S(symbol: TermSymbol) =>\n          raiseDesugaringError(msg\"variable ${nme.name} is not associated with a class symbol\" -> nme.toLoc)\n          context.getOrCreateDummyClassSymbol(nme)\n        case N =>\n          raiseDesugaringError(msg\"variable ${nme.name} is not associated with any symbols\" -> nme.toLoc)\n          context.getOrCreateDummyClassSymbol(nme)\n      }\n      println(s\"getClassLikeSymbol: ${nme.name} ==> ${symbol.showDbg}\")\n      symbol\n    }\n\n    /**\n      * A short hand for `nme.symbol.getScrutinee` but add a diagnostic message\n      * to a local diagnostic archive if there's any error.\n      */\n    def getOrCreateScrutinee(implicit context: Context): Scrutinee = nme.symbolOption match {\n      case S(symbol: TermSymbol) => symbol.getOrCreateScrutinee\n      case S(otherSymbol) =>\n        raiseDesugaringError(msg\"cannot identifier `${nme.name}` with a scrutinee\" -> nme.toLoc)\n        context.freshScrutinee\n      case N => lastWords(s\"`${nme.name}` should be assoicated with a symbol\")\n    }\n\n    /** Associate the `Var` with a scrutinee and returns the same `Var`. */\n    def withScrutinee(scrutinee: Scrutinee)(implicit context: Context): Var = nme.symbolOption match {\n      case S(symbol: TermSymbol) =>\n        symbol.addScrutinee(scrutinee)\n        nme\n      case S(otherSymbol) =>\n        raiseDesugaringError(msg\"cannot identifier `${nme.name}` with a scrutinee\" -> nme.toLoc)\n        nme\n      case N => lastWords(s\"`${nme.name}` should be assoicated with a symbol\")\n    }\n\n    /**\n      * If the `Var` is associated with a term symbol, returns it. Otherwise,\n      * resolve the term symbol and associate the `Var` with the term symbol.\n      */\n    def getOrResolveTermSymbol(implicit scope: Scope): TermSymbol = {\n      nme.symbolOption match {\n        case N => resolveTermSymbol\n        case S(symbol: TermSymbol) => symbol\n        case S(otherSymbol) =>\n          raiseDesugaringError(msg\"identifier `${nme.name}` should be a term\" -> nme.toLoc)\n          freshSymbol(nme)\n      }\n    }\n\n    /** Associate the `Var` with a term symbol and returns the term symbol. */\n    def resolveTermSymbol(implicit scope: Scope): TermSymbol = {\n      val symbol = scope.getTermSymbol(nme.name).getOrElse {\n        raiseDesugaringError(msg\"identifier `${nme.name}` not found\" -> nme.toLoc)\n        freshSymbol(nme)\n      }\n      nme.symbol = symbol\n      symbol\n    }\n\n    /** Associate the `Var` with a term symbol and returns the same `Var`. */\n    def withResolvedTermSymbol(implicit scope: Scope): Var = { nme.resolveTermSymbol; nme }\n\n    /** Associate the `Var` with a class like symbol and returns the class like symbol. */\n    def resolveClassLikeSymbol(implicit scope: Scope, context: Context): ClassLikeSymbol = {\n      val symbol = scope.getTypeSymbol(nme.name) match {\n        case S(symbol) => requireClassLikeSymbol(symbol)\n        case N =>\n          raiseDesugaringError(msg\"type identifier `${nme.name}` not found\" -> nme.toLoc)\n          context.getOrCreateDummyClassSymbol(nme)\n      }\n      nme.symbol = symbol\n      symbol\n    }\n\n    /**\n      * Associate the `Var` with a class like symbol and returns the same `Var`.\n      * We might be able to remove this function. Currently, it is only used for\n      * resolving `Var(\"true\")` and `Var(\"false\")` in `Desugaring`. */\n    def withResolvedClassLikeSymbol(implicit scope: Scope, context: Context): Var =\n      { nme.resolveClassLikeSymbol; nme }\n  }\n\n  /**\n    * This class defines common operations on _splits_ in source abstract syntax\n    * (i.e., `ucs.syntax.source.Split`). \n    */\n  protected implicit class SourceSplitOps[+B <: s.Branch](these: s.Split[B]) {\n    /**\n      * Concatenate two splits and raise a warning if the latter is discarded.\n      *\n      * @param those the right-hand side `ucs.syntax.source.Split`\n      * @return a new split which is the concatenation of LHS and RHS\n      */\n    def ++[BB >: B <: s.Branch](those: s.Split[BB]): s.Split[BB] =\n      if (those === s.Split.Nil) these else (these match {\n        case s.Split.Cons(head, tail) => s.Split.Cons(head, tail ++ those)\n        case s.Split.Let(rec, nme, rhs, tail) => s.Split.Let(rec, nme, rhs, tail ++ those)\n        case s.Split.Else(_) => reportUnreachableCase(those, these)\n        case s.Split.Nil => those\n      })\n  }\n\n  /**\n    * This class defines common operations on _splits_ in _core_ abstract syntax\n    * (i.e., `ucs.syntax.core.Split`). \n    */\n  protected implicit class CoreSplitOps(these: c.Split) {\n    /**\n      * Concatenate two splits and raise a warning if the latter is discarded.\n      *\n      * @param those the right-hand side `ucs.syntax.core.Split`\n      * @return a new split which is the concatenation of LHS and RHS\n      */\n    def ++(those: c.Split): c.Split =\n      if (those === c.Split.Nil) these else (these match {\n        case me: c.Split.Cons => me.copy(tail = me.tail ++ those)\n        case me: c.Split.Let => me.copy(tail = me.tail ++ those)\n        case _: c.Split.Else => reportUnreachableCase(those, these)\n        case c.Split.Nil => those\n      })\n  }\n\n  /**\n    * The entry-point of desugaring a UCS syntax tree (`If` node) to a normal\n    * MLscript syntax tree made of `CaseOf` and `Let` nodes. `PreTyper` is\n    * supposed to call this function. Note that the caller doesn't need to\n    * resolve symbols and bindings inside the UCS tree.\n    *\n    * @param if the UCS syntax tree to be desugared\n    * @param scope the scope of the `If` node\n    */\n  protected def traverseIf(`if`: If)(implicit scope: Scope): Unit = {\n    `if`.desugaredTerm match {\n      case S(desugaredTerm) => lastWords(\"the `if` expression has already been desugared, please make sure that the objects are copied\")\n      case N => ()\n    }\n    implicit val context: Context = new Context(`if`)\n    trace(\"traverseIf\") {\n      // Stage 0: Transformation\n      val transformed = traceWithTopic(\"transform\") {\n        println(\"STEP 0\")\n        transform(`if`)\n      }\n      traceWithTopic(\"transform.result\") {\n        println(\"Transformed UCS term:\", withIndent = false)\n        println(showSplit(transformed), withIndent = false)\n      }\n      // Stage 1: Desugaring\n      val desugared = traceWithTopic(\"desugar\") {\n        println(\"STEP 1\")\n        desugar(transformed)\n      }\n      traceWithTopic(\"desugar.result\") {\n        println(\"Desugared UCS term:\", withIndent = false)\n        println(showSplit(desugared), withIndent = false)\n      }\n      traceWithTopic(\"traverse\") {\n        println(\"STEP 1.5\")\n        traverseSplit(desugared)\n      }\n      // Stage 2: Normalization\n      val normalized = traceWithTopic(\"normalize\") {\n        println(\"STEP 2\")\n        normalize(desugared)\n      }\n      traceWithTopic(\"normalize.result\") {\n        println(\"Normalized UCS term:\", withIndent = false)\n        println(showNormalizedTerm(normalized), withIndent = false)\n      }\n      // Stage 3: Post-processing\n      val postProcessed = traceWithTopic(\"postprocess\") {\n        println(\"STEP 3\")\n        postProcess(normalized)\n      }\n      traceWithTopic(\"postprocess.result\") {\n        println(\"Post-processed UCS term:\", withIndent = false)\n        println(showNormalizedTerm(postProcessed), withIndent = false)\n      }\n      // Stage 4: Coverage checking\n      traceWithTopic(\"coverage\") {\n        val checked = println(\"STEP 4\")\n        val diagnostics = checkCoverage(postProcessed)\n        println(s\"Coverage checking result: ${diagnostics.size} errors\")\n        raiseMany(diagnostics)\n      }\n      traceWithTopic(\"desugared\") {\n        println(s\"Desugared term: ${postProcessed.showDbg}\", withIndent = false)\n      }\n      // Epilogue\n      `if`.desugaredTerm = S(postProcessed)\n    }(_ => \"traverseIf ==> ()\")\n  }\n  \n  /**\n    * Traverse a desugared _core abstract syntax_ tree. The function takes care\n    * of let bindings and resolves variables.\n    */\n  private def traverseSplit(split: c.Split)(implicit scope: Scope): Unit =\n    split match {\n      case c.Split.Cons(c.Branch(scrutinee, pattern, continuation), tail) => \n        traverseTerm(scrutinee)\n        val patternSymbols = pattern.declaredVars.map(nme => nme -> nme.symbol)\n        traverseSplit(continuation)(scope.withEntries(patternSymbols))\n        traverseSplit(tail)\n      case c.Split.Let(isRec, name, rhs, tail) =>\n        val recScope = scope + name.symbol\n        traverseTerm(rhs)(if (isRec) recScope else scope)\n        traverseSplit(tail)(recScope)\n      case c.Split.Else(default) => traverseTerm(default)\n      case c.Split.Nil => ()\n    }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/context/Context.scala",
    "content": "package mlscript\npackage ucs\npackage context\n\nimport collection.mutable.{Buffer, Map => MutMap}\nimport utils._, shorthands._\nimport pretyper.symbol.{DummyClassSymbol, TypeSymbol}\nimport pretyper.Scope\n\nclass Context(originalTerm: If) {\n  /** The prefix of all prefixes. */\n  private val prefix = Context.freshPrefix\n  private val cachePrefix = prefix + \"$cache$\"\n  private val scrutineePrefix = prefix + \"$scrut$\"\n  private val testPrefix = prefix + \"$test$\"\n  private val shadowPrefix = prefix + \"$shadow$\"\n  val unappliedPrefix: Str = prefix + \"$args_\"\n\n  def isCacheVar(nme: Var): Bool = nme.name.startsWith(cachePrefix)\n  def isScrutineeVar(nme: Var): Bool = nme.name.startsWith(scrutineePrefix)\n  def isTestVar(nme: Var): Bool = nme.name.startsWith(testPrefix)\n  def isUnappliedVar(nme: Var): Bool = nme.name.startsWith(unappliedPrefix)\n  def isGeneratedVar(nme: Var): Bool =\n    isCacheVar(nme) || isScrutineeVar(nme) || isTestVar(nme) || isUnappliedVar(nme)\n\n  // Call these objects to generate fresh variables for different purposes.\n  // I plan to mix the unique identifiers of UCS expressions into the prefixes.\n  // So that the generated variables will definitely not conflict with others.\n  val freshCache: VariableGenerator = new VariableGenerator(cachePrefix)\n  val freshScrutineeVar: VariableGenerator = new VariableGenerator(scrutineePrefix)\n  val freshTest: VariableGenerator = new VariableGenerator(testPrefix)\n  val freshShadowed: VariableGenerator = new VariableGenerator(shadowPrefix)\n\n  // Symbol Management\n  // =================\n\n  private val dummyClassSymbols: MutMap[Var, DummyClassSymbol] = MutMap.empty\n  def getOrCreateDummyClassSymbol(nme: Var): DummyClassSymbol =\n    dummyClassSymbols.getOrElseUpdate(nme, new DummyClassSymbol(nme))\n\n  // Scrutinee Management\n  // ====================\n\n  /** The buffer contains all `ScrutineeData` created within this context. */\n  private val scrutineeBuffer: Buffer[Scrutinee] = Buffer.empty\n\n  def freshScrutinee: Scrutinee = {\n    val scrutinee = new Scrutinee(this, N)\n    scrutineeBuffer += scrutinee\n    scrutinee\n  }\n\n  private[context] def freshScrutinee(parent: Scrutinee): Scrutinee = {\n    val scrutinee = new Scrutinee(this, S(parent))\n    scrutineeBuffer += scrutinee\n    scrutinee\n  }\n\n  def scrutinees: Iterator[Scrutinee] = scrutineeBuffer.iterator\n}\n\nobject Context {\n  private val freshPrefix: Str = \"ucs\"\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/context/Matchable.scala",
    "content": "package mlscript.ucs.context\n\nimport collection.mutable.{Map => MutMap}\nimport mlscript.utils._, shorthands._\n\n/**\n  * A trait for \"things\" (e.g., variables, functions, symbols, etc) that can be\n  * matched in a UCS term. This trait holds everything that is needed to track\n  * scrutinee information.\n  */\ntrait Matchable {\n  /**\n    * A map from the context to the scrutinee associated with the symbol in the\n    * context. The reason why we need this map is that the same symbol may be\n    * matched in different UCS terms. Each context corresponds to a UCS term. \n    */\n  private val scrutinees: MutMap[Context, Scrutinee] = MutMap.empty\n    \n  /**\n    * Get the scrutinee associated with the symbol in the given context. If\n    * there's no scrutinee associated with the symbol, create a new one in the\n    * given context. **Note**: This function should only be called from the\n    * UCS desugarer.\n    */\n  private[ucs] def getOrCreateScrutinee(implicit context: Context): Scrutinee =\n    scrutinees.getOrElseUpdate(context, context.freshScrutinee)\n\n  /** Get the scrutinee associated with the symbol in the given context. */\n  def getScrutinee(implicit context: Context): Opt[Scrutinee] = scrutinees.get(context)\n\n  /** Check if the symbol is associated with a scrutinee in the given context. */\n  def isScrutinee(implicit context: Context): Bool = scrutinees.contains(context)\n\n  /** Associate the symbol with a scrutinee in the given context. */\n  private[ucs] def addScrutinee(scrutinee: Scrutinee)(implicit context: Context): Unit = {\n    require(!isScrutinee) // It should be impossible to add a scrutinee twice.\n    scrutinees += context -> scrutinee\n  }\n\n  /** Associate the symbol with a scrutinee in the given context and returns the current object. */\n  private[ucs] def withScrutinee(scrutinee: Scrutinee)(implicit context: Context): this.type = {\n    addScrutinee(scrutinee)\n    this\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/context/Pattern.scala",
    "content": "package mlscript\npackage ucs.context\n\nimport collection.mutable.{Buffer, SortedMap => MutSortedMap}\nimport utils._, shorthands._\nimport pretyper.symbol.{ClassLikeSymbol, DummyClassSymbol, ModuleSymbol, TypeSymbol}\n\nsealed abstract class Pattern {\n  private val locationsBuffer: Buffer[Loc] = Buffer.empty\n\n  def addLocation(located: Located): Unit = located.getLoc.foreach(locationsBuffer += _)\n\n  def addLocation(location: Opt[Loc]): Unit = locationsBuffer ++= location\n\n  /** Get the location of this pattern's first occurrence. */\n  def firstOccurrence: Option[Loc] = locationsBuffer.headOption\n\n  def locations: Ls[Loc] = locationsBuffer.toList\n\n  def arity: Opt[Int]\n\n  def showDbg: Str\n\n  /** Get a string suitable for diagnostics. */\n  def showInDiagnostics: Str\n\n  /**\n    * Checks if the pattern is same as expressed by the given `SimpleTerm`. Note\n    * that we should pass `pat` of `Case` to this function.\n    */\n  def matches(pat: SimpleTerm): Bool\n\n  /** Create a `SimpleTerm` which can be used as `pat` of `Case`. */\n  def toCasePattern: SimpleTerm\n\n  def refined: Bool\n}\n\nobject Pattern {\n  final case class ClassLike(\n      val classLikeSymbol: ClassLikeSymbol,\n      scrutinee: Scrutinee\n  )(override val refined: Bool) extends Pattern {\n    private var unappliedVarOpt: Opt[Var] = N\n    private val parameters: MutSortedMap[Int, Scrutinee] = MutSortedMap.empty\n\n    private[context] def findSubScrutinee(scrutinee: Scrutinee): Opt[Int] =\n      parameters.find(_._2 === scrutinee).map(_._1)\n\n    /**\n      * Get or create a sub-scrutinee for the given parameter index.\n      *\n      * @param index the index of the parameter.\n      * @return a `ScrutineeData` for the parameter whose parent scrutinee is the\n      *         current scrutinee\n      */\n    def getParameter(index: Int): Scrutinee = {\n      require(index >= 0)\n      parameters.getOrElseUpdate(index, scrutinee.freshSubScrutinee)\n    }\n\n    def getUnappliedVar(default: => Var): Var =\n      unappliedVarOpt.getOrElse {\n        val unappliedVar = default\n        unappliedVarOpt = S(unappliedVar)\n        unappliedVar\n      }\n\n    override def arity: Opt[Int] = parameters.keysIterator.maxOption.map(_ + 1)\n\n    override def showDbg: Str =\n      (if (refined) \"refined \" else \"\") + s\"${classLikeSymbol.name}\"\n\n    override def showInDiagnostics: Str = s\"${(classLikeSymbol match {\n      case dummySymbol: DummyClassSymbol => \"class\"\n      case s: ModuleSymbol if s.name === \"true\" || s.name === \"false\" => s\"Boolean value\"\n      case otherSymbol: TypeSymbol => otherSymbol.defn.kind.str\n    })} `${classLikeSymbol.name}`\"\n\n    /** Checks whether this pattern can cover the given pattern. */\n    override def matches(pat: SimpleTerm): Bool =\n      pat match {\n        case pat: Var => pat.getClassLikeSymbol.fold(false)(_ <:< classLikeSymbol)\n        case _: Lit => false\n      }\n\n    override def toCasePattern: SimpleTerm =\n      Var(classLikeSymbol.name).withLoc(firstOccurrence).withSymbol(classLikeSymbol)\n  }\n\n  final case class Tuple(scrutinee: Scrutinee) extends Pattern {\n    private val fields: MutSortedMap[Int, Scrutinee] = MutSortedMap.empty\n\n    def getField(index: Int): Scrutinee =\n      fields.getOrElseUpdate(index, scrutinee.freshSubScrutinee)\n\n    override def arity: Opt[Int] = fields.keysIterator.maxOption.map(_ + 1)\n\n    override def showDbg: Str = s\"tuple#${arity.getOrElse(\"?\")}\"\n\n    override def showInDiagnostics: Str =\n      \"tuple of \" + (arity match {\n        case N => \"certain number of elements\"\n        case S(1) => \"1 element\"\n        case S(n) => s\"${n} elements\"\n      })\n\n    override def matches(pat: SimpleTerm): Bool = false\n\n    /**\n      * Note that currently we only support simple tuple patterns. They should\n      * disappear after desugaring stage, therefore, it will be an error if you\n      * find an instance of this class.\n      */\n    override def toCasePattern: SimpleTerm = ???\n\n    override def refined: Bool = ???\n  }\n\n  final case class Literal(val literal: Lit) extends Pattern {\n    override def arity: Opt[Int] = N\n\n    override def showDbg: Str = literal.idStr\n\n    override def showInDiagnostics: Str = s\"literal ${literal.idStr}\"\n\n    override def matches(pat: SimpleTerm): Bool =\n      pat match {\n        case _: Var => false\n        case pat => pat === literal\n      }\n\n    override def toCasePattern: SimpleTerm = literal.withLoc(firstOccurrence)\n\n    override def refined: Bool = false\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/context/Scrutinee.scala",
    "content": "package mlscript\npackage ucs.context\n\nimport collection.mutable.{Buffer, SortedMap => MutSortedMap, SortedSet => MutSortedSet}\nimport pretyper.symbol.{ClassLikeSymbol, TermSymbol, TypeSymbol}, utils._, shorthands._\nimport scala.annotation.tailrec\n\nclass Scrutinee(val context: Context, parent: Opt[Scrutinee]) {\n  import Scrutinee._\n\n  private val locations: Buffer[Loc] = Buffer.empty\n  private var generatedVarOpt: Opt[Var] = N\n  private val classLikePatterns: MutSortedMap[TypeSymbol, Pattern.ClassLike] = MutSortedMap.empty(classLikeSymbolOrdering)\n  // Currently we only support simple tuple patterns, so there is only _one_\n  // slot for tuple patterns. After we support complex tuple patterns, we need\n  // to extend this fields to a map from tuple arity to `Pattern.Tuple`.\n  //    private val tuplePatterns: MutMap[Int, Pattern.Tuple] = MutMap.empty\n  // If we support tuple pattern splice, we need a more expressive key in the\n  // map's type.\n  private var tuplePatternOpt: Opt[Pattern.Tuple] = N\n  private var aliasVarSet: MutSortedSet[Var] = MutSortedSet.empty\n\n  private val literalPatterns: MutSortedMap[Lit, Pattern.Literal] = MutSortedMap.empty(literalOrdering)\n\n  def addAliasVar(alias: Var): Unit = aliasVarSet += alias\n\n  def withAliasVar(alias: Var): Scrutinee = { addAliasVar(alias); this }\n\n  def aliasesIterator: Iterator[Var] = aliasVarSet.iterator\n\n  /**\n    * If there is already a `Pattern.ClassLike` for the given symbol, return it.\n    * Otherwise, create a new `Pattern.ClassLike` and return it.\n    */\n  def getOrCreateClassPattern(classLikeSymbol: ClassLikeSymbol, refined: Bool): Pattern.ClassLike =\n    classLikePatterns.getOrElseUpdate(classLikeSymbol, Pattern.ClassLike(classLikeSymbol, this)(refined))\n\n  /**\n    * Get the class pattern but DO NOT create a new one if there isn't. This\n    * function is mainly used in post-processing because we don't want to\n    * accidentally create new patterns.\n    */\n  def getClassPattern(classLikeSymbol: TypeSymbol): Opt[Pattern.ClassLike] =\n    classLikePatterns.get(classLikeSymbol)\n\n  /**\n   * If there is already a `Pattern.Tuple`, return it. Otherwise, create a\n   * new `Pattern.Tuple` and return it.\n   * \n   * **NOTE**: There's only one slot for tuple patterns because we cannot\n   * differentiate tuple types in underlying MLscript case terms. In the future,\n   * we will support complex tuple patterns, so we need to extend this method to\n   * a signature like this.\n   * \n   * ```scala\n   * def getOrCreateTuplePattern(dimension: TupleDimension): Pattern.Tuple\n   * case class TupleDimension(knownArity: Int, hasSplice: Bool)\n   * ```\n   */\n  def getOrCreateTuplePattern: Pattern.Tuple =\n    tuplePatternOpt.getOrElse {\n      val tuplePattern = Pattern.Tuple(this)\n      tuplePatternOpt = S(tuplePattern)\n      tuplePattern\n    }\n\n  /** Get the tuple pattern and create a new one if there isn't. */\n  def getOrCreateLiteralPattern(literal: Lit): Pattern.Literal =\n    literalPatterns.getOrElseUpdate(literal, Pattern.Literal(literal))\n\n  def classLikePatternsIterator: Iterator[Pattern.ClassLike] = classLikePatterns.valuesIterator\n\n  def patternsIterator: Iterator[Pattern] =\n    classLikePatterns.valuesIterator ++ literalPatterns.valuesIterator\n\n  /** Get a list of string representation of patterns. Only for debugging. */\n  private[ucs] def showPatternsDbg: Str = {\n    val classLikePatternsStr = classLikePatterns.iterator.map { case (symbol, pattern) =>\n      s\"${symbol.name}(${pattern.arity.fold(\"?\")(_.toString)})\"\n    }\n    val tuplePatternStr = tuplePatternOpt.iterator.map { tuplePattern =>\n      s\"tuple(${tuplePattern.arity.fold(\"?\")(_.toString)})\"\n    }\n    (classLikePatternsStr ++ tuplePatternStr).mkString(\", \")\n  }\n\n  def freshSubScrutinee: Scrutinee = context.freshScrutinee(this)\n\n  def getReadableName(scrutineeVar: Var): Str = {\n    parent match {\n      case N if context.isGeneratedVar(scrutineeVar) => \"term\"\n      case N => s\"`${scrutineeVar.name}`\"\n      case S(parentScrutinee) =>\n        parentScrutinee.classLikePatterns.iterator.flatMap { case (symbol, pattern) =>\n          pattern.findSubScrutinee(this).map(_ -> symbol.name)\n        }.nextOption() match {\n          case S(index -> typeName) => s\"the ${index.toOrdinalWord} argument of `${typeName}`\"\n          case N => s\"`${scrutineeVar.name}`\" // Still not the best.\n        }\n    }\n  }\n\n  @tailrec\n  final def isSubScrutineeOf(scrutinee: Scrutinee): Bool = this === scrutinee || (parent match {\n    case Some(parentScrutinee) => parentScrutinee.isSubScrutineeOf(scrutinee)\n    case N => false\n  })\n}\n\nobject Scrutinee {\n  // We might need to move these method to a private `VarOps` because they may\n  // emit diagnostics.\n  def unapply(term: Term)(implicit context: Context): Opt[Scrutinee] = term match {\n    case v: Var => v.symbol match {\n      case symbol: TermSymbol => symbol.getScrutinee\n      case _ => N\n    }\n    case _ => N\n  }\n\n  type WithVar = Var -> Scrutinee\n\n  object WithVar {\n    def unapply(term: Term)(implicit context: Context): Opt[WithVar] = term match {\n      case v @ Var(_) => v.symbol match {\n        case symbol: TermSymbol => symbol.getScrutinee.map(v -> _)\n        case _ => N\n      }\n      case _ => N\n    }\n  }\n\n  private def literalInternalOrder(literal: Lit): Int = literal match {\n    case UnitLit(true) => 0\n    case UnitLit(false) => 1\n    case _: DecLit => 2\n    case _: IntLit => 3\n    case _: StrLit => 4\n  }\n\n  private implicit val classLikeSymbolOrdering: Ordering[TypeSymbol] = new Ordering[TypeSymbol] {\n    override def compare(x: TypeSymbol, y: TypeSymbol): Int = x.name.compareTo(y.name)\n  }\n\n  private implicit val literalOrdering: Ordering[Lit] = new Ordering[Lit] {\n    override def compare(x: Lit, y: Lit): Int = (x, y) match {\n      case (DecLit(x), DecLit(y)) => x.compare(y)\n      case (IntLit(x), IntLit(y)) => x.compare(y)\n      case (StrLit(x), StrLit(y)) => x.compare(y)\n      case _ => literalInternalOrder(x).compare(literalInternalOrder(y))\n    }\n  }\n\n  private implicit val varNameOrdering: Ordering[Var] = new Ordering[Var] {\n    override def compare(x: Var, y: Var): Int = x.name.compareTo(y.name)\n  }\n}"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/display.scala",
    "content": "package mlscript\npackage ucs\n\nimport syntax.{core => c, source => s}\nimport context.{Context}\nimport pretyper.symbol.{TermSymbol, TypeSymbol}\nimport utils._, shorthands._\n\n/** All the pretty-printing stuff go here. */\npackage object display {\n\n  /** If the variable has a location, mark it with an asterisk.\n    * If the variable is associated with a term symbol, mark it with an asterisk.\n    * If the variable is associated with a term symbol and has a scrutinee, mark it with a double dagger. */\n  private def showVar(`var`: Var)(implicit context: Context): String = {\n    val postfix = `var`.symbolOption match {\n      case S(symbol: TermSymbol) if symbol.isScrutinee => \"‡\"\n      case S(_: TermSymbol) => \"†\"\n      case S(_: TypeSymbol) => \"◊\"\n      case N => \"\"\n    }\n    `var`.name + (`var`.symbolOption.fold(\"\")(_ => \"*\")) + postfix\n  }\n\n  def showSplit(split: s.TermSplit)(implicit context: Context): Str = {\n    def termSplit(split: s.TermSplit, isFirst: Bool, isAfterAnd: Bool): Lines = split match {\n      case s.Split.Cons(head, tail) => (termBranch(head) match {\n        case (n, line) :: tail => (n, (if (isAfterAnd) \"\" else \"and \") + s\"$line\") :: tail\n        case Nil => Nil\n      }) ::: termSplit(tail, false, isAfterAnd)\n      case s.Split.Let(_, nme, rhs, tail) =>\n        (0, s\"let ${nme.name} = ${rhs.showDbg}\") :: termSplit(tail, false, isAfterAnd)\n      case s.Split.Else(term) =>\n        (if (isFirst) (0, s\"then ${term.showDbg}\") else (0, s\"else ${term.showDbg}\")) :: Nil\n      case s.Split.Nil => Nil\n    }\n    def termBranch(branch: s.TermBranch): Lines = branch match {\n      case s.TermBranch.Boolean(test, continuation) => \n        s\"${test.showDbg}\" #: termSplit(continuation, true, false)\n      case s.TermBranch.Match(scrutinee, continuation) =>\n        s\"${scrutinee.showDbg} is\" #: patternSplit(continuation)\n      case s.TermBranch.Left(left, continuation) =>\n        s\"${left.showDbg}\" #: operatorSplit(continuation)\n    }\n    def patternSplit(split: s.PatternSplit): Lines = split match {\n      case s.Split.Cons(head, tail) => patternBranch(head) ::: patternSplit(tail)\n      case s.Split.Let(rec, nme, rhs, tail) =>\n        (0, s\"let ${nme.name} = ${rhs.showDbg}\") :: patternSplit(tail)\n      case s.Split.Else(term) => (0, s\"else ${term.showDbg}\") :: Nil\n      case s.Split.Nil => Nil\n    }\n    def operatorSplit(split: s.OperatorSplit): Lines = split match {\n      case s.Split.Cons(head, tail) => operatorBranch(head) ::: operatorSplit(tail)\n      case s.Split.Let(rec, nme, rhs, tail) =>\n        (0, s\"let ${nme.name} = ${rhs.showDbg}\") :: operatorSplit(tail)\n      case s.Split.Else(term) => (0, s\"else ${term.showDbg}\") :: Nil\n      case s.Split.Nil => Nil\n    }\n    def operatorBranch(branch: s.OperatorBranch): Lines =\n      s\"${branch.operator.name}\" #: (branch match {\n        case s.OperatorBranch.Match(_, continuation) => patternSplit(continuation)\n        case s.OperatorBranch.Binary(_, continuation) => termSplit(continuation, true, true)\n      })\n    def patternBranch(branch: s.PatternBranch): Lines = {\n      val s.PatternBranch(pattern, continuation) = branch\n      termSplit(continuation, true, false) match {\n        case (0, line) :: lines => (0, s\"$pattern $line\") :: lines\n        case lines => (0, pattern.toString) :: lines\n      }\n    }\n    (\"if\" #: termSplit(split, true, true)).toIndentedString\n  }\n\n  @inline def showSplit(s: c.Split, showFirstLevel: Bool = false)(implicit context: Context): Str =\n    showSplit(\"if\", s, showFirstLevel)\n\n  def showSplit(prefix: Str, s: c.Split, showFirstLevel: Bool)(implicit context: Context): Str = {\n    def split(s: c.Split, isFirst: Bool, isTopLevel: Bool): Lines = s match {\n      case c.Split.Cons(head, tail) => (branch(head, isTopLevel) match {\n        case (n, line) :: tail => (n, (if (isTopLevel) \"\" else \"and \") + (if (s.isFallback) \"?\" else \"\") + line) :: tail\n        case Nil => Nil\n      }) ::: split(tail, false, isTopLevel)\n      case c.Split.Let(_, nme, rhs, tail) =>\n        (0, s\"let ${showVar(nme)} = ${rhs.showDbg}\") :: split(tail, false, isTopLevel)\n      case c.Split.Else(term) =>\n        (if (isFirst) (0, s\"then ${term.showDbg}\") else (0, s\"else ${term.showDbg}\")) :: Nil\n      case c.Split.Nil => Nil\n    }\n    def branch(b: c.Branch, isTopLevel: Bool): Lines = {\n      val c.Branch(scrutinee, pattern, continuation) = b\n      if (showFirstLevel) {\n        val continuation = b.continuation match {\n          case c.Split.Nil => \"empty\"\n          case c.Split.Else(_) => \"then ...\"\n          case _ => \"and ...\"\n        }\n        (0, s\"${showVar(scrutinee)} is $pattern \" + continuation) :: Nil\n      }\n      else s\"${showVar(scrutinee)} is $pattern\" #: split(continuation, true, isTopLevel)\n    }\n    val lines = split(s, true, true)\n    (if (prefix.isEmpty) lines else prefix #: lines).toIndentedString\n  }\n\n  /**\n    * Convert a normalized term to a string with indentation. It makes use of\n    * some special markers.\n    *\n    * - `*` if the variable has a location.\n    * - `†` if the variable is associated with a term symbol.\n    * - `‡` if the variable is associated with a term symbol and has a scrutinee.\n    */\n  def showNormalizedTerm(term: Term)(implicit context: Context): String = {\n    def showTerm(term: Term): Lines = term.desugaredTerm match {\n      case N => term match {\n        case let: Let => showLet(let)\n        case caseOf: CaseOf => showCaseOf(caseOf)\n        case other => (0, other.showDbg) :: Nil\n      }\n      case S(desugaredTerm) => \"[desugared]\" @: showTerm(desugaredTerm)\n    }\n    def showScrutinee(term: Term): Str = term match {\n      case vari: Var => showVar(vari)\n      case _ => term.showDbg\n    }\n    def showPattern(pat: SimpleTerm): Str = pat match {\n      case vari: Var => showVar(vari)\n      case _ => pat.showDbg\n    }\n    def showCaseOf(caseOf: CaseOf): Lines = {\n      val CaseOf(trm, cases) = caseOf\n      s\"case ${showScrutinee(trm)} of\" ##: showCaseBranches(cases)\n    }\n    def showCaseBranches(caseBranches: CaseBranches): Lines =\n      caseBranches match {\n        case k @ Case(pat, rhs, tail) =>\n          (s\"${if (k.refined) \"refined \" else \"\"}${showPattern(pat)} ->\" @: showTerm(rhs)) ++ showCaseBranches(tail)\n        case Wildcard(term) => s\"_ ->\" @: showTerm(term)\n        case NoCases => Nil\n      }\n    def showLet(let: Let): Lines = {\n      val Let(rec, nme, rhs, body) = let\n      (0, s\"let ${showVar(nme)} = ${rhs.showDbg}\") :: showTerm(body)\n    }\n    showTerm(term).toIndentedString\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/package.scala",
    "content": "package mlscript\n\nimport scala.annotation.tailrec\nimport utils._, shorthands._\n\npackage object ucs {\n  class VariableGenerator(prefix: Str) {\n    private var nextIndex = 0\n\n    def apply(): Var = {\n      val thisIndex = nextIndex\n      nextIndex += 1\n      Var(s\"$prefix$thisIndex\")\n    }\n\n    def reset(): Unit = nextIndex = 0\n  }\n\n  type Lines = Ls[(Int, Str)]\n\n  implicit class LinesOps(private val lines: Lines) extends AnyVal {\n    /** Increase the indentation of all lines by one. */\n    def indent: Lines = lines.map { case (n, line) => (n + 1, line) }\n\n    /**\n      * Prepend a new line and indent the remaining lines. When you want to add\n      * a \"title\" to several lines and indent them, you should use this function.\n      * \n      * Suppose we have the following `Lines` representing case branches.\n      * ```\n      * A -> 0\n      * B -> 0\n      * ```\n      * We can prepend string `case x of` to lines and get the following result.\n      * ```\n      * case x of\n      *   A -> 0\n      *   B -> 0\n      * ```\n      */\n    def ##:(prefix: Str): Lines = (0, prefix) :: lines.indent\n\n    /**\n      * If the first line does not have indentation and the remaining lines are\n      * indented, prepend the given string to the first line. Otherwise, prepend\n      * the given string to the first line and indent all remaining lines.\n      *\n      * When you want to amend the title of lines, you should use this function.\n      */\n    def #:(prefix: Str): Lines = {\n      lines match {\n        case (0, line) :: lines if lines.forall(_._1 > 0) => (0, s\"$prefix $line\") :: lines\n        case lines => (0, prefix) :: lines.indent\n      }\n    }\n    /**\n      * If there is only one line, prepend the given string to the beginning of\n      * this line. Otherwise, use the given string as the first line and indent\n      * the remaining lines.\n      * \n      * Similar to `##:`, except this function does not indent if there is only\n      * one line.\n      */\n    def @:(prefix: Str): Lines = lines match {\n      case (_, line) :: Nil => (0, prefix + \" \" + line) :: Nil\n      case lines => (0, prefix) :: lines.indent\n    }\n\n    /** Make a multi-line string. */\n    def toIndentedString: Str =\n      lines.iterator.map { case (n, line) => \"  \" * n + line }.mkString(\"\\n\")\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/stages/CoverageChecking.scala",
    "content": "package mlscript\npackage ucs\npackage stages\n\nimport utils._, shorthands._, Message.MessageContext\nimport context.{Context, Pattern, Scrutinee}\nimport pretyper.Traceable, pretyper.symbol._\n\ntrait CoverageChecking { self: Desugarer with Traceable =>\n  import CoverageChecking._\n\n  def checkCoverage(term: Term)(implicit context: Context): Ls[Diagnostic] = {\n    // Collect an immutable map from scrutinees to patterns.\n    val registry: ScrutineePatternSetMap = context.scrutinees.flatMap { scrutinee =>\n      val caseSet = CaseSet(scrutinee.patternsIterator.toList)\n      scrutinee.aliasesIterator.map(alias => (alias -> scrutinee) -> caseSet)\n    }.toMap\n    println(\"collected match registry: \" + showRegistry(registry))\n    checkCoverage(term, Map.empty, registry, Map.empty)\n  }\n\n  private def checkCoverage(\n      term: Term,\n      pending: ScrutineePatternSetMap,\n      working: ScrutineePatternSetMap,\n      seen: SeenRegistry\n  )(implicit context: Context): Ls[Diagnostic] = {\n    term match {\n      case Let(_, nme, _, body) =>\n        println(s\"checkCoverage <== LET `${nme.name}`\")\n        checkCoverage(body, pending, working, seen)\n      case CaseOf(scrutineeVar: Var, Case(Var(\"true\"), body, NoCases)) if context.isTestVar(scrutineeVar) =>\n        raiseDesugaringError(msg\"missing else branch\" -> body.toLoc)\n        Nil\n      case CaseOf(scrutineeVar: Var, Case(Var(\"true\"), whenTrue, Wildcard(whenFalse))) if context.isTestVar(scrutineeVar) =>\n        println(s\"checkCoverage <== TEST `${scrutineeVar.name}`\")\n        checkCoverage(whenTrue, pending, working, seen) ++\n          checkCoverage(whenFalse, pending, working, seen)\n      case CaseOf(Scrutinee.WithVar(scrutineeVar, scrutinee), cases) =>\n        trace(s\"checkCoverage <== ${pending.size} pending, ${working.size} working, ${seen.size} seen\") {\n          println(s\"CASE ${scrutineeVar.name}\")\n          println(s\"SEEN: ${seen.showDbg}\")\n          // If the scrutinee is still pending (i.e., not matched yet), then we\n          // remove it from the pending list. If the scrutinee is matched, and\n          // there are still classes to be matched, then we find the remaining\n          // classes from the working list. If neither of the above is true,\n          // there are two possible cases:\n          // 1. The scrutinee has been never visited, which is an error.\n          // 2. It has been matched to be an instance of some class. Therefore,\n          //    we need to check if this is a contradiction.\n          val namedScrutinee = scrutineeVar -> scrutinee\n          val (unseenPatterns, newPending) = pending.get(namedScrutinee) match {\n            case S(matchedClasses) => matchedClasses -> (pending - namedScrutinee)\n            case N => working.get(namedScrutinee) match {\n              case S(unseenPatterns) => unseenPatterns -> pending\n              case N =>\n                // Neither in the working list nor in the pending list.\n                seen.get(namedScrutinee) match {\n                  // The scrutine may have been matched.\n                  case S((_, _, remainingPatterns)) => remainingPatterns -> pending\n                  case N =>\n                    // The scrutinee has never been visited. This should not happen.\n                    println(\"working list: \" + showRegistry(working))\n                    throw new Exception(s\"Scrutinee ${scrutineeVar.name} is not in the working list.\")\n                }\n            }\n          }\n          // We go through cases and keep removing the current pattern from the\n          // unseen pattern set.\n          // Meanwhile, we keep adding diagnostics if we meet warnings and errors.\n          cases.foldLeft((unseenPatterns, Nil: Ls[Diagnostic]))({\n            case ((unseenPatterns, diagnostics), (boolLit: Var) -> body)\n                if boolLit.name === \"true\" || boolLit.name === \"false\" =>\n              (\n                unseenPatterns.remove(boolLit),\n                diagnostics ++ checkCoverage(body, newPending, working - namedScrutinee, seen)\n              )\n            case ((unseenPatterns, diagnostics), (className: Var) -> body) =>\n              val classSymbol = className.getClassLikeSymbol.getOrElse {\n                throw new Exception(s\"$className is not associated with a type symbol\")\n              }\n              println(s\"class symbol: `${classSymbol.name}`\")\n              unseenPatterns.split(classSymbol) match {\n                case S((pattern, refiningPatterns, remainingPatterns)) =>\n                  println(s\"REMOVE `${className.name}` from working\")\n                  println(s\"unseen: ${unseenPatterns.showInDiagnostics}\")\n                  println(s\"remaining: ${remainingPatterns.showInDiagnostics}\")\n                  // Remove the scrutinee from the working list.\n                  val newWorking = if (remainingPatterns.isEmpty)\n                    working - namedScrutinee\n                  else\n                    working.updated(namedScrutinee, remainingPatterns)\n                  // Add \"`scrutinee` is `className`\" to the seen registry.\n                  val newSeen = seen + (namedScrutinee -> (classSymbol, pattern.locations, refiningPatterns))\n                  (\n                    remainingPatterns,\n                    diagnostics ++ checkCoverage(body, newPending, newWorking, newSeen)\n                  )\n                case N =>\n                  println(s\"cannot split the set by ${classSymbol.name}\")\n                  unseenPatterns -> (diagnostics :+ (seen.get(namedScrutinee) match {\n                    case S((`classSymbol`, _, _)) => WarningReport(\"tautology\", Nil, Diagnostic.Desugaring)\n                    case S(_) => ErrorReport(\"contradiction\", Nil, Diagnostic.Desugaring)\n                    case N => ErrorReport(\"unvisited scrutinee\", Nil, Diagnostic.Desugaring)\n                  }))\n              }\n            case ((unseenPatterns, diagnostics), (literal: Lit) -> body) =>\n              (\n                unseenPatterns.remove(literal),\n                diagnostics ++ checkCoverage(body, newPending, working - namedScrutinee, seen)\n              )\n          }) {\n            case ((missingCases, diagnostics), N) =>\n              println(s\"remaining cases are not covered: ${missingCases.showInDiagnostics}\")\n              diagnostics ++ explainMissingCases(namedScrutinee, seen, missingCases)\n            case ((remainingCases, diagnostics), S(default)) =>\n              println(\"remaining cases should be covered by the wildcard\")\n              checkCoverage(default, newPending, working.updated(namedScrutinee, remainingCases), seen)\n          }\n        }(ls => s\"checkCoverage ==> ${ls.length} diagnostics\")\n      case other =>\n        println(s\"checkCoverage <== TERM ${other.showDbg}\")\n        Nil\n    }\n  }\n}\n\nobject CoverageChecking {\n  /** Create an `ErrorReport` that explains missing cases. */\n  private def explainMissingCases(\n      scrutinee: Scrutinee.WithVar,\n      seen: SeenRegistry,\n      missingCases: CaseSet\n  )(implicit context: Context): Opt[ErrorReport] =\n    if (missingCases.isEmpty) {\n      N\n    } else {\n      S(ErrorReport({\n        val readableName = scrutinee._2.getReadableName(scrutinee._1)\n        val lines = (msg\"$readableName has ${\"missing case\".pluralize(missingCases.size, true)}\" -> scrutinee._1.toLoc) ::\n          (missingCases.patterns.iterator.flatMap { pattern =>\n            (msg\"it can be ${pattern.showInDiagnostics}\" -> pattern.firstOccurrence) :: Nil\n          }.toList)\n        if (seen.isEmpty) {\n          lines\n        } else {\n          seen.iterator.zipWithIndex.map { case ((scrutineeVar -> scrutinee, (classSymbol, locations, cases)), i) =>\n            val prologue = if (i === 0) \"when \" else \"\"\n            val epilogue = if (seen.size === 1) \"\" else if (i === seen.size - 2) \", and\" else \",\"\n            val scrutineeName = scrutinee.getReadableName(scrutineeVar)\n            msg\"$prologue$scrutineeName is `${classSymbol.name}`$epilogue\" -> locations.headOption\n          }.toList ::: lines\n        }\n      }, true, Diagnostic.Desugaring))\n    }\n\n  /** A helper function that prints entries from the given registry line by line. */\n  private def showRegistry(registry: ScrutineePatternSetMap): Str =\n    if (registry.isEmpty) \"empty\" else\n      registry.iterator.map { case (scrutineeVar -> scrutinee, matchedClasses) =>\n        matchedClasses.patterns.iterator.map(_.showInDiagnostics).mkString(s\">>> ${scrutineeVar.name} => [\", \", \", \"]\")\n      }.mkString(\"\\n\", \"\\n\", \"\")\n\n  type ScrutineePatternSetMap = Map[Scrutinee.WithVar, CaseSet]\n\n  type SeenRegistry = Map[Scrutinee.WithVar, (TypeSymbol, Ls[Loc], CaseSet)]\n\n  implicit class SeenRegistryOps(val self: SeenRegistry) extends AnyVal {\n    def showDbg: Str = if (self.isEmpty) \"empty\" else\n      self.iterator.map { case ((k, _), (s, _, _)) => s\"${k.name} is ${s.name}\" }.mkString(\", \")\n  }\n\n  /**\n    * A `CaseSet` represents all patterns that a particular scrutinee is\n    * being matched with within a UCS expression.\n    *\n    * @param patterns a list of patterns.\n    */\n  final case class CaseSet(val patterns: List[Pattern]) {\n    def showInDiagnostics: Str =\n      patterns.iterator.map(_.showInDiagnostics).mkString(\"[\", \", \", \"]\")\n\n    /** Get a iterator of all class-like patterns. */\n    def classLikePatterns: Iterator[Pattern.ClassLike] = patterns.iterator.flatMap {\n      case pattern: Pattern.ClassLike => S(pattern)\n      case _: Pattern.Literal | _: Pattern.Tuple => N\n    }\n\n    /** Separate a class-like pattern if it appears in `patterns`. */\n    def separate(classLikeSymbol: ClassLikeSymbol): Opt[(Pattern.ClassLike, Ls[Pattern.ClassLike])] = {\n      classLikePatterns.foldRight[(Opt[Pattern.ClassLike], Ls[Pattern.ClassLike])]((N, Nil)) {\n        case (pattern, (S(separated), rest)) => (S(separated), pattern :: rest)\n        case (pattern, (N, rest)) if pattern.classLikeSymbol === classLikeSymbol => (S(pattern), rest)\n        case (pattern, (N, rest)) => (N, pattern :: rest)\n      } match {\n        case (N, _) => N\n        case (S(separated), rest) => S((separated, rest))\n      }\n    }\n    /**\n      * Split the pattern set into two pattern sets.\n      * \n      * For example, let A be the base type of B, C, and D. Plus, class `Z` is\n      * unrelated to any of them. Suppose the initial pattern set is\n      * `{ A, B, C, Z }`. Splitting the set results in two sets, one set\n      * contains classes that are compatible with `A`, and the other set\n      * contains classes that are unrelated to `A`.\n      * \n      * For example, if we split the set with `A`, then we get `{ B, C }` and\n      * set `{ Z }`. Set `{ B, C }` represents that the scrutinee can be further\n      * refined to class `B` or `class C`. Set `{ Z }` represents that if the\n      * scrutinee is not `A`, then it can be `Z`.\n      *\n      * @param classLikeSymbol the type symbol represents the class like type\n      * @return If the pattern set doesn't include the given type symbol, this\n      *         returns `None`. Otherwise, the function returns a triplet of the\n      *         locations where the pattern appears, the related patterns, and\n      *         unrelated patterns.\n      */\n    def split(classLikeSymbol: ClassLikeSymbol): Opt[(Pattern.ClassLike, CaseSet, CaseSet)] = {\n      def mk(pattern: Pattern): Opt[Lit \\/ TypeSymbol] = pattern match {\n        case Pattern.ClassLike(classLikeSymbol, _) => S(R(classLikeSymbol))\n        case Pattern.Literal(literal) => S(L(literal))\n        case _ => N\n      }\n      separate(classLikeSymbol) match {\n        case N => N\n        case S((pattern, patterns)) =>\n          val (unrelated, related) = patterns.partitionMap { otherPattern =>\n            if (compareCasePattern(mk(otherPattern), mk(pattern))) {\n              R(otherPattern)\n            } else {\n              L(otherPattern)\n            }\n          }\n          S((pattern, CaseSet(related), CaseSet(unrelated)))\n      }\n    }\n\n    @inline def remove(boolLit: Var): CaseSet = {\n      require(boolLit.name === \"true\" || boolLit.name === \"false\")\n      CaseSet(patterns.filter(!_.matches(boolLit)))\n    }\n\n    @inline def remove(literal: Lit): CaseSet =\n      CaseSet(patterns.filter(!_.matches(literal)))\n\n    @inline def isEmpty: Bool = patterns.isEmpty\n\n    @inline def size: Int = patterns.size\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/stages/Desugaring.scala",
    "content": "package mlscript\npackage ucs\npackage stages\n\nimport syntax.{core => c, source => s}\nimport context.{Context, Scrutinee}\nimport utils._, shorthands._, Message.MessageContext\nimport pretyper.symbol._, pretyper.{PreTyper, Scope}\n\n/**\n  * The desugaring stage of UCS. In this stage, we transform the source abstract\n  * syntax into core abstract syntax, which is more concise. We will make\n  * following changes during this stage:\n  * \n  * 1. Flatten nested patterns and generated bindings for nameless scrutinees\n  *    and parameters of class-like patterns.\n  * 2. Desugar variable patterns to plain let bindings.\n  * 3. Desugar literal patterns to equivalent boolean expressions.\n  * 4. Reassemble partial terms that are broken by \"conditional splits\".\n  * 5. Associate each scrutinee with a unique `ScrutineeData`.\n  * \n  * Desugared UCS terms (core abstract syntax) are in the form of `Split`, which\n  * is a list of branches. Each branch consists of a scrutinee, a pattern, and a\n  * continuation.\n  */\ntrait Desugaring { self: PreTyper =>\n  import Desugaring._\n\n  /**\n    * The entry point of the desugaring stage.\n    *\n    * @param term the root of source abstrax syntax term, obtained from the\n    *             transformation stage\n    * @param scope the scope is for resolving type symbols. The scope should\n    *              contains a TypeSymbol for `true` literal.\n    * @return the root of desugared core abstract syntax term\n    */\n  @inline def desugar(term: s.TermSplit)(implicit scope: Scope, context: Context): c.Split =\n    desugarTermSplit(term)(PartialTerm.Empty, scope, context)\n\n  /**\n    * Coin a fresh name for a destructed parameter. The name consists of three\n    * parts: the name of the parent scrutinee, the name of matched class, and\n    * the index of the parameter. For example, if variable `x` is matched as\n    * `Cons(hd, tl)`, then the name of `hd` will be `x$Cons_0` and the name of\n    * `tl` will be `x$Cons_1`.\n    */\n  private def freshSubScrutineeVar(parentScrutinee: Var, parentClassName: Str, index: Int): Var =\n    Var(s\"${parentScrutinee.name}$$${parentClassName}_${index.toString}\")\n\n  /**\n    * Coin a fresh name for the result of `unapply` method. The name begins with\n    * `args_`, followed by the name of the scrutinee, and finally ends with the\n    * name of the matched class. For example, if variable `x` is matched as\n    * `Cons(hd, tl)`, then the name of `Cons.unapply(x)` will be `args_x$Cons`.\n    * Parameters `hd` and `tl` are obtained by selecting `.1` and `.2` from\n    * `args_x$Cons`.\n    */\n  private def makeUnappliedVar(scrutinee: Var, className: Var)(implicit context: Context): Var =\n    Var(s\"${context.unappliedPrefix}${scrutinee.name}$$${className.name}\")\n\n  /**\n    * A shorthand for making a true pattern, which is useful in desugaring\n    * Boolean conditions.\n    */\n  private def truePattern(implicit scope: Scope, context: Context) = {\n    val className = Var(\"true\")\n    val classSymbol = className.resolveClassLikeSymbol\n    c.Pattern.Class(className, classSymbol, false)\n  }\n  private def falsePattern(implicit scope: Scope, context: Context) = {\n    val className = Var(\"false\")\n    val classSymbol = className.resolveClassLikeSymbol\n    c.Pattern.Class(className, classSymbol, false)\n  }\n\n  private def desugarTermSplit(split: s.TermSplit)(implicit termPart: PartialTerm.Incomplete, scope: Scope, context: Context): c.Split =\n    split match {\n      case s.Split.Cons(head, tail) => desugarTermBranch(head) ++ desugarTermSplit(tail)\n      case s.Split.Let(rec, nme, rhs, tail) =>\n        c.Split.Let(rec, nme, rhs, desugarTermSplit(tail)(termPart, scope + nme.withFreshSymbol.symbol, context)) // <-- Weird use.\n      case s.Split.Else(default) => c.Split.Else(default); \n      case s.Split.Nil => c.Split.Nil\n    }\n\n  // This function does not need to can `withCachedTermPart` because all branches assume that\n  // `termPart` is either empty or waiting for an RHS.\n  private def desugarTermBranch(branch: s.TermBranch)(implicit termPart: PartialTerm.Incomplete, scope: Scope, context: Context): c.Split =\n    trace(s\"desugarTermBranch <== $termPart\") {\n      branch match {\n        case s.TermBranch.Boolean(testPart, continuation) =>\n          val test = context.freshTest().withFreshSymbol\n          c.Split.Let(\n            rec = false,\n            name = test,\n            term = Asc(termPart.addTerm(testPart).get, TypeName(\"Bool\")),\n            tail = c.Branch(test, truePattern, desugarTermSplit(continuation)(PartialTerm.Empty, scope + test.symbol, context)) :: c.Split.Nil\n          )\n        case s.TermBranch.Match(scrutinee, split) =>\n          desugarPatternSplit(termPart.addTerm(scrutinee).get, split)\n        case s.TermBranch.Left(left, continuation) =>\n          desugarOperatorSplit(continuation)(termPart.addTerm(left), scope, context)\n      }\n    }()\n\n  private def withCachedTermPart[B <: s.Branch](desugar: (PartialTerm.Total, Scope) => c.Split)(implicit termPart: PartialTerm.Total, scope: Scope, context: Context): c.Split =\n    termPart.get match {\n      case v: Var => desugar(termPart, scope) // No need to cache variables.\n      case rhs =>\n        val cache = context.freshCache().withFreshSymbol\n        c.Split.Let(false, cache, rhs, desugar(PartialTerm.Total(cache, Nil), scope + cache.symbol))\n    }\n\n  private def desugarOperatorSplit(split: s.OperatorSplit)(implicit termPart: PartialTerm.Total, scope: Scope, context: Context): c.Split =\n    withCachedTermPart { (termPart, scope) => split match {\n      case s.Split.Cons(head, tail) => desugarOperatorBranch(head)(termPart, scope, context) ++ desugarOperatorSplit(tail)(termPart, scope, context)\n      case s.Split.Let(rec, nme, rhs, tail) =>\n        c.Split.Let(rec, nme, rhs, desugarOperatorSplit(tail)(termPart, scope + nme.withFreshSymbol.symbol, context)) // <-- Weird use.\n      case s.Split.Else(default) => c.Split.Else(default)\n      case s.Split.Nil => c.Split.Nil\n    }}\n\n  private def desugarOperatorBranch(branch: s.OperatorBranch)(implicit termPart: PartialTerm.Total, scope: Scope, context: Context): c.Split =\n    trace(s\"desugarOperatorBranch <== $termPart\") {\n      branch match {\n        case s.OperatorBranch.Binary(op, split) => desugarTermSplit(split)(termPart.addOp(op), scope, context)\n        case s.OperatorBranch.Match(_, split) => desugarPatternSplit(termPart.get, split)(scope, context)\n      }\n    }()\n\n  private def makeLiteralTest(scrutinee: Var, literal: Lit)(implicit scope: Scope): c.Split => c.Split =\n    next => c.Branch(scrutinee, c.Pattern.Literal(literal), next) :: c.Split.Nil\n\n  private def flattenClassParameters(\n      parentScrutineeVar: Var,\n      parentScrutinee: Scrutinee,\n      parentClassLikeSymbol: ClassLikeSymbol,\n      parentRefined: Bool,\n      parameters: Ls[s.Pattern],\n  )(implicit context: Context): Ls[Opt[(Var, Opt[s.Pattern], Ls[Var])]] = {\n    // Make it `lazy` so that it will not be created if all fields are wildcards.\n    lazy val classPattern = parentScrutinee.getOrCreateClassPattern(parentClassLikeSymbol, parentRefined)\n    def flattenPattern(\n      parameterPattern: s.Pattern,\n      index: Int,\n      subScrutineeVarOpt: Opt[(Var, Scrutinee)],\n      aliasVars: Ls[Var],\n    ): Opt[(Var, Opt[s.Pattern], Ls[Var])] = { // scrutineeVar, subPattern, aliasVars\n      lazy val (subScrutineeVar, subScrutinee) = subScrutineeVarOpt.getOrElse {\n        val subScrutineeVar = freshSubScrutineeVar(parentScrutineeVar, parentClassLikeSymbol.name, index)\n        val symbol = new LocalTermSymbol(subScrutineeVar)\n        val subScrutinee = classPattern.getParameter(index).withAliasVar(subScrutineeVar.withSymbol(symbol))\n        symbol.addScrutinee(subScrutinee)\n        (subScrutineeVar, subScrutinee)\n      }\n      parameterPattern match {\n        case _: s.EmptyPattern => N\n        case s.NamePattern(name) =>\n          val subScrutinee = classPattern.getParameter(index).withAliasVar(name)\n          S((name.withFreshSymbol.withScrutinee(subScrutinee), N, aliasVars.reverse))\n        case parameterPattern @ (s.ClassPattern(_, _, _) | s.LiteralPattern(_) | s.TuplePattern(_)) =>\n          S((subScrutineeVar, S(parameterPattern), aliasVars.reverse))\n        case parameterPattern @ s.AliasPattern(aliasVar, innerPattern) =>\n          println(s\"alias pattern found ${subScrutineeVar.name} -> ${aliasVar.name}\")\n          flattenPattern(innerPattern, index, S((subScrutineeVar, subScrutinee)), aliasVar.withFreshSymbol.withScrutinee(subScrutinee) :: aliasVars)\n        case pattern =>\n          raiseDesugaringError(msg\"unsupported pattern\" -> pattern.toLoc)\n          N\n      }\n    }\n    trace(s\"flattenClassParameters <== ${parentScrutineeVar.name} is ${parentClassLikeSymbol.name}\") {\n      parameters.iterator.zipWithIndex.map {\n        case (pattern, index) => flattenPattern(pattern, index, N, Nil)\n      }.toList\n    }(r => s\"flattenClassParameters ==> ${r.mkString(\", \")}\")\n  }\n\n  /**\n    * Recursively decompose and flatten a possibly nested class pattern. Any\n    * user-declared and generated variables will be added to the given scope and\n    * a augmented scope will be returned. Meanwhile, it produces a function that\n    * wrap a split with all bindings and matches.\n    * \n    * This function involves some higher-order function's compose operation, so\n    * it is somewhat convoluted to read. However, this is a necessary\n    * complication, as we need information from the scope when generating\n    * variable names.\n    *\n    * @param pattern the class pattern\n    * @param scrutinee the scrutinee of the pattern. The caller should make sure\n    *                  that the scrutinee is associated with a symbol in the\n    *                  given scope.\n    * @param initialScope the scope before flattening the class pattern\n    * @return a tuple of the augmented scope and a function that wrap a split\n    */\n  private def desugarClassPattern(\n      pattern: s.ClassPattern,\n      scrutineeVar: Var,\n      initialScope: Scope,\n      refined: Bool\n  )(implicit context: Context): (Scope, c.Split => c.Branch) = {\n    val scrutinee = scrutineeVar.getOrCreateScrutinee.withAliasVar(scrutineeVar)\n    val patternClassSymbol = pattern.nme.resolveClassLikeSymbol(initialScope, context)\n    val classPattern = scrutinee.getOrCreateClassPattern(patternClassSymbol, refined)\n    println(s\"desugarClassPattern: ${scrutineeVar.name} is ${pattern.nme.name}\")\n    classPattern.addLocation(pattern.nme)\n    val (scopeWithAll, bindAll) = pattern.parameters match {\n      case S(parameters) =>\n        // Before processing sub-patterns, we need to generate a variable that\n        // holds the result of `unapply` method. Such variable might have been\n        // generated by a previous branches. We MUST reuse so that we can merge\n        // duplicated bindings during normalization.\n        lazy val unapp = classPattern.getUnappliedVar {\n          val vari = makeUnappliedVar(scrutineeVar, pattern.nme)\n          vari.withSymbol(new LocalTermSymbol(vari))\n        }\n        val nestedPatterns = flattenClassParameters(scrutineeVar, scrutinee, patternClassSymbol, refined, parameters)\n        println(s\"nestedPatterns = $nestedPatterns\")\n        // First, handle bindings of parameters of the current class pattern.\n        val identity = (split: c.Split) => split\n        val bindParameters = nestedPatterns.iterator.zipWithIndex.foldRight[c.Split => c.Split](identity) {\n          case ((N, _), bindNextParameter) => bindNextParameter\n          case ((S((parameter, _, _)), index), bindNextParameter) => \n            bindNextParameter.andThen { c.Split.Let(false, parameter, Sel(unapp, Var(index.toString)), _) }\n        }\n        println(s\"bindParameters === identity: ${bindParameters === identity}\")\n        val bindAll = if (bindParameters === identity) bindParameters else bindParameters.andThen {\n          c.Split.Let(false, unapp, makeUnapplyCall(scrutineeVar, pattern.nme), _): c.Split\n        }\n        val scopeWithClassParameters = initialScope ++ (unapp.symbol :: nestedPatterns.flatMap(_.map(_._1.symbol)))\n        desugarNestedPatterns(nestedPatterns, scopeWithClassParameters, bindAll)\n      // If there is no parameter, then we are done.\n      case N => (initialScope, identity(_: c.Split))\n    }\n    println(s\"${scrutineeVar.name}: ${scrutinee.showPatternsDbg}\")\n    // Last, return the scope with all bindings and a function that adds all matches and bindings to a split.\n    (scopeWithAll, split => c.Branch(scrutineeVar, c.Pattern.Class(pattern.nme, patternClassSymbol, refined), bindAll(split)))\n  }\n\n  /**\n    * This function collects bindings from nested patterns and accumulate a\n    * function that add let bindings to a split (we call such function a\n    * \"binder\"). This function is supposed to be called from pattern desugaring\n    * functions.\n    *\n    * @param nestedPatterns nested patterns are a list of sub-scrutinees and \n    *                       corresponding sub-patterns\n    * @param scopeWithScrutinees a scope with all sub-scrutinees\n    * @param bindScrutinees a function that adds all bindings to a split\n    */\n  private def desugarNestedPatterns(\n      nestedPatterns: Ls[Opt[(Var, Opt[s.Pattern], Ls[Var])]],\n      scopeWithScrutinees: Scope,\n      bindScrutinees: c.Split => c.Split\n  )(implicit context: Context): (Scope, c.Split => c.Split) =\n    trace(\"desugarNestedPatterns\") {\n      nestedPatterns.foldLeft((scopeWithScrutinees, bindScrutinees)) {\n        // If this parameter is empty (e.g. produced by wildcard), then we do\n        // nothing and pass on scope and binder.\n        case (acc, N) => acc\n        // If this sub-pattern is a class pattern, we need to recursively flatten\n        // the class pattern. We will get a scope with all bindings and a function\n        // that adds all bindings to a split. The scope can be passed on to the\n        // next sub-pattern. The binder needs to be composed with the previous\n        // binder.\n        case (acc @ (scope, bindPrevious), S((nme, patternOpt, aliasVars))) =>\n          println(s\"subScrut = ${nme.name}; aliasVars = ${aliasVars.iterator.map(_.name).mkString(\"[\", \", \", \"]\")}\")\n          val bindAliasVars = aliasVars.foldRight[c.Split => c.Split](identity[c.Split]) {\n            case (aliasVar, bindNext) => (inner: c.Split) => c.Split.Let(false, aliasVar, nme, bindNext(inner))\n          }\n          patternOpt match {\n            // If this parameter is not matched with a sub-pattern, then we do\n            // nothing and pass on scope and binder.\n            case N => (scope, bindAliasVars.andThen(bindPrevious))\n            case S(pattern) => pattern match {\n              case pattern: s.ClassPattern =>\n                println(s\"${nme.name} is ${pattern.nme.name}\")\n                val (scopeWithNestedAll, bindNestedAll) = desugarClassPattern(pattern, nme, scope, pattern.refined)\n                (scopeWithNestedAll, split => bindPrevious(bindNestedAll(bindAliasVars(split)) :: c.Split.Nil))\n              case pattern @ s.ConcretePattern(Var(\"true\") | Var(\"false\")) =>\n                println(s\"${nme.name} is ${pattern.nme.name}\")\n                val classSymbol = pattern.nme.resolveClassLikeSymbol(scope, context)\n                (scope, split => bindPrevious(c.Branch(nme, c.Pattern.Class(pattern.nme, classSymbol, false), bindAliasVars(split)) :: c.Split.Nil))\n              case s.LiteralPattern(literal) =>\n                nme.getOrCreateScrutinee\n                  .withAliasVar(nme)\n                  .getOrCreateLiteralPattern(literal)\n                  .addLocation(literal)\n                (scope, bindAliasVars.andThen(makeLiteralTest(nme, literal)(scope)).andThen(bindPrevious))\n              case s.TuplePattern(fields) =>\n                val (scopeWithNestedAll, bindNestedAll) = desugarTuplePattern(fields, nme, scope)\n                (scopeWithNestedAll, bindAliasVars.andThen(bindNestedAll).andThen(bindPrevious))\n              // Well, other patterns are not supported yet.\n              case _ =>\n                raiseDesugaringError(msg\"unsupported pattern\" -> pattern.toLoc)\n                acc\n            }\n          }\n      }\n    }()\n\n  private def flattenTupleFields(\n      parentScrutineeVar: Var,\n      parentScrutinee: Scrutinee,\n      fields: Ls[s.Pattern]\n  )(implicit context: Context): Ls[Opt[(Var, Opt[s.Pattern], Ls[Var])]] = {\n    // Make it `lazy` so that it will not be created if all fields are wildcards.\n    lazy val tuplePattern = parentScrutinee.getOrCreateTuplePattern\n    lazy val tupleDummyClassName = s\"Tuple$$${fields.length}\"\n    def flattenPattern(\n        pattern: s.Pattern,\n        index: Int,\n        subScrutineeVarOpt: Opt[(Var, Scrutinee)],\n        aliasVars: Ls[Var],\n    ): Opt[(Var, Opt[s.Pattern], Ls[Var])] = {\n      lazy val (subScrutineeVar, subScrutinee) = subScrutineeVarOpt.getOrElse {\n        val subScrutineeVar = freshSubScrutineeVar(parentScrutineeVar, tupleDummyClassName, index)\n        val symbol = new LocalTermSymbol(subScrutineeVar)\n        val subScrutinee = tuplePattern.getField(index).withAliasVar(subScrutineeVar.withSymbol(symbol))\n        symbol.addScrutinee(subScrutinee)\n        (subScrutineeVar, subScrutinee)\n      }\n      pattern match {\n        case _: s.EmptyPattern => N\n        case s.NamePattern(name) =>\n          S((name.withFreshSymbol.withScrutinee(tuplePattern.getField(index)), N, aliasVars.reverse))\n        case parameterPattern @ (s.ClassPattern(_, _, _) | s.LiteralPattern(_) | s.TuplePattern(_)) =>\n          val subScrutineeVar = freshSubScrutineeVar(parentScrutineeVar, tupleDummyClassName, index)\n          val symbol = new LocalTermSymbol(subScrutineeVar)\n          symbol.addScrutinee(tuplePattern.getField(index).withAliasVar(subScrutineeVar))\n          S((subScrutineeVar.withSymbol(symbol), S(parameterPattern), aliasVars.reverse))\n        case parameterPattern @ s.ConcretePattern(nme @ (Var(\"true\") | Var(\"false\"))) =>\n          val subScrutineeVar = freshSubScrutineeVar(parentScrutineeVar, tupleDummyClassName, index)\n          val symbol = new LocalTermSymbol(subScrutineeVar)\n          symbol.addScrutinee(tuplePattern.getField(index).withAliasVar(subScrutineeVar))\n          S((subScrutineeVar.withSymbol(symbol), S(parameterPattern), aliasVars.reverse))\n        case parameterPattern @ s.AliasPattern(aliasVar, innerPattern) =>\n          println(s\"alias pattern found ${subScrutineeVar.name} -> ${aliasVar.name}\")\n          flattenPattern(innerPattern, index, S((subScrutineeVar, subScrutinee)), aliasVar.withFreshSymbol.withScrutinee(subScrutinee) :: aliasVars)\n        case pattern =>\n          raiseDesugaringError(msg\"unsupported pattern\" -> pattern.toLoc)\n          N\n      }\n    }\n    fields.iterator.zipWithIndex.map { case (pattern, index) => flattenPattern(pattern, index, N, Nil) }.toList\n  }\n\n  private def desugarTuplePattern(fields: Ls[s.Pattern], scrutineeVar: Var, initialScope: Scope)(implicit context: Context): (Scope, c.Split => c.Split) = {\n    val scrutinee = scrutineeVar.getOrCreateScrutinee.withAliasVar(scrutineeVar)\n    val nestedPatterns = flattenTupleFields(scrutineeVar, scrutinee, fields)\n    val bindFields = nestedPatterns.iterator.zipWithIndex.foldRight[c.Split => c.Split](identity) {\n      case ((N, _), bindNextField) => bindNextField\n      case ((S((parameter, _, _)), index), bindNextField) => \n        val indexVar = Var(index.toString).withLoc(parameter.toLoc)\n        bindNextField.andThen { c.Split.Let(false, parameter, Sel(scrutineeVar, indexVar), _) }\n    }\n    val scopeWithFields = initialScope ++ nestedPatterns.flatMap(_.map(_._1.symbol))\n    desugarNestedPatterns(nestedPatterns, scopeWithFields, bindFields)\n  }\n\n  private def desugarPatternSplit(\n      scrutineeTerm: Term,\n      split: s.PatternSplit\n  )(implicit scope: Scope, context: Context): c.Split = {\n    def rec(scrutineeVar: Var, split: s.PatternSplit)(implicit scope: Scope): c.Split = split match {\n      case s.Split.Cons(head, tail) =>\n        val scrutineeSymbol = scrutineeVar.getOrResolveTermSymbol\n        val scrutinee = scrutineeSymbol.getOrCreateScrutinee\n        scrutinee.addAliasVar(scrutineeVar)\n        // Some functions that allow me to write less code, this function was\n        // very long before I introduced them.\n        def desugarRight(implicit scope: Scope) =\n          desugarTermSplit(head.continuation)(PartialTerm.Empty, scope, context)\n        def desugarTail(implicit scope: Scope) = rec(scrutineeVar, tail)\n        def desugarPatternBranch(pattern: s.Pattern): c.Split = pattern match {\n          case pattern @ s.AliasPattern(aliasVar, nestedPattern) =>\n            scrutinee.addAliasVar(aliasVar.withFreshSymbol)\n            c.Split.Let(false, aliasVar, scrutineeVar, desugarPatternBranch(nestedPattern))\n          case s.LiteralPattern(literal) =>\n            scrutinee.getOrCreateLiteralPattern(literal).addLocation(literal)\n            c.Branch(scrutineeVar, c.Pattern.Literal(literal), desugarRight) :: desugarTail\n          case s.ConcretePattern(nme @ (Var(\"true\") | Var(\"false\"))) =>\n            val classSymbol = nme.resolveClassLikeSymbol\n            scrutinee.getOrCreateClassPattern(classSymbol, false).addLocation(nme)\n            c.Branch(\n              scrutinee = scrutineeVar,\n              pattern = c.Pattern.Class(nme, classSymbol, false),\n              continuation = desugarRight\n            ) :: desugarTail\n          case s.ConcretePattern(nme) =>\n            val testVar = context.freshTest().withFreshSymbol\n            val testTerm = App(Var(\"===\"), PlainTup(scrutineeVar, nme))\n            c.Split.Let(false, testVar, testTerm,\n              c.Branch(testVar, truePattern, desugarRight(scope + testVar.symbol)) :: desugarTail)\n          case s.EmptyPattern(_) | s.NamePattern(Var(\"_\")) =>\n            desugarRight ++ desugarTail\n          case s.NamePattern(nme) =>\n            // If the top-level pattern is a name pattern, we need to check if\n            // `nme` shadows any variables in the scope. For example, code\n            // `fun f(x, y) = if x is y then \"yes\" else \"no\"` may read like\n            // `if x === y then \"yes\" else \"no\"`.\n            scope.getTermSymbol(nme.name) match {\n              case S(shadowed) =>\n                raiseDesugaringWarning(\n                  msg\"the outer binding `${nme.name}`\" -> shadowed.nameVar.toLoc,\n                  msg\"is shadowed by name pattern `${nme.name}`\" -> nme.toLoc\n                )\n              case N => ()\n            }\n            val symbol = freshSymbol(nme).withScrutinee(scrutinee)\n            val scopeWithSymbol = scope + symbol\n            c.Branch(scrutineeVar, c.Pattern.Name(nme.withSymbol(symbol)),\n              desugarRight(scopeWithSymbol)) :: desugarTail(scopeWithSymbol)\n          case pattern @ s.ClassPattern(nme, fields, rfd) =>\n            val (scopeWithAll, bindAll) = desugarClassPattern(pattern, scrutineeVar, scope, rfd)\n            bindAll(desugarRight(scopeWithAll)) :: desugarTail\n          case s.TuplePattern(fields) =>\n            val (scopeWithAll, bindAll) = desugarTuplePattern(fields, scrutineeVar, scope)\n            bindAll(desugarRight(scopeWithAll)) ++ desugarTail\n          case pattern @ s.RecordPattern(_) =>\n            raiseDesugaringError(msg\"record pattern is not supported for now\" -> pattern.toLoc)\n            desugarTail\n        }\n        desugarPatternBranch(head.pattern)\n      case s.Split.Let(isRec, nme, rhs, tail) =>\n        c.Split.Let(isRec, nme, rhs, rec(scrutineeVar, tail)(scope + nme.withFreshSymbol.symbol)) // <-- Weird use.\n      case s.Split.Else(default) => c.Split.Else(default)\n      case s.Split.Nil => c.Split.Nil\n    }\n    scrutineeTerm match {\n      case nme: Var => rec(nme.withResolvedTermSymbol, split)\n      case other =>\n        val alias = context.freshScrutineeVar().withFreshSymbol\n        c.Split.Let(false, alias, other, rec(alias, split)(scope + alias.symbol))\n    }\n  }\n}\n\nobject Desugaring {\n  /** Make a term like `ClassName.unapply(scrutinee)`. */\n  private def makeUnapplyCall(scrutinee: Var, className: Var) = \n    App(Sel(className, Var(\"unapply\").withLocOf(className)), Tup(N -> Fld(FldFlags.empty, scrutinee) :: Nil))\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/stages/Normalization.scala",
    "content": "package mlscript\npackage ucs\npackage stages\n\nimport mlscript.utils._, shorthands._, Message.MessageContext\nimport context.{Context, Scrutinee}\nimport display.{showNormalizedTerm, showSplit}\nimport syntax.core.{Pattern, Branch, Split}\nimport pretyper.symbol._\nimport pretyper.{Diagnosable, Scope, Traceable}\n\ntrait Normalization { self: Desugarer with Traceable =>\n  import Normalization._\n\n  private def fillImpl(these: Split, those: Split)(implicit\n      scope: Scope,\n      context: Context,\n      declaredVars: Set[Var],\n      shouldReportDiscarded: Bool\n  ): Split =\n    if (these.isFull) {\n      reportUnreachableCase(those, these, onlyIf = those =/= Split.Nil && shouldReportDiscarded)\n    } else (these match {\n      case these @ Split.Cons(head, tail) =>\n        these.copy(tail = fillImpl(tail, those))\n      case these @ Split.Let(_, nme, _, tail) =>\n        println(s\"fill let binding ${nme.name}\")\n        if (scope.getTermSymbol(nme.name).isDefined && (those.freeVars contains nme)) {\n          val fresh = context.freshShadowed()\n          val thoseWithShadowed = Split.Let(false, nme, fresh, those)\n          val concatenated = these.copy(tail = fillImpl(tail, thoseWithShadowed))\n          Split.Let(false, fresh, nme, concatenated)\n        } else {\n          these.copy(tail = fillImpl(tail, those)(scope, context, declaredVars + nme, false))\n        }\n      case _: Split.Else => these\n      case Split.Nil => those.withoutBindings(declaredVars).markAsFallback()\n    })\n\n  private implicit class SplitOps(these: Split) {\n    /**\n      * Fill the split into the previous split. \n      *\n      * @param those the split to append\n      * @param shouldReportDiscarded whether we should raise an error if the given\n      *                        split is discarded because of the else branch\n      * @param declaredVars the generated variables which have been declared\n      * @return the concatenated split\n      */\n    def fill(\n        those: Split,\n        declaredVars: Set[Var],\n        shouldReportDiscarded: Bool,\n    )(implicit\n        scope: Scope,\n        context: Context,\n    ): Split =\n      trace(s\"fill <== vars = ${declaredVars.iterator.map(_.name).mkString(\"{\", \", \", \"}\")}\") {\n        println(s\"LHS: ${showSplit(these)}\")\n        println(s\"RHS: ${showSplit(those)}\")\n        fillImpl(these, those)(scope, context, declaredVars, shouldReportDiscarded)\n      }(sp => s\"fill ==> ${showSplit(sp)}\")\n\n    def :++(tail: => Split): Split = {\n      if (these.isFull) {\n        println(\"tail is discarded\")\n        // raiseDesugaringWarning(msg\"Discarded split because of else branch\" -> these.toLoc)\n        these\n      } else {\n        these ++ tail\n      }\n    }\n  }\n\n  /** We don't care about `Pattern.Name` because they won't appear in `specialize`. */\n  private implicit class PatternOps(val self: Pattern) extends AnyRef {\n    /** Checks if two patterns are the same. */\n    def =:=(other: Pattern): Bool = (self, other) match {\n      case (Pattern.Class(_, s1, _), Pattern.Class(_, s2, _)) => s1 === s2\n      case (Pattern.Literal(l1), Pattern.Literal(l2)) => l1 === l2\n      case (_, _) => false\n    }\n    /** Checks if `self` can be subsumed under `other`. */\n    def <:<(other: Pattern): Bool = {\n      def mk(pattern: Pattern): Opt[Lit \\/ TypeSymbol] = pattern match {\n        case Pattern.Class(_, s, _) => S(R(s))\n        case Pattern.Literal(l) => S(L(l))\n        case _ => N\n      }\n      compareCasePattern(mk(self), mk(other))\n    }\n    /**\n      * If two class-like patterns has different `refined` flag. Report the\n      * inconsistency as a warning.\n      */\n    def reportInconsistentRefinedWith(other: Pattern): Unit = (self, other) match {\n      case (Pattern.Class(n1, _, r1), Pattern.Class(n2, _, r2)) if r1 =/= r2 =>\n        def be(value: Bool): Str = if (value) \"is\" else \"is not\"\n        raiseDesugaringWarning(\n          msg\"inconsistent refined pattern\" -> other.toLoc,\n          msg\"pattern `${n1.name}` ${be(r1)} refined\" -> n1.toLoc,\n          msg\"but pattern `${n2.name}` ${be(r2)} refined\" -> n2.toLoc\n        )\n      case (_, _) => ()\n    }\n    /** If the pattern is a class-like pattern, override its `refined` flag. */\n    def markAsRefined: Unit = self match {\n      case self: Pattern.Class => self.refined = true\n      case _ => ()\n    }\n  }\n  \n\n  /**\n    * Normalize core abstract syntax to MLscript syntax.\n    *\n    * @param split the split to normalize\n    * @return the normalized term\n    */ \n  @inline protected def normalize(split: Split)(implicit\n      scope: Scope,\n      context: Context\n  ): Term = normalizeToTerm(split, Set.empty)(scope, context)\n\n  private def errorTerm: Term = Var(\"error\")\n\n  private def normalizeToTerm(split: Split, declaredVars: Set[Var])(implicit\n      scope: Scope,\n      context: Context,\n  ): Term = trace(s\"normalizeToTerm <== ${showSplit(split)}\") {\n    normalizeToTermImpl(split, declaredVars)\n  }(split => \"normalizeToTerm ==> \" + showNormalizedTerm(split))\n\n  private def normalizeToTermImpl(split: Split, declaredVars: Set[Var])(implicit\n      scope: Scope,\n      context: Context,\n  ): Term =\n    split match {\n      case Split.Cons(head, tail) =>\n        head match {\n          case Branch(scrutinee, Pattern.Name(nme), _) =>\n            println(s\"ALIAS: ${scrutinee.name} is ${nme.name}\")\n            val (wrap, realTail) = preventShadowing(nme, tail)\n            val continuation = head.continuation.fill(realTail, declaredVars, true)\n            wrap(Let(false, nme, scrutinee, normalizeToTermImpl(continuation, declaredVars)))\n          // Skip Boolean conditions as scrutinees, because they only appear once.\n          case Branch(test, pattern @ Pattern.Class(nme @ Var(\"true\"), _, _), _) if context.isTestVar(test) =>\n            println(s\"TRUE: ${test.name} is true\")\n            val continuation = head.continuation.fill(tail, declaredVars, false)\n            val whenTrue = normalizeToTerm(continuation, declaredVars)\n            val whenFalse = normalizeToCaseBranches(tail, declaredVars)\n            CaseOf(test, Case(nme, whenTrue, whenFalse)(refined = false))\n          case Branch(Scrutinee.WithVar(scrutineeVar, scrutinee), pattern @ (Pattern.Literal(_) | Pattern.Class(_, _, _)), _) =>\n            println(s\"CONS: ${scrutineeVar.name} is $pattern\")\n            val continuation = head.continuation.fill(tail, declaredVars, false)\n            val whenTrue = normalizeToTerm(specialize(continuation, +, scrutineeVar, scrutinee, pattern), declaredVars)\n            val whenFalse = normalizeToCaseBranches(specialize(tail, `-`(head.continuation.isFull), scrutineeVar, scrutinee, pattern).clearFallback(), declaredVars)\n            CaseOf(scrutineeVar, Case(pattern.toSimpleTerm, whenTrue, whenFalse)(refined = pattern.refined))\n          case Branch(scrutinee, pattern, _) =>\n            raiseDesugaringError(msg\"unsupported pattern matching: ${scrutinee.name} is ${pattern.toString}\" -> pattern.toLoc)\n            errorTerm\n        }\n      case Split.Let(_, nme, _, tail) if context.isScrutineeVar(nme) && declaredVars.contains(nme) =>\n        println(s\"LET: SKIP already declared scrutinee ${nme.name}\")\n        normalizeToTermImpl(tail, declaredVars)\n      case Split.Let(rec, nme, rhs, tail) if context.isGeneratedVar(nme) =>\n        println(s\"LET: generated ${nme.name}\")\n        Let(rec, nme, rhs, normalizeToTermImpl(tail, declaredVars + nme)(scope, context))\n      case Split.Let(rec, nme, rhs, tail) =>\n        println(s\"LET: ${nme.name}\")\n        Let(rec, nme, rhs, normalizeToTermImpl(tail, declaredVars))\n      case Split.Else(default) =>\n        println(s\"DFLT: ${default.showDbg}\")\n        default\n      case Split.Nil =>\n        // raiseDesugaringError(msg\"unexpected empty split found\" -> N)\n        errorTerm\n    }\n\n  private def normalizeToCaseBranches(split: Split, declaredVars: Set[Var])(implicit\n      scope: Scope,\n      context: Context,\n  ): CaseBranches =\n    trace(s\"normalizeToCaseBranches <==\") {\n      split match {\n        // case Split.Cons(head, Split.Nil) => Case(head.pattern, normalizeToTerm(head.continuation), NoCases)\n        case other: Split.Cons => Wildcard(normalizeToTerm(other, declaredVars))\n        case Split.Let(_, nme, _, tail) if context.isScrutineeVar(nme) && declaredVars.contains(nme) =>\n          normalizeToCaseBranches(tail, declaredVars)\n        case Split.Let(rec, nme, rhs, tail) =>\n          val newDeclaredVars = if (context.isGeneratedVar(nme)) declaredVars + nme else declaredVars\n          normalizeToCaseBranches(tail, newDeclaredVars)(scope, context) match {\n            case NoCases => Wildcard(rhs)\n            case Wildcard(term) => Wildcard(Let(rec, nme, rhs, term))\n            case _: Case => die\n          }\n        case Split.Else(default) => Wildcard(default)\n        case Split.Nil => NoCases\n      }\n    }(r => \"normalizeToCaseBranches ==>\")\n\n  /**\n    * Specialize `split` with the assumption that `scrutinee` matches `pattern`.\n    * If `matchOrNot` is `true`, the function _keeps_ branches that agree on\n    * `scrutinee` matches `pattern`. Otherwise, the function _removes_ branches\n    * that agree on `scrutinee` matches `pattern`.\n    */\n  private def specialize(\n      split: Split,\n      mode: Mode,\n      scrutineeVar: Var,\n      scrutinee: Scrutinee,\n      pattern: Pattern\n  )(implicit context: Context): Split = \n    trace(s\"S$mode <== ${scrutineeVar.name} is ${pattern} : ${showSplit(split, true)}\"){\n      val specialized = specializeImpl(split)(mode, scrutineeVar, scrutinee, pattern, context)\n      // if (split =/= Split.Nil && specialized === Split.Nil && !split.isFallback) {\n      //   raiseDesugaringWarning(msg\"the case is unreachable\" -> split.toLoc)\n      // }\n      specialized\n    }(r => s\"S$mode ==> ${showSplit(r, true)}\")\n\n  /**\n   * This function does not trace. Call it when handling `tail`s, so we can get\n   * flattened debug logs.\n   * @param keepOrRemove `N` if S+ or `S(...)` if S-. If we don't need to track\n   *                     duplication information, this parameter can be denoted\n   *                     by just a Boolean variable.\n   */\n  private def specializeImpl(split: Split)(implicit\n      mode: Mode,\n      scrutineeVar: Var,\n      scrutinee: Scrutinee,\n      pattern: Pattern,\n      context: Context): Split = split match {\n    case split @ Split.Cons(head, tail) =>\n      println(s\"CASE Cons ${head.showDbg}\")\n      lazy val continuation = specialize(head.continuation, mode, scrutineeVar, scrutinee, pattern)\n      head match {\n        case Branch(thatScrutineeVar, Pattern.Name(alias), _) =>\n          Split.Let(false, alias, thatScrutineeVar, continuation)\n        case Branch(test, Pattern.Class(Var(\"true\"), _, _), _) if context.isTestVar(test) =>\n          head.copy(continuation = continuation) :: specializeImpl(tail)\n        case Branch(Scrutinee.WithVar(thatScrutineeVar, thatScrutinee), thatPattern, _) =>\n          if (scrutinee === thatScrutinee) mode match {\n            case + =>\n              println(s\"Case 1.1: ${scrutineeVar.name} === ${thatScrutineeVar.name}\")\n              if (thatPattern =:= pattern) {\n                println(s\"Case 1.1.1: $pattern =:= $thatPattern\")\n                thatPattern reportInconsistentRefinedWith pattern\n                continuation :++ specializeImpl(tail)\n              } else if (thatPattern <:< pattern) {\n                println(s\"Case 1.1.2: $pattern <:< $thatPattern\")\n                pattern.markAsRefined; split\n              } else {\n                println(s\"Case 1.1.3: $pattern is unrelated with $thatPattern\")\n                // The `continuation` is discarded because `thatPattern` is unrelated\n                // to the specialization topic.\n                if (!split.isFallback) {\n                  println(s\"report warning\")\n                  if (pattern <:< thatPattern) {\n                    raiseDesugaringWarning(\n                      msg\"the pattern always matches\" -> thatPattern.toLoc,\n                      msg\"the scrutinee was matched against ${pattern.toString}\" -> pattern.toLoc,\n                      msg\"which is a subtype of ${thatPattern.toString}\" -> (pattern match {\n                        case Pattern.Class(_, symbol, _) => symbol.defn.toLoc\n                        case _ => thatPattern.getLoc\n                      }))\n                    continuation :++ specializeImpl(tail)\n                  } else {\n                    raiseDesugaringWarning(\n                      msg\"possibly conflicting patterns for this scrutinee\" -> scrutineeVar.toLoc,\n                      msg\"the scrutinee was matched against ${pattern.toString}\" -> pattern.toLoc,\n                      msg\"which is unrelated with ${thatPattern.toString}\" -> thatPattern.toLoc)\n                    specializeImpl(tail)\n                  }\n                } else {\n                  specializeImpl(tail)\n                }\n              }\n            case -(full) =>\n              println(s\"Case 1.2: ${scrutineeVar.name} === ${thatScrutineeVar.name}\")\n              thatPattern reportInconsistentRefinedWith pattern\n              val samePattern = thatPattern =:= pattern\n              if (samePattern || thatPattern <:< pattern) {\n                println(s\"Case 1.2.1: $pattern =:= (or <:<) $thatPattern\")\n                // The `continuation` is discarded because `thatPattern` is related\n                // to the specialization topic.\n                println(s\"`${thatScrutineeVar.name} is ${thatPattern}` is${if (split.isFallback) \" \" else \" not \"}fallback\")\n                println(s\"already removed = $full\")\n                if (!split.isFallback && full && !head.continuation.isEmpty) {\n                  println(s\"report warning\")\n                  if (pattern === thatPattern) {\n                    raiseDesugaringWarning(\n                      msg\"found a duplicated case\" -> thatPattern.toLoc,\n                      msg\"there is an identical pattern ${pattern.toString}\" -> pattern.toLoc,\n                    )\n                  } else {\n                    raiseDesugaringWarning(\n                      msg\"found a duplicated case\" -> thatPattern.toLoc,\n                      msg\"the case is covered by pattern ${pattern.toString}\" -> pattern.toLoc,\n                      msg\"due to the subtyping relation\" -> (thatPattern match {\n                        case Pattern.Class(_, symbol, _) => symbol.defn.getLoc\n                        case _ => thatPattern.toLoc\n                      })\n                    )\n                  }\n                }\n                specializeImpl(tail)(\n                  `-`(if (samePattern) continuation.isFull else full),\n                  scrutineeVar, scrutinee, pattern, context)\n              } else {\n                println(s\"Case 1.2.2: $pattern are unrelated to $thatPattern\")\n                split.copy(tail = specializeImpl(tail))\n              }\n          } else {\n            println(s\"Case 2: ${scrutineeVar.name} =/= ${thatScrutineeVar.name}\")\n            head.copy(continuation = continuation) :: specializeImpl(tail)\n          }\n        case _ =>\n          raiseDesugaringError(msg\"unsupported pattern\" -> pattern.toLoc)\n          split\n      }\n    case split @ Split.Let(_, nme, _, tail) =>\n      println(s\"CASE Let ${nme.name}\")\n      split.copy(tail = specializeImpl(tail))\n    case Split.Else(_) => println(\"CASE Else\"); split\n    case Split.Nil => println(\"CASE Nil\"); split\n  }\n\n  /**\n    * If you want to prepend `tail` to another `Split` where the `nme` takes\n    * effects, you should use this function to prevent shadowing.\n    */\n  private def preventShadowing(nme: Var, tail: Split)(implicit\n      scope: Scope,\n      context: Context\n  ): (Term => Term, Split) = scope.getTermSymbol(nme.name) match {\n    case S(symbol) if tail.freeVars contains nme =>\n      val stashVar = context.freshShadowed()\n      ((body: Term) => Let(false, stashVar, nme, body)) ->\n        Split.Let(false, nme, stashVar, tail)\n    case S(_) | N => identity[Term] _ -> tail\n  }\n}\n\nobject Normalization {\n  /** Specialization mode */\n  sealed abstract class Mode\n  final case object + extends Mode {\n    override def toString(): String = \"+\"\n  }\n  final case class -(full: Bool) extends Mode {\n    override def toString(): String = s\"-($full)\"\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/stages/PartialTerm.scala",
    "content": "package mlscript\npackage ucs.stages\n\nimport utils._, shorthands._\n\n/**\n  * A `PartialTerm` represents a possibly incomplete term.\n  * We'd better precisely track detailed locations of each parts.\n  */\nsealed abstract class PartialTerm {\n  /** Individual terms that used to build this `PartialTerm`. */\n  def terms: Iterator[Term]\n\n  override def toString(): String = this match {\n    case PartialTerm.Empty => \"<empty>\"\n    case PartialTerm.Total(term, _) => s\"<total> ${term.showDbg}\"\n    case PartialTerm.Half(lhs, op, _) => s\"<half> ${lhs.showDbg} ${op.name}\"\n  }\n}\n\nobject PartialTerm {\n  sealed abstract class Incomplete extends PartialTerm {\n    def addTerm(term: Term): PartialTerm.Total\n  }\n\n  final case object Empty extends Incomplete {\n    override def terms: Iterator[Term] = Iterator.empty\n    def addTerm(term: Term): Total = Total(term, term :: Nil)\n  }\n\n  final case class Total(term: Term, parts: Ls[Term]) extends PartialTerm {\n    override def terms: Iterator[Term] = parts.reverseIterator\n    def addOp(op: Var): Half = Half(term, op, op :: parts)\n    def get: Term = term\n  }\n\n  final case class Half(lhs: Term, op: Var, parts: Ls[Term]) extends Incomplete {\n    override def terms: Iterator[Term] = parts.reverseIterator\n    def addTerm(rhs: Term): Total = {\n      val (realRhs, extraExprOpt) = separatePattern(rhs)\n      val leftmost = App(op, PlainTup(lhs, realRhs))\n      extraExprOpt match {\n        case N            => Total(leftmost, parts)\n        case S(extraExpr) => Total(App(Var(\"and\"), PlainTup(leftmost, extraExpr)), extraExpr :: parts)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/stages/PostProcessing.scala",
    "content": "package mlscript\npackage ucs\npackage stages\n\nimport annotation.tailrec\nimport context.{Context, Pattern, Scrutinee}\nimport pretyper.symbol._\nimport utils._, shorthands._, Message.MessageContext\n\ntrait PostProcessing { self: Desugarer with mlscript.pretyper.Traceable =>\n  import PostProcessing._\n\n  def postProcess(term: Term)(implicit context: Context): Term = trace(s\"postProcess <== ${term.showDbg}\") {\n    // Normalized terms are constructed using `Let` and `CaseOf`.\n    term match {\n      case top @ CaseOf(testVar: Var, fst @ Case(Var(\"true\"), trueBranch, Wildcard(falseBranch))) if context.isTestVar(testVar) =>\n        println(s\"TEST: ${testVar.name}\")\n        top.copy(cases = fst.copy(body = postProcess(trueBranch), rest = Wildcard(postProcess(falseBranch)))(refined = fst.refined))\n      case top @ CaseOf(Scrutinee(_), Wildcard(body)) => body\n      case top @ CaseOf(Scrutinee.WithVar(scrutineeVar, scrutinee), fst @ Case(className: Var, body, NoCases)) =>\n        println(s\"UNARY: ${scrutineeVar.name} is ${className.name}\")\n        top.copy(cases = fst.copy(body = postProcess(body))(refined = fst.refined))\n      case top @ CaseOf(Scrutinee.WithVar(scrutineeVar, scrutinee), fst @ Case(pat, trueBranch, Wildcard(falseBranch))) =>\n        println(s\"BINARY: ${scrutineeVar.name} is ${pat.showDbg}\")\n        println(s\"patterns of `${scrutineeVar.name}`: ${scrutinee.showPatternsDbg}\")\n        // Post-process the true branch.\n        println(\"TRUE\")\n        val processedTrueBranch = postProcess(trueBranch)\n        // Post-process the false branch.\n        println(\"FALSE\")\n        // Get all patterns, except the current one `pat`.\n        val patterns = scrutinee.patternsIterator.filter(!_.matches(pat)).toList\n        println(s\"found ${patterns.length} patterns to distentangle: ${patterns.iterator.map(_.showDbg).mkString(\", \")}\")\n        val (default, cases) = patterns\n          // Search each pattern in `falseBranch`. If there exists a branch for\n          // the given pattern, we separate the branch body from the term. The\n          // leftover term will be used in next iteration, until there is no\n          // term left (i.e., `leftoverTerm` is `N`).\n          .foldLeft[Opt[Term] -> Ls[(Pattern, Opt[Loc], Term)]](S(falseBranch) -> Nil) {\n            // If the remaining term is not empty, we continue our search.\n            case ((S(remainingTerm), cases), pattern) =>\n              println(s\"searching for branches of pattern ${pattern.showDbg}\")\n              val (leftoverTerm, extracted) = disentangleTerm(remainingTerm)(\n                context, scrutineeVar, scrutinee, pattern)\n              trimEmptyTerm(leftoverTerm) -> (extracted match {\n                // `remainingTerm` does not have branches for `pattern`.\n                case N =>\n                  println(s\"cannot extract pattern ${pattern.showDbg}\")\n                  cases\n                // We extracted a term and it needs to be further post-processed.\n                case terms @ S(extractedTerm) => \n                  println(s\"extracted a term of pattern ${pattern.showDbg}\")\n                  (pattern, pattern.firstOccurrence, postProcess(extractedTerm)) :: cases\n              })\n            // If no terms are left, we pass on `acc` until the iteration ends.\n            case (acc @ (N, _), _) => acc\n          }\n        println(s\"found ${cases.length} case branches\")\n        println(s\"default branch: ${default.fold(\"<empty>\")(_.showDbg)}\")\n        val postProcessedDefault = default.map(postProcess)\n        // Assemble a `CaseBranches`.\n        val actualFalseBranch = cases.foldRight[CaseBranches](\n          postProcessedDefault.fold[CaseBranches](NoCases)(Wildcard(_))\n        ) { case ((pattern, loc, body), rest) =>\n          Case(pattern.toCasePattern, body, rest)(refined = pattern.refined)\n        }\n        // Assemble the final `CaseOf`.\n        top.copy(cases = fst.copy(body = processedTrueBranch, rest = actualFalseBranch)\n          (refined = fst.refined))\n      // We recursively process the body of `Let` bindings.\n      case let @ Let(_, _, _, body) => let.copy(body = postProcess(body))\n      // Otherwise, this is not a part of a normalized term.\n      case other => println(s\"CANNOT post-process ${other.showDbg}\"); other\n    }\n  }(res => s\"postProcess ==> ${res.showDbg}\")\n\n  private def trimEmptyTerm(term: Term): Opt[Term] = term match {\n    case k @ CaseOf(_, cases) =>\n      trimEmptyCaseBranches(cases).flatMap(_ match {\n        case cases: Case => S(k.copy(cases = cases))\n        case NoCases => N\n        case Wildcard(body) => S(body)\n      })\n    case let @ Let(_, _, _, body) => trimEmptyTerm(body).map(t => let.copy(body = t))\n    case _ => S(term)\n  }\n\n  private def trimEmptyCaseBranches(cases: CaseBranches): Opt[CaseBranches] = cases match {\n    case NoCases => N\n    case w @ Wildcard(body) => trimEmptyTerm(body).map(t => w.copy(body = t))\n    case k @ Case(_, body, rest) =>\n      (trimEmptyTerm(body), trimEmptyCaseBranches(rest)) match {\n        case (N, N) => N\n        case (S(body), N) => S(k.copy(body = body, rest = NoCases)(refined = k.refined))\n        case (N, S(rest)) => S(rest)\n        case (S(body), S(rest)) => S(k.copy(body = body, rest = rest)(refined = k.refined))\n      }\n  }\n\n  /**\n    * Merge two optional terms. If both are not empty we will call the other\n    * `mergeTerms`.\n    */\n  private def mergeTerms(t1: Opt[Term], t2: Opt[Term]): Opt[Term] =\n    (t1, t2) match {\n      case (N, N) => N\n      case (S(t1), N) => S(t1)\n      case (N, S(t2)) => S(t2)\n      case (S(t1), S(t2)) => S(mergeTerms(t1, t2))\n    }\n\n  /**\n    * Merge two terms. In most cases, two terms cannot be merged. This function\n    * replaces `Wildcard` in `t1` with `t2`.\n    */\n  private def mergeTerms(t1: Term, t2: Term): Term = {\n    def recTerm(lhs: Term, rhs: Term): Term = lhs match {\n      case lhs @ Let(_, _, _, body) => lhs.copy(body = mergeTerms(body, rhs))\n      case lhs @ CaseOf(scrutinee: Var, cases) =>\n        lhs.copy(cases = recCaseBranches(cases, rhs))\n      case _ =>\n        println(\"unreachable: \" + rhs.describe)\n        reportUnreachableCase(rhs, lhs)\n    }\n    def recCaseBranches(lhs: CaseBranches, rhs: Term): CaseBranches = lhs match {\n      case NoCases => Wildcard(rhs).withLocOf(rhs)\n      case Wildcard(body) => Wildcard(mergeTerms(body, rhs))\n      case lhs @ Case(_, _, rest) =>\n        lhs.copy(rest = recCaseBranches(rest, rhs))(refined = lhs.refined)\n    }\n    trace(s\"mergeTerms <==\") {\n      println(s\"LHS: ${t1.showDbg}\")\n      println(s\"RHS: ${t2.showDbg}\")\n      recTerm(t1, t2)\n    }(merged => s\"mergedTerms ==> ${merged.showDbg}\")\n  }\n\n  /**\n    * Disentangle case branches that match `scrutinee` against `className` from `term`.\n    * The `term` should be obtained from _normalization_. Because there may exists multiple\n    * `CaseOf`s which contains such case branches, we merge them on the fly.\n    * \n    * @param term the term to disentangle from\n    * @param scrutinee the symbol of the scrutinee variable\n    * @param className the class name\n    * @return the remaining term and the disentangled term\n    */\n  private def disentangleTerm(term: Term)(implicit\n      context: Context,\n      scrutineeVar: Var,\n      scrutinee: Scrutinee,\n      pattern: Pattern\n  ): (Term, Opt[Term]) = {\n    def rec(term: Term): (Term, Opt[Term]) =\n      term match {\n        // Disentangle pattern matching\n        case top @ CaseOf(Scrutinee.WithVar(otherScrutineeVar, otherScrutinee), cases) =>\n          if (scrutinee === otherScrutinee) {\n            println(s\"found a `CaseOf` that matches on `${scrutineeVar.name}`\")\n            val (n, y) = disentangleMatchedCaseBranches(cases)\n            (top.copy(cases = n), y)\n          } else {\n            println(s\"found a `CaseOf` that does NOT match on ${scrutineeVar.name}\")\n            val (n, y) = disentangleUnmatchedCaseBranches(cases)\n            (top.copy(cases = n), (if (y === NoCases) N else S(top.copy(cases = y))))\n          }\n        // Disentangle tests with two case branches\n        case top @ CaseOf(testVar: Var, Case(Var(\"true\"), whenTrue, Wildcard(whenFalse))) if context.isTestVar(testVar) =>\n          println(s\"TEST `${testVar.name}`\")\n          val (n1, y1) = disentangleTerm(whenTrue)\n          val (n2, y2) = disentangleTerm(whenFalse)\n          (\n            CaseOf(testVar, Case(Var(\"true\"), n1, Wildcard(n2))(false)),\n            (y1, y2) match {\n              case (N, N) => N\n              case (S(t1), N) => S(CaseOf(testVar, Case(Var(\"true\"), t1, Wildcard(n2))(false)))\n              case (N, S(t2)) => S(CaseOf(testVar, Case(Var(\"true\"), n1, Wildcard(t2))(false)))\n              case (S(t1), S(t2)) => S(CaseOf(testVar, Case(Var(\"true\"), t1, Wildcard(t2))(false)))\n            }\n          )\n        // For let bindings, we just go deeper.\n        case let @ Let(_, _, _, body) =>\n          val (n, y) = rec(body)\n          (let.copy(body = n), y.map(t => let.copy(body = t)))\n        // Otherwise, the scrutinee does not belong to the UCS term.\n        case other =>\n          println(s\"cannot disentangle ${other.showDbg}. STOP\")\n          other -> N\n      }\n    trace[(Term, Opt[Term])](s\"disentangleTerm <== ${scrutineeVar.name}: ${pattern.showDbg}\") {\n      rec(term)\n    }({ case (n, y) => s\"disentangleTerm ==> `${n.showDbg}` and `${y.fold(\"<empty>\")(_.showDbg)}`\" })\n  }\n\n  /**\n    * Helper function for `disentangleTerm`.\n    */\n  private def disentangleMatchedCaseBranches(cases: CaseBranches)(implicit\n      context: Context,\n      scrutineeVar: Var,\n      scrutinee: Scrutinee,\n      pattern: Pattern\n  ): (CaseBranches, Opt[Term]) =\n    cases match {\n      case NoCases => NoCases -> N\n      case wildcard @ Wildcard(body) =>\n        println(\"found a wildcard, go deeper\")\n        val (n, y) = disentangleTerm(body)\n        wildcard.copy(body = n) -> y\n      case kase @ Case(pat, body, rest) =>\n        println(s\"found a case branch matching against ${pat.showDbg}\")\n        if (pattern.matches(pat)) {\n          rest -> S(body)\n        } else {\n          val (n1, y1) = disentangleTerm(body)\n          val (n2, y2) = disentangleMatchedCaseBranches(rest)\n          (kase.copy(body = n1, rest = n2)(kase.refined), mergeTerms(y1, y2))\n        }\n    }\n\n  /** Helper function for `disentangleTerm`. */\n  private def disentangleUnmatchedCaseBranches(cases: CaseBranches)(implicit\n      context: Context,\n      scrutineeVar: Var,\n      scrutinee: Scrutinee,\n      pattern: Pattern\n  ): (CaseBranches, CaseBranches) =\n    cases match {\n      case NoCases => NoCases -> NoCases\n      case wildcard @ Wildcard(body) =>\n        println(\"found a wildcard, go deeper\")\n        val (n, y) = disentangleTerm(body)\n        (wildcard.copy(body = n), y.fold(NoCases: CaseBranches)(Wildcard(_)))\n      case kase @ Case(_, body, rest) =>\n        println(s\"found a case branch\")\n        val (n1, y1) = disentangleTerm(body)\n        val (n2, y2) = disentangleUnmatchedCaseBranches(rest)\n        (kase.copy(body = n1, rest = n2)(kase.refined), (y1 match {\n          case S(term) => kase.copy(body = term, rest = y2)(kase.refined)\n          case N => y2\n        }))\n    }\n}\n\nobject PostProcessing {\n  private object typeSymbolOrdering extends Ordering[TypeSymbol] {\n    override def compare(x: TypeSymbol, y: TypeSymbol): Int = {\n      (x.defn.toLoc, y.defn.toLoc) match {\n        case (S(xLoc), S(yLoc)) => xLoc.spanStart.compare(yLoc.spanStart)\n        case (_, _) => x.defn.name.compare(y.defn.name)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/stages/Transformation.scala",
    "content": "package mlscript\npackage ucs\npackage stages\n\nimport collection.immutable, annotation.tailrec, util.chaining._\nimport utils._, shorthands._, Message._\nimport syntax.source._, pretyper.Traceable\n\n/**\n  * Transform the parsed AST into an AST similar to the one in the paper.\n  * The parsed AST represents pattern with terms and does not distingiush\n  * `is` and `and` operators.\n  * The AST in the paper is more flexible. For example, it allows interleaved\n  * `let` bindings in operator splits.\n  */\ntrait Transformation { self: Desugarer with Traceable =>\n  import Transformation._\n\n  /** The entry point of transformation. */\n  def transform(`if`: If): TermSplit =\n    transformIfBody(`if`.body) ++ `if`.els.fold(Split.empty)(Split.default)\n\n  /**\n    * Transform a conjunction of terms into a nested split. The conjunction is\n    * of the following form.\n    * ```bnf\n    * conjunction ::= term \"is\" term conjunction-tail\n    *               | \"_\" conjunction-tail\n    *               | term conjunction-tail\n    * conjunction-tail ::= \"and\" conjunction\n    *                    | ε\n    * ```\n    * @param init a list of term representing the conjunction\n    * @param last the innermost split we should take if all terms of the\n    *             conjunction work\n    * @return\n    */\n  private def transformConjunction[B <: Branch](init: Ls[Term], last: TermSplit, skipWildcard: Bool): TermSplit =\n    init.foldRight(last) {\n      case (scrutinee is pattern, following) =>\n        val branch = PatternBranch(transformPattern(pattern), following).toSplit\n        TermBranch.Match(scrutinee, branch).toSplit\n      // Maybe we don't need `skipWildcard` flag and we should take care of\n      // wildcards at _this_ level in all cases.\n      case (Var(\"_\"), following) if skipWildcard => following\n      case (test, following) => TermBranch.Boolean(test, following).toSplit\n    }\n\n  private def transformIfBody(body: IfBody): TermSplit = trace(s\"transformIfBody <== ${body.showDbg}\") {\n    body match {\n      case IfThen(expr, rhs) => transformConjunction(splitAnd(expr), Split.then(rhs), true)\n      case IfLet(isRec, name, rhs, body) => die\n      case IfElse(expr) => Split.then(expr)\n      case IfOpApp(lhs, Var(\"is\"), rhs) =>\n        val (tests, scrutinee) = extractLast(splitAnd(lhs))\n        transformConjunction(tests, TermBranch.Match(scrutinee, transformPatternMatching(rhs)).toSplit, false)\n      case IfOpApp(lhs, Var(\"and\"), rhs) => transformConjunction(splitAnd(lhs), transformIfBody(rhs), true)\n      case IfOpApp(lhs, op, rhs) => \n        val (init, last) = extractLast(splitAnd(lhs))\n        transformConjunction(init, TermBranch.Left(last, OperatorBranch.Binary(op, transformIfBody(rhs)).toSplit).toSplit, false)\n      case IfBlock(lines) =>\n        lines.foldLeft(Split.empty[TermBranch]) {\n          case (acc, L(body)) => acc ++ transformIfBody(body)\n          case (acc, R(NuFunDef(S(rec), nme, _, _, L(rhs)))) =>\n            acc ++ Split.Let(rec, nme, rhs, Split.Nil)\n          case (acc, R(statement)) =>\n            raiseDesugaringError(msg\"Unexpected statement in an if block\" -> statement.toLoc)\n            acc\n        }\n      case IfOpsApp(lhs, opsRhss) =>\n        splitAnd(lhs) match {\n          case init :+ (scrutinee is pattern) =>\n            // If `last` is in the form of `scrutinee is pattern`, the `op` in\n            // `opsRhss` must be `and`. Otherwise, it's a syntax error.\n            val innermost = transformBrokenIfOpsApp(opsRhss)\n            val inner = TermBranch.Match(scrutinee, PatternBranch(transformPattern(pattern), innermost).toSplit).toSplit\n            transformConjunction(init, inner, false)\n          case init :+ last =>\n            transformConjunction(init, TermBranch.Left(last, Split.from(opsRhss.map(transformOperatorBranch))).toSplit, false)\n          case _ => die\n        }\n    }\n  }(_ => \"transformIfBody ==> \")\n\n  /**\n    * Transform the case where `lhs` of `IfOpsApp` concludes pattern matching\n    * and we need to handle its `opsRhss`. This is special, because the first\n    * field of elements of `opsRhss` must be `and`.\n    */\n  private def transformBrokenIfOpsApp(opsRhss: Ls[Var -> IfBody]): TermSplit = {\n    opsRhss.iterator.flatMap {\n      case Var(\"and\") -> rhs => S(transformIfBody(rhs))\n      case op -> rhs =>\n        raiseDesugaringError(\n          msg\"cannot transform due to an illegal split operator ${op.name}\" -> op.toLoc,\n          msg\"the following branch will be discarded\" -> rhs.toLoc)\n        N\n    }.foldLeft(Split.Nil: TermSplit)(_ ++ _)\n  }\n  \n  private def transformOperatorBranch(opsRhs: Var -> IfBody): OperatorBranch =\n    opsRhs match {\n      case (op @ Var(\"is\"), rhs) => OperatorBranch.Match(op, transformPatternMatching(rhs))\n      case (op, rhs) => OperatorBranch.Binary(op, transformIfBody(rhs))\n    }\n\n  /**\n    * Transform an `IfBody` into a `PatternSplit`.\n    */\n  private def transformPatternMatching(body: IfBody): PatternSplit =\n    trace(s\"transformPatternMatching <== ${body.showDbg}\") {\n      body match {\n        case IfThen(expr, rhs) => \n          val ::(head, tail) = splitAnd(expr)\n          PatternBranch(transformPattern(head), transformConjunction(tail, Split.then(rhs), false)).toSplit\n        case IfOpApp(lhs, Var(\"and\"), rhs) =>\n          val ::(head, tail) = splitAnd(lhs)\n          PatternBranch(transformPattern(head), transformConjunction(tail, transformIfBody(rhs), false)).toSplit\n        case IfOpApp(lhs, op, rhs) =>\n          raiseDesugaringError(msg\"Syntactic split of patterns are not supported\" -> op.toLoc)\n          Split.Nil\n        case IfOpsApp(lhs, opsRhss) =>\n          // BEGIN TEMPORARY PATCH\n          // Generally, syntactic split of patterns are not supported. Examples\n          // like the following code is impossible.\n          // ```\n          // fun pairwise(xs) =\n          //   if xs is Cons of\n          //     x, Nil then [x, x]\n          //     x, Cons of x', tail then [x, x'] :: pairwise of tail\n          //     else Nil\n          // ```\n          // We could support this in future but it's disallowed for now. But I\n          // found some mis-parsed examples. For example, as in `zipWith.mls:76`.\n          // ```\n          // fun zipWith_wrong(f, xs, ys) =\n          //   if  xs is Cons(x, xs)\n          //     and ys is Cons(y, ys)\n          //     and zipWith_wrong(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n          //   else None\n          // ```\n          // This is parsed as `{ and ( Cons x xs ) [ is ys ( Cons y ys ) ] }`.\n          // I think it's not very well-formed. But I still implement it for not\n          // breaking existing tests.\n          val ::(pattern, tail) = splitAnd(lhs)\n          // Here, `pattern` will be `( Cons x xs )` and `tail` will be\n          // `[ is ys (Cons y ys) ]`. We can make a new `IfOpsApp`.\n          tail match {\n            case init :+ last =>\n              val remake = IfOpsApp(last, opsRhss)\n              val following = transformConjunction(init, transformIfBody(remake), true)\n              PatternBranch(transformPattern(pattern), following).toSplit\n            case _ => // This can only be `Nil`.\n              PatternBranch(transformPattern(pattern), transformBrokenIfOpsApp(opsRhss)).toSplit\n          }\n          // END TEMPORARY PATCH\n        case IfLet(rec, nme, rhs, body) => die\n        case IfBlock(lines) => lines.foldLeft(Split.empty[PatternBranch]) {\n          case (acc, L(body)) => acc ++ transformPatternMatching(body)\n          case (acc, R(NuFunDef(S(rec), nme, _, _, L(rhs)))) =>\n            acc ++ Split.Let(rec, nme, rhs, Split.Nil)\n          case (acc, R(statement)) =>\n            raiseDesugaringError(msg\"Unexpected statement in an if block\" -> statement.toLoc)\n            acc\n        }\n        case IfElse(expr) => Split.default(expr)\n      }\n    }(_ => \"transformPatternMatching ==>\")\n\n  private def transformTupleTerm(tuple: Tup): Ls[Pattern] =\n    tuple.fields.map(_._2.value |> transformPattern)\n\n  /**\n    * If we know the `term` represents a pattern, we can transform it to a\n    * pattern with this function.\n    *\n    * @param term the term representing a pattern\n    * @return \n    */\n  private def transformPattern(term: Term): Pattern = term match {\n    case wildcard @ Var(\"_\") => EmptyPattern(wildcard) // The case for wildcard.\n    case nme @ Var(\"true\" | \"false\") => ConcretePattern(nme)\n    case nme @ Var(name) if name.isCapitalized => ClassPattern(nme, N, refined = false)\n    case nme: Var => NamePattern(nme)\n    case literal: Lit => LiteralPattern(literal)\n    case App(Var(\"refined\"), PlainTup(p)) =>\n      transformPattern(p) match {\n        case cp: ClassPattern => cp.copy(refined = true).withLocOf(cp)\n        case p =>\n          raiseDesugaringError(msg\"only class patterns can be refined\" -> p.toLoc)\n          p\n      }\n    case App(Var(\"as\"), PlainTup(pattern, alias)) =>\n      alias match {\n        case nme @ Var(_) => AliasPattern(nme, transformPattern(pattern))\n        case other =>\n          raiseDesugaringError(msg\"the pattern alias must be a variable\" -> other.toLoc)\n          transformPattern(pattern)\n      }\n    case App(TyApp(classNme @ Var(_), targs), parameters: Tup) =>\n      raiseDesugaringWarning(msg\"type parameters in patterns are currently ignored\" -> Loc(targs))\n      ClassPattern(classNme, S(transformTupleTerm(parameters)), refined = false)\n    case App(classNme @ Var(_), parameters: Tup) =>\n      ClassPattern(classNme, S(transformTupleTerm(parameters)), refined = false)\n    case tuple: Tup => TuplePattern(transformTupleTerm(tuple))\n    case Blk((term: Term) :: Nil) => transformPattern(term) // A speical case for FunnyIndet.mls\n    case Bra(false, term) => transformPattern(term)\n    case other =>\n      println(s\"other $other\")\n      raiseDesugaringError(msg\"unknown pattern ${other.showDbg}\" -> other.toLoc)\n      EmptyPattern(other)\n  }\n\n  /**\n    * Split a term into a list of terms. Note that the return type is `::[Term]`\n    * because there should be at least one term even we don't split. It used to\n    * split right-associate `and` terms, but it turned out that `and` may\n    * nested in a left-associate manner. Therefore, the function now traverse\n    * the entire term and split all `and` terms.\n    */\n  private def splitAnd(t: Term): ::[Term] = {\n    @tailrec def rec(acc: Ls[Term], rest: ::[Term]): ::[Term] = rest.head match {\n      case lhs and rhs => rec(acc, ::(rhs, lhs :: rest.tail))\n      case sole => rest.tail match {\n        case Nil => ::(sole, acc)\n        case more @ ::(_, _) => rec(sole :: acc, more)\n      }\n    }\n    rec(Nil, ::(t, Nil)).tap { rs =>\n      println(s\"splitAnd ${t.showDbg} ==> ${rs.iterator.map(_.showDbg).mkString(\" ∧ \")}\")\n    }\n  }\n}\n\nobject Transformation {\n  private def extractLast[T](xs: List[T]): (List[T], T) = xs match {\n    case init :+ last => init -> last\n    case _ => die\n  }\n\n  /** Matches terms like `x is y`. */\n  private object is {\n    def unapply(term: Term): Opt[Term -> Term] = term match {\n      case App(Var(\"is\"), PlainTup(scrutinee, pattern)) => S(scrutinee -> pattern)\n      case _ => N\n    }\n  }\n\n  /** Matches terms like `x and y` */\n  private object and {\n    def unapply(term: Term): Opt[(Term, Term)] = term match {\n      case App(Var(\"and\"), PlainTup(lhs, rhs)) => S((lhs, rhs))\n      case _ => N\n    }\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/stages/package.scala",
    "content": "package mlscript\npackage ucs\n\nimport utils._, shorthands._\nimport pretyper.symbol.{ClassLikeSymbol, TypeSymbol}\n\npackage object stages {\n  /**\n    * Split a term into two parts: the pattern and the extra test.\n    * This is used to extract patterns from UCS conjunctions. For example,\n    * the second line results in `IfThen(Some(xv) and xv == 0, ...)`\n    * in the following case.\n    * \n    * ```\n    * if x is\n    *   Some(xv) and xv == 0 then ...\n    * ```\n    * \n    * We must separate `Some(xv)` from the term to complete the pattern\n    * `x is Some(xv)`.\n    *\n    * @param term a term which might contains a pattern and an extra test\n    * @return a tuple, whose the first element is the pattern and the second\n    *   element is the extra test\n    */\n  def separatePattern(term: Term): (Term, Opt[Term]) = term match {\n    case App(and @ Var(\"and\"), PlainTup(lhs, rhs)) => separatePattern(lhs) match {\n      case (pattern, N) => (pattern, S(rhs))\n      case (pattern, S(lhsRhs)) => (pattern, S(App(and, PlainTup(lhsRhs, rhs))))\n    }\n    case _ => (term, N)\n  }\n\n  /**\n    * Hard-coded subtyping relations used in normalization and coverage checking.\n    * Pass literals in `L` and pass variables together with `TypeSymbol` in `R`.\n    */\n  private[ucs] def compareCasePattern(\n      lhs: Opt[Lit \\/ TypeSymbol],\n      rhs: Opt[Lit \\/ TypeSymbol]\n  ): Bool = (lhs, rhs) match {\n    case (S(lhs), S(rhs)) => compareCasePattern(lhs, rhs)\n    case (_, _) => false\n  }\n  /**\n    * Hard-coded subtyping relations used in normalization and coverage checking.\n    * Pass literals in `L` and pass variables together with `TypeSymbol` in `R`.\n    */\n  private[stages] def compareCasePattern(\n      lhs: Lit \\/ TypeSymbol,\n      rhs: Lit \\/ TypeSymbol\n  ): Bool = (lhs, rhs) match {\n    case (_, R(s)) if s.name === \"Object\" => true\n    case (R(s1), R(s2)) if (s1.name === \"true\" || s1.name === \"false\") && s2.name === \"Bool\" => true\n    case (R(s1), R(s2)) if s1.name === \"Int\" && s2.name === \"Num\" => true\n    case (R(s1: ClassLikeSymbol), R(s2: ClassLikeSymbol)) => s1 <:< s2\n    case (L(IntLit(_)), R(s)) if s.name === \"Int\" || s.name === \"Num\" => true\n    case (L(StrLit(_)), R(s)) if s.name === \"Str\" => true\n    case (L(DecLit(_)), R(s)) if s.name === \"Num\" => true\n    case (_, _) => false\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/syntax/core.scala",
    "content": "package mlscript\npackage ucs\npackage syntax\n\nimport collection.mutable.{Set => MutSet}\nimport utils._, shorthands._, pretyper.symbol.ClassLikeSymbol, context.Scrutinee\n\npackage object core {\n  sealed abstract class Pattern extends Located {\n    def refined: Bool\n    def toSimpleTerm: SimpleTerm = this match {\n      case Pattern.Literal(literal) => literal\n      case Pattern.Class(nme, _, _) => nme\n      case Pattern.Name(_) => die\n    }\n    def declaredVars: Iterator[Var] = this match {\n      case _: Pattern.Literal | _: Pattern.Class => Iterator.empty\n      case Pattern.Name(nme) => Iterator.single(nme)\n    }\n    override def toString(): String = this match {\n      case Pattern.Literal(literal) => literal.idStr\n      case Pattern.Name(Var(name)) => name\n      case Pattern.Class(Var(name), _, rfd) => (if (rfd) \"refined \" else \"\") + name\n    }\n  }\n  object Pattern {\n    final case class Literal(literal: Lit) extends Pattern {\n      override def refined: Bool = false\n      override def children: Ls[Located] = literal :: Nil\n    }\n    final case class Name(nme: Var) extends Pattern {\n      override def refined: Bool = false\n      override def children: Ls[Located] = nme :: Nil\n    }\n    /**\n      * @param nme the name of the class-like symbol\n      * @param originallyRefined whether the class is marked as refined from\n      *                          in source AST\n      */\n    final case class Class(nme: Var, symbol: ClassLikeSymbol, originallyRefined: Bool) extends Pattern {\n      override def children: Ls[Located] = nme :: Nil\n\n      /**\n        * A mutable field to override the refinement status of the class. \n        * During normalization, if a case can be further refined in its\n        * descendants branches, we should mark it as `refined`. See relevant\n        * tests in `Normalization.mls`.\n        */\n      var refined: Bool = originallyRefined\n    }\n  }\n\n  final case class Branch(scrutinee: Var, pattern: Pattern, continuation: Split) extends Located {\n    override def children: List[Located] = scrutinee :: pattern :: continuation :: Nil\n\n    def showDbg: String = s\"${scrutinee.showDbg} is $pattern\"\n  }\n\n  sealed abstract class Split extends Located {\n    @inline def ::(head: Branch): Split = {\n      val res = Split.Cons(head, this)\n      // res.withFallbackOf(head.continuation)\n      if (head.continuation.isFallback) res.markAsFallback() else res\n    }\n    \n    /**\n      * Returns true if the split has an else branch.\n      */\n    lazy val isFull: Bool = this match {\n      case Split.Cons(_, tail) => tail.isFull\n      case Split.Let(_, _, _, tail) => tail.isFull\n      case Split.Else(_) => true\n      case Split.Nil => false\n    }\n\n    lazy val isEmpty: Bool = this match {\n      case Split.Let(_, _, _, tail) => tail.isEmpty\n      case Split.Else(_) | Split.Cons(_, _) => false\n      case Split.Nil => true\n    }\n\n    override lazy val freeVars: Set[Var] = this match {\n      case Split.Cons(Branch(scrutinee, pattern, continuation), tail) =>\n        continuation.freeVars ++ tail.freeVars\n      case Split.Let(true, nme, rhs, tail) => tail.freeVars ++ rhs.freeVars - nme\n      case Split.Let(false, nme, rhs, tail) => tail.freeVars - nme ++ rhs.freeVars\n      case Split.Else(term) => term.freeVars\n      case Split.Nil => Set.empty\n    }\n\n    /**\n      * Remove duplicated bindings.\n      */\n    def withoutBindings(vars: Set[Var]): Split = this match {\n      case self @ Split.Cons(head @ Branch(_, _, continuation), tail) =>\n        self.copy(head.copy(continuation = continuation.withoutBindings(vars)), tail.withoutBindings(vars))\n      case self @ Split.Let(_, name, _, tail) if vars contains name => tail.withoutBindings(vars)\n      case self @ Split.Let(_, _, _, tail) => self.copy(tail = tail.withoutBindings(vars))\n      case Split.Else(_) | Split.Nil => this\n    }\n\n    final override def children: Ls[Located] = this match {\n      case Split.Cons(head, tail) => head :: tail :: Nil\n      case Split.Let(rec, name, term, tail) => name :: term :: tail :: Nil\n      case Split.Else(default) => default :: Nil\n      case Split.Nil => Nil\n    }\n\n    // TODO: Make the following flag temporary. It is only meaningful in a\n    // single run of specialization. The flag is useless outside specialization\n    // functions.\n\n    /**\n     * The split is concatenated as a fallback when specializing the given\n     * scrutinee and pattern.\n     */\n\n    private var _fallback: Bool = false\n\n    def isFallback: Bool = _fallback\n\n    def markAsFallback(): this.type = {\n      _fallback = true\n      this match {\n        case Split.Cons(head, tail) =>\n          head.continuation.markAsFallback()\n          tail.markAsFallback()\n        case Split.Let(_, _, _, tail) => tail.markAsFallback()\n        case _: Split.Else | Split.Nil => ()\n      }\n      this\n    }\n\n    def clearFallback(): this.type = {\n      _fallback = false\n      this match {\n        case Split.Cons(head, tail) =>\n          head.continuation.clearFallback()\n          tail.clearFallback()\n        case Split.Let(_, _, _, tail) => tail.clearFallback()\n        case _: Split.Else | Split.Nil => ()\n      }\n      this\n    }\n\n    // private val _fallbackSource = MutSet.empty[(Scrutinee, Pattern)]\n\n    // def isFallbackOf(scrutinee: Scrutinee, pattern: Pattern): Bool =\n    //   _fallbackSource.contains((scrutinee, pattern))\n\n    // def markAsFallback(target: Opt[(Scrutinee, Pattern)]): this.type =\n    //   target.fold[this.type](this)(this.markAsFallback)\n\n    // def markAsFallback(target: (Scrutinee, Pattern)): this.type = {\n    //   _fallbackSource += target\n    //   this match {\n    //     case Split.Cons(head, tail) =>\n    //       head.continuation.markAsFallback(target)\n    //       tail.markAsFallback(target)\n    //     case Split.Let(_, _, _, tail) => tail.markAsFallback(target)\n    //     case _: Split.Else | Split.Nil => ()\n    //   }\n    //   this\n    // }\n\n    // def withFallbackOf(that: Split): this.type = {\n    //   _fallbackSource ++= that._fallbackSource\n    //   this\n    // }\n  }\n\n  object Split {\n    final case class Cons(head: Branch, tail: Split) extends Split\n    final case class Let(rec: Bool, name: Var, term: Term, tail: Split) extends Split\n    final case class Else(default: Term) extends Split\n    final case object Nil extends Split\n  }\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/ucs/syntax/source.scala",
    "content": "package mlscript.ucs.syntax\n\nimport mlscript.{Lit, Located, Term, Var}\nimport mlscript.utils._, shorthands._\nimport scala.annotation.tailrec\nimport scala.collection.immutable\n\npackage object source {\n  sealed abstract class Pattern extends Located {\n    override def toString(): String = this match {\n      case AliasPattern(nme, pattern) => s\"${nme.name} @ $pattern\"\n      case LiteralPattern(literal) => literal.idStr\n      case ConcretePattern(nme) => s\"`${nme.name}`\"\n      case NamePattern(nme) => nme.name\n      case EmptyPattern(_) => \"•\"\n      case ClassPattern(Var(name), ps, rfd) => (if (rfd) \"refined \" else \"\") + (ps match {\n        case N => name\n        case S(parameters) => parameters.mkString(s\"$name(\", \", \", \")\")\n      })\n      case TuplePattern(fields) => fields.mkString(\"(\", \", \", \")\")\n      case RecordPattern(Nil) => \"{}\"\n      case RecordPattern(entries) => entries.iterator.map { case (nme, als) => s\"$nme: $als\" }.mkString(\"{ \", \", \", \" }\")\n    }\n  }\n  final case class AliasPattern(nme: Var, pattern: Pattern) extends Pattern {\n    override def children: List[Located] = nme :: pattern :: Nil\n  }\n  final case class LiteralPattern(literal: Lit) extends Pattern {\n    override def children: List[Located] = literal :: Nil\n  }\n  final case class ConcretePattern(nme: Var) extends Pattern {\n    override def children: List[Located] = nme :: Nil\n  }\n  final case class NamePattern(nme: Var) extends Pattern {\n    override def children: List[Located] = nme :: Nil\n  }\n  /**\n    * Represents wildcard patterns or missing patterns which match everything.\n    * Should be transformed from `Var(\"_\")` or unrecognized terms.\n    */\n  final case class EmptyPattern(source: Term) extends Pattern {\n    override def children: List[Located] = source :: Nil\n  }\n  final case class ClassPattern(nme: Var, parameters: Opt[List[Pattern]], refined: Bool) extends Pattern {\n    override def children: List[Located] = nme :: parameters.getOrElse(Nil)\n  }\n  final case class TuplePattern(fields: List[Pattern]) extends Pattern {\n    override def children: List[Located] = fields\n  }\n  final case class RecordPattern(entries: List[(Var -> Pattern)]) extends Pattern {\n    override def children: List[Located] = entries.iterator.flatMap { case (nme, als) => nme :: als :: Nil }.toList\n  }\n\n  sealed abstract class Split[+SomeBranch <: Branch] extends Located {\n    def ::[OtherBranch >: SomeBranch <: Branch](head: OtherBranch): Split[OtherBranch] = Split.Cons(head, this)\n  }\n  object Split {\n    import immutable.{Nil => LNil}\n    final case class Cons[SomeBranch <: Branch](head: SomeBranch, tail: Split[SomeBranch]) extends Split[SomeBranch] {\n      override def children: List[Located] = head :: tail :: LNil\n    }\n    final case class Let[SomeBranch <: Branch](rec: Bool, nme: Var, rhs: Term, tail: Split[SomeBranch]) extends Split[SomeBranch] {\n      override def children: List[Located] = nme :: rhs :: tail :: LNil\n    }\n    final case class Else(term: Term) extends Split[Nothing] {\n      override def children: List[Located] = term :: LNil\n    }\n    final case object Nil extends Split[Nothing] {\n      override def children: List[Located] = LNil\n    }\n\n    def empty[SomeBranch <: Branch]: Split[SomeBranch] = Nil\n    def single[SomeBranch <: Branch](branch: SomeBranch): Split[SomeBranch] = Cons(branch, Nil)\n    def `then`(term: Term): Split[TermBranch] = Else(term)\n    def default[SomeBranch <: Branch](term: Term): Split[SomeBranch] = Else(term)\n    def from[SomeBranch <: Branch](branches: Iterable[SomeBranch]): Split[SomeBranch] =\n      branches.foldRight(Nil: Split[SomeBranch])(Cons.apply)\n  }\n\n  sealed abstract class Branch extends Located\n\n  sealed abstract class TermBranch extends Branch {\n    final def toSplit: TermSplit = Split.single(this)\n  }\n  object TermBranch {\n    final case class Boolean(test: Term, continuation: TermSplit) extends TermBranch {\n      override def children: List[Located] = test :: continuation :: Nil\n    }\n    final case class Match(scrutinee: Term, continuation: PatternSplit) extends TermBranch {\n      override def children: List[Located] = scrutinee :: continuation :: Nil\n    }\n    final case class Left(left: Term, continuation: OperatorSplit) extends TermBranch {\n      override def children: List[Located] = left :: continuation :: Nil\n    }\n  }\n  type TermSplit = Split[TermBranch]\n\n  sealed abstract class OperatorBranch extends Branch {\n    val operator: Var\n    final def toSplit: OperatorSplit = Split.single(this)\n  }\n  object OperatorBranch {\n    final case class Match(override val operator: Var, continuation: PatternSplit) extends OperatorBranch {\n      override def children: List[Located] = operator :: continuation :: Nil\n    }\n    final case class Binary(override val operator: Var, continuation: TermSplit) extends OperatorBranch {\n      override def children: List[Located] = operator :: continuation :: Nil\n    }\n  }\n  type OperatorSplit = Split[OperatorBranch]\n\n  final case class PatternBranch(val pattern: Pattern, val continuation: TermSplit) extends Branch {\n    override def children: List[Located] = pattern :: continuation :: Nil\n    final def toSplit: PatternSplit = Split.single(this)\n  }\n  type PatternSplit = Split[PatternBranch]\n}\n"
  },
  {
    "path": "shared/src/main/scala/mlscript/utils/FastParseHelpers.scala",
    "content": "package mlscript\n\nimport mlscript.utils._, shorthands._\n\nclass FastParseHelpers(val blockStr: Str, val lines: collection.IndexedSeq[Str]) {\n  def this(lines: IndexedSeq[Str]) = this(lines.mkString(\"\\n\"), lines)\n  def this(blockStr: Str) = this(blockStr, blockStr.splitSane('\\n'))\n  \n  // this line-parsing logic was copied from fastparse internals:\n  val lineNumberLookup: Array[Int] = fastparse.internal.Util.lineNumberLookup(blockStr)\n  def getLineColAt(index: Int): (Int, String, Int) = {\n    val lineNum = lineNumberLookup.indexWhere(_ > index) match {\n      case -1 => lineNumberLookup.length\n      case n => math.max(1, n)\n    }\n    val idx = lineNum.min(lines.length) - 1\n    val colNum = index - lineNumberLookup(idx) + 1\n    val lineStr = lines(idx)\n    (lineNum, lineStr, colNum)\n  }\n  \n}\n"
  },
  {
    "path": "shared/src/test/diff/analysis/Variance.mls",
    "content": "\ntype UseT[T] = T -> int\nclass C[X]: { y: X }\n  method Create: int -> C[X]\n  method MapWrap: (int -> int) -> int -> D[C[X]]\nclass D[R]: { z: R }\n  method Produce: string -> D[R]\n  method Producer: int -> C[R] -> D[R]\n  method Unwrap: D[R] -> R\n//│ Defined type alias UseT[-T]\n//│ Defined class C[=X]\n//│ Declared C.Create: C['X] -> int -> C['X]\n//│ Declared C.MapWrap: C['X] -> (int -> int) -> int -> D[C['X]]\n//│ Defined class D[=R]\n//│ Declared D.Produce: D['R] -> string -> D['R]\n//│ Declared D.Producer: D['R] -> int -> C['R] -> D['R]\n//│ Declared D.Unwrap: D['R] -> D['R] -> 'R\n\n:w\nclass F[S, T]: E[T]\n  method Create: S -> T\nclass E[G]\n  method Id: G -> G\nclass Z[X, R]\n  method Phantom: C[X]\n//│ Defined class F[-S, =T]\n//│ Declared F.Create: F['S, 'T] -> 'S -> 'T\n//│ Defined class E[=G]\n//│ Declared E.Id: E['G] -> 'G -> 'G\n//│ Defined class Z[=X, ±R]\n//│ Declared Z.Phantom: Z['X, ?] -> C['X]\n//│ ╔══[WARNING] Type definition Z has bivariant type parameters:\n//│ ║  l.24: \tclass Z[X, R]\n//│ ║        \t      ^\n//│ ╟── R is irrelevant and may be removed\n//│ ║  l.24: \tclass Z[X, R]\n//│ ╙──      \t           ^\n\n\nclass C0[A]\n  method M0 (x: A) = x\n//│ Defined class C0[=A]\n//│ Defined C0.M0: C0['A] -> 'A -> 'A\n\n\n// Note that the variance that'd be implied by the method definition inferred type\n//  is not taken into consideration because that inferred type is discarded\n//  in favor of the explicit signature.\n:w\nclass C1[A]\n  method M1 (x: A) = x\n  method M1: nothing -> anything\n//│ Defined class C1[±A]\n//│ Declared C1.M1: C1[?] -> nothing -> anything\n//│ Defined C1.M1: C1[?] -> 'A -> 'A\n//│ ╔══[WARNING] Type definition C1 has bivariant type parameters:\n//│ ║  l.50: \tclass C1[A]\n//│ ║        \t      ^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.50: \tclass C1[A]\n//│ ╙──      \t         ^\n\n\n"
  },
  {
    "path": "shared/src/test/diff/analysis/Weird.mls",
    "content": "\nclass Base1[A]\n  method M1: A -> Base1[A]\n//│ Defined class Base1[-A]\n//│ Declared Base1.M1: Base1['A] -> 'A -> Base1['A]\n\n\n:DistributeForalls\n\n// * Note: C used to be inferred as invariant here with :DistributeForalls;\n// *  It happened when `subst` did not hygienically substitute under polymorphic types\n:w\nclass Derived2[C]: Base1[anything]\n  method M1 r = Derived2{}\n//│ Defined class Derived2[±C]\n//│ Defined Derived2.M1: Derived2[?] -> anything -> Derived2[?]\n//│ ╔══[WARNING] Type definition Derived2 has bivariant type parameters:\n//│ ║  l.13: \tclass Derived2[C]: Base1[anything]\n//│ ║        \t      ^^^^^^^^\n//│ ╟── C is irrelevant and may be removed\n//│ ║  l.13: \tclass Derived2[C]: Base1[anything]\n//│ ╙──      \t               ^\n\nDerived2.M1\n//│ res: Derived2[?] -> anything -> Derived2[?]\n//│    = undefined\n\n\n:DontDistributeForalls\n\n:w\nclass Derived3[C]: Base1[anything]\n  method M1 r = Derived3{}\n//│ Defined class Derived3[±C]\n//│ Defined Derived3.M1: Derived3[?] -> anything -> Derived3[?]\n//│ ╔══[WARNING] Type definition Derived3 has bivariant type parameters:\n//│ ║  l.32: \tclass Derived3[C]: Base1[anything]\n//│ ║        \t      ^^^^^^^^\n//│ ╟── C is irrelevant and may be removed\n//│ ║  l.32: \tclass Derived3[C]: Base1[anything]\n//│ ╙──      \t               ^\n\nDerived3.M1\n//│ res: Derived3[?] -> anything -> Derived3[?]\n//│    = undefined\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/AsBindings.fun",
    "content": "\nlet f x =\n  discard / x as { v: (y) } // TODO accept plain `y`\n  log / v\n  log / y + 1\n//│ f: {v: int} -> unit\n\nlet f x =\n  discard / x as { v: (y) } // TODO accept plain `y`\n  log / v + 1\n  log / y\n//│ f: {v: int} -> unit\n\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Blocks.fun",
    "content": "\n// let foo x = // TODO\nlet foo = x =>\n  let a = x + 1\n  a\n//│ foo: int -> int\n\nlet foo = x =>\n  log x\n  let u = x + 1\n  log true\n  u + 1\n//│ foo: int -> int\n\nlet foo = x =>\n  log x;\n  let u = x + 1;\n  log true;\n  u + 1\n//│ foo: int -> int\n\nfoo 1\nfoo / 1\nfoo / foo / 1\n//│ res: int\n//│ res: int\n//│ res: int\nfoo\n  foo\n    1\n//│ res: int\nfoo\n  discard / foo\n    1\n  foo\n    1\n//│ res: int\nfoo / foo /\n  foo 1\n//│ res: int\n\n:p\ndiscard / foo\n    1\n//│ Parsed: discard(...(foo(...{1})));\n//│ Desugared: discard(...(foo(...{1})))\n//│ AST: App(Var(discard),App(Var(foo),Blk(List(IntLit(1)))))\n\n:e\ndiscard foo\n  1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.50: \tdiscard foo\n//│ ║        \t^^^^^^^^^^^\n//│ ║  l.51: \t  1\n//│ ║        \t^^^\n//│ ╟── application of type `unit` is not a function\n//│ ║  l.50: \tdiscard foo\n//│ ╙──      \t^^^^^^^^^^^\n//│ res: error\n\n:w\nfoo\n  foo 1\n  foo 2\n//│ ╔══[WARNING] Expression in statement position should have type `unit`.\n//│ ╟── Use the `discard` function to discard non-unit values, making the intent clearer.\n//│ ╟── Type mismatch in application:\n//│ ║  l.64: \t  foo 1\n//│ ║        \t  ^^^^^\n//│ ╟── operator application of type `int` is not an instance of type `unit`\n//│ ║  l.19: \t  u + 1\n//│ ║        \t  ^^^^^\n//│ ╟── but it flows into application with expected type `unit`\n//│ ║  l.64: \t  foo 1\n//│ ╙──      \t  ^^^^^\n//│ res: int\n\n:p\nid id\n  id\n//│ Parsed: id(...id)(...{id});\n//│ Desugared: id(...id)(...{id})\n//│ AST: App(App(Var(id),Var(id)),Blk(List(Var(id))))\n//│ res: 'a -> 'a\n\n:p\nid id id\n  id id id\n    id id id\n      id id id\n//│ Parsed: id(...id)(...id)(...{id(...id)(...id)(...{id(...id)(...id)(...{id(...id)(...id)})})});\n//│ Desugared: id(...id)(...id)(...{id(...id)(...id)(...{id(...id)(...id)(...{id(...id)(...id)})})})\n//│ AST: App(App(App(Var(id),Var(id)),Var(id)),Blk(List(App(App(App(Var(id),Var(id)),Var(id)),Blk(List(App(App(App(Var(id),Var(id)),Var(id)),Blk(List(App(App(Var(id),Var(id)),Var(id)))))))))))\n//│ res: 'a -> 'a\n\n:p\nid id /\n  id id /\n    id id\n//│ Parsed: id(...id)(...{id(...id)(...{id(...id)})});\n//│ Desugared: id(...id)(...{id(...id)(...{id(...id)})})\n//│ AST: App(App(Var(id),Var(id)),Blk(List(App(App(Var(id),Var(id)),Blk(List(App(Var(id),Var(id))))))))\n//│ res: 'a -> 'a\n\n:p\nid id\n    id id\n  id id\n//│ Parsed: id(...id)(...{id(...id)})(...{id(...id)});\n//│ Desugared: id(...id)(...{id(...id)})(...{id(...id)})\n//│ AST: App(App(App(Var(id),Var(id)),Blk(List(App(Var(id),Var(id))))),Blk(List(App(Var(id),Var(id)))))\n//│ res: 'a -> 'a\n\nlet foo =\n  log 1\n  log 2\n//│ foo: unit\n\nlet foo =\n  log 1\n  \n  log 2\n//│ foo: unit\n\nlet foo =\n \n  log 1\n   \n  log 2\n  \n//│ foo: unit\n\nsucc (\n  log 1\n  1\n)\nsucc (\n  log 1\n  1)\nsucc (succ\n  1)\nsucc (succ\n  1\n)\nsucc (succ\n  succ 1)\nsucc (succ\n    let x = 1; x)\n//│ res: int\n//│ res: int\n//│ res: int\n//│ res: int\n//│ res: int\n//│ res: int\n\n:w\nsucc (\n  succ\n  1\n)\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.159: \t  succ\n//│ ╙──       \t  ^^^^\n//│ res: int\n\n:pe\nsucc (succ\n1)\n//│ /!\\ Parse error: Expected end-of-input:1:6, found \"(succ\\n1)\\n\" at l.168:6: succ (succ\n\n:pe\nsucc (succ\nsucc 1)\n//│ /!\\ Parse error: Expected end-of-input:1:6, found \"(succ\\nsucc\" at l.173:6: succ (succ\n\n:pe\nsucc (succ\nsucc\n  1)\n//│ /!\\ Parse error: Expected end-of-input:1:6, found \"(succ\\nsucc\" at l.178:6: succ (succ\n\n(let x = 1)\n(let x = 1; x)\n(\n  let x = 1\n  x\n)\nsucc(\n  let x = 1\n  x\n)\n//│ res: ()\n//│ res: 1\n//│ res: 1\n//│ res: int\n\nsucc\n  (\n    let x = 1\n    x\n  )\n//│ res: int\n\nlog 1; log 2; log 3\n\nlet a = 1; log a; let b = 2\n//│ a: 1\n//│ b: 2\n\n(let a = 1; log a; let b = 2)\n//│ res: ()\n\n(let a = 1; log a; let b = 2; a + b)\n//│ res: int\n\n\n:e\nlet test =\n  let aaa =\n    let bbb = 42\n    bbb\n  bbb\n//│ ╔══[ERROR] identifier not found: bbb\n//│ ║  l.223: \t  bbb\n//│ ╙──       \t  ^^^\n//│ test: error\n\nlet test =\n  let aaa =\n    let bbb = 42\n    bbb\n  aaa\n//│ test: 42\n\n:e\naaa\n//│ ╔══[ERROR] identifier not found: aaa\n//│ ║  l.237: \taaa\n//│ ╙──       \t^^^\n//│ res: error\n\n\n:pe\nsucc\n  (\n    let x = 1\n    x\n)\n//│ /!\\ Parse error: Expected expression:1:1, found \"succ\\n  (\\n \" at l.245:1: succ\n\n:pe\nlet a =\n    succ\n  1\n  \"?\"\n//│ /!\\ Parse error: Expected end-of-input:3:3, found \"1\\n  \\\"?\\\"\\n\" at l.255:3:   1\n\n:pe\n  1\n//│ /!\\ Parse error: Expected (data type definition | data definition | let binding | expression):1:1, found \"  1\\n\" at l.260:1:   1\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Data.fun",
    "content": "\n:p\ndata Test a b\n//│ Parsed: data Test(...a)(...b);\n//│ Desugared: class Test[a, b]: {a: a, b: b}\n//│ Desugared: def Test: forall a b. (...a) -> (...b) -> Test[a, b]\n//│ AST: Def(false,Var(Test),Right(PolyType(List(Left(TypeName(a)), Left(TypeName(b))),Function(TypeName(a),Function(TypeName(b),AppliedType(TypeName(Test),List(TypeName(a), TypeName(b))))))),true)\n//│ Defined class Test[+a, +b]\n//│ Test: 'a -> 'b -> Test['a, 'b]\n\n:p\ndata Person(name: string, age: int)\n//│ Parsed: data Person(...'(' {[name: string, age: int,]} ')');\n//│ Desugared: class Person: {age: int, name: string}\n//│ Desugared: def Person: (name: string, age: int) -> Person[]\n//│ AST: Def(false,Var(Person),Right(PolyType(List(),Function(Tuple(List((Some(Var(name)),Field(None,TypeName(string))), (Some(Var(age)),Field(None,TypeName(int))))),AppliedType(TypeName(Person),List())))),true)\n//│ Defined class Person\n//│ Person: (name: string, age: int,) -> Person\n\nlet p = Person(\"Bob\", 42)\n//│ p: Person\n\nlet foo q = q.age\nfoo p\n//│ foo: {age: 'age} -> 'age\n//│ res: int\n\n// TODO properly check pattern types!\nlet bar (q: Person _) = q.age\n//│ bar: (q: {age: 'age},) -> 'age\n\nbar p\n//│ res: int\n\n:e\nbar {}\nbar {name: \"Bob\"}\nbar {age: 1} // TODO B/E\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.36: \tbar {}\n//│ ║        \t^^^^^^\n//│ ╟── tuple of type `anything` does not have field 'age'\n//│ ║  l.36: \tbar {}\n//│ ║        \t    ^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.29: \tlet bar (q: Person _) = q.age\n//│ ║        \t                         ^^^^\n//│ ╟── from binding:\n//│ ║  l.29: \tlet bar (q: Person _) = q.age\n//│ ╙──      \t         ^^^^^^^^^^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.37: \tbar {name: \"Bob\"}\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{name: \"Bob\"}` does not have field 'age'\n//│ ║  l.37: \tbar {name: \"Bob\"}\n//│ ║        \t    ^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.29: \tlet bar (q: Person _) = q.age\n//│ ║        \t                         ^^^^\n//│ ╟── from binding:\n//│ ║  l.29: \tlet bar (q: Person _) = q.age\n//│ ╙──      \t         ^^^^^^^^^^^\n//│ res: error\n//│ res: 1\n\nlet fake-p = { name: \"Bob\", age: 42 }\n//│ fake-p: {age: 42, name: \"Bob\"}\n\n// :e // TODO B/E\nbar fake-p\n//│ res: 42\n\ndata Wine(name: string, age: int)\nlet w = Wine(\"Côtes du Rhône\", 3)\n//│ Defined class Wine\n//│ Wine: (name: string, age: int,) -> Wine\n//│ w: Wine\n\n// :e\nbar w\nbar (q: w)\n//│ res: int\n//│ res: int\n\nlet bar2 (q: Person _) = succ q.age\n//│ bar2: (q: {age: int},) -> int\n\n\n:e\nlet nested x =\n  data Foo a // Note: we get one error for the synthetic class, and one for the synthetic def...\n  Foo x\n//│ ╔══[ERROR] Illegal position for this type declaration statement.\n//│ ║  l.92: \t  data Foo a // Note: we get one error for the synthetic class, and one for the synthetic def...\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] Illegal position for this definition statement.\n//│ ║  l.92: \t  data Foo a // Note: we get one error for the synthetic class, and one for the synthetic def...\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] identifier not found: Foo\n//│ ║  l.93: \t  Foo x\n//│ ╙──      \t  ^^^\n//│ nested: error -> error\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Datatypes.fun",
    "content": "\n:p\ndata type Boolean of Tru, Fals\n//│ Parsed: data type Boolean of {Tru; Fals};\n//│ Desugared: type alias Boolean = Tru[] | Fals[]\n//│ Desugared: class Tru: {}\n//│ Desugared: class Fals: {}\n//│ Desugared: def Tru: Tru[]\n//│ AST: Def(false,Var(Tru),Right(PolyType(List(),AppliedType(TypeName(Tru),List()))),true)\n//│ Desugared: def Fals: Fals[]\n//│ AST: Def(false,Var(Fals),Right(PolyType(List(),AppliedType(TypeName(Fals),List()))),true)\n//│ Defined type alias Boolean\n//│ Defined class Tru\n//│ Defined class Fals\n//│ Tru: Tru\n//│ Fals: Fals\n\n:e\nBoolean\n//│ ╔══[ERROR] identifier not found: Boolean\n//│ ║  l.19: \tBoolean\n//│ ╙──      \t^^^^^^^\n//│ res: error\n\n:p\n:e\ndata type Bool2 of True2 & False2\n//│ Parsed: data type Bool2 of {&(...True2)(...False2)};\n//│ Desugared: type alias Bool2 = &[True2, False2]\n//│ Desugared: class &[True2, False2]: {False2 <: False2, True2 <: True2}\n//│ Desugared: def &: forall True2 False2. (...True2) -> (...False2) -> &[True2, False2]\n//│ AST: Def(false,Var(&),Right(PolyType(List(Left(TypeName(True2)), Left(TypeName(False2))),Function(TypeName(True2),Function(TypeName(False2),AppliedType(TypeName(&),List(TypeName(True2), TypeName(False2))))))),true)\n//│ ╔══[ERROR] type identifier not found: True2\n//│ ║  l.27: \tdata type Bool2 of True2 & False2\n//│ ╙──      \t                   ^^^^^\n//│ ╔══[ERROR] type identifier not found: False2\n//│ ║  l.27: \tdata type Bool2 of True2 & False2\n//│ ╙──      \t                           ^^^^^^\n//│ ╔══[ERROR] Type names must start with a capital letter\n//│ ║  l.27: \tdata type Bool2 of True2 & False2\n//│ ╙──      \t                         ^\n//│ ╔══[ERROR] Field identifiers must start with a small letter\n//│ ║  l.27: \tdata type Bool2 of True2 & False2\n//│ ╙──      \t                           ^^^^^^\n//│ ╔══[ERROR] Field identifiers must start with a small letter\n//│ ║  l.27: \tdata type Bool2 of True2 & False2\n//│ ╙──      \t                   ^^^^^\n//│ Defined type alias Bool2\n//│ Defined class &[+True2, +False2]\n//│ &: 'a -> 'b -> &['a, 'b]\n\ndata type Bool3 of\n  True3; False3\n//│ Defined type alias Bool3\n//│ Defined class True3\n//│ Defined class False3\n//│ True3: True3\n//│ False3: False3\n\ndata type Bool4 of\n  True4\n  False4\n//│ Defined type alias Bool4\n//│ Defined class True4\n//│ Defined class False4\n//│ True4: True4\n//│ False4: False4\n\n:e\nBoolean\n//│ ╔══[ERROR] identifier not found: Boolean\n//│ ║  l.70: \tBoolean\n//│ ╙──      \t^^^^^^^\n//│ res: error\n\nTru\n//│ res: Tru\n\n:e // TODO support types on RHS of `as`\nTru as Boolean\nTru : Boolean\n//│ ╔══[ERROR] identifier not found: Boolean\n//│ ║  l.80: \tTru as Boolean\n//│ ╙──      \t       ^^^^^^^\n//│ res: error\n//│ ╔══[ERROR] identifier not found: Boolean\n//│ ║  l.81: \tTru : Boolean\n//│ ╙──      \t      ^^^^^^^\n//│ res: (Tru: error,)\n\n:e // Maybe we shouldn't interpret capitalized identifiers as field names...\nTru : Boolean\n//│ ╔══[ERROR] identifier not found: Boolean\n//│ ║  l.92: \tTru : Boolean\n//│ ╙──      \t      ^^^^^^^\n//│ res: (Tru: error,)\n\n:pe\n(Tru) : Boolean\n//│ /!\\ Parse error: Expected end-of-input:1:7, found \": Boolean\\n\" at l.99:7: (Tru) : Boolean\n\n\n// TODO treat the ending curly-blocks as bodies (not params)?\n// data type List of\n//   Nil { T: Nothing }\n//   Cons head tail { T: head | tail.T }\n\n// TODO also try the one-line version:\n// data type List of Nil { T: Nothing }, Cons head tail { T: head | tail.T }\n\n:p\n:pe\n:w\ndata type List a of\n  Nil\n  Cons (head: a) (tail: List a)\n//│ Parsed: data type List(...a) of {Nil; Cons(...'(' {[head: a,]} ')')(...'(' {[tail: List(...a),]} ')')};\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.116: \t  Cons (head: a) (tail: List a)\n//│ ╙──       \t                        ^^^^^^\n//│ Desugared: type alias List[a] = Nil[a] | Cons[a]\n//│ Desugared: class Nil[a]: {}\n//│ Desugared: class Cons[a]: {head: a, tail: anything}\n//│ Desugared: def Nil: forall a. Nil[a]\n//│ AST: Def(false,Var(Nil),Right(PolyType(List(Left(TypeName(a))),AppliedType(TypeName(Nil),List(TypeName(a))))),true)\n//│ Desugared: def Cons: forall a. (head: a) -> (tail: anything) -> Cons[a]\n//│ AST: Def(false,Var(Cons),Right(PolyType(List(Left(TypeName(a))),Function(Tuple(List((Some(Var(head)),Field(None,TypeName(a))))),Function(Tuple(List((Some(Var(tail)),Field(None,Top)))),AppliedType(TypeName(Cons),List(TypeName(a))))))),true)\n//│ Defined type alias List[+a]\n//│ Defined class Nil[±a]\n//│ Defined class Cons[+a]\n//│ ╔══[WARNING] Type definition Nil has bivariant type parameters:\n//│ ║  l.115: \t  Nil\n//│ ║         \t  ^^^\n//│ ╟── a is irrelevant and may be removed\n//│ ║  l.114: \tdata type List a of\n//│ ╙──       \t               ^\n//│ Nil: Nil[?]\n//│ Cons: (head: 'a,) -> (tail: anything,) -> Cons['a]\n\n// TODO interpret as free type variable?\n:p\ndata type Ls of LsA a\n//│ Parsed: data type Ls of {LsA(...a)};\n//│ Desugared: type alias Ls = LsA[a]\n//│ Desugared: class LsA[a]: {a: a}\n//│ Desugared: def LsA: forall a. (...a) -> LsA[a]\n//│ AST: Def(false,Var(LsA),Right(PolyType(List(Left(TypeName(a))),Function(TypeName(a),AppliedType(TypeName(LsA),List(TypeName(a)))))),true)\n//│ ╔══[ERROR] type identifier not found: a\n//│ ║  l.142: \tdata type Ls of LsA a\n//│ ╙──       \t                    ^\n//│ Defined type alias Ls\n//│ Defined class LsA[+a]\n//│ LsA: 'a -> LsA['a]\n\n:p\n:e\ndata type Ls2 of LsA2 `a\n//│ Parsed: data type Ls2 of {LsA2(...`a)};\n//│ Desugared: type alias Ls2 = LsA2[]\n//│ Desugared: class LsA2: {`a: 'a}\n//│ Desugared: def LsA2: (...'a) -> LsA2[]\n//│ AST: Def(false,Var(LsA2),Right(PolyType(List(),Function(a,AppliedType(TypeName(LsA2),List())))),true)\n//│ ╔══[ERROR] cannot inherit from a polymorphic type\n//│ ║  l.157: \tdata type Ls2 of LsA2 `a\n//│ ╙──       \t                 ^^^^^^^\n//│ ╔══[ERROR] type identifier not found: LsA2\n//│ ╙──\n//│ Defined type alias Ls2\n//│ ╔══[ERROR] type identifier not found: LsA2\n//│ ╙──\n//│ LsA2: anything -> error\n\nNil\nCons\nCons 1\nCons 2 Nil\nCons 1 (Cons 2 Nil)\n//│ res: Nil[?]\n//│ res: (head: 'a,) -> (tail: anything,) -> Cons['a]\n//│ res: (tail: anything,) -> Cons[1]\n//│ res: Cons[2]\n//│ res: Cons[1]\n\n(Cons 3 Nil).head\nsucc (Cons 3 Nil).head\nnot (Cons false Nil).head\n//│ res: 3\n//│ res: int\n//│ res: bool\n\n:e\nnot (Cons 42 Nil).head\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.192: \tnot (Cons 42 Nil).head\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `42` is not an instance of type `bool`\n//│ ║  l.192: \tnot (Cons 42 Nil).head\n//│ ║         \t          ^^\n//│ ╟── but it flows into field selection with expected type `bool`\n//│ ║  l.192: \tnot (Cons 42 Nil).head\n//│ ╙──       \t                 ^^^^^\n//│ res: bool | error\n\n:e\n(Cons 4).head\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.205: \t(Cons 4).head\n//│ ║         \t        ^^^^^\n//│ ╟── type `(tail: anything,) -> Cons[?a]` does not have field 'head'\n//│ ║  l.114: \tdata type List a of\n//│ ║         \t               ^\n//│ ╟── but it flows into receiver with expected type `{head: ?head}`\n//│ ║  l.205: \t(Cons 4).head\n//│ ╙──       \t^^^^^^^^\n//│ res: error\n\n// :e\nCons 1 2\n//│ res: Cons[1]\n\n// TODO Allow method/field defintions in the same file (lose the let?):\n:e\nlet List.head = () // ...\n//│ ╔══[ERROR] Unsupported pattern shape\n//│ ║  l.223: \tlet List.head = () // ...\n//│ ╙──       \t        ^^^^^\n//│ <error>: ()\n\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Either.fun",
    "content": "\n:p\n:w\ndata type Either l r of\n  Left l\n  Right r\n//│ Parsed: data type Either(...l)(...r) of {Left(...l); Right(...r)};\n//│ Desugared: type alias Either[l, r] = Left[l, r] | Right[l, r]\n//│ Desugared: class Left[l, r]: {l: l}\n//│ Desugared: class Right[l, r]: {r: r}\n//│ Desugared: def Left: forall l r. (...l) -> Left[l, r]\n//│ AST: Def(false,Var(Left),Right(PolyType(List(Left(TypeName(l)), Left(TypeName(r))),Function(TypeName(l),AppliedType(TypeName(Left),List(TypeName(l), TypeName(r)))))),true)\n//│ Desugared: def Right: forall l r. (...r) -> Right[l, r]\n//│ AST: Def(false,Var(Right),Right(PolyType(List(Left(TypeName(l)), Left(TypeName(r))),Function(TypeName(r),AppliedType(TypeName(Right),List(TypeName(l), TypeName(r)))))),true)\n//│ Defined type alias Either[+l, +r]\n//│ Defined class Left[+l, ±r]\n//│ Defined class Right[±l, +r]\n//│ ╔══[WARNING] Type definition Left has bivariant type parameters:\n//│ ║  l.5: \t  Left l\n//│ ║       \t  ^^^^\n//│ ╟── r is irrelevant and may be removed\n//│ ║  l.4: \tdata type Either l r of\n//│ ╙──     \t                   ^\n//│ ╔══[WARNING] Type definition Right has bivariant type parameters:\n//│ ║  l.6: \t  Right r\n//│ ║       \t  ^^^^^\n//│ ╟── l is irrelevant and may be removed\n//│ ║  l.4: \tdata type Either l r of\n//│ ╙──     \t                 ^\n//│ Left: 'a -> Left['a, ?]\n//│ Right: 'a -> Right[?, 'a]\n\n:e\ndata type Either2 (l: _) (r: _) of\n  Left2 l\n  Right2 r\n//│ ╔══[ERROR] illegal datatype type parameter shape: '(' {[l: _,]} ')'\n//│ ║  l.34: \tdata type Either2 (l: _) (r: _) of\n//│ ╙──      \t                  ^^^^^^\n//│ ╔══[ERROR] illegal datatype type parameter shape: '(' {[r: _,]} ')'\n//│ ║  l.34: \tdata type Either2 (l: _) (r: _) of\n//│ ╙──      \t                         ^^^^^^\n//│ ╔══[ERROR] type identifier not found: l\n//│ ║  l.35: \t  Left2 l\n//│ ╙──      \t        ^\n//│ ╔══[ERROR] type identifier not found: r\n//│ ║  l.36: \t  Right2 r\n//│ ╙──      \t         ^\n//│ Defined type alias Either2\n//│ Defined class Left2[+l]\n//│ Defined class Right2[+r]\n//│ Left2: 'a -> Left2['a]\n//│ Right2: 'a -> Right2['a]\n\nlet l = Left 1\nlet r = Right \"ok\"\nlet e = if _ then l else r\n//│ l: Left[1, ?]\n//│ r: Right[?, \"ok\"]\n//│ e: Left[1, ?] | Right[?, \"ok\"]\n\n:e // TODO\ne as Either Int String\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.63: \te as Either Int String\n//│ ╙──      \t     ^^^^^^^^^^^^^^^^^\n//│ res: error\n\n// TODO\n// e as (_: Either Int String)\n// e as (_: Either (L: Int) (R: String))\n\n:e\ne as Either\n//│ ╔══[ERROR] identifier not found: Either\n//│ ║  l.74: \te as Either\n//│ ╙──      \t     ^^^^^^\n//│ res: error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Errors.fun",
    "content": ":ShowRelativeLineNums\n\nlet a = succ\n//│ a: int -> int\n\nlet b = a 1\n//│ b: int\n\n\n// identifier not found\n\n:e\nc\nid c\nlog 1\nlog / c + 1\nlog / abc + 1\nc + 1\nabc + 1\n1 + c\nlet d = c + 1\nlet d = 1 + abc + 1 + 1\nd + 1\n//│ ╔══[ERROR] identifier not found: c\n//│ ║  l.+1: \tc\n//│ ╙──      \t^\n//│ res: error\n//│ ╔══[ERROR] identifier not found: c\n//│ ║  l.+2: \tid c\n//│ ╙──      \t   ^\n//│ res: error\n//│ ╔══[ERROR] identifier not found: c\n//│ ║  l.+4: \tlog / c + 1\n//│ ╙──      \t      ^\n//│ ╔══[ERROR] identifier not found: abc\n//│ ║  l.+5: \tlog / abc + 1\n//│ ╙──      \t      ^^^\n//│ ╔══[ERROR] identifier not found: c\n//│ ║  l.+6: \tc + 1\n//│ ╙──      \t^\n//│ res: int\n//│ ╔══[ERROR] identifier not found: abc\n//│ ║  l.+7: \tabc + 1\n//│ ╙──      \t^^^\n//│ res: int\n//│ ╔══[ERROR] identifier not found: c\n//│ ║  l.+8: \t1 + c\n//│ ╙──      \t    ^\n//│ res: int\n//│ ╔══[ERROR] identifier not found: c\n//│ ║  l.+9: \tlet d = c + 1\n//│ ╙──      \t        ^\n//│ d: int\n//│ ╔══[ERROR] identifier not found: abc\n//│ ║  l.+10: \tlet d = 1 + abc + 1 + 1\n//│ ╙──       \t            ^^^\n//│ d: int\n//│ res: int\n\n\n// cannot constrain\n\n:e\n1 2 3\na b c\nlet oops = succ false\nfalse + 1\n1 + false\ntrue + false\nlog / false + 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t1 2 3\n//│ ║        \t^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.+1: \t1 2 3\n//│ ╙──      \t^\n//│ res: error\n//│ ╔══[ERROR] identifier not found: c\n//│ ║  l.+2: \ta b c\n//│ ╙──      \t    ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \ta b c\n//│ ║        \t^^^^^\n//│ ╟── application of type `int` is not a function\n//│ ║  l.+2: \ta b c\n//│ ╙──      \t^^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \tlet oops = succ false\n//│ ║        \t           ^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+3: \tlet oops = succ false\n//│ ╙──      \t                ^^^^^\n//│ oops: error | int\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+4: \tfalse + 1\n//│ ║        \t^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+4: \tfalse + 1\n//│ ╙──      \t^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+5: \t1 + false\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+5: \t1 + false\n//│ ╙──      \t    ^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+6: \ttrue + false\n//│ ║        \t^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.+6: \ttrue + false\n//│ ╙──      \t^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+6: \ttrue + false\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+6: \ttrue + false\n//│ ╙──      \t       ^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+7: \tlog / false + 1\n//│ ║        \t      ^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+7: \tlog / false + 1\n//│ ╙──      \t      ^^^^^\n\n:e\nsucc succ\n  1\n(\n  succ\n) false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tsucc succ\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `int -> int` is not an instance of type `int`\n//│ ║  l.+1: \tsucc succ\n//│ ╙──      \t     ^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tsucc succ\n//│ ║        \t^^^^^^^^^\n//│ ║  l.+2: \t  1\n//│ ║        \t^^^\n//│ ╟── application of type `int` is not a function\n//│ ║  l.+1: \tsucc succ\n//│ ╙──      \t^^^^^^^^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \t(\n//│ ║        \t^\n//│ ║  l.+4: \t  succ\n//│ ║        \t^^^^^^\n//│ ║  l.+5: \t) false\n//│ ║        \t^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+5: \t) false\n//│ ╙──      \t  ^^^^^\n//│ res: error | int\n\n:e\n:w\nlog\n  1\n    2\nlog 1\n  2\nlog\n  1\n  2\nlog\n  let f = 1\n  f 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \t  1\n//│ ║        \t  ^\n//│ ║  l.+3: \t    2\n//│ ║        \t^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.+2: \t  1\n//│ ╙──      \t  ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+4: \tlog 1\n//│ ║        \t^^^^^\n//│ ║  l.+5: \t  2\n//│ ║        \t^^^\n//│ ╟── application of type `unit` is not a function\n//│ ║  l.+4: \tlog 1\n//│ ╙──      \t^^^^^\n//│ res: error\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.+7: \t  1\n//│ ╙──      \t  ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+11: \t  f 2\n//│ ║         \t  ^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.+10: \t  let f = 1\n//│ ║         \t          ^\n//│ ╟── but it flows into reference with expected type `2 -> ?a`\n//│ ║  l.+11: \t  f 2\n//│ ╙──       \t  ^\n\n:w\nlog\n  succ 1\n  2\n//│ ╔══[WARNING] Expression in statement position should have type `unit`.\n//│ ╟── Use the `discard` function to discard non-unit values, making the intent clearer.\n//│ ╟── Type mismatch in application:\n//│ ║  l.+2: \t  succ 1\n//│ ║        \t  ^^^^^^\n//│ ╙── application of type `int` is not an instance of type `unit`\n\n:e\nsucc ((((false))))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tsucc ((((false))))\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+1: \tsucc ((((false))))\n//│ ║        \t         ^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \tsucc ((((false))))\n//│ ╙──      \t     ^^^^^^^^^^^^^\n//│ res: error | int\n\n:e\nlet rec f = n => if n then 0 else f (miss + 1)\n//│ ╔══[ERROR] identifier not found: miss\n//│ ║  l.+1: \tlet rec f = n => if n then 0 else f (miss + 1)\n//│ ╙──      \t                                     ^^^^\n//│ ╔══[ERROR] Type mismatch in binding of lambda expression:\n//│ ║  l.+1: \tlet rec f = n => if n then 0 else f (miss + 1)\n//│ ║        \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` is not an instance of type `bool`\n//│ ║  l.+1: \tlet rec f = n => if n then 0 else f (miss + 1)\n//│ ║        \t                                     ^^^^^^^^\n//│ ╟── but it flows into argument with expected type `bool`\n//│ ║  l.+1: \tlet rec f = n => if n then 0 else f (miss + 1)\n//│ ║        \t                                    ^^^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.+1: \tlet rec f = n => if n then 0 else f (miss + 1)\n//│ ╙──      \t                    ^\n//│ f: bool -> 0\n\n\n// missing field, cannot constrain\n\n:e\n1.u\n{}.u\n{a: 1}.u\n{a: 1}.a 1\n1 + {a: true}.a\n{a: true}.a + 1\nsucc {a: 1}\n{a: 1} succ\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t1.u\n//│ ║        \t ^^\n//│ ╟── integer literal of type `1` does not have field 'u'\n//│ ║  l.+1: \t1.u\n//│ ╙──      \t^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+2: \t{}.u\n//│ ║        \t  ^^\n//│ ╟── tuple of type `anything` does not have field 'u'\n//│ ║  l.+2: \t{}.u\n//│ ╙──      \t^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+3: \t{a: 1}.u\n//│ ║        \t      ^^\n//│ ╟── record of type `{a: 1}` does not have field 'u'\n//│ ║  l.+3: \t{a: 1}.u\n//│ ╙──      \t^^^^^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+4: \t{a: 1}.a 1\n//│ ║        \t      ^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.+4: \t{a: 1}.a 1\n//│ ║        \t    ^\n//│ ╟── but it flows into field selection with expected type `1 -> ?a`\n//│ ║  l.+4: \t{a: 1}.a 1\n//│ ╙──      \t      ^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+5: \t1 + {a: true}.a\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.+5: \t1 + {a: true}.a\n//│ ║        \t        ^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.+5: \t1 + {a: true}.a\n//│ ╙──      \t             ^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+6: \t{a: true}.a + 1\n//│ ║        \t         ^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.+6: \t{a: true}.a + 1\n//│ ║        \t    ^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.+6: \t{a: true}.a + 1\n//│ ╙──      \t         ^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+7: \tsucc {a: 1}\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── record of type `{a: 1}` is not an instance of type `int`\n//│ ║  l.+7: \tsucc {a: 1}\n//│ ╙──      \t     ^^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+8: \t{a: 1} succ\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── record of type `{a: 1}` is not a function\n//│ ║  l.+8: \t{a: 1} succ\n//│ ╙──      \t^^^^^^\n//│ res: error\n\nlet f = x =>\n  log / succ x.prop\n  x.prop\nf { prop: 42 }\n//│ f: {prop: int & 'prop} -> 'prop\n//│ res: 42\n\n// FIXME 'prop' requirement is added twice\n:e\nf 42\nf { prap: 1 }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tf 42\n//│ ║        \t^^^^\n//│ ╟── integer literal of type `42` does not have field 'prop'\n//│ ║  l.+1: \tf 42\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t  ^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \tf { prap: 1 }\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── record of type `{prap: 1}` does not have field 'prop'\n//│ ║  l.+2: \tf { prap: 1 }\n//│ ║        \t  ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t  ^\n//│ res: error\n\n:e\nf { prop: false }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tf { prop: false }\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+1: \tf { prop: false }\n//│ ║        \t          ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.327: \t  log / succ x.prop\n//│ ║         \t             ^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.327: \t  log / succ x.prop\n//│ ╙──       \t              ^^^^^\n//│ res: error | false\n\n:e\nlet arg = 0\nf arg\n//│ arg: 0\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \tf arg\n//│ ║        \t^^^^^\n//│ ╟── integer literal of type `0` does not have field 'prop'\n//│ ║  l.+1: \tlet arg = 0\n//│ ║        \t          ^\n//│ ╟── but it flows into reference with expected type `{prop: ?prop}`\n//│ ║  l.+2: \tf arg\n//│ ║        \t  ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t  ^\n//│ res: error\n\n:e\nlet arg = {prop: not true}\nf arg\n//│ arg: {prop: bool}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \tf arg\n//│ ║        \t^^^^^\n//│ ╟── application of type `bool` is not an instance of type `int`\n//│ ║  l.+1: \tlet arg = {prop: not true}\n//│ ║        \t                 ^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.327: \t  log / succ x.prop\n//│ ║         \t             ^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.327: \t  log / succ x.prop\n//│ ╙──       \t              ^^^^^\n//│ res: bool | error\n\n\nlet g = y =>\n  f { prop: y.fld }\ng { fld: 42 }\n//│ g: {fld: int & 'a} -> 'a\n//│ res: 42\n\n:e\ng 1\ng { fld: false }\ng { fld: { oops: 1 } }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tg 1\n//│ ║        \t^^^\n//│ ╟── integer literal of type `1` does not have field 'fld'\n//│ ║  l.+1: \tg 1\n//│ ║        \t  ^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.421: \t  f { prop: y.fld }\n//│ ║         \t             ^^^^\n//│ ╟── from reference:\n//│ ║  l.421: \t  f { prop: y.fld }\n//│ ╙──       \t            ^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \tg { fld: false }\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+2: \tg { fld: false }\n//│ ║        \t         ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.327: \t  log / succ x.prop\n//│ ║         \t             ^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.421: \t  f { prop: y.fld }\n//│ ╙──       \t             ^^^^\n//│ res: error | false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \tg { fld: { oops: 1 } }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{oops: 1}` is not an instance of type `int`\n//│ ║  l.+3: \tg { fld: { oops: 1 } }\n//│ ║        \t         ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.327: \t  log / succ x.prop\n//│ ║         \t             ^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.421: \t  f { prop: y.fld }\n//│ ╙──       \t             ^^^^\n//│ res: error | {oops: 1}\n\n:e\nlet arg1 = {fld: not true}\nlet arg2 = {fld: arg}\nf arg1\nf arg2\n//│ arg1: {fld: bool}\n//│ arg2: {fld: {prop: bool}}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \tf arg1\n//│ ║        \t^^^^^^\n//│ ╟── record of type `forall ?a. {fld: ?a}` does not have field 'prop'\n//│ ║  l.+1: \tlet arg1 = {fld: not true}\n//│ ║        \t           ^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{prop: ?prop}`\n//│ ║  l.+3: \tf arg1\n//│ ║        \t  ^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t  ^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+4: \tf arg2\n//│ ║        \t^^^^^^\n//│ ╟── record of type `{fld: forall ?a. {prop: ?a}}` does not have field 'prop'\n//│ ║  l.+2: \tlet arg2 = {fld: arg}\n//│ ║        \t           ^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{prop: ?prop}`\n//│ ║  l.+4: \tf arg2\n//│ ║        \t  ^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t  ^\n//│ res: error\n\nlet h = y =>\n  succ / f y\nsucc / h { prop: 42 }\n//│ h: {prop: int} -> int\n//│ res: int\n\n:e\nh arg2\nh arg\nh / 42\nx => h / succ x\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \th arg2\n//│ ║        \t^^^^^^\n//│ ╟── record of type `{fld: forall ?a. {prop: ?a}}` does not have field 'prop'\n//│ ║  l.472: \tlet arg2 = {fld: arg}\n//│ ║         \t           ^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{prop: ?prop}`\n//│ ║  l.+1: \th arg2\n//│ ║        \t  ^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.511: \t  succ / f y\n//│ ╙──       \t           ^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \th arg\n//│ ║        \t^^^^^\n//│ ╟── application of type `bool` is not an instance of type `int`\n//│ ║  l.402: \tlet arg = {prop: not true}\n//│ ║         \t                 ^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.511: \t  succ / f y\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t   ^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \th / 42\n//│ ║        \t^^^^^^\n//│ ╟── integer literal of type `42` does not have field 'prop'\n//│ ║  l.+3: \th / 42\n//│ ║        \t    ^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.511: \t  succ / f y\n//│ ╙──       \t           ^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+4: \tx => h / succ x\n//│ ║        \t     ^^^^^^^^^^\n//│ ╟── application of type `int` does not have field 'prop'\n//│ ║  l.+4: \tx => h / succ x\n//│ ║        \t         ^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ║         \t   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.511: \t  succ / f y\n//│ ╙──       \t           ^\n//│ res: int -> (error | int)\n\n:e\nlet mkArg2 = a => {prop: succ a}\nh / mkArg2 false\n//│ mkArg2: int -> {prop: int}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \th / mkArg2 false\n//│ ║        \t    ^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+2: \th / mkArg2 false\n//│ ║        \t           ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.+1: \tlet mkArg2 = a => {prop: succ a}\n//│ ╙──      \t                              ^\n//│ res: int\n\nlet i = y =>\n  succ / f y.fld\n//│ i: {fld: {prop: int}} -> int\n\n:e\ni arg2\ni arg\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \ti arg2\n//│ ║        \t^^^^^^\n//│ ╟── application of type `bool` is not an instance of type `int`\n//│ ║  l.402: \tlet arg = {prop: not true}\n//│ ║         \t                 ^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.593: \t  succ / f y.fld\n//│ ║         \t         ^^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t   ^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \ti arg\n//│ ║        \t^^^^^\n//│ ╟── record of type `forall ?a. {prop: ?a}` does not have field 'fld'\n//│ ║  l.402: \tlet arg = {prop: not true}\n//│ ║         \t          ^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{fld: ?fld}`\n//│ ║  l.+2: \ti arg\n//│ ║        \t  ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.593: \t  succ / f y.fld\n//│ ║         \t            ^^^^\n//│ ╟── from reference:\n//│ ║  l.593: \t  succ / f y.fld\n//│ ╙──       \t           ^\n//│ res: error | int\n\nlet test x y = if x.prop then i x else y\n//│ test: {fld: {prop: int}, prop: bool} -> 'a -> (int | 'a)\n\n:e\ntest arg2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \ttest arg2\n//│ ║        \t^^^^^^^^^\n//│ ╟── application of type `bool` is not an instance of type `int`\n//│ ║  l.402: \tlet arg = {prop: not true}\n//│ ║         \t                 ^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.593: \t  succ / f y.fld\n//│ ║         \t         ^^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t   ^^^^^\n//│ res: error | 'a -> (int | 'a)\n\nlet mkArg = a => {prop: a}\nh / mkArg 1\ni { fld: mkArg 1 }\n//│ mkArg: 'a -> {prop: 'a}\n//│ res: int\n//│ res: int\n\n:e\ng { fld: mkArg 1 } // TODO multi-step flow message?\nh / mkArg false\ni { fld: mkArg false }\ni / mkArg 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tg { fld: mkArg 1 } // TODO multi-step flow message?\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{prop: ?a}` is not an instance of type `int`\n//│ ║  l.648: \tlet mkArg = a => {prop: a}\n//│ ║         \t                 ^^^^^^^^^\n//│ ╟── but it flows into application with expected type `int`\n//│ ║  l.+1: \tg { fld: mkArg 1 } // TODO multi-step flow message?\n//│ ║        \t         ^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.327: \t  log / succ x.prop\n//│ ║         \t             ^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.421: \t  f { prop: y.fld }\n//│ ╙──       \t             ^^^^\n//│ res: error | {prop: 1}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \th / mkArg false\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+2: \th / mkArg false\n//│ ║        \t          ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.511: \t  succ / f y\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t   ^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \ti { fld: mkArg false }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.+3: \ti { fld: mkArg false }\n//│ ║        \t               ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.593: \t  succ / f y.fld\n//│ ║         \t         ^^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.328: \t  x.prop\n//│ ╙──       \t   ^^^^^\n//│ res: error | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+4: \ti / mkArg 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── record of type `{prop: ?a}` does not have field 'fld'\n//│ ║  l.648: \tlet mkArg = a => {prop: a}\n//│ ║         \t                 ^^^^^^^^^\n//│ ╟── but it flows into application with expected type `{fld: ?fld}`\n//│ ║  l.+4: \ti / mkArg 1\n//│ ║        \t    ^^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.593: \t  succ / f y.fld\n//│ ║         \t            ^^^^\n//│ ╟── from reference:\n//│ ║  l.593: \t  succ / f y.fld\n//│ ╙──       \t           ^\n//│ res: error | int\n\n\n\n// parse error\n\n:pe\nfoo\nba)r\nbaz\n//│ /!\\ Parse error: Expected end-of-input:2:3, found \")r\\nbaz\\n\" at l.725:3: ba)r\n"
  },
  {
    "path": "shared/src/test/diff/basics/ExplicitDatatypes.fun",
    "content": "\ndata Left v\ndata Right v\n//│ Defined class Left[+v]\n//│ Defined class Right[+v]\n//│ Left: 'a -> Left['a]\n//│ Right: 'a -> Right['a]\n\nlet Either l r = Left l | Right r // TODO actual type parameters\n//│ Either: 'a -> 'b -> (Left['a] | Right['b])\n\nEither 1 2\n//│ res: Left[1] | Right[2]\n\nres.v\n//│ res: 1 | 2\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Flow.fun",
    "content": "\n:p\ndata L x\ndata R x\n//│ Parsed: data L(...x); data R(...x);\n//│ Desugared: class L[x]: {x: x}\n//│ Desugared: class R[x]: {x: x}\n//│ Desugared: def L: forall x. (...x) -> L[x]\n//│ AST: Def(false,Var(L),Right(PolyType(List(Left(TypeName(x))),Function(TypeName(x),AppliedType(TypeName(L),List(TypeName(x)))))),true)\n//│ Desugared: def R: forall x. (...x) -> R[x]\n//│ AST: Def(false,Var(R),Right(PolyType(List(Left(TypeName(x))),Function(TypeName(x),AppliedType(TypeName(R),List(TypeName(x)))))),true)\n//│ Defined class L[+x]\n//│ Defined class R[+x]\n//│ L: 'a -> L['a]\n//│ R: 'a -> R['a]\n\n// TODO flow-type\n:e\nlet f x = if x is L y then y else 0\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.19: \tlet f x = if x is L y then y else 0\n//│ ╙──      \t                  ^^^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.19: \tlet f x = if x is L y then y else 0\n//│ ╙──      \t                           ^\n//│ f: error -> (0 | error)\n\n// TODO\n// true and false\n// :e\n// 1 and 2\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Intersections.fun",
    "content": "\n// Overloading is not yet really supported...\n// the simplifier thinks it's an impossible type!\nlet foo = _ as (_: (Int => Int) & (Bool => Bool))\n//│ foo: (_: nothing,)\n\n:ns\nlet foo = _ as (_: (Int => Int) & (Bool => Bool))\nlet foo = (_ as (_: (Int => Int) & (Bool => Bool))).0\n//│ foo: forall 'a. (_: 'a,)\n//│   where\n//│     'a <: int -> int & bool -> bool\n//│ foo: forall 'a. 'a\n\nfoo(1)\n//│ res: nothing\n\n:ns\nfoo(1)\n//│ res: 'a\n\nsucc / foo(1)\n//│ res: int\n\n// Intersection-based overloading is not actually supported... a value of this type is impossible to provide:\nlet foo = (Int => Int) & (Bool => Bool)\n//│ foo: int -> int & bool -> bool\n\n:e\nfoo(1) // returns int & bool, equivalent to nothing\nsucc / foo(1)\nfoo(true)\nnot / foo(true)\n//│ res: bool | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.31: \tsucc / foo(1)\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── reference of type `bool` is not an instance of type `int`\n//│ ║  l.26: \tlet foo = (Int => Int) & (Bool => Bool)\n//│ ║        \t                                  ^^^^\n//│ ╟── but it flows into application with expected type `int`\n//│ ║  l.31: \tsucc / foo(1)\n//│ ╙──      \t       ^^^^^^\n//│ res: error | int\n//│ res: bool | int\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.33: \tnot / foo(true)\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int` is not an instance of type `bool`\n//│ ║  l.26: \tlet foo = (Int => Int) & (Bool => Bool)\n//│ ║        \t                  ^^^\n//│ ╟── but it flows into application with expected type `bool`\n//│ ║  l.33: \tnot / foo(true)\n//│ ╙──      \t      ^^^^^^^^^\n//│ res: bool | error\n\n:e\nnot / foo(1)\nfoo(1) as Nothing\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.58: \tnot / foo(1)\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── reference of type `int` is not an instance of type `bool`\n//│ ║  l.26: \tlet foo = (Int => Int) & (Bool => Bool)\n//│ ║        \t                  ^^^\n//│ ╟── but it flows into application with expected type `bool`\n//│ ║  l.58: \tnot / foo(1)\n//│ ╙──      \t      ^^^^^^\n//│ res: bool | error\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.59: \tfoo(1) as Nothing\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int` does not match type `nothing`\n//│ ║  l.26: \tlet foo = (Int => Int) & (Bool => Bool)\n//│ ║        \t                  ^^^\n//│ ╟── but it flows into application with expected type `nothing`\n//│ ║  l.59: \tfoo(1) as Nothing\n//│ ║        \t^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.59: \tfoo(1) as Nothing\n//│ ╙──      \t          ^^^^^^^\n//│ res: nothing\n\n:e\nfoo as Nothing\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.85: \tfoo as Nothing\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type intersection of type `int -> int & bool -> bool` does not match type `nothing`\n//│ ║  l.26: \tlet foo = (Int => Int) & (Bool => Bool)\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `nothing`\n//│ ║  l.85: \tfoo as Nothing\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.85: \tfoo as Nothing\n//│ ╙──      \t       ^^^^^^^\n//│ res: nothing\n\n:e\nlet oops = (&)\n//│ ╔══[ERROR] Illegal use of reserved operator: &\n//│ ║  l.101: \tlet oops = (&)\n//│ ╙──       \t           ^^^\n//│ ╔══[ERROR] identifier not found: &\n//│ ║  l.101: \tlet oops = (&)\n//│ ╙──       \t           ^^^\n//│ oops: error\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Iso.fun",
    "content": "// A file to isolating tests for easier debugging\n\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Lambdas.fun",
    "content": "\nlet a = succ\nlet x = true\n//│ a: int -> int\n//│ x: true\n\nx => add (a x)\n//│ res: int -> int -> int\n\nx =>\n  add (a x)\n//│ res: int -> int -> int\n\nlet x =\n  x =>\n    add (a x)\n//│ x: int -> int -> int\n\nlet id = v => v\n//│ id: 'a -> 'a\n\nf => f f\n//│ res: ('a -> 'b & 'a) -> 'b\n\nf => id f id f id\n//│ res: ((forall 'a. 'a -> 'a) -> 'b -> (forall 'a. 'a -> 'a) -> 'c & 'b) -> 'c\n\n:pe\nlet oops = hu(h\n//│ /!\\ Parse error: Expected end-of-input:1:14, found \"(h\\n\" at l.29:14: let oops = hu(h\n\nx => x; y => y\n//│ res: 'a -> 'a\n//│ res: 'a -> 'a\n\n:pe\nx => let y = x; y\n//│ /!\\ Parse error: Expected expression:1:1, found \"x => let y\" at l.37:1: x => let y = x; y\n\nx => (let y = x; y)\nx =>\n  let y = x; y\nx =>\n  let y = x\n  y\n//│ res: 'a -> 'a\n//│ res: 'a -> 'a\n//│ res: 'a -> 'a\n\nlet f x = x + 1\nlet f x y = x + y\nlet f x y z = if x then y else z\nlet f x y z = { log x; if y < z then y else z }\n//│ f: int -> int\n//│ f: int -> int -> int\n//│ f: bool -> 'a -> 'a -> 'a\n//│ f: anything -> (number & 'a) -> (number & 'a) -> 'a\n\n// TODO\n// let f (x: int) = x + 1\n\n// TODO\n:pe\nlet f / x: int = x + 1\nlet f / x: int, y: int = x + y\n//│ /!\\ Parse error: Expected (data type definition | data definition | let binding | expression):1:1, found \"let f / x:\" at l.64:1: let f / x: int = x + 1\n\n// TODO\n// let f (\n//   x\n//   y\n// ) = x + 1\n\nlet f(x: int) = x + 1\n//│ f: (x: int,) -> int\n\nf 42\n//│ res: int\n\nf (x: 42)\n//│ res: int\n\n:e\nf (y: 42)\n//│ ╔══[ERROR] Wrong tuple field name: found 'y' instead of 'x'\n//│ ║  l.84: \tf (y: 42)\n//│ ╙──      \t   ^^^^^\n//│ res: error | int\n\n:e\nf (x: 42, y: 43)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.91: \tf (x: 42, y: 43)\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── tuple of type `(x: 42, y: 43,)` is not an instance of type `int`\n//│ ║  l.91: \tf (x: 42, y: 43)\n//│ ║        \t   ^^^^^^^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.91: \tf (x: 42, y: 43)\n//│ ║        \t  ^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.74: \tlet f(x: int) = x + 1\n//│ ║        \t                ^\n//│ ╟── from binding:\n//│ ║  l.74: \tlet f(x: int) = x + 1\n//│ ╙──      \t      ^^^^^^\n//│ res: error | int\n\n(a, b) => a + b\n//│ res: (int, int,) -> int\nres(1,2)\n//│ res: int\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Literals.fun",
    "content": "\n1\n//│ res: 1\n\n\"hello\"\n//│ res: \"hello\"\n\n// TODO literal booleans\ntrue\n//│ res: true\n\n1 as Int\n\"hello\" as String\ntrue as Bool\n//│ res: int\n//│ res: string\n//│ res: bool\n\n:w\n1 as int\n\"hello\" as string\n//│ ╔══[WARNING] Variable name 'int' already names a symbol in scope. If you want to refer to that symbol, you can use `scope.int`; if not, give your future readers a break and use another name :^)\n//│ ║  l.20: \t1 as int\n//│ ╙──      \t     ^^^\n//│ res: 1\n//│ ╔══[WARNING] Variable name 'string' already names a symbol in scope. If you want to refer to that symbol, you can use `scope.string`; if not, give your future readers a break and use another name :^)\n//│ ║  l.21: \t\"hello\" as string\n//│ ╙──      \t           ^^^^^^\n//│ res: \"hello\"\n\n1 as (_: int)\n\"hello\" as (_: string)\n//│ res: (_: 1,)\n//│ res: (_: \"hello\",)\n\n:e\n1 as true\ntrue as Int\nfalse as 1\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.37: \t1 as true\n//│ ║        \t^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `true`\n//│ ║  l.37: \t1 as true\n//│ ║        \t^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.37: \t1 as true\n//│ ╙──      \t     ^^^^\n//│ res: true\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.38: \ttrue as Int\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.38: \ttrue as Int\n//│ ║        \t^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.38: \ttrue as Int\n//│ ╙──      \t        ^^^\n//│ res: int\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.39: \tfalse as 1\n//│ ║        \t^^^^^^^^^^\n//│ ╟── reference of type `false` does not match type `1`\n//│ ║  l.39: \tfalse as 1\n//│ ║        \t^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.39: \tfalse as 1\n//│ ╙──      \t         ^\n//│ res: 1\n\nlet f = b => if b then 0 else 1\n//│ f: bool -> (0 | 1)\n\nlet pred = n => 0 < n\n//│ pred: number -> bool\n\nlet g = x => if pred x then x else f false\n//│ g: (number & 'a) -> (0 | 1 | 'a)\n\ng 3\n//│ res: 0 | 1 | 3\n\ng / succ 3\n//│ res: int\n\nx => if x then x else f false\n//│ res: (bool & 'a) -> (0 | 1 | 'a)\n\nres false\n//│ res: 0 | 1 | false\n\nlet rec f = n =>\n  if pred n then n else f (n + 1)\n//│ f: int -> int\n\nlet g = n =>\n  if pred n then 0 else if not (pred n) then 1 else f n\n//│ g: int -> int\n\nx => if pred x then x else f x\n//│ res: int -> int\n\n:e\nf false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.104: \tf false\n//│ ║         \t^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.104: \tf false\n//│ ║         \t  ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.93: \t  if pred n then n else f (n + 1)\n//│ ╙──      \t                           ^\n//│ res: error | false | int\n\nlet take0 (x: 0) = 0\nlet take1 (x: 1) = 1\n//│ take0: (x: 0,) -> 0\n//│ take1: (x: 1,) -> 1\n\nlet takeWhat y = if y < 0 then take0 y else take1 y\n//│ takeWhat: nothing -> (0 | 1)\n\nlet takeWhat y = if y < 0 then take0 (x: y) else take1 (x: y)\n//│ takeWhat: nothing -> (0 | 1)\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Negations.fun",
    "content": "\ndata Wine\n//│ Defined class Wine\n//│ Wine: Wine\n\n\nlet jesus = neg Wine => Wine\n//│ jesus: ~Wine -> Wine\n\nlet w = jesus(water: \"Evian\")\n//│ w: Wine\n\n\nlet jesus = (water: neg Wine) => Wine\n//│ jesus: (water: ~Wine,) -> Wine\n\nlet w = jesus(water: \"Evian\")\n//│ w: Wine\n\n:e\njesus w\njesus(water: w)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.21: \tjesus w\n//│ ║        \t^^^^^^^\n//│ ╟── reference of type `Wine` does not match type `~Wine`\n//│ ║  l.14: \tlet jesus = (water: neg Wine) => Wine\n//│ ║        \t                                 ^^^^\n//│ ╟── but it flows into reference with expected type `~Wine`\n//│ ║  l.21: \tjesus w\n//│ ║        \t      ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.14: \tlet jesus = (water: neg Wine) => Wine\n//│ ║        \t                    ^^^^^^^^\n//│ ╟── from binding:\n//│ ║  l.14: \tlet jesus = (water: neg Wine) => Wine\n//│ ╙──      \t             ^^^^^^^^^^^^^^^\n//│ res: Wine | error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.22: \tjesus(water: w)\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── reference of type `Wine` does not match type `~Wine`\n//│ ║  l.14: \tlet jesus = (water: neg Wine) => Wine\n//│ ║        \t                                 ^^^^\n//│ ╟── but it flows into reference with expected type `~Wine`\n//│ ║  l.22: \tjesus(water: w)\n//│ ║        \t             ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.14: \tlet jesus = (water: neg Wine) => Wine\n//│ ╙──      \t                    ^^^^^^^^\n//│ res: Wine | error\n\n\n(0 | 1) & neg 0\n//│ res: 1\n\n(0 | 1) & neg 0 as 1\n//│ res: 1\n\n:e\n(0 | 1) & neg 0 as 0\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.61: \t(0 | 1) & neg 0 as 0\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type intersection of type `1` does not match type `0`\n//│ ║  l.61: \t(0 | 1) & neg 0 as 0\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.61: \t(0 | 1) & neg 0 as 0\n//│ ╙──      \t                   ^\n//│ res: 0\n\n(0 | 1) & neg 0 & neg 1 as \"wat\"\n//│ res: \"wat\"\n\n:e\nneg 0 as 1\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.77: \tneg 0 as 1\n//│ ║        \t^^^^^^^^^^\n//│ ╟── application of type `~0` does not match type `1`\n//│ ║  l.77: \tneg 0 as 1\n//│ ║        \t^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.77: \tneg 0 as 1\n//│ ╙──      \t         ^\n//│ res: 1\n\n1 as neg 0\n//│ res: ~0\n"
  },
  {
    "path": "shared/src/test/diff/basics/Operators.fun",
    "content": "\nlet a = 1\nlet b = 2\nlet c = 3\nlet d = 4\n//│ a: 1\n//│ b: 2\n//│ c: 3\n//│ d: 4\n\na + b\n//│ res: int\n\n:p\na +\n  b\n//│ Parsed: +(...a)(...{b});\n//│ Desugared: +(...a)(...{b})\n//│ AST: App(App(Var(+),Var(a)),Blk(List(Var(b))))\n//│ res: int\n\n:pe\na +\n  b +\n  c\n//│ /!\\ Parse error: Expected expression:1:1, found \"a +\\n  b +\\n\" at l.23:1: a +\n\n:p\nsucc a +\n  b +\n    c\n//│ Parsed: +(...(succ(...a)))(...{+(...b)(...{c})});\n//│ Desugared: +(...(succ(...a)))(...{+(...b)(...{c})})\n//│ AST: App(App(Var(+),App(Var(succ),Var(a))),Blk(List(App(App(Var(+),Var(b)),Blk(List(Var(c)))))))\n//│ res: int\n\n:p\nsucc / a +\n  b +\n    c\n//│ Parsed: succ(...(+(...a)(...{+(...b)(...{c})})));\n//│ Desugared: succ(...(+(...a)(...{+(...b)(...{c})})))\n//│ AST: App(Var(succ),App(App(Var(+),Var(a)),Blk(List(App(App(Var(+),Var(b)),Blk(List(Var(c))))))))\n//│ res: int\n\n:p\na\n  + b\na\n  + b\n  + c\na\n  + b\n  + c\n  + d\n//│ Parsed: +(...a)(...b); +(...(+(...a)(...b)))(...c); +(...(+(...(+(...a)(...b)))(...c)))(...d);\n//│ Desugared: +(...a)(...b)\n//│ AST: App(App(Var(+),Var(a)),Var(b))\n//│ Desugared: +(...(+(...a)(...b)))(...c)\n//│ AST: App(App(Var(+),App(App(Var(+),Var(a)),Var(b))),Var(c))\n//│ Desugared: +(...(+(...(+(...a)(...b)))(...c)))(...d)\n//│ AST: App(App(Var(+),App(App(Var(+),App(App(Var(+),Var(a)),Var(b))),Var(c))),Var(d))\n//│ res: int\n//│ res: int\n//│ res: int\n\n:p\na\n  + b\n  + c\n    + 1\n    + 2\n      + 3\n  + d\n//│ Parsed: +(...(+(...(+(...a)(...b)))(...(+(...(+(...c)(...1)))(...(+(...2)(...3)))))))(...d);\n//│ Desugared: +(...(+(...(+(...a)(...b)))(...(+(...(+(...c)(...1)))(...(+(...2)(...3)))))))(...d)\n//│ AST: App(App(Var(+),App(App(Var(+),App(App(Var(+),Var(a)),Var(b))),App(App(Var(+),App(App(Var(+),Var(c)),IntLit(1))),App(App(Var(+),IntLit(2)),IntLit(3))))),Var(d))\n//│ res: int\n\n:pe\na\n+ b\n//│ /!\\ Parse error: Expected end-of-input:2:1, found \"+ b\\n\" at l.82:1: + b\n\n:pe\nlet x = 1\n+ 2\n//│ /!\\ Parse error: Expected end-of-input:2:1, found \"+ 2\\n\" at l.87:1: + 2\n\nlet x = 1\n  + 2\n//│ x: int\n\n:pe\nlet x =\n  1\n  + 2\n//│ /!\\ Parse error: Expected end-of-input:3:3, found \"+ 2\\n\" at l.97:3:   + 2\n\nlet x =\n  1\n    + 2\n//│ x: int\n\nsucc / succ 1\n  + 1\n//│ res: int\n\n:p\nsucc\n    a + b\n  + c\n//│ Parsed: +(...(succ(...{+(...a)(...b)})))(...c);\n//│ Desugared: +(...(succ(...{+(...a)(...b)})))(...c)\n//│ AST: App(App(Var(+),App(Var(succ),Blk(List(App(App(Var(+),Var(a)),Var(b)))))),Var(c))\n//│ res: int\n\n// Maybe allow this as it lets us nicely align the operands?\n:pe\nlet test =\n    a\n  + b\n  + c\n//│ /!\\ Parse error: Expected end-of-input:3:3, found \"+ b\\n  + c\\n\" at l.122:3:   + b\n"
  },
  {
    "path": "shared/src/test/diff/basics/RecFuns.fun",
    "content": "\n// From a comment on the Simple-sub blog post:\n\nlet rec r a = r\n//│ r: 'r\n//│   where\n//│     'r :> anything -> 'r\n\nlet join a b = if true then a else b\n//│ join: 'a -> 'a -> 'a\n\n// \"Lateral\" hash consing\nlet s = join r r\n//│ s: 'r\n//│   where\n//│     'r :> anything -> 'r\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Records.fun",
    "content": "\nlet empty = {}\n//│ empty: anything\n\n1\n(1)\n((1))\n{1}\n{{1}}\n{(1)}\n//│ res: 1\n//│ res: 1\n//│ res: 1\n//│ res: 1\n//│ res: 1\n//│ res: 1\n\nx : 1\nx: 1\n{x: 1}\nx: 1, y: 2\n//│ res: (x: 1,)\n//│ res: (x: 1,)\n//│ res: {x: 1}\n//│ res: (x: 1, y: 2,)\n\nx : 1, 2, 3\nx: 1, 2, z: 3\n1, y: 2, z: 3\nx: 1, y: 2, z: 3\n//│ res: (x: 1, 2, 3,)\n//│ res: (x: 1, 2, z: 3,)\n//│ res: (1, y: 2, z: 3,)\n//│ res: (x: 1, y: 2, z: 3,)\n\nlet r = {u:1,v:2}\nlet r = { u:1 , v:2 }\nlet r = { u :1 , v :2 }\nlet r = {u: 1, v: 2}\nlet r = { u: 1, v: 2 }\nlet r = { u: 1,v: 2 }\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n\nr.u + r.v\nr . u + r . v\nr .u + r .v\nr. u + r. v\n//│ res: int\n//│ res: int\n//│ res: int\n//│ res: int\n\n:e\nempty.w\nr.w\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.59: \tempty.w\n//│ ║        \t     ^^\n//│ ╟── tuple of type `anything` does not have field 'w'\n//│ ║  l.2: \tlet empty = {}\n//│ ║       \t            ^^\n//│ ╟── but it flows into reference with expected type `{w: ?w}`\n//│ ║  l.59: \tempty.w\n//│ ╙──      \t^^^^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.60: \tr.w\n//│ ║        \t ^^\n//│ ╟── record of type `{u: 1, v: 2}` does not have field 'w'\n//│ ║  l.41: \tlet r = { u: 1,v: 2 }\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{w: ?w}`\n//│ ║  l.60: \tr.w\n//│ ╙──      \t^\n//│ res: error\n\nlet rec sumHeads = x => x.head + sumHeads x.tail\n//│ sumHeads: 'a -> int\n//│   where\n//│     'a <: {head: int, tail: 'a}\n\nlet rec ouroboros = {head: 0, tail: ouroboros, eyes: {l: 1, r: 2}}\n//│ ouroboros: 'ouroboros\n//│   where\n//│     'ouroboros :> {eyes: {l: 1, r: 2}, head: 0, tail: 'ouroboros}\n\nsumHeads ouroboros\n//│ res: int\n\nlet r = {\n  u: 1, v: 2 }\nlet r = {\n  u: 1,\n  v: 2,\n}\nlet r = {\n  u: 1\n  v: 2\n}\nlet r = {\n  u: 1,\n  v: 2\n}\nlet r = {\n  u: 1;\n  v: 2\n}\nlet r = {\n  u: 1\n  v: u + 1\n}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: int}\n\n:pe\nlet r = {\n  u: 1;\n  v: 2;\n}\n//│ /!\\ Parse error: Expected let binding:1:1, found \"let r = {\\n\" at l.125:1: let r = {\n\nlet r = {\n  u:\n    1\n  v:\n    2\n}\nlet r = {\n  u:\n    log \"ok\"\n    1\n  v:\n    log \"ko\"\n    2\n}\nlet r = {\n  u:\n    let x = 1\n    x\n  v:\n    let y = 2\n    y\n}\n//│ r: {u: 1, v: 2}\n//│ r: {u: 1, v: 2}\n//│ r: {u: {x: 1}, v: {y: 2}}\n// ^ FIXME? field punning...\n\n// TODO\nlet r = {\n  u:\n    x: 1\n    y: 2\n  v:\n    x: 3\n    y: 4\n}\n//│ r: {u: {x: 1, y: 2}, v: {x: 3, y: 4}}\n\n:w // Disallow or warn about this?\nlet r = { u:\n  1, v: 2 }\n//│ ╔══[WARNING] Missing name for record field\n//│ ║  l.171: \t  1, v: 2 }\n//│ ╙──       \t  ^\n//│ r: {u: {_1: 1, v: 2}}\n\n// :e // used to raise: useless fields in statement position\nlet r =\n  u:\n    x: 1\n    y: 2\n  v:\n    x: 3\n    y: 4\nlet r = (\n  u:\n    x: 1\n    y: 2\n  v:\n    x: 3\n    y: 4\n)\nlet r = (\n  u: (\n    x: 1\n    y: 2\n  ),\n  v:\n    x: 3\n    y: 4\n)\n//│ r: (u: (x: 1, y: 2,), v: (x: 3, y: 4,),)\n//│ r: (u: (x: 1, y: 2,), v: (x: 3, y: 4,),)\n//│ r: (u: (x: 1, y: 2,), v: (x: 3, y: 4,),)\n\nlet r = (\n  u: (\n    x: 1,\n    y: 2,\n  ),\n  v:\n    x: 3\n    y: 4\n)\nlet r = (\n  u: (\n    x: 1,\n    y: 2,\n  ),\n  v: (\n    x: 3,\n    y: 4,\n  ),\n)\n//│ r: (u: (x: 1, y: 2,), v: (x: 3, y: 4,),)\n//│ r: (u: (x: 1, y: 2,), v: (x: 3, y: 4,),)\n\nlet r = (\n  u:\n    x: 1,\n    y: 2,,\n  v:\n    x: 3,\n    y: 4,\n)\n//│ r: (u: (x: 1, y: 2,), v: (x: 3, y: 4,),)\n\n:pe\nlet r = (\n  u:\n    x: 1,\n    y: 2,\n    ,\n  v:\n    x: 3,\n    y: 4,\n)\n//│ /!\\ Parse error: Expected let binding:1:1, found \"let r = (\\n\" at l.239:1: let r = (\n\na:\n  b:\n    c:\n      1\na: {\n  b:\n    c:\n      1\n  d: 2\n}\na:\n  b: {\n    c:\n      1\n  }\n  d: 2\n//│ res: (a: (b: (c: 1,),),)\n//│ res: (a: {b: {c: 1}, d: 2},)\n//│ res: (a: (b: {c: 1}, d: 2,),)\n\n// :e // used to raise: useless fields in statement position\na:\n  b:\n    c:\n      1\n  d: 2\n//│ res: (a: (b: (c: 1,), d: 2,),)\n\n:w\na:\n  b: 1\n  c: 2\n  3\na: {\n  b: 1\n  c: 2\n  3\n}\n//│ ╔══[WARNING] Previous field definitions are discarded by this returned expression.\n//│ ║  l.282: \t  3\n//│ ╙──       \t  ^\n//│ res: (a: 3,)\n//│ ╔══[WARNING] Previous field definitions are discarded by this returned expression.\n//│ ║  l.286: \t  3\n//│ ╙──       \t  ^\n//│ res: (a: 3,)\n\nlet r =\n  x: 1\n  log x\n  y: 2\nlet r =\n  x: 1\n  log x\n  y: 2\n  let _ = log y\n//│ r: (x: 1, y: 2,)\n//│ r: (x: 1, y: 2,)\n\n// TODO ignore return-position unit expressions?\n:w\nlet r =\n  x: 1\n  log x\n  y: 2\n  log y\n//│ ╔══[WARNING] Previous field definitions are discarded by this returned expression.\n//│ ║  l.315: \t  log y\n//│ ╙──       \t  ^^^^^\n//│ r: unit\n\n\n// Funnily, because of dependent record literals, one can do:\n:w\nlet res =\n  arg: 0\n  arg + 1\n//│ ╔══[WARNING] Previous field definitions are discarded by this returned expression.\n//│ ║  l.326: \t  arg + 1\n//│ ╙──       \t  ^^^^^^^\n//│ res: int\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Simplesub1.fun",
    "content": "// Tests ported from Simplesub\n\n:ShowRelativeLineNums\n\n\n\n// --- basic --- //\n\n\n42\n//│ res: 42\n\nx => 42\n//│ res: anything -> 42\n\nx => x\n//│ res: 'a -> 'a\n\nx => x 42\n//│ res: (42 -> 'a) -> 'a\n\n(x => x) 42\n//│ res: 42\n\nf => x => f (f x)  // twice\n//│ res: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n\nlet twice = f => x => f (f x)\n//│ twice: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n\n\n\n// --- booleans --- //\n\n\ntrue\n//│ res: true\n\nnot true\n//│ res: bool\n\nx => not x\n//│ res: bool -> bool\n\n(x => not x) true\n//│ res: bool\n\nx => y => z => if x then y else z\n//│ res: bool -> 'a -> 'a -> 'a\n\nx => y => if x then y else x\n//│ res: (bool & 'a) -> 'a -> 'a\n\n:e\nsucc true\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tsucc true\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.+1: \tsucc true\n//│ ╙──      \t     ^^^^\n//│ res: error | int\n\n:e\nx => succ (not x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tx => succ (not x)\n//│ ║        \t     ^^^^^^^^^^^^\n//│ ╟── application of type `bool` is not an instance of type `int`\n//│ ║  l.+1: \tx => succ (not x)\n//│ ║        \t           ^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \tx => succ (not x)\n//│ ╙──      \t          ^^^^^^^\n//│ res: bool -> (error | int)\n\n:e\n(x => not x.f) { f: 123 }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(x => not x.f) { f: 123 }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `123` is not an instance of type `bool`\n//│ ║  l.+1: \t(x => not x.f) { f: 123 }\n//│ ║        \t                    ^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.+1: \t(x => not x.f) { f: 123 }\n//│ ║        \t          ^^^\n//│ ╟── from field selection:\n//│ ║  l.+1: \t(x => not x.f) { f: 123 }\n//│ ╙──      \t           ^^\n//│ res: bool | error\n\n:e\n(f => x => not (f x.u)) false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(f => x => not (f x.u)) false\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not a function\n//│ ║  l.+1: \t(f => x => not (f x.u)) false\n//│ ║        \t                        ^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.+1: \t(f => x => not (f x.u)) false\n//│ ║        \t                ^^^^^\n//│ ╟── from reference:\n//│ ║  l.+1: \t(f => x => not (f x.u)) false\n//│ ╙──      \t                ^\n//│ res: error | {u: anything} -> bool\n\n\n\n// --- records --- //\n\n\nx => x.f\n//│ res: {f: 'f} -> 'f\n\n// note: MLsub returns \"⊤\" (equivalent)\n{}\n//│ res: anything\n\n{ f: 42 }\n//│ res: {f: 42}\n\n{ f: 42 }.f\n//│ res: 42\n\n(x => x.f) { f: 42 }\n//│ res: 42\n\nf => { x: f 42 }.x\n//│ res: (42 -> 'x) -> 'x\n\nf => { x: f 42, y: 123 }.y\n//│ res: (42 -> anything) -> 123\n\nif true then { a: 1, b: true } else { b: false, c: 42 }\n//│ res: {b: Bool}\n\n:e\n{ a: 123, b: true }.c\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{ a: 123, b: true }.c\n//│ ║        \t                   ^^\n//│ ╟── record of type `{a: 123, b: true}` does not have field 'c'\n//│ ║  l.+1: \t{ a: 123, b: true }.c\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^\n//│ res: error\n\n:e\nx => { a: x }.b\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \tx => { a: x }.b\n//│ ║        \t             ^^\n//│ ╟── record of type `{a: ?a}` does not have field 'b'\n//│ ║  l.+1: \tx => { a: x }.b\n//│ ╙──      \t     ^^^^^^^^\n//│ res: anything -> error\n\n\n\n// --- self-app --- //\n\n\nx => x x\n//│ res: ('a -> 'b & 'a) -> 'b\n\nres id\n//│ res: 'a -> 'a\n\n\nlet f = (x => x + 1); {a: f; b: f 2}\n//│ f: int -> int\n//│ res: {a: int -> int, b: int}\n\nx => x x x\n//│ res: ('a -> 'a -> 'b & 'a) -> 'b\n\nx => y => x y x\n//│ res: ('a -> 'b -> 'c & 'b) -> 'a -> 'c\n\nx => y => x x y\n//│ res: ('a -> 'b -> 'c & 'a) -> 'b -> 'c\n\n:e // Omega: causes divergence in first-class-polymorphic type inference, as expected\n(x => x x) (x => x x)\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.+1: \t(x => x x) (x => x x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n\n\nx => {l: x x, r: x }\n//│ res: ('a -> 'b & 'a) -> {l: 'b, r: 'a}\n\n\n// * From https://github.com/stedolan/mlsub\n// * Y combinator:\n:e // similarly to Omega\n(f => (x => f (x x)) (x => f (x x)))\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.+1: \t(f => (x => f (x x)) (x => f (x x)))\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: ('a -> 'a) -> (error | 'a)\n\n// * Z combinator:\n:e\n(f => (x => f (v => (x x) v)) (x => f (v => (x x) v)))\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.+1: \t(f => (x => f (v => (x x) v)) (x => f (v => (x x) v)))\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> (error | 'c)\n\n// * Function that takes arbitrarily many arguments:\n:e\n(f => (x => f (v => (x x) v)) (x => f (v => (x x) v))) (f => x => f)\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.+1: \t(f => (x => f (v => (x x) v)) (x => f (v => (x x) v))) (f => x => f)\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error | anything -> anything -> anything -> 'a\n//│   where\n//│     'a :> forall 'a. anything -> 'a\n\nres 1 2\n//│ res: error | anything -> 'a\n//│   where\n//│     'a :> forall 'a. anything -> 'a\n\n\nlet rec trutru = g => trutru (g true)\n//│ trutru: 'a -> nothing\n//│   where\n//│     'a <: true -> 'a\n\ni => if ((i i) true) then true else true\n//│ res: ('a -> true -> bool & 'a) -> true\n// ^ for: λi. if ((i i) true) then true else true,\n//    Dolan's thesis says MLsub infers: (α → ((bool → bool) ⊓ α)) → bool\n//    which does seem equivalent, despite being quite syntactically different\n\n\n\n// --- let-poly --- //\n\n\nlet f = x => x; {a: f 0, b: f true}\n//│ f: 'a -> 'a\n//│ res: {a: 0, b: true}\n\ny => (let f = x => x; {a: f y, b: f true})\n//│ res: 'a -> {a: 'a, b: true}\n\ny => (let f = x => y x; {a: f 0, b: f true})\n//│ res: ((0 | true) -> 'a) -> {a: 'a, b: 'a}\n\ny => (let f = x => x y; {a: f (z => z), b: f (z => true)})\n//│ res: 'a -> {a: 'a, b: true}\n\ny => (let f = x => x y; {a: f (z => z), b: f (z => succ z)})\n//│ res: (int & 'a) -> {a: 'a, b: int}\n\n\n\n// --- recursion --- //\n\n\nlet rec f = x => f x.u\n//│ f: 'a -> nothing\n//│   where\n//│     'a <: {u: 'a}\n\n\n// from https://www.cl.cam.ac.uk/~sd601/mlsub/\nlet rec recursive_monster = x => { thing: x, self: recursive_monster x }\n//│ recursive_monster: 'a -> 'b\n//│   where\n//│     'b :> {self: 'b, thing: 'a}\n\n\n\n// --- random --- //\n\n\n(let rec x = {a: x, b: x}; x)\n//│ res: 'x\n//│   where\n//│     'x :> {a: 'x, b: 'x}\n\n(let rec x = v => {a: x v, b: x v}; x)\n//│ res: anything -> 'a\n//│   where\n//│     'a :> {a: 'a, b: 'a}\n\n:e\nlet rec x = (let rec y = {u: y, v: (x y)}; 0); 0\n//│ ╔══[ERROR] Type mismatch in binding of block of statements:\n//│ ║  l.+1: \tlet rec x = (let rec y = {u: y, v: (x y)}; 0); 0\n//│ ║        \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \tlet rec x = (let rec y = {u: y, v: (x y)}; 0); 0\n//│ ║        \t                                           ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.+1: \tlet rec x = (let rec y = {u: y, v: (x y)}; 0); 0\n//│ ║        \t                                    ^^^\n//│ ╟── from reference:\n//│ ║  l.+1: \tlet rec x = (let rec y = {u: y, v: (x y)}; 0); 0\n//│ ╙──      \t                                    ^\n//│ x: 0\n//│ res: 0\n\n(x => (let y = (x x); 0))\n//│ res: ('a -> anything & 'a) -> 0\n\n// TODO simplify more?\n(let rec x = (y => (y (x x))); x)\n//│ res: 'a -> 'b\n//│   where\n//│     'a <: 'b -> 'b\n//│     'b <: 'a\n\n:e // * Note: this works with precise-rec-typing (see below)\nres (z => (z, z))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tres (z => (z, z))\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── tuple of type `(?a, ?a,)` is not a function\n//│ ║  l.+1: \tres (z => (z, z))\n//│ ║        \t           ^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.318: \t(let rec x = (y => (y (x x))); x)\n//│ ╙──       \t                    ^^^^^^^\n//│ res: error | 'a\n//│   where\n//│     'a :> ('a, 'a,)\n\n:precise-rec-typing\n(let rec x = (y => (y (x x))); x)\n//│ res: (nothing -> 'a) -> 'a\n\nres (z => (z, z))\n//│ res: (nothing, nothing,)\n\n\nnext => 0\n//│ res: anything -> 0\n\n((x => (x x)) (x => x))\n//│ res: 'a -> 'a\n\n(let rec x = (y => (x (y y))); x)\n//│ res: 'a -> nothing\n//│   where\n//│     'a <: 'a -> 'a\n\nx => (y => (x (y y)))\n//│ res: ('a -> 'b) -> ('c -> 'a & 'c) -> 'b\n\n(let rec x = (let y = (x x); (z => z)); x)\n//│ res: 'a -> 'a\n//│   where\n//│     'a :> 'a -> 'a\n\n(let rec x = (y => (let z = (x x); y)); x)\n//│ res: 'a -> 'a\n//│   where\n//│     'a :> 'a -> 'a\n\n(let rec x = (y => {u: y, v: (x x)}); x)\n//│ res: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│     'b :> {u: 'a, v: 'b}\n\n(let rec x = (y => {u: (x x), v: y}); x)\n//│ res: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│     'b :> {u: 'b, v: 'a}\n\n(let rec x = (y => (let z = (y x); y)); x)\n//│ res: 'x\n//│   where\n//│     'x :> 'a -> 'a\n//│     'a <: 'x -> anything\n\n(x => (let y = (x x.v); 0))\n//│ res: ('v -> anything & {v: 'v}) -> 0\n\nlet rec x = (let y = (x x); (z => z)); (x (y => y.u)) // [test:T1]\n//│ x: 'a -> 'a\n//│   where\n//│     'a :> 'a -> 'a\n//│ res: ({u: 'u} & 'a) -> ('u | 'a) | 'b\n//│   where\n//│     'a :> forall 'u. ({u: 'u} & 'a) -> ('a | 'u)\n//│        <: 'b\n\n:ns\nlet rec x = (let y = (x x); (z => z))\n//│ x: forall 'x 'a 'b. 'x\n//│   where\n//│     'x := 'b -> 'b\n//│     'b :> 'b -> 'b\n//│        <: 'a\n//│     'a :> 'b -> 'b\n\n\n\n// Converges under normal-order reduction, but type inference follows more of an applicative order:\n\n:e\n(w => x => x) ((y => y y) (y => y y))\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.+1: \t(w => x => x) ((y => y y) (y => y y))\n//│ ║        \t               ^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: 'a -> 'a\n\n\n\n// * === With Constrained Types ===\n\n:DontDistributeForalls\n:ConstrainedTypes\n\n\n// * Z combinator:\n// :e // Works thanks to inconsistent constrained types...\n(f => (x => f (v => (x x) v)) (x => f (v => (x x) v)))\n//│ res: ((forall 'a 'b. 'a -> 'b\n//│   where\n//│     forall 'c 'd. 'c -> 'd\n//│       where\n//│         'e <: (forall 'f 'g. 'f -> 'g\n//│           where\n//│             'c <: 'c -> 'f -> 'g) -> 'd <: (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'e <: (forall 'f 'g. 'f -> 'g\n//│           where\n//│             'c <: 'c -> 'f -> 'g) -> 'd) -> 'a -> 'b) -> 'h & 'e) -> 'h\n\n// * Function that takes arbitrarily many arguments:\n// :e // Works thanks to inconsistent constrained types...\n(f => (x => f (v => (x x) v)) (x => f (v => (x x) v))) (f => x => f)\n//│ res: anything -> (forall 'a 'b. 'a -> 'b\n//│   where\n//│     forall 'c 'd. 'c -> 'd\n//│       where\n//│         forall 'e. 'e -> anything -> 'e <: (forall 'f 'g. 'f -> 'g\n//│           where\n//│             'c <: 'c -> 'f -> 'g) -> 'd <: (forall 'c 'd. 'c -> 'd\n//│       where\n//│         forall 'e. 'e -> anything -> 'e <: (forall 'f 'g. 'f -> 'g\n//│           where\n//│             'c <: 'c -> 'f -> 'g) -> 'd) -> 'a -> 'b)\n\n\n\n\n:NoCycleCheck\n\n// Exceeds recursion depth limit:\n// :e\n// (w => x => x) ((y => y y) (y => y y))\n\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Simplesub2.fun",
    "content": "// Tests ported from Simplesub\n\n\n\n// --- mlsub --- //\n\n\nlet id = x => x\n//│ id: 'a -> 'a\n\nlet twice = f => x => f (f x)\n//│ twice: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n\nlet object1 = { x: 42, y: id }\n//│ object1: {x: 42, y: forall 'a. 'a -> 'a}\n\nlet object2 = { x: 17, y: false }\n//│ object2: {x: 17, y: false}\n\nlet pick_an_object = b =>\n  if b then object1 else object2\n//│ pick_an_object: bool -> {x: 17 | 42, y: forall 'a. false | 'a -> 'a}\n\nlet rec recursive_monster = x =>\n  { thing: x, self: recursive_monster x }\n//│ recursive_monster: 'a -> 'b\n//│   where\n//│     'b :> {self: 'b, thing: 'a}\n\n\n\n// --- top-level-polymorphism --- //\n\n\nlet id = x => x\n//│ id: 'a -> 'a\n\nlet ab = {u: id 0, v: id true}\n//│ ab: {u: 0, v: true}\n\n\n\n// --- rec-producer-consumer --- //\n\n\nlet rec produce = arg => { head: arg, tail: produce (succ arg) }\nlet rec consume = strm => add strm.head (consume strm.tail)\n//│ produce: int -> 'a\n//│   where\n//│     'a :> {head: int, tail: 'a}\n//│ consume: 'a -> int\n//│   where\n//│     'a <: {head: int, tail: 'a}\n\nlet codata = produce 42\nlet res = consume codata\n//│ codata: 'a\n//│   where\n//│     'a :> {head: int, tail: 'a}\n//│ res: int\n\nlet rec codata2 = { head: 0, tail: { head: 1, tail: codata2 } }\nlet res = consume codata2\n//│ codata2: 'codata2\n//│   where\n//│     'codata2 :> {head: 0, tail: {head: 1, tail: 'codata2}}\n//│ res: int\n\n// TODO better parser error\n:pe\nlet rec produce3 = b => { head: 123, tail: if b then codata else codata2 }\n//│ /!\\ Parse error: Expected let binding:1:1, found \"let rec pr\" at l.71:1: let rec produce3 = b => { head: 123, tail: if b then codata else codata2 }\n\nlet rec produce3 = b => { head: 123, tail: (if b then codata else codata2) }\nlet res = x => consume (produce3 x)\n//│ produce3: bool -> {head: 123, tail: forall 'codata2 'a. 'codata2 | 'a}\n//│   where\n//│     'a :> {head: int, tail: 'a}\n//│     'codata2 :> {head: 0, tail: {head: 1, tail: 'codata2}}\n//│ res: bool -> int\n\nlet consume2 =\n  let rec go = strm => add strm.head (add strm.tail.head (go strm.tail.tail))\n  strm => add strm.head (go strm.tail)\n  // go\n// let rec consume2 = strm => add strm.head (add strm.tail.head (consume2 strm.tail.tail))\nlet res = consume2 codata2\n//│ consume2: 'a -> int\n//│   where\n//│     'a <: {head: int, tail: 'a}\n//│ res: int\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Slashes.fun",
    "content": "\nsucc / 1\nsucc / succ / 1\n//│ res: int\n//│ res: int\n\nlet foo = f => f 1\n//│ foo: (1 -> 'a) -> 'a\n\nfoo / x => x\n//│ res: 1\n\nfoo / x => succ x\n//│ res: int\n\nx => succ / x + 1\n//│ res: int -> int\n\nx => succ / succ / x + 1\n//│ res: int -> int\n\n:p\nfoo / x => succ / succ / x\n//│ Parsed: foo(...((...x) => succ(...(succ(...x)))));\n//│ Desugared: foo(...((...x) => succ(...(succ(...x)))))\n//│ AST: App(Var(foo),Lam(Var(x),App(Var(succ),App(Var(succ),Var(x)))))\n//│ res: int\n\n:e\nfoo / foo / x => succ / succ / x\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.30: \tfoo / foo / x => succ / succ / x\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `int` is not a function\n//│ ║  l.30: \tfoo / foo / x => succ / succ / x\n//│ ║        \t                 ^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `1 -> ?a`\n//│ ║  l.30: \tfoo / foo / x => succ / succ / x\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.7: \tlet foo = f => f 1\n//│ ║       \t               ^^^\n//│ ╟── from reference:\n//│ ║  l.7: \tlet foo = f => f 1\n//│ ╙──     \t               ^\n//│ res: error\n\n:e\nfoo / foo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.49: \tfoo / foo\n//│ ║        \t^^^^^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.7: \tlet foo = f => f 1\n//│ ║       \t                 ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.7: \tlet foo = f => f 1\n//│ ║       \t               ^^^\n//│ ╟── from reference:\n//│ ║  l.7: \tlet foo = f => f 1\n//│ ╙──     \t               ^\n//│ res: error\n"
  },
  {
    "path": "shared/src/test/diff/basics/Tuples.fun",
    "content": "\nlet t3 = 1, 2, 3\nlet t3 = 1, 2, 3,\nlet t2 = 1, 2,\nlet t1 = 1,\nlet t0 = ()\n//│ t3: (1, 2, 3,)\n//│ t3: (1, 2, 3,)\n//│ t2: (1, 2,)\n//│ t1: (1,)\n//│ t0: ()\n\nlet t = 1, y: 2, 3\nlet t = x: 1, y: 2, z: 3\n//│ t: (1, y: 2, 3,)\n//│ t: (x: 1, y: 2, z: 3,)\n\n(1, true, \"hey\").1\n(1, true, \"hey\").2\n//│ res: true\n//│ res: \"hey\"\n\n:e\n(1, true, \"hey\").3\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.24: \t(1, true, \"hey\").3\n//│ ║        \t                ^^\n//│ ╟── tuple of type `{0: 1, 1: true, 2: \"hey\"}` does not have field '3'\n//│ ║  l.24: \t(1, true, \"hey\").3\n//│ ║        \t ^^^^^^^^^^^^^^\n//│ ╟── but it flows into receiver with expected type `{3: ?a}`\n//│ ║  l.24: \t(1, true, \"hey\").3\n//│ ╙──      \t^^^^^^^^^^^^^^^^\n//│ res: error\n\n(1, true, \"hey\").1\n//│ res: true\n\n:w\nlet not-tup = (\n  1\n  2\n)\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.41: \t  1\n//│ ╙──      \t  ^\n//│ not-tup: 2\n\n:w\nlet tup = (\n  1,\n  2\n)\n//│ ╔══[WARNING] Previous field definitions are discarded by this returned expression.\n//│ ║  l.52: \t  2\n//│ ╙──      \t  ^\n//│ tup: 2\n\n:w\nlet tup =\n  1,\n  2,\n  3\n//│ ╔══[WARNING] Previous field definitions are discarded by this returned expression.\n//│ ║  l.63: \t  3\n//│ ╙──      \t  ^\n//│ tup: 3\n\nlet tup =\n  1,\n  2,\n  3,\n//│ tup: (1, 2, 3,)\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Twice.fun",
    "content": "\nlet twice f x = f / f x\n//│ twice: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n// Note: the pretty-printed type of `twice` *used to be* simplified to ('a -> ('a & 'b)) -> 'a -> 'b\n//    (another equivalent simplification is ('a | 'b -> 'a) -> 'b -> 'a);\n//    this simplification lost some information in the context of first-class polymorphism\n//    because function types effectively become non-mergeable without losing precsion...\n// (Also see this HN thread: https://news.ycombinator.com/item?id=13783237)\n\ntwice(x => x + 1)\n//│ res: int -> int\n\ntwice twice\n//│ res: ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c\n\nlet f = x => 1, x\n//│ f: 'a -> (1, 'a,)\n\n// Note: now that we instantiate during constraint solving instead of on variable reference,\n//    we get the more useful type: 'a -> (1, (1, 'a,),).\n//    Previously, we were getting: 'a -> ((1, 'c | 'b | 'a,) as 'b)\ntwice f\n//│ res: 'a -> (1, (1, 'a,),)\n\ntwice / x => x, x\n//│ res: 'a -> (('a, 'a,), ('a, 'a,),)\n\nlet one = twice (o => o.x) { x: { x: 1 } }\n//│ one: 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/Unions.fun",
    "content": "\n\nlet f(x: 0 | 1) = x\n//│ f: (x: 'a & (0 | 1),) -> 'a\n\nlet f(x: 0 | 1) = succ x\n//│ f: (x: 0 | 1,) -> int\n\nlet f(x) = x as 0 | 1\n//│ f: (0 | 1) -> (0 | 1)\n\nf 1\nf 0\nf(0 as 0 | 1)\n//│ res: 0 | 1\n//│ res: 0 | 1\n//│ res: 0 | 1\n\n:e\nf 3\nf (0 as 1 | 3)\nf (0 as 0 | 3)\nf (0 as 3 | 4)\nf (0 as Int)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.20: \tf 3\n//│ ║        \t^^^\n//│ ╟── integer literal of type `3` does not match type `0 | 1`\n//│ ║  l.20: \tf 3\n//│ ║        \t  ^\n//│ ╟── Note: constraint arises from type union:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ║       \t                ^^^^^\n//│ ╟── from reference:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ╙──     \t           ^\n//│ res: 0 | 1 | error\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.21: \tf (0 as 1 | 3)\n//│ ║        \t   ^^^^^^^^^^\n//│ ╟── integer literal of type `0` does not match type `1 | 3`\n//│ ║  l.21: \tf (0 as 1 | 3)\n//│ ║        \t   ^\n//│ ╟── Note: constraint arises from type union:\n//│ ║  l.21: \tf (0 as 1 | 3)\n//│ ╙──      \t        ^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.21: \tf (0 as 1 | 3)\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `3` does not match type `0 | 1`\n//│ ║  l.21: \tf (0 as 1 | 3)\n//│ ║        \t            ^\n//│ ╟── but it flows into type union with expected type `0 | 1`\n//│ ║  l.21: \tf (0 as 1 | 3)\n//│ ║        \t        ^^^^^\n//│ ╟── Note: constraint arises from type union:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ║       \t                ^^^^^\n//│ ╟── from reference:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ╙──     \t           ^\n//│ res: 0 | 1 | error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.22: \tf (0 as 0 | 3)\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `3` does not match type `0 | 1`\n//│ ║  l.22: \tf (0 as 0 | 3)\n//│ ║        \t            ^\n//│ ╟── but it flows into type union with expected type `0 | 1`\n//│ ║  l.22: \tf (0 as 0 | 3)\n//│ ║        \t        ^^^^^\n//│ ╟── Note: constraint arises from type union:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ║       \t                ^^^^^\n//│ ╟── from reference:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ╙──     \t           ^\n//│ res: 0 | 1 | error\n//│ ╔══[ERROR] Type mismatch in 'as' binding:\n//│ ║  l.23: \tf (0 as 3 | 4)\n//│ ║        \t   ^^^^^^^^^^\n//│ ╟── integer literal of type `0` does not match type `3 | 4`\n//│ ║  l.23: \tf (0 as 3 | 4)\n//│ ║        \t   ^\n//│ ╟── Note: constraint arises from type union:\n//│ ║  l.23: \tf (0 as 3 | 4)\n//│ ╙──      \t        ^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.23: \tf (0 as 3 | 4)\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `3` does not match type `0 | 1`\n//│ ║  l.23: \tf (0 as 3 | 4)\n//│ ║        \t        ^\n//│ ╟── but it flows into type union with expected type `0 | 1`\n//│ ║  l.23: \tf (0 as 3 | 4)\n//│ ║        \t        ^^^^^\n//│ ╟── Note: constraint arises from type union:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ║       \t                ^^^^^\n//│ ╟── from reference:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ╙──     \t           ^\n//│ res: 0 | 1 | error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.24: \tf (0 as Int)\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── reference of type `int` does not match type `0 | 1`\n//│ ║  l.24: \tf (0 as Int)\n//│ ║        \t        ^^^\n//│ ╟── but it flows into argument with expected type `0 | 1`\n//│ ║  l.24: \tf (0 as Int)\n//│ ║        \t  ^^^^^^^^^^\n//│ ╟── Note: constraint arises from type union:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ║       \t                ^^^^^\n//│ ╟── from reference:\n//│ ║  l.9: \tlet f(x) = x as 0 | 1\n//│ ╙──     \t           ^\n//│ res: 0 | 1 | error\n\nlet g(x: int) = succ x\ng 0\ng (0 as 0 | 1)\nlet h = y => g(y as 0 | 1)\nh(0)\n//│ g: (x: int,) -> int\n//│ res: int\n//│ res: int\n//│ h: (0 | 1) -> int\n//│ res: int\n\nlet foo(r: { v: 0 } | { v: 1 }) = if r.v < 1 then r.v else 2\n//│ foo: (r: {v: 'a & (0 | 1)},) -> (2 | 'a)\n\nfoo({ v: 0 })\nfoo({ v: 1 })\n//│ res: 0 | 2\n//│ res: 1 | 2\n\nx => foo(x)\n//│ res: (r: {v: 'a & (0 | 1)},) -> (2 | 'a)\n\nx => foo { v: x }\n//│ res: ('a & (0 | 1)) -> (2 | 'a)\n\n\n// Notice that in MLscript, `(0, 0) | (1, 1)` is equivalent to `(0 | 1, 0 | 1)`\nlet bar(r: (0, 0) | (1, 1)) = if r.0 < 1 then r.0 else r.1\n//│ bar: (r: ('a & (0 | 1), 'a & (0 | 1),),) -> 'a\n\nbar(0, 1)\n//│ res: 0 | 1\n\n:e\nbar(2, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.155: \tbar(2, 2)\n//│ ║         \t^^^^^^^^^\n//│ ╟── integer literal of type `2` does not match type `0 | 1`\n//│ ║  l.155: \tbar(2, 2)\n//│ ╙──       \t    ^\n//│ res: 2 | error\n\nbar(0, 0)\nbar(1, 1)\nbar(0, _)\nbar(_, 1)\n//│ res: 0\n//│ res: 1\n//│ res: 0\n//│ res: 1\n\nlet f x = bar(x, x)\n//│ f: ('a & (0 | 1)) -> 'a\n\nf 0\nf 1\n//│ res: 0\n//│ res: 1\n\n:e\nf 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.182: \tf 2\n//│ ║         \t^^^\n//│ ╟── integer literal of type `2` does not match type `0 | 1`\n//│ ║  l.182: \tf 2\n//│ ║         \t  ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.173: \tlet f x = bar(x, x)\n//│ ╙──       \t              ^\n//│ res: 2 | error\n\nx => bar(1, x)\nx => bar(x, 0)\n//│ res: ('a & (0 | 1)) -> (1 | 'a)\n//│ res: ('a & (0 | 1)) -> (0 | 'a)\n\nbar(_, _)\n(x, y) => bar(x, y)\n//│ res: nothing\n//│ res: ('a & (0 | 1), 'a & (0 | 1),) -> 'a\n\n// ^ TODO allow explicit request for inferring an overloaded type in case of ambiguities\n\nx => bar(bar(0, x), 0)\nx => bar(bar(x, x), 0)\nx => bar(bar(0, x), x)\nx => bar(bar(x, x), 0)\n//│ res: ('a & (0 | 1)) -> (0 | 'a)\n//│ res: ('a & (0 | 1)) -> (0 | 'a)\n//│ res: ('a & (0 | 1)) -> (0 | 'a)\n//│ res: ('a & (0 | 1)) -> (0 | 'a)\n\nx => bar(bar(x, 1), 0)\n(x, y) => bar(bar(x, y), x)\n//│ res: ('a & (0 | 1)) -> (0 | 1 | 'a)\n//│ res: ('a & (0 | 1), 'a & (0 | 1),) -> 'a\n\n(x, y) => bar(bar(x, y), 0)\n//│ res: ('a & (0 | 1), 'a & (0 | 1),) -> (0 | 'a)\n\n\nlet baz(r: (0, 0) | _) = if r.0 < 1 then r.0 else r.1\n//│ baz: (r: {0: number & 'a, 1: 'a},) -> 'a\n\n:e\nbaz(0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.228: \tbaz(0)\n//│ ║         \t^^^^^^\n//│ ╟── integer literal of type `0` does not have field '1'\n//│ ║  l.228: \tbaz(0)\n//│ ║         \t    ^\n//│ ╟── but it flows into argument with expected type `{1: ?a}`\n//│ ║  l.228: \tbaz(0)\n//│ ║         \t   ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.224: \tlet baz(r: (0, 0) | _) = if r.0 < 1 then r.0 else r.1\n//│ ║         \t                                                   ^^\n//│ ╟── from binding:\n//│ ║  l.224: \tlet baz(r: (0, 0) | _) = if r.0 < 1 then r.0 else r.1\n//│ ╙──       \t        ^^^^^^^^^^^^^\n//│ res: error\n\nbaz(0, 0)\nbaz(0, 1)\nbaz(1, 1)\n//│ res: 0\n//│ res: 0 | 1\n//│ res: 1\n\nx => baz(x, 0)\nx => baz(0, x)\nx => baz(x, x)\n(x, y) => baz(x, y)\n//│ res: (number & 'a) -> (0 | 'a)\n//│ res: 'a -> (0 | 'a)\n//│ res: (number & 'a) -> 'a\n//│ res: (number & 'a, 'a,) -> 'a\n\n\nlet baz(r: (0, 0) | (1, _)) = if r.0 < 1 then r.0 else r.1\n//│ baz: (r: ('a & (0 | 1), 'a,),) -> 'a\n\n:e\nbaz(0)\nbaz(0, 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.267: \tbaz(0)\n//│ ║         \t^^^^^^\n//│ ╟── integer literal of type `0` does not have field '1'\n//│ ║  l.267: \tbaz(0)\n//│ ║         \t    ^\n//│ ╟── but it flows into argument with expected type `{1: ?a}`\n//│ ║  l.267: \tbaz(0)\n//│ ║         \t   ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.263: \tlet baz(r: (0, 0) | (1, _)) = if r.0 < 1 then r.0 else r.1\n//│ ║         \t                                                        ^^\n//│ ╟── from binding:\n//│ ║  l.263: \tlet baz(r: (0, 0) | (1, _)) = if r.0 < 1 then r.0 else r.1\n//│ ╙──       \t        ^^^^^^^^^^^^^^^^^^\n//│ res: error\n//│ res: 0 | 1\n\nbaz(0, 0)\nbaz(1, 1)\nx => baz(0, x)\nx => baz(1, x)\nx => baz(x, 1)\n//│ res: 0\n//│ res: 1\n//│ res: 'a -> (0 | 'a)\n//│ res: 'a -> (1 | 'a)\n//│ res: ('a & (0 | 1)) -> (1 | 'a)\n\nx => baz(x, 0)\nx => baz(x, x)\n(x, y) => baz(x, y)\n//│ res: ('a & (0 | 1)) -> (0 | 'a)\n//│ res: ('a & (0 | 1)) -> 'a\n//│ res: ('a & (0 | 1), 'a,) -> 'a\n\n"
  },
  {
    "path": "shared/src/test/diff/basics/VerboseErrors.fun",
    "content": "\n:v // Note: removing this will mean not showing parameter provs in downstream errors\nlet f = x =>\n  log / succ x.prop\n  x.prop\nlet h = y =>\n  succ / f y\nlet mkArg = a => {prop: a}\n//│ f: {prop: int & 'prop} -> 'prop\n//│ h: {prop: int} -> int\n//│ mkArg: 'a -> {prop: 'a}\n\n:v\n:e\nh / mkArg false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.15: \th / mkArg false\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.15: \th / mkArg false\n//│ ║        \t          ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.7: \t  succ / f y\n//│ ║       \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.5: \t  x.prop\n//│ ╙──     \t   ^^^^^\n//│ res: error | int\n\n:v\n:e\n(x => succ x) false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.32: \t(x => succ x) false\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.32: \t(x => succ x) false\n//│ ║        \t              ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.32: \t(x => succ x) false\n//│ ║        \t           ^\n//│ ╟── from variable:\n//│ ║  l.32: \t(x => succ x) false\n//│ ╙──      \t ^\n//│ res: error | int\n\n\nlet f = x =>\n  log / succ x.prop\n  x.prop\nlet arg = {prop: not true}\nlet arg2 = {fld: arg}\nlet i = y =>\n  succ / f y.fld\nlet test = x => y => if x.prop then i x else y\n//│ f: {prop: int & 'prop} -> 'prop\n//│ arg: {prop: bool}\n//│ arg2: {fld: {prop: bool}}\n//│ i: {fld: {prop: int}} -> int\n//│ test: {fld: {prop: int}, prop: bool} -> 'a -> (int | 'a)\n\n:e\n:verbose\ntest arg2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.64: \ttest arg2\n//│ ║        \t^^^^^^^^^\n//│ ╟── application of type `bool` is not an instance of type `int`\n//│ ║  l.51: \tlet arg = {prop: not true}\n//│ ║        \t                 ^^^^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.54: \t  succ / f y.fld\n//│ ║        \t         ^^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.50: \t  x.prop\n//│ ╙──      \t   ^^^^^\n//│ res: error | 'a -> (int | 'a)\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/AuxiliaryConstructors.mls",
    "content": ":NewDefs\n\n:js\nclass A(x: Int) {}\n//│ class A(x: Int)\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #x;\n//│         constructor(x) {\n//│           this.#x = x;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       };\n//│       this.#A = ((x) => Object.freeze(new A(x)));\n//│       this.#A.class = A;\n//│       this.#A.unapply = A.unapply;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.A = typing_unit.A;\n//│ // End of generated code\n\n:js\nclass B {}\n//│ class B {\n//│   constructor()\n//│ }\n//│ // Prelude\n//│ class TypingUnit1 {\n//│   #B;\n//│   constructor() {\n//│   }\n//│   get B() {\n//│     const qualifier = this;\n//│     if (this.#B === undefined) {\n//│       class B {};\n//│       this.#B = B;\n//│     }\n//│     return this.#B;\n//│   }\n//│ }\n//│ const typing_unit1 = new TypingUnit1;\n//│ globalThis.B = typing_unit1.B;\n//│ // End of generated code\n\nnew B\n//│ B\n//│ res\n//│     = B {}\n\n:e\nB()\n//│ ╔══[ERROR] Construction of unparameterized class B should use the `new` keyword\n//│ ║  l.65: \tB()\n//│ ╙──      \t^\n//│ B\n//│ res\n//│ Runtime error:\n//│   TypeError: Class constructor B cannot be invoked without 'new'\n\nabstract class C\n//│ abstract class C\n\n:e\nnew C\n//│ ╔══[ERROR] Class C is abstract and cannot be instantiated\n//│ ║  l.78: \tnew C\n//│ ╙──      \t    ^\n//│ C\n//│ res\n//│     = C {}\n\n:e\nC()\n//│ ╔══[ERROR] Class C is abstract and cannot be instantiated\n//│ ║  l.87: \tC()\n//│ ╙──      \t^\n//│ ╔══[ERROR] Class C cannot be instantiated as it exposes no constructor\n//│ ║  l.87: \tC()\n//│ ╙──      \t^\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: Class constructor C cannot be invoked without 'new'\n\n:js\nclass C {\n  constructor(x: Int) { log(x) }\n}\n//│ class C {\n//│   constructor(x: Int)\n//│ }\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ class TypingUnit7 {\n//│   #C;\n//│   constructor() {\n//│   }\n//│   get C() {\n//│     const qualifier = this;\n//│     if (this.#C === undefined) {\n//│       class C {\n//│         constructor(x) {\n//│           log(x);\n//│         }\n//│       };\n//│       this.#C = C;\n//│     }\n//│     return this.#C;\n//│   }\n//│ }\n//│ const typing_unit7 = new TypingUnit7;\n//│ globalThis.C = typing_unit7.C;\n//│ // End of generated code\n\n:e\nlet c = new C()\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.132: \tlet c = new C()\n//│ ║         \t        ^^^^^^^\n//│ ╟── argument list of type `[]` does not match type `[x: Int]`\n//│ ║  l.132: \tlet c = new C()\n//│ ╙──       \t             ^^\n//│ let c: C | error\n//│ c\n//│   = C {}\n//│ // Output\n//│ undefined\n\nlet c = new C(1)\n//│ let c: C\n//│ c\n//│   = C {}\n//│ // Output\n//│ 1\n\n:js\nclass D(val x: Int) {\n  constructor(y: Int) {\n    x = y + 1\n  }\n  log(x)\n}\n//│ class D(x: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ // Prelude\n//│ class TypingUnit10 {\n//│   #D;\n//│   constructor() {\n//│   }\n//│   get D() {\n//│     const qualifier = this;\n//│     if (this.#D === undefined) {\n//│       class D {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         constructor(y) {\n//│           this.#x = y + 1;\n//│           const x = this.#x;\n//│           log(x);\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       };\n//│       this.#D = ((y) => Object.freeze(new D(y)));\n//│       this.#D.class = D;\n//│       this.#D.unapply = D.unapply;\n//│     }\n//│     return this.#D;\n//│   }\n//│ }\n//│ const typing_unit10 = new TypingUnit10;\n//│ globalThis.D = typing_unit10.D;\n//│ // End of generated code\n\nlet dd = new D(41)\ndd.x\n//│ let dd: D\n//│ Int\n//│ dd\n//│    = D {}\n//│ // Output\n//│ 42\n//│ res\n//│     = 42\n\nlet dd = new D(41)\ndd.x\n//│ let dd: D\n//│ Int\n//│ dd\n//│    = D {}\n//│ // Output\n//│ 42\n//│ res\n//│     = 42\n\n:pe\nclass E {\n  constructor(x: Int)\n  constructor(y: Int)\n}\n//│ ╔══[PARSE ERROR] A class may have at most one explicit constructor\n//│ ║  l.217: \tclass E {\n//│ ╙──       \t^^^^^\n//│ class E {\n//│   constructor(x: Int)\n//│ }\n\n:e\nconstructor(x: Int)\n//│ ╔══[ERROR] Illegal position for this constructor statement.\n//│ ║  l.229: \tconstructor(x: Int)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^\n//│ \n//│ Code generation encountered an error:\n//│   unexpected constructor.\n\n:js\nclass F(x: Int) extends C(x + 1) {}\nclass G extends C(2) {}\nclass H extends B {}\n//│ class F(x: Int) extends C\n//│ class G extends C {\n//│   constructor()\n//│ }\n//│ class H extends B {\n//│   constructor()\n//│ }\n//│ // Prelude\n//│ class TypingUnit14 {\n//│   #F;\n//│   #G;\n//│   #H;\n//│   constructor() {\n//│   }\n//│   get F() {\n//│     const qualifier = this;\n//│     if (this.#F === undefined) {\n//│       class F extends C {\n//│         #x;\n//│         constructor(x) {\n//│           super(x + 1);\n//│           this.#x = x;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       };\n//│       this.#F = ((x) => Object.freeze(new F(x)));\n//│       this.#F.class = F;\n//│       this.#F.unapply = F.unapply;\n//│     }\n//│     return this.#F;\n//│   }\n//│   get G() {\n//│     const qualifier = this;\n//│     if (this.#G === undefined) {\n//│       class G extends C {\n//│         constructor() {\n//│           super(2);\n//│         }\n//│       };\n//│       this.#G = G;\n//│     }\n//│     return this.#G;\n//│   }\n//│   get H() {\n//│     const qualifier = this;\n//│     if (this.#H === undefined) {\n//│       class H extends B {\n//│         constructor() {\n//│           super();\n//│         }\n//│       };\n//│       this.#H = H;\n//│     }\n//│     return this.#H;\n//│   }\n//│ }\n//│ const typing_unit14 = new TypingUnit14;\n//│ globalThis.F = typing_unit14.F;\n//│ globalThis.G = typing_unit14.G;\n//│ globalThis.H = typing_unit14.H;\n//│ // End of generated code\n\n:js\nfun f(c) =\n  if c is\n    F(x) then x\n    G() then 2\n    _ then 0\n//│ fun f: Object -> Int\n//│ // Prelude\n//│ class TypingUnit15 {}\n//│ const typing_unit15 = new TypingUnit15;\n//│ // Query 1\n//│ globalThis.f = function f(c) {\n//│   return ((() => {\n//│     let a;\n//│     return a = c, a instanceof F.class ? ((ucs$args_c$F) => ((x) => x)(ucs$args_c$F[0]))(F.unapply(c)) : a instanceof G ? 2 : 0;\n//│   })());\n//│ };\n//│ // End of generated code\n\nf(F(12))\nf(new G())\n//│ Int\n//│ res\n//│     = 12\n//│ // Output\n//│ 13\n//│ res\n//│     = 2\n//│ // Output\n//│ 2\n\n:js\nmodule I {\n  class J {\n    constructor(x: Int)\n  }\n  module K {\n    class L extends J(0)\n  }\n}\n//│ module I {\n//│   class J {\n//│     constructor(x: Int)\n//│   }\n//│   module K {\n//│     class L extends J {\n//│       constructor()\n//│     }\n//│   }\n//│ }\n//│ // Prelude\n//│ class TypingUnit17 {\n//│   #I;\n//│   constructor() {\n//│   }\n//│   get I() {\n//│     const qualifier = this;\n//│     if (this.#I === undefined) {\n//│       class I {\n//│         #J;\n//│         #K;\n//│         constructor() {\n//│         }\n//│         get K() {\n//│           const qualifier1 = this;\n//│           if (this.#K === undefined) {\n//│             class K {\n//│               #L;\n//│               constructor() {\n//│               }\n//│               get L() {\n//│                 const qualifier2 = this;\n//│                 if (this.#L === undefined) {\n//│                   class L extends qualifier1.J {\n//│                     constructor() {\n//│                       super(0);\n//│                     }\n//│                   };\n//│                   this.#L = L;\n//│                 }\n//│                 return this.#L;\n//│               }\n//│             }\n//│             this.#K = new K();\n//│             this.#K.class = K;\n//│           }\n//│           return this.#K;\n//│         }\n//│         get J() {\n//│           const qualifier1 = this;\n//│           if (this.#J === undefined) {\n//│             class J {};\n//│             this.#J = J;\n//│           }\n//│           return this.#J;\n//│         }\n//│       }\n//│       this.#I = new I();\n//│       this.#I.class = I;\n//│     }\n//│     return this.#I;\n//│   }\n//│ }\n//│ const typing_unit17 = new TypingUnit17;\n//│ globalThis.I = typing_unit17.I;\n//│ // End of generated code\n\n:js\nfun g(x: Int) =\n  class L(y: Int) {\n    constructor(z: Int) {\n      y = z + 1\n    }\n    fun ll = x + y\n  }\n  x => new L(x)\n//│ fun g: (x: Int) -> Int -> L\n//│ // Prelude\n//│ class TypingUnit18 {}\n//│ const typing_unit18 = new TypingUnit18;\n//│ // Query 1\n//│ globalThis.g = function g(x) {\n//│   return ((() => {\n//│     const L = (() => {\n//│       class L {\n//│         #y;\n//│         constructor(z) {\n//│           this.#y = z + 1;\n//│           const y = this.#y;\n//│         }\n//│         get ll() {\n//│           const y = this.#y;\n//│           return x + y;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#y];\n//│         }\n//│       }\n//│       let ctor;\n//│       ctor = ((z) => new L(z));\n//│       ctor.class = L;\n//│       return ctor;\n//│     })();\n//│     return (x) => new L.class(x);\n//│   })());\n//│ };\n//│ // End of generated code\n\n:js\nlet m = g(1)\nlet n = m(2)\nn.ll\n//│ let m: Int -> L\n//│ let n: L\n//│ Int\n//│ // Prelude\n//│ class TypingUnit19 {}\n//│ const typing_unit19 = new TypingUnit19;\n//│ // Query 1\n//│ globalThis.m = g(1);\n//│ // Query 2\n//│ globalThis.n = m(2);\n//│ // Query 3\n//│ res = n.ll;\n//│ // End of generated code\n//│ m\n//│   = [Function (anonymous)]\n//│ n\n//│   = L {}\n//│ res\n//│     = 4\n\nclass M()\n//│ class M()\n\n:js\nlet mm = new M()\n//│ let mm: M\n//│ // Prelude\n//│ class TypingUnit21 {}\n//│ const typing_unit21 = new TypingUnit21;\n//│ // Query 1\n//│ globalThis.mm = new M.class();\n//│ // End of generated code\n//│ mm\n//│    = M {}\n\n:e // TODO support first-class classes\nfun h(z: Int) =\n  class N {\n    constructor(x: Int) {\n      log(x + z)\n    }\n  }\n  N\n//│ ╔══[ERROR] Construction of unparameterized class N should use the `new` keyword\n//│ ║  l.501: \t  N\n//│ ╙──       \t  ^\n//│ fun h: (z: Int) -> (x: Int) -> N\n\nlet hh = h(1)\n//│ let hh: (x: Int) -> N\n//│ hh\n//│    = [class N]\n\n:e\nnew hh(1)\n//│ ╔══[ERROR] type identifier not found: hh\n//│ ║  l.513: \tnew hh(1)\n//│ ╙──       \t    ^^\n//│ error\n//│ res\n//│     = N {}\n//│ // Output\n//│ 2\n\n:e\nmodule O {\n  constructor(x: Int)\n}\nmixin P {\n  constructor(x: Int)\n}\n//│ ╔══[ERROR] Explicit module constructors are not supported\n//│ ║  l.525: \t  constructor(x: Int)\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Explicit mixin constructors are not supported\n//│ ║  l.528: \t  constructor(x: Int)\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^\n//│ module O {\n//│   constructor(x: Int)\n//│ }\n//│ mixin P()\n\n:w\n:e\nclass QQ(qq: Str) {\n  constructor(foo: Int) {\n    lol\n    qq = foo\n  }\n}\n//│ ╔══[ERROR] identifier not found: lol\n//│ ║  l.545: \t    lol\n//│ ╙──       \t    ^^^\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.545: \t    lol\n//│ ╙──       \t    ^^^\n//│ ╔══[ERROR] Type mismatch in auxiliary class constructor:\n//│ ║  l.544: \t  constructor(foo: Int) {\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.545: \t    lol\n//│ ║         \t^^^^^^^\n//│ ║  l.546: \t    qq = foo\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.547: \t  }\n//│ ║         \t^^^\n//│ ╟── type `Int` is not an instance of type `Str`\n//│ ║  l.544: \t  constructor(foo: Int) {\n//│ ║         \t                   ^^^\n//│ ╟── but it flows into reference with expected type `Str`\n//│ ║  l.546: \t    qq = foo\n//│ ║         \t         ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.543: \tclass QQ(qq: Str) {\n//│ ╙──       \t             ^^^\n//│ class QQ(qq: Str) {\n//│   constructor(foo: Int)\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol lol\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Classes.mls",
    "content": "\n// To generate the prelude without printing it in the next test case\n() with { x = add 1 }\n//│ res: () & {x: int -> int}\n//│    = [ x: [Function (anonymous)] ]\n\n:js\ndef f = 0\n//│ // Query 1\n//│ globalThis.f = function f() {\n//│   return 0;\n//│ };\n//│ // End of generated code\n//│ f: 0\n//│  = [Function: f]\n\n:js\nf\n//│ // Query 1\n//│ res = f();\n//│ // End of generated code\n//│ res: 0\n//│    = 0\n\n:js\nclass Box[T]: { inner: T }\n  method Map: (T -> 'a) -> Box['a]\n  method Map f = Box { inner = f this.inner }\n  method Get = this.inner\n  method Get2 () = this.inner\n  method Foo () = 0\n//│ Defined class Box[+T]\n//│ Declared Box.Map: Box['T] -> ('T -> 'a) -> Box['a]\n//│ Defined Box.Map: Box['T] -> ('T -> 'inner) -> Box['inner]\n//│ Defined Box.Get: Box['T] -> 'T\n//│ Defined Box.Get2: Box['T] -> () -> 'T\n//│ Defined Box.Foo: Box[?] -> () -> 0\n//│ // Prelude\n//│ class Box {\n//│   constructor(fields) {\n//│     this.inner = fields.inner;\n//│   }\n//│   Map(f) {\n//│     const self = this;\n//│     return new Box({ inner: f(self.inner) });\n//│   }\n//│   get Get() {\n//│     const self = this;\n//│     return self.inner;\n//│   }\n//│   Get2() {\n//│     const self = this;\n//│     return self.inner;\n//│   }\n//│   Foo() {\n//│     return 0;\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\ndef Box value = Box { inner = value }\n//│ // Query 1\n//│ globalThis.Box1 = function Box1(value) {\n//│   return new Box({ inner: value });\n//│ };\n//│ // End of generated code\n//│ Box: 'inner -> Box['inner]\n//│    = [Function: Box1]\n\n:js\ndef box1 = Box 1\ndef box2 = box1.Map (fun x -> add x 1)\n//│ // Query 1\n//│ globalThis.box1 = function box1() {\n//│   return Box1(1);\n//│ };\n//│ // Query 2\n//│ globalThis.box2 = function box2() {\n//│   return box1().Map((x) => add(x)(1));\n//│ };\n//│ // End of generated code\n//│ box1: Box[1]\n//│     = [Function: box1]\n//│ box2: Box[int]\n//│     = [Function: box2]\n\n:js\nbox2.inner + box2.Get\n//│ // Query 1\n//│ res = box2().inner + box2().Get;\n//│ // End of generated code\n//│ res: int\n//│    = 4\n\n:js\nclass MyBox: Box[int] & { info: string }\n  method Map f = Box (f this.inner) with { info = this.info }\n  method Inc = MyBox { inner = this.inner + 1; info = this.info }\ndef MyBox inner info = MyBox { inner; info }\n//│ Defined class MyBox\n//│ Defined MyBox.Map: MyBox -> (int -> 'inner) -> (Box['inner] & {info: string})\n//│ Defined MyBox.Inc: MyBox -> MyBox\n//│ // Prelude\n//│ class MyBox extends Box {\n//│   constructor(fields) {\n//│     super(fields);\n//│     this.info = fields.info;\n//│   }\n//│   Map(f) {\n//│     const self = this;\n//│     return withConstruct(Box1(f(self.inner)), { info: self.info });\n//│   }\n//│   get Inc() {\n//│     const self = this;\n//│     return (new MyBox({\n//│       inner: self.inner + 1,\n//│       info: self.info\n//│     }));\n//│   }\n//│ }\n//│ // Query 1\n//│ globalThis.MyBox1 = function MyBox1(inner) {\n//│   return ((info) => new MyBox({\n//│     inner: inner,\n//│     info: info\n//│   }));\n//│ };\n//│ // End of generated code\n//│ MyBox: (int & 'inner) -> (string & 'info) -> (MyBox with {info: 'info, inner: 'inner})\n//│      = [Function: MyBox1]\n\n:js\nmb = MyBox 1 \"hello\"\nmb = mb.Inc\nmb.Get\nmb2 = mb.Map (fun x -> x * 3)\nmb2.Get\n//│ // Query 1\n//│ globalThis.mb = MyBox1(1)(\"hello\");\n//│ // Query 2\n//│ globalThis.mb1 = mb.Inc;\n//│ // Query 3\n//│ res = mb1.Get;\n//│ // Query 4\n//│ globalThis.mb2 = mb1.Map((x) => x * 3);\n//│ // Query 5\n//│ res = mb2.Get;\n//│ // End of generated code\n//│ mb: MyBox & {info: \"hello\", inner: 1}\n//│   = MyBox { inner: 1, info: 'hello' }\n//│ mb: MyBox\n//│   = MyBox { inner: 2, info: 'hello' }\n//│ res: int\n//│    = 2\n//│ mb2: Box[int]\n//│    = Box { inner: 6, info: 'hello' }\n//│ res: int\n//│    = 6\n\n// TODO support this syntax\n:js\nmb.(MyBox.Map) (fun x -> x * 3)\nMyBox.Map mb (fun x -> x * 3)\n//│ // Query 1\n//│ res = mb1[\"MyBox.Map\"]((x) => x * 3);\n//│ // Query 2\n//│ res = MyBox1.Map(mb1)((x) => x * 3);\n//│ // End of generated code\n//│ res: Box[int] & {info: string}\n//│ Runtime error:\n//│   TypeError: mb1.MyBox.Map is not a function\n//│ res: Box[int] & {info: string}\n//│ Runtime error:\n//│   TypeError: MyBox1.Map is not a function\n\n\n\n// Note that there is currently an inconsistency with wildcards:\n//  The type simplifier uses `?` to denote a class type argument wildcard,\n//    meaning there are no constraints on the corresponding class parameter in that type application,\n//    while user-written `?` in type signatures is handled like a definition-wide existential,\n//    which is NOT the same:\n\ndef f0 (x: Box['_]) = 42\n//│ f0: Box[?] -> 42\n//│   = [Function: f0]\n\nf0(Box{})\n//│ res: 42\n//│    = 42\n\n// i.e., def f: exists T. Box[T] -> int\ndef f: Box[?] -> int\n//│ f: in Box[?] -> int out Box[nothing] -> int\n//│  = <missing implementation>\n\n:e\nf(Box{})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.199: \tf(Box{})\n//│ ║         \t^^^^^^^^\n//│ ╟── record literal of type `anything` does not match type `nothing`\n//│ ║  l.199: \tf(Box{})\n//│ ║         \t     ^^\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.194: \tdef f: Box[?] -> int\n//│ ╙──       \t           ^\n//│ res: error | int\n//│    = <no result>\n//│      f is not implemented\n\nf = f0\n//│ Box[?] -> 42\n//│   <:  f:\n//│ Box[?] -> int\n//│  = [Function: f0]\n\n\n// The following test ensures `const self = this` is generated correctly.\n\n:js\nclass Point: { x: int; y: int }\n  method Zero = 0\n  method Move (dx: int, dy: int) =\n    Point { x = this.x + dx; y = this.y + dy }\n  method Sum self =\n    Point { x = this.x + self.x; y = this.y + self.y }\n  method Shadow this = Point { x = this.x + 1; y = this.y + 1 }\n  method Shadow2 ((this,)) = Point { x = this.x + 1; y = this.y + 1 }\n  method Shadow3 { this } = Point { x = this.x + 1; y = this.y + 1 }\n//│ Defined class Point\n//│ Defined Point.Zero: Point -> 0\n//│ Defined Point.Move: Point -> (int, int,) -> Point\n//│ Defined Point.Sum: Point -> {x: int, y: int} -> Point\n//│ Defined Point.Shadow: Point -> {x: int, y: int} -> Point\n//│ Defined Point.Shadow2: Point -> (({x: int, y: int},),) -> Point\n//│ Defined Point.Shadow3: Point -> {this: {x: int, y: int}} -> Point\n//│ // Prelude\n//│ class Point {\n//│   constructor(fields) {\n//│     this.x = fields.x;\n//│     this.y = fields.y;\n//│   }\n//│   get Zero() {\n//│     return 0;\n//│   }\n//│   Move(dx, dy) {\n//│     const self = this;\n//│     return (new Point({\n//│       x: self.x + dx,\n//│       y: self.y + dy\n//│     }));\n//│   }\n//│   Sum(self1) {\n//│     const self = this;\n//│     return (new Point({\n//│       x: self.x + self1.x,\n//│       y: self.y + self1.y\n//│     }));\n//│   }\n//│   Shadow(this$) {\n//│     return (new Point({\n//│       x: this$.x + 1,\n//│       y: this$.y + 1\n//│     }));\n//│   }\n//│   Shadow2([this$]) {\n//│     return (new Point({\n//│       x: this$.x + 1,\n//│       y: this$.y + 1\n//│     }));\n//│   }\n//│   Shadow3({ \"this\": this$ }) {\n//│     return (new Point({\n//│       x: this$.x + 1,\n//│       y: this$.y + 1\n//│     }));\n//│   }\n//│ }\n//│ // End of generated code\n\n//  Some simplification tests:\n\n:NoJS\n\nerror : 2 & int\n//│ res: 2\n\nerror : 2 | int\n//│ res: int\n\nerror : Box[int] & ~box\n//│ res: nothing\n\nerror : Box[?] | Box[?] & {x: '_}\n//│ res: Box[?]\n\nerror : ((Box[?] | Box[?] & {x: 'a -> int}) & 'a) -> 'a\n//│ res: (Box[nothing] & 'a) -> 'a\n\nerror: \"\" | string\n//│ res: string\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/ConstructorStmt.mls",
    "content": ":NewDefs\n\n\nlog(\"Hello!\")\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ Hello!\n\n\n:js\nmodule Test0 {\n  log(\"Hello!\")\n}\n//│ module Test0\n//│ // Prelude\n//│ class TypingUnit1 {\n//│   #Test0;\n//│   constructor() {\n//│   }\n//│   get Test0() {\n//│     const qualifier = this;\n//│     if (this.#Test0 === undefined) {\n//│       class Test0 {\n//│         constructor() {\n//│           log(\"Hello!\");\n//│         }\n//│       }\n//│       this.#Test0 = new Test0();\n//│       this.#Test0.class = Test0;\n//│     }\n//│     return this.#Test0;\n//│   }\n//│ }\n//│ const typing_unit1 = new TypingUnit1;\n//│ globalThis.Test0 = typing_unit1.Test0;\n//│ // End of generated code\n\n:js\nTest0\n//│ Test0\n//│ // Prelude\n//│ class TypingUnit2 {}\n//│ const typing_unit2 = new TypingUnit2;\n//│ // Query 1\n//│ res = Test0;\n//│ // End of generated code\n//│ res\n//│     = Test0 { class: [class Test0] }\n//│ // Output\n//│ Hello!\n\n:js\nTest0\n//│ Test0\n//│ // Prelude\n//│ class TypingUnit3 {}\n//│ const typing_unit3 = new TypingUnit3;\n//│ // Query 1\n//│ res = Test0;\n//│ // End of generated code\n//│ res\n//│     = Test0 { class: [class Test0] }\n\n:js\nclass A(a: Int) {\n  log(a)\n}\n//│ class A(a: Int)\n//│ // Prelude\n//│ class TypingUnit4 {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #a;\n//│         constructor(a) {\n//│           this.#a = a;\n//│           log(a);\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#a];\n//│         }\n//│       };\n//│       this.#A = ((a) => Object.freeze(new A(a)));\n//│       this.#A.class = A;\n//│       this.#A.unapply = A.unapply;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit4 = new TypingUnit4;\n//│ globalThis.A = typing_unit4.A;\n//│ // End of generated code\n\n:js\nlet aa = A(42)\n//│ let aa: A\n//│ // Prelude\n//│ class TypingUnit5 {}\n//│ const typing_unit5 = new TypingUnit5;\n//│ // Query 1\n//│ globalThis.aa = A(42);\n//│ // End of generated code\n//│ aa\n//│    = A {}\n//│ // Output\n//│ 42\n\n:js\naa\n//│ A\n//│ // Prelude\n//│ class TypingUnit6 {}\n//│ const typing_unit6 = new TypingUnit6;\n//│ // Query 1\n//│ res = aa;\n//│ // End of generated code\n//│ res\n//│     = A {}\n\n:js\nlet ab = A(0)\n//│ let ab: A\n//│ // Prelude\n//│ class TypingUnit7 {}\n//│ const typing_unit7 = new TypingUnit7;\n//│ // Query 1\n//│ globalThis.ab = A(0);\n//│ // End of generated code\n//│ ab\n//│    = A {}\n//│ // Output\n//│ 0\n\n:e\n:w\n:js\nclass Foo {\n  this: { x: Int }\n}\n//│ ╔══[ERROR] Type `#Foo` does not contain member `x`\n//│ ║  l.145: \t  this: { x: Int }\n//│ ╙──       \t          ^\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in type ascription:\n//│ ║  l.145: \t  this: { x: Int }\n//│ ║         \t  ^^^^\n//│ ╟── type `{x: Int}` does not match type `()`\n//│ ║  l.145: \t  this: { x: Int }\n//│ ║         \t        ^^^^^^^^^^\n//│ ╟── but it flows into expression in statement position with expected type `()`\n//│ ║  l.145: \t  this: { x: Int }\n//│ ╙──       \t  ^^^^\n//│ class Foo {\n//│   constructor()\n//│ }\n//│ // Prelude\n//│ class TypingUnit8 {\n//│   #Foo;\n//│   constructor() {\n//│   }\n//│   get Foo() {\n//│     const qualifier = this;\n//│     if (this.#Foo === undefined) {\n//│       class Foo {};\n//│       this.#Foo = Foo;\n//│     }\n//│     return this.#Foo;\n//│   }\n//│ }\n//│ const typing_unit8 = new TypingUnit8;\n//│ globalThis.Foo = typing_unit8.Foo;\n//│ // End of generated code\n\n:e\n:w\n:js\nclass Bar {\n  super: { x: Int }\n}\n//│ ╔══[ERROR] Illegal use of `super`\n//│ ║  l.186: \t  super: { x: Int }\n//│ ╙──       \t  ^^^^^\n//│ ╔══[ERROR] Type `#Bar` does not contain member `x`\n//│ ║  l.186: \t  super: { x: Int }\n//│ ╙──       \t           ^\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in type ascription:\n//│ ║  l.186: \t  super: { x: Int }\n//│ ║         \t  ^^^^^\n//│ ╟── type `{x: Int}` does not match type `()`\n//│ ║  l.186: \t  super: { x: Int }\n//│ ║         \t         ^^^^^^^^^^\n//│ ╟── but it flows into expression in statement position with expected type `()`\n//│ ║  l.186: \t  super: { x: Int }\n//│ ╙──       \t  ^^^^^\n//│ class Bar {\n//│   constructor()\n//│ }\n//│ // Prelude\n//│ class TypingUnit9 {\n//│   #Bar;\n//│   constructor() {\n//│   }\n//│   get Bar() {\n//│     const qualifier = this;\n//│     if (this.#Bar === undefined) {\n//│       class Bar {};\n//│       this.#Bar = Bar;\n//│     }\n//│     return this.#Bar;\n//│   }\n//│ }\n//│ const typing_unit9 = new TypingUnit9;\n//│ globalThis.Bar = typing_unit9.Bar;\n//│ // End of generated code\n\n:js\nclass Baz() {\n  val x = 123\n  log([1, x])\n  val y =\n    log([2, x])\n    x + 1\n  log([3, y])\n}\n//│ class Baz() {\n//│   val x: 123\n//│   val y: Int\n//│ }\n//│ // Prelude\n//│ class TypingUnit10 {\n//│   #Baz;\n//│   constructor() {\n//│   }\n//│   get Baz() {\n//│     const qualifier = this;\n//│     if (this.#Baz === undefined) {\n//│       class Baz {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         #y;\n//│         get y() { return this.#y; }\n//│         constructor() {\n//│           this.#x = 123;\n//│           const x = this.#x;\n//│           log([\n//│             1,\n//│             x\n//│           ]);\n//│           this.#y = (() => {\n//│             log([\n//│               2,\n//│               x\n//│             ]);\n//│             return x + 1;\n//│           })();\n//│           const y = this.#y;\n//│           log([\n//│             3,\n//│             y\n//│           ]);\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [];\n//│         }\n//│       };\n//│       this.#Baz = (() => Object.freeze(new Baz()));\n//│       this.#Baz.class = Baz;\n//│       this.#Baz.unapply = Baz.unapply;\n//│     }\n//│     return this.#Baz;\n//│   }\n//│ }\n//│ const typing_unit10 = new TypingUnit10;\n//│ globalThis.Baz = typing_unit10.Baz;\n//│ // End of generated code\n\nlet baz = Baz()\nlog([baz.x, baz.y])\n//│ let baz: Baz\n//│ ()\n//│ baz\n//│     = Baz {}\n//│ // Output\n//│ [ 1, 123 ]\n//│ [ 2, 123 ]\n//│ [ 3, 124 ]\n//│ res\n//│     = undefined\n//│ // Output\n//│ [ 123, 124 ]\n\n:js\nclass Q() {\n  let q = 42\n  fun qq =\n    let f = (x: Int) => {q: x + q}; f(1)\n}\n//│ class Q() {\n//│   let q: 42\n//│   fun qq: {q: Int}\n//│ }\n//│ // Prelude\n//│ class TypingUnit12 {\n//│   #Q;\n//│   constructor() {\n//│   }\n//│   get Q() {\n//│     const qualifier = this;\n//│     if (this.#Q === undefined) {\n//│       class Q {\n//│         #q;\n//│         constructor() {\n//│           this.#q = 42;\n//│           const q = this.#q;\n//│         }\n//│         get qq() {\n//│           const qualifier1 = this;\n//│           return ((() => {\n//│             let f = (x) => ({ q: x + qualifier1.#q });\n//│             return f(1);\n//│           })());\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [];\n//│         }\n//│       };\n//│       this.#Q = (() => Object.freeze(new Q()));\n//│       this.#Q.class = Q;\n//│       this.#Q.unapply = Q.unapply;\n//│     }\n//│     return this.#Q;\n//│   }\n//│ }\n//│ const typing_unit12 = new TypingUnit12;\n//│ globalThis.Q = typing_unit12.Q;\n//│ // End of generated code\n\nlet q = Q()\nq.qq.q\n//│ let q: Q\n//│ Int\n//│ q\n//│   = Q {}\n//│ res\n//│     = 43\n\n:js\nclass W() {\n  let x = 42\n  fun add(self: Int) = x + self\n}\n//│ class W() {\n//│   fun add: (self: Int) -> Int\n//│   let x: 42\n//│ }\n//│ // Prelude\n//│ class TypingUnit14 {\n//│   #W;\n//│   constructor() {\n//│   }\n//│   get W() {\n//│     const qualifier = this;\n//│     if (this.#W === undefined) {\n//│       class W {\n//│         #x;\n//│         constructor() {\n//│           this.#x = 42;\n//│           const x = this.#x;\n//│         }\n//│         add(self) {\n//│           const qualifier1 = this;\n//│           return qualifier1.#x + self;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [];\n//│         }\n//│       };\n//│       this.#W = (() => Object.freeze(new W()));\n//│       this.#W.class = W;\n//│       this.#W.unapply = W.unapply;\n//│     }\n//│     return this.#W;\n//│   }\n//│ }\n//│ const typing_unit14 = new TypingUnit14;\n//│ globalThis.W = typing_unit14.W;\n//│ // End of generated code\n\n:js\nlet www = W()\nwww.add(42)\n//│ let www: W\n//│ Int\n//│ // Prelude\n//│ class TypingUnit15 {}\n//│ const typing_unit15 = new TypingUnit15;\n//│ // Query 1\n//│ globalThis.www = W();\n//│ // Query 2\n//│ res = www.add(42);\n//│ // End of generated code\n//│ www\n//│     = W {}\n//│ res\n//│     = 84\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Declare.mls",
    "content": "// This file tests the error message of unimplemented symbols.\n()\n//│ res: ()\n//│    = []\n\n:js\ndef a: int\n//│ // Query 1 is empty\n//│ // End of generated code\n//│ a: int\n//│  = <missing implementation>\n\n:js\ndef b = a\n//│ // Query 1 aborted: a is not implemented\n//│ // End of generated code\n//│ b: int\n//│  = <no result>\n//│    a is not implemented\n\n// We can use some unimplemented value.\n// But preserve other implemented things in the same block.\n:js\ndef c = b\ndef q = 0\n//│ // Query 1 aborted: b and a are not implemented\n//│ // Query 2\n//│ globalThis.q = function q() {\n//│   return 0;\n//│ };\n//│ // End of generated code\n//│ c: int\n//│  = <no result>\n//│    b and a are not implemented\n//│ q: 0\n//│  = [Function: q]\n\n// We will display all unimplemented symbols.\n:js\ndef d = c\n//│ // Query 1 aborted: c, b and a are not implemented\n//│ // End of generated code\n//│ d: int\n//│  = <no result>\n//│    c, b and a are not implemented\n\ndef q: int\ndef q: string\n//│ q: int\n//│  = <missing implementation>\n//│ q: string\n//│  = <missing implementation>\n\nq: anything\n//│ res: anything\n//│    = <no result>\n//│      q is not implemented\n\n// Use unimplemented symbols defined in the same block.\n0\ndef f: int -> int\nf 0\n//│ res: 0\n//│    = 0\n//│ f: int -> int\n//│  = <missing implementation>\n//│ res: int\n//│    = <no result>\n//│      f is not implemented\n\ndef a: int\n//│ a: int\n//│  = <missing implementation>\n\na = 0\n//│ 0\n//│   <:  a:\n//│ int\n//│  = 0\n\ndef b = a\n//│ b: int\n//│  = [Function: b]\n\n// Declare JavaScript reserved words.\n:js\ndef break = 1\ndef str = \"str\"\n//│ // Query 1\n//│ globalThis.break1 = function break1() {\n//│   return 1;\n//│ };\n//│ // Query 2\n//│ globalThis.str = function str() {\n//│   return \"str\";\n//│ };\n//│ // End of generated code\n//│ break: 1\n//│      = [Function: break1]\n//│ str: \"str\"\n//│    = [Function: str]\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Escape.mls",
    "content": "()\n//│ res: ()\n//│    = []\n\n:js\n:escape\ndef console: nothing\n//│ // Query 1 is empty\n//│ // End of generated code\n//│ console: nothing\n//│        = <missing implementation>\n\n:js\nconsole.log \"hello\"\n//│ // Query 1\n//│ res = console.log(\"hello\");\n//│ // End of generated code\n//│ res: nothing\n//│    = undefined\n\n:js\n0\n//│ // Query 1\n//│ res = 0;\n//│ // End of generated code\n//│ res: 0\n//│    = 0\n"
  },
  {
    "path": "shared/src/test/diff/codegen/FieldOverride.mls",
    "content": ":NewParser\n:NewDefs\n\n:js\nclass C(a: Int) { val a = 1 }\n//│ class C(a: Int) {\n//│   val a: 1\n//│ }\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #C;\n//│   constructor() {\n//│   }\n//│   get C() {\n//│     const qualifier = this;\n//│     if (this.#C === undefined) {\n//│       class C {\n//│         #a;\n//│         get a() { return this.#a; }\n//│         constructor(a) {\n//│           this.#a = a;\n//│           this.#a = 1;\n//│           const a1 = this.#a;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#a];\n//│         }\n//│       };\n//│       this.#C = ((a) => Object.freeze(new C(a)));\n//│       this.#C.class = C;\n//│       this.#C.unapply = C.unapply;\n//│     }\n//│     return this.#C;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.C = typing_unit.C;\n//│ // End of generated code\n\n// should return 1\nlet a = C(2)\na.a\n//│ let a: C\n//│ 1\n//│ a\n//│   = C {}\n//│ res\n//│     = 1\n\n:js\nclass C2(a: Int, b: Int) {\n  val a = b + 1\n  val b = a + 1\n}\n//│ class C2(a: Int, b: Int) {\n//│   val a: Int\n//│   val b: Int\n//│ }\n//│ // Prelude\n//│ class TypingUnit2 {\n//│   #C2;\n//│   constructor() {\n//│   }\n//│   get C2() {\n//│     const qualifier = this;\n//│     if (this.#C2 === undefined) {\n//│       class C2 {\n//│         #a;\n//│         #b;\n//│         get a() { return this.#a; }\n//│         get b() { return this.#b; }\n//│         constructor(a, b) {\n//│           this.#a = a;\n//│           this.#b = b;\n//│           this.#a = b + 1;\n//│           const a1 = this.#a;\n//│           this.#b = a1 + 1;\n//│           const b1 = this.#b;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return ([\n//│             x.#a,\n//│             x.#b\n//│           ]);\n//│         }\n//│       };\n//│       this.#C2 = ((a, b) => Object.freeze(new C2(a, b)));\n//│       this.#C2.class = C2;\n//│       this.#C2.unapply = C2.unapply;\n//│     }\n//│     return this.#C2;\n//│   }\n//│ }\n//│ const typing_unit2 = new TypingUnit2;\n//│ globalThis.C2 = typing_unit2.C2;\n//│ // End of generated code\n\nlet c2 = C2(1, 2)\nc2.a\nc2.b\n//│ let c2: C2\n//│ Int\n//│ c2\n//│    = C2 {}\n//│ res\n//│     = 3\n//│ res\n//│     = 4\n\nclass C3(a: Int) {\n  val a = 42\n  class C4(a: Int) {\n    val a = 44\n  }\n}\n//│ class C3(a: Int) {\n//│   class C4(a: Int) {\n//│     val a: 44\n//│   }\n//│   val a: 42\n//│ }\n\n:e\nlet c3 = C3(1)\nlet c4 = c3.C4(2)\nc3.a\nc4.a\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.128: \tlet c4 = c3.C4(2)\n//│ ╙──       \t           ^^^\n//│ let c3: C3\n//│ let c4: error\n//│ error\n//│ c3\n//│    = C3 {}\n//│ c4\n//│    = C4 {}\n//│ res\n//│     = 42\n//│ res\n//│     = 44\n"
  },
  {
    "path": "shared/src/test/diff/codegen/IndirectRecursion.mls",
    "content": "\n\ndef z: (('a -> 'b) -> (('a -> 'b) & 'c)) -> 'c\n//│ z: (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│  = <missing implementation>\n\n:e\ndef z =\n  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))\n//│ (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> (error | 'c)\n//│   <:  z:\n//│ (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.9: \t  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))\n//│ ║       \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│  = [Function: z]\n\ndef z =\n  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v))!)\n//│ (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> 'c\n//│   <:  z:\n//│ (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│  = [Function: z1]\n\n\ndef pow1 = z (fun pow0 -> fun n -> fun x ->\n    if n > 0 then pow0 (n - 1) x * x\n    else 1\n  )\n//│ pow1: int -> int -> int\n//│     = [Function: pow1]\n\npow1 3 4\n//│ res: int\n//│    = 64\n\n\n:e\nz (fun self -> 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.40: \tz (fun self -> 1)\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.40: \tz (fun self -> 1)\n//│ ║        \t               ^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.3: \tdef z: (('a -> 'b) -> (('a -> 'b) & 'c)) -> 'c\n//│ ║       \t                       ^^^^^^^^^^\n//│ ╟── from intersection type:\n//│ ║  l.3: \tdef z: (('a -> 'b) -> (('a -> 'b) & 'c)) -> 'c\n//│ ╙──     \t                      ^^^^^^^^^^^^^^^^^\n//│ res: 1 | error\n//│    = 1\n\n\nzid = z (fun self -> id)\n//│ zid: 'a -> 'a\n//│    = [Function: id]\n\nzid 1\n//│ res: 1\n//│    = 1\n\n\nzargs = z (fun self -> fun x -> self)\n//│ zargs: 'b\n//│   where\n//│     'b :> anything -> 'b\n//│      = [Function (anonymous)]\n\nzargs 1\n//│ res: 'b\n//│   where\n//│     'b :> anything -> 'b\n//│    = [Function (anonymous)]\n\nzargs 1 2 3 4\n//│ res: 'b\n//│   where\n//│     'b :> anything -> 'b\n//│    = [Function (anonymous)]\n\n\nloop = z (fun self -> self)\n//│ loop: anything -> nothing\n//│     = [Function (anonymous)]\n\n:re\nloop 1\n//│ res: nothing\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\ndef pow pow n x =\n    if n > 0 then pow (n - 1) x * x\n    else 1\n//│ pow: (int -> 'a -> int) -> int -> (int & 'a) -> int\n//│    = [Function: pow]\n\ndef pow = z pow\npow 3 4\n//│ pow: int -> int -> int\n//│    = [Function: pow2]\n//│ res: int\n//│    = 64\n\n\ndef oops = z (fun f -> f)\n//│ oops: anything -> nothing\n//│     = [Function: oops]\n\n:re\noops 1\n//│ res: nothing\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n\n:NoRecursiveTypes\n\n:e\ndef z =\n  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))\n//│ (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> (error | 'c)\n//│   <:  z:\n//│ (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.126: \t  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│  = [Function: z2]\n\n:e\ndef z =\n  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v))!)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 'a -> ?\n//│        <: 'a -> ? -> ?\n//│ ╙──\n//│ (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> 'c\n//│   <:  z:\n//│ (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│  = [Function: z3]\n\n:NoCycleCheck\n\n// Exceeds recursion depth limit:\n:e\ndef z =\n  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))\n//│ ((anything -> nothing) -> anything) -> error\n//│   <:  z:\n//│ (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b <: (forall ?c ?d. ?c -> ?d) -> ?e` exceeded recursion depth limit (250)\n//│ ║  l.154: \t  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v)))\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│  = [Function: z4]\n\n:e\ndef z =\n  (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v))!)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 'a -> ?\n//│        <: 'a -> ? -> ?\n//│ ╙──\n//│ (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> 'c\n//│   <:  z:\n//│ (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│  = [Function: z5]\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Inheritance.mls",
    "content": "\n:js\ntrait X: { x: int }\nclass Y: X\n  method MX = this.x\n//│ Defined trait X\n//│ Defined class Y\n//│ Defined Y.MX: Y -> int\n//│ // Prelude\n//│ let res;\n//│ const X = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ class Y {\n//│   constructor(fields) {\n//│     X.implement(this);\n//│     this.x = fields.x;\n//│   }\n//│   get MX() {\n//│     const self = this;\n//│     return self.x;\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\n(Y {x = 1}).x\n//│ // Query 1\n//│ res = new Y({ x: 1 }).x;\n//│ // End of generated code\n//│ res: 1\n//│    = 1\n\n:js\ntrait A: { a: int }\ntrait B: { b: int } & A\nclass C: B & { c: int }\n//│ Defined trait A\n//│ Defined trait B\n//│ Defined class C\n//│ // Prelude\n//│ const A = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ const B = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│       A.implement(instance);\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ class C {\n//│   constructor(fields) {\n//│     B.implement(this);\n//│     this.c = fields.c;\n//│     this.b = fields.b;\n//│     this.a = fields.a;\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\nclass P: Q & { p: int }\ntrait Q: R & { q: int }\ntrait R: S & { r: int }\ntrait S: { s: int }\n//│ Defined class P\n//│ Defined trait Q\n//│ Defined trait R\n//│ Defined trait S\n//│ // Prelude\n//│ const Q = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│       R.implement(instance);\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ const R = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│       S.implement(instance);\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ const S = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ class P {\n//│   constructor(fields) {\n//│     Q.implement(this);\n//│     this.p = fields.p;\n//│     this.q = fields.q;\n//│     this.r = fields.r;\n//│     this.s = fields.s;\n//│   }\n//│ }\n//│ // End of generated code\n\ndef checkS x = case x of\n  { S -> true\n  | _ -> false\n  }\ndef checkR x = case x of\n  { R -> true\n  | _ -> false\n  }\ndef checkQ x = case x of\n  { Q -> true\n  | _ -> false\n  }\ndef checkP x = case x of\n  { P -> true\n  | _ -> false\n  }\n//│ checkS: anything -> Bool\n//│       = [Function: checkS]\n//│ checkR: anything -> Bool\n//│       = [Function: checkR]\n//│ checkQ: anything -> Bool\n//│       = [Function: checkQ]\n//│ checkP: anything -> Bool\n//│       = [Function: checkP]\n\n// Should pass all checks.\n:js\np = P { s = 0; q = 0; r = 0; p = 0 }\ncheckS p && checkR p && checkQ p && checkP p\n//│ // Query 1\n//│ globalThis.p = new P({\n//│   s: 0,\n//│   q: 0,\n//│   r: 0,\n//│   p: 0\n//│ });\n//│ // Query 2\n//│ res = checkS(p) && checkR(p) && checkQ(p) && checkP(p);\n//│ // End of generated code\n//│ p: P & {p: 0, q: 0, r: 0, s: 0}\n//│  = P { p: 0, q: 0, r: 0, s: 0 }\n//│ res: bool\n//│    = true\n\ntrait Foo\n  method Foo = 1\n//│ Defined trait Foo\n//│ Defined Foo.Foo: Foo -> 1\n\nclass Bar: Foo\n//│ Defined class Bar\n\n// `Foo` should not appear.\nbar = Bar{}\n//│ bar: Bar\n//│    = Bar {}\n\n// But it is actually there.\nbar.Foo\n//│ res: 1\n//│    = 1\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/LogInfo.mls",
    "content": "\n:js\nlog 1\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ let res;\n//│ // Query 1\n//│ res = log(1);\n//│ // End of generated code\n//│ = undefined\n//│ // Output\n//│ 1\n\n:escape\ndef console: nothing\n//│ console: nothing\n//│        = <missing implementation>\n\nconsole.log 1\n//│ res: nothing\n//│    = undefined\n\nconsole.info(1)\n//│ res: nothing\n//│    = undefined\n//│ // Output\n//│ 1\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/MemberInitShadowing.mls",
    "content": ":NewDefs\n\n\n// * This is a valid use of let-binding shadowing\n:js\nclass A(x0: Int) {\n  let x1 = x0 + 1\n  let x1 = x1 + 1\n  log(x1)\n}\n//│ class A(x0: Int) {\n//│   let x1: Int\n//│ }\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ let res;\n//│ class TypingUnit {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #x0;\n//│         constructor(x0) {\n//│           this.#x0 = x0;\n//│           const x1 = x0 + 1;\n//│           const x11 = x11 + 1;\n//│           log(x11);\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x0];\n//│         }\n//│       };\n//│       this.#A = ((x0) => Object.freeze(new A(x0)));\n//│       this.#A.class = A;\n//│       this.#A.unapply = A.unapply;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.A = typing_unit.A;\n//│ // End of generated code\n\n// FIXME\nA(123)\n//│ A\n//│ res\n//│ Runtime error:\n//│   ReferenceError: Cannot access 'x11' before initialization\n\n\n// TODO `val` redefinition should be a type error\n:js\nclass A(x0: Int) {\n  val x1 = x0 + 1\n  val x1 = x1 + 1\n  log(x1)\n}\n//│ class A(x0: Int) {\n//│   val x1: Int\n//│ }\n//│ // Prelude\n//│ class TypingUnit2 {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #x0;\n//│         #x1;\n//│         get x1() { return this.#x1; }\n//│         constructor(x0) {\n//│           this.#x0 = x0;\n//│           this.#x1 = x0 + 1;\n//│           const x1 = this.#x1;\n//│           this.#x1 = x1 + 1;\n//│           const x11 = this.#x1;\n//│           log(x11);\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x0];\n//│         }\n//│       };\n//│       this.#A = ((x0) => Object.freeze(new A(x0)));\n//│       this.#A.class = A;\n//│       this.#A.unapply = A.unapply;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit2 = new TypingUnit2;\n//│ globalThis.A = typing_unit2.A;\n//│ // End of generated code\n\nA(123)\n//│ A\n//│ res\n//│     = A {}\n//│ // Output\n//│ 125\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Mixin.mls",
    "content": ":NewDefs\n\n:js\nclass Add<out E>(lhs: E, rhs: E)\nclass Lit(n: Int)\n//│ class Add[E](lhs: E, rhs: E)\n//│ class Lit(n: Int)\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #Add;\n//│   #Lit;\n//│   constructor() {\n//│   }\n//│   get Add() {\n//│     const qualifier = this;\n//│     if (this.#Add === undefined) {\n//│       class Add {\n//│         #lhs;\n//│         #rhs;\n//│         constructor(lhs, rhs) {\n//│           this.#lhs = lhs;\n//│           this.#rhs = rhs;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return ([\n//│             x.#lhs,\n//│             x.#rhs\n//│           ]);\n//│         }\n//│       };\n//│       this.#Add = ((lhs, rhs) => Object.freeze(new Add(lhs, rhs)));\n//│       this.#Add.class = Add;\n//│       this.#Add.unapply = Add.unapply;\n//│     }\n//│     return this.#Add;\n//│   }\n//│   get Lit() {\n//│     const qualifier = this;\n//│     if (this.#Lit === undefined) {\n//│       class Lit {\n//│         #n;\n//│         constructor(n) {\n//│           this.#n = n;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#n];\n//│         }\n//│       };\n//│       this.#Lit = ((n) => Object.freeze(new Lit(n)));\n//│       this.#Lit.class = Lit;\n//│       this.#Lit.unapply = Lit.unapply;\n//│     }\n//│     return this.#Lit;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.Add = typing_unit.Add;\n//│ globalThis.Lit = typing_unit.Lit;\n//│ // End of generated code\n\n:js\nmixin EvalBase {\n  fun eval(e) =\n    if e is\n      Lit(n) then n: Int\n      Add(l, r) then this.eval(l) + this.eval(r)\n}\n//│ mixin EvalBase() {\n//│   this: {eval: 'a -> Int}\n//│   fun eval: (Add['a] | Lit) -> Int\n//│ }\n//│ // Prelude\n//│ class TypingUnit1 {\n//│   constructor() {\n//│   }\n//│   EvalBase(base) {\n//│     const qualifier = this;\n//│     return (class EvalBase extends base {\n//│       constructor(...rest) {\n//│         super(...rest);\n//│       }\n//│       eval(e) {\n//│         const qualifier1 = this;\n//│         return ((() => {\n//│           let a;\n//│           return (a = e, a instanceof Lit.class ? ((ucs$args_e$Lit) => ((n) => n)(ucs$args_e$Lit[0]))(Lit.unapply(e)) : a instanceof Add.class ? ((ucs$args_e$Add) => ((l) => ((r) => qualifier1.eval(l) + qualifier1.eval(r))(ucs$args_e$Add[1]))(ucs$args_e$Add[0]))(Add.unapply(e)) : (() => {\n//│             throw new Error(\"non-exhaustive case expression\");\n//│           })());\n//│         })());\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit1 = new TypingUnit1;\n//│ globalThis.EvalBase = ((base) => typing_unit1.EvalBase(base));\n//│ // End of generated code\n\n:js\nclass Neg<out A>(expr: A)\n//│ class Neg[A](expr: A)\n//│ // Prelude\n//│ class TypingUnit2 {\n//│   #Neg;\n//│   constructor() {\n//│   }\n//│   get Neg() {\n//│     const qualifier = this;\n//│     if (this.#Neg === undefined) {\n//│       class Neg {\n//│         #expr;\n//│         constructor(expr) {\n//│           this.#expr = expr;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#expr];\n//│         }\n//│       };\n//│       this.#Neg = ((expr) => Object.freeze(new Neg(expr)));\n//│       this.#Neg.class = Neg;\n//│       this.#Neg.unapply = Neg.unapply;\n//│     }\n//│     return this.#Neg;\n//│   }\n//│ }\n//│ const typing_unit2 = new TypingUnit2;\n//│ globalThis.Neg = typing_unit2.Neg;\n//│ // End of generated code\n\n:js\nmixin EvalNeg {\n  fun eval(e) =\n    if e is Neg(d) then 0 - this.eval(d)\n    else super.eval(e)\n}\n//│ mixin EvalNeg() {\n//│   super: {eval: 'a -> 'b}\n//│   this: {eval: 'c -> Int}\n//│   fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b)\n//│ }\n//│ // Prelude\n//│ class TypingUnit3 {\n//│   constructor() {\n//│   }\n//│   EvalNeg(base) {\n//│     const qualifier = this;\n//│     return (class EvalNeg extends base {\n//│       constructor(...rest) {\n//│         super(...rest);\n//│       }\n//│       eval(e) {\n//│         const qualifier1 = this;\n//│         return ((() => {\n//│           return e instanceof Neg.class ? ((ucs$args_e$Neg) => ((d) => 0 - qualifier1.eval(d))(ucs$args_e$Neg[0]))(Neg.unapply(e)) : super.eval(e);\n//│         })());\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit3 = new TypingUnit3;\n//│ globalThis.EvalNeg = ((base) => typing_unit3.EvalNeg(base));\n//│ // End of generated code\n\n:js\nmixin EvalNegNeg {\n  fun eval(e) =\n    if e is Neg(Neg(d)) then this.eval(d)\n    else super.eval(e)\n}\n//│ mixin EvalNegNeg() {\n//│   super: {eval: (Neg[nothing] | 'a) -> 'b}\n//│   this: {eval: 'c -> 'b}\n//│   fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b\n//│ }\n//│ // Prelude\n//│ class TypingUnit4 {\n//│   constructor() {\n//│   }\n//│   EvalNegNeg(base) {\n//│     const qualifier = this;\n//│     return (class EvalNegNeg extends base {\n//│       constructor(...rest) {\n//│         super(...rest);\n//│       }\n//│       eval(e) {\n//│         const qualifier1 = this;\n//│         return ((() => {\n//│           return e instanceof Neg.class ? ((ucs$args_e$Neg) => ((e$Neg_0) => e$Neg_0 instanceof Neg.class ? ((ucs$args_e$Neg_0$Neg) => ((d) => qualifier1.eval(d))(ucs$args_e$Neg_0$Neg[0]))(Neg.unapply(e$Neg_0)) : super.eval(e))(ucs$args_e$Neg[0]))(Neg.unapply(e)) : super.eval(e);\n//│         })());\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit4 = new TypingUnit4;\n//│ globalThis.EvalNegNeg = ((base) => typing_unit4.EvalNegNeg(base));\n//│ // End of generated code\n\n:js\nmodule TestLang extends EvalBase, EvalNeg, EvalNegNeg\n//│ module TestLang {\n//│   fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int\n//│ }\n//│ where\n//│   'A <: 'b & (Neg['b] | Object & ~#Neg)\n//│   'b <: Neg['A] | Object & 'a & ~#Neg\n//│   'a <: Add['b] | Lit | Neg['b]\n//│ // Prelude\n//│ class TypingUnit5 {\n//│   #TestLang;\n//│   constructor() {\n//│   }\n//│   get TestLang() {\n//│     const qualifier = this;\n//│     if (this.#TestLang === undefined) {\n//│       class TestLang extends EvalNegNeg(EvalNeg(EvalBase(Object))) {\n//│         constructor() {\n//│           super();\n//│         }\n//│       }\n//│       this.#TestLang = new TestLang();\n//│       this.#TestLang.class = TestLang;\n//│     }\n//│     return this.#TestLang;\n//│   }\n//│ }\n//│ const typing_unit5 = new TypingUnit5;\n//│ globalThis.TestLang = typing_unit5.TestLang;\n//│ // End of generated code\n\nfun mk(n) = if n is\n  0 then Lit(0)\n  1 then Neg(mk(n))\n  _ then Add(mk(n), mk(n))\nTestLang.eval(mk(0))\n//│ fun mk: forall 'a. Object -> (Lit | 'a)\n//│ Int\n//│ where\n//│   'a :> Add[Lit | 'a] | Neg[Lit | 'a]\n//│ res\n//│     = 0\n\n\nclass Foo(x: Int)\n//│ class Foo(x: Int)\n\nclass Bar(x2: Int, y: Int) extends Foo(x2 + y)\n//│ class Bar(x2: Int, y: Int) extends Foo\n\n\nmixin AA(a: Int) {\n}\n//│ mixin AA(a: Int)\n\nmixin BB {}\n//│ mixin BB()\n\n\nclass C(x: Int) extends BB\n//│ class C(x: Int)\n\nclass D(x: Int) extends AA(x)\n//│ class D(x: Int)\n\nclass E(x: Int) extends BB, AA(x)\n//│ class E(x: Int)\n\n:js\nmixin Fooo(val x: Int) { fun f = [x, this.x] }\n//│ mixin Fooo(x: Int) {\n//│   this: {x: 'x}\n//│   fun f: [Int, 'x]\n//│ }\n//│ // Prelude\n//│ class TypingUnit14 {\n//│   constructor() {\n//│   }\n//│   Fooo(base) {\n//│     const qualifier = this;\n//│     return (class Fooo extends base {\n//│       #x;\n//│       get x() { return this.#x; }\n//│       constructor(x, ...rest) {\n//│         super(...rest);\n//│         this.#x = x;\n//│       }\n//│       get f() {\n//│         const x = this.#x;\n//│         const qualifier1 = this;\n//│         return ([\n//│           x,\n//│           qualifier1.x\n//│         ]);\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit14 = new TypingUnit14;\n//│ globalThis.Fooo = ((base) => typing_unit14.Fooo(base));\n//│ // End of generated code\n\n:js\nmixin Bazz(val y: Int)\n//│ mixin Bazz(y: Int)\n//│ // Prelude\n//│ class TypingUnit15 {\n//│   constructor() {\n//│   }\n//│   Bazz(base) {\n//│     const qualifier = this;\n//│     return (class Bazz extends base {\n//│       #y;\n//│       get y() { return this.#y; }\n//│       constructor(y, ...rest) {\n//│         super(...rest);\n//│         this.#y = y;\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit15 = new TypingUnit15;\n//│ globalThis.Bazz = ((base) => typing_unit15.Bazz(base));\n//│ // End of generated code\n\n:js\nmodule Barr extends Fooo(0), Bazz(1)\n//│ module Barr {\n//│   fun f: [Int, 0]\n//│ }\n//│ // Prelude\n//│ class TypingUnit16 {\n//│   #Barr;\n//│   constructor() {\n//│   }\n//│   get Barr() {\n//│     const qualifier = this;\n//│     if (this.#Barr === undefined) {\n//│       class Barr extends Bazz(Fooo(Object)) {\n//│         constructor() {\n//│           super(1, 0);\n//│         }\n//│       }\n//│       this.#Barr = new Barr();\n//│       this.#Barr.class = Barr;\n//│     }\n//│     return this.#Barr;\n//│   }\n//│ }\n//│ const typing_unit16 = new TypingUnit16;\n//│ globalThis.Barr = typing_unit16.Barr;\n//│ // End of generated code\n\nBarr.x\n//│ 0\n//│ res\n//│     = 0\n\nBarr.y\n//│ 1\n//│ res\n//│     = 1\n\n:e\n:ge\nmixin Base {\n  fun x = y\n}\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.368: \t  fun x = y\n//│ ╙──       \t          ^\n//│ mixin Base() {\n//│   fun x: error\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol y\n\n\n:re\nmodule Test extends Base\n//│ module Test {\n//│   fun x: error\n//│ }\n//│ Runtime error:\n//│   ReferenceError: Base is not defined\n\n\nmixin MA(val a: Int)\nmixin MB(val b1: Int, val b2: Int)\nmixin MC(val c: Int)\n//│ mixin MA(a: Int)\n//│ mixin MB(b1: Int, b2: Int)\n//│ mixin MC(c: Int)\n\n:js\nmodule MM extends MA(1), MB(2, 3), MC(4)\n//│ module MM\n//│ // Prelude\n//│ class TypingUnit22 {\n//│   #MM;\n//│   constructor() {\n//│   }\n//│   get MM() {\n//│     const qualifier = this;\n//│     if (this.#MM === undefined) {\n//│       class MM extends MC(MB(MA(Object))) {\n//│         constructor() {\n//│           super(4, 2, 3, 1);\n//│         }\n//│       }\n//│       this.#MM = new MM();\n//│       this.#MM.class = MM;\n//│     }\n//│     return this.#MM;\n//│   }\n//│ }\n//│ const typing_unit22 = new TypingUnit22;\n//│ globalThis.MM = typing_unit22.MM;\n//│ // End of generated code\n\nMM.a\nMM.b1\nMM.b2\nMM.c\n//│ 4\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n//│ res\n//│     = 3\n//│ res\n//│     = 4\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/MixinCapture.mls",
    "content": ":NewDefs\n\n:js\nclass Lit(n: Int)\nmixin EvalAddLit {\n  fun eval(e) =\n    if e is\n      Lit(n) then n\n}\n//│ class Lit(n: Int)\n//│ mixin EvalAddLit() {\n//│   fun eval: Lit -> Int\n//│ }\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #Lit;\n//│   constructor() {\n//│   }\n//│   EvalAddLit(base) {\n//│     const qualifier = this;\n//│     return (class EvalAddLit extends base {\n//│       constructor(...rest) {\n//│         super(...rest);\n//│       }\n//│       eval(e) {\n//│         return ((() => {\n//│           let a;\n//│           return (a = e, a instanceof qualifier.Lit.class ? ((ucs$args_e$Lit) => ((n) => n)(ucs$args_e$Lit[0]))(qualifier.Lit.unapply(e)) : (() => {\n//│             throw new Error(\"non-exhaustive case expression\");\n//│           })());\n//│         })());\n//│       }\n//│     });\n//│   }\n//│   get Lit() {\n//│     const qualifier = this;\n//│     if (this.#Lit === undefined) {\n//│       class Lit {\n//│         #n;\n//│         constructor(n) {\n//│           this.#n = n;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#n];\n//│         }\n//│       };\n//│       this.#Lit = ((n) => Object.freeze(new Lit(n)));\n//│       this.#Lit.class = Lit;\n//│       this.#Lit.unapply = Lit.unapply;\n//│     }\n//│     return this.#Lit;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.Lit = typing_unit.Lit;\n//│ globalThis.EvalAddLit = ((base) => typing_unit.EvalAddLit(base));\n//│ // End of generated code\n\nmodule TestLang extends EvalAddLit\n//│ module TestLang {\n//│   fun eval: Lit -> Int\n//│ }\n\nTestLang.eval(Lit(0))\n//│ Int\n//│ res\n//│     = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Modules.mls",
    "content": ":NewDefs\n\n\nmodule test { // hello\n  fun a = 1\n}\n//│ module test {\n//│   fun a: 1\n//│ }\n\n\n:js\nfun y = 1\nmodule Foo {\n  fun x = y\n}\n//│ fun y: 1\n//│ module Foo {\n//│   fun x: 1\n//│ }\n//│ // Prelude\n//│ class TypingUnit1 {\n//│   #Foo;\n//│   constructor() {\n//│   }\n//│   get Foo() {\n//│     const qualifier = this;\n//│     if (this.#Foo === undefined) {\n//│       class Foo {\n//│         constructor() {\n//│         }\n//│         get x() {\n//│           return y();\n//│         }\n//│       }\n//│       this.#Foo = new Foo();\n//│       this.#Foo.class = Foo;\n//│     }\n//│     return this.#Foo;\n//│   }\n//│ }\n//│ const typing_unit1 = new TypingUnit1;\n//│ globalThis.Foo = typing_unit1.Foo;\n//│ // Query 1\n//│ globalThis.y = function y() {\n//│   return 1;\n//│ };\n//│ // End of generated code\n\n\n:js\nmodule Foo {\n  fun x = y\n}\nfun y = 1\n//│ module Foo {\n//│   fun x: 1\n//│ }\n//│ fun y: 1\n//│ // Prelude\n//│ class TypingUnit2 {\n//│   #Foo;\n//│   constructor() {\n//│   }\n//│   get Foo() {\n//│     const qualifier = this;\n//│     if (this.#Foo === undefined) {\n//│       class Foo {\n//│         constructor() {\n//│         }\n//│         get x() {\n//│           return y1();\n//│         }\n//│       }\n//│       this.#Foo = new Foo();\n//│       this.#Foo.class = Foo;\n//│     }\n//│     return this.#Foo;\n//│   }\n//│ }\n//│ const typing_unit2 = new TypingUnit2;\n//│ globalThis.Foo = typing_unit2.Foo;\n//│ // Query 1\n//│ globalThis.y1 = function y1() {\n//│   return 1;\n//│ };\n//│ // End of generated code\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/MutFields.mls",
    "content": ":NewDefs\n\n\n:js\nmodule Foo {\n  log(\"Creating Foo\")\n  mut val x: Int = 1\n}\n//│ module Foo {\n//│   mut val x: Int\n//│ }\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ let res;\n//│ class TypingUnit {\n//│   #Foo;\n//│   constructor() {\n//│   }\n//│   get Foo() {\n//│     const qualifier = this;\n//│     if (this.#Foo === undefined) {\n//│       class Foo {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         set x($value) { return this.#x = $value; }\n//│         constructor() {\n//│           log(\"Creating Foo\");\n//│           this.#x = 1;\n//│           const x = this.#x;\n//│         }\n//│       }\n//│       this.#Foo = new Foo();\n//│       this.#Foo.class = Foo;\n//│     }\n//│     return this.#Foo;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.Foo = typing_unit.Foo;\n//│ // End of generated code\n\nFoo\n//│ Foo\n//│ res\n//│     = Foo { class: [class Foo] }\n//│ // Output\n//│ Creating Foo\n\nlog(Foo.x)\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ 1\n\n:js\nset Foo.x = Foo.x + 1\n//│ ()\n//│ // Prelude\n//│ class TypingUnit3 {}\n//│ const typing_unit3 = new TypingUnit3;\n//│ // Query 1\n//│ res = void(Foo.x = Foo.x + 1);\n//│ // End of generated code\n//│ res\n//│     = undefined\n\n:js\nlog(Foo.x)\n//│ ()\n//│ // Prelude\n//│ class TypingUnit4 {}\n//│ const typing_unit4 = new TypingUnit4;\n//│ // Query 1\n//│ res = log(Foo.x);\n//│ // End of generated code\n//│ res\n//│     = undefined\n//│ // Output\n//│ 2\n\n\n:e\nset Foo.y = 123\n//│ ╔══[ERROR] Type `Foo` does not contain member `y`\n//│ ║  l.86: \tset Foo.y = 123\n//│ ╙──      \t       ^^\n//│ ()\n//│ res\n//│     = undefined\n\n:e\nFoo.y\n//│ ╔══[ERROR] Type `Foo` does not contain member `y`\n//│ ║  l.95: \tFoo.y\n//│ ╙──      \t   ^^\n//│ error\n//│ res\n//│     = 123\n\n:js\nclass Test {\n  mut val x = 1\n  fun incr =\n    log(x)\n    set x = x + 1\n    log(x)\n}\n//│ class Test {\n//│   constructor()\n//│   fun incr: ()\n//│   mut val x: Int\n//│ }\n//│ // Prelude\n//│ class TypingUnit7 {\n//│   #Test;\n//│   constructor() {\n//│   }\n//│   get Test() {\n//│     const qualifier = this;\n//│     if (this.#Test === undefined) {\n//│       class Test {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         set x($value) { return this.#x = $value; }\n//│         constructor() {\n//│           this.#x = 1;\n//│           const x = this.#x;\n//│         }\n//│         get incr() {\n//│           const qualifier1 = this;\n//│           return ((() => {\n//│             log(qualifier1.x);\n//│             void(qualifier1.x = qualifier1.x + 1);\n//│             return log(qualifier1.x);\n//│           })());\n//│         }\n//│       };\n//│       this.#Test = Test;\n//│     }\n//│     return this.#Test;\n//│   }\n//│ }\n//│ const typing_unit7 = new TypingUnit7;\n//│ globalThis.Test = typing_unit7.Test;\n//│ // End of generated code\n\nlet t = new Test()\n//│ let t: Test\n//│ t\n//│   = Test {}\n\nt.x\n//│ Int\n//│ res\n//│     = 1\n\nt.incr\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ 1\n//│ 2\n\nt.x\n//│ Int\n//│ res\n//│     = 2\n\n\nclass Cont\nclass MySumCont extends Cont {\n  val init(n) = n + 1\n  mut val pc = init(0)\n}\n//│ class Cont {\n//│   constructor()\n//│ }\n//│ class MySumCont extends Cont {\n//│   constructor()\n//│   val init: Int -> Int\n//│   mut val pc: Int\n//│ }\n\nfun f(b) = if b then 0 else new MySumCont\n//│ fun f: Bool -> (0 | MySumCont)\n\n:js\nif f(false) is MySumCont then 1 else 2\n//│ 1 | 2\n//│ // Prelude\n//│ class TypingUnit14 {}\n//│ const typing_unit14 = new TypingUnit14;\n//│ // Query 1\n//│ res = ((ucs$scrut$0) => ucs$scrut$0 instanceof MySumCont ? 1 : 2)(f(false));\n//│ // End of generated code\n//│ res\n//│     = 1\n\nnew MySumCont().init\n//│ Int -> Int\n//│ res\n//│     = [Function (anonymous)]\n\n\n:pe\n:e\n:ng\nclass Test(mut val x: Int)\n//│ ╔══[PARSE ERROR] Unexpected 'val' keyword in expression position\n//│ ║  l.212: \tclass Test(mut val x: Int)\n//│ ╙──       \t               ^^^\n//│ ╔══[ERROR] Unsupported field specification\n//│ ║  l.212: \tclass Test(mut val x: Int)\n//│ ╙──       \t                   ^\n//│ class Test()\n\n\nmodule Foo { val x = 0 }\n//│ module Foo {\n//│   val x: 0\n//│ }\n\n:e\nfun test = set Foo.x = 1\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.228: \tfun test = set Foo.x = 1\n//│ ║         \t           ^^^^^^^^^^^^^\n//│ ╟── member of type `0` is not mutable\n//│ ║  l.222: \tmodule Foo { val x = 0 }\n//│ ║         \t                 ^^^^^\n//│ ╟── but it flows into assigned field with expected type `?x`\n//│ ║  l.228: \tfun test = set Foo.x = 1\n//│ ╙──       \t                  ^^\n//│ fun test: ()\n\ntest\n//│ ()\n//│ res\n//│     = undefined\n\nFoo.x\n//│ 0\n//│ res\n//│     = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NamedArgsCurry.mls",
    "content": ":NewDefs\n\n\n:js\nfun print(x: Int) = (y: Int, z: Int) => log([x, y, z])\nlet p = print(0)\nlet r = p(z: 1, y: 2)\n//│ fun print: (x: Int) -> (y: Int, z: Int) -> ()\n//│ let p: (y: Int, z: Int) -> ()\n//│ let r: ()\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ globalThis.print = function print(x) {\n//│   return ((y, z) => log([\n//│     x,\n//│     y,\n//│     z\n//│   ]));\n//│ };\n//│ // Query 2\n//│ globalThis.p = print(0);\n//│ // Query 3\n//│ globalThis.r = p(2, 1);\n//│ // End of generated code\n//│ p\n//│   = [Function (anonymous)]\n//│ r\n//│   = undefined\n//│ // Output\n//│ [ 0, 2, 1 ]\n\n:js\nfun print(x) = [x, x]\nlet p = print\nlet r = p(1)\n//│ fun print: forall 'a. 'a -> ['a, 'a]\n//│ let p: forall 'a. 'a -> ['a, 'a]\n//│ let r: [1, 1]\n//│ // Prelude\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ globalThis.print1 = function print1(x) {\n//│   return ([\n//│     x,\n//│     x\n//│   ]);\n//│ };\n//│ // Query 2\n//│ globalThis.p1 = print1;\n//│ // Query 3\n//│ globalThis.r1 = p1(1);\n//│ // End of generated code\n//│ p\n//│   = [Function: print1]\n//│ r\n//│   = [ 1, 1 ]\n\n:js\nfun print(x) = (y) => [x, y]\nlet p = print(0)\nlet r = p(1)\n//│ fun print: forall 'a 'b. 'a -> 'b -> ['a, 'b]\n//│ let p: forall 'c. 'c -> [0, 'c]\n//│ let r: [0, 1]\n//│ // Prelude\n//│ class TypingUnit2 {}\n//│ const typing_unit2 = new TypingUnit2;\n//│ // Query 1\n//│ globalThis.print2 = function print2(x) {\n//│   return ((y) => [\n//│     x,\n//│     y\n//│   ]);\n//│ };\n//│ // Query 2\n//│ globalThis.p2 = print2(0);\n//│ // Query 3\n//│ globalThis.r2 = p2(1);\n//│ // End of generated code\n//│ p\n//│   = [Function (anonymous)]\n//│ r\n//│   = [ 0, 1 ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Nested.mls",
    "content": ":NewDefs\n\n:js\nmodule A {\n  val a = 42\n  class B(x: Int) {\n    fun b = x + 1\n  }\n}\n//│ module A {\n//│   class B(x: Int) {\n//│     fun b: Int\n//│   }\n//│   val a: 42\n//│ }\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #B;\n//│         #a;\n//│         get a() { return this.#a; }\n//│         constructor() {\n//│           this.#a = 42;\n//│           const a = this.#a;\n//│         }\n//│         get B() {\n//│           const qualifier1 = this;\n//│           if (this.#B === undefined) {\n//│             class B {\n//│               #x;\n//│               constructor(x) {\n//│                 this.#x = x;\n//│               }\n//│               get b() {\n//│                 const x = this.#x;\n//│                 return x + 1;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#B = ((x) => Object.freeze(new B(x)));\n//│             this.#B.class = B;\n//│             this.#B.unapply = B.unapply;\n//│           }\n//│           return this.#B;\n//│         }\n//│       }\n//│       this.#A = new A();\n//│       this.#A.class = A;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.A = typing_unit.A;\n//│ // End of generated code\n\n:e\n:js\nlet bb = A.B(A.a)\nbb.b\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.69: \tlet bb = A.B(A.a)\n//│ ╙──      \t          ^^\n//│ let bb: error\n//│ error\n//│ // Prelude\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ globalThis.bb = A.B(A.a);\n//│ // Query 2\n//│ res = bb.b;\n//│ // End of generated code\n//│ bb\n//│    = B {}\n//│ res\n//│     = 43\n\n\n:e\nclass B(x: Int) {\n  val outer = 42\n  class C(y: Int) {\n    val outer1 = outer + outer\n  }\n  class D(val outer: Int)\n}\nlet b = B(1)\nb.outer\nlet c = b.C(1)\nc.outer1\nlet d = b.D(1)\nd.outer\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.100: \tlet c = b.C(1)\n//│ ╙──       \t         ^^\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.102: \tlet d = b.D(1)\n//│ ╙──       \t         ^^\n//│ class B(x: Int) {\n//│   class C(y: Int) {\n//│     val outer1: Int\n//│   }\n//│   class D(outer: Int)\n//│   val outer: 42\n//│ }\n//│ let b: B\n//│ let c: error\n//│ let d: error\n//│ error\n//│ b\n//│   = B {}\n//│ res\n//│     = 42\n//│ c\n//│   = C {}\n//│ res\n//│     = 84\n//│ d\n//│   = D {}\n//│ res\n//│     = 1\n\n:js\nmixin C() {\n  mixin D() {\n    mixin E() {}\n  }\n}\n//│ mixin C() {\n//│   mixin D() {\n//│     mixin E()\n//│   }\n//│ }\n//│ // Prelude\n//│ class TypingUnit3 {\n//│   constructor() {\n//│   }\n//│   C(base) {\n//│     const qualifier = this;\n//│     return (class C extends base {\n//│       constructor(...rest) {\n//│         super(...rest);\n//│       }\n//│       D(base) {\n//│         const qualifier1 = this;\n//│         return (class D extends base {\n//│           constructor(...rest) {\n//│             super(...rest);\n//│           }\n//│           E(base) {\n//│             const qualifier2 = this;\n//│             return (class E extends base {\n//│               constructor(...rest) {\n//│                 super(...rest);\n//│               }\n//│             });\n//│           }\n//│         });\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit3 = new TypingUnit3;\n//│ globalThis.C = ((base) => typing_unit3.C(base));\n//│ // End of generated code\n\n:js\nmodule D {\n  class E(val x: Int) {}\n  fun createE(x: Int) = E(x + 1)\n}\n//│ module D {\n//│   class E(x: Int)\n//│   fun createE: (x: Int) -> E\n//│ }\n//│ // Prelude\n//│ class TypingUnit4 {\n//│   #D;\n//│   constructor() {\n//│   }\n//│   get D() {\n//│     const qualifier = this;\n//│     if (this.#D === undefined) {\n//│       class D {\n//│         #E;\n//│         constructor() {\n//│         }\n//│         createE(x) {\n//│           const qualifier1 = this;\n//│           return qualifier1.E(x + 1);\n//│         }\n//│         get E() {\n//│           const qualifier1 = this;\n//│           if (this.#E === undefined) {\n//│             class E {\n//│               #x;\n//│               get x() { return this.#x; }\n//│               constructor(x) {\n//│                 this.#x = x;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#E = ((x) => Object.freeze(new E(x)));\n//│             this.#E.class = E;\n//│             this.#E.unapply = E.unapply;\n//│           }\n//│           return this.#E;\n//│         }\n//│       }\n//│       this.#D = new D();\n//│       this.#D.class = D;\n//│     }\n//│     return this.#D;\n//│   }\n//│ }\n//│ const typing_unit4 = new TypingUnit4;\n//│ globalThis.D = typing_unit4.D;\n//│ // End of generated code\n\n:js\nlet ee = D.createE(42)\nee.x\n//│ let ee: E\n//│ Int\n//│ // Prelude\n//│ class TypingUnit5 {}\n//│ const typing_unit5 = new TypingUnit5;\n//│ // Query 1\n//│ globalThis.ee = D.createE(42);\n//│ // Query 2\n//│ res = ee.x;\n//│ // End of generated code\n//│ ee\n//│    = E {}\n//│ res\n//│     = 43\n\n:js\nclass E(x: Int) {\n  class F(y: Int) {\n    fun sum = x + y\n    class G(z: Int) {\n      fun sum = x + y + z\n    }\n  }\n}\n//│ class E(x: Int) {\n//│   class F(y: Int) {\n//│     class G(z: Int) {\n//│       fun sum: Int\n//│     }\n//│     fun sum: Int\n//│   }\n//│ }\n//│ // Prelude\n//│ class TypingUnit6 {\n//│   #E;\n//│   constructor() {\n//│   }\n//│   get E() {\n//│     const qualifier = this;\n//│     if (this.#E === undefined) {\n//│       class E {\n//│         #F;\n//│         #x;\n//│         constructor(x) {\n//│           this.#x = x;\n//│         }\n//│         get F() {\n//│           const qualifier1 = this;\n//│           if (this.#F === undefined) {\n//│             class F {\n//│               #G;\n//│               #y;\n//│               constructor(y) {\n//│                 this.#y = y;\n//│               }\n//│               get sum() {\n//│                 const y = this.#y;\n//│                 return qualifier1.#x + y;\n//│               }\n//│               get G() {\n//│                 const qualifier2 = this;\n//│                 if (this.#G === undefined) {\n//│                   class G {\n//│                     #z;\n//│                     constructor(z) {\n//│                       this.#z = z;\n//│                     }\n//│                     get sum() {\n//│                       const z = this.#z;\n//│                       return qualifier1.#x + qualifier2.#y + z;\n//│                     }\n//│                   static\n//│                     unapply(x) {\n//│                       return [x.#z];\n//│                     }\n//│                   };\n//│                   this.#G = ((z) => Object.freeze(new G(z)));\n//│                   this.#G.class = G;\n//│                   this.#G.unapply = G.unapply;\n//│                 }\n//│                 return this.#G;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#y];\n//│               }\n//│             };\n//│             this.#F = ((y) => Object.freeze(new F(y)));\n//│             this.#F.class = F;\n//│             this.#F.unapply = F.unapply;\n//│           }\n//│           return this.#F;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       };\n//│       this.#E = ((x) => Object.freeze(new E(x)));\n//│       this.#E.class = E;\n//│       this.#E.unapply = E.unapply;\n//│     }\n//│     return this.#E;\n//│   }\n//│ }\n//│ const typing_unit6 = new TypingUnit6;\n//│ globalThis.E = typing_unit6.E;\n//│ // End of generated code\n\n:e\n:js\nlet es = E(1)\nlet fff = es.F(2)\nlet gg = fff.G(3)\ngg.sum\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.349: \tlet fff = es.F(2)\n//│ ╙──       \t            ^^\n//│ let es: E\n//│ let fff: error\n//│ let gg: error\n//│ error\n//│ // Prelude\n//│ class TypingUnit7 {}\n//│ const typing_unit7 = new TypingUnit7;\n//│ // Query 1\n//│ globalThis.es = E(1);\n//│ // Query 2\n//│ globalThis.fff = es.F(2);\n//│ // Query 3\n//│ globalThis.gg = fff.G(3);\n//│ // Query 4\n//│ res = gg.sum;\n//│ // End of generated code\n//│ es\n//│    = E {}\n//│ fff\n//│     = F {}\n//│ gg\n//│    = G {}\n//│ res\n//│     = 6\n\n:js\nclass F() {\n  let x = 42\n  class G() {\n    let x1 = x + 1\n  }\n}\n//│ class F() {\n//│   class G() {\n//│     let x1: Int\n//│   }\n//│   let x: 42\n//│ }\n//│ // Prelude\n//│ class TypingUnit8 {\n//│   #F;\n//│   constructor() {\n//│   }\n//│   get F() {\n//│     const qualifier = this;\n//│     if (this.#F === undefined) {\n//│       class F {\n//│         #G;\n//│         #x;\n//│         constructor() {\n//│           this.#x = 42;\n//│           const x = this.#x;\n//│         }\n//│         get G() {\n//│           const qualifier1 = this;\n//│           if (this.#G === undefined) {\n//│             class G {\n//│               constructor() {\n//│                 const x1 = qualifier1.#x + 1;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [];\n//│               }\n//│             };\n//│             this.#G = (() => Object.freeze(new G()));\n//│             this.#G.class = G;\n//│             this.#G.unapply = G.unapply;\n//│           }\n//│           return this.#G;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [];\n//│         }\n//│       };\n//│       this.#F = (() => Object.freeze(new F()));\n//│       this.#F.class = F;\n//│       this.#F.unapply = F.unapply;\n//│     }\n//│     return this.#F;\n//│   }\n//│ }\n//│ const typing_unit8 = new TypingUnit8;\n//│ globalThis.F = typing_unit8.F;\n//│ // End of generated code\n\n\n:js\nmodule G {\n  class I(val x: Int) {}\n  module H {\n    fun i1(x: Int) = I(x + 1)\n    class J(x: Int) {\n      fun ii(a: Int) = I(x + a)\n    }\n  }\n}\n//│ module G {\n//│   module H {\n//│     class J(x: Int) {\n//│       fun ii: (a: Int) -> I\n//│     }\n//│     fun i1: (x: Int) -> I\n//│   }\n//│   class I(x: Int)\n//│ }\n//│ // Prelude\n//│ class TypingUnit9 {\n//│   #G;\n//│   constructor() {\n//│   }\n//│   get G() {\n//│     const qualifier = this;\n//│     if (this.#G === undefined) {\n//│       class G {\n//│         #I;\n//│         #H;\n//│         constructor() {\n//│         }\n//│         get H() {\n//│           const qualifier1 = this;\n//│           if (this.#H === undefined) {\n//│             class H {\n//│               #J;\n//│               constructor() {\n//│               }\n//│               i1(x) {\n//│                 return qualifier1.I(x + 1);\n//│               }\n//│               get J() {\n//│                 const qualifier2 = this;\n//│                 if (this.#J === undefined) {\n//│                   class J {\n//│                     #x;\n//│                     constructor(x) {\n//│                       this.#x = x;\n//│                     }\n//│                     ii(a) {\n//│                       const x = this.#x;\n//│                       return qualifier1.I(x + a);\n//│                     }\n//│                   static\n//│                     unapply(x) {\n//│                       return [x.#x];\n//│                     }\n//│                   };\n//│                   this.#J = ((x) => Object.freeze(new J(x)));\n//│                   this.#J.class = J;\n//│                   this.#J.unapply = J.unapply;\n//│                 }\n//│                 return this.#J;\n//│               }\n//│             }\n//│             this.#H = new H();\n//│             this.#H.class = H;\n//│           }\n//│           return this.#H;\n//│         }\n//│         get I() {\n//│           const qualifier1 = this;\n//│           if (this.#I === undefined) {\n//│             class I {\n//│               #x;\n//│               get x() { return this.#x; }\n//│               constructor(x) {\n//│                 this.#x = x;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#I = ((x) => Object.freeze(new I(x)));\n//│             this.#I.class = I;\n//│             this.#I.unapply = I.unapply;\n//│           }\n//│           return this.#I;\n//│         }\n//│       }\n//│       this.#G = new G();\n//│       this.#G.class = G;\n//│     }\n//│     return this.#G;\n//│   }\n//│ }\n//│ const typing_unit9 = new TypingUnit9;\n//│ globalThis.G = typing_unit9.G;\n//│ // End of generated code\n\n\n:e\n:js\nlet jj = G.H.J(42)\nlet i = jj.ii(2)\ni.x\n//│ ╔══[ERROR] Access to module member not yet supported\n//│ ║  l.548: \tlet jj = G.H.J(42)\n//│ ╙──       \t          ^^\n//│ let jj: error\n//│ let i: error\n//│ error\n//│ // Prelude\n//│ class TypingUnit10 {}\n//│ const typing_unit10 = new TypingUnit10;\n//│ // Query 1\n//│ globalThis.jj = G.H.J(42);\n//│ // Query 2\n//│ globalThis.i = jj.ii(2);\n//│ // Query 3\n//│ res = i.x;\n//│ // End of generated code\n//│ jj\n//│    = J {}\n//│ i\n//│   = I {}\n//│ res\n//│     = 44\n\n:js\nmodule H {\n  class I(val x: Int)\n  class J(x: Int) {\n    val i = I(x + 1)\n  }\n}\n//│ module H {\n//│   class I(x: Int)\n//│   class J(x: Int) {\n//│     val i: I\n//│   }\n//│ }\n//│ // Prelude\n//│ class TypingUnit11 {\n//│   #H;\n//│   constructor() {\n//│   }\n//│   get H() {\n//│     const qualifier = this;\n//│     if (this.#H === undefined) {\n//│       class H {\n//│         #I;\n//│         #J;\n//│         constructor() {\n//│         }\n//│         get I() {\n//│           const qualifier1 = this;\n//│           if (this.#I === undefined) {\n//│             class I {\n//│               #x;\n//│               get x() { return this.#x; }\n//│               constructor(x) {\n//│                 this.#x = x;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#I = ((x) => Object.freeze(new I(x)));\n//│             this.#I.class = I;\n//│             this.#I.unapply = I.unapply;\n//│           }\n//│           return this.#I;\n//│         }\n//│         get J() {\n//│           const qualifier1 = this;\n//│           if (this.#J === undefined) {\n//│             class J {\n//│               #x;\n//│               #i;\n//│               get i() { return this.#i; }\n//│               constructor(x) {\n//│                 this.#x = x;\n//│                 this.#i = qualifier1.I(x + 1);\n//│                 const i = this.#i;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#J = ((x) => Object.freeze(new J(x)));\n//│             this.#J.class = J;\n//│             this.#J.unapply = J.unapply;\n//│           }\n//│           return this.#J;\n//│         }\n//│       }\n//│       this.#H = new H();\n//│       this.#H.class = H;\n//│     }\n//│     return this.#H;\n//│   }\n//│ }\n//│ const typing_unit11 = new TypingUnit11;\n//│ globalThis.H = typing_unit11.H;\n//│ // End of generated code\n\n\n:e\n:js\nlet j = H.J(42)\nj.i.x\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.657: \tlet j = H.J(42)\n//│ ╙──       \t         ^^\n//│ let j: error\n//│ error\n//│ // Prelude\n//│ class TypingUnit12 {}\n//│ const typing_unit12 = new TypingUnit12;\n//│ // Query 1\n//│ globalThis.j = H.J(42);\n//│ // Query 2\n//│ res = j.i.x;\n//│ // End of generated code\n//│ j\n//│   = J {}\n//│ res\n//│     = 43\n\n:js\n:e\nclass I(x: Int) {\n  let y = x + 1\n  class J(x: Int) {\n    let y = x + 2\n    fun incY = y + 1\n  }\n}\nlet i = I(1)\nlet ij = i.J(0)\nij.incY\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.687: \tlet ij = i.J(0)\n//│ ╙──       \t          ^^\n//│ class I(x: Int) {\n//│   class J(x: Int) {\n//│     fun incY: Int\n//│     let y: Int\n//│   }\n//│   let y: Int\n//│ }\n//│ let i: I\n//│ let ij: error\n//│ error\n//│ // Prelude\n//│ class TypingUnit13 {\n//│   #I;\n//│   constructor() {\n//│   }\n//│   get I() {\n//│     const qualifier = this;\n//│     if (this.#I === undefined) {\n//│       class I {\n//│         #J;\n//│         #x;\n//│         constructor(x) {\n//│           this.#x = x;\n//│           const y = x + 1;\n//│         }\n//│         get J() {\n//│           const qualifier1 = this;\n//│           if (this.#J === undefined) {\n//│             class J {\n//│               #y;\n//│               #x;\n//│               constructor(x) {\n//│                 this.#x = x;\n//│                 this.#y = x + 2;\n//│                 const y = this.#y;\n//│               }\n//│               get incY() {\n//│                 const x = this.#x;\n//│                 const qualifier2 = this;\n//│                 return qualifier2.#y + 1;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#J = ((x) => Object.freeze(new J(x)));\n//│             this.#J.class = J;\n//│             this.#J.unapply = J.unapply;\n//│           }\n//│           return this.#J;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       };\n//│       this.#I = ((x) => Object.freeze(new I(x)));\n//│       this.#I.class = I;\n//│       this.#I.unapply = I.unapply;\n//│     }\n//│     return this.#I;\n//│   }\n//│ }\n//│ const typing_unit13 = new TypingUnit13;\n//│ globalThis.I = typing_unit13.I;\n//│ // Query 1\n//│ globalThis.i1 = I(1);\n//│ // Query 2\n//│ globalThis.ij = i1.J(0);\n//│ // Query 3\n//│ res = ij.incY;\n//│ // End of generated code\n//│ i\n//│   = I {}\n//│ ij\n//│    = J {}\n//│ res\n//│     = 3\n\n\n:js\nmodule J {\n  class K(x: Int) {}\n  mixin L() {}\n  class M() extends K(1) {}\n  class N(x2: Int) extends K(x2 + 2), L\n}\n//│ module J {\n//│   class K(x: Int)\n//│   mixin L()\n//│   class M() extends K\n//│   class N(x2: Int) extends K\n//│ }\n//│ // Prelude\n//│ class TypingUnit14 {\n//│   #J;\n//│   constructor() {\n//│   }\n//│   get J() {\n//│     const qualifier = this;\n//│     if (this.#J === undefined) {\n//│       class J {\n//│         #K;\n//│         #M;\n//│         #N;\n//│         constructor() {\n//│         }\n//│         L(base) {\n//│           const qualifier1 = this;\n//│           return (class L extends base {\n//│             constructor(...rest) {\n//│               super(...rest);\n//│             }\n//│           });\n//│         }\n//│         get K() {\n//│           const qualifier1 = this;\n//│           if (this.#K === undefined) {\n//│             class K {\n//│               #x;\n//│               constructor(x) {\n//│                 this.#x = x;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#K = ((x) => Object.freeze(new K(x)));\n//│             this.#K.class = K;\n//│             this.#K.unapply = K.unapply;\n//│           }\n//│           return this.#K;\n//│         }\n//│         get M() {\n//│           const qualifier1 = this;\n//│           if (this.#M === undefined) {\n//│             class M extends qualifier1.K.class {\n//│               constructor() {\n//│                 super(1);\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [];\n//│               }\n//│             };\n//│             this.#M = (() => Object.freeze(new M()));\n//│             this.#M.class = M;\n//│             this.#M.unapply = M.unapply;\n//│           }\n//│           return this.#M;\n//│         }\n//│         get N() {\n//│           const qualifier1 = this;\n//│           if (this.#N === undefined) {\n//│             class N extends qualifier1.L(qualifier1.K.class) {\n//│               #x2;\n//│               constructor(x2) {\n//│                 super(x2 + 2);\n//│                 this.#x2 = x2;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x2];\n//│               }\n//│             };\n//│             this.#N = ((x2) => Object.freeze(new N(x2)));\n//│             this.#N.class = N;\n//│             this.#N.unapply = N.unapply;\n//│           }\n//│           return this.#N;\n//│         }\n//│       }\n//│       this.#J = new J();\n//│       this.#J.class = J;\n//│     }\n//│     return this.#J;\n//│   }\n//│ }\n//│ const typing_unit14 = new TypingUnit14;\n//│ globalThis.J = typing_unit14.J;\n//│ // End of generated code\n\n:e\n:js\nlet m = J.M()\nlet n = J.N(2)\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.878: \tlet m = J.M()\n//│ ╙──       \t         ^^\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.879: \tlet n = J.N(2)\n//│ ╙──       \t         ^^\n//│ let m: error\n//│ let n: error\n//│ // Prelude\n//│ class TypingUnit15 {}\n//│ const typing_unit15 = new TypingUnit15;\n//│ // Query 1\n//│ globalThis.m = J.M();\n//│ // Query 2\n//│ globalThis.n = J.N(2);\n//│ // End of generated code\n//│ m\n//│   = M {}\n//│ n\n//│   = N {}\n\n\nmodule K {\n  let x = 1\n  module L {\n    let x = 42\n    class M() {\n      fun f = x\n    }\n  }\n}\n//│ module K {\n//│   module L {\n//│     class M() {\n//│       fun f: 42\n//│     }\n//│     let x: 42\n//│   }\n//│   let x: 1\n//│ }\n\n:e\nlet m = K.L.M()\nm.f\n//│ ╔══[ERROR] Access to module member not yet supported\n//│ ║  l.922: \tlet m = K.L.M()\n//│ ╙──       \t         ^^\n//│ let m: error\n//│ error\n//│ m\n//│   = M {}\n//│ res\n//│     = 42\n\nmodule L {\n  class M(val x: Int) {}\n  module N {\n    module O {\n      class P(y: Int) extends M(y + 1) {}\n    }\n  }\n}\n//│ module L {\n//│   class M(x: Int)\n//│   module N {\n//│     module O {\n//│       class P(y: Int) extends M\n//│     }\n//│   }\n//│ }\n\n:e\nlet op = L.N.O.P(0)\nop.x\n//│ ╔══[ERROR] Access to module member not yet supported\n//│ ║  l.952: \tlet op = L.N.O.P(0)\n//│ ╙──       \t          ^^\n//│ let op: error\n//│ error\n//│ op\n//│    = P {}\n//│ res\n//│     = 1\n\n:js\n:e\nmodule M {\n  module N {\n    fun op(x) = if x is\n      O then 0\n      P then 1\n      _ then 2\n  }\n  class O()\n  class P()\n  fun op(x) = if x is\n    O then 0\n    P then 1\n    _ then 2\n}\nM.N.op(M.P())\n//│ ╔══[ERROR] Access to module member not yet supported\n//│ ║  l.980: \tM.N.op(M.P())\n//│ ╙──       \t ^^\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.980: \tM.N.op(M.P())\n//│ ╙──       \t        ^^\n//│ module M {\n//│   module N {\n//│     fun op: Object -> (0 | 1 | 2)\n//│   }\n//│   class O()\n//│   class P()\n//│   fun op: Object -> (0 | 1 | 2)\n//│ }\n//│ error\n//│ // Prelude\n//│ class TypingUnit20 {\n//│   #M;\n//│   constructor() {\n//│   }\n//│   get M() {\n//│     const qualifier = this;\n//│     if (this.#M === undefined) {\n//│       class M {\n//│         #O;\n//│         #P;\n//│         #N;\n//│         constructor() {\n//│         }\n//│         op(x) {\n//│           let a;\n//│           const qualifier1 = this;\n//│           return a = x, a instanceof qualifier1.O.class ? 0 : a instanceof qualifier1.P.class ? 1 : 2;\n//│         }\n//│         get N() {\n//│           const qualifier1 = this;\n//│           if (this.#N === undefined) {\n//│             class N {\n//│               constructor() {\n//│               }\n//│               op(x) {\n//│                 let a;\n//│                 return a = x, a instanceof qualifier1.O.class ? 0 : a instanceof qualifier1.P.class ? 1 : 2;\n//│               }\n//│             }\n//│             this.#N = new N();\n//│             this.#N.class = N;\n//│           }\n//│           return this.#N;\n//│         }\n//│         get O() {\n//│           const qualifier1 = this;\n//│           if (this.#O === undefined) {\n//│             class O {\n//│               constructor() {\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [];\n//│               }\n//│             };\n//│             this.#O = (() => Object.freeze(new O()));\n//│             this.#O.class = O;\n//│             this.#O.unapply = O.unapply;\n//│           }\n//│           return this.#O;\n//│         }\n//│         get P() {\n//│           const qualifier1 = this;\n//│           if (this.#P === undefined) {\n//│             class P {\n//│               constructor() {\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [];\n//│               }\n//│             };\n//│             this.#P = (() => Object.freeze(new P()));\n//│             this.#P.class = P;\n//│             this.#P.unapply = P.unapply;\n//│           }\n//│           return this.#P;\n//│         }\n//│       }\n//│       this.#M = new M();\n//│       this.#M.class = M;\n//│     }\n//│     return this.#M;\n//│   }\n//│ }\n//│ const typing_unit20 = new TypingUnit20;\n//│ globalThis.M = typing_unit20.M;\n//│ // Query 1\n//│ res = M.N.op(M.P());\n//│ // End of generated code\n//│ res\n//│     = 1\n\n:js\nmodule N {\n  module O {\n    class P() extends Q\n  }\n  class Q()\n}\n//│ module N {\n//│   module O {\n//│     class P() extends Q\n//│   }\n//│   class Q()\n//│ }\n//│ // Prelude\n//│ class TypingUnit21 {\n//│   #N;\n//│   constructor() {\n//│   }\n//│   get N() {\n//│     const qualifier = this;\n//│     if (this.#N === undefined) {\n//│       class N {\n//│         #Q;\n//│         #O;\n//│         constructor() {\n//│         }\n//│         get O() {\n//│           const qualifier1 = this;\n//│           if (this.#O === undefined) {\n//│             class O {\n//│               #P;\n//│               constructor() {\n//│               }\n//│               get P() {\n//│                 const qualifier2 = this;\n//│                 if (this.#P === undefined) {\n//│                   class P extends qualifier1.Q.class {\n//│                     constructor() {\n//│                       super();\n//│                     }\n//│                   static\n//│                     unapply(x) {\n//│                       return [];\n//│                     }\n//│                   };\n//│                   this.#P = (() => Object.freeze(new P()));\n//│                   this.#P.class = P;\n//│                   this.#P.unapply = P.unapply;\n//│                 }\n//│                 return this.#P;\n//│               }\n//│             }\n//│             this.#O = new O();\n//│             this.#O.class = O;\n//│           }\n//│           return this.#O;\n//│         }\n//│         get Q() {\n//│           const qualifier1 = this;\n//│           if (this.#Q === undefined) {\n//│             class Q {\n//│               constructor() {\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [];\n//│               }\n//│             };\n//│             this.#Q = (() => Object.freeze(new Q()));\n//│             this.#Q.class = Q;\n//│             this.#Q.unapply = Q.unapply;\n//│           }\n//│           return this.#Q;\n//│         }\n//│       }\n//│       this.#N = new N();\n//│       this.#N.class = N;\n//│     }\n//│     return this.#N;\n//│   }\n//│ }\n//│ const typing_unit21 = new TypingUnit21;\n//│ globalThis.N = typing_unit21.N;\n//│ // End of generated code\n\n:e\nN.O.P()\n//│ ╔══[ERROR] Access to module member not yet supported\n//│ ║  l.1166: \tN.O.P()\n//│ ╙──        \t ^^\n//│ error\n//│ res\n//│     = P {}\n\n:js\n:e\nclass I(x: Int) {\n  let y = x + 1\n  class J(z: Int) {\n    val a = [x, y, z] \n  }\n}\nI(1).J(3).a\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.1182: \tI(1).J(3).a\n//│ ╙──        \t    ^^\n//│ class I(x: Int) {\n//│   class J(z: Int) {\n//│     val a: [Int, Int, Int]\n//│   }\n//│   let y: Int\n//│ }\n//│ error\n//│ // Prelude\n//│ class TypingUnit23 {\n//│   #I;\n//│   constructor() {\n//│   }\n//│   get I() {\n//│     const qualifier = this;\n//│     if (this.#I === undefined) {\n//│       class I {\n//│         #J;\n//│         #y;\n//│         #x;\n//│         constructor(x) {\n//│           this.#x = x;\n//│           this.#y = x + 1;\n//│           const y = this.#y;\n//│         }\n//│         get J() {\n//│           const qualifier1 = this;\n//│           if (this.#J === undefined) {\n//│             class J {\n//│               #z;\n//│               #a;\n//│               get a() { return this.#a; }\n//│               constructor(z) {\n//│                 this.#z = z;\n//│                 this.#a = [\n//│                   qualifier1.#x,\n//│                   qualifier1.#y,\n//│                   z\n//│                 ];\n//│                 const a = this.#a;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#z];\n//│               }\n//│             };\n//│             this.#J = ((z) => Object.freeze(new J(z)));\n//│             this.#J.class = J;\n//│             this.#J.unapply = J.unapply;\n//│           }\n//│           return this.#J;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       };\n//│       this.#I = ((x) => Object.freeze(new I(x)));\n//│       this.#I.class = I;\n//│       this.#I.unapply = I.unapply;\n//│     }\n//│     return this.#I;\n//│   }\n//│ }\n//│ const typing_unit23 = new TypingUnit23;\n//│ globalThis.I = typing_unit23.I;\n//│ // Query 1\n//│ res = I(1).J(3).a;\n//│ // End of generated code\n//│ res\n//│     = [ 1, 2, 3 ]\n\n\n:js\nfun main =\n  let f(x: Int): Int = if x is\n    0 then 1\n    else g(x - 1)\n  let g(x: Int): Int = f(x)\n  f\n//│ fun main: (x: Int) -> Int\n//│ // Prelude\n//│ class TypingUnit24 {}\n//│ const typing_unit24 = new TypingUnit24;\n//│ // Query 1\n//│ globalThis.main = function main() {\n//│   return ((() => {\n//│     let f = (x) => x === 0 ? 1 : g(x - 1);\n//│     let g = (x) => f(x);\n//│     return f;\n//│   })());\n//│ };\n//│ // End of generated code\n\n:js\nfun mian =\n  class A(x: Int)\n  mixin B()\n  module C\n  A(42)\n//│ fun mian: A\n//│ // Prelude\n//│ class TypingUnit25 {}\n//│ const typing_unit25 = new TypingUnit25;\n//│ // Query 1\n//│ globalThis.mian = function mian() {\n//│   return ((() => {\n//│     const A = (() => {\n//│       class A {\n//│         #x;\n//│         constructor(x) {\n//│           this.#x = x;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       }\n//│       let ctor;\n//│       ctor = ((x) => new A(x));\n//│       ctor.class = A;\n//│       return ctor;\n//│     })();\n//│     const B = (base) => {\n//│       return (class B extends base {\n//│         constructor(...rest) {\n//│           super(...rest);\n//│         }\n//│       });\n//│     };\n//│     const C = (() => {\n//│       class C {}\n//│       let ins;\n//│       ins = new C();\n//│       ins.class = C;\n//│       return ins;\n//│     })();\n//│     return A(42);\n//│   })());\n//│ };\n//│ // End of generated code\n\n:js\nfun mian =\n  mixin B()\n  class A(x: Int) extends B\n  module C extends B\n  [A, C]\n//│ fun mian: [(x: Int) -> A, C]\n//│ // Prelude\n//│ class TypingUnit26 {}\n//│ const typing_unit26 = new TypingUnit26;\n//│ // Query 1\n//│ globalThis.mian1 = function mian1() {\n//│   return ((() => {\n//│     const B = (base) => {\n//│       return (class B extends base {\n//│         constructor(...rest) {\n//│           super(...rest);\n//│         }\n//│       });\n//│     };\n//│     const A = (() => {\n//│       class A extends B(Object) {\n//│         #x;\n//│         constructor(x) {\n//│           super();\n//│           this.#x = x;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x];\n//│         }\n//│       }\n//│       let ctor;\n//│       ctor = ((x) => new A(x));\n//│       ctor.class = A;\n//│       return ctor;\n//│     })();\n//│     const C = (() => {\n//│       class C extends B(Object) {\n//│         constructor() {\n//│           super();\n//│         }\n//│       }\n//│       let ins;\n//│       ins = new C();\n//│       ins.class = C;\n//│       return ins;\n//│     })();\n//│     return ([\n//│       A,\n//│       C\n//│     ]);\n//│   })());\n//│ };\n//│ // End of generated code\n\n:js\nfun main(arg) =\n  let x = arg + 1\n  let foo(y) = x + y\n  class C(u: Int) { fun z = [foo(u), bar] }\n  let bar = x\n  C(123)\n//│ fun main: Int -> C\n//│ // Prelude\n//│ class TypingUnit27 {}\n//│ const typing_unit27 = new TypingUnit27;\n//│ // Query 1\n//│ globalThis.main1 = function main1(arg) {\n//│   return ((() => {\n//│     let x = arg + 1;\n//│     let foo = (y) => x + y;\n//│     const C = (() => {\n//│       class C {\n//│         #u;\n//│         constructor(u) {\n//│           this.#u = u;\n//│         }\n//│         get z() {\n//│           const u = this.#u;\n//│           return ([\n//│             foo(u),\n//│             bar\n//│           ]);\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#u];\n//│         }\n//│       }\n//│       let ctor;\n//│       ctor = ((u) => new C(u));\n//│       ctor.class = C;\n//│       return ctor;\n//│     })();\n//│     let bar = x;\n//│     return C(123);\n//│   })());\n//│ };\n//│ // End of generated code\n\nmodule Test {\n  log(0)\n  module Foo { log(2) }\n  log(1)\n  discard(Foo)\n  log(3)\n  discard(Foo)\n}\n//│ module Test {\n//│   module Foo\n//│ }\n\n:js\nclass Outer1(outer: Int) {\n  log(outer)\n  class Outer2(x: Int) {\n    let outer = x + 1\n  }\n}\n//│ class Outer1(outer: Int) {\n//│   class Outer2(x: Int) {\n//│     let outer: Int\n//│   }\n//│ }\n//│ // Prelude\n//│ class TypingUnit29 {\n//│   #Outer1;\n//│   constructor() {\n//│   }\n//│   get Outer1() {\n//│     const qualifier = this;\n//│     if (this.#Outer1 === undefined) {\n//│       class Outer1 {\n//│         #Outer2;\n//│         #outer;\n//│         constructor(outer) {\n//│           this.#outer = outer;\n//│           log(outer);\n//│         }\n//│         get Outer2() {\n//│           const qualifier1 = this;\n//│           if (this.#Outer2 === undefined) {\n//│             class Outer2 {\n//│               #x;\n//│               constructor(x) {\n//│                 this.#x = x;\n//│                 const outer = x + 1;\n//│               }\n//│             static\n//│               unapply(x) {\n//│                 return [x.#x];\n//│               }\n//│             };\n//│             this.#Outer2 = ((x) => Object.freeze(new Outer2(x)));\n//│             this.#Outer2.class = Outer2;\n//│             this.#Outer2.unapply = Outer2.unapply;\n//│           }\n//│           return this.#Outer2;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#outer];\n//│         }\n//│       };\n//│       this.#Outer1 = ((outer) => Object.freeze(new Outer1(outer)));\n//│       this.#Outer1.class = Outer1;\n//│       this.#Outer1.unapply = Outer1.unapply;\n//│     }\n//│     return this.#Outer1;\n//│   }\n//│ }\n//│ const typing_unit29 = new TypingUnit29;\n//│ globalThis.Outer1 = typing_unit29.Outer1;\n//│ // End of generated code\n"
  },
  {
    "path": "shared/src/test/diff/codegen/New.mls",
    "content": ":NewDefs\n\n\nclass C\n//│ class C {\n//│   constructor()\n//│ }\n\n:js\nnew C\n//│ C\n//│ // Prelude\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ res = new C;\n//│ // End of generated code\n//│ res\n//│     = C {}\n\n:e\n:js\nC()\n//│ ╔══[ERROR] Construction of unparameterized class C should use the `new` keyword\n//│ ║  l.23: \tC()\n//│ ╙──      \t^\n//│ C\n//│ // Prelude\n//│ class TypingUnit2 {}\n//│ const typing_unit2 = new TypingUnit2;\n//│ // Query 1\n//│ res = C();\n//│ // End of generated code\n//│ res\n//│ Runtime error:\n//│   TypeError: Class constructor C cannot be invoked without 'new'\n\n:js\n:e // TODO support first-class classes\nlet c = C\n//│ ╔══[ERROR] Construction of unparameterized class C should use the `new` keyword\n//│ ║  l.40: \tlet c = C\n//│ ╙──      \t        ^\n//│ let c: () -> C\n//│ // Prelude\n//│ class TypingUnit3 {}\n//│ const typing_unit3 = new TypingUnit3;\n//│ // Query 1\n//│ globalThis.c = C;\n//│ // End of generated code\n//│ c\n//│   = [class C]\n\n:re // TODO should eventually be reject in type checking\nc()\n//│ C\n//│ res\n//│ Runtime error:\n//│   TypeError: Class constructor C cannot be invoked without 'new'\n\n\nclass C()\n//│ class C()\n\n:js\nnew C\n//│ C\n//│ // Prelude\n//│ class TypingUnit6 {}\n//│ const typing_unit6 = new TypingUnit6;\n//│ // Query 1\n//│ res = new C.class;\n//│ // End of generated code\n//│ res\n//│     = C {}\n\n:js\nC()\n//│ C\n//│ // Prelude\n//│ class TypingUnit7 {}\n//│ const typing_unit7 = new TypingUnit7;\n//│ // Query 1\n//│ res = C();\n//│ // End of generated code\n//│ res\n//│     = C {}\n\n:js\nlet c = C\n//│ let c: () -> C\n//│ // Prelude\n//│ class TypingUnit8 {}\n//│ const typing_unit8 = new TypingUnit8;\n//│ // Query 1\n//│ globalThis.c1 = C;\n//│ // End of generated code\n//│ c\n//│   = [Function (anonymous)] {\n//│       class: [class C],\n//│       unapply: [Function: unapply]\n//│     }\n\nc()\n//│ C\n//│ res\n//│     = C {}\n\n\n:js\nclass X(val a: Int)\nnew X(1).a\n//│ class X(a: Int)\n//│ Int\n//│ // Prelude\n//│ class TypingUnit10 {\n//│   #X;\n//│   constructor() {\n//│   }\n//│   get X() {\n//│     const qualifier = this;\n//│     if (this.#X === undefined) {\n//│       class X {\n//│         #a;\n//│         get a() { return this.#a; }\n//│         constructor(a) {\n//│           this.#a = a;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#a];\n//│         }\n//│       };\n//│       this.#X = ((a) => Object.freeze(new X(a)));\n//│       this.#X.class = X;\n//│       this.#X.unapply = X.unapply;\n//│     }\n//│     return this.#X;\n//│   }\n//│ }\n//│ const typing_unit10 = new TypingUnit10;\n//│ globalThis.X = typing_unit10.X;\n//│ // Query 1\n//│ res = new X.class(1).a;\n//│ // End of generated code\n//│ res\n//│     = 1\n\n:js\nclass X {\n  val a = 1\n}\n(new X).a\n//│ class X {\n//│   constructor()\n//│   val a: 1\n//│ }\n//│ 1\n//│ // Prelude\n//│ class TypingUnit11 {\n//│   #X;\n//│   constructor() {\n//│   }\n//│   get X() {\n//│     const qualifier = this;\n//│     if (this.#X === undefined) {\n//│       class X {\n//│         #a;\n//│         get a() { return this.#a; }\n//│         constructor() {\n//│           this.#a = 1;\n//│           const a = this.#a;\n//│         }\n//│       };\n//│       this.#X = X;\n//│     }\n//│     return this.#X;\n//│   }\n//│ }\n//│ const typing_unit11 = new TypingUnit11;\n//│ globalThis.X = typing_unit11.X;\n//│ // Query 1\n//│ res = (new X).a;\n//│ // End of generated code\n//│ res\n//│     = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NewClasses.mls",
    "content": ":NewDefs\n\n\nclass C[A](n: A) {\n  fun f = g\n  fun g = 0\n}\n//│ class C[A](n: A) {\n//│   fun f: 0\n//│   fun g: 0\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NewMatching.mls",
    "content": ":NewDefs\n\nclass V0()\nclass V1(val x: Int)\nclass V2(x: Int, y: Int)\nclass Pos(x: Int)\nclass V22(c1: V2, c2: V2)\nclass Half(invalid: Int, valid: Int)\nclass None(no: Int)\n//│ class V0()\n//│ class V1(x: Int)\n//│ class V2(x: Int, y: Int)\n//│ class Pos(x: Int)\n//│ class V22(c1: V2, c2: V2)\n//│ class Half(invalid: Int, valid: Int)\n//│ class None(no: Int)\n\nV2.unapply(V2(114, 514))\n//│ [Int, Int]\n//│ res\n//│     = [ 114, 514 ]\n\n:js\nfun sum(v) =\n  if v is\n    V0() then 0\n    V1(a) then a\n    V2(a, b) then a + b\n    Pos(x) and x > 0 then x\n    V22(V2(x1, y1), V2(x2, y2)) then x1 + y1 + x2 + y2\n    Half(_, x) then x\n    None(_) then 0\n    _ then -1\n//│ fun sum: Object -> Int\n//│ // Prelude\n//│ class TypingUnit2 {}\n//│ const typing_unit2 = new TypingUnit2;\n//│ // Query 1\n//│ globalThis.sum = function sum(v) {\n//│   return ((() => {\n//│     let a;\n//│     return a = v, a instanceof V0.class ? 0 : a instanceof V22.class ? ((ucs$args_v$V22) => ((v$V22_0) => ((v$V22_1) => v$V22_0 instanceof V2.class ? ((ucs$args_v$V22_0$V2) => ((x1) => ((y1) => v$V22_1 instanceof V2.class ? ((ucs$args_v$V22_1$V2) => ((x2) => ((y2) => x1 + y1 + x2 + y2)(ucs$args_v$V22_1$V2[1]))(ucs$args_v$V22_1$V2[0]))(V2.unapply(v$V22_1)) : -1)(ucs$args_v$V22_0$V2[1]))(ucs$args_v$V22_0$V2[0]))(V2.unapply(v$V22_0)) : -1)(ucs$args_v$V22[1]))(ucs$args_v$V22[0]))(V22.unapply(v)) : a instanceof V2.class ? ((ucs$args_v$V2) => ((a) => ((b) => a + b)(ucs$args_v$V2[1]))(ucs$args_v$V2[0]))(V2.unapply(v)) : a instanceof V1.class ? ((ucs$args_v$V1) => ((a) => a)(ucs$args_v$V1[0]))(V1.unapply(v)) : a instanceof Pos.class ? ((ucs$args_v$Pos) => ((x) => ((ucs$test$0) => ucs$test$0 === true ? x : -1)(x > 0))(ucs$args_v$Pos[0]))(Pos.unapply(v)) : a instanceof None.class ? 0 : a instanceof Half.class ? ((ucs$args_v$Half) => ((x) => x)(ucs$args_v$Half[1]))(Half.unapply(v)) : -1;\n//│   })());\n//│ };\n//│ // End of generated code\n\nsum(V0())\nsum(V1(42))\nsum(V2(1, 1))\nsum(Pos(1))\nsum(Pos(0))\nsum(V22(V2(1, 2), V2(3, 4)))\nsum(Half(-1, 1))\nsum(None(42))\nsum(42)\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 42\n//│ res\n//│     = 2\n//│ res\n//│     = 1\n//│ res\n//│     = -1\n//│ res\n//│     = 10\n//│ res\n//│     = 1\n//│ res\n//│     = 0\n//│ res\n//│     = -1\n\nclass Some[out T](val value: T)\n//│ class Some[T](value: T)\n\n:js\nfun get1(s) =\n  if s is\n    Some(V1(x)) then x\n    Some(y) then y\n//│ fun get1: forall 'a. Some[Object & 'a] -> (Int | 'a)\n//│ // Prelude\n//│ class TypingUnit5 {}\n//│ const typing_unit5 = new TypingUnit5;\n//│ // Query 1\n//│ globalThis.get1 = function get1(s) {\n//│   return ((() => {\n//│     let a;\n//│     return (a = s, a instanceof Some.class ? ((ucs$args_s$Some) => ((s$Some_0) => s$Some_0 instanceof V1.class ? ((ucs$args_s$Some_0$V1) => ((x) => x)(ucs$args_s$Some_0$V1[0]))(V1.unapply(s$Some_0)) : ((y) => y)(ucs$args_s$Some[0]))(ucs$args_s$Some[0]))(Some.unapply(s)) : (() => {\n//│       throw new Error(\"non-exhaustive case expression\");\n//│     })());\n//│   })());\n//│ };\n//│ // End of generated code\n\nget1(Some(V1(1)))\nget1(Some(V0()))\n//│ Int | V0\n//│ res\n//│     = 1\n//│ res\n//│     = V0 {}\n\nlet s2 = Some(1)\n//│ let s2: Some[1]\n//│ s2\n//│    = Some {}\n\n:js\nfun foo(s) =\n  if s is\n    Some(t) then let b = s2.value in b + t.x\n    _ then 0  \n//│ fun foo: (Object & ~#Some | Some[{x: Int}]) -> Int\n//│ // Prelude\n//│ class TypingUnit8 {}\n//│ const typing_unit8 = new TypingUnit8;\n//│ // Query 1\n//│ globalThis.foo = function foo(s) {\n//│   return ((() => {\n//│     return s instanceof Some.class ? ((ucs$args_s$Some) => ((t) => ((b) => b + t.x)(s2.value))(ucs$args_s$Some[0]))(Some.unapply(s)) : 0;\n//│   })());\n//│ };\n//│ // End of generated code\n\nfoo(Some(V1(12)))\n//│ Int\n//│ res\n//│     = 13\n\nfun bar(s) =\n  if s is\n    Some(_) then let b = s2.value in b + 1\n    _ then 0\n//│ fun bar: (Object & ~#Some | Some[anything]) -> Int\n\nbar(Some(V1(12)))\n//│ Int\n//│ res\n//│     = 2\n\n:js\nclass FooBar {\n  val x = 42\n}\n//│ class FooBar {\n//│   constructor()\n//│   val x: 42\n//│ }\n//│ // Prelude\n//│ class TypingUnit12 {\n//│   #FooBar;\n//│   constructor() {\n//│   }\n//│   get FooBar() {\n//│     const qualifier = this;\n//│     if (this.#FooBar === undefined) {\n//│       class FooBar {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         constructor() {\n//│           this.#x = 42;\n//│           const x = this.#x;\n//│         }\n//│       };\n//│       this.#FooBar = FooBar;\n//│     }\n//│     return this.#FooBar;\n//│   }\n//│ }\n//│ const typing_unit12 = new TypingUnit12;\n//│ globalThis.FooBar = typing_unit12.FooBar;\n//│ // End of generated code\n\n:js\nfun t(x) =\n  if x is\n    FooBar then 1\n    _ then 0\n//│ fun t: Object -> (0 | 1)\n//│ // Prelude\n//│ class TypingUnit13 {}\n//│ const typing_unit13 = new TypingUnit13;\n//│ // Query 1\n//│ globalThis.t = function t(x) {\n//│   return ((() => {\n//│     return x instanceof FooBar ? 1 : 0;\n//│   })());\n//│ };\n//│ // End of generated code\n\nt(new FooBar())\n//│ 0 | 1\n//│ res\n//│     = 1\n\n:e\nfun ft(x) =\n  if x is\n    FooBar(x) then x\n    _ then 0\n//│ ╔══[ERROR] Construction of unparameterized class FooBar should use the `new` keyword\n//│ ║  l.203: \t    FooBar(x) then x\n//│ ╙──       \t    ^^^^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.203: \t    FooBar(x) then x\n//│ ║         \t    ^^^^^^\n//│ ╙── reference of type `() -> FooBar` does not have field 'unapply'\n//│ fun ft: Object -> (0 | error)\n\n:js\nmodule MM\nfun m(x) =\n  if x is\n    MM then 1\n    _ then 0\n//│ module MM\n//│ fun m: Object -> (0 | 1)\n//│ // Prelude\n//│ class TypingUnit16 {\n//│   #MM;\n//│   constructor() {\n//│   }\n//│   get MM() {\n//│     const qualifier = this;\n//│     if (this.#MM === undefined) {\n//│       class MM {}\n//│       this.#MM = new MM();\n//│       this.#MM.class = MM;\n//│     }\n//│     return this.#MM;\n//│   }\n//│ }\n//│ const typing_unit16 = new TypingUnit16;\n//│ globalThis.MM = typing_unit16.MM;\n//│ // Query 1\n//│ globalThis.m = function m(x) {\n//│   return ((() => {\n//│     return x instanceof MM.class ? 1 : 0;\n//│   })());\n//│ };\n//│ // End of generated code\n\n:e\nclass VVC(v: Int, vc: Int)\nfun c(x) =\n  if x is\n    VVC(x, y, z) then x + y + z\n    _ then 0\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ╟── tuple literal of type `{0: ?#v, 1: ?#vc}` does not have field '2'\n//│ ║  l.248: \tclass VVC(v: Int, vc: Int)\n//│ ║         \t          ^^^^^^^^^^\n//│ ╟── but it flows into operator application with expected type `{2: ?a}`\n//│ ║  l.250: \t  if x is\n//│ ║         \t     ^^^^\n//│ ║  l.251: \t    VVC(x, y, z) then x + y + z\n//│ ╙──       \t^^^^^^^\n//│ class VVC(v: Int, vc: Int)\n//│ fun c: Object -> Int\n\n\n\n// * Testing polymorphic `unapply`\n\nclass C[A](f: A -> A)\n//│ class C[A](f: A -> A)\n\nlet r = C.unapply\n//│ let r: forall '#f. (C[?] & {#f: '#f}) -> ['#f]\n//│ r\n//│   = [Function: unapply]\n\nlet r2 = r(C(succ))\n//│ let r2: [Int -> Int]\n//│ r2\n//│    = [ [Function: succ] ]\n\nlet r3 = (([f]) => f) of r2\n//│ let r3: Int -> Int\n//│ r3\n//│    = [Function: succ]\n\nr3(123)\n//│ Int\n//│ res\n//│     = 124\n\nlet r4 = r(C(id))\n//│ let r4: ['A -> 'A]\n//│ r4\n//│    = [ [Function: id] ]\n\n// * Notice that the type is not generalized (lack of distributivity?)\nlet g = (([f]) => f) of r4\n//│ let g: 'A -> 'A\n//│ g\n//│   = [Function: id]\n\ng(0)\n//│ 0\n//│ res\n//│     = 0\n\n// * Approximated type\ng(true)\n//│ 0 | true\n//│ res\n//│     = true\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NewMutualRef.mls",
    "content": ":NewDefs\n\n:js\nfun foo: Int -> Int\nfun foo = x => x + 1 // <- This will be added as a value symbol before translating `Bar`.\nclass Bar {\n  fun calc(x) = foo(x)\n}\n//│ fun foo: Int -> Int\n//│ class Bar {\n//│   constructor()\n//│   fun calc: Int -> Int\n//│ }\n//│ fun foo: Int -> Int\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #Bar;\n//│   constructor() {\n//│   }\n//│   get Bar() {\n//│     const qualifier = this;\n//│     if (this.#Bar === undefined) {\n//│       class Bar {\n//│         constructor() {\n//│         }\n//│         calc(x) {\n//│           return foo(x);\n//│         }\n//│       };\n//│       this.#Bar = Bar;\n//│     }\n//│     return this.#Bar;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.Bar = typing_unit.Bar;\n//│ // Query 1 is empty\n//│ // Query 2\n//│ globalThis.foo = function foo(x) {\n//│   return x + 1;\n//│ };\n//│ // End of generated code\n\n// Note: This test case looks trivial but it was like:\n//\n// ```\n// :re\n// (new Bar()).calc(0)\n// //│ Int\n// //│ res\n// //│ Runtime error:\n// //│   ReferenceError: foo is not defined\n// ```\n//\n// My fix is a little bit hacky. The root of the problem is: when generating\n// code within a class, we need all top-level bindings to be accessible. This\n// part of implementation of new-definition-typing chose to declare all term\n// `NuFunDef` as `ValueSymbol` in advance, but this can lead to the fact that\n// the same symbol is declared multiple times, thus wasting some runtime names.\n// Consequently, the code that references these wasted runtime names are invalid.\n// \n// Actually, I have a better solution, but it requires adjusting the order of\n// translation, and I don't have much time to spend on this at the moment. So，\n// my current fix is rather hacky. But I will complete this part after `PreTyper`\n// is finished, when I replacing the old Scope with the new Scope.\n//\n//                                                      Luyu Cheng on 2023/12/30\n(new Bar()).calc(0)\n//│ Int\n//│ res\n//│     = 1\n\n:js\nfun foo: Int -> Int\nfun foo = x => x + 1\nclass Bar { fun calc(x) = foo(x) }\n//│ fun foo: Int -> Int\n//│ class Bar {\n//│   constructor()\n//│   fun calc: Int -> Int\n//│ }\n//│ fun foo: Int -> Int\n//│ // Prelude\n//│ class TypingUnit2 {\n//│   #Bar;\n//│   constructor() {\n//│   }\n//│   get Bar() {\n//│     const qualifier = this;\n//│     if (this.#Bar === undefined) {\n//│       class Bar {\n//│         constructor() {\n//│         }\n//│         calc(x) {\n//│           return foo1(x);\n//│         }\n//│       };\n//│       this.#Bar = Bar;\n//│     }\n//│     return this.#Bar;\n//│   }\n//│ }\n//│ const typing_unit2 = new TypingUnit2;\n//│ globalThis.Bar = typing_unit2.Bar;\n//│ // Query 1 is empty\n//│ // Query 2\n//│ globalThis.foo1 = function foo1(x) {\n//│   return x + 1;\n//│ };\n//│ // End of generated code\n\nfoo(0)\nnew Bar().calc(0)\n//│ Int\n//│ res\n//│     = 1\n//│ res\n//│     = 1\n\n:js\nclass Bar { fun calc(x) = foo }\nfun foo: Int\nfun foo = 123\n//│ class Bar {\n//│   constructor()\n//│   fun calc: anything -> Int\n//│ }\n//│ fun foo: 123\n//│ fun foo: Int\n//│ // Prelude\n//│ class TypingUnit4 {\n//│   #Bar;\n//│   constructor() {\n//│   }\n//│   get Bar() {\n//│     const qualifier = this;\n//│     if (this.#Bar === undefined) {\n//│       class Bar {\n//│         constructor() {\n//│         }\n//│         calc(x) {\n//│           return foo2();\n//│         }\n//│       };\n//│       this.#Bar = Bar;\n//│     }\n//│     return this.#Bar;\n//│   }\n//│ }\n//│ const typing_unit4 = new TypingUnit4;\n//│ globalThis.Bar = typing_unit4.Bar;\n//│ // Query 1 is empty\n//│ // Query 2\n//│ globalThis.foo2 = function foo2() {\n//│   return 123;\n//│ };\n//│ // End of generated code\n\nfoo\nnew Bar().calc(0)\n//│ Int\n//│ res\n//│     = 123\n//│ res\n//│     = 123\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NuClasses.mls",
    "content": ":NewDefs\n\n:js\nclass Test(val n: Int) {\n  fun inc = Test(n + 1)\n}\n//│ class Test(n: Int) {\n//│   fun inc: Test\n//│ }\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #Test;\n//│   constructor() {\n//│   }\n//│   get Test() {\n//│     const qualifier = this;\n//│     if (this.#Test === undefined) {\n//│       class Test {\n//│         #n;\n//│         get n() { return this.#n; }\n//│         constructor(n) {\n//│           this.#n = n;\n//│         }\n//│         get inc() {\n//│           const n = this.#n;\n//│           return qualifier.Test(n + 1);\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#n];\n//│         }\n//│       };\n//│       this.#Test = ((n) => Object.freeze(new Test(n)));\n//│       this.#Test.class = Test;\n//│       this.#Test.unapply = Test.unapply;\n//│     }\n//│     return this.#Test;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.Test = typing_unit.Test;\n//│ // End of generated code\n\nTest(0).inc.n\n//│ Int\n//│ res\n//│     = 1\n\nclass Test2(val n: Int) {\n  fun inc = Test3.inc(n)\n}\nmodule Test3 {\n  fun inc(n) = Test2(n + 1)\n}\n//│ class Test2(n: Int) {\n//│   fun inc: Test2\n//│ }\n//│ module Test3 {\n//│   fun inc: Int -> Test2\n//│ }\n\nTest2(0).inc.n\n//│ Int\n//│ res\n//│     = 1\n\nclass C[out A](n: A) {\n  fun f = g\n  fun g = n\n}\n//│ class C[A](n: A) {\n//│   fun f: A\n//│   fun g: A\n//│ }\n\n:e\nlet a = C[Int](42)\na.f\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.78: \tlet a = C[Int](42)\n//│ ╙──      \t        ^^^^^^\n//│ let a: C[42]\n//│ 42\n//│ a\n//│   = C {}\n//│ res\n//│     = 42\n\n\nmodule Foo {\n  fun f = C0()\n  class C0()\n}\n//│ module Foo {\n//│   class C0()\n//│   fun f: C0\n//│ }\n\n\nmixin M0(n: Int) {\n  val m = n // this refers to specifically the `n` we had in parameter, not necessarily this.n\n  fun bar = m\n  fun foo = [n, m, bar] // should this be the same as `[this.n, this.m, this.bar]`?\n}\n//│ mixin M0(n: Int) {\n//│   fun bar: Int\n//│   fun foo: [Int, Int, Int]\n//│   val m: Int\n//│ }\n\nmodule M1 extends M0(123) {\n  fun n = \"n\"\n  fun m = \"m\"\n  fun bar = \"bar\"\n}\n//│ module M1 {\n//│   fun bar: \"bar\"\n//│   fun foo: [Int, Int, Int]\n//│   fun m: \"m\"\n//│   fun n: \"n\"\n//│ }\n\n[M1.n, M1.m, M1.bar]\n//│ [\"n\", \"m\", \"bar\"]\n//│ res\n//│     = [ 'n', 'm', 'bar' ]\n\n// FIXME typing/runtime mismatch\nM1.foo\n//│ [Int, Int, Int]\n//│ res\n//│     = [ 123, 'm', 'bar' ]\n\n:e\n:js\nmodule M2 {\n  val m = 100\n  fun foo(y) =\n    fun bar(x) = x + y + this.m\n    bar(10)\n}\n//│ ╔══[ERROR] Cannot use `val` or `fun` in local block; use `let` instead.\n//│ ║  l.140: \t    fun bar(x) = x + y + this.m\n//│ ╙──       \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.140: \t    fun bar(x) = x + y + this.m\n//│ ╙──       \t                             ^^\n//│ module M2 {\n//│   fun foo: Int -> Int\n//│   val m: 100\n//│ }\n//│ // Prelude\n//│ class TypingUnit11 {\n//│   #M2;\n//│   constructor() {\n//│   }\n//│   get M2() {\n//│     const qualifier = this;\n//│     if (this.#M2 === undefined) {\n//│       class M2 {\n//│         #m;\n//│         get m() { return this.#m; }\n//│         constructor() {\n//│           this.#m = 100;\n//│           const m = this.#m;\n//│         }\n//│         foo(y) {\n//│           const qualifier1 = this;\n//│           return ((() => {\n//│             let bar = (x) => x + y + qualifier1.m;\n//│             return bar(10);\n//│           })());\n//│         }\n//│       }\n//│       this.#M2 = new M2();\n//│       this.#M2.class = M2;\n//│     }\n//│     return this.#M2;\n//│   }\n//│ }\n//│ const typing_unit11 = new TypingUnit11;\n//│ globalThis.M2 = typing_unit11.M2;\n//│ // End of generated code\n\nM2.foo(1)\n//│ Int\n//│ res\n//│     = 111\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NuFuns.mls",
    "content": ":NewDefs\n\n\n:js\nfun foo =\n  let bar(x) = x + 1\n  bar(10)\n//│ fun foo: Int\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ globalThis.foo = function foo() {\n//│   return ((() => {\n//│     let bar = (x) => x + 1;\n//│     return bar(10);\n//│   })());\n//│ };\n//│ // End of generated code\n\nfun foo =\n  class C(a: Int) { fun bar(x) = a + x + 1 }\n  C(100).bar(10)\nfoo\n//│ fun foo: Int\n//│ Int\n//│ res\n//│     = 111\n\n\nfun main =\n  log(\"Hello\")\nmain\n//│ fun main: ()\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ Hello\n\nfun main =\n  log(\"Hello\")\n//│ fun main: ()\n\nmain\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ Hello\n\n\nfun main =\n  mixin B { log(1) }\n  log(0)\n  module M extends B\n  log(2)\nmain\n//│ fun main: ()\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ 0\n//│ 1\n//│ 2\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NuParentheses.mls",
    "content": ":NewDefs\n\n\n:js\n16 / (2 / 2)\n//│ Num\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ res = 16 / (2 / 2);\n//│ // End of generated code\n//│ res\n//│     = 16\n\n:js\n1 - (3 - 5)\n//│ Int\n//│ // Prelude\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ res = 1 - (3 - 5);\n//│ // End of generated code\n//│ res\n//│     = 3\n\n\nfun (--) minusminus(a, b) = a - b\n//│ fun (--) minusminus: (Int, Int) -> Int\n\n:js\n1 -- (3 -- 5)\n//│ Int\n//│ // Prelude\n//│ class TypingUnit3 {}\n//│ const typing_unit3 = new TypingUnit3;\n//│ // Query 1\n//│ res = minusminus(1, minusminus(3, 5));\n//│ // End of generated code\n//│ res\n//│     = 3\n\n\nfun (-+-) complex(a, b) = a - 2*b\n//│ fun (-+-) complex: (Int, Int) -> Int\n\n:js\n1 -+- (3 -+- 5)\n//│ Int\n//│ // Prelude\n//│ class TypingUnit5 {}\n//│ const typing_unit5 = new TypingUnit5;\n//│ // Query 1\n//│ res = complex(1, complex(3, 5));\n//│ // End of generated code\n//│ res\n//│     = 15\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/NuReplHost.mls",
    "content": ":NewDefs\n\n\n// * This should crash due to `error`,\n// * but the crash is somehow swallowed and we get the result of the previous statement instead!\n// * The same happens with any other side effect, like `log(...)`\n// * Note: this doesn't happen if the last line is in a spearate diff-test block\n:showRepl\n:re\nfun foo(x) = error\nlet r = foo(1)\n//│ fun foo: anything -> nothing\n//│ let r: nothing\n//│ ┌ Block at NuReplHost.mls:10\n//│ ├─┬ Prelude\n//│ │ ├── Code\n//│ │ │   function error() {\n//│ │ │     throw new Error(\"an error was thrown\");\n//│ │ │   }\n//│ │ │   let res;\n//│ │ │   class TypingUnit {}\n//│ │ │   const typing_unit = new TypingUnit;\n//│ │ └── Reply\n//│ │     undefined\n//│ ├─┬ Query 1/2\n//│ │ ├── Prelude: <empty>\n//│ │ ├── Code:\n//│ │ ├──   globalThis.foo = function foo(x) {\n//│ │ ├──     return error();\n//│ │ ├──   };\n//│ │ ├── Intermediate: [Function: foo]\n//│ │ └── Reply: [success] [Function: foo]\n//│ └─┬ Query 2/2\n//│   ├── Prelude: <empty>\n//│   ├── Code:\n//│   ├──   globalThis.r = foo(1);\n//│   └── Reply: [runtime error] Error: an error was thrown\n//│ r\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nr\n//│ nothing\n//│ res\n//│ Runtime error:\n//│   ReferenceError: r is not defined\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/ParameterPattern.mls",
    "content": "// This test file ensures that parameter destruction patterns are translated correctly.\n()\n//│ res: ()\n//│    = []\n\n:js\ndef volatile ((this, break)) = this + break\n//│ // Query 1\n//│ globalThis.volatile1 = function volatile1([\n//│   this$,\n//│   break$\n//│ ]) {\n//│   return this$ + break$;\n//│ };\n//│ // End of generated code\n//│ volatile: ((int, int,),) -> int\n//│         = [Function: volatile1]\n\n:js\ndef volatile1 { debugger; continue } = debugger + continue\n//│ // Query 1\n//│ globalThis.volatile11 = function volatile11({\n//│   \"debugger\": debugger$,\n//│   \"continue\": continue$\n//│ }) {\n//│   return debugger$ + continue$;\n//│ };\n//│ // End of generated code\n//│ volatile1: {continue: int, debugger: int} -> int\n//│          = [Function: volatile11]\n\n:js\ndef volatile2 export = export + 2\n//│ // Query 1\n//│ globalThis.volatile2 = function volatile2(export$) {\n//│   return export$ + 2;\n//│ };\n//│ // End of generated code\n//│ volatile2: int -> int\n//│          = [Function: volatile2]\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Parentheses.mls",
    "content": "()\nadd\nmul\nid\n//│ res: ()\n//│    = []\n//│ res: int -> int -> int\n//│    = [Function: add]\n//│ res: int -> int -> int\n//│    = [Function: mul]\n//│ res: 'a -> 'a\n//│    = [Function: id]\n\n// Simple expressions.\n:e\n:js\n1 + 1 * 2 / 4 - 5\n//│ // Query 1\n//│ res = 1 + 1 * 2 / 4 - 5;\n//│ // End of generated code\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.17: \t1 + 1 * 2 / 4 - 5\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── operator application of type `number` is not an instance of type `int`\n//│ ║  l.17: \t1 + 1 * 2 / 4 - 5\n//│ ╙──      \t    ^^^^^^^^^\n//│ res: int\n//│    = -3.5\n\n:e\n:js\n1 * (2 + 3) / 4 - 5\n//│ // Query 1\n//│ res = 1 * (2 + 3) / 4 - 5;\n//│ // End of generated code\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.32: \t1 * (2 + 3) / 4 - 5\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `number` is not an instance of type `int`\n//│ ║  l.32: \t1 * (2 + 3) / 4 - 5\n//│ ╙──      \t^^^^^^^^^^^^^^^\n//│ res: error | int\n//│    = -3.75\n\n:js\nx = 0\nx > 0 && x < 0\n//│ // Query 1\n//│ globalThis.x = 0;\n//│ // Query 2\n//│ res = x > 0 && x < 0;\n//│ // End of generated code\n//│ x: 0\n//│  = 0\n//│ res: bool\n//│    = false\n\n// Some complicated expressions.\n:js\n1 + (if (case x + 1 of { int -> 8 | string -> 9 }) == 3 then 2 else 3)\n//│ // Query 1\n//│ let a;\n//│ res = 1 + ((a = x + 1, Number.isInteger(a) ? 8 : a.constructor === String ? 9 : (() => {\n//│   throw new Error(\"non-exhaustive case expression\");\n//│ })()) == 3 ? 2 : 3);\n//│ // End of generated code\n//│ res: int\n//│    = 4\n\n:js\ncase x of { int -> 1 | string -> 0 }\n//│ // Query 1\n//│ let b;\n//│ res = (b = x, Number.isInteger(b) ? 1 : b.constructor === String ? 0 : (() => {\n//│   throw new Error(\"non-exhaustive case expression\");\n//│ })());\n//│ // End of generated code\n//│ res: 0 | 1\n//│    = 1\n\n// When generating comma expressions in comma-separated lists, don't forget to\n// wrap the expression in parentheses.\n:js\n(case x of { int -> 1 | string -> 0 }, case x of { int -> 1 | string -> 0 })\n//│ // Query 1\n//│ let c, d;\n//│ res = [\n//│   (c = x, Number.isInteger(c) ? 1 : c.constructor === String ? 0 : (() => {\n//│     throw new Error(\"non-exhaustive case expression\");\n//│   })()),\n//│   (d = x, Number.isInteger(d) ? 1 : d.constructor === String ? 0 : (() => {\n//│     throw new Error(\"non-exhaustive case expression\");\n//│   })())\n//│ ];\n//│ // End of generated code\n//│ res: (0 | 1, 0 | 1,)\n//│    = [ 1, 1 ]\n\n// Don't add extra parentheses when generating invocations.\n:js\nadd 0 1\n//│ // Query 1\n//│ res = add(0)(1);\n//│ // End of generated code\n//│ res: int\n//│    = 1\n\n:js\nid (fun x -> x)\n//│ // Query 1\n//│ res = id((x) => x);\n//│ // End of generated code\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\n:js\nfun x -> {t1 = gt 1 2; t2 = 1}\n//│ // Prelude\n//│ function gt(x, y) {\n//│   if (arguments.length === 2) {\n//│     return x > y;\n//│   } else {\n//│     return (y) => x > y;\n//│   }\n//│ }\n//│ // Query 1\n//│ res = ((x) => ({\n//│   t1: gt(1)(2),\n//│   t2: 1\n//│ }));\n//│ // End of generated code\n//│ res: anything -> {t1: bool, t2: 1}\n//│    = [Function: res]\n"
  },
  {
    "path": "shared/src/test/diff/codegen/PatternMatch.mls",
    "content": "trait T\n//│ Defined trait T\n\n// Traits with Primitives\n\nt = T 1\n//│ t: 1 & #T\n//│  = [Number: 1]\n\nt + 1\n//│ res: int\n//│    = 2\n\ncase t of { T -> 0 }\n//│ res: 0\n//│    = 0\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Polyfill.mls",
    "content": "// If you didn't use any prelude, it will not be inserted.\n:js\n0\n//│ // Prelude\n//│ let res;\n//│ // Query 1\n//│ res = 0;\n//│ // End of generated code\n//│ res: 0\n//│    = 0\n\n// Look, prelude is empty!\n:js\n1\n//│ // Query 1\n//│ res = 1;\n//│ // End of generated code\n//│ res: 1\n//│    = 1\n\n// If we use `concat`, it will appear.\n:js\nconcat \"a\" \"b\"\n//│ // Prelude\n//│ function concat(x, y) {\n//│   if (arguments.length === 2) {\n//│     return x + y;\n//│   } else {\n//│     return (y) => x + y;\n//│   }\n//│ }\n//│ // Query 1\n//│ res = concat(\"a\")(\"b\");\n//│ // End of generated code\n//│ res: string\n//│    = 'ab'\n\n// Define a function with the same name will shadow the default one. Of course!\n:js\ndef add x y = x + y + x + y\n//│ // Query 1\n//│ globalThis.add = function add(x) {\n//│   return (y) => x + y + x + y;\n//│ };\n//│ // End of generated code\n//│ add: int -> int -> int\n//│    = [Function: add]\n\n// Now the add function is not the default one.\n:js\nadd 1 2\n//│ // Query 1\n//│ res = add(1)(2);\n//│ // End of generated code\n//│ res: int\n//│    = 6\n\n// `withConstruct` will be inserted only when `with` is used.\n:js\nn = 123 with { x = 1 }\n//│ // Prelude\n//│ function withConstruct(target, fields) {\n//│   if (typeof target === \"string\" || typeof target === \"number\" || typeof target === \"boolean\" || typeof target === \"bigint\" || typeof target === \"symbol\") {\n//│     return Object.assign(target, fields);\n//│   }\n//│   if (target instanceof String || target instanceof Number || target instanceof Boolean || target instanceof BigInt) {\n//│     return Object.assign(target.valueOf(), target, fields);\n//│   }\n//│   if (Array.isArray(target)) {\n//│     const clone = Array.from(target);\n//│     for (const key in target){\n//│       clone[key] = target[key];\n//│     }\n//│     for (const key in fields){\n//│       clone[key] = fields[key];\n//│     }\n//│     return clone;\n//│   }\n//│   if (target == null) {\n//│     return Object.assign({}, {}, fields);\n//│   }\n//│   const copy = Object.assign({}, target, fields);\n//│   Object.setPrototypeOf(copy, Object.getPrototypeOf(target));\n//│   return copy;\n//│ }\n//│ // Query 1\n//│ globalThis.n = withConstruct(123, { x: 1 });\n//│ // End of generated code\n//│ n: 123 & {x: 1}\n//│  = [Number: 123] { x: 1 }\n\n:js\nn + 1\n//│ // Query 1\n//│ res = n + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 124\n\n// `withConstruct` should works on extended primitive values.\nm = n with { y = 2 }\n//│ m: 123 & {x: 1, y: 2}\n//│  = [Number: 123] { x: 1, y: 2 }\n\n// `m` should work well with following operations.\nm.x\nm.y\nm + 1\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n//│ res: int\n//│    = 124\n\np = m with { z = 9 }\np.x\np.y\np.z\np + 2\n//│ p: 123 & {x: 1, y: 2, z: 9}\n//│  = [Number: 123] { x: 1, y: 2, z: 9 }\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n//│ res: 9\n//│    = 9\n//│ res: int\n//│    = 125\n\nq = p with { x = 0; y = 0; z = 0 }\nq.x\nq.y\nq.z\nq + 3\n//│ q: 123 & {x: 0, y: 0, z: 0}\n//│  = [Number: 123] { x: 0, y: 0, z: 0 }\n//│ res: 0\n//│    = 0\n//│ res: 0\n//│    = 0\n//│ res: 0\n//│    = 0\n//│ res: int\n//│    = 126\n\n:js\ntoString 0\n//│ // Prelude\n//│ function toString(x) {\n//│   return String(x);\n//│ }\n//│ // Query 1\n//│ res = toString(0);\n//│ // End of generated code\n//│ res: string\n//│    = '0'\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Recursion.mls",
    "content": ":js\nrec def pow0 n x =\n  if n > 0 then pow0 (n - 1) x * x\n  else 1\n//│ // Prelude\n//│ let res;\n//│ // Query 1\n//│ globalThis.pow0 = function pow0(n) {\n//│   return (x) => n > 0 ? pow0(n - 1)(x) * x : 1;\n//│ };\n//│ // End of generated code\n//│ pow0: int -> int -> int\n//│     = [Function: pow0]\n\npow0 3 4\n//│ res: int\n//│    = 64\n\n:js\ndef pow1 x =\n  let rec go n =\n    if n > 0 then go (n - 1) * x\n    else 1\n  in go\n//│ // Query 1\n//│ globalThis.pow1 = function pow1(x) {\n//│   return (((go) => go)(function go(n) {\n//│     return n > 0 ? go(n - 1) * x : 1;\n//│   }));\n//│ };\n//│ // End of generated code\n//│ pow1: int -> int -> int\n//│     = [Function: pow1]\n\npow1 3 4\n//│ res: int\n//│    = 81\n\n:js\nrec def pow2 n = { call = fun x -> if n > 0 then (pow2 (n - 1)).call x * x else 1 }\n//│ // Query 1\n//│ globalThis.pow2 = function pow2(n) {\n//│   return { call: (x) => n > 0 ? pow2(n - 1).call(x) * x : 1 };\n//│ };\n//│ // End of generated code\n//│ pow2: int -> {call: int -> int}\n//│     = [Function: pow2]\n\n(pow2 3).call 4\n//│ res: int\n//│    = 64\n\n:ge\nlet rec x = { f = x } in x\n//│ res: 'x\n//│   where\n//│     'x :> {f: 'x}\n//│ Code generation encountered an error:\n//│   recursive non-function definition x is not supported\n\n:ge\nlet x = { f = x } in x\n//│ res: 'x\n//│   where\n//│     'x :> {f: 'x}\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n\n//  TODO later: code generation for recursive method\n:ge\nclass A\n  rec method M x = M\n//│ Defined class A\n//│ Defined A.M: A -> 'M\n//│   where\n//│     'M :> anything -> 'M\n//│ Code generation encountered an error:\n//│   unresolved symbol M\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/ReplHost.mls",
    "content": "\n:showRepl\nclass Box[T]: { inner: T }\n  method Map: (T -> 'a) -> Box['a]\n  method Map f = Box { inner = f this.inner }\n  method Get = this.inner\nbox0 = Box { inner = 0 }\n//│ Defined class Box[+T]\n//│ Declared Box.Map: Box['T] -> ('T -> 'a) -> Box['a]\n//│ Defined Box.Map: Box['T] -> ('T -> 'inner) -> Box['inner]\n//│ Defined Box.Get: Box['T] -> 'T\n//│ ┌ Block at ReplHost.mls:3\n//│ ├─┬ Prelude\n//│ │ ├── Code\n//│ │ │   let res;\n//│ │ │   class Box {\n//│ │ │     constructor(fields) {\n//│ │ │       this.inner = fields.inner;\n//│ │ │     }\n//│ │ │     Map(f) {\n//│ │ │       const self = this;\n//│ │ │       return new Box({ inner: f(self.inner) });\n//│ │ │     }\n//│ │ │     get Get() {\n//│ │ │       const self = this;\n//│ │ │       return self.inner;\n//│ │ │     }\n//│ │ │   }\n//│ │ └── Reply\n//│ │     undefined\n//│ └─┬ Query 1/1\n//│   ├── Prelude: <empty>\n//│   ├── Code:\n//│   ├──   globalThis.box0 = new Box({ inner: 0 });\n//│   ├── Intermediate: Box { inner: 0 }\n//│   └── Reply: [success] Box { inner: 0 }\n//│ box0: Box[0]\n//│     = Box { inner: 0 }\n\n:showRepl\nbox1 = Box { inner = 1 }\n//│ ┌ Block at ReplHost.mls:41\n//│ ├── No prelude\n//│ └─┬ Query 1/1\n//│   ├── Prelude: <empty>\n//│   ├── Code:\n//│   ├──   globalThis.box1 = new Box({ inner: 1 });\n//│   ├── Intermediate: Box { inner: 1 }\n//│   └── Reply: [success] Box { inner: 1 }\n//│ box1: Box[1]\n//│     = Box { inner: 1 }\n\n:showRepl\ncase box1 of { Box -> 0 }\n//│ ┌ Block at ReplHost.mls:54\n//│ ├── No prelude\n//│ └─┬ Query 1/1\n//│   ├── Prelude:\n//│   ├──   let a;\n//│   ├── Code:\n//│   ├──   res = (a = box1, a instanceof Box ? 0 : (() => {\n//│   ├──     throw new Error(\"non-exhaustive case expression\");\n//│   ├──   })());\n//│   ├── Intermediate: 0\n//│   └── Reply: [success] 0\n//│ res: 0\n//│    = 0\n\n:showRepl\nbox1.Map (fun x -> add x 1)\nbox1.Map (fun x -> add x 2)\nbox1.Map (fun x -> Box { inner = x })\n//│ ┌ Block at ReplHost.mls:70\n//│ ├─┬ Prelude\n//│ │ ├── Code\n//│ │ │   function add(x, y) {\n//│ │ │     if (arguments.length === 2) {\n//│ │ │       return x + y;\n//│ │ │     } else {\n//│ │ │       return (y) => x + y;\n//│ │ │     }\n//│ │ │   }\n//│ │ └── Reply\n//│ │     undefined\n//│ ├─┬ Query 1/3\n//│ │ ├── Prelude: <empty>\n//│ │ ├── Code:\n//│ │ ├──   res = box1.Map((x) => add(x)(1));\n//│ │ ├── Intermediate: Box { inner: 2 }\n//│ │ └── Reply: [success] Box { inner: 2 }\n//│ ├─┬ Query 2/3\n//│ │ ├── Prelude: <empty>\n//│ │ ├── Code:\n//│ │ ├──   res = box1.Map((x) => add(x)(2));\n//│ │ ├── Intermediate: Box { inner: 3 }\n//│ │ └── Reply: [success] Box { inner: 3 }\n//│ └─┬ Query 3/3\n//│   ├── Prelude: <empty>\n//│   ├── Code:\n//│   ├──   res = box1.Map((x) => new Box({ inner: x }));\n//│   ├── Intermediate: Box { inner: Box { inner: 1 } }\n//│   └── Reply: [success] Box { inner: Box { inner: 1 } }\n//│ res: Box[int]\n//│    = Box { inner: 2 }\n//│ res: Box[int]\n//│    = Box { inner: 3 }\n//│ res: Box[Box[1]]\n//│    = Box { inner: Box { inner: 1 } }\n\nbox1.Map (fun x -> Box { inner = x })\n//│ res: Box[Box[1]]\n//│    = Box { inner: Box { inner: 1 } }\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Res.mls",
    "content": "// This test tracks how `res` works.\n\n0\n//│ res: 0\n//│    = 0\n\n:js\nres + 1\n//│ // Query 1\n//│ res = res + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 1\n\n:js\nres + 1\n//│ // Query 1\n//│ res = res + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 2\n\n:js\nres + 1\n//│ // Query 1\n//│ res = res + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 3\n\n:js\nres + 1\n//│ // Query 1\n//│ res = res + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 4\n\n:js\nres + 1\n//│ // Query 1\n//│ res = res + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 5\n\n:js\nres == 4\n//│ // Query 1\n//│ res = res == 4;\n//│ // End of generated code\n//│ res: bool\n//│    = false\n\n:js\ndef res = 0\n//│ // Query 1\n//│ globalThis.res1 = function res1() {\n//│   return 0;\n//│ };\n//│ // End of generated code\n//│ res: 0\n//│    = [Function: res1]\n\n// However, we can shadow `res`!\n\n:js\nres + 1\n//│ // Query 1\n//│ res = res1() + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 1\n\n:js\nres + 1\n//│ // Query 1\n//│ res = res + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 2\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Shadowing.mls",
    "content": ":NewDefs\n\n\n:js\nx =>\n  x =>\n    x + 1\n//│ anything -> Int -> Int\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ res = ((x) => (() => {\n//│   return ((x) => (() => {\n//│     return x + 1;\n//│   })());\n//│ })());\n//│ // End of generated code\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/SortClass.mls",
    "content": "// Simple one\n:js\nclass B: A\nclass A\n//│ Defined class B\n//│ Defined class A\n//│ // Prelude\n//│ let res;\n//│ class A {}\n//│ class B extends A {\n//│   constructor(fields) {\n//│     super(fields);\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\nclass E: D\nclass D: C\nclass C\n//│ Defined class E\n//│ Defined class D\n//│ Defined class C\n//│ // Prelude\n//│ class C {}\n//│ class D extends C {\n//│   constructor(fields) {\n//│     super(fields);\n//│   }\n//│ }\n//│ class E extends D {\n//│   constructor(fields) {\n//│     super(fields);\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\nclass F: { x: int } & G\nclass G: { y: int } & H\nclass K\nclass H: { b: int }\nclass I: J\nclass J\n//│ Defined class F\n//│ Defined class G\n//│ Defined class K\n//│ Defined class H\n//│ Defined class I\n//│ Defined class J\n//│ // Prelude\n//│ class H {\n//│   constructor(fields) {\n//│     this.b = fields.b;\n//│   }\n//│ }\n//│ class J {}\n//│ class K {}\n//│ class G extends H {\n//│   constructor(fields) {\n//│     super(fields);\n//│     this.y = fields.y;\n//│   }\n//│ }\n//│ class I extends J {\n//│   constructor(fields) {\n//│     super(fields);\n//│   }\n//│ }\n//│ class F extends G {\n//│   constructor(fields) {\n//│     super(fields);\n//│     this.x = fields.x;\n//│   }\n//│ }\n//│ // End of generated code\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Super.mls",
    "content": ":NewDefs\n\n\n\n:js\nmixin Foo0 {\n  val foo0 = 0\n}\n//│ mixin Foo0() {\n//│   val foo0: 0\n//│ }\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   constructor() {\n//│   }\n//│   Foo0(base) {\n//│     const qualifier = this;\n//│     return (class Foo0 extends base {\n//│       #foo0;\n//│       get foo0() { return this.#foo0; }\n//│       constructor(...rest) {\n//│         super(...rest);\n//│         this.#foo0 = 0;\n//│         const foo0 = this.#foo0;\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.Foo0 = ((base) => typing_unit.Foo0(base));\n//│ // End of generated code\n\n:js\nmixin Foo1 {\n  val foo0 = 1\n  val foo1 = super.foo0\n}\n//│ mixin Foo1() {\n//│   super: {foo0: 'foo0}\n//│   val foo0: 1\n//│   val foo1: 'foo0\n//│ }\n//│ // Prelude\n//│ class TypingUnit1 {\n//│   constructor() {\n//│   }\n//│   Foo1(base) {\n//│     const qualifier = this;\n//│     return (class Foo1 extends base {\n//│       #foo0;\n//│       get foo0() { return this.#foo0; }\n//│       #foo1;\n//│       get foo1() { return this.#foo1; }\n//│       constructor(...rest) {\n//│         super(...rest);\n//│         this.#foo0 = 1;\n//│         const foo0 = this.#foo0;\n//│         this.#foo1 = super.foo0;\n//│         const foo1 = this.#foo1;\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit1 = new TypingUnit1;\n//│ globalThis.Foo1 = ((base) => typing_unit1.Foo1(base));\n//│ // End of generated code\n\nmodule Test0 extends Foo0, Foo1\n//│ module Test0 {\n//│   val foo0: 1\n//│   val foo1: 0\n//│ }\n\n[Test0.foo0, Test0.foo1]\n//│ [1, 0]\n//│ res\n//│     = [ 1, 0 ]\n\n\n:js\n:e\nmixin Foo2 {\n  fun foo2 = super\n}\n//│ ╔══[ERROR] Illegal use of `super`\n//│ ║  l.84: \t  fun foo2 = super\n//│ ╙──      \t             ^^^^^\n//│ mixin Foo2() {\n//│   super: 'super\n//│   fun foo2: 'super\n//│ }\n//│ // Prelude\n//│ class TypingUnit4 {\n//│   constructor() {\n//│   }\n//│   Foo2(base) {\n//│     const qualifier = this;\n//│     return (class Foo2 extends base {\n//│       constructor(...rest) {\n//│         super(...rest);\n//│       }\n//│       get foo2() {\n//│         return super;\n//│       }\n//│     });\n//│   }\n//│ }\n//│ const typing_unit4 = new TypingUnit4;\n//│ globalThis.Foo2 = ((base) => typing_unit4.Foo2(base));\n//│ // End of generated code\n//│ Syntax error:\n//│   'super' keyword unexpected here\n\n:re\n:js\nmodule Test0 extends Foo2\n//│ module Test0 {\n//│   fun foo2: anything\n//│ }\n//│ // Prelude\n//│ class TypingUnit5 {\n//│   #Test0;\n//│   constructor() {\n//│   }\n//│   get Test0() {\n//│     const qualifier = this;\n//│     if (this.#Test0 === undefined) {\n//│       class Test0 extends Foo2(Object) {\n//│         constructor() {\n//│           super();\n//│         }\n//│       }\n//│       this.#Test0 = new Test0();\n//│       this.#Test0.class = Test0;\n//│     }\n//│     return this.#Test0;\n//│   }\n//│ }\n//│ const typing_unit5 = new TypingUnit5;\n//│ globalThis.Test0 = typing_unit5.Test0;\n//│ // End of generated code\n//│ Runtime error:\n//│   ReferenceError: Foo2 is not defined\n\nTest0\n//│ Test0\n//│ res\n//│     = Test0 { class: [Function: Test0] }\n\nTest0.foo2\n//│ anything\n//│ res\n//│     = undefined\n\n\nclass Foo extends Foo0 {\n  fun foo0(n) = [super.foo0, super.foo0 + n]\n}\n//│ class Foo {\n//│   constructor()\n//│   fun foo0: Int -> [0, Int]\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/SymbolicOps.mls",
    "content": ":NewDefs\n\n\nfun (>>) compose(f, g) = x => g(f(x))\n//│ fun (>>) compose: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c\n\n:js \nlet r = succ >> succ\n//│ let r: Int -> Int\n//│ // Prelude\n//│ function succ(x) {\n//│   return x + 1;\n//│ }\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ globalThis.r = compose(succ, succ);\n//│ // End of generated code\n//│ r\n//│   = [Function (anonymous)]\n\nr(3)\n//│ Int\n//│ res\n//│     = 5\n\ncompose(succ, succ)(3)\n//│ Int\n//│ res\n//│     = 5\n\n(succ >> succ)(3)\n//│ Int\n//│ res\n//│     = 5\n\n(succ >> succ) of 3\n//│ Int\n//│ res\n//│     = 5\n\n// * Note the high left-precedence of `of`\n:e\nsucc >> succ of 3\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.44: \tsucc >> succ of 3\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Int` is not a function\n//│ ║  l.44: \tsucc >> succ of 3\n//│ ║        \t        ^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.4: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ║       \t                              ^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.4: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ╙──     \t                              ^\n//│ error | Int -> nothing\n//│ res\n//│     = [Function (anonymous)]\n\n:js\nlet f = (>>)\n//│ let f: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c\n//│ // Prelude\n//│ class TypingUnit7 {}\n//│ const typing_unit7 = new TypingUnit7;\n//│ // Query 1\n//│ globalThis.f = compose;\n//│ // End of generated code\n//│ f\n//│   = [Function: compose]\n\nf(succ, succ)(3)\n//│ Int\n//│ res\n//│     = 5\n\n(>>)(succ, succ)(3)\n//│ Int\n//│ res\n//│     = 5\n\n(>>) of succ, succ\n//│ Int -> Int\n//│ res\n//│     = [Function (anonymous)]\n\n((>>) of succ, succ) of 3\n//│ Int\n//│ res\n//│     = 5\n\n:e // TODO parse this differently?\n(>>) of succ, succ\n  of 3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.94: \t(>>) of succ, succ\n//│ ║        \t ^^^^^^^^^^^^^^^^^\n//│ ║  l.95: \t  of 3\n//│ ║        \t^^^^^^\n//│ ╟── application of type `Int` is not a function\n//│ ║  l.94: \t(>>) of succ, succ\n//│ ║        \t              ^^^^\n//│ ║  l.95: \t  of 3\n//│ ║        \t^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.4: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ║       \t                              ^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.4: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ╙──     \t                              ^\n//│ error | Int -> nothing\n//│ res\n//│     = [Function (anonymous)]\n\n\n:ge // TODO support this syntax for builtin operators\nfun oops = (+)\n//│ fun oops: (Int, Int) -> Int\n//│ Code generation encountered an error:\n//│   unresolved symbol +\n\n\nfun (%) mod = div\n//│ fun (%) mod: (Int, Int) -> Int\n\n// TODO builtin `div` should compute *integer* division\n12 % 5\n//│ Int\n//│ res\n//│     = 2.4\n\n\n\n// TODO support code-gen for non-top-level operator definitions\nmodule Nested {\n  fun (++) conc(a, b) = concat(a)(b)\n  log(\"abc\" ++ \"def\")\n}\n//│ module Nested {\n//│   fun (++) conc: (Str, Str) -> Str\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol ++\n\n// TODO\nabstract class Nested {\n  fun (++) conc: (Int, Int) -> Int\n  log(\"abc\" ++ \"def\")\n}\n//│ ╔══[ERROR] identifier not found: ++\n//│ ║  l.149: \t  log(\"abc\" ++ \"def\")\n//│ ╙──       \t            ^^\n//│ abstract class Nested {\n//│   fun (++) conc: (Int, Int) -> Int\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol ++\n\n\n\nfun (??) oops: (Int, Int) => Int\n//│ fun (??) oops: (Int, Int) -> Int\n\n1 ?? 2\n//│ Int\n//│ res\n//│     = <no result>\n//│       ?? is not implemented\n\nfun (??) oops: (Int, Int) => Int\nfun oops(a, b) = a + b\n//│ fun oops: (Int, Int) -> Int\n//│ fun (??) oops: (Int, Int) -> Int\n\n// FIXME-later (stub symbols) This is actually implemented...\n1 ?? 2\n//│ Int\n//│ res\n//│     = <no result>\n//│       ?? is not implemented\n\nfun oops: (Int, Int) => Int\nfun (??) oops(a, b) = a + b\n//│ fun (??) oops: (Int, Int) -> Int\n//│ fun oops: (Int, Int) -> Int\n\n1 ?? 2\n//│ Int\n//│ res\n//│     = 3\n\nfun (!?) oops: (Int, Int) => Int\nfun (??) oops(a, b) = a + b\n//│ fun (??) oops: (Int, Int) -> Int\n//│ fun (!?) oops: (Int, Int) -> Int\n\n1 ?? 2\n//│ Int\n//│ res\n//│     = 3\n\n1 !? 2\n//│ Int\n//│ res\n//│     = <no result>\n//│       !? is not implemented\n\n\n\n// * Note: some malformed definitions\n\n:pe\n:e\nfun (>>)(f, g) = x => g(f(x))\n//│ ╔══[PARSE ERROR] Expected a function name; found parenthesis section instead\n//│ ║  l.215: \tfun (>>)(f, g) = x => g(f(x))\n//│ ╙──       \t        ^^^^^^\n//│ ╔══[ERROR] identifier not found: g\n//│ ║  l.215: \tfun (>>)(f, g) = x => g(f(x))\n//│ ╙──       \t                      ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.215: \tfun (>>)(f, g) = x => g(f(x))\n//│ ║         \t                        ^^^^\n//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]`\n//│ ║  l.215: \tfun (>>)(f, g) = x => g(f(x))\n//│ ║         \t                         ^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.4: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ╙──     \t                ^^^^^^\n//│ fun (>>) <error>: anything -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol g\n\n:pe\nfun compose(>>)(f, g) = x => g(f(x))\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.236: \tfun compose(>>)(f, g) = x => g(f(x))\n//│ ╙──       \t            ^^\n//│ fun compose: forall 'a 'b 'c. () -> ('a -> 'b, 'b -> 'c) -> 'a -> 'c\n\n\n:pe\nfun () foo(a, b) = a + b\n//│ ╔══[PARSE ERROR] Expected a symbolic name between brackets, found nothing\n//│ ║  l.244: \tfun () foo(a, b) = a + b\n//│ ╙──       \t    ^^\n//│ fun foo: (Int, Int) -> Int\n\n:pe\nfun (   ) foo(a, b) = a + b\n//│ ╔══[PARSE ERROR] Expected a symbolic name, found space instead\n//│ ║  l.251: \tfun (   ) foo(a, b) = a + b\n//│ ╙──       \t     ^^^\n//│ fun foo: (Int, Int) -> Int\n\n:pe\nfun (\n) foo(a, b) = a + b\n//│ ╔══[PARSE ERROR] Expected a symbolic name, found newline instead\n//│ ║  l.258: \tfun (\n//│ ║         \t     ^\n//│ ║  l.259: \t) foo(a, b) = a + b\n//│ ╙──       \t\n//│ fun foo: (Int, Int) -> Int\n\n:pe\nfun (1) foo(a, b) = a + b\n//│ ╔══[PARSE ERROR] Expected a symbolic name, found literal instead\n//│ ║  l.268: \tfun (1) foo(a, b) = a + b\n//│ ╙──       \t     ^\n//│ fun foo: (Int, Int) -> Int\n\n:pe\nfun (++ 1) foo(a, b) = a + b\n//│ ╔══[PARSE ERROR] Unexpected literal after symbolic name\n//│ ║  l.275: \tfun (++ 1) foo(a, b) = a + b\n//│ ╙──       \t        ^\n//│ fun (++) foo: (Int, Int) -> Int\n\n:pe\nfun (a ++ 1) foo(a, b) = a + b\n//│ ╔══[PARSE ERROR] Expected a symbolic name, found identifier instead\n//│ ║  l.282: \tfun (a ++ 1) foo(a, b) = a + b\n//│ ╙──       \t     ^\n//│ fun foo: (Int, Int) -> Int\n// should be `<<|+_+|>>`, but we got `<<|+`\n\n\n:pe\nfun (<<|+_+|>>) robot(a, b) = a + b\n//│ ╔══[PARSE ERROR] Unexpected identifier after symbolic name\n//│ ║  l.291: \tfun (<<|+_+|>>) robot(a, b) = a + b\n//│ ╙──       \t         ^\n//│ fun (<<|+) robot: (Int, Int) -> Int\n\nfun (<<|+-+|>>) robot(a, b) = a + b\n//│ fun (<<|+-+|>>) robot: (Int, Int) -> Int\n\n2 <<|+-+|>> 2\n//│ Int\n//│ res\n//│     = 4\n\n\n:pe\nfun (:-D) dd(a, b) = a + b\n//│ ╔══[PARSE ERROR] Unexpected identifier after symbolic name\n//│ ║  l.307: \tfun (:-D) dd(a, b) = a + b\n//│ ╙──       \t       ^\n//│ fun (:-) dd: (Int, Int) -> Int\n// should be `:-D`, but we got `:-`\n\n\nval (->) f(x, y) = [x, y]\n//│ val (->) f: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n//│ f\n//│   = [Function: f1]\n\n12 -> 34\n//│ [12, 34]\n//│ res\n//│     = [ 12, 34 ]\n\n\nlet (->) _ = f\n//│ let (->) _: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n//│ _\n//│   = [Function: f1]\n\n:js\n12 -> 34\n//│ [12, 34]\n//│ // Prelude\n//│ class TypingUnit42 {}\n//│ const typing_unit42 = new TypingUnit42;\n//│ // Query 1\n//│ res = _(12, 34);\n//│ // End of generated code\n//│ res\n//│     = [ 12, 34 ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Terms.mls",
    "content": "\n// Define some classes.\nclass A: { a: int }\nclass B: { b: int }\nclass C: { c: int }\nclass D: { d: int }\n//│ Defined class A\n//│ Defined class B\n//│ Defined class C\n//│ Defined class D\n\n// Then define some values.\ndef x = 0\ndef y = 1\ndef z = 2\ndef s = \"s\"\n//│ x: 0\n//│  = [Function: x]\n//│ y: 1\n//│  = [Function: y]\n//│ z: 2\n//│  = [Function: z]\n//│ s: \"s\"\n//│  = [Function: s]\n\n// Var\n:js\nx\n//│ // Query 1\n//│ res = x();\n//│ // End of generated code\n//│ res: 0\n//│    = 0\n\n// Lam\n:js\nfun x -> x\n//│ // Query 1\n//│ res = ((x) => x);\n//│ // End of generated code\n//│ res: 'a -> 'a\n//│    = [Function: res]\n\n// App(Var(op), lhs, rhs)\n:js\n0 + 1\n//│ // Query 1\n//│ res = 0 + 1;\n//│ // End of generated code\n//│ res: int\n//│    = 1\n\n// App(Var(op), lhs, rhs): Complex 1\n:js\nx * y - 1 * 3\n//│ // Query 1\n//│ res = x() * y() - 1 * 3;\n//│ // End of generated code\n//│ res: int\n//│    = -3\n\n// App(Var(op), lhs, rhs): Complex 2\n:js\n:e\nz ** 4 * z / (x + 5)\n//│ // Query 1\n//│ res = z() ** 4 * z() / (x() + 5);\n//│ // End of generated code\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.65: \tz ** 4 * z / (x + 5)\n//│ ║        \t^^^^^^^^\n//│ ╟── operator application of type `number` is not an instance of type `int`\n//│ ║  l.65: \tz ** 4 * z / (x + 5)\n//│ ╙──      \t^^^^^^\n//│ res: number\n//│    = 6.4\n\n// App(App(App(Var(\"if\"), test), consequent), alternative)\n:js\nif true then 1 else 2\n//│ // Query 1\n//│ res = true ? 1 : 2;\n//│ // End of generated code\n//│ res: 1 | 2\n//│    = 1\n\n// App(Var(callee), ...): Construct objects conforming some traits\n:js\ntrait T: { x: int }\nT { x = 0 }\n//│ Defined trait T\n//│ // Prelude\n//│ const T = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // Query 1\n//│ res = T.build({ x: 0 });\n//│ // End of generated code\n//│ res: {x: 0} & #T\n//│    = { x: 0 }\n\n// App(callee, Tup(args)): Call a constructor\n:js\nA { a = 0 }\n//│ // Query 1\n//│ res = new A({ a: 0 });\n//│ // End of generated code\n//│ res: A & {a: 0}\n//│    = A { a: 0 }\n\n// App(callee, Tup(args)): Call a function\n:js\ndef f x = x\nf 0\n//│ // Query 1\n//│ globalThis.f = function f(x) {\n//│   return x;\n//│ };\n//│ // Query 2\n//│ res = f(0);\n//│ // End of generated code\n//│ f: 'a -> 'a\n//│  = [Function: f]\n//│ res: 0\n//│    = 0\n\n// Rcd: Empty\n:js\n{}\n//│ // Query 1\n//│ res = {};\n//│ // End of generated code\n//│ res: anything\n//│    = {}\n\n// Rcd: Sole\n:js\n{ x = 0 }\n//│ // Query 1\n//│ res = { x: 0 };\n//│ // End of generated code\n//│ res: {x: 0}\n//│    = { x: 0 }\n\n// Rcd: Flat\n:js\n{ x = 0; y = 0 }\n//│ // Query 1\n//│ res = {\n//│   x: 0,\n//│   y: 0\n//│ };\n//│ // End of generated code\n//│ res: {x: 0, y: 0}\n//│    = { x: 0, y: 0 }\n\n// Rcd: Nested\n:js\n{ x = { y = 0 }; z = 0 }\n//│ // Query 1\n//│ res = {\n//│   x: { y: 0 },\n//│   z: 0\n//│ };\n//│ // End of generated code\n//│ res: {x: {y: 0}, z: 0}\n//│    = { x: { y: 0 }, z: 0 }\n\n// Rcd: Super nested\n:js\n{ x = { y = { a = 0; b = \"s\" } }; w = 0; a = (0, 0); z }\n//│ // Query 1\n//│ res = {\n//│   x: {\n//│     y: {\n//│       a: 0,\n//│       b: \"s\"\n//│     }\n//│   },\n//│   w: 0,\n//│   a: [\n//│     0,\n//│     0\n//│   ],\n//│   z: z()\n//│ };\n//│ // End of generated code\n//│ res: {a: (0, 0,), w: 0, x: {y: {a: 0, b: \"s\"}}, z: 2}\n//│    = { x: { y: { a: 0, b: 's' } }, w: 0, a: [ 0, 0 ], z: 2 }\n\n// Sel: Select an immediate record\n:js\n{ x = 0; y = 0 }.x\n//│ // Query 1\n//│ res = ({\n//│   x: 0,\n//│   y: 0\n//│ }).x;\n//│ // End of generated code\n//│ res: 0\n//│    = 0\n\n// Sel: Select from an expression\n:js\n(if true then { x = 0 } else { x = 1 }).x\n//│ // Query 1\n//│ res = (true ? { x: 0 } : { x: 1 }).x;\n//│ // End of generated code\n//│ res: 0 | 1\n//│    = 0\n\n// Let\n:js\nlet x = 0 in x + 1\n//│ // Query 1\n//│ res = ((x) => x + 1)(0);\n//│ // End of generated code\n//│ res: int\n//│    = 1\n\n// Blk: Unused in MLParser\n\n// CaseOf: Empty\n:js\ndef f x = case x of { }\n//│ // Query 1\n//│ globalThis.f1 = function f1(x) {\n//│   let a;\n//│   return (a = x, (() => {\n//│     throw new Error(\"non-exhaustive case expression\");\n//│   })());\n//│ };\n//│ // End of generated code\n//│ f: nothing -> nothing\n//│  = [Function: f1]\n\n// CaseOf: Just the wildcard\n:js\ncase 0 of { _ -> 1 }\n//│ // Query 1\n//│ res = (0, 1);\n//│ // End of generated code\n//│ res: 1\n//│    = 1\n\n// CaseOf: One branch with the wildcard\n:js\ncase 0 of\n  { A -> 1\n  | _ -> 0\n  }\n//│ // Query 1\n//│ res = 0 instanceof A ? 1 : 0;\n//│ // End of generated code\n//│ res: 0 | 1\n//│    = 0\n\n// CaseOf: Two branches with the wildcard\n:js\ncase 0 of\n  { A -> 1\n  | B -> 2\n  | _ -> 0\n  }\n//│ // Query 1\n//│ let a;\n//│ res = (a = 0, a instanceof A ? 1 : a instanceof B ? 2 : 0);\n//│ // End of generated code\n//│ res: 0 | 1 | 2\n//│    = 0\n\n// CaseOf: Two branches without the wildcard\n:js\ncase A { a = 0 } of\n  { A -> \"A\"\n  | B -> \"B\"\n  }\n//│ // Query 1\n//│ let b;\n//│ res = (b = new A({ a: 0 }), b instanceof A ? \"A\" : b instanceof B ? \"B\" : (() => {\n//│   throw new Error(\"non-exhaustive case expression\");\n//│ })());\n//│ // End of generated code\n//│ res: \"A\" | \"B\"\n//│    = 'A'\n\n// IntLit\n:js\n42\n//│ // Query 1\n//│ res = 42;\n//│ // End of generated code\n//│ res: 42\n//│    = 42\n\n// StrLit\n:js\n\"Hello\"\n//│ // Query 1\n//│ res = \"Hello\";\n//│ // End of generated code\n//│ res: \"Hello\"\n//│    = 'Hello'\n\n// Asc\n:js\n42 : int\n//│ // Query 1\n//│ res = 42;\n//│ // End of generated code\n//│ res: int\n//│    = 42\n\n// Bra: How?\n\n// Tup\n:js\n(x, y)\n//│ // Query 1\n//│ res = [\n//│   x(),\n//│   y()\n//│ ];\n//│ // End of generated code\n//│ res: (0, 1,)\n//│    = [ 0, 1 ]\n\n\n// With\n{} with {}\n//│ res: anything\n//│    = {}\n:js\nrcd1 = { x = \"a\"; y = \"b\" }\nrcd2 = rcd1 with { x = 1; z = 2 }\n(rcd1.x, rcd1.y, rcd2.x, rcd2.y, rcd2.z)\n//│ // Query 1\n//│ globalThis.rcd1 = {\n//│   x: \"a\",\n//│   y: \"b\"\n//│ };\n//│ // Query 2\n//│ globalThis.rcd2 = withConstruct(rcd1, {\n//│   x: 1,\n//│   z: 2\n//│ });\n//│ // Query 3\n//│ res = [\n//│   rcd1.x,\n//│   rcd1.y,\n//│   rcd2.x,\n//│   rcd2.y,\n//│   rcd2.z\n//│ ];\n//│ // End of generated code\n//│ rcd1: {x: \"a\", y: \"b\"}\n//│     = { x: 'a', y: 'b' }\n//│ rcd2: {x: 1, y: \"b\", z: 2}\n//│     = { x: 1, y: 'b', z: 2 }\n//│ res: (\"a\", \"b\", 1, \"b\", 2,)\n//│    = [ 'a', 'b', 1, 'b', 2 ]\n\nclass M: {mut x : int}\n//│ Defined class M\n\n:js\na1 = M {mut x = 233}\na1.x <- 666\na1.x\n//│ // Query 1\n//│ globalThis.a1 = new M({ x: 233 });\n//│ // Query 2\n//│ res = void(a1.x = 666);\n//│ // Query 3\n//│ res = a1.x;\n//│ // End of generated code\n//│ a1: M with {mut x: 'x}\n//│   where\n//│     'x :> 233\n//│        <: int\n//│   = M { x: 233 }\n//│ = undefined\n//│ res: 233\n//│    = 666\n\n:js\nt1 = (mut \"hello\", mut true)\n//│ // Query 1\n//│ globalThis.t1 = [\n//│   \"hello\",\n//│   true\n//│ ];\n//│ // End of generated code\n//│ t1: (mut 'a, mut 'b,)\n//│   where\n//│     'b :> true\n//│     'a :> \"hello\"\n//│   = [ 'hello', true ]\n\n:js\nt1.0 <- \"bye\"\nt1.0\n//│ // Query 1\n//│ res = void(t1[0] = \"bye\");\n//│ // Query 2\n//│ res = t1[0];\n//│ // End of generated code\n//│ = undefined\n//│ res: \"hello\"\n//│    = 'bye'\n\n:js\ndef muta1 : MutArray[int]\nmuta1 = (mut 1, mut 2, mut 3, mut 4)\n//│ // Query 1 is empty\n//│ // Query 2\n//│ globalThis.muta1 = [\n//│   1,\n//│   2,\n//│   3,\n//│   4\n//│ ];\n//│ // End of generated code\n//│ muta1: MutArray[int]\n//│      = <missing implementation>\n//│ (mut 'a, mut 'b, mut 'c, mut 'd,)\n//│   where\n//│     'd :> 4\n//│     'c :> 3\n//│     'b :> 2\n//│     'a :> 1\n//│   <:  muta1:\n//│ MutArray[int]\n//│      = [ 1, 2, 3, 4 ]\n\n:js\nmuta1[1] <- 233\nmuta1\n//│ // Query 1\n//│ res = void(muta1[1] = 233);\n//│ // Query 2\n//│ res = muta1;\n//│ // End of generated code\n//│ = undefined\n//│ res: MutArray[int]\n//│    = [ 1, 233, 3, 4 ]\n\n:js\ndef xpp rc = (fun _ -> rc) (rc.x <- rc.x + 1)\nxpp a1\n//│ // Query 1\n//│ globalThis.xpp = function xpp(rc) {\n//│   return ((_) => rc)(void(rc.x = rc.x + 1));\n//│ };\n//│ // Query 2\n//│ res = xpp(a1);\n//│ // End of generated code\n//│ xpp: ({mut x: int} & 'a) -> 'a\n//│    = [Function: xpp]\n//│ res: M with {mut x: 'x}\n//│   where\n//│     'x :> 233\n//│        <: int\n//│    = M { x: 667 }\n\n:js\ntu = (mut (), mut 2)\ntu.0 <- (tu.1 <- 3)\ntu.0\ntu.1\n//│ // Query 1\n//│ globalThis.tu = [\n//│   [],\n//│   2\n//│ ];\n//│ // Query 2\n//│ res = void(tu[0] = void(tu[1] = 3));\n//│ // Query 3\n//│ res = tu[0];\n//│ // Query 4\n//│ res = tu[1];\n//│ // End of generated code\n//│ tu: (mut 'a, mut 'b,)\n//│   where\n//│     'b :> 2\n//│     'a :> ()\n//│   = [ [], 2 ]\n//│ = undefined\n//│ res: ()\n//│    = undefined\n//│ res: 2\n//│    = 3\n"
  },
  {
    "path": "shared/src/test/diff/codegen/TraitMethods.mls",
    "content": "\n// To generate the prelude without printing it in the next test case\n()\n//│ res: ()\n//│    = []\n\n:js\ntrait T0\n  method Foo: int\n//│ Defined trait T0\n//│ Declared T0.Foo: T0 -> int\n//│ // Prelude\n//│ const T0 = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // End of generated code\n\ndef foo x = x.Foo\n//│ foo: T0 -> int\n//│    = [Function: foo]\n\n:js\ntrait T1\n  method Foo = 1\n//│ Defined trait T1\n//│ Defined T1.Foo: T1 -> 1\n//│ // Prelude\n//│ const T1 = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│       if (!(\"Foo\" in instance)) {\n//│         Object.defineProperty(instance, \"Foo\", {\n//│           get: function () {\n//│             return 1;\n//│           }\n//│         });\n//│       }\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // End of generated code\n\n:js\nclass A: T0\n//│ Defined class A\n//│ // Prelude\n//│ class A {\n//│   constructor(fields) {\n//│     T0.implement(this);\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\nclass B: A & T1\n//│ Defined class B\n//│ // Prelude\n//│ class B extends A {\n//│   constructor(fields) {\n//│     super(fields);\n//│     T1.implement(this);\n//│   }\n//│ }\n//│ // End of generated code\n\n:e\n:js\na = A{}\n//│ // Query 1\n//│ globalThis.a = new A({});\n//│ // End of generated code\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.101: \ta = A{}\n//│ ║         \t    ^\n//│ ╟── Note that class A is abstract:\n//│ ║  l.77: \tclass A: T0\n//│ ║        \t      ^^^^^\n//│ ╟── Hint: method Foo is abstract\n//│ ║  l.9: \t  method Foo: int\n//│ ╙──     \t         ^^^^^^^^\n//│ a: error\n//│  = A {}\n\nfoo a\n//│ res: int\n//│    = undefined\n\n// Note: calling convention not yet supported in JS\na.(A.Foo)\n//│ res: int\n//│    = undefined\n\n:js\nb = B{}\nfoo b\n//│ // Query 1\n//│ globalThis.b = new B({});\n//│ // Query 2\n//│ res = foo(b);\n//│ // End of generated code\n//│ b: B\n//│  = B {}\n//│ res: int\n//│    = 1\n\nb.(A.Foo)\n//│ res: int\n//│    = undefined\n\n:e\ntype Id[X] = X\nclass AAA\n  method F: int\n  method F = 1\n  method G: 'a -> 'a\n  method G x = x\nclass BBB: AAA\n  method F: int\n  method G: 'a -> 'a\n//│ ╔══[ERROR] Overriding method AAA.F without an overriding definition is not allowed.\n//│ ║  l.151: \t  method F: int\n//│ ║         \t         ^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.147: \t  method F = 1\n//│ ╙──       \t         ^^^^^\n//│ ╔══[ERROR] Overriding method AAA.G without an overriding definition is not allowed.\n//│ ║  l.152: \t  method G: 'a -> 'a\n//│ ║         \t         ^^^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.149: \t  method G x = x\n//│ ╙──       \t         ^^^^^^^\n//│ Defined type alias Id[+X]\n//│ Defined class AAA\n//│ Declared AAA.F: AAA -> int\n//│ Declared AAA.G: AAA -> 'a -> 'a\n//│ Defined AAA.F: AAA -> 1\n//│ Defined AAA.G: AAA -> 'a -> 'a\n//│ Defined class BBB\n//│ Declared BBB.F: BBB -> int\n//│ Declared BBB.G: BBB -> 'a -> 'a\n\n\ntrait T3\n  method Foo: 1 | 2\ntrait T4\n  method Foo: 0 | 1\nclass C: T3 & T4\n//│ Defined trait T3\n//│ Declared T3.Foo: T3 -> (1 | 2)\n//│ Defined trait T4\n//│ Declared T4.Foo: T4 -> (0 | 1)\n//│ Defined class C\n\nC.Foo\n//│ res: C -> 1\n//│    = undefined\n\n:e\nfun x -> x.Foo\n//│ ╔══[ERROR] Implicit call to method Foo is forbidden because it is ambiguous.\n//│ ║  l.192: \tfun x -> x.Foo\n//│ ║         \t         ^^^^^\n//│ ╟── Unrelated methods named Foo are defined by:\n//│ ╟── • trait T0\n//│ ║  l.8: \ttrait T0\n//│ ║       \t      ^^\n//│ ╟── • trait T1\n//│ ║  l.41: \ttrait T1\n//│ ║        \t      ^^\n//│ ╟── • trait T3\n//│ ║  l.176: \ttrait T3\n//│ ║         \t      ^^\n//│ ╟── • trait T4\n//│ ║  l.178: \ttrait T4\n//│ ╙──       \t      ^^\n//│ res: anything -> error\n//│    = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/TrickyShadowing.mls",
    "content": "\n:js\nclass A: {}\nA\nA = 2\n//│ Defined class A\n//│ // Prelude\n//│ let res;\n//│ class A {}\n//│ // Query 1\n//│ res = ((x) => new A(x));\n//│ // Query 2\n//│ globalThis.A1 = 2;\n//│ // End of generated code\n//│ res: anything -> A\n//│    = [Function: res]\n//│ A: 2\n//│  = 2\n\nA\n//│ res: 2\n//│    = 2\n\n:e\n:js\nclass add\n//│ ╔══[ERROR] Type names must start with a capital letter\n//│ ║  l.26: \tclass add\n//│ ╙──      \t      ^^^\n//│ // Prelude\n//│ class add1 {}\n//│ // End of generated code\n\nadd\n//│ res: int -> int -> int\n//│    = [Function: res]\n\nadd = 2\n//│ add: 2\n//│    = 2\n\nadd\n//│ res: 2\n//│    = 2\n\n\nTest = 1\n//│ Test: 1\n//│     = 1\n\nclass Test\n//│ Defined class Test\n\n:js\nx = Test\n//│ // Query 1\n//│ globalThis.x = function x(x) {\n//│   return new Test1(x);\n//│ };\n//│ // End of generated code\n//│ x: anything -> Test\n//│  = [Function: x]\n\nx 1\n//│ res: Test\n//│    = Test1 {}\n\n\n\nclass Test2\n//│ Defined class Test2\n\n:js\nx = Test2\n//│ // Query 1\n//│ globalThis.x1 = function x1(x) {\n//│   return new Test2(x);\n//│ };\n//│ // End of generated code\n//│ x: anything -> Test2\n//│  = [Function: x1]\n\n:js\ntype B = Test2\n//│ Defined type alias B\n//│ // End of generated code\n\n:e\n:ge\n:js\nclass C: B\n//│ ╔══[ERROR] cannot inherit from a type alias\n//│ ║  l.91: \tclass C: B\n//│ ╙──      \t      ^^^^\n//│ Code generation encountered an error:\n//│   cannot inherit from type alias B\n\n:js\nB = 1\n//│ // Query 1\n//│ globalThis.B = 1;\n//│ // End of generated code\n//│ B: 1\n//│  = 1\n\n\n\n:js\ndef f: int\n// def f = 1\n//│ // Query 1 is empty\n//│ // End of generated code\n//│ f: int\n//│  = <missing implementation>\n\n:js\ndef f = 2\ndef f = 3\n//│ // Query 1\n//│ globalThis.f = function f() {\n//│   return 2;\n//│ };\n//│ // Query 2\n//│ globalThis.f1 = function f1() {\n//│   return 3;\n//│ };\n//│ // End of generated code\n//│ 2\n//│   <:  f:\n//│ int\n//│  = [Function: f]\n//│ 3\n//│   <:  f:\n//│ int\n//│  = [Function: f1]\n\nf\n//│ res: int\n//│    = 3\n\ng = 1\n//│ g: 1\n//│  = 1\n\nh = g\n//│ h: 1\n//│  = 1\n\ndef g: string\n//│ g: string\n//│  = <missing implementation>\n\n:js\ng = \"a\"\n//│ // Query 1\n//│ globalThis.g1 = \"a\";\n//│ // End of generated code\n//│ \"a\"\n//│   <:  g:\n//│ string\n//│  = 'a'\n\ndef h: int\n//│ h: int\n//│  = <missing implementation>\n\nh\n//│ res: int\n//│    = <no result>\n//│      h is not implemented\n\n:js\ni = 1\ndef i: string\ni = \"a\"\n//│ // Query 1\n//│ globalThis.i = 1;\n//│ // Query 2 is empty\n//│ // Query 3\n//│ globalThis.i1 = \"a\";\n//│ // End of generated code\n//│ i: 1\n//│  = 1\n//│ i: string\n//│  = <missing implementation>\n//│ \"a\"\n//│   <:  i:\n//│ string\n//│  = 'a'\n\ni\n//│ res: string\n//│    = 'a'\n\n\nclass C1\n//│ Defined class C1\n\n:js\nC1 = \"a\"\n//│ // Query 1\n//│ globalThis.C11 = \"a\";\n//│ // End of generated code\n//│ C1: \"a\"\n//│   = 'a'\n\n:js\nclass C2: C1\n//│ Defined class C2\n//│ // Prelude\n//│ class C2 extends C1 {\n//│   constructor(fields) {\n//│     super(fields);\n//│   }\n//│ }\n//│ // End of generated code\n\n\n\ntype Lol = 1\n//│ Defined type alias Lol\n\n:e\n:ge\n:js\nLol\n//│ ╔══[ERROR] identifier not found: Lol\n//│ ║  l.226: \tLol\n//│ ╙──       \t^^^\n//│ res: error\n//│ Code generation encountered an error:\n//│   type alias Lol is not a valid expression\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/TrickyTerms.mls",
    "content": "\n// To generate the prelude without printing it in the next test case\nsucc 1\n//│ res: int\n//│    = 2\n\n:js\nfun ((x, y)) -> x\n//│ // Query 1\n//│ res = (([\n//│   x,\n//│   y\n//│ ]) => x);\n//│ // End of generated code\n//│ res: (('a, anything,),) -> 'a\n//│    = [Function: res]\n\n:js\nfun {x = 1} -> 0\nres { x = 1 }\n//│ // Query 1\n//│ res = (({ x }) => 0);\n//│ // Query 2\n//│ res = res({ x: 1 });\n//│ // End of generated code\n//│ res: {x: 1} -> 0\n//│    = [Function: res]\n//│ res: 0\n//│    = 0\n\n:js\ndef f x = case 1 of { 1 -> x }\n//│ // Query 1\n//│ globalThis.f = function f(x) {\n//│   let a;\n//│   return (a = 1, a === 1 ? x : (() => {\n//│     throw new Error(\"non-exhaustive case expression\");\n//│   })());\n//│ };\n//│ // End of generated code\n//│ f: 'a -> 'a\n//│  = [Function: f]\n\n// Top-level `def` shadowing:\n:js\ndef tmp = 1\ndef tmp = succ tmp\n//│ // Query 1\n//│ globalThis.tmp = function tmp() {\n//│   return 1;\n//│ };\n//│ // Query 2\n//│ globalThis.tmp1 = function tmp1() {\n//│   return succ(tmp());\n//│ };\n//│ // End of generated code\n//│ tmp: 1\n//│    = [Function: tmp]\n//│ tmp: int\n//│    = [Function: tmp1]\n\n// Local shadowing:\n:js\ndef tmp tmp = tmp\ntmp (let tmp = 1 in tmp)\nlet t = tmp in let tmp = 1 in t tmp\n//│ // Query 1\n//│ globalThis.tmp2 = function tmp2(tmp) {\n//│   return tmp;\n//│ };\n//│ // Query 2\n//│ res = tmp2(((tmp) => tmp)(1));\n//│ // Query 3\n//│ res = ((t) => ((tmp) => t(tmp))(1))(tmp2);\n//│ // End of generated code\n//│ tmp: 'a -> 'a\n//│    = [Function: tmp2]\n//│ res: 1\n//│    = 1\n//│ res: 1\n//│    = 1\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/TrickyWiths.mls",
    "content": "\n\n() with {}\n//│ res: ()\n//│    = []\n\n:js\nn = 42 with { x = 1 }\nn + n.x\n//│ // Query 1\n//│ globalThis.n = withConstruct(42, { x: 1 });\n//│ // Query 2\n//│ res = n + n.x;\n//│ // End of generated code\n//│ n: 42 & {x: 1}\n//│  = [Number: 42] { x: 1 }\n//│ res: int\n//│    = 43\n\n\n// * Note that `with` works on arrays:\n\n:js\na = (1,2,3) with {}\n//│ // Query 1\n//│ globalThis.a = withConstruct([\n//│   1,\n//│   2,\n//│   3\n//│ ], {});\n//│ // End of generated code\n//│ a: (1, 2, 3,)\n//│  = [ 1, 2, 3 ]\n\na : Array[int]\n//│ res: Array[int]\n//│    = [ 1, 2, 3 ]\n\na[0]\n//│ res: 1 | 2 | 3 | undefined\n//│    = 1\n\n:escape\ndef a: nothing // unsound escape hatch\n//│ a: nothing\n//│  = <missing implementation>\n\na.length\na.map(fun x -> x + 1)\n//│ res: nothing\n//│    = 3\n//│ res: nothing\n//│    = [ 2, 3, 4 ]\n\n:js\nax = (1,2,3) with {x = 4}\n//│ // Query 1\n//│ globalThis.ax = withConstruct([\n//│   1,\n//│   2,\n//│   3\n//│ ], { x: 4 });\n//│ // End of generated code\n//│ ax: (1, 2, 3,) & {x: 4}\n//│   = [ 1, 2, 3, x: 4 ]\n\nax.x + 1\n//│ res: int\n//│    = 5\n\nax[0]\n//│ res: 1 | 2 | 3 | undefined\n//│    = 1\n\n:escape\ndef ax: nothing // unsound escape hatch\n//│ ax: nothing\n//│   = <missing implementation>\n\nax.length\nax.map(fun x -> x + 1)\n//│ res: nothing\n//│    = 3\n//│ res: nothing\n//│    = [ 2, 3, 4 ]\n\n\n// * Note that `with` currently doesn work on functions:\n\nf = fun x -> x + 1\ng = f with { a = 123 }\n//│ f: int -> int\n//│  = [Function: f]\n//│ g: int -> int & {a: 123}\n//│  = Function { a: 123 }\n\ng.a\n//│ res: 123\n//│    = 123\n\n:re // FIXME\ng 0\ng g.a\n//│ res: int\n//│ Runtime error:\n//│   TypeError: g is not a function\n//│ res: int\n//│ Runtime error:\n//│   TypeError: g is not a function\n\n\n\ndef f x = x with { a = x.a + 1 }\n//│ f: ({a: int} & 'a) -> ('a\\a & {a: int})\n//│  = [Function: f1]\n\nf { a = 12; b = 34 }\n//│ res: {a: int, b: 34}\n//│    = { a: 13, b: 34 }\n\n:e\nf { a = \"oops\"; b = 34 }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.122: \tf { a = \"oops\"; b = 34 }\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.122: \tf { a = \"oops\"; b = 34 }\n//│ ║         \t        ^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.113: \tdef f x = x with { a = x.a + 1 }\n//│ ╙──       \t                       ^^^\n//│ res: error | {a: int, b: 34}\n//│    = { a: 'oops1', b: 34 }\n\n\n\nclass A\n//│ Defined class A\n\nA{} with { x = 1 }\n//│ res: A & {x: 1}\n//│    = A { x: 1 }\n\nclass A2: { x: string }\n//│ Defined class A2\n\na2 = A2{x=\"a\"}\nr = a2 with { x = 1 }\n//│ a2: A2 & {x: \"a\"}\n//│   = A2 { x: 'a' }\n//│ r: A2 with {x: 1}\n//│  = A2 { x: 1 }\n\n// * Field removal is not supported in negative positions!\n// * (When it appears in such positions, it means somethign different.)\n// * TODO reject such uses this in the typer\n:e\nr : (A2 \\ x) & {x: 1}\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.158: \tr : (A2 \\ x) & {x: 1}\n//│ ║         \t^\n//│ ╟── application of type `A2` does not match type `{x: string}`\n//│ ║  l.147: \ta2 = A2{x=\"a\"}\n//│ ║         \t     ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{x: string}`\n//│ ║  l.158: \tr : (A2 \\ x) & {x: 1}\n//│ ║         \t^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.144: \tclass A2: { x: string }\n//│ ║         \t          ^^^^^^^^^^^^^\n//│ ╟── from intersection type:\n//│ ║  l.158: \tr : (A2 \\ x) & {x: 1}\n//│ ╙──       \t    ^^^^^^^^^^^^^^^^^\n//│ res: A2\\x & {x: 1}\n//│    = A2 { x: 1 }\n\n:e // * Field removal in negative position (see above)\nr2 = r : (A2 \\ y) & {x: 1}\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.178: \tr2 = r : (A2 \\ y) & {x: 1}\n//│ ║         \t     ^\n//│ ╟── integer literal of type `1` is not an instance of type `string`\n//│ ║  l.148: \tr = a2 with { x = 1 }\n//│ ║         \t                  ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.144: \tclass A2: { x: string }\n//│ ╙──       \t               ^^^^^^\n//│ r2: A2\\y & {x: 1}\n//│   = A2 { x: 1 }\n\nr2.x\n//│ res: nothing\n//│    = 1\n\n\ntest a = case a of\n  A2 -> a.x\n//│ test: (A2 with {x: 'x}) -> 'x\n//│     = [Function: test]\n\ntest a2\n//│ res: \"a\"\n//│    = 'a'\n\ntest r\n//│ res: 1\n//│    = 1\n\ntest r2\n//│ res: nothing\n//│    = 1\n\n\nf = (fun x -> x) with {a = 0}\n//│ f: 'a -> 'a & {a: 0}\n//│  = Function { a: 0 }\n\nf.a\n//│ res: 0\n//│    = 0\n\n:re // `with` is currently broken with functions\nf(0)\n//│ res: 0\n//│ Runtime error:\n//│   TypeError: f2 is not a function\n\n\n"
  },
  {
    "path": "shared/src/test/diff/codegen/Unicode.mls",
    "content": "\n:js\n\"τ → π\"\n//│ // Prelude\n//│ let res;\n//│ // Query 1\n//│ res = \"\\u03C4 \\u2192 \\u03C0\";\n//│ // End of generated code\n//│ res: \"τ → π\"\n//│    = 'τ → π'\n\n:js\n\"🌮\"\n//│ // Query 1\n//│ res = \"\\uD83C\\uDF2E\";\n//│ // End of generated code\n//│ res: \"🌮\"\n//│    = '🌮'\n"
  },
  {
    "path": "shared/src/test/diff/codegen/ValLet.mls",
    "content": ":NewDefs\n\n:js\nclass A(x0: Int) {\n  let x1 = x0 + 1\n  log([x1])\n  let x2 = x1 + 1\n  log([x1, x2])\n  val x3 = x2 + 1\n}\n//│ class A(x0: Int) {\n//│   let x1: Int\n//│   let x2: Int\n//│   val x3: Int\n//│ }\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ let res;\n//│ class TypingUnit {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #x0;\n//│         #x3;\n//│         get x3() { return this.#x3; }\n//│         constructor(x0) {\n//│           this.#x0 = x0;\n//│           const x1 = x0 + 1;\n//│           log([x1]);\n//│           const x2 = x1 + 1;\n//│           log([\n//│             x1,\n//│             x2\n//│           ]);\n//│           this.#x3 = x2 + 1;\n//│           const x3 = this.#x3;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [x.#x0];\n//│         }\n//│       };\n//│       this.#A = ((x0) => Object.freeze(new A(x0)));\n//│       this.#A.class = A;\n//│       this.#A.unapply = A.unapply;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.A = typing_unit.A;\n//│ // End of generated code\n\n:e\nA(0).x1\n//│ ╔══[ERROR] Let binding 'x1' cannot tbe accessed as a field\n//│ ║  l.61: \tA(0).x1\n//│ ║        \t    ^^^\n//│ ╟── Use a `val` declaration to make it a field\n//│ ║  l.5: \t  let x1 = x0 + 1\n//│ ╙──     \t      ^^^^^^^^^^^\n//│ Int | error\n//│ res\n//│     = undefined\n//│ // Output\n//│ [ 1 ]\n//│ [ 1, 2 ]\n\nA(1).x3\n//│ Int\n//│ res\n//│     = 4\n//│ // Output\n//│ [ 2 ]\n//│ [ 2, 3 ]\n\n:js\nclass AA() {\n  let x = 42\n  let no = 0\n  fun f(y: Int) = x + y\n}\nAA().f(0)\n//│ class AA() {\n//│   fun f: (y: Int) -> Int\n//│   let no: 0\n//│   let x: 42\n//│ }\n//│ Int\n//│ // Prelude\n//│ class TypingUnit3 {\n//│   #AA;\n//│   constructor() {\n//│   }\n//│   get AA() {\n//│     const qualifier = this;\n//│     if (this.#AA === undefined) {\n//│       class AA {\n//│         #x;\n//│         constructor() {\n//│           this.#x = 42;\n//│           const x = this.#x;\n//│           const no = 0;\n//│         }\n//│         f(y) {\n//│           const qualifier1 = this;\n//│           return qualifier1.#x + y;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return [];\n//│         }\n//│       };\n//│       this.#AA = (() => Object.freeze(new AA()));\n//│       this.#AA.class = AA;\n//│       this.#AA.unapply = AA.unapply;\n//│     }\n//│     return this.#AA;\n//│   }\n//│ }\n//│ const typing_unit3 = new TypingUnit3;\n//│ globalThis.AA = typing_unit3.AA;\n//│ // Query 1\n//│ res = AA().f(0);\n//│ // End of generated code\n//│ res\n//│     = 42\n\n:js\nclass B(x: Int, val y: Int)\n//│ class B(x: Int, y: Int)\n//│ // Prelude\n//│ class TypingUnit4 {\n//│   #B;\n//│   constructor() {\n//│   }\n//│   get B() {\n//│     const qualifier = this;\n//│     if (this.#B === undefined) {\n//│       class B {\n//│         #x;\n//│         #y;\n//│         get y() { return this.#y; }\n//│         constructor(x, y) {\n//│           this.#x = x;\n//│           this.#y = y;\n//│         }\n//│       static\n//│         unapply(x) {\n//│           return ([\n//│             x.#x,\n//│             x.#y\n//│           ]);\n//│         }\n//│       };\n//│       this.#B = ((x, y) => Object.freeze(new B(x, y)));\n//│       this.#B.class = B;\n//│       this.#B.unapply = B.unapply;\n//│     }\n//│     return this.#B;\n//│   }\n//│ }\n//│ const typing_unit4 = new TypingUnit4;\n//│ globalThis.B = typing_unit4.B;\n//│ // End of generated code\n\n:e\nB(0, 0).x\n//│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field\n//│ ║  l.174: \tB(0, 0).x\n//│ ║         \t       ^^\n//│ ╟── Either make the parameter a `val` or access it through destructuring\n//│ ║  l.136: \tclass B(x: Int, val y: Int)\n//│ ╙──       \t        ^\n//│ Int | error\n//│ res\n//│     = undefined\n\nB(0, 0).y\n//│ Int\n//│ res\n//│     = 0\n\n:e\n:js\nclass C {\n  constructor(val x: Int, y: Int)\n}\n//│ ╔══[ERROR] Cannot use `val` in constructor parameters\n//│ ║  l.193: \t  constructor(val x: Int, y: Int)\n//│ ╙──       \t                  ^\n//│ class C {\n//│   constructor(x: Int, y: Int)\n//│ }\n//│ // Prelude\n//│ class TypingUnit7 {\n//│   #C;\n//│   constructor() {\n//│   }\n//│   get C() {\n//│     const qualifier = this;\n//│     if (this.#C === undefined) {\n//│       class C {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         constructor(x, y) {\n//│           this.#x = x;\n//│         }\n//│       };\n//│       this.#C = C;\n//│     }\n//│     return this.#C;\n//│   }\n//│ }\n//│ const typing_unit7 = new TypingUnit7;\n//│ globalThis.C = typing_unit7.C;\n//│ // End of generated code\n\n// * TODO improve error location\n:e\nfun f(val x: Int) = x + 1\n//│ ╔══[ERROR] Cannot use `val` in this position\n//│ ║  l.227: \tfun f(val x: Int) = x + 1\n//│ ╙──       \t          ^^^^^^\n//│ fun f: (x: Int) -> Int\n\n:pe\n(val x: 1)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.234: \t(val x: 1)\n//│ ╙──       \t     ^^^^\n//│ 1\n//│ res\n//│     = 1\n\n:pe\n:e\n(val x: 1) =>\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.244: \t(val x: 1) =>\n//│ ╙──       \t             ^\n//│ ╔══[ERROR] Cannot use `val` in this position\n//│ ║  l.244: \t(val x: 1) =>\n//│ ╙──       \t     ^^^^\n//│ (x: 1) -> ()\n//│ res\n//│     = [Function: res]\n\n:e\n(val x: 1) => ()\n//│ ╔══[ERROR] Cannot use `val` in this position\n//│ ║  l.256: \t(val x: 1) => ()\n//│ ╙──       \t     ^^^^\n//│ (x: 1) -> ()\n//│ res\n//│     = [Function: res]\n\nclass D(x: Int) {\n  val x = 1\n}\nif D(42) is D(x) then x else 0\n//│ class D(x: Int) {\n//│   val x: 1\n//│ }\n//│ 0 | 1\n//│ res\n//│     = 1\n\nclass E(x: Int) {\n  val x = 2\n}\nif E(42) is E(x) then x else 0\n//│ class E(x: Int) {\n//│   val x: 2\n//│ }\n//│ 0 | 2\n//│ res\n//│     = 2\n\nclass F(val x: Int) {\n  val x = 3\n}\nF(0).x\n//│ class F(x: Int) {\n//│   val x: 3\n//│ }\n//│ 3\n//│ res\n//│     = 3\n\nclass G(val x: Int) {\n  val x = 4\n}\nG(1).x\n//│ class G(x: Int) {\n//│   val x: 4\n//│ }\n//│ 4\n//│ res\n//│     = 4\n"
  },
  {
    "path": "shared/src/test/diff/codegen/While.mls",
    "content": ":NewDefs\n\n\n// * TODO improve code-gen (no immediately-applied lambdas)\n:js\nmut let i = 0\nwhile i < 10 do\n  log(i)\n  set i = i + 1\ni\n//│ mut let i: Int\n//│ Int\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ globalThis.i = 0;\n//│ // Query 2\n//│ res = (() => {\n//│   while (i < 10) {\n//│     (() => {\n//│       log(i);\n//│       return void(i = i + 1);\n//│     })()\n//│   }\n//│ })();\n//│ // Query 3\n//│ res = i;\n//│ // End of generated code\n//│ i\n//│   = 0\n//│ res\n//│     = undefined\n//│ // Output\n//│ 0\n//│ 1\n//│ 2\n//│ 3\n//│ 4\n//│ 5\n//│ 6\n//│ 7\n//│ 8\n//│ 9\n//│ res\n//│     = 10\n\ni\n//│ Int\n//│ res\n//│     = 10\n\n\nlet foo =\n  if true then (set i = 0), () else ()\n  ()\n//│ let foo: ()\n//│ foo\n//│     = undefined\n\nmut let min = 123\nlet go =\n    if true then set min = 0 else ()\n    1\n//│ mut let min: 0 | 123\n//│ let go: 1\n//│ min\n//│     = 123\n//│ go\n//│    = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/contys/AbstractBounds.mls",
    "content": ":NoRecursiveTypes\n:NoConstrainedTypes\n:DontDistributeForalls\n\n\n:e\nclass Test[A, B]\n  method Foo (a: A) = a: B\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.8: \t  method Foo (a: A) = a: B\n//│ ║       \t                      ^\n//│ ╟── reference of type `A` does not match type `B`\n//│ ╟── Note: constraint arises from class type parameter:\n//│ ║  l.7: \tclass Test[A, B]\n//│ ║       \t              ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.7: \tclass Test[A, B]\n//│ ╙──     \t           ^\n//│ Defined class Test[-A, +B]\n//│ Defined Test.Foo: Test['A, 'B] -> 'A -> 'B\n\nfun x -> fun y -> x.Foo y\n//│ res: Test['A, 'B] -> 'A -> 'B\n//│    = [Function: res]\n\n\n:GeneralizeCurriedFunctions\n\n:e\nclass Test2[A, B]\n  method Foo2 (a: A) = a: B\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.31: \t  method Foo2 (a: A) = a: B\n//│ ║        \t                       ^\n//│ ╟── reference of type `A` does not match type `B`\n//│ ╟── Note: constraint arises from class type parameter:\n//│ ║  l.30: \tclass Test2[A, B]\n//│ ║        \t               ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.30: \tclass Test2[A, B]\n//│ ╙──      \t            ^\n//│ Defined class Test2[-A, +B]\n//│ Defined Test2.Foo2: Test2['A, 'B] -> 'A -> 'B\n\nfun x -> fun y -> x.Foo2 y\n//│ res: Test2['A, 'B] -> 'A -> 'B\n//│    = [Function: res]\n\n\n:ConstrainedTypes\n\n:e\nclass Test3[A, B]\n  method Foo3 (a: A) = a: B\n  method Bar3 (a: A) = ((fun x -> x) a): B\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.54: \t  method Foo3 (a: A) = a: B\n//│ ║        \t                       ^\n//│ ╟── reference of type `A` does not match type `B`\n//│ ╟── Note: constraint arises from class type parameter:\n//│ ║  l.53: \tclass Test3[A, B]\n//│ ║        \t               ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.53: \tclass Test3[A, B]\n//│ ╙──      \t            ^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.55: \t  method Bar3 (a: A) = ((fun x -> x) a): B\n//│ ║        \t                       ^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `A` does not match type `B`\n//│ ║  l.55: \t  method Bar3 (a: A) = ((fun x -> x) a): B\n//│ ║        \t                                     ^\n//│ ╟── but it flows into reference with expected type `B`\n//│ ║  l.55: \t  method Bar3 (a: A) = ((fun x -> x) a): B\n//│ ║        \t                                  ^\n//│ ╟── Note: constraint arises from class type parameter:\n//│ ║  l.53: \tclass Test3[A, B]\n//│ ║        \t               ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.53: \tclass Test3[A, B]\n//│ ╙──      \t            ^\n//│ Defined class Test3[-A, +B]\n//│ Defined Test3.Foo3: Test3['A, 'B] -> 'A -> 'B\n//│ Defined Test3.Bar3: Test3['A, 'B] -> 'A -> 'B\n\nfun x -> fun y -> x.Foo3 y\n//│ res: 'a -> (forall 'A 'b. 'A -> 'b\n//│   where\n//│     'a <: Test3['A, 'b])\n//│    = [Function: res]\n\n\n// * `Baz4` is equivalent to `Foo3`, and yet it is accepted when the other isn't!\n\nclass Test4[A, B]\n  method Bar4 i (a: A) = i a : B\n  method Baz4 = this.Bar4 id\n//│ Defined class Test4[=A, =B]\n//│ Defined Test4.Bar4: Test4['A, 'B] -> (forall 'a. 'a -> (forall 'a. 'A -> 'B\n//│   where\n//│     'a <: 'A -> 'B))\n//│ Defined Test4.Baz4: Test4['A, 'B] -> ('A -> 'B\n//│   where\n//│     forall 'a. 'a -> 'a <: 'A -> 'B)\n\nfun x -> fun y -> x.Bar4 y id\n//│ res: 'a -> (forall 'A 'B. ('A -> 'B) -> 'B\n//│   where\n//│     'a <: Test4['A, 'B])\n//│ where\n//│   'A :> forall 'b. 'b -> 'b\n//│    = [Function: res]\n\nfun x -> fun y -> x.Baz4 y\n//│ res: 'a -> (forall 'A 'B. ('A & 'B) -> 'B\n//│   where\n//│     'a <: Test4['A, 'B])\n//│ where\n//│   'A <: 'B\n//│    = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/contys/ExplicitConstraints.mls",
    "content": ":NewParser\n:NoJS\n:ConstrainedTypes\n\n\n\nfun f: int => int\n//│ f: int -> int\n\n:e\nfun f: int => int where int : string\n//│ ╔══[ERROR] Type mismatch in constraint specifiation:\n//│ ║  l.11: \tfun f: int => int where int : string\n//│ ║        \t                        ^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.11: \tfun f: int => int where int : string\n//│ ║        \t                        ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.11: \tfun f: int => int where int : string\n//│ ╙──      \t                              ^^^^^^\n//│ f: int -> int\n\n:e\nfun f: int => (int where int : string)\n//│ ╔══[ERROR] Type mismatch in constraint specifiation:\n//│ ║  l.24: \tfun f: int => (int where int : string)\n//│ ║        \t                         ^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.24: \tfun f: int => (int where int : string)\n//│ ║        \t                         ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.24: \tfun f: int => (int where int : string)\n//│ ╙──      \t                               ^^^^^^\n//│ f: int -> int\n\nfun f: 'a => ('a where 'a : string)\n//│ f: (string & 'a) -> 'a\n\n\n:e\nfun f: 'a => ('a where 'a : string) where int : 'a\n//│ ╔══[ERROR] Type mismatch in constraint specifiation:\n//│ ║  l.41: \tfun f: 'a => ('a where 'a : string) where int : 'a\n//│ ║        \t                                          ^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.41: \tfun f: 'a => ('a where 'a : string) where int : 'a\n//│ ║        \t                                          ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.41: \tfun f: 'a => ('a where 'a : string) where int : 'a\n//│ ║        \t                            ^^^^^^\n//│ ╟── from type variable:\n//│ ║  l.41: \tfun f: 'a => ('a where 'a : string) where int : 'a\n//│ ╙──      \t                                                ^^\n//│ f: (string & 'a) -> (int | 'a)\n\n\n:e\nfun f: 'a => 'a where\n  'a : string\n  int : 'a\n//│ ╔══[ERROR] Type mismatch in constraint specifiation:\n//│ ║  l.60: \t  int : 'a\n//│ ║        \t  ^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.60: \t  int : 'a\n//│ ║        \t  ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.59: \t  'a : string\n//│ ║        \t       ^^^^^^\n//│ ╟── from type variable:\n//│ ║  l.60: \t  int : 'a\n//│ ╙──      \t        ^^\n//│ f: (string & 'a) -> (int | 'a)\n\n\n:e\nfun f: 'a => forall 'b: 'a where\n  'a : 'b\n  'b : string\n  int : 'a\n//│ ╔══[ERROR] Type mismatch in constraint specifiation:\n//│ ║  l.80: \t  int : 'a\n//│ ║        \t  ^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.80: \t  int : 'a\n//│ ║        \t  ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.79: \t  'b : string\n//│ ║        \t       ^^^^^^\n//│ ╟── from type variable:\n//│ ║  l.80: \t  int : 'a\n//│ ╙──      \t        ^^\n//│ f: (string & 'a) -> (int | 'a)\n\n\n// * Constraint is stashed!\nfun f: 'a => forall 'b: 'a where\n  'a : 'b => 'b\n  int : 'a\n//│ f: 'a -> (int | 'a\n//│   where\n//│     int | 'a <: 'b -> 'b)\n\n:ns\nf\n//│ res: forall 'a. 'a -> (forall 'b. 'a\n//│   where\n//│     'a <: 'b -> 'b)\n//│ where\n//│   'a :> int\n\n// * Note the first-class polymorphic type with impossible bound...\nlet r = f(1)\n//│ r: int\n//│   where\n//│     int <: 'b -> 'b\n:ns\nr\n//│ res: forall 'c 'a. 'c\n//│   where\n//│     'c :> forall 'b. 'a\n//│       where\n//│         'a <: 'b -> 'b\n//│     'a :> int\n\n:e\nr(2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.127: \tr(2)\n//│ ║         \t^^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.99: \t  int : 'a\n//│ ║        \t  ^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.98: \t  'a : 'b => 'b\n//│ ╙──      \t       ^^^^^^^^\n//│ res: error\n\n:e\nr + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.140: \tr + 1\n//│ ║         \t^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.99: \t  int : 'a\n//│ ║        \t  ^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.98: \t  'a : 'b => 'b\n//│ ╙──      \t       ^^^^^^^^\n//│ res: error | int\n\n\nfun f: 'a => forall 'b: 'b where\n  'a : 'b => 'b\n  int : 'a\n//│ f: 'a -> ('b\n//│   where\n//│     int | 'a <: 'b -> 'b)\n\n:ns\nf\n//│ res: forall 'a. 'a -> (forall 'b. 'b\n//│   where\n//│     'a <: 'b -> 'b)\n//│ where\n//│   'a :> int\n\nlet r = f(1)\n//│ r: 'b\n//│   where\n//│     int <: 'b -> 'b\n\n:e\nr(2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.174: \tr(2)\n//│ ║         \t^^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.155: \t  int : 'a\n//│ ║         \t  ^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.154: \t  'a : 'b => 'b\n//│ ╙──       \t       ^^^^^^^^\n//│ res: error\n\n:e\nr + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.187: \tr + 1\n//│ ║         \t^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.155: \t  int : 'a\n//│ ║         \t  ^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.154: \t  'a : 'b => 'b\n//│ ╙──       \t       ^^^^^^^^\n//│ res: error | int\n\n"
  },
  {
    "path": "shared/src/test/diff/ecoop23/ComparePointPoly.mls",
    "content": ":NewDefs\n\n\nclass Some[out A](val value: A)\nmodule None\n//│ class Some[A](value: A)\n//│ module None\n\nmixin ComparePoint {\n  fun compare(lhs, rhs) = (lhs.x === rhs.x) && (lhs.y === rhs.y)\n}\nmixin CompareColored {\n  fun compare(lhs, rhs) =\n    super.compare(lhs, rhs) && (lhs.color === rhs.color)\n}\nmixin CompareNested {\n  fun compare(lhs, rhs) =\n    super.compare(lhs, rhs) &&\n      if lhs.parent is Some(p)\n        then rhs.parent is Some(q) and this.compare(p, q)\n        else rhs.parent is None\n}\n//│ mixin ComparePoint() {\n//│   fun compare: ({x: Eql['a], y: Eql['b]}, {x: 'a, y: 'b}) -> Bool\n//│ }\n//│ mixin CompareColored() {\n//│   super: {compare: ('c, 'd) -> Bool}\n//│   fun compare: ({color: Eql['e]} & 'c, {color: 'e} & 'd) -> Bool\n//│ }\n//│ mixin CompareNested() {\n//│   super: {compare: ('f, 'g) -> Bool}\n//│   this: {compare: ('h, 'i) -> Bool}\n//│   fun compare: ({parent: Object & ~#Some | Some['h]} & 'f, {parent: Object & ~#Some | Some['i]} & 'g) -> Bool\n//│ }\n\nclass MyPoint[out Col](val x: Int, val y: Int, val color: Col, val parent: Some[MyPoint[Col]] | None)\n//│ class MyPoint[Col](x: Int, y: Int, color: Col, parent: None | Some[MyPoint[Col]])\n\nmodule CompareMyPoint extends ComparePoint, CompareColored, CompareNested\n//│ module CompareMyPoint {\n//│   fun compare: ('a, 'b) -> Bool\n//│ }\n//│ where\n//│   'b <: {color: 'c, parent: Object & ~#Some | Some['b], x: 'd, y: 'e}\n//│   'a <: {color: Eql['c], parent: Object & ~#Some | Some['a], x: Eql['d], y: Eql['e]}\n\nlet Red = 0\nlet p0 = MyPoint(0, 0, Red, None)\nlet p1 = MyPoint(0, 1, Red, None)\nlet p2 = MyPoint(0, 1, Red, None)\nlet p3 = MyPoint(0, 1, Red, Some(p1))\nlet p4 = MyPoint(0, 1, Red, Some(p2))\nlet p5 = MyPoint(0, 1, Red, Some(p3))\n//│ let Red: 0\n//│ let p0: MyPoint[0]\n//│ let p1: MyPoint[0]\n//│ let p2: MyPoint[0]\n//│ let p3: MyPoint[0]\n//│ let p4: MyPoint[0]\n//│ let p5: MyPoint[0]\n//│ Red\n//│     = 0\n//│ p0\n//│    = MyPoint {}\n//│ p1\n//│    = MyPoint {}\n//│ p2\n//│    = MyPoint {}\n//│ p3\n//│    = MyPoint {}\n//│ p4\n//│    = MyPoint {}\n//│ p5\n//│    = MyPoint {}\n\nCompareMyPoint.compare(p0, p1)\nCompareMyPoint.compare(p1, p2)\nCompareMyPoint.compare(p3, p4)\nCompareMyPoint.compare(p3, p5)\n//│ Bool\n//│ res\n//│     = false\n//│ res\n//│     = true\n//│ res\n//│     = true\n//│ res\n//│     = false\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ecoop23/ExpressionProblem.mls",
    "content": ":NewDefs\n\n\n// * Motivating paper example, demonstrating the expression problem solution\n\n\nclass Add<out E>(lhs: E, rhs: E)\nclass Lit(n: Int)\n//│ class Add[E](lhs: E, rhs: E)\n//│ class Lit(n: Int)\n\nfun add11 = Add(Lit(1), Lit(2))\n//│ fun add11: Add[Lit]\n\n\nfun eval(e) =\n  if e is\n    Lit(n) then n\n    Add(l, r) then eval(l) + eval(r)\n//│ fun eval: forall 'a. 'a -> Int\n//│   where\n//│     'a <: Add['a] | Lit\n\n\nmixin EvalBase {\n  fun eval(e) =\n    if e is\n      Lit(n) then n: Int\n      Add(l, r) then this.eval(l) + this.eval(r)\n}\n//│ mixin EvalBase() {\n//│   this: {eval: 'a -> Int}\n//│   fun eval: (Add['a] | Lit) -> Int\n//│ }\n\n\nmodule TestLang extends EvalBase\n//│ module TestLang {\n//│   fun eval: 'a -> Int\n//│ }\n//│ where\n//│   'a <: Add['a] | Lit\n\nTestLang.eval\n//│ 'a -> Int\n//│   where\n//│     'a <: Add['a] | Lit\n//│ res\n//│     = [Function: eval]\n\nTestLang.eval(add11)\n//│ Int\n//│ res\n//│     = 3\n\n\nmixin EvalNothing {\n  fun eval(e) = e : nothing\n}\nmixin EvalAddLit {\n  fun eval(e) =\n    if e is\n      Lit(n) then n: Int\n      Add(l, r) then this.eval(l) + this.eval(r)\n    else super.eval(e)\n}\nmodule TestLang extends EvalNothing, EvalAddLit\n//│ mixin EvalNothing() {\n//│   fun eval: nothing -> nothing\n//│ }\n//│ mixin EvalAddLit() {\n//│   super: {eval: 'a -> 'b}\n//│   this: {eval: 'c -> Int}\n//│   fun eval: (Add['c] | Lit | Object & 'a & ~#Add & ~#Lit) -> (Int | 'b)\n//│ }\n//│ module TestLang {\n//│   fun eval: 'd -> Int\n//│ }\n//│ where\n//│   'd <: Add['d] | Lit\n\nTestLang.eval\n//│ 'a -> Int\n//│   where\n//│     'a <: Add['a] | Lit\n//│ res\n//│     = [Function: eval]\n\nTestLang.eval(add11)\n//│ Int\n//│ res\n//│     = 3\n\n\nclass Neg<out A>(expr: A)\n//│ class Neg[A](expr: A)\n\nlet add2negadd11 = Add(Lit(2), Neg(add11))\n//│ let add2negadd11: Add[Lit | Neg[Add[Lit]]]\n//│ add2negadd11\n//│              = Add {}\n\n\nmixin EvalNeg {\n  fun eval(e) =\n    if e is Neg(d) then 0 - this.eval(d)\n    else super.eval(e)\n}\n//│ mixin EvalNeg() {\n//│   super: {eval: 'a -> 'b}\n//│   this: {eval: 'c -> Int}\n//│   fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b)\n//│ }\n\n\nmodule TestLang extends EvalBase, EvalNeg\n//│ module TestLang {\n//│   fun eval: 'a -> Int\n//│ }\n//│ where\n//│   'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg\n\nTestLang.eval\n//│ 'a -> Int\n//│   where\n//│     'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg\n//│ res\n//│     = [Function: eval]\n\n\nTestLang.eval(add11)\n//│ Int\n//│ res\n//│     = 3\n\nTestLang.eval(Neg(add11))\n//│ Int\n//│ res\n//│     = -3\n\nTestLang.eval(Add(Lit(2), Neg(Lit(1))))\n//│ Int\n//│ res\n//│     = 1\n\nTestLang.eval(Neg(Neg(add11)))\n//│ Int\n//│ res\n//│     = 3\n\n\nTestLang.eval(add2negadd11)\n//│ Int\n//│ res\n//│     = -1\n\n// add11\n\nTestLang.eval(Add(Lit(2), Neg(add11)))\n//│ Int\n//│ res\n//│     = -1\n\n\nmixin EvalNegNeg_0 {\n  fun eval(e) =\n    if e is Neg(Neg(d)) then this.eval(d)\n    else super.eval(e)\n    // * Note: the above is equivalent to:\n    // if e is Neg(f) then\n    //   if f is Neg(d) then this.eval(d)\n    //   else super.eval(e)\n    // else super.eval(e)\n}\n//│ mixin EvalNegNeg_0() {\n//│   super: {eval: (Neg[nothing] | 'a) -> 'b}\n//│   this: {eval: 'c -> 'b}\n//│   fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b\n//│ }\n\n// * Concise alternative, usign syntax sugar:\nmixin EvalNegNeg {\n  fun eval(override Neg(Neg(d))) = this.eval(d)\n}\n//│ mixin EvalNegNeg() {\n//│   super: {eval: (Neg[nothing] | 'a) -> 'b}\n//│   this: {eval: 'c -> 'b}\n//│   fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b\n//│ }\n\nmodule TestLang extends EvalBase, EvalNeg, EvalNegNeg\n//│ module TestLang {\n//│   fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int\n//│ }\n//│ where\n//│   'A <: 'b & (Neg['b] | Object & ~#Neg)\n//│   'b <: Neg['A] | Object & 'a & ~#Neg\n//│   'a <: Add['b] | Lit | Neg['b]\n\nfun mk(n) = if n is\n  0 then Lit(0)\n  1 then Neg(mk(n))\n  _ then Add(mk(n), mk(n))\n//│ fun mk: forall 'a. Object -> (Lit | 'a)\n//│   where\n//│     'a :> Add[Lit | 'a] | Neg[Lit | 'a]\n\nTestLang.eval\n//│ (Neg['A] | Object & 'a & ~#Neg) -> Int\n//│   where\n//│     'A <: 'b & (Neg['b] | Object & ~#Neg)\n//│     'b <: Neg['A] | Object & 'a & ~#Neg\n//│     'a <: Add['b] | Lit | Neg['b]\n//│ res\n//│     = [Function: eval]\n\nTestLang.eval(mk(0))\n//│ Int\n//│ res\n//│     = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ecoop23/Intro.mls",
    "content": ":NewDefs\n\n\n// * Examples from paper intro\n\n\nclass Some<A>(value: A)\nmodule None\n//│ class Some[A](value: A)\n//│ module None\n\n\n\nmixin ComparePoint {\n  fun compare(lhs, rhs) =\n    (lhs.x === rhs.x) && (lhs.y === rhs.y)\n}\n//│ mixin ComparePoint() {\n//│   fun compare: ({x: Eql['a], y: Eql['b]}, {x: 'a, y: 'b}) -> Bool\n//│ }\n\n\nclass Color(val str: Str) {\n  fun equals(that) = str === that.str\n}\n//│ class Color(str: Str) {\n//│   fun equals: {str: anything} -> Bool\n//│ }\n\nlet Red = Color(\"red\")\n//│ let Red: Color\n//│ Red\n//│     = Color {}\n\n\nmixin CompareColored {\n  fun compare(lhs, rhs) =\n    super.compare(lhs, rhs) && lhs.color.equals(rhs.color)\n}\n//│ mixin CompareColored() {\n//│   super: {compare: ('a, 'b) -> Bool}\n//│   fun compare: ({color: {equals: 'color -> Bool}} & 'a, {color: 'color} & 'b) -> Bool\n//│ }\n\n\n\n// * Explicit version from paper:\n\n// interface Nested[Base] { parent: Option[Base] }\n\n// mixin CompareNested[Base, Final] {\n//   super: { compare: (Base, Base) -> Bool }\n//   this:  { compare: (Final, Final) -> Bool }\n//  \n//   fun compare(lhs: Base & Nested[Final], rhs: Base & Nested[Final]): Bool =\n//     super.compare(lhs, rhs) &&\n//       if lhs.parent is Some(p)\n//         then rhs.parent is Some(q) and this.compare(p, q)\n//         else rhs.parent is None\n// }\n\n// * Implicit version:\n\nmixin CompareNested {\n  fun compare(lhs, rhs): Bool =\n    super.compare(lhs, rhs) &&\n      if lhs.parent is Some(p)\n        then rhs.parent is Some(q) and this.compare(p, q)\n        else rhs.parent is None\n}\n//│ mixin CompareNested() {\n//│   super: {compare: ('a, 'b) -> Bool}\n//│   this: {compare: ('c, 'd) -> Bool}\n//│   fun compare: ({parent: Object & ~#Some | Some['c]} & 'a, {parent: Object & ~#Some | Some['d]} & 'b) -> Bool\n//│ }\n\n// * Alternatively:\n\n// mixin CompareNested {\n//   fun compare(lhs, rhs): Bool =\n//     super.compare(lhs, rhs) &&\n//       if lhs.parent is\n//         Some(p) then rhs.parent is Some(q) and this.compare(p, q)\n//         None    then rhs.parent is None\n// }\n\n\n\nclass MyPoint(val x: Int, val y: Int, val color: Color, val parent: Some[MyPoint] | None)\n//│ class MyPoint(x: Int, y: Int, color: Color, parent: None | Some[MyPoint])\n\n\nmodule CompareMyPoint extends ComparePoint, CompareColored, CompareNested\n//│ module CompareMyPoint {\n//│   fun compare: ('a, 'b) -> Bool\n//│ }\n//│ where\n//│   'b <: {color: 'color, parent: Object & ~#Some | Some['b], x: 'c, y: 'd}\n//│   'a <: {\n//│     color: {equals: 'color -> Bool},\n//│     parent: Object & ~#Some | Some['a],\n//│     x: Eql['c],\n//│     y: Eql['d]\n//│   }\n\n\nlet p0 = MyPoint(0, 0, Red, None)\nlet p1 = MyPoint(0, 1, Red, None)\nlet p2 = MyPoint(0, 1, Red, None)\nlet p3 = MyPoint(0, 1, Red, Some(p1))\nlet p4 = MyPoint(0, 1, Red, Some(p2))\nlet p5 = MyPoint(0, 1, Red, Some(p3))\n//│ let p0: MyPoint\n//│ let p1: MyPoint\n//│ let p2: MyPoint\n//│ let p3: MyPoint\n//│ let p4: MyPoint\n//│ let p5: MyPoint\n//│ p0\n//│    = MyPoint {}\n//│ p1\n//│    = MyPoint {}\n//│ p2\n//│    = MyPoint {}\n//│ p3\n//│    = MyPoint {}\n//│ p4\n//│    = MyPoint {}\n//│ p5\n//│    = MyPoint {}\n\n\nCompareMyPoint.compare(p0, p1)\n//│ Bool\n//│ res\n//│     = false\n\nCompareMyPoint.compare(p1, p2)\n//│ Bool\n//│ res\n//│     = true\n\nCompareMyPoint.compare(p3, p4)\n//│ Bool\n//│ res\n//│     = true\n\nCompareMyPoint.compare(p3, p5)\n//│ Bool\n//│ res\n//│     = false\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ecoop23/PolymorphicVariants.mls",
    "content": ":NewDefs\n\n\n// * Adapted example from Code reuse through polymorphic variants (FOSE 2000)\n\n\nclass Cons[out A](head: A, tail: Cons[A] | Nil)\nmodule Nil\n//│ class Cons[A](head: A, tail: Cons[A] | Nil)\n//│ module Nil\n\nlet l = Cons(1, Nil)\n//│ let l: Cons[1]\n//│ l\n//│   = Cons {}\n\nclass NotFound()\nclass Success[out A](result: A)\n//│ class NotFound()\n//│ class Success[A](result: A)\n\nfun list_assoc(s, l) =\n  if l is\n    Cons(h, t) then\n      if s === h.0 then Success(h.1)\n      else list_assoc(s, t)\n    Nil then NotFound()\n//│ fun list_assoc: forall 'a 'A. (Eql['a], Cons[{0: 'a, 1: 'A}] | Nil) -> (NotFound | Success['A])\n\n// fun list_assoc(s: Str, l: Cons[{ _1: Str, _2: 'b }] | Nil): NotFound | Success['b]\n\nclass Var(s: Str)\n//│ class Var(s: Str)\n\nmixin EvalVar {\n  fun eval(sub, v) =\n    if v is Var(s) then\n      if list_assoc(s, sub) is\n        NotFound then v\n        Success(r) then r\n}\n//│ mixin EvalVar() {\n//│   fun eval: (Cons[{0: anything, 1: 'a}] | Nil, Var) -> (Var | 'a)\n//│ }\n\nclass Abs[out A](x: Str, t: A)\nclass App[out A](s: A, t: A)\n//│ class Abs[A](x: Str, t: A)\n//│ class App[A](s: A, t: A)\n\nfun gensym(): Str = \"fun\"\n//│ fun gensym: () -> Str\n\nfun int_to_string(x: Int): Str = \"0\"\n//│ fun int_to_string: (x: Int) -> Str\n\nmixin EvalLambda {\n  fun eval(sub, v) =\n    if v is\n      App(t1, t2) then\n        let l1 = this.eval(sub, t1)\n        let l2 = this.eval(sub, t2)\n        if t1 is\n          Abs(x, t) then this.eval(Cons([x, l2], Nil), t)\n        else\n          App(l1, l2)\n      Abs(x, t) then\n        let s = gensym()\n        Abs(s, this.eval(Cons([x, Var(s)], sub), t))\n    else\n      super.eval(sub, v)\n}\n//│ mixin EvalLambda() {\n//│   super: {eval: ('a, 'b) -> 'c}\n//│   this: {\n//│     eval: ('a, 'd) -> 'A & (Cons[[Str, 'A]], 'e) -> 'c & (Cons[[Str, Var] | 'A0], 'f) -> 'A1\n//│   }\n//│   fun eval: ('a & (Cons['A0] | Nil), Abs['f] | App['d & (Abs['e] | Object & ~#Abs)] | Object & 'b & ~#Abs & ~#App) -> (Abs['A1] | App['A] | 'c)\n//│ }\n\nmodule Test1 extends EvalVar, EvalLambda\n//│ module Test1 {\n//│   fun eval: (Cons[{0: anything, 1: 'a}] | Nil, 'b) -> 'a\n//│ }\n//│ where\n//│   'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Var\n//│   'a :> Abs['a] | App['a] | Var\n\nTest1.eval(Nil, Var(\"a\"))\n//│ 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n//│ res\n//│     = Var {}\n\nTest1.eval(Nil, Abs(\"b\", Var(\"a\")))\n//│ 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n//│ res\n//│     = Abs {}\n\nTest1.eval(Cons([\"c\", Var(\"d\")], Nil), App(Abs(\"b\", Var(\"b\")), Var(\"c\")))\n//│ 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n//│ res\n//│     = Var {}\n\nTest1.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), App(Abs(\"b\", Var(\"b\")), Var(\"c\")))\n//│ Abs['a] | 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n//│ res\n//│     = Abs {}\n\nclass Numb(n: Int)\nclass Add[out A](l: A, r: A)\nclass Mul[out A](l: A, r: A)\n//│ class Numb(n: Int)\n//│ class Add[A](l: A, r: A)\n//│ class Mul[A](l: A, r: A)\n\nfun map_expr(f, v) =\n  if v is\n    Var then v\n    Numb then v\n    Add(l, r) then Add(f(l), f(r))\n    Mul(l, r) then Mul(f(l), f(r))\n//│ fun map_expr: forall 'a 'A 'b 'A0. ('a -> 'A & 'b -> 'A0, Add['b] | Mul['a] | Numb | Var) -> (Add['A0] | Mul['A] | Numb | Var)\n\nmixin EvalExpr {\n  fun eval(sub, v) =\n    let eta(e) = this.eval(sub, e)\n    let vv = map_expr(eta, v)\n    if vv is\n      Var then super.eval(sub, vv)\n      Add(Numb(l), Numb(r)) then Numb(l + r)\n      Mul(Numb(l), Numb(r)) then Numb(l * r)\n    else v\n}\n//│ mixin EvalExpr() {\n//│   super: {eval: ('a, Var) -> 'b}\n//│   this: {eval: ('a, 'c) -> Object}\n//│   fun eval: ('a, 'b & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | 'b)\n//│ }\n\nmodule Test2 extends EvalVar, EvalExpr\n//│ module Test2 {\n//│   fun eval: forall 'a. (Cons[{0: anything, 1: Object & 'b}] | Nil, 'a & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | Var | 'b | 'c | 'a)\n//│ }\n//│ where\n//│   'c <: Add['c] | Mul['c] | Numb | Var\n\nTest2.eval(Nil, Var(\"a\"))\n//│ Numb | Var\n//│ res\n//│     = Var {}\n\nTest2.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Var(\"a\"))\n//│ Abs[Var] | Numb | Var\n//│ res\n//│     = Var {}\n\nTest2.eval(Cons([\"a\", Numb(1)], Nil), Var(\"a\"))\n//│ Numb | Var\n//│ res\n//│     = Numb {}\n\n// * This expected error shows that Test2 does not handle Abs expression inputs\n:e\nTest2.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Abs(\"a\", Var(\"a\")))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.172: \tTest2.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Abs(\"a\", Var(\"a\")))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Abs[?A]` does not match type `Add[?A0] | Mul[?A1] | Numb | Var`\n//│ ║  l.172: \tTest2.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Abs(\"a\", Var(\"a\")))\n//│ ║         \t                                                 ^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.125: \t  if v is\n//│ ║         \t     ^\n//│ ╟── from reference:\n//│ ║  l.135: \t    let vv = map_expr(eta, v)\n//│ ╙──       \t                           ^\n//│ Abs[Var] | Numb | Var | error\n//│ res\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\nTest2.eval(Cons([\"a\", Abs(\"d\", Var(\"d\"))], Nil), Add(Numb(1), Var(\"a\")))\n//│ Abs[Var] | Add[Numb | Var] | Numb | Var\n//│ res\n//│     = Add {}\n\nmodule Test3 extends EvalVar, EvalExpr, EvalLambda\n//│ module Test3 {\n//│   fun eval: (Cons[{0: anything, 1: 'a}] | Nil, 'b) -> (Abs['c] | App['c] | 'c)\n//│ }\n//│ where\n//│   'a :> 'c\n//│      <: Object\n//│   'c :> 'a | 'd\n//│   'd <: Add['b] | Mul['b] | Numb | Var\n//│   'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Object & 'd & ~#Abs & ~#App\n\nTest3.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Abs(\"a\", Var(\"a\")))\n//│ Abs['a] | 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Numb | Var\n//│ res\n//│     = Abs {}\n\nTest3.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), App(Abs(\"a\", Var(\"a\")), Add(Numb(1), Var(\"c\"))))\n//│ Abs['a] | 'a\n//│   where\n//│     'a :> Abs['a] | Add[Numb | Var] | App['a] | Numb | Var\n//│ res\n//│     = Add {}\n\n// * Incorrect version, for regression testing – EvalLambda should be mixed in after EvalExpr\nmodule Test3 extends EvalVar, EvalLambda, EvalExpr\n//│ module Test3 {\n//│   fun eval: (Cons[{0: anything, 1: 'a}] | Nil, 'a & (Add['b] | Mul['b] | Numb | Var)) -> (Numb | 'c | 'a | 'b)\n//│ }\n//│ where\n//│   'a :> 'b | 'c\n//│      <: Object\n//│   'c :> Abs['c | 'a] | App['c | 'a] | 'a\n//│   'b <: Add['b] | Mul['b] | Numb | Var\n\n// * Because EvalExpr does not dispatch lambdas to super and map_expr only\n// * handles exprs\n:e\nTest3.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Abs(\"a\", Var(\"a\")))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.234: \tTest3.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Abs(\"a\", Var(\"a\")))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Abs[?A]` does not match type `Add[?A0] | Mul[?A1] | Numb | Var`\n//│ ║  l.234: \tTest3.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil), Abs(\"a\", Var(\"a\")))\n//│ ║         \t                                                 ^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.125: \t  if v is\n//│ ║         \t     ^\n//│ ╟── from reference:\n//│ ║  l.135: \t    let vv = map_expr(eta, v)\n//│ ╙──       \t                           ^\n//│ Abs[Var] | error | 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Numb | Var\n//│ res\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n"
  },
  {
    "path": "shared/src/test/diff/ecoop23/SimpleRegionDSL_annot.mls",
    "content": ":NewDefs\n\n\n// * Adapted example from Compositional Embeddings of Domain-Specific Languages (OOPSLA 2022)\n\n\n// ******************* Initial System *******************\n\nclass Vector(val x: Int, val y: Int)\n//│ class Vector(x: Int, y: Int)\n\nclass Circle(radius: Int)\nclass Outside[out Region](a: Region)\nclass Union[out Region](a: Region, b: Region)\nclass Intersect[out Region](a: Region, b: Region)\nclass Translate[out Region](v: Vector, a: Region)\n//│ class Circle(radius: Int)\n//│ class Outside[Region](a: Region)\n//│ class Union[Region](a: Region, b: Region)\n//│ class Intersect[Region](a: Region, b: Region)\n//│ class Translate[Region](v: Vector, a: Region)\n\ntype BaseLang[T] = Circle | Intersect[T] | Union[T] | Outside[T] | Translate[T]\n//│ type BaseLang[T] = Circle | Intersect[T] | Outside[T] | Translate[T] | Union[T]\n\nmixin SizeBase {\n  fun size(r) =\n    if r is\n      Circle(_) then 1\n      Outside(a) then this.size(a) + 1\n      Union(a, b) then this.size(a) + this.size(b) + 1\n      Intersect(a, b) then this.size(a) + this.size(b) + 1\n      Translate(_, a) then this.size(a) + 1\n}\n//│ mixin SizeBase() {\n//│   this: {size: 'a -> Int}\n//│   fun size: (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) -> Int\n//│ }\n\n// ******************* Linguistic Reuse and Meta-Language Optimizations *******************\n\nfun round(n: Num): Int = 0\n//│ fun round: (n: Num) -> Int\n\nfun go(x, offset) =\n  if x is 0 then Circle(1)\n  else\n    let shared = go(x - 1, round(offset / 2))\n    Union(Translate(Vector(0 - offset, 0), shared), Translate(Vector(offset, 0), shared))\n//│ fun go: forall 'a. (0 | Int & ~0, Int) -> (Circle | 'a)\n//│   where\n//│     'a :> Union[Translate[Circle | 'a]]\n\n// * Note that first-class polymorphism manages (correctly) to preserve the universal quantification\nlet circles = go(2, 1024)\n//│ let circles: forall 'a. Circle | 'a\n//│   where\n//│     'a :> Union[Translate[Circle | 'a]]\n//│ circles\n//│         = Union {}\n\n// ******************* Adding More Language Constructs *******************\n\nclass Univ()\nclass Empty()\nclass Scale[out Region](v: Vector, a: Region)\n//│ class Univ()\n//│ class Empty()\n//│ class Scale[Region](v: Vector, a: Region)\n\ntype ExtLang[T] = Univ | Empty | Scale[T]\n//│ type ExtLang[T] = Empty | Scale[T] | Univ\n\nmixin SizeExt {\n  fun size(a) =\n    if a is\n      Univ then 1\n      Empty then 1\n      Scale(_, b) then this.size(b) + 1\n    else super.size(a)\n}\n//│ mixin SizeExt() {\n//│   super: {size: 'a -> 'b}\n//│   this: {size: 'c -> Int}\n//│   fun size: (Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['c] | Univ) -> (Int | 'b)\n//│ }\n\ntype RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang]\n//│ type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang]\n\nmodule TestSize extends SizeBase, SizeExt {\n  fun size: RegionLang -> Int\n}\n//│ module TestSize {\n//│   fun size: RegionLang -> Int\n//│ }\n\nTestSize.size(Empty())\n//│ Int\n//│ res\n//│     = 1\n\nTestSize.size(circles)\n//│ Int\n//│ res\n//│     = 13\n\nTestSize.size(Scale(Vector(1, 1), circles))\n//│ Int\n//│ res\n//│     = 14\n\n// ******************* Adding a New Interpretation *******************\n// a stupid power (Int ** Int) implementation\nfun pow(x, a) =\n  if a is 0 then 1\n  else x * pow(x, a - 1)\n//│ fun pow: (Int, 0 | Int & ~0) -> Int\n\nmixin Contains {\n  fun contains(a, p) =\n    if a is\n      Circle(r) then pow(p.x, 2) + pow(p.y, 2) <= pow(r, 2)\n      Outside(a) then not (this.contains(a, p))\n      Union(lhs, rhs) then this.contains(lhs, p) || this.contains(rhs, p)\n      Intersect(lhs, rhs) then this.contains(lhs, p) && this.contains(rhs, p)\n      Translate(v, a) then this.contains(a, Vector(p.x - v.x, p.y - v.y))\n}\n//│ mixin Contains() {\n//│   this: {contains: ('a, 'b) -> Bool & ('c, Vector) -> 'd}\n//│   fun contains: (Circle | Intersect['a] | Outside['a] | Translate['c] | Union['a], {x: Int, y: Int} & 'b) -> (Bool | 'd)\n//│ }\n\ntype BaseRegionLang = BaseLang[BaseRegionLang]\n//│ type BaseRegionLang = BaseLang[BaseRegionLang]\n\nmodule TestContains extends Contains {\n  fun contains: (BaseRegionLang, Vector) -> Bool\n}\n//│ module TestContains {\n//│   fun contains: (BaseRegionLang, Vector) -> Bool\n//│ }\n\nTestContains.contains(Translate(Vector(0, 0), Circle(1)), Vector(0, 0))\n//│ Bool\n//│ res\n//│     = true\n\nTestContains.contains(Intersect(Translate(Vector(0, 0), Circle(1)), Circle(1)), Vector(0, 0))\n//│ Bool\n//│ res\n//│     = true\n\nTestContains.contains(circles, Vector(0, 0))\n//│ Bool\n//│ res\n//│     = false\n\n// ******************* Dependencies, Complex Interpretations, and Domain-Specific Optimizations *******************\n\nfun toString(a: Int): Str = \"foo\"\nfun concat(a: Str, b: Str): Str = a\n//│ fun toString: (a: Int) -> Str\n//│ fun concat: (a: Str, b: Str) -> Str\n\nmixin Text {\n  fun text(e) =\n    if e is\n      Circle(r) then concat(\"a circular region of radius \", toString(r))\n      Outside(a) then concat(\"outside a region of size \", toString(this.size(a)))\n      Union then concat(\"the union of two regions of size \", toString(this.size(e)))\n      Intersect then concat(\"the intersection of two regions of size \", toString(this.size(e)))\n      Translate then concat(\"a translated region of size \", toString(this.size(e)))\n}\n//│ mixin Text() {\n//│   this: {size: (Intersect['Region] | Translate[nothing] | Union[nothing] | 'a) -> Int}\n//│   fun text: (Circle | Intersect['Region] | Outside['a] | Translate[anything] | Union[anything]) -> Str\n//│ }\n\n:e\nmodule SizeText extends Text\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.172: \t      Intersect then concat(\"the intersection of two regions of size \", toString(this.size(e)))\n//│ ╙──       \t                                                                                     ^^^^^\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.170: \t      Outside(a) then concat(\"outside a region of size \", toString(this.size(a)))\n//│ ╙──       \t                                                                       ^^^^^\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.173: \t      Translate then concat(\"a translated region of size \", toString(this.size(e)))\n//│ ╙──       \t                                                                         ^^^^^\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.171: \t      Union then concat(\"the union of two regions of size \", toString(this.size(e)))\n//│ ╙──       \t                                                                          ^^^^^\n//│ module SizeText {\n//│   fun text: (Circle | Intersect[anything] | Outside[anything] | Translate[anything] | Union[anything]) -> Str\n//│ }\n\n// * Note: this inferred type got *much worse* after this commit (field access type refinement)\nmodule SizeText extends SizeBase, Text {\n  fun size: BaseRegionLang -> Int\n  fun text: BaseRegionLang -> Str\n}\n//│ module SizeText {\n//│   fun size: BaseRegionLang -> Int\n//│   fun text: BaseRegionLang -> Str\n//│ }\n\nSizeText.text(circles)\n//│ Str\n//│ res\n//│     = 'the union of two regions of size '\n\nSizeText.size(circles)\n//│ Int\n//│ res\n//│     = 13\n\nSizeText.text(Intersect(Translate(Vector(0, 0), Circle(1)), Circle(1)))\n//│ Str\n//│ res\n//│     = 'the intersection of two regions of size '\n\nSizeText.size(Intersect(Translate(Vector(0, 0), Circle(1)), Circle(1)))\n//│ Int\n//│ res\n//│     = 4\n\nmixin IsUniv {\n  fun isUniv(e) =\n    if e is\n      Univ then true\n      Outside(a) then this.isEmpty(a)\n      Union(a, b) then this.isUniv(a) || this.isUniv(b)\n      Intersect(a, b) then this.isUniv(a) && this.isUniv(b)\n      Translate(_, a) then this.isUniv(a)\n      Scale(_, a) then this.isUniv(a)\n    else false\n}\n//│ mixin IsUniv() {\n//│   this: {isEmpty: 'a -> 'b, isUniv: 'c -> Bool & 'd -> 'b}\n//│   fun isUniv: (Intersect['c] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['d] | Translate['d] | Union['c] | Univ) -> (Bool | 'b)\n//│ }\n\nmixin IsEmpty {\n  fun isEmpty(e) =\n    if e is\n      Univ then true\n      Outside(a) then this.isUniv(a)\n      Union(a, b) then this.isEmpty(a) || this.isEmpty(b)\n      Intersect(a, b) then this.isEmpty(a) && this.isEmpty(b)\n      Translate(_, a) then this.isEmpty(a)\n      Scale(_, a) then this.isEmpty(a)\n    else false\n}\n//│ mixin IsEmpty() {\n//│   this: {isEmpty: 'a -> Bool & 'b -> 'c, isUniv: 'd -> 'c}\n//│   fun isEmpty: (Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['d] | Scale['b] | Translate['b] | Union['a] | Univ) -> (Bool | 'c)\n//│ }\n\nmodule IsUnivIsEmpty extends IsUniv, IsEmpty {\n  fun isEmpty: RegionLang -> Bool\n  fun isUniv: RegionLang -> Bool\n}\n//│ module IsUnivIsEmpty {\n//│   fun isEmpty: RegionLang -> Bool\n//│   fun isUniv: RegionLang -> Bool\n//│ }\n\nmodule IsUnivIsEmpty extends IsEmpty, IsUniv {\n  fun isEmpty: RegionLang -> Bool\n  fun isUniv: RegionLang -> Bool\n}\n//│ module IsUnivIsEmpty {\n//│   fun isEmpty: RegionLang -> Bool\n//│   fun isUniv: RegionLang -> Bool\n//│ }\n\nIsUnivIsEmpty.isUniv(circles)\n//│ Bool\n//│ res\n//│     = false\n\nIsUnivIsEmpty.isEmpty(circles)\n//│ Bool\n//│ res\n//│     = false\n\n:e // Expected since the annotation only allows Lang variants\nclass Foo()\nIsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles)))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.290: \tIsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles)))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Foo` does not match type `BaseLang[RegionLang] | ExtLang[RegionLang]`\n//│ ║  l.290: \tIsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles)))\n//│ ║         \t                                                    ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.88: \ttype RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang]\n//│ ║        \t                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.88: \ttype RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang]\n//│ ╙──      \t                           ^^^^^^^^^^\n//│ class Foo()\n//│ error | false | true\n//│ res\n//│     = false\n\nmixin Eliminate {\n  fun eliminate(e) =\n    if e is\n      Outside(Outside(a)) then this.eliminate(a)\n      Outside(a) then Outside(this.eliminate(a))\n      Union(a, b) then Union(this.eliminate(a), this.eliminate(b))\n      Intersect(a, b) then Intersect(this.eliminate(a), this.eliminate(b))\n      Translate(v, a) then Translate(v, this.eliminate(a))\n      Scale(v, a) then Scale(v, this.eliminate(a))\n    else e\n}\n//│ mixin Eliminate() {\n//│   this: {\n//│     eliminate: 'a -> 'b & 'c -> 'Region & 'd -> 'Region0 & 'e -> 'Region1 & 'f -> 'Region2 & 'g -> 'Region3\n//│   }\n//│   fun eliminate: (Intersect['g] | Object & 'b & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['c & (Object & ~#Outside | Outside['a])] | Scale['f] | Translate['e] | Union['d]) -> (Intersect['Region3] | Outside['Region] | Scale['Region2] | Translate['Region1] | Union['Region0] | 'b)\n//│ }\n\nmodule TestElim extends Eliminate {\n  fun eliminate: RegionLang -> RegionLang\n}\n//│ module TestElim {\n//│   fun eliminate: RegionLang -> RegionLang\n//│ }\n\nTestElim.eliminate(Outside(Outside(Univ())))\n//│ RegionLang\n//│ res\n//│     = Univ {}\n\nTestElim.eliminate(circles)\n//│ RegionLang\n//│ res\n//│     = Union {}\n\nfun mk(n) = if n is\n  1 then Outside(mk(n))\n  2 then Union(mk(n), mk(n))\n  3 then Intersect(mk(n), mk(n))\n  4 then Translate(Vector(0, 0), mk(n))\n  _ then Scale(Vector(0, 0), mk(n))\n//│ fun mk: forall 'a. Object -> 'a\n//│   where\n//│     'a :> Intersect['a] | Outside['a] | Scale['a] | Translate['a] | Union['a]\n\n:re\nTestElim.eliminate(mk(100))\n//│ RegionLang\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// *************************************************************************\n\nmodule Lang extends SizeBase, SizeExt, Contains, Text, IsUniv, IsEmpty, Eliminate {\n  fun contains: (BaseRegionLang, Vector) -> Bool\n  fun eliminate: RegionLang -> RegionLang\n  fun isEmpty: RegionLang -> Bool\n  fun isUniv: RegionLang -> Bool\n  fun size: RegionLang -> Int\n  fun text: BaseRegionLang -> Str\n}\n//│ module Lang {\n//│   fun contains: (BaseRegionLang, Vector) -> Bool\n//│   fun eliminate: RegionLang -> RegionLang\n//│   fun isEmpty: RegionLang -> Bool\n//│   fun isUniv: RegionLang -> Bool\n//│   fun size: RegionLang -> Int\n//│   fun text: BaseRegionLang -> Str\n//│ }\n\nLang.size(circles)\n//│ Int\n//│ res\n//│     = 13\n\nLang.contains(circles, Vector(0, 0))\n//│ Bool\n//│ res\n//│     = false\n\nLang.text(circles)\n//│ Str\n//│ res\n//│     = 'the union of two regions of size '\n\nLang.isUniv(circles)\n//│ Bool\n//│ res\n//│     = false\n\nLang.isEmpty(circles)\n//│ Bool\n//│ res\n//│     = false\n\nLang.size(Lang.eliminate(circles))\n//│ Int\n//│ res\n//│     = 13\n\n:re\nLang.size(mk(100))\n//│ Int\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\n:re\nLang.contains(mk(100), Vector(0, 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.418: \tLang.contains(mk(100), Vector(0, 0))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[BaseRegionLang] | Outside[BaseRegionLang] | Translate[BaseRegionLang] | Union[BaseRegionLang]`\n//│ ║  l.348: \t  _ then Scale(Vector(0, 0), mk(n))\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.23: \ttype BaseLang[T] = Circle | Intersect[T] | Union[T] | Outside[T] | Translate[T]\n//│ ║        \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.134: \ttype BaseRegionLang = BaseLang[BaseRegionLang]\n//│ ╙──       \t                               ^^^^^^^^^^^^^^\n//│ error | false | true\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\n:re\nLang.text(mk(100))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.438: \tLang.text(mk(100))\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[BaseRegionLang] | Outside[BaseRegionLang] | Translate[BaseRegionLang] | Union[BaseRegionLang]`\n//│ ║  l.348: \t  _ then Scale(Vector(0, 0), mk(n))\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.23: \ttype BaseLang[T] = Circle | Intersect[T] | Union[T] | Outside[T] | Translate[T]\n//│ ║        \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.134: \ttype BaseRegionLang = BaseLang[BaseRegionLang]\n//│ ╙──       \t                               ^^^^^^^^^^^^^^\n//│ Str | error\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nLang.isUniv(mk(100))\n//│ Bool\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nLang.isEmpty(mk(100))\n//│ Bool\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nLang.size(Lang.eliminate(mk(100)))\n//│ Int\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "shared/src/test/diff/ecoop23/SimpleRegionDSL_raw.mls",
    "content": ":NewDefs\n\n\n// * Adapted example from Compositional Embeddings of Domain-Specific Languages (OOPSLA 2022)\n\n\n// ******************* Initial System *******************\n\nclass Vector(val x: Int, val y: Int)\n//│ class Vector(x: Int, y: Int)\n\nclass Circle(radius: Int)\nclass Outside[out Region](a: Region)\nclass Union[out Region](a: Region, b: Region)\nclass Intersect[out Region](a: Region, b: Region)\nclass Translate[out Region](v: Vector, a: Region)\n//│ class Circle(radius: Int)\n//│ class Outside[Region](a: Region)\n//│ class Union[Region](a: Region, b: Region)\n//│ class Intersect[Region](a: Region, b: Region)\n//│ class Translate[Region](v: Vector, a: Region)\n\nmixin SizeBase {\n  fun size(r) =\n    if r is\n      Circle(_) then 1\n      Outside(a) then this.size(a) + 1\n      Union(a, b) then this.size(a) + this.size(b) + 1\n      Intersect(a, b) then this.size(a) + this.size(b) + 1\n      Translate(_, a) then this.size(a) + 1\n}\n//│ mixin SizeBase() {\n//│   this: {size: 'a -> Int}\n//│   fun size: (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) -> Int\n//│ }\n\n// ******************* Linguistic Reuse and Meta-Language Optimizations *******************\n\nfun round(n: Num): Int = 0\n//│ fun round: (n: Num) -> Int\n\nfun go(x, offset) =\n  if x is 0 then Circle(1)\n  else\n    let shared = go(x - 1, round(offset / 2))\n    Union(Translate(Vector(0 - offset, 0), shared), Translate(Vector(offset, 0), shared))\n//│ fun go: forall 'a. (0 | Int & ~0, Int) -> (Circle | 'a)\n//│   where\n//│     'a :> Union[Translate[Circle | 'a]]\n\n// * Note that first-class polymorphism manages (correctly) to preserve the universal quantification\nlet circles = go(2, 1024)\n//│ let circles: forall 'a. Circle | 'a\n//│   where\n//│     'a :> Union[Translate[Circle | 'a]]\n//│ circles\n//│         = Union {}\n\n// ******************* Adding More Language Constructs *******************\n\nclass Univ()\nclass Empty()\nclass Scale[out Region](v: Vector, a: Region)\n//│ class Univ()\n//│ class Empty()\n//│ class Scale[Region](v: Vector, a: Region)\n\nmixin SizeExt {\n  fun size(a) =\n    if a is\n      Univ then 1\n      Empty then 1\n      Scale(_, b) then this.size(b) + 1\n    else super.size(a)\n}\n//│ mixin SizeExt() {\n//│   super: {size: 'a -> 'b}\n//│   this: {size: 'c -> Int}\n//│   fun size: (Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['c] | Univ) -> (Int | 'b)\n//│ }\n\nmodule TestSize extends SizeBase, SizeExt\n//│ module TestSize {\n//│   fun size: 'a -> Int\n//│ }\n//│ where\n//│   'a <: Empty | Object & (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) & ~#Empty & ~#Scale & ~#Univ | Scale['a] | Univ\n\nTestSize.size(Empty())\n//│ Int\n//│ res\n//│     = 1\n\nTestSize.size(circles)\n//│ Int\n//│ res\n//│     = 13\n\nTestSize.size(Scale(Vector(1, 1), circles))\n//│ Int\n//│ res\n//│     = 14\n\n// ******************* Adding a New Interpretation *******************\n// a stupid power (Int ** Int) implementation\nfun pow(x, a) =\n  if a is 0 then 1\n  else x * pow(x, a - 1)\n//│ fun pow: (Int, 0 | Int & ~0) -> Int\n\nmixin Contains {\n  fun contains(a, p) =\n    if a is\n      Circle(r) then pow(p.x, 2) + pow(p.y, 2) <= pow(r, 2)\n      Outside(a) then not (this.contains(a, p))\n      Union(lhs, rhs) then this.contains(lhs, p) || this.contains(rhs, p)\n      Intersect(lhs, rhs) then this.contains(lhs, p) && this.contains(rhs, p)\n      Translate(v, a) then this.contains(a, Vector(p.x - v.x, p.y - v.y))\n}\n//│ mixin Contains() {\n//│   this: {contains: ('a, 'b) -> Bool & ('c, Vector) -> 'd}\n//│   fun contains: (Circle | Intersect['a] | Outside['a] | Translate['c] | Union['a], {x: Int, y: Int} & 'b) -> (Bool | 'd)\n//│ }\n\nmodule TestContains extends Contains\n//│ module TestContains {\n//│   fun contains: ('a, {x: Int, y: Int}) -> Bool\n//│ }\n//│ where\n//│   'a <: Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]\n\nTestContains.contains(Translate(Vector(0, 0), Circle(1)), Vector(0, 0))\n//│ Bool\n//│ res\n//│     = true\n\nTestContains.contains(Intersect(Translate(Vector(0, 0), Circle(1)), Circle(1)), Vector(0, 0))\n//│ Bool\n//│ res\n//│     = true\n\nTestContains.contains(circles, Vector(0, 0))\n//│ Bool\n//│ res\n//│     = false\n\n// ******************* Dependencies, Complex Interpretations, and Domain-Specific Optimizations *******************\n\nfun toString(a: Int): Str = \"foo\"\nfun concat(a: Str, b: Str): Str = a\n//│ fun toString: (a: Int) -> Str\n//│ fun concat: (a: Str, b: Str) -> Str\n\nmixin Text {\n  fun text(e) =\n    if e is\n      Circle(r) then concat(\"a circular region of radius \", toString(r))\n      Outside(a) then concat(\"outside a region of size \", toString(this.size(a)))\n      Union then concat(\"the union of two regions of size \", toString(this.size(e)))\n      Intersect then concat(\"the intersection of two regions of size \", toString(this.size(e)))\n      Translate then concat(\"a translated region of size \", toString(this.size(e)))\n}\n//│ mixin Text() {\n//│   this: {size: (Intersect['Region] | Translate[nothing] | Union[nothing] | 'a) -> Int}\n//│   fun text: (Circle | Intersect['Region] | Outside['a] | Translate[anything] | Union[anything]) -> Str\n//│ }\n\n:e\nmodule SizeText extends Text\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.160: \t      Intersect then concat(\"the intersection of two regions of size \", toString(this.size(e)))\n//│ ╙──       \t                                                                                     ^^^^^\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.158: \t      Outside(a) then concat(\"outside a region of size \", toString(this.size(a)))\n//│ ╙──       \t                                                                       ^^^^^\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.161: \t      Translate then concat(\"a translated region of size \", toString(this.size(e)))\n//│ ╙──       \t                                                                         ^^^^^\n//│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size`\n//│ ║  l.159: \t      Union then concat(\"the union of two regions of size \", toString(this.size(e)))\n//│ ╙──       \t                                                                          ^^^^^\n//│ module SizeText {\n//│   fun text: (Circle | Intersect[anything] | Outside[anything] | Translate[anything] | Union[anything]) -> Str\n//│ }\n\n// * Note: this inferred type got *much worse* after this commit (field access type refinement)\nmodule SizeText extends SizeBase, Text\n//│ module SizeText {\n//│   fun size: (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) -> Int\n//│   fun text: 'a -> Str\n//│ }\n//│ where\n//│   'a <: Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]\n\nSizeText.text(circles)\n//│ Str\n//│ res\n//│     = 'the union of two regions of size '\n\nSizeText.size(circles)\n//│ Int\n//│ res\n//│     = 13\n\nSizeText.text(Intersect(Translate(Vector(0, 0), Circle(1)), Circle(1)))\n//│ Str\n//│ res\n//│     = 'the intersection of two regions of size '\n\nSizeText.size(Intersect(Translate(Vector(0, 0), Circle(1)), Circle(1)))\n//│ Int\n//│ res\n//│     = 4\n\nmixin IsUniv {\n  fun isUniv(e) =\n    if e is\n      Univ then true\n      Outside(a) then this.isEmpty(a)\n      Union(a, b) then this.isUniv(a) || this.isUniv(b)\n      Intersect(a, b) then this.isUniv(a) && this.isUniv(b)\n      Translate(_, a) then this.isUniv(a)\n      Scale(_, a) then this.isUniv(a)\n    else false\n}\n//│ mixin IsUniv() {\n//│   this: {isEmpty: 'a -> 'b, isUniv: 'c -> Bool & 'd -> 'b}\n//│   fun isUniv: (Intersect['c] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['d] | Translate['d] | Union['c] | Univ) -> (Bool | 'b)\n//│ }\n\nmixin IsEmpty {\n  fun isEmpty(e) =\n    if e is\n      Univ then true\n      Outside(a) then this.isUniv(a)\n      Union(a, b) then this.isEmpty(a) || this.isEmpty(b)\n      Intersect(a, b) then this.isEmpty(a) && this.isEmpty(b)\n      Translate(_, a) then this.isEmpty(a)\n      Scale(_, a) then this.isEmpty(a)\n    else false\n}\n//│ mixin IsEmpty() {\n//│   this: {isEmpty: 'a -> Bool & 'b -> 'c, isUniv: 'd -> 'c}\n//│   fun isEmpty: (Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['d] | Scale['b] | Translate['b] | Union['a] | Univ) -> (Bool | 'c)\n//│ }\n\nmodule IsUnivIsEmpty extends IsUniv, IsEmpty\n//│ module IsUnivIsEmpty {\n//│   fun isEmpty: 'a -> Bool\n//│   fun isUniv: 'b -> Bool\n//│ }\n//│ where\n//│   'b <: Intersect['b] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['b] | Scale['b] | Translate['b] | Union['b] | Univ\n//│   'a <: Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['a] | Translate['a] | Union['a] | Univ\n\nmodule IsUnivIsEmpty extends IsEmpty, IsUniv\n//│ module IsUnivIsEmpty {\n//│   fun isEmpty: 'a -> Bool\n//│   fun isUniv: 'b -> Bool\n//│ }\n//│ where\n//│   'b <: Intersect['b] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['b] | Scale['b] | Translate['b] | Union['b] | Univ\n//│   'a <: Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['a] | Translate['a] | Union['a] | Univ\n\nIsUnivIsEmpty.isUniv(circles)\n//│ Bool\n//│ res\n//│     = false\n\nIsUnivIsEmpty.isEmpty(circles)\n//│ Bool\n//│ res\n//│     = false\n\nclass Foo()\nIsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles)))\n//│ class Foo()\n//│ Bool\n//│ res\n//│     = false\n\nmixin Eliminate {\n  fun eliminate(e) =\n    if e is\n      Outside(Outside(a)) then this.eliminate(a)\n      Outside(a) then Outside(this.eliminate(a))\n      Union(a, b) then Union(this.eliminate(a), this.eliminate(b))\n      Intersect(a, b) then Intersect(this.eliminate(a), this.eliminate(b))\n      Translate(v, a) then Translate(v, this.eliminate(a))\n      Scale(v, a) then Scale(v, this.eliminate(a))\n    else e\n}\n//│ mixin Eliminate() {\n//│   this: {\n//│     eliminate: 'a -> 'b & 'c -> 'Region & 'd -> 'Region0 & 'e -> 'Region1 & 'f -> 'Region2 & 'g -> 'Region3\n//│   }\n//│   fun eliminate: (Intersect['g] | Object & 'b & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['c & (Object & ~#Outside | Outside['a])] | Scale['f] | Translate['e] | Union['d]) -> (Intersect['Region3] | Outside['Region] | Scale['Region2] | Translate['Region1] | Union['Region0] | 'b)\n//│ }\n\nmodule TestElim extends Eliminate\n//│ module TestElim {\n//│   fun eliminate: 'a -> 'b\n//│ }\n//│ where\n//│   'a <: Intersect['a] | Object & 'b & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['a & (Object & ~#Outside | Outside['a])] | Scale['a] | Translate['a] | Union['a]\n//│   'b :> Intersect['b] | Outside['b] | Scale['b] | Translate['b] | Union['b]\n\nTestElim.eliminate(Outside(Outside(Univ())))\n//│ 'a\n//│   where\n//│     'a :> Intersect['a] | Outside[Univ | 'a] | Scale[Univ | 'a] | Translate[Univ | 'a] | Union[Univ | 'a] | Univ\n//│ res\n//│     = Univ {}\n\nTestElim.eliminate(circles)\n//│ 'a\n//│   where\n//│     'a :> Circle | Intersect['a] | Outside[Circle | 'a] | Scale[Circle | 'a] | Translate[Circle | 'a] | Union[Circle | 'a]\n//│ res\n//│     = Union {}\n\nfun mk(n) = if n is\n  1 then Outside(mk(n))\n  2 then Union(mk(n), mk(n))\n  3 then Intersect(mk(n), mk(n))\n  4 then Translate(Vector(0, 0), mk(n))\n  _ then Scale(Vector(0, 0), mk(n))\n//│ fun mk: forall 'a. Object -> 'a\n//│   where\n//│     'a :> Intersect['a] | Outside['a] | Scale['a] | Translate['a] | Union['a]\n\n:re\nTestElim.eliminate(mk(100))\n//│ 'a\n//│   where\n//│     'a :> Intersect['a] | Outside['a] | Scale['a] | Translate['a] | Union['a]\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// *************************************************************************\n\nmodule Lang extends SizeBase, SizeExt, Contains, Text, IsUniv, IsEmpty, Eliminate\n//│ module Lang {\n//│   fun contains: ('a, {x: Int, y: Int}) -> Bool\n//│   fun eliminate: 'b -> 'c\n//│   fun isEmpty: 'd -> Bool\n//│   fun isUniv: 'e -> Bool\n//│   fun size: 'f -> Int\n//│   fun text: (Circle | Intersect['g] | Outside['g] | Translate['g] | Union['g]) -> Str\n//│ }\n//│ where\n//│   'g <: Empty | Object & (Circle | Intersect['g] | Outside['g] | Translate['g] | Union['g]) & ~#Empty & ~#Scale & ~#Univ | Scale['g] | Univ\n//│   'f <: Empty | Object & (Circle | Intersect['f] | Outside['f] | Translate['f] | Union['f]) & ~#Empty & ~#Scale & ~#Univ | Scale['f] | Univ\n//│   'e <: Intersect['e] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['e] | Scale['e] | Translate['e] | Union['e] | Univ\n//│   'd <: Intersect['d] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['d] | Scale['d] | Translate['d] | Union['d] | Univ\n//│   'b <: Intersect['b] | Object & 'c & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['b & (Object & ~#Outside | Outside['b])] | Scale['b] | Translate['b] | Union['b]\n//│   'c :> Intersect['c] | Outside['c] | Scale['c] | Translate['c] | Union['c]\n//│   'a <: Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]\n\nLang.size(circles)\n//│ Int\n//│ res\n//│     = 13\n\nLang.contains(circles, Vector(0, 0))\n//│ Bool\n//│ res\n//│     = false\n\nLang.text(circles)\n//│ Str\n//│ res\n//│     = 'the union of two regions of size '\n\nLang.isUniv(circles)\n//│ Bool\n//│ res\n//│     = false\n\nLang.isEmpty(circles)\n//│ Bool\n//│ res\n//│     = false\n\nLang.size(Lang.eliminate(circles))\n//│ Int\n//│ res\n//│     = 13\n\n:re\nLang.size(mk(100))\n//│ Int\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\n:re\nLang.contains(mk(100), Vector(0, 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.400: \tLang.contains(mk(100), Vector(0, 0))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[?Region0] | Outside[?Region1] | Translate[?Region2] | Union[?Region3]`\n//│ ║  l.327: \t  _ then Scale(Vector(0, 0), mk(n))\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.113: \t    if a is\n//│ ║         \t       ^\n//│ ╟── from field selection:\n//│ ║  l.13: \tclass Outside[out Region](a: Region)\n//│ ║        \t                          ^\n//│ ╟── Note: type parameter Region is defined at:\n//│ ║  l.13: \tclass Outside[out Region](a: Region)\n//│ ╙──      \t                  ^^^^^^\n//│ error | false | true\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\n:re\nLang.text(mk(100))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.423: \tLang.text(mk(100))\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[?Region0] | Outside[?Region1] | Translate[?Region2] | Union[?Region3]`\n//│ ║  l.327: \t  _ then Scale(Vector(0, 0), mk(n))\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `Circle | Intersect[?Region4] | Outside[?Region5] | Translate[?Region6] | Union[?Region7]`\n//│ ║  l.423: \tLang.text(mk(100))\n//│ ║         \t          ^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.156: \t    if e is\n//│ ╙──       \t       ^\n//│ Str | error\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nLang.isUniv(mk(100))\n//│ Bool\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nLang.isEmpty(mk(100))\n//│ Bool\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nLang.size(Lang.eliminate(mk(100)))\n//│ Int\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "shared/src/test/diff/ex/RepMin.mls",
    "content": ":NewDefs\n\n\n// * https://web.cecs.pdx.edu/~sheard/course/CS457-557/Notes/Laziness-6up.pdf\n// * Example Haskell implementation: https://gist.github.com/23Skidoo/3869595\n\n\nclass defined[out A](val value: A)\ntype Option[A] = defined[A] | ()\n//│ class defined[A](value: A)\n//│ type Option[A] = defined[A] | ()\n\n// * TODO should check the variance; making it covariant should require using private state\nclass Lazy[out A](init: () => A) {\n  mut val cached: Option[A] = ()\n  fun get =\n    if cached is defined(v) then v\n    else\n      let v = init()\n      set cached = defined(v)\n      v\n  fun toString() = join of \"Lazy(\", (if cached is defined(v) then String(v) else \"...\"), \")\"\n}\n//│ class Lazy[A](init: () -> A) {\n//│   mut val cached: Option[A]\n//│   fun get: A\n//│   fun toString: () -> Str\n//│ }\n\nlet l = Lazy(() => (log(\"Hello!\"), 42))\n//│ let l: Lazy[42]\n//│ l\n//│   = Lazy {}\n\nString of l\n//│ Str\n//│ res\n//│     = 'Lazy(...)'\n\nl.get\n//│ 42\n//│ res\n//│     = 42\n//│ // Output\n//│ Hello!\n\nString of l\n//│ Str\n//│ res\n//│     = 'Lazy(42)'\n\nl.get\n//│ 42\n//│ res\n//│     = 42\n\n\ntype Tree[out A] = Leaf[A] | Node[A]\nclass Leaf[out A](val value: A) { fun toString() = join of \"Leaf(\", String(value), \")\" }\nclass Node[out A](val left: Tree[A], val right: Tree[A]) {\n  fun toString() = join of \"Node(\", String(left), \", \", String(right), \")\" }\n//│ type Tree[A] = Leaf[A] | Node[A]\n//│ class Leaf[A](value: A) {\n//│   fun toString: () -> Str\n//│ }\n//│ class Node[A](left: Tree[A], right: Tree[A]) {\n//│   fun toString: () -> Str\n//│ }\n\nString of Leaf(12)\n//│ Str\n//│ res\n//│     = 'Leaf(12)'\n\nfun min(x, y) = if x < y then x else y\n//│ fun min: forall 'a. (Num & 'a, Num & 'a) -> 'a\n\n\n// * An eager walk function just for fun\n\nfun walk(t, mn) = if t is\n  Leaf(n) then [n, Leaf(if n > 2 * mn then mn else n)]\n  Node(l, r) then\n    // * Currently unsupported syntax:\n    // let [mn1, l1] = walk(l, mn)\n    // let [mn2, r1] = walk(r, mn)\n    // [min(mn1, mn2), Node(l1, r1)]\n    let mnl = walk(l, mn)\n    let mnr = walk(r, mn)\n    [min(mnl.0, mnr.0), Node(mnl.1, mnr.1)]\n//│ fun walk: forall 'a 'b. (Leaf[Num & 'a] | Node[Num & 'a], Int & 'b) -> ['a, Leaf['b | 'a] | Node['b | 'a]]\n\n\nlet tree = Node of (Node of (Node of Leaf(1), Leaf(5)), Leaf(3)), Node of Leaf(3), Leaf(2)\n//│ let tree: Node[1 | 2 | 3 | 5]\n//│ tree\n//│      = Node {}\n\nString of tree\n//│ Str\n//│ res\n//│     = 'Node(Node(Node(Leaf(1), Leaf(5)), Leaf(3)), Node(Leaf(3), Leaf(2)))'\n\nString of walk(tree, 2)\n//│ Str\n//│ res\n//│     = '1,Node(Node(Node(Leaf(1), Leaf(2)), Leaf(3)), Node(Leaf(3), Leaf(2)))'\n\nString of walk(tree, 1)\n//│ Str\n//│ res\n//│     = '1,Node(Node(Node(Leaf(1), Leaf(1)), Leaf(1)), Node(Leaf(1), Leaf(2)))'\n\n\n// * An eager walk function using Pair\n\nclass Pair[out A, out B](val left: A, right: B) {\n  fun toString() = join of \"Pair(\", String(left), \", \", String(right), \")\" }\n//│ class Pair[A, B](left: A, right: B) {\n//│   fun toString: () -> Str\n//│ }\n\nfun walk(t, mn) = if t is\n  Leaf(n) then\n    Pair of n, Leaf(if n > 2 * mn then mn else n)\n  Node(l, r) and walk(l, mn) is Pair(mn1, l1) and walk(r, mn) is Pair(mn2, r1) then\n    Pair of min(mn1, mn2), Node(l1, r1)\n//│ fun walk: forall 'A 'a. (Leaf['A] | Node['A], Int & 'a) -> Pair['A, Leaf['a | 'A] | Node['a | 'A]]\n//│   where\n//│     'A <: Num\n\nString of walk(tree, 2)\n//│ Str\n//│ res\n//│     = 'Pair(1, Node(Node(Node(Leaf(1), Leaf(2)), Leaf(3)), Node(Leaf(3), Leaf(2))))'\n\n\n// * A lazy walk function\n\nfun walkLazy(t, mn) = if t is\n  Leaf(n) then\n    log of join of \"Traversing leaf \", String of n\n    [n, Lazy of () => Leaf of if n > 2 * mn.get then mn.get else n]\n  Node(l, r) then\n    let mnl = walkLazy(l, mn)\n    let mnr = walkLazy(r, mn)\n    [min(mnl.0, mnr.0), Lazy of () => Node of mnl.1.get, mnr.1.get]\n//│ fun walkLazy: forall 'a 'get. (Leaf[Num & 'a] | Node[Num & 'a], {get: Int & 'get}) -> ['a, Lazy[Leaf['get | 'a] | Node['get | 'a]]]\n\n\n// * One way to tie the recursive knot\n\nclass repmin(t: Tree[Int]) {\n  val mn_res = walkLazy of t, Lazy of () => mn_res.0\n  val mn = mn_res.0\n  val tree = mn_res.1.get\n}\n//│ class repmin(t: Tree[Int]) {\n//│   val mn: Int\n//│   val mn_res: [Int, Lazy[Leaf[Int] | Node[Int]]]\n//│   val tree: Leaf[Int] | Node[Int]\n//│ }\n\nlet rm = repmin(tree)\n//│ let rm: repmin\n//│ rm\n//│    = repmin {}\n//│ // Output\n//│ Traversing leaf 1\n//│ Traversing leaf 5\n//│ Traversing leaf 3\n//│ Traversing leaf 3\n//│ Traversing leaf 2\n\n[rm.mn, String of rm.tree]\n//│ [Int, Str]\n//│ res\n//│     = [\n//│         1,\n//│         'Node(Node(Node(Leaf(1), Leaf(1)), Leaf(1)), Node(Leaf(1), Leaf(2)))'\n//│       ]\n\n\n// * Another way\n\nfun repmin(t) =\n  module Rec {\n    val mn_res = walkLazy of t, Lazy of () => mn_res.0\n  }\n  [Rec.mn_res.0, Rec.mn_res.1.get]\n//│ fun repmin: forall 'a. (Leaf[Int & 'a] | Node[Int & 'a]) -> ['a, Leaf['a] | Node['a]]\n\nString of repmin(tree)\n//│ Str\n//│ res\n//│     = '1,Node(Node(Node(Leaf(1), Leaf(1)), Leaf(1)), Node(Leaf(1), Leaf(2)))'\n//│ // Output\n//│ Traversing leaf 1\n//│ Traversing leaf 5\n//│ Traversing leaf 3\n//│ Traversing leaf 3\n//│ Traversing leaf 2\n\n\n// * A way that could work but currently doesn't because of a codegen limitation\n\n:ge\nfun repmin(t) =\n  let rec mn_res = walkLazy of t, Lazy(() => mn_res.0)\n  [mn_res.0, mn_res.1.get]\n//│ fun repmin: forall 'a. (Leaf[Int & 'a] | Node[Int & 'a]) -> ['a, Leaf['a] | Node['a]]\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding mn_res\n\n:re\nString of repmin(tree)\n//│ Str\n//│ res\n//│ Runtime error:\n//│   ReferenceError: repmin2 is not defined\n\n\n// * An alternative solution using mutation and thunks instead of laziness\n\nlet IntMax = 2147483648\n//│ let IntMax: 2147483648\n//│ IntMax\n//│        = 2147483648\n\nfun repmin(t) =\n  mut let min = IntMax\n  let rec go(t) = if t is\n    Leaf(n) then\n      log of join of \"Traversing leaf \", String of n\n      if n < min then set min = n else ()\n      () => Leaf of if n > 2 * min then min else n\n    Node(l, r) then\n      let l' = go(l)\n      let r' = go(r)\n      () => Node of l'(), r'()\n  let res = go(t)\n  [min, res()]\n//│ fun repmin: forall 'min. (Leaf[Int & 'min] | Node[Int & 'min]) -> [2147483648 | 'min, Leaf[2147483648 | 'min] | Node[2147483648 | 'min]]\n\nString of repmin(tree)\n//│ Str\n//│ res\n//│     = '1,Node(Node(Node(Leaf(1), Leaf(1)), Leaf(1)), Node(Leaf(1), Leaf(2)))'\n//│ // Output\n//│ Traversing leaf 1\n//│ Traversing leaf 5\n//│ Traversing leaf 3\n//│ Traversing leaf 3\n//│ Traversing leaf 2\n\n\n\n\n// * Aside on UCS parsing:\n\np => if p is Pair of a, b then a + b\n//│ Pair[Int, Int] -> Int\n//│ res\n//│     = [Function: res]\n\n:e // TODO handle this pattern better in the parser?\n(p, q) => if p is Pair of a, b and q is Pair of a', b' then Pair of a + a', b + b'\n//│ ╔══[ERROR] type identifier `and` not found\n//│ ║  l.267: \t(p, q) => if p is Pair of a, b and q is Pair of a', b' then Pair of a + a', b + b'\n//│ ╙──       \t                               ^^^\n//│ ╔══[ERROR] type identifier `is` not found\n//│ ║  l.267: \t(p, q) => if p is Pair of a, b and q is Pair of a', b' then Pair of a + a', b + b'\n//│ ╙──       \t                                     ^^\n//│ ╔══[ERROR] type identifier not found: and\n//│ ║  l.267: \t(p, q) => if p is Pair of a, b and q is Pair of a', b' then Pair of a + a', b + b'\n//│ ╙──       \t                               ^^^\n//│ (Pair[anything, nothing], anything) -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol is\n\n(p, q) => if p is (Pair of a, b) and q is Pair of a', b' then Pair of a + a', b + b'\n//│ (Pair[Int, Int], Pair[Int, Int]) -> Pair[Int, Int]\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ex/UnboxedOptions.mls",
    "content": ":NewDefs\n\n\n// * Similar in spirit to https://github.com/sjrd/scala-unboxed-option\n\n// * In these tests, we need to use an `Object` bound to allow pattern-matching on unboxed option values.\n// * This bound is needed by the type system in order to preserve parametricity in the general case.\n// * However, a real implementation could keep the definition of Opt abstract and do away with the `Object` bound\n// * through unchecked casts without compromising safety or parametricity.\n\n\nmodule None\nclass Some[out A](val value: A)\n//│ module None\n//│ class Some[A](value: A)\n\ntype Opt[out A] = Some[A] | None | A & ~Some & ~None\n//│ type Opt[A] = None | Some[A] | A & ~None & ~#Some\n\n\nfun some(x) = if x is\n  refined(None) then Some(x)\n  refined(Some) then Some(x)\n  else x\n//│ fun some: forall 'a 'b 'c. (None & 'a | Object & 'b & ~#None & ~#Some | Some[anything] & 'c) -> (Some[None & 'a | Some[anything] & 'c] | 'b)\n\nlet some_ = some : forall 'a: (Object & 'a) -> Opt['a]\n//│ let some_: forall 'a. (Object & 'a) -> Opt['a]\n//│ some_\n//│       = [Function: some]\n\n\nfun fold(opt, k, d) = if opt is\n  refined(None) then d\n  refined(Some) then k(opt.value)\n  else k(opt)\n//│ fun fold: forall 'value 'a. (None | Object & 'value & ~#None & ~#Some | Some[anything] & {value: 'value}, 'value -> 'a, 'a) -> 'a\n\nlet fold_ = fold : forall 'a, 'b: (Opt['a] & Object, 'a -> 'b, 'b) -> 'b\n//│ let fold_: forall 'a 'b. (Opt['a] & Object, 'a -> 'b, 'b) -> 'b\n//│ fold_\n//│       = [Function: fold]\n\nlet fold_ = fold : forall 'a, 'b: (Opt['a & Object], 'a -> 'b, 'b) -> 'b\n//│ let fold_: forall 'a 'b. (Opt[Object & 'a], 'a -> 'b, 'b) -> 'b\n//│ fold_\n//│       = [Function: fold]\n\n\n// * Examples using the annotated definitions, which is what things will look like from the outside world.\n\nlet s = some_(42)\n//│ let s: Opt[42]\n//│ s\n//│   = 42\n\ns : Opt[Int]\n//│ Opt[Int]\n//│ res\n//│     = 42\n\nfold_(s, id, 0)\n//│ 0 | 42\n//│ res\n//│     = 42\n\n// * This wont work when `Opt` is made opaque to the outside:\ns : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = 42\n\nlet ss = some_(some_(42))\n//│ let ss: Opt[Opt[42]]\n//│ ss\n//│    = 42\n\n:e\nss : Opt[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.79: \tss : Opt[Int]\n//│ ║        \t^^\n//│ ╟── type `Some['a]` is not an instance of type `Int`\n//│ ║  l.17: \ttype Opt[out A] = Some[A] | None | A & ~Some & ~None\n//│ ║        \t                  ^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.79: \tss : Opt[Int]\n//│ ╙──      \t         ^^^\n//│ Opt[Int]\n//│ res\n//│     = 42\n\nss : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = 42\n\nfold_(ss, o => fold_(o, id, -1), 0)\n//│ -1 | 0 | 42\n//│ res\n//│     = 42\n\n\nlet s = some_(None)\n//│ let s: Opt[None]\n//│ s\n//│   = Some {}\n\n:e\ns : Opt[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.110: \ts : Opt[Int]\n//│ ║         \t^\n//│ ╟── reference of type `None` is not an instance of `Int`\n//│ ║  l.104: \tlet s = some_(None)\n//│ ║         \t              ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.110: \ts : Opt[Int]\n//│ ╙──       \t        ^^^\n//│ Opt[Int]\n//│ res\n//│     = Some {}\n\ns : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = Some {}\n\nfold_(s, o => fold_(o, id, -1), 0)\n//│ -1 | 0\n//│ res\n//│     = -1\n\nsome_(some_(None))\n//│ Opt[Opt[None]]\n//│ res\n//│     = Some {}\n\n:e\nss : Opt[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.140: \tss : Opt[Int]\n//│ ║         \t^^\n//│ ╟── type `Some['a]` is not an instance of type `Int`\n//│ ║  l.17: \ttype Opt[out A] = Some[A] | None | A & ~Some & ~None\n//│ ║        \t                  ^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.140: \tss : Opt[Int]\n//│ ╙──       \t         ^^^\n//│ Opt[Int]\n//│ res\n//│     = 42\n\nss : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = 42\n\nfold_(ss, o => fold_(o, id, -1), 0)\n//│ -1 | 0 | 42\n//│ res\n//│     = 42\n\n\n// * Here we use the precise, unannotated types directly to showcase precise inferred types.\n\nlet s = some(42)\n//│ let s: 42 | Some[nothing]\n//│ s\n//│   = 42\n\ns : Opt[Int]\n//│ Opt[Int]\n//│ res\n//│     = 42\n\nfold(s, id, 0)\n//│ 0 | 42\n//│ res\n//│     = 42\n\ns : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = 42\n\nlet ss = some(some(42))\n//│ let ss: 42 | Some[Some[nothing]]\n//│ ss\n//│    = 42\n\n:e\nss : Opt[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.193: \tss : Opt[Int]\n//│ ║         \t^^\n//│ ╟── application of type `Some[?A]` does not match type `Int | ~Some[anything]`\n//│ ║  l.23: \t  refined(Some) then Some(x)\n//│ ╙──      \t                     ^^^^^^^\n//│ Opt[Int]\n//│ res\n//│     = 42\n\nss : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = 42\n\nfold(ss, o => fold(o, id, -1), 0)\n//│ -1 | 0 | 42\n//│ res\n//│     = 42\n\n\nlet s = some(None)\n//│ let s: Some[None]\n//│ s\n//│   = Some {}\n\n:e\ns : Opt[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.221: \ts : Opt[Int]\n//│ ║         \t^\n//│ ╟── reference of type `None` does not match type `Int | ~None`\n//│ ║  l.215: \tlet s = some(None)\n//│ ╙──       \t             ^^^^\n//│ Opt[Int]\n//│ res\n//│     = Some {}\n\ns : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = Some {}\n\nfold(s, o => fold(o, id, -1), 0)\n//│ -1 | 0\n//│ res\n//│     = -1\n\nsome(some(None))\n//│ Some[Some[None]]\n//│ res\n//│     = Some {}\n\n:e\nss : Opt[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.248: \tss : Opt[Int]\n//│ ║         \t^^\n//│ ╟── application of type `Some[?A]` does not match type `Int | ~Some[anything]`\n//│ ║  l.23: \t  refined(Some) then Some(x)\n//│ ╙──      \t                     ^^^^^^^\n//│ Opt[Int]\n//│ res\n//│     = 42\n\nss : Opt[Opt[Int]]\n//│ Opt[Opt[Int]]\n//│ res\n//│     = 42\n\nfold(ss, o => fold(o, id, -1), 0)\n//│ -1 | 0 | 42\n//│ res\n//│     = 42\n\n\n// * Demonstration that we can't lift a parametric value into an unboxed option without casts.\n\nfun mk(x: Object) = some(x)\n//│ fun mk: (x: Object) -> (Object & ~#None & ~#Some | Some[None | Some[anything]])\n\n:e\nfun mk[A](x: A) = some(x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.276: \tfun mk[A](x: A) = some(x)\n//│ ║         \t                  ^^^^^^^\n//│ ╟── reference of type `A` is not an instance of type `Object`\n//│ ║  l.276: \tfun mk[A](x: A) = some(x)\n//│ ║         \t                       ^\n//│ ╟── Note: constraint arises from `case` expression:\n//│ ║  l.21: \tfun some(x) = if x is\n//│ ║        \t                 ^^^^\n//│ ║  l.22: \t  refined(None) then Some(x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.23: \t  refined(Some) then Some(x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.24: \t  else x\n//│ ║        \t^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.21: \tfun some(x) = if x is\n//│ ║        \t                 ^\n//│ ╟── Note: method type parameter A is defined at:\n//│ ║  l.276: \tfun mk[A](x: A) = some(x)\n//│ ╙──       \t       ^\n//│ fun mk: forall 'A. (x: 'A) -> (Some['A & (None | Some[anything])] | error | 'A & ~#None & ~#Some)\n\nfun mk[A](x: A & Object) = some(x)\n//│ fun mk: forall 'A. (x: Object & 'A) -> (Object & 'A & ~#None & ~#Some | Some['A & (None | Some[anything])])\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/AA.mls",
    "content": "\n// https://github.com/cliffclick/aa/issues/28\npair x y = (x, y)\nI = (fun x->x);  \nK = (fun x->(fun y->x));  \nW = (fun x->(x x));  \nterm = (fun z->(fun y ->((y (z I))(z K))));\ntest = (term W);\n(test (fun x -> (fun y -> (pair (x 3) (((y \"a\") \"b\") \"c\")) ) ))\n//│ pair: 'a -> 'b -> ('a, 'b,)\n//│     = [Function: pair]\n//│ I: 'a -> 'a\n//│  = [Function: I]\n//│ K: 'a -> anything -> 'a\n//│  = [Function: K]\n//│ W: ('a -> 'b & 'a) -> 'b\n//│  = [Function: W]\n//│ term: ((forall 'a. 'a -> 'a) -> 'b & (forall 'c. 'c -> anything -> 'c) -> 'd) -> ('b -> 'd -> 'e) -> 'e\n//│     = [Function: term]\n//│ test: ((forall 'a. 'a -> 'a) -> (forall 'b. anything -> 'b -> anything -> 'b) -> 'c) -> 'c\n//│     = [Function (anonymous)]\n//│ res: (3, \"b\",)\n//│    = [ 3, 'b' ]\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Aleks.mls",
    "content": ":NoJS\n\n\n// ∀x. (x -> x, x -> x)  <:  ∀y. (y -> y, a)\n//   SKOLEM y\n//   FLEX x\n//   x < y < x\n//   x -> x < a -- wrong level\n//     x_L -> x_U < a\n//     where\n//       x_L < x_U\n//       x < x_U\n//       x > x_L\n//       x_U > Top ( > y )\n//       x_L < Bot ( < y )\n\n\ndef foo: forall 'x. ('x -> 'x, 'x -> 'x)\n//│ foo: ('x -> 'x, 'x -> 'x,)\n\n\ndef bar: (forall 'y. ('y -> 'y, 'a)) -> 'a\n//│ bar: (forall 'y. ('y -> 'y, 'a,)) -> 'a\n\nr1 = bar foo\n//│ r1: ??y -> anything\n\n\ndef baz: (forall 'y. ('a, 'y -> 'y)) -> 'a\n//│ baz: (forall 'y. ('a, 'y -> 'y,)) -> 'a\n\nr2 = bar foo\n//│ r2: ??y -> anything\n\n\n\n:e\nr1 id\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.38: \tr1 id\n//│ ║        \t^^^^^\n//│ ╟── type variable `'y` leaks out of its scope\n//│ ║  l.38: \tr1 id\n//│ ║        \t   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.25: \tr1 = bar foo\n//│ ║        \t         ^^^\n//│ ╟── • this reference:\n//│ ║  l.25: \tr1 = bar foo\n//│ ║        \t     ^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.18: \tdef foo: forall 'x. ('x -> 'x, 'x -> 'x)\n//│ ╙──      \t                               ^^\n//│ res: anything\n\n:e\nr2 id\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.58: \tr2 id\n//│ ║        \t^^^^^\n//│ ╟── type variable `'y` leaks out of its scope\n//│ ║  l.58: \tr2 id\n//│ ║        \t   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.32: \tr2 = bar foo\n//│ ║        \t         ^^^\n//│ ╟── • this reference:\n//│ ║  l.32: \tr2 = bar foo\n//│ ║        \t     ^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.18: \tdef foo: forall 'x. ('x -> 'x, 'x -> 'x)\n//│ ╙──      \t                               ^^\n//│ res: anything\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Aliases.mls",
    "content": ":NoJS\n\n\ntype Sid = forall 'A. 'A -> 'A\n//│ Defined type alias Sid\n\ntype Sid2 = 'B -> 'B\n//│ Defined type alias Sid2\n\ntype A1 = forall 'S. 'S -> ('S | Sid)\n//│ Defined type alias A1\n\n\n\ndef a: Sid -> Sid\n//│ a: Sid -> Sid\n\na : Sid2 -> Sid2 : Sid -> Sid\n//│ res: Sid -> Sid\n\na = error : A1\n//│ A1\n//│   <:  a:\n//│ Sid -> Sid\n\n\n// def f: A1 -> Sid\ndef f: A1 -> A1\n//│ f: A1 -> A1\n\ndef f (x: A1) = x id\n//│ A1 -> ('a -> 'a | Sid)\n//│   <:  f:\n//│ A1 -> A1\n\n// def f: A1 -> Sid\ndef f: A1 -> A1\n//│ f: A1 -> A1\n\ndef f (x: Sid -> Sid) = x (fun y -> y)\n//│ (Sid -> Sid) -> Sid\n//│   <:  f:\n//│ A1 -> A1\n\n\ntype A2 = forall 'a. (('a | Sid) -> 'a) -> 'a -> ('a | Sid)\ntype A3 = (Sid -> Sid) -> Sid -> Sid\n//│ Defined type alias A2\n//│ Defined type alias A3\n\nerror : A2 : A3\n//│ res: A3\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Basics.mls",
    "content": ":NoRecursiveTypes\n\n\n\ndef id: forall 'a. 'a -> 'a\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n\ndef id x = x\n//│ 'a -> 'a\n//│   <:  id:\n//│ 'a -> 'a\n//│   = [Function: id1]\n\n\ntest1 f =\n  (f 0, f true)\n//│ test1: (0 -> 'a & true -> 'b) -> ('a, 'b,)\n//│      = [Function: test1]\n\ntest1 (fun value -> { value })\n//│ res: ({value: 0}, {value: true},)\n//│    = [ { value: 0 }, { value: true } ]\n\ntest2 f =\n  let r x = f x\n  in (r 0, r true)\n//│ test2: ((0 | true) -> 'a) -> ('a, 'a,)\n//│      = [Function: test2]\n\ntest2 (fun value -> { value })\n//│ res: ({value: 0 | true}, {value: 0 | true},)\n//│    = [ { value: 0 }, { value: true } ]\n\n\n\n// * From supertype's `freeze-ml.sup`\n\ndef poly f = (f 42, f true)\n//│ poly: (42 -> 'a & true -> 'b) -> ('a, 'b,)\n//│     = [Function: poly]\n\ndef bad1 f = (poly f, f 42 + 1)\ndef bad2 f = (f 42 + 1, poly f)\n//│ bad1: (42 -> (int & 'a) & true -> 'b) -> (('a, 'b,), int,)\n//│     = [Function: bad1]\n//│ bad2: (42 -> (int & 'a) & true -> 'b) -> (int, ('a, 'b,),)\n//│     = [Function: bad2]\n\n\n\ndef example f = (f: forall 'a. 'a -> 'a)\n//│ example: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│        = [Function: example]\n\n:e\nexample 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.57: \texample 1\n//│ ║        \t^^^^^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.57: \texample 1\n//│ ║        \t        ^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.52: \tdef example f = (f: forall 'a. 'a -> 'a)\n//│ ║        \t                               ^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.52: \tdef example f = (f: forall 'a. 'a -> 'a)\n//│ ╙──      \t                 ^\n//│ res: error | 'a -> 'a\n//│    = 1\n\n:e\nexample succ\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.74: \texample succ\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.52: \tdef example f = (f: forall 'a. 'a -> 'a)\n//│ ║        \t                               ^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.52: \tdef example f = (f: forall 'a. 'a -> 'a)\n//│ ╙──      \t                           ^^\n//│ res: error | 'a -> 'a\n//│    = [Function: succ]\n\nexample id\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n\ndef example f = (f: forall 'a. 'a -> int -> 'b) f\n//│ example: (anything -> int -> 'b) -> int -> 'b\n//│        = [Function: example1]\n\ndef example f = ((fun x -> x, f) : forall 'a. ('a -> 'a, 'a -> 'a))\n//│ example: (??a -> ??a0) -> ('a -> 'a, 'a -> 'a,)\n//│        = [Function: example2]\n\ndef example f = ((0, f) : forall 'a. (0, 'a))\n//│ example: ??a -> (0, nothing,)\n//│        = [Function: example3]\n\ndef ex = example\n//│ ex: ??a -> (0, nothing,)\n//│   = [Function: ex]\n\ndef ex x = example x\n//│ ex: ??a -> (0, nothing,)\n//│   = [Function: ex1]\n\n:e\nex 1\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.113: \tex 1\n//│ ║         \t^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.113: \tex 1\n//│ ║         \t   ^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.100: \tdef example f = ((0, f) : forall 'a. (0, 'a))\n//│ ║         \t                     ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.108: \tdef ex x = example x\n//│ ╙──       \t                   ^\n//│ res: error | (0, nothing,)\n//│    = [ 0, 1 ]\n\ndef example f = ((0, f) : forall 'a. (0, 'a -> 'a))\n//│ example: (??a -> ??a0) -> (0, 'a -> 'a,)\n//│        = [Function: example4]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Church_CT.mls",
    "content": ":NoRecursiveTypes\n:ConstrainedTypes\n:DontDistributeForalls\n\n\n\ntype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ Defined type alias ChurchInt\n\n\n\n// * === Explicitly Annotated ===\n\n\ndef zero: forall 'a. ('a -> 'a) -> ('a -> 'a)\ndef zero f x = x\n//│ zero: ('a -> 'a) -> 'a -> 'a\n//│     = <missing implementation>\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  zero:\n//│ ('a -> 'a) -> 'a -> 'a\n//│     = [Function: zero]\n\ndef zero: ChurchInt\ndef zero f x = x\n//│ zero: ChurchInt\n//│     = <missing implementation>\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  zero:\n//│ ChurchInt\n//│     = [Function: zero1]\n\n\ndef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ succ: (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = <missing implementation>\n\n:e // * Since \"sound extrusion\"\ndef succ n f x = f (n f x)\n//│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.39: \tdef succ n f x = f (n f x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                      ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.39: \tdef succ n f x = f (n f x)\n//│ ║        \t           ^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ╙──      \t                             ^^\n//│     = [Function: succ1]\n\ndef succ: ChurchInt -> ChurchInt\n//│ succ: ChurchInt -> ChurchInt\n//│     = <missing implementation>\n\n:e // * Since \"sound extrusion\"\ndef succ n f x = f (n f x)\n//│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.69: \tdef succ n f x = f (n f x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.69: \tdef succ n f x = f (n f x)\n//│ ╙──      \t           ^^^^^^^^^^^^^^^\n//│     = [Function: succ2]\n\n\ndef succD: forall 'M. ChurchInt -> ('M -> 'M) -> ('M -> 'M)\ndef succD n f x = f (n f x)\n//│ succD: ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = <missing implementation>\n//│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│   <:  succD:\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = [Function: succD]\n\nsuccD = succ\n//│ ChurchInt -> ChurchInt\n//│   <:  succD:\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = [Function: succ2]\n\n// * This does not hold without distrobutivity\n:e\nsucc = succD\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.112: \tsucc = succD\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                        ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.112: \tsucc = succD\n//│ ╙──       \t       ^^^^^\n//│     = [Function: succ2]\n\n\n\n// * === Usages ===\n\n\nn1 = succ zero\n//│ n1: ChurchInt\n//│   = [Function (anonymous)]\n\nn2 = succ (succ zero)\n//│ n2: ChurchInt\n//│   = [Function (anonymous)]\n\nn3 = succ (succ (succ zero))\n//│ n3: ChurchInt\n//│   = [Function (anonymous)]\n\n\nwrap x = { x }\n//│ wrap: 'a -> {x: 'a}\n//│     = [Function: wrap]\n\n:e\nn1w = n1 wrap\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> {x: 'a}\n//│ ╙──\n//│ n1w: 'N -> 'N\n//│   where\n//│     'N :> {x: 'N}\n//│    = [Function (anonymous)]\n\n:e\nn1w 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: 0 }\n\n:e\nn1 wrap 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: 0 }\n\n:e\nres.x + 1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.184: \tres.x + 1\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.173: \tn1 wrap 0\n//│ ║         \t        ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.184: \tres.x + 1\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.184: \tres.x + 1\n//│ ║         \t^^^^^^^\n//│ ╟── record literal of type `{x: ?a}` is not an instance of type `int`\n//│ ║  l.146: \twrap x = { x }\n//│ ║         \t         ^^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.184: \tres.x + 1\n//│ ╙──       \t^^^^^\n//│ res: error | int\n//│    = 1\n\n:e\nn2 wrap 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: { x: 0 } }\n\n:e\nres.x.x + 1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.222: \tres.x.x + 1\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.211: \tn2 wrap 0\n//│ ║         \t        ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.222: \tres.x.x + 1\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.222: \tres.x.x + 1\n//│ ║         \t^^^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.211: \tn2 wrap 0\n//│ ║         \t        ^\n//│ ╟── but it flows into field selection with expected type `{x: ?x}`\n//│ ║  l.222: \tres.x.x + 1\n//│ ╙──       \t^^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.222: \tres.x.x + 1\n//│ ║         \t^^^^^^^^^\n//│ ╟── record literal of type `{x: ?a}` is not an instance of type `int`\n//│ ║  l.146: \twrap x = { x }\n//│ ║         \t         ^^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.222: \tres.x.x + 1\n//│ ╙──       \t^^^^^^^\n//│ res: error | int\n//│    = 1\n\n\ndef wrap_ty: 'a -> {x: 'a}\n//│ wrap_ty: 'a -> {x: 'a}\n//│        = <missing implementation>\n\nwrap_ty = wrap\n//│ 'a -> {x: 'a}\n//│   <:  wrap_ty:\n//│ 'a -> {x: 'a}\n//│        = [Function: wrap]\n\n:e\nn1w = n1 wrap_ty\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> {x: 'a}\n//│ ╙──\n//│ n1w: 'N -> 'N\n//│   where\n//│     'N :> {x: 'N}\n//│    = [Function (anonymous)]\n\n:e\nn1w 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: 0 }\n\n:e\nres.x + 1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.291: \tres.x + 1\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.280: \tn1w 0\n//│ ║         \t    ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.291: \tres.x + 1\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.291: \tres.x + 1\n//│ ║         \t^^^^^^^\n//│ ╟── type `{x: 'a}` is not an instance of type `int`\n//│ ║  l.258: \tdef wrap_ty: 'a -> {x: 'a}\n//│ ║         \t                   ^^^^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.291: \tres.x + 1\n//│ ╙──       \t^^^^^\n//│ res: error | int\n//│    = 1\n\n  \n\n// * === Unannotated (More Powerful) ===\n\n\ndef z f x = x\n//│ z: anything -> (forall 'a. 'a -> 'a)\n//│  = [Function: z]\n\ndef s n f x = f (n f x)\n//│ s: 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│  = [Function: s]\n\nzero = z\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  zero:\n//│ ChurchInt\n//│     = [Function: z]\n\n:e // * Since \"sound extrusion\"\nsucc = s\n//│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.340: \tsucc = s\n//│ ║         \t^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.326: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.340: \tsucc = s\n//│ ╙──       \t       ^\n//│     = [Function: s]\n\n:stats\nz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function: z]\n//│ constrain calls  : 16\n//│ annoying  calls  : 0\n//│ subtyping calls  : 33\n\n:e // * Since \"sound extrusion\"\n:stats\ns: ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.375: \ts: ChurchInt -> ChurchInt\n//│ ║         \t^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.326: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.375: \ts: ChurchInt -> ChurchInt\n//│ ╙──       \t^\n//│ res: ChurchInt -> ChurchInt\n//│    = [Function: s]\n//│ constrain calls  : 87\n//│ annoying  calls  : 0\n//│ subtyping calls  : 229\n\n\n\n// * === Usages ===\n\n\nn1 = s z\n//│ n1: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     anything -> (forall 'e. 'e -> 'e) <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd)\n//│   = [Function (anonymous)]\n\nn2 = s (s z)\n//│ n2: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     forall 'e. 'e -> (forall 'f 'g 'h. 'f -> 'h\n//│       where\n//│         anything -> (forall 'i. 'i -> 'i) <: 'e -> 'f -> 'g\n//│         'e <: 'g -> 'h) <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd)\n//│   = [Function (anonymous)]\n\nn3 = s (s (s z))\n//│ n3: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     forall 'e. 'e -> (forall 'f 'g 'h. 'f -> 'h\n//│       where\n//│         forall 'i. 'i -> (forall 'j 'k 'l. 'j -> 'l\n//│           where\n//│             anything -> (forall 'm. 'm -> 'm) <: 'i -> 'j -> 'k\n//│             'i <: 'k -> 'l) <: 'e -> 'f -> 'g\n//│         'e <: 'g -> 'h) <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd)\n//│   = [Function (anonymous)]\n\n\nwrap x = { x }\n//│ wrap: 'a -> {x: 'a}\n//│     = [Function: wrap1]\n\nn1w = n1 wrap\n//│ n1w: 'a -> 'b\n//│   where\n//│     anything -> (forall 'c. 'c -> 'c) <: (forall 'd. 'd -> {x: 'd}) -> 'a -> 'e\n//│     forall 'd. 'd -> {x: 'd} <: 'e -> 'b\n//│    = [Function (anonymous)]\n\nn1w 0\n//│ res: {x: 0}\n//│    = { x: 0 }\n\nn1 wrap 0\n//│ res: {x: 0}\n//│    = { x: 0 }\n\nres.x + 1\n//│ res: int\n//│    = 1\n\nn2 wrap 0\n//│ res: {x: {x: 0}}\n//│    = { x: { x: 0 } }\n\nres.x.x + 1\n//│ res: int\n//│    = 1\n\nn3 wrap 0\n//│ res: {x: {x: {x: 0}}}\n//│    = { x: { x: { x: 0 } } }\n\nres.x.x.x + 1\n//│ res: int\n//│    = 1\n\n\ndef wrap_ty: 'a -> {x: 'a}\n//│ wrap_ty: 'a -> {x: 'a}\n//│        = <missing implementation>\n\nwrap_ty = wrap\n//│ 'a -> {x: 'a}\n//│   <:  wrap_ty:\n//│ 'a -> {x: 'a}\n//│        = [Function: wrap1]\n\nn1w = n1 wrap_ty\n//│ n1w: 'b -> 'c\n//│   where\n//│     anything -> (forall 'd. 'd -> 'd) <: (forall 'a. 'a -> {x: 'a}) -> 'b -> 'e\n//│     forall 'a. 'a -> {x: 'a} <: 'e -> 'c\n//│    = [Function (anonymous)]\n\nn1w 0\n//│ res: {x: 0}\n//│    = { x: 0 }\n\nres.x + 1\n//│ res: int\n//│    = 1\n\nn2 wrap_ty 0\n//│ res: {x: {x: 0}}\n//│    = { x: { x: 0 } }\n\nres.x.x + 1\n//│ res: int\n//│    = 1\n\nn3 wrap_ty 0\n//│ res: {x: {x: {x: 0}}}\n//│    = { x: { x: { x: 0 } } }\n\nres.x.x.x + 1\n//│ res: int\n//│    = 1\n\n\n\n// * === Other Usages ===\n\n\nsz = s zero\n//│ sz: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     ChurchInt <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd)\n//│   = [Function (anonymous)]\n\n:ns\nsz\n//│ res: forall 'a 'b. 'a\n//│   where\n//│     'a :> forall 'c. 'c -> (forall 'd 'e 'f 'g. 'e -> 'g\n//│       where\n//│         'b <: 'c -> 'd\n//│         'c <: 'f -> 'g)\n//│     'd <: 'e -> 'f\n//│     'b :> ChurchInt\n//│    = [Function (anonymous)]\n\nsz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n:e // * Since \"sound extrusion\"\ns zero : ChurchInt\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.544: \ts zero : ChurchInt\n//│ ║         \t^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                             ^^\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n// * Error delayed by inconsistent constrained types\n// * Notice the unsatisfiable constraint `1 <: 'c -> 'b`\nsz1 = sz 1\n//│ sz1: 'a -> 'b\n//│   where\n//│     ChurchInt <: 1 -> 'a -> 'c\n//│     1 <: 'c -> 'b\n//│    = [Function (anonymous)]\n\n:ns\nsz1\n//│ res: forall 'a 'b 'c. 'a\n//│   where\n//│     'a :> forall 'd 'e 'f 'g. 'e -> 'g\n//│       where\n//│         'b <: 'c -> 'd\n//│         'c <: 'f -> 'g\n//│     'd <: 'e -> 'f\n//│     'c :> 1\n//│     'b :> ChurchInt\n//│    = [Function (anonymous)]\n\n:e  // * Since inconsistent constrained types (delayed error from above)\nsz1 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.580: \tsz1 2\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.559: \tsz1 = sz 1\n//│ ║         \t         ^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                            ^^^^^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: f is not a function\n\n\n\n// * === Conversions (Using Annotated Defs) ===\n\n\nrec def to_church n =\n  if n == 0 then zero\n  else succ (to_church (n - 1))\n//│ to_church: int -> ChurchInt\n//│          = [Function: to_church]\n\ndef to_church_ty: int -> ChurchInt\n//│ to_church_ty: int -> ChurchInt\n//│             = <missing implementation>\n\nto_church_ty = to_church\n//│ int -> ChurchInt\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church]\n\n// * Non-recursive def emulates annotated recursive def\ndef to_church_ty n =\n  if n == 0 then zero\n  else succ (to_church_ty (n - 1))\n//│ int -> ChurchInt\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_ty1]\n\n\n\n// * === Conversions (Using Unannotated Defs) ===\n\n:e\nrec def to_ch_s n =\n  if n == 0 then z\n  else s (to_ch_s (n - 1))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. (? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e)\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ to_ch_s: int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('e & 'b) -> ('d | 'e)\n//│   where\n//│     'f <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd))\n//│ where\n//│   'f :> forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('e & 'b) -> ('e | 'd)\n//│     where\n//│       'f <: 'a -> 'b -> 'c\n//│       'a <: 'c -> 'd)\n//│        = [Function: to_ch_s]\n\n:e\nrec def to_ch n =\n  if n == 0 then z\n  else s (to_ch (n - 1))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. (? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e)\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('e & 'b) -> ('d | 'e)\n//│   where\n//│     'f <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd))\n//│ where\n//│   'f :> forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('e & 'b) -> ('e | 'd)\n//│     where\n//│       'f <: 'a -> 'b -> 'c\n//│       'a <: 'c -> 'd)\n//│      = [Function: to_ch]\n\n:e // * Needs distrib (see below)\nto_church_ty = to_ch\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. (? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e)\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('e & 'b) -> ('d | 'e)\n//│   where\n//│     'f <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd))\n//│ where\n//│   'f :> forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('e & 'b) -> ('e | 'd)\n//│     where\n//│       'f <: 'a -> 'b -> 'c\n//│       'a <: 'c -> 'd)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch. ?to_ch <: int -> ChurchInt` exceeded recursion depth limit (250)\n//│ ║  l.673: \tto_church_ty = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch]\n\n:e\nrec def to_ch_simplif n = s (to_ch_simplif n)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ to_ch_simplif: anything -> 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│              = [Function: to_ch_simplif]\n\n:e\nto_church_ty = to_ch_simplif\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ anything -> 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch_simplif. ?to_ch_simplif <: int -> ChurchInt` exceeded recursion depth limit (250)\n//│ ║  l.716: \tto_church_ty = to_ch_simplif\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch_simplif]\n\n\n// * This annotation now only helps when also having :precise-rec-typing (see below)\n:e\nrec def to_ch_A1 n =\n  if n == 0 then z\n  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.741: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.742: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.743: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                             ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.741: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.742: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.743: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                             ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.741: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.742: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.743: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.326: \tdef s n f x = f (n f x)\n//│ ╙──       \t                 ^^^^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.741: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.742: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.743: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.326: \tdef s n f x = f (n f x)\n//│ ╙──       \t                 ^^^^^\n//│ to_ch_A1: int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e)\n//│   where\n//│     ChurchInt <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd))\n//│         = [Function: to_ch_A1]\n\n:precise-rec-typing\n:e // occurs-check\nrec def to_ch_A1 n =\n  if n == 0 then z\n  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ╔══[ERROR] Inferred recursive type: 'to_ch_A1\n//│   where\n//│     'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. (? & 'a) -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e)\n//│       where\n//│         ChurchInt <: 'a -> 'b -> 'c\n//│         'a <: 'c -> 'd))\n//│     where\n//│       'to_ch_A1 <: int -> ChurchInt\n//│ ╙──\n//│ to_ch_A1: 'to_ch_A1\n//│   where\n//│     'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e)\n//│       where\n//│         ChurchInt <: 'a -> 'b -> 'c\n//│         'a <: 'c -> 'd))\n//│     where\n//│       'to_ch_A1 <: int -> ChurchInt\n//│         = [Function: to_ch_A11]\n\n// * But we can't check the corresponding type\n:e\nto_church_ty = to_ch_A1\n//│ ╔══[ERROR] Inferred recursive type: 'to_ch_A1\n//│   where\n//│     'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. (? & 'a) -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e)\n//│       where\n//│         ChurchInt <: 'a -> 'b -> 'c\n//│         'a <: 'c -> 'd))\n//│     where\n//│       'to_ch_A1 <: int -> ChurchInt\n//│ ╙──\n//│ 'to_ch_A1\n//│   where\n//│     'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e)\n//│       where\n//│         ChurchInt <: 'a -> 'b -> 'c\n//│         'a <: 'c -> 'd))\n//│     where\n//│       'to_ch_A1 <: int -> ChurchInt\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required\n//│ ║  l.834: \tto_church_ty = to_ch_A1\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch_A11]\n\n// * Similarly:\n:e\nrec def to_ch_A2 n = (\n    if n == 0 then z\n    else s (to_ch_A2 (n - 1))\n  ) : ChurchInt\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.862: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.863: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.864: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.865: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                             ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.862: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.863: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.864: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.865: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                             ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.862: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.863: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.864: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.865: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.326: \tdef s n f x = f (n f x)\n//│ ╙──       \t                 ^^^^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.862: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.863: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.864: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.865: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.326: \tdef s n f x = f (n f x)\n//│ ╙──       \t                 ^^^^^\n//│ to_ch_A2: int -> ChurchInt\n//│         = [Function: to_ch_A2]\n\n:precise-rec-typing\n:e // occurs-check\nrec def to_ch_A2 n = (\n    if n == 0 then z\n    else s (to_ch_A2 (n - 1))\n  ) : ChurchInt\n//│ ╔══[ERROR] Inferred recursive type: 'to_ch_A2\n//│   where\n//│     'to_ch_A2 :> forall 'to_ch_A2. int -> ChurchInt\n//│       where\n//│         'to_ch_A2 <: int -> (??N -> ??N0) -> ??N0 -> ??N\n//│ ╙──\n//│ to_ch_A2: 'to_ch_A2\n//│   where\n//│     'to_ch_A2 :> forall 'to_ch_A2. int -> ChurchInt\n//│       where\n//│         'to_ch_A2 <: int -> (??N -> ??N0) -> ??N0 -> ??N\n//│         = [Function: to_ch_A21]\n\n:e // * Since the removal of \"recursive definition hacks\"\nto_church_ty = to_ch_A2\n//│ ╔══[ERROR] Inferred recursive type: 'to_ch_A2\n//│   where\n//│     'to_ch_A2 :> forall 'to_ch_A2. int -> ChurchInt\n//│       where\n//│         'to_ch_A2 <: int -> (??N -> ??N0) -> ??N0 -> ??N\n//│ ╙──\n//│ 'to_ch_A2\n//│   where\n//│     'to_ch_A2 :> forall 'to_ch_A2. int -> ChurchInt\n//│       where\n//│         'to_ch_A2 <: int -> (??N -> ??N0) -> ??N0 -> ??N\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required\n//│ ║  l.955: \tto_church_ty = to_ch_A2\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch_A21]\n\n\n// * Uses `to_church` as the rec call\ndef to_church_mix n =\n  if n == 0 then z\n  else s (to_church (n - 1))\n//│ to_church_mix: int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e)\n//│   where\n//│     ChurchInt <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd))\n//│              = [Function: to_church_mix]\n\n:e\nto_church_ty = to_church_mix\n//│ int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e)\n//│   where\n//│     ChurchInt <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd))\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.987: \tto_church_ty = to_church_mix\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.326: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.979: \t  else s (to_church (n - 1))\n//│ ║         \t       ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.987: \tto_church_ty = to_church_mix\n//│ ╙──       \t               ^^^^^^^^^^^^^\n//│             = [Function: to_church_mix]\n\n\n:e\n// * It would seem we need to distribute back (in the other direction) here, but it works:\n:precise-rec-typing\nrec def to_chD n =\n  succD (to_chD n)\n//│ ╔══[ERROR] Inferred recursive type: 'to_chD\n//│   where\n//│     'to_chD :> forall 'a 'M. 'a -> ('M -> 'M) -> 'M -> 'M\n//│       where\n//│         'to_chD <: 'a -> ChurchInt\n//│ ╙──\n//│ to_chD: 'to_chD\n//│   where\n//│     'to_chD :> forall 'a 'M. 'a -> ('M -> 'M) -> 'M -> 'M\n//│       where\n//│         'to_chD <: 'a -> ChurchInt\n//│       = [Function: to_chD]\n\n\n\n// * === With Distributivity ===\n\n\n:DistributeForalls\n\n\n// * Now everything Just Works!\n\n\n// * Now works\nsucc = s\n//│ 'a -> 'b -> ('c -> 'd\n//│   where\n//│     'a <: 'b -> 'c -> 'e\n//│     'b <: 'e -> 'd)\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│     = [Function: s]\n\n// * Now works\nsucc = succD\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│     = [Function: succ2]\n\n// * Now works\nrec def to_chD n =\n  succD (to_chD n)\n//│ to_chD: anything -> ('M -> 'M) -> 'M -> 'M\n//│       = [Function: to_chD1]\n\n:e // * Since the removal of \"recursive definition hacks\"\nto_church_ty = to_ch\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e 'f. (? & 'b) -> (('f & 'c) -> ('f | 'e)\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ int -> 'a -> ('b -> ('c | 'b)\n//│   where\n//│     'd <: 'a -> 'b -> 'e\n//│     'a <: 'e -> 'c)\n//│ where\n//│   'd :> forall 'f 'g 'h 'i 'j. 'f -> (('j & 'g) -> ('j | 'i)\n//│     where\n//│       'd <: 'f -> 'g -> 'h\n//│       'f <: 'h -> 'i)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch. ?to_ch <: int -> ChurchInt` exceeded recursion depth limit (250)\n//│ ║  l.1069: \tto_church_ty = to_ch\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch]\n\n:e // * Since the removal of \"recursive definition hacks\"\nto_church_ty = to_ch_simplif\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e. 'b -> ('c -> 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ anything -> 'a -> ('b -> 'c\n//│   where\n//│     'd <: 'a -> 'b -> 'e\n//│     'a <: 'e -> 'c)\n//│ where\n//│   'd :> forall 'f 'g 'h 'i. 'f -> ('g -> 'i\n//│     where\n//│       'd <: 'f -> 'g -> 'h\n//│       'f <: 'h -> 'i)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required\n//│ ║  l.1095: \tto_church_ty = to_ch_simplif\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch_simplif]\n\n// * Redefinition in the context of distrib, just for the record (still infers but doesn't check)\n:e\nrec def to_ch_simplif n = s (to_ch_simplif n)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e. 'b -> ('c -> 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ to_ch_simplif: anything -> 'a -> ('b -> 'c\n//│   where\n//│     'd <: 'a -> 'b -> 'e\n//│     'a <: 'e -> 'c)\n//│ where\n//│   'd :> forall 'f 'g 'h 'i. 'f -> ('g -> 'i\n//│     where\n//│       'd <: 'f -> 'g -> 'h\n//│       'f <: 'h -> 'i)\n//│              = [Function: to_ch_simplif1]\n\n:e // * Since the removal of \"recursive definition hacks\"\nto_church_ty = to_ch_simplif\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e. 'b -> ('c -> 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'd\n//│         'b <: 'd -> 'e)\n//│ ╙──\n//│ anything -> 'a -> ('b -> 'c\n//│   where\n//│     'd <: 'a -> 'b -> 'e\n//│     'a <: 'e -> 'c)\n//│ where\n//│   'd :> forall 'f 'g 'h 'i. 'f -> ('g -> 'i\n//│     where\n//│       'd <: 'f -> 'g -> 'h\n//│       'f <: 'h -> 'i)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required\n//│ ║  l.1142: \tto_church_ty = to_ch_simplif\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch_simplif1]\n\n// * Still doesn't work (Same with the full definition)\n:e\nto_church_ty = to_ch_A1\n//│ ╔══[ERROR] Inferred recursive type: 'to_ch_A1\n//│   where\n//│     'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a 'b 'c 'd 'e. (? & 'a) -> (('b & 'e) -> ('d | 'e)\n//│       where\n//│         ChurchInt <: 'a -> 'b -> 'c\n//│         'a <: 'c -> 'd))\n//│     where\n//│       'to_ch_A1 <: int -> ChurchInt\n//│ ╙──\n//│ 'to_ch_A1\n//│   where\n//│     'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a 'b 'c 'd 'e. 'a -> (('b & 'e) -> ('d | 'e)\n//│       where\n//│         ChurchInt <: 'a -> 'b -> 'c\n//│         'a <: 'c -> 'd))\n//│     where\n//│       'to_ch_A1 <: int -> ChurchInt\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required\n//│ ║  l.1169: \tto_church_ty = to_ch_A1\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│             = [Function: to_ch_A11]\n\n// * Now works\nto_church_ty = to_church_mix\n//│ int -> 'a -> ('b -> ('c | 'b)\n//│   where\n//│     ChurchInt <: 'a -> 'b -> 'd\n//│     'a <: 'd -> 'c)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_mix]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Church_ST.mls",
    "content": ":NoRecursiveTypes\n:NoConstrainedTypes\n:DontDistributeForalls\n\n\n\ntype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ Defined type alias ChurchInt\n\n\n\n// * === Explicitly Annotated ===\n\n\ndef zero: forall 'a. ('a -> 'a) -> ('a -> 'a)\ndef zero f x = x\n//│ zero: ('a -> 'a) -> 'a -> 'a\n//│     = <missing implementation>\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  zero:\n//│ ('a -> 'a) -> 'a -> 'a\n//│     = [Function: zero]\n\ndef zero: ChurchInt\ndef zero f x = x\n//│ zero: ChurchInt\n//│     = <missing implementation>\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  zero:\n//│ ChurchInt\n//│     = [Function: zero1]\n\n\ndef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ succ: (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = <missing implementation>\n\n// * When we don't infer constrained types and extrude eagerly instead,\n// * this one requires distributing the RHS forall to rigidify it earlier:\n:e\ndef succ n f x = f (n f x)\n//│ ('a -> 'b -> 'c) -> (forall 'd. ('c -> 'd & 'a) -> 'b -> 'd)\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.41: \tdef succ n f x = f (n f x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                      ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.41: \tdef succ n f x = f (n f x)\n//│ ║        \t           ^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ╙──      \t                             ^^\n//│     = [Function: succ1]\n\n// * This explicit annotation makes it type check; like in MLF:\ndef succ (n: (forall 'N. ('N -> 'N) -> ('N -> 'N))) = fun f -> fun x -> f (n f x)\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'N0 'N1 'a. ('N0 -> ('N0 & 'N1) & 'N1 -> 'a) -> ('N0 & 'N1) -> 'a)\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = [Function: succ2]\n\ndef succ (n: ChurchInt) f x = f (n f x)\n//│ ChurchInt -> (forall 'N 'N0 'a. ('N -> ('N & 'N0) & 'N0 -> 'a) -> ('N & 'N0) -> 'a)\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = [Function: succ3]\n\n// * Manually distributing the signature also fixes the type checking:\ndef succD: forall 'M. ChurchInt -> ('M -> 'M) -> ('M -> 'M)\ndef succD n f x = f (n f x)\n//│ succD: ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = <missing implementation>\n//│ ('a -> 'b -> 'c) -> (forall 'd. ('c -> 'd & 'a) -> 'b -> 'd)\n//│   <:  succD:\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = [Function: succD]\n\nsuccD = succ\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│   <:  succD:\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = [Function: succ3]\n\n// * This does not hold without distrobutivity\n:e\nsucc = succD\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.94: \tsucc = succD\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                      ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.94: \tsucc = succD\n//│ ║        \t       ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.77: \tdef succD: forall 'M. ChurchInt -> ('M -> 'M) -> ('M -> 'M)\n//│ ╙──      \t                                          ^^\n//│     = [Function: succ3]\n\n\n\n// * === Usages ===\n\n\nn1 = succ zero\n//│ n1: ('M -> 'M) -> 'M -> 'M\n//│   = [Function (anonymous)]\n\nn2 = succ (succ zero)\n//│ n2: ('M -> 'M) -> 'M -> 'M\n//│   = [Function (anonymous)]\n\nn3 = succ (succ (succ zero))\n//│ n3: ('M -> 'M) -> 'M -> 'M\n//│   = [Function (anonymous)]\n\n\nwrap x = { x }\n//│ wrap: 'a -> {x: 'a}\n//│     = [Function: wrap]\n\n:e\nn1w = n1 wrap\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> {x: 'a}\n//│ ╙──\n//│ n1w: 'M -> 'M\n//│   where\n//│     'M :> {x: 'M}\n//│    = [Function (anonymous)]\n\n:e\nn1w 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: 0 }\n\n:e\nn1 wrap 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: 0 }\n\n:e\nres.x + 1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.172: \tres.x + 1\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.161: \tn1 wrap 0\n//│ ║         \t        ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.172: \tres.x + 1\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.172: \tres.x + 1\n//│ ║         \t^^^^^^^\n//│ ╟── record literal of type `{x: ?a}` is not an instance of type `int`\n//│ ║  l.134: \twrap x = { x }\n//│ ║         \t         ^^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.172: \tres.x + 1\n//│ ╙──       \t^^^^^\n//│ res: error | int\n//│    = 1\n\n:e\nn2 wrap 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: { x: 0 } }\n\n:e\nres.x.x + 1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.210: \tres.x.x + 1\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.199: \tn2 wrap 0\n//│ ║         \t        ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.210: \tres.x.x + 1\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.210: \tres.x.x + 1\n//│ ║         \t^^^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.199: \tn2 wrap 0\n//│ ║         \t        ^\n//│ ╟── but it flows into field selection with expected type `{x: ?x}`\n//│ ║  l.210: \tres.x.x + 1\n//│ ╙──       \t^^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.210: \tres.x.x + 1\n//│ ║         \t^^^^^^^^^\n//│ ╟── record literal of type `{x: ?a}` is not an instance of type `int`\n//│ ║  l.134: \twrap x = { x }\n//│ ║         \t         ^^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.210: \tres.x.x + 1\n//│ ╙──       \t^^^^^^^\n//│ res: error | int\n//│    = 1\n\n\ndef wrap_ty: 'a -> {x: 'a}\n//│ wrap_ty: 'a -> {x: 'a}\n//│        = <missing implementation>\n\nwrap_ty = wrap\n//│ 'a -> {x: 'a}\n//│   <:  wrap_ty:\n//│ 'a -> {x: 'a}\n//│        = [Function: wrap]\n\n:e\nn1w = n1 wrap_ty\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> {x: 'a}\n//│ ╙──\n//│ n1w: 'M -> 'M\n//│   where\n//│     'M :> {x: 'M}\n//│    = [Function (anonymous)]\n\n:e\nn1w 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│    = { x: 0 }\n\n:e\nres.x + 1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.279: \tres.x + 1\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `0` does not have field 'x'\n//│ ║  l.268: \tn1w 0\n//│ ║         \t    ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.279: \tres.x + 1\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.279: \tres.x + 1\n//│ ║         \t^^^^^^^\n//│ ╟── type `{x: 'a}` is not an instance of type `int`\n//│ ║  l.246: \tdef wrap_ty: 'a -> {x: 'a}\n//│ ║         \t                   ^^^^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.279: \tres.x + 1\n//│ ╙──       \t^^^^^\n//│ res: error | int\n//│    = 1\n\n\n\n// * === Unannotated (More Powerful) ===\n\n\ndef z f x = x\n//│ z: anything -> (forall 'a. 'a -> 'a)\n//│  = [Function: z]\n\ndef s n f x = f (n f x)\n//│ s: ('a -> 'b -> 'c) -> (forall 'd. ('c -> 'd & 'a) -> 'b -> 'd)\n//│  = [Function: s]\n\ndef s_A1 (n: ChurchInt) f x = f (n f x)\n//│ s_A1: ChurchInt -> (forall 'N 'N0 'a. ('N -> ('N & 'N0) & 'N0 -> 'a) -> ('N & 'N0) -> 'a)\n//│     = [Function: s_A1]\n\nzero = z\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  zero:\n//│ ChurchInt\n//│     = [Function: z]\n\n// * Similalry as before, unannotated succ impl requires constrained types\n:e\nsucc = s\n//│ ('a -> 'b -> 'c) -> (forall 'd. ('c -> 'd & 'a) -> 'b -> 'd)\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.330: \tsucc = s\n//│ ║         \t^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                      ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                                                ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.330: \tsucc = s\n//│ ║         \t       ^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.34: \tdef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ╙──      \t                             ^^\n//│     = [Function: s]\n\nsucc = s_A1\n//│ ChurchInt -> (forall 'N 'N0 'a. ('N -> ('N & 'N0) & 'N0 -> 'a) -> ('N & 'N0) -> 'a)\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = [Function: s_A1]\n\nsuccD = s\n//│ ('a -> 'b -> 'c) -> (forall 'd. ('c -> 'd & 'a) -> 'b -> 'd)\n//│   <:  succD:\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = [Function: s]\n\n:stats\nz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function: z]\n//│ constrain calls  : 16\n//│ annoying  calls  : 0\n//│ subtyping calls  : 33\n\n:e\n:stats\ns: ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.377: \ts: ChurchInt -> ChurchInt\n//│ ║         \t^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.377: \ts: ChurchInt -> ChurchInt\n//│ ╙──       \t^\n//│ res: ChurchInt -> ChurchInt\n//│    = [Function: s]\n//│ constrain calls  : 90\n//│ annoying  calls  : 0\n//│ subtyping calls  : 255\n\n\n\n// * === Usages ===\n\n\n// * Interestingly, even without constrained types,\n// * we can still use these inferred types to check the following uses:\n\n\nn1 = s z\n//│ n1: ('a -> 'b) -> 'a -> 'b\n//│   = [Function (anonymous)]\n\nn2 = s (s z)\n//│ n2: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│   = [Function (anonymous)]\n\nn3 = s (s (s z))\n//│ n3: ('a -> 'b & 'b -> 'c & 'c -> 'd) -> 'a -> 'd\n//│   = [Function (anonymous)]\n\n\nwrap x = { x }\n//│ wrap: 'a -> {x: 'a}\n//│     = [Function: wrap1]\n\nn1w = n1 wrap\n//│ n1w: 'a -> {x: 'a}\n//│    = [Function (anonymous)]\n\nn1w 0\n//│ res: {x: 0}\n//│    = { x: 0 }\n\nn1 wrap 0\n//│ res: {x: 0}\n//│    = { x: 0 }\n\nres.x + 1\n//│ res: int\n//│    = 1\n\nn2 wrap 0\n//│ res: {x: {x: 0}}\n//│    = { x: { x: 0 } }\n\nres.x.x + 1\n//│ res: int\n//│    = 1\n\nn3 wrap 0\n//│ res: {x: {x: {x: 0}}}\n//│    = { x: { x: { x: 0 } } }\n\nres.x.x.x + 1\n//│ res: int\n//│    = 1\n\n\ndef wrap_ty: 'a -> {x: 'a}\n//│ wrap_ty: 'a -> {x: 'a}\n//│        = <missing implementation>\n\nwrap_ty = wrap\n//│ 'a -> {x: 'a}\n//│   <:  wrap_ty:\n//│ 'a -> {x: 'a}\n//│        = [Function: wrap1]\n\nn1w = n1 wrap_ty\n//│ n1w: 'a -> {x: 'a}\n//│    = [Function (anonymous)]\n\nn1w 0\n//│ res: {x: 0}\n//│    = { x: 0 }\n\nres.x + 1\n//│ res: int\n//│    = 1\n\nn2 wrap_ty 0\n//│ res: {x: {x: 0}}\n//│    = { x: { x: 0 } }\n\nres.x.x + 1\n//│ res: int\n//│    = 1\n\nn3 wrap_ty 0\n//│ res: {x: {x: {x: 0}}}\n//│    = { x: { x: { x: 0 } } }\n\nres.x.x.x + 1\n//│ res: int\n//│    = 1\n\n\n\n// * === Conversions (Using Annotated Defs) ===\n\n\nrec def to_church n =\n  if n == 0 then zero\n  else succ (to_church (n - 1))\n//│ to_church: int -> (forall 'M. ('M -> 'M) -> 'M -> 'M | ChurchInt)\n//│          = [Function: to_church]\n\ndef to_church_ty: int -> ChurchInt\n//│ to_church_ty: int -> ChurchInt\n//│             = <missing implementation>\n\nto_church_ty = to_church\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M | ChurchInt)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church]\n\n// * Non-recursive def emulates annotated recursive def\ndef to_church_ty n =\n  if n == 0 then zero\n  else succ (to_church_ty (n - 1))\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M | ChurchInt)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_ty1]\n\n\n\n// * === Other Usages ===\n\n\nsz = s zero\n//│ sz: ('N -> ('N & 'a)) -> 'N -> 'a\n//│   = [Function (anonymous)]\n\n:ns\nsz\n//│ res: forall 'a 'b 'c 'd 'N. 'a\n//│   where\n//│     'a :> forall 'e 'f 'g. 'e -> (forall 'h 'i. 'h -> 'i)\n//│     'i :> 'g\n//│     'h <: 'c\n//│     'c <: 'N\n//│     'e <: 'f -> 'g & 'b\n//│     'b <: 'N -> 'N\n//│     'N <: 'd\n//│     'f :> 'd\n//│    = [Function (anonymous)]\n\nsz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n// * This one works with CT...\n// * Apparently worked when generalizing the LHS of ascriptions\n:e\ns zero : ChurchInt\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.557: \ts zero : ChurchInt\n//│ ║         \t^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.557: \ts zero : ChurchInt\n//│ ╙──       \t^^^^^^\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n// * Unlike with CT, here the error is not delayed\n:e\nsz1 = sz 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.579: \tsz1 = sz 1\n//│ ║         \t      ^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.579: \tsz1 = sz 1\n//│ ║         \t         ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t              ^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t              ^\n//│ sz1: error | anything -> nothing\n//│    = [Function (anonymous)]\n\n:re\nsz1 2\n//│ res: error\n//│ Runtime error:\n//│   TypeError: f is not a function\n\n\n\n// * === Conversions (Using Unannotated Defs) ===\n\nrec def to_ch_s n =\n  if n == 0 then z\n  else s (to_ch_s (n - 1))\n//│ to_ch_s: int -> (forall 'a. ('b -> 'a & 'b -> 'b) -> (forall 'c. ('b & 'c) -> ('a | 'c)))\n//│        = [Function: to_ch_s]\n\n\n// Q: what's the difference with to_ch_s?!\nrec def to_ch n =\n  if n == 0 then z\n  else s (to_ch (n - 1))\n//│ to_ch: int -> (forall 'a. ('b -> 'a & 'b -> 'b) -> (forall 'c. ('b & 'c) -> ('a | 'c)))\n//│      = [Function: to_ch]\n\n:e // * Needs distrib (see below)\nto_church_ty = to_ch\n//│ int -> (forall 'a. ('b -> 'a & 'b -> 'b) -> (forall 'c. ('b & 'c) -> ('a | 'c)))\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.620: \tto_church_ty = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.615: \t  else s (to_ch (n - 1))\n//│ ║         \t       ^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.620: \tto_church_ty = to_ch\n//│ ║         \t               ^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t              ^^^^^^^^^\n//│             = [Function: to_ch]\n\n// * Works with version where `s` has annotated `n: ChurchInt` parameter\nrec def to_ch_s_A1 n =\n  if n == 0 then z\n  else s_A1 (to_ch_s_A1 (n - 1))\n//│ to_ch_s_A1: int -> (forall 'N 'N0 'a. ('N -> ('N & 'N0) & 'N0 -> 'a) -> (forall 'b. ('N & 'N0 & 'b) -> ('a | 'b)))\n//│           = [Function: to_ch_s_A1]\n\nto_church_ty = to_ch_s_A1\n//│ int -> (forall 'N 'N0 'a. ('N -> ('N & 'N0) & 'N0 -> 'a) -> (forall 'b. ('N & 'N0 & 'b) -> ('a | 'b)))\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_ch_s_A1]\n\n// * Boil down the problem with `to_ch`\nrec def to_ch_simplif n = s (to_ch_simplif n)\n//│ to_ch_simplif: anything -> (forall 'a. ('b -> 'a & 'b -> 'b) -> anything -> 'a)\n//│              = [Function: to_ch_simplif]\n\n:e\nto_church_ty = to_ch_simplif\n//│ anything -> (forall 'a. ('b -> 'a & 'b -> 'b) -> anything -> 'a)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.667: \tto_church_ty = to_ch_simplif\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.662: \trec def to_ch_simplif n = s (to_ch_simplif n)\n//│ ║         \t                          ^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.667: \tto_church_ty = to_ch_simplif\n//│ ║         \t               ^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t              ^^^^^^^^^\n//│             = [Function: to_ch_simplif]\n\n\n// * This annotation here doesn't help\n:e\nrec def to_ch_A1 n =\n  if n == 0 then z\n  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.698: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.699: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t          ^^^^^^^^^^^^^^^^\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t        ^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.698: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.699: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t          ^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t                 ^^^^^\n//│ ╟── • this applied expression:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t              ^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.698: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.699: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t          ^^^^^^^^^^^^^^^^\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t          ^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t                     ^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.698: \trec def to_ch_A1 n =\n//│ ║         \t                 ^^^\n//│ ║  l.699: \t  if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t          ^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t                 ^^^^^\n//│ ╟── • this applied expression:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t              ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t                     ^\n//│ to_ch_A1: int -> (forall 'a. (anything -> (??N & 'N & 'a)) -> (forall 'b. (??N & 'N & 'b) -> ('a | 'b)))\n//│         = [Function: to_ch_A1]\n\n// * nope\n// to_church_ty = to_ch_A1\n\n// * This annotation makes it work with Constrained Types, but not without them!!\n:e\nrec def to_ch_A2 n = (\n    if n == 0 then z\n    else s (to_ch_A2 (n - 1))\n  ) : ChurchInt\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.801: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.802: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.804: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ╙──       \t         ^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.801: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.802: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.804: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t          ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ╙──       \t         ^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.801: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.802: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.804: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t                 ^^^^^\n//│ ╟── • this applied expression:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t              ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t                 ^^^^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.801: \trec def to_ch_A2 n = (\n//│ ║         \t                 ^^^^^\n//│ ║  l.802: \t    if n == 0 then z\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.804: \t  ) : ChurchInt\n//│ ║         \t^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.803: \t    else s (to_ch_A2 (n - 1))\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t                 ^^^^^\n//│ ╟── • this applied expression:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t              ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t                 ^^^^^\n//│ to_ch_A2: int -> ChurchInt\n//│         = [Function: to_ch_A2]\n\nto_church_ty = to_ch_A2\n//│ int -> ChurchInt\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_ch_A2]\n\n\n// * Uses `to_church` as the rec call\ndef to_church_mix n =\n  if n == 0 then z\n  else s (to_church (n - 1))\n//│ to_church_mix: int -> (forall 'a. ('M -> ('M & 'b) & 'N -> ('b & 'N) & 'b -> 'a) -> (forall 'c. ('M & 'b & 'N & 'c) -> ('a | 'c)))\n//│              = [Function: to_church_mix]\n\n// * Works with Constrained Types\n:e\nto_church_ty = to_church_mix\n//│ int -> (forall 'a. ('M -> ('M & 'b) & 'N -> ('b & 'N) & 'b -> 'a) -> (forall 'c. ('M & 'b & 'N & 'c) -> ('a | 'c)))\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.924: \tto_church_ty = to_church_mix\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.918: \t  else s (to_church (n - 1))\n//│ ║         \t       ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.924: \tto_church_ty = to_church_mix\n//│ ╙──       \t               ^^^^^^^^^^^^^\n//│             = [Function: to_church_mix]\n\n\n:e // * Needs to distribute back (in the other direction) here:\nrec def to_chD n =\n  succD (to_chD n)\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.951: \trec def to_chD n =\n//│ ║         \t               ^^^\n//│ ║  l.952: \t  succD (to_chD n)\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.77: \tdef succD: forall 'M. ChurchInt -> ('M -> 'M) -> ('M -> 'M)\n//│ ╙──      \t                                          ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.951: \trec def to_chD n =\n//│ ║         \t               ^^^\n//│ ║  l.952: \t  succD (to_chD n)\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.77: \tdef succD: forall 'M. ChurchInt -> ('M -> 'M) -> ('M -> 'M)\n//│ ╙──      \t                                                  ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.951: \trec def to_chD n =\n//│ ║         \t               ^^^\n//│ ║  l.952: \t  succD (to_chD n)\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                                                 ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.951: \trec def to_chD n =\n//│ ║         \t               ^^^\n//│ ║  l.952: \t  succD (to_chD n)\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──     \t                                                 ^^\n//│ to_chD: anything -> (anything -> ??N) -> ??N -> anything\n//│       = [Function: to_chD]\n\n\n\n// * === With Distributivity ===\n\n\n:DistributeForalls\n\n\ndef zero f x = x\n//│ anything -> 'a -> 'a\n//│   <:  zero:\n//│ ChurchInt\n//│     = [Function: zero3]\n\n// * Now it works!\ndef succ n f x = f (n f x)\n//│ ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = [Function: succ7]\n\nzero = z\n//│ anything -> 'a -> 'a\n//│   <:  zero:\n//│ ChurchInt\n//│     = [Function: z]\n\n// * Now works\nsucc = s\n//│ ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = [Function: s]\n\n// * Still works\nsuccD = s\n//│ ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│   <:  succD:\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│      = [Function: s]\n\n// * Now works\nsucc = succD\n//│ ChurchInt -> ('M -> 'M) -> 'M -> 'M\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = [Function: s]\n\n// * Now works\nrec def to_chD n =\n  succD (to_chD n)\n//│ to_chD: anything -> ('M -> 'M) -> 'M -> 'M\n//│       = [Function: to_chD1]\n\n:stats\nz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function: z]\n//│ constrain calls  : 16\n//│ annoying  calls  : 0\n//│ subtyping calls  : 33\n\n:stats\ns: ChurchInt -> ChurchInt\n//│ res: ChurchInt -> ChurchInt\n//│    = [Function: s]\n//│ constrain calls  : 80\n//│ annoying  calls  : 0\n//│ subtyping calls  : 228\n\n// * Now works\nto_church_ty = to_ch\n//│ int -> ('a -> 'b & 'a -> 'a) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_ch]\n\n// * Still works\nto_church_ty = to_ch_s_A1\n//│ int -> ('N -> ('N & 'N0) & 'N0 -> 'a) -> ('N & 'N0 & 'a) -> 'a\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_ch_s_A1]\n\n// * Now works\nto_church_ty = to_ch_simplif\n//│ anything -> ('a -> 'b & 'a -> 'a) -> anything -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_ch_simplif]\n\n// * Redefinition in the context of distrib, just for the record (still works)\nrec def to_ch_simplif n = s (to_ch_simplif n)\nto_church_ty = to_ch_simplif\n//│ to_ch_simplif: anything -> ('a -> 'b & 'a -> 'a) -> anything -> 'b\n//│              = [Function: to_ch_simplif1]\n//│ anything -> ('a -> 'b & 'a -> 'a) -> anything -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_ch_simplif1]\n\n:e\nto_church_ty = to_ch_A1\n//│ int -> (anything -> (??N & 'N & 'a)) -> (??N & 'N & 'a) -> 'a\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.1108: \tto_church_ty = to_ch_A1\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                                           ^^\n//│ ╟── into type `'N0`\n//│ ║  l.7: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║       \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.700: \t  else s (to_ch_A1 (n - 1) : ChurchInt)\n//│ ║         \t          ^^^^^^^^^^^^^^^^\n//│ ╟── • this function:\n//│ ║  l.314: \tdef s n f x = f (n f x)\n//│ ╙──       \t          ^^^^^^^^^^^^^\n//│             = [Function: to_ch_A1]\n\n// * Now works\nto_church_ty = to_ch_A2\n//│ int -> ChurchInt\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_ch_A2]\n\n// * Now works\nto_church_ty = to_church_mix\n//│ int -> ('M -> ('M & 'a) & 'N -> ('a & 'N) & 'a -> 'b) -> ('M & 'a & 'N & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_mix]\n\n\n\n// * === Usages ===\n\n\nn3 = s (s (s z))\n//│ n3: ('a -> 'b & 'b -> 'c & 'c -> 'd) -> 'a -> 'd\n//│   = [Function (anonymous)]\n\nn3 wrap_ty 0\n//│ res: {x: {x: {x: 0}}}\n//│    = { x: { x: { x: 0 } } }\n\nres.x.x.x + 1\n//│ res: int\n//│    = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/ConstrainedTypes1.mls",
    "content": ":ConstrainedTypes\n\n\n// :d\nfoo x =\n  log (succ x.prop)\n//│ foo: {prop: int} -> unit\n//│    = [Function: foo]\n\n:ns\nfoo x =\n  let _ = log (succ x.prop)\n  in x\n//│ foo: forall 'a 'prop. 'a -> 'a\n//│   where\n//│     'a <: {prop: 'prop}\n//│     'prop <: int\n//│    = [Function: foo1]\n\n:e\nfoo false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.21: \tfoo false\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `false` does not have field 'prop'\n//│ ║  l.21: \tfoo false\n//│ ║        \t    ^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.12: \t  let _ = log (succ x.prop)\n//│ ╙──      \t                    ^^^^^^\n//│ res: error | false\n//│    = false\n//│ // Output\n//│ NaN\n\nfoo x =\n  let _ = log (fun y -> x.prop y)\n  in x\n//│ foo: 'a -> 'a\n//│    = [Function: foo2]\n\n// :e // * Error swallowed by inconsistent constrained types... but it seems this can't lead to unsoundness\nfoo false\n//│ res: false\n//│    = false\n//│ // Output\n//│ [Function (anonymous)]\n\nfoo x =\n  let _ = log ((fun y -> x.prop y) 0)\n  in x\n//│ foo: ({prop: 0 -> anything} & 'a) -> 'a\n//│    = [Function: foo3]\n\n:e\nfoo false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.56: \tfoo false\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `false` does not have field 'prop'\n//│ ║  l.56: \tfoo false\n//│ ║        \t    ^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.50: \t  let _ = log ((fun y -> x.prop y) 0)\n//│ ╙──      \t                         ^^^^^^\n//│ res: error | false\n//│ Runtime error:\n//│   TypeError: x.prop is not a function\n\n:ng\napp = error : ('a -> 'a) -> ()\n//│ app: ('a -> 'a) -> ()\n\n:ng\nfoo x =\n  let _ = app (fun y -> x.prop y)\n  in x\n//│ foo: ({prop: 'a -> 'a} & 'b) -> 'b\n\n:e\nfoo false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.81: \tfoo false\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `false` does not have field 'prop'\n//│ ║  l.81: \tfoo false\n//│ ║        \t    ^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.76: \t  let _ = app (fun y -> x.prop y)\n//│ ╙──      \t                        ^^^^^^\n//│ res: error | false\n//│ Runtime error:\n//│   TypeError: x.prop is not a function\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/ConstrainedTypes2.mls",
    "content": ":ConstrainedTypes\n\n\ndef f n = n 0\n//│ f: (0 -> 'a) -> 'a\n//│  = [Function: f]\n\n:e\nf {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.9: \tf {}\n//│ ║       \t^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.9: \tf {}\n//│ ║       \t  ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.4: \tdef f n = n 0\n//│ ║       \t          ^^^\n//│ ╟── from reference:\n//│ ║  l.4: \tdef f n = n 0\n//│ ╙──     \t          ^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\n// :d\n:e\nf {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.28: \tf {} {}\n//│ ║        \t^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.28: \tf {} {}\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.4: \tdef f n = n 0\n//│ ║       \t          ^^^\n//│ ╟── from reference:\n//│ ║  l.4: \tdef f n = n 0\n//│ ╙──     \t          ^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\n\ndef f n m = n 0\n//│ f: 'a -> (anything -> 'b\n//│   where\n//│     'a <: 0 -> 'b)\n//│  = [Function: f1]\n\n// :e // Error delayed by inconsistent constrained types\nf {}\n//│ res: anything -> 'a\n//│   where\n//│     anything <: 0 -> 'a\n//│    = [Function (anonymous)]\n\n:e\nf {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.60: \tf {} {}\n//│ ║        \t^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.60: \tf {} {}\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.46: \tdef f n m = n 0\n//│ ╙──      \t            ^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\n\n\ndef test extr =\n  let f n m = n 0\n  in let _ = extr f\n  in f 0\n//│ test: ((forall 'a 'b. 'a -> (anything -> 'b\n//│   where\n//│     'a <: 0 -> 'b)) -> anything) -> (anything -> 'c\n//│   where\n//│     0 <: 0 -> 'c)\n//│     = [Function: test]\n\n:e\ntest 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.88: \ttest 1\n//│ ║        \t^^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.88: \ttest 1\n//│ ║        \t     ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.78: \t  in let _ = extr f\n//│ ╙──      \t             ^^^^^^\n//│ res: error | anything -> 'a\n//│   where\n//│     0 <: 0 -> 'a\n//│ Runtime error:\n//│   TypeError: extr is not a function\n\n// * Note: this extrudes a Constrainedtype referring to a higher-level variable (x)\ndef test extr x =\n  let f n m = x (n 0)\n  in let _ = extr f\n  in f 0\n//│ test: ((forall 'a 'b 'c. 'a -> (anything -> 'c\n//│   where\n//│     'd <: 'b -> 'c\n//│     'a <: 0 -> 'b)) -> anything) -> 'd -> (anything -> 'e\n//│   where\n//│     'd <: 'f -> 'e\n//│     0 <: 0 -> 'f)\n//│     = [Function: test1]\n\n:e\ntest 0\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.119: \ttest 0\n//│ ║         \t^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.119: \ttest 0\n//│ ║         \t     ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.107: \t  in let _ = extr f\n//│ ╙──       \t             ^^^^^^\n//│ res: error | 'a -> (anything -> 'b\n//│   where\n//│     'a <: 'c -> 'b\n//│     0 <: 0 -> 'c)\n//│    = [Function (anonymous)]\n\ndef test extr x =\n  let f n m = x (n 0)\n  in f 0\n//│ test: anything -> 'a -> (anything -> 'b\n//│   where\n//│     'a <: 'c -> 'b\n//│     0 <: 0 -> 'c)\n//│     = [Function: test2]\n\n// Error delayed by inconsistent constrained types\ntest 0 1\n//│ res: anything -> 'a\n//│   where\n//│     1 <: 'b -> 'a\n//│     0 <: 0 -> 'b\n//│    = [Function (anonymous)]\n\n:e\ntest 0 1 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.153: \ttest 0 1 2\n//│ ║         \t^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.153: \ttest 0 1 2\n//│ ║         \t       ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.136: \t  let f n m = x (n 0)\n//│ ╙──       \t              ^^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\ndef test extr x =\n  let f n m = (n x 0)\n  in f 0\n//│ test: anything -> 'a -> (anything -> 'b\n//│   where\n//│     0 <: 'a -> 0 -> 'b)\n//│     = [Function: test3]\n\n// Error delayed by inconsistent constrained types\ntest 0 1\n//│ res: anything -> 'a\n//│   where\n//│     0 <: 1 -> 0 -> 'a\n//│    = [Function (anonymous)]\n\n:e\ntest 0 1 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.183: \ttest 0 1 2\n//│ ║         \t^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.169: \t  in f 0\n//│ ║         \t       ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.168: \t  let f n m = (n x 0)\n//│ ╙──       \t               ^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Demo.mls",
    "content": "\n:NoJS // TODO support JS code-gen for datatypes\n\n\n\ndatatype Option[A] = Some(A) | None\n//│ Defined class Option[+A]\n//│ Declared Option.Some: Option['A] -> ('A,)\n//│ Declared Option.None: Option[?] -> anything\n//│ Defined class Some[+A]\n//│ Defined class None[+A]\n//│ Some: 'a -> Option['a]\n//│ None: Option[nothing]\n\n\n// * Original\n\ndef foo f = (f 123, f true)\nfooid = foo id\nfooSome = foo Some\n//│ foo: (123 -> 'a & true -> 'b) -> ('a, 'b,)\n//│ fooid: (123, true,)\n//│ fooSome: (Option[123], Option[true],)\n\ndef bar f = (f (fun x -> x), f (fun x -> Some x))\ntest = bar foo\n//│ bar: ((forall 'a. 'a -> 'a) -> 'b & (forall 'c. 'c -> Option['c]) -> 'd) -> ('b, 'd,)\n//│ test: ((123, true,), (Option[123], Option[true],),)\n\n\n// * Let-expanded\n\ndef foo f = let g = f in (f 123, f true)\nfooid = foo id\nfooSome = foo Some\n//│ foo: (123 -> 'a & true -> 'b) -> ('a, 'b,)\n//│ fooid: (123, true,)\n//│ fooSome: (Option[123], Option[true],)\n\ndef bar f = (f (fun x -> x), f (fun x -> Some x))\ntest = bar foo\n//│ bar: ((forall 'a. 'a -> 'a) -> 'b & (forall 'c. 'c -> Option['c]) -> 'd) -> ('b, 'd,)\n//│ test: ((123, true,), (Option[123], Option[true],),)\n\n\n// * Eta-expanded (notice the lesser generality)\n\ndef foo f = let g x = f x in (g 123, g true)\nfooid = foo id\nfooSome = foo Some\n//│ foo: ((123 | true) -> 'a) -> ('a, 'a,)\n//│ fooid: (123 | true, 123 | true,)\n//│ fooSome: (Option[123 | true], Option[123 | true],)\n\ndef bar f = (f (fun x -> x), f (fun x -> Some x))\ntest = bar foo\n//│ bar: ((forall 'a. 'a -> 'a) -> 'b & (forall 'c. 'c -> Option['c]) -> 'd) -> ('b, 'd,)\n//│ test: ((123 | true, 123 | true,), (Option[123 | true], Option[123 | true],),)\n\n\n// * With function type annotation (same lesser generality)\n\ndef foo (f: 'x -> 'a) = (f 123, f true)\nfooid = foo id\nfooSome = foo Some\n//│ foo: ((123 | true) -> 'a) -> ('a, 'a,)\n//│ fooid: (123 | true, 123 | true,)\n//│ fooSome: (Option[123 | true], Option[123 | true],)\n\ndef bar f = (f (fun x -> x), f (fun x -> Some x))\ntest = bar foo\n//│ bar: ((forall 'a. 'a -> 'a) -> 'b & (forall 'c. 'c -> Option['c]) -> 'd) -> ('b, 'd,)\n//│ test: ((123 | true, 123 | true,), (Option[123 | true], Option[123 | true],),)\n\n\n// * Here's an idea: we could use application types to retain this function's precise typing\n\n// let g x = f x\n// g : forall 'a. 'a -> ('f 'a) where constraint: 'f <: 'a -> anything\n//                              extruded to 'f <: 'a0 -> anything where 'a <: 'a0\n// \n// foo : 'f -> ('f 123, 'f true) where 'f <: 'a0 -> anything, 123 <: 'a0, true <: 'a0\n// foo : 'f -> ('f 123, 'f true) where 'f <: (123 | true) -> anything\n// \n// foo Some -- ok because Some : (forall 'a. 'a -> Option['a]) <: (123 | true) -> anything\n// \n\n// * Note: the old idea was to use constrained types, as in:\n\n// def example f = f 123\n// example : 'a -> ('a 123) where 'a <: 123 -> anything\n\n// * ... which worked, but CTs are a pain to work with/implement\n// * AND they may be silently inconsistent, delaying error reporting to use sites.\n// * Moreover, ensuring that CTs remain consistent defeats their purpose (can't solve tis problem anymore)\n\n\n\ndatatype List[A] = Cons(A, List[A]) | Nil\n//│ Defined class List[+A]\n//│ Declared List.Cons: List['A] -> ('A, List['A],)\n//│ Declared List.Nil: List[?] -> anything\n//│ Defined class Cons[+A]\n//│ Defined class Nil[+A]\n//│ Cons: ('a, List['a],) -> List['a]\n//│ Nil: List[nothing]\n\nrec def find(table, key) =\n  match table with\n    | Nil -> None\n    | Cons(h, t) ->\n        if h.key == key then Some(h.val) else find(t, key)\n//│ find: (List[{key: number, val: 'a}], number,) -> Option['a]\n\n\nls = Cons({key=0; val=id}, Cons({key=1; val=fun x -> x x}, Nil))\n//│ ls: List[{key: 0 | 1, val: forall 'a 'b 'c. ('a -> 'b & 'c & 'a) -> ('c | 'b)}]\n\ndef found: Option[forall 'a 'b. ('a -> 'b & 'a) -> ('b | 'a)]\n//│ found: Option[forall 'a 'b. ('a -> 'b & 'a) -> ('b | 'a)]\n\nfound = find(ls, 1)\n//│ Option[forall 'a 'b 'c. ('a -> 'b & 'a & 'c) -> ('b | 'c)]\n//│   <:  found:\n//│ Option[forall 'a 'b. ('a -> 'b & 'a) -> ('b | 'a)]\n\nmatch found with\n  | None -> (\"???\", false)\n  | Some(r) -> (r id \"!!!\", r id true)\n//│ res: (\"!!!\" | \"???\", Bool,)\n\n\nusing fnd = match fnd with\n  | None -> (\"???\", false)\n  | Some(r) -> (r id \"!!!\", r id true)\n//│ using: Option[(forall 'a. 'a -> 'a) -> (\"!!!\" -> 'b & true -> 'c)] -> (\"???\" | 'b, false | 'c,)\n\nusing found\n//│ res: (\"!!!\" | \"???\", Bool,)\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Distrib.mls",
    "content": ":NoRecursiveTypes\n:DistributeForalls\n:NoJS\n\n\n\ndef f1: 'a -> (forall 'b. 'b -> ('a, 'b))\ndef f2: 'a -> 'b -> ('a, 'b)\n//│ f1: 'a -> 'b -> ('a, 'b,)\n//│ f2: 'a -> 'b -> ('a, 'b,)\n\n\n// * With distributivity, f1 and f2 have equivalent types, as shown below\n\nf1 = f2\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  f1:\n//│ 'a -> 'b -> ('a, 'b,)\n\nf2 = f1\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  f2:\n//│ 'a -> 'b -> ('a, 'b,)\n\n\n// * However, f2 currently is not as flexible:\n\ndef test: (forall 'b. 'b -> (int, 'b)) -> (int, bool)\n//│ test: (forall 'b. 'b -> (int, 'b,)) -> (int, bool,)\n\ntest (f1 42)\n//│ res: (int, bool,)\n\n// This used not to be handled because we didn't yet try to split\n//    type parameters in order to distribute only *part* of the quantification\ntest (f2 42)\n//│ res: (int, bool,)\n\n\n// * Though these work!\n\nf1_42 = f1 42\nf2_42 = f2 42\n//│ f1_42: 'b -> (42, 'b,)\n//│ f2_42: 'b -> (42, 'b,)\n\ntest f1_42\ntest f2_42\n//│ res: (int, bool,)\n//│ res: (int, bool,)\n\n\n\ndef test: forall 'a. (forall 'b. 'b -> (int, 'b)) -> (int, bool)\n//│ test: (forall 'b. 'b -> (int, 'b,)) -> (int, bool,)\n\ndef f1_1: forall 'a. 'a -> (forall 'b. 'b -> ('a, 'b))\n//│ f1_1: 'a -> 'b -> ('a, 'b,)\n\ndef f2_1: forall 'a. forall 'b. 'a -> 'b -> ('a, 'b)\ndef f2_2: forall 'b. forall 'a. 'a -> 'b -> ('a, 'b)\ndef f2_3: forall 'a 'b. 'a -> 'b -> ('a, 'b)\n//│ f2_1: 'a -> 'b -> ('a, 'b,)\n//│ f2_2: 'a -> 'b -> ('a, 'b,)\n//│ f2_3: 'a -> 'b -> ('a, 'b,)\n\ntest (f1_1 42)\n//│ res: (int, bool,)\n\ntest (f2_1 42)\ntest (f2_2 42)\ntest (f2_3 42)\n//│ res: (int, bool,)\n//│ res: (int, bool,)\n//│ res: (int, bool,)\n\n\nf1_1_42 = f1_1 42\nf2_1_42 = f2_1 42\nf2_2_42 = f2_2 42\nf2_3_42 = f2_3 42\n//│ f1_1_42: 'b -> (42, 'b,)\n//│ f2_1_42: 'b -> (42, 'b,)\n//│ f2_2_42: 'b -> (42, 'b,)\n//│ f2_3_42: 'b -> (42, 'b,)\n\ntest f1_1_42\ntest f2_1_42\ntest f2_2_42\ntest f2_3_42\n//│ res: (int, bool,)\n//│ res: (int, bool,)\n//│ res: (int, bool,)\n//│ res: (int, bool,)\n\n\n\n// * Note: without distributivity:\n\n:DontDistributeForalls\n\n:e\nf1 = f2\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  f1:\n//│ 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.103: \tf1 = f2\n//│ ║         \t^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.7: \tdef f1: 'a -> (forall 'b. 'b -> ('a, 'b))\n//│ ║       \t                          ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.7: \tdef f1: 'a -> (forall 'b. 'b -> ('a, 'b))\n//│ ║       \t                                     ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.103: \tf1 = f2\n//│ ╙──       \t     ^^\n\nf2 = f1\n//│ 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│   <:  f2:\n//│ 'a -> 'b -> ('a, 'b,)\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Distrib2.mls",
    "content": ":NoRecursiveTypes\n:DistributeForalls\n:NoJS\n\n\n\ntype BTB = forall 'b. 'b -> 'b\n//│ Defined type alias BTB\n\n\n\n// * ========= This first version works fine because the LHS `forall 'a.` can be distributed. =========\n\n\ndef ty_1: (nothing -> 'a) -> 'a\n//│ ty_1: (nothing -> 'a) -> 'a\n\ndef ty_2: (forall 'c. 'c -> 'c -> 'c) -> BTB\n//│ ty_2: (forall 'c. 'c -> 'c -> 'c) -> BTB\n\n// * Works thanks to `:DistributeForalls`, distributing the LHS (`forall 'a`)\nty_2 = ty_1\n//│ (nothing -> 'a) -> 'a\n//│   <:  ty_2:\n//│ (forall 'c. 'c -> 'c -> 'c) -> BTB\n\ndef ty_1_2: (nothing -> BTB) -> BTB\n//│ ty_1_2: (nothing -> BTB) -> BTB\n\nty_1_2 = ty_1\n//│ (nothing -> 'a) -> 'a\n//│   <:  ty_1_2:\n//│ (nothing -> BTB) -> BTB\n\nty_2 = ty_1_2\n//│ (nothing -> BTB) -> BTB\n//│   <:  ty_2:\n//│ (forall 'c. 'c -> 'c -> 'c) -> BTB\n\n\n\n// * ========= Here the `forall 'a.` can't be distributed. =========\n// * (Unless we somehow knew to widen the function to `nothing -> ...` and then distribute.)\n\n\ndef ty_1: 'a -> (nothing -> 'a) -> 'a\n//│ ty_1: 'a -> (nothing -> 'a) -> 'a\n\ndef ty_2: nothing -> (forall 'c. 'c -> 'c -> 'c) -> BTB\n//│ ty_2: nothing -> (forall 'c. 'c -> 'c -> 'c) -> BTB\n\n// * But this still works thanks to `:DistributeForalls`, distributing the RHS (`forall 'b` out of BTB)\nty_2 = ty_1\n//│ 'a -> (nothing -> 'a) -> 'a\n//│   <:  ty_2:\n//│ nothing -> (forall 'c. 'c -> 'c -> 'c) -> BTB\n\n\n\n// * ========= Now without distributivity. =========\n\n\n:DontDistributeForalls\n\n\n// * This fails to constrain, as expected\n:e\nty_2 = ty_1\n//│ 'a -> (nothing -> 'a) -> 'a\n//│   <:  ty_2:\n//│ nothing -> (forall 'c. 'c -> 'c -> 'c) -> BTB\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.68: \tty_2 = ty_1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.7: \ttype BTB = forall 'b. 'b -> 'b\n//│ ║       \t                      ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.7: \ttype BTB = forall 'b. 'b -> 'b\n//│ ║       \t                            ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.68: \tty_2 = ty_1\n//│ ╙──      \t       ^^^^\n\n\n// * We can manually take ty_1 closer to ty_2\n\ndef ty_1_2: BTB -> (nothing -> BTB) -> BTB\n//│ ty_1_2: BTB -> (nothing -> BTB) -> BTB\n\nty_1_2 = ty_1\n//│ 'a -> (nothing -> 'a) -> 'a\n//│   <:  ty_1_2:\n//│ BTB -> (nothing -> BTB) -> BTB\n\n// * But it still need distributivity for the inner comparison\n:e\nty_2 = ty_1_2\n//│ BTB -> (nothing -> BTB) -> BTB\n//│   <:  ty_2:\n//│ nothing -> (forall 'c. 'c -> 'c -> 'c) -> BTB\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.99: \tty_2 = ty_1_2\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.7: \ttype BTB = forall 'b. 'b -> 'b\n//│ ║       \t                      ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.7: \ttype BTB = forall 'b. 'b -> 'b\n//│ ╙──     \t                            ^^\n\n// * Note\ndef ty_1_3: BTB -> (nothing -> anything -> nothing) -> BTB\n//│ ty_1_3: BTB -> (nothing -> anything -> nothing) -> BTB\nty_1_3 = ty_1_2\n//│ BTB -> (nothing -> BTB) -> BTB\n//│   <:  ty_1_3:\n//│ BTB -> (nothing -> anything -> nothing) -> BTB\n\n\n// * Again, with distrib.\n\n:DistributeForalls\n\nty_2 = ty_1_2\n//│ BTB -> (nothing -> BTB) -> BTB\n//│   <:  ty_2:\n//│ nothing -> (forall 'c. 'c -> 'c -> 'c) -> BTB\n\n\n\n// * ========= Some additional semi-random tests. =========\n\n\ndef ty_0: nothing -> BTB\n//│ ty_0: nothing -> BTB\n\n\nty_0 = id\n//│ 'a -> 'a\n//│   <:  ty_0:\n//│ nothing -> BTB\n\nty_0 = (fun x -> fun y -> y)\n//│ anything -> 'a -> 'a\n//│   <:  ty_0:\n//│ nothing -> BTB\n\nidid = id (fun x -> id (fun y -> id y))\n//│ idid: anything -> 'a -> 'a\n\ndef foo: 'a -> 'a -> 'a\n//│ foo: 'a -> 'a -> 'a\n\nidid x = foo (x (fun y -> y))\n//│ idid: ((forall 'b. 'b -> 'b) -> 'a) -> 'a -> 'a\n\nty_0 = idid\n//│ ((forall 'b. 'b -> 'b) -> 'a) -> 'a -> 'a\n//│   <:  ty_0:\n//│ nothing -> BTB\n\n// ∀𝛼{𝛽≤𝛼}.𝛼→𝛼 ≤ ⊤→(∀𝛾.𝛾→𝛾)\nty_0 = idid id\n//│ 'a -> ('b -> 'b | 'a)\n//│   <:  ty_0:\n//│ nothing -> BTB\n\ndef idid = let x = (fun y -> y) : 'a in id : 'a -> 'a\n//│ idid: 'a -> 'a\n\nty_0 = idid id\n//│ 'a -> 'a\n//│   <:  ty_0:\n//│ nothing -> BTB\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/DistribRight.mls",
    "content": "// * Variations/minimizations on the case found in the Fiota test\n// * These tests exercise problems that could arise from distributing\n// * RHS functions with polymorphic codomain.\n\n\n\nS x = x x\n//│ S: ('a -> 'b & 'a) -> 'b\n//│  = [Function: S]\n\nS: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│    = [Function: S]\n\n\nS x y = x\n//│ S: 'a -> anything -> 'a\n//│  = [Function: S1]\n\nS: (forall 'a. 'a -> 'a) -> anything -> (forall 'c. 'c -> 'c)\n//│ res: (forall 'a. 'a -> 'a) -> anything -> (forall 'c. 'c -> 'c)\n//│    = [Function: S1]\n\nS: 'c -> 'b -> (forall 'a. 'a -> 'a)\n//│ res: (??a -> ??a0) -> anything -> (forall 'a. 'a -> 'a)\n//│    = [Function: S1]\n\nS: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1)\n//│    = [Function: S1]\n\n\nS x y = x y\n//│ S: ('a -> 'b) -> 'a -> 'b\n//│  = [Function: S2]\n\nS: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1)\n//│    = [Function: S2]\n\n\nS x y z = x z y\n//│ S: ('a -> 'b -> 'c) -> 'b -> 'a -> 'c\n//│  = [Function: S3]\n\nS: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1) -> (forall 'a2. 'a2 -> 'a2)\n//│    = [Function: S3]\n\n\n\n:NoJS\n\n\n\ndef T: 'a -> 'a -> anything -> 'a\n//│ T: 'a -> 'a -> anything -> 'a\n\nT: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1) -> (forall 'a2. 'a2 -> 'a2)\n\n\n// * This one works out because we currently DO NOT distribute out when both sides of\n// * the constraint are plain function types:\n\ndef T: ('a, 'a -> 'a)\n//│ T: ('a, 'a -> 'a,)\n\nT: (forall 'a. 'a -> 'a, (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a))\n//│ res: (forall 'a. 'a -> 'a, (forall 'a0. 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1),)\n\n\n// * However, we can contort things enough so that we end up forcing the distribution,\n// * and causing a problematic extrusion/avoidance:\n\ndef T: ('a, forall 'b. ('a, 'b) -> 'a)\n//│ T: ('a, ('a, anything,) -> 'a,)\n\n:e\nT: (anything, (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a))\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.80: \tT: (anything, (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a))\n//│ ║        \t^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.80: \tT: (anything, (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a))\n//│ ║        \t                                                             ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.80: \tT: (anything, (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a))\n//│ ║        \t                                                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.80: \tT: (anything, (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a))\n//│ ╙──      \t^\n//│ res: (anything, (forall 'a. 'a -> 'a, anything,) -> (forall 'a0. 'a0 -> 'a0),)\n\n\n// * Similarly:\n\ndef T: 'a -> (forall 'b. ('a, 'b) -> 'a)\n//│ T: 'a -> ('a, anything,) -> 'a\n\n:e\nT: anything -> (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.103: \tT: anything -> (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a)\n//│ ║         \t^\n//│ ╟── type `anything` is not a function\n//│ ║  l.103: \tT: anything -> (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a)\n//│ ║         \t   ^^^^^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.103: \tT: anything -> (forall 'a. 'a -> 'a, anything) -> (forall 'a. 'a -> 'a)\n//│ ╙──       \t                                                              ^^^^^^^^\n//│ res: anything -> (forall 'a. 'a -> 'a, anything,) -> (forall 'a0. 'a0 -> 'a0)\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/DistribUnionInter.mls",
    "content": "\n// * This test demonstrates how unions and intersections can interfere withb FCP type inference\n\n\ndef foo: forall 'a 'b. 'a | 1 -> 'b -> 'b\n//│ foo: 1 -> 'b -> 'b\n//│    = <missing implementation>\n\nfoo\n//│ res: 1 -> 'b -> 'b\n//│    = <no result>\n//│      foo is not implemented\n\ndef bar(f: 1 -> ('d | (forall 'c. 'c -> 'c))) = 1\n//│ bar: (1 -> anything) -> 1\n//│    = [Function: bar]\n\n// * Still works because we distribute from the right\nbar foo\n//│ res: 1\n//│    = <no result>\n//│      foo is not implemented\n\ndef bar(f: 1 -> ('d & (forall 'c. 'c -> 'c))) = 1\n//│ bar: (1 -> (forall 'c. 'c -> 'c)) -> 1\n//│    = [Function: bar1]\n\nbar\n//│ res: (1 -> (forall 'c. 'c -> 'c)) -> 1\n//│    = [Function: bar1]\n\n// * Doesn't works because we are forced into DNF constraining where no distrib is currently done\n:e\nbar foo\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.34: \tbar foo\n//│ ║        \t^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.24: \tdef bar(f: 1 -> ('d & (forall 'c. 'c -> 'c))) = 1\n//│ ║        \t                                  ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.24: \tdef bar(f: 1 -> ('d & (forall 'c. 'c -> 'c))) = 1\n//│ ║        \t                                        ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.34: \tbar foo\n//│ ║        \t    ^^^\n//│ ╟── • this function:\n//│ ║  l.24: \tdef bar(f: 1 -> ('d & (forall 'c. 'c -> 'c))) = 1\n//│ ║        \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.34: \tbar foo\n//│ ╙──      \t^^^\n//│ res: 1 | error\n//│    = <no result>\n//│      foo is not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/DistribWorsening.mls",
    "content": ":NoRecursiveTypes\n:DistributeForalls\n:NoJS\n\n\n// * Test that exposes worseining of type inference due to eager distributivity\n// * (compared to no distributivity at all)\n\n\n\ntype BTB = forall 'b. 'b -> 'b\n//│ Defined type alias BTB\n\n\n\n// * OK\n(fun g -> fun x -> x) : anything -> BTB\n//│ res: anything -> BTB\n\n\n// * OK\ndef test f =\n  f id : anything -> BTB\ntest (fun g -> fun n -> id)\n//│ test: ((forall 'a. 'a -> 'a) -> anything -> BTB) -> anything -> BTB\n//│ res: anything -> BTB\n\n\n// * OK\ndef test f =\n  (fun a -> a : anything -> BTB) (f id)\ntest (fun g -> fun n -> id)\n//│ test: ((forall 'a. 'a -> 'a) -> anything -> BTB) -> anything -> BTB\n//│ res: anything -> BTB\n\n\n// * OK\ndef test f =\n  (fun () -> f id)() : anything -> BTB\ntest (fun g -> fun n -> id)\n//│ test: ((forall 'a. 'a -> 'a) -> anything -> BTB) -> anything -> BTB\n//│ res: anything -> BTB\n\n\n// * NOT OK: Notice the extruded skolem in `??b -> ??b0` whichb results from distributing 'b out of BTB\ndef test f =\n  let a = f() in\n  a : anything -> BTB\n//│ test: (() -> anything -> ??b -> ??b0) -> anything -> BTB\n\n:e\ntest (fun () -> fun n -> id)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.52: \ttest (fun () -> fun n -> id)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.11: \ttype BTB = forall 'b. 'b -> 'b\n//│ ║        \t                      ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.11: \ttype BTB = forall 'b. 'b -> 'b\n//│ ║        \t                            ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.47: \t  let a = f() in\n//│ ║        \t          ^^^\n//│ ╟── • this reference:\n//│ ║  l.48: \t  a : anything -> BTB\n//│ ╙──      \t  ^\n//│ res: error | anything -> BTB\n\n\n// * Idem\ndef test f =\n  let a() = f id in\n  a() : nothing -> BTB\n//│ test: ((forall 'a. 'a -> 'a) -> nothing -> ??b -> ??b0) -> nothing -> BTB\n\n:e\ntest (fun g -> fun n -> id)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.79: \ttest (fun g -> fun n -> id)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.11: \ttype BTB = forall 'b. 'b -> 'b\n//│ ║        \t                      ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.11: \ttype BTB = forall 'b. 'b -> 'b\n//│ ║        \t                            ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.74: \t  let a() = f id in\n//│ ║        \t            ^^^^\n//│ ╟── • this application:\n//│ ║  l.75: \t  a() : nothing -> BTB\n//│ ╙──      \t  ^^^\n//│ res: error | nothing -> BTB\n\n\n\n:DontDistributeForalls\n\n\n// * There is no longer an extruded skolem\ndef test f =\n  let a = f() in\n  a : anything -> BTB\n//│ test: (() -> anything -> BTB) -> anything -> BTB\n\ntest (fun () -> fun n -> id)\n//│ res: anything -> BTB\n\n\n// * Idem\ndef test f =\n  let a = f id in\n  a : nothing -> BTB\n//│ test: ((forall 'a. 'a -> 'a) -> nothing -> BTB) -> nothing -> BTB\n\ntest (fun g -> fun n -> id)\n//│ res: nothing -> BTB\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/FCPTony.mls",
    "content": ":NoRecursiveTypes\n:ConstrainedTypes\n\n\n\ndef app n f = n f\n//│ app: 'a -> ('b -> 'c\n//│   where\n//│     'a <: 'b -> 'c)\n//│    = [Function: app]\n\ndef g x y = app x y\n//│ g: 'a -> ('b -> 'c\n//│   where\n//│     'a <: 'b -> 'c)\n//│  = [Function: g]\n\n:e\ng {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.19: \tg {} {}\n//│ ║        \t^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.19: \tg {} {}\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.6: \tdef app n f = n f\n//│ ╙──     \t              ^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\n\n\n// ————————————————————————\n\n\ndef app p q = p q\n//│ app: 'a -> ('b -> 'c\n//│   where\n//│     'a <: 'b -> 'c)\n//│    = [Function: app1]\n\ndef mul r s = r (app s) id\n//│ mul: 'a -> ('b -> 'c\n//│   where\n//│     'a <: (forall 'd 'e. 'd -> 'e\n//│       where\n//│         'b <: 'd -> 'e) -> (forall 'f. 'f -> 'f) -> 'c)\n//│    = [Function: mul]\n\n:e\nmul id {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.53: \tmul id {}\n//│ ║        \t^^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.53: \tmul id {}\n//│ ║        \t       ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.38: \tdef app p q = p q\n//│ ║        \t              ^^^\n//│ ╟── from reference:\n//│ ║  l.44: \tdef mul r s = r (app s) id\n//│ ╙──      \t                     ^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: p is not a function\n\ndef fact t = mul t {}\n//│ fact: ((forall 'a 'b. 'a -> 'b\n//│   where\n//│     anything <: 'a -> 'b) -> (forall 'c. 'c -> 'c) -> 'd) -> 'd\n//│     = [Function: fact]\n\n:e\nfact id\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.77: \tfact id\n//│ ║        \t^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.70: \tdef fact t = mul t {}\n//│ ║        \t                   ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.38: \tdef app p q = p q\n//│ ╙──      \t              ^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: p is not a function\n\ndef mul r s = r (app s)\n//│ mul: 'a -> ('b -> 'c\n//│   where\n//│     'a <: (forall 'd 'e. 'd -> 'e\n//│       where\n//│         'b <: 'd -> 'e) -> 'c)\n//│    = [Function: mul1]\n\nmul id id {}\n//│ res: anything\n//│    = {}\n\n\n\n// ————————————————————————\n\n\n:GeneralizeArguments\n:DistributeForalls\n\n\ntype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ Defined type alias ChurchInt\n\ndef succ: ChurchInt -> ChurchInt\ndef succ n f x = f (n f x)\n//│ succ: ChurchInt -> ChurchInt\n//│     = <missing implementation>\n//│ 'a -> 'b -> ('c -> 'd\n//│   where\n//│     'b <: (forall 'e. 'e\n//│       where\n//│         'a <: 'b -> 'c -> 'e) -> 'd)\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│     = [Function: succ1]\n\n:ns\ndef add n m = n succ m\n//│ add: forall 'a. 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     'a <: (ChurchInt -> ChurchInt) -> 'c)\n//│ where\n//│   'c <: 'b -> 'd\n//│    = [Function: add]\n\nadd\n//│ res: 'a -> ('b -> 'c\n//│   where\n//│     'a <: (ChurchInt -> ChurchInt) -> 'b -> 'c)\n//│    = [Function: add]\n\n:ns\ndef f x y = add x y\n//│ f: forall 'a. 'a -> (forall 'b 'c 'd 'e 'f. 'b -> 'c\n//│   where\n//│     'a <: (ChurchInt -> ChurchInt) -> 'd)\n//│ where\n//│   'b <: 'e\n//│   'd <: 'e -> 'f\n//│   'f <: 'c\n//│  = [Function: f]\n\n// :ds\nf\n//│ res: 'a -> ('b -> 'c\n//│   where\n//│     'a <: (ChurchInt -> ChurchInt) -> 'b -> 'c)\n//│    = [Function: f]\n\n:e\nf {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.162: \tf {} {}\n//│ ║         \t^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.162: \tf {} {}\n//│ ║         \t  ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.129: \tdef add n m = n succ m\n//│ ╙──       \t              ^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\n\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/FCPTony3.mls",
    "content": ":NoRecursiveTypes\n:NoConstrainedTypes\n:NoCycleCheck\n\n\n// * ========= Minimized: =========\n\nconst a b = a\n// const x y = y\n//│ const: 'a -> anything -> 'a\n//│      = [Function: const1]\n\ndef id2: 'A -> 'A\nid2 = id\n//│ id2: 'A -> 'A\n//│    = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id2:\n//│ 'A -> 'A\n//│    = [Function: id]\n\ndef f y = (fun h -> h (h (h (const y)))) id2\n//│ f: 'a -> anything -> 'a\n//│  = [Function: f]\n\n// * This used to be accepted!\n:e\nf {} {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.28: \tf {} {} {}\n//│ ║        \t^^^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.28: \tf {} {} {}\n//│ ║        \t  ^^\n//│ ╟── but it flows into application with expected type `anything -> ?a`\n//│ ║  l.28: \tf {} {} {}\n//│ ╙──      \t^^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: f(...)(...) is not a function\n\n\n// * ========= Original: =========\n\ndef f y = (fun h -> h (h (h (fun _ -> y)))) id {}\n//│ f: 'a -> 'a\n//│  = [Function: f1]\n\n:e\nf {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.50: \tf {} {}\n//│ ║        \t^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.50: \tf {} {}\n//│ ║        \t  ^^\n//│ ╟── but it flows into application with expected type `anything -> ?a`\n//│ ║  l.50: \tf {} {}\n//│ ╙──      \t^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: f1(...) is not a function\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Fiota.mls",
    "content": ":NoRecursiveTypes\n\n\n\n// On the Power of Coercion Abstraction\n\nS x y z = x z (y z)\n//│ S: ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c\n//│  = [Function: S]\n\ntype S1 = ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c\n//│ Defined type alias S1\n\ntype S2 = (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ Defined type alias S2\n\ns1 = S: S1\n//│ s1: S1\n//│   = [Function: S]\n\ns1: S2\n//│ res: S2\n//│    = [Function: S]\n\ns2 = S: S2\n//│ s2: S2\n//│   = [Function: S]\n\n:e // * S2 is less genetral than S1\ns2: S1\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.30: \ts2: S1\n//│ ║        \t^^\n//│ ╟── type `'a` does not match type `'a0`\n//│ ║  l.14: \ttype S2 = (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ║        \t                      ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.11: \ttype S1 = ('a -> 'b -> 'c) -> ('a -> 'b) -> 'a -> 'c\n//│ ║        \t           ^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.14: \ttype S2 = (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ╙──      \t                  ^^\n//│ res: S1\n//│    = [Function: S]\n\n\ntype Id = forall 'a. 'a -> 'a\n//│ Defined type alias Id\n\n\n:e // TODO: could probably use different type var shadows from different type alias occurrences\nS: Id -> Id -> Id -> Id\n//│ ╔══[ERROR] Cyclic-looking constraint while typing type ascription; a type annotation may be required\n//│ ║  l.52: \tS: Id -> Id -> Id -> Id\n//│ ║        \t^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: Id -> Id -> Id -> Id\n//│    = [Function: S]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/ForallTerms.mls",
    "content": ":NoRecursiveTypes\n\n\n\n(forall 'A. fun (x: 'A) -> x) : forall 'X. 'X -> 'X\n//│ res: 'X -> 'X\n//│    = [Function: res]\n\n\nf = forall 'A. fun (x: 'A) -> x\n//│ f: 'A -> 'A\n//│  = [Function: f]\n\nf 0\nf true\nf: forall 'X. 'X -> 'X\n//│ res: 0\n//│    = 0\n//│ res: true\n//│    = true\n//│ res: 'X -> 'X\n//│    = [Function: f]\n\n\nr = { f = forall 'A. fun (x: 'A) -> x }\n//│ r: {f: forall 'A. 'A -> 'A}\n//│  = { f: [Function: f] }\n\nr.f 0\nr.f true\n//│ res: 0\n//│    = 0\n//│ res: true\n//│    = true\n\n\ndef k1(f: forall 'X. 'X -> 'X) = (f 0, f true)\n//│ k1: (forall 'X. 'X -> 'X) -> (0, true,)\n//│   = [Function: k1]\n\nk1 f\n//│ res: (0, true,)\n//│    = [ 0, true ]\n\nk1 r.f\n//│ res: (0, true,)\n//│    = [ 0, true ]\n\n\ndef k2(f) = (f 0, f true)\n//│ k2: (0 -> 'a & true -> 'b) -> ('a, 'b,)\n//│   = [Function: k2]\n\nk2 f\n//│ res: (0, true,)\n//│    = [ 0, true ]\n\nk2 r.f\n//│ res: (0, true,)\n//│    = [ 0, true ]\n\n\n// * Interesting trick: can use an empty `forall` to force generalization of curried lambdas:\n:ns\nf = fun x -> fun y -> (x, y)\ng = fun x -> forall. fun y -> (x, y)\n//│ f: forall 'a 'b. 'a -> 'b -> ('a, 'b,)\n//│  = [Function: f1]\n//│ g: forall 'a. 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│  = [Function: g]\n\n// * They still appear the same after simplification, due to distributivity of `forall` over `->`:\nf\ng\n//│ res: 'a -> 'b -> ('a, 'b,)\n//│    = [Function: f1]\n//│ res: 'a -> 'b -> ('a, 'b,)\n//│    = [Function: g]\n\n\n\n// * Explicitly-bound type variables are rigid (like in OCaml)\n:e\nf = forall 'A. fun (x: 'A) -> x + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.84: \tf = forall 'A. fun (x: 'A) -> x + 1\n//│ ║        \t                              ^^^\n//│ ╟── rigid type variable of type `'A` is not an instance of type `int`\n//│ ║  l.84: \tf = forall 'A. fun (x: 'A) -> x + 1\n//│ ║        \t           ^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.84: \tf = forall 'A. fun (x: 'A) -> x + 1\n//│ ╙──      \t                              ^\n//│ f: anything -> (error | int)\n//│  = [Function: f2]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/FunnyId.mls",
    "content": ":NoRecursiveTypes\n\n\ndef id_ty: forall 'a. 'a -> 'a\n//│ id_ty: 'a -> 'a\n//│      = <missing implementation>\n\n\nrec def id x = let tmp = id x in x\n//│ id: 'a -> 'a\n//│   = [Function: id]\n\n:re\nid 1\n//│ res: 1\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\nid_ty = id\n//│ 'a -> 'a\n//│   <:  id_ty:\n//│ 'a -> 'a\n//│      = [Function: id]\n\n\n// * When we had the \"recursive definition hacks\", and the reason was:\n// * \"we get `'a <: 'a -> anything` because `id` is passed for `x`\n// * and we can't infer polymorphic recursion, so all `x` should have the same type\"\n:e // occurs-check\nrec def id x = let tmp = id id x in x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> ?\n//│     'b :> 'b -> 'b\n//│        <: ? & 'a\n//│ ║  l.30: \trec def id x = let tmp = id id x in x\n//│ ╙──      \t                         ^^^^^\n//│ id: 'a -> 'a\n//│   where\n//│     'a :> 'a -> 'a\n//│        <: 'a -> anything\n//│   = [Function: id1]\n\n:e\n:re\nid 1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> ?\n//│     'b :> 1 | 'b -> 'b\n//│        <: ? & 'a\n//│ ║  l.30: \trec def id x = let tmp = id id x in x\n//│ ╙──      \t                         ^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.46: \tid 1\n//│ ║        \t^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.46: \tid 1\n//│ ║        \t   ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.30: \trec def id x = let tmp = id id x in x\n//│ ║        \t                         ^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.30: \trec def id x = let tmp = id id x in x\n//│ ╙──      \t                                    ^\n//│ res: 1 | error | 'a -> 'a | 'b\n//│   where\n//│     'a :> 1 | 'a -> 'a\n//│        <: 'a -> anything & 'b\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\nid_ty = id\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> ?\n//│     'b :> 'b -> 'b\n//│        <: ? & 'a\n//│ ║  l.30: \trec def id x = let tmp = id id x in x\n//│ ╙──      \t                         ^^^^^\n//│ 'a -> 'a\n//│   where\n//│     'a :> 'a -> 'a\n//│        <: 'a -> anything\n//│   <:  id_ty:\n//│ 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.74: \tid_ty = id\n//│ ║        \t^^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.4: \tdef id_ty: forall 'a. 'a -> 'a\n//│ ║       \t                      ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.30: \trec def id x = let tmp = id id x in x\n//│ ║        \t                         ^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.30: \trec def id x = let tmp = id id x in x\n//│ ║        \t                                    ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.4: \tdef id_ty: forall 'a. 'a -> 'a\n//│ ╙──     \t                  ^^\n//│      = [Function: id1]\n\n// * Note: the above seem to work with :precise-rec-typing\n:precise-rec-typing\nrec def id x = let tmp = id id x in x\n//│ id: 'a -> 'a\n//│   = [Function: id2]\n\n:re\nid 1\n//│ res: 1\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\nid_ty = id\n//│ 'a -> 'a\n//│   <:  id_ty:\n//│ 'a -> 'a\n//│      = [Function: id2]\n\n\n// * Not sure why we get a cycle in this slight variation!\n:e\nrec def id x = if true then x else id id x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> 'c\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c :> 'b -> 'c\n//│        <: 'a\n//│ ║  l.126: \trec def id x = if true then x else id id x\n//│ ╙──       \t                                   ^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required\n//│ ║  l.126: \trec def id x = if true then x else id id x\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ id: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│   = [Function: id3]\n\n:e\nid_ty = id\n//│ ╔══[ERROR] Inferred recursive type: 'b\n//│   where\n//│     'b :> 'c -> 'b | 'a\n//│        <: 'c -> 'a & 'a\n//│     'c :> 'c -> 'b | 'a\n//│        <: 'a\n//│     'a <: 'b\n//│ ║  l.126: \trec def id x = if true then x else id id x\n//│ ╙──       \t                  ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│   <:  id_ty:\n//│ 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.148: \tid_ty = id\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.4: \tdef id_ty: forall 'a. 'a -> 'a\n//│ ║       \t                      ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.126: \trec def id x = if true then x else id id x\n//│ ║         \t                                   ^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.126: \trec def id x = if true then x else id id x\n//│ ║         \t                            ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.4: \tdef id_ty: forall 'a. 'a -> 'a\n//│ ╙──     \t                  ^^\n//│      = [Function: id3]\n\n\n\n:RecursiveTypes\n:NoJS\n\n\ndef choose: 'a -> 'a -> 'a\n//│ choose: 'a -> 'a -> 'a\n\nrec def id1 x = choose x (id1 id1 x)\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n\nid1 id\n//│ res: ('a & 'b) -> 'a\n//│   where\n//│     'a :> forall 'c 'd. ('a & 'b & 'c) -> ('a | 'd)\n//│        <: ((forall 'c 'd. 'c -> 'd) | 'b) -> 'a\n//│     'c :> 'c -> 'd\n//│        <: 'd\n//│     'd := 'c -> 'd\n\nrec def id1 x = if true then x else id1 id1 x\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n\nid1 id\n//│ res: ('a & 'b) -> 'a\n//│   where\n//│     'a :> forall 'c 'd. ('a & 'b & 'c) -> ('a | 'd)\n//│        <: ((forall 'c 'd. 'c -> 'd) | 'b) -> 'a\n//│     'c :> 'c -> 'd\n//│        <: 'd\n//│     'd := 'c -> 'd\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Inst.mls",
    "content": ":NoRecursiveTypes\n\n\ni = id! id!\n//│ i: 'a -> 'a\n//│  = [Function: id]\n\ni i! i 1\n//│ res: 1\n//│    = 1\n\n\n:NoJS\n\n\n{ x = id }\n//│ res: {x: forall 'a. 'a -> 'a}\n\n{ x = id! }\n//│ res: {x: 'a -> 'a}\n\n{ x = id id! }\n//│ res: {x: 'a -> 'a}\n\n{ x = id! id }\n//│ res: {x: forall 'a. 'a -> 'a}\n\n{ x = id! id! }\n//│ res: {x: 'a -> 'a}\n\n:w\ndef foo x = x!\n//│ ╔══[WARNING] Inferred type `?a` of this reference cannot be instantiated\n//│ ║  l.32: \tdef foo x = x!\n//│ ╙──      \t            ^\n//│ foo: 'a -> 'a\n\n\ntype Id = forall 'a. 'a -> 'a\n//│ Defined type alias Id\n\n\ndef foo (x: Id) = x!\n//│ foo: Id -> 'a -> 'a\n\ndef foo (x: Id) = x! x!\n//│ foo: Id -> 'a -> 'a\n\ndef foo (x: Id) = x! x\n//│ foo: Id -> Id\n\ndef foo (x: Id) = x x!\n//│ foo: Id -> 'a -> 'a\n\ndef foo (x: Id) = x x\n//│ foo: Id -> Id\n\n\n// * Note that `this` selections currently don't provide a concrete type in method typing\n:w\nclass A: { f: Id }\n  method F x = x\n  method G1 = this.f\n  method G2 = this.f!\n  method G3 = (this.f: Id)!\n//│ ╔══[WARNING] Inferred type `?f` of this field selection cannot be instantiated\n//│ ║  l.64: \t  method G2 = this.f!\n//│ ╙──      \t              ^^^^^^\n//│ Defined class A\n//│ Defined A.F: A -> 'a -> 'a\n//│ Defined A.G1: A -> Id\n//│ Defined A.G2: A -> Id\n//│ Defined A.G3: A -> 'a -> 'a\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/InvariantPolyContainer.mls",
    "content": ":NoRecursiveTypes\n:NoJS\n\n\ndef single: 'a -> MutArray['a]\n//│ single: 'a -> MutArray['a]\n\nsid = single id\n//│ sid: MutArray['a]\n//│   where\n//│     'a :> forall 'b. 'b -> 'b\n\ndef ty1: MutArray[forall 'X. 'X -> 'X]\ndef ty1 = sid\n//│ ty1: MutArray[forall 'X. 'X -> 'X]\n//│ MutArray['a]\n//│   where\n//│     'a :> forall 'b. 'b -> 'b\n//│   <:  ty1:\n//│ MutArray[forall 'X. 'X -> 'X]\n\ndef ty2: forall 'A. MutArray['A -> 'A]\ndef ty2 = sid\n//│ ty2: MutArray['A -> 'A]\n//│ MutArray['a]\n//│   where\n//│     'a :> forall 'b. 'b -> 'b\n//│   <:  ty2:\n//│ MutArray['A -> 'A]\n\n:e\nty1 = ty2\n//│ MutArray['A -> 'A]\n//│   <:  ty1:\n//│ MutArray[forall 'X. 'X -> 'X]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.32: \tty1 = ty2\n//│ ║        \t^^^^^^^^^\n//│ ╟── type variable `'X` leaks out of its scope\n//│ ║  l.13: \tdef ty1: MutArray[forall 'X. 'X -> 'X]\n//│ ║        \t                             ^^\n//│ ╟── back into type variable `'X`\n//│ ║  l.13: \tdef ty1: MutArray[forall 'X. 'X -> 'X]\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.32: \tty1 = ty2\n//│ ╙──      \t      ^^^\n\n:e\nty2 = ty1\n//│ MutArray[forall 'X. 'X -> 'X]\n//│   <:  ty2:\n//│ MutArray['A -> 'A]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.51: \tty2 = ty1\n//│ ║        \t^^^^^^^^^\n//│ ╟── type `'X` does not match type `'A`\n//│ ║  l.13: \tdef ty1: MutArray[forall 'X. 'X -> 'X]\n//│ ║        \t                             ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.22: \tdef ty2: forall 'A. MutArray['A -> 'A]\n//│ ║        \t                             ^^\n//│ ╟── Note: quantified type variable 'X is defined at:\n//│ ║  l.13: \tdef ty1: MutArray[forall 'X. 'X -> 'X]\n//│ ╙──      \t                         ^^\n\n\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/ListBuild.mls",
    "content": ":NoRecursiveTypes\n\n\nclass Ls[A]\n  method HeadTail: (A, Ls[A]) | undefined\n//│ Defined class Ls[+A]\n//│ Declared Ls.HeadTail: Ls['A] -> (undefined | ('A, Ls['A],))\n\n// * Note that a more structural type such as this will raise cycle errors due to `:NoRecursiveTypes`\n// class Ls[A]: { head: A | undefined; tail: Ls[A] | undefined }\n\nclass Nil: Ls[nothing]\n  method HeadTail = undefined\n//│ Defined class Nil\n//│ Defined Nil.HeadTail: Nil -> undefined\n\nclass Cons[A]: Ls[A] & { head: A; tail: Ls[A] }\n  method HeadTail = (this.head, this.tail)\n//│ Defined class Cons[+A]\n//│ Defined Cons.HeadTail: Cons['A] -> ('A, Ls['A],)\n\ndef nil: Ls['a]\ndef cons: ('a, Ls['a]) -> Ls['a]\ndef single: 'a -> Ls['a]\n//│ nil: Ls[nothing]\n//│    = <missing implementation>\n//│ cons: ('a, Ls['a],) -> Ls['a]\n//│     = <missing implementation>\n//│ single: 'a -> Ls['a]\n//│       = <missing implementation>\n\nnil = Nil {}\ncons (head, tail) = Cons { head; tail }\n//│ Nil\n//│   <:  nil:\n//│ Ls[nothing]\n//│    = Nil {}\n//│ ('head & 'A, Ls['A] & 'tail,) -> (Cons['A] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ ('a, Ls['a],) -> Ls['a]\n//│     = [Function: cons]\n\n\n\n// * Random minimized trials:\n\n\ndef build0 (g: forall 'b. ('a -> 'b) -> 'b) = g single\n//│ build0: (forall 'b. ('a -> 'b) -> 'b) -> Ls['a]\n//│       = <no result>\n//│         single is not implemented\n\nbuild0 (fun s -> s 1)\n//│ res: Ls[1]\n//│    = <no result>\n//│      build0 and single are not implemented\n\nres: Ls[int]\n//│ res: Ls[int]\n//│    = undefined\n\n\ndef build0 (g: forall 'b. ('a -> 'b) -> 'b) = g (fun x -> single((x, x)))\n//│ build0: (forall 'b. ('a -> 'b) -> 'b) -> Ls[('a, 'a,)]\n//│       = <no result>\n//│         single is not implemented\n\ndef build0 (g: forall 'b. ('a -> 'a -> 'b) -> 'b) = g (fun x -> fun y -> single((x, y)))\n//│ build0: (forall 'b. ('a -> 'a -> 'b) -> 'b) -> Ls[('a, 'a,)]\n//│       = <no result>\n//│         single is not implemented\n\n:e // * This is recursive because we place the list-typed value inside a new list along with the head.\ndef build0 (g: forall 'b. ('a -> 'b -> 'b) -> 'b) = g (fun x -> fun y -> single((x, y)))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> Ls[(?, forall 'a. 'a,)]\n//│ ║  l.74: \tdef build0 (g: forall 'b. ('a -> 'b -> 'b) -> 'b) = g (fun x -> fun y -> single((x, y)))\n//│ ╙──      \t                                                                         ^^^^^^^^^^^^^^\n//│ build0: (forall 'b. ('a -> 'b -> 'b) -> 'b) -> 'c\n//│   where\n//│     'c :> Ls[('a, forall 'c. 'c,)]\n//│       = <no result>\n//│         single is not implemented\n\ndef build0 (g: forall 'b. (('a, 'b) -> 'b) -> 'b) = g cons\n//│ build0: (forall 'b. (('a, 'b,) -> 'b) -> 'b) -> Ls['a]\n//│       = [Function: build01]\n\ndef build0 (g: forall 'b. (('a, 'b) -> 'b) -> 'b) = g (fun (x, xs) -> cons (x, xs))\n//│ build0: (forall 'b. (('a, 'b,) -> 'b) -> 'b) -> Ls['a]\n//│       = [Function: build02]\n\ndef g: forall 'b. (('a, 'b) -> 'b) -> 'b\n//│ g: ((nothing, 'b,) -> 'b) -> 'b\n//│  = <missing implementation>\n\ng (fun (x, xs) -> cons (x, xs))\n//│ res: Ls[nothing]\n//│    = <no result>\n//│      g is not implemented\n\ndef g: ((int, 'b) -> 'b) -> 'b\n//│ g: ((int, 'b,) -> 'b) -> 'b\n//│  = <missing implementation>\n\ng (fun (x, xs) -> cons (x, xs))\n//│ res: Ls[int]\n//│    = <no result>\n//│      g is not implemented\n\ndef cons2: ('a, {x:'a}) -> {x:'a}\n// def cons2: ('a, 'a) -> 'a\n//│ cons2: ('a, {x: 'a},) -> {x: 'a}\n//│      = <missing implementation>\n\nf (x, xs) = cons2 (x, xs)\n//│ f: ('a, {x: 'a},) -> {x: 'a}\n//│  = <no result>\n//│    cons2 is not implemented\n\ng f\n//│ res: {x: int}\n//│    = <no result>\n//│      g is not implemented\n\n\ndef build0 (g: forall 'b. ('a -> 'b -> 'b) -> 'b) = g (fun x -> fun xs -> cons (x, xs))\n//│ build0: (forall 'b. ('a -> 'b -> 'b) -> 'b) -> Ls['a]\n//│       = [Function: build03]\n\n:re\nbuild0 (fun k -> k 1 error)\n//│ res: Ls[1]\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n\n// * The Real Deal:\n\n\ndef build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> cons (x, xs)) nil\n//│ build: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│      = [Function: build]\n\nxs0 = build (fun c -> fun n -> n)\n//│ xs0: Ls[nothing]\n//│    = Nil {}\n\nxs1 = build (fun c -> fun n -> c 1 n)\n//│ xs1: Ls[1]\n//│    = Cons { head: 1, tail: Nil {} }\n\nxs3 = build (fun c -> fun n -> c 1 (c 2 (c 3 n)))\n//│ xs3: Ls[1 | 2 | 3]\n//│    = Cons {\n//│        head: 1,\n//│        tail: Cons { head: 2, tail: Cons { head: 3, tail: Nil {} } }\n//│      }\n\n\n\nbuild: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│ res: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│    = [Function: build]\n\ndef build_ty: forall 'a. (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│ build_ty: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│         = <missing implementation>\n\nbuild_ty = build_ty\n//│ (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│   <:  build_ty:\n//│ (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│         = <no result>\n//│           build_ty is not implemented\n\nbuild: forall 'a. (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│ res: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│    = [Function: build]\n\n\n// * This `build` type is _too_ general as it lets the continuation assume it will handle lists instead of some unknown 'b\n:e\nbuild: (('a -> Ls['a] -> Ls['a]) -> Ls['a] -> Ls['a]) -> Ls['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.186: \tbuild: (('a -> Ls['a] -> Ls['a]) -> Ls['a] -> Ls['a]) -> Ls['a]\n//│ ║         \t^^^^^\n//│ ╟── type `Ls['a]` does not match type `'b`\n//│ ║  l.186: \tbuild: (('a -> Ls['a] -> Ls['a]) -> Ls['a] -> Ls['a]) -> Ls['a]\n//│ ║         \t               ^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.143: \tdef build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> cons (x, xs)) nil\n//│ ╙──       \t                                      ^^\n//│ res: (('a -> Ls['a] -> Ls['a]) -> Ls['a] -> Ls['a]) -> Ls['a]\n//│    = [Function: build]\n\n\n\n// * It also Just Works without type annotations!\n\n\ndef build_ = fun g -> g (fun x -> fun xs -> cons (x, xs)) nil\n//│ build_: ((forall 'a. 'a -> Ls['a] -> Ls['a]) -> Ls[nothing] -> 'b) -> 'b\n//│       = [Function: build_]\n\nbuild_ (fun c -> fun n -> n)\n//│ res: Ls[nothing]\n//│    = Nil {}\n\nbuild_ (fun c -> fun n -> c 1 n)\n//│ res: Ls[1]\n//│    = Cons { head: 1, tail: Nil {} }\n\nbuild_ (fun c -> fun n -> c 1 (c 2 (c 3 n)))\n//│ res: Ls[1 | 2 | 3]\n//│    = Cons {\n//│        head: 1,\n//│        tail: Cons { head: 2, tail: Cons { head: 3, tail: Nil {} } }\n//│      }\n\n\n\ndef g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b\n//│ g: (nothing -> 'b -> 'b) -> 'b -> 'b\n//│  = <missing implementation>\n\ng : ('a -> Ls['a] -> Ls['a]) -> Ls['a] -> Ls['a]\n//│ res: ('a -> Ls['a] -> Ls['a]) -> Ls['a] -> Ls['a]\n//│    = <no result>\n//│      g is not implemented\n\n\nbuild_ : (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│ res: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│    = [Function: build_]\n\n\ndef b: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│ b: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│  = <missing implementation>\n\nb = build_\n//│ ((forall 'a. 'a -> Ls['a] -> Ls['a]) -> Ls[nothing] -> 'b) -> 'b\n//│   <:  b:\n//│ (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│  = [Function: build_]\n\nb g = build_ g\n//│ ((forall 'a. 'a -> Ls['a] -> Ls['a]) -> Ls[nothing] -> 'b) -> 'b\n//│   <:  b:\n//│ (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│  = [Function: b1]\n\nb g = build_ (fun x -> g x)\n//│ ((forall 'a. 'a -> Ls['a] -> Ls['a]) -> Ls[nothing] -> 'b) -> 'b\n//│   <:  b:\n//│ (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│  = [Function: b2]\n\n:e\nb g x = build_ g x\n//│ ((forall 'a. 'a -> Ls['a] -> Ls['a]) -> Ls[nothing] -> 'b -> 'c) -> 'b -> 'c\n//│   <:  b:\n//│ (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.263: \tb g x = build_ g x\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Ls['a]` is not a function\n//│ ║  l.22: \tdef nil: Ls['a]\n//│ ║        \t         ^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.263: \tb g x = build_ g x\n//│ ║         \t        ^^^^^^^^^^\n//│ ╟── from application:\n//│ ║  l.204: \tdef build_ = fun g -> g (fun x -> fun xs -> cons (x, xs)) nil\n//│ ╙──       \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│  = [Function: b3]\n\n\n\nrec def fold f z xs =\n  let ht = xs.HeadTail in case ht of {\n  | undefined -> z\n  | _ -> (fun ((h, t)) -> f h (fold f z t)) ht\n  }\n//│ fold: ('a -> 'b -> 'b) -> 'b -> Ls['a] -> 'b\n//│     = [Function: fold]\n\nfold add 0 xs0\n//│ res: int\n//│    = 0\n\nfold add 0 xs1\n//│ res: int\n//│    = 1\n\nfold add 0 xs3\n//│ res: int\n//│    = 6\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Min1_ex_shallow.mls",
    "content": ":NoRecursiveTypes\n\n\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\ntype A1' = forall 'a. (('a | Sid) -> 'a) -> anything\n// type A1' = (Sid -> Sid) -> Sid -> Sid\n//│ Defined type alias A1'\n\ndef a1' : ((forall 'a. 'a -> 'a) -> anything) -> nothing\n//│ a1': ((forall 'a. 'a -> 'a) -> anything) -> nothing\n//│    = <missing implementation>\n\n// * Fails due to premature LHS instantiation (TODO improve)\n// :d\n:e\na1' : A1'\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.18: \ta1' : A1'\n//│ ║        \t^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.4: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║       \t                      ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.4: \ttype Sid = forall 'a. 'a -> 'a\n//│ ╙──     \t                            ^^\n//│ res: A1'\n//│    = <no result>\n//│      a1' is not implemented\n\ndef a2' (x: A1') = 0\n//│ a2': A1' -> 0\n//│    = [Function: a2$]\n\n:e\ndef a0' = a2' a1'\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.37: \tdef a0' = a2' a1'\n//│ ║        \t          ^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.4: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║       \t                      ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.4: \ttype Sid = forall 'a. 'a -> 'a\n//│ ╙──     \t                            ^^\n//│ a0': 0 | error\n//│    = <no result>\n//│      a1' is not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/MoreChurch.mls",
    "content": ":DistributeForalls\n:NoRecursiveTypes\n// :GeneralizeArguments // * This actually causes extrusions in pred, failing its type checking\n\n\n\ntype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ Defined type alias ChurchInt\n\n\n\ndef zero_ty: ChurchInt\n//│ zero_ty: ChurchInt\n//│        = <missing implementation>\n\ndef zero f x = x\n//│ zero: anything -> 'a -> 'a\n//│     = [Function: zero]\n\nzero_ty = zero\n//│ anything -> 'a -> 'a\n//│   <:  zero_ty:\n//│ ChurchInt\n//│        = [Function: zero]\n\n\ndef succ_ty: ChurchInt -> ChurchInt\n//│ succ_ty: ChurchInt -> ChurchInt\n//│        = <missing implementation>\n\ndef succ n f x = f (n f x)\n//│ succ: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│     = [Function: succ]\n\nsucc_ty = succ\n//│ ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│   <:  succ_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: succ]\n\n\n\ndef to_church_ty: int -> ChurchInt\n//│ to_church_ty: int -> ChurchInt\n//│             = <missing implementation>\n\nrec def to_church n =\n  if n == 0 then zero\n  else succ (to_church (n - 1))\n//│ to_church: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│          = [Function: to_church]\n\nto_church_ty = to_church\n//│ int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church]\n\n\n\ndef add_ty: ChurchInt -> ChurchInt -> ChurchInt\n//│ add_ty: ChurchInt -> ChurchInt -> ChurchInt\n//│       = <missing implementation>\n\ndef add n m = n succ m\n//│ add: ((forall 'a 'b 'c 'd. ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd) -> 'e -> 'f) -> 'e -> 'f\n//│    = [Function: add]\n\n// * Note: cycle check fails when generalizing curried lambdas\nadd_ty = add\n//│ ((forall 'a 'b 'c 'd. ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd) -> 'e -> 'f) -> 'e -> 'f\n//│   <:  add_ty:\n//│ ChurchInt -> ChurchInt -> ChurchInt\n//│       = [Function: add]\n\ndef add (n: ChurchInt) m = n succ m\n// def add (n: ChurchInt) m = n succ_ty m\n//│ add: ChurchInt -> ('a -> 'b -> 'c & 'd) -> (('c -> ('c & 'e) & 'a) -> 'b -> 'e | 'd)\n//│    = [Function: add1]\n\nadd_ty = add\n//│ ChurchInt -> ('a -> 'b -> 'c & 'd) -> (('c -> ('c & 'e) & 'a) -> 'b -> 'e | 'd)\n//│   <:  add_ty:\n//│ ChurchInt -> ChurchInt -> ChurchInt\n//│       = [Function: add1]\n\n\ndef mul_ty: ChurchInt -> ChurchInt -> ChurchInt\n//│ mul_ty: ChurchInt -> ChurchInt -> ChurchInt\n//│       = <missing implementation>\n\ndef mul n m = n (add m) zero\n//│ mul: ((forall 'a 'b 'c 'd 'e. ('a -> 'b -> 'c & 'd) -> (('c -> ('c & 'e) & 'a) -> 'b -> 'e | 'd)) -> (forall 'f. anything -> 'f -> 'f) -> 'g) -> ChurchInt -> 'g\n//│    = [Function: mul]\n\n// * Note: cycle check fails when generalizing curried lambdas\nmul_ty = mul\n//│ ((forall 'a 'b 'c 'd 'e. ('a -> 'b -> 'c & 'd) -> (('c -> ('c & 'e) & 'a) -> 'b -> 'e | 'd)) -> (forall 'f. anything -> 'f -> 'f) -> 'g) -> ChurchInt -> 'g\n//│   <:  mul_ty:\n//│ ChurchInt -> ChurchInt -> ChurchInt\n//│       = [Function: mul]\n\ndef mul (n: ChurchInt) m = n (add m) zero\n//│ mul: ChurchInt -> ChurchInt -> ('a -> ('a & 'b)) -> ('b & 'a) -> 'b\n//│    = [Function: mul1]\n\nmul_ty = mul\n//│ ChurchInt -> ChurchInt -> ('a -> ('a & 'b)) -> ('b & 'a) -> 'b\n//│   <:  mul_ty:\n//│ ChurchInt -> ChurchInt -> ChurchInt\n//│       = [Function: mul1]\n\n\n\ndef pow_ty: ChurchInt -> ChurchInt -> ChurchInt\n//│ pow_ty: ChurchInt -> ChurchInt -> ChurchInt\n//│       = <missing implementation>\n\n:e\ndef pow (n: ChurchInt) (m: ChurchInt) = n (mul m) (succ zero)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.120: \tdef pow (n: ChurchInt) (m: ChurchInt) = n (mul m) (succ zero)\n//│ ║         \t                                        ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.7: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║       \t                                           ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.7: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║       \t                             ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.31: \tdef succ n f x = f (n f x)\n//│ ╙──      \t                        ^\n//│ pow: ChurchInt -> ChurchInt -> (error | (anything -> ??a & 'a -> 'a) -> (??a & 'a) -> anything)\n//│    = [Function: pow]\n\ndef pow (n: ChurchInt) (m: ChurchInt) = n (mul_ty m) (succ_ty zero_ty)\n//│ pow: ChurchInt -> ChurchInt -> ChurchInt\n//│    = [Function: pow1]\npow_ty = pow\n//│ ChurchInt -> ChurchInt -> ChurchInt\n//│   <:  pow_ty:\n//│ ChurchInt -> ChurchInt -> ChurchInt\n//│       = [Function: pow1]\n\ndef pow (n: ChurchInt) m = n (mul m) (succ_ty zero)\n//│ pow: ChurchInt -> ChurchInt -> (('a -> ('a & 'b)) -> ('b & 'a) -> 'b | ChurchInt)\n//│    = [Function: pow2]\npow_ty = pow\n//│ ChurchInt -> ChurchInt -> (('a -> ('a & 'b)) -> ('b & 'a) -> 'b | ChurchInt)\n//│   <:  pow_ty:\n//│ ChurchInt -> ChurchInt -> ChurchInt\n//│       = [Function: pow2]\n\n\n\ndef unit = id\n//│ unit: 'a -> 'a\n//│     = [Function: unit]\n\ntype Unit_t = 'a -> 'a\nunit : Unit_t\n//│ Defined type alias Unit_t\n//│ res: Unit_t\n//│    = [Function: id]\n\ndef tru x _ = x unit\n//│ tru: ((forall 'a. 'a -> 'a) -> 'b) -> anything -> 'b\n//│    = [Function: tru]\n\ndef fls _ x = x unit\n//│ fls: anything -> ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│    = [Function: fls]\n\ntype If_t = (Unit_t -> 'a) -> (Unit_t -> 'a) -> 'a\ntru : If_t\nfls : If_t\n//│ Defined type alias If_t\n//│ res: If_t\n//│    = [Function: tru]\n//│ res: If_t\n//│    = [Function: fls]\n\ndef iszero n = n (fun _ -> fls) tru\n//│ iszero: ((forall 'a. anything -> anything -> ((forall 'b. 'b -> 'b) -> 'a) -> 'a) -> (forall 'c. ((forall 'b. 'b -> 'b) -> 'c) -> anything -> 'c) -> 'd) -> 'd\n//│       = [Function: iszero]\n\niszero : ChurchInt -> If_t\n//│ res: ChurchInt -> If_t\n//│    = [Function: iszero]\n\ndef pair x y f = f x y\n//│ pair: 'a -> 'b -> ('a -> 'b -> 'c) -> 'c\n//│     = [Function: pair]\n\ndef fst p = p (fun x -> fun _ -> x)\n//│ fst: ((forall 'a. 'a -> anything -> 'a) -> 'b) -> 'b\n//│    = [Function: fst]\n\ndef snd p = p (fun _ -> fun x -> x)\n//│ snd: ((forall 'a. anything -> 'a -> 'a) -> 'b) -> 'b\n//│    = [Function: snd]\n\n\n\ndef pred_ty: ChurchInt -> ChurchInt\n//│ pred_ty: ChurchInt -> ChurchInt\n//│        = <missing implementation>\n\ndef s p = pair (snd p) (succ (snd p))\n//│ s: ((forall 'a. anything -> 'a -> 'a) -> ('b -> 'c -> 'd & 'e)) -> ('e -> (('d -> 'f & 'b) -> 'c -> 'f) -> 'g) -> 'g\n//│  = [Function: s]\n\ndef z = pair zero zero\n//│ z: ((forall 'a. anything -> 'a -> 'a) -> (forall 'a. anything -> 'a -> 'a) -> 'b) -> 'b\n//│  = [Function: z]\n\ndef pred (n: ChurchInt) = fst (n s z)\n//│ pred: ChurchInt -> ('a -> ('a & 'b)) -> ('b & 'a) -> 'b\n//│     = [Function: pred]\n\npred_ty = pred\n//│ ChurchInt -> ('a -> ('a & 'b)) -> ('b & 'a) -> 'b\n//│   <:  pred_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: pred]\n\n\n\ndef pred n =\n  let s p = pair (snd p) (succ (snd p)) in\n  let z = pair zero zero in\n  fst (n s z)\n//│ pred: ((forall 'a 'b 'c 'd 'e 'f. ((forall 'g. anything -> 'g -> 'g) -> ('a -> 'b -> 'c & 'd)) -> ('d -> (('c -> 'e & 'a) -> 'b -> 'e) -> 'f) -> 'f) -> (forall 'h. ((forall 'i. anything -> 'i -> 'i) -> (forall 'i. anything -> 'i -> 'i) -> 'h) -> 'h) -> (forall 'j. 'j -> anything -> 'j) -> 'k) -> 'k\n//│     = [Function: pred1]\n// * Note: cycle check fails when generalizing curried lambdas\npred_ty = pred\n//│ ((forall 'a 'b 'c 'd 'e 'f. ((forall 'g. anything -> 'g -> 'g) -> ('a -> 'b -> 'c & 'd)) -> ('d -> (('c -> 'e & 'a) -> 'b -> 'e) -> 'f) -> 'f) -> (forall 'h. ((forall 'i. anything -> 'i -> 'i) -> (forall 'i. anything -> 'i -> 'i) -> 'h) -> 'h) -> (forall 'j. 'j -> anything -> 'j) -> 'k) -> 'k\n//│   <:  pred_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: pred1]\n\n// * Only difference: use `succ_ty`\ndef pred n =\n  let s p = pair (snd p) (succ_ty (snd p)) in\n  let z = pair zero zero in\n  fst (n s z)\n//│ pred: ((forall 'a 'b. ((forall 'c. anything -> 'c -> 'c) -> (ChurchInt & 'a)) -> ('a -> ChurchInt -> 'b) -> 'b) -> (forall 'd. ((forall 'e. anything -> 'e -> 'e) -> (forall 'e. anything -> 'e -> 'e) -> 'd) -> 'd) -> (forall 'f. 'f -> anything -> 'f) -> 'g) -> 'g\n//│     = [Function: pred2]\npred_ty = pred\n//│ ((forall 'a 'b. ((forall 'c. anything -> 'c -> 'c) -> (ChurchInt & 'a)) -> ('a -> ChurchInt -> 'b) -> 'b) -> (forall 'd. ((forall 'e. anything -> 'e -> 'e) -> (forall 'e. anything -> 'e -> 'e) -> 'd) -> 'd) -> (forall 'f. 'f -> anything -> 'f) -> 'g) -> 'g\n//│   <:  pred_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: pred2]\n\n\n\ndef fact_ty: ChurchInt -> ChurchInt\n//│ fact_ty: ChurchInt -> ChurchInt\n//│        = <missing implementation>\n\n// * Note: cycle check fails when generalizing curried lambdas\nrec def fact (n: ChurchInt) = (iszero n) (fun _ -> succ zero) (fun _ -> mul n (fact (pred n)))\n//│ fact: ChurchInt -> ('a -> ('a & 'b) & 'c -> 'b) -> ('b & 'a & 'c) -> 'b\n//│     = [Function: fact]\n\n:precise-rec-typing\nrec def fact (n: ChurchInt) = (iszero n) (fun _ -> succ zero) (fun _ -> mul n (fact (pred n)))\n//│ fact: ChurchInt -> ('a -> ('a & 'b) & 'c -> 'b) -> ('b & 'a & 'c) -> 'b\n//│     = [Function: fact1]\n\nfact_ty = fact\n//│ ChurchInt -> ('a -> ('a & 'b) & 'c -> 'b) -> ('b & 'a & 'c) -> 'b\n//│   <:  fact_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: fact1]\n\n// * A dummy mistake:\n:e\ndef fact (n: ChurchInt) = (iszero n) (fun _ -> succ zero) (fun _ -> mul n {})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.279: \tdef fact (n: ChurchInt) = (iszero n) (fun _ -> succ zero) (fun _ -> mul n {})\n//│ ║         \t                                                                    ^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.279: \tdef fact (n: ChurchInt) = (iszero n) (fun _ -> succ zero) (fun _ -> mul n {})\n//│ ║         \t                                                                          ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.7: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║       \t                            ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.103: \tdef mul (n: ChurchInt) m = n (add m) zero\n//│ ╙──       \t                                  ^\n//│ fact: ChurchInt -> (error | ('a -> ('a & 'b) & 'c -> 'b) -> ('b & 'a & 'c) -> 'b)\n//│     = [Function: fact2]\n\n// * We can drop all intermediate annotations if the recursive call is annotated:\ndef fact n = (iszero n) (fun _ -> succ zero) (fun _ -> mul n (fact_ty (pred n)))\n//│ fact: (ChurchInt & (forall 'a. anything -> anything -> ((forall 'b. 'b -> 'b) -> 'a) -> 'a) -> (forall 'c. ((forall 'b. 'b -> 'b) -> 'c) -> anything -> 'c) -> (forall 'd 'e. anything -> ('d -> 'e) -> 'd -> 'e) -> (forall 'f 'g. anything -> ('f -> ('f & 'g)) -> ('g & 'f) -> 'g) -> 'h & (forall 'i 'j. ((forall 'k. anything -> 'k -> 'k) -> (ChurchInt & 'i)) -> ('i -> ChurchInt -> 'j) -> 'j) -> (forall 'l. ((forall 'm. anything -> 'm -> 'm) -> (forall 'm. anything -> 'm -> 'm) -> 'l) -> 'l) -> (forall 'n. 'n -> anything -> 'n) -> ChurchInt) -> 'h\n//│     = [Function: fact3]\n\nfact_ty = fact\n//│ (ChurchInt & (forall 'a. anything -> anything -> ((forall 'b. 'b -> 'b) -> 'a) -> 'a) -> (forall 'c. ((forall 'b. 'b -> 'b) -> 'c) -> anything -> 'c) -> (forall 'd 'e. anything -> ('d -> 'e) -> 'd -> 'e) -> (forall 'f 'g. anything -> ('f -> ('f & 'g)) -> ('g & 'f) -> 'g) -> 'h & (forall 'i 'j. ((forall 'k. anything -> 'k -> 'k) -> (ChurchInt & 'i)) -> ('i -> ChurchInt -> 'j) -> 'j) -> (forall 'l. ((forall 'm. anything -> 'm -> 'm) -> (forall 'm. anything -> 'm -> 'm) -> 'l) -> 'l) -> (forall 'n. 'n -> anything -> 'n) -> ChurchInt) -> 'h\n//│   <:  fact_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: fact3]\n\n\nfact (to_church 4) (fun x -> x + 1) 0\n//│ res: int\n//│    = 24\n\nfact_ty (to_church 4) (fun x -> x + 1) 0\n//│ res: int\n//│    = 24\n\nfact (to_church_ty 4) (fun x -> x + 1) 0\n//│ res: int\n//│    = 24\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/NestedDataTypes.mls",
    "content": ":NoRecursiveTypes\n:ConstrainedTypes // * The test takes too much time without this\n\n// * Perfect Trees (https://www.cis.upenn.edu/~plclub/blog/2020-12-04-nested-datatypes/)\n\n// data NTree (a :: Type) =\n//     NLeaf a\n//   | NNode (NTree (Two a))\n\n\ntype Two[A] = (A, A)\n//│ Defined type alias Two[+A]\n\ndef mapTwo f ((a, b)) = (f a, f b)\n//│ mapTwo: 'a -> ((('b, 'c,),) -> ('d, 'e,)\n//│   where\n//│     'a <: 'b -> 'd & 'c -> 'e)\n//│       = [Function: mapTwo]\n\nclass Leaf[A]: { value: A }\n//│ Defined class Leaf[+A]\n\n:e\nclass Node[A]: { subTree: PerfectTree[Two[A]] }\ntype PerfectTree[A] = Leaf[A] | Node[A]\n//│ ╔══[ERROR] Type definition is not regular: it occurs within itself as Node[Two['A]], but is defined as Node['A]\n//│ ║  l.24: \tclass Node[A]: { subTree: PerfectTree[Two[A]] }\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type definition is not regular: it occurs within itself as PerfectTree[Two['A]], but is defined as PerfectTree['A]\n//│ ║  l.25: \ttype PerfectTree[A] = Leaf[A] | Node[A]\n//│ ╙──      \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:IrregularTypes\n\nclass Node[A]: { subTree: PerfectTree[Two[A]] }\ntype PerfectTree[A] = Leaf[A] | Node[A]\n//│ Defined class Node[+A]\n//│ Defined type alias PerfectTree[+A]\n\n\nn1 = Leaf { value = 1 }\n//│ n1: Leaf[1]\n//│   = Leaf { value: 1 }\nn1: PerfectTree[int]\n//│ res: PerfectTree[int]\n//│    = Leaf { value: 1 }\n\nn2 = Node { subTree = Leaf { value = (1, 2) } }\n//│ n2: Node[1 | 2] with {subTree: Leaf[(1, 2,)]}\n//│   = Node1 { subTree: Leaf { value: [ 1, 2 ] } }\nn2: PerfectTree[int]\n//│ res: PerfectTree[int]\n//│    = Node1 { subTree: Leaf { value: [ 1, 2 ] } }\n\nn4 = Node { subTree = Node { subTree = Leaf { value = ((1, 2), (3, 4)) } } }\n//│ n4: Node[1 | 2 | 3 | 4] with {subTree: Node[(1 | 3, 2 | 4,)] with {subTree: Leaf[((1, 2,), (3, 4,),)]}}\n//│   = Node1 { subTree: Node1 { subTree: Leaf { value: [Array] } } }\nn4: PerfectTree[int]\n//│ res: PerfectTree[int]\n//│    = Node1 { subTree: Node1 { subTree: Leaf { value: [Array] } } }\n\n\n// * On some systems, the default -Xss4M is not enough for this case\n// :e // * Needs precise-rec-typing (see below)\n// rec def map f tree = case tree of {\n//   | Leaf -> Leaf { value = f tree.value }\n//   | Node -> Node { subTree = map (mapTwo f) tree.subTree }\n//   }\n\n:e // occurs-check\n:precise-rec-typing\nrec def map f tree = case tree of {\n  | Leaf -> Leaf { value = f tree.value }\n  | Node -> Node { subTree = map (mapTwo f) tree.subTree }\n  }\n//│ ╔══[ERROR] Inferred recursive type: 'map\n//│   where\n//│     'map :> forall 'a 'subTree 'A 'subTree0 'value 'value0. 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: 'subTree})) -> (Leaf['value0] | (Node['A] with {subTree: 'subTree0}))\n//│       where\n//│         'map <: (forall 'b 'c 'd 'e. (('b, 'd,),) -> ('c, 'e,)\n//│           where\n//│             'a <: 'b -> 'c & 'd -> 'e) -> 'subTree -> (PerfectTree[Two['A]] & 'subTree0)\n//│         'a <: 'value -> 'value0)\n//│ ╙──\n//│ map: 'map\n//│   where\n//│     'map :> forall 'a 'subTree 'A 'subTree0 'value 'value0. 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: 'subTree})) -> (Leaf['value0] | (Node['A] with {subTree: 'subTree0}))\n//│       where\n//│         'map <: (forall 'b 'c 'd 'e. (('b, 'd,),) -> ('c, 'e,)\n//│           where\n//│             'a <: 'b -> 'c & 'd -> 'e) -> 'subTree -> (PerfectTree[Two['A]] & 'subTree0)\n//│         'a <: 'value -> 'value0)\n//│    = [Function: map]\n\n:e\nmap succ n4\n//│ ╔══[ERROR] Inferred recursive type: 'map\n//│   where\n//│     'map :> forall 'subTree 'A 'subTree0 'value 'value0. 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: 'subTree})) -> (Leaf['value0] | (Node['A] with {subTree: 'subTree0}))\n//│       where\n//│         'map <: (forall 'b 'c 'd 'e. (('b, 'd,),) -> ('c, 'e,)\n//│           where\n//│             'a <: 'b -> 'c & 'd -> 'e) -> 'subTree -> (PerfectTree[Two['A]] & 'subTree0)\n//│         'a <: 'value -> 'value0)\n//│ ╙──\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.96: \tmap succ n4\n//│ ║        \t^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│    = Node1 { subTree: Node1 { subTree: Leaf { value: [Array] } } }\n\n\ndef map: ('a -> 'b) -> PerfectTree['a] -> PerfectTree['b]\n//│ map: ('a -> 'b) -> PerfectTree['a] -> PerfectTree['b]\n//│    = <missing implementation>\n\ndef map f tree = case tree of {\n  | Leaf -> Leaf { value = f tree.value }\n  | Node -> Node { subTree = map (mapTwo f) tree.subTree }\n  }\n//│ 'a -> ((Leaf[?] & {value: 'value} | (Node[?] with {subTree: PerfectTree[('b, 'c,)]})) -> (Leaf['value0] | (Node['A] with {subTree: PerfectTree[('d, 'e,)]}))\n//│   where\n//│     'a <: 'value -> 'value0 & 'b -> ('d & 'A) & 'c -> ('A & 'e))\n//│   <:  map:\n//│ ('a -> 'b) -> PerfectTree['a] -> PerfectTree['b]\n//│    = <no result>\n//│      map is not implemented\n\nmap succ n4\n//│ res: PerfectTree[int]\n//│    = <no result>\n//│      map and map are not implemented\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/NestedDataTypesGADT.mls",
    "content": ":NoRecursiveTypes\n:IrregularTypes\n\n\n// * Perfect Trees (https://www.cis.upenn.edu/~plclub/blog/2020-12-04-nested-datatypes/)\n\n// * Representing perfect trees with GADTs\n\n// data HTree (h :: Nat) (a :: Type) where\n//   DLeaf :: a -> HTree Z a\n//   DNode :: Two (HTree h a) -> HTree (S h) a\n\n\ntype Two[A] = (A, A)\n//│ Defined type alias Two[+A]\n\ndef mapTwo f ((a, b)) = (f a, f b)\n//│ mapTwo: ('a -> 'b & 'c -> 'd) -> (('a, 'c,),) -> ('b, 'd,)\n//│       = [Function: mapTwo]\n\n// class Z\n// class S: { value: Nat }\n// type NAT = S | Z\nclass Z\nclass S[P]\n  method Inv: P -> P\n  method Inv = id\n//│ Defined class Z\n//│ Defined class S[=P]\n//│ Declared S.Inv: S['P] -> 'P -> 'P\n//│ Defined S.Inv: S['P] -> 'a -> 'a\n\n:w\nclass HTreeBase[N, A]: { n: N }\nclass DLeaf[A]: HTreeBase[Z, A] & { value: A }\nclass DNode[N, A]: HTreeBase[S[N], A] & { subTree: Two[HTree[N, A]] }\ntype HTree[N, A] = forall 'r. (forall 'p. (DLeaf[A] | DNode[S['p], A] & DNode[N, A]) -> 'r) -> 'r\n//│ Defined class HTreeBase[+N, ±A]\n//│ Defined class DLeaf[+A]\n//│ Defined class DNode[=N, +A]\n//│ Defined type alias HTree[=N, +A]\n//│ ╔══[WARNING] Type definition HTreeBase has bivariant type parameters:\n//│ ║  l.34: \tclass HTreeBase[N, A]: { n: N }\n//│ ║        \t      ^^^^^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.34: \tclass HTreeBase[N, A]: { n: N }\n//│ ╙──      \t                   ^\n\n\nd1 = DLeaf { value = 1; n = Z{} }\n//│ d1: DLeaf[1]\n//│   = DLeaf { n: Z {}, value: 1 }\nd1: HTreeBase[Z, int]\n//│ res: HTreeBase[Z, ?]\n//│    = DLeaf { n: Z {}, value: 1 }\n\nd1_ k = k d1\n//│ d1_: (DLeaf[1] -> 'a) -> 'a\n//│    = [Function: d1_]\n\nd1_ : HTree[Z, int]\n//│ res: HTree[Z, int]\n//│    = [Function: d1_]\n\nd2 = DNode { subTree = (d1_, d1_); n = S{} }\n//│ d2: DNode['N, 1] with {\n//│   n: forall 'P. S['P],\n//│   subTree: (forall 'a. (DLeaf[1] -> 'a) -> 'a, forall 'a. (DLeaf[1] -> 'a) -> 'a,)\n//│ }\n//│   = DNode { n: S {}, subTree: [ [Function: d1_], [Function: d1_] ] }\n\ndef d1_ty: HTree[Z, int]\n//│ d1_ty: HTree[Z, int]\n//│      = <missing implementation>\n\nd2 = DNode { subTree = (d1_ty, d1_ty); n = S{} }\n//│ d2: DNode[Z, int] with {n: forall 'P. S['P], subTree: (HTree[Z, int], HTree[Z, int],)}\n//│   = <no result>\n//│     d1_ty is not implemented\nd2: DNode[Z, int]\nd2: HTreeBase[S[Z], int]\n//│ res: DNode[Z, int]\n//│    = <no result>\n//│      d2 and d1_ty are not implemented\n//│ res: HTreeBase[S[Z], ?]\n//│    = <no result>\n//│      d2 and d1_ty are not implemented\n\nd2_ k = k d2\n//│ d2_: ((DNode[Z, int] with {n: forall 'P. S['P], subTree: (HTree[Z, int], HTree[Z, int],)}) -> 'a) -> 'a\n//│    = <no result>\n//│      d2 and d1_ty are not implemented\n\n:e // FIXME\nd2_ : HTree[S[Z], int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.95: \td2_ : HTree[S[Z], int]\n//│ ║        \t^^^\n//│ ╟── expression of type `S[in Z & 'p out Z | 'p]` is not an instance of type `Z`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.72: \tdef d1_ty: HTree[Z, int]\n//│ ║        \t                 ^\n//│ ╟── Note: class type parameter N is defined at:\n//│ ║  l.36: \tclass DNode[N, A]: HTreeBase[S[N], A] & { subTree: Two[HTree[N, A]] }\n//│ ╙──      \t            ^\n//│ res: HTree[S[Z], int]\n//│    = <no result>\n//│      d2_, d2 and d1_ty are not implemented\n\n:e // FIXME\nd2_ k = k (d2:HTreeBase[S[Z], int])\nd2_ : HTree[S[Z], int]\n//│ d2_: (HTreeBase[S[Z], ?] -> 'a) -> 'a\n//│    = <no result>\n//│      d2 and d1_ty are not implemented\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.112: \td2_ : HTree[S[Z], int]\n//│ ║         \t^^^\n//│ ╟── type `HTreeBase[S[Z], ?]` does not match type `DLeaf[int] | DNode[S[in Z & 'p out Z | 'p], int]`\n//│ ║  l.111: \td2_ k = k (d2:HTreeBase[S[Z], int])\n//│ ║         \t              ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.37: \ttype HTree[N, A] = forall 'r. (forall 'p. (DLeaf[A] | DNode[S['p], A] & DNode[N, A]) -> 'r) -> 'r\n//│ ╙──      \t                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: HTree[S[Z], int]\n//│    = <no result>\n//│      d2_, d2 and d1_ty are not implemented\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/NoRecursiveTypes.mls",
    "content": ":NoRecursiveTypes\n\n\n:e\nfoo =\n  let rec f x = f x.a in 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: {a: 'a}\n//│ ║  l.6: \t  let rec f x = f x.a in 0\n//│ ╙──     \t                  ^^^\n//│ foo: 0\n//│    = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/OCamlList.mls",
    "content": ":NoJS\n\n// From https://github.com/ocaml/ocaml/blob/5312b4d7b913cde2a69fc0eb5e97e353865b82df/stdlib/list.ml\n// and https://github.com/ocaml/ocaml/blob/5312b4d7b913cde2a69fc0eb5e97e353865b82df/stdlib/list.mli\n\n\n\n// *** Signatures of required definitions ***\n\n\n// `compare` and (=) in OCaml are polymorphic\ndef compare' : 'a -> 'a -> int\ndef eq' : 'a -> 'a -> bool\n//│ compare': anything -> anything -> int\n//│ eq': anything -> anything -> bool\n\ndef asr: int -> int -> int\n//│ asr: int -> int -> int\n\ndef fst: (('a, 'b),) -> 'a\ndef snd: (('a, 'b),) -> 'b\n//│ fst: (('a, anything,),) -> 'a\n//│ snd: ((anything, 'b,),) -> 'b\n\ndef assert: { fail: anything -> nothing }\n//│ assert: {fail: anything -> nothing}\n\ndef failwith: string -> nothing\ndef failwith s = assert.fail (concat \"Failure: \" s)\ndef invalid_arg: string -> nothing\ndef invalid_arg s = assert.fail (concat \"Invalid argument: \" s)\n//│ failwith: string -> nothing\n//│ string -> nothing\n//│   <:  failwith:\n//│ string -> nothing\n//│ invalid_arg: string -> nothing\n//│ string -> nothing\n//│   <:  invalid_arg:\n//│ string -> nothing\n\nclass Exn\ndef Not_found: Exn\ndef raise: Exn -> nothing\n//│ Defined class Exn\n//│ Not_found: Exn\n//│ raise: Exn -> nothing\n\ndatatype Option[A] = Some(A) | None\n//│ Defined class Option[+A]\n//│ Declared Option.Some: Option['A] -> ('A,)\n//│ Declared Option.None: Option[?] -> anything\n//│ Defined class Some[+A]\n//│ Defined class None[+A]\n//│ Some: 'a -> Option['a]\n//│ None: Option[nothing]\n\ndatatype Either[A, B] = Left(A) | Right(B)\n//│ Defined class Either[+A, +B]\n//│ Declared Either.Left: Either['A, ?] -> ('A,)\n//│ Declared Either.Right: Either[?, 'B] -> ('B,)\n//│ Defined class Left[+A, +B]\n//│ Defined class Right[+A, +B]\n//│ Left: 'a -> Either['a, nothing]\n//│ Right: 'a -> Either[nothing, 'a]\n\ndatatype List[A] = Cons(A, List[A]) | Nil\n//│ Defined class List[+A]\n//│ Declared List.Cons: List['A] -> ('A, List['A],)\n//│ Declared List.Nil: List[?] -> anything\n//│ Defined class Cons[+A]\n//│ Defined class Nil[+A]\n//│ Cons: ('a, List['a],) -> List['a]\n//│ Nil: List[nothing]\n\ndatatype Node[A] = SeqNil | SeqCons(A, Seq[A])\ntype Seq[A] = unit -> Node[A]\n//│ Defined class Node[+A]\n//│ Declared Node.SeqNil: Node[?] -> anything\n//│ Declared Node.SeqCons: Node['A] -> ('A, Seq['A],)\n//│ Defined class SeqNil[+A]\n//│ Defined class SeqCons[+A]\n//│ Defined type alias Seq[+A]\n//│ SeqNil: Node[nothing]\n//│ SeqCons: ('a, Seq['a],) -> Node['a]\n\n\n\n// *** Signatures ported from List.mli ***\n\n\ndef length: List['a] -> int\n//│ length: List[?] -> int\n\ndef compare_lengths: List['a] -> List['b] -> int\n//│ compare_lengths: List[?] -> List[?] -> int\n\ndef compare_length_with: List['a] -> int -> int\n//│ compare_length_with: List[?] -> int -> int\n\ndef is_empty: List['a] -> bool\n//│ is_empty: List[?] -> bool\n\ndef cons: 'a -> List['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n\ndef hd: List['a] -> 'a\n//│ hd: List['a] -> 'a\n\ndef tl: List['a] -> List['a]\n//│ tl: List['a] -> List['a]\n\ndef nth: List['a] -> int -> 'a\n//│ nth: List['a] -> int -> 'a\n\ndef nth_opt: List['a] -> int -> Option['a]\n//│ nth_opt: List['a] -> int -> Option['a]\n\ndef rev: List['a] -> List['a]\n//│ rev: List['a] -> List['a]\n\ndef init: int -> (int -> 'a) -> List['a]\n//│ init: int -> (int -> 'a) -> List['a]\n\ndef append: List['a] -> List['a] -> List ['a]\n//│ append: List['a] -> List['a] -> List['a]\n\ndef rev_append: List['a] -> List['a] -> List ['a]\n//│ rev_append: List['a] -> List['a] -> List['a]\n\ndef concat: List[List['a]] -> List['a]\n//│ concat: List[List['a]] -> List['a]\n\ndef flatten: List[List['a]] -> List['a]\n//│ flatten: List[List['a]] -> List['a]\n\ndef equal: ('a -> 'a -> bool) -> List['a] -> List['a] -> bool\n//│ equal: ('a -> 'a -> bool) -> List['a] -> List['a] -> bool\n\ndef compare: ('a -> 'a -> int) -> List['a] -> List['a] -> int\n//│ compare: ('a -> 'a -> int) -> List['a] -> List['a] -> int\n\ndef iter: ('a -> unit) -> List['a] -> unit\n//│ iter: ('a -> unit) -> List['a] -> unit\n\ndef iteri: (int -> 'a -> unit) -> List['a] -> unit\n//│ iteri: (int -> 'a -> unit) -> List['a] -> unit\n\ndef map: ('a -> 'b) -> List['a] -> List['b]\n//│ map: ('a -> 'b) -> List['a] -> List['b]\n\ndef mapi: (int -> 'a -> 'b) -> List['a] -> List['b]\n//│ mapi: (int -> 'a -> 'b) -> List['a] -> List['b]\n\ndef rev_map: ('a -> 'b) -> List['a] -> List['b]\n//│ rev_map: ('a -> 'b) -> List['a] -> List['b]\n\ndef filter_map: ('a -> Option['b]) -> List['a] -> List['b]\n//│ filter_map: ('a -> Option['b]) -> List['a] -> List['b]\n\ndef concat_map: ('a -> List['b]) -> List['a] -> List['b]\n//│ concat_map: ('a -> List['b]) -> List['a] -> List['b]\n\ndef fold_left_map: ('acc -> 'a -> ('acc, 'b)) -> 'acc -> List['a] -> ('acc, List['b])\n//│ fold_left_map: ('acc -> 'a -> ('acc, 'b,)) -> 'acc -> List['a] -> ('acc, List['b],)\n\ndef fold_left: ('acc -> 'a -> 'acc) -> 'acc -> List['a] -> 'acc\n//│ fold_left: ('acc -> 'a -> 'acc) -> 'acc -> List['a] -> 'acc\n\ndef fold_right: ('a -> 'acc -> 'acc) -> List['a] -> 'acc -> 'acc\n//│ fold_right: ('a -> 'acc -> 'acc) -> List['a] -> 'acc -> 'acc\n\ndef iter2: ('a -> 'b -> unit) -> List['a] -> List['b] -> unit\n//│ iter2: ('a -> 'b -> unit) -> List['a] -> List['b] -> unit\n\ndef map2: ('a -> 'b -> 'c) -> List['a] -> List['b] -> List['c]\n//│ map2: ('a -> 'b -> 'c) -> List['a] -> List['b] -> List['c]\n\ndef rev_map2: ('a -> 'b -> 'c) -> List['a] -> List['b] -> List['c]\n//│ rev_map2: ('a -> 'b -> 'c) -> List['a] -> List['b] -> List['c]\n\ndef fold_left2: ('acc -> 'a -> 'b -> 'acc) -> 'acc -> List['a] -> List['b] -> 'acc\n//│ fold_left2: ('acc -> 'a -> 'b -> 'acc) -> 'acc -> List['a] -> List['b] -> 'acc\n\ndef fold_right2: ('a -> 'b -> 'acc -> 'acc) -> List['a] -> List['b] -> 'acc -> 'acc\n//│ fold_right2: ('a -> 'b -> 'acc -> 'acc) -> List['a] -> List['b] -> 'acc -> 'acc\n\ndef for_all: ('a -> bool) -> List['a] -> bool\n//│ for_all: ('a -> bool) -> List['a] -> bool\n\ndef exists: ('a -> bool) -> List['a] -> bool\n//│ exists: ('a -> bool) -> List['a] -> bool\n\ndef for_all2: ('a -> 'b -> bool) -> List['a] -> List['b] -> bool\n//│ for_all2: ('a -> 'b -> bool) -> List['a] -> List['b] -> bool\n\ndef exists2: ('a -> 'b -> bool) -> List['a] -> List['b] -> bool\n//│ exists2: ('a -> 'b -> bool) -> List['a] -> List['b] -> bool\n\ndef mem: 'a -> List['a] -> bool\n//│ mem: anything -> List[?] -> bool\n\ndef memq: 'a -> List['a] -> bool\n//│ memq: anything -> List[?] -> bool\n\ndef find: ('a -> bool) -> List['a] -> 'a\n//│ find: ('a -> bool) -> List['a] -> 'a\n\ndef find_opt: ('a -> bool) -> List['a] -> Option['a]\n//│ find_opt: ('a -> bool) -> List['a] -> Option['a]\n\ndef find_index: ('a -> bool) -> List['a] -> Option[int]\n//│ find_index: ('a -> bool) -> List['a] -> Option[int]\n\ndef find_map: ('a -> Option['b]) -> List['a] -> Option['b]\n//│ find_map: ('a -> Option['b]) -> List['a] -> Option['b]\n\ndef find_mapi: (int -> 'a -> Option['b]) -> List['a] -> Option['b]\n//│ find_mapi: (int -> 'a -> Option['b]) -> List['a] -> Option['b]\n\ndef filter: ('a -> bool) -> List['a] -> List['a]\n//│ filter: ('a -> bool) -> List['a] -> List['a]\n\ndef find_all: ('a -> bool) -> List['a] -> List['a]\n//│ find_all: ('a -> bool) -> List['a] -> List['a]\n\ndef filteri: (int -> 'a -> bool) -> List['a] -> List['a]\n//│ filteri: (int -> 'a -> bool) -> List['a] -> List['a]\n\ndef partition: ('a -> bool) -> List['a] -> (List['a], List['a])\n//│ partition: ('a -> bool) -> List['a] -> (List['a], List['a],)\n\ndef partition_map: ('a -> Either['b, 'c]) -> List['a] -> (List['b], List['c])\n//│ partition_map: ('a -> Either['b, 'c]) -> List['a] -> (List['b], List['c],)\n\ndef assoc: 'a -> List[('a, 'b)] -> 'b\n//│ assoc: anything -> List[(anything, 'b,)] -> 'b\n\ndef assoc_opt: 'a -> List[('a, 'b)] -> Option['b]\n//│ assoc_opt: anything -> List[(anything, 'b,)] -> Option['b]\n\ndef assq: 'a -> List[('a, 'b)] -> 'b\n//│ assq: anything -> List[(anything, 'b,)] -> 'b\n\ndef assq_opt: 'a -> List[('a, 'b)] -> Option['b]\n//│ assq_opt: anything -> List[(anything, 'b,)] -> Option['b]\n\ndef mem_assoc: 'a -> List[('a, 'b)] -> bool\n//│ mem_assoc: anything -> List[(anything, anything,)] -> bool\n\ndef mem_assq: 'a -> List[('a, 'b)] -> bool\n//│ mem_assq: anything -> List[(anything, anything,)] -> bool\n\ndef remove_assoc: 'a -> List[('a, 'b)] -> List[('a, 'b)]\n//│ remove_assoc: 'a -> List[('a, 'b,)] -> List[('a, 'b,)]\n\ndef remove_assq: 'a -> List[('a, 'b)] -> List[('a, 'b)]\n//│ remove_assq: 'a -> List[('a, 'b,)] -> List[('a, 'b,)]\n\ndef split: List[('a, 'b)] -> (List['a], List['b])\n//│ split: List[('a, 'b,)] -> (List['a], List['b],)\n\ndef combine: List['a] -> List['b] -> List[('a, 'b)]\n//│ combine: List['a] -> List['b] -> List[('a, 'b,)]\n\ndef sort: ('a -> 'a -> int) -> List['a] -> List['a]\n//│ sort: ('a -> 'a -> int) -> List['a] -> List['a]\n\ndef stable_sort: ('a -> 'a -> int) -> List['a] -> List['a]\n//│ stable_sort: ('a -> 'a -> int) -> List['a] -> List['a]\n\ndef fast_sort: ('a -> 'a -> int) -> List['a] -> List['a]\n//│ fast_sort: ('a -> 'a -> int) -> List['a] -> List['a]\n\ndef sort_uniq: ('a -> 'a -> int) -> List['a] -> List['a]\n//│ sort_uniq: ('a -> 'a -> int) -> List['a] -> List['a]\n\ndef merge: ('a -> 'a -> int) -> List['a] -> List['a] -> List['a]\n//│ merge: ('a -> 'a -> int) -> List['a] -> List['a] -> List['a]\n\ndef to_seq: List['a] -> Seq['a]\n//│ to_seq: List['a] -> Seq['a]\n\ndef of_seq: Seq['a] -> List['a]\n//│ of_seq: Seq['a] -> List['a]\n\n\n\n// *** Implementations ported from List.ml ***\n\n\nrec def length_aux len = fun x -> match x with\n  | Nil -> len\n  | Cons(_, l) -> length_aux (len + 1) l\n//│ length_aux: int -> List[?] -> int\n\ndef length l = length_aux 0 l\n//│ List[?] -> int\n//│   <:  length:\n//│ List[?] -> int\n\ndef cons a l = Cons(a, l)\n//│ 'a -> List['a] -> List['a]\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n\ndef hd = fun x -> match x with\n  | Nil -> failwith \"hd\"\n  | Cons(a, _) -> a\n//│ List['a] -> 'a\n//│   <:  hd:\n//│ List['a] -> 'a\n\ndef tl = fun x -> match x with\n  | Nil -> failwith \"tl\"\n  | Cons(_, l) -> l\n//│ List['A] -> List['A]\n//│   <:  tl:\n//│ List['a] -> List['a]\n\ndef nth l n =\n  if n < 0 then invalid_arg \"List.nth\" else\n  let rec nth_aux l n =\n    match l with\n    | Nil -> failwith \"nth\"\n    | Cons(a, l) -> if n == 0 then a else nth_aux l (n-1)\n  in nth_aux l n\n//│ List['a] -> int -> 'a\n//│   <:  nth:\n//│ List['a] -> int -> 'a\n\ndef nth_opt l n =\n  if n < 0 then invalid_arg \"List.nth\" else\n  let rec nth_aux l n =\n    match l with\n    | Nil -> None\n    | Cons(a, l) -> if n == 0 then Some(a) else nth_aux l (n-1)\n  in nth_aux l n\n//│ List['a] -> int -> Option['a]\n//│   <:  nth_opt:\n//│ List['a] -> int -> Option['a]\n\n// https://github.com/ocaml/ocaml/blob/5312b4d7b913cde2a69fc0eb5e97e353865b82df/stdlib/stdlib.ml#L298\nrec def append l1 l2 =\n  match l1 with\n  | Nil -> l2\n  | Cons(h1, Nil) -> Cons(h1, l2)\n  | Cons(h1, Cons(h2, Nil)) -> Cons(h1, Cons(h2, l2))\n  | Cons(h1, Cons(h2, Cons(h3, tl))) -> Cons(h1, Cons(h2, Cons(h3, append tl l2)))\n//│ List['a] -> List['a] -> List['a]\n//│   <:  append:\n//│ List['a] -> List['a] -> List['a]\n\nrec def rev_append l1 l2 =\n  match l1 with\n    Nil -> l2\n  | Cons(a, l) -> rev_append l (Cons(a, l2))\n//│ List['a] -> List['a] -> List['a]\n//│   <:  rev_append:\n//│ List['a] -> List['a] -> List['a]\n\ndef rev l = rev_append l Nil\n//│ List['a] -> List['a]\n//│   <:  rev:\n//│ List['a] -> List['a]\n\n// overloaded with `init` in OCaml\nrec def init_aux i last f =\n  if i > last then Nil\n  else if i == last then Cons(f i, Nil)\n  else\n    let r1 = f i in\n    let r2 = f (i+1) in\n    Cons(r1, Cons(r2, init_aux (i+2) last f))\n//│ init_aux: int -> number -> (int -> 'a) -> List['a]\n\ndef init len f =\n  if len < 0 then invalid_arg \"List.init\" else\n  init_aux 0 (len - 1) f\n//│ int -> (int -> 'a) -> List['a]\n//│   <:  init:\n//│ int -> (int -> 'a) -> List['a]\n\nrec def flatten = fun x -> match x with\n    Nil -> Nil\n  | Cons(l, r) -> append l (flatten r)\n//│ List[List['a]] -> List['a]\n//│   <:  flatten:\n//│ List[List['a]] -> List['a]\n\ndef concat = flatten\n//│ List[List['a]] -> List['a]\n//│   <:  concat:\n//│ List[List['a]] -> List['a]\n\nrec def map f = fun x -> match x with\n    Nil -> Nil\n  | Cons(a1, Nil) ->\n      let r1 = f a1 in\n      Cons(r1, Nil)\n  | Cons(a1, Cons(a2, l)) ->\n      let r1 = f a1 in\n      let r2 = f a2 in\n      Cons(r1, Cons(r2, map f l))\n//│ ('A -> 'a) -> List['A] -> List['a]\n//│   <:  map:\n//│ ('a -> 'b) -> List['a] -> List['b]\n\n// overloaded with mapi in OCaml\nrec def mapi_aux i f = fun x -> match x with\n    Nil -> Nil\n  | Cons(a1, Nil) ->\n      let r1 = f i a1 in\n      Cons(r1, Nil)\n  | Cons(a1, Cons(a2, l)) ->\n      let r1 = f i a1 in\n      let r2 = f (i+1) a2 in\n      Cons(r1, Cons(r2, mapi_aux (i+2) f l))\n//│ mapi_aux: int -> (int -> 'A -> 'a) -> List['A] -> List['a]\n\ndef mapi f l = mapi_aux 0 f l\n//│ (int -> 'A -> 'a) -> List['A] -> List['a]\n//│   <:  mapi:\n//│ (int -> 'a -> 'b) -> List['a] -> List['b]\n\ndef rev_map f l =\n  let rec rmap_f accu = fun x -> match x with\n    | Nil -> accu\n    | Cons(a, l) -> rmap_f (Cons(f a, accu)) l\n  in\n  rmap_f Nil l\n//│ ('A -> 'a) -> List['A] -> List['a]\n//│   <:  rev_map:\n//│ ('a -> 'b) -> List['a] -> List['b]\n\nrec def iter f = fun x -> match x with\n    Nil -> Unit\n  | Cons(a, l) -> let _ = f a in iter f l\n//│ ('A -> anything) -> List['A] -> unit\n//│   <:  iter:\n//│ ('a -> unit) -> List['a] -> unit\n\n// overloaded with iteri in OCaml\nrec def iteri_aux i f = fun x -> match x with\n    Nil -> Unit\n  | Cons(a, l) -> let _ = f i a in iteri_aux (i + 1) f l\n//│ iteri_aux: int -> (int -> 'A -> anything) -> List['A] -> unit\n\ndef iteri f l = iteri_aux 0 f l\n//│ (int -> 'A -> anything) -> List['A] -> unit\n//│   <:  iteri:\n//│ (int -> 'a -> unit) -> List['a] -> unit\n\nrec def fold_left f accu l =\n  match l with\n    Nil -> accu\n  | Cons(a, l) -> fold_left f (f accu a) l\n//│ ('a -> 'A -> 'a) -> 'a -> List['A] -> 'a\n//│   <:  fold_left:\n//│ ('acc -> 'a -> 'acc) -> 'acc -> List['a] -> 'acc\n\nrec def fold_right f l accu =\n  match l with\n    Nil -> accu\n  | Cons(a, l) -> f a (fold_right f l accu)\n//│ ('A -> 'a -> 'a) -> List['A] -> 'a -> 'a\n//│   <:  fold_right:\n//│ ('a -> 'acc -> 'acc) -> List['a] -> 'acc -> 'acc\n\nrec def map2 f l1 l2 =\n  match (l1, l2) with\n    (Nil, Nil) -> Nil\n  | (Cons(a1, Nil), Cons(b1, Nil)) ->\n      let r1 = f a1 b1 in\n      Cons(r1, Nil)\n  | (Cons(a1, Cons(a2, l1)), Cons(b1, Cons(b2, l2))) ->\n      let r1 = f a1 b1 in\n      let r2 = f a2 b2 in\n      Cons(r1, Cons(r2, map2 f l1 l2))\n  | (_, _) -> invalid_arg \"List.map2\"\n//│ ('A -> 'A0 -> 'a) -> List['A] -> List['A0] -> List['a]\n//│   <:  map2:\n//│ ('a -> 'b -> 'c) -> List['a] -> List['b] -> List['c]\n\ndef rev_map2 f l1 l2 =\n  let rec rmap2_f accu l1 l2 =\n    match (l1, l2) with\n    | (Nil, Nil) -> accu\n    | (Cons(a1, l1), Cons(a2, l2)) -> rmap2_f (Cons(f a1 a2, accu)) l1 l2\n    | (_, _) -> invalid_arg \"List.rev_map2\"\n  in\n  rmap2_f Nil l1 l2\n//│ ('A -> 'A0 -> 'a) -> List['A] -> List['A0] -> List['a]\n//│   <:  rev_map2:\n//│ ('a -> 'b -> 'c) -> List['a] -> List['b] -> List['c]\n\nrec def iter2 f l1 l2 =\n  match (l1, l2) with\n    (Nil, Nil) -> Unit\n  | (Cons(a1, l1), Cons(a2, l2)) -> let _ = f a1 a2 in iter2 f l1 l2\n  | (_, _) -> invalid_arg \"List.iter2\"\n//│ ('A -> 'A0 -> anything) -> List['A] -> List['A0] -> unit\n//│   <:  iter2:\n//│ ('a -> 'b -> unit) -> List['a] -> List['b] -> unit\n\nrec def fold_left2 f accu l1 l2 =\n  match (l1, l2) with\n    (Nil, Nil) -> accu\n  | (Cons(a1, l1), Cons(a2, l2)) -> fold_left2 f (f accu a1 a2) l1 l2\n  | (_, _) -> invalid_arg \"List.fold_left2\"\n//│ ('a -> 'A -> 'A0 -> 'a) -> 'a -> List['A] -> List['A0] -> 'a\n//│   <:  fold_left2:\n//│ ('acc -> 'a -> 'b -> 'acc) -> 'acc -> List['a] -> List['b] -> 'acc\n\nrec def fold_right2 f l1 l2 accu =\n  match (l1, l2) with\n    (Nil, Nil) -> accu\n  | (Cons(a1, l1), Cons(a2, l2)) -> f a1 a2 (fold_right2 f l1 l2 accu)\n  | (_, _) -> invalid_arg \"List.fold_right2\"\n//│ ('A -> 'A0 -> 'a -> 'a) -> List['A] -> List['A0] -> 'a -> 'a\n//│   <:  fold_right2:\n//│ ('a -> 'b -> 'acc -> 'acc) -> List['a] -> List['b] -> 'acc -> 'acc\n\nrec def for_all p = fun x -> match x with\n    Nil -> true\n  | Cons(a, l) -> p a && for_all p l\n//│ ('A -> bool) -> List['A] -> bool\n//│   <:  for_all:\n//│ ('a -> bool) -> List['a] -> bool\n\nrec def exists p = fun x -> match x with\n    Nil -> false\n  | Cons(a, l) -> p a || exists p l\n//│ ('A -> bool) -> List['A] -> bool\n//│   <:  exists:\n//│ ('a -> bool) -> List['a] -> bool\n\nrec def for_all2 p l1 l2 =\n  match (l1, l2) with\n    (Nil, Nil) -> true\n  | (Cons(a1, l1), Cons(a2, l2)) -> p a1 a2 && for_all2 p l1 l2\n  | (_, _) -> invalid_arg \"List.for_all2\"\n//│ ('A -> 'A0 -> bool) -> List['A] -> List['A0] -> bool\n//│   <:  for_all2:\n//│ ('a -> 'b -> bool) -> List['a] -> List['b] -> bool\n\nrec def exists2 p l1 l2 =\n  match (l1, l2) with\n    (Nil, Nil) -> false\n  | (Cons(a1, l1), Cons(a2, l2)) -> p a1 a2 || exists2 p l1 l2\n  | (_, _) -> invalid_arg \"List.exists2\"\n//│ ('A -> 'A0 -> bool) -> List['A] -> List['A0] -> bool\n//│   <:  exists2:\n//│ ('a -> 'b -> bool) -> List['a] -> List['b] -> bool\n\nrec def mem x = fun y -> match y with\n    Nil -> false\n  | Cons(a, l) -> compare' a x == 0 || mem x l\n//│ anything -> List[?] -> bool\n//│   <:  mem:\n//│ anything -> List[?] -> bool\n\nrec def memq x = fun y -> match y with\n    Nil -> false\n  | Cons(a, l) -> eq a x || memq x l\n//│ anything -> List[?] -> bool\n//│   <:  memq:\n//│ anything -> List[?] -> bool\n\nrec def assoc x = fun y -> match y with\n    Nil -> raise Not_found\n  | Cons((a, b), l) -> if compare' a x == 0 then b else assoc x l\n//│ anything -> List[(anything, 'a,)] -> 'a\n//│   <:  assoc:\n//│ anything -> List[(anything, 'b,)] -> 'b\n\nrec def assoc_opt x = fun y -> match y with\n    Nil -> None\n  | Cons((a, b), l) -> if compare' a x == 0 then Some(b) else assoc_opt x l\n//│ anything -> List[(anything, 'a,)] -> Option['a]\n//│   <:  assoc_opt:\n//│ anything -> List[(anything, 'b,)] -> Option['b]\n\nrec def assq x = fun y -> match y with\n    Nil -> raise Not_found\n  | Cons((a, b), l) -> if eq a x then b else assq x l\n//│ anything -> List[(anything, 'a,)] -> 'a\n//│   <:  assq:\n//│ anything -> List[(anything, 'b,)] -> 'b\n\nrec def assq_opt x = fun y -> match y with\n    Nil -> None\n  | Cons((a, b), l) -> if eq a x then Some(b) else assq_opt x l\n//│ anything -> List[(anything, 'a,)] -> Option['a]\n//│   <:  assq_opt:\n//│ anything -> List[(anything, 'b,)] -> Option['b]\n\nrec def mem_assoc x = fun y -> match y with\n  | Nil -> false\n  | Cons((a, _), l) -> compare' a x == 0 || mem_assoc x l\n//│ anything -> List[(anything, anything,)] -> bool\n//│   <:  mem_assoc:\n//│ anything -> List[(anything, anything,)] -> bool\n\nrec def mem_assq x = fun y -> match y with\n  | Nil -> false\n  | Cons((a, _), l) -> eq a x || mem_assq x l\n//│ anything -> List[(anything, anything,)] -> bool\n//│   <:  mem_assq:\n//│ anything -> List[(anything, anything,)] -> bool\n\nrec def remove_assoc x = fun y -> match y with\n  | Nil -> Nil\n  | Cons((a, _) as pair, l) ->\n      if compare' a x == 0 then l else Cons(pair, remove_assoc x l)\n//│ anything -> List[(anything, anything,) & 'A] -> List['A]\n//│   <:  remove_assoc:\n//│ 'a -> List[('a, 'b,)] -> List[('a, 'b,)]\n\nrec def remove_assq x = fun y -> match y with\n  | Nil -> Nil\n  | Cons((a, _) as pair, l) ->\n      if eq a x then l else Cons(pair, remove_assq x l)\n//│ anything -> List[(anything, anything,) & 'A] -> List['A]\n//│   <:  remove_assq:\n//│ 'a -> List[('a, 'b,)] -> List[('a, 'b,)]\n\nrec def find p = fun x -> match x with\n  | Nil -> raise Not_found\n  | Cons(x, l) -> if p x then x else find p l\n//│ ('A -> bool) -> List['A] -> 'A\n//│   <:  find:\n//│ ('a -> bool) -> List['a] -> 'a\n\nrec def find_opt p = fun x -> match x with\n  | Nil -> None\n  | Cons(x, l) -> if p x then Some(x) else find_opt p l\n//│ ('A -> bool) -> List['A] -> Option['A]\n//│   <:  find_opt:\n//│ ('a -> bool) -> List['a] -> Option['a]\n\ndef find_index p =\n  let rec aux i = fun x -> match x with\n    Nil -> None\n    | Cons(a, l) -> if p a then Some(i) else aux (i+1) l in\n  aux 0\n//│ ('A -> bool) -> List['A] -> Option[int]\n//│   <:  find_index:\n//│ ('a -> bool) -> List['a] -> Option[int]\n\nrec def find_map f = fun x -> match x with\n  | Nil -> None\n  | Cons(x, l) ->\n      match f x with\n        | Some(_) as result -> result\n        | None -> find_map f l\n//│ ('A -> (Option[?] & 'a)) -> List['A] -> (Option[nothing] | 'a)\n//│   <:  find_map:\n//│ ('a -> Option['b]) -> List['a] -> Option['b]\n\ndef find_mapi f =\n  let rec aux i = fun x -> match x with\n  | Nil -> None\n  | Cons(x, l) ->\n      match f i x with\n        | Some(_) as result -> result\n        | None -> aux (i+1) l\n      in\n  aux 0\n//│ (int -> 'A -> (Option[?] & 'a)) -> List['A] -> (Option[nothing] | 'a)\n//│   <:  find_mapi:\n//│ (int -> 'a -> Option['b]) -> List['a] -> Option['b]\n\nrec def find_all p = fun x -> match x with\n  | Nil -> Nil\n  | Cons(x, l) -> if p x then Cons(x, find_all p l) else find_all p l\n//│ ('A -> bool) -> List['A] -> List['A]\n//│   <:  find_all:\n//│ ('a -> bool) -> List['a] -> List['a]\n\ndef filter = find_all\n//│ ('a -> bool) -> List['a] -> List['a]\n//│   <:  filter:\n//│ ('a -> bool) -> List['a] -> List['a]\n\n// overloaded with filter in OCaml\nrec def filteri_aux p i = fun x -> match x with\n  | Nil -> Nil\n  | Cons(x, l) ->\n      let i' = i + 1 in\n      if p i x then Cons(x, filteri_aux p i' l) else filteri_aux p i' l\n//│ filteri_aux: (int -> 'A -> bool) -> int -> List['A] -> List['A]\n\ndef filteri p l = filteri_aux p 0 l\n//│ (int -> 'A -> bool) -> List['A] -> List['A]\n//│   <:  filteri:\n//│ (int -> 'a -> bool) -> List['a] -> List['a]\n\nrec def filter_map f = fun x -> match x with\n  | Nil -> Nil\n  | Cons(x, l) ->\n      match f x with\n      | None -> filter_map f l\n      | Some(v) -> Cons(v, filter_map f l)\n//│ ('A -> Option['a]) -> List['A] -> List['a]\n//│   <:  filter_map:\n//│ ('a -> Option['b]) -> List['a] -> List['b]\n\ndef concat_map = let rec r = {\n    concat_map = fun f -> fun x -> match x with\n      | Nil -> Nil\n      | Cons(x, xs) -> r.prepend_concat_map (f x) f xs,\n    prepend_concat_map = fun ys -> fun f -> fun xs ->\n      match ys with\n      | Nil -> r.concat_map f xs\n      | Cons(y, ys) -> r.prepend_concat_map ys f xs\n  } in r.concat_map\n//│ ('A -> List[?]) -> List['A] -> (List[nothing] | 'a)\n//│   <:  concat_map:\n//│ ('a -> List['b]) -> List['a] -> List['b]\n\ndef fold_left_map f accu l =\n  let rec aux accu l_accu = fun x -> match x with\n    | Nil -> (accu, rev l_accu)\n    | Cons(x, l) -> \n        match f accu x with (accu, x) ->\n        aux accu (Cons(x, l_accu)) l in\n  aux accu Nil l\n//│ ('a -> 'A -> ('a, 'b,)) -> 'a -> List['A] -> ('a, List['b],)\n//│   <:  fold_left_map:\n//│ ('acc -> 'a -> ('acc, 'b,)) -> 'acc -> List['a] -> ('acc, List['b],)\n\ndef partition p l =\n  let rec part yes no = fun x -> match x with\n  | Nil -> (rev yes, rev no)\n  | Cons(x, l) -> if p x then part (Cons(x, yes)) no l else part yes (Cons(x, no)) l in\n  part Nil Nil l\n//│ ('A -> bool) -> List['A] -> (List['A], List['A],)\n//│   <:  partition:\n//│ ('a -> bool) -> List['a] -> (List['a], List['a],)\n\ndef partition_map p l =\n  let rec part left right = fun x -> match x with\n  | Nil -> (rev left, rev right)\n  | Cons(x, l) ->\n      match p x with\n        | Left(v) -> part (Cons(v, left)) right l\n        | Right(v) -> part left (Cons(v, right)) l\n  in\n  part Nil Nil l\n//│ ('A -> Either['A0, 'B]) -> List['A] -> (List['A0], List['B],)\n//│   <:  partition_map:\n//│ ('a -> Either['b, 'c]) -> List['a] -> (List['b], List['c],)\n\nrec def split = fun x -> match x with\n    Nil -> (Nil, Nil)\n  | Cons((x, y), l) ->\n      match split l with (rx, ry) -> (Cons(x, rx), Cons(y, ry))\n//│ List[('a, 'b,)] -> (List['a], List['b],)\n//│   <:  split:\n//│ List[('a, 'b,)] -> (List['a], List['b],)\n\nrec def combine l1 l2 =\n  match (l1, l2) with\n    (Nil, Nil) -> Nil\n  | (Cons(a1, l1), Cons(a2, l2)) -> Cons((a1, a2), combine l1 l2)\n  | (_, _) -> invalid_arg \"List.combine\"\n//│ List['A] -> List['A0] -> List[('A, 'A0,)]\n//│   <:  combine:\n//│ List['a] -> List['b] -> List[('a, 'b,)]\n\nrec def merge cmp l1 l2 =\n  match (l1, l2) with\n  | (Nil, l2) -> l2\n  | (l1, Nil) -> l1\n  | (Cons(h1, t1), Cons(h2, t2)) ->\n      if cmp h1 h2 <= 0\n      then Cons(h1, merge cmp t1 l2)\n      else Cons(h2, merge cmp l1 t2)\n//│ ('A -> 'A0 -> number) -> List['A & 'a] -> List['A0 & 'a] -> List['a | 'A0 | 'A]\n//│   <:  merge:\n//│ ('a -> 'a -> int) -> List['a] -> List['a] -> List['a]\n\ndef stable_sort cmp l =\n  let rec rev_merge l1 l2 accu =\n    match (l1, l2) with\n    | (Nil, l2) -> rev_append l2 accu\n    | (l1, Nil) -> rev_append l1 accu\n    | (Cons(h1, t1), Cons(h2, t2)) ->\n        if cmp h1 h2 <= 0\n        then rev_merge t1 l2 (Cons(h1, accu))\n        else rev_merge l1 t2 (Cons(h2, accu))\n  in\n  let rec rev_merge_rev l1 l2 accu =\n    match (l1, l2) with\n    | (Nil, l2) -> rev_append l2 accu\n    | (l1, Nil) -> rev_append l1 accu\n    | (Cons(h1, t1), Cons(h2, t2)) ->\n        if cmp h1 h2 > 0\n        then rev_merge_rev t1 l2 (Cons(h1, accu))\n        else rev_merge_rev l1 t2 (Cons(h2, accu))\n  in\n  let rec r = {\n  sort = fun n -> fun l ->\n    match (n, l) with\n    | (2, Cons(x1, Cons(x2, tl))) ->\n        let s = if cmp x1 x2 <= 0 then Cons(x1, Cons(x2, Nil)) else Cons(x2, Cons(x1, Nil)) in\n        (s, tl)\n    | (3, Cons(x1, Cons(x2, Cons(x3, tl)))) ->\n        let s =\n          if cmp x1 x2 <= 0 then\n            if cmp x2 x3 <= 0 then Cons(x1, Cons(x2, Cons(x3, Nil)))\n            else if cmp x1 x3 <= 0 then Cons(x1, Cons(x3, Cons(x2, Nil)))\n            else Cons(x3, Cons(x1, Cons(x2, Nil)))\n          else if cmp x1 x3 <= 0 then Cons(x2, Cons(x1, Cons(x3, Nil)))\n          else if cmp x2 x3 <= 0 then Cons(x2, Cons(x3, Cons(x1, Nil)))\n          else Cons(x3, Cons(x2, Cons(x1, Nil)))\n        in\n        (s, tl)\n    | (n, l) ->\n      let n1 = asr n 1 in\n      let n2 = n - n1 in\n      match r.rev_sort n1 l with (s1, l2) ->\n      match r.rev_sort n2 l2 with (s2, tl) ->\n      (rev_merge_rev s1 s2 Nil, tl),\n  rev_sort = fun n -> fun l ->\n    match (n, l) with\n    | (2, Cons(x1, Cons(x2, tl))) ->\n        let s = if cmp x1 x2 > 0 then Cons(x1, Cons(x2, Nil)) else Cons(x2, Cons(x1, Nil)) in\n        (s, tl)\n    | (3, Cons(x1, Cons(x2, Cons(x3, tl)))) ->\n        let s =\n          if cmp x1 x2 > 0 then\n            if cmp x2 x3 > 0 then Cons(x1, Cons(x2, Cons(x3, Nil)))\n            else if cmp x1 x3 > 0 then Cons(x1, Cons(x3, Cons(x2, Nil)))\n            else Cons(x3, Cons(x1, Cons(x2, Nil)))\n          else if cmp x1 x3 > 0 then Cons(x2, Cons(x1, Cons(x3, Nil)))\n          else if cmp x2 x3 > 0 then Cons(x2, Cons(x3, Cons(x1, Nil)))\n          else Cons(x3, Cons(x2, Cons(x1, Nil)))\n        in\n        (s, tl)\n    | (n, l) ->\n      let n1 = asr n 1 in\n      let n2 = n - n1 in\n      match r.sort n1 l with (s1, l2) ->\n      match r.sort n2 l2 with (s2, tl) ->\n      (rev_merge s1 s2 Nil, tl)\n  }\n  in let sort = r.sort\n  in let rev_sort = r.rev_sort\n  in\n  let len = length l in\n  if len < 2 then l else fst (sort len l)\n//│ ('A -> 'A -> number) -> (List['A & 'A0] & 'a & List['A & 'A1]) -> (List['A0 | 'A1] | 'a)\n//│   <:  stable_sort:\n//│ ('a -> 'a -> int) -> List['a] -> List['a]\n\ndef sort = stable_sort\ndef fast_sort = stable_sort\n//│ ('a -> 'a -> int) -> List['a] -> List['a]\n//│   <:  sort:\n//│ ('a -> 'a -> int) -> List['a] -> List['a]\n//│ ('a -> 'a -> int) -> List['a] -> List['a]\n//│   <:  fast_sort:\n//│ ('a -> 'a -> int) -> List['a] -> List['a]\n\ndef sort_uniq cmp l =\n  let rec rev_merge l1 l2 accu =\n    match (l1, l2) with\n    | (Nil, l2) -> rev_append l2 accu\n    | (l1, Nil) -> rev_append l1 accu\n    | (Cons(h1, t1), Cons(h2, t2)) ->\n        let c = cmp h1 h2 in\n        if c == 0 then rev_merge t1 t2 (Cons(h1, accu))\n        else if c < 0\n        then rev_merge t1 l2 (Cons(h1, accu))\n        else rev_merge l1 t2 (Cons(h2, accu))\n  in\n  let rec rev_merge_rev l1 l2 accu =\n    match (l1, l2) with\n    | (Nil, l2) -> rev_append l2 accu\n    | (l1, Nil) -> rev_append l1 accu\n    | (Cons(h1, t1), Cons(h2, t2)) ->\n        let c = cmp h1 h2 in\n        if c == 0 then rev_merge_rev t1 t2 (Cons(h1, accu))\n        else if c > 0\n        then rev_merge_rev t1 l2 (Cons(h1, accu))\n        else rev_merge_rev l1 t2 (Cons(h2, accu))\n  in\n  let rec r = {\n  sort = fun n -> fun l ->\n    match (n, l) with\n    | (2, Cons(x1, Cons(x2, tl))) ->\n        let s =\n          let c = cmp x1 x2 in\n          if c == 0 then Cons(x1, Nil) else if c < 0 then Cons(x1, Cons(x2, Nil)) else Cons(x2, Cons(x1, Nil)) in\n        (s, tl)\n    | (3, Cons(x1, Cons(x2, Cons(x3, tl)))) ->\n        let s =\n          let c = cmp x1 x2 in\n          if c == 0 then\n            let c = cmp x2 x3 in\n            if c == 0 then Cons(x2, Nil) else if c < 0 then Cons(x2, Cons(x3, Nil)) else Cons(x3, Cons(x2, Nil))\n          else if c < 0 then\n            let c = cmp x2 x3 in\n            if c == 0 then Cons(x1, Cons(x2, Nil))\n            else if c < 0 then Cons(x1, Cons(x2, Cons(x3, Nil)))\n            else\n              let c = cmp x1 x3 in\n              if c == 0 then Cons(x1, Cons(x2, Nil))\n              else if c < 0 then Cons(x1, Cons(x3, Cons(x2, Nil)))\n              else Cons(x3, Cons(x1, Cons(x2, Nil)))\n          else\n            let c = cmp x1 x3 in\n            if c == 0 then Cons(x2, Cons(x1, Nil))\n            else if c < 0 then Cons(x2, Cons(x1, Cons(x3, Nil)))\n            else\n              let c = cmp x2 x3 in\n              if c == 0 then Cons(x2, Cons(x1, Nil))\n              else if c < 0 then Cons(x2, Cons(x3, Cons(x1, Nil)))\n              else Cons(x3, Cons(x2, Cons(x1, Nil)))\n        in\n        (s, tl)\n    | (n, l) ->\n      let n1 = asr n 1 in\n      let n2 = n - n1 in\n      match r.rev_sort n1 l with (s1, l2) ->\n      match r.rev_sort n2 l2 with (s2, tl) ->\n      (rev_merge_rev s1 s2 Nil, tl),\n  rev_sort = fun n -> fun l ->\n    match (n, l) with\n    | (2, Cons(x1, Cons(x2, tl))) ->\n        let s =\n          let c = cmp x1 x2 in\n          if c == 0 then Cons(x1, Nil) else if c > 0 then Cons(x1, Cons(x2, Nil)) else Cons(x2, Cons(x1, Nil)) in\n        (s, tl)\n    | (3, Cons(x1, Cons(x2, Cons(x3, tl)))) ->\n        let s =\n          let c = cmp x1 x2 in\n          if c == 0 then\n            let c = cmp x2 x3 in\n            if c == 0 then Cons(x2, Nil) else if c > 0 then Cons(x2, Cons(x3, Nil)) else Cons(x3, Cons(x2, Nil))\n          else if c > 0 then\n            let c = cmp x2 x3 in\n            if c == 0 then Cons(x1, Cons(x2, Nil))\n            else if c > 0 then Cons(x1, Cons(x2, Cons(x3, Nil)))\n            else\n              let c = cmp x1 x3 in\n              if c == 0 then Cons(x1, Cons(x2, Nil))\n              else if c > 0 then Cons(x1, Cons(x3, Cons(x2, Nil)))\n              else Cons(x3, Cons(x1, Cons(x2, Nil)))\n          else\n            let c = cmp x1 x3 in\n            if c == 0 then Cons(x2, Cons(x1, Nil))\n            else if c > 0 then Cons(x2, Cons(x1, Cons(x3, Nil)))\n            else\n              let c = cmp x2 x3 in\n              if c == 0 then Cons(x2, Cons(x1, Nil))\n              else if c > 0 then Cons(x2, Cons(x3, Cons(x1, Nil)))\n              else Cons(x3, Cons(x2, Cons(x1, Nil)))\n        in\n        (s, tl)\n    | (n, l) ->\n      let n1 = asr n 1 in\n      let n2 = n - n1 in\n      match r.sort n1 l with (s1, l2) ->\n      match r.sort n2 l2 with (s2, tl) ->\n      (rev_merge s1 s2 Nil, tl)\n  }\n  in let sort = r.sort\n  in let rev_sort = r.rev_sort\n  in\n  let len = length l in\n  if len < 2 then l else fst (sort len l)\n//│ ('A -> 'A -> number) -> (List['A & 'A0] & 'a & List['A & 'A1]) -> (List['A0 | 'A1] | 'a)\n//│   <:  sort_uniq:\n//│ ('a -> 'a -> int) -> List['a] -> List['a]\n\nrec def compare_lengths l1 l2 =\n  match (l1, l2) with\n  | (Nil, Nil) -> 0\n  | (Nil, _) -> negate 1\n  | (_, Nil) -> 1\n  | (Cons(_, l1), Cons(_, l2)) -> compare_lengths l1 l2\n//│ List[?] -> List[?] -> int\n//│   <:  compare_lengths:\n//│ List[?] -> List[?] -> int\n\nrec def compare_length_with l n =\n  match l with\n  | Nil ->\n    if n == 0 then 0 else\n      if n > 0 then negate 1 else 1\n  | Cons(_, l) ->\n    if n <= 0 then 1 else\n      compare_length_with l (n-1)\n//│ List[?] -> int -> int\n//│   <:  compare_length_with:\n//│ List[?] -> int -> int\n\ndef is_empty = fun x -> match x with\n  | Nil -> true\n  | Cons(_, _) -> false\n//│ List[?] -> Bool\n//│   <:  is_empty:\n//│ List[?] -> bool\n\nrec def equal eq l1 l2 =\n  match (l1, l2) with\n  | (Nil, Nil) -> true\n  | (Nil, Cons(_, _)) -> false\n  | (Cons(_, _), Nil) -> false\n  | (Cons(a1, l1), Cons(a2, l2)) -> eq a1 a2 && equal eq l1 l2\n//│ ('A -> 'A0 -> bool) -> List['A] -> List['A0] -> (bool | false)\n//│   <:  equal:\n//│ ('a -> 'a -> bool) -> List['a] -> List['a] -> bool\n\nrec def compare cmp l1 l2 =\n  match (l1, l2) with\n  | (Nil, Nil) -> 0\n  | (Nil, Cons(_, _)) -> negate 1\n  | (Cons(_, _), Nil) -> 1\n  | (Cons(a1, l1), Cons(a2, l2)) ->\n    let c = cmp a1 a2 in\n    if c <> 0 then c\n    else compare cmp l1 l2\n//│ ('A -> 'A0 -> (number & 'a)) -> List['A] -> List['A0] -> (int | 'a)\n//│   <:  compare:\n//│ ('a -> 'a -> int) -> List['a] -> List['a] -> int\n\ndef to_seq l =\n  let rec aux l Unit = match l with\n    | Nil -> SeqNil\n    | Cons(x, tail) -> SeqCons(x, aux tail)\n  in\n  aux l\n//│ List['a] -> unit -> Node['a]\n//│   <:  to_seq:\n//│ List['a] -> Seq['a]\n\nrec def of_seq seq =\n  match seq Unit with\n  | SeqNil -> Nil\n  | SeqCons(x1, seq) ->\n      match seq Unit with\n      | SeqNil -> Cons(x1, Nil)\n      | SeqCons(x2, seq) -> Cons(x1, Cons(x2, of_seq seq))\n//│ (unit -> Node['A]) -> List['A]\n//│   <:  of_seq:\n//│ Seq['a] -> List['a]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/OverloadSimplif.mls",
    "content": ":NoJS\n\n\ndef foo f x =\n  if true then f x\n  else f (id x)\n//│ foo: ('a -> 'b) -> 'a -> 'b\n\ndef foo k f x =\n  if true then f x\n  else f (k x)\n//│ foo: ('a -> 'b) -> (('a | 'b) -> 'c) -> 'a -> 'c\n\n// * Not ethe simplified type, similar to the one above, as expected\nfoo id\n//│ res: ('a -> 'b) -> 'a -> 'b\n\n\ndef f: ('a -> 'b & 'c -> 'b & 'a -> 'c) -> 'a -> 'b\n//│ f: (('a | 'c) -> 'b & 'a -> 'c) -> 'a -> 'b\n\ndef f: int -> int & nothing -> string\n//│ f: int -> int\n\ndef f: int -> int & string -> anything\n//│ f: int -> int & string -> anything\n\ndef f: int -> int & 1 -> number\n//│ f: int -> int\n\ndef f: int -> int & 'a -> 'a\n//│ f: int -> int & 'a -> 'a\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Overloads.mls",
    "content": "\n:NoJS\n\n\ntype IISS = int -> int & string -> string\ntype BBNN = bool -> bool & number -> number\ntype ZZII = 0 -> 0 & int -> int\n//│ Defined type alias IISS\n//│ Defined type alias BBNN\n//│ Defined type alias ZZII\n\ndef IISS: int -> int & string -> string\ndef BBNN: bool -> bool & number -> number\ndef ZZII: 0 -> 0 & int -> int\n//│ IISS: int -> int & string -> string\n//│ BBNN: bool -> bool & number -> number\n//│ ZZII: 0 -> 0 & int -> int\n\n\nIISS : IISS\n//│ res: IISS\n\nIISS : int -> int & string -> string\n//│ res: int -> int & string -> string\n\nIISS : IISS | BBNN\n//│ res: BBNN | IISS\n\n:e\nIISS : ZZII\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.30: \tIISS : ZZII\n//│ ║        \t^^^^\n//│ ╟── type `int` does not match type `0`\n//│ ║  l.12: \tdef IISS: int -> int & string -> string\n//│ ║        \t                 ^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.7: \ttype ZZII = 0 -> 0 & int -> int\n//│ ╙──     \t                 ^\n//│ res: ZZII\n\n:e\nIISS : BBNN\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.43: \tIISS : BBNN\n//│ ║        \t^^^^\n//│ ╟── type `bool` does not match type `int | string`\n//│ ║  l.6: \ttype BBNN = bool -> bool & number -> number\n//│ ╙──     \t            ^^^^\n//│ res: BBNN\n\n\n// * These tests show that we currently throw away information when constraining LHS overloading sets:\n\nIISS : int -> int\n//│ res: int -> int\n\nIISS : (0 | 1) -> number\n//│ res: (0 | 1) -> number\n\nIISS : 'a -> 'a\n//│ res: ('a & (int | string)) -> (int | string | 'a)\n\nIISS 0\n//│ res: int | string\n\n(IISS : int -> int) 0\n//│ res: int\n\n(if true then IISS else BBNN) 0\n//│ res: bool | number | string\n\ndef f = fun x -> (if true then IISS else BBNN) x\n//│ f: int -> (bool | number | string)\n\nf(0)\n//│ res: bool | number | string\n\n:e\nf(0) + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.80: \tf(0) + 1\n//│ ║        \t^^^^^^\n//│ ╟── type `bool` is not an instance of type `int`\n//│ ║  l.13: \tdef BBNN: bool -> bool & number -> number\n//│ ║        \t                  ^^^^\n//│ ╟── but it flows into application with expected type `int`\n//│ ║  l.80: \tf(0) + 1\n//│ ╙──      \t^^^^\n//│ res: error | int\n\n:e\nf : int -> number\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.93: \tf : int -> number\n//│ ║        \t^\n//│ ╟── type `bool` is not an instance of type `number`\n//│ ║  l.13: \tdef BBNN: bool -> bool & number -> number\n//│ ║        \t                  ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.93: \tf : int -> number\n//│ ╙──      \t           ^^^^^^\n//│ res: int -> number\n\n:e\nf : number -> int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.106: \tf : number -> int\n//│ ║         \t^\n//│ ╟── type `number` does not match type `int | string`\n//│ ║  l.106: \tf : number -> int\n//│ ║         \t    ^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.73: \tdef f = fun x -> (if true then IISS else BBNN) x\n//│ ╙──      \t                                               ^\n//│ res: number -> int\n\n\nif true then IISS else BBNN\n//│ res: bool -> bool & number -> number | int -> int & string -> string\n\n(if true then IISS else ZZII) : int -> int\n//│ res: int -> int\n\n(if true then IISS else BBNN) : (0 | 1) -> number\n//│ res: (0 | 1) -> number\n\n:e\n(if true then IISS else BBNN) : (0 | 1 | true) -> number\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.129: \t(if true then IISS else BBNN) : (0 | 1 | true) -> number\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `true` does not match type `int | string`\n//│ ║  l.129: \t(if true then IISS else BBNN) : (0 | 1 | true) -> number\n//│ ╙──       \t                                         ^^^^\n//│ res: (0 | 1 | true) -> number\n\n\n// * Note that type normalization used to be very aggressive at approximating non-tag type negations,\n// * to simplify the result, but this was changed as it was unsound\n\ndef test: ~(int -> int)\n//│ test: ~(int -> int)\n\n// * See also test file BooleanFail.mls about this previous unsoundness\n:e\ntest = 42\nnot test\n//│ 42\n//│   <:  test:\n//│ ~(int -> int)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.148: \tnot test\n//│ ║         \t^^^^^^^^\n//│ ╟── type `~(int -> int)` is not an instance of type `bool`\n//│ ║  l.142: \tdef test: ~(int -> int)\n//│ ║         \t          ^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `bool`\n//│ ║  l.148: \tnot test\n//│ ╙──       \t    ^^^^\n//│ res: bool | error\n\ndef test: ~(int -> int) & ~bool\n//│ test: ~bool & ~(int -> int)\n\ndef test: ~(int -> int) & bool\n//│ test: bool\n\ndef test: ~(int -> int) & ~(bool -> bool)\n//│ test: ~(nothing -> (bool | int))\n\ndef test: ~(int -> int | bool -> bool)\n//│ test: ~(nothing -> (bool | int))\n\ndef test: ~(int -> int & string -> string) & ~(bool -> bool & number -> number)\n//│ test: in ~(nothing -> (number | string) & int -> number & nothing -> (bool | string) & nothing -> (bool | int)) out ~(nothing -> (bool | int) & nothing -> (bool | string) & int -> number & nothing -> (number | string))\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Overloads_Precise.mls",
    "content": "\n:NoJS\n:NoApproximateOverload\n\ntype IISS = int -> int & string -> string\ntype BBNN = bool -> bool & number -> number\ntype ZZII = 0 -> 0 & int -> int\n//│ Defined type alias IISS\n//│ Defined type alias BBNN\n//│ Defined type alias ZZII\n\ndef IISS: int -> int & string -> string\ndef BBNN: bool -> bool & number -> number\ndef ZZII: 0 -> 0 & int -> int\n//│ IISS: int -> int & string -> string\n//│ BBNN: bool -> bool & number -> number\n//│ ZZII: 0 -> 0 & int -> int\n\n\nIISS : IISS\n//│ res: IISS\n\nIISS : int -> int & string -> string\n//│ res: int -> int & string -> string\n\nIISS : IISS | BBNN\n//│ res: BBNN | IISS\n\n:e\nIISS : ZZII\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.30: \tIISS : ZZII\n//│ ║        \t^^^^\n//│ ╟── type `int -> int & string -> string` is not an instance of `0 -> 0`\n//│ ║  l.12: \tdef IISS: int -> int & string -> string\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `0 -> 0`\n//│ ║  l.30: \tIISS : ZZII\n//│ ║        \t^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.7: \ttype ZZII = 0 -> 0 & int -> int\n//│ ║       \t            ^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.30: \tIISS : ZZII\n//│ ╙──      \t       ^^^^\n//│ res: ZZII\n\n:e\nIISS : BBNN\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.49: \tIISS : BBNN\n//│ ║        \t^^^^\n//│ ╟── type `int -> int & string -> string` is not an instance of `bool -> bool`\n//│ ║  l.12: \tdef IISS: int -> int & string -> string\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `bool -> bool`\n//│ ║  l.49: \tIISS : BBNN\n//│ ║        \t^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.6: \ttype BBNN = bool -> bool & number -> number\n//│ ║       \t            ^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.49: \tIISS : BBNN\n//│ ╙──      \t       ^^^^\n//│ res: BBNN\n\n\n// * These tests show that we currently throw away information when constraining LHS overloading sets:\n\nIISS : int -> int\n//│ res: int -> int\n\nIISS : (0 | 1) -> number\n//│ res: (0 | 1) -> number\n\nIISS : 'a -> 'a\n//│ res: 'a -> 'a\n//│   where\n//│     [-'a, +'a] in {[int, int], [string, string]}\n\nIISS 0\n//│ res: int\n\n(IISS : int -> int) 0\n//│ res: int\n\n(if true then IISS else BBNN) 0\n//│ res: number\n\n// * Note that this is not considered ambiguous\n// * because the type variable occurrences are polar,\n// * meaning that the TSCs are always trivially satisfiable\n// * and thus the code is well-typed.\n// * Conceptually, we'd expect this inferred type to reduce to `int -> number`,\n// * but it's tricky to do such simplifications in general.\ndef f = fun x -> (if true then IISS else BBNN) x\n//│ f: 'a -> 'b\n//│   where\n//│     [+'a, -'b] in {[int, int], [string, string]}\n//│     [+'a, -'b] in {[bool, bool], [number, number]}\n\nf(0)\n//│ res: number\n\n:e\nf(0) + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.106: \tf(0) + 1\n//│ ║         \t^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.13: \tdef BBNN: bool -> bool & number -> number\n//│ ║        \t                                   ^^^^^^\n//│ ╟── but it flows into application with expected type `int`\n//│ ║  l.106: \tf(0) + 1\n//│ ╙──       \t^^^^\n//│ res: error | int\n\nf : int -> number\n//│ res: int -> number\n\n:e\nf : number -> int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.122: \tf : number -> int\n//│ ║         \t^\n//│ ╟── type `number` does not match type `?a`\n//│ ║  l.122: \tf : number -> int\n//│ ╙──       \t    ^^^^^^\n//│ res: number -> int\n\n\nif true then IISS else BBNN\n//│ res: bool -> bool & number -> number | int -> int & string -> string\n\n(if true then IISS else ZZII) : int -> int\n//│ res: int -> int\n\n(if true then IISS else BBNN) : (0 | 1) -> number\n//│ res: (0 | 1) -> number\n\n:e\n(if true then IISS else BBNN) : (0 | 1 | true) -> number\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.142: \t(if true then IISS else BBNN) : (0 | 1 | true) -> number\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `int -> int & string -> string` is not an instance of `(0 | 1 | true) -> number`\n//│ ║  l.12: \tdef IISS: int -> int & string -> string\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(0 | 1 | true) -> number`\n//│ ║  l.142: \t(if true then IISS else BBNN) : (0 | 1 | true) -> number\n//│ ║         \t              ^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.142: \t(if true then IISS else BBNN) : (0 | 1 | true) -> number\n//│ ╙──       \t                                ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: (0 | 1 | true) -> number\n\n\n// * Note that type normalization used to be very aggressive at approximating non-tag type negations,\n// * to simplify the result, but this was changed as it was unsound\n\ndef test: ~(int -> int)\n//│ test: ~(int -> int)\n\n// * See also test file BooleanFail.mls about this previous unsoundness\n:e\ntest = 42\nnot test\n//│ 42\n//│   <:  test:\n//│ ~(int -> int)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.167: \tnot test\n//│ ║         \t^^^^^^^^\n//│ ╟── type `~(int -> int)` is not an instance of type `bool`\n//│ ║  l.161: \tdef test: ~(int -> int)\n//│ ║         \t          ^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `bool`\n//│ ║  l.167: \tnot test\n//│ ╙──       \t    ^^^^\n//│ res: bool | error\n\ndef test: ~(int -> int) & ~bool\n//│ test: ~bool & ~(int -> int)\n\ndef test: ~(int -> int) & bool\n//│ test: bool\n\ndef test: ~(int -> int) & ~(bool -> bool)\n//│ test: ~(nothing -> (bool | int))\n\ndef test: ~(int -> int | bool -> bool)\n//│ test: ~(nothing -> (bool | int))\n\ndef test: ~(int -> int & string -> string) & ~(bool -> bool & number -> number)\n//│ test: in ~(nothing -> (number | string) & int -> number & nothing -> (bool | string) & nothing -> (bool | int)) out ~(nothing -> (bool | int) & nothing -> (bool | string) & int -> number & nothing -> (number | string))\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Paper.mls",
    "content": ":NoJS\n:NoRecursiveTypes\n:NoConstrainedTypes\n\n\nI x = x\nK x y = x\nauto x = x x\nmonster = (fun y -> (let tmp = y I in y K)) auto\n//│ I: 'a -> 'a\n//│ K: 'a -> anything -> 'a\n//│ auto: ('a -> 'b & 'a) -> 'b\n//│ monster: anything -> 'a -> anything -> 'a\n\nmonster{}\n//│ res: 'a -> anything -> 'a\n\nfun y -> (let tmp = y I in y K)\n//│ res: ((forall 'a. 'a -> 'a) -> anything & (forall 'b. 'b -> anything -> 'b) -> 'c) -> 'c\n\n\n\ndef bar x = if true then x else id\n//│ bar: 'a -> ('b -> 'b | 'a)\n\nbar succ\n//│ res: int -> int\n\n\n\ndef k: forall 'a. (forall 'b. 'b -> ('a, 'b)) -> 'a\n//│ k: (forall 'b. 'b -> ('a, 'b,)) -> 'a\n\n:e\nk (fun x -> (x, x)) + 1\n//│ ╔══[ERROR] Type error in operator application\n//│ ║  l.35: \tk (fun x -> (x, x)) + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.31: \tdef k: forall 'a. (forall 'b. 'b -> ('a, 'b)) -> 'a\n//│ ║        \t                              ^^\n//│ ╟── into type `int`\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this tuple literal:\n//│ ║  l.35: \tk (fun x -> (x, x)) + 1\n//│ ║        \t            ^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.35: \tk (fun x -> (x, x)) + 1\n//│ ╙──      \t^\n//│ res: error | int\n\n\ndef k: (forall 'a. 'a -> 'a) -> int\n//│ k: (forall 'a. 'a -> 'a) -> int\n\n:e\n(fun f -> k (fun x -> f x)) id\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.57: \t(fun f -> k (fun x -> f x)) id\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.53: \tdef k: (forall 'a. 'a -> 'a) -> int\n//│ ║        \t                   ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.53: \tdef k: (forall 'a. 'a -> 'a) -> int\n//│ ║        \t                         ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.57: \t(fun f -> k (fun x -> f x)) id\n//│ ║        \t                      ^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.57: \t(fun f -> k (fun x -> f x)) id\n//│ ╙──      \t                      ^^^\n//│ res: error | int\n\n\n\n// * Expected error\n:e\nauto auto\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.80: \tauto auto\n//│ ║        \t^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n\n// * Note: this creates a cyclic bound structure:\n// *  (α32_94 -> α33_95) <: α32_94 <: ((α32_94,) -> α33_95)\n// * so it is rejected by the occurs-check\n:e // occurs-check\nauto auto!\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'a -> (? & 'b)\n//│ ╙──\n//│ res: nothing\n\n\n:NoCycleCheck\n:RecursiveTypes\n\n:e\nauto auto\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?a ?b. ?b -> ?a <: (forall ?a ?c. ?c -> ?a) -> ?d` exceeded recursion depth limit (250)\n//│ ║  l.104: \tauto auto\n//│ ║         \t^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n\nauto auto!\n//│ res: nothing\n\nauto! auto!\n//│ res: nothing\n\n:e\nauto! auto\n//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b <: (forall ?c ?d. ?d -> ?c) -> ?e` exceeded recursion depth limit (250)\n//│ ║  l.118: \tauto! auto\n//│ ║         \t^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n\n(fun x -> x x) (fun x -> x x)!\n//│ res: nothing\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/PaperTable.mls",
    "content": "\n:NoConstrainedTypes\n:DontDistributeForalls\n:NoCycleCheck\n:NoRecursiveTypes\n\n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n\nclass ST[S, A]\n  method Inv_S: S -> S\n  method Cov_A: A\n//│ Defined class ST[=S, +A]\n//│ Declared ST.Inv_S: ST['S, ?] -> 'S -> 'S\n//│ Declared ST.Cov_A: ST['S, 'A] -> 'A\n\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: List['a] -> 'a\ndef head l = l.Head\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n//│ List['a] -> 'a\n//│   <:  head:\n//│ List['a] -> 'a\n//│     = [Function: head]\n\ndef tail: List['a] -> List['a]\ndef tail l = l.Tail\n//│ tail: List['a] -> List['a]\n//│     = <missing implementation>\n//│ List['a] -> List['a]\n//│   <:  tail:\n//│ List['a] -> List['a]\n//│     = [Function: tail]\n\n// Used to represent `[]` in the papers\ndef nil: List['a]\nnil = Nil {}\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\ndef cons: 'a -> List['a] -> List['a]\ndef cons head tail = Cons { head; tail }\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ 'b -> (forall 'a 'tail. (List['a] & 'tail) -> (Cons['b | 'a] with {head: 'b, tail: 'tail}))\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\ndef is_empty: List['a] -> bool\ndef is_empty l = eq l nil\n//│ is_empty: List[?] -> bool\n//│         = <missing implementation>\n//│ anything -> bool\n//│   <:  is_empty:\n//│ List[?] -> bool\n//│         = [Function: is_empty]\n\ndef single: 'a -> List['a]\ndef single x = cons x nil\n//│ single: 'a -> List['a]\n//│       = <missing implementation>\n//│ 'a -> List['a]\n//│   <:  single:\n//│ 'a -> List['a]\n//│       = [Function: single]\n\ndef append: List['a] -> List['a] -> List['a]\nrec def append l1 l2 =\n  if is_empty l1 then l2\n  else cons (head l1) (append (tail l1) l2)\n//│ append: List['a] -> List['a] -> List['a]\n//│       = <missing implementation>\n//│ List['a] -> List['a] -> List['a]\n//│   <:  append:\n//│ List['a] -> List['a] -> List['a]\n//│       = [Function: append]\n\ndef length: List['a] -> int\nrec def length l =\n  if is_empty l then 0\n  else succ (length (tail l))\n//│ length: List[?] -> int\n//│       = <missing implementation>\n//│ List[?] -> int\n//│   <:  length:\n//│ List[?] -> int\n//│       = [Function: length1]\n\ndef id: 'a -> 'a\ndef id x = x\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id:\n//│ 'a -> 'a\n//│   = [Function: id1]\n\ndef ids: List[forall 'a. 'a -> 'a]\ndef ids = single id\n//│ ids: List[forall 'a. 'a -> 'a]\n//│    = <missing implementation>\n//│ List[forall 'a. 'a -> 'a]\n//│   <:  ids:\n//│ List[forall 'a. 'a -> 'a]\n//│    = [Function: ids]\n\ndef inc: int -> int\ndef inc = succ\n//│ inc: int -> int\n//│    = <missing implementation>\n//│ int -> int\n//│   <:  inc:\n//│ int -> int\n//│    = [Function: inc]\n\ndef choose: 'a -> 'a -> 'a\ndef choose x y = if true then x else y\n//│ choose: 'a -> 'a -> 'a\n//│       = <missing implementation>\n//│ 'a -> (forall 'b. 'b -> ('a | 'b))\n//│   <:  choose:\n//│ 'a -> 'a -> 'a\n//│       = [Function: choose]\n\ndef poly: (forall 'a. 'a -> 'a) -> (int, bool)\ndef poly f = (f 1, f true)\n//│ poly: (forall 'a. 'a -> 'a) -> (int, bool,)\n//│     = <missing implementation>\n//│ (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│   <:  poly:\n//│ (forall 'a. 'a -> 'a) -> (int, bool,)\n//│     = [Function: poly]\n\ndef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\ndef auto x = x x\n//│ auto: (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│     = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  auto:\n//│ (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│     = [Function: auto]\n\ndef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\ndef auto_ x = x x\n//│ auto_: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│      = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  auto_:\n//│ (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│      = [Function: auto_]\n\ndef map: ('a -> 'b) -> List['a] -> List['b]\nrec def map f l =\n  if is_empty l then nil\n  else cons (f (head l)) (map f (tail l))\n//│ map: ('a -> 'b) -> List['a] -> List['b]\n//│    = <missing implementation>\n//│ ('b -> 'a) -> List['b] -> List['a]\n//│   <:  map:\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│    = [Function: map]\n\ndef app: ('a -> 'b) -> 'a -> 'b\ndef app f x = f x\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = <missing implementation>\n//│ ('a -> 'b) -> 'a -> 'b\n//│   <:  app:\n//│ ('a -> 'b) -> 'a -> 'b\n//│    = [Function: app]\n\ndef revapp: 'a -> ('a -> 'b) -> 'b\ndef revapp x f = f x\n//│ revapp: 'a -> ('a -> 'b) -> 'b\n//│       = <missing implementation>\n//│ 'a -> (forall 'b. ('a -> 'b) -> 'b)\n//│   <:  revapp:\n//│ 'a -> ('a -> 'b) -> 'b\n//│       = [Function: revapp]\n\n:ng\ndef runST: (forall 's. ST['s, 'v]) -> 'v\n//│ runST: (forall 's. ST['s, 'v]) -> 'v\n\n:ng\ndef argST: ST['s, int]\n//│ argST: ST['s, int]\n\n// A9\n:ng\ndef f: ('a -> 'a) -> List['a] -> 'a\n//│ f: ('a -> 'a) -> List['a] -> 'a\n\n// C8\n:ng\ndef g: List['a] -> List['a] -> 'a\n//│ g: List['a] -> List['a] -> 'a\n\n// E1, E2\n:ng\ndef h: int -> (forall 'a. 'a -> 'a)\ndef k: 'a -> List['a] -> 'a\ndef lst: List[forall 'a. int -> 'a -> 'a]\n//│ h: int -> (forall 'a. 'a -> 'a)\n//│ k: 'a -> List['a] -> 'a\n//│ lst: List[forall 'a. int -> 'a -> 'a]\n\n// E3\n:ng\ndef r: (forall 'a. 'a -> (forall 'b. 'b -> 'b)) -> int\n//│ r: (anything -> (forall 'b. 'b -> 'b)) -> int\n\n\ntype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ Defined type alias ChurchInt\n\ntype Pair[A, B] = (A, B)\n//│ Defined type alias Pair[+A, +B]\n\ndef fst: forall 'a 'b. Pair['a, 'b] -> 'a\ndef fst((x, y)) = x\n//│ fst: Pair['a, ?] -> 'a\n//│    = <missing implementation>\n//│ (('a, anything,),) -> 'a\n//│   <:  fst:\n//│ Pair['a, ?] -> 'a\n//│    = [Function: fst]\n\ndef zero: ChurchInt\ndef zero f x = x\n//│ zero: ChurchInt\n//│     = <missing implementation>\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  zero:\n//│ ChurchInt\n//│     = [Function: zero]\n\ndef succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\ndef succ (n: ChurchInt) f x = f (n f x)\n//│ succ: (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = <missing implementation>\n//│ ChurchInt -> (forall 'N 'N0 'a. ('N -> ('N & 'N0) & 'N0 -> 'a) -> ('N & 'N0) -> 'a)\n//│   <:  succ:\n//│ (forall 'N. ('N -> 'N) -> 'N -> 'N) -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│     = [Function: succ1]\n\n\n\n\n// ================================================================\n// ======================== Vanilla SuperF ========================\n// ================================================================\n\n\n// ============ A. polymorphic instantiation ============\n\n// A1\nfun x -> fun y -> y\n//│ res: anything -> (forall 'a. 'a -> 'a)\n//│    = [Function: res]\n\n// A2\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// A3\nchoose nil ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// A4\nfun x -> x x\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// A5\nid auto\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│    = [Function: auto]\n\n// A6\nid auto_\n//│ res: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│    = [Function: auto_]\n\n// A7\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> (forall 'b. 'b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A8\nchoose id auto_\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A9\n:ng\nf (choose id) ids\n//│ res: 'a -> 'a\n\n// A10\npoly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A11\npoly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A12\nid poly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n\n// ============ B. inference of polymorphic arguments ============\n\n// B1\nfun f -> (f 1, f true)\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: res]\n\n// B2\nfun xs -> poly (head xs)\n//│ res: List[forall 'a. 'a -> 'a] -> (int, bool,)\n//│    = [Function: res]\n\n\n// ============ C. functions on polymorphic lists ============\n\n// C1\nlength ids\n//│ res: int\n//│    = 1\n\n// C2\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// C3\nhead ids\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// C4\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// C5\ncons id ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C6\ncons (fun x -> x) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function (anonymous)],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C7\nappend (single inc) (single id)\n//│ res: List[int -> int]\n//│    = Cons {\n//│        head: [Function: succ],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C8\n:ng\ng (single id) ids\n//│ res: 'a -> 'a\n\n// C9\nmap poly (single id)\n//│ res: List[(int, bool,)]\n//│    = Cons { head: [ 1, true ], tail: Nil {} }\n\n// C10\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n\n// ============ D. application functions ============\n\n// D1\napp poly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D2\nrevapp id poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D3\n:ng\nrunST argST\n//│ res: int\n\n// D4\n:ng\napp runST argST\n//│ res: int\n\n// D5\n:ng\nrevapp argST runST\n//│ res: int\n\n\n// ============ E. η-expansion ============\n\n// E1\n:ng\nk h lst\n//│ res: int -> (forall 'a. 'a -> 'a)\n\n// E2\n:ng\nk (fun x -> h x) lst\n//│ res: int -> (forall 'a. 'a -> 'a)\n\n// E3\n:ng\nr (fun x -> fun y -> y)\n//│ res: int\n\n\n// ============ F. FreezeML Additions ============\n\n// F5\nauto id\n//│ res: 'b -> 'b\n//│    = [Function: id1]\n\n// F6\ncons (head ids) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// F7\n(head ids) 3\n//│ res: 3\n//│    = 3\n\n// F8\nchoose (head ids)\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// F9\nlet f = revapp id in f poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// F10\nchoose id (fun x -> auto_ x)\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n\n// ============ G. SuperF Additions ============\n\n// G1\ndef z f x = x\n//│ z: anything -> (forall 'a. 'a -> 'a)\n//│  = [Function: z]\n\n// G2\ndef s n f x = f (n f x)\n//│ s: ('a -> 'b -> 'c) -> (forall 'd. ('c -> 'd & 'a) -> 'b -> 'd)\n//│  = [Function: s]\n\n// G3\nn3 = s (s (s z))\n//│ n3: ('a -> 'b & 'b -> 'c & 'c -> 'd) -> 'a -> 'd\n//│   = [Function (anonymous)]\n\n// G1A\nz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function: z]\n\n:e\n// G2A\ns: ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.528: \ts: ChurchInt -> ChurchInt\n//│ ║         \t^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.243: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.243: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║         \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.512: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.528: \ts: ChurchInt -> ChurchInt\n//│ ╙──       \t^\n//│ res: ChurchInt -> ChurchInt\n//│    = [Function: s]\n\n// G3A\nn3: ChurchInt\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n// G4\nfst (fst (fst (n3 (fun x -> (x, 0)) 1)))\n//│ res: 1\n//│    = 1\n\n(succ (succ zero)) (succ (succ zero))\n//│ res: ('M -> 'M) -> 'M -> 'M\n//│    = [Function (anonymous)]\n\n(s (s z)) (s (s z))\n//│ res: ('a -> ('a & 'b) & 'b -> ('a & 'b & 'c)) -> 'a -> 'c\n//│    = [Function (anonymous)]\n\n// G7\nrec def to_ch n = if n == 0 then z else s (to_ch (n - 1))\n//│ to_ch: int -> (forall 'a. ('b -> 'a & 'b -> 'b) -> (forall 'c. ('b & 'c) -> ('a | 'c)))\n//│      = [Function: to_ch]\n\n:e\n// G7A\nto_ch: int -> ChurchInt\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.573: \tto_ch: int -> ChurchInt\n//│ ║         \t^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.243: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.243: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║         \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.512: \tdef s n f x = f (n f x)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.567: \trec def to_ch n = if n == 0 then z else s (to_ch (n - 1))\n//│ ║         \t                                        ^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.573: \tto_ch: int -> ChurchInt\n//│ ║         \t^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.512: \tdef s n f x = f (n f x)\n//│ ╙──       \t              ^^^^^^^^^\n//│ res: int -> ChurchInt\n//│    = [Function: to_ch]\n\n:e\n// G8\nrec def id1 x = if true then x else id1 id1 x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> 'c\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c :> 'b -> 'c\n//│        <: 'a\n//│ ║  l.601: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──       \t                                    ^^^^^^^\n//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b <: ?id1` exceeded recursion depth limit (250)\n//│ ║  l.601: \trec def id1 x = if true then x else id1 id1 x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id11]\n\n:e\n// G9\nid1 id1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c. ('d & 'b) -> ('a | 'c)\n//│        <: 'd -> 'a\n//│     'd :> forall 'b 'c. ('d & 'b) -> ('a | 'c)\n//│        <: 'a & 'e\n//│     'e :> forall 'b 'c. ('b & 'e) -> ('f | 'c)\n//│        <: 'f & 'g\n//│     'g :> forall 'b 'c. ('b & 'g) -> ('h | 'c)\n//│        <: 'h & 'i\n//│     'i :> forall 'b 'c. ('b & 'i) -> ('j | 'c)\n//│        <: 'j & 'k\n//│     'k :> forall 'b 'c. ('b & 'k) -> ('l | 'c)\n//│        <: 'l & 'm\n//│     'm :> forall 'b 'c. ('b & 'm) -> ('n | 'c)\n//│        <: 'n & 'o\n//│     'o :> forall 'b 'c. ('b & 'o) -> ('p | 'c)\n//│        <: 'p & 'q\n//│     'q :> forall 'b 'c. ('b & 'q) -> ('r | 'c)\n//│        <: 'r & 's\n//│     's :> forall 'b 'c. ('b & 's) -> ('t | 'c)\n//│        <: 't & 'u\n//│     'u :> forall 'b 'c. ('b & 'u) -> ('v | 'c)\n//│        <: 'v\n//│     'v :> forall 'b 'c. ('b & 'u) -> ('v | 'c)\n//│        <: 'u -> 'v\n//│     't :> forall 'b 'c. ('b & 's) -> ('t | 'c)\n//│        <: 's -> 't\n//│     'r :> forall 'b 'c. ('b & 'q) -> ('r | 'c)\n//│        <: 'q -> 'r\n//│     'p :> forall 'b 'c. ('b & 'o) -> ('p | 'c)\n//│        <: 'o -> 'p\n//│     'n :> forall 'b 'c. ('b & 'm) -> ('n | 'c)\n//│        <: 'm -> 'n\n//│     'l :> forall 'b 'c. ('b & 'k) -> ('l | 'c)\n//│        <: 'k -> 'l\n//│     'j :> forall 'b 'c. ('b & 'i) -> ('j | 'c)\n//│        <: 'i -> 'j\n//│     'h :> forall 'b 'c. ('b & 'g) -> ('h | 'c)\n//│        <: 'g -> 'h\n//│     'f :> forall 'b 'c. ('b & 'e) -> ('f | 'c)\n//│        <: 'e -> 'f\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c := 'b -> 'c\n//│ ║  l.601: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──       \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?id1. ?id1 <: (forall ?id10. ?id10) -> ?a` exceeded recursion depth limit (250)\n//│ ║  l.624: \tid1 id1\n//│ ║         \t^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│    = [Function: id11]\n\n// Gn\n:e\nauto auto\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.681: \tauto auto\n//│ ║         \t^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^^^^^^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ╙──       \t                   ^^\n//│ res: error | 'b -> 'b\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// Gn+1\n:e\n(fun x -> x x) (fun x -> x x)\n//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b <: (forall ?c ?d. ?d -> ?c) -> ?e` exceeded recursion depth limit (250)\n//│ ║  l.700: \t(fun x -> x x) (fun x -> x x)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\n:re\n// Gn+2\n(fun x -> x x) (fun x -> x x)!\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'a -> (? & 'b)\n//│ ╙──\n//│ res: nothing\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n\n// ===========================================================\n// ======================== SuperF +D ========================\n// ===========================================================\n\n:DistributeForalls\n\n\n// ============ A. polymorphic instantiation ============\n\n// A1\nfun x -> fun y -> y\n//│ res: anything -> 'a -> 'a\n//│    = [Function: res]\n\n// A2\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// A3\nchoose nil ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// A4\nfun x -> x x\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// A5\nid auto\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│    = [Function: auto]\n\n// A6\nid auto_\n//│ res: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│    = [Function: auto_]\n\n// A7\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A8\nchoose id auto_\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A9\n:ng\nf (choose id) ids\n//│ res: 'a -> 'a\n\n// A10\npoly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A11\npoly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A12\nid poly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n\n// ============ B. inference of polymorphic arguments ============\n\n// B1\nfun f -> (f 1, f true)\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: res]\n\n// B2\nfun xs -> poly (head xs)\n//│ res: List[forall 'a. 'a -> 'a] -> (int, bool,)\n//│    = [Function: res]\n\n\n// ============ C. functions on polymorphic lists ============\n\n// C1\nlength ids\n//│ res: int\n//│    = 1\n\n// C2\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// C3\nhead ids\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// C4\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// C5\ncons id ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C6\ncons (fun x -> x) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function (anonymous)],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C7\nappend (single inc) (single id)\n//│ res: List[int -> int]\n//│    = Cons {\n//│        head: [Function: succ],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C8\n:ng\ng (single id) ids\n//│ res: 'a -> 'a\n\n// C9\nmap poly (single id)\n//│ res: List[(int, bool,)]\n//│    = Cons { head: [ 1, true ], tail: Nil {} }\n\n// C10\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n\n// ============ D. application functions ============\n\n// D1\napp poly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D2\nrevapp id poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D3\n:ng\nrunST argST\n//│ res: int\n\n// D4\n:ng\napp runST argST\n//│ res: int\n\n// D5\n:ng\nrevapp argST runST\n//│ res: int\n\n\n// ============ E. η-expansion ============\n\n// E1\n:ng\nk h lst\n//│ res: int -> 'a -> 'a\n\n// E2\n:ng\nk (fun x -> h x) lst\n//│ res: int -> 'a -> 'a\n\n// E3\n:ng\nr (fun x -> fun y -> y)\n//│ res: int\n\n\n// ============ F. FreezeML Additions ============\n\n// F5\nauto id\n//│ res: 'b -> 'b\n//│    = [Function: id1]\n\n// F6\ncons (head ids) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// F7\n(head ids) 3\n//│ res: 3\n//│    = 3\n\n// F8\nchoose (head ids)\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// F9\nlet f = revapp id in f poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// F10\nchoose id (fun x -> auto_ x)\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n\n// ============ G. SuperF Additions ============\n\n// G1\ndef z f x = x\n//│ z: anything -> 'a -> 'a\n//│  = [Function: z1]\n\n// G2\ndef s n f x = f (n f x)\n//│ s: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│  = [Function: s1]\n\n// G3\nn3 = s (s (s z))\n//│ n3: ('a -> 'b & 'c -> 'a & 'd -> 'c) -> 'd -> 'b\n//│   = [Function (anonymous)]\n\n// G1A\nz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function: z1]\n\n// G2A\ns: ChurchInt -> ChurchInt\n//│ res: ChurchInt -> ChurchInt\n//│    = [Function: s1]\n\n// G3A\nn3: ChurchInt\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n// G4\nfst (fst (fst (n3 (fun x -> (x, 0)) 1)))\n//│ res: 1\n//│    = 1\n\n(succ (succ zero)) (succ (succ zero))\n//│ res: ('M -> 'M) -> 'M -> 'M\n//│    = [Function (anonymous)]\n\n(s (s z)) (s (s z))\n//│ res: ('a -> ('a & 'b & 'c) & 'c -> ('a & 'c)) -> 'c -> 'b\n//│    = [Function (anonymous)]\n\n// G7\nrec def to_ch n = if n == 0 then z else s (to_ch (n - 1))\n//│ to_ch: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│      = [Function: to_ch1]\n\n// G7A\nto_ch: int -> ChurchInt\n//│ res: int -> ChurchInt\n//│    = [Function: to_ch1]\n\n:e\n// G8\nrec def id1 x = if true then x else id1 id1 x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> 'c\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c :> 'b -> 'c\n//│        <: 'a\n//│ ║  l.1008: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──        \t                                    ^^^^^^^\n//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b <: ?id1` exceeded recursion depth limit (250)\n//│ ║  l.1008: \trec def id1 x = if true then x else id1 id1 x\n//│ ║          \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id12]\n\n:e\n// G9\nid1 id1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c. ('d & 'b) -> ('a | 'c)\n//│        <: 'd -> 'a\n//│     'd :> forall 'b 'c. ('d & 'b) -> ('a | 'c)\n//│        <: 'a & 'e\n//│     'e :> forall 'b 'c. ('b & 'e) -> ('f | 'c)\n//│        <: 'f & 'g\n//│     'g :> forall 'b 'c. ('b & 'g) -> ('h | 'c)\n//│        <: 'h & 'i\n//│     'i :> forall 'b 'c. ('b & 'i) -> ('j | 'c)\n//│        <: 'j & 'k\n//│     'k :> forall 'b 'c. ('b & 'k) -> ('l | 'c)\n//│        <: 'l & 'm\n//│     'm :> forall 'b 'c. ('b & 'm) -> ('n | 'c)\n//│        <: 'n & 'o\n//│     'o :> forall 'b 'c. ('b & 'o) -> ('p | 'c)\n//│        <: 'p & 'q\n//│     'q :> forall 'b 'c. ('b & 'q) -> ('r | 'c)\n//│        <: 'r & 's\n//│     's :> forall 'b 'c. ('b & 's) -> ('t | 'c)\n//│        <: 't & 'u\n//│     'u :> forall 'b 'c. ('b & 'u) -> ('v | 'c)\n//│        <: 'v\n//│     'v :> forall 'b 'c. ('b & 'u) -> ('v | 'c)\n//│        <: 'u -> 'v\n//│     't :> forall 'b 'c. ('b & 's) -> ('t | 'c)\n//│        <: 's -> 't\n//│     'r :> forall 'b 'c. ('b & 'q) -> ('r | 'c)\n//│        <: 'q -> 'r\n//│     'p :> forall 'b 'c. ('b & 'o) -> ('p | 'c)\n//│        <: 'o -> 'p\n//│     'n :> forall 'b 'c. ('b & 'm) -> ('n | 'c)\n//│        <: 'm -> 'n\n//│     'l :> forall 'b 'c. ('b & 'k) -> ('l | 'c)\n//│        <: 'k -> 'l\n//│     'j :> forall 'b 'c. ('b & 'i) -> ('j | 'c)\n//│        <: 'i -> 'j\n//│     'h :> forall 'b 'c. ('b & 'g) -> ('h | 'c)\n//│        <: 'g -> 'h\n//│     'f :> forall 'b 'c. ('b & 'e) -> ('f | 'c)\n//│        <: 'e -> 'f\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c := 'b -> 'c\n//│ ║  l.1008: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──        \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?id1. ?id1 <: (forall ?id10. ?id10) -> ?a` exceeded recursion depth limit (250)\n//│ ║  l.1031: \tid1 id1\n//│ ║          \t^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│    = [Function: id12]\n\n// Gn\n:e\nauto auto\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.1088: \tauto auto\n//│ ║          \t^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^^^^^^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ╙──       \t                   ^^\n//│ res: error | 'b -> 'b\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// Gn+1\n:e\n(fun x -> x x) (fun x -> x x)\n//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b <: (forall ?c ?d. ?d -> ?c) -> ?e` exceeded recursion depth limit (250)\n//│ ║  l.1107: \t(fun x -> x x) (fun x -> x x)\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\n:re\n// Gn+2\n(fun x -> x x) (fun x -> x x)!\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'a -> (? & 'b)\n//│ ╙──\n//│ res: nothing\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n\n// ==============================================================\n// ======================== SuperF +D+CC ========================\n// ==============================================================\n\n:CycleCheck\n\n\n// ============ A. polymorphic instantiation ============\n\n// A1\nfun x -> fun y -> y\n//│ res: anything -> 'a -> 'a\n//│    = [Function: res]\n\n// A2\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// A3\nchoose nil ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// A4\nfun x -> x x\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// A5\nid auto\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│    = [Function: auto]\n\n// A6\nid auto_\n//│ res: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│    = [Function: auto_]\n\n// A7\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A8\nchoose id auto_\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A9\n:ng\nf (choose id) ids\n//│ res: 'a -> 'a\n\n// A10\npoly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A11\npoly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A12\nid poly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n\n// ============ B. inference of polymorphic arguments ============\n\n// B1\nfun f -> (f 1, f true)\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: res]\n\n// B2\nfun xs -> poly (head xs)\n//│ res: List[forall 'a. 'a -> 'a] -> (int, bool,)\n//│    = [Function: res]\n\n\n// ============ C. functions on polymorphic lists ============\n\n// C1\nlength ids\n//│ res: int\n//│    = 1\n\n// C2\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// C3\nhead ids\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// C4\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// C5\ncons id ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C6\ncons (fun x -> x) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function (anonymous)],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C7\nappend (single inc) (single id)\n//│ res: List[int -> int]\n//│    = Cons {\n//│        head: [Function: succ],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C8\n:ng\ng (single id) ids\n//│ res: 'a -> 'a\n\n// C9\nmap poly (single id)\n//│ res: List[(int, bool,)]\n//│    = Cons { head: [ 1, true ], tail: Nil {} }\n\n// C10\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n\n// ============ D. application functions ============\n\n// D1\napp poly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D2\nrevapp id poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D3\n:ng\nrunST argST\n//│ res: int\n\n// D4\n:ng\napp runST argST\n//│ res: int\n\n// D5\n:ng\nrevapp argST runST\n//│ res: int\n\n\n// ============ E. η-expansion ============\n\n// E1\n:ng\nk h lst\n//│ res: int -> 'a -> 'a\n\n// E2\n:ng\nk (fun x -> h x) lst\n//│ res: int -> 'a -> 'a\n\n// E3\n:ng\nr (fun x -> fun y -> y)\n//│ res: int\n\n\n// ============ F. FreezeML Additions ============\n\n// F5\nauto id\n//│ res: 'b -> 'b\n//│    = [Function: id1]\n\n// F6\ncons (head ids) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// F7\n(head ids) 3\n//│ res: 3\n//│    = 3\n\n// F8\nchoose (head ids)\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// F9\nlet f = revapp id in f poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// F10\nchoose id (fun x -> auto_ x)\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n\n// ============ G. SuperF Additions ============\n\n// G1\ndef z f x = x\n//│ z: anything -> 'a -> 'a\n//│  = [Function: z2]\n\n// G2\ndef s n f x = f (n f x)\n//│ s: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│  = [Function: s2]\n\n// G3\nn3 = s (s (s z))\n//│ n3: ('a -> 'b & 'c -> 'a & 'd -> 'c) -> 'd -> 'b\n//│   = [Function (anonymous)]\n\n// G1A\nz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function: z2]\n\n// G2A\ns: ChurchInt -> ChurchInt\n//│ res: ChurchInt -> ChurchInt\n//│    = [Function: s2]\n\n// G3A\nn3: ChurchInt\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n// G4\nfst (fst (fst (n3 (fun x -> (x, 0)) 1)))\n//│ res: 1\n//│    = 1\n\n(succ (succ zero)) (succ (succ zero))\n//│ res: ('M -> 'M) -> 'M -> 'M\n//│    = [Function (anonymous)]\n\n(s (s z)) (s (s z))\n//│ res: ('a -> ('a & 'b & 'c) & 'c -> ('a & 'c)) -> 'c -> 'b\n//│    = [Function (anonymous)]\n\n// G7\nrec def to_ch n = if n == 0 then z else s (to_ch (n - 1))\n//│ to_ch: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│      = [Function: to_ch2]\n\n// G7A\nto_ch: int -> ChurchInt\n//│ res: int -> ChurchInt\n//│    = [Function: to_ch2]\n\n:e\n// G8\nrec def id1 x = if true then x else id1 id1 x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> 'c\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c :> 'b -> 'c\n//│        <: 'a\n//│ ║  l.1415: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──        \t                                    ^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required\n//│ ║  l.1415: \trec def id1 x = if true then x else id1 id1 x\n//│ ║          \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id13]\n\n:e\n// G9\nid1 id1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c. ('d & 'b) -> ('a | 'c)\n//│        <: 'd -> 'a\n//│     'd :> forall 'b 'c. ('d & 'b) -> ('a | 'c)\n//│        <: 'a & 'e & 'f\n//│     'f :> ('d & 'f) -> ('g | 'a)\n//│        <: 'd & 'g\n//│     'g :> ('d & 'f) -> ('g | 'a)\n//│        <: 'f -> 'g\n//│     'e :> ('d & 'e) -> ('h | 'a)\n//│        <: 'd & 'h\n//│     'h :> ('d & 'e) -> ('h | 'a)\n//│        <: 'e -> 'h\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c := 'b -> 'c\n//│ ║  l.1415: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──        \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1438: \tid1 id1\n//│ ║          \t^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│    = [Function: id13]\n\n// Gn\n:e\nauto auto\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.1467: \tauto auto\n//│ ║          \t^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^^^^^^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ╙──       \t                   ^^\n//│ res: error | 'b -> 'b\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// Gn+1\n:e\n(fun x -> x x) (fun x -> x x)\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1486: \t(fun x -> x x) (fun x -> x x)\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:e\n:re\n// Gn+2\n(fun x -> x x) (fun x -> x x)!\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'a -> (? & 'b)\n//│ ╙──\n//│ res: nothing\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n\n// =================================================================\n// ======================== SuperF +D+CC+RT ========================\n// =================================================================\n\n:RecursiveTypes\n\n\n// ============ A. polymorphic instantiation ============\n\n// A1\nfun x -> fun y -> y\n//│ res: anything -> 'a -> 'a\n//│    = [Function: res]\n\n// A2\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// A3\nchoose nil ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// A4\nfun x -> x x\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// A5\nid auto\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│    = [Function: auto]\n\n// A6\nid auto_\n//│ res: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│    = [Function: auto_]\n\n// A7\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A8\nchoose id auto_\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A9\n:ng\nf (choose id) ids\n//│ res: 'a -> 'a\n\n// A10\npoly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A11\npoly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A12\nid poly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n\n// ============ B. inference of polymorphic arguments ============\n\n// B1\nfun f -> (f 1, f true)\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: res]\n\n// B2\nfun xs -> poly (head xs)\n//│ res: List[forall 'a. 'a -> 'a] -> (int, bool,)\n//│    = [Function: res]\n\n\n// ============ C. functions on polymorphic lists ============\n\n// C1\nlength ids\n//│ res: int\n//│    = 1\n\n// C2\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// C3\nhead ids\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// C4\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// C5\ncons id ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C6\ncons (fun x -> x) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function (anonymous)],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C7\nappend (single inc) (single id)\n//│ res: List[int -> int]\n//│    = Cons {\n//│        head: [Function: succ],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C8\n:ng\ng (single id) ids\n//│ res: 'a -> 'a\n\n// C9\nmap poly (single id)\n//│ res: List[(int, bool,)]\n//│    = Cons { head: [ 1, true ], tail: Nil {} }\n\n// C10\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n\n// ============ D. application functions ============\n\n// D1\napp poly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D2\nrevapp id poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D3\n:ng\nrunST argST\n//│ res: int\n\n// D4\n:ng\napp runST argST\n//│ res: int\n\n// D5\n:ng\nrevapp argST runST\n//│ res: int\n\n\n// ============ E. η-expansion ============\n\n// E1\n:ng\nk h lst\n//│ res: int -> 'a -> 'a\n\n// E2\n:ng\nk (fun x -> h x) lst\n//│ res: int -> 'a -> 'a\n\n// E3\n:ng\nr (fun x -> fun y -> y)\n//│ res: int\n\n\n// ============ F. FreezeML Additions ============\n\n// F5\nauto id\n//│ res: 'b -> 'b\n//│    = [Function: id1]\n\n// F6\ncons (head ids) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// F7\n(head ids) 3\n//│ res: 3\n//│    = 3\n\n// F8\nchoose (head ids)\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// F9\nlet f = revapp id in f poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// F10\nchoose id (fun x -> auto_ x)\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n\n// ============ G. SuperF Additions ============\n\n// G1\ndef z f x = x\n//│ z: anything -> 'a -> 'a\n//│  = [Function: z3]\n\n// G2\ndef s n f x = f (n f x)\n//│ s: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│  = [Function: s3]\n\n// G3\nn3 = s (s (s z))\n//│ n3: ('a -> 'b & 'c -> 'a & 'd -> 'c) -> 'd -> 'b\n//│   = [Function (anonymous)]\n\n// G1A\nz: ChurchInt\n//│ res: ChurchInt\n//│    = [Function: z3]\n\n// G2A\ns: ChurchInt -> ChurchInt\n//│ res: ChurchInt -> ChurchInt\n//│    = [Function: s3]\n\n// G3A\nn3: ChurchInt\n//│ res: ChurchInt\n//│    = [Function (anonymous)]\n\n// G4\nfst (fst (fst (n3 (fun x -> (x, 0)) 1)))\n//│ res: 1\n//│    = 1\n\n(succ (succ zero)) (succ (succ zero))\n//│ res: ('M -> 'M) -> 'M -> 'M\n//│    = [Function (anonymous)]\n\n(s (s z)) (s (s z))\n//│ res: ('a -> ('a & 'b & 'c) & 'c -> ('a & 'c)) -> 'c -> 'b\n//│    = [Function (anonymous)]\n\n// G7\nrec def to_ch n = if n == 0 then z else s (to_ch (n - 1))\n//│ to_ch: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│      = [Function: to_ch3]\n\n// G7A\nto_ch: int -> ChurchInt\n//│ res: int -> ChurchInt\n//│    = [Function: to_ch3]\n\n// G8\nrec def id1 x = if true then x else id1 id1 x\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id14]\n\n// G9\nid1 id1\n//│ res: ('a & 'b) -> 'a\n//│   where\n//│     'a :> forall 'c 'd. ('a & 'b & 'c) -> ('a | 'd)\n//│        <: ((forall 'c 'd. 'c -> 'd) | 'b) -> 'a\n//│     'c :> 'c -> 'd\n//│        <: 'd\n//│     'd := 'c -> 'd\n//│    = [Function: id14]\n\n// Gn\n:e\nauto auto\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.1814: \tauto auto\n//│ ║          \t^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ║         \t                       ^^^^^^^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.163: \tdef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│ ╙──       \t                   ^^\n//│ res: error | 'b -> 'b\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// Gn+1\n:e\n(fun x -> x x) (fun x -> x x)\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1833: \t(fun x -> x x) (fun x -> x x)\n//│ ║          \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\n// Gn+2\n(fun x -> x x) (fun x -> x x)!\n//│ res: nothing\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/PolyParams.mls",
    "content": ":NoRecursiveTypes\n\n\ndef foo(f: forall 'a. 'a -> 'a) =\n  (f 1, f true)\n//│ foo: (forall 'a. 'a -> 'a) -> (1, true,)\n//│    = [Function: foo]\n\nfooid = foo id\n//│ fooid: (1, true,)\n//│      = [ 1, true ]\n\nfooid.0\nfooid.1\n//│ res: 1\n//│    = 1\n//│ res: true\n//│    = true\n\ndef foo(f: (forall 'A. 'A -> 'A) -> (forall 'B. 'B -> 'B)) =\n  id f id (f id)\n//│ foo: ((forall 'A. 'A -> 'A) -> (forall 'B. 'B -> 'B)) -> 'B0 -> 'B0\n//│    = [Function: foo1]\n\nfoo id\n//│ res: 'B -> 'B\n//│    = [Function: id]\n\nfoo id id\n//│ res: 'a -> 'a\n//│    = [Function: id]\n\n\n\ndef bui_ty: forall 'a. (forall 'b. 'a -> 'b) -> ()\n//│ bui_ty: (nothing -> nothing) -> ()\n//│       = <missing implementation>\n\n// :d\nbui_ty = bui_ty\n//│ (nothing -> nothing) -> ()\n//│   <:  bui_ty:\n//│ (nothing -> nothing) -> ()\n//│       = <no result>\n//│         bui_ty is not implemented\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/PolymorphicTypeAliases.mls",
    "content": ":NoJS\n\n\ntype F[A] = forall 'a. (A, 'a) -> (A, 'a)\n//│ Defined type alias F[=A]\n\nclass Test[B]\n  method M = (fun (x: B, y) -> (x, y)) : F[B]\n//│ Defined class Test[=B]\n//│ Defined Test.M: Test['B] -> F['B]\n\nclass Test2[B]\n  method M = id (fun x -> id (fun (x: B, y) -> (x, y)) : F[B])\n//│ Defined class Test2[=B]\n//│ Defined Test2.M: Test2['B] -> anything -> F['B]\n\ndef foo = forall 'a. (fun (x: 'a, y) -> (x, y)) : F['a]\n//│ foo: F['a]\n\n\ntype G[A] = forall 'a. (A, 'a)\n//│ Defined type alias G[+A]\n\ndef foo x = forall 'a. (x, x) : G['a]\n//│ foo: (??a & ??a0) -> G[nothing]\n\n:e\nfoo 1\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.28: \tfoo 1\n//│ ║        \t^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.28: \tfoo 1\n//│ ║        \t    ^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.24: \tdef foo x = forall 'a. (x, x) : G['a]\n//│ ║        \t                           ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.24: \tdef foo x = forall 'a. (x, x) : G['a]\n//│ ╙──      \t                           ^\n//│ res: error | G[nothing]\n\ndef foo = forall 'a. fun x -> (x, x) : G['a]\n//│ foo: (??a & 'a) -> G['a]\n\n:e\nfoo 1\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.48: \tfoo 1\n//│ ║        \t^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.48: \tfoo 1\n//│ ║        \t    ^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.44: \tdef foo = forall 'a. fun x -> (x, x) : G['a]\n//│ ║        \t                                  ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.44: \tdef foo = forall 'a. fun x -> (x, x) : G['a]\n//│ ╙──      \t                                  ^\n//│ res: error | G[1]\n\ndef foo x y = forall 'a. (x, y) : G['a]\n//│ foo: ??a -> ??a0 -> G[nothing]\n\ndef foo = forall 'a. fun (x, y) -> (x, y) : G['a]\n//│ foo: ('a, ??a,) -> G['a]\n\ndef foo = fun a -> forall 'a. fun (x, y) -> (x, y) : G['a]\n//│ foo: anything -> ('a, ??a,) -> G['a]\n\nfoo 1 (2, error)\n//│ res: G[2]\n\ndef foo = fun a -> forall 'a. fun x -> (x, error) : G['a]\n//│ foo: anything -> 'a -> G['a]\n\nfoo 1 2\n//│ res: G[2]\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Proofs.mls",
    "content": ":NoRecursiveTypes\n:NoConstrainedTypes\n:DontDistributeForalls\n\n\n// * Negation\ntype Not[A] = A -> nothing\n//│ Defined type alias Not[-A]\n\n// * Disjunction\nclass Left: { v: anything }\nclass Right: { v: anything }\ntype Either[A, B] = Left & { v: A } | Right & { v: B }\n//│ Defined class Left\n//│ Defined class Right\n//│ Defined type alias Either[+A, +B]\n\n// * Type of: excluded middle (EM)\ntype EM = forall 'a. Either['a, Not['a]]\n//│ Defined type alias EM\n\n// * Type of double negation elimination (DNE)\ntype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ Defined type alias DNE\n\n\n// * Proof that EN implies DNE\n// * In explicit type parameters syntax:\n// *   fun (em: forall[A]. Either[A, Not[A]]) ->\n// *      forall[A]. fun (nna: Not[Not[A]]) -> (em[A] match Left a -> a; Right na -> nna na)\ndef EM_to_DNE em nna =\n  case em of Left -> em.v, Right -> nna em.v\n//│ EM_to_DNE: ((Left with {v: 'v}) | (Right with {v: 'v0})) -> (forall 'a. ('v0 -> 'a) -> ('v | 'a))\n//│          = [Function: EM_to_DNE]\n\n// * This requires distributivity or retyping with constrained types\n:e\nEM_to_DNE: EM -> DNE\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.38: \tEM_to_DNE: EM -> DNE\n//│ ║        \t^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                              ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                                      ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this field selection:\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                                        ^^^^\n//│ ╟── • this reference:\n//│ ║  l.38: \tEM_to_DNE: EM -> DNE\n//│ ║        \t^^^^^^^^^\n//│ ╟── • this applied expression:\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                                    ^^^\n//│ ╟── • this field selection:\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ╙──      \t                     ^^^^\n//│ res: EM -> DNE\n//│    = [Function: EM_to_DNE]\n\n\n// * Proof that EN implies DNE, annotated\ndef EM_to_DNE_A0 (em: EM) nna =\n  case em of Left -> em.v, Right -> nna em.v\n//│ EM_to_DNE_A0: EM -> (forall 'v. (Not['v] -> 'v) -> 'v)\n//│             = [Function: EM_to_DNE_A0]\n\nEM_to_DNE_A0: EM -> DNE\n//│ res: EM -> DNE\n//│    = [Function: EM_to_DNE_A0]\n\n\n// * This one still requires distributivity or constrained types\n\ndef EM_to_DNE_A1 em =\n  let poly (nna: Not[Not['A]]) = case em of Left -> em.v, Right -> nna em.v\n  in poly\n//│ EM_to_DNE_A1: ((Left with {v: 'v}) | Right & {v: Not['A]}) -> Not[Not['A]] -> 'v\n//│             = [Function: EM_to_DNE_A1]\n\n:e\nEM_to_DNE_A1: EM -> DNE\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.85: \tEM_to_DNE_A1: EM -> DNE\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                              ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                                      ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.80: \t  in poly\n//│ ║        \t     ^^^^\n//│ ╟── • this reference:\n//│ ║  l.85: \tEM_to_DNE_A1: EM -> DNE\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── • this field selection:\n//│ ║  l.79: \t  let poly (nna: Not[Not['A]]) = case em of Left -> em.v, Right -> nna em.v\n//│ ╙──      \t                                                    ^^^^\n//│ res: EM -> DNE\n//│    = [Function: EM_to_DNE_A1]\n\n\n// * Proof that DNE implies EM\n// * In explicit type parameters syntax:\n// *   (dne: forall[A]. Not[Not[A]] -> A) -> forall[A].\n// *      dne[Either[A, Not[A]]] (fun (not_em: Not[Either[A, Not[A]]]) ->\n// *        not_em (Right (fun a -> n_em (Left a)))\n// *      )\ndef DNE_to_EM dne =\n  dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ DNE_to_EM: ((forall 'v 'a 'b. ((Left with {v: 'v}) -> 'a & (Right & {v: 'v -> 'a}) -> 'b) -> 'b) -> 'c) -> 'c\n//│          = [Function: DNE_to_EM]\n\n// * Requires distributivity because we currently don't generalize function bodies\n:e\nDNE_to_EM: DNE -> EM\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.122: \tDNE_to_EM: DNE -> EM\n//│ ║         \t^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                                    ^^\n//│ ╟── back into type variable `'a0`\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                 ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.122: \tDNE_to_EM: DNE -> EM\n//│ ║         \t^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.116: \t  dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ ╙──       \t                                                          ^^^^^^^^^^^^^^\n//│ res: DNE -> EM\n//│    = [Function: DNE_to_EM]\n\ndef DNE_to_EM_let dne =\n  let poly = dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n  in poly\n//│ DNE_to_EM_let: ((forall 'v 'a 'b. ((Left with {v: 'v}) -> 'a & (Right & {v: 'v -> 'a}) -> 'b) -> 'b) -> 'c) -> 'c\n//│              = [Function: DNE_to_EM_let]\n\n// * This one used to work because we used let polymorphism\n// * Stopped working after \"sound extrusion\", but works with distrib (see below)\n:e\nDNE_to_EM_let: DNE -> EM\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.151: \tDNE_to_EM_let: DNE -> EM\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                                    ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                 ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.143: \t  let poly = dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ ║         \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.144: \t  in poly\n//│ ║         \t     ^^^^\n//│ ╟── • this reference:\n//│ ║  l.151: \tDNE_to_EM_let: DNE -> EM\n//│ ╙──       \t^^^^^^^^^^^^^\n//│ res: DNE -> EM\n//│    = [Function: DNE_to_EM_let]\n\n\n// * Note: this doesn't help\n\ndef DNE_to_EM_A0 (dne: DNE) =\n  dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ DNE_to_EM_A0: DNE -> ((Left with {v: 'v}) | Right & {v: 'v -> nothing})\n//│             = [Function: DNE_to_EM_A0]\n\n:e\nDNE_to_EM_A0: DNE -> EM\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.183: \tDNE_to_EM_A0: DNE -> EM\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                                    ^^\n//│ ╟── back into type variable `'a0`\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                 ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.183: \tDNE_to_EM_A0: DNE -> EM\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.178: \t  dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ ╙──       \t                                                          ^^^^^^^^^^^^^^\n//│ res: DNE -> EM\n//│    = [Function: DNE_to_EM_A0]\n\n\n// * Note: this doesn't help either\n\ntype EM_of[A] = Either[A, Not[A]]\n//│ Defined type alias EM_of[=A]\n\ndef DNE_to_EM_A1 dne =\n  (dne: Not[Not[EM_of['a]]] -> EM_of['a]) (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ DNE_to_EM_A1: (Not[Not[EM_of['a]]] -> EM_of['a]) -> EM_of['a]\n//│             = [Function: DNE_to_EM_A1]\n\n:e\nDNE_to_EM_A1: DNE -> EM\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.215: \tDNE_to_EM_A1: DNE -> EM\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                                    ^^\n//│ ╟── back into type variable `'a0`\n//│ ║  l.210: \t  (dne: Not[Not[EM_of['a]]] -> EM_of['a]) (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ ║         \t                                     ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.210: \t  (dne: Not[Not[EM_of['a]]] -> EM_of['a]) (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.215: \tDNE_to_EM_A1: DNE -> EM\n//│ ╙──       \t^^^^^^^^^^^^\n//│ res: DNE -> EM\n//│    = [Function: DNE_to_EM_A1]\n\n\n// * Note: this doesn't help either\n\ndef helper: Not[Either['A, Not['A]]] -> 'A -> nothing\ndef helper not_em = fun a -> not_em (Left { v = a })\n//│ helper: Not[Either['A, Not['A]]] -> 'A -> nothing\n//│       = <missing implementation>\n//│ ((Left with {v: 'v}) -> 'a) -> 'v -> 'a\n//│   <:  helper:\n//│ Not[Either['A, Not['A]]] -> 'A -> nothing\n//│       = [Function: helper]\n\ndef DNE_to_EM_A2 (dne: DNE) =\n  dne (fun (not_em: Not[Either['A, Not['A]]]) -> not_em (Right { v = helper not_em }))\n//│ DNE_to_EM_A2: DNE -> Either['A, Not['A]]\n//│             = [Function: DNE_to_EM_A2]\n\n// * ^ Note how this is not `DNE -> forall 'A. (Either['A, Not['A]] | 'a)`?\n\n:e\nDNE_to_EM_A2: DNE -> EM\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.255: \tDNE_to_EM_A2: DNE -> EM\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                                    ^^\n//│ ╟── back into type variable `'a0`\n//│ ║  l.248: \t  dne (fun (not_em: Not[Either['A, Not['A]]]) -> not_em (Right { v = helper not_em }))\n//│ ║         \t                                       ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.248: \t  dne (fun (not_em: Not[Either['A, Not['A]]]) -> not_em (Right { v = helper not_em }))\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.255: \tDNE_to_EM_A2: DNE -> EM\n//│ ╙──       \t^^^^^^^^^^^^\n//│ res: DNE -> EM\n//│    = [Function: DNE_to_EM_A2]\n\n\n\n// * === Usages ===\n\n\n:NoJS\n\ndef dne: DNE\ndef em: EM\n//│ dne: DNE\n//│ em: EM\n\n\nEM_to_DNE em\n//│ res: (Not['v] -> 'a) -> ('v | 'a)\n\nDNE_to_EM dne\n//│ res: (Left with {v: 'v}) | Right & {v: 'v -> nothing}\n\n\nEM_to_DNE_A0 em\n//│ res: (Not['v] -> 'v) -> 'v\n\nEM_to_DNE_A1 em\n//│ res: Not[Not['v]] -> 'v\n\n\nDNE_to_EM_A0 dne\n//│ res: (Left with {v: 'v}) | Right & {v: 'v -> nothing}\n\nDNE_to_EM_A1 dne\n//│ res: EM_of['a]\n\nDNE_to_EM_A2 dne\n//│ res: Either['A, Not['A]]\n\n\ndef to_DNE: DNE\nto_DNE nna = case em of Left -> em.v, Right -> nna em.v\n//│ to_DNE: DNE\n//│ (Not['v] -> 'v) -> 'v\n//│   <:  to_DNE:\n//│ DNE\n\ndef to_EM: EM\nto_EM = dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ to_EM: EM\n//│ (Left with {v: 'v}) | Right & {v: 'v -> nothing}\n//│   <:  to_EM:\n//│ EM\n\n\n\n// * === With Distributivity ===\n\n:DistributeForalls\n\n\nEM_to_DNE: EM -> DNE\nDNE_to_EM: DNE -> EM\nDNE_to_EM_let: DNE -> EM\n//│ res: EM -> DNE\n//│ res: DNE -> EM\n//│ res: DNE -> EM\n\nEM_to_DNE_A0: EM -> DNE\nDNE_to_EM_A0: DNE -> EM\n//│ res: EM -> DNE\n//│ res: DNE -> EM\n\nEM_to_DNE_A1: EM -> DNE\n//│ res: EM -> DNE\n\nDNE_to_EM_A1: DNE -> EM\n//│ res: DNE -> EM\n\n\nEM_to_DNE em\n//│ res: (Not['v] -> 'a) -> ('v | 'a)\n\nDNE_to_EM dne\n//│ res: (Left with {v: 'v}) | Right & {v: 'v -> nothing}\n\n\n\n\n// * === With Constrained Types ===\n\n:DontDistributeForalls\n:ConstrainedTypes\n\n\n// * We still need to retype these definitions\n\n:e\nEM_to_DNE: EM -> DNE\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.370: \tEM_to_DNE: EM -> DNE\n//│ ║         \t^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                              ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                     ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this field selection:\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                                        ^^^^\n//│ ╟── • this reference:\n//│ ║  l.370: \tEM_to_DNE: EM -> DNE\n//│ ║         \t^^^^^^^^^\n//│ ╟── • this field selection:\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                     ^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ╙──      \t                                    ^^\n//│ res: EM -> DNE\n\n:e\nEM_to_DNE: EM -> DNE\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.396: \tEM_to_DNE: EM -> DNE\n//│ ║         \t^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                              ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                     ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this field selection:\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                                        ^^^^\n//│ ╟── • this reference:\n//│ ║  l.396: \tEM_to_DNE: EM -> DNE\n//│ ║         \t^^^^^^^^^\n//│ ╟── • this field selection:\n//│ ║  l.32: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║        \t                     ^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ╙──      \t                                    ^^\n//│ res: EM -> DNE\n\n\n// * Now retyping them\n\ndef EM_to_DNE em nna =\n  case em of Left -> em.v, Right -> nna em.v\n//│ EM_to_DNE: 'a -> (forall 'v 'v0. ('v0 -> 'v) -> 'v\n//│   where\n//│     'a <: (Left with {v: 'v}) | (Right with {v: 'v0}))\n\n:e // * Still needs distrib! (after \"sound extrusion\")\nEM_to_DNE: EM -> DNE\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.431: \tEM_to_DNE: EM -> DNE\n//│ ║         \t^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                              ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.23: \ttype DNE = forall 'a. Not[Not['a]] -> 'a\n//│ ║        \t                                      ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.424: \tdef EM_to_DNE em nna =\n//│ ║         \t                 ^^^^^\n//│ ║  l.425: \t  case em of Left -> em.v, Right -> nna em.v\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.431: \tEM_to_DNE: EM -> DNE\n//│ ║         \t^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ╙──      \t                                    ^^\n//│ res: EM -> DNE\n\ndef DNE_to_EM dne =\n  dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ DNE_to_EM: ((forall 'a 'b. ((Right & {v: forall 'v 'c. 'v -> 'c\n//│   where\n//│     'a <: (Left with {v: 'v}) -> 'c}) -> 'b & 'a) -> 'b) -> 'd) -> 'd\n\n:e // * Still needs distrib! (after \"sound extrusion\")\nDNE_to_EM: DNE -> EM\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.462: \tDNE_to_EM: DNE -> EM\n//│ ║         \t^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.19: \ttype EM = forall 'a. Either['a, Not['a]]\n//│ ║        \t                                    ^^\n//│ ╟── back into type variable `'a0`\n//│ ║  l.456: \t  dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ ║         \t                                                                     ^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.462: \tDNE_to_EM: DNE -> EM\n//│ ║         \t^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.456: \t  dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) }))\n//│ ╙──       \t                                                          ^^^^^^^^^^^^^^\n//│ res: DNE -> EM\n\n// * They work with distrib:\n:DistributeForalls\nEM_to_DNE: EM -> DNE\nDNE_to_EM: DNE -> EM\n//│ res: EM -> DNE\n//│ res: DNE -> EM\n:DontDistributeForalls\n\n\n\n// * === === ===\n\n\n\n// * [Some old notes, using obsolete notation:]\n// Type inference for:  DNE_to_EM dne\n//    'fun (('a -> bot) -> bot) -> 'a  <:  (''fun ((Left ''a -> ''b) & (Right (''a -> ''b) -> ''c)) -> ''c) -> ?d\n//    ((?a -> bot) -> bot) -> ?a  <:  (''fun ((Left ''a -> ''b) & (Right (''a -> ''b) -> ''c)) -> ''c) -> ?d)\n//    ?a  <:  ?d  AND  ''fun ((Left ''a -> ''b) & (Right (''a -> ''b) -> ''c)) -> ''c  <:  ((?a -> bot) -> bot)\n//    ((Left ?a2 -> ?b) & (Right (?a2 -> ?b) -> ?c)) -> ?c  <:  ((?a2 -> bot) -> bot)\n//    ?c  <:  bot  AND  (?a -> bot)  <:  (Left ?a2 -> ?b) & (Right (?a2 -> ?b) -> ?c)\n//    (?a -> bot)  <:  (Left ?a2 -> ?b)  AND  (?a -> bot)  <:  (Right (?a2 -> ?b) -> ?c)\n//    Left ?a2  <:  ?a  AND  Right (?a2 -> ?b)  <:  ?a\n// Result (generalized):\n//    Left 'a | Right ('a -> Bot)\n// i.e., the excluded middle for any 'a !!\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_Classes.mls",
    "content": "// * Adaptation of QML's original existentials example; using encoded existentials and classes\n\n:NoRecursiveTypes\n\n\n\nclass ArraysRep[A, Rep]\n  method Init: A -> Rep\n  method Sub: Rep -> int -> A\n  method Update: Rep -> int -> A -> Rep\n  method Fold: (A -> 'b -> 'b) -> 'b -> Rep -> 'b\n//│ Defined class ArraysRep[=A, =Rep]\n//│ Declared ArraysRep.Init: ArraysRep['A, 'Rep] -> 'A -> 'Rep\n//│ Declared ArraysRep.Sub: ArraysRep['A, 'Rep] -> 'Rep -> int -> 'A\n//│ Declared ArraysRep.Update: ArraysRep['A, 'Rep] -> 'Rep -> int -> 'A -> 'Rep\n//│ Declared ArraysRep.Fold: ArraysRep['A, 'Rep] -> ('A -> 'b -> 'b) -> 'b -> 'Rep -> 'b\n\nclass ArraysImpl[A, Rep]: ArraysRep[A, Rep] & {\n    init: A -> Rep;\n    sub: Rep -> int -> A;\n    update: Rep -> int -> A -> Rep;\n    fold: forall 'b. (A -> 'b -> 'b) -> 'b -> Rep -> 'b\n  }\n  method Init = this.init\n  method Sub = this.sub\n  method Update = this.update\n  method Fold = this.fold\n//│ Defined class ArraysImpl[=A, =Rep]\n//│ Defined ArraysImpl.Init: ArraysImpl['A, 'Rep] -> 'A -> 'Rep\n//│ Defined ArraysImpl.Sub: ArraysImpl['A, 'Rep] -> 'Rep -> int -> 'A\n//│ Defined ArraysImpl.Update: ArraysImpl['A, 'Rep] -> 'Rep -> int -> 'A -> 'Rep\n//│ Defined ArraysImpl.Fold: ArraysImpl['A, 'Rep] -> ('A -> 'b -> 'b) -> 'b -> 'Rep -> 'b\n\ntype ArraysRepConsumer[A, R] = forall 'rep. ArraysRep[A, 'rep] -> R\n//│ Defined type alias ArraysRepConsumer[=A, +R]\n\ntype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ Defined type alias Arrays[=A]\n\n\n\nbaseImpl = ArraysImpl {\n    init   = fun a -> a;\n    sub    = fun r -> fun (i : int) -> r;\n    update = fun r -> fun (i : int) -> fun a -> a;\n    fold   = fun f -> fun b -> fun r -> f r b\n  }\n//│ baseImpl: ArraysImpl['Rep, 'Rep] with {\n//│   fold: forall 'a 'b 'c. ('a -> 'b -> 'c) -> 'b -> 'a -> 'c,\n//│   init: forall 'd. 'd -> 'd,\n//│   sub: forall 'e. 'e -> int -> 'e,\n//│   update: forall 'f. anything -> int -> 'f -> 'f\n//│ }\n//│         = ArraysImpl {\n//│             init: [Function: init],\n//│             sub: [Function: sub],\n//│             update: [Function: update],\n//│             fold: [Function: fold]\n//│           }\n\ndef base: Arrays['a]\ndef base f = f baseImpl\n//│ base: Arrays['a]\n//│     = <missing implementation>\n//│ ((forall 'Rep. ArraysImpl['Rep, 'Rep] with {\n//│   fold: forall 'a 'b 'c. ('a -> 'b -> 'c) -> 'b -> 'a -> 'c,\n//│   init: forall 'd. 'd -> 'd,\n//│   sub: forall 'e. 'e -> int -> 'e,\n//│   update: forall 'f. anything -> int -> 'f -> 'f\n//│ }) -> 'g) -> 'g\n//│   <:  base:\n//│ Arrays['a]\n//│     = [Function: base]\n\n\n\n// * Notice the strange `anything` and `nothing` occurrences...\n// * They don't seem to cause problems. Maybe simplification bug artifacts?\ndef simpleStepImpl arrImpl = ArraysImpl {\n    init   = fun a -> (arrImpl.Init a, \"initialized\");\n    sub    = fun ((r0, r1)) -> fun i -> arrImpl.Sub r0 i;\n    update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, \"updated\");\n    fold   = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f b r0\n  }\n//│ simpleStepImpl: ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a out 'Rep | 'Rep0] -> (ArraysImpl['A1, 'Rep1] with {\n//│   fold: forall 'b. ('A0 -> 'b -> 'b) -> 'b -> (('Rep0, anything,),) -> 'b,\n//│   init: 'A -> ('Rep, \"initialized\",),\n//│   sub: (('Rep0, anything,),) -> int -> 'A0,\n//│   update: forall 'c. (('Rep0 & 'c, anything,),) -> int -> 'A -> ('Rep | 'c, \"updated\",)\n//│ })\n//│ where\n//│   'Rep1 :> ('Rep | 'd, \"initialized\" | \"updated\",)\n//│         <: ('Rep0 & 'a, anything,)\n//│   'a <: 'Rep0 & 'd\n//│   'd :> 'Rep\n//│      <: 'Rep0 & 'a\n//│   'A1 :> 'A0\n//│       <: 'A\n//│               = [Function: simpleStepImpl]\n\ndef simpleStepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ simpleStepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│                  = <missing implementation>\n\nsimpleStepImpl_ty = simpleStepImpl\n//│ ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a out 'Rep | 'Rep0] -> (ArraysImpl['A1, 'Rep1] with {\n//│   fold: forall 'b. ('A0 -> 'b -> 'b) -> 'b -> (('Rep0, anything,),) -> 'b,\n//│   init: 'A -> ('Rep, \"initialized\",),\n//│   sub: (('Rep0, anything,),) -> int -> 'A0,\n//│   update: forall 'c. (('Rep0 & 'c, anything,),) -> int -> 'A -> ('Rep | 'c, \"updated\",)\n//│ })\n//│ where\n//│   'Rep1 :> ('Rep | 'd, \"initialized\" | \"updated\",)\n//│         <: ('Rep0 & 'a, anything,)\n//│   'a <: 'Rep0 & 'd\n//│   'd :> 'Rep\n//│      <: 'Rep0 & 'a\n//│   'A1 :> 'A0\n//│       <: 'A\n//│   <:  simpleStepImpl_ty:\n//│ ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│                  = [Function: simpleStepImpl]\n\n// * This is weird.\n// * It seems to be the same subtype check as above, but it goes of the rails (see stats)\n// * Also weird: this type checks efficiently when the file is typed with `:ConstrainedTypes`\n:e\n:stats\nsimpleStepImpl : ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?a ?b. ?a -> ?b <: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]` took too many steps and ran out of fuel (10000)\n//│ ║  l.129: \tsimpleStepImpl : ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│    = [Function: simpleStepImpl]\n//│ constrain calls  : 9926\n//│ annoying  calls  : 78\n//│ subtyping calls  : 28186\n// * Note that the above incidentally can be checked using recursive types\n:RecursiveTypes\n:stats\nsimpleStepImpl : ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ res: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│    = [Function: simpleStepImpl]\n//│ constrain calls  : 432\n//│ annoying  calls  : 104\n//│ subtyping calls  : 3111\n:NoRecursiveTypes\n\n// * Apparently, it's due to excessive extrusion due to the type annot not being generalized!\n:stats\nsimpleStepImpl : forall 'a 'r. ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ res: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│    = [Function: simpleStepImpl]\n//│ constrain calls  : 576\n//│ annoying  calls  : 104\n//│ subtyping calls  : 1183\n\n\n\n// * First approach to implementing step\n\ndef simpleStep: Arrays['a] -> Arrays['a]\n//│ simpleStep: Arrays['a] -> Arrays['a]\n//│           = <missing implementation>\n\n// * Note: this one fails to type check when the file is typed with `:ConstrainedTypes`\ndef simpleStep arr = arr (fun impl -> fun (k: ArraysRepConsumer['a, 'r]) -> k (simpleStepImpl impl))\n//│ ((forall 'A 'A0 'A1 'Rep 'a. ArraysRep[in 'A & 'A0 & 'A1 out 'A | 'A0, 'Rep] -> ArraysRepConsumer['A, 'a] -> 'a) -> 'b) -> 'b\n//│   where\n//│     'A :> 'A0\n//│        <: 'A1\n//│     'A1 <: 'A\n//│   <:  simpleStep:\n//│ Arrays['a] -> Arrays['a]\n//│           = [Function: simpleStep]\n\n\n// * Second approach to implementing step\n\ndef simpleStep2: Arrays['a] -> Arrays['a]\n//│ simpleStep2: Arrays['a] -> Arrays['a]\n//│            = <missing implementation>\n\ndef simpleStep2 arr (k: ArraysRepConsumer['a, 'r]) = arr (fun impl -> k (simpleStepImpl impl))\n//│ ((forall 'Rep. ArraysRep['a, 'Rep] -> 'r) -> 'b) -> ArraysRepConsumer['a, 'r] -> 'b\n//│   <:  simpleStep2:\n//│ Arrays['a] -> Arrays['a]\n//│            = [Function: simpleStep2]\n\n\n\nsb = simpleStep base\n//│ sb: Arrays['a]\n//│   = [Function (anonymous)]\n\nsb (fun arr -> arr.Init true)\n//│ res: ??Rep\n//│    = [ true, 'initialized' ]\n\nsb (fun arr -> arr.Sub (arr.Init true) 1)\n//│ res: true\n//│    = true\n\n:e // * Type error is expected – argument order confusion\nsb (fun arr -> arr.Sub 0 (arr.Init true))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.206: \tsb (fun arr -> arr.Sub 0 (arr.Init true))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'Rep` is not an instance of type `int`\n//│ ║  l.37: \ttype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ ║        \t                                            ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.9: \t  method Sub: Rep -> int -> A\n//│ ║       \t                     ^^^\n//│ ╟── from application:\n//│ ║  l.206: \tsb (fun arr -> arr.Sub 0 (arr.Init true))\n//│ ║         \t                          ^^^^^^^^^^^^^\n//│ ╟── Note: quantified type variable 'Rep is defined at:\n//│ ║  l.37: \ttype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ ║        \t                         ^^^^\n//│ ╟──       class type parameter Rep is defined at:\n//│ ║  l.7: \tclass ArraysRep[A, Rep]\n//│ ╙──     \t                   ^^^\n//│ res: error | true\n//│ Runtime error:\n//│   TypeError: number 0 is not iterable (cannot read property Symbol(Symbol.iterator))\n\nsb (fun arr -> arr.Update (arr.Init true) 1 false)\n//│ res: anything\n//│    = [ false, 'updated' ]\n\n:e // * Rightly prevent skolem confusion\nsb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true)))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.234: \tsb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true)))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'Rep` leaks out of its scope\n//│ ║  l.37: \ttype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ ║        \t                                            ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.234: \tsb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true)))\n//│ ║         \t                                             ^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.193: \tsb = simpleStep base\n//│ ║         \t     ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.234: \tsb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true)))\n//│ ║         \t                ^^\n//│ ╟── • this reference:\n//│ ║  l.234: \tsb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true)))\n//│ ║         \t                                ^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.234: \tsb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true)))\n//│ ╙──       \t                                             ^^^^^^^^^^^^^^\n//│ res: error | int -> anything -> anything\n//│    = [Function (anonymous)]\n\nsb (fun arr ->\n    let r2 = arr.Update (arr.Init true) 1 false\n    in (arr.Sub r2 0, arr.Sub r2 1)\n  )\n//│ res: (Bool, Bool,)\n//│    = [ false, false ]\n\n\n\n// * The unannotated versions of `step` do not work, as expected\n\n:e\ndef simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl))\n//│ ((forall 'A 'A0 'A1 'Rep 'Rep0 'a 'c 'd. ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a out 'Rep | 'Rep0] -> ((forall 'Rep1. ArraysImpl['A1, 'Rep1] with {\n//│   fold: forall 'b. ('A0 -> 'b -> 'b) -> 'b -> (('Rep0, anything,),) -> 'b,\n//│   init: 'A -> ('Rep, \"initialized\",),\n//│   sub: (('Rep0, anything,),) -> int -> 'A0,\n//│   update: forall 'e. (('Rep0 & 'e, anything,),) -> int -> 'A -> ('Rep | 'e, \"updated\",)\n//│ }) -> 'd) -> 'd) -> 'f) -> 'f\n//│ where\n//│   'Rep1 :> ('Rep | 'c, \"initialized\" | \"updated\",)\n//│         <: ('Rep0 & 'a, anything,)\n//│   'a <: 'Rep0 & 'c\n//│   'c :> 'Rep\n//│      <: 'Rep0 & 'a\n//│   'A1 :> 'A0\n//│       <: 'A\n//│   <:  simpleStep:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.272: \tdef simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'Rep` leaks out of its scope\n//│ ║  l.37: \ttype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ ║        \t                                            ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.272: \tdef simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl))\n//│ ║         \t                     ^^^\n//│ ╟── • this function:\n//│ ║  l.272: \tdef simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl))\n//│ ║         \t                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.81: \t    sub    = fun ((r0, r1)) -> fun i -> arrImpl.Sub r0 i;\n//│ ╙──      \t                                                    ^^\n//│           = [Function: simpleStep1]\n\n:e\ndef simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl))\n//│ ((ArraysRep[out 'A, out 'Rep] -> 'a) -> 'c) -> ((forall 'Rep0. ArraysImpl[in 'A & 'A0 out 'A0, 'Rep0] with {\n//│   fold: forall 'b. (nothing -> 'b -> 'b) -> 'b -> (('Rep, anything,),) -> 'b,\n//│   init: 'A -> (nothing, \"initialized\",),\n//│   sub: (('Rep, anything,),) -> int -> nothing,\n//│   update: forall 'd. (('Rep & 'd, anything,),) -> int -> 'A -> ('d, \"updated\",)\n//│ }) -> 'a) -> 'c\n//│ where\n//│   'Rep0 :> ('e | 'f, \"initialized\" | \"updated\",)\n//│         <: ('Rep & 'g & 'h, anything,)\n//│   'f :> 'e\n//│      <: 'Rep & 'g & 'h\n//│   'h <: 'Rep & 'f\n//│   'e <: 'Rep & 'g\n//│   'g <: 'Rep & 'e\n//│   <:  simpleStep2:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.308: \tdef simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'Rep` leaks out of its scope\n//│ ║  l.37: \ttype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ ║        \t                                            ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.83: \t    fold   = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f b r0\n//│ ║        \t                                                 ^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.308: \tdef simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl))\n//│ ║         \t                                                           ^^^^\n//│ ╟── • this applied expression:\n//│ ║  l.308: \tdef simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl))\n//│ ╙──       \t                        ^^^\n//│            = [Function: simpleStep21]\n\n\n\n// * Now for the real version of `step`\n\n\n:escape\ndef Math: nothing\n//│ Math: nothing\n//│     = <missing implementation>\n\ndef div: int -> int -> int\ndef div a b = Math.trunc(a/b)\n//│ div: int -> int -> int\n//│    = <missing implementation>\n//│ number -> number -> nothing\n//│   <:  div:\n//│ int -> int -> int\n//│    = [Function: div1]\n\ndef mod: int -> int -> int\nrec def mod a b = if a < b then a else mod (a - b) b\n//│ mod: int -> int -> int\n//│    = <missing implementation>\n//│ int -> int -> int\n//│   <:  mod:\n//│ int -> int -> int\n//│    = [Function: mod]\n\ndef stepImpl arrImpl = ArraysImpl {\n    init = fun a -> (arrImpl.Init a, arrImpl.Init a);\n    sub = fun ((r0, r1)) -> fun i ->\n      if mod i 2 == 0\n      then arrImpl.Sub r0 (div i 2)\n      else arrImpl.Sub r1 (div i 2);\n    update = fun ((r0, r1)) -> fun i -> fun a ->\n      if mod i 2 == 0\n      then (arrImpl.Update r0 (div i 2) a, r1)\n      else (r0, arrImpl.Update r1 (div i 2) a);\n    fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f (arrImpl.Fold f b r0) r1\n  }\n//│ stepImpl: ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a & 'c out 'Rep | 'Rep0] -> (ArraysImpl['A1, 'Rep1] with {\n//│   fold: forall 'b 'b0. ('A0 -> 'b -> 'b & 'A0 -> 'b0 -> ('b & 'b0)) -> ('b & 'b0) -> (('Rep0, 'Rep0,),) -> 'b,\n//│   init: 'A -> ('Rep, 'Rep,),\n//│   sub: (('Rep0, 'Rep0,),) -> int -> 'A0,\n//│   update: forall 'd 'e. (('Rep0 & 'd, 'Rep0 & 'e,),) -> int -> 'A -> ('Rep | 'd, 'Rep | 'e,)\n//│ })\n//│ where\n//│   'Rep1 :> ('Rep | 'a | 'f, 'Rep | 'g | 'c,)\n//│         <: ('Rep0 & 'a, 'Rep0 & 'c,)\n//│   'c <: 'Rep0 & 'g\n//│   'g :> 'Rep\n//│      <: 'Rep0 & 'c\n//│   'a <: 'Rep0 & 'f\n//│   'f :> 'Rep\n//│      <: 'Rep0 & 'a\n//│   'A1 :> 'A0\n//│       <: 'A\n//│         = [Function: stepImpl]\n\n\ndef step: Arrays['a] -> Arrays['a]\n//│ step: Arrays['a] -> Arrays['a]\n//│     = <missing implementation>\n\ndef step arr = arr (fun impl -> fun (k: ArraysRepConsumer['a, 'r]) -> k (stepImpl impl))\n//│ ((forall 'A 'A0 'A1 'Rep 'a. ArraysRep[in 'A & 'A0 & 'A1 out 'A | 'A0, 'Rep] -> ArraysRepConsumer['A, 'a] -> 'a) -> 'b) -> 'b\n//│   where\n//│     'A :> 'A0\n//│        <: 'A1\n//│     'A1 <: 'A\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step]\n\n\ndef step2: Arrays['a] -> Arrays['a]\n//│ step2: Arrays['a] -> Arrays['a]\n//│      = <missing implementation>\n\ndef step2 arr (k: ArraysRepConsumer['a, 'r]) = arr (fun impl -> k (simpleStepImpl impl))\n//│ ((forall 'Rep. ArraysRep['a, 'Rep] -> 'r) -> 'b) -> ArraysRepConsumer['a, 'r] -> 'b\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step2]\n\n\nssb = step (step base)\n//│ ssb: Arrays['a]\n//│    = [Function (anonymous)]\n\nssb (fun arr ->\n    let r2 = arr.Update (arr.Init true) 1 false\n    in (arr.Sub r2 0, arr.Sub r2 1)\n  )\n//│ res: (Bool, Bool,)\n//│    = [ true, false ]\n\n\nssb = step2 (step2 base)\n//│ ssb: Arrays['a]\n//│    = [Function (anonymous)]\n\nssb (fun arr ->\n    let r2 = arr.Update (arr.Init true) 1 false\n    in (arr.Sub r2 0, arr.Sub r2 1)\n  )\n//│ res: (Bool, Bool,)\n//│    = [ false, false ]\n\n\nrec def mkMonoArray n =\n  if n == 0 then base else step (mkMonoArray(n - 1))\n//│ mkMonoArray: int -> Arrays['a]\n//│            = [Function: mkMonoArray]\n\nsnb = mkMonoArray 5\n//│ snb: Arrays['a]\n//│    = [Function (anonymous)]\n\nsnb (fun arr -> arr.Init true)\n//│ res: anything\n//│    = [\n//│        [ [ [Array], [Array] ], [ [Array], [Array] ] ],\n//│        [ [ [Array], [Array] ], [ [Array], [Array] ] ]\n//│      ]\n\n\nrec def mkMonoArray n =\n  if n == 0 then base else step2 (mkMonoArray(n - 1))\n//│ mkMonoArray: int -> Arrays['a]\n//│            = [Function: mkMonoArray1]\n\nsnb = mkMonoArray 5\n//│ snb: Arrays['a]\n//│    = [Function (anonymous)]\n\nsnb (fun arr -> arr.Init true)\n//│ res: anything\n//│    = [ [ [ [Array], 'initialized' ], 'initialized' ], 'initialized' ]\n\n\n\n// * From the paper:\n// let mkPolyArray n = {∀α(∃ρ.∀β.sig(α,ρ,β))} (mkMonoArray n)\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_Classes_min.mls",
    "content": "// * Some minimized failures\n\n:NoRecursiveTypes\n\n\nclass ArraysRep[A, Rep]\n  method Update: Rep -> int -> A -> Rep\n//│ Defined class ArraysRep[-A, =Rep]\n//│ Declared ArraysRep.Update: ArraysRep['A, 'Rep] -> 'Rep -> int -> 'A -> 'Rep\n\nclass ArraysImpl[A, Rep]: ArraysRep[A, Rep] & {\n    update: Rep -> int -> A -> Rep\n  }\n  method Update = this.update\n//│ Defined class ArraysImpl[-A, =Rep]\n//│ Defined ArraysImpl.Update: ArraysImpl['A, 'Rep] -> 'Rep -> int -> 'A -> 'Rep\n\ntype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ Defined type alias Arrays[-A]\n\n\ndef simpleStepImpl arrImpl = ArraysImpl {\n    update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, \"updated\")\n  }\n//│ simpleStepImpl: ArraysRep['A, in 'Rep & 'a out 'Rep | 'Rep0] -> (ArraysImpl['A, 'Rep1] with {\n//│   update: forall 'b. (('Rep0 & 'b, anything,),) -> int -> 'A -> ('Rep | 'b, \"updated\",)\n//│ })\n//│ where\n//│   'Rep1 :> ('c, \"updated\",)\n//│         <: ('a, anything,)\n//│   'a <: 'Rep0 & 'c\n//│   'c :> 'Rep\n//│      <: 'a\n//│               = [Function: simpleStepImpl]\n\n\ndef arr: Arrays[int]\n//│ arr: Arrays[int]\n//│    = <missing implementation>\n\n\ndef mkArrays: ArraysImpl['a, 'r] -> Arrays['a]\nmkArrays impl k = k impl\n//│ mkArrays: ArraysImpl['a, 'r] -> Arrays['a]\n//│         = <missing implementation>\n//│ 'a -> ('a -> 'b) -> 'b\n//│   <:  mkArrays:\n//│ ArraysImpl['a, 'r] -> Arrays['a]\n//│         = [Function: mkArrays]\n\n\n// * Inconsistent bounds on 'Rep after type avoidance during extrusion (<- not sure comment is still current)\n:e\ndef stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.54: \tdef stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl))\n//│ ║        \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'Rep` leaks out of its scope\n//│ ║  l.18: \ttype Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r\n//│ ║        \t                                            ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.54: \tdef stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl))\n//│ ║        \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.54: \tdef stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl))\n//│ ║        \t              ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.23: \t    update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, \"updated\")\n//│ ╙──      \t                                                                 ^^\n//│ stepped: error\n//│        = <no result>\n//│          arr is not implemented\n\n\ndef stepped = arr (fun arrImpl -> fun (k: forall 'Rep. ArraysRep[int, 'Rep] -> 'r) -> k (simpleStepImpl arrImpl))\n//│ stepped: (forall 'Rep. ArraysRep[int, 'Rep] -> 'a) -> 'a\n//│        = <no result>\n//│          arr is not implemented\n\nstepped: Arrays[int]\n//│ res: Arrays[int]\n//│    = <no result>\n//│      stepped and arr are not implemented\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_Records_D.mls",
    "content": "// * Adaptation of QML's original existentials example; using encoded existentials and plain records\n\n:NoRecursiveTypes\n\n\n\n// *** Type definitions *** //\n\ntype ArraysImpl[A, Rep] = {\n    init: A -> Rep;\n    sub: Rep -> int -> A;\n    update: Rep -> int -> A -> Rep;\n    fold: forall 'b. (A -> 'b -> 'b) -> 'b -> Rep -> 'b\n  }\n//│ Defined type alias ArraysImpl[=A, =Rep]\n\ntype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ Defined type alias ArraysImplConsumer[=A, +R]\n\ntype Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r\n//│ Defined type alias Arrays[=A]\n\n\n\n// *** Base *** //\n\n\nbaseImpl = {\n    init   = fun a -> a;\n    sub    = fun r -> fun i -> r;\n    update = fun r -> fun i -> fun a -> a;\n    fold   = fun f -> fun b -> fun r -> f r b\n  }\n//│ baseImpl: {\n//│   fold: forall 'a 'b 'c. ('a -> 'b -> 'c) -> 'b -> 'a -> 'c,\n//│   init: forall 'd. 'd -> 'd,\n//│   sub: forall 'e. 'e -> anything -> 'e,\n//│   update: forall 'f. anything -> anything -> 'f -> 'f\n//│ }\n//│         = {\n//│             init: [Function: init],\n//│             sub: [Function: sub],\n//│             update: [Function: update],\n//│             fold: [Function: fold]\n//│           }\n\nbaseImpl : ArraysImpl['a, 'a]\n//│ res: ArraysImpl['a, 'a]\n//│    = {\n//│        init: [Function: init],\n//│        sub: [Function: sub],\n//│        update: [Function: update],\n//│        fold: [Function: fold]\n//│      }\n\ndef base: Arrays['a]\n//│ base: Arrays['a]\n//│     = <missing implementation>\n\n// * This works because `f` is used immediately, at the top level\n// * (not within a more polymorphic context),\n// * so we do not need first-class parametric polymorphism to type check the definition.\ndef base f = f baseImpl\n//│ ({\n//│   fold: forall 'a 'b 'c. ('a -> 'b -> 'c) -> 'b -> 'a -> 'c,\n//│   init: forall 'd. 'd -> 'd,\n//│   sub: forall 'e. 'e -> anything -> 'e,\n//│   update: forall 'f. anything -> anything -> 'f -> 'f\n//│ } -> 'g) -> 'g\n//│   <:  base:\n//│ Arrays['a]\n//│     = [Function: base]\n\n// * Also works, but not necessary\ndef base (f: ArraysImplConsumer['a, 'res]) = f baseImpl\n//│ ArraysImplConsumer['a, 'b] -> 'b\n//│   <:  base:\n//│ Arrays['a]\n//│     = [Function: base1]\n\n\n\n// *** Step *** //\n\n\ndef stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│            = <missing implementation>\n\n// * `arrImpl` is meant to be used polymorphically under lambdas, so it needs an annotation\ndef stepImpl (arrImpl: ArraysImpl['a, 'r]) = {\n    init   = fun a -> (arrImpl.init a, \"hi\");\n    sub    = fun ((r0, r1)) -> fun i -> arrImpl.sub r0 i;\n    update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.update r0 i a, \"hey\");\n    fold   = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.fold f b r0\n  }\n//│ stepImpl: ArraysImpl['a, 'r] -> {\n//│   fold: forall 'b. ('a -> 'b -> 'b) -> 'b -> (('r, anything,),) -> 'b,\n//│   init: 'a -> ('r, \"hi\",),\n//│   sub: (('r, anything,),) -> int -> 'a,\n//│   update: (('r, anything,),) -> int -> 'a -> ('r, \"hey\",)\n//│ }\n//│         = [Function: stepImpl]\n\nstepImpl_ty = stepImpl\n//│ ArraysImpl['a, 'r] -> {\n//│   fold: forall 'b. ('a -> 'b -> 'b) -> 'b -> (('r, anything,),) -> 'b,\n//│   init: 'a -> ('r, \"hi\",),\n//│   sub: (('r, anything,),) -> int -> 'a,\n//│   update: (('r, anything,),) -> int -> 'a -> ('r, \"hey\",)\n//│ }\n//│   <:  stepImpl_ty:\n//│ ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│            = [Function: stepImpl]\n\n\ndef step: Arrays['a] -> Arrays['a]\n//│ step: Arrays['a] -> Arrays['a]\n//│     = <missing implementation>\n\n\ndef helper impl (k: ArraysImplConsumer['a, '_]) = k (stepImpl impl)\n// * Or equivalently:\n// def helper impl (k: forall 'rep. ArraysImpl['a, 'rep] -> 'r) = k (stepImpl impl)\n//│ helper: ArraysImpl['a, 'r] -> ArraysImplConsumer['a, 'b] -> 'b\n//│       = [Function: helper]\n\n// * Note: these versions where we annotate `impl` instead don't work\n// * (cause problem in later definition of step)\n// def helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl)\n// def helper (impl: ArraysImpl['a, 'rep]) = let f = fun k -> k (stepImpl impl) in f\n// def helper (impl: ArraysImpl['a, 'rep]) k = k (let tmp = stepImpl impl in tmp)\n\ndef step arr = arr helper\n//│ ((forall 'a 'r 'b. ArraysImpl['a, 'r] -> ArraysImplConsumer['a, 'b] -> 'b) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step]\n\n// * Also works, but not necessary\ndef step (arr: Arrays['a]) = arr helper\n//│ Arrays['a] -> ArraysImplConsumer['a, 'b] -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step1]\n\n// * In one go:  <------------------------ this is probably the most canonical definition of `step` in this file\n\n// * With `stepImpl`\ndef step arr = arr (fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl))\n//│ ((forall 'a 'r 'b. ArraysImpl['a, 'r] -> ArraysImplConsumer['a, 'b] -> 'b) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step2]\n\n// * With `stepImpl_ty`\ndef step arr = arr (fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl))\n//│ ((forall 'a 'r 'b. ArraysImpl['a, 'r] -> ArraysImplConsumer['a, 'b] -> 'b) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step3]\n\n// * With one more annotation (not needed)\ndef step (arr: Arrays['a0]) = arr (fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl))\n//│ Arrays['a0] -> ArraysImplConsumer['a0, 'a] -> 'a\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step4]\n\n\n\n// *** Uses *** //\n\n\nssb = step (step base)\n//│ ssb: Arrays['a]\n//│    = [Function (anonymous)]\n\nssb (fun arr ->\n    let r2 = arr.update (arr.init true) 1 false\n    in (arr.sub r2 0, arr.sub r2 1)\n  )\n//│ res: (Bool, Bool,)\n//│    = [ false, false ]\n\n\nrec def mkMonoArray n =\n  if n == 0 then base else step (mkMonoArray (n - 1))\n//│ mkMonoArray: int -> Arrays['a]\n//│            = [Function: mkMonoArray]\n\nsnb = mkMonoArray 3\n//│ snb: Arrays['a]\n//│    = [Function (anonymous)]\n\n// * Here we are trying to leak the internally-quantified representation, resulting in `anything` being returned\nsnb (fun arr -> arr.init true)\n//│ res: anything\n//│    = [ [ [ true, 'hi' ], 'hi' ], 'hi' ]\n\n\n\n// *** An alternative way of defining Step! *** //\n\n\n// * Use another name to clarify this is an alternative way of defining it\ndef step2: Arrays['a] -> Arrays['a]\n//│ step2: Arrays['a] -> Arrays['a]\n//│      = <missing implementation>\n\n\ndef step2 (arr: Arrays['a]) (k: ArraysImplConsumer['a2, 'rep]) = arr (fun impl -> k (stepImpl impl))\n//│ Arrays['a] -> ArraysImplConsumer['a, 'rep] -> 'rep\n//│   where\n//│     'a := 'a0\n//│     'a0 :> 'a\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step21]\n\n\n// * Removing the `arr` annotation still works:\n\ndef step2 = forall 'a. fun arr ->\n  fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl impl))\n//│ ((forall 'r. ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step22]\n\n// * Or just:\ndef step2 arr (k: ArraysImplConsumer['a, 'rep]) = arr (fun impl -> k (stepImpl impl))\n//│ ((forall 'r. ArraysImpl[in 'a & 'a0 out 'a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b\n//│   where\n//│     'a := 'a0\n//│     'a0 :> 'a\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step23]\n\n\n\n// *** Uses *** //\n\n\nssb = step2 (step2 base)\n//│ ssb: Arrays['a]\n//│    = [Function (anonymous)]\n\nssb (fun arr ->\n    let r2 = arr.update (arr.init true) 1 false\n    in (arr.sub r2 0, arr.sub r2 1)\n  )\n//│ res: (Bool, Bool,)\n//│    = [ false, false ]\n\n\nrec def mkMonoArray n =\n  if n == 0 then base else step2 (mkMonoArray (n - 1))\n//│ mkMonoArray: int -> Arrays['a]\n//│            = [Function: mkMonoArray1]\n\nsnb = mkMonoArray 3\n//│ snb: Arrays['a]\n//│    = [Function (anonymous)]\n\n// * Here we are trying to leak the internally-quantified representation, resulting in `anything` being returned\nsnb (fun arr -> arr.init true)\n//│ res: anything\n//│    = [ [ [ true, 'hi' ], 'hi' ], 'hi' ]\n\n\n\n// *** Alternative definitions of `step` that do and don't work *** //\n\n\n// * Removing the `k` annotation breaks `step2`, even with `stepImpl_ty`, as before:\n:e\ndef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ Arrays['a] -> (ArraysImpl['a, in (??rep, string,) out (anything, string,)] -> 'b) -> 'b\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.279: \tdef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.17: \ttype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.279: \tdef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ║         \t                                                                                         ^^^^\n//│ ╟── • this reference:\n//│ ║  l.279: \tdef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ║         \t                                                         ^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.86: \tdef stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ ╙──      \t                                                       ^^\n//│      = [Function: step24]\n\n\n// * `step` not work with no annotations (even with stepImpl_ty),\n// * because that makes `k` leak its argument type\n:e\ndef step arr = arr (fun impl -> fun k -> k (stepImpl_ty impl))\n//│ ((forall 'a 'r 'b. ArraysImpl['a, 'r] -> (ArraysImpl['a, ('r, string,)] -> 'b) -> 'b) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.305: \tdef step arr = arr (fun impl -> fun k -> k (stepImpl_ty impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.17: \ttype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.305: \tdef step arr = arr (fun impl -> fun k -> k (stepImpl_ty impl))\n//│ ║         \t               ^^^\n//│ ╟── • this function:\n//│ ║  l.305: \tdef step arr = arr (fun impl -> fun k -> k (stepImpl_ty impl))\n//│ ║         \t                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.86: \tdef stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ ╙──      \t                                                       ^^\n//│     = [Function: step5]\n\n// * Still doesn't work if we only annotate `arr`, as `k` still leaks the internal repr\n:e\ndef step (arr: Arrays['a]) = arr (fun impl -> fun k -> k (stepImpl impl))\n//│ Arrays['a] -> ({\n//│   fold: forall 'b. ('a -> 'b -> 'b) -> 'b -> ((??rep, anything,),) -> 'b,\n//│   init: 'a -> (anything, \"hi\",),\n//│   sub: ((??rep, anything,),) -> int -> 'a,\n//│   update: ((??rep, anything,),) -> int -> 'a -> (anything, \"hey\",)\n//│ } -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.329: \tdef step (arr: Arrays['a]) = arr (fun impl -> fun k -> k (stepImpl impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.17: \ttype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.329: \tdef step (arr: Arrays['a]) = arr (fun impl -> fun k -> k (stepImpl impl))\n//│ ║         \t                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.329: \tdef step (arr: Arrays['a]) = arr (fun impl -> fun k -> k (stepImpl impl))\n//│ ║         \t                             ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.93: \t    sub    = fun ((r0, r1)) -> fun i -> arrImpl.sub r0 i;\n//│ ╙──      \t                                                    ^^\n//│     = [Function: step6]\n\n\n// * Works. Note: removing `forall 'a.` here leads to badness\ndef step arr = arr (forall 'a. fun impl -> forall 'r. fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl))\n//│ ((forall 'a 'r 'r0. ArraysImpl['a, 'r] -> ArraysImplConsumer['a, 'r0] -> 'r0) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step7]\n\n// * ...unless we use `stepImpl_ty` instead of `stepImpl`\ndef step arr = arr (fun impl -> forall 'r. fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl))\n//│ ((forall 'a 'a0 'r 'a1 'r0. ArraysImpl[in 'a & 'a0 out 'a | 'a0, 'r] -> ArraysImplConsumer['a1, 'r0] -> 'r0) -> 'b) -> 'b\n//│   where\n//│     'a1 :> 'a\n//│         <: 'a0\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step8]\n\n\ndef step arr = arr (fun impl -> (fun k -> k (stepImpl impl)) : Arrays['a])\n//│ ((forall 'a 'a0 'r. ArraysImpl[in 'a & 'a0 out 'a, 'r] -> Arrays['a0]) -> 'b) -> 'b\n//│   where\n//│     'a :> 'a0\n//│     'a0 := 'a\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step9]\n\ndef step arr = arr (fun impl -> (fun k -> k (stepImpl_ty impl)) : Arrays['a])\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step10]\n\ndef step = forall 'a. fun (arr : Arrays['a]) -> arr (fun impl -> (fun k -> k (stepImpl impl)) : Arrays['a])\n//│ Arrays['a] -> Arrays['a]\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step11]\n\ndef step = forall 'a. fun arr -> arr (forall 'rep. fun (impl : ArraysImpl['a, 'rep]) -> (fun k -> k (stepImpl impl)) : Arrays['a])\n//│ ((forall 'rep. ArraysImpl['a, 'rep] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step12]\n\n\n// * The following `arrayRepToArray` definition can help type check `step`:\n\ndef arrayRepToArray impl (k: forall 'rep. ArraysImpl['a, 'rep] -> 'r) = k impl\n//│ arrayRepToArray: ArraysImpl['a, 'rep] -> (forall 'rep0. ArraysImpl['a, 'rep0] -> 'b) -> 'b\n//│                = [Function: arrayRepToArray]\n\ndef arrayRepToArray_A : ArraysImpl['a, 'rep] -> Arrays['a]\n//│ arrayRepToArray_A: ArraysImpl['a, 'rep] -> Arrays['a]\n//│                  = <missing implementation>\n\ndef arrayRepToArray_A impl k = k impl\n//│ 'a -> ('a -> 'b) -> 'b\n//│   <:  arrayRepToArray_A:\n//│ ArraysImpl['a, 'rep] -> Arrays['a]\n//│                  = [Function: arrayRepToArray_A]\n\n\ndef step arr = arr (fun impl -> arrayRepToArray_A (stepImpl_ty impl))\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step13]\n\ndef step arr = arr (fun impl -> arrayRepToArray (stepImpl_ty impl))\n//│ ((forall 'a 'r 'b. ArraysImpl['a, 'r] -> (forall 'rep. ArraysImpl['a, 'rep] -> 'b) -> 'b) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step14]\n\ndef step (arr: Arrays['a]) = arr (fun impl -> arrayRepToArray_A (stepImpl impl))\n//│ Arrays['a] -> Arrays['a]\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step15]\n\ndef step arr = arr (fun impl -> arrayRepToArray (stepImpl impl))\n//│ ((forall 'a 'r 'b. ArraysImpl['a, 'r] -> (forall 'rep. ArraysImpl['a, 'rep] -> 'b) -> 'b) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step16]\n\n\n// * We can get away with not annotating `arrImpl` as long as we annotate its polymorphic field use:\n\ntype Fold[A, Rep] = forall 'b. (A -> 'b -> 'b) -> 'b -> Rep -> 'b\n//│ Defined type alias Fold[+A, -Rep]\n\ndef stepImpl_Ann = forall 'a 'rep. fun arrImpl -> {\n    init   = fun a -> (arrImpl.init a, \"hi\");\n    sub    = fun ((r0, r1)) -> fun i -> arrImpl.sub r0 i;\n    update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.update r0 i a, \"hey\");\n    fold   = fun f -> fun b -> fun ((r0, r1)) -> (arrImpl.fold: Fold['a, 'rep]) f b r0\n  }\n//│ stepImpl_Ann: {\n//│   fold: Fold['a, 'rep],\n//│   init: 'c -> 'd,\n//│   sub: 'e -> 'f -> 'g,\n//│   update: 'h -> 'i -> 'j -> 'k\n//│ } -> {\n//│   fold: forall 'b. ('a -> 'b -> 'b) -> 'b -> (('rep, anything,),) -> 'b,\n//│   init: 'c -> ('d, \"hi\",),\n//│   sub: (('e, anything,),) -> 'f -> 'g,\n//│   update: (('h, anything,),) -> 'i -> 'j -> ('k, \"hey\",)\n//│ }\n//│             = [Function: stepImpl_Ann]\n\ndef step arr = arr (fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_Ann impl))\n//│ ((forall 'a 'rep 'b. {\n//│   fold: Fold['a, 'rep],\n//│   init: 'a -> 'rep,\n//│   sub: 'rep -> int -> 'a,\n//│   update: 'rep -> int -> 'a -> 'rep\n//│ } -> ArraysImplConsumer['a, 'b] -> 'b) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step17]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_Records_ND.mls",
    "content": "// * Adaptation of QML's original existentials example; using encoded existentials and plain records\n// * This alternative version is an exploration of how things go when we DON'T have forall distributivity (ie ND)\n\n:NoRecursiveTypes\n:DontDistributeForalls\n\n\n\n// *** Type definitions *** //\n\ntype ArraysImpl[A, Rep] = {\n    init: A -> Rep;\n    sub: Rep -> int -> A;\n    update: Rep -> int -> A -> Rep;\n    fold: forall 'b. (A -> 'b -> 'b) -> 'b -> Rep -> 'b\n  }\n//│ Defined type alias ArraysImpl[=A, =Rep]\n\ntype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ Defined type alias ArraysImplConsumer[=A, +R]\n\ntype Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r\n//│ Defined type alias Arrays[=A]\n\n\n\n// *** Base *** //\n\n\nbaseImpl = {\n    init   = fun a -> a;\n    sub    = fun r -> fun i -> r;\n    update = fun r -> fun i -> fun a -> a;\n    fold   = fun f -> fun b -> fun r -> f r b\n  }\n//│ baseImpl: {\n//│   fold: forall 'a 'b 'c. ('a -> 'b -> 'c) -> 'b -> 'a -> 'c,\n//│   init: forall 'd. 'd -> 'd,\n//│   sub: forall 'e. 'e -> anything -> 'e,\n//│   update: anything -> anything -> (forall 'f. 'f -> 'f)\n//│ }\n//│         = {\n//│             init: [Function: init],\n//│             sub: [Function: sub],\n//│             update: [Function: update],\n//│             fold: [Function: fold]\n//│           }\n\nbaseImpl : ArraysImpl['a, 'a]\n//│ res: ArraysImpl['a, 'a]\n//│    = {\n//│        init: [Function: init],\n//│        sub: [Function: sub],\n//│        update: [Function: update],\n//│        fold: [Function: fold]\n//│      }\n\ndef base: Arrays['a]\n//│ base: Arrays['a]\n//│     = <missing implementation>\n\n// * This works because `f` is used immediately, at the top level\n// * (not within a more polymorphic context),\n// * so we do not need first-class parametric polymorphism to type check the definition.\ndef base f = f baseImpl\n//│ ({\n//│   fold: forall 'a 'b 'c. ('a -> 'b -> 'c) -> 'b -> 'a -> 'c,\n//│   init: forall 'd. 'd -> 'd,\n//│   sub: forall 'e. 'e -> anything -> 'e,\n//│   update: anything -> anything -> (forall 'f. 'f -> 'f)\n//│ } -> 'g) -> 'g\n//│   <:  base:\n//│ Arrays['a]\n//│     = [Function: base]\n\n// * Also works, but not necessary\ndef base (f: ArraysImplConsumer['a, 'res]) = f baseImpl\n//│ ArraysImplConsumer['a, 'b] -> 'b\n//│   <:  base:\n//│ Arrays['a]\n//│     = [Function: base1]\n\n\n\n// *** Step *** //\n\n\ndef stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│            = <missing implementation>\n\n// * `arrImpl` is meant to be used polymorphically under lambdas, so it needs an annotation\ndef stepImpl (arrImpl: ArraysImpl['a, 'r]) = {\n    init   = fun a -> (arrImpl.init a, \"hi\");\n    sub    = fun ((r0, r1)) -> fun i -> arrImpl.sub r0 i;\n    update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.update r0 i a, \"hey\");\n    fold   = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.fold f b r0\n  }\n//│ stepImpl: ArraysImpl['a, 'r] -> {\n//│   fold: forall 'b 'b0. ('a -> 'b -> ('b & 'b0)) -> (forall 'c. ('b & 'c) -> (('r, anything,),) -> ('c | 'b0)),\n//│   init: 'a -> ('r, \"hi\",),\n//│   sub: (('r, anything,),) -> int -> 'a,\n//│   update: (('r, anything,),) -> int -> 'a -> ('r, \"hey\",)\n//│ }\n//│         = [Function: stepImpl]\n\nstepImpl_ty = stepImpl\n//│ ArraysImpl['a, 'r] -> {\n//│   fold: forall 'b 'b0. ('a -> 'b -> ('b & 'b0)) -> (forall 'c. ('b & 'c) -> (('r, anything,),) -> ('c | 'b0)),\n//│   init: 'a -> ('r, \"hi\",),\n//│   sub: (('r, anything,),) -> int -> 'a,\n//│   update: (('r, anything,),) -> int -> 'a -> ('r, \"hey\",)\n//│ }\n//│   <:  stepImpl_ty:\n//│ ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n//│            = [Function: stepImpl]\n\n\ndef step: Arrays['a] -> Arrays['a]\n//│ step: Arrays['a] -> Arrays['a]\n//│     = <missing implementation>\n\n\n// * --- Using stepImpl --- * //\n\n\n// * Works\ndef helper impl (k: ArraysImplConsumer['a, 'res]) = k (stepImpl impl)\n//│ helper: ArraysImpl[in 'a & 'a0 out 'a | 'a0, 'r] -> (forall 'a1 'b. ArraysImplConsumer['a1, 'b] -> 'b)\n//│   where\n//│     'a1 :> 'a\n//│         <: 'a0\n//│       = [Function: helper]\n\n// * FIXME why does this require so much fuel?!\n:Fuel 50000\ndef step (arr: Arrays['a]) = arr helper\n//│ Arrays['a] -> (forall 'a0 'b. ArraysImplConsumer['a0, 'b] -> 'b)\n//│   where\n//│     'a0 := 'a\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step]\n:ResetFuel\n\n\n// * It behaves better when we bind 'a at the right place\ndef helper = forall 'a. fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl)\n// * Or equivalently:\n// def helper = forall 'a. fun impl -> forall 'b. fun (k: ArraysImplConsumer['a, 'b]) -> k (stepImpl impl)\n//│ helper: ArraysImpl['a, 'r] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│       = [Function: helper1]\n\ndef step arr = arr helper\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step1]\n\n// * In one go:  <------------------------ this is probably the most canonical definition of `step` in this file\n\ndef step arr = arr (forall 'a. fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl))\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step2]\n\n\n// * Also kind of works – note that 'res is quantified in the right place (innermost lambda)\n// * Note that currently, undeclared TVs are not shared between type annots, so we couldn't use 'a in both\ndef helper (impl: ArraysImpl['a, 'rep]) (k: ArraysImplConsumer['b, 'res]) = k (stepImpl impl)\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'b 'c. ArraysImplConsumer['b, 'c] -> 'c)\n//│   where\n//│     'b := 'a\n//│       = [Function: helper2]\n\n// * FIXME this works with `:Fuel 4000000` but takes ~10s!!\n// * Why require so much fuel? (notably, more than in the same `helper` but *without* the impl annot)\n// * -> probably due to 'b being generalized too early\n// * Note [2023-10-06]:\n// *    It seems the fuel might be needed because of TV reconstraining after extrusion,\n// *    which is currently implemented in a very naive and wasteful way!\n// *    Indeed, if we set (includeBounds = true) in the `getVars` method,\n// *    which is used for reconstraining, then this no longer require extra fuel!\n:e\ndef step (arr: Arrays['a]) = arr helper\n//│ Arrays['a] -> error\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Subtyping constraint of the form `Arrays['a] <: (forall 'a0 'rep. ArraysImpl['a0, 'rep] -> (forall ?a 'b 'res. ArraysImplConsumer['b, 'res] -> ?a)) -> ?b` took too many steps and ran out of fuel (10000)\n//│ ║  l.186: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t                             ^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ ╔══[ERROR] Subtyping constraint of the form `forall 'a ?a. Arrays['a] -> ?a <: forall 'a0. Arrays['a0] -> Arrays['a0]` took too many steps and ran out of fuel (10000)\n//│ ║  l.186: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│     = [Function: step3]\n\n\n// * With explicit foralls (otherwise each annot FV refers to a different var)\n// * Note: changing this to `ArraysImplConsumer['b, 'res]` requires similar crazy fuel consumption\n// * as above, as expected (in fact, I had to use even more `:Fuel 10000000`).\n// * The issue is probably in some excessive/pathological extrusion behavior due to 'b being too polymorphic\n// * Removing `'a` in the forall clause has a similar effect but \"only\" requires `:Fuel 4000000`\n// *  — the difference is probably due to `'a` being rigid or not causing slightly different behaviors\ndef helper = forall 'a 'rep. fun (impl: ArraysImpl['a, 'rep]) ->\n  forall 'res. fun (k: ArraysImplConsumer['a, 'res]) -> k (stepImpl impl)\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'res. ArraysImplConsumer['a, 'res] -> 'res)\n//│       = [Function: helper3]\n\ndef step (arr: Arrays['a]) = arr helper\n//│ Arrays['a] -> (forall 'res. ArraysImplConsumer['a, 'res] -> 'res)\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step4]\n\n\n// * Doesn't work (`'rep` leaks out of its scope in `step`)\ndef helper impl k = k (stepImpl impl)\n//│ helper: ArraysImpl[in 'a out 'a | 'a0, in 'r out 'r | 'r0] -> (forall 'a1 'r1 'c. ({\n//│   fold: forall 'b 'b0. (('a | 'a1) -> 'b -> ('b & 'b0)) -> (forall 'd. ('b & 'd) -> (('r0 & 'r1, anything,),) -> ('d | 'b0)),\n//│   init: ('a0 & 'a1) -> ('r | 'r1, \"hi\",),\n//│   sub: (('r0 & 'r1, anything,),) -> int -> ('a | 'a1),\n//│   update: (('r0 & 'r1, anything,),) -> int -> ('a0 & 'a1) -> ('r | 'r1, \"hey\",)\n//│ } -> 'c) -> 'c)\n//│       = [Function: helper4]\n\n// * Idem\ndef helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl)\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'c. ({\n//│   fold: forall 'b 'b0. ('a -> 'b -> ('b & 'b0)) -> (forall 'd. ('b & 'd) -> (('rep, anything,),) -> ('d | 'b0)),\n//│   init: 'a -> ('rep, \"hi\",),\n//│   sub: (('rep, anything,),) -> int -> 'a,\n//│   update: (('rep, anything,),) -> int -> 'a -> ('rep, \"hey\",)\n//│ } -> 'c) -> 'c)\n//│       = [Function: helper5]\n\n:e\ndef step (arr: Arrays['a]) = arr helper\n//│ Arrays['a] -> (forall 'c. error | ({\n//│   fold: forall 'b 'b0. ('a0 -> 'b -> ('b & 'b0)) -> (forall 'd. ('b & 'd) -> (('rep & 'rep0, anything,),) -> ('d | 'b0)),\n//│   init: ('a & 'a0) -> ('rep, \"hi\",),\n//│   sub: (('rep & 'rep0, anything,),) -> int -> 'a0,\n//│   update: (('rep & 'rep0, anything,),) -> int -> ('a & 'a0) -> ('rep, \"hey\",)\n//│ } -> 'c) -> 'c)\n//│ where\n//│   'rep :> anything\n//│        <: 'rep0\n//│   'rep0 <: ??rep & 'rep\n//│   'a <: 'a0\n//│   'a0 := 'a\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.240: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t                             ^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.19: \ttype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.230: \tdef helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl)\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.240: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t                                 ^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.240: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t                             ^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.93: \tdef stepImpl (arrImpl: ArraysImpl['a, 'r]) = {\n//│ ╙──      \t                                      ^^\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.240: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.19: \ttype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.230: \tdef helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl)\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.240: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t                                 ^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.240: \tdef step (arr: Arrays['a]) = arr helper\n//│ ║         \t                             ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.95: \t    sub    = fun ((r0, r1)) -> fun i -> arrImpl.sub r0 i;\n//│ ╙──      \t                                                    ^^\n//│     = [Function: step5]\n\n\n// * An alternative way, and in one go:\n\ndef step arr = arr (fun impl -> (fun k -> k (stepImpl_ty impl)) : Arrays['a])\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step6]\n\ndef step arr = arr (fun impl -> (fun k -> k (stepImpl impl)) : Arrays['a])\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step7]\n\ndef step = forall 'a. fun arr -> arr (fun impl -> (fun k -> k (stepImpl impl)) : Arrays['a])\n//│ ((forall 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step8]\n\n// * This one is wrong (notice the extrusion in the type):\ndef step_ arr = forall 'a. arr (fun (impl : ArraysImpl['a, 'rep]) -> (fun k -> k (stepImpl impl)) : Arrays['a])\n//│ step_: ((forall 'rep. ArraysImpl[in ??a out ??a0, 'rep] -> Arrays[in ??a out ??a0]) -> 'a) -> 'a\n//│      = [Function: step_]\n\ndef step = forall 'a. fun arr -> arr (fun (impl : ArraysImpl['a, 'rep]) -> (fun k -> k (stepImpl impl)) : Arrays['a])\n//│ ((forall 'rep. ArraysImpl['a, 'rep] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step9]\n\n\n\n// * --- Using stepImpl_ty --- * //\n\n\n// * Still doesn't work (`'rep` leaks out of its scope in `step`) – expected\ndef helper impl k = k (stepImpl_ty impl)\n//│ helper: ArraysImpl[in 'a out 'a | 'a0, in 'r out 'r | 'r0] -> (forall 'a1 'r1 'b. (ArraysImpl['a1, ('r1, string,)] -> 'b) -> 'b)\n//│   where\n//│     'r1 :> 'r\n//│         <: 'r0\n//│     'a1 :> 'a\n//│         <: 'a0\n//│       = [Function: helper6]\n\n// * Idem – expected, as `k` needs an annot to avoid leaking its argument's type\ndef helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl_ty impl)\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'b. (ArraysImpl['a, ('rep, string,)] -> 'b) -> 'b)\n//│       = [Function: helper7]\n\n// * Idem – this is a bit surprising, given that it works with the plain `stepImpl`! (tho with much fuel)\ndef helper impl (k: ArraysImplConsumer['a2, 'res]) = k (stepImpl_ty impl)\n//│ helper: ArraysImpl[in 'a & 'a0 out 'a | 'a0, 'r] -> (forall 'a2 'b. ArraysImplConsumer['a2, 'b] -> 'b)\n//│   where\n//│     'a2 :> 'a\n//│         <: 'a0\n//│       = [Function: helper8]\n\n// * Now this works – so the problem was 'a2 not being generalized at the right place\ndef helper = forall 'a2. fun impl -> fun (k: ArraysImplConsumer['a2, 'res]) -> k (stepImpl_ty impl)\n//│ helper: ArraysImpl['a2, 'r] -> (forall 'a. ArraysImplConsumer['a2, 'a] -> 'a)\n//│       = [Function: helper9]\n\ndef step arr = arr helper\n//│ ((forall 'a2 'r. ArraysImpl['a2, 'r] -> (forall 'a. ArraysImplConsumer['a2, 'a] -> 'a)) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step10]\n\n\n// * Also works\ndef helper (impl: ArraysImpl['a, 'rep]) (k: ArraysImplConsumer['a2, 'res]) = k (stepImpl_ty impl)\n// def helper (impl: ArraysImpl['a, 'rep]) (k: ArraysImplConsumer['a, 'rep]) = k (stepImpl_ty impl)\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│       = [Function: helper10]\n\n// * Why so much? – probably the same reason as above ('a2 instead of the same 'a)\n:Fuel 500000\ndef step arr = arr helper\n//│ ((forall 'a 'rep. ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step11]\n:ResetFuel\n\n// * Note that `:GeneralizeCurriedFunctions` is enabled here because of `:DontDistributeForalls`,\n// * so this version still generalizes the innermost lambda:\ndef helper = forall 'a 'rep. fun (impl: ArraysImpl['a, 'rep]) -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl)\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│       = [Function: helper11]\n\ndef step arr = arr helper\n//│ ((forall 'a 'rep. ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step12]\n\n:DontGeneralizeCurriedFunctions\n\n// * Note: could also force explicit generalization with `forall.`\ndef helper = forall 'a 'rep. fun (impl: ArraysImpl['a, 'rep]) -> forall. fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl)\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│       = [Function: helper12]\n\n// * Note: or could also let-bind the lambda to force generalization\ndef helper = forall 'a 'rep. fun (impl: ArraysImpl['a, 'rep]) -> let res = fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl) in res\n//│ helper: ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│       = [Function: helper13]\n\n:GeneralizeCurriedFunctions\n\n\n// * Interesting alternative to annotating `k` that also works:\n\n// * Works\ndef helper = forall 'a 'rep. fun (impl: ArraysImpl['a, 'rep]) -> (fun k -> k (stepImpl_ty impl)) : Arrays['a]\n//│ helper: ArraysImpl['a, 'rep] -> Arrays['a]\n//│       = [Function: helper14]\n\n// * Works\ndef helper = forall 'a. fun impl -> (fun k -> k (stepImpl_ty impl)) : Arrays['a]\n//│ helper: ArraysImpl['a, 'r] -> Arrays['a]\n//│       = [Function: helper15]\n\ndef step arr = arr helper\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step13]\n\n// * Works\n// * Note the slight difference in type with above due to 'a being generalized at a different place:\ndef helper impl = (fun k -> k (stepImpl_ty impl)) : Arrays['a]\n//│ helper: ArraysImpl['a, 'r] -> Arrays['a]\n//│       = [Function: helper16]\n\nhelper : ArraysImplConsumer['a, 'r]\n//│ res: ArraysImplConsumer['a, Arrays['a]]\n//│    = [Function: helper16]\n\ndef step arr = arr helper\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step14]\n\n// * In one go:\n\ndef step arr = arr (fun impl -> (fun k -> k (stepImpl_ty impl)) : Arrays['a])\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step15]\n\ndef step arr = arr helper\n//│ ((forall 'a 'r. ArraysImpl['a, 'r] -> Arrays['a]) -> 'b) -> 'b\n//│   <:  step:\n//│ Arrays['a] -> Arrays['a]\n//│     = [Function: step16]\n\n\n\n// *** Uses *** //\n\n\nssb = step (step base)\n//│ ssb: Arrays['a]\n//│    = [Function (anonymous)]\n\nssb (fun arr ->\n    let r2 = arr.update (arr.init true) 1 false\n    in (arr.sub r2 0, arr.sub r2 1)\n  )\n//│ res: (Bool, Bool,)\n//│    = [ false, false ]\n\n\nrec def mkMonoArray n =\n  if n == 0 then base else step (mkMonoArray (n - 1))\n//│ mkMonoArray: int -> (forall 'a. Arrays['a])\n//│            = [Function: mkMonoArray]\n\nsnb = mkMonoArray 3\n//│ snb: Arrays['a]\n//│    = [Function (anonymous)]\n\n// * Here we are trying to leak the internally-quantified representation, resulting in extruded types being returned\nsnb (fun arr -> arr.init true)\n//│ res: anything\n//│    = [ [ [ true, 'hi' ], 'hi' ], 'hi' ]\n\n\n\n// *** An alternative way of defining Step! *** //\n\n\n// * Use another name to clarify this is an alternative way of defining it\ndef step2: Arrays['a] -> Arrays['a]\n//│ step2: Arrays['a] -> Arrays['a]\n//│      = <missing implementation>\n\n\n// * Using `stepImpl`\ndef step2 = forall 'a. fun (arr: Arrays['a]) ->\n  fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl impl))\n//│ Arrays['a] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step21]\n\n// * Using `stepImpl_ty`\ndef step2 = forall 'a. fun (arr: Arrays['a]) ->\n  fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl))\n//│ Arrays['a] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step22]\n\n// * Being a bit more explicit about generalization points:\ndef step2 = forall 'a. fun (arr: Arrays['a]) -> forall 'res.\n  fun (k: forall 'rep. ArraysImpl['a, 'rep] -> 'res) -> arr (fun impl -> k (stepImpl_ty impl))\n//│ Arrays['a] -> (forall 'res. (forall 'rep. ArraysImpl['a, 'rep] -> 'res) -> 'res)\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step23]\n\n// * Or being less explicit: removing `forall 'a` and using `stepImpl`:\ndef step2 (arr: Arrays['a]) (k: ArraysImplConsumer['a2, 'rep]) = arr (fun impl -> k (stepImpl impl))\n//│ Arrays['a] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│      = [Function: step24]\n\n\n// * Removing either annotation breaks it:\n\n:e\ndef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ Arrays['a] -> (forall 'b. (ArraysImpl['a, in (??rep, string,) out (anything, string,)] -> 'b) -> 'b)\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.534: \tdef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.19: \ttype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.534: \tdef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ║         \t                                                                                         ^^^^\n//│ ╟── • this reference:\n//│ ║  l.534: \tdef step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ║         \t                                                         ^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.88: \tdef stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ ╙──      \t                                                       ^^\n//│      = [Function: step25]\n\n:e\ndef step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl))\n// * Or equivalently:\n// def step = forall 'a. fun arr -> forall 'rep. fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ((forall 'r. ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.557: \tdef step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.22: \ttype Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r\n//│ ║        \t                                                  ^^\n//│ ╟── back into type variable `'r`\n//│ ║  l.22: \ttype Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r\n//│ ║        \t                                                         ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.557: \tdef step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl))\n//│ ╙──       \t                                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│      = [Function: step26]\n\n\n// * FIXME why is this displayed as `'a <: nothing`? Simplification bug?\ndef s arr (k: ArraysImplConsumer['a, 'rep]) = arr (fun impl -> k (stepImpl_ty impl))\n//│ s: ((forall 'r. ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b\n//│  = [Function: s]\n// * We can see it shouldn't be simplified to nothing:\n:ns\ns\n//│ res: forall 'b 'a 'a0 'rep 'c. 'b -> (forall 'a1 'rep0 'd. ArraysImplConsumer['a1, 'rep0] -> 'd)\n//│   where\n//│     'd :> 'c\n//│     'rep0 <: 'rep\n//│     'a1 :> 'a0\n//│         <: 'a\n//│     'b <: (forall 'r 'e 'a2 'f. 'e -> 'f) -> 'c\n//│     'f :> 'rep\n//│     'e <: ArraysImpl['a2, 'r]\n//│     'a2 :> 'a\n//│         <: 'a0\n//│     'a <: 'a0\n//│     'a0 <: 'a\n//│    = [Function: s]\n\n// * BTW: this doesn't work (same reason as before: k needs an annotation)\n:e\nstep2 = s\n//│ ((forall 'r. ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b\n//│   <:  step2:\n//│ Arrays['a] -> Arrays['a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.603: \tstep2 = s\n//│ ║         \t^^^^^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.22: \ttype Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r\n//│ ║        \t                                                  ^^\n//│ ╟── back into type variable `'r`\n//│ ║  l.22: \ttype Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r\n//│ ║        \t                                                         ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.603: \tstep2 = s\n//│ ║         \t        ^\n//│ ╟── • this application:\n//│ ║  l.580: \tdef s arr (k: ArraysImplConsumer['a, 'rep]) = arr (fun impl -> k (stepImpl_ty impl))\n//│ ╙──       \t                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│      = [Function: s]\n\n\n\n// *** Uses 2 *** //\n\n\nssb = step2 (step2 base)\n//│ ssb: Arrays['a]\n//│    = [Function (anonymous)]\n\nssb (fun arr ->\n    let r2 = arr.update (arr.init true) 1 false\n    in (arr.sub r2 0, arr.sub r2 1)\n  )\n//│ res: (Bool, Bool,)\n//│    = [ false, false ]\n\n\nrec def mkMonoArray n =\n  if n == 0 then base else step2 (mkMonoArray (n - 1))\n//│ mkMonoArray: int -> (forall 'a. Arrays['a])\n//│            = [Function: mkMonoArray1]\n\nsnb = mkMonoArray 3\n//│ snb: Arrays['a]\n//│    = [Function (anonymous)]\n\n// * Here we are trying to leak the internally-quantified representation, resulting in extruded types being returned\nsnb (fun arr -> arr.init true)\n//│ res: anything\n//│    = [ [ [ true, 'hi' ], 'hi' ], 'hi' ]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_Records_min_1.mls",
    "content": "// * This is a minimization of the error that happens in `QML_exist_Records`\n// * when we don't annotate `arrImpl` in `stepImpl`.\n\n:NoRecursiveTypes\n:NoJS\n\n\n\ntype ArraysImpl = { fold: forall 'b. 'b -> 'b }\n//│ Defined type alias ArraysImpl\n\ntype ArraysImplConsumer[R] = ArraysImpl -> R\n//│ Defined type alias ArraysImplConsumer[+R]\n\ntype Arrays = (ArraysImpl -> 'r) -> 'r\n//│ Defined type alias Arrays\n\n\ndef stepImpl (arrImpl: ArraysImpl) = { fold = fun f -> arrImpl.fold f }\n//│ stepImpl: ArraysImpl -> {fold: forall 'a. 'a -> 'a}\n\ndef stepImpl_noAnn arrImpl = { fold = fun f -> arrImpl.fold f }\n//│ stepImpl_noAnn: {fold: 'a -> 'b} -> {fold: 'a -> 'b}\n\n\ndef step2: Arrays -> Arrays\n//│ step2: Arrays -> Arrays\n\n\ndef step2 arr k = k (arr stepImpl)\n//│ ((ArraysImpl -> {fold: forall 'a. 'a -> 'a}) -> 'b) -> ('b -> 'c) -> 'c\n//│   <:  step2:\n//│ Arrays -> Arrays\n\ndef step2 arr (k: ArraysImplConsumer['rep]) = k (arr stepImpl)\n//│ ((ArraysImpl -> {fold: forall 'a. 'a -> 'a}) -> ArraysImpl) -> ArraysImplConsumer['b] -> 'b\n//│   <:  step2:\n//│ Arrays -> Arrays\n\ndef step2 (arr: Arrays) k = k (arr stepImpl)\n//│ Arrays -> ({fold: forall 'a. 'a -> 'a} -> 'b) -> 'b\n//│   <:  step2:\n//│ Arrays -> Arrays\n\n// * Using `stepImpl_noAnn` fails to work, as expected:\n\n:e\ndef step2 arr k = k (arr stepImpl_noAnn)\n//│ ((forall 'a 'b. {fold: 'a -> 'b} -> {fold: 'a -> 'b}) -> 'c) -> ('c -> 'd) -> 'd\n//│   <:  step2:\n//│ Arrays -> Arrays\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.48: \tdef step2 arr k = k (arr stepImpl_noAnn)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.9: \ttype ArraysImpl = { fold: forall 'b. 'b -> 'b }\n//│ ║       \t                                     ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.9: \ttype ArraysImpl = { fold: forall 'b. 'b -> 'b }\n//│ ║       \t                                           ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.48: \tdef step2 arr k = k (arr stepImpl_noAnn)\n//│ ║        \t                  ^\n//│ ╟── • this application:\n//│ ║  l.48: \tdef step2 arr k = k (arr stepImpl_noAnn)\n//│ ║        \t                     ^^^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.22: \tdef stepImpl_noAnn arrImpl = { fold = fun f -> arrImpl.fold f }\n//│ ╙──      \t                                               ^^^^^^^^^^^^^^\n\n:e\ndef step2 arr (k: ArraysImplConsumer['rep]) = k (arr stepImpl_noAnn)\n//│ ((forall 'a 'b. {fold: 'a -> 'b} -> {fold: 'a -> 'b}) -> ArraysImpl) -> ArraysImplConsumer['c] -> 'c\n//│   <:  step2:\n//│ Arrays -> Arrays\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.73: \tdef step2 arr (k: ArraysImplConsumer['rep]) = k (arr stepImpl_noAnn)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.9: \ttype ArraysImpl = { fold: forall 'b. 'b -> 'b }\n//│ ║       \t                                     ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.9: \ttype ArraysImpl = { fold: forall 'b. 'b -> 'b }\n//│ ║       \t                                           ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.73: \tdef step2 arr (k: ArraysImplConsumer['rep]) = k (arr stepImpl_noAnn)\n//│ ║        \t                                                 ^^^\n//│ ╟── • this application:\n//│ ║  l.22: \tdef stepImpl_noAnn arrImpl = { fold = fun f -> arrImpl.fold f }\n//│ ╙──      \t                                               ^^^^^^^^^^^^^^\n\n:e\ndef step2 (arr: Arrays) k = k (arr stepImpl_noAnn)\n//│ Arrays -> ({fold: 'a -> 'a} -> 'b) -> 'b\n//│   <:  step2:\n//│ Arrays -> Arrays\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.95: \tdef step2 (arr: Arrays) k = k (arr stepImpl_noAnn)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.9: \ttype ArraysImpl = { fold: forall 'b. 'b -> 'b }\n//│ ║       \t                                     ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.9: \ttype ArraysImpl = { fold: forall 'b. 'b -> 'b }\n//│ ║       \t                                           ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.95: \tdef step2 (arr: Arrays) k = k (arr stepImpl_noAnn)\n//│ ║        \t                            ^\n//│ ╟── • this application:\n//│ ║  l.95: \tdef step2 (arr: Arrays) k = k (arr stepImpl_noAnn)\n//│ ║        \t                               ^^^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.22: \tdef stepImpl_noAnn arrImpl = { fold = fun f -> arrImpl.fold f }\n//│ ╙──      \t                                               ^^^^^^^^^^^^^^\n\n\n\n// * A slight variation with `:ConstrainedTypes`, because why not:\n\n:ConstrainedTypes\n\n\ntype ArraysImpl2[Rep] = { fold: forall 'b. 'b -> Rep -> 'b }\n//│ Defined type alias ArraysImpl2[-Rep]\n\ntype Arrays2 = (forall 'Rep. ArraysImpl2['Rep] -> 'r) -> 'r\n//│ Defined type alias Arrays2\n\ndef stepImpl arrImpl = { fold = fun f -> fun r0 -> arrImpl.fold f r0 }\n//│ stepImpl: 'a -> {fold: forall 'b 'c 'd. 'b -> ('c -> 'd\n//│   where\n//│     'a <: {fold: 'b -> 'c -> 'd})}\n\n\ndef step: Arrays2 -> Arrays2\n//│ step: Arrays2 -> Arrays2\n\n:e\ndef step arr k = k (arr stepImpl)\n//│ 'a -> (('b -> 'c) -> 'c\n//│   where\n//│     'a <: (forall 'd. 'd -> {\n//│       fold: forall 'e 'f 'g. 'e -> ('f -> 'g\n//│         where\n//│           'd <: {fold: 'e -> 'f -> 'g})\n//│     }) -> 'b)\n//│   <:  step:\n//│ Arrays2 -> Arrays2\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.142: \tdef step arr k = k (arr stepImpl)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.126: \ttype ArraysImpl2[Rep] = { fold: forall 'b. 'b -> Rep -> 'b }\n//│ ║         \t                                           ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.126: \ttype ArraysImpl2[Rep] = { fold: forall 'b. 'b -> Rep -> 'b }\n//│ ║         \t                                                        ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.132: \tdef stepImpl arrImpl = { fold = fun f -> fun r0 -> arrImpl.fold f r0 }\n//│ ║         \t                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.142: \tdef step arr k = k (arr stepImpl)\n//│ ║         \t                    ^^^^^^^^^^^^\n//│ ╟── • this applied expression:\n//│ ║  l.142: \tdef step arr k = k (arr stepImpl)\n//│ ║         \t                 ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.132: \tdef stepImpl arrImpl = { fold = fun f -> fun r0 -> arrImpl.fold f r0 }\n//│ ╙──       \t                                                   ^^^^^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_Records_min_2.mls",
    "content": "// * This creates a funny TV cycle which used to throw off type simplification into a SOF\n// * ie:\n// * \t\t'a29_51'' <: 'a29_52''\n// * \t\t'a29_52'' :> 'a29_51''\n// *  whose bounds were inlined in a loop alternating between the positive and negative polarity\n\n:NoRecursiveTypes\n:DontDistributeForalls\n:NoJS\n\n\ntype ArraysImpl[A, Rep] = {\n    init: A -> Rep;\n    sub: Rep -> A\n  }\n//│ Defined type alias ArraysImpl[=A, =Rep]\n\ntype ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n//│ Defined type alias ArraysImplConsumer[=A, +R]\n\ntype Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r\n//│ Defined type alias Arrays[=A]\n\ndef stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)]\n//│ stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]\n\n\n:ns\ndef helper impl (k: ArraysImplConsumer['a2, 'res]) = k (stepImpl_ty impl)\n//│ helper: forall 'b 'a 'a0 'r 'r0. 'b -> (forall 'a2 'res 'a1 'c. ArraysImplConsumer['a2, 'res] -> 'c)\n//│   where\n//│     'res <: 'c\n//│     'a2 :> 'a\n//│         <: 'a1\n//│     'a1 :> 'a\n//│         <: 'a2 & 'a0\n//│     'b <: ArraysImpl[in 'a out 'a0, in 'r out 'r0]\n//│     'r0 :> 'r\n//│     'a <: 'a0\n//│     'a0 :> 'a\n\n// * Used to SOF in simplif:\nhelper\n//│ res: ArraysImpl[in 'a & 'a0 out 'a | 'a0, 'r] -> (forall 'a2 'b. ArraysImplConsumer['a2, 'b] -> 'b)\n//│   where\n//│     'a2 :> 'a\n//│         <: 'a0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_Records_min_3.mls",
    "content": ":NoRecursiveTypes\n:DontDistributeForalls\n:NoJS\n\n\ntype ArraysImpl[A] = { sub: A -> A }\n//│ Defined type alias ArraysImpl[=A]\n\ntype ArraysImplConsumer[A] = ArraysImpl[A] -> int\n//│ Defined type alias ArraysImplConsumer[=A]\n\ndef stepImpl_ty: ArraysImpl['a] -> ArraysImpl['a]\n//│ stepImpl_ty: ArraysImpl['a] -> ArraysImpl['a]\n\n\n// * There used to be a wrongly-simplified `'a <: nothing` bound here\ndef s arr (k: ArraysImplConsumer['a]) = arr (fun impl -> k (stepImpl_ty impl))\n//│ s: ((ArraysImpl['a] -> int) -> 'b) -> ArraysImplConsumer['a] -> 'b\n\n// * ...although we could see that it shouldn't be simplified to nothing:\n:ns\ns\n//│ res: forall 'b 'a 'a0 'c. 'b -> (forall 'a1 'd. ArraysImplConsumer['a1] -> 'd)\n//│   where\n//│     'd :> 'c\n//│     'a1 :> 'a0\n//│         <: 'a\n//│     'b <: (forall 'e 'a2 'f. 'e -> 'f) -> 'c\n//│     'f :> int\n//│     'e <: ArraysImpl['a2]\n//│     'a2 :> 'a\n//│         <: 'a0\n//│     'a <: 'a0\n//│     'a0 <: 'a\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/QML_exist_nu.mls",
    "content": "// * TODO also a GADT version of this where we use `Arrays[A]: ArraysImpl[A, ?]`\n\n:NewDefs\n\n:DontDistributeForalls // * Also works without this\n\n\n\ndeclare module Math {\n  fun trunc: Num -> Int\n}\n//│ declare module Math {\n//│   fun trunc: Num -> Int\n//│ }\n\nfun div(a, b) = Math.trunc(a/b)\nfun mod(a, b) = if a < b then a else mod(a - b, b)\n//│ fun div: (Num, Num) -> Int\n//│ fun mod: (Int, Int) -> Int\n\n\n\nabstract class ArraysImpl[A, Rep] {\n  fun init: A -> Rep\n  fun sub: (Rep, Int) -> A\n  fun update: (Rep, Int, A) -> Rep\n  fun fold: (Rep, 'b, A -> 'b -> 'b) -> 'b\n}\n//│ abstract class ArraysImpl[A, Rep] {\n//│   fun fold: forall 'b. (Rep, 'b, A -> 'b -> 'b) -> 'b\n//│   fun init: A -> Rep\n//│   fun sub: (Rep, Int) -> A\n//│   fun update: (Rep, Int, A) -> Rep\n//│ }\n\ntype ArraysImplConsumer[A, R] = forall 'rep: ArraysImpl[A, 'rep] -> R\n//│ type ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R\n\nabstract class Arrays[A] {\n  fun use: ArraysImplConsumer[A, 'res] -> 'res\n}\n//│ abstract class Arrays[A] {\n//│   fun use: forall 'res. ArraysImplConsumer[A, 'res] -> 'res\n//│ }\n\n\nclass BaseImpl[A]() extends ArraysImpl[A, A] {\n    fun init  (a) = a\n    fun sub   (r, i) = r\n    fun update(r, i, a) = a\n    fun fold  (r, b, f) = f(r)(b)\n}\n//│ class BaseImpl[A]() extends ArraysImpl {\n//│   fun fold: forall 'a 'b 'c. ('a, 'b, 'a -> 'b -> 'c) -> 'c\n//│   fun init: forall 'd. 'd -> 'd\n//│   fun sub: forall 'e. ('e, anything) -> 'e\n//│   fun update: forall 'f. (anything, anything, 'f) -> 'f\n//│ }\n\nclass StepImpl[A, R](underlying: ArraysImpl[A, R]) extends ArraysImpl[A, [R, R]] {\n  fun init(a) = [underlying.init(a), underlying.init(a)]\n  fun sub([r0, r1], i) =\n    if mod(i, 2) === 0\n    then underlying.sub(r0, div(i, 2))\n    else underlying.sub(r1, div(i, 2))\n  fun update([r0, r1], i, a) =\n    if mod(i, 2) == 0\n    then [underlying.update(r0, div(i, 2), a), r1]\n    else [r0, underlying.update(r1, div(i, 2), a)]\n  fun fold([r0, r1], b, f) =\n    underlying.fold(r0, underlying.fold(r1, b, f), f)\n}\n//│ class StepImpl[A, R](underlying: ArraysImpl[A, R]) extends ArraysImpl {\n//│   fun fold: forall 'b 'b0. ([R, R], 'b & 'b0, A -> ('b -> ('b & 'b0) & 'b0 -> 'b0)) -> 'b0\n//│   fun init: A -> [R, R]\n//│   fun sub: ([R, R], Eql[0] & Int) -> A\n//│   fun update: ([R, R], Int, A) -> [R, R]\n//│ }\n\n\nclass Base[A]() extends Arrays[A] {\n  val impl = BaseImpl()\n  fun use(k) = k(impl)\n}\n//│ class Base[A]() extends Arrays {\n//│   val impl: BaseImpl[A]\n//│   fun use: forall 'a. (BaseImpl[A] -> 'a) -> 'a\n//│ }\n\nclass Step[A](from: Arrays[A]) extends Arrays[A] {\n  \n  // * Note: expansion of alias is capture-avoiding of polymorphic levels\n  fun use(k: ArraysImplConsumer[A, 'res]) = from.use of\n    forall 'rep:\n      (impl: ArraysImpl[A, 'rep]) => k(StepImpl(impl))\n  \n}\n//│ class Step[A](from: Arrays[A]) extends Arrays {\n//│   fun use: forall 'res. (k: ArraysImplConsumer[A, 'res]) -> 'res\n//│ }\n\n// * A version with fewer annotations\nclass Step[A](from: Arrays[A]) extends Arrays[A] {\n  \n  fun use(k: ArraysImplConsumer[A, 'res]) =\n    from.use of impl => k(StepImpl(impl))\n  \n  // * Spelling out the type synonym:\n  fun use': ArraysImplConsumer[A, 'res] -> 'res\n  fun use'(k: forall 'rep: ArraysImpl[A, 'rep] -> 'res) =\n    from.use of impl => k of StepImpl(impl)\n  \n}\n//│ class Step[A](from: Arrays[A]) extends Arrays {\n//│   fun use: forall 'res. (k: ArraysImplConsumer[A, 'res]) -> 'res\n//│   fun use': forall 'res0. ArraysImplConsumer[A, 'res0] -> 'res0\n//│ }\n\n// * Note: the annotation on `k` is required, otherwise we leak the locally-polymorphic `impl`\n// * (We don't currently do any bidirectional typing.)\n:e\nclass Step'[A](from: Arrays[A]) extends Arrays[A] {\n  fun use(k) =\n    from.use of impl => k(StepImpl(impl))\n}\n//│ ╔══[ERROR] Type error in definition of method use\n//│ ║  l.123: \t  fun use(k) =\n//│ ║         \t      ^^^^^^^^\n//│ ║  l.124: \t    from.use of impl => k(StepImpl(impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.36: \ttype ArraysImplConsumer[A, R] = forall 'rep: ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.124: \t    from.use of impl => k(StepImpl(impl))\n//│ ║         \t                                   ^^^^\n//│ ╟── • this signature of member `use`:\n//│ ║  l.40: \t  fun use: ArraysImplConsumer[A, 'res] -> 'res\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this field selection:\n//│ ║  l.124: \t    from.use of impl => k(StepImpl(impl))\n//│ ╙──       \t    ^^^^^^^^\n//│ class Step'[A](from: Arrays[A]) extends Arrays {\n//│   fun use: forall 'a. (StepImpl[A, in ??rep] -> 'a) -> 'a\n//│ }\n//│ Syntax error:\n//│   Unexpected string\n\n\nlet ssb = Step(Step(Base()))\n//│ let ssb: Step['A]\n//│ ssb\n//│     = Step {}\n\nssb.use of impl =>\n  let r = impl.update(impl.init(true), 1, false)\n  log(r)\n  [impl.sub(r, 0), impl.sub(r, 1)]\n//│ [Bool, Bool]\n//│ res\n//│     = [ true, false ]\n//│ // Output\n//│ [ [ true, true ], [ false, true ] ]\n\nfun mkMonoArray(n) =\n  if n === 0 then Base() else Step(mkMonoArray(n - 1))\n//│ fun mkMonoArray: forall 'A. (Eql[0] & Int) -> (Base['A] | Step['A])\n\nlet snb = mkMonoArray(3)\n//│ let snb: Base['A] | Step['A]\n//│ snb\n//│     = Step {}\n\nsnb.use of impl =>\n  let r = impl.update(impl.init(true), 1, false)\n  log(r)\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ [\n//│   [ [ true, true ], [ true, true ] ],\n//│   [ [ false, true ], [ true, true ] ]\n//│ ]\n\n// * Here we are trying to leak the internally-quantified representation, resulting in the `??rep` extrusion\nsnb.use of impl => impl.init(true)\n// :d\n//│ anything\n//│ res\n//│     = [\n//│         [ [ true, true ], [ true, true ] ],\n//│         [ [ true, true ], [ true, true ] ]\n//│       ]\n\n\n// * An alternative implementation of Step with the existential opened outside the function.\n\nclass StepAlt[A](from: Arrays[A]) extends Arrays[A] {\n  val use = from.use of impl =>\n    (k: ArraysImplConsumer[A, 'res]) => k(StepImpl(impl))\n}\n//│ class StepAlt[A](from: Arrays[A]) extends Arrays {\n//│   val use: forall 'res. (k: ArraysImplConsumer[A, 'res]) -> 'res\n//│ }\n\n// * With the following, we get \"type variable `'rep` leaks out of its scope\"\n:e\nclass StepAlt'[A](from: Arrays[A]) extends Arrays[A] {\n  val use = from.use of impl =>\n    k => k(StepImpl(impl))\n    // * ^ This is because we leak impl's representation to `k` in the local `k =>` lambda,\n    // * which flows to the type of `use`, where it's extruded:\n    // *    forall 'r; (StepImpl[A, ??impl] -> 'r) -> 'r\n    // * Interestingly, once we use first-class existentials to extrude things,\n    // * this should start working, because we'll get\n    // *    exists impl; forall 'r; (StepImpl[A, impl] -> 'r) -> 'r\n    // * which is a sutbype of the required\n    // *    (forall 'rep; ArraysImpl[A, 'rep] -> 'res) -> 'res\n    // * because we can 0-rigidify `impl` and then subtype\n    // *    0. (StepImpl[A, impl] -> 'r) -> 'r  <:  (forall 'rep; ArraysImpl[A, 'rep] -> 'res) -> 'res\n    // * ie, constraining the parameters and 1-instantiating `forall 'rep`:\n    // *    1. ArraysImpl[A, 'rep] -> 'res  <:  (StepImpl[A, impl] -> 'r) -> 'r\n    // * which eventually leads to 'rep := impl and 'r := 'res.\n}\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.211: \t  val use = from.use of impl =>\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^\n//│ ║  l.212: \t    k => k(StepImpl(impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'rep` leaks out of its scope\n//│ ║  l.36: \ttype ArraysImplConsumer[A, R] = forall 'rep: ArraysImpl[A, 'rep] -> R\n//│ ║        \t                                                           ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.211: \t  val use = from.use of impl =>\n//│ ║         \t                        ^^^^^^^\n//│ ║  l.212: \t    k => k(StepImpl(impl))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this signature of member `use`:\n//│ ║  l.40: \t  fun use: ArraysImplConsumer[A, 'res] -> 'res\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this field selection:\n//│ ║  l.211: \t  val use = from.use of impl =>\n//│ ╙──       \t            ^^^^^^^^\n//│ class StepAlt'[A](from: Arrays[A]) extends Arrays {\n//│   val use: forall 'R 'a. error | (StepImpl[A, 'R] -> 'a) -> 'a\n//│ }\n//│ where\n//│   'R :> ??rep\n//│      <: ??rep0\n//│ Syntax error:\n//│   Unexpected string\n\n\n// * An alternative implementation of Step which only allocates one StepImpl per instance!\n\nclass StepAlt[A](from: Arrays[A]) extends Arrays[A] {\n  \n  // * The explicit `forall 'res` is needed with distributivity turned off\n  val use = forall 'res: from.use of impl =>\n    val impl2 = StepImpl(impl)\n    (k: ArraysImplConsumer[A, 'res]) => k(impl2)\n  \n  // * Version with full annotations (not necessary):\n  val use2: ArraysImplConsumer[A, 'res] -> 'res\n  val use2 = forall 'res: from.use of forall 'rr: (impl : ArraysImpl[A, 'rr]) =>\n    val impl2 = StepImpl(impl)\n    (k: ArraysImplConsumer[A, 'res]) => k(impl2)\n  \n}\n//│ class StepAlt[A](from: Arrays[A]) extends Arrays {\n//│   val use: forall 'res. (k: ArraysImplConsumer[A, 'res]) -> 'res\n//│   val use2: forall 'res0. ArraysImplConsumer[A, 'res0] -> 'res0\n//│ }\n\n\n// * A variation of the above without explicitly binding 'res, so it has to be distributed out\n\n:DistributeForalls // * Distributivity is needed here!\n\nclass StepAlt[A](from: Arrays[A]) extends Arrays[A] {\n  val use = from.use of impl =>\n    val impl2 = StepImpl(impl)\n    (k: ArraysImplConsumer[A, 'res]) => k(impl2)\n}\n//│ class StepAlt[A](from: Arrays[A]) extends Arrays {\n//│   val use: forall 'res. (k: ArraysImplConsumer[A, 'res]) -> 'res\n//│ }\n\n\n// * Works the same:\n\nlet ssb = StepAlt(StepAlt(Base()))\n//│ let ssb: StepAlt['A]\n//│ ssb\n//│     = StepAlt {}\n\nssb.use of impl =>\n  let r = impl.update(impl.init(true), 1, false)\n  log(r)\n  [impl.sub(r, 0), impl.sub(r, 1)]\n//│ [Bool, Bool]\n//│ res\n//│     = [ true, false ]\n//│ // Output\n//│ [ [ true, true ], [ false, true ] ]\n\nfun mkMonoArray(n) =\n  if n === 0 then Base() else StepAlt(mkMonoArray(n - 1))\n//│ fun mkMonoArray: forall 'A. (Eql[0] & Int) -> (forall 'A0. Base['A0] | StepAlt['A])\n\nlet snb = mkMonoArray(3)\n//│ let snb: forall 'A 'A0. Base['A] | StepAlt['A0]\n//│ snb\n//│     = StepAlt {}\n\nsnb.use of impl =>\n  let r = impl.update(impl.init(true), 1, false)\n  log(r)\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ [\n//│   [ [ true, true ], [ true, true ] ],\n//│   [ [ false, true ], [ true, true ] ]\n//│ ]\n\nsnb.use of impl => impl.init(true)\n//│ anything\n//│ res\n//│     = [\n//│         [ [ true, true ], [ true, true ] ],\n//│         [ [ true, true ], [ true, true ] ]\n//│       ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Rank2.mls",
    "content": ":NoRecursiveTypes\n:NoConstrainedTypes\n:DontDistributeForalls\n\n\n// --------- //\n\n\ndef test (f: forall 'a. 'a -> 'a) =\n  f\n//│ test: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│     = [Function: test]\n\ntest(f: forall 'a. 'a -> 'a) =\n  f 1\n//│ test: (forall 'a. 'a -> 'a) -> 1\n//│     = [Function: test1]\n\ntest(f: forall 'a. 'a -> 'a) =\n  (f 1, f true)\n//│ test: (forall 'a. 'a -> 'a) -> (1, true,)\n//│     = [Function: test2]\n\n\ntest id\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\ntest(fun x -> x)\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\ntest(fun x ->\n  let tmp = log x\n  in x)\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ // Output\n//│ 1\n//│ true\n\n:e\ntest(fun x -> x + 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.43: \ttest(fun x -> x + 1)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.19: \ttest(f: forall 'a. 'a -> 'a) =\n//│ ║        \t                   ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.43: \ttest(fun x -> x + 1)\n//│ ║        \t              ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.19: \ttest(f: forall 'a. 'a -> 'a) =\n//│ ╙──      \t               ^^\n//│ res: error | (1, true,)\n//│    = [ 2, 2 ]\n\n:e\ntest succ\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.60: \ttest succ\n//│ ║        \t^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.19: \ttest(f: forall 'a. 'a -> 'a) =\n//│ ║        \t                   ^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.19: \ttest(f: forall 'a. 'a -> 'a) =\n//│ ╙──      \t               ^^\n//│ res: error | (1, true,)\n//│    = [ 2, 2 ]\n\n\n// --------- //\n\n\ntest f =\n  ((f: forall 'a. 'a -> 'a) 1, f 2)\n//│ test: (forall 'a. 'a -> 'a & 2 -> 'b) -> (1, 'b,)\n//│     = [Function: test3]\n\ndef pair x y = test id\n//│ pair: anything -> anything -> (1, 2,)\n//│     = [Function: pair]\n\ndef pair x y = test (fun x -> (let tmp = log x in x))\n//│ pair: anything -> anything -> (1, 2,)\n//│     = [Function: pair1]\n\n\ndef test f =\n  pair (f 1) (f true)\n//│ test: ((1 | true) -> anything) -> (1, 2,)\n//│     = [Function: test4]\n\ntest id\n//│ res: (1, 2,)\n//│    = [ 1, 2 ]\n//│ // Output\n//│ 1\n//│ 2\n\n:e\ntest (fun x -> x + 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.104: \ttest (fun x -> x + 1)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.92: \t  pair (f 1) (f true)\n//│ ║        \t                ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.104: \ttest (fun x -> x + 1)\n//│ ╙──       \t               ^\n//│ res: error | (1, 2,)\n//│    = [ 1, 2 ]\n//│ // Output\n//│ 1\n//│ 2\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/RecExtr.mls",
    "content": ":NoRecursiveTypes\n:DontDistributeForalls\n:DontGeneralizeCurriedFunctions\n\n\n// * Note: funnily-recursive function\nrec def foo x y =\n  let tmp = foo x y in (x, y,)\n//│ foo: 'a -> 'b -> ('a, 'b,)\n//│    = [Function: foo]\n\nfoo\n//│ res: 'a -> 'b -> ('a, 'b,)\n//│    = [Function: foo]\n\ndef foo_ty: 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ foo_ty: 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│       = <missing implementation>\n\n\n:e // * Needs distributivity (see at the end)\nfoo_ty = foo\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  foo_ty:\n//│ 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.22: \tfoo_ty = foo\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.16: \tdef foo_ty: 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ ║        \t                              ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.16: \tdef foo_ty: 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ ║        \t                                         ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.22: \tfoo_ty = foo\n//│ ║        \t         ^^^\n//│ ╟── • this reference:\n//│ ║  l.8: \t  let tmp = foo x y in (x, y,)\n//│ ╙──     \t                           ^\n//│       = [Function: foo]\n\n:e // * Needs distributivity (see at the end)\nfoo_ty x y = (x, y,)\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  foo_ty:\n//│ 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.45: \tfoo_ty x y = (x, y,)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.16: \tdef foo_ty: 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ ║        \t                              ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.16: \tdef foo_ty: 'a -> (forall 'b. 'b -> ('a, 'b,))\n//│ ║        \t                                         ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.45: \tfoo_ty x y = (x, y,)\n//│ ╙──      \t                 ^\n//│       = [Function: foo_ty1]\n\n\nrec def foo2 x y z =\n  let tmp = foo2 x y z in (x, y, z)\n//│ foo2: 'a -> 'b -> 'c -> ('a, 'b, 'c,)\n//│     = [Function: foo2]\n\ndef foo2_ty: 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│ foo2_ty: 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│        = <missing implementation>\n\n:e\nfoo2_ty = foo2\n//│ 'a -> 'b -> 'c -> ('a, 'b, 'c,)\n//│   <:  foo2_ty:\n//│ 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.75: \tfoo2_ty = foo2\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.70: \tdef foo2_ty: 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│ ║        \t                               ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.70: \tdef foo2_ty: 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│ ║        \t                                                            ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.75: \tfoo2_ty = foo2\n//│ ║        \t          ^^^^\n//│ ╟── • this reference:\n//│ ║  l.66: \t  let tmp = foo2 x y z in (x, y, z)\n//│ ╙──      \t                              ^\n//│        = [Function: foo2]\n\n:e // * Needs distributivity (see at the end)\nfoo2_ty x y z = (x, y, z,)\n//│ 'a -> 'b -> 'c -> ('a, 'b, 'c,)\n//│   <:  foo2_ty:\n//│ 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.98: \tfoo2_ty x y z = (x, y, z,)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.70: \tdef foo2_ty: 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│ ║        \t                               ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.70: \tdef foo2_ty: 'a -> (forall 'b. 'b -> (forall 'c. 'c -> ('a, 'b, 'c,)))\n//│ ║        \t                                                            ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.98: \tfoo2_ty x y z = (x, y, z,)\n//│ ╙──      \t                    ^\n//│        = [Function: foo2_ty1]\n\n\n\nrec def r x = let tmp = x in x\n//│ r: 'a -> 'a\n//│  = [Function: r]\n\nrec def x = x\n//│ x: nothing\n//│  = [Function: x]\n\n:e\nrec def lr1 = { tail = lr1 }\n//│ ╔══[ERROR] Inferred recursive type: 'lr1\n//│   where\n//│     'lr1 :> {tail: 'lr1}\n//│ ╙──\n//│ lr1: 'lr1\n//│   where\n//│     'lr1 :> {tail: 'lr1}\n//│    = [Function: lr1]\n\n:e\nrec def lr1 = { head = 0; tail = lr1 }\n//│ ╔══[ERROR] Inferred recursive type: 'lr1\n//│   where\n//│     'lr1 :> {head: 0, tail: 'lr1}\n//│ ╙──\n//│ lr1: 'lr1\n//│   where\n//│     'lr1 :> {head: 0, tail: 'lr1}\n//│    = [Function: lr11]\n\n\n\n// * With distributivity:\n:DistributeForalls\n\n\nfoo_ty = foo\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  foo_ty:\n//│ 'a -> 'b -> ('a, 'b,)\n//│       = [Function: foo]\n\n\nfoo_ty x y = (x, y,)\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  foo_ty:\n//│ 'a -> 'b -> ('a, 'b,)\n//│       = [Function: foo_ty3]\n\n\nfoo2_ty = foo2\n//│ 'a -> 'b -> 'c -> ('a, 'b, 'c,)\n//│   <:  foo2_ty:\n//│ 'a -> 'b -> 'c -> ('a, 'b, 'c,)\n//│        = [Function: foo2]\n\n\nfoo2_ty x y z = (x, y, z,)\n//│ 'a -> 'b -> 'c -> ('a, 'b, 'c,)\n//│   <:  foo2_ty:\n//│ 'a -> 'b -> 'c -> ('a, 'b, 'c,)\n//│        = [Function: foo2_ty3]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/SelfAppMin.mls",
    "content": ":NoRecursiveTypes\n\n\nclass L\nclass A: { f: anything }\n//│ Defined class L\n//│ Defined class A\n\n\n\ndef eval eval x = case x of\n  L -> 0,\n  A -> eval eval x.f\n//│ eval: ('a -> 'f -> 'b & 'a) -> ((A with {f: 'f}) | L) -> (0 | 'b)\n//│     = [Function: eval]\n\n\n:e\ne = eval eval\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.19: \te = eval eval\n//│ ║        \t    ^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ e: error | (A & {f: A | L} | L) -> 0\n//│  = [Function (anonymous)]\n\ne (A{f = L{}})\n//│ res: 0 | error\n//│    = 0\n\n\n:e\ne = eval eval!\n//│ ╔══[ERROR] Inferred recursive type: 'f\n//│   where\n//│     'f <: A with {f: 'f}\n//│ ║  l.13: \t  A -> eval eval x.f\n//│ ╙──      \t                 ^^^\n//│ e: 'a -> 0\n//│   where\n//│     'a <: (A with {f: 'a}) | L\n//│  = [Function (anonymous)]\n\n:e\ne (A{f = L{}})\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: {f: A & 'a}\n//│ ║  l.11: \tdef eval eval x = case x of\n//│ ╙──      \t                       ^\n//│ res: 0\n//│    = 0\n\n:e\n// * Note: this computation will diverge\nrec def v = A{f = v}\n//│ ╔══[ERROR] Inferred recursive type: 'f\n//│   where\n//│     'f :> A with {f: 'f}\n//│ ╙──\n//│ v: 'f\n//│   where\n//│     'f :> A with {f: 'f}\n//│  = [Function: v]\n\n:e\ne v\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: {f: A & 'a}\n//│ ║  l.11: \tdef eval eval x = case x of\n//│ ╙──      \t                       ^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.67: \te v\n//│ ║        \t^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: 0 | error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:RecursiveTypes\n\n// * Note: Expected divergence\n:re\ne v\n//│ res: 0\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n\ndef eval eval x = case x of\n  L -> 0,\n  A -> { x = eval eval x.f }\n//│ eval: ('a -> 'f -> 'b & 'a) -> ((A with {f: 'f}) | L) -> (0 | {x: 'b})\n//│     = [Function: eval1]\n\n\n:e\ne = eval eval\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.100: \te = eval eval\n//│ ║         \t    ^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ e: error | (A & {f: A | L} | L) -> (0 | {x: 0 | {x: nothing}})\n//│  = [Function (anonymous)]\n\n:re\ne v\n//│ res: 0 | error | {x: 0 | {x: nothing}}\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\ne = eval eval!\n//│ e: 'a -> 'b\n//│   where\n//│     'b :> 0 | {x: 'b}\n//│     'a <: A & {f: 'a} | L\n//│  = [Function (anonymous)]\n\n:re\ne v\n//│ res: 'a\n//│   where\n//│     'a :> 0 | {x: 'a}\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Simplif.mls",
    "content": ":NoJS\n\n\ndef f: 'a -> int\n//│ f: anything -> int\n\ndef f: forall 'a. 'a -> int\n//│ f: anything -> int\n\ndef f: forall 'a. int -> 'a\n//│ f: int -> nothing\n\ndef f: 'a -> 'b -> ('a, 'b)\n//│ f: 'a -> 'b -> ('a, 'b,)\n\ndef f: (forall 'a. 'a -> 'b) -> 'b\n//│ f: (anything -> 'b) -> 'b\n\ndef f: (forall 'a. 'b -> 'a) -> 'b\n//│ f: (nothing -> nothing) -> nothing\n\ndef f: (forall 'a. 'b -> 'a) -> 'b -> 'b\n//│ f: ('b -> nothing) -> 'b -> 'b\n\n\ndef bar: forall 'a. 'a -> int\n//│ bar: anything -> int\n\ndef foo: (forall 'a. 'a -> 'b) -> 'b\n//│ foo: (anything -> 'b) -> 'b\n\nfoo bar\n//│ res: int\n\ndef foo: MutArray[forall 'a. 'a -> 'b] -> 'b\n//│ foo: MutArray[anything -> 'b] -> 'b\n\ndef foo: (forall 'a. MutArray['a -> 'b]) -> 'b\n//│ foo: (forall 'a. MutArray['a -> 'b]) -> 'b\n\n// def foo: MutArray[forall 'b. forall 'a {'a <: 'b}. ('a .. 'b) -> 'b] -> 'b\n\n// def foo: MutArray[forall 'b. forall 'a. ('a .. 'b) -> ('a .. 'b)] -> 'b\n\n\ndef foo: forall 'a 'b. ('a & 'b) -> ('a | 'b)\n//│ foo: 'b -> 'b\n\ndef foo: (forall 'a 'b. ('a & 'b) -> ('a | 'b)) -> 1\n//│ foo: (forall 'b. 'b -> 'b) -> 1\n\ndef foo: ((forall 'a 'b. ('a & 'b) -> ('a | 'b)) -> 1) -> 2\n//│ foo: ((forall 'b. 'b -> 'b) -> 1) -> 2\n\ndef foo: (((forall 'a 'b. ('a & 'b) -> ('a | 'b)) -> 1) -> 2) -> 3\n//│ foo: (((forall 'b. 'b -> 'b) -> 1) -> 2) -> 3\n\n\n// * Note that this degenerate type is equivalent to `anything -> nothing`\n// * (Take 'a = Int and 'b = ~Int.)\ndef foo: forall 'a 'b. ('a | 'b) -> ('a & 'b)\n//│ foo: ('a | 'b) -> ('a & 'b)\nfoo (1 : anything) : nothing\n//│ res: nothing\n\ndef foo: (forall 'a 'b. ('a | 'b) -> ('a & 'b)) -> 1\n//│ foo: (forall 'a 'b. ('a | 'b) -> ('a & 'b)) -> 1\n\n:e\nfoo id\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.70: \tfoo id\n//│ ║        \t^^^^^^\n//│ ╟── type `'a` does not match type `'b`\n//│ ║  l.66: \tdef foo: (forall 'a 'b. ('a | 'b) -> ('a & 'b)) -> 1\n//│ ║        \t                         ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.66: \tdef foo: (forall 'a 'b. ('a | 'b) -> ('a & 'b)) -> 1\n//│ ║        \t                                           ^^\n//│ ╟── from intersection type:\n//│ ║  l.66: \tdef foo: (forall 'a 'b. ('a | 'b) -> ('a & 'b)) -> 1\n//│ ║        \t                                     ^^^^^^^^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.66: \tdef foo: (forall 'a 'b. ('a | 'b) -> ('a & 'b)) -> 1\n//│ ╙──      \t                 ^^\n//│ res: 1 | error\n\n\ndef foo: MutArray[forall 'a 'b. ('a & 'b) -> ('a | 'b)]\n//│ foo: MutArray[forall 'b. 'b -> 'b]\n\ndef foo: MutArray[MutArray[(forall 'a 'b. ('a & 'b) -> ('a | 'b)) -> 1]]\n//│ foo: MutArray[MutArray[(forall 'b. 'b -> 'b) -> 1]]\n\n\ndef foo: forall 'a 'b. ('a & 'b) -> 'a -> 'b -> ('a | 'b, 'b | 'a)\n//│ foo: 'a -> 'a -> 'a -> ('a, 'a,)\n\ndef foo: (forall 'a 'b. ('a & 'b) -> 'a -> 'b -> ('a | 'b, 'b | 'a)) -> 1\n//│ foo: (forall 'a. 'a -> 'a -> 'a -> ('a, 'a,)) -> 1\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/SkolemErrors.mls",
    "content": "\n:NoJS\n\n\ndef k: (forall 'a. 'a -> 'a) -> int\n//│ k: (forall 'a. 'a -> 'a) -> int\n\n\nfun x -> k x\n//│ res: (forall 'a. 'a -> 'a) -> int\n\nfun x -> k (fun y -> x y)\n//│ res: (??a -> ??a0) -> int\n\n\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n:e\nk (fun x -> x + 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tk (fun x -> x + 1)\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.5: \tdef k: (forall 'a. 'a -> 'a) -> int\n//│ ║       \t                   ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.+1: \tk (fun x -> x + 1)\n//│ ║        \t            ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.5: \tdef k: (forall 'a. 'a -> 'a) -> int\n//│ ╙──     \t               ^^\n//│ res: error | int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Skolems.mls",
    "content": ":NoRecursiveTypes\n// :GeneralizeArguments\n\n\ndef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\ndef auto_ x = x x\n//│ auto_: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│      = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  auto_:\n//│ (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│      = [Function: auto_]\n\nfun (x: (forall 'a. 'a -> 'a)) -> auto_ x\n//│ res: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│    = [Function: res]\n\n// * Compares an extruded higher-level skolem; rightly rejected\n:e\nfun (x: ('a -> 'a)) -> auto_ x\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.20: \tfun (x: ('a -> 'a)) -> auto_ x\n//│ ║        \t                       ^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ╙──     \t                              ^^\n//│ res: (anything -> ??a) -> (error | 'b -> 'b)\n//│    = [Function: res]\n\nfoo(x: ('a -> 'b)) = auto_ x\n//│ foo: (??a -> ??a0) -> 'b -> 'b\n//│    = [Function: foo]\n\n:e\nfoo (fun x -> x)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.38: \tfoo (fun x -> x)\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                              ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.33: \tfoo(x: ('a -> 'b)) = auto_ x\n//│ ╙──      \t              ^^\n//│ res: error | 'b -> 'b\n//│    = [Function (anonymous)]\n\n:e\nfoo (fun x -> 0)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.55: \tfoo (fun x -> 0)\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.55: \tfoo (fun x -> 0)\n//│ ║        \t              ^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.33: \tfoo(x: ('a -> 'b)) = auto_ x\n//│ ╙──      \t              ^^\n//│ res: error | 'b -> 'b\n//│    = 0\n\n:e\nfoo (fun x -> foo (fun y -> y) x)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.69: \tfoo (fun x -> foo (fun y -> y) x)\n//│ ║        \t              ^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                              ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.33: \tfoo(x: ('a -> 'b)) = auto_ x\n//│ ╙──      \t              ^^\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.69: \tfoo (fun x -> foo (fun y -> y) x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                              ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.33: \tfoo(x: ('a -> 'b)) = auto_ x\n//│ ╙──      \t              ^^\n//│ res: error | 'b -> 'b\n//│    = [Function (anonymous)]\n\n// * This would be unsound; `fun y -> x` does not have type `forall 'a. 'a -> 'a` but it is eventually passed to auto_\n:e\nfoo (fun x -> foo (fun y -> x) x)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.99: \tfoo (fun x -> foo (fun y -> x) x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.5: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║       \t                              ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.99: \tfoo (fun x -> foo (fun y -> x) x)\n//│ ╙──      \t                            ^\n//│ res: error | 'b -> 'b\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n// * Producing an actual crash from this:\n\ndef oops (i: forall 'a. 'a -> 'a) =\n  let _ = (i id) \"hello\"\n  in i\n//│ oops: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│     = [Function: oops]\n\n// If we were not careful this would lead to unsound skolem extrusion:\ndef extrude (f: 'a -> 'b) = oops f\n//│ extrude: (??a -> ??a0) -> 'a -> 'a\n//│        = [Function: extrude]\n\n:e\nf = extrude (fun x -> extrude (fun y -> x) x)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.131: \tf = extrude (fun x -> extrude (fun y -> x) x)\n//│ ║         \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.119: \tdef oops (i: forall 'a. 'a -> 'a) =\n//│ ║         \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.119: \tdef oops (i: forall 'a. 'a -> 'a) =\n//│ ║         \t                              ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.131: \tf = extrude (fun x -> extrude (fun y -> x) x)\n//│ ╙──       \t                                        ^\n//│ f: error | 'a -> 'a\n//│  = [Function (anonymous)]\n\n:re\nf 42 // Boom!\n//│ res: 42 | error\n//│ Runtime error:\n//│   TypeError: i(...) is not a function\n\n\n\ndef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ swapWith: (forall 'x 'y. (('x, 'y,),) -> ('y, 'x,)) -> ('a, 'b,) -> ('b, 'a,)\n//│         = <missing implementation>\n\ndef swapWith f (a, b) = f ((a, b))\n//│ ((('a, 'b,),) -> 'c) -> ('a, 'b,) -> 'c\n//│   <:  swapWith:\n//│ (forall 'x 'y. (('x, 'y,),) -> ('y, 'x,)) -> ('a, 'b,) -> ('b, 'a,)\n//│         = [Function: swapWith]\n\n\n// * This is an error because it would force the swapped tuple to be the same 'a as the original\n:e\nfun (x: ('a -> 'a)) -> swapWith x\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.168: \tfun (x: ('a -> 'a)) -> swapWith x\n//│ ║         \t                       ^^^^^^^^^^\n//│ ╟── type variable `'x` leaks out of its scope\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ║         \t                               ^^\n//│ ╟── back into type variable `'y`\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ╙──       \t                                             ^^\n//│ res: (((??x, ??y,) | 'a) -> ((??y0, ??x0,) & 'a)) -> (error | ('a0, 'b,) -> ('b, 'a0,))\n//│    = [Function: res]\n\nfoo = fun (x: ('a -> 'b)) -> swapWith x\n//│ foo: (((??x, ??y,),) -> (??y0, ??x0,)) -> ('a, 'b,) -> ('b, 'a,)\n//│    = [Function: foo1]\n\nbar = fun f -> foo f (1, 2)\n//│ bar: (((??x, ??y,),) -> (??y0, ??x0,)) -> (2, 1,)\n//│    = [Function: bar]\n\n:e\nbar (fun ((u, v),) -> (v, u))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.190: \tbar (fun ((u, v),) -> (v, u))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'y` leaks out of its scope\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'y`\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ╙──       \t                                             ^^\n//│ res: error | (2, 1,)\n//│    = [ 2, 1 ]\n\n:e\nbar (fun ((u1, v1),) -> let tmp = bar (fun ((u2, v2),) -> (v2, u2)) in (v1, u1))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.204: \tbar (fun ((u1, v1),) -> let tmp = bar (fun ((u2, v2),) -> (v2, u2)) in (v1, u1))\n//│ ║         \t                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'y` leaks out of its scope\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'y`\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ╙──       \t                                             ^^\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.204: \tbar (fun ((u1, v1),) -> let tmp = bar (fun ((u2, v2),) -> (v2, u2)) in (v1, u1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'y` leaks out of its scope\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'y`\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ╙──       \t                                             ^^\n//│ res: error | (2, 1,)\n//│    = [ 2, 1 ]\n\n:e // * Not sure why this one is rejected (but the `extrude` version above is accepted.)\nbar (fun ((u1, v1),) -> let tmp = bar (fun ((u2, v2),) -> (v1, u1)) in (v1, u1))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.227: \tbar (fun ((u1, v1),) -> let tmp = bar (fun ((u2, v2),) -> (v1, u1)) in (v1, u1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'x` leaks out of its scope\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ║         \t                               ^^\n//│ ╟── back into type variable `'x`\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ║         \t                                                 ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.227: \tbar (fun ((u1, v1),) -> let tmp = bar (fun ((u2, v2),) -> (v1, u1)) in (v1, u1))\n//│ ╙──       \t                                                               ^^\n//│ res: error\n//│    = [ 2, 1 ]\n\n\n:e\nfun (x: ((('a, 'b),) -> ('b, 'a))) -> swapWith x\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.245: \tfun (x: ((('a, 'b),) -> ('b, 'a))) -> swapWith x\n//│ ║         \t                                      ^^^^^^^^^^\n//│ ╟── type variable `'y` leaks out of its scope\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'y`\n//│ ║  l.155: \tdef swapWith: (forall 'x 'y. (('x, 'y),) -> ('y, 'x)) -> ('a, 'b) -> ('b, 'a)\n//│ ╙──       \t                                             ^^\n//│ res: (((anything, anything,),) -> (??y, ??x,)) -> (error | ('a, 'b,) -> ('b, 'a,))\n//│    = [Function: res]\n\nfun (x: ((('a, 'b),) -> ('c, 'd))) -> swapWith x\n//│ res: (((??x, ??y,),) -> (??y0, ??x0,)) -> ('a, 'b,) -> ('b, 'a,)\n//│    = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Skolems2.mls",
    "content": ":NoRecursiveTypes\n:ConstrainedTypes\n:DontDistributeForalls\n// \n\n\n// * This asks for a polymorphic function and leverages that polymorphism\ndef oops (i: forall 'c. ('c -> 'c, 0)) =\n  let _ = log \"Hi!\"\n  in let _ = (fun ((f, 0)) ->\n    let _ = log f\n    in let r = (f id) \"hello\"\n    in log r) i\n  in (fun ((f, 0)) -> f) i\n//│ oops: (forall 'c. ('c -> 'c, 0,)) -> 'c0 -> 'c0\n//│     = [Function: oops]\n\n// * Notice the skolem extrusion/leakage which extrudes into `anything -> nothing`\ndef extrude f = oops((f, 0))\n//│ extrude: (??c -> ??c0) -> 'c -> 'c\n//│        = [Function: extrude]\n\n:e\nextrude(id)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.24: \textrude(id)\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                         ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                               ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this tuple literal:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ║        \t                     ^^^^^^\n//│ ╟── • this function:\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.9: \t  let _ = log \"Hi!\"\n//│ ║       \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.10: \t  in let _ = (fun ((f, 0)) ->\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.11: \t    let _ = log f\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.12: \t    in let r = (f id) \"hello\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.13: \t    in log r) i\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ║  l.14: \t  in (fun ((f, 0)) -> f) i\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ╙──      \t                ^^^^\n//│ res: error | 'c -> 'c\n//│    = [Function: id]\n//│ // Output\n//│ Hi!\n//│ [Function: id]\n//│ hello\n\n:e\nextrude(id)(42)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.64: \textrude(id)(42)\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                         ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                               ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this tuple literal:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ║        \t                     ^^^^^^\n//│ ╟── • this function:\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.9: \t  let _ = log \"Hi!\"\n//│ ║       \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.10: \t  in let _ = (fun ((f, 0)) ->\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.11: \t    let _ = log f\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.12: \t    in let r = (f id) \"hello\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.13: \t    in log r) i\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ║  l.14: \t  in (fun ((f, 0)) -> f) i\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ╙──      \t                ^^^^\n//│ res: 42 | error\n//│    = 42\n//│ // Output\n//│ Hi!\n//│ [Function: id]\n//│ hello\n\n:e\nextrude(id)(id)(42)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.104: \textrude(id)(id)(42)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                         ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                               ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this tuple literal:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ║        \t                     ^^^^^^\n//│ ╟── • this function:\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.9: \t  let _ = log \"Hi!\"\n//│ ║       \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.10: \t  in let _ = (fun ((f, 0)) ->\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.11: \t    let _ = log f\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.12: \t    in let r = (f id) \"hello\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.13: \t    in log r) i\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ║  l.14: \t  in (fun ((f, 0)) -> f) i\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ╙──      \t                ^^^^\n//│ res: 42 | error\n//│    = 42\n//│ // Output\n//│ Hi!\n//│ [Function: id]\n//│ hello\n\n// * This clearly shouldn't be possible – it passes one skolem as the other\n:e\nf = extrude (fun x -> extrude (fun y -> x) x)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.145: \tf = extrude (fun x -> extrude (fun y -> x) x)\n//│ ║         \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                         ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t                               ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this tuple literal:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ║        \t                     ^^^^^^\n//│ ╟── • this function:\n//│ ║  l.8: \tdef oops (i: forall 'c. ('c -> 'c, 0)) =\n//│ ║       \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.9: \t  let _ = log \"Hi!\"\n//│ ║       \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.10: \t  in let _ = (fun ((f, 0)) ->\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.11: \t    let _ = log f\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.12: \t    in let r = (f id) \"hello\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.13: \t    in log r) i\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ║  l.14: \t  in (fun ((f, 0)) -> f) i\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.19: \tdef extrude f = oops((f, 0))\n//│ ║        \t                ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.145: \tf = extrude (fun x -> extrude (fun y -> x) x)\n//│ ╙──       \t                                        ^\n//│ f: error | 'c -> 'c\n//│  = [Function (anonymous)]\n//│ // Output\n//│ Hi!\n//│ [Function (anonymous)]\n//│ Hi!\n//│ [Function (anonymous)]\n//│ hello\n//│ hello\n\n// * Boom! (exhibits crash using ill-typed `f` above)\n:re\nf 42\n//│ res: 42 | error\n//│ Runtime error:\n//│   TypeError: f(...) is not a function\n//│ // Output\n//│ Hi!\n//│ [Function (anonymous)]\n\n// * Note: parser parses this the same as `oops((f, 0)._1)`\ndef extrude f = oops((f, 0)).0\n//│ extrude: (forall 'c. ('c -> 'c, 0,)) -> 'c0 -> 'c0\n//│        = [Function: extrude1]\n\n\n\n// *** Other random tests ***\n\n\n\ndef oops (i: forall 'c. ('c -> 'c, 0)) =\n  let _ = (i.0 id) \"hello\"\n  in i.0\n//│ oops: (forall 'c. ('c -> 'c, 0,)) -> 'c0 -> 'c0\n//│     = [Function: oops1]\n\ndef oops (i: forall 'c. ('c -> 'c, 0)) =\n  let _ = log \"Hi!\"\n  in (fun ((f, 0)) ->\n    let _ = log f\n    in let r = (f id) \"hello\"\n    in let _ = log r\n    in f) i\n//│ oops: (forall 'c. ('c -> 'c, 0,)) -> (\"hello\" -> anything & 'c0) -> (forall 'a. 'a -> 'a | 'c0)\n//│     = [Function: oops2]\n\n\n\ndef foo(a, b) = (a, b) : forall 'c. ('c, 'c)\n//│ foo: (??c, ??c,) -> (nothing, nothing,)\n//│    = [Function: foo]\n\n:re\nfoo(error, error)\n//│ res: (nothing, nothing,)\n//│ Runtime error:\n//│   Error: an error was thrown\n\ndef foo(a, b) = (a, b) : forall 'c. ('c, 'c -> 'c)\n//│ foo: (??c, ??c0 -> ??c,) -> (forall 'c. ('c, 'c -> 'c,))\n//│    = [Function: foo1]\n\ndef foo(a, b) = (a, b) : forall 'c. ('c -> 'c, 'c -> 'c)\n//│ foo: (??c -> ??c0, ??c -> ??c0,) -> (forall 'c. ('c -> 'c, 'c -> 'c,))\n//│    = [Function: foo2]\n\n:e\nfoo(id, id)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.248: \tfoo(id, id)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.243: \tdef foo(a, b) = (a, b) : forall 'c. ('c -> 'c, 'c -> 'c)\n//│ ║         \t                                     ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.243: \tdef foo(a, b) = (a, b) : forall 'c. ('c -> 'c, 'c -> 'c)\n//│ ╙──       \t                                           ^^\n//│ res: error | ('c -> 'c, 'c -> 'c,)\n//│    = [ [Function: id], [Function: id] ]\n\n\ndef foo(f) = (fun a -> f a) : forall 'c. 'c -> 'c\n//│ foo: (??c -> ??c0) -> (forall 'c. 'c -> 'c)\n//│    = [Function: foo3]\n\n:e\nfoo(id)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.267: \tfoo(id)\n//│ ║         \t^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.262: \tdef foo(f) = (fun a -> f a) : forall 'c. 'c -> 'c\n//│ ║         \t                                         ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.262: \tdef foo(f) = (fun a -> f a) : forall 'c. 'c -> 'c\n//│ ║         \t                                               ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.262: \tdef foo(f) = (fun a -> f a) : forall 'c. 'c -> 'c\n//│ ╙──       \t                       ^^^\n//│ res: error | 'c -> 'c\n//│    = [Function (anonymous)]\n\n\ndef foo(a, b) = let tmp = (a, b) : forall 'c. ('c -> 'c, 0) in a\n//│ foo: (??c -> ??c0 & 'a, 0,) -> 'a\n//│    = [Function: foo4]\n\n:e\nfoo(id, 0)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.289: \tfoo(id, 0)\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.284: \tdef foo(a, b) = let tmp = (a, b) : forall 'c. ('c -> 'c, 0) in a\n//│ ║         \t                                               ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.284: \tdef foo(a, b) = let tmp = (a, b) : forall 'c. ('c -> 'c, 0) in a\n//│ ╙──       \t                                                     ^^\n//│ res: error | 'a -> 'a\n//│    = [Function: id]\n\n:e\nfoo(fun x -> foo(fun y -> x, 0) x, 0)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.303: \tfoo(fun x -> foo(fun y -> x, 0) x, 0)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.284: \tdef foo(a, b) = let tmp = (a, b) : forall 'c. ('c -> 'c, 0) in a\n//│ ║         \t                                               ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.284: \tdef foo(a, b) = let tmp = (a, b) : forall 'c. ('c -> 'c, 0) in a\n//│ ║         \t                                                     ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.303: \tfoo(fun x -> foo(fun y -> x, 0) x, 0)\n//│ ╙──       \t                          ^\n//│ res: error | (??c & 'a) -> 'a\n//│    = [Function (anonymous)]\n\n\n:e\ndef foo((a, b) : forall 'c. ('c -> 'c, 0)) = ()\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.321: \tdef foo((a, b) : forall 'c. ('c -> 'c, 0)) = ()\n//│ ║         \t        ^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.321: \tdef foo((a, b) : forall 'c. ('c -> 'c, 0)) = ()\n//│ ║         \t                             ^^\n//│ ╟── back into type variable `'c`\n//│ ║  l.321: \tdef foo((a, b) : forall 'c. ('c -> 'c, 0)) = ()\n//│ ╙──       \t                                   ^^\n//│ foo: (forall 'c. ('c -> 'c, 0,)) -> ()\n//│    = [Function: foo5]\n\nfoo((id, 0))\n//│ res: ()\n//│    = []\n\n:e\nfoo((fun x -> foo((fun y -> x, 0)), 0))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.339: \tfoo((fun x -> foo((fun y -> x, 0)), 0))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.321: \tdef foo((a, b) : forall 'c. ('c -> 'c, 0)) = ()\n//│ ╙──       \t                             ^^\n//│ res: error | ()\n//│    = []\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Skolems3.mls",
    "content": ":NoConstrainedTypes\n:DontDistributeForalls\n:NoCycleCheck\n:NoRecursiveTypes\n\n\n\n// *** Here are interesting examples of (relatively minor) limitations of the current extrusion scheme. ***\n\n\n// * Here we essentially extrude skolem `a` in a constraint similar to `'y <: (a, a) -> a`\n// * which is correctly approximated as `'y <: (anything, anything) -> nothing`.\ndef bar y =\n  (fun x -> y (x, x)) : forall 'a. 'a -> 'a\n//│ bar: ((??a, ??a,) -> ??a0) -> (forall 'a. 'a -> 'a)\n//│    = [Function: bar]\n\n// * In fact, what happens above is that local TV 'x is extruded into 'x0 (where 'x <: 'x0)\n// * when passed to the lower-polymorphic-level TV 'y, as in `'y <: ('x0, 'x0) -> 'r0`.\n// * Then we get constraint `a <: 'x` leading to `a <: 'x0` extruded into `anything <: 'x0`\n// * and constraint `'r0 <: a` which is extruded into `'r0 <: nothing`.\n// * Hence the inferred type.\n// * This is all dandy and fine because we at no point try to unify `a` with a lower-level TV.\n\n// * But in the following contrived example, we want to extrude `a` through **the same**\n// * lower-polymorphic-level TV 's, resulting in extruded `a <: anything <: 's <: nothing <: a`\n// * which is inconsistent because of the implied `anything <: nothing` constraint.\n:e\ndef baz x =\n  (x: 's -> 's): forall 'a. 'a -> 'a\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.30: \t  (x: 's -> 's): forall 'a. 'a -> 'a\n//│ ║        \t  ^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.30: \t  (x: 's -> 's): forall 'a. 'a -> 'a\n//│ ║        \t                            ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.30: \t  (x: 's -> 's): forall 'a. 'a -> 'a\n//│ ╙──      \t                                  ^^\n//│ baz: (anything -> ??a) -> (forall 'a. 'a -> 'a)\n//│    = [Function: baz]\n\n// * Thankfully, it turns out this kind of situations just doesn't seem to arise very often.\n// * Usually, we extrude things through **different** lower-level TVs which represent the\n// * approximants of an extruded type variable, as in bar above as well as baz below:\ndef baz x =\n  (x: 's -> 't): forall 'a. 'a -> 'a\n//│ baz: (??a -> ??a0) -> (forall 'a. 'a -> 'a)\n//│    = [Function: baz1]\n\n\n// * Even when involving invariant type constructors, things just seem to work out fine.\n\ndef bar y =\n  (fun x -> y (mut x)) : forall 'a. 'a -> 'a\n//│ bar: (??a -> ??a0) -> (forall 'a. 'a -> 'a)\n//│    = [Function: bar1]\n\ndef lift: 'a -> MutArray['a]\ndef lift x = (mut x)\n//│ lift: 'a -> MutArray['a]\n//│     = <missing implementation>\n//│ 'a -> (mut 'a,)\n//│   <:  lift:\n//│ 'a -> MutArray['a]\n//│     = [Function: lift]\n\ndef bar y =\n  (fun x -> y (lift x)) : forall 'a. 'a -> 'a\n//│ bar: (MutArray[anything] -> ??a) -> (forall 'a. 'a -> 'a)\n//│    = [Function: bar2]\n\ndef bar y =\n  (fun x -> y (x, x)) : forall 'a. MutArray['a] -> 'a\n//│ bar: ((MutArray[in ??a out ??a0], MutArray[in ??a out ??a0],) -> ??a) -> (forall 'a. MutArray['a] -> 'a)\n//│    = [Function: bar3]\n\ndef bar y =\n  (fun x -> y (x, x)) : forall 'a. MutArray['a] -> MutArray['a]\n//│ bar: ((MutArray[in ??a out ??a0], MutArray[in ??a out ??a0],) -> MutArray[in ??a0 out ??a]) -> (forall 'a. MutArray['a] -> MutArray['a])\n//│    = [Function: bar4]\n\ndef bar y =\n  (fun x -> y (mut x)) : forall 'a. MutArray['a] -> 'a\n//│ bar: (MutArray[in ??a out ??a0] -> ??a) -> (forall 'a. MutArray['a] -> 'a)\n//│    = [Function: bar5]\n\ndef bar y =\n  (fun x -> y (lift x)) : forall 'a. MutArray['a] -> 'a\n//│ bar: (MutArray[in 'a out MutArray[in ??a out ??a0] | 'a] -> ??a) -> (forall 'a0. MutArray['a0] -> 'a0)\n//│    = [Function: bar6]\n\ndef bar y =\n  (fun x -> y (lift x)) : forall 'a. MutArray['a] -> MutArray['a]\n//│ bar: (MutArray[in 'a out MutArray[in ??a out ??a0] | 'a] -> MutArray[in ??a0 out ??a]) -> (forall 'a0. MutArray['a0] -> MutArray['a0])\n//│    = [Function: bar7]\n\n// * Again, we can still make it fail using contrived annotations.\n:e\ndef baz x =\n  (x: MutArray['s] -> 't): forall 'a. 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.101: \t  (x: MutArray['s] -> 't): forall 'a. 'a -> 'a\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` does not match type `MutArray['s]`\n//│ ║  l.101: \t  (x: MutArray['s] -> 't): forall 'a. 'a -> 'a\n//│ ║         \t                                      ^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.101: \t  (x: MutArray['s] -> 't): forall 'a. 'a -> 'a\n//│ ║         \t      ^^^^^^^^^^^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.101: \t  (x: MutArray['s] -> 't): forall 'a. 'a -> 'a\n//│ ╙──       \t                                  ^^\n//│ baz: (MutArray['s] -> ??a) -> (forall 'a. 'a -> 'a)\n//│    = [Function: baz2]\n:e\ndef baz x =\n  (x: MutArray['s] -> 't): forall 'a. MutArray['a] -> 'a\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.118: \t  (x: MutArray['s] -> 't): forall 'a. MutArray['a] -> 'a\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.118: \t  (x: MutArray['s] -> 't): forall 'a. MutArray['a] -> 'a\n//│ ╙──       \t                                               ^^\n//│ baz: (MutArray['s] -> ??a) -> (forall 'a. MutArray['a] -> 'a)\n//│   where\n//│     's :> ??a0\n//│        <: ??a\n//│    = [Function: baz3]\n\n\n\n// *** Other various tests and tweaks. ***\n\n\n// * Here, the polymorphic nested let binding introduces more intermediate extrusions,\n// * but things still work out similarly as before.\ndef bar y =\n  (fun x -> let tmp = y (x, x) in x) : forall 'a. 'a -> 'a\n//│ bar: ((??a, ??a,) -> anything) -> (forall 'a. 'a -> 'a)\n//│    = [Function: bar8]\n\ndef bar y =\n  (fun x -> let tmp = (fun x0 -> y (x0, x0)) x in x) : forall 'a. 'a -> 'a\n//│ bar: ((??a, ??a,) -> anything) -> (forall 'a. 'a -> 'a)\n//│    = [Function: bar9]\n\ndef id2: (forall 's. 's -> 's) -> (forall 't. 't -> 't)\nid2 = id\n//│ id2: (forall 's. 's -> 's) -> (forall 't. 't -> 't)\n//│    = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id2:\n//│ (forall 's. 's -> 's) -> (forall 't. 't -> 't)\n//│    = [Function: id]\n\n:e // * Legit (rigid var not a function)\ndef bar y =\n  (fun x -> y (id2 x, x)) : forall 'a. 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.159: \t  (fun x -> y (id2 x, x)) : forall 'a. 'a -> 'a\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.159: \t  (fun x -> y (id2 x, x)) : forall 'a. 'a -> 'a\n//│ ║         \t                                       ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.148: \tdef id2: (forall 's. 's -> 's) -> (forall 't. 't -> 't)\n//│ ║         \t                     ^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.159: \t  (fun x -> y (id2 x, x)) : forall 'a. 'a -> 'a\n//│ ║         \t                   ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.159: \t  (fun x -> y (id2 x, x)) : forall 'a. 'a -> 'a\n//│ ╙──       \t                                   ^^\n//│ bar: ((forall 't. 't -> 't, ??a,) -> ??a0) -> (forall 'a. 'a -> 'a)\n//│    = [Function: bar10]\n\n:e // * Legit (rigid var function can't be used as polymorphic function)\ndef bar y =\n  (fun x -> y (id2 x, x)) : forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.180: \t  (fun x -> y (id2 x, x)) : forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'s` does not match type `'a`\n//│ ║  l.148: \tdef id2: (forall 's. 's -> 's) -> (forall 't. 't -> 't)\n//│ ║         \t                     ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.180: \t  (fun x -> y (id2 x, x)) : forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║         \t                                        ^^\n//│ ╟── Note: quantified type variable 's is defined at:\n//│ ║  l.148: \tdef id2: (forall 's. 's -> 's) -> (forall 't. 't -> 't)\n//│ ╙──       \t                 ^^\n//│ bar: ((forall 't. 't -> 't, ??a -> ??a0,) -> ??a0 -> ??a) -> (forall 'a. ('a -> 'a) -> 'a -> 'a)\n//│    = [Function: bar11]\n\ndef id3: ('s -> 's) -> ('s -> 's)\nid3 = id\n//│ id3: ('s -> 's) -> 's -> 's\n//│    = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id3:\n//│ ('s -> 's) -> 's -> 's\n//│    = [Function: id]\n\ndef bar y =\n  (fun x -> y (id3 x, 0)) : forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ bar: ((??a -> anything, 0,) -> ??a0 -> ??a) -> (forall 'a. ('a -> 'a) -> 'a -> 'a)\n//│    = [Function: bar12]\n\n\n:e // * Legit (similar to previous baz example)\ndef baz x =\n  (x: ('s -> 's) -> 0): forall 'a. ('a -> 'a) -> 0\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.213: \t  (x: ('s -> 's) -> 0): forall 'a. ('a -> 'a) -> 0\n//│ ║         \t  ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.213: \t  (x: ('s -> 's) -> 0): forall 'a. ('a -> 'a) -> 0\n//│ ║         \t                                          ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.213: \t  (x: ('s -> 's) -> 0): forall 'a. ('a -> 'a) -> 0\n//│ ║         \t                                    ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.213: \t  (x: ('s -> 's) -> 0): forall 'a. ('a -> 'a) -> 0\n//│ ╙──       \t             ^^\n//│ baz: ((??a -> anything) -> 0) -> (forall 'a. ('a -> 'a) -> 0)\n//│    = [Function: baz4]\n\n\n:e\ndef boo =\n  let tmp = (id: 's -> 's): forall 'a. 'a -> 'a\n  in 0\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.232: \t  let tmp = (id: 's -> 's): forall 'a. 'a -> 'a\n//│ ║         \t            ^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.232: \t  let tmp = (id: 's -> 's): forall 'a. 'a -> 'a\n//│ ║         \t                                       ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.232: \t  let tmp = (id: 's -> 's): forall 'a. 'a -> 'a\n//│ ╙──       \t                                             ^^\n//│ boo: 0\n//│    = [Function: boo]\n\ndef boo =\n  let tmp = (error: 's -> 't): forall 'a. ('a -> 'a) -> 0\n  in 0\n//│ boo: 0\n//│    = [Function: boo1]\n\ndef boo x =\n  let tmp = (x: 's -> 't): forall 'a. ('a -> 'a) -> 0\n  in 0\n//│ boo: ((??a -> ??a0) -> 0) -> 0\n//│    = [Function: boo2]\n\n:e\ndef boo x =\n  let tmp = (x: ('s -> 's) -> 't): forall 'a. ('a -> 'a) -> 0\n  in 0\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.260: \t  let tmp = (x: ('s -> 's) -> 't): forall 'a. ('a -> 'a) -> 0\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.260: \t  let tmp = (x: ('s -> 's) -> 't): forall 'a. ('a -> 'a) -> 0\n//│ ║         \t                                                     ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.260: \t  let tmp = (x: ('s -> 's) -> 't): forall 'a. ('a -> 'a) -> 0\n//│ ║         \t                                               ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.260: \t  let tmp = (x: ('s -> 's) -> 't): forall 'a. ('a -> 'a) -> 0\n//│ ╙──       \t                       ^^\n//│ boo: ((??a -> anything) -> 0) -> 0\n//│    = [Function: boo3]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/SystemF.mls",
    "content": "// * From https://crypto.stanford.edu/~blynn/lambda/systemf.html\n\n:NoRecursiveTypes\n:NoConstrainedTypes\n:DontDistributeForalls\n\n\ndef succ: int -> int\n//│ succ: int -> int\n//│     = <missing implementation>\n\n\n(fun f -> f succ(f 0)) (fun x -> x)\n//│ res: int\n//│    = <no result>\n//│      succ is not implemented\n\n// Note: does not type check without precise function type intersections\n(fun f -> f succ (f 0)) (fun x -> x)\n//│ res: int\n//│    = <no result>\n//│      succ is not implemented\n\n\n// [Reset]\n\n// Polymorphic identity.\nid x = x\ndef id_ty: forall 'A. 'A -> 'A\n//│ id: 'a -> 'a\n//│   = [Function: id]\n//│ id_ty: 'A -> 'A\n//│      = <missing implementation>\n\nid_ty = id\n//│ 'a -> 'a\n//│   <:  id_ty:\n//│ 'A -> 'A\n//│      = [Function: id]\n\n// Self-application.\nxx = fun x -> x x\ndef xx_ty: (forall 'X. 'X -> 'X) -> (forall 'X. 'X -> 'X)\n//│ xx: ('a -> 'b & 'a) -> 'b\n//│   = [Function: xx]\n//│ xx_ty: (forall 'X. 'X -> 'X) -> (forall 'X0. 'X0 -> 'X0)\n//│      = <missing implementation>\n\nxx_ty = xx\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  xx_ty:\n//│ (forall 'X. 'X -> 'X) -> (forall 'X0. 'X0 -> 'X0)\n//│      = [Function: xx]\n\nxx id\niter2 f x = f(f x)\ndef iter2_ty: forall 'X. ('X -> 'X) -> 'X -> 'X\n//│ res: 'a -> 'a\n//│    = [Function: id]\n//│ iter2: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│      = [Function: iter2]\n//│ iter2_ty: ('X -> 'X) -> 'X -> 'X\n//│         = <missing implementation>\n\niter2_ty = iter2\n//│ ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│   <:  iter2_ty:\n//│ ('X -> 'X) -> 'X -> 'X\n//│         = [Function: iter2]\n\niter4() = iter2 iter2\n//│ iter4: () -> ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c\n//│      = [Function: iter4]\n\ndef iter4_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ iter4_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│         = <missing implementation>\n\n// * Needs distributivity or constrained types\n:e\niter4_ty() = iter2_ty iter2_ty\niter4_ty = iter4\n//│ () -> ('X -> 'X) -> 'X -> 'X\n//│   <:  iter4_ty:\n//│ () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.81: \titer4_ty() = iter2_ty iter2_ty\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'X` leaks out of its scope\n//│ ║  l.75: \tdef iter4_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ║        \t                                       ^^\n//│ ╟── back into type variable `'X`\n//│ ║  l.75: \tdef iter4_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ║        \t                                 ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.81: \titer4_ty() = iter2_ty iter2_ty\n//│ ║        \t             ^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.57: \tdef iter2_ty: forall 'X. ('X -> 'X) -> 'X -> 'X\n//│ ╙──      \t                                ^^\n//│         = [Function: iter4_ty]\n//│ () -> ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c\n//│   <:  iter4_ty:\n//│ () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.82: \titer4_ty = iter4\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'X` leaks out of its scope\n//│ ║  l.75: \tdef iter4_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ║        \t                                       ^^\n//│ ╟── back into type variable `'X`\n//│ ║  l.75: \tdef iter4_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ║        \t                                 ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.56: \titer2 f x = f(f x)\n//│ ║        \t        ^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.71: \titer4() = iter2 iter2\n//│ ║        \t          ^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.82: \titer4_ty = iter4\n//│ ╙──      \t           ^^^^^\n//│         = [Function: iter4]\n\n:DistributeForalls\n\niter4_ty = iter4\n//│ () -> ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c\n//│   <:  iter4_ty:\n//│ () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│         = [Function: iter4]\n\niter4_ty() = iter2_ty iter2_ty\n//│ () -> ('X -> 'X) -> 'X -> 'X\n//│   <:  iter4_ty:\n//│ () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│         = [Function: iter4_ty3]\n\n\n// :e // * Started failing after better distrib, not sure why...\n// 4^4 = 256.\niter256() = iter4() (iter4())\ndef iter256_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\niter256_ty() = iter4_ty() (iter4_ty())\niter256_ty = iter256\n//│ iter256: () -> ('a -> ('a & 'b) & ('c | 'b) -> ('a & 'c)) -> 'a -> 'c\n//│   where\n//│     'a :> 'c\n//│        = [Function: iter256]\n//│ iter256_ty: () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│           = <missing implementation>\n//│ () -> ('X -> 'X) -> 'X -> 'X\n//│   <:  iter256_ty:\n//│ () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│           = [Function: iter256_ty]\n//│ () -> ('a -> ('a & 'b) & ('c | 'b) -> ('a & 'c)) -> 'a -> 'c\n//│   where\n//│     'a :> 'c\n//│   <:  iter256_ty:\n//│ () -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│           = [Function: iter256]\n\n// Church numerals.\nZ s z = z\ndef Z_ty: forall 'X. ('X -> 'X) -> 'X -> 'X\nZ_ty = Z\n//│ Z: anything -> 'a -> 'a\n//│  = [Function: Z]\n//│ Z_ty: ('X -> 'X) -> 'X -> 'X\n//│     = <missing implementation>\n//│ anything -> 'a -> 'a\n//│   <:  Z_ty:\n//│ ('X -> 'X) -> 'X -> 'X\n//│     = [Function: Z]\n\nS n s z = s (n s z)\ndef S_ty: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\nS_ty = S\n//│ S: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│  = [Function: S]\n//│ S_ty: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0)\n//│     = <missing implementation>\n//│ ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│   <:  S_ty:\n//│ (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0)\n//│     = [Function: S]\n\nres1() = iter4() S Z\nres2() = iter256() S Z\n//│ res1: () -> ('a -> ('b & 'c) & 'c -> 'a) -> 'c -> 'b\n//│     = [Function: res1]\n//│ res2: () -> ('a -> ('a & 'b & 'c) & 'c -> ('a & 'c)) -> 'c -> 'b\n//│     = [Function: res2]\n\nres1_ty() = iter4_ty() S_ty Z_ty\nres2_ty() = iter256_ty() S_ty Z_ty\n//│ res1_ty: () -> ('X -> 'X & 'X0 -> 'X0) -> ('X & 'X0) -> ('X | 'X0)\n//│        = [Function: res1_ty]\n//│ res2_ty: () -> ('X -> 'X & 'X0 -> 'X0) -> ('X & 'X0) -> ('X | 'X0)\n//│        = [Function: res2_ty]\n\n\nS (S Z)\n//│ res: ('a -> 'b & 'c -> 'a) -> 'c -> 'b\n//│    = [Function (anonymous)]\n\n\n// [Pair]\n\npair x y f = f x y\ndef pair_ty: forall 'X. forall 'Y. 'X -> 'Y -> (forall 'Z. ('X -> 'Y -> 'Z) -> 'Z)\npair_ty = pair\nfst p = p (fun x -> fun y -> x)\ndef fst_ty: forall 'X. forall 'Y. (forall 'Z. ('X -> 'Y -> 'Z) -> 'Z) -> 'X\nfst_ty = fst\nsnd p = p (fun x -> fun y -> y)\ndef snd_ty: forall 'X. forall 'Y. (forall 'Z. ('X -> 'Y -> 'Z) -> 'Z) -> 'Y\nsnd_ty = snd\n//│ pair: 'a -> 'b -> ('a -> 'b -> 'c) -> 'c\n//│     = [Function: pair]\n//│ pair_ty: 'X -> 'Y -> ('X -> 'Y -> 'Z) -> 'Z\n//│        = <missing implementation>\n//│ 'a -> 'b -> ('a -> 'b -> 'c) -> 'c\n//│   <:  pair_ty:\n//│ 'X -> 'Y -> ('X -> 'Y -> 'Z) -> 'Z\n//│        = [Function: pair]\n//│ fst: ((forall 'a. 'a -> anything -> 'a) -> 'b) -> 'b\n//│    = [Function: fst]\n//│ fst_ty: (forall 'Z. ('X -> anything -> 'Z) -> 'Z) -> 'X\n//│       = <missing implementation>\n//│ ((forall 'a. 'a -> anything -> 'a) -> 'b) -> 'b\n//│   <:  fst_ty:\n//│ (forall 'Z. ('X -> anything -> 'Z) -> 'Z) -> 'X\n//│       = [Function: fst]\n//│ snd: ((forall 'a. anything -> 'a -> 'a) -> 'b) -> 'b\n//│    = [Function: snd]\n//│ snd_ty: (forall 'Z. (anything -> 'Y -> 'Z) -> 'Z) -> 'Y\n//│       = <missing implementation>\n//│ ((forall 'a. anything -> 'a -> 'a) -> 'b) -> 'b\n//│   <:  snd_ty:\n//│ (forall 'Z. (anything -> 'Y -> 'Z) -> 'Z) -> 'Y\n//│       = [Function: snd]\n\np02 = pair Z (S (S Z))\n//│ p02: ((forall 'a. anything -> 'a -> 'a) -> (('b -> 'c & 'd -> 'b) -> 'd -> 'c) -> 'e) -> 'e\n//│    = [Function (anonymous)]\n\np02_ty = pair_ty Z_ty (S_ty (S_ty Z_ty))\n//│ p02_ty: ((forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0) -> 'Z) -> 'Z\n//│       = [Function (anonymous)]\n\nfp = fst p02\nsp = snd p02\n//│ fp: anything -> 'a -> 'a\n//│   = [Function: Z]\n//│ sp: ('a -> 'b & 'c -> 'a) -> 'c -> 'b\n//│   = [Function (anonymous)]\n\n\ndef fp_ty: forall 'a. ('a -> 'a) -> 'a -> 'a\nfp_ty = fst_ty p02_ty\nfp_ty = fp\ndef sp_ty: forall 'a. ('a -> 'a) -> 'a -> 'a\nsp_ty = snd_ty p02_ty\nsp_ty = sp\n//│ fp_ty: ('a -> 'a) -> 'a -> 'a\n//│      = <missing implementation>\n//│ ('X -> 'X) -> 'X -> 'X\n//│   <:  fp_ty:\n//│ ('a -> 'a) -> 'a -> 'a\n//│      = [Function: Z]\n//│ anything -> 'a -> 'a\n//│   <:  fp_ty:\n//│ ('a -> 'a) -> 'a -> 'a\n//│      = [Function: Z]\n//│ sp_ty: ('a -> 'a) -> 'a -> 'a\n//│      = <missing implementation>\n//│ ('X -> 'X) -> 'X -> 'X\n//│   <:  sp_ty:\n//│ ('a -> 'a) -> 'a -> 'a\n//│      = [Function (anonymous)]\n//│ ('a -> 'b & 'c -> 'a) -> 'c -> 'b\n//│   <:  sp_ty:\n//│ ('a -> 'a) -> 'a -> 'a\n//│      = [Function (anonymous)]\n\np01 = pair (()) Z\n//│ p01: (((),) -> (forall 'a. anything -> 'a -> 'a) -> 'b) -> 'b\n//│    = [Function (anonymous)]\n\np = pair (())\n//│ p: 'a -> (((),) -> 'a -> 'b) -> 'b\n//│  = [Function (anonymous)]\n\np01 = p Z\n//│ p01: (((),) -> (forall 'a. anything -> 'a -> 'a) -> 'b) -> 'b\n//│    = [Function (anonymous)]\n\n\n(fun p -> p (fun x -> fun y -> x)) : forall 'X. forall 'Y. (forall 'Z. ('X -> 'Y -> 'Z) -> 'Z) -> 'X\n//│ res: (forall 'Z. ('X -> anything -> 'Z) -> 'Z) -> 'X\n//│    = [Function: res]\n\n\np02 = pair Z (S (S Z))\np02_ty = pair_ty Z_ty (S_ty (S_ty Z_ty))\np02_ty = p02\n//│ p02: ((forall 'a. anything -> 'a -> 'a) -> (('b -> 'c & 'd -> 'b) -> 'd -> 'c) -> 'e) -> 'e\n//│    = [Function (anonymous)]\n//│ p02_ty: ((forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0) -> 'Z) -> 'Z\n//│       = [Function (anonymous)]\n//│ p02_ty: ((forall 'a. anything -> 'a -> 'a) -> (('b -> 'c & 'd -> 'b) -> 'd -> 'c) -> 'e) -> 'e\n//│       = [Function (anonymous)]\n\nfp02 = fst p02\ndef fp02_ty: forall 'X. ('X -> 'X) -> 'X -> 'X\nfp02_ty = fst_ty p02_ty\nfp02_ty = fp02\n//│ fp02: anything -> 'a -> 'a\n//│     = [Function: Z]\n//│ fp02_ty: ('X -> 'X) -> 'X -> 'X\n//│        = <missing implementation>\n//│ anything -> 'a -> 'a\n//│   <:  fp02_ty:\n//│ ('X -> 'X) -> 'X -> 'X\n//│        = [Function: Z]\n//│ anything -> 'a -> 'a\n//│   <:  fp02_ty:\n//│ ('X -> 'X) -> 'X -> 'X\n//│        = [Function: Z]\n\n:ns\nfp02\n//│ res: forall 'a. 'a\n//│   where\n//│     'a :> forall 'b 'c. 'b -> 'c -> 'c\n//│    = [Function: Z]\n\nsp02 = snd p02\ndef sp02_ty: forall 'X. ('X -> 'X) -> 'X -> 'X\nsp02_ty = snd_ty p02_ty\nsp02_ty = sp02\n//│ sp02: ('a -> 'b & 'c -> 'a) -> 'c -> 'b\n//│     = [Function (anonymous)]\n//│ sp02_ty: ('X -> 'X) -> 'X -> 'X\n//│        = <missing implementation>\n//│ ('a -> 'b & 'c -> 'a) -> 'c -> 'b\n//│   <:  sp02_ty:\n//│ ('X -> 'X) -> 'X -> 'X\n//│        = [Function (anonymous)]\n//│ ('a -> 'b & 'c -> 'a) -> 'c -> 'b\n//│   <:  sp02_ty:\n//│ ('X -> 'X) -> 'X -> 'X\n//│        = [Function (anonymous)]\n\n\n// * TODO try:\n\n// [Booleans, Integers, Pairs, Lists]\n// true  = \\X x:X y:X.x\n// false = \\X x:X y:X.y\n// not   = \\b:forall X.X->X->X X t:X f:X.b [X] f t\n// 0    = \\X s:X->X z:X.z\n// succ = \\n:(forall X.(X->X)->X->X) X s:X->X z:X.s(n[X] s z)\n// pair = \\X Y x:X y:Y Z f:X->Y->Z.f x y\n// fst  = \\X Y p:forall Z.(X->Y->Z)->Z.p [X] (\\x:X y:Y.x)\n// snd  = \\X Y p:forall Z.(X->Y->Z)->Z.p [Y] (\\x:X y:Y.y)\n// nil  = \\X.(\\R.\\c:X->R->R.\\n:R.n)\n// cons = \\X h:X t:forall R.(X->R->R)->R->R.(\\R c:X->R->R n:R.c h (t [R] c n))\n\n\n// [Surprise!]\n// -- See Brown and Palsberg, \"Breaking Through the Normalization Barrier:\n// -- A Self-Interpreter for F-omega\": \"Several books, papers, and web pages\"\n// -- claim the following program cannot exist! That is, self-interpreters are\n// -- supposedly impossible in strongly normalizing languages.\n\n// id=\\X x:X.x -- Polymorphic identity.\n// true  = \\X x:X y:X.x  -- Church booleans.\n// false = \\X x:X y:X.y\n// not   = \\b:forall X.X->X->X X t:X f:X.b [X] f t\ntru x y = x\nfls x y = y\nnot b t f = b f t\n//│ tru: 'a -> anything -> 'a\n//│    = [Function: tru]\n//│ fls: anything -> 'a -> 'a\n//│    = [Function: fls]\n//│ not: ('a -> 'b -> 'c) -> 'b -> 'a -> 'c\n//│    = [Function: not]\n\n// E=\\T q:(forall X.X->X)->T.q id  -- Self-interpreter.\nE q = q id\n//│ E: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│  = [Function: E]\n\n// shallow (not (not true))        -- Shallow encoding.\n// λid.id(λb t f.b f t)(id(λb t f.b f t)(λx y.x))\nsh id = (id not) ((id not) tru)\n//│ sh: ((forall 'a 'b 'c. ('a -> 'b -> 'c) -> 'b -> 'a -> 'c) -> ('d -> 'e & (forall 'f. 'f -> anything -> 'f) -> 'd)) -> 'e\n//│   = [Function: sh]\n\n// E[forall X.X->X->X](shallow (not( not true)))\nE sh\n//│ res: 'a -> anything -> 'a\n//│    = [Function (anonymous)]\n\nu = E\npu x y = (u x) x\nsh_pu id x y = id (id u x) x\n//│ u: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│  = [Function: E]\n//│ pu: ((forall 'a. 'a -> 'a) -> 'b -> 'c & 'b) -> anything -> 'c\n//│   = [Function: pu]\n//│ sh_pu: ((forall 'a. ((forall 'b. 'b -> 'b) -> 'a) -> 'a) -> 'c -> 'd & 'd -> 'c -> 'e) -> 'c -> anything -> 'e\n//│      = [Function: sh_pu]\n\n:e\npu sh_pu\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.421: \tpu sh_pu\n//│ ║         \t^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error | anything -> anything -> anything -> nothing\n//│    = [Function (anonymous)]\n\n// * \"Of course, self-application of self-application ((\\x.x x)(\\x.x x)) remains untypable, because it has no normal form.\"\n:e\n(fun x -> x x) (fun x -> x x)\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.431: \t(fun x -> x x) (fun x -> x x)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/SystemF_2.mls",
    "content": ":NoRecursiveTypes\n:NoConstrainedTypes\n:DistributeForalls\n\n\n\nI x = x\nK x y = x\n//│ I: 'a -> 'a\n//│  = [Function: I]\n//│ K: 'a -> anything -> 'a\n//│  = [Function: K]\n\nid x = x\niter2 f x = f(f x)\n//│ id: 'a -> 'a\n//│   = [Function: id]\n//│ iter2: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│      = [Function: iter2]\n\niter2 K\n//│ res: 'a -> anything -> anything -> 'a\n//│    = [Function (anonymous)]\n\niter2 iter2\n//│ res: ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c\n//│    = [Function (anonymous)]\n\nid iter2 iter2\n//│ res: ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c\n//│    = [Function (anonymous)]\n\n// * The following occurs-check failure is legit.\n// * We have `K: 'A -> anything -> 'A` which flows into `'a -> 'b & ('c | 'b) -> 'a`\n// *  which implies `anything -> 'A <: 'b <: 'A`, a nested cycle.\n// * The cycle displayed below is a 1-unrolling of the one above.\n:e\niter2 iter2 K\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> ? -> ? -> 'a\n//│ ╙──\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> anything -> 'b\n//│     'b :> anything -> 'a\n//│    = [Function (anonymous)]\n\niter2 iter2 iter2\n//│ res: ('a -> ('a & 'b) & 'b -> ('a & 'b & 'c)) -> 'a -> 'c\n//│    = [Function (anonymous)]\n\niter2 K iter2 iter2 iter2\n//│ res: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│    = [Function: iter2]\n\n\n\n// (λzy. y(zI)(zK))(λx. xx).\nfoo = (fun z -> fun y -> y (z I) (z K))\n//│ foo: ((forall 'a. 'a -> 'a) -> 'b & (forall 'c. 'c -> anything -> 'c) -> 'd) -> ('b -> 'd -> 'e) -> 'e\n//│    = [Function: foo]\n\nfoo (fun x -> x x)\n//│ res: ((forall 'a. 'a -> 'a) -> (forall 'b. anything -> 'b -> anything -> 'b) -> 'c) -> 'c\n//│    = [Function (anonymous)]\n\nn0_ s z = z\ndef n0: forall 'X. ('X -> 'X) -> 'X -> 'X\nn0 = n0_\n//│ n0_: anything -> 'a -> 'a\n//│    = [Function: n0_]\n//│ n0: ('X -> 'X) -> 'X -> 'X\n//│   = <missing implementation>\n//│ anything -> 'a -> 'a\n//│   <:  n0:\n//│ ('X -> 'X) -> 'X -> 'X\n//│   = [Function: n0_]\n\nsucc_ n s z = s (n s z)\ndef succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\nsucc = succ_\n//│ succ_: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│      = [Function: succ_]\n//│ succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0)\n//│     = <missing implementation>\n//│ ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│   <:  succ:\n//│ (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0)\n//│     = [Function: succ_]\n\nc2 = succ (succ n0)\n//│ c2: ('X -> 'X) -> 'X -> 'X\n//│   = [Function (anonymous)]\n\n:e\nc2 c2 K\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> ? -> 'a\n//│ ╙──\n//│ res: ('a & 'X) -> (anything -> 'a | 'X)\n//│   where\n//│     'X :> anything -> 'X\n//│    = [Function (anonymous)]\n\ndef c2_ n0 = succ_ (succ_ n0)\n//│ c2_: ('a -> 'b -> 'c) -> ('d -> 'e & 'c -> 'd & 'a) -> 'b -> 'e\n//│    = [Function: c2_]\n\nc2_ = succ_ (succ_ n0)\n//│ c2_: ('a -> 'b & 'X -> ('a & 'X)) -> 'X -> 'b\n//│    = [Function (anonymous)]\n\n// * Note: cycle check fails when generalizing curried lambdas\nc2_ c2_\n//│ res: ('a -> ('X & 'X0 & 'b) & 'X0 -> ('a & 'X & 'X0) & 'c -> ('a & 'X & 'X0 & 'b & 'c) & 'X -> ('X & 'c)) -> ('X & 'X0) -> 'b\n//│    = [Function (anonymous)]\n\n// * Idem\nc2_ c2_!\n//│ res: ('a -> ('a & 'b & 'X) & 'X -> ('a & 'X)) -> 'X -> 'b\n//│    = [Function (anonymous)]\n\n// * Note: cycle check fails when generalizing curried lambdas\n:e // occurs-check\nc2_ c2_ K\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> ? -> ('a | 'b | 'c | 'd)\n//│     'c :> ? -> ('d | 'b) | ? -> ('b | 'c)\n//│     'd :> ? -> ('c | 'b)\n//│     'b :> ? -> ('a | 'b)\n//│ ╙──\n//│ res: ('a & 'b & 'c) -> anything -> ('d | 'e)\n//│   where\n//│     'a :> anything -> ('a | 'd | 'b | 'c | 'e)\n//│     'b :> anything -> ('d | 'b | 'e)\n//│     'e :> anything -> ('c | 'd)\n//│     'c :> anything -> ('b | 'd | 'e)\n//│     'd :> anything -> ('a | 'd)\n//│    = [Function (anonymous)]\n\nc2__ = succ_ (succ_ n0_)\n//│ c2__: ('a -> 'b & 'c -> 'a) -> 'c -> 'b\n//│     = [Function (anonymous)]\n\nc2__ c2__\n//│ res: ('a -> ('b & 'c) & 'b -> 'a) -> 'b -> 'c\n//│    = [Function (anonymous)]\n\n:e\nc2__ c2__ K\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> ? -> ? -> 'a\n//│ ╙──\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> anything -> 'b\n//│     'b :> anything -> 'a\n//│    = [Function (anonymous)]\n\n\n// --------------\n:RecursiveTypes\n\niter2 iter2 K\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> anything -> 'b\n//│     'b :> anything -> 'a\n//│    = [Function (anonymous)]\n\nres id\n//│ res: anything -> 'a\n//│   where\n//│     'a :> forall 'b. anything -> 'b -> ('a | 'b)\n//│    = [Function (anonymous)]\n\nr1 = res id id id id id\n//│ r1: 'a -> ('b | 'a)\n//│   where\n//│     'b :> forall 'c. 'c -> (anything -> 'b | 'c)\n//│   = [Function: id]\n\nr1 iter2 iter2 K\n//│ res: ('a & 'b & 'c) -> (anything -> (anything -> 'b | 'd) | 'c | 'e)\n//│   where\n//│     'e :> forall 'f. anything -> 'f -> ('e | 'f)\n//│     'a :> anything -> 'd\n//│     'd :> anything -> 'a\n//│    = [Function (anonymous)]\n\nr = r1 iter2 iter2\n//│ r: ('a -> 'b & 'b -> 'c & 'd -> 'e & 'e -> ('d & 'f)) -> (('a & 'd) -> ('c | 'f) | 'g)\n//│   where\n//│     'g :> forall 'h. 'h -> (anything -> 'g | 'h)\n//│  = [Function (anonymous)]\n\nr iter2\n//│ res: ('a -> ('a & 'b) & 'b -> ('a & 'b & 'c) & 'd -> 'e & 'e -> ('d & 'f) & 'g) -> (('a & 'd) -> ('c | 'f) | 'g | 'h)\n//│   where\n//│     'h :> forall 'i. anything -> 'i -> ('h | 'i)\n//│    = [Function (anonymous)]\n\n:NoRecursiveTypes\n// --------------\n\n\n\n// ==============\n\n:ConstrainedTypes\n:DontDistributeForalls\n\n// ==============\n\n\n\nid x = x\niter2 f x = f(f x)\n//│ id: 'a -> 'a\n//│   = [Function: id1]\n//│ iter2: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     'a <: 'b -> 'c & 'c -> 'd)\n//│      = [Function: iter21]\n\niter2 iter2\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f\n//│       where\n//│         'c <: 'd -> 'e & 'e -> 'f) <: 'a -> 'g & 'g -> 'b\n//│    = [Function (anonymous)]\n\nid iter2 iter2\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f\n//│       where\n//│         'c <: 'd -> 'e & 'e -> 'f) <: 'a -> 'g & 'g -> 'b\n//│    = [Function (anonymous)]\n\n\niter2 iter2 K\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c 'd 'e. 'c -> 'e\n//│       where\n//│         forall 'f. 'f -> anything -> 'f <: 'c -> 'd & 'd -> 'e <: 'a -> 'g & 'g -> 'b\n//│    = [Function (anonymous)]\n\n\n\n// (λzy. y(zI)(zK))(λx. xx).\nfoo = (fun z -> fun y -> y (z I) (z K))\n//│ foo: 'a -> (forall 'b 'c 'd. ('b -> 'c -> 'd) -> 'd\n//│   where\n//│     'a <: (forall 'e. 'e -> 'e) -> 'b & (forall 'f. 'f -> anything -> 'f) -> 'c)\n//│    = [Function: foo1]\n\nfoo (fun x -> x x)\n//│ res: ('a -> 'b -> 'c) -> 'c\n//│   where\n//│     forall 'd 'e. ('d -> 'e & 'd) -> 'e <: (forall 'f. 'f -> 'f) -> 'a & (forall 'g. 'g -> anything -> 'g) -> 'b\n//│    = [Function (anonymous)]\n\nn0_ s z = z\ndef n0: forall 'X. ('X -> 'X) -> 'X -> 'X\nn0 = n0_\n//│ n0_: anything -> (forall 'a. 'a -> 'a)\n//│    = [Function: n0_1]\n//│ n0: ('X -> 'X) -> 'X -> 'X\n//│   = <missing implementation>\n//│ anything -> (forall 'a. 'a -> 'a)\n//│   <:  n0:\n//│ ('X -> 'X) -> 'X -> 'X\n//│   = [Function: n0_1]\n\n// :d\nsucc_ n s z = s (n s z)\n//│ succ_: 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│      = [Function: succ_1]\n\ndef succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0)\n//│     = <missing implementation>\n:e // * Needs distrib\nsucc = succ_\n//│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│   <:  succ:\n//│ (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X0. ('X0 -> 'X0) -> 'X0 -> 'X0)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.294: \tsucc = succ_\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type variable `'X` leaks out of its scope\n//│ ║  l.290: \tdef succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ║         \t                                                                    ^^\n//│ ╟── back into type variable `'X`\n//│ ║  l.290: \tdef succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ║         \t                                                              ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.283: \tsucc_ n s z = s (n s z)\n//│ ║         \t        ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.294: \tsucc = succ_\n//│ ║         \t       ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.290: \tdef succ: (forall 'X. ('X -> 'X) -> 'X -> 'X) -> (forall 'X. ('X -> 'X) -> 'X -> 'X)\n//│ ╙──       \t                             ^^\n//│     = [Function: succ_1]\n\nc2 = succ (succ n0)\n//│ c2: ('X -> 'X) -> 'X -> 'X\n//│   = [Function (anonymous)]\n\n:e\nc2 c2 K\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> ? -> 'a\n//│ ╙──\n//│ res: ('a & 'X) -> (anything -> 'a | 'X)\n//│   where\n//│     'X :> anything -> 'X\n//│    = [Function (anonymous)]\n\nc2_ = succ_ (succ_ n0)\n//│ c2_: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     forall 'e. 'e -> (forall 'f 'g 'h. 'f -> 'h\n//│       where\n//│         forall 'X. ('X -> 'X) -> 'X -> 'X <: 'e -> 'f -> 'g\n//│         'e <: 'g -> 'h) <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd)\n//│    = [Function (anonymous)]\n\nc2_ c2_\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f\n//│       where\n//│         forall 'X. ('X -> 'X) -> 'X -> 'X <: 'c -> 'd -> 'e\n//│         'c <: 'e -> 'f) <: (forall 'g. 'g -> (forall 'h 'i 'j. 'h -> 'j\n//│       where\n//│         forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n\n//│           where\n//│             forall 'X. ('X -> 'X) -> 'X -> 'X <: 'k -> 'l -> 'm\n//│             'k <: 'm -> 'n) <: 'g -> 'h -> 'i\n//│         'g <: 'i -> 'j)) -> 'a -> 'o\n//│     forall 'g. 'g -> (forall 'h 'i 'j. 'h -> 'j\n//│       where\n//│         forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n\n//│           where\n//│             forall 'X. ('X -> 'X) -> 'X -> 'X <: 'k -> 'l -> 'm\n//│             'k <: 'm -> 'n) <: 'g -> 'h -> 'i\n//│         'g <: 'i -> 'j) <: 'o -> 'b\n//│    = [Function (anonymous)]\n\n:e\nc2_ c2_ K\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e. ('b & 'e) -> (? -> 'e | 'd)\n//│       where\n//│         forall 'f. 'f -> (forall 'g 'h 'i. 'g -> 'i\n//│           where\n//│             forall 'X. ('X -> 'X) -> 'X -> 'X <: 'f -> 'g -> 'h\n//│             'f <: 'h -> 'i) <: 'a -> 'b -> 'c\n//│         'a <: 'c -> 'd\n//│ ╙──\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f\n//│       where\n//│         forall 'X. ('X -> 'X) -> 'X -> 'X <: 'c -> 'd -> 'e\n//│         'c <: 'e -> 'f) <: (forall 'g 'h 'i. 'g -> 'i\n//│       where\n//│         forall 'j. 'j -> (forall 'k 'l 'm. 'k -> 'm\n//│           where\n//│             forall 'X. ('X -> 'X) -> 'X -> 'X <: 'j -> 'k -> 'l\n//│             'j <: 'l -> 'm) <: 'n -> 'g -> 'h\n//│         'n <: 'h -> 'i) -> 'a -> 'o\n//│     forall 'g 'h 'i. 'g -> 'i\n//│       where\n//│         forall 'j. 'j -> (forall 'k 'l 'm. 'k -> 'm\n//│           where\n//│             forall 'X. ('X -> 'X) -> 'X -> 'X <: 'j -> 'k -> 'l\n//│             'j <: 'l -> 'm) <: 'n -> 'g -> 'h\n//│         'n <: 'h -> 'i <: 'o -> 'b\n//│ where\n//│   'n :> forall 'p 'q 'r 's. ('p & 's) -> (anything -> 's | 'r)\n//│     where\n//│       forall 't. 't -> (forall 'u 'v 'w. 'u -> 'w\n//│         where\n//│           forall 'X. ('X -> 'X) -> 'X -> 'X <: 't -> 'u -> 'v\n//│           't <: 'v -> 'w) <: 'n -> 'p -> 'q\n//│       'n <: 'q -> 'r\n//│    = [Function (anonymous)]\n\nc2__ = succ_ (succ_ n0_)\n//│ c2__: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     forall 'e. 'e -> (forall 'f 'g 'h. 'f -> 'h\n//│       where\n//│         anything -> (forall 'i. 'i -> 'i) <: 'e -> 'f -> 'g\n//│         'e <: 'g -> 'h) <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd)\n//│     = [Function (anonymous)]\n\nc2__ c2__\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f\n//│       where\n//│         anything -> (forall 'g. 'g -> 'g) <: 'c -> 'd -> 'e\n//│         'c <: 'e -> 'f) <: (forall 'h. 'h -> (forall 'i 'j 'k. 'i -> 'k\n//│       where\n//│         forall 'l. 'l -> (forall 'm 'n 'o. 'm -> 'o\n//│           where\n//│             anything -> (forall 'g. 'g -> 'g) <: 'l -> 'm -> 'n\n//│             'l <: 'n -> 'o) <: 'h -> 'i -> 'j\n//│         'h <: 'j -> 'k)) -> 'a -> 'p\n//│     forall 'h. 'h -> (forall 'i 'j 'k. 'i -> 'k\n//│       where\n//│         forall 'l. 'l -> (forall 'm 'n 'o. 'm -> 'o\n//│           where\n//│             anything -> (forall 'g. 'g -> 'g) <: 'l -> 'm -> 'n\n//│             'l <: 'n -> 'o) <: 'h -> 'i -> 'j\n//│         'h <: 'j -> 'k) <: 'p -> 'b\n//│    = [Function (anonymous)]\n\nc2__ c2__ K\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c. 'c -> (forall 'd 'e 'f. 'd -> 'f\n//│       where\n//│         anything -> (forall 'g. 'g -> 'g) <: 'c -> 'd -> 'e\n//│         'c <: 'e -> 'f) <: (forall 'h 'i 'j. 'h -> 'j\n//│       where\n//│         forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n\n//│           where\n//│             anything -> (forall 'g. 'g -> 'g) <: 'k -> 'l -> 'm\n//│             'k <: 'm -> 'n) <: (forall 'o. 'o -> anything -> 'o) -> 'h -> 'i\n//│         forall 'o. 'o -> anything -> 'o <: 'i -> 'j) -> 'a -> 'p\n//│     forall 'h 'i 'j. 'h -> 'j\n//│       where\n//│         forall 'k. 'k -> (forall 'l 'm 'n. 'l -> 'n\n//│           where\n//│             anything -> (forall 'g. 'g -> 'g) <: 'k -> 'l -> 'm\n//│             'k <: 'm -> 'n) <: (forall 'o. 'o -> anything -> 'o) -> 'h -> 'i\n//│         forall 'o. 'o -> anything -> 'o <: 'i -> 'j <: 'p -> 'b\n//│    = [Function (anonymous)]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/ToChurchSimplif_CT.mls",
    "content": "// * This test contains simplifications of the to_church function,\n// * used to minimize and reproduce problems with to_church and related definitions.\n\n:NoRecursiveTypes\n:ConstrainedTypes\n:DontDistributeForalls\n\n\n\ntype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ Defined type alias ChurchInt\n\ndef zero: ChurchInt\ndef succ: ChurchInt -> ChurchInt\n//│ zero: ChurchInt\n//│     = <missing implementation>\n//│ succ: ChurchInt -> ChurchInt\n//│     = <missing implementation>\n\ndef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ to_church: int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = <missing implementation>\n\n\n\ndef z f x = x\n//│ z: anything -> (forall 'a. 'a -> 'a)\n//│  = [Function: z]\n\n// * Simpler functions that can be used instead of `s` to debug\n// def s n f x = f (n f x) // * original succ\n// def s n f = f (n f)\ndef s n f x = (n f x)\n// def s n f = n f\n//│ s: 'a -> (forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│   where\n//│     'a <: 'b -> 'c -> 'd))\n//│  = [Function: s]\n\n:ns\ns\n//│ res: forall 'a. 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'd))\n//│ where\n//│   'd <: 'c -> 'e\n//│    = [Function: s]\n\n:e // * Since \"sound extrusion\"\nsucc = s\n//│ 'a -> (forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│   where\n//│     'a <: 'b -> 'c -> 'd))\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.50: \tsucc = s\n//│ ║        \t^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.50: \tsucc = s\n//│ ╙──      \t       ^\n//│     = [Function: s]\n\n:e // * Since \"sound extrusion\"\nsucc n f = n f\n//│ 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     'a <: 'b -> 'c)\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.75: \tsucc n f = n f\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.75: \tsucc n f = n f\n//│ ╙──      \t       ^^^^^^^\n//│     = [Function: succ2]\n\nsucc n = n\n//│ 'a -> 'a\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│     = [Function: succ3]\n\ndef succ_min : (forall 'N. ('N -> 'N)) -> (forall 'M. ('M -> 'M))\n//│ succ_min: (forall 'N. 'N -> 'N) -> (forall 'M. 'M -> 'M)\n//│         = <missing implementation>\n\n:e // * Since \"sound extrusion\"\nsucc_min n f = n f\n//│ 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     'a <: 'b -> 'c)\n//│   <:  succ_min:\n//│ (forall 'N. 'N -> 'N) -> (forall 'M. 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.107: \tsucc_min n f = n f\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.102: \tdef succ_min : (forall 'N. ('N -> 'N)) -> (forall 'M. ('M -> 'M))\n//│ ║         \t                                                       ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.102: \tdef succ_min : (forall 'N. ('N -> 'N)) -> (forall 'M. ('M -> 'M))\n//│ ║         \t                                                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.107: \tsucc_min n f = n f\n//│ ║         \t           ^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.107: \tsucc_min n f = n f\n//│ ╙──       \t               ^^^\n//│         = [Function: succ_min]\n\n\n\n:e\nrec def to_ch n =\n  if n == 0 then zero\n  else s (to_ch n)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│ ╙──\n//│ to_ch: number -> 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│      = <no result>\n//│        zero is not implemented\n\n:e\nto_church = to_ch\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│ ╙──\n//│ number -> 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch. ?to_ch <: int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)` exceeded recursion depth limit (250)\n//│ ║  l.152: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\n:e\nrec def to_ch n =\n  if true then zero\n  else s (to_ch n)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│ ╙──\n//│ to_ch: anything -> 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│      = <no result>\n//│        zero is not implemented\n\n:e\nto_church = to_ch\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│ ╙──\n//│ anything -> 'a\n//│   where\n//│     'a :> forall 'b. 'b -> (forall 'c 'd. 'c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd) | ChurchInt\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch. ?to_ch <: int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)` exceeded recursion depth limit (250)\n//│ ║  l.193: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  if true then zero\n  else s (to_church n)\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c) | ChurchInt)\n//│      = <no result>\n//│        zero is not implemented\n\n:e\nto_church = to_ch\n//│ int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c) | ChurchInt)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.225: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.217: \t  else s (to_church n)\n//│ ║         \t       ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.225: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\ndef to_ch n =\n  if true then z\n  else s (to_church n)\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd. ('b & 'd) -> ('c | 'd)\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│      = <no result>\n//│        to_church, to_ch and zero are not implemented\n\n:e // * Since \"sound extrusion\"\nto_church = to_ch\n//│ int -> (forall 'a. 'a -> (forall 'a 'b 'c 'd. ('b & 'd) -> ('c | 'd)\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.264: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.256: \t  else s (to_church n)\n//│ ║         \t       ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.264: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch and zero are not implemented\n\n\ndef to_ch n =\n  if true then zero\n  else s (to_church n)\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c) | ChurchInt)\n//│      = <no result>\n//│        zero is not implemented\n\n:e // * Since \"sound extrusion\"\nto_church = to_ch\n//│ int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c) | ChurchInt)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.303: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.295: \t  else s (to_church n)\n//│ ║         \t       ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.303: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\ndef to_ch n =\n  s (to_church n)\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│      = <no result>\n//│        to_church, to_ch and zero are not implemented\n\n:e // * Since \"sound extrusion\"\nto_church = to_ch\n//│ int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.341: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.333: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.341: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  s (to_church n)\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e\nto_church = to_ch\n//│ int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.379: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.371: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.379: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\ndef to_ch (n:int) =\n  s (to_church n)\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e // * Since \"sound extrusion\"\nto_church = to_ch\n//│ int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.417: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.409: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.417: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n// * Marking it `rec` (on a minimized version) makes it fail\n// *  This is because of `destroyConstrainedTypes` which is invoked on rec defs:\n// *  (disabling the destruction fixes this problem)\n\nrec def to_ch n =\n  s (to_church n)\n//│ to_ch: int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e\nto_church = to_ch\n//│ int -> (forall 'a. 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c))\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.458: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.450: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.458: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\ndef to_ch =\n  s (to_church 0)\n//│ to_ch: 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c)\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e\nto_church = to_ch\n//│ 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.496: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t               ^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ╙──      \t                                  ^^^^^^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\n// * But distributivity allows getting around the recursion limitation by recovering _some_ of the lost expressiveness\n:DistributeForalls\n\n\nrec def to_ch n =\n  s (to_church n)\n//│ to_ch: int -> 'a -> ('b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c)\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\nto_church = to_ch\n//│ int -> 'a -> ('b -> 'c\n//│   where\n//│     forall 'M. ('M -> 'M) -> 'M -> 'M <: 'a -> 'b -> 'c)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  if n == 0 then zero\n  else succ (to_ch (n - 1))\n//│ to_ch: int -> ChurchInt\n//│      = <no result>\n//│        zero is not implemented\n\nto_church = to_ch\n//│ int -> ChurchInt\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\n:e\nrec def to_ch n =\n  if n == 0 then z\n  else s (to_ch (n - 1))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e. (? & 'b) -> (('e & 'c) -> ('e | 'd)\n//│       where\n//│         'a <: 'b -> 'c -> 'd)\n//│ ╙──\n//│ to_ch: int -> 'a -> ('b -> ('c | 'b)\n//│   where\n//│     'd <: 'a -> 'b -> 'c)\n//│ where\n//│   'd :> forall 'e 'f 'g 'h. 'e -> (('h & 'f) -> ('h | 'g)\n//│     where\n//│       'd <: 'e -> 'f -> 'g)\n//│      = [Function: to_ch7]\n\n:e // * Since the removal of \"recursive definition hacks\"\nto_church = to_ch\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e. (? & 'b) -> (('e & 'c) -> ('e | 'd)\n//│       where\n//│         'a <: 'b -> 'c -> 'd)\n//│ ╙──\n//│ int -> 'a -> ('b -> ('c | 'b)\n//│   where\n//│     'd <: 'a -> 'b -> 'c)\n//│ where\n//│   'd :> forall 'e 'f 'g 'h. 'e -> (('h & 'f) -> ('h | 'g)\n//│     where\n//│       'd <: 'e -> 'f -> 'g)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch. ?to_ch <: int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)` exceeded recursion depth limit (250)\n//│ ║  l.572: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│          = [Function: to_ch7]\n\n\n:e // occurs-check\nrec def to_ch_weird n =\n  s (to_ch_weird n)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd. 'b -> ('c -> 'd\n//│       where\n//│         'a <: 'b -> 'c -> 'd)\n//│ ╙──\n//│ to_ch_weird: anything -> 'a -> ('b -> 'c\n//│   where\n//│     'd <: 'a -> 'b -> 'c)\n//│ where\n//│   'd :> forall 'e 'f 'g. 'e -> ('f -> 'g\n//│     where\n//│       'd <: 'e -> 'f -> 'g)\n//│            = [Function: to_ch_weird]\n\n:e // * Since the removal of \"recursive definition hacks\"\nto_church = to_ch\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'b 'c 'd 'e. (? & 'b) -> (('e & 'c) -> ('e | 'd)\n//│       where\n//│         'a <: 'b -> 'c -> 'd)\n//│ ╙──\n//│ int -> 'a -> ('b -> ('c | 'b)\n//│   where\n//│     'd <: 'a -> 'b -> 'c)\n//│ where\n//│   'd :> forall 'e 'f 'g 'h. 'e -> (('h & 'f) -> ('h | 'g)\n//│     where\n//│       'd <: 'e -> 'f -> 'g)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?to_ch. ?to_ch <: int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)` exceeded recursion depth limit (250)\n//│ ║  l.614: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│          = [Function: to_ch7]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/ToChurchSimplif_ST.mls",
    "content": "// * This test contains simplifications of the to_church function,\n// * used to minimize and reproduce problems with to_church and related definitions.\n\n:NoRecursiveTypes\n:NoConstrainedTypes\n:DontDistributeForalls\n\n\n\ntype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ Defined type alias ChurchInt\n\ndef zero: ChurchInt\ndef succ: ChurchInt -> ChurchInt\n//│ zero: ChurchInt\n//│     = <missing implementation>\n//│ succ: ChurchInt -> ChurchInt\n//│     = <missing implementation>\n\ndef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ to_church: int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = <missing implementation>\n\n\n\ndef z f x = x\n//│ z: anything -> (forall 'a. 'a -> 'a)\n//│  = [Function: z]\n\n// * Simpler functions that can be used instead of `s` to debug\n// def s n f x = f (n f x) // * original succ\n// def s n f = f (n f)\ndef s n f x = (n f x)\n// def s n f = n f\n//│ s: ('a -> 'b -> 'c) -> 'a -> 'b -> 'c\n//│  = [Function: s]\n\n:ns\ns\n//│ res: forall 'a 'b 'c 'd 'e. 'a -> (forall 'f. 'f -> (forall 'g 'h. 'g -> 'h))\n//│   where\n//│     'h :> 'e\n//│     'g <: 'd\n//│     'f <: 'b\n//│     'a <: 'b -> 'c\n//│     'c <: 'd -> 'e\n//│    = [Function: s]\n\n:e // * Works with CT\nsucc = s\n//│ ('a -> 'b -> 'c) -> 'a -> 'b -> 'c\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.50: \tsucc = s\n//│ ║        \t^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.50: \tsucc = s\n//│ ╙──      \t       ^\n//│     = [Function: s]\n\n:e // * Works with CT\nsucc n f = n f\n//│ ('a -> 'b) -> 'a -> 'b\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.73: \tsucc n f = n f\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type variable `'N` leaks out of its scope\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'N`\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.73: \tsucc n f = n f\n//│ ╙──      \t       ^^^^^^^\n//│     = [Function: succ2]\n\nsucc n = n\n//│ 'a -> 'a\n//│   <:  succ:\n//│ ChurchInt -> ChurchInt\n//│     = [Function: succ3]\n\ndef succ_min : (forall 'N. ('N -> 'N)) -> (forall 'M. ('M -> 'M))\n//│ succ_min: (forall 'N. 'N -> 'N) -> (forall 'M. 'M -> 'M)\n//│         = <missing implementation>\n\n:e // * Works with CT\nsucc_min n f = n f\n//│ ('a -> 'b) -> 'a -> 'b\n//│   <:  succ_min:\n//│ (forall 'N. 'N -> 'N) -> (forall 'M. 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.103: \tsucc_min n f = n f\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.98: \tdef succ_min : (forall 'N. ('N -> 'N)) -> (forall 'M. ('M -> 'M))\n//│ ║        \t                                                       ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.98: \tdef succ_min : (forall 'N. ('N -> 'N)) -> (forall 'M. ('M -> 'M))\n//│ ║        \t                                                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.103: \tsucc_min n f = n f\n//│ ╙──       \t               ^^^\n//│         = [Function: succ_min]\n\n\n\nrec def to_ch n =\n  if n == 0 then zero\n  else s (to_ch n)\n//│ to_ch: number -> (('N -> 'N) -> 'N -> 'N | ChurchInt)\n//│      = <no result>\n//│        zero is not implemented\n\n:e\nto_church = to_ch\n//│ number -> (('N -> 'N) -> 'N -> 'N | ChurchInt)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.132: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.126: \t  else s (to_ch n)\n//│ ║         \t       ^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.132: \tto_church = to_ch\n//│ ║         \t            ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──      \t                                   ^^\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  if true then zero\n  else s (to_ch n)\n//│ to_ch: anything -> (('N -> 'N) -> 'N -> 'N | ChurchInt)\n//│      = <no result>\n//│        zero is not implemented\n\n:e\nto_church = to_ch\n//│ anything -> (('N -> 'N) -> 'N -> 'N | ChurchInt)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.170: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.164: \t  else s (to_ch n)\n//│ ║         \t       ^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.170: \tto_church = to_ch\n//│ ║         \t            ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.10: \ttype ChurchInt = forall 'N. ('N -> 'N) -> ('N -> 'N)\n//│ ╙──      \t                                   ^^\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  if true then zero\n  else s (to_church n)\n//│ to_ch: int -> (('M -> 'M) -> 'M -> 'M | ChurchInt)\n//│      = <no result>\n//│        zero is not implemented\n\n:e // * Works with :GeneralizeArguments\nto_church = to_ch\n//│ int -> (('M -> 'M) -> 'M -> 'M | ChurchInt)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.208: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.202: \t  else s (to_church n)\n//│ ║         \t       ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.208: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\ndef to_ch n =\n  if true then z\n  else s (to_church n)\n//│ to_ch: int -> ('M -> 'M) -> 'M -> 'M\n//│      = <no result>\n//│        to_church, to_ch and zero are not implemented\n\n:e // * Works with CT, :GeneralizeArguments\nto_church = to_ch\n//│ int -> ('M -> 'M) -> 'M -> 'M\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.243: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.237: \t  else s (to_church n)\n//│ ║         \t       ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.243: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch and zero are not implemented\n\n\ndef to_ch n =\n  if true then zero\n  else s (to_church n)\n//│ to_ch: int -> (('M -> 'M) -> 'M -> 'M | ChurchInt)\n//│      = <no result>\n//│        zero is not implemented\n\n:e // * Works with CT, :GeneralizeArguments\nto_church = to_ch\n//│ int -> (('M -> 'M) -> 'M -> 'M | ChurchInt)\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.278: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.272: \t  else s (to_church n)\n//│ ║         \t       ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.278: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\ndef to_ch n =\n  s (to_church n)\n//│ to_ch: int -> ('M -> 'M) -> 'M -> 'M\n//│      = <no result>\n//│        to_church, to_ch and zero are not implemented\n\n:e // * Works with CT\nto_church = to_ch\n//│ int -> ('M -> 'M) -> 'M -> 'M\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.312: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.306: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.312: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  s (to_church n)\n//│ to_ch: int -> ('M -> 'M) -> 'M -> 'M\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e\nto_church = to_ch\n//│ int -> ('M -> 'M) -> 'M -> 'M\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.346: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.340: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.346: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\ndef to_ch (n:int) =\n  s (to_church n)\n//│ to_ch: int -> ('M -> 'M) -> 'M -> 'M\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e // * Works with CT\nto_church = to_ch\n//│ int -> ('M -> 'M) -> 'M -> 'M\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.380: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.374: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.380: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n// * Marking it `rec` (on a minimized version) makes it fail\n// *  This is because of `destroyConstrainedTypes` which is invoked on rec defs:\n// *  (disabling the destruction fixes this problem)\n\nrec def to_ch n =\n  s (to_church n)\n//│ to_ch: int -> ('M -> 'M) -> 'M -> 'M\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e\nto_church = to_ch\n//│ int -> ('M -> 'M) -> 'M -> 'M\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.417: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'M` leaks out of its scope\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                         ^^\n//│ ╟── back into type variable `'M`\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.411: \t  s (to_church n)\n//│ ║         \t  ^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.417: \tto_church = to_ch\n//│ ╙──       \t            ^^^^^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\ndef to_ch =\n  s (to_church 0)\n//│ to_ch: ('M -> 'M) -> 'M -> 'M\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n:e\nto_church = to_ch\n//│ ('M -> 'M) -> 'M -> 'M\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.451: \tto_church = to_ch\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t               ^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.20: \tdef to_church: int -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n//│ ║        \t                                  ^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.33: \tdef s n f x = (n f x)\n//│ ╙──      \t                 ^\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\n// * But distributivity allows getting around the recursion limitation by recovering _some_ of the lost expressiveness\n:DistributeForalls\n\n\nrec def to_ch n =\n  s (to_church n)\n//│ to_ch: int -> ('M -> 'M) -> 'M -> 'M\n//│      = <no result>\n//│        to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\nto_church = to_ch\n//│ int -> ('M -> 'M) -> 'M -> 'M\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = <no result>\n//│            to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch, to_church, to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  if n == 0 then zero\n  else succ (to_ch (n - 1))\n//│ to_ch: int -> ChurchInt\n//│      = <no result>\n//│        zero is not implemented\n\nto_church = to_ch\n//│ int -> ChurchInt\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = <no result>\n//│            to_ch and zero are not implemented\n\n\nrec def to_ch n =\n  if n == 0 then z\n  else s (to_ch (n - 1))\n//│ to_ch: int -> anything -> 'a -> 'a\n//│      = [Function: to_ch7]\n\nto_church = to_ch\n//│ int -> anything -> 'a -> 'a\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = [Function: to_ch7]\n\n\nrec def to_ch_weird n =\n  s (to_ch_weird n)\n//│ to_ch_weird: anything -> anything -> anything -> nothing\n//│            = [Function: to_ch_weird]\n\nto_church = to_ch\n//│ int -> anything -> 'a -> 'a\n//│   <:  to_church:\n//│ int -> (forall 'M. ('M -> 'M) -> 'M -> 'M)\n//│          = [Function: to_ch7]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/Vec.mls",
    "content": "\n// :GeneralizeArguments // Type of cons is much simpler without this...\n\n:AllowTypeErrors // TODO\n\n\nclass Z\nclass S[P]\n  method Inv: P -> P\n  method Inv = id\n//│ Defined class Z\n//│ Defined class S[=P]\n//│ Declared S.Inv: S['P] -> 'P -> 'P\n//│ Defined S.Inv: S['P] -> 'a -> 'a\n\n:IrregularTypes\n\nclass Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] }\nclass Nil: { size: Z }\ntype Vec[A, N] = forall 'r. (forall 'p. (Nil & { size: N } | Cons[A, S['p]] & Cons[A, N]) -> 'r) -> 'r\n//│ Defined class Cons[+A, =N]\n//│ Defined class Nil\n//│ Defined type alias Vec[+A, =N]\n\ntype AnyVec[A] = forall 'r. (forall 'p. Nil | Cons[A, S['p]] -> 'r) -> 'r\n//│ Defined type alias AnyVec[+A]\n\ndef Nil = Nil { size = Z{} }\ndef Cons head tail = Cons { head; tail; size = S{} }\n//│ Nil: Nil\n//│ Cons: ('head & 'A) -> (Vec['A, 'N] & 'tail) -> (Cons['A, 'N] with {head: 'head, size: forall 'P. S['P], tail: 'tail})\n\n\ndef nil k = k Nil\ndef cons h t k = k (Cons h t)\n//│ nil: (Nil -> 'a) -> 'a\n//│ cons: ('head & 'A) -> (Vec['A, 'N] & 'tail) -> ((Cons['A, 'N] with {head: 'head, size: forall 'P. S['P], tail: 'tail}) -> 'a) -> 'a\n\nnil_ty = nil : Vec[int, Z]\n//│ nil_ty: Vec[int, Z]\n\ndef cons_ty : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ cons_ty: 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n\n// * Note: test cases like this are quite slow... this one seems to take about 100ms!!\ncons_ty = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│   where\n//│     'n := S['n]\n//│   <:  cons_ty:\n//│ 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.46: \tcons_ty = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type `'n` is not an instance of type `S`\n//│ ║  l.42: \tdef cons_ty : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t                                       ^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.46: \tcons_ty = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t                                                         ^^^^^\n//│ ╟── from type variable:\n//│ ║  l.46: \tcons_ty = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ╙──      \t                                          ^^\n\ncons_ty2 = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ cons_ty2: 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│   where\n//│     'n := S['n]\n\ntype Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ Defined type alias Cons_ty\n\n\n\n\n\n\n\n\n\n\n\n\n// :exit\n// ====================================================================================================\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ncons_ty = cons : Cons_ty\n//│ Cons_ty\n//│   <:  cons_ty:\n//│ 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.104: \tcons_ty = cons : Cons_ty\n//│ ║         \t          ^^^^\n//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n`\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.70: \ttype Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t                                        ^^\n//│ ╟── Note: class type parameter N is defined at:\n//│ ║  l.18: \tclass Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] }\n//│ ╙──      \t              ^\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.104: \tcons_ty = cons : Cons_ty\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── expression of type `'n` does not match type `'p`\n//│ ╟── Note: constraint arises from quantified type variable:\n//│ ║  l.20: \ttype Vec[A, N] = forall 'r. (forall 'p. (Nil & { size: N } | Cons[A, S['p]] & Cons[A, N]) -> 'r) -> 'r\n//│ ╙──      \t                                    ^^\n\ncons_ty3 = cons : Cons_ty\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.126: \tcons_ty3 = cons : Cons_ty\n//│ ║         \t           ^^^^\n//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n`\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.70: \ttype Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t                                        ^^\n//│ ╟── Note: class type parameter N is defined at:\n//│ ║  l.18: \tclass Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] }\n//│ ╙──      \t              ^\n//│ cons_ty3: Cons_ty\n\ndef cons h (t: Vec['a, 'n]) k = k (Cons h t)\n//│ cons: ('head & 'A) -> Vec['A & 'a, 'n] -> ((Cons['A, 'n] with {head: 'head, size: forall 'P. S['P], tail: Vec['a, 'n]}) -> 'b) -> 'b\n\ncons : Cons_ty\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.142: \tcons : Cons_ty\n//│ ║         \t^^^^\n//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n`\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.70: \ttype Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t                                        ^^\n//│ ╟── from type variable:\n//│ ║  l.139: \tdef cons h (t: Vec['a, 'n]) k = k (Cons h t)\n//│ ║         \t                       ^^\n//│ ╟── Note: class type parameter N is defined at:\n//│ ║  l.18: \tclass Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] }\n//│ ╙──      \t              ^\n//│ res: Cons_ty\n\ndef cons h (t: Vec['a, 'n]) k = k (Cons h t)\n//│ cons: ('head & 'A) -> Vec['A & 'a, 'n] -> ((Cons['A, 'n] with {head: 'head, size: forall 'P. S['P], tail: Vec['a, 'n]}) -> 'b) -> 'b\n\ncons : Cons_ty\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.161: \tcons : Cons_ty\n//│ ║         \t^^^^\n//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n`\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.70: \ttype Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t                                        ^^\n//│ ╟── from type variable:\n//│ ║  l.158: \tdef cons h (t: Vec['a, 'n]) k = k (Cons h t)\n//│ ║         \t                       ^^\n//│ ╟── Note: class type parameter N is defined at:\n//│ ║  l.18: \tclass Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] }\n//│ ╙──      \t              ^\n//│ res: Cons_ty\n\n\n// v0 = nil\n\n// v0_ty = v0 : Vec[int, Z]\n\nv1_ = Cons 1 nil\n//│ v1_: Cons[1, 'N] with {size: forall 'P. S['P], tail: forall 'a. (Nil -> 'a) -> 'a}\n//│   where\n//│     'N :> Z\n\nv1_ty = v1_ : Cons[int, Z]\n//│ v1_ty: Cons[int, Z]\n\nv1_0 = cons 1 nil\n//│ v1_0: ((Cons[1, 'n] with {size: forall 'P. S['P], tail: Vec[nothing, 'n]}) -> 'a) -> 'a\n//│   where\n//│     'n :> Z\n\nv1_0 : Vec[int, S[Z]]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.195: \tv1_0 : Vec[int, S[Z]]\n//│ ║         \t^^^^\n//│ ╟── application of type `Z` is not an instance of type `S`\n//│ ║  l.28: \tdef Nil = Nil { size = Z{} }\n//│ ║        \t                       ^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.195: \tv1_0 : Vec[int, S[Z]]\n//│ ║         \t                ^^^^\n//│ ╟── Note: class Z is defined at:\n//│ ║  l.7: \tclass Z\n//│ ╙──     \t      ^\n//│ res: Vec[int, S[Z]]\n\nv1_1 k = k v1_\n//│ v1_1: ((forall 'N. Cons[1, 'N] with {size: forall 'P. S['P], tail: forall 'a. (Nil -> 'a) -> 'a}) -> 'b) -> 'b\n//│   where\n//│     'N :> Z\n\n// :e\nv1_1 : Vec[int, S[Z]]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.216: \tv1_1 : Vec[int, S[Z]]\n//│ ║         \t^^^^\n//│ ╟── application of type `Z` is not an instance of type `S`\n//│ ║  l.28: \tdef Nil = Nil { size = Z{} }\n//│ ║        \t                       ^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.216: \tv1_1 : Vec[int, S[Z]]\n//│ ║         \t                ^^^^\n//│ ╟── Note: class Z is defined at:\n//│ ║  l.7: \tclass Z\n//│ ╙──     \t      ^\n//│ res: Vec[int, S[Z]]\n\n\nv1_tty = cons_ty 1 nil_ty\n//│ v1_tty: Vec[int, S[Z]]\n\nv1_tty = cons_ty2 1 nil_ty\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.235: \tv1_tty = cons_ty2 1 nil_ty\n//│ ║         \t         ^^^^^^^^^^^^^^^^^\n//│ ╟── type `Z` is not an instance of type `S`\n//│ ║  l.39: \tnil_ty = nil : Vec[int, Z]\n//│ ║        \t                        ^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.65: \tcons_ty2 = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ║        \t                                                          ^^^^^\n//│ ╟── from type variable:\n//│ ║  l.65: \tcons_ty2 = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]]\n//│ ╙──      \t                                           ^^\n//│ v1_tty: error | Vec[int, S['n]]\n//│   where\n//│     'n :> S['n] | Z\n//│        <: nothing\n\nv1_tty = cons_ty3 1 nil_ty\n//│ v1_tty: Vec[int, S[Z]]\n\n\nv1 = cons 1 nil\n//│ v1: ((Cons[1, 'n] with {size: forall 'P. S['P], tail: Vec[nothing, 'n]}) -> 'a) -> 'a\n//│   where\n//│     'n :> Z\n\nv2 = cons 1 (cons 2 nil)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.262: \tv2 = cons 1 (cons 2 nil)\n//│ ║         \t     ^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Z` is not an instance of type `S`\n//│ ║  l.28: \tdef Nil = Nil { size = Z{} }\n//│ ║        \t                       ^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.20: \ttype Vec[A, N] = forall 'r. (forall 'p. (Nil & { size: N } | Cons[A, S['p]] & Cons[A, N]) -> 'r) -> 'r\n//│ ║        \t                                                                     ^^^^^\n//│ ╟── Note: class Z is defined at:\n//│ ║  l.7: \tclass Z\n//│ ╙──     \t      ^\n//│ v2: error\n\n\ndef impossible x = case x of {}\n//│ impossible: nothing -> nothing\n\ndef head1 vec = vec (fun v -> case v of {\n  | Nil -> impossible v.size\n  | Cons -> v.head\n  })\n//│ head1: ((forall 'head. (Cons[?, ?] & {head: 'head} | Nil & {size: nothing}) -> 'head) -> 'a) -> 'a\n\ndef head1_ty : Vec['a, S['p]] -> 'a\nhead1_ty = head1\n//│ head1_ty: Vec['a, S['p]] -> 'a\n//│ ((forall 'head. (Cons[?, ?] & {head: 'head} | Nil & {size: nothing}) -> 'head) -> 'a) -> 'a\n//│   <:  head1_ty:\n//│ Vec['a, S['p]] -> 'a\n\ndef head2 (vec: Vec['a, S['p]]) = vec (fun v -> case v of {\n  | Nil -> impossible v.size\n  | Cons -> v.head\n  })\n//│ head2: Vec['a, S['p]] -> 'a\n\nhead1 v1\nhead1 v2\n//│ res: 1\n//│ res: error\n\n:e\nhead1 nil\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.306: \thead1 nil\n//│ ║         \t^^^^^^^^^\n//│ ╟── application of type `Z` does not match type `nothing`\n//│ ║  l.28: \tdef Nil = Nil { size = Z{} }\n//│ ║        \t                       ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.278: \tdef impossible x = case x of {}\n//│ ║         \t                        ^\n//│ ╟── from field selection:\n//│ ║  l.282: \t  | Nil -> impossible v.size\n//│ ║         \t                      ^^^^^^\n//│ ╟── Note: class Z is defined at:\n//│ ║  l.7: \tclass Z\n//│ ╙──     \t      ^\n//│ res: error\n\n\nrec def sum vec = vec (fun v -> case v of {\n  | Nil -> 0\n  | Cons -> v.head + sum v.tail\n  })\n//│ sum: 'a -> 'b\n//│   where\n//│     'a <: (((Cons[?, ?]\\size with {head: int, tail: 'a}) | Nil) -> int) -> (int & 'b)\n\ndef sum_ty : Vec[int, 'n] -> int\n//│ sum_ty: Vec[int, 'n] -> int\n\n// * Note: for crazy reasons, this one works out when we extrude top/bot\n// * instead of specific Extruded types...\nsum_ty = sum\n//│ 'a -> 'b\n//│   where\n//│     'a <: (((Cons[?, ?]\\size with {head: int, tail: 'a}) | Nil) -> int) -> (int & 'b)\n//│   <:  sum_ty:\n//│ Vec[int, 'n] -> int\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?sum. ?sum <: forall 'n. Vec[int, 'n] -> int` exceeded recursion depth limit (250)\n//│ ║  l.338: \tsum_ty = sum\n//│ ║         \t^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n\n\nsum nil\n//│ res: int\n\n// * Note: also worked woth top/bot extrusion\nsum v1_0\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?sum. ?sum <: (forall ?a. ?a) -> ?b` exceeded recursion depth limit (250)\n//│ ║  l.354: \tsum v1_0\n//│ ║         \t^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n\n// * Note: also worked woth top/bot extrusion\nsum v2\n//│ res: error\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\ndef head1_ty v = case v of {\n  | Nil -> impossible v.size\n  | Cons -> v.head\n  }\n//│ (Cons[?, ?] & {head: 'head} | Nil & {size: nothing}) -> 'head\n//│   <:  head1_ty:\n//│ Vec['a, S['p]] -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \tdef head1_ty v = case v of {\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+2: \t  | Nil -> impossible v.size\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+3: \t  | Cons -> v.head\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.+4: \t  }\n//│ ║        \t^^^\n//│ ╟── type `(forall 'p. (Cons['a, in S[in 'p0 & 'p out 'p0 | 'p] out S[in 'p0 | 'p out 'p0 & 'p]] | (Nil with {size: S['p0]})) -> 'r) -> 'r` does not match type `Cons[?, ?] & ?a | Nil & ?b`\n//│ ║  l.20: \ttype Vec[A, N] = forall 'r. (forall 'p. (Nil & { size: N } | Cons[A, S['p]] & Cons[A, N]) -> 'r) -> 'r\n//│ ║        \t                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.+1: \tdef head1_ty v = case v of {\n//│ ╙──      \t                      ^\n\n\nsum v1_ty\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tsum v1_ty\n//│ ║        \t^^^^^^^^^\n//│ ╟── type `Cons[int, Z]` is not a function\n//│ ║  l.187: \tv1_ty = v1_ : Cons[int, Z]\n//│ ║         \t              ^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(forall ?a ?b. ?a -> ?b) -> ?c`\n//│ ║  l.+1: \tsum v1_ty\n//│ ║        \t    ^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.325: \trec def sum vec = vec (fun v -> case v of {\n//│ ║         \t                  ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.326: \t  | Nil -> 0\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.327: \t  | Cons -> v.head + sum v.tail\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.328: \t  })\n//│ ║         \t^^^^\n//│ ╟── from reference:\n//│ ║  l.325: \trec def sum vec = vec (fun v -> case v of {\n//│ ╙──       \t                  ^^^\n//│ res: error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp/YicongFCP.mls",
    "content": "\n\ndef foo =\n  forall 'a. fun (x: 'a) -> x\n//│ foo: 'a -> 'a\n//│    = [Function: foo]\n\n\ndef foo esc =\n  forall 'T. fun (x: 'T) -> esc x\n//│ foo: (??T -> 'a) -> anything -> 'a\n//│    = [Function: foo1]\n\ntmp = foo (fun x -> 1)\n//│ tmp: anything -> 1\n//│    = [Function (anonymous)]\n\ntmp 0\n//│ res: 1\n//│    = 1\n\nfoo (fun x -> 1) \"2\"\n//│ res: 1\n//│    = 1\n\nfoo id\n//│ res: anything -> ??T\n//│    = [Function (anonymous)]\n\nr = foo id true\n//│ r: ??T\n//│  = true\n\n:e\nnot r\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.35: \tnot r\n//│ ║        \t^^^^^\n//│ ╟── type variable `'T` leaks out of its scope\n//│ ║  l.10: \t  forall 'T. fun (x: 'T) -> esc x\n//│ ║        \t         ^^\n//│ ╟── into type `bool`\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.10: \t  forall 'T. fun (x: 'T) -> esc x\n//│ ╙──      \t                            ^^^\n//│ res: bool | error\n//│    = false\n\n\ndef foo esc =\n  forall 'T. fun (x: 'T) -> esc x : 'T\n//│ foo: (??T -> ??T0) -> 'T -> 'T\n//│    = [Function: foo2]\n\n:e\nfoo id\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.57: \tfoo id\n//│ ║        \t^^^^^^\n//│ ╟── type variable `'T` leaks out of its scope\n//│ ║  l.52: \t  forall 'T. fun (x: 'T) -> esc x : 'T\n//│ ║        \t         ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.52: \t  forall 'T. fun (x: 'T) -> esc x : 'T\n//│ ║        \t                            ^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.52: \t  forall 'T. fun (x: 'T) -> esc x : 'T\n//│ ╙──      \t                            ^^^^^\n//│ res: error | 'T -> 'T\n//│    = [Function (anonymous)]\n\nfoo (fun x -> error)\n//│ res: 'T -> 'T\n//│    = [Function (anonymous)]\n\ndef foo (esc: forall 'a. 'a -> 'a) =\n  forall 'T. fun (x: 'T) -> esc x : 'T\n//│ foo: (forall 'a. 'a -> 'a) -> (forall 'T. 'T -> 'T)\n//│    = [Function: foo3]\n\nfoo id\n//│ res: 'T -> 'T\n//│    = [Function (anonymous)]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/Boxy.mls",
    "content": ":NoJS\n:NoRecursiveTypes\n\n// ============ Dummy classes to represent the types in the examples ============\n// Char is represented as String\n// All type constructors beside arrow are invariant in Boxy\n\nclass None\nclass Some[a]: { val: a }\ntype Option[a] = None | Some[a]\n//│ Defined class None\n//│ Defined class Some[+a]\n//│ Defined type alias Option[+a]\n\nclass List[a]\n  method Head: a\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n\ndef cons[a]: a -> List[a] -> List[a]\n//│ cons: 'a -> List['a] -> List['a]\n\ndef nil: List['a]\n//│ nil: List[nothing]\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: forall 'a. List['a] -> 'a\n//│ head: List['a] -> 'a\n\ndef tail: forall 'a. List['a] -> List['a]\n//│ tail: List['a] -> List['a]\n\ndef single: forall 'a. 'a -> List['a]\n//│ single: 'a -> List['a]\n\ndef length: forall 'a. List['a] -> int\n//│ length: List[?] -> int\n\ndef ids: List[forall 'a. 'a -> 'a]\n//│ ids: List[forall 'a. 'a -> 'a]\n\n// ============ Sec 1 ============\n\ndef f get = (get (cons 1 (cons 2 nil)), get (cons \"a\" (cons \"b\" (cons \"c\" nil))))\n//│ f: (List[1 | 2] -> 'a & List[\"a\" | \"b\" | \"c\"] -> 'b) -> ('a, 'b,)\n\n// definition in paper:\n//   g None = (0, \"0\")\n//   g (Some get) = (get [1,2], get [\"a\",\"b\",\"c\"])\ndef g x = case x of\n  { None -> (0, \"0\")\n  | Some -> (x.val (cons 1 (cons 2 nil)), x.val (cons \"a\" (cons \"b\" (cons \"c\" nil))))\n  }\n//│ g: (None | Some[?] & {val: List[1 | 2] -> 'a & List[\"a\" | \"b\" | \"c\"] -> 'b}) -> (0 | 'a, \"0\" | 'b,)\n\n// ============ Sec 2 ============\n\n// FreezeML C1\nlength ids\n//│ res: int\n\n// ============ Sec 3.2 ============\n\n(fun x -> fun g -> (g true, g 3)) 4\n//│ res: (true -> 'a & 3 -> 'b) -> ('a, 'b,)\n\n// ============ Sec 3.3 ============\n\n// let-bound version of id, with lexically scoped type variables (TODO: support this)\n// def id: forall 'a. 'a -> 'a\n// def id = fun x -> let y = x: 'a in y\nfun x -> let y = x in y\n//│ res: 'a -> 'a\n\n// ============ Sec 4.4 ============\n\nlet f = (fun g -> (g 3, g true)): (forall 'a. 'a -> 'a) -> (int, bool) in f (fun x -> x)\nlet f = fun g -> (g 3, g true) in f (fun x -> x)\n//│ res: (int, bool,)\n//│ res: (3, true,)\n\n(fun g -> (g 3, g true)) (fun x -> x)\n//│ res: (3, true,)\n\n// ============ Sec 6 ============\n\n// FreezeML C2\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n\n// FreezeML C4\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n\n// FreezeML C3\nhead ids\n//│ res: 'a -> 'a\n\n// FreezeML C6\ncons (fun x -> x) ids\n//│ res: List[forall 'a. 'a -> 'a]\n\nlet f = fun x -> nil in f (fun g -> (g 3, g true))\n//│ res: List[nothing]\n\n// ============ Sec 7 ============\n\n// eta-expansion does not preserve typability (in the presented system)\ndef f: (int -> (forall 'a. 'a -> 'a)) -> int\nfun x -> f x // Not typeable in Boxy Types!\n//│ f: (int -> (forall 'a. 'a -> 'a)) -> int\n//│ res: (int -> (forall 'a. 'a -> 'a)) -> int\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/CPS_LB.mls",
    "content": ":NoJS\n:NoRecursiveTypes\n\n\n// ------------ Dummy classes to represent the types in the examples ------------\n\nclass List[a]\n  method Get: a\n//│ Defined class List[+a]\n//│ Declared List.Get: List['a] -> 'a\n\n// Used to represent `::`\ndef cons: 'a -> List['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n\n// Used to represent `[]`\ndef nil: List['a]\n//│ nil: List[nothing]\n\ndef concat: string -> List[string] -> string\n//│ concat: string -> List[string] -> string\n\n\n// ------------ Examples ------------\n\n\n// (* s  starts a sequence, cps style *)\ndef s k = k () nil\n//│ s: (() -> List[nothing] -> 'a) -> 'a\n\ndef insert v () acu k = k () (cons v acu)\n//│ insert: 'a -> () -> List['a] -> (() -> List['a] -> 'b) -> 'b\n\n// (* x  inserts \"x\" in the acu *)\ndef x () = insert \"x\" ()\n//│ x: () -> List['a] -> (() -> List[\"x\" | 'a] -> 'b) -> 'b\n\n// (* We call x a 'token', in the sequence. *)\n\n// (* e  ends the sequence. It builds a token that can be inserted in another sequence or that can be printed. *)\ndef e () acu = insert (concat \",\" acu)\n//│ e: () -> List[string] -> () -> List['a] -> (() -> List[string | 'a] -> 'b) -> 'b\n\n\n// (* Prints a token *)\ndef print t = t () nil (fun () -> fun r -> log (concat \",\" r))\n//│ print: (() -> List[nothing] -> (() -> List[string] -> unit) -> 'a) -> 'a\n\n// Added by me:\ns x x (s x x e)\n//│ res: (() -> List[string] -> 'a) -> 'a\n\n\ndef test8  = (s x x (s x x e) x (s x x x e) e)\n//│ test8: () -> List['a] -> (() -> List[string | 'a] -> 'b) -> 'b\n\nprint test8\n\n\ndef test14 = (s x x x x x x x x x x x x x x e)\n//│ test14: () -> List['a] -> (() -> List[string | 'a] -> 'b) -> 'b\n\ndef test16 = (s x x x x x x x x x x x x x x x x e)\n//│ test16: () -> List['a] -> (() -> List[string | 'a] -> 'b) -> 'b\n\n// (* This is too much for the type-checker. *)\ndef test18 = (s x x x x x x x x x x x x x x x x x x e)\n//│ test18: () -> List['a] -> (() -> List[string | 'a] -> 'b) -> 'b\n\n:RecursiveTypes\ndef test18 = (s x x x x x x x x x x x x x x x x x x e)\n//│ test18: () -> List['a] -> (() -> List[string | 'a] -> 'b) -> 'b\n:NoRecursiveTypes\n\n\n// (* A function that receives a token *)\ndef f t = (s x x t x x e)\n//│ f: (() -> List[\"x\"] -> (forall 'a 'b. () -> List['a] -> (() -> List[\"x\" | 'a] -> 'b) -> 'b) -> (forall 'a 'c. () -> List['a] -> (() -> List[\"x\" | 'a] -> 'c) -> 'c) -> (forall 'a0 'd. () -> List[string] -> () -> List['a0] -> (() -> List[string | 'a0] -> 'd) -> 'd) -> 'e) -> 'e\n\n// (* If the token is used twice, we must reveive two arguments *)\ndef g t1 t2 = (s x x t1 x (s x t2 x e) e)\n//│ g: (() -> List[\"x\"] -> (forall 'a 'b. () -> List['a] -> (() -> List[\"x\" | 'a] -> 'b) -> 'b) -> 'c -> (forall 'a0 'd. () -> List[string] -> () -> List['a0] -> (() -> List[string | 'a0] -> 'd) -> 'd) -> 'e) -> (() -> List[\"x\"] -> (forall 'a 'f. () -> List['a] -> (() -> List[\"x\" | 'a] -> 'f) -> 'f) -> (forall 'a0 'g. () -> List[string] -> () -> List['a0] -> (() -> List[string | 'a0] -> 'g) -> 'g) -> 'c) -> 'e\n\n// (* This does not type. It requires first-class polymorphism. *)\ndef h t = g t t\n//│ h: (() -> List[\"x\"] -> ((forall 'a 'b. () -> List['a] -> (() -> List[\"x\" | 'a] -> 'b) -> 'b) -> 'c -> (forall 'a0 'd. () -> List[string] -> () -> List['a0] -> (() -> List[string | 'a0] -> 'd) -> 'd) -> 'e & (forall 'a 'f. () -> List['a] -> (() -> List[\"x\" | 'a] -> 'f) -> 'f) -> (forall 'a0 'g. () -> List[string] -> () -> List['a0] -> (() -> List[string | 'a0] -> 'g) -> 'g) -> 'c)) -> 'e\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/FreezeML.mls",
    "content": "// * FreezeML: complete and easy type inference for first-class polymorphism\n// * https://dl.acm.org/doi/10.1145/3385412.3386003\n// * Extended version: https://arxiv.org/abs/2004.00396\n\n:NoRecursiveTypes\n\n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n\nclass ST[S, A]\n  method Inv_S: S -> S\n  method Cov_A: A\n//│ Defined class ST[=S, +A]\n//│ Declared ST.Inv_S: ST['S, ?] -> 'S -> 'S\n//│ Declared ST.Cov_A: ST['S, 'A] -> 'A\n\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: List['a] -> 'a\ndef head l = l.Head\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n//│ List['a] -> 'a\n//│   <:  head:\n//│ List['a] -> 'a\n//│     = [Function: head]\n\ndef tail: List['a] -> List['a]\ndef tail l = l.Tail\n//│ tail: List['a] -> List['a]\n//│     = <missing implementation>\n//│ List['a] -> List['a]\n//│   <:  tail:\n//│ List['a] -> List['a]\n//│     = [Function: tail]\n\n// Used to represent `[]` in the papers\ndef nil: List['a]\nnil = Nil {}\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\ndef cons: 'a -> List['a] -> List['a]\ndef cons head tail = Cons { head; tail }\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\ndef is_empty: forall 'a. List['a] -> bool\ndef is_empty l = eq l nil\n//│ is_empty: List[?] -> bool\n//│         = <missing implementation>\n//│ anything -> bool\n//│   <:  is_empty:\n//│ List[?] -> bool\n//│         = [Function: is_empty]\n\ndef single: 'a -> List['a]\ndef single x = cons x nil\n//│ single: 'a -> List['a]\n//│       = <missing implementation>\n//│ 'a -> List['a]\n//│   <:  single:\n//│ 'a -> List['a]\n//│       = [Function: single]\n\ndef append: List['a] -> List['a] -> List['a]\nrec def append l1 l2 =\n  if is_empty l1 then l2\n  else cons (head l1) (append (tail l1) l2)\n//│ append: List['a] -> List['a] -> List['a]\n//│       = <missing implementation>\n//│ List['a] -> List['a] -> List['a]\n//│   <:  append:\n//│ List['a] -> List['a] -> List['a]\n//│       = [Function: append]\n\ndef length: List['a] -> int\nrec def length l =\n  if is_empty l then 0\n  else succ (length (tail l))\n//│ length: List[?] -> int\n//│       = <missing implementation>\n//│ List[?] -> int\n//│   <:  length:\n//│ List[?] -> int\n//│       = [Function: length1]\n\ndef id: 'a -> 'a\ndef id x = x\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id:\n//│ 'a -> 'a\n//│   = [Function: id1]\n\ndef ids: List[forall 'a. 'a -> 'a]\ndef ids = single id\n//│ ids: List[forall 'a. 'a -> 'a]\n//│    = <missing implementation>\n//│ List[forall 'a. 'a -> 'a]\n//│   <:  ids:\n//│ List[forall 'a. 'a -> 'a]\n//│    = [Function: ids]\n\ndef inc: int -> int\ndef inc = succ\n//│ inc: int -> int\n//│    = <missing implementation>\n//│ int -> int\n//│   <:  inc:\n//│ int -> int\n//│    = [Function: inc]\n\ndef choose: 'a -> 'a -> 'a\ndef choose x y = if true then x else y\n//│ choose: 'a -> 'a -> 'a\n//│       = <missing implementation>\n//│ 'a -> 'a -> 'a\n//│   <:  choose:\n//│ 'a -> 'a -> 'a\n//│       = [Function: choose]\n\ndef poly: (forall 'a. 'a -> 'a) -> (int, bool)\ndef poly f = (f 1, f true)\n//│ poly: (forall 'a. 'a -> 'a) -> (int, bool,)\n//│     = <missing implementation>\n//│ (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│   <:  poly:\n//│ (forall 'a. 'a -> 'a) -> (int, bool,)\n//│     = [Function: poly]\n\ndef auto : (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\ndef auto x = x x\n//│ auto: (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│     = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  auto:\n//│ (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│     = [Function: auto]\n\ndef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\ndef auto_ x = x x\n//│ auto_: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│      = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  auto_:\n//│ (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│      = [Function: auto_]\n\ndef map: ('a -> 'b) -> List['a] -> List['b]\nrec def map f l =\n  if is_empty l then nil\n  else cons (f (head l)) (map f (tail l))\n//│ map: ('a -> 'b) -> List['a] -> List['b]\n//│    = <missing implementation>\n//│ ('b -> 'a) -> List['b] -> List['a]\n//│   <:  map:\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│    = [Function: map]\n\ndef app: ('a -> 'b) -> 'a -> 'b\ndef app f x = f x\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = <missing implementation>\n//│ ('a -> 'b) -> 'a -> 'b\n//│   <:  app:\n//│ ('a -> 'b) -> 'a -> 'b\n//│    = [Function: app]\n\ndef revapp: 'a -> ('a -> 'b) -> 'b\ndef revapp x f = f x\n//│ revapp: 'a -> ('a -> 'b) -> 'b\n//│       = <missing implementation>\n//│ 'a -> ('a -> 'b) -> 'b\n//│   <:  revapp:\n//│ 'a -> ('a -> 'b) -> 'b\n//│       = [Function: revapp]\n\ndef flip: ('a -> 'b -> 'c) -> 'b -> 'a -> 'c\ndef flip f = fun x -> fun y -> f y x\n//│ flip: ('a -> 'b -> 'c) -> 'b -> 'a -> 'c\n//│     = <missing implementation>\n//│ ('a -> 'b -> 'c) -> 'b -> 'a -> 'c\n//│   <:  flip:\n//│ ('a -> 'b -> 'c) -> 'b -> 'a -> 'c\n//│     = [Function: flip]\n\n:ng\ndef runST: (forall 's. ST['s, 'v]) -> 'v\n//│ runST: (forall 's. ST['s, 'v]) -> 'v\n\n:ng\ndef argST: ST['s, int]\n//│ argST: ST['s, int]\n\n\n// ============ A. polymorphic instantiation ============\n\n// A1\nconst2 x y = y\n//│ const2: anything -> 'a -> 'a\n//│       = [Function: const2]\n\n// A2\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// A3\nchoose nil ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// A4\nfun (x: forall 'a. 'a -> 'a) -> x x\n//│ res: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│    = [Function: res]\n\n// A4'\nfun x -> x x\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// A5\nid auto\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'b. 'b -> 'b)\n//│    = [Function: auto]\n\n// A6\nid auto_\n//│ res: (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│    = [Function: auto_]\n\n// A7\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\n// A8\n:ns\nchoose id auto_\n//│ res: 'c\n//│   where\n//│     'c :> (forall 'a. 'a -> 'a) | (forall 'b. (forall 'a0. 'a0 -> 'a0) -> 'b -> 'b)\n//│    = [Function: id1]\n\n// A9\ndef f: ('a -> 'a) -> List['a] -> 'a\n//│ f: ('a -> 'a) -> List['a] -> 'a\n//│  = <missing implementation>\n\n:ng\nf (choose id) ids\n//│ res: 'a -> 'a\n\n// A10\npoly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A11\npoly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// A12\nid poly (fun x -> x)\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n\n// ============ B. inference of polymorphic arguments ============\n\n// B1\nfun f -> (f 1, f true)\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: res]\n\n// B2\nfun xs -> poly (head xs)\n//│ res: List[forall 'a. 'a -> 'a] -> (int, bool,)\n//│    = [Function: res]\n\n\n// ============ C. functions on polymorphic lists ============\n\n// C1\nlength ids\n//│ res: int\n//│    = 1\n\n// C2\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// C3\nhead ids\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// C4\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// C5\ncons id ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C6\ncons (fun x -> x) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function (anonymous)],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C7\nappend (single inc) (single id)\n//│ res: List[int -> int]\n//│    = Cons {\n//│        head: [Function: succ],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// C8\n:ng\ndef g: List['a] -> List['a] -> 'a\ng (single id) ids\n//│ g: List['a] -> List['a] -> 'a\n//│ res: 'a -> 'a\n\n// C9\nmap poly (single id)\n//│ res: List[(int, bool,)]\n//│    = Cons { head: [ 1, true ], tail: Nil {} }\n\n// C10\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n\n// ============ D. application functions ============\n\n// D1\napp poly id\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D2\nrevapp id poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// D3\n:ng\nrunST argST\n//│ res: int\n\n// D4\n:ng\napp runST argST\n//│ res: int\n\n// D5\n:ng\nrevapp argST runST\n//│ res: int\n\n\n// ============ E. η-expansion ============\n\n:ng\ndef h: int -> (forall 'a. 'a -> 'a)\ndef k: 'a -> List['a] -> 'a\ndef lst: List[forall 'a. int -> 'a -> 'a]\n//│ h: int -> (forall 'a. 'a -> 'a)\n//│ k: 'a -> List['a] -> 'a\n//│ lst: List[forall 'a. int -> 'a -> 'a]\n\n// E1\n:ng\nk h lst\n//│ res: int -> 'a -> 'a\n\n// E2\n:ng\nk (fun x -> h x) lst\n//│ res: int -> 'a -> 'a\n\n// E3\n:ng\ndef r: (forall 'a. 'a -> (forall 'b. 'b -> 'b)) -> int\n//│ r: (forall 'b. anything -> 'b -> 'b) -> int\n:ng\nr (fun x -> fun y -> y)\n//│ res: int\n\n:ng\n:ns\nr\n//│ res: (forall 'a. 'a -> (forall 'b. 'b -> 'b)) -> int\n\n\n// ============ F. FreezeML Programs ============\n\n// F5\nauto id\n//│ res: 'b -> 'b\n//│    = [Function: id1]\n\n// F6\ncons (head ids) ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons {\n//│        head: [Function: id1],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\n// F7\n(head ids) 3\n//│ res: 3\n//│    = 3\n\n// F8\nchoose (head ids)\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// F9\nlet f = revapp id in f poly\n//│ res: (int, bool,)\n//│    = [ 1, true ]\n\n// F10\na = choose id (fun (x: (forall 'a. 'a -> 'a)) -> auto_ x)\n//│ a: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│  = [Function: id1]\n\na id\n//│ res: 'b -> 'b\n//│    = [Function: id1]\n\nchoose id (fun x -> auto_ x)\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│    = [Function: id1]\n\na = choose id auto_\n//│ a: (forall 'a. 'a -> 'a & 'a0) -> ('b -> 'b | 'a0)\n//│  = [Function: id1]\n\na id\n//│ res: 'b -> 'b\n//│    = [Function: id1]\n\n\n\n\n\n\n// ============ Expected error cases (useful for regression-testing error messages) ============\n\n\n:ns\n:e // * Skolem extrusion; rightly rejected\nchoose id (fun (x: ('a -> 'a)) -> auto_ x)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.503: \tchoose id (fun (x: ('a -> 'a)) -> auto_ x)\n//│ ║         \t                                  ^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.172: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║         \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.172: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ╙──       \t                              ^^\n//│ res: 'c\n//│   where\n//│     'c :> (forall 'a. 'a -> 'a) | (forall 'a0 'd. ('a0 -> 'a0) -> 'd)\n//│     'd :> (forall 'b. 'b -> 'b) | error\n//│     'a0 :> ??a\n//│         <: ??a0\n//│    = [Function: id1]\n\n// * The skolem used to (unsafely) leak into this type – see also `Skolems.mls`:\nres\n//│ res: (anything -> ??a & 'a) -> (error | 'b -> 'b | 'a)\n//│    = [Function: id1]\n\n:e // skolem extrusion\nres id\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.527: \tres id\n//│ ║         \t^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.172: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║         \t                        ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.172: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ║         \t                              ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.503: \tchoose id (fun (x: ('a -> 'a)) -> auto_ x)\n//│ ╙──       \t                          ^^\n//│ res: error | 'b -> 'b\n//│    = [Function: id1]\n\n\n:e\na (fun x -> { u = x })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.545: \ta (fun x -> { u = x })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{u: ?a}` does not match type `'a`\n//│ ║  l.545: \ta (fun x -> { u = x })\n//│ ║         \t            ^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.172: \tdef auto_ : (forall 'a. 'a -> 'a) -> 'b -> 'b\n//│ ╙──       \t                              ^^\n//│ res: error | 'b -> ({u: 'b} | 'b)\n//│    = [Function (anonymous)]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/GHC-rank-n.mls",
    "content": "// * Practical type inference for arbitrary-rank types\n// * Many examples in the Motivation section, incl a rank-3 one\n\n\n\n// Theorem 4.3 (Distributivity) ⊢dsk ∀a.σ1 → σ2 ≤ (∀a.σ1) → ∀a.σ2.\n\n\nclass F[A]\n  method Id: A -> A\nclass G[A]\n  method Id: A -> A\n//│ Defined class F[=A]\n//│ Declared F.Id: F['A] -> 'A -> 'A\n//│ Defined class G[=A]\n//│ Declared G.Id: G['A] -> 'A -> 'A\n\ndef f: forall 'a. F['a] -> G['a]\n//│ f: F['a] -> G['a]\n//│  = <missing implementation>\n\n\nf : (forall 'a. F['a]) -> (forall 'a. G['a])\n//│ res: (forall 'a. F['a]) -> (forall 'a0. G['a0])\n//│    = <no result>\n//│      f is not implemented\n\n\n:DontDistributeForalls\n\n:e\nf: (forall 'a. F['a]) -> (forall 'a. G['a])\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.32: \tf: (forall 'a. F['a]) -> (forall 'a. G['a])\n//│ ║        \t^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.32: \tf: (forall 'a. F['a]) -> (forall 'a. G['a])\n//│ ║        \t                                       ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.32: \tf: (forall 'a. F['a]) -> (forall 'a. G['a])\n//│ ╙──      \t^\n//│ res: (forall 'a. F['a]) -> (forall 'a0. G['a0])\n//│    = <no result>\n//│      f is not implemented\n\n\n\n// \"In this example it is plain as a pike-staff that i should have the type (∀a.a → a)\"\n// foo = (\\i. (i 3, i True)) :: (∀a.a → a) → (Int, Bool)\n\nfoo = (fun i -> (i 3, i true)) : (forall 'a. 'a -> 'a) -> (int, bool)\n//│ foo: (forall 'a. 'a -> 'a) -> (int, bool,)\n//│    = [Function: foo]\n\n// bar has type ∀a.(Int → a) → a\n// foo w = bar (\\x. x+w)\n\ndef bar: forall 'a. (int -> 'a) -> 'a\n//│ bar: (int -> 'a) -> 'a\n//│    = <missing implementation>\n\nfoo w = bar (fun x -> x + w)\n//│ foo: int -> int\n//│    = <no result>\n//│      bar is not implemented\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/HMF.mls",
    "content": ":NoRecursiveTypes\n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\ndef cons[a]: a -> List[a] -> List[a]\ndef cons head tail = Cons { head; tail }\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\ndef nil: List['a]\nnil = Nil {}\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\nclass ST[S, A]\n  method Inv_S: S -> S\n  method Cov_A: A\n//│ Defined class ST[=S, +A]\n//│ Declared ST.Inv_S: ST['S, ?] -> 'S -> 'S\n//│ Declared ST.Cov_A: ST['S, 'A] -> 'A\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: forall 'a. List['a] -> 'a\ndef head l = l.Head\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n//│ List['a] -> 'a\n//│   <:  head:\n//│ List['a] -> 'a\n//│     = [Function: head]\n\ndef tail: forall 'a. List['a] -> List['a]\ndef tail l = l.Tail\n//│ tail: List['a] -> List['a]\n//│     = <missing implementation>\n//│ List['a] -> List['a]\n//│   <:  tail:\n//│ List['a] -> List['a]\n//│     = [Function: tail]\n\ndef is_empty: forall 'a. List['a] -> bool\ndef is_empty l = eq l nil\n//│ is_empty: List[?] -> bool\n//│         = <missing implementation>\n//│ anything -> bool\n//│   <:  is_empty:\n//│ List[?] -> bool\n//│         = [Function: is_empty]\n\ndef single: forall 'a. 'a -> List['a]\ndef single x = cons x nil\n//│ single: 'a -> List['a]\n//│       = <missing implementation>\n//│ 'a -> List['a]\n//│   <:  single:\n//│ 'a -> List['a]\n//│       = [Function: single]\n\ndef length: forall 'a. List['a] -> int\nrec def length l =\n  if is_empty l then 0\n  else succ (length (tail l))\n//│ length: List[?] -> int\n//│       = <missing implementation>\n//│ List[?] -> int\n//│   <:  length:\n//│ List[?] -> int\n//│       = [Function: length1]\n\ndef choose: forall 'a. 'a -> 'a -> 'a\ndef choose x y = if true then x else y\n//│ choose: 'a -> 'a -> 'a\n//│       = <missing implementation>\n//│ 'a -> 'a -> 'a\n//│   <:  choose:\n//│ 'a -> 'a -> 'a\n//│       = [Function: choose]\n\ndef map: forall 'a 'b. ('a -> 'b) -> List['a] -> List['b]\nrec def map f l =\n  if is_empty l then nil\n  else cons (f (head l)) (map f (tail l))\n//│ map: ('a -> 'b) -> List['a] -> List['b]\n//│    = <missing implementation>\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│   <:  map:\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│    = [Function: map]\n\ndef runST: (forall 's. ST['s, 'v]) -> 'v\n//│ runST: (forall 's. ST['s, 'v]) -> 'v\n//│      = <missing implementation>\n\ndef argST: ST['s, int]\n//│ argST: ST['s, int]\n//│      = <missing implementation>\n\n\n\n// ============ Sec 2 ============\n\ndef id x = x\n//│ id: 'a -> 'a\n//│   = [Function: id]\n\n// FreezeML B1\ndef poly f = (f 1, f true)\n//│ poly: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│     = [Function: poly]\n\n// FreezeML A10\npoly id\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\ndef app f x = f x\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = [Function: app]\n\n// FreezeML D1\napp poly id\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// FreezeML F2\nids = single id\n//│ ids: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id], tail: Nil {} }\n\nidss = single ids\n//│ idss: List[List[forall 'a. 'a -> 'a]]\n//│     = Cons {\n//│         head: Cons { head: [Function: id], tail: Nil {} },\n//│         tail: Nil {}\n//│       }\n\ndef revapp x f = f x\n//│ revapp: 'a -> ('a -> 'b) -> 'b\n//│       = [Function: revapp]\n\n// FreezeML D2\nrevapp id poly\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// FreezeML C1\nlength ids\n//│ res: int\n//│    = 1\n\n// FreezeML C10\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id], tail: Nil {} }\n\napp (map head) (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id], tail: Nil {} }\n\n// nope\nfun f -> poly f\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: res]\n\n// FreezeML D2\n// nope in plain HMF\nrevapp id poly\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// nope\nlet f = revapp id in f poly\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n:ne\ndef iapp: (int -> int) -> int -> int\nlet f = revapp id in (f poly, f iapp)\n//│ iapp: (int -> int) -> int -> int\n//│ res: ((1, true,), int -> int,)\n\n// ============ Sec 3 ============\n\n// FreezeML C2\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// nope\nsingle id : List[forall 'a. 'a -> 'a]\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id], tail: Nil {} }\n\n:ne\ndef foo: ((forall 'a. 'a -> 'a) -> (int, bool)) -> int\nfoo (fun f -> (f 1, f true))\n//│ foo: ((forall 'a. 'a -> 'a) -> (int, bool,)) -> int\n//│ res: int\n\nchoose nil ids\nchoose ids nil\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id], tail: Nil {} }\n\nlet f = choose nil in f ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// FreezeML D4\n:ne\napp runST argST\n//│ res: int\n\n// ============ Sec 4 ============\n\n// c.f. FreezeML A1\nfun x -> fun y -> x\n//│ res: 'a -> anything -> 'a\n//│    = [Function: res]\n\n// FreezeML C4\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id], tail: Nil {} }\n\nlet foo x y = single y in foo ids id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id], tail: Nil {} }\n\nhead ids 1\n//│ res: 1\n//│    = 1\n\n// ============ Sec 5 ============\n\n// FreezeML B1\ndef poly: (forall 'a. 'a -> 'a) -> (int, bool)\ndef poly f = (f 1, f true)\n//│ poly: (forall 'a. 'a -> 'a) -> (int, bool,)\n//│     = <missing implementation>\n//│ (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│   <:  poly:\n//│ (forall 'a. 'a -> 'a) -> (int, bool,)\n//│     = [Function: poly1]\n\nconst x y = x\n//│ const: 'a -> anything -> 'a\n//│      = [Function: const1]\n\n// ============ Sec 6 ============\n\n// FreezeML C5\nxs = cons id ids\n//│ xs: List[forall 'a. 'a -> 'a]\n//│   = Cons {\n//│       head: [Function: id],\n//│       tail: Cons { head: [Function: id], tail: Nil {} }\n//│     }\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/HML.mls",
    "content": ":NoRecursiveTypes\n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\ndef cons[a]: a -> List[a] -> List[a]\ndef cons head tail = Cons { head; tail }\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\ndef nil: List['a]\nnil = Nil {}\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: forall 'a. List['a] -> 'a\ndef head l = l.Head\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n//│ List['a] -> 'a\n//│   <:  head:\n//│ List['a] -> 'a\n//│     = [Function: head]\n\ndef tail: forall 'a. List['a] -> List['a]\ndef tail l = l.Tail\n//│ tail: List['a] -> List['a]\n//│     = <missing implementation>\n//│ List['a] -> List['a]\n//│   <:  tail:\n//│ List['a] -> List['a]\n//│     = [Function: tail]\n\ndef is_empty: forall 'a. List['a] -> bool\ndef is_empty l = eq l nil\n//│ is_empty: List[?] -> bool\n//│         = <missing implementation>\n//│ anything -> bool\n//│   <:  is_empty:\n//│ List[?] -> bool\n//│         = [Function: is_empty]\n\ndef single: forall 'a. 'a -> List['a]\ndef single x = cons x nil\n//│ single: 'a -> List['a]\n//│       = <missing implementation>\n//│ 'a -> List['a]\n//│   <:  single:\n//│ 'a -> List['a]\n//│       = [Function: single]\n\ndef append: List['a] -> List['a] -> List['a]\nrec def append l1 l2 =\n  if is_empty l1 then l2\n  else cons (head l1) (append (tail l1) l2)\n//│ append: List['a] -> List['a] -> List['a]\n//│       = <missing implementation>\n//│ List['a] -> List['a] -> List['a]\n//│   <:  append:\n//│ List['a] -> List['a] -> List['a]\n//│       = [Function: append]\n\ndef length: forall 'a. List['a] -> int\nrec def length l =\n  if is_empty l then 0\n  else succ (length (tail l))\n//│ length: List[?] -> int\n//│       = <missing implementation>\n//│ List[?] -> int\n//│   <:  length:\n//│ List[?] -> int\n//│       = [Function: length1]\n\ndef id: forall 'a. 'a -> 'a\ndef id x = x\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id:\n//│ 'a -> 'a\n//│   = [Function: id1]\n\ndef inc: int -> int\ninc = succ\n//│ inc: int -> int\n//│    = <missing implementation>\n//│ int -> int\n//│   <:  inc:\n//│ int -> int\n//│    = [Function: succ]\n\ndef choose: forall 'a. 'a -> 'a -> 'a\ndef choose x y = if true then x else y\n//│ choose: 'a -> 'a -> 'a\n//│       = <missing implementation>\n//│ 'a -> 'a -> 'a\n//│   <:  choose:\n//│ 'a -> 'a -> 'a\n//│       = [Function: choose]\n\ndef map: forall 'a 'b. ('a -> 'b) -> List['a] -> List['b]\nrec def map f l =\n  if is_empty l then nil\n  else cons (f (head l)) (map f (tail l))\n//│ map: ('a -> 'b) -> List['a] -> List['b]\n//│    = <missing implementation>\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│   <:  map:\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│    = [Function: map]\n\ndef app: forall 'a 'b. ('a -> 'b) -> 'a -> 'b\ndef app f x = f x\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = <missing implementation>\n//│ ('a -> 'b) -> 'a -> 'b\n//│   <:  app:\n//│ ('a -> 'b) -> 'a -> 'b\n//│    = [Function: app]\n\ndef revapp: forall 'a 'b. 'a -> ('a -> 'b) -> 'b\ndef revapp x f = f x\n//│ revapp: 'a -> ('a -> 'b) -> 'b\n//│       = <missing implementation>\n//│ 'a -> ('a -> 'b) -> 'b\n//│   <:  revapp:\n//│ 'a -> ('a -> 'b) -> 'b\n//│       = [Function: revapp]\n\n\n\n// ============ Sec 2 ============\n\n// FreezeML B1\ndef poly (f: forall 'a. 'a -> 'a) = (f 1, f true)\ndef poly_ f = (f 1, f true)\n//│ poly: (forall 'a. 'a -> 'a) -> (1, true,)\n//│     = [Function: poly]\n//│ poly_: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│      = [Function: poly_]\n\n// FreezeML A10\npoly id\npoly_ id\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// FreezeML A11\npoly (fun x -> x)\npoly_ (fun x -> x)\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// FreezeML D1\napp poly id\napp poly_ id\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// FreezeML D2\nrevapp id poly\nrevapp id poly_\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// FreezeML C9\nmap poly (single id)\nmap poly_ (single id)\n//│ res: List[(1, true,)]\n//│    = Cons { head: [ 1, true ], tail: Nil {} }\n//│ res: List[(1, true,)]\n//│    = Cons { head: [ 1, true ], tail: Nil {} }\n\n// FreezeML C7\nappend (single inc) (single id)\n//│ res: List[int -> int]\n//│    = Cons {\n//│        head: [Function: succ],\n//│        tail: Cons { head: [Function: id1], tail: Nil {} }\n//│      }\n\nlet ids = single id in\n  (map poly ids, append (single inc) ids)\n//│ res: (List[(1, true,)], List[int -> int],)\n//│    = [\n//│        Cons { head: [ 1, true ], tail: Nil {} },\n//│        Cons {\n//│          head: [Function: succ],\n//│          tail: Cons { head: [Function: id1], tail: Nil {} }\n//│        }\n//│      ]\n\n// FreezeML A2\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\nfun (f: forall 'a. 'a -> 'a) -> poly f\nfun f -> poly f\n//│ res: (forall 'a. 'a -> 'a) -> (1, true,)\n//│    = [Function: res]\n//│ res: (forall 'a. 'a -> 'a) -> (1, true,)\n//│    = [Function: res]\n\n// ============ Sec 4 ============\n\n// FreezeML C4\nids = single id\n//│ ids: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ============ Sec 7 ============\n\nxs = cons id ids\n//│ xs: List[forall 'a. 'a -> 'a]\n//│   = Cons {\n//│       head: [Function: id1],\n//│       tail: Cons { head: [Function: id1], tail: Nil {} }\n//│     }\n\nys = tail ids\n//│ ys: List[forall 'a. 'a -> 'a]\n//│   = Nil {}\n\nzs = map id (tail (cons id ids))\n//│ zs: List[forall 'a. 'a -> 'a]\n//│   = Cons { head: [Function: id1], tail: Nil {} }\n\ndef foo: (int -> (forall 'a. 'a -> 'a)) -> int\npoly (fun x -> x)\nfoo (fun y -> fun x -> x)\n//│ foo: (int -> (forall 'a. 'a -> 'a)) -> int\n//│    = <missing implementation>\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ res: int\n//│    = <no result>\n//│      foo is not implemented\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/Jim.mls",
    "content": ":NoRecursiveTypes\n\n\n// TODO also try stuff from his intersection type systems\n\n\n// ============ A Polar Type System (System P) ============\n\n// λf. f (λx. x)\nfun f -> f (fun x -> x)\n//│ res: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│    = [Function: res]\n\n// λy. y y\nfun y -> y y\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// Typeable in P; not in ML nor I2:\n// (λf. f (λx. x)) (λy. y y)\n(fun f -> f (fun x -> x)) (fun y -> y y)\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/Leijen.mls",
    "content": ":NoRecursiveTypes\n:GeneralizeArguments // * Needed in order to quantify non-function arguments to runST\n\n// From HML implementation\n\n// Daan Leijen. 2009. Flexible Types: Robust Type Inference for First-Class Polymorphism. In\n//   Proceedings of the 36th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming\n//   Languages (Savannah, GA, USA) (POPL ’09). Association for Computing Machinery, New York,\n//   NY, USA, 66–77. https://doi.org/10.1145/1480881.1480891 \n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n\nclass ST[S, A]\n  method Inv_S: S -> S\n  method Cov_A: A\n//│ Defined class ST[=S, +A]\n//│ Declared ST.Inv_S: ST['S, ?] -> 'S -> 'S\n//│ Declared ST.Cov_A: ST['S, 'A] -> 'A\n\nclass Ref[S, A]\n  method Inv_S: S -> S\n  method Cov_A: A\n//│ Defined class Ref[=S, +A]\n//│ Declared Ref.Inv_S: Ref['S, ?] -> 'S -> 'S\n//│ Declared Ref.Cov_A: Ref['S, 'A] -> 'A\n\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: List['a] -> 'a\ndef head l = l.Head\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n//│ List['a] -> 'a\n//│   <:  head:\n//│ List['a] -> 'a\n//│     = [Function: head]\n\ndef tail: List['a] -> List['a]\ndef tail l = l.Tail\n//│ tail: List['a] -> List['a]\n//│     = <missing implementation>\n//│ List['a] -> List['a]\n//│   <:  tail:\n//│ List['a] -> List['a]\n//│     = [Function: tail]\n\n// Used to represent `[]` in the papers\ndef nil: List['a]\nnil = Nil {}\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\ndef cons: 'a -> List['a] -> List['a]\ndef cons head tail = Cons { head; tail }\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\ndef is_empty: forall 'a. List['a] -> bool\ndef is_empty l = eq l nil\n//│ is_empty: List[?] -> bool\n//│         = <missing implementation>\n//│ anything -> bool\n//│   <:  is_empty:\n//│ List[?] -> bool\n//│         = [Function: is_empty]\n\ndef single: 'a -> List['a]\ndef single x = cons x nil\n//│ single: 'a -> List['a]\n//│       = <missing implementation>\n//│ 'a -> List['a]\n//│   <:  single:\n//│ 'a -> List['a]\n//│       = [Function: single]\n\ndef append: List['a] -> List['a] -> List['a]\nrec def append l1 l2 =\n  if is_empty l1 then l2\n  else cons (head l1) (append (tail l1) l2)\n//│ append: List['a] -> List['a] -> List['a]\n//│       = <missing implementation>\n//│ List['a] -> (List['a] & 'b) -> (List['a] | 'b)\n//│   <:  append:\n//│ List['a] -> List['a] -> List['a]\n//│       = [Function: append]\n\ndef length: List['a] -> int\nrec def length l =\n  if is_empty l then 0\n  else succ (length (tail l))\n//│ length: List[?] -> int\n//│       = <missing implementation>\n//│ List[?] -> int\n//│   <:  length:\n//│ List[?] -> int\n//│       = [Function: length1]\n\ndef id: 'a -> 'a\ndef id x = x\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id:\n//│ 'a -> 'a\n//│   = [Function: id1]\n\ndef ids: List[forall 'a. 'a -> 'a]\nids = single id\n//│ ids: List[forall 'a. 'a -> 'a]\n//│    = <missing implementation>\n//│ List[forall 'a. 'a -> 'a]\n//│   <:  ids:\n//│ List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\ndef inc: int -> int\ninc = succ\n//│ inc: int -> int\n//│    = <missing implementation>\n//│ int -> int\n//│   <:  inc:\n//│ int -> int\n//│    = [Function: succ]\n\ndef choose: 'a -> 'a -> 'a\ndef choose x y = if true then x else y\n//│ choose: 'a -> 'a -> 'a\n//│       = <missing implementation>\n//│ 'a -> 'a -> 'a\n//│   <:  choose:\n//│ 'a -> 'a -> 'a\n//│       = [Function: choose]\n\ndef auto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\ndef auto x = x x\n//│ auto: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│     = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  auto:\n//│ (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│     = [Function: auto]\n\ndef xauto : forall 'a. (forall 'b. 'b -> 'b) -> 'a -> 'a\ndef xauto x = x x\n//│ xauto: (forall 'b. 'b -> 'b) -> 'a -> 'a\n//│      = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  xauto:\n//│ (forall 'b. 'b -> 'b) -> 'a -> 'a\n//│      = [Function: xauto]\n\ndef takeAuto: ((forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)) -> (forall 'a. 'a -> 'a)\ndef takeAuto auto = auto id\n//│ takeAuto: ((forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)) -> (forall 'a1. 'a1 -> 'a1)\n//│         = <missing implementation>\n//│ ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│   <:  takeAuto:\n//│ ((forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)) -> (forall 'a1. 'a1 -> 'a1)\n//│         = [Function: takeAuto]\n\ndef const: forall 'a 'b. 'a -> 'b -> 'a\ndef const x y = x\n//│ const: 'a -> anything -> 'a\n//│      = <missing implementation>\n//│ 'a -> anything -> 'a\n//│   <:  const:\n//│ 'a -> anything -> 'a\n//│      = [Function: const1]\n\ndef map: ('a -> 'b) -> List['a] -> List['b]\nrec def map f l =\n  if is_empty l then nil\n  else cons (f (head l)) (map f (tail l))\n//│ map: ('a -> 'b) -> List['a] -> List['b]\n//│    = <missing implementation>\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│   <:  map:\n//│ ('a -> 'b) -> List['a] -> List['b]\n//│    = [Function: map]\n\ndef app: ('a -> 'b) -> 'a -> 'b\ndef app f x = f x\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = <missing implementation>\n//│ ('a -> 'b) -> 'a -> 'b\n//│   <:  app:\n//│ ('a -> 'b) -> 'a -> 'b\n//│    = [Function: app]\n\ndef revapp: 'a -> ('a -> 'b) -> 'b\ndef revapp x f = f x\n//│ revapp: 'a -> ('a -> 'b) -> 'b\n//│       = <missing implementation>\n//│ 'a -> ('a -> 'b) -> 'b\n//│   <:  revapp:\n//│ 'a -> ('a -> 'b) -> 'b\n//│       = [Function: revapp]\n\ndef fst: forall 'a 'b. (('a, 'b),) -> 'a\ndef fst ((x, _),) = x\n//│ fst: (('a, anything,),) -> 'a\n//│    = <missing implementation>\n//│ (('a, anything,),) -> 'a\n//│   <:  fst:\n//│ (('a, anything,),) -> 'a\n//│    = [Function: fst]\n\ndef snd: forall 'a 'b. (('a, 'b),) -> 'b\ndef snd ((_, x),) = x\n//│ snd: ((anything, 'b,),) -> 'b\n//│    = <missing implementation>\n//│ ((anything, 'a,),) -> 'a\n//│   <:  snd:\n//│ ((anything, 'b,),) -> 'b\n//│    = [Function: snd]\n\n:ng\ndef runST: forall 'a. (forall 's. ST['s, 'a]) -> 'a\n//│ runST: (forall 's. ST['s, 'a]) -> 'a\n\n:ng\ndef newRef: forall 'a 's. 'a -> ST['s, Ref['s, 'a]]\n//│ newRef: 'a -> ST['s, Ref['s, 'a]]\n\n:ng\ndef returnST: forall 'a 's. 'a -> ST['s, 'a]\n//│ returnST: 'a -> ST['s, 'a]\n\n\n\n// ============ Hindley Milner ============\n\n// -- standard Hindley-Milner tests\n\n// [(\"\\\\x -> x\", ok \"forall a. a -> a\")\nfun x -> x\n//│ res: 'a -> 'a\n//│    = [Function: res]\n\n// ,(\"\\\\f x -> f x\", ok \"forall a b. (a -> b) -> a -> b\")\nfun f -> fun x -> f x\n//│ res: ('a -> 'b) -> 'a -> 'b\n//│    = [Function: res]\n\n// ,(\"inc True\", Wrong)\n:e\ninc true\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.277: \tinc true\n//│ ║         \t^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.277: \tinc true\n//│ ║         \t    ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.146: \tdef inc: int -> int\n//│ ╙──       \t         ^^^\n//│ res: error | int\n//│    = 2\n\n// ,(\"let i = \\\\x -> x in i i\", ok \"forall a. a -> a\")\nlet i = fun x -> x in i i\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\n// ,(\"\\\\i -> i i\", Wrong)              -- infinite type\nfun i -> i i\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// ,(\"\\\\i -> (i 1, i True)\", Wrong)    -- polymorphic use of parameter\nfun i -> (i 1, i true)\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: res]\n\n// ,(\"single id\", ok \"forall (a >= forall b. b -> b). [a]\")\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"choose (\\\\x y -> x) (\\\\x y -> y)\", ok \"forall a. a -> a -> a\")\nchoose (fun x -> fun y -> x) (fun x -> fun y -> y)\n//│ res: 'a -> 'a -> 'a\n//│    = [Function (anonymous)]\n\n// ,(\"choose id\", ok \"forall (a >= forall b. b -> b). a -> a\")\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// ]\n\n// ============ Higher rank & impredicative ============\n\n// -- impredicative application and higher rank arguments are fully supported\n\n// [(\"xauto\",ok \"forall a. (forall a. a -> a) -> a -> a\")     -- just to show the types of xauto and auto\nxauto\n//│ res: (forall 'b. 'b -> 'b) -> 'a -> 'a\n//│    = [Function: xauto]\n\n// ,(\"auto\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\nauto\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│    = [Function: auto]\n\n// ,(\"\\\\(i :: forall a. a -> a) -> i i\", ok \"forall (a >= forall b. b -> b). (forall b. b -> b) -> a\") -- ok \"forall a. (forall a. a -> a) -> a -> a\")\nfun (i: forall 'a. 'a -> 'a) -> i i\nfun i -> i i\n//│ res: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│    = [Function: res]\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// ,(\"auto id\", ok \"forall a. a -> a\")\nauto id\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"apply auto id\", ok \"forall a. a -> a\")\napp auto id\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"(single :: (forall a. a -> a) -> [forall a. a->a]) id\", ok \"[forall a. a-> a]\")\n(single : (forall 'a. 'a -> 'a) -> List[forall 'a. 'a -> 'a]) id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"runST (returnST 1)\", ok \"Int\")\n:ng\nrunST (returnST 1)\n//│ res: 1\n\n// ,(\"runST (newRef 1)\", Wrong)\n:ng\nrunST (newRef 1)\n//│ res: Ref[in ??s, 1]\n\n// ,(\"apply runST (returnST 1)\", ok \"Int\")\n:ng\napp runST (returnST 1)\n//│ res: 1\n\n// ,(\"map xauto ids\", ok \"forall a. [a -> a]\")\nmap xauto ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"map xauto (map xauto ids)\", Wrong)\n// * This term is fine, though they mark it as wrong in their system (because they don't have distrib. nor subtyping)\nmap xauto (map xauto ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"map auto ids\", ok \"[forall a. a -> a]\")\nmap auto ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"map auto (map auto ids)\", ok \"[forall a. a -> a]\")\nmap auto (map auto ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"head ids\", ok \"forall a. a -> a\")\nhead ids\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"tail ids\", ok \"[forall a. a -> a]\")\ntail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// ,(\"apply tail ids\", ok \"[forall a. a -> a]\")\napp tail ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// ,(\"map head (single ids)\", ok \"[forall a. a -> a]\")\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"apply (map head) (single ids)\", ok \"[forall a. a -> a]\")\napp (map head) (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// -- check infinite poly types\n\n:e\n// ,(\"(undefined :: some a. [a -> a] -> Int) (undefined :: some c. [(forall d. d -> c) -> c])\", Wrong)\n:ng\n(error : List['a -> 'a] -> int) (error : List[(forall 'd. 'd -> 'c) -> 'c])\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: ? -> 'a\n//│ ╙──\n//│ res: int\n\n// ,(\"(undefined :: some a. [a -> a] -> Int) (undefined :: [(forall d. d -> d) -> (Int -> Int)])\", Wrong)\n:e\n:ng\n(error : List['a -> 'a] -> int) (error : List[(forall 'd. 'd -> 'd) -> (int -> int)])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.435: \t(error : List['a -> 'a] -> int) (error : List[(forall 'd. 'd -> 'd) -> (int -> int)])\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'d` is not an instance of type `int`\n//│ ║  l.435: \t(error : List['a -> 'a] -> int) (error : List[(forall 'd. 'd -> 'd) -> (int -> int)])\n//│ ║         \t                                                          ^^\n//│ ╟── but it flows into quantified type variable with expected type `int`\n//│ ║  l.435: \t(error : List['a -> 'a] -> int) (error : List[(forall 'd. 'd -> 'd) -> (int -> int)])\n//│ ║         \t                                                      ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.435: \t(error : List['a -> 'a] -> int) (error : List[(forall 'd. 'd -> 'd) -> (int -> int)])\n//│ ╙──       \t                                                                        ^^^\n//│ res: error | int\n\n// ,(\"(undefined :: some a. [a -> (forall b. b -> b)] -> Int) (undefined :: some c. [(forall d. d -> d) -> c])\", ok \"Int\")\n:ng\n(error : List['a -> (forall 'b. 'b -> 'b)] -> int) (error : List[(forall 'd. 'd -> 'd) -> 'c])\n//│ res: int\n\n// -- these fail horribly in ghc: (choose auto id) is rejected while ((choose auto) id) is accepted -- so much for parenthesis :-)\n\n// ,(\"choose id auto\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('a1 -> 'a1 | 'a0)\n//│    = [Function: id1]\n\n// ,(\"choose auto id\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\nchoose auto id\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('a1 -> 'a1 | 'a0)\n//│    = [Function: auto]\n\n// ,(\"choose xauto xauto\", ok \"forall a. (forall b. b -> b) -> a -> a\")\nchoose xauto xauto\n//│ res: (forall 'b. 'b -> 'b) -> 'a -> 'a\n//│    = [Function: xauto]\n\n// ,(\"choose id xauto\", Wrong)\nchoose id xauto\n//│ res: (forall 'b. 'b -> 'b & 'a) -> ('a0 -> 'a0 | 'a)\n//│    = [Function: id1]\n\n// ,(\"choose xauto id\", Wrong)\nchoose xauto id\n//│ res: (forall 'b. 'b -> 'b & 'a) -> ('a0 -> 'a0 | 'a)\n//│    = [Function: xauto]\n\n// -- these fail too in ghc: (choose ids []) is accepted while (choose [] ids) is rejected\n\n// ,(\"choose [] ids\", ok \"[forall a. a -> a]\")\nchoose nil ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Nil {}\n\n// ,(\"choose ids []\", ok \"[forall a. a -> a]\")\nchoose ids nil\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// -- check escaping skolems\n\n// ,(\"\\\\x -> auto x\", Wrong)                                                                             -- escape in match\nfun x -> auto x\n//│ res: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│    = [Function: res]\n\n// ,(\"let poly (xs :: [forall a. a -> a]) = 1 in (\\\\x -> poly x)\", Wrong)                              -- escape in apply\nlet poly (xs: List[forall 'a. 'a -> 'a]) = 1 in fun x -> poly x\n//│ res: List[forall 'a. 'a -> 'a] -> 1\n//│    = [Function (anonymous)]\n\n// ,(\"\\\\x -> (x :: [forall a. a -> a])\", Wrong)                                                          -- escape in apply\nfun x -> (x : List[forall 'a. 'a -> 'a])\n//│ res: List[forall 'a. 'a -> 'a] -> List[forall 'a. 'a -> 'a]\n//│    = [Function: res]\n\n// ,(\"\\\\x -> let polys (xs :: [forall a . a -> a]) = 1; f y = x in polys [f::some a. forall b. b -> a]\",Wrong)  -- escape in unify (with rigid annotations, otherwise we get a skolem mismatch)\nfun x -> let polys (xs: List[forall 'a. 'a -> 'a]) = 1 in let f y = x in polys (single (f : forall 'b. 'b -> 'a))\n//│ res: ??a -> 1\n//│    = [Function: res]\n\n// ,(\"ids :: forall b. [forall a. a -> b]\", Wrong)                                                       -- unify different skolems\n:e\nids : forall 'b. List[forall 'a. 'a -> 'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.518: \tids : forall 'b. List[forall 'a. 'a -> 'b]\n//│ ║         \t^^^\n//│ ╟── type `'a` does not match type `'b`\n//│ ║  l.518: \tids : forall 'b. List[forall 'a. 'a -> 'b]\n//│ ║         \t                                 ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.518: \tids : forall 'b. List[forall 'a. 'a -> 'b]\n//│ ║         \t                                       ^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.518: \tids : forall 'b. List[forall 'a. 'a -> 'b]\n//│ ╙──       \t                             ^^\n//│ res: List[anything -> nothing]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// -- co/contra variance\n\n// ,(\"let g (x::(forall a. a -> a) -> Int) = x id; f (x :: Int -> Int) = x 1 in g f\", Wrong)                                      -- HMF is invariant\nlet g (x: (forall 'a. 'a -> 'a) -> int) = x id in let f (x: int -> int) = x 1 in g f\n//│ res: int\n//│    = 1\n\n// ,(\"let g (x::(forall a. a -> a) -> Int) = x id; f (x :: Int -> Int) = x 1 in g (\\\\(x :: forall a. a -> a) -> f x)\", ok \"Int\")  -- but we can always use explicit annotations to type such examples\nlet g (x: (forall 'a. 'a -> 'a) -> int) = x id in let f (x: int -> int) = x 1 in g (fun (x: forall 'a. 'a -> 'a) -> f x)\n//│ res: int\n//│    = 1\n\n// -- shared polymorphism\n\n// ,(\"let f (x :: [forall a.a -> a]) = x in let g (x :: [Int -> Int]) = x in let ids = [id] in (f ids, g ids)\", ok \"([forall a. a -> a],[Int -> Int])\")\nlet f (x: List[forall 'a. 'a -> 'a]) = x in let g (x: List[int -> int]) = x in let ids = single id in (f ids, g ids)\n//│ res: (List[forall 'a. 'a -> 'a], List[int -> int],)\n//│    = [\n//│        Cons { head: [Function: id1], tail: Nil {} },\n//│        Cons { head: [Function: id1], tail: Nil {} }\n//│      ]\n\n// ]\n\n// ============ Encoding of existentials ============\n\n// -- simulating existential types\n\n// (\"let pack x f    = \\\\(open :: some b. forall a. (a,a -> Int) -> b) -> open (x,f); \\\n//     \\unpack ex f = ex f; \\\n//     \\existsB = pack True (\\\\b -> if b then 1 else 0); \\\n//     \\existsI = pack 1 id; \\\n//     \\exs     = [existsB,existsI]\\   \n// \\in unpack (head exs) (\\\\ex -> (snd ex) (fst ex))\"     \n// ,ok \"Int\")\nlet pack x f = fun (open: forall 'a. (('a, 'a -> int),) -> 'b) -> open ((x, f)) in\n  let unpack ex f = ex f in\n  let existsB = pack true (fun b -> if b then 1 else 0) in\n  let existsI = pack 1 id in\n  let exs = cons existsB (cons existsI nil) in\n    unpack (head exs) (fun ex -> (snd ex) (fst ex))\n//│ res: int\n//│    = 1\n\n// ============ Rigid annotations ============\n\n// -- test 'rigid' annotations, i.e. annotations are taken literally and do not instantiate or generalize\n\n// [(\"single (id :: forall a. a -> a)\", ok \"forall (a >= forall b. b -> b). [a]\")\nsingle (id : forall 'a. 'a -> 'a)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"(id :: forall a. a -> a) 1\", ok \"Int\")   -- not all annotations are rigid\n(id : forall 'a. 'a -> 'a) 1\n//│ res: 1\n//│    = 1\n\n// ,(\"(id :: some a. a -> a) 1\", ok \"Int\")\n(id : 'a -> 'a) 1\n//│ res: 1\n//│    = 1\n\n// ,(\"\\\\x -> ((\\\\y -> x) :: some a. forall b. b -> a)\", ok \"forall a. forall (b >= forall c. c -> a). a -> b\")\nfun x -> (fun y -> x) : forall 'b. 'b -> 'a\n//│ res: 'a -> anything -> 'a\n//│    = [Function: res]\n\n// ,(\"\\\\(f :: forall a. a -> a) -> ((f f) :: forall a. a -> a)\", ok \"forall (a >= forall b. b -> b). (forall b. b -> b) -> a\")\nfun (f: forall 'a. 'a -> 'a) -> ((f f) : forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│    = [Function: res]\n\n// ,(\"revapp (id :: forall a. a -> a) auto\", ok \"forall a. a -> a\")\nrevapp (id : forall 'a. 'a -> 'a) auto\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"choose inc id\", ok \"Int -> Int\")\nchoose inc id\n//│ res: int -> int\n//│    = [Function: succ]\n\n// ,(\"choose inc (id :: forall a. a -> a)\", if SupportRigidAnnotations `elem` features then Wrong else ok \"Int -> Int\")\nchoose inc (id : forall 'a. 'a -> 'a)\n//│ res: int -> int\n//│    = [Function: succ]\n\n// ,(\"choose inc (id :: some a. a -> a)\", ok \"Int -> Int\")\nchoose inc (id : 'a -> 'a)\n//│ res: int -> int\n//│    = [Function: succ]\n\n// ]\n\n// ============ N-ary applications, order of arguments ============\n\n// -- tests n-ary applications\n\n// [(\"revapp id auto\", ok \"forall a. a -> a\")     \nrevapp id auto\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"let f = revapp id in f auto\", ok \"forall a. a -> a\")   \nlet f = revapp id in f auto\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"let f = revapp (id :: forall a. a -> a) in f auto\", ok \"forall a. a -> a\") \nlet f = revapp (id : forall 'a. 'a -> 'a) in f auto\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// -- check functions that return polymorphic values\n\n// ,(\"head ids 1\", ok \"Int\")\nhead ids 1\n//│ res: 1\n//│    = 1\n\n// ,(\"auto id 1\", ok \"Int\")\nauto id 1\n//│ res: 1\n//│    = 1\n\n// ]\n\n// ============ Flexible bounds ============\n\n// -- test sharing of polymorphic types\n\n// [(\"let ids = single id in (map auto ids, append (single inc) ids)\", ok \"([forall a. a -> a],[Int -> Int])\")\nlet ids = single id in (map auto ids, append (single inc) ids)\n//│ res: (List[forall 'a. 'a -> 'a], List[int -> int],)\n//│    = [\n//│        Cons { head: [Function: id1], tail: Nil {} },\n//│        Cons {\n//│          head: [Function: succ],\n//│          tail: Cons { head: [Function: id1], tail: Nil {} }\n//│        }\n//│      ]\n\n// ,(\"single id\",ok \"forall (a >= forall b. b -> b). [a]\")\nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"choose id\",ok \"forall (a >= forall b. b -> b). a -> a\")\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// ,(\"choose id inc\", ok \"Int -> Int\")\nchoose id inc\n//│ res: int -> int\n//│    = [Function: id1]\n\n// ,(\"choose id auto\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'a0) -> ('a1 -> 'a1 | 'a0)\n//│    = [Function: id1]\n\n// ,(\"\\\\x y -> x\", ok \"forall a. forall (b >= forall c. c -> a). a -> b\")\nfun x -> fun y -> x\n//│ res: 'a -> anything -> 'a\n//│    = [Function: res]\n\n// ]\n\n// ============ Experimental \"rigid\" keyword ============\n\n// -- Experimental: the \"rigid\" keyword prevents instantiation or generalization of the principal type of an expression\n// -- this is perhaps more convenient than writing an annotation (but not more expressive)\n\n// (\"single (rigid id)\", ok \"[forall a. a -> a]\")  \nsingle id\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"let pauto (f :: forall a. a -> a) = rigid f in map pauto ids\", ok \"[forall a. a -> a]\")\nlet pauto (f: forall 'a. 'a -> 'a) = f in map pauto ids\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"let pauto (f :: forall a. a -> a) = rigid f in map pauto (map pauto ids)\", ok \"[forall a. a -> a]\")\nlet pauto (f: forall 'a. 'a -> 'a) = f in map pauto (map pauto ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"\\\\x -> rigid (\\\\y -> x)\", ok \"forall a. a -> (forall b. b -> a)\")\nf = fun x -> fun y -> x\n//│ f: 'a -> anything -> 'a\n//│  = [Function: f]\n\n// ,(\"\\\\x -> rigid (\\\\y -> const x y)\", ok \"forall a. a -> (forall b. b -> a)\")\nfun x -> fun y -> const x y\n//│ res: 'a -> anything -> 'a\n//│    = [Function: res]\n\n// ,(\"let c x = rigid (\\\\y -> x) in \\\\x y -> c x y\", ok \"forall a b. a -> b -> a\")\nlet c x = fun y -> x in fun x -> fun y -> c x y\n//│ res: 'a -> anything -> 'a\n//│    = [Function (anonymous)]\n\n// ,(\"choose plus (\\\\x -> id)\", ok \"Int -> Int -> Int\")\nchoose add (fun x -> id)\n//│ res: int -> int -> int\n//│    = [Function: add]\n\n// ,(\"choose plus (\\\\x -> rigid id)\", Wrong)      \nchoose add (fun x -> id)\n//│ res: int -> int -> int\n//│    = [Function: add]\n\n// ,(\"choose inc (rigid id)\", Wrong)  \nchoose inc id\n//│ res: int -> int\n//│    = [Function: succ]\n\n// ,(\"choose id\", ok \"forall a. (a -> a) -> (a -> a)\")\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// ,(\"choose (rigid id)\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\nchoose id\n//│ res: 'a -> (forall 'a0. 'a0 -> 'a0 | 'a)\n//│    = [Function (anonymous)]\n\n// ,(\"revapp (rigid id) auto\", ok \"forall a. a -> a\")\nrevapp id auto\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// -- manipulate instantiation of each quantifier:\n\n// ,(\"[const]\", ok \"forall a b. [a -> b -> a]\")\nsingle const\n//│ res: List[forall 'a. 'a -> anything -> 'a]\n//│    = Cons { head: [Function: const1], tail: Nil {} }\n\n// ,(\"[rigid const]\", ok \"[forall a b. a -> b -> a]\")    \nsingle const\n//│ res: List[forall 'a. 'a -> anything -> 'a]\n//│    = Cons { head: [Function: const1], tail: Nil {} }\n\n// ,(\"[const :: some a. forall b. a -> b -> a]\", ok \"forall a. [forall b. a -> b -> a]\")\nsingle (const : forall 'b. 'a -> 'b -> 'a)\n//│ res: List[forall 'a. 'a -> anything -> 'a]\n//│    = Cons { head: [Function: const1], tail: Nil {} }\n\n// ,(\"[const :: some b. forall a. a -> b -> a]\", ok \"forall b. [forall a. a -> b -> a]\")\nsingle (const : forall 'a. 'a -> 'b -> 'a)\n//│ res: List[forall 'a. 'a -> anything -> 'a]\n//│    = Cons { head: [Function: const1], tail: Nil {} }\n\n// ]\n\n// ============ Type propagation ============\n\n// -- test type propagation  (SupportPropagation `elem` features)\n\n// (\"(\\\\f -> f f) :: (forall a. a -> a) -> (forall a. a -> a)\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\n(fun f -> f f) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│    = [Function: res]\n\n// ,(\"(let x = 1 in (\\\\f -> (f x, f True))) :: (forall a. a -> a) -> (Int,Bool)\", ok \"(forall a. a -> a) -> (Int,Bool)\")\n(let x = 1 in fun f -> (f x, f true)) : (forall 'a. 'a -> 'a) -> (int, bool)\n//│ res: (forall 'a. 'a -> 'a) -> (int, bool,)\n//│    = [Function (anonymous)]\n\n// -- test type propagation through applications (SupportAppPropagation `elem` features)\n\n// (\"single id :: [forall a. a -> a]\", ok \"[forall a. a -> a]\")\nsingle id : List[forall 'a. 'a -> 'a]\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = Cons { head: [Function: id1], tail: Nil {} }\n\n// ,(\"returnST 1 :: forall s. ST s Int\", ok \"forall s. ST s Int\")\n// * Note: requires :DistributeForalls OR ascription-LHS generalization\n:ng\nreturnST 1 : forall 's. ST['s, int]\n//│ res: ST['s, int]\n\n// ,(\"auto id :: Int -> Int\", ok \"Int -> Int\")\nauto id : int -> int\n//│ res: int -> int\n//│    = [Function: id1]\n\n// ,(\"head ids 1 :: Int\", ok \"Int\")\nhead ids 1 : int\n//│ res: int\n//│    = 1\n\n// ,(\"head ids :: Int -> Int\", ok \"Int -> Int\")\nhead ids : int -> int\n//│ res: int -> int\n//│    = [Function: id1]\n\n// ============ Type propagation to arguments ============\n\n// -- test type propagation to arguments (SupportPropagateToArg `elem` features)\n\n// (\"takeAuto (\\\\f -> f f)\", ok \"forall a. a -> a\")\ntakeAuto (fun f -> f f)\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"[id]: [ids]\", ok \"[[forall a. a -> a]]\")\ncons (single id) (single ids)\n//│ res: List[List[forall 'a. 'a -> 'a]]\n//│    = Cons {\n//│        head: Cons { head: [Function: id1], tail: Nil {} },\n//│        tail: Cons {\n//│          head: Cons { head: [Function: id1], tail: Nil {} },\n//│          tail: Nil {}\n//│        }\n//│      }\n\n// ,(\"([id] :: [forall a. a -> a]) : [[\\\\x -> x]]\", ok \"[[forall a. a -> a]]\")\ncons (single id : List[forall 'a. 'a -> 'a]) (single (single (fun x -> x)))\n//│ res: List[List[forall 'a. 'a -> 'a]]\n//│    = Cons {\n//│        head: Cons { head: [Function: id1], tail: Nil {} },\n//│        tail: Cons {\n//│          head: Cons { head: [Function (anonymous)], tail: Nil {} },\n//│          tail: Nil {}\n//│        }\n//│      }\n\n// ,(\"apply takeAuto (\\\\f -> f f)\", ok \"forall a. a -> a\")\napp takeAuto (fun f -> f f)\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"revapp (\\\\f -> f f) takeAuto\", ok \"forall a. a -> a\")\nrevapp (fun f -> f f) takeAuto\n//│ res: 'a -> 'a\n//│    = [Function: id1]\n\n// ,(\"apply (\\\\f -> choose auto f) (auto :: (forall a. a -> a) -> (forall a. a -> a))\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\napp (fun f -> choose auto f) (auto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a))\n//│ res: (forall 'a 'a0. 'a -> 'a & 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1)\n//│    = [Function: auto]\n\n// ,(\"revapp (auto :: (forall a. a -> a) -> (forall a. a -> a)) (\\\\f -> choose auto f)\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\nrevapp (auto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)) (fun f -> choose auto f)\n//│ res: (forall 'a 'a0. 'a -> 'a & 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1)\n//│    = [Function: auto]\n\n// ============ Eta expansion of polymorphic types ============\n\n// -- this is *not* supported by HML: inference of polymorphic types for arguments that are just passed around..\n// -- in MLF arguments can have an inferred polymorphic type as long as it is not used (or revealed explicitly)\n\n// [(\"\\\\x -> auto x\", ok \"forall a. (forall a. a -> a) -> a -> a\")\nfun x -> auto x\n//│ res: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│    = [Function: res]\n\n// ,(\"\\\\x -> (auto x, x 1)\", Wrong)\nfun x -> (auto x, x 1)\n//│ res: (forall 'a. 'a -> 'a & 1 -> 'b) -> (forall 'a0. 'a0 -> 'a0, 'b,)\n//│    = [Function: res]\n\n// ,(\"\\\\x -> (auto x, (x :: forall a. a -> a) 1)\", ok \"forall a. (forall a. a -> a) -> (a -> a, Int)\")\nfun x -> (auto x, (x : forall 'a. 'a -> 'a) 1)\n//│ res: (forall 'a 'a0. 'a -> 'a & 'a0 -> 'a0) -> (forall 'a1. 'a1 -> 'a1, 1,)\n//│    = [Function: res]\n\n// ,(\"\\\\x -> (auto x, (x :: Int -> Int) 1)\", Wrong)\nfun x -> (auto x, (x : int -> int) 1)\n//│ res: (forall 'a. 'a -> 'a & int -> int) -> (forall 'a0. 'a0 -> 'a0, int,)\n//│    = [Function: res]\n\n// ]\n\n// (\"(\\\\(x :: forall a. a -> a) -> xauto x) :: (forall a. a -> a) -> (forall a. a -> a)\", ok \"(forall a. a -> a) -> (forall a. a -> a)\")\n\n(fun x -> xauto x) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│    = [Function: res]\n\n// (\"xauto :: (forall a. a -> a) -> (forall a. a -> a)\"\", Wrong)\nxauto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│    = [Function: xauto]\n\n\n\n// ============ ============ ============ Our own tests ============ ============ ============\n\n\n:NoJS\n\n\ndef runST2: forall 'a. (forall 's. (ST['s, 'a], ST['s, 'a])) -> 'a\nrunST2 ((newRef 1, newRef 2))\n//│ runST2: (forall 's. (ST['s, 'a], ST['s, 'a],)) -> 'a\n//│ res: Ref[in ??s, 1 | 2]\n\ndef runST3: forall 'a. (forall 's. ST[('s, 's), 'a]) -> 'a\ndef newRef3: forall 'a 's. 'a -> ST[('s, 's), Ref['s, 'a]]\nrunST3 (newRef3 1)\n//│ runST3: (forall 's. ST[('s, 's,), 'a]) -> 'a\n//│ newRef3: 'a -> ST[('s, 's,), Ref['s, 'a]]\n//│ res: Ref[in ??s, 1]\n\ndef runST4: forall 'a 'b. (forall 's. ST['s, ('a, 'b)]) -> ('a, 'b)\ndef newRef4: forall 'a 's. 'a -> ST['s, (Ref['s, 'a], Ref['s, 'a])]\nrunST4 (newRef4 1)\n//│ runST4: (forall 's. ST['s, ('a, 'b,)]) -> ('a, 'b,)\n//│ newRef4: 'a -> ST['s, (Ref['s, 'a], Ref['s, 'a],)]\n//│ res: (Ref[in ??s, 1], Ref[in ??s, 1],)\n\n\n// * Distributivity demonstration:\n\ndef test1: List['a -> 'a]\ndef test2: List[forall 'a. 'a -> 'a]\n//│ test1: List['a -> 'a]\n//│ test2: List[forall 'a. 'a -> 'a]\n\ntest1 = test2\n//│ List[forall 'a. 'a -> 'a]\n//│   <:  test1:\n//│ List['a -> 'a]\n\n:e\ntest2 = test1\n//│ List['a -> 'a]\n//│   <:  test2:\n//│ List[forall 'a. 'a -> 'a]\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.965: \ttest2 = test1\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.955: \tdef test2: List[forall 'a. 'a -> 'a]\n//│ ║         \t                           ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.955: \tdef test2: List[forall 'a. 'a -> 'a]\n//│ ╙──       \t                                 ^^\n\n\n\n// ———————————— Some tests without distribtivity, for reference ————————————\n\n\n// * Here are all the cases that fail without :DistributeForalls\n\n:DontDistributeForalls\n\n\n// ,(\"map xauto ids\", ok \"forall a. [a -> a]\")\n// * Note the less precise type we now infer:\nmap xauto ids\n//│ res: List['a -> 'a]\n\n// ,(\"map xauto (map xauto ids)\", Wrong)\n:e\nmap xauto (map xauto ids)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.996: \tmap xauto (map xauto ids)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.173: \tdef xauto : forall 'a. (forall 'b. 'b -> 'b) -> 'a -> 'a\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.173: \tdef xauto : forall 'a. (forall 'b. 'b -> 'b) -> 'a -> 'a\n//│ ╙──       \t                                         ^^\n//│ res: List['a -> 'a] | error\n\n\n// * This doesn't work (without distrib.) because we don't currently generalize non-functions:\n:e\n(fun x -> xauto x) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.1011: \t(fun x -> xauto x) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ║          \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.1011: \t(fun x -> xauto x) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ║          \t                                                          ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.1011: \t(fun x -> xauto x) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ║          \t                                                                ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.1011: \t(fun x -> xauto x) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ╙──        \t          ^^^^^^^\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n// * But we can trivially fix it by forcing generalization through a polymorphic let binding:\n(fun x -> let poly = xauto x in poly) : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n\n:e\nxauto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.1031: \txauto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ║          \t^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.1031: \txauto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ║          \t                                             ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.1031: \txauto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ║          \t                                                   ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.1031: \txauto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│ ╙──        \t^^^^^\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/MLF.mls",
    "content": ":NoRecursiveTypes\n:NoJS\n\n\n// ------------ Dummy classes to represent the types in the examples ------------\n\nclass List[a]\n  method Get: a\n//│ Defined class List[+a]\n//│ Declared List.Get: List['a] -> 'a\n\nclass ST[S, A]\n  method Inv_S: S -> S\n  method Cov_A: A\n//│ Defined class ST[=S, +A]\n//│ Declared ST.Inv_S: ST['S, ?] -> 'S -> 'S\n//│ Declared ST.Cov_A: ST['S, 'A] -> 'A\n\n\n// ============ Type signatures for functions used in the examples ============\n\ndef choose x y = if true then x else y\n//│ choose: 'a -> 'a -> 'a\n\ndef id x = x\n//│ id: 'a -> 'a\n\ndef auto (x: forall 'a. 'a -> 'a) = x x\n//│ auto: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n\ndef app f x = f x\n//│ app: ('a -> 'b) -> 'a -> 'b\n\ndef inc: int -> int\n//│ inc: int -> int\n\n// Used to represent `::` in the papers\ndef cons: 'a -> List['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n\n// Used to represent `[]` in the papers\ndef nil: List['a]\n//│ nil: List[nothing]\n\ndef single: 'a -> List['a]\n//│ single: 'a -> List['a]\n\ndef head: List['a] -> 'a\n//│ head: List['a] -> 'a\n\ndef tail: List['a] -> List['a]\n//│ tail: List['a] -> List['a]\n\ndef append: List['a] -> List['a] -> List['a]\n//│ append: List['a] -> List['a] -> List['a]\n\ndef runST: (forall 's. ST['s, 'v]) -> 'v\n//│ runST: (forall 's. ST['s, 'v]) -> 'v\n\ndef argST: ST['s, int]\n//│ argST: ST['s, int]\n\n\n// ============ Raising ML to the power of System F (2003) ============\n\n// FreezeML A2\nchoose id\n//│ res: 'a -> ('b -> 'b | 'a)\n\nfun (g: forall 'a. ('a -> 'a) -> ('a -> 'a)) -> fun (x: forall 'a. 'a -> 'a) -> fun a -> g a (x a)\n//│ res: (forall 'a. ('a -> 'a) -> 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0) -> ('a1 -> 'a1 & 'a1) -> 'a1\n\nchoose id succ\n//│ res: int -> int\n\n// FreezeML A7\nchoose id auto\n//│ res: (forall 'a. 'a -> 'a & 'b) -> ('a0 -> 'a0 | 'b)\n\n// Not typeable in MLF, along with anything with it as a subterm\n// i.e. unannotated auto\nomega = fun x -> x x\n//│ omega: ('a -> 'b & 'a) -> 'b\n\nfun (x: forall 'a. 'a) -> x x\n//│ res: nothing -> nothing\n\n// i.e. auto\nomegad = fun (x: forall 'a. 'a -> 'a) -> x x\n//│ omegad: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n\n// FreezeML A5\nid auto\n//│ res: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n\n// ~ auto id (FreezeML F5, PolyML 1.1)\n(fun x -> x id) auto\n//│ res: 'a -> 'a\n\napp auto id\n//│ res: 'a -> 'a\n\n// ------------ Sec 5.2 ------------\n\n// * Mistake in the paper (confirmed by Rémy via email).\n:e\nlet f = choose id in (f auto) (f succ)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.107: \tlet f = choose id in (f auto) (f succ)\n//│ ║         \t                     ^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.28: \tdef auto (x: forall 'a. 'a -> 'a) = x x\n//│ ║        \t                        ^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.28: \tdef auto (x: forall 'a. 'a -> 'a) = x x\n//│ ╙──      \t                    ^^\n//│ res: error | int -> int\n\n// * Reproduced with an unnanotated auto:\n\ndef auto2 x = x x\n//│ auto2: ('a -> 'b & 'a) -> 'b\n\nchoose id auto2\n//│ res: ('a -> 'b & 'a) -> ('b | 'a)\n\n:e // * This is a legit error\nres (choose id succ)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.128: \tres (choose id succ)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int` is not an instance of type `int`\n//│ ║  l.128: \tres (choose id succ)\n//│ ║         \t               ^^^^\n//│ ╟── but it flows into application with expected type `int`\n//│ ║  l.128: \tres (choose id succ)\n//│ ╙──       \t     ^^^^^^^^^^^^^^\n//│ res: error | int | int -> int\n\n// * Didier Le Botlan suggested this fix by email:\n\nlet f = choose id in (f auto, f succ)\n//│ res: (forall 'b 'a. (forall 'a0. 'a0 -> 'a0 & 'b) -> ('a -> 'a | 'b), forall 'b. (int & 'b) -> (int | 'b),)\n\nlet f = choose id in (f auto2, f succ)\n//│ res: (forall 'a 'b 'c. ('a -> 'b & 'a & 'c) -> ('b | 'c), forall 'c. (int & 'c) -> (int | 'c),)\n\n// ------------ Sec 6 ------------\n\n// (λ(y) y I ; y K) (λ(x) x x)\n// \"typable in Fω but not in F [9]\"\n// [9] P. Giannini and S. R. D. Rocca. Characterization of typings in polymorphic type discipline. In Third annual Symposium on Logic in Computer Science, pages 61–70. IEEE, 1988.\n\n// I := λx.x\nI x = x\n//│ I: 'a -> 'a\n\n// K := λx.λy.x\nK x y = x\n//│ K: 'a -> anything -> 'a\n\n(fun y -> let tmp = y I in y K) (fun x -> x x)\n//│ res: anything -> 'a -> anything -> 'a\n\n// * Note: reduces to\nlet tmp = (fun x -> x x) I in (fun x -> x x) K\n//│ res: anything -> 'a -> anything -> 'a\n\n// to\nlet tmp = I I in K K\n//│ res: anything -> 'a -> anything -> 'a\n\n\n// ============ Recasting MLF (2009) ============\n\n// ------------ Sec 1.3 ------------\n\n// ~ FreezeML B1\n(fun f -> (f 42, f \"foo\")) (fun x -> x)\n//│ res: (42, \"foo\",)\n\n(fun f -> (f succ, choose f auto)) (choose id)\n//│ res: (int -> int | 'b, (forall 'a. 'a -> 'a & 'b) -> (int -> int | 'b),)\n\n// ------------ Sec 2.3.1 ------------\n\n// * i.e. id auto (FreezeML A5)\n(fun z -> z) omegad\n(fun z -> z) omega\n//│ res: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│ res: ('a -> 'b & 'a) -> 'b\n\n// * i.e. auto id (FreezeML F5)\n(fun x -> x x) id\n//│ res: 'a -> 'a\n\nfun z -> (z omegad)\nfun z -> (z omega)\n//│ res: ((forall 'a. (forall 'a0. 'a0 -> 'a0) -> 'a -> 'a) -> 'b) -> 'b\n//│ res: ((forall 'a 'b. ('a -> 'b & 'a) -> 'b) -> 'c) -> 'c\n\n(fun y -> fun z -> z y) omegad\n(fun y -> fun z -> z y) omega\n//│ res: ((forall 'a. (forall 'a0. 'a0 -> 'a0) -> 'a -> 'a) -> 'b) -> 'b\n//│ res: ((forall 'a 'b. ('a -> 'b & 'a) -> 'b) -> 'c) -> 'c\n\nfun z -> omegad z\nfun z -> omega z\n//│ res: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│ res: ('a -> 'b & 'a) -> 'b\n\n(fun x -> fun y -> x y) omegad\n(fun x -> fun y -> x y) omega\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a0. 'a0 -> 'a0)\n//│ res: ('a -> 'b & 'a) -> 'b\n\n// ------------ Sec 4.3 ------------\n// affects the order of bindings in the result type in MLF, not very interesting otherwise\n\nfun (x: forall 'a. 'a -> 'b -> 'a) -> x\n//│ res: (forall 'a. 'a -> 'b -> 'a) -> 'a0 -> 'b -> 'a0\n\nfun (x: forall 'b 'a. 'a -> 'b -> 'a) -> x\n//│ res: (forall 'a. 'a -> anything -> 'a) -> (forall 'a. 'a -> anything -> 'a)\n\n// ============ Leijen 2007 ============\n\n// ------------ Sec 2 ------------\n\n// * FreezeML B1\n// Not typeable in MLF\npoly = fun f -> (f 1, f true)\n//│ poly: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n\n// * FreezeML B2\npolyL = fun xs -> poly (head xs)\n//│ polyL: List[1 -> 'a & true -> 'b] -> ('a, 'b,)\n\nlet ids = single id in (polyL ids, append ids (single inc))\n//│ res: ((1, true,), List[int -> int],)\n\n// ------------ Sec 5 ------------\n\n// * FreezeML C5\nids = single id\n//│ ids: List[forall 'a. 'a -> 'a]\n\n// * Let-bound version of FreezeML A3\nlet f = choose nil in f ids\n//│ res: List[forall 'a. 'a -> 'a]\n\n// * FreezeML A3\nchoose nil ids\n//│ res: List[forall 'a. 'a -> 'a]\n\ndef g: (int -> (forall 'a. 'a -> 'a)) -> int\n//│ g: (int -> (forall 'a. 'a -> 'a)) -> int\n\ng (fun x -> id)\n//│ res: int\n\nlet f = fun x -> id in g f\n//│ res: int\n\n// * FreezeML D4\napp runST argST\n//│ res: int\n\n\n// ============ Variations ported from old Supertype prototype tests ============\n\nkiller_app = (fun x -> x id) auto\n//│ killer_app: 'a -> 'a\n\nI x = x\nK x y = x\n//│ I: 'a -> 'a\n//│ K: 'a -> anything -> 'a\n\n// \"\"\" In particular, we conjecture that the term ...\nmonster = (fun y -> (let tmp = y I in y K)) (fun x -> x x)\n// \"\"\" ... that is typable in Fω but not in F [9] is not typable in MLF either.\n//│ monster: anything -> 'a -> anything -> 'a\n\nignore x y = y\n//│ ignore: anything -> 'a -> 'a\n\nmonsterThunk() = (fun y -> (ignore (y I) (y K))) (fun x -> x x)\n//│ monsterThunk: () -> anything -> 'a -> anything -> 'a\n\nmonster2 = (fun y -> (y I, y K)) (fun x -> x x)\n//│ monster2: (forall 'a. 'a -> 'a, forall 'b. anything -> 'b -> anything -> 'b,)\n\nmonster = (fun y -> (let tmp = y I in y K)) (fun x -> x x)\n//│ monster: anything -> 'a -> anything -> 'a\n\nmonsterThunk() = (fun y -> ignore (y I) (y K)) (fun x -> x x)\n//│ monsterThunk: () -> anything -> 'a -> anything -> 'a\n\nmonster2 = (fun y -> (y I, y K)) (fun x -> x x)\n//│ monster2: (forall 'a. 'a -> 'a, forall 'b. anything -> 'b -> anything -> 'b,)\n\nK K\n//│ res: anything -> 'a -> anything -> 'a\n\n\n\n// ============ A new look on MLF (2008 slides) ============\n\n\n// def pack : forall α. forall β. (α, (α -> β)) -> (forall γ. (forall δ. (δ, (δ -> β)) -> γ) -> γ)\n\ntype Pair[A,B] = (A,B)\ndef pack : forall α. forall β. (α, (α -> β)) -> (forall γ. (forall δ. Pair[δ, (δ -> β)] -> γ) -> γ)\n//│ Defined type alias Pair[+A, +B]\n//│ pack: ('α, 'α -> 'β,) -> (forall 'δ. Pair['δ, 'δ -> 'β] -> 'γ) -> 'γ\n\ndef packed_int = pack (1, fun x -> x + 1)\n//│ packed_int: (forall 'δ. Pair['δ, 'δ -> int] -> 'γ) -> 'γ\n\ndef packed_pair = pack (1, fun x -> (x, x ))\n//│ packed_pair: (forall 'δ. Pair['δ, 'δ -> (1, 1,)] -> 'γ) -> 'γ\n\ndef fst((x,y)) = x\ndef snd((x,y)) = y\n//│ fst: (('a, anything,),) -> 'a\n//│ snd: ((anything, 'a,),) -> 'a\n\nv = packed_int (fun p -> (snd p) ( fst p ))\n//│ v: int\n\n\ndef a: ' -> '\n//│ a: 'a -> 'a\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/Misc.mls",
    "content": ":NoRecursiveTypes\n:NoConstrainedTypes\n:DontDistributeForalls\n\n\n\n// * Pfenning 88\n(fun f -> (f 1, f true))(fun x -> x)\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n\n\n// * FML: Simple, partial type-inference for System F based on type-containment\n// * https://dl.acm.org/doi/abs/10.1145/1090189.1086383\n\n// we may exhibit terms than are typable in F but not in the predicative fragment F(≤^F_p)\n// One such term (λz. z y z) (λz. z y z) is due to Pawel Urzyczyn, according to Leivant [Lei91].\npawel y = (fun z -> z y z) (fun z -> z y z)\n//│ pawel: ('a -> 'a -> (forall 'b 'c. ('a -> 'b -> 'c & 'b) -> 'c) -> 'd & 'a) -> 'd\n//│      = [Function: pawel]\n\ndef f = (fun z -> z z : (forall 'X. 'X -> 'X) -> (forall 'X. 'X -> 'X))\n//│ f: ('a -> (forall 'X. 'X -> 'X) -> (forall 'X0. 'X0 -> 'X0) & 'a) -> (forall 'X. 'X -> 'X) -> (forall 'X0. 'X0 -> 'X0)\n//│  = [Function: f]\n\nf ((fun y -> y) : forall 'X. 'X -> 'X)\n//│ res: (forall 'X. 'X -> 'X) -> (forall 'X0. 'X0 -> 'X0)\n//│    = [Function (anonymous)]\n\ndef f = (fun z -> z z); f (fun y -> y)\n//│ f: ('a -> 'b & 'a) -> 'b\n//│  = [Function: f1]\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\n\n\n// * A Dependently Typed Calculus with Polymorphic Subtyping\n// * https://i.cs.hku.hk/~bruno/papers/scp2021.pdf\n\n// callcc’ : ∀a:⋆. ((∀b:⋆. a → b) → a) → a\n// callcc : ∀a:⋆.∀b:⋆. ((a → b) → a) → a\n// callcc = callcc’\n\ndef callcc' : forall 'A. ((forall 'B. 'A -> 'B) -> 'A) -> 'A\n//│ callcc': (('A -> nothing) -> 'A) -> 'A\n//│        = <missing implementation>\n\ndef callcc : forall 'A. forall 'B. (('A -> 'B) -> 'A) -> 'A\n//│ callcc: (('A -> nothing) -> 'A) -> 'A\n//│       = <missing implementation>\n\ndef callcc = callcc'\n//│ (('A -> nothing) -> 'A) -> 'A\n//│   <:  callcc:\n//│ (('A -> nothing) -> 'A) -> 'A\n//│       = <no result>\n//│         callcc' is not implemented\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/PolyML.mls",
    "content": ":NoRecursiveTypes\n\n\n// ============ Sec 1.1 ============\n\n// * i.e. auto\ng = fun (f: forall 'a. 'a -> 'a) -> f f\ng' = fun f -> f f\n//│ g: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│  = [Function: g]\n//│ g': ('a -> 'b & 'a) -> 'b\n//│   = [Function: g$]\n\n// * i.e. auto id (FreezeML F5)\n(fun (f: forall 'a. 'a -> 'a) -> f f) (fun x -> x)\n(fun f -> f f) (fun x -> x)\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\n// * i.e. (fun auto -> auto id) auto\n(fun g -> g (fun x -> x)) (fun f -> f f)\n(fun g -> g (fun x -> x)) (fun (f: forall 'a. 'a -> 'a) -> f f)\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\n// ============ Sec 1.2 ============\n\nfun f -> f (g f)\nfun f -> f (g' f)\n//│ res: (forall 'a. 'a -> 'a & (forall 'a0. 'a0 -> 'a0) -> 'b) -> 'b\n//│    = [Function: res]\n//│ res: ('a -> 'b & 'b -> 'c & 'a) -> 'c\n//│    = [Function: res]\n\n// ============ Sec 4.1 ============\n\nlet f = fun x -> x in \n  let g = (fun x -> x) f in\n    g g\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\n\n:NoJS\n\n\n// ============ Sec 4.2 ============\n// * Using FCP to solve method typing issues,\n// * which is overkill since it can be solved with subtyping and two levels of polymorphism...\n\n// ------------ Dummy classes to represent the types in the examples ------------\n\nclass List[a]\n  method Get: a\n//│ Defined class List[+a]\n//│ Declared List.Get: List['a] -> 'a\n\n// Used to represent `::` in the papers\ndef cons[a]: a -> List[a] -> List[a]\n//│ cons: 'a -> List['a] -> List['a]\n\n// Used to represent `[]` in the papers\ndef nil: List['a]\n//│ nil: List[nothing]\n\ndef match_list: forall 'a 'b. List['a] -> 'b -> ('a -> List['a] -> 'b) -> 'b\n//│ match_list: List['a] -> 'b -> ('a -> List['a] -> 'b) -> 'b\n\n// ------------ Type signatures for functions used in the examples ------------\n\ndef mem[a]: a -> List[a] -> bool\n//│ mem: anything -> List[?] -> bool\n\nrec def mem x l = match_list l false (fun head -> fun tail -> if eq head x then true else mem x tail)\n//│ anything -> List[?] -> Bool\n//│   <:  mem:\n//│ anything -> List[?] -> bool\n\n\n\n// def fold_left[a, b]: (a -> b -> a) -> a -> List[b] -> a\ndef fold_left: forall 'a 'b. ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n//│ fold_left: ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n\nrec def fl f x l = match_list l x (fun head -> fun tail -> fl f (f x head) tail)\n//│ fl: ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n\nrec def fl2 f x l = match_list l x (fun head -> fun tail -> fold_left f (f x head) tail)\n//│ fl2: ('a -> 'b -> ('a & 'a0)) -> ('a & 'a0) -> List['b] -> 'a0\n\ndef fold_left = fl\n//│ ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n//│   <:  fold_left:\n//│ ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n\ndef fold_left = fl2\n//│ ('a -> 'b -> ('a & 'a0)) -> ('a & 'a0) -> List['b] -> 'a0\n//│   <:  fold_left:\n//│ ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n\nrec def fold_left f x l = match_list l x (fun head -> fun tail -> fold_left f (f x head) tail)\n//│ ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n//│   <:  fold_left:\n//│ ('a -> 'b -> 'a) -> 'a -> List['b] -> 'a\n\n\n// ------------ polymorphic methods ------------\n\nclass Collection[a]: { l: List[a] }\n  method Mem x = mem x this.l\n  method Fold f x = fold_left f x this.l\n//│ Defined class Collection[+a]\n//│ Defined Collection.Mem: Collection[?] -> anything -> bool\n//│ Defined Collection.Fold: Collection['a] -> ('a0 -> 'a -> 'a0) -> 'a0 -> 'a0\n\ndef coll_mem c x = c.Mem x\n//│ coll_mem: Collection[?] -> anything -> bool\n\n// * Typo in the paper? it was `fun x -> fun y -> ...`\ndef simple_and_double c =\n  let l1 = c.Fold (fun y -> fun x -> cons x y) nil in\n  let l2 = c.Fold (fun y -> fun x -> cons ((x, x),) y) nil in\n  (l1, l2)\n//│ simple_and_double: Collection['a] -> (List['a], List[('a, 'a,)],)\n\nsimple_and_double (Collection{l = cons 1 nil})\n//│ res: (List[1], List[(1, 1,)],)\n\n// ------------ subtyping & methods ------------\n\nclass Float\nclass Color\nclass Point: { x: Float; y: Float }\nclass ColorPoint: Point & { c: Color }\nclass Circle: { x: Float; y: Float; r: Float }\n  method Distance: Point -> Float\n//│ Defined class Float\n//│ Defined class Color\n//│ Defined class Point\n//│ Defined class ColorPoint\n//│ Defined class Circle\n//│ Declared Circle.Distance: Circle -> Point -> Float\n\nc = error : Circle\ncp = error : ColorPoint\nc.Distance cp\n//│ c: Circle\n//│ cp: ColorPoint\n//│ res: Float\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/QML.mls",
    "content": ":NoRecursiveTypes\n:DontDistributeForalls\n// :GeneralizeArguments\n\n\n// =============== Sec 2 ===============\nlet id x = x in id\n(id 3, id false)\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n//│ res: (3, false,)\n//│    = [ 3, false ]\n\nlet poly f = (f 1, f true) in poly\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function (anonymous)]\nlet poly f = let y = f in (y 1, y true) in poly\n//│ res: (1 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function (anonymous)]\n\n// Altered from\n// let poly f = let y = f {forall 'a. 'a -> 'a} in (y 1, y true)\ndef poly = fun (f : (forall 'a. 'a -> 'a)) -> (f 1, f true)\n//│ poly: (forall 'a. 'a -> 'a) -> (1, true,)\n//│     = [Function: poly]\n\ndef app : ('a -> 'b) -> 'a -> 'b\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = <missing implementation>\n\ndef revapp : 'a -> ('a -> 'b) -> 'b\n//│ revapp: 'a -> ('a -> 'b) -> 'b\n//│       = <missing implementation>\n\napp poly (fun x -> x)\n//│ res: (1, true,)\n//│    = <no result>\n//│      app is not implemented\n\nrevapp (fun x -> x) poly\n//│ res: (1, true,)\n//│    = <no result>\n//│      revapp is not implemented\n\nclass List[A]\n  method Get: A\n//│ Defined class List[+A]\n//│ Declared List.Get: List['A] -> 'A\n\ndef single : 'a -> List['a]\n//│ single: 'a -> List['a]\n//│       = <missing implementation>\n\ndef ids = single (fun x -> x)\n//│ ids: List[forall 'a. 'a -> 'a]\n//│    = <no result>\n//│      single is not implemented\n\nsingle ids\n//│ res: List[List[forall 'a. 'a -> 'a]]\n//│    = <no result>\n//│      single is not implemented\n\ndef map: ('a -> 'b) -> List['a] -> List['b]\ndef head: List['a] -> 'a\n//│ map: ('a -> 'b) -> List['a] -> List['b]\n//│    = <missing implementation>\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n\nmap head (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = <no result>\n//│      map is not implemented\napp (map head) (single ids)\n//│ res: List[forall 'a. 'a -> 'a]\n//│    = <no result>\n//│      app is not implemented\n\ndef fst: forall 'a 'b. (('a, 'b),) -> 'a\ndef fst ((x, _),) = x\ndef snd: forall 'a 'b. (('a, 'b),) -> 'b\ndef snd ((_, x),) = x\n//│ fst: (('a, anything,),) -> 'a\n//│    = <missing implementation>\n//│ (('a, anything,),) -> 'a\n//│   <:  fst:\n//│ (('a, anything,),) -> 'a\n//│    = [Function: fst]\n//│ snd: ((anything, 'b,),) -> 'b\n//│    = <missing implementation>\n//│ ((anything, 'a,),) -> 'a\n//│   <:  snd:\n//│ ((anything, 'b,),) -> 'b\n//│    = [Function: snd]\n\n// def pack : \ndef pack t = fun f -> f t\n//│ pack: 'a -> (forall 'b. ('a -> 'b) -> 'b)\n//│     = [Function: pack]\n\ndef open p t = p t\n//│ open: ('a -> 'b) -> 'a -> 'b\n//│     = [Function: open]\n\n// Altered from\n// let f = {exists 'a. 'a * ('a -> 'a) * ('a -> int)} (0, (fun x -> x + 1) , (fun x -> x));\n// open {exists 'a. a * ('a -> 'a) * ('a -> int)} g = f in (snd (snd g)) (fst g);\nlet f = pack ((0, (fun x -> x + 1, fun x -> x),),) in\n  open f (fun x -> (snd (snd x)) (fst x))\n//│ res: 0\n//│    = 0\n\n\n// =============== Sec 3 ===============\n\ndef run : (forall 'g. 'g -> 'a) -> 'a\n//│ run: (anything -> 'a) -> 'a\n//│    = <missing implementation>\n\ndef e : 'g -> int\n//│ e: anything -> int\n//│  = <missing implementation>\n\n// * Notice the effect of distributivity\n(fun (f : (forall 'g. int -> 'g)) -> f 1)\n//│ res: (int -> nothing) -> nothing\n//│    = [Function: res]\n\nrun e\n//│ res: int\n//│    = <no result>\n//│      run is not implemented\n\nfun (x : (forall 'a. 'a -> 'a)) -> x\n//│ res: (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a)\n//│    = [Function: res]\n\n\nlet abstype = pack ((id, id),) in\n  let module = pack ((id, app),) in\n  open abstype (fun x -> (snd x) (fst x 1))\n//│ res: 1\n//│    = <no result>\n//│      app is not implemented\n\nlet abstype = pack ((id, id),) in\n  let module = pack ((id, app),) in\n  open module (fun x -> (snd x) (fun a -> ((a, a),)) (fst x 1))\n//│ res: ((1, 1,),)\n//│    = <no result>\n//│      app is not implemented\n\n:escape\ndef Math: nothing\n//│ Math: nothing\n//│     = <missing implementation>\n\ndef div: int -> int -> int\ndef div a b = Math.trunc(a/b)\n//│ div: int -> int -> int\n//│    = <missing implementation>\n//│ number -> number -> nothing\n//│   <:  div:\n//│ int -> int -> int\n//│    = [Function: div1]\n\ndef mod = let rec mod a b = if a < b then a else mod (a - b) b in mod\n//│ mod: int -> int -> int\n//│    = [Function: mod]\n\n\n// ********** SMALL ARRAY EXAMPLE **********\n\n// exists r. forall b. Sig[a, r, b]\n// (forall r. (forall b. Sig[a, r, b]) -> y) -> y\n\n:DistributeForalls\n// :GeneralizeArguments\n\ntype ExSmall = (forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> 'y\n//│ Defined type alias ExSmall\n\ndef sbase : ExSmall\ndef sbase f = f (fun a -> a, fun r -> fun (i : int) -> r)\n//│ sbase: ExSmall\n//│      = <missing implementation>\n//│ ((forall 'a. 'a -> 'a, forall 'b. 'b -> int -> 'b,) -> 'c) -> 'c\n//│   <:  sbase:\n//│ ExSmall\n//│      = [Function: sbase]\n\ndef sstep : ExSmall -> ExSmall\n//│ sstep: ExSmall -> ExSmall\n//│      = <missing implementation>\n\n:e // * Since \"sound extrusion\"\ndef sstep = fun xx -> xx (fun (xinit, xsub) -> \n  let init a = (xinit a, xinit a) in\n  let sub ((r1, r2)) i =\n    if mod i 2 == 0\n    then xsub r1 (div i 2)\n    else xsub r2 (div i 2) in\n  fun f -> f (init, sub))\n//│ ((forall 'a 'b 'c 'd 'e. ('a -> 'b, 'c -> int -> 'd,) -> (('a -> ('b, 'b,), (('c, 'c,),) -> int -> 'd,) -> 'e) -> 'e) -> 'f) -> 'f\n//│   <:  sstep:\n//│ ExSmall -> ExSmall\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.198: \tdef sstep = fun xx -> xx (fun (xinit, xsub) -> \n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.199: \t  let init a = (xinit a, xinit a) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.200: \t  let sub ((r1, r2)) i =\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.201: \t    if mod i 2 == 0\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.202: \t    then xsub r1 (div i 2)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.203: \t    else xsub r2 (div i 2) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.204: \t  fun f -> f (init, sub))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.181: \ttype ExSmall = (forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> 'y\n//│ ║         \t                                  ^^\n//│ ╟── back into type variable `'r`\n//│ ║  l.181: \ttype ExSmall = (forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> 'y\n//│ ║         \t                                      ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.198: \tdef sstep = fun xx -> xx (fun (xinit, xsub) -> \n//│ ║         \t                      ^^\n//│ ╟── • this function:\n//│ ║  l.198: \tdef sstep = fun xx -> xx (fun (xinit, xsub) -> \n//│ ║         \t                          ^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.199: \t  let init a = (xinit a, xinit a) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.200: \t  let sub ((r1, r2)) i =\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.201: \t    if mod i 2 == 0\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.202: \t    then xsub r1 (div i 2)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.203: \t    else xsub r2 (div i 2) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.204: \t  fun f -> f (init, sub))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.202: \t    then xsub r1 (div i 2)\n//│ ╙──       \t              ^^\n//│      = [Function: sstep]\n\n// * Alternative, with an annotation on `f`:\ndef sstep = fun xx -> xx (fun (xinit, xsub) -> \n  let init a = (xinit a, xinit a) in\n  let sub ((r1, r2)) i =\n    if mod i 2 == 0\n    then xsub r1 (div i 2)\n    else xsub r2 (div i 2) in\n  fun (f : forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> f (init, sub))\n//│ ((forall 'a 'b 'c. ('a -> 'b, 'b -> int -> 'a,) -> (forall 'r. ('a -> 'r, 'r -> int -> 'a,) -> 'c) -> 'c) -> 'd) -> 'd\n//│   <:  sstep:\n//│ ExSmall -> ExSmall\n//│      = [Function: sstep1]\n\nlet mkSArray n = if n == 0 then sbase else sstep (sstep sbase) in\n  mkSArray 1 (fun (xinit, xsub) -> xsub (xinit 2) 2)\n//│ res: 2\n//│    = 2\n\ndef mkSArray : int -> ExSmall\nrec def mkSArray n = if n == 0 then sbase else sstep (mkSArray (n - 1))\n//│ mkSArray: int -> ExSmall\n//│         = <missing implementation>\n//│ int -> ExSmall\n//│   <:  mkSArray:\n//│ int -> ExSmall\n//│         = [Function: mkSArray]\n\nmkSArray 2 (fun (xinit, xsub) -> xinit 2)\n//│ res: ??r\n//│    = [ [ 2, 2 ], [ 2, 2 ] ]\n\nma2 = mkSArray 2\n//│ ma2: ExSmall\n//│    = [Function (anonymous)]\n\na2 = ma2 (fun (xinit, xsub) -> xsub (xinit true) 0)\n//│ a2: true\n//│   = true\n\nnot a2\n//│ res: bool\n//│    = false\n\na2 = ma2 (fun (xinit, xsub) -> xinit true)\n//│ a2: ??r\n//│   = [ [ true, true ], [ true, true ] ]\n\n:e // This is expected – xinit returns a value of locally-quantified type 'r\na2[0]\n//│ ╔══[ERROR] Type error in array access\n//│ ║  l.301: \ta2[0]\n//│ ║         \t^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.181: \ttype ExSmall = (forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> 'y\n//│ ║         \t                                  ^^\n//│ ╟── into array access of type `Array[?a]`\n//│ ║  l.301: \ta2[0]\n//│ ║         \t^^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.296: \ta2 = ma2 (fun (xinit, xsub) -> xinit true)\n//│ ║         \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.284: \tma2 = mkSArray 2\n//│ ║         \t      ^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.296: \ta2 = ma2 (fun (xinit, xsub) -> xinit true)\n//│ ╙──       \t     ^^^\n//│ res: error | undefined\n//│    = [ true, true ]\n\n// * Notice the (safely-)extruded skolem for the locally-quantified 'r\nma2 (fun (xinit, xsub) -> let tmp = xinit true in (tmp, tmp))\n//│ res: (??r, ??r,)\n//│    = [\n//│        [ [ true, true ], [ true, true ] ],\n//│        [ [ true, true ], [ true, true ] ]\n//│      ]\n\nma1 = mkSArray 1\n//│ ma1: ExSmall\n//│    = [Function (anonymous)]\n\nma1 (fun (xinit, xsub) -> xinit true)\n//│ res: ??r\n//│    = [ true, true ]\n\nma1 (fun (xinit, xsub) -> xsub (xinit true) 0)\n//│ res: true\n//│    = true\n\n\n// * Trying to do something unsafe now!\n\n:e\nma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub2 (xinit1 true) 0))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.348: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub2 (xinit1 true) 0))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.181: \ttype ExSmall = (forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> 'y\n//│ ║         \t                                  ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.348: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub2 (xinit1 true) 0))\n//│ ║         \t                                                               ^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.284: \tma2 = mkSArray 2\n//│ ║         \t      ^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.348: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub2 (xinit1 true) 0))\n//│ ║         \t                            ^^^\n//│ ╟── • this applied expression:\n//│ ║  l.348: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub2 (xinit1 true) 0))\n//│ ║         \t                                                        ^^^^^\n//│ ╟── • this tuple literal:\n//│ ║  l.348: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub2 (xinit1 true) 0))\n//│ ║         \t                                     ^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.348: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub2 (xinit1 true) 0))\n//│ ╙──       \t                                                               ^^^^^^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: boolean true is not iterable (cannot read property Symbol(Symbol.iterator))\n\n:e\nma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub1 (xinit2 true) 0))\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.379: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub1 (xinit2 true) 0))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.181: \ttype ExSmall = (forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> 'y\n//│ ║         \t                                  ^^\n//│ ╟── into type `'r0`\n//│ ║  l.181: \ttype ExSmall = (forall 'r. ('a -> 'r, 'r -> int -> 'a) -> 'y) -> 'y\n//│ ║         \t                                      ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.379: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub1 (xinit2 true) 0))\n//│ ║         \t                                                               ^^^^^^\n//│ ╟── • this tuple literal:\n//│ ║  l.379: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub1 (xinit2 true) 0))\n//│ ║         \t                                     ^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.284: \tma2 = mkSArray 2\n//│ ║         \t      ^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.379: \tma1 (fun (xinit1, xsub1) -> ma2 (fun (xinit2, xsub2) -> xsub1 (xinit2 true) 0))\n//│ ╙──       \t                            ^^^\n//│ res: error\n//│    = [ true, true ]\n\n\n// ******** ORIGINAL ARRAY EXAMPLE ********\n\ntype Sig[a, r, b] = (((a -> r, r -> int -> a), r -> int -> a -> r), (a -> b -> b) -> b -> r -> b)\ntype ExSig = (forall 'r. (forall 'b. ((('a -> 'r, 'r -> int -> 'a), 'r -> int -> 'a -> 'r), ('a -> 'b -> 'b) -> 'b -> 'r -> 'b)) -> 'y) -> 'y\n//│ Defined type alias Sig[=a, =r, =b]\n//│ Defined type alias ExSig\n\n// :e // works after fixing freshening levels\ndef base : ExSig\ndef base f = f ((((fun a -> a, fun r -> fun (i : int) -> r), fun r -> fun (i : int) -> fun a -> a), fun f -> fun b -> fun r -> f r b),)\n//│ base: ExSig\n//│     = <missing implementation>\n//│ (((((forall 'a. 'a -> 'a, forall 'b. 'b -> int -> 'b,), forall 'c. anything -> int -> 'c -> 'c,), forall 'd 'e 'f. ('d -> 'e -> 'f) -> 'e -> 'd -> 'f,),) -> 'g) -> 'g\n//│   <:  base:\n//│ ExSig\n//│     = [Function: base]\n\ndef step : ExSig -> ExSig\n//│ step: ExSig -> ExSig\n//│     = <missing implementation>\n\n// * The problem here is due to the polymorphism of the `fold` function, which is defined on the outside of the tuple.\n// * The reproduction in `QML_exist_Records.mls`, where `fold` is quantified on the inside, does not have this problem.\n// * So I suppose we could avoid the problem by pushing (distributing) the quantification inside the tuple, which we do not yet support.\n:e\ndef step = fun xx -> xx (fun ((((xinit, xsub), xupdate), xfold),) ->\n  let init a = (xinit a, xinit a) in\n  let sub r i =\n    if mod i 2 == 0\n    then xsub (fst r) (div i 2)\n    else xsub (snd r) (div i 2) in\n  let update r i a =\n    if mod i 2 == 0\n    then (xupdate (fst r) (div i 2) a, snd r)\n    else (fst r, xupdate (snd r) (div i 2) a) in\n  let fold f b r = xfold f (xfold f b (fst r)) (snd r) in\n    fun f -> f ((((init, sub), update), fold),) )\n//│ ((forall 'a 'b 'c 'd 'e 'f 'g 'h 'i 'j 'k 'l 'm 'n 'o 'p. (((('a -> 'b, 'c -> int -> 'd,), 'e -> int -> 'f -> 'g & 'h -> int -> 'f -> 'i,), 'j -> ('k -> 'l -> 'm & 'n -> 'o -> 'k),),) -> ((((('a -> ('b, 'b,), (('c, 'c,),) -> int -> 'd,), forall 'q 'r. (('e & 'q, 'h & 'r,),) -> int -> 'f -> ('q | 'g, 'i | 'r,),), 'j -> 'n -> (('o, 'l,),) -> 'm,),) -> 'p) -> 'p) -> 's) -> 's\n//│   <:  step:\n//│ ExSig -> ExSig\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.431: \tdef step = fun xx -> xx (fun ((((xinit, xsub), xupdate), xfold),) ->\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.432: \t  let init a = (xinit a, xinit a) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.433: \t  let sub r i =\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.434: \t    if mod i 2 == 0\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.435: \t    then xsub (fst r) (div i 2)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.436: \t    else xsub (snd r) (div i 2) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.437: \t  let update r i a =\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.438: \t    if mod i 2 == 0\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.439: \t    then (xupdate (fst r) (div i 2) a, snd r)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.440: \t    else (fst r, xupdate (snd r) (div i 2) a) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.441: \t  let fold f b r = xfold f (xfold f b (fst r)) (snd r) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.442: \t    fun f -> f ((((init, sub), update), fold),) )\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.409: \ttype ExSig = (forall 'r. (forall 'b. ((('a -> 'r, 'r -> int -> 'a), 'r -> int -> 'a -> 'r), ('a -> 'b -> 'b) -> 'b -> 'r -> 'b)) -> 'y) -> 'y\n//│ ║         \t                                              ^^\n//│ ╟── back into type variable `'r`\n//│ ║  l.409: \ttype ExSig = (forall 'r. (forall 'b. ((('a -> 'r, 'r -> int -> 'a), 'r -> int -> 'a -> 'r), ('a -> 'b -> 'b) -> 'b -> 'r -> 'b)) -> 'y) -> 'y\n//│ ║         \t                                                  ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.431: \tdef step = fun xx -> xx (fun ((((xinit, xsub), xupdate), xfold),) ->\n//│ ║         \t                     ^^\n//│ ╟── • this function:\n//│ ║  l.431: \tdef step = fun xx -> xx (fun ((((xinit, xsub), xupdate), xfold),) ->\n//│ ║         \t                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.432: \t  let init a = (xinit a, xinit a) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.433: \t  let sub r i =\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.434: \t    if mod i 2 == 0\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.435: \t    then xsub (fst r) (div i 2)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.436: \t    else xsub (snd r) (div i 2) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.437: \t  let update r i a =\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.438: \t    if mod i 2 == 0\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.439: \t    then (xupdate (fst r) (div i 2) a, snd r)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.440: \t    else (fst r, xupdate (snd r) (div i 2) a) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.441: \t  let fold f b r = xfold f (xfold f b (fst r)) (snd r) in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.442: \t    fun f -> f ((((init, sub), update), fold),) )\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.82: \tdef snd: forall 'a 'b. (('a, 'b),) -> 'b\n//│ ╙──      \t                             ^^\n//│     = [Function: step]\n\nlet mkArray n = if n == 0 then base else step base in\n  mkArray 1 (fun ((((xinit, xsub), xupdate), xfold),) -> xinit 2)\n//│ res: anything\n//│    = [ 2, 2 ]\n\ndef mkArray : int -> ExSig\n//│ mkArray: int -> ExSig\n//│        = <missing implementation>\n\nrec def mkArray n = if n == 0 then base else step (mkArray (n - 1))\n//│ int -> ExSig\n//│   <:  mkArray:\n//│ int -> ExSig\n//│        = [Function: mkArray]\n\nmkArray 3 (fun ((((xinit, xsub), xupdate), xfold),) -> xinit 2)\n//│ res: ??r\n//│    = [ [ [ 2, 2 ], [ 2, 2 ] ], [ [ 2, 2 ], [ 2, 2 ] ] ]\n\n:e\nres 0\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.531: \tres 0\n//│ ║         \t^^^^^\n//│ ╟── type variable `'r` leaks out of its scope\n//│ ║  l.409: \ttype ExSig = (forall 'r. (forall 'b. ((('a -> 'r, 'r -> int -> 'a), 'r -> int -> 'a -> 'r), ('a -> 'b -> 'b) -> 'b -> 'r -> 'b)) -> 'y) -> 'y\n//│ ║         \t                                              ^^\n//│ ╟── into application of type `0 -> ?a`\n//│ ║  l.531: \tres 0\n//│ ║         \t^^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.526: \tmkArray 3 (fun ((((xinit, xsub), xupdate), xfold),) -> xinit 2)\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this application:\n//│ ║  l.526: \tmkArray 3 (fun ((((xinit, xsub), xupdate), xfold),) -> xinit 2)\n//│ ╙──       \t^^^^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: res is not a function\n\n\n// =============== Sec 7 ===============\n\ndef choose: 'a -> 'a -> 'a\n//│ choose: 'a -> 'a -> 'a\n//│       = <missing implementation>\n\nchoose (head ids)\n//│ res: 'a -> (forall 'b. 'b -> 'b | 'a)\n//│    = <no result>\n//│      choose is not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/Stability.mls",
    "content": "// * Seeking Stability by Being Lazy and Shallow\n// * Lazy and Shallow Instantiation Is User Friendly\n// * https://dl.acm.org/doi/10.1145/3471874.3472985\n\n// * A lot of these examples are transcribed lossily because we currently\n// * do not have anything like explicit type applications and Haskell-style type classes.\n// * It turns out most of the examples are very Haskell-specific and thus not insightful for us.\n\n\n:NoRecursiveTypes\n\n\n\n// Preliminary definitions\n\n\n// id :: ∀ a. a → a\ndef id: forall 'a. 'a -> 'a\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n\n// pair :: ∀ a. a → ∀ b. b → (a, b)\ndef pair: forall 'a. 'a -> (forall 'b. 'b -> ('a, 'b,))\npair x y = (x, y)\n//│ pair: 'a -> 'b -> ('a, 'b,)\n//│     = <missing implementation>\n//│ 'a -> 'b -> ('a, 'b,)\n//│   <:  pair:\n//│ 'a -> 'b -> ('a, 'b,)\n//│     = [Function: pair]\n\n// myPairX x = pair x\nmyPairX x = pair x\n//│ myPairX: 'a -> 'b -> ('a, 'b,)\n//│        = [Function: myPairX]\n\n\n\n// 3.1 Similarity 1: Let-Inlining and Extraction\n\n\n// Example 1: myId\n\n// myId = id\nmyId = id\n//│ myId: 'a -> 'a\n//│     = <no result>\n//│       id is not implemented\n\n\n// Example 2: myPair\n\n// myPair = pair\nmyPair = pair\n//│ myPair: 'a -> 'b -> ('a, 'b,)\n//│       = [Function: pair]\n\n\n// Example 3: myPairX\n\n// myPairX x = pair x\nmyPairX x = pair x\n//│ myPairX: 'a -> 'b -> ('a, 'b,)\n//│        = [Function: myPairX1]\n\n\n\n// 3.2 Similarity 2: Signature Property\n// (The second similarity annotates a let binding with the inferred type 𝜎 of the bound expression e1.)\n\n\n// Example 4: infer\n\n// infer = 𝜆 @a (x :: a) → x\ninfer = forall 'a. fun (x: 'a) -> x\n//│ infer: 'a -> 'a\n//│      = [Function: infer]\n\ndef infer: 'a -> 'a\ninfer = forall 'a. fun (x: 'a) -> x\n//│ infer: 'a -> 'a\n//│      = <missing implementation>\n//│ 'a -> 'a\n//│   <:  infer:\n//│ 'a -> 'a\n//│      = [Function: infer1]\n\n\n\n// 3.3 Similarity 3: Type Signatures\n// (Changing a type signature should not affect runtime semantics.)\n\n\n// Example 5: swizzle\n\n// undef :: ∀ a. Int → a → a\n// undef = undefined\n:re\ndef undef: forall 'a. int -> 'a -> 'a\nundef = error\n//│ undef: int -> 'a -> 'a\n//│      = <missing implementation>\n//│ nothing\n//│   <:  undef:\n//│ int -> 'a -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\n// swizzle :: Int → ∀ a. a → a\n// swizzle = undef\n:re\ndef swizzle: int -> (forall 'a. 'a -> 'a)\nswizzle = undef\n//│ swizzle: int -> (forall 'a. 'a -> 'a)\n//│        = <missing implementation>\n//│ int -> 'a -> 'a\n//│   <:  swizzle:\n//│ int -> (forall 'a. 'a -> 'a)\n//│ Runtime error:\n//│   ReferenceError: undef is not defined\n\n// In Haskell, \"deeply skolemization\" would eta expand swizzle as:\nswizzle = fun x -> undef x\n//│ int -> 'a -> 'a\n//│   <:  swizzle:\n//│ int -> (forall 'a. 'a -> 'a)\n//│        = [Function: swizzle1]\n\n\n\n// 3.4 Similarity 4: Pattern-Inlining and Extraction\n// (changing variable patterns into 𝜆-binders)\n\n\n// Example 6: infer2, again\n\n// infer2 @a (x :: a) = x\ninfer2 = forall 'a. fun (x: 'a) -> x\n//│ infer2: 'a -> 'a\n//│       = [Function: infer2]\n\n\n\n// 3.5 Similarity 5: Single vs. Multiple Equations\n\n\n// Example 7: unitId1 and unitId2\n\nunitId1 () = id\n//│ unitId1: () -> (forall 'a. 'a -> 'a)\n//│        = <no result>\n//│          id is not implemented\n\n// Unlike in Haskell, here multiple equations simply shadow one another\nunitId2 () = id\nunitId2 () = id\n//│ unitId2: () -> (forall 'a. 'a -> 'a)\n//│        = <no result>\n//│          id is not implemented\n//│ unitId2: () -> (forall 'a. 'a -> 'a)\n//│        = <no result>\n//│          id is not implemented\n\n\n\n// 3.6 Similarity 6: 𝜂-Expansion\n\n\n// Example 8: eta\n\n// noEta = id\nnoEta = id\n//│ noEta: 'a -> 'a\n//│      = <no result>\n//│        id is not implemented\n\n// eta = 𝜆x → id x\neta = fun x -> id x\n//│ eta: 'a -> 'a\n//│    = <no result>\n//│      id is not implemented\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/fcp-lit/variations_PolyML.mls",
    "content": "// * Alternative: separate `Cons` and `Nil` types with definition of `mem` and `fold_left`\n// * :RecursiveTypes is now needed due to the structural typing of Cons and Nil\n\n// :NoRecursiveTypes\n:NoJS\n\n\n// ============ Sec 4.2 ============\n\n// ------------ Dummy classes to represent the types in the examples ------------\n\nclass Nil: {}\nclass Cons[a]: { head: a; tail: List[a] }\ntype List[a] = Nil | Cons[a]\n//│ Defined class Nil\n//│ Defined class Cons[+a]\n//│ Defined type alias List[+a]\n\ndef Nil = Nil {}\n//│ Nil: Nil\n\ndef Cons head tail = Cons { head; tail }\n//│ Cons: ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n\n// ------------ Type signatures for functions used in the examples ------------\n\nrec def mem x l = case l of\n  { Nil -> false\n  | Cons -> if eq l.head x then true else mem x l.tail\n  }\n//│ mem: anything -> 'a -> Bool\n//│   where\n//│     'a <: (Cons[?] with {tail: 'a}) | Nil\n\nrec def fold_left f x l = case l of\n  { Nil -> x\n  | Cons -> fold_left f (f x l.head) l.tail\n  }\n//│ fold_left: ('a -> 'head -> 'a) -> 'a -> 'b -> 'a\n//│   where\n//│     'b <: (Cons[?] with {head: 'head, tail: 'b}) | Nil\n\n// ------------ polymorphic methods ------------\n\nclass Collection[a]: { l: List[a] }\n  method Mem x = mem x this.l\n  method Fold f x = fold_left f x this.l\n//│ Defined class Collection[+a]\n//│ Defined Collection.Mem: Collection[?] -> anything -> Bool\n//│ Defined Collection.Fold: Collection['a] -> ('b -> 'a -> 'b) -> 'b -> 'b\n\ndef coll_mem c x = c.Mem x\n//│ coll_mem: Collection[?] -> anything -> Bool\n\n// * Typo in the paper? it was `fun x -> fun y -> ...`\ndef simple_and_double c =\n  let l1 = c.Fold (fun y -> fun x -> Cons x y) Nil in\n  let l2 = c.Fold (fun y -> fun x -> Cons ((x, x),) y) Nil in\n  (l1, l2)\n//│ simple_and_double: Collection['a] -> (forall 'b. Nil | 'b, forall 'c. Nil | 'c,)\n//│   where\n//│     'c :> Cons[('a, 'a,)] with {tail: forall 'c. Nil | 'c}\n//│     'b :> Cons['a] with {tail: forall 'b. Nil | 'b}\n\n\n\n// * Note: the kind of errors we get witout recursive types:\n\n:NoRecursiveTypes\n\n:e\nrec def mem x l = case l of\n  { Nil -> false\n  | Cons -> if eq l.head x then true else mem x l.tail\n  }\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: {head: ?, tail: Cons[?] & 'a}\n//│ ║  l.72: \trec def mem x l = case l of\n//│ ╙──      \t                       ^\n//│ mem: anything -> 'a -> Bool\n//│   where\n//│     'a <: (Cons[?] with {tail: 'a}) | Nil\n\n\n"
  },
  {
    "path": "shared/src/test/diff/gadt/Exp1.mls",
    "content": ":NewDefs\n\n\nabstract class Exp[A]: Pair | Lit\nclass Lit(n: Int) extends Exp[Int]\nclass Pair[L, R](val lhs: L, val rhs: R) extends Exp[[L, R]]\n//│ abstract class Exp[A]: Lit | Pair[anything, anything]\n//│ class Lit(n: Int) extends Exp\n//│ class Pair[L, R](lhs: L, rhs: R) extends Exp\n\n\nfun f(p: Pair['a, 'b]) = p.lhs\n//│ fun f: forall 'a 'b. (p: Pair['a, 'b]) -> 'a\n\n\nfun f(e) = if e is\n  Pair(l, r) then [l, r]\n//│ fun f: forall 'a 'b. Pair['a, 'b] -> ['a, 'b]\n// f: (Exp['a] & Pair) -> 0\n\n\nfun f(e) = if e is\n  Pair(l, r) then [l, r]\n  Lit(n) then n\n//│ fun f: forall 'a 'b. (Lit | Pair['a, 'b]) -> (Int | ['a, 'b])\n\n(e: Exp['X]) => f(e)\n//│ forall 'X. (e: Exp['X]) -> (Int | [??L, ??R])\n//│ res\n//│     = [Function: res]\n\n\n:w\nfun f(e) = if e is\n  Pair['a, 'b](l, r) then [l, r]\n//│ ╔══[WARNING] type parameters in patterns are currently ignored\n//│ ║  l.35: \t  Pair['a, 'b](l, r) then [l, r]\n//│ ╙──      \t       ^^^^^^\n//│ fun f: forall 'a 'b. Pair['a, 'b] -> ['a, 'b]\n\n\n:e // TODO support\nfun f(e) = if e is\n  Pair(l: a, r) then\n    let f(x: a) = x\n    f(l)\n//│ ╔══[ERROR] type identifier not found: a\n//│ ║  l.45: \t    let f(x: a) = x\n//│ ╙──      \t             ^\n//│ ╔══[ERROR] identifier not found: l\n//│ ║  l.46: \t    f(l)\n//│ ╙──      \t      ^\n//│ fun f: Pair[anything, anything] -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol l\n// fun f: forall 'lhs 'rhs. Pair['lhs, 'rhs] -> ('lhs, 'rhs,)\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/gadt/Exp2.mls",
    "content": ":NewDefs\n\n\n\n// * Variant:\n\nabstract class Exp[out A]: Pair | Lit\nclass Lit(val n: Int) extends Exp[Int]\nclass Pair[out L, out R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]]\n//│ abstract class Exp[A]: Lit | Pair[anything, anything]\n//│ class Lit(n: Int) extends Exp\n//│ class Pair[L, R](lhs: Exp[L], rhs: Exp[R]) extends Exp\n\n\nfun f(p: Pair['a, 'b]) = p.lhs\n//│ fun f: forall 'a. (p: Pair['a, anything]) -> Exp['a]\n\nfun f(e) = if e is\n  Pair(l, r) then [l, r]\n//│ fun f: forall 'L 'R. Pair['L, 'R] -> [Exp['L], Exp['R]]\n// f: (Exp['a] & Pair) -> 0\n\nfun f(e) = if e is\n  Pair(l, r) then [l, r]\n  Lit(n) then n\n//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> (Int | [Exp['L], Exp['R]])\n\n(e: Exp['X]) => f(e)\n//│ (e: Exp[anything]) -> (Int | [Exp[??L], Exp[??R]])\n//│ res\n//│     = [Function: res]\n\nfun f(e) = if e is\n  Pair(l, r) then f(l) + f(r)\n  Lit(n) then n\n//│ fun f: (Lit | Pair[anything, anything]) -> Int\n\n\n// * Invariant:\n\nabstract class Exp[A]: Pair | Lit\nclass Lit(val n: Int) extends Exp[Int]\nclass Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]]\n//│ abstract class Exp[A]: Lit | Pair[?, ?]\n//│ class Lit(n: Int) extends Exp\n//│ class Pair[L, R](lhs: Exp[L], rhs: Exp[R]) extends Exp\n\n\nfun f(p: Pair['a, 'b]) = p.lhs\n//│ fun f: forall 'a 'b. (p: Pair['a, 'b]) -> Exp['a]\n\nfun f(e) = if e is\n  Pair(l, r) then [l, r]\n//│ fun f: forall 'L 'R. Pair['L, 'R] -> [Exp['L], Exp['R]]\n// f: (Exp['a] & Pair) -> 0\n\nfun f(e) = if e is\n  Pair(l, r) then [l, r]\n  Lit(n) then n\n//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> (Int | [Exp['L], Exp['R]])\n\n:e\n(e: Exp['X]) => f(e)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.63: \t(e: Exp['X]) => f(e)\n//│ ║        \t                ^^^^\n//│ ╟── type variable `L` leaks out of its scope\n//│ ║  l.43: \tclass Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]]\n//│ ╙──      \t           ^\n//│ forall 'X 'L 'R. (e: Exp['X]) -> (Int | error | [Exp['L], Exp['R]])\n//│   where\n//│     'R :> ??R\n//│        <: ??R0\n//│     'L :> ??L\n//│        <: ??L0\n//│ res\n//│     = [Function: res]\n\n:e\nfun f(e) = if e is\n  Pair(l, r) then f(l) + f(r)\n  Lit(n) then n\n//│ ╔══[ERROR] Type error in definition\n//│ ║  l.80: \tfun f(e) = if e is\n//│ ║        \t    ^^^^^^^^^^^^^^\n//│ ║  l.81: \t  Pair(l, r) then f(l) + f(r)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.82: \t  Lit(n) then n\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── type variable `L` leaks out of its scope\n//│ ║  l.43: \tclass Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]]\n//│ ╙──      \t           ^\n//│ ╔══[ERROR] Type error in definition\n//│ ║  l.80: \tfun f(e) = if e is\n//│ ║        \t    ^^^^^^^^^^^^^^\n//│ ║  l.81: \t  Pair(l, r) then f(l) + f(r)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.82: \t  Lit(n) then n\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── type variable `R` leaks out of its scope\n//│ ║  l.43: \tclass Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]]\n//│ ╙──      \t              ^\n//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> Int\n//│   where\n//│     'R :> ??R\n//│        <: ??R0\n//│     'L :> ??L\n//│        <: ??L0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/gadt/ThisMatching.mls",
    "content": ":NewDefs\n\n\n:e\n:re\nmodule Dummy {\n  log(if this is Dummy then \"duh!\" else \"huh?\")\n}\n//│ ╔══[ERROR] Cannot access `this` during object initialization\n//│ ║  l.7: \t  log(if this is Dummy then \"duh!\" else \"huh?\")\n//│ ╙──     \t         ^^^^\n//│ module Dummy\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\nmodule Dummy {\n  fun introspect =\n    if this is Dummy then \"duh!\" else \"huh?\"\n}\n//│ module Dummy {\n//│   fun introspect: \"duh!\" | \"huh?\"\n//│ }\n\nDummy.introspect\n//│ \"duh!\" | \"huh?\"\n//│ res\n//│     = 'duh!'\n\n\nabstract class Funny: Int { fun test = this + 1 }\n//│ abstract class Funny: Int {\n//│   fun test: Int\n//│ }\n\n:e\nclass Unfunny { fun test = this + 1 }\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.36: \tclass Unfunny { fun test = this + 1 }\n//│ ║        \t                           ^^^^^^^^\n//│ ╟── reference of type `#Unfunny` is not an instance of type `Int`\n//│ ║  l.36: \tclass Unfunny { fun test = this + 1 }\n//│ ╙──      \t                           ^^^^\n//│ class Unfunny {\n//│   constructor()\n//│   fun test: Int | error\n//│ }\n\n\nabstract class Exp: (Pair | Lit) {\n  fun test = if this is\n    Lit then 0\n    Pair then 1\n}\nclass Lit(n: Int) extends Exp\nclass Pair(lhs: Exp, rhs: Exp) extends Exp\n//│ abstract class Exp: Lit | Pair {\n//│   fun test: 0 | 1\n//│ }\n//│ class Lit(n: Int) extends Exp {\n//│   fun test: 0 | 1\n//│ }\n//│ class Pair(lhs: Exp, rhs: Exp) extends Exp {\n//│   fun test: 0 | 1\n//│ }\n\n\nabstract class Exp: (() | Lit) {\n  fun test = if this is\n    Lit then 0\n    () then 1\n}\nclass Lit(n: Int) extends Exp\n//│ abstract class Exp: Lit | () {\n//│   fun test: 0 | 1\n//│ }\n//│ class Lit(n: Int) extends Exp {\n//│   fun test: 0 | 1\n//│ }\n\n// * TODO fix this by requiring a type annotation on `test` and delaying its body's type checking until all the involed classes are completed\n// * Currently we try to complete Exp ->{type checking defn body} complete test ->{type checking pattern} find Wrap's typed fields ->{get Wrap's typed parents} complete Exp\n:e\nabstract class Exp: (() | Wrap) {\n  fun test = if this is\n    Wrap(a) then 0\n    () then 1\n}\nclass Wrap(n: Exp) extends Exp\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.83: \tabstract class Exp: (() | Wrap) {\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.84: \t  fun test = if this is\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.85: \t    Wrap(a) then 0\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.86: \t    () then 1\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.87: \t}\n//│ ╙──      \t^\n//│ abstract class Exp: Wrap | () {\n//│   fun test: 0 | 1\n//│ }\n//│ class Wrap(n: Exp) extends Exp\n\n// * TODO (same as above)\n:e\nabstract class Exp: (Pair | Lit) {\n  fun test: Int\n  fun test = if this is\n    Lit then 0\n    Pair(l, r) then 1\n}\nclass Lit(n: Int) extends Exp\nclass Pair(lhs: Exp, rhs: Exp) extends Exp\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.107: \tabstract class Exp: (Pair | Lit) {\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.108: \t  fun test: Int\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.109: \t  fun test = if this is\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.110: \t    Lit then 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.111: \t    Pair(l, r) then 1\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.112: \t}\n//│ ╙──       \t^\n//│ abstract class Exp: Lit | Pair {\n//│   fun test: Int\n//│ }\n//│ class Lit(n: Int) extends Exp {\n//│   fun test: Int\n//│ }\n//│ class Pair(lhs: Exp, rhs: Exp) extends Exp\n\n:e // TODO\nPair(Lit(1), Lit(2)).test\n//│ ╔══[ERROR] Type `Pair` does not contain member `test`\n//│ ║  l.137: \tPair(Lit(1), Lit(2)).test\n//│ ╙──       \t                    ^^^^^\n//│ error\n//│ res\n//│     = 1\n\n\n:e // TODO can we support this?\nabstract class Exp: (Pair | Lit) {\n  fun test = if this is\n    Lit then 0\n    Pair(l, r) then l.test + r.test\n}\nclass Lit(n: Int) extends Exp\nclass Pair(lhs: Exp, rhs: Exp) extends Exp\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.147: \tabstract class Exp: (Pair | Lit) {\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.148: \t  fun test = if this is\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.149: \t    Lit then 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.150: \t    Pair(l, r) then l.test + r.test\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.151: \t}\n//│ ╙──       \t^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.150: \t    Pair(l, r) then l.test + r.test\n//│ ╙──       \t                     ^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.150: \t    Pair(l, r) then l.test + r.test\n//│ ╙──       \t                              ^^^^^\n//│ abstract class Exp: Lit | Pair {\n//│   fun test: Int\n//│ }\n//│ class Lit(n: Int) extends Exp {\n//│   fun test: Int\n//│ }\n//│ class Pair(lhs: Exp, rhs: Exp) extends Exp\n\n\n:e // TODO\nabstract class Exp: (Pair | Lit) {\n  fun test : Int\n  fun test = if this is\n    Lit then 0\n    Pair(l, r) then l.test + r.test\n}\nclass Lit(n: Int) extends Exp\nclass Pair(lhs: Exp, rhs: Exp) extends Exp\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.181: \tabstract class Exp: (Pair | Lit) {\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.182: \t  fun test : Int\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ║  l.183: \t  fun test = if this is\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.184: \t    Lit then 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.185: \t    Pair(l, r) then l.test + r.test\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.186: \t}\n//│ ╙──       \t^\n//│ abstract class Exp: Lit | Pair {\n//│   fun test: Int\n//│ }\n//│ class Lit(n: Int) extends Exp {\n//│   fun test: Int\n//│ }\n//│ class Pair(lhs: Exp, rhs: Exp) extends Exp\n\n\n:e // TODO support – this requires implementing type member lookup without forced completion (we get constraints like Pair<Exp> <: Pair#L)\nabstract class Exp[A]: (Pair | Lit) {\n  fun test = if this is\n    Lit then 0\n    Pair then 1\n}\nclass Lit(n: Int) extends Exp[Int]\nclass Pair[L, R](lhs: L, rhs: R) extends Exp[[L, R]]\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.212: \tabstract class Exp[A]: (Pair | Lit) {\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.213: \t  fun test = if this is\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.214: \t    Lit then 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.215: \t    Pair then 1\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.216: \t}\n//│ ╙──       \t^\n//│ ╔══[ERROR] Type error in `case` expression\n//│ ║  l.213: \t  fun test = if this is\n//│ ║         \t                ^^^^^^^\n//│ ║  l.214: \t    Lit then 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.215: \t    Pair then 1\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── type variable `L` leaks out of its scope\n//│ ║  l.218: \tclass Pair[L, R](lhs: L, rhs: R) extends Exp[[L, R]]\n//│ ╙──       \t           ^\n//│ abstract class Exp[A]: Lit | Pair[anything, anything] {\n//│   fun test: 0 | 1\n//│ }\n//│ class Lit(n: Int) extends Exp {\n//│   fun test: 0 | 1\n//│ }\n//│ class Pair[L, R](lhs: L, rhs: R) extends Exp\n\nLit(0).test\n//│ 0 | 1\n//│ res\n//│     = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/gen/genTests_v1-0.14-15-x2.fun",
    "content": "// Automatically generated by mlscript.EnumeratePrograms — DO NOT EDIT\n\n:AllowTypeErrors\n:ShowRelativeLineNums\n\n\n0\n//│ res: 0\n\nadd\n//│ res: int -> int -> int\n\n(0 0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(0 0)\n//│ ║        \t ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(0 0)\n//│ ╙──      \t ^\n//│ res: error\n\n(0 add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(0 add)\n//│ ║        \t ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(0 add)\n//│ ╙──      \t ^\n//│ res: error\n\n(0 {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(0 {u: 0})\n//│ ║        \t ^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(0 {u: 0})\n//│ ╙──      \t ^\n//│ res: error\n\n(0 {u: add})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(0 {u: add})\n//│ ║        \t ^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(0 {u: add})\n//│ ╙──      \t ^\n//│ res: error\n\n(add 0)\n//│ res: int -> int\n\n(add add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(add add)\n//│ ║        \t ^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t(add add)\n//│ ╙──      \t     ^^^\n//│ res: error | int -> int\n\n(add 0.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(add 0.u)\n//│ ║        \t      ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(add 0.u)\n//│ ╙──      \t     ^\n//│ res: int -> int\n\n(add add.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(add add.u)\n//│ ║        \t        ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(add add.u)\n//│ ╙──      \t     ^^^\n//│ res: int -> int\n\n(add 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(add 0.v)\n//│ ║        \t      ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(add 0.v)\n//│ ╙──      \t     ^\n//│ res: int -> int\n\n(add add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(add add.v)\n//│ ║        \t        ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(add add.v)\n//│ ╙──      \t     ^^^\n//│ res: int -> int\n\n(add {v: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(add {v: 0})\n//│ ║        \t ^^^^^^^^^^\n//│ ╟── record of type `{v: 0}` is not an instance of type `int`\n//│ ║  l.+1: \t(add {v: 0})\n//│ ╙──      \t     ^^^^^^\n//│ res: error | int -> int\n\n(add {v: add})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(add {v: add})\n//│ ║        \t ^^^^^^^^^^^^\n//│ ╟── record of type `{v: int -> int -> int}` is not an instance of type `int`\n//│ ║  l.+1: \t(add {v: add})\n//│ ╙──      \t     ^^^^^^^^\n//│ res: error | int -> int\n\n(add {v: 0.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(add {v: 0.v})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(add {v: 0.v})\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(add {v: 0.v})\n//│ ║        \t ^^^^^^^^^^^^\n//│ ╟── record of type `{v: ?v}` is not an instance of type `int`\n//│ ║  l.+1: \t(add {v: 0.v})\n//│ ╙──      \t     ^^^^^^^^\n//│ res: error | int -> int\n\n(add {v: add.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(add {v: add.v})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(add {v: add.v})\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(add {v: add.v})\n//│ ║        \t ^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: ?v}` is not an instance of type `int`\n//│ ║  l.+1: \t(add {v: add.v})\n//│ ╙──      \t     ^^^^^^^^^^\n//│ res: error | int -> int\n\n((x => 0) 0)\n//│ res: 0\n\n((x => 0) add)\n//│ res: 0\n\n((x => 0) {u: 0})\n//│ res: 0\n\n((x => 0) {u: 0, v: 0})\n//│ res: 0\n\n((x => 0) {u: 0, v: add})\n//│ res: 0\n\n((x => 0) {u: add})\n//│ res: 0\n\n((x => add) 0)\n//│ res: int -> int -> int\n\n((x => add) add)\n//│ res: int -> int -> int\n\n((x => add) 0.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add) 0.u)\n//│ ║        \t             ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => add) 0.u)\n//│ ╙──      \t            ^\n//│ res: int -> int -> int\n\n((x => add) add.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add) add.u)\n//│ ║        \t               ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => add) add.u)\n//│ ╙──      \t            ^^^\n//│ res: int -> int -> int\n\n((x => add) {u: 0})\n//│ res: int -> int -> int\n\n((x => add) {u: add})\n//│ res: int -> int -> int\n\n((x => add) {u: add, v: 0})\n//│ res: int -> int -> int\n\n((x => add) {u: add, v: add})\n//│ res: int -> int -> int\n\n((x => add) {u: 0.u})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add) {u: 0.u})\n//│ ║        \t                 ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => add) {u: 0.u})\n//│ ╙──      \t                ^\n//│ res: int -> int -> int\n\n((x => add) {u: add.u})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add) {u: add.u})\n//│ ║        \t                   ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => add) {u: add.u})\n//│ ╙──      \t                ^^^\n//│ res: int -> int -> int\n\n((x => add) 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add) 0.v)\n//│ ║        \t             ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t((x => add) 0.v)\n//│ ╙──      \t            ^\n//│ res: int -> int -> int\n\n((x => add) add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add) add.v)\n//│ ║        \t               ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t((x => add) add.v)\n//│ ╙──      \t            ^^^\n//│ res: int -> int -> int\n\n((let x = 0; add) 0)\n//│ res: int -> int\n\n((let x = 0; add) add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) add)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) add)\n//│ ╙──      \t                  ^^^\n//│ res: error | int -> int\n\n((let x = 0; add) (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) (0 0))\n//│ ║        \t                   ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = 0; add) (0 0))\n//│ ╙──      \t                   ^\n//│ res: int -> int\n\n((let x = 0; add) (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) (0 add))\n//│ ║        \t                   ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = 0; add) (0 add))\n//│ ╙──      \t                   ^\n//│ res: int -> int\n\n((let x = 0; add) (x => 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) (x => 0))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> 0` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) (x => 0))\n//│ ║        \t                   ^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = 0; add) (x => 0))\n//│ ╙──      \t                  ^^^^^^^^\n//│ res: error | int -> int\n\n((let x = 0; add) (let x = 0; 0))\n//│ res: int -> int\n\n((let x = 0; add) (let x = add; 0))\n//│ res: int -> int\n\n((let x = 0; add) (let rec x = x; 0))\n//│ res: int -> int\n\n((let x = 0; add) (let x = 0.u; 0))\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = 0; add) (let x = 0.u; 0))\n//│ ║        \t                            ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((let x = 0; add) (let x = 0.u; 0))\n//│ ╙──      \t                           ^\n//│ res: int -> int\n\n((let x = 0; add) (let x = add.u; 0))\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = 0; add) (let x = add.u; 0))\n//│ ║        \t                              ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((let x = 0; add) (let x = add.u; 0))\n//│ ╙──      \t                           ^^^\n//│ res: int -> int\n\n((let x = 0; add) (let rec x = x.u; 0))\n//│ res: int -> int\n\n((let x = 0; add) (x => add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) (x => add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) (x => add))\n//│ ║        \t                   ^^^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = 0; add) (x => add))\n//│ ╙──      \t                  ^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = 0; add) (x => x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) (x => x))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> ?a` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) (x => x))\n//│ ║        \t                   ^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = 0; add) (x => x))\n//│ ╙──      \t                  ^^^^^^^^\n//│ res: error | int -> int\n\n((let x = 0; add) (let x = 0; x))\n//│ res: int -> int\n\n((let x = 0; add) (let x = add; x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) (let x = add; x))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) (let x = add; x))\n//│ ║        \t                           ^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.+1: \t((let x = 0; add) (let x = add; x))\n//│ ╙──      \t                                ^\n//│ res: error | int -> int\n\n((let x = 0; add) (let rec x = x; x))\n//│ res: int -> int\n\n((let x = 0; add) 0.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = 0; add) 0.u)\n//│ ║        \t                   ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((let x = 0; add) 0.u)\n//│ ╙──      \t                  ^\n//│ res: int -> int\n\n((let x = 0; add) add.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = 0; add) add.u)\n//│ ║        \t                     ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((let x = 0; add) add.u)\n//│ ╙──      \t                  ^^^\n//│ res: int -> int\n\n((let x = 0; add) {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) {u: 0})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{u: 0}` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) {u: 0})\n//│ ╙──      \t                  ^^^^^^\n//│ res: error | int -> int\n\n((let x = 0; add) {u: add})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) {u: add})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{u: int -> int -> int}` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) {u: add})\n//│ ╙──      \t                  ^^^^^^^^\n//│ res: error | int -> int\n\n((let x = 0; add) {v: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) {v: 0})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: 0}` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) {v: 0})\n//│ ╙──      \t                  ^^^^^^\n//│ res: error | int -> int\n\n((let x = 0; add) {v: add})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = 0; add) {v: add})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: int -> int -> int}` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = 0; add) {v: add})\n//│ ╙──      \t                  ^^^^^^^^\n//│ res: error | int -> int\n\n((let x = add; add) 0)\n//│ res: int -> int\n\n((let x = add; add) add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) add)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = add; add) add)\n//│ ╙──      \t                    ^^^\n//│ res: error | int -> int\n\n((let x = add; add) (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (0 0))\n//│ ║        \t                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = add; add) (0 0))\n//│ ╙──      \t                     ^\n//│ res: int -> int\n\n((let x = add; add) (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (0 add))\n//│ ║        \t                     ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = add; add) (0 add))\n//│ ╙──      \t                     ^\n//│ res: int -> int\n\n((let x = add; add) (0 {u: 0}))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (0 {u: 0}))\n//│ ║        \t                     ^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = add; add) (0 {u: 0}))\n//│ ╙──      \t                     ^\n//│ res: int -> int\n\n((let x = add; add) (0 {u: add}))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (0 {u: add}))\n//│ ║        \t                     ^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = add; add) (0 {u: add}))\n//│ ╙──      \t                     ^\n//│ res: int -> int\n\n((let x = add; add) ((0 add) 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) ((0 add) 0))\n//│ ║        \t                      ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = add; add) ((0 add) 0))\n//│ ╙──      \t                      ^\n//│ res: int -> int\n\n((let x = add; add) ((0 add) add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) ((0 add) add))\n//│ ║        \t                      ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((let x = add; add) ((0 add) add))\n//│ ╙──      \t                      ^\n//│ res: int -> int\n\n((let x = add; add) (x => 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (x => 0))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> 0` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = add; add) (x => 0))\n//│ ║        \t                     ^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = add; add) (x => 0))\n//│ ╙──      \t                    ^^^^^^^^\n//│ res: error | int -> int\n\n((let x = add; add) (let x = 0; 0))\n//│ res: int -> int\n\n((let x = add; add) (let x = add; 0))\n//│ res: int -> int\n\n((let x = add; add) (let rec x = x; 0))\n//│ res: int -> int\n\n((let x = add; add) (x => add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (x => add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = add; add) (x => add))\n//│ ║        \t                     ^^^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = add; add) (x => add))\n//│ ╙──      \t                    ^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = add; add) (let x = 0; add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (let x = 0; add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = add; add) (let x = 0; add))\n//│ ║        \t                                ^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = add; add) (let x = 0; add))\n//│ ╙──      \t                    ^^^^^^^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = add; add) (let x = add; add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (let x = add; add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = add; add) (let x = add; add))\n//│ ║        \t                                  ^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = add; add) (let x = add; add))\n//│ ╙──      \t                    ^^^^^^^^^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = add; add) (let rec x = x; add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (let rec x = x; add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = add; add) (let rec x = x; add))\n//│ ║        \t                                    ^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = add; add) (let rec x = x; add))\n//│ ╙──      \t                    ^^^^^^^^^^^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = add; add) (x => x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = add; add) (x => x))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> ?a` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = add; add) (x => x))\n//│ ║        \t                     ^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = add; add) (x => x))\n//│ ╙──      \t                    ^^^^^^^^\n//│ res: error | int -> int\n\n((let rec x = x; add) 0)\n//│ res: int -> int\n\n((let rec x = x; add) add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let rec x = x; add) add)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let rec x = x; add) add)\n//│ ╙──      \t                      ^^^\n//│ res: error | int -> int\n\n((let rec x = x; add) 0.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let rec x = x; add) 0.u)\n//│ ║        \t                       ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((let rec x = x; add) 0.u)\n//│ ╙──      \t                      ^\n//│ res: int -> int\n\n((let rec x = x; add) add.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let rec x = x; add) add.u)\n//│ ║        \t                         ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((let rec x = x; add) add.u)\n//│ ╙──      \t                      ^^^\n//│ res: int -> int\n\n((let rec x = x; add) {u: 0}.u)\n//│ res: int -> int\n\n((let rec x = x; add) {u: add}.u)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let rec x = x; add) {u: add}.u)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let rec x = x; add) {u: add}.u)\n//│ ║        \t                          ^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.+1: \t((let rec x = x; add) {u: add}.u)\n//│ ╙──      \t                              ^^\n//│ res: error | int -> int\n\n((let rec x = x; add) {v: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let rec x = x; add) {v: 0})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: 0}` is not an instance of type `int`\n//│ ║  l.+1: \t((let rec x = x; add) {v: 0})\n//│ ╙──      \t                      ^^^^^^\n//│ res: error | int -> int\n\n((let rec x = x; add) {v: add})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let rec x = x; add) {v: add})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: int -> int -> int}` is not an instance of type `int`\n//│ ║  l.+1: \t((let rec x = x; add) {v: add})\n//│ ╙──      \t                      ^^^^^^^^\n//│ res: error | int -> int\n\n((let rec x = x; add) {v: 0.u})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let rec x = x; add) {v: 0.u})\n//│ ║        \t                           ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((let rec x = x; add) {v: 0.u})\n//│ ╙──      \t                          ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let rec x = x; add) {v: 0.u})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: ?u}` is not an instance of type `int`\n//│ ║  l.+1: \t((let rec x = x; add) {v: 0.u})\n//│ ╙──      \t                      ^^^^^^^^\n//│ res: error | int -> int\n\n((let rec x = x; add) {v: add.u})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let rec x = x; add) {v: add.u})\n//│ ║        \t                             ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((let rec x = x; add) {v: add.u})\n//│ ╙──      \t                          ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let rec x = x; add) {v: add.u})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: ?u}` is not an instance of type `int`\n//│ ║  l.+1: \t((let rec x = x; add) {v: add.u})\n//│ ╙──      \t                      ^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) 0)\n//│ res: int -> int\n\n((let x = {v: 0}; add) add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) add)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) add)\n//│ ╙──      \t                       ^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (add 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add 0))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add 0))\n//│ ║        \t                        ^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add 0))\n//│ ╙──      \t                       ^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (add add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add add))\n//│ ║        \t                        ^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add add))\n//│ ╙──      \t                            ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add add))\n//│ ║        \t                        ^^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (add add))\n//│ ╙──      \t                       ^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (x => 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => 0))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> 0` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => 0))\n//│ ║        \t                        ^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => 0))\n//│ ╙──      \t                       ^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (let x = 0; 0))\n//│ res: int -> int\n\n((let x = {v: 0}; add) (let x = add; 0))\n//│ res: int -> int\n\n((let x = {v: 0}; add) (let rec x = x; 0))\n//│ res: int -> int\n\n((let x = {v: 0}; add) (x => add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => add))\n//│ ║        \t                        ^^^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => add))\n//│ ╙──      \t                       ^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (let x = 0; add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let x = 0; add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let x = 0; add))\n//│ ║        \t                                   ^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let x = 0; add))\n//│ ╙──      \t                       ^^^^^^^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (let x = add; add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let x = add; add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let x = add; add))\n//│ ║        \t                                     ^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let x = add; add))\n//│ ╙──      \t                       ^^^^^^^^^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (let rec x = x; add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let rec x = x; add))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let rec x = x; add))\n//│ ║        \t                                       ^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (let rec x = x; add))\n//│ ╙──      \t                       ^^^^^^^^^^^^^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) (x => x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => x))\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> ?a` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => x))\n//│ ║        \t                        ^^^^^^\n//│ ╟── but it flows into argument with expected type `int`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => x))\n//│ ╙──      \t                       ^^^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: 0}; add) 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = {v: 0}; add) 0.v)\n//│ ║        \t                        ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t((let x = {v: 0}; add) 0.v)\n//│ ╙──      \t                       ^\n//│ res: int -> int\n\n((let x = {v: 0}; add) add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = {v: 0}; add) add.v)\n//│ ║        \t                          ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t((let x = {v: 0}; add) add.v)\n//│ ╙──      \t                       ^^^\n//│ res: int -> int\n\n((let x = {v: 0}; add) (x => 0).v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => 0).v)\n//│ ║        \t                               ^^\n//│ ╟── function of type `?a -> 0` does not have field 'v'\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => 0).v)\n//│ ║        \t                        ^^^^^^\n//│ ╟── but it flows into receiver with expected type `{v: ?v}`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => 0).v)\n//│ ╙──      \t                       ^^^^^^^^\n//│ res: int -> int\n\n((let x = {v: 0}; add) (x => add).v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => add).v)\n//│ ║        \t                                 ^^\n//│ ╟── function of type `?a -> int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => add).v)\n//│ ║        \t                        ^^^^^^^^\n//│ ╟── but it flows into receiver with expected type `{v: ?v}`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => add).v)\n//│ ╙──      \t                       ^^^^^^^^^^\n//│ res: int -> int\n\n((let x = {v: 0}; add) (x => x).v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => x).v)\n//│ ║        \t                               ^^\n//│ ╟── function of type `?a -> ?a` does not have field 'v'\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => x).v)\n//│ ║        \t                        ^^^^^^\n//│ ╟── but it flows into receiver with expected type `{v: ?v}`\n//│ ║  l.+1: \t((let x = {v: 0}; add) (x => x).v)\n//│ ╙──      \t                       ^^^^^^^^\n//│ res: int -> int\n\n((let x = {v: add}; add) 0)\n//│ res: int -> int\n\n((let x = {v: add}; add) add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: add}; add) add)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: add}; add) add)\n//│ ╙──      \t                         ^^^\n//│ res: error | int -> int\n\n((let x = {v: add}; add) {v: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: add}; add) {v: 0})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: 0}` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: add}; add) {v: 0})\n//│ ╙──      \t                         ^^^^^^\n//│ res: error | int -> int\n\n((let x = {v: add}; add) {v: add})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let x = {v: add}; add) {v: add})\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record of type `{v: int -> int -> int}` is not an instance of type `int`\n//│ ║  l.+1: \t((let x = {v: add}; add) {v: add})\n//│ ╙──      \t                         ^^^^^^^^\n//│ res: error | int -> int\n\n((let rec x = {v: x}; add) 0)\n//│ res: int -> int\n\n((let rec x = {v: x}; add) add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((let rec x = {v: x}; add) add)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t((let rec x = {v: x}; add) add)\n//│ ╙──      \t                           ^^^\n//│ res: error | int -> int\n\n((x => x) 0)\n//│ res: 0\n\n((x => x) add)\n//│ res: int -> int -> int\n\n((x => x) (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x) (0 0))\n//│ ║        \t           ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((x => x) (0 0))\n//│ ╙──      \t           ^\n//│ res: error\n\n((x => x) (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x) (0 add))\n//│ ║        \t           ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((x => x) (0 add))\n//│ ╙──      \t           ^\n//│ res: error\n\n((x => x) (0 (x => 0)))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x) (0 (x => 0)))\n//│ ║        \t           ^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((x => x) (0 (x => 0)))\n//│ ╙──      \t           ^\n//│ res: error\n\n((x => x) (0 (x => add)))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x) (0 (x => add)))\n//│ ║        \t           ^^^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((x => x) (0 (x => add)))\n//│ ╙──      \t           ^\n//│ res: error\n\n((x => x) (0 (x => x)))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x) (0 (x => x)))\n//│ ║        \t           ^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t((x => x) (0 (x => x)))\n//│ ╙──      \t           ^\n//│ res: error\n\n((x => x) {v: 0})\n//│ res: {v: 0}\n\n((x => x) {v: add})\n//│ res: {v: int -> int -> int}\n\n((x => 0.u) 0)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => 0.u) 0)\n//│ ║        \t        ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => 0.u) 0)\n//│ ╙──      \t       ^\n//│ res: error\n\n((x => 0.u) add)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => 0.u) add)\n//│ ║        \t        ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => 0.u) add)\n//│ ╙──      \t       ^\n//│ res: error\n\n((x => add.u) 0)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add.u) 0)\n//│ ║        \t          ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => add.u) 0)\n//│ ╙──      \t       ^^^\n//│ res: error\n\n((x => add.u) add)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add.u) add)\n//│ ║        \t          ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => add.u) add)\n//│ ╙──      \t       ^^^\n//│ res: error\n\n((x => add.u) 0.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add.u) 0.u)\n//│ ║        \t          ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => add.u) 0.u)\n//│ ╙──      \t       ^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add.u) 0.u)\n//│ ║        \t               ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => add.u) 0.u)\n//│ ╙──      \t              ^\n//│ res: error\n\n((x => add.u) add.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add.u) add.u)\n//│ ║        \t          ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => add.u) add.u)\n//│ ╙──      \t       ^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => add.u) add.u)\n//│ ║        \t                 ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => add.u) add.u)\n//│ ╙──      \t              ^^^\n//│ res: error\n\n((x => x.u) 0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x.u) 0)\n//│ ║        \t ^^^^^^^^^^^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => x.u) 0)\n//│ ║        \t            ^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.+1: \t((x => x.u) 0)\n//│ ║        \t        ^^\n//│ ╟── from reference:\n//│ ║  l.+1: \t((x => x.u) 0)\n//│ ╙──      \t       ^\n//│ res: error\n\n((x => x.u) add)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x.u) add)\n//│ ║        \t ^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => x.u) add)\n//│ ║        \t            ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.+1: \t((x => x.u) add)\n//│ ║        \t        ^^\n//│ ╟── from reference:\n//│ ║  l.+1: \t((x => x.u) add)\n//│ ╙──      \t       ^\n//│ res: error\n\n((x => x.u) 0.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => x.u) 0.u)\n//│ ║        \t             ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => x.u) 0.u)\n//│ ╙──      \t            ^\n//│ res: error\n\n((x => x.u) add.u)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t((x => x.u) add.u)\n//│ ║        \t               ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => x.u) add.u)\n//│ ╙──      \t            ^^^\n//│ res: error\n\n((x => x.u) {u: 0}.u)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x.u) {u: 0}.u)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t((x => x.u) {u: 0}.u)\n//│ ║        \t                ^\n//│ ╟── but it flows into field selection with expected type `{u: ?u}`\n//│ ║  l.+1: \t((x => x.u) {u: 0}.u)\n//│ ║        \t                  ^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.+1: \t((x => x.u) {u: 0}.u)\n//│ ║        \t        ^^\n//│ ╟── from reference:\n//│ ║  l.+1: \t((x => x.u) {u: 0}.u)\n//│ ╙──      \t       ^\n//│ res: error\n\n((x => x.u) {u: add}.u)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t((x => x.u) {u: add}.u)\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t((x => x.u) {u: add}.u)\n//│ ║        \t                ^^^\n//│ ╟── but it flows into field selection with expected type `{u: ?u}`\n//│ ║  l.+1: \t((x => x.u) {u: add}.u)\n//│ ║        \t                    ^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.+1: \t((x => x.u) {u: add}.u)\n//│ ║        \t        ^^\n//│ ╟── from reference:\n//│ ║  l.+1: \t((x => x.u) {u: add}.u)\n//│ ╙──      \t       ^\n//│ res: error\n\n(x => 0)\n//│ res: anything -> 0\n\n(let x = 0; 0)\n//│ res: 0\n\n(let x = add; 0)\n//│ res: 0\n\n(let rec x = x; 0)\n//│ res: 0\n\n(let x = 0.u; 0)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u; 0)\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(let x = 0.u; 0)\n//│ ╙──      \t         ^\n//│ res: 0\n\n(let x = add.u; 0)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u; 0)\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(let x = add.u; 0)\n//│ ╙──      \t         ^^^\n//│ res: 0\n\n(let rec x = x.u; 0)\n//│ res: 0\n\n(x => add)\n//│ res: anything -> int -> int -> int\n\n(let x = 0; add)\n//│ res: int -> int -> int\n\n(let x = add; add)\n//│ res: int -> int -> int\n\n(let rec x = x; add)\n//│ res: int -> int -> int\n\n(let x = 0.v; add)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; add)\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; add)\n//│ ╙──      \t         ^\n//│ res: int -> int -> int\n\n(let x = add.v; add)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; add)\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; add)\n//│ ╙──      \t         ^^^\n//│ res: int -> int -> int\n\n(let rec x = x.v; add)\n//│ res: int -> int -> int\n\n(x => x)\n//│ res: 'a -> 'a\n\n(let x = 0; x)\n//│ res: 0\n\n(let x = add; x)\n//│ res: int -> int -> int\n\n(let rec x = x; x)\n//│ res: nothing\n\n(let x = (0 0); x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 0); x)\n//│ ║        \t          ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 0); x)\n//│ ╙──      \t          ^\n//│ res: error\n\n(let x = (0 add); x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 add); x)\n//│ ║        \t          ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 add); x)\n//│ ╙──      \t          ^\n//│ res: error\n\n(let rec x = (0 x); x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (0 x); x)\n//│ ║        \t              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (0 x); x)\n//│ ╙──      \t              ^\n//│ res: error\n\n(let x = 0.u; x)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u; x)\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(let x = 0.u; x)\n//│ ╙──      \t         ^\n//│ res: error\n\n(let x = add.u; x)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u; x)\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(let x = add.u; x)\n//│ ╙──      \t         ^^^\n//│ res: error\n\n(let rec x = x.u; x)\n//│ res: nothing\n\n(let x = {v: 0}.u; x)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: 0}.u; x)\n//│ ║        \t               ^^\n//│ ╟── record of type `{v: 0}` does not have field 'u'\n//│ ║  l.+1: \t(let x = {v: 0}.u; x)\n//│ ╙──      \t         ^^^^^^\n//│ res: error\n\n(let x = {v: add}.u; x)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: add}.u; x)\n//│ ║        \t                 ^^\n//│ ╟── record of type `{v: int -> int -> int}` does not have field 'u'\n//│ ║  l.+1: \t(let x = {v: add}.u; x)\n//│ ╙──      \t         ^^^^^^^^\n//│ res: error\n\n(let rec x = {v: x}.u; x)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = {v: x}.u; x)\n//│ ║        \t                   ^^\n//│ ╟── record of type `{v: ?x}` does not have field 'u'\n//│ ║  l.+1: \t(let rec x = {v: x}.u; x)\n//│ ╙──      \t             ^^^^^^\n//│ res: error\n\n(let x = {u: 0}; x)\n//│ res: {u: 0}\n\n(let x = {u: 0, v: 0}; x)\n//│ res: {u: 0, v: 0}\n\n(let x = {u: 0, v: add}; x)\n//│ res: {u: 0, v: int -> int -> int}\n\n(let rec x = {u: 0, v: x}; x)\n//│ res: 'x\n//│   where\n//│     'x :> {u: 0, v: 'x}\n\n(let x = {u: 0, v: 0.v}; x)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {u: 0, v: 0.v}; x)\n//│ ║        \t                    ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = {u: 0, v: 0.v}; x)\n//│ ╙──      \t                   ^\n//│ res: {u: 0, v: error}\n\n(let x = {u: 0, v: add.v}; x)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {u: 0, v: add.v}; x)\n//│ ║        \t                      ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = {u: 0, v: add.v}; x)\n//│ ╙──      \t                   ^^^\n//│ res: {u: 0, v: error}\n\n(let rec x = {u: 0, v: x.v}; x)\n//│ res: {u: 0, v: nothing}\n\n(let x = {u: add}; x)\n//│ res: {u: int -> int -> int}\n\n(let rec x = {u: x}; x)\n//│ res: 'x\n//│   where\n//│     'x :> {u: 'x}\n\n(x => (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(x => (0 0))\n//│ ║        \t       ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(x => (0 0))\n//│ ╙──      \t       ^\n//│ res: anything -> error\n\n(let x = 0; (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = 0; (0 0))\n//│ ║        \t             ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = 0; (0 0))\n//│ ╙──      \t             ^\n//│ res: error\n\n(let x = add; (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = add; (0 0))\n//│ ║        \t               ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = add; (0 0))\n//│ ╙──      \t               ^\n//│ res: error\n\n(let rec x = x; (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = x; (0 0))\n//│ ║        \t                 ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = x; (0 0))\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let x = (0 0); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 0); (0 0))\n//│ ║        \t          ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 0); (0 0))\n//│ ╙──      \t          ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 0); (0 0))\n//│ ║        \t                 ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 0); (0 0))\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let x = (0 add); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 add); (0 0))\n//│ ║        \t          ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 add); (0 0))\n//│ ╙──      \t          ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 add); (0 0))\n//│ ║        \t                   ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 add); (0 0))\n//│ ╙──      \t                   ^\n//│ res: error\n\n(let rec x = (0 x); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (0 x); (0 0))\n//│ ║        \t              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (0 x); (0 0))\n//│ ╙──      \t              ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (0 x); (0 0))\n//│ ║        \t                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (0 x); (0 0))\n//│ ╙──      \t                     ^\n//│ res: error\n\n(let x = (y => 0); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => 0); (0 0))\n//│ ║        \t                    ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => 0); (0 0))\n//│ ╙──      \t                    ^\n//│ res: error\n\n(let x = (y => add); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => add); (0 0))\n//│ ║        \t                      ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => add); (0 0))\n//│ ╙──      \t                      ^\n//│ res: error\n\n(let x = (y => y); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => y); (0 0))\n//│ ║        \t                    ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => y); (0 0))\n//│ ╙──      \t                    ^\n//│ res: error\n\n(let x = (let y = 0; y); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (let y = 0; y); (0 0))\n//│ ║        \t                          ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (let y = 0; y); (0 0))\n//│ ╙──      \t                          ^\n//│ res: error\n\n(let x = (let y = add; y); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (let y = add; y); (0 0))\n//│ ║        \t                            ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (let y = add; y); (0 0))\n//│ ╙──      \t                            ^\n//│ res: error\n\n(let x = (let rec y = y; y); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (let rec y = y; y); (0 0))\n//│ ║        \t                              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (let rec y = y; y); (0 0))\n//│ ╙──      \t                              ^\n//│ res: error\n\n(let rec x = (let y = x; y); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = x; y); (0 0))\n//│ ║        \t                              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = x; y); (0 0))\n//│ ╙──      \t                              ^\n//│ res: error\n\n(let rec x = (y => x); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (y => x); (0 0))\n//│ ║        \t                        ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (y => x); (0 0))\n//│ ╙──      \t                        ^\n//│ res: error\n\n(let rec x = (let y = 0; x); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = 0; x); (0 0))\n//│ ║        \t                              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = 0; x); (0 0))\n//│ ╙──      \t                              ^\n//│ res: error\n\n(let rec x = (let y = add; x); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = add; x); (0 0))\n//│ ║        \t                                ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = add; x); (0 0))\n//│ ╙──      \t                                ^\n//│ res: error\n\n(let rec x = (let rec y = y; x); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let rec y = y; x); (0 0))\n//│ ║        \t                                  ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let rec y = y; x); (0 0))\n//│ ╙──      \t                                  ^\n//│ res: error\n\n(let rec x = (let y = x; x); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = x; x); (0 0))\n//│ ║        \t                              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = x; x); (0 0))\n//│ ╙──      \t                              ^\n//│ res: error\n\n(let x = (y => (z => 0)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => (z => 0)); (0 0))\n//│ ║        \t                           ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => (z => 0)); (0 0))\n//│ ╙──      \t                           ^\n//│ res: error\n\n(let x = (y => (z => add)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => (z => add)); (0 0))\n//│ ║        \t                             ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => (z => add)); (0 0))\n//│ ╙──      \t                             ^\n//│ res: error\n\n(let x = (y => (z => z)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => (z => z)); (0 0))\n//│ ║        \t                           ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => (z => z)); (0 0))\n//│ ╙──      \t                           ^\n//│ res: error\n\n(let x = (y => (z => y)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => (z => y)); (0 0))\n//│ ║        \t                           ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => (z => y)); (0 0))\n//│ ╙──      \t                           ^\n//│ res: error\n\n(let x = (let y = 0; (z => y)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (let y = 0; (z => y)); (0 0))\n//│ ║        \t                                 ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (let y = 0; (z => y)); (0 0))\n//│ ╙──      \t                                 ^\n//│ res: error\n\n(let x = (let y = add; (z => y)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (let y = add; (z => y)); (0 0))\n//│ ║        \t                                   ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (let y = add; (z => y)); (0 0))\n//│ ╙──      \t                                   ^\n//│ res: error\n\n(let x = (let rec y = y; (z => y)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (let rec y = y; (z => y)); (0 0))\n//│ ║        \t                                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (let rec y = y; (z => y)); (0 0))\n//│ ╙──      \t                                     ^\n//│ res: error\n\n(let rec x = (let y = x; (z => y)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = x; (z => y)); (0 0))\n//│ ║        \t                                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = x; (z => y)); (0 0))\n//│ ╙──      \t                                     ^\n//│ res: error\n\n(let rec x = (y => (z => x)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (y => (z => x)); (0 0))\n//│ ║        \t                               ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (y => (z => x)); (0 0))\n//│ ╙──      \t                               ^\n//│ res: error\n\n(let rec x = (let y = 0; (z => x)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = 0; (z => x)); (0 0))\n//│ ║        \t                                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = 0; (z => x)); (0 0))\n//│ ╙──      \t                                     ^\n//│ res: error\n\n(let rec x = (let y = add; (z => x)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = add; (z => x)); (0 0))\n//│ ║        \t                                       ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = add; (z => x)); (0 0))\n//│ ╙──      \t                                       ^\n//│ res: error\n\n(let rec x = (let rec y = y; (z => x)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let rec y = y; (z => x)); (0 0))\n//│ ║        \t                                         ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let rec y = y; (z => x)); (0 0))\n//│ ╙──      \t                                         ^\n//│ res: error\n\n(let rec x = (let y = x; (z => x)); (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = x; (z => x)); (0 0))\n//│ ║        \t                                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = x; (z => x)); (0 0))\n//│ ╙──      \t                                     ^\n//│ res: error\n\n(let x = {u: 0}; (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {u: 0}; (0 0))\n//│ ║        \t                  ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {u: 0}; (0 0))\n//│ ╙──      \t                  ^\n//│ res: error\n\n(let x = {u: add}; (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {u: add}; (0 0))\n//│ ║        \t                    ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {u: add}; (0 0))\n//│ ╙──      \t                    ^\n//│ res: error\n\n(let rec x = {u: x}; (0 0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = {u: x}; (0 0))\n//│ ║        \t                      ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = {u: x}; (0 0))\n//│ ╙──      \t                      ^\n//│ res: error\n\n(x => (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(x => (0 add))\n//│ ║        \t       ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(x => (0 add))\n//│ ╙──      \t       ^\n//│ res: anything -> error\n\n(let x = 0; (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = 0; (0 add))\n//│ ║        \t             ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = 0; (0 add))\n//│ ╙──      \t             ^\n//│ res: error\n\n(let x = add; (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = add; (0 add))\n//│ ║        \t               ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = add; (0 add))\n//│ ╙──      \t               ^\n//│ res: error\n\n(let rec x = x; (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = x; (0 add))\n//│ ║        \t                 ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = x; (0 add))\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let x = 0.v; (0 add))\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; (0 add))\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; (0 add))\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = 0.v; (0 add))\n//│ ║        \t               ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = 0.v; (0 add))\n//│ ╙──      \t               ^\n//│ res: error\n\n(let x = add.v; (0 add))\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; (0 add))\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; (0 add))\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = add.v; (0 add))\n//│ ║        \t                 ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = add.v; (0 add))\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let rec x = x.v; (0 add))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = x.v; (0 add))\n//│ ║        \t                   ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = x.v; (0 add))\n//│ ╙──      \t                   ^\n//│ res: error\n\n(x => (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(x => (0 x))\n//│ ║        \t       ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(x => (0 x))\n//│ ╙──      \t       ^\n//│ res: anything -> error\n\n(let x = 0; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = 0; (0 x))\n//│ ║        \t             ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = 0; (0 x))\n//│ ╙──      \t             ^\n//│ res: error\n\n(let x = add; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = add; (0 x))\n//│ ║        \t               ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = add; (0 x))\n//│ ╙──      \t               ^\n//│ res: error\n\n(let rec x = x; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = x; (0 x))\n//│ ║        \t                 ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = x; (0 x))\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let x = (0 0); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 0); (0 x))\n//│ ║        \t          ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 0); (0 x))\n//│ ╙──      \t          ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 0); (0 x))\n//│ ║        \t                 ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 0); (0 x))\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let x = (0 add); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 add); (0 x))\n//│ ║        \t          ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 add); (0 x))\n//│ ╙──      \t          ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 add); (0 x))\n//│ ║        \t                   ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 add); (0 x))\n//│ ╙──      \t                   ^\n//│ res: error\n\n(let rec x = (0 x); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (0 x); (0 x))\n//│ ║        \t              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (0 x); (0 x))\n//│ ╙──      \t              ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (0 x); (0 x))\n//│ ║        \t                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (0 x); (0 x))\n//│ ╙──      \t                     ^\n//│ res: error\n\n(let x = (add 0); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (add 0); (0 x))\n//│ ║        \t                   ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (add 0); (0 x))\n//│ ╙──      \t                   ^\n//│ res: error\n\n(let x = (add add); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (add add); (0 x))\n//│ ║        \t          ^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t(let x = (add add); (0 x))\n//│ ╙──      \t              ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (add add); (0 x))\n//│ ║        \t                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (add add); (0 x))\n//│ ╙──      \t                     ^\n//│ res: error\n\n(let rec x = (add x); (0 x))\n//│ ╔══[ERROR] Type mismatch in binding of application:\n//│ ║  l.+1: \t(let rec x = (add x); (0 x))\n//│ ║        \t             ^^^^^^^\n//│ ╟── application of type `int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t(let rec x = (add x); (0 x))\n//│ ║        \t              ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.+1: \t(let rec x = (add x); (0 x))\n//│ ╙──      \t                  ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (add x); (0 x))\n//│ ║        \t                       ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (add x); (0 x))\n//│ ╙──      \t                       ^\n//│ res: error\n\n(let rec x = (x 0); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (x 0); (0 x))\n//│ ║        \t                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (x 0); (0 x))\n//│ ╙──      \t                     ^\n//│ res: error\n\n(let rec x = (x add); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (x add); (0 x))\n//│ ║        \t                       ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (x add); (0 x))\n//│ ╙──      \t                       ^\n//│ res: error\n\n(let rec x = (x x); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (x x); (0 x))\n//│ ║        \t                     ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (x x); (0 x))\n//│ ╙──      \t                     ^\n//│ res: error\n\n(let x = (y => 0); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => 0); (0 x))\n//│ ║        \t                    ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => 0); (0 x))\n//│ ╙──      \t                    ^\n//│ res: error\n\n(let x = (y => add); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => add); (0 x))\n//│ ║        \t                      ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => add); (0 x))\n//│ ╙──      \t                      ^\n//│ res: error\n\n(let x = (y => y); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (y => y); (0 x))\n//│ ║        \t                    ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (y => y); (0 x))\n//│ ╙──      \t                    ^\n//│ res: error\n\n(let rec x = (y => x); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (y => x); (0 x))\n//│ ║        \t                        ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (y => x); (0 x))\n//│ ╙──      \t                        ^\n//│ res: error\n\n(let rec x = (let y = 0; x); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = 0; x); (0 x))\n//│ ║        \t                              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = 0; x); (0 x))\n//│ ╙──      \t                              ^\n//│ res: error\n\n(let rec x = (let y = add; x); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = add; x); (0 x))\n//│ ║        \t                                ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = add; x); (0 x))\n//│ ╙──      \t                                ^\n//│ res: error\n\n(let rec x = (let rec y = y; x); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let rec y = y; x); (0 x))\n//│ ║        \t                                  ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let rec y = y; x); (0 x))\n//│ ╙──      \t                                  ^\n//│ res: error\n\n(let rec x = (let y = x; x); (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (let y = x; x); (0 x))\n//│ ║        \t                              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (let y = x; x); (0 x))\n//│ ╙──      \t                              ^\n//│ res: error\n\n(let x = {u: 0}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {u: 0}; (0 x))\n//│ ║        \t                  ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {u: 0}; (0 x))\n//│ ╙──      \t                  ^\n//│ res: error\n\n(let x = {u: add}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {u: add}; (0 x))\n//│ ║        \t                    ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {u: add}; (0 x))\n//│ ╙──      \t                    ^\n//│ res: error\n\n(let x = {u: add, v: 0}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {u: add, v: 0}; (0 x))\n//│ ║        \t                          ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {u: add, v: 0}; (0 x))\n//│ ╙──      \t                          ^\n//│ res: error\n\n(let x = {u: add, v: add}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {u: add, v: add}; (0 x))\n//│ ║        \t                            ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {u: add, v: add}; (0 x))\n//│ ╙──      \t                            ^\n//│ res: error\n\n(let rec x = {u: add, v: x}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = {u: add, v: x}; (0 x))\n//│ ║        \t                              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = {u: add, v: x}; (0 x))\n//│ ╙──      \t                              ^\n//│ res: error\n\n(let rec x = {u: x}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = {u: x}; (0 x))\n//│ ║        \t                      ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = {u: x}; (0 x))\n//│ ╙──      \t                      ^\n//│ res: error\n\n(let x = 0.v; (0 x))\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; (0 x))\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; (0 x))\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = 0.v; (0 x))\n//│ ║        \t               ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = 0.v; (0 x))\n//│ ╙──      \t               ^\n//│ res: error\n\n(let x = add.v; (0 x))\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; (0 x))\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; (0 x))\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = add.v; (0 x))\n//│ ║        \t                 ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = add.v; (0 x))\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let rec x = x.v; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = x.v; (0 x))\n//│ ║        \t                   ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = x.v; (0 x))\n//│ ╙──      \t                   ^\n//│ res: error\n\n(let x = {v: 0}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {v: 0}; (0 x))\n//│ ║        \t                  ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {v: 0}; (0 x))\n//│ ╙──      \t                  ^\n//│ res: error\n\n(let x = {v: add}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = {v: add}; (0 x))\n//│ ║        \t                    ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = {v: add}; (0 x))\n//│ ╙──      \t                    ^\n//│ res: error\n\n(let rec x = {v: x}; (0 x))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = {v: x}; (0 x))\n//│ ║        \t                      ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = {v: x}; (0 x))\n//│ ╙──      \t                      ^\n//│ res: error\n\n(x => {u: 0})\n//│ res: anything -> {u: 0}\n\n(let x = 0; {u: 0})\n//│ res: {u: 0}\n\n(let x = add; {u: 0})\n//│ res: {u: 0}\n\n(let rec x = x; {u: 0})\n//│ res: {u: 0}\n\n(let x = (0 0); {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 0); {u: 0})\n//│ ║        \t          ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 0); {u: 0})\n//│ ╙──      \t          ^\n//│ res: {u: 0}\n\n(let x = (0 add); {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 add); {u: 0})\n//│ ║        \t          ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 add); {u: 0})\n//│ ╙──      \t          ^\n//│ res: {u: 0}\n\n(let rec x = (0 x); {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (0 x); {u: 0})\n//│ ║        \t              ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (0 x); {u: 0})\n//│ ╙──      \t              ^\n//│ res: {u: 0}\n\n(let x = (0 {v: 0}); {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 {v: 0}); {u: 0})\n//│ ║        \t          ^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 {v: 0}); {u: 0})\n//│ ╙──      \t          ^\n//│ res: {u: 0}\n\n(let x = (0 {v: add}); {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (0 {v: add}); {u: 0})\n//│ ║        \t          ^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let x = (0 {v: add}); {u: 0})\n//│ ╙──      \t          ^\n//│ res: {u: 0}\n\n(let rec x = (0 {v: x}); {u: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let rec x = (0 {v: x}); {u: 0})\n//│ ║        \t              ^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t(let rec x = (0 {v: x}); {u: 0})\n//│ ╙──      \t              ^\n//│ res: {u: 0}\n\n(let x = 0.u; {u: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u; {u: 0})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(let x = 0.u; {u: 0})\n//│ ╙──      \t         ^\n//│ res: {u: 0}\n\n(let x = add.u; {u: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u; {u: 0})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(let x = add.u; {u: 0})\n//│ ╙──      \t         ^^^\n//│ res: {u: 0}\n\n(let rec x = x.u; {u: 0})\n//│ res: {u: 0}\n\n(let x = 0.u.u; {u: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u.u; {u: 0})\n//│ ║        \t            ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(let x = 0.u.u; {u: 0})\n//│ ╙──      \t         ^\n//│ res: {u: 0}\n\n(let x = add.u.u; {u: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u.u; {u: 0})\n//│ ║        \t              ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(let x = add.u.u; {u: 0})\n//│ ╙──      \t         ^^^\n//│ res: {u: 0}\n\n(let rec x = x.u.u; {u: 0})\n//│ res: {u: 0}\n\n(x => {u: 0, v: 0})\n//│ res: anything -> {u: 0, v: 0}\n\n(let x = 0; {u: 0, v: 0})\n//│ res: {u: 0, v: 0}\n\n(let x = add; {u: 0, v: 0})\n//│ res: {u: 0, v: 0}\n\n(let rec x = x; {u: 0, v: 0})\n//│ res: {u: 0, v: 0}\n\n(let x = (add 0); {u: 0, v: 0})\n//│ res: {u: 0, v: 0}\n\n(let x = (add add); {u: 0, v: 0})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t(let x = (add add); {u: 0, v: 0})\n//│ ║        \t          ^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t(let x = (add add); {u: 0, v: 0})\n//│ ╙──      \t              ^^^\n//│ res: {u: 0, v: 0}\n\n(let rec x = (add x); {u: 0, v: 0})\n//│ ╔══[ERROR] Type mismatch in binding of application:\n//│ ║  l.+1: \t(let rec x = (add x); {u: 0, v: 0})\n//│ ║        \t             ^^^^^^^\n//│ ╟── application of type `int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t(let rec x = (add x); {u: 0, v: 0})\n//│ ║        \t              ^^^^^\n//│ ╟── Note: constraint arises from argument:\n//│ ║  l.+1: \t(let rec x = (add x); {u: 0, v: 0})\n//│ ╙──      \t                  ^\n//│ res: {u: 0, v: 0}\n\n(let x = 0.u; {u: 0, v: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u; {u: 0, v: 0})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(let x = 0.u; {u: 0, v: 0})\n//│ ╙──      \t         ^\n//│ res: {u: 0, v: 0}\n\n(let x = add.u; {u: 0, v: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u; {u: 0, v: 0})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(let x = add.u; {u: 0, v: 0})\n//│ ╙──      \t         ^^^\n//│ res: {u: 0, v: 0}\n\n(let rec x = x.u; {u: 0, v: 0})\n//│ res: {u: 0, v: 0}\n\n(x => {u: 0, v: add})\n//│ res: anything -> {u: 0, v: int -> int -> int}\n\n(let x = 0; {u: 0, v: add})\n//│ res: {u: 0, v: int -> int -> int}\n\n(let x = add; {u: 0, v: add})\n//│ res: {u: 0, v: int -> int -> int}\n\n(let rec x = x; {u: 0, v: add})\n//│ res: {u: 0, v: int -> int -> int}\n\n(x => {u: 0, v: x})\n//│ res: 'a -> {u: 0, v: 'a}\n\n(let x = 0; {u: 0, v: x})\n//│ res: {u: 0, v: 0}\n\n(let x = add; {u: 0, v: x})\n//│ res: {u: 0, v: int -> int -> int}\n\n(let rec x = x; {u: 0, v: x})\n//│ res: {u: 0, v: nothing}\n\n(let rec x = (x 0); {u: 0, v: x})\n//│ res: {u: 0, v: nothing}\n\n(let rec x = (x add); {u: 0, v: x})\n//│ res: {u: 0, v: nothing}\n\n(let rec x = (x x); {u: 0, v: x})\n//│ res: {u: 0, v: nothing}\n\n(x => {u: add})\n//│ res: anything -> {u: int -> int -> int}\n\n(let x = 0; {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = add; {u: add})\n//│ res: {u: int -> int -> int}\n\n(let rec x = x; {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = (y => 0); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = (let y = 0; 0); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = (let y = add; 0); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = (let rec y = y; 0); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let rec x = (let y = x; 0); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = (y => add); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = (y => y); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let rec x = (y => x); {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = 0.v; {u: add})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; {u: add})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; {u: add})\n//│ ╙──      \t         ^\n//│ res: {u: int -> int -> int}\n\n(let x = add.v; {u: add})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; {u: add})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; {u: add})\n//│ ╙──      \t         ^^^\n//│ res: {u: int -> int -> int}\n\n(let rec x = x.v; {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = {v: 0}; {u: add})\n//│ res: {u: int -> int -> int}\n\n(let x = {v: add}; {u: add})\n//│ res: {u: int -> int -> int}\n\n(let rec x = {v: x}; {u: add})\n//│ res: {u: int -> int -> int}\n\n(x => {u: x})\n//│ res: 'a -> {u: 'a}\n\n(let x = 0; {u: x})\n//│ res: {u: 0}\n\n(let x = add; {u: x})\n//│ res: {u: int -> int -> int}\n\n(let rec x = x; {u: x})\n//│ res: {u: nothing}\n\n(let x = {v: 0}; {u: x})\n//│ res: {u: {v: 0}}\n\n(let x = {v: add}; {u: x})\n//│ res: {u: {v: int -> int -> int}}\n\n(let rec x = {v: x}; {u: x})\n//│ res: {u: forall 'x. 'x}\n//│   where\n//│     'x :> {v: 'x}\n\n(x => {u: x, v: 0})\n//│ res: 'a -> {u: 'a, v: 0}\n\n(let x = 0; {u: x, v: 0})\n//│ res: {u: 0, v: 0}\n\n(let x = add; {u: x, v: 0})\n//│ res: {u: int -> int -> int, v: 0}\n\n(let rec x = x; {u: x, v: 0})\n//│ res: {u: nothing, v: 0}\n\n(let x = 0.v; {u: x, v: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; {u: x, v: 0})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; {u: x, v: 0})\n//│ ╙──      \t         ^\n//│ res: {u: error, v: 0}\n\n(let x = add.v; {u: x, v: 0})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; {u: x, v: 0})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; {u: x, v: 0})\n//│ ╙──      \t         ^^^\n//│ res: {u: error, v: 0}\n\n(let rec x = x.v; {u: x, v: 0})\n//│ res: {u: nothing, v: 0}\n\n(x => {u: x, v: add})\n//│ res: 'a -> {u: 'a, v: int -> int -> int}\n\n(let x = 0; {u: x, v: add})\n//│ res: {u: 0, v: int -> int -> int}\n\n(let x = add; {u: x, v: add})\n//│ res: {u: int -> int -> int, v: int -> int -> int}\n\n(let rec x = x; {u: x, v: add})\n//│ res: {u: nothing, v: int -> int -> int}\n\n(let x = 0.u; {u: x, v: add})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u; {u: x, v: add})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(let x = 0.u; {u: x, v: add})\n//│ ╙──      \t         ^\n//│ res: {u: error, v: int -> int -> int}\n\n(let x = add.u; {u: x, v: add})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u; {u: x, v: add})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(let x = add.u; {u: x, v: add})\n//│ ╙──      \t         ^^^\n//│ res: {u: error, v: int -> int -> int}\n\n(let rec x = x.u; {u: x, v: add})\n//│ res: {u: nothing, v: int -> int -> int}\n\n(let x = 0.v; {u: x, v: add})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; {u: x, v: add})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; {u: x, v: add})\n//│ ╙──      \t         ^\n//│ res: {u: error, v: int -> int -> int}\n\n(let x = add.v; {u: x, v: add})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; {u: x, v: add})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; {u: x, v: add})\n//│ ╙──      \t         ^^^\n//│ res: {u: error, v: int -> int -> int}\n\n(let rec x = x.v; {u: x, v: add})\n//│ res: {u: nothing, v: int -> int -> int}\n\n(x => {u: x, v: x})\n//│ res: 'a -> {u: 'a, v: 'a}\n\n(let x = 0; {u: x, v: x})\n//│ res: {u: 0, v: 0}\n\n(let x = add; {u: x, v: x})\n//│ res: {u: int -> int -> int, v: int -> int -> int}\n\n(let rec x = x; {u: x, v: x})\n//│ res: {u: nothing, v: nothing}\n\n(let x = {u: 0}; {u: x, v: x})\n//│ res: {u: {u: 0}, v: {u: 0}}\n\n(let x = {u: add}; {u: x, v: x})\n//│ res: {u: {u: int -> int -> int}, v: {u: int -> int -> int}}\n\n(let rec x = {u: x}; {u: x, v: x})\n//│ res: {u: forall 'x. 'x, v: forall 'x. 'x}\n//│   where\n//│     'x :> {u: 'x}\n\n(let rec x = {u: x, v: 0}; {u: x, v: x})\n//│ res: {u: forall 'x. 'x, v: forall 'x. 'x}\n//│   where\n//│     'x :> {u: 'x, v: 0}\n\n(let rec x = {u: x, v: add}; {u: x, v: x})\n//│ res: {u: forall 'x. 'x, v: forall 'x. 'x}\n//│   where\n//│     'x :> {u: 'x, v: int -> int -> int}\n\n(let rec x = {u: x, v: x}; {u: x, v: x})\n//│ res: {u: forall 'x. 'x, v: forall 'x. 'x}\n//│   where\n//│     'x :> {u: 'x, v: 'x}\n\n(let x = {v: 0}; {u: x, v: x})\n//│ res: {u: {v: 0}, v: {v: 0}}\n\n(let x = {v: add}; {u: x, v: x})\n//│ res: {u: {v: int -> int -> int}, v: {v: int -> int -> int}}\n\n(let rec x = {v: x}; {u: x, v: x})\n//│ res: {u: forall 'x. 'x, v: forall 'x. 'x}\n//│   where\n//│     'x :> {v: 'x}\n\n(x => {u: 0.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(x => {u: 0.v})\n//│ ║        \t           ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(x => {u: 0.v})\n//│ ╙──      \t          ^\n//│ res: anything -> {u: error}\n\n(let x = 0; {u: 0.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0; {u: 0.v})\n//│ ║        \t                 ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0; {u: 0.v})\n//│ ╙──      \t                ^\n//│ res: {u: error}\n\n(let x = add; {u: 0.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add; {u: 0.v})\n//│ ║        \t                   ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = add; {u: 0.v})\n//│ ╙──      \t                  ^\n//│ res: {u: error}\n\n(let rec x = x; {u: 0.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = x; {u: 0.v})\n//│ ║        \t                     ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = x; {u: 0.v})\n//│ ╙──      \t                    ^\n//│ res: {u: error}\n\n(x => {u: add.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(x => {u: add.v})\n//│ ║        \t             ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(x => {u: add.v})\n//│ ╙──      \t          ^^^\n//│ res: anything -> {u: error}\n\n(let x = 0; {u: add.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0; {u: add.v})\n//│ ║        \t                   ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0; {u: add.v})\n//│ ╙──      \t                ^^^\n//│ res: {u: error}\n\n(let x = add; {u: add.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add; {u: add.v})\n//│ ║        \t                     ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add; {u: add.v})\n//│ ╙──      \t                  ^^^\n//│ res: {u: error}\n\n(let rec x = x; {u: add.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = x; {u: add.v})\n//│ ║        \t                       ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = x; {u: add.v})\n//│ ╙──      \t                    ^^^\n//│ res: {u: error}\n\n(x => {u: x.v})\n//│ res: {v: 'v} -> {u: 'v}\n\n(let x = 0; {u: x.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0; {u: x.v})\n//│ ║        \t                 ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0; {u: x.v})\n//│ ║        \t         ^\n//│ ╟── but it flows into reference with expected type `{v: ?v}`\n//│ ║  l.+1: \t(let x = 0; {u: x.v})\n//│ ╙──      \t                ^\n//│ res: {u: error}\n\n(let x = add; {u: x.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add; {u: x.v})\n//│ ║        \t                   ^^\n//│ ╟── reference of type `int -> int -> int` does not match type `{v: ?v}`\n//│ ║  l.+1: \t(let x = add; {u: x.v})\n//│ ║        \t         ^^^\n//│ ╟── but it flows into reference with expected type `{v: ?v}`\n//│ ║  l.+1: \t(let x = add; {u: x.v})\n//│ ╙──      \t                  ^\n//│ res: {u: error}\n\n(let rec x = x; {u: x.v})\n//│ res: {u: nothing}\n\n(let x = 0.v; {u: x.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; {u: x.v})\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; {u: x.v})\n//│ ╙──      \t         ^\n//│ res: {u: error}\n\n(let x = add.v; {u: x.v})\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; {u: x.v})\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; {u: x.v})\n//│ ╙──      \t         ^^^\n//│ res: {u: error}\n\n(let rec x = x.v; {u: x.v})\n//│ res: {u: nothing}\n\n(let x = {v: 0}; {u: x.v})\n//│ res: {u: 0}\n\n(let x = {v: add}; {u: x.v})\n//│ res: {u: int -> int -> int}\n\n(let rec x = {v: x}; {u: x.v})\n//│ res: {u: 'x}\n//│   where\n//│     'x :> {v: 'x}\n\n(let x = {v: (y => 0)}; {u: x.v})\n//│ res: {u: anything -> 0}\n\n(let x = {v: (y => add)}; {u: x.v})\n//│ res: {u: anything -> int -> int -> int}\n\n(let x = {v: (y => y)}; {u: x.v})\n//│ res: {u: forall 'a. 'a -> 'a}\n\n(let rec x = {v: (y => x)}; {u: x.v})\n//│ res: {u: anything -> 'x}\n//│   where\n//│     'x :> {v: anything -> 'x}\n\n(x => 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(x => 0.v)\n//│ ║        \t       ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(x => 0.v)\n//│ ╙──      \t      ^\n//│ res: anything -> error\n\n(let x = 0; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0; 0.v)\n//│ ║        \t             ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0; 0.v)\n//│ ╙──      \t            ^\n//│ res: error\n\n(let x = add; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add; 0.v)\n//│ ║        \t               ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = add; 0.v)\n//│ ╙──      \t              ^\n//│ res: error\n\n(let rec x = x; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = x; 0.v)\n//│ ║        \t                 ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = x; 0.v)\n//│ ╙──      \t                ^\n//│ res: error\n\n(let x = 0.u; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u; 0.v)\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t(let x = 0.u; 0.v)\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.u; 0.v)\n//│ ║        \t               ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.u; 0.v)\n//│ ╙──      \t              ^\n//│ res: error\n\n(let x = add.u; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u; 0.v)\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t(let x = add.u; 0.v)\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.u; 0.v)\n//│ ║        \t                 ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.u; 0.v)\n//│ ╙──      \t                ^\n//│ res: error\n\n(let rec x = x.u; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = x.u; 0.v)\n//│ ║        \t                   ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = x.u; 0.v)\n//│ ╙──      \t                  ^\n//│ res: error\n\n(let x = 0.v; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; 0.v)\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; 0.v)\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; 0.v)\n//│ ║        \t               ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; 0.v)\n//│ ╙──      \t              ^\n//│ res: error\n\n(let x = add.v; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; 0.v)\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; 0.v)\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; 0.v)\n//│ ║        \t                 ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; 0.v)\n//│ ╙──      \t                ^\n//│ res: error\n\n(let rec x = x.v; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = x.v; 0.v)\n//│ ║        \t                   ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = x.v; 0.v)\n//│ ╙──      \t                  ^\n//│ res: error\n\n(let x = {v: 0}; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: 0}; 0.v)\n//│ ║        \t                  ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = {v: 0}; 0.v)\n//│ ╙──      \t                 ^\n//│ res: error\n\n(let x = {v: add}; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: add}; 0.v)\n//│ ║        \t                    ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = {v: add}; 0.v)\n//│ ╙──      \t                   ^\n//│ res: error\n\n(let rec x = {v: x}; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = {v: x}; 0.v)\n//│ ║        \t                      ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = {v: x}; 0.v)\n//│ ╙──      \t                     ^\n//│ res: error\n\n(let x = {v: 0.v}; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: 0.v}; 0.v)\n//│ ║        \t              ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = {v: 0.v}; 0.v)\n//│ ╙──      \t             ^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: 0.v}; 0.v)\n//│ ║        \t                    ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = {v: 0.v}; 0.v)\n//│ ╙──      \t                   ^\n//│ res: error\n\n(let x = {v: add.v}; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: add.v}; 0.v)\n//│ ║        \t                ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = {v: add.v}; 0.v)\n//│ ╙──      \t             ^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {v: add.v}; 0.v)\n//│ ║        \t                      ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = {v: add.v}; 0.v)\n//│ ╙──      \t                     ^\n//│ res: error\n\n(let rec x = {v: x.v}; 0.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = {v: x.v}; 0.v)\n//│ ║        \t                        ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = {v: x.v}; 0.v)\n//│ ╙──      \t                       ^\n//│ res: error\n\n(x => add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(x => add.v)\n//│ ║        \t         ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(x => add.v)\n//│ ╙──      \t      ^^^\n//│ res: anything -> error\n\n(let x = 0; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0; add.v)\n//│ ║        \t               ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0; add.v)\n//│ ╙──      \t            ^^^\n//│ res: error\n\n(let x = add; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add; add.v)\n//│ ║        \t                 ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add; add.v)\n//│ ╙──      \t              ^^^\n//│ res: error\n\n(let rec x = x; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = x; add.v)\n//│ ║        \t                   ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = x; add.v)\n//│ ╙──      \t                ^^^\n//│ res: error\n\n(let x = {u: 0}; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {u: 0}; add.v)\n//│ ║        \t                    ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = {u: 0}; add.v)\n//│ ╙──      \t                 ^^^\n//│ res: error\n\n(let x = {u: add}; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {u: add}; add.v)\n//│ ║        \t                      ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = {u: add}; add.v)\n//│ ╙──      \t                   ^^^\n//│ res: error\n\n(let rec x = {u: x}; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = {u: x}; add.v)\n//│ ║        \t                        ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = {u: x}; add.v)\n//│ ╙──      \t                     ^^^\n//│ res: error\n\n(let x = {u: {v: 0}}; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {u: {v: 0}}; add.v)\n//│ ║        \t                         ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = {u: {v: 0}}; add.v)\n//│ ╙──      \t                      ^^^\n//│ res: error\n\n(let x = {u: {v: add}}; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = {u: {v: add}}; add.v)\n//│ ║        \t                           ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = {u: {v: add}}; add.v)\n//│ ╙──      \t                        ^^^\n//│ res: error\n\n(let rec x = {u: {v: x}}; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = {u: {v: x}}; add.v)\n//│ ║        \t                             ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = {u: {v: x}}; add.v)\n//│ ╙──      \t                          ^^^\n//│ res: error\n\n(let x = 0.v; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; add.v)\n//│ ║        \t          ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; add.v)\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0.v; add.v)\n//│ ║        \t                 ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0.v; add.v)\n//│ ╙──      \t              ^^^\n//│ res: error\n\n(let x = add.v; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; add.v)\n//│ ║        \t            ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; add.v)\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add.v; add.v)\n//│ ║        \t                   ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let x = add.v; add.v)\n//│ ╙──      \t                ^^^\n//│ res: error\n\n(let rec x = x.v; add.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let rec x = x.v; add.v)\n//│ ║        \t                     ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t(let rec x = x.v; add.v)\n//│ ╙──      \t                  ^^^\n//│ res: error\n\n(x => x.v)\n//│ res: {v: 'v} -> 'v\n\n(let x = 0; x.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = 0; x.v)\n//│ ║        \t             ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t(let x = 0; x.v)\n//│ ║        \t         ^\n//│ ╟── but it flows into reference with expected type `{v: ?v}`\n//│ ║  l.+1: \t(let x = 0; x.v)\n//│ ╙──      \t            ^\n//│ res: error\n\n(let x = add; x.v)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t(let x = add; x.v)\n//│ ║        \t               ^^\n//│ ╟── reference of type `int -> int -> int` does not match type `{v: ?v}`\n//│ ║  l.+1: \t(let x = add; x.v)\n//│ ║        \t         ^^^\n//│ ╟── but it flows into reference with expected type `{v: ?v}`\n//│ ║  l.+1: \t(let x = add; x.v)\n//│ ╙──      \t              ^\n//│ res: error\n\n(let rec x = x; x.v)\n//│ res: nothing\n\n(let x = {v: 0}; x.v)\n//│ res: 0\n\n(let x = {v: add}; x.v)\n//│ res: int -> int -> int\n\n(let rec x = {v: x}; x.v)\n//│ res: 'x\n//│   where\n//│     'x :> {v: 'x}\n\n(let x = {v: {v: 0}}; x.v)\n//│ res: {v: 0}\n\n(let x = {v: {v: add}}; x.v)\n//│ res: {v: int -> int -> int}\n\n(let rec x = {v: {v: x}}; x.v)\n//│ res: {v: 'x}\n//│   where\n//│     'x :> {v: {v: 'x}}\n\n0.u\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t0.u\n//│ ║        \t ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t0.u\n//│ ╙──      \t^\n//│ res: error\n\nadd.u\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \tadd.u\n//│ ║        \t   ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \tadd.u\n//│ ╙──      \t^^^\n//│ res: error\n\n0.v.u\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t0.v.u\n//│ ║        \t   ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t0.v.u\n//│ ╙──      \t^\n//│ res: error\n\nadd.v.u\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \tadd.v.u\n//│ ║        \t     ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \tadd.v.u\n//│ ╙──      \t^^^\n//│ res: error\n\n{v: 0}.u\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{v: 0}.u\n//│ ║        \t      ^^\n//│ ╟── record of type `{v: 0}` does not have field 'u'\n//│ ║  l.+1: \t{v: 0}.u\n//│ ╙──      \t^^^^^^\n//│ res: error\n\n{v: add}.u\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{v: add}.u\n//│ ║        \t        ^^\n//│ ╟── record of type `{v: int -> int -> int}` does not have field 'u'\n//│ ║  l.+1: \t{v: add}.u\n//│ ╙──      \t^^^^^^^^\n//│ res: error\n\n{u: 0}\n//│ res: {u: 0}\n\n{u: 0, v: 0}\n//│ res: {u: 0, v: 0}\n\n{u: 0, v: add}\n//│ res: {u: 0, v: int -> int -> int}\n\n{u: 0, v: (x => 0)}\n//│ res: {u: 0, v: anything -> 0}\n\n{u: 0, v: (let x = 0; 0)}\n//│ res: {u: 0, v: 0}\n\n{u: 0, v: (let x = add; 0)}\n//│ res: {u: 0, v: 0}\n\n{u: 0, v: (let rec x = x; 0)}\n//│ res: {u: 0, v: 0}\n\n{u: 0, v: (let x = 0.u; 0)}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: 0, v: (let x = 0.u; 0)}\n//│ ║        \t                    ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t{u: 0, v: (let x = 0.u; 0)}\n//│ ╙──      \t                   ^\n//│ res: {u: 0, v: 0}\n\n{u: 0, v: (let x = add.u; 0)}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: 0, v: (let x = add.u; 0)}\n//│ ║        \t                      ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t{u: 0, v: (let x = add.u; 0)}\n//│ ╙──      \t                   ^^^\n//│ res: {u: 0, v: 0}\n\n{u: 0, v: (let rec x = x.u; 0)}\n//│ res: {u: 0, v: 0}\n\n{u: 0, v: (x => add)}\n//│ res: {u: 0, v: anything -> int -> int -> int}\n\n{u: 0, v: (x => x)}\n//│ res: {u: 0, v: forall 'a. 'a -> 'a}\n\n{u: 0, v: {u: 0}}\n//│ res: {u: 0, v: {u: 0}}\n\n{u: 0, v: {u: 0, v: 0}}\n//│ res: {u: 0, v: {u: 0, v: 0}}\n\n{u: 0, v: {u: 0, v: add}}\n//│ res: {u: 0, v: {u: 0, v: int -> int -> int}}\n\n{u: 0, v: {u: add}}\n//│ res: {u: 0, v: {u: int -> int -> int}}\n\n{u: 0, v: {v: 0}}\n//│ res: {u: 0, v: {v: 0}}\n\n{u: 0, v: {v: add}}\n//│ res: {u: 0, v: {v: int -> int -> int}}\n\n{u: add}\n//│ res: {u: int -> int -> int}\n\n{u: add, v: 0}\n//│ res: {u: int -> int -> int, v: 0}\n\n{u: add, v: add}\n//│ res: {u: int -> int -> int, v: int -> int -> int}\n\n{u: add, v: {u: 0}}\n//│ res: {u: int -> int -> int, v: {u: 0}}\n\n{u: add, v: {u: add}}\n//│ res: {u: int -> int -> int, v: {u: int -> int -> int}}\n\n{u: add, v: {u: add, v: 0}}\n//│ res: {u: int -> int -> int, v: {u: int -> int -> int, v: 0}}\n\n{u: add, v: {u: add, v: add}}\n//│ res: {u: int -> int -> int, v: {u: int -> int -> int, v: int -> int -> int}}\n\n{u: add, v: {u: (x => 0)}}\n//│ res: {u: int -> int -> int, v: {u: anything -> 0}}\n\n{u: add, v: {u: (x => add)}}\n//│ res: {u: int -> int -> int, v: {u: anything -> int -> int -> int}}\n\n{u: add, v: {u: (x => add), v: 0}}\n//│ res: {u: int -> int -> int, v: {u: anything -> int -> int -> int, v: 0}}\n\n{u: add, v: {u: (x => add), v: add}}\n//│ res: {u: int -> int -> int, v: {u: anything -> int -> int -> int, v: int -> int -> int}}\n\n{u: add, v: {u: (x => x)}}\n//│ res: {u: int -> int -> int, v: {u: forall 'a. 'a -> 'a}}\n\n{u: add, v: {u: {v: 0}}}\n//│ res: {u: int -> int -> int, v: {u: {v: 0}}}\n\n{u: add, v: {u: {v: add}}}\n//│ res: {u: int -> int -> int, v: {u: {v: int -> int -> int}}}\n\n{u: add, v: 0.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: add, v: 0.v}\n//│ ║        \t             ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t{u: add, v: 0.v}\n//│ ╙──      \t            ^\n//│ res: {u: int -> int -> int, v: error}\n\n{u: add, v: add.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: add, v: add.v}\n//│ ║        \t               ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t{u: add, v: add.v}\n//│ ╙──      \t            ^^^\n//│ res: {u: int -> int -> int, v: error}\n\n{u: add, v: (x => 0).v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: add, v: (x => 0).v}\n//│ ║        \t                    ^^\n//│ ╟── function of type `?a -> 0` does not have field 'v'\n//│ ║  l.+1: \t{u: add, v: (x => 0).v}\n//│ ║        \t             ^^^^^^\n//│ ╟── but it flows into receiver with expected type `{v: ?v}`\n//│ ║  l.+1: \t{u: add, v: (x => 0).v}\n//│ ╙──      \t            ^^^^^^^^\n//│ res: {u: int -> int -> int, v: error}\n\n{u: add, v: (x => add).v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: add, v: (x => add).v}\n//│ ║        \t                      ^^\n//│ ╟── function of type `?a -> int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t{u: add, v: (x => add).v}\n//│ ║        \t             ^^^^^^^^\n//│ ╟── but it flows into receiver with expected type `{v: ?v}`\n//│ ║  l.+1: \t{u: add, v: (x => add).v}\n//│ ╙──      \t            ^^^^^^^^^^\n//│ res: {u: int -> int -> int, v: error}\n\n{u: add, v: (x => x).v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: add, v: (x => x).v}\n//│ ║        \t                    ^^\n//│ ╟── function of type `?a -> ?a` does not have field 'v'\n//│ ║  l.+1: \t{u: add, v: (x => x).v}\n//│ ║        \t             ^^^^^^\n//│ ╟── but it flows into receiver with expected type `{v: ?v}`\n//│ ║  l.+1: \t{u: add, v: (x => x).v}\n//│ ╙──      \t            ^^^^^^^^\n//│ res: {u: int -> int -> int, v: error}\n\n{u: add, v: {u: 0}.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: add, v: {u: 0}.v}\n//│ ║        \t                  ^^\n//│ ╟── record of type `{u: 0}` does not have field 'v'\n//│ ║  l.+1: \t{u: add, v: {u: 0}.v}\n//│ ╙──      \t            ^^^^^^\n//│ res: {u: int -> int -> int, v: error}\n\n{u: add, v: {u: add}.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: add, v: {u: add}.v}\n//│ ║        \t                    ^^\n//│ ╟── record of type `{u: int -> int -> int}` does not have field 'v'\n//│ ║  l.+1: \t{u: add, v: {u: add}.v}\n//│ ╙──      \t            ^^^^^^^^\n//│ res: {u: int -> int -> int, v: error}\n\n{u: add, v: {v: 0}}\n//│ res: {u: int -> int -> int, v: {v: 0}}\n\n{u: add, v: {v: add}}\n//│ res: {u: int -> int -> int, v: {v: int -> int -> int}}\n\n{u: {u: 0}}\n//│ res: {u: {u: 0}}\n\n{u: {u: 0}, v: 0}\n//│ res: {u: {u: 0}, v: 0}\n\n{u: {u: 0}, v: add}\n//│ res: {u: {u: 0}, v: int -> int -> int}\n\n{u: {u: 0}, v: (add 0)}\n//│ res: {u: {u: 0}, v: int -> int}\n\n{u: {u: 0}, v: (add add)}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t{u: {u: 0}, v: (add add)}\n//│ ║        \t                ^^^^^^^\n//│ ╟── reference of type `int -> int -> int` is not an instance of type `int`\n//│ ║  l.+1: \t{u: {u: 0}, v: (add add)}\n//│ ╙──      \t                    ^^^\n//│ res: {u: {u: 0}, v: error | int -> int}\n\n{u: {u: 0}, v: (add {v: 0})}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t{u: {u: 0}, v: (add {v: 0})}\n//│ ║        \t                ^^^^^^^^^^\n//│ ╟── record of type `{v: 0}` is not an instance of type `int`\n//│ ║  l.+1: \t{u: {u: 0}, v: (add {v: 0})}\n//│ ╙──      \t                    ^^^^^^\n//│ res: {u: {u: 0}, v: error | int -> int}\n\n{u: {u: 0}, v: (add {v: add})}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t{u: {u: 0}, v: (add {v: add})}\n//│ ║        \t                ^^^^^^^^^^^^\n//│ ╟── record of type `{v: int -> int -> int}` is not an instance of type `int`\n//│ ║  l.+1: \t{u: {u: 0}, v: (add {v: add})}\n//│ ╙──      \t                    ^^^^^^^^\n//│ res: {u: {u: 0}, v: error | int -> int}\n\n{u: {u: 0}, v: (x => 0)}\n//│ res: {u: {u: 0}, v: anything -> 0}\n\n{u: {u: 0}, v: (x => add)}\n//│ res: {u: {u: 0}, v: anything -> int -> int -> int}\n\n{u: {u: 0}, v: (x => x)}\n//│ res: {u: {u: 0}, v: forall 'a. 'a -> 'a}\n\n{u: {u: 0}, v: (x => 0.u)}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {u: 0}, v: (x => 0.u)}\n//│ ║        \t                      ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t{u: {u: 0}, v: (x => 0.u)}\n//│ ╙──      \t                     ^\n//│ res: {u: {u: 0}, v: anything -> error}\n\n{u: {u: 0}, v: (let x = 0; 0.u)}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {u: 0}, v: (let x = 0; 0.u)}\n//│ ║        \t                            ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t{u: {u: 0}, v: (let x = 0; 0.u)}\n//│ ╙──      \t                           ^\n//│ res: {u: {u: 0}, v: error}\n\n{u: {u: 0}, v: (let x = add; 0.u)}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {u: 0}, v: (let x = add; 0.u)}\n//│ ║        \t                              ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t{u: {u: 0}, v: (let x = add; 0.u)}\n//│ ╙──      \t                             ^\n//│ res: {u: {u: 0}, v: error}\n\n{u: {u: 0}, v: (let rec x = x; 0.u)}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {u: 0}, v: (let rec x = x; 0.u)}\n//│ ║        \t                                ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t{u: {u: 0}, v: (let rec x = x; 0.u)}\n//│ ╙──      \t                               ^\n//│ res: {u: {u: 0}, v: error}\n\n{u: {u: 0}, v: (x => add.u)}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {u: 0}, v: (x => add.u)}\n//│ ║        \t                        ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t{u: {u: 0}, v: (x => add.u)}\n//│ ╙──      \t                     ^^^\n//│ res: {u: {u: 0}, v: anything -> error}\n\n{u: {u: 0}, v: (x => x.u)}\n//│ res: {u: {u: 0}, v: forall 'u. {u: 'u} -> 'u}\n\n{u: {u: 0}, v: 0.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {u: 0}, v: 0.v}\n//│ ║        \t                ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t{u: {u: 0}, v: 0.v}\n//│ ╙──      \t               ^\n//│ res: {u: {u: 0}, v: error}\n\n{u: {u: 0}, v: add.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {u: 0}, v: add.v}\n//│ ║        \t                  ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t{u: {u: 0}, v: add.v}\n//│ ╙──      \t               ^^^\n//│ res: {u: {u: 0}, v: error}\n\n{u: {u: add}}\n//│ res: {u: {u: int -> int -> int}}\n\n{u: {u: add}, v: 0}\n//│ res: {u: {u: int -> int -> int}, v: 0}\n\n{u: {u: add}, v: add}\n//│ res: {u: {u: int -> int -> int}, v: int -> int -> int}\n\n{u: {u: add}, v: (x => 0)}\n//│ res: {u: {u: int -> int -> int}, v: anything -> 0}\n\n{u: {u: add}, v: (x => add)}\n//│ res: {u: {u: int -> int -> int}, v: anything -> int -> int -> int}\n\n{u: {u: add}, v: (let x = 0; add)}\n//│ res: {u: {u: int -> int -> int}, v: int -> int -> int}\n\n{u: {u: add}, v: (let x = add; add)}\n//│ res: {u: {u: int -> int -> int}, v: int -> int -> int}\n\n{u: {u: add}, v: (let rec x = x; add)}\n//│ res: {u: {u: int -> int -> int}, v: int -> int -> int}\n\n{u: {u: add}, v: (x => x)}\n//│ res: {u: {u: int -> int -> int}, v: forall 'a. 'a -> 'a}\n\n{u: {v: 0}}\n//│ res: {u: {v: 0}}\n\n{u: {v: 0}, v: 0}\n//│ res: {u: {v: 0}, v: 0}\n\n{u: {v: 0}, v: add}\n//│ res: {u: {v: 0}, v: int -> int -> int}\n\n{u: {v: 0}, v: (0 0)}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t{u: {v: 0}, v: (0 0)}\n//│ ║        \t                ^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t{u: {v: 0}, v: (0 0)}\n//│ ╙──      \t                ^\n//│ res: {u: {v: 0}, v: error}\n\n{u: {v: 0}, v: (0 add)}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \t{u: {v: 0}, v: (0 add)}\n//│ ║        \t                ^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.+1: \t{u: {v: 0}, v: (0 add)}\n//│ ╙──      \t                ^\n//│ res: {u: {v: 0}, v: error}\n\n{u: {v: 0}, v: (x => 0)}\n//│ res: {u: {v: 0}, v: anything -> 0}\n\n{u: {v: 0}, v: (let x = 0; 0)}\n//│ res: {u: {v: 0}, v: 0}\n\n{u: {v: 0}, v: (let x = add; 0)}\n//│ res: {u: {v: 0}, v: 0}\n\n{u: {v: 0}, v: (let rec x = x; 0)}\n//│ res: {u: {v: 0}, v: 0}\n\n{u: {v: 0}, v: (x => add)}\n//│ res: {u: {v: 0}, v: anything -> int -> int -> int}\n\n{u: {v: 0}, v: (let x = 0; add)}\n//│ res: {u: {v: 0}, v: int -> int -> int}\n\n{u: {v: 0}, v: (let x = add; add)}\n//│ res: {u: {v: 0}, v: int -> int -> int}\n\n{u: {v: 0}, v: (let rec x = x; add)}\n//│ res: {u: {v: 0}, v: int -> int -> int}\n\n{u: {v: 0}, v: (x => x)}\n//│ res: {u: {v: 0}, v: forall 'a. 'a -> 'a}\n\n{u: {v: add}}\n//│ res: {u: {v: int -> int -> int}}\n\n{u: {v: add}, v: 0}\n//│ res: {u: {v: int -> int -> int}, v: 0}\n\n{u: {v: add}, v: add}\n//│ res: {u: {v: int -> int -> int}, v: int -> int -> int}\n\n{u: {v: add}, v: 0.u}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {v: add}, v: 0.u}\n//│ ║        \t                  ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t{u: {v: add}, v: 0.u}\n//│ ╙──      \t                 ^\n//│ res: {u: {v: int -> int -> int}, v: error}\n\n{u: {v: add}, v: add.u}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {v: add}, v: add.u}\n//│ ║        \t                    ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t{u: {v: add}, v: add.u}\n//│ ╙──      \t                 ^^^\n//│ res: {u: {v: int -> int -> int}, v: error}\n\n{u: {v: add}, v: 0.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {v: add}, v: 0.v}\n//│ ║        \t                  ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t{u: {v: add}, v: 0.v}\n//│ ╙──      \t                 ^\n//│ res: {u: {v: int -> int -> int}, v: error}\n\n{u: {v: add}, v: add.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{u: {v: add}, v: add.v}\n//│ ║        \t                    ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t{u: {v: add}, v: add.v}\n//│ ╙──      \t                 ^^^\n//│ res: {u: {v: int -> int -> int}, v: error}\n\n{u: {v: add}, v: {v: 0}}\n//│ res: {u: {v: int -> int -> int}, v: {v: 0}}\n\n{u: {v: add}, v: {v: add}}\n//│ res: {u: {v: int -> int -> int}, v: {v: int -> int -> int}}\n\n0.v\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t0.v\n//│ ║        \t ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t0.v\n//│ ╙──      \t^\n//│ res: error\n\nadd.v\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \tadd.v\n//│ ║        \t   ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \tadd.v\n//│ ╙──      \t^^^\n//│ res: error\n\n{v: 0}\n//│ res: {v: 0}\n\n{v: add}\n//│ res: {v: int -> int -> int}\n\n{v: 0.u}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{v: 0.u}\n//│ ║        \t     ^^\n//│ ╟── integer literal of type `0` does not have field 'u'\n//│ ║  l.+1: \t{v: 0.u}\n//│ ╙──      \t    ^\n//│ res: {v: error}\n\n{v: add.u}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{v: add.u}\n//│ ║        \t       ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'u'\n//│ ║  l.+1: \t{v: add.u}\n//│ ╙──      \t    ^^^\n//│ res: {v: error}\n\n{v: 0.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{v: 0.v}\n//│ ║        \t     ^^\n//│ ╟── integer literal of type `0` does not have field 'v'\n//│ ║  l.+1: \t{v: 0.v}\n//│ ╙──      \t    ^\n//│ res: {v: error}\n\n{v: add.v}\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+1: \t{v: add.v}\n//│ ║        \t       ^^\n//│ ╟── reference of type `int -> int -> int` does not have field 'v'\n//│ ║  l.+1: \t{v: add.v}\n//│ ╙──      \t    ^^^\n//│ res: {v: error}\n\n{v: {v: 0}}\n//│ res: {v: {v: 0}}\n\n{v: {v: add}}\n//│ res: {v: {v: int -> int -> int}}\n\n\n// Number of expressions generated: 499\n\n// Program sizes:\n//   1: 2\n//   2: 8\n//   3: 34\n//   4: 62\n//   5: 123\n//   6: 128\n//   7: 99\n//   8: 22\n//   9: 21\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_casparticuliers.mls",
    "content": ":NoRecursiveTypes\n:DistributeForalls\n\n\n// (*** L'annotation est n�cessaire sur z, mais z n'est utilis� qu'une seule fois. ***)\n// type sid = ['a] 'a -> 'a\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\n// let t (z:sid) = ( (fun a -> z) : ['a,'b] 'b -> 'a -> 'a )\ndef t (z: Sid) = (fun a -> z) : forall 'a 'b. 'b -> 'a -> 'a\n//│ t: Sid -> (forall 'a. anything -> 'a -> 'a)\n//│  = [Function: t]\n\n// (* Une seule instance, mais polymorphe. *)\n// let t z = ( (fun a -> z) : ['a,'b] 'b -> 'a -> 'a );;\ndef t z = (fun a -> z) : forall 'a 'b. 'b -> 'a -> 'a\n//│ t: (??a -> ??a0) -> anything -> 'a -> 'a\n//│  = [Function: t1]\n\ndef t z = fun a -> z\n//│ t: 'a -> anything -> 'a\n//│  = [Function: t2]\n\n\n// (*** Ne type pas avec les value-restriction. Emb�tant. ***)\n\n// type Int = ['a] ('a -> 'a) -> ('a -> 'a)\n// ;;\ntype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ Defined type alias ChurchInt\n\n// let zero f x = x\n// ;;\n\ndef zero f x = x\n//│ zero: anything -> 'a -> 'a\n//│     = [Function: zero]\n\ndef zero_ty: ChurchInt\n//│ zero_ty: ChurchInt\n//│        = <missing implementation>\n\n// let succ (n:Int) = fun f x -> f (n f x)\n// ;;\ndef succ_ty: ChurchInt -> ChurchInt\ndef succ (n: ChurchInt) = fun f -> fun x -> f (n f x)\ndef succ' n = fun f -> fun x -> f (n f x)\n//│ succ_ty: ChurchInt -> ChurchInt\n//│        = <missing implementation>\n//│ succ: ChurchInt -> ('a -> ('a & 'b)) -> 'a -> 'b\n//│     = [Function: succ]\n//│ succ': ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│      = [Function: succ$]\n\n// * Note: without constrained types we don't get the principal type of succ' (at least assuming no distrib.)\n\nsucc_ty = succ\n//│ ChurchInt -> ('a -> ('a & 'b)) -> 'a -> 'b\n//│   <:  succ_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: succ]\n\n// * Note that this equires distributivity (see Church encoding test files)\nsucc_ty = succ'\n//│ ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│   <:  succ_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: succ$]\n\nsucc'\n//│ res: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│    = [Function: succ$]\n\n// * Legit error: (bad bounds)\n:e\nsucc' {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.77: \tsucc' {}\n//│ ║        \t^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.77: \tsucc' {}\n//│ ║        \t      ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ║        \t                                   ^^^\n//│ ╟── from reference:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ╙──      \t                                   ^\n//│ res: error | (nothing -> 'a) -> anything -> 'a\n//│    = [Function (anonymous)]\n\n:e\nsucc' {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.94: \tsucc' {} {}\n//│ ║        \t^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.94: \tsucc' {} {}\n//│ ║        \t      ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ║        \t                                   ^^^\n//│ ╟── from reference:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ╙──      \t                                   ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.94: \tsucc' {} {}\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.94: \tsucc' {} {}\n//│ ║        \t         ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ║        \t                                ^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ╙──      \t                                ^\n//│ res: error | anything -> nothing\n//│    = [Function (anonymous)]\n\n:e\nsucc' {} {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.123: \tsucc' {} {} {}\n//│ ║         \t^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.123: \tsucc' {} {} {}\n//│ ║         \t      ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ║        \t                                   ^^^\n//│ ╟── from reference:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ╙──      \t                                   ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.123: \tsucc' {} {} {}\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.123: \tsucc' {} {} {}\n//│ ║         \t         ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ║        \t                                ^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.48: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ╙──      \t                                ^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\nfun x -> succ' x x x x x x x x x\n//│ res: ('a -> 'b -> 'b -> 'b -> 'b -> 'b -> 'b -> 'c & 'b -> 'b -> 'a & 'b) -> 'c\n//│    = [Function: res]\n\n\n// let rec to_church n =\n//   if n = 0 then zero\n//   else succ (to_church (n-1))\n// ;;\n\n// * Note: we exercise many variations of `to_church` with/without various annotations\n\ndef to_church_ty: int -> ChurchInt\n//│ to_church_ty: int -> ChurchInt\n//│             = <missing implementation>\n\nrec def to_church_1 n =\n  if n == 0 then zero\n  else succ (to_church_1 (n - 1))\n//│ to_church_1: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│            = [Function: to_church_1]\n\nrec def to_church_1_t n =\n  if n == 0 then zero\n  else succ_ty (to_church_1_t (n - 1))\n//│ to_church_1_t: int -> (anything -> 'a -> 'a | ChurchInt)\n//│              = [Function: to_church_1_t]\n\nrec def to_church_1_tt n =\n  if n == 0 then zero_ty\n  else succ_ty (to_church_1_tt (n - 1))\n//│ to_church_1_tt: int -> ChurchInt\n//│               = <no result>\n//│                 zero_ty is not implemented\n\n// def succ: (forall 'N. ('N -> 'N) -> ('N -> 'N)) -> (forall 'M. ('M -> 'M) -> ('M -> 'M))\n\n\n// * === Digression: our own little weird meaningless tests ===\n\n:ng // * (recursive non-function not supported in JS)\nrec def wat =\n  succ wat\n//│ wat: ('a -> ('a & 'b)) -> 'a -> 'b\n\nrec def wat n =\n  succ (wat n)\n//│ wat: anything -> ('a -> ('a & 'b)) -> 'a -> 'b\n//│    = [Function: wat]\n\n:e\nrec def wat n =\n  succ wat n\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.203: \trec def wat n =\n//│ ║         \t            ^^^\n//│ ║  l.204: \t  succ wat n\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ╙──      \t                             ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.203: \trec def wat n =\n//│ ║         \t            ^^^\n//│ ║  l.204: \t  succ wat n\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ╙──      \t                             ^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.203: \trec def wat n =\n//│ ║         \t            ^^^\n//│ ║  l.204: \t  succ wat n\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                           ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.204: \t  succ wat n\n//│ ║         \t  ^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.47: \tdef succ (n: ChurchInt) = fun f -> fun x -> f (n f x)\n//│ ╙──      \t                                                   ^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.203: \trec def wat n =\n//│ ║         \t            ^^^\n//│ ║  l.204: \t  succ wat n\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                           ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.204: \t  succ wat n\n//│ ║         \t  ^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.47: \tdef succ (n: ChurchInt) = fun f -> fun x -> f (n f x)\n//│ ╙──      \t                                                   ^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.203: \trec def wat n =\n//│ ║         \t            ^^^\n//│ ║  l.204: \t  succ wat n\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                                 ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.204: \t  succ wat n\n//│ ╙──       \t  ^^^^^^^^^^\n//│ wat: (anything -> (??a & 'a)) -> (??a & 'a) -> anything\n//│    = [Function: wat1]\n\n// * Works with this option!\n:precise-rec-typing\nrec def wat n =\n  succ wat n\n//│ wat: ('a -> ('a & 'b)) -> 'a -> 'b\n//│    = [Function: wat2]\n\n:ng\nrec def nani =\n  succ' nani\n//│ nani: ('a -> 'a) -> anything -> 'a\n\nrec def wat_2 n =\n  succ (wat_2 n)\n//│ wat_2: anything -> ('a -> ('a & 'b)) -> 'a -> 'b\n//│      = [Function: wat_2]\n\ndef to_church_1_repro n =\n  succ (to_church_ty n)\n//│ to_church_1_repro: int -> ('a -> ('a & 'b)) -> 'a -> 'b\n//│                  = <no result>\n//│                    to_church_ty is not implemented\n\n// * === /Digression ===\n\n\nrec def to_church_1_st n =\n  if n == 0 then zero\n  else succ_ty (to_church_1_st (n - 1))\n//│ to_church_1_st: int -> (anything -> 'a -> 'a | ChurchInt)\n//│               = [Function: to_church_1_st]\n\nrec def to_church_2 n =\n  if n == 0 then zero\n  else succ' (to_church_2 (n - 1))\n//│ to_church_2: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│            = [Function: to_church_2]\n\nto_church_ty = to_church_2\n//│ int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_2]\n\n// (* Marche *)\n// let rec to_church n =\n//   if n = 0 then fun f x -> x\n//   else fun f x -> f ((to_church (n-1) : Int) f x)\n// ;;\n\nrec def to_church_3 n =\n  if n == 0 then fun f -> fun x -> x\n  else fun f -> fun x -> f ((to_church_3 (n - 1) : ChurchInt) f x)\n//│ to_church_3: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│            = [Function: to_church_3]\n\n// (* Ne Marche Pas *)\n// let rec to_church n =\n//   if n = 0 then fun f x -> x\n//   else (fun f x -> f ((to_church (n-1)) f x) : Int)\n// ;;\n// * Type checks for us, but not a subtype of to_church_ty (see below)\nrec def to_church_4 n =\n  if n == 0 then fun f -> fun x -> x\n  else fun f -> fun x -> f ((to_church_4 (n - 1)) f x) : ChurchInt\n//│ to_church_4: int -> ((ChurchInt | 'a) -> ChurchInt) -> 'a -> (ChurchInt | 'a)\n//│            = [Function: to_church_4]\n\n\n// (* La r�cursion est monomorphe. *)\n// let rec to_church n =\n//   if n = 0 then fun f x -> x\n//   else fun f x -> f ((to_church (n-1)) f x)\n// ;;\n\nrec def to_church_5 n =\n  if n == 0 then fun f -> fun x -> x\n  else fun f -> fun x -> f ((to_church_5 (n - 1)) f x)\n//│ to_church_5: int -> ('a -> 'b & 'a -> 'a) -> ('a & 'b) -> 'b\n//│            = [Function: to_church_5]\n\n\n// * Now checking whether the inferred types conform to the expected signature:\n\nto_church_ty = to_church_1\n//│ int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_1]\n\nto_church_ty = to_church_1_t\n//│ int -> (anything -> 'a -> 'a | ChurchInt)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_1_t]\n\nto_church_ty = to_church_1_tt\n//│ int -> ChurchInt\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = <no result>\n//│               to_church_1_tt and zero_ty are not implemented\n\nto_church_ty = to_church_1_st\n//│ int -> (anything -> 'a -> 'a | ChurchInt)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_1_st]\n\nto_church_ty = to_church_2\n//│ int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_2]\n\nto_church_ty = to_church_3\n//│ int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_3]\n\n:e\nto_church_ty = to_church_4\n//│ int -> ((ChurchInt | 'a) -> ChurchInt) -> 'a -> (ChurchInt | 'a)\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.403: \tto_church_ty = to_church_4\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `('a -> 'a) -> 'a -> 'a` does not match type `'a0`\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                            ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ╙──      \t                             ^^\n//│             = [Function: to_church_4]\n\nto_church_ty = to_church_5\n//│ int -> ('a -> 'b & 'a -> 'a) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_5]\n\n\n\n\n// (* Echoue avec la value restriction. *)\n// let rec (to_church:int -> Int) n =\n//   if n = 0 then fun f x -> x\n//   else fun f x -> f ((to_church (n-1)) f x)\n// ;;\n\n\nrec def to_church_ty n =\n  if n == 0 then fun f -> fun x -> x\n  else fun f -> fun x -> f ((to_church_ty (n - 1)) f x)\n//│ int -> ('a -> 'b & 'a -> 'a) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_ty8]\n\n// * Note: same but without `rec`, picking up the to_church_ty annotation for rec calls\ndef to_church_ty n =\n  if n == 0 then fun f -> fun x -> x\n  else fun f -> fun x -> f ((to_church_ty (n - 1)) f x)\n//│ int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   <:  to_church_ty:\n//│ int -> ChurchInt\n//│             = [Function: to_church_ty9]\n\n\n// (* �a coince. *)\n// let tc n = (to_church n : Int);;\n\ndef tc n = to_church_1 n : ChurchInt\n//│ tc: int -> ChurchInt\n//│   = [Function: tc]\n\ndef tc n = to_church_ty n : ChurchInt\n//│ tc: int -> ChurchInt\n//│   = [Function: tc1]\n\ndef tc n = to_church_2 n : ChurchInt\n//│ tc: int -> ChurchInt\n//│   = [Function: tc2]\n\ndef tc n = to_church_3 n\n//│ tc: int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   = [Function: tc3]\n\ntc 1 id\n//│ res: 'a -> 'a\n//│    = [Function (anonymous)]\n\ntc: int -> ChurchInt\n//│ res: int -> ChurchInt\n//│    = [Function: tc3]\n\ndef tc n = to_church_3 n : ChurchInt\n//│ tc: int -> ChurchInt\n//│   = [Function: tc4]\n\n\n// (* Duplicate with to_church1 (\"Marche\") above *)\n// (* Avec la value restriction : �a passe. *)\n// let rec to_church n =\n//   if n = 0 then fun f x -> x\n//   else fun f x -> f ((to_church (n-1) : Int) f x)\n\n\n// (*** Les annotations de type ne commutent pas. ***)\n// type sid = ['a] 'a -> 'a\n// type z = ['a,'b] ('a -> 'b) -> ('a -> 'b)\ntype Z = forall 'a 'b. ('a -> 'b) -> ('a -> 'b)\n//│ Defined type alias Z\n\n// let f x = (x:sid), ((x:sid):z)\n\ndef f x = ((x : Sid), ((x : Sid) : Z))\n//│ f: Sid -> (Sid, Z,)\n//│  = [Function: f]\n\n// (* Ne type pas ... c'est une instance polymorphe. Interdit. *)\n// untype fun x -> (x:sid), (x:z)\nfun x -> ((x : Sid), (x : Z))\n//│ res: (Sid & Z) -> (Sid, Z,)\n//│    = [Function: res]\n\n\n\n\n\n// * === With Constrained Types ===\n\n\n:DontDistributeForalls\n:ConstrainedTypes\n\n\n\n// let succ (n:Int) = fun f x -> f (n f x)\n// ;;\ndef succ_ty: ChurchInt -> ChurchInt\ndef succ (n: ChurchInt) = fun f -> fun x -> f (n f x)\ndef succ' n = fun f -> fun x -> f (n f x)\n//│ succ_ty: ChurchInt -> ChurchInt\n//│        = <missing implementation>\n//│ succ: ChurchInt -> (forall 'b. 'b -> (forall 'a 'c. 'a -> 'c\n//│   where\n//│     'b <: 'a -> 'a & 'a -> 'c))\n//│     = [Function: succ1]\n//│ succ': 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│      = [Function: succ$1]\n\n// * Note: without constrained types (and distrib.) we wouldn't get the principal type of succ'\n\nsucc_ty = succ\n//│ ChurchInt -> (forall 'b. 'b -> (forall 'a 'c. 'a -> 'c\n//│   where\n//│     'b <: 'a -> 'a & 'a -> 'c))\n//│   <:  succ_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: succ1]\n\n// * Still requires distributivity even with CT\n:e\nsucc_ty = succ'\n//│ 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│   <:  succ_ty:\n//│ ChurchInt -> ChurchInt\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.550: \tsucc_ty = succ'\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                   ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.30: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.525: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ║         \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.550: \tsucc_ty = succ'\n//│ ╙──       \t          ^^^^^\n//│        = [Function: succ$1]\n:DistributeForalls\nsucc_ty = succ'\n//│ 'a -> 'b -> ('c -> 'd\n//│   where\n//│     'a <: 'b -> 'c -> 'e\n//│     'b <: 'e -> 'd)\n//│   <:  succ_ty:\n//│ ChurchInt -> ChurchInt\n//│        = [Function: succ$1]\n:DontDistributeForalls\n\nsucc'\n//│ res: 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'c -> 'e\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'd -> 'e))\n//│    = [Function: succ$1]\n\n// :e // * Error delayed by inconsistent constrained types\nsucc' {}\n//│ res: 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     anything <: 'a -> 'b -> 'c\n//│     'a <: 'c -> 'd)\n//│    = [Function (anonymous)]\n\n// :e // * Error delayed by inconsistent constrained types\nsucc' {} {}\n//│ res: 'a -> 'b\n//│   where\n//│     anything <: anything -> 'a -> 'c & 'c -> 'b\n//│    = [Function (anonymous)]\n\n:e\nsucc' {} {} {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.608: \tsucc' {} {} {}\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.608: \tsucc' {} {} {}\n//│ ║         \t      ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.525: \tdef succ' n = fun f -> fun x -> f (n f x)\n//│ ╙──       \t                                   ^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: n is not a function\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_concrete.mls",
    "content": ":NoRecursiveTypes\n\n// type mylist ('b) = Nil | Cons of ('b * mylist ('b))\n// ;;\nclass Nil\nclass Cons[a]: { head: a; tail: List[a] }\ntype List[a] = Nil | Cons[a]\nNil = Nil {}\nCons (head, tail) = Cons { head; tail }\n//│ Defined class Nil\n//│ Defined class Cons[+a]\n//│ Defined type alias List[+a]\n//│ Nil: Nil\n//│    = Nil {}\n//│ Cons: ('head & 'a, List['a] & 'tail,) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│     = [Function: Cons1]\n\n// let un = Nil ;;\n// let deux = Nil ;;\n// let trois = Cons (10, un) ;;\n// let quatre = Cons (\"ok\", deux) ;;\n// let cinq = Cons (\"zozo\", quatre) ;;\nun = Nil\ndeux = Nil\ntrois = Cons (10, un)\nquatre = Cons (\"ok\", deux)\ncinq = Cons (\"zozo\", quatre)\n//│ un: Nil\n//│   = Nil {}\n//│ deux: Nil\n//│     = Nil {}\n//│ trois: Cons[10] with {tail: Nil}\n//│      = Cons { head: 10, tail: Nil {} }\n//│ quatre: Cons[\"ok\"] with {tail: Nil}\n//│       = Cons { head: 'ok', tail: Nil {} }\n//│ cinq: Cons[\"ok\" | \"zozo\"] with {head: \"zozo\", tail: Cons[\"ok\"] with {tail: Nil}}\n//│     = Cons { head: 'zozo', tail: Cons { head: 'ok', tail: Nil {} } }\n\n// let id x = x \ndef id x = x\n//│ id: 'a -> 'a\n//│   = [Function: id]\n\n// let rec mymap f l =\n//   begin match l with\n//   | Nil -> Nil\n//   | Cons (car,cdr) -> Cons (f car, mymap f cdr) \n//   end\n:RecursiveTypes // * Needed for this structurally-typed recursive def\nrec def map f l = case l of\n  { Nil -> Nil\n  | Cons -> Cons (f l.head, map f l.tail)\n  }\n//│ map: ('head -> 'head0) -> 'a -> (Nil | 'b)\n//│   where\n//│     'b :> Cons['head0] with {tail: Nil | 'b}\n//│     'a <: (Cons[?] with {head: 'head, tail: 'a}) | Nil\n//│    = [Function: map]\n:NoRecursiveTypes\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_demo.mls",
    "content": ":NoRecursiveTypes\n\n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass None\nclass Some[a]: { val: a }\ntype Option[a] = None | Some[a]\n//│ Defined class None\n//│ Defined class Some[+a]\n//│ Defined type alias Option[+a]\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\ndef cons[a]: a -> List[a] -> List[a]\ndef cons head tail = Cons { head; tail }\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\ndef nil: List['a]\nnil = Nil {}\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: forall 'a. List['a] -> 'a\ndef head l = l.Head\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n//│ List['a] -> 'a\n//│   <:  head:\n//│ List['a] -> 'a\n//│     = [Function: head]\n\ndef tail: forall 'a. List['a] -> List['a]\ndef tail l = l.Tail\n//│ tail: List['a] -> List['a]\n//│     = <missing implementation>\n//│ List['a] -> List['a]\n//│   <:  tail:\n//│ List['a] -> List['a]\n//│     = [Function: tail]\n\ndef print_bool: bool -> unit\ndef print_bool b = log b\n//│ print_bool: bool -> unit\n//│           = <missing implementation>\n//│ anything -> unit\n//│   <:  print_bool:\n//│ bool -> unit\n//│           = [Function: print_bool]\n\ndef print_int: int -> unit\ndef print_int i = log i\n//│ print_int: int -> unit\n//│          = <missing implementation>\n//│ anything -> unit\n//│   <:  print_int:\n//│ int -> unit\n//│          = [Function: print_int]\n\ndef print_string: string -> unit\ndef print_string s = log s\n//│ print_string: string -> unit\n//│             = <missing implementation>\n//│ anything -> unit\n//│   <:  print_string:\n//│ string -> unit\n//│             = [Function: print_string]\n\n\n\n// (* A quick demo of MLF *)\n\n// (* In the following, \"untype expr\" means that the expression expr should not be typable. *)\n\n// type sid = ['a] 'a -> 'a\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\n// let id = fun x -> x\ndef id = fun x -> x\n//│ id: 'a -> 'a\n//│   = [Function: id]\n\n// let delta = fun (x:sid) -> x x\ndef delta = fun (x: Sid) -> x x\ndef delta_ = fun x -> x x\n//│ delta: Sid -> Sid\n//│      = [Function: delta]\n//│ delta_: ('a -> 'b & 'a) -> 'b\n//│       = [Function: delta_]\n\n// let choose x y = if true then x else y\ndef choose x y = if true then x else y\n//│ choose: 'a -> 'a -> 'a\n//│       = [Function: choose]\n\n// let succ n = n + 1\n// ;;\ndef succ n = n + 1\n//│ succ: int -> int\n//│     = [Function: succ]\n\n// let test1 = delta id\ntest1 = delta id\n//│ test1: Sid\n//│      = [Function: id]\n\n// untype delta succ\n:e\ndelta succ\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.138: \tdelta succ\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.104: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║         \t                      ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.127: \tdef succ n = n + 1\n//│ ║         \t             ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.104: \ttype Sid = forall 'a. 'a -> 'a\n//│ ╙──       \t                  ^^\n//│ res: error | Sid\n//│    = 'function succ(n) {  return n + 1;}1'\n\n// let test2 = delta (choose id id)\ntest2 = delta (choose id id)\n//│ test2: Sid\n//│      = [Function: id]\n\ntest2 = delta_ (choose id id)\n//│ test2: 'a -> 'a\n//│      = [Function: id]\n\n// untype delta (choose id succ)\n:e\ndelta (choose id succ)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.165: \tdelta (choose id succ)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.104: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║         \t                      ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.127: \tdef succ n = n + 1\n//│ ║         \t             ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.104: \ttype Sid = forall 'a. 'a -> 'a\n//│ ╙──       \t                  ^^\n//│ res: error | Sid\n//│    = [Function: id]\n\n// let test3 = choose id succ\ntest3 = choose id succ\n//│ test3: int -> int\n//│      = [Function: id]\n\n// let test4 = choose succ id\n// ;;\ntest4 = choose succ id\n//│ test4: int -> int\n//│      = [Function: succ]\n\n\n// let eqstring s1 s2 = (s1^\"A\" = s2^\"A\")\ndef eqstring s1 s2 = eq (concat s1 \"A\") (concat s2 \"A\")\n//│ eqstring: string -> string -> bool\n//│         = [Function: eqstring]\n\n// let eqint i1 i2 = (i1 - i2) = 0\ndef eqint i1 i2 = (i1 - i2) == 0\n//│ eqint: int -> int -> bool\n//│      = [Function: eqint]\n\n// let eqbool b1 b2 = if b1 then b2 else (not b2)\ndef eqbool b1 b2 = if b1 then b2 else (not b2)\n//│ eqbool: bool -> bool -> bool\n//│       = [Function: eqbool]\n\n// let ignore x = ()\ndef ignore x = null\n//│ ignore: anything -> null\n//│       = [Function: ignore]\n\n\n// let rec listiter f ll =\n//   if ll = [] then ()\n//   else begin ignore (f (car ll)) ; listiter f (cdr ll) end\n// ;;\n\nrec def listiter f ll =\n  if eq ll nil then unit\n  else\n    let _ = ignore (f (head ll)) in \n    listiter f (tail ll)\n//│ listiter: ('a -> anything) -> List['a] -> unit\n//│         = [Function: listiter]\n\ndef listiterA: ('a -> unit) -> List['a] -> unit\n//│ listiterA: ('a -> unit) -> List['a] -> unit\n//│          = <missing implementation>\n\nlistiterA = listiter\n//│ ('a -> anything) -> List['a] -> unit\n//│   <:  listiterA:\n//│ ('a -> unit) -> List['a] -> unit\n//│          = [Function: listiter]\n\n\n\n// (* Polymorphic recursion. *)\n\n// untype let rec id x = if true then x else id id x in id\n:e\nrec def id1 x = if true then x else id1 id1 x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> 'c\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c :> 'b -> 'c\n//│        <: 'a\n//│ ║  l.243: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──       \t                                    ^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required\n//│ ║  l.243: \trec def id1 x = if true then x else id1 id1 x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id1]\n\n\n\n// * === \\ Below, some of our own variations ===\n\n// * With annotated recursive calls\ndef idy_ty: forall 'a. 'a -> 'a\ndef id1 x = if true then x else idy_ty idy_ty x\n//│ idy_ty: 'a -> 'a\n//│       = <missing implementation>\n//│ id1: 'a -> 'a\n//│    = <no result>\n//│      idy_ty is not implemented\n\n// * This definition does not actually seem to require general polymorphic recursion,\n// *  but it does need at least recursive types:\n:RecursiveTypes\nrec def id1 x = if true then x else id1 id1 x\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id11]\nid1 id\n//│ res: ('a & 'b) -> 'b | 'c\n//│   where\n//│     'a :> ('a & 'b) -> 'b\n//│        <: 'b\n//│     'b :> ('a & 'b) -> 'b\n//│        <: 'a -> 'b & 'c\n//│    = [Function: id]\nid1 id1\n//│ res: ('a & 'b) -> 'a\n//│   where\n//│     'a :> forall 'c 'd. ('a & 'b & 'c) -> ('a | 'd)\n//│        <: ((forall 'c 'd. 'c -> 'd) | 'b) -> 'a\n//│     'c :> 'c -> 'd\n//│        <: 'd\n//│     'd := 'c -> 'd\n//│    = [Function: id11]\n// * Note that it can't be applied when typed with :precise-rec-typing AND :DontDistributeForalls\n:DontDistributeForalls\n:precise-rec-typing\nrec def id1_p x = if true then x else id1_p id1_p x\n//│ id1_p: 'a -> 'b\n//│   where\n//│     'a <: 'b & 'c\n//│     'b :> 'd\n//│     'd :> forall 'a 'b. 'a -> 'b\n//│        <: 'c -> 'd\n//│     'c :> forall 'a 'b. 'a -> 'b\n//│        <: 'd\n//│      = [Function: id1_p]\n// * Can't apply it:\n:e\nid1_p id\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.319: \tid1_p id\n//│ ║         \t^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error | ('a & 'b) -> 'a | 'c\n//│   where\n//│     'a :> 'd\n//│     'd :> forall 'a 'b. ('a & 'b) -> 'a\n//│        <: 'e -> 'd & 'c\n//│     'b <: 'a & 'e\n//│     'e :> forall 'a 'b. ('a & 'b) -> 'a\n//│        <: 'd\n//│    = [Function: id]\n:DistributeForalls\n:NoRecursiveTypes\n\n// * TODO type pp – inline id1?\n:e\nid1\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│ ╙──\n//│ res: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id11]\n\n:e\nid1: nothing\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a := 'b -> 'a\n//│     'b :> 'b -> 'a\n//│        <: 'a\n//│ ║  l.280: \trec def id1 x = if true then x else id1 id1 x\n//│ ╙──       \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.353: \tid1: nothing\n//│ ║         \t^^^\n//│ ╟── function of type `?a -> ?b` does not match type `nothing`\n//│ ║  l.280: \trec def id1 x = if true then x else id1 id1 x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `nothing`\n//│ ║  l.353: \tid1: nothing\n//│ ║         \t^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.353: \tid1: nothing\n//│ ╙──       \t     ^^^^^^^\n//│ res: nothing\n//│    = [Function: id11]\n\n:e\nrec def id1_ x = id1_ id1_ x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: ('b -> 'c | 'b) -> 'c\n//│     'c <: 'a\n//│ ║  l.377: \trec def id1_ x = id1_ id1_ x\n//│ ╙──       \t                 ^^^^^^^^^\n//│ id1_: anything -> nothing\n//│     = [Function: id1_]\n\n:e // * Incorrect annotation\nrec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ╔══[ERROR] Inferred recursive type: 'b\n//│   where\n//│     'b <: (forall 'a. 'a -> 'a) -> (??a & 'b)\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ╙──       \t                                                           ^^^^^^^\n//│ ╔══[ERROR] Type mismatch in binding of lambda expression:\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t                           ^^\n//│ ╟── but it flows into quantified type variable with expected type `'a0 -> 'a0`\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t                       ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ╙──       \t                           ^^^^^^^^\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t                           ^^^^^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ╙──       \t                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t                           ^^^^^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ║         \t                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.388: \trec def id1 (x: forall 'a. 'a -> 'a) = if true then x else id1 id1 x\n//│ ╙──       \t                                                           ^^^^^^^^^\n//│ id1: (forall 'a. 'a -> 'a) -> 'a0 -> 'a0\n//│    = [Function: id12]\n\n// * === / ===\n\n\n\n// let rec (id:sid) x = if true then x else id id x\n\ndef id2: Sid\n//│ id2: Sid\n//│    = <missing implementation>\n\n// * (Note: absence of `rec` emulates annotated rec def.)\ndef id2 x = if true then x else id2 id2 x\n//│ 'a -> 'a\n//│   <:  id2:\n//│ Sid\n//│    = <no result>\n//│      id2 is not implemented\n\n\n\n\n// (* Existential types. *)\n// (* Creating an encapsulation is explicit (unavoidable). *)\n// (* Here, we build (Exist 'a . 'a * ('a -> unit))              *)\n// (*        then    (Exist 'a . 'a * 'a * ('a -> 'a -> bool))   *)\n\n\n// let make_ex1 x (f:['a] ('a * ('a -> 'c)) -> 'b) = f x\ndef make_ex1 x (f: forall 'a. (('a, 'a -> 'c),) -> 'b) = f x\n//│ make_ex1: (('a, 'a -> 'c,),) -> (forall 'a0. (('a0, 'a0 -> 'c,),) -> 'b) -> 'b\n//│         = [Function: make_ex1]\n\nex1_1 = make_ex1 ((\"A String\", print_string))\n//│ ex1_1: (forall 'a. (('a, 'a -> unit,),) -> 'b) -> 'b\n//│      = [Function (anonymous)]\n\nex1_1 (fun ((x, f)) -> f x)\n//│ = undefined\n//│ // Output\n//│ A String\n\nex1_2 = if true then make_ex1 ((42, print_int)) else ex1_1\n//│ ex1_2: (forall 'a 'a0. (('a, 'a -> unit,),) -> 'b & (('a0, 'a0 -> unit,),) -> 'b) -> 'b\n//│      = [Function (anonymous)]\n\nex1_2 (fun ((x, f)) -> f x)\n//│ = undefined\n//│ // Output\n//│ 42\n\n\n// let make_ex2 x (f:['a] ('a * 'a * ('a -> 'a -> 'c)) -> 'b) = f x\n// ;;\ndef make_ex2 x (f: forall 'a. (('a, 'a, 'a -> 'a -> 'c),) -> 'b) = f x\n//│ make_ex2: (('a, 'a, 'a -> 'a -> 'c,),) -> (forall 'a0. (('a0, 'a0, 'a0 -> 'a0 -> 'c,),) -> 'b) -> 'b\n//│         = [Function: make_ex2]\n\n// let ex_list1 = [ make_ex1 (\"A String\", print_string) ; \n// \t\t make_ex1 (8250, print_int) ;\n// \t\t make_ex1 (true, print_bool) ]\n// ;;\nex_list1 = cons (make_ex1 ((\"A String\", print_string)))\n  (cons (make_ex1 ((8250, print_int)))\n  (cons (make_ex1 ((true, print_bool))) nil))\n//│ ex_list1: List[forall 'b. (forall 'a 'a0 'a1. (('a, 'a -> unit,),) -> 'b & (('a0, 'a0 -> unit,),) -> 'b & (('a1, 'a1 -> unit,),) -> 'b) -> 'b]\n//│         = Cons {\n//│             head: [Function (anonymous)],\n//│             tail: Cons {\n//│               head: [Function (anonymous)],\n//│               tail: Cons { head: [Function (anonymous)], tail: Nil {} }\n//│             }\n//│           }\n\n// let ex_list2 = [ make_ex2 (\"String\", \"String\", eqstring) ;\n// \t\t make_ex2 ( 1250, 4890, eqint) ;\n// \t\t make_ex2 ( true, false, eqbool) ]\n// ;;\nex_list2 = cons (make_ex2 ((\"String\", \"String\", eqstring)))\n  (cons (make_ex2 ((1250, 4890, eqint)))\n  (cons (make_ex2 ((true, false, eqbool))) nil))\n//│ ex_list2: List[forall 'b. (forall 'a 'a0 'a1. (('a, 'a, 'a -> 'a -> bool,),) -> 'b & (('a0, 'a0, 'a0 -> 'a0 -> (bool | false),),) -> 'b & (('a1, 'a1, 'a1 -> 'a1 -> bool,),) -> 'b) -> 'b]\n//│         = Cons {\n//│             head: [Function (anonymous)],\n//│             tail: Cons {\n//│               head: [Function (anonymous)],\n//│               tail: Cons { head: [Function (anonymous)], tail: Nil {} }\n//│             }\n//│           }\n\n\nh = head ex_list1\n//│ h: (forall 'a 'a0 'a1. (('a, 'a -> unit,),) -> 'b & (('a0, 'a0 -> unit,),) -> 'b & (('a1, 'a1 -> unit,),) -> 'b) -> 'b\n//│  = [Function (anonymous)]\n\nh (fun ((x, f)) -> f x)\n//│ = undefined\n//│ // Output\n//│ A String\n\n// * _n accessors not yet implemented in JS backend:\n// test1 = listiterA (fun ex -> ex (fun p -> p._2 p._1)) ex_list1\n\ntest1 = listiterA (fun ex -> ex (fun ((p1, p2)) -> p2 p1)) ex_list1\n//│ test1: unit\n//│      = [Function: unit]\n//│ // Output\n//│ A String\n//│ 8250\n//│ true\n\n// let test1 = listiter (fun ex -> ex (fun p -> (snd p) (fst p))) ex_list1\n// ;;\ntest1 = listiter (fun ex -> ex (fun ((p1, p2)) -> p2 p1)) ex_list1\n//│ test1: unit\n//│      = [Function: unit]\n//│ // Output\n//│ A String\n//│ 8250\n//│ true\n\ntest1_ = listiter (fun ex -> ex (fun ((p1, p2)) -> p2 p1))\n//│ test1_: List[(forall 'a 'b. (('a, 'a -> 'b,),) -> 'b) -> anything] -> unit\n//│       = [Function (anonymous)]\n\ntest1_ ex_list1\n//│ = [Function: unit]\n//│ // Output\n//│ A String\n//│ 8250\n//│ true\n\nprocess ex = ex (fun ((p1, p2)) -> p2 p1)\n//│ process: ((forall 'a 'b. (('a, 'a -> 'b,),) -> 'b) -> 'c) -> 'c\n//│        = [Function: process]\n\nprocess h\n//│ = undefined\n//│ // Output\n//│ A String\n\nlistiter process ex_list1\n//│ = [Function: unit]\n//│ // Output\n//│ A String\n//│ 8250\n//│ true\n\n\n// let test2 = listiter (fun ex -> ex (fun t -> \n//   let arg1 = fst t\n//   and arg2 = fst (snd t)\n//   and eqf  = snd (snd t) in\n//   let areequal = eqf arg1 arg2\n//   in print_bool areequal )) ex_list2\n// ;;\ntest2 = listiterA (fun ex -> ex (fun ((t1, t2, t3)) ->\n  let arg1 = t1 in\n  let arg2 = t2 in\n  let eqf = t3 in\n  let areequal = eqf arg1 arg2 in\n  print_bool areequal )) ex_list2\n//│ test2: unit\n//│      = [Function: unit]\n//│ // Output\n//│ true\n//│ false\n//│ false\n\ntest2_ = listiter (fun ex -> ex (fun ((t1, t2, t3)) ->\n  let arg1 = t1 in\n  let arg2 = t2 in\n  let eqf = t3 in\n  let areequal = eqf arg1 arg2 in\n  print_bool areequal ))\n//│ test2_: List[(forall 'a 'b. (('a, 'b, 'a -> 'b -> bool,),) -> unit) -> anything] -> unit\n//│       = [Function (anonymous)]\n\ntest2_ ex_list2\n//│ = [Function: unit]\n//│ // Output\n//│ true\n//│ false\n//│ false\n\n\n\n// * ============ Annotated+untupled versions: ============\n\ndef make_ex1: ('x, 'x -> 'c) -> (forall 'b. (forall 'a. ('a, 'a -> 'c) -> 'b) -> 'b)\n//│ make_ex1: ('x, 'x -> 'c,) -> (forall 'a. ('a, 'a -> 'c,) -> 'b) -> 'b\n//│         = <missing implementation>\n\nmake_ex1 (x, f) k = k (x, f)\n//│ ('a, 'b,) -> (('a, 'b,) -> 'c) -> 'c\n//│   <:  make_ex1:\n//│ ('x, 'x -> 'c,) -> (forall 'a. ('a, 'a -> 'c,) -> 'b) -> 'b\n//│         = [Function: make_ex11]\n\nex1_1 = make_ex1 (\"A String\", print_string)\n//│ ex1_1: (forall 'a. ('a, 'a -> unit,) -> 'b) -> 'b\n//│      = [Function (anonymous)]\n\nex1_1 (fun (x, f) -> f x)\n//│ = undefined\n//│ // Output\n//│ A String\n\nex1_2 = if true then make_ex1 (42, print_int) else ex1_1\n//│ ex1_2: (forall 'a 'a0. ('a, 'a -> unit,) -> 'b & ('a0, 'a0 -> unit,) -> 'b) -> 'b\n//│      = [Function (anonymous)]\n\nex1_2 (fun (x, f) -> f x)\n//│ = undefined\n//│ // Output\n//│ 42\n\n\n// let make_ex2 x (f:['a] ('a * 'a * ('a -> 'a -> 'c)) -> 'b) = f x\n// ;;\ndef make_ex2: ('x, 'x, 'x -> 'c) -> (forall 'b. (forall 'a. ('a, 'a, 'a -> 'c) -> 'b) -> 'b)\n//│ make_ex2: ('x, 'x, 'x -> 'c,) -> (forall 'a. ('a, 'a, 'a -> 'c,) -> 'b) -> 'b\n//│         = <missing implementation>\n\nmake_ex2 (x, y, f) k = k (x, y, f)\n//│ ('a, 'b, 'c,) -> (('a, 'b, 'c,) -> 'd) -> 'd\n//│   <:  make_ex2:\n//│ ('x, 'x, 'x -> 'c,) -> (forall 'a. ('a, 'a, 'a -> 'c,) -> 'b) -> 'b\n//│         = [Function: make_ex21]\n\n// let ex_list1 = [ make_ex1 (\"A String\", print_string) ; \n// \t\t make_ex1 (8250, print_int) ;\n// \t\t make_ex1 (true, print_bool) ]\n// ;;\n//\nex_list1 = cons (make_ex1 (\"A String\", print_string))\n  (cons (make_ex1 (8250, print_int))\n  (cons (make_ex1 (true, print_bool)) nil))\n//│ ex_list1: List[forall 'b. (forall 'a 'a0 'a1. ('a, 'a -> unit,) -> 'b & ('a0, 'a0 -> unit,) -> 'b & ('a1, 'a1 -> unit,) -> 'b) -> 'b]\n//│         = Cons {\n//│             head: [Function (anonymous)],\n//│             tail: Cons {\n//│               head: [Function (anonymous)],\n//│               tail: Cons { head: [Function (anonymous)], tail: Nil {} }\n//│             }\n//│           }\n\n// let ex_list2 = [ make_ex2 (\"String\", \"String\", eqstring) ;\n// \t\t make_ex2 ( 1250, 4890, eqint) ;\n// \t\t make_ex2 ( true, false, eqbool) ]\n// ;;\nex_list2 = cons (make_ex2 (\"String\", \"String\", eqstring))\n  (cons (make_ex2 (1250, 4890, eqint))\n  (cons (make_ex2 (true, false, eqbool)) nil))\n//│ ex_list2: List[forall 'b. (forall 'a 'a0 'a1. ('a, 'a, 'a -> string -> bool,) -> 'b & ('a0, 'a0, 'a0 -> bool -> bool,) -> 'b & ('a1, 'a1, 'a1 -> int -> bool,) -> 'b) -> 'b]\n//│         = Cons {\n//│             head: [Function (anonymous)],\n//│             tail: Cons {\n//│               head: [Function (anonymous)],\n//│               tail: Cons { head: [Function (anonymous)], tail: Nil {} }\n//│             }\n//│           }\n\n// let test1 = listiter (fun ex -> ex (fun p -> (snd p) (fst p))) ex_list1\n// ;;\n\ntest1 = listiterA (fun ex -> ex (fun (a, b) -> b a)) ex_list1\n//│ test1: unit\n//│      = [Function: unit]\n//│ // Output\n//│ A String\n//│ 8250\n//│ true\n\ntest1_ = listiterA (fun ex -> ex (fun (a, b) -> b a))\n//│ test1_: List[(forall 'a 'b. ('a, 'a -> 'b,) -> 'b) -> unit] -> unit\n//│       = [Function (anonymous)]\n\ntest1_ ex_list1\n//│ = [Function: unit]\n//│ // Output\n//│ A String\n//│ 8250\n//│ true\n\n\n\n\n// (* Some examples for MLF inspired by standard encoding in System F. *)\n\n// type Void   = ['x] 'x\n// type Unit   = ['x] 'x -> 'x\n// type Int    = ['x] ('x -> 'x) -> ('x -> 'x)\n// type Bool   = ['x] (Unit -> 'x) -> (Unit -> 'x) -> 'x \ntype Fvoid = forall 'a. 'a\ntype Funit = forall 'a. 'a -> 'a\ntype Fint  = forall 'a. ('a -> 'a) -> ('a -> 'a)\ntype Fbool = forall 'a. (Funit -> 'a) -> (Funit -> 'a) -> 'a\n//│ Defined type alias Fvoid\n//│ Defined type alias Funit\n//│ Defined type alias Fint\n//│ Defined type alias Fbool\n\n// type Sum    = ['x] (Int -> 'x) -> (Int -> 'x) -> 'x\n// type Pair   = ['x] (Int -> Int -> 'x) -> 'x\n// type Triple = ['x] (Int -> Int -> Int -> 'x) -> 'x\ntype Sum    = forall 'a. (Fint -> 'a) -> (Fint -> 'a) -> 'a\ntype Pair   = forall 'a. (Fint -> Fint -> 'a) -> 'a\ntype Triple = forall 'a. (Fint -> Fint -> Fint -> 'a) -> 'a\n//│ Defined type alias Sum\n//│ Defined type alias Pair\n//│ Defined type alias Triple\n\n// (* Unit *)\n// let c_unit = fun x -> x\ndef c_unit = fun x -> x\n//│ c_unit: 'a -> 'a\n//│       = [Function: c_unit]\n\n\n// (* BOOLEANS, IFS, AND, OR, NOT. *)\n// let c_true  = fun a b -> a c_unit\ndef c_true = fun a -> fun b -> a c_unit\n//│ c_true: ((forall 'a. 'a -> 'a) -> 'b) -> anything -> 'b\n//│       = [Function: c_true]\n\n// let c_false = fun a b -> b c_unit\ndef c_false = fun a -> fun b -> b c_unit\n//│ c_false: anything -> ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│        = [Function: c_false]\n\n// let c_if (cond:Bool) c_then c_else = cond c_then c_else \ndef c_if (cond: Fbool) c_then c_else = cond c_then c_else\ndef c_if_ cond c_then c_else = cond c_then c_else\n//│ c_if: Fbool -> (Funit -> 'a) -> (Funit -> 'a) -> 'a\n//│     = [Function: c_if]\n//│ c_if_: ('a -> 'b -> 'c) -> 'a -> 'b -> 'c\n//│      = [Function: c_if_]\n\n// let c_and (a:Bool) (b:Bool) = c_if a (fun z -> b) (fun z -> c_false)\ndef c_and (a: Fbool) (b: Fbool) = c_if a (fun z -> b) (fun z -> c_false)\ndef c_and_ a b = c_if a (fun z -> b) (fun z -> c_false)\n//│ c_and: Fbool -> Fbool -> (anything -> ((forall 'a. 'a -> 'a) -> 'b) -> 'b | Fbool)\n//│      = [Function: c_and]\n//│ c_and_: Fbool -> 'a -> (anything -> ((forall 'b. 'b -> 'b) -> 'c) -> 'c | 'a)\n//│       = [Function: c_and_]\n\n// let c_or  (a:Bool) (b:Bool) = c_if a (fun z -> c_true) (fun z -> b)\ndef c_or (a: Fbool) (b: Fbool) = c_if a (fun z -> c_true) (fun z -> b)\ndef c_or_ a b = c_if a (fun z -> c_true) (fun z -> b)\n//│ c_or: Fbool -> Fbool -> (((forall 'a. 'a -> 'a) -> 'b) -> anything -> 'b | Fbool)\n//│     = [Function: c_or]\n//│ c_or_: Fbool -> 'a -> (((forall 'b. 'b -> 'b) -> 'c) -> anything -> 'c | 'a)\n//│      = [Function: c_or_]\n\n// let c_not (a:Bool) = c_if a (fun z -> c_false) (fun z -> c_true)\ndef c_not (a: Fbool) = c_if a (fun z -> c_false) (fun z -> c_true)\ndef c_not_ a = c_if a (fun z -> c_false) (fun z -> c_true)\n//│ c_not: Fbool -> ((forall 'a. 'a -> 'a) -> 'b) -> ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│      = [Function: c_not]\n//│ c_not_: Fbool -> ((forall 'a. 'a -> 'a) -> 'b) -> ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│       = [Function: c_not_]\n\n// let c_or = (c_or : Bool -> Bool -> Bool)\n\ndef c_or2 = c_or : Fbool -> Fbool -> Fbool\n//│ c_or2: Fbool -> Fbool -> Fbool\n//│      = [Function: c_or2]\n\ndef c_or2_ = c_or_ : Fbool -> Fbool -> Fbool\n//│ c_or2_: Fbool -> Fbool -> Fbool\n//│       = [Function: c_or2_]\n\n\n// (* CONSTRUCTORS FOR PAIRS ET TRIPLES. *)\n// let c_pair x y   = fun f -> f x y\ndef c_pair x y = fun f -> f x y\n//│ c_pair: 'a -> 'b -> ('a -> 'b -> 'c) -> 'c\n//│       = [Function: c_pair]\n\n// let c_trip x y z = fun f -> f x y z\ndef c_trip x y z = fun f -> f x y z\n//│ c_trip: 'a -> 'b -> 'c -> ('a -> 'b -> 'c -> 'd) -> 'd\n//│       = [Function: c_trip]\n\n\n// (* PROJECTIONS FOR PRODUCTS. *)\n// let c_1_2 (p:Pair) = p (fun x y -> x) \ndef c_1_2 (p: Pair) = p (fun x -> fun y -> x)\ndef c_1_2_ p = p (fun x -> fun y -> x)\n//│ c_1_2: Pair -> Fint\n//│      = [Function: c_1_2]\n//│ c_1_2_: ((forall 'a. 'a -> anything -> 'a) -> 'b) -> 'b\n//│       = [Function: c_1_2_]\n\n// let c_2_2 (p:Pair) = p (fun x y -> y) \ndef c_2_2 (p: Pair) = p (fun x -> fun y -> y)\ndef c_2_2_ p = p (fun x -> fun y -> y)\n//│ c_2_2: Pair -> Fint\n//│      = [Function: c_2_2]\n//│ c_2_2_: ((forall 'a. anything -> 'a -> 'a) -> 'b) -> 'b\n//│       = [Function: c_2_2_]\n\n// let c_1_3 (t:Triple) = t (fun x y z -> x)\ndef c_1_3 (t: Triple) = t (fun x -> fun y -> fun z -> x)\ndef c_1_3_ t = t (fun x -> fun y -> fun z -> x)\n//│ c_1_3: Triple -> Fint\n//│      = [Function: c_1_3]\n//│ c_1_3_: ((forall 'a. 'a -> anything -> anything -> 'a) -> 'b) -> 'b\n//│       = [Function: c_1_3_]\n\n// let c_2_3 (t:Triple) = t (fun x y z -> y) \ndef c_2_3 (t: Triple) = t (fun x -> fun y -> fun z -> y)\ndef c_2_3_ t = t (fun x -> fun y -> fun z -> y)\n//│ c_2_3: Triple -> Fint\n//│      = [Function: c_2_3]\n//│ c_2_3_: ((forall 'a. anything -> 'a -> anything -> 'a) -> 'b) -> 'b\n//│       = [Function: c_2_3_]\n\n// let c_3_3 (t:Triple) = t (fun x y z -> z) \ndef c_3_3 (t: Triple) = t (fun x -> fun y -> fun z -> z)\ndef c_3_3_ t = t (fun x -> fun y -> fun z -> z)\n//│ c_3_3: Triple -> Fint\n//│      = [Function: c_3_3]\n//│ c_3_3_: ((forall 'a. anything -> anything -> 'a -> 'a) -> 'b) -> 'b\n//│       = [Function: c_3_3_]\n\n\n// (* CONSTRUCTOR FOR A BINARY SUM. *)\n// let c_sumg = fun x fg fd -> fg x\ndef c_sumg = fun x -> fun fg -> fun fd -> fg x\n//│ c_sumg: 'a -> ('a -> 'b) -> anything -> 'b\n//│       = [Function: c_sumg]\n\n// let c_sumd = fun x fg fd -> fd x\ndef c_sumd = fun x -> fun fg -> fun fd -> fd x\n//│ c_sumd: 'a -> anything -> ('a -> 'b) -> 'b\n//│       = [Function: c_sumd]\n\n\n// (* CASE FOR A SUM. *)\n// let c_case (s:Sum) g d = s g d\ndef c_case (s: Sum) g d = s g d\ndef c_case_ s g d = s g d\n//│ c_case: Sum -> (Fint -> 'a) -> (Fint -> 'a) -> 'a\n//│       = [Function: c_case]\n//│ c_case_: ('a -> 'b -> 'c) -> 'a -> 'b -> 'c\n//│        = [Function: c_case_]\n\n\n// (* Integers. *)\n// let c_i0 = fun f x ->   x\ndef c_i0 = fun f -> fun x -> x\n//│ c_i0: anything -> 'a -> 'a\n//│     = [Function: c_i0]\n\n// let c_i1 = fun f x -> f x\ndef c_i1 = fun f -> fun x -> f x\n//│ c_i1: ('a -> 'b) -> 'a -> 'b\n//│     = [Function: c_i1]\n\n// let c_i2 = fun f x -> f (f x)\ndef c_i2 = fun f -> fun x -> f (f x)\n//│ c_i2: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│     = [Function: c_i2]\n\n// let c_succ (n:Int) = fun f x -> n f (f x)\ndef c_succ (n: Fint) = fun f -> fun x -> n f (f x)\ndef c_succ_ n = fun f -> fun x -> n f (f x)\n//│ c_succ: Fint -> (('a | 'b) -> 'a) -> 'b -> 'a\n//│       = [Function: c_succ]\n//│ c_succ_: ('a -> 'b -> 'c) -> ('d -> 'b & 'a) -> 'd -> 'c\n//│        = [Function: c_succ_]\n\n// let c_iszero (n:Int) = n (fun x -> c_false) c_true\ndef c_iszero (n: Fint) = n (fun x -> c_false) c_true\ndef c_iszero_ n = n (fun x -> c_false) c_true\n//│ c_iszero: Fint -> ((forall 'a. 'a -> 'a) -> 'b) -> ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│         = [Function: c_iszero]\n//│ c_iszero_: ((forall 'a. anything -> anything -> ((forall 'b. 'b -> 'b) -> 'a) -> 'a) -> (forall 'c. ((forall 'b. 'b -> 'b) -> 'c) -> anything -> 'c) -> 'd) -> 'd\n//│          = [Function: c_iszero_]\n\n// let c_add n (m:Int) = m c_succ n\n\ndef c_add n (m: Fint) = m c_succ n\n//│ c_add: (Fint & 'b) -> Fint -> ((('a | 'c) -> 'a) -> 'c -> 'a | 'b)\n//│      = [Function: c_add]\n\ndef c_add_ n m = m c_succ_ n\n//│ c_add_: 'a -> ((forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('e -> 'c & 'b) -> 'e -> 'd) -> 'a -> 'f) -> 'f\n//│       = [Function: c_add_]\n\n// let c_mul n (m:Int) = m (c_add n) c_i0\n\ndef c_mul m (n: Fint) = m (c_add n) c_i0\n//│ c_mul: ((Fint -> (forall 'a 'b. (('a | 'b) -> 'a) -> 'b -> 'a | Fint)) -> (forall 'c. anything -> 'c -> 'c) -> 'd) -> Fint -> 'd\n//│      = [Function: c_mul]\n\ndef c_mul_ m n = m (c_add_ n) c_i0\n//│ c_mul_: ((forall 'a. ((forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('e -> 'c & 'b) -> 'e -> 'd) -> 'f -> 'a) -> 'a) -> (forall 'g. anything -> 'g -> 'g) -> 'h) -> 'f -> 'h\n//│       = [Function: c_mul_]\n\n// let c_pow n (m:Int) = m (c_mul n) c_i1\n\ndef c_pow m (n: Fint) = m (c_mul n) c_i1\n//│ c_pow: ((Fint -> (forall 'a 'b. (('a | 'b) -> 'a) -> 'b -> ('b | 'a) | Fint)) -> (forall 'c 'd. ('c -> 'd) -> 'c -> 'd) -> 'e) -> Fint -> 'e\n//│      = [Function: c_pow]\n\ndef c_pow_ m n = m (c_mul_ n) c_i1\n//│ c_pow_: (('a -> 'b) -> (forall 'c 'd. ('c -> 'd) -> 'c -> 'd) -> 'e) -> ((forall 'f. ((forall 'g 'h 'i 'j. ('g -> 'h -> 'i) -> ('j -> 'h & 'g) -> 'j -> 'i) -> 'a -> 'f) -> 'f) -> (forall 'k. anything -> 'k -> 'k) -> 'b) -> 'e\n//│       = [Function: c_pow_]\n\n\n// let c_pred (n:Int) =\n//    let s p = c_pair (c_2_2 p) (c_succ (c_2_2 p))\n//   and z = c_pair c_i0 c_i0 in\n//   c_1_2 (n s z)\n\ndef c_pred (n: Fint) =\n  let s = fun p -> c_pair (c_2_2 p) (c_succ (c_2_2 p)) in\n  let z = c_pair c_i0 c_i0 in\n  c_1_2 (n s z)\n//│ c_pred: Fint -> Fint\n//│       = [Function: c_pred]\n\ndef c_pred_ n =\n  let s = fun p -> c_pair (c_2_2_ p) (c_succ_ (c_2_2_ p)) in\n  let z = c_pair c_i0 c_i0 in\n  c_1_2_ (n s z)\n//│ c_pred_: ((forall 'a 'b 'c 'd 'e 'f. ((forall 'g. anything -> 'g -> 'g) -> ('a -> 'b -> 'c & 'd)) -> ('d -> (('e -> 'b & 'a) -> 'e -> 'c) -> 'f) -> 'f) -> (forall 'h. ((forall 'i. anything -> 'i -> 'i) -> (forall 'i. anything -> 'i -> 'i) -> 'h) -> 'h) -> (forall 'j. 'j -> anything -> 'j) -> 'k) -> 'k\n//│        = [Function: c_pred_]\n\n\n// let c_printint (n:Int) = print_int (n (fun x -> x+1) 0); print \" \"\ndef c_printint (n: Fint) =\n  let _ = print_int (n (fun x -> x + 1) 0) in\n  print_string \" \"\ndef c_printint_ n =\n  let _ = print_int (n (fun x -> x + 1) 0) in\n  print_string \" \"\n//│ c_printint: Fint -> unit\n//│           = [Function: c_printint]\n//│ c_printint_: ((int -> int) -> 0 -> int) -> unit\n//│            = [Function: c_printint_]\n\ndef c_printint2 (n: Fint) = toString (n (fun x -> x + 1) 0)\ndef c_printint2_ n = toString (n (fun x -> x + 1) 0)\n//│ c_printint2: Fint -> string\n//│            = [Function: c_printint2]\n//│ c_printint2_: ((int -> int) -> 0 -> anything) -> string\n//│             = [Function: c_printint2_]\n\n// let c_i2 = c_succ c_i1\ndef c_i2 = c_succ c_i1\ndef c_i2_ = c_succ_ c_i1\n//│ c_i2: (('a | 'b) -> 'a) -> 'b -> 'a\n//│     = [Function: c_i21]\n//│ c_i2_: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│      = [Function: c_i2_]\n\n// let c_i3 = c_succ c_i2\ndef c_i3 = c_succ c_i2\ndef c_i3_ = c_succ_ c_i2\n//│ c_i3: (('a | 'b) -> 'a) -> 'b -> 'a\n//│     = [Function: c_i3]\n//│ c_i3_: ('b -> 'c & ('a | 'c) -> 'a) -> 'b -> 'a\n//│      = [Function: c_i3_]\n\n// let c_i4 = c_succ c_i3\ndef c_i4 = c_succ c_i3\ndef c_i4_ = c_succ_ c_i3\n//│ c_i4: (('a | 'b) -> 'a) -> 'b -> 'a\n//│     = [Function: c_i4]\n//│ c_i4_: ('b -> 'c & ('a | 'c) -> 'a) -> 'b -> 'a\n//│      = [Function: c_i4_]\n\n\n\n// (* Fails with value restriction. *)\n// (* Passes with relaxed value restriction. *)\n// let rec (to_church:int -> Int) n =\n//   if n = 0 then fun f x -> x\n//   else fun f x -> f ((to_church (n-1)) f x)\n\ndef to_church: int -> Fint\n//│ to_church: int -> Fint\n//│          = <missing implementation>\n\n// * See to_church_3 in `ex_casparticuliers.mls`\nrec def to_church n =\n  if n == 0 then fun f -> fun x -> x\n  else fun f -> fun x -> f ((to_church (n - 1) : Fint) f x)\n//│ int -> ('a -> ('a & 'b)) -> ('a & 'b) -> 'b\n//│   <:  to_church:\n//│ int -> Fint\n//│          = [Function: to_church]\n\n\n// let rec to_church n =\n//   if n = 0 then fun f x -> x\n//   else fun f x -> f ((to_church (n-1)) f x)\n\nrec def to_church_ n =\n  if n == 0 then fun f -> fun x -> x\n  else fun f -> fun x -> f ((to_church_ (n - 1)) f x)\n//│ to_church_: int -> ('a -> 'b & 'a -> 'a) -> ('a & 'b) -> 'b\n//│           = [Function: to_church_]\n\n\n// let rec c_fact (n:Int) =\n//   c_if (c_iszero n) (fun (u:Unit) -> c_i1)\n//     (fun (u:Unit) -> c_mul n (c_fact (c_pred n)))\n\nrec def c_fact (n: Fint) =\n  c_if (c_iszero n) (fun (u: Funit) -> c_i1)\n    (fun (u: Funit) -> c_mul n (c_fact (c_pred n)))\n//│ c_fact: Fint -> ((('a | 'b) -> 'a & 'b -> 'c) -> 'b -> ('a | 'b | 'c) | Fint)\n//│       = [Function: c_fact]\n\n// def c_fact: Fint -> (forall 'a 'b. ('a & 'b) -> (forall 'c 'd 'e 'f 'g 'h. (('c & 'h) -> ('d | 'g | 'c))))\ndef c_fact_A: Fint -> Fint\n//│ c_fact_A: Fint -> Fint\n//│         = <missing implementation>\n\ndef c_fact_A n =\n  c_if (c_iszero n) (fun u -> c_i1)\n    (fun u -> c_mul n (c_fact_A (c_pred n)))\n//│ (Fint & (Fint -> (forall 'a 'b. (('a | 'b) -> 'a) -> 'b -> 'a | Fint)) -> (forall 'c. anything -> 'c -> 'c) -> 'd) -> (('e -> 'f) -> 'e -> 'f | 'd)\n//│   <:  c_fact_A:\n//│ Fint -> Fint\n//│         = <no result>\n//│           c_fact_A is not implemented\n\n// * This one MLF probably can't type\n// * TODO: better type simplif...?\n:e\nrec def c_fact_ n =\n  c_if_ (c_iszero_ n) (fun _ -> c_i1)\n    (fun _ -> c_mul_ n (c_fact_ (c_pred_ n)))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (? -> 'j) -> 'k & (forall 'l. ((forall 'm 'n 'o 'p. ('m -> 'n -> 'o) -> ('p -> 'n & 'm) -> 'p -> 'o) -> 'k -> 'l) -> 'l) -> (forall 'c. ? -> 'c -> 'c) -> 'j & (forall 'q 'r 's 't 'u 'v. ((forall 'w. ? -> 'w -> 'w) -> ('q -> 'r -> 's & 't)) -> ('t -> (('u -> 'r & 'q) -> 'u -> 's) -> 'v) -> 'v) -> 'a)\n//│ ║  l.963: \t  c_1_2_ (n s z)\n//│ ╙──       \t          ^^^\n//│ c_fact_: 'a -> 'b\n//│   where\n//│     'a <: (forall 'c. anything -> anything -> ((forall 'd. 'd -> 'd) -> 'c) -> 'c) -> (forall 'e. ((forall 'd. 'd -> 'd) -> 'e) -> anything -> 'e) -> (forall 'f 'g. anything -> ('f -> 'g) -> 'f -> 'g) -> (anything -> 'h) -> 'b & (forall 'i. ((forall 'j 'k 'l 'm. ('j -> 'k -> 'l) -> ('m -> 'k & 'j) -> 'm -> 'l) -> 'b -> 'i) -> 'i) -> (forall 'n. anything -> 'n -> 'n) -> 'h & (forall 'o 'p 'q 'r 's 't. ((forall 'u. anything -> 'u -> 'u) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (('s -> 'p & 'o) -> 's -> 'q) -> 't) -> 't) -> (forall 'v. ((forall 'n. anything -> 'n -> 'n) -> (forall 'n. anything -> 'n -> 'n) -> 'v) -> 'v) -> (forall 'w. 'w -> anything -> 'w) -> 'a\n//│        = [Function: c_fact_]\n\n:e // * The type we infer without any annotations can't be checked against the desired signature\nc_fact_A = c_fact_\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. ? -> (? -> 'j -> 'j | 'k)) -> 'l & (forall 'm. ((forall 'n 'o 'p 'q. ('n -> 'o -> 'p) -> ('q -> 'o & 'n) -> 'q -> 'p) -> (forall 'r 's. ('r -> 's) -> 'r -> 's | 'l) -> 'm) -> 'm) -> (forall 'c. ? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. ? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a)\n//│ ║  l.963: \t  c_1_2_ (n s z)\n//│ ╙──       \t          ^^^\n//│ 'a -> 'b\n//│   where\n//│     'a <: (forall 'c. anything -> anything -> ((forall 'd. 'd -> 'd) -> 'c) -> 'c) -> (forall 'e. ((forall 'd. 'd -> 'd) -> 'e) -> anything -> 'e) -> (forall 'f 'g. anything -> ('f -> 'g) -> 'f -> 'g) -> (anything -> 'h) -> 'b & (forall 'i. ((forall 'j 'k 'l 'm. ('j -> 'k -> 'l) -> ('m -> 'k & 'j) -> 'm -> 'l) -> 'b -> 'i) -> 'i) -> (forall 'n. anything -> 'n -> 'n) -> 'h & (forall 'o 'p 'q 'r 's 't. ((forall 'u. anything -> 'u -> 'u) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (('s -> 'p & 'o) -> 's -> 'q) -> 't) -> 't) -> (forall 'v. ((forall 'n. anything -> 'n -> 'n) -> (forall 'n. anything -> 'n -> 'n) -> 'v) -> 'v) -> (forall 'w. 'w -> anything -> 'w) -> 'a\n//│   <:  c_fact_A:\n//│ Fint -> Fint\n//│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required\n//│ ║  l.1085: \tc_fact_A = c_fact_\n//│ ║          \t^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│         = [Function: c_fact_]\n\n\n// let print_fact n =\n//   print_string \"Factorial \" ;\n//   print_int n ;\n//   print_string \" = \" ;\n//   c_printint (c_fact (to_church n)) ;\n//   print_string \"\\n\" ;\n//   ()\ndef print_fact n =\n  let _ = print_string \"Factorial \" in\n  let _ = print_int n in\n  let _ = print_string \" = \" in\n  let _ = c_printint (c_fact (to_church n)) in\n          print_string \"\\n\"\n//│ print_fact: int -> unit\n//│           = [Function: print_fact]\n\n:e // * We get a cycle error because recursive `c_fact_` has NO annotations whatsoever\ndef print_fact_ n =\n  let _ = print_string \"Factorial \" in\n  let _ = print_int n in\n  let _ = print_string \" = \" in\n  let _ = c_printint_ (c_fact_ (to_church_ n)) in\n          print_string \"\\n\"\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. ? -> (? -> 'j -> 'j | 'k)) -> 'l & (forall 'm. ((forall 'n 'o 'p 'q. ('n -> 'o -> 'p) -> ('q -> 'o & 'n) -> 'q -> 'p) -> (forall 'r 's. ('r -> 's) -> 'r -> 's | 'l) -> 'm) -> 'm) -> (forall 'c. ? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. ? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a)\n//│ ║  l.963: \t  c_1_2_ (n s z)\n//│ ╙──       \t          ^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1124: \t  let _ = c_printint_ (c_fact_ (to_church_ n)) in\n//│ ║          \t                       ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ print_fact_: int -> unit\n//│            = [Function: print_fact_]\n// * Works when using the annotated `c_fact`:\ndef print_fact_ n =\n  let _ = print_string \"Factorial \" in\n  let _ = print_int n in\n  let _ = print_string \" = \" in\n  let _ = c_printint_ (c_fact (to_church_ n)) in\n          print_string \"\\n\"\n//│ print_fact_: int -> unit\n//│            = [Function: print_fact_1]\n\ndef print_fact2 n =\n  concat \"Factorial \" (\n  concat (toString n) (\n  concat \" = \"\n         (c_printint2 (c_fact (to_church n))) ))\n//│ print_fact2: int -> string\n//│            = [Function: print_fact2]\n\n:e // * Similar as above (bad `c_fact_`)\ndef print_fact2_ n =\n  concat \"Factorial_ \" (\n  concat (toString n) (\n  concat \" = \"\n         (c_printint2_ (c_fact_ (to_church_ n))) ))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. ? -> (? -> 'j -> 'j | 'k)) -> 'l & (forall 'm. ((forall 'n 'o 'p 'q. ('n -> 'o -> 'p) -> ('q -> 'o & 'n) -> 'q -> 'p) -> (forall 'r 's. ('r -> 's) -> 'r -> 's | 'l) -> 'm) -> 'm) -> (forall 'c. ? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. ? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a)\n//│ ║  l.963: \t  c_1_2_ (n s z)\n//│ ╙──       \t          ^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1160: \t         (c_printint2_ (c_fact_ (to_church_ n))) ))\n//│ ║          \t                        ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ print_fact2_: int -> string\n//│             = [Function: print_fact2_]\n// * Works when using the annotated `c_fact`:\ndef print_fact2_ n =\n  concat \"Factorial_ \" (\n  concat (toString n) (\n  concat \" = \"\n         (c_printint2_ (c_fact (to_church_ n))) ))\n//│ print_fact2_: int -> string\n//│             = [Function: print_fact2_1]\n\n// let essai =\n//   print_string \"Church integers :\\n\";\n//   let c_i5 = c_add c_i3 c_i2 in\n//   let c_i10 = c_mul c_i5 c_i2 in\n//   let c_i9 = c_pred c_i10 in\n//   let c_99 = c_add (c_mul c_i9 c_i10) c_i9 in\n//   let c_98 = c_pred c_99 in\n//   print_string \"This should be 98 : \" ;\n//   c_printint c_98;\n//   print_string \"\\n\\n\" ;\n\nthis_should_be_98 =\n  let c_i5 = c_add c_i3 c_i2 in\n  let c_i10 = c_mul c_i5 c_i2 in\n  let c_i9 = c_pred c_i10 in\n  let c_99 = c_add (c_mul c_i9 c_i10) c_i9 in\n  let c_98 = c_pred c_99 in\n  c_printint2 c_98\n//│ this_should_be_98: string\n//│                  = '98'\n\n// * [FCP:patho] This version without any type annotations doesn't work (probably also doesn't in MLF)\n:stats // * Note: subtyping takes too many steps when replacing both `c_mul_` by `c_mul`\n:e // * Not sure what's a minimal change to make this one work\nthis_should_be_98_ =\n  let c_i5_ = c_add_ c_i3_ c_i2_ in\n  let c_i10_ = c_mul_ c_i5_ c_i2_ in\n  let c_i9_ = c_pred_ c_i10_ in\n  let c_99_ = c_add_ (c_mul_ c_i9_ c_i10_) c_i9_ in\n  let c_98_ = c_pred_ c_99_ in\n  c_printint2_ c_98_\n//│ ╔══[ERROR] Inferred recursive type: nothing\n//│ ║  l.731: \ttype Fint  = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ╙──       \t                    ^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1207: \t  let c_i10_ = c_mul_ c_i5_ c_i2_ in\n//│ ║          \t               ^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1208: \t  let c_i9_ = c_pred_ c_i10_ in\n//│ ║          \t              ^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ this_should_be_98_: string\n//│                   = '98'\n//│ constrain calls  : 11252\n//│ annoying  calls  : 0\n//│ subtyping calls  : 38847\n\n// * Decomposing...\n\n:stats\nc_i5_ = c_add_ c_i3_ c_i2_\n//│ c_i5_: ('b -> 'c & 'c -> 'd & 'd -> 'e & ('a | 'e) -> 'a) -> 'b -> 'a\n//│      = [Function (anonymous)]\n//│ constrain calls  : 118\n//│ annoying  calls  : 0\n//│ subtyping calls  : 493\n\n:stats\n:e\nc_i10_ = c_mul_ c_i5_ c_i2_\n//│ ╔══[ERROR] Inferred recursive type: nothing\n//│ ║  l.731: \ttype Fint  = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ╙──       \t                    ^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1241: \tc_i10_ = c_mul_ c_i5_ c_i2_\n//│ ║          \t         ^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ c_i10_: error | ((forall 'a 'b 'c. ('a -> 'b & 'b -> 'c) -> 'a -> 'c | 'd) -> ('e -> 'f -> ('g & 'h & 'i & 'j & 'k & 'l & 'm) & 'n) & (('o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 's) -> 'o -> 'r | 'n) -> ('t -> 'u -> ('h & 'i & 'j & 'k & 'l & 'm) & 'v) & (('w -> ('f & 'o) & 'o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'e & 's) -> 'w -> 'g | 'v) -> ('x -> 'y -> ('i & 'j & 'k & 'l & 'm) & 'z) & (('a1 -> ('u & 'w) & 'w -> ('f & 'o) & 'o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'e & 's & 't) -> 'a1 -> 'h | 'z) -> ('b1 -> 'c1 -> ('j & 'k & 'l & 'm) & 'd1) & (('e1 -> ('y & 'a1) & 'a1 -> ('u & 'w) & 'w -> ('f & 'o) & 'o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'e & 's & 't & 'x) -> 'e1 -> 'i | 'd1) -> ('f1 -> 'g1 -> ('k & 'l & 'm) & 'h1) & (('i1 -> ('c1 & 'e1) & 'e1 -> ('y & 'a1) & 'a1 -> ('u & 'w) & 'w -> ('f & 'o) & 'o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'e & 's & 't & 'x & 'b1) -> 'i1 -> 'j | 'h1) -> ('j1 -> 'k1 -> ('l & 'm) & 'l1) & (('m1 -> ('g1 & 'i1) & 'i1 -> ('c1 & 'e1) & 'e1 -> ('y & 'a1) & 'a1 -> ('u & 'w) & 'w -> ('f & 'o) & 'o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'e & 's & 't & 'x & 'b1 & 'f1) -> 'm1 -> 'k | 'l1) -> ('n1 -> 'o1 -> 'm & 'p1) & (('q1 -> ('k1 & 'm1) & 'm1 -> ('g1 & 'i1) & 'i1 -> ('c1 & 'e1) & 'e1 -> ('y & 'a1) & 'a1 -> ('u & 'w) & 'w -> ('f & 'o) & 'o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'e & 's & 't & 'x & 'b1 & 'f1 & 'j1) -> 'q1 -> 'l | 'p1) -> ('r1 & 's1)) -> ('s -> 'p -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'd) -> (('t1 -> ('o1 & 'q1) & 'q1 -> ('k1 & 'm1) & 'm1 -> ('g1 & 'i1) & 'i1 -> ('c1 & 'e1) & 'e1 -> ('y & 'a1) & 'a1 -> ('u & 'w) & 'w -> ('f & 'o) & 'o -> 'p & 'p -> 'q & 'q -> ('g & 'h & 'i & 'j & 'k & 'l & 'm & 'r) & 'e & 's & 't & 'x & 'b1 & 'f1 & 'j1 & 'n1) -> 't1 -> 'm | 'r1) | 's1\n//│   where\n//│     's1 <: (forall 'u1 'v1 'w1 'x1. ('u1 -> 'v1 -> 'w1) -> ('x1 -> 'v1 & 'u1) -> 'x1 -> 'w1) -> (forall 'y1 'z1 'a2. ('y1 -> 'z1 & 'z1 -> 'a2) -> 'y1 -> 'a2) -> 's1\n//│       = [Function (anonymous)]\n//│ constrain calls  : 983\n//│ annoying  calls  : 0\n//│ subtyping calls  : 32252\n:stats\n// * This one works:\nc_i10_ = c_mul c_i5_ c_i2_\n//│ c_i10_: (('a | 'b) -> 'a & ('a0 | 'b) -> 'a0) -> 'b -> ('a | 'a0) | Fint\n//│       = [Function (anonymous)]\n//│ constrain calls  : 624\n//│ annoying  calls  : 0\n//│ subtyping calls  : 2474\n\n// * Ouchie (cf stats)\n:stats\nc_i9_ = c_pred_ c_i10_\n//│ c_i9_: ('a -> ('a & 'b) & 'c -> 'b & 'c -> 'c & 'd -> ('d & 'b) & 'e -> 'b & 'e -> 'e) -> ('a & 'b & 'c & 'd & 'e) -> 'b\n//│      = [Function (anonymous)]\n//│ constrain calls  : 2552\n//│ annoying  calls  : 0\n//│ subtyping calls  : 11102\n\n:stats\n:e\nc_99_ = c_add_ (c_mul_ c_i9_ c_i10_) c_i9_\n//│ ╔══[ERROR] Inferred recursive type: 'b\n//│   where\n//│     'b <: (forall 'c 'd 'e 'f. ('c -> 'd -> 'e) -> ('f -> 'd & 'c) -> 'f -> 'e) -> ((forall 'a 'g 'a0 'a1 'a2. (('a | 'g) -> 'a & ('a0 | 'g) -> 'a0 & ('a1 | 'g) -> 'a1 & ('a2 | 'g) -> 'a2) -> 'g -> ('a | 'a0 | 'a1 | 'a2) | Fint) -> ? & (forall 'a3 'h 'a4. (('a3 | 'h) -> 'a3 & ('a4 | 'h) -> 'a4) -> 'h -> ('a3 | 'a4) | Fint) -> anything)\n//│ ║  l.903: \tdef c_succ_ n = fun f -> fun x -> n f (f x)\n//│ ╙──       \t                                       ^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.1276: \tc_99_ = c_add_ (c_mul_ c_i9_ c_i10_) c_i9_\n//│ ║          \t                ^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ c_99_: error | ('a -> 'a & 'b -> 'b & 'c -> 'c & 'd -> 'd) -> ('a & 'b & 'c & 'd) -> error\n//│      = [Function (anonymous)]\n//│ constrain calls  : 3117\n//│ annoying  calls  : 0\n//│ subtyping calls  : 14864\n:stats\n// * Note: works with `c_mul` AND recursive types...\n:RecursiveTypes\nc_99_ = c_add_ (c_mul c_i9_ c_i10_) c_i9_\n//│ c_99_: ('b -> ('b & 'c & 'a & 'a0) & 'a -> ('c & 'a) & 'a0 -> ('c & 'a0) & 'd -> ('e & 'c & 'a1 & 'a2) & 'e -> ('e & 'c & 'a3 & 'a4) & 'a3 -> ('c & 'a3) & 'a4 -> ('c & 'a4) & 'a1 -> ('c & 'a1) & 'a2 -> ('c & 'a2) & 'f -> ('f & 'c & 'a5 & 'a6) & 'a5 -> ('c & 'a5) & 'a6 -> ('c & 'a6) & ('a7 | 'd) -> 'a7 & 'd -> ('g & 'c & 'a8 & 'a9) & 'g -> ('g & 'c & 'a10 & 'a11) & 'a10 -> ('c & 'a10) & 'a11 -> ('c & 'a11) & 'a8 -> ('c & 'a8) & 'a9 -> ('c & 'a9)) -> ('b & 'd & 'f & 'c) -> ('c | 'a7) | Fint\n//│      = [Function (anonymous)]\n//│ constrain calls  : 2217\n//│ annoying  calls  : 0\n//│ subtyping calls  : 22997\n:NoRecursiveTypes\n\n// * Ouchie++\n:stats\n:Fuel 20000\nc_98_ = c_pred_ c_99_\n//│ c_98_: ('a -> ('a & 'b) & 'c -> 'a & 'c -> 'c & 'd -> ('a & 'd) & 'e -> 'b & 'f -> 'e & 'f -> 'f & 'g -> ('e & 'g) & 'h -> ('e & 'h) & 'i -> 'h & 'i -> 'i & 'j -> ('h & 'j) & 'k -> ('k & 'b) & 'l -> 'k & 'l -> 'l & 'm -> ('k & 'm) & 'n -> ('n & 'b) & 'o -> 'b & 'o -> 'o & 'p -> 'b & 'q -> 'p & 'q -> 'q & 'r -> ('p & 'r) & 's -> ('p & 's) & 't -> 's & 't -> 't & 'u -> ('s & 'u)) -> ('a & 'c & 'd & 'b & 'e & 'f & 'g & 'h & 'i & 'j & 'k & 'l & 'm & 'n & 'o & 'p & 'q & 'r & 's & 't & 'u) -> 'b\n//│      = [Function (anonymous)]\n//│ constrain calls  : 11598\n//│ annoying  calls  : 0\n//│ subtyping calls  : 74107\n:ResetFuel\n\n\n//   print_fact 0 ;\n//   print_fact 1 ;\n//   print_fact 2 ;\n//   print_fact 3 ;\n//   print_fact 4 ;\n//   print_fact 5 ;\n//   print_fact 6 ;\n//   ()\nprint_fact2 0\nprint_fact2 1\nprint_fact2 2\nprint_fact2 3\nprint_fact2 4\nprint_fact2 5\nprint_fact2 6\n//│ res: string\n//│    = 'Factorial 0 = 1'\n//│ res: string\n//│    = 'Factorial 1 = 1'\n//│ res: string\n//│    = 'Factorial 2 = 2'\n//│ res: string\n//│    = 'Factorial 3 = 6'\n//│ res: string\n//│    = 'Factorial 4 = 24'\n//│ res: string\n//│    = 'Factorial 5 = 120'\n//│ res: string\n//│    = 'Factorial 6 = 720'\n\nprint_fact2_ 0\nprint_fact2_ 1\nprint_fact2_ 2\nprint_fact2_ 3\nprint_fact2_ 4\nprint_fact2_ 5\nprint_fact2_ 6\n//│ res: string\n//│    = 'Factorial_ 0 = 1'\n//│ res: string\n//│    = 'Factorial_ 1 = 1'\n//│ res: string\n//│    = 'Factorial_ 2 = 2'\n//│ res: string\n//│    = 'Factorial_ 3 = 6'\n//│ res: string\n//│    = 'Factorial_ 4 = 24'\n//│ res: string\n//│    = 'Factorial_ 5 = 120'\n//│ res: string\n//│    = 'Factorial_ 6 = 720'\n\n\n\n\n\n// * === Variation: With Constrained Types ===\n\n\n:DontDistributeForalls\n:ConstrainedTypes\n\n\ndef c_succ (n: Fint) = fun f -> fun x -> n f (f x)\ndef c_succ_ n = fun f -> fun x -> n f (f x)\n//│ c_succ: Fint -> (forall 'b. 'b -> (forall 'a 'c. 'c -> 'a\n//│   where\n//│     'b <: 'a -> 'a & 'c -> 'a))\n//│       = [Function: c_succ1]\n//│ c_succ_: 'a -> (forall 'b. 'b -> (forall 'c 'd 'e. 'e -> 'd\n//│   where\n//│     'a <: 'b -> 'c -> 'd\n//│     'b <: 'e -> 'c))\n//│        = [Function: c_succ_1]\n\ndef c_add_ n m = m c_succ_ n\n//│ c_add_: 'a -> (forall 'b. ((forall 'c. 'c -> (forall 'd. 'd -> (forall 'e 'f 'g. 'g -> 'f\n//│   where\n//│     'c <: 'd -> 'e -> 'f\n//│     'd <: 'g -> 'e))) -> 'a -> 'b) -> 'b)\n//│       = [Function: c_add_1]\n\n// let c_i1 = fun f x -> f x\ndef c_i1 = fun f -> fun x -> f x\n//│ c_i1: 'a -> (forall 'b 'c. 'b -> 'c\n//│   where\n//│     'a <: 'b -> 'c)\n//│     = [Function: c_i11]\n\n// let c_i2 = c_succ c_i1\ndef c_i2 = c_succ c_i1\ndef c_i2_ = c_succ_ c_i1\n//│ c_i2: 'b -> (forall 'a 'c. 'c -> 'a\n//│   where\n//│     'b <: 'a -> 'a & 'c -> 'a)\n//│     = [Function: c_i22]\n//│ c_i2_: 'a -> (forall 'b 'c 'd. 'd -> 'c\n//│   where\n//│     forall 'e. 'e -> (forall 'f 'g. 'f -> 'g\n//│       where\n//│         'e <: 'f -> 'g) <: 'a -> 'b -> 'c\n//│     'a <: 'd -> 'b)\n//│      = [Function: c_i2_1]\n\n// let c_i3 = c_succ c_i2\ndef c_i3 = c_succ c_i2\ndef c_i3_ = c_succ_ c_i2\n//│ c_i3: 'b -> (forall 'a 'c. 'c -> 'a\n//│   where\n//│     'b <: 'a -> 'a & 'c -> 'a)\n//│     = [Function: c_i31]\n//│ c_i3_: 'b -> (forall 'c 'd 'e. 'e -> 'd\n//│   where\n//│     forall 'f. 'f -> (forall 'a 'g. 'g -> 'a\n//│       where\n//│         'f <: 'a -> 'a & 'g -> 'a) <: 'b -> 'c -> 'd\n//│     'b <: 'e -> 'c)\n//│      = [Function: c_i3_1]\n\n:e\n:stats\nc_i5_ = c_add_ c_i3_ c_i2\n//│ ╔══[ERROR] Inferred recursive type: 'b\n//│   where\n//│     'b :> forall 'c. 'c -> (forall 'd 'e 'f 'g. 'f -> 'e\n//│       where\n//│         'c <: 'f -> 'd & 'f -> 'g\n//│         'b <: 'c -> 'd -> 'e\n//│         forall 'h. 'h -> (forall 'i 'j 'k. 'k -> 'j\n//│           where\n//│             forall 'l. 'l -> (forall 'a 'm. 'm -> 'a\n//│               where\n//│                 'l <: 'a -> 'a & 'm -> 'a) <: 'h -> 'i -> 'j\n//│             'h <: 'k -> 'i) <: 'c -> 'g -> 'e)\n//│ ╙──\n//│ c_i5_: 'b\n//│   where\n//│     'b :> forall 'c. 'c -> (forall 'd 'e 'f 'g. 'f -> 'e\n//│       where\n//│         'c <: 'f -> 'd & 'f -> 'g\n//│         'b <: 'c -> 'd -> 'e\n//│         forall 'h. 'h -> (forall 'i 'j 'k. 'k -> 'j\n//│           where\n//│             forall 'l. 'l -> (forall 'a 'm. 'm -> 'a\n//│               where\n//│                 'l <: 'a -> 'a & 'm -> 'a) <: 'h -> 'i -> 'j\n//│             'h <: 'k -> 'i) <: 'c -> 'g -> 'e)\n//│      = [Function (anonymous)]\n//│ constrain calls  : 107\n//│ annoying  calls  : 0\n//│ subtyping calls  : 378\n\n:stats\n:e\nc_i10_ = c_mul_ c_i5_ c_i2_\n//│ ╔══[ERROR] Inferred recursive type: nothing\n//│ ║  l.731: \ttype Fint  = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ╙──       \t                    ^^\n//│ ╔══[ERROR] Subtyping constraint of the form `forall ?a ?b ?c. ?b -> ?c -> ?a <: (forall ?d. ?d) -> ?e` exceeded recursion depth limit (250)\n//│ ║  l.1468: \tc_i10_ = c_mul_ c_i5_ c_i2_\n//│ ║          \t         ^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ c_i10_: error\n//│       = [Function (anonymous)]\n//│ constrain calls  : 3360\n//│ annoying  calls  : 0\n//│ subtyping calls  : 23503\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_hashtbl.mls",
    "content": ":NoRecursiveTypes\n:NoJS\n\n\n\n// ============ Dummy definitions to type the examples ============\n\n\nclass List[a]\n  method Get: a\ndef nil: List['a]\ndef cons[a]: a -> List[a] -> List[a]\ndef isnil: List['a] -> bool\ndef car: List['a] -> 'a\ndef cdr: List['a] -> List['a]\ndef fst: (('a, 'b),) -> 'a\ndef snd: (('a, 'b),) -> 'b\n//│ Defined class List[+a]\n//│ Declared List.Get: List['a] -> 'a\n//│ nil: List[nothing]\n//│ cons: 'a -> List['a] -> List['a]\n//│ isnil: List[?] -> bool\n//│ car: List['a] -> 'a\n//│ cdr: List['a] -> List['a]\n//│ fst: (('a, anything,),) -> 'a\n//│ snd: ((anything, 'b,),) -> 'b\n\n\n// (* Use the value restriction ! *)\n\n// type option ('a) = None | Some of 'a\nclass None\nclass Some[a]: { val: a }\ntype Option[a] = None | Some[a]\ndef none: Option['a]\ndef none = None {}\ndef some: 'a -> Option['a]\ndef some val = Some { val }\n//│ Defined class None\n//│ Defined class Some[+a]\n//│ Defined type alias Option[+a]\n//│ none: Option[nothing]\n//│ None\n//│   <:  none:\n//│ Option[nothing]\n//│ some: 'a -> Option['a]\n//│ 'val -> Some['val]\n//│   <:  some:\n//│ 'a -> Option['a]\n\ndef match_opt: forall 'a 'r. (() -> 'r, 'a -> 'r) -> Option['a] -> 'r\n//│ match_opt: (() -> 'r, 'a -> 'r,) -> Option['a] -> 'r\n\nmatch_opt (n, s) opt = case opt of\n  None -> n(),\n  Some -> s(opt.val)\n//│ (() -> 'a, 'val -> 'a,) -> (None | Some[?] & {val: 'val}) -> 'a\n//│   <:  match_opt:\n//│ (() -> 'r, 'a -> 'r,) -> Option['a] -> 'r\n\n\n\n// ============ The original examples ============\n\n\n// let create_hashtbl () = []\ndef create_hashtbl () = nil\n//│ create_hashtbl: () -> List[nothing]\n\n// let hashtbl_add table key element = (key, element) :: table\ndef hashtbl_add table key element = cons ((key, element)) table\n//│ hashtbl_add: List['a] -> 'b -> 'c -> List[('b, 'c,) | 'a]\n\n\n// let rec find table key = \n//   if nil table then None\n//   else if fst (car table) = key then Some (snd (car table))\n//   else find (cdr table) key\n\nrec def find table key =\n  if isnil table then none\n  else if eq (fst (car table)) key then some (snd (car table))\n  else find (cdr table) key\n//│ find: List[(anything, 'a,)] -> anything -> Option['a]\n\n// :ns\n// find\n\n:ng\nfind(error:List[(int, string)])(unit)\n//│ res: Option[string]\n\n\n// * Versions with `_A` are versions we annotate that weren't originally annotated\ndef find_A: forall 'a 'b. List[('a, 'b)] -> 'a -> Option['b]\n//│ find_A: List[(anything, 'b,)] -> anything -> Option['b]\n\ndef find_A table key =\n  if isnil table then none\n  else if eq (fst (car table)) key then some (snd (car table))\n  else find_A (cdr table) key\n//│ List[(anything, 'b,)] -> anything -> Option['b]\n//│   <:  find_A:\n//│ List[(anything, 'b,)] -> anything -> Option['b]\n\n\n// let nfind table key =\n//   begin match find table key with\n//   | None -> fun f x -> x\n//   | Some n -> n\n//   end\n\ndef nfind table key =\n  match_opt (\n    fun () -> fun f -> fun x -> x,\n    fun v -> v\n  ) (find table key)\n//│ nfind: List[(anything, 'a,)] -> anything -> (anything -> 'b -> 'b | 'a)\n\n\n// type Int = ['a] ('a -> 'a) -> ('a -> 'a)\ntype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ Defined type alias ChurchInt\n\n// let succ (n:Int) = fun f x -> f (n f x)\ndef succ (n: ChurchInt) = fun f -> fun x -> f (n f x)\n//│ succ: ChurchInt -> ('a -> ('a & 'b)) -> 'a -> 'b\n\n// * Versions with `_` are versions where we removed the annotatation\ndef succ_ n = fun f -> fun x -> f (n f x)\n//│ succ_: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n\n// let add (n:Int) (m:Int) = n succ m\ndef add (n: ChurchInt) (m: ChurchInt) = n succ m\ndef add_ n m = n succ_ m\n//│ add: ChurchInt -> ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n//│ add_: ((forall 'a 'b 'c 'd. ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd) -> 'e -> 'f) -> 'e -> 'f\n\n// let printInt (n:Int) = print (n (fun x -> x+1) 0)\ndef printInt (n: ChurchInt) = toString (n (fun x -> x + 1) 0)\ndef printInt_ n = toString (n (fun x -> x + 1) 0)\n//│ printInt: ChurchInt -> string\n//│ printInt_: ((int -> int) -> 0 -> anything) -> string\n\n// let table = create_hashtbl ()\n// let table = hashtbl_add table \"one\" (fun f x -> f x)\n// let table = hashtbl_add table \"two\" (fun f x -> f (f x))\ntable = create_hashtbl ()\ntable = hashtbl_add table \"one\" (fun f -> fun x -> f x)\ntable = hashtbl_add table \"two\" (fun f -> fun x -> f (f x))\n//│ table: List[nothing]\n//│ table: List[(\"one\", forall 'a 'b. ('a -> 'b) -> 'a -> 'b,)]\n//│ table: List[(\"one\" | \"two\", forall 'a 'b 'c. ('a -> 'b & 'b -> 'c & 'a -> 'c) -> 'a -> 'c,)]\n\n// let zog =\n//   printInt (add (nfind table \"one\") (nfind table \"two\"))\n:stats\nzog = printInt (add (nfind table \"one\") (nfind table \"two\"))\n//│ zog: string\n//│ constrain calls  : 3206\n//│ annoying  calls  : 56\n//│ subtyping calls  : 16169\n\n// * Some subexpressions typed individually:\n\n:stats\na = add (nfind table \"one\")\n//│ a: ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n//│ constrain calls  : 1556\n//│ annoying  calls  : 28\n//│ subtyping calls  : 7972\n\n:stats\nb = (nfind table \"two\")\n//│ b: ('a -> 'b & 'b -> 'c & 'a -> 'c & 'a -> 'd & 'd -> 'c & 'a -> 'e & 'e -> 'c & 'a -> 'f & 'f -> 'c & 'a -> 'g & 'g -> 'c) -> 'a -> ('c | 'a)\n//│ constrain calls  : 767\n//│ annoying  calls  : 28\n//│ subtyping calls  : 7102\n\n:stats\nb (fun x -> x)\n//│ res: 'a -> 'a\n//│ constrain calls  : 640\n//│ annoying  calls  : 0\n//│ subtyping calls  : 4884\n\nb (fun x -> x (not x))\n//│ res: nothing -> nothing\n\nb (fun x -> 0)\n//│ res: 'a -> (0 | 'a)\n\n// * Note: this one required `:DistributeForalls`\n:stats\na b\n//│ res: ('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt\n//│ constrain calls  : 759\n//│ annoying  calls  : 0\n//│ subtyping calls  : 4467\n\n\n// * [FCP:patho] !! Note the stats here for this fully annotation-free version\n:stats\n// ==========================================================================================\n:Fuel 20000\nzog_ = printInt_ (add_ (nfind table \"one\") (nfind table \"two\"))\n//│ zog_: string\n//│ constrain calls  : 22066\n//│ annoying  calls  : 56\n//│ subtyping calls  : 71169\n\n:stats\na_ = add_ (nfind table \"one\")\n//│ a_: ('a -> 'b -> 'c & 'a -> 'b -> 'd & 'a -> 'b -> 'e & 'a -> 'b -> 'f & 'a -> 'b -> 'g & 'a -> 'b -> 'h & 'a -> 'b -> 'i & 'a -> 'b -> 'j & 'a -> 'b -> 'k & 'a -> 'b -> 'l & 'a -> 'b -> 'm & 'a -> 'b -> 'n & 'a -> 'b -> 'o & 'a -> 'b -> 'p & 'a -> 'b -> 'q & 'a -> 'b -> 'r & 's) -> (('c -> 't & 'd -> 't & 'e -> 't & 'f -> 't & 'u -> 't & 'g -> 'u & 'v -> 't & 'h -> 'v & 'w -> 't & 'i -> 'w & 'x -> 't & 'j -> 'x & 'k -> 't & 'l -> 't & 'm -> 't & 'n -> 't & 'y -> 't & 'o -> 'y & 'z -> 't & 'p -> 'z & 'a1 -> 't & 'q -> 'a1 & 'b1 -> 't & 'r -> 'b1 & 'a) -> 'b -> 't | 's)\n//│ constrain calls  : 1794\n//│ annoying  calls  : 28\n//│ subtyping calls  : 15835\n\n:stats\na_ b\n//│ res: ('a -> 'b & 'b -> 'c & 'a -> 'c & 'a -> 'd & 'd -> 'c & 'a -> 'e & 'e -> 'c & 'a -> 'f & 'f -> 'c & 'a -> 'g & 'g -> 'c & 'h -> 'i & 'j -> 'h & 'k -> ('j & 'l) & 'l -> 'j & 'm -> 'i & 'n -> 'm & 'k -> ('n & 'o) & 'o -> 'n & 'p -> 'i & 'q -> 'p & 'k -> ('q & 'r) & 'r -> 'q & 's -> 'i & 't -> 's & 'k -> ('t & 'u) & 'u -> 't & 'v -> 'i & 'k -> ('v & 'w) & 'w -> 'v & 'x -> 'i & 'k -> ('x & 'y) & 'y -> 'x & 'z -> 'i & 'k -> ('z & 'a1) & 'a1 -> 'z & 'b1 -> 'i & 'k -> ('b1 & 'c1) & 'c1 -> 'b1 & 'd1 -> 'i & 'e1 -> 'd1 & 'k -> ('e1 & 'f1) & 'f1 -> 'e1 & 'g1 -> 'i & 'h1 -> 'g1 & 'k -> ('h1 & 'i1) & 'i1 -> 'h1 & 'j1 -> 'i & 'k1 -> 'j1 & 'k -> ('k1 & 'l1) & 'l1 -> 'k1 & 'm1 -> 'i & 'n1 -> 'm1 & 'k -> ('n1 & 'o1) & 'o1 -> 'n1 & 'p1 -> 'i & 'k -> ('p1 & 'q1) & 'q1 -> 'p1 & 'r1 -> 'i & 'k -> ('r1 & 's1) & 's1 -> 'r1 & 't1 -> 'i & 'k -> ('t1 & 'u1) & 'u1 -> 't1 & 'v1 -> 'i & 'k -> ('v1 & 'w1) & 'w1 -> 'v1) -> ('a & 'j & 'k & 'n & 'q & 't & 'v & 'x & 'z & 'b1 & 'e1 & 'h1 & 'k1 & 'n1 & 'p1 & 'r1 & 't1 & 'v1) -> ('c | 'a | 'i)\n//│ constrain calls  : 8808\n//│ annoying  calls  : 0\n//│ subtyping calls  : 182765\n:ResetFuel\n// ==========================================================================================\n\n\n\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_predicative.mls",
    "content": ":NoRecursiveTypes\n\n// * In these tests, argument generalization is sometimes needed; I have annotated where.\n:GeneralizeArguments\n\n\n// type bot = 0;;\ntype Bot = forall 'a. 'a\n//│ Defined type alias Bot\n\n// (* Rank 6 with intersection types, untypable in predicative System F,\n//    typable in impredicative System F *)\n\n\n// let imp (z : bot) =\n//   (fun (x : ['a] ('a -> 'u) -> 'v) -> x x)\n//   (fun (y : 'a -> bot) -> y z y);;\ndef imp (z: Bot) =\n  (fun (x: forall 'a. ('a -> 'u) -> 'v) -> x x)\n  (fun (y: 'a -> Bot) -> y z y)\n//│ imp: Bot -> nothing\n//│    = [Function: imp]\n\ndef imp' z =\n  (fun x -> x x)\n  (fun y -> y z y)\n//│ imp': ('a -> 'a -> (forall 'b 'c. ('a -> 'b -> 'c & 'b) -> 'c) -> 'd & 'a) -> 'd\n//│     = [Function: imp$]\n\n\n// (* Quelques constantes. *)\n\n// type sid = ['a] 'a -> 'a\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\n// let id = fun x -> x\n// ;;\ndef id = fun x -> x\n//│ id: 'a -> 'a\n//│   = [Function: id]\n\n// let delta = fun (x:sid) -> x x\n// ;;\ndef delta = fun (x: Sid) -> x x\ndef delta' = fun x -> x x\n//│ delta: Sid -> Sid\n//│      = [Function: delta]\n//│ delta': ('a -> 'b & 'a) -> 'b\n//│       = [Function: delta$]\n\n// delta id ;;\ndelta id\ndelta' id\n//│ res: Sid\n//│    = [Function: id]\n//│ res: 'a -> 'a\n//│    = [Function: id]\n\n// let t a b c d e = (fun x -> a x x) ((fun y -> b (c y)) (d e)) ;;\ndef t a b c d e = (fun x -> a x x) ((fun y -> b (c y)) (d e))\n//│ t: ('a -> 'a -> 'b) -> ('c -> 'a) -> ('d -> 'c) -> ('e -> 'd) -> 'e -> 'b\n//│  = [Function: t]\n\n// let t w z a b = (fun y -> (fun x -> w (x y) z) a) b ;;\ndef t w z a b = (fun y -> (fun x -> w (x y) z) a) b\n//│ t: ('a -> 'b -> 'c) -> 'b -> ('d -> 'a) -> 'd -> 'c\n//│  = [Function: t1]\n\n// let t y a = (fun x -> x (x y)) ((fun z -> z) (fun x -> a x)) ;;\ndef t y a = (fun x -> x (x y)) ((fun z -> z) (fun x -> a x))\n//│ t: 'a -> (('b | 'a) -> 'b) -> 'b\n//│  = [Function: t2]\n\n// (* Rank 1 *)\n// (fun x -> fun y -> x y) (fun y -> fun x -> x y) ;;\n// * Note that the `forall` is not distributed out because there's no enclosing polymorphic type here!\n(fun x -> fun y -> x y) (fun y -> fun x -> x y)\n//│ res: 'a -> (forall 'b. ('a -> 'b) -> 'b)\n//│    = [Function (anonymous)]\n\n// (* Rank 3 *)\n// (fun x -> fun y -> x) delta ;;\n(fun x -> fun y -> x) delta\n(fun x -> fun y -> x) delta'\n//│ res: anything -> Sid -> Sid\n//│    = [Function (anonymous)]\n//│ res: anything -> (forall 'a 'b. ('a -> 'b & 'a) -> 'b)\n//│    = [Function (anonymous)]\n\n// (* Rank 5 *)\n// (fun x -> fun y -> x y) (fun y -> fun x -> x y) delta ;;\n(fun x -> fun y -> x y) (fun y -> fun x -> x y) delta\n(fun x -> fun y -> x y) (fun y -> fun x -> x y) delta'\n//│ res: ((Sid -> Sid) -> 'a) -> 'a\n//│    = [Function (anonymous)]\n//│ res: ((forall 'a 'b. ('a -> 'b & 'a) -> 'b) -> 'c) -> 'c\n//│    = [Function (anonymous)]\n\n// (* Rank 8 *)\n// (fun (x:sid) -> x x x x x) id delta ;;\n(fun (x: Sid) -> x x x x x) id delta\n(fun x -> x x x x x) id delta'\n//│ res: Sid -> Sid\n//│    = [Function: delta]\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: delta$]\n\n// (* Rank 2 *)\n// type sk = ['a,'b] 'a -> 'b -> 'a;;\n// (fun (f:sk) -> fun x -> f f x) (fun v -> fun w -> v) ;;\ntype Sk = forall 'a 'b. 'a -> 'b -> 'a\n(fun (f: Sk) -> fun x -> f f x) (fun v -> fun w -> v)\n(fun f -> fun x -> f f x) (fun v -> fun w -> v)\n//│ Defined type alias Sk\n//│ res: anything -> Sk\n//│    = [Function (anonymous)]\n//│ res: anything -> (forall 'a. 'a -> anything -> 'a)\n//│    = [Function (anonymous)]\n\n// (* Rank 3 *)\n// (fun t -> fun k -> t k) (fun (f:sk) -> fun x -> f f x) (fun v -> fun w -> v);;\n(fun t -> fun k -> t k) (fun (f: Sk) -> fun x -> f f x) (fun v -> fun w -> v)\n(fun t -> fun k -> t k) (fun f -> fun x -> f f x) (fun v -> fun w -> v)\n//│ res: anything -> Sk\n//│    = [Function (anonymous)]\n//│ res: anything -> (forall 'a. 'a -> anything -> 'a)\n//│    = [Function (anonymous)]\n\n\n// let k = fun x y -> x\n// let k' = fun x y -> y\n// let app = fun f x -> f x\n// let two = fun f x -> f (f x)\n// let three = fun f x -> f (f (f x))\ndef k = fun x -> fun y -> x\ndef k2 = fun x -> fun y -> y\ndef app = fun f -> fun x -> f x\ndef two = fun f -> fun x -> f (f x)\ndef three = fun f -> fun x -> f (f (f x))\n//│ k: 'a -> anything -> 'a\n//│  = [Function: k]\n//│ k2: anything -> 'a -> 'a\n//│   = [Function: k2]\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = [Function: app]\n//│ two: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│    = [Function: two]\n//│ three: ('a -> 'b & 'b -> 'c & 'c -> 'd) -> 'a -> 'd\n//│      = [Function: three]\n\n\n:e // * Note: this test case of ours works when generalizing the LHS of ascriptions\n(app id): Sid\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.154: \t(app id): Sid\n//│ ║         \t^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.34: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║        \t                      ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.34: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║        \t                            ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.138: \tdef app = fun f -> fun x -> f x\n//│ ╙──       \t                            ^^^\n//│ res: Sid\n//│    = [Function (anonymous)]\n// * this one works:\nlet t = app id in t: Sid\n//│ res: Sid\n//│    = [Function (anonymous)]\n\n\n// type Int = ['a] ('a -> 'a) -> ('a -> 'a)\n// ;;\ntype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ Defined type alias ChurchInt\n\n\n// (* Factorial of two and three *)\n// (* Only ONE annotation ! *)\n// let t y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun (n:Int) -> n (fun v -> k') k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k') (fun f -> fun x -> f (p k' f x))) (fun s -> s k' k') k) g) x)) two ;;\n\n// * [FCP-LIM] requires :GeneralizeArguments\ndef t y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun (n: ChurchInt) -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) two\n//│ t: ('b -> 'a -> 'a) -> ('c -> 'd & 'a -> 'a & 'b) -> ('a & 'c) -> ('d | 'a)\n//│  = [Function: t3]\n\nt id succ 0\n//│ res: int\n//│    = 2\n\n// * Same as above but WITHOUT the type annotation (unlike MLF)\n:e\ndef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) two\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: ? -> (forall 'b. 'b) -> 'c\n//│     'b :> forall 'd 'e. ((forall 'f. ? -> 'f -> 'f) -> (forall 'f. ? -> 'f -> 'f) -> 'd & 'e) -> (? -> 'e | 'd) | 'c\n//│     'c :> 'g\n//│        <: (forall 'f. ? -> 'f -> 'f) -> (? -> ? -> ? & 'h)\n//│     'g :> forall 'b 'i. 'i -> 'i | 'b\n//│        <: (forall 'f. ? -> 'f -> 'f) -> (? -> ? -> ? & 'h)\n//│     'h <: (forall 'j. ? -> ? -> 'j -> 'j) -> (forall 'k. 'k -> ? -> 'k) -> (forall 'l 'm. ('l -> 'm) -> 'l -> 'm) -> (? -> 'n -> 'g) -> 'a & (forall 'o 'p 'q 'r 's. ((forall 'f. ? -> 'f -> 'f) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (forall 't. ('q -> 't & 'o) -> 'p -> 't) -> 's) -> 's) -> (forall 'u. ((forall 'f. ? -> 'f -> 'f) -> (forall 'f. ? -> 'f -> 'f) -> 'u) -> 'u) -> (forall 'k. 'k -> ? -> 'k) -> ? & ? -> 'n -> 'g\n//│     'n :> forall 'b. 'b\n//│        <: ? & 'g\n//│ ║  l.197: \tdef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) two\n//│ ╙──       \t                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.197: \tdef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) two\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ t_: (nothing -> anything) -> error\n//│   = [Function: t_]\n\nt_ id succ 0\n//│ res: error\n//│    = 2\n\n// * Works with CT:\n:ConstrainedTypes\ndef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) two\n//│ t_: 'a -> 'b -> ('c -> 'd\n//│   where\n//│     forall 'e 'f 'g. ('e -> 'f & 'f -> 'g) -> 'e -> 'g <: (forall 'h. 'h\n//│       where\n//│         forall 'i. 'i\n//│           where\n//│             forall 'j 'k 'l. 'j -> ((forall 'm. anything -> anything -> 'm -> 'm) -> (forall 'n. 'n -> anything -> 'n) -> (forall 'o 'p. ('o -> 'p) -> 'o -> 'p) -> (forall 'q 'r 's. 'q -> ('r -> 's\n//│               where\n//│                 'k <: (forall 't. 't\n//│                   where\n//│                     'j <: (forall 'u. 'u\n//│                       where\n//│                         'k <: (forall 'v 'w. 'v -> ((forall 'x. 'x\n//│                           where\n//│                             'v <: (forall 'y. anything -> 'y -> 'y) -> 'x) -> (forall 'z 'a1 'b1. 'z -> ('a1 -> 'b1\n//│                           where\n//│                             'z <: (forall 'c1. 'c1\n//│                               where\n//│                                 'v <: (forall 'y. anything -> 'y -> 'y) -> 'z -> 'a1 -> 'c1) -> 'b1)) -> 'w) -> 'w) -> (forall 'd1. ((forall 'y. anything -> 'y -> 'y) -> (forall 'y. anything -> 'y -> 'y) -> 'd1) -> 'd1) -> (forall 'n. 'n -> anything -> 'n) -> 'u) -> 'q -> 't) -> 'r -> 's)) -> 'l & 'k) -> 'l <: (forall 'e1. 'e1\n//│               where\n//│                 forall 'j 'k 'l. 'j -> ((forall 'm. anything -> anything -> 'm -> 'm) -> (forall 'n. 'n -> anything -> 'n) -> (forall 'o 'p. ('o -> 'p) -> 'o -> 'p) -> (forall 'q 'r 's. 'q -> ('r -> 's\n//│                   where\n//│                     'k <: (forall 't. 't\n//│                       where\n//│                         'j <: (forall 'u. 'u\n//│                           where\n//│                             'k <: (forall 'v 'w. 'v -> ((forall 'x. 'x\n//│                               where\n//│                                 'v <: (forall 'y. anything -> 'y -> 'y) -> 'x) -> (forall 'z 'a1 'b1. 'z -> ('a1 -> 'b1\n//│                               where\n//│                                 'z <: (forall 'c1. 'c1\n//│                                   where\n//│                                     'v <: (forall 'y. anything -> 'y -> 'y) -> 'z -> 'a1 -> 'c1) -> 'b1)) -> 'w) -> 'w) -> (forall 'd1. ((forall 'y. anything -> 'y -> 'y) -> (forall 'y. anything -> 'y -> 'y) -> 'd1) -> 'd1) -> (forall 'n. 'n -> anything -> 'n) -> 'u) -> 'q -> 't) -> 'r -> 's)) -> 'l & 'k) -> 'l <: (anything -> 'a) -> 'e1) -> 'i <: (forall 'f1. 'f1\n//│           where\n//│             forall 'e 'f 'g. ('e -> 'f & 'f -> 'g) -> 'e -> 'g <: (forall 'v 'g1. 'v -> ((forall 'x. 'x\n//│               where\n//│                 'v <: (forall 'y. anything -> 'y -> 'y) -> 'x) -> (forall 'z 'a1 'b1. 'z -> ('a1 -> 'b1\n//│               where\n//│                 'z <: (forall 'c1. 'c1\n//│                   where\n//│                     'v <: (forall 'y. anything -> 'y -> 'y) -> 'z -> 'a1 -> 'c1) -> 'b1)) -> 'g1) -> 'g1) -> (forall 'd1. ((forall 'y. anything -> 'y -> 'y) -> (forall 'y. anything -> 'y -> 'y) -> 'd1) -> 'd1) -> (forall 'n. 'n -> anything -> 'n) -> 'f1) -> 'b -> 'h) -> 'c -> 'd)\n//│   = [Function: t_1]\n:NoConstrainedTypes\n\nt_ id succ 0\n//│ res: int\n//│    = 2\n\n\n// let t y = (fun h -> h (h (h (h (fun x -> y))))) (fun f -> fun (n:Int) -> n (fun v -> k') k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k') (fun f -> fun x -> f (p k' f x))) (fun s -> s k' k') k) g) x)) three\n\n// * [FCP-LIM] requires :GeneralizeArguments\ndef t y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun (n: ChurchInt) -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three\n//│ t: ('b -> 'a -> 'a) -> ('c -> 'd & 'a -> 'a & 'b) -> ('a & 'c) -> ('d | 'a)\n//│  = [Function: t4]\n\n// * Same as above but WITHOUT the type annotation (unlike MLF)\n// * Interestingly this one does NOT require CT\n:Fuel 6000\n:e // occurs-check\ndef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three\n//│ ╔══[ERROR] Inferred recursive type: ? -> (((forall 'a. nothing -> ('a -> 'a | ?) | ?) | 'b) -> ((forall 'c. ? -> 'c -> 'c) -> nothing & 'd) & (forall 'e 'f. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'e & 'f) -> (? -> 'f | 'e) | ? | 'd) -> ((forall 'c. ? -> 'c -> 'c) -> nothing & 'b))\n//│ ║  l.285: \tdef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three\n//│ ╙──       \t                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ t_: ('a -> ((forall 'b 'c. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'b & 'c) -> (anything -> 'c | 'b) | 'e | 'f | 'g | 'h | 'i | 'j) -> 'g & 'k)) -> ('a & 'l) -> ((forall 'd. anything -> 'd -> 'd) -> ((forall 'm 'n 'o 'p 'q 'r. ((forall 'd. anything -> 'd -> 'd) -> ('m -> 'n -> 'o & 'p)) -> ('p -> (forall 's. ('o -> 's & 'm) -> 'n -> 's) -> 'q) -> ('r -> 'r | 'q) | 'k | 't) -> (forall 'u 'v. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'u & 'v) -> (anything -> 'v | 'u) | 'f | 'g | 'h | 'i | 'w) -> 'e & 'x) & 'i) -> ('g | 'h)\n//│   where\n//│     'e :> forall 'y 'z. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'y & 'z & 'y) -> (anything -> 'z | 'y) | 'f | 'g | 'h | 'i\n//│        <: (forall 'd. anything -> 'd -> 'd) -> nothing -> nothing -> anything\n//│     'f :> forall 'a1 'b1. ((forall 'c1 'd1. anything -> 'c1 -> ('d1 -> 'd1 | 'c1) | 'x) -> (forall 'e1. ('e -> 'e1 & 't) -> ('e & 'w) -> 'e1) -> 'a1) -> ('b1 -> 'b1 | 'a1) | 'g\n//│        <: (forall 'd. anything -> 'd -> 'd) -> (nothing -> nothing -> anything & 'f1)\n//│     'g <: (forall 'd. anything -> 'd -> 'd) -> ((forall 'm 'n 'o 'p 'q 'r. ((forall 'd. anything -> 'd -> 'd) -> ('m -> 'n -> 'o & 'p)) -> ('p -> (forall 's. ('o -> 's & 'm) -> 'n -> 's) -> 'q) -> ('r -> 'r | 'q) | 'k | 't) -> (forall 'g1 'h1. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'g1 & 'h1) -> (anything -> 'h1 | 'g1) | 'f | 'g | 'h | 'i | 'w) -> 'e & 'x & 'f1)\n//│     'f1 <: (forall 'i1. anything -> anything -> 'i1 -> 'i1) -> (forall 'j1. 'j1 -> anything -> 'j1) -> (forall 'k1 'l1. ('k1 -> 'l1) -> 'k1 -> 'l1) -> ('a -> ('e & 'w & 'j) -> 'g) -> 'l -> ('f -> ((forall 'd. anything -> 'd -> 'd) -> ((forall 'm 'n 'o 'p 'q 'r. ((forall 'd. anything -> 'd -> 'd) -> ('m -> 'n -> 'o & 'p)) -> ('p -> (forall 's. ('o -> 's & 'm) -> 'n -> 's) -> 'q) -> ('r -> 'r | 'q) | 'k | 't) -> (forall 'm1 'n1. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'm1 & 'n1) -> (anything -> 'n1 | 'm1) | 'f | 'g | 'h | 'i | 'w) -> 'e & 'x) & 'h) & (forall 'o1 'p1. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'o1 & 'p1) -> (anything -> 'p1 | 'o1) | 'g | 'h | 'i) -> 'f) & (forall 'm 'n 'o 'p 'q. ((forall 'd. anything -> 'd -> 'd) -> ('m -> 'n -> 'o & 'p)) -> ('p -> (forall 's. ('o -> 's & 'm) -> 'n -> 's) -> 'q) -> 'q) -> (forall 'q1. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'q1) -> 'q1) -> (forall 'j1. 'j1 -> anything -> 'j1) -> anything & 'k -> (forall 'r1 's1. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'r1 & 's1) -> (anything -> 's1 | 'r1) | 'f | 'g | 'h | 'i | 'j) -> 'g\n//│   = [Function: t_2]\n:ResetFuel\n\n// (* This comment is from the ORIGINAL PAGE: *)\n// (* Factorial of three. Exposed bugs in old implementation. This one works correctly, but the generated files take up to 3.8GB, and it takes about 1 hour on a 2GHz PIII box to get the result. You can see the final judgement here. Yes, the result is the Church numeral for 6. *)\n\n// (* We test that the result is 6: *)\n// let succ n = n + 1 ;;\n// t id succ 0 ;;\n\nt id succ 0\n//│ res: int\n//│    = 6\n\n:stats\n:e // * Strange recursive error. The bounds graph is quite large and hard to analyze for debugging...\nt_ id succ 0\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> int -> int\n//│        <: (forall 'b 'c 'd 'e 'f 'g 'h. ((forall 'i. ? -> 'i -> 'i) -> (forall 'i. ? -> 'i -> 'i) -> 'b & 'c) -> (? -> 'c | 'b) | ((forall 'i. ? -> 'i -> 'i) -> (forall 'i. ? -> 'i -> 'i) -> 'd & 'e & 'f) -> (? -> 'f | 'e | 'd) | nothing -> ('g -> 'g | ?) | 'j | ? | nothing -> ('h -> 'h | ?)) -> nothing\n//│ ║  l.285: \tdef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three\n//│ ╙──       \t                                                                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.313: \tt_ id succ 0\n//│ ║         \t^^^^^^^^^^\n//│ ╟── function of type `?a -> ?b` is not an instance of type `int`\n//│ ║  l.285: \tdef t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three\n//│ ╙──       \t                                                                                                                                                                                ^^^^^^^^^^^^^^^^\n//│ res: error\n//│    = 6\n//│ constrain calls  : 218\n//│ annoying  calls  : 0\n//│ subtyping calls  : 1556\n\n\n// let t (z : 0) = let x = (fun (y: ['t > 0] 'a -> 't) -> y z y) in x x;;\ndef t (z: nothing) = let x = fun (y: forall 't. 'a -> 't) -> y z y in x x\n//│ t: nothing -> nothing\n//│  = [Function: t5]\n\n// (* Plus petit. *)\n// type tt = ['b = 0] ['c > ['a] ['d = ['t] 'a -> 't] ['e] 'd -> 'e] 'b -> 'c ;;\n// let t (z : 0) = let x = (fun (y: ['t > 0] 'a -> 't) -> y z) in x x;;\ntype Tt = forall 'b 'c. ('b & nothing) -> ('c | (forall 'a 'd 'e. ('d & (forall 't. 'a -> 't))) -> 'e)\ndef t (z: nothing) = let x = fun (y: forall 't. 'a -> 't) -> y z in x x\n//│ Defined type alias Tt\n//│ t: nothing -> nothing\n//│  = [Function: t6]\n\n\n// (*\n//     * Rank 3, untypable in System F?\n//       (fun x -> z (x (fun f -> fun u -> f u)) (x (fun v -> fun g -> g v))) (fun y -> y y y)\n\n// * Note: `z` is free in the MLF commented example... TODO: Ask the MLF authors what they meant\n\n\n//     * Untypable at any rank\n//       (fun x -> x x) (fun x -> x x)\n\n:re\n:e\n(fun x -> x x) (fun x -> x x)\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.360: \t(fun x -> x x) (fun x -> x x)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n//     * Rank 3, untypable in F2 but F3\n//       (fun f x -> f (f x)) (fun f x -> f (f x)) (fun v w -> v)\n\n:e\n(fun f -> fun x -> f (f x)) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ ╔══[ERROR] Inferred recursive type: ? -> ? -> ?\n//│ ║  l.374: \t(fun f -> fun x -> f (f x)) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ ╙──       \t                                                  ^^^\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> anything -> 'b\n//│     'b :> anything -> 'a\n//│    = [Function (anonymous)]\n\n:RecursiveTypes\n(fun f -> fun x -> f (f x)) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> anything -> 'b\n//│     'b :> anything -> 'a\n//│    = [Function (anonymous)]\n:NoRecursiveTypes\n\n\n//     * Rank 4, alternate formulation, untypeable in F2, but F3\n//       (fun two k -> two two k)(fun f x -> f (f x)) (fun v w -> v)\n\n:e\n(fun two -> fun k -> two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ ╔══[ERROR] Inferred recursive type: ? -> ? -> ?\n//│ ║  l.398: \t(fun two -> fun k -> two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ ╙──       \t                                                      ^^^\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> anything -> 'b\n//│     'b :> anything -> 'a\n//│    = [Function (anonymous)]\n\n:RecursiveTypes\n(fun two -> fun k -> two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> anything -> 'b\n//│     'b :> anything -> 'a\n//│    = [Function (anonymous)]\n:NoRecursiveTypes\n\n\n//     * Rank 5, causes huge blowup. Do not attempt to output skeletons !\n//       (fun two k -> two two two k)(fun f -x -> f (f x)) (fun v w -> v)\n\n// :d\n:e\n(fun two -> fun k -> two two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ ╔══[ERROR] Inferred recursive type: ? -> 'a\n//│   where\n//│     'a :> ? -> ('a | ?)\n//│ ║  l.423: \t(fun two -> fun k -> two two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ ╙──       \t                                                          ^^^\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> forall 'c. anything -> 'b | 'c\n//│     'b :> forall 'c. 'c\n//│     'c :> anything -> ('b | 'a)\n//│    = [Function (anonymous)]\n\n:RecursiveTypes\n(fun two -> fun k -> two two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ res: 'a -> anything -> 'b\n//│   where\n//│     'a :> forall 'c. 'c\n//│     'c :> anything -> ('b | 'a)\n//│     'b :> forall 'c. 'c\n//│    = [Function (anonymous)]\n:NoRecursiveTypes\n\n// * Also works with CT:\n:ConstrainedTypes\n(fun two -> fun k -> two two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v)\n//│ res: 'a -> 'b\n//│   where\n//│     forall 'c. 'c\n//│       where\n//│         forall 'd 'e 'f. 'd -> ('e -> 'f\n//│           where\n//│             'd <: (forall 'g. 'g\n//│               where\n//│                 'd <: 'e -> 'g) -> 'f) <: (forall 'h. 'h\n//│           where\n//│             forall 'i. 'i\n//│               where\n//│                 forall 'd 'j 'k. 'd -> ('j -> 'k\n//│                   where\n//│                     'd <: (forall 'l. 'l\n//│                       where\n//│                         'd <: 'j -> 'l) -> 'k) <: (forall 'd 'm 'n. 'd -> ('m -> 'n\n//│                   where\n//│                     'd <: (forall 'o. 'o\n//│                       where\n//│                         'd <: 'm -> 'o) -> 'n)) -> 'i <: (forall 'p. 'p -> anything -> 'p) -> 'h) -> 'c <: (forall 'q. 'q\n//│       where\n//│         forall 'c. 'c\n//│           where\n//│             forall 'd 'e 'f. 'd -> ('e -> 'f\n//│               where\n//│                 'd <: (forall 'g. 'g\n//│                   where\n//│                     'd <: 'e -> 'g) -> 'f) <: (forall 'h. 'h\n//│               where\n//│                 forall 'i. 'i\n//│                   where\n//│                     forall 'd 'j 'k. 'd -> ('j -> 'k\n//│                       where\n//│                         'd <: (forall 'l. 'l\n//│                           where\n//│                             'd <: 'j -> 'l) -> 'k) <: (forall 'd 'm 'n. 'd -> ('m -> 'n\n//│                       where\n//│                         'd <: (forall 'o. 'o\n//│                           where\n//│                             'd <: 'm -> 'o) -> 'n)) -> 'i <: (forall 'p. 'p -> anything -> 'p) -> 'h) -> 'c <: 'a -> 'q) -> 'b\n//│    = [Function (anonymous)]\n:NoConstrainedTypes\n\n\n\n//  ?????\n//     * Factorial of two, using the Y combinator\n//       (fun h -> (fun x -> h (x x)) (fun x -> h (x x))) (fun f -> fun n -> n (fun v -> fun x -> fun y -> y) k (fun f -> fun x -> f x)(fun g -> fun x -> n (f (n (fun p -> fun s -> s (p (fun x -> fun y -> y)) (fun f -> fun x -> f (p (fun x -> fun y -> y) f x))) (fun s -> s (fun f -> fun x -> x) (fun f -> fun x -> x)) k) g) x)) (fun f -> fun x -> f (f x))\n\n// * This one still doesn't work with :RecursiveTypes\n:e\n:re\n(fun h -> (fun x -> h (x x)) (fun x -> h (x x))) (fun f -> fun n -> n (fun v -> fun x -> fun y -> y) k (fun f -> fun x -> f x)(fun g -> fun x -> n (f (n (fun p -> fun s -> s (p (fun x -> fun y -> y)) (fun f -> fun x -> f (p (fun x -> fun y -> y) f x))) (fun s -> s (fun f -> fun x -> x) (fun f -> fun x -> x)) k) g) x)) (fun f -> fun x -> f (f x))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: (nothing -> ('b | 'c) | 'd) -> 'e & (forall 'f 'g 'h 'i 'j. ((forall 'k. ? -> 'k -> 'k) -> 'f & (forall 'l. ? -> 'l -> 'l) -> 'g -> 'h -> 'i) -> ('f -> (forall 'm. ('i -> 'm & 'g) -> 'h -> 'm) -> 'j) -> 'j) -> (forall 'n. ((forall 'o. ? -> 'o -> 'o) -> (forall 'p. ? -> 'p -> 'p) -> 'n) -> 'n) -> (forall 'q. 'q -> ? -> 'q) -> 'a & (forall 'r. ? -> ? -> 'r -> 'r) -> (forall 'q. 'q -> ? -> 'q) -> (forall 's 't. ('s -> 't) -> 's -> 't) -> (((forall 'u. ? -> ? -> 'u -> 'u | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & (forall 'v. ? -> ? -> 'v -> 'v | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & (forall 'w. ? -> ? -> 'w -> 'w) -> (nothing -> ? -> ?) -> 'e & (forall 'x. ? -> ? -> 'x -> 'x | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & (forall 'y. ? -> ? -> 'y -> 'y | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & 'd & 'z) -> nothing -> 'c) -> 'z -> ((forall 'a1. ? -> ? -> 'a1 -> 'a1) -> (nothing -> ? -> ?) -> 'e & 'd)\n//│     'c :> forall 'b1 'c1. (? & 'b1) -> (? -> 'c1 -> 'c1 | 'b1 | ?)\n//│        <: (nothing -> ? -> ?) -> 'e\n//│     'e <: (forall 'd1. ? -> ? -> 'd1 -> 'd1 | ?) -> 'c\n//│ ║  l.502: \t(fun h -> (fun x -> h (x x)) (fun x -> h (x x))) (fun f -> fun n -> n (fun v -> fun x -> fun y -> y) k (fun f -> fun x -> f x)(fun g -> fun x -> n (f (n (fun p -> fun s -> s (p (fun x -> fun y -> y)) (fun f -> fun x -> f (p (fun x -> fun y -> y) f x))) (fun s -> s (fun f -> fun x -> x) (fun f -> fun x -> x)) k) g) x)) (fun f -> fun x -> f (f x))\n//│ ╙──       \t                                                                                                                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.502: \t(fun h -> (fun x -> h (x x)) (fun x -> h (x x))) (fun f -> fun n -> n (fun v -> fun x -> fun y -> y) k (fun f -> fun x -> f x)(fun g -> fun x -> n (f (n (fun p -> fun s -> s (p (fun x -> fun y -> y)) (fun f -> fun x -> f (p (fun x -> fun y -> y) f x))) (fun s -> s (fun f -> fun x -> x) (fun f -> fun x -> x)) k) g) x)) (fun f -> fun x -> f (f x))\n//│ ║         \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.502: \t(fun h -> (fun x -> h (x x)) (fun x -> h (x x))) (fun f -> fun n -> n (fun v -> fun x -> fun y -> y) k (fun f -> fun x -> f x)(fun g -> fun x -> n (f (n (fun p -> fun s -> s (p (fun x -> fun y -> y)) (fun f -> fun x -> f (p (fun x -> fun y -> y) f x))) (fun s -> s (fun f -> fun x -> x) (fun f -> fun x -> x)) k) g) x)) (fun f -> fun x -> f (f x))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// *)\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_propagate.mls",
    "content": ":NoRecursiveTypes\n:DontDistributeForalls\n\n\n// (* Use option -pa *)\n\n// type sid = ['a] 'a -> 'a\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\n// let delta = (fun x -> x x : sid -> 'b)\n// let k = ((fun x y -> y) : ['a] 'a -> sid)\ndef delta = (fun x -> x x) : Sid -> 'b\ndef delta_ = fun x -> x x\ndef k = (fun x -> fun y -> y) : forall 'a. 'a -> Sid\ndef k_ = fun x -> fun y -> y\n//│ delta: Sid -> Sid\n//│      = [Function: delta]\n//│ delta_: ('a -> 'b & 'a) -> 'b\n//│       = [Function: delta_]\n//│ k: anything -> Sid\n//│  = [Function: k]\n//│ k_: anything -> (forall 'a. 'a -> 'a)\n//│   = [Function: k_]\n\n// let id x = x\n// let id' = (id : sid -> sid)\ndef id x = x\ndef id_ = id : Sid -> Sid\n//│ id: 'a -> 'a\n//│   = [Function: id]\n//│ id_: Sid -> Sid\n//│    = [Function: id_]\n\n// (* Next: We do not give enough information. *)\n// untype fun x -> ((fun y -> y y) : 'a -> sid)\nfun x -> ((fun y -> y y) : 'a -> Sid)\nfun x_ -> (fun y -> y y)\n//│ res: anything -> ('a -> Sid & 'a) -> Sid\n//│    = [Function: res]\n//│ res: anything -> (forall 'a 'b. ('a -> 'b & 'a) -> 'b)\n//│    = [Function: res]\n\n// let (delta:sid -> sid) = fun x -> x x\ndef delta = (fun x -> x x) : Sid -> Sid\n//│ delta: Sid -> Sid\n//│      = [Function: delta1]\n\n// let (delta:sid -> 'b) = fun x -> x x\ndef delta = (fun x -> x x) : Sid -> 'b\n//│ delta: Sid -> Sid\n//│      = [Function: delta2]\n\n// untype let (delta:'a -> sid) = fun x -> x x in delta\nlet delta = (fun x -> x x) : 'a -> Sid in delta\n//│ res: ('a -> Sid & 'a) -> Sid\n//│    = [Function (anonymous)]\n\n\n\n// ———————————— Distribtivity ————————————\n\n:DistributeForalls\n\n// * Interestingly, these ones change from the ones above\n\nfun x -> ((fun y -> y y) : 'a -> Sid)\n//│ res: anything -> ('a -> ??a -> ??a0 & 'a) -> Sid\n//│    = [Function: res]\n\nlet delta = (fun x -> x x) : 'a -> Sid in delta\n//│ res: ('a -> ??a -> ??a0 & 'a) -> Sid\n//│    = [Function (anonymous)]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_rvr_validate.mls",
    "content": ":NoRecursiveTypes\n\n// (* Value restriction. *)\n// let id x = x \n// let x = id id in x 1, x true\n// let x = (id id:'a) in x 1, x true\n// ;;\ndef id x = x\nlet x = id id in (x 1, x true)\nlet x = id id : 'a in (x 1, x true)\n//│ id: 'a -> 'a\n//│   = [Function: id]\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// type sid = ['a] 'a -> 'a\n// ;;\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\n// let annot x = (x:sid)\n// ;;\ndef annot x = x : Sid\n//│ annot: Sid -> Sid\n//│      = [Function: annot]\n\n// let delta x = let y = (x:sid) in y y\n// ;;\ndef delta x = let y = x : Sid in y y\n//│ delta: Sid -> Sid\n//│      = [Function: delta]\n\n// let delta x = let y = (annot x) in y y\n// ;;\ndef delta x = let y = annot x in y y\n//│ delta: Sid -> Sid\n//│      = [Function: delta1]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_selfapp.mls",
    "content": ":NoRecursiveTypes\n\n\n\n// (*\n//  * This example was written by Susumu NISHIMURA \n//  * According to him, it requires impredicative polymorphism.\n//  *)\n\n\n\n// (* my list definition *)\n\n// type mylist ('b) = Nil | Cons of ('b * mylist ('b));;\n\n// * ML-style version\nclass Ls[A] method Head: A\ndef cons: ('a, Ls['a]) -> Ls['a]\ndef nil: Ls['a]\ndef elim: Ls['a] -> (('a, Ls['a]) -> 'r, () -> 'r) -> 'r\n//│ Defined class Ls[+A]\n//│ Declared Ls.Head: Ls['A] -> 'A\n//│ cons: ('a, Ls['a],) -> Ls['a]\n//│     = <missing implementation>\n//│ nil: Ls[nothing]\n//│    = <missing implementation>\n//│ elim: Ls['a] -> (('a, Ls['a],) -> 'r, () -> 'r,) -> 'r\n//│     = <missing implementation>\n\n// * Structural version\nclass Nil\nclass Cons[a]: { head: a; tail: List[a] }\ntype List[a] = Nil | Cons[a]\nNil = Nil {}\nCons (head, tail) = Cons { head; tail }\n//│ Defined class Nil\n//│ Defined class Cons[+a]\n//│ Defined type alias List[+a]\n//│ Nil: Nil\n//│    = Nil {}\n//│ Cons: ('head & 'a, List['a] & 'tail,) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│     = [Function: Cons1]\n\n\n\n// let rec foo =\n//   fun xs ->\n//     begin match xs with\n//       Nil -> Nil\n//     | Cons (x,xs) -> Cons (x+1, foo (foo xs))\n//     end\n\n// * Note: doesn't work with :precise-rec-typing\nrec def foo xs = elim xs (\n    fun (h, t) -> cons (h + 1, foo (foo t)),\n    fun () -> nil\n  )\n//│ foo: Ls[int] -> Ls[int]\n//│    = <no result>\n//│      elim is not implemented\n\n// * An simplified version, easier to type check, just for the record\nrec def foo xs = elim xs (\n    fun (h, t) -> cons (h + 1, foo t),\n    fun () -> nil\n  )\n//│ foo: Ls[int] -> Ls[int]\n//│    = <no result>\n//│      elim is not implemented\n\n// * === === === *\n:RecursiveTypes\nrec def foo = fun xs -> case xs of\n  Nil -> Nil,\n  Cons -> Cons (xs.head + 1, foo (foo xs.tail))\n//│ foo: 'a -> (Nil | 'b)\n//│   where\n//│     'b :> Cons[int] with {tail: Nil | 'b}\n//│     'a <: (Cons[?] with {head: int, tail: 'a}) | Nil\n//│    = [Function: foo2]\n// * An simplified version, easier to type check, just for the record\nrec def foo = fun xs -> case xs of\n  { Nil -> Nil\n  | Cons -> Cons (xs.head + 1, foo xs.tail)\n  }\n//│ foo: 'a -> (Nil | 'b)\n//│   where\n//│     'b :> Cons[int] with {tail: Nil | 'b}\n//│     'a <: (Cons[?] with {head: int, tail: 'a}) | Nil\n//│    = [Function: foo3]\n:NoRecursiveTypes\n// * === === === *\n\n\n\n// (* Type def: ba = forall b.(int->b->b)->b->b *)\n// type ba = ['b] (int -> 'b -> 'b) -> 'b -> 'b\n// (* z can be typed more polymorphic. *)\n// type baa = ['a, 'b] ('a  -> 'b -> 'b)-> 'b -> 'b \ntype Ba = forall 'b. (int -> 'b -> 'b) -> 'b -> 'b\ntype Baa = forall 'a 'b. ('a -> 'b -> 'b) -> 'b -> 'b\n//│ Defined type alias Ba\n//│ Defined type alias Baa\n\n\n// * LP: this Baa type is a bit weird. It's equivalent to:\ndef b: (nothing -> 'b -> 'b) -> 'b -> 'b\n//│ b: (nothing -> 'b -> 'b) -> 'b -> 'b\n//│  = <missing implementation>\n\n// * LP: indeed:\nb: Baa\n//│ res: Baa\n//│    = <no result>\n//│      b is not implemented\n:ng\nb = error: Baa\n//│ Baa\n//│   <:  b:\n//│ (nothing -> 'b -> 'b) -> 'b -> 'b\n\n\n\n// (* build and foldr *)\n// let build = \n//   fun (g : ['b] (('a -> 'b -> 'b) -> 'b -> 'b)) -> \n//     g (fun x xs -> Cons (x,xs)) Nil\n\n\ndef build_ = fun g -> g (fun x -> fun xs -> Cons (x, xs)) Nil\n//│ build_: ((forall 'head 'a 'tail. ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})) -> Nil -> 'b) -> 'b\n//│       = [Function: build_]\n\n:e // * Expected: List is a structural equirecursive types and recursive types are disabled\nbuild_ : forall 'a. (forall 'b. (('a -> 'b -> 'b) -> 'b -> 'b)) -> List['a]\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> Cons[?] with {tail: forall 'a. Nil | 'a}\n//│ ║  l.130: \tdef build_ = fun g -> g (fun x -> fun xs -> Cons (x, xs)) Nil\n//│ ╙──       \t                                            ^^^^^^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing type ascription; a type annotation may be required\n//│ ║  l.135: \tbuild_ : forall 'a. (forall 'b. (('a -> 'b -> 'b) -> 'b -> 'b)) -> List['a]\n//│ ║         \t^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> List['a]\n//│    = [Function: build_]\n\n:e // * Works with :RecursiveTypes due to structural typing (see below)\ndef build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> Cons (x, xs)) Nil\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> Cons[?] with {tail: forall 'a. Nil | 'a}\n//│ ║  l.149: \tdef build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> Cons (x, xs)) Nil\n//│ ╙──       \t                                                                                      ^^^^^^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.149: \tdef build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> Cons (x, xs)) Nil\n//│ ║         \t                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ build: (forall 'b. ('head -> 'b -> 'b) -> 'b -> 'b) -> (Nil | error | 'a)\n//│   where\n//│     'a :> Cons['head] with {tail: forall 'a. Nil | 'a}\n//│      = [Function: build]\n:RecursiveTypes\ndef build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> Cons (x, xs)) Nil\n//│ build: (forall 'b. ('head -> 'b -> 'b) -> 'b -> 'b) -> (Nil | 'a)\n//│   where\n//│     'a :> Cons['head] with {tail: forall 'a. Nil | 'a}\n//│      = [Function: build1]\n:NoRecursiveTypes\n\n\ndef build2_ = fun g -> g (fun x -> fun xs -> cons (x, xs)) nil\n//│ build2_: ((forall 'a. 'a -> Ls['a] -> Ls['a]) -> Ls[nothing] -> 'b) -> 'b\n//│        = <no result>\n//│          cons is not implemented\n\n// * Perfect!\nbuild2_ : forall 'a. (forall 'b. (('a -> 'b -> 'b) -> 'b -> 'b)) -> Ls['a]\n//│ res: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│    = <no result>\n//│      build2_ and cons are not implemented\n\ndef build2 = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> cons (x, xs)) nil\n//│ build2: (forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> Ls['a]\n//│       = <no result>\n//│         cons is not implemented\n\n\n\n// let rec foldr =\n//   fun k z xs -> \n//     begin match xs with\n//       Nil -> z\n//     | Cons (x, xs) -> k x (foldr k z xs)\n//     end\n\n\nrec def foldr k z xs =\n  elim xs (\n    fun (h, t) -> k h (foldr k z t),\n    fun () -> z\n  )\n//│ foldr: ('a -> 'b -> 'b) -> 'b -> Ls['a] -> 'b\n//│      = <no result>\n//│        elim is not implemented\n\n\n:e\nrec def foldr = fun k -> fun z -> fun xs ->\n  case xs of\n    Nil -> z,\n    Cons -> k xs.head (foldr k z xs.tail)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: {head: ?, tail: Cons[?] & 'a}\n//│ ║  l.210: \t  case xs of\n//│ ╙──       \t       ^^\n//│ foldr: ('head -> 'a -> 'a) -> 'a -> 'b -> 'a\n//│   where\n//│     'b <: (Cons[?] with {head: 'head, tail: 'b}) | Nil\n//│      = [Function: foldr1]\n\n\n\n// (* encoding `foo' with foldr *)\n\n// let (z : baa) = fun c n -> n\ndef z = (fun c -> fun n -> n) : Baa\ndef z_ = fun c -> fun n -> n\n//│ z: Baa\n//│  = [Function: z]\n//│ z_: anything -> 'a -> 'a\n//│   = [Function: z_]\n\n\n\n// let rec (k : int -> ba -> ba) = fun x (xs : ba) c n -> c (x+1) (xs k z c n)\n\n\ndef k: int -> Ba -> Ba\n//│ k: int -> Ba -> Ba\n//│  = <missing implementation>\n\n// * Note: annotation in `(xs: Ba)` is needed\ndef k = fun x -> fun (xs: Ba) -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ int -> Ba -> (int -> ('b -> 'a & 'b -> 'b)) -> 'b -> 'a\n//│   <:  k:\n//│ int -> Ba -> Ba\n//│  = <no result>\n//│    k is not implemented\n\n// * [FCP-IMPROV] annotation in `z` was not needed\ndef k = fun x -> fun (xs: Ba) -> fun c -> fun n -> c (x + 1) (xs k z_ c n)\n//│ int -> Ba -> (int -> 'b -> ('b & 'a)) -> 'b -> 'a\n//│   <:  k:\n//│ int -> Ba -> Ba\n//│  = <no result>\n//│    k and k are not implemented\n\n\n// * Versions with unannotated recursive defs:\n\n// * The following tests don't benefit from `:RecursiveTypes` but enabling it reduces the number of shown errors\n// * === === === *\n:RecursiveTypes\n\n// * Notice the extrusion, yielding an imprecise type\n:e\nrec def k = fun x -> fun (xs: Ba) -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ int -> Ba -> (int -> anything -> ??b) -> ??b -> anything\n//│   <:  k:\n//│ int -> Ba -> Ba\n//│ ╔══[ERROR] Type error in binding of lambda expression\n//│ ║  l.269: \trec def k = fun x -> fun (xs: Ba) -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.100: \ttype Ba = forall 'b. (int -> 'b -> 'b) -> 'b -> 'b\n//│ ║         \t                                   ^^\n//│ ╟── back into type variable `'b`\n//│ ║  l.100: \ttype Ba = forall 'b. (int -> 'b -> 'b) -> 'b -> 'b\n//│ ║         \t                             ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.101: \ttype Baa = forall 'a 'b. ('a -> 'b -> 'b) -> 'b -> 'b\n//│ ╙──       \t                                      ^^\n//│ ╔══[ERROR] Type error in def definition\n//│ ║  l.269: \trec def k = fun x -> fun (xs: Ba) -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'b` leaks out of its scope\n//│ ║  l.100: \ttype Ba = forall 'b. (int -> 'b -> 'b) -> 'b -> 'b\n//│ ║         \t                                   ^^\n//│ ╟── into type `'b0`\n//│ ║  l.100: \ttype Ba = forall 'b. (int -> 'b -> 'b) -> 'b -> 'b\n//│ ╙──       \t                             ^^\n//│  = [Function: k1]\n\n\nrec def k_ = fun x -> fun xs -> fun c -> fun n -> c (x + 1) (xs k_ z_ c n)\n//│ k_: 'k_\n//│   where\n//│     'k_ :> int -> ('k_ -> (forall 'a. anything -> 'a -> 'a) -> 'b -> 'c -> 'd) -> (int -> 'd -> 'e & 'b) -> 'c -> 'e\n//│   = [Function: k_]\n\n:e\nk = k_\n//│ 'k_\n//│   where\n//│     'k_ :> int -> ('k_ -> (forall 'a. anything -> 'a -> 'a) -> 'b -> 'c -> 'd) -> (int -> 'd -> 'e & 'b) -> 'c -> 'e\n//│   <:  k:\n//│ int -> Ba -> Ba\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.304: \tk = k_\n//│ ║         \t^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b -> ?b)` does not match type `'b`\n//│ ║  l.229: \tdef z_ = fun c -> fun n -> n\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.100: \ttype Ba = forall 'b. (int -> 'b -> 'b) -> 'b -> 'b\n//│ ╙──       \t                             ^^\n//│  = [Function: k_]\n\n\n\n// (* untyped terms *)\n// (* let z = fun c -> fun n -> n *)\n// (* let rec k = fun x xs c cn -> c (x+1) (xs k z c n) *)\n\n// (* System F terms *)\n// (* let z = /\\b -> fun (c : int -> b -> b) -> fun (n : b) -> n *)\n// (* let rec (k : int -> (forall b.(int->b->b)->b->b)\t\t\t*)\n// (*\t            -> (forall b.(int->b->b)->b->b)) =\t\t\t*)\n// (*     \\(a : int) -> \\(as : forall b.(int->b->b)->b->b) ->\t\t*)\n// (*         /\\b -> \\(c : int->b->b) -> \\(n : b) ->\t\t\t*)\n// (*             ((as[forall b.(int->b->b)->b->b] k z)[b] c z)\t\t*)\n\n\n// (* definition with build and foldr *)\n// let bfoo xs = build (foldr k z xs)\n\ndef bfoo xs = build (foldr k z xs)\n//│ bfoo: 'a -> (Nil | 'b)\n//│   where\n//│     'b :> Cons[int] with {tail: forall 'b. Nil | 'b}\n//│     'a <: (Cons[?] with {head: int, tail: 'a}) | Nil\n//│     = [Function: bfoo]\n\n:e\ndef bfoo_ xs = build_ (foldr k_ z_ xs)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.347: \tdef bfoo_ xs = build_ (foldr k_ z_ xs)\n//│ ║         \t               ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?b -> (forall ?c. ?c -> ?c)` does not match type `Cons[?a] | Nil`\n//│ ║  l.229: \tdef z_ = fun c -> fun n -> n\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.33: \ttype List[a] = Nil | Cons[a]\n//│ ║        \t               ^^^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.130: \tdef build_ = fun g -> g (fun x -> fun xs -> Cons (x, xs)) Nil\n//│ ╙──       \t                                                     ^^\n//│ bfoo_: 'a -> error\n//│   where\n//│     'a <: (Cons[?] with {head: int, tail: 'a}) | Nil\n//│      = [Function: bfoo_]\n// * Alt (requires :RecursiveTypes):\ndef bfoo_ xs = build_ (foldr k z_ xs)\n//│ bfoo_: 'a -> (Nil | 'b)\n//│   where\n//│     'b :> Cons[int] with {tail: forall 'b. Nil | 'b}\n//│     'a <: (Cons[?] with {head: int, tail: 'a}) | Nil\n//│      = [Function: bfoo_1]\n\n\nlst = Cons (0, Cons (0, Cons (0, Nil)))\n//│ lst: Cons[0] with {tail: Cons[0] with {tail: Cons[0] with {tail: Nil}}}\n//│    = Cons {\n//│        head: 0,\n//│        tail: Cons { head: 0, tail: Cons { head: 0, tail: Nil {} } }\n//│      }\n\n// (* test run *)\n// let lst0 = Cons (0, Cons (0, Cons (0, Cons (0, Nil))));;\nlst0 = Cons (0, Cons (0, Cons (0, Cons (0, Nil))))\n//│ lst0: Cons[0] with {tail: Cons[0] with {tail: Cons[0] with {tail: Cons[0] with {tail: Nil}}}}\n//│     = Cons {\n//│         head: 0,\n//│         tail: Cons { head: 0, tail: Cons { head: 0, tail: [Cons] } }\n//│       }\n\n// foo lst0;;\nfoo lst0\n//│ res: Nil | 'a\n//│   where\n//│     'a :> Cons[int] with {tail: Nil | 'a}\n//│    = Cons {\n//│        head: 1,\n//│        tail: Cons { head: 1, tail: Cons { head: 1, tail: [Cons] } }\n//│      }\n\n// bfoo lst0;;\nbfoo lst0\n//│ res: Nil | 'a\n//│   where\n//│     'a :> Cons[int] with {tail: forall 'a. Nil | 'a}\n//│    = Cons {\n//│        head: 1,\n//│        tail: Cons { head: 2, tail: Cons { head: 4, tail: [Cons] } }\n//│      }\n\nbfoo_ lst0\n//│ res: Nil | 'a\n//│   where\n//│     'a :> Cons[int] with {tail: forall 'a. Nil | 'a}\n//│    = Cons {\n//│        head: 1,\n//│        tail: Cons { head: 2, tail: Cons { head: 4, tail: [Cons] } }\n//│      }\n\n:NoRecursiveTypes\n// * === === === *\n\n\n\n// (* This does not type :\n// type baa = ['a, 'b] ('a  -> 'b -> 'b)-> 'b -> 'b\n//   let rec (k : int -> baa -> baa) = fun x (xs : baa) c n -> c (x+1) (xs k z c n)\n// *)\n\n\ndef k: int -> Baa -> Baa\n//│ k: int -> Baa -> Baa\n//│  = <missing implementation>\n\n:e\ndef k = fun x -> fun (xs: Baa) -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ int -> Baa -> (int -> 'a -> 'b) -> 'a -> 'b\n//│   <:  k:\n//│ int -> Baa -> Baa\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.434: \tdef k = fun x -> fun (xs: Baa) -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` does not match type `'a`\n//│ ║  l.434: \tdef k = fun x -> fun (xs: Baa) -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ ║         \t                                                       ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.101: \ttype Baa = forall 'a 'b. ('a -> 'b -> 'b) -> 'b -> 'b\n//│ ╙──       \t                          ^^\n//│  = <no result>\n//│    k is not implemented\n\n\n// * Using `k` here on purpose to simulate an annotated rec def\ndef k_ = fun x -> fun xs -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ k_: int -> ((int -> Baa -> Baa) -> Baa -> 'a -> 'b -> 'c) -> (int -> 'c -> 'd & 'a) -> 'b -> 'd\n//│   = <no result>\n//│     k and k are not implemented\n\n:e\nk = k_ // nope\n//│ int -> ((int -> Baa -> Baa) -> Baa -> 'a -> 'b -> 'c) -> (int -> 'c -> 'd & 'a) -> 'b -> 'd\n//│   <:  k:\n//│ int -> Baa -> Baa\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.458: \tk = k_ // nope\n//│ ║         \t^^^^^^\n//│ ╟── operator application of type `int` does not match type `'a`\n//│ ║  l.452: \tdef k_ = fun x -> fun xs -> fun c -> fun n -> c (x + 1) (xs k z c n)\n//│ ║         \t                                                 ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.101: \ttype Baa = forall 'a 'b. ('a -> 'b -> 'b) -> 'b -> 'b\n//│ ╙──       \t                          ^^\n//│  = <no result>\n//│    k_, k and k are not implemented\n\n\n:e // occurs-check\nrec def k_ = fun x -> fun xs -> fun c -> fun n -> c (x + 1) (xs k_ z c n)\n//│ ╔══[ERROR] Inferred recursive type: 'k_\n//│   where\n//│     'k_ :> int -> ('k_ -> Baa -> 'a -> 'b -> 'c) -> (int -> 'c -> 'd & 'a) -> 'b -> 'd\n//│ ╙──\n//│ k_: 'k_\n//│   where\n//│     'k_ :> int -> ('k_ -> Baa -> 'a -> 'b -> 'c) -> (int -> 'c -> 'd & 'a) -> 'b -> 'd\n//│   = [Function: k_1]\n\n:e\nk = k_ // nope\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'c -> 'd\n//│     'c :> 'e -> 'f -> 'd\n//│        <: 'g\n//│     'e :> int -> 'g -> 'e -> 'f -> 'd\n//│        <: int -> 'a & ? -> 'b -> 'b\n//│     'b :> 'e -> 'f -> 'd\n//│        <: 'g\n//│     'g <: (int -> 'g -> 'e -> 'f -> 'd) -> Baa -> 'h\n//│     'd :> 'e -> 'f -> 'd\n//│        <: 'c & 'h\n//│     'h <: 'e -> (Baa | 'f) -> 'c\n//│ ║  l.476: \trec def k_ = fun x -> fun xs -> fun c -> fun n -> c (x + 1) (xs k_ z c n)\n//│ ╙──       \t                                                  ^^^^^^^^^\n//│ 'k_\n//│   where\n//│     'k_ :> int -> ('k_ -> Baa -> 'a -> 'b -> 'c) -> (int -> 'c -> 'd & 'a) -> 'b -> 'd\n//│   <:  k:\n//│ int -> Baa -> Baa\n//│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required\n//│ ║  l.487: \tk = k_ // nope\n//│ ║         \t^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│  = [Function: k_1]\n\n\n:e // occurs-check\nrec def k_ = fun x -> fun xs -> fun c -> fun n -> c (x + 1) (xs k_ z_ c n)\n//│ ╔══[ERROR] Inferred recursive type: 'k_\n//│   where\n//│     'k_ :> int -> ('k_ -> (forall 'a. ? -> 'a -> 'a) -> 'b -> 'c -> 'd) -> (int -> 'd -> 'e & 'b) -> 'c -> 'e\n//│ ╙──\n//│ k_: 'k_\n//│   where\n//│     'k_ :> int -> ('k_ -> (forall 'a. anything -> 'a -> 'a) -> 'b -> 'c -> 'd) -> (int -> 'd -> 'e & 'b) -> 'c -> 'e\n//│   = [Function: k_2]\n\n// k = k_ // nope\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_shallow.mls",
    "content": ":NoRecursiveTypes\n\n// type sid = ['a] 'a -> 'a;;\n// type nat = ['a] ('a -> 'a) -> 'a -> 'a\ntype Sid = forall 'a. 'a -> 'a\ntype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ Defined type alias Sid\n//│ Defined type alias ChurchInt\n\n// let auto (x:sid) = x x\n// let id x = x\n// let k x y = x\ndef auto (x: Sid) = x x\ndef auto_ x = x x\ndef id x = x\ndef k x y = x\n//│ auto: Sid -> Sid\n//│     = [Function: auto]\n//│ auto_: ('a -> 'b & 'a) -> 'b\n//│      = [Function: auto_]\n//│ id: 'a -> 'a\n//│   = [Function: id]\n//│ k: 'a -> anything -> 'a\n//│  = [Function: k]\n\n// (* church_zero is like the sequence *)\n// let church_zero = fun f -> id\ndef church_zero = fun f -> id\n//│ church_zero: anything -> 'a -> 'a\n//│            = [Function: church_zero]\n\n// (* church_un is like apply *)\n// let church_one = fun f x -> f x\ndef church_one = fun f -> fun x -> f x\n//│ church_one: ('a -> 'b) -> 'a -> 'b\n//│           = [Function: church_one]\n\n// (* church_un is like apply_twice *)\n// let church_two = fun f x -> f (f x)\ndef church_two = fun f -> fun x -> f (f x)\n//│ church_two: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│           = [Function: church_two]\n\n// let church_succ n = fun f x -> f (n f x)\ndef church_succ n = fun f -> fun x -> f (n f x)\n//│ church_succ: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│            = [Function: church_succ]\n\n// (* We build the a0 of the icfp version paper *)\n// type a1 = ['b] ['a > sid] ('a -> 'b) -> 'b\n// let a1 = fun f -> f id;;\n// let a3 = (fun z z' -> z church_two);;\n// let a2 (x:a1) =  (x auto); (fun y -> x y; y church_succ) a3;;\n// let a0 = a2 a1;;\n\n// * The MLF type above could be encoded as:\n// type A1 = forall 'a 'b. (('a | Sid) -> 'b) -> 'b\n// * However that's unnecessary as this is equivalent to the type below,\n// * which MLF cannot express directly due to its rigid syntactic limitations:\ntype A1 = forall 'b. (Sid -> 'b) -> 'b\n//│ Defined type alias A1\n\ndef a1 = fun f -> f id\ndef a3 = fun z -> fun _ -> z church_two\ndef a2 (x: A1) =\n  let _ = x auto in\n  (fun y ->\n    let _ = x y in\n    y church_succ\n  ) a3\ndef a2_ (x: A1) =\n  let _ = x auto_ in\n  (fun y ->\n    let _ = x y in\n    y church_succ\n  ) a3\n//│ a1: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│   = [Function: a1]\n//│ a3: ((forall 'a 'b 'c. ('a -> 'b & 'b -> 'c) -> 'a -> 'c) -> 'd) -> anything -> 'd\n//│   = [Function: a3]\n//│ a2: A1 -> anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│   = [Function: a2]\n//│ a2_: A1 -> anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│    = [Function: a2_]\n\ndef a0 = a2 a1\n//│ a0: anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│   = [Function: a0]\n\ndef a0_ = a2_ a1\n//│ a0_: anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│    = [Function: a0_]\n\n\n// let test0 = \n//   (fun f -> f (fun h -> h id))\n//     (fun (g:a1) ->\n//       k (g (fun (x:sid) -> x x))\n//         ((fun t -> (fun u v -> v) (g t) (t (fun f x -> x)))\n//            (fun x -> ((fun f x -> f x) x) (fun f x -> x))))\n// ;;\n\ndef test0 =\n  (fun f -> f (fun h -> h id))\n    (fun (g: A1) ->\n      k (g (fun (x: Sid) -> x x))\n        ((fun t -> (fun u -> fun v -> v) (g t) (t (fun f -> fun x -> x)))\n          (fun x -> ((fun f -> fun x -> f x) x) (fun f -> fun x -> x))))\n//│ test0: Sid\n//│      = [Function: test0]\n\ndef test0_ =\n  (fun f -> f (fun h -> h id))\n    (fun g ->\n      k (g (fun x -> x x))\n        ((fun t -> (fun u -> fun v -> v) (g t) (t (fun f -> fun x -> x)))\n          (fun x -> ((fun f -> fun x -> f x) x) (fun f -> fun x -> x))))\n//│ test0_: 'a -> 'a\n//│       = [Function: test0_]\n\n\n// (** Encoding in F+eta **)\n// (* we repace sa by sb and build a coercion function form sb to sc *)\n\n// type a1_sid = ['b] ['a = sid] ('a -> 'b) -> 'b;;\n// type a1_nat = ['b] ['a = nat -> nat] ('a -> 'b) -> 'b;;\n\n// type A1_sid = forall 'a 'b. (('a & Sid | Sid) -> 'b) -> 'b\n// type A1_nat = forall 'a 'b. (('a & ChurchInt -> ChurchInt | ChurchInt -> ChurchInt) -> 'b) -> 'b\n// * Simplified:\ntype A1_sid = forall 'b. (Sid -> 'b) -> 'b\ntype A1_nat = forall 'a 'b. ((ChurchInt -> ChurchInt) -> 'b) -> 'b\n//│ Defined type alias A1_sid\n//│ Defined type alias A1_nat\n\n// let a1_sid_to_nat (g : a1_sid) =\n//   let r = fun f -> g (fun (x : sid) -> f x) in\n//   (r : a1_nat);;\n\ndef a1_sid_to_nat (g: A1_sid) =\n  let r = fun f -> g (fun (x: Sid) -> f x) in\n  (r: A1_nat)\n//│ a1_sid_to_nat: A1_sid -> A1_nat\n//│              = [Function: a1_sid_to_nat]\n\ndef a1_sid_to_nat_ g =\n  let r = fun f -> g (fun x -> f x) in\n  r\n//│ a1_sid_to_nat_: (('a -> 'b) -> 'c) -> ('a -> 'b) -> 'c\n//│               = [Function: a1_sid_to_nat_]\n\n// (* the term is as above but abstract over sb and uses the coercion *)\n\n// let test_in_F_eta = \n//   (fun f -> f (fun h -> h id))\n//     (fun (g : a1_sid) ->\n//       k (g (fun (x : sid) -> x x))\n//         ((fun t -> (fun u v -> v) ((a1_sid_to_nat g) t) (t (fun f x -> x)))\n//            (fun x -> ((fun f x -> f x) x) (fun f x -> x))))\n// ;;\n\ndef test_in_F_eta = \n  (fun f -> f (fun h -> h id))\n    (fun (g: A1_sid) ->\n      k (g (fun (x : Sid) -> x x))\n        ((fun t -> (fun u -> fun v -> v) ((a1_sid_to_nat g) t) (t (fun f -> fun x -> x)))\n          (fun x -> ((fun f -> fun x -> f x) x) (fun f -> fun x -> x))))\n//│ test_in_F_eta: Sid\n//│              = [Function: test_in_F_eta]\n\ndef test_in_F_eta_ = \n  (fun f -> f (fun h -> h id))\n    (fun g ->\n      k (g (fun x -> x x))\n        ((fun t -> (fun u -> fun v -> v) ((a1_sid_to_nat_ g) t) (t (fun f -> fun x -> x)))\n          (fun x -> ((fun f -> fun x -> f x) x) (fun f -> fun x -> x))))\n//│ test_in_F_eta_: 'a -> 'a\n//│               = [Function: test_in_F_eta_]\n\n// (*\n// (* Le terme dans la syntaxe de Joe Wells *)\n//   (fn f => f (fn h => h id))\n//     (fn g => \n//         k (g (fn x => x x))\n//           ((fn t => (fn u v => v) (g t) (t (fn f x => x)))\n//              (fn x => ((fn f x => f x) x) (fn f x => x))))\n\n// *)\n\n// (* We can also build a version of a0 that should not be in F+eta. \n// To do that we require x to return its argument. \n// *)\n\n// type a1' = ['a > sid] ('a -> 'a) -> 'a -> 'a;;\n\n// type A1' = forall 'a. (('a | Sid) -> ('a | Sid)) -> ('a | Sid) -> ('a | Sid)\n// * Or (no need to change the negative occurrences):\ntype A1' = forall 'a. (('a | Sid) -> 'a) -> 'a -> ('a | Sid)\n// * Since 'a occurs both positively and negatively, we cannot simplify it to the following:\n// type A1' = (Sid -> Sid) -> Sid -> Sid\n//│ Defined type alias A1'\n\n// let either x y = if true then x else y;;\n// let a1' = fun f x -> f (f (either id x));;\n// let a2' (x:a1') = x auto id; (fun y -> x y church_two; y church_succ) a3;;\n// let a0' = a2' a1';;\n\ndef either x y = if true then x else y\n//│ either: 'a -> 'a -> 'a\n//│       = [Function: either]\n\ndef a1' = fun f -> fun x -> f (f (either id x))\n//│ a1': ((forall 'a. 'a -> 'a | 'b) -> 'c & 'c -> 'd) -> 'b -> 'd\n//│    = [Function: a1$]\n\ndef a2' (x: A1') =\n  let _ = x auto id in\n  (fun y ->\n    let _ = x y church_two in\n    y church_succ\n  ) a3\n//│ a2': A1' -> anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│    = [Function: a2$]\n\ndef a2'_ x =\n  let _ = x auto_ id in\n  (fun y ->\n    let _ = x y church_two in\n    y church_succ\n  ) a3\n//│ a2'_: ((forall 'a 'b. ('a -> 'b & 'a) -> 'b) -> (forall 'c. 'c -> 'c) -> anything & (forall 'd. ((forall 'e 'f 'g. ('e -> 'f & 'f -> 'g) -> 'e -> 'g) -> 'd) -> anything -> 'd) -> (forall 'e 'f 'g. ('e -> 'f & 'f -> 'g) -> 'e -> 'g) -> anything) -> anything -> ('h -> 'i & 'j -> 'k & 'k -> 'h) -> 'j -> 'i\n//│     = [Function: a2$_]\n\n:e // * [FCP-LIM] current limitation due to the union type in A1' (we don't currently handle them precisely)\ndef a0' = a2' a1'\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.235: \tdef a0' = a2' a1'\n//│ ║         \t          ^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.5: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║       \t                      ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.5: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║       \t                            ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.212: \tdef a1' = fun f -> fun x -> f (f (either id x))\n//│ ║         \t                               ^\n//│ ╟── • this reference:\n//│ ║  l.212: \tdef a1' = fun f -> fun x -> f (f (either id x))\n//│ ║         \t                                         ^^\n//│ ╟── • this reference:\n//│ ║  l.208: \tdef either x y = if true then x else y\n//│ ║         \t                              ^\n//│ ╟── • this reference:\n//│ ║  l.235: \tdef a0' = a2' a1'\n//│ ║         \t              ^^^\n//│ ╟── • this reference:\n//│ ║  l.15: \tdef id x = x\n//│ ╙──      \t           ^\n//│ a0': error | anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│    = [Function: a0$]\n\n:e\ndef a0'_ = a2'_ a1'\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.265: \tdef a0'_ = a2'_ a1'\n//│ ║         \t           ^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ a0'_: error | anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│     = [Function: a0$_]\n\n:RecursiveTypes\n// * Note: requires :DistributeForalls\ndef a0'_ = a2'_ a1'\n//│ a0'_: anything -> ('a -> 'b & 'c -> 'd & 'd -> 'a) -> 'c -> 'b\n//│     = [Function: a0$_1]\n:NoRecursiveTypes\n\n// type a1'_sid = ['a = sid] ('a -> 'a) -> 'a -> 'a;;\n// type a1'_nat = ['a = nat] ('a -> 'a) -> 'a -> 'a;;\ntype A1'_sid = forall 'a. (('a & Sid | Sid) -> ('a & Sid | Sid)) -> ('a & Sid | Sid) -> ('a & Sid | Sid)\ntype A1'_nat = forall 'a. (('a & ChurchInt | ChurchInt) -> ('a & ChurchInt | ChurchInt)) -> ('a & ChurchInt | ChurchInt) -> ('a & ChurchInt | ChurchInt)\n//│ Defined type alias A1'_sid\n//│ Defined type alias A1'_nat\n\n// (* There is no coercion from a1'_sid to a1'_nat, hence we can conjecture that a0'\n//    is not in F+eta. *)\n\n\n\n\n\n// * === With Constrained Types ===\n\n:DontDistributeForalls\n:ConstrainedTypes\n\n\n\n\ndef a1 = fun f -> f id\ndef a3 = fun z -> fun _ -> z church_two\ndef a2 (x: A1) =\n  let _ = x auto in\n  (fun y ->\n    let _ = x y in\n    y church_succ\n  ) a3\ndef a2_ (x: A1) =\n  let _ = x auto_ in\n  (fun y ->\n    let _ = x y in\n    y church_succ\n  ) a3\n//│ a1: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│   = [Function: a11]\n//│ a3: 'a -> (forall 'b. anything -> 'b\n//│   where\n//│     'a <: (forall 'c 'd 'e. ('c -> 'd & 'd -> 'e) -> 'c -> 'e) -> 'b)\n//│   = [Function: a31]\n//│ a2: A1 -> (forall 'a. anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a)\n//│   = [Function: a21]\n//│ a2_: A1 -> (forall 'a. anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a)\n//│    = [Function: a2_1]\n\ndef a0 = a2 a1\n//│ a0: anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a\n//│   = [Function: a01]\n\ndef a0_ = a2_ a1\n//│ a0_: anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a\n//│    = [Function: a0_1]\n\ndef a1' = fun f -> fun x -> f (f (either id x))\n//│ a1': 'a -> (forall 'b 'c 'd. 'b -> 'd\n//│   where\n//│     'a <: (forall 'e. 'e -> 'e | 'b) -> 'c & 'c -> 'd)\n//│    = [Function: a1$1]\n\n:e // occurs-check\ndef a2' (x: A1') =\n  let _ = x auto id in\n  (fun y ->\n    let _ = x y church_two in\n    y church_succ\n  ) a3\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> forall 'a 'b 'c 'd. nothing -> ('b -> 'c | 'd)\n//│       where\n//│         Sid | 'a <: (forall 'b 'e 'c. ('b -> 'e & 'e -> 'c) -> 'b -> 'c) -> 'd\n//│ ║  l.198: \ttype A1' = forall 'a. (('a | Sid) -> 'a) -> 'a -> ('a | Sid)\n//│ ╙──       \t                  ^^\n//│ a2': A1' -> (forall 'a. anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a)\n//│    = [Function: a2$1]\n\ndef a2'_ x =\n  let _ = x auto_ id in\n  (fun y ->\n    let _ = x y church_two in\n    y church_succ\n  ) a3\n//│ a2'_: ((forall 'a 'b. ('a -> 'b & 'a) -> 'b) -> (forall 'c. 'c -> 'c) -> anything & (forall 'd. 'd -> (forall 'e. anything -> 'e\n//│   where\n//│     'd <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'e)) -> (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> anything) -> (forall 'i. anything -> 'i\n//│   where\n//│     forall 'j 'k 'l 'm. ('j -> 'k -> 'l) -> ('l -> 'm & 'j) -> 'k -> 'm <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'i)\n//│     = [Function: a2$_1]\n\n:e // * [FCP-LIM] see previous version above\ndef a0' = a2' a1'\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.382: \tdef a0' = a2' a1'\n//│ ║         \t          ^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.5: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║       \t                  ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.15: \tdef id x = x\n//│ ║        \t       ^^^^^\n//│ ╟── • this reference:\n//│ ║  l.343: \tdef a1' = fun f -> fun x -> f (f (either id x))\n//│ ║         \t                                         ^^\n//│ ╟── • this reference:\n//│ ║  l.208: \tdef either x y = if true then x else y\n//│ ║         \t                              ^\n//│ ╟── • this reference:\n//│ ║  l.382: \tdef a0' = a2' a1'\n//│ ║         \t              ^^^\n//│ ╟── • this function:\n//│ ║  l.350: \tdef a2' (x: A1') =\n//│ ║         \t        ^^^^^^^^^^\n//│ ║  l.351: \t  let _ = x auto id in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.352: \t  (fun y ->\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.353: \t    let _ = x y church_two in\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.354: \t    y church_succ\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ║  l.355: \t  ) a3\n//│ ║         \t^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.382: \tdef a0' = a2' a1'\n//│ ╙──       \t          ^^^\n//│ a0': error | anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a\n//│    = [Function: a0$1]\n\n:e\ndef a0'_ = a2'_ a1'\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.424: \tdef a0'_ = a2'_ a1'\n//│ ║         \t           ^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ a0'_: error | anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a\n//│     = [Function: a0$_2]\n\n:RecursiveTypes\ndef a0'_ = a2'_ a1'\n//│ a0'_: anything -> 'a\n//│   where\n//│     forall 'b 'c 'd 'e. ('b -> 'c -> 'd) -> ('d -> 'e & 'b) -> 'c -> 'e <: (forall 'f 'g 'h. ('f -> 'g & 'g -> 'h) -> 'f -> 'h) -> 'a\n//│     = [Function: a0$_3]\n:NoRecursiveTypes\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_validate.mls",
    "content": ":NoRecursiveTypes\n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\ndef cons[a]: a -> List[a] -> List[a]\ndef cons head tail = Cons { head; tail }\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\ndef nil: List['a]\nnil = Nil {}\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\n// ============ Type signatures for functions used in the examples ============\n\ndef head: forall 'a. List['a] -> 'a\ndef head l = l.Head\n//│ head: List['a] -> 'a\n//│     = <missing implementation>\n//│ List['a] -> 'a\n//│   <:  head:\n//│ List['a] -> 'a\n//│     = [Function: head]\n\ndef tail: forall 'a. List['a] -> List['a]\ndef tail l = l.Tail\n//│ tail: List['a] -> List['a]\n//│     = <missing implementation>\n//│ List['a] -> List['a]\n//│   <:  tail:\n//│ List['a] -> List['a]\n//│     = [Function: tail]\n\ndef is_empty: forall 'a. List['a] -> bool\ndef is_empty l = eq l nil\n//│ is_empty: List[?] -> bool\n//│         = <missing implementation>\n//│ anything -> bool\n//│   <:  is_empty:\n//│ List[?] -> bool\n//│         = [Function: is_empty]\n\ndef concat: forall 'a. List['a] -> List['a] -> List['a]\nrec def concat l1 l2 =\n  if is_empty l1 then l2\n  else cons (head l1) (concat (tail l1) l2)\n//│ concat: List['a] -> List['a] -> List['a]\n//│       = <missing implementation>\n//│ List['a] -> List['a] -> List['a]\n//│   <:  concat:\n//│ List['a] -> List['a] -> List['a]\n//│       = [Function: concat1]\n\ndef print_bool: bool -> unit\ndef print_bool b = log b\n//│ print_bool: bool -> unit\n//│           = <missing implementation>\n//│ anything -> unit\n//│   <:  print_bool:\n//│ bool -> unit\n//│           = [Function: print_bool]\n\ndef print_int: int -> unit\ndef print_int i = log i\n//│ print_int: int -> unit\n//│          = <missing implementation>\n//│ anything -> unit\n//│   <:  print_int:\n//│ int -> unit\n//│          = [Function: print_int]\n\ndef print_string: string -> unit\ndef print_string s = log s\n//│ print_string: string -> unit\n//│             = <missing implementation>\n//│ anything -> unit\n//│   <:  print_string:\n//│ string -> unit\n//│             = [Function: print_string]\n\ndef print x = log x\n//│ print: anything -> unit\n//│      = [Function: print]\n\n\n\n// (* Ces exemples permettent de tester durement le syst�me de types. *)\n\n// type id = ['a] 'a -> 'a\ntype Id = forall 'a. 'a -> 'a\n//│ Defined type alias Id\n\n// let choose x y = if true then x else y\n// let succ n = n + 1\n// let z = (succ : int -> int)\ndef choose x y = if true then x else y\ndef succ n = n + 1\ndef z = succ : int -> int\n//│ choose: 'a -> 'a -> 'a\n//│       = [Function: choose]\n//│ succ: int -> int\n//│     = [Function: succ]\n//│ z: int -> int\n//│  = [Function: z]\n\n// let id x = x\n// let z = choose (id:id) id\n// let z = (choose id succ) 10\n// let z = (choose succ id) 10\ndef id x = x\nz = choose (id : Id) id\nz = (choose id succ) 10\nz = (choose succ id) 10\n//│ id: 'a -> 'a\n//│   = [Function: id]\n//│ z: 'a -> 'a | Id\n//│  = [Function: id]\n//│ z: int\n//│  = 10\n//│ z: int\n//│  = 11\n\n// untype fun x -> x x\nfun x -> x x\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\n// let delta (x:id) = x x\ndef delta (x: Id) = x x\ndef delta_ x = x x\n//│ delta: Id -> Id\n//│      = [Function: delta]\n//│ delta_: ('a -> 'b & 'a) -> 'b\n//│       = [Function: delta_]\n\n// let z = delta (delta id)\n\ndef z = delta (delta id)\n//│ z: Id\n//│  = [Function: z4]\n\ndef z_ = delta_ (delta_ id)\n//│ z_: 'a -> 'a\n//│   = [Function: z_]\n\n// untype delta succ\n:e\ndelta succ\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.176: \tdelta succ\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.118: \ttype Id = forall 'a. 'a -> 'a\n//│ ║         \t                     ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.125: \tdef succ n = n + 1\n//│ ║         \t             ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.118: \ttype Id = forall 'a. 'a -> 'a\n//│ ╙──       \t                 ^^\n//│ res: error | Id\n//│    = 'function succ(n) {  return n + 1;}1'\n:e\ndelta_ succ\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.192: \tdelta_ succ\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b)` is not an instance of type `int`\n//│ ║  l.125: \tdef succ n = n + 1\n//│ ║         \t         ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.192: \tdelta_ succ\n//│ ║         \t       ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.125: \tdef succ n = n + 1\n//│ ╙──       \t             ^\n//│ res: error | int\n//│    = 'function succ(n) {  return n + 1;}1'\n\n// let z = delta (choose id id)\n\ndef z = delta (choose id id)\n//│ z: Id\n//│  = [Function: z5]\n\ndef z_ = delta_ (choose id id)\n//│ z_: 'a -> 'a\n//│   = [Function: z_1]\n\n// let step g = (g 1) - (g 0)\n// let apply_to_id f = f id\n// let test1 = apply_to_id step\n// let test2 = apply_to_id delta\ndef step g = (g 1) - (g 0)\ndef apply_to_id f = f id\ntest1 = apply_to_id step\ntest2 = apply_to_id delta\ntest2_ = apply_to_id delta_\n//│ step: ((0 | 1) -> int) -> int\n//│     = [Function: step]\n//│ apply_to_id: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│            = [Function: apply_to_id]\n//│ test1: int\n//│      = 1\n//│ test2: Id\n//│      = [Function: id]\n//│ test2_: 'a -> 'a\n//│       = [Function: id]\n\n// type s  = ['a] list ('a) -> bool\n// let annote_s (x:id) = (x : s -> s)\ntype S = forall 'a. List['a] -> bool\ndef annote_s (x: Id) = x : S -> S\ndef annote_s_ x = x : S -> S\n//│ Defined type alias S\n//│ annote_s: Id -> S -> S\n//│         = [Function: annote_s]\n//│ annote_s_: (S -> S) -> S -> S\n//│          = [Function: annote_s_]\n\n// let isnil l = l = []\ndef isnil l = eq l nil\n//│ isnil: anything -> bool\n//│      = [Function: isnil]\n\n// passif value_restriction\n// let t = fun x y ->\n//   let isnil = (annote_s x) y in\n//   (isnil [ 1 ; 2 ; 3] , isnil [] , isnil [\"ok\"] , isnil [true])\n// in t id isnil\nlet t = fun x -> fun y ->\n  let isnil = (annote_s x) y in\n    (isnil (cons 1 (cons 2 (cons 3 nil))), isnil nil, isnil (cons \"ok\" nil), isnil (cons true nil)) \n  in t id isnil\nlet t = fun x -> fun y ->\n  let isnil = (annote_s_ x) y in\n    (isnil (cons 1 (cons 2 (cons 3 nil))), isnil nil, isnil (cons \"ok\" nil), isnil (cons true nil)) \n  in t id isnil\n//│ res: (bool, bool, bool, bool,)\n//│    = [ false, true, false, false ]\n//│ res: (bool, bool, bool, bool,)\n//│    = [ false, true, false, false ]\n\n// untype fun x y ->\n//   let isnil = (x:id) y in\n//   (isnil [ 1 ; 2 ; 3] , isnil [] , isnil [\"ok\"] , isnil [true])\nfun x -> fun y ->\n  let isnil = (x : Id) y in\n    (isnil (cons 1 (cons 2 (cons 3 nil))), isnil nil, isnil (cons \"ok\" nil), isnil (cons true nil))\nfun x -> fun y ->\n  let isnil = x y in\n    (isnil (cons 1 (cons 2 (cons 3 nil))), isnil nil, isnil (cons \"ok\" nil), isnil (cons true nil)) \n//│ res: Id -> (List[1 | 2 | 3] -> 'a & List[nothing] -> 'b & List[\"ok\"] -> 'c & List[true] -> 'd) -> ('a, 'b, 'c, 'd,)\n//│    = [Function: res]\n//│ res: ('a -> (List[1 | 2 | 3] -> 'b & List[nothing] -> 'c & List[\"ok\"] -> 'd & List[true] -> 'e)) -> 'a -> ('b, 'c, 'd, 'e,)\n//│    = [Function: res]\n\n// (*let t1 = f delta\t\n// let t2 = f step*)\n\n// let partage x = choose id x\n// let departage x = choose id (x:id)\ndef partage x = choose id x\ndef departage x = choose id (x : Id)\n//│ partage: 'a -> ('b -> 'b | 'a)\n//│        = [Function: partage]\n//│ departage: Id -> ('a -> 'a | Id)\n//│          = [Function: departage]\n\n// let delta' = fun x -> (departage x) x\n// untype fun x -> partage x x\ndef delta' = fun x -> (departage x) x\ndef delta'_ = fun x -> (partage x) x\n//│ delta': (Id & 'a) -> 'a\n//│       = [Function: delta$]\n//│ delta'_: ('a -> 'b & 'a & 'b) -> 'b\n//│        = [Function: delta$_]\n\n// let t = fun x -> (x:id) x, x\n// let t = fun (x:id) -> x x, (x:id)\n// let t = fun (x:id) -> x x, x\n// untype fun x -> x (x:id), x\n// untype fun x -> x x, (x:id)\ndef t = fun x -> ((x : Id) x, x)\ndef t = fun (x: Id) -> (x x, (x : Id))\ndef t = fun (x: Id) -> (x x, x)\ndef t = fun x -> (x (x : Id), x)\ndef t = fun x -> (x x, x : Id)\ndef t_ = fun x -> (x x, x)\n//│ t: (Id & 'a) -> ('a, 'a,)\n//│  = [Function: t]\n//│ t: Id -> (Id, Id,)\n//│  = [Function: t1]\n//│ t: Id -> (Id, Id,)\n//│  = [Function: t2]\n//│ t: (Id & Id -> 'a & 'b) -> ('a, 'b,)\n//│  = [Function: t3]\n//│ t: (Id & 'a -> 'b & 'a) -> ('b, Id,)\n//│  = [Function: t4]\n//│ t_: ('a -> 'b & 'a) -> ('b, 'a,)\n//│   = [Function: t_]\n\n// untype fun x -> (x:id), x x\n// * [FCP-IMPROV] It works for us\nfun x -> (x : Id, x x)\n//│ res: (Id & 'a -> 'b & 'a) -> (Id, 'b,)\n//│    = [Function: res]\n\n// let ig x = () (* ignore *)\ndef ig x = null\n//│ ig: anything -> null\n//│   = [Function: ig]\n\n\n// (* The following is not typable in System F (afaik) *)\n// let aa f = f id\n// untype fun g -> ig (g delta) ; (fun t -> ig (g t) ; t succ) (fun x -> succ (x 8))\n// let ff = fun (g:['a > id] ['b] ('a -> 'b) -> 'b) ->\n//         ig (g delta) ; (fun t -> ig (g t) ; t succ) (fun x -> succ (x 8))\n\ndef aa f = f id\n//│ aa: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│   = [Function: aa]\n\ndef ff = fun (g: forall 'a 'b. (('a | Id) -> 'b) -> 'b) ->\n  let _ = ig (g delta) in\n    (fun t ->\n      let _ = ig (g t) in\n      t succ\n    ) (fun x -> succ (x 8))\n//│ ff: (forall 'b. (Id -> 'b) -> 'b) -> int\n//│   = [Function: ff]\n\n// * [FCP-IMPROV] It works for us!\ndef ff_ = fun g ->\n  let _ = ig (g delta) in\n    (fun t ->\n      let _ = ig (g t) in\n      t succ\n    ) (fun x -> succ (x 8))\n//│ ff_: (((Id & 8 -> int) -> (int | Id)) -> anything) -> int\n//│    = [Function: ff_]\n\n// let bigtest = ff aa\n\n// * Probably due to the union type used above (not yet well supported)\n:e\nbigtest = ff aa\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.376: \tbigtest = ff aa\n//│ ║         \t          ^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.118: \ttype Id = forall 'a. 'a -> 'a\n//│ ║         \t                     ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.118: \ttype Id = forall 'a. 'a -> 'a\n//│ ║         \t                           ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this applied expression:\n//│ ║  l.349: \tdef aa f = f id\n//│ ║         \t           ^\n//│ ╟── • this reference:\n//│ ║  l.349: \tdef aa f = f id\n//│ ║         \t             ^^\n//│ ╟── • this reference:\n//│ ║  l.376: \tbigtest = ff aa\n//│ ║         \t             ^^\n//│ ╟── • this reference:\n//│ ║  l.138: \tdef id x = x\n//│ ╙──       \t           ^\n//│ bigtest: error | int\n//│        = 10\n\nbigtest_ = ff_ aa\n//│ bigtest_: int\n//│         = 10\n\n// (* Variable libre / variable li�e dans les annotations. *)\n// let example f = (f:['a] 'a -> int -> 'b) f\n// let mkpair x y = (x,y)\ndef example f = (f: forall 'a. 'a -> int -> 'b) f\ndef example_ f = f f\ndef mkpair x y = (x, y)\n//│ example: (anything -> int -> 'b) -> int -> 'b\n//│        = [Function: example]\n//│ example_: ('a -> 'b & 'a) -> 'b\n//│         = [Function: example_]\n//│ mkpair: 'a -> 'b -> ('a, 'b,)\n//│       = [Function: mkpair]\n\n// untype example mkpair\n// (* �a echoue parce qu'on instancie 'b avec un type contenant 'a *)\n// (* Il faudrait que le message d'erreur soit plus clair. *)\nexample mkpair\nexample_ mkpair\n//│ res: int -> (??a, int,)\n//│    = [Function (anonymous)]\n//│ res: 'a -> (forall 'b 'c. 'b -> 'c -> ('b, 'c,), 'a,)\n//│    = [Function (anonymous)]\n\n\n\n// (* Exemple MLF avec des fonctions et des constructions r�cursives. *)\n\n// let rec x = 1 :: y\n// and     y = 2 :: x\n\n:ng\nrec def p = { x = cons 1 p.y; y = cons 2 p.x }\ndef x = p.x\ndef y = p.y\n//│ p: {x: List[1 | 2], y: List[1 | 2]}\n//│ x: List[1 | 2]\n//│ y: List[1 | 2]\n\n// let print_int x = print_string \"#\"; print_int x; print_string \" \"\n// let intprint x = print_int x\ndef print_int x =\n  let _ = print_string \"#\" in\n  let _ = print_int x in\n  print_string \" \"\ndef intprint x = print_int x\n//│ int -> unit\n//│   <:  print_int:\n//│ int -> unit\n//│          = [Function: print_int1]\n//│ intprint: int -> unit\n//│         = [Function: intprint]\n\n// let myNil l = l = []\ndef myNil l = eq l nil\n//│ myNil: anything -> bool\n//│      = [Function: myNil]\n\n// let rec append x l =\n//   if l = [] then [x]\n//   else (car l)::(append x (cdr l))\nrec def append x l =\n  if eq l nil then cons x nil\n  else cons (head l) (append x (tail l))\n//│ append: 'a -> List['a] -> List['a]\n//│       = [Function: append]\n\n// let rec map l f =\n//  if l = [] then []\n//  else (f (car l)) :: (map (cdr l) f)\nrec def map l f =\n  if eq l nil then nil\n  else cons (f (head l)) (map (tail l) f)\n//│ map: List['a] -> ('a -> 'b) -> List['b]\n//│    = [Function: map]\n\n// let message () = print \"** MESSAGE **\"\ndef message (_: unit) = print \"** MESSAGE **\"\n//│ message: unit -> unit\n//│        = [Function: message]\n\n// let intfa f = f 15\ndef intfa f = f 15\n//│ intfa: (15 -> 'a) -> 'a\n//│      = [Function: intfa]\n\n// let polyann (a:'x) (b:int) f (g:int -> 'x -> 'y) = g (f 10) a b\ndef polyann (a: 'x) (b: int) f (g: int -> 'x -> 'y) = g (f 10) a b\n//│ polyann: 'x -> int -> (10 -> int) -> (int -> 'x -> int -> 'a) -> 'a\n//│        = [Function: polyann]\n\ndef polyann_ a b f g = g (f 10) a b\n//│ polyann_: 'a -> 'b -> (10 -> 'c) -> ('c -> 'a -> 'b -> 'd) -> 'd\n//│         = [Function: polyann_]\n\n// let voyage (f:'p -> 'q) x y = (y, f x)\ndef voyage (f: 'p -> 'q) x y = (y, f x)\n//│ voyage: ('p -> 'a) -> 'p -> 'b -> ('b, 'a,)\n//│       = [Function: voyage]\n\ndef voyage_ f x y = (y, f x)\n//│ voyage_: ('a -> 'b) -> 'a -> 'c -> ('c, 'b,)\n//│        = [Function: voyage_]\n\n\n// let main =\n\n//   let print_sep s l =\n\n//     let max_depth = 20 in\n\n//     let rec alpha = print_list\n//     and print_list n l =\n\n//       if not(n < 0) then\n\n//         if nil l then print_string \"]\"\n//         else \n//           begin\n//             intprint (car l);\n//             print_string s;\n//             print_list (n-1) (cdr l)\n//           end\n//       else \n// \t       begin\n// \t         print_string (\"... ]\");\n// \t         (* failwith (\"T�te de liste : \"^(string_of_int (car l))) *)\n// \t       end\n//     in\n//     print_string \"[\";\n//     print_list max_depth l;\n\n//   in\n\n//   print (myNil [1;2]);\n//   print \" \";\n//   print (myNil [\"foo\";\"bar\"]);\n//   print \"\\n\";\n\n//   let ll = [10; 20; 30; 40] @ [50; 60; 70] in\n//   let ll2 = append 80 ll in\n//   print_sep \"; \" ll2;\n//   print_string \"\\n\";\n//   print_sep \"\" x;\n\n//   ()\n\n:stats\n:ng\ndef main =\n  let print_sep = fun s -> fun l ->\n    let max_depth = 20 in\n      let rec p =\n        { alpha = p.print_list;\n          print_list = fun n -> fun l ->\n            if not (n < 0) then\n              if is_empty l then print_string \"]\"\n              else\n                let _ = intprint (head l) in\n                let _ = print_string s in\n                p.print_list (n - 1) (tail l)\n            else\n              print_string \"... ]\"\n        } in\n      let alpha = p.alpha in\n      let print_list = p.print_list in\n        let _ = print_string \"[\" in\n        print_list max_depth l\n  in\n    let _ = print (myNil (cons 1 (cons 2 nil))) in\n    let _ = print \" \" in\n    let _ = print (myNil (cons \"foo\" (cons \"bar\" nil))) in\n    let _ = print \"\\n\" in\n    let ll = concat (cons 10 (cons 20 (cons 30 (cons 40 nil)))) (cons 50 (cons 60 (cons 70 nil))) in\n      let ll2 = append 80 ll in\n        let _ = print_sep \"; \" ll2 in\n        let _ = print_string \"\\n\" in\n        let _ = print_sep \"\" x in\n        null\n//│ main: null\n//│ constrain calls  : 1743\n//│ annoying  calls  : 94\n//│ subtyping calls  : 5536\n\n\n\n// (* Des probl�mes d'unification � gogo. *)\n// type sid = ['a] 'a -> 'a\n// type siid = ['a,'b] ('a -> 'b) -> ('a -> 'b)\n// type sdup = ['a,'b] ('a -> 'a) -> ('b -> 'b)\n// type sdip = ['a]    ('a -> 'a) -> ('a -> 'a)\n// type i = int\n// type j = bool\n\n// (*  PAGE 1 *)\n\n// please unify ['a > ['a0 > sid] i -> 'a0] 'a -> 'a \n// (* with *) :   ['c > sdup] (i -> 'c) -> (i -> 'c)\n// (* Result should be *) \n//          =   ['a0 > sdip] ['a = i -> 'a0] 'a -> 'a\n\n// please unify ['a > ['a0 > sid] i -> 'a0] ['b > ['b0 > siid] j -> 'b0] 'a -> 'b\n//          :   ['c > sdup] (i -> 'c) -> (j -> 'c)\n//          =   ['c0 > sdip] (i -> 'c0) -> (j -> 'c0)\n\n// please unify ['a > sid, 'b > sdup] 'a -> 'b  :   sid\n//          =   ['a > sdip] 'a -> 'a\n\n// please failon_unify ['a > sid, 'b = sdup] 'a -> 'b  :   sid\n\n// please unify ['a > sid, 'b = siid] 'a -> 'b  :   sid\n//          =   ['a = siid] 'a -> 'a\n\n// please unify ['a > ['a1 > sid, 'a2 > siid] 'a1 -> 'a2] 'a -> 'a\n//          :   ['c > ['c2 > siid] (i -> i) -> 'c2] 'c -> 'c\n//          =   ['a > ['c2 > siid] (i -> i) -> 'c2] 'a -> 'a\n\n// please unify ['a > ['a0 > siid] ('a0 -> i) -> i] 'a -> 'a\n//          :   ['a > ['a0 > sdup] 'a0 -> i] ('a -> i) -> ('a -> i)\n//          =   ['c0 > sdip, 'c = 'c0 -> i] ('c -> i) -> ('c -> i)\n\n// please unify ['a > sid] ['b1 > ['c] 'c -> 'a]    ['c1 > ['c3] 'c3 -> 'a] 'b1 -> 'c1\n//          :   ['a > sid] ['b2 > ['c] 'c -> i -> i, 'c2 = ['c3] 'c3 -> 'a] 'b2 -> 'c2\n//          =   ['a = i -> i] ['b1 > ['c] 'c -> 'a] ['c1 = ['c3] 'c3 -> 'a] 'b1 -> 'c1\n\n// please unify ['a > sid] ['b > sdup] ('b -> 'b) -> 'a\n//          :   ['c > sid] 'c -> 'c\n//          =   ['b > sdup] ('b -> 'b) -> ('b -> 'b)\n\n// please failon_unify ['a] ['b = ['b0] 'b0 -> 'a] 'a -> 'b : sid\n\n\n// (* PAGE 2 *)\n// please unify ['a1 = ['b1 = sdup] ['c] 'c -> 'b1] 'a1 -> i\n//          :   ['b2 = sdup] ['a2 = ['c3] 'c3 -> 'b2] 'a2 -> i\n//          =   ['b2 = sdup] ['a2 = ['c3] 'c3 -> 'b2] 'a2 -> i\n\n// please unify ['a1 = ['a2 = ['a3 = sdup] ['c] 'c -> 'a3 -> 'a3] 'a2 -> i] 'a1 -> i\n//          :   ['a1 = ['a3 = sdup] ['a2 = ['c] 'c -> 'a3 -> 'a3] 'a2 -> i] 'a1 -> i\n//          =   ['a1 = ['a3 = sdup] ['a2 = ['c] 'c -> 'a3 -> 'a3] 'a2 -> i] 'a1 -> i\n\n// please failon_unify ['a1 = ['a2 > sdup] 'a2 -> 'a2] 'a1 -> i\n//          :   ['a2 = sdup] ['a1 = 'a2 -> 'a2] 'a1 -> i\n\n// please failon_unify ['a1 = ['a2 > sdup] ['a3 = ['a4 > siid] 'a2 -> 'a4] ['a5] 'a5 -> 'a3 -> i] 'a1 -> i\n//          :   ['b2 > sdup] ['b3 = ['b4 > siid] 'b2 -> 'b4] ['b1 = ['b5] 'b5 -> 'b3 -> i] 'b1 -> i\n\n// please unify ['a1 = ['a2 = sdup, 'a3 = sdup] 'a2 -> 'a3] 'a1 -> i\n//          :   ['a1 = ['a = sdup] 'a -> 'a] 'a1 -> i\n//          =   ['a1 = ['a = sdup] 'a -> 'a] 'a1 -> i\n\n// please unify ['a1 = ['a2 = sdup, 'a3 = sdup] 'a2 -> 'a3] 'a1 -> i\n//          :   ['a1 > ['a] 'a -> 'a] 'a1 -> i\n//          =   ['a1 = ['a = sdup] 'a -> 'a] 'a1 -> i\n\n// please unify ['a1 = ['a2 = ['a3 = sdup] ['b] 'b -> 'a3 -> i] ['c] 'c -> 'a2 -> i] 'a1 -> i\n//          :   ['a3 = sdup] ['a1 = ['a2 = ['b] 'b -> 'a3 -> i] ['c] 'c -> 'a2 -> i] 'a1 -> i\n//          =   ['a3 = sdup] ['a1 = ['a2 = ['b] 'b -> 'a3 -> i] ['c] 'c -> 'a2 -> i] 'a1 -> i\n\n// please failon_unify ['a1 = ['a2 = ['a3 > sdup] ['b] 'b -> 'a3 -> i] ['c] 'c -> 'a2 -> i] 'a1 -> i\n//          :   ['a3 = sdup] ['a2 = ['b] 'b -> 'a3 -> i] ['a1 = ['c] 'c -> 'a2 -> i] 'a1 -> i\n\n// please unify ['a = ['a2 = ['b1 = sdup] i -> 'b1] ['a1 > ['c] 'c -> 'a2] 'a1 -> 'a1] 'a -> 'a\n//          :   ['b1 = sdup] ['a = ['a1 > ['c] 'c -> i -> 'b1] 'a1 -> 'a1] 'a -> 'a\n//          =   ['b1 = sdup] ['a = ['a1 > ['c] 'c -> i -> 'b1] 'a1 -> 'a1] 'a -> 'a\n\n// please unify ['b > sid, 'a = ['a1 = siid, 'a2 = ['c] 'a1 -> 'b -> 'c, 'a3 = ['c] 'a1 -> 'c] 'a2 -> 'a3] 'a -> 'a\n//          :   ['a = ['a1 = siid, 'a2 = ['c] 'a1 -> (i -> i) -> 'c, 'a3 = ['c] 'a1 -> 'c] 'a2 -> 'a3] 'a -> 'a\n//          =   ['a = ['a1 = siid, 'a2 = ['c] 'a1 -> (i -> i) -> 'c, 'a3 = ['c] 'a1 -> 'c] 'a2 -> 'a3] 'a -> 'a\n\n// please unify ['a1 = ['a2 = ['a3 = siid] i -> 'a3] j -> 'a2] i -> 'a1\n//          :   ['a3 = siid] i -> j -> i -> 'a3\n//          =   ['a3 = siid] i -> j -> i -> 'a3\n\n// please failon_unify ['a1 = ['a2 = ['a3 = sdup] ['b] 'b -> 'a3 -> i] ['c] 'c -> 'a2 -> i] 'a1 -> i\n//          :   ['a3 = sdup] ['a1 = ['a2 > ['b] 'b -> 'a3 -> i] ['c] 'c -> 'a2 -> i] 'a1 -> i\n\n\n// please unify ['a1 = ['a2 = ['a3 = ['a4 = ['a5 = 0] 'a5 -> i]\n//                                         ('a4 -> i) -> i]\n//                                         ('a3 -> i) -> i] 'a2 -> i] 'a1 -> i\n//          :   ['b1 = ['b2 = ['b3 = ['b4 = 0] ('b4 -> i) -> i]\n//                                         ('b3 -> i) -> i]\n//                                         ('b2 -> i) -> i] 'b1 -> i\n//          =   ['c1 = ['c5 = 0] ((((('c5 -> i) -> i) -> i) -> i) -> i) -> i] 'c1 -> i\n\n// please unify ['a1 > ['a2 > ['a3 > ['a4 > ['a5 > siid] 'a5 -> i]\n//                                         ('a4 -> i) -> i]\n//                                         ('a3 -> i) -> i] 'a2 -> i] 'a1 -> i\n//          :   ['b1 > ['b2 > ['b3 > ['b4 > sdup] ('b4 -> i) -> i]\n//                                         ('b3 -> i) -> i]\n//                                         ('b2 -> i) -> i] 'b1 -> i\n//          =   ['c1 > ['c5 > sdip] ((((('c5 -> i) -> i) -> i) -> i) -> i) -> i] 'c1 -> i\n\n// (* Avec deux quantificateurs � remonter. *)\n// please unify ['a2 > ['a4 > ['a6,'a7] ('a6 -> 'a7) -> i ] ('a4 -> i) -> i ] ('a2 -> i) -> i\n//          :   ['b1 > ['b3 > ['b5 > ['b6,'b7] 'b6 -> 'b7 ] ('b5 -> i) -> i ] ('b3 -> i) -> i ] 'b1 -> i\n//          =   ['c6,'c7] ((((('c6 -> 'c7) -> i) -> i) -> i) -> i) -> i\n\n\n// (* Cet exemple cr�e un graphe mal form�. *)\n// please failon_unify ['a] ['b = ['c] 'c -> 'a] 'b -> 'a\n//          :   ['a] ['b > ['c] 'c -> list ('c)] 'b -> 'a\n\n// (* Plus simple *)\n// please failon_unify ['a] ['b = ['c] 'c -> 'a] 'b -> 'a\n//          :   ['a] ['b > ['c] 'c -> 'c] 'b -> 'a\n\n// (* Extrusion automatique de binders. *)\n// please unify  ['a] ['b > ['c] 'c -> 'a] 'b -> 'a\n//           :   ['a] ['b > ['c] 'c -> 'c] 'b -> 'a\n//           =   ['c] ('c -> 'c) -> 'c\n\n// (* Plus compliqu�. *)\n// please unify  ['a] ['b > ['c] 'c -> 'a] 'b -> 'a\n//           :   ['a] ['b > ['c] 'c -> list ('c)] 'b -> 'a\n//           =   ['c] ('c -> list ('c)) -> list ('c)\n\n// (* Variante *)\n// please unify  ['a] ['b > ['c] ['d] 'c -> 'd] 'b -> 'a\n//           :   ['a] ['b = ['c] 'c -> 'a] 'b -> 'a\n//           =   ['a] ['b = ['c] 'c -> 'a] 'b -> 'a\n\n// please failon_unify  ['a] ['b = ['c] ['d] 'c -> 'd] 'b -> 'a\n//           :   ['a] ['b > ['c] 'c -> 'a] 'b -> 'a\n\n\n// please unify ['a] ['b > ['c] ['d > ['e] 'c -> 'e] 'c -> 'd] 'b -> 'a\n//          :   ['a] ['b > ['c] 'c -> 'a] 'b -> 'a\n//          =   ['c] ['a > ['e] 'c -> 'e] ('c -> 'a) -> 'a\n\n// please unify ['a] ['b > ['f] ['c] ['d > ['e] 'c -> 'e] 'f * 'c * 'd] 'b -> 'a\n//          :   ['a] ['b > ['f] ['c] 'f * 'c * 'a] 'b -> 'a\n//          =   ['c] ['a > ['e] 'c -> 'e] ['b > ['f] ('f * 'c * 'a)] 'b -> 'a\n\n// please failon_unify ['a] ['b = ['c] ['d > ['e] 'c -> 'e] 'c -> 'd] 'b -> 'a\n//          :   ['a] ['b > ['c] 'c -> 'a] 'b -> 'a\n\n// please failon_unify ['a] ['b > ['c] ['d > ['e] 'c -> 'e] 'c -> 'd] 'b -> 'a\n//          :   ['a] ['b = ['c] 'c -> 'a] 'b -> 'a\n\n\n\n// please unify ['a] ['b > ['b1] ['c > ['c1] ['d > ['d1] list ('b1 * 'c1 * 'd1)] list ('d) ] list ('c) ] 'b -> 'a\n//          :   ['a] (list (list (list ('a)))) -> 'a\n//          =   ['b1] ['c1] ['d1] (list (list (list ('b1 * 'c1 * 'd1)))) -> ('b1 * 'c1 * 'd1)\n\n\n// please notequiv ['b]['c] ('b * 'c)  -> ('b * 'c)\n//          :   ['b]['c] ('b * 'c)  -> ('c * 'b)\n\n\n\n// (* Unification d'une variable avec un sch�ma de types. *)\n// type sid = ['a] 'a -> 'a\n// let id y = y\n// let succ n = n + 1\n// let test = fun (x:'a) -> ((x:sid) , if true then x else id)\n// untype fun (x:'a) -> ((x:sid) , if true then x else succ)\n\ntype Sid = forall 'a. 'a -> 'a\ndef id y = y\ndef succ n = n + 1\ndef test = fun (x : 'a) -> (x : Sid, if true then x else id)\n//│ Defined type alias Sid\n//│ id: 'a -> 'a\n//│   = [Function: id1]\n//│ succ: int -> int\n//│     = [Function: succ1]\n//│ test: (Sid & 'a) -> (Sid, forall 'b. 'b -> 'b | 'a,)\n//│     = [Function: test]\n\n// * [FCP-IMPROV]\ndef test2 = fun (x : 'a) -> (x : Sid, if true then x else succ)\n//│ test2: (Sid & 'a) -> (Sid, int -> int | 'a,)\n//│      = [Function: test21]\n\n\n// (* Typable dans MLF, mais pas dans systeme F. *)\n// type sid = ['a] 'a -> 'a\n// type sa = ['b] ['a > sid] ('a -> 'b) -> 'b\n\n// * Same as A1 in `ex_shallow.mls` (see remarks there):\n// type Sa = forall 'a 'b. (('a | Sid) -> 'b) -> 'b\ntype Sa = forall 'b. (Sid -> 'b) -> 'b\n//│ Defined type alias Sa\n\n\n// let auto (x:sid) = x x\n// let id x = x\n// let k x y = x\ndef auto (x: Sid) = x x\ndef auto_ x = x x\ndef id x = x\ndef k x y = x\n//│ auto: Sid -> Sid\n//│     = [Function: auto]\n//│ auto_: ('a -> 'b & 'a) -> 'b\n//│      = [Function: auto_]\n//│ id: 'a -> 'a\n//│   = [Function: id2]\n//│ k: 'a -> anything -> 'a\n//│  = [Function: k]\n\n\n// let church_zero = fun f -> id\n// let church_un = id\n// let church_succ n = fun f x -> f (n f x)\n// untype fun g -> k (g auto) ((fun t -> g t ; t church_un) (fun x -> (church_succ x) church_zero))\n// let f  = fun (g:sa) -> k (g auto) ((fun t -> g t ; t church_un) (fun x -> (church_succ x) church_zero))\n// let a = fun f -> f id\ndef church_zero = fun f -> id\ndef church_un = id\ndef church_succ n = fun f -> fun x -> f (n f x)\ndef f = fun (g: Sa) -> k (g auto) ((fun t -> let _ = g t in t church_un) (fun x -> (church_succ x) church_zero))\ndef f_ = fun g -> k (g auto_) ((fun t -> let _ = g t in t church_un) (fun x -> (church_succ x) church_zero))\ndef a = fun f -> f id\n//│ church_zero: anything -> 'a -> 'a\n//│            = [Function: church_zero]\n//│ church_un: 'a -> 'a\n//│          = [Function: church_un]\n//│ church_succ: ('a -> 'b -> 'c) -> ('c -> 'd & 'a) -> 'b -> 'd\n//│            = [Function: church_succ]\n//│ f: Sa -> Sid\n//│  = [Function: f]\n//│ f_: ((forall 'a 'b. ('a -> 'b & 'a) -> 'b) -> 'c & (forall 'd 'e. ((forall 'f. anything -> 'f -> 'f) -> 'd -> anything) -> 'd -> 'e -> 'e) -> anything) -> 'c\n//│   = [Function: f_]\n//│ a: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│  = [Function: a]\n\n\n// let app x y = x y\n// let test1 = f a\n// let test2 = app f a\n\ndef app x y = x y\n//│ app: ('a -> 'b) -> 'a -> 'b\n//│    = [Function: app]\n\ndef test1 = f a\n//│ test1: Sid\n//│      = [Function: test11]\n\ndef test1 = f_ a\n//│ test1: 'a -> 'a\n//│      = [Function: test12]\n\ndef test2 = app f a\n//│ test2: Sid\n//│      = [Function: test22]\n\ndef test2 = app f_ a\n//│ test2: 'a -> 'a\n//│      = [Function: test23]\n\n\n\n// (* Create occur-checks. *)\n// please failon_unify ['b] 'b -> ('b -> 'b)\n//          :   ['a > ['c] ('c -> 'c) -> ('c -> 'c)]\n//                   'a -> 'a\n\n// please failon_unify ['i] 'i -> 'i\n//          :   ['a > ['c] ('c -> 'c) -> ('c -> 'c)]\n//              ['b > ['d] 'd -> 'a]\n//              'b -> 'a\n\n// ;;\n// please failon_unify ['i] 'i -> 'i\n//          :   ['a > ['c] ('c -> 'c) -> ('c -> 'c)]\n//              ['b > ['d] 'd -> 'a]\n//              'a -> 'b\n\n// ;;\n\n\n\n// let t = let x = fun y -> y in x x ;;\n// let t = let x = ((fun y -> y) : ['a] 'a -> 'a) in x x ;;\n// let t = let x = ((fun y -> y) : 'a) in x x ;;\ndef t = let x = fun y -> y in x x\ndef t = let x = (fun y -> y) : forall 'a. 'a -> 'a in x x\ndef t = let x = (fun y -> y) : 'a in x x\n//│ t: 'a -> 'a\n//│  = [Function: t5]\n//│ t: 'a -> 'a\n//│  = [Function: t6]\n//│ t: 'a -> 'a\n//│  = [Function: t7]\n\n\n// untype  fun x -> ( (((x:'a) : sid):'a), (x:'a) x)\n// untype  fun x -> ( ((x:'a) : sid), (x:'a) x)\n// untype  fun x -> ( ((x : sid):'a), (x:'a) x)\n// untype  fun x -> ( (((x:'a) : sid):'a), x x)\n// untype  fun x -> ( (x : sid), (x:'a) x)\n// let t = fun x -> ( (((x:'a) : sid):'a), (x:'a))\nfun x -> ( (((x : 'a) : Sid) : 'a), (x : 'a) x)\nfun x -> ( ((x : 'a) : Sid), (x : 'a) x)\nfun x -> ( ((x : Sid) : 'a), (x : 'a) x)\nfun x -> ( (((x : 'a) : Sid) : 'a), x x)\nfun x -> ( (x : Sid), (x : 'a) x)\nfun x -> ( (((x : 'a) : Sid) : 'a), x : 'a)\n//│ res: (Sid & 'a -> 'b & 'a) -> (Sid, 'b,)\n//│    = [Function: res]\n//│ res: (Sid & 'a -> 'b & 'a) -> (Sid, 'b,)\n//│    = [Function: res]\n//│ res: (Sid & 'a -> 'b & 'a) -> (Sid, 'b,)\n//│    = [Function: res]\n//│ res: (Sid & 'a -> 'b & 'a) -> (Sid, 'b,)\n//│    = [Function: res]\n//│ res: (Sid & 'a -> 'b & 'a) -> (Sid, 'b,)\n//│    = [Function: res]\n//│ res: (Sid & 'a) -> (Sid, 'a,)\n//│    = [Function: res]\n\n\n// (* R�cursion polymorphe. *)\n// untype let rec id x = if true then x else id id x in id\n\n// Same as `id1` in `ex_demo.mls`; works with `:RecursiveTypes`\n:e\nrec def id_ x = if true then x else id_ id_ x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> 'c\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c :> 'b -> 'c\n//│        <: 'a\n//│ ║  l.927: \trec def id_ x = if true then x else id_ id_ x\n//│ ╙──       \t                                    ^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required\n//│ ║  l.927: \trec def id_ x = if true then x else id_ id_ x\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ id_: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = [Function: id_]\n\n// let rec (id:sid) x = if true then x else id id x\n\ndef id: Sid\n//│ id: Sid\n//│   = <missing implementation>\n\n// * Note: infers with `:RecursiveTypes` but does not signature-check\n:e\nrec def id x = if true then x else id id x\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: 'b -> 'c\n//│     'b :> 'b -> 'c\n//│        <: 'c\n//│     'c :> 'b -> 'c\n//│        <: 'a\n//│ ║  l.956: \trec def id x = if true then x else id id x\n//│ ╙──       \t                                   ^^^^^\n//│ 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│   <:  id:\n//│ Sid\n//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required\n//│ ║  l.956: \trec def id x = if true then x else id id x\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.956: \trec def id x = if true then x else id id x\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.765: \ttype Sid = forall 'a. 'a -> 'a\n//│ ║         \t                      ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.956: \trec def id x = if true then x else id id x\n//│ ║         \t                                   ^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.956: \trec def id x = if true then x else id id x\n//│ ║         \t                            ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.765: \ttype Sid = forall 'a. 'a -> 'a\n//│ ╙──       \t                  ^^\n//│   = [Function: id3]\n\n\n// let z = print_string \"Ok, all tests passed.\"\n\nz = log \"Ok, all tests passed.\"\n//│ z: unit\n//│  = undefined\n//│ // Output\n//│ Ok, all tests passed.\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_voir.mls",
    "content": ":NoRecursiveTypes\n\n// ============ Dummy classes to represent the types in the examples ============\n\nclass List[a]\n  method Head: a\n  method Tail: List[a]\n//│ Defined class List[+a]\n//│ Declared List.Head: List['a] -> 'a\n//│ Declared List.Tail: List['a] -> List['a]\n\nclass Cons[a]: List[a] & { head: a; tail: List[a] }\n  method Head = this.head\n  method Tail = this.tail\ndef cons[a]: a -> List[a] -> List[a]\ndef cons head tail = Cons { head; tail }\n//│ Defined class Cons[+a]\n//│ Defined Cons.Head: Cons['a] -> 'a\n//│ Defined Cons.Tail: Cons['a] -> List['a]\n//│ cons: 'a -> List['a] -> List['a]\n//│     = <missing implementation>\n//│ ('head & 'a) -> (List['a] & 'tail) -> (Cons['a] with {head: 'head, tail: 'tail})\n//│   <:  cons:\n//│ 'a -> List['a] -> List['a]\n//│     = [Function: cons]\n\nclass Nil[a]: List[a]\n  method Head = error\n  method Tail = this\ndef nil: List['a]\nnil = Nil {}\n//│ Defined class Nil[+a]\n//│ Defined Nil.Head: Nil[?] -> nothing\n//│ Defined Nil.Tail: (Nil['a] & 'this) -> (Nil['a] & 'this)\n//│ nil: List[nothing]\n//│    = <missing implementation>\n//│ Nil[nothing]\n//│   <:  nil:\n//│ List[nothing]\n//│    = Nil {}\n\n\n\n// type sid = ['a] 'a -> 'a\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\n// let choose x y = if true then x else y\n// let choose3 x y z = (choose (choose x y) z)\n// let id = (fun x -> x : sid)\n// let succ n = n + 1\ndef choose x y = if true then x else y\ndef choose3 x y z = choose (choose x y) z\ndef id = (fun x -> x) : Sid\ndef id_ = fun x -> x\ndef succ n = n + 1\n//│ choose: 'a -> 'a -> 'a\n//│       = [Function: choose]\n//│ choose3: 'a -> 'a -> 'a -> 'a\n//│        = [Function: choose3]\n//│ id: Sid\n//│   = [Function: id]\n//│ id_: 'a -> 'a\n//│    = [Function: id_]\n//│ succ: int -> int\n//│     = [Function: succ]\n\n// let test = choose3 id\n// let test2 = test succ\ndef test = choose3 id\ndef test_ = choose3 id_\ndef test2 = test succ\ndef test2_ = test_ succ\n//│ test: 'a -> 'a -> (Sid | 'a)\n//│     = [Function: test]\n//│ test_: 'a -> 'a -> ('b -> 'b | 'a)\n//│      = [Function: test_]\n//│ test2: 'a -> (int -> int | Sid | 'a)\n//│      = [Function: test2]\n//│ test2_: 'a -> (int -> int | 'a)\n//│       = [Function: test2_]\n\n// (* Messages d'erreur foireux : *)\n// type s1 = ['a] 'a -> int * int ;;\n// type s2 = ['a] 'a -> bool * bool ;\n// fun x y -> ((x:s1),(y:s2), if true then x else y) ;; \n// fun x y -> ((x:s1),(y:s2), x x) ;; \ntype S1 = forall 'a. 'a -> (int, int)\ntype S2 = forall 'a. 'a -> (bool, bool)\nfun x -> fun y -> ((x : S1), (y : S2), if true then x else y)\nfun x -> fun y -> ((x : S1), (y : S2), x x)\n//│ Defined type alias S1\n//│ Defined type alias S2\n//│ res: (S1 & 'a) -> (S2 & 'a) -> (S1, S2, 'a,)\n//│    = [Function: res]\n//│ res: (S1 & 'a -> 'b & 'a) -> S2 -> (S1, S2, 'b,)\n//│    = [Function: res]\n\n// (* please onlyweak ['b = sid] 'b -> 'b : sid -> sid *)\n\n// (*\n// let example f = (f:['a] 'a -> int -> 'b) f\n// let mkpair x y = (x,y)\ndef example f = (f: forall 'a. 'a -> int -> 'b) f\ndef example_ f = f f\ndef mkpair x y = (x, y)\n//│ example: (anything -> int -> 'b) -> int -> 'b\n//│        = [Function: example]\n//│ example_: ('a -> 'b & 'a) -> 'b\n//│         = [Function: example_]\n//│ mkpair: 'a -> 'b -> ('a, 'b,)\n//│       = [Function: mkpair]\n\n// untype example mkpair\n// (* �a echoue parce qu'on instancie 'b avec un type contenant 'a *)\n// (* Il faudrait que le message d'erreur soit plus clair. *)\n// *)\nexample mkpair\nexample_ mkpair\n//│ res: int -> (??a, int,)\n//│    = [Function (anonymous)]\n//│ res: 'a -> (forall 'b 'c. 'b -> 'c -> ('b, 'c,), 'a,)\n//│    = [Function (anonymous)]\n\n// let make_ex3 x (f:['a > sid] 'a -> 'b ) = f x \ndef make_ex3 x (f: forall 'a. ('a | Sid) -> 'b) = f x\n//│ make_ex3: anything -> (anything -> 'a) -> 'a\n//│         = [Function: make_ex3]\n\n// let ex_list3 = [ make_ex3 succ ;\n// \t\t make_ex3 id ;\n// \t\t make_ex3 not ]\n\ndef ex_list3 = cons (make_ex3 succ) (\n      cons (make_ex3 id) (\n      cons (make_ex3 not) nil))\n//│ ex_list3: List[forall 'a. (anything -> 'a) -> 'a]\n//│         = [Function: ex_list3]\n\n\n// * TODO: what is `open`?\n\n// (*let test3 = listiter (open (fun v -> choose v id)) ex_list3  *)\n// (* Meme message d'erreur je crois. *)\n\n// type i = int\n// (* Affichage : nom des variables ??? *)\n// please unify ['a1 = ['a2 = ['a3 = ['a4 = ['a5 = 0] 'a5 -> i]\n//                                         ('a4 -> i) -> i]\n//                                         ('a3 -> i) -> i] 'a2 -> i] 'a1 -> i\n//          :   ['b1 = ['b2 = ['b3 = ['b4 = 0] ('b4 -> i) -> i]\n//                                         ('b3 -> i) -> i]\n//                                         ('b2 -> i) -> i] 'b1 -> i\n\n// (* Cet exemple cr�e un graphe mal form�. *)\n// please failon_unify ['a] ['b = ['c] 'c -> 'a] 'b -> 'a\n//          :   ['a] ['b > ['c] 'c -> list ('c)] 'b -> 'a\n\n// (* Plus simple *)\n// please failon_unify ['a] ['b = ['c] 'c -> 'a] 'b -> 'a\n//          :   ['a] ['b > ['c] 'c -> 'c] 'b -> 'a\n\n// (* Extrusion automatique de binders. *)\n// please unify  ['a] ['b > ['c] 'c -> 'a] 'b -> 'a\n//           :   ['a] ['b > ['c] 'c -> 'c] 'b -> 'a\n//           =   ['c] ('c -> 'c) -> 'c\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/ex_vr_validate.mls",
    "content": ":NoRecursiveTypes\n\n// (* Value restriction. *)\n// let id x = x \ndef id x = x\n//│ id: 'a -> 'a\n//│   = [Function: id]\n\n// untype let x = id id in x 1, x true\n// untype let x = (id id:'a) in x 1, x true\n// ;;\nlet x = id id in (x 1, x true)\nlet x = (id id : 'a) in (x 1, x true)\n//│ res: (1, true,)\n//│    = [ 1, true ]\n//│ res: (1, true,)\n//│    = [ 1, true ]\n\n// type sid = ['a] 'a -> 'a\n// ;;\ntype Sid = forall 'a. 'a -> 'a\n//│ Defined type alias Sid\n\n// let annot x = (x:sid)\n// ;;\ndef annot x = x : Sid\n//│ annot: Sid -> Sid\n//│      = [Function: annot]\n\n// let delta x = let y = (x:sid) in y y\n// ;;\ndef delta x = let y = (x : Sid) in y y\n//│ delta: Sid -> Sid\n//│      = [Function: delta]\n\n// untype fun x -> let y = (annot x) in y y\n// ;;\nfun x -> let y = annot x in y y\n//│ res: Sid -> Sid\n//│    = [Function: res]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/merge_regression_min.mls",
    "content": ":DontGeneralizeCurriedFunctions\n\n\ndef choose: 'a -> 'a -> 'a\n//│ choose: 'a -> 'a -> 'a\n//│       = <missing implementation>\n\nrec def id1 x = choose x (id1 id1 x)\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = <no result>\n//│      choose is not implemented\n\nid1 id\n//│ res: ('a & 'b) -> 'b | 'c\n//│   where\n//│     'a :> ('a & 'b) -> 'b\n//│        <: 'b\n//│     'b :> ('a & 'b) -> 'b\n//│        <: 'a -> 'b & 'c\n//│    = <no result>\n//│      id1 and choose are not implemented\n\n\n:GeneralizeCurriedFunctions\n\nid1 id\n//│ res: ('a & 'b) -> 'b | 'c\n//│   where\n//│     'a :> ('a & 'b) -> 'b\n//│        <: 'b\n//│     'b :> ('a & 'b) -> 'b\n//│        <: 'a -> 'b & 'c\n//│    = <no result>\n//│      id1 and choose are not implemented\n\nrec def id1 x = choose x (id1 id1 x)\n//│ id1: 'a -> 'b\n//│   where\n//│     'a :> 'a -> 'b\n//│        <: 'b\n//│     'b := 'a -> 'b\n//│    = <no result>\n//│      choose is not implemented\n\n// :e\nid1 id\n//│ res: ('a & 'b) -> 'b | 'c\n//│   where\n//│     'a :> ('a & 'b) -> 'b\n//│        <: 'b\n//│     'b :> ('a & 'b) -> 'b\n//│        <: 'a -> 'b & 'c\n//│    = <no result>\n//│      id1 and choose are not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/mlf-examples/variations_ex_hashtbl.mls",
    "content": ":NoRecursiveTypes\n:NoJS\n\n\n\n// ============ Dummy definitions to type the examples ============\n\n\nclass List[a]\n  method Get: a\ndef nil: List['a]\ndef cons[a]: a -> List[a] -> List[a]\ndef match_list: forall 'a 'b. List['a] -> 'b -> ('a -> List['a] -> 'b) -> 'b\ndef isnil: List['a] -> bool\n//│ Defined class List[+a]\n//│ Declared List.Get: List['a] -> 'a\n//│ nil: List[nothing]\n//│ cons: 'a -> List['a] -> List['a]\n//│ match_list: List['a] -> 'b -> ('a -> List['a] -> 'b) -> 'b\n//│ isnil: List[?] -> bool\n\nclass None\nclass Some[a]: { val: a }\ntype Option[a] = None | Some[a]\ndef none = None {}\ndef some val = Some { val }\n//│ Defined class None\n//│ Defined class Some[+a]\n//│ Defined type alias Option[+a]\n//│ none: None\n//│ some: 'val -> Some['val]\n\ndef match_opt: forall 'a 'r. (() -> 'r, 'a -> 'r) -> Option['a] -> 'r\n//│ match_opt: (() -> 'r, 'a -> 'r,) -> Option['a] -> 'r\n\nmatch_opt (n, s) opt = case opt of\n  None -> n(),\n  Some -> s(opt.val)\n//│ (() -> 'a, 'val -> 'a,) -> (None | Some[?] & {val: 'val}) -> 'a\n//│   <:  match_opt:\n//│ (() -> 'r, 'a -> 'r,) -> Option['a] -> 'r\n\n\n\n// ============ From the original examples ============\n\ntype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ Defined type alias ChurchInt\n\ndef succ (n: ChurchInt) = fun f -> fun x -> f (n f x)\ndef add (n: ChurchInt) (m: ChurchInt) = n succ m\ndef printInt (n: ChurchInt) = toString (n (fun x -> x + 1) 0)\n//│ succ: ChurchInt -> ('a -> ('a & 'b)) -> 'a -> 'b\n//│ add: ChurchInt -> ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n//│ printInt: ChurchInt -> string\n\ndef create_hashtbl () = nil\ndef hashtbl_add table key element = cons ((key, element)) table\n//│ create_hashtbl: () -> List[nothing]\n//│ hashtbl_add: List['a] -> 'b -> 'c -> List[('b, 'c,) | 'a]\n\ntable = create_hashtbl ()\ntable = hashtbl_add table \"one\" (fun f -> fun x -> f x)\n// table = hashtbl_add table \"two\" (fun f -> fun x -> f (f x))\n//│ table: List[nothing]\n//│ table: List[(\"one\", forall 'a 'b. ('a -> 'b) -> 'a -> 'b,)]\n\n\n\n// ============ Our own variations on ex_hashtbl ============\n\n\nrec def find table key =\n  match_list table none (fun h -> fun t ->\n    if eq h.0 key then some h.1\n    else find t key\n  )\n//│ find: List[{0: anything, 1: 'val}] -> anything -> (None | Some['val])\n\ndef nfind table key =\n  let opt = find table key in\n  case opt of\n  { None -> fun f -> fun x -> x\n  | Some -> opt.val\n  }\n//│ nfind: List[{0: anything, 1: 'val}] -> anything -> (anything -> 'a -> 'a | 'val)\n\ndef nfind: List[{0: anything; 1: 'val}] -> anything -> (anything -> 'a -> 'a | 'val)\n//│ nfind: List[{0: anything, 1: 'val}] -> anything -> (anything -> 'a -> 'a | 'val)\n\n// * Alternative\n// def nfind table key =\n//   (fun opt -> case opt of\n//   { None -> fun f -> fun x -> x\n//   | Some -> opt.val\n//   }) (find table key)\n\n\n// * Note that this works:\n\ndef x = nfind table \"one\"\n//│ x: ('b -> 'a) -> ('a & 'b) -> 'a\n\n// def x: ('b -> 'a) -> ('a & 'b) -> 'a\n\nadd x\n//│ res: ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n\n// * But this doesn't, because `nfind table \"one\"` is no longer generalized:\n\n:stats\n:e\nadd (nfind table \"one\")\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.113: \tadd (nfind table \"one\")\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.47: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                                           ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.47: \ttype ChurchInt = forall 'a. ('a -> 'a) -> ('a -> 'a)\n//│ ║        \t                             ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.113: \tadd (nfind table \"one\")\n//│ ║         \t     ^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.63: \ttable = hashtbl_add table \"one\" (fun f -> fun x -> f x)\n//│ ╙──      \t                                                     ^\n//│ res: error | ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n//│ constrain calls  : 100\n//│ annoying  calls  : 7\n//│ subtyping calls  : 305\n\n// * On the other hand, in this variation, distributivity saves the day:\n\ntmp = nfind table\n//│ tmp: anything -> ('b -> 'a) -> ('a & 'b) -> 'a\n\ntmp \"one\"\n//│ res: ('b -> 'a) -> ('a & 'b) -> 'a\n\nadd (tmp \"one\")\n//│ res: ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n\n// * But it all works with argument-generalization:\n// ==========================================================================================\n:GeneralizeArguments\n\n:stats\nadd (nfind table \"one\")\n//│ res: ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n//│ constrain calls  : 94\n//│ annoying  calls  : 7\n//│ subtyping calls  : 280\n\n:stats\n(fun x -> add x) (nfind table \"one\")\n//│ res: ChurchInt -> (('a -> ('a & 'b)) -> 'a -> 'b | ChurchInt)\n//│ constrain calls  : 106\n//│ annoying  calls  : 7\n//│ subtyping calls  : 314\n\n\n:stats\nzog = printInt (add (nfind table \"one\") (nfind table \"two\"))\n//│ zog: string\n//│ constrain calls  : 283\n//│ annoying  calls  : 14\n//│ subtyping calls  : 786\n\n:DontGeneralizeArguments\n// ==========================================================================================\n\n\n\nb = find table \"two\"\n//│ b: None | Some[forall 'a 'b. ('a -> 'b) -> 'a -> 'b]\n\nmatch_opt (\n    fun () -> fun f -> fun x -> x,\n    fun v -> v\n  ) b\n//│ res: ('a -> 'b) -> ('a & 'c) -> ('b | 'c)\n\nmatch_opt (\n    fun () -> fun f -> fun x -> x,\n    fun v -> v\n  ) (find table \"two\")\n//│ res: ('a -> 'b) -> ('a & 'c) -> ('b | 'c)\n\ndef foo key = match_opt (\n    fun () -> fun f -> id,\n    fun v -> v\n  ) (find table key)\n//│ foo: anything -> ('a -> 'b) -> 'a -> ('b | 'a)\n\nfoo 1\n//│ res: ('a -> 'b) -> 'a -> ('b | 'a)\n\n:e\nfoo 1 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.202: \tfoo 1 2\n//│ ║         \t^^^^^^^\n//│ ╟── integer literal of type `2` is not a function\n//│ ║  l.202: \tfoo 1 2\n//│ ║         \t      ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.63: \ttable = hashtbl_add table \"one\" (fun f -> fun x -> f x)\n//│ ║        \t                                                   ^^^\n//│ ╟── from reference:\n//│ ║  l.63: \ttable = hashtbl_add table \"one\" (fun f -> fun x -> f x)\n//│ ╙──      \t                                                   ^\n//│ res: error | 'a -> 'a\n\nfoo 1 error\n//│ res: 'a -> 'a\n\nfoo 1 error 2\n//│ res: 2\n\n(fun key -> match_opt (\n    fun () -> fun f -> fun x -> x,\n    fun v -> v\n  ) (find table key)) \"two\"\n//│ res: ('a -> 'b) -> ('c & 'a) -> ('c | 'b)\n\nres id\n//│ res: 'a -> 'a\n\ncase b of\n  None -> fun f -> fun x -> x,\n  Some -> b.val\n//│ res: ('a -> 'b) -> ('c & 'a) -> ('c | 'b)\n\nres id\n//│ res: 'a -> 'a\n\n(fun opt -> case b of\n  None -> fun f -> fun x -> x,\n  Some -> b.val) (find table \"two\")\n//│ res: ('a -> 'b) -> ('c & 'a) -> ('c | 'b)\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ADTs.mls",
    "content": "\nclass Lit: { val: int }\nclass Add[E]: { lhs: E; rhs: E }\nclass Nega[E]: { arg: E }\ndef lit val = Lit { val }\ndef add lhs rhs = Add { lhs; rhs }\ndef nega arg = Nega { arg }\n//│ Defined class Lit\n//│ Defined class Add[+E]\n//│ Defined class Nega[+E]\n//│ lit: (int & 'val) -> (Lit with {val: 'val})\n//│    = [Function: lit]\n//│ add: ('lhs & 'E) -> ('E & 'rhs) -> (Add['E] with {lhs: 'lhs, rhs: 'rhs})\n//│    = [Function: add]\n//│ nega: 'arg -> Nega['arg]\n//│     = [Function: nega]\n\nrec def evalStub1 e = case e of {\n  Lit -> e.val\n  }\n//│ evalStub1: (Lit with {val: 'val}) -> 'val\n//│          = [Function: evalStub1]\n\nrec def evalStub2 e = case e of {\n  Lit -> e.val | Nega -> 0 - (evalStub2 e.arg)\n  }\n//│ evalStub2: 'a -> int\n//│   where\n//│     'a <: Lit | Nega[?] & {arg: 'a}\n//│          = [Function: evalStub2]\n\nrec def eval e = case e of {\n  | Lit -> e.val\n  | Add -> eval e.lhs + eval e.rhs\n  | Nega -> 0 - (eval e.arg)\n  }\n//│ eval: 'a -> int\n//│   where\n//│     'a <: Add[?] & {lhs: 'a, rhs: 'a} | Lit | Nega[?] & {arg: 'a}\n//│     = [Function: eval]\n\nex = add (lit 2) (lit 2)\n//│ ex: Add[Lit & {val: 2}]\n//│   = Add { lhs: Lit { val: 2 }, rhs: Lit { val: 2 } }\n\neval ex\n//│ res: int\n//│    = 4\n\ndef e: Add['e] as 'e\n//│ e: 'e\n//│   where\n//│     'e :> Add['e]\n//│  = <missing implementation>\n\ndef e: Lit | Add['e] as 'e\n//│ e: 'e\n//│   where\n//│     'e :> Add['e] | Lit\n//│  = <missing implementation>\n\ndef e: Lit | Add['e] | Nega['e] as 'e\n//│ e: 'e\n//│   where\n//│     'e :> Add['e] | Lit | Nega['e]\n//│  = <missing implementation>\n\ne = ex\n//│ Add[Lit & {val: 2}]\n//│   <:  e:\n//│ 'e\n//│   where\n//│     'e :> Add['e] | Lit | Nega['e]\n//│  = Add { lhs: Lit { val: 2 }, rhs: Lit { val: 2 } }\n\neval e\n//│ res: int\n//│    = 4\n\neval (e : Lit | Add['e] | Nega['e] as 'e)\n//│ res: int\n//│    = 4\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\nclass Automata\nclass Binding\n//│ Defined class Automata\n//│ Defined class Binding\n\ndef exp: Array[Automata] -> Array[Binding]\neval exp\n//│ exp: Array[Automata] -> Array[Binding]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \teval exp\n//│ ║        \t^^^^^^^^\n//│ ╟── type `Array[Automata] -> Array[Binding]` does not match type `Add[?] & ?a | Lit & ?b | Nega[?] & ?c`\n//│ ║  l.+1: \tdef exp: Array[Automata] -> Array[Binding]\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Add[?] & ?d | Lit & ?e | Nega[?] & ?f`\n//│ ║  l.+2: \teval exp\n//│ ║        \t     ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.32: \trec def eval e = case e of {\n//│ ╙──      \t                      ^\n//│ res: error | int\n\n:e\neval (e : Lit | Add['e] | Nega[int] as 'e)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.+1: \teval (e : Lit | Add['e] | Nega[int] as 'e)\n//│ ║        \t      ^\n//│ ╟── type `Lit` is not an instance of type `int`\n//│ ║  l.62: \tdef e: Lit | Add['e] | Nega['e] as 'e\n//│ ║        \t       ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.+1: \teval (e : Lit | Add['e] | Nega[int] as 'e)\n//│ ╙──      \t                               ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \teval (e : Lit | Add['e] | Nega[int] as 'e)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `int` does not match type `Add[?] & ?a | Lit & ?b | Nega[?] & ?c`\n//│ ║  l.+1: \teval (e : Lit | Add['e] | Nega[int] as 'e)\n//│ ║        \t                               ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.32: \trec def eval e = case e of {\n//│ ║        \t                      ^\n//│ ╟── from field selection:\n//│ ║  l.35: \t  | Nega -> 0 - (eval e.arg)\n//│ ╙──      \t                      ^^^^^\n//│ res: error | int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ADTsRepro.mls",
    "content": "\ntype Add[E] = { x: E -> E }\n//│ Defined type alias Add[=E]\n\ndef e2: Add['e] as 'e\n//│ e2: 'e\n//│   where\n//│     'e := Add['e]\n//│   = <missing implementation>\n\ne2 : Add['e] as 'e\n//│ res: 'e\n//│   where\n//│     'e := Add['e]\n//│    = <no result>\n//│      e2 is not implemented\n\n\ndef f0: ('a -> int) as 'a\n//│ f0: 'a\n//│   where\n//│     'a := 'a -> int\n//│   = <missing implementation>\n\n// :e // * Did not work before when added subtype checking to constraining...\nf0 = f0\n//│ 'a\n//│   where\n//│     'a := 'a -> int\n//│   <:  f0:\n//│ 'a\n//│   where\n//│     'a := 'a -> int\n//│   = <no result>\n//│     f0 is not implemented\n\n\ntype F1 = F1 -> int\n//│ Defined type alias F1\n\ndef f1: F1\n//│ f1: F1\n//│   = <missing implementation>\n\nf1 = f1\n//│ F1\n//│   <:  f1:\n//│ F1\n//│   = <no result>\n//│     f1 is not implemented\n\n\ntype F2[A] = F2[A] -> A\n//│ Defined type alias F2[=A]\n\ndef f1: F2[int]\n//│ f1: F2[int]\n//│   = <missing implementation>\n\nf1 = f1\n//│ F2[int]\n//│   <:  f1:\n//│ F2[int]\n//│   = <no result>\n//│     f1 is not implemented\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Addable.mls",
    "content": "\nclass Addable[A]\n  method Add: A -> A\n//│ Defined class Addable[=A]\n//│ Declared Addable.Add: Addable['A] -> 'A -> 'A\n\nclass Numb: Addable[Numb] & { val: int }\n  method Add that = Numb { val = this.val + that.val }\n//│ Defined class Numb\n//│ Defined Numb.Add: Numb -> {val: int} -> Numb\n\nclass Stri: Addable[Stri] & { val: string }\n  method Add that = Stri { val = concat this.val that.val }\n//│ Defined class Stri\n//│ Defined Stri.Add: Stri -> {val: string} -> Stri\n\nn = Numb { val = 1 }\n//│ n: Numb & {val: 1}\n//│  = Numb { val: 1 }\n\nn.Add n\n//│ res: Numb\n//│    = Numb { val: 2 }\n\nn.Add\n//│ res: Numb -> Numb\n//│    = [Function: Add]\n\n\ndef addTwo a0 a1 = a0.Add a1\n//│ addTwo: Addable['A] -> 'A -> 'A\n//│       = [Function: addTwo]\n\n\naddTwo n n\n//│ res: Numb\n//│    = Numb { val: 2 }\n\ns = Stri { val = \"hey\" }\n//│ s: Stri & {val: \"hey\"}\n//│  = Stri { val: 'hey' }\n\ns.Add s\n//│ res: Stri\n//│    = Stri { val: 'heyhey' }\n\naddTwo s s\n//│ res: Stri\n//│    = Stri { val: 'heyhey' }\n\n\n\ndef addSame a = a.Add a\n//│ addSame: (Addable['A] & 'A) -> 'A\n//│        = [Function: addSame]\n\naddSame n\n//│ res: Numb\n//│    = Numb { val: 2 }\n\n\nrec def addNTimes a n =\n  if n <= 1 then a else a.Add (addNTimes a (n - 1))\n//│ addNTimes: (Addable['A] & 'A) -> int -> 'A\n//│          = [Function: addNTimes]\n\naddNTimes n 12\n//│ res: Numb\n//│    = Numb { val: 12 }\n\naddNTimes s 5\n//│ res: Stri\n//│    = Stri { val: 'heyheyheyheyhey' }\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\nrec def addNTimes a n =\n  if n < 0 then 0 else a.Add (addNTimes a (n - 1))\naddNTimes n 12\n//│ addNTimes: Addable['A] -> int -> 'A\n//│   where\n//│     'A :> 0\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \taddNTimes n 12\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not an instance of type `Numb`\n//│ ║  l.+2: \t  if n < 0 then 0 else a.Add (addNTimes a (n - 1))\n//│ ║        \t                ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.7: \tclass Numb: Addable[Numb] & { val: int }\n//│ ╙──     \t                    ^^^^\n//│ res: error\n\nrec def addNTimes a n =\n  if n <= 0 then 0 else a.Add addNTimes a (n - 1)\n//│ addNTimes: 'a -> int -> 'b\n//│   where\n//│     'a <: Addable['A]\n//│     'A := 'a -> int -> 'b\n//│     'b :> 0\n\naddNTimes n 12\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \taddNTimes n 12\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── function of type `?a -> ?b -> ?c` is not an instance of type `Numb`\n//│ ║  l.102: \trec def addNTimes a n =\n//│ ║         \t                  ^^^^^\n//│ ║  l.103: \t  if n <= 0 then 0 else a.Add addNTimes a (n - 1)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.7: \tclass Numb: Addable[Numb] & { val: int }\n//│ ╙──     \t                    ^^^^\n//│ res: error\n\naddSame n n\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \taddSame n n\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── application of type `Numb & {val: ?val}` is not a function\n//│ ║  l.17: \tn = Numb { val = 1 }\n//│ ║        \t    ^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(forall ?a. ?a) -> ?b`\n//│ ║  l.+1: \taddSame n n\n//│ ╙──      \t        ^\n//│ res: error\n\naddTwo s n\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \taddTwo s n\n//│ ║        \t^^^^^^^^^^\n//│ ╟── application of type `Numb & {val: ?val}` is not an instance of type `Stri`\n//│ ║  l.17: \tn = Numb { val = 1 }\n//│ ║        \t    ^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Stri`\n//│ ║  l.+1: \taddTwo s n\n//│ ║        \t         ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.12: \tclass Stri: Addable[Stri] & { val: string }\n//│ ║        \t                    ^^^^\n//│ ╟── from reference:\n//│ ║  l.30: \tdef addTwo a0 a1 = a0.Add a1\n//│ ╙──      \t                          ^^\n//│ res: error\n\nclass Str_bad_0: Addable[Str_bad_0] & { val: string }\n  method Add that = Str_bad_0 { val = this.val + that.val }\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+2: \t  method Add that = Str_bad_0 { val = this.val + that.val }\n//│ ║        \t                                      ^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.+1: \tclass Str_bad_0: Addable[Str_bad_0] & { val: string }\n//│ ║        \t                                             ^^^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.+2: \t  method Add that = Str_bad_0 { val = this.val + that.val }\n//│ ╙──      \t                                      ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+2: \t  method Add that = Str_bad_0 { val = this.val + that.val }\n//│ ║        \t                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` is not an instance of type `string`\n//│ ║  l.+2: \t  method Add that = Str_bad_0 { val = this.val + that.val }\n//│ ║        \t                                      ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.+1: \tclass Str_bad_0: Addable[Str_bad_0] & { val: string }\n//│ ╙──      \t                                             ^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Add that = Str_bad_0 { val = this.val + that.val }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.+1: \tclass Str_bad_0: Addable[Str_bad_0] & { val: string }\n//│ ║        \t                                             ^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.+2: \t  method Add that = Str_bad_0 { val = this.val + that.val }\n//│ ╙──      \t                                                 ^^^^^^^^\n//│ Defined class Str_bad_0\n//│ Defined Str_bad_0.Add: Str_bad_0 -> {val: int} -> ((Str_bad_0 with {val: error | int}) | error)\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/AdtStyle.mls",
    "content": ":NoJS\n\ndatatype Either[A, B] = Left(A) | Right(B)\n//│ Defined class Either[+A, +B]\n//│ Declared Either.Left: Either['A, ?] -> ('A,)\n//│ Declared Either.Right: Either[?, 'B] -> ('B,)\n//│ Defined class Left[+A, +B]\n//│ Defined class Right[+A, +B]\n//│ Left: 'a -> Either['a, nothing]\n//│ Right: 'a -> Either[nothing, 'a]\n\n\ndatatype List[A] = Cons(A, List[A]) | Nil\n//│ Defined class List[+A]\n//│ Declared List.Cons: List['A] -> ('A, List['A],)\n//│ Declared List.Nil: List[?] -> anything\n//│ Defined class Cons[+A]\n//│ Defined class Nil[+A]\n//│ Cons: ('a, List['a],) -> List['a]\n//│ Nil: List[nothing]\n\ntype Heap = List[(string, int)]\ndatatype HeapVar = HeapInt(int) | HeapV(Heap)\ndatatype Exp = EInt(int) | Var(string) | Plus(Exp, Exp) | Times(Exp, Exp)\ndatatype Stmt = Skip | Assign(string, Exp)\n//│ Defined type alias Heap\n//│ Defined class HeapVar\n//│ Declared HeapVar.HeapInt: HeapVar -> (int,)\n//│ Declared HeapVar.HeapV: HeapVar -> (Heap,)\n//│ Defined class HeapInt\n//│ Defined class HeapV\n//│ Defined class Exp\n//│ Declared Exp.EInt: Exp -> (int,)\n//│ Declared Exp.Var: Exp -> (string,)\n//│ Declared Exp.Plus: Exp -> (Exp, Exp,)\n//│ Declared Exp.Times: Exp -> (Exp, Exp,)\n//│ Defined class EInt\n//│ Defined class Var\n//│ Defined class Plus\n//│ Defined class Times\n//│ Defined class Stmt\n//│ Declared Stmt.Skip: Stmt -> anything\n//│ Declared Stmt.Assign: Stmt -> (string, Exp,)\n//│ Defined class Skip\n//│ Defined class Assign\n//│ HeapInt: int -> HeapVar\n//│ HeapV: Heap -> HeapVar\n//│ EInt: int -> Exp\n//│ Var: string -> Exp\n//│ Plus: (Exp, Exp,) -> Exp\n//│ Times: (Exp, Exp,) -> Exp\n//│ Skip: Stmt\n//│ Assign: (string, Exp,) -> Stmt\n\ndatatype Poly[A] = PolyList(List[A -> A])\n//│ Defined class Poly[=A]\n//│ Declared Poly.PolyList: Poly['A] -> (List['A -> 'A],)\n//│ Defined class PolyList[=A]\n//│ PolyList: List['a -> 'a] -> Poly['a]\n\ndatatype FCPoly = FCPolyList(List[forall 'a. 'a -> 'a])\n//│ Defined class FCPoly\n//│ Declared FCPoly.FCPolyList: FCPoly -> (List[forall 'a. 'a -> 'a],)\n//│ Defined class FCPolyList\n//│ FCPolyList: List[forall 'a. 'a -> 'a] -> FCPoly\n\n\nfun x ->\n  match x with\n   | Cons(a, b) -> b\n   | Nil -> Nil\n//│ res: List['A] -> List['A]\n\nfun x ->\n  match x with\n   | Cons(1, b) -> Cons(0, b)\n   | Cons(a, b) -> b\n   | Nil -> Nil\n//│ res: List[int & 'A] -> List[0 | 'A]\n\nfun x ->\n  match x with\n   | EInt(v,) -> v\n   | _ -> 0\n//│ res: Exp -> int\n\nfun x ->\n  match x with\n   | (1, 2, 3) -> 6\n   | (x, y, 3,) -> x + y\n   | _ -> 0\n//│ res: ((int, int, int,),) -> int\n\nfun (x, y) ->\n  match (x, y) with\n   | (1, 2) -> 3\n   | _ -> 0\n//│ res: (int, int,) -> (0 | 3)\n\n\nfoo x = match x with\n  | 0 -> 0\n  | 1 -> 1\n//│ foo: int -> (0 | 1)\n\nfoo 0\n//│ res: 0 | 1\n\n// FIXME allow ascriptions\n:e\nfoo x = match x with\n  | (0 : int) -> 0\n  | (1 : int) -> 1\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Cannot handle pattern 0 : int\n\nfoo 0\n//│ res: 0 | 1\n\n// FIXME such patterns are not allowed\n:e\nfoo x = match x with\n  | (id 0) -> 0\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: id cannot be pattern matched\n\n\nmatch Cons(0, Nil) with Cons(0, Nil) -> 0\n//│ res: 0\n\nmatch Cons(false, Nil) with Cons(true, Nil) -> 0\n//│ res: 0\n\nmatch Cons(0, Nil) with Cons(1, Nil) -> 0\n//│ res: 0\n\n:e\nmatch Cons(true, Nil) with Cons(1, Nil) -> 0\n//│ ╔══[ERROR] Type mismatch in ADT pattern matching:\n//│ ║  l.136: \tmatch Cons(true, Nil) with Cons(1, Nil) -> 0\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.136: \tmatch Cons(true, Nil) with Cons(1, Nil) -> 0\n//│ ║         \t           ^^^^\n//│ ╟── Note: constraint arises from literal pattern:\n//│ ║  l.136: \tmatch Cons(true, Nil) with Cons(1, Nil) -> 0\n//│ ╙──       \t                                ^\n//│ res: 0\n\nfun x -> \n  match x with Cons(Left a, Nil) -> a\n//│ res: List[Either['a, ?]] -> 'a\n\n:e\nres(Cons(true, Nil))\n// match Cons(true, Nil) with Cons(Left a, Nil) -> a\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.153: \tres(Cons(true, Nil))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `Either`\n//│ ║  l.153: \tres(Cons(true, Nil))\n//│ ║         \t         ^^^^\n//│ ╟── Note: constraint arises from pattern:\n//│ ║  l.149: \t  match x with Cons(Left a, Nil) -> a\n//│ ║         \t                    ^^^^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.13: \tdatatype List[A] = Cons(A, List[A]) | Nil\n//│ ╙──      \t              ^\n//│ res: error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/AlexJ.mls",
    "content": "\n\n1\n//│ res: 1\n//│    = 1\n\nclass A: { x: int }\n//│ Defined class A\n\na = A{ x = 123 }\n//│ a: A & {x: 123}\n//│  = A { x: 123 }\n\na.x\n//│ res: 123\n//│    = 123\n\n\ndef foo x = (x, x)\n//│ foo: 'a -> ('a, 'a,)\n//│    = [Function: foo]\n\nid\n//│ res: 'a -> 'a\n//│    = [Function: id]\n\nr = foo id\n//│ r: (forall 'a. 'a -> 'a, forall 'a. 'a -> 'a,)\n//│  = [ [Function: id], [Function: id] ]\n\ndef fst(x, _) = x\ndef snd(_, x) = x\n//│ fst: ('a, anything,) -> 'a\n//│    = [Function: fst]\n//│ snd: (anything, 'a,) -> 'a\n//│    = [Function: snd]\n\nfst(1,2)\n//│ res: 1\n//│    = 1\n\n:e\nfst((1,2))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.43: \tfst((1,2))\n//│ ║        \t^^^^^^^^^^\n//│ ╟── argument of type `((1, 2,),)` does not match type `(?a, ?b,)`\n//│ ║  l.43: \tfst((1,2))\n//│ ║        \t   ^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.31: \tdef fst(x, _) = x\n//│ ╙──      \t       ^^^^^^\n//│ res: error\n//│    = [ 1, 2 ]\n\ndef fst((x, _)) = x\ndef snd((_, x)) = x\n//│ fst: (('a, anything,),) -> 'a\n//│    = [Function: fst1]\n//│ snd: ((anything, 'a,),) -> 'a\n//│    = [Function: snd1]\n\n:e\nfst(1,2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.64: \tfst(1,2)\n//│ ║        \t^^^^^^^^\n//│ ╟── argument list of type `(1, 2,)` does not match type `((?a, ?b,),)`\n//│ ║  l.64: \tfst(1,2)\n//│ ╙──      \t   ^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))\n\nfst((1,2))\n//│ res: 1\n//│    = 1\n\ns = fst(r)\n//│ s: 'a -> 'a\n//│  = [Function: id]\n\ns \"abc\"\n//│ res: \"abc\"\n//│    = 'abc'\n\ns 123\n//│ res: 123\n//│    = 123\n\nfst r \"abc\"\n//│ res: \"abc\"\n//│    = 'abc'\n\nfst(r)\n//│ res: 'a -> 'a\n//│    = [Function: id]\n\nsnd(r) 123\n//│ res: 123\n//│    = 123\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Annoying.mls",
    "content": ":NoJS\n// :NoProvs\n\ndef foo: ~int\\x\n//│ foo: ~int\\x\n\nfoo: ~(int\\x)\n//│ res: ~int\\x\n\nfoo: (~int)\\x\n//│ res: ~int\n\nres: ~(int\\x)\n//│ res: ~int\\x\n\n\ndef foo: (~ 'a \\ x) -> 'a -> 'a\n//│ foo: ~'a\\x -> 'a -> 'a\n\nfoo 1\n//│ res: ('a & ~1) -> 'a\n\ndef foo: (~ 'a \\ x) -> 'a\n//│ foo: anything -> nothing\n\nfoo 1\n//│ res: nothing\n\n\nclass X: {}\n//│ Defined class X\n\ndef v0: (~(X\\x))\\y\n//│ v0: ~X\\x\\y\n\n:e\nv0: int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.37: \tv0: int\n//│ ║        \t^^\n//│ ╟── type `~X\\x\\y` is not an instance of type `int`\n//│ ║  l.33: \tdef v0: (~(X\\x))\\y\n//│ ║        \t        ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.37: \tv0: int\n//│ ║        \t^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.37: \tv0: int\n//│ ╙──      \t    ^^^\n//│ res: int\n\n\n\n// def test: (int | { x: 'a } | { y: 'a }) -> 'a\ndef test: (int & { f: 'a } | { x: 'a } | { y: 'a }) -> 'a\n//│ test: anything -> nothing\n\n:e\ndef test x = case x of { int -> x.f | _ -> x.x }\n//│ (int & {f: 'f} | {x: 'f} & ~int) -> 'f\n//│   <:  test:\n//│ anything -> nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.59: \tdef test x = case x of { int -> x.f | _ -> x.x }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `int & {x: 'a} | {x: 'a} & ~?a` does not have field 'f'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.59: \tdef test x = case x of { int -> x.f | _ -> x.x }\n//│ ║        \t                                ^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.59: \tdef test x = case x of { int -> x.f | _ -> x.x }\n//│ ╙──      \t                  ^\n\n// Note: not an error, but a terminating `test` can't be implemented\ntest 1\n//│ res: nothing\n\ntest { x = 1 }\n//│ res: nothing\n\ntest { y = 1 }\n//│ res: nothing\n\n\nclass A: { }\nclass B: { }\nclass C: { }\n//│ Defined class A\n//│ Defined class B\n//│ Defined class C\n\ndef test: (A & { a: 'a } | B & { b: 'a } | C & { c: 'a }) -> 'a\n//│ test: (A & {a: 'a} | B & {b: 'a} | C & {c: 'a}) -> 'a\n\ntest (error: A & { a: int })\ntest (error: B & { b: int })\ntest (error: C & { c: int })\n//│ res: int\n//│ res: int\n//│ res: int\n\n:e\ntest (error: B & { c: int })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.103: \ttest (error: B & { c: int })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `B & {c: int}` does not match type `A & {a: 'a} | B & {b: 'a} | C & {c: 'a}`\n//│ ║  l.103: \ttest (error: B & { c: int })\n//│ ║         \t             ^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.92: \tdef test: (A & { a: 'a } | B & { b: 'a } | C & { c: 'a }) -> 'a\n//│ ╙──      \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error\n\n\ndef test: (A & { x: 'a; y: 'b } | B & { x: 'a; y: 'b } | C & { x: 'a; y: 'b }) -> { l: 'a; r: 'b }\n//│ test: (A & {x: 'a, y: 'b} | B & {x: 'a, y: 'b} | C & {x: 'a, y: 'b}) -> {l: 'a, r: 'b}\n\ntest (error: A & { x: int; y: string })\ntest (error: B & { x: int; y: string })\ntest (error: C & { x: int; y: string })\n//│ res: {l: int, r: string}\n//│ res: {l: int, r: string}\n//│ res: {l: int, r: string}\n\n:e\ntest (error: A & { x: int })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.127: \ttest (error: A & { x: int })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `A & {x: int}` does not match type `A & {x: 'a, y: 'b} | B & {x: 'a, y: 'b} | C & {x: 'a, y: 'b}`\n//│ ║  l.127: \ttest (error: A & { x: int })\n//│ ║         \t             ^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.116: \tdef test: (A & { x: 'a; y: 'b } | B & { x: 'a; y: 'b } | C & { x: 'a; y: 'b }) -> { l: 'a; r: 'b }\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | {l: int, r: nothing}\n\n\ndef test: (A & { xA: 'a; yA: 'b } | B & { xB: 'a; yB: 'b } | C & { xC: 'a; yC: 'b }) -> { l: 'a; r: 'b }\n//│ test: (A & {xA: 'a, yA: 'b} | B & {xB: 'a, yB: 'b} | C & {xC: 'a, yC: 'b}) -> {l: 'a, r: 'b}\n\ntest (error: A & { xA: int; yA: string })\ntest (error: B & { xB: int; yB: string })\ntest (error: C & { xC: int; yC: string })\n//│ res: {l: int, r: string}\n//│ res: {l: int, r: string}\n//│ res: {l: int, r: string}\n\n\ndef negInt: ~int\n//│ negInt: ~int\n\ndef v = negInt with { x = 1 }\n//│ v: ~int & {x: 1}\n\nv.x\n//│ res: 1\n\n(id v).x\n//│ res: 1\n\n:e\nnegInt: A | { x: 'a }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.164: \tnegInt: A | { x: 'a }\n//│ ║         \t^^^^^^\n//│ ╟── type `~int` does not match type `A | {x: 'a}`\n//│ ║  l.151: \tdef negInt: ~int\n//│ ║         \t            ^^^^\n//│ ╟── but it flows into reference with expected type `A | {x: 'a}`\n//│ ║  l.164: \tnegInt: A | { x: 'a }\n//│ ║         \t^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.164: \tnegInt: A | { x: 'a }\n//│ ╙──       \t        ^^^^^^^^^^^^^\n//│ res: A | {x: nothing}\n\nv: A | { x: 'a }\n//│ res: A | {x: 1}\n\n(error: A) with { x = 1 }\n//│ res: A\\x & {x: 1}\n\n// Note that we get {x: nothing} because the LHS is a subtype of A so 'a is not constrained\n(error: A) with { x = 1 } : A | { x: 'a }\n//│ res: A | {x: nothing}\n\nid (error: A) with { x = 1 } : A | { x: 'a }\n//│ res: A | {x: nothing}\n\ndef negWeird: ~(~(~(A & { x: int })))\n//│ negWeird: ~(A & {x: int})\n\ndef v = negWeird with { x = 1 }\n//│ v: ~A\\x & {x: 1} | {x: 1} & ~{x: int}\n\ndef w: {x: 1} & ~{x: int} | ~A\\x & {x: 1}\n//│ w: {x: 1} & ~A\\x\n\nv: A | { x: 'a }\n//│ res: A | {x: 1}\n\n\nw: A | { x: 'a }\n//│ res: A | {x: 1}\n\ndef v: {x: 1} & ~{x: int}\nv: { x: 'a }\n//│ v: nothing\n//│ res: {x: nothing}\n\ndef v: A & {x: 1} & ~{x: int}\nv: A & { x: 'a }\n//│ v: nothing\n//│ res: A & {x: nothing}\n\n\ndef funny = error: nothing\\x\n//│ funny: nothing\n\n// It could be agrued this should fail... but that would make constraint solving more awkward!\nfunny.x\n//│ res: nothing\n\n\n:e\n(error: { x: int }): int | string\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.228: \t(error: { x: int }): int | string\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `{x: int}` does not match type `int | string`\n//│ ║  l.228: \t(error: { x: int }): int | string\n//│ ║         \t        ^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.228: \t(error: { x: int }): int | string\n//│ ╙──       \t                     ^^^^^^^^^^^^\n//│ res: int | string\n\n\n(error: (~ 'a) \\ x): { x: int }\n//│ res: {x: int}\n\n\nidx = id with { x = 1 }\n//│ idx: 'a -> 'a & {x: 1}\n\nidx idx.x\n//│ res: 1\n\ndef indirect i = i i.x\n//│ indirect: ('x -> 'a & {x: 'x}) -> 'a\n\nindirect idx\n//│ res: 1\n\nif true then id else idx\n//│ res: 'a -> 'a\n\nr =  if true then id with { x = \"a\"; y = \"b\" } else idx\n//│ r: 'a -> 'a & {x: \"a\" | 1}\n\nr r.x\n//│ res: \"a\" | 1\n\nindirect r\n//│ res: \"a\" | 1\n\ndef takeFunOrRecord: (int -> int | { x: int }) -> int\n//│ takeFunOrRecord: anything -> int\n\n:pe\ntakeFunOrRecord x = case x of { { x = v } -> 0 | _ -> 1 }\n//│ /!\\ Parse error: Expected \"}\":1:33, found \"{ x = v } \" at l.273:33: takeFunOrRecord x = case x of { { x = v } -> 0 | _ -> 1 }\n\n:pe\ntakeFunOrRecord x = case x of { { x } -> 0 | _ -> 1 }\n//│ /!\\ Parse error: Expected \"}\":1:33, found \"{ x } -> 0\" at l.277:33: takeFunOrRecord x = case x of { { x } -> 0 | _ -> 1 }\n\n:pe\ntakeFunOrRecord x = case x of { (int -> int) -> 0 | _ -> 1 }\n//│ /!\\ Parse error: Expected \"}\":1:33, found \"(int -> in\" at l.281:33: takeFunOrRecord x = case x of { (int -> int) -> 0 | _ -> 1 }\n\n:pe\ntakeFunOrRecord x = case x of { (->) -> 0 | _ -> 1 }\n//│ /!\\ Parse error: Expected \"}\":1:33, found \"(->) -> 0 \" at l.285:33: takeFunOrRecord x = case x of { (->) -> 0 | _ -> 1 }\n\n\nclass AA\ntrait TT\ndef ty: AA | ('a \\ x)\ndef ty2: TT & { x: int }\n// def ty: AA | (int -> int)\n//│ Defined class AA\n//│ Defined trait TT\n//│ ty: in AA | nothing\\x out AA\n//│ ty2: TT & {x: int}\n\n:e\nty = ty2\n//│ TT & {x: int}\n//│   <:  ty:\n//│ AA | nothing\\x\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.300: \tty = ty2\n//│ ║         \t^^^^^^^^\n//│ ╟── type `TT & {x: int}` does not match type `AA | 'a\\x`\n//│ ║  l.292: \tdef ty2: TT & { x: int }\n//│ ║         \t         ^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `AA | 'a\\x`\n//│ ║  l.300: \tty = ty2\n//│ ║         \t     ^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.291: \tdef ty: AA | ('a \\ x)\n//│ ╙──       \t        ^^^^^^^^^^^^^\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Arrays.mls",
    "content": ":ShowRelativeLineNums\n:NoJS\n\nclass MyArray[A]: { size: int; set: (int, A) -> (); get: int -> A }\n//│ Defined class MyArray[=A]\n\ndummy = MyArray {\n    size = 0;\n    set = fun (i, a) -> ();\n    get = fun i -> error\n  }\n//│ dummy: MyArray['A] & {get: anything -> nothing, set: (anything, anything,) -> (), size: 0}\n\ndummy: MyArray[int]\n//│ res: MyArray[int]\n\ndef ty1A: MyArray[int]\ndef ty1B: MyArray[0 | 1]\n//│ ty1A: MyArray[int]\n//│ ty1B: MyArray[0 | 1]\n\n\ndef ty2A: MyArray['a]\n//│ ty2A: MyArray['a]\n\n:stats\nty2A = ty2A\n//│ MyArray['a]\n//│   <:  ty2A:\n//│ MyArray['a]\n//│ constrain calls  : 1\n//│ annoying  calls  : 0\n//│ subtyping calls  : 1\n\ndef ty2B: MyArray[MyArray['a]]\n//│ ty2B: MyArray[MyArray['a]]\n\n:stats\nty2B = ty2A\n//│ MyArray['a]\n//│   <:  ty2B:\n//│ MyArray[MyArray['a]]\n//│ constrain calls  : 26\n//│ annoying  calls  : 23\n//│ subtyping calls  : 63\n\n\n\ndef ty3A: MyArray['a] as 'a\n//│ ty3A: 'a\n//│   where\n//│     'a := MyArray['a]\n\n:stats\nty3A = ty3A\n//│ 'a\n//│   where\n//│     'a := MyArray['a]\n//│   <:  ty3A:\n//│ 'a\n//│   where\n//│     'a := MyArray['a]\n//│ constrain calls  : 1\n//│ annoying  calls  : 0\n//│ subtyping calls  : 1\n\ndef ty3B: MyArray[MyArray['a]] as 'a\n//│ ty3B: 'a\n//│   where\n//│     'a := MyArray[MyArray['a]]\n\n:stats\nty3B = ty3A\n//│ 'a\n//│   where\n//│     'a := MyArray['a]\n//│   <:  ty3B:\n//│ 'a\n//│   where\n//│     'a := MyArray[MyArray['a]]\n//│ constrain calls  : 78\n//│ annoying  calls  : 23\n//│ subtyping calls  : 199\n\n:stats\nty3A = ty3B\n//│ 'a\n//│   where\n//│     'a := MyArray[MyArray['a]]\n//│   <:  ty3A:\n//│ 'a\n//│   where\n//│     'a := MyArray['a]\n//│ constrain calls  : 78\n//│ annoying  calls  : 23\n//│ subtyping calls  : 199\n\ndef ty4B: MyArray[MyArray[MyArray['a]]] as 'a\n//│ ty4B: 'a\n//│   where\n//│     'a := MyArray[MyArray[MyArray['a]]]\n\n:stats\nty4B = ty4B\n//│ 'a\n//│   where\n//│     'a := MyArray[MyArray[MyArray['a]]]\n//│   <:  ty4B:\n//│ 'a\n//│   where\n//│     'a := MyArray[MyArray[MyArray['a]]]\n//│ constrain calls  : 1\n//│ annoying  calls  : 0\n//│ subtyping calls  : 1\n\n\n\n//===//===//===// ERRORS //===//===//===//\n\n\n:e\n:stats\nty1A = ty1B\n//│ MyArray[0 | 1]\n//│   <:  ty1A:\n//│ MyArray[int]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \tty1A = ty1B\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── type `int` does not match type `0 | 1`\n//│ ║  l.17: \tdef ty1A: MyArray[int]\n//│ ║        \t                  ^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.18: \tdef ty1B: MyArray[0 | 1]\n//│ ╙──      \t                  ^^^^^\n//│ constrain calls  : 5\n//│ annoying  calls  : 5\n//│ subtyping calls  : 69\n\n:e\n:stats\nty1B = ty1A\n//│ MyArray[int]\n//│   <:  ty1B:\n//│ MyArray[0 | 1]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \tty1B = ty1A\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── type `int` does not match type `0 | 1`\n//│ ║  l.17: \tdef ty1A: MyArray[int]\n//│ ║        \t                  ^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.18: \tdef ty1B: MyArray[0 | 1]\n//│ ╙──      \t                  ^^^^^\n//│ constrain calls  : 5\n//│ annoying  calls  : 5\n//│ subtyping calls  : 59\n\n\n:e\n:stats\nty2A = ty2B\n//│ MyArray[MyArray['a]]\n//│   <:  ty2A:\n//│ MyArray['a]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \tty2A = ty2B\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `MyArray`\n//│ ║  l.23: \tdef ty2A: MyArray['a]\n//│ ║        \t                  ^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.35: \tdef ty2B: MyArray[MyArray['a]]\n//│ ╙──      \t                  ^^^^^^^^^^^\n//│ constrain calls  : 18\n//│ annoying  calls  : 29\n//│ subtyping calls  : 51\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Arrays2.mls",
    "content": ":ShowRelativeLineNums\n\nclass MyArray[A]: { size: int }\n  method Set: (int, A) -> ()\n  method Get: int -> A \n//│ Defined class MyArray[=A]\n//│ Declared MyArray.Set: MyArray['A] -> (int, 'A,) -> ()\n//│ Declared MyArray.Get: MyArray['A] -> int -> 'A\n\n\n\nclass Dummy[A]: MyArray[A] & { size: 0 }\n  method Set (i, a) = ()\n  method Get i = error\n//│ Defined class Dummy[=A]\n//│ Defined Dummy.Set: Dummy['A] -> (anything, anything,) -> ()\n//│ Defined Dummy.Get: Dummy['A] -> anything -> nothing\n\n\ndummy = Dummy { size = 0 }\n//│ dummy: Dummy['A]\n//│      = Dummy { size: 0 }\n\ndummy: MyArray[int]\n//│ res: MyArray[int]\n//│    = Dummy { size: 0 }\n\n\ndef ty4B: MyArray[MyArray[MyArray['a]]] as 'a\n//│ ty4B: 'a\n//│   where\n//│     'a := MyArray[MyArray[MyArray['a]]]\n//│     = <missing implementation>\n\n\n\n\n:e\nMyArray{ size = 0 }\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.+1: \tMyArray{ size = 0 }\n//│ ║        \t^^^^^^^\n//│ ╟── Note that class MyArray is abstract:\n//│ ║  l.3: \tclass MyArray[A]: { size: int }\n//│ ║       \t      ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Hint: method Set is abstract\n//│ ║  l.4: \t  method Set: (int, A) -> ()\n//│ ║       \t         ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Hint: method Get is abstract\n//│ ║  l.5: \t  method Get: int -> A \n//│ ╙──     \t         ^^^^^^^^^^^^^\n//│ res: error\n//│    = MyArray { size: 0 }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Ascribe.mls",
    "content": "\n\"hello\": 'a\n//│ res: \"hello\"\n//│    = 'hello'\n\n:e\n\"hello\": 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.7: \t\"hello\": 'a -> 'a\n//│ ║       \t^^^^^^^\n//│ ╟── string literal of type `\"hello\"` is not a function\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.7: \t\"hello\": 'a -> 'a\n//│ ╙──     \t         ^^^^^^^^\n//│ res: 'a -> (error | 'a)\n//│    = 'hello'\n\n{ name = \"Bob\" } : { name: 'a }\n//│ res: {name: \"Bob\"}\n//│    = { name: 'Bob' }\n\ndef foo(n: 'a) = add n 1\n//│ foo: int -> int\n//│    = [Function: foo]\ndef foo(n: 'a) = add n 1: 'a\n//│ foo: int -> int\n//│    = [Function: foo1]\n\n\nclass Foo[A]: { field: A }\n//│ Defined class Foo[+A]\n\ndef foo(f: Foo['a]) = f.field\n//│ foo: Foo['field] -> 'field\n//│    = [Function: foo2]\n\n\n(succ 1): int\n//│ res: int\n//│    = 2\n\n\ndef foo({ a; b }: { a: int; b: string}) = { b; a }\n//│ foo: {a: int, b: string} -> {a: int, b: string}\n//│    = [Function: foo3]\n\n:e\ndef foo({ a = \"hey\" }: { a: string}) = 0\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.48: \tdef foo({ a = \"hey\" }: { a: string}) = 0\n//│ ║        \t        ^^^^^^^^^^^^^\n//│ ╟── type `string` does not match type `\"hey\"`\n//│ ║  l.48: \tdef foo({ a = \"hey\" }: { a: string}) = 0\n//│ ║        \t                            ^^^^^^\n//│ ╟── Note: constraint arises from string literal:\n//│ ║  l.48: \tdef foo({ a = \"hey\" }: { a: string}) = 0\n//│ ╙──      \t              ^^^^^\n//│ foo: {a: string} -> 0\n//│    = [Function: foo4]\n\n:e\ndef foo({ a; b }: { a: int }) = b\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.62: \tdef foo({ a; b }: { a: int }) = b\n//│ ║        \t        ^^^^^^^^\n//│ ╟── type `{a: int}` does not have field 'b'\n//│ ║  l.62: \tdef foo({ a; b }: { a: int }) = b\n//│ ╙──      \t                  ^^^^^^^^^^\n//│ foo: {a: int} -> nothing\n//│    = [Function: foo5]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Baber.mls",
    "content": "\nclass Foo[A]: { x: A }\nclass Bar\n//│ Defined class Foo[+A]\n//│ Defined class Bar\n\ndef f e = case e of\n  Foo -> e.y,\n  Foo -> e.z,\n  _ -> e\n//│ f: (Foo[?] & {y: 'y} | 'y & ~#Foo) -> 'y\n//│  = [Function: f]\n\n:ns\nf\n//│ res: forall 'a 'b 'y 'c 'z 'd. 'a -> ('y | 'z | 'd)\n//│   where\n//│     'a <: #Foo & 'b | (#Foo & 'c | 'd & ~#Foo) & ~#Foo\n//│     'c <: {z: 'z}\n//│     'b <: {y: 'y}\n//│    = [Function: f]\n\nclass Foo2: Foo[int] & { y: int }\n//│ Defined class Foo2\n\nf (Foo2{x=1;y=2})\n//│ res: 2\n//│    = 2\n\n// #Foo\n\ndef f e = case e of\n  Foo2 -> e.y,\n  Foo -> e.z,\n//│ f: (Foo[?] & {z: 'y} & ~#Foo2 | (Foo2\\x with {y: 'y})) -> 'y\n//│  = [Function: f1]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadAlias.mls",
    "content": "\n:e\ntype A = A\n//│ ╔══[ERROR] illegal cycle involving type A\n//│ ║  l.3: \ttype A = A\n//│ ╙──     \t     ^^^^^\n\n:e\n\"oops\": A\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.9: \t\"oops\": A\n//│ ╙──     \t        ^\n//│ res: error\n//│    = 'oops'\n\nres: \"oops\"\n//│ res: \"oops\"\n//│    = 'oops'\n\n:e\nadd res 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.21: \tadd res 1\n//│ ║        \t^^^^^^^\n//│ ╟── type `\"oops\"` is not an instance of type `int`\n//│ ║  l.16: \tres: \"oops\"\n//│ ║        \t     ^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.21: \tadd res 1\n//│ ╙──      \t    ^^^\n//│ res: error | int\n//│    = 'oops1'\n\n:e\ntype B = Oops\n//│ ╔══[ERROR] type identifier not found: Oops\n//│ ║  l.35: \ttype B = Oops\n//│ ╙──      \t         ^^^^\n//│ Defined type alias B\n\n42: B\n//│ res: B\n//│    = 42\n\n:e\ntype NonReg[A] = { x: NonReg[NonReg[A]] }\n//│ ╔══[ERROR] Type definition is not regular: it occurs within itself as NonReg[NonReg['A]], but is defined as NonReg['A]\n//│ ║  l.46: \ttype NonReg[A] = { x: NonReg[NonReg[A]] }\n//│ ╙──      \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:e\ntype B = NonReg[A]\n//│ ╔══[ERROR] Type 'B' is already defined.\n//│ ║  l.52: \ttype B = NonReg[A]\n//│ ╙──      \t     ^\n\n:e\ntype NonReg[A] = { x: NonReg[int] }\n//│ ╔══[ERROR] Type definition is not regular: it occurs within itself as NonReg[int], but is defined as NonReg['A]\n//│ ║  l.58: \ttype NonReg[A] = { x: NonReg[int] }\n//│ ╙──      \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:e\n42: NonReg[int]\n//│ ╔══[ERROR] type identifier not found: NonReg\n//│ ║  l.64: \t42: NonReg[int]\n//│ ╙──      \t    ^^^^^^^^^^^\n//│ res: error\n//│    = 42\n\n:e\n:w\ntype NonReg[A] = { x: NonReg[int] }\ntype RefToNongReg[A] = { x: NonReg[A] }\n//│ ╔══[ERROR] Type definition is not regular: it occurs within itself as NonReg[int], but is defined as NonReg['A]\n//│ ║  l.73: \ttype NonReg[A] = { x: NonReg[int] }\n//│ ╙──      \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ Defined type alias RefToNongReg[±A]\n//│ ╔══[WARNING] Type definition RefToNongReg has bivariant type parameters:\n//│ ║  l.74: \ttype RefToNongReg[A] = { x: NonReg[A] }\n//│ ║        \t     ^^^^^^^^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.74: \ttype RefToNongReg[A] = { x: NonReg[A] }\n//│ ╙──      \t                  ^\n\n\n:w\ntype Reg[A] = Reg[A] -> Reg[A]\n//│ Defined type alias Reg[±A]\n//│ ╔══[WARNING] Type definition Reg has bivariant type parameters:\n//│ ║  l.88: \ttype Reg[A] = Reg[A] -> Reg[A]\n//│ ║        \t     ^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.88: \ttype Reg[A] = Reg[A] -> Reg[A]\n//│ ╙──      \t         ^\n\n\ntype Id[A] = A\n//│ Defined type alias Id[+A]\n\n// Our regularity check for now is very syntactic:\n:e\ntype FalseNeg[A] = { x: FalseNeg[Id[A]] }\n//│ ╔══[ERROR] Type definition is not regular: it occurs within itself as FalseNeg[Id['A]], but is defined as FalseNeg['A]\n//│ ║  l.103: \ttype FalseNeg[A] = { x: FalseNeg[Id[A]] }\n//│ ╙──       \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n\n:e\n42: Id\n//│ ╔══[ERROR] Type Id takes parameters\n//│ ║  l.110: \t42: Id\n//│ ╙──       \t    ^^\n//│ res: error\n//│    = 42\n\n42: Id[int]\n//│ res: Id[int]\n//│    = 42\n\n\n\ntype Bot = 'a\n//│ Defined type alias Bot\n\n:e\n42 : Bot\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.127: \t42 : Bot\n//│ ║         \t^^\n//│ ╟── integer literal of type `42` does not match type `'a`\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.123: \ttype Bot = 'a\n//│ ║         \t           ^^\n//│ ╟── from type reference:\n//│ ║  l.127: \t42 : Bot\n//│ ╙──       \t     ^^^\n//│ res: Bot\n//│    = 42\n\n:re\nerror: Bot\n//│ res: Bot\n//│ Runtime error:\n//│   Error: an error was thrown\n\ntype PolyId = 'a -> 'a\n//│ Defined type alias PolyId\n\nid : PolyId\n//│ res: PolyId\n//│    = [Function: id]\n\n:e\nsucc : PolyId\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.155: \tsucc : PolyId\n//│ ║         \t^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.147: \ttype PolyId = 'a -> 'a\n//│ ╙──       \t              ^^\n//│ res: PolyId\n//│    = [Function: succ]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadClasses.mls",
    "content": ":AllowTypeErrors\n\n\nclass Box[T]: { inner: T }\n  method Get = this.inner\n  method Get2 = this.x\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.6: \t  method Get2 = this.x\n//│ ║       \t                ^^^^^^\n//│ ╟── reference of type `Box[T] & this` does not have field 'x'\n//│ ║  l.6: \t  method Get2 = this.x\n//│ ╙──     \t                ^^^^\n//│ Defined class Box[+T]\n//│ Defined Box.Get: Box['T] -> 'T\n//│ Defined Box.Get2: Box[?] -> error\n\n\nclass Box2[T]: { inner: T }\n  method Test = this.inner + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.19: \t  method Test = this.inner + 1\n//│ ║        \t                ^^^^^^^^^^^^\n//│ ╟── field selection of type `T` is not an instance of type `int`\n//│ ║  l.19: \t  method Test = this.inner + 1\n//│ ║        \t                ^^^^^^^^^^\n//│ ╟── Note: class type parameter T is defined at:\n//│ ║  l.18: \tclass Box2[T]: { inner: T }\n//│ ╙──      \t           ^\n//│ Defined class Box2[+T]\n//│ Defined Box2.Test: Box2[?] -> (error | int)\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadInherit.mls",
    "content": "\nclass Parent1: { name: string }\n//│ Defined class Parent1\n\nclass Parent2: { name: int }\n//│ Defined class Parent2\n\n:e\n:ge\nclass Child: Parent1 & Parent2\n//│ ╔══[ERROR] class Child cannot inherit from class Parent2 as it already inherits from class Parent1\n//│ ║  l.10: \tclass Child: Parent1 & Parent2\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ Code generation encountered an error:\n//│   cannot have 2 base classes: Parent1, Parent2\n\ntype Child = Parent1 & Parent2\ndef Child: (Parent1 & Parent2) -> Child\n//│ Defined type alias Child\n//│ Child: nothing -> Child\n//│      = <missing implementation>\n\ndef f(x:Child) = x.name\n//│ f: Child -> nothing\n//│  = [Function: f]\n\ndef f(x:Child) = x: nothing\n//│ f: Child -> nothing\n//│  = [Function: f1]\n\n:pe\ndef c = Child(Parent1{name=\"A\"} with Parent2{name=\"B\"})\n//│ /!\\ Parse error: Expected \")\":1:33, found \"with Paren\" at l.32:33: def c = Child(Parent1{name=\"A\"} with Parent2{name=\"B\"})\n\n:e\ndef c = Child(Parent1{name=\"A\"})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.36: \tdef c = Child(Parent1{name=\"A\"})\n//│ ║        \t        ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Parent1 & {name: ?name}` is not an instance of type `Parent2`\n//│ ║  l.36: \tdef c = Child(Parent1{name=\"A\"})\n//│ ║        \t              ^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.18: \tdef Child: (Parent1 & Parent2) -> Child\n//│ ║        \t                      ^^^^^^^\n//│ ╟── from intersection type:\n//│ ║  l.18: \tdef Child: (Parent1 & Parent2) -> Child\n//│ ╙──      \t           ^^^^^^^^^^^^^^^^^^^\n//│ c: error | Child\n//│  = <no result>\n//│    Child is not implemented\n\n:e\n:ge\ntype Sly1 = Parent2\nclass Child2: Parent1 & Sly1\n//│ ╔══[ERROR] cannot inherit from a type alias\n//│ ║  l.56: \tclass Child2: Parent1 & Sly1\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^\n//│ Defined type alias Sly1\n//│ Code generation encountered an error:\n//│   cannot inherit from type alias Sly1\n\n:e\n:ge\ntype Sly2[A] = A\nclass Child2: Sly2[Parent1] & Parent2\n//│ ╔══[ERROR] cannot inherit from a type alias\n//│ ║  l.67: \tclass Child2: Sly2[Parent1] & Parent2\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ Defined type alias Sly2[+A]\n//│ Code generation encountered an error:\n//│   cannot inherit from type alias Sly2\n\n:e\n:ge\nclass Crazy[A]: A & { name: A }\n//│ ╔══[ERROR] cannot inherit from a type variable\n//│ ║  l.77: \tclass Crazy[A]: A & { name: A }\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ Code generation encountered an error:\n//│   undeclared type name A when resolving base classes\n\nclass Crazy[A]: { name: A }\ndef Crazy: 'a -> (Crazy['a] & 'a)\n//│ Defined class Crazy[+A]\n//│ Crazy: 'a -> (Crazy['a] & 'a)\n//│      = <missing implementation>\n\nCrazy\n//│ res: 'a -> (Crazy['a] & 'a)\n//│    = <no result>\n//│      Crazy is not implemented\n\ndef c = Crazy({ name = \"Bob\"; age = 42 })\n//│ c: Crazy[{age: 42, name: \"Bob\"}] with {age: 42, name: \"Bob\"}\n//│  = <no result>\n//│    Crazy is not implemented\n\n:e\nc: nothing\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.101: \tc: nothing\n//│ ║         \t^\n//│ ╟── record literal of type `{age: 42, name: \"Bob\"}` does not match type `~Crazy['a]`\n//│ ║  l.95: \tdef c = Crazy({ name = \"Bob\"; age = 42 })\n//│ ║        \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `~Crazy['a0]`\n//│ ║  l.101: \tc: nothing\n//│ ║         \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.101: \tc: nothing\n//│ ╙──       \t   ^^^^^^^\n//│ res: nothing\n//│    = <no result>\n//│      c and Crazy are not implemented\n\ndef d = Crazy(Parent1{name = \"Bob\"})\n//│ d: nothing\n//│  = <no result>\n//│    Crazy is not implemented\n\nd: nothing\n//│ res: nothing\n//│    = <no result>\n//│      d and Crazy are not implemented\n\n\n:e\nclass Stupid: Parent1 | Parent2\n//│ ╔══[ERROR] cannot inherit from a type union\n//│ ║  l.130: \tclass Stupid: Parent1 | Parent2\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^^^\n:e\nclass Stupid: Parent1 -> Parent2\n//│ ╔══[ERROR] cannot inherit from a function type\n//│ ║  l.135: \tclass Stupid: Parent1 -> Parent2\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^\n:e\nclass Stupid: ~Parent1\n//│ ╔══[ERROR] cannot inherit from a type negation\n//│ ║  l.140: \tclass Stupid: ~Parent1\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^\n\n:e // TODO don't report several times\n:ge\nclass Cycle1: Cycle2\nclass Cycle2: Cycle1\ntype Stutter = Cycle1\n//│ ╔══[ERROR] illegal cycle involving type Cycle1\n//│ ║  l.147: \tclass Cycle1: Cycle2\n//│ ╙──       \t      ^^^^^^^^^^^^^^\n//│ ╔══[ERROR] illegal cycle involving type Cycle2\n//│ ║  l.148: \tclass Cycle2: Cycle1\n//│ ╙──       \t      ^^^^^^^^^^^^^^\n//│ ╔══[ERROR] illegal cycle involving type Cycle1\n//│ ║  l.149: \ttype Stutter = Cycle1\n//│ ╙──       \t     ^^^^^^^^^^^^^^^^\n//│ Code generation encountered an error:\n//│   cyclic inheritance detected\n\n:e\ndef c = Cycle1 error\nc: Cycle1\n//│ ╔══[ERROR] identifier not found: Cycle1\n//│ ║  l.163: \tdef c = Cycle1 error\n//│ ╙──       \t        ^^^^^^\n//│ c: error\n//│  = [Function: c1]\n//│ ╔══[ERROR] type identifier not found: Cycle1\n//│ ║  l.164: \tc: Cycle1\n//│ ╙──       \t   ^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   ReferenceError: Cycle1 is not defined\n\n\ntype N[A] = ~A\n//│ Defined type alias N[-A]\n\n:e\n:ge\nclass Cycle: N[Cycle]\n//│ ╔══[ERROR] cannot inherit from a type alias\n//│ ║  l.183: \tclass Cycle: N[Cycle]\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ Code generation encountered an error:\n//│   cannot inherit from type alias N\n\n\n\n:ng\n// TODO forbid\nclass D: int\n//│ Defined class D\n\n:ge\nadd (D{}) 2\n//│ res: int\n//│ Code generation encountered an error:\n//│   unresolved symbol D\n\n\n// TODO forbid\nclass E: 1\n//│ Defined class E\n\n:e\nE{}: 1\nE{}: int\nE{} + 1\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.209: \tE{}: 1\n//│ ║         \t^^^\n//│ ╟── application of type `E` does not match type `1`\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.209: \tE{}: 1\n//│ ║         \t     ^\n//│ ╟── Note: class E is defined at:\n//│ ║  l.205: \tclass E: 1\n//│ ╙──       \t      ^\n//│ res: 1\n//│    = E {}\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.210: \tE{}: int\n//│ ║         \t^^^\n//│ ╟── application of type `E` is not an instance of type `int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.210: \tE{}: int\n//│ ║         \t     ^^^\n//│ ╟── Note: class E is defined at:\n//│ ║  l.205: \tclass E: 1\n//│ ╙──       \t      ^\n//│ res: int\n//│    = E {}\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.211: \tE{} + 1\n//│ ║         \t^^^^^\n//│ ╟── application of type `E` is not an instance of type `int`\n//│ ║  l.211: \tE{} + 1\n//│ ║         \t^^^\n//│ ╟── Note: class E is defined at:\n//│ ║  l.205: \tclass E: 1\n//│ ╙──       \t      ^\n//│ res: error | int\n//│    = '[object Object]1'\n\n:e\n:ge\nclass F: nothing\nF{}\n//│ ╔══[ERROR] cannot inherit from a type alias\n//│ ║  l.250: \tclass F: nothing\n//│ ╙──       \t      ^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: F\n//│ ║  l.251: \tF{}\n//│ ╙──       \t^\n//│ res: error\n//│ Code generation encountered an error:\n//│   cannot inherit from type alias nothing\n\n\n:e\nclass String\nclass Bool\n//│ ╔══[ERROR] Type name 'String' is reserved.\n//│ ║  l.264: \tclass String\n//│ ╙──       \t      ^^^^^^\n//│ ╔══[ERROR] Type name 'Bool' is reserved.\n//│ ║  l.265: \tclass Bool\n//│ ╙──       \t      ^^^^\n//│ Defined class String\n//│ Defined class Bool\n\n:e\n\"1\" : String\ntrue : Bool\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.276: \t\"1\" : String\n//│ ║         \t^^^\n//│ ╟── string literal of type `\"1\"` is not an instance of type `String`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.276: \t\"1\" : String\n//│ ╙──       \t      ^^^^^^\n//│ res: String\n//│    = '1'\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.277: \ttrue : Bool\n//│ ║         \t^^^^\n//│ ╟── reference of type `true` is not an instance of type `Bool`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.277: \ttrue : Bool\n//│ ╙──       \t       ^^^^\n//│ res: Bool\n//│    = true\n\n\n:e\nclass Weird: {} | {}\n//│ ╔══[ERROR] cannot inherit from a type union\n//│ ║  l.299: \tclass Weird: {} | {}\n//│ ╙──       \t      ^^^^^^^^^^^^^^\n\n\n:e\n:ge\nclass A\ntype Id[T] = T\nclass B: Id[A]\n//│ ╔══[ERROR] cannot inherit from a type alias\n//│ ║  l.309: \tclass B: Id[A]\n//│ ╙──       \t      ^^^^^^^^\n//│ Defined class A\n//│ Defined type alias Id[+T]\n//│ Code generation encountered an error:\n//│   cannot inherit from type alias Id\n\n\n:e // TODO improve prov of the TV\nclass Class3A\nclass Class3B: Class3A & 'a\n//│ ╔══[ERROR] cannot inherit from a polymorphic type\n//│ ║  l.321: \tclass Class3B: Class3A & 'a\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^\n//│ Defined class Class3A\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadInherit2.mls",
    "content": "\n\n// ———\n\n\ntrait S0[A]\n  method Foo0: A -> A\ntrait T0[B]: S0[B]\n//│ Defined trait S0[=A]\n//│ Declared S0.Foo0: S0['A] -> 'A -> 'A\n//│ Defined trait T0[=B]\n\n:e\nclass A0: S0[int] & T0[string]\n(A0{}).Foo0\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ║        \t             ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ╙──      \t                       ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ║        \t                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ╙──      \t             ^^^\n//│ Defined class A0\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.15: \t(A0{}).Foo0\n//│ ║        \t ^^\n//│ ╟── Note that class A0 is abstract:\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Hint: method Foo0 is abstract\n//│ ║  l.14: \tclass A0: S0[int] & T0[string]\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: 'A -> 'A\n//│    = undefined\n\n:e\nclass A0_2: S0[int] & T0[string]\n  method Foo0 x = 1\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.48: \tclass A0_2: S0[int] & T0[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.48: \tclass A0_2: S0[int] & T0[string]\n//│ ║        \t               ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.48: \tclass A0_2: S0[int] & T0[string]\n//│ ╙──      \t                         ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.48: \tclass A0_2: S0[int] & T0[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.48: \tclass A0_2: S0[int] & T0[string]\n//│ ║        \t                         ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.48: \tclass A0_2: S0[int] & T0[string]\n//│ ╙──      \t               ^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.49: \t  method Foo0 x = 1\n//│ ║        \t         ^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `string`\n//│ ║  l.49: \t  method Foo0 x = 1\n//│ ║        \t                  ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.48: \tclass A0_2: S0[int] & T0[string]\n//│ ╙──      \t                         ^^^^^^\n//│ Defined class A0_2\n//│ Defined A0_2.Foo0: A0_2 -> anything -> 1\n\n(A0_2{}).Foo0\n//│ res: ('A & (int | string)) -> 'A\n//│    = [Function: Foo0]\n\n\n// ———\n\n\ntrait R1[A]\n  method Foo1: A -> A\n//│ Defined trait R1[=A]\n//│ Declared R1.Foo1: R1['A] -> 'A -> 'A\n\ntrait S1: R1[int]\n  method Foo1 x = 1\ntrait T1: R1[string]\n  method Foo1 x = \"a\"\n//│ Defined trait S1\n//│ Defined S1.Foo1: S1 -> anything -> 1\n//│ Defined trait T1\n//│ Defined T1.Foo1: T1 -> anything -> \"a\"\n\n:e\nclass A1: S1 & T1\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.103: \tclass A1: S1 & T1\n//│ ║         \t      ^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.93: \ttrait S1: R1[int]\n//│ ║        \t             ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.95: \ttrait T1: R1[string]\n//│ ╙──      \t             ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.103: \tclass A1: S1 & T1\n//│ ║         \t      ^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.95: \ttrait T1: R1[string]\n//│ ║        \t             ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.93: \ttrait S1: R1[int]\n//│ ╙──      \t             ^^^\n//│ ╔══[ERROR] An overriding method definition must be given when inheriting from multiple method definitions\n//│ ║  l.103: \tclass A1: S1 & T1\n//│ ║         \t      ^^\n//│ ╟── Definitions of method Foo1 inherited from:\n//│ ╟── • S1\n//│ ║  l.94: \t  method Foo1 x = 1\n//│ ║        \t         ^^^^^^^^^^\n//│ ╟── • T1\n//│ ║  l.96: \t  method Foo1 x = \"a\"\n//│ ╙──      \t         ^^^^^^^^^^^^\n//│ Defined class A1\n\na1 = A1{}\n//│ a1: A1\n//│   = A1 { Foo1: [Function (anonymous)] }\n\na1.Foo1\n//│ res: ('A & (int | string)) -> 'A\n//│    = [Function (anonymous)]\n\na1: S1\na1: R1[int]\na1: R1[string]\na1: R1['_]\n//│ res: S1\n//│    = A1 { Foo1: [Function (anonymous)] }\n//│ res: R1[int]\n//│    = A1 { Foo1: [Function (anonymous)] }\n//│ res: R1[string]\n//│    = A1 { Foo1: [Function (anonymous)] }\n//│ res: R1['_]\n//│   where\n//│     '_ <: int | string\n//│    = A1 { Foo1: [Function (anonymous)] }\n\n:ns\na1: R1['_]\n//│ res: R1['_]\n//│   where\n//│     '_ <: int | string\n//│    = A1 { Foo1: [Function (anonymous)] }\n\n\n:e\n:js\nclass A1_2: S1 & T1\n  method Foo1 = error\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.167: \tclass A1_2: S1 & T1\n//│ ║         \t      ^^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.93: \ttrait S1: R1[int]\n//│ ║        \t             ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.95: \ttrait T1: R1[string]\n//│ ╙──      \t             ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.167: \tclass A1_2: S1 & T1\n//│ ║         \t      ^^^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.95: \ttrait T1: R1[string]\n//│ ║        \t             ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.93: \ttrait S1: R1[int]\n//│ ╙──      \t             ^^^\n//│ Defined class A1_2\n//│ Defined A1_2.Foo1: A1_2 -> nothing\n//│ // Prelude\n//│ function error() {\n//│   throw new Error(\"an error was thrown\");\n//│ }\n//│ class A1_2 {\n//│   constructor(fields) {\n//│     S1.implement(this);\n//│     T1.implement(this);\n//│   }\n//│   get Foo1() {\n//│     return error();\n//│   }\n//│ }\n//│ // End of generated code\n\n:re\n(A1_2{}).Foo1\n//│ res: ('A & (int | string)) -> 'A\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\nf = 0\n//│ f: 0\n//│  = 0\n\nf' = 1\n//│ f': 1\n//│   = 1\n\nf'\n//│ res: 1\n//│    = 1\n\n\n\nclass C0[A]: S0[A]\n  method Foo0 = id\n//│ Defined class C0[=A]\n//│ Defined C0.Foo0: C0['A] -> 'a -> 'a\n\ndef s0: S0['a] -> S0['a]\n//│ s0: S0['a] -> S0['a]\n//│   = <missing implementation>\n\ns0 (C0{})\n//│ res: S0['a]\n//│    = <no result>\n//│      s0 is not implemented\n\ndef s0: S0[?] -> S0[?]\n//│ s0: S0[?] -> S0[?]\n//│   = <missing implementation>\n\n:e\ns0 (C0{})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.244: \ts0 (C0{})\n//│ ║         \t^^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.239: \tdef s0: S0[?] -> S0[?]\n//│ ╙──       \t           ^\n//│ res: error | S0[?]\n//│    = <no result>\n//│      s0 is not implemented\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadInherit2Co.mls",
    "content": "\n\n// ———\n\n\n:e\ntrait S00[A]\n  method Foo00: A\ntrait T00[B]: S00[B]\nclass A00: S00[int] & T00[string]\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.10: \tclass A00: S00[int] & T00[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.10: \tclass A00: S00[int] & T00[string]\n//│ ║        \t               ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.10: \tclass A00: S00[int] & T00[string]\n//│ ╙──      \t                          ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type definition:\n//│ ║  l.10: \tclass A00: S00[int] & T00[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.10: \tclass A00: S00[int] & T00[string]\n//│ ║        \t                          ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.10: \tclass A00: S00[int] & T00[string]\n//│ ╙──      \t               ^^^\n//│ Defined trait S00[+A]\n//│ Declared S00.Foo00: S00['A] -> 'A\n//│ Defined trait T00[+B]\n//│ Defined class A00\n\n// Note: the definition above becomes valid if we split it into two definition groups\n//    so that the variance analysis has a chance of running in between...\n\ntrait S0[A]\n  method Foo0: A\ntrait T0[B]: S0[B]\n//│ Defined trait S0[+A]\n//│ Declared S0.Foo0: S0['A] -> 'A\n//│ Defined trait T0[+B]\n\nclass A0: S0[int] & T0[string]\n//│ Defined class A0\n\n:e\n(A0{}).Foo0\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.48: \t(A0{}).Foo0\n//│ ║        \t ^^\n//│ ╟── Note that class A0 is abstract:\n//│ ║  l.44: \tclass A0: S0[int] & T0[string]\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Hint: method Foo0 is abstract\n//│ ║  l.44: \tclass A0: S0[int] & T0[string]\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: nothing\n//│    = undefined\n\n:e\nclass A0_2: S0[int] & T0[string]\n  method Foo0 = 1\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.63: \t  method Foo0 = 1\n//│ ║        \t         ^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `string`\n//│ ║  l.63: \t  method Foo0 = 1\n//│ ║        \t                ^\n//│ ╟── but it flows into method definition with expected type `string`\n//│ ║  l.63: \t  method Foo0 = 1\n//│ ║        \t         ^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.62: \tclass A0_2: S0[int] & T0[string]\n//│ ║        \t                         ^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.38: \t  method Foo0: A\n//│ ╙──      \t         ^^^^^^^\n//│ Defined class A0_2\n//│ Defined A0_2.Foo0: A0_2 -> 1\n\n(A0_2{}).Foo0\n//│ res: nothing\n//│    = 1\n\n\n// ———\n\n\ntrait R1[A]\n  method Foo1: A\n//│ Defined trait R1[+A]\n//│ Declared R1.Foo1: R1['A] -> 'A\n\ntrait S1: R1[int]\n  method Foo1 = 1\ntrait T1: R1[string]\n  method Foo1 = \"a\"\n//│ Defined trait S1\n//│ Defined S1.Foo1: S1 -> 1\n//│ Defined trait T1\n//│ Defined T1.Foo1: T1 -> \"a\"\n\n:e\nclass A1: S1 & T1\n//│ ╔══[ERROR] An overriding method definition must be given when inheriting from multiple method definitions\n//│ ║  l.105: \tclass A1: S1 & T1\n//│ ║         \t      ^^\n//│ ╟── Definitions of method Foo1 inherited from:\n//│ ╟── • S1\n//│ ║  l.96: \t  method Foo1 = 1\n//│ ║        \t         ^^^^^^^^\n//│ ╟── • T1\n//│ ║  l.98: \t  method Foo1 = \"a\"\n//│ ╙──      \t         ^^^^^^^^^^\n//│ Defined class A1\n\na1 = A1{}\n//│ a1: A1\n//│   = A1 {}\n\na1.Foo1\n//│ res: nothing\n//│    = 1\n\na1: S1\na1: R1[int]\na1: R1[string]\na1: R1['_]\n//│ res: S1\n//│    = A1 {}\n//│ res: R1[int]\n//│    = A1 {}\n//│ res: R1[string]\n//│    = A1 {}\n//│ res: R1[nothing]\n//│    = A1 {}\n\n:ns\na1: R1['_]\n//│ res: R1['_]\n//│    = A1 {}\n\n\n:js\nclass A1_2: S1 & T1\n  method Foo1 = error\n//│ Defined class A1_2\n//│ Defined A1_2.Foo1: A1_2 -> nothing\n//│ // Prelude\n//│ function error() {\n//│   throw new Error(\"an error was thrown\");\n//│ }\n//│ class A1_2 {\n//│   constructor(fields) {\n//│     S1.implement(this);\n//│     T1.implement(this);\n//│   }\n//│   get Foo1() {\n//│     return error();\n//│   }\n//│ }\n//│ // End of generated code\n\n:re\n(A1_2{}).Foo1\n//│ res: nothing\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\nf = 0\n//│ f: 0\n//│  = 0\n\nf' = 1\n//│ f': 1\n//│   = 1\n\nf'\n//│ res: 1\n//│    = 1\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadMethods.mls",
    "content": ":AllowTypeErrors\n\nclass Foo[A]: { x: A }\n    method Map[B]: (A -> B) -> A\nclass Bar[A]: Foo[A]\n    method Map[B]: B -> A\n    rec method Map f = f Map (fun x -> Map)\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.7: \t    rec method Map f = f Map (fun x -> Map)\n//│ ║       \t               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `B` is not a function\n//│ ║  l.6: \t    method Map[B]: B -> A\n//│ ║       \t               ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.7: \t    rec method Map f = f Map (fun x -> Map)\n//│ ║       \t                       ^^^^^\n//│ ╟── from reference:\n//│ ║  l.7: \t    rec method Map f = f Map (fun x -> Map)\n//│ ╙──     \t                       ^\n//│ Defined class Foo[+A]\n//│ Declared Foo.Map: Foo['A] -> ('A -> anything) -> 'A\n//│ Defined class Bar[+A]\n//│ Declared Bar.Map: Bar['A] -> anything -> 'A\n//│ Defined Bar.Map: Bar[?] -> 'Map\n//│   where\n//│     'Map :> ('Map -> (anything -> 'Map) -> 'a) -> 'a\n\nFoo.Map\nBar.Map\n//│ res: Foo['A] -> ('A -> anything) -> 'A\n//│ res: Bar['A] -> anything -> 'A\n\n\n\n\nclass bar[A, B]: Foo[A] & { Y: B; z: int }\n    method identity z = z\n    method identity z = z\n//│ ╔══[ERROR] Type names must start with a capital letter\n//│ ║  l.36: \tclass bar[A, B]: Foo[A] & { Y: B; z: int }\n//│ ╙──      \t      ^^^\n//│ ╔══[ERROR] Type 'Bar' is already defined.\n//│ ║  l.36: \tclass bar[A, B]: Foo[A] & { Y: B; z: int }\n//│ ╙──      \t      ^^^\n\n\n\n\nclass ImplicitCall[A]: { x: A }\n    method Fun = this.x\n//│ Defined class ImplicitCall[+A]\n//│ Defined ImplicitCall.Fun: ImplicitCall['A] -> 'A\n\ni = ImplicitCall { x = \"stonks\" }\ni.Fun\n//│ i: ImplicitCall[\"stonks\"]\n//│ res: \"stonks\"\n\nclass NoMoreImplicitCall\n    method Fun = \"not stonks\"\n//│ Defined class NoMoreImplicitCall\n//│ Defined NoMoreImplicitCall.Fun: NoMoreImplicitCall -> \"not stonks\"\n\ni.Fun\n//│ ╔══[ERROR] Implicit call to method Fun is forbidden because it is ambiguous.\n//│ ║  l.64: \ti.Fun\n//│ ║        \t^^^^^\n//│ ╟── Unrelated methods named Fun are defined by:\n//│ ╟── • class ImplicitCall\n//│ ║  l.49: \tclass ImplicitCall[A]: { x: A }\n//│ ║        \t      ^^^^^^^^^^^^\n//│ ╟── • class NoMoreImplicitCall\n//│ ║  l.59: \tclass NoMoreImplicitCall\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^\n//│ res: error\n\n\n\n\ndef this = fun x -> fun y -> add x y\nthis 42 42\n//│ this: int -> int -> int\n//│ res: int\n\nclass BadThis: { x: int; y: int }\n    method Sum = this this.x this.y\n    method Funny = this 42 42\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.86: \t    method Sum = this this.x this.y\n//│ ║        \t                 ^^^^^^^^^^^\n//│ ╟── reference of type `BadThis & this` is not a function\n//│ ║  l.86: \t    method Sum = this this.x this.y\n//│ ╙──      \t                 ^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.87: \t    method Funny = this 42 42\n//│ ║        \t                   ^^^^^^^\n//│ ╟── reference of type `BadThis & this` is not a function\n//│ ║  l.87: \t    method Funny = this 42 42\n//│ ╙──      \t                   ^^^^\n//│ Defined class BadThis\n//│ Defined BadThis.Sum: BadThis -> error\n//│ Defined BadThis.Funny: BadThis -> error\n\n\n\n\nclass BadSelf[A]: { x: A }\n    method F = this.x 42\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.108: \t    method F = this.x 42\n//│ ║         \t               ^^^^^^^^^\n//│ ╟── field selection of type `A` is not a function\n//│ ║  l.108: \t    method F = this.x 42\n//│ ║         \t               ^^^^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.107: \tclass BadSelf[A]: { x: A }\n//│ ╙──       \t              ^\n//│ Defined class BadSelf[+A]\n//│ Defined BadSelf.F: BadSelf[?] -> error\n\nc = BadSelf { x = fun x -> x }\nc.F\n//│ c: BadSelf[forall 'a. 'a -> 'a]\n//│ res: error\n\n\n\n\nclass Simple2[A]: { a: A }\n    method Get: A\n//│ Defined class Simple2[+A]\n//│ Declared Simple2.Get: Simple2['A] -> 'A\n\nclass Simple3[A, B]: Simple2[A]\n    method Get: B\n//│ ╔══[ERROR] Type mismatch in method declaration:\n//│ ║  l.135: \t    method Get: B\n//│ ║         \t           ^^^^^^\n//│ ╟── type `B` does not match type `A`\n//│ ║  l.134: \tclass Simple3[A, B]: Simple2[A]\n//│ ║         \t                 ^\n//│ ╟── Note: constraint arises from class type parameter:\n//│ ║  l.134: \tclass Simple3[A, B]: Simple2[A]\n//│ ╙──       \t              ^\n//│ Defined class Simple3[+A, +B]\n//│ Declared Simple3.Get: Simple3[?, 'B] -> 'B\n\n\n\n\nclass AbstractPair[A, B]: { x: A; y: B }\n    method Test: (A -> B -> bool) -> bool\n    method Map[C, D]: (A -> C) -> (B -> D) -> AbstractPair[C, D]\n//│ Defined class AbstractPair[+A, +B]\n//│ Declared AbstractPair.Test: AbstractPair['A, 'B] -> ('A -> 'B -> bool) -> bool\n//│ Declared AbstractPair.Map: AbstractPair['A, 'B] -> ('A -> 'C) -> ('B -> 'D) -> AbstractPair['C, 'D]\n\nclass BadPair[A, B]: AbstractPair[A, B]\n    method Test f = f this.x this.x\n    method Map fx fy = BadPair { x = fx this.x; y = fx this.x }\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.159: \t    method Test f = f this.x this.x\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── field selection of type `A` does not match type `B`\n//│ ║  l.159: \t    method Test f = f this.x this.x\n//│ ║         \t                             ^^^^^^\n//│ ╟── Note: constraint arises from class type parameter:\n//│ ║  l.158: \tclass BadPair[A, B]: AbstractPair[A, B]\n//│ ║         \t                 ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.158: \tclass BadPair[A, B]: AbstractPair[A, B]\n//│ ╙──       \t              ^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.160: \t    method Map fx fy = BadPair { x = fx this.x; y = fx this.x }\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `C` does not match type `D`\n//│ ║  l.160: \t    method Map fx fy = BadPair { x = fx this.x; y = fx this.x }\n//│ ║         \t                                                    ^^^^^^^^^\n//│ ╟── Note: constraint arises from method type parameter:\n//│ ║  l.153: \t    method Map[C, D]: (A -> C) -> (B -> D) -> AbstractPair[C, D]\n//│ ║         \t                  ^\n//│ ╟── Note: method type parameter C is defined at:\n//│ ║  l.153: \t    method Map[C, D]: (A -> C) -> (B -> D) -> AbstractPair[C, D]\n//│ ╙──       \t               ^\n//│ Defined class BadPair[+A, +B]\n//│ Defined BadPair.Test: BadPair['A, ?] -> ('A -> 'A -> 'a) -> 'a\n//│ Defined BadPair.Map: BadPair['A, ?] -> ('A -> 'x) -> anything -> BadPair['x, 'x]\n\nbp = BadPair { x = 42; y = true }\nbp.(BadPair.Test) (fun x -> fun y -> if (y) then x else y)\n//│ bp: BadPair[42, true]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.190: \tbp.(BadPair.Test) (fun x -> fun y -> if (y) then x else y)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `42` is not an instance of type `bool`\n//│ ║  l.189: \tbp = BadPair { x = 42; y = true }\n//│ ║         \t                   ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.190: \tbp.(BadPair.Test) (fun x -> fun y -> if (y) then x else y)\n//│ ╙──       \t                                         ^\n//│ res: 42 | error\n\nBadPair = BadPair { x = 42; y = 0 }\nBadPair.Map\nBadPair.(BadPair.Map)\n//│ BadPair: BadPair[42, 0]\n//│ res: BadPair['A, ?] -> (forall 'x. ('A -> 'x) -> anything -> BadPair['x, 'x])\n//│ ╔══[ERROR] Class BadPair has no method BadPair.Map\n//│ ║  l.205: \tBadPair.(BadPair.Map)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^\n//│ res: (42 -> 'x) -> anything -> BadPair['x, 'x]\n\n\nclass ClassA\n    method MtdA = 42\n//│ Defined class ClassA\n//│ Defined ClassA.MtdA: ClassA -> 42\n\n:e\nclass ClassB: ClassA\n    method MtdA = 43\n//│ ╔══[ERROR] Overriding method ClassA.MtdA without explicit declaration is not allowed.\n//│ ║  l.221: \t    method MtdA = 43\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.221: \t    method MtdA = 43\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── integer literal of type `43` does not match type `42`\n//│ ║  l.221: \t    method MtdA = 43\n//│ ║         \t                  ^^\n//│ ╟── but it flows into method definition with expected type `42`\n//│ ║  l.221: \t    method MtdA = 43\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ║         \t                  ^^\n//│ ╟── from inherited method definition:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ Defined class ClassB\n//│ Defined ClassB.MtdA: ClassB -> 43\n\n:e\nclass ClassC: ClassA\n    method MtdA: int\n    method MtdA = 43\n//│ ╔══[ERROR] Overriding method ClassA.MtdA without explicit declaration is not allowed.\n//│ ║  l.248: \t    method MtdA: int\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method declaration:\n//│ ║  l.248: \t    method MtdA: int\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── type `int` does not match type `42`\n//│ ║  l.248: \t    method MtdA: int\n//│ ║         \t                 ^^^\n//│ ╟── but it flows into method declaration with expected type `42`\n//│ ║  l.248: \t    method MtdA: int\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ║         \t                  ^^\n//│ ╟── from inherited method definition:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ Defined class ClassC\n//│ Declared ClassC.MtdA: ClassC -> int\n//│ Defined ClassC.MtdA: ClassC -> 43\n\n:e\nclass ClassD: ClassA\n    method MtdA: int\n//│ ╔══[ERROR] Overriding method ClassA.MtdA without explicit declaration is not allowed.\n//│ ║  l.277: \t    method MtdA: int\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method declaration:\n//│ ║  l.277: \t    method MtdA: int\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── type `int` does not match type `42`\n//│ ║  l.277: \t    method MtdA: int\n//│ ║         \t                 ^^^\n//│ ╟── but it flows into method declaration with expected type `42`\n//│ ║  l.277: \t    method MtdA: int\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ║         \t                  ^^\n//│ ╟── from inherited method definition:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ Defined class ClassD\n//│ Declared ClassD.MtdA: ClassD -> int\n\n// TODO: remove repeated overriding errors?\nclass ClassE: ClassD\n    method MtdA = 43\n//│ ╔══[ERROR] Overriding method ClassA.MtdA without explicit declaration is not allowed.\n//│ ║  l.304: \t    method MtdA = 43\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.304: \t    method MtdA = 43\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── integer literal of type `43` does not match type `42`\n//│ ║  l.304: \t    method MtdA = 43\n//│ ║         \t                  ^^\n//│ ╟── but it flows into method definition with expected type `42`\n//│ ║  l.304: \t    method MtdA = 43\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ║         \t                  ^^\n//│ ╟── from inherited method definition:\n//│ ║  l.215: \t    method MtdA = 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ Defined class ClassE\n//│ Defined ClassE.MtdA: ClassE -> 43\n\n(ClassE{}).MtdA // typed as 42!\n//│ res: 42\n\n\n:e\nclass Class2A[A]\n    method MtdA: A\ntrait Trait2A[B]\n    method MtdA: B\nclass Class2B: Class2A[int] & Trait2A[string]\n    method MtdA = \"ok\"\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.339: \t    method MtdA = \"ok\"\n//│ ║         \t           ^^^^^^^^^^^\n//│ ╟── string literal of type `\"ok\"` is not an instance of type `int`\n//│ ║  l.339: \t    method MtdA = \"ok\"\n//│ ║         \t                  ^^^^\n//│ ╟── but it flows into method definition with expected type `int`\n//│ ║  l.339: \t    method MtdA = \"ok\"\n//│ ║         \t           ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.338: \tclass Class2B: Class2A[int] & Trait2A[string]\n//│ ║         \t                       ^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.335: \t    method MtdA: A\n//│ ╙──       \t           ^^^^^^^\n//│ Defined class Class2A[+A]\n//│ Declared Class2A.MtdA: Class2A['A] -> 'A\n//│ Defined trait Trait2A[+B]\n//│ Declared Trait2A.MtdA: Trait2A['B] -> 'B\n//│ Defined class Class2B\n//│ Defined Class2B.MtdA: Class2B -> \"ok\"\n\n\n:e\nclass Class3A[A]\n    method MtdA: A\ntype Type3A = Class3A[string]\nclass Class3B: Type3A\n    method MtdA = 1\n//│ ╔══[ERROR] cannot inherit from a type alias\n//│ ║  l.367: \tclass Class3B: Type3A\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ Defined class Class3A[+A]\n//│ Declared Class3A.MtdA: Class3A['A] -> 'A\n//│ Defined type alias Type3A\n\n\n:e\nOops.M\n//│ ╔══[ERROR] Method M not found\n//│ ║  l.378: \tOops.M\n//│ ╙──       \t^^^^^^\n//│ res: error\n\n\nclass Test4A\n    method Mth4A: anything\n    method Mth4A = true\n//│ Defined class Test4A\n//│ Declared Test4A.Mth4A: Test4A -> anything\n//│ Defined Test4A.Mth4A: Test4A -> true\n:e\nclass Test4B: Test4A\n    method Mth4A: int\n//│ ╔══[ERROR] Type mismatch in inherited method definition:\n//│ ║  l.387: \t    method Mth4A = true\n//│ ║         \t           ^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.387: \t    method Mth4A = true\n//│ ║         \t                   ^^^^\n//│ ╟── but it flows into inherited method definition with expected type `int`\n//│ ║  l.387: \t    method Mth4A = true\n//│ ║         \t           ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.393: \t    method Mth4A: int\n//│ ║         \t                  ^^^\n//│ ╟── from method declaration:\n//│ ║  l.393: \t    method Mth4A: int\n//│ ╙──       \t           ^^^^^^^^^^\n//│ ╔══[ERROR] Overriding method Test4A.Mth4A without an overriding definition is not allowed.\n//│ ║  l.393: \t    method Mth4A: int\n//│ ║         \t           ^^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.387: \t    method Mth4A = true\n//│ ╙──       \t           ^^^^^^^^^^^^\n//│ Defined class Test4B\n//│ Declared Test4B.Mth4A: Test4B -> int\n\no = Test4A {}\no.Mth4A\no.(Test4A.Mth4A)\n//│ o: Test4A\n//│ res: anything\n//│ res: anything\n\n:e\nclass Test5A\n    method Mth5A: 42\nclass Test5B: Test5A\n    method Mth5A = 43\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.429: \t    method Mth5A = 43\n//│ ║         \t           ^^^^^^^^^^\n//│ ╟── integer literal of type `43` does not match type `42`\n//│ ║  l.429: \t    method Mth5A = 43\n//│ ║         \t                   ^^\n//│ ╟── but it flows into method definition with expected type `42`\n//│ ║  l.429: \t    method Mth5A = 43\n//│ ║         \t           ^^^^^^^^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.427: \t    method Mth5A: 42\n//│ ║         \t                  ^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.427: \t    method Mth5A: 42\n//│ ╙──       \t           ^^^^^^^^^\n//│ Defined class Test5A\n//│ Declared Test5A.Mth5A: Test5A -> 42\n//│ Defined class Test5B\n//│ Defined Test5B.Mth5A: Test5B -> 43\n\n\nclass Test6A[A]\n    method Mth6A: A\n    method Mth6B[B]: (A -> B) -> B\ntrait Test6B\n    method Mth6A: bool\nclass Test6C: Test6A[int] & Test6B\n//│ Defined class Test6A[+A]\n//│ Declared Test6A.Mth6A: Test6A['A] -> 'A\n//│ Declared Test6A.Mth6B: Test6A['A] -> ('A -> 'B) -> 'B\n//│ Defined trait Test6B\n//│ Declared Test6B.Mth6A: Test6B -> bool\n//│ Defined class Test6C\n\n:e\nTest6A\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.465: \tTest6A\n//│ ║         \t^^^^^^\n//│ ╟── Note that class Test6A is abstract:\n//│ ║  l.451: \tclass Test6A[A]\n//│ ║         \t      ^^^^^^^^\n//│ ╟── Hint: method Mth6A is abstract\n//│ ║  l.452: \t    method Mth6A: A\n//│ ║         \t           ^^^^^^^^\n//│ ╟── Hint: method Mth6B is abstract\n//│ ║  l.453: \t    method Mth6B[B]: (A -> B) -> B\n//│ ╙──       \t           ^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error\n\n:e\nTest6B\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.481: \tTest6B\n//│ ║         \t^^^^^^\n//│ ╟── Note that trait Test6B is abstract:\n//│ ║  l.454: \ttrait Test6B\n//│ ║         \t      ^^^^^^\n//│ ╟── Hint: method Mth6A is abstract\n//│ ║  l.455: \t    method Mth6A: bool\n//│ ╙──       \t           ^^^^^^^^^^^\n//│ res: error\n\n:e\nTest6C\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.494: \tTest6C\n//│ ║         \t^^^^^^\n//│ ╟── Note that class Test6C is abstract:\n//│ ║  l.456: \tclass Test6C: Test6A[int] & Test6B\n//│ ║         \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Hint: method Mth6B is abstract\n//│ ║  l.453: \t    method Mth6B[B]: (A -> B) -> B\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Hint: method Mth6A is abstract\n//│ ║  l.456: \tclass Test6C: Test6A[int] & Test6B\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error\n\n\n\n\n:e\nclass Dup[A, A]: { x: A }\n    method MthDup[B, C, // random comment\n        B]: (A -> B) -> B\n    method MthDup f = f this.x\n//│ ╔══[ERROR] Multiple declarations of type parameter A in class definition\n//│ ║  l.513: \tclass Dup[A, A]: { x: A }\n//│ ║         \t      ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Declared at\n//│ ║  l.513: \tclass Dup[A, A]: { x: A }\n//│ ║         \t          ^\n//│ ╟── Declared at\n//│ ║  l.513: \tclass Dup[A, A]: { x: A }\n//│ ╙──       \t             ^\n//│ ╔══[ERROR] Multiple declarations of type parameter B in method declaration\n//│ ║  l.514: \t    method MthDup[B, C, // random comment\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.515: \t        B]: (A -> B) -> B\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Declared at\n//│ ║  l.514: \t    method MthDup[B, C, // random comment\n//│ ║         \t                  ^\n//│ ╟── Declared at\n//│ ║  l.515: \t        B]: (A -> B) -> B\n//│ ╙──       \t        ^\n//│ Defined class Dup[±A, +A]\n//│ Declared Dup.MthDup: Dup[?, 'A] -> ('A -> 'B) -> 'B\n//│ Defined Dup.MthDup: Dup[?, 'A] -> ('A -> 'a) -> 'a\n//│ ╔══[WARNING] Type definition Dup has bivariant type parameters:\n//│ ║  l.513: \tclass Dup[A, A]: { x: A }\n//│ ║         \t      ^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.513: \tclass Dup[A, A]: { x: A }\n//│ ╙──       \t          ^\n\nt = Dup { x = 42 }\n//│ t: Dup[?, ?] & {x: 42}\n\n:stats\nt : Dup[bool, int]\n//│ res: Dup[?, int]\n//│ constrain calls  : 25\n//│ annoying  calls  : 21\n//│ subtyping calls  : 54\n\n:stats\nt : Dup[int, bool]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.558: \tt : Dup[int, bool]\n//│ ║         \t^\n//│ ╟── integer literal of type `42` is not an instance of type `bool`\n//│ ║  l.547: \tt = Dup { x = 42 }\n//│ ║         \t              ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.558: \tt : Dup[int, bool]\n//│ ╙──       \t             ^^^^\n//│ res: Dup[?, bool]\n//│ constrain calls  : 28\n//│ annoying  calls  : 24\n//│ subtyping calls  : 67\n\n:stats\nt.MthDup (fun x -> mul 2 x)\n//│ res: int\n//│ constrain calls  : 66\n//│ annoying  calls  : 21\n//│ subtyping calls  : 179\n\n:stats\nt.MthDup id\n//│ res: 42\n//│ constrain calls  : 54\n//│ annoying  calls  : 20\n//│ subtyping calls  : 136\n\n\n// We don't currently analyze forward method declarations\n:e\nclass A\n  method Yes = B { x = 1 }\n  method Nope = this.Yes.F1\nclass B: { x: int }\n  method F1: int\n  method F1 = 1\n//│ ╔══[ERROR] Method F1 not found\n//│ ║  l.592: \t  method Nope = this.Yes.F1\n//│ ╙──       \t                ^^^^^^^^^^^\n//│ Defined class A\n//│ Defined A.Yes: A -> (B & {x: 1})\n//│ Defined A.Nope: A -> error\n//│ Defined class B\n//│ Declared B.F1: B -> int\n//│ Defined B.F1: B -> 1\n\n\ntrait D\n  method G = 1\ntrait E\n  method G: int\nclass H: D & E\n  method G = 2\n//│ ╔══[ERROR] Overriding method D.G without explicit declaration is not allowed.\n//│ ║  l.612: \t  method G = 2\n//│ ║         \t         ^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.608: \t  method G = 1\n//│ ╙──       \t         ^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.612: \t  method G = 2\n//│ ║         \t         ^^^^^\n//│ ╟── integer literal of type `2` does not match type `1`\n//│ ║  l.612: \t  method G = 2\n//│ ║         \t             ^\n//│ ╟── but it flows into method definition with expected type `1`\n//│ ║  l.612: \t  method G = 2\n//│ ║         \t         ^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.608: \t  method G = 1\n//│ ║         \t             ^\n//│ ╟── from inherited method definition:\n//│ ║  l.608: \t  method G = 1\n//│ ╙──       \t         ^^^^^\n//│ Defined trait D\n//│ Defined D.G: D -> 1\n//│ Defined trait E\n//│ Declared E.G: E -> int\n//│ Defined class H\n//│ Defined H.G: H -> 2\n\nh = H{}\n//│ h: H\n\nd = h: D\n//│ d: D\n\nd.(D.G)\n//│ res: 1\n\n((H{}): D).(D.G)\n//│ res: 1\n\n\ntrait D2\n  method G2 = 1\ntrait E2\n  method G2: bool\nclass H2: D2 & E2\n//│ ╔══[ERROR] Type mismatch in inherited method definition:\n//│ ║  l.655: \t  method G2 = 1\n//│ ║         \t         ^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `bool`\n//│ ║  l.655: \t  method G2 = 1\n//│ ║         \t              ^\n//│ ╟── but it flows into inherited method definition with expected type `bool`\n//│ ║  l.655: \t  method G2 = 1\n//│ ║         \t         ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.657: \t  method G2: bool\n//│ ║         \t             ^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.657: \t  method G2: bool\n//│ ╙──       \t         ^^^^^^^^\n//│ Defined trait D2\n//│ Defined D2.G2: D2 -> 1\n//│ Defined trait E2\n//│ Declared E2.G2: E2 -> bool\n//│ Defined class H2\n\n\n\n\ntrait Test7A\n  method Mth7A: int\n  method Mth7A = 42\ntrait Test7B\n  method Mth7A: int\n  method Mth7A = 43\n//│ Defined trait Test7A\n//│ Declared Test7A.Mth7A: Test7A -> int\n//│ Defined Test7A.Mth7A: Test7A -> 42\n//│ Defined trait Test7B\n//│ Declared Test7B.Mth7A: Test7B -> int\n//│ Defined Test7B.Mth7A: Test7B -> 43\n\n:e\nclass Test7C: Test7A & Test7B\n//│ ╔══[ERROR] An overriding method definition must be given when inheriting from multiple method definitions\n//│ ║  l.697: \tclass Test7C: Test7A & Test7B\n//│ ║         \t      ^^^^^^\n//│ ╟── Definitions of method Mth7A inherited from:\n//│ ╟── • Test7A\n//│ ║  l.685: \t  method Mth7A = 42\n//│ ║         \t         ^^^^^^^^^^\n//│ ╟── • Test7B\n//│ ║  l.688: \t  method Mth7A = 43\n//│ ╙──       \t         ^^^^^^^^^^\n//│ Defined class Test7C\n\nTest7C.Mth7A\n//│ res: error\n\nclass Test7D: Test7A & Test7B\n  method Mth7A = this.(Test7A.Mth7A) * this.(Test7B.Mth7A)\n//│ Defined class Test7D\n//│ Defined Test7D.Mth7A: Test7D -> int\n\n:e // TODO: suppress?\nclass Test7E: Test7C\n  method Mth7A = 0\n//│ ╔══[ERROR] An overriding method definition must be given when inheriting from multiple method definitions\n//│ ║  l.697: \tclass Test7C: Test7A & Test7B\n//│ ║         \t      ^^^^^^\n//│ ╟── Definitions of method Mth7A inherited from:\n//│ ╟── • Test7A\n//│ ║  l.685: \t  method Mth7A = 42\n//│ ║         \t         ^^^^^^^^^^\n//│ ╟── • Test7B\n//│ ║  l.688: \t  method Mth7A = 43\n//│ ╙──       \t         ^^^^^^^^^^\n//│ Defined class Test7E\n//│ Defined Test7E.Mth7A: Test7E -> 0\n\ntrait Test7F\n  method Mth7A = 0\n//│ Defined trait Test7F\n//│ Defined Test7F.Mth7A: Test7F -> 0\n\n:e\nclass Test7G: Test7C & Test7F\n//│ ╔══[ERROR] An overriding method definition must be given when inheriting from multiple method definitions\n//│ ║  l.697: \tclass Test7C: Test7A & Test7B\n//│ ║         \t      ^^^^^^\n//│ ╟── Definitions of method Mth7A inherited from:\n//│ ╟── • Test7A\n//│ ║  l.685: \t  method Mth7A = 42\n//│ ║         \t         ^^^^^^^^^^\n//│ ╟── • Test7B\n//│ ║  l.688: \t  method Mth7A = 43\n//│ ╙──       \t         ^^^^^^^^^^\n//│ ╔══[ERROR] An overriding method definition must be given when inheriting from multiple method definitions\n//│ ║  l.740: \tclass Test7G: Test7C & Test7F\n//│ ║         \t      ^^^^^^\n//│ ╟── Definitions of method Mth7A inherited from:\n//│ ╟── • Test7C\n//│ ║  l.697: \tclass Test7C: Test7A & Test7B\n//│ ║         \t      ^^^^^^\n//│ ╟── • Test7F\n//│ ║  l.735: \t  method Mth7A = 0\n//│ ╙──       \t         ^^^^^^^^^\n//│ Defined class Test7G\n\n\n\n\nclass Test8A\n    method F: int\n    method F = 1\n//│ Defined class Test8A\n//│ Declared Test8A.F: Test8A -> int\n//│ Defined Test8A.F: Test8A -> 1\n\n:e\nclass Test8B: Test8A\n    method F: 1\n//│ ╔══[ERROR] Overriding method Test8A.F without an overriding definition is not allowed.\n//│ ║  l.775: \t    method F: 1\n//│ ║         \t           ^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.768: \t    method F = 1\n//│ ╙──       \t           ^^^^^\n//│ Defined class Test8B\n//│ Declared Test8B.F: Test8B -> 1\n\nclass Test8C[A]\n    method F: A\n    method F = error\n//│ Defined class Test8C[+A]\n//│ Declared Test8C.F: Test8C['A] -> 'A\n//│ Defined Test8C.F: Test8C[?] -> nothing\n\n// We used to allow syntactically identitcal declarations for documentation,\n//  but that's actually a bad idea (and the implementation was broken)\n:e\nclass Test8D: Test8C[int]\n    method F: int\n//│ ╔══[ERROR] Overriding method Test8C.F without an overriding definition is not allowed.\n//│ ║  l.796: \t    method F: int\n//│ ║         \t           ^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.787: \t    method F = error\n//│ ╙──       \t           ^^^^^^^^^\n//│ Defined class Test8D\n//│ Declared Test8D.F: Test8D -> int\n\n\n\n\nclass Test9A[A]: { x: A }\n    method Mth9A = this.x\n//│ Defined class Test9A[+A]\n//│ Defined Test9A.Mth9A: Test9A['A] -> 'A\n\nclass Test9B: Test9A[int]\n    method Mth9A : Test9A[int] -> int\n    method Mth9A = this.x\n//│ ╔══[ERROR] Overriding method Test9A.Mth9A without explicit declaration is not allowed.\n//│ ║  l.815: \t    method Mth9A : Test9A[int] -> int\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.810: \t    method Mth9A = this.x\n//│ ╙──       \t           ^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method declaration:\n//│ ║  l.815: \t    method Mth9A : Test9A[int] -> int\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Test9A[int] -> int` does not match type `int | ?x`\n//│ ║  l.815: \t    method Mth9A : Test9A[int] -> int\n//│ ║         \t                   ^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into method declaration with expected type `int | ?x`\n//│ ║  l.815: \t    method Mth9A : Test9A[int] -> int\n//│ ║         \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.810: \t    method Mth9A = this.x\n//│ ║         \t                   ^^^^^^\n//│ ╟── from inherited method definition:\n//│ ║  l.810: \t    method Mth9A = this.x\n//│ ╙──       \t           ^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.816: \t    method Mth9A = this.x\n//│ ║         \t           ^^^^^^^^^^^^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.814: \tclass Test9B: Test9A[int]\n//│ ║         \t                     ^^^\n//│ ╟── but it flows into field selection with expected type `Test9A[int] -> int`\n//│ ║  l.816: \t    method Mth9A = this.x\n//│ ║         \t                   ^^^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.815: \t    method Mth9A : Test9A[int] -> int\n//│ ║         \t                   ^^^^^^^^^^^^^^^^^^\n//│ ╟── from method declaration:\n//│ ║  l.815: \t    method Mth9A : Test9A[int] -> int\n//│ ╙──       \t           ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ Defined class Test9B\n//│ Declared Test9B.Mth9A: Test9B -> Test9A[int] -> int\n//│ Defined Test9B.Mth9A: Test9B -> int\n\n:e\n:NoJS\nerror.(Test9B.Mth9A): nothing\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.859: \terror.(Test9B.Mth9A): nothing\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Test9A[int] -> int` does not match type `nothing`\n//│ ║  l.815: \t    method Mth9A : Test9A[int] -> int\n//│ ║         \t                   ^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into field selection with expected type `nothing`\n//│ ║  l.859: \terror.(Test9B.Mth9A): nothing\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.859: \terror.(Test9B.Mth9A): nothing\n//│ ╙──       \t                      ^^^^^^^\n//│ res: nothing\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadPolym.mls",
    "content": "// TL;DR we need a special form of function types that does NOT merge\n//    (as merging approximates unsoundly in the presence of first-class polymorphism)\n\n\ndef foo1: (int -> int & string -> string)\n//│ foo1: int -> int & string -> string\n//│     = <missing implementation>\n\ndef foo: (int -> int & string -> string) -> ()\n//│ foo: (int -> int & string -> string) -> ()\n//│    = <missing implementation>\n\nfooImpl f = f 1\n//│ fooImpl: (1 -> 'a) -> 'a\n//│        = [Function: fooImpl]\n\n:e\nfoo = fooImpl\n//│ (1 -> 'a) -> 'a\n//│   <:  foo:\n//│ (int -> int & string -> string) -> ()\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.18: \tfoo = fooImpl\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── type `int` is not a 0-element tuple\n//│ ║  l.9: \tdef foo: (int -> int & string -> string) -> ()\n//│ ║       \t                 ^^^\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.9: \tdef foo: (int -> int & string -> string) -> ()\n//│ ╙──     \t                                            ^^\n//│    = [Function: fooImpl]\n\nfoo id\n//│ res: ()\n//│    = 1\n\nfooImpl id\n//│ res: 1\n//│    = 1\n\n\nfooImpl2 (f: int -> int & string -> string) = f 1\n//│ fooImpl2: (int -> int & string -> string) -> (int | string)\n//│         = [Function: fooImpl2]\n\nfooImpl2 id\n//│ res: int | string\n//│    = 1\n\n:e\n:re\nres \"oops\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.52: \tres \"oops\"\n//│ ║        \t^^^^^^^^^^\n//│ ╟── type `int` is not a function\n//│ ║  l.42: \tfooImpl2 (f: int -> int & string -> string) = f 1\n//│ ║        \t                    ^^^\n//│ ╟── but it flows into reference with expected type `\"oops\" -> ?a`\n//│ ║  l.52: \tres \"oops\"\n//│ ╙──      \t^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: res is not a function\n\n\n\n// Currently we remove the unsoundness by approximating positive function type intersections.\n// But this leads to things not type checking when they clearly should:\n//    (Basically we lose the property that A & B <: A for all A, B.)\n\ndef bar1: int -> int & string -> string\n//│ bar1: int -> int & string -> string\n//│     = <missing implementation>\n\n// :e // * Did not work before when added subtype checking to constraining...\nbar1 = bar1\n//│ int -> int & string -> string\n//│   <:  bar1:\n//│ int -> int & string -> string\n//│     = <no result>\n//│       bar1 is not implemented\n\n\n:re\nerror: int -> int & string -> string : (int & string) -> (int | string)\n//│ res: nothing -> (int | string)\n//│ Runtime error:\n//│   Error: an error was thrown\n\n// :e // * Did not work before when added subtype checking to constraining...\n:re\nerror: int -> int & string -> string : int -> int\n//│ res: int -> int\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: number -> int & string -> string : int -> number\n//│ res: int -> number\n//│ Runtime error:\n//│   Error: an error was thrown\n\n// * The tricky thing in these tests is that we currently lossily merge function types\n// * in constraint solving, so the best-effort subtyping check may actually accept things\n// * that fail to constrain. But in this case we try to make the check fail by using a type alias.\n// * It somehow still seems to work well...\n\ntype Als = number -> int\n//│ Defined type alias Als\n\n:re\nerror: Als & string -> string : int -> number\n//│ res: int -> number\n//│ Runtime error:\n//│   Error: an error was thrown\n\ntype Id[A] = A\n//│ Defined type alias Id[+A]\n\n:re\nerror: Id[Id[Als] & bool -> bool] & string -> string : int -> number\n//│ res: int -> number\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadTraits.mls",
    "content": "class A\nclass B\n//│ Defined class A\n//│ Defined class B\n\n// Okay to define, but impossible to instantiate:\ntrait T: A & B\n//│ Defined trait T\n\n:e\nT {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.11: \tT {}\n//│ ║        \t^^^^\n//│ ╟── record literal of type `anything` is not an instance of type `A`\n//│ ║  l.11: \tT {}\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.7: \ttrait T: A & B\n//│ ║       \t         ^\n//│ ╟── from intersection type:\n//│ ║  l.7: \ttrait T: A & B\n//│ ╙──     \t         ^^^^^\n//│ res: error | #T\n//│    = {}\n\na = A{}\n//│ a: A\n//│  = A {}\n\n:e\nT a\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.32: \tT a\n//│ ║        \t^^^\n//│ ╟── application of type `A` is not an instance of type `B`\n//│ ║  l.27: \ta = A{}\n//│ ║        \t    ^^^\n//│ ╟── but it flows into reference with expected type `B`\n//│ ║  l.32: \tT a\n//│ ║        \t  ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.7: \ttrait T: A & B\n//│ ║       \t             ^\n//│ ╟── from intersection type:\n//│ ║  l.7: \ttrait T: A & B\n//│ ║       \t         ^^^^^\n//│ ╟── Note: class A is defined at:\n//│ ║  l.1: \tclass A\n//│ ╙──     \t      ^\n//│ res: A & #T | error\n//│    = A {}\n\n:e\n:js\nT A\n//│ // Query 1\n//│ res = T.build((x) => new A(x));\n//│ // End of generated code\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.56: \tT A\n//│ ║        \t^^^\n//│ ╟── reference of type `anything -> A` is not an instance of type `A`\n//│ ║  l.56: \tT A\n//│ ║        \t  ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.7: \ttrait T: A & B\n//│ ║       \t         ^\n//│ ╟── from intersection type:\n//│ ║  l.7: \ttrait T: A & B\n//│ ║       \t         ^^^^^\n//│ ╟── Note: class constructor A is defined at:\n//│ ║  l.1: \tclass A\n//│ ╙──     \t      ^\n//│ res: error | anything -> A & #T\n//│    = [Function (anonymous)]\n\n:e\nT (B {})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.79: \tT (B {})\n//│ ║        \t^^^^^^^^\n//│ ╟── application of type `B` is not an instance of type `A`\n//│ ║  l.79: \tT (B {})\n//│ ║        \t   ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.7: \ttrait T: A & B\n//│ ║       \t         ^\n//│ ╟── from intersection type:\n//│ ║  l.7: \ttrait T: A & B\n//│ ║       \t         ^^^^^\n//│ ╟── Note: class B is defined at:\n//│ ║  l.2: \tclass B\n//│ ╙──     \t      ^\n//│ res: B & #T | error\n//│    = B {}\n\n:re\nt = T error\n//│ t: nothing\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nt: nothing\n//│ res: nothing\n//│ Runtime error:\n//│   ReferenceError: t is not defined\n\ntype Als = A & B\n//│ Defined type alias Als\n\n:re\nt: Als\n//│ res: Als\n//│ Runtime error:\n//│   ReferenceError: t is not defined\n\n\n:e\nclass D0: T\n//│ ╔══[ERROR] class D0 cannot inherit from class B as it already inherits from class A\n//│ ║  l.121: \tclass D0: T\n//│ ╙──       \t      ^^^^^\n\n:e\nclass D1: B & T\n//│ ╔══[ERROR] class D1 cannot inherit from class A as it already inherits from class B\n//│ ║  l.127: \tclass D1: B & T\n//│ ╙──       \t      ^^^^^^^^^\n\n\ntrait S: { x: int }\n//│ Defined trait S\n\ns = S{ x = 1 }\n//│ s: {x: 1} & #S\n//│  = { x: 1 }\n\nt = s: s\n//│ t: #S\n//│  = { x: 1 }\n\n:e\nt.x\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.145: \tt.x\n//│ ║         \t^^^\n//│ ╟── type `#S` does not have field 'x'\n//│ ║  l.140: \tt = s: s\n//│ ║         \t       ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.145: \tt.x\n//│ ╙──       \t^\n//│ res: error\n//│    = 1\n\nt = s: S\n//│ t: S\n//│  = { x: 1 }\n\nt.x\n//│ res: int\n//│    = 1\n\n\ntrait Lol\n  method Foo = 1\nclass Hey\n  method Foo = \"oops\"\n//│ Defined trait Lol\n//│ Defined Lol.Foo: Lol -> 1\n//│ Defined class Hey\n//│ Defined Hey.Foo: Hey -> \"oops\"\n\n:e\nclass H: Lol & Hey\n//│ ╔══[ERROR] An overriding method definition must be given when inheriting from multiple method definitions\n//│ ║  l.177: \tclass H: Lol & Hey\n//│ ║         \t      ^\n//│ ╟── Definitions of method Foo inherited from:\n//│ ╟── • Lol\n//│ ║  l.168: \t  method Foo = 1\n//│ ║         \t         ^^^^^^^\n//│ ╟── • Hey\n//│ ║  l.170: \t  method Foo = \"oops\"\n//│ ╙──       \t         ^^^^^^^^^^^^\n//│ Defined class H\n\n\n// Forbid trait constructors when the trait contains method defs as well:\n\nh = Hey{}\n//│ h: Hey\n//│  = Hey {}\n\n:e\nl = Lol h\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.198: \tl = Lol h\n//│ ║         \t    ^^^\n//│ ╟── Note that traits with methods are always considered abstract\n//│ ║  l.167: \ttrait Lol\n//│ ╙──       \t      ^^^\n//│ l: error\n//│  = Hey {}\n\n:e\ne = Lol\ne\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.209: \te = Lol\n//│ ║         \t    ^^^\n//│ ╟── Note that traits with methods are always considered abstract\n//│ ║  l.167: \ttrait Lol\n//│ ╙──       \t      ^^^\n//│ e: error\n//│  = [Function: build]\n//│ res: error\n//│    = [Function: build]\n\nl.(Lol.Foo)\n//│ res: 1\n//│    = undefined\n\nl.(Hey.Foo)\n//│ res: \"oops\"\n//│    = undefined\n\n\ntrait Lol2: Lol\n//│ Defined trait Lol2\n\n:e\nLol2\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.235: \tLol2\n//│ ║         \t^^^^\n//│ ╟── Note that traits with methods are always considered abstract\n//│ ║  l.231: \ttrait Lol2: Lol\n//│ ╙──       \t      ^^^^^^^^^\n//│ res: error\n//│    = [Function: build]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BadTypes.mls",
    "content": ":ShowRelativeLineNums\n\n\n:e\nclass oops: { x: int }\n//│ ╔══[ERROR] Type names must start with a capital letter\n//│ ║  l.+1: \tclass oops: { x: int }\n//│ ╙──      \t      ^^^^\n\n:e\ntype oops = int\n//│ ╔══[ERROR] Type names must start with a capital letter\n//│ ║  l.+1: \ttype oops = int\n//│ ╙──      \t     ^^^^\n//│ ╔══[ERROR] Type 'Oops' is already defined.\n//│ ║  l.+1: \ttype oops = int\n//│ ╙──      \t     ^^^^\n\nclass Oops2\n//│ Defined class Oops2\n\n:e\nclass oops2\n//│ ╔══[ERROR] Type names must start with a capital letter\n//│ ║  l.+1: \tclass oops2\n//│ ╙──      \t      ^^^^^\n//│ ╔══[ERROR] Type 'Oops2' is already defined.\n//│ ║  l.+1: \tclass oops2\n//│ ╙──      \t      ^^^^^\n\n\ntype Hello = int\n//│ Defined type alias Hello\n\n42: Hello\n//│ res: Hello\n//│    = 42\n\n:e\n42: hello\n//│ ╔══[ERROR] Type alias Hello cannot be used as a type tag\n//│ ║  l.+1: \t42: hello\n//│ ╙──      \t    ^^^^^\n//│ res: error\n//│    = 42\n\n\n:e\naa = { a = 1; a = \"oops\" }\n//│ ╔══[ERROR] Multiple declarations of field name a in record literal\n//│ ║  l.+1: \taa = { a = 1; a = \"oops\" }\n//│ ║        \t     ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Declared at\n//│ ║  l.+1: \taa = { a = 1; a = \"oops\" }\n//│ ║        \t       ^\n//│ ╟── Declared at\n//│ ║  l.+1: \taa = { a = 1; a = \"oops\" }\n//│ ╙──      \t              ^\n//│ aa: {a: 1, a: \"oops\"}\n//│   = { a: 'oops' }\n\n:e\naa: { a: int; a: string }\n//│ ╔══[ERROR] Multiple declarations of field name a in record type\n//│ ║  l.+1: \taa: { a: int; a: string }\n//│ ║        \t    ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Declared at\n//│ ║  l.+1: \taa: { a: int; a: string }\n//│ ║        \t      ^\n//│ ╟── Declared at\n//│ ║  l.+1: \taa: { a: int; a: string }\n//│ ╙──      \t              ^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.+1: \taa: { a: int; a: string }\n//│ ║        \t^^\n//│ ╟── integer literal of type `1` is not an instance of type `string`\n//│ ║  l.49: \taa = { a = 1; a = \"oops\" }\n//│ ║        \t           ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.+1: \taa: { a: int; a: string }\n//│ ╙──      \t                 ^^^^^^\n//│ res: {a: int, a: string}\n//│    = { a: 'oops' }\n\naa.a\n//│ res: 1\n//│    = 'oops'\n\naa: { a: 'a }\n//│ res: {a: 1}\n//│    = { a: 'oops' }\n\n\n\n\n// Note that free type variables in type definitions are now treated as global (level 0),\n//    i.e., shared between all uses of the data type.\n//  It would of course not be sound to refresh them on every expansion of the type definition\n\n\ntype Bad = { x: 'a }\n//│ Defined type alias Bad\n\n:e\n{x = 123}: Bad\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.+1: \t{x = 123}: Bad\n//│ ║        \t^^^^^^^^^\n//│ ╟── integer literal of type `123` does not match type `'a`\n//│ ║  l.+1: \t{x = 123}: Bad\n//│ ║        \t     ^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.101: \ttype Bad = { x: 'a }\n//│ ╙──       \t                ^^\n//│ res: Bad\n//│    = { x: 123 }\n\n:e\n{x = \"ah\"}: Bad\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.+1: \t{x = \"ah\"}: Bad\n//│ ║        \t^^^^^^^^^^\n//│ ╟── string literal of type `\"ah\"` does not match type `'a`\n//│ ║  l.+1: \t{x = \"ah\"}: Bad\n//│ ║        \t     ^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.101: \ttype Bad = { x: 'a }\n//│ ╙──       \t                ^^\n//│ res: Bad\n//│    = { x: 'ah' }\n\n{x = \"ah\"}: { x: 'a }\n//│ res: {x: \"ah\"}\n//│    = { x: 'ah' }\n\n:re\nerror: Bad\n//│ res: Bad\n//│ Runtime error:\n//│   Error: an error was thrown\n\ntype BadRec = { x: 'a; y: BadRec }\n//│ Defined type alias BadRec\n\n:re\n(fun (x: BadRec) -> ()) (error: BadRec)\n//│ res: ()\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: BadRec\n//│ res: BadRec\n//│ Runtime error:\n//│   Error: an error was thrown\n\ndef someRec: { y: 'a } as 'a\n//│ someRec: 'a\n//│   where\n//│     'a :> {y: 'a}\n//│        = <missing implementation>\n\n:e\nsomeRec: BadRec\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.+1: \tsomeRec: BadRec\n//│ ║        \t^^^^^^^\n//│ ╟── type `forall 'a. 'a` does not match type `{x: 'a0, y: BadRec}`\n//│ ║  l.157: \tdef someRec: { y: 'a } as 'a\n//│ ║         \t             ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{x: 'a0, y: BadRec}`\n//│ ║  l.+1: \tsomeRec: BadRec\n//│ ║        \t^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.142: \ttype BadRec = { x: 'a; y: BadRec }\n//│ ║         \t              ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.+1: \tsomeRec: BadRec\n//│ ╙──      \t         ^^^^^^\n//│ res: BadRec\n//│    = <no result>\n//│      someRec is not implemented\n\ndef someRec: { x: 'a; y: 'a } as 'a\n//│ someRec: 'a\n//│   where\n//│     'a :> {x: 'a, y: 'a}\n//│        = <missing implementation>\n\n:e\nsomeRec: BadRec\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.+1: \tsomeRec: BadRec\n//│ ║        \t^^^^^^^\n//│ ╟── type `{x: 'a, y: 'a}` does not match type `'a0`\n//│ ║  l.184: \tdef someRec: { x: 'a; y: 'a } as 'a\n//│ ║         \t             ^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.142: \ttype BadRec = { x: 'a; y: BadRec }\n//│ ╙──       \t                   ^^\n//│ res: BadRec\n//│    = <no result>\n//│      someRec is not implemented\n\n\n\ntype SigR[a] = a\n//│ Defined type alias SigR[+a]\n\n:e\ntype SigR[a] = a\n//│ ╔══[ERROR] Type 'SigR' is already defined.\n//│ ║  l.+1: \ttype SigR[a] = a\n//│ ╙──      \t     ^^^^\n\ntype ExSigR = SigR[int]\n//│ Defined type alias ExSigR\n\n1: ExSigR\n//│ res: ExSigR\n//│    = 1\n\n:e\ntype SigR[a, b] = a\n//│ ╔══[ERROR] Type 'SigR' is already defined.\n//│ ║  l.+1: \ttype SigR[a, b] = a\n//│ ╙──      \t     ^^^^\n\ntype ExSigR2 = SigR[int]\n//│ Defined type alias ExSigR2\n\n:e\ntype ExSigR3 = SigR[int, string]\n//│ ╔══[ERROR] Wrong number of type arguments – expected 1, found 2\n//│ ║  l.+1: \ttype ExSigR3 = SigR[int, string]\n//│ ╙──      \t               ^^^^^^^^^^^^^^^^^\n//│ Defined type alias ExSigR3\n\ntype ExSigR4 = SigR['a]\n//│ Defined type alias ExSigR4\n\n:e\n1: ExSigR4\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.+1: \t1: ExSigR4\n//│ ║        \t^\n//│ ╟── integer literal of type `1` does not match type `'a`\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.239: \ttype ExSigR4 = SigR['a]\n//│ ║         \t                    ^^\n//│ ╟── from type reference:\n//│ ║  l.+1: \t1: ExSigR4\n//│ ╙──      \t   ^^^^^^^\n//│ res: ExSigR4\n//│    = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Basics.mls",
    "content": "\nx = 1\n//│ x: 1\n//│  = 1\n\n1\n//│ res: 1\n//│    = 1\n\n1;\n2\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n\nx = 1;\n2\n//│ x: 1\n//│  = 1\n//│ res: 2\n//│    = 2\n\nx = 1;;\n2\n//│ x: 1\n//│  = 1\n//│ res: 2\n//│    = 2\n\nx = 1\ny = 2\n//│ x: 1\n//│  = 1\n//│ y: 2\n//│  = 2\n\n1\n2\n3\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n//│ res: 3\n//│    = 3\n\n1\nx = add x 1\n//│ res: 1\n//│    = 1\n//│ x: int\n//│  = 2\n\nx = 1\nx\ny = 2\ny\nz = x + y\n//│ x: 1\n//│  = 1\n//│ res: 1\n//│    = 1\n//│ y: 2\n//│  = 2\n//│ res: 2\n//│    = 2\n//│ z: int\n//│  = 3\n\n:e\n1\n 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.72: \t1\n//│ ║        \t^\n//│ ║  l.73: \t 2\n//│ ║        \t^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.72: \t1\n//│ ╙──      \t^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: 1 is not a function\n\ndef f x y z = add x y \n//│ f: int -> int -> anything -> int\n//│  = [Function: f]\n\n\n:e\n:ge\ndef f (x y z) = add x y\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.93: \tdef f (x y z) = add x y\n//│ ╙──      \t       ^^^^^\n//│ f: error -> int\n//│ Code generation encountered an error:\n//│   term App(App(Var(x),Tup(List((None,Fld(_,Var(y)))))),Tup(List((None,Fld(_,Var(z)))))) is not a valid pattern\n\nf 1\n//│ res: int\n//│    = [Function (anonymous)]\n\n\n{a = 0; b = 1}\n//│ res: {a: 0, b: 1}\n//│    = { a: 0, b: 1 }\n\n{a = 0, b = 1}\n//│ res: {a: 0, b: 1}\n//│    = { a: 0, b: 1 }\n\n:pe\n{a: 0, b: 1}\n//│ /!\\ Parse error: Expected \"}\":1:3, found \": 0, b: 1}\" at l.115:3: {a: 0, b: 1}\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Boolean.mls",
    "content": "type Boolean = Tru | Fals\nclass Tru\nclass Fals\ndef Tru: Tru\ndef Fals: Fals\n//│ Defined type alias Boolean\n//│ Defined class Tru\n//│ Defined class Fals\n//│ Tru: Tru\n//│    = <missing implementation>\n//│ Fals: Fals\n//│     = <missing implementation>\n\n:js\nTru: Boolean\n//│ // Query 1 aborted: Tru is not implemented\n//│ // End of generated code\n//│ res: Boolean\n//│    = <no result>\n//│      Tru is not implemented\n\n:e\n:ge\nBoolean\n//│ ╔══[ERROR] identifier not found: Boolean\n//│ ║  l.24: \tBoolean\n//│ ╙──      \t^^^^^^^\n//│ res: error\n//│ Code generation encountered an error:\n//│   type alias Boolean is not a valid expression\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/BooleanFail.mls",
    "content": "\n// TODO fix this\n\n// * The MLscript subtyping system is currently ill-formed in some corner cases.\n// * Notably, it considers functions and classes to intersect to nothing\n// * and also used to considers positive negated function/record types equivalent to nothing.\n\n// * (This isn't the case in MLstruct, which has a sound subtyping lattice.)\n\n\n\n// * Example 1 – now fixed\n\noops = 42 : ~(int -> int)\n//│ oops: ~(int -> int)\n//│     = 42\n\n:e\nnot oops\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.19: \tnot oops\n//│ ║        \t^^^^^^^^\n//│ ╟── type `~(int -> int)` is not an instance of type `bool`\n//│ ║  l.14: \toops = 42 : ~(int -> int)\n//│ ║        \t            ^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `bool`\n//│ ║  l.19: \tnot oops\n//│ ╙──      \t    ^^^^\n//│ res: bool | error\n//│    = false\n\n\n// * This was accepted but didn't immediately lead to immediate unsoundness:\ndef f: (~{x: int}) -> 'a\n//│ f: ~{x: int} -> nothing\n//│  = <missing implementation>\n\n:e\nf = id\n//│ 'a -> 'a\n//│   <:  f:\n//│ ~{x: int} -> nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.39: \tf = id\n//│ ║        \t^^^^^^\n//│ ╟── type `~{x: int}` does not match type `'a`\n//│ ║  l.34: \tdef f: (~{x: int}) -> 'a\n//│ ║        \t       ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.34: \tdef f: (~{x: int}) -> 'a\n//│ ╙──      \t                      ^^\n//│  = [Function: id]\n\n:e\nf 0\nf id\nf {}\nf (forall 'a. fun (x: 'a) -> x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.55: \tf 0\n//│ ║        \t^^^\n//│ ╟── integer literal of type `0` does not match type `~{x: int}`\n//│ ║  l.55: \tf 0\n//│ ║        \t  ^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.34: \tdef f: (~{x: int}) -> 'a\n//│ ╙──      \t       ^^^^^^^^^^^\n//│ res: error\n//│    = 0\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.56: \tf id\n//│ ║        \t^^^^\n//│ ╟── reference of type `?a -> ?a` does not match type `~{x: int}`\n//│ ║  l.56: \tf id\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.34: \tdef f: (~{x: int}) -> 'a\n//│ ╙──      \t       ^^^^^^^^^^^\n//│ res: error\n//│    = [Function: id]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.57: \tf {}\n//│ ║        \t^^^^\n//│ ╟── record literal of type `anything` does not match type `~{x: int}`\n//│ ║  l.57: \tf {}\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.34: \tdef f: (~{x: int}) -> 'a\n//│ ╙──      \t       ^^^^^^^^^^^\n//│ res: error\n//│    = {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.58: \tf (forall 'a. fun (x: 'a) -> x)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `'a -> 'a` does not match type `~{x: int}`\n//│ ║  l.58: \tf (forall 'a. fun (x: 'a) -> x)\n//│ ║        \t              ^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.34: \tdef f: (~{x: int}) -> 'a\n//│ ╙──      \t       ^^^^^^^^^^^\n//│ res: error\n//│    = [Function (anonymous)]\n\n\n// * Example 2 – now fixed\n\ndef g(x: 'a | {f: nothing}) = x.f(0)\n//│ g: {f: 0 -> 'a} -> 'a\n//│  = [Function: g]\n\n:e\nfoo = forall 'x. fun (x: 'x) -> g(x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.112: \tfoo = forall 'x. fun (x: 'x) -> g(x)\n//│ ║         \t                                ^^^^\n//│ ╟── expression of type `'x & ~{f: nothing}` does not have field 'f'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.107: \tdef g(x: 'a | {f: nothing}) = x.f(0)\n//│ ║         \t                              ^^^\n//│ ╟── from type variable:\n//│ ║  l.107: \tdef g(x: 'a | {f: nothing}) = x.f(0)\n//│ ╙──       \t         ^^\n//│ foo: anything -> error\n//│    = [Function: foo]\n\n:re\nfoo 0\n//│ res: error\n//│ Runtime error:\n//│   TypeError: x.f is not a function\n\n\n\n// * Now let's consider why functions and classes can't intersect to nothing due to distributivity\n\n\nclass Foo: { x: anything }\n//│ Defined class Foo\n\n\n// * These two types should be equivalent, but they visibly aren't:\n\ndef a: (int -> int | {x: int}) & Foo\ndef b: int -> int & Foo | {x: int} & Foo\n//│ a: Foo\n//│  = <missing implementation>\n//│ b: Foo & {x: int}\n//│  = <missing implementation>\n\n:ne\nax = a.x\nbx = b.x\n//│ ax: anything\n//│ bx: int\n\n\n// * Yet, this does not immediately lead to unsoundness due to the aggressive normalization\n// * performed during constraint solving:\n\n:ne\na = b\n//│ Foo & {x: int}\n//│   <:  a:\n//│ Foo\n\n:e\n:ne\nb = a\n//│ Foo\n//│   <:  b:\n//│ Foo & {x: int}\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.168: \tb = a\n//│ ║         \t^^^^^\n//│ ╟── expression of type `anything` is not an instance of type `int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.144: \tdef b: int -> int & Foo | {x: int} & Foo\n//│ ╙──       \t                              ^^^\n\n\n// * To expose the unsoundness, we need some indirection with abstract types\n// * that prevent eagerly distributing the intersection type:\n\nclass Test1[A, B]: { f: A & Foo }\n  method M: B & Foo | {x: int} & Foo\n//│ Defined class Test1[+A, +B]\n//│ Declared Test1.M: Test1[?, 'B] -> (Foo & 'B | Foo & {x: int})\n\nclass Test2[B]: Test1[B | {x: int}, B]\n  method M = this.f : B & Foo | {x: int} & Foo\n//│ Defined class Test2[+B]\n//│ Defined Test2.M: Test2['B] -> (Foo & 'B | Foo & {x: int})\n\noops = (Test2{f = Foo{x = \"oops\"}} : Test1[anything, int -> int]).M \n//│ oops: Foo & {x: int}\n//│     = Foo { x: 'oops' }\n\n// * Notice the type confusion:\noops.x + 1\n//│ res: int\n//│    = 'oops1'\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ByNameByValue.mls",
    "content": ":js\ndef incr x = x.a <- x.a + 1\n//│ // Prelude\n//│ let res;\n//│ // Query 1\n//│ globalThis.incr = function incr(x) {\n//│   return void(x.a = x.a + 1);\n//│ };\n//│ // End of generated code\n//│ incr: {mut a: int} -> unit\n//│     = [Function: incr]\n\n\n:p\n:js\ndef gensym = let n = { mut a = 0 } in fun () -> (incr n, n)\n//│ Parsed: def gensym: let n = {mut a: 0} in () => [incr(n,), n,];\n//│ Desugared: def gensym: let n = {mut a: 0} in () => [incr(n,), n,]\n//│ AST: Def(false,Var(gensym),Left(Let(false,Var(n),Rcd(List((Var(a),Fld(m,IntLit(0))))),Lam(Tup(List()),Tup(List((None,Fld(_,App(Var(incr),Tup(List((None,Fld(_,Var(n)))))))), (None,Fld(_,Var(n)))))))),true)\n//│ // Query 1\n//│ globalThis.gensym = function gensym() {\n//│   return (((n) => () => [\n//│     incr(n),\n//│     n\n//│   ])({ a: 0 }));\n//│ };\n//│ // End of generated code\n//│ gensym: () -> (unit, forall 'a. {mut a: 'a},)\n//│   where\n//│     'a :> 0\n//│       = [Function: gensym]\n\n:js\n:p\ngensym1 = let n = { mut a = 0 } in fun () -> (incr n, n)\n//│ Parsed: let gensym1 = let n = {mut a: 0} in () => [incr(n,), n,];\n//│ Desugared: def gensym1: let n = {mut a: 0} in () => [incr(n,), n,]\n//│ AST: Def(false,Var(gensym1),Left(Let(false,Var(n),Rcd(List((Var(a),Fld(m,IntLit(0))))),Lam(Tup(List()),Tup(List((None,Fld(_,App(Var(incr),Tup(List((None,Fld(_,Var(n)))))))), (None,Fld(_,Var(n)))))))),false)\n//│ // Query 1\n//│ globalThis.gensym1 = ((n) => () => [\n//│   incr(n),\n//│   n\n//│ ])({ a: 0 });\n//│ // End of generated code\n//│ gensym1: () -> (unit, forall 'a. {mut a: 'a},)\n//│   where\n//│     'a :> 0\n//│        = [Function (anonymous)]\n\n:js\ngensym ()\n//│ // Query 1\n//│ res = gensym()();\n//│ // End of generated code\n//│ res: (unit, forall 'a. {mut a: 'a},)\n//│   where\n//│     'a :> 0\n//│    = [ undefined, { a: 1 } ]\n\n:js\ngensym ()\n//│ // Query 1\n//│ res = gensym()();\n//│ // End of generated code\n//│ res: (unit, forall 'a. {mut a: 'a},)\n//│   where\n//│     'a :> 0\n//│    = [ undefined, { a: 1 } ]\n\n:js\ngensym1 ()\n//│ // Query 1\n//│ res = gensym1();\n//│ // End of generated code\n//│ res: (unit, forall 'a. {mut a: 'a},)\n//│   where\n//│     'a :> 0\n//│    = [ undefined, { a: 1 } ]\n\ngensym1 ()\n//│ res: (unit, forall 'a. {mut a: 'a},)\n//│   where\n//│     'a :> 0\n//│    = [ undefined, { a: 2 } ]\n\n:js\ngensym1 ()\n//│ // Query 1\n//│ res = gensym1();\n//│ // End of generated code\n//│ res: (unit, forall 'a. {mut a: 'a},)\n//│   where\n//│     'a :> 0\n//│    = [ undefined, { a: 3 } ]\n\n:js\ndef f x = x\n//│ // Query 1\n//│ globalThis.f = function f(x) {\n//│   return x;\n//│ };\n//│ // End of generated code\n//│ f: 'a -> 'a\n//│  = [Function: f]\n\n:js\nf 1\n//│ // Query 1\n//│ res = f(1);\n//│ // End of generated code\n//│ res: 1\n//│    = 1\n\n:js\nrec def xx = xx\n//│ // Query 1\n//│ globalThis.xx = function xx() {\n//│   return xx();\n//│ };\n//│ // End of generated code\n//│ xx: nothing\n//│   = [Function: xx]\n\nclass Nil: {}\nclass Cons[A]: { head: A; tail: List[A] }\ntype List[A] = Nil | Cons[A]\n//│ Defined class Nil\n//│ Defined class Cons[+A]\n//│ Defined type alias List[+A]\n\ndef Nil = Nil {}\ndef Cons head tail = Cons { head; tail }\n//│ Nil: Nil\n//│    = [Function: Nil1]\n//│ Cons: ('head & 'A) -> (List['A] & 'tail) -> (Cons['A] with {head: 'head, tail: 'tail})\n//│     = [Function: Cons1]\n\n:js\nrec def xs = Cons 0 (Cons 1 xs)\n//│ // Query 1\n//│ globalThis.xs = function xs() {\n//│   return Cons1(0)(Cons1(1)(xs()));\n//│ };\n//│ // End of generated code\n//│ xs: 'a\n//│   where\n//│     'a :> Cons[0 | 1] with {head: 0, tail: Cons[0 | 1] with {head: 1, tail: forall 'a. 'a}}\n//│   = [Function: xs]\n\n:re\nxs\n//│ res: 'a\n//│   where\n//│     'a :> Cons[0 | 1] with {head: 0, tail: Cons[0 | 1] with {head: 1, tail: forall 'a. 'a}}\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/David.mls",
    "content": "def toBool = fun x -> true\nb = toBool true\nbb = (fun a -> fun b -> toBool (if b then not a else not a)) true\n//│ toBool: anything -> true\n//│       = [Function: toBool]\n//│ b: true\n//│  = true\n//│ bb: bool -> true\n//│   = [Function (anonymous)]\n\ndef isInt = fun x -> b\n//│ isInt: anything -> true\n//│      = [Function: isInt]\n\nselectBoolOrInt = fun x -> if isInt x then 1 else true\nr1 = selectBoolOrInt true\nr2 = selectBoolOrInt 1\naddOneI = fun x -> add x 1\naddOneB = bb\n//│ selectBoolOrInt: anything -> (1 | true)\n//│                = [Function: selectBoolOrInt]\n//│ r1: 1 | true\n//│   = 1\n//│ r2: 1 | true\n//│   = 1\n//│ addOneI: int -> int\n//│        = [Function: addOneI]\n//│ addOneB: bool -> true\n//│        = [Function (anonymous)]\n\naddOne = fun x -> \n    if (isInt x) \n    then addOneI x \n    else addOneB x\nr3 = isInt r2\n//│ addOne: nothing -> (int | true)\n//│       = [Function: addOne]\n//│ r3: true\n//│   = true\n\n:e\nr4 = addOne (selectBoolOrInt 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.42: \tr4 = addOne (selectBoolOrInt 1)\n//│ ║        \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `bool`\n//│ ║  l.15: \tselectBoolOrInt = fun x -> if isInt x then 1 else true\n//│ ║        \t                                           ^\n//│ ╟── but it flows into application with expected type `bool`\n//│ ║  l.42: \tr4 = addOne (selectBoolOrInt 1)\n//│ ║        \t             ^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.3: \tbb = (fun a -> fun b -> toBool (if b then not a else not a)) true\n//│ ║       \t                                   ^\n//│ ╟── from reference:\n//│ ║  l.34: \t    else addOneB x\n//│ ╙──      \t                 ^\n//│ r4: error | int | true\n//│   = 2\n\n:e\nr4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp }\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.62: \tr4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp }\n//│ ║        \t                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.15: \tselectBoolOrInt = fun x -> if isInt x then 1 else true\n//│ ║        \t                                                  ^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.62: \tr4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp }\n//│ ║        \t                                         ^^^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.62: \tr4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp }\n//│ ╙──      \t                                                  ^^^\n//│ r4: error | int | true\n//│   = 2\n\n// TODO improve:\n//    Note the strange lack of specific provenance flows for `1` and `bool`.\n//    This is due to our eagerly collapsing `int & bool` in the previously-inferred type.\n//    We should either not collapse them until type simplification or somehow remember the original components\n//      so a proper error can later be displayed.\n:e\nr4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp | _ -> 0 }\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.84: \tr4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp | _ -> 0 }\n//│ ║        \t                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `1` is not an instance of type `bool`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.3: \tbb = (fun a -> fun b -> toBool (if b then not a else not a)) true\n//│ ║       \t                                   ^\n//│ ╟── from refined scrutinee:\n//│ ║  l.84: \tr4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp | _ -> 0 }\n//│ ╙──      \t                                         ^^^\n//│ r4: int | true\n//│   = 2\n\ndef addOne x = case x of {\n  | int -> addOneI x \n  | bool -> addOneB x\n  }\n//│ addOne: (bool | int) -> (int | true)\n//│       = [Function: addOne1]\n\ndef r4 = addOne (selectBoolOrInt 1)\n//│ r4: int | true\n//│   = [Function: r43]\n\n\n\n\ndef addOneS = fun x -> concat x \"One\"\n//│ addOneS: string -> string\n//│        = [Function: addOneS]\n\naddOneI 1\naddOneS \"Two\"\n//│ res: int\n//│    = 2\n//│ res: string\n//│    = 'TwoOne'\n\n\n// Attempt 1:\n\ndef isInt = fun x -> case x of { int -> true | string -> false }\n//│ isInt: (int | string) -> Bool\n//│      = [Function: isInt1]\n\nisInt 1\nisInt \"Two\"\n//│ res: Bool\n//│    = true\n//│ res: Bool\n//│    = false\n\ndef addOne = fun x -> if isInt x then addOneI x else addOneS x\n//│ addOne: nothing -> (int | string)\n//│       = [Function: addOne2]\n\n:e\naddOne \"hello\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.142: \taddOne \"hello\"\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"hello\"` is not an instance of type `int`\n//│ ║  l.142: \taddOne \"hello\"\n//│ ║         \t       ^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.18: \taddOneI = fun x -> add x 1\n//│ ║        \t                       ^\n//│ ╟── from reference:\n//│ ║  l.137: \tdef addOne = fun x -> if isInt x then addOneI x else addOneS x\n//│ ╙──       \t                                              ^\n//│ res: error | int | string\n//│    = 'helloOne'\n\n\n// Attempt 2: use a match instead of isInt\n\ndef addOne = fun x -> case x of {\n   int -> addOneI x | \n   string -> addOneS x }\n//│ addOne: (int | string) -> (int | string)\n//│       = [Function: addOne3]\n\naddOne 1\naddOne \"Two\"\n//│ res: int | string\n//│    = 2\n//│ res: int | string\n//│    = 'TwoOne'\n\n:e\n(addOne 1) + 1\nconcat \"Three\" (addOne \"Two\")\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.175: \t(addOne 1) + 1\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── application of type `string` is not an instance of type `int`\n//│ ║  l.112: \tdef addOneS = fun x -> concat x \"One\"\n//│ ║         \t                       ^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `int`\n//│ ║  l.175: \t(addOne 1) + 1\n//│ ╙──       \t ^^^^^^^^\n//│ res: error | int\n//│    = 3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.176: \tconcat \"Three\" (addOne \"Two\")\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `int` is not an instance of type `string`\n//│ ║  l.18: \taddOneI = fun x -> add x 1\n//│ ║        \t                   ^^^^^^^\n//│ ╟── but it flows into application with expected type `string`\n//│ ║  l.176: \tconcat \"Three\" (addOne \"Two\")\n//│ ╙──       \t                ^^^^^^^^^^^^\n//│ res: error | string\n//│    = 'ThreeTwoOne'\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/David2.mls",
    "content": "\nclass Integer: { value: int; addOne: Integer -> Integer }\n//│ Defined class Integer\n\nclass Numb: Integer & { addOne: Numb -> Numb }\n//│ Defined class Numb\n\nclass Stri: { value: string; addOne: Stri -> Stri }\n//│ Defined class Stri\n\naddOne1 x = case x of {\n  | Integer -> x.addOne x\n  | Numb -> x.addOne x\n  }\n//│ addOne1: ((Integer\\value with {addOne: 'a -> 'b}) & 'a) -> 'b\n//│        = [Function: addOne1]\n\n\nrec def loopy() =\n  Integer { value = 1; addOne = fun x -> loopy() }\n//│ loopy: () -> (Integer with {addOne: 'addOne, value: 1})\n//│   where\n//│     'addOne :> anything -> (Integer with {addOne: 'addOne, value: 1})\n//│      = [Function: loopy]\n\naddOne1 (loopy())\n//│ res: 'a\n//│   where\n//│     'a :> Integer with {addOne: anything -> 'a, value: 1}\n//│    = Integer { value: 1, addOne: [Function: addOne] }\n\nres : Integer\n//│ res: Integer\n//│    = Integer { value: 1, addOne: [Function: addOne] }\n\n\n// * Note: In the type of addOne1, `Integer\\value` means we don't use the value field here\n// *  so it could be anything; example:\n\nfunny = loopy() with { value = \"oops!\" }\n//│ funny: Integer with {addOne: 'addOne, value: \"oops!\"}\n//│   where\n//│     'addOne :> anything -> (Integer with {addOne: 'addOne, value: 1})\n//│      = Integer { value: 'oops!', addOne: [Function: addOne] }\n\naddOne1 funny\n//│ res: 'a\n//│   where\n//│     'a :> Integer with {addOne: anything -> 'a, value: 1}\n//│    = Integer { value: 1, addOne: [Function: addOne] }\n\n\n:re\naddOne1 (Integer { value = 1; addOne = fun x -> (error : Integer) } with { value = \"oops!\" })\n//│ res: Integer\n//│ Runtime error:\n//│   Error: an error was thrown\n\n// * `addOne` is now typed polymorphically, so this line now works!\naddOne1 ((Integer { value = 1; addOne = id }) with { value = \"oops!\" })\n//│ res: Integer with {addOne: forall 'a. 'a -> 'a, value: \"oops!\"}\n//│    = Integer { value: 'oops!', addOne: [Function: id] }\n\n\naddOne1 (Integer { value = 1; addOne = id })\n//│ res: Integer with {addOne: forall 'a. 'a -> 'a, value: 1}\n//│    = Integer { value: 1, addOne: [Function: id] }\n\n\n// * Now for properly closing the loop with a constructor for Integer:\n\nrec def mkInteger value = Integer { value; addOne = fun n -> mkInteger (n.value + 1) }\n//│ mkInteger: int -> (Integer with {addOne: 'addOne})\n//│   where\n//│     'addOne :> {value: int} -> (Integer with {addOne: 'addOne})\n//│          = [Function: mkInteger]\n\nn = mkInteger 42\n//│ n: Integer with {addOne: 'addOne}\n//│   where\n//│     'addOne :> {value: int} -> (Integer with {addOne: 'addOne})\n//│  = Integer { value: 42, addOne: [Function: addOne] }\n\nn : Integer\n//│ res: Integer\n//│    = Integer { value: 42, addOne: [Function: addOne] }\n\nm = addOne1 n\n//│ m: 'a\n//│   where\n//│     'a :> Integer with {addOne: {value: int} -> 'a}\n//│  = Integer { value: 43, addOne: [Function: addOne] }\n\nm : Integer\n//│ res: Integer\n//│    = Integer { value: 43, addOne: [Function: addOne] }\n\n\n// * The type of mkInteger above is actually too precise for out taste. We can explicitly restrict it:\n\ndef mkInteger2: int -> Integer\ndef mkInteger2 = mkInteger\n//│ mkInteger2: int -> Integer\n//│           = <missing implementation>\n//│ int -> (Integer with {addOne: 'addOne})\n//│   where\n//│     'addOne :> {value: int} -> (Integer with {addOne: 'addOne})\n//│   <:  mkInteger2:\n//│ int -> Integer\n//│           = [Function: mkInteger2]\n\naddOne1 (mkInteger2 42)\n//│ res: Integer\n//│    = Integer { value: 43, addOne: [Function: addOne] }\n\ndef mkInteger_oops: (int & 'a) -> (Integer & { value: 'a })\n//│ mkInteger_oops: (int & 'a) -> (Integer\\addOne with {value: 'a})\n//│               = <missing implementation>\n\n:e\nrec def mkInteger_oops value = Integer { value; addOne = fun n -> mkInteger_oops (n.value + 1) }\n//│ int -> (Integer with {addOne: 'addOne})\n//│   where\n//│     'addOne :> {value: int} -> (Integer with {addOne: 'addOne})\n//│   <:  mkInteger_oops:\n//│ (int & 'a) -> (Integer\\addOne with {value: 'a})\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.121: \trec def mkInteger_oops value = Integer { value; addOne = fun n -> mkInteger_oops (n.value + 1) }\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` does not match type `'a`\n//│ ║  l.121: \trec def mkInteger_oops value = Integer { value; addOne = fun n -> mkInteger_oops (n.value + 1) }\n//│ ║         \t                                                                                  ^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `'a`\n//│ ║  l.121: \trec def mkInteger_oops value = Integer { value; addOne = fun n -> mkInteger_oops (n.value + 1) }\n//│ ║         \t                                         ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.116: \tdef mkInteger_oops: (int & 'a) -> (Integer & { value: 'a })\n//│ ╙──       \t                                                      ^^\n//│               = [Function: mkInteger_oops]\n\n:precise-rec-typing\nrec def mkInteger_oops value = Integer { value; addOne = fun n -> mkInteger_oops (n.value + 1) }\n//│ (int & 'value) -> (Integer with {addOne: forall 'a. {value: int} -> 'a, value: 'value})\n//│   where\n//│     'a :> Integer with {addOne: forall 'a. {value: int} -> 'a}\n//│   <:  mkInteger_oops:\n//│ (int & 'a) -> (Integer\\addOne with {value: 'a})\n//│               = [Function: mkInteger_oops1]\n\n// * We may still want to retain the precise typing of the `value` part:\n\ndef mkIntegerPrecise value = Integer { value; addOne = addOne1 }\n//│ mkIntegerPrecise: (int & 'value) -> (Integer with {\n//│   addOne: forall 'a 'b. ((Integer\\value with {addOne: 'a -> 'b}) & 'a) -> 'b,\n//│   value: 'value\n//│ })\n//│                 = [Function: mkIntegerPrecise]\n\ndef mkIntegerPrecise value = Integer { value; addOne = fun n -> mkInteger (n.value + 1) }\n//│ mkIntegerPrecise: (int & 'value) -> (Integer with {addOne: forall 'addOne. 'addOne, value: 'value})\n//│   where\n//│     'addOne :> {value: int} -> (Integer with {addOne: 'addOne})\n//│                 = [Function: mkIntegerPrecise1]\n\ndef mkIntegerPrecise value = Integer { value; addOne = fun (n: Integer) -> mkInteger2 (n.value + 1) }\n//│ mkIntegerPrecise: (int & 'value) -> (Integer with {value: 'value})\n//│                 = [Function: mkIntegerPrecise2]\n\nn = mkIntegerPrecise 42\n//│ n: Integer & {value: 42}\n//│  = Integer { value: 42, addOne: [Function: addOne] }\n\naddOne1 n\n//│ res: Integer\n//│    = Integer { value: 43, addOne: [Function: addOne] }\n\ndef mkIntegerPrecise2: (int & 'a) -> (Integer & { value: 'a })\ndef mkIntegerPrecise2 = mkIntegerPrecise\n//│ mkIntegerPrecise2: (int & 'a) -> (Integer\\addOne with {value: 'a})\n//│                  = <missing implementation>\n//│ (int & 'value) -> (Integer with {value: 'value})\n//│   <:  mkIntegerPrecise2:\n//│ (int & 'a) -> (Integer\\addOne with {value: 'a})\n//│                  = [Function: mkIntegerPrecise21]\n\nn = mkIntegerPrecise2 42\n//│ n: Integer & {value: 42}\n//│  = Integer { value: 42, addOne: [Function: addOne] }\n\naddOne1 n\n//│ res: Integer\n//│    = Integer { value: 43, addOne: [Function: addOne] }\n\n\n// * Note that due to recursive function approximation,\n// *  the type of `mkIntegerPrecise` used not to be an instance of the original `mkInteger` type;\n// *  though this now works since distributive first-class polymorphism:\ndef mkIntegerPrecise3: (int & 'a) -> (Integer & { value: 'a })\n//│ mkIntegerPrecise3: (int & 'a) -> (Integer\\addOne with {value: 'a})\n//│                  = <missing implementation>\n\n// * Note: works with :precise-rec-typing when typing mkInteger\n:e\ndef mkIntegerPrecise3 = mkInteger\n//│ int -> (Integer with {addOne: 'addOne})\n//│   where\n//│     'addOne :> {value: int} -> (Integer with {addOne: 'addOne})\n//│   <:  mkIntegerPrecise3:\n//│ (int & 'a) -> (Integer\\addOne with {value: 'a})\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.204: \tdef mkIntegerPrecise3 = mkInteger\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` does not match type `'a`\n//│ ║  l.72: \trec def mkInteger value = Integer { value; addOne = fun n -> mkInteger (n.value + 1) }\n//│ ║        \t                                                                        ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.198: \tdef mkIntegerPrecise3: (int & 'a) -> (Integer & { value: 'a })\n//│ ╙──       \t                                                         ^^\n//│                  = [Function: mkIntegerPrecise3]\n\n\n:e\naddOne1 (Stri { value = \"\"; addOne = error })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.223: \taddOne1 (Stri { value = \"\"; addOne = error })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Stri & {addOne: ?addOne, value: ?value}` does not match type `Integer & ?a`\n//│ ║  l.223: \taddOne1 (Stri { value = \"\"; addOne = error })\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.11: \taddOne1 x = case x of {\n//│ ╙──      \t                 ^\n//│ res: error\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\naddOne2 x = case x of {\n  | Integer -> x.addOne x\n  | Numb -> x.addOne x\n  | Stri -> x.addOne x\n  }\n//│ addOne2: ((Integer\\value with {addOne: 'a -> 'b}) & 'a | (Stri\\value with {addOne: 'c -> 'b}) & 'c) -> 'b\n//│        = [Function: addOne2]\n\naddOne2 (mkIntegerPrecise 42)\n//│ res: Integer\n//│    = Integer { value: 43, addOne: [Function: addOne] }\n\n:re\naddOne2 (Stri { value = \"\"; addOne = error })\n//│ res: nothing\n//│ Runtime error:\n//│   Error: an error was thrown\n\ndef mkStr: string -> Stri\nrec def mkStr value = Stri { value; addOne = fun s -> mkStr (concat s.value \"1\") }\n//│ mkStr: string -> Stri\n//│      = <missing implementation>\n//│ string -> (Stri with {addOne: 'addOne})\n//│   where\n//│     'addOne :> {value: string} -> (Stri with {addOne: 'addOne})\n//│   <:  mkStr:\n//│ string -> Stri\n//│      = [Function: mkStr]\n\naddOne2 (mkStr \"hello\")\n//│ res: Stri\n//│    = Stri { value: 'hello1', addOne: [Function: addOne] }\n\nunion = if true then mkIntegerPrecise 42 else mkStr \"hello\"\n//│ union: Integer & {value: 42} | Stri\n//│      = Integer { value: 42, addOne: [Function: addOne] }\n\nunion2 = addOne2 union\n//│ union2: Integer | Stri\n//│       = Integer { value: 43, addOne: [Function: addOne] }\n\naddOne2 union2\n//│ res: Integer | Stri\n//│    = Integer { value: 44, addOne: [Function: addOne] }\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/DavidB.mls",
    "content": "\n\n\ntuple1 = (1, 2, 3)\n//│ tuple1: (1, 2, 3,)\n//│       = [ 1, 2, 3 ]\n\ntuple2 = (4, 5)\n//│ tuple2: (4, 5,)\n//│       = [ 4, 5 ]\n\nif true then tuple1 else tuple2\n//│ res: Array[1 | 2 | 3 | 4 | 5] & {0: 1 | 4, 1: 2 | 5}\n//│    = [ 1, 2, 3 ]\n\narr = tuple1 : Array[int]\n//│ arr: Array[int]\n//│    = [ 1, 2, 3 ]\n\nif true then tuple1 else arr\n//│ res: Array[int]\n//│    = [ 1, 2, 3 ]\n\n\n\ntype Cons[H, T] = { h: H; t: T }\ntype List[A] = Cons[A, List[A]] | ()\n//│ Defined type alias Cons[+H, +T]\n//│ Defined type alias List[+A]\n\nlist1 = { h = 1; t = { h = 2; t = () }}\n//│ list1: {h: 1, t: {h: 2, t: ()}}\n//│      = { h: 1, t: { h: 2, t: [] } }\n\nlist2 = { h = 3; t = () }\n//│ list2: {h: 3, t: ()}\n//│      = { h: 3, t: [] }\n\nls = if true then list1 else list2\n//│ ls: {h: 1 | 3, t: () | {h: 2, t: ()}}\n//│   = { h: 1, t: { h: 2, t: [] } }\n\nls : List[int]\n//│ res: List[int]\n//│    = { h: 1, t: { h: 2, t: [] } }\n\ntype NonEmptyList[A] = Cons[A, List[A]]\n//│ Defined type alias NonEmptyList[+A]\n\nls : NonEmptyList[int]\n//│ res: NonEmptyList[int]\n//│    = { h: 1, t: { h: 2, t: [] } }\n\n:e // TODO improve error message\nls : Cons[int, Cons[int, List[int]]]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.55: \tls : Cons[int, Cons[int, List[int]]]\n//│ ║        \t^^\n//│ ╟── expression of type `anything` does not have field 'h'\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.26: \ttype Cons[H, T] = { h: H; t: T }\n//│ ║        \t                  ^^^^^^^^^^^^^^\n//│ ╟── from applied type reference:\n//│ ║  l.55: \tls : Cons[int, Cons[int, List[int]]]\n//│ ╙──      \t               ^^^^^^^^^^^^^^^^^^^^\n//│ res: Cons[int, Cons[int, List[int]]]\n//│    = { h: 1, t: { h: 2, t: [] } }\n\nls : { h: int; t: List[int] }\n//│ res: {h: int, t: List[int]}\n//│    = { h: 1, t: { h: 2, t: [] } }\n\n:e\nls : { h: int; t: { h: int; t: List[int] } }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.74: \tls : { h: int; t: { h: int; t: List[int] } }\n//│ ║        \t^^\n//│ ╟── expression of type `anything` does not have field 'h'\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.74: \tls : { h: int; t: { h: int; t: List[int] } }\n//│ ╙──      \t                  ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: {h: int, t: {h: int, t: List[int]}}\n//│    = { h: 1, t: { h: 2, t: [] } }\n\n\n\nclass C[A]: { h: A; t: List[A] }\ntype List0[A] = C[A] | ()\n//│ Defined class C[+A]\n//│ Defined type alias List0[+A]\n\nlist1 = C { h = 1; t = C { h = 2; t = () }}\n//│ list1: C[1 | 2] with {h: 1, t: C[2] with {t: ()}}\n//│      = C { h: 1, t: C { h: 2, t: [] } }\n\nlist2 = C { h = 3; t = () }\n//│ list2: C[3] with {t: ()}\n//│      = C { h: 3, t: [] }\n\nls = if true then list1 else list2\n//│ ls: C[1 | 2 | 3] with {h: 1 | 3, t: (C[2] with {t: ()}) | ()}\n//│   = C { h: 1, t: C { h: 2, t: [] } }\n\nls : List0[int]\n//│ res: List0[int]\n//│    = C { h: 1, t: C { h: 2, t: [] } }\n\n\n\ntype List1[A] = (A, List1[A]) | ()\n//│ Defined type alias List1[+A]\n\nlist1 = (1, (2, (3, ())))\n//│ list1: (1, (2, (3, (),),),)\n//│      = [ 1, [ 2, [ 3, [] ] ] ]\n\nlist1: List1[int]\n//│ res: List1[int]\n//│    = [ 1, [ 2, [ 3, [] ] ] ]\n\nlist2 = (4, (5, ()))\n//│ list2: (4, (5, (),),)\n//│      = [ 4, [ 5, [] ] ]\n\nif true then list1 else list2\n//│ res: (1 | 4, (2 | 5, Array[3 | ()],),)\n//│    = [ 1, [ 2, [ 3, [] ] ] ]\n\n\n\nclass N\n//│ Defined class N\n\nclass Con[H, T]: { h: H; t: T }\n//│ Defined class Con[+H, +T]\n\ntype List2[A] = Cons[A, List2[A]] | N\n//│ Defined type alias List2[+A]\n\n\nrec def foo xs = case xs of\n  Con -> if xs.h then Con { h = xs.t.h; t = foo xs.t.t } else foo xs.t.t\n//│ foo: 'a -> 'T\n//│   where\n//│     'T :> Con['h, 'T]\n//│     'a <: Con[?, ?] & {h: bool, t: {h: 'h, t: 'a}}\n//│    = [Function: foo]\n\nrec def foo xs = case xs of\n  Con ->\n    let tmp = foo xs.t.t in\n    if xs.h then Con { h = xs.t.h; t = tmp } else tmp,\n  N -> xs\n//│ foo: 'a -> 'b\n//│   where\n//│     'a <: Con[?, ?] & {h: bool, t: {h: 'h, t: 'a}} | N & 'b\n//│     'b :> Con['h, 'b]\n//│    = [Function: foo1]\n\nrec def foo xs = case xs of\n  Con -> if xs.h then Con { h = xs.t.h; t = foo xs.t.t } else foo xs.t.t,\n  N -> xs\n//│ foo: 'a -> 'b\n//│   where\n//│     'a <: Con[?, ?] & {h: bool, t: {h: 'h, t: 'a}} | N & 'b\n//│     'b :> Con['h, 'b]\n//│    = [Function: foo2]\n\nfoo (N{})\n//│ res: 'a\n//│   where\n//│     'a :> Con[nothing, 'a] | N\n//│    = N {}\n\nfoo (Con{ h = true; t = Con{ h = 0; t = N{} } })\n//│ res: 'a\n//│   where\n//│     'a :> Con[0, 'a] | N\n//│    = Con { h: 0, t: N {} }\n\ndef inf: Con[true, Con[0, 'I]] as 'I\n//│ inf: 'I\n//│   where\n//│     'I :> Con[true, Con[0, 'I]]\n//│    = <missing implementation>\n\nfoo inf\n//│ res: 'a\n//│   where\n//│     'a :> Con[0, 'a]\n//│    = <no result>\n//│      inf is not implemented\n\n\nrec def foo2 xs = case xs of\n  Con -> if xs.h then Con { h = xs.t.h; t = foo xs.t.t } else foo xs.t.t,\n  N -> N{}\n//│ foo2: (Con[?, ?] & {h: bool, t: {h: 'h, t: 'a & 'b}} | N) -> (Con['h, forall 'c. 'c | 'd] | N | 'e)\n//│   where\n//│     'c :> Con['h0, 'c | 'd] | 'd\n//│     'b <: Con[?, ?] & {h: bool, t: {h: 'h1, t: 'b}} | N & 'e\n//│     'e :> Con['h1, 'e]\n//│     'a <: Con[?, ?] & {h: bool, t: {h: 'h0, t: 'a}} | N & 'd\n//│     = [Function: foo21]\n\n\n\n// === === === ERROR CASES === === === //\n\n\n\n:e\nfoo (Con{ h = 1; t = N{} })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.213: \tfoo (Con{ h = 1; t = N{} })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `N` does not have field 't'\n//│ ║  l.213: \tfoo (Con{ h = 1; t = N{} })\n//│ ║         \t                     ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.161: \t  Con -> if xs.h then Con { h = xs.t.h; t = foo xs.t.t } else foo xs.t.t,\n//│ ║         \t                                                                  ^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.161: \t  Con -> if xs.h then Con { h = xs.t.h; t = foo xs.t.t } else foo xs.t.t,\n//│ ║         \t                                                                  ^^^^\n//│ ╟── Note: class N is defined at:\n//│ ║  l.131: \tclass N\n//│ ╙──       \t      ^\n//│ res: error\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Didier.mls",
    "content": "\n\ndef either x y = if 42 == 6 * 7 then x else y\ndef fst((a,b)) = a\ndef snd((a,b)) = b\n//│ either: 'a -> 'a -> 'a\n//│       = [Function: either]\n//│ fst: (('a, anything,),) -> 'a\n//│    = [Function: fst]\n//│ snd: ((anything, 'a,),) -> 'a\n//│    = [Function: snd]\n\ndef K : 'A -> 'B -> 'B\nK a b = b\ntype Sid = 'A -> 'A\ndef id : Sid\nid x = x\ndef auto : Sid -> Sid\nauto f = f f\n//│ Defined type alias Sid\n//│ K: anything -> 'B -> 'B\n//│  = <missing implementation>\n//│ anything -> 'a -> 'a\n//│   <:  K:\n//│ anything -> 'B -> 'B\n//│  = [Function: K]\n//│ id: Sid\n//│   = <missing implementation>\n//│ 'a -> 'a\n//│   <:  id:\n//│ Sid\n//│   = [Function: id1]\n//│ auto: Sid -> Sid\n//│     = <missing implementation>\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  auto:\n//│ Sid -> Sid\n//│     = [Function: auto]\n\ndef trial =\n     fun x ->\n        (fun z ->\n            K (auto (either x (fst z) : Sid))\n              (snd z))\n        ((id, id))\n        1\n//│ trial: Sid -> 1\n//│      = [Function: trial]\n\ntrial id\n//│ res: 1\n//│    = 1\n\n\n// * In a discussion regarding a declarative system using boxes\n\nlet px =\n    (fun x ->\n      let pz =\n          (fun z ->\n            (let e =  (either x (fst z) : forall 'A. 'A -> 'A) in\n              // (** [1] forces x and z to have the same tag,\n              //     or to be unboxed with {} marks *)\n              K (auto e) e,\n              // (** [2] returning e requires to stay boxed, for\n              //     implicit use of polymorphism below *)\n              snd z))\n          ((id, id)) in\n      (fst pz\n        // (** [3] returns the first component unchanged with x=z1-tag,\n        //     still in scope *)\n        , snd pz 1\n        // (** [4] this requires pz to be tagged, with z2-tag, which is\n        //     no longer in scope and can be instantiated *)\n        ))\n    id\n  in\n  fst px 0\n  // (** the z1=x tag is no more in scope so it can be instantiated *)\n//│ res: 0\n//│    = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Dmitry.mls",
    "content": "\nclass Class1: { payload: int }\n//│ Defined class Class1\n\n:e\nclass Hidden[A]\n  method Foo s = case s of { Class1 -> s.payload | _ -> 123 }\n  method Main (a: A) = this.Foo a\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.8: \t  method Main (a: A) = this.Foo a\n//│ ║       \t                       ^^^^^^^^^^\n//│ ╟── expression of type `A & (Class1 | ~?a)` does not have field 'payload'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.7: \t  method Foo s = case s of { Class1 -> s.payload | _ -> 123 }\n//│ ║       \t                                       ^^^^^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.7: \t  method Foo s = case s of { Class1 -> s.payload | _ -> 123 }\n//│ ╙──     \t                      ^\n//│ Defined class Hidden[-A]\n//│ Defined Hidden.Foo: Hidden[?] -> ((Class1 with {payload: 'payload}) | ~Class1) -> (123 | 'payload)\n//│ Defined Hidden.Main: Hidden['A] -> 'A -> (123 | error)\n\nclass Hidden2[A]\n  method Foo s = case s of { Class1 -> s.payload | _ -> 123 }\n  method Main (a: A) = this.Foo (a with { payload = 1 })\n//│ Defined class Hidden2[-A]\n//│ Defined Hidden2.Foo: Hidden2[?] -> ((Class1 with {payload: 'payload}) | ~Class1) -> (123 | 'payload)\n//│ Defined Hidden2.Main: Hidden2['A] -> 'A -> (1 | 123)\n\n\ndef foo: (\"A\" | \"B\" | \"D\" | \"E\" | \"F\" | \"G\" | \"H\" | \"I\" | \"J\") -> int\n//│ foo: (\"A\" | \"B\" | \"D\" | \"E\" | \"F\" | \"G\" | \"H\" | \"I\" | \"J\") -> int\n//│    = <missing implementation>\n\narg = if true then \"B\" else if false then \"C\" else \"D\"\n//│ arg: \"B\" | \"C\" | \"D\"\n//│    = 'B'\n\n:e\nfoo arg\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.40: \tfoo arg\n//│ ║        \t^^^^^^^\n//│ ╟── string literal of type `\"C\"` does not match type `\"A\" | \"B\" | \"D\" | \"E\" | \"F\" | \"G\" | \"H\" | \"I\" | \"J\"`\n//│ ║  l.35: \targ = if true then \"B\" else if false then \"C\" else \"D\"\n//│ ║        \t                                          ^^^\n//│ ╟── but it flows into reference with expected type `\"A\" | \"B\" | \"D\" | \"E\" | \"F\" | \"G\" | \"H\" | \"I\" | \"J\"`\n//│ ║  l.40: \tfoo arg\n//│ ║        \t    ^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.31: \tdef foo: (\"A\" | \"B\" | \"D\" | \"E\" | \"F\" | \"G\" | \"H\" | \"I\" | \"J\") -> int\n//│ ╙──      \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | int\n//│    = <no result>\n//│      foo is not implemented\n\nfoo2 x = case x of {\n  | \"A\" -> 1\n  | \"B\" -> 2\n  | \"D\" -> 3\n  | \"E\" -> 4\n  | \"F\" -> 5\n  | \"G\" -> 6\n  | \"H\" -> 7\n  | \"I\" -> 8\n  | \"J\" -> 9\n  }\n//│ foo2: (\"A\" | \"B\" | \"D\" | \"E\" | \"F\" | \"G\" | \"H\" | \"I\" | \"J\") -> (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9)\n//│     = [Function: foo2]\n\n:e\nfoo2 arg\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.72: \tfoo2 arg\n//│ ║        \t^^^^^^^^\n//│ ╟── string literal of type `\"C\"` does not match type `\"A\" & ?a | \"B\" & ?b | \"D\" & ?c | \"E\" & ?d | \"F\" & ?e | \"G\" & ?f | \"H\" & ?g | \"I\" & ?h | \"J\" & ?i`\n//│ ║  l.35: \targ = if true then \"B\" else if false then \"C\" else \"D\"\n//│ ║        \t                                          ^^^\n//│ ╟── but it flows into reference with expected type `\"A\" & ?a | \"B\" & ?j | \"D\" & ?c | \"E\" & ?d | \"F\" & ?e | \"G\" & ?f | \"H\" & ?g | \"I\" & ?h | \"J\" & ?i`\n//│ ║  l.72: \tfoo2 arg\n//│ ║        \t     ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.57: \tfoo2 x = case x of {\n//│ ╙──      \t              ^\n//│ res: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | error\n//│    = 2\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/EitherClasses.mls",
    "content": "class Left[A]: { value: A }\n//│ Defined class Left[+A]\n\nLeft{value=1}\n//│ res: Left[1]\n//│    = Left { value: 1 }\n\ndef Left value = Left{ value }\n//│ Left: 'value -> Left['value]\n//│     = [Function: Left1]\n\nclass Right[A]: { value: A }\ndef Right value = Right{ value }\n//│ Defined class Right[+A]\n//│ Right: 'value -> Right['value]\n//│      = [Function: Right1]\n\ntestVal = if true then Left 1 else Right 2\n//│ testVal: Left[1] | Right[2]\n//│        = Left { value: 1 }\n\ntestVal.value\n//│ res: 1 | 2\n//│    = 1\n\nres = case testVal of\n  { Left -> testVal.value\n  | Right -> 1\n  }\n//│ res: 1\n//│    = 1\n\nres: 1\n//│ res: 1\n//│    = 1\n\ncase res of { 1 -> \"ok\" }\n//│ res: \"ok\"\n//│    = 'ok'\n\nres = case testVal of\n  { Left -> testVal\n  | Right -> 1\n  }\n//│ res: 1 | Left[1]\n//│    = Left { value: 1 }\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ExplicitVariance.mls",
    "content": "\n// TODO have a way of specifying the variance explicitly,\n//    because it would be too expensive to infer it when it's needed in method implementations\n//    (we'd have to re-type-check methods at every iteration of the fixed point)\n\n// class Covar[out A]\n\n:e\n:w\nclass Covar[A]\n  method CovarMtd =\n    let tmp = (error : Covar[{ x: int }]) : Covar[{}]\n    in ()\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.12: \t    let tmp = (error : Covar[{ x: int }]) : Covar[{}]\n//│ ║        \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `anything` does not have field 'x'\n//│ ║  l.12: \t    let tmp = (error : Covar[{ x: int }]) : Covar[{}]\n//│ ║        \t                                                  ^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.12: \t    let tmp = (error : Covar[{ x: int }]) : Covar[{}]\n//│ ╙──      \t                             ^^^^^^^^^^\n//│ Defined class Covar[±A]\n//│ Defined Covar.CovarMtd: Covar[?] -> ()\n//│ ╔══[WARNING] Type definition Covar has bivariant type parameters:\n//│ ║  l.10: \tclass Covar[A]\n//│ ║        \t      ^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.10: \tclass Covar[A]\n//│ ╙──      \t            ^\n\n:re\n(error : Covar[{ x: int }]) : Covar[{}]\n//│ res: Covar[?]\n//│ Runtime error:\n//│   Error: an error was thrown\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ExprProb.mls",
    "content": "\ndef intToString: int -> string\ndef intToString x = toString x\ndef done x = case x of {}\n//│ intToString: int -> string\n//│            = <missing implementation>\n//│ anything -> string\n//│   <:  intToString:\n//│ int -> string\n//│            = [Function: intToString]\n//│ done: nothing -> nothing\n//│     = [Function: done]\n\n\n\nclass Lit: { val: int }\nclass Add[E]: { lhs: E; rhs: E }\ndef lit val = Lit { val }\ndef add lhs rhs = Add { lhs; rhs }\n//│ Defined class Lit\n//│ Defined class Add[+E]\n//│ lit: (int & 'val) -> (Lit with {val: 'val})\n//│    = [Function: lit]\n//│ add: ('lhs & 'E) -> ('E & 'rhs) -> (Add['E] with {lhs: 'lhs, rhs: 'rhs})\n//│    = [Function: add]\n\n\n\nrec def eval1_stub k e = case e of {\n  | Add -> eval1_stub k e.lhs\n  | _ -> k e\n  }\n//│ eval1_stub: ('a -> 'b) -> 'c -> 'b\n//│   where\n//│     'c <: Add[?] & {lhs: 'c} | 'a & ~#Add\n//│           = [Function: eval1_stub]\n\nrec def eval1_stub k e = case e of {\n  | Add -> eval1_stub k e.lhs + eval1_stub k e.rhs\n  | _ -> k e\n  }\n//│ eval1_stub: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | 'a & ~#Add\n//│           = [Function: eval1_stub1]\n\n:ns\nrec def eval1_stub e = case e of {\n  | Lit -> 1\n  | Add -> eval1_stub e.lhs\n  | _ -> 0\n  }\n//│ eval1_stub: forall 'eval1_stub 'a 'b 'c 'lhs 'd 'e. 'eval1_stub\n//│   where\n//│     'eval1_stub := 'a -> (1 | 'd | 0)\n//│     'd :> 1 | 'd | 0\n//│     'a <: #Lit & 'b | (#Add & 'c | 'e & ~#Add) & ~#Lit\n//│     'c <: {lhs: 'lhs}\n//│     'lhs <: 'a\n//│           = [Function: eval1_stub2]\n\neval1_stub\n//│ res: 'a -> (0 | 1)\n//│   where\n//│     'a <: Add[?] & {lhs: 'a} | Lit | ~Add[?] & ~Lit\n//│    = [Function: eval1_stub2]\n\n// def eval1: ('b -> int) -> Expr['b] -> int\n:stats\nrec def eval1 k e = case e of {\n  | Lit -> e.val\n  | Add -> eval1 k e.lhs + eval1 k e.rhs\n  | _ -> k e\n  }\n//│ eval1: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit | 'a & ~#Add & ~#Lit\n//│      = [Function: eval1]\n//│ constrain calls  : 73\n//│ annoying  calls  : 0\n//│ subtyping calls  : 291\n\n:ns\neval1\n//│ res: forall 'eval1 'a 'b 'c 'val 'd 'lhs 'rhs 'e 'f 'g. 'eval1\n//│   where\n//│     'eval1 := 'a -> 'b -> ('val | 'e | 'g)\n//│     'e := int\n//│     'b <: #Lit & 'c | (#Add & 'd | 'f & ~#Add) & ~#Lit\n//│     'd <: {rhs: 'rhs} & {lhs: 'lhs}\n//│     'lhs <: 'b\n//│     'rhs <: 'b\n//│     'c <: {val: 'val}\n//│     'val <: int\n//│     'a <: 'f -> 'g\n//│     'g <: int\n//│    = [Function: eval1]\n\n:re\nerror: ~Add[?]\n//│ res: ~Add[nothing]\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: ('a & ~Lit) -> 'a\n//│ res: ('a & ~Lit) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: ('a) -> ('a & Add[?])\nerror: ('a) -> ('a & ~Add[?])\nerror: ('a & ~Add[?]) -> 'a\n//│ res: 'a -> (Add[?] & 'a)\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res: 'a -> ('a & ~Add[nothing])\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res: ('a & ~Add[?]) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: ('a & ~add) -> 'a\n//│ res: ('a & ~#Add) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:ns\ndef eval1_ty_ugly: ('a -> int) -> (Lit | Add['b] | 'a & ~Lit & ~Add[?] as 'b) -> int\n//│ eval1_ty_ugly: forall 'a 'b. ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Lit | Add['b] | 'a & ~Lit & ~Add[?]\n//│              = <missing implementation>\n\neval1_ty_ugly\n//│ res: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│    = <no result>\n//│      eval1_ty_ugly is not implemented\n\n:ns\ndef eval1_ty: ('a -> int) -> (Lit | Add['b] | 'a & ~lit & ~add as 'b) -> int\n//│ eval1_ty: forall 'a 'b. ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Lit | Add['b] | 'a & ~#Lit & ~#Add\n//│         = <missing implementation>\n\neval1_ty\n//│ res: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add['b] | Lit | 'a & ~#Add & ~#Lit\n//│    = <no result>\n//│      eval1_ty is not implemented\n\n:stats\ndef eval1_ty = eval1\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit | 'a & ~#Add & ~#Lit\n//│   <:  eval1_ty:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add['b] | Lit | 'a & ~#Add & ~#Lit\n//│         = [Function: eval1_ty]\n//│ constrain calls  : 71\n//│ annoying  calls  : 37\n//│ subtyping calls  : 576\n\n:stats\neval1_ty = eval1_ty_ugly\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│   <:  eval1_ty:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add['b] | Lit | 'a & ~#Add & ~#Lit\n//│         = <no result>\n//│           eval1_ty_ugly is not implemented\n//│ constrain calls  : 238\n//│ annoying  calls  : 565\n//│ subtyping calls  : 5737\n\n\n// Workaround:\n:ns\ntype E1[A] = Lit | Add[E1[A]] | A & ~lit & ~add\ndef eval1_ty: ('a -> int) -> E1['a] -> int\n//│ Defined type alias E1[+A]\n//│ eval1_ty: forall 'a. ('a -> int) -> E1['a] -> int\n//│         = <missing implementation>\n\neval1_ty\n//│ res: ('a -> int) -> E1['a] -> int\n//│    = <no result>\n//│      eval1_ty is not implemented\n\n:stats\ndef eval1_ty = eval1\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit | 'a & ~#Add & ~#Lit\n//│   <:  eval1_ty:\n//│ ('a -> int) -> E1['a] -> int\n//│         = [Function: eval1_ty1]\n//│ constrain calls  : 67\n//│ annoying  calls  : 37\n//│ subtyping calls  : 471\n\n\n:stats\nrec def pretty1 k e = case e of {\n  | Lit -> intToString e.val\n  | Add -> concat (pretty1 k e.lhs) (pretty1 k e.rhs)\n  | _ -> k e\n  }\n//│ pretty1: ('a -> string) -> 'b -> string\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit | 'a & ~#Add & ~#Lit\n//│        = [Function: pretty1]\n//│ constrain calls  : 81\n//│ annoying  calls  : 0\n//│ subtyping calls  : 326\n\n\n:stats\nrec def prettier1 k ev e = case e of {\n  | Lit -> intToString e.val\n  | Add ->\n      if ev e.lhs == 0 then prettier1 k ev e.rhs\n      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n      else concat (prettier1 k ev e.lhs) (prettier1 k ev e.rhs)\n  | _ -> k e\n  }\n//│ prettier1: ('a -> string) -> ('lhs -> number) -> 'b -> string\n//│   where\n//│     'b <: Add[?] & {lhs: 'lhs & 'b, rhs: 'lhs & 'b} | Lit | 'a & ~#Add & ~#Lit\n//│          = [Function: prettier1]\n//│ constrain calls  : 260\n//│ annoying  calls  : 0\n//│ subtyping calls  : 832\n\n:stats\nrec def prettier11 k ev e = case e of {\n  | Lit -> intToString e.val\n  | Add ->\n      let tmp = pretty1 k e.lhs\n      in if ev e.rhs == 0 then tmp else concat tmp (prettier11 k ev e.rhs)\n  | _ -> k e\n  }\n//│ prettier11: ('a -> string) -> ('rhs -> number) -> 'b -> string\n//│   where\n//│     'b <: Add[?] & {lhs: Add[?] & 'c | Lit | 'a & ~#Add & ~#Lit, rhs: 'rhs & 'b} | Lit | 'a & ~#Add & ~#Lit\n//│     'c <: {lhs: 'd, rhs: 'd}\n//│     'd <: Add[?] & 'c | Lit | 'a & ~#Add & ~#Lit\n//│           = [Function: prettier11]\n//│ constrain calls  : 178\n//│ annoying  calls  : 0\n//│ subtyping calls  : 737\n\n// Doesn't make much sense, but generates very ugly type unless aggressively simplified:\n:stats\nrec def prettier12 k ev e = case e of {\n  | Lit -> intToString e.val\n  | Add ->\n      let tmp = pretty1 k e.lhs\n      in if ev e == 0 then tmp else concat tmp (pretty1 k e.rhs)\n  | _ -> k e\n  }\n//│ prettier12: ('a -> string & 'b -> 'c) -> ('d -> number) -> (Add[?] & {lhs: Add[?] & 'e | Lit | 'a & ~#Add & ~#Lit, rhs: 'f} & 'd | Lit | 'b & ~#Add & ~#Lit) -> (string | 'c)\n//│   where\n//│     'f <: Add[?] & {lhs: 'f, rhs: 'f} | Lit | 'a & ~#Add & ~#Lit\n//│     'e <: {lhs: 'g, rhs: 'g}\n//│     'g <: Add[?] & 'e | Lit | 'a & ~#Add & ~#Lit\n//│           = [Function: prettier12]\n//│ constrain calls  : 158\n//│ annoying  calls  : 0\n//│ subtyping calls  : 798\n\n\n:stats\ne1 = Add{lhs = Lit {val = 1}; rhs = Add{lhs = Lit {val = 2}; rhs = Lit {val = 3}}}\neval1 done e1\npretty1 done e1\nprettier1 done (eval1 done) e1\nprettier11 done (eval1 done) e1\nprettier12 done (eval1 done) e1\n//│ e1: Add[Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}} | Lit & {val: 1}] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}\n//│ }\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Add { lhs: Lit { val: 2 }, rhs: Lit { val: 3 } }\n//│     }\n//│ res: int\n//│    = 6\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ constrain calls  : 1109\n//│ annoying  calls  : 500\n//│ subtyping calls  : 9419\n\n\ne1 = add (lit 1) (add (lit 2) (lit 3))\neval1 done e1\npretty1 done e1\nprettier1 done (eval1 done) e1\nprettier11 done (eval1 done) e1\nprettier12 done (eval1 done) e1\n//│ e1: Add[Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}} | Lit & {val: 1}] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}\n//│ }\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Add { lhs: Lit { val: 2 }, rhs: Lit { val: 3 } }\n//│     }\n//│ res: int\n//│    = 6\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n\n\n\nclass Nega[E]: { arg: E }\ndef nega arg = Nega { arg }\n//│ Defined class Nega[+E]\n//│ nega: 'arg -> Nega['arg]\n//│     = [Function: nega]\n\n\n\nrec def eval2 k = eval1 (fun x -> case x of {\n  | Nega -> 0 - (eval2 k x.arg)\n  | _ -> k x\n  })\n//│ eval2: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'd} | 'a & ~#Nega\n//│     'd <: Add[?] & {lhs: 'd, rhs: 'd} | Lit | 'c & ~#Add & ~#Lit\n//│      = [Function: eval2]\n\n\n:stats\nrec def prettier2 k ev = prettier1 (fun x -> case x of {\n  | Nega -> concat \"-\" (prettier2 k ev x.arg)\n  | _ -> k x\n  }) ev\n//│ prettier2: ('a -> string) -> ('lhs -> number) -> 'b -> string\n//│   where\n//│     'b <: Add[?] & {lhs: 'lhs & 'b, rhs: 'lhs & 'b} | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'd} | 'a & ~#Nega\n//│     'd <: Add[?] & {lhs: 'lhs & 'd, rhs: 'lhs & 'd} | Lit | 'c & ~#Add & ~#Lit\n//│          = [Function: prettier2]\n//│ constrain calls  : 116\n//│ annoying  calls  : 0\n//│ subtyping calls  : 509\n\n:stats\nrec def prettier22 k ev = prettier12 (fun x -> case x of {\n  | Nega -> concat \"-\" (prettier22 k ev x.arg)\n  | _ -> k x\n  }) ev\n//│ prettier22: ('a -> string) -> ('b -> number) -> (Add[?] & 'b | Lit | 'c & ~#Add & ~#Lit) -> string\n//│   where\n//│     'b <: {lhs: Add[?] & 'd | Lit | 'e & ~#Add & ~#Lit, rhs: 'f}\n//│     'f <: Add[?] & {lhs: 'f, rhs: 'f} | Lit | Nega[?] & {arg: 'arg} | 'a & ~#Add & ~#Lit & ~#Nega\n//│     'd <: {lhs: 'g, rhs: 'g}\n//│     'g <: Add[?] & 'd | Lit | 'e & ~#Add & ~#Lit\n//│     'e <: Nega[?] & {arg: 'arg} | 'a & ~#Nega\n//│     'arg <: Add[?] & 'b | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'arg} | 'a & ~#Nega\n//│           = [Function: prettier22]\n//│ constrain calls  : 175\n//│ annoying  calls  : 0\n//│ subtyping calls  : 877\n\n\n\n:stats\neval2 done e1\n//│ res: int\n//│    = 6\n//│ constrain calls  : 140\n//│ annoying  calls  : 60\n//│ subtyping calls  : 947\n\ne2 = add (lit 1) (nega e1)\n//│ e2: Add[Lit & {val: 1} | Nega[Add[Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}} | Lit & {val: 1}] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}\n//│ }]] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Nega[Add[Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}} | Lit & {val: 1}] with {\n//│     lhs: Lit & {val: 1},\n//│     rhs: Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}\n//│   }]\n//│ }\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Nega { arg: Add { lhs: [Lit], rhs: [Add] } }\n//│     }\n\n:stats\neval2 done e2\n//│ res: int\n//│    = -5\n//│ constrain calls  : 217\n//│ annoying  calls  : 103\n//│ subtyping calls  : 1458\n\nd2 = nega (add (lit 1) (nega (lit 1)))\n//│ d2: Nega[Add[Lit & {val: 1} | Nega[Lit & {val: 1}]] with {lhs: Lit & {val: 1}, rhs: Nega[Lit & {val: 1}]}]\n//│   = Nega { arg: Add { lhs: Lit { val: 1 }, rhs: Nega { arg: [Lit] } } }\n\n:stats\neval2 done d2\n//│ res: int\n//│    = 0\n//│ constrain calls  : 147\n//│ annoying  calls  : 71\n//│ subtyping calls  : 940\n\n\nprettier2 done\n//│ res: ('lhs -> number) -> 'a -> string\n//│   where\n//│     'a <: Add[?] & {lhs: 'lhs & 'a, rhs: 'lhs & 'a} | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'c}\n//│     'c <: Add[?] & {lhs: 'lhs & 'c, rhs: 'lhs & 'c} | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n\nprettier22 done\n//│ res: ('a -> number) -> (Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit) -> string\n//│   where\n//│     'a <: {lhs: Add[?] & 'c | Lit | 'd & ~#Add & ~#Lit, rhs: 'e}\n//│     'e <: Add[?] & {lhs: 'e, rhs: 'e} | Lit | Nega[?] & {arg: 'arg}\n//│     'c <: {lhs: 'f, rhs: 'f}\n//│     'f <: Add[?] & 'c | Lit | 'd & ~#Add & ~#Lit\n//│     'd <: Nega[?] & {arg: 'arg}\n//│     'arg <: Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'arg}\n//│    = [Function (anonymous)]\n\n:stats\nprettier2 done (eval1 done)\n//│ res: 'a -> string\n//│   where\n//│     'a <: Add[?] & {lhs: 'b & 'a, rhs: 'b & 'a} | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'd}\n//│     'd <: Add[?] & {lhs: 'b & 'd, rhs: 'b & 'd} | Lit | 'c & ~#Add & ~#Lit\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit\n//│    = [Function (anonymous)]\n//│ constrain calls  : 91\n//│ annoying  calls  : 0\n//│ subtyping calls  : 523\n\n\n\nprettier22 done (eval1 done)\n//│ res: (Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit) -> string\n//│   where\n//│     'a <: {lhs: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit, rhs: 'd} & 'e\n//│     'e <: Add[?] & {lhs: 'e, rhs: 'e} | Lit\n//│     'd <: Add[?] & {lhs: 'd, rhs: 'd} | Lit | Nega[?] & {arg: 'arg}\n//│     'c <: {lhs: 'f, rhs: 'f}\n//│     'f <: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'arg}\n//│     'arg <: Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n\n// * TODO could probably merge `c` and `b` here!\n:stats\nprettier2 done (eval2 done)\n//│ res: 'a -> string\n//│   where\n//│     'a <: Add[?] & {lhs: 'b & 'a, rhs: 'c & 'a} | Lit | 'd & ~#Add & ~#Lit\n//│     'd <: Nega[?] & {arg: 'e}\n//│     'e <: Add[?] & {lhs: 'b & 'e, rhs: 'c & 'e} | Lit | 'd & ~#Add & ~#Lit\n//│     'c <: Add[?] & {lhs: 'c, rhs: 'c} | Lit | 'f & ~#Add & ~#Lit\n//│     'f <: Nega[?] & {arg: 'c}\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit | 'g & ~#Add & ~#Lit\n//│     'g <: Nega[?] & {arg: 'b}\n//│    = [Function (anonymous)]\n//│ constrain calls  : 100\n//│ annoying  calls  : 0\n//│ subtyping calls  : 732\n\nprettier2 done (eval2 done) e2\nprettier2 done (eval2 done) d2\n//│ res: string\n//│    = '1-123'\n//│ res: string\n//│    = '-1-1'\n\n:stats\nprettier22 done (eval2 done)\nprettier22 done (eval2 done) e2\nprettier22 done (eval2 done) d2\n//│ res: (Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit) -> string\n//│   where\n//│     'a <: {lhs: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit, rhs: 'd} & 'e\n//│     'e <: Add[?] & {lhs: 'e, rhs: 'e} | Lit | 'f & ~#Add & ~#Lit\n//│     'f <: Nega[?] & {arg: 'e}\n//│     'd <: Add[?] & {lhs: 'd, rhs: 'd} | Lit | Nega[?] & {arg: 'arg}\n//│     'c <: {lhs: 'g, rhs: 'g}\n//│     'g <: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'arg}\n//│     'arg <: Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n//│ res: string\n//│    = '1-123'\n//│ res: string\n//│    = '-1'\n//│ constrain calls  : 940\n//│ annoying  calls  : 390\n//│ subtyping calls  : 7495\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n:ShowRelativeLineNums\n\n\n:stats\n:e\ndef eval1_ty_ugly = eval1\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Lit | 'a & ~#Add & ~#Lit\n//│   <:  eval1_ty_ugly:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \tdef eval1_ty_ugly = eval1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `'a & (Add[?] & ~{val: int} & ~#Add | Lit & ~{val: int} | ~{val: int} & ~#Add & ~?a)` does not have field 'val'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.71: \t  | Lit -> e.val\n//│ ║        \t           ^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.70: \trec def eval1 k e = case e of {\n//│ ╙──      \t                         ^\n//│              = [Function: eval1_ty_ugly]\n//│ constrain calls  : 105\n//│ annoying  calls  : 121\n//│ subtyping calls  : 3819\n\n:stats\n:e\neval1_ty_ugly = eval1_ty\n//│ ('a -> int) -> E1['a] -> int\n//│   <:  eval1_ty_ugly:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \teval1_ty_ugly = eval1_ty\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a & ~Add[?] & ~Lit` does not match type `Add[E1['a0]] | Lit | 'a0 & ~#Add & ~#Lit`\n//│ ║  l.132: \tdef eval1_ty_ugly: ('a -> int) -> (Lit | Add['b] | 'a & ~Lit & ~Add[?] as 'b) -> int\n//│ ║         \t                                                   ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.191: \ttype E1[A] = Lit | Add[E1[A]] | A & ~lit & ~add\n//│ ║         \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from applied type reference:\n//│ ║  l.192: \tdef eval1_ty: ('a -> int) -> E1['a] -> int\n//│ ╙──       \t                             ^^^^^^\n//│              = [Function: eval1]\n//│ constrain calls  : 53\n//│ annoying  calls  : 182\n//│ subtyping calls  : 1809\n\n\n:e\neval1 done e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \teval1 done e2\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── application of type `Nega[?E] & {Nega#E = ?E, arg: ?arg}` does not match type `nothing`\n//│ ║  l.343: \tdef nega arg = Nega { arg }\n//│ ║         \t               ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.4: \tdef done x = case x of {}\n//│ ║       \t                  ^\n//│ ╟── from field selection:\n//│ ║  l.72: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ╙──      \t                                   ^^^^^\n//│ res: error | int\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\n:e\nprettier2 done eval1 e1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.70: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.71: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.72: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.74: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.18: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '123'\n\n\n:e\n:stats\nprettier2 done (eval1 done) e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done (eval1 done) e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Nega[?E] & {Nega#E = ?E, arg: ?arg}` does not match type `nothing`\n//│ ║  l.343: \tdef nega arg = Nega { arg }\n//│ ║         \t               ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.4: \tdef done x = case x of {}\n//│ ║       \t                  ^\n//│ ╟── from field selection:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error | string\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n//│ constrain calls  : 543\n//│ annoying  calls  : 238\n//│ subtyping calls  : 6309\n\n:e\n:stats\nprettier2 done eval2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.70: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.71: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.72: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.74: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ res: error | 'a -> string\n//│   where\n//│     'a <: Add[?] & {lhs: nothing -> int & 'a, rhs: nothing -> int & 'a} | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'c}\n//│     'c <: Add[?] & {lhs: nothing -> int & 'c, rhs: nothing -> int & 'c} | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n//│ constrain calls  : 63\n//│ annoying  calls  : 0\n//│ subtyping calls  : 469\n\n:e\n:stats\nprettier2 done eval2 e1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.70: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.71: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.72: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.74: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.18: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.352: \t  | _ -> k x\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '123'\n//│ constrain calls  : 299\n//│ annoying  calls  : 108\n//│ subtyping calls  : 3130\n\n:e\n:stats\nprettier2 done eval2 e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.70: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.71: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.72: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.74: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.18: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.352: \t  | _ -> k x\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '1-123'\n//│ constrain calls  : 346\n//│ annoying  calls  : 131\n//│ subtyping calls  : 3539\n\n:e\n:stats\nprettier2 done eval2 d2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 d2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.70: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.71: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.72: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.74: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 d2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Nega[?E] & {Nega#E = ?E, arg: ?arg}` is not a function\n//│ ║  l.343: \tdef nega arg = Nega { arg }\n//│ ║         \t               ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.352: \t  | _ -> k x\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error | string\n//│    = '-1-1'\n//│ constrain calls  : 253\n//│ annoying  calls  : 95\n//│ subtyping calls  : 2422\n\n:e\n:stats\nprettier2 done eval1 e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.70: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.71: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.72: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.74: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.18: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.73: \t  | _ -> k e\n//│ ║        \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.235: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '1-123'\n//│ constrain calls  : 346\n//│ annoying  calls  : 131\n//│ subtyping calls  : 3493\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ExprProb2.mls",
    "content": "\n// --- Lit, Add ---\n\n\nclass Lit: { val: int }\nclass Add[E]: { lhs: E; rhs: E }\ndef lit val = Lit { val }\ndef add lhs rhs = Add { lhs; rhs }\n//│ Defined class Lit\n//│ Defined class Add[+E]\n//│ lit: (int & 'val) -> (Lit with {val: 'val})\n//│    = [Function: lit]\n//│ add: ('lhs & 'E) -> ('E & 'rhs) -> (Add['E] with {lhs: 'lhs, rhs: 'rhs})\n//│    = [Function: add]\n\n\n:stats\ndef eval1 eval1 e = case e of {\n  | Lit -> e.val\n  | Add -> eval1 eval1 e.lhs + eval1 eval1 e.rhs\n  }\n//│ eval1: ('a -> 'lhs -> int & 'a) -> (Add[?] & {lhs: 'lhs, rhs: 'lhs} | (Lit with {val: 'val})) -> (int | 'val)\n//│      = [Function: eval1]\n//│ constrain calls  : 36\n//│ annoying  calls  : 0\n//│ subtyping calls  : 181\n\n:stats\n:js\ndef eval1f eval1 e = case e of {\n  | Lit -> e.val\n  | Add -> eval1 e.lhs + eval1 e.rhs\n  }\n//│ // Query 1\n//│ globalThis.eval1f = function eval1f(eval1) {\n//│   return ((e) => {\n//│     let a;\n//│     return (a = e, a instanceof Lit ? e.val : a instanceof Add ? eval1(e.lhs) + eval1(e.rhs) : (() => {\n//│       throw new Error(\"non-exhaustive case expression\");\n//│     })());\n//│   });\n//│ };\n//│ // End of generated code\n//│ eval1f: ('lhs -> int) -> (Add[?] & {lhs: 'lhs, rhs: 'lhs} | (Lit with {val: 'val})) -> (int | 'val)\n//│       = [Function: eval1f]\n//│ constrain calls  : 32\n//│ annoying  calls  : 0\n//│ subtyping calls  : 161\n\n\ne1 = add (lit 1) (add (lit 2) (lit 3))\n//│ e1: Add[Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}} | Lit & {val: 1}] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}\n//│ }\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Add { lhs: Lit { val: 2 }, rhs: Lit { val: 3 } }\n//│     }\n\n\neval1 eval1! e1\n//│ res: int\n//│    = 6\n\ndef eval1_fixed_1 = eval1 eval1!\n//│ eval1_fixed_1: (Add[?] & {lhs: 'a, rhs: 'a} | (Lit with {val: 'val})) -> (int | 'val)\n//│   where\n//│     'a <: Add[?] & {lhs: 'a, rhs: 'a} | Lit\n//│              = [Function: eval1_fixed_1]\n\neval1_fixed_1 e1\n//│ res: int\n//│    = 6\n\n\nrec def eval1_fixed_2 = eval1f (fun x -> eval1f eval1_fixed_2 x)\n//│ eval1_fixed_2: (Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\\val & {val: 'val}) -> (int | 'val)\n//│   where\n//│     'lhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│     'lhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│     'rhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│     'rhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│              = [Function: eval1_fixed_2]\n\neval1_fixed_2 e1\n//│ res: int\n//│    = 6\n\n\n// Tying the knot without a recursive def:\ndef eval1_fixed_3 =\n  let fixed fixed = eval1f (fun x -> eval1f (fixed fixed) x)\n  in fixed fixed!\n//│ eval1_fixed_3: (Add[?] & {\n//│   lhs: Add[?] & {\n//│     lhs: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit,\n//│     rhs: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│   } | Lit,\n//│   rhs: Add[?] & {\n//│     lhs: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit,\n//│     rhs: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│   } | Lit\n//│ } | Lit\\val & {val: 'val}) -> (int | 'val)\n//│ where\n//│   'lhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│   'lhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│   'rhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│   'rhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│              = [Function: eval1_fixed_3]\n\neval1_fixed_3 e1\n//│ res: int\n//│    = 6\n\n\n\n// --- Nega ---\n\n\nclass Nega[E]: { arg: E }\ndef nega arg = Nega { arg }\n//│ Defined class Nega[+E]\n//│ nega: 'arg -> Nega['arg]\n//│     = [Function: nega]\n\n\ndef eval2 eval2 e = case e of {\n  | Nega -> 0 - (eval2 eval2 e.arg)\n  | _ -> eval1 eval2 e\n  }\n//│ eval2: ('a -> 'lhs -> int & 'a) -> (Add[?] & {lhs: 'lhs, rhs: 'lhs} | (Lit with {val: 'val}) | Nega[?] & {arg: 'lhs}) -> (int | 'val)\n//│      = [Function: eval2]\n\ndef eval2f eval2 e = case e of {\n  | Nega -> 0 - (eval2 e.arg)\n  | _ -> eval1f eval2 e\n  }\n//│ eval2f: ('arg -> int) -> (Add[?] & {lhs: 'arg, rhs: 'arg} | (Lit with {val: 'val}) | Nega[?] & {arg: 'arg}) -> (int | 'val)\n//│       = [Function: eval2f]\n\n\ne2 = add (lit 1) (nega e1)\n//│ e2: Add[Lit & {val: 1} | Nega[Add[Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}} | Lit & {val: 1}] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}\n//│ }]] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Nega[Add[Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}} | Lit & {val: 1}] with {\n//│     lhs: Lit & {val: 1},\n//│     rhs: Add[Lit & {val: 2 | 3}] & {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}\n//│   }]\n//│ }\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Nega { arg: Add { lhs: [Lit], rhs: [Add] } }\n//│     }\n\n\ndef eval2_fixed_1 = eval2 eval2!\n//│ eval2_fixed_1: (Add[?] & {lhs: 'a, rhs: 'a} | (Lit with {val: 'val}) | Nega[?] & {arg: 'a}) -> (int | 'val)\n//│   where\n//│     'a <: Add[?] & {lhs: 'a, rhs: 'a} | Lit | Nega[?] & {arg: 'a}\n//│              = [Function: eval2_fixed_1]\n\neval2_fixed_1 e1\neval2_fixed_1 e2\n//│ res: int\n//│    = 6\n//│ res: int\n//│    = -5\n\ndef fix f = let fixed = fun x -> f (fun v -> (x x) v) in fixed fixed!\n//│ fix: (('a -> 'b) -> ('a -> 'b & 'c)) -> 'c\n//│    = [Function: fix]\n\ndef eval2_fixed_2 = fix eval2f\n//│ eval2_fixed_2: (Add[?] & {lhs: 'a, rhs: 'a} | (Lit with {val: 'val}) | Nega[?] & {arg: 'a}) -> (int | 'val)\n//│   where\n//│     'a <: Add[?] & {lhs: 'a, rhs: 'a} | Lit | Nega[?] & {arg: 'a}\n//│              = [Function: eval2_fixed_2]\n\n:stats\neval2_fixed_2 e1\n//│ res: int\n//│    = 6\n//│ constrain calls  : 267\n//│ annoying  calls  : 140\n//│ subtyping calls  : 1865\n\n:stats\neval2_fixed_2 e2\n//│ res: int\n//│    = -5\n//│ constrain calls  : 648\n//│ annoying  calls  : 345\n//│ subtyping calls  : 5049\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n\n:ge\nlet rec eval1_fixed = eval1f (eval1f eval1_fixed) in eval1_fixed e1\n//│ res: int\n//│ Code generation encountered an error:\n//│   recursive non-function definition eval1_fixed is not supported\n\n:js\nrec def eval1_fixed = eval1f (eval1f eval1_fixed)\n//│ // Query 1\n//│ globalThis[\"eval1_fixed\"] = function eval1_fixed() {\n//│   return eval1f(eval1f(eval1_fixed()));\n//│ };\n//│ // End of generated code\n//│ eval1_fixed: (Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\\val & {val: 'val}) -> (int | 'val)\n//│   where\n//│     'lhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│     'lhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│     'rhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│     'rhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│            = [Function: eval1_fixed]\n\n:re\neval1_fixed e1\n//│ res: int\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\nrec def eval1_fixed() = eval1f (eval1f (eval1_fixed()))\n//│ eval1_fixed: () -> (Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\\val & {val: 'val}) -> (int | 'val)\n//│   where\n//│     'lhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│     'lhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│     'rhs <: Add[?] & {lhs: 'lhs0, rhs: 'rhs0} | Lit\n//│     'rhs0 <: Add[?] & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│            = [Function: eval1_fixed1]\n\n:re\neval1_fixed() e1\n//│ res: int\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\n\ndef eval1_fixed = eval1f (fun x -> eval1f eval1f x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tdef eval1_fixed = eval1f (fun x -> eval1f eval1f x)\n//│ ║        \t                                   ^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?val | ?b)` is not an instance of type `int`\n//│ ║  l.30: \tdef eval1f eval1 e = case e of {\n//│ ║        \t                 ^^^^^^^^^^^^^^^\n//│ ║  l.31: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.33: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ╙──      \t                         ^^^^^^^^^^^\n//│ eval1_fixed: (Add[?] & {\n//│   lhs: Add[?] & {lhs: nothing -> int, rhs: nothing -> int} | Lit,\n//│   rhs: Add[?] & {lhs: nothing -> int, rhs: nothing -> int} | Lit\n//│ } | (Lit with {val: 'val})) -> (int | 'val)\n\nrec def eval1_fixed = eval1f (fun x -> eval1_fixed eval1_fixed x)\n//│ ╔══[ERROR] Type mismatch in binding of application:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f (fun x -> eval1_fixed eval1_fixed x)\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?val | ?b)` does not match type `Add[?] & ?c | Lit & ?d`\n//│ ║  l.30: \tdef eval1f eval1 e = case e of {\n//│ ║        \t                 ^^^^^^^^^^^^^^^\n//│ ║  l.31: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.33: \t  }\n//│ ║        \t^^^\n//│ ╟── but it flows into application with expected type `Add[?] & ?e | Lit & ?f`\n//│ ║  l.+1: \trec def eval1_fixed = eval1f (fun x -> eval1_fixed eval1_fixed x)\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.30: \tdef eval1f eval1 e = case e of {\n//│ ╙──      \t                          ^\n//│ ╔══[ERROR] Type mismatch in binding of application:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f (fun x -> eval1_fixed eval1_fixed x)\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` is not a function\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ║        \t           ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f (fun x -> eval1_fixed eval1_fixed x)\n//│ ║        \t                                       ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from application:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f (fun x -> eval1_fixed eval1_fixed x)\n//│ ╙──      \t                                       ^^^^^^^^^^^^^^^^^^^^^^^\n//│ eval1_fixed: (Add[?] | (Lit with {val: 'val})) -> (int | 'val)\n\n:e\nrec def eval1_fixed = eval1f eval1_fixed e1\n//│ ╔══[ERROR] Type mismatch in binding of application:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f eval1_fixed e1\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` is not a function\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ║        \t           ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `?rhs -> ?a`\n//│ ║  l.+1: \trec def eval1_fixed = eval1f eval1_fixed e1\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ║        \t                         ^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f eval1_fixed e1\n//│ ╙──      \t                             ^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in binding of application:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f eval1_fixed e1\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` is not a function\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ║        \t           ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `?lhs -> ?a`\n//│ ║  l.+1: \trec def eval1_fixed = eval1f eval1_fixed e1\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.32: \t  | Add -> eval1 e.lhs + eval1 e.rhs\n//│ ║        \t           ^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.+1: \trec def eval1_fixed = eval1f eval1_fixed e1\n//│ ╙──      \t                             ^^^^^^^^^^^\n//│ eval1_fixed: int\n\n\ndef eval2_broken eval2 e = case e of {\n  | Nega -> e.arg\n  | _ -> eval1 eval2 e\n  }\n//│ eval2_broken: ('a -> 'lhs -> int & 'a) -> (Add[?] & {lhs: 'lhs, rhs: 'lhs} | (Lit with {val: 'arg}) | Nega[?] & {arg: 'arg}) -> (int | 'arg)\n\n:e\neval2_broken eval2_broken! e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \teval2_broken eval2_broken! e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Add[?E] & {Add#E = ?E, lhs: ?lhs, rhs: ?rhs}` is not an instance of type `int`\n//│ ║  l.8: \tdef add lhs rhs = Add { lhs; rhs }\n//│ ║       \t                  ^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.20: \t  | Add -> eval1 eval1 e.lhs + eval1 eval1 e.rhs\n//│ ║        \t                               ^^^^^^^^^^^^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.345: \t  | Nega -> e.arg\n//│ ╙──       \t            ^^^^^\n//│ res: error | int\n\n\ndef eval2f_oops eval2 e = case e of {\n  | Nega -> 0 - (eval2 e.arg)\n  | _ -> eval1 eval2 e // should be: eval1f eval2 e\n  }\n//│ eval2f_oops: ('arg -> int & 'a -> 'lhs -> int & 'a) -> (Add[?] & {lhs: 'lhs, rhs: 'lhs} | (Lit with {val: 'val}) | Nega[?] & {arg: 'arg}) -> (int | 'val)\n\n// :e\nfix eval2f_oops e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tfix eval2f_oops e2\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b)` does not match type `Add[?] & ?c | Lit & ?d`\n//│ ║  l.173: \tdef fix f = let fixed = fun x -> f (fun v -> (x x) v) in fixed fixed!\n//│ ║         \t                                    ^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.18: \tdef eval1 eval1 e = case e of {\n//│ ║        \t                         ^\n//│ ╟── from reference:\n//│ ║  l.367: \tdef eval2f_oops eval2 e = case e of {\n//│ ╙──       \t                               ^\n//│ res: error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ExprProb_Inv.mls",
    "content": "\ndef intToString: int -> string\ndef intToString x = toString x\ndef done x = case x of {}\n//│ intToString: int -> string\n//│            = <missing implementation>\n//│ anything -> string\n//│   <:  intToString:\n//│ int -> string\n//│            = [Function: intToString]\n//│ done: nothing -> nothing\n//│     = [Function: done]\n\n\n\nclass Lit: { val: int }\nclass Add[E]: { lhs: E; rhs: E }\n  method Inv (x: E) = x\ndef lit val = Lit { val }\ndef add lhs rhs = Add { lhs; rhs }\n//│ Defined class Lit\n//│ Defined class Add[=E]\n//│ Defined Add.Inv: Add['E] -> 'E -> 'E\n//│ lit: (int & 'val) -> (Lit with {val: 'val})\n//│    = [Function: lit]\n//│ add: ('lhs & 'E) -> ('E & 'rhs) -> (Add['E] with {lhs: 'lhs, rhs: 'rhs})\n//│    = [Function: add]\n\n\n\nrec def eval1_stub k e = case e of {\n  | Add -> eval1_stub k e.lhs\n  | _ -> k e\n  }\n//│ eval1_stub: ('a -> 'b) -> 'c -> 'b\n//│   where\n//│     'c <: (Add[?]\\rhs with {lhs: 'c}) | 'a & ~#Add\n//│           = [Function: eval1_stub]\n\nrec def eval1_stub k e = case e of {\n  | Add -> eval1_stub k e.lhs + eval1_stub k e.rhs\n  | _ -> k e\n  }\n//│ eval1_stub: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | 'a & ~#Add\n//│           = [Function: eval1_stub1]\n\n:ns\nrec def eval1_stub e = case e of {\n  | Lit -> 1\n  | Add -> eval1_stub e.lhs\n  | _ -> 0\n  }\n//│ eval1_stub: forall 'eval1_stub 'a 'b 'c 'lhs 'd 'e. 'eval1_stub\n//│   where\n//│     'eval1_stub := 'a -> (1 | 'd | 0)\n//│     'd :> 1 | 'd | 0\n//│     'a <: #Lit & 'b | (#Add & 'c | 'e & ~#Add) & ~#Lit\n//│     'c <: {lhs: 'lhs}\n//│     'lhs <: 'a\n//│           = [Function: eval1_stub2]\n\neval1_stub\n//│ res: 'a -> (0 | 1)\n//│   where\n//│     'a <: (Add[?]\\rhs with {lhs: 'a}) | Lit | ~Add[?] & ~Lit\n//│    = [Function: eval1_stub2]\n\n// def eval1: ('b -> int) -> Expr['b] -> int\n:stats\nrec def eval1 k e = case e of {\n  | Lit -> e.val\n  | Add -> eval1 k e.lhs + eval1 k e.rhs\n  | _ -> k e\n  }\n//│ eval1: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | Lit | 'a & ~#Add & ~#Lit\n//│      = [Function: eval1]\n//│ constrain calls  : 73\n//│ annoying  calls  : 0\n//│ subtyping calls  : 307\n\n:ns\neval1\n//│ res: forall 'eval1 'a 'b 'c 'val 'd 'lhs 'rhs 'e 'f 'g. 'eval1\n//│   where\n//│     'eval1 := 'a -> 'b -> ('val | 'e | 'g)\n//│     'e := int\n//│     'b <: #Lit & 'c | (#Add & 'd | 'f & ~#Add) & ~#Lit\n//│     'd <: {rhs: 'rhs} & {lhs: 'lhs}\n//│     'lhs <: 'b\n//│     'rhs <: 'b\n//│     'c <: {val: 'val}\n//│     'val <: int\n//│     'a <: 'f -> 'g\n//│     'g <: int\n//│    = [Function: eval1]\n\n:re\nerror: ~Add[?]\n//│ res: ~Add[?]\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: ('a & ~Lit) -> 'a\n//│ res: ('a & ~Lit) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: ('a) -> ('a & Add[?])\nerror: ('a) -> ('a & ~Add[?])\nerror: ('a & ~Add[?]) -> 'a\n//│ res: 'a -> (Add[?] & 'a)\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res: 'a -> ('a & ~Add[?])\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res: ('a & ~Add[?]) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: ('a & ~add) -> 'a\n//│ res: ('a & ~#Add) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:ns\ndef eval1_ty_ugly: ('a -> int) -> (Lit | Add['b] | 'a & ~Lit & ~Add[?] as 'b) -> int\n//│ eval1_ty_ugly: forall 'a 'b. ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Lit | Add['b] | 'a & ~Lit & ~Add[?]\n//│              = <missing implementation>\n\neval1_ty_ugly\n//│ res: ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│    = <no result>\n//│      eval1_ty_ugly is not implemented\n\n:ns\ndef eval1_ty: ('a -> int) -> (Lit | Add['b] | 'a & ~lit & ~add as 'b) -> int\n//│ eval1_ty: forall 'a 'b. ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Lit | Add['b] | 'a & ~#Lit & ~#Add\n//│         = <missing implementation>\n\neval1_ty\n//│ res: ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Add['b] | Lit | 'a & ~#Add & ~#Lit\n//│    = <no result>\n//│      eval1_ty is not implemented\n\n:stats\ndef eval1_ty = eval1\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | Lit | 'a & ~#Add & ~#Lit\n//│   <:  eval1_ty:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Add['b] | Lit | 'a & ~#Add & ~#Lit\n//│         = [Function: eval1_ty]\n//│ constrain calls  : 71\n//│ annoying  calls  : 37\n//│ subtyping calls  : 588\n\n:stats\neval1_ty = eval1_ty_ugly\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│   <:  eval1_ty:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Add['b] | Lit | 'a & ~#Add & ~#Lit\n//│         = <no result>\n//│           eval1_ty_ugly is not implemented\n//│ constrain calls  : 4870\n//│ annoying  calls  : 1519\n//│ subtyping calls  : 668110\n\n\n// Workaround:\n:ns\ntype E1[A] = Lit | Add[E1[A]] | A & ~lit & ~add\ndef eval1_ty: ('a -> int) -> E1['a] -> int\n//│ Defined type alias E1[=A]\n//│ eval1_ty: forall 'a. ('a -> int) -> E1['a] -> int\n//│         = <missing implementation>\n\neval1_ty\n//│ res: ('a -> int) -> E1['a] -> int\n//│    = <no result>\n//│      eval1_ty is not implemented\n\n:stats\ndef eval1_ty = eval1\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | Lit | 'a & ~#Add & ~#Lit\n//│   <:  eval1_ty:\n//│ ('a -> int) -> E1['a] -> int\n//│         = [Function: eval1_ty1]\n//│ constrain calls  : 67\n//│ annoying  calls  : 37\n//│ subtyping calls  : 487\n\n\n:stats\nrec def pretty1 k e = case e of {\n  | Lit -> intToString e.val\n  | Add -> concat (pretty1 k e.lhs) (pretty1 k e.rhs)\n  | _ -> k e\n  }\n//│ pretty1: ('a -> string) -> 'b -> string\n//│   where\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | Lit | 'a & ~#Add & ~#Lit\n//│        = [Function: pretty1]\n//│ constrain calls  : 81\n//│ annoying  calls  : 0\n//│ subtyping calls  : 342\n\n\n:stats\nrec def prettier1 k ev e = case e of {\n  | Lit -> intToString e.val\n  | Add ->\n      if ev e.lhs == 0 then prettier1 k ev e.rhs\n      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n      else concat (prettier1 k ev e.lhs) (prettier1 k ev e.rhs)\n  | _ -> k e\n  }\n//│ prettier1: ('a -> string) -> ('lhs -> number) -> 'b -> string\n//│   where\n//│     'b <: (Add[?] with {lhs: 'lhs & 'b, rhs: 'lhs & 'b}) | Lit | 'a & ~#Add & ~#Lit\n//│          = [Function: prettier1]\n//│ constrain calls  : 260\n//│ annoying  calls  : 0\n//│ subtyping calls  : 854\n\n:stats\nrec def prettier11 k ev e = case e of {\n  | Lit -> intToString e.val\n  | Add ->\n      let tmp = pretty1 k e.lhs\n      in if ev e.rhs == 0 then tmp else concat tmp (prettier11 k ev e.rhs)\n  | _ -> k e\n  }\n//│ prettier11: ('a -> string) -> ('rhs -> number) -> 'b -> string\n//│   where\n//│     'b <: (Add[?] with {lhs: Add[?] & 'c | Lit | 'a & ~#Add & ~#Lit, rhs: 'rhs & 'b}) | Lit | 'a & ~#Add & ~#Lit\n//│     'c <: {lhs: 'd, rhs: 'd}\n//│     'd <: Add[?] & 'c | Lit | 'a & ~#Add & ~#Lit\n//│           = [Function: prettier11]\n//│ constrain calls  : 178\n//│ annoying  calls  : 0\n//│ subtyping calls  : 758\n\n// Doesn't make much sense, but generates very ugly type unless aggressively simplified:\n:stats\nrec def prettier12 k ev e = case e of {\n  | Lit -> intToString e.val\n  | Add ->\n      let tmp = pretty1 k e.lhs\n      in if ev e == 0 then tmp else concat tmp (pretty1 k e.rhs)\n  | _ -> k e\n  }\n//│ prettier12: ('a -> string & 'b -> 'c) -> ('d -> number) -> ((Add[?] with {lhs: Add[?] & 'e | Lit | 'a & ~#Add & ~#Lit, rhs: 'f}) & 'd | Lit | 'b & ~#Add & ~#Lit) -> (string | 'c)\n//│   where\n//│     'f <: (Add[?] with {lhs: 'f, rhs: 'f}) | Lit | 'a & ~#Add & ~#Lit\n//│     'e <: {lhs: 'g, rhs: 'g}\n//│     'g <: Add[?] & 'e | Lit | 'a & ~#Add & ~#Lit\n//│           = [Function: prettier12]\n//│ constrain calls  : 158\n//│ annoying  calls  : 0\n//│ subtyping calls  : 834\n\n\n:stats\ne1 = Add{lhs = Lit {val = 1}; rhs = Add{lhs = Lit {val = 2}; rhs = Lit {val = 3}}}\neval1 done e1\npretty1 done e1\nprettier1 done (eval1 done) e1\nprettier11 done (eval1 done) e1\nprettier12 done (eval1 done) e1\n//│ e1: Add['E] with {lhs: Lit & {val: 1}, rhs: Add['E0] with {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}}\n//│   where\n//│     'E :> (Add['E0] with {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}) | Lit & {val: 1}\n//│     'E0 :> Lit & {val: 2 | 3}\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Add { lhs: Lit { val: 2 }, rhs: Lit { val: 3 } }\n//│     }\n//│ res: int\n//│    = 6\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ constrain calls  : 1109\n//│ annoying  calls  : 500\n//│ subtyping calls  : 9272\n\n\ne1 = add (lit 1) (add (lit 2) (lit 3))\neval1 done e1\npretty1 done e1\nprettier1 done (eval1 done) e1\nprettier11 done (eval1 done) e1\nprettier12 done (eval1 done) e1\n//│ e1: Add['E] with {lhs: Lit & {val: 1}, rhs: Add['E0] with {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}}\n//│   where\n//│     'E :> (Add['E0] with {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}) | Lit & {val: 1}\n//│     'E0 :> Lit & {val: 2 | 3}\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Add { lhs: Lit { val: 2 }, rhs: Lit { val: 3 } }\n//│     }\n//│ res: int\n//│    = 6\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n//│ res: string\n//│    = '123'\n\n\n\nclass Nega[E]: { arg: E }\ndef nega arg = Nega { arg }\n//│ Defined class Nega[+E]\n//│ nega: 'arg -> Nega['arg]\n//│     = [Function: nega]\n\n\n\nrec def eval2 k = eval1 (fun x -> case x of {\n  | Nega -> 0 - (eval2 k x.arg)\n  | _ -> k x\n  })\n//│ eval2: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add[?]\\lhs\\rhs & {lhs: 'b, rhs: 'b} | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'd} | 'a & ~#Nega\n//│     'd <: Add[?]\\lhs\\rhs & {lhs: 'd, rhs: 'd} | Lit | 'c & ~#Add & ~#Lit\n//│      = [Function: eval2]\n\n\n:stats\nrec def prettier2 k ev = prettier1 (fun x -> case x of {\n  | Nega -> concat \"-\" (prettier2 k ev x.arg)\n  | _ -> k x\n  }) ev\n//│ prettier2: ('a -> string) -> ('lhs -> number) -> 'b -> string\n//│   where\n//│     'b <: Add[?]\\lhs\\rhs & {lhs: 'lhs & 'b, rhs: 'lhs & 'b} | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'd} | 'a & ~#Nega\n//│     'd <: Add[?]\\lhs\\rhs & {lhs: 'lhs & 'd, rhs: 'lhs & 'd} | Lit | 'c & ~#Add & ~#Lit\n//│          = [Function: prettier2]\n//│ constrain calls  : 116\n//│ annoying  calls  : 0\n//│ subtyping calls  : 549\n\n:stats\nrec def prettier22 k ev = prettier12 (fun x -> case x of {\n  | Nega -> concat \"-\" (prettier22 k ev x.arg)\n  | _ -> k x\n  }) ev\n//│ prettier22: ('a -> string) -> ('b -> number) -> (Add[?] & 'b | Lit | 'c & ~#Add & ~#Lit) -> string\n//│   where\n//│     'b <: {lhs: Add[?] & 'd | Lit | 'e & ~#Add & ~#Lit, rhs: 'f}\n//│     'f <: Add[?]\\lhs\\rhs & {lhs: 'f, rhs: 'f} | Lit | Nega[?] & {arg: 'arg} | 'a & ~#Add & ~#Lit & ~#Nega\n//│     'd <: {lhs: 'g, rhs: 'g}\n//│     'g <: Add[?] & 'd | Lit | 'e & ~#Add & ~#Lit\n//│     'e <: Nega[?] & {arg: 'arg} | 'a & ~#Nega\n//│     'arg <: Add[?] & 'b | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'arg} | 'a & ~#Nega\n//│           = [Function: prettier22]\n//│ constrain calls  : 175\n//│ annoying  calls  : 0\n//│ subtyping calls  : 897\n\n\n\n:stats\neval2 done e1\n//│ res: int\n//│    = 6\n//│ constrain calls  : 140\n//│ annoying  calls  : 60\n//│ subtyping calls  : 947\n\ne2 = add (lit 1) (nega e1)\n//│ e2: Add['E] with {\n//│   lhs: Lit & {val: 1},\n//│   rhs: Nega[forall 'E0 'E1. Add['E0] with {lhs: Lit & {val: 1}, rhs: Add['E1] with {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}}]\n//│ }\n//│ where\n//│   'E :> Lit & {val: 1} | Nega[forall 'E0 'E1. Add['E0] with {lhs: Lit & {val: 1}, rhs: Add['E1] with {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}}]\n//│   'E0 :> (Add['E1] with {lhs: Lit & {val: 2}, rhs: Lit & {val: 3}}) | Lit & {val: 1}\n//│   'E1 :> Lit & {val: 2 | 3}\n//│   = Add {\n//│       lhs: Lit { val: 1 },\n//│       rhs: Nega { arg: Add { lhs: [Lit], rhs: [Add] } }\n//│     }\n\n:stats\neval2 done e2\n//│ res: int\n//│    = -5\n//│ constrain calls  : 217\n//│ annoying  calls  : 103\n//│ subtyping calls  : 1458\n\nd2 = nega (add (lit 1) (nega (lit 1)))\n//│ d2: Nega[Add['E] with {lhs: Lit & {val: 1}, rhs: Nega[Lit & {val: 1}]}]\n//│   where\n//│     'E :> Lit & {val: 1} | Nega[Lit & {val: 1}]\n//│   = Nega { arg: Add { lhs: Lit { val: 1 }, rhs: Nega { arg: [Lit] } } }\n\n:stats\neval2 done d2\n//│ res: int\n//│    = 0\n//│ constrain calls  : 147\n//│ annoying  calls  : 71\n//│ subtyping calls  : 940\n\n\nprettier2 done\n//│ res: ('lhs -> number) -> 'a -> string\n//│   where\n//│     'a <: Add[?]\\lhs\\rhs & {lhs: 'lhs & 'a, rhs: 'lhs & 'a} | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'c}\n//│     'c <: Add[?]\\lhs\\rhs & {lhs: 'lhs & 'c, rhs: 'lhs & 'c} | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n\nprettier22 done\n//│ res: ('a -> number) -> (Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit) -> string\n//│   where\n//│     'a <: {lhs: Add[?] & 'c | Lit | 'd & ~#Add & ~#Lit, rhs: 'e}\n//│     'e <: Add[?]\\lhs\\rhs & {lhs: 'e, rhs: 'e} | Lit | Nega[?] & {arg: 'arg}\n//│     'c <: {lhs: 'f, rhs: 'f}\n//│     'f <: Add[?] & 'c | Lit | 'd & ~#Add & ~#Lit\n//│     'd <: Nega[?] & {arg: 'arg}\n//│     'arg <: Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'arg}\n//│    = [Function (anonymous)]\n\n:stats\nprettier2 done (eval1 done)\n//│ res: 'a -> string\n//│   where\n//│     'a <: Add[?]\\lhs\\rhs & {lhs: 'b & 'a, rhs: 'b & 'a} | Lit | 'c & ~#Add & ~#Lit\n//│     'c <: Nega[?] & {arg: 'd}\n//│     'd <: Add[?]\\lhs\\rhs & {lhs: 'b & 'd, rhs: 'b & 'd} | Lit | 'c & ~#Add & ~#Lit\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | Lit\n//│    = [Function (anonymous)]\n//│ constrain calls  : 91\n//│ annoying  calls  : 0\n//│ subtyping calls  : 616\n\n\nprettier22 done (eval1 done)\n//│ res: (Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit) -> string\n//│   where\n//│     'a <: {lhs: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit, rhs: 'd} & 'e\n//│     'e <: (Add[?] with {lhs: 'e, rhs: 'e}) | Lit\n//│     'd <: (Add[?] with {lhs: 'd, rhs: 'd}) | Lit | Nega[?] & {arg: 'arg}\n//│     'c <: {lhs: 'f, rhs: 'f}\n//│     'f <: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'arg}\n//│     'arg <: Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n\n// TODO could probably merge `a` and `b` here!\n:stats\nprettier2 done (eval2 done)\n//│ res: 'a -> string\n//│   where\n//│     'a <: Add[?]\\lhs\\rhs & {lhs: 'b & 'a, rhs: 'c & 'a} | Lit | 'd & ~#Add & ~#Lit\n//│     'd <: Nega[?] & {arg: 'e}\n//│     'e <: Add[?]\\lhs\\rhs & {lhs: 'b & 'e, rhs: 'c & 'e} | Lit | 'd & ~#Add & ~#Lit\n//│     'c <: (Add[?] with {lhs: 'c, rhs: 'c}) | Lit | 'f & ~#Add & ~#Lit\n//│     'f <: Nega[?] & {arg: 'c}\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | Lit | 'g & ~#Add & ~#Lit\n//│     'g <: Nega[?] & {arg: 'b}\n//│    = [Function (anonymous)]\n//│ constrain calls  : 100\n//│ annoying  calls  : 0\n//│ subtyping calls  : 864\n\nprettier2 done (eval2 done) e2\nprettier2 done (eval2 done) d2\n//│ res: string\n//│    = '1-123'\n//│ res: string\n//│    = '-1-1'\n\n:stats\nprettier22 done (eval2 done)\nprettier22 done (eval2 done) e2\nprettier22 done (eval2 done) d2\n//│ res: (Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit) -> string\n//│   where\n//│     'a <: {lhs: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit, rhs: 'd} & 'e\n//│     'e <: (Add[?] with {lhs: 'e, rhs: 'e}) | Lit | 'f & ~#Add & ~#Lit\n//│     'f <: Nega[?] & {arg: 'e}\n//│     'd <: (Add[?] with {lhs: 'd, rhs: 'd}) | Lit | Nega[?] & {arg: 'arg}\n//│     'c <: {lhs: 'g, rhs: 'g}\n//│     'g <: Add[?] & 'c | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'arg}\n//│     'arg <: Add[?] & 'a | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n//│ res: string\n//│    = '1-123'\n//│ res: string\n//│    = '-1'\n//│ constrain calls  : 940\n//│ annoying  calls  : 390\n//│ subtyping calls  : 7554\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n:ShowRelativeLineNums\n\n\n:stats\n:e\ndef eval1_ty_ugly = eval1\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: (Add[?] with {lhs: 'b, rhs: 'b}) | Lit | 'a & ~#Add & ~#Lit\n//│   <:  eval1_ty_ugly:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \tdef eval1_ty_ugly = eval1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `'a & (Add[?] & ~{val: int} & ~#Add | Lit & ~{val: int} | ~{val: int} & ~#Add & ~?a)` does not have field 'val'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.73: \t  | Lit -> e.val\n//│ ║        \t           ^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.72: \trec def eval1 k e = case e of {\n//│ ╙──      \t                         ^\n//│              = [Function: eval1_ty_ugly]\n//│ constrain calls  : 105\n//│ annoying  calls  : 121\n//│ subtyping calls  : 3763\n\n:stats\n:e\neval1_ty_ugly = eval1_ty\n//│ ('a -> int) -> E1['a] -> int\n//│   <:  eval1_ty_ugly:\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b := Add['b] | Lit | 'a & ~Add[?] & ~Lit\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \teval1_ty_ugly = eval1_ty\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a & ~Add[?] & ~Lit` does not match type `Add[E1['a0]] | Lit | 'a0 & ~#Add & ~#Lit`\n//│ ║  l.134: \tdef eval1_ty_ugly: ('a -> int) -> (Lit | Add['b] | 'a & ~Lit & ~Add[?] as 'b) -> int\n//│ ║         \t                                                   ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.193: \ttype E1[A] = Lit | Add[E1[A]] | A & ~lit & ~add\n//│ ║         \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from applied type reference:\n//│ ║  l.194: \tdef eval1_ty: ('a -> int) -> E1['a] -> int\n//│ ╙──       \t                             ^^^^^^\n//│              = [Function: eval1]\n//│ constrain calls  : 200\n//│ annoying  calls  : 9801\n//│ subtyping calls  : 21512\n\n\n:e\neval1 done e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \teval1 done e2\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── application of type `Nega[?E] & {Nega#E = ?E, arg: ?arg}` does not match type `nothing`\n//│ ║  l.345: \tdef nega arg = Nega { arg }\n//│ ║         \t               ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.4: \tdef done x = case x of {}\n//│ ║       \t                  ^\n//│ ╟── from field selection:\n//│ ║  l.74: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ╙──      \t                                   ^^^^^\n//│ res: error | int\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\n:e\nprettier2 done eval1 e1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.72: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.74: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.76: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.19: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '123'\n\n\n:e\n:stats\nprettier2 done (eval1 done) e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done (eval1 done) e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Nega[?E] & {Nega#E = ?E, arg: ?arg}` does not match type `nothing`\n//│ ║  l.345: \tdef nega arg = Nega { arg }\n//│ ║         \t               ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.4: \tdef done x = case x of {}\n//│ ║       \t                  ^\n//│ ╟── from field selection:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error | string\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n//│ constrain calls  : 543\n//│ annoying  calls  : 238\n//│ subtyping calls  : 6175\n\n:e\n:stats\nprettier2 done eval2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.72: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.74: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.76: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ res: error | 'a -> string\n//│   where\n//│     'a <: Add[?]\\lhs\\rhs & {lhs: nothing -> int & 'a, rhs: nothing -> int & 'a} | Lit | 'b & ~#Add & ~#Lit\n//│     'b <: Nega[?] & {arg: 'c}\n//│     'c <: Add[?]\\lhs\\rhs & {lhs: nothing -> int & 'c, rhs: nothing -> int & 'c} | Lit | 'b & ~#Add & ~#Lit\n//│    = [Function (anonymous)]\n//│ constrain calls  : 63\n//│ annoying  calls  : 0\n//│ subtyping calls  : 517\n\n:e\n:stats\nprettier2 done eval2 e1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.72: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.74: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.76: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.19: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.354: \t  | _ -> k x\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '123'\n//│ constrain calls  : 299\n//│ annoying  calls  : 108\n//│ subtyping calls  : 3050\n\n:e\n:stats\nprettier2 done eval2 e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.72: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.74: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.76: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.19: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.354: \t  | _ -> k x\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '1-123'\n//│ constrain calls  : 346\n//│ annoying  calls  : 131\n//│ subtyping calls  : 3457\n\n:e\n:stats\nprettier2 done eval2 d2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 d2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.72: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.74: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.76: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval2 d2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Nega[?E] & {Nega#E = ?E, arg: ?arg}` is not a function\n//│ ║  l.345: \tdef nega arg = Nega { arg }\n//│ ║         \t               ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.354: \t  | _ -> k x\n//│ ║         \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error | string\n//│    = '-1-1'\n//│ constrain calls  : 253\n//│ annoying  calls  : 95\n//│ subtyping calls  : 2432\n\n:e\n:stats\nprettier2 done eval1 e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b | ?c)` is not an instance of type `number`\n//│ ║  l.72: \trec def eval1 k e = case e of {\n//│ ║        \t                ^^^^^^^^^^^^^^^\n//│ ║  l.73: \t  | Lit -> e.val\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ║  l.74: \t  | Add -> eval1 k e.lhs + eval1 k e.rhs\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.76: \t  }\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t              ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tprettier2 done eval1 e2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.19: \tdef lit val = Lit { val }\n//│ ║        \t              ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.75: \t  | _ -> k e\n//│ ║        \t         ^^^\n//│ ╟── from field selection:\n//│ ║  l.237: \t      else if ev e.rhs == 0 then prettier1 k ev e.lhs\n//│ ╙──       \t                 ^^^^^\n//│ res: error\n//│    = '1-123'\n//│ constrain calls  : 346\n//│ annoying  calls  : 131\n//│ subtyping calls  : 3407\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/FatNegs.mls",
    "content": "\nclass Lit: { n: int }\n//│ Defined class Lit\n\n// TODO should eventually print these differently or make them truly equivalent\n//  by making #Lit <: Lit, i.e. making the tags include the fields implicitly.\n\n// * Q: What happens if one writes ~Lit instead of ~#Lit?\ndef nc: ~Lit\ndef nt: ~#Lit\n//│ nc: ~Lit\n//│   = <missing implementation>\n//│ nt: ~Lit\n//│   = <missing implementation>\n\n// * A: It's not equivalent.\n\n// * Demonstrates that the negated tag is a subtype of the whole negated class:\nnc = nt\n//│ ~Lit\n//│   <:  nc:\n//│ ~Lit\n//│   = <no result>\n//│     nt is not implemented\n\n// * Demonstrates that the negated tag is not a supertype of the whole negated class:\n:e\nnt = nc\n//│ ~Lit\n//│   <:  nt:\n//│ ~Lit\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.28: \tnt = nc\n//│ ║        \t^^^^^^^\n//│ ╟── type `Lit` does not have field 'n'\n//│ ║  l.9: \tdef nc: ~Lit\n//│ ║       \t        ^^^^\n//│ ╟── but it flows into reference with expected type `{n: int}`\n//│ ║  l.28: \tnt = nc\n//│ ║        \t     ^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.2: \tclass Lit: { n: int }\n//│ ║       \t           ^^^^^^^^^^\n//│ ╟── from type negation:\n//│ ║  l.10: \tdef nt: ~#Lit\n//│ ╙──      \t        ^^^^^\n//│   = <no result>\n//│     nc and nt are not implemented\n\nnc = nc\n//│ ~Lit\n//│   <:  nc:\n//│ ~Lit\n//│   = <no result>\n//│     nc and nt are not implemented\n\nnt = nt\n//│ ~Lit\n//│   <:  nt:\n//│ ~Lit\n//│   = <no result>\n//│     nt, nc and nt are not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/FunnySubsumptions.mls",
    "content": ":NoJS\n\ntrait C\ntrait D\ntrait S\ntrait T\ntrait U\n//│ Defined trait C\n//│ Defined trait D\n//│ Defined trait S\n//│ Defined trait T\n//│ Defined trait U\n\n\ndef A0: (C | {x:T}) & (D | {y:S})\ndef B0: C&{y:S} | D&{x:T} | {x: T; y: S}\n//│ A0: {x: T, y: S} | C & D | C & {y: S} | D & {x: T}\n//│ B0: {x: T, y: S} | C & {y: S} | D & {x: T}\n\n:stats\nA0 = B0\n//│ {x: T, y: S} | C & {y: S} | D & {x: T}\n//│   <:  A0:\n//│ {x: T, y: S} | C & D | C & {y: S} | D & {x: T}\n//│ constrain calls  : 1\n//│ annoying  calls  : 0\n//│ subtyping calls  : 185\n\n:stats\nB0 = A0\n//│ {x: T, y: S} | C & D | C & {y: S} | D & {x: T}\n//│   <:  B0:\n//│ {x: T, y: S} | C & {y: S} | D & {x: T}\n//│ constrain calls  : 2\n//│ annoying  calls  : 32\n//│ subtyping calls  : 277\n\n\ndef A1: C & {x : T} | D & {y : U}\ndef B1: (C | D) & (C | {y : U}) & (D | {x : T})\n//│ A1: C & {x: T} | D & {y: U}\n//│ B1: C & D | C & {x: T} | D & {y: U}\n\n:stats\nA1 = B1\n//│ C & D | C & {x: T} | D & {y: U}\n//│   <:  A1:\n//│ C & {x: T} | D & {y: U}\n//│ constrain calls  : 2\n//│ annoying  calls  : 13\n//│ subtyping calls  : 233\n\n:stats\nB1 = A1\n//│ C & {x: T} | D & {y: U}\n//│   <:  B1:\n//│ C & D | C & {x: T} | D & {y: U}\n//│ constrain calls  : 1\n//│ annoying  calls  : 0\n//│ subtyping calls  : 170\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/GenericClasses.mls",
    "content": "\nclass None: {}\ndef None = None{}\n//│ Defined class None\n//│ None: None\n//│     = [Function: None1]\n\nclass Some[A]: { value: A }\ndef Some v = Some { value = v }\n//│ Defined class Some[+A]\n//│ Some: 'value -> Some['value]\n//│     = [Function: Some1]\n\nSome 42\n(Some 42).value\n//│ res: Some[42]\n//│    = Some { value: 42 }\n//│ res: 42\n//│    = 42\n\ntype Option[A] = Some[A] | None\n//│ Defined type alias Option[+A]\n\nNone: Option[int]\nSome 42 : Option[int]\n//│ res: Option[int]\n//│    = None {}\n//│ res: Option[int]\n//│    = Some { value: 42 }\n\n:e\nres.value\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.32: \tres.value\n//│ ║        \t^^^^^^^^^\n//│ ╟── type `Option[int]` does not have field 'value'\n//│ ║  l.25: \tSome 42 : Option[int]\n//│ ║        \t          ^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{value: ?value}`\n//│ ║  l.32: \tres.value\n//│ ╙──      \t^^^\n//│ res: error | int\n//│    = 42\n\n:e\n42: Option[int, int]\n//│ ╔══[ERROR] Wrong number of type arguments – expected 1, found 2\n//│ ║  l.46: \t42: Option[int, int]\n//│ ╙──      \t    ^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.46: \t42: Option[int, int]\n//│ ║        \t^^\n//│ ╟── integer literal of type `42` does not match type `None | Some[int]`\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.21: \ttype Option[A] = Some[A] | None\n//│ ║        \t                 ^^^^^^^^^^^^^^\n//│ ╟── from applied type reference:\n//│ ║  l.46: \t42: Option[int, int]\n//│ ╙──      \t    ^^^^^^^^^^^^^^^^\n//│ res: Option[int]\n//│    = 42\n\n\n\nclass Foo1[A]: { x: A }\nclass Bar1: Foo1[int]\n//│ Defined class Foo1[+A]\n//│ Defined class Bar1\n\nBar1\n//│ res: {x: int & 'x} -> (Bar1 with {x: 'x})\n//│    = [Function: res]\n\ng = Bar1 { x = 42 }\n//│ g: Bar1 & {x: 42}\n//│  = Bar1 { x: 42 }\n\ng: Foo1['a]\n//│ res: Foo1[int]\n//│    = Bar1 { x: 42 }\n\nres.x\n//│ res: int\n//│    = 42\n\ng: Foo1['a]: Foo1[int]\n//│ res: Foo1[int]\n//│    = Bar1 { x: 42 }\n\nres.x\n//│ res: int\n//│    = 42\n\n:e\ng: Foo1['a]: Foo1[string]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.95: \tg: Foo1['a]: Foo1[string]\n//│ ║        \t^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.66: \tclass Bar1: Foo1[int]\n//│ ║        \t                 ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.95: \tg: Foo1['a]: Foo1[string]\n//│ ╙──      \t                  ^^^^^^\n//│ res: Foo1[string]\n//│    = Bar1 { x: 42 }\n\n\n\nclass Foo2[A]\n  method Foo2: A -> A\n  method Foo2 = id\n//│ Defined class Foo2[=A]\n//│ Declared Foo2.Foo2: Foo2['A] -> 'A -> 'A\n//│ Defined Foo2.Foo2: Foo2['A] -> 'a -> 'a\n\nFoo2\n//│ res: anything -> Foo2['A]\n//│    = [Function: res]\n\n:re\nerror: Foo2[int]\n//│ res: Foo2[int]\n//│ Runtime error:\n//│   Error: an error was thrown\n\nf = fun x -> case x of { Foo2 -> x }\n//│ f: (Foo2[?] & 'a) -> 'a\n//│  = [Function: f]\n\nf (Foo2 {})\n//│ res: Foo2['A]\n//│    = Foo2 {}\n\n:re\nerror: (Foo2[?] & 'a) -> 'a\n//│ res: (Foo2[?] & 'a) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\nf: (Foo2[?] & 'a) -> 'a\n//│ res: (Foo2[?] & 'a) -> 'a\n//│    = [Function: f]\n\n:ns\nf: (Foo2[?] & 'a) -> 'a\n//│ res: (Foo2[?] & 'a) -> 'a\n//│    = [Function: f]\n\nf\n//│ res: (Foo2[?] & 'a) -> 'a\n//│    = [Function: f]\n\n\ndef mrg: Foo2[int] & Foo2[string]\n//│ mrg: in Foo2[out int | string] out Foo2[in int | string out nothing]\n//│    = <missing implementation>\n\nmrg: Foo2[int]\n//│ res: Foo2[int]\n//│    = <no result>\n//│      mrg is not implemented\n\n// * This no longer causes an error because it treats `mrg` as polymorphic and it separately satisfies each side of `Foo2[Int] & Foo2[String]`...\nmrg = Foo2{}\n//│ Foo2['A]\n//│   <:  mrg:\n//│ Foo2[out int | string]\n//│    = Foo2 {}\n\n// * Even this one works although the LHS is not generalized.\n// * It works because the ctor's polymorphic type is pushed in by distributivity,\n// * resulting in a generalized value....\nmrg2 = Foo2{} : Foo2[int] & Foo2[string]\n//│ mrg2: Foo2[in int | string out nothing]\n//│     = Foo2 {}\n\n// * Notice how this one doesn't work when we can't distribute foralls.\n:DontDistributeForalls\n:e\nmrg2 = Foo2{} : Foo2[int] & Foo2[string]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.181: \tmrg2 = Foo2{} : Foo2[int] & Foo2[string]\n//│ ║         \t       ^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.181: \tmrg2 = Foo2{} : Foo2[int] & Foo2[string]\n//│ ║         \t                                 ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.181: \tmrg2 = Foo2{} : Foo2[int] & Foo2[string]\n//│ ║         \t                     ^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.110: \tclass Foo2[A]\n//│ ╙──       \t           ^\n//│ mrg2: Foo2[in int | string out nothing]\n//│     = Foo2 {}\n:DistributeForalls\n\nmrg.Foo2\n//│ res: ('A & (int | string)) -> 'A\n//│    = [Function: id]\n\nmrg.Foo2 42\n//│ res: 42\n//│    = 42\n\n\ndef mrg: Foo2[int] | Foo2[string]\n//│ mrg: Foo2[out int | string]\n//│    = <missing implementation>\n\n\n\nclass Foo2_Co[A]\n  method Foo2_Co: A\n  method Foo2_Co = error\n//│ Defined class Foo2_Co[+A]\n//│ Declared Foo2_Co.Foo2_Co: Foo2_Co['A] -> 'A\n//│ Defined Foo2_Co.Foo2_Co: Foo2_Co[?] -> nothing\n\nFoo2_Co\n//│ res: anything -> Foo2_Co[nothing]\n//│    = [Function: res]\n\n:re\nerror: Foo2_Co[int]\n//│ res: Foo2_Co[int]\n//│ Runtime error:\n//│   Error: an error was thrown\n\nf = fun x -> case x of { Foo2_Co -> x }\n//│ f: (Foo2_Co[?] & 'a) -> 'a\n//│  = [Function: f1]\n\nf (Foo2_Co {})\n//│ res: Foo2_Co[nothing]\n//│    = Foo2_Co {}\n\n:re\nerror: (Foo2_Co[?] & 'a) -> 'a\n//│ res: (Foo2_Co[nothing] & 'a) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\nf: (Foo2_Co[?] & 'a) -> 'a\n//│ res: (Foo2_Co[nothing] & 'a) -> 'a\n//│    = [Function: f1]\n\n:ns\nf: (Foo2_Co[?] & 'a) -> 'a\n//│ res: (Foo2_Co[?] & 'a) -> 'a\n//│    = [Function: f1]\n\nf\n//│ res: (Foo2_Co[?] & 'a) -> 'a\n//│    = [Function: f1]\n\n\ndef mrg: Foo2_Co[int] & Foo2_Co[string]\n//│ mrg: Foo2_Co[nothing]\n//│    = <missing implementation>\n\nmrg: Foo2_Co[int]\n//│ res: Foo2_Co[int]\n//│    = <no result>\n//│      mrg is not implemented\n\nmrg = Foo2_Co{}\n//│ Foo2_Co[nothing]\n//│   <:  mrg:\n//│ Foo2_Co[nothing]\n//│    = Foo2_Co {}\n\ndef mrg: Foo2_Co[int] | Foo2_Co[string]\n//│ mrg: in Foo2_Co[nothing] out Foo2_Co[int | string]\n//│    = <missing implementation>\n\n\n\n:w\nclass Foo2_Bi[A]\n//│ Defined class Foo2_Bi[±A]\n//│ ╔══[WARNING] Type definition Foo2_Bi has bivariant type parameters:\n//│ ║  l.280: \tclass Foo2_Bi[A]\n//│ ║         \t      ^^^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.280: \tclass Foo2_Bi[A]\n//│ ╙──       \t              ^\n\nFoo2_Bi\n//│ res: anything -> Foo2_Bi[?]\n//│    = [Function: res]\n\n:re\nerror: Foo2_Bi[int]\n//│ res: Foo2_Bi[?]\n//│ Runtime error:\n//│   Error: an error was thrown\n\nf = fun x -> case x of { Foo2_Bi -> x }\n//│ f: (Foo2_Bi[?] & 'a) -> 'a\n//│  = [Function: f2]\n\nf (Foo2_Bi {})\n//│ res: Foo2_Bi[?]\n//│    = Foo2_Bi {}\n\n:re\nerror: (Foo2_Bi[?] & 'a) -> 'a\n//│ res: (Foo2_Bi[?] & 'a) -> 'a\n//│ Runtime error:\n//│   Error: an error was thrown\n\nf: (Foo2_Bi[?] & 'a) -> 'a\n//│ res: (Foo2_Bi[?] & 'a) -> 'a\n//│    = [Function: f2]\n\n:ns\nf: (Foo2_Bi[?] & 'a) -> 'a\n//│ res: (Foo2_Bi[?] & 'a) -> 'a\n//│    = [Function: f2]\n\nf\n//│ res: (Foo2_Bi[?] & 'a) -> 'a\n//│    = [Function: f2]\n\n\ndef mrg: Foo2_Bi[int] & Foo2_Bi[string]\n//│ mrg: Foo2_Bi[?]\n//│    = <missing implementation>\n\nmrg: Foo2_Bi[int]\n//│ res: Foo2_Bi[?]\n//│    = <no result>\n//│      mrg is not implemented\n\nmrg = Foo2_Bi{}\n//│ Foo2_Bi[?]\n//│   <:  mrg:\n//│ Foo2_Bi[?]\n//│    = Foo2_Bi {}\n\ndef mrg: Foo2_Bi[int] | Foo2_Bi[string]\n//│ mrg: Foo2_Bi[?]\n//│    = <missing implementation>\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/GenericClasses2.mls",
    "content": "\nclass Foo1[A]: { x: A }\nclass Bar1: Foo1[int]\n//│ Defined class Foo1[+A]\n//│ Defined class Bar1\n\nFoo1\n//│ res: {x: 'x} -> Foo1['x]\n//│    = [Function: res]\n\nBar1\n//│ res: {x: int & 'x} -> (Bar1 with {x: 'x})\n//│    = [Function: res]\n\nb = Bar1{x = 1}\n//│ b: Bar1 & {x: 1}\n//│  = Bar1 { x: 1 }\n\n:e\nb: Foo1[string]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.20: \tb: Foo1[string]\n//│ ║        \t^\n//│ ╟── integer literal of type `1` is not an instance of type `string`\n//│ ║  l.15: \tb = Bar1{x = 1}\n//│ ║        \t             ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.20: \tb: Foo1[string]\n//│ ╙──      \t        ^^^^^^\n//│ res: Foo1[string]\n//│    = Bar1 { x: 1 }\n\n\nclass Foo2[A]\n  method M2: A\nclass Bar2: Foo2[int] & { x: int }\n  method M2 = 1\n//│ Defined class Foo2[+A]\n//│ Declared Foo2.M2: Foo2['A] -> 'A\n//│ Defined class Bar2\n//│ Defined Bar2.M2: Bar2 -> 1\n\nclass Bar3: Foo2[int]\n//│ Defined class Bar3\n\n:e\n:ns\nBar2\nBar3\n//│ res: forall 'x. {x: 'x} -> (#Bar2 & {Foo2#A = int, x: 'x})\n//│   where\n//│     'x <: int\n//│    = [Function: res]\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.49: \tBar3\n//│ ║        \t^^^^\n//│ ╟── Note that class Bar3 is abstract:\n//│ ║  l.43: \tclass Bar3: Foo2[int]\n//│ ║        \t      ^^^^^^^^^^^^^^^\n//│ ╟── Hint: method M2 is abstract\n//│ ║  l.35: \t  method M2: A\n//│ ╙──      \t         ^^^^^\n//│ res: error\n//│    = [Function: res]\n\n:e\nBar2\nBar3\n//│ res: {x: int & 'x} -> (Bar2 with {x: 'x})\n//│    = [Function: res]\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.68: \tBar3\n//│ ║        \t^^^^\n//│ ╟── Note that class Bar3 is abstract:\n//│ ║  l.43: \tclass Bar3: Foo2[int]\n//│ ║        \t      ^^^^^^^^^^^^^^^\n//│ ╟── Hint: method M2 is abstract\n//│ ║  l.35: \t  method M2: A\n//│ ╙──      \t         ^^^^^\n//│ res: error\n//│    = [Function: res]\n\n:e\n{A = 1}\n//│ ╔══[ERROR] Field identifiers must start with a small letter\n//│ ║  l.84: \t{A = 1}\n//│ ╙──      \t^^^^^^^\n//│ res: {A <: 1}\n//│    = { A: 1 }\n\n:e\nerror: {A: 1}\n//│ ╔══[ERROR] Field identifiers must start with a small letter\n//│ ║  l.92: \terror: {A: 1}\n//│ ╙──      \t        ^\n//│ res: {A <: 1}\n//│ Runtime error:\n//│   Error: an error was thrown\n\nb = Bar2{x = 1}\n//│ b: Bar2 & {x: 1}\n//│  = Bar2 { x: 1 }\n\n:e\nc = b: Foo2[string]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.105: \tc = b: Foo2[string]\n//│ ║         \t    ^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.36: \tclass Bar2: Foo2[int] & { x: int }\n//│ ║        \t                 ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.105: \tc = b: Foo2[string]\n//│ ╙──       \t            ^^^^^^\n//│ c: Foo2[string]\n//│  = Bar2 { x: 1 }\n\nc.M2\n//│ res: string\n//│    = 1\n\nd = b: Bar2\n//│ d: Bar2\n//│  = Bar2 { x: 1 }\n\nd.M2\n//│ res: int\n//│    = 1\n\nd: Foo2['a]\n//│ res: Foo2[int]\n//│    = Bar2 { x: 1 }\n\n:e\nd: Foo2[string]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.135: \td: Foo2[string]\n//│ ║         \t^\n//│ ╟── type `int` is not an instance of type `string`\n//│ ║  l.36: \tclass Bar2: Foo2[int] & { x: int }\n//│ ║        \t                 ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.135: \td: Foo2[string]\n//│ ╙──       \t        ^^^^^^\n//│ res: Foo2[string]\n//│    = Bar2 { x: 1 }\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Group_2021_12_02.mls",
    "content": "\nclass Lit\nclass Add\nclass Const\n//│ Defined class Lit\n//│ Defined class Add\n//│ Defined class Const\n\nLit\n//│ res: anything -> Lit\n//│    = [Function: res]\n\ndef eval0: ('b -> ('c & int)) -> (Lit & {val: int} | Add & {lhs: 'a; rhs: 'a} | ~lit & ~add & 'b as 'a) -> (int | 'c)\n//│ eval0: ('b -> int) -> 'a -> int\n//│   where\n//│     'a <: Add & {lhs: 'a, rhs: 'a} | Lit & {val: int} | 'b & ~#Add & ~#Lit\n//│      = <missing implementation>\n\ndef evalUgly: ('b -> ('c & int)) -> (Lit & {val: int} | Add & {lhs: 'a; rhs: 'a} | ~Lit & ~Add & 'b as 'a) -> (int | 'c)\n//│ evalUgly: ('b -> int) -> 'a -> int\n//│   where\n//│     'a <: Add & {lhs: 'a, rhs: 'a} | Lit & {val: int} | 'b & ~Add & ~Lit\n//│         = <missing implementation>\n\ndef evalBad: ('b -> 'c) -> (Lit & {val: int} | Add & {lhs: 'a; rhs: 'a} | ~Lit & ~Add & 'b as 'a) -> (int | 'c)\n//│ evalBad: ('b -> 'c) -> 'a -> (int | 'c)\n//│   where\n//│     'a <: Add & {lhs: 'a, rhs: 'a} | Lit & {val: int} | 'b & ~Add & ~Lit\n//│        = <missing implementation>\n\ntype Expr[A] = Lit & {val: int} | Add & {lhs: Expr[A]; rhs: Expr[A]} | ~Lit & ~Add & A\n//│ Defined type alias Expr[+A]\n\ndef eval1: ('b -> ('c & int)) -> Expr['b] -> (int | 'c)\n//│ eval1: ('b -> int) -> Expr['b] -> int\n//│      = <missing implementation>\n\ndef eval: ('b -> int) -> Expr['b] -> int\n//│ eval: ('b -> int) -> Expr['b] -> int\n//│     = <missing implementation>\n\nrec def evalImpl f e = case e of {\n  | Lit -> e.val\n  | Add -> evalImpl f e.lhs + evalImpl f e.rhs\n  | _ -> f e\n  }\n//│ evalImpl: ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add & {lhs: 'b, rhs: 'b} | Lit & {val: int} | 'a & ~#Add & ~#Lit\n//│         = [Function: evalImpl]\n\nrec def evalPeel f e = case e of {\n  | Lit -> e.val\n  | Add -> eval f e.lhs + eval f e.rhs\n  | _ -> f e\n  }\n//│ evalPeel: ('b -> int & 'a -> 'val) -> (Add & {lhs: Expr['b], rhs: Expr['b]} | Lit & {val: 'val} | 'a & ~#Add & ~#Lit) -> (int | 'val)\n//│         = <no result>\n//│           eval is not implemented\n\neval = evalPeel\n//│ ('b -> int & 'a -> 'val) -> (Add & {lhs: Expr['b], rhs: Expr['b]} | Lit & {val: 'val} | 'a & ~#Add & ~#Lit) -> (int | 'val)\n//│   <:  eval:\n//│ ('b -> int) -> Expr['b] -> int\n//│     = <no result>\n//│       evalPeel and eval are not implemented\n\neval = evalImpl\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add & {lhs: 'b, rhs: 'b} | Lit & {val: int} | 'a & ~#Add & ~#Lit\n//│   <:  eval:\n//│ ('b -> int) -> Expr['b] -> int\n//│     = [Function: evalImpl]\n\neval0 = evalImpl\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add & {lhs: 'b, rhs: 'b} | Lit & {val: int} | 'a & ~#Add & ~#Lit\n//│   <:  eval0:\n//│ ('b -> int) -> 'a -> int\n//│   where\n//│     'a <: Add & {lhs: 'a, rhs: 'a} | Lit & {val: int} | 'b & ~#Add & ~#Lit\n//│      = [Function: evalImpl]\n\nevalUgly = evalImpl\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add & {lhs: 'b, rhs: 'b} | Lit & {val: int} | 'a & ~#Add & ~#Lit\n//│   <:  evalUgly:\n//│ ('b -> int) -> 'a -> int\n//│   where\n//│     'a <: Add & {lhs: 'a, rhs: 'a} | Lit & {val: int} | 'b & ~Add & ~Lit\n//│         = [Function: evalImpl]\n\neval1 = evalImpl\n//│ ('a -> int) -> 'b -> int\n//│   where\n//│     'b <: Add & {lhs: 'b, rhs: 'b} | Lit & {val: int} | 'a & ~#Add & ~#Lit\n//│   <:  eval1:\n//│ ('b -> int) -> Expr['b] -> int\n//│      = [Function: evalImpl]\n\n:e\nevalBad = eval\n//│ ('b -> int) -> Expr['b] -> int\n//│   <:  evalBad:\n//│ ('b -> 'c) -> 'a -> (int | 'c)\n//│   where\n//│     'a <: Add & {lhs: 'a, rhs: 'a} | Lit & {val: int} | 'b & ~Add & ~Lit\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.105: \tevalBad = eval\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── type `'c` is not an instance of type `int`\n//│ ║  l.25: \tdef evalBad: ('b -> 'c) -> (Lit & {val: int} | Add & {lhs: 'a; rhs: 'a} | ~Lit & ~Add & 'b as 'a) -> (int | 'c)\n//│ ║        \t                    ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.38: \tdef eval: ('b -> int) -> Expr['b] -> int\n//│ ╙──      \t                 ^^^\n//│        = [Function: evalImpl]\n\n:e\neval {} (Lit{} with { val = 1 })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.123: \teval {} (Lit{} with { val = 1 })\n//│ ║         \t^^^^^^^\n//│ ╟── record literal of type `anything` is not a function\n//│ ║  l.123: \teval {} (Lit{} with { val = 1 })\n//│ ║         \t     ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.38: \tdef eval: ('b -> int) -> Expr['b] -> int\n//│ ╙──      \t          ^^^^^^^^^^^\n//│ res: error | int\n//│    = 1\n\neval (fun x -> x) (Lit{} with { val = 1 })\n//│ res: int\n//│    = 1\n\neval (fun x -> x) 1\n//│ res: int\n//│    = 1\n\neval (fun x -> x.hello) (Const{} with {hello=1})\n//│ res: int\n//│    = 1\n\n:e\neval (fun x -> x.hello) {hello=1}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.149: \teval (fun x -> x.hello) {hello=1}\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{hello: 1}` does not match type `Add & {lhs: Expr['b], rhs: Expr['b]} | Lit & {val: int} | 'b & ~Add & ~Lit`\n//│ ║  l.149: \teval (fun x -> x.hello) {hello=1}\n//│ ║         \t                        ^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.31: \ttype Expr[A] = Lit & {val: int} | Add & {lhs: Expr[A]; rhs: Expr[A]} | ~Lit & ~Add & A\n//│ ║        \t               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from applied type reference:\n//│ ║  l.38: \tdef eval: ('b -> int) -> Expr['b] -> int\n//│ ╙──      \t                         ^^^^^^^^\n//│ res: error | int\n//│    = 1\n\nl = Lit{} with {hello=1}\n//│ l: Lit & {hello: 1}\n//│  = Lit { hello: 1 }\nl: {hello:1}\n//│ res: {hello: 1}\n//│    = Lit { hello: 1 }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Group_2022_05_10.mls",
    "content": "\ndef f x = (x 1, x \"ok\")\n//│ f: (1 -> 'a & \"ok\" -> 'b) -> ('a, 'b,)\n//│  = [Function: f]\n\nf (fun x -> (x, x))\n//│ res: ((1, 1,), (\"ok\", \"ok\",),)\n//│    = [ [ 1, 1 ], [ 'ok', 'ok' ] ]\n\n(fun id -> id id 0) (fun x -> x)\n//│ res: 0\n//│    = 0\n\nfun id -> id id 0\n//│ res: ('a -> 0 -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\nfun x -> x\n//│ res: 'a -> 'a\n//│    = [Function: res]\n\n// forall 'a. 'a -> 'a  <:  'a1 -> 0 -> 'b1 & 'a1\n// i.e.\n//    forall 'a. 'a -> 'a  <:  'a1 -> 0 -> 'b1\n//    forall 'a. 'a -> 'a  <:  'a1\n// i.e.\n//    'a2 -> 'a2  <:  'a1 -> 0 -> 'b1\n//    'a3 -> 'a3  <:  'a1\n\n\ndef g x = x (fun x -> x)\n//│ g: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│  = [Function: g]\n\n\ndef g x y = x (fun x -> y x)\n//│ g: (('a -> 'b) -> 'c) -> ('a -> 'b) -> 'c\n//│  = [Function: g1]\n\n\nself x = x x\n//│ self: ('a -> 'b & 'a) -> 'b\n//│     = [Function: self]\n\n:re\nself self!\n//│ res: nothing\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Group_2022_06_09.mls",
    "content": "\nclass Exp\n//│ Defined class Exp\n\nclass Lit: { n: int } & Exp\nclass Add: { lhs: Exp; rhs: Exp } & Exp\n//│ Defined class Lit\n//│ Defined class Add\n\nrec def eval e = case e of {\n  | Lit -> e.n\n  | Add -> eval e.lhs + eval e.rhs\n  }\n//│ eval: 'a -> int\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit\n//│     = [Function: eval]\n\ne = Add { lhs = Lit {n=1}; rhs = Lit {n=2} }\n//│ e: Add with {lhs: Lit & {n: 1}, rhs: Lit & {n: 2}}\n//│  = Add { lhs: Lit { n: 1 }, rhs: Lit { n: 2 } }\n\neval e\n//│ res: int\n//│    = 3\n\n\nclass Neg: { e: Exp } & Exp\n//│ Defined class Neg\n\ne2 = Neg { e }\n//│ e2: Neg with {e: Add with {lhs: Lit & {n: 1}, rhs: Lit & {n: 2}}}\n//│   = Neg { e: Add { lhs: Lit { n: 1 }, rhs: Lit { n: 2 } } }\n\ne2.e.lhs.n\n//│ res: 1\n//│    = 1\n\n:e\neval e2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.40: \teval e2\n//│ ║        \t^^^^^^^\n//│ ╟── application of type `Neg & {e: ?e}` does not match type `Add & ?a | Lit & ?b`\n//│ ║  l.31: \te2 = Neg { e }\n//│ ║        \t     ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Add & ?c | Lit & ?d`\n//│ ║  l.40: \teval e2\n//│ ║        \t     ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.10: \trec def eval e = case e of {\n//│ ╙──      \t                      ^\n//│ res: error | int\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\ndef eval eval e = case e of {\n  | Lit -> e.n\n  | Add -> eval eval e.lhs + eval eval e.rhs\n  }\n//│ eval: ('a -> 'lhs -> int & 'a) -> ((Add with {lhs: 'lhs, rhs: 'lhs}) | (Lit with {n: 'n})) -> (int | 'n)\n//│     = [Function: eval1]\n\neval eval! e\n//│ res: int\n//│    = 3\n\n\ndef evalN evalN e = case e of {\n  | Neg -> 0 - evalN evalN e.e\n  | _ -> eval evalN e\n  }\n//│ evalN: ('a -> 'lhs -> int & 'a) -> ((Add with {lhs: 'lhs, rhs: 'lhs}) | (Lit with {n: 'n}) | (Neg with {e: 'lhs})) -> (int | 'n)\n//│      = [Function: evalN]\n\nevalN eval! e\n//│ res: int\n//│    = 3\n\nevalN eval! e2\n//│ res: int\n//│    = -3\n\nev = evalN evalN!\n//│ ev: ((Add with {lhs: 'a, rhs: 'a}) | (Lit with {n: 'n}) | (Neg with {e: 'a})) -> (int | 'n)\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit | (Neg with {e: 'a})\n//│   = [Function (anonymous)]\n\n(ev e, ev e2)\n//│ res: (int, int,)\n//│    = [ 3, -3 ]\n\n\ne3 = Add { lhs = Neg { e = Lit {n=1} }; rhs = Lit {n=2} }\n//│ e3: Add with {lhs: Neg with {e: Lit & {n: 1}}, rhs: Lit & {n: 2}}\n//│   = Add { lhs: Neg { e: Lit { n: 1 } }, rhs: Lit { n: 2 } }\n\nev e3\n//│ res: int\n//│    = 1\n\n\n// * With a continuation, to make `evalN` not need to mention `eval` at all:\n\ndef evalN evalN k e = case e of {\n  | Neg -> 0 - evalN evalN k e.e\n  | _ -> k e\n  }\n//│ evalN: ('a -> 'b -> 'e -> int & 'a) -> ('c -> 'd & 'b) -> ((Neg with {e: 'e}) | 'c & ~#Neg) -> (int | 'd)\n//│      = [Function: evalN1]\n\n\n// * Note that these `evalComposed` types could be simplified further\n// *  by making the simplifier realize that in `Lit with {n: 'n}`, `'n` really co-occurs with `int`!\n\ndef evalComposed evalComposed = evalN evalN! (fun e -> eval evalComposed e)\n//│ evalComposed: ('a -> 'rhs -> int & 'a) -> ((Add with {lhs: 'rhs, rhs: 'rhs}) | (Lit with {n: 'n}) | (Neg with {e: 'b})) -> (int | 'n)\n//│   where\n//│     'b <: (Add with {lhs: 'rhs, rhs: 'rhs}) | Lit | (Neg with {e: 'b})\n//│             = [Function: evalComposed]\n\ndef evalComposed evalComposed = evalN evalN! (eval evalComposed)\n//│ evalComposed: ('a -> 'lhs -> int & 'a) -> ((Add with {lhs: 'lhs, rhs: 'lhs}) | (Lit with {n: 'n}) | (Neg with {e: 'b})) -> (int | 'n)\n//│   where\n//│     'b <: (Add with {lhs: 'lhs, rhs: 'lhs}) | Lit | (Neg with {e: 'b})\n//│             = [Function: evalComposed1]\n\n\n// * NOTE: This inferred type is a good example\n// *    of the need for an algorithm to tie recursive TV knots and inline the rest;\n// *    once we inline, `b` we should get the expected simplified recursive type.\nev2 = evalComposed evalComposed!\n//│ ev2: (Add\\lhs\\rhs & {lhs: Neg\\e & {e: 'a} | 'b & ~#Neg, rhs: Neg\\e & {e: 'a} | 'b & ~#Neg} | Lit\\n & {n: 'n} | Neg\\e & {e: 'c}) -> (int | 'n)\n//│   where\n//│     'c <: Add\\lhs\\rhs & {lhs: Neg\\e & {e: 'a} | 'b & ~#Neg, rhs: Neg\\e & {e: 'a} | 'b & ~#Neg} | Lit | Neg\\e & {e: 'c}\n//│     'a <: Add\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Lit | Neg\\e & {e: 'a}\n//│     'lhs <: Neg\\e & {e: 'a} | 'b & ~#Neg\n//│     'b <: Add\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│     'rhs <: Neg\\e & {e: 'a} | 'b & ~#Neg\n//│    = [Function (anonymous)]\n\nev2 e3\n//│ res: int\n//│    = 1\n\n\ndef ev2_ty: (Add & { lhs: 'a; rhs: 'a } | Lit | Neg & { e: 'a } as 'a) -> int\n//│ ev2_ty: 'a -> int\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit | (Neg with {e: 'a})\n//│       = <missing implementation>\n\nev2_ty = ev2\n//│ (Add\\lhs\\rhs & {lhs: Neg\\e & {e: 'a} | 'b & ~#Neg, rhs: Neg\\e & {e: 'a} | 'b & ~#Neg} | Lit\\n & {n: 'n} | Neg\\e & {e: 'c}) -> (int | 'n)\n//│   where\n//│     'c <: Add\\lhs\\rhs & {lhs: Neg\\e & {e: 'a} | 'b & ~#Neg, rhs: Neg\\e & {e: 'a} | 'b & ~#Neg} | Lit | Neg\\e & {e: 'c}\n//│     'a <: Add\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Lit | Neg\\e & {e: 'a}\n//│     'lhs <: Neg\\e & {e: 'a} | 'b & ~#Neg\n//│     'b <: Add\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Lit\n//│     'rhs <: Neg\\e & {e: 'a} | 'b & ~#Neg\n//│   <:  ev2_ty:\n//│ 'a -> int\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit | (Neg with {e: 'a})\n//│       = [Function (anonymous)]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/HeadOption.mls",
    "content": ":NoJS\n\n:w\nclass Option[A]\nclass Some[A]: Option[A] & { payload: A }\nclass None[A]: Option[A]\n//│ Defined class Option[±A]\n//│ Defined class Some[+A]\n//│ Defined class None[±A]\n//│ ╔══[WARNING] Type definition None has bivariant type parameters:\n//│ ║  l.6: \tclass None[A]: Option[A]\n//│ ║       \t      ^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.6: \tclass None[A]: Option[A]\n//│ ╙──     \t           ^\n//│ ╔══[WARNING] Type definition Option has bivariant type parameters:\n//│ ║  l.4: \tclass Option[A]\n//│ ║       \t      ^^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.4: \tclass Option[A]\n//│ ╙──     \t             ^\n\n\n:w\nclass List[A]\n    method HeadOption: Option[A]\n//│ Defined class List[±A]\n//│ Declared List.HeadOption: List[?] -> Option[?]\n//│ ╔══[WARNING] Type definition List has bivariant type parameters:\n//│ ║  l.25: \tclass List[A]\n//│ ║        \t      ^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.25: \tclass List[A]\n//│ ╙──      \t           ^\n\n:w\nclass Nil[A]: List[A]\n    method HeadOption = None {}\n//│ Defined class Nil[±A]\n//│ Defined Nil.HeadOption: Nil[?] -> None[?]\n//│ ╔══[WARNING] Type definition Nil has bivariant type parameters:\n//│ ║  l.37: \tclass Nil[A]: List[A]\n//│ ║        \t      ^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.37: \tclass Nil[A]: List[A]\n//│ ╙──      \t          ^\n\nclass Cons[A]: List[A] & { head: A; tail: List[A] }\n    method HeadOption = Some { payload = error: A }\n//│ Defined class Cons[+A]\n//│ Defined Cons.HeadOption: Cons['A] -> Some['A]\n\n// * Incur much fewer constraining/subtyping checks:\n// class Cons[A]: List[A] & { head: A; tail: list }\n// class Cons[A]: List[A] & { head: A; tail: anything }\n\n\n:stats\nl0 = Cons { head = 1; tail = Nil {} }\n//│ l0: Cons[1] with {tail: Nil[?]}\n//│ constrain calls  : 24\n//│ annoying  calls  : 1\n//│ subtyping calls  : 84\n\n:stats\nCons.HeadOption l0\n//│ res: Some[1]\n//│ constrain calls  : 45\n//│ annoying  calls  : 22\n//│ subtyping calls  : 137\n\n:stats\nl1 = Cons { head = 1; tail = Cons { head = 2; tail = Cons { head = 3; tail = Nil {} } } }\n//│ l1: Cons[1] with {tail: Cons[2] with {tail: Cons[3] with {tail: Nil[?]}}}\n//│ constrain calls  : 54\n//│ annoying  calls  : 1\n//│ subtyping calls  : 246\n\n:stats\nCons.HeadOption l1\n//│ res: Some[1]\n//│ constrain calls  : 42\n//│ annoying  calls  : 21\n//│ subtyping calls  : 140\n\n:stats\nl2 = Cons { head = 0; tail = l1 }\n//│ l2: Cons[0] with {tail: Cons[1] with {tail: Cons[2] with {tail: Cons[3] with {tail: Nil[?]}}}}\n//│ constrain calls  : 20\n//│ annoying  calls  : 1\n//│ subtyping calls  : 169\n\n:stats\nCons.HeadOption l2\n//│ res: Some[0]\n//│ constrain calls  : 48\n//│ annoying  calls  : 22\n//│ subtyping calls  : 143\n\n:stats\nl3 = Cons { head = 0-1; tail = l2 }\n//│ l3: Cons[int] with {\n//│   tail: Cons[0] with {tail: Cons[1] with {tail: Cons[2] with {tail: Cons[3] with {tail: Nil[?]}}}}\n//│ }\n//│ constrain calls  : 33\n//│ annoying  calls  : 1\n//│ subtyping calls  : 250\n\n:stats\nCons.HeadOption l3\n//│ res: Some[int]\n//│ constrain calls  : 50\n//│ annoying  calls  : 22\n//│ subtyping calls  : 148\n\n\n:stats\nrec def lr1 = Cons { head = 0; tail = lr1 }\n//│ lr1: 'tail\n//│   where\n//│     'tail :> Cons[0] with {tail: 'tail}\n//│ constrain calls  : 19\n//│ annoying  calls  : 0\n//│ subtyping calls  : 96\n\n:stats\nCons.HeadOption lr1\n//│ res: Some[0]\n//│ constrain calls  : 45\n//│ annoying  calls  : 21\n//│ subtyping calls  : 147\n\n:stats\nrec def lr2 = Cons { head = 0; tail = Cons { head = 1; tail = Cons { head = 3; tail = lr2 } } }\n//│ lr2: Cons[0] with {tail: 'tail}\n//│   where\n//│     'tail :> Cons[1] with {tail: Cons[3] with {tail: Cons[0] with {tail: 'tail}}}\n//│ constrain calls  : 49\n//│ annoying  calls  : 0\n//│ subtyping calls  : 280\n\n:stats\nCons.HeadOption lr2\n//│ res: Some[0]\n//│ constrain calls  : 44\n//│ annoying  calls  : 21\n//│ subtyping calls  : 142\n\n\n:e\nl1 = Cons { tail = Cons { tail = Cons { tail = Nil {} } } }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.151: \tl1 = Cons { tail = Cons { tail = Cons { tail = Nil {} } } }\n//│ ║         \t                                 ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{tail: ?a}` does not have field 'head'\n//│ ║  l.151: \tl1 = Cons { tail = Cons { tail = Cons { tail = Nil {} } } }\n//│ ╙──       \t                                      ^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.151: \tl1 = Cons { tail = Cons { tail = Cons { tail = Nil {} } } }\n//│ ║         \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{tail: ?a}` does not have field 'head'\n//│ ║  l.151: \tl1 = Cons { tail = Cons { tail = Cons { tail = Nil {} } } }\n//│ ╙──       \t                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.151: \tl1 = Cons { tail = Cons { tail = Cons { tail = Nil {} } } }\n//│ ║         \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{tail: ?a}` does not have field 'head'\n//│ ║  l.151: \tl1 = Cons { tail = Cons { tail = Cons { tail = Nil {} } } }\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ l1: (Cons[nothing] with {\n//│   tail: (Cons[nothing] with {tail: (Cons[nothing] with {tail: Nil[?]}) | error}) | error\n//│ }) | error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Huawei2.mls",
    "content": "\nclass C[A]: { a: A -> A }\n//│ Defined class C[=A]\n\nclass D: C[int] & { b: int }\n//│ Defined class D\n\nd = D{a = id; b = if true then 0 else 1}\n//│ d: D with {a: forall 'a. 'a -> 'a, b: 0 | 1}\n//│  = D { a: [Function: id], b: 0 }\n\nd.a true\n//│ res: true\n//│    = true\n\nd.a 0\n//│ res: 0\n//│    = 0\n\nd : #D\n//│ res: D\n//│    = D { a: [Function: id], b: 0 }\n\ndef foo x = case x of D -> x.b, _ -> 0\n//│ foo: ((D\\a with {b: 'b}) | ~D) -> (0 | 'b)\n//│    = [Function: foo]\n\n// Overloading through intersections: not supported\n// foo: ((D\\a with {b: 'b}) -> 'b) & (~D -> 0)\n\nfoo d\n//│ res: 0 | 1\n//│    = 0\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Inherit.mls",
    "content": "\nclass Parent: { name: string }\n//│ Defined class Parent\n\nclass Child: Parent & { age: int }\n//│ Defined class Child\n\np = Parent{ name = \"Bob\" }\n//│ p: Parent & {name: \"Bob\"}\n//│  = Parent { name: 'Bob' }\n\np: Parent\n//│ res: Parent\n//│    = Parent { name: 'Bob' }\n\n:e\nc = Child(Parent { name = \"Bob\" })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.17: \tc = Child(Parent { name = \"Bob\" })\n//│ ║        \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Parent & {name: ?name}` does not have all required fields 'name', 'age'\n//│ ║  l.17: \tc = Child(Parent { name = \"Bob\" })\n//│ ╙──      \t          ^^^^^^^^^^^^^^^^^^^^^^^\n//│ c: Child & {age: nothing, name: \"Bob\"} | error\n//│  = Child { name: 'Bob', age: undefined }\n\nc = Child(Parent { name = \"Bob\" } with { age = 123 })\n//│ c: Child & {age: 123, name: \"Bob\"}\n//│  = Child { name: 'Bob', age: 123 }\n\nc: Parent\n//│ res: Parent\n//│    = Child { name: 'Bob', age: 123 }\n\nc.name\n//│ res: \"Bob\"\n//│    = 'Bob'\n\nc: { name: 'a }\n//│ res: {name: \"Bob\"}\n//│    = Child { name: 'Bob', age: 123 }\n\nc: { name: string }\n//│ res: {name: string}\n//│    = Child { name: 'Bob', age: 123 }\n\n\ndef f x = case x of {\n  | Parent -> x.name\n  }\n//│ f: (Parent with {name: 'name}) -> 'name\n//│  = [Function: f]\n\nf c\n//│ res: \"Bob\"\n//│    = 'Bob'\n\nf (c: Parent)\n//│ res: string\n//│    = 'Bob'\n\n\ndef f x = case x of {\n  | Child -> x.name\n  }\n//│ f: (Child\\age with {name: 'name}) -> 'name\n//│  = [Function: f1]\n\nf c\n//│ res: \"Bob\"\n//│    = 'Bob'\n\n:e\nf (c: Parent)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.74: \tf (c: Parent)\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── type `Parent` is not an instance of type `Child`\n//│ ║  l.74: \tf (c: Parent)\n//│ ║        \t      ^^^^^^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.64: \t  | Child -> x.name\n//│ ║        \t    ^^^^^\n//│ ╟── from reference:\n//│ ║  l.63: \tdef f x = case x of {\n//│ ╙──      \t               ^\n//│ res: error | string\n//│    = 'Bob'\n\n\ndef f x = case x of {\n  | Parent -> x.name\n  | _ -> \"\"\n  }\n//│ f: ((Parent with {name: 'name}) | ~Parent) -> (\"\" | 'name)\n//│  = [Function: f2]\n\nf c\n//│ res: \"\" | \"Bob\"\n//│    = 'Bob'\n\nf (c: Parent)\n//│ res: string\n//│    = 'Bob'\n\n\ndef f x = case x of {\n  | Parent -> x.name\n  | Child -> x.name\n  }\n//│ f: (Parent with {name: 'name}) -> 'name\n//│  = [Function: f3]\n\nf c\n//│ res: \"Bob\"\n//│    = 'Bob'\n\nf (c: Parent)\n//│ res: string\n//│    = 'Bob'\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/InheritSimple.mls",
    "content": "\nclass Parent: {}\n//│ Defined class Parent\n\nclass Child: Parent\n//│ Defined class Child\n\np = Parent{}\n//│ p: Parent\n//│  = Parent {}\n\nc = Child(p)\n//│ c: Child\n//│  = Child {}\n\n:e\nc.name\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.17: \tc.name\n//│ ║        \t^^^^^^\n//│ ╟── application of type `Child` does not have field 'name'\n//│ ║  l.12: \tc = Child(p)\n//│ ║        \t    ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{name: ?name}`\n//│ ║  l.17: \tc.name\n//│ ║        \t^\n//│ ╟── Note: class Child is defined at:\n//│ ║  l.5: \tclass Child: Parent\n//│ ╙──     \t      ^^^^^\n//│ res: error\n//│    = undefined\n\nc: Child\n//│ res: Child\n//│    = Child {}\n\nc: Parent\n//│ res: Parent\n//│    = Child {}\n\nc: Parent & Child\n//│ res: Child & Parent\n//│    = Child {}\n\nc: Parent & Child & {}\n//│ res: Child & Parent\n//│    = Child {}\n\nc: Parent & anything & Child & {}\n//│ res: Child & Parent\n//│    = Child {}\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/JetBrains.mls",
    "content": "\nclass Expr\nclass Lit: Expr & { val: int }\nclass Add: Expr & { lhs: Expr; rhs: Expr }\n//│ Defined class Expr\n//│ Defined class Lit\n//│ Defined class Add\n\nrec def eval x = case x of {\n  Lit -> x.val\n  | Add -> eval x.lhs + eval x.rhs\n  }\n//│ eval: 'a -> int\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit\n//│     = [Function: eval]\n\ndef eval eval x = case x of {\n  Lit -> x.val\n  | Add -> eval eval x.lhs + eval eval x.rhs\n  }\n//│ eval: ('a -> 'lhs -> int & 'a) -> ((Add with {lhs: 'lhs, rhs: 'lhs}) | (Lit with {val: 'val})) -> (int | 'val)\n//│     = [Function: eval1]\n\neval eval!\n//│ res: ((Add with {lhs: 'a, rhs: 'a}) | (Lit with {val: 'val})) -> (int | 'val)\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit\n//│    = [Function (anonymous)]\n\neval eval!\n//│ res: ((Add with {lhs: 'a, rhs: 'a}) | (Lit with {val: 'val})) -> (int | 'val)\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit\n//│    = [Function (anonymous)]\n\nclass Neg: Expr & { underlying: Expr }\n//│ Defined class Neg\n\ndef evalN evalN x = case x of {\n  Neg -> 0 - (evalN evalN x.underlying)\n  | _ -> eval evalN x\n  }\n//│ evalN: ('a -> 'lhs -> int & 'a) -> ((Add with {lhs: 'lhs, rhs: 'lhs}) | (Lit with {val: 'val}) | (Neg with {underlying: 'lhs})) -> (int | 'val)\n//│      = [Function: evalN]\n\nevalN evalN!\n//│ res: ((Add with {lhs: 'a, rhs: 'a}) | (Lit with {val: 'val}) | (Neg with {underlying: 'a})) -> (int | 'val)\n//│   where\n//│     'a <: (Add with {lhs: 'a, rhs: 'a}) | Lit | (Neg with {underlying: 'a})\n//│    = [Function (anonymous)]\n\ne = Add{lhs = Lit{val = 1}; rhs = Neg{underlying = Lit{val = 2}}}\n//│ e: Add with {lhs: Lit & {val: 1}, rhs: Neg with {underlying: Lit & {val: 2}}}\n//│  = Add { lhs: Lit { val: 1 }, rhs: Neg { underlying: Lit { val: 2 } } }\n\nevalN evalN! e\n//│ res: int\n//│    = -1\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\n\ndef evalN2 evalN2 x = case x of {\n  Neg -> 0 - (evalN2 evalN2 x.underlying)\n  | _ -> eval eval! x\n  }\n//│ evalN2: ('a -> 'underlying -> int & 'a) -> ((Add with {lhs: 'b, rhs: 'b}) | (Lit with {val: 'val}) | (Neg with {underlying: 'underlying})) -> (int | 'val)\n//│   where\n//│     'b <: (Add with {lhs: 'b, rhs: 'b}) | Lit\n\nevalN2 evalN2! e\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tevalN2 evalN2! e\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Neg & {underlying: ?underlying}` does not match type `Add & ?a | Lit & ?b`\n//│ ║  l.53: \te = Add{lhs = Lit{val = 1}; rhs = Neg{underlying = Lit{val = 2}}}\n//│ ║        \t                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.18: \tdef eval eval x = case x of {\n//│ ║        \t                       ^\n//│ ╟── from field selection:\n//│ ║  l.20: \t  | Add -> eval eval x.lhs + eval eval x.rhs\n//│ ╙──      \t                                       ^^^^^\n//│ res: error | int\n\n\ndef evalN3 evalN3 x = case x of {\n  Neg -> 0 - (evalN2 x.underlying)\n  | _ -> eval evalN3 x\n  }\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+2: \t  Neg -> 0 - (evalN2 x.underlying)\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b ?c. ?b | ?c)` is not an instance of type `int`\n//│ ║  l.73: \tdef evalN2 evalN2 x = case x of {\n//│ ║        \t                  ^^^^^^^^^^^^^^^\n//│ ║  l.74: \t  Neg -> 0 - (evalN2 evalN2 x.underlying)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.75: \t  | _ -> eval eval! x\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.76: \t  }\n//│ ║        \t^^^\n//│ ╟── but it flows into application with expected type `int`\n//│ ║  l.+2: \t  Neg -> 0 - (evalN2 x.underlying)\n//│ ╙──      \t              ^^^^^^^^^^^^^^^^^^^\n//│ evalN3: ('a -> 'lhs -> int & 'a) -> ((Add with {lhs: 'lhs, rhs: 'lhs}) | (Lit with {val: 'val}) | (Neg with {underlying: 'b -> nothing -> int & 'b})) -> (error | int | 'val)\n\ndef evalN3 evalN3 x = case x of {\n  Neg -> 0 - (evalN3 x.underlying)\n  | _ -> eval evalN3 x\n  }\n//│ evalN3: ('underlying -> int & 'a -> 'lhs -> int & 'a) -> ((Add with {lhs: 'lhs, rhs: 'lhs}) | (Lit with {val: 'val}) | (Neg with {underlying: 'underlying})) -> (int | 'val)\n\nevalN3 evalN3! e\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tevalN3 evalN3! e\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (?b | ?c)` is not an instance of type `int`\n//│ ║  l.118: \tdef evalN3 evalN3 x = case x of {\n//│ ║         \t                  ^^^^^^^^^^^^^^^\n//│ ║  l.119: \t  Neg -> 0 - (evalN3 x.underlying)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.120: \t  | _ -> eval evalN3 x\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.121: \t  }\n//│ ║         \t^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.119: \t  Neg -> 0 - (evalN3 x.underlying)\n//│ ╙──       \t              ^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tevalN3 evalN3! e\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Lit & {val: ?val}` is not a function\n//│ ║  l.53: \te = Add{lhs = Lit{val = 1}; rhs = Neg{underlying = Lit{val = 2}}}\n//│ ║        \t                                                   ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.20: \t  | Add -> eval eval x.lhs + eval eval x.rhs\n//│ ║        \t                             ^^^^^^^^^\n//│ ╟── from field selection:\n//│ ║  l.119: \t  Neg -> 0 - (evalN3 x.underlying)\n//│ ╙──       \t                     ^^^^^^^^^^^^\n//│ res: error | int\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/LetPolym.mls",
    "content": "\ndef test f =\n  let local x = f x\n  in (local 0, local true)\n//│ test: ((0 | true) -> 'a) -> ('a, 'a,)\n//│     = [Function: test]\n\ndef test f =\n  let local x = f x\n  in (local (fun z -> z), local (fun z -> true))\n//│ test: ((forall 'a. 'a -> (true | 'a)) -> 'b) -> ('b, 'b,)\n//│     = [Function: test1]\n\ndef test f =\n  let local x = x f\n  in (local (fun z -> z), local (fun z -> true))\n//│ test: 'a -> ('a, true,)\n//│     = [Function: test2]\n\ndef test f a b =\n  let local x = f x\n  in (local a, local b)\n//│ test: ('a -> 'b) -> 'a -> 'a -> ('b, 'b,)\n//│     = [Function: test3]\n\ndef test x =\n  let local g = g x\n  in local succ\n//│ test: int -> int\n//│     = [Function: test4]\n\ntest 1\n//│ res: int\n//│    = 2\n\n:e\ntest \"hi\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.37: \ttest \"hi\"\n//│ ║        \t^^^^^^^^^\n//│ ╟── string literal of type `\"hi\"` is not an instance of type `int`\n//│ ║  l.37: \ttest \"hi\"\n//│ ║        \t     ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.27: \t  let local g = g x\n//│ ╙──      \t                  ^\n//│ res: error | int\n//│    = 'hi1'\n\ndef test f =\n  let local() = succ (f 1)\n  in local()\n//│ test: (1 -> int) -> int\n//│     = [Function: test5]\n\ntest succ\ntest id\n//│ res: int\n//│    = 3\n//│ res: int\n//│    = 2\n\n:e\ntest (fun x -> false)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.64: \ttest (fun x -> false)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.64: \ttest (fun x -> false)\n//│ ║        \t               ^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.51: \t  let local() = succ (f 1)\n//│ ╙──      \t                      ^^^\n//│ res: error | int\n//│    = 1\n\n:e\ntest concat\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.78: \ttest concat\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `string`\n//│ ║  l.51: \t  let local() = succ (f 1)\n//│ ╙──      \t                        ^\n//│ res: error | int\n//│    = '(y) => x + y1'\n\ndef test f =\n  let local g = g f\n  in local succ\n//│ test: int -> int\n//│     = [Function: test6]\n\ndef test f =\n  let local g = g (f 1)\n  in local succ\n//│ test: (1 -> int) -> int\n//│     = [Function: test7]\n\n:e\ntest (fun x -> \"oops\")\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.101: \ttest (fun x -> \"oops\")\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.101: \ttest (fun x -> \"oops\")\n//│ ║         \t               ^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.95: \t  let local g = g (f 1)\n//│ ╙──      \t                   ^^^\n//│ res: error | int\n//│    = 'oops1'\n\n\ndef test f =\n  let local g x = g (f x)\n  in local succ\n//│ test: ('a -> int) -> 'a -> int\n//│     = [Function: test8]\n\ndef test f =\n  let local g x = g (f x)\n  in local add\n//│ test: ('a -> int) -> 'a -> int -> int\n//│     = [Function: test9]\n\ndef test f =\n  let local g x = g (f x)\n  in local add 1\n//│ test: (1 -> int) -> int -> int\n//│     = [Function: test10]\n\ndef test f =\n  let local g x = g (f x)\n  in (local add 1, local (fun y -> fun z -> y + z) 2)\n//│ test: ((1 | 2) -> int) -> (int -> int, int -> int,)\n//│     = [Function: test11]\n\nf_g = test succ\nf_g.0 42\nf_g.1 42\n//│ f_g: (int -> int, int -> int,)\n//│    = [ [Function (anonymous)], [Function (anonymous)] ]\n//│ res: int\n//│    = 44\n//│ res: int\n//│    = 45\n\n\ndef test f =\n  let local g x = g (f x)\n  in (local add 1, local concat \"ok\")\n//│ test: ((\"ok\" | 1) -> nothing) -> (int -> int, string -> string,)\n//│     = [Function: test12]\n\n:e\ntest succ\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.157: \ttest succ\n//│ ║         \t^^^^^^^^^\n//│ ╟── string literal of type `\"ok\"` is not an instance of type `int`\n//│ ║  l.152: \t  in (local add 1, local concat \"ok\")\n//│ ╙──       \t                                ^^^^\n//│ res: error | (int -> int, string -> string,)\n//│    = [ [Function (anonymous)], [Function (anonymous)] ]\n\n\ndef test =\n  (fun f ->\n    let local g x = f (g x)\n    in local\n  ) add\n//│ test: ('a -> int) -> 'a -> int -> int\n//│     = [Function: test13]\n\ndef test =\n  (fun f -> fun x ->\n    let local g = f (g x)\n    in local\n  ) add \"1\"\n//│ test: (\"1\" -> int) -> int -> int\n//│     = [Function: test14]\n\ndef test =\n  (fun f -> fun x ->\n    let local g = f (g x)\n    in local add \"1\"\n  )\n//│ test: ((int -> int) -> \"1\" -> 'a) -> int -> 'a\n//│     = [Function: test15]\n\nfun f -> fun x ->\n  let local = (fun y -> f y) x\n  in ()\n//│ res: ('a -> anything) -> 'a -> ()\n//│    = [Function: res]\n\n:e\nres add \"1\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.199: \tres add \"1\"\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── string literal of type `\"1\"` is not an instance of type `int`\n//│ ║  l.199: \tres add \"1\"\n//│ ║         \t        ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.193: \t  let local = (fun y -> f y) x\n//│ ║         \t                          ^\n//│ ╟── from reference:\n//│ ║  l.193: \t  let local = (fun y -> f y) x\n//│ ╙──       \t                             ^\n//│ res: error | ()\n//│    = []\n\nfun f -> fun x ->\n  let local = f ((fun y -> y) x)\n  in ()\n//│ res: ('a -> anything) -> 'a -> ()\n//│    = [Function: res]\n\n:e\nres add \"1\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.222: \tres add \"1\"\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── string literal of type `\"1\"` is not an instance of type `int`\n//│ ║  l.222: \tres add \"1\"\n//│ ║         \t        ^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.216: \t  let local = f ((fun y -> y) x)\n//│ ║         \t                 ^^^^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.216: \t  let local = f ((fun y -> y) x)\n//│ ╙──       \t                              ^\n//│ res: error | ()\n//│    = []\n\ndef id: 'a -> 'a\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n\nfun f -> fun x ->\n  let local = f (id x)\n  in ()\n//│ res: ('a -> anything) -> 'a -> ()\n//│    = <no result>\n//│      id is not implemented\n\n:e\n(fun k -> k (fun x ->\n    let tmp = add x 1 in x\n  )) (fun f -> f true)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.250: \t(fun k -> k (fun x ->\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.251: \t    let tmp = add x 1 in x\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.252: \t  )) (fun f -> f true)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.252: \t  )) (fun f -> f true)\n//│ ║         \t                 ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.251: \t    let tmp = add x 1 in x\n//│ ╙──       \t                  ^\n//│ res: error | true\n//│    = true\n\n:e\n(fun k ->\n    let test = k (fun x ->\n      let tmp = add x 1 in x\n    ) in test\n  ) (fun f -> f true)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.270: \t(fun k ->\n//│ ║         \t^^^^^^^^^\n//│ ║  l.271: \t    let test = k (fun x ->\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.272: \t      let tmp = add x 1 in x\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.273: \t    ) in test\n//│ ║         \t^^^^^^^^^^^^^\n//│ ║  l.274: \t  ) (fun f -> f true)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.274: \t  ) (fun f -> f true)\n//│ ║         \t                ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.272: \t      let tmp = add x 1 in x\n//│ ╙──       \t                    ^\n//│ res: error | true\n//│    = true\n\n\n\ndef fst ((a, b)) = a\ndef snd ((a, b)) = b\n//│ fst: (('a, anything,),) -> 'a\n//│    = [Function: fst]\n//│ snd: ((anything, 'a,),) -> 'a\n//│    = [Function: snd]\n\ndef foo f =\n  let x = f 42\n  in fst x + snd x\n//│ foo: (42 -> (int, int,)) -> int\n//│    = [Function: foo]\n\ndef foo f =\n  let x = f 42\n  in fst x + snd x\n//│ foo: (42 -> (int, int,)) -> int\n//│    = [Function: foo1]\n\nfoo (fun x -> (x, x))\nfoo (fun x -> (0, x + 1))\n//│ res: int\n//│    = 84\n//│ res: int\n//│    = 43\n\ndef foo (f: 'a -> ('a, 'a)) =\n  let x = f 42\n  in fst x + snd x\n//│ foo: ((42 | 'a) -> (int & 'a, int & 'a,)) -> int\n//│    = [Function: foo2]\n\nfoo (fun x -> (x, x))\nfoo (fun x -> (0, x + 1))\n//│ res: int\n//│    = 84\n//│ res: int\n//│    = 43\n\ndef foo (f: forall 'a. 'a -> ('a, 'a)) =\n  let x = f 42\n  in fst x + snd x\n//│ foo: (forall 'a. 'a -> ('a, 'a,)) -> int\n//│    = [Function: foo3]\n\nfoo (fun x -> (x, x))\n//│ res: int\n//│    = 84\n\n:e\nfoo (fun x -> (0, x + 1))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.347: \tfoo (fun x -> (0, x + 1))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.336: \tdef foo (f: forall 'a. 'a -> ('a, 'a)) =\n//│ ║         \t                       ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.347: \tfoo (fun x -> (0, x + 1))\n//│ ║         \t                  ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.336: \tdef foo (f: forall 'a. 'a -> ('a, 'a)) =\n//│ ╙──       \t                   ^^\n//│ res: error | int\n//│    = 43\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/LineComments.mls",
    "content": "\n1\n2\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n\n1\n// A\n2\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Lists.mls",
    "content": "\nclass Nil: {}\nclass Cons[A]: { head: A; tail: List[A] }\ntype List[A] = Nil | Cons[A]\n//│ Defined class Nil\n//│ Defined class Cons[+A]\n//│ Defined type alias List[+A]\n\ndef originalCons = Cons  // Note: type still seems over-complicated because we push 'b inside the union, killing a hash-consing opportunity at the outer level...\n//│ originalCons: {head: 'head & 'A, tail: List['A] & 'tail} -> (Cons['A] with {head: 'head, tail: 'tail})\n//│             = [Function: originalCons]\n\ndef Nil = Nil {}\n//│ Nil: Nil\n//│    = [Function: Nil1]\n\ndef Cons head tail = Cons { head; tail }\n//│ Cons: ('head & 'A) -> (List['A] & 'tail) -> (Cons['A] with {head: 'head, tail: 'tail})\n//│     = [Function: Cons1]\n\n\nCons 2\n//│ res: (List['A] & 'tail) -> (Cons[2 | 'A] with {head: 2, tail: 'tail})\n//│    = [Function (anonymous)]\n\nc = Cons 2 Nil\n//│ c: Cons[2] with {tail: Nil}\n//│  = Cons { head: 2, tail: Nil {} }\n\nd = Cons 1 c\n//│ d: Cons[1 | 2] with {head: 1, tail: Cons[2] with {tail: Nil}}\n//│  = Cons { head: 1, tail: Cons { head: 2, tail: Nil {} } }\n\nd.head\n//│ res: 1\n//│    = 1\n\nres: 1\n//│ res: 1\n//│    = 1\n\nd.tail\n//│ res: Cons[2] with {tail: Nil}\n//│    = Cons { head: 2, tail: Nil {} }\n\nCons 1 res\n//│ res: Cons[1 | 2] with {head: 1, tail: Cons[2] with {tail: Nil}}\n//│    = Cons { head: 1, tail: Cons { head: 2, tail: Nil {} } }\n\nres.tail\n//│ res: Cons[2] with {tail: Nil}\n//│    = Cons { head: 2, tail: Nil {} }\n\nCons 1 (Cons 2 Nil)\n//│ res: Cons[1 | 2] with {head: 1, tail: Cons[2] with {tail: Nil}}\n//│    = Cons { head: 1, tail: Cons { head: 2, tail: Nil {} } }\n\nres.tail\n//│ res: Cons[2] with {tail: Nil}\n//│    = Cons { head: 2, tail: Nil {} }\n\n// We can now access the tail's tail, thanks to the refined type\nres.tail\n//│ res: Nil\n//│    = Nil {}\n\n:e\nres.tail.head\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.68: \tres.tail.head\n//│ ║        \t^^^^^^^^\n//│ ╟── application of type `Nil` does not have field 'tail'\n//│ ║  l.13: \tdef Nil = Nil {}\n//│ ║        \t          ^^^^^^\n//│ ╟── but it flows into reference with expected type `{tail: ?tail}`\n//│ ║  l.68: \tres.tail.head\n//│ ║        \t^^^\n//│ ╟── Note: class Nil is defined at:\n//│ ║  l.2: \tclass Nil: {}\n//│ ╙──     \t      ^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading 'head')\n\n\n\n// This used to yield a more precise Cons constructor, but it's no longer necessary in the new class semantics\ndef Cons head tail = originalCons { head; tail } with { head; tail }\n//│ Cons: ('A & 'head) -> (List['A] & 'tail) -> (Cons['A] & {head: 'head, tail: 'tail})\n//│     = [Function: Cons2]\n\n\nCons 2\n//│ res: (List['A] & 'tail) -> (Cons[2 | 'A] & {head: 2, tail: 'tail})\n//│    = [Function (anonymous)]\n\nCons 2 Nil\n//│ res: Cons[2] with {tail: Nil}\n//│    = Cons { head: 2, tail: Nil {} }\n\nres.head\n//│ res: 2\n//│    = 2\n\n:e\nCons 1 res\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.106: \tCons 1 res\n//│ ║         \t^^^^^^^^^^\n//│ ╟── integer literal of type `2` does not match type `Cons[?A] | Nil`\n//│ ║  l.97: \tCons 2 Nil\n//│ ║        \t     ^\n//│ ╟── but it flows into reference with expected type `Cons[?A0] | Nil`\n//│ ║  l.106: \tCons 1 res\n//│ ║         \t       ^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.4: \ttype List[A] = Nil | Cons[A]\n//│ ║       \t               ^^^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.88: \tdef Cons head tail = originalCons { head; tail } with { head; tail }\n//│ ╙──      \t                                          ^^^^\n//│ res: (Cons[1] with {tail: 2}) | error\n//│    = Cons { head: 1, tail: 2 }\n\n// Here there used to be a loss of precision in the older with-field approach.\n//    The problem occured when constraining `α8 w/ {head: α5, tail: [α6]}  <!  nil | {head: α2}`\n//    as we can't decide whether to constrain `α8 <! nil` or `α5 <! α2`...\n// I seemingly solved it by just pushing `with` extensions applied on variables to the right\n//    just long enough to push it back on the left after travsering type variable bounds...\n//    This is okay because `with` types otherwise never occur in negative position... Note we could\n//    have used a different \"delayed with\" type to be cleaner, though it's just not necessary.\n// But then I reverted to the use of simple field-hiding types, as they are simpler!\n// \nCons 1 (Cons 2 Nil)\n//│ res: Cons[1 | 2] with {head: 1, tail: Cons[2] with {tail: Nil}}\n//│    = Cons { head: 1, tail: Cons { head: 2, tail: Nil {} } }\n\n{ a = res.head; b = res.tail.head; c = res.tail.tail }\n//│ res: {a: 1, b: 2, c: Nil}\n//│    = { a: 1, b: 2, c: Nil {} }\n\nCons 2 Nil\n//│ res: Cons[2] with {tail: Nil}\n//│    = Cons { head: 2, tail: Nil {} }\n\nCons 1 (id res)\n//│ res: Cons[1 | 2] with {head: 1, tail: Cons[2] with {tail: Nil}}\n//│    = Cons { head: 1, tail: Cons { head: 2, tail: Nil {} } }\n\n{ a = res.head; b = res.tail.head; c = res.tail.tail }\n//│ res: {a: 1, b: 2, c: Nil}\n//│    = { a: 1, b: 2, c: Nil {} }\n\n\n\nrec def filter p ls = case ls of\n  { Cons -> if p ls.head then Cons ls.head (filter p ls.tail) else filter p ls.tail\n  | Nil -> Nil\n  }\n//│ filter: ('head -> bool) -> 'a -> 'b\n//│   where\n//│     'b :> (Cons['head] with {tail: 'b}) | Nil\n//│     'a <: (Cons[?] with {head: 'head, tail: 'a}) | Nil\n//│       = [Function: filter]\n\n\n\n\ndef Cons head = originalCons { head=0; tail=Nil } with { head }\n//│ Cons: 'a -> (Cons[0] with {head: 'a, tail: Nil})\n//│     = [Function: Cons3]\n\nCons 1\n//│ res: Cons[0] with {head: 1, tail: Nil}\n//│    = Cons { head: 1, tail: Nil {} }\n\nres.head\n//│ res: 1\n//│    = 1\n\nc = Cons 1\n//│ c: Cons[0] with {head: 1, tail: Nil}\n//│  = Cons { head: 1, tail: Nil {} }\n\nc.head\n//│ res: 1\n//│    = 1\n\ndef c: 'a -> List['b] -> List['a | 'b]\nc 1 (c 2 Nil)\n//│ c: 'a -> List['a] -> List['a]\n//│  = <missing implementation>\n//│ res: List[1 | 2]\n//│    = <no result>\n//│      c is not implemented\n\ndef c: 'a -> ('l & List['b]) -> (Cons[anything] & { head: 'a; tail: 'l })\nc 1 (c 2 Nil)\n//│ c: 'a -> (List[?] & 'l) -> (Cons[?] with {head: 'a, tail: 'l})\n//│  = <missing implementation>\n//│ res: Cons[?] with {head: 1, tail: Cons[?] with {head: 2, tail: Nil}}\n//│    = <no result>\n//│      c is not implemented\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Luyu.mls",
    "content": "\n\n// Preamble\ndef plus1 x = x + 1\n//│ plus1: int -> int\n//│      = [Function: plus1]\n\nclass JustIntBox: { value: int }\n  method Get = this.value\n//│ Defined class JustIntBox\n//│ Defined JustIntBox.Get: JustIntBox -> int\n\nib0 = JustIntBox { value = 0 }\n//│ ib0: JustIntBox & {value: 0}\n//│    = JustIntBox { value: 0 }\n\nib0.Get\n//│ res: int\n//│    = 0\n\n// Extend with some function.\nclass MappableIntBox: JustIntBox\n  method Map f = MappableIntBox { value = f this.value }\n//│ Defined class MappableIntBox\n//│ Defined MappableIntBox.Map: MappableIntBox -> (int -> (int & 'value)) -> (MappableIntBox with {value: 'value})\n\nmib0 = MappableIntBox { value = 0 }\n//│ mib0: MappableIntBox & {value: 0}\n//│     = MappableIntBox { value: 0 }\n\nmib0.Get\n//│ res: int\n//│    = 0\n\nmib0.Map\n//│ res: (int -> (int & 'value)) -> (MappableIntBox with {value: 'value})\n//│    = [Function: Map]\n\nmib0.Map plus1\n//│ res: MappableIntBox\n//│    = MappableIntBox { value: 1 }\n\n// Naughty map...\n:e\nmib0.Map (fun _ -> \"str\")\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.45: \tmib0.Map (fun _ -> \"str\")\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"str\"` is not an instance of type `int`\n//│ ║  l.45: \tmib0.Map (fun _ -> \"str\")\n//│ ║        \t                   ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.8: \tclass JustIntBox: { value: int }\n//│ ║       \t                           ^^^\n//│ ╟── from application:\n//│ ║  l.23: \t  method Map f = MappableIntBox { value = f this.value }\n//│ ╙──      \t                                          ^^^^^^^^^^^^\n//│ res: (MappableIntBox with {value: \"str\"}) | error\n//│    = MappableIntBox { value: 'str' }\n\nclass BetterIntBox: { value: int }\n  method Get = this.value\n  method Map f = BetterIntBox { value = f this.value }\n//│ Defined class BetterIntBox\n//│ Defined BetterIntBox.Get: BetterIntBox -> int\n//│ Defined BetterIntBox.Map: BetterIntBox -> (int -> (int & 'value)) -> (BetterIntBox with {value: 'value})\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/MLList.mls",
    "content": "\nclass List[A]\n  method Fold: (() -> 'b, (A, List[A]) -> 'b) -> 'b\nclass Nil[A]: List[A]\n  method Fold(f, _) = f()\nclass Cons[A]: List[A] & { head: A; tail: List[A] }\n  method Fold(_, f) = f(this.head, this.tail)\n//│ Defined class List[+A]\n//│ Declared List.Fold: List['A] -> (() -> 'b, ('A, List['A],) -> 'b,) -> 'b\n//│ Defined class Nil[+A]\n//│ Defined Nil.Fold: Nil[?] -> (() -> 'a, anything,) -> 'a\n//│ Defined class Cons[+A]\n//│ Defined Cons.Fold: Cons['A] -> (anything, ('A, List['A],) -> 'a,) -> 'a\n\ndef nil = Nil {} : List['a]\ndef cons(head, tail) = Cons { head; tail } : List['a]\n//│ nil: List[nothing]\n//│    = [Function: nil]\n//│ cons: ('a, List['a],) -> List['a]\n//│     = [Function: cons]\n\nrec def find(table, key) =\n  table.Fold(\n    fun () -> undefined,\n    fun (h, t) -> if eq h.key key then h.val else find(t, key))\n//│ find: (List[{key: anything, val: 'a}], anything,) -> (undefined | 'a)\n//│     = [Function: find]\n\nls = cons({key=\"I\"; val=id}, cons({key=\"omega\"; val=fun x -> x x}, nil))\n//│ ls: List[{key: \"I\" | \"omega\", val: forall 'a 'b 'c. ('a -> 'b & 'c & 'a) -> ('c | 'b)}]\n//│   = Cons {\n//│       head: { key: 'I', val: [Function: id] },\n//│       tail: Cons { head: { key: 'omega', val: [Function: val] }, tail: Nil {} }\n//│     }\n\nres = find(ls, \"omega\")\n//│ res: undefined | ('a -> 'b & 'b & 'a) -> 'b\n//│    = [Function: val]\n\ncase res of undefined -> \"???\", _ -> res id \"!\"\n//│ res: \"!\" | \"???\"\n//│    = '!'\n\nfind(ls, \"oops\")\n//│ res: undefined | ('a -> 'b & 'c & 'a) -> ('c | 'b)\n//│    = undefined\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/MLTuples.mls",
    "content": "\nt = (1, 2, 3)\n//│ t: (1, 2, 3,)\n//│  = [ 1, 2, 3 ]\n\n{} with {}\n//│ res: anything\n//│    = {}\n\n:js\ntx = t with { x = 1 }\n//│ // Query 1\n//│ globalThis.tx = withConstruct(t, { x: 1 });\n//│ // End of generated code\n//│ tx: (1, 2, 3,) & {x: 1}\n//│   = [ 1, 2, 3, x: 1 ]\n\ntx.x\n//│ res: 1\n//│    = 1\n\ntrait Hey: { x: int }\n//│ Defined trait Hey\n\n:e\nHey t\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.26: \tHey t\n//│ ║        \t^^^^^\n//│ ╟── tuple literal of type `{0: 1, 1: 2, 2: 3}` does not have field 'x'\n//│ ║  l.2: \tt = (1, 2, 3)\n//│ ║       \t    ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{x: int}`\n//│ ║  l.26: \tHey t\n//│ ║        \t    ^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.22: \ttrait Hey: { x: int }\n//│ ╙──      \t           ^^^^^^^^^^\n//│ res: error | (1, 2, 3,) & #Hey\n//│    = [ 1, 2, 3 ]\n\nhtx = Hey tx\n//│ htx: (1, 2, 3,) & {x: 1} & #Hey\n//│    = [ 1, 2, 3, x: 1 ]\n\nhtx.x\n//│ res: 1\n//│    = 1\n\nf ((a, b, c)) = { a; b; c }\n//│ f: (('a, 'b, 'c,),) -> {a: 'a, b: 'b, c: 'c}\n//│  = [Function: f]\n\nf t\n//│ res: {a: 1, b: 2, c: 3}\n//│    = { a: 1, b: 2, c: 3 }\n\nf tx\n//│ res: {a: 1, b: 2, c: 3}\n//│    = { a: 1, b: 2, c: 3 }\n\nf htx\n//│ res: {a: 1, b: 2, c: 3}\n//│    = { a: 1, b: 2, c: 3 }\n\nf ((a, b)) = add a b\n//│ f: ((int, int,),) -> int\n//│  = [Function: f1]\n\n:e\nf t\nf tx\nf htx\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.71: \tf t\n//│ ║        \t^^^\n//│ ╟── tuple literal of type `(1, 2, 3,)` does not match type `(?a, ?b,)`\n//│ ║  l.2: \tt = (1, 2, 3)\n//│ ║       \t    ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(?c, ?d,)`\n//│ ║  l.71: \tf t\n//│ ║        \t  ^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.66: \tf ((a, b)) = add a b\n//│ ╙──      \t   ^^^^^^\n//│ res: error | int\n//│    = 3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.72: \tf tx\n//│ ║        \t^^^^\n//│ ╟── `with` extension of type `(1, 2, 3,) & {x: 1}` is not a 2-element tuple\n//│ ║  l.11: \ttx = t with { x = 1 }\n//│ ║        \t     ^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(?a, ?b,)`\n//│ ║  l.72: \tf tx\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.66: \tf ((a, b)) = add a b\n//│ ╙──      \t   ^^^^^^\n//│ res: error | int\n//│    = 3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.73: \tf htx\n//│ ║        \t^^^^^\n//│ ╟── `with` extension of type `(1, 2, 3,) & {x: 1}` does not match type `(?a, ?b,) | ~#Hey`\n//│ ║  l.11: \ttx = t with { x = 1 }\n//│ ║        \t     ^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(?c, ?d,) | ~#Hey`\n//│ ║  l.73: \tf htx\n//│ ║        \t  ^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.66: \tf ((a, b)) = add a b\n//│ ╙──      \t   ^^^^^^\n//│ res: error | int\n//│    = 3\n\n\ng arg = case arg of { Hey -> arg.x | _ -> () }\n//│ g: ({x: 'x} & #Hey | ~#Hey) -> (() | 'x)\n//│  = [Function: g]\n\ng htx\ng tx\n//│ res: 1 | ()\n//│    = 1\n//│ res: 1 | ()\n//│    = 1\n\n// TODO: pattern match for traits in JavaScript\ng arg = case arg of { Hey -> arg.x | _ -> arg.y }\n//│ g: ({y: 'x} & ~#Hey | {x: 'x} & #Hey) -> 'x\n//│  = [Function: g1]\n\ng htx\ng (tx with { y = 2 })\n//│ res: 1\n//│    = 1\n//│ res: 1 | 2\n//│    = 2\n\n:e\ng tx\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.142: \tg tx\n//│ ║         \t^^^^\n//│ ╟── expression of type `(1, 2, 3,) & {x: 1} & ~#Hey` does not have field 'y'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.130: \tg arg = case arg of { Hey -> arg.x | _ -> arg.y }\n//│ ╙──       \t                                          ^^^^^\n//│ res: 1 | error\n//│    = 1\n\n:ge\nif bool then (1,) else (2,)\n//│ res: (1 | 2,)\n//│ Code generation encountered an error:\n//│   type alias bool is not a valid expression\n\n:ge\nif bool then (1,) else (2, 3)\n//│ res: Array[1 | 2 | 3] & {0: 1 | 2}\n//│ Code generation encountered an error:\n//│   type alias bool is not a valid expression\n\n:ge\nif bool then (1,) with { a = 1; b = 2 } else (2, 3) with { b = 3; c = 4 }\n//│ res: Array[1 | 2 | 3] & {0: 1 | 2, b: 2 | 3}\n//│ Code generation encountered an error:\n//│   type alias bool is not a valid expression\n\n:ge\nif bool then (1,) else fun x -> x\n//│ res: anything\n//│ Code generation encountered an error:\n//│   type alias bool is not a valid expression\n\n\n\nt.0\nt.1\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n\n\nt = (1, 2, 3) with {x = 1}\n// t = (1, 2, 3)\n//│ t: (1, 2, 3,) & {x: 1}\n//│  = [ 1, 2, 3, x: 1 ]\n\nt.x\n//│ res: 1\n//│    = 1\n\nt.0\nt.1\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n\n\nt = (1, 2, 3) with {0 = \"oops\"}\n//│ t: {0: \"oops\", 1: 2, 2: 3}\n//│  = [ 'oops', 2, 3 ]\n\n// TODO (https://github.com/hkust-taco/mlscript/issues/69)\n:e\n(t: (\"oops\",int,int,)).0\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.210: \t(t: (\"oops\",int,int,)).0\n//│ ║         \t ^\n//│ ╟── `with` extension of type `{0: \"oops\", 1: 2, 2: 3}` is not a 3-element tuple\n//│ ║  l.204: \tt = (1, 2, 3) with {0 = \"oops\"}\n//│ ║         \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(\"oops\", int, int,)`\n//│ ║  l.210: \t(t: (\"oops\",int,int,)).0\n//│ ║         \t ^\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.210: \t(t: (\"oops\",int,int,)).0\n//│ ╙──       \t    ^^^^^^^^^^^^^^^^^\n//│ res: \"oops\"\n//│    = 'oops'\n\n\ndef f: (1, 2, 3) & (2, 2 | 3, 3 | 4)\n//│ f: (nothing, 2, 3,)\n//│  = <missing implementation>\n\ndef f: (1, 2, 3) & (2, 3)\n//│ f: nothing\n//│  = <missing implementation>\n\ndef f: (1, 2, 3) & Array[2 | 3 | 4]\n//│ f: (nothing, 2, 3,)\n//│  = <missing implementation>\n\n\n\na = (if true then (0, 1) else (2, 1, 2))[1]\n//│ a: 0 | 1 | 2 | undefined\n//│  = 1\n\ncase a of\n  undefined -> 0, _ -> a\n//│ res: 0 | 1 | 2\n//│    = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Match1.mls",
    "content": "\n1\n//│ res: 1\n//│    = 1\n\n:e\ncase 1 of { }\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.7: \tcase 1 of { }\n//│ ║       \t^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `nothing`\n//│ ║  l.7: \tcase 1 of { }\n//│ ╙──     \t     ^\n//│ res: nothing\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n:e\n:ge\ncase 1 of { A -> 0 }\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.20: \tcase 1 of { A -> 0 }\n//│ ╙──      \t            ^\n//│ res: error\n//│ Code generation encountered an error:\n//│   unknown match case: A\n\n:e\n:ge\ncase 1 of { A -> 0 | B -> 1 }\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.30: \tcase 1 of { A -> 0 | B -> 1 }\n//│ ╙──      \t            ^\n//│ res: error\n//│ Code generation encountered an error:\n//│   unknown match case: B\n\n:e\n:ge\ndef f = fun x -> case x of { Foo -> 0 | Bar -> 1 }\n//│ ╔══[ERROR] type identifier not found: Foo\n//│ ║  l.40: \tdef f = fun x -> case x of { Foo -> 0 | Bar -> 1 }\n//│ ╙──      \t                             ^^^\n//│ f: error -> error\n//│ Code generation encountered an error:\n//│   unknown match case: Bar\n\n:e\n:ge\ndef f = fun x -> case x of\n  { Foo -> 0\n  | Bar -> 1\n  }\n//│ ╔══[ERROR] type identifier not found: Foo\n//│ ║  l.51: \t  { Foo -> 0\n//│ ╙──      \t    ^^^\n//│ f: error -> error\n//│ Code generation encountered an error:\n//│   unknown match case: Bar\n\n:e\n:ge\ndef f = fun x -> case x of { Foo -> x | Bar -> x }\n//│ ╔══[ERROR] type identifier not found: Foo\n//│ ║  l.63: \tdef f = fun x -> case x of { Foo -> x | Bar -> x }\n//│ ╙──      \t                             ^^^\n//│ f: error -> error\n//│ Code generation encountered an error:\n//│   unknown match case: Bar\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Match2.mls",
    "content": "\nclass Test: { value: int }\n//│ Defined class Test\n\ndef foo x = case x of\n  { Test -> x.value\n  | _ -> 1\n  }\n//│ foo: ((Test with {value: 'value}) | ~Test) -> (1 | 'value)\n//│    = [Function: foo]\n\n// Q: why type of `value` widened?\nt = Test { value = 0 }\n//│ t: Test & {value: 0}\n//│  = Test { value: 0 }\n\nfoo Test\n//│ res: 1\n//│    = 1\n\nfoo t\n//│ res: 0 | 1\n//│    = 0\n\n\nclass Toast: { name: string }\n//│ Defined class Toast\n\ndef bar x = case x of\n  { Test -> x.value\n  | Toast -> x.name\n  }\n//│ bar: ((Test with {value: 'value}) | (Toast with {name: 'value})) -> 'value\n//│    = [Function: bar]\n\n:e\nbar Test\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.37: \tbar Test\n//│ ║        \t^^^^^^^^\n//│ ╟── reference of type `{value: ?value} -> (Test & {value: ?value})` does not match type `Test & ?a | Toast & ?b`\n//│ ║  l.37: \tbar Test\n//│ ║        \t    ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.29: \tdef bar x = case x of\n//│ ║        \t                 ^\n//│ ╟── Note: class constructor Test is defined at:\n//│ ║  l.2: \tclass Test: { value: int }\n//│ ╙──     \t      ^^^^\n//│ res: error\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n:e\nbar \"ops\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.55: \tbar \"ops\"\n//│ ║        \t^^^^^^^^^\n//│ ╟── string literal of type `\"ops\"` does not match type `Test & ?a | Toast & ?b`\n//│ ║  l.55: \tbar \"ops\"\n//│ ║        \t    ^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.29: \tdef bar x = case x of\n//│ ╙──      \t                 ^\n//│ res: error\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\ndef baz x = case x of\n  { Test -> x\n  | Toast -> x\n  }\n//│ baz: ('a & (Test | Toast)) -> 'a\n//│    = [Function: baz]\n\n:e\nbaz \"oops\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.78: \tbaz \"oops\"\n//│ ║        \t^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` does not match type `Test & ?a | Toast & ?b`\n//│ ║  l.78: \tbaz \"oops\"\n//│ ║        \t    ^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.70: \tdef baz x = case x of\n//│ ╙──      \t                 ^\n//│ res: error\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Match3.mls",
    "content": "\nclass N\nclass M\n//│ Defined class N\n//│ Defined class M\n\ndef eval_expr v =\n  case v of {\n    | M -> let tmp = v.l in v\n    | N -> v\n    }\n//│ eval_expr: (M & {l: anything} & 'a | N & 'a) -> 'a\n//│          = [Function: eval_expr]\n\neval_expr (N {})\n//│ res: N\n//│    = N {}\n\n:e\neval_expr (M {})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.20: \teval_expr (M {})\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── application of type `M` does not have field 'l'\n//│ ║  l.20: \teval_expr (M {})\n//│ ║        \t           ^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.9: \t    | M -> let tmp = v.l in v\n//│ ║       \t                     ^^^\n//│ ╟── from reference:\n//│ ║  l.8: \t  case v of {\n//│ ║       \t       ^\n//│ ╟── Note: class M is defined at:\n//│ ║  l.3: \tclass M\n//│ ╙──     \t      ^\n//│ res: M | error\n//│    = M {}\n\ndef eval_expr v =\n  case v of {\n    | M -> let tmp = v.l in tmp\n    | N -> v\n    }\n//│ eval_expr: (M & {l: 'l} | N & 'l) -> 'l\n//│          = [Function: eval_expr1]\n\neval_expr (N {})\n//│ res: N\n//│    = N {}\n\n:e\neval_expr (M {})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.52: \teval_expr (M {})\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── application of type `M` does not have field 'l'\n//│ ║  l.52: \teval_expr (M {})\n//│ ║        \t           ^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.41: \t    | M -> let tmp = v.l in tmp\n//│ ║        \t                     ^^^\n//│ ╟── from reference:\n//│ ║  l.40: \t  case v of {\n//│ ║        \t       ^\n//│ ╟── Note: class M is defined at:\n//│ ║  l.3: \tclass M\n//│ ╙──     \t      ^\n//│ res: error\n//│    = undefined\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/MatchBool.mls",
    "content": "\ndef absImpl lt x =\n  case lt of\n    { true -> x\n    | false -> 0 - x }\n//│ absImpl: Bool -> int -> int\n//│        = [Function: absImpl]\n\n// * TODO support this\n:e\ndef abs x =\n  let r = x < 0 in absImpl r x\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.12: \t  let r = x < 0 in absImpl r x\n//│ ║        \t                   ^^^^^^^^^\n//│ ╟── operator application of type `bool` does not match type `false & ?a | true & ?b`\n//│ ║  l.12: \t  let r = x < 0 in absImpl r x\n//│ ║        \t          ^^^^^\n//│ ╟── but it flows into reference with expected type `false & ?a | true & ?b`\n//│ ║  l.12: \t  let r = x < 0 in absImpl r x\n//│ ║        \t                           ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.3: \t  case lt of\n//│ ╙──     \t       ^^\n//│ abs: int -> (error | int)\n//│    = [Function: abs]\n\n\ndef neg b = case b of\n  { true -> false\n  | false -> true }\n//│ neg: Bool -> Bool\n//│    = [Function: neg]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/MethodAndMatches.mls",
    "content": ":w\nclass Base1[A]\n  method M1: A -> Base1[A]\nclass Derived1: Base1[int] & { x: int }\n  method M1 y = Derived1 { x = add this.x y }\n  method M2 = Derived1 { x = add this.x 1 }\nclass Derived2[C, D]: Base1[{ c: C; d: D }]\n  // method M1 { c, d } = Derived2 { c; d }\n  method M1 r = Derived2 { c = r.c; d = r.d }\nclass Derived3[C, D]: Base1[{ c: C; d: D }] & { c: C; d: D }\n  method M1 r = Derived3 { c = r.c; d = r.d }\ntype Type1[A] = Derived1 | Derived3['a, 'b]\n//│ Defined class Base1[-A]\n//│ Declared Base1.M1: Base1['A] -> 'A -> Base1['A]\n//│ Defined class Derived1\n//│ Defined Derived1.M1: Derived1 -> int -> Derived1\n//│ Defined Derived1.M2: Derived1 -> Derived1\n//│ Defined class Derived2[-C, -D]\n//│ Defined Derived2.M1: Derived2[?, ?] -> {c: anything, d: anything} -> Derived2[anything, anything]\n//│ Defined class Derived3[=C, =D]\n//│ Defined Derived3.M1: Derived3['C, 'D] -> {c: 'c & 'C0, d: 'd & 'D0} -> (Derived3['C0, 'D0] with {c: 'c, d: 'd})\n//│ Defined type alias Type1[±A]\n//│ ╔══[WARNING] Type definition Type1 has bivariant type parameters:\n//│ ║  l.12: \ttype Type1[A] = Derived1 | Derived3['a, 'b]\n//│ ║        \t     ^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.12: \ttype Type1[A] = Derived1 | Derived3['a, 'b]\n//│ ╙──      \t           ^\n// class Derived2[C, D]: Base1[C -> D]\n\ndef foo b x = case b of {\n  | Derived1 -> b.M2\n  | Base1 -> b.M1 x\n  }\n//│ foo: (Base1['A] & ~#Derived1 | Derived1) -> 'A -> (Base1['A] | Derived1)\n//│    = [Function: foo]\n\nd1 = Derived1 { x = 1 }\n//│ d1: Derived1 & {x: 1}\n//│   = Derived1 { x: 1 }\n\nfoo d1\nfoo d1 0\n//│ res: anything -> (Base1[anything] | Derived1)\n//│    = [Function (anonymous)]\n//│ res: Base1[anything] | Derived1\n//│    = Derived1 { x: 2 }\n\ndef bar0: Base1[int] -> int -> Base1[int]\nbar0 d1\nbar0 d1 0\n//│ bar0: Base1[int] -> int -> Base1[int]\n//│     = <missing implementation>\n//│ res: int -> Base1[int]\n//│    = <no result>\n//│      bar0 is not implemented\n//│ res: Base1[int]\n//│    = <no result>\n//│      bar0 is not implemented\n\n// This is ill-typed because type `Base1[int]` includes things like `Derived1\\x` (a `Derived` instance without an `x` field)\n:e\ndef bar0 = foo\n//│ (Base1['A] & ~#Derived1 | Derived1) -> 'A -> (Base1['A] | Derived1)\n//│   <:  bar0:\n//│ Base1[int] -> int -> Base1[int]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.63: \tdef bar0 = foo\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── expression of type `Base1[int] & ~?a | Derived1` does not have field 'x'\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.4: \tclass Derived1: Base1[int] & { x: int }\n//│ ║       \t                             ^^^^^^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.31: \tdef foo b x = case b of {\n//│ ╙──      \t                   ^\n//│     = [Function: bar0]\n\ndef bar1: Type1[int] -> int -> Type1[int]\nbar1 d1\nbar1 d1 0\n//│ bar1: Type1[?] -> int -> Type1[?]\n//│     = <missing implementation>\n//│ res: int -> Type1[?]\n//│    = <no result>\n//│      bar1 is not implemented\n//│ res: Type1[?]\n//│    = <no result>\n//│      bar1 is not implemented\n\n:e\ndef bar1 = foo\n//│ (Base1['A] & ~#Derived1 | Derived1) -> 'A -> (Base1['A] | Derived1)\n//│   <:  bar1:\n//│ Type1[?] -> int -> Type1[?]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.92: \tdef bar1 = foo\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type `int` is not a record (expected a record with fields: c, d)\n//│ ║  l.79: \tdef bar1: Type1[int] -> int -> Type1[int]\n//│ ║        \t                        ^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.10: \tclass Derived3[C, D]: Base1[{ c: C; d: D }] & { c: C; d: D }\n//│ ║        \t                            ^^^^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.33: \t  | Base1 -> b.M1 x\n//│ ╙──      \t                  ^\n//│     = [Function: bar1]\n\ndef bar2: Base1['a] -> 'a -> Base1['a]\nbar2 d1\nbar2 d1 0\n//│ bar2: Base1['a] -> 'a -> Base1['a]\n//│     = <missing implementation>\n//│ res: int -> Base1[int]\n//│    = <no result>\n//│      bar2 is not implemented\n//│ res: Base1[int]\n//│    = <no result>\n//│      bar2 is not implemented\n\n// Note that typing this would require GADT reasoning! Though it also suffers from the previous \"Derived1 with missing x field\" problem.\n:e\ndef bar2 = foo\n//│ (Base1['A] & ~#Derived1 | Derived1) -> 'A -> (Base1['A] | Derived1)\n//│   <:  bar2:\n//│ Base1['a] -> 'a -> Base1['a]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.124: \tdef bar2 = foo\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── type `int` does not match type `'a`\n//│ ║  l.4: \tclass Derived1: Base1[int] & { x: int }\n//│ ║       \t                      ^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.110: \tdef bar2: Base1['a] -> 'a -> Base1['a]\n//│ ╙──       \t                ^^\n//│     = [Function: bar2]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Methods.mls",
    "content": "\nclass Foo[A, B]: { x: A; y: B }\n    method Fun[C]: (A -> B -> C) -> (A -> B -> C)\n    method Fun[C, D] (f: C -> D) = f\n//│ Defined class Foo[=A, =B]\n//│ Declared Foo.Fun: Foo['A, 'B] -> ('A -> 'B -> 'C) -> 'A -> 'B -> 'C\n//│ Defined Foo.Fun: Foo['A, 'B] -> ('C -> 'D) -> 'C -> 'D\n\nclass Bar: Foo[int, bool]\n    method Fun f = f\n//│ Defined class Bar\n//│ Defined Bar.Fun: Bar -> 'a -> 'a\n\nFoo.Fun\nBar.Fun\n//│ res: Foo['A, 'B] -> ('A -> 'B -> 'C) -> 'A -> 'B -> 'C\n//│    = undefined\n//│ res: Bar -> (forall 'a. 'a -> 'a)\n//│    = undefined\n\nf = Foo { x = 1; y = 2 }\n//│ f: Foo['A, 'B] & {x: 1, y: 2}\n//│   where\n//│     'B :> 2\n//│     'A :> 1\n//│  = Foo { x: 1, y: 2 }\n\nf.(Foo.Fun)\n//│ res: ((1 | 'A) -> (2 | 'B) -> 'C) -> 'A -> 'B -> 'C\n//│    = undefined\n\n:re\nFoo.Fun f\n//│ res: ((1 | 'A) -> (2 | 'B) -> 'C) -> 'A -> 'B -> 'C\n//│ Runtime error:\n//│   TypeError: (intermediate value).Fun is not a function\n\nf.Fun\n//│ res: ((1 | 'A) -> (2 | 'B) -> 'C) -> 'A -> 'B -> 'C\n//│    = [Function: Fun]\n\n// :d\nBar\n//│ res: {x: int & 'x, y: bool & 'y} -> (Bar with {x: 'x, y: 'y})\n//│    = [Function: res]\n\ng = Bar { x = 42; y = true }\n//│ g: Bar & {x: 42, y: true}\n//│  = Bar { x: 42, y: true }\n\ng.(Foo.Fun)\ng.(Bar.Fun)\n//│ res: (int -> bool -> 'C) -> int -> bool -> 'C\n//│    = undefined\n//│ res: 'a -> 'a\n//│    = undefined\n\n:re\nFoo.Fun g\nBar.Fun g\n//│ res: (int -> bool -> 'C) -> int -> bool -> 'C\n//│ Runtime error:\n//│   TypeError: (intermediate value).Fun is not a function\n//│ res: 'a -> 'a\n//│ Runtime error:\n//│   TypeError: (intermediate value).Fun is not a function\n\ng.Fun\n//│ res: (int -> bool -> 'C) -> int -> bool -> 'C\n//│    = [Function: Fun]\n\nh = Bar { x = 43; y = true }\nh.Fun\n//│ h: Bar & {x: 43, y: true}\n//│  = Bar { x: 43, y: true }\n//│ res: (int -> bool -> 'C) -> int -> bool -> 'C\n//│    = [Function: Fun]\n\n\n\n\nclass Wrapper[A]: { x: A }\n    method Apply f = Wrapper { x = f this.x }\n    method Apply[B]: (A -> B) -> Wrapper[B]\n    // method Apply f = Wrapper { x = f this.x }\n//│ Defined class Wrapper[+A]\n//│ Declared Wrapper.Apply: Wrapper['A] -> ('A -> 'B) -> Wrapper['B]\n//│ Defined Wrapper.Apply: Wrapper['A] -> ('A -> 'x) -> Wrapper['x]\n\nclass IntWrapper: Wrapper[int]\n    method Apply f = Wrapper { x = f this.x }\n//│ Defined class IntWrapper\n//│ Defined IntWrapper.Apply: IntWrapper -> (int -> 'x) -> Wrapper['x]\n\nclass Psyduck[B]: Wrapper[B]\n    method Apply[A]: (B -> A) -> Psyduck[A]\n    method Apply f = Psyduck { x = f this.x }\n//│ Defined class Psyduck[+B]\n//│ Declared Psyduck.Apply: Psyduck['B] -> ('B -> 'A) -> Psyduck['A]\n//│ Defined Psyduck.Apply: Psyduck['B] -> ('B -> 'x) -> Psyduck['x]\n\nclass WrapperWrapper[A]: Wrapper[Wrapper[A]]\n    method Apply2[B]: (A -> B) -> WrapperWrapper[B]\n    method Apply2 f = WrapperWrapper { x = this.x.Apply f }\n//│ Defined class WrapperWrapper[+A]\n//│ Declared WrapperWrapper.Apply2: WrapperWrapper['A] -> ('A -> 'B) -> WrapperWrapper['B]\n//│ Defined WrapperWrapper.Apply2: WrapperWrapper['A] -> ('A -> 'B) -> WrapperWrapper['B]\n\nWrapperWrapper { x = Psyduck { x = 0 } }\n//│ res: WrapperWrapper[0] with {x: Psyduck[0]}\n//│    = WrapperWrapper { x: Psyduck { x: 0 } }\n\nres.Apply2 (fun x -> mul x 2)\n//│ res: WrapperWrapper[int]\n//│    = WrapperWrapper { x: Psyduck { x: 0 } }\n\nWrapper\n//│ res: {x: 'x} -> Wrapper['x]\n//│    = [Function: res]\n\n\n\n\nclass Asc[A, B]: { x: A; y: B }\n    method Left = { x = this.x; y = this.y } : { x: A }\n    method Right2 = this : { y: B }\n//│ Defined class Asc[+A, +B]\n//│ Defined Asc.Left: Asc['A, ?] -> {x: 'A}\n//│ Defined Asc.Right2: Asc[?, 'B] -> {y: 'B}\n\n\n\n\nclass Simple[A]\n    method Get: A\n//│ Defined class Simple[+A]\n//│ Declared Simple.Get: Simple['A] -> 'A\n\nclass Simple2[A]: { a: A }\n    method Get: A\n//│ Defined class Simple2[+A]\n//│ Declared Simple2.Get: Simple2['A] -> 'A\n\n\n\n\nclass AbstractPair[A, B]: { x: A; y: B }\n    method Test: (A -> B -> bool) -> bool\n    method Map[C, D]: (A -> C) -> (B -> D) -> AbstractPair[C, D]\n//│ Defined class AbstractPair[+A, +B]\n//│ Declared AbstractPair.Test: AbstractPair['A, 'B] -> ('A -> 'B -> bool) -> bool\n//│ Declared AbstractPair.Map: AbstractPair['A, 'B] -> ('A -> 'C) -> ('B -> 'D) -> AbstractPair['C, 'D]\n\nclass Pair[A, B]: AbstractPair[A, B]\n    method Test(f: A -> B -> bool) = f this.x this.y\n    method Map fx fy = Pair { x = fx this.x; y = fy this.y }\n//│ Defined class Pair[+A, +B]\n//│ Defined Pair.Test: Pair['A, 'B] -> ('A -> 'B -> bool) -> bool\n//│ Defined Pair.Map: Pair['A, 'B] -> ('A -> 'x) -> ('B -> 'y) -> Pair['x, 'y]\n\nclass Tru[A, B]: Pair[A, B]\n    method Test f = true\n    method True = this.Test (fun x -> error)\n//│ Defined class Tru[+A, +B]\n//│ Defined Tru.Test: Tru[?, ?] -> anything -> true\n//│ Defined Tru.True: Tru[?, ?] -> true\n\nclass True2[A, B]: Pair[A, B]\n    method Test: anything -> bool\n    method True = this.Test (fun x -> error)\n    method Test f = true\n//│ Defined class True2[+A, +B]\n//│ Declared True2.Test: True2[?, ?] -> anything -> bool\n//│ Defined True2.True: True2[?, ?] -> bool\n//│ Defined True2.Test: True2[?, ?] -> anything -> true\n\np = Pair { x = 42; y = true }\nfx = fun x -> mul x 2\nfy = fun x -> not x\nft = fun x -> fun y -> if (y) then gt x 0 else y\n//│ p: Pair[42, true]\n//│  = Pair { x: 42, y: true }\n//│ fx: int -> int\n//│   = [Function: fx]\n//│ fy: bool -> bool\n//│   = [Function: fy]\n//│ ft: number -> bool -> bool\n//│   = [Function: ft]\n\np.Map fx fy\np.Test ft\n(p.Map fx fy).Test ft\n//│ res: AbstractPair[int, bool]\n//│    = Pair { x: 84, y: false }\n//│ res: bool\n//│    = true\n//│ res: bool\n//│    = false\n\nt = Tru { x = \"foo\"; y = false }\nt.(Tru.True)\n//│ t: Tru[\"foo\", false]\n//│  = Tru { x: 'foo', y: false }\n//│ res: true\n//│    = undefined\n\nt = True2 { x = \"bar\"; y = false }\nt.(True2.True)\n//│ t: True2[\"bar\", false]\n//│  = True2 { x: 'bar', y: false }\n//│ res: bool\n//│    = undefined\n\n\nclass Class1A[A]\n    method MtdA: A\ntrait Trait1A[B]\n    method MtdA: B\nclass Class1B: Class1A[\"a\" | \"b\"] & Trait1A[\"b\" | \"c\"]\n    method MtdA = \"b\"\n//│ Defined class Class1A[+A]\n//│ Declared Class1A.MtdA: Class1A['A] -> 'A\n//│ Defined trait Trait1A[+B]\n//│ Declared Trait1A.MtdA: Trait1A['B] -> 'B\n//│ Defined class Class1B\n//│ Defined Class1B.MtdA: Class1B -> \"b\"\n\n\ntrait Trait2A[A]\n    method MtdB: A\nclass Class2B[A, B]: Class1A[A] & Trait2A[B]\n    method MtdA: A\n    method MtdB: B\nclass Class2C: Class2B[int, bool]\n    method MtdA = 42\n    method MtdB = true\n//│ Defined trait Trait2A[+A]\n//│ Declared Trait2A.MtdB: Trait2A['A] -> 'A\n//│ Defined class Class2B[+A, +B]\n//│ Declared Class2B.MtdA: Class2B['A, ?] -> 'A\n//│ Declared Class2B.MtdB: Class2B[?, 'B] -> 'B\n//│ Defined class Class2C\n//│ Defined Class2C.MtdA: Class2C -> 42\n//│ Defined Class2C.MtdB: Class2C -> true\n\n\n:e\nclass Class3C: Class2C\n    method MtdA = 42\n    method MtdB = 42\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.250: \t    method MtdB = 42\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── integer literal of type `42` is not an instance of type `bool`\n//│ ║  l.250: \t    method MtdB = 42\n//│ ║         \t                  ^^\n//│ ╟── but it flows into method definition with expected type `bool`\n//│ ║  l.250: \t    method MtdB = 42\n//│ ║         \t           ^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.234: \tclass Class2C: Class2B[int, bool]\n//│ ║         \t                            ^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.233: \t    method MtdB: B\n//│ ╙──       \t           ^^^^^^^\n//│ Defined class Class3C\n//│ Defined Class3C.MtdA: Class3C -> 42\n//│ Defined Class3C.MtdB: Class3C -> 42\n\ntype Id[T] = T\nclass Test1[A]: { x: A }\n    method F: A\nclass Test2[B]: Test1[Id[B]] & { x: B }\n    method F = this.x\n//│ Defined type alias Id[+T]\n//│ Defined class Test1[+A]\n//│ Declared Test1.F: Test1['A] -> 'A\n//│ Defined class Test2[+B]\n//│ Defined Test2.F: Test2['B] -> (Id['B] & 'B)\n\n\n:e\nclass Test3A: Test1['a -> 'a]\nTest3A.F\n//│ ╔══[ERROR] cannot inherit from a polymorphic type\n//│ ║  l.283: \tclass Test3A: Test1['a -> 'a]\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: Test3A\n//│ ║  l.284: \tTest3A.F\n//│ ╙──       \t^^^^^^\n//│ res: nothing\n//│    = undefined\n\nclass Test3A: Test1[forall 'a. 'a -> 'a]\nTest3A.F\n//│ Defined class Test3A\n//│ res: Test3A -> (forall 'a. 'a -> 'a)\n//│    = undefined\n\n:e\nclass Test3B: Test1['a -> 'a] & { x: 'a }\nTest3B.F\n//│ ╔══[ERROR] cannot inherit from a polymorphic type\n//│ ║  l.301: \tclass Test3B: Test1['a -> 'a] & { x: 'a }\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: Test3B\n//│ ║  l.302: \tTest3B.F\n//│ ╙──       \t^^^^^^\n//│ res: nothing\n//│    = undefined\n\n\n\n:w\nclass Test4A[A]: { x: A }\n    method Mth4A[A]: A\n//│ ╔══[WARNING] Method type parameter A\n//│ ║  l.315: \tclass Test4A[A]: { x: A }\n//│ ║         \t             ^\n//│ ╟── shadows class type parameter A\n//│ ║  l.316: \t    method Mth4A[A]: A\n//│ ╙──       \t                 ^\n//│ Defined class Test4A[+A]\n//│ Declared Test4A.Mth4A: Test4A[?] -> nothing\n\n\nclass Test[A]: { x: A }\n    method Mth[B]: (A -> B) -> B\n    method Mth[B] (f: A -> B) = f this.x\n//│ Defined class Test[+A]\n//│ Declared Test.Mth: Test['A] -> ('A -> 'B) -> 'B\n//│ Defined Test.Mth: Test['A] -> ('A -> 'B) -> 'B\n\n\n\ntrait D\n  method G = 1\ntrait E\n  method G: int\nclass H: D & E\n//│ Defined trait D\n//│ Defined D.G: D -> 1\n//│ Defined trait E\n//│ Declared E.G: E -> int\n//│ Defined class H\n\n((H{}): D).(D.G)\n//│ res: 1\n//│    = undefined\n\n\n\nclass Fee\n    method F: 1 | 2\n//│ Defined class Fee\n//│ Declared Fee.F: Fee -> (1 | 2)\n\ntrait Fee2\n    method F: 2 | 3\n//│ Defined trait Fee2\n//│ Declared Fee2.F: Fee2 -> (2 | 3)\n\nclass Ber: Fee & Fee2\n//│ Defined class Ber\n\nBer.F\n//│ res: Ber -> 2\n//│    = undefined\n\n:e\nBer\n//│ ╔══[ERROR] Instantiation of an abstract type is forbidden\n//│ ║  l.371: \tBer\n//│ ║         \t^^^\n//│ ╟── Note that class Ber is abstract:\n//│ ║  l.363: \tclass Ber: Fee & Fee2\n//│ ║         \t      ^^^^^^^^^^^^^^^\n//│ ╟── Hint: method F is abstract\n//│ ║  l.363: \tclass Ber: Fee & Fee2\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ res: error\n//│    = [Function: res]\n\n\n\n\nclass Test5A[A]: { a: A }\n    method Mth5A[B]: (A -> B) -> B\n//│ Defined class Test5A[+A]\n//│ Declared Test5A.Mth5A: Test5A['A] -> ('A -> 'B) -> 'B\n\n\ntrait Test5B: { tag: int }\n    method Mth5B = this.tag\n//│ Defined trait Test5B\n//│ Defined Test5B.Mth5B: Test5B -> int\n\n\nclass Test5C[A]: Test5A[A] & Test5B\n    method Mth5A f = case this.Mth5B of { 0 -> f this.a | _ -> f this.a }\n//│ Defined class Test5C[+A]\n//│ Defined Test5C.Mth5A: Test5C['A] -> ('A -> 'a) -> 'a\n\n\nclass Test5D: Test5A[int] & Test5B\n    method Mth5A f = case this.Mth5B of { 0 -> f this.a | _ -> f this.Mth5B }\n//│ Defined class Test5D\n//│ Defined Test5D.Mth5A: Test5D -> (int -> 'a) -> 'a\n\n\n\n\nclass Test6A: { a: int }\n    method Add (that: Test6A) = Test6A { a = this.a + that.a }\n//│ Defined class Test6A\n//│ Defined Test6A.Add: Test6A -> Test6A -> Test6A\n\nclass Test6B: { a: Test6A; b: Test6A }\n    method Add (that: Test6B) = Test6B { a = this.a.(Test6A.Add) that.a; b = this.b.(Test6A.Add) that.b }\n//│ Defined class Test6B\n//│ Defined Test6B.Add: Test6B -> Test6B -> Test6B\n\nclass Test6C: Test6B\n//│ Defined class Test6C\n\n\n\n\ntrait Test7A\n    method Mth7A: int\n    method Mth7A = 0\n//│ Defined trait Test7A\n//│ Declared Test7A.Mth7A: Test7A -> int\n//│ Defined Test7A.Mth7A: Test7A -> 0\n\ntrait Test7B\n    method Mth7A: int\n//│ Defined trait Test7B\n//│ Declared Test7B.Mth7A: Test7B -> int\n\nclass Test7C: Test7A & Test7B\n    method Mth7A = 42\n//│ Defined class Test7C\n//│ Defined Test7C.Mth7A: Test7C -> 42\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Methods2.mls",
    "content": "\nclass Option[A]\n    method Get: A\n    method Destruct: Some[A] | None[A]\nclass Some[A]: Option[A] & { payload: A }\n    method Get = this.payload\n    method Destruct = this\nclass None[A]: Option[A]\n    method Get = error\n    method Destruct = this\n//│ Defined class Option[+A]\n//│ Declared Option.Get: Option['A] -> 'A\n//│ Declared Option.Destruct: Option['A] -> (None['A] | Some['A])\n//│ Defined class Some[+A]\n//│ Defined Some.Get: Some['A] -> 'A\n//│ Defined Some.Destruct: (Some['A] & 'this) -> (Some['A] & 'this)\n//│ Defined class None[+A]\n//│ Defined None.Get: None[?] -> nothing\n//│ Defined None.Destruct: (None['A] & 'this) -> (None['A] & 'this)\n\n\nclass List[A]\n    method Size: int\n    method HeadOption: Option[A]\n    method Map[B]: (A -> B) -> List[B]\n//│ Defined class List[+A]\n//│ Declared List.Size: List[?] -> int\n//│ Declared List.HeadOption: List['A] -> Option['A]\n//│ Declared List.Map: List['A] -> ('A -> 'B) -> List['B]\n\n:DistributeForalls\n// * Note: this used to fail when `subst` did not hygienically substitute under polymorphic types\nclass Nil_oops[A]: List[A]\n    method Size = 0\n    method HeadOption = None {}\n    method Map f = Nil_oops {}\n//│ Defined class Nil_oops[+A]\n//│ Defined Nil_oops.Size: Nil_oops[?] -> 0\n//│ Defined Nil_oops.HeadOption: Nil_oops[?] -> None[nothing]\n//│ Defined Nil_oops.Map: Nil_oops[?] -> anything -> Nil_oops[nothing]\n// * Works without distrib:\n:DontDistributeForalls\nclass Nil[A]: List[A]\n    method Size = 0\n    method HeadOption = None {}\n    method Map f = Nil {}\n//│ Defined class Nil[+A]\n//│ Defined Nil.Size: Nil[?] -> 0\n//│ Defined Nil.HeadOption: Nil[?] -> None[nothing]\n//│ Defined Nil.Map: Nil[?] -> anything -> Nil[nothing]\n\n// * Note: `forall 'B` not distributed out in `Cons.Map` because for some weird reason\n// * the `this` TV has level 0, though it is seemingly refreshed on every use...\nclass Cons[A]: List[A] & { head: A; tail: List[A] }\n    method Size = succ this.tail.Size\n    method HeadOption = Some { payload = this.head }\n    method Map[B] f = Cons { head = f this.head; tail = this.tail.Map f }\n//│ Defined class Cons[+A]\n//│ Defined Cons.Size: Cons[?] -> int\n//│ Defined Cons.HeadOption: Cons['A] -> Some['A]\n//│ Defined Cons.Map: Cons['A] -> (forall 'head. ('A -> 'head) -> (Cons['head] with {head: 'head, tail: List['head]}))\n\n// Note that the useless `with {tail: List['A]}` refinement is kept\n//  because the approximate subtyping check `list & {List#A = 'A} <: List['A]` currently returns false\n//  as we do not try to expand type aliases right now.\nCons.Size\n//│ res: Cons[?] -> int\n//│    = undefined\n\nList.HeadOption\n//│ res: List['A] -> Option['A]\n//│    = undefined\n\nCons.HeadOption\n//│ res: Cons['A] -> Some['A]\n//│    = undefined\n\nl = Cons { head = 0; tail = Cons { head = 1; tail = Nil {} } }\n//│ l: Cons[0 | 1] with {head: 0, tail: Cons[1] with {tail: Nil[nothing]}}\n//│  = Cons { head: 0, tail: Cons { head: 1, tail: Nil {} } }\n\nl.Size\n//│ res: int\n//│    = 2\n\n:stats\nl.Map (fun x -> mul x 2)\n//│ res: List[int]\n//│    = Cons { head: 0, tail: Cons { head: 2, tail: Nil {} } }\n//│ constrain calls  : 56\n//│ annoying  calls  : 6\n//│ subtyping calls  : 156\n\nl0 = Cons { head = 0; tail = Nil {} }\n//│ l0: Cons[0] with {tail: Nil[nothing]}\n//│   = Cons { head: 0, tail: Nil {} }\n\n:re\n:stats\nCons.HeadOption l0\n//│ res: Some[0]\n//│ Runtime error:\n//│   TypeError: (intermediate value).HeadOption is not a function\n//│ constrain calls  : 51\n//│ annoying  calls  : 31\n//│ subtyping calls  : 169\n\n\nl1 = Cons { head = 0; tail = Nil {} }\n//│ l1: Cons[0] with {tail: Nil[nothing]}\n//│   = Cons { head: 0, tail: Nil {} }\n\n:re\n:stats\nCons.HeadOption l1\n//│ res: Some[0]\n//│ Runtime error:\n//│   TypeError: (intermediate value).HeadOption is not a function\n//│ constrain calls  : 51\n//│ annoying  calls  : 31\n//│ subtyping calls  : 169\n\n:re\n:stats\nCons.HeadOption l\n//│ res: Some[0 | 1]\n//│ Runtime error:\n//│   TypeError: (intermediate value).HeadOption is not a function\n//│ constrain calls  : 57\n//│ annoying  calls  : 31\n//│ subtyping calls  : 195\n\n:stats\no = l.(Cons.HeadOption)\n//│ o: Some[0 | 1]\n//│  = undefined\n//│ constrain calls  : 55\n//│ annoying  calls  : 31\n//│ subtyping calls  : 182\n\no = l.(Cons.HeadOption)\n//│ o: Some[0 | 1]\n//│  = undefined\n\no = l.HeadOption\n//│ o: Option[0 | 1]\n//│  = Some { payload: 0 }\n\n:e\ncase o of {None -> 0 | Some -> o.payload}\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.150: \tcase o of {None -> 0 | Some -> o.payload}\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Option[?A]` does not match type `None[?] & ?a | Some[?] & ?b`\n//│ ║  l.24: \t    method HeadOption: Option[A]\n//│ ║        \t                       ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `None[?] & ?a | Some[?] & ?c`\n//│ ║  l.150: \tcase o of {None -> 0 | Some -> o.payload}\n//│ ╙──       \t     ^\n//│ res: 0\n//│    = 0\n\nv = o.Destruct\ncase v of {None -> 0 | Some -> v.payload}\n//│ v: None[0 | 1] | Some[0 | 1]\n//│  = Some { payload: 0 }\n//│ res: 0 | 1\n//│    = 0\n\n\ndef newHeadOption x = case x of {\n    | Cons -> Some {payload = x.head}\n    | _ -> None{}\n    }\n//│ newHeadOption: (Cons[?] & {head: 'payload} | ~Cons[?]) -> (None[nothing] | Some['payload])\n//│              = [Function: newHeadOption]\n\n// Note that `o` is not a list, so this takes the default case:\nnewHeadOption o\n//│ res: None[nothing] | Some[nothing]\n//│    = None {}\n\nnewHeadOption l\n//│ res: None[nothing] | Some[0]\n//│    = Some { payload: 0 }\n\ncase res of {None -> 0 | Some -> res.payload}\n//│ res: 0\n//│    = 0\n\n\n// Idiomatic definition for proper matching: `type Option[A] = Some[A] | None[A]`\n:e\ncase o of {\n    Some -> o.Get | None -> 0 }\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.194: \tcase o of {\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.195: \t    Some -> o.Get | None -> 0 }\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Option[?A]` does not match type `None[?] & ?a | Some[?] & ?b`\n//│ ║  l.24: \t    method HeadOption: Option[A]\n//│ ║        \t                       ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `None[?] & ?a | Some[?] & ?c`\n//│ ║  l.194: \tcase o of {\n//│ ╙──       \t     ^\n//│ res: 0 | 1\n//│    = 0\n\ncase o of {\n    Some -> o.Get | None -> 0 | Option -> error }\n//│ res: 0 | 1\n//│    = 0\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Misc.mls",
    "content": ":NoJS\n\n\nrec def x = {u = x}\n//│ x: 'x\n//│   where\n//│     'x :> {u: 'x}\n\n:ns\n{u = x; v = x}\n//│ res: {u: forall 'x. 'x, v: forall 'x. 'x}\n//│   where\n//│     'x := {u: 'x}\n\n{u = x; v = x}\n//│ res: {u: forall 'x. 'x, v: forall 'x. 'x}\n//│   where\n//│     'x :> {u: 'x}\n\n\n\n\nclass C[A]: {x: A}\n  method X = this.x\n//│ Defined class C[+A]\n//│ Defined C.X: C['A] -> 'A\n\nc = C{x = 1}\n//│ c: C[1]\n\ndef mkC() = C{x = 1}\n//│ mkC: () -> C[1]\n\ndef arg = if true then c else 0\n//│ arg: 0 | C[1]\n\ndef arg = if true then mkC() else 0\n//│ arg: 0 | C[1]\n\n\ndef arg = if true then C{x = 42} else 0\n//│ arg: 0 | C[42]\n\ndef arg = if true then c else 0\n//│ arg: 0 | C[1]\n\n:ns\ndef arg = if true then C{x = 42} else C{x = 1}\n//│ arg: forall 'x 'A 'x0 'A0 'a. 'a\n//│   where\n//│     'a :> #C & {x: 'x, C#A = 'A} | #C & {x: 'x0, C#A = 'A0}\n//│     'x0 :> 1\n//│         <: 'A0\n//│     'A0 :> 1\n//│     'x :> 42\n//│        <: 'A\n//│     'A :> 42\n\n:ns\narg\n//│ res: forall 'x 'A 'x0 'A0 'a. 'a\n//│   where\n//│     'a :> #C & {x: 'x, C#A = 'A} | #C & {x: 'x0, C#A = 'A0}\n//│     'x0 :> 1\n//│         <: 'A0\n//│     'A0 :> 1\n//│     'x :> 42\n//│        <: 'A\n//│     'A :> 42\n\narg\n//│ res: C[1 | 42]\n\nC.X\n//│ res: C['A] -> 'A\n\n:ns\nC.X\n//│ res: 'this -> 'x\n//│   where\n//│     'x :> 'A\n//│     'this <: C['A]\n\nres arg\n//│ res: 1 | 42\n\narg.X\n//│ res: 1 | 42\n\n:e\narg: C[nothing]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.91: \targ: C[nothing]\n//│ ║        \t^^^\n//│ ╟── integer literal of type `42` does not match type `nothing`\n//│ ║  l.48: \tdef arg = if true then C{x = 42} else C{x = 1}\n//│ ╙──      \t                             ^^\n//│ res: C[nothing]\n\n\ntest x = case x of { C -> x.X }\n//│ test: C['a] -> 'a\n\ntest x = case x of { C -> x.X | int -> x }\n//│ test: (C['a] | int & 'a) -> 'a\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/MiscExtrusion.mls",
    "content": ":NoJS\n\n\nclass Expr[A]\n  method Inv: A -> A\n//│ Defined class Expr[=A]\n//│ Declared Expr.Inv: Expr['A] -> 'A -> 'A\n\ndef asExpr: Expr['a] -> Expr['a]\n//│ asExpr: Expr['a] -> Expr['a]\n\ndef alsoPrintSizeSimple f =\n  let rec nested expr =\n    f expr\n  in nested\n//│ alsoPrintSizeSimple: ('a -> 'b) -> 'a -> 'b\n\ndef alsoPrintSizeSimple f =\n  let rec nested expr =\n    f (asExpr expr)\n  in nested\n//│ alsoPrintSizeSimple: (Expr['a] -> 'b) -> Expr['a] -> 'b\n\ndef alsoPrintSizeSimple f =\n  let rec nested expr =\n    asExpr (f (asExpr expr))\n  in nested\n//│ alsoPrintSizeSimple: (Expr['a] -> Expr['a0]) -> Expr['a] -> Expr['a0]\n\n// * Note: the type of definitions like this one is much cleaner with :ConstrainedTypes\ndef alsoPrintSizeSimple f =\n  let rec nested expr =\n    f (asExpr expr) nested\n  in nested\n//│ alsoPrintSizeSimple: (Expr[in 'a out 'a | 'a0] -> (Expr[in 'a0 & 'a1 out 'a2] -> 'b) -> 'b) -> Expr['a2] -> 'b\n//│   where\n//│     'a2 :> 'a | 'a1\n//│         <: 'a0\n\n\nclass Program\n//│ Defined class Program\n\ndef mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program\ndef print: Expr['a] -> unit\n//│ mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program\n//│ print: Expr['a] -> unit\n\ndef alsoPrintSize f =\n  mapExpr(fun e -> let tmp = print e in f e)\n//│ alsoPrintSize: (Expr[in ??a out ??a0] -> Expr[in ??a0 out ??a]) -> Program -> Program\n\n:e\nalsoPrintSize id\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.54: \talsoPrintSize id\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.44: \tdef mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program\n//│ ║        \t                                          ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.44: \tdef mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program\n//│ ║        \t                              ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.50: \t  mapExpr(fun e -> let tmp = print e in f e)\n//│ ╙──      \t                                        ^^^\n//│ res: error | Program -> Program\n\ndef alsoPrintSize (f: forall 'a. Expr['a] -> Expr['a]) =\n  mapExpr(fun e -> let tmp = print e in f e)\n//│ alsoPrintSize: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program\n\nalsoPrintSize id\n//│ res: Program -> Program\n\n\nclass ExprCo[A]\n  method Co: A\n//│ Defined class ExprCo[+A]\n//│ Declared ExprCo.Co: ExprCo['A] -> 'A\n\ndef mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program\ndef printCo: ExprCo['a] -> unit\n//│ mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program\n//│ printCo: ExprCo[?] -> unit\n\ndef alsoPrintSizeCo f =\n  mapExprCo(fun e -> let tmp = printCo e in f e)\n//│ alsoPrintSizeCo: (ExprCo[??a] -> ExprCo[??a0]) -> Program -> Program\n\n:e\nalsoPrintSizeCo id\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.93: \talsoPrintSizeCo id\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.83: \tdef mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program\n//│ ║        \t                                  ^^\n//│ ╟── back into type variable `'a`\n//│ ║  l.83: \tdef mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program\n//│ ║        \t                                                ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this application:\n//│ ║  l.89: \t  mapExprCo(fun e -> let tmp = printCo e in f e)\n//│ ╙──      \t                                            ^^^\n//│ res: error | Program -> Program\n\ndef alsoPrintSizeCo (f: forall 'a. Expr['a] -> Expr['a]) =\n  mapExpr(fun e -> let tmp = print e in f e)\n//│ alsoPrintSizeCo: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program\n\nalsoPrintSizeCo id\n//│ res: Program -> Program\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Mohammad.mls",
    "content": "\ndef test f = f (fun b -> if b then 1 else 2)\n//│ test: ((bool -> (1 | 2)) -> 'a) -> 'a\n//│     = [Function: test]\n\ntest (fun k -> (k true, k false))\n//│ res: (1 | 2, 1 | 2,)\n//│    = [ 1, 2 ]\n\n\nclass Class: {x : int}\n  method Test = 12\n//│ Defined class Class\n//│ Defined Class.Test: Class -> 12\n\nc = Class{x = 1}\n//│ c: Class & {x: 1}\n//│  = Class { x: 1 }\n\n:js\ndef useCls c = case c of { Class -> c.x | int -> \"oops\" }\n//│ // Query 1\n//│ globalThis.useCls = function useCls(c) {\n//│   let a;\n//│   return (a = c, a instanceof Class ? c.x : Number.isInteger(a) ? \"oops\" : (() => {\n//│     throw new Error(\"non-exhaustive case expression\");\n//│   })());\n//│ };\n//│ // End of generated code\n//│ useCls: ((Class with {x: 'x}) | int) -> (\"oops\" | 'x)\n//│       = [Function: useCls]\n\nuseCls c\n//│ res: \"oops\" | 1\n//│    = 1\n\nuseCls (c with { x = 2 })\n//│ res: \"oops\" | 2\n//│    = 2\n\n:js\ntrait T\n  method Test2: int\n  method Test2 = 1\n//│ Defined trait T\n//│ Declared T.Test2: T -> int\n//│ Defined T.Test2: T -> 1\n//│ // Prelude\n//│ const T = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│       if (!(\"Test2\" in instance)) {\n//│         Object.defineProperty(instance, \"Test2\", {\n//│           get: function () {\n//│             return 1;\n//│           }\n//│         });\n//│       }\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // End of generated code\n\n:js\nclass D: T & {z: int}\n  method Test2 = 2\n//│ Defined class D\n//│ Defined D.Test2: D -> 2\n//│ // Prelude\n//│ class D {\n//│   constructor(fields) {\n//│     T.implement(this);\n//│     this.z = fields.z;\n//│   }\n//│   get Test2() {\n//│     return 2;\n//│   }\n//│ }\n//│ // End of generated code\n\ndef useTrt t = case t of { T -> t.y | Class -> t.x }\n//│ useTrt: ((Class with {x: 'y}) & ~#T | {y: 'y} & #T) -> 'y\n//│       = [Function: useTrt]\n\n:e\nuseTrt c\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.101: \tuseTrt c\n//│ ║         \t^^^^^^^^\n//│ ╟── expression of type `Class & {x: ?x} & ~?a | Class & {x: ?x} & #T` does not have field 'y'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.96: \tdef useTrt t = case t of { T -> t.y | Class -> t.x }\n//│ ║        \t                                ^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.96: \tdef useTrt t = case t of { T -> t.y | Class -> t.x }\n//│ ╙──      \t                    ^\n//│ res: 1 | error\n//│    = 1\n\nuseTrt (c with { y = 1 })\n//│ res: 1\n//│    = 1\n\n:e\nuseTrt c\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.120: \tuseTrt c\n//│ ║         \t^^^^^^^^\n//│ ╟── expression of type `Class & {x: ?x} & ~?a | Class & {x: ?x} & #T` does not have field 'y'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.96: \tdef useTrt t = case t of { T -> t.y | Class -> t.x }\n//│ ║        \t                                ^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.96: \tdef useTrt t = case t of { T -> t.y | Class -> t.x }\n//│ ╙──      \t                    ^\n//│ res: 1 | error\n//│    = 1\n\nd = D{z = 1213}\n//│ d: D & {z: 1213}\n//│  = D { z: 1213 }\n\nd: {z: 'a}\n//│ res: {z: 1213}\n//│    = D { z: 1213 }\n\nd.Test2\n//│ res: int\n//│    = 2\n\ntrait T1\n  method Test3: int\n  method Test3 = 1\n  method Test4 = 4\n//│ Defined trait T1\n//│ Declared T1.Test3: T1 -> int\n//│ Defined T1.Test3: T1 -> 1\n//│ Defined T1.Test4: T1 -> 4\n\n:js\ntrait T2: T1\n  method Test3: int\n  method Test3 = 2\n//│ Defined trait T2\n//│ Declared T2.Test3: T2 -> int\n//│ Defined T2.Test3: T2 -> 2\n//│ // Prelude\n//│ const T2 = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│       if (!(\"Test3\" in instance)) {\n//│         Object.defineProperty(instance, \"Test3\", {\n//│           get: function () {\n//│             return 2;\n//│           }\n//│         });\n//│       }\n//│       T1.implement(instance);\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // End of generated code\n\n:js\nclass C3: T2\n//│ Defined class C3\n//│ // Prelude\n//│ class C3 {\n//│   constructor(fields) {\n//│     T2.implement(this);\n//│   }\n//│ }\n//│ // End of generated code\n\n(C3{}).Test3\n//│ res: int\n//│    = 2\n\n(C3{}).Test4\n//│ res: 4\n//│    = 4\n\n\n:js\ntrait Oops\n//│ Defined trait Oops\n//│ // Prelude\n//│ const Oops = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // End of generated code\n\n:js\noo = Oops 2\n//│ // Query 1\n//│ globalThis.oo = Oops.build(2);\n//│ // End of generated code\n//│ oo: 2 & #Oops\n//│   = [Number: 2]\n\n:js\ncase oo of { Oops -> 1 }\n//│ // Query 1\n//│ let a;\n//│ res = (a = oo, Oops.is(a) ? 1 : (() => {\n//│   throw new Error(\"non-exhaustive case expression\");\n//│ })());\n//│ // End of generated code\n//│ res: 1\n//│    = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/MultiArgs.mls",
    "content": "\ndef foo(a, b, c) = add a (add b c)\nfoo(1, 2, 3)\nfoo(1, 2, 3,)\n//│ foo: (int, int, int,) -> int\n//│    = [Function: foo]\n//│ res: int\n//│    = 6\n//│ res: int\n//│    = 6\n\ndef bar() = 1\nbar()\nbar(,)\n//│ bar: () -> 1\n//│    = [Function: bar]\n//│ res: 1\n//│    = 1\n//│ res: 1\n//│    = 1\n\ndef bar(x) = x\nbar(1)\nbar(1,)\n//│ bar: 'a -> 'a\n//│    = [Function: bar1]\n//│ res: 1\n//│    = 1\n//│ res: 1\n//│    = 1\n\ndef bar(x,) = x\nbar(1)\nbar(1,)\n//│ bar: 'a -> 'a\n//│    = [Function: bar2]\n//│ res: 1\n//│    = 1\n//│ res: 1\n//│    = 1\n\ndef bar(x, y) = add x y\nbar(1, 2)\nbar(1, 2,)\n//│ bar: (int, int,) -> int\n//│    = [Function: bar3]\n//│ res: int\n//│    = 3\n//│ res: int\n//│    = 3\n\n:e\nbar((1, 2))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.53: \tbar((1, 2))\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── argument of type `((1, 2,),)` does not match type `(?a, ?b,)`\n//│ ║  l.53: \tbar((1, 2))\n//│ ║        \t   ^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.42: \tdef bar(x, y) = add x y\n//│ ╙──      \t       ^^^^^^\n//│ res: error | int\n//│    = '1,2undefined'\n\ndef bar((x, y)) = add x y\nbar((1, 2))\n//│ bar: ((int, int,),) -> int\n//│    = [Function: bar4]\n//│ res: int\n//│    = 3\n\n:p\nf = fun (x, y) -> add x y\nf(1, 2)\n//│ Parsed: let f = (x, y,) => add(x,)(y,); f(1, 2,);\n//│ Desugared: def f: (x, y,) => add(x,)(y,)\n//│ AST: Def(false,Var(f),Left(Lam(Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y))))),App(App(Var(add),Tup(List((None,Fld(_,Var(x)))))),Tup(List((None,Fld(_,Var(y)))))))),false)\n//│ Desugared: f(1, 2,)\n//│ AST: App(Var(f),Tup(List((None,Fld(_,IntLit(1))), (None,Fld(_,IntLit(2))))))\n//│ f: (int, int,) -> int\n//│  = [Function: f]\n//│ res: int\n//│    = 3\n\n:e\nf((1, 2))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.87: \tf((1, 2))\n//│ ║        \t^^^^^^^^^\n//│ ╟── argument of type `((1, 2,),)` does not match type `(?a, ?b,)`\n//│ ║  l.87: \tf((1, 2))\n//│ ║        \t ^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.74: \tf = fun (x, y) -> add x y\n//│ ╙──      \t        ^^^^^^\n//│ res: error | int\n//│    = '1,2undefined'\n\n:e\nr = (1, 2)\nf r\n//│ r: (1, 2,)\n//│  = [ 1, 2 ]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.102: \tf r\n//│ ║         \t^^^\n//│ ╟── argument of type `((1, 2,),)` does not match type `(?a, ?b,)`\n//│ ║  l.102: \tf r\n//│ ║         \t  ^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.74: \tf = fun (x, y) -> add x y\n//│ ╙──      \t        ^^^^^^\n//│ res: error | int\n//│    = '1,2undefined'\n\n:p\nf = fun ((x, y)) -> add x y\nf((1, 2))\n//│ Parsed: let f = ('(' [x, y,] ')',) => add(x,)(y,); f('(' [1, 2,] ')',);\n//│ Desugared: def f: ('(' [x, y,] ')',) => add(x,)(y,)\n//│ AST: Def(false,Var(f),Left(Lam(Tup(List((None,Fld(_,Bra(false,Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))))))),App(App(Var(add),Tup(List((None,Fld(_,Var(x)))))),Tup(List((None,Fld(_,Var(y)))))))),false)\n//│ Desugared: f('(' [1, 2,] ')',)\n//│ AST: App(Var(f),Tup(List((None,Fld(_,Bra(false,Tup(List((None,Fld(_,IntLit(1))), (None,Fld(_,IntLit(2)))))))))))\n//│ f: ((int, int,),) -> int\n//│  = [Function: f1]\n//│ res: int\n//│    = 3\n\n:e\nf(1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.131: \tf(1, 2)\n//│ ║         \t^^^^^^^\n//│ ╟── argument list of type `(1, 2,)` does not match type `((?a, ?b,),)`\n//│ ║  l.131: \tf(1, 2)\n//│ ╙──       \t ^^^^^^\n//│ res: error | int\n//│ Runtime error:\n//│   TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))\n\nr = (1, 2)\nf r\n//│ r: (1, 2,)\n//│  = [ 1, 2 ]\n//│ res: int\n//│    = 3\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Mut.mls",
    "content": "\nclass A: { x: int }\n//│ Defined class A\n\ndef muta1: MutArray[int]\n//│ muta1: MutArray[int]\n//│      = <missing implementation>\n\nmuta1[2] <- 666\n//│ = <no result>\n//│   muta1 is not implemented\n\n:e\nmuta1[1] <- false\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.14: \tmuta1[1] <- false\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.14: \tmuta1[1] <- false\n//│ ║        \t            ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.5: \tdef muta1: MutArray[int]\n//│ ║       \t                    ^^^\n//│ ╟── from assigned array element:\n//│ ║  l.14: \tmuta1[1] <- false\n//│ ╙──      \t^^^^^^^^\n//│ = <no result>\n//│   muta1 is not implemented\n\ndef a1: Array[int]\n//│ a1: Array[int]\n//│   = <missing implementation>\n\nmuta1 : Array[int]\n//│ res: Array[int]\n//│    = <no result>\n//│      muta1 is not implemented\n\n:e\na1: MutArray[int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.40: \ta1: MutArray[int]\n//│ ║        \t^^\n//│ ╙── type `int` cannot be reassigned\n//│ res: MutArray[int]\n//│    = <no result>\n//│      a1 is not implemented\n\na2 = A {x=3}\n//│ a2: A & {x: 3}\n//│   = A { x: 3 }\n\ndef rc1 : { mut x : int}\nrc1 = {mut x = 1}\n//│ rc1: {mut x: int}\n//│    = <missing implementation>\n//│ {mut x: 'x}\n//│   where\n//│     'x :> 1\n//│   <:  rc1:\n//│ {mut x: int}\n//│    = { x: 1 }\n\nrc1.x <- 3\n//│ = undefined\n\n:e\nrc1.x <- true\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.68: \trc1.x <- true\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.68: \trc1.x <- true\n//│ ║        \t         ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.53: \tdef rc1 : { mut x : int}\n//│ ║        \t                    ^^^\n//│ ╟── from assigned selection:\n//│ ║  l.68: \trc1.x <- true\n//│ ╙──      \t^^^^^\n//│ = undefined\n\n\nimmrcd = { x = 1: int }\nimmtpl = (1: int,)\n//│ immrcd: {x: int}\n//│       = { x: 1 }\n//│ immtpl: (int,)\n//│       = [ 1 ]\n\nimmrcd.x\nimmtpl.0\nimmtpl[0]\n//│ res: int\n//│    = 1\n//│ res: int\n//│    = 1\n//│ res: int | undefined\n//│    = 1\n\n:e\nimmrcd.x <- 0\nimmtpl.0 <- 0\nimmtpl[0] <- 0\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.102: \timmrcd.x <- 0\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── record field of type `int` is not mutable\n//│ ║  l.84: \timmrcd = { x = 1: int }\n//│ ║        \t           ^^^^^\n//│ ╟── but it flows into assigned field with expected type `?x`\n//│ ║  l.102: \timmrcd.x <- 0\n//│ ╙──       \t       ^\n//│ = undefined\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.103: \timmtpl.0 <- 0\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── tuple field of type `int` is not mutable\n//│ ║  l.85: \timmtpl = (1: int,)\n//│ ║        \t          ^\n//│ ╟── but it flows into assigned field with expected type `?0`\n//│ ║  l.103: \timmtpl.0 <- 0\n//│ ╙──       \t       ^\n//│ = undefined\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.104: \timmtpl[0] <- 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── tuple field of type `int` is not mutable\n//│ ║  l.85: \timmtpl = (1: int,)\n//│ ║        \t          ^\n//│ ╟── but it flows into assigned array element with expected type `?a`\n//│ ║  l.104: \timmtpl[0] <- 0\n//│ ╙──       \t^^^^^^^^^\n//│ = undefined\n\n\nrc2 = {mut x = 1}\nrc2.x <- true\nrc2.x <- \"hello\"\n//│ rc2: {mut x: 'x}\n//│   where\n//│     'x :> 1\n//│    = { x: 1 }\n//│ = undefined\n//│ = undefined\n\n// TODO let-bound values should be treated as monomorphic – see mismatch in:\nrc2\n//│ res: {mut x: 'x}\n//│   where\n//│     'x :> 1\n//│    = { x: 'hello' }\n\ndef g r = (fun x -> r) (r.x <- 3)\ng rc1\ng rc2\n//│ g: ({mut x: in 3} & 'a) -> 'a\n//│  = [Function: g]\n//│ res: {mut x: int}\n//│    = { x: 3 }\n//│ res: {mut x: 'x}\n//│   where\n//│     'x :> 1\n//│    = { x: 3 }\n\n:e \ng {x = 3}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.167: \tg {x = 3}\n//│ ║         \t^^^^^^^^^\n//│ ╟── record field of type `3` is not mutable\n//│ ║  l.167: \tg {x = 3}\n//│ ╙──       \t   ^^^^^\n//│ res: error | {x: 3}\n//│    = { x: 3 }\n\ndef ga r = (fun x -> r) (r[1] <- 6)\nga muta1\n//│ ga: (MutArray['a] & 'b) -> 'b\n//│   where\n//│     'a :> 6\n//│   = [Function: ga]\n//│ res: MutArray[int]\n//│    = <no result>\n//│      muta1 is not implemented\n\n:e\nga a1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.188: \tga a1\n//│ ║         \t^^^^^\n//│ ╟── assigned array element of type `int` cannot be reassigned\n//│ ║  l.177: \tdef ga r = (fun x -> r) (r[1] <- 6)\n//│ ╙──       \t                         ^^^^\n//│ res: error | Array[int]\n//│    = <no result>\n//│      a1 is not implemented\n\ntrait T\n//│ Defined trait T\n\ndef t1 : T & {mut x : int; y : bool}\nt1 = T {mut x = 2; y = false}\nt2 = T {x = 2}\n//│ t1: T & {mut x: int, y: bool}\n//│   = <missing implementation>\n//│ {mut x: 'x, y: false} & #T\n//│   where\n//│     'x :> 2\n//│   <:  t1:\n//│ T & {mut x: int, y: bool}\n//│   = { x: 2, y: false }\n//│ t2: {x: 2} & #T\n//│   = { x: 2 }\n\nt1.x <- 4\n//│ = undefined\n\n:e\nt1.y <- true\nt2.x <- 3\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.220: \tt1.y <- true\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── record field of type `bool` is not mutable\n//│ ║  l.202: \tdef t1 : T & {mut x : int; y : bool}\n//│ ║         \t                           ^^^^^^^^\n//│ ╟── but it flows into assigned field with expected type `?y`\n//│ ║  l.220: \tt1.y <- true\n//│ ╙──       \t   ^\n//│ = undefined\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.221: \tt2.x <- 3\n//│ ║         \t^^^^^^^^^\n//│ ╟── record field of type `2` is not mutable\n//│ ║  l.204: \tt2 = T {x = 2}\n//│ ║         \t        ^^^^^\n//│ ╟── but it flows into assigned field with expected type `?x`\n//│ ║  l.221: \tt2.x <- 3\n//│ ╙──       \t   ^\n//│ = undefined\n\nclass B: { mut x: int; y: bool }\n  method Foo = this.x\n//│ Defined class B\n//│ Defined B.Foo: B -> int\n\ndef b1 : B\nb1 = B { mut x = 2; y = true }\nb2 = B { mut x = 1; y = false}\n//│ b1: B\n//│   = <missing implementation>\n//│ B with {mut x: 'x, y: true}\n//│   where\n//│     'x :> 2\n//│        <: int\n//│   <:  b1:\n//│ B\n//│   = B { x: 2, y: true }\n//│ b2: B with {mut x: 'x, y: false}\n//│   where\n//│     'x :> 1\n//│        <: int\n//│   = B { x: 1, y: false }\n\nb1.Foo\n//│ res: int\n//│    = 2\n\n:e\nb1.Foo <- 0\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.271: \tb1.Foo <- 0\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type `B` does not have field 'Foo'\n//│ ║  l.248: \tdef b1 : B\n//│ ║         \t         ^\n//│ ╟── but it flows into reference with expected type `{Foo :> ?Foo}`\n//│ ║  l.271: \tb1.Foo <- 0\n//│ ║         \t^^\n//│ ╟── Note: constraint arises from assigned selection:\n//│ ║  l.271: \tb1.Foo <- 0\n//│ ╙──       \t^^^^^^\n//│ = undefined\n\n:e\nb3 = B {x = 6; y = false}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.287: \tb3 = B {x = 6; y = false}\n//│ ║         \t     ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record field of type `6` is not mutable\n//│ ║  l.287: \tb3 = B {x = 6; y = false}\n//│ ╙──       \t        ^^^^^\n//│ b3: (B with {mut x: 'x, y: false}) | error\n//│   where\n//│     'x :> 6\n//│        <: int\n//│   = B { x: 6, y: false }\n\n:e\nb2.y <- b1.y\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.301: \tb2.y <- b1.y\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── record field of type `?y` is not mutable\n//│ ║  l.243: \tclass B: { mut x: int; y: bool }\n//│ ║         \t                       ^^^^^^^\n//│ ╟── but it flows into assigned field with expected type `?y0`\n//│ ║  l.301: \tb2.y <- b1.y\n//│ ╙──       \t   ^\n//│ = undefined\n\n:e\nb2.x <- b1.y\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.314: \tb2.x <- b1.y\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type `bool` is not an instance of type `int`\n//│ ║  l.243: \tclass B: { mut x: int; y: bool }\n//│ ║         \t                          ^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.314: \tb2.x <- b1.y\n//│ ║         \t        ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.243: \tclass B: { mut x: int; y: bool }\n//│ ║         \t                  ^^^\n//│ ╟── from assigned selection:\n//│ ║  l.314: \tb2.x <- b1.y\n//│ ╙──       \t^^^^\n//│ = undefined\n\nb2.x <- b1.x\nb1.x <- a2.x\n//│ = undefined\n//│ = undefined\n\ndef h : B -> int -> int\ndef h b i = (fun _ -> b.x) (b.x <- i) \n//│ h: B -> int -> int\n//│  = <missing implementation>\n//│ {mut x: in 'x out 'a} -> 'x -> 'a\n//│   <:  h:\n//│ B -> int -> int\n//│  = [Function: h]\n\nh b1 2\n//│ res: int\n//│    = 2\n\n:e\nh {mut x = 4} 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.351: \th {mut x = 4} 2\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── record literal of type `{mut x: ?x}` is not an instance of type `B`\n//│ ║  l.351: \th {mut x = 4} 2\n//│ ║         \t  ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.337: \tdef h : B -> int -> int\n//│ ╙──       \t        ^\n//│ res: error | int\n//│    = 2\n\ndef mt1: (mut int, mut bool)\ndef mt2: (int, int)\ndef mt3: (mut int, mut int)\ndef mt4: (mut bool, bool, bool)\nmt4 = (mut true, false, false)\n//│ mt1: (mut int, mut bool,)\n//│    = <missing implementation>\n//│ mt2: (int, int,)\n//│    = <missing implementation>\n//│ mt3: (mut int, mut int,)\n//│    = <missing implementation>\n//│ mt4: (mut bool, bool, bool,)\n//│    = <missing implementation>\n//│ (mut 'a, false, false,)\n//│   where\n//│     'a :> true\n//│   <:  mt4:\n//│ (mut bool, bool, bool,)\n//│    = [ true, false, false ]\n\nmt1 : (int, bool)\n//│ res: (int, bool,)\n//│    = <no result>\n//│      mt1 is not implemented\n\ndef emt: (mut int)\nemt.0\n//│ emt: (mut int,)\n//│    = <missing implementation>\n//│ res: int\n//│    = <no result>\n//│      emt is not implemented\n\nk1 = (mut 233, \"hello\", mut true)\nk1.0 <- k1.0 + 1\n//│ k1: (mut 'a, \"hello\", mut 'b,)\n//│   where\n//│     'b :> true\n//│     'a :> 233\n//│   = [ 233, 'hello', true ]\n//│ = undefined\n\n:e\nk1.1 <- 233\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.407: \tk1.1 <- 233\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── assigned field of type `\"hello\"` cannot be reassigned\n//│ ║  l.407: \tk1.1 <- 233\n//│ ╙──       \t   ^\n//│ = undefined\n\nmt1 = (mut 3, mut false)\n//│ (mut 'a, mut 'b,)\n//│   where\n//│     'b :> false\n//│     'a :> 3\n//│   <:  mt1:\n//│ (mut int, mut bool,)\n//│    = [ 3, false ]\n\ndef amf : MutArray['a] -> 'a\n//│ amf: MutArray['a] -> 'a\n//│    = <missing implementation>\n\namf mt3\n//│ res: int\n//│    = <no result>\n//│      amf is not implemented\n\n:e\namf mt4\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.435: \tamf mt4\n//│ ║         \t^^^^^^^\n//│ ╙── expression of type `bool` cannot be reassigned\n//│ res: bool | error\n//│    = <no result>\n//│      amf is not implemented\n\n:e\na1[0] <- 1\nmt1[0] <- mt2.0\nmt4[3] <- true\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.445: \ta1[0] <- 1\n//│ ║         \t^^^^^^^^^^\n//│ ╟── assigned array element of type `int` cannot be reassigned\n//│ ║  l.445: \ta1[0] <- 1\n//│ ╙──       \t^^^^^\n//│ = <no result>\n//│   a1 is not implemented\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.446: \tmt1[0] <- mt2.0\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `bool`\n//│ ║  l.364: \tdef mt1: (mut int, mut bool)\n//│ ║         \t              ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.364: \tdef mt1: (mut int, mut bool)\n//│ ║         \t                       ^^^^\n//│ ╟── from assigned array element:\n//│ ║  l.446: \tmt1[0] <- mt2.0\n//│ ╙──       \t^^^^^^\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.446: \tmt1[0] <- mt2.0\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `bool`\n//│ ║  l.365: \tdef mt2: (int, int)\n//│ ║         \t          ^^^\n//│ ╟── but it flows into field selection with expected type `bool`\n//│ ║  l.446: \tmt1[0] <- mt2.0\n//│ ║         \t          ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.364: \tdef mt1: (mut int, mut bool)\n//│ ║         \t                       ^^^^\n//│ ╟── from assigned array element:\n//│ ║  l.446: \tmt1[0] <- mt2.0\n//│ ╙──       \t^^^^^^\n//│ = <no result>\n//│   mt2 is not implemented\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.447: \tmt4[3] <- true\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── assigned array element of type `bool` cannot be reassigned\n//│ ║  l.447: \tmt4[3] <- true\n//│ ╙──       \t^^^^^^\n//│ = undefined\n\nmt1.0 <- mt2.0\nmt1.0 <- mt1.0 * 2\nmt1.1 <- false\nmt3[0] <- let tmp = mt3[1] in case tmp of { undefined -> 0 | _ -> tmp }\nmt3[1] <- mt1.0\n//│ = <no result>\n//│   mt2 is not implemented\n//│ = undefined\n//│ = undefined\n//│ = <no result>\n//│   mt3 is not implemented\n//│ = <no result>\n//│   mt3 is not implemented\n\n:e\n:ge\nmt1.0 <- mt1.1\nmt1.1 <- 1\nmt1.0 <- (b1.t <- 4)\n(mt1.0 <- b1.t) <- 4\nb1.x <- 1 + 2 <- 4\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.509: \tmt1.0 <- mt1.1\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── type `bool` is not an instance of type `int`\n//│ ║  l.364: \tdef mt1: (mut int, mut bool)\n//│ ║         \t                       ^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.509: \tmt1.0 <- mt1.1\n//│ ║         \t         ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.364: \tdef mt1: (mut int, mut bool)\n//│ ║         \t              ^^^\n//│ ╟── from assigned selection:\n//│ ║  l.509: \tmt1.0 <- mt1.1\n//│ ╙──       \t^^^^^\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.510: \tmt1.1 <- 1\n//│ ║         \t^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `bool`\n//│ ║  l.510: \tmt1.1 <- 1\n//│ ║         \t         ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.364: \tdef mt1: (mut int, mut bool)\n//│ ║         \t                       ^^^^\n//│ ╟── from assigned selection:\n//│ ║  l.510: \tmt1.1 <- 1\n//│ ╙──       \t^^^^^\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.511: \tmt1.0 <- (b1.t <- 4)\n//│ ║         \t          ^^^^^^^^^\n//│ ╟── type `B` does not have field 't'\n//│ ║  l.248: \tdef b1 : B\n//│ ║         \t         ^\n//│ ╟── but it flows into reference with expected type `{mut t: in ?t}`\n//│ ║  l.511: \tmt1.0 <- (b1.t <- 4)\n//│ ║         \t          ^^\n//│ ╟── Note: constraint arises from assigned selection:\n//│ ║  l.511: \tmt1.0 <- (b1.t <- 4)\n//│ ╙──       \t          ^^^^\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.511: \tmt1.0 <- (b1.t <- 4)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── assignment of type `unit` is not an instance of type `int`\n//│ ║  l.511: \tmt1.0 <- (b1.t <- 4)\n//│ ║         \t          ^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.364: \tdef mt1: (mut int, mut bool)\n//│ ║         \t              ^^^\n//│ ╟── from assigned selection:\n//│ ║  l.511: \tmt1.0 <- (b1.t <- 4)\n//│ ╙──       \t^^^^^\n//│ ╔══[ERROR] Illegal assignment\n//│ ║  l.512: \t(mt1.0 <- b1.t) <- 4\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── cannot assign to assignment\n//│ ║  l.512: \t(mt1.0 <- b1.t) <- 4\n//│ ╙──       \t^^^^^^^^^^^^^^^\n//│ res: error\n//│ ╔══[ERROR] Illegal assignment\n//│ ║  l.513: \tb1.x <- 1 + 2 <- 4\n//│ ║         \t            ^^^^^^\n//│ ╟── cannot assign to integer literal\n//│ ║  l.513: \tb1.x <- 1 + 2 <- 4\n//│ ╙──       \t            ^\n//│ Code generation encountered an error:\n//│   illegal assignemnt left-hand side: Bra(false,Assign(Sel(Var(mt1),Var(0)),Sel(Var(b1),Var(t))))\n\ndef f : {mut 0 : int} -> int -> unit\ndef g : (mut int, bool) -> int -> unit\n//│ f: {mut 0: int} -> int -> unit\n//│  = <missing implementation>\n//│ g: (mut int, bool,) -> int -> unit\n//│  = <missing implementation>\n\ndef f a n = a.0 <- n\n//│ {mut 0: in '0} -> '0 -> unit\n//│   <:  f:\n//│ {mut 0: int} -> int -> unit\n//│  = [Function: f]\n\nf mt1 1\n//│ = undefined\n\n:e\nf mt2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.598: \tf mt2\n//│ ║         \t^^^^^\n//│ ╟── tuple field of type `int` is not mutable\n//│ ║  l.365: \tdef mt2: (int, int)\n//│ ╙──       \t          ^^^\n//│ res: error | int -> unit\n//│    = <no result>\n//│      mt2 is not implemented\n\n:e\ng (1, true) 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.610: \tg (1, true) 2\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── argument of type `1` is not mutable\n//│ ║  l.610: \tg (1, true) 2\n//│ ╙──       \t   ^\n//│ res: error | unit\n//│    = <no result>\n//│      g is not implemented\n\n// TODO forbid `mut` here\ng (mut 1, true) 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.622: \tg (mut 1, true) 2\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── argument of type `1` is not mutable\n//│ ║  l.622: \tg (mut 1, true) 2\n//│ ╙──       \t       ^\n//│ res: error | unit\n//│    = <no result>\n//│      g is not implemented\n\nw1 = 3 with {mut x = 4}\nw1.x <- 3\n//│ w1: 3 & {mut x: 'x}\n//│   where\n//│     'x :> 4\n//│   = [Number: 3] { x: 4 }\n//│ = undefined\n\nw1.x\n//│ res: 4\n//│    = 3\n\ndef st1 : (int, )\ndef st2 : (mut int, )\n//│ st1: (int,)\n//│    = <missing implementation>\n//│ st2: (mut int,)\n//│    = <missing implementation>\n\nst1 = (3,)\nst2 = (mut 4,)\n//│ (3,)\n//│   <:  st1:\n//│ (int,)\n//│    = [ 3 ]\n//│ (mut 'a,)\n//│   where\n//│     'a :> 4\n//│   <:  st2:\n//│ (mut int,)\n//│    = [ 4 ]\n\nst2.0 <- 8\n//│ = undefined\n\n:e\nst1.0 <- 9\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.669: \tst1.0 <- 9\n//│ ║         \t^^^^^^^^^^\n//│ ╟── tuple field of type `int` is not mutable\n//│ ║  l.645: \tdef st1 : (int, )\n//│ ║         \t           ^^^\n//│ ╟── but it flows into assigned field with expected type `?0`\n//│ ║  l.669: \tst1.0 <- 9\n//│ ╙──       \t    ^\n//│ = undefined\n\ndef am1 : Array[(mut int)]\n//│ am1: Array[(mut int,)]\n//│    = <missing implementation>\n\ndef foreach : Array['a] -> ('a -> unit) -> Array['a]\n//│ foreach: Array['a] -> ('a -> unit) -> Array['a]\n//│        = <missing implementation>\n\nforeach am1 (fun x -> x[0] <- 1)\nforeach am1 (fun y -> y.0 <- 2)\n//│ res: Array[(mut int,)]\n//│    = <no result>\n//│      foreach is not implemented\n//│ res: Array[(mut int,)]\n//│    = <no result>\n//│      foreach is not implemented\n\n:e\n(1,2,3)[0] <- true\n(1,2,3).0 <- \"hello\"\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.699: \t(1,2,3)[0] <- true\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── assigned array element of type `1 | 2 | 3` cannot be reassigned\n//│ ║  l.699: \t(1,2,3)[0] <- true\n//│ ╙──       \t^^^^^^^^^^\n//│ = undefined\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.700: \t(1,2,3).0 <- \"hello\"\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── tuple field of type `1` is not mutable\n//│ ║  l.700: \t(1,2,3).0 <- \"hello\"\n//│ ║         \t ^\n//│ ╟── but it flows into assigned field with expected type `?0`\n//│ ║  l.700: \t(1,2,3).0 <- \"hello\"\n//│ ╙──       \t        ^\n//│ = undefined\n\n:e\n(0,)[\"oops\"]\n(mut 0,)[\"oops\"] <- 1\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.720: \t(0,)[\"oops\"]\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.720: \t(0,)[\"oops\"]\n//│ ╙──       \t     ^^^^^^\n//│ res: 0 | undefined\n//│    = undefined\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.721: \t(mut 0,)[\"oops\"] <- 1\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.721: \t(mut 0,)[\"oops\"] <- 1\n//│ ╙──       \t         ^^^^^^\n//│ = undefined\n\noops = \"oops\"\narr = (mut 0,)\n//│ oops: \"oops\"\n//│     = 'oops'\n//│ arr: (mut 'a,)\n//│   where\n//│     'a :> 0\n//│    = [ 0 ]\n\n:e\narr[oops]\narr[oops] <- 1\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.748: \tarr[oops]\n//│ ║         \t^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.738: \toops = \"oops\"\n//│ ║         \t       ^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.748: \tarr[oops]\n//│ ╙──       \t    ^^^^\n//│ res: 0 | undefined\n//│    = undefined\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.749: \tarr[oops] <- 1\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.738: \toops = \"oops\"\n//│ ║         \t       ^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.749: \tarr[oops] <- 1\n//│ ╙──       \t    ^^^^\n//│ = undefined\n\n\n// TODO support typing of mutable local variable\n\nx = 1\n//│ x: 1\n//│  = 1\n\n:e\nx <- 2\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.780: \tx <- 2\n//│ ║         \t^^^^^^\n//│ ╟── integer literal of type `2` does not match type `1`\n//│ ║  l.780: \tx <- 2\n//│ ║         \t     ^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.775: \tx = 1\n//│ ╙──       \t    ^\n//│ = undefined\n\nx\n//│ res: 1\n//│    = 2\n\n\n\nfun x -> (x.a <- 0, x.a + 1)\n//│ res: {mut a: in 0 out int} -> (unit, int,)\n//│    = [Function: res]\n\ndef foo x y = (x.a <- 0, x.a + 1, x.a, x.a <- y)\n//│ foo: {mut a: in 0 | 'a out int & 'a0} -> 'a -> (unit, int, 'a0, unit,)\n//│    = [Function: foo]\n\ndef foo x y z = (x.a <- 0, x.a + 1, x.a, x.a <- y, z x.a)\n//│ foo: {mut a: in 0 | 'a out int & 'a0} -> 'a -> ('a0 -> 'b) -> (unit, int, 'a0, unit, 'b,)\n//│    = [Function: foo1]\n\nfoo { mut a = 1 } 2 add\n//│ res: (unit, int, 0 | 1 | 2, unit, int -> int,)\n//│    = [ undefined, 1, 0, undefined, [Function (anonymous)] ]\n\n:e\nfoo { mut a = 1 } 2 3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.815: \tfoo { mut a = 1 } 2 3\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `3` is not a function\n//│ ║  l.815: \tfoo { mut a = 1 } 2 3\n//│ ║         \t                    ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.806: \tdef foo x y z = (x.a <- 0, x.a + 1, x.a, x.a <- y, z x.a)\n//│ ║         \t                                                   ^^^^^\n//│ ╟── from reference:\n//│ ║  l.806: \tdef foo x y z = (x.a <- 0, x.a + 1, x.a, x.a <- y, z x.a)\n//│ ╙──       \t                                                   ^\n//│ res: error | (unit, int, 0 | 1 | 2, unit, nothing,)\n//│ Runtime error:\n//│   TypeError: z is not a function\n\n:e\nfoo { mut a = \"oops\" } 2\nfoo { a = 1 } 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.833: \tfoo { mut a = \"oops\" } 2\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.833: \tfoo { mut a = \"oops\" } 2\n//│ ║         \t              ^^^^^^\n//│ ╟── but it flows into mutable record field with expected type `int`\n//│ ║  l.833: \tfoo { mut a = \"oops\" } 2\n//│ ║         \t          ^^^^^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.806: \tdef foo x y z = (x.a <- 0, x.a + 1, x.a, x.a <- y, z x.a)\n//│ ╙──       \t                           ^^^\n//│ res: error | ((\"oops\" | 0 | 2) -> 'a) -> (unit, int, \"oops\" | 0 | 2, unit, 'a,)\n//│    = [Function (anonymous)]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.834: \tfoo { a = 1 } 2\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── record field of type `1` is not mutable\n//│ ║  l.834: \tfoo { a = 1 } 2\n//│ ╙──       \t      ^^^^^\n//│ res: error | (1 -> 'a) -> (unit, int, 1, unit, 'a,)\n//│    = [Function (anonymous)]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Mut2.mls",
    "content": "\n(mut 1,): MutArray['a]\n//│ res: MutArray['a]\n//│   where\n//│     'a :> 1\n//│    = [ 1 ]\n\n(mut 1, mut 2): MutArray['a]\n//│ res: MutArray['a]\n//│   where\n//│     'a :> 1 | 2\n//│    = [ 1, 2 ]\n\n((fun t -> let tmp = t.0 <- 3 in t) ((mut 1, mut 2))): MutArray['a]\n//│ res: MutArray['a]\n//│   where\n//│     'a :> 1 | 2 | 3\n//│    = [ 3, 2 ]\n\n((fun t -> let tmp = t.0 + 1 in t) ((mut 1, mut 2))): MutArray['a]\n//│ res: MutArray[in 'a & 'b out 'b]\n//│   where\n//│     'a <: int & 'b\n//│     'b :> 1 | 2\n//│        <: 'a\n//│    = [ 1, 2 ]\n\nif true then (mut 1,) else (mut 2,)\n//│ res: (mut in 'a out 1 | 2 | 'a,)\n//│    = [ 1 ]\n\nif true then (mut 1, mut 2) else (mut 3, mut 4)\n//│ res: (mut in 'a out 1 | 3 | 'a, mut in 'b out 2 | 4 | 'b,)\n//│    = [ 1, 2 ]\n\ndef t1: (mut 1, mut 2)\ndef t2: (mut 3, mut 4)\n//│ t1: (mut 1, mut 2,)\n//│   = <missing implementation>\n//│ t2: (mut 3, mut 4,)\n//│   = <missing implementation>\n\nr = if true then t1 else t2\n//│ r: (mut out 1 | 3, mut out 2 | 4,)\n//│  = <no result>\n//│    t1 is not implemented\n\n:e\nr.0 <- 1\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.49: \tr.0 <- 1\n//│ ║        \t^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `3`\n//│ ║  l.49: \tr.0 <- 1\n//│ ║        \t       ^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.37: \tdef t2: (mut 3, mut 4)\n//│ ║        \t             ^\n//│ ╟── from assigned selection:\n//│ ║  l.49: \tr.0 <- 1\n//│ ╙──      \t^^^\n//│ = <no result>\n//│   r and t1 are not implemented\n\n\ndef t1: (mut 1 | 2 | 3)\ndef t2: (mut 2 | 3 | 4)\n//│ t1: (mut 1 | 2 | 3,)\n//│   = <missing implementation>\n//│ t2: (mut 2 | 3 | 4,)\n//│   = <missing implementation>\n\nr = if true then t1 else t2\n//│ r: (mut in 2 | 3 out 1 | 2 | 3 | 4,)\n//│  = <no result>\n//│    t1 is not implemented\n\nr.0 <- if true then 2 else 3\n//│ = <no result>\n//│   r and t1 are not implemented\n\n:e\nr.0 <- if true then 2 else 1\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.83: \tr.0 <- if true then 2 else 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `2 | 3 | 4`\n//│ ║  l.83: \tr.0 <- if true then 2 else 1\n//│ ║        \t                           ^\n//│ ╟── but it flows into application with expected type `2 | 3 | 4`\n//│ ║  l.83: \tr.0 <- if true then 2 else 1\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.67: \tdef t2: (mut 2 | 3 | 4)\n//│ ║        \t             ^^^^^^^^^\n//│ ╟── from assigned selection:\n//│ ║  l.83: \tr.0 <- if true then 2 else 1\n//│ ╙──      \t^^^\n//│ = <no result>\n//│   r and t1 are not implemented\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/MutArray.mls",
    "content": "\n\n\ndef access0 arr = arr[0]\n//│ access0: Array['a & ~undefined] -> (undefined | 'a)\n//│        = [Function: access0]\n\ndef set0 arr x = arr[0] <- x\n//│ set0: MutArray['a] -> 'a -> unit\n//│     = [Function: set0]\n\n\naccess0((1,))\naccess0((mut 1,))\n//│ res: 1 | undefined\n//│    = 1\n//│ res: 1 | undefined\n//│    = 1\n\nset0((mut 1,))\n//│ res: anything -> unit\n//│    = [Function (anonymous)]\n\n:e\nset0((1,))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.25: \tset0((1,))\n//│ ║        \t^^^^^^^^^^\n//│ ╟── tuple field of type `1` is not mutable\n//│ ║  l.25: \tset0((1,))\n//│ ╙──      \t      ^\n//│ res: error | anything -> unit\n//│    = [Function (anonymous)]\n\n\naccess0 emptyArray\n//│ res: undefined\n//│    = undefined\n\nset0 emptyArray 42\n//│ = undefined\n\n\n\ndef update0 i arr = arr[i] <- arr[i]\n//│ update0: int -> MutArray[in 'a | undefined out 'a & ~undefined] -> unit\n//│        = [Function: update0]\n\ndef update1 i arr = arr[i] <- let a = arr[i] in case a of undefined -> error, _ -> a\n//│ update1: int -> MutArray[in 'a out 'a & ~undefined] -> unit\n//│        = [Function: update1]\n\ndef update2 i arr = let a = arr[i] in arr[i] <- case a of undefined -> error, _ -> a\n//│ update2: int -> MutArray[in 'a out 'a & ~undefined] -> unit\n//│        = [Function: update2]\n\n\n// * Strange that it's reported here\n:e\nupdate0 0 ((mut 1,))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.60: \tupdate0 0 ((mut 1,))\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── possibly-undefined array access of type `undefined` does not match type `~undefined`\n//│ ║  l.45: \tdef update0 i arr = arr[i] <- arr[i]\n//│ ╙──      \t                              ^^^^^^\n//│ res: error | unit\n//│    = undefined\n\nupdate1 0 ((mut 1,))\n//│ = undefined\n\nupdate2 0 ((mut 1,))\n//│ = undefined\n\n\n\n\n// * Weird stuff:\n\n\ndef foo: MutArray[int] & MutArray[string]\n//│ foo: MutArray[in int | string out nothing]\n//│    = <missing implementation>\n\n// * Note that this now signature-checks because it instantiates the inferred polymorphic type\n// * later (once for each intersection component)\n// :e\nfoo = emptyArray\n//│ MutArray['a]\n//│   <:  foo:\n//│ MutArray[in int | string out nothing]\n//│    = [Function: emptyArray] { '0': 42 }\n\n:e\ndef bar x = (mut x,) : MutArray[int] & MutArray[string]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.96: \tdef bar x = (mut x,) : MutArray[int] & MutArray[string]\n//│ ║        \t            ^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.96: \tdef bar x = (mut x,) : MutArray[int] & MutArray[string]\n//│ ║        \t                                                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.96: \tdef bar x = (mut x,) : MutArray[int] & MutArray[string]\n//│ ║        \t                                ^^^\n//│ ╟── from mutable tuple field:\n//│ ║  l.96: \tdef bar x = (mut x,) : MutArray[int] & MutArray[string]\n//│ ╙──      \t                 ^\n//│ bar: nothing -> MutArray[in int | string out nothing]\n//│    = [Function: bar]\n\nfoo[0]\n//│ res: undefined\n//│    = 42\n\nfun x -> foo[0] <- x\n//│ res: (int | string) -> unit\n//│    = [Function: res]\n\naccess0 foo\nset0 foo \"ok\"\n//│ res: undefined\n//│    = 42\n//│ = undefined\n\nupdate1 0 foo\n//│ = undefined\n\nfoo: MutArray['a]\n//│ res: MutArray['a]\n//│   where\n//│     'a <: int | string\n//│    = [Function: emptyArray] { '0': 'ok' }\n\nfoo: MutArray['a] & MutArray['b]\n//│ res: MutArray[in (int | string) & 'a | (int | string) & 'b out 'a & 'b]\n//│    = [Function: emptyArray] { '0': 'ok' }\n\nfoo[0]\n//│ res: undefined\n//│    = 'ok'\n\nfoo: MutArray['a] | MutArray['b]\n//│ res: MutArray[in 'b & (int | string | ~'b) out 'b]\n//│    = [Function: emptyArray] { '0': 'ok' }\n\nfoo[0]\n//│ res: undefined\n//│    = 'ok'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Neg.mls",
    "content": "\n1: ~string\n//│ res: ~string\n//│    = 1\n\n:e\n1: ~int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.7: \t1: ~int\n//│ ║       \t^\n//│ ╟── integer literal of type `1` does not match type `~int`\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.7: \t1: ~int\n//│ ╙──     \t   ^^^^\n//│ res: ~int\n//│    = 1\n\n:e\nadd res 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.19: \tadd res 1\n//│ ║        \t^^^^^^^\n//│ ╟── type `~int` is not an instance of type `int`\n//│ ║  l.7: \t1: ~int\n//│ ║       \t   ^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.19: \tadd res 1\n//│ ╙──      \t    ^^^\n//│ res: error | int\n//│    = 2\n\n:e\n(1: int): ~int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.33: \t(1: int): ~int\n//│ ║        \t^^^^^^^^\n//│ ╟── type `int` does not match type `~int`\n//│ ║  l.33: \t(1: int): ~int\n//│ ║        \t    ^^^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.33: \t(1: int): ~int\n//│ ╙──      \t          ^^^^\n//│ res: ~int\n//│    = 1\n\n1: ~2\n//│ res: ~2\n//│    = 1\n\n1: int\n//│ res: int\n//│    = 1\n\n\"ok\": ~int\n//│ res: ~int\n//│    = 'ok'\n\n1: ~(~1 & ~2)\n//│ res: 1 | 2\n//│    = 1\n\n:e\n1: ~(~3 & ~2)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.63: \t1: ~(~3 & ~2)\n//│ ║        \t^\n//│ ╟── integer literal of type `1` does not match type `2 | 3`\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.63: \t1: ~(~3 & ~2)\n//│ ╙──      \t   ^^^^^^^^^^\n//│ res: 2 | 3\n//│    = 1\n\n\nclass Lit\nclass Add\n//│ Defined class Lit\n//│ Defined class Add\n\ndef f: ~lit & {x:int} -> int // Note the precedence!\n//│ f: {x: int} -> int\n//│  = <missing implementation>\n\ndef f: (~lit & {x:int}) -> int\n//│ f: ({x: int} & ~#Lit) -> int\n//│  = <missing implementation>\n\n// :ds\ndef f: (~Lit & {x:int}) -> int\n//│ f: ({x: int} & ~Lit) -> int\n//│  = <missing implementation>\n\ndef f: ~Lit & 'b -> 'b\n//│ f: 'b -> 'b & ~Lit\n//│  = <missing implementation>\n\ndef f: ~Lit & ~Add & 'b -> 'b\n//│ f: 'b -> 'b & ~Add & ~Lit\n//│  = <missing implementation>\n\ndef f: (~Lit & 'b) -> 'b\n//│ f: ('b & ~Lit) -> 'b\n//│  = <missing implementation>\n\ndef f: (~Lit & ~Add & 'b) -> 'b\n//│ f: ('b & ~Add & ~Lit) -> 'b\n//│  = <missing implementation>\n\ndef f: ~Lit & ~Lit\n//│ f: ~Lit\n//│  = <missing implementation>\n\n:w\nclass Foo[A]\n//│ Defined class Foo[±A]\n//│ ╔══[WARNING] Type definition Foo has bivariant type parameters:\n//│ ║  l.114: \tclass Foo[A]\n//│ ║         \t      ^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.114: \tclass Foo[A]\n//│ ╙──       \t          ^\n\ndef f: ~Foo[1 | 2] | ~Foo[2 | 3]\n//│ f: ~Foo[?]\n//│  = <missing implementation>\n\ndef f: (~Foo[1 | 2] & 'a | ~Foo[2 | 3] & 'a) -> 'a\n//│ f: ('a & ~Foo[?]) -> 'a\n//│  = <missing implementation>\n\n// * Type ~{x: 1 | 2} & 'a | ~{x: 2 | 3} & 'a\n// *   is ~({x: 1 | 2} & {x: 2 | 3}) & 'a\n// *   is ~{x: 2}) & 'a\ndef f: (~{x: 1 | 2} & 'a | ~{x: 2 | 3} & 'a) -> 'a\n//│ f: ('a & ~{x: 2}) -> 'a\n//│  = <missing implementation>\n\nf = id\n//│ 'a -> 'a\n//│   <:  f:\n//│ ('a & ~{x: 2}) -> 'a\n//│  = [Function: id]\n\n:e\nf x = case x of {}\n//│ nothing -> nothing\n//│   <:  f:\n//│ ('a & ~{x: 2}) -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.145: \tf x = case x of {}\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a & ~{x: 1 | 2}` does not match type `nothing`\n//│ ║  l.134: \tdef f: (~{x: 1 | 2} & 'a | ~{x: 2 | 3} & 'a) -> 'a\n//│ ║         \t        ^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.145: \tf x = case x of {}\n//│ ╙──       \t           ^\n//│  = [Function: f2]\n\ndef f: (~{x: 1 | 2} & ~lit & 'a | ~{x: 2 | 3} & ~lit & 'a) -> 'a\n//│ f: ('a & ~{x: 2} & ~#Lit) -> 'a\n//│  = <missing implementation>\n\n\ndef f: string & 'a & ~int & ~string | string & ~int\n//│ f: string\n//│  = <missing implementation>\n\n\ntrait T\n//│ Defined trait T\n\ndef a: T & 1 | T & 1 & ~'a | 'a\n//│ a: T & 1\n//│  = <missing implementation>\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/NestedClassArgs.mls",
    "content": ":NoJS\n// :NoProvs\n\n\nclass C[A]\n  method In: A -> A\n  method In = id\n//│ Defined class C[=A]\n//│ Declared C.In: C['A] -> 'A -> 'A\n//│ Defined C.In: C['A] -> 'a -> 'a\n\ndef c: C[C[int]]\n//│ c: C[C[int]]\n\ndef c: 'a -> C[C['a]]\n//│ c: 'a -> C[C['a]]\n\ndef c: C[C['a]] -> 'a\n//│ c: C[C['a]] -> 'a\n\ndef c: C['a] as 'a\n//│ c: 'a\n//│   where\n//│     'a := C['a]\n\n// * [test:T3] What happens here is we use `factorize` to simplify the union,\n// * which uses the fact that `C['a] <: 'a` to reduce `C['a] | 'a` to `'a`...\n// * which is obviously NOT valid when that union we're processing is itself the definition of `'a`!\n// * So we will need to be more careful about simplifying types, so as not to assume bounds\n// * we are in the process of simplifying. This could be done by NOT simplifying things in place.\ndef c: C['a] | 'a as 'a\n//│ c: 'a\n//│   where\n//│     'a := 'a\n\ndef c: C[C['a]] as 'a\n//│ c: 'a\n//│   where\n//│     'a := C[C['a]]\n\ndef c: C[C['a] & 'a] as 'a\n//│ c: 'a\n//│   where\n//│     'a := C[C['a] & 'a]\n\ndef c: C[C['a] & 'a | 'a] as 'a\n//│ c: 'a\n//│   where\n//│     'a := C['a]\n\ndef c: C['a]\n//│ c: C['a]\n\n\nclass C2[A]: { a: A }\n  method In: A -> A\n  method In = id\n//│ Defined class C2[=A]\n//│ Declared C2.In: C2['A] -> 'A -> 'A\n//│ Defined C2.In: C2['A] -> 'a -> 'a\n\n\ndef mkC: 'a -> C2['a]\n//│ mkC: 'a -> C2['a]\n\nmkC' a = C2 { a }\n//│ mkC': ('a & 'A) -> (C2['A] with {a: 'a})\n\nmkC = mkC'\n//│ ('a & 'A) -> (C2['A] with {a: 'a})\n//│   <:  mkC:\n//│ 'a -> C2['a]\n\nrec def rc = mkC(rc)\n//│ rc: C2['a]\n//│   where\n//│     'a :> C2['a]\n\nrec def rc = mkC'(rc)\n//│ rc: 'a\n//│   where\n//│     'a :> C2['A] & {a: forall 'a. 'a}\n//│     'A :> forall 'a. 'a\n\n\n\nclass C3[A]: { a: C3[A] }\n  method In: A -> A\n  method In = id\n//│ Defined class C3[=A]\n//│ Declared C3.In: C3['A] -> 'A -> 'A\n//│ Defined C3.In: C3['A] -> 'a -> 'a\n\ndef c: 'a -> C3['a]\n//│ c: 'a -> C3['a]\n\nrec def c a = C3 { a = c a }\n//│ anything -> 'a\n//│   where\n//│     'a :> C3['A] with {a: 'a}\n//│   <:  c:\n//│ 'a -> C3['a]\n\nrec def c (a: 'X) = C3 { a = c a: 'X }: C3['X]\n//│ anything -> C3['X]\n//│   <:  c:\n//│ 'a -> C3['a]\n\n\nclass C4[A]: { a: C[C4[A]] }\n  method In: A -> A\n  method In = id\n//│ Defined class C4[=A]\n//│ Declared C4.In: C4['A] -> 'A -> 'A\n//│ Defined C4.In: C4['A] -> 'a -> 'a\n\ndef c: 'a -> C4['a]\n//│ c: 'a -> C4['a]\n\nC{}\n//│ res: C['A]\n\ndef c4 a = C4{ a = C{} }\n//│ c4: anything -> (C4['A] with {a: forall 'A0. C['A0]})\n\ndef c = c4\n//│ anything -> (C4['A] with {a: forall 'A0. C['A0]})\n//│   <:  c:\n//│ 'a -> C4['a]\n\n\nclass C5[A]: { a: C2[C5[A]] }\n  method In: A -> A\n  method In = id\n//│ Defined class C5[=A]\n//│ Declared C5.In: C5['A] -> 'A -> 'A\n//│ Defined C5.In: C5['A] -> 'a -> 'a\n\ndef c: 'a -> C5['a]\n//│ c: 'a -> C5['a]\n\nrec def c5 a = C5{ a = C2 { a = c5 a } }\n//│ c5: anything -> (C5['A] with {a: 'a})\n//│   where\n//│     'a :> C2['A0] with {a: C5['A] with {a: 'a}}\n//│     'A0 :> (C5['A] with {a: 'a}) | C5['A]\n//│         <: C5['A]\n\nc = c5\n//│ anything -> (C5['A] with {a: 'a})\n//│   where\n//│     'a :> C2['A0] with {a: C5['A] with {a: 'a}}\n//│     'A0 :> (C5['A] with {a: 'a}) | C5['A]\n//│         <: C5['A]\n//│   <:  c:\n//│ 'a -> C5['a]\n\n\nclass C6[A]: { a: C5[C6[A]] }\n  method In: A -> A\n  method In = id\n//│ Defined class C6[=A]\n//│ Declared C6.In: C6['A] -> 'A -> 'A\n//│ Defined C6.In: C6['A] -> 'a -> 'a\n\ndef c: 'a -> C6['a]\n//│ c: 'a -> C6['a]\n\nrec def c6 a = C6{ a = c5 (c6 a) }\n//│ c6: anything -> (C6['A] with {a: forall 'A0 'a 'A1. C5['A0] with {a: 'a}})\n//│   where\n//│     'a :> C2['A1] with {a: C5['A0] with {a: 'a}}\n//│     'A1 :> (C5['A0] with {a: 'a}) | C5['A0]\n//│         <: C5['A0]\n\n:stats\nc = c6\n//│ anything -> (C6['A] with {a: forall 'A0 'a 'A1. C5['A0] with {a: 'a}})\n//│   where\n//│     'a :> C2['A1] with {a: C5['A0] with {a: 'a}}\n//│     'A1 :> (C5['A0] with {a: 'a}) | C5['A0]\n//│         <: C5['A0]\n//│   <:  c:\n//│ 'a -> C6['a]\n//│ constrain calls  : 64\n//│ annoying  calls  : 34\n//│ subtyping calls  : 434\n\n\n// Reproduction of an issue found while trying out TypeRef ctor typing:\n\ndef e: C5[C6['A]] | C5[C6['A]] & ~c5 | C5[C6['A]] | C5[C6['A]] & ~{a: C2[C5[C6['A]]]}\n//│ e: C5[C6['A]]\n\ndef e: C5[C6['A]] & {a: C2[C5[C6['A]] | C5[C6['A]] & ~c5 | C5[C6['A]] | C5[C6['A]] & ~{a: C2[C5[C6['A]]]}] & {a: 'a}}\n//│ e: C5[C6['A]] & {a: C2[C5[C6['A]]] & {a: nothing}}\n\ntype Inner = C5[C6['A]] & {a: C2[C5[C6['A]] | C5[C6['A]] & ~c5 | C5[C6['A]] | C5[C6['A]] & ~{a: C2[C5[C6['A]]]}] & {a: 'a}} as 'a\n//│ Defined type alias Inner\n\ndef e: anything -> (C6['A] & {a: Inner})\n//│ e: anything -> (C6['A] with {a: Inner})\n\n// * The problem seems to come from Inner defining type variables, which are given level 0...\n// *  This is actually the expected behavior of type vars in type aliases,\n// *  but it's really weird and fishy so it should probably be rejected.\n// :e // no longer an error...(?)\n// :e // Fails with polymorphic RHS extrusion\n// Used to fail with a depth excess... (before implicitly quantifying TVs in type defs)\nc = e\n//│ anything -> (C6['A] with {a: Inner})\n//│   <:  c:\n//│ 'a -> C6['a]\n\ntype Inner2[A] = C5[C6[A]] & {a: C2[C5[C6[A]] | C5[C6[A]] & ~c5 | C5[C6[A]] | C5[C6[A]] & ~{a: C2[C5[C6[A]]]}] & {a: Inner2[A]}}\n//│ Defined type alias Inner2[=A]\n\ndef e: anything -> (C6['A] & {a: Inner2['A]})\n//│ e: anything -> (C6['A] with {a: Inner2['A]})\n\nc = e\n//│ anything -> (C6['A] with {a: Inner2['A]})\n//│   <:  c:\n//│ 'a -> C6['a]\n\n\n\nclass N: {}\nclass S[T]: { v: T }\n  method In: T -> ()\n  method In _ = ()\ntype O[T] = S[T] | N\nclass L[T]: { h: T; t: O[L[T]] }\n  method Append: T -> L[T]\n  method Append elem = L { h = elem; t = S { v = this } }\n//│ Defined class N\n//│ Defined class S[=T]\n//│ Declared S.In: S['T] -> 'T -> ()\n//│ Defined S.In: S['T] -> anything -> ()\n//│ Defined type alias O[=T]\n//│ Defined class L[=T]\n//│ Declared L.Append: L['T] -> 'T -> L['T]\n//│ Defined L.Append: (L['T] & 'this) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] & {v: L['T] & 'this}})\n\ns1 = S{v=1}:O['_]\ns2 = S{v=S{v=1}}:O[O['_]]\n//│ s1: O['_]\n//│   where\n//│     '_ :> 1\n//│ s2: O[O['_]]\n//│   where\n//│     '_ :> 1\n\n:e\nL{h=error;t=s1}\nL{h=error;t=s2}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.255: \tL{h=error;t=s1}\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `L`\n//│ ║  l.245: \ts1 = S{v=1}:O['_]\n//│ ║         \t         ^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.233: \tclass L[T]: { h: T; t: O[L[T]] }\n//│ ╙──       \t                         ^^^^\n//│ res: error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.256: \tL{h=error;t=s2}\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── type `S['_]` is not an instance of type `L`\n//│ ║  l.232: \ttype O[T] = S[T] | N\n//│ ║         \t            ^^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.233: \tclass L[T]: { h: T; t: O[L[T]] }\n//│ ╙──       \t                         ^^^^\n//│ res: error\n\n// :ds\n// L.Append\n\n// before:\n//  Defined L.Append: L['T] -> ('T & 'a & 'b) -> (L['T & 'b .. 'T | 'b] with {h: 'a, t: S[L['T & 'b .. 'T | 'b] & 'c .. L['T & 'b .. 'T | 'b] | L['T] | 'c] with {v: L['T]}})\n\nL.Append\n//│ res: L['T] -> 'T -> L['T]\n\n\ndef append ls elem = L { h = elem; t = S { v = ls } }\n//│ append: (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] with {v: 'v}})\n\n:ns\nappend\n//│ res: forall 'a 'b 'v 'T 'c 'h 'T0 't. 'a -> 'b -> 'c\n//│   where\n//│     'c :> #L & {h: 'h, t: 't, L#T = 'T0}\n//│     't :> #S & {v: 'v, S#T = 'T}\n//│        <: O[L['T0]]\n//│     'b <: 'h\n//│     'h <: 'T0\n//│     'a <: 'v\n//│     'v <: L['T0] & 'T\n//│     'T := L['T0]\n\nappend error\n//│ res: ('h & 'T) -> (L['T] with {h: 'h, t: S[L['T]] & {v: nothing}})\n\n\ndef append_ty: (L['T] & 'v) -> ('T & 'h) -> (L['T] & {h: 'h; t: S[L['T]] & {v: 'v}})\n//│ append_ty: (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] with {v: 'v}})\n\nappend_ty error\n//│ res: ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] & {v: nothing}})\n\nappend_ty = append\n//│ (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] with {v: 'v}})\n//│   <:  append_ty:\n//│ (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] with {v: 'v}})\n\n\n// * Note: An older bug (fixed in 2a562ddfc712ab44a55a12370380ef4f1c3383cb)\n// *    was dropping the bounds on T0 and generating this signature, which is too general:\ndef append_ty_2: (L['T] & 'v & 'T0) -> ('T & 'h) -> (L['T] & {h: 'h; t: S['T0] & {v: 'v}})\n//│ append_ty_2: (L['T] & 'v & 'T0) -> ('T & 'h) -> (L['T] with {h: 'h, t: S['T0] with {v: 'v}})\n\nappend_ty_2 error\n//│ res: ('T & 'h) -> (L['T] with {h: 'h, t: S['T0] & {v: nothing}})\n\n:e\nappend_ty_2 = append\n//│ (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] with {v: 'v}})\n//│   <:  append_ty_2:\n//│ (L['T] & 'v & 'T0) -> ('T & 'h) -> (L['T] with {h: 'h, t: S['T0] with {v: 'v}})\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.329: \tappend_ty_2 = append\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'T0` is not an instance of type `L`\n//│ ║  l.322: \tdef append_ty_2: (L['T] & 'v & 'T0) -> ('T & 'h) -> (L['T] & {h: 'h; t: S['T0] & {v: 'v}})\n//│ ║         \t                                                                          ^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.233: \tclass L[T]: { h: T; t: O[L[T]] }\n//│ ║         \t                         ^^^^\n//│ ╟── Note: class type parameter T is defined at:\n//│ ║  l.229: \tclass S[T]: { v: T }\n//│ ╙──       \t        ^\n\nappend_ty = append_ty_2\n//│ (L['T] & 'v & 'T0) -> ('T & 'h) -> (L['T] with {h: 'h, t: S['T0] with {v: 'v}})\n//│   <:  append_ty:\n//│ (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] with {v: 'v}})\n\n:e\nappend_ty_2 = append_ty\n//│ (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] with {v: 'v}})\n//│   <:  append_ty_2:\n//│ (L['T] & 'v & 'T0) -> ('T & 'h) -> (L['T] with {h: 'h, t: S['T0] with {v: 'v}})\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.352: \tappend_ty_2 = append_ty\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'T0` is not an instance of type `L`\n//│ ║  l.322: \tdef append_ty_2: (L['T] & 'v & 'T0) -> ('T & 'h) -> (L['T] & {h: 'h; t: S['T0] & {v: 'v}})\n//│ ║         \t                                                                          ^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.308: \tdef append_ty: (L['T] & 'v) -> ('T & 'h) -> (L['T] & {h: 'h; t: S[L['T]] & {v: 'v}})\n//│ ╙──       \t                                                                  ^^^^^\n\n\ndef append0 ls = L { h = 0; t = S { v = ls } }\n//│ append0: (L['T] & 'v) -> (L['T] with {h: 0, t: S[L['T]] with {v: 'v}})\n//│   where\n//│     'T :> 0\n\ndef appendNil elem = L { h = elem; t = N{} }\n//│ appendNil: ('h & 'T) -> (L['T] with {h: 'h, t: N})\n\n\nS{v=1}\n//│ res: S['T] & {v: 1}\n//│   where\n//│     'T :> 1\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/NestedClassArgs_Co.mls",
    "content": ":NoJS\n// :NoProvs\n\n\nclass C[A]\n  method Co: A\n  method Co = error\n//│ Defined class C[+A]\n//│ Declared C.Co: C['A] -> 'A\n//│ Defined C.Co: C[?] -> nothing\n\ndef c: C[C[int]]\n//│ c: C[C[int]]\n\ndef c: 'a -> C[C['a]]\n//│ c: 'a -> C[C['a]]\n\ndef c: C[C['a]] -> 'a\n//│ c: C[C['a]] -> 'a\n\ndef c: C['a] as 'a\n//│ c: 'a\n//│   where\n//│     'a :> C['a]\n\ndef c: C['a] | 'a as 'a\n//│ c: 'a\n//│   where\n//│     'a :> C['a]\n\ndef c: C[C['a]] as 'a\n//│ c: 'a\n//│   where\n//│     'a :> C[C['a]]\n\ndef c: C[C['a] & 'a] as 'a\n//│ c: 'a\n//│   where\n//│     'a :> C[C['a] & 'a]\n\ndef c: C[C['a] & 'a | 'a] as 'a\n//│ c: 'a\n//│   where\n//│     'a :> C['a]\n\ndef c: C['a]\n//│ c: C[nothing]\n\n\nclass C2[A]: { a: A }\n//│ Defined class C2[+A]\n\n\ndef mkC: 'a -> C2['a]\n//│ mkC: 'a -> C2['a]\n\nmkC' a = C2 { a }\n//│ mkC': 'a -> C2['a]\n\nmkC = mkC'\n//│ 'a -> C2['a]\n//│   <:  mkC:\n//│ 'a -> C2['a]\n\nrec def rc = mkC(rc)\n//│ rc: 'a\n//│   where\n//│     'a :> C2['a]\n\nrec def rc = mkC'(rc)\n//│ rc: 'a\n//│   where\n//│     'a :> C2[forall 'a. 'a]\n\n\n\nclass C3[A]: { a: C3[A] }\n  method Co: A\n  method Co = error\n//│ Defined class C3[+A]\n//│ Declared C3.Co: C3['A] -> 'A\n//│ Defined C3.Co: C3[?] -> nothing\n\ndef c: 'a -> C3['a]\n//│ c: 'a -> C3['a]\n\nrec def c a = C3 { a = c a }\n//│ anything -> 'a\n//│   where\n//│     'a :> C3[nothing] with {a: 'a}\n//│   <:  c:\n//│ 'a -> C3['a]\n\nrec def c (a: 'X) = C3 { a = c a: 'X }: C3['X]\n//│ anything -> C3[nothing]\n//│   <:  c:\n//│ 'a -> C3['a]\n\n\nclass C4[A]: { a: C[C4[A]] }\n  method Co: A\n  method Co = error\n//│ Defined class C4[+A]\n//│ Declared C4.Co: C4['A] -> 'A\n//│ Defined C4.Co: C4[?] -> nothing\n\ndef c: 'a -> C4['a]\n//│ c: 'a -> C4['a]\n\nC{}\n//│ res: C[nothing]\n\ndef c4 a = C4{ a = C{} }\n//│ c4: anything -> (C4[nothing] & {a: C[nothing]})\n\ndef c = c4\n//│ anything -> (C4[nothing] & {a: C[nothing]})\n//│   <:  c:\n//│ 'a -> C4['a]\n\n\nclass C5[A]: { a: C2[C5[A]] }\n  method Co: A\n  method Co = error\n//│ Defined class C5[+A]\n//│ Declared C5.Co: C5['A] -> 'A\n//│ Defined C5.Co: C5[?] -> nothing\n\ndef c: 'a -> C5['a]\n//│ c: 'a -> C5['a]\n\nrec def c5 a = C5{ a = C2 { a = c5 a } }\n//│ c5: anything -> (C5[nothing] with {a: 'a})\n//│   where\n//│     'a :> C2[C5[nothing] with {a: 'a}]\n\nc = c5\n//│ anything -> (C5[nothing] with {a: 'a})\n//│   where\n//│     'a :> C2[C5[nothing] with {a: 'a}]\n//│   <:  c:\n//│ 'a -> C5['a]\n\n\nclass C6[A]: { a: C5[C6[A]] }\n  method Co: A\n  method Co = error\n//│ Defined class C6[+A]\n//│ Declared C6.Co: C6['A] -> 'A\n//│ Defined C6.Co: C6[?] -> nothing\n\ndef c: 'a -> C6['a]\n//│ c: 'a -> C6['a]\n\n// :s\n// :d\n// rec def c a = C6{ a = c5 (c a) }\n\nrec def c6 a = C6{ a = c5 (c6 a) }\n//│ c6: anything -> (C6[nothing] with {a: forall 'a. C5[nothing] with {a: 'a}})\n//│   where\n//│     'a :> C2[C5[nothing] with {a: 'a}]\n\nc = c6\n//│ anything -> (C6[nothing] with {a: forall 'a. C5[nothing] with {a: 'a}})\n//│   where\n//│     'a :> C2[C5[nothing] with {a: 'a}]\n//│   <:  c:\n//│ 'a -> C6['a]\n\n\n\n\nclass N: {}\nclass S[T]: { v: T }\ntype O[T] = S[T] | N\nclass L[T]: { h: T; t: O[L[T]] }\n  method Append: T -> L[T]\n  method Append elem = L { h = elem; t = S { v = this } }\n//│ Defined class N\n//│ Defined class S[+T]\n//│ Defined type alias O[+T]\n//│ Defined class L[=T]\n//│ Declared L.Append: L['T] -> 'T -> L['T]\n//│ Defined L.Append: (L['T] & 'this) -> ('T & 'h) -> (L['T] with {h: 'h, t: S[L['T]] & {v: L['T] & 'this}})\n\n// :ds\n// L.Append\n\n// before:\n//  Defined L.Append: L['T] -> ('T & 'a & 'b) -> (L['T & 'b .. 'T | 'b] with {h: 'a, t: S[L['T & 'b .. 'T | 'b] & 'c .. L['T & 'b .. 'T | 'b] | L['T] | 'c] with {v: L['T]}})\n\nL.Append\n//│ res: L['T] -> 'T -> L['T]\n\n\ndef append ls elem = L { h = elem; t = S { v = ls } }\n//│ append: (L['T] & 'v) -> ('T & 'h) -> (L['T] with {h: 'h, t: S['v]})\n\ndef append0 ls = L { h = 0; t = S { v = ls } }\n//│ append0: (L['T] & 'v) -> (L['T] with {h: 0, t: S['v]})\n//│   where\n//│     'T :> 0\n\ndef appendNil elem = L { h = elem; t = N{} }\n//│ appendNil: ('h & 'T) -> (L['T] with {h: 'h, t: N})\n\n\nS{v=1}\n//│ res: S[1]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/NestedMatch.mls",
    "content": "\ndef f x = case x of {\n  | 0 -> 0\n  | _ -> case x of {\n    | 1 -> 1\n    | 2 -> 2\n    }\n  }\n//│ f: (0 | 1 | 2) -> (0 | 1 | 2)\n//│  = [Function: f]\n\ndef f x = case x of {\n  | 0 -> 0\n  | _ -> case x of {\n    | 1 -> 1\n    | _ -> 2\n    }\n  }\n//│ f: anything -> (0 | 1 | 2)\n//│  = [Function: f1]\n\ndef f x = case x of {\n  | 0 -> 0\n  | _ -> case x of {\n    | 1 -> 1\n    | _ -> x\n    }\n  }\n//│ f: (0 | 1 | 'a & ~0 & ~1) -> (0 | 1 | 'a)\n//│  = [Function: f2]\n\ndef f x = case x of {\n  | 0 -> x\n  | _ -> case x of {\n    | 1 -> 1\n    | _ -> x\n    }\n  }\n//│ f: (1 | 'a & (0 | ~0 & ~1)) -> (1 | 'a)\n//│  = [Function: f3]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/NestedRecursiveMatch.mls",
    "content": ":NoJS\n\nclass Leaf\nclass Node\nclass Some[A]: { value: A }\n  method Id: A -> A\nclass None\n//│ Defined class Leaf\n//│ Defined class Node\n//│ Defined class Some[=A]\n//│ Declared Some.Id: Some['A] -> 'A -> 'A\n//│ Defined class None\n\ndef Some: 'a -> Some['a]\ndef None: None\n//│ Some: 'a -> Some['a]\n//│ None: None\n\nrec def f w = case w of\n  Leaf -> None,\n  Node ->\n    let left = (w).left in\n    let right = (w).right in\n    let tmp0 = f (left,) in\n    case tmp0 of\n      None -> (\n        let tmp1 = f (right,) in\n        case tmp1 of\n          None -> Some (0,),\n          Some ->\n            let m = (tmp1).value in\n            Some (m,)\n      ),\n      Some ->\n        let m = (tmp0).value in\n        Some (m,)\n//│ f: (Leaf | Node & 'b) -> (None | Some[in 'a out 0 | 'a])\n//│   where\n//│     'b <: {left: Leaf | Node & 'b, right: Leaf | Node & 'b}\n\n// * Minimizations:\n\nrec def f w = case w of\n  Node ->\n    let left = (w).left in\n    let tmp0 = f (left,) in\n    case tmp0 of\n      None -> Some (0,),\n      Some ->\n        let m = (tmp0).value in\n        Some (m,)\n//│ f: 'left -> Some[in 'a out 0 | 'a]\n//│   where\n//│     'left <: Node & {left: 'left}\n\nrec def f w = case w of\n  Node ->\n    let tmp0 = f w.left in\n    case tmp0 of\n      None -> Some 0,\n      Some ->\n        // Some tmp0.value // * produces different result!\n        let m = tmp0.value in Some m\n//│ f: 'b -> Some[in 'a out 0 | 'a]\n//│   where\n//│     'b <: Node & {left: 'b}\n\ndef f w =\n  let tmp0 = f w.left in\n  case tmp0 of\n    None -> Some 0,\n    Some ->\n      let m = tmp0.value in Some m\n//│ f: 'b -> Some[in 'a out 0 | 'a]\n//│   where\n//│     'b <: {left: Node & 'b}\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/OccursCheck.mls",
    "content": "\n:OccursCheck\n\n\nrec def f x = (x, x)\n//│ f: 'a -> ('a, 'a,)\n//│  = [Function: f]\n\nrec def f x = f x\n//│ f: anything -> nothing\n//│  = [Function: f1]\n\n:e\nrec def f x = f\n//│ ╔══[ERROR] Inferred recursive type: 'f\n//│   where\n//│     'f :> ? -> 'f\n//│ ╙──\n//│ f: 'f\n//│   where\n//│     'f :> anything -> 'f\n//│  = [Function: f2]\n\n:e\nrec def f x = (f x, f x)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a :> ('a, 'a,)\n//│ ║  l.25: \trec def f x = (f x, f x)\n//│ ╙──      \t               ^^^\n//│ f: anything -> 'a\n//│   where\n//│     'a :> ('a, 'a,)\n//│  = [Function: f3]\n\n:e\nrec def f x = f x.a\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: {a: 'a}\n//│ ║  l.37: \trec def f x = f x.a\n//│ ╙──      \t                ^^^\n//│ f: 'a -> nothing\n//│   where\n//│     'a <: {a: 'a}\n//│  = [Function: f4]\n\n\n// class Foo[A] method Id: A -> A\nclass Foo[A] method Get: A\n//│ Defined class Foo[+A]\n//│ Declared Foo.Get: Foo['A] -> 'A\n\n:e\nrec def foo(x: Foo['a]) = foo(x.Get)\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: Foo['a]\n//│ ║  l.55: \trec def foo(x: Foo['a]) = foo(x.Get)\n//│ ╙──      \t                              ^^^^^\n//│ foo: 'a -> nothing\n//│   where\n//│     'a <: Foo['a]\n//│    = [Function: foo]\n\n\ntype Bar[A] = A\ndef get: Bar['a] -> 'a\n//│ Defined type alias Bar[+A]\n//│ get: Bar['a] -> 'a\n//│    = <missing implementation>\n\n// * Note that this is not truly a recursive type,\n// * since `a <: Bar['a]` is equivalent to `'a <: 'a`!\n// * But our analysis omits expanding type aliases,\n// * for performance and simplicity (sidesteps infinite expansion problems).\n:e\nrec def bar(x: Bar['a]) = bar(get(x))\n//│ ╔══[ERROR] Inferred recursive type: 'a\n//│   where\n//│     'a <: Bar['a]\n//│ ║  l.78: \trec def bar(x: Bar['a]) = bar(get(x))\n//│ ╙──      \t                              ^^^^^^\n//│ bar: 'a -> nothing\n//│   where\n//│     'a <: Bar['a]\n//│    = <no result>\n//│      get is not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Ops.mls",
    "content": "\n:p\n2 + 2\n//│ Parsed: +(2,)(2,);\n//│ Desugared: +(2,)(2,)\n//│ AST: App(App(Var(+),Tup(List((None,Fld(_,IntLit(2)))))),Tup(List((None,Fld(_,IntLit(2))))))\n//│ res: int\n//│    = 4\n\n:p\n1 + 2 * 2 + 3\n//│ Parsed: +(+(1,)(*(2,)(2,),),)(3,);\n//│ Desugared: +(+(1,)(*(2,)(2,),),)(3,)\n//│ AST: App(App(Var(+),Tup(List((None,Fld(_,App(App(Var(+),Tup(List((None,Fld(_,IntLit(1)))))),Tup(List((None,Fld(_,App(App(Var(*),Tup(List((None,Fld(_,IntLit(2)))))),Tup(List((None,Fld(_,IntLit(2)))))))))))))))),Tup(List((None,Fld(_,IntLit(3))))))\n//│ res: int\n//│    = 8\n\n:e\n:p\n1 + 2 / 2 + 3\n//│ Parsed: +(+(1,)(/(2,)(2,),),)(3,);\n//│ Desugared: +(+(1,)(/(2,)(2,),),)(3,)\n//│ AST: App(App(Var(+),Tup(List((None,Fld(_,App(App(Var(+),Tup(List((None,Fld(_,IntLit(1)))))),Tup(List((None,Fld(_,App(App(Var(/),Tup(List((None,Fld(_,IntLit(2)))))),Tup(List((None,Fld(_,IntLit(2)))))))))))))))),Tup(List((None,Fld(_,IntLit(3))))))\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.20: \t1 + 2 / 2 + 3\n//│ ║        \t^^^^^^^^^\n//│ ╟── operator application of type `number` is not an instance of type `int`\n//│ ║  l.20: \t1 + 2 / 2 + 3\n//│ ╙──      \t    ^^^^^\n//│ res: int\n//│    = 5\n\n:e\n:ge\n:p\n1 |> 2 || 3\n//│ Parsed: ||(|>(1,)(2,),)(3,);\n//│ Desugared: ||(|>(1,)(2,),)(3,)\n//│ AST: App(App(Var(||),Tup(List((None,Fld(_,App(App(Var(|>),Tup(List((None,Fld(_,IntLit(1)))))),Tup(List((None,Fld(_,IntLit(2))))))))))),Tup(List((None,Fld(_,IntLit(3))))))\n//│ ╔══[ERROR] identifier not found: |>\n//│ ║  l.36: \t1 |> 2 || 3\n//│ ╙──      \t  ^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.36: \t1 |> 2 || 3\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── integer literal of type `3` is not an instance of type `bool`\n//│ ║  l.36: \t1 |> 2 || 3\n//│ ╙──      \t          ^\n//│ res: bool | error\n//│ Code generation encountered an error:\n//│   unresolved symbol |>\n\n:p\ntrue || false && true || false\n//│ Parsed: ||(||(true,)(&&(false,)(true,),),)(false,);\n//│ Desugared: ||(||(true,)(&&(false,)(true,),),)(false,)\n//│ AST: App(App(Var(||),Tup(List((None,Fld(_,App(App(Var(||),Tup(List((None,Fld(_,Var(true)))))),Tup(List((None,Fld(_,App(App(Var(&&),Tup(List((None,Fld(_,Var(false)))))),Tup(List((None,Fld(_,Var(true)))))))))))))))),Tup(List((None,Fld(_,Var(false))))))\n//│ res: bool\n//│    = true\n\n\n// Infix operators not yet supported:\n\n:pe\n-1\n//│ /!\\ Parse error: Expected end-of-input:1:1, found \"-1;\" at l.65:1: -1\n\n:pe\n- 1\n//│ /!\\ Parse error: Expected end-of-input:1:1, found \"- 1;\" at l.69:1: - 1\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/OtherErrors.mls",
    "content": ":AllowTypeErrors\n\n// Multiline error:\nid\n  id\n  id\n  3 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.4: \tid\n//│ ║       \t^^\n//│ ║  l.5: \t  id\n//│ ║       \t^^^^\n//│ ║  l.6: \t  id\n//│ ║       \t^^^^\n//│ ║  l.7: \t  3 2\n//│ ║       \t^^^^^\n//│ ╟── integer literal of type `3` is not a function\n//│ ║  l.7: \t  3 2\n//│ ║       \t  ^\n//│ ╟── but it flows into application with expected type `2 -> ?a`\n//│ ║  l.4: \tid\n//│ ║       \t^^\n//│ ║  l.5: \t  id\n//│ ║       \t^^^^\n//│ ║  l.6: \t  id\n//│ ║       \t^^^^\n//│ ║  l.7: \t  3 2\n//│ ╙──     \t^^^\n//│ res: error\n\n\n1: 1 & int: { x: int; y: string }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.32: \t1: 1 & int: { x: int; y: string }\n//│ ║        \t^\n//│ ╟── type `1` does not have all required fields 'x', 'y'\n//│ ║  l.32: \t1: 1 & int: { x: int; y: string }\n//│ ║        \t   ^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.32: \t1: 1 & int: { x: int; y: string }\n//│ ╙──      \t            ^^^^^^^^^^^^^^^^^^^^^\n//│ res: {x: int, y: string}\n\n1: 1 & int: { x: int; y: string } | string\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.44: \t1: 1 & int: { x: int; y: string } | string\n//│ ║        \t^\n//│ ╟── type `1` does not match type `string | {x: int, y: string}`\n//│ ║  l.44: \t1: 1 & int: { x: int; y: string } | string\n//│ ║        \t   ^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.44: \t1: 1 & int: { x: int; y: string } | string\n//│ ╙──      \t            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: string | {x: int, y: string}\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Paper.mls",
    "content": "\nclass None: {}\nclass Some[A]: { value: A }\ntype Option[A] = Some[A] | None\n//│ Defined class None\n//│ Defined class Some[+A]\n//│ Defined type alias Option[+A]\n\n\ndef flatMap f opt = case opt of\n  Some -> f opt.value,\n  None -> None{}\n//│ flatMap: ('value -> 'a) -> (None | Some[?] & {value: 'value}) -> (None | 'a)\n//│        = [Function: flatMap]\n\nres = flatMap (fun x -> x) (Some{value = 42})\n//│ res: 42 | None\n//│    = 42\n\ncase res of int -> res, None -> 0\n//│ res: 0 | 42\n//│    = 42\n\nflatMap (fun x -> None{}) (Some{value = 42})\n//│ res: None\n//│    = None {}\n\n\ndef flatMap2 f opt = case opt of Some -> f opt.value, _ -> opt\n//│ flatMap2: ('value -> 'a) -> (Some[?] & {value: 'value} | 'a & ~#Some) -> 'a\n//│         = [Function: flatMap2]\n\nflatMap2 (fun x -> Some{value = x}) (Some{value = 12})\n//│ res: Some[12]\n//│    = Some { value: 12 }\n\nflatMap2 (fun x -> Some{value = x}) 42\n//│ res: 42 | Some[nothing]\n//│    = 42\n\nflatMap2 (fun x -> x) 42\n//│ res: 42\n//│    = 42\n\n\ndef mapSome f opt = case opt of Some -> f opt, _ -> opt\n//│ mapSome: ('a -> 'b) -> (Some[?] & 'a | 'b & ~#Some) -> 'b\n//│        = [Function: mapSome]\n\n\nclass SomeAnd[A, P]: Some[A] & { payload: P }\n//│ Defined class SomeAnd[+A, +P]\n\nlet arg = if true then SomeAnd{value = 42; payload = 23} else None{}\n  in mapSome (fun x -> x.value + x.payload) arg\n//│ res: None | int\n//│    = 65\n\n\n// * Note: there was a typo in the original paper submission: we used `(m: ~0)` instead of `(m: ~0 & int)`\ndef div n m = n / (m: ~0 & number)\n//│ div: number -> (number & ~0) -> number\n//│    = [Function: div]\n\nf x = div x 2\n//│ f: number -> number\n//│  = [Function: f]\n\n:e // `:e` is used to indicate this error is expected\ng (x: int) = div 100 x\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.70: \tg (x: int) = div 100 x\n//│ ║        \t             ^^^^^^^^^\n//│ ╟── type `int` does not match type `~0`\n//│ ║  l.70: \tg (x: int) = div 100 x\n//│ ║        \t      ^^^\n//│ ╟── but it flows into reference with expected type `~0`\n//│ ║  l.70: \tg (x: int) = div 100 x\n//│ ║        \t                     ^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.61: \tdef div n m = n / (m: ~0 & number)\n//│ ║        \t                      ^^\n//│ ╟── from reference:\n//│ ║  l.61: \tdef div n m = n / (m: ~0 & number)\n//│ ╙──      \t                   ^\n//│ g: int -> (error | number)\n//│  = [Function: g]\n\ndiv_opt n m = case m of 0 -> None{}, _ -> Some{value = div n m}\n//│ div_opt: number -> (0 | number & ~0) -> (None | Some[number])\n//│        = [Function: div_opt]\n\n\n\ndef capitalize: string -> string\n//│ capitalize: string -> string\n//│           = <missing implementation>\n\nclass Person: {name: string; age: int; isMajor: bool}\n//│ Defined class Person\n\ndef Person n a = Person{name = capitalize n; age = a; isMajor = a >= 18}\n//│ Person: string -> (int & 'age) -> (Person with {age: 'age})\n//│       = <no result>\n//│         capitalize is not implemented\n\n\n\nclass Cons[A]: Some[A] & { tail: List[A] }\ntype List[A] = Cons[A] | None\n//│ Defined class Cons[+A]\n//│ Defined type alias List[+A]\n\nrec def mapList f ls = case ls of\n  Cons -> Cons{value = f ls.value; tail = mapList f ls.tail},\n  None -> None{}\n//│ mapList: ('value -> 'value0) -> 'a -> (None | 'b)\n//│   where\n//│     'b :> Cons['value0] with {tail: None | 'b}\n//│     'a <: (Cons[?] with {tail: 'a, value: 'value}) | None\n//│        = [Function: mapList]\n\n\n\ndef Cons head tail = Cons { value = head; tail = tail }\n//│ Cons: ('value & 'A) -> (List['A] & 'tail) -> (Cons['A] with {tail: 'tail, value: 'value})\n//│     = [Function: Cons1]\n\ndef None = None{}\n//│ None: None\n//│     = [Function: None1]\n\nrec def unzip xs = case xs of\n  None -> { fst = None; snd = None },\n  Some -> let tmp = unzip xs.tail in { fst = Cons xs.value.fst tmp.fst ;\n                                       snd = Cons xs.value.snd tmp.snd }\n//│ unzip: 'a -> {fst: None | 'b, snd: None | 'c}\n//│   where\n//│     'c :> Cons['value] with {tail: None | 'c}\n//│     'b :> Cons['value0] with {tail: None | 'b}\n//│     'a <: None | Some[?] & {tail: 'a, value: {fst: 'value0, snd: 'value}}\n//│      = [Function: unzip]\n\n// * Declare desired types:\ndef Cons_ty: 'a -> ('b & List['a]) -> (Cons['a] & { value: 'a; tail: 'b })\ndef unzip_ty: List[{ fst: 'a; snd: 'b }] -> { fst: List['a]; snd: List['b] }\n//│ Cons_ty: 'a -> (List['a] & 'b) -> (Cons['a] with {tail: 'b})\n//│        = <missing implementation>\n//│ unzip_ty: List[{fst: 'a, snd: 'b}] -> {fst: List['a], snd: List['b]}\n//│         = <missing implementation>\n\n// * Assert the inferred types subsume them (the signatures above are checked):\ndef Cons_ty = Cons\ndef unzip_ty = unzip\n//│ ('value & 'A) -> (List['A] & 'tail) -> (Cons['A] with {tail: 'tail, value: 'value})\n//│   <:  Cons_ty:\n//│ 'a -> (List['a] & 'b) -> (Cons['a] with {tail: 'b})\n//│        = [Function: Cons_ty]\n//│ 'a -> {fst: None | 'b, snd: None | 'c}\n//│   where\n//│     'c :> Cons['value] with {tail: None | 'c}\n//│     'b :> Cons['value0] with {tail: None | 'b}\n//│     'a <: None | Some[?] & {tail: 'a, value: {fst: 'value0, snd: 'value}}\n//│   <:  unzip_ty:\n//│ List[{fst: 'a, snd: 'b}] -> {fst: List['a], snd: List['b]}\n//│         = [Function: unzip_ty]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/PolyVariant.mls",
    "content": "// Examples from Set-Theoretic Types for Polymorphic Variants\n\n//************** PRELIMINARIES *************\n\nclass Nil\nclass Cons[A]: { head: A; tail: List[A] }\ntype List[A] = Nil | Cons[A]\n//│ Defined class Nil\n//│ Defined class Cons[+A]\n//│ Defined type alias List[+A]\n\ndef Nil = Nil {}\n//│ Nil: Nil\n//│    = [Function: Nil1]\n\ndef Cons head tail = Cons { head; tail }\n//│ Cons: ('head & 'A) -> (List['A] & 'tail) -> (Cons['A] with {head: 'head, tail: 'tail})\n//│     = [Function: Cons1]\n\nclass A\nclass B\nclass C\nclass D\n//│ Defined class A\n//│ Defined class B\n//│ Defined class C\n//│ Defined class D\n\n//************** EXAMPLE 1: LOSS OF POLYMORPHISM *************\n\ndef id x = x\n//│ id: 'a -> 'a\n//│   = [Function: id]\n\n\nid A{}\n//│ res: A\n//│    = A {}\n\ndef f x = case x of { A -> true }\n//│ f: A -> true\n//│  = [Function: f]\n\nf (id A{})\n//│ res: true\n//│    = true\n\n// # [`A; `C]\n// - : [> `A | `C] list\n// # [id `A; `C]\n// - : [> `A | `C] list\n\nCons (A{}) (Cons (C{}) Nil)\n//│ res: Cons[A | C] with {head: A, tail: Cons[C] with {tail: Nil}}\n//│    = Cons { head: A {}, tail: Cons { head: C {}, tail: Nil {} } }\n\nCons (id A{}) (Cons (C{}) Nil)\n//│ res: Cons[A | C] with {head: A, tail: Cons[C] with {tail: Nil}}\n//│    = Cons { head: A {}, tail: Cons { head: C {}, tail: Nil {} } }\n\n// val id2 : ([< `A | `B ] as 'a) -> 'a = <fun>\n\ndef id2 x = case x of { A -> x | B -> x }\n//│ id2: ('a & (A | B)) -> 'a\n//│    = [Function: id2]\n\n// id2 `A\n// - : [< `A | `B > `A ] = `A\n\nid2 (A{})\n//│ res: A\n//│    = A {}\n\n// # [(id2 `A); `C];;\n// Error: This expression has type [> `C ] but an expression was expected of\n// type [< `A | `B > `A ]. The second variant type does not allow tag(s) `C\n\nCons (id2 (A{})) (Cons (C{}) Nil)\n//│ res: Cons[A | C] with {head: A, tail: Cons[C] with {tail: Nil}}\n//│    = Cons { head: A {}, tail: Cons { head: C {}, tail: Nil {} } }\n\n//************** EXAMPLE 2: ROUGHLY-TYPED PATTERN MATCHING *************\n\n// val f : [ `A | `B ] -> [ `A | `B ] = <fun>\n\ndef f x = let xx = id2 x in case xx of { A -> B{} | _ -> xx }\n//│ f: (A | B) -> B\n//│  = [Function: f1]\n\n// val g : ([< `A | `B > `A ] as 'a) -> 'a = <fun>\n\n// Actually ~A !!\ndef g x = case x of { A -> id2 x | _ -> x }\n//│ g: ('a & (A | ~#A)) -> 'a\n//│  = [Function: g]\n\ng (C{})\n//│ res: C\n//│    = C {}\n\n// val map : ('a -> 'a) -> 'a list -> 'a list = <fun>\n\nrec def map f l = case l of {\n  | Nil -> l\n  | Cons -> Cons (f l.head) (map f l.tail)\n  }\n//│ map: ('head -> ('head0 & 'A)) -> 'a -> 'b\n//│   where\n//│     'a <: (Cons[?] with {head: 'head, tail: 'a}) | Nil & List['A] & 'b\n//│     'b :> Cons['A] with {head: 'head0, tail: 'b}\n//│    = [Function: map]\n\nmap (fun x -> \"lol\") (Cons 2 (Cons 3 Nil))\n//│ res: Nil | 'a\n//│   where\n//│     'a :> Cons[\"lol\"] with {tail: Nil | 'a}\n//│    = Cons { head: 'lol', tail: Cons { head: 'lol', tail: Nil {} } }\n\n//************** EXAMPLE 3: ROUGH APPROXIMATIONS *************\n\n// let f x = match x with\n//  | (`A, _) -> 1 | (`B, _) -> 2\n//  | (_, `A) -> 3 | (_, `B) -> 4\n// Warning 8 [partial-match]: this pattern-matching is not exhaustive.\n// Here is an example of a case that is not matched:\n// (`AnyOtherTag, `AnyOtherTag)\n// val f : [> `A | `B ] * [> `A | `B ] -> int = <fun>\n\n// Inferred type is not good enough\ndef f = fun x -> case x._1 of {\n  | A -> 1\n  | B -> 2\n  | _ -> case x._2 of {\n    | A -> 3\n    | B -> 4\n    }\n  }\n//│ f: {_1: anything, _2: A | B} -> (1 | 2 | 3 | 4)\n//│  = [Function: f2]\n\n:e\nf ({ _1 = A{}; _2 = C{} })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.142: \tf ({ _1 = A{}; _2 = C{} })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `C` does not match type `A | B`\n//│ ║  l.142: \tf ({ _1 = A{}; _2 = C{} })\n//│ ║         \t                    ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.133: \t  | _ -> case x._2 of {\n//│ ║         \t              ^^^^\n//│ ╟── Note: class C is defined at:\n//│ ║  l.22: \tclass C\n//│ ╙──      \t      ^\n//│ res: 1 | 2 | 3 | 4 | error\n//│    = 1\n\n// x actually has equivalent type {_1: anything; _2: anything}\n\ndef t1: {_1: A | B; _2: anything} | {_1: anything; _2: A | B}\n//│ t1: {_1: anything, _2: anything}\n//│   = <missing implementation>\n\n:e\ndef f = fun (x: {_1: A | B; _2: anything} | {_1: anything; _2: A | B}) -> case x._1 of {\n  | A -> 1\n  | B -> 2\n  | _ -> case x._2 of {\n    | A -> 3\n    | B -> 4\n    }\n  }\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.168: \t  | _ -> case x._2 of {\n//│ ║         \t         ^^^^^^^^^^^^^^\n//│ ║  l.169: \t    | A -> 3\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.170: \t    | B -> 4\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.171: \t    }\n//│ ║         \t^^^^^\n//│ ╟── type `anything` does not match type `A | B`\n//│ ║  l.165: \tdef f = fun (x: {_1: A | B; _2: anything} | {_1: anything; _2: A | B}) -> case x._1 of {\n//│ ║         \t                                ^^^^^^^^\n//│ ╟── but it flows into field selection with expected type `A | B`\n//│ ║  l.168: \t  | _ -> case x._2 of {\n//│ ╙──       \t              ^^^^\n//│ f: {_1: anything, _2: anything} -> (1 | 2 | 3 | 4)\n//│  = [Function: f3]\n\n// not useful\nclass Tuple[a, b]: { _1: a; _2: b }\n//│ Defined class Tuple[+a, +b]\n\ndef t2: Tuple[A | B, anything] | Tuple[anything, A | B] \n//│ t2: in Tuple[A | B, A | B] out Tuple[?, ?]\n//│   = <missing implementation>\ndef t3: Tuple[anything, anything]\n//│ t3: Tuple[?, ?]\n//│   = <missing implementation>\n\nt3 = t2\nt2 = t3\n//│ Tuple[?, ?]\n//│   <:  t3:\n//│ Tuple[?, ?]\n//│   = <no result>\n//│     t2 is not implemented\n//│ Tuple[?, ?]\n//│   <:  t2:\n//│ Tuple[A | B, A | B]\n//│   = <no result>\n//│     t3 and t2 are not implemented\n\nclass L: { _1: A | B; _2: anything }\nclass R: { _1: anything; _2: A | B }\n//│ Defined class L\n//│ Defined class R\n\n:e\ndef f = fun (x: L | R) -> case x._1 of {\n  | A -> 1\n  | B -> 2\n  | _ -> case x._2 of {\n    | A -> 3\n    | B -> 4\n    }\n  }\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.224: \t  | _ -> case x._2 of {\n//│ ║         \t         ^^^^^^^^^^^^^^\n//│ ║  l.225: \t    | A -> 3\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.226: \t    | B -> 4\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.227: \t    }\n//│ ║         \t^^^^^\n//│ ╟── field selection of type `anything` does not match type `A | B`\n//│ ║  l.224: \t  | _ -> case x._2 of {\n//│ ╙──       \t              ^^^^\n//│ f: (L | R) -> (1 | 2 | 3 | 4)\n//│  = [Function: f4]\n\nf (L { _1 = A{}; _2 = C{} })\n//│ res: 1 | 2 | 3 | 4\n//│    = 1\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/PolyVariantCodeReuse.mls",
    "content": "// Example from Code reuse through polymorphic variants\n\n\n// * Bad things currently happen without these:\n// * TODO: investigate why\n:DontDistributeForalls\n:DontGeneralizeCurriedFunctions\n\n// * This makes inferred types slightly simpler by approximating constraints like\n// * `'a <: (S -> T) & (U -> V)` to `'a <: (S | U) -> (T & V)`.\n:ApproximateNegativeFunction\n\n\n//************************** PRELIMINARIES *************************\n\nclass NotFound\nclass Success: { result: anything }\n//│ Defined class NotFound\n//│ Defined class Success\n\ndef NotFound = NotFound {}\ndef Success result = Success { result }\n//│ NotFound: NotFound\n//│         = [Function: NotFound1]\n//│ Success: 'result -> (Success with {result: 'result})\n//│        = [Function: Success1]\n\ntype Tuple[A, B] = (A, B)\n//│ Defined type alias Tuple[+A, +B]\n\ndef Tuple l r = (l, r)\n//│ Tuple: 'a -> 'b -> ('a, 'b,)\n//│      = [Function: Tuple]\n\nclass Nil\nclass Cons[A]: { head: A; tail: List[A] }\ntype List[A] = Nil | Cons[A]\n//│ Defined class Nil\n//│ Defined class Cons[+A]\n//│ Defined type alias List[+A]\n\ndef Nil = Nil {}\n//│ Nil: Nil\n//│    = [Function: Nil1]\n\ndef Cons head tail = Cons { head; tail }\n//│ Cons: ('head & 'A) -> (List['A] & 'tail) -> (Cons['A] with {head: 'head, tail: 'tail})\n//│     = [Function: Cons1]\n\ndef eq: string -> string -> bool\n//│ eq: string -> string -> bool\n//│   = <missing implementation>\n\nrec def list_assoc s l = case l of {\n  | Cons ->\n      if eq l.head.0 s then Success l.head.1\n      else list_assoc s l.tail\n  | Nil -> NotFound\n  }\n//│ list_assoc: string -> 'a -> (NotFound | (Success with {result: 'result}))\n//│   where\n//│     'a <: (Cons[?] with {head: {0: string, 1: 'result}, tail: 'a}) | Nil\n//│           = <no result>\n//│             eq is not implemented\n\nlist_assoc \"2\" (Cons (Tuple \"2\" 1) Nil )\n//│ res: NotFound | Success & {result: 1}\n//│    = <no result>\n//│      list_assoc and eq are not implemented\n\n// ***************************** Var *******************************\n\nclass Expr\nclass Lambda\n//│ Defined class Expr\n//│ Defined class Lambda\n\nclass Var: Lambda & { name: string }\n//│ Defined class Var\n\ndef eval_var sub v = case v of {\n  | Var -> let res = list_assoc v.name sub in case res of {\n          | NotFound -> v\n          | Success -> res.result\n          }\n  }\n//│ eval_var: (Cons[?] & 'a | Nil) -> (Var & 'result) -> 'result\n//│   where\n//│     'a <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'a | Nil}\n//│         = <no result>\n//│           list_assoc and eq are not implemented\n\n// *************************** Lambda ********************************\n\nclass Abs[a]: Lambda & { name: string; body: a }\nclass App[a]: Lambda & { lhs: a; rhs: a }\n//│ Defined class Abs[+a]\n//│ Defined class App[+a]\n\n:js\ndef incr: {a: int} -> unit\n// def incr x = x.a <- x.a + 1\n//│ // Query 1 is empty\n//│ // End of generated code\n//│ incr: {a: int} -> unit\n//│     = <missing implementation>\n\n:js\ndef gensym: () -> (unit, {a: 'a},)\n// def gensym = let n = { mut a = 0 } in fun () -> (incr n, n)\n//│ // Query 1 is empty\n//│ // End of generated code\n//│ gensym: () -> (unit, {a: nothing},)\n//│       = <missing implementation>\n\ndef int_to_string: int -> string\n//│ int_to_string: int -> string\n//│              = <missing implementation>\n\ndef eval_lambda eval_rec subst v = case v of {\n  | Var -> eval_var subst v\n  | App -> let l2 = eval_rec subst v.lhs in\n    let l1 = eval_rec subst v.rhs in\n    case l1 of {\n    | Abs -> eval_rec (Cons (Tuple l1.name l2) Nil) l1.body\n    | _ -> App { lhs = l1; rhs = l2 }\n    }\n  | Abs -> let new_name = int_to_string ((gensym ()).1.a) in\n    Abs { name = new_name;\n          body = eval_rec (Cons (Tuple v.name (Var { name = new_name })) subst) v.body }\n  }\n//│ eval_lambda: (((Cons[('a, Var | 'body,) | 'A] with {head: ('a, Var | 'body,), tail: Nil | 'tail}) | 'tail) -> 'lhs -> ('result & 'body & ((Abs[?] with {body: 'lhs, name: 'a}) | 'lhs0 & ~#Abs))) -> ((Cons[?] & List['A] & 'b | Nil & List['A]) & 'tail) -> ((Abs[?] with {body: 'lhs, name: 'a}) | App[?] & {lhs: 'lhs, rhs: 'lhs} | Var & 'result) -> (Abs['body] | (App['body | 'lhs0] with {lhs: 'lhs0, rhs: 'body}) | 'result)\n//│   where\n//│     'b <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'b | Nil}\n//│            = <no result>\n//│              eval_var, list_assoc and eq are not implemented\n\nrec def eval1 subst = eval_lambda eval1 subst\n//│ eval1: ('tail & (Cons[?] & List[?] & 'b | Nil & List[?])) -> 'c -> 'd\n//│   where\n//│     'tail <: Cons[?] & 'b | Nil\n//│     'b <: {head: {0: string, 1: 'result}, tail: 'tail}\n//│     'result :> 'd\n//│             <: Abs[?] & 'e & 'f | 'lhs & (Abs[?] & 'f & ~#Abs | App[?] & 'g | Var & 'h)\n//│     'd :> Abs['d] | App['a]\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | 'i | 'result\n//│     'a :> App['a]\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | 'd\n//│     'lhs :> App['a]\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Var\n//│          <: 'a & 'c\n//│     'c <: Abs[?] & 'f | App[?] & 'g | Var & 'h\n//│     'h <: Var & 'i\n//│     'i :> Var\n//│        <: Abs[?] & 'e & 'f | 'lhs & (Abs[?] & 'f & ~#Abs | App[?] & {name: string} & 'g | Var & 'h)\n//│     'e <: {body: 'c, name: string}\n//│     'g <: {lhs: 'c, rhs: 'c}\n//│     'f <: {body: 'c, name: string}\n//│     'rhs :> 'd\n//│      = <no result>\n//│        eval_lambda, eval_var, list_assoc and eq are not implemented\n\n// ------------- OCaml's type -------------\n// val eval_lambda :\n//   ((string *\n//     ([> `Abs of string * 'a | `App of 'a * 'a | `Var of string ] as 'a))\n//   list -> 'a -> 'a) ->\n//   (string * 'a) list ->\n//   [< `Abs of string * 'a | `App of 'a * 'a | `Var of string ] -> 'a = <fun>\n//\n//   val eval1 :\n//   (string * ([ `Abs of string * 'a | `App of 'a * 'a | `Var of string ] as 'a))\n//   list -> 'a -> 'a = <fun>\n\n// ************************* Expr ******************************\n\nclass Numb: Expr & { num: int }\nclass Add[a]: Expr & { lhs: a; rhs: a }\nclass Mul[a]: Expr & { lhs: a; rhs: a }\n//│ Defined class Numb\n//│ Defined class Add[+a]\n//│ Defined class Mul[+a]\n\ndef map_expr f v = case v of {\n  | Var -> v\n  | Numb -> v\n  | Add -> Add { lhs = f v.lhs; rhs = f v.rhs }\n  | Mul -> Mul { lhs = f v.lhs; rhs = f v.rhs }\n  }\n//│ map_expr: ('lhs -> 'lhs0) -> (Add[?] & {lhs: 'lhs, rhs: 'lhs} | Mul[?] & {lhs: 'lhs, rhs: 'lhs} | 'a & (Numb | Var)) -> (Add['lhs0] | Mul['lhs0] | 'a)\n//│         = [Function: map_expr]\n\nrec def eval_expr eval_rec subst v =\n  let vv = map_expr (eval_rec subst) v in\n  case vv of {\n    | Var -> eval_var subst vv\n    | Add -> let vv1 = vv.lhs in\n              let vv2 = vv.rhs in\n              case vv1 of {\n              | Numb -> case vv2 of {\n                | Numb -> Numb { num = vv1.num + vv2.num }\n                | _ -> vv\n                }\n              | _ -> vv\n              }\n    | Mul -> let vv1 = vv.lhs in\n              let vv2 = vv.rhs in\n              case vv1 of {\n              | Numb -> case vv2 of {\n                | Numb -> Numb { num = vv1.num * vv2.num }\n                | _ -> vv\n                }\n              | _ -> vv\n              }\n    | Numb -> vv // _ -> vv\n    }\n//│ eval_expr: ('a -> 'rhs -> 'rhs0) -> ('a & (Cons[?] & 'b | Nil)) -> (Add[?] & {lhs: 'rhs, rhs: 'rhs} | Mul[?] & {lhs: 'rhs, rhs: 'rhs} | Numb & 'result | Var & 'result) -> (Add['rhs0] | Mul['rhs0] | Numb | 'result)\n//│   where\n//│     'b <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'b | Nil}\n//│          = <no result>\n//│            eval_var, list_assoc and eq are not implemented\n\nrec def eval2 subst = eval_expr eval2 subst\n//│ eval2: (Cons[?] & 'a | Nil) -> 'b -> (Numb | 'result)\n//│   where\n//│     'b <: Add[?] & {lhs: 'b, rhs: 'b} | Mul[?] & {lhs: 'b, rhs: 'b} | Numb & 'result | Var & 'result\n//│     'a <: {head: {0: string, 1: 'result & (Numb | ~#Numb)}, tail: Cons[?] & 'a | Nil}\n//│     'result :> Mul[Numb | 'result] | Add[Numb | 'result]\n//│      = <no result>\n//│        eval_expr, eval_var, list_assoc and eq are not implemented\n\n\n// ------------- OCaml's type -------------\n// val map_expr :\n//   ('a -> 'b) ->\n//   [< `Add of 'a * 'a | `Mult of 'a * 'a | `Numb of 'c | `Var of string ] ->\n//   [> `Add of 'b * 'b | `Mult of 'b * 'b | `Numb of 'c | `Var of string ] = <fun>\n\n// val eval_expr :\n//   ((string *\n//     ([> `Add of ([> `Numb of int ] as 'b) * 'b\n//       | `Mult of 'b * 'b\n//       | `Numb of int\n//       | `Var of string ]\n//      as 'a))\n//    list -> 'c -> 'b) ->\n//   (string * 'a) list ->\n//   [< `Add of 'c * 'c | `Mult of 'c * 'c | `Numb of int | `Var of string ] -> 'a =\n//   <fun>\n// val eval2 :\n//   (string *\n//    ([> `Add of 'a * 'a | `Mult of 'a * 'a | `Numb of int | `Var of string ]\n//     as 'a))\n//   list ->\n//   ([< `Add of 'b * 'b | `Mult of 'b * 'b | `Numb of int | `Var of string ] as 'b) ->\n//   'a = <fun>\n\n\n// ************************** Mix things *******************************\n\ndef eval_lexpr eval_rec subst v = case v of {\n  | Lambda -> eval_lambda eval_rec subst v\n  | Expr -> eval_expr eval_rec subst v\n  }\n//│ eval_lexpr: ((Cons[('a, Var | 'body,) | 'A]\\head\\tail & {head: ('a, Var | 'body,), tail: Nil | 'tail} | 'tail) -> 'lhs -> ('result & 'body & (Abs[?]\\body\\name & {body: 'lhs, name: 'a} | 'lhs0 & ~#Abs))) -> ((Cons[?] & List['A] & 'b & 'c | Nil & List['A]) & 'tail) -> (Abs[?]\\body\\name & {body: 'lhs, name: 'a} | Add[?] & {lhs: 'lhs, rhs: 'lhs} | App[?] & {lhs: 'lhs, rhs: 'lhs} | Mul[?] & {lhs: 'lhs, rhs: 'lhs} | Numb & 'result | Var & 'result) -> (Abs['body] | Add['body] | App['body | 'lhs0]\\lhs\\rhs & {lhs: 'lhs0, rhs: 'body} | Mul['body] | Numb | 'result)\n//│   where\n//│     'c <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'c | Nil}\n//│     'b <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'b | Nil}\n//│           = <no result>\n//│             eval_lambda, eval_var, list_assoc and eq are not implemented\n\nrec def eval3 subst = eval_lexpr eval3 subst\n//│ eval3: ('tail & 'tail0 & (Cons[?] & List[?] & 'b & 'c | Nil & List[?])) -> 'd -> 'e\n//│   where\n//│     'tail0 <: Cons[?] & 'c | Nil\n//│     'c <: {head: {0: string, 1: 'result}, tail: 'tail0}\n//│     'tail <: Cons[?] & 'b | Nil\n//│     'b <: {head: {0: string, 1: 'result}, tail: 'tail}\n//│     'result :> Numb | Var | 'e\n//│             <: Abs[?] & 'f & 'g | 'lhs & (Lambda & 'f & ~#Abs | 'h & (Expr & ~#Numb | Numb))\n//│     'e :> Abs['e] | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | Numb | 'result | (Add['e] with {lhs: 'e, rhs: 'e}) | (Mul['e] with {lhs: 'e, rhs: 'e}) | 'i\n//│     'a :> (Add['e] with {lhs: 'e, rhs: 'e}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['e] with {lhs: 'e, rhs: 'e}) | Numb | 'e\n//│     'lhs :> (Add['e] with {lhs: 'e, rhs: 'e}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['e] with {lhs: 'e, rhs: 'e}) | Numb | Var\n//│          <: 'd & 'a\n//│     'd <: Expr & 'h | Lambda & 'f\n//│     'h <: Add[?] & {lhs: 'd, rhs: 'd} | Mul[?] & {lhs: 'd, rhs: 'd} | Numb & 'result | Var & 'f & 'lhs\n//│     'f <: Abs[?] & {body: 'd} | App[?] & {lhs: 'd, rhs: 'd} | Var & 'i\n//│     'i :> Var\n//│        <: Abs[?] & 'f & 'g | 'lhs & (Lambda & {name: string} & 'f & ~#Abs | 'h & (Expr & {name: string} & ~#Numb | Numb & {name: string}))\n//│     'g <: {body: 'd, name: string}\n//│     'rhs :> 'e\n//│      = <no result>\n//│        eval_lexpr, eval_lambda, eval_var, list_assoc and eq are not implemented\n\n// ------------- OCaml's type -------------\n// val eval_lexpr :\n//   ((string *\n//     ([> `Abs of string * 'a\n//       | `Add of 'a * 'a\n//       | `App of 'a * 'a\n//       | `Mult of 'a * 'a\n//       | `Numb of int\n//       | `Var of string ]\n//      as 'a))\n//    list -> 'a -> 'a) ->\n//   (string * 'a) list ->\n//   [< `Abs of string * 'a\n//    | `Add of 'a * 'a\n//    | `App of 'a * 'a\n//    | `Mult of 'a * 'a\n//    | `Numb of int\n//    | `Var of string ] ->\n//   'a = <fun>\n//\n// val eval3 :\n//   (string *\n//    ([ `Abs of string * 'a\n//     | `Add of 'a * 'a\n//     | `App of 'a * 'a\n//     | `Mult of 'a * 'a\n//     | `Numb of int\n//     | `Var of string ] as 'a))\n//   list -> 'a -> 'a = <fun>\n\n// ************************** Tests *******************************\n\neval3 Nil (Var { name = \"s\" })\n//│ res: 'b\n//│   where\n//│     'b :> Abs['b] | (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'a :> 'lhs | 'b\n//│     'lhs :> (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'rhs :> 'b\n//│    = <no result>\n//│      eval3, eval_lexpr, eval_lambda, eval_var, list_assoc and eq are not implemented\n// ------------- OCaml's type -------------\n// - : [ `Abs of string * 'a\n//     | `Add of 'a * 'a\n//     | `App of 'a * 'a\n//     | `Mult of 'a * 'a\n//     | `Numb of int\n//     | `Var of string ] as 'a\n// = `Var \"s\"\n\n\neval3 Nil (Abs { name = \"s\"; body = Var { name = \"s\" } })\n//│ res: 'b\n//│   where\n//│     'b :> Abs['b] | (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'a :> 'lhs | 'b\n//│     'lhs :> (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'rhs :> 'b\n//│    = <no result>\n//│      eval3, eval_lexpr, eval_lambda, eval_var, list_assoc and eq are not implemented\n\neval2 Nil (Numb { num = 1 })\n//│ res: Numb | 'a\n//│   where\n//│     'a :> Add[Numb | 'a] | Mul[Numb | 'a]\n//│    = <no result>\n//│      eval2, eval_expr, eval_var, list_assoc and eq are not implemented\n\neval3 Nil (Numb { num = 1 })\n//│ res: 'b\n//│   where\n//│     'b :> Abs['b] | (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'a :> 'lhs | 'b\n//│     'lhs :> (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'rhs :> 'b\n//│    = <no result>\n//│      eval3, eval_lexpr, eval_lambda, eval_var, list_assoc and eq are not implemented\n\neval3 Nil (App { lhs = Numb {num = 0}; rhs = Numb {num = 0}})\n//│ res: 'b\n//│   where\n//│     'b :> Abs['b] | (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'a :> 'lhs | 'b\n//│     'lhs :> (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'rhs :> 'b\n//│    = <no result>\n//│      eval3, eval_lexpr, eval_lambda, eval_var, list_assoc and eq are not implemented\n\neval3 Nil (Abs { name = \"s\"; body = Add { lhs = Var { name = \"s\" }; rhs = Numb { num = 1 } } })\n//│ res: 'b\n//│   where\n//│     'b :> Abs['b] | (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'a :> 'lhs | 'b\n//│     'lhs :> (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'rhs :> 'b\n//│    = <no result>\n//│      eval3, eval_lexpr, eval_lambda, eval_var, list_assoc and eq are not implemented\n\n\n// *************************************\n\n// * Note: the type size explodes and the test times out if we incorrectly call\n// * `eval_var eval_rec subst v` instead of `eval_var subst v`.\n// * This is a problem, and we should find a way to make it less so.\n\ndef eval_lexpr' eval_rec subst v = case v of {\n  | Var -> eval_var subst v\n  | Abs -> eval_lambda eval_rec subst v\n  | App -> eval_lambda eval_rec subst v\n  | Numb -> eval_expr eval_rec subst v\n  | Add -> eval_expr eval_rec subst v\n  | Mul -> eval_expr eval_rec subst v\n  }\n//│ eval_lexpr': ((Cons[('b, Var | 'body,) | 'A]\\head\\tail & {head: ('b, Var | 'body,), tail: Nil | 'tail} | 'tail) -> 'body0 -> ('result & 'body & (Abs[?]\\body\\name & {body: 'body0, name: 'b} | 'lhs & 'a & (Abs[?]\\body\\name & {body: 'body0, name: 'b} & ~#Abs | 'lhs & 'a & ~#Abs)))) -> ((Cons[?] & List['A] & 'c & 'd & 'e & 'f & 'g | Nil & List['A]) & 'tail & (Cons[?] & 'h | Nil)) -> (Abs[?]\\body\\name & {body: 'body0, name: 'b} | Add[?] & {lhs: 'body0, rhs: 'body0} | App[?] & {lhs: 'body0, rhs: 'body0} | Mul[?] & {lhs: 'body0, rhs: 'body0} | Numb & 'result | Var & 'result) -> (Abs['body] | Add['body] | App['body | 'a]\\lhs\\rhs & {lhs: 'lhs, rhs: 'body} | Mul['body] | Numb | 'result)\n//│   where\n//│     'h <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'h | Nil}\n//│     'g <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'g | Nil}\n//│     'f <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'f | Nil}\n//│     'e <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'e | Nil}\n//│     'd <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'd | Nil}\n//│     'c <: {head: {0: string, 1: 'result}, tail: Cons[?] & 'c | Nil}\n//│            = <no result>\n//│              eval_var, list_assoc and eq are not implemented\n\n:e\nrec def eval4 subst = eval_lexpr' eval4 subst\n//│ ╔══[ERROR] Subtyping constraint of the form `?a -> ?b <: ?eval4` took too many steps and ran out of fuel (10000)\n//│ ║  l.417: \trec def eval4 subst = eval_lexpr' eval4 subst\n//│ ║         \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ eval4: ('tail & 'tail0 & 'tail1 & 'tail2 & 'tail3 & 'tail4 & (Cons[?] & List[?] & 'b & 'c & 'd & 'e & 'f & 'g | Nil & List[?])) -> 'h -> 'i\n//│   where\n//│     'tail4 <: Cons[?] & 'g | Nil\n//│     'g <: {head: {0: string, 1: 'result}, tail: 'tail4}\n//│     'tail3 <: Cons[?] & 'f | Nil\n//│     'f <: {head: {0: string, 1: 'result0}, tail: 'tail3}\n//│     'tail2 <: Cons[?] & 'e | Nil\n//│     'e <: {head: {0: string, 1: 'result0}, tail: 'tail2}\n//│     'tail1 <: Cons[?] & 'd | Nil\n//│     'd <: {head: {0: string, 1: 'result0}, tail: 'tail1}\n//│     'tail0 <: Cons[?] & 'c | Nil\n//│     'c <: {head: {0: string, 1: 'result}, tail: 'tail0}\n//│     'tail <: Cons[?] & 'b | Nil\n//│     'b <: {head: {0: string, 1: 'result}, tail: 'tail}\n//│     'result :> 'i\n//│             <: Abs[?] & 'j & 'k | 'lhs & (Abs[?] & 'k & ~#Abs | Add[?] & 'l | App[?] & 'm | Mul[?] & 'n | Numb & 'o | Var & 'p)\n//│     'i :> Abs['i] | App['a]\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Numb | 'result0 | Add['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | Mul['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | 'q | 'result\n//│     'a :> Add['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | App['a]\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Mul['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | Numb | 'i\n//│     'lhs :> Add['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | App['a]\\lhs\\rhs & {lhs: 'lhs, rhs: 'rhs} | Mul['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | Numb | Var\n//│          <: 'h & 'a\n//│     'h <: Abs[?] & 'k | Add[?] & 'l | App[?] & 'm | Mul[?] & 'n | Numb & 'o | Var & 'p\n//│     'k <: Abs[?] | App[?] | Var & 'q\n//│     'q :> Var\n//│        <: Abs[?] & 'j & 'k | 'lhs & (Abs[?] & 'k & ~#Abs | Add[?] & {name: string} & 'l | App[?] & {name: string} & 'm | Mul[?] & {name: string} & 'n | Numb & {name: string} & 'o | Var & 'p)\n//│     'l <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'p & 'lhs\n//│     'result0 :> Numb | Var | 'i\n//│              <: Abs[?] & 'j & 'k | 'lhs & (Add[?] & 'l | App[?] & 'm | Mul[?] & 'n | Numb & 'o | Var & 'p)\n//│     'o <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'p & 'lhs\n//│     'n <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'p & 'lhs\n//│     'p <: Var & 'q\n//│     'm <: Abs[?] & {body: 'h} | App[?] & {lhs: 'h, rhs: 'h} | Var & 'q\n//│     'j <: {body: 'h, name: string}\n//│     'rhs :> 'i\n//│      = <no result>\n//│        eval_lexpr', eval_var, list_assoc and eq are not implemented\n\n:Fuel 20000\n\n:stats\nrec def eval4 subst = eval_lexpr' eval4 subst\n//│ eval4: ('tail & 'tail0 & 'tail1 & 'tail2 & 'tail3 & 'tail4 & (Cons[?] & List[?] & 'b & 'c & 'd & 'e & 'f & 'g | Nil & List[?])) -> 'h -> 'i\n//│   where\n//│     'tail4 <: Cons[?] & 'g | Nil\n//│     'g <: {head: {0: string, 1: 'result}, tail: 'tail4}\n//│     'tail3 <: Cons[?] & 'f | Nil\n//│     'f <: {head: {0: string, 1: 'result0}, tail: 'tail3}\n//│     'tail2 <: Cons[?] & 'e | Nil\n//│     'e <: {head: {0: string, 1: 'result0}, tail: 'tail2}\n//│     'tail1 <: Cons[?] & 'd | Nil\n//│     'd <: {head: {0: string, 1: 'result0}, tail: 'tail1}\n//│     'tail0 <: Cons[?] & 'c | Nil\n//│     'c <: {head: {0: string, 1: 'result}, tail: 'tail0}\n//│     'tail <: Cons[?] & 'b | Nil\n//│     'b <: {head: {0: string, 1: 'result}, tail: 'tail}\n//│     'result :> 'i\n//│             <: Abs[?] & 'j & 'k & 'l | 'lhs & (Abs[?] & 'k & 'l & ~#Abs | 'lhs0 & (Add[?] & 'm | App[?] & 'n | Mul[?] & 'o | Numb & 'p | Var & 'q))\n//│     'i :> Abs['i] | App['a]\\lhs\\rhs & {lhs: 'lhs | 'lhs0, rhs: 'rhs} | Numb | 'result0 | Add['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | Mul['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | 'r | 'result\n//│     'a :> Add['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | App['a]\\lhs\\rhs & {lhs: 'lhs0 | 'lhs, rhs: 'rhs} | Mul['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | Numb | 'i\n//│     'lhs0 :> Add['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | App['a]\\lhs\\rhs & {lhs: 'lhs0 | 'lhs, rhs: 'rhs} | Mul['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | Numb | Var\n//│           <: 'h & 'a\n//│     'lhs :> Add['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | App['a]\\lhs\\rhs & {lhs: 'lhs0 | 'lhs, rhs: 'rhs} | Mul['i]\\lhs\\rhs & {lhs: 'i, rhs: 'i} | Numb | Var\n//│          <: 'h & 'a\n//│     'h <: Abs[?] & 'k | Add[?] & 'm | App[?] & 'n | Mul[?] & 'o | Numb & 'p | Var & 'q\n//│     'k <: Abs[?] & {body: 'h} | App[?] & {lhs: 'h, rhs: 'h} | Var & 'r\n//│     'r :> Var\n//│        <: Abs[?] & 'j & 'k & 'l | 'lhs & (Abs[?] & 'k & 'l & ~#Abs | 'lhs0 & (Add[?] & {name: string} & 'm | App[?] & {name: string} & 'n | Mul[?] & {name: string} & 'o | Numb & {name: string} & 'p | Var & 'q))\n//│     'm <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'q & 'lhs & 'lhs0\n//│     'result0 :> Numb | Var | 'i\n//│              <: Abs[?] & 'j & 'k & 'l | 'lhs & 'lhs0 & (Add[?] & 'm | App[?] & 'n | Mul[?] & 'o | Numb & 'p | Var & 'q)\n//│     'p <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'q & 'lhs & 'lhs0\n//│     'o <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'q & 'lhs & 'lhs0\n//│     'q <: Var & 'r\n//│     'n <: Abs[?] & {body: 'h} | App[?] & {lhs: 'h, rhs: 'h} | Var & 'r\n//│     'l <: {body: 'h, name: string}\n//│     'j <: {body: 'h, name: string}\n//│     'rhs :> 'i\n//│      = <no result>\n//│        eval_lexpr', eval_var, list_assoc and eq are not implemented\n//│ constrain calls  : 10599\n//│ annoying  calls  : 2300\n//│ subtyping calls  : 319664\n\n:ResetFuel\n\neval4 Nil (Abs { name = \"s\"; body = Add { lhs = Var { name = \"s\" }; rhs = Numb { num = 1 } } })\n//│ res: 'b\n//│   where\n//│     'b :> Abs['b] | (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'a :> 'lhs | 'b\n//│     'lhs :> (Add['b] with {lhs: 'b, rhs: 'b}) | (App['a] with {lhs: 'lhs, rhs: 'rhs}) | (Mul['b] with {lhs: 'b, rhs: 'b}) | Numb | Var\n//│     'rhs :> 'b\n//│    = <no result>\n//│      eval4, eval_lexpr', eval_var, list_assoc and eq are not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Polym.mls",
    "content": "\ndef foo f =\n  f (fun x -> x)\n//│ foo: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│    = [Function: foo]\n\ndef bar h =\n  (h 0, h true)\n//│ bar: (0 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: bar]\n\nbar id\n//│ res: (0, true,)\n//│    = [ 0, true ]\n\nfoo bar\n//│ res: (0, true,)\n//│    = [ 0, true ]\n\n\ndef foo2 f =\n  f id\n//│ foo2: ((forall 'a. 'a -> 'a) -> 'b) -> 'b\n//│     = [Function: foo2]\n\nfoo2 bar\n//│ res: (0, true,)\n//│    = [ 0, true ]\n\n\n\ndef foo x f = f (fun a -> (x, a))\n//│ foo: 'a -> ((forall 'b. 'b -> ('a, 'b,)) -> 'c) -> 'c\n//│    = [Function: foo1]\n\n// Swapping the parameters givesa an isomorphic type:\n\ndef foo f x = f (fun a -> (x, a))\n//│ foo: ((forall 'a. 'a -> ('b, 'a,)) -> 'c) -> 'b -> 'c\n//│    = [Function: foo3]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/PolymExtrusion.mls",
    "content": ":NoConstrainedTypes\n:DontDistributeForalls\n:NoCycleCheck\n:NoRecursiveTypes\n\n\n\ndef foo: (forall 'a. 'a -> 'a) -> int\n//│ foo: (forall 'a. 'a -> 'a) -> int\n//│    = <missing implementation>\n\nfoo f = f 42\n//│ (42 -> 'a) -> 'a\n//│   <:  foo:\n//│ (forall 'a. 'a -> 'a) -> int\n//│    = [Function: foo]\n\nfoo id\n//│ res: int\n//│    = 42\n\n// Notice `f` is passed an arg of locally-quantified type 'a, which is extruded to `anything`:\nbar f = foo (fun x -> let tmp = f x in x)\n//│ bar: (??a -> anything) -> int\n//│    = [Function: bar]\n\nbar (fun x -> 0)\n//│ res: int\n//│    = 42\n\n:e\nbar succ\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.32: \tbar succ\n//│ ║        \t^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.8: \tdef foo: (forall 'a. 'a -> 'a) -> int\n//│ ║       \t                     ^^\n//│ ╟── into type `int`\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.23: \tbar f = foo (fun x -> let tmp = f x in x)\n//│ ╙──      \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | int\n//│    = 42\n\n:e\nbar (fun x -> case x of {})\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.48: \tbar (fun x -> case x of {})\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'a` leaks out of its scope\n//│ ║  l.8: \tdef foo: (forall 'a. 'a -> 'a) -> int\n//│ ║       \t                     ^^\n//│ ╟── into reference of type `nothing`\n//│ ║  l.48: \tbar (fun x -> case x of {})\n//│ ║        \t                   ^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.23: \tbar f = foo (fun x -> let tmp = f x in x)\n//│ ╙──      \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | int\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\ndef f: 'a -> 'b\n//│ f: anything -> nothing\n//│  = <missing implementation>\n\ndef foo: (forall 'a. 'a -> 'b) -> 'b\n//│ foo: (anything -> 'b) -> 'b\n//│    = <missing implementation>\n\n\n// Notice `id` returns its arg of locally-quantified type 'a, which is extruded to `anything`:\nfoo id\n//│ res: ??a\n//│    = <no result>\n//│      foo is not implemented\n\n:e\nfoo (fun a -> a + 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.83: \tfoo (fun a -> a + 1)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.71: \tdef foo: (forall 'a. 'a -> 'b) -> 'b\n//│ ║        \t                     ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.83: \tfoo (fun a -> a + 1)\n//│ ║        \t              ^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.71: \tdef foo: (forall 'a. 'a -> 'b) -> 'b\n//│ ╙──      \t                 ^^\n//│ res: error | int\n//│    = <no result>\n//│      foo is not implemented\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/PolymorphicExtension.mls",
    "content": "// * Here we compare to OCaml's polymorphic variants, showing their limitation\n\n\nclass Apple\nclass Banana\n//│ Defined class Apple\n//│ Defined class Banana\n\n\n// utop # let foo x default otherwise = match x with `Apple -> default | y -> otherwise y ;;\n// val foo : ([> `Apple ] as 'a) -> 'b -> ('a -> 'b) -> 'b = <fun>\n\ndef foo x default otherwise = case x of { Apple -> default | _ -> otherwise x }\n//│ foo: (Apple | 'a & ~#Apple) -> 'b -> ('a -> 'b) -> 'b\n//│    = [Function: foo]\n\n// utop # foo `Apple ;;\n// - : '_a -> (_[> `Apple ] -> '_a) -> '_a = <fun>\n\nfoo (Apple{})\n//│ res: 'a -> (nothing -> 'a) -> 'a\n//│    = [Function (anonymous)]\n\n// utop # foo `Banana ;;\n// - : '_a -> (_[> `Apple | `Banana ] -> '_a) -> '_a = <fun>\n\nfoo (Banana{})\n//│ res: 'a -> (Banana -> 'a) -> 'a\n//│    = [Function (anonymous)]\n\n// utop # foo `Banana 0 (function `Banana -> 1) ;;\n// Characters 9-27:\n// Warning 8: this pattern-matching is not exhaustive.\n// Here is an example of a value that is not matched:\n// `Apple\n// Characters 9-27:\n// Warning 8: this pattern-matching is not exhaustive.\n// Here is an example of a value that is not matched:\n// `Apple\n// - : int = 1\n\nfoo (Banana{}) 0 (fun z -> case z of  { Banana -> 1 })\n//│ res: 0 | 1\n//│    = 1\n\n// utop # foo `Apple 0 (function `Apple -> 1) ;;\n// - : int = 0\n\nfoo (Apple{}) 0 (fun z -> case z of  { Apple -> 1 })\n//│ res: 0 | 1\n//│    = 0\n\nfoo (Apple{}) 0 (fun z -> z.lol) // z has type `nothing` so we can do whatever we want in this unreachable case\n//│ res: 0\n//│    = 0\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/PreservationFail.mls",
    "content": "\n// * Strictly speaking, type preservation does not hold in the MLscript implementation,\n// *  though this is merely a technicality that can be addressed in the formal language.\n// * Consider the following example:\n\nclass C1\nclass C2: C1\nclass C3\n//│ Defined class C1\n//│ Defined class C2\n//│ Defined class C3\n\ndef foo x = case x of {\n  | C2 -> C3{}\n  | _ -> x\n  }\n//│ foo: (C2 | 'a & ~#C2) -> (C3 | 'a)\n//│    = [Function: foo]\n\nc1 = C1{}\n//│ c1: C1\n//│   = C1 {}\n\nr = foo c1\n//│ r: C1 & ~#C2 | C3\n//│  = C1 {}\n\n// * Here we have the C1{} value typed at ~C2\nr : ~C2\n//│ res: ~C2\n//│    = C1 {}\n\n// * But that C1{} value cannot be typed at ~C2 directly!\n:e\nc1 : ~C2\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.35: \tc1 : ~C2\n//│ ║        \t^^\n//│ ╟── application of type `C1` does not match type `~C2`\n//│ ║  l.20: \tc1 = C1{}\n//│ ║        \t     ^^^^\n//│ ╟── but it flows into reference with expected type `~C2`\n//│ ║  l.35: \tc1 : ~C2\n//│ ║        \t^^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.35: \tc1 : ~C2\n//│ ║        \t     ^^^\n//│ ╟── Note: class C1 is defined at:\n//│ ║  l.6: \tclass C1\n//│ ╙──     \t      ^^\n//│ res: ~C2\n//│    = C1 {}\n\n// * The problem is resolved by saying that when instantiating a non-final class C1,\n// *  we are really instantiating a hidden final C1_Impl version of it:\n\nclass C1_Impl: C1\n//│ Defined class C1_Impl\n\nc1 = C1_Impl{}\n//│ c1: C1_Impl\n//│   = C1_Impl {}\n\nr = foo c1\n//│ r: C1_Impl | C3\n//│  = C1_Impl {}\n\nr : ~C2\n//│ res: ~C2\n//│    = C1_Impl {}\n\nc1 : ~C2\n//│ res: ~C2\n//│    = C1_Impl {}\n\n\n// * More concerning: trait constructors are unsound as long as we allow matching on traits!\n// * Trait constructors were always a fringe feature that we wanted to eventually remove anyway.\n\ntrait T1\n//│ Defined trait T1\n\nrec def getNegT1 x = case x of {\n  | T1 -> getNegT1 x\n  | _ -> x\n  }\n//│ getNegT1: (#T1 | 'a & ~#T1) -> 'a\n//│         = [Function: getNegT1]\n\nnt1 = getNegT1 {}\n//│ nt1: ~#T1\n//│    = {}\n\nT1\n//│ res: 'a -> (#T1 & 'a)\n//│    = [Function: build]\n\nt1nt1 = T1 nt1\n//│ t1nt1: nothing\n//│      = {}\n\n:re\nt1nt1.lol \"oops!\"\n//│ res: nothing\n//│ Runtime error:\n//│   TypeError: t1nt1.lol is not a function\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/ProvFlows.mls",
    "content": ":AllowTypeErrors\n\ndef succ: int -> int\n//│ succ: int -> int\n\n\nx1 = false\nx2 = x1\nx3 = x2\n//│ x1: false\n//│ x2: false\n//│ x3: false\n\n:ex\nsucc x3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.15: \tsucc x3\n//│ ║        \t^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.7: \tx1 = false\n//│ ║       \t     ^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.15: \tsucc x3\n//│ ║        \t     ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from type `false`\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.7: \tx1 = false\n//│ ║       \t     ^^^^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.8: \tx2 = x1\n//│ ║       \t     ^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.9: \tx3 = x2\n//│ ║       \t     ^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.15: \tsucc x3\n//│ ║        \t     ^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ╙──     \t          ^^^\n//│ res: error | int\n\n\nf1 y1 = succ y1\nf2 y2 = f1 y2\nf3 y3 = f2 y3\n//│ f1: int -> int\n//│ f2: int -> int\n//│ f3: int -> int\n\n:ex\nf3 true\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.59: \tf3 true\n//│ ║        \t^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.59: \tf3 true\n//│ ║        \t   ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── from reference:\n//│ ║  l.53: \tf3 y3 = f2 y3\n//│ ║        \t           ^^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from type `true`\n//│ ╟── [info] flowing from reference of type `true`\n//│ ║  l.59: \tf3 true\n//│ ║        \t   ^^^^\n//│ ╟── [info] flowing into variable of type `?a`\n//│ ╟── [info] flowing into variable of type `?b`\n//│ ╟── [info] flowing into reference of type `?c`\n//│ ║  l.53: \tf3 y3 = f2 y3\n//│ ║        \t           ^^\n//│ ╟── [info] flowing into variable of type `?d`\n//│ ╟── [info] flowing into variable of type `?e`\n//│ ╟── [info] flowing into reference of type `?f`\n//│ ║  l.52: \tf2 y2 = f1 y2\n//│ ║        \t           ^^\n//│ ╟── [info] flowing into variable of type `?g`\n//│ ╟── [info] flowing into variable of type `int`\n//│ ╟── [info] flowing into reference of type `int`\n//│ ║  l.51: \tf1 y1 = succ y1\n//│ ║        \t             ^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ╙──     \t          ^^^\n//│ res: error | int\n\n\n:ex\nf3 x3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.102: \tf3 x3\n//│ ║         \t^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.7: \tx1 = false\n//│ ║       \t     ^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.102: \tf3 x3\n//│ ║         \t   ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── from reference:\n//│ ║  l.53: \tf3 y3 = f2 y3\n//│ ║        \t           ^^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from type `false`\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.7: \tx1 = false\n//│ ║       \t     ^^^^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.8: \tx2 = x1\n//│ ║       \t     ^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.9: \tx3 = x2\n//│ ║       \t     ^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.102: \tf3 x3\n//│ ║         \t   ^^\n//│ ╟── [info] flowing into variable of type `?a`\n//│ ╟── [info] flowing into variable of type `?b`\n//│ ╟── [info] flowing into reference of type `?c`\n//│ ║  l.53: \tf3 y3 = f2 y3\n//│ ║        \t           ^^\n//│ ╟── [info] flowing into variable of type `?d`\n//│ ╟── [info] flowing into variable of type `?e`\n//│ ╟── [info] flowing into reference of type `?f`\n//│ ║  l.52: \tf2 y2 = f1 y2\n//│ ║        \t           ^^\n//│ ╟── [info] flowing into variable of type `?g`\n//│ ╟── [info] flowing into variable of type `int`\n//│ ╟── [info] flowing into reference of type `int`\n//│ ║  l.51: \tf1 y1 = succ y1\n//│ ║        \t             ^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ╙──     \t          ^^^\n//│ res: error | int\n\n\nh1 f x = f x\nh2 f x = h1 f x\nh3 f x = h2 f x\n//│ h1: ('a -> 'b) -> 'a -> 'b\n//│ h2: ('a -> 'b) -> 'a -> 'b\n//│ h3: ('a -> 'b) -> 'a -> 'b\n\n:ex\nh3 f3 x3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.164: \th3 f3 x3\n//│ ║         \t^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.7: \tx1 = false\n//│ ║       \t     ^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.164: \th3 f3 x3\n//│ ║         \t      ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── from reference:\n//│ ║  l.158: \th3 f x = h2 f x\n//│ ║         \t              ^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from type `false`\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.7: \tx1 = false\n//│ ║       \t     ^^^^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.8: \tx2 = x1\n//│ ║       \t     ^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.9: \tx3 = x2\n//│ ║       \t     ^^\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.164: \th3 f3 x3\n//│ ║         \t      ^^\n//│ ╟── [info] flowing into variable of type `?a`\n//│ ╟── [info] flowing into variable of type `?b`\n//│ ╟── [info] flowing into reference of type `?c`\n//│ ║  l.158: \th3 f x = h2 f x\n//│ ║         \t              ^\n//│ ╟── [info] flowing into variable of type `?d`\n//│ ╟── [info] flowing into variable of type `?e`\n//│ ╟── [info] flowing into reference of type `?f`\n//│ ║  l.157: \th2 f x = h1 f x\n//│ ║         \t              ^\n//│ ╟── [info] flowing into variable of type `?g`\n//│ ╟── [info] flowing into variable of type `?h`\n//│ ╟── [info] flowing into reference of type `?i`\n//│ ║  l.156: \th1 f x = f x\n//│ ║         \t           ^\n//│ ╟── [info] flowing into variable of type `?j`\n//│ ╟── [info] flowing into variable of type `?k`\n//│ ╟── [info] flowing into reference of type `?l`\n//│ ║  l.53: \tf3 y3 = f2 y3\n//│ ║        \t           ^^\n//│ ╟── [info] flowing into variable of type `?m`\n//│ ╟── [info] flowing into variable of type `?n`\n//│ ╟── [info] flowing into reference of type `?o`\n//│ ║  l.52: \tf2 y2 = f1 y2\n//│ ║        \t           ^^\n//│ ╟── [info] flowing into variable of type `?p`\n//│ ╟── [info] flowing into variable of type `int`\n//│ ╟── [info] flowing into reference of type `int`\n//│ ║  l.51: \tf1 y1 = succ y1\n//│ ║        \t             ^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ╙──     \t          ^^^\n//│ res: error | int\n\n\n:ex\n(fun x -> succ x) false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.234: \t(fun x -> succ x) false\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.234: \t(fun x -> succ x) false\n//│ ║         \t                  ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── from reference:\n//│ ║  l.234: \t(fun x -> succ x) false\n//│ ║         \t               ^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from type `false`\n//│ ╟── [info] flowing from reference of type `false`\n//│ ║  l.234: \t(fun x -> succ x) false\n//│ ║         \t                  ^^^^^\n//│ ╟── [info] flowing into variable of type `?a`\n//│ ╟── [info] flowing into variable of type `int`\n//│ ╟── [info] flowing into reference of type `int`\n//│ ║  l.234: \t(fun x -> succ x) false\n//│ ║         \t               ^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ╙──     \t          ^^^\n//│ res: error | int\n\n// :d\n:ex\nrec def x = add x\n//│ ╔══[ERROR] Type mismatch in binding of application:\n//│ ║  l.267: \trec def x = add x\n//│ ║         \t            ^^^^^\n//│ ╟── application of type `int -> int` is not an instance of type `int`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.267: \trec def x = add x\n//│ ║         \t                ^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from expression of type `int -> int`\n//│ ╟── [info] flowing from application of type `int -> int`\n//│ ║  l.267: \trec def x = add x\n//│ ║         \t            ^^^^^\n//│ ╟── [info] flowing from application of type `?a`\n//│ ║  l.267: \trec def x = add x\n//│ ║         \t            ^^^^^\n//│ ╟── [info] flowing into expression of type `?x`\n//│ ╟── [info] flowing into reference of type `int`\n//│ ║  l.267: \trec def x = add x\n//│ ║         \t                ^\n//│ ╙── [info] flowing into type `int`\n//│ x: int -> int\n\n\ndef foo: int | string\n//│ foo: int | string\n\n:ex\nsucc foo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.295: \tsucc foo\n//│ ║         \t^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.291: \tdef foo: int | string\n//│ ║         \t               ^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.295: \tsucc foo\n//│ ║         \t     ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from type `string`\n//│ ║  l.291: \tdef foo: int | string\n//│ ║         \t               ^^^^^^\n//│ ╟── [info] flowing from type `string`\n//│ ║  l.291: \tdef foo: int | string\n//│ ║         \t               ^^^^^^\n//│ ╟── [info] flowing from type `int | string`\n//│ ║  l.291: \tdef foo: int | string\n//│ ║         \t         ^^^^^^^^^^^^\n//│ ╟── [info] flowing from reference of type `int | string`\n//│ ║  l.295: \tsucc foo\n//│ ║         \t     ^^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ║       \t          ^^^\n//│ ╟── [info] flowing into type `int`\n//│ ║  l.3: \tdef succ: int -> int\n//│ ╙──     \t          ^^^\n//│ res: error | int\n\n\n\nclass A\nclass B\n//│ Defined class A\n//│ Defined class B\n\ndef ty00: ('a & A | 'b & B) -> ('a, 'b)\n//│ ty00: (A & 'a | B & 'b) -> ('a, 'b,)\n\ndef ty11: ('a & A | 'a & B) -> ('a, 'a)\n//│ ty11: ('a & (A | B)) -> ('a, 'a,)\n\nty11 = ty00\n//│ (A & 'a | B & 'b) -> ('a, 'b,)\n//│   <:  ty11:\n//│ ('a & (A | B)) -> ('a, 'a,)\n\n// :d\n:ex\nty00 = ty11\n//│ ('a & (A | B)) -> ('a, 'a,)\n//│   <:  ty00:\n//│ (A & 'a | B & 'b) -> ('a, 'b,)\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.349: \tty00 = ty11\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type `B & 'b` does not match type `'a`\n//│ ║  l.336: \tdef ty00: ('a & A | 'b & B) -> ('a, 'b)\n//│ ║         \t                    ^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.336: \tdef ty00: ('a & A | 'b & B) -> ('a, 'b)\n//│ ║         \t                                ^^\n//│ ╟── ========= Additional explanations below =========\n//│ ╟── [info] flowing from expression of type `B & 'b`\n//│ ╟── [info] flowing from type `B & 'b`\n//│ ║  l.336: \tdef ty00: ('a & A | 'b & B) -> ('a, 'b)\n//│ ║         \t                    ^^^^^^\n//│ ╟── [info] flowing from type `B & 'b`\n//│ ║  l.336: \tdef ty00: ('a & A | 'b & B) -> ('a, 'b)\n//│ ║         \t          ^^^^^^^^^^^^^^^^^\n//│ ╟── [info] flowing from type `B & 'b`\n//│ ║  l.339: \tdef ty11: ('a & A | 'a & B) -> ('a, 'a)\n//│ ║         \t          ^^^^^^^^^^^^^^^^^\n//│ ╟── [info] flowing from expression of type `'a0`\n//│ ╟── [info] flowing from type `'a1`\n//│ ║  l.339: \tdef ty11: ('a & A | 'a & B) -> ('a, 'a)\n//│ ║         \t                                ^^\n//│ ╟── [info] flowing into type `'a`\n//│ ║  l.336: \tdef ty00: ('a & A | 'b & B) -> ('a, 'b)\n//│ ║         \t                                ^^\n//│ ╙── [info] flowing into expression of type `'a`\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Random1.mls",
    "content": "\n:w\n// class G[A]: { a: G[A] & A & G[A] }\nclass G[A]: { a: G[A] }\n//│ Defined class G[±A]\n//│ ╔══[WARNING] Type definition G has bivariant type parameters:\n//│ ║  l.4: \tclass G[A]: { a: G[A] }\n//│ ║       \t      ^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.4: \tclass G[A]: { a: G[A] }\n//│ ╙──     \t        ^\n\ndef g: G['a] & {a: 'a} as 'a\n//│ g: 'a\n//│   where\n//│     'a :> G[?] with {a: 'a}\n//│  = <missing implementation>\n\n:NoJS\n\nrec def g2 a = G { a }\n//│ g2: (G[?] & 'a) -> (G[?] with {a: 'a})\n\n:e\ng = g2\n//│ (G[?] & 'a) -> (G[?] with {a: 'a})\n//│   <:  g:\n//│ 'a\n//│   where\n//│     'a :> G[?] with {a: 'a}\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.25: \tg = g2\n//│ ║        \t^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b)` is not an instance of type `G`\n//│ ║  l.21: \trec def g2 a = G { a }\n//│ ║        \t           ^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `G[?]`\n//│ ║  l.25: \tg = g2\n//│ ║        \t    ^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.13: \tdef g: G['a] & {a: 'a} as 'a\n//│ ║        \t       ^^^^^\n//│ ╟── from local type binding:\n//│ ║  l.13: \tdef g: G['a] & {a: 'a} as 'a\n//│ ╙──      \t       ^^^^^^^^^^^^^^^\n\nrec def g2 = G { a = g2 }\n//│ g2: 'a\n//│   where\n//│     'a :> G[?] with {a: 'a}\n\ng = g2\n//│ 'a\n//│   where\n//│     'a :> G[?] with {a: 'a}\n//│   <:  g:\n//│ 'a\n//│   where\n//│     'a :> G[?] with {a: 'a}\n\ng = g\n//│ 'a\n//│   where\n//│     'a :> G[?] with {a: 'a}\n//│   <:  g:\n//│ 'a\n//│   where\n//│     'a :> G[?] with {a: 'a}\n\n\ndef manual: 'a -> nothing as 'a\n//│ manual: 'a\n//│   where\n//│     'a := 'a -> nothing\n\n:e\nmanual id\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.77: \tmanual id\n//│ ║        \t^^^^^^^^^\n//│ ╟── type `'a -> nothing` does not match type `nothing`\n//│ ║  l.71: \tdef manual: 'a -> nothing as 'a\n//│ ║        \t            ^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.71: \tdef manual: 'a -> nothing as 'a\n//│ ╙──      \t                  ^^^^^^^\n//│ res: error\n\ndef manual: 'a -> anything as 'a\n//│ manual: 'a\n//│   where\n//│     'a := 'a -> anything\n\nmanual id\n//│ res: anything\n\n\ndef f: { mut x: int }\n//│ f: {mut x: int}\n\nf: { mut x: int }\n//│ res: {mut x: int}\n\nf = { mut x = 1 }\n//│ {mut x: 'x}\n//│   where\n//│     'x :> 1\n//│   <:  f:\n//│ {mut x: int}\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Random2.mls",
    "content": ":NoJS\n\n\n// :stdout\n// :s\n// :d\n// :ds\ndef f: { x: 'a } as 'a\n//│ f: 'a\n//│   where\n//│     'a :> {x: 'a}\n\n\n// :stdout\n// :s\n// :d\n// :ds\nrec def l x = l\n//│ l: 'l\n//│   where\n//│     'l :> anything -> 'l\n\nl\n//│ res: 'l\n//│   where\n//│     'l :> anything -> 'l\n\n:ns\nm y = l y\n//│ m: forall 'a 'b 'c. 'a -> 'b\n//│   where\n//│     'b :> forall 'l. 'l\n//│     'l := 'c -> 'l\n//│     'a <: 'c\n\nm\n//│ res: 'l\n//│   where\n//│     'l :> anything -> 'l\n\n\nfun a -> a a\n//│ res: ('a -> 'b & 'a) -> 'b\n\n\n// :stdout\n// :s\n// :d\n// :ds\n:e\nrec def f a = a a\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  f:\n//│ 'a\n//│   where\n//│     'a :> {x: 'a}\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.51: \trec def f a = a a\n//│ ║        \t^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `forall ?f. ?f` does not match type `{x: 'a}`\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.8: \tdef f: { x: 'a } as 'a\n//│ ╙──     \t       ^^^^^^^^^\n\n\n// :stdout\n// :s\n// :d\n// :ds\nrec def g a = a a\n//│ g: ('a -> 'b & 'a) -> 'b\n\n\n// :ds\ndef ite x y z = if x then y else z\n//│ ite: bool -> 'a -> 'a -> 'a\n\n\n\nclass Some[A]: { v: A }\n//│ Defined class Some[+A]\n\ndef Some v = Some{v}\n//│ Some: 'v -> Some['v]\n\n\ndef foo(x: Some['a]) =\n  let _ = x.v : Some[?]\n  in x: Some['a & some]\n//│ foo: Some[Some[nothing] & 'a] -> Some[Some[?] & 'a]\n\ndef f: Some['a]\n//│ f: Some[nothing]\n\n\n\ndef foo(x: 'a) = (x + 1, x)\n//│ foo: (int & 'a) -> (int, 'a,)\n\n// * NOTE: currently each parameter type is typed independently – so these 'a are different!\ndef foo(x: 'a, y: 'a) = (x + 1, y)\n//│ foo: (int, 'a,) -> (int, 'a,)\n\ndef foo(f: 'a -> 'a, x: 'a) =\n  let _ = x + 1\n  in error: Some['a & some]\n//│ foo: ('a -> 'a, int,) -> Some[nothing]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/RecDefs.mls",
    "content": "\nrec def f x = x\n//│ f: 'a -> 'a\n//│  = [Function: f]\n\nf 1\n//│ res: 1\n//│    = 1\n\nf 2\n//│ res: 2\n//│    = 2\n\n\n\nrec def f = if true then fun (x: 'a) -> 32 else let tmp = f f + 1 in error\n//│ f: anything -> 32\n//│  = [Function: f1]\n\n\n:e\nrec def f = forall 'a. (fun (x: 'a) -> 32) : 'a\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.22: \trec def f = forall 'a. (fun (x: 'a) -> 32) : 'a\n//│ ║        \t                       ^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `'a -> 32` does not match type `'a`\n//│ ║  l.22: \trec def f = forall 'a. (fun (x: 'a) -> 32) : 'a\n//│ ║        \t                        ^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from rigid type variable:\n//│ ║  l.22: \trec def f = forall 'a. (fun (x: 'a) -> 32) : 'a\n//│ ╙──      \t                   ^^\n//│ f: nothing\n//│  = [Function: f2]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/RecErrors.mls",
    "content": "\n:AllowTypeErrors\n:ShowRelativeLineNums\n\n\nrec def f n =\n  if n then 0 else f (miss + 1)\n//│ ╔══[ERROR] identifier not found: miss\n//│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n//│ ╙──      \t                      ^^^^\n//│ ╔══[ERROR] Type mismatch in binding of lambda expression:\n//│ ║  l.+1: \trec def f n =\n//│ ║        \t          ^^^\n//│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `int` is not an instance of type `bool`\n//│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n//│ ║        \t                      ^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n//│ ╙──      \t     ^\n//│ f: bool -> 0\n\n\nclass Left: { v: anything }\n//│ Defined class Left\n\n// TODO missing prov of `a` in `let Left a`\n:e\nrec def lefts() =\n  let res = Left {v = lefts()}\n  in let a = res.v\n  in let tmo = log(a + 1)\n  in res\n//│ ╔══[ERROR] Type mismatch in binding of lambda expression:\n//│ ║  l.+1: \trec def lefts() =\n//│ ║        \t             ^^^^\n//│ ║  l.+2: \t  let res = Left {v = lefts()}\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+3: \t  in let a = res.v\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.+4: \t  in let tmo = log(a + 1)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+5: \t  in res\n//│ ║        \t^^^^^^^^^\n//│ ╟── application of type `Left & {v: ?v}` is not an instance of type `int`\n//│ ║  l.+2: \t  let res = Left {v = lefts()}\n//│ ║        \t            ^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.+5: \t  in res\n//│ ║        \t     ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.+4: \t  in let tmo = log(a + 1)\n//│ ║        \t                   ^\n//│ ╟── from application:\n//│ ║  l.+2: \t  let res = Left {v = lefts()}\n//│ ╙──      \t                      ^^^^^^^\n//│ lefts: () -> 'a\n//│   where\n//│     'a :> Left & {v: forall 'a. 'a}\n\n\n\n\n// * For the record – the errors in Supertype prototype:\n\n\n///│ ╔══[ERROR]══ identifier not found: miss\n///│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n///│ ╙──      \t                      ^^^^\n///│ ╔══[ERROR]══ Type mismatch in member definition:\n///│ ║  l.+1: \tf n = ...\n///│ ║        \t^^^^^^^\n///│ ╟────────────── expression of type:  Int\n///│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n///│ ║        \t                     ^^^^^^^^^^\n///│ ╟── which flows into\n///│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n///│ ║        \t     ^\n///│ ╟──── does not match expected type:  Bool\n///│ ╠══════[DETAILS]══════\n///│ ╟── Expression of type: \tInt\n///│ ║  [predef.sup]\n///│ ║  l.129: \t(+): Int -> Int -> Int\n///│ ║         \t                   ^^^\n///│ ╟────► flowing into\n///│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n///│ ║        \t                     ^^^^^^^^^^\n///│ ╟────► into\n///│ ║  l.+1: \tf n =\n///│ ║        \t  ^\n///│ ╟── does not match expected type: Bool\n///│ ║  l.+2: \t  if n then 0 else f (miss + 1)\n///│ ╙──      \t     ^\n///│ f: Bool -> 0\n\n\n// TODO missing prov of `a` in `let Left a`\n///│ ╔══[ERROR]══ Type mismatch in member definition:\n///│ ║  l.+1: \tlefts() = ...\n///│ ║        \t^^^^^^^^^^^\n///│ ╟────────────── expression of type:  Left ?a as ?a\n///│ ║  l.+2: \t  let res = Left lefts()\n///│ ║        \t            ^^^^^^^^^^^^\n///│ ╟── which flows into\n///│ ║  l.+4: \t  println @ a + 1\n///│ ║        \t            ^\n///│ ╟──── does not match expected type:  Int\n///│ ║  [predef.sup]\n///│ ║  l.129: \t(+): Int -> Int -> Int\n///│ ║         \t     ^^^\n///│ ╠══════[DETAILS]══════\n///│ ╟── Expression of type [1] : \tLeft ?b as ?b\n///│ ║  l.+2: \t  let res = Left lefts()\n///│ ║        \t            ^^^^^^^^^^^^\n///│ ╟────► flowing into\n///│ ║  l.+2: \t  let res = Left lefts()\n///│ ║        \t      ^^^\n///│ ╟────► into\n///│ ║  l.+5: \t  res\n///│ ║        \t  ^^^\n///│ ╟────► into\n///│ ║  l.+2: \t  let res = Left lefts()\n///│ ║        \t                 ^^^^^^^\n///│ ╟────►► flowing into Left's first argument, with type: \tLeft (Left ?c as ?c)\n///│ ║                                                      \t     ^^^^^^^^^^^^^^^\n///│ ║  l.+2: \t  let res = Left lefts()\n///│ ║        \t            ^^^^^^^^^^^^\n///│ ╟────►► flowing into\n///│ ║  l.+2: \t  let res = Left lefts()\n///│ ║        \t      ^^^\n///│ ╟────►► into\n///│ ║  l.+3: \t  let Left a = res\n///│ ║        \t               ^^^\n///│ ╟────►► into\n///│ ║  l.+3: \t  let Left a = res\n///│ ║        \t      ^^^^^^\n///│ ╟────► flowing out of Left's first pattern, with type [1] : \tLeft ?d as ?d\n///│ ║                                                           \t^^^^^^^^^^^^^\n///│ ║  l.+3: \t  let Left a = res\n///│ ║        \t           ^\n///│ ╟────► flowing into\n///│ ║  l.+4: \t  println @ a + 1\n///│ ║        \t            ^\n///│ ╟── does not match expected type: Int\n///│ ║  [predef.sup]\n///│ ║  l.129: \t(+): Int -> Int -> Int\n///│ ╙──       \t     ^^^\n///│ lefts: 'fun () -> (Left 'a as 'a)\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/RecursiveTypes.mls",
    "content": "\n\n// From Simple-sub tests:\n:js\nlet rec l = fun a -> fun a -> fun a -> l in let rec r = fun a -> fun a -> r in if true then l else r\n//│ // Prelude\n//│ let res;\n//│ // Query 1\n//│ res = ((l) => ((r) => true ? l : r)(function r(a) {\n//│   return (a) => r;\n//│ }))(function l(a) {\n//│   return (a) => (a) => l;\n//│ });\n//│ // End of generated code\n//│ res: 'r | 'l\n//│   where\n//│     'l :> anything -> anything -> anything -> 'l\n//│     'r :> anything -> anything -> 'r\n//│    = [Function: l]\n\n\n\nrec def l a = l\n//│ l: 'l\n//│   where\n//│     'l :> anything -> 'l\n//│  = [Function: l]\n\nif true then l else l\n//│ res: 'l\n//│   where\n//│     'l :> anything -> 'l\n//│    = [Function: l]\n\n\n\nrec def l a a a = l\n//│ l: 'l\n//│   where\n//│     'l :> anything -> anything -> anything -> 'l\n//│  = [Function: l1]\n\n\nrec def r a a = l\n//│ r: anything -> anything -> 'l\n//│   where\n//│     'l :> anything -> anything -> anything -> 'l\n//│  = [Function: r]\n\nrec def r a a = l\n//│ r: anything -> anything -> 'l\n//│   where\n//│     'l :> anything -> anything -> anything -> 'l\n//│  = [Function: r1]\n\n\nrec def r a a = r\n//│ r: 'r\n//│   where\n//│     'r :> anything -> anything -> 'r\n//│  = [Function: r2]\n\n\nif true then l else r\n//│ res: 'r | 'l\n//│   where\n//│     'l :> anything -> anything -> anything -> 'l\n//│     'r :> anything -> anything -> 'r\n//│    = [Function: l1]\n\nif true then l else r\n//│ res: 'r | 'l\n//│   where\n//│     'l :> anything -> anything -> anything -> 'l\n//│     'r :> anything -> anything -> 'r\n//│    = [Function: l1]\n\n\n\nrec def l (a: int) (a: int) = l\nrec def r (a: bool) (a: bool) (a: bool) = r\n//│ l: 'l\n//│   where\n//│     'l :> int -> int -> 'l\n//│  = [Function: l2]\n//│ r: 'r\n//│   where\n//│     'r :> bool -> bool -> bool -> 'r\n//│  = [Function: r3]\n\nif true then l else r\n//│ res: 'r | 'l\n//│   where\n//│     'l :> int -> int -> 'l\n//│     'r :> bool -> bool -> bool -> 'r\n//│    = [Function: l2]\n\nif true then l else r\n//│ res: 'r | 'l\n//│   where\n//│     'l :> int -> int -> 'l\n//│     'r :> bool -> bool -> bool -> 'r\n//│    = [Function: l2]\n\nif true then (fun x -> add x 1) else (fun y -> not y)\n//│ res: nothing -> (bool | int)\n//│    = [Function (anonymous)]\n\nif true then (fun x -> add x 1) else (fun y -> not y)\n//│ res: nothing -> (bool | int)\n//│    = [Function (anonymous)]\n\n\n\nrec def l (a: int) (a: bool) = l\nrec def r (a: int) (a: bool) (a: bool) = r\n//│ l: 'l\n//│   where\n//│     'l :> int -> bool -> 'l\n//│  = [Function: l3]\n//│ r: 'r\n//│   where\n//│     'r :> int -> bool -> bool -> 'r\n//│  = [Function: r4]\n\nif true then l else r\n//│ res: 'r | 'l\n//│   where\n//│     'l :> int -> bool -> 'l\n//│     'r :> int -> bool -> bool -> 'r\n//│    = [Function: l3]\n\nif true then l else r\n//│ res: 'r | 'l\n//│   where\n//│     'l :> int -> bool -> 'l\n//│     'r :> int -> bool -> bool -> 'r\n//│    = [Function: l3]\n\n\n\nrec def l (a: int) b = if true then l else b\nrec def r (a: int) b c = if true then r else if true then b else c\n//│ l: int -> 'a -> 'a\n//│   where\n//│     'a :> int -> 'a -> 'a\n//│  = [Function: l4]\n//│ r: int -> 'a -> 'a -> 'a\n//│   where\n//│     'a :> int -> 'a -> 'a -> 'a\n//│  = [Function: r5]\n\nif true then l else r\n//│ res: int -> ('a & 'b) -> ('a -> 'a | 'b)\n//│   where\n//│     'b :> int -> 'b -> 'b\n//│     'a :> int -> 'a -> 'a -> 'a\n//│    = [Function: l4]\n\nif true then l else r\n//│ res: int -> ('a & 'b) -> ('a -> 'a | 'b)\n//│   where\n//│     'b :> int -> 'b -> 'b\n//│     'a :> int -> 'a -> 'a -> 'a\n//│    = [Function: l4]\n\n\n\nrec def l (a: int) (b: int) = l\n//│ l: 'l\n//│   where\n//│     'l :> int -> int -> 'l\n//│  = [Function: l5]\n\nrec def r (a: int) (b: int) (c: int) = r\n//│ r: 'r\n//│   where\n//│     'r :> int -> int -> int -> 'r\n//│  = [Function: r6]\n\nif true then l else r\n//│ res: 'r | 'l\n//│   where\n//│     'l :> int -> int -> 'l\n//│     'r :> int -> int -> int -> 'r\n//│    = [Function: l5]\n\n\n\n// ------ // ------ // ------ // ------ // ------ // ------ //\n\n\n:NoJS\n\n\nclass C[A]: { a: A }\n//│ Defined class C[+A]\n\n\n\n:ns\nrec def foo (c: C['a]) = foo (c.a)\n//│ foo: forall 'foo 'a 'a0 'b. 'foo\n//│   where\n//│     'foo := C['a] -> 'b\n//│     'a <: 'a0\n//│     'a0 <: C['a]\n\nfoo\n//│ res: 'a -> nothing\n//│   where\n//│     'a <: C['a]\n\ntype Rec = C[Rec]\ndef foo_ty: Rec -> nothing\n//│ Defined type alias Rec\n//│ foo_ty: Rec -> nothing\n\nfoo_ty = foo\n//│ 'a -> nothing\n//│   where\n//│     'a <: C['a]\n//│   <:  foo_ty:\n//│ Rec -> nothing\n\ndef foo_ty2: (C['r] as 'r) -> nothing\n//│ foo_ty2: 'r -> nothing\n//│   where\n//│     'r <: C['r]\n\n:ns\nfoo_ty2\n//│ res: forall 'r. 'r -> nothing\n//│   where\n//│     'r := C['r]\n\nfoo_ty = foo_ty2\n//│ 'r -> nothing\n//│   where\n//│     'r <: C['r]\n//│   <:  foo_ty:\n//│ Rec -> nothing\n\nfoo_ty2 = foo_ty\n//│ Rec -> nothing\n//│   <:  foo_ty2:\n//│ 'r -> nothing\n//│   where\n//│     'r <: C['r]\n\nfoo_ty2 = foo\n//│ 'a -> nothing\n//│   where\n//│     'a <: C['a]\n//│   <:  foo_ty2:\n//│ 'r -> nothing\n//│   where\n//│     'r <: C['r]\n\n\n\nrec def bar = C { a = bar }\n//│ bar: 'A\n//│   where\n//│     'A :> C['A]\n\ntype Rec2 = C[Rec2]\ndef bar_ty: Rec2\n//│ Defined type alias Rec2\n//│ bar_ty: Rec2\n\nbar_ty = bar\n//│ 'A\n//│   where\n//│     'A :> C['A]\n//│   <:  bar_ty:\n//│ Rec2\n\ndef bar_ty2: C['r] as 'r\n//│ bar_ty2: 'r\n//│   where\n//│     'r :> C['r]\n\n:ns\nbar_ty2\n//│ res: forall 'r. 'r\n//│   where\n//│     'r := C['r]\n\nbar_ty2\n//│ res: 'r\n//│   where\n//│     'r :> C['r]\n\nbar_ty = bar_ty2\n//│ 'r\n//│   where\n//│     'r :> C['r]\n//│   <:  bar_ty:\n//│ Rec2\n\nbar_ty2 = bar_ty\n//│ Rec2\n//│   <:  bar_ty2:\n//│ 'r\n//│   where\n//│     'r :> C['r]\n\nbar_ty2 = bar\n//│ 'A\n//│   where\n//│     'A :> C['A]\n//│   <:  bar_ty2:\n//│ 'r\n//│   where\n//│     'r :> C['r]\n\n\n\ntype Rec3 = { x: Rec3 }\n//│ Defined type alias Rec3\n\ndef bar2_ty: Rec3\n//│ bar2_ty: Rec3\n\ndef bar2_ty2: { x: 'r } as 'r\n//│ bar2_ty2: 'r\n//│   where\n//│     'r :> {x: 'r}\n\nbar2_ty = bar2_ty2\n//│ 'r\n//│   where\n//│     'r :> {x: 'r}\n//│   <:  bar2_ty:\n//│ Rec3\n\nbar2_ty2 = bar2_ty\n//│ Rec3\n//│   <:  bar2_ty2:\n//│ 'r\n//│   where\n//│     'r :> {x: 'r}\n\n:e\nbar2_ty2 = bar_ty2\n//│ 'r\n//│   where\n//│     'r :> C['r]\n//│   <:  bar2_ty2:\n//│ 'r\n//│   where\n//│     'r :> {x: 'r}\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.346: \tbar2_ty2 = bar_ty2\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type `forall 'r. 'r` does not match type `{x: 'r0}`\n//│ ║  l.279: \tdef bar_ty2: C['r] as 'r\n//│ ║         \t             ^^^^^\n//│ ╟── but it flows into reference with expected type `{x: 'r1}`\n//│ ║  l.346: \tbar2_ty2 = bar_ty2\n//│ ║         \t           ^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.326: \tdef bar2_ty2: { x: 'r } as 'r\n//│ ╙──       \t              ^^^^^^^^^\n\n:e\nbar_ty2 = bar2_ty2\n//│ 'r\n//│   where\n//│     'r :> {x: 'r}\n//│   <:  bar_ty2:\n//│ 'r\n//│   where\n//│     'r :> C['r]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.368: \tbar_ty2 = bar2_ty2\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type `{x: 'r}` is not an instance of type `C`\n//│ ║  l.326: \tdef bar2_ty2: { x: 'r } as 'r\n//│ ║         \t              ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `C[?]`\n//│ ║  l.368: \tbar_ty2 = bar2_ty2\n//│ ║         \t          ^^^^^^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.279: \tdef bar_ty2: C['r] as 'r\n//│ ╙──       \t             ^^^^^\n\n\n\n// ------ // ------ // ------ // ------ // ------ // ------ //\n\n\n\nrec def f x = if x > 0 then f (x with { a = x - 1 }) else x\n//│ f: 'a -> 'a\n//│   where\n//│     'a :> 'a\\a & {a: int}\n//│        <: int & (int | ~{a: int})\\a & (number | ~{a: int})\\a\n\nf 1\n//│ res: 'a\n//│   where\n//│     'a :> 1 | 'a\\a & {a: int}\n\n:ns\nrec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ f: forall 'f 'b 'c 'd 'a 'e 'g. 'f\n//│   where\n//│     'f := 'b -> 'g\n//│     'b :> 'b\\a & {a: 'c}\n//│        <: ({a: 'a} | ~{a: 'c} | ~{})\\a & ({a: 'a} | ~{a: 'c})\\a & (number | ~{a: 'c} | ~{})\\a & (number | ~{a: 'c})\\a & (int | ~{a: 'c} | ~{})\\a & (int | ~{a: 'c})\\a & 'e & int & number\n//│     'a <: 'e\n//│     'e :> 'b\\a & {a: 'c}\n//│        <: 'g\n//│     'g :> 'b\\a & {a: 'c}\n//│        <: 'd\n//│     'd :> 'b\\a & {a: 'c}\n//│        <: {a: 'a}\n//│     'c :> int\n\nf\n//│ res: 'a -> 'b\n//│   where\n//│     'a :> 'a\\a & {a: int}\n//│        <: int & (int | ~{a: int})\\a & (number | ~{a: int})\\a & ({a: 'b} | ~{a: int})\\a & 'b\n//│     'b :> 'a\\a & {a: int}\n//│        <: {a: 'b}\n\n// Notice how what is most likely an the error is reported in call sites,\n//    due to the delaying effect of the field removal type...\n//    though it *is* still possible to call this function wtihout errors,\n//    using a bottom-typed argument.\n\n:e\nf 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.436: \tf 1\n//│ ║         \t^^^\n//│ ╟── operator application of type `int` does not have field 'a'\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ║         \t                                             ^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ╙──       \t                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | int | 'a\\a & {a: int}\n//│   where\n//│     'a :> 1 | 'a\\a & {a: int}\n\n:e\nf { a = 1 }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.451: \tf { a = 1 }\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── operator application of type `int` does not have field 'a'\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ║         \t                                             ^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ╙──       \t                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error\n\nf error\n//│ res: 'a\n//│   where\n//│     'a :> 'a\\a & {a: int}\n\n\n:e\nrec def ainf = { a = ainf }\nf ainf\n//│ ainf: 'ainf\n//│   where\n//│     'ainf :> {a: 'ainf}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.471: \tf ainf\n//│ ║         \t^^^^^^\n//│ ╟── operator application of type `int` does not have field 'a'\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ║         \t                                             ^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ╙──       \t                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error\n\n:e\nrec def infina = 0 with { a = infina }\nf infina\n//│ infina: 'infina\n//│   where\n//│     'infina :> 0 & {a: 'infina}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.488: \tf infina\n//│ ║         \t^^^^^^^^\n//│ ╟── operator application of type `int` does not have field 'a'\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ║         \t                                             ^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.407: \trec def f x = if x > 0 then (f (x with { a = x - 1 })).a else x\n//│ ╙──       \t                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | int | 'a\\a & {a: int} | 'infina | 'infina0\n//│   where\n//│     'infina :> 0 & {a: 'infina}\n//│     'a :> forall 'infina0. 'a\\a & {a: int} | 'infina0\n//│     'infina0 :> 0 & {a: 'infina0}\n\n\ndef f_manual: (({a: 'b & 'a & 'c} as 'a) & 'd) -> ('c | ('d | 'e\\a & {a: int} as 'e))\n//│ f_manual: ('a & 'd) -> ('c | 'd)\n//│   where\n//│     'd :> 'd\\a & {a: int}\n//│     'a <: {a: 'a & 'c}\n\n:e\nf_manual 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.515: \tf_manual 1\n//│ ║         \t^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not have field 'a'\n//│ ║  l.515: \tf_manual 1\n//│ ║         \t         ^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.508: \tdef f_manual: (({a: 'b & 'a & 'c} as 'a) & 'd) -> ('c | ('d | 'e\\a & {a: int} as 'e))\n//│ ║         \t                ^^^^^^^^^^^^^^^^^\n//│ ╟── from intersection type:\n//│ ║  l.508: \tdef f_manual: (({a: 'b & 'a & 'c} as 'a) & 'd) -> ('c | ('d | 'e\\a & {a: int} as 'e))\n//│ ╙──       \t              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | 'e\n//│   where\n//│     'e :> 1 | 'e\\a & {a: int}\n\n:e\nf_manual { a = 1 }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.533: \tf_manual { a = 1 }\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not have field 'a'\n//│ ║  l.533: \tf_manual { a = 1 }\n//│ ║         \t               ^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.508: \tdef f_manual: (({a: 'b & 'a & 'c} as 'a) & 'd) -> ('c | ('d | 'e\\a & {a: int} as 'e))\n//│ ║         \t                ^^^^^^^^^^^^^^^^^\n//│ ╟── from intersection type:\n//│ ║  l.508: \tdef f_manual: (({a: 'b & 'a & 'c} as 'a) & 'd) -> ('c | ('d | 'e\\a & {a: int} as 'e))\n//│ ╙──       \t                    ^^^^^^^^^^^^\n//│ res: 1 | error | 'e\n//│   where\n//│     'e :> 'e\\a & {a: int} | {a: 1}\n\nf_manual error\n//│ res: 'e\n//│   where\n//│     'e :> 'e\\a & {a: int}\n\n// > FIXME why is this one accepted but `f ainf` is not?\n//    It looks like a simplification error (I copy-pasted the simplified type for f_manual)\n//    since `f_manual_ns ainf` gets the same error as `f ainf`.\nf_manual ainf\n//│ res: 'ainf | 'e\n//│   where\n//│     'e :> 'e\\a & {a: int} | 'ainf\n//│     'ainf :> {a: 'ainf}\n\n// Notice the simplified type is NOT the same as that of `f`...\ndef f_manual_ns: 'a | ('b & (({a: 'd & 'c} as 'c) | ~{a: 'e | int} | ~{})\\a & (({a: 'd & 'c} as 'c) | ~{a: 'e | int})\\a & (({a: 'f} as 'c) as 'f) & (int | ~{a: 'e | int} | ~{})\\a & (int | ~{a: 'e | int})\\a & int & int) -> ('g | 'd | ('b | 'h\\a & {a: 'e | int} as 'h))\n//│ f_manual_ns: in forall 'b 'f 'c 'd 'c0. ('b & 'f & (int & ~{a: int} | (int & 'c)\\a & 'c0\\a & int)) -> ('d | 'b) out forall 'b 'f 'c 'd 'c0. ((int & 'c & 'c0 | ~{a: int})\\a & int & 'b & 'f) -> ('d | 'b)\n//│   where\n//│     'c0 <: {a: 'd & 'c0}\n//│     'c <: {a: 'c & 'd}\n//│     'f <: {a: 'f}\n//│     'b :> 'b\\a & {a: int}\n\n:e\nf_manual_ns ainf\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.574: \tf_manual_ns ainf\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ╟── type `int` does not have field 'a'\n//│ ║  l.565: \tdef f_manual_ns: 'a | ('b & (({a: 'd & 'c} as 'c) | ~{a: 'e | int} | ~{})\\a & (({a: 'd & 'c} as 'c) | ~{a: 'e | int})\\a & (({a: 'f} as 'c) as 'f) & (int | ~{a: 'e | int} | ~{})\\a & (int | ~{a: 'e | int})\\a & int & int) -> ('g | 'd | ('b | 'h\\a & {a: 'e | int} as 'h))\n//│ ║         \t                                                              ^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.565: \tdef f_manual_ns: 'a | ('b & (({a: 'd & 'c} as 'c) | ~{a: 'e | int} | ~{})\\a & (({a: 'd & 'c} as 'c) | ~{a: 'e | int})\\a & (({a: 'f} as 'c) as 'f) & (int | ~{a: 'e | int} | ~{})\\a & (int | ~{a: 'e | int})\\a & int & int) -> ('g | 'd | ('b | 'h\\a & {a: 'e | int} as 'h))\n//│ ║         \t                              ^^^^^^^^^^^^\n//│ ╟── from local type binding:\n//│ ║  l.565: \tdef f_manual_ns: 'a | ('b & (({a: 'd & 'c} as 'c) | ~{a: 'e | int} | ~{})\\a & (({a: 'd & 'c} as 'c) | ~{a: 'e | int})\\a & (({a: 'f} as 'c) as 'f) & (int | ~{a: 'e | int} | ~{})\\a & (int | ~{a: 'e | int})\\a & int & int) -> ('g | 'd | ('b | 'h\\a & {a: 'e | int} as 'h))\n//│ ╙──       \t                             ^^^^^^^^^^^^^^^^^^^^\n//│ res: error\n\ndef f_manual_2: (({a: 'a} as 'a) & 'b) -> ('b | 'c\\a & {a: int} as 'c)\n//│ f_manual_2: ('a & 'b) -> 'b\n//│   where\n//│     'b :> 'b\\a & {a: int}\n//│     'a <: {a: 'a}\n\nf_manual_2 // [test:T2]\n//│ res: ('a & 'b) -> 'b\n//│   where\n//│     'b :> 'b\\a & {a: int}\n//│     'a <: {a: 'a}\n\nf_manual_2 ainf\n//│ res: 'c\n//│   where\n//│     'c :> forall 'ainf. 'c\\a & {a: int} | 'ainf\n//│     'ainf :> {a: 'ainf}\n\n\n\nrec def f x = if error then f (x with { a = x - 1 }) else x\n//│ f: 'a -> 'a\n//│   where\n//│     'a :> 'a\\a & {a: int}\n//│        <: int & (int | ~{a: int})\\a\n\nr = f 1\n//│ r: 'a\n//│   where\n//│     'a :> 1 | 'a\\a & {a: int}\n\nr + 1\n//│ res: int\n\n:e\nr.a\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.624: \tr.a\n//│ ║         \t^^^\n//│ ╟── integer literal of type `1` does not have field 'a'\n//│ ║  l.615: \tr = f 1\n//│ ║         \t      ^\n//│ ╟── but it flows into reference with expected type `{a: ?a}`\n//│ ║  l.624: \tr.a\n//│ ╙──       \t^\n//│ res: error | int\n\ncase r of {int -> 0 | _ -> r.a}\n//│ res: 0\n\nr2 = case r of {int -> error | _ -> r}\n//│ r2: nothing\n\nr2.a\n//│ res: nothing\n\nr2 + 1\n//│ res: int\n\nr: int\n//│ res: int\n\n\n\nrec def f x = if error then f (x with { a = 1 }) else x\n//│ f: 'a -> 'a\n//│   where\n//│     'a :> 'a\\a & {a: 1}\n\nr = f 1\n//│ r: 'a\n//│   where\n//│     'a :> 1 | 'a\\a & {a: 1}\n\nr: int\n//│ res: int\n\n\n// Field removal also blocks proper simplification\n\ndef fancyBottom1: 'a & ('a -> 'a) as 'a\ndef fancyBottom2: 'a\\x as 'a\n//│ fancyBottom1: 'a\n//│   where\n//│     'a := 'a -> 'a & 'a\n//│ fancyBottom2: 'a\n//│   where\n//│     'a :> 'a\\x\n\nfancyBottom2: nothing\n//│ res: nothing\n\n\n\n// ------ // ------ // ------ // ------ // ------ // ------ //\n\n\n\n// Just poking around:\n\ndef impossible: 'a -> ('a & int)\n//│ impossible: 'a -> (int & 'a)\n\nrec def f (x: int | string) = f (impossible x) + 1\n//│ f: (int | string) -> int\n\nrec def f (x: int | string) = (case x of {int -> f \"ok\" | string -> f (impossible x)}) + 1\n//│ f: (int | string) -> int\n\nrec def f x = (case x of {int -> f \"ok\" | string -> f (impossible x)}) + 1\n//│ f: (int | string & (int | string | ~int)) -> int\n\nf 1\nf \"a\"\n//│ res: int\n//│ res: int\n\nrec def f x = case x of {int -> f \"ok\" | string -> f (impossible x) | _ -> x}\n//│ f: (int | string & (int | string | ~int) | 'a & ~int & ~string) -> 'a\n\nf 1\nf \"a\"\nf false\n//│ res: nothing\n//│ res: nothing\n//│ res: false\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/RecursiveTypes2.mls",
    "content": ":NoJS\n\n\ntype T1 = { x: T1 & { x: T1 } }\ntype T2 = { x: T2 }\n//│ Defined type alias T1\n//│ Defined type alias T2\n\n:stats\nerror : T1 : T2\n//│ res: T2\n//│ constrain calls  : 6\n//│ annoying  calls  : 4\n//│ subtyping calls  : 24\n\ntype T3 = { x: T2 & { x: T3 } | T3 & { x: T2 } }\n//│ Defined type alias T3\n\n:stats\nerror : T1 : T3\n//│ res: T3\n//│ constrain calls  : 7\n//│ annoying  calls  : 12\n//│ subtyping calls  : 408\n\n:stats\nerror : T2 : T3\n//│ res: T3\n//│ constrain calls  : 10\n//│ annoying  calls  : 12\n//│ subtyping calls  : 389\n\ndef f: T3 & { x: T1 & 'a } as 'a\n//│ f: 'a\n//│   where\n//│     'a :> T3 & {x: T1 & 'a}\n\n:stats\nf.x\n//│ res: 'a & (T1 & T2 & {x: T3} | T1 & T3 & {x: T2})\n//│   where\n//│     'a :> T3 & {x: T1 & 'a}\n//│ constrain calls  : 4\n//│ annoying  calls  : 4\n//│ subtyping calls  : 102\n\ng = error : T1 & { x: T2 | 'a } as 'a\n//│ g: 'a\n//│   where\n//│     'a :> T1 & {x: T2 | 'a}\n\n:stats\ng.x\n//│ res: T1 & T2 & {x: T1} | T1 & {x: T1} & 'a\n//│   where\n//│     'a :> T1 & {x: T2 | 'a}\n//│ constrain calls  : 4\n//│ annoying  calls  : 4\n//│ subtyping calls  : 84\n\n:stats\nf = g\n//│ 'a\n//│   where\n//│     'a :> T1 & {x: T2 | 'a}\n//│   <:  f:\n//│ 'a\n//│   where\n//│     'a :> T3 & {x: T1 & 'a}\n//│ constrain calls  : 48\n//│ annoying  calls  : 60\n//│ subtyping calls  : 1979\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/References.mls",
    "content": "\n\nclass Ref[A]\n  method Get: A\n  method Set: A -> unit\n  method Swap x = let tmp = this.Get in let _ = this.Set x in tmp\n//│ Defined class Ref[=A]\n//│ Declared Ref.Get: Ref['A] -> 'A\n//│ Declared Ref.Set: Ref['A] -> 'A -> unit\n//│ Defined Ref.Swap: Ref['A] -> 'A -> 'A\n\nclass RefImpl[A]: Ref[A] & { mut value: A }\n  method Get   = this.value\n  method Set a = this.value <- a\n//│ Defined class RefImpl[=A]\n//│ Defined RefImpl.Get: RefImpl['A] -> 'A\n//│ Defined RefImpl.Set: RefImpl['A] -> 'A -> unit\n\n\n\ndef move a b = a.Set b.Get\n//│ move: Ref['A] -> Ref['A0] -> unit\n//│   where\n//│     'A0 <: 'A\n//│     = [Function: move]\n\ndef move_ty: Ref['a] -> Ref[('a & 'b)..'b] -> unit\n//│ move_ty: Ref['a] -> Ref[in 'a & 'b out 'b] -> unit\n//│        = <missing implementation>\n:e // * Works with existential wildcards\nmove_ty = move\n//│ Ref['A] -> Ref['A0] -> unit\n//│   where\n//│     'A0 <: 'A\n//│   <:  move_ty:\n//│ Ref['a] -> Ref[in 'a & 'b out 'b] -> unit\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.31: \tmove_ty = move\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type `'b` does not match type `'a`\n//│ ║  l.27: \tdef move_ty: Ref['a] -> Ref[('a & 'b)..'b] -> unit\n//│ ║        \t                                       ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.27: \tdef move_ty: Ref['a] -> Ref[('a & 'b)..'b] -> unit\n//│ ║        \t                 ^^\n//│ ╟── from field selection:\n//│ ║  l.21: \tdef move a b = a.Set b.Get\n//│ ║        \t                     ^^^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.3: \tclass Ref[A]\n//│ ╙──     \t          ^\n//│        = [Function: move]\n\ndef move_approx: Ref['a] -> Ref['a] -> unit\nmove_approx = move\n//│ move_approx: Ref['a] -> Ref['a] -> unit\n//│            = <missing implementation>\n//│ Ref['A] -> Ref['A0] -> unit\n//│   where\n//│     'A0 <: 'A\n//│   <:  move_approx:\n//│ Ref['a] -> Ref['a] -> unit\n//│            = [Function: move]\n\ndef move_bad: Ref['a] -> Ref['a..('a & 'b)] -> unit\n//│ move_bad: Ref['a] -> Ref['a] -> unit\n//│         = <missing implementation>\n// :e // * Doesn't work with existential wildcards\nmove_bad = move\n//│ Ref['A] -> Ref['A0] -> unit\n//│   where\n//│     'A0 <: 'A\n//│   <:  move_bad:\n//│ Ref['a] -> Ref['a] -> unit\n//│         = [Function: move]\n\n\nr = RefImpl{mut value = 1}\n//│ r: RefImpl['A] with {mut value: 'value}\n//│   where\n//│     'value :> 1\n//│            <: 'A\n//│     'A :> 1\n//│  = RefImpl { value: 1 }\n\nri = r : Ref[int]\nrn = r : Ref[number]\n//│ ri: Ref[int]\n//│   = RefImpl { value: 1 }\n//│ rn: Ref[number]\n//│   = RefImpl { value: 1 }\n\n(r.Get, r.Set, r.Swap)\n//│ res: (1, anything -> unit, 'A -> (1 | 'A),)\n//│    = [ 1, [Function: Set], [Function: Swap] ]\n\nmove r\nmove_ty r\nmove_approx r\n//│ res: Ref['A] -> unit\n//│    = [Function (anonymous)]\n//│ res: Ref['b] -> unit\n//│    = [Function (anonymous)]\n//│ res: Ref['a] -> unit\n//│   where\n//│     'a :> 1\n//│    = [Function (anonymous)]\n\nmove ri\nmove_ty ri\nmove_approx ri\n//│ res: Ref['A] -> unit\n//│   where\n//│     'A <: int\n//│    = [Function (anonymous)]\n//│ res: Ref[in int & 'b out 'b] -> unit\n//│    = [Function (anonymous)]\n//│ res: Ref[int] -> unit\n//│    = [Function (anonymous)]\n\nfun x -> move x r\nfun x -> move_ty x r\nfun x -> move_approx x r\n//│ res: Ref['A] -> unit\n//│   where\n//│     'A :> 1\n//│    = [Function: res]\n//│ res: Ref['a] -> unit\n//│   where\n//│     'a :> 1\n//│    = [Function: res]\n//│ res: Ref['a] -> unit\n//│   where\n//│     'a :> 1\n//│    = [Function: res]\n\nfun x -> move x ri\nfun x -> move_ty x ri\nfun x -> move_approx x ri\n//│ res: Ref['A] -> unit\n//│   where\n//│     'A :> int\n//│    = [Function: res]\n//│ res: Ref['a] -> unit\n//│   where\n//│     'a :> int\n//│    = [Function: res]\n//│ res: Ref[int] -> unit\n//│    = [Function: res]\n\nmove r ri\nmove rn r\nmove rn ri\n//│ = undefined\n//│ = undefined\n//│ = undefined\n\n:e\nmove ri rn\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.159: \tmove ri rn\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.87: \trn = r : Ref[number]\n//│ ║        \t             ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.86: \tri = r : Ref[int]\n//│ ║        \t             ^^^\n//│ ╟── from field selection:\n//│ ║  l.21: \tdef move a b = a.Set b.Get\n//│ ║        \t                     ^^^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.3: \tclass Ref[A]\n//│ ╙──     \t          ^\n//│ res: error | unit\n//│    = undefined\n\n\ndef swap a b = let tmp = a.Get in (a.Set b.Get, b.Set tmp)\n//│ swap: Ref[in 'A & 'A0 out 'A | 'A0] -> Ref[in 'A1 & 'A0 out 'A | 'A1] -> (unit, unit,)\n//│     = [Function: swap]\n\nswap r\nswap ri\nswap rn\n//│ res: Ref[in 'A out 1 | 'A] -> (unit, unit,)\n//│    = [Function (anonymous)]\n//│ res: Ref[int] -> (unit, unit,)\n//│    = [Function (anonymous)]\n//│ res: Ref[number] -> (unit, unit,)\n//│    = [Function (anonymous)]\n\nswap r ri\nswap ri r\n//│ res: (unit, unit,)\n//│    = [ undefined, undefined ]\n//│ res: (unit, unit,)\n//│    = [ undefined, undefined ]\n\n:e\nswap rn ri\nswap ri rn\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.201: \tswap rn ri\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.87: \trn = r : Ref[number]\n//│ ║        \t             ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.86: \tri = r : Ref[int]\n//│ ╙──      \t             ^^^\n//│ res: error | (unit, unit,)\n//│    = [ undefined, undefined ]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.202: \tswap ri rn\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.87: \trn = r : Ref[number]\n//│ ║        \t             ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.86: \tri = r : Ref[int]\n//│ ║        \t             ^^^\n//│ ╟── from field selection:\n//│ ║  l.179: \tdef swap a b = let tmp = a.Get in (a.Set b.Get, b.Set tmp)\n//│ ║         \t                                         ^^^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.3: \tclass Ref[A]\n//│ ╙──     \t          ^\n//│ res: error | (unit, unit,)\n//│    = [ undefined, undefined ]\n\n\n\ndef refin: Ref[int] & Ref[string]\n//│ refin: in Ref[out int | string] out Ref[in int | string out nothing]\n//│      = <missing implementation>\n\nrefin.Get\n//│ res: nothing\n//│    = <no result>\n//│      refin is not implemented\n\nfun x -> refin.Set x\n//│ res: (int | string) -> unit\n//│    = <no result>\n//│      refin is not implemented\n\nrefin.Swap\n//│ res: ('A & (int | string)) -> 'A\n//│    = <no result>\n//│      refin is not implemented\n\nrefin: Ref['a..'b]\n//│ res: Ref[in 'b & (int | string) out 'b]\n//│    = <no result>\n//│      refin is not implemented\n\nres.Swap\n//│ res: ((int | string) & 'A) -> 'A\n//│    = undefined\n\nrefin: Ref['a..'b] & Ref['c..'d]\n//│ res: Ref[in 'd & (int | string) | 'b & (int | string) out 'b & 'd]\n//│    = <no result>\n//│      refin is not implemented\n\n:ng\nres.Swap\n//│ res: ('A & ((int | string) & 'b | 'd & (int | string))) -> ('b & 'd | 'A)\n\nrefin: Ref['a..'b] | Ref['c..'d]\n//│ res: Ref[in 'd & (int | string | ~'d) out 'd]\n//│    = <no result>\n//│      refin is not implemented\n\n:ng\nres.Swap\n//│ res: 'A -> 'A\n\n\ndef refrefin: Ref[Ref[int] & Ref[string]]\n//│ refrefin: Ref[in Ref[out int | string] out Ref[in int | string out nothing]]\n//│         = <missing implementation>\n\n:re\nrefrefin = RefImpl { mut value = error }\n//│ RefImpl['A] with {mut value: 'value}\n//│   where\n//│     'value <: 'A\n//│   <:  refrefin:\n//│ Ref[in Ref[out int | string] out Ref[in int | string out nothing]]\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:e\nrefrefin = RefImpl { mut value = RefImpl { mut value = error } }\n//│ RefImpl['A] with {mut value: 'value}\n//│   where\n//│     'value :> RefImpl['A0] with {mut value: 'value0}\n//│            <: 'A\n//│     'A :> RefImpl['A0] with {mut value: 'value0}\n//│     'value0 <: 'A0\n//│   <:  refrefin:\n//│ Ref[in Ref[out int | string] out Ref[in int | string out nothing]]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.296: \trefrefin = RefImpl { mut value = RefImpl { mut value = error } }\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `int` does not match type `nothing`\n//│ ║  l.281: \tdef refrefin: Ref[Ref[int] & Ref[string]]\n//│ ╙──       \t                      ^^^\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\ndef consrefin: (Ref[int] & Ref[string]) -> int\n//│ consrefin: in Ref[in int | string out nothing] -> int out Ref[out int | string] -> int\n//│          = <missing implementation>\n\n:e\nconsrefin (RefImpl { mut value = error })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.320: \tconsrefin (RefImpl { mut value = error })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.315: \tdef consrefin: (Ref[int] & Ref[string]) -> int\n//│ ║         \t                               ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.315: \tdef consrefin: (Ref[int] & Ref[string]) -> int\n//│ ║         \t                    ^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.12: \tclass RefImpl[A]: Ref[A] & { mut value: A }\n//│ ╙──      \t              ^\n//│ res: error | int\n//│    = <no result>\n//│      consrefin is not implemented\n\n\n\ndef refun: Ref[int] | Ref[string]\n//│ refun: Ref[out int | string]\n//│      = <missing implementation>\n\n// * Errors happen because we constrain `Ref[int] | Ref[string] <: Ref['A]`\n// * ie `Ref[int & string .. int | string] <: Ref['A]`\n// * ie `int & string .. int | string <: 'A` and `'A <: int & string .. int | string`\n// * ie `int | string <: 'A` and `'A <: int & string`\n:e\nrefun.Get\nfun x -> refun.Set x\nrefun.Swap\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.348: \trefun.Get\n//│ ║         \t^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.339: \tdef refun: Ref[int] | Ref[string]\n//│ ║         \t                          ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.339: \tdef refun: Ref[int] | Ref[string]\n//│ ║         \t               ^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.3: \tclass Ref[A]\n//│ ╙──     \t          ^\n//│ res: error | int | string\n//│    = <no result>\n//│      refun is not implemented\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.349: \tfun x -> refun.Set x\n//│ ║         \t         ^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.339: \tdef refun: Ref[int] | Ref[string]\n//│ ║         \t                          ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.339: \tdef refun: Ref[int] | Ref[string]\n//│ ║         \t               ^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.3: \tclass Ref[A]\n//│ ╙──     \t          ^\n//│ res: nothing -> (error | unit)\n//│    = <no result>\n//│      refun is not implemented\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.350: \trefun.Swap\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.339: \tdef refun: Ref[int] | Ref[string]\n//│ ║         \t                          ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.339: \tdef refun: Ref[int] | Ref[string]\n//│ ║         \t               ^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.3: \tclass Ref[A]\n//│ ╙──     \t          ^\n//│ res: error | nothing -> (int | string)\n//│    = <no result>\n//│      refun is not implemented\n\n\n\n:e\ndef bar x = RefImpl { mut value = x } : Ref[int] & Ref[string]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.400: \tdef bar x = RefImpl { mut value = x } : Ref[int] & Ref[string]\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `string` is not an instance of type `int`\n//│ ║  l.400: \tdef bar x = RefImpl { mut value = x } : Ref[int] & Ref[string]\n//│ ║         \t                                                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.400: \tdef bar x = RefImpl { mut value = x } : Ref[int] & Ref[string]\n//│ ║         \t                                            ^^^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.12: \tclass RefImpl[A]: Ref[A] & { mut value: A }\n//│ ╙──      \t              ^\n//│ bar: nothing -> Ref[in int | string out nothing]\n//│    = [Function: bar]\n\n// * Note that this now signature-checks because it instantiates the inferred polymorphic type\n// * later (once for each intersection component)\n// :e\nrec def refin = RefImpl { mut value = refin.Get }\n//│ RefImpl['A]\n//│   <:  refin:\n//│ Ref[out int | string]\n//│      = [Function: refin]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Repro.mls",
    "content": ":NewDefs\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/RigidVariables.mls",
    "content": "\n\n:e\ndef foo[AAA]: AAA -> AAA\ndef foo(x) = x.a\n//│ foo: 'a -> 'a\n//│    = <missing implementation>\n//│ {a: 'a} -> 'a\n//│   <:  foo:\n//│ 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.5: \tdef foo(x) = x.a\n//│ ║       \t^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `?a` does not have field 'a'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.5: \tdef foo(x) = x.a\n//│ ║       \t             ^^^\n//│ ╟── from reference:\n//│ ║  l.5: \tdef foo(x) = x.a\n//│ ╙──     \t             ^\n//│    = [Function: foo]\n\n:e\nclass Test0\n  method Foo0[AAA]: AAA -> AAA\n  method Foo0(x) = x.a\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.26: \t  method Foo0(x) = x.a\n//│ ║        \t         ^^^^^^^^^^^^^\n//│ ╟── type `AAA` does not have field 'a'\n//│ ║  l.25: \t  method Foo0[AAA]: AAA -> AAA\n//│ ║        \t              ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.26: \t  method Foo0(x) = x.a\n//│ ║        \t                   ^^^\n//│ ╟── from reference:\n//│ ║  l.26: \t  method Foo0(x) = x.a\n//│ ╙──      \t                   ^\n//│ Defined class Test0\n//│ Declared Test0.Foo0: Test0 -> 'AAA -> 'AAA\n//│ Defined Test0.Foo0: Test0 -> {a: 'a} -> 'a\n\nclass Test1\n  method Foo1[AAA]: (AAA & {a: int}) -> int\n  method Foo1(x) = x.a\n//│ Defined class Test1\n//│ Declared Test1.Foo1: Test1 -> {a: int} -> int\n//│ Defined Test1.Foo1: Test1 -> {a: 'a} -> 'a\n\n:e\n(Test1{}).Foo1({x=1})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.51: \t(Test1{}).Foo1({x=1})\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{x: 1}` does not have field 'a'\n//│ ║  l.51: \t(Test1{}).Foo1({x=1})\n//│ ║        \t               ^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.44: \t  method Foo1[AAA]: (AAA & {a: int}) -> int\n//│ ║        \t                           ^^^^^^^^\n//│ ╟── from intersection type:\n//│ ║  l.44: \t  method Foo1[AAA]: (AAA & {a: int}) -> int\n//│ ╙──      \t                    ^^^^^^^^^^^^^^^^\n//│ res: error | int\n//│    = undefined\n\n(Test1{}).Foo1({a=1})\n//│ res: int\n//│    = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/SafeDiv.mls",
    "content": "\n:e\ndef safeDiv x (y: ~0) = div x y\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.3: \tdef safeDiv x (y: ~0) = div x y\n//│ ║       \t                        ^^^^^^^\n//│ ╟── type `~0` is not an instance of type `int`\n//│ ║  l.3: \tdef safeDiv x (y: ~0) = div x y\n//│ ║       \t                  ^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.3: \tdef safeDiv x (y: ~0) = div x y\n//│ ╙──     \t                              ^\n//│ safeDiv: int -> ~0 -> (error | int)\n//│        = [Function: safeDiv]\n\ndef safeDiv x (y: int & ~0) = div x y\n//│ safeDiv: int -> (int & ~0) -> int\n//│        = [Function: safeDiv1]\n\n:e\nsafeDiv 1 0\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.21: \tsafeDiv 1 0\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── integer literal of type `0` does not match type `~0`\n//│ ║  l.21: \tsafeDiv 1 0\n//│ ║        \t          ^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.16: \tdef safeDiv x (y: int & ~0) = div x y\n//│ ║        \t                        ^^\n//│ ╟── from intersection type:\n//│ ║  l.16: \tdef safeDiv x (y: int & ~0) = div x y\n//│ ╙──      \t                  ^^^^^^^^\n//│ res: error | int\n//│    = Infinity\n\nfun x -> safeDiv 1 x\n//│ res: (int & ~0) -> int\n//│    = [Function: res]\n\n\nclass None: {}\nclass Some[A]: { value: A }\ntype Option[A] = Some[A] | None\n//│ Defined class None\n//│ Defined class Some[+A]\n//│ Defined type alias Option[+A]\n\n\nfun x -> case x of { int -> safeDiv 1 x | _ -> None{} }\n//│ res: (int & ~0 | ~int) -> (None | int)\n//│    = [Function: res]\n\n:e // we no longer refine x's type here, as that was rather unexpected\nfun (x: int) -> safeDiv 1 x\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.55: \tfun (x: int) -> safeDiv 1 x\n//│ ║        \t                ^^^^^^^^^^^\n//│ ╟── type `int` does not match type `~0`\n//│ ║  l.55: \tfun (x: int) -> safeDiv 1 x\n//│ ║        \t        ^^^\n//│ ╟── but it flows into reference with expected type `~0`\n//│ ║  l.55: \tfun (x: int) -> safeDiv 1 x\n//│ ║        \t                          ^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.16: \tdef safeDiv x (y: int & ~0) = div x y\n//│ ║        \t                        ^^\n//│ ╟── from intersection type:\n//│ ║  l.16: \tdef safeDiv x (y: int & ~0) = div x y\n//│ ╙──      \t                  ^^^^^^^^\n//│ res: int -> (error | int)\n//│    = [Function: res]\n\nfun (x: int & ~0) -> safeDiv 1 x\n//│ res: (int & ~0) -> int\n//│    = [Function: res]\n\ndef tryDiv: int -> int -> Option[int]\n//│ tryDiv: int -> int -> Option[int]\n//│       = <missing implementation>\n\ndef tryDiv x y = case y of { 0 -> None{} | _ -> Some { value = safeDiv x y } }\n//│ int -> (0 | int & ~0) -> (None | Some[int])\n//│   <:  tryDiv:\n//│ int -> int -> Option[int]\n//│       = [Function: tryDiv]\n// ^ Note: `0 | int & ~0` could be further simplified\n\ntryDiv 1 1\ntryDiv 1 0\n//│ res: Option[int]\n//│    = Some { value: 1 }\n//│ res: Option[int]\n//│    = None {}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Scratch.mls",
    "content": ""
  },
  {
    "path": "shared/src/test/diff/mlscript/SelfNeg.mls",
    "content": "\n\ndef foo: ('a -> (~'a -> 'b) -> 'b) -> 'b\n//│ foo: (nothing -> (anything -> 'b) -> 'b) -> 'b\n//│    = <missing implementation>\n\ndef foo: ('a -> (~'a -> 'a) -> 'a) -> 'a -> 'a\n//│ foo: ('a -> (~'a -> 'a) -> 'a) -> 'a -> 'a\n//│    = <missing implementation>\n\n:ns\nfoo\n//│ res: forall 'a. ('a -> (~'a -> 'a) -> 'a) -> 'a -> 'a\n//│    = <no result>\n//│      foo is not implemented\n\n:ns\nr = foo (fun a -> fun f -> f a)\n//│ r: forall 'b 'a 'c 'd. 'b\n//│   where\n//│     'b :> 'a -> 'a\n//│     'a <: 'd & 'c\n//│     'c <: ~'a\n//│     'd <: 'a\n//│  = <no result>\n//│    foo is not implemented\n\nr\n//│ res: 'a -> 'a\n//│    = <no result>\n//│      r and foo are not implemented\n\n:e\nr: anything -> nothing\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.34: \tr: anything -> nothing\n//│ ║        \t^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.34: \tr: anything -> nothing\n//│ ║        \t   ^^^^^^^^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.7: \tdef foo: ('a -> (~'a -> 'a) -> 'a) -> 'a -> 'a\n//│ ║       \t                 ^^^\n//│ ╟── from type variable:\n//│ ║  l.7: \tdef foo: ('a -> (~'a -> 'a) -> 'a) -> 'a -> 'a\n//│ ╙──     \t                                      ^^\n//│ res: anything -> nothing\n//│    = <no result>\n//│      r and foo are not implemented\n\n\n\ndef foo: ('a -> (~'a -> anything) -> anything) -> MutArray['a]\n//│ foo: ('a -> (~'a -> anything) -> anything) -> MutArray['a]\n//│    = <missing implementation>\n\n:ns\nr = foo (fun a -> fun f -> f a)\n//│ r: forall 'b 'a 'c. 'b\n//│   where\n//│     'b :> MutArray['a]\n//│     'a <: 'c\n//│     'c <: ~'a\n//│  = <no result>\n//│    foo is not implemented\n\n:e\nr[0] <- \"test\"\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.68: \tr[0] <- \"test\"\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"test\"` does not match type `~\"test\"`\n//│ ║  l.68: \tr[0] <- \"test\"\n//│ ║        \t        ^^^^^^\n//│ ╟── but it flows into assigned array element with expected type `~\"test\"`\n//│ ║  l.68: \tr[0] <- \"test\"\n//│ ╙──      \t^^^^\n//│ = <no result>\n//│   r and foo are not implemented\n\n:e\nr[0] + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.82: \tr[0] + 1\n//│ ║        \t^^^^^^\n//│ ╟── possibly-undefined array access of type `undefined` is not an instance of type `int`\n//│ ║  l.82: \tr[0] + 1\n//│ ╙──      \t^^^^\n//│ res: error | int\n//│    = <no result>\n//│      r and foo are not implemented\n\n\n\n\n:ns\ndef bar: (('a & ~'a) -> 'b) -> 'b\n//│ bar: forall 'b. (nothing -> 'b) -> 'b\n//│    = <missing implementation>\n\ndef bar: (('a & int & ~'a) -> 'b) -> 'b\n//│ bar: ((int & 'a & ~'a) -> 'b) -> 'b\n//│    = <missing implementation>\n\nr = bar (fun x -> (x, x + 1, not x, x x))\n//│ r: (int & 'a & ~'a, int, bool, nothing,)\n//│  = <no result>\n//│    bar is not implemented\n\n:ns\nr\n//│ res: forall 'b 'a 'c 'd. 'b\n//│   where\n//│     'b :> forall 'e 'f. ('c, 'e, 'f, 'd,)\n//│     'f :> bool\n//│     'e :> int\n//│     'c :> 'a & int & ~'a\n//│        <: 'c -> 'd & bool & int\n//│     'a <: (bool | ~(int & ~'a)) & ('c -> 'd | ~(int & ~'a))\n//│    = <no result>\n//│      r and bar are not implemented\n\nr.0 : nothing\n//│ res: nothing\n//│    = <no result>\n//│      r and bar are not implemented\n\ndef impossible x = case x of {}\n//│ impossible: nothing -> nothing\n//│           = [Function: impossible]\n\nbar impossible\n//│ res: nothing\n//│    = <no result>\n//│      bar is not implemented\n\n\ndef k: 'a -> 'a\n//│ k: 'a -> 'a\n//│  = <missing implementation>\n\n:e\nk = impossible\n//│ nothing -> nothing\n//│   <:  k:\n//│ 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.143: \tk = impossible\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── type `'a` does not match type `nothing`\n//│ ║  l.138: \tdef k: 'a -> 'a\n//│ ║         \t       ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.128: \tdef impossible x = case x of {}\n//│ ╙──       \t                        ^\n//│  = [Function: impossible]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/SelfNegs.mls",
    "content": "\n// * Here the two occurrences of `'a` in different types are separate:\ndef foo(f: (~'a) -> 'a, a: 'a) =\n  f a\n//│ foo: (~'a -> 'a, ~'a,) -> 'a\n//│    = [Function: foo]\n\ndef foo(fa: ((~'a) -> 'a, 'a)) =\n  fa.0 fa.1\n//│ foo: ((~'a -> 'a, 'a,),) -> 'a\n//│    = [Function: foo1]\n\n:ns\nfoo\n//│ res: forall 'a 'b 'c. ((~'a -> 'a, 'a,),) -> 'c\n//│   where\n//│     'a <: 'c & 'b\n//│     'b <: ~'a\n//│    = [Function: foo1]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Seqs.mls",
    "content": ":w\nclass Seq[A]: { size: int }\n//│ Defined class Seq[±A]\n//│ ╔══[WARNING] Type definition Seq has bivariant type parameters:\n//│ ║  l.2: \tclass Seq[A]: { size: int }\n//│ ║       \t      ^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.2: \tclass Seq[A]: { size: int }\n//│ ╙──     \t          ^\n\n:w\nclass ListBase[A]: Seq[A]\n//│ Defined class ListBase[±A]\n//│ ╔══[WARNING] Type definition ListBase has bivariant type parameters:\n//│ ║  l.12: \tclass ListBase[A]: Seq[A]\n//│ ║        \t      ^^^^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.12: \tclass ListBase[A]: Seq[A]\n//│ ╙──      \t               ^\n\nclass Nil: ListBase[nothing] & {}\nclass Cons[A]: ListBase[A] & { head: A; tail: List[A] }\ntype List[A] = Nil | Cons[A]\n//│ Defined class Nil\n//│ Defined class Cons[+A]\n//│ Defined type alias List[+A]\n\n:e\nNil{}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.29: \tNil{}\n//│ ║        \t^^^^^\n//│ ╟── record literal of type `anything` does not have field 'size'\n//│ ║  l.29: \tNil{}\n//│ ╙──      \t   ^^\n//│ res: Nil & {size: nothing} | error\n//│    = Nil { size: undefined }\n\ndef Nil = Nil { size = 0 }\n//│ Nil: Nil & {size: 0}\n//│    = [Function: Nil1]\n\n:e\n:re\nCons 1 Nil\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.45: \tCons 1 Nil\n//│ ║        \t^^^^^^\n//│ ╟── integer literal of type `1` is not a record (expected a record with fields: size, tail, head)\n//│ ║  l.45: \tCons 1 Nil\n//│ ╙──      \t     ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.45: \tCons 1 Nil\n//│ ║        \t^^^^^^^^^^\n//│ ╟── application of type `Cons[?A] & {Cons#A = ?A, head: ?head, size: ?size, tail: ?tail}` is not a function\n//│ ║  l.45: \tCons 1 Nil\n//│ ╙──      \t^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: (intermediate value) is not a function\n\nCons\n//│ res: {head: 'A & 'head, size: int & 'size, tail: List['A] & 'tail} -> (Cons['A] with {head: 'head, size: 'size, tail: 'tail})\n//│    = [Function: res]\n\n// In the old inheritance semantics, this used to be required:\ndef Cons_old head tail =\n  Cons (ListBase (Seq { size = succ tail.size }) with { head; tail })\n//│ Cons_old: ('head & 'A) -> (List['A] & {size: int} & 'tail) -> (Cons['A] with {head: 'head, tail: 'tail})\n//│         = [Function: Cons_old]\n\ndef Cons head tail =\n  Cons { size = succ tail.size; head; tail }\n//│ Cons: ('head & 'A) -> (List['A] & {size: int} & 'tail) -> (Cons['A] with {head: 'head, tail: 'tail})\n//│     = [Function: Cons1]\n\n// * Works thanks to variance analysis\nNil: ListBase[anything]\n//│ res: ListBase[?]\n//│    = Nil { size: 0 }\n\nc = Cons 1 Nil\n//│ c: Cons[1] with {tail: Nil & {size: 0}}\n//│  = Cons { size: 1, head: 1, tail: Nil { size: 0 } }\n\nc: ListBase[int]\n//│ res: ListBase[?]\n//│    = Cons { size: 1, head: 1, tail: Nil { size: 0 } }\n\nc.head\n//│ res: 1\n//│    = 1\n\nc.tail\n//│ res: Nil & {size: 0}\n//│    = Nil { size: 0 }\n\nc.size\n//│ res: int\n//│    = 1\n\nd = Cons 2 c\n//│ d: Cons[1 | 2] with {head: 2, tail: Cons[1] with {tail: Nil & {size: 0}}}\n//│  = Cons {\n//│      size: 2,\n//│      head: 2,\n//│      tail: Cons { size: 1, head: 1, tail: Nil { size: 0 } }\n//│    }\n\nd.head\n//│ res: 2\n//│    = 2\n\nd.size\n//│ res: int\n//│    = 2\n\nd.tail\n//│ res: Cons[1] with {tail: Nil & {size: 0}}\n//│    = Cons { size: 1, head: 1, tail: Nil { size: 0 } }\n\nd.tail.size\n//│ res: int\n//│    = 1\n\nd.tail.head\nd.tail.tail\n//│ res: 1\n//│    = 1\n//│ res: Nil & {size: 0}\n//│    = Nil { size: 0 }\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Sequence.mls",
    "content": ":NewDefs\n\n\n:e\nlet test(x) = log(x); x + 1\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.5: \tlet test(x) = log(x); x + 1\n//│ ╙──     \t                      ^\n//│ let test: anything -> ()\n//│ Int\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\nlet test(x) = log(x), x + 1\n//│ let test: Int -> Int\n//│ test\n//│      = [Function: test1]\n\ntest(1)\n//│ Int\n//│ res\n//│     = 2\n//│ // Output\n//│ 1\n\n:pe\n:e\ntest(log(\"here we go\"); 123)\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.28: \ttest(log(\"here we go\"); 123)\n//│ ╙──      \t                      ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.28: \ttest(log(\"here we go\"); 123)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `()` is not an instance of type `Int`\n//│ ║  l.28: \ttest(log(\"here we go\"); 123)\n//│ ║        \t     ^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.14: \tlet test(x) = log(x), x + 1\n//│ ╙──      \t                      ^\n//│ Int | error\n//│ res\n//│     = NaN\n//│ // Output\n//│ here we go\n//│ undefined\n\ntest((log(\"here we go\"), 123))\n//│ Int\n//│ res\n//│     = 124\n//│ // Output\n//│ here we go\n//│ 123\n\n\nlet a = 1; let b = a + 1\n//│ let a: 1\n//│ let b: Int\n//│ a\n//│   = 1\n//│ b\n//│   = 2\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Signatures.mls",
    "content": "\ndef foo: int -> (string -> anything)\n//│ foo: int -> string -> anything\n//│    = <missing implementation>\n\ndef foo: int -> string -> anything\n//│ foo: int -> string -> anything\n//│    = <missing implementation>\n\ndef foo: (int -> string) -> anything\n//│ foo: (int -> string) -> anything\n//│    = <missing implementation>\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Simple.mls",
    "content": "\na = 1\nb = 2\nc = 3\n//│ a: 1\n//│  = 1\n//│ b: 2\n//│  = 2\n//│ c: 3\n//│  = 3\n\nif true then if true then a else b else a\n//│ res: 1 | 2\n//│    = 1\n\nif true then if true then id a else id b else a\n//│ res: 1 | 2\n//│    = 1\n\nclass Foo[A]: { field: A }\nclass Bar: {}\n//│ Defined class Foo[+A]\n//│ Defined class Bar\n\nfoo = Foo { field = id 1 }\n//│ foo: Foo[1]\n//│    = Foo { field: 1 }\n\n(if true then foo else { field = 2 }).field\n//│ res: 1 | 2\n//│    = 1\n\nFoo { field = id 1 }\n//│ res: Foo[1]\n//│    = Foo { field: 1 }\n\ndef test x = case x of { Bar -> 1 | Foo -> 2 }\n//│ test: (Bar | Foo[?]) -> (1 | 2)\n//│     = [Function: test]\n\ntest foo\n//│ res: 1 | 2\n//│    = 2\n\ndef test x = case x of { Bar -> 1 | Foo -> x.field }\n//│ test: (Bar | Foo[?] & {field: 'field}) -> (1 | 'field)\n//│     = [Function: test1]\n\ntest foo\n//│ res: 1\n//│    = 1\n\ntest (Foo { field = 2 })\n//│ res: 1 | 2\n//│    = 2\n\ndef test x = case x of { Foo -> x.field | _ -> 1 }\n//│ test: (Foo[?] & {field: 'field} | ~Foo[?]) -> (1 | 'field)\n//│     = [Function: test2]\n\n\ndef f x = x.u\n//│ f: {u: 'u} -> 'u\n//│  = [Function: f]\n\nf { u = 1 }\n//│ res: 1\n//│    = 1\n\nf { u = 1; v = 2 }\n//│ res: 1\n//│    = 1\n\nf (if true then { u = 1; v = 2 } else { u = 1 })\n//│ res: 1\n//│    = 1\n\nif true then { u = 1; v = 2 } else { u = 2 }\n//│ res: {u: 1 | 2}\n//│    = { u: 1, v: 2 }\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/SimpleErrors.mls",
    "content": ":AllowTypeErrors\n\nsucc false\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.3: \tsucc false\n//│ ║       \t^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.3: \tsucc false\n//│ ╙──     \t     ^^^^^\n//│ res: error | int\n\nx = \"oops\"\n//│ x: \"oops\"\n\nf y = succ y\n//│ f: int -> int\n\n:e\nf x\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.19: \tf x\n//│ ║        \t^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.12: \tx = \"oops\"\n//│ ║        \t    ^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.19: \tf x\n//│ ║        \t  ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.15: \tf y = succ y\n//│ ╙──      \t           ^\n//│ res: error | int\n\n\n\ntrait MyTrait: { value: anything }\n//│ Defined trait MyTrait\n\ndef test1 x = case x of { MyTrait -> x.value | _ -> 0 }\n//│ test1: ({value: 'value} & #MyTrait | ~#MyTrait) -> (0 | 'value)\n\n:e\ntest1 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.43: \ttest1 1\n//│ ║        \t^^^^^^^\n//│ ╟── expression of type `1 & ~?a | 1 & #MyTrait` does not have field 'value'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.39: \tdef test1 x = case x of { MyTrait -> x.value | _ -> 0 }\n//│ ║        \t                                     ^^^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.39: \tdef test1 x = case x of { MyTrait -> x.value | _ -> 0 }\n//│ ╙──      \t                   ^\n//│ res: 0 | error\n\n\ndef map: 'a -> 'a\ndef map f = f map (fun x -> map)\n//│ map: 'a -> 'a\n//│ ((forall 'a. 'a -> 'a) -> (forall 'a0. anything -> 'a0 -> 'a0) -> 'b) -> 'b\n//│   <:  map:\n//│ 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.58: \tdef map f = f map (fun x -> map)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not a function\n//│ ║  l.57: \tdef map: 'a -> 'a\n//│ ║        \t         ^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.58: \tdef map f = f map (fun x -> map)\n//│ ║        \t            ^^^^^\n//│ ╟── from reference:\n//│ ║  l.58: \tdef map f = f map (fun x -> map)\n//│ ╙──      \t            ^\n\n\nclass Bar\n    method Map[B]: B -> B\n    rec method Map f = f 1\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.79: \t    rec method Map f = f 1\n//│ ║        \t               ^^^^^^^^^^^\n//│ ╟── type `B` is not a function\n//│ ║  l.78: \t    method Map[B]: B -> B\n//│ ║        \t               ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.79: \t    rec method Map f = f 1\n//│ ║        \t                       ^^^\n//│ ╟── from reference:\n//│ ║  l.79: \t    rec method Map f = f 1\n//│ ╙──      \t                       ^\n//│ Defined class Bar\n//│ Declared Bar.Map: Bar -> 'B -> 'B\n//│ Defined Bar.Map: Bar -> (1 -> 'a) -> 'a\n\n\ndef boom: anything\n//│ boom: anything\n\n// :d\n:e\nadd boom 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.102: \tadd boom 1\n//│ ║         \t^^^^^^^^\n//│ ╟── type `anything` is not an instance of type `int`\n//│ ║  l.97: \tdef boom: anything\n//│ ║        \t          ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.102: \tadd boom 1\n//│ ╙──       \t    ^^^^\n//│ res: error | int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/SimpleMethods.mls",
    "content": "\n:e\nclass C0\n  method Foo0[A](a: A) = a + 1\n  method Foo1[A](a: A) = { a }\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.4: \t  method Foo0[A](a: A) = a + 1\n//│ ║       \t                         ^^^\n//│ ╟── reference of type `#A` is not an instance of type `int`\n//│ ║  l.4: \t  method Foo0[A](a: A) = a + 1\n//│ ║       \t                         ^\n//│ ╟── Note: method type parameter A is defined at:\n//│ ║  l.4: \t  method Foo0[A](a: A) = a + 1\n//│ ╙──     \t              ^\n//│ Defined class C0\n//│ Defined C0.Foo0: C0 -> anything -> (error | int)\n//│ Defined C0.Foo1: C0 -> 'A -> {a: 'A}\n\n(C0{}).Foo0\n//│ res: anything -> (error | int)\n//│    = [Function: Foo0]\n\nf1 = (C0{}).Foo1\n//│ f1: 'A -> {a: 'A}\n//│   = [Function: Foo1]\n\nf1 1\n//│ res: {a: 1}\n//│    = { a: 1 }\n\n\nclass C1\n  method F: int\n  method F = 1\n//│ Defined class C1\n//│ Declared C1.F: C1 -> int\n//│ Defined C1.F: C1 -> 1\n\nclass C2: C1\n  method F = 2\n//│ Defined class C2\n//│ Defined C2.F: C2 -> 2\n\n\nclass C3\n  method F: 'a -> 'a\n  method F = id\n//│ Defined class C3\n//│ Declared C3.F: C3 -> 'a -> 'a\n//│ Defined C3.F: C3 -> 'a -> 'a\n\nclass C4: C3\n  method F = id\n//│ Defined class C4\n//│ Defined C4.F: C4 -> 'a -> 'a\n\n\n:e\nclass C5[A]\n  method F(x: A) = x + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.60: \t  method F(x: A) = x + 1\n//│ ║        \t                   ^^^\n//│ ╟── reference of type `A` is not an instance of type `int`\n//│ ║  l.60: \t  method F(x: A) = x + 1\n//│ ║        \t                   ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.59: \tclass C5[A]\n//│ ╙──      \t         ^\n//│ Defined class C5[-A]\n//│ Defined C5.F: C5['A] -> 'A -> (error | int)\n\n\n:w\nclass Tru[A]\n    method Test f = true\n    method Tru = this.Test (fun x -> error)\n//│ Defined class Tru[±A]\n//│ Defined Tru.Test: Tru[?] -> anything -> true\n//│ Defined Tru.Tru: Tru[?] -> true\n//│ ╔══[WARNING] Type definition Tru has bivariant type parameters:\n//│ ║  l.75: \tclass Tru[A]\n//│ ║        \t      ^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.75: \tclass Tru[A]\n//│ ╙──      \t          ^\n\n\n:e\n:ge\nclass Hey\n    rec method A = B\n    rec method B = 1\n//│ ╔══[ERROR] identifier not found: B\n//│ ║  l.92: \t    rec method A = B\n//│ ╙──      \t                   ^\n//│ Defined class Hey\n//│ Defined Hey.A: Hey -> error\n//│ Defined Hey.B: Hey -> 1\n//│ Code generation encountered an error:\n//│   unresolved symbol B\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Splice.mls",
    "content": ":NoJS\n\ndef t1 : (int, ...Array[int], bool)\n//│ t1: (int, ...Array[int], bool)\n\ndef t2 : (int, ...(bool, int))\n//│ t2: (int, ...(bool, int,))\n\n:e\ndef t3 : (int, ...bool, mut int)\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.10: \tdef t3 : (int, ...bool, mut int)\n//│ ║        \t                  ^^^^\n//│ ╙── type `bool` does not match type `Array[?a]`\n//│ t3: (int, ...bool, int)\n\n:e\ndef t4 : (int, ...int, bool)\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.18: \tdef t4 : (int, ...int, bool)\n//│ ║        \t                  ^^^\n//│ ╙── type `int` does not match type `Array[?a]`\n//│ t4: (int, ...int, bool)\n\ndef f1 : ('a, ...Array[int]) -> 'a\n//│ f1: ('a, ...Array[int]) -> 'a\n\n// TODO\ndef f1 (x, ...y) = x\n//│ ('a, ...Array[anything]) -> 'a\n//│   <:  f1:\n//│ ('a, ...Array[int]) -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.29: \tdef f1 (x, ...y) = x\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `('a, ...Array[int])` does not match type `(?a, ...?b)`\n//│ ║  l.25: \tdef f1 : ('a, ...Array[int]) -> 'a\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from splice:\n//│ ║  l.29: \tdef f1 (x, ...y) = x\n//│ ╙──      \t       ^^^^^^^^^\n\n:e\nerrt = (1, ...2, 3)\n//│ ╔══[ERROR] Type mismatch in splice:\n//│ ║  l.44: \terrt = (1, ...2, 3)\n//│ ║        \t       ^^^^^^^^^^^^\n//│ ╟── integer literal of type `2` does not match type `Array[?a]`\n//│ ║  l.44: \terrt = (1, ...2, 3)\n//│ ╙──      \t              ^\n//│ errt: (1, ...2, 3)\n\n:e\nwrerr = (1, ...true, mut 3)\n//│ ╔══[ERROR] Type mismatch in splice:\n//│ ║  l.54: \twrerr = (1, ...true, mut 3)\n//│ ║        \t        ^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` does not match type `Array[?a]`\n//│ ║  l.54: \twrerr = (1, ...true, mut 3)\n//│ ╙──      \t               ^^^^\n//│ wrerr: (1, ...true, 3)\n\ngt1 = (1, ...(1,2,3), 2)\n//│ gt1: (1, ...(1, 2, 3,), 2)\n\ngt1[0]\n//│ res: 1 | 2 | 3 | undefined\n\n//FIXME\ndef arr1: Array[int]\ngt2 = (...arr1)\n//│ arr1: Array[int]\n//│ gt2: (...Array[int])\n\n:e\n(1, ...(true, false), \"hi\") : Array[int | bool]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.76: \t(1, ...(true, false), \"hi\") : Array[int | bool]\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"hi\"` does not match type `bool | int`\n//│ ║  l.76: \t(1, ...(true, false), \"hi\") : Array[int | bool]\n//│ ║        \t                      ^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.76: \t(1, ...(true, false), \"hi\") : Array[int | bool]\n//│ ╙──      \t                                    ^^^^^^^^^^\n//│ res: Array[bool | int]\n\na1 = (1,2,3,4,5)\na2 = (1,2, ...a1, 4,5)\n//│ a1: (1, 2, 3, 4, 5,)\n//│ a2: (1, 2, ...(1, 2, 3, 4, 5,), 4, 5)\n\n// TODO\na2 : Array[int]\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: an implementation is missing\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Stress.mls",
    "content": ":NoJS\n\nclass A[T]: { fA: T }\nclass B[T]: { fB: T }\nclass C[T]: { fC: T }\nclass D[T]: { fD: T }\nclass E[T]: { fE: T }\nclass F[T]: { fF: T }\nclass G[T]: { fG: T }\nclass H[T]: { fH: T }\n//│ Defined class A[+T]\n//│ Defined class B[+T]\n//│ Defined class C[+T]\n//│ Defined class D[+T]\n//│ Defined class E[+T]\n//│ Defined class F[+T]\n//│ Defined class G[+T]\n//│ Defined class H[+T]\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  | G -> x.fG\n  | H -> x.fH\n  }\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA} | C[?] & {fC: 'fA} | D[?] & {fD: 'fA} | E[?] & {fE: 'fA} | F[?] & {fF: 'fA} | G[?] & {fG: 'fA} | H[?] & {fH: 'fA}) -> 'fA\n//│ constrain calls  : 26\n//│ annoying  calls  : 0\n//│ subtyping calls  : 986\n\n\n// ====== 1 & all ====== //\n\n// :stats\n// def arg: A[int]\n// foo arg\n// //│ arg: A[int]\n// //│ res: int | (nothing | (nothing | (nothing | (nothing | (nothing | (nothing | nothing))))))\n// //│ constrain calls: 55374\n// //│ annoying  calls: 423405\n\n// // Too long!\n// // :stats\n// // def arg: A[int] | B[int]\n// // foo arg\n\n\n// ====== 2 ====== //\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  }\ndef arg: A[int] | B[int]\nfoo arg\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA}) -> 'fA\n//│ arg: A[int] | B[int]\n//│ res: int\n//│ constrain calls  : 36\n//│ annoying  calls  : 20\n//│ subtyping calls  : 276\n\n\n// ====== 3 ====== //\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  }\ndef arg: A[int] | B[int] | C[int]\nfoo arg\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA} | C[?] & {fC: 'fA}) -> 'fA\n//│ arg: A[int] | B[int] | C[int]\n//│ res: int\n//│ constrain calls  : 48\n//│ annoying  calls  : 30\n//│ subtyping calls  : 522\n\n\n// ====== 4 ====== //\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  }\ndef arg: A[int] | B[int] | C[int] | D[int]\nfoo arg\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA} | C[?] & {fC: 'fA} | D[?] & {fD: 'fA}) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int]\n//│ res: int\n//│ constrain calls  : 60\n//│ annoying  calls  : 40\n//│ subtyping calls  : 852\n\n:stats\nfoo (arg with { x = 1} with { y = 2 })\n//│ res: int\n//│ constrain calls  : 35\n//│ annoying  calls  : 37\n//│ subtyping calls  : 369\n\n:stats\nfoo (arg with { x = 1; y = 2; z = 3 })\n//│ res: int\n//│ constrain calls  : 35\n//│ annoying  calls  : 37\n//│ subtyping calls  : 345\n\n\n// ====== 5 ====== //\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int]\nfoo arg\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA} | C[?] & {fC: 'fA} | D[?] & {fD: 'fA} | E[?] & {fE: 'fA}) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int]\n//│ res: int\n//│ constrain calls  : 72\n//│ annoying  calls  : 50\n//│ subtyping calls  : 1274\n\n\n// ====== 6 ====== //\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int]\nfoo arg\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA} | C[?] & {fC: 'fA} | D[?] & {fD: 'fA} | E[?] & {fE: 'fA} | F[?] & {fF: 'fA}) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int]\n//│ res: int\n//│ constrain calls  : 84\n//│ annoying  calls  : 60\n//│ subtyping calls  : 1796\n\n\n// ====== 7 ====== //\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  | G -> x.fG\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int]\nfoo arg\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA} | C[?] & {fC: 'fA} | D[?] & {fD: 'fA} | E[?] & {fE: 'fA} | F[?] & {fF: 'fA} | G[?] & {fG: 'fA}) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int]\n//│ res: int\n//│ constrain calls  : 96\n//│ annoying  calls  : 70\n//│ subtyping calls  : 2426\n\n\n// ====== 8 ====== //\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  | G -> x.fG\n  | H -> x.fH\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] | H[int]\nfoo arg\n//│ foo: (A[?] & {fA: 'fA} | B[?] & {fB: 'fA} | C[?] & {fC: 'fA} | D[?] & {fD: 'fA} | E[?] & {fE: 'fA} | F[?] & {fF: 'fA} | G[?] & {fG: 'fA} | H[?] & {fH: 'fA}) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] | H[int]\n//│ res: int\n//│ constrain calls  : 108\n//│ annoying  calls  : 80\n//│ subtyping calls  : 3172\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/StressDNF.mls",
    "content": ":NoJS\n\nclass A\nclass B\nclass C\nclass D\nclass E\n//│ Defined class A\n//│ Defined class B\n//│ Defined class C\n//│ Defined class D\n//│ Defined class E\n\ndef ty0: ('a & 'b & A | 'b & 'c & B | 'c & 'd & C | 'd & 'e & D | 'e & 'f & E) -> ('a, 'b, 'c, 'd, 'e, 'f)\n//│ ty0: (E & 'e & 'f | 'd & (C & 'c | D & 'e) | 'b & (A & 'a | B & 'c)) -> ('a, 'b, 'c, 'd, 'e, 'f,)\n\n:stats\nty0 = ty0\n//│ (E & 'e & 'f | 'd & (C & 'c | D & 'e) | 'b & (A & 'a | B & 'c)) -> ('a, 'b, 'c, 'd, 'e, 'f,)\n//│   <:  ty0:\n//│ (E & 'e & 'f | 'd & (C & 'c | D & 'e) | 'b & (A & 'a | B & 'c)) -> ('a, 'b, 'c, 'd, 'e, 'f,)\n//│ constrain calls  : 1\n//│ annoying  calls  : 0\n//│ subtyping calls  : 259\n\ndef ty1: ('a & A | 'b & B | 'c & C | 'd & D | 'e & E) -> ('a, 'b, 'c, 'd, 'e, 'f)\n//│ ty1: (A & 'a | B & 'b | C & 'c | D & 'd | E & 'e) -> ('a, 'b, 'c, 'd, 'e, nothing,)\n\n:stats\nty0 = ty1\n//│ (A & 'a | B & 'b | C & 'c | D & 'd | E & 'e) -> ('a, 'b, 'c, 'd, 'e, nothing,)\n//│   <:  ty0:\n//│ (E & 'e & 'f | 'd & (C & 'c | D & 'e) | 'b & (A & 'a | B & 'c)) -> ('a, 'b, 'c, 'd, 'e, 'f,)\n//│ constrain calls  : 45\n//│ annoying  calls  : 25\n//│ subtyping calls  : 1035\n\n:stats\n:e\nty1 = ty0\n//│ (E & 'e & 'f | 'd & (C & 'c | D & 'e) | 'b & (A & 'a | B & 'c)) -> ('a, 'b, 'c, 'd, 'e, 'f,)\n//│   <:  ty1:\n//│ (A & 'a | B & 'b | C & 'c | D & 'd | E & 'e) -> ('a, 'b, 'c, 'd, 'e, nothing,)\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.40: \tty1 = ty0\n//│ ║        \t^^^^^^^^^\n//│ ╟── type `A & 'a` does not match type `'b`\n//│ ║  l.26: \tdef ty1: ('a & A | 'b & B | 'c & C | 'd & D | 'e & E) -> ('a, 'b, 'c, 'd, 'e, 'f)\n//│ ║        \t          ^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.26: \tdef ty1: ('a & A | 'b & B | 'c & C | 'd & D | 'e & E) -> ('a, 'b, 'c, 'd, 'e, 'f)\n//│ ╙──      \t                                                              ^^\n//│ constrain calls  : 70\n//│ annoying  calls  : 51\n//│ subtyping calls  : 1048\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/StressTraits.mls",
    "content": ":NoJS\n\ntrait A[T]: { fA: T }\ntrait B[T]: { fB: T }\ntrait C[T]: { fC: T }\ntrait D[T]: { fD: T }\ntrait E[T]: { fE: T }\ntrait F[T]: { fF: T }\ntrait G[T]: { fG: T }\ntrait H[T]: { fH: T }\n//│ Defined trait A[+T]\n//│ Defined trait B[+T]\n//│ Defined trait C[+T]\n//│ Defined trait D[+T]\n//│ Defined trait E[+T]\n//│ Defined trait F[+T]\n//│ Defined trait G[+T]\n//│ Defined trait H[+T]\n\n:stats\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  | G -> x.fG\n  | H -> x.fH\n  }\n//│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | ~#E & ({fF: 'fA} & #F | ~#F & ({fG: 'fA} & #G | {fH: 'fA} & #H & ~#G))))))) -> 'fA\n//│ constrain calls  : 26\n//│ annoying  calls  : 0\n//│ subtyping calls  : 756\n\n\n// ====== 1 & all ====== //\n\n:stats\ndef arg: A[int]\nfoo arg\n//│ arg: A[int]\n//│ res: int\n//│ constrain calls  : 19\n//│ annoying  calls  : 9\n//│ subtyping calls  : 248\n\n:stats\n:e\ndef arg: A[int] | B[int]\nfoo arg\n//│ arg: A[int] | B[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.51: \tfoo arg\n//│ ║        \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.22: \t  | A -> x.fA\n//│ ║        \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.21: \tdef foo x = case x of {\n//│ ╙──      \t                 ^\n//│ res: error | int\n//│ constrain calls  : 36\n//│ annoying  calls  : 31\n//│ subtyping calls  : 724\n\n:stats\n:e\ndef arg: A[int] | B[int] | C[int]\nfoo arg\n//│ arg: A[int] | B[int] | C[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.71: \tfoo arg\n//│ ║        \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.22: \t  | A -> x.fA\n//│ ║        \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.21: \tdef foo x = case x of {\n//│ ╙──      \t                 ^\n//│ res: error | int\n//│ constrain calls  : 65\n//│ annoying  calls  : 90\n//│ subtyping calls  : 3498\n\n:stats\n:e\ndef arg: A[int] | B[int] | D[int]\nfoo arg\n//│ arg: A[int] | B[int] | D[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.91: \tfoo arg\n//│ ║        \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.22: \t  | A -> x.fA\n//│ ║        \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.21: \tdef foo x = case x of {\n//│ ╙──      \t                 ^\n//│ res: error\n//│ constrain calls  : 82\n//│ annoying  calls  : 209\n//│ subtyping calls  : 17621\n\n\n// ====== 2 ====== //\n\n:stats\n:e\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  }\ndef arg: A[int] | B[int]\nfoo arg\n//│ foo: ({fB: 'fA} & #B & ~#A | {fA: 'fA} & #A) -> 'fA\n//│ arg: A[int] | B[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.118: \tfoo arg\n//│ ║         \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.114: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.113: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error | int\n//│ constrain calls  : 44\n//│ annoying  calls  : 31\n//│ subtyping calls  : 520\n\n\n// ====== 3 ====== //\n\n:stats\n:e\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  }\ndef arg: A[int] | B[int] | C[int]\nfoo arg\n//│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | {fC: 'fA} & #C & ~#B)) -> 'fA\n//│ arg: A[int] | B[int] | C[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.147: \tfoo arg\n//│ ║         \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.142: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.141: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error | int\n//│ constrain calls  : 76\n//│ annoying  calls  : 90\n//│ subtyping calls  : 3279\n\n\n// ====== 4 ====== //\n\n:stats\n:e\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  }\ndef arg: A[int] | B[int] | C[int] | D[int]\nfoo arg\n//│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | {fD: 'fA} & #D & ~#C))) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.177: \tfoo arg\n//│ ║         \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.171: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.170: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error\n//│ constrain calls  : 94\n//│ annoying  calls  : 131\n//│ subtyping calls  : 4350\n\n:stats\n:e\nfoo (arg with { x = 1} with { y = 2 })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.197: \tfoo (arg with { x = 1} with { y = 2 })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int, x: 1, y: 2} & ~#B | {fB: int, x: 1, y: 2} & ~?a | {fB: int, x: 1, y: 2} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.171: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.170: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error\n//│ constrain calls  : 69\n//│ annoying  calls  : 128\n//│ subtyping calls  : 3820\n\n:stats\n:e\nfoo (arg with { x = 1; y = 2; z = 3 })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.215: \tfoo (arg with { x = 1; y = 2; z = 3 })\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int, x: 1, y: 2, z: 3} & ~#B | {fB: int, x: 1, y: 2, z: 3} & ~?a | {fB: int, x: 1, y: 2, z: 3} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.171: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.170: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error\n//│ constrain calls  : 69\n//│ annoying  calls  : 128\n//│ subtyping calls  : 3820\n\n\n// ====== 5 ====== //\n\n:stats\n:e\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int]\nfoo arg\n//│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | {fE: 'fA} & #E & ~#D)))) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.244: \tfoo arg\n//│ ║         \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.237: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.236: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error\n//│ constrain calls  : 98\n//│ annoying  calls  : 131\n//│ subtyping calls  : 4638\n\n\n// ====== 6 ====== //\n\n:stats\n:e\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int]\nfoo arg\n//│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | {fF: 'fA} & #F & ~#E))))) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.276: \tfoo arg\n//│ ║         \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.268: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.267: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error\n//│ constrain calls  : 102\n//│ annoying  calls  : 131\n//│ subtyping calls  : 4984\n\n\n// ====== 7 ====== //\n\n:stats\n:e\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  | G -> x.fG\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int]\nfoo arg\n//│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | ~#E & ({fF: 'fA} & #F | {fG: 'fA} & #G & ~#F)))))) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.309: \tfoo arg\n//│ ║         \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.300: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.299: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error\n//│ constrain calls  : 106\n//│ annoying  calls  : 131\n//│ subtyping calls  : 5393\n\ndef foo_manual: ({fA: 'a} & a | {fB: 'a} & b & ~a | {fC: 'a} & c & ~a & ~b | {fD: 'a} & d & ~a & ~b & ~c | {fE: 'a} & e & ~a & ~b & ~c & ~d | {fF: 'a} & f & ~a & ~b & ~c & ~d & ~e | {fG: 'a} & g & ~a & ~b & ~c & ~d & ~e & ~f) -> 'a\n//│ foo_manual: ({fA: 'a} & #A | ~#A & ({fB: 'a} & #B | ~#B & ({fC: 'a} & #C | ~#C & ({fD: 'a} & #D | ~#D & ({fE: 'a} & #E | ~#E & ({fF: 'a} & #F | {fG: 'a} & #G & ~#F)))))) -> 'a\n\n:stats\n:e\nfoo_manual arg\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.332: \tfoo_manual arg\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── type `{fB: int} & #B` does not match type `{fA: 'a} & #A | ~#A & ({fB: 'a} & #B | ~#B & ({fC: 'a} & #C | ~#C & ({fD: 'a} & #D | ~#D & ({fE: 'a} & #E | ~#E & ({fF: 'a} & #F | {fG: 'a} & #G & ~#F)))))`\n//│ ║  l.308: \tdef arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int]\n//│ ║         \t                  ^^^^^^\n//│ ╟── but it flows into reference with expected type `{fA: 'a0} & #A | ~#A & ({fB: 'a0} & #B | ~#B & ({fC: 'a0} & #C | ~#C & ({fD: 'a0} & #D | ~#D & ({fE: 'a0} & #E | ~#E & ({fF: 'a0} & #F | {fG: 'a0} & #G & ~#F)))))`\n//│ ║  l.332: \tfoo_manual arg\n//│ ║         \t           ^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.327: \tdef foo_manual: ({fA: 'a} & a | {fB: 'a} & b & ~a | {fC: 'a} & c & ~a & ~b | {fD: 'a} & d & ~a & ~b & ~c | {fE: 'a} & e & ~a & ~b & ~c & ~d | {fF: 'a} & f & ~a & ~b & ~c & ~d & ~e | {fG: 'a} & g & ~a & ~b & ~c & ~d & ~e & ~f) -> 'a\n//│ ╙──       \t                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: error\n//│ constrain calls  : 24\n//│ annoying  calls  : 67\n//│ subtyping calls  : 4417\n\n:stats\nfoo_manual = foo\n//│ ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | ~#E & ({fF: 'fA} & #F | {fG: 'fA} & #G & ~#F)))))) -> 'fA\n//│   <:  foo_manual:\n//│ ({fA: 'a} & #A | ~#A & ({fB: 'a} & #B | ~#B & ({fC: 'a} & #C | ~#C & ({fD: 'a} & #D | ~#D & ({fE: 'a} & #E | ~#E & ({fF: 'a} & #F | {fG: 'a} & #G & ~#F)))))) -> 'a\n//│ constrain calls  : 91\n//│ annoying  calls  : 183\n//│ subtyping calls  : 3611\n\n\n// ====== 8 ====== //\n\n:stats\n:e\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  | D -> x.fD\n  | E -> x.fE\n  | F -> x.fF\n  | G -> x.fG\n  | H -> x.fH\n  }\ndef arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] | H[int]\nfoo arg\n//│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | ~#E & ({fF: 'fA} & #F | ~#F & ({fG: 'fA} & #G | {fH: 'fA} & #H & ~#G))))))) -> 'fA\n//│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] | H[int]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.375: \tfoo arg\n//│ ║         \t^^^^^^^\n//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.365: \t  | A -> x.fA\n//│ ║         \t         ^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.364: \tdef foo x = case x of {\n//│ ╙──       \t                 ^\n//│ res: error\n//│ constrain calls  : 110\n//│ annoying  calls  : 131\n//│ subtyping calls  : 5870\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/StressUgly.mls",
    "content": "\nclass Lit: { val: int }\nclass Add[E]: { lhs: E; rhs: E }\n  method In: E -> E\n  method In = id\n//│ Defined class Lit\n//│ Defined class Add[=E]\n//│ Declared Add.In: Add['E] -> 'E -> 'E\n//│ Defined Add.In: Add['E] -> 'a -> 'a\n\n\n\ndef eval1_ty_ugly: Add['b] | 'a & ~Lit as 'b\n//│ eval1_ty_ugly: 'b\n//│   where\n//│     'b := Add['b] | 'a & ~Lit\n//│              = <missing implementation>\n\n// def eval1_ty: Add['b]\ndef eval1_ty: Add[int] // ~500\n// def eval1_ty: Add['b] | 'a // ~800\n// def eval1_ty: Add['b]\n//│ eval1_ty: Add[int]\n//│         = <missing implementation>\n\n// :stdout\n// :d\n:stats\n:e\neval1_ty = eval1_ty_ugly\n//│ 'b\n//│   where\n//│     'b := Add['b] | 'a & ~Lit\n//│   <:  eval1_ty:\n//│ Add[int]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.30: \teval1_ty = eval1_ty_ugly\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Add['b]` is not an instance of type `int`\n//│ ║  l.13: \tdef eval1_ty_ugly: Add['b] | 'a & ~Lit as 'b\n//│ ║        \t                   ^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.20: \tdef eval1_ty: Add[int] // ~500\n//│ ╙──      \t                  ^^^\n//│         = <no result>\n//│           eval1_ty_ugly is not implemented\n//│ constrain calls  : 54\n//│ annoying  calls  : 46\n//│ subtyping calls  : 433\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Subsume.mls",
    "content": "\n// Declare signature:\ndef f: int -> int\n//│ f: int -> int\n//│  = <missing implementation>\n\n// Define body:\ndef f x = x\n//│ 'a -> 'a\n//│   <:  f:\n//│ int -> int\n//│  = [Function: f]\n\n:e\nf = 42\n//│ 42\n//│   <:  f:\n//│ int -> int\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.15: \tf = 42\n//│ ║        \t^^^^^^\n//│ ╟── integer literal of type `42` is not a function\n//│ ║  l.15: \tf = 42\n//│ ║        \t    ^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.3: \tdef f: int -> int\n//│ ╙──     \t       ^^^^^^^^^^\n//│  = 42\n\n:re\nf 1\n//│ res: int\n//│ Runtime error:\n//│   TypeError: f1 is not a function\n\nfun x -> f x\n//│ res: int -> int\n//│    = [Function: res]\n\n\n\ndef boom: anything\n//│ boom: anything\n//│     = <missing implementation>\n\nboom = 1\n//│ 1\n//│   <:  boom:\n//│ anything\n//│     = 1\n\n:e\nadd boom 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.53: \tadd boom 1\n//│ ║        \t^^^^^^^^\n//│ ╟── type `anything` is not an instance of type `int`\n//│ ║  l.42: \tdef boom: anything\n//│ ║        \t          ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.53: \tadd boom 1\n//│ ╙──      \t    ^^^^\n//│ res: error | int\n//│    = 2\n\n\ndef boom: nothing\n//│ boom: nothing\n//│     = <missing implementation>\n\n:e\ndef boom = 1\n//│ 1\n//│   <:  boom:\n//│ nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.72: \tdef boom = 1\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `nothing`\n//│ ║  l.72: \tdef boom = 1\n//│ ║        \t           ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.67: \tdef boom: nothing\n//│ ╙──      \t          ^^^^^^^\n//│     = [Function: boom1]\n\n\ndef boom: 'a\n//│ boom: nothing\n//│     = <missing implementation>\n\n:e\nboom = 1\n//│ 1\n//│   <:  boom:\n//│ nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.93: \tboom = 1\n//│ ║        \t^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `'a`\n//│ ║  l.93: \tboom = 1\n//│ ║        \t       ^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.88: \tdef boom: 'a\n//│ ╙──      \t          ^^\n//│     = 1\n\n\n\ndef id: 'a -> 'a\n//│ id: 'a -> 'a\n//│   = <missing implementation>\n\nid 1\nid true\n//│ res: 1\n//│    = <no result>\n//│      id is not implemented\n//│ res: true\n//│    = <no result>\n//│      id is not implemented\n\ndef id x = x\n//│ 'a -> 'a\n//│   <:  id:\n//│ 'a -> 'a\n//│   = [Function: id1]\n\nid 1\nid true\n//│ res: 1\n//│    = 1\n//│ res: true\n//│    = true\n\n\n:e\ndef id n = add n 1\n//│ int -> int\n//│   <:  id:\n//│ 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.138: \tdef id n = add n 1\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.110: \tdef id: 'a -> 'a\n//│ ║         \t        ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.138: \tdef id n = add n 1\n//│ ╙──       \t               ^\n//│   = [Function: id2]\n\n:e\ndef id (x: int) = x\n//│ int -> int\n//│   <:  id:\n//│ 'a -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.154: \tdef id (x: int) = x\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `'a` is not an instance of type `int`\n//│ ║  l.110: \tdef id: 'a -> 'a\n//│ ║         \t        ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.154: \tdef id (x: int) = x\n//│ ╙──       \t           ^^^\n//│   = [Function: id3]\n\n\n\ndef f: (int & 'a) -> 'a\n//│ f: (int & 'a) -> 'a\n//│  = <missing implementation>\n\ndef impl a = a a\n//│ impl: ('a -> 'b & 'a) -> 'b\n//│     = [Function: impl]\n\n:e\ndef f = impl\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  f:\n//│ (int & 'a) -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.180: \tdef f = impl\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type `int & 'a` is not a function\n//│ ║  l.171: \tdef f: (int & 'a) -> 'a\n//│ ║         \t       ^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.175: \tdef impl a = a a\n//│ ║         \t             ^^^\n//│ ╟── from reference:\n//│ ║  l.175: \tdef impl a = a a\n//│ ╙──       \t             ^\n//│  = [Function: f2]\n\n:re\nf 1 \n//│ res: 1\n//│ Runtime error:\n//│   TypeError: a is not a function\n\n\ndef f: (int & 'a) -> (int & 'a) -> 'a \ndef f a b = if gt a b then a else b\n//│ f: (int & 'a) -> (int & 'a) -> 'a\n//│  = <missing implementation>\n//│ (number & 'a) -> (number & 'a) -> 'a\n//│   <:  f:\n//│ (int & 'a) -> (int & 'a) -> 'a\n//│  = [Function: f3]\n\nf 1 \n//│ res: (int & 'a) -> (1 | 'a)\n//│    = [Function (anonymous)]\n\n:e\ndef f a b = if gt a b then a else b b // mistake!\n//│ (number & 'a) -> nothing -> 'a\n//│   <:  f:\n//│ (int & 'a) -> (int & 'a) -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.219: \tdef f a b = if gt a b then a else b b // mistake!\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `int & 'a` is not a function\n//│ ║  l.205: \tdef f: (int & 'a) -> (int & 'a) -> 'a \n//│ ║         \t                     ^^^^^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.219: \tdef f a b = if gt a b then a else b b // mistake!\n//│ ║         \t                                  ^^^\n//│ ╟── from reference:\n//│ ║  l.219: \tdef f a b = if gt a b then a else b b // mistake!\n//│ ╙──       \t                                  ^\n//│  = [Function: f4]\n\nf 1 \n//│ res: (int & 'a) -> (1 | 'a)\n//│    = [Function (anonymous)]\n\n:re\nres 2\n//│ res: 1 | 2\n//│ Runtime error:\n//│   TypeError: b is not a function\n\n\n:e\ndef g: (int & 'a) -> 'a\ndef g a = add a 1\n//│ g: (int & 'a) -> 'a\n//│  = <missing implementation>\n//│ int -> int\n//│   <:  g:\n//│ (int & 'a) -> 'a\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.250: \tdef g a = add a 1\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `int` does not match type `'a`\n//│ ║  l.250: \tdef g a = add a 1\n//│ ║         \t          ^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.249: \tdef g: (int & 'a) -> 'a\n//│ ╙──       \t                     ^^\n//│  = [Function: g]\n\n\n\n// --- // The Twice Function // --- //\n\n\ndef twice f x = f (f x)\n//│ twice: ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│      = [Function: twice]\n\ndef ty1: (('b | 'c) -> 'c) -> 'b -> 'c\ndef ty2: ('b -> ('b & 'd)) -> 'b -> 'd\n//│ ty1: (('b | 'c) -> 'c) -> 'b -> 'c\n//│    = <missing implementation>\n//│ ty2: ('b -> ('b & 'd)) -> 'b -> 'd\n//│    = <missing implementation>\n\nty1 = ty2\n//│ ('b -> ('b & 'd)) -> 'b -> 'd\n//│   <:  ty1:\n//│ (('b | 'c) -> 'c) -> 'b -> 'c\n//│    = <no result>\n//│      ty2 is not implemented\n\nty2 = ty1\n//│ (('b | 'c) -> 'c) -> 'b -> 'c\n//│   <:  ty2:\n//│ ('b -> ('b & 'd)) -> 'b -> 'd\n//│    = <no result>\n//│      ty1 and ty2 are not implemented\n\nty1 = twice\nty2 = twice\n//│ ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│   <:  ty1:\n//│ (('b | 'c) -> 'c) -> 'b -> 'c\n//│    = [Function: twice]\n//│ ('a -> 'b & 'b -> 'c) -> 'a -> 'c\n//│   <:  ty2:\n//│ ('b -> ('b & 'd)) -> 'b -> 'd\n//│    = [Function: twice]\n\ntwice twice\n//│ res: ('a -> 'b & 'b -> ('a & 'c)) -> 'a -> 'c\n//│    = [Function (anonymous)]\n\n// * Note: cycle check fails when generalizing curried lambdas\ntwice twice!\n//│ res: ('a -> ('a & 'b) & 'b -> ('a & 'b & 'c)) -> 'a -> 'c\n//│    = [Function (anonymous)]\n\n\n// --- // Self Application // --- //\n\n\ndef self1: ('a -> 'b & 'a) -> 'b\n//│ self1: ('a -> 'b & 'a) -> 'b\n//│      = <missing implementation>\n\ndef self1 a = a a\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  self1:\n//│ ('a -> 'b & 'a) -> 'b\n//│      = [Function: self1]\n\nfun a -> a a\n//│ res: ('a -> 'b & 'a) -> 'b\n//│    = [Function: res]\n\nself1 = res\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  self1:\n//│ ('a -> 'b & 'a) -> 'b\n//│      = [Function: res]\n\nr = fun a -> a a\n//│ r: ('a -> 'b & 'a) -> 'b\n//│  = [Function: r]\n\nself1 = r\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  self1:\n//│ ('a -> 'b & 'a) -> 'b\n//│      = [Function: r]\n\ndef self2: 'a -> 'b as 'a\n//│ self2: 'a\n//│   where\n//│     'a := 'a -> 'b\n//│      = <missing implementation>\n\n// :e // fails since the fix to spurious-TV-cycles // works since assigned TVs\ndef self2 = self1\n//│ ('a -> 'b & 'a) -> 'b\n//│   <:  self2:\n//│ 'a\n//│   where\n//│     'a := 'a -> 'b\n//│      = [Function: self2]\n\n\nfun p -> fun q -> p q p\n//│ res: ('a -> 'b -> 'c & 'b) -> 'a -> 'c\n//│    = [Function: res]\n\n:ns\nfun p -> fun q -> p q p\n//│ res: forall 'a 'b 'c 'd. 'a -> 'b -> 'd\n//│   where\n//│     'a <: 'b -> 'c\n//│     'c <: 'a -> 'd\n//│    = [Function: res]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Test.mls",
    "content": "\nclass Person: { name: string; age: int }\ndef Person = fun n -> fun a -> Person { name = n; age = a }\n//│ Defined class Person\n//│ Person: (string & 'name) -> (int & 'age) -> (Person with {age: 'age, name: 'name})\n//│       = [Function: Person1]\n\nclass Animal: {}\n//│ Defined class Animal\n\ndef test = fun x -> case x of\n  { Person -> x.age\n  | Animal -> 0\n  }\n//│ test: (Animal | (Person\\name with {age: 'age})) -> (0 | 'age)\n//│     = [Function: test]\n\ntest: Person & {age: 'a} | Animal -> 'a | 0\n//│ res: 0 | Person & {age: 0} | Animal -> 0\n//│    = [Function: test]\n\ntest: (Person & {age: int} | Animal) -> int\n//│ res: (Animal | Person) -> int\n//│    = [Function: test]\n\na = Animal{}\n//│ a: Animal\n//│  = Animal {}\n\na: {}\n//│ res: anything\n//│    = Animal {}\n\np = Person \"Bob\" 42\n//│ p: Person & {age: 42, name: \"Bob\"}\n//│  = Person { name: 'Bob', age: 42 }\n\np: { age: int }\n//│ res: {age: int}\n//│    = Person { name: 'Bob', age: 42 }\n\ntest a\n//│ res: 0\n//│    = 0\n\ntest p\n//│ res: 0 | 42\n//│    = 42\n\n1: int\n//│ res: int\n//│    = 1\n\n\ndef f: 'a -> 'a & string\n//│ f: nothing\n//│  = <missing implementation>\n\ndef f: 'a -> ('a & string)\n//│ f: 'a -> (string & 'a)\n//│  = <missing implementation>\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/This.mls",
    "content": ":NoJS\n\nclass A\n  method Boom: int -> this\n//│ Defined class A\n//│ Declared A.Boom: (A & 'this) -> int -> (A & 'this)\n\nclass B: A\n  method Boom n = this\n//│ Defined class B\n//│ Defined B.Boom: (B & 'this) -> anything -> (B & 'this)\n\na = B{}\n//│ a: B\n\na.Boom 1 // : B\n//│ res: B & A\n\ndef b: A\nb = a\nb.Boom 1 // : A\n//│ b: A\n//│ B\n//│   <:  b:\n//│ A\n//│ res: A\n\n\n\n:w\nclass Myself[A]\n  method Me = this\n//│ Defined class Myself[±A]\n//│ Defined Myself.Me: (Myself[?] & 'this) -> (Myself[?] & 'this)\n//│ ╔══[WARNING] Type definition Myself has bivariant type parameters:\n//│ ║  l.31: \tclass Myself[A]\n//│ ║        \t      ^^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.31: \tclass Myself[A]\n//│ ╙──      \t             ^\n\nm0 = Myself {}\n//│ m0: Myself[?]\n\nm0.Me\n//│ res: Myself[?]\n\n\n\n:e\nclass Addable[A]\n  method Me = this\n  method Oops = this.oops // disallowed if `this` is rigid\n  method Add: A -> A\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.53: \t  method Oops = this.oops // disallowed if `this` is rigid\n//│ ║        \t                ^^^^^^^^^\n//│ ╟── reference of type `Addable[A] & this` does not have field 'oops'\n//│ ║  l.53: \t  method Oops = this.oops // disallowed if `this` is rigid\n//│ ╙──      \t                ^^^^\n//│ Defined class Addable[=A]\n//│ Declared Addable.Add: Addable['A] -> 'A -> 'A\n//│ Defined Addable.Me: (Addable['A] & 'this) -> (Addable['A] & 'this)\n//│ Defined Addable.Oops: Addable['A] -> error\n\n\n\nclass Base0\n  method Foo0: this\n//│ Defined class Base0\n//│ Declared Base0.Foo0: (Base0 & 'this) -> (Base0 & 'this)\n\nclass Derived0: Base0\n//│ Defined class Derived0\n\nDerived0.Foo0\n//│ res: (Derived0 & 'this) -> (Base0 & 'this)\n\nclass Base\n  method Foo: this\n  method Foo = this\n//│ Defined class Base\n//│ Declared Base.Foo: (Base & 'this) -> (Base & 'this)\n//│ Defined Base.Foo: (Base & 'this) -> (Base & 'this)\n\nclass Derived: Base\n//│ Defined class Derived\n\nBase.Foo\n//│ res: (Base & 'this) -> (Base & 'this)\n\nDerived.Foo\n//│ res: (Derived & 'this) -> (Base & 'this)\n\nres (Derived{})\n//│ res: Derived & Base\n\n(error: Derived).Foo\n//│ res: Derived & Base\n\nclass Base2\n  method Foo2: this\nclass Derived2: Base2\n  method Foo3 = (this.Foo2,)\nclass DerivedDerived2: Derived2\n  method Foo2 = this.Foo3.0\n//│ Defined class Base2\n//│ Declared Base2.Foo2: (Base2 & 'this) -> (Base2 & 'this)\n//│ Defined class Derived2\n//│ Defined Derived2.Foo3: (Derived2 & 'this) -> (Derived2 & Base2 & 'this,)\n//│ Defined class DerivedDerived2\n//│ Defined DerivedDerived2.Foo2: (DerivedDerived2 & 'this) -> (DerivedDerived2 & Base2 & Derived2 & 'this)\n\nDerived2.Foo3\n//│ res: (Derived2 & 'this) -> (Derived2 & Base2 & 'this,)\n\nDerivedDerived2.Foo3\n//│ res: (DerivedDerived2 & 'this) -> (Derived2 & Base2 & 'this,)\n\n\n\nclass NewBase\n  method NewFoo: this\n  method NewBar = (this.NewFoo,)\n//│ Defined class NewBase\n//│ Declared NewBase.NewFoo: (NewBase & 'this) -> (NewBase & 'this)\n//│ Defined NewBase.NewBar: (NewBase & 'this) -> (NewBase & 'this,)\n\nclass NewDerived: NewBase\n  method NewQux = this.NewBar.0\n//│ Defined class NewDerived\n//│ Defined NewDerived.NewQux: (NewDerived & 'this) -> (NewDerived & NewBase & 'this)\n\n// Test methods of NewDerived.\nNewDerived.NewFoo\nNewDerived.NewBar\nNewDerived.NewQux\n//│ res: (NewDerived & 'this) -> (NewBase & 'this)\n//│ res: (NewDerived & 'this) -> (NewBase & 'this,)\n//│ res: (NewDerived & 'this) -> (NewDerived & NewBase & 'this)\n\nclass NewDerivedDerived: NewDerived\n  method NewQuz = (this.NewQux)\n//│ Defined class NewDerivedDerived\n//│ Defined NewDerivedDerived.NewQuz: (NewDerivedDerived & 'this) -> (NewDerivedDerived & NewBase & NewDerived & 'this)\n\nNewDerivedDerived.NewFoo\nNewDerivedDerived.NewBar\nNewDerivedDerived.NewQux\nNewDerivedDerived.NewQuz\n//│ res: (NewDerivedDerived & 'this) -> (NewBase & 'this)\n//│ res: (NewDerivedDerived & 'this) -> (NewBase & 'this,)\n//│ res: (NewDerivedDerived & 'this) -> (NewDerived & NewBase & 'this)\n//│ res: (NewDerivedDerived & 'this) -> (NewDerivedDerived & NewBase & NewDerived & 'this)\n\n:e\nclass NewDerivedDerivedDerived: NewDerivedDerived\n  method NewQux = this.NewBar.0\n//│ ╔══[ERROR] Overriding method NewDerived.NewQux without explicit declaration is not allowed.\n//│ ║  l.158: \t  method NewQux = this.NewBar.0\n//│ ║         \t         ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: method definition inherited from\n//│ ║  l.130: \t  method NewQux = this.NewBar.0\n//│ ╙──       \t         ^^^^^^^^^^^^^^^^^^^^^^\n//│ Defined class NewDerivedDerivedDerived\n//│ Defined NewDerivedDerivedDerived.NewQux: (NewDerivedDerivedDerived & 'this) -> (NewDerivedDerivedDerived & NewBase & 'this)\n\n// Test methods of NewDerivedDerivedDerived\nNewDerivedDerivedDerived.NewBar\nNewDerivedDerivedDerived.NewFoo\nNewDerivedDerivedDerived.NewQuz\nNewDerivedDerivedDerived.NewQux\n//│ res: (NewDerivedDerivedDerived & 'this) -> (NewBase & 'this,)\n//│ res: (NewDerivedDerivedDerived & 'this) -> (NewBase & 'this)\n//│ res: (NewDerivedDerivedDerived & 'this) -> (NewDerivedDerived & NewBase & NewDerived & 'this)\n//│ res: (NewDerivedDerivedDerived & 'this) -> (NewDerivedDerivedDerived & NewBase & 'this)\n\n\n\nclass Animal\n  method Eat = this\n//│ Defined class Animal\n//│ Defined Animal.Eat: (Animal & 'this) -> (Animal & 'this)\n\nclass Cat: Animal\n//│ Defined class Cat\n\nAnimal.Eat\n//│ res: (Animal & 'this) -> (Animal & 'this)\n\nCat.Eat\n//│ res: (Cat & 'this) -> (Animal & 'this)\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Ticks.mls",
    "content": ":js\nf' = 2\n//│ // Prelude\n//│ let res;\n//│ // Query 1\n//│ globalThis.f$ = 2;\n//│ // End of generated code\n//│ f': 2\n//│   = 2\n\n:js\nf'\n//│ // Query 1\n//│ res = f$;\n//│ // End of generated code\n//│ res: 2\n//│    = 2\n\n:js\nf' + 2\n//│ // Query 1\n//│ res = f$ + 2;\n//│ // End of generated code\n//│ res: int\n//│    = 4\n\n:js\ntrait Foo'[T']\n  method Bar': T' -> T'\n//│ Defined trait Foo'[=T']\n//│ Declared Foo'.Bar': Foo'['T'] -> 'T' -> 'T'\n//│ // Prelude\n//│ const Foo$ = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // End of generated code\n\n:js\nclass A'[B'] : {x': B'}\n  method C' = this.x'\n//│ Defined class A'[+B']\n//│ Defined A'.C': A'['B'] -> 'B'\n//│ // Prelude\n//│ class A$ {\n//│   constructor(fields) {\n//│     this[\"x'\"] = fields[\"x'\"];\n//│   }\n//│   get \"C'\"() {\n//│     const self = this;\n//│     return self[\"x'\"];\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\nclass M : {x': int}\n  method N' = this.x'\n  method P' y' = this.x' + y'\nmm = M{ x' = 2 }\nmm.N'\nmm.P' f'\n//│ Defined class M\n//│ Defined M.N': M -> int\n//│ Defined M.P': M -> int -> int\n//│ // Prelude\n//│ class M {\n//│   constructor(fields) {\n//│     this[\"x'\"] = fields[\"x'\"];\n//│   }\n//│   get \"N'\"() {\n//│     const self = this;\n//│     return self[\"x'\"];\n//│   }\n//│   \"P'\"(y$) {\n//│     const self = this;\n//│     return self[\"x'\"] + y$;\n//│   }\n//│ }\n//│ // Query 1\n//│ globalThis.mm = new M({ \"x'\": 2 });\n//│ // Query 2\n//│ res = mm[\"N'\"];\n//│ // Query 3\n//│ res = mm[\"P'\"](f$);\n//│ // End of generated code\n//│ mm: M & {x': 2}\n//│   = M { \"x'\": 2 }\n//│ res: int\n//│    = 2\n//│ res: int\n//│    = 4\n\n:js\nclass D'[B'] : A'[B']\n//│ Defined class D'[+B']\n//│ // Prelude\n//│ class D$ extends A$ {\n//│   constructor(fields) {\n//│     super(fields);\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\ntype E' = D'[int] | A'[int]\n//│ Defined type alias E'\n//│ // End of generated code\n\n:js\nclass None': {}\n//│ Defined class None'\n//│ // Prelude\n//│ class None$ {}\n//│ // End of generated code\n\n:js\nclass CC': None' & Foo'[anything]\n//│ Defined class CC'\n//│ // Prelude\n//│ class CC$ extends None$ {\n//│   constructor(fields) {\n//│     super(fields);\n//│     Foo$.implement(this);\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\nclass TT' : { a': int }\n//│ Defined class TT'\n//│ // Prelude\n//│ class TT$ {\n//│   constructor(fields) {\n//│     this[\"a'\"] = fields[\"a'\"];\n//│   }\n//│ }\n//│ // End of generated code\n\n:js\ntt' = TT'{a'=4}\ntt'.a'\n//│ // Query 1\n//│ globalThis.tt$ = new TT$({ \"a'\": 4 });\n//│ // Query 2\n//│ res = tt$[\"a'\"];\n//│ // End of generated code\n//│ tt': TT' & {a': 4}\n//│    = TT$ { \"a'\": 4 }\n//│ res: 4\n//│    = 4\n\n:js\na' = {b' = 42}\n//│ // Query 1\n//│ globalThis.a$ = { \"b'\": 42 };\n//│ // End of generated code\n//│ a': {b': 42}\n//│   = { \"b'\": 42 }\n\n:js\na'.b'\n//│ // Query 1\n//│ res = a$[\"b'\"];\n//│ // End of generated code\n//│ res: 42\n//│    = 42\n\n:js\ndef g' x' = x' with { c' = 24 }\n//│ // Prelude\n//│ function withConstruct(target, fields) {\n//│   if (typeof target === \"string\" || typeof target === \"number\" || typeof target === \"boolean\" || typeof target === \"bigint\" || typeof target === \"symbol\") {\n//│     return Object.assign(target, fields);\n//│   }\n//│   if (target instanceof String || target instanceof Number || target instanceof Boolean || target instanceof BigInt) {\n//│     return Object.assign(target.valueOf(), target, fields);\n//│   }\n//│   if (Array.isArray(target)) {\n//│     const clone = Array.from(target);\n//│     for (const key in target){\n//│       clone[key] = target[key];\n//│     }\n//│     for (const key in fields){\n//│       clone[key] = fields[key];\n//│     }\n//│     return clone;\n//│   }\n//│   if (target == null) {\n//│     return Object.assign({}, {}, fields);\n//│   }\n//│   const copy = Object.assign({}, target, fields);\n//│   Object.setPrototypeOf(copy, Object.getPrototypeOf(target));\n//│   return copy;\n//│ }\n//│ // Query 1\n//│ globalThis.g$ = function g$(x$) {\n//│   return withConstruct(x$, { \"c'\": 24 });\n//│ };\n//│ // End of generated code\n//│ g': 'a -> ('a\\c' & {c': 24})\n//│   = [Function: g$]\n\n:js\ngg' = let w' = 2 in w' + w'\n//│ // Query 1\n//│ globalThis.gg$ = ((w$) => w$ + w$)(2);\n//│ // End of generated code\n//│ gg': int\n//│    = 4\n\n:js\nrcd' = { x' = 1 }\nrcd'.x'\n//│ // Query 1\n//│ globalThis.rcd$ = { \"x'\": 1 };\n//│ // Query 2\n//│ res = rcd$[\"x'\"];\n//│ // End of generated code\n//│ rcd': {x': 1}\n//│     = { \"x'\": 1 }\n//│ res: 1\n//│    = 1\n\n:js\nfoo { x' } = x'\n//│ // Query 1\n//│ globalThis.foo = function foo({ \"x'\": x$ }) {\n//│   return x$;\n//│ };\n//│ // End of generated code\n//│ foo: {x': 'a} -> 'a\n//│    = [Function: foo]\n\n:js\nfoo { x' = y' } = y'\n//│ // Query 1\n//│ globalThis.foo1 = function foo1({ \"x'\": y$ }) {\n//│   return y$;\n//│ };\n//│ // End of generated code\n//│ foo: {x': 'a} -> 'a\n//│    = [Function: foo1]\n\n:js\ntrait T : {x': int}\n  method N' = this.x'\n  method P' y' = this.x' + y'\n  method Q ((y', {z'})) = this.x' + y' + z'\n//│ Defined trait T\n//│ Defined T.N': T -> int\n//│ Defined T.P': T -> int -> int\n//│ Defined T.Q: T -> ((int, {z': int},),) -> int\n//│ // Prelude\n//│ const T = function () {\n//│   const tag = Symbol();\n//│   return ({\n//│     implement: function implement(instance) {\n//│       if (tag in instance) {\n//│         return;\n//│       }\n//│       Object.defineProperty(instance, tag, { value: {} });\n//│       if (!(\"N'\" in instance)) {\n//│         Object.defineProperty(instance, \"N'\", {\n//│           get: function () {\n//│             return this1[\"x'\"];\n//│           }\n//│         });\n//│       }\n//│       if (!(\"P'\" in instance)) {\n//│         instance[\"P'\"] = function (y$) {\n//│           return this1[\"x'\"] + y$;\n//│         };\n//│       }\n//│       if (!(\"Q\" in instance)) {\n//│         instance.Q = function ([\n//│           y$,\n//│           { \"z'\": z$ }\n//│         ]) {\n//│           return this1[\"x'\"] + y$ + z$;\n//│         };\n//│       }\n//│     },\n//│     build: function build(instance) {\n//│       if (typeof instance !== \"object\") {\n//│         instance = Object.assign(instance, {});\n//│       }\n//│       this.implement(instance);\n//│       return instance;\n//│     },\n//│     is: function is(x) {\n//│       return typeof x === \"object\" && x !== null && tag in x;\n//│     }\n//│   });\n//│ }();\n//│ // End of generated code\n\n:js\nlet f' = fun x -> x + 1 in f' 2\n//│ // Query 1\n//│ res = ((f$) => f$(2))((x) => x + 1);\n//│ // End of generated code\n//│ res: int\n//│    = 3\n\n:js\nfoo { return } = return\n//│ // Query 1\n//│ globalThis.foo2 = function foo2({ \"return\": return$ }) {\n//│   return return$;\n//│ };\n//│ // End of generated code\n//│ foo: {return: 'a} -> 'a\n//│    = [Function: foo2]\n\nfoo { return = 1 }\n//│ res: 1\n//│    = 1\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Tony.mls",
    "content": "class Some[A]: { value: A }\nclass None: {}\n//│ Defined class Some[+A]\n//│ Defined class None\n\n\n\ndef flatMap3 = fun f -> fun opt -> case opt of { Some -> f opt | _ -> opt }\n//│ flatMap3: ('a -> 'b) -> (Some[?] & 'a | 'b & ~#Some) -> 'b\n//│         = [Function: flatMap3]\n\n\narg = if true then Some{value = 42} with {payload = 23} else None {}\n//│ arg: None | Some[42] & {payload: 23}\n//│    = Some { value: 42, payload: 23 }\n\n// > TODO don't distribute neg inters + handle better at constraint top level\n:stats\nflatMap3 (fun x -> add x.value x.payload) arg\n//│ res: None | int\n//│    = 65\n//│ constrain calls  : 82\n//│ annoying  calls  : 23\n//│ subtyping calls  : 350\n\n\narg = if true then Some{value = 42} else None {}\n//│ arg: None | Some[42]\n//│    = Some { value: 42 }\n\nflatMap3 (fun x -> x.value) arg\n//│ res: 42 | None\n//│    = 42\n\n\nfoo = flatMap3 (fun x -> x.value)\n//│ foo: (Some[?] & {value: 'a} | 'a & ~#Some) -> 'a\n//│    = [Function (anonymous)]\n\nfoo arg\n//│ res: 42 | None\n//│    = 42\n\nfoo 1\n//│ res: 1\n//│    = 1\n\nfn = foo None\n//│ fn: anything -> None\n//│   = [Function (anonymous)]\n\n// :d\nfn{} // foo None {}\n//│ res: None\n//│    = None {}\n\n// :d\nfoo (None{})\n//│ res: None\n//│    = None {}\n\n\nfun f -> flatMap3 f arg\n//│ res: (Some[42] -> 'a) -> (None | 'a)\n//│    = [Function: res]\n\n\n\n\nfoo = flatMap3 (fun x -> x)\n//│ foo: (Some[?] & 'a | 'a & ~#Some) -> 'a\n//│    = [Function (anonymous)]\n\nfoo 1\n//│ res: 1\n//│    = 1\n\n\n\n\ndef simpler = fun f -> case None{} of { Some -> f 1 | _ -> None{} }\n//│ simpler: (1 -> 'a) -> (None | 'a)\n//│        = [Function: simpler]\n\ndef simpler = fun f -> fun opt -> case opt of { Some -> f opt | None -> opt }\n//│ simpler: ('a -> 'b) -> (None & 'b | Some[?] & 'a) -> 'b\n//│        = [Function: simpler1]\n\nsimpler (fun x -> x.value)\n//│ res: (None & 'a | Some[?] & {value: 'b}) -> ('b | 'a)\n//│    = [Function (anonymous)]\n\n:e\nres 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.94: \tres 1\n//│ ║        \t^^^^^\n//│ ╟── integer literal of type `1` does not match type `None & ?a | Some[?] & ?b`\n//│ ║  l.94: \tres 1\n//│ ║        \t    ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.85: \tdef simpler = fun f -> fun opt -> case opt of { Some -> f opt | None -> opt }\n//│ ╙──      \t                                       ^^^\n//│ res: error\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\ndef funny = fun f -> case f of { Some -> f f }\n//│ funny: nothing -> nothing\n//│      = [Function: funny]\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TraitMatching.mls",
    "content": "\ntrait MyTrait[A]: { value: A }\n//│ Defined trait MyTrait[+A]\n\n\ndef test1 x = case x of { MyTrait -> x.value | _ -> 0 }\n//│ test1: ({value: 'value} & #MyTrait | ~#MyTrait) -> (0 | 'value)\n//│      = [Function: test1]\n\n:e\ntest1 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.11: \ttest1 1\n//│ ║        \t^^^^^^^\n//│ ╟── expression of type `1 & ~?a | 1 & #MyTrait` does not have field 'value'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.6: \tdef test1 x = case x of { MyTrait -> x.value | _ -> 0 }\n//│ ║       \t                                     ^^^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.6: \tdef test1 x = case x of { MyTrait -> x.value | _ -> 0 }\n//│ ╙──     \t                   ^\n//│ res: 0 | error\n//│    = 0\n\ntest1 { value = 1 }\n//│ res: 0 | 1\n//│    = 0\n\nmt = MyTrait { value = 1 }\n//│ mt: {value: 1} & #MyTrait\n//│   = { value: 1 }\n\ntest1 mt\n//│ res: 0 | 1\n//│    = 1\n\nclass C1: MyTrait[int]\n//│ Defined class C1\n\ntest1 (C1 { value = 1 })\n//│ res: 0 | 1\n//│    = 1\n\n\ndef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ test2: ({default: 'value} & ~#MyTrait | {value: 'value} & #MyTrait) -> 'value\n//│      = [Function: test2]\n\n:e\ntest2 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.50: \ttest2 1\n//│ ║        \t^^^^^^^\n//│ ╟── expression of type `1 & ~#MyTrait` does not have field 'default'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ╙──      \t                                                    ^^^^^^^^^\n//│ res: error\n//│    = undefined\n\n:e\ntest2 { value = 1 }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.62: \ttest2 { value = 1 }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `{value: 1} & ~#MyTrait` does not have field 'default'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ╙──      \t                                                    ^^^^^^^^^\n//│ res: 1 | error\n//│    = undefined\n\ntest2 { value = 1; default = \"hi\" }\n//│ res: \"hi\" | 1\n//│    = 'hi'\n\ntest2 mt\n//│ res: 1\n//│    = 1\n\ntest2 (C1 { value = 1 })\n//│ res: 1\n//│    = 1\n\n\n// TODO: ability to declare classes as `final` so they can be assumed _not_ to inherit from a trait?\nclass C2: { default: string }\n//│ Defined class C2\n\n:e\ntest2 (C2 { default = \"oops\" })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.91: \ttest2 (C2 { default = \"oops\" })\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `C2 & {default: ?default} & ~?a | C2 & {default: ?default} & #MyTrait` does not have field 'value'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ║        \t                                     ^^^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ╙──      \t                   ^\n//│ res: \"oops\" | error\n//│    = 'oops'\n\n// Note: `value` is unused here; would deserve a warning\nc2 = C2 { value = 1; default = \"oops\" }\n//│ c2: C2 & {default: \"oops\"}\n//│   = C2 { default: 'oops' }\n\n:e\ntest2 c2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.111: \ttest2 c2\n//│ ║         \t^^^^^^^^\n//│ ╟── expression of type `C2 & {default: ?default} & ~?a | C2 & {default: ?default} & #MyTrait` does not have field 'value'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ║        \t                                     ^^^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ╙──      \t                   ^\n//│ res: \"oops\" | error\n//│    = 'oops'\n\ntest2 (c2 with { value = 1 })\n//│ res: \"oops\" | 1\n//│    = 'oops'\n\n\n// Note: if we allowed this, we'd have to be careful in the semantics of trait ctors!\n:e\nclass C3: { default: string } & ~myTrait\n//│ ╔══[ERROR] cannot inherit from a type negation\n//│ ║  l.132: \tclass C3: { default: string } & ~myTrait\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n:e\nclass C3: { default: string } & ~MyTrait[anything]\n//│ ╔══[ERROR] cannot inherit from a type negation\n//│ ║  l.138: \tclass C3: { default: string } & ~MyTrait[anything]\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\ndef strawman: C2 & ~MyTrait[anything]\n//│ strawman: C2 & ~MyTrait[?]\n//│         = <missing implementation>\n\n:e\ntest2 strawman\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.148: \ttest2 strawman\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── expression of type `C2 & ~{value: anything} & ~?a | C2 & #MyTrait & ~{value: anything}` does not have field 'value'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ║        \t                                     ^^^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.45: \tdef test2 x = case x of { MyTrait -> x.value | _ -> x.default }\n//│ ╙──      \t                   ^\n//│ res: error | string\n//│    = <no result>\n//│      strawman is not implemented\n\nstrawman: C2\n//│ res: C2\n//│    = <no result>\n//│      strawman is not implemented\n\n:e\nstrawman: ~{ value: anything }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.169: \tstrawman: ~{ value: anything }\n//│ ║         \t^^^^^^^^\n//│ ╟── type `C2 & ~MyTrait[?]` does not match type `~{value: anything}`\n//│ ║  l.143: \tdef strawman: C2 & ~MyTrait[anything]\n//│ ║         \t              ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `~{value: anything}`\n//│ ║  l.169: \tstrawman: ~{ value: anything }\n//│ ║         \t^^^^^^^^\n//│ ╟── Note: constraint arises from type negation:\n//│ ║  l.169: \tstrawman: ~{ value: anything }\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^\n//│ res: ~{value: anything}\n//│    = <no result>\n//│      strawman is not implemented\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Traits.mls",
    "content": "trait A: { x: int }\ntrait B: { y: string }\nclass C: { x: 0 | 1 }\n//│ Defined trait A\n//│ Defined trait B\n//│ Defined class C\n\n\nA { x = 1 }\n//│ res: {x: 1} & #A\n//│    = { x: 1 }\n\n:e\nA {}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.14: \tA {}\n//│ ║        \t^^^^\n//│ ╟── record literal of type `anything` does not have field 'x'\n//│ ║  l.14: \tA {}\n//│ ║        \t  ^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.1: \ttrait A: { x: int }\n//│ ╙──     \t         ^^^^^^^^^^\n//│ res: error | #A\n//│    = {}\n\n\nclass D: C & A & B\n//│ Defined class D\n\nD\n//│ res: {x: 'x & (0 | 1), y: string & 'y} -> (D with {x: 'x, y: 'y})\n//│    = [Function: res]\n\n:re\nerror: A & B\n//│ res: A & B\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:e\ndv = D{}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.42: \tdv = D{}\n//│ ║        \t     ^^^\n//│ ╟── record literal of type `anything` is not a record (expected a record with fields: y, x)\n//│ ║  l.42: \tdv = D{}\n//│ ╙──      \t      ^^\n//│ dv: D & {x: nothing, y: nothing} | error\n//│   = D { x: undefined, y: undefined }\n\ndv = D { x = 0; y = \"hello\" }\n//│ dv: D & {x: 0, y: \"hello\"}\n//│   = D { x: 0, y: 'hello' }\n\n:e\ndv: nothing\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.57: \tdv: nothing\n//│ ║        \t^^\n//│ ╟── application of type `D with {x: ?x, y: ?y}` does not match type `nothing`\n//│ ║  l.52: \tdv = D { x = 0; y = \"hello\" }\n//│ ║        \t     ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `nothing`\n//│ ║  l.57: \tdv: nothing\n//│ ║        \t^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.57: \tdv: nothing\n//│ ╙──      \t    ^^^^^^^\n//│ res: nothing\n//│    = D { x: 0, y: 'hello' }\n\ndv: A & B\n//│ res: A & B\n//│    = D { x: 0, y: 'hello' }\n\n:e\ndv: A & B: nothing\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.78: \tdv: A & B: nothing\n//│ ║        \t^^\n//│ ╟── type `A & B` does not match type `nothing`\n//│ ║  l.78: \tdv: A & B: nothing\n//│ ║        \t    ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.78: \tdv: A & B: nothing\n//│ ╙──      \t           ^^^^^^^\n//│ res: nothing\n//│    = D { x: 0, y: 'hello' }\n\n\ntrait Indirect: C\n//│ Defined trait Indirect\n\nclass E: Indirect\n//│ Defined class E\n\n:e\nE{}\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.99: \tE{}\n//│ ║        \t^^^\n//│ ╟── record literal of type `anything` does not have field 'x'\n//│ ║  l.99: \tE{}\n//│ ╙──      \t ^^\n//│ res: E & {x: nothing} | error\n//│    = E {}\n\nev = E { x = 1 }\nev: C\n//│ ev: E & {x: 1}\n//│   = E {}\n//│ res: C\n//│    = E {}\n\n\ntrait T1: C & A\n//│ Defined trait T1\n\n:e\ndef t = T1 (A { x = 1 })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.121: \tdef t = T1 (A { x = 1 })\n//│ ║         \t        ^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{x: 1}` does not match type `C | ~#A`\n//│ ║  l.121: \tdef t = T1 (A { x = 1 })\n//│ ║         \t              ^^^^^^^^^\n//│ ╟── but it flows into application with expected type `C | ~#A`\n//│ ║  l.121: \tdef t = T1 (A { x = 1 })\n//│ ║         \t            ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.117: \ttrait T1: C & A\n//│ ║         \t          ^\n//│ ╟── from intersection type:\n//│ ║  l.117: \ttrait T1: C & A\n//│ ╙──       \t          ^^^^^\n//│ t: error | {x: 1} & #A & #T1\n//│  = [Function: t]\n\nt = T1 (A (C { x = 1 }))\n//│ t: C & {x: 1} & #A & #T1\n//│  = C { x: 1 }\n\nclass CA: C & A\n//│ Defined class CA\n\nt = T1 (CA { x = 1 })\n//│ t: CA & {x: 1} & #T1\n//│  = CA { x: 1 }\n\n\nclass C1: B & T1 & { y: \"hi\" | \"hello\" }\n//│ Defined class C1\n\n:e\nc1 = C1 { }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.156: \tc1 = C1 { }\n//│ ║         \t     ^^^^^^\n//│ ╟── record literal of type `anything` is not a record (expected a record with fields: y, x)\n//│ ║  l.156: \tc1 = C1 { }\n//│ ╙──       \t        ^^^\n//│ c1: C1 & {x: nothing, y: nothing} | error\n//│   = C1 { y: undefined, x: undefined }\n\nc1 = C1 { x = 1; y = \"hi\" }\n//│ c1: C1 & {x: 1, y: \"hi\"}\n//│   = C1 { y: 'hi', x: 1 }\n\nc1: T1\n//│ res: T1\n//│    = C1 { y: 'hi', x: 1 }\n\nc1: A\n//│ res: A\n//│    = C1 { y: 'hi', x: 1 }\n\nc1.x\nc1.y\n//│ res: 1\n//│    = 1\n//│ res: \"hi\"\n//│    = 'hi'\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Trans.mls",
    "content": "\nclass A\nclass B: A\nclass C: B\nc = C{}\n//│ Defined class A\n//│ Defined class B\n//│ Defined class C\n//│ c: C\n//│  = C {}\n\nc: C\n//│ res: C\n//│    = C {}\n\nc: B\n//│ res: B\n//│    = C {}\n\nres: A\n//│ res: A\n//│    = C {}\n\nc: A\n//│ res: A\n//│    = C {}\n\na = res\n//│ a: A\n//│  = C {}\n\n:e\na: B\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.33: \ta: B\n//│ ║        \t^\n//│ ╟── type `A` is not an instance of type `B`\n//│ ║  l.24: \tc: A\n//│ ║        \t   ^\n//│ ╟── but it flows into reference with expected type `B`\n//│ ║  l.33: \ta: B\n//│ ║        \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.33: \ta: B\n//│ ╙──      \t   ^\n//│ res: B\n//│    = C {}\n\n:e\na: C\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.50: \ta: C\n//│ ║        \t^\n//│ ╟── type `A` is not an instance of type `C`\n//│ ║  l.24: \tc: A\n//│ ║        \t   ^\n//│ ╟── but it flows into reference with expected type `C`\n//│ ║  l.50: \ta: C\n//│ ║        \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.50: \ta: C\n//│ ╙──      \t   ^\n//│ res: C\n//│    = C {}\n\n\n// Transitivity is currently broken for primitive literals:\n\n42: int\nres: number\n//│ res: int\n//│    = 42\n//│ res: number\n//│    = 42\n\n42: number\n//│ res: number\n//│    = 42\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TrickyExtrusion.mls",
    "content": "\n// From SuperType tests\n\nTrue = true\n//│ True: true\n//│     = true\n\ndef inc: int -> int\n//│ inc: int -> int\n//│    = <missing implementation>\n\ntest f =\n  let r = fun x -> fun g -> (g x, )\n  in (r 0 inc, r True not)\n//│ test: anything -> ((int,), (bool,),)\n//│     = <no result>\n//│       inc is not implemented\n\n// * Precise type:\ntest f = (f 0, f True)\n//│ test: (0 -> 'a & true -> 'b) -> ('a, 'b,)\n//│     = [Function: test]\n\n// * Imprecise type (notice the `(0 | true)`):\n// * Note: With inferred first-class constrained types and generalized curried functions,\n// *  this approximation be avoided (see below).\ntest f =\n  let r x = f x\n  in (r 0, r True)\n//│ test: ((0 | true) -> 'a) -> ('a, 'a,)\n//│     = [Function: test1]\n\n// Same example, a little elaborated\ntest f =\n  let r = fun x -> fun g -> (g x, f x)\n  in (r 0 inc, r True not)\n//│ test: ((0 | true) -> 'a) -> ((int, 'a,), (bool, 'a,),)\n//│     = <no result>\n//│       inc is not implemented\n\n\n\n\n:GeneralizeCurriedFunctions\n\n\n\n// * Note the still approximative type due to extrusion\ntest f =\n  let r x = f x\n  in (r 0, r True)\n//│ test: ((0 | true) -> 'a) -> ('a, 'a,)\n//│     = [Function: test2]\n\n:e // * Due to lack of precision\n(test id).0 + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.56: \t(test id).0 + 1\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.4: \tTrue = true\n//│ ║       \t       ^^^^\n//│ ╟── but it flows into field selection with expected type `int`\n//│ ║  l.56: \t(test id).0 + 1\n//│ ╙──      \t^^^^^^^^^^^\n//│ res: error | int\n//│    = 1\n\n:e // * Due to lack of precision\nnot (test id).1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.70: \tnot (test id).1\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not an instance of type `bool`\n//│ ║  l.51: \t  in (r 0, r True)\n//│ ║        \t        ^\n//│ ╟── but it flows into field selection with expected type `bool`\n//│ ║  l.70: \tnot (test id).1\n//│ ╙──      \t    ^^^^^^^^^^^\n//│ res: bool | error\n//│    = false\n\n:e // * Legit\nnot (test id).0\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.84: \tnot (test id).0\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not an instance of type `bool`\n//│ ║  l.51: \t  in (r 0, r True)\n//│ ║        \t        ^\n//│ ╟── but it flows into field selection with expected type `bool`\n//│ ║  l.84: \tnot (test id).0\n//│ ╙──      \t    ^^^^^^^^^^^\n//│ res: bool | error\n//│    = true\n\n\n\n\n\n// * === With Constrained Types ===\n\n:DontDistributeForalls\n:ConstrainedTypes\n\n\n\n// * Note the precise type now\n:ns\ntest f =\n  let r x = f x\n  in (r 0, r True)\n//│ test: forall 'a 'b 'c 'd 'e 'f 'g. 'a -> ('b, 'e,)\n//│   where\n//│     'a <: 'f -> 'g & 'c -> 'd\n//│     'd <: 'b\n//│     'c :> 0\n//│     'g <: 'e\n//│     'f :> true\n//│     = [Function: test3]\n\n// * Q: why does this type *appear* approximated after simplification?\ntest\n//│ res: (0 -> 'a & true -> 'b) -> ('a, 'b,)\n//│    = [Function: test3]\n\n// * We can tell the type is still precise enough because these work:\n\n(test id).0 + 1\n//│ res: int\n//│    = 1\n\nnot (test id).1\n//│ res: bool\n//│    = false\n\n:e // * Legit\nnot (test id).0\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.138: \tnot (test id).0\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `0` is not an instance of type `bool`\n//│ ║  l.112: \t  in (r 0, r True)\n//│ ║         \t        ^\n//│ ╟── but it flows into field selection with expected type `bool`\n//│ ║  l.138: \tnot (test id).0\n//│ ╙──       \t    ^^^^^^^^^^^\n//│ res: bool | error\n//│    = true\n\n\n// * Note: works with dummy recursive definition (we used to have some hacks for rec defns)\nrec def test f =\n  let r x = f x\n  in (r 0, r True)\n//│ test: (0 -> 'a & true -> 'b) -> ('a, 'b,)\n//│     = [Function: test4]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TrickySimplif.mls",
    "content": ":NoJS\n\n\n// * This is fine\ndef f: 'a -> 'b -> ('a, 'b)\n//│ f: 'a -> 'b -> ('a, 'b,)\n\n// * This is fine\ndef f: ('b -> 'a) -> 'b\n//│ f: (nothing -> anything) -> nothing\n\n// * This could be simplified to `anything -> nothing`\ndef foo: ('a | 'b) -> ('a & 'b)\n//│ foo: ('a | 'b) -> ('a & 'b)\n\n// * Case in point\n(foo 1) : bool\n//│ res: bool\n\nrec def foo x = foo x\n//│ anything -> nothing\n//│   <:  foo:\n//│ ('a | 'b) -> ('a & 'b)\n\n\ndef f: MutArray['a & 'b]\n//│ f: MutArray['a]\n\ndef f: MutArray[('a & 'b, 'a)]\n//│ f: MutArray[('a & 'b, 'a,)]\n\ndef f: MutArray[('a & 'b, 'a | 'b)]\n//│ f: MutArray[('a, 'a,)]\n\ndef f: MutArray[('a & 'b, ('a | 'b) -> int)]\n//│ f: MutArray[('b, 'b -> int,)]\n\ndef f: MutArray[('a & 'b, ('a & 'b) -> int)]\n//│ f: MutArray[('a, 'a -> int,)]\n\ndef f: MutArray[('a & 'b) -> ('a & 'b)]\n//│ f: MutArray['a -> 'a]\n\ndef f: MutArray[('a & 'b) -> ('a | 'b)]\n//│ f: MutArray[('a & 'b) -> ('a | 'b)]\n\ndef f: MutArray[('a | 'b) -> ('a | 'b)]\n//│ f: MutArray['a -> 'a]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Trio.mls",
    "content": "\nclass A: { fA: int }\nclass B: { fB: string }\nclass C: { fC: bool }\n//│ Defined class A\n//│ Defined class B\n//│ Defined class C\n\ndef foo x = case x of {\n  | A -> x.fA\n  | B -> x.fB\n  | C -> x.fC\n  }\n//│ foo: ((A with {fA: 'fA}) | (B with {fB: 'fA}) | (C with {fC: 'fA})) -> 'fA\n//│    = [Function: foo]\n\n\nb = B { fB = \"test\" }\n//│ b: B & {fB: \"test\"}\n//│  = B { fB: 'test' }\n\n:stats\nfoo b\n//│ res: \"test\"\n//│    = 'test'\n//│ constrain calls  : 22\n//│ annoying  calls  : 10\n//│ subtyping calls  : 156\n\n\ndef arg: A | B | C\n//│ arg: A | B | C\n//│    = <missing implementation>\n\n:stats\nfoo arg\n//│ res: bool | int | string\n//│    = <no result>\n//│      arg is not implemented\n//│ constrain calls  : 37\n//│ annoying  calls  : 30\n//│ subtyping calls  : 342\n\n:stats\nfoo (arg with { fC = true })\n//│ res: int | string | true\n//│    = <no result>\n//│      arg is not implemented\n//│ constrain calls  : 30\n//│ annoying  calls  : 28\n//│ subtyping calls  : 274\n\ndef foo x = case x of {\n  | A -> add x.fA x.payload\n  | B -> x.fB\n  | C -> { l = x.fC; r = x.payload }\n  }\n//│ foo: (A & {payload: int} | (B with {fB: 'fB}) | (C with {fC: 'fC, payload: 'payload})) -> (int | {l: 'fC, r: 'payload} | 'fB)\n//│    = [Function: foo1]\n\n:e\n:stats\nfoo arg\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.63: \tfoo arg\n//│ ║        \t^^^^^^^\n//│ ╟── type `A` does not have field 'payload'\n//│ ║  l.31: \tdef arg: A | B | C\n//│ ║        \t         ^\n//│ ╟── but it flows into reference with expected type `{payload: ?payload}`\n//│ ║  l.63: \tfoo arg\n//│ ║        \t    ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.54: \t  | A -> add x.fA x.payload\n//│ ║        \t                  ^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.53: \tdef foo x = case x of {\n//│ ╙──      \t                 ^\n//│ res: error | int | string | {l: bool, r: nothing}\n//│    = <no result>\n//│      arg is not implemented\n//│ constrain calls  : 48\n//│ annoying  calls  : 40\n//│ subtyping calls  : 427\n\n:stats\nfoo (arg with { payload = 1 })\n//│ res: int | string | {l: bool, r: 1}\n//│    = <no result>\n//│      arg is not implemented\n//│ constrain calls  : 42\n//│ annoying  calls  : 38\n//│ subtyping calls  : 330\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TupleArray.mls",
    "content": "\nx = { a = 1 }\n//│ x: {a: 1}\n//│  = { a: 1 }\n\nx with { b = 2 }\n//│ res: {a: 1, b: 2}\n//│    = { a: 1, b: 2 }\n\ndef f x = x with { b = 2 }\n//│ f: 'a -> ('a\\b & {b: 2})\n//│  = [Function: f]\n\ndef r: {b: string; c: int}\\b\n//│ r: in {b: string, c: int}\\b out {c: int}\n//│  = <missing implementation>\n\n:e\nr = {c = 1}\n//│ {c: 1}\n//│   <:  r:\n//│ {b: string, c: int}\\b\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.19: \tr = {c = 1}\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── record literal of type `{c: 1}` does not have field 'b'\n//│ ║  l.19: \tr = {c = 1}\n//│ ║        \t    ^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.14: \tdef r: {b: string; c: int}\\b\n//│ ╙──      \t       ^^^^^^^^^^^^^^^^^^^\n//│  = { c: 1 }\n\n// * Note that \\b in negative position has special semantics\n// * (it's moved onto the LHS in a constraint)\n:e\nr = {b = \"a\", c = 1}\n//│ {b: \"a\", c: 1}\n//│   <:  r:\n//│ {b: string, c: int}\\b\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.37: \tr = {b = \"a\", c = 1}\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{c: 1}` does not match type `{b: string, c: int}`\n//│ ║  l.37: \tr = {b = \"a\", c = 1}\n//│ ║        \t    ^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.14: \tdef r: {b: string; c: int}\\b\n//│ ╙──      \t       ^^^^^^^^^^^^^^^^^^^\n//│  = { b: 'a', c: 1 }\n\n(1,2,3) with { 3 = \"oops\" }\n//│ res: (1, 2, 3,) & {3: \"oops\"}\n//│    = [ 1, 2, 3, 'oops' ]\n\n(1,2,3) with { 0 = \"oops\" }\n//│ res: {0: \"oops\", 1: 2, 2: 3}\n//│    = [ 'oops', 2, 3 ]\n\n:e\n(res: (int,int,int,)).0\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.61: \t(res: (int,int,int,)).0\n//│ ║        \t ^^^\n//│ ╟── `with` extension of type `{0: \"oops\", 1: 2, 2: 3}` is not a 3-element tuple\n//│ ║  l.56: \t(1,2,3) with { 0 = \"oops\" }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(int, int, int,)`\n//│ ║  l.61: \t(res: (int,int,int,)).0\n//│ ║        \t ^^^\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.61: \t(res: (int,int,int,)).0\n//│ ╙──      \t      ^^^^^^^^^^^^^^\n//│ res: int\n//│    = 'oops'\n\n\ndef r: int \\ 0\n//│ r: int\\0\n//│  = <missing implementation>\n\ndef r: (1,2,3) \\ 0\n//│ r: in (1, 2, 3,)\\0 out {1: 2, 2: 3}\n//│  = <missing implementation>\n// (1,2,3).toRecord \\ 1\n\ndef r: (1,2,3) \\ 12345\n//│ r: in (1, 2, 3,)\\12345 out (1, 2, 3,)\n//│  = <missing implementation>\n\ndef arr: Array[int]\narr = (1,2)\n//│ arr: Array[int]\n//│    = <missing implementation>\n//│ (1, 2,)\n//│   <:  arr:\n//│ Array[int]\n//│    = [ 1, 2 ]\n\nfr = f r\nfr : Array[int] & {b: int}\n//│ fr: (1, 2, 3,) & {b: 2}\n//│   = <no result>\n//│     r is not implemented\n//│ res: Array[int] & {b: int}\n//│    = <no result>\n//│      fr and r are not implemented\n\n:e\narr.0\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.110: \tarr.0\n//│ ║         \t^^^^^\n//│ ╟── type `Array[int]` does not have field '0'\n//│ ║  l.91: \tdef arr: Array[int]\n//│ ║        \t         ^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{0: ?a}`\n//│ ║  l.110: \tarr.0\n//│ ╙──       \t^^^\n//│ res: error\n//│    = 1\n\nrr = arr with { x = 1 }\n//│ rr: Array[int] & {x: 1}\n//│   = [ 1, 2, x: 1 ]\n\nrr.x\n//│ res: 1\n//│    = 1\n\n\n\n\n\n\nt = (1, 2, 3) with {x = 1}\n// t = (1, 2, 3)\n//│ t: (1, 2, 3,) & {x: 1}\n//│  = [ 1, 2, 3, x: 1 ]\n\nt.0\nt.1\nt.x\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n//│ res: 1\n//│    = 1\n\n\n\n// :d\ndef test: {x: 1} & (1, 2, 3)\n//│ test: (1, 2, 3,) & {x: 1}\n//│     = <missing implementation>\n\n\n// def f x = x[1]\n// Array['a] -> 'a\n\n// def f x = x.1\n// {1: 'a} -> 'a\n\n// f(... : Array[int])\n// Array[int] <: {1: 'a}\n\n// { 1 = 3456 }\n\n:e\nf(1,2,3) : 1 | 2 | 3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.171: \tf(1,2,3) : 1 | 2 | 3\n//│ ║         \t^^^^^^^^\n//│ ╟── argument list of type `(1, 2, 3,)` does not match type `(?a,)`\n//│ ║  l.171: \tf(1,2,3) : 1 | 2 | 3\n//│ ╙──       \t ^^^^^^^\n//│ res: 1 | 2 | 3\n//│    = [Number: 1] { b: 2 }\n\n:e\n(arr[0])[1][2]\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.182: \t(arr[0])[1][2]\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type `int` does not match type `Array[?a]`\n//│ ║  l.91: \tdef arr: Array[int]\n//│ ║        \t               ^^^\n//│ ╟── but it flows into array access with expected type `Array[?b]`\n//│ ║  l.182: \t(arr[0])[1][2]\n//│ ╙──       \t ^^^^^^\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.182: \t(arr[0])[1][2]\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── possibly-undefined array access of type `undefined` does not match type `Array[?a]`\n//│ ║  l.182: \t(arr[0])[1][2]\n//│ ╙──       \t^^^^^^^^^^^\n//│ res: error | undefined\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading '2')\n\n\nclass A: { x: int }\n//│ Defined class A\n\ndef myval: A & { x: anything }\n//│ myval: A\n//│      = <missing implementation>\n\n// def myval: a & { x: string }\n// //│ myval: A with {x: string}\n\n\ndef tuuu: (1 | 2, true) & {0: 2 | 3}\n//│ tuuu: (2, true,)\n//│     = <missing implementation>\n// tuuu: ((1 | 2) & (2 | 3), true,)\n// tuuu: (2, true,)\n\n// (S, T, U)\n// Array[S | T | U] & { 1: S; 2: T; 3: U }\n\ndef f(x: int, y: string) = x\n//│ f: (int, string,) -> int\n//│  = [Function: f1]\n\n// f(x = 1, y = \"asf\")\n\ndef f x = x\ndef f(x,) = x\n//│ f: 'a -> 'a\n//│  = [Function: f2]\n//│ f: 'a -> 'a\n//│  = [Function: f3]\n\n// (1, 2)\n// f((1, 2))\n\n// [1, 2]\n// f [1, 2]\n// f ([1, 2], 2, 3)\n\n\nf(1)\nf 1\n//│ res: 1\n//│    = 1\n//│ res: 1\n//│    = 1\n\nf((1,2))\n//│ res: (1, 2,)\n//│    = [ 1, 2 ]\n\n\ntrait T: { x: int }\n//│ Defined trait T\n\ndef t: T\n//│ t: T\n//│  = <missing implementation>\n\nt.x\n//│ res: int\n//│    = <no result>\n//│      t is not implemented\n\nrcd = { x = 1 }\n//│ rcd: {x: 1}\n//│    = { x: 1 }\n\nT rcd\n//│ res: {x: 1} & #T\n//│    = { x: 1 }\n\nres: { x: int }\n//│ res: {x: int}\n//│    = { x: 1 }\n\n\n(1,2, (true, false, (\"hello\", \"world\", \"bye\")))\n//│ res: (1, 2, (true, false, (\"hello\", \"world\", \"bye\",),),)\n//│    = [ 1, 2, [ true, false, [ 'hello', 'world', 'bye' ] ] ]\n\nk1 = (6, \"hi\", false) with {4=5; 5=true}\nk1.0\nk1.2\n//│ k1: (6, \"hi\", false,) & {4: 5, 5: true}\n//│   = [ 6, 'hi', false, <1 empty item>, 5, true ]\n//│ res: 6\n//│    = 6\n//│ res: false\n//│    = false\n\n(1,2,3) with {1 = \"hello\"; _a = true; 3 = 4}\n//│ res: {0: 1, 1: \"hello\", 2: 3, 3: 4, _a: true}\n//│    = [ 1, 'hello', 3, 4, _a: true ]\n\n(1,2,3) with {1 = true; 0 = 233}\n//│ res: {0: 233, 1: true, 2: 3}\n//│    = [ 233, true, 3 ]\n\n(1, 2, true) with {0 = \"hello\"}\n//│ res: {0: \"hello\", 1: 2, 2: true}\n//│    = [ 'hello', 2, true ]\n\nta1 = (5, 6, true, false, \"hahaha\")\nta2 = ta1 with {x = 123; 7 = \"bye\"; 0 = 0}\nta1.0\nta2.1\nta2.2\n//│ ta1: (5, 6, true, false, \"hahaha\",)\n//│    = [ 5, 6, true, false, 'hahaha' ]\n//│ ta2: {0: 0, 1: 6, 2: true, 3: false, 4: \"hahaha\", 7: \"bye\", x: 123}\n//│    = [ 0, 6, true, false, 'hahaha', <2 empty items>, 'bye', x: 123 ]\n//│ res: 5\n//│    = 5\n//│ res: 6\n//│    = 6\n//│ res: true\n//│    = true\n\ndef rep5: 'a -> Array['a]\ndef rep5 x = (x,x,x,x,x)\n//│ rep5: 'a -> Array['a]\n//│     = <missing implementation>\n//│ 'a -> ('a, 'a, 'a, 'a, 'a,)\n//│   <:  rep5:\n//│ 'a -> Array['a]\n//│     = [Function: rep5]\n\nrep5 1 with {0 = 10}\na2 = rep5 2 with {1 = true; x = \"haha\"}\na2.1\na2.x\n//│ res: Array[1] & {0: 10}\n//│    = [ 10, 1, 1, 1, 1 ]\n//│ a2: Array[2] & {1: true, x: \"haha\"}\n//│   = [ 2, true, 2, 2, 2, x: 'haha' ]\n//│ res: true\n//│    = true\n//│ res: \"haha\"\n//│    = 'haha'\n\n:e\na2.0\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.346: \ta2.0\n//│ ║         \t^^^^\n//│ ╟── type `Array['a]` does not match type `{0: ?a} | ~{1: true, x: \"haha\"}`\n//│ ║  l.323: \tdef rep5: 'a -> Array['a]\n//│ ║         \t                ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{0: ?a} | ~{1: true, x: \"haha\"}`\n//│ ║  l.346: \ta2.0\n//│ ╙──       \t^^\n//│ res: error\n//│    = 2\n\n(1,2,3,true) with {_a = 1; _b1 = false}\n//│ res: (1, 2, 3, true,) & {_a: 1, _b1: false}\n//│    = [ 1, 2, 3, true, _a: 1, _b1: false ]\n\nht1 = (1,2,false) with {0 = 'a'; 1 = 'hello'; 2 = false}\nht1.0\n//│ ht1: {0: \"a\", 1: \"hello\", 2: false}\n//│    = [ 'a', 'hello', false ]\n//│ res: \"a\"\n//│    = 'a'\n\ndef hg1 t = (t.0, t.1)\nhg1 ht1\nhg1 ((5,5,5))\n(hg1 ht1).1\n//│ hg1: {0: 'a, 1: 'b} -> ('a, 'b,)\n//│    = [Function: hg1]\n//│ res: (\"a\", \"hello\",)\n//│    = [ 'a', 'hello' ]\n//│ res: (5, 5,)\n//│    = [ 5, 5 ]\n//│ res: \"hello\"\n//│    = 'hello'\n\ndef ta1: Array[int] | (int, bool)\ndef test: (string, 1) & { 0: \"hello\" }\ndef test2: (string, 1) & { 0: \"hello\"; 2: int }\n//│ ta1: Array[bool | int]\n//│    = <missing implementation>\n//│ test: (\"hello\", 1,)\n//│     = <missing implementation>\n//│ test2: (\"hello\", 1,) & {2: int}\n//│      = <missing implementation>\n\ntest: { 0: 'a }\n//│ res: {0: \"hello\"}\n//│    = <no result>\n//│      test is not implemented\n\n// TODO: One could expect (\"hello\", 1,) here,\n//    but we currently don't recover the intersected positional field from the record\n//    when constraining refined tuples.\ntest: ('a, 1)\n//│ res: (string, 1,)\n//│    = <no result>\n//│      test is not implemented\n\n// TODO in principe, we could narrow the refinement to ` & { 1: 1 }` here...\ndef test3: Array[1] & { 0: int }\n//│ test3: Array[1] & {0: int}\n//│      = <missing implementation>\n\ndef fta1: Array[int | bool] -> int\ndef tb1: (int, true)\nfta1 tb1\nr1 = if true then (1,2,3) else (1, 2)\nfta1 r1\n//│ fta1: Array[bool | int] -> int\n//│     = <missing implementation>\n//│ tb1: (int, true,)\n//│    = <missing implementation>\n//│ res: int\n//│    = <no result>\n//│      fta1 is not implemented\n//│ r1: Array[1 | 2 | 3] & {0: 1, 1: 2}\n//│   = [ 1, 2, 3 ]\n//│ res: int\n//│    = <no result>\n//│      fta1 is not implemented\n\n:NoJS\ndef p1: T | Array[bool] | (int, string) | (true, 3)\ndef p2: T | (string, bool) | Array[int] | (2, 4)\ndef pf t = (t[1], t.0)\npf((1,2,3))\n//│ p1: Array[bool | int | string] | T\n//│ p2: Array[bool | int | string] | T\n//│ pf: (Array['a & ~undefined] & {0: 'b}) -> (undefined | 'a, 'b,)\n//│ res: (1 | 2 | 3 | undefined, 1,)\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TupleArray2.mls",
    "content": "\n:e\n(1,2): (2,1)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.3: \t(1,2): (2,1)\n//│ ║       \t^^^^^\n//│ ╟── integer literal of type `1` does not match type `2`\n//│ ║  l.3: \t(1,2): (2,1)\n//│ ║       \t ^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.3: \t(1,2): (2,1)\n//│ ╙──     \t        ^\n//│ res: (2, 1,)\n//│    = [ 1, 2 ]\n\n:e\n(1,2): (2,1,0)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.17: \t(1,2): (2,1,0)\n//│ ║        \t^^^^^\n//│ ╟── tuple literal of type `(1, 2,)` does not match type `(2, 1, 0,)`\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.17: \t(1,2): (2,1,0)\n//│ ╙──      \t       ^^^^^^^\n//│ res: (2, 1, 0,)\n//│    = [ 1, 2 ]\n\n:e\n(1,2) with { x = 1 } : (2,1,0)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.29: \t(1,2) with { x = 1 } : (2,1,0)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── `with` extension of type `(1, 2,) & {x: 1}` is not a 3-element tuple\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.29: \t(1,2) with { x = 1 } : (2,1,0)\n//│ ╙──      \t                       ^^^^^^^\n//│ res: (2, 1, 0,)\n//│    = [ 1, 2, x: 1 ]\n\ntrait T\n//│ Defined trait T\n\n:e\n(1,2) with { x = 1 } : (2,1,0) | t\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.44: \t(1,2) with { x = 1 } : (2,1,0) | t\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── `with` extension of type `(1, 2,) & {x: 1}` does not match type `(2, 1, 0,) | #T`\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.44: \t(1,2) with { x = 1 } : (2,1,0) | t\n//│ ╙──      \t                       ^^^^^^^^^^^\n//│ res: (2, 1, 0,) | #T\n//│    = [ 1, 2, x: 1 ]\n\n:e\n(1,2) with { x = 1 } : (2,1)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.56: \t(1,2) with { x = 1 } : (2,1)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `2`\n//│ ║  l.56: \t(1,2) with { x = 1 } : (2,1)\n//│ ║        \t ^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.56: \t(1,2) with { x = 1 } : (2,1)\n//│ ╙──      \t                        ^\n//│ res: (2, 1,)\n//│    = [ 1, 2, x: 1 ]\n\n(1,2) with { x = 1 } : (1,2)\n//│ res: (1, 2,)\n//│    = [ 1, 2, x: 1 ]\n\n\n:re\nerror: (1,2) & t | Array[3]\n//│ res: Array[3] | (1, 2,) & #T\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\ndef arr: Array[1]\n//│ arr: Array[1]\n//│    = <missing implementation>\n\narr: Array[2] | (1, 1)\n//│ res: Array[1 | 2]\n//│    = <no result>\n//│      arr is not implemented\n\narr: Array[2] | (1, 2)\n//│ res: Array[1 | 2]\n//│    = <no result>\n//│      arr is not implemented\n\n:e\narr: Array[2] & t | (1, 1)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.96: \tarr: Array[2] & t | (1, 1)\n//│ ║        \t^^^\n//│ ╟── type `Array[1]` does not match type `Array[2] & #T | (1, 1,)`\n//│ ║  l.81: \tdef arr: Array[1]\n//│ ║        \t         ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Array[2] & #T | (1, 1,)`\n//│ ║  l.96: \tarr: Array[2] & t | (1, 1)\n//│ ║        \t^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.96: \tarr: Array[2] & t | (1, 1)\n//│ ╙──      \t     ^^^^^^^^^^^^^^^^^^^^^\n//│ res: Array[2] & #T | (1, 1,)\n//│    = <no result>\n//│      arr is not implemented\n\ndef arrt: Array[1] & t\n//│ arrt: Array[1] & #T\n//│     = <missing implementation>\n\narrt: Array[2] & t | (1, 1)\n//│ res: Array[2] & #T | (1, 1,)\n//│    = <no result>\n//│      arrt is not implemented\n\n\ndef f_1: 'a -> (Array['a] & t)\n//│ f_1: 'a -> (Array['a] & #T)\n//│    = <missing implementation>\n\ndef f_2: 'a -> (Array['a] & t | (1,))\n//│ f_2: 'a -> (Array['a] & #T | (1,))\n//│    = <missing implementation>\n\n:e\nf_1 = f_2\n//│ 'a -> (Array['a] & #T | (1,))\n//│   <:  f_1:\n//│ 'a -> (Array['a] & #T)\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.132: \tf_1 = f_2\n//│ ║         \t^^^^^^^^^\n//│ ╟── type `1` does not match type `'a`\n//│ ║  l.127: \tdef f_2: 'a -> (Array['a] & t | (1,))\n//│ ║         \t                                 ^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.123: \tdef f_1: 'a -> (Array['a] & t)\n//│ ╙──       \t                      ^^\n//│    = <no result>\n//│      f_2 is not implemented\n\nf_2 = f_1\n//│ 'a -> (Array['a] & #T)\n//│   <:  f_2:\n//│ 'a -> (Array['a] & #T | (1,))\n//│    = <no result>\n//│      f_1 and f_2 are not implemented\n\n\n\ndef test: (string, 1) & { 0: \"hello\" }\n//│ test: (\"hello\", 1,)\n//│     = <missing implementation>\n\n:e\ntest = (\"hi\", 1)\n//│ (\"hi\", 1,)\n//│   <:  test:\n//│ (\"hello\", 1,)\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.162: \ttest = (\"hi\", 1)\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"hi\"` does not match type `\"hello\"`\n//│ ║  l.162: \ttest = (\"hi\", 1)\n//│ ║         \t        ^^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.157: \tdef test: (string, 1) & { 0: \"hello\" }\n//│ ╙──       \t                             ^^^^^^^\n//│     = [ 'hi', 1 ]\n\ntest = (\"hello\", 1)\n//│ (\"hello\", 1,)\n//│   <:  test:\n//│ (\"hello\", 1,)\n//│     = [ 'hello', 1 ]\n\n(fun ((a, b)) -> a) test\n//│ res: string\n//│    = 'hello'\n\ntest: { 0: 'a }\n//│ res: {0: \"hello\"}\n//│    = [ 'hello', 1 ]\n\ntest: ('a, 1)\n//│ res: (string, 1,)\n//│    = [ 'hello', 1 ]\n\n:e\nclass A: (1,2)\n//│ ╔══[ERROR] cannot inherit from a tuple type\n//│ ║  l.196: \tclass A: (1,2)\n//│ ╙──       \t      ^^^^^^^^\n\n\n:re\nerror: Array[1] & { 0: int }\n//│ res: Array[1] & {0: int}\n//│ Runtime error:\n//│   Error: an error was thrown\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TypeClasses.mls",
    "content": "\nclass Monoid[A]\n  method Empty: A\n  method Add: A -> A -> A\n//│ Defined class Monoid[=A]\n//│ Declared Monoid.Empty: Monoid['A] -> 'A\n//│ Declared Monoid.Add: Monoid['A] -> 'A -> 'A -> 'A\n\nclass IntMonoid: Monoid[int]\n  method Empty = 0\n  method Add = add\ndef IntMonoid = IntMonoid {}\n//│ Defined class IntMonoid\n//│ Defined IntMonoid.Empty: IntMonoid -> 0\n//│ Defined IntMonoid.Add: IntMonoid -> int -> int -> int\n//│ IntMonoid: IntMonoid\n//│          = [Function: IntMonoid1]\n\nclass Numb: { val: int }\n//│ Defined class Numb\n\nclass NumMonoid: Monoid[Numb]\n  method Empty = Numb { val = 1 }\n  method Add this that = Numb { val = this.val * that.val }\n//│ Defined class NumMonoid\n//│ Defined NumMonoid.Empty: NumMonoid -> (Numb & {val: 1})\n//│ Defined NumMonoid.Add: NumMonoid -> {val: int} -> {val: int} -> Numb\n\nclass Complex[A]: { real: A; imaginary: A }\n  method Map f = Complex { real = f this.real; imaginary = f this.imaginary }\ndef Complex real imaginary = Complex { real; imaginary }\n//│ Defined class Complex[+A]\n//│ Defined Complex.Map: Complex['A] -> ('A -> 'real) -> (Complex['real] with {imaginary: 'real, real: 'real})\n//│ Complex: ('real & 'A) -> ('A & 'imaginary) -> (Complex['A] with {imaginary: 'imaginary, real: 'real})\n//│        = [Function: Complex1]\n\nclass ComplexMonoid[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n  method Empty = Complex this.base.Empty this.base.Empty\n  method Add self that =\n    Complex (this.base.Add self.real that.real) (this.base.Add self.imaginary that.imaginary)\n  method Add2 (self: Complex['_]) (that: Complex['_]) =\n    Complex (this.base.(Monoid.Add) self.real that.real) (this.base.(Monoid.Add) self.imaginary that.imaginary)\n//│ Defined class ComplexMonoid[=A]\n//│ Defined ComplexMonoid.Empty: ComplexMonoid['A] -> Complex['A]\n//│ Defined ComplexMonoid.Add: ComplexMonoid['A] -> {imaginary: 'A, real: 'A} -> {imaginary: 'A, real: 'A} -> Complex['A]\n//│ Defined ComplexMonoid.Add2: ComplexMonoid['A] -> Complex['A] -> Complex['A] -> Complex['A]\n\ncmi = ComplexMonoid { base = IntMonoid }\n//│ cmi: ComplexMonoid[int] with {base: IntMonoid}\n//│    = ComplexMonoid { base: IntMonoid {} }\n\ndef ComplexMonoid base = ComplexMonoid { base }\n//│ ComplexMonoid: (Monoid['A] & 'base) -> (ComplexMonoid['A] with {base: 'base})\n//│              = [Function: ComplexMonoid1]\n\ncmi = ComplexMonoid IntMonoid\n//│ cmi: ComplexMonoid[int] with {base: IntMonoid}\n//│    = ComplexMonoid { base: IntMonoid {} }\n\ncmi.Empty\n//│ res: Complex[int]\n//│    = Complex { real: 0, imaginary: 0 }\n\ncmi.Empty.real\n//│ res: int\n//│    = 0\n\nc12 = Complex 1 2\nc34 = Complex 3 4\n//│ c12: Complex[1 | 2] & {imaginary: 2, real: 1}\n//│    = Complex { real: 1, imaginary: 2 }\n//│ c34: Complex[3 | 4] & {imaginary: 4, real: 3}\n//│    = Complex { real: 3, imaginary: 4 }\n\nif true then c12 else c34\n//│ res: Complex[1 | 2 | 3 | 4] & {imaginary: 2 | 4, real: 1 | 3}\n//│    = Complex { real: 1, imaginary: 2 }\n\ncmi.Add (Complex 1 2) (Complex 3 4)\n//│ res: Complex[int]\n//│    = Complex { real: 4, imaginary: 6 }\n\n\n\n// === === === ERROR CASES === === === //\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\n\ncmi = ComplexMonoid { base = IntMonoid }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tcmi = ComplexMonoid { base = IntMonoid }\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{base: forall ?a. ?a}` is not an instance of type `Monoid`\n//│ ║  l.+1: \tcmi = ComplexMonoid { base = IntMonoid }\n//│ ║        \t                    ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.37: \tclass ComplexMonoid[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n//│ ║        \t                                                     ^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.52: \tdef ComplexMonoid base = ComplexMonoid { base }\n//│ ╙──      \t                                         ^^^^\n//│ cmi: (ComplexMonoid['A] with {base: {base: IntMonoid}}) | error\n\n\n\nclass ComplexMonoid_bad_0[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n  method Empty = Complex { real = this.base }\n  method Add this that = error\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b)` is not an instance of type `Complex`\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `Complex[?]`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.+1: \tclass ComplexMonoid_bad_0[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n//│ ║        \t                                     ^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `forall ?a ?b. ?a -> ?b` is not a record (expected a record with fields: real, imaginary)\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `{imaginary: A, real: A}`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.29: \tclass Complex[A]: { real: A; imaginary: A }\n//│ ║        \t                  ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `forall ?a ?b. ?a -> ?b` is not a record (expected a record with fields: real, imaginary)\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `{imaginary: A, real: A}`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.29: \tclass Complex[A]: { real: A; imaginary: A }\n//│ ║        \t                  ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `forall ?a ?b. ?a -> ?b` does not have field 'Complex#A'\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `{Complex#A <: A}`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.+1: \tclass ComplexMonoid_bad_0[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n//│ ║        \t                                     ^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ Defined class ComplexMonoid_bad_0[=A]\n//│ Defined ComplexMonoid_bad_0.Empty: ComplexMonoid_bad_0['A] -> 'A0 -> (Complex[{real: Monoid['A]} | 'A0] with {imaginary: 'A0, real: {real: Monoid['A]}})\n//│ Defined ComplexMonoid_bad_0.Add: ComplexMonoid_bad_0['A] -> anything -> anything -> nothing\n\n\nclass ComplexMonoid_bad_1[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n  method Add this that = error\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t                                                               ^^^^^^^^^^^^^^\n//│ ╟── reference of type `ComplexMonoid_bad_1[A] & this` does not have field 'imaginary'\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ╙──      \t                                                               ^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b)` is not an instance of type `Complex`\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `Complex[?]`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.+1: \tclass ComplexMonoid_bad_1[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n//│ ║        \t                                     ^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `forall ?a ?b. ?a -> ?b` is not a record (expected a record with fields: real, imaginary)\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `{imaginary: A, real: A}`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.29: \tclass Complex[A]: { real: A; imaginary: A }\n//│ ║        \t                  ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `forall ?a ?b. ?a -> ?b` is not a record (expected a record with fields: real, imaginary)\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `{imaginary: A, real: A}`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from record type:\n//│ ║  l.29: \tclass Complex[A]: { real: A; imaginary: A }\n//│ ║        \t                  ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in method definition:\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── function of type `forall ?a ?b. ?a -> ?b` does not have field 'Complex#A'\n//│ ║  l.31: \tdef Complex real imaginary = Complex { real; imaginary }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into application with expected type `{Complex#A <: A}`\n//│ ║  l.+2: \t  method Empty = Complex { real = this.base.Empty; imaginary = this.imaginary.Empty }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.+1: \tclass ComplexMonoid_bad_1[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n//│ ║        \t                                     ^^^^^^^^^^\n//│ ╟── from inherited method declaration:\n//│ ║  l.3: \t  method Empty: A\n//│ ╙──     \t         ^^^^^^^^\n//│ Defined class ComplexMonoid_bad_1[=A]\n//│ Defined ComplexMonoid_bad_1.Empty: ComplexMonoid_bad_1['A] -> 'A0 -> (Complex[{imaginary: nothing, real: 'A} | 'A0] with {imaginary: 'A0, real: {imaginary: nothing, real: 'A}})\n//│ Defined ComplexMonoid_bad_1.Add: ComplexMonoid_bad_1['A] -> anything -> anything -> nothing\n\n\nclass ComplexMonoid_bad_2[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n  method Add self that =\n    Complex (this.base.Add self.real that.real) (this.base.Add self.imaginary that.imaginary)\n  method Add2 (self: Complex['_]) (that: Complex['_]) =\n    Complex (this.base.Add self.real that.real) (this.base.Add self.imaginary that.imaginary)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+5: \t    Complex (this.base.Add self.real that.real) (this.base.Add self.imaginary that.imaginary)\n//│ ║        \t             ^^^^^^^^^^^^^\n//│ ╟── type `Monoid[A]` is not an instance of type `ComplexMonoid_bad_2`\n//│ ║  l.+1: \tclass ComplexMonoid_bad_2[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n//│ ║        \t                                                           ^^^^^^^^^\n//│ ╟── but it flows into field selection with expected type `ComplexMonoid_bad_2[?]`\n//│ ║  l.+5: \t    Complex (this.base.Add self.real that.real) (this.base.Add self.imaginary that.imaginary)\n//│ ╙──      \t             ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.+5: \t    Complex (this.base.Add self.real that.real) (this.base.Add self.imaginary that.imaginary)\n//│ ║        \t                                                 ^^^^^^^^^^^^^\n//│ ╟── type `Monoid[A]` is not an instance of type `ComplexMonoid_bad_2`\n//│ ║  l.+1: \tclass ComplexMonoid_bad_2[A]: Monoid[Complex[A]] & { base: Monoid[A] }\n//│ ║        \t                                                           ^^^^^^^^^\n//│ ╟── but it flows into field selection with expected type `ComplexMonoid_bad_2[?]`\n//│ ║  l.+5: \t    Complex (this.base.Add self.real that.real) (this.base.Add self.imaginary that.imaginary)\n//│ ╙──      \t                                                 ^^^^^^^^^\n//│ Defined class ComplexMonoid_bad_2[=A]\n//│ Defined ComplexMonoid_bad_2.Add: ComplexMonoid_bad_2['A] -> {imaginary: 'A, real: 'A} -> {imaginary: 'A, real: 'A} -> Complex['A]\n//│ Defined ComplexMonoid_bad_2.Add2: ComplexMonoid_bad_2['A] -> Complex[?] -> Complex[?] -> Complex[error]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TypeDefs.mls",
    "content": "\nclass Test1: { x: int }\n//│ Defined class Test1\n\nTest1\n//│ res: {x: int & 'x} -> (Test1 with {x: 'x})\n//│    = [Function: res]\n\nTest1 { x = 123 }\n//│ res: Test1 & {x: 123}\n//│    = Test1 { x: 123 }\n\n:e\nTest1 { x = \"oops\" }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.14: \tTest1 { x = \"oops\" }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `int`\n//│ ║  l.14: \tTest1 { x = \"oops\" }\n//│ ║        \t            ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.2: \tclass Test1: { x: int }\n//│ ╙──     \t                  ^^^\n//│ res: (Test1 with {x: \"oops\"}) | error\n//│    = Test1 { x: 'oops' }\n\ndef Test1 = fun x -> Test1 { x = x }\n//│ Test1: (int & 'x) -> (Test1 with {x: 'x})\n//│      = [Function: Test11]\n\nclass Test11: { x: int }\ndef Test11 x = Test11 { x }\n//│ Defined class Test11\n//│ Test11: (int & 'x) -> (Test11 with {x: 'x})\n//│       = [Function: Test112]\n\n\n:e\ntype Test1 = { x: int }\n//│ ╔══[ERROR] Type 'Test1' is already defined.\n//│ ║  l.39: \ttype Test1 = { x: int }\n//│ ╙──      \t     ^^^^^\n\ntype Test2 = { x: int }\n//│ Defined type alias Test2\n\n:pe\nclass Test = { x: int }\n//│ /!\\ Parse error: Expected end-of-input:1:12, found \"= { x: int\" at l.48:12: class Test = { x: int }\n\n:pe\ntype Test: { x: int }\n//│ /!\\ Parse error: Expected \"=\":1:10, found \": { x: int\" at l.52:10: type Test: { x: int }\n\ntype Test3 = int -> int\n//│ Defined type alias Test3\n\ntype Test4 = int -> int -> int\n//│ Defined type alias Test4\n\ntype Test5 = (int -> int) -> int\n//│ Defined type alias Test5\n\n\ntype T = int\n//│ Defined type alias T\n\n:e\ntype T = int\ntype T = int\n//│ ╔══[ERROR] Type 'T' is already defined.\n//│ ║  l.69: \ttype T = int\n//│ ╙──      \t     ^\n//│ ╔══[ERROR] Type 'T' is already defined.\n//│ ║  l.70: \ttype T = int\n//│ ╙──      \t     ^\n\n:e\n:ge\ntype TypeA = int\nfoo 42\ndef foo = 1\nfoo 42\n//│ Defined type alias TypeA\n//│ ╔══[ERROR] identifier not found: foo\n//│ ║  l.81: \tfoo 42\n//│ ╙──      \t^^^\n//│ res: error\n//│ foo: 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.83: \tfoo 42\n//│ ║        \t^^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.82: \tdef foo = 1\n//│ ║        \t          ^\n//│ ╟── but it flows into reference with expected type `42 -> ?a`\n//│ ║  l.83: \tfoo 42\n//│ ╙──      \t^^^\n//│ res: error\n//│ Code generation encountered an error:\n//│   unresolved symbol foo\n\n42: TypeA\n//│ res: TypeA\n//│    = 42\n\n:e\ntype TypeOops = TypeOops\ntype TypeB = TypeC\ndef test = fun x -> (x: TypeB)\ntest 42\ntype TypeC = TypeA\n//│ ╔══[ERROR] illegal cycle involving type TypeOops\n//│ ║  l.108: \ttype TypeOops = TypeOops\n//│ ╙──       \t     ^^^^^^^^^^^^^^^^^^^\n//│ Defined type alias TypeB\n//│ Defined type alias TypeC\n//│ test: TypeB -> TypeB\n//│     = [Function: test]\n//│ res: TypeB\n//│    = 42\n\n\n\ndef test = fun (x: TypeB) -> x\n//│ test: TypeB -> TypeB\n//│     = [Function: test1]\n\n\n\n// Note: type alias definitions can contain type variables,\n//   which are refreshed on every use (every expansion) of the alias\ntype Lol = { x: 'a -> 'a }\n//│ Defined type alias Lol\n\n:re\nerror: Lol -> Lol\n//│ res: Lol -> Lol\n//│ Runtime error:\n//│   Error: an error was thrown\n\n{ x = id } : Lol\n//│ res: Lol\n//│    = { x: [Function: id] }\n\n\n:e\ntype Runaway[A] = Runaway['a]\n//│ ╔══[ERROR] illegal cycle involving type Runaway\n//│ ║  l.148: \ttype Runaway[A] = Runaway['a]\n//│ ╙──       \t     ^^^^^^^^^^^^^^^^^^^^^^^^\n\n:e\ntype Runaway[A] = 'a -> Runaway['a]\ntype RunawayAlias = Runaway[int]\n//│ ╔══[ERROR] Type definition is not regular: it occurs within itself as Runaway['a], but is defined as Runaway['A]\n//│ ║  l.154: \ttype Runaway[A] = 'a -> Runaway['a]\n//│ ╙──       \t     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] type identifier not found: Runaway\n//│ ║  l.155: \ttype RunawayAlias = Runaway[int]\n//│ ╙──       \t                    ^^^^^^^^^^^^\n//│ Defined type alias RunawayAlias\n\n\ntype Runaway2 = Lol -> Runaway2\n//│ Defined type alias Runaway2\n\n:e\nid: Runaway2\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.169: \tid: Runaway2\n//│ ║         \t^^\n//│ ╟── type `{x: 'a -> 'a}` is not a function\n//│ ║  l.133: \ttype Lol = { x: 'a -> 'a }\n//│ ║         \t           ^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.165: \ttype Runaway2 = Lol -> Runaway2\n//│ ║         \t                ^^^^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.165: \ttype Runaway2 = Lol -> Runaway2\n//│ ╙──       \t                       ^^^^^^^^\n//│ res: Runaway2\n//│    = [Function: id]\n\n:re\nerror: Runaway2\n//│ res: Runaway2\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:e\n:re\nerror: {x: int} -> nothing : Runaway2\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.193: \terror: {x: int} -> nothing : Runaway2\n//│ ║         \t^^^^^\n//│ ╟── type `'a -> 'a` is not an instance of type `int`\n//│ ║  l.133: \ttype Lol = { x: 'a -> 'a }\n//│ ║         \t                ^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.193: \terror: {x: int} -> nothing : Runaway2\n//│ ╙──       \t           ^^^\n//│ res: Runaway2\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:re\nerror: {x: 'x -> 'x} -> nothing : Runaway2\n//│ res: Runaway2\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n\n\ntype A1[A] = A -> A -> A1[A]\ntype A2[A] = A -> A2[A]\n//│ Defined type alias A1[-A]\n//│ Defined type alias A2[-A]\n\ndef ty1: A1[anything]\ndef ty2: A2[anything]\n//│ ty1: A1[anything]\n//│    = <missing implementation>\n//│ ty2: A2[anything]\n//│    = <missing implementation>\n\nty1 = ty2\n//│ A2[anything]\n//│   <:  ty1:\n//│ A1[anything]\n//│    = <no result>\n//│      ty2 is not implemented\n\nty2 = ty1\n//│ A1[anything]\n//│   <:  ty2:\n//│ A2[anything]\n//│    = <no result>\n//│      ty1 and ty2 are not implemented\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TypeRanges.mls",
    "content": "\n\ndef set0: MutArray['a..'b] -> 'a -> ()\n//│ set0: MutArray['b] -> 'b -> ()\n//│     = <missing implementation>\n\ndef set1: MutArray['a..'b] -> 'b -> ()\n//│ set1: MutArray['b] -> 'b -> ()\n//│     = <missing implementation>\n\ndef set2: MutArray[int..number] -> int -> ()\n//│ set2: in MutArray[in int out number] -> int -> () out MutArray[in number out int] -> int -> ()\n//│     = <missing implementation>\n\n:e\ndef set3: MutArray[number..int] -> 'b -> ()\n//│ ╔══[ERROR] Type mismatch in type bounds:\n//│ ║  l.16: \tdef set3: MutArray[number..int] -> 'b -> ()\n//│ ║        \t                   ^^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.16: \tdef set3: MutArray[number..int] -> 'b -> ()\n//│ ║        \t                   ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.16: \tdef set3: MutArray[number..int] -> 'b -> ()\n//│ ╙──      \t                           ^^^\n//│ set3: in MutArray[in number out int] -> anything -> () out MutArray[in int out number] -> anything -> ()\n//│     = <missing implementation>\n\n\n:ns\nfun x -> set2 x 0\n//│ res: forall 'a 'b. 'a -> 'b\n//│   where\n//│     'b :> ()\n//│     'a <: MutArray[in int out number]\n//│    = <no result>\n//│      set2 is not implemented\n\n// :ns\nfun x -> set0 x 0\nfun x -> set1 x 0\n//│ res: MutArray[in 0 | 'b out 'b] -> ()\n//│    = <no result>\n//│      set0 is not implemented\n//│ res: MutArray[in 0 | 'b out 'b] -> ()\n//│    = <no result>\n//│      set1 is not implemented\n\n\ndef foo: MutArray[int..number]\n//│ foo: in MutArray[in number out int] out MutArray[in int out number]\n//│    = <missing implementation>\n\n:e\n:ng\nfoo = foo\n//│ MutArray[in int out number]\n//│   <:  foo:\n//│ MutArray[in number out int]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.56: \tfoo = foo\n//│ ║        \t^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                  ^^^\n//│ ╟── from type bounds:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ╙──      \t                  ^^^^^^^^^^^\n\n:e\nfoo = (mut 0,)\n//│ (mut 'a,)\n//│   where\n//│     'a :> 0\n//│   <:  foo:\n//│ MutArray[in number out int]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.74: \tfoo = (mut 0,)\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── but it flows into mutable tuple field with expected type `int`\n//│ ║  l.74: \tfoo = (mut 0,)\n//│ ║        \t           ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                  ^^^\n//│ ╟── from type bounds:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ╙──      \t                  ^^^^^^^^^^^\n//│    = [ 0 ]\n\n:e\nset0 foo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.98: \tset0 foo\n//│ ║        \t^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                  ^^^\n//│ ╟── from type bounds:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ╙──      \t                  ^^^^^^^^^^^\n//│ res: error | int -> ()\n//│    = <no result>\n//│      set0 is not implemented\n\n:e\nset2 foo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.116: \tset2 foo\n//│ ║         \t^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.11: \tdef set2: MutArray[int..number] -> int -> ()\n//│ ║        \t                   ^^^\n//│ ╟── from type bounds:\n//│ ║  l.11: \tdef set2: MutArray[int..number] -> int -> ()\n//│ ╙──      \t                   ^^^^^^^^^^^\n//│ res: error | int -> ()\n//│    = <no result>\n//│      set2 is not implemented\n\n:e\nfoo : MutArray['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.134: \tfoo : MutArray['a]\n//│ ║         \t^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                  ^^^\n//│ ╟── from type bounds:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ╙──      \t                  ^^^^^^^^^^^\n//│ res: MutArray['a]\n//│   where\n//│     'a :> number\n//│        <: int\n//│    = [ 0 ]\n\nfoo : Array['a]\n//│ res: Array[number]\n//│    = [ 0 ]\n\n:e\nfoo[0] <- 1\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.158: \tfoo[0] <- 1\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                  ^^^\n//│ ╟── from assigned array element:\n//│ ║  l.158: \tfoo[0] <- 1\n//│ ╙──       \t^^^^^^\n//│ = undefined\n\nfoo[0]\n//│ res: number | undefined\n//│    = 1\n\nres : number | undefined\n//│ res: number | undefined\n//│    = 1\n\nfoo[0]\n//│ res: number | undefined\n//│    = 1\n\n:e\nres : int | undefined\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.186: \tres : int | undefined\n//│ ║         \t^^^\n//│ ╟── type `number` does not match type `int | undefined`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── but it flows into reference with expected type `int | undefined`\n//│ ║  l.186: \tres : int | undefined\n//│ ║         \t^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.186: \tres : int | undefined\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ res: int | undefined\n//│    = 1\n\n\n:e\nfoo2 = foo : MutArray['a..'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.204: \tfoo2 = foo : MutArray['a..'b]\n//│ ║         \t       ^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                  ^^^\n//│ ╟── from type bounds:\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ╙──      \t                  ^^^^^^^^^^^\n//│ foo2: MutArray[in int & 'b out number | 'b]\n//│     = [ 1 ]\n\nfoo2[0]\n//│ res: number | undefined\n//│    = 1\n\n:e\nres : undefined\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.225: \tres : undefined\n//│ ║         \t^^^\n//│ ╟── type `number` does not match type `undefined`\n//│ ║  l.50: \tdef foo: MutArray[int..number]\n//│ ║        \t                       ^^^^^^\n//│ ╟── but it flows into reference with expected type `undefined`\n//│ ║  l.225: \tres : undefined\n//│ ║         \t^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.225: \tres : undefined\n//│ ╙──       \t      ^^^^^^^^^\n//│ res: undefined\n//│    = 1\n\n\n:e\ndef foo: MutArray[number..int]\n//│ ╔══[ERROR] Type mismatch in type bounds:\n//│ ║  l.243: \tdef foo: MutArray[number..int]\n//│ ║         \t                  ^^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.243: \tdef foo: MutArray[number..int]\n//│ ║         \t                  ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.243: \tdef foo: MutArray[number..int]\n//│ ╙──       \t                          ^^^\n//│ foo: in MutArray[in int out number] out MutArray[in number out int]\n//│    = <missing implementation>\n\nfoo = (mut 0,)\n//│ (mut 'a,)\n//│   where\n//│     'a :> 0\n//│   <:  foo:\n//│ MutArray[in int out number]\n//│    = [ 0 ]\n\nfoo[0]\n//│ res: int | undefined\n//│    = 0\n\nres : int | undefined\n//│ res: int | undefined\n//│    = 0\n\nfoo[0] <- 1\n//│ = undefined\n\nfoo[0] <- (1/2)\n//│ = undefined\n\n\n\n:ng\nbar = if true then error : MutArray[int] else error : MutArray[number]\n//│ bar: MutArray[in int out number]\n\nfun x -> (x : MutArray[int], x : MutArray[number])\n//│ res: MutArray[in number out int] -> (MutArray[int], MutArray[number],)\n//│    = [Function: res]\n\nfun x -> if true then x : MutArray[int] else x : MutArray[number]\n//│ res: MutArray[in number out int] -> MutArray[in int out number]\n//│    = [Function: res]\n\n\n\n// * FIXME\ndef maf: MutArray[int..number] -> MutArray[int..number]\n//│ maf: in MutArray[in int out number] -> MutArray[in number out int] out MutArray[in number out int] -> MutArray[in int out number]\n//│    = <missing implementation>\n:ns\nmaf\n//│ res: MutArray[in int out number] -> MutArray[in int out number]\n//│    = <no result>\n//│      maf is not implemented\n\n// :ds\nmaf\n//│ res: MutArray[in number out int] -> MutArray[in int out number]\n//│    = <no result>\n//│      maf is not implemented\n\n\n:e\nmaf ((mut error,))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.312: \tmaf ((mut error,))\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.295: \tdef maf: MutArray[int..number] -> MutArray[int..number]\n//│ ║         \t                       ^^^^^^\n//│ ╟── but it flows into mutable tuple field with expected type `int`\n//│ ║  l.312: \tmaf ((mut error,))\n//│ ║         \t          ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.295: \tdef maf: MutArray[int..number] -> MutArray[int..number]\n//│ ║         \t                  ^^^\n//│ ╟── from type bounds:\n//│ ║  l.295: \tdef maf: MutArray[int..number] -> MutArray[int..number]\n//│ ╙──       \t                  ^^^^^^^^^^^\n//│ res: error | MutArray[in int out number]\n//│    = <no result>\n//│      maf is not implemented\n\n:e\nfun x -> maf ((mut x,))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.333: \tfun x -> maf ((mut x,))\n//│ ║         \t         ^^^^^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.295: \tdef maf: MutArray[int..number] -> MutArray[int..number]\n//│ ║         \t                       ^^^^^^\n//│ ╟── but it flows into mutable tuple field with expected type `int`\n//│ ║  l.333: \tfun x -> maf ((mut x,))\n//│ ║         \t                   ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.295: \tdef maf: MutArray[int..number] -> MutArray[int..number]\n//│ ║         \t                  ^^^\n//│ ╟── from type bounds:\n//│ ║  l.295: \tdef maf: MutArray[int..number] -> MutArray[int..number]\n//│ ╙──       \t                  ^^^^^^^^^^^\n//│ res: int -> (error | MutArray[in int out number])\n//│    = <no result>\n//│      maf is not implemented\n\nmaf error\n//│ res: MutArray[in int out number]\n//│    = <no result>\n//│      maf is not implemented\n\n\n:e\ndef maf: MutArray[number..int] -> MutArray[int..number]\n//│ ╔══[ERROR] Type mismatch in type bounds:\n//│ ║  l.360: \tdef maf: MutArray[number..int] -> MutArray[int..number]\n//│ ║         \t                  ^^^^^^^^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.360: \tdef maf: MutArray[number..int] -> MutArray[int..number]\n//│ ║         \t                  ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.360: \tdef maf: MutArray[number..int] -> MutArray[int..number]\n//│ ╙──       \t                          ^^^\n//│ maf: in MutArray[in number out int] -> MutArray[in number out int] out MutArray[in int out number] -> MutArray[in int out number]\n//│    = <missing implementation>\n\nmaf ((mut error,))\nfun x -> maf ((mut x,))\n//│ res: MutArray[in int out number]\n//│    = <no result>\n//│      maf is not implemented\n//│ res: number -> MutArray[in int out number]\n//│    = <no result>\n//│      maf is not implemented\n\n\n\n\ntype R[A] = { get: A; set: A -> () }\n//│ Defined type alias R[=A]\n\ndef foo: R[int..number]\nfoo = { get = 0; set = fun n -> () }\n//│ foo: R[in int out number]\n//│    = <missing implementation>\n//│ {get: 0, set: anything -> ()}\n//│   <:  foo:\n//│ R[in int out number]\n//│    = { get: 0, set: [Function: set] }\n\nfoo.get\n//│ res: number\n//│    = 0\n\n:e\nfoo: R['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.402: \tfoo: R['a]\n//│ ║         \t^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t           ^^^\n//│ ╟── from type bounds:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ╙──       \t           ^^^^^^^^^^^\n//│ res: R['a]\n//│   where\n//│     'a :> number\n//│        <: int\n//│    = { get: 0, set: [Function: set] }\n\n:e\nfoo: R['a..'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.422: \tfoo: R['a..'b]\n//│ ║         \t^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t           ^^^\n//│ ╟── from type bounds:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ╙──       \t           ^^^^^^^^^^^\n//│ res: R[in int & 'b out number | 'b]\n//│    = { get: 0, set: [Function: set] }\n\n// * FIXME\nres.get\n//│ res: number\n//│    = 0\n\ntype S[A] = { get: A; set: A -> () }\n//│ Defined type alias S[=A]\n\n:e\nfoo: S['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.447: \tfoo: S['a]\n//│ ║         \t^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t           ^^^\n//│ ╟── from type bounds:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ╙──       \t           ^^^^^^^^^^^\n//│ res: S['a]\n//│   where\n//│     'a :> number\n//│        <: int\n//│    = { get: 0, set: [Function: set] }\n\n:e\nfoo: S['a..'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.467: \tfoo: S['a..'b]\n//│ ║         \t^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t           ^^^\n//│ ╟── from type bounds:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ╙──       \t           ^^^^^^^^^^^\n//│ res: S[in int & 'b out number | 'b]\n//│    = { get: 0, set: [Function: set] }\n\nfoo: { get: number; set: int -> () }\n//│ res: {get: number, set: int -> ()}\n//│    = { get: 0, set: [Function: set] }\n\n:e\nfoo: { get: int }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.488: \tfoo: { get: int }\n//│ ║         \t^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.488: \tfoo: { get: int }\n//│ ╙──       \t            ^^^\n//│ res: {get: int}\n//│    = { get: 0, set: [Function: set] }\n\n:e\nfoo: { set: number -> () }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.502: \tfoo: { set: number -> () }\n//│ ║         \t^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.502: \tfoo: { set: number -> () }\n//│ ║         \t            ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t           ^^^\n//│ ╟── from type bounds:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ╙──       \t           ^^^^^^^^^^^\n//│ res: {set: number -> ()}\n//│    = { get: 0, set: [Function: set] }\n\nfoo2 = foo: { get: 'a; set: 'b -> () }\n//│ foo2: {get: number, set: int -> ()}\n//│     = { get: 0, set: [Function: set] }\n\n:e\nfoo2: S['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.523: \tfoo2: S['a]\n//│ ║         \t^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t           ^^^\n//│ ╟── from type variable:\n//│ ║  l.518: \tfoo2 = foo: { get: 'a; set: 'b -> () }\n//│ ╙──       \t                            ^^\n//│ res: S['a]\n//│   where\n//│     'a :> number\n//│        <: int\n//│    = { get: 0, set: [Function: set] }\n\n:e\nfoo2: S['a..'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.543: \tfoo2: S['a..'b]\n//│ ║         \t^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.388: \tdef foo: R[int..number]\n//│ ║         \t           ^^^\n//│ ╟── from type variable:\n//│ ║  l.518: \tfoo2 = foo: { get: 'a; set: 'b -> () }\n//│ ╙──       \t                            ^^\n//│ res: S[in int & 'b out number | 'b]\n//│    = { get: 0, set: [Function: set] }\n\n\n{ a = 0 } : { a: 'a..'b }\n//│ res: {a: 0}\n//│    = { a: 0 }\n\n\ndef maf: { get: int..number; set: (int..number) -> () } -> { get: int..number; set: (int..number) -> () }\n//│ maf: in {get: number, set: int -> ()} -> {get: int, set: number -> ()} out {get: int, set: number -> ()} -> {get: number, set: int -> ()}\n//│    = <missing implementation>\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TypeRefs.mls",
    "content": ":NoJS\n\nclass Foo[A]\n  method Inv: A -> A\n//│ Defined class Foo[=A]\n//│ Declared Foo.Inv: Foo['A] -> 'A -> 'A\n\ntrait Bar[A]\n  method Inv: A -> A\n//│ Defined trait Bar[=A]\n//│ Declared Bar.Inv: Bar['A] -> 'A -> 'A\n\ntype Baz[A] = Bar[A -> A]\n//│ Defined type alias Baz[=A]\n\ndef foo: Foo[int] & Bar[int] & Baz[string]\n//│ foo: Foo[int] & Bar[int] & Baz[string]\n\nfoo: Foo['res]\n//│ res: Foo[int]\n\nfoo: Baz['res]\n//│ res: Baz[string]\n\n// * Note that we don't get a `'res :> string -> string & int` upper bound because it's simplified to bottom:\nfoo: Bar['res]\n//│ res: Bar['res]\n//│   where\n//│     'res <: int | string -> string\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/TypeTags.mls",
    "content": "\n\nclass Foo[A]: { x: A; y: A }\n//│ Defined class Foo[+A]\n\ndef foo: #Foo\n//│ foo: Foo[?]\n//│    = <missing implementation>\n\nfoo12 = Foo { x = 1; y = 2 }\n//│ foo12: Foo[1 | 2] & {x: 1, y: 2}\n//│      = Foo { x: 1, y: 2 }\n\nfoo = foo12\n//│ Foo[1 | 2] & {x: 1, y: 2}\n//│   <:  foo:\n//│ Foo[?]\n//│    = Foo { x: 1, y: 2 }\n\ndef test1 f = case f of { Foo -> f }\n//│ test1: (Foo[?] & 'a) -> 'a\n//│      = [Function: test1]\n\ntest1 foo\n//│ res: Foo[?]\n//│    = Foo { x: 1, y: 2 }\n\ndef test2 f = case f of { Foo -> f.x }\n//│ test2: (Foo[?] & {x: 'x}) -> 'x\n//│      = [Function: test2]\n\ntest2 foo12\n//│ res: 1\n//│    = 1\n\n\n// * Only has the tag in its type, not the field\n:e\ntest2 foo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.39: \ttest2 foo\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `Foo[?]` does not have field 'x'\n//│ ║  l.39: \ttest2 foo\n//│ ║        \t      ^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.28: \tdef test2 f = case f of { Foo -> f.x }\n//│ ║        \t                                 ^^^\n//│ ╟── from reference:\n//│ ║  l.28: \tdef test2 f = case f of { Foo -> f.x }\n//│ ╙──      \t                   ^\n//│ res: error\n//│    = 1\n\n// * Mistakenly passing the constructor\n:e\nfoo = Foo\n//│ {x: 'x & 'A, y: 'A & 'y} -> (Foo['A] with {x: 'x, y: 'y})\n//│   <:  foo:\n//│ Foo[?]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.57: \tfoo = Foo\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `{x: ?x, y: ?y} -> (Foo[?A] & {Foo#A = ?A, x: ?x, y: ?y})` is not an instance of type `Foo`\n//│ ║  l.57: \tfoo = Foo\n//│ ║        \t      ^^^\n//│ ╟── Note: class constructor Foo is defined at:\n//│ ║  l.3: \tclass Foo[A]: { x: A; y: A }\n//│ ╙──     \t      ^^^\n//│    = [Function: foo1]\n\n\n\n:e\n1 : #Eql\n//│ ╔══[ERROR] type identifier not found: eql\n//│ ╙──\n//│ res: error\n//│    = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Undef.mls",
    "content": "\nclass Undef\n//│ Defined class Undef\n\nundef = Undef{}\n//│ undef: Undef\n//│      = Undef {}\n\n\ndef example: int | Undef\n//│ example: Undef | int\n//│        = <missing implementation>\n\nexample = if true then undef else 42\n//│ 42 | Undef\n//│   <:  example:\n//│ Undef | int\n//│        = Undef {}\n\ndef qmrk_qmrk lhs rhs = case lhs of { Undef -> rhs | _ -> lhs }\n//│ qmrk_qmrk: (Undef | 'a & ~#Undef) -> 'a -> 'a\n//│          = [Function: qmrk_qmrk]\n\nqmrk_qmrk example 0\n//│ res: int\n//│    = 0\n\nqmrk_qmrk example \"123\"\n//│ res: \"123\" | int\n//│    = '123'\n\nqmrk_qmrk undef \"123\"\n//│ res: \"123\"\n//│    = '123'\n\nqmrk_qmrk 42 \"123\"\n//│ res: \"123\" | 42\n//│    = 42\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Undefined.mls",
    "content": "class Undefined2: { x: undefined }\n//│ Defined class Undefined2\n\nUndefined2\n//│ res: {x: undefined & 'x} -> (Undefined2 with {x: 'x})\n//│    = [Function: res]\n\nUndefined2 { x = undefined }\n//│ res: Undefined2\n//│    = Undefined2 { x: undefined }\n\n:e\nUndefined2 { x = \"I am here to make a type mismatch.\" }\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.13: \tUndefined2 { x = \"I am here to make a type mismatch.\" }\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"I am here to make a type mismatch.\"` does not match type `undefined`\n//│ ║  l.13: \tUndefined2 { x = \"I am here to make a type mismatch.\" }\n//│ ║        \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.1: \tclass Undefined2: { x: undefined }\n//│ ╙──     \t                       ^^^^^^^^^\n//│ res: (Undefined2 with {x: \"I am here to make a type mismatch.\"}) | error\n//│    = Undefined2 { x: 'I am here to make a type mismatch.' }\n\n:e\ntype Undefined2 = { x: string }\n//│ ╔══[ERROR] Type 'Undefined2' is already defined.\n//│ ║  l.27: \ttype Undefined2 = { x: string }\n//│ ╙──      \t     ^^^^^^^^^^\n\ntype AnotherUndefined = { x: undefined }\n//│ Defined type alias AnotherUndefined\n\ntype MoreOnTypes0 = undefined\n//│ Defined type alias MoreOnTypes0\n\ntype MoreOnTypes1 = undefined -> undefined\n//│ Defined type alias MoreOnTypes1\n\ntype MoreOnTypes2 = undefined -> undefined -> undefined\n//│ Defined type alias MoreOnTypes2\n\ntype MoreOnTypes3 = (undefined -> undefined) -> null\n//│ Defined type alias MoreOnTypes3\n\nsample = undefined\nsample: undefined\n//│ sample: undefined\n//│       = undefined\n//│ res: undefined\n//│    = undefined\n\nsample2 = null\nsample2: null\n//│ sample2: null\n//│        = null\n//│ res: null\n//│    = null\n\n:e\nsample: bool\nsample2: bool\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.62: \tsample: bool\n//│ ║        \t^^^^^^\n//│ ╟── undefined literal of type `undefined` is not an instance of type `bool`\n//│ ║  l.47: \tsample = undefined\n//│ ║        \t         ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `bool`\n//│ ║  l.62: \tsample: bool\n//│ ║        \t^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.62: \tsample: bool\n//│ ╙──      \t        ^^^^\n//│ res: bool\n//│    = undefined\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.63: \tsample2: bool\n//│ ║        \t^^^^^^^\n//│ ╟── null literal of type `null` is not an instance of type `bool`\n//│ ║  l.54: \tsample2 = null\n//│ ║        \t          ^^^^\n//│ ╟── but it flows into reference with expected type `bool`\n//│ ║  l.63: \tsample2: bool\n//│ ║        \t^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.63: \tsample2: bool\n//│ ╙──      \t         ^^^^\n//│ res: bool\n//│    = null\n\nif false then sample else 0\nif true then sample2 else 0\n//│ res: 0 | undefined\n//│    = 0\n//│ res: 0 | null\n//│    = null\n\n\ndef bar = fun sample -> (sample: MoreOnTypes0)\nbar undefined\n//│ bar: MoreOnTypes0 -> MoreOnTypes0\n//│    = [Function: bar]\n//│ res: MoreOnTypes0\n//│    = undefined\n\n:e\nbar \"undefined\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.109: \tbar \"undefined\"\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"undefined\"` does not match type `undefined`\n//│ ║  l.109: \tbar \"undefined\"\n//│ ║         \t    ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.35: \ttype MoreOnTypes0 = undefined\n//│ ║        \t                    ^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.101: \tdef bar = fun sample -> (sample: MoreOnTypes0)\n//│ ╙──       \t                         ^^^^^^\n//│ res: error | MoreOnTypes0\n//│    = 'undefined'\n\ncase (undefined) of { undefined -> \"undefined it is\" | null -> \"null it is\"}\n//│ res: \"null it is\" | \"undefined it is\"\n//│    = 'undefined it is'\n\ncase (null) of { undefined -> \"undefined it is\" | null -> \"null it is\" }\n//│ res: \"null it is\" | \"undefined it is\"\n//│    = 'null it is'\n\n\nabsent = ()[0]\n//│ absent: undefined\n//│       = undefined\n\ncase absent of { undefined -> 1 }\n//│ res: 1\n//│    = 1\n\ncase absent of { null -> 0 | undefined -> 1 }\n//│ res: 0 | 1\n//│    = 1\n\ncase absent of { \"\" -> 0 | undefined -> 1 }\n//│ res: 0 | 1\n//│    = 1\n\n\nuw = undefined with { x = 1 }\nnw = null with { x = 1 }\nuw.x\nnw.x\n//│ uw: undefined & {x: 1}\n//│   = { x: 1 }\n//│ nw: null & {x: 1}\n//│   = { x: 1 }\n//│ res: 1\n//│    = 1\n//│ res: 1\n//│    = 1\n\n:e\nundefined.x\nnull.x\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.165: \tundefined.x\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── undefined literal of type `undefined` does not have field 'x'\n//│ ║  l.165: \tundefined.x\n//│ ╙──       \t^^^^^^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading 'x')\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.166: \tnull.x\n//│ ║         \t^^^^^^\n//│ ╟── null literal of type `null` does not have field 'x'\n//│ ║  l.166: \tnull.x\n//│ ╙──       \t^^^^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: Cannot read properties of null (reading 'x')\n\ndef bypass: nothing\n//│ bypass: nothing\n//│       = <missing implementation>\n\n\n:e\nbypass = undefined\n//│ undefined\n//│   <:  bypass:\n//│ nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.192: \tbypass = undefined\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── undefined literal of type `undefined` does not match type `nothing`\n//│ ║  l.192: \tbypass = undefined\n//│ ║         \t         ^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.186: \tdef bypass: nothing\n//│ ╙──       \t            ^^^^^^^\n//│       = undefined\n\n:re\nbypass.x\nbypass + 1\n//│ res: nothing\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading 'x')\n//│ res: int\n//│    = NaN\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Under.mls",
    "content": "\n_ = 1\n//│ _: 1\n//│  = 1\n\n:e\n_\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.7: \t_\n//│ ╙──     \t^\n//│ res: error\n//│    = 1\n\ndef foo _ = 1\n//│ foo: anything -> 1\n//│    = [Function: foo]\n\n:e\ndef foo _ = _\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.19: \tdef foo _ = _\n//│ ╙──      \t            ^\n//│ foo: anything -> error\n//│    = [Function: foo1]\n\n// :js\ndef foo(_, _) = 1\n//│ foo: (anything, anything,) -> 1\n//│    = [Function: foo2]\n\ndef foo { _ } = 1\n//│ foo: {_: anything} -> 1\n//│    = [Function: foo3]\n\n:e\ndef foo { _ } = { _ }\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.36: \tdef foo { _ } = { _ }\n//│ ╙──      \t                  ^\n//│ foo: {_: anything} -> {_: error}\n//│    = [Function: foo4]\n\n{ _ = 1 }._\n//│ res: 1\n//│    = 1\n\n:e\ndef foo { _ ; _ } = 1\n//│ ╔══[ERROR] Multiple declarations of field name _ in record literal\n//│ ║  l.48: \tdef foo { _ ; _ } = 1\n//│ ║        \t        ^^^^^^^^^\n//│ ╟── Declared at\n//│ ║  l.48: \tdef foo { _ ; _ } = 1\n//│ ║        \t          ^\n//│ ╟── Declared at\n//│ ║  l.48: \tdef foo { _ ; _ } = 1\n//│ ╙──      \t              ^\n//│ foo: {_: anything, _: anything} -> 1\n//│    = [Function: foo5]\n\n// :js\ndef foo { _ = _ ; __ = _ } = 1\n//│ foo: {_: anything, __: anything} -> 1\n//│    = [Function: foo6]\n\n_ = 1\n//│ _: 1\n//│  = 1\n\ndef _ = 1\n//│ _: 1\n//│  = [Function: _2]\n\nrec def _ = 1\n//│ _: 1\n//│  = [Function: _3]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/VarCycles.mls",
    "content": "\n:RecursiveTypes\n\n\ndef foo: ('a,) as 'a\n//│ foo: 'a\n//│   where\n//│     'a :> ('a,)\n//│    = <missing implementation>\n\ndef bar: (('b,) as 'b) -> ()\n//│ bar: 'b -> ()\n//│   where\n//│     'b <: ('b,)\n//│    = <missing implementation>\n\n\nbar foo\n//│ res: ()\n//│    = <no result>\n//│      bar is not implemented\n\n\n:ns\nid1 = id\n//│ id1: forall 'a. 'a -> 'a\n//│    = [Function: id]\n\n:ns\n// def f x = id x\ndef f = id : 'c -> 'c\n//│ f: forall 'c 'a. 'c -> 'c\n//│   where\n//│     'c <: 'a\n//│     'a <: 'c\n//│  = [Function: f]\n\nf 1 + 2\n//│ res: int\n//│    = 3\n\n\n\n:NoRecursiveTypes\n\n\n:e\nbar foo\n//│ ╔══[ERROR] Inferred recursive type: 'b\n//│   where\n//│     'b :> ('b,)\n//│ ║  l.11: \tdef bar: (('b,) as 'b) -> ()\n//│ ╙──      \t         ^^^^^^^^^^^^^\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.48: \tbar foo\n//│ ║        \t^^^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: error | ()\n//│    = <no result>\n//│      bar is not implemented\n\n\nf 1 + 2\n//│ res: int\n//│    = 3\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Variant-sub-ad-hoc.mls",
    "content": "class None\nclass Some\n//│ Defined class None\n//│ Defined class Some\n\ndef Some v = Some{} with {v}\ndef None = None{}\n//│ Some: 'a -> (Some & {v: 'a})\n//│     = [Function: Some1]\n//│ None: None\n//│     = [Function: None1]\n\ndef flatMap = fun f -> fun opt ->\n  case opt of { Some -> f opt.v | _ -> opt }\n//│ flatMap: ('v -> 'a) -> (Some & {v: 'v} | 'a & ~#Some) -> 'a\n//│        = [Function: flatMap]\n\nf = fun x -> Some x\nres = flatMap f (Some 1)\nres = flatMap f None\n//│ f: 'a -> (Some & {v: 'a})\n//│  = [Function: f]\n//│ res: Some & {v: 1}\n//│    = Some { v: 1 }\n//│ res: None | Some & {v: nothing}\n//│    = None {}\n\nclass Lit\nclass Neg\nclass Var\nclass Plus\n//│ Defined class Lit\n//│ Defined class Neg\n//│ Defined class Var\n//│ Defined class Plus\n\n:stats\nrec def evalOpt = fun x -> case x of {\n  | Lit ->\n      Some x.v\n  | Neg ->\n      flatMap (fun s -> Some (0 - s)) (evalOpt x.sub)\n  | Var ->\n      None with {err = concat \"free var: \" x.nme}\n  | Plus ->\n      flatMap (fun l -> flatMap (fun r ->\n        Some (l + r)\n      ) (evalOpt x.rhs)) (evalOpt x.lhs)\n  }\n//│ evalOpt: 'a -> (None & {err: string} | Some & {v: int})\n//│   where\n//│     'a <: Lit & {v: int} | Neg & {sub: 'a} | Plus & {lhs: 'a, rhs: 'a} | Var & {nme: string}\n//│        = [Function: evalOpt]\n//│ constrain calls  : 533\n//│ annoying  calls  : 156\n//│ subtyping calls  : 3001\n\n:stats\nevalOpt (Plus{} with {lhs = Lit{} with {v=2}; rhs = Lit{} with {v=2}})\n//│ res: None & {err: string} | Some & {v: int}\n//│    = Some { v: 4 }\n//│ constrain calls  : 88\n//│ annoying  calls  : 34\n//│ subtyping calls  : 653\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Variant-sub.mls",
    "content": "class None: {}\nclass Some[A]: { v: A }\n//│ Defined class None\n//│ Defined class Some[+A]\n\ndef Some v = Some{v}\ndef None = None{}\n//│ Some: 'v -> Some['v]\n//│     = [Function: Some1]\n//│ None: None\n//│     = [Function: None1]\n\ndef flatMap = fun f -> fun opt ->\n  case opt of { Some -> f opt.v | None -> opt }\n//│ flatMap: ('v -> 'a) -> (None & 'a | Some[?] & {v: 'v}) -> 'a\n//│        = [Function: flatMap]\n\nf x = Some x\nflatMap f (Some 1)\nflatMap f None\n//│ f: 'v -> Some['v]\n//│  = [Function: f]\n//│ res: Some[1]\n//│    = Some { v: 1 }\n//│ res: None | Some[nothing]\n//│    = None {}\n\n:e\nflatMap f \"oops\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.29: \tflatMap f \"oops\"\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` does not match type `None & ?a | Some[?] & ?b`\n//│ ║  l.29: \tflatMap f \"oops\"\n//│ ║        \t          ^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.14: \t  case opt of { Some -> f opt.v | None -> opt }\n//│ ╙──      \t       ^^^\n//│ res: Some[nothing] | error\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\nclass NoneBecause: None & { reason: string }\nflatMap f (NoneBecause { reason = \"uh uh\" })\n//│ Defined class NoneBecause\n//│ res: NoneBecause & {reason: \"uh uh\"} | Some[nothing]\n//│    = NoneBecause { reason: 'uh uh' }\n\ntype Expr = Lit | Neg | Var | Plus\nclass Lit: {v: int}\nclass Neg: {sub: Expr}\nclass Var: {nme: string}\nclass Plus: {lhs: Expr; rhs: Expr}\n//│ Defined type alias Expr\n//│ Defined class Lit\n//│ Defined class Neg\n//│ Defined class Var\n//│ Defined class Plus\n\n:stats\nrec def evalOpt x = case x of {\n  | Lit ->\n      Some x.v\n  | Neg ->\n      // flatMap (fun s -> Some (neg x.sub)) (evalOpt x.sub)\n      flatMap (fun s -> Some (negate s)) (evalOpt x.sub)\n  | Var ->\n      // None with {err = concat \"free var: \" x.nme}\n      NoneBecause {reason = concat \"free var: \" x.nme}\n      // None\n  | Plus ->\n      flatMap (fun l -> flatMap (fun r ->\n        // Some (add x.lhs x.rhs)\n        Some (l + r)\n      ) (evalOpt x.rhs)) (evalOpt x.lhs)\n  }\n//│ evalOpt: 'a -> (NoneBecause | Some[int])\n//│   where\n//│     'a <: Lit & {v: int} | (Neg with {sub: 'a}) | (Plus with {lhs: 'a, rhs: 'a}) | Var\n//│        = [Function: evalOpt]\n//│ constrain calls  : 537\n//│ annoying  calls  : 105\n//│ subtyping calls  : 3721\n\n:stats\nevalOpt (Plus{lhs = Lit{v=2}; rhs = Lit{v=3}})\n//│ res: NoneBecause | Some[int]\n//│    = Some { v: 5 }\n//│ constrain calls  : 127\n//│ annoying  calls  : 37\n//│ subtyping calls  : 959\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Weird.mls",
    "content": "// * Weird features to eventually remove\n\n:AllowRuntimeErrors\n\n\n:ge\nanything\n//│ res: anything\n//│ Code generation encountered an error:\n//│   type alias anything is not a valid expression\n\n:ge\nnothing\n//│ res: nothing\n//│ Code generation encountered an error:\n//│   type alias nothing is not a valid expression\n\n:ge\nNothing\n//│ res: nothing\n//│ Code generation encountered an error:\n//│   unresolved symbol Nothing\n\n:ge\nint\n//│ res: int\n//│ Code generation encountered an error:\n//│   type alias int is not a valid expression\n\n:ge\nint + 1\n//│ res: int\n//│ Code generation encountered an error:\n//│   type alias int is not a valid expression\n\n\nclass C\n//│ Defined class C\n\n:p\ndef n: C{}\n//│ Parsed: rec def n: C; {};\n//│ Desugared: rec def n: C\n//│ AST: Def(true,Var(n),Right(PolyType(List(),TypeName(C))),true)\n//│ Desugared: {}\n//│ AST: Rcd(List())\n//│ n: C\n//│  = <missing implementation>\n//│ res: anything\n//│    = {}\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Wildcards.mls",
    "content": "\n\n:e\n42: ?\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.4: \t42: ?\n//│ ║       \t^^\n//│ ╟── integer literal of type `42` does not match type `nothing`\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.4: \t42: ?\n//│ ╙──     \t    ^\n//│ res: anything\n//│    = 42\n\n:e // FIXME new rigidification semantics\ndef n: ?\nn = 42\n//│ n: ?\n//│  = <missing implementation>\n//│ 42\n//│   <:  n:\n//│ nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.17: \tn = 42\n//│ ║        \t^^^^^^\n//│ ╟── integer literal of type `42` does not match type `nothing`\n//│ ║  l.17: \tn = 42\n//│ ║        \t    ^^\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.16: \tdef n: ?\n//│ ╙──      \t       ^\n//│  = 42\n\n\ndef f x = x : ?\n//│ f: nothing -> anything\n//│  = [Function: f]\n\nclass E[A]\n  method In: A -> A\n  method In = id\n//│ Defined class E[=A]\n//│ Declared E.In: E['A] -> 'A -> 'A\n//│ Defined E.In: E['A] -> 'a -> 'a\n\n:e\nE{} : E[?]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.47: \tE{} : E[?]\n//│ ║        \t^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.47: \tE{} : E[?]\n//│ ╙──      \t        ^\n//│ res: E[?]\n//│    = E {}\n\n:e // FIXME new rigidification semantics\ndef e: E[?]\ndef e = E{}\n//│ e: E[?]\n//│  = <missing implementation>\n//│ E['A]\n//│   <:  e:\n//│ E[?]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.59: \tdef e = E{}\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.58: \tdef e: E[?]\n//│ ╙──      \t         ^\n//│  = [Function: e]\n\n\ntype Als1[A] = int -> A\n//│ Defined type alias Als1[+A]\n\n:e\nadd 1 : Als1[?]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.78: \tadd 1 : Als1[?]\n//│ ║        \t^^^^^\n//│ ╟── type `int` does not match type `nothing`\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.78: \tadd 1 : Als1[?]\n//│ ╙──      \t             ^\n//│ res: Als1[?]\n//│    = [Function (anonymous)]\n\n:e // FIXME new rigidification semantics\ndef a1: Als1[?]\na1 = add 1\n//│ a1: in Als1[nothing] out Als1[?]\n//│   = <missing implementation>\n//│ int -> int\n//│   <:  a1:\n//│ Als1[nothing]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.91: \ta1 = add 1\n//│ ║        \t^^^^^^^^^^\n//│ ╟── type `int` does not match type `nothing`\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.90: \tdef a1: Als1[?]\n//│ ╙──      \t             ^\n//│   = [Function (anonymous)]\n\n\ntype Als2[A] = A -> int\n//│ Defined type alias Als2[-A]\n\n:e\nadd 1 : Als2[?]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.111: \tadd 1 : Als2[?]\n//│ ║         \t^^^^^\n//│ ╟── type `anything` is not an instance of type `int`\n//│ ║  l.111: \tadd 1 : Als2[?]\n//│ ╙──       \t             ^\n//│ res: Als2[?]\n//│    = [Function (anonymous)]\n\n:e // FIXME new rigidification semantics\ndef a2: Als2[?]\na2 = add 1\n//│ a2: in Als2[anything] out Als2[?]\n//│   = <missing implementation>\n//│ int -> int\n//│   <:  a2:\n//│ Als2[anything]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.123: \ta2 = add 1\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `anything` is not an instance of type `int`\n//│ ║  l.122: \tdef a2: Als2[?]\n//│ ╙──       \t             ^\n//│   = [Function (anonymous)]\n\n\ndef q: ?\n//│ q: ?\n//│  = <missing implementation>\n\n:e // FIXME new rigidification semantics\nq = 1\n//│ 1\n//│   <:  q:\n//│ nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.143: \tq = 1\n//│ ║         \t^^^^^\n//│ ╟── integer literal of type `1` does not match type `nothing`\n//│ ║  l.143: \tq = 1\n//│ ║         \t    ^\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.138: \tdef q: ?\n//│ ╙──       \t       ^\n//│  = 1\n\n:e\nq + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.159: \tq + 1\n//│ ║         \t^^^\n//│ ╟── type `anything` is not an instance of type `int`\n//│ ║  l.138: \tdef q: ?\n//│ ║         \t       ^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.159: \tq + 1\n//│ ╙──       \t^\n//│ res: error | int\n//│    = 2\n\n:e\nq q\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.173: \tq q\n//│ ║         \t^^^\n//│ ╟── type `anything` is not a function\n//│ ║  l.138: \tdef q: ?\n//│ ║         \t       ^\n//│ ╟── but it flows into reference with expected type `anything -> ?a`\n//│ ║  l.173: \tq q\n//│ ╙──       \t^\n//│ res: error\n//│ Runtime error:\n//│   TypeError: q is not a function\n\n\n:NoJS\n\nclass Expr[A]\n  method Inv: A -> A\n//│ Defined class Expr[=A]\n//│ Declared Expr.Inv: Expr['A] -> 'A -> 'A\n\ndef e: Expr[?]\ndef f: Expr[?] -> Expr[?]\n//│ e: Expr[?]\n//│ f: Expr[?] -> Expr[?]\n\n// * `Expr[?] <: Expr[?]` is false\n// * because each `?` stands for an unknown type ranging from Bot to Top\n:e\nf e\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.203: \tf e\n//│ ║         \t^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.195: \tdef e: Expr[?]\n//│ ║         \t            ^\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.196: \tdef f: Expr[?] -> Expr[?]\n//│ ╙──       \t            ^\n//│ res: Expr[?] | error\n\n\n\n\nclass Foo[A]\n  method Get = error : A\n  method Foo1: Foo[A] -> Foo[A]\n  method Foo1 = id\n  method Id = id : A -> A\n//│ Defined class Foo[=A]\n//│ Declared Foo.Foo1: Foo['A] -> Foo['A] -> Foo['A]\n//│ Defined Foo.Get: Foo['A] -> 'A\n//│ Defined Foo.Foo1: Foo['A] -> 'a -> 'a\n//│ Defined Foo.Id: Foo['A] -> 'A -> 'A\n\ndef foo: Foo[?]\n//│ foo: Foo[?]\n\n:e // * Works with existential wildcards\nfoo = Foo{}\n//│ Foo['A]\n//│   <:  foo:\n//│ Foo[?]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.233: \tfoo = Foo{}\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ╙──       \t             ^\n\nfoo\n//│ res: Foo[?]\n\n:e\nfoo : Foo['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.248: \tfoo : Foo['a]\n//│ ║         \t^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ╙──       \t             ^\n//│ res: Foo['a]\n//│   where\n//│     'a :> anything\n//│        <: nothing\n\n:e\nfoo.Foo1\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.261: \tfoo.Foo1\n//│ ║         \t^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ╙──       \t             ^\n//│ res: error | Foo['A] -> Foo['A]\n//│   where\n//│     'A :> anything\n//│        <: nothing\n\nfoo1 = Foo.Foo1\n//│ foo1: Foo['A] -> Foo['A] -> Foo['A]\n\n:e\nfoo1 foo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.277: \tfoo1 foo\n//│ ║         \t^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ╙──       \t             ^\n//│ res: error | Foo['A] -> Foo['A]\n//│   where\n//│     'A :> anything\n//│        <: nothing\n\n\n:e\nfoo2 = foo : Foo['a .. 'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.291: \tfoo2 = foo : Foo['a .. 'b]\n//│ ║         \t       ^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ╙──       \t             ^\n//│ foo2: Foo[anything]\n\n:e\nfoo2.Id\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.301: \tfoo2.Id\n//│ ║         \t^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ║         \t             ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.218: \tclass Foo[A]\n//│ ╙──       \t          ^\n//│ res: error | nothing -> anything\n\n:e\nfoo3 = foo2 : Foo['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.314: \tfoo3 = foo2 : Foo['a]\n//│ ║         \t       ^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ╙──       \t             ^\n//│ foo3: Foo['a]\n//│   where\n//│     'a :> anything\n//│        <: nothing\n\n:e\nfoo3.Id\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.327: \tfoo3.Id\n//│ ║         \t^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.229: \tdef foo: Foo[?]\n//│ ║         \t             ^\n//│ ╟── Note: class type parameter A is defined at:\n//│ ║  l.218: \tclass Foo[A]\n//│ ╙──       \t          ^\n//│ res: error | nothing -> anything\n\n\n:e\nfoo2 = foo : Foo[anything .. nothing]\n//│ ╔══[ERROR] Type mismatch in type bounds:\n//│ ║  l.341: \tfoo2 = foo : Foo[anything .. nothing]\n//│ ║         \t                 ^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.341: \tfoo2 = foo : Foo[anything .. nothing]\n//│ ║         \t                 ^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.341: \tfoo2 = foo : Foo[anything .. nothing]\n//│ ╙──       \t                             ^^^^^^^\n//│ foo2: Foo[in anything out nothing]\n\nfoo2.Id\n//│ res: 'A -> 'A\n\nfoo3 = foo2 : Foo['a]\n//│ foo3: Foo['a]\n\nfoo3.Id\n//│ res: 'A -> 'A\n\n\nfid = Foo.Id\n//│ fid: Foo['A] -> 'A -> 'A\n\nfid foo2\n//│ res: 'A -> 'A\n\nfid (f: Foo['a..'b]) = Foo.Id f\n//│ fid: Foo['a] -> 'a -> 'a\n\n\nclass Bar[A]: { value: A; id: A -> A }\n  method Bid: A -> A\n  method Bid = id\n//│ Defined class Bar[=A]\n//│ Declared Bar.Bid: Bar['A] -> 'A -> 'A\n//│ Defined Bar.Bid: Bar['A] -> 'a -> 'a\n\ndef bar: Bar[?]\n//│ bar: Bar[?]\n\n:e\nrec def bar = Bar{value = bar; id}\n//│ 'value\n//│   where\n//│     'value :> Bar['A] with {id: forall 'a. 'a -> 'a, value: 'value}\n//│     'A :> 'value\n//│   <:  bar:\n//│ Bar[?]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.384: \trec def bar = Bar{value = bar; id}\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Bar[?A] & {id: ?id, value: ?value}` does not match type `nothing`\n//│ ║  l.384: \trec def bar = Bar{value = bar; id}\n//│ ║         \t              ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `nothing`\n//│ ║  l.384: \trec def bar = Bar{value = bar; id}\n//│ ║         \t                          ^^^\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.380: \tdef bar: Bar[?]\n//│ ╙──       \t             ^\n\n:e\nbar.Bid\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.405: \tbar.Bid\n//│ ║         \t^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.380: \tdef bar: Bar[?]\n//│ ╙──       \t             ^\n//│ res: error | nothing -> anything\n\n:e\nbar: Bar['a..'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.415: \tbar: Bar['a..'b]\n//│ ║         \t^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.380: \tdef bar: Bar[?]\n//│ ╙──       \t             ^\n//│ res: Bar[anything]\n\nbar.value\n//│ res: anything\n\nbar.id\n//│ res: nothing -> anything\n\n\n\ntype Baz[A] = { id: A -> A; bid: Baz[A] -> Baz[A] }\n//│ Defined type alias Baz[=A]\n\ndef baz: Baz[?]\n//│ baz: Baz[?]\n\n:e\nbaz = { id; bid = id }\n//│ {bid: forall 'a. 'a -> 'a, id: forall 'a. 'a -> 'a}\n//│   <:  baz:\n//│ Baz[?]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.439: \tbaz = { id; bid = id }\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.435: \tdef baz: Baz[?]\n//│ ╙──       \t             ^\n\nbaz.id\n//│ res: nothing -> anything\n\nbaz.bid\n//│ res: Baz[?] -> Baz[?]\n\n:e\nbaz.bid baz\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.457: \tbaz.bid baz\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.435: \tdef baz: Baz[?]\n//│ ╙──       \t             ^\n//│ res: error | Baz[?]\n\n:e\nbaz.bid (baz: Baz['a..'b])\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.467: \tbaz.bid (baz: Baz['a..'b])\n//│ ║         \t         ^^^\n//│ ╟── type `anything` does not match type `nothing`\n//│ ║  l.435: \tdef baz: Baz[?]\n//│ ╙──       \t             ^\n//│ res: Baz[?]\n\n\n\ndef baz: Baz[Baz[?]]\n//│ baz: Baz[Baz[?]]\n\nbaz.id\n//│ res: Baz[?] -> Baz[?]\n\nbaz.bid\n//│ res: Baz[Baz[?]] -> Baz[Baz[?]]\n\n\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/With.mls",
    "content": "\nrcd = { x = 1 }\n//│ rcd: {x: 1}\n//│    = { x: 1 }\n\nrcd.x\n//│ res: 1\n//│    = 1\n\nrcd with { y = 2 }\n//│ res: {x: 1, y: 2}\n//│    = { x: 1, y: 2 }\n\nadd res.x res.y\n//│ res: int\n//│    = 3\n\nrcd with { x = \"oops\" }\n//│ res: {x: \"oops\"}\n//│    = { x: 'oops' }\n\nres.x\n//│ res: \"oops\"\n//│    = 'oops'\n\nid rcd with { x = \"oops\" }\n//│ res: {x: \"oops\"}\n//│    = { x: 'oops' }\n\nres.x\n//│ res: \"oops\"\n//│    = 'oops'\n\n\nrcd = { }\n//│ rcd: anything\n//│    = {}\n\nid rcd with { x = \"oops\" }\n//│ res: {x: \"oops\"}\n//│    = { x: 'oops' }\n\nres.x\n//│ res: \"oops\"\n//│    = 'oops'\n\n\ndef f r = r with { x = \"oops\" }\n//│ f: 'a -> ('a\\x & {x: \"oops\"})\n//│  = [Function: f]\n\nf rcd\n//│ res: {x: \"oops\"}\n//│    = { x: 'oops' }\n\nf (rcd with { y = 2 })\n//│ res: {x: \"oops\", y: 2}\n//│    = { y: 2, x: 'oops' }\n\n\ndef f a b = if true then a else b\n//│ f: 'a -> 'a -> 'a\n//│  = [Function: f1]\n\ndef f a b = (if true then a else b) with { x = \"oops\" }\n//│ f: 'a -> 'a -> ('a\\x & {x: \"oops\"})\n//│  = [Function: f2]\n\ndef f a b = let tmp = a.x in (if true then a else b) with { x = \"oops\" }\n//│ f: ({x: anything} & 'a) -> 'a -> ('a\\x & {x: \"oops\"})\n//│  = [Function: f3]\n\n\n({ name = \"Bob\" } with { age = 123 }).age\n//│ res: 123\n//│    = 123\n\n({ name = \"Bob\" } with { age = 123 }).name\n//│ res: \"Bob\"\n//│    = 'Bob'\n\n({ name = \"Bob\" } with { name = 123 }).name\n//│ res: 123\n//│    = 123\n\n\ndef getf { f } = f\n//│ getf: {f: 'a} -> 'a\n//│     = [Function: getf]\n\ndef foo x =\n  let xf = x with { f = 42 }\n  in getf xf\n//│ foo: ({f: 'a} | ~{f: 42})\\f -> 'a\n//│    = [Function: foo]\n\nfoo 123\n//│ res: 42\n//│    = 42\n\ndef fooManual: (~{f: 42} | {f: 'a})\\f -> 'a\n//│ fooManual: in forall 'a. anything -> 'a out forall 'a. ({f: 'a} | ~{f: 42})\\f -> 'a\n//│          = <missing implementation>\n\nfooManual x = error\n//│ anything -> nothing\n//│   <:  fooManual:\n//│ anything -> nothing\n//│          = [Function: fooManual]\n\n:e\nfooManual = id\n//│ 'a -> 'a\n//│   <:  fooManual:\n//│ anything -> nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.112: \tfooManual = id\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── type `anything` does not match type `'a`\n//│ ║  l.101: \tdef fooManual: (~{f: 42} | {f: 'a})\\f -> 'a\n//│ ║         \t               ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.101: \tdef fooManual: (~{f: 42} | {f: 'a})\\f -> 'a\n//│ ╙──       \t                                         ^^\n//│          = [Function: id]\n\nfooManual 123\n//│ res: 42\n//│    = 123\n\ndef foo x =\n  let xf = x with { f = 42 }\n  in add (getf xf) (getf x)\n//│ foo: (({f: int} | ~{f: 42})\\f & {f: int}) -> int\n//│    = [Function: foo1]\n\ndef foo x =\n  let xf = x with { f = 42 }\n  in { l = getf xf; r = getf x; s = x }\n//│ foo: (({f: 'a} | ~{f: 42})\\f & {f: 'b} & 'c) -> {l: 'a, r: 'b, s: 'c}\n//│    = [Function: foo2]\n\n:e\nfoo 42\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.144: \tfoo 42\n//│ ║         \t^^^^^^\n//│ ╟── integer literal of type `42` does not have field 'f'\n//│ ║  l.144: \tfoo 42\n//│ ║         \t    ^^\n//│ ╟── Note: constraint arises from record literal:\n//│ ║  l.87: \tdef getf { f } = f\n//│ ║        \t         ^^^^^\n//│ ╟── from reference:\n//│ ║  l.139: \t  in { l = getf xf; r = getf x; s = x }\n//│ ╙──       \t                             ^\n//│ res: error | {l: 42, r: nothing, s: 42}\n//│    = { l: 42, r: undefined, s: 42 }\n\nr = foo (42 with { f = 1 })\n//│ r: {l: 42, r: 1, s: 42 & {f: 1}}\n//│  = { l: 42, r: 1, s: [Number: 42] { f: 1 } }\n\nr.s.f\n//│ res: 1\n//│    = 1\n\nadd r.s 1\n//│ res: int\n//│    = 43\n\n\n{} with { x = 1 } with { y = 2 }\n//│ res: {x: 1, y: 2}\n//│    = { x: 1, y: 2 }\n\n:e\nres.z\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.178: \tres.z\n//│ ║         \t^^^^^\n//│ ╟── `with` extension of type `{x: 1, y: 2}` does not have field 'z'\n//│ ║  l.173: \t{} with { x = 1 } with { y = 2 }\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{z: ?z}`\n//│ ║  l.178: \tres.z\n//│ ╙──       \t^^^\n//│ res: error\n//│    = undefined\n\n\n\n// === With and classes === //\n\nclass C[A]: { x: A }\n//│ Defined class C[+A]\n\nc = C{x = 1}\n//│ c: C[1]\n//│  = C { x: 1 }\n\nc.x\n//│ res: 1\n//│    = 1\n\nd = c with { x = \"hi\"; y = 2 }\n//│ d: C[1] with {x: \"hi\", y: 2}\n//│  = C { x: 'hi', y: 2 }\n\nd.x\n//│ res: \"hi\"\n//│    = 'hi'\n\nd: C['a]\n//│ res: C[\"hi\" | 1]\n//│    = C { x: 'hi', y: 2 }\n\nres.x\n//│ res: \"hi\" | 1\n//│    = 'hi'\n\n\ndef f x = (x with { a = 1 }).b\n//│ f: ({b: 'b} | ~{a: 1})\\a -> 'b\n//│  = [Function: f4]\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Yicong.mls",
    "content": "\ntrait T1\ntrait T2\n//│ Defined trait T1\n//│ Defined trait T2\n\nr = if true then T1 1 else T2 2\n//│ r: 1 & #T1 | 2 & #T2\n//│  = [Number: 1]\n\ncase r of { T1 -> r | _ -> 0 }\n//│ res: 0 | #T1 & (1 | 2 & #T2)\n//│    = [Number: 1]\n\n// TODO also factor ClassTag-s like `2`:\ncase r of { T1 -> r | T2 -> r }\n//│ res: 1 & #T1 | 'a | #T2 & (2 & ~#T1 | 2 & ~#T2 | 2 & ~'a | 2 & #T1)\n//│    = [Number: 1]\n\nr = if true then T1 ((1,2,3)) else T2 ((3,4,5,4))\n//│ r: (3, 4, 5, 4,) & #T2 | (1, 2, 3,) & #T1\n//│  = [ 1, 2, 3 ]\n\ncase r of { T1 -> r | _ -> 0 }\n//│ res: 0 | #T1 & ((1, 2, 3,) | (3, 4, 5, 4,) & #T2)\n//│    = [ 1, 2, 3 ]\n\ncase r of { T1 -> r | T2 -> r }\n//│ res: (1, 2, 3,) & #T1 | 'a | #T2 & ((3, 4, 5, 4,) & ~#T1 | (3, 4, 5, 4,) & ~#T2 | (3, 4, 5, 4,) & ~'a | (3, 4, 5, 4,) & #T1)\n//│    = [ 1, 2, 3 ]\n\n\nx = 1\n//│ x: 1\n//│  = 1\n\nt2 = T2 x\n//│ t2: 1 & #T2\n//│   = [Number: 1]\n\nt1 = T1 t2\n//│ t1: 1 & #T1 & #T2\n//│   = [Number: 1]\n\nt1: T1\nt1: T2\n//│ res: T1\n//│    = [Number: 1]\n//│ res: T2\n//│    = [Number: 1]\n\n\nclass C1[A]: { a: A }\nclass C2[A]: { a: A }\n//│ Defined class C1[+A]\n//│ Defined class C2[+A]\n\nr = if true then C1 {a=x} else C2 {a=(3,4,5,4)}\n//│ r: C1[1] | C2[(3, 4, 5, 4,)]\n//│  = C1 { a: 1 }\n\ncase r of { C1 -> r.a | _ -> 0 }\n//│ res: 0 | 1\n//│    = 1\n\ndef x1: (int, bool)\ndef x2: (string, unit)\n//│ x1: (int, bool,)\n//│   = <missing implementation>\n//│ x2: (string, unit,)\n//│   = <missing implementation>\n\n\nif true then x1 else x2\n//│ res: (int | string, bool | unit,)\n//│    = <no result>\n//│      x1 is not implemented\n\n\n\ndef f: ((1,2) | (3,4)) -> anything\n//│ f: ((1 | 3, 2 | 4,),) -> anything\n//│  = <missing implementation>\n\nfun (x, y) -> f ((x,y))\n//│ res: (1 | 3, 2 | 4,) -> anything\n//│    = <no result>\n//│      f is not implemented\n\ndef f: ((1,2)&t1 | (3,4)&t2) -> anything\n//│ f: ((1, 2,) & #T1 | (3, 4,) & #T2) -> anything\n//│  = <missing implementation>\n\n:e\nf ((true,false))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.95: \tf ((true,false))\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` does not match type `1 | 3`\n//│ ║  l.95: \tf ((true,false))\n//│ ╙──      \t    ^^^^\n//│ res: error\n//│    = <no result>\n//│      f is not implemented\n\n:e\nfun (x, y) -> f ((x,y))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.107: \tfun (x, y) -> f ((x,y))\n//│ ║         \t              ^^^^^^^^^\n//│ ╟── tuple literal of type `(?a, ?b,)` does not match type `(1, 2,) & #T1 | (3, 4,) & #T2`\n//│ ║  l.107: \tfun (x, y) -> f ((x,y))\n//│ ║         \t                 ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.90: \tdef f: ((1,2)&t1 | (3,4)&t2) -> anything\n//│ ╙──      \t       ^^^^^^^^^^^^^^^^^^^^^\n//│ res: (nothing, nothing,) -> anything\n//│    = <no result>\n//│      f is not implemented\n\nfun (x, y) -> f (T1 ((x,y)))\n//│ res: (1, 2,) -> anything\n//│    = <no result>\n//│      f is not implemented\n\nfun (x, y) -> f (T2 ((x,y)))\n//│ res: (3, 4,) -> anything\n//│    = <no result>\n//│      f is not implemented\n\n:ns\nres = if true then (1,2, \"hello\") else (true, 3)\n//│ res: forall 'a. 'a\n//│   where\n//│     'a :> (1, 2, \"hello\",) | (true, 3,)\n//│    = [ 1, 2, 'hello' ]\n\nres = if true then (1, 2, 3, 'hello') else (true, 4, false)\nhhh = if false then (45,345, 'bye', true) else (false, 3)\nt = if false then res else hhh\ng = if true then (6,6,6) else res\ngwx = g with {x=123}\ngwx.x with {y = gwx}\n//│ res: Array[\"hello\" | 1 | 2 | 3 | 4 | false | true] & {0: 1 | true, 1: 2 | 4, 2: 3 | false}\n//│    = [ 1, 2, 3, 'hello' ]\n//│ hhh: Array[\"bye\" | 3 | 345 | 45 | false | true] & {0: 45 | false, 1: 3 | 345}\n//│    = [ false, 3 ]\n//│ t: Array[\"bye\" | \"hello\" | 1 | 2 | 3 | 345 | 4 | 45 | false | true] & {0: 1 | 45 | false | true, 1: 2 | 3 | 345 | 4}\n//│  = [ false, 3 ]\n//│ g: Array[\"hello\" | 1 | 2 | 3 | 4 | 6 | false | true] & {0: 1 | 6 | true, 1: 2 | 4 | 6, 2: 3 | 6 | false}\n//│  = [ 6, 6, 6 ]\n//│ gwx: Array[\"hello\" | 1 | 2 | 3 | 4 | 6 | false | true] & {0: 1 | 6 | true, 1: 2 | 4 | 6, 2: 3 | 6 | false, x: 123}\n//│    = [ 6, 6, 6, x: 123 ]\n//│ res: 123 & {\n//│   y: Array[\"hello\" | 1 | 2 | 3 | 4 | 6 | false | true] & {0: 1 | 6 | true, 1: 2 | 4 | 6, 2: 3 | 6 | false, x: 123}\n//│ }\n//│    = [Number: 123] { y: [ 6, 6, 6, x: 123 ] }\n\ndef f: (int, bool) -> int\ndef g: (bool, string, int) -> int\n// def h x = (f(x), g(x))\n//│ f: (int, bool,) -> int\n//│  = <missing implementation>\n//│ g: (bool, string, int,) -> int\n//│  = <missing implementation>\n\np1 = if true then (1, 2, 2) else (true, false)\n//│ p1: Array[1 | 2 | false | true] & {0: 1 | true, 1: 2 | false}\n//│   = [ 1, 2, 2 ]\n\ndef q: Array[int]\nq = if true then (1,1) else (1,1,1)\n//│ q: Array[int]\n//│  = <missing implementation>\n//│ Array[1] & {0: 1, 1: 1}\n//│   <:  q:\n//│ Array[int]\n//│  = [ 1, 1 ]\n\n// Note: function with non-tuple domain\ndef h f = (f (1,2,false), f (1,true))\n//│ h: ((1, 2, false,) -> 'a & (1, true,) -> 'b) -> ('a, 'b,)\n//│  = [Function: h]\n\n:e\nh (fun x -> x[0])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.186: \th (fun x -> x[0])\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── argument list of type `(1, true,)` does not match type `(?a,)`\n//│ ║  l.181: \tdef h f = (f (1,2,false), f (1,true))\n//│ ╙──       \t                            ^^^^^^^^\n//│ res: error | (undefined, undefined,)\n//│    = [ undefined, undefined ]\n\n:e\nh (fun (x, y) -> x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.197: \th (fun (x, y) -> x)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument list of type `(1, 2, false,)` does not match type `(?a, ?b,)`\n//│ ║  l.181: \tdef h f = (f (1,2,false), f (1,true))\n//│ ║         \t             ^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.197: \th (fun (x, y) -> x)\n//│ ╙──       \t       ^^^^^^\n//│ res: error | (nothing, 1,)\n//│    = [ 1, 1 ]\n\ndef h f = (f ((1,2,false)), f ((1,true)))\n//│ h: (((1, 2, false,),) -> 'a & ((1, true,),) -> 'b) -> ('a, 'b,)\n//│  = [Function: h1]\n\nh (fun x -> x[0])\nh (fun x -> x.0)\n//│ res: (1 | 2 | false | undefined, 1 | true | undefined,)\n//│    = [ 1, 1 ]\n//│ res: (1, 1,)\n//│    = [ 1, 1 ]\n\n\nq1 = (1,1,1,1)\nq2 = (1,1)\nfx ((a,b,c)) = a + b + c\n//│ q1: (1, 1, 1, 1,)\n//│   = [ 1, 1, 1, 1 ]\n//│ q2: (1, 1,)\n//│   = [ 1, 1 ]\n//│ fx: ((int, int, int,),) -> int\n//│   = [Function: fx]\n\n:e\nfx q1\nfx q2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.233: \tfx q1\n//│ ║         \t^^^^^\n//│ ╟── tuple literal of type `(1, 1, 1, 1,)` does not match type `(?a, ?b, ?c,)`\n//│ ║  l.222: \tq1 = (1,1,1,1)\n//│ ║         \t     ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(?d, ?e, ?f,)`\n//│ ║  l.233: \tfx q1\n//│ ║         \t   ^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.224: \tfx ((a,b,c)) = a + b + c\n//│ ╙──       \t    ^^^^^^^\n//│ res: error | int\n//│    = 3\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.234: \tfx q2\n//│ ║         \t^^^^^\n//│ ╟── tuple literal of type `(1, 1,)` does not match type `(?a, ?b, ?c,)`\n//│ ║  l.223: \tq2 = (1,1)\n//│ ║         \t     ^^^^^\n//│ ╟── but it flows into reference with expected type `(?d, ?e, ?f,)`\n//│ ║  l.234: \tfx q2\n//│ ║         \t   ^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.224: \tfx ((a,b,c)) = a + b + c\n//│ ╙──       \t    ^^^^^^^\n//│ res: error | int\n//│    = NaN\n\n\n// :d\nq = (1,1)\n//│ (1, 1,)\n//│   <:  q:\n//│ Array[int]\n//│  = [ 1, 1 ]\n\ndef sum: Array[int] -> int\nt1 = (1,2,3,4,5,6)\nsum t1\n//│ sum: Array[int] -> int\n//│    = <missing implementation>\n//│ t1: (1, 2, 3, 4, 5, 6,)\n//│   = [ 1, 2, 3, 4, 5, 6 ]\n//│ res: int\n//│    = <no result>\n//│      sum is not implemented\n\n:e\nt2 = (1,1,2,true)\nsum t2\n//│ t2: (1, 1, 2, true,)\n//│   = [ 1, 1, 2, true ]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.285: \tsum t2\n//│ ║         \t^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.284: \tt2 = (1,1,2,true)\n//│ ║         \t            ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.272: \tdef sum: Array[int] -> int\n//│ ╙──       \t               ^^^\n//│ res: error | int\n//│    = <no result>\n//│      sum is not implemented\n\nt2: (1, 1, 2, bool)\nt2: Array[int | bool]\n//│ res: (1, 1, 2, bool,)\n//│    = [ 1, 1, 2, true ]\n//│ res: Array[bool | int]\n//│    = [ 1, 1, 2, true ]\n\nclass Wrapped[A]: {len: int; inner: Array[A]}\n//│ Defined class Wrapped[+A]\n\ndef tk: Array['a] -> Wrapped['a]\ntk ((1,2,3,true,false))\n//│ tk: Array['a] -> Wrapped['a]\n//│   = <missing implementation>\n//│ res: Wrapped[1 | 2 | 3 | false | true]\n//│    = <no result>\n//│      tk is not implemented\n\nclass Two[A, B]: {fst: Array[A]; snd: Array[B]}\ntwo = Two {fst=(1,2,3); snd=(true,false)}\ntwo.fst\ntk (two.snd)\n//│ Defined class Two[+A, +B]\n//│ two: Two[1 | 2 | 3, Bool] & {fst: (1, 2, 3,), snd: (true, false,)}\n//│    = Two { fst: [ 1, 2, 3 ], snd: [ true, false ] }\n//│ res: (1, 2, 3,)\n//│    = [ 1, 2, 3 ]\n//│ res: Wrapped[Bool]\n//│    = <no result>\n//│      tk is not implemented\n\n:e\ndef a1: Array[int]\na1 = (1,2,true,'hello')\na1.1\n//│ a1: Array[int]\n//│   = <missing implementation>\n//│ (1, 2, true, \"hello\",)\n//│   <:  a1:\n//│ Array[int]\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.334: \ta1 = (1,2,true,'hello')\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of type `int`\n//│ ║  l.334: \ta1 = (1,2,true,'hello')\n//│ ║         \t          ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.333: \tdef a1: Array[int]\n//│ ╙──       \t              ^^^\n//│   = [ 1, 2, true, 'hello' ]\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.335: \ta1.1\n//│ ║         \t^^^^\n//│ ╟── type `Array[int]` does not have field '1'\n//│ ║  l.333: \tdef a1: Array[int]\n//│ ║         \t        ^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{1: ?a}`\n//│ ║  l.335: \ta1.1\n//│ ╙──       \t^^\n//│ res: error\n//│    = 2\n\ndef getx p = p.x\ndef a123: Array[int]\na123 = (1,2,3)\ngetx (a123 with {x=('hello', a123)})\n//│ getx: {x: 'x} -> 'x\n//│     = [Function: getx]\n//│ a123: Array[int]\n//│     = <missing implementation>\n//│ (1, 2, 3,)\n//│   <:  a123:\n//│ Array[int]\n//│     = [ 1, 2, 3 ]\n//│ res: (\"hello\", Array[int],)\n//│    = [ 'hello', [ 1, 2, 3 ] ]\n\ndef append: Array['a] -> Array['b] -> Array['a | 'b]\nappend ((1,2,false)) (((), 'hi'))\n//│ append: Array['a] -> Array['a] -> Array['a]\n//│       = <missing implementation>\n//│ res: Array[\"hi\" | 1 | 2 | false | ()]\n//│    = <no result>\n//│      append is not implemented\n\ndef append2: MutArray['aa] -> MutArray['bb] -> MutArray['aa | 'bb]\nappend2 ((mut 1, mut 2, mut false)) ((mut (), mut 'hi'))\n//│ append2: MutArray['aa] -> MutArray['bb] -> MutArray['aa | 'bb]\n//│        = <missing implementation>\n//│ res: MutArray['aa | 'bb]\n//│   where\n//│     'bb := 'a\n//│     'a :> \"hi\" | ()\n//│     'aa :> 'b\n//│         <: 'c & 'b\n//│     'b :> 1 | 2 | false\n//│        <: 'c\n//│     'c <: 'b\n//│    = <no result>\n//│      append2 is not implemented\n\n:e\nappend2 ((mut 1, mut 2, mut false)) ((mut (), 'hi'))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.403: \tappend2 ((mut 1, mut 2, mut false)) ((mut (), 'hi'))\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `\"hi\" | ?a` cannot be reassigned\n//│ res: error | MutArray['aa | 'bb]\n//│   where\n//│     'bb :> \"hi\" | ()\n//│     'aa :> 'a\n//│         <: 'b & 'a\n//│     'a :> 1 | 2 | false\n//│        <: 'b\n//│     'b <: 'a\n//│    = <no result>\n//│      append2 is not implemented\n\ndef ta: T1 & Array[int]\nta = T1 a123\n//│ ta: T1 & Array[int]\n//│   = <missing implementation>\n//│ Array[int] & #T1\n//│   <:  ta:\n//│ T1 & Array[int]\n//│   = [ 1, 2, 3 ]\n\ndef tb: T2 & Array[int]\ntb = T2 ((1,2,3))\ndef tba: (T2 & Array[int | bool]) -> (T2 & int)\ntba tb\n//│ tb: T2 & Array[int]\n//│   = <missing implementation>\n//│ (1, 2, 3,) & #T2\n//│   <:  tb:\n//│ T2 & Array[int]\n//│   = [ 1, 2, 3 ]\n//│ tba: (T2 & Array[bool | int]) -> (T2 & int)\n//│    = <missing implementation>\n//│ res: T2 & int\n//│    = <no result>\n//│      tba is not implemented\n\ndef k: (true, false, 3) & Array[int | true]\ndef k2: Array[1 | 2 | 3] & (true, 'hi', 2, 3)\n//│ k: (true, nothing, 3,)\n//│  = <missing implementation>\n//│ k2: (nothing, nothing, 2, 3,)\n//│   = <missing implementation>\n\ndef gett1 p q = case p of {T1 -> p | _ -> q}\ngett1 ta (T1 123)\ndef gt: (T1 & Array[int | bool]) -> Array[int]\ngt ta\ndef tg: ((T1 & Array[int]) | (T2 & Array[bool])) -> (T1 | T2)\n//│ gett1: (#T1 & 'a | ~#T1) -> 'a -> 'a\n//│      = [Function: gett1]\n//│ res: #T1 & (123 | Array[int])\n//│    = [ 1, 2, 3 ]\n//│ gt: (T1 & Array[bool | int]) -> Array[int]\n//│   = <missing implementation>\n//│ res: Array[int]\n//│    = <no result>\n//│      gt is not implemented\n//│ tg: (T1 & Array[int] | T2 & Array[bool]) -> (T1 | T2)\n//│   = <missing implementation>\n\ngett1 ta (T1 123)\ntg (T1 ((1,2,3,4)))\ntg (T2 ((true,false,false)))\n//│ res: #T1 & (123 | Array[int])\n//│    = [ 1, 2, 3 ]\n//│ res: T1 | T2\n//│    = <no result>\n//│      tg is not implemented\n//│ res: T1 | T2\n//│    = <no result>\n//│      tg is not implemented\n\ndef fst ((a, b)) = a\ndef snd ((a, b)) = b\ndef get: Array['a] -> int -> 'a\n//│ fst: (('a, anything,),) -> 'a\n//│    = [Function: fst]\n//│ snd: ((anything, 'a,),) -> 'a\n//│    = [Function: snd]\n//│ get: Array['a] -> int -> 'a\n//│    = <missing implementation>\n\nfst ((1,2))\nsnd ((1,2))\nget ((1,2,3)) 1\n//│ res: 1\n//│    = 1\n//│ res: 2\n//│    = 2\n//│ res: 1 | 2 | 3\n//│    = <no result>\n//│      get is not implemented\n\ndef intersect: Array['a] -> Array['b] -> Array['a & 'b]\niarr = intersect ((1,2,3,false)) ((1,5,true,'hi',false))\n//│ intersect: Array['a] -> Array['b] -> Array['a & 'b]\n//│          = <missing implementation>\n//│ iarr: Array[1 | false]\n//│     = <no result>\n//│       intersect is not implemented\n\n:e\nfst iarr\nsnd (T1 ((1,2,3)))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.510: \tfst iarr\n//│ ║         \t^^^^^^^^\n//│ ╟── type `Array['a & 'b]` is not a 2-element tuple\n//│ ║  l.501: \tdef intersect: Array['a] -> Array['b] -> Array['a & 'b]\n//│ ║         \t                                         ^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(?a, ?b,)`\n//│ ║  l.510: \tfst iarr\n//│ ║         \t    ^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.480: \tdef fst ((a, b)) = a\n//│ ╙──       \t         ^^^^^^\n//│ res: error\n//│    = <no result>\n//│      iarr and intersect are not implemented\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.511: \tsnd (T1 ((1,2,3)))\n//│ ║         \t^^^^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `(1, 2, 3,)` does not match type `(?a, ?b,) | ~#T1`\n//│ ║  l.511: \tsnd (T1 ((1,2,3)))\n//│ ║         \t         ^^^^^^^\n//│ ╟── but it flows into application with expected type `(?a, ?b,) | ~#T1`\n//│ ║  l.511: \tsnd (T1 ((1,2,3)))\n//│ ║         \t     ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.481: \tdef snd ((a, b)) = b\n//│ ╙──       \t         ^^^^^^\n//│ res: error\n//│    = 2\n\nv1 = T1 (T2 ((1,2,true)))\nv2 = T2 (v1 with {x=v1})\ndef inn: (T1 & T2 & Array['a]) -> 'a\ndef inn2: (T2 & Array[Array['a]]) -> Array[T1 & 'a]\ninn v1\ninn (v2 with {y= T1 ((1,2,3))})\ndef v3: Array[Array[(int, true)]]\nr1 = inn2 (T2 v3)\ninn (T1 (T2 v3))\n//│ v1: (1, 2, true,) & #T1 & #T2\n//│   = [ 1, 2, true ]\n//│ v2: (1, 2, true,) & {x: (1, 2, true,) & #T1 & #T2} & #T1 & #T2\n//│   = [ 1, 2, true, x: [ 1, 2, true ] ]\n//│ inn: (T1 & T2 & Array['a]) -> 'a\n//│    = <missing implementation>\n//│ inn2: (T2 & Array[Array['a]]) -> Array[T1 & 'a]\n//│     = <missing implementation>\n//│ res: 1 | 2 | true\n//│    = <no result>\n//│      inn is not implemented\n//│ res: 1 | 2 | true\n//│    = <no result>\n//│      inn is not implemented\n//│ v3: Array[Array[(int, true,)]]\n//│   = <missing implementation>\n//│ r1: Array[T1 & (int, true,)]\n//│   = <no result>\n//│     inn2 is not implemented\n//│ res: Array[(int, true,)]\n//│    = <no result>\n//│      inn is not implemented\n\nv3: Array[Array[Array[int | bool]]]\ninn2 (T2 r1)\n//│ res: Array[Array[Array[bool | int]]]\n//│    = <no result>\n//│      v3 is not implemented\n//│ res: Array[T1 & int | T1 & true]\n//│    = <no result>\n//│      inn2 is not implemented\n\n:e\ninn (T1 v3)\ninn2 v1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.584: \tinn (T1 v3)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── type `Array[Array[(int, true,)]]` does not match type `#T2 | ~#T1`\n//│ ║  l.548: \tdef v3: Array[Array[(int, true)]]\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `#T2 | ~#T1`\n//│ ║  l.584: \tinn (T1 v3)\n//│ ║         \t        ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.544: \tdef inn: (T1 & T2 & Array['a]) -> 'a\n//│ ║         \t               ^^\n//│ ╟── from intersection type:\n//│ ║  l.544: \tdef inn: (T1 & T2 & Array['a]) -> 'a\n//│ ╙──       \t         ^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | Array[(int, true,)]\n//│    = <no result>\n//│      inn is not implemented\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.585: \tinn2 v1\n//│ ║         \t^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `Array['a]`\n//│ ║  l.542: \tv1 = T1 (T2 ((1,2,true)))\n//│ ╙──       \t              ^\n//│ res: error | Array[nothing]\n//│    = <no result>\n//│      inn2 is not implemented\n\ndef ra: ('a, 'a) as 'a\nra: Array[Array['a]] as 'a\nra: Array[('a, 'a)] as 'a\nra: (Array['a], Array['a]) as 'a\n//│ ra: 'a\n//│   where\n//│     'a :> ('a, 'a,)\n//│   = <missing implementation>\n//│ res: 'a\n//│   where\n//│     'a :> Array[Array['a]]\n//│    = <no result>\n//│      ra is not implemented\n//│ res: 'a\n//│   where\n//│     'a :> Array[('a, 'a,)]\n//│    = <no result>\n//│      ra is not implemented\n//│ res: 'a\n//│   where\n//│     'a :> (Array['a], Array['a],)\n//│    = <no result>\n//│      ra is not implemented\n\n:e\nra: ('a, 'a, 'a) as 'a\nra: (Array['a], Array['a], Array['a]) as 'a\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.639: \tra: ('a, 'a, 'a) as 'a\n//│ ║         \t^^\n//│ ╟── type `('a, 'a,)` does not match type `('a0, 'a0, 'a0,)`\n//│ ║  l.614: \tdef ra: ('a, 'a) as 'a\n//│ ║         \t        ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `('a1, 'a1, 'a1,)`\n//│ ║  l.639: \tra: ('a, 'a, 'a) as 'a\n//│ ║         \t^^\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.639: \tra: ('a, 'a, 'a) as 'a\n//│ ╙──       \t    ^^^^^^^^^^^^\n//│ res: 'a\n//│   where\n//│     'a :> ('a, 'a, 'a,)\n//│    = <no result>\n//│      ra is not implemented\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.640: \tra: (Array['a], Array['a], Array['a]) as 'a\n//│ ║         \t^^\n//│ ╟── type `('a, 'a,)` does not match type `(Array['a0], Array['a0], Array['a0],)`\n//│ ║  l.614: \tdef ra: ('a, 'a) as 'a\n//│ ║         \t        ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(Array['a1], Array['a1], Array['a1],)`\n//│ ║  l.640: \tra: (Array['a], Array['a], Array['a]) as 'a\n//│ ║         \t^^\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.640: \tra: (Array['a], Array['a], Array['a]) as 'a\n//│ ╙──       \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: 'a\n//│   where\n//│     'a :> (Array['a], Array['a], Array['a],)\n//│    = <no result>\n//│      ra is not implemented\n\ndef tktup t = (t.1, t.2)\ntktup ((1,2,3,true))\n//│ tktup: {1: 'a, 2: 'b} -> ('a, 'b,)\n//│      = [Function: tktup]\n//│ res: (2, 3,)\n//│    = [ 2, 3 ]\n\n:e\ntktup a123\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.684: \ttktup a123\n//│ ║         \t^^^^^^^^^^\n//│ ╟── type `Array[int]` does not have field '2'\n//│ ║  l.364: \tdef a123: Array[int]\n//│ ║         \t          ^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{2: ?a}`\n//│ ║  l.684: \ttktup a123\n//│ ║         \t      ^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.676: \tdef tktup t = (t.1, t.2)\n//│ ║         \t                    ^^^\n//│ ╟── from reference:\n//│ ║  l.676: \tdef tktup t = (t.1, t.2)\n//│ ╙──       \t                    ^\n//│ res: error | (nothing, nothing,)\n//│    = [ 2, 3 ]\n\n\ndef definedOr x els = case x of {\n  | undefined -> els()\n  | _ -> x\n  }\ndef defined x = definedOr x (fun () -> error)\ndef ornull x = definedOr x (fun () -> null)\n//│ definedOr: (undefined | 'a & ~undefined) -> (() -> 'a) -> 'a\n//│          = [Function: definedOr]\n//│ defined: (undefined | 'a & ~undefined) -> 'a\n//│        = [Function: defined]\n//│ ornull: (undefined | 'a & ~undefined) -> (null | 'a)\n//│       = [Function: ornull]\n\n:re\ndefined ()[0]\n//│ res: nothing\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\nta1 = (2,3,4,5)\nta1[1]\nta2 = ((1,2,4), (true, false))\n(ornull (defined ta2[0])[1+4], defined ta[1])[0]\nta3 = ((1,2,3), \"hello\", false)\nta3[1-2]\n(1,2,3)[4]\n//│ ta1: (2, 3, 4, 5,)\n//│    = [ 2, 3, 4, 5 ]\n//│ res: 2 | 3 | 4 | 5 | undefined\n//│    = 3\n//│ ta2: ((1, 2, 4,), (true, false,),)\n//│    = [ [ 1, 2, 4 ], [ true, false ] ]\n//│ res: false | int | null | true | undefined\n//│    = null\n//│ ta3: ((1, 2, 3,), \"hello\", false,)\n//│    = [ [ 1, 2, 3 ], 'hello', false ]\n//│ res: \"hello\" | false | undefined | (1, 2, 3,)\n//│    = undefined\n//│ res: 1 | 2 | 3 | undefined\n//│    = undefined\n\n:e\n((defined ta2[0])[1+4], ta[1])[0]\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.747: \t((defined ta2[0])[1+4], ta[1])[0]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── possibly-undefined array access of type `undefined` does not match type `~undefined`\n//│ ║  l.747: \t((defined ta2[0])[1+4], ta[1])[0]\n//│ ╙──       \t ^^^^^^^^^^^^^^^^^^^^^\n//│ res: error | false | int | true | undefined\n//│    = undefined\n\n:e\ndef ge x = x + 1\nta3[ge 3][ge (1+2)]\ntrue[false]\n4[\"hello\"]\nge[2]\n//│ ge: int -> int\n//│   = [Function: ge]\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.759: \tta3[ge 3][ge (1+2)]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"hello\"` does not match type `Array[?a]`\n//│ ║  l.728: \tta3 = ((1,2,3), \"hello\", false)\n//│ ║         \t                ^^^^^^^\n//│ ╟── but it flows into array access with expected type `Array[?b]`\n//│ ║  l.759: \tta3[ge 3][ge (1+2)]\n//│ ╙──       \t^^^^^^^^^\n//│ res: 1 | 2 | 3 | error | undefined\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading '4')\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.760: \ttrue[false]\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of type `int`\n//│ ║  l.760: \ttrue[false]\n//│ ╙──       \t     ^^^^^\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.760: \ttrue[false]\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── reference of type `true` does not match type `Array[?a]`\n//│ ║  l.760: \ttrue[false]\n//│ ╙──       \t^^^^\n//│ res: error | undefined\n//│    = undefined\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.761: \t4[\"hello\"]\n//│ ║         \t^^^^^^^^^^\n//│ ╟── string literal of type `\"hello\"` is not an instance of type `int`\n//│ ║  l.761: \t4[\"hello\"]\n//│ ╙──       \t  ^^^^^^^\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.761: \t4[\"hello\"]\n//│ ║         \t^^^^^^^^^^\n//│ ╟── integer literal of type `4` does not match type `Array[?a]`\n//│ ║  l.761: \t4[\"hello\"]\n//│ ╙──       \t^\n//│ res: error | undefined\n//│    = undefined\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.762: \tge[2]\n//│ ║         \t^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b)` does not match type `Array[?c]`\n//│ ║  l.758: \tdef ge x = x + 1\n//│ ║         \t       ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Array[?d]`\n//│ ║  l.762: \tge[2]\n//│ ╙──       \t^^\n//│ res: error | undefined\n//│    = undefined\n\ndef mkarr: 'a -> Array['a]\ndef mkarr x = (x,x,x,x,x)\nmk1 = defined (mkarr 6)[ 0]\n(mkarr (mk1/3))[(3)]\nmkarr (1,true,\"hi\")[0]\n//│ mkarr: 'a -> Array['a]\n//│      = <missing implementation>\n//│ 'a -> ('a, 'a, 'a, 'a, 'a,)\n//│   <:  mkarr:\n//│ 'a -> Array['a]\n//│      = [Function: mkarr]\n//│ mk1: 6\n//│    = 6\n//│ res: number | undefined\n//│    = 2\n//│ res: Array[\"hi\" | 1 | true | undefined]\n//│    = [ 1, 1, 1, 1, 1 ]\n\n:e \nmkarr 3 [  1]\nmk1[2  ]\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.836: \tmkarr 3 [  1]\n//│ ║         \t      ^^^^^^^\n//│ ╟── integer literal of type `3` does not match type `Array[?a]`\n//│ ║  l.836: \tmkarr 3 [  1]\n//│ ╙──       \t      ^\n//│ res: Array[error | undefined]\n//│    = [ undefined, undefined, undefined, undefined, undefined ]\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.837: \tmk1[2  ]\n//│ ║         \t^^^^^^^^\n//│ ╟── integer literal of type `6` does not match type `Array[?a]`\n//│ ║  l.819: \tmk1 = defined (mkarr 6)[ 0]\n//│ ║         \t                     ^\n//│ ╟── but it flows into reference with expected type `Array[?b]`\n//│ ║  l.837: \tmk1[2  ]\n//│ ╙──       \t^^^\n//│ res: error | undefined\n//│    = undefined\n\ndef s1 a = (defined a[1] + defined a[2], a[(1,2).1])\ndef s2 a = (defined (defined a[1])[0]).1 + (defined a[2]).0\ndef s3 a = defined a.0.t[0] + defined (defined a.x[1])[2]\n(defined ((1, \"hello\"),(2, true, false),(3,3,4))[0]).0\n//│ s1: Array[int & 'a] -> (int, undefined | 'a,)\n//│   = [Function: s1]\n//│ s2: Array[Array[{1: int} & ~undefined] & {0: int}] -> int\n//│   = [Function: s2]\n//│ s3: {0: {t: Array[int]}, x: Array[Array[int]]} -> int\n//│   = [Function: s3]\n//│ res: 1 | 2 | 3\n//│    = 1\n\ndef ara: Array[(int, bool)]\ndef arb: Array[Array[(int, int)]]\n(defined ara[1]).0\n(defined (defined arb[0])[1]).1\ndef s4 arr = (defined (defined (defined arr.x[0]).2[6])[7])._h.hello\n//│ ara: Array[(int, bool,)]\n//│    = <missing implementation>\n//│ arb: Array[Array[(int, int,)]]\n//│    = <missing implementation>\n//│ res: int\n//│    = <no result>\n//│      ara is not implemented\n//│ res: int\n//│    = <no result>\n//│      arb is not implemented\n//│ s4: {x: Array[{2: Array[Array[{_h: {hello: 'hello}} & ~undefined]]} & ~undefined]} -> 'hello\n//│   = [Function: s4]\n\ndef at1 xs = (defined xs[0]).0\ndef dup a b = a * 2 + b\ndup (defined ara[1]).0 (defined (defined arb[10])[8]).1 + 1\n//│ at1: Array[{0: 'a} & ~undefined] -> 'a\n//│    = [Function: at1]\n//│ dup: int -> int -> int\n//│    = [Function: dup]\n//│ res: int\n//│    = <no result>\n//│      ara is not implemented\n\n:e\n(1,2,3).0[1]\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.901: \t(1,2,3).0[1]\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `Array[?a]`\n//│ ║  l.901: \t(1,2,3).0[1]\n//│ ║         \t ^\n//│ ╟── but it flows into field selection with expected type `Array[?b]`\n//│ ║  l.901: \t(1,2,3).0[1]\n//│ ╙──       \t^^^^^^^^^\n//│ res: error | undefined\n//│    = undefined\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/Yuheng.mls",
    "content": "\n1 + 2\n//│ res: int\n//│    = 3\n\ndef foo(x) = x + 1\n//│ foo: int -> int\n//│    = [Function: foo]\n\nclass A: { x: number }\n//│ Defined class A\n\ndef f v = v.x\n//│ f: {x: 'x} -> 'x\n//│  = [Function: f]\n\n// def f: (A & {x: int} | anything) -> int\n\ndef f v = case v of {\n    A -> (v.x : int)\n  | _ -> 0\n }\n//│ f: (A & {x: int} | ~A) -> int\n//│  = [Function: f1]\n\na1 = A { x = 0 }\n//│ a1: A & {x: 0}\n//│   = A { x: 0 }\n\nf a1\n//│ res: int\n//│    = 0\n\na2 = A { x = 0: number }\n//│ a2: A\n//│   = A { x: 0 }\n\n:e\nf a2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.39: \tf a2\n//│ ║        \t^^^^\n//│ ╟── type `number` is not an instance of type `int`\n//│ ║  l.34: \ta2 = A { x = 0: number }\n//│ ║        \t                ^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.20: \t    A -> (v.x : int)\n//│ ║        \t                ^^^\n//│ ╟── from field selection:\n//│ ║  l.20: \t    A -> (v.x : int)\n//│ ╙──      \t          ^^^\n//│ res: error | int\n//│    = 0\n\ndef f2: (A & {x: int} | anything) -> int\n//│ f2: anything -> int\n//│   = <missing implementation>\n\nf2 a2\n//│ res: int\n//│    = <no result>\n//│      f2 is not implemented\n\n\n// const x: [0, 1] = [0, 1]\n\na = (0, 1)\n//│ a: (0, 1,)\n//│  = [ 0, 1 ]\n\n\n1 : 1\n//│ res: 1\n//│    = 1\n\n// def f(x) =\n//   x : x\n//   f2 x : f2 x\n\n:w\nclass Expr[A]\n//│ Defined class Expr[±A]\n//│ ╔══[WARNING] Type definition Expr has bivariant type parameters:\n//│ ║  l.81: \tclass Expr[A]\n//│ ║        \t      ^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.81: \tclass Expr[A]\n//│ ╙──      \t           ^\n\nclass IntLit: Expr[int] & { value: int }\n//│ Defined class IntLit\n\n:w\nclass Pair[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[B] }\n//│ Defined class Pair[±A, ±B]\n//│ ╔══[WARNING] Type definition Pair has bivariant type parameters:\n//│ ║  l.94: \tclass Pair[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[B] }\n//│ ║        \t      ^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.94: \tclass Pair[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[B] }\n//│ ║        \t           ^\n//│ ╟── B is irrelevant and may be removed\n//│ ║  l.94: \tclass Pair[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[B] }\n//│ ╙──      \t              ^\n\nrec def eval(e) = case e of\n  { IntLit -> e.value\n  | Pair -> (eval e.lhs, eval e.rhs)\n  }\n//│ eval: 'a -> 'value\n//│   where\n//│     'a <: (IntLit with {value: 'value}) | (Pair[?, ?] with {lhs: 'a, rhs: 'a})\n//│     'value :> ('value, 'value,)\n//│     = [Function: eval]\n\nrec def eval(e) = case e of\n  { IntLit -> e.value\n  | Pair -> (eval e.lhs,)\n  }\n//│ eval: 'a -> 'value\n//│   where\n//│     'a <: (IntLit with {value: 'value}) | (Pair[?, ?]\\rhs with {lhs: 'a})\n//│     'value :> ('value,)\n//│     = [Function: eval1]\n\nrec def eval(e) = case e of\n  { IntLit -> e.value\n  | Pair -> (eval e.lhs, eval e.rhs)\n  | _ -> error\n  }\n//│ eval: 'a -> 'value\n//│   where\n//│     'a <: (IntLit with {value: 'value}) | (Pair[?, ?] with {lhs: 'a, rhs: 'a}) | ~IntLit & ~Pair[?, ?]\n//│     'value :> ('value, 'value,)\n//│     = [Function: eval2]\n\neval (IntLit { value = 1 })\n//│ res: 'a\n//│   where\n//│     'a :> 1 | ('a, 'a,)\n//│    = 1\n\neval (Pair {\n  lhs = IntLit { value = 1 };\n  rhs = IntLit { value = 2 } })\n//│ res: 'a\n//│   where\n//│     'a :> 1 | 2 | ('a, 'a,)\n//│    = [ 1, 2 ]\n\np = Pair {\n  lhs = IntLit { value = 1 };\n  rhs = Pair {\n    lhs = IntLit { value = 2 };\n    rhs = IntLit { value = 3 } } }\n//│ p: Pair[?, ?] with {\n//│   lhs: IntLit & {value: 1},\n//│   rhs: Pair[?, ?] with {lhs: IntLit & {value: 2}, rhs: IntLit & {value: 3}}\n//│ }\n//│  = Pair {\n//│      lhs: IntLit1 { value: 1 },\n//│      rhs: Pair { lhs: IntLit1 { value: 2 }, rhs: IntLit1 { value: 3 } }\n//│    }\n\nep = eval p\n//│ ep: 'a\n//│   where\n//│     'a :> 1 | 2 | 3 | ('a, 'a,)\n//│   = [ 1, [ 2, 3 ] ]\n\n\n// FUTURE:\n\n// class Expr[type A]\n\n// def eval['a]: Expr['a] -> 'a\n// rec def eval(e: Expr['a]) = case e of\n//   { IntLit -> e.value\n//   | Pair -> (eval e.lhs, eval[e.rhs] (e.rhs: Expr[e.rhs.A]))\n//   | _ -> error\n//   }\n\n// class Vector[A, N: nat]\n// class Nil: Vector['a, 0]\n// class Cons[A, m]: Vector[A, S m]\n\n\n\n// === === === ERROR CASES === === === //\n\n\n\n:w\nclass Pair2[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[A] }\n//│ Defined class Pair2[±A, ±B]\n//│ ╔══[WARNING] Type definition Pair2 has bivariant type parameters:\n//│ ║  l.194: \tclass Pair2[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[A] }\n//│ ║         \t      ^^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.194: \tclass Pair2[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[A] }\n//│ ║         \t            ^\n//│ ╟── B is irrelevant and may be removed\n//│ ║  l.194: \tclass Pair2[A, B]: Expr[(A, B)] & { lhs: Expr[A]; rhs: Expr[A] }\n//│ ╙──       \t               ^\n\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\n\nep + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.+1: \tep + 1\n//│ ║        \t^^^^\n//│ ╟── tuple literal of type `(?a, ?b,)` is not an instance of type `int`\n//│ ║  l.128: \t  | Pair -> (eval e.lhs, eval e.rhs)\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `int`\n//│ ║  l.+1: \tep + 1\n//│ ╙──      \t^^\n//│ res: error | int\n\nep[0]\n//│ ╔══[ERROR] Type mismatch in array access:\n//│ ║  l.+1: \tep[0]\n//│ ║        \t^^^^^\n//│ ╟── integer literal of type `1` does not match type `Array[?a]`\n//│ ║  l.152: \t  lhs = IntLit { value = 1 };\n//│ ║         \t                         ^\n//│ ╟── but it flows into reference with expected type `Array[?b]`\n//│ ║  l.+1: \tep[0]\n//│ ╙──      \t^^\n//│ res: error | undefined | 'a\n//│   where\n//│     'a :> 1 | 2 | 3 | ('a, 'a,)\n\n\neval (Pair {\n  lhs = IntLit { value = 1 };\n  rhs = IntLit { value = Pair {\n    lhs = IntLit { value = 2 };\n    rhs = IntLit { value = 3 } } } })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+3: \t  rhs = IntLit { value = Pair {\n//│ ║        \t        ^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+4: \t    lhs = IntLit { value = 2 };\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+5: \t    rhs = IntLit { value = 3 } } } })\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Pair[?, ?] & {Pair#A = ?A, Pair#B = ?B, lhs: ?lhs, rhs: ?rhs}` is not an instance of type `int`\n//│ ║  l.+3: \t  rhs = IntLit { value = Pair {\n//│ ║        \t                         ^^^^^^\n//│ ║  l.+4: \t    lhs = IntLit { value = 2 };\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+5: \t    rhs = IntLit { value = 3 } } } })\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.90: \tclass IntLit: Expr[int] & { value: int }\n//│ ╙──      \t                                   ^^^\n//│ res: 'a\n//│   where\n//│     'a :> 1 | (Pair[?, ?] with {lhs: IntLit & {value: 2}, rhs: IntLit & {value: 3}}) | ('a, 'a,)\n\n\np = Pair2 {\n  lhs = IntLit { value = 1 };\n  rhs = Pair2 {\n    lhs = IntLit { value = 2 };\n    rhs = IntLit { value = 3 } } }\n//│ p: Pair2[?, ?] with {\n//│   lhs: IntLit & {value: 1},\n//│   rhs: Pair2[?, ?] with {lhs: IntLit & {value: 2}, rhs: IntLit & {value: 3}}\n//│ }\n\n\n\ndef eval: Expr['a] -> 'a\n//│ eval: Expr[?] -> nothing\n\nrec def eval(e) = case e of\n  { IntLit -> e.value\n  | Pair -> (eval e.lhs, eval e.rhs)\n  }\n//│ 'a -> 'value\n//│   where\n//│     'a <: (IntLit with {value: 'value}) | (Pair[?, ?] with {lhs: 'a, rhs: 'a})\n//│     'value :> ('value, 'value,)\n//│   <:  eval:\n//│ Expr[?] -> nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \trec def eval(e) = case e of\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+2: \t  { IntLit -> e.value\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+3: \t  | Pair -> (eval e.lhs, eval e.rhs)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+4: \t  }\n//│ ║        \t^^^\n//│ ╟── type `Expr[?]` does not match type `IntLit & ?a | Pair[?, ?] & ?b`\n//│ ║  l.279: \tdef eval: Expr['a] -> 'a\n//│ ║         \t          ^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.+1: \trec def eval(e) = case e of\n//│ ╙──      \t                       ^\n\nrec def eval(e) = case e of\n  { IntLit -> e.value\n  | Pair -> (eval e.lhs, eval e.rhs)\n  | _ -> error\n  }\n//│ 'a -> 'value\n//│   where\n//│     'a <: (IntLit with {value: 'value}) | (Pair[?, ?] with {lhs: 'a, rhs: 'a}) | ~IntLit & ~Pair[?, ?]\n//│     'value :> ('value, 'value,)\n//│   <:  eval:\n//│ Expr[?] -> nothing\n//│ ╔══[ERROR] Type mismatch in def definition:\n//│ ║  l.+1: \trec def eval(e) = case e of\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+2: \t  { IntLit -> e.value\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+3: \t  | Pair -> (eval e.lhs, eval e.rhs)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.+4: \t  | _ -> error\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.+5: \t  }\n//│ ║        \t^^^\n//│ ╟── expression of type `Expr[?] & ~#IntLit & ~?a | Pair[?, ?]` does not have field 'rhs'\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.+3: \t  | Pair -> (eval e.lhs, eval e.rhs)\n//│ ║        \t                              ^^^^^\n//│ ╟── from refined scrutinee:\n//│ ║  l.+1: \trec def eval(e) = case e of\n//│ ╙──      \t                       ^\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/i26.mls",
    "content": ""
  },
  {
    "path": "shared/src/test/diff/mlscript/i56.mls",
    "content": "// https://github.com/hkust-taco/mlscript/issues/56\n\n\ndef test3 x = case x of\n  { 1 -> true\n  | true -> true\n  | _ -> false\n  }\n//│ test3: anything -> Bool\n//│      = [Function: test3]\n\n:ns\ntest3\n//│ res: forall 'a 'b 'c 'd. 'a -> Bool\n//│   where\n//│     'a <: 1 & 'b | (true & 'c | 'd & ~true) & ~1\n//│    = [Function: test3]\n\n\ndef test3 x = case x of\n  { 1 -> x\n  | true -> true\n  | _ -> false\n  }\n//│ test3: (1 & 'a | ~1) -> (Bool | 'a)\n//│      = [Function: test31]\n\n\ndef ty_1: (1 & 'a | true | ~1 & ~true) -> (false | true | 'a)\n//│ ty_1: (1 & 'a | true | ~1 & ~true) -> (Bool | 'a)\n//│     = <missing implementation>\n\nty_1 = test3\n//│ (1 & 'a | ~1) -> (Bool | 'a)\n//│   <:  ty_1:\n//│ (1 & 'a | true | ~1 & ~true) -> (Bool | 'a)\n//│     = [Function: test31]\n\ndef ty_2: (1 & 'a | ~1) -> (false | true | 'a)\n//│ ty_2: (1 & 'a | ~1) -> (Bool | 'a)\n//│     = <missing implementation>\n\nty_2 = ty_1\n//│ (1 & 'a | true | ~1 & ~true) -> (Bool | 'a)\n//│   <:  ty_2:\n//│ (1 & 'a | ~1) -> (Bool | 'a)\n//│     = [Function: test31]\n\n\n// * Note: it is a bit counter-intuitive that we have:\n// *    (1 & 'a | ~1)  <:  (1 & 'a | true | ~1 & ~true)\n// *  and in particular:\n// *    ~1  <:  (1 & 'a | true | ~1 & ~true)\n// *  but the latter can be understood by seeing that it's equivalent (by swapping) to:\n// *    (1 | true)  <:  (1 & 'a | true | 1)\n// *  ie\n// *    (1 | true)  <:  (true | 1)\n\n"
  },
  {
    "path": "shared/src/test/diff/mlscript/i65.mls",
    "content": ":js\n42\n//│ // Prelude\n//│ let res;\n//│ // Query 1\n//│ res = 42;\n//│ // End of generated code\n//│ res: 42\n//│    = 42\n\n:js\nfoo = \"oops\"\n//│ // Query 1\n//│ globalThis.foo = \"oops\";\n//│ // End of generated code\n//│ foo: \"oops\"\n//│    = 'oops'\n\n:js\nres\n//│ // Query 1\n//│ res = res;\n//│ // End of generated code\n//│ res: 42\n//│    = 42\n\n:js\nres = 5\n//│ // Query 1\n//│ globalThis.res1 = 5;\n//│ // End of generated code\n//│ res: 5\n//│    = 5\n\nres\n//│ res: 5\n//│    = 5\n\n:js\nfoo\n//│ // Query 1\n//│ res = foo;\n//│ // End of generated code\n//│ res: \"oops\"\n//│    = 'oops'\n\n:js\nres\n//│ // Query 1\n//│ res = res;\n//│ // End of generated code\n//│ res: \"oops\"\n//│    = 'oops'\n\ndef res: bool\n//│ res: bool\n//│    = <missing implementation>\n\n42\n//│ res: 42\n//│    = 42\n\nres\n//│ res: 42\n//│    = 42\n"
  },
  {
    "path": "shared/src/test/diff/nu/AbstractClasses.mls",
    "content": ":NewDefs\n\n\n\nabstract class Foo(x: Int) {\n  fun f(y: Int) = x + y\n}\n//│ abstract class Foo(x: Int) {\n//│   fun f: (y: Int) -> Int\n//│ }\n\n:e\nFoo(1)\n//│ ╔══[ERROR] Class Foo is abstract and cannot be instantiated\n//│ ║  l.13: \tFoo(1)\n//│ ╙──      \t^^^\n//│ Foo\n//│ res\n//│     = Foo {}\n\n:e // TODO allow with `new` keyword\nnew Foo(1)\n//│ ╔══[ERROR] Class Foo is abstract and cannot be instantiated\n//│ ║  l.22: \tnew Foo(1)\n//│ ╙──      \t^^^^^^^^^^\n//│ Foo\n//│ res\n//│     = Foo {}\n\n\nabstract class Foo(x: Int) {\n  fun f: Int -> Int\n}\n//│ abstract class Foo(x: Int) {\n//│   fun f: Int -> Int\n//│ }\n\n:e\nFoo(1)\n//│ ╔══[ERROR] Class Foo is abstract and cannot be instantiated\n//│ ║  l.39: \tFoo(1)\n//│ ╙──      \t^^^\n//│ Foo\n//│ res\n//│     = Foo {}\n\n:e // TODO support\nnew Foo(1) { fun f = id }\n//│ ╔══[ERROR] Refinement terms are not yet supported\n//│ ║  l.48: \tnew Foo(1) { fun f = id }\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   cannot generate code for term Rft(App(NuNew(Var(Foo)),Tup(List((None,Fld(_,IntLit(1)))))),TypingUnit(List(NuFunDef(None,Var(f),None,List(),Left(Var(id))))))\n\n\nabstract class Bar extends Foo(1)\n//│ abstract class Bar extends Foo {\n//│   fun f: Int -> Int\n//│ }\n\n:e\nmodule Baz extends Bar\nBaz.f(1)\n//│ ╔══[ERROR] Member `f` is declared (or its declaration is inherited) but is not implemented in `Baz`\n//│ ║  l.63: \tmodule Baz extends Bar\n//│ ║        \t       ^^^\n//│ ╟── Declared here:\n//│ ║  l.32: \t  fun f: Int -> Int\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^\n//│ module Baz extends Bar, Foo {\n//│   fun f: Int -> Int\n//│ }\n//│ Int\n//│ res\n//│ Runtime error:\n//│   TypeError: Baz.f is not a function\n\nmodule Baz extends Bar {\n  fun f(x) = x + 1\n}\nBaz.f(1)\n//│ module Baz extends Bar, Foo {\n//│   fun f: Int -> Int\n//│ }\n//│ Int\n//│ res\n//│     = 2\n\n\n\nabstract class C1 { fun x: Int | Str }\n//│ abstract class C1 {\n//│   fun x: Int | Str\n//│ }\n\ntrait T1 { fun x: Int | Bool }\n//│ trait T1 {\n//│   fun x: Int | false | true\n//│ }\n\n:e\nclass C2 extends C1, T1\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C2`\n//│ ║  l.103: \tclass C2 extends C1, T1\n//│ ║         \t      ^^\n//│ ╟── Declared here:\n//│ ║  l.92: \tabstract class C1 { fun x: Int | Str }\n//│ ╙──      \t                        ^^^^^^^^^^^^\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│   fun x: Int\n//│ }\n\nclass C2 extends C1, T1 { fun x = 1 }\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\nabstract class C2 extends C1, T1\n//│ abstract class C2 extends C1, T1 {\n//│   fun x: Int\n//│ }\n\n:e\nclass C3 extends C2\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C3`\n//│ ║  l.127: \tclass C3 extends C2\n//│ ║         \t      ^^\n//│ ╟── Declared here:\n//│ ║  l.92: \tabstract class C1 { fun x: Int | Str }\n//│ ╙──      \t                        ^^^^^^^^^^^^\n//│ class C3 extends C1, C2, T1 {\n//│   constructor()\n//│   fun x: Int\n//│ }\n\nclass C3 extends C2 { fun x = 1 }\n//│ class C3 extends C1, C2, T1 {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\n\n\n:e\nabstract class C {\n  fun x : Int\n  fun foo0 = x\n  fun foo1 = this.x\n}\n//│ ╔══[ERROR] Unqualified access to virtual member x\n//│ ║  l.150: \t  fun foo0 = x\n//│ ║         \t      ^^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.149: \t  fun x : Int\n//│ ╙──       \t  ^^^^^^^^^^^\n//│ abstract class C {\n//│   fun foo0: Int\n//│   fun foo1: Int\n//│   fun x: Int\n//│ }\n\n:e\nabstract class C {\n  val x : Int\n  fun foo0 = x\n  fun foo1 = this.x\n}\n//│ ╔══[ERROR] Unqualified access to virtual member x\n//│ ║  l.168: \t  fun foo0 = x\n//│ ║         \t      ^^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.167: \t  val x : Int\n//│ ╙──       \t  ^^^^^^^^^^^\n//│ abstract class C {\n//│   fun foo0: Int\n//│   fun foo1: Int\n//│   val x: Int\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Andong.mls",
    "content": ":NewDefs\n\n\nclass Union<Region>(a: Region, b: Region)\n//│ class Union[Region](a: Region, b: Region)\n\nfun hmm(x) =\n  if x is Union(x, y) then x\n//│ fun hmm: forall 'a. Union['a] -> 'a\n\nfun hmm(x) =\n  if x is Union(z, y) then x\n//│ fun hmm: forall 'Region. Union['Region] -> Union['Region]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Annotations.mls",
    "content": ":NewDefs\n\n// This should not be needed once we implemented the @tailrec annotation internally.\nmodule tailrec extends Annotation\n//│ module tailrec extends Annotation\n\ntailrec\n//│ tailrec\n//│ res\n//│     = tailrec { class: [class tailrec extends Object] }\n\n@tailrec fun foo(n) =\n  if n > 0 then\n    log(join of \"hi \", String(n))\n    foo(n - 1)\n  else ()\n//│ fun foo: Int -> ()\n\n\nmodule Foo extends Annotation { \n}\n//│ module Foo extends Annotation\n\n@Foo 5\n//│ 5\n//│ res\n//│     = 5\n\nFoo\n//│ Foo\n//│ res\n//│     = Foo { class: [class Foo extends Object] }\n\n:e\n@Bar 5\n//│ ╔══[ERROR] identifier not found: Bar\n//│ ║  l.35: \t@Bar 5\n//│ ╙──      \t ^^^\n//│ 5\n//│ res\n//│     = 5\n\n:e\nlet x = 1\n@x 2\n//│ ╔══[ERROR] Type mismatch in annotated integer literal:\n//│ ║  l.45: \t@x 2\n//│ ║        \t ^^^\n//│ ╟── integer literal of type `1` is not an instance of type `Annotation`\n//│ ║  l.44: \tlet x = 1\n//│ ║        \t        ^\n//│ ╟── but it flows into reference with expected type `Annotation`\n//│ ║  l.45: \t@x 2\n//│ ╙──      \t ^\n//│ let x: 1\n//│ 2\n//│ x\n//│   = 1\n//│ res\n//│     = 2\n\n:e\nlet x = 1\n@x\nfun foo(x) = 1\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.65: \tfun foo(x) = 1\n//│ ║        \t    ^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `Annotation`\n//│ ║  l.63: \tlet x = 1\n//│ ╙──      \t        ^\n//│ let x: 1\n//│ fun foo: anything -> 1\n//│ x\n//│   = 1\n\nfun foo(n) =\n  if n > 0.5 then\n    log(join of \"hi \", String(n))\n    foo(div of n,  2)\n    @tailrec foo(n - 1)\n  else ()\n//│ fun foo: Int -> ()\n\nfoo(5)\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ hi 5\n//│ hi 2.5\n//│ hi 1.25\n//│ hi 0.625\n//│ hi 1.5\n//│ hi 0.75\n//│ hi 4\n//│ hi 2\n//│ hi 1\n//│ hi 1\n//│ hi 3\n//│ hi 1.5\n//│ hi 0.75\n//│ hi 2\n//│ hi 1\n//│ hi 1\n\n\n\n// TODO: Tail recursion modulo cons\n// fun foo(n) =\n//   ...\n//   Cons(a, foo(n - 1))\n// ———>\n// fun foo(n) =\n//   ...\n//   foo(n - 1, Cons(a, .))\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ArrayProg.mls",
    "content": ":NewDefs\n\n\n\nfun cast(x) = x\ndeclare fun cast: anything -> nothing\n//│ fun cast: forall 'a. 'a -> 'a\n//│ fun cast: anything -> nothing\n\n\nfun mapi: (Array['a], ('a, Int) -> 'b) -> Array['b]\nfun mapi(xs, f) = cast(xs).map(f)\n//│ fun mapi: (anything, anything) -> nothing\n//│ fun mapi: forall 'a 'b. (Array['a], ('a, Int) -> 'b) -> Array['b]\n\nmapi of [\"a\", \"\", \"bb\"], (x, i) => [i, length of x]\n//│ Array[[Int, Int]]\n//│ res\n//│     = [ [ 0, 1 ], [ 1, 0 ], [ 2, 2 ] ]\n\n\nfun map(xs, f) = mapi(xs, (x, i) => f(x))\n//│ fun map: forall 'a 'b. (Array['a], 'a -> 'b) -> Array['b]\n\nmap of [\"a\", \"\", \"bb\"], x => length of x\n//│ Array[Int]\n//│ res\n//│     = [ 1, 0, 2 ]\n\n\nfun zip: (Array['a], Array['b & ~undefined & Object]) -> Array[['a, 'b]]\nfun zip(xs, ys) = mapi of xs, (x, i) =>\n  if ys.[i] is\n    undefined then error\n    y then [x, y]\n//│ fun zip: forall 'c 'd. (Array['c], Array[Object & 'd & ~()]) -> Array[['c, 'd]]\n//│ fun zip: forall 'a 'b. (Array['a], Array[Object & 'b & ~()]) -> Array[['a, 'b]]\n\n\nzip\n//│ forall 'a 'b. (Array['a], Array[Object & 'b & ~()]) -> Array[['a, 'b]]\n//│ res\n//│     = [Function: zip]\n\n\n\nclass Numbr(n: Int)\nclass Vectr(xs: Array[Numbr | Vectr])\n//│ class Numbr(n: Int)\n//│ class Vectr(xs: Array[Numbr | Vectr])\n\nclass Pair[A, B](a: A, b: B)\n//│ class Pair[A, B](a: A, b: B)\n\n\nfun unbox(x) = if x is\n  Numbr(n) then n\n  Vectr(xs) then map of xs, unbox\n//│ fun unbox: forall 'a. (Numbr | Vectr) -> (Int | 'a)\n//│   where\n//│     'a :> Array[Int | 'a]\n\nfun add(e) =\n  if e is\n    Pair(Numbr(n), Numbr(m)) then Numbr(n + m)\n    Pair(Vectr(xs), Vectr(ys)) then\n      Vectr of map of zip(xs, ys), ([x, y]) => add of Pair of x, y\n    Pair(Vectr(xs),  Numbr(n)) then\n      Vectr of map of xs, x => add of Pair of x, Numbr(n)\n    Pair(Numbr(n), Vectr(xs)) then\n      Vectr of map of xs, x => add of Pair of Numbr(n), x\n//│ fun add: Pair[Numbr | Vectr, Numbr | Vectr] -> (Numbr | Vectr)\n\n\nadd(Pair(Numbr(0), Numbr(1)))\n//│ Numbr | Vectr\n//│ res\n//│     = Numbr {}\n\nadd(Pair(Vectr([]), Vectr([])))\n//│ Numbr | Vectr\n//│ res\n//│     = Vectr {}\n\nlet v = Vectr of [Numbr(10), Numbr(20), Numbr(30)]\n//│ let v: Vectr\n//│ v\n//│   = Vectr {}\n\nunbox(v)\n//│ forall 'a. Int | 'a\n//│   where\n//│     'a :> Array[Int | 'a]\n//│ res\n//│     = [ 10, 20, 30 ]\n\n\nlet res = add of Pair of (Vectr of [Numbr(1), Numbr(2)]), (Vectr of [Numbr(3), v])\n//│ let res: Numbr | Vectr\n//│ res\n//│     = Vectr {}\n\nunbox(res)\n//│ forall 'a. Int | 'a\n//│   where\n//│     'a :> Array[Int | 'a]\n//│ res\n//│     = [ 4, [ 12, 22, 32 ] ]\n\n\nfun add2(e) =\n  if e is\n    Pair(Numbr(n), Numbr(m)) then Numbr(m + m)\n    Pair(Numbr(n), Vectr(n)) then n\n//│ fun add2: Pair[Numbr, Numbr | Vectr] -> (Int | Numbr)\n\nadd2(Pair(Numbr(0), Numbr(1)))\n//│ Int | Numbr\n//│ res\n//│     = Numbr {}\n\n\n\n// * Playing with approximated unions/intersections\n\n\nfun t: ([Numbr,Numbr]|[Vectr,Vectr]) -> Int\n//│ fun t: ([Numbr | Vectr, Numbr | Vectr]) -> Int\n\n\nfun s: (([Numbr,Numbr] -> Int) & ([Vectr,Vectr] -> Int),)\n//│ fun s: (Numbr | Vectr, Numbr | Vectr) -> Int\n\n// FIXME why does the above parse the same as:\n\nfun s: ([Numbr,Numbr] -> Int) & ([Vectr,Vectr] -> Int)\n//│ fun s: (Numbr | Vectr, Numbr | Vectr) -> Int\n\n\ns(Vectr([]),Vectr([]))\n//│ Int\n//│ res\n//│     = <no result>\n//│       s is not implemented\n\n\nmodule A {\n  fun g: (Int -> Int) & (Str -> Str)\n  fun g(x) = x\n}\n// g: (Int | Str) -> (Int & Str) -- under-approx\n// g: (Int & Str) -> (Int | Str) -- over-approx\n//│ module A {\n//│   fun g: Int -> Int & Str -> Str\n//│ }\n\nA.g(0)\n//│ Int | Str\n//│ res\n//│     = 0\n\n\n\n\n// === === === ERROR CASES === === === //\n\n\n:ShowRelativeLineNums\n:AllowTypeErrors\n\n\n:e\ns([Numbr(0),Numbr(0)])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \ts([Numbr(0),Numbr(0)])\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument of type `[[?a, ?b]]` does not match type `[Numbr | Vectr, Numbr | Vectr]`\n//│ ║  l.+1: \ts([Numbr(0),Numbr(0)])\n//│ ║        \t ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.136: \tfun s: ([Numbr,Numbr] -> Int) & ([Vectr,Vectr] -> Int)\n//│ ╙──       \t        ^^^^^^^^^^^^^\n//│ Int | error\n// g <: 0 -> 'a\n\n:e\nfun add(e) =\n  if e is\n    Pair(Numbr(n), Numbr(m))    then 0\n    Pair(Vectr(xs),  Vectr(ys)) then 1\n    Pair(Vectr(xs),  Numbr(n))  then 2\n//│ ╔══[ERROR] when `e` is `Pair`, and\n//│ ║  l.+3: \t    Pair(Numbr(n), Numbr(m))    then 0\n//│ ║        \t    ^^^^\n//│ ╟── the first argument of `Pair` is `Numbr`,\n//│ ║  l.+3: \t    Pair(Numbr(n), Numbr(m))    then 0\n//│ ║        \t         ^^^^^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `Vectr`\n//│ ║  l.+4: \t    Pair(Vectr(xs),  Vectr(ys)) then 1\n//│ ╙──      \t                     ^^^^^\n//│ fun add: Pair[Numbr | Vectr, Numbr] -> (0 | 1 | 2)\n\n:e\nfun add(e) =\n  if e is\n    Pair(Numbr(n), Numbr(m))    then 0\n    Pair(Vectr(xs),  Vectr(ys)) then 1\n//│ ╔══[ERROR] when `e` is `Pair`, and\n//│ ║  l.+3: \t    Pair(Numbr(n), Numbr(m))    then 0\n//│ ║        \t    ^^^^\n//│ ╟── the first argument of `Pair` is `Numbr`,\n//│ ║  l.+3: \t    Pair(Numbr(n), Numbr(m))    then 0\n//│ ║        \t         ^^^^^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `Vectr`\n//│ ║  l.+4: \t    Pair(Vectr(xs),  Vectr(ys)) then 1\n//│ ╙──      \t                     ^^^^^\n//│ ╔══[ERROR] when `e` is `Pair`, and\n//│ ║  l.+3: \t    Pair(Numbr(n), Numbr(m))    then 0\n//│ ║        \t    ^^^^\n//│ ╟── the first argument of `Pair` is `Vectr`,\n//│ ║  l.+4: \t    Pair(Vectr(xs),  Vectr(ys)) then 1\n//│ ║        \t         ^^^^^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `Numbr`\n//│ ║  l.+3: \t    Pair(Numbr(n), Numbr(m))    then 0\n//│ ╙──      \t                   ^^^^^\n//│ fun add: Pair[Numbr | Vectr, nothing] -> (0 | 1)\n\n:e\nadd2(Pair(Vectr(0), Numbr(1)))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tadd2(Pair(Vectr(0), Numbr(1)))\n//│ ║        \t          ^^^^^^^^\n//│ ╟── integer literal of type `0` does not match type `Array[Numbr | Vectr]`\n//│ ║  l.+1: \tadd2(Pair(Vectr(0), Numbr(1)))\n//│ ║        \t                ^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.48: \tclass Vectr(xs: Array[Numbr | Vectr])\n//│ ╙──      \t                ^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.+1: \tadd2(Pair(Vectr(0), Numbr(1)))\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Vectr` is not an instance of type `Numbr`\n//│ ║  l.+1: \tadd2(Pair(Vectr(0), Numbr(1)))\n//│ ║        \t          ^^^^^^^^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.113: \t    Pair(Numbr(n), Numbr(m)) then Numbr(m + m)\n//│ ║         \t         ^^^^^\n//│ ╟── from field selection:\n//│ ║  l.52: \tclass Pair[A, B](a: A, b: B)\n//│ ║        \t                 ^\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.52: \tclass Pair[A, B](a: A, b: B)\n//│ ╙──      \t           ^\n//│ Int | Numbr | error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Ascription.mls",
    "content": ":NewDefs\n\n1: Int\n//│ Int\n//│ res\n//│     = 1\n\n1 : Int\n//│ Int\n//│ res\n//│     = 1\n\n// TODO?\n:pe\n1 : Int : Int\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.15: \t1 : Int : Int\n//│ ╙──      \t    ^^^\n//│ anything\n//│ res\n//│     = 1\n\nfun foo(x: Int) = x + 1\n//│ fun foo: (x: Int) -> Int\n\nfun foo(x : Int) = x + 1\n//│ fun foo: Int -> Int\n\nfoo(123 : Int) : Int\n//│ Int\n//│ res\n//│     = 124\n\n:e\nfoo(123: Int): Int\n//│ ╔══[ERROR] Cannot use named arguments as the function type has untyped arguments\n//│ ║  l.35: \tfoo(123: Int): Int\n//│ ╙──      \t   ^^^^^^^^^^\n//│ Int\n//│ Code generation encountered an error:\n//│   unresolved symbol Int\n\n:e\nfoo(123:Int):Int\n//│ ╔══[ERROR] Cannot use named arguments as the function type has untyped arguments\n//│ ║  l.44: \tfoo(123:Int):Int\n//│ ╙──      \t   ^^^^^^^^^\n//│ Int\n//│ Code generation encountered an error:\n//│   unresolved symbol Int\n\nfun foo(f) =\n  let g = (x => f(x)): forall 'a : 'a -> 'a in g(123)\n//│ fun foo: (??a -> ??a0) -> 123\n\nfun foo(f) =\n  let g: forall 'a : 'a -> 'a = x => f(x) in g(123)\n//│ fun foo: (??a -> ??a0) -> 123\n"
  },
  {
    "path": "shared/src/test/diff/nu/AuxCtors.mls",
    "content": ":NewDefs\n\n\nclass C(val x: Int) { constructor(y: Int) { x = y } }\nnew C(123).x\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ Int\n//│ res\n//│     = 123\n\nclass C(val x: Int) { constructor(y) { x = y } }\nnew C(123).x\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ Int\n//│ res\n//│     = 123\n\nclass C(val x: Int) { constructor(y: Int) { log(y); x = y; log(x) } }\nnew C(123).x\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ Int\n//│ res\n//│     = 123\n//│ // Output\n//│ 123\n//│ 123\n\n:e\nclass C(val x: Int) { constructor(y: Int) { x = y; log(x); x = y + 1; log(x) } }\nnew C(123).x\n//│ ╔══[ERROR] Class parameter 'x' was already set\n//│ ║  l.35: \tclass C(val x: Int) { constructor(y: Int) { x = y; log(x); x = y + 1; log(x) } }\n//│ ╙──      \t                                                           ^\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ Int\n//│ res\n//│     = 124\n//│ // Output\n//│ 123\n//│ 124\n\n:e\nclass C(val x: Int) { constructor(y: Int) { log(x); x = y } }\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.51: \tclass C(val x: Int) { constructor(y: Int) { log(x); x = y } }\n//│ ╙──      \t                                                ^\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\nclass C(val x: Int) { constructor(y: Str) { x = y } }\n//│ ╔══[ERROR] Type mismatch in auxiliary class constructor:\n//│ ║  l.62: \tclass C(val x: Int) { constructor(y: Str) { x = y } }\n//│ ║        \t                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Str` is not an instance of type `Int`\n//│ ║  l.62: \tclass C(val x: Int) { constructor(y: Str) { x = y } }\n//│ ║        \t                                     ^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.62: \tclass C(val x: Int) { constructor(y: Str) { x = y } }\n//│ ║        \t                                                ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.62: \tclass C(val x: Int) { constructor(y: Str) { x = y } }\n//│ ╙──      \t               ^^^\n//│ class C(x: Int) {\n//│   constructor(y: Str)\n//│ }\n\n:e\nclass C(val x: Int) { constructor(y: Int) { z = y } }\n//│ ╔══[ERROR] Unknown class parameter 'z'\n//│ ║  l.80: \tclass C(val x: Int) { constructor(y: Int) { z = y } }\n//│ ╙──      \t                                            ^\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n//│ Syntax error:\n//│   Private field '#z' must be declared in an enclosing class\n\n:e\nclass C(val x: Int) { constructor(val y: Int) { x = y } }\n//│ ╔══[ERROR] Cannot use `val` in constructor parameters\n//│ ║  l.91: \tclass C(val x: Int) { constructor(val y: Int) { x = y } }\n//│ ╙──      \t                                      ^\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n\n:e\nclass C(val x: Int) { constructor(val y) { x = y } }\n//│ ╔══[ERROR] Cannot use `val` in constructor parameters\n//│ ║  l.100: \tclass C(val x: Int) { constructor(val y) { x = y } }\n//│ ╙──       \t                                      ^\n//│ class C(x: Int) {\n//│   constructor(y: Int)\n//│ }\n\n:e\nclass C(val x: Int) { constructor(2 + 2) { x = 0 } }\n//│ ╔══[ERROR] Unsupported constructor parameter shape\n//│ ║  l.109: \tclass C(val x: Int) { constructor(2 + 2) { x = 0 } }\n//│ ╙──       \t                                  ^^^^^\n//│ class C(x: Int) {\n//│   constructor(<error>: error)\n//│ }\n//│ Code generation encountered an error:\n//│   Unexpected constructor parameters in C.\n\n\nclass C(val x: Int, y: Int) {\n  constructor(z: Int) { x = z; y = z }\n  log([x, y])\n}\n//│ class C(x: Int, y: Int) {\n//│   constructor(z: Int)\n//│ }\n\n:e\nC(11)\n//│ ╔══[ERROR] Construction of class with auxiliary constructor should use the `new` keyword\n//│ ║  l.129: \tC(11)\n//│ ╙──       \t^\n//│ C\n//│ res\n//│     = C {}\n//│ // Output\n//│ [ 11, 11 ]\n\n:e\nnew C(1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.140: \tnew C(1, 2)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── tuple literal of type `[1, 2]` does not match type `[z: Int]`\n//│ ║  l.140: \tnew C(1, 2)\n//│ ╙──       \t     ^^^^^^\n//│ C | error\n//│ res\n//│     = C {}\n//│ // Output\n//│ [ 1, 1 ]\n\nnew C(11)\n//│ C\n//│ res\n//│     = C {}\n//│ // Output\n//│ [ 11, 11 ]\n\n:e\nnew C(1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.161: \tnew C(1, 2)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── tuple literal of type `[1, 2]` does not match type `[z: Int]`\n//│ ║  l.161: \tnew C(1, 2)\n//│ ╙──       \t     ^^^^^^\n//│ C | error\n//│ res\n//│     = C {}\n//│ // Output\n//│ [ 1, 1 ]\n\n:pe\n:w\nclass C { constructor(x: Int); constructor(y: Int) }\n//│ ╔══[PARSE ERROR] A class may have at most one explicit constructor\n//│ ║  l.176: \tclass C { constructor(x: Int); constructor(y: Int) }\n//│ ╙──       \t^^^^^\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.176: \tclass C { constructor(x: Int); constructor(y: Int) }\n//│ ╙──       \t                             ^\n//│ class C {\n//│   constructor(x: Int)\n//│ }\n\n\n:w // * FIXME\nclass Foo { constructor(x: Int){}; val y = 2 }\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.189: \tclass Foo { constructor(x: Int){}; val y = 2 }\n//│ ╙──       \t                                 ^\n//│ class Foo {\n//│   constructor(x: Int)\n//│   val y: 2\n//│ }\n\n:w\nclass Foo { constructor(x: Int){}; val y = 2 }\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.199: \tclass Foo { constructor(x: Int){}; val y = 2 }\n//│ ╙──       \t                                 ^\n//│ class Foo {\n//│   constructor(x: Int)\n//│   val y: 2\n//│ }\n\nclass Foo { constructor(x: Int){} val y = 2 }\n//│ class Foo {\n//│   constructor(x: Int)\n//│   val y: 2\n//│ }\n\nclass Foo {\n  constructor(x: Int){}\n  val y = 2\n}\n//│ class Foo {\n//│   constructor(x: Int)\n//│   val y: 2\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadAliases.mls",
    "content": ":NewDefs\n\n\n// TODO check cyclicity\n// :e\ntype A = A\n//│ type A = A\n\n// TODO check cyclicity\n// :e\ntype A = A | Int\n//│ type A = Int | A\n\n// TODO check regularity\n// :e\ntype Foo[A] = { x: A, y: Foo[[A, A]] }\n//│ type Foo[A] = {x: A, y: Foo[[A, A]]}\n\n\n// TODO support abstract types\n:e\ntype Test\n//│ ╔══[ERROR] Type alias definition requires a right-hand side\n//│ ║  l.22: \ttype Test\n//│ ╙──      \t^^^^^^^^^\n//│ type Test = error\n\n:e\ntype Test(n: Int) = n\n//│ ╔══[ERROR] Type alias definitions cannot have value parameters\n//│ ║  l.29: \ttype Test(n: Int) = n\n//│ ╙──      \t         ^^^^^^^^\n//│ ╔══[ERROR] type identifier not found: n\n//│ ║  l.29: \ttype Test(n: Int) = n\n//│ ╙──      \t                    ^\n//│ type Test = error\n\nclass Base\n//│ class Base {\n//│   constructor()\n//│ }\n\n:pe\n:e\ntype Test: Base\n//│ ╔══[PARSE ERROR] Expected end of input; found ':' instead\n//│ ║  l.45: \ttype Test: Base\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type alias definition requires a right-hand side\n//│ ║  l.45: \ttype Test: Base\n//│ ╙──      \t^^^^^^^^^\n//│ type Test = error\n\n:pe\n:e\ntype Test: Base = Int\n//│ ╔══[PARSE ERROR] Expected end of input; found ':' instead\n//│ ║  l.56: \ttype Test: Base = Int\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type alias definition requires a right-hand side\n//│ ║  l.56: \ttype Test: Base = Int\n//│ ╙──      \t^^^^^^^^^\n//│ type Test = error\n\n:e\ntype Test extends Base\n//│ ╔══[ERROR] Type alias definitions cannot extend parents\n//│ ║  l.66: \ttype Test extends Base\n//│ ╙──      \t                  ^^^^\n//│ ╔══[ERROR] Type alias definition requires a right-hand side\n//│ ║  l.66: \ttype Test extends Base\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^\n//│ type Test = error\n\n:pe\n:e\ntype Test extends Base = Int\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' instead\n//│ ║  l.77: \ttype Test extends Base = Int\n//│ ╙──      \t                       ^\n//│ ╔══[ERROR] Type alias definitions cannot extend parents\n//│ ║  l.77: \ttype Test extends Base = Int\n//│ ╙──      \t                  ^^^^\n//│ ╔══[ERROR] Type alias definition requires a right-hand side\n//│ ║  l.77: \ttype Test extends Base = Int\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^\n//│ type Test = error\n\n:e\ntype Test = Int extends Base\n//│ ╔══[ERROR] Type alias definitions cannot extend parents\n//│ ║  l.90: \ttype Test = Int extends Base\n//│ ╙──      \t                        ^^^^\n//│ type Test = Int\n\n\n:pe\ntype Poly[mut A] = A\n//│ ╔══[PARSE ERROR] Unexpected 'mut' keyword here\n//│ ║  l.98: \ttype Poly[mut A] = A\n//│ ╙──      \t          ^^^\n//│ type Poly = A\n\n:pe\ntype Poly[#A] = A\n//│ ╔══[PARSE ERROR] Unexpected '#' here\n//│ ║  l.105: \ttype Poly[#A] = A\n//│ ╙──       \t          ^\n//│ type Poly = A\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadBlocks.mls",
    "content": ":NewDefs\n\n\n:e\nfun test =\n  fun lol = log(\"ok\")\n  [lol, lol]\n//│ ╔══[ERROR] Cannot use `val` or `fun` in local block; use `let` instead.\n//│ ║  l.6: \t  fun lol = log(\"ok\")\n//│ ╙──     \t  ^^^^^^^^^^^^^^^^^^^\n//│ fun test: [(), ()]\n\ntest\n//│ [(), ()]\n//│ res\n//│     = [ undefined, undefined ]\n//│ // Output\n//│ ok\n\n:e\nfun test =\n  fun lol = log(\"ok\")\n  []\n//│ ╔══[ERROR] Cannot use `val` or `fun` in local block; use `let` instead.\n//│ ║  l.22: \t  fun lol = log(\"ok\")\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^\n//│ fun test: []\n\ntest\n//│ []\n//│ res\n//│     = []\n//│ // Output\n//│ ok\n\nfun test =\n  let a = 0\n  a\n//│ fun test: 0\n\n:e\nfun test =\n  fun a = b\n  fun b = 1\n  a\n//│ ╔══[ERROR] Cannot use `val` or `fun` in local block; use `let` instead.\n//│ ║  l.43: \t  fun a = b\n//│ ╙──      \t  ^^^^^^^^^\n//│ ╔══[ERROR] Cannot use `val` or `fun` in local block; use `let` instead.\n//│ ║  l.44: \t  fun b = 1\n//│ ╙──      \t  ^^^^^^^^^\n//│ fun test: 1\n\n// TODO[init-check] reject\nfun test =\n  let a = b\n  let b = 1\n  a\n//│ fun test: 1\n\n:re\ntest\n//│ 1\n//│ res\n//│ Runtime error:\n//│   ReferenceError: Cannot access 'b' before initialization\n\n:js\nfun test =\n  let a() = b\n  let b = 1\n  a()\n//│ fun test: 1\n//│ // Prelude\n//│ class TypingUnit8 {}\n//│ const typing_unit8 = new TypingUnit8;\n//│ // Query 1\n//│ globalThis.test5 = function test5() {\n//│   return ((() => {\n//│     let a = () => b;\n//│     let b = 1;\n//│     return a();\n//│   })());\n//│ };\n//│ // End of generated code\n\ntest\n//│ 1\n//│ res\n//│     = 1\n\n\n// * OK\nfun test =\n  class Foo(x: Int) { fun y = x + 1 }\n  Foo(1).y\n//│ fun test: Int\n\n// * MAYBE OK\n:ge // TODO accept?\nfun test =\n  let r() = Foo(1).y\n  class Foo(x: Int) { fun y = x + 1 }\n  r()\n//│ fun test: Int\n//│ Code generation encountered an error:\n//│   unresolved symbol Foo\n\n// * NOT OK\n:ge // :e // TODO[init-check] reject\nfun test =\n  let r = Foo(1).y\n  class Foo(x: Int) { fun y = x + 1 }\n  r\n//│ fun test: Int\n//│ Code generation encountered an error:\n//│   unresolved symbol Foo\n\n:re\ntest\n//│ Int\n//│ res\n//│ Runtime error:\n//│   ReferenceError: test8 is not defined\n\n\n:pe\n:ge\nfun test = {\n  fun a = 1\n}\n//│ ╔══[PARSE ERROR] Unexpected 'fun' keyword in expression position\n//│ ║  l.130: \t  fun a = 1\n//│ ╙──       \t  ^^^\n//│ ╔══[PARSE ERROR] Unexpected '=' here\n//│ ║  l.130: \t  fun a = 1\n//│ ╙──       \t        ^\n//│ fun test: {a: () -> 1}\n//│ Code generation encountered an error:\n//│   unresolved symbol a\n\n:pe\n:e\nfun test = {\n  val res = a + 1\n  fun a = 123\n}.res\n//│ ╔══[PARSE ERROR] Unexpected '=' here\n//│ ║  l.145: \t  val res = a + 1\n//│ ╙──       \t          ^\n//│ ╔══[ERROR] identifier not found: res\n//│ ║  l.145: \t  val res = a + 1\n//│ ╙──       \t      ^^^\n//│ fun test: error\n\n:pe // TODO support\n:e\nfun test = (new {\n  val res = a + 1\n  fun a = 123\n}).res\n//│ ╔══[PARSE ERROR] Unexpected '=' here\n//│ ║  l.159: \t  val res = a + 1\n//│ ╙──       \t          ^\n//│ ╔══[ERROR] type identifier not found: res\n//│ ║  l.159: \t  val res = a + 1\n//│ ╙──       \t      ^^^\n//│ ╔══[ERROR] Unexpected type `{res: error}` after `new` keyword\n//│ ║  l.158: \tfun test = (new {\n//│ ║         \t                ^\n//│ ║  l.159: \t  val res = a + 1\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ║  l.160: \t  fun a = 123\n//│ ║         \t^^^^^^^^^^^^^\n//│ ║  l.161: \t}).res\n//│ ╙──       \t^\n//│ fun test: error\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: Bra(true,Rcd(List((Var(res),Fld(g,Var(res))))))\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadClassInherit.mls",
    "content": ":NewDefs\n\n\nclass C1(x: Int)\n//│ class C1(x: Int)\n\n:e\nclass C2(x: Int) extends C1(y) {\n  val y = x\n}\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.8: \tclass C2(x: Int) extends C1(y) {\n//│ ╙──     \t                            ^\n//│ class C2(x: Int) extends C1 {\n//│   val y: Int\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol y\n\n:e\nabstract class C2 extends C1(y) {\n  val y: Int\n}\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.21: \tabstract class C2 extends C1(y) {\n//│ ╙──      \t                             ^\n//│ abstract class C2 extends C1 {\n//│   val y: Int\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol y\n\n:e\nabstract class C2 extends C1(this.y) {\n  val y: Int\n}\n//│ ╔══[ERROR] identifier not found: this\n//│ ║  l.34: \tabstract class C2 extends C1(this.y) {\n//│ ╙──      \t                             ^^^^\n//│ abstract class C2 extends C1 {\n//│   val y: Int\n//│ }\n\n\nclass C1(x: C1)\n//│ class C1(x: C1)\n\n:e\nclass C2 extends C1(this)\n//│ ╔══[ERROR] identifier not found: this\n//│ ║  l.49: \tclass C2 extends C1(this)\n//│ ╙──      \t                    ^^^^\n//│ class C2 extends C1 {\n//│   constructor()\n//│ }\n\n\nclass Foo { virtual fun x: Int = 1 }\n//│ class Foo {\n//│   constructor()\n//│   fun x: Int\n//│ }\n\n:e\nclass Bar extends Foo { fun x = false }\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.65: \tclass Bar extends Foo { fun x = false }\n//│ ║        \t                            ^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of `Int`\n//│ ║  l.65: \tclass Bar extends Foo { fun x = false }\n//│ ║        \t                                ^^^^^\n//│ ╟── but it flows into definition of method x with expected type `Int`\n//│ ║  l.65: \tclass Bar extends Foo { fun x = false }\n//│ ║        \t                            ^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ║        \t                           ^^^\n//│ ╟── from definition of method x:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ╙──      \t                        ^^^^^^^^^^\n//│ class Bar extends Foo {\n//│   constructor()\n//│   fun x: false\n//│ }\n\n:e\nclass Bar extends Foo {\n  fun x: Bool\n  fun x = false\n}\n//│ ╔══[ERROR] Type mismatch in signature of member `x`:\n//│ ║  l.88: \t  fun x: Bool\n//│ ║        \t      ^^^^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ║  l.88: \t  fun x: Bool\n//│ ║        \t         ^^^^\n//│ ╟── but it flows into signature of member `x` with expected type `Int`\n//│ ║  l.88: \t  fun x: Bool\n//│ ║        \t      ^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ║        \t                           ^^^\n//│ ╟── from definition of method x:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ╙──      \t                        ^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in signature of member `x`:\n//│ ║  l.88: \t  fun x: Bool\n//│ ║        \t      ^^^^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ║  l.88: \t  fun x: Bool\n//│ ║        \t         ^^^^\n//│ ╟── but it flows into signature of member `x` with expected type `Int`\n//│ ║  l.88: \t  fun x: Bool\n//│ ║        \t      ^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ║        \t                           ^^^\n//│ ╟── from definition of method x:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ╙──      \t                        ^^^^^^^^^^\n//│ class Bar extends Foo {\n//│   constructor()\n//│   fun x: Bool\n//│ }\n\nmixin M { fun x = false }\n//│ mixin M() {\n//│   fun x: false\n//│ }\n\n:e\nclass Bar extends Foo, M\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.126: \tmixin M { fun x = false }\n//│ ║         \t              ^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of `Int`\n//│ ║  l.126: \tmixin M { fun x = false }\n//│ ║         \t                  ^^^^^\n//│ ╟── but it flows into definition of method x with expected type `Int`\n//│ ║  l.126: \tmixin M { fun x = false }\n//│ ║         \t              ^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ║        \t                           ^^^\n//│ ╟── from definition of method x:\n//│ ║  l.58: \tclass Foo { virtual fun x: Int = 1 }\n//│ ╙──      \t                        ^^^^^^^^^^\n//│ class Bar extends Foo {\n//│   constructor()\n//│   fun x: false\n//│ }\n\n\n\nclass A { class X { fun f = 1 } }\ntrait B { class X { fun g = 1 } }\n//│ class A {\n//│   constructor()\n//│   class X {\n//│     constructor()\n//│     fun f: 1\n//│   }\n//│ }\n//│ trait B {\n//│   class X {\n//│     constructor()\n//│     fun g: 1\n//│   }\n//│ }\n\n:e\nclass C extends A, B\n//│ ╔══[ERROR] Class member 'X' cannot override class member of the same name declared in parent\n//│ ║  l.172: \tclass C extends A, B\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.156: \ttrait B { class X { fun g = 1 } }\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Intersection of class member and class members currently unsupported\n//│ ║  l.172: \tclass C extends A, B\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── The class member is defined here:\n//│ ║  l.155: \tclass A { class X { fun f = 1 } }\n//│ ║         \t          ^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── The class member is defined here:\n//│ ║  l.156: \ttrait B { class X { fun g = 1 } }\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^^\n//│ class C extends A, B {\n//│   constructor()\n//│   class X {\n//│     constructor()\n//│     fun f: 1\n//│   }\n//│ }\n\n:e\nclass C extends A {\n  class X { fun g = 1 }\n}\n//│ ╔══[ERROR] Class member 'X' cannot override class member of the same name declared in parent\n//│ ║  l.197: \tclass C extends A {\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.198: \t  class X { fun g = 1 }\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.199: \t}\n//│ ║         \t^\n//│ ╟── Originally declared here:\n//│ ║  l.155: \tclass A { class X { fun f = 1 } }\n//│ ╙──       \t          ^^^^^^^^^^^^^^^^^^^^^\n//│ class C extends A {\n//│   constructor()\n//│   class X {\n//│     constructor()\n//│     fun g: 1\n//│   }\n//│ }\n\n\n\n:e\nclass Foo2 extends Foo2\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.221: \tclass Foo2 extends Foo2\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ class Foo2 extends Foo2 {\n//│   constructor()\n//│ }\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadClassSignatures.mls",
    "content": ":NewDefs\n\n\nabstract class Foo(): Foo\n//│ abstract class Foo(): Foo\n\nmodule Bar extends Foo\n//│ module Bar extends Foo\n\nabstract class Baz(): Baz | Baz\n//│ abstract class Baz(): Baz\n\n\nabstract class Foo(): Int\n//│ abstract class Foo(): Int\n\nfun foo(x: Foo) = x : Int\n//│ fun foo: (x: Foo) -> Int\n\n:e\nlet f = Foo() : Foo\n//│ ╔══[ERROR] Class Foo is abstract and cannot be instantiated\n//│ ║  l.21: \tlet f = Foo() : Foo\n//│ ╙──      \t        ^^^\n//│ let f: Foo\n//│ f\n//│   = Foo {}\n\nf + 1\n//│ Int\n//│ res\n//│     = '[object Object]1'\n\n:e\nFoo() + 1\n//│ ╔══[ERROR] Class Foo is abstract and cannot be instantiated\n//│ ║  l.35: \tFoo() + 1\n//│ ╙──      \t^^^\n//│ Int\n//│ res\n//│     = '[object Object]1'\n\n:e\n(Foo() : Foo) + 1\n//│ ╔══[ERROR] Class Foo is abstract and cannot be instantiated\n//│ ║  l.44: \t(Foo() : Foo) + 1\n//│ ╙──      \t ^^^\n//│ Int\n//│ res\n//│     = '[object Object]1'\n\n\n:w\n:e\nmodule Foo: Int\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract module definitions\n//│ ║  l.55: \tmodule Foo: Int\n//│ ║        \t            ^^^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.55: \tmodule Foo: Int\n//│ ║        \t^^^^^^^^^^\n//│ ╟── expression of type `#Foo` is not an instance of type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.55: \tmodule Foo: Int\n//│ ╙──      \t            ^^^\n//│ module Foo: Int\n\nFoo + 1\n//│ Int\n//│ res\n//│     = '[object Object]1'\n\n\n:w\nclass Foo(): {}\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract class definitions\n//│ ║  l.76: \tclass Foo(): {}\n//│ ║        \t             ^^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ class Foo()\n\n:w\nclass Foo(): {} {\n  fun x = 0\n}\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract class definitions\n//│ ║  l.84: \tclass Foo(): {} {\n//│ ║        \t             ^^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ class Foo() {\n//│   fun x: 0\n//│ }\n\n:w\n:e\nclass Foo(): { x: Int } {\n  fun x = 0\n}\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract class definitions\n//│ ║  l.97: \tclass Foo(): { x: Int } {\n//│ ║        \t             ^^^^^^^^^^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.97: \tclass Foo(): { x: Int } {\n//│ ╙──      \t               ^\n//│ class Foo(): {x: Int} {\n//│   fun x: 0\n//│ }\n\nabstract class Foo(): { x: Int } {\n  fun x = 0\n}\n//│ abstract class Foo(): {x: Int} {\n//│   fun x: 0\n//│ }\n\n:e\nmodule FooM extends Foo\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.111: \tabstract class Foo(): { x: Int } {\n//│ ╙──       \t                        ^\n//│ module FooM extends Foo {\n//│   fun x: 0\n//│ }\n\nabstract class Foo(): { x: Int } {\n  fun x: Int\n  fun x = 0\n}\n//│ abstract class Foo(): {x: Int} {\n//│   fun x: Int\n//│ }\n\n:e // TODO should work?\nmodule FooM extends Foo\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.127: \tabstract class Foo(): { x: Int } {\n//│ ╙──       \t                        ^\n//│ module FooM extends Foo {\n//│   fun x: Int\n//│ }\n\n:w\n:e\nclass Foo(): { x: 'FigureItOut } {\n  fun x: Int\n  fun x = 0\n}\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract class definitions\n//│ ║  l.146: \tclass Foo(): { x: 'FigureItOut } {\n//│ ║         \t             ^^^^^^^^^^^^^^^^^^^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ ╔══[ERROR] Type error in type declaration\n//│ ║  l.146: \tclass Foo(): { x: 'FigureItOut } {\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.147: \t  fun x: Int\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.148: \t  fun x = 0\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.149: \t}\n//│ ║         \t^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.147: \t  fun x: Int\n//│ ╙──       \t         ^^^\n//│ class Foo(): {x: ??FigureItOut} {\n//│   fun x: Int\n//│ }\n\n:e\nnot(Foo().x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.171: \tnot(Foo().x)\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── field selection of type `Int & ??FigureItOut` is not an instance of type `Bool`\n//│ ║  l.171: \tnot(Foo().x)\n//│ ╙──       \t    ^^^^^^^\n//│ error | false | true\n//│ res\n//│     = true\n\n(f: Foo) => f.x\n//│ (f: Foo) -> (Int & ??FigureItOut)\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadClasses.mls",
    "content": ":NewDefs\n\n\n\nmixin M0(x: Int)\n//│ mixin M0(x: Int)\n\n:e\nclass C0 extends M0\n//│ ╔══[ERROR] mixin M0 expects 1 parameter(s); got 0\n//│ ║  l.9: \tclass C0 extends M0\n//│ ╙──     \t                 ^^\n//│ class C0 {\n//│   constructor()\n//│ }\n\n:e\nclass C0 extends M0(1, 2)\n//│ ╔══[ERROR] mixin M0 expects 1 parameter(s); got 2\n//│ ║  l.18: \tclass C0 extends M0(1, 2)\n//│ ╙──      \t                 ^^^^^^^\n//│ class C0 {\n//│   constructor()\n//│ }\n\n:e\nclass C0 extends M0(true)\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.27: \tclass C0 extends M0(true)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Int`\n//│ ║  l.27: \tclass C0 extends M0(true)\n//│ ║        \t                    ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.5: \tmixin M0(x: Int)\n//│ ╙──     \t            ^^^\n//│ class C0 {\n//│   constructor()\n//│ }\n\n\nmodule Foo {\n  fun foo = 0\n  fun bar = foo\n}\n[Foo.foo, Foo.bar]\n//│ module Foo {\n//│   fun bar: 0\n//│   fun foo: 0\n//│ }\n//│ [0, 0]\n//│ res\n//│     = [ 0, 0 ]\n\n// * FIXME add initialization checking for non-lazy fields\nmodule Foo {\n  val foo = tmp\n  fun bar = foo\n  let tmp = 0\n}\n[Foo.foo, Foo.bar]\n//│ module Foo {\n//│   fun bar: 0\n//│   val foo: 0\n//│   let tmp: 0\n//│ }\n//│ [0, 0]\n//│ res\n//│     = [ undefined, undefined ]\n\n\nmodule Bar {\n  fun hello = 0\n  type I = Int\n}\n//│ module Bar {\n//│   type I = Int\n//│   fun hello: 0\n//│ }\n\n:e\nhello\n//│ ╔══[ERROR] identifier not found: hello\n//│ ║  l.82: \thello\n//│ ╙──      \t^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol hello\n\n:e\n1 : I\n//│ ╔══[ERROR] type identifier not found: I\n//│ ║  l.91: \t1 : I\n//│ ╙──      \t    ^\n//│ error\n//│ res\n//│     = 1\n\n\n:e\n:w\nclass Foo[A] { 42: A }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.102: \tclass Foo[A] { 42: A }\n//│ ║         \t               ^^\n//│ ╟── integer literal of type `42` does not match type `A`\n//│ ╟── Note: constraint arises from type parameter:\n//│ ║  l.102: \tclass Foo[A] { 42: A }\n//│ ╙──       \t          ^\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in type ascription:\n//│ ║  l.102: \tclass Foo[A] { 42: A }\n//│ ║         \t               ^^\n//│ ╟── expression in statement position of type `A` does not match type `()`\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.102: \tclass Foo[A] { 42: A }\n//│ ╙──       \t          ^\n//│ class Foo[A] {\n//│   constructor()\n//│ }\n\n\n:e\nclass C1 { fun oops = this.x }\n//│ ╔══[ERROR] Type `#C1` does not contain member `x`\n//│ ║  l.125: \tclass C1 { fun oops = this.x }\n//│ ╙──       \t                          ^^\n//│ class C1 {\n//│   constructor()\n//│   fun oops: error\n//│ }\n\n\n:e\nclass C { fun x: Int }\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C`\n//│ ║  l.136: \tclass C { fun x: Int }\n//│ ║         \t      ^\n//│ ╟── Declared here:\n//│ ║  l.136: \tclass C { fun x: Int }\n//│ ╙──       \t          ^^^^^^^^^^\n//│ class C {\n//│   constructor()\n//│   fun x: Int\n//│ }\n\n:e\nclass C { val x: Int }\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C`\n//│ ║  l.149: \tclass C { val x: Int }\n//│ ║         \t      ^\n//│ ╟── Declared here:\n//│ ║  l.149: \tclass C { val x: Int }\n//│ ╙──       \t          ^^^^^^^^^^\n//│ class C {\n//│   constructor()\n//│   val x: Int\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadFieldInit.mls",
    "content": ":NewDefs\n\n\n\n:js\nmodule A {\n  val x = y\n  val y = x\n}\n//│ module A {\n//│   val x: nothing\n//│   val y: nothing\n//│ }\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         #y;\n//│         get y() { return this.#y; }\n//│         constructor() {\n//│           const qualifier1 = this;\n//│           this.#x = qualifier1.y;\n//│           const x = this.#x;\n//│           this.#y = x;\n//│           const y = this.#y;\n//│         }\n//│       }\n//│       this.#A = new A();\n//│       this.#A.class = A;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit = new TypingUnit;\n//│ globalThis.A = typing_unit.A;\n//│ // End of generated code\n\n[A.x, A.y]\n//│ [nothing, nothing]\n//│ res\n//│     = [ undefined, undefined ]\n\n\n:js\nmodule A {\n  val x = y\n  val y = 1\n}\n//│ module A {\n//│   val x: 1\n//│   val y: 1\n//│ }\n//│ // Prelude\n//│ class TypingUnit2 {\n//│   #A;\n//│   constructor() {\n//│   }\n//│   get A() {\n//│     const qualifier = this;\n//│     if (this.#A === undefined) {\n//│       class A {\n//│         #x;\n//│         get x() { return this.#x; }\n//│         #y;\n//│         get y() { return this.#y; }\n//│         constructor() {\n//│           const qualifier1 = this;\n//│           this.#x = qualifier1.y;\n//│           const x = this.#x;\n//│           this.#y = 1;\n//│           const y = this.#y;\n//│         }\n//│       }\n//│       this.#A = new A();\n//│       this.#A.class = A;\n//│     }\n//│     return this.#A;\n//│   }\n//│ }\n//│ const typing_unit2 = new TypingUnit2;\n//│ globalThis.A = typing_unit2.A;\n//│ // End of generated code\n\n[A.x, A.y]\n//│ [1, 1]\n//│ res\n//│     = [ undefined, 1 ]\n\n\n\n:e\nclass B(x: Int, y: Int) {\n  constructor() {\n    x = y\n    y = x\n  }\n}\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.102: \t    x = y\n//│ ╙──       \t        ^\n//│ class B(x: Int, y: Int) {\n//│   constructor()\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol y\n\n:e\nclass B(x: Int, y: Int) {\n  constructor() {\n    x = y\n    y = 1\n  }\n}\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.118: \t    x = y\n//│ ╙──       \t        ^\n//│ class B(x: Int, y: Int) {\n//│   constructor()\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol y\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadLets.mls",
    "content": ":NewDefs\n\n\nmodule M {\n  let x = 0\n}\n//│ module M {\n//│   let x: 0\n//│ }\n\n:e\nM.x\n//│ ╔══[ERROR] Let binding 'x' cannot tbe accessed as a field\n//│ ║  l.12: \tM.x\n//│ ║        \t ^^\n//│ ╟── Use a `val` declaration to make it a field\n//│ ║  l.5: \t  let x = 0\n//│ ╙──     \t      ^^^^^\n//│ 0 | error\n//│ res\n//│     = undefined\n\n\nabstract class Base { val x: Int }\n//│ abstract class Base {\n//│   val x: Int\n//│ }\n\n:e\nclass Der extends Base { let x = true }\n//│ ╔══[ERROR] Cannot implement value member 'x' with a let binding\n//│ ║  l.30: \tclass Der extends Base { let x = true }\n//│ ║        \t                             ^^^^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.24: \tabstract class Base { val x: Int }\n//│ ╙──      \t                      ^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in definition of let binding x:\n//│ ║  l.30: \tclass Der extends Base { let x = true }\n//│ ║        \t                             ^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Int`\n//│ ║  l.30: \tclass Der extends Base { let x = true }\n//│ ║        \t                                 ^^^^\n//│ ╟── but it flows into definition of let binding x with expected type `Int`\n//│ ║  l.30: \tclass Der extends Base { let x = true }\n//│ ║        \t                             ^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.24: \tabstract class Base { val x: Int }\n//│ ║        \t                             ^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.24: \tabstract class Base { val x: Int }\n//│ ╙──      \t                          ^^^^^^\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `Der`\n//│ ║  l.30: \tclass Der extends Base { let x = true }\n//│ ║        \t      ^^^\n//│ ╟── Declared here:\n//│ ║  l.24: \tabstract class Base { val x: Int }\n//│ ║        \t                      ^^^^^^^^^^\n//│ ╟── Note: value member `x` is private and cannot be used as a valid implementation\n//│ ║  l.30: \tclass Der extends Base { let x = true }\n//│ ╙──      \t                             ^^^^^^^^\n//│ class Der extends Base {\n//│   constructor()\n//│   let x: true\n//│ }\n\n:e\nmodule Der extends Base { let x = 0 }\n//│ ╔══[ERROR] Cannot implement value member 'x' with a let binding\n//│ ║  l.67: \tmodule Der extends Base { let x = 0 }\n//│ ║        \t                              ^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.24: \tabstract class Base { val x: Int }\n//│ ╙──      \t                      ^^^^^^^^^^\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `Der`\n//│ ║  l.67: \tmodule Der extends Base { let x = 0 }\n//│ ║        \t       ^^^\n//│ ╟── Declared here:\n//│ ║  l.24: \tabstract class Base { val x: Int }\n//│ ║        \t                      ^^^^^^^^^^\n//│ ╟── Note: value member `x` is private and cannot be used as a valid implementation\n//│ ║  l.67: \tmodule Der extends Base { let x = 0 }\n//│ ╙──      \t                              ^^^^^\n//│ module Der extends Base {\n//│   let x: 0\n//│ }\n\n:e\nDer.x\n//│ ╔══[ERROR] Let binding 'x' cannot tbe accessed as a field\n//│ ║  l.88: \tDer.x\n//│ ║        \t   ^^\n//│ ╟── Use a `val` declaration to make it a field\n//│ ║  l.67: \tmodule Der extends Base { let x = 0 }\n//│ ╙──      \t                              ^^^^^\n//│ 0 | error\n//│ res\n//│     = undefined\n\n(Der : Base).x\n//│ Int\n//│ res\n//│     = undefined\n\n\n\nmodule M {\n  val x = 1\n  fun foo = x\n  // foo, ()\n}\nM.x\nM.foo\n//│ module M {\n//│   fun foo: 1\n//│   val x: 1\n//│ }\n//│ 1\n//│ res\n//│     = 1\n//│ res\n//│     = 1\n\n// * TODO init checking\nmodule M {\n  val x = foo\n  fun foo = x\n  // foo, ()\n}\nM.x\nM.foo\n//│ module M {\n//│   fun foo: nothing\n//│   val x: nothing\n//│ }\n//│ nothing\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n\nmodule M {\n  let x = foo\n  fun foo = 1\n  // foo, ()\n}\nM.foo\n//│ module M {\n//│   fun foo: 1\n//│   let x: 1\n//│ }\n//│ 1\n//│ res\n//│     = 1\n\n// * TODO init checking\nmodule M {\n  let x = foo\n  fun foo = x\n  // foo, ()\n}\nM.foo\n//│ module M {\n//│   fun foo: nothing\n//│   let x: nothing\n//│ }\n//│ nothing\n//│ res\n//│     = undefined\n\n:e\nM.x\n//│ ╔══[ERROR] Let binding 'x' cannot tbe accessed as a field\n//│ ║  l.171: \tM.x\n//│ ║         \t ^^\n//│ ╟── Use a `val` declaration to make it a field\n//│ ║  l.157: \t  let x = foo\n//│ ╙──       \t      ^^^^^^^\n//│ error\n//│ res\n//│     = undefined\n\nmodule M {\n  let x = 1\n  let y = foo\n  fun foo = x\n  fun bar = y\n  // foo, ()\n}\nM.foo\nM.bar\n//│ module M {\n//│   fun bar: 1\n//│   fun foo: 1\n//│   let x: 1\n//│   let y: 1\n//│ }\n//│ 1\n//│ res\n//│     = 1\n//│ res\n//│     = 1\n\n// * TODO init checking\nmodule M {\n  let y = foo\n  let x = 1\n  fun foo = x\n  fun bar = y\n  // foo, ()\n}\nM.foo\nM.bar\n//│ module M {\n//│   fun bar: 1\n//│   fun foo: 1\n//│   let x: 1\n//│   let y: 1\n//│ }\n//│ 1\n//│ res\n//│     = 1\n//│ res\n//│     = undefined\n\n\n// * TODO init checking\nmodule M {\n  let x = 1\n  let y = foo\n  val foo = x\n  val bar = y\n  // foo, ()\n}\nM.foo\nM.bar\n//│ module M {\n//│   val bar: 1\n//│   val foo: 1\n//│   let x: 1\n//│   let y: 1\n//│ }\n//│ 1\n//│ res\n//│     = 1\n//│ res\n//│     = undefined\n\n\n\nabstract class Foo {\n  let size: Int = 1\n  fun get = size + 1\n}\n//│ abstract class Foo {\n//│   fun get: Int\n//│   let size: Int\n//│ }\n\n:e\nabstract class Foo {\n  let size: Int\n  fun get = size + 1\n}\n//│ ╔══[ERROR] `let` bindings must have a right-hand side\n//│ ║  l.261: \t  let size: Int\n//│ ╙──       \t  ^^^^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: size\n//│ ║  l.262: \t  fun get = size + 1\n//│ ╙──       \t            ^^^^\n//│ abstract class Foo {\n//│   fun get: Int\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol size\n\n:e\nabstract class Foo {\n  let size: Int = 1\n  fun get = this.size + 1\n}\n//│ ╔══[ERROR] Type `#Foo` does not contain member `size`\n//│ ║  l.279: \t  fun get = this.size + 1\n//│ ╙──       \t                ^^^^^\n//│ abstract class Foo {\n//│   fun get: Int\n//│   let size: Int\n//│ }\n\nmodule F extends Foo\n//│ module F extends Foo {\n//│   fun get: Int\n//│   let size: Int\n//│ }\n\n:e\nF.size\n//│ ╔══[ERROR] Let binding 'size' cannot tbe accessed as a field\n//│ ║  l.296: \tF.size\n//│ ║         \t ^^^^^\n//│ ╟── Use a `val` declaration to make it a field\n//│ ║  l.278: \t  let size: Int = 1\n//│ ╙──       \t      ^^^^^^^^^^^^^\n//│ Int | error\n//│ res\n//│     = undefined\n\nmodule F extends Foo { val size = 123 }\n//│ module F extends Foo {\n//│   fun get: Int\n//│   val size: 123\n//│ }\n\nF.get\n//│ Int\n//│ res\n//│     = 124\n\nF.size\n//│ 123\n//│ res\n//│     = 123\n\nmodule F extends Foo { fun size = 123 }\n//│ module F extends Foo {\n//│   fun get: Int\n//│   fun size: 123\n//│ }\n\nF.get\n//│ Int\n//│ res\n//│     = 124\n\nF.size\n//│ 123\n//│ res\n//│     = 123\n\nmodule F extends Foo { let size = 123 }\n//│ module F extends Foo {\n//│   fun get: Int\n//│   let size: 123\n//│ }\n\n// * Garbage result since `Foo` is ill-typed\nF.get\n//│ Int\n//│ res\n//│     = NaN\n\n:e\nF.size\n//│ ╔══[ERROR] Let binding 'size' cannot tbe accessed as a field\n//│ ║  l.352: \tF.size\n//│ ║         \t ^^^^^\n//│ ╟── Use a `val` declaration to make it a field\n//│ ║  l.339: \tmodule F extends Foo { let size = 123 }\n//│ ╙──       \t                           ^^^^^^^^^^\n//│ 123 | error\n//│ res\n//│     = undefined\n\n\nclass Foo(x: Int) { fun get0 = x }\n//│ class Foo(x: Int) {\n//│   fun get0: Int\n//│ }\n\n:e\nclass Bar extends Foo(123) { fun get2 = this.x }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.370: \tclass Bar extends Foo(123) { fun get2 = this.x }\n//│ ╙──       \t                                            ^^\n//│ class Bar extends Foo {\n//│   constructor()\n//│   fun get0: Int\n//│   fun get2: error\n//│ }\n\n:e\nmodule Bar extends Foo(123) { val x: Int; fun get2 = this.x }\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `Bar`\n//│ ║  l.381: \tmodule Bar extends Foo(123) { val x: Int; fun get2 = this.x }\n//│ ║         \t       ^^^\n//│ ╟── Declared here:\n//│ ║  l.381: \tmodule Bar extends Foo(123) { val x: Int; fun get2 = this.x }\n//│ ║         \t                              ^^^^^^^^^^\n//│ ╟── Note: value member `x` is private and cannot be used as a valid implementation\n//│ ║  l.364: \tclass Foo(x: Int) { fun get0 = x }\n//│ ╙──       \t          ^\n//│ module Bar extends Foo {\n//│   fun get0: Int\n//│   fun get2: Int\n//│   val x: Int\n//│ }\n\nBar.x\n//│ Int\n//│ res\n//│     = undefined\n\nBar.get0\n//│ Int\n//│ res\n//│     = 123\n\nBar.get2\n//│ Int\n//│ res\n//│     = undefined\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadMixins.mls",
    "content": ":NewDefs\n\n\n:e\nmixin M0\nM0\n//│ ╔══[ERROR] mixin M0 cannot be used in term position\n//│ ║  l.6: \tM0\n//│ ╙──     \t^^\n//│ mixin M0()\n//│ error\n//│ res\n//│     = [Function (anonymous)]\n\n:e\nM0\n//│ ╔══[ERROR] mixin M0 cannot be used in term position\n//│ ║  l.16: \tM0\n//│ ╙──      \t^^\n//│ error\n//│ res\n//│     = [Function (anonymous)]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadScopes.mls",
    "content": ":NewDefs\n\n\n:e\nmixin Foo(x: Int)\nx\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.6: \tx\n//│ ╙──     \t^\n//│ mixin Foo(x: Int)\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n\n:e\nclass Foo(x: Int)\nx\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.18: \tx\n//│ ╙──      \t^\n//│ class Foo(x: Int)\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n\n:e\nclass Bar { x }\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.29: \tclass Bar { x }\n//│ ╙──      \t            ^\n//│ class Bar {\n//│   constructor()\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadSignatures.mls",
    "content": ":NewDefs\n\n\n:e\ntrait T {\n  fun x : Int\n  fun x = false\n}\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.7: \t  fun x = false\n//│ ╙──     \t  ^^^^^^^^^^^^^\n//│ trait T {\n//│   fun x: Int\n//│ }\n\n\nclass A { virtual fun x = 1 }\n//│ class A {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\n:e\nclass B() extends A {\n  fun x: Int\n}\n//│ ╔══[ERROR] Type mismatch in signature of member `x`:\n//│ ║  l.25: \t  fun x: Int\n//│ ║        \t      ^^^^^^\n//│ ╟── type `Int` does not match type `1`\n//│ ║  l.25: \t  fun x: Int\n//│ ║        \t         ^^^\n//│ ╟── but it flows into signature of member `x` with expected type `1`\n//│ ║  l.25: \t  fun x: Int\n//│ ║        \t      ^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.17: \tclass A { virtual fun x = 1 }\n//│ ║        \t                          ^\n//│ ╟── from definition of method x:\n//│ ║  l.17: \tclass A { virtual fun x = 1 }\n//│ ╙──      \t                      ^^^^^\n//│ class B() extends A {\n//│   fun x: Int\n//│ }\n\nB().x\n//│ Int\n//│ res\n//│     = 1\n\n(B() : A).x\n//│ 1\n//│ res\n//│     = 1\n\nclass C() extends B { fun x = 0 }\n//│ class C() extends A, B {\n//│   fun x: 0\n//│ }\n\n(C() : A).x\n//│ 1\n//│ res\n//│     = 0\n\n:e\nclass B() extends A {\n  fun x: Int\n  fun x = 1\n}\n//│ ╔══[ERROR] Type mismatch in signature of member `x`:\n//│ ║  l.68: \t  fun x: Int\n//│ ║        \t      ^^^^^^\n//│ ╟── type `Int` does not match type `1`\n//│ ║  l.68: \t  fun x: Int\n//│ ║        \t         ^^^\n//│ ╟── but it flows into signature of member `x` with expected type `1`\n//│ ║  l.68: \t  fun x: Int\n//│ ║        \t      ^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.17: \tclass A { virtual fun x = 1 }\n//│ ║        \t                          ^\n//│ ╟── from definition of method x:\n//│ ║  l.17: \tclass A { virtual fun x = 1 }\n//│ ╙──      \t                      ^^^^^\n//│ class B() extends A {\n//│   fun x: Int\n//│ }\n\n\n:e\nmixin M { fun x : Int }\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `M`\n//│ ║  l.92: \tmixin M { fun x : Int }\n//│ ║        \t      ^\n//│ ╟── Declared here:\n//│ ║  l.92: \tmixin M { fun x : Int }\n//│ ╙──      \t          ^^^^^^^^^^^\n//│ mixin M() {\n//│   fun x: Int\n//│ }\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadSuper.mls",
    "content": ":NewDefs\n\n\nmixin M0 {\n  fun f = 42\n}\n//│ mixin M0() {\n//│   fun f: 42\n//│ }\n\n:e\nmixin M1 {\n  fun g = super\n}\n//│ ╔══[ERROR] Illegal use of `super`\n//│ ║  l.13: \t  fun g = super\n//│ ╙──      \t          ^^^^^\n//│ mixin M1() {\n//│   super: 'super\n//│   fun g: 'super\n//│ }\n//│ Syntax error:\n//│   'super' keyword unexpected here\n\n:re\nmodule C0 extends M0, M1\nC0.g\n//│ module C0 {\n//│   fun f: 42\n//│   fun g: {f: 42}\n//│ }\n//│ {f: 42}\n//│ res\n//│ Runtime error:\n//│   ReferenceError: M1 is not defined\n\n\n:e\nclass Foo {\n  fun f = super\n}\n//│ ╔══[ERROR] Illegal use of `super`\n//│ ║  l.40: \t  fun f = super\n//│ ╙──      \t          ^^^^^\n//│ class Foo {\n//│   constructor()\n//│   fun f: Foo\n//│ }\n//│ Syntax error:\n//│   'super' keyword unexpected here\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadTraits.mls",
    "content": ":NewDefs\n\n\ntrait Foo\n//│ trait Foo\n\n:e\nFoo\n//│ ╔══[ERROR] trait Foo cannot be used in term position\n//│ ║  l.8: \tFoo\n//│ ╙──     \t^^^\n//│ error\n//│ Code generation encountered an error:\n//│   trait used in term position\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BadUCS.mls",
    "content": ":NewDefs\n\n\nclass Foo\n//│ class Foo {\n//│   constructor()\n//│ }\n\nfun foo(x) = if x is Foo then 0\n//│ fun foo: Foo -> 0\n\n\nmodule Bar {\n  class Foo0\n}\n//│ module Bar {\n//│   class Foo0 {\n//│     constructor()\n//│   }\n//│ }\n\nfun foo(x) = if x is Bar then 0\n//│ fun foo: Bar -> 0\n\n:e\n:ge\nfun foo(x) = if x is Foo0 then 0\n//│ ╔══[ERROR] type identifier `Foo0` not found\n//│ ║  l.27: \tfun foo(x) = if x is Foo0 then 0\n//│ ╙──      \t                     ^^^^\n//│ ╔══[ERROR] type identifier not found: Foo0\n//│ ║  l.27: \tfun foo(x) = if x is Foo0 then 0\n//│ ╙──      \t                     ^^^^\n//│ fun foo: nothing -> error\n//│ Code generation encountered an error:\n//│   unknown match case: Foo0\n\n\ntype F = Foo\n//│ type F = Foo\n\n:e\n:ge\nfun foo(x) = if x is F then 0\n//│ ╔══[ERROR] Type alias is not allowed in pattern\n//│ ║  l.44: \tfun foo(x) = if x is F then 0\n//│ ╙──      \t                     ^\n//│ ╔══[ERROR] can only match on classes and traits\n//│ ║  l.44: \tfun foo(x) = if x is F then 0\n//│ ╙──      \t                     ^\n//│ fun foo: nothing -> error\n//│ Code generation encountered an error:\n//│   cannot match type alias F\n\n:e\n:ge\nfun foo(x) = if x is F() then 0\n//│ ╔══[ERROR] Type alias is not allowed in pattern\n//│ ║  l.57: \tfun foo(x) = if x is F() then 0\n//│ ╙──      \t                     ^\n//│ ╔══[ERROR] can only match on classes and traits\n//│ ║  l.57: \tfun foo(x) = if x is F() then 0\n//│ ╙──      \t                     ^\n//│ fun foo: nothing -> error\n//│ Code generation encountered an error:\n//│   cannot match type alias F\n\n\nmixin M\n//│ mixin M()\n\n:e\n:ge\nfun foo(x) = if x is M then 0\n//│ ╔══[ERROR] Mixins are not allowed in pattern\n//│ ║  l.74: \tfun foo(x) = if x is M then 0\n//│ ╙──      \t                     ^\n//│ ╔══[ERROR] can only match on classes and traits\n//│ ║  l.74: \tfun foo(x) = if x is M then 0\n//│ ╙──      \t                     ^\n//│ fun foo: nothing -> error\n//│ Code generation encountered an error:\n//│   unknown match case: M\n\n:e\n:ge\nfun foo(x) = if x is M() then 0\n//│ ╔══[ERROR] Mixins are not allowed in pattern\n//│ ║  l.87: \tfun foo(x) = if x is M() then 0\n//│ ╙──      \t                     ^\n//│ ╔══[ERROR] can only match on classes and traits\n//│ ║  l.87: \tfun foo(x) = if x is M() then 0\n//│ ╙──      \t                     ^\n//│ fun foo: nothing -> error\n//│ Code generation encountered an error:\n//│   unknown match case: M\n\n:w\nfun foo0(x, y) = if x is y then 0\n//│ ╔══[WARNING] the outer binding `y`\n//│ ║  l.99: \tfun foo0(x, y) = if x is y then 0\n//│ ║        \t            ^\n//│ ╟── is shadowed by name pattern `y`\n//│ ║  l.99: \tfun foo0(x, y) = if x is y then 0\n//│ ╙──      \t                         ^\n//│ fun foo0: (anything, anything) -> 0\n\n\nfun foo = 0\n//│ fun foo: 0\n\n:e\n:ge\nfun foo0(x) = if x is foo() then 0\n//│ ╔══[ERROR] type identifier `foo` not found\n//│ ║  l.114: \tfun foo0(x) = if x is foo() then 0\n//│ ╙──       \t                      ^^^\n//│ ╔══[ERROR] can only match on classes and traits\n//│ ║  l.114: \tfun foo0(x) = if x is foo() then 0\n//│ ╙──       \t                      ^^^\n//│ fun foo0: nothing -> error\n//│ Code generation encountered an error:\n//│   unknown match case: foo\n\n:e\n:ge\n// FIXME: Typer.scala:1497\nfun foo(x) = if x is foo() then 0\n//│ ╔══[ERROR] type identifier `foo` not found\n//│ ║  l.128: \tfun foo(x) = if x is foo() then 0\n//│ ╙──       \t                     ^^^\n//│ ╔══[ERROR] can only match on classes and traits\n//│ ║  l.128: \tfun foo(x) = if x is foo() then 0\n//│ ╙──       \t                     ^^^\n//│ /!!!\\ Uncaught error: java.lang.Exception: Internal Error: Program reached an unexpected state.\n\nmodule Nil\nclass Cons[out A](head: A, tail: Cons[A] | Nil)\n//│ module Nil\n//│ class Cons[A](head: A, tail: Cons[A] | Nil)\n\nfun join(xs) =\n  if xs is\n    Nil then \"\"\n    Cons(x, Nil) then toString(x)\n    Cons(x, xs') then concat(toString(x))(concat(\", \")(join(xs')))\n//│ fun join: (Cons[anything] | Nil) -> Str\n"
  },
  {
    "path": "shared/src/test/diff/nu/BasicClassInheritance.mls",
    "content": ":NewDefs\n\n\nclass A\n//│ class A {\n//│   constructor()\n//│ }\n\nclass B(m: Int) extends A\n//│ class B(m: Int) extends A\n\n\nclass A(n: Int)\n//│ class A(n: Int)\n\nclass B(m: Int) extends A(m + 1)\n//│ class B(m: Int) extends A\n\n\nclass A {\n  fun a1: Int\n  fun a1 = 1\n  fun a2 = 2\n}\n//│ class A {\n//│   constructor()\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\nclass B extends A\n//│ class B extends A {\n//│   constructor()\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\n\n// * Interestingly, we can currently inherit from modules...\n\nmodule C { fun test = 0 }\n//│ module C {\n//│   fun test: 0\n//│ }\n\nclass D() extends C\n//│ class D() extends C {\n//│   fun test: 0\n//│ }\n\nD().test\n//│ 0\n//│ res\n//│     = 0\n\n\nclass E(val m: Int) extends A {\n  constructor(a: Int, b: Int) {\n    m = a + b\n    log of concat(\"Here's m: \")(toString of m)\n  }\n}\n//│ class E(m: Int) extends A {\n//│   constructor(a: Int, b: Int)\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\n:e\nE(1).m\n//│ ╔══[ERROR] Construction of class with auxiliary constructor should use the `new` keyword\n//│ ║  l.70: \tE(1).m\n//│ ╙──      \t^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.70: \tE(1).m\n//│ ║        \t^^^^\n//│ ╟── argument of type `[1]` does not match type `[a: Int, b: Int]`\n//│ ║  l.70: \tE(1).m\n//│ ╙──      \t ^^^\n//│ Int | error\n//│ res\n//│     = NaN\n//│ // Output\n//│ Here's m: NaN\n\n(new E(1, 2)).m\n//│ Int\n//│ res\n//│     = 3\n//│ // Output\n//│ Here's m: 3\n\nnew E(1, 2).m\n//│ Int\n//│ res\n//│     = 3\n//│ // Output\n//│ Here's m: 3\n\nif new E(1, 2) is E(x) then x\n//│ Int\n//│ res\n//│     = 3\n//│ // Output\n//│ Here's m: 3\n\n:e\nmodule F extends E\n//│ ╔══[ERROR] class E expects 2 parameter(s); got 0\n//│ ║  l.108: \tmodule F extends E\n//│ ╙──       \t                 ^\n//│ module F extends A, E {\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\n:e\nmodule F extends E(123)\n//│ ╔══[ERROR] class E expects 2 parameter(s); got 1\n//│ ║  l.118: \tmodule F extends E(123)\n//│ ╙──       \t                 ^^^^^\n//│ module F extends A, E {\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\nmodule F extends E(123, 456)\n//│ module F extends A, E {\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\n// * Note: strangely, we see here the ctor output from the previous definitions of the F module 🤔\nF.m\n//│ Int\n//│ res\n//│     = 579\n//│ // Output\n//│ Here's m: NaN\n//│ Here's m: NaN\n//│ Here's m: 579\n\n\nclass G(x: Int) extends E(x, x + 1)\n//│ class G(x: Int) extends A, E {\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\nG(123).m\n//│ Int\n//│ res\n//│     = 247\n//│ // Output\n//│ Here's m: 247\n\n\n:e // TODO support\nclass H extends E {\n  constructor(a: Int, b: Int) {\n    super(a, b)\n  }\n}\n//│ ╔══[ERROR] class E expects 2 parameter(s); got 0\n//│ ║  l.159: \tclass H extends E {\n//│ ╙──       \t                ^\n//│ ╔══[ERROR] Illegal use of `super`\n//│ ║  l.161: \t    super(a, b)\n//│ ╙──       \t    ^^^^^\n//│ ╔══[ERROR] identifier not found: super\n//│ ║  l.161: \t    super(a, b)\n//│ ╙──       \t    ^^^^^\n//│ class H extends A, E {\n//│   constructor(a: Int, b: Int)\n//│   fun a1: Int\n//│   fun a2: 2\n//│ }\n\n:re\nnew H(111, 222)\n//│ H\n//│ res\n//│ Runtime error:\n//│   ReferenceError: Super constructor may only be called once\n//│ // Output\n//│ Here's m: NaN\n//│ Here's m: 333\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BasicClasses.mls",
    "content": ":NewDefs\n\n\nclass A(val n: Int)\n//│ class A(n: Int)\n\nA\n//│ (n: Int) -> A\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class A],\n//│         unapply: [Function: unapply]\n//│       }\n\nlet a = A(42)\n//│ let a: A\n//│ a\n//│   = A {}\n\na.n\n//│ Int\n//│ res\n//│     = 42\n\n\nfun f(x: A) = x.n\n//│ fun f: (x: A) -> Int\n\nfun f(x: A) = if x is A then x.n\n//│ fun f: (x: A) -> Int\n\nfun f(x: A | 'b) = if x is A then x.n else 0\n//│ fun f: (x: Object) -> Int\n\n\nfun f(x) = x.n\n//│ fun f: forall 'n. {n: 'n} -> 'n\n\nf(a)\n//│ Int\n//│ res\n//│     = 42\n\nfun f(x) = if x is A then x.n\n//│ fun f: A -> Int\n\nf(a)\n//│ Int\n//│ res\n//│     = 42\n\nfun f(x) = if x is A then x.n else 0\n//│ fun f: Object -> Int\n\nf(a)\n//│ Int\n//│ res\n//│     = 42\n\n\n\nclass C {\n  fun id(x) = x\n  fun const(x) = id\n}\n//│ class C {\n//│   constructor()\n//│   fun const: anything -> (forall 'a. 'a -> 'a)\n//│   fun id: forall 'a. 'a -> 'a\n//│ }\n\n\n// TODO\nclass Base0(val n) {\n  fun me = this\n  fun my = this.n\n  fun mine = my\n  fun oops = this.my\n}\n//│ ╔══[ERROR] Class parameters currently need type annotations\n//│ ║  l.74: \tclass Base0(val n) {\n//│ ╙──      \t                ^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.78: \t  fun oops = this.my\n//│ ╙──      \t                 ^^^\n//│ class Base0(n: error) {\n//│   fun me: Base0 & {n: error}\n//│   fun mine: error\n//│   fun my: error\n//│   fun oops: error\n//│ }\n\n// :d\n// Base0\n\nlet b1 = Base0(42)\n//│ let b1: Base0\n//│ b1\n//│    = Base0 {}\n\nlet n1 = b1.n\n//│ let n1: error\n//│ n1\n//│    = 42\n\n// TODO\nn1 + 1\n//│ Int\n//│ res\n//│     = 43\n\n\nlet b2 = Base0(\"hi\")\nlet n2 = b2.n\n//│ let b2: Base0\n//│ let n2: error\n//│ b2\n//│    = Base0 {}\n//│ n2\n//│    = 'hi'\n\n\n\nclass Base1(val base: Int) {\n  fun getBase1 = base\n  fun getBase2 = this.base\n  fun foo(x) = this.base + x\n}\n//│ class Base1(base: Int) {\n//│   fun foo: Int -> Int\n//│   fun getBase1: Int\n//│   fun getBase2: Int\n//│ }\n\nclass Base1(val base: Int) {\n  fun getBase1 = base\n  fun me = this\n  fun foo(x) = base + x\n}\n//│ class Base1(base: Int) {\n//│   fun foo: Int -> Int\n//│   fun getBase1: Int\n//│   fun me: Base1 & {base: Int}\n//│ }\n\nBase1\n//│ (base: Int) -> Base1\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Base1],\n//│         unapply: [Function: unapply]\n//│       }\n\nlet b = Base1(1)\n//│ let b: Base1\n//│ b\n//│   = Base1 {}\n\nb.base\n//│ Int\n//│ res\n//│     = 1\n\nb.getBase1\n//│ Int\n//│ res\n//│     = 1\n\n// :d\nb.me\n//│ Base1 & {base: Int}\n//│ res\n//│     = Base1 {}\n\n:e\nb.getBaseTypo\n//│ ╔══[ERROR] Type `Base1` does not contain member `getBaseTypo`\n//│ ║  l.176: \tb.getBaseTypo\n//│ ╙──       \t ^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = undefined\n\n\nb : Base1\n//│ Base1\n//│ res\n//│     = Base1 {}\n\n\nclass Rec(val n: Int) {\n  fun go = Rec(n + 1)\n}\n//│ class Rec(n: Int) {\n//│   fun go: Rec\n//│ }\n\nlet r = Rec(0)\nr.n\n//│ let r: Rec\n//│ Int\n//│ r\n//│   = Rec {}\n//│ res\n//│     = 0\n\nr.go.n\n//│ Int\n//│ res\n//│     = 1\n\n\n\n\n// TODO treat `a: Int` as a signature\nclass Annots(base: 0 | 1) {\n  a: Int\n  fun a = base\n}\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in type ascription:\n//│ ║  l.217: \t  a: Int\n//│ ║         \t  ^\n//│ ╟── type `Int` does not match type `()`\n//│ ║  l.217: \t  a: Int\n//│ ║         \t     ^^^\n//│ ╟── but it flows into expression in statement position with expected type `()`\n//│ ║  l.217: \t  a: Int\n//│ ╙──       \t  ^\n//│ class Annots(base: 0 | 1) {\n//│   fun a: 0 | 1\n//│ }\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/BasicMixins.mls",
    "content": ":NewDefs\n\n\nmixin Base {\n  val base = 42\n}\n//│ mixin Base() {\n//│   val base: 42\n//│ }\n\nmixin BaseTest {\n  fun test = super.base\n}\n//│ mixin BaseTest() {\n//│   super: {base: 'base}\n//│   fun test: 'base\n//│ }\n\n\nmodule Base0 extends Base, BaseTest\n//│ module Base0 {\n//│   val base: 42\n//│   fun test: 42\n//│ }\n\nBase0\n//│ Base0\n//│ res\n//│     = Base0 { class: [Function: Base0] }\n\nBase0.test\n//│ 42\n//│ res\n//│     = 42\n\n\n:e\nclass Base1(val base: Int) extends BaseTest {\n  fun test2 = [base, this.base]\n}\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.38: \tclass Base1(val base: Int) extends BaseTest {\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.39: \t  fun test2 = [base, this.base]\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.40: \t}\n//│ ║        \t^\n//│ ╟── Object of type `anything` does not have field 'base'\n//│ ║  l.38: \tclass Base1(val base: Int) extends BaseTest {\n//│ ║        \t                                   ^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.12: \t  fun test = super.base\n//│ ║        \t             ^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.12: \t  fun test = super.base\n//│ ╙──      \t             ^^^^^\n//│ class Base1(base: Int) {\n//│   fun test: nothing\n//│   fun test2: [Int, Int]\n//│ }\n\n\nmixin BaseOf(val base: Int) {\n  fun original = base\n}\n//│ mixin BaseOf(base: Int) {\n//│   fun original: Int\n//│ }\n\nmixin BaseInc {\n  fun base = super.base + 1\n  fun test2 = [this.original, this.base]\n}\n//│ mixin BaseInc() {\n//│   super: {base: Int}\n//│   this: {base: 'base, original: 'original}\n//│   fun base: Int\n//│   fun test2: ['original, 'base]\n//│ }\n\n\nclass Base2(x: Int) extends BaseOf(x + 1), BaseTest, BaseInc {\n  fun base = x\n  fun overridden = super.base\n}\n//│ class Base2(x: Int) {\n//│   fun base: Int\n//│   fun original: Int\n//│   fun overridden: Int\n//│   fun test: Int\n//│   fun test2: [Int, Int]\n//│ }\n\nBase2(11).base\n//│ Int\n//│ res\n//│     = 11\n\nBase2(11).overridden\n//│ Int\n//│ res\n//│     = 13\n\nBase2(11).test\n//│ Int\n//│ res\n//│     = 12\n\nBase2(11).test2\n//│ [Int, Int]\n//│ res\n//│     = [ 12, 11 ]\n\n\n:e // TODO\nclass Base2(x) extends BaseOf(x + 1), BaseTest\n//│ ╔══[ERROR] Class parameters currently need type annotations\n//│ ║  l.116: \tclass Base2(x) extends BaseOf(x + 1), BaseTest\n//│ ╙──       \t            ^\n//│ class Base2(x: error) {\n//│   fun original: Int\n//│   fun test: Int\n//│ }\n\n:w\n:e\nclass Base1(x: Int): BaseTest\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract class definitions\n//│ ║  l.127: \tclass Base1(x: Int): BaseTest\n//│ ║         \t                     ^^^^^^^^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ ╔══[ERROR] mixin BaseTest cannot be used as a type\n//│ ║  l.127: \tclass Base1(x: Int): BaseTest\n//│ ╙──       \t                     ^^^^^^^^\n//│ class Base1(x: Int): BaseTest\n\nBase1\n//│ (x: Int) -> Base1\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Base1],\n//│         unapply: [Function: unapply]\n//│       }\n\n:e\n1 : BaseTest\n//│ ╔══[ERROR] mixin BaseTest cannot be used as a type\n//│ ║  l.146: \t1 : BaseTest\n//│ ╙──       \t    ^^^^^^^^\n//│ BaseTest\n//│ res\n//│     = 1\n\n:e\nerror : BaseTest\n//│ ╔══[ERROR] mixin BaseTest cannot be used as a type\n//│ ║  l.155: \terror : BaseTest\n//│ ╙──       \t        ^^^^^^^^\n//│ BaseTest\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n// :ns\nmixin Foo {\n  fun test(x) = [super.base + x, x, super.misc]\n}\n//│ mixin Foo() {\n//│   super: {base: Int, misc: 'misc}\n//│   fun test: (Int & 'a) -> [Int, 'a, 'misc]\n//│ }\n\n:e\nmodule Base1(base: Int, misc: string) extends Foo\n//│ ╔══[ERROR] Module parameters are not supported\n//│ ║  l.175: \tmodule Base1(base: Int, misc: string) extends Foo\n//│ ╙──       \t             ^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.175: \tmodule Base1(base: Int, misc: string) extends Foo\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Object of type `anything` does not have field 'misc'\n//│ ║  l.175: \tmodule Base1(base: Int, misc: string) extends Foo\n//│ ║         \t                                              ^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.167: \t  fun test(x) = [super.base + x, x, super.misc]\n//│ ║         \t                                    ^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.167: \t  fun test(x) = [super.base + x, x, super.misc]\n//│ ╙──       \t                                    ^^^^^\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.175: \tmodule Base1(base: Int, misc: string) extends Foo\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Object of type `anything` does not have field 'base'\n//│ ║  l.175: \tmodule Base1(base: Int, misc: string) extends Foo\n//│ ║         \t                                              ^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.167: \t  fun test(x) = [super.base + x, x, super.misc]\n//│ ║         \t                 ^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.167: \t  fun test(x) = [super.base + x, x, super.misc]\n//│ ╙──       \t                 ^^^^^\n//│ module Base1(base: Int, misc: string) {\n//│   fun test: forall 'a. (Int & 'a) -> [Int, 'a, nothing]\n//│ }\n\n:e\nBase1.test\n//│ ╔══[ERROR] Parameterized modules are not yet supported\n//│ ║  l.208: \tBase1.test\n//│ ╙──       \t^^^^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.208: \tBase1.test\n//│ ║         \t^^^^^^^^^^\n//│ ╟── reference of type `(base: Int, misc: string) -> Base1` does not have field 'test'\n//│ ║  l.208: \tBase1.test\n//│ ╙──       \t^^^^^\n//│ error\n//│ res\n//│     = [Function: test]\n\n\nmixin WrapBase {\n  // fun wrap(x) = x\n  // fun wrap(x) = x : Int\n  fun wrapA(x: Int) = x : Int\n  fun wrap(x) = x\n}\n//│ mixin WrapBase() {\n//│   fun wrap: 'a -> 'a\n//│   fun wrapA: (x: Int) -> Int\n//│ }\n\n// :d\nmixin Wrap {\n  fun wrapA(x) = [super.wrapA(x)]\n  fun wrap(x) = [super.wrap(x)]\n}\n//│ mixin Wrap() {\n//│   super: {wrap: 'a -> 'b, wrapA: 'c -> 'd}\n//│   fun wrap: 'a -> ['b]\n//│   fun wrapA: 'c -> ['d]\n//│ }\n\n\n\n// :d\nmodule WrapBase1 extends WrapBase, Wrap\n//│ module WrapBase1 {\n//│   fun wrap: 'a -> ['a]\n//│   fun wrapA: Int -> [Int]\n//│ }\n\n\nWrapBase1\n//│ WrapBase1\n//│ res\n//│     = WrapBase1 { class: [Function: WrapBase1] }\n\n// :d\nWrapBase1.wrapA\n//│ Int -> [Int]\n//│ res\n//│     = [Function: wrapA]\n\nWrapBase1.wrap\n//│ 'a -> ['a]\n//│ res\n//│     = [Function: wrap]\n\n// :d\n// WrapBase1.wrap\n\n\nWrapBase1.wrap(1)\n//│ [1]\n//│ res\n//│     = [ 1 ]\n\nWrapBase1.wrap(\"ok\")\n//│ [\"ok\"]\n//│ res\n//│     = [ 'ok' ]\n\n\nWrapBase1.wrapA(1)\n//│ [Int]\n//│ res\n//│     = [ 1 ]\n\n:e\nWrapBase1.wrapA(\"ok\")\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.292: \tWrapBase1.wrapA(\"ok\")\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"ok\"` is not an instance of type `Int`\n//│ ║  l.292: \tWrapBase1.wrapA(\"ok\")\n//│ ║         \t                ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.236: \t  fun wrapA(x) = [super.wrapA(x)]\n//│ ╙──       \t                              ^\n//│ error | [Int]\n//│ res\n//│     = [ 'ok' ]\n\n\n\nmodule WrapBase2 extends WrapBase, Wrap, Wrap, Wrap\n//│ module WrapBase2 {\n//│   fun wrap: 'a -> [[['a]]]\n//│   fun wrapA: Int -> [[[Int]]]\n//│ }\n\nlet w = WrapBase2.wrap\n//│ let w: 'a -> [[['a]]]\n//│ w\n//│   = [Function: wrap]\n\nlet wd = w(1)\n//│ let wd: [[[1]]]\n//│ wd\n//│    = [ [ [ 1 ] ] ]\n\nwd.0.0.0 + 1\n//│ Int\n//│ res\n//│     = 2\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/CallByName.mls",
    "content": ":NewDefs\n\n\nlet x = log(\"ok\")\n//│ let x: ()\n//│ x\n//│   = undefined\n//│ // Output\n//│ ok\n\nx\n//│ ()\n//│ res\n//│     = undefined\n\nx\n//│ ()\n//│ res\n//│     = undefined\n\n\nfun x = log(\"ok\")\n//│ fun x: ()\n\nx\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ ok\n\nx\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ ok\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/CaseExpr.mls",
    "content": ":NewDefs\n\n\ncase 0 then true\n//│ 0 -> true\n//│ res\n//│     = [Function: res]\n\n:pe // TODO support\ncase 0 then true, 1 then false\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.10: \tcase 0 then true, 1 then false\n//│ ╙──      \t                  ^^^^^^^^^^^^\n//│ 0 -> ()\n//│ res\n//│     = [Function: res]\n\ncase\n  0 then true\n  1 then false\n//│ (0 | 1) -> Bool\n//│ res\n//│     = [Function: res]\n\n\nfun foo = case\n  0 then true\n  1 then false\n//│ fun foo: (0 | 1) -> Bool\n\n[foo(0), foo(1)]\n//│ [Bool, Bool]\n//│ res\n//│     = [ true, false ]\n\n\n\nabstract class Option[out A]: Some[A] | None\nclass Some[out A](val value: A) extends Option[A]\nmodule None extends Option[nothing]\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\n\nfun map(f) = case\n  Some(x) then Some(f(x))\n  None    then None\n//│ fun map: forall 'a 'A. ('a -> 'A) -> (None | Some['a]) -> (None | Some['A])\n\nmap(succ) of Some of 123\n//│ None | Some[Int]\n//│ res\n//│     = Some {}\n\nmap(succ) of None\n//│ None | Some[Int]\n//│ res\n//│     = None { class: [class None extends Option] }\n\n\n\nfun map(f) = case\n  Some(x)   then Some(f(x))\n  None as n then n\n//│ fun map: forall 'a 'A. ('a -> 'A) -> (None | Some['a]) -> (None | Some['A])\n\n\n:pe\ncase 1\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found integer literal instead\n//│ ║  l.70: \tcase 1\n//│ ║        \t     ^\n//│ ╟── Note: 'case' expression starts here:\n//│ ║  l.70: \tcase 1\n//│ ╙──      \t^^^^\n//│ anything -> 1\n//│ res\n//│     = [Function: res]\n\n:pe\ncase (1 then true)\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.82: \tcase (1 then true)\n//│ ╙──      \t        ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found integer literal instead\n//│ ║  l.82: \tcase (1 then true)\n//│ ║        \t     ^^^^^^^^^^^^^\n//│ ╟── Note: 'case' expression starts here:\n//│ ║  l.82: \tcase (1 then true)\n//│ ╙──      \t^^^^\n//│ anything -> 1\n//│ res\n//│     = [Function: res]\n\ncase else 0\n//│ anything -> 0\n//│ res\n//│     = [Function: res]\n\n:pe\ncase then 1 else 0\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword in expression position\n//│ ║  l.102: \tcase then 1 else 0\n//│ ╙──       \t     ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found integer literal instead\n//│ ║  l.102: \tcase then 1 else 0\n//│ ║         \t          ^\n//│ ╟── Note: 'case' expression starts here:\n//│ ║  l.102: \tcase then 1 else 0\n//│ ╙──       \t^^^^\n//│ ╔══[PARSE ERROR] Expected end of input; found 'else' keyword instead\n//│ ║  l.102: \tcase then 1 else 0\n//│ ╙──       \t            ^^^^\n//│ anything -> 1\n//│ res\n//│     = [Function: res]\n\n\n\n// TODO:\n\n:pe\n:e\ncase x, y then x + y\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.125: \tcase x, y then x + y\n//│ ╙──       \t        ^^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found operator application instead\n//│ ║  l.125: \tcase x, y then x + y\n//│ ║         \t     ^^^^^^^^^^^^^^^\n//│ ╟── Note: 'case' expression starts here:\n//│ ║  l.125: \tcase x, y then x + y\n//│ ╙──       \t^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.125: \tcase x, y then x + y\n//│ ╙──       \t     ^\n//│ anything -> ()\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\ncase (x, y) then x + y\n//│ ╔══[ERROR] type identifier `,` not found\n//│ ║  l.143: \tcase (x, y) then x + y\n//│ ╙──       \t      ^^^^\n//│ ╔══[ERROR] type identifier not found: ,\n//│ ║  l.143: \tcase (x, y) then x + y\n//│ ╙──       \t      ^^^^\n//│ nothing -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol ,\n\n\nlet foo = case [x, y] then x + y\n//│ let foo: {0: Int, 1: Int} -> Int\n//│ foo\n//│     = [Function: foo1]\n\nfoo([1, 2])\n//│ Int\n//│ res\n//│     = 3\n"
  },
  {
    "path": "shared/src/test/diff/nu/ClassField.mls",
    "content": ":NewDefs\n\n\n\nclass Foo(x: Int)\n//│ class Foo(x: Int)\n\nFoo\n//│ (x: Int) -> Foo\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Foo],\n//│         unapply: [Function: unapply]\n//│       }\n\ntypeof(Foo)\n//│ Str\n//│ res\n//│     = 'function'\n\nlet f = Foo(123)\n//│ let f: Foo\n//│ f\n//│   = Foo {}\n\ntypeof(f)\n//│ Str\n//│ res\n//│     = 'object'\n\n:e\nlet cls = Foo.class\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.32: \tlet cls = Foo.class\n//│ ║        \t          ^^^^^^^^^\n//│ ╟── reference of type `(x: Int) -> Foo` does not have field 'class'\n//│ ║  l.32: \tlet cls = Foo.class\n//│ ╙──      \t          ^^^\n//│ let cls: error\n//│ cls\n//│     = [class Foo]\n\ntypeof(cls)\n//│ Str\n//│ res\n//│     = 'function'\n\n\n\nmixin Base\n//│ mixin Base()\n\nclass Derived() extends Base\n//│ class Derived()\n\n// * Strangely, we now get `{ class: [Function: Derived] }`\nDerived\n//│ () -> Derived\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [Function: Derived],\n//│         unapply: [Function: unapply]\n//│       }\n\n:e\nlet cls = Derived.class\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.66: \tlet cls = Derived.class\n//│ ║        \t          ^^^^^^^^^^^^^\n//│ ╟── reference of type `() -> Derived` does not have field 'class'\n//│ ║  l.66: \tlet cls = Derived.class\n//│ ╙──      \t          ^^^^^^^\n//│ let cls: error\n//│ cls\n//│     = [Function: Derived]\n\ntypeof(cls)\n//│ Str\n//│ res\n//│     = 'function'\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ClassInstantiation.mls",
    "content": "// *** Class instantiation tests *** //\n\n:NewDefs\n\n\nclass C\n//│ class C {\n//│   constructor()\n//│ }\n\nnew C\n//│ C\n//│ res\n//│     = C {}\n\n// * TODO decide: forbid?\nnew C()\n//│ C\n//│ res\n//│     = C {}\n\n:e\nC()\n//│ ╔══[ERROR] Construction of unparameterized class C should use the `new` keyword\n//│ ║  l.23: \tC()\n//│ ╙──      \t^\n//│ C\n//│ res\n//│ Runtime error:\n//│   TypeError: Class constructor C cannot be invoked without 'new'\n\n\nclass D(x: Int)\n//│ class D(x: Int)\n\n:js\nD(0)\n//│ D\n//│ // Prelude\n//│ class TypingUnit5 {}\n//│ const typing_unit5 = new TypingUnit5;\n//│ // Query 1\n//│ res = D(0);\n//│ // End of generated code\n//│ res\n//│     = D {}\n\n// * TODO decide: reject or accept?\n:js\nnew D(0)\n//│ D\n//│ // Prelude\n//│ class TypingUnit6 {}\n//│ const typing_unit6 = new TypingUnit6;\n//│ // Query 1\n//│ res = new D.class(0);\n//│ // End of generated code\n//│ res\n//│     = D {}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ClassSignatures.mls",
    "content": ":NewDefs\n\n\nabstract class C0: C1 | C2\nclass C1() extends C0\nmodule C2 extends C0\n//│ abstract class C0: C1 | C2\n//│ class C1() extends C0\n//│ module C2 extends C0\n\nfun foo(x: C0) = if x is\n  C1 then 1\n  C2 then 2\n//│ fun foo: (x: C0) -> (1 | 2)\n\nfun foo(x: C0) = x : C1 | C2\n//│ fun foo: (x: C0) -> (C1 | C2)\n\nfun foo(x) = if x is\n  C1 then 1\n  C2 then 2\n//│ fun foo: (C1 | C2) -> (1 | 2)\n\nfoo(C1()) + foo(C2)\n//│ Int\n//│ res\n//│     = 3\n\n\n:e\nclass C3 extends C0\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.31: \tclass C3 extends C0\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#C3` does not match type `C1 | C2`\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.4: \tabstract class C0: C1 | C2\n//│ ╙──     \t                   ^^^^^^^\n//│ class C3 extends C0 {\n//│   constructor()\n//│ }\n\n\ntrait B\n//│ trait B\n\n:w\n:e\nclass A(): B\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract class definitions\n//│ ║  l.49: \tclass A(): B\n//│ ║        \t           ^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.49: \tclass A(): B\n//│ ║        \t^^^^^^^^^\n//│ ╟── expression of type `#A` is not an instance of type `B`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.49: \tclass A(): B\n//│ ╙──      \t           ^\n//│ class A(): B\n\nA() : B\n//│ B\n//│ res\n//│     = A {}\n\nabstract class A(): B\n//│ abstract class A(): B\n\n:e\nA() : B\n//│ ╔══[ERROR] Class A is abstract and cannot be instantiated\n//│ ║  l.72: \tA() : B\n//│ ╙──      \t^\n//│ B\n//│ res\n//│     = A {}\n\nmodule C extends A, B\n//│ module C extends A, B\n\nC : B\n//│ B\n//│ res\n//│     = C { class: [class C extends A] }\n\n\n:w\n:e\nclass A(): C\nclass B() extends A\nclass C() extends B\n//│ ╔══[WARNING] Self-type annotations have no effects on non-abstract class definitions\n//│ ║  l.91: \tclass A(): C\n//│ ║        \t           ^\n//│ ╙── Did you mean to use `extends` and inherit from a parent class?\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.91: \tclass A(): C\n//│ ║        \t^^^^^^^^^\n//│ ╟── expression of type `#A` is not an instance of type `C`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.91: \tclass A(): C\n//│ ╙──      \t           ^\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.92: \tclass B() extends A\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#B` is not an instance of type `C`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.91: \tclass A(): C\n//│ ╙──      \t           ^\n//│ class A(): C\n//│ class B() extends A\n//│ class C() extends A, B\n\n\n:e\nabstract class A(): C\nclass B() extends A\nclass C() extends B\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.119: \tclass B() extends A\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#B` is not an instance of type `C`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.118: \tabstract class A(): C\n//│ ╙──       \t                    ^\n//│ abstract class A(): C\n//│ class B() extends A\n//│ class C() extends A, B\n\n\nabstract class A(): C\nabstract class B() extends A\nclass C() extends B\n//│ abstract class A(): C\n//│ abstract class B(): C extends A\n//│ class C() extends A, B\n\n\n// * Transitively-inherited self-types are checked\n\n:e\nclass D() extends B\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.144: \tclass D() extends B\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#D` is not an instance of type `C`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.133: \tabstract class A(): C\n//│ ╙──       \t                    ^\n//│ class D() extends A, B\n\n\n// * Transitively-inherited self-types can be leveraged\n\nfun test(x: B): C = x\n//│ fun test: (x: B) -> C\n\nfun test[A](x: B & A): C = x\n//│ fun test: (x: B) -> C\n\ntrait T\nfun test(x: B & T): C = x\n//│ trait T\n//│ fun test: (x: B & T) -> C\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ClassesInMixins.mls",
    "content": ":NewDefs\n\n\n\nmixin Test {\n  class Foo(val n: Int)\n  val f = Foo(123)\n}\n//│ mixin Test() {\n//│   class Foo(n: Int)\n//│   val f: Foo\n//│ }\n\nmodule M extends Test\n//│ module M {\n//│   class Foo(n: Int)\n//│   val f: Foo\n//│ }\n\nM.f\n//│ Foo\n//│ res\n//│     = Foo {}\n\nM.f.n\n//│ Int\n//│ res\n//│     = 123\n\n:e\nM.Foo\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.31: \tM.Foo\n//│ ╙──      \t ^^^^\n//│ error\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Foo],\n//│         unapply: [Function: unapply]\n//│       }\n\n:e // TODO support\nfun foo(x) = if x is M.Foo then 1\n//│ ╔══[ERROR] unknown pattern (M).Foo\n//│ ║  l.43: \tfun foo(x) = if x is M.Foo then 1\n//│ ╙──      \t                     ^^^^^\n//│ fun foo: anything -> 1\n\n:e\nmixin Test2 { let f = Foo(1) }\n//│ ╔══[ERROR] identifier not found: Foo\n//│ ║  l.50: \tmixin Test2 { let f = Foo(1) }\n//│ ╙──      \t                      ^^^\n//│ mixin Test2() {\n//│   let f: error\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol Foo\n\n:e\nmixin Test3 { fun f(x) = if x is Foo then 1 }\n//│ ╔══[ERROR] type identifier `Foo` not found\n//│ ║  l.61: \tmixin Test3 { fun f(x) = if x is Foo then 1 }\n//│ ╙──      \t                                 ^^^\n//│ ╔══[ERROR] type identifier not found: Foo\n//│ ║  l.61: \tmixin Test3 { fun f(x) = if x is Foo then 1 }\n//│ ╙──      \t                                 ^^^\n//│ mixin Test3() {\n//│   fun f: nothing -> error\n//│ }\n//│ Code generation encountered an error:\n//│   unknown match case: Foo\n\n\n\n:e\nmixin Test {\n  class Lit(n: Int)\n  class Add<A>(lhs: A, rhs: A) {\n    // Should be a lazy val only forceable when A has the right shape (constrained types?):\n    fun cached = size(this)\n  }\n  fun size(x) = if x is\n    Add(l, r) then this.size(l) + this.size(r)\n}\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.81: \t    fun cached = size(this)\n//│ ║        \t                 ^^^^^^^^^^\n//│ ╟── type variable `A` leaks out of its scope\n//│ ║  l.79: \t  class Add<A>(lhs: A, rhs: A) {\n//│ ╙──      \t            ^\n//│ mixin Test() {\n//│   this: {size: anything -> Int}\n//│   class Add[A](lhs: A, rhs: A) {\n//│     fun cached: Int | error\n//│   }\n//│   class Lit(n: Int)\n//│   fun size: Add[??A & 'a] -> Int\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/CommaOperator.mls",
    "content": ":NewDefs\n\n\n1; 2\n//│ 2\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n\n// :dp\n:js\n1, 2\n//│ 2\n//│ // Prelude\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ res = (1 , 2);\n//│ // End of generated code\n//│ res\n//│     = 2\n\n(1, 2)\n//│ 2\n//│ res\n//│     = 2\n\n(1, 2, 3)\n//│ 3\n//│ res\n//│     = 3\n\n1, ()\n//│ ()\n//│ res\n//│     = undefined\n\nlog(1), 2\n//│ 2\n//│ res\n//│     = 2\n//│ // Output\n//│ 1\n\n\n(),\n1\n//│ 1\n//│ res\n//│     = 1\n\n:pe\n(),\n1,\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.55: \t1,\n//│ ╙──      \t  ^\n//│ ()\n//│ res\n//│     = undefined\n\n(),\n  1\n//│ 1\n//│ res\n//│     = 1\n\n(),\n  log(\"ok\")\n  1\n//│ 1\n//│ res\n//│     = 1\n//│ // Output\n//│ ok\n\n:w\n(),\n  2 + 2\n  1\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in operator application:\n//│ ║  l.80: \t  2 + 2\n//│ ║        \t  ^^^^^\n//│ ╙── operator application of type `Int` does not match type `()`\n//│ 1\n//│ res\n//│     = 1\n\n(),\n  2 + 2, ()\n  1\n//│ 1\n//│ res\n//│     = 1\n\n\n\nlet a = 1, 2\n//│ let a: 2\n//│ a\n//│   = 2\n\nlet a = 1; 2\n//│ let a: 1\n//│ 2\n//│ a\n//│   = 1\n//│ res\n//│     = 2\n\n:pe // TODO support; make `;` have even less precedence than `,`\n(1;2)\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.115: \t(1;2)\n//│ ╙──       \t  ^\n//│ 1\n//│ res\n//│     = 1\n\n:pe\n(1,2;3)\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.124: \t(1,2;3)\n//│ ╙──       \t    ^\n//│ 2\n//│ res\n//│     = 2\n\n(log(1), 2)\n//│ 2\n//│ res\n//│     = 2\n//│ // Output\n//│ 1\n\n\n\nfun foo(x) = x\n//│ fun foo: forall 'a. 'a -> 'a\n\n:pe\nfoo(1;2)\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.145: \tfoo(1;2)\n//│ ╙──       \t     ^\n//│ 1\n//│ res\n//│     = 1\n\nfoo(let x = 1; x + 1)\n//│ Int\n//│ res\n//│     = 2\n\n:js\nfoo(let x = log(0), 1; log(x), x + 1)\n//│ Int\n//│ // Prelude\n//│ class TypingUnit20 {}\n//│ const typing_unit20 = new TypingUnit20;\n//│ // Query 1\n//│ res = foo(((x) => (log(x) , x + 1))((log(0) , 1)));\n//│ // End of generated code\n//│ res\n//│     = 2\n//│ // Output\n//│ 0\n//│ 1\n\n\n:js\nfoo((1, 2))\n//│ 2\n//│ // Prelude\n//│ class TypingUnit21 {}\n//│ const typing_unit21 = new TypingUnit21;\n//│ // Query 1\n//│ res = foo((1 , 2));\n//│ // End of generated code\n//│ res\n//│     = 2\n\nfoo(let x = 1; x + 1)\n//│ Int\n//│ res\n//│     = 2\n\nfoo(let x = 1 in x + 1)\n//│ Int\n//│ res\n//│     = 2\n\nfoo((log(1), 2))\n//│ 2\n//│ res\n//│     = 2\n//│ // Output\n//│ 1\n\nfoo(1), 2\n//│ 2\n//│ res\n//│     = 2\n\n\n:ge // FIXME\nlet rec x() = x() in x\n//│ nothing\n//│ Code generation encountered an error:\n//│   recursive non-function definition x is not supported\n\n\n:pe\nlet x[T] = 1 in x\n//│ ╔══[PARSE ERROR] Expected function parameter list; found square bracket section instead\n//│ ║  l.217: \tlet x[T] = 1 in x\n//│ ╙──       \t     ^^^\n//│ 1\n//│ res\n//│     = 1\n\n\nlet x = 2 in log(x), x + 1\n//│ Int\n//│ res\n//│     = 3\n//│ // Output\n//│ 2\n\nlet x = 2; log(x), x + 1\n//│ let x: 2\n//│ Int\n//│ x\n//│   = 2\n//│ res\n//│     = 3\n//│ // Output\n//│ 2\n\n\n\nfun foo(x, y) = [x, y]\n//│ fun foo: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n\nfoo(1,2)\n//│ [1, 2]\n//│ res\n//│     = [ 1, 2 ]\n\nfoo(log(1),2)\n//│ [(), 2]\n//│ res\n//│     = [ undefined, 2 ]\n//│ // Output\n//│ 1\n\nfoo(\n  log(1),\n  2\n)\n//│ [(), 2]\n//│ res\n//│     = [ undefined, 2 ]\n//│ // Output\n//│ 1\n\nfoo(\n  log(1),\n  2,\n)\n//│ [(), 2]\n//│ res\n//│     = [ undefined, 2 ]\n//│ // Output\n//│ 1\n\n:pe\n:e\nfoo(log(1);2)\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.282: \tfoo(log(1);2)\n//│ ╙──       \t          ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.282: \tfoo(log(1);2)\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]`\n//│ ║  l.282: \tfoo(log(1);2)\n//│ ║         \t   ^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.245: \tfun foo(x, y) = [x, y]\n//│ ╙──       \t       ^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│     = [ undefined, undefined ]\n//│ // Output\n//│ 1\n\n:e\nfoo((log(1),2))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.302: \tfoo((log(1),2))\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]`\n//│ ║  l.302: \tfoo((log(1),2))\n//│ ║         \t   ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.245: \tfun foo(x, y) = [x, y]\n//│ ╙──       \t       ^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│     = [ 2, undefined ]\n//│ // Output\n//│ 1\n\nfoo((let x = log(0), 1; log(x), x + 1), 2)\n//│ [Int, 2]\n//│ res\n//│     = [ 2, 2 ]\n//│ // Output\n//│ 0\n//│ 1\n\n:e\nfoo(let x = log(0), 1; log(x), x + 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.327: \tfoo(let x = log(0), 1; log(x), x + 1)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]`\n//│ ║  l.327: \tfoo(let x = log(0), 1; log(x), x + 1)\n//│ ║         \t   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.245: \tfun foo(x, y) = [x, y]\n//│ ╙──       \t       ^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│     = [ 2, undefined ]\n//│ // Output\n//│ 0\n//│ 1\n\n:e\nfoo(let x = log(0), 1 in log(x), x + 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.345: \tfoo(let x = log(0), 1 in log(x), x + 1)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]`\n//│ ║  l.345: \tfoo(let x = log(0), 1 in log(x), x + 1)\n//│ ║         \t   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.245: \tfun foo(x, y) = [x, y]\n//│ ╙──       \t       ^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│     = [ 2, undefined ]\n//│ // Output\n//│ 0\n//│ 1\n\n:e\nfoo(let x = log(0), 1; log(x), 1 + 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.363: \tfoo(let x = log(0), 1; log(x), 1 + 1)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]`\n//│ ║  l.363: \tfoo(let x = log(0), 1; log(x), 1 + 1)\n//│ ║         \t   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.245: \tfun foo(x, y) = [x, y]\n//│ ╙──       \t       ^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│     = [ 2, undefined ]\n//│ // Output\n//│ 0\n//│ 1\n\n:e\nfoo(if true then 1 else 2, 3)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.381: \tfoo(if true then 1 else 2, 3)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument of type `[1 | ?a]` does not match type `[?b, ?c]`\n//│ ║  l.381: \tfoo(if true then 1 else 2, 3)\n//│ ║         \t   ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.245: \tfun foo(x, y) = [x, y]\n//│ ╙──       \t       ^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│     = [ 1, undefined ]\n\nfoo((if true then 1 else 2), 3)\n//│ [1 | 2, 3]\n//│ res\n//│     = [ 1, 3 ]\n\n:e\nfoo(if true then log(\"ok\"), 1 else log(\"nok\"), 2, 3)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.401: \tfoo(if true then log(\"ok\"), 1 else log(\"nok\"), 2, 3)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument of type `[?a | ?b]` does not match type `[?c, ?d]`\n//│ ║  l.401: \tfoo(if true then log(\"ok\"), 1 else log(\"nok\"), 2, 3)\n//│ ║         \t   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.245: \tfun foo(x, y) = [x, y]\n//│ ╙──       \t       ^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│     = [ 1, undefined ]\n//│ // Output\n//│ ok\n\nfoo((if true then log(\"ok\"), 1 else log(\"nok\"), 2), 3)\n//│ [1 | 2, 3]\n//│ res\n//│     = [ 1, 3 ]\n//│ // Output\n//│ ok\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/CtorSubtraction.mls",
    "content": ":NewDefs\n\n\nclass Cls\n//│ class Cls {\n//│   constructor()\n//│ }\n\nfun x: ('a & Object) -> ('a \\ Cls)\nfun x = case\n  Cls then error\n  y then y\n//│ fun x: forall 'b. (Cls | Object & 'b & ~#Cls) -> 'b\n//│ fun x: forall 'a. (Object & 'a) -> ('a & ~Cls)\n\nx : Int -> Int\n//│ Int -> Int\n//│ res\n//│     = [Function: x]\n\nx : Cls -> nothing\n//│ Cls -> nothing\n//│ res\n//│     = [Function: x]\n\n\nfun x: (Int | Str | Cls) \\ Cls\nfun x = 42\n//│ fun x: 42\n//│ fun x: Int & ~Cls | Str & ~Cls\n\nx : Int | Str\n//│ Int | Str\n//│ res\n//│     = 42\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/CycleTypeDefErrors.mls",
    "content": ":NewDefs\n\n// * These type definitions should be checked for cyclicity, like we did in the old frontend,\n// * but this is currently not implemented.\n\n\ntype Foo = Foo\n//│ type Foo = Foo\n\n(f: Foo) => f : Str\n//│ (f: Foo) -> Str\n//│ res\n//│     = [Function: res]\n\n\ntype Foo = Foo & Int\n//│ type Foo = Foo & Int\n\n// FIXME\n(f: Foo) => f : Str\n//│ /!!!\\ Uncaught error: java.lang.StackOverflowError\n\n\nabstract class Foo: Foo\n//│ abstract class Foo: Foo\n\n// FIXME\n(f: Foo) => f : Str\n//│ /!!!\\ Uncaught error: java.lang.StackOverflowError\n\n\nabstract class Foo[T]: Foo[Int]\n//│ abstract class Foo[T]: Foo[Int]\n\n// FIXME\nfun test(f: Foo['a]) = f : Str\n//│ /!!!\\ Uncaught error: java.lang.StackOverflowError\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Darin.mls",
    "content": ":NewDefs\n\n\nclass Some[out A](val x: A)\n//│ class Some[A](x: A)\n\n\nlet s = Some(Some(42))\n//│ let s: Some[Some[42]]\n//│ s\n//│   = Some {}\n\n\n// * Expected error:\n\n:e\ns : Some[Int] | ()\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.17: \ts : Some[Int] | ()\n//│ ║        \t^\n//│ ╟── application of type `Some[?A]` is not an instance of type `Int`\n//│ ║  l.8: \tlet s = Some(Some(42))\n//│ ╙──     \t             ^^^^^^^^\n//│ Some[Int] | ()\n//│ res\n//│     = Some {}\n\n\n// * Yet, repeating the same code no longer yields the error:\n\ns : Some[Int] | ()\n//│ Some[Int] | ()\n//│ res\n//│     = Some {}\n\n// * This is because type inference sometimes takes some shortcuts (using a subtyping check instead of full constraining)\n// * that assume that previously-typed code was correctly typed\n// * (because subtyping checks may leverage previously-added bounds even when these were inconsistent).\n// * So this lack of repeated errors is not a soundness problem nor a bug.\n\n\n// * Note: a case where the shortcut does not currently trigger:\n\n:e\ns : Some[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.45: \ts : Some[Int]\n//│ ║        \t^\n//│ ╟── application of type `Some[?A]` is not an instance of `Int`\n//│ ║  l.8: \tlet s = Some(Some(42))\n//│ ║       \t             ^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.45: \ts : Some[Int]\n//│ ╙──      \t         ^^^\n//│ Some[Int]\n//│ res\n//│     = Some {}\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Dates.mls",
    "content": ":NewDefs\n\n\ndeclare class Date {\n  constructor(date: Num)\n  fun toString(): Str\n  fun toLocaleString(locales: Str | Array[Str], options: anything): Str\n}\n//│ declare class Date {\n//│   constructor(date: Num)\n//│   fun toLocaleString: (locales: Str | Array[Str], options: anything) -> Str\n//│   fun toString: () -> Str\n//│ }\n\nlet date1 = new Date(12345678)\n//│ let date1: Date\n//│ date1\n//│       = 1970-01-01T03:25:45.678Z\n\ndate1.toLocaleString(\"en-US\", { timeZone: \"America/New_York\" })\n//│ Str\n//│ res\n//│     = '12/31/1969, 10:25:45 PM'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/DecLit.mls",
    "content": ":NewDefs\n\n// Real Numbers\n// ============\n\n[0.5, 1.0, 3.14159]\n//│ [0.5, 1.0, 3.14159]\n//│ res\n//│     = [ 0.5, 1, 3.14159 ]\n\n[1e100, 1E100, 1e+100, 1E+100, 1E-11, 1e-10, 1E-2, 1e-2]\n//│ [1E+100, 1E+100, 1E+100, 1E+100, 1E-11, 1E-10, 0.01, 0.01]\n//│ res\n//│     = [\n//│         1e+100, 1e+100,\n//│         1e+100, 1e+100,\n//│          1e-11,  1e-10,\n//│           0.01,   0.01\n//│       ]\n\n[3.14e-10, 3.14E-10, 3.14e+10, 3.14E+10]\n//│ [3.14E-10, 3.14E-10, 3.14E+10, 3.14E+10]\n//│ res\n//│     = [ 3.14e-10, 3.14e-10, 31400000000, 31400000000 ]\n\n[0.5e-10, 0.5E-10, 0.5e+10, 0.5E+10]\n//│ [5E-11, 5E-11, 5E+9, 5E+9]\n//│ res\n//│     = [ 5e-11, 5e-11, 5000000000, 5000000000 ]\n\n// Separators in integral, fractional, and exponent parts.\n[12_34_56.0, 12_34_56.78_90]\n[1_2.3_4e-1_0, 1_2.3_4e+1_0, 1_2.3_4e1_0]\n[1_2.3_4E-1_0, 1_2.3_4E+1_0, 1_2.3_4E1_0]\n//│ [1.234E-9, 1.234E+11, 1.234E+11]\n//│ res\n//│     = [ 123456, 123456.789 ]\n//│ res\n//│     = [ 1.234e-9, 123400000000, 123400000000 ]\n//│ res\n//│     = [ 1.234e-9, 123400000000, 123400000000 ]\n\n// Conflict with tuple index selection.\n:pe\n.1\n//│ ╔══[PARSE ERROR] Unexpected selector in expression position\n//│ ║  l.45: \t.1\n//│ ╙──      \t^^\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.45: \t.1\n//│ ╙──      \t  ^\n//│ ()\n//│ res\n//│     = undefined\n\n// Corner cases.\n:pe\n0.E10\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the decimal point\n//│ ║  l.58: \t0.E10\n//│ ╙──      \t  ^\n//│ 0E+10\n//│ res\n//│     = 0\n\n:pe\n0.0E\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the exponent sign\n//│ ║  l.67: \t0.0E\n//│ ╙──      \t   ^\n//│ 0.0\n//│ res\n//│     = 0\n\n:pe\n0.0E+\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the exponent sign\n//│ ║  l.76: \t0.0E+\n//│ ╙──      \t    ^\n//│ 0.0\n//│ res\n//│     = 0\n\n:pe\n0E\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the exponent sign\n//│ ║  l.85: \t0E\n//│ ╙──      \t ^\n//│ 0\n//│ res\n//│     = 0\n\n:pe\n0E+\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the exponent sign\n//│ ║  l.94: \t0E+\n//│ ╙──      \t  ^\n//│ 0\n//│ res\n//│     = 0\n\n:pe\n1234E\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the exponent sign\n//│ ║  l.103: \t1234E\n//│ ╙──       \t    ^\n//│ 1234\n//│ res\n//│     = 1234\n\n:pe\n4378.\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the decimal point\n//│ ║  l.112: \t4378.\n//│ ╙──       \t     ^\n//│ 4378\n//│ res\n//│     = 4378\n\n:pe\n5.\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the decimal point\n//│ ║  l.121: \t5.\n//│ ╙──       \t  ^\n//│ 5\n//│ res\n//│     = 5\n\n:pe\n789.E\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the decimal point\n//│ ║  l.130: \t789.E\n//│ ╙──       \t    ^\n//│ ╔══[LEXICAL ERROR] Expect at least one digit after the exponent sign\n//│ ║  l.130: \t789.E\n//│ ╙──       \t    ^\n//│ 789\n//│ res\n//│     = 789\n"
  },
  {
    "path": "shared/src/test/diff/nu/Declarations.mls",
    "content": ":NewDefs\n\n\n\ndeclare fun btoa: nothing\ndeclare fun atob: nothing\n//│ fun btoa: nothing\n//│ fun atob: nothing\n\nlet str = btoa(\"hello\")\natob(str)\n//│ let str: nothing\n//│ nothing\n//│ str\n//│     = 'aGVsbG8='\n//│ res\n//│     = 'hello'\n\n\ndeclare module console {\n  fun error: Str -> unit\n}\n//│ declare module console {\n//│   fun error: Str -> unit\n//│ }\n\nconsole.error(\"hello\")\n//│ unit\n//│ res\n//│     = undefined\n//│ // Output\n//│ hello\n\n:e\nconsole.log(\"hello\")\n//│ ╔══[ERROR] Type `console` does not contain member `log`\n//│ ║  l.35: \tconsole.log(\"hello\")\n//│ ╙──      \t       ^^^^\n//│ error\n//│ res\n//│     = undefined\n\n\n\ndeclare module Foo {\n  fun foo: Int\n}\n//│ declare module Foo {\n//│   fun foo: Int\n//│ }\n\n:re\nFoo.foo\n//│ Int\n//│ res\n//│ Runtime error:\n//│   ReferenceError: Foo is not defined\n\n\ndeclare type A = Int\n//│ type A = Int\n\n42 : A\n//│ A\n//│ res\n//│     = 42\n\n\n\ndeclare class Sanitizer {\n  fun sanitizeFor(element: Str, input: Str): Str\n}\n//│ declare class Sanitizer {\n//│   constructor()\n//│   fun sanitizeFor: (element: Str, input: Str) -> Str\n//│ }\n\n:re\nlet s = new Sanitizer\n//│ let s: Sanitizer\n//│ s\n//│ Runtime error:\n//│   ReferenceError: Sanitizer is not defined\n\n\n\n// * TODO allow Buffer2 to be named Buffer...\n// :d\ndeclare module Buffer {\n  abstract class Buffer2 {\n    val length: Int\n  }\n  fun bar: Int\n  fun from(a: Array[Int]): Buffer2 = from(a)\n  // fun from1(a: Array[Int]): this.Buffer2 = from1(a) // FIXME\n  // fun from2(a: Array[Int]): Buffer.Buffer2 = from2(a) // FIXME\n}\n//│ declare module Buffer {\n//│   abstract class Buffer2 {\n//│     val length: Int\n//│   }\n//│   fun bar: Int\n//│   fun from: (a: Array[Int]) -> Buffer2\n//│ }\n\nlet b = Buffer.from([0, 1, 2])\n//│ let b: Buffer2\n//│ b\n//│   = <Buffer 00 01 02>\n\nb.length\n//│ Int\n//│ res\n//│     = 3\n\n\n\n\n:pe\ndeclare 42\n//│ ╔══[PARSE ERROR] Unexpected literal token after modifier\n//│ ║  l.120: \tdeclare 42\n//│ ╙──       \t        ^^\n//│ ╔══[PARSE ERROR] Unexpected literal token after modifier\n//│ ║  l.120: \tdeclare 42\n//│ ╙──       \t        ^^\n//│ 42\n//│ res\n//│     = 42\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/DiamondInherit.mls",
    "content": ":NewDefs\n\n\n\n\ntrait Foo[A] { fun foo: A }\n//│ trait Foo[A] {\n//│   fun foo: A\n//│ }\n\nmodule Bar extends Foo[Int | Bool], Foo[Int | Str] {\n  fun foo = 123\n}\n//│ module Bar extends Foo {\n//│   fun foo: 123\n//│ }\n\nBar.foo\n//│ 123\n//│ res\n//│     = 123\n\nBar : Foo['X]\n//│ Foo['X]\n//│   where\n//│     'X := Int | Str\n//│ res\n//│     = Bar { class: [class Bar extends Object] }\n\n(Bar : Foo['X]).foo\n//│ Int | Str\n//│ res\n//│     = 123\n\n\ntrait Foo[A] { fun foo: A; fun bar: A -> A }\n//│ trait Foo[A] {\n//│   fun bar: A -> A\n//│   fun foo: A\n//│ }\n\nmodule Bar extends Foo[Int | Bool], Foo[Int | Str] {\n  fun foo = 123\n  fun bar = id\n}\n//│ module Bar extends Foo {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: 123\n//│ }\n\nBar.bar\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\nBar : Foo['X]\n//│ Foo['X]\n//│   where\n//│     'X := Int | Str\n//│ res\n//│     = Bar { class: [class Bar extends Object] }\n\n\ntrait T1 extends Foo[Int | Bool]\n//│ trait T1 extends Foo {\n//│   fun bar: 'A -> 'A\n//│   fun foo: 'A\n//│ }\n//│ where\n//│   'A := Int | false | true\n\nmodule Bar extends T1, Foo[Int | Str] {\n  fun foo = 123\n  fun bar = id\n}\n//│ module Bar extends Foo, T1 {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: 123\n//│ }\n\n(Bar : Foo['X]).foo\n//│ Int | Str\n//│ res\n//│     = 123\n\n(Bar : Foo['X]).bar\n//│ ('X & (Int | Str)) -> (Int | Str | 'X)\n//│ res\n//│     = [Function: id]\n\n(Bar : T1).foo\n//│ Int | false | true\n//│ res\n//│     = 123\n\nlet f = (Bar : T1).bar\nf(true)\n//│ let f: ('A & (Int | false | true)) -> (Int | false | true | 'A)\n//│ Int | false | true\n//│ f\n//│   = [Function: id]\n//│ res\n//│     = true\n\n:e\nmodule Bar extends T1, Foo[Int | Str] {\n  fun foo = 123\n  fun bar(x) = x + 1\n}\n//│ ╔══[ERROR] Type mismatch in definition of method bar:\n//│ ║  l.108: \t  fun bar(x) = x + 1\n//│ ║         \t      ^^^^^^^^^^^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ║  l.64: \ttrait T1 extends Foo[Int | Bool]\n//│ ║        \t                           ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.108: \t  fun bar(x) = x + 1\n//│ ╙──       \t               ^\n//│ ╔══[ERROR] Type mismatch in definition of method bar:\n//│ ║  l.108: \t  fun bar(x) = x + 1\n//│ ║         \t      ^^^^^^^^^^^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ║  l.64: \ttrait T1 extends Foo[Int | Bool]\n//│ ║        \t                           ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.108: \t  fun bar(x) = x + 1\n//│ ╙──       \t               ^\n//│ ╔══[ERROR] Type mismatch in definition of method bar:\n//│ ║  l.108: \t  fun bar(x) = x + 1\n//│ ║         \t      ^^^^^^^^^^^^^^\n//│ ╟── type `Str` is not an instance of type `Int`\n//│ ║  l.106: \tmodule Bar extends T1, Foo[Int | Str] {\n//│ ║         \t                                 ^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.108: \t  fun bar(x) = x + 1\n//│ ╙──       \t               ^\n//│ module Bar extends Foo, T1 {\n//│   fun bar: Int -> Int\n//│   fun foo: 123\n//│ }\n\n\ntrait Base[A] { fun foo: A; fun bar: A -> A }\ntrait Derived1[A] extends Base[A]\ntrait Derived2 extends Base[[Int | Str, Int | Str]]\n//│ trait Base[A] {\n//│   fun bar: A -> A\n//│   fun foo: A\n//│ }\n//│ trait Derived1[A] extends Base {\n//│   fun bar: 'A -> 'A\n//│   fun foo: 'A\n//│ }\n//│ trait Derived2 extends Base {\n//│   fun bar: 'A0 -> 'A0\n//│   fun foo: 'A0\n//│ }\n//│ where\n//│   'A0 := [Int | Str, Int | Str]\n//│   'A := A\n\nclass Final extends Derived1[[Int, Int]], Derived2 {\n  fun foo = [123, 456]\n  fun bar([x, y]) = [error, error]\n}\n//│ class Final extends Base, Derived1, Derived2 {\n//│   constructor()\n//│   fun bar: ([anything, anything]) -> [nothing, nothing]\n//│   fun foo: [123, 456]\n//│ }\n\nclass Final extends Derived1[[Int, Int]], Derived2 {\n  fun foo = [123, 456]\n  fun bar([x, y]) = [y, x]\n}\n//│ class Final extends Base, Derived1, Derived2 {\n//│   constructor()\n//│   fun bar: forall 'a 'b. (['a, 'b]) -> ['b, 'a]\n//│   fun foo: [123, 456]\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/DidierNu.mls",
    "content": ":NewDefs\n\n\n// val k x y = y\n// val unify : A. B. A -> A -> B -> B\n//           = fun x y z -> k (fun z -> k (z x) (k (z y))) z\n// val a0 = (fun z -> z) (id : A. A -> A) 1\n// val a1 x = (fun z -> unify x (fst z) (snd z)) (id, (id : A. A -> A)) 1\n\n\nfun k(x, y) = y\n//│ fun k: forall 'a. (anything, 'a) -> 'a\n\nfun unify : 'A -> 'A -> 'B -> 'B\n//│ fun unify: forall 'B. anything -> anything -> 'B -> 'B\n\nfun unify = x => y => z => k(z => k(z(x), y => k(z(y), y)), z)\n//│ fun unify: forall 'a. anything -> anything -> 'a -> 'a\n\nfun unify = x => y => z => k of z => k(z(x), y => k of z(y), y), z\n//│ fun unify: forall 'a. anything -> anything -> 'a -> 'a\n\n\nfun a0 = (z => z) (id : forall 'A: 'A -> 'A) of 1\n//│ fun a0: 1\n\nfun fst([a, _]) = a\nfun snd([_, b]) = b\n//│ fun fst: forall 'a. (['a, anything]) -> 'a\n//│ fun snd: forall 'b. ([anything, 'b]) -> 'b\n\nfun a1(x) = (z => unify(x)(fst of z)(snd of z))([id, (id : forall 'A: 'A -> 'A)]) of 1\n//│ fun a1: anything -> 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Eduardo.mls",
    "content": ":NewDefs\n\n// https://twitter.com/LParreaux/status/1762843603804770408\n\n\ntype f =  forall 'a: ('a      ) -> 'a where 'a : Int\n//│ type f = forall 'a. (Int & 'a) -> 'a\n\ntype f = (forall 'a: ('a      ) -> 'a where 'a : Int)\n//│ type f = forall 'a. (Int & 'a) -> 'a\n\ntype g = forall 'a: ('a & Int) -> 'a\n//│ type g = forall 'a. (Int & 'a) -> 'a\n\n(id : f) : g\n//│ g\n//│ res\n//│     = [Function: id]\n\n\ntype f = (forall 'a: ('a      ) -> 'a where 'a : Int)\ntype g =  forall 'a: ('a & Int) -> 'a\n//│ type f = forall 'a. (Int & 'a) -> 'a\n//│ type g = forall 'a0. (Int & 'a0) -> 'a0\n\n(id : f) : g\n(id : g) : f\n//│ f\n//│ res\n//│     = [Function: id]\n//│ res\n//│     = [Function: id]\n\nx => (id : f)(x) : Int\n//│ Int -> Int\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/EncodedLists.mls",
    "content": ":NewDefs\n:NoJS\n\n\nclass List<A> {\n  fun match: forall 'res: (ifNil: () => 'res, ifCons: ('res, List[A]) => 'res) => 'res\n  fun match = error // TODO use self-type...\n}\nval Nil: List<nothing>\nval Cons: (head: 'a, tail: List<'a>) => List<'a>\n//│ class List[A] {\n//│   constructor()\n//│   fun match: forall 'res. (ifNil: () -> 'res, ifCons: ('res, List[A]) -> 'res) -> 'res\n//│ }\n//│ val Nil: List[nothing]\n//│ val Cons: forall 'a. (head: 'a, tail: List['a]) -> List['a]\n\nval x: List<Int>\n//│ val x: List[Int]\n\n// FIXME\nx: List<anything>\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.22: \tx: List<anything>\n//│ ║        \t^\n//│ ╙── expression of type `anything` is not an instance of type `Int`\n//│ List[anything]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Eql.mls",
    "content": ":NewDefs\n\n\nval x: Eql[Int]\n//│ val x: Eql[Int]\n//│ x\n//│   = <missing implementation>\n\nx === 1\n//│ Bool\n//│ res\n//│     = <no result>\n//│       x is not implemented\n\n:e\n1 === x\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.16: \t1 === x\n//│ ║        \t^^^^^^^\n//│ ╟── type `#Eql` is not an instance of type `Num`\n//│ ║  l.4: \tval x: Eql[Int]\n//│ ║       \t       ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Num`\n//│ ║  l.16: \t1 === x\n//│ ╙──      \t      ^\n//│ error | false | true\n//│ res\n//│     = <no result>\n//│       x is not implemented\n\n:e\nx === x\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.32: \tx === x\n//│ ║        \t^^^^^^^\n//│ ╟── type `#Eql` is not an instance of type `Int`\n//│ ║  l.4: \tval x: Eql[Int]\n//│ ║       \t       ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.32: \tx === x\n//│ ╙──      \t      ^\n//│ error | false | true\n//│ res\n//│     = <no result>\n//│       x is not implemented\n\n\nfun test1(x) =\n  x === x\n//│ fun test1: forall 'a. (Eql['a] & 'a) -> Bool\n\nfun test2(x, y) =\n  x === y\n//│ fun test2: forall 'a. (Eql['a], 'a) -> Bool\n\n\n1 : Eql['a]\n//│ Eql[Num]\n//│ res\n//│     = 1\n\n1 : Eql[Int]\n//│ Eql[Int]\n//│ res\n//│     = 1\n\n1 : Eql[1]\n//│ Eql[1]\n//│ res\n//│     = 1\n\ntest1(1)\n//│ Bool\n//│ res\n//│     = true\n\n:e\ntest1(x)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.78: \ttest1(x)\n//│ ║        \t^^^^^^^^\n//│ ╟── type `#Eql` is not an instance of type `Int`\n//│ ║  l.4: \tval x: Eql[Int]\n//│ ║       \t       ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.78: \ttest1(x)\n//│ ╙──      \t      ^\n//│ error | false | true\n//│ res\n//│     = <no result>\n//│       x is not implemented\n\n\nlet n: Int = 1\n//│ let n: Int\n//│ n\n//│   = 1\n\nn : Eql['a]\n//│ Eql[anything]\n//│ res\n//│     = 1\n\ntest1(n)\n//│ Bool\n//│ res\n//│     = true\n\n\nval n: Num\n//│ val n: Num\n//│ n\n//│   = <missing implementation>\n\ntest1(n)\n//│ Bool\n//│ res\n//│     = <no result>\n//│       n is not implemented\n\nlet d = 1/2\n//│ let d: Num\n//│ d\n//│   = 0.5\n\ntest1(d)\n//│ Bool\n//│ res\n//│     = true\n\ntest1(\"hello\")\n//│ Bool\n//│ res\n//│     = true\n\n\ntest2(0, 1)\n//│ Bool\n//│ res\n//│     = false\n\ntest2(0, d)\n//│ Bool\n//│ res\n//│     = false\n\nx => test2(0, x)\n//│ Num -> Bool\n//│ res\n//│     = [Function: res]\n\nx => test2(x, 0)\n//│ Eql[0] -> Bool\n//│ res\n//│     = [Function: res]\n\nx => test2(d, x)\n//│ anything -> Bool\n//│ res\n//│     = [Function: res]\n\nx => test2(x, d)\n//│ Eql[Num] -> Bool\n//│ res\n//│     = [Function: res]\n\n\n:e\ntest2(1, \"oops\")\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.169: \ttest2(1, \"oops\")\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `Num`\n//│ ║  l.169: \ttest2(1, \"oops\")\n//│ ║         \t         ^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.53: \t  x === y\n//│ ╙──      \t        ^\n//│ error | false | true\n//│ res\n//│     = false\n\n:e\ntest2(\"oops\", 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.184: \ttest2(\"oops\", 1)\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `Str`\n//│ ║  l.184: \ttest2(\"oops\", 1)\n//│ ║         \t              ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.53: \t  x === y\n//│ ╙──      \t        ^\n//│ error | false | true\n//│ res\n//│     = false\n\n:e\ntest2(1, {})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.199: \ttest2(1, {})\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── record literal of type `anything` is not an instance of type `Num`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.53: \t  x === y\n//│ ╙──      \t        ^\n//│ error | false | true\n//│ res\n//│     = false\n\n:e\ntest2({}, 1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.212: \ttest2({}, 1)\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── record literal of type `anything` is not an instance of type `Eql`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.53: \t  x === y\n//│ ╙──      \t  ^\n//│ error | false | true\n//│ res\n//│     = false\n\n:e\ntest2({}, {})\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.225: \ttest2({}, {})\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── record literal of type `anything` is not an instance of type `Eql`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.53: \t  x === y\n//│ ╙──      \t  ^\n//│ error | false | true\n//│ res\n//│     = false\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/EqlClasses.mls",
    "content": ":NewDefs\n\n\n\nmodule Mod\n//│ module Mod\n\n:e\nMod === Mod\n//│ ╔══[ERROR] Module 'Mod' does not support equality comparison because it does not have a parameter list\n//│ ║  l.9: \tMod === Mod\n//│ ╙──     \t^^^^^^^^^^^\n//│ error | false | true\n//│ res\n//│     = true\n\n\nclass Cls1()\n//│ class Cls1()\n\nCls1() === Cls1()\n//│ Bool\n//│ res\n//│     = false\n\n\nclass Cls2(x: Int)\n//│ class Cls2(x: Int)\n\n:e // TODO better error – or actually only support data classes\nCls2(0) === Cls2(1)\n//│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field\n//│ ║  l.27: \tclass Cls2(x: Int)\n//│ ║        \t           ^\n//│ ╟── Either make the parameter a `val` or access it through destructuring\n//│ ║  l.27: \tclass Cls2(x: Int)\n//│ ╙──      \t           ^\n//│ error | false | true\n//│ res\n//│     = false\n\n\nclass Cls2(val x: Int)\n//│ class Cls2(x: Int)\n\nCls2(0) === Cls2(1)\n//│ Bool\n//│ res\n//│     = false\n\n\n\nclass Pair[out A](val fst: A, val snd: A)\n//  extends (A <: Eql[A]) => Eql[Pair[A]]\n//│ class Pair[A](fst: A, snd: A)\n\nlet p = Pair(1, 2)\n//│ let p: Pair[1 | 2]\n//│ p\n//│   = Pair {}\n\np === p\n//│ Bool\n//│ res\n//│     = true\n\n\nx => p === x\n//│ {fst: Eql[1 | 2], snd: Eql[1 | 2]} -> Bool\n//│ res\n//│     = [Function: res]\n\nx => x === p\n//│ Eql[Pair[1 | 2]] -> Bool\n//│ res\n//│     = [Function: res]\n\np === { fst: 1, snd: 2 }\n//│ Bool\n//│ res\n//│     = false\n\n:e\n{ fst: 1, snd: 2 } === p\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.84: \t{ fst: 1, snd: 2 } === p\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{fst: 1, snd: 2}` is not an instance of type `Eql`\n//│ ║  l.84: \t{ fst: 1, snd: 2 } === p\n//│ ╙──      \t       ^^^^^^^^^\n//│ error | false | true\n//│ res\n//│     = false\n\nlet r = {x: 42, y: y => y}\n//│ let r: {x: 42, y: forall 'a. 'a -> 'a}\n//│ r\n//│   = { x: 42, y: [Function: y] }\n\nr : {x: Int}\n//│ {x: Int}\n//│ res\n//│     = { x: 42, y: [Function: y] }\n\n\n:e\nx => { a: 0 } === x\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.107: \tx => { a: 0 } === x\n//│ ║         \t     ^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{a: 0}` is not an instance of type `Eql`\n//│ ║  l.107: \tx => { a: 0 } === x\n//│ ╙──       \t          ^\n//│ anything -> (error | false | true)\n//│ res\n//│ Syntax error:\n//│   Unexpected token '==='\n\nx => x === { a: 0 }\n//│ Eql[{a: 0}] -> Bool\n//│ res\n//│     = [Function: res]\n\n\n\nlet q = Pair(1, \"oops\")\n//│ let q: Pair[\"oops\" | 1]\n//│ q\n//│   = Pair {}\n\n:e\nq === q\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.132: \tq === q\n//│ ║         \t^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `Str`\n//│ ║  l.126: \tlet q = Pair(1, \"oops\")\n//│ ╙──       \t             ^\n//│ error | false | true\n//│ res\n//│     = true\n\n\nclass Pair2[out A, out B](val fst: A, val snd: B)\n//│ class Pair2[A, B](fst: A, snd: B)\n\nlet q = Pair2(1, \"oops\")\n//│ let q: Pair2[1, \"oops\"]\n//│ q\n//│   = Pair2 {}\n\nq === q\n//│ Bool\n//│ res\n//│     = true\n\n\n\nclass MP[out Col](val color: Col)\n//│ class MP[Col](color: Col)\n\nval mp = MP(1)\n//│ val mp: MP[1]\n//│ mp\n//│    = MP {}\n\nmp === mp\n//│ Bool\n//│ res\n//│     = true\n\nfun cmp(lhs, rhs) = lhs.color === rhs.color\n//│ fun cmp: forall 'a. ({color: Eql['a]}, {color: 'a}) -> Bool\n\ncmp(mp, mp)\n//│ Bool\n//│ res\n//│     = true\n\nmodule Mix {\n  fun compare(lhs, rhs) = (lhs.color === rhs.color)\n}\nmodule Comp extends Mix\n//│ module Mix {\n//│   fun compare: forall 'a. ({color: Eql['a]}, {color: 'a}) -> Bool\n//│ }\n//│ module Comp extends Mix {\n//│   fun compare: forall 'b. ({color: Eql['b]}, {color: 'b}) -> Bool\n//│ }\n\nComp.compare(mp, mp)\n//│ Bool\n//│ res\n//│     = true\n\n\n\n\n// *** NOTES ***\n\n// * Intended type for comparing Cons:\n// Eql[Cons & { head: Eql['h], tail: Eql['t] } | ~Cons & List]\n\n\n// * Original code\n// x: Int\n// y: Int\n// x == y\n\n// * Refactored code (we want an error)\n// x: Option[Int]\n// y: Int\n// x == y\n// -->\n// x.exists(_ == y)\n\n// * Should not be equatable:\n// Int | Option[Int]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Eval.mls",
    "content": ":NewDefs\n\n\n\n// * Standard definitions:\n\n\ndeclare fun String: anything -> Str\n//│ fun String: anything -> Str\n\nfun (++) stringConcat(a, b) = concat(a)(b)\n//│ fun (++) stringConcat: (Str, Str) -> Str\n\nfun (|>) pipe(x, f) = f(x)\nfun (<|) pepi(f, x) = f(x)\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (<|) pepi: forall 'c 'd. ('c -> 'd, 'c) -> 'd\n\n\n// * Hack to throw exceptions\n:e\ndeclare class throw(arg: anything): nothing\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.22: \tdeclare class throw(arg: anything): nothing\n//│ ║        \t        ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#Throw & {arg: anything}` does not match type `nothing`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.22: \tdeclare class throw(arg: anything): nothing\n//│ ╙──      \t                                    ^^^^^^^\n//│ declare class throw(arg: anything): nothing\n\nfun raise(err) =\n  throw(err)\n  error\n//│ fun raise: anything -> nothing\n\n:re\nraise(1); 0\n//│ 0\n//│ res\n//│ Runtime error:\n//│   1\n//│ res\n//│     = 0\n\nfun test = raise(1); 0\n//│ fun test: nothing\n//│ 0\n//│ res\n//│     = 0\n\n:re\ntest\n//│ nothing\n//│ res\n//│ Runtime error:\n//│   1\n\nfun test = raise(1), 0\n//│ fun test: 0\n\n:re\ntest\n//│ 0\n//│ res\n//│ Runtime error:\n//│   1\n\nfun test =\n  raise(1)\n  error\n//│ fun test: nothing\n\n:re\ntest\n//│ nothing\n//│ res\n//│ Runtime error:\n//│   1\n\n\nabstract class Option[out A]: Some[A] | None\nclass Some[out A](val value: A) extends Option[A]\nmodule None extends Option[nothing]\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class List[out A]: (Cons[A] | Nil) { virtual val length: Int }\nclass Cons[out A](val head: A, val tail: List[A]) extends List[A] {\n  val length: Int\n  val length = tail.length + 1\n  fun toString() = \"Cons(\" ++ String(head) ++ \", \" ++ String(tail) ++ \")\"\n}\nmodule Nil extends List[nothing] {\n  val length = 0\n  fun toString() = \"Nil\"\n}\n//│ abstract class List[A]: Cons[A] | Nil {\n//│   val length: Int\n//│ }\n//│ class Cons[A](head: A, tail: List[A]) extends List {\n//│   val length: Int\n//│   fun toString: () -> Str\n//│ }\n//│ module Nil extends List {\n//│   val length: 0\n//│   fun toString: () -> \"Nil\"\n//│ }\n\nfun (::) cons(x, xs) = Cons(x, xs)\nfun (:::) concatList(xs, ys) = if xs is\n  Nil then ys\n  Cons(x, xs) then x :: xs ::: ys\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n//│ fun (:::) concatList: forall 'A0 'a. (Cons['A0] | Nil, List['A0] & 'a) -> (Cons['A0] | 'a)\n\nmodule Lists { // TODO use name List when module overloading is supported:\n  \n  fun map(f) = case\n    Nil then Nil\n    Cons(x, xs) then f(x) :: map(f)(xs)\n  \n  fun zip(xs, ys) = if xs is\n    Nil then Nil\n    Cons(x, xs) then if ys is\n      Nil then Nil\n      Cons(y, ys) then\n        [x, y] :: zip(xs, ys)\n  \n  fun assoc(e) = case\n    Cons(kv, rest) then\n      if kv.key === e then Some(kv.value)\n      else assoc(e)(rest)\n    Nil then None\n  \n}\n//│ module Lists {\n//│   fun assoc: forall 'a 'A. 'a -> (Cons[{key: Eql['a], value: 'A}] | Nil) -> (None | Some['A])\n//│   fun map: forall 'b 'A0. ('b -> 'A0) -> (Cons['b] | Nil) -> (Cons['A0] | Nil)\n//│   fun zip: forall 'c 'd. (Cons['c] | Nil, Cons['d] | Nil) -> (Cons[['c, 'd]] | Nil)\n//│ }\n\nlet xs = 1 :: 2 :: 3 :: Nil\n//│ let xs: Cons[1 | 2 | 3]\n//│ xs\n//│    = Cons {}\n\nString of xs ::: 4 :: 5 :: Nil\n//│ Str\n//│ res\n//│     = 'Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Nil)))))'\n\n\nlet ls = {key: \"a\", value: 0} :: Nil\n//│ let ls: Cons[{key: \"a\", value: 0}]\n//│ ls\n//│    = Cons {}\n\nls |> Lists.assoc(\"a\")\n//│ None | Some[0]\n//│ res\n//│     = Some {}\n\n\n\n// * Our little language:\n\n\n:e // * We don't yet support upper bounds on type parameters, so we can't provide the needed `out Sub <: Term`\nabstract class Term: Var | App | Lam | Sel | Rcd[Term] | Lit\nclass Var(val name: Str) extends Term\nclass App(val lhs: Term, val args: List[Term]) extends Term\nclass Lam(val params: List[Str], val body: Term) extends Term\nclass Rcd[out Sub](val fields: List[{key: Str, value: Sub}]) extends Term\nclass Sel(val prefix: Term, val fieldName: Str) extends Term\nabstract class Lit[out A](val value: A): IntLit | StrLit extends Term\nclass IntLit(v: Int) extends Lit[Int](v)\nclass StrLit(v: Str) extends Lit[Str](v)\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.175: \tclass Rcd[out Sub](val fields: List[{key: Str, value: Sub}]) extends Term\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Sub` is not an instance of type `Term`\n//│ ║  l.175: \tclass Rcd[out Sub](val fields: List[{key: Str, value: Sub}]) extends Term\n//│ ║         \t              ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.171: \tabstract class Term: Var | App | Lam | Sel | Rcd[Term] | Lit\n//│ ╙──       \t                                                 ^^^^\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.175: \tclass Rcd[out Sub](val fields: List[{key: Str, value: Sub}]) extends Term\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Sub` does not match type `App | Lam | #Lit | Rcd[Term] | Sel | Var`\n//│ ║  l.175: \tclass Rcd[out Sub](val fields: List[{key: Str, value: Sub}]) extends Term\n//│ ║         \t              ^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.171: \tabstract class Term: Var | App | Lam | Sel | Rcd[Term] | Lit\n//│ ║         \t                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.171: \tabstract class Term: Var | App | Lam | Sel | Rcd[Term] | Lit\n//│ ╙──       \t                                                 ^^^^\n//│ ╔══[ERROR] Type `Sub` does not contain member `Rcd#Sub`\n//│ ║  l.175: \tclass Rcd[out Sub](val fields: List[{key: Str, value: Sub}]) extends Term\n//│ ╙──       \t              ^^^\n//│ abstract class Term: App | Lam | Lit[anything] | Rcd[Term] | Sel | Var\n//│ class Var(name: Str) extends Term\n//│ class App(lhs: Term, args: List[Term]) extends Term\n//│ class Lam(params: List[Str], body: Term) extends Term\n//│ class Rcd[Sub](fields: List[{key: Str, value: Sub}]) extends Term\n//│ class Sel(prefix: Term, fieldName: Str) extends Term\n//│ abstract class Lit[A](value: A): IntLit | StrLit extends Term\n//│ class IntLit(v: Int) extends Lit, Term\n//│ class StrLit(v: Str) extends Lit, Term\n\n// * Workaround/alternative:\ntype Term = Var | App | Lam | Sel | Rcd[Term] | Lit\nclass Var(val name: Str)\nclass App(val lhs: Term, val args: List[Term])\nclass Lam(val params: List[Str], val body: Term)\nclass Rcd[out Sub](val fields: List[{key: Str, value: Sub}])\nclass Sel(val prefix: Term, val fieldName: Str)\nabstract class Lit[out A](val value: A): IntLit | StrLit\nclass IntLit(v: Int) extends Lit[Int](v)\nclass StrLit(v: Str) extends Lit[Str](v)\n//│ type Term = App | Lam | Lit[anything] | Rcd[Term] | Sel | Var\n//│ class Var(name: Str)\n//│ class App(lhs: Term, args: List[Term])\n//│ class Lam(params: List[Str], body: Term)\n//│ class Rcd[Sub](fields: List[{key: Str, value: Sub}])\n//│ class Sel(prefix: Term, fieldName: Str)\n//│ abstract class Lit[A](value: A): IntLit | StrLit\n//│ class IntLit(v: Int) extends Lit\n//│ class StrLit(v: Str) extends Lit\n\ntype Value = Lam | Lit | Rcd[Value]\n//│ type Value = Lam | Lit[anything] | Rcd[Value]\n\n\nfun err(msg) =\n  throw(concat(\"Evaluation error: \" ++ msg))\n  error\n//│ fun err: Str -> nothing\n\nfun eval(t, env) = if t is\n  Var(nme) then if env |> Lists.assoc(nme) is Some(v)\n    then v\n    else err(\"variable not found: \" ++ nme)\n  Lit then t\n  Lam then t\n  App(f, args) then\n    let fe = eval(f, env)\n    if fe is Lam(ps, bod) then\n      val argse = args |> Lists.map(a => eval(a, env))\n      if ps.length === argse.length then () else err(\"wrong number of arguments\")\n      let envp = Lists.zip(ps, argse) |> Lists.map of ([key, value]) => {key, value}\n      eval(bod, envp ::: env)\n    else err(String(fe) ++ \" cannot be applied\")\n  Sel(pre, nme) then\n    let pree = eval(pre, env)\n    if pree is Rcd(xs) and xs |> Lists.assoc(nme) is Some(v) then v\n    else err(String(pree) ++ \" does not have field \" ++ nme)\n  Rcd(fs) then\n    Rcd of fs |> Lists.map of {key, value} => {key, value: eval(value, env)}\n//│ fun eval: forall 'a 'b 'c. ('a, Cons[{key: Eql[Str], value: 'b}] & {List#A <: {key: Eql[Str], value: 'b}} & List[{key: Eql[Str], value: 'b}] | Nil & {List#A <: {key: Eql[Str], value: 'b}} & List[{key: Eql[Str], value: 'b}]) -> ('b | 'c)\n//│   where\n//│     'b :> 'c\n//│        <: Object & ~#Rcd | Rcd['b]\n//│     'c :> Lam | Lit[??A] | Rcd[Lam | Lit[??A] | 'b | 'c] | 'b\n//│     'a <: App | Lam | Lit[anything] | Rcd['a] | Sel | Var\n\neval : (Term, List[{key: Str, value: Value}]) -> Value\n//│ (Term, List[{key: Str, value: Value}]) -> Value\n//│ res\n//│     = [Function: eval]\n\nlet rcd = Rcd({key: \"a\", value: IntLit(0)} :: Nil)\n//│ let rcd: Rcd[IntLit]\n//│ rcd\n//│     = Rcd {}\n\neval of rcd, Nil\n//│ 'a\n//│   where\n//│     'a :> Lam | Lit[anything] | Rcd[Lam | Lit[anything] | 'a]\n//│ res\n//│     = Rcd {}\n\neval of Sel(rcd, \"a\"), Nil\n//│ 'a\n//│   where\n//│     'a :> Lam | Lit[??A] | Rcd[Lam | Lit[??A] | 'a]\n//│ res\n//│     = IntLit {}\n\neval of App(Lam(\"x\" :: Nil, Sel(Var(\"x\"), \"a\")), rcd :: Nil), Nil\n//│ 'a\n//│   where\n//│     'a :> Lam | Lit[??A] | Rcd[Lam | Lit[??A] | 'a]\n//│ res\n//│     = IntLit {}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/EvalNegNeg.mls",
    "content": ":NewDefs\n\n\nclass Add<out E>(lhs: E, rhs: E)\nclass Lit(n: Int)\n//│ class Add[E](lhs: E, rhs: E)\n//│ class Lit(n: Int)\n\n\nmixin EvalBase {\n  fun eval(e) =\n    if e is\n      Lit(n) then n: Int\n      Add(l, r) then this.eval(l) + this.eval(r)\n}\n//│ mixin EvalBase() {\n//│   this: {eval: 'a -> Int}\n//│   fun eval: (Add['a] | Lit) -> Int\n//│ }\n\n\nclass Neg<out A>(expr: A)\n//│ class Neg[A](expr: A)\n\n\nmixin EvalNeg {\n  fun eval(e) =\n    if e is Neg(d) then 0 - this.eval(d)\n    else super.eval(e)\n}\n//│ mixin EvalNeg() {\n//│   super: {eval: 'a -> 'b}\n//│   this: {eval: 'c -> Int}\n//│   fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b)\n//│ }\n\n\nmixin EvalNegNeg {\n  fun eval(e) =\n    if e is Neg(Neg(d)) then this.eval(d)\n    else super.eval(e)\n}\n//│ mixin EvalNegNeg() {\n//│   super: {eval: (Neg[nothing] | 'a) -> 'b}\n//│   this: {eval: 'c -> 'b}\n//│   fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b\n//│ }\n\n\nmodule TestLang extends EvalBase, EvalNeg, EvalNegNeg\n//│ module TestLang {\n//│   fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int\n//│ }\n//│ where\n//│   'A <: 'b & (Neg['b] | Object & ~#Neg)\n//│   'b <: Neg['A] | Object & 'a & ~#Neg\n//│   'a <: Add['b] | Lit | Neg['b]\n\n\nfun mk(n) = if n is\n  0 then Lit(3)\n  1 then Neg(mk(n - 1))\n  _ then Add(mk(n - 1), mk(n - 1))\n//│ fun mk: forall 'a. (0 | 1 | Int & ~0 & ~1) -> (Lit | 'a)\n//│   where\n//│     'a :> Add[Lit | 'a] | Neg[Lit | 'a]\n\nTestLang.eval(mk(0))\n//│ Int\n//│ res\n//│     = 3\n\nTestLang.eval(mk(11))\n//│ Int\n//│ res\n//│     = -3072\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ExplicitVariance.mls",
    "content": ":NewDefs\n\n\n\nclass Foo[out A](x: A)\n//│ class Foo[A](x: A)\n\nfun foo(x: Foo[Int]): Foo[Num] = x\n//│ fun foo: (x: Foo[Int]) -> Foo[Num]\n\n:e\nfun foo(x: Foo[Num]): Foo[Int] = x\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.12: \tfun foo(x: Foo[Num]): Foo[Int] = x\n//│ ║        \t                                 ^\n//│ ╟── type `Num` is not an instance of type `Int`\n//│ ║  l.12: \tfun foo(x: Foo[Num]): Foo[Int] = x\n//│ ║        \t               ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.12: \tfun foo(x: Foo[Num]): Foo[Int] = x\n//│ ╙──      \t                          ^^^\n//│ fun foo: (x: Foo[Num]) -> Foo[Int]\n\n\nclass Foo[in A](x: A -> Int)\n//│ class Foo[A](x: A -> Int)\n\nfun foo(x: Foo[Num]): Foo[Int] = x\n//│ fun foo: (x: Foo[Num]) -> Foo[Int]\n\n:e\nfun foo(x: Foo[Int]): Foo[Num] = x\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.32: \tfun foo(x: Foo[Int]): Foo[Num] = x\n//│ ║        \t                                 ^\n//│ ╟── type `Num` is not an instance of type `Int`\n//│ ║  l.32: \tfun foo(x: Foo[Int]): Foo[Num] = x\n//│ ║        \t                          ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.32: \tfun foo(x: Foo[Int]): Foo[Num] = x\n//│ ╙──      \t               ^^^\n//│ fun foo: (x: Foo[Int]) -> Foo[Num]\n\n\n\n// * Note that not checking variance annotations can actually be made sound in MLscript,\n// *  but this would be surprising for users, who would find type errors at the definition's use sites.\n\n\n// :e // TODO check variance annotations!\nclass Oops0[in A](val x: A)\n//│ class Oops0[A](x: A)\n\n// :e // TODO check variance annotations!\nclass Oops0[out A](val x: A -> Int)\n//│ class Oops0[A](x: A -> Int)\n\nlet o = Oops0(id)\n//│ let o: Oops0[nothing]\n//│ o\n//│   = Oops0 {}\n\n// * What used to happens is `Oops9{ A = nothing..'? }` was inferred for `o` (consistent with `A`'s covariance),\n// *  so all negative occurrences of `o.A` were viewed as `nothing` from the outside, resulting in `o.x : nothing -> Int`\n// * No lomnger the case since I simplified substitution for variant type arguments, to improve inferred type simplification.\no.x\n//│ Int -> Int\n//│ res\n//│     = [Function: id]\n\n// * Similarly, `Oops0[Int]` here used to expand to the equivalent `Oops0{ A = nothing..Int }`, giving `(o : Oops0[Int]).x : nothing -> Int`\n(o : Oops0[Int]).x\n//│ Int -> Int\n//│ res\n//│     = [Function: id]\n\n// * So code like this no longer reports an error:\n// :e\no.x(123)\n//│ Int\n//│ res\n//│     = 123\n\n// :e\n(o : Oops0[Int]).x(123)\n//│ Int\n//│ res\n//│     = 123\n\n\nclass Oops1[out A](val x: A -> A, val y: A)\n//│ class Oops1[A](x: A -> A, y: A)\n\nlet o = Oops1(id, 123)\n//│ let o: Oops1[123]\n//│ o\n//│   = Oops1 {}\n\no.x\n//│ 'A -> (123 | 'A)\n//│ res\n//│     = [Function: id]\n\n// :e\no.x(123)\n//│ 123\n//│ res\n//│     = 123\n\n:re\no.x(error) + 1\n//│ Int\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\nclass Oops2[out A](val x: A -> A, val y: A)\n//│ class Oops2[A](x: A -> A, y: A)\n\nlet o = Oops2(id, 123)\n//│ let o: Oops2[123]\n//│ o\n//│   = Oops2 {}\n\no.x\n//│ 'A -> (123 | 'A)\n//│ res\n//│     = [Function: id]\n\n// :e\no.x(123)\n//│ 123\n//│ res\n//│     = 123\n\n// :e // * We will be able to make this work later, through `o.x : o.A -> o.A` and `o.y : o.A`\no.x(o.y)\n//│ 123\n//│ res\n//│     = 123\n\n:re\no.x(error) + 1\n//│ Int\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ExpressionProblem_repro.mls",
    "content": ":NewDefs\n:NoJS\n\n\nclass Add0<out E>(lhs: E)\n//│ class Add0[E](lhs: E)\n\nfun eval(e) = if e is Add0(l) then eval(l)\n//│ fun eval: forall 'a. 'a -> nothing\n//│   where\n//│     'a <: Add0['a]\n\n\nclass Add<out E>(lhs: E, rhs: E)\nclass Lit(val value: Int)\n//│ class Add[E](lhs: E, rhs: E)\n//│ class Lit(value: Int)\n\nlet add11 = Add(Lit(1), Lit(2))\n//│ let add11: Add[Lit]\n\nfun eval(e) =\n  if e is\n    Lit(n) then n: Int\n    Add(l, r) then eval(l) + eval(r)\n//│ fun eval: forall 'a. 'a -> Int\n//│   where\n//│     'a <: Add['a] | Lit\n\n\nmixin EvalLit {\n  fun eval(e) =\n    if e is\n      Lit(n) then n\n}\n//│ mixin EvalLit() {\n//│   fun eval: Lit -> Int\n//│ }\n\nmixin EvalLit {\n  fun eval(e: Lit) = e.value\n}\n//│ mixin EvalLit() {\n//│   fun eval: (e: Lit) -> Int\n//│ }\n\n\nmixin EvalAdd {\n  fun eval(e) =\n    if e is\n      Add(l, r) then this.eval(l)\n}\n//│ mixin EvalAdd() {\n//│   this: {eval: 'a -> 'b}\n//│   fun eval: Add['a] -> 'b\n//│ }\n\nmodule TestLang extends EvalAdd\n//│ module TestLang {\n//│   fun eval: 'a -> nothing\n//│ }\n//│ where\n//│   'a <: Add['a]\n\nTestLang.eval\n//│ 'a -> nothing\n//│   where\n//│     'a <: Add['a]\n\n\n\nmixin EvalBase {\n  fun eval(e) =\n    if e is\n      Lit(n) then n: Int\n      Add(l, r) then this.eval(l) + this.eval(r)\n}\n//│ mixin EvalBase() {\n//│   this: {eval: 'a -> Int}\n//│   fun eval: (Add['a] | Lit) -> Int\n//│ }\n\n\nmodule TestLang extends EvalBase\n//│ module TestLang {\n//│   fun eval: 'a -> Int\n//│ }\n//│ where\n//│   'a <: Add['a] | Lit\n\nTestLang.eval\n//│ 'a -> Int\n//│   where\n//│     'a <: Add['a] | Lit\n\n\n\nadd11\n//│ Add[Lit]\n\nTestLang.eval(add11)\n//│ Int\n\nadd11\n//│ Add[Lit]\n\nTestLang.eval(add11)\n//│ Int\n\nadd11\n//│ Add[Lit]\n\n\n\nclass Neg<out A>(expr: A)\n//│ class Neg[A](expr: A)\n\nlet add2negadd11 = Add(Lit(2), Neg(add11))\n//│ let add2negadd11: Add[Lit | Neg[Add[Lit]]]\n\n\nmixin EvalNeg {\n  fun eval(e) =\n    if e is Neg(d) then 0 - this.eval(d)\n    else super.eval(e)\n}\n//│ mixin EvalNeg() {\n//│   super: {eval: 'a -> 'b}\n//│   this: {eval: 'c -> Int}\n//│   fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b)\n//│ }\n\n\nmodule TestLang extends EvalBase, EvalNeg\n//│ module TestLang {\n//│   fun eval: 'a -> Int\n//│ }\n//│ where\n//│   'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg\n\nTestLang.eval\n//│ 'a -> Int\n//│   where\n//│     'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg\n\n\nTestLang.eval(add11)\n//│ Int\n\nTestLang.eval(Neg(add11))\n//│ Int\n\nTestLang.eval(Add(Lit(2), Neg(Lit(1))))\n//│ Int\n\nTestLang.eval(Neg(Neg(add11)))\n//│ Int\n\n\nTestLang.eval(add2negadd11)\n//│ Int\n\nTestLang.eval(Add(Lit(2), Neg(add11)))\n//│ Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ExpressionProblem_small.mls",
    "content": ":NewDefs\n:NoJS\n\n\nclass Neg[out A](expr: A)\nclass Add[out E](lhs: E, rhs: E)\nclass Lit(n: Int)\n//│ class Neg[A](expr: A)\n//│ class Add[E](lhs: E, rhs: E)\n//│ class Lit(n: Int)\n\nlet add11 = Add(Lit(1), Lit(2))\nlet add2negadd11 = Add(Lit(2), Neg(add11))\n//│ let add11: Add[Lit]\n//│ let add2negadd11: Add[Lit | Neg[Add[Lit]]]\n\nmixin EvalNothing {\n  fun eval(e: nothing) = e\n}\nmixin EvalAddLit {\n  fun eval(e) =\n    if e is\n      Lit(n) then n\n      Add(l, r) then this.eval(l) + this.eval(r)\n    else super.eval(e)\n}\nmixin EvalNeg {\n  fun eval(e) =\n    if e is Neg(d) then 0 - this.eval(d)\n    else super.eval(e)\n}\n//│ mixin EvalNothing() {\n//│   fun eval: (e: nothing) -> nothing\n//│ }\n//│ mixin EvalAddLit() {\n//│   super: {eval: 'a -> 'b}\n//│   this: {eval: 'c -> Int}\n//│   fun eval: (Add['c] | Lit | Object & 'a & ~#Add & ~#Lit) -> (Int | 'b)\n//│ }\n//│ mixin EvalNeg() {\n//│   super: {eval: 'd -> 'e}\n//│   this: {eval: 'f -> Int}\n//│   fun eval: (Neg['f] | Object & 'd & ~#Neg) -> (Int | 'e)\n//│ }\n\nmodule TestLang extends EvalNothing, EvalAddLit, EvalNeg\n//│ module TestLang {\n//│   fun eval: 'a -> Int\n//│ }\n//│ where\n//│   'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg\n\nTestLang.eval\n//│ 'a -> Int\n//│   where\n//│     'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Extrusion.mls",
    "content": ":NewDefs\n\n\nfun f(y) =\n  let local = forall 'A: (x: 'A) =>\n    discard of y(x) + 1\n    x\n  y\n//│ fun f: forall 'a. (??A -> Int & 'a) -> 'a\n\n:e\nf(id)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.12: \tf(id)\n//│ ║        \t^^^^^\n//│ ╟── type variable `'A` leaks out of its scope\n//│ ║  l.5: \t  let local = forall 'A: (x: 'A) =>\n//│ ║       \t                     ^^\n//│ ╟── into application of type `Int`\n//│ ║  l.6: \t    discard of y(x) + 1\n//│ ║       \t               ^^^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.6: \t    discard of y(x) + 1\n//│ ╙──     \t               ^\n//│ forall 'a. error | 'a -> 'a\n//│ res\n//│     = [Function: id]\n\n\nfun f(y) =\n  let local = forall 'A: (x: 'A) =>\n    discard of (y : forall 'a: 'a -> 'a)(x)\n    x\n  y\n//│ fun f: forall 'b. (forall 'a. 'a -> 'a & 'b) -> 'b\n\nf(id)\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FieldRefinement.mls",
    "content": ":NewDefs\n:NoJS\n\n\nclass Foo(val x: Int) {\n  fun bar = x\n  fun baz: 1 | 2 = 1\n}\n//│ class Foo(x: Int) {\n//│   fun bar: Int\n//│   fun baz: 1 | 2\n//│ }\n\nval foo: Foo & { x: 0 | 1, bar: 0 | 1, baz: 0 | 1, y: Bool }\n//│ val foo: Foo & {y: Bool, bar: 0 | 1, baz: 0 | 1, x: 0 | 1}\n\nfoo.x\n//│ 0 | 1\n\nfoo.bar\n//│ 0 | 1\n\nfoo.baz\n//│ 1\n\nfoo.y\n//│ Bool\n\n:e\nfoo.z\n//│ ╔══[ERROR] Type `Foo & {y: Bool, bar: 0 | 1, baz: 0 | 1, x: 0 | 1}` does not contain member `z`\n//│ ║  l.30: \tfoo.z\n//│ ╙──      \t   ^^\n//│ error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FilterMap.mls",
    "content": ":NewDefs\n\n\n// * From https://arxiv.org/abs/2302.12783\n\n// 1 -spec filtermap ( fun (( T ) -> Boolean ()) , [ T ]) -> [ T ]\n// 2 ; ( fun (( T ) -> { true , U } | false ) , [ T ]) -> [ U ]\n// 3 ; ( fun (( T ) -> { true , U } | Boolean ()) , [ T ]) -> [ T | U ].\n// 4 filtermap ( _F , []) -> [];\n// 5 filtermap (F , [ X | XS ]) ->\n// 6 case F ( X ) of\n// 7 false -> filtermap (F , XS );\n// 8 true -> [ X | filtermap (F , XS )];\n// 9 { true , Y } -> [ Y | filtermap (F , XS )]\n// 10 end.\n\ntype List[A] = Cons[A] | Nil\nclass Cons[out A](head: A, tail: Cons[A] | Nil)\nmodule Nil\n//│ type List[A] = Cons[A] | Nil\n//│ class Cons[A](head: A, tail: Cons[A] | Nil)\n//│ module Nil\n\nfun (::) cons(h, t) = Cons(h, t)\n//│ fun (::) cons: forall 'A. ('A, Cons['A] | Nil) -> Cons['A]\n\nfun filtermap(f, xs: List['A]) = if xs is\n  Nil then Nil\n  Cons(y, ys) and f(y) is\n    false then filtermap(f, ys)\n    true then Cons(y, filtermap(f, ys))\n    [true, z] then Cons(z, filtermap(f, ys))\n//│ fun filtermap: forall 'A 'A0. ('A -> (Object & {0: true, 1: 'A0} & ~false & ~true | false | true), xs: List['A]) -> (Cons['A0] | Nil)\n//│   where\n//│     'A <: 'A0\n\nlet xs = 0 :: 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: Nil\n//│ let xs: Cons[0 | 1 | 2 | 3 | 4 | 5 | 6 | 7]\n//│ xs\n//│    = Cons {}\n\nfun f(x) = if x % 3 is\n  0 then [true, -x]\n  1 then false\n  _ then true\n//│ fun f: Int -> (Bool | [true, Int])\n\n:e // TODO: Records are not `Object`s\nfiltermap(f, xs)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.49: \tfiltermap(f, xs)\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `[true, ?a]` is not an instance of type `Object`\n//│ ║  l.43: \t  0 then [true, -x]\n//│ ║        \t         ^^^^^^^^^^\n//│ ╟── Note: constraint arises from `case` expression:\n//│ ║  l.30: \t    false then filtermap(f, ys)\n//│ ║        \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.31: \t    true then Cons(y, filtermap(f, ys))\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.32: \t    [true, z] then Cons(z, filtermap(f, ys))\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from application:\n//│ ║  l.29: \t  Cons(y, ys) and f(y) is\n//│ ╙──      \t                  ^^^^\n//│ Cons[Int] | Nil | error\n//│ res\n//│     = Cons {}\n\n\nmodule Tru\nmodule Fals\n//│ module Tru\n//│ module Fals\n\nclass Pair[A, B](lhs: A, rhs: B)\n//│ class Pair[A, B](lhs: A, rhs: B)\n\nfun filtermap(f, xs) = if xs is\n  Nil then Nil\n  Cons(y, ys) then if f(y) is\n    Tru then filtermap(f, ys)\n    Fals then Cons(y, filtermap(f, ys))\n    Pair(Tru, z) then Cons(z, filtermap(f, ys))\n//│ fun filtermap: forall 'a 'A. ('a -> (Fals | Pair[Tru, 'A] | Tru), Cons['a & 'A] | Nil) -> (Cons['A] | Nil)\n\nfun mkString(xs) =\n  if xs is\n    Nil then \"\"\n    Cons(x, xs') and xs' is\n      Nil then toString(x)\n      else concat(toString(x))(concat(\", \")(mkString(xs')))\n//│ fun mkString: (Cons[anything] | Nil) -> Str\n\nlet list = Cons(1, Cons(2, Cons(3, Cons(4, Cons(5, Cons(6, Cons(7, Nil)))))))\nmkString of list\n//│ let list: Cons[1 | 2 | 3 | 4 | 5 | 6 | 7]\n//│ Str\n//│ list\n//│      = Cons {}\n//│ res\n//│     = '1, 2, 3, 4, 5, 6, 7'\n\nmkString of filtermap(x => (if x % 2 == 0 then Tru else Fals), list)\nmkString of filtermap(x => (if x % 2 == 0 then Fals else Tru), list)\nmkString of filtermap(x => (if\n  x % 2 == 0 then Fals\n  x % 3 == 0 then Pair(Tru, x / 3)\n  else Tru), list)\n//│ Str\n//│ res\n//│     = '1, 3, 5, 7'\n//│ res\n//│     = '2, 4, 6'\n//│ res\n//│     = '2, 1, 4, 6'\n"
  },
  {
    "path": "shared/src/test/diff/nu/FlatIfThenElse.mls",
    "content": ":NewDefs\n\n\ntype Option[out A] = Some[A] | None\nclass Some[out A](val value: A)\nmodule None\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A)\n//│ module None\n\n\nfun test(x: Option[Int]) =\n  if x is None then [0, 0] else\n  log(x.value)\n  // ...\n  // do other things on the happy path\n  // ...\n  [x.value - 1, x.value + 1]\n//│ fun test: (x: Option[Int]) -> [Int, Int]\n\ntest(Some(10))\n//│ [Int, Int]\n//│ res\n//│     = [ 9, 11 ]\n//│ // Output\n//│ 10\n\n\nfun test(x: Option[Int]) =\n  if x is\n    None then [0, 0]\n    Some(value) then\n      log(value)\n      [value - 1, value + 1]\n//│ fun test: (x: Option[Int]) -> [Int, Int]\n\nfun test(x: Option[Int]) =\n  if x is\n    None then [0, 0]\n    Some(value)\n    then\n      log(value)\n      [value - 1, value + 1]\n//│ fun test: (x: Option[Int]) -> [Int, Int]\n\nfun test(x: Option[Int]) =\n  if x is\n    None then [0, 0]\n    Some(value)\n    then\n    log(value)\n    [value - 1, value + 1]\n//│ fun test: (x: Option[Int]) -> [Int, Int]\n\nfun test(x: Option[Int]) =\n  if x is\n    None then [0, 0]\n    Some(value) then\n    log(value)\n    [value - 1, value + 1]\n//│ fun test: (x: Option[Int]) -> [Int, Int]\n\n:pe // TODO support\nfun test(x: Option[Int]) =\n  if x is\n  None then [0, 0]\n  Some(value) then [value - 1, value + 1]\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.65: \t  if x is\n//│ ║        \t     ^^^^\n//│ ║  l.66: \t  None then [0, 0]\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.67: \t  Some(value) then [value - 1, value + 1]\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun test: (x: Option[Int]) -> ()\n\n:pe // TODO support\nfun test(x: Option[Int]) =\n  if x is\n  None then [0, 0]\n  Some(value) then\n  log(value)\n  [value - 1, value + 1]\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.79: \t  if x is\n//│ ║        \t     ^^^^\n//│ ║  l.80: \t  None then [0, 0]\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.81: \t  Some(value) then\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.82: \t  log(value)\n//│ ║        \t^^^^^^^^^^^^\n//│ ║  l.83: \t  [value - 1, value + 1]\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun test: (x: Option[Int]) -> ()\n\n// Q: Support?\n:pe\n:e\n:w\nfun test(x: Option[Int]) =\n  if x is\n    None then [0, 0]\n    Some(value)\n  then\n    log(value)\n    [value - 1, value + 1]\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword in expression position\n//│ ║  l.105: \t  then\n//│ ╙──       \t  ^^^^\n//│ ╔══[ERROR] Unexpected statement in an if block\n//│ ║  l.104: \t    Some(value)\n//│ ╙──       \t    ^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.102: \t  if x is\n//│ ║         \t     ^^^^\n//│ ║  l.103: \t    None then [0, 0]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Some[Int]` is not an instance of type `None`\n//│ ║  l.4: \ttype Option[out A] = Some[A] | None\n//│ ║       \t                     ^^^^^^^\n//│ ╟── but it flows into reference with expected type `None`\n//│ ║  l.102: \t  if x is\n//│ ║         \t     ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.103: \t    None then [0, 0]\n//│ ╙──       \t    ^^^^\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in if-else block:\n//│ ║  l.102: \t  if x is\n//│ ║         \t     ^^^^\n//│ ║  l.103: \t    None then [0, 0]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.104: \t    Some(value)\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `[0, 0]` does not match type `()`\n//│ ║  l.103: \t    None then [0, 0]\n//│ ║         \t              ^^^^^^\n//│ ╟── but it flows into expression in statement position with expected type `()`\n//│ ║  l.102: \t  if x is\n//│ ║         \t     ^^^^\n//│ ║  l.103: \t    None then [0, 0]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.104: \t    Some(value)\n//│ ╙──       \t^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: value\n//│ ║  l.106: \t    log(value)\n//│ ╙──       \t        ^^^^^\n//│ ╔══[ERROR] identifier not found: value\n//│ ║  l.107: \t    [value - 1, value + 1]\n//│ ╙──       \t     ^^^^^\n//│ ╔══[ERROR] identifier not found: value\n//│ ║  l.107: \t    [value - 1, value + 1]\n//│ ╙──       \t                ^^^^^\n//│ fun test: (x: Option[Int]) -> [Int, Int]\n//│ Code generation encountered an error:\n//│   unresolved symbol value\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FlatIndentFuns.mls",
    "content": ":NewDefs\n\n\nx =>\ny =>\nx + y\n//│ Int -> Int -> Int\n//│ res\n//│     = [Function: res]\n\nid of x =>\ny =>\nx + y\n//│ Int -> Int -> Int\n//│ res\n//│     = [Function (anonymous)]\n\nlet r = x =>\ny =>\nx + y\n//│ let r: Int -> Int -> Int\n//│ r\n//│   = [Function: r]\n\nr(1)(2)\n//│ Int\n//│ res\n//│     = 3\n\n(r of 1) of 2\n//│ Int\n//│ res\n//│     = 3\n\n:e\nr of 1 of 2\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.36: \tr of 1 of 2\n//│ ║        \t     ^^^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.36: \tr of 1 of 2\n//│ ╙──      \t     ^\n//│ Int -> Int\n//│ res\n//│ Runtime error:\n//│   TypeError: 1 is not a function\n\n\n// * Could support this too...\n:pe\nlet r =\nx =>\ny =>\nx + y\n//│ ╔══[PARSE ERROR] Unexpected newline in expression position\n//│ ║  l.51: \tlet r =\n//│ ║        \t       ^\n//│ ║  l.52: \tx =>\n//│ ╙──      \t\n//│ let r: Int -> Int -> Int\n//│ r\n//│   = [Function: r1]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FlatMonads.mls",
    "content": ":NewDefs\n\n\ndeclare fun String: anything -> Str\n//│ fun String: anything -> Str\n\n\nabstract class IO[A] {\n  fun bind(f) = Bind(this, f)\n  fun run: A\n}\nclass Pure[A](value: A) extends IO[A] {\n  fun run = value\n}\nclass Bind[A, B](underlying: IO[A], f: A -> IO[B]) extends IO[B] {\n  fun run = f(underlying.run).run\n}\n//│ abstract class IO[A] {\n//│   fun bind: forall 'B. (A -> IO['B]) -> Bind[A, 'B]\n//│   fun run: A\n//│ }\n//│ class Pure[A](value: A) extends IO {\n//│   fun bind: forall 'B0. ('A -> IO['B0]) -> Bind['A, 'B0]\n//│   fun run: A\n//│ }\n//│ class Bind[A, B](underlying: IO[A], f: A -> IO[B]) extends IO {\n//│   fun bind: forall 'B1. ('A0 -> IO['B1]) -> Bind['A0, 'B1]\n//│   fun run: B\n//│ }\n//│ where\n//│   'A0 := B\n//│   'A := A\n\nmodule readInt extends IO[Int] { fun run: Int = 42 }\nclass printLine(str: Str) extends IO[undefined] { fun run = log(str) }\n//│ module readInt extends IO {\n//│   fun bind: forall 'B. ('A -> IO['B]) -> Bind[Int & 'A, 'B]\n//│   fun run: Int\n//│ }\n//│ class printLine(str: Str) extends IO {\n//│   fun bind: forall 'B0. ('A0 -> IO['B0]) -> Bind[() & 'A0, 'B0]\n//│   fun run: ()\n//│ }\n//│ where\n//│   'A0 := ()\n//│   'A := Int\n\n\n// * Nested indent:\n\nval main =\n  printLine(\"Hi! Input two numbers: \").bind of _ =>\n    readInt.bind of n =>\n      readInt.bind of m =>\n        val sum = n + m\n        printLine(concat(\"The sum is: \")(String of sum)).bind of _ =>\n          Pure(sum)\n//│ val main: Bind[(), 'B]\n//│   where\n//│     'B :> Int\n//│ main\n//│      = Bind {}\n\nmain.run\n//│ Int\n//│ res\n//│     = 84\n//│ // Output\n//│ Hi! Input two numbers: \n//│ The sum is: 84\n\n\n// * Flat indent:\n\nval main =\n  printLine(\"Hi! Input two numbers: \").bind of _ =>\n  readInt.bind of n =>\n  readInt.bind of m =>\n  val sum = n + m\n  printLine(concat(\"The sum is: \")(String of sum)).bind of _ =>\n  Pure(sum)\n//│ val main: Bind[(), 'B]\n//│   where\n//│     'B :> Int\n//│ main\n//│      = Bind {}\n\nmain.run\n//│ Int\n//│ res\n//│     = 84\n//│ // Output\n//│ Hi! Input two numbers: \n//│ The sum is: 84\n\n\n// * TODO improve this error – missing provenance for '0-element tuple'\n:e\nprintLine(\"\").bind of [] => error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.99: \tprintLine(\"\").bind of [] => error\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `()` is not a 0-element tuple\n//│ ║  l.35: \tclass printLine(str: Str) extends IO[undefined] { fun run = log(str) }\n//│ ╙──      \t                                     ^^^^^^^^^\n//│ Bind[out (), 'B] | error\n//│ res\n//│     = Bind {}\n\n// * TODO improve this error (parameter list repr.)\n:e\nprintLine(\"\").bind of () => error\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.112: \tprintLine(\"\").bind of () => error\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `[?A]` does not match type `[]`\n//│ ║  l.15: \tclass Bind[A, B](underlying: IO[A], f: A -> IO[B]) extends IO[B] {\n//│ ╙──      \t                                       ^\n//│ Bind[(), 'B] | error\n//│ res\n//│     = Bind {}\n\n\nprintLine(\"\").bind of (()) => error\n//│ Bind[(), 'B]\n//│ res\n//│     = Bind {}\n\n\n// * Using a shortand operator for `bind`... What's the use of a `do` notation?! :^)\n\nfun (#>>) bind[A, B](x: IO[A], f: A -> IO[B]): IO[B] = x.bind(f)\n//│ fun (#>>) bind: forall 'A 'B. (x: IO['A], f: 'A -> IO['B]) -> IO['B]\n\nval main =\n  printLine(\"Hi! Input two numbers: \") #>> _ =>\n  readInt #>> n =>\n  readInt #>> m =>\n  val sum = n + m\n  printLine(concat(\"The sum is: \")(String of sum)) #>> _ =>\n  Pure(sum)\n//│ val main: IO['B]\n//│   where\n//│     'B :> Int\n//│ main\n//│      = Bind {}\n\nmain.run\n//│ Int\n//│ res\n//│     = 84\n//│ // Output\n//│ Hi! Input two numbers: \n//│ The sum is: 84\n\nfun loop =\n  printLine(\"Input a positive number: \") #>> _ =>\n  readInt #>> n =>\n  if n < 0 then loop else Pure(n)\n//│ fun loop: forall 'B. IO['B]\n//│   where\n//│     'B :> Int\n\nlet r = loop.run\n//│ let r: Int\n//│ r\n//│   = 42\n//│ // Output\n//│ Input a positive number: \n\n\n// * Using another shortand operator for `map`\n\nfun (>>) compose[A, B, C](f: A -> B, g: B -> C): A -> C = x => g(f(x))\nfun (#>) map[A, B](x: IO[A], f: A -> B): IO[B] = x.bind(f >> Pure)\n//│ fun (>>) compose: forall 'A 'B 'C. (f: 'A -> 'B, g: 'B -> 'C) -> 'A -> 'C\n//│ fun (#>) map: forall 'A0 'B0. (x: IO['A0], f: 'A0 -> 'B0) -> IO['B0]\n\nval main =\n  printLine(\"Hi! Input two numbers: \") #>> _ =>\n  readInt #>> n =>\n  readInt #>> m =>\n  val sum = n + m\n  printLine(concat(\"The sum is: \")(String of sum)) #> _ =>\n  sum\n//│ val main: IO['B]\n//│   where\n//│     'B :> Int\n//│ main\n//│      = Bind {}\n\n\n// * With no type annotations:\n\nfun (>>) compose(f, g) = x => g(f(x))\nfun (#>>) bind(x, f) = x.bind(f)\nfun (#>) map(x, f) = x.bind(f >> Pure)\n//│ fun (>>) compose: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c\n//│ fun (#>>) bind: forall 'd 'e. ({bind: 'd -> 'e}, 'd) -> 'e\n//│ fun (#>) map: forall 'f 'A 'g. ({bind: ('f -> Pure['A]) -> 'g}, 'f -> 'A) -> 'g\n\nval main =\n  printLine(\"Hi! Input two numbers: \") #>> _ =>\n  readInt #>> n =>\n  readInt #>> m =>\n  val sum = n + m\n  printLine(concat(\"The sum is: \")(String of sum)) #> _ =>\n  sum\n//│ val main: Bind[(), 'B]\n//│   where\n//│     'B :> Int\n//│ main\n//│      = Bind {}\n\nmain.run\n//│ Int\n//│ res\n//│     = 84\n//│ // Output\n//│ Hi! Input two numbers: \n//│ The sum is: 84\n\nfun loop =\n  printLine(\"Input a positive number: \") #>> _ =>\n  readInt #>> n =>\n  if n < 0 then loop else Pure(n)\n//│ fun loop: forall 'B. Bind[(), 'B]\n//│   where\n//│     'B :> Int\n\nlet r = loop.run\n//│ let r: Int\n//│ r\n//│   = 42\n//│ // Output\n//│ Input a positive number: \n\n\n// * Abstracting over the monad:\n\nfun main(ctx) =\n  ctx.printLine(\"Hi! Input two numbers: \") #>> _ =>\n  ctx.readInt #>> n =>\n  ctx.readInt #>> m =>\n  val sum = n + m\n  ctx.printLine(concat(\"The sum is: \")(String of sum)) #>> _ =>\n  ctx.pure(sum)\n//│ fun main: forall 'a 'b 'c 'd 'e. {\n//│   printLine: \"Hi! Input two numbers: \" -> {bind: (anything -> 'a) -> 'b} & Str -> {bind: (anything -> 'c) -> 'd},\n//│   pure: Int -> 'c,\n//│   readInt: {bind: (Int -> 'e) -> 'a & (Int -> 'd) -> 'e}\n//│ } -> 'b\n\nval defaultCtx = {printLine, readInt, pure: Pure}\n//│ val defaultCtx: {\n//│   printLine: (str: Str) -> printLine,\n//│   pure: forall 'A. (value: 'A) -> Pure['A],\n//│   readInt: readInt\n//│ }\n//│ defaultCtx\n//│            = {\n//│                printLine: [Function (anonymous)] {\n//│                  class: [class printLine extends IO],\n//│                  unapply: [Function: unapply]\n//│                },\n//│                readInt: readInt { class: [class readInt extends IO] },\n//│                pure: [Function (anonymous)] {\n//│                  class: [class Pure extends IO],\n//│                  unapply: [Function: unapply]\n//│                }\n//│              }\n\nmain(defaultCtx).run\n//│ Int\n//│ res\n//│     = 84\n//│ // Output\n//│ Hi! Input two numbers: \n//│ The sum is: 84\n\nfun loop(ctx) =\n  ctx.printLine(\"Input a positive number: \") #>> _ =>\n  ctx.readInt #>> n =>\n  if n < 0 then loop(ctx) else ctx.pure(n)\n//│ fun loop: forall 'a 'b 'c 'd. {\n//│   printLine: \"Input a positive number: \" -> {bind: (anything -> 'a) -> 'b},\n//│   pure: 'c -> 'd,\n//│   readInt: {bind: ((Num & 'c) -> ('b | 'd)) -> 'a}\n//│ } -> 'b\n\nlet r = loop(defaultCtx)\n//│ let r: Bind[(), 'B]\n//│   where\n//│     'B :> Int\n//│ r\n//│   = Bind {}\n\nlet r = loop(defaultCtx).run\n//│ let r: Int\n//│ r\n//│   = 42\n//│ // Output\n//│ Input a positive number: \n\n:e\nnot(r)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.306: \tnot(r)\n//│ ║         \t^^^^^^\n//│ ╟── type `Int` is not an instance of type `Bool`\n//│ ║  l.34: \tmodule readInt extends IO[Int] { fun run: Int = 42 }\n//│ ║        \t                          ^^^\n//│ ╟── but it flows into reference with expected type `Bool`\n//│ ║  l.306: \tnot(r)\n//│ ╙──       \t    ^\n//│ error | false | true\n//│ res\n//│     = false\n\n\n// * Note: using inferred parent type arguments\n\nmodule readInt extends IO { fun run = 42 }\nclass printLine(str: Str) extends IO { fun run = log(str) }\n//│ module readInt extends IO {\n//│   fun bind: forall 'B. ('A -> IO['B]) -> Bind['A, 'B]\n//│   fun run: 42\n//│ }\n//│ class printLine(str: Str) extends IO {\n//│   fun bind: forall 'B0. ('A0 -> IO['B0]) -> Bind['A0, 'B0]\n//│   fun run: ()\n//│ }\n//│ where\n//│   'A0 :> ()\n//│   'A :> 42\n\nval main =\n  printLine(\"Hi! Input two numbers: \").bind of _ =>\n  readInt.bind of n =>\n  readInt.bind of m =>\n  val sum = n + m\n  printLine(concat(\"The sum is: \")(String of sum)).bind of _ =>\n  Pure(sum)\n//│ val main: Bind[in 'A out () | 'A, 'B]\n//│   where\n//│     'B :> Int\n//│ main\n//│      = Bind {}\n\nmain\n//│ Bind[in 'A out () | 'A, 'B]\n//│   where\n//│     'B :> Int\n//│ res\n//│     = Bind {}\n\n\n:e\nlet r = printLine(\"\").bind of 0 => Pure(1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.359: \tlet r = printLine(\"\").bind of 0 => Pure(1)\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `()` does not match type `0`\n//│ ║  l.324: \tclass printLine(str: Str) extends IO { fun run = log(str) }\n//│ ║         \t                                                 ^^^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.359: \tlet r = printLine(\"\").bind of 0 => Pure(1)\n//│ ╙──       \t                              ^\n//│ let r: Bind[in 0 & 'A out () | 'A, 'B] | error\n//│   where\n//│     'B :> 1\n//│ r\n//│   = Bind {}\n\n:e\nlet r = printLine(\"\").bind of x =>\nlog(x.a)\nPure(1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.376: \tlet r = printLine(\"\").bind of x =>\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.377: \tlog(x.a)\n//│ ║         \t^^^^^^^^^\n//│ ║  l.378: \tPure(1)\n//│ ║         \t^^^^^^^\n//│ ╟── application of type `()` does not have field 'a'\n//│ ║  l.324: \tclass printLine(str: Str) extends IO { fun run = log(str) }\n//│ ║         \t                                                 ^^^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.377: \tlog(x.a)\n//│ ║         \t    ^^^\n//│ ╟── from reference:\n//│ ║  l.377: \tlog(x.a)\n//│ ╙──       \t    ^\n//│ let r: Bind[in {a: anything} & 'A out () | 'A, 'B] | error\n//│   where\n//│     'B :> 1\n//│ r\n//│   = Bind {}\n\n:re\nr.run\n//│ 1 | error\n//│ res\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading 'a')\n\n\n// * We can even technically support the following syntax...\n\n:NoJS // * TODO We'll need to support functions extended with fields\n\n// * An interface that describes monadic functions with a field `run`\ndeclare trait IO[A]: (forall 'b: (A -> IO['b]) -> IO['b]) {\n  fun run: A\n}\ndeclare fun pure: 'a -> IO['a]\ndeclare fun readInt: IO[Int]\ndeclare fun printLine: Str -> IO[()]\n//│ declare trait IO[A]: forall 'b. (A -> IO['b]) -> IO['b] {\n//│   fun run: A\n//│ }\n//│ fun printLine: Str -> IO[()]\n//│ fun pure: forall 'a. 'a -> IO['a]\n//│ fun readInt: IO[Int]\n\nval main =\n  printLine(\"Hi! Input two numbers: \") of _ =>\n  readInt of n =>\n  readInt of m =>\n  val sum = n + m\n  printLine(concat(\"The sum is: \")(String of sum)) of _ =>\n  pure(sum)\n//│ val main: IO['b]\n//│   where\n//│     'b :> Int\n\nmain.run\n//│ Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FlatMonads_repro.mls",
    "content": ":NewDefs\n\n\nabstract class IO[A] {\n  fun bind(f) = Bind(this, f)\n  fun hey = this\n  fun run: A\n}\nclass Bind[CC, AA](underlying: IO[CC], f: CC -> IO[AA]) extends IO[AA] {\n  fun run = f(underlying.run).run\n}\nclass Pure[A](value: A) extends IO[A] {\n  fun run = value\n}\n//│ abstract class IO[A] {\n//│   fun bind: forall 'AA. (A -> IO['AA]) -> Bind[A, 'AA]\n//│   fun hey: IO[A]\n//│   fun run: A\n//│ }\n//│ class Bind[CC, AA](underlying: IO[CC], f: CC -> IO[AA]) extends IO {\n//│   fun bind: forall 'AA0. ('A -> IO['AA0]) -> Bind['A, 'AA0]\n//│   fun hey: IO['A]\n//│   fun run: AA\n//│ }\n//│ class Pure[A](value: A) extends IO {\n//│   fun bind: forall 'AA1. ('A0 -> IO['AA1]) -> Bind['A0, 'AA1]\n//│   fun hey: IO['A0]\n//│   fun run: A\n//│ }\n//│ where\n//│   'A0 := A\n//│   'A := AA\n\nmodule readInt extends IO[Int] { fun run: Int = 42 }\n//│ module readInt extends IO {\n//│   fun bind: forall 'AA. ('A -> IO['AA]) -> Bind[Int & 'A, 'AA]\n//│   fun hey: IO['A]\n//│   fun run: Int\n//│ }\n//│ where\n//│   'A := Int\n\n\nlet ri(f) = Bind(Pure(42), f)\n// let ri(f) = Bind(Pure(42) : IO[Int], f)\n// let ri(f) = Bind(error : IO[Int], f)\n//│ let ri: forall 'CC 'AA. ('CC -> IO['AA]) -> Bind['CC, 'AA]\n//│   where\n//│     'CC :> 42\n//│ ri\n//│    = [Function: ri]\n\nri(Pure)\n//│ Bind['CC, 'AA]\n//│   where\n//│     'CC :> 42\n//│         <: 'AA\n//│     'AA :> 42\n//│ res\n//│     = Bind {}\n\nreadInt.bind\n//│ forall 'AA. (Int -> IO['AA]) -> Bind[Int, 'AA]\n//│ res\n//│     = [Function: bind]\n\nBind(readInt, Pure)\n//│ Bind[Int & 'AA, 'AA]\n//│   where\n//│     'AA :> Int\n//│ res\n//│     = Bind {}\n\n\n// TODO prevent JS method extrusion; force explicit use of eta epxansion\n\nlet b = readInt.bind : (Int -> IO['B]) -> Bind[Int, 'B]\n//│ let b: (Int -> IO['B]) -> Bind[Int, 'B]\n//│ b\n//│   = [Function: bind]\n\nlet b = readInt.bind : ('A -> IO['B]) -> Bind['A, 'B] where 'A : Int\n//│ let b: (Int -> IO['B]) -> Bind[Int, 'B]\n//│ b\n//│   = [Function: bind]\n\nlet b = readInt.bind : ('A -> IO['B]) -> Bind['A, 'B] where Int : 'A\n//│ let b: (Int -> IO['B]) -> Bind[Int, 'B]\n//│ b\n//│   = [Function: bind]\n\n\nlet r = b of Pure\n//│ let r: Bind[in Int & 'B out Int, 'B]\n//│   where\n//│     'B :> Int\n//│ r\n//│   = Bind {}\n\n:re // FIXME `undefined` due to JS method extrusion\nr.run\n//│ Int\n//│ res\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading 'run')\n\n\nlet r = readInt.bind of Pure\n//│ let r: Bind[in Int & 'AA out Int, 'AA]\n//│   where\n//│     'AA :> Int\n//│ r\n//│   = Bind {}\n\nr.run\n//│ Int\n//│ res\n//│     = 42\n\nx => readInt.bind of x\n//│ forall 'AA. (Int -> IO['AA]) -> Bind[Int, 'AA]\n//│ res\n//│     = [Function: res]\n\nreadInt.bind of Pure\n//│ Bind[in Int & 'AA out Int, 'AA]\n//│   where\n//│     'AA :> Int\n//│ res\n//│     = Bind {}\n\nreadInt: IO['a]\n//│ IO[Int]\n//│ res\n//│     = readInt { class: [class readInt extends IO] }\n\n(readInt : IO[Int]).bind\n//│ forall 'AA. (Int -> IO['AA]) -> Bind[Int, 'AA]\n//│ res\n//│     = [Function: bind]\n\nreadInt.run\n//│ Int\n//│ res\n//│     = 42\n\nx => Pure(x).run\n//│ forall 'run. 'run -> 'run\n//│ res\n//│     = [Function: res]\n\n\nfun loop0 = readInt.bind of Pure\nfun loop1 = readInt.bind of (Pure : Int => IO[Int])\nfun loop2 = readInt.bind of ((x: Int) => Pure(x))\nfun loop3 = readInt.bind of (x => Pure(x) : IO[Int])\n//│ fun loop0: forall 'AA. Bind[in Int & 'AA out Int, 'AA]\n//│ fun loop1: Bind[Int, Int]\n//│ fun loop2: forall 'AA0. Bind[Int, 'AA0]\n//│ fun loop3: Bind[Int, Int]\n//│ where\n//│   'AA0 :> Int\n//│   'AA :> Int\n\nfun (#>>) bindOp(x, f) = x.bind(f)\n//│ fun (#>>) bindOp: forall 'a 'b. ({bind: 'a -> 'b}, 'a) -> 'b\n\nfun loop =\n  readInt #>> n =>\n  Pure(n)\n//│ fun loop: forall 'AA. Bind[in Int & 'AA out Int, 'AA]\n//│   where\n//│     'AA :> Int\n\n\n\nval x: Bind['A, 'B] where undefined : 'A; 'A : 'B\n//│ val x: forall 'A 'B. Bind['A, 'B]\n//│   where\n//│     'A :> ()\n//│        <: 'B\n//│     'B :> ()\n//│ x\n//│   = <missing implementation>\n\nx.run\n//│ ()\n//│ res\n//│     = <no result>\n//│       x is not implemented\n\nval x: Bind['A, 'B] where 'A : undefined; 'A : 'B\n//│ val x: forall 'A 'B. Bind['A, 'B]\n//│   where\n//│     'A <: () & 'B\n//│ x\n//│   = <missing implementation>\n\nx.run\n//│ nothing\n//│ res\n//│     = <no result>\n//│       x is not implemented\n\nval x: Bind[Int, Bool]\n//│ val x: Bind[Int, Bool]\n//│ x\n//│   = <missing implementation>\n\n// :d\nx.run\n//│ Bool\n//│ res\n//│     = <no result>\n//│       x is not implemented\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FunPatterns.mls",
    "content": ":NewDefs\n:NoJS\n\n\nfun f(x, y) = x + y\n//│ fun f: (Int, Int) -> Int\n\n// FIXME array pattern...?!\nfun f1([x, y]) = x + y\nfun f2([x, y],) = x + y\nfun f3([[x, y,],],) = x + y\n//│ fun f1: ([Int, Int]) -> Int\n//│ fun f2: ([Int, Int]) -> Int\n//│ fun f3: ([[Int, Int]]) -> Int\n\n:e\nfun f3([(x, y,),],) = x + y\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.17: \tfun f3([(x, y,),],) = x + y\n//│ ╙──      \t        ^^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.17: \tfun f3([(x, y,),],) = x + y\n//│ ╙──      \t                      ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.17: \tfun f3([(x, y,),],) = x + y\n//│ ╙──      \t                          ^\n//│ fun f3: ([error]) -> Int\n\n\nclass Pair(lhs: Int, rhs: Int)\n//│ class Pair(lhs: Int, rhs: Int)\n\n:e // * TODO\nfun f(Pair(x, y)) = x + y\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.34: \tfun f(Pair(x, y)) = x + y\n//│ ╙──      \t      ^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.34: \tfun f(Pair(x, y)) = x + y\n//│ ╙──      \t                    ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.34: \tfun f(Pair(x, y)) = x + y\n//│ ╙──      \t                        ^\n//│ fun f: error -> Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FunPoly.mls",
    "content": ":NewDefs\n\n\n\nfun id(x) = x\n//│ fun id: forall 'a. 'a -> 'a\n\n[id(1), id(true)]\n//│ [1, true]\n//│ res\n//│     = [ 1, true ]\n\nnot(id(true))\n//│ Bool\n//│ res\n//│     = false\n\n\n\nfun id(x) = x\n[id(1), id(true)]\n//│ fun id: forall 'a. 'a -> 'a\n//│ [1, true]\n//│ res\n//│     = [ 1, true ]\n\n\n\n// * Currently, we type entire typing units monomorphically;\n// * later we should try to separate mutually-recursive components and generalize them independently.\nfun test = [id(1), id(true)]\nfun id(x) = x\n//│ fun test: forall 'a 'b. [1 | true | 'a, 1 | true | 'b]\n//│ fun id: forall 'a 'b. ('b & 'a) -> (1 | true | 'a)\n\n[id(1), id(true)]\n//│ [1 | true, 1 | true]\n//│ res\n//│     = [ 1, true ]\n\n:e\nnot(id(true))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.42: \tnot(id(true))\n//│ ║        \t^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `Bool`\n//│ ║  l.31: \tfun test = [id(1), id(true)]\n//│ ║        \t               ^\n//│ ╟── but it flows into application with expected type `Bool`\n//│ ║  l.42: \tnot(id(true))\n//│ ╙──      \t    ^^^^^^^^\n//│ error | false | true\n//│ res\n//│     = false\n\n\n\nfun test = [Helper.id(1), Helper.id(true)]\nmodule Helper {\n  fun id(x) = x\n}\n//│ fun test: [1, true]\n//│ module Helper {\n//│   fun id: forall 'a. 'a -> 'a\n//│ }\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FunSigs.mls",
    "content": ":NewDefs\n\n\n\nfun log(msg: Str): ()\n//│ fun log: (msg: Str) -> ()\n\nlet f =\n  log(\"ok\")\n  123\n//│ let f: 123\n//│ f\n//│   = <no result>\n//│     log is not implemented\n\nfun log: Str -> unit\n//│ fun log: Str -> unit\n\nfun log: Str => unit\n//│ fun log: Str -> unit\n\nlog(\"ok\")\n//│ unit\n//│ res\n//│     = <no result>\n//│       log is not implemented\n\n\n\nfun con: Str => Str => Str\nfun con = concat\n//│ fun con: Str -> Str -> Str\n//│ fun con: Str -> Str -> Str\n\ncon(\"aa\")(\"bbb\")\n//│ Str\n//│ res\n//│     = 'aabbb'\n\n\nfun con: Str => Str => Str\n//│ fun con: Str -> Str -> Str\n\nfun con = concat\n//│ fun con: Str -> Str -> Str\n\ncon(\"aa\")(\"bbb\")\n//│ Str\n//│ res\n//│     = 'aabbb'\n\n\n\nfun oops: Str => Str\n//│ fun oops: Str -> Str\n\nfun oops = 0\n//│ fun oops: 0\n\noops\n//│ 0\n//│ res\n//│     = 0\n\n\n:e\nfun oops: Str => Str\nfun oops = 0\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.68: \tfun oops = 0\n//│ ║        \t    ^^^^^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.68: \tfun oops = 0\n//│ ║        \t           ^\n//│ ╟── but it flows into definition of method oops with expected type `Str -> Str`\n//│ ║  l.68: \tfun oops = 0\n//│ ║        \t    ^^^^^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.67: \tfun oops: Str => Str\n//│ ╙──      \t          ^^^^^^^^^^\n//│ fun oops: 0\n//│ fun oops: Str -> Str\n\noops\n//│ Str -> Str\n//│ res\n//│     = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FunnyIndet.mls",
    "content": ":NewDefs\n\n\n2 +\n  2 *\n    3\n//│ Int\n//│ res\n//│     = 8\n\n2 -\n  3 -\n    4\n//│ Int\n//│ res\n//│     = 3\n\n2 +\n  2\n//│ Int\n//│ res\n//│     = 4\n\n2 +\n2\n//│ Int\n//│ res\n//│     = 4\n\n\n2 is\n  2\n//│ Bool\n//│ res\n//│     = true\n\nif 2 is 2 then true\n//│ true\n//│ res\n//│     = true\n\n2 is\n2\n//│ Bool\n//│ res\n//│     = true\n\n\nif 2 is\n2 then true\n//│ true\n//│ res\n//│     = true\n\n:pe // TODO support\nif 2 is\n2 then true\n1 then false\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.58: \t1 then false\n//│ ╙──      \t^^^^^^^^^^^^\n//│ ()\n//│ res\n//│     = true\n//│ res\n//│     = undefined\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/FunnyPoly.mls",
    "content": ":NewDefs\n:NoJS\n\n// * A bunch of semi-random polymorphism and extrusion tests.\n// * Some of them yield very ugly types. (They might improve once we use proper wildcard args.)\n// * I've been trying to reproduce/trigger the incompleteness of constraint solving\n// * for constraints like `MyClass[S] & ?b <: MyClass[T]` where ?b is a lower-level type variable.\n\n\n\nfun test(x: (forall 'a: 'a -> 'a) & 'b) =\n  let foo(y) =\n    x(y)\n  foo\n//│ fun test: forall 'a 'b 'c. (x: forall 'a0. 'a0 -> 'a0 & ~('a -> 'a) | 'a0 -> 'a0 & 'b -> 'c) -> 'b -> 'c\n\n\ntype Id = forall 'a: 'a -> 'a\n//│ type Id = forall 'a. 'a -> 'a\n\nfun test(x: Id & 'b) =\n  let foo(y) = x(y)\n  foo\n//│ fun test: forall 'b 'c 'a. (x: Id & 'b -> 'c | Id & ~('a -> 'a)) -> 'b -> 'c\n\nfun test(x: Int | 'b) =\n  let foo(y) = (if true then x else y) : (Int | 'c)\n  foo\n//│ fun test: forall 'c. (x: Int | 'c) -> (forall 'c0. (Int | 'c0) -> (Int | 'c | 'c0))\n\n\n\nclass Ref[T](x: T -> T)\n//│ class Ref[T](x: T -> T)\n\nclass MyClass[A](x: A -> A)\n//│ class MyClass[A](x: A -> A)\n\n// Note: precedence of & is lower than that of ->\nfun mk: forall 'b: (Ref['b]) -> MyClass[Int] & 'b\n// fun mk(x) = error\n//│ fun mk: forall 'b. Ref['b] -> MyClass[Int] & 'b\n\n(x, y) => mk(x, y)\n//│ (anything, anything) -> nothing\n\nfun mk: forall 'a, 'b: (Ref['a], Ref['b]) -> (MyClass['a] & 'b)\n//│ fun mk: forall 'a 'b. (Ref['a], Ref['b]) -> (MyClass['a] & 'b)\n\nfun test(x, y) = mk(x, y)\n//│ fun test: forall 'a 'b. (Ref['a], Ref['b]) -> (MyClass['a] & 'b)\n\n:ns\ntest\n//│ forall 'c 'd 'e 'a 'b. ('c, 'd) -> 'e\n//│   where\n//│     'e :> MyClass['a] & 'b\n//│     'd <: Ref['b]\n//│     'c <: Ref['a]\n\n\n\nfun test(x, y) =\n  let tmp = mk(x, y)\n  tmp\n//│ fun test: forall 'a 'b. (Ref['a], Ref['b]) -> (MyClass['a] & 'b)\n\nfun test(x, y) =\n  let tmp = mk(x, y)\n  let foo(z) = mk(z, tmp)\n  foo\n//│ fun test: forall 'a 'b 'b0. (Ref['a], Ref['b]) -> (forall 'a0. Ref['a0] -> (MyClass['a0] & 'b0))\n//│   where\n//│     'b <: Ref[?] | Ref[?] & ~{MyClass#A = 'a} | Ref['b0] | ~MyClass['a]\n\nfun test(x, y) =\n  let tmp = mk(x, y)\n  let foo(z) = mk(z, tmp) : MyClass['x]\n  foo\n//│ fun test: forall 'a 'b 'b0 'a0 'a1 'a2 'x. (Ref['a], Ref['b]) -> (forall 'a3 'x0. Ref['a3] -> MyClass['x0])\n//│   where\n//│     'x0 <: 'x\n//│     'a3 :> 'a2 | 'a1\n//│         <: 'a0\n//│     'b <: Ref[?] | Ref[?] & ~{MyClass#A = 'a} | Ref[in 'b0 out 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1} | MyClass[in 'x out nothing] | {MyClass#A :> 'x <: nothing} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1})] & {\n//│       Ref#T :> 'b0 <: 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1 <: 'a2 | 'a1} | MyClass[in 'x out nothing] | {MyClass#A = 'x} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1 <: 'a2 | 'a0 | 'a1})\n//│     } | ~MyClass['a]\n\nfun test(x, y) =\n  let tmp = mk(x, y)\n  let foo(z) = mk(z, tmp) : MyClass['x]\n  [tmp, foo]\n//│ fun test: forall 'a 'b 'b0 'a0 'a1 'a2 'x. (Ref['a], Ref['b]) -> [MyClass['a] & 'b, forall 'a3 'x0. Ref['a3] -> MyClass['x0]]\n//│   where\n//│     'x0 <: 'x\n//│     'a3 :> 'a2 | 'a1\n//│         <: 'a0\n//│     'b <: Ref[?] | Ref[?] & ~{MyClass#A = 'a} | Ref[in 'b0 out 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1} | MyClass[in 'x out nothing] | {MyClass#A :> 'x <: nothing} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1})] & {\n//│       Ref#T :> 'b0 <: 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1 <: 'a2 | 'a1} | MyClass[in 'x out nothing] | {MyClass#A = 'x} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1 <: 'a2 | 'a0 | 'a1})\n//│     } | ~MyClass['a]\n\n\n\nfun ref: 'a -> Ref['a]\n//│ fun ref: forall 'a. 'a -> Ref['a]\n\nfun test(x, y) =\n  let tmp = ref(mk(x, y))\n  let foo(z) = mk(z, tmp)\n  foo\n//│ fun test: forall 'a 'b. (Ref['a], Ref['b]) -> (forall 'a0. Ref['a0] -> (MyClass[in 'a0 | 'a out 'a & 'a0] & 'b))\n\nfun test(x, y) =\n  let tmp = ref(mk(x, y))\n  let foo(z) = mk(z, tmp) : MyClass['x]\n  foo\n//│ fun test: forall 'a 'b 'a0 'a1 'a2 'a3 'x 'x0. (Ref['a], Ref['b]) -> (forall 'a4 'x1. Ref['a4] -> MyClass['x1])\n//│   where\n//│     'x1 :> 'x0\n//│         <: 'x\n//│     'a4 :> 'a2 | 'a1\n//│         <: 'a0 & 'a3\n//│     'b <: MyClass[?] & ~{MyClass#A :> 'a0 & 'a1 | 'a <: 'a & ('a2 | 'a1 | 'a3)} | MyClass[in 'x out 'x & 'x0] | {MyClass#A :> 'x <: 'x & 'x0} & ~{MyClass#A :> 'a2 | 'a <: 'a & ('a2 | 'a0)} | ~MyClass[in 'a | 'a2 & ('a0 & 'a1 | 'a) out 'a & ('a2 | 'a0 | 'a1 | 'a3)]\n\n\n\nfun refined': forall 'A, 'B: (r: 'A) -> ('A & Ref['B])\n//│ fun refined': forall 'A 'B. (r: 'A) -> (Ref['B] & 'A)\n\nfun test(x: 'x) =\n  let foo() = refined'(x)\n  foo\n//│ fun test: forall 'x. (x: 'x) -> (forall 'B. () -> (Ref['B] & 'x))\n\n// fun refined': forall 'A, 'B, 'C: (r: 'A, s: 'B) -> ('A & 'B & Ref['C])\nfun refined': forall 'A, 'B, 'C: (r: 'A, s: 'B) -> ('A & 'B)\n//│ fun refined': forall 'A 'B. (r: 'A, s: 'B) -> ('A & 'B)\n\nfun test(x: 'x) =\n  let foo(y: Ref['r] & 'y) = y\n  foo(x)\n//│ fun test: forall 'r 'y. (x: Ref['r] & 'y) -> (Ref['r] & 'y)\n\nfun test(x: 'x) =\n  let foo(y) = refined'(x, y) : Ref['r]\n  foo\n//│ fun test: forall 'B 'r. (x: Ref[?] & ~'B | Ref[in 'r out nothing] | ~'B) -> (forall 'r0. 'B -> Ref['r0])\n//│   where\n//│     'r0 <: 'r\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/GADTMono.mls",
    "content": ":NewDefs\n\ntrait Expr[A]: LitInt | LitBool | Add | Cond | Pair | Fst | Snd\nclass LitInt(n: Int) extends Expr[Int]\nclass LitBool(b: Bool) extends Expr[Bool]\nclass Add(x: Expr[Int], y: Expr[Int]) extends Expr[Int]\nclass Cond[T](p: Expr[Bool], t: Expr[T], e: Expr[T]) extends Expr[T]\nclass Pair[S, T](a: Expr[S], b: Expr[T]) extends Expr[[S, T]]\nclass Fst[S, T](p: Expr[[S, T]]) extends Expr[S]\nclass Snd[S, T](p: Expr[[S, T]]) extends Expr[T]\n//│ trait Expr[A]: Add | Cond[?] | Fst[?, ?] | LitBool | LitInt | Pair[?, ?] | Snd[?, ?]\n//│ class LitInt(n: Int) extends Expr\n//│ class LitBool(b: Bool) extends Expr\n//│ class Add(x: Expr[Int], y: Expr[Int]) extends Expr\n//│ class Cond[T](p: Expr[Bool], t: Expr[T], e: Expr[T]) extends Expr\n//│ class Pair[S, T](a: Expr[S], b: Expr[T]) extends Expr\n//│ class Fst[S, T](p: Expr[[S, T]]) extends Expr\n//│ class Snd[S, T](p: Expr[[S, T]]) extends Expr\n\nlet l1 = LitInt(1)\n//│ let l1: LitInt\n//│ l1\n//│    = LitInt {}\n\n// TODO\nclass Exp[type A]\n//│ ╔══[PARSE ERROR] Unexpected 'type' keyword here\n//│ ║  l.26: \tclass Exp[type A]\n//│ ╙──      \t          ^^^^\n//│ class Exp {\n//│   constructor()\n//│ }\n\nl1: Expr[Int]\n//│ Expr[Int]\n//│ res\n//│     = LitInt {}\n\n:e\nl1: Expr[Bool]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.40: \tl1: Expr[Bool]\n//│ ║        \t^^\n//│ ╟── type `Int` is not an instance of type `Bool`\n//│ ║  l.4: \tclass LitInt(n: Int) extends Expr[Int]\n//│ ║       \t                                  ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.40: \tl1: Expr[Bool]\n//│ ╙──      \t         ^^^^\n//│ Expr[Bool]\n//│ res\n//│     = LitInt {}\n\n// FIXME\nfun eval[A](e: Expr[A]): A =\n    if \n        e is LitInt(n) then n\n        e is LitBool(b) then b\n        e is Add(x, y) then eval(x) + eval(y)\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.57: \t        e is LitInt(n) then n\n//│ ║        \t        ^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.58: \t        e is LitBool(b) then b\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.59: \t        e is Add(x, y) then eval(x) + eval(y)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `#Expr & (Add & {Expr#A = A} | Cond[?] & {Expr#A = A} | Fst[?, ?] & {Expr#A = A} | LitBool & {Expr#A = A} | LitInt & {Expr#A = A} | Pair[?, ?] & {Expr#A = A} | Snd[?, ?] & {Expr#A = A})` does not match type `Add | LitBool | LitInt`\n//│ ║  l.55: \tfun eval[A](e: Expr[A]): A =\n//│ ║        \t               ^^^^^^^\n//│ ╟── but it flows into reference with expected type `Add | LitBool | LitInt`\n//│ ║  l.57: \t        e is LitInt(n) then n\n//│ ╙──      \t        ^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.57: \t        e is LitInt(n) then n\n//│ ║        \t        ^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.58: \t        e is LitBool(b) then b\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.59: \t        e is Add(x, y) then eval(x) + eval(y)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Int` does not match type `A`\n//│ ║  l.4: \tclass LitInt(n: Int) extends Expr[Int]\n//│ ║       \t                ^^^\n//│ ╟── but it flows into reference with expected type `A`\n//│ ║  l.57: \t        e is LitInt(n) then n\n//│ ║        \t                            ^\n//│ ╟── Note: constraint arises from method type parameter:\n//│ ║  l.55: \tfun eval[A](e: Expr[A]): A =\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.55: \tfun eval[A](e: Expr[A]): A =\n//│ ║        \t    ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.56: \t    if \n//│ ║        \t^^^^^^^\n//│ ║  l.57: \t        e is LitInt(n) then n\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.58: \t        e is LitBool(b) then b\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.59: \t        e is Add(x, y) then eval(x) + eval(y)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Int` does not match type `A`\n//│ ║  l.6: \tclass Add(x: Expr[Int], y: Expr[Int]) extends Expr[Int]\n//│ ║       \t                                ^^^\n//│ ╟── Note: constraint arises from method type parameter:\n//│ ║  l.55: \tfun eval[A](e: Expr[A]): A =\n//│ ╙──      \t         ^\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.55: \tfun eval[A](e: Expr[A]): A =\n//│ ║        \t    ^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.56: \t    if \n//│ ║        \t^^^^^^^\n//│ ║  l.57: \t        e is LitInt(n) then n\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.58: \t        e is LitBool(b) then b\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.59: \t        e is Add(x, y) then eval(x) + eval(y)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `A` is not an instance of type `Int`\n//│ ║  l.55: \tfun eval[A](e: Expr[A]): A =\n//│ ║        \t         ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.6: \tclass Add(x: Expr[Int], y: Expr[Int]) extends Expr[Int]\n//│ ╙──     \t                                ^^^\n//│ fun eval: forall 'A. (e: Expr['A]) -> 'A\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/GenericClassInheritance.mls",
    "content": ":NewDefs\n\nclass Room[A](name: Str) {\n    virtual fun foo(x: A) = x\n}\n//│ class Room[A](name: Str) {\n//│   fun foo: (x: A) -> A\n//│ }\n\nclass BigRoom extends Room[Bool](\"big\")\n//│ class BigRoom extends Room {\n//│   constructor()\n//│   fun foo: (x: 'A) -> 'A\n//│ }\n//│ where\n//│   'A := Bool\n\n// * Note that this essentially infers Room[Bool]\nclass InferredRoom extends Room(\"infer\") {\n    fun foo(x) = x && true\n}\n//│ class InferredRoom extends Room {\n//│   constructor()\n//│   fun foo: Bool -> Bool\n//│ }\n\n(new InferredRoom) : Room['X]\n//│ Room['X]\n//│   where\n//│     'X := Bool\n//│ res\n//│     = InferredRoom {}\n\n:e\nclass TooManyRoom extends Room[Int, Str](\"too many\")\n//│ ╔══[ERROR] class Room expects 1 type parameter(s); got 2\n//│ ║  l.35: \tclass TooManyRoom extends Room[Int, Str](\"too many\")\n//│ ╙──      \t                          ^^^^^^^^^^^^^\n//│ class TooManyRoom extends Room {\n//│   constructor()\n//│   fun foo: (x: 'A) -> 'A\n//│ }\n//│ where\n//│   'A := Int\n\n:e\nclass WrongRoom extends Room[Bool](\"wrong\") {\n    fun foo(x) = x + 1\n}\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ║        \t        ^^^^^^^^^^^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ║  l.47: \tclass WrongRoom extends Room[Bool](\"wrong\") {\n//│ ║        \t                             ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ╙──      \t                 ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ║        \t        ^^^^^^^^^^^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ║  l.47: \tclass WrongRoom extends Room[Bool](\"wrong\") {\n//│ ║        \t                             ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ╙──      \t                 ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ║        \t        ^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Int` is not an instance of type `Bool`\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ║        \t                 ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.47: \tclass WrongRoom extends Room[Bool](\"wrong\") {\n//│ ║        \t                             ^^^^\n//│ ╟── from reference:\n//│ ║  l.4: \t    virtual fun foo(x: A) = x\n//│ ╙──     \t                            ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ║        \t        ^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Int` does not match type `Bool`\n//│ ║  l.48: \t    fun foo(x) = x + 1\n//│ ║        \t                 ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.47: \tclass WrongRoom extends Room[Bool](\"wrong\") {\n//│ ║        \t                             ^^^^\n//│ ╟── from reference:\n//│ ║  l.4: \t    virtual fun foo(x: A) = x\n//│ ╙──     \t                            ^\n//│ class WrongRoom extends Room {\n//│   constructor()\n//│   fun foo: Int -> Int\n//│ }\n\n\nabstract class C0[A] { val a: A }\n//│ abstract class C0[A] {\n//│   val a: A\n//│ }\n\nclass C1[A] extends C0[A] { val a = a }\n//│ class C1[A] extends C0 {\n//│   constructor()\n//│   val a: nothing\n//│ }\n\nnew C1() : C1[Int]\n//│ C1[Int]\n//│ res\n//│     = C1 {}\n\n(new C1() : C1[Int]) : C0['X]\n//│ C0[Int]\n//│ res\n//│     = C1 {}\n\nnew C1().a\n//│ nothing\n//│ res\n//│     = undefined\n\n\nmixin M1[A] {\n    fun f1(x: A): A = x\n    fun f2(x: A): [A, A] = [x, x]\n}\n//│ mixin M1[A]() {\n//│   fun f1: (x: A) -> A\n//│   fun f2: (x: A) -> [A, A]\n//│ }\n\nclass A1 extends M1 {\n    fun f1(x: Int) = x\n}\n//│ class A1 {\n//│   constructor()\n//│   fun f1: (x: Int) -> Int\n//│   fun f2: (x: 'A) -> ['A, 'A]\n//│ }\n\nclass A2[S, T] extends M1[[S, T]]\n//│ class A2[S, T] {\n//│   constructor()\n//│   fun f1: (x: [S, T]) -> [S, T]\n//│   fun f2: (x: [S, T]) -> [[S, T], [S, T]]\n//│ }\n\nclass A3(f1: Bool => Bool) extends M1\n//│ class A3(f1: Bool -> Bool) {\n//│   fun f1: (x: 'A) -> 'A\n//│   fun f2: (x: 'A) -> ['A, 'A]\n//│ }\n\nmixin M2[A] {\n    fun m: A = this.a\n}\n//│ mixin M2[A]() {\n//│   this: {a: A}\n//│   fun m: A\n//│ }\n\nclass B1(val a: Int) extends M2[Int]\n//│ class B1(a: Int) {\n//│   fun m: Int\n//│ }\n\nclass B2[A](val a: Int => A) extends M2\n//│ class B2[A](a: Int -> A) {\n//│   fun m: Int -> A\n//│ }\n\n:e\nclass E1(val a: Int) extends M2[Bool]\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.175: \tclass E1(val a: Int) extends M2[Bool]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `Int` is not an instance of type `Bool`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.175: \tclass E1(val a: Int) extends M2[Bool]\n//│ ║         \t                                ^^^^\n//│ ╟── from field selection:\n//│ ║  l.157: \t    fun m: A = this.a\n//│ ╙──       \t               ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.175: \tclass E1(val a: Int) extends M2[Bool]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `Int` does not match type `Bool`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.175: \tclass E1(val a: Int) extends M2[Bool]\n//│ ║         \t                                ^^^^\n//│ ╟── from field selection:\n//│ ║  l.157: \t    fun m: A = this.a\n//│ ╙──       \t               ^^^^^^\n//│ class E1(a: Int) {\n//│   fun m: Bool\n//│ }\n"
  },
  {
    "path": "shared/src/test/diff/nu/GenericClasses.mls",
    "content": ":NewDefs\n\n\nclass C<A>\n//│ class C[A] {\n//│   constructor()\n//│ }\n\nfun f(x) = if x is C then x\n//│ fun f: forall 'A. C['A] -> C['A]\n\n// * TODO parse class tags?\n// f(C : #C)\n\n\nclass C<out A>(val a: A)\n//│ class C[A](a: A)\n\nlet c = C(1)\n//│ let c: C[1]\n//│ c\n//│   = C {}\n\nc.a\n//│ 1\n//│ res\n//│     = 1\n\nfun f(x) = if x is C(a) then a\n//│ fun f: forall 'a. C['a] -> 'a\n\nf(c)\n//│ 1\n//│ res\n//│     = 1\n\n\nclass C[A](val n: A) {\n  fun f = this.n\n  fun g = C(12).n\n}\n//│ class C[A](n: A) {\n//│   fun f: A\n//│   fun g: 12\n//│ }\n\n\nclass Some<out A>(val value: A) {\n  fun get = value\n  fun toArray = [value]\n  fun map(f) = Some(f(value))\n  fun map_A(f : A => 'b) = Some(f(value))\n}\n//│ class Some[A](value: A) {\n//│   fun get: A\n//│   fun map: forall 'A. (A -> 'A) -> Some['A]\n//│   fun map_A: forall 'A0. (A -> 'A0) -> Some['A0]\n//│   fun toArray: [A]\n//│ }\n\n\nlet s = Some(1)\n//│ let s: Some[1]\n//│ s\n//│   = Some {}\n\n\ns.value\n//│ 1\n//│ res\n//│     = 1\n\ns.get\n//│ 1\n//│ res\n//│     = 1\n\ns.toArray\n//│ [1]\n//│ res\n//│     = [ 1 ]\n\n\ns.map\n//│ forall 'A. (1 -> 'A) -> Some['A]\n//│ res\n//│     = [Function: map]\n\ns.map(succ)\n//│ Some[Int]\n//│ res\n//│     = Some {}\n\n\ns.map_A\n//│ forall 'A. (1 -> 'A) -> Some['A]\n//│ res\n//│     = [Function: map_A]\n\ns.map_A(succ)\n//│ Some[Int]\n//│ res\n//│     = Some {}\n\n\n\nmodule None {\n  fun get = error\n  fun toArray = []\n  fun map(f) = None\n  fun map_A(f: nothing -> anything) = None\n}\n//│ module None {\n//│   fun get: nothing\n//│   fun map: anything -> None\n//│   fun map_A: (f: nothing -> anything) -> None\n//│   fun toArray: []\n//│ }\n\n\nNone.toArray\n//│ []\n//│ res\n//│     = []\n\n\ntype Option<A> = Some<A> | None\n//│ type Option[A] = None | Some[A]\n\n\n\nlet opt = if true then Some(123) else None\n//│ let opt: None | Some[123]\n//│ opt\n//│     = Some {}\n\nopt.toArray\n//│ Array[123]\n//│ res\n//│     = [ 123 ]\n\n\nopt.map(succ)\n//│ None | Some[Int]\n//│ res\n//│     = Some {}\n\nopt.map_A(succ)\n//│ None | Some[Int]\n//│ res\n//│     = Some {}\n\nopt.map(x => x > 0)\n//│ None | Some[Bool]\n//│ res\n//│     = Some {}\n\n\n\nif opt is Some then opt.value else 0\n//│ 0 | 123\n//│ res\n//│     = 123\n\nif opt is Some(v) then v else 0\n//│ 0 | 123\n//│ res\n//│     = 123\n\n\nfun map(x, f) = if x is\n  None then None\n  Some(v) then Some(f(v))\n//│ fun map: forall 'a 'A. (None | Some['a], 'a -> 'A) -> (None | Some['A])\n\nlet mo = map(opt, succ)\n//│ let mo: None | Some[Int]\n//│ mo\n//│    = Some {}\n\nmo.toArray\n//│ Array[Int]\n//│ res\n//│     = [ 124 ]\n\n\n\n// TODO\nclass Test(n) {\n  fun foo = n + 1\n  fun bar = n\n}\n//│ ╔══[ERROR] Class parameters currently need type annotations\n//│ ║  l.189: \tclass Test(n) {\n//│ ╙──       \t           ^\n//│ class Test(n: error) {\n//│   fun bar: error\n//│   fun foo: Int\n//│ }\n\nTest(1)\n//│ Test\n//│ res\n//│     = Test {}\n\n// :e\nTest(true)\n//│ Test\n//│ res\n//│     = Test {}\n\n\n:e\nclass Test<out A>(n: A) {\n  fun foo = n + 1\n}\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.215: \t  fun foo = n + 1\n//│ ║         \t            ^^^^^\n//│ ╟── reference of type `A` is not an instance of type `Int`\n//│ ║  l.215: \t  fun foo = n + 1\n//│ ║         \t            ^\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.214: \tclass Test<out A>(n: A) {\n//│ ╙──       \t               ^\n//│ class Test[A](n: A) {\n//│   fun foo: Int | error\n//│ }\n\nTest(1)\n//│ Test[1]\n//│ res\n//│     = Test {}\n\nTest(true)\n//│ Test[true]\n//│ res\n//│     = Test {}\n\n\nclass Test<A>(n: A) {\n  fun foo: A = n\n  fun foo1(x: A) = x\n  fun id(x) = x\n}\n//│ class Test[A](n: A) {\n//│   fun foo: A\n//│   fun foo1: (x: A) -> A\n//│   fun id: forall 'a. 'a -> 'a\n//│ }\n\nTest(1)\n//│ Test['A]\n//│   where\n//│     'A :> 1\n//│ res\n//│     = Test {}\n\nTest(1).foo\n//│ 1\n//│ res\n//│     = 1\n\nTest(\"ok\").foo\n//│ \"ok\"\n//│ res\n//│     = 'ok'\n\nlet t = Test(1)\n//│ let t: Test['A]\n//│   where\n//│     'A :> 1\n//│ t\n//│   = Test {}\n\nt.foo1(true)\n//│ 1 | true\n//│ res\n//│     = true\n\nt : Test<'a>\n//│ Test['a]\n//│   where\n//│     'a :> 1 | true\n//│ res\n//│     = Test {}\n\nt.id\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\n[t.id(1), t.id(true)]\n//│ [1, true]\n//│ res\n//│     = [ 1, true ]\n\n\n:e\nclass TestBad<A>() {\n  fun foo1(x: A) = x\n  fun foo2(x: A) = x + 1\n}\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.302: \t  fun foo2(x: A) = x + 1\n//│ ║         \t                   ^^^^^\n//│ ╟── reference of type `A` is not an instance of type `Int`\n//│ ║  l.302: \t  fun foo2(x: A) = x + 1\n//│ ║         \t                   ^\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.300: \tclass TestBad<A>() {\n//│ ╙──       \t              ^\n//│ class TestBad[A]() {\n//│   fun foo1: (x: A) -> A\n//│   fun foo2: (x: A) -> (Int | error)\n//│ }\n\nTestBad().foo1\n//│ (x: 'A) -> 'A\n//│ res\n//│     = [Function: foo1]\n\nTestBad().foo1(1)\n//│ 1\n//│ res\n//│     = 1\n\nx => TestBad().foo1(x)\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: res]\n\n// :d\nlet t = TestBad()\n//│ let t: forall 'A. TestBad['A]\n//│ t\n//│   = TestBad {}\n\nt.foo1\n//│ (x: 'A) -> 'A\n//│ res\n//│     = [Function: foo1]\n\n[t.foo1(0), t.foo1(true)]\n//│ [0, true]\n//│ res\n//│     = [ 0, true ]\n\nt.foo1(0)\n//│ 0\n//│ res\n//│     = 0\n\nt\n//│ forall 'A. TestBad['A]\n//│ res\n//│     = TestBad {}\n\n\nfun foo(x: TestBad<Int>) = x.foo1\n//│ fun foo: (x: TestBad[Int]) -> (x: Int) -> Int\n\nfoo(t)\n//│ (x: Int) -> Int\n//│ res\n//│     = [Function: foo1]\n\nfoo(t)(1)\n//│ Int\n//│ res\n//│     = 1\n\n\nTestBad().foo2\n//│ (x: anything) -> (Int | error)\n//│ res\n//│     = [Function: foo2]\n\n\n\nclass Weird(val x: C<'a>)\n//│ class Weird(x: C['a])\n\nlet w = Weird(c)\n//│ let w: Weird\n//│ w\n//│   = Weird {}\n\nw.x\n//│ C['a]\n//│ res\n//│     = C {}\n\nnot(w.x.n)\n//│ Bool\n//│ res\n//│     = true\n\n:e\nnot(w.x.a)\n//│ ╔══[ERROR] Type `C['a]` does not contain member `a`\n//│ ║  l.400: \tnot(w.x.a)\n//│ ╙──       \t       ^^\n//│ Bool\n//│ res\n//│     = false\n\n\n\nabstract class Cls[A](val x: A) { fun g: A -> Int }\n//│ abstract class Cls[A](x: A) {\n//│   fun g: A -> Int\n//│ }\n\nmodule M extends Cls(123) { fun g = id }\n//│ module M extends Cls {\n//│   fun g: forall 'a. 'a -> 'a\n//│ }\n\nM: Cls['a]\n//│ Cls['a]\n//│   where\n//│     'a :> 123\n//│        <: Int\n//│ res\n//│     = M { class: [class M extends Cls] }\n\n\nclass Cls[A](val x: A) { fun g: A -> Int; fun g(x) = 42 }\n//│ class Cls[A](x: A) {\n//│   fun g: A -> Int\n//│ }\n\nCls(123)\n//│ Cls['A]\n//│   where\n//│     'A :> 123\n//│ res\n//│     = Cls {}\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/GenericMethods.mls",
    "content": ":NewDefs\n\n\nfun foo1 = forall 'A: (x: 'A) => x\n//│ fun foo1: forall 'A. (x: 'A) -> 'A\n\nfoo1(42)\n//│ 42\n//│ res\n//│     = 42\n\n:e\nfoo1[Int](42)\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.13: \tfoo1[Int](42)\n//│ ╙──      \t^^^^^^^^^\n//│ 42\n//│ res\n//│     = 42\n\n\nfun foo2<A>(x: A) = x\n//│ fun foo2: forall 'A. (x: 'A) -> 'A\n\nfoo2(42)\n//│ 42\n//│ res\n//│     = 42\n\n:e\nfoo2<Int>(42)\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.31: \tfoo2<Int>(42)\n//│ ╙──      \t^^^^^^^^^\n//│ 42\n//│ res\n//│     = 42\n\n\nfun foo3[A](x: A) = x\n//│ fun foo3: forall 'A. (x: 'A) -> 'A\n\nfoo3(42)\n//│ 42\n//│ res\n//│     = 42\n\n:e\nfoo3[Int](42)\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.49: \tfoo3[Int](42)\n//│ ╙──      \t^^^^^^^^^\n//│ 42\n//│ res\n//│     = 42\n\n\nfun bar: forall 'A: 'A => 'A\n//│ fun bar: forall 'A. 'A -> 'A\n\n:e\nfun bar<A> : A => A\n//│ ╔══[ERROR] Type parameters are not yet supported in this position\n//│ ║  l.62: \tfun bar<A> : A => A\n//│ ╙──      \t        ^\n//│ fun bar: forall 'A. 'A -> 'A\n\n:pe\n:e\n:w\nfun bar<A>: A => A\n//│ ╔══[PARSE ERROR] Unmatched opening angle bracket\n//│ ║  l.71: \tfun bar<A>: A => A\n//│ ║        \t       ^\n//│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator\n//│ ╔══[PARSE ERROR] Unexpected 'fun' keyword in expression position\n//│ ║  l.71: \tfun bar<A>: A => A\n//│ ╙──      \t^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.71: \tfun bar<A>: A => A\n//│ ╙──      \t    ^^^^^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: >:\n//│ ║  l.71: \tfun bar<A>: A => A\n//│ ╙──      \t         ^^\n//│ ╔══[ERROR] identifier not found: A\n//│ ║  l.71: \tfun bar<A>: A => A\n//│ ╙──      \t        ^\n//│ ╔══[ERROR] identifier not found: A\n//│ ║  l.71: \tfun bar<A>: A => A\n//│ ╙──      \t            ^\n//│ ╔══[ERROR] identifier not found: A\n//│ ║  l.71: \tfun bar<A>: A => A\n//│ ╙──      \t                 ^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol >:\n\n\n:e\nmodule Test {\n  fun foo: 'A => 'A\n  fun bar: 'A\n  fun test<A>(x: A) = x\n}\n//│ ╔══[ERROR] Member `foo` is declared (or its declaration is inherited) but is not implemented in `Test`\n//│ ║  l.100: \tmodule Test {\n//│ ║         \t       ^^^^\n//│ ╟── Declared here:\n//│ ║  l.101: \t  fun foo: 'A => 'A\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Member `bar` is declared (or its declaration is inherited) but is not implemented in `Test`\n//│ ║  l.100: \tmodule Test {\n//│ ║         \t       ^^^^\n//│ ╟── Declared here:\n//│ ║  l.102: \t  fun bar: 'A\n//│ ╙──       \t  ^^^^^^^^^^^\n//│ module Test {\n//│   fun bar: nothing\n//│   fun foo: forall 'A. 'A -> 'A\n//│   fun test: forall 'A0. (x: 'A0) -> 'A0\n//│ }\n\nclass Test<A>(n: A) {\n  fun test<A>(x: A) = [x, n]\n}\n//│ class Test[A](n: A) {\n//│   fun test: forall 'A. (x: 'A) -> ['A, A]\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/GenericMixins.mls",
    "content": ":NewDefs\n\n\n\n// TODO support\nmixin BaseTest[A] {\n  fun test(x: A) = x\n}\n//│ mixin BaseTest[A]() {\n//│   fun test: (x: A) -> A\n//│ }\n\nmixin BaseTest[A](x: A) {\n  fun test = x\n}\n//│ mixin BaseTest[A](x: A) {\n//│   fun test: A\n//│ }\n\n\n\nmixin Test[A] {\n  fun foo: A -> A\n  fun foo = id\n  fun bar: (A -> A) -> (A -> A)\n  fun bar = id\n}\n//│ mixin Test[A]() {\n//│   fun bar: (A -> A) -> A -> A\n//│   fun foo: A -> A\n//│ }\n\nmodule C extends Test {\n  fun baz1 = this.foo(0)\n  fun baz2 = this.bar(this.foo)\n}\n//│ module C {\n//│   fun bar: ((0 | 'A) -> 'A) -> 'A -> (0 | 'A)\n//│   fun baz1: 0 | 'A\n//│   fun baz2: 'A -> (0 | 'A)\n//│   fun foo: 'A -> (0 | 'A)\n//│ }\n\nC.baz1\n//│ 0\n//│ res\n//│     = 0\n\nC.foo(1)\n//│ 0 | 1\n//│ res\n//│     = 1\n\nC.foo(false)\n//│ 0 | false\n//│ res\n//│     = false\n\nmodule C extends Test[Int] {\n  fun baz1 = this.foo(0)\n  fun baz2 = this.bar(this.foo)\n}\n//│ module C {\n//│   fun bar: (Int -> Int) -> Int -> Int\n//│   fun baz1: Int\n//│   fun baz2: Int -> Int\n//│   fun foo: Int -> Int\n//│ }\n\nC.baz1\n//│ Int\n//│ res\n//│     = 0\n\nC.foo(1)\n//│ Int\n//│ res\n//│     = 1\n\n:e\nC.foo(false)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.81: \tC.foo(false)\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of `Int`\n//│ ║  l.81: \tC.foo(false)\n//│ ║        \t      ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.59: \tmodule C extends Test[Int] {\n//│ ║        \t                      ^^^\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.22: \tmixin Test[A] {\n//│ ╙──      \t           ^\n//│ Int | error\n//│ res\n//│     = false\n\nclass C[A] extends Test[Array[A]] {\n  fun baz1 = this.foo([])\n  fun baz2 = this.bar(this.foo)\n}\n//│ class C[A] {\n//│   constructor()\n//│   fun bar: (Array[A] -> Array[A]) -> Array[A] -> Array[A]\n//│   fun baz1: Array[A]\n//│   fun baz2: Array[A] -> Array[A]\n//│   fun foo: Array[A] -> Array[A]\n//│ }\n\n\n\nmixin Test[A] {\n  fun foo: A -> A\n  fun foo = id\n  fun bar: [A, A]\n  fun bar = [this.arg, this.arg]\n  fun baz = foo(this.arg)\n}\n//│ mixin Test[A]() {\n//│   this: {arg: A & 'a}\n//│   fun bar: [A, A]\n//│   fun baz: 'a\n//│   fun foo: A -> A\n//│ }\n\nclass C(val arg: Int) extends Test\n//│ class C(arg: Int) {\n//│   fun bar: [Int | 'A, Int | 'A]\n//│   fun baz: Int\n//│   fun foo: 'A -> (Int | 'A)\n//│ }\n\nlet c = C(1)\n[c.foo(false), c.bar]\n//│ let c: C\n//│ [Int | false, [Int, Int]]\n//│ c\n//│   = C {}\n//│ res\n//│     = [ false, [ 1, 1 ] ]\n\n:e // FIXME\nmodule D extends C(0) {\n  this.foo(false)\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.144: \t  this.foo(false)\n//│ ╙──       \t      ^^^^\n//│ ╔══[ERROR] Cannot access `this` during object initialization\n//│ ║  l.144: \t  this.foo(false)\n//│ ╙──       \t  ^^^^\n//│ module D extends C {\n//│   fun bar: forall 'A. [Int | 'A, Int | 'A]\n//│   fun baz: Int\n//│   fun foo: forall 'A. 'A -> (Int | 'A)\n//│ }\n\n:e // TODO support or produce better error (arg is not actually recursive)\nclass C extends Test { // it also fails with Test[Int]...\n  fun arg = 123\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.117: \t  fun baz = foo(this.arg)\n//│ ╙──       \t                    ^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.116: \t  fun bar = [this.arg, this.arg]\n//│ ╙──       \t                           ^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.116: \t  fun bar = [this.arg, this.arg]\n//│ ╙──       \t                 ^^^^\n//│ class C {\n//│   constructor()\n//│   fun arg: 123\n//│   fun bar: [error | 'A, error | 'A]\n//│   fun baz: error\n//│   fun foo: 'A -> (error | 'A)\n//│ }\n\nclass C extends Test {\n  fun arg: Int\n  fun arg = 123\n}\n//│ class C {\n//│   constructor()\n//│   fun arg: Int\n//│   fun bar: [Int | 'A, Int | 'A]\n//│   fun baz: Int\n//│   fun foo: 'A -> (Int | 'A)\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/GenericModules.mls",
    "content": ":NewDefs\n\n\n// * TODO generic module definitions need to be restricted so they do not include nay state\n// * to avoid unsoundness...\n\n\nmodule Test[A] {\n  fun foo: A -> A = id\n}\n//│ module Test[A] {\n//│   fun foo: A -> A\n//│ }\n\nTest.foo(1) + 1\n//│ Int\n//│ res\n//│     = 2\n\nnot(Test.foo(true))\n//│ Bool\n//│ res\n//│     = false\n\nTest.foo\n//│ 'A -> 'A\n//│ res\n//│     = [Function: id]\n\n\n// * FIXME merging generic module types, as we currently do, is unsound:\n\nlet t = Test : Test[Int] & Test[Str]\n//│ let t: Test[in Int | Str out nothing]\n//│ t\n//│   = Test { class: [class Test] }\n\nt.foo\n//│ (Int | Str) -> nothing\n//│ res\n//│     = [Function: id]\n\n:re\nt.foo(1)(2)\n//│ nothing\n//│ res\n//│ Runtime error:\n//│   TypeError: t.foo(...) is not a function\n\n\n\nmodule Test<A> {\n  fun foo: A => A\n  fun foo = id\n  fun bar: A => A = id\n  fun baz(x: A) = x\n  fun poly0: 'a -> 'a\n  fun poly0 = id\n  fun poly1: forall 'a: 'a -> 'a\n  fun poly1 = id\n  fun poly2: 'a -> 'a = id\n}\n//│ module Test[A] {\n//│   fun bar: A -> A\n//│   fun baz: (x: A) -> A\n//│   fun foo: A -> A\n//│   fun poly0: forall 'a. 'a -> 'a\n//│   fun poly1: forall 'a0. 'a0 -> 'a0\n//│   fun poly2: forall 'a1. 'a1 -> 'a1\n//│ }\n\nTest.foo\n//│ 'A -> 'A\n//│ res\n//│     = [Function: id]\n\nTest.bar\n//│ 'A -> 'A\n//│ res\n//│     = [Function: id]\n\nTest.baz\n//│ (x: 'A) -> 'A\n//│ res\n//│     = [Function: baz]\n\nTest.poly0\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\nTest.poly1\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\nTest.poly2\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\nTest.foo(1)\n//│ 1\n//│ res\n//│     = 1\n\n:re\nTest.foo(error) + 1\n//│ Int\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:e\nTest<Int> .foo\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.115: \tTest<Int> .foo\n//│ ╙──       \t^^^^^^^^^\n//│ 'A -> 'A\n//│ res\n//│     = [Function: id]\n\n:e\n(Test<Int>).foo\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.124: \t(Test<Int>).foo\n//│ ╙──       \t ^^^^^^^^^\n//│ 'A -> 'A\n//│ res\n//│     = [Function: id]\n\n\nTest\n//│ forall 'A. Test['A]\n//│ res\n//│     = Test { class: [class Test] }\n\nTest : Test<'a>\n//│ Test['a]\n//│ res\n//│     = Test { class: [class Test] }\n\n\nfun test(x) = if x is Test then x.foo\n//│ fun test: forall 'A. Test['A] -> 'A -> 'A\n\ntest(Test)\n//│ 'A -> 'A\n//│ res\n//│     = [Function: id]\n\n\nmodule Test<A> {\n  fun foo = id\n}\n//│ module Test[A] {\n//│   fun foo: forall 'a. 'a -> 'a\n//│ }\n\nTest.foo\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\n\nmodule Test<A> {\n  fun foo: A => A\n  fun foo = id\n}\n//│ module Test[A] {\n//│   fun foo: A -> A\n//│ }\n\nTest.foo\n//│ 'A -> 'A\n//│ res\n//│     = [Function: id]\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/HeungTung.mls",
    "content": ":NewDefs\n:NoApproximateOverload\n\n\n\ntrait A\ntrait B\n//│ trait A\n//│ trait B\n\nmodule AA extends A, B\n//│ module AA extends A, B\n\nfun x: A & B\nfun x = AA\n//│ fun x: AA\n//│ fun x: A & B\n\nx : A\n//│ A\n//│ res\n//│     = AA { class: [class AA extends Object] }\n\n\n\nabstract class Foo[A, B] { fun x: A & B }\n//│ abstract class Foo[A, B] {\n//│   fun x: A & B\n//│ }\n\nmodule Bar extends Foo[Int, Bool] { fun x = x }\n//│ module Bar extends Foo {\n//│   fun x: nothing\n//│ }\n\nmodule Bar extends Foo { fun x = () }\n//│ module Bar extends Foo {\n//│   fun x: ()\n//│ }\n\nBar : Foo['a, 'b]\n//│ Foo['a, 'b]\n//│   where\n//│     'b :> ()\n//│     'a :> ()\n//│ res\n//│     = Bar { class: [class Bar extends Foo] }\n\n\n// * An overloaded function type\nfun f: (Int -> Int) & (Bool -> Bool)\nfun f = id\n//│ fun f: forall 'a. 'a -> 'a\n//│ fun f: Int -> Int & Bool -> Bool\n\n\n// * Widen the results\nfun h: (Int -> (Int | Bool)) & (Bool -> (Int | Bool))\nfun h = f\n//│ fun h: Int -> Int & Bool -> Bool\n//│ fun h: (Int | false | true) -> (Int | false | true)\n\n// * Merge intersected functions with same domain\nfun g: (Int | Bool) -> (Int | Bool)\nfun g = h\n//│ fun g: (Int | false | true) -> (Int | false | true)\n//│ fun g: (Int | false | true) -> (Int | false | true)\n\n// * In one step\n:e // TODO: argument of union type\nfun g: (Int | Bool) -> (Int | Bool)\nfun g = f\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.72: \tfun g = f\n//│ ║        \t    ^^^^^\n//│ ╟── type `Int -> Int & Bool -> Bool` is not an instance of `(Int | false | true) -> (Int | false | true)`\n//│ ║  l.51: \tfun f: (Int -> Int) & (Bool -> Bool)\n//│ ║        \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(Int | false | true) -> (Int | false | true)`\n//│ ║  l.72: \tfun g = f\n//│ ║        \t        ^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.71: \tfun g: (Int | Bool) -> (Int | Bool)\n//│ ╙──      \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun g: Int -> Int & Bool -> Bool\n//│ fun g: (Int | false | true) -> (Int | false | true)\n\n\n// * Can also widen into intersection\nfun i: ((Int & Bool) -> Int) & ((Int & Bool) -> Bool)\nfun i = f\n//│ fun i: Int -> Int & Bool -> Bool\n//│ fun i: nothing -> nothing\n\n// * Merge intersected functions with same codomain\nfun j: (Int & Bool) -> (Int & Bool)\nfun j = i\n//│ fun j: nothing -> nothing\n//│ fun j: nothing -> nothing\n\n:e // * Note: currently it doesn't work when done in a single step\nfun j: (Int & Bool) -> (Int & Bool)\nfun j = f\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.103: \tfun j = f\n//│ ║         \t    ^^^^^\n//│ ╟── type `Int -> Int & Bool -> Bool` is not an instance of `nothing -> nothing`\n//│ ║  l.51: \tfun f: (Int -> Int) & (Bool -> Bool)\n//│ ║        \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `nothing -> nothing`\n//│ ║  l.103: \tfun j = f\n//│ ║         \t        ^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.102: \tfun j: (Int & Bool) -> (Int & Bool)\n//│ ╙──       \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun j: Int -> Int & Bool -> Bool\n//│ fun j: nothing -> nothing\n\n\n// * Or widen even further with both an intersection and a union, into this\nfun g: (Int & Bool) -> (Int | Bool)\nfun g = f\n//│ fun g: Int -> Int & Bool -> Bool\n//│ fun g: nothing -> (Int | false | true)\n\n\n// * Note: we currently approximate uses of overloaded function types!\n// * With match-type-based constraint solving, we could return Int here\n\nf(0)\n//│ Int\n//│ res\n//│     = 0\n\n// f(0) : case 0 of { Int => Int; Bool => Bool } == Int\n\n\nx => f(x)\n//│ forall 'a 'b. 'a -> 'b\n//│   where\n//│     [+'a, -'b] in {[Int, Int], [Bool, Bool]}\n//│ res\n//│     = [Function: res]\n\n// : forall 'a: 'a -> case 'a of { Int => Int; Bool => Bool } where 'a <: Int | Bool\n\n:e\nf(if true then 0 else false)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.148: \tf(if true then 0 else false)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Int -> Int & Bool -> Bool` is not an instance of `(0 | false) -> ?a`\n//│ ║  l.51: \tfun f: (Int -> Int) & (Bool -> Bool)\n//│ ║        \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(0 | false) -> ?a`\n//│ ║  l.148: \tf(if true then 0 else false)\n//│ ╙──       \t^\n//│ error\n//│ res\n//│     = 0\n\n// * With match-type-based constraint solving, we could *also* return Int here\n\n:e // TODO implement this syntax\n:w\nf(refined if true then 0 else false) // this one can be precise again!\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.166: \tf(refined if true then 0 else false) // this one can be precise again!\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Illegal use of reserved operator: refined\n//│ ║  l.166: \tf(refined if true then 0 else false) // this one can be precise again!\n//│ ╙──       \t  ^^^^^^^\n//│ ╔══[ERROR] identifier not found: refined\n//│ ║  l.166: \tf(refined if true then 0 else false) // this one can be precise again!\n//│ ╙──       \t  ^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.166: \tf(refined if true then 0 else false) // this one can be precise again!\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `error` does not match type `?a`\n//│ ║  l.166: \tf(refined if true then 0 else false) // this one can be precise again!\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ 'a\n//│   where\n//│     'b :> error\n//│     'a :> error\n//│     [+'b, -'a] in {}\n//│ Code generation encountered an error:\n//│   unresolved symbol refined\n\n\n\n// * Notes on constraint solving\n\n\n// * Easy:\n\n// ?a -> ?b <: (Int -> Int) & (Bool -> Bool)\n// to:\n// ?a -> ?b <: (Int -> Int) AND ?a -> ?b <: (Bool -> Bool)\n\n// * Hard; but can solve with match types:\n\n// (Int -> Int) & (Bool -> Bool) <: ?a -> ?b\n// to:\n// ?a <: Int | Bool AND (case ?a of { Int => Int; Bool => Bool }) <: ?b\n\n// We can still widen if needed; consider:\n// ?a := Int | Bool\n// then:\n// (case (Int | Bool) of { Int => Int; Bool => Bool }) <: ?b\n// to:\n// Int <: ?b AND Bool <: ?b\n\n// An simple match-type constraint example:\n// (case ?a of { Int => Int; Bool => Bool }) <: Int\n// to:\n// ?a <: Int\n\n// A more complicated match-type constraint example:\n// (case ?a of { Int => ?b; Bool => ?c }) <: T\n// to:\n// ?b <: (case ?a of { Int => T; Bool => Top }) AND ?c <: (case ?a of { Int => Top; Bool => T })\n\n\n\nclass List[A]\n//│ class List[A] {\n//│   constructor()\n//│ }\n\n// * Note: match type `T match { case List[t] => ... t ... }` could be encoded as:\n\ntype M = (forall 't: List['t] => 't)\n//│ type M = forall 't. List['t] -> 't\n\ntype T = List[Int]\n//│ type T = List[Int]\n\n:e // TODO application types\ntype Res = M(T)\n//│ ╔══[ERROR] Wrong number of type arguments – expected 0, found 1\n//│ ║  l.240: \ttype Res = M(T)\n//│ ╙──       \t           ^^^^\n//│ type Res = M\n\n\n\nlet f = x => [x, x]\n//│ let f: forall 'a. 'a -> ['a, 'a]\n//│ f\n//│   = [Function: f1]\n\n[f(1), f(true)]\n//│ [[1, 1], [true, true]]\n//│ res\n//│     = [ [ 1, 1 ], [ true, true ] ]\n\n\n\n:e // TODO support\nfun f: Int -> Int\nfun f: Bool -> Bool\nfun f = id\n//│ ╔══[ERROR] A type signature for 'f' was already given\n//│ ║  l.262: \tfun f: Bool -> Bool\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^\n//│ fun f: forall 'a. 'a -> 'a\n//│ fun f: Int -> Int\n\n:e // TODO support\nf: (Int -> Int) & (Bool -> Bool)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.271: \tf: (Int -> Int) & (Bool -> Bool)\n//│ ║         \t^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ║  l.271: \tf: (Int -> Int) & (Bool -> Bool)\n//│ ║         \t                   ^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.261: \tfun f: Int -> Int\n//│ ╙──       \t       ^^^\n//│ Int -> Int & Bool -> Bool\n//│ res\n//│     = [Function: id]\n\n//   t: S  t: T\n// -------------\n//   t: S & T\n\n\n\n// * Weird MLstruct rule (only sound when we don't have FCP):\n// forall 'a: 'a -> 'a <: (Int -> Int) & (Bool -> Bool) == (Int | Bool) -> (Int & Bool)\n// ~{ a: Int } <: Str -> Str\n\n// * Notice: in positive position, this is equivalent to Bottom\nfun x: ~{ a: Int }\n//│ fun x: ~{a: Int}\n\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nA() : ~B\n//│ ~B\n//│ res\n//│     = A {}\n\n// A <: ~B\n// <=>\n// A <: ~B | Bot\n// <=>\n// A & B <: Bot\n\nfun x: A & B\n//│ fun x: nothing\n\n\nfun test(x) = if x is\n  A then 0\n  _ then x\n//│ fun test: forall 'a. (A | Object & 'a & ~#A) -> (0 | 'a)\n\ntest(B())\n//│ 0 | B\n//│ res\n//│     = B {}\n\ntest(A())\n//│ 0\n//│ res\n//│     = 0\n\n// A <: A | Object & 'a & ~A\n// A & ~A <: Object & 'a & ~A\n// Bot <: Object & 'a & ~A\n\n\n:e // TODO implement this syntax\n:w\nfun test(x) = refined if x is\n  A then 0\n  B then 1\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.342: \tfun test(x) = refined if x is\n//│ ║         \t              ^^^^^^^^^^^^^^^\n//│ ║  l.343: \t  A then 0\n//│ ║         \t^^^^^^^^^^\n//│ ║  l.344: \t  B then 1\n//│ ╙──       \t^^^^^^^^^^\n//│ ╔══[ERROR] Illegal use of reserved operator: refined\n//│ ║  l.342: \tfun test(x) = refined if x is\n//│ ╙──       \t              ^^^^^^^\n//│ ╔══[ERROR] identifier not found: refined\n//│ ║  l.342: \tfun test(x) = refined if x is\n//│ ╙──       \t              ^^^^^^^\n//│ fun test: (A | B) -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol refined\n\n// forall 'a: 'a -> (case 'a of A -> 0, B & ~A -> 1)\n\n\n\nfun q: (0|1) -> true & (1|2) -> false\n//│ fun q: (0 | 1) -> true & (1 | 2) -> false\n\nq(0)\n//│ true\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\nq(0) : true\n//│ true\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\nq(1)\n//│ 'a\n//│   where\n//│     [-'a] in {[true], [false]}\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\nq(1) : Bool\n//│ Bool\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\nx => q(x): true\n//│ (0 | 1) -> true\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\nx => q(x)\n//│ forall 'a 'b. 'a -> 'b\n//│   where\n//│     [+'a, -'b] in {[0 | 1, true], [1 | 2, false]}\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\n:e\n(x => q(x))(1):Int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.410: \t(x => q(x))(1):Int\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ╟── application of type `?a` does not match type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.410: \t(x => q(x))(1):Int\n//│ ╙──       \t               ^^^\n//│ Int\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\n:e\nq(1):int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.424: \tq(1):int\n//│ ║         \t^^^^\n//│ ╟── application of type `?a` does not match type `int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.424: \tq(1):int\n//│ ╙──       \t     ^^^\n//│ int\n//│ res\n//│     = <no result>\n//│       q is not implemented\n\nfun w = x => q(x)\n//│ fun w: forall 'a 'b. 'a -> 'b\n//│   where\n//│     [+'a, -'b] in {[0 | 1, true], [1 | 2, false]}\n\nw(0)\n//│ true\n//│ res\n//│     = <no result>\n//│       w and q are not implemented\n\nx => (f: forall a: ((0, Int) -> 'a & (1, Str) -> ['a])) => f(0, x) + 1\n//│ Int -> (f: (0, Int) -> Int & (1, Str) -> [Int]) -> Int\n//│ res\n//│     = [Function: res]\n\nfun r: Int -> Int & Bool -> Bool\n//│ fun r: Int -> Int & Bool -> Bool\n\n:e\nx => r(r(x))\n//│ ╔══[ERROR] ambiguous\n//│ ╟── cannot determine satisfiability of type ?a\n//│ ║  l.457: \tx => r(r(x))\n//│ ╙──       \t       ^^^^\n//│ forall 'a 'b 'c. 'a -> 'c\n//│   where\n//│     [+'a, -'b] in {[Int, Int], [Bool, Bool]}\n//│     [-'c, +'b] in {[Int, Int], [Bool, Bool]}\n//│ res\n//│     = <no result>\n//│       r is not implemented\n\n\nr(r(0))\n//│ Int\n//│ res\n//│     = <no result>\n//│       r is not implemented\n\nx => r(r(x))+1\n//│ Int -> Int\n//│ res\n//│     = <no result>\n//│       r is not implemented\n\nfun u: {x:0, y:Int} -> Int & {x:1, z: Str} -> Str\n//│ fun u: {x: 0, y: Int} -> Int & {x: 1, z: Str} -> Str\n\n(a, b, c) => u({x: a, y: b, z: c})\n//│ forall 'a 'b 'c 'd. ('a, 'c, 'd) -> 'b\n//│   where\n//│     [-'b, +'a, +'c, +'d] in {[Int, 0, Int, anything], [Str, 1, anything, Str]}\n//│ res\n//│     = <no result>\n//│       u is not implemented\n\n(a, b) => u({x: a, y: \"abc\", z: b})\n//│ (1, Str) -> Str\n//│ res\n//│     = <no result>\n//│       u is not implemented\n\nfun s: Str -> Str & AA -> AA\n//│ fun s: Str -> Str & AA -> AA\n\n:e\nlet g = x => s(r(x))\n//│ ╔══[ERROR] ambiguous\n//│ ╟── cannot determine satisfiability of type ?a\n//│ ║  l.504: \tlet g = x => s(r(x))\n//│ ╙──       \t               ^^^^\n//│ let g: forall 'a 'b 'c. 'a -> 'c\n//│   where\n//│     [+'a, -'b] in {[Int, Int], [Bool, Bool]}\n//│     [+'b, -'c] in {[Str, Str], [AA, AA]}\n//│ g\n//│   = <no result>\n//│     s is not implemented\n\n:e\nfun g(x) = s(r(x))\n//│ ╔══[ERROR] ambiguous\n//│ ╟── cannot determine satisfiability of type ?a\n//│ ║  l.518: \tfun g(x) = s(r(x))\n//│ ╙──       \t             ^^^^\n//│ fun g: forall 'a 'b 'c. 'a -> 'c\n//│   where\n//│     [+'a, -'b] in {[Int, Int], [Bool, Bool]}\n//│     [-'c, +'b] in {[Str, Str], [AA, AA]}\n\n:e\nx => s(r(x))\n//│ ╔══[ERROR] ambiguous\n//│ ╟── cannot determine satisfiability of type ?a\n//│ ║  l.529: \tx => s(r(x))\n//│ ╙──       \t       ^^^^\n//│ forall 'a 'b 'c. 'a -> 'c\n//│   where\n//│     [+'a, -'b] in {[Int, Int], [Bool, Bool]}\n//│     [-'c, +'b] in {[Str, Str], [AA, AA]}\n//│ res\n//│     = <no result>\n//│       s is not implemented\n\n:e\ng(0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.543: \tg(0)\n//│ ║         \t^^^^\n//│ ╟── expression of type `Int` does not match type `?a`\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.518: \tfun g(x) = s(r(x))\n//│ ╙──       \t             ^^^^\n//│ error\n//│ res\n//│     = <no result>\n//│       g and s are not implemented\n\nfun rt: {0: Int} -> Int & {0: Str} -> Str\n//│ fun rt: {0: Int} -> Int & {0: Str} -> Str\n\nrt([1,\"str\"])\n//│ Int\n//│ res\n//│     = <no result>\n//│       rt is not implemented\n\nrt([\"str\",1])\n//│ Str\n//│ res\n//│     = <no result>\n//│       rt is not implemented\n\nfun app2: ('a -> 'a -> 'a) -> 'a -> 'a\n//│ fun app2: forall 'a. ('a -> 'a -> 'a) -> 'a -> 'a\n\nfun snd: A -> Int -> Int & Str -> Str -> Str\n//│ fun snd: A -> Int -> Int & Str -> Str -> Str\n\n:e\nx => app2(snd)(x):Int\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.578: \tx => app2(snd)(x):Int\n//│ ║         \t     ^^^^^^^^^^^^\n//│ ╟── type `Int` is not an instance of type `A`\n//│ ║  l.571: \tfun app2: ('a -> 'a -> 'a) -> 'a -> 'a\n//│ ║         \t                       ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.574: \tfun snd: A -> Int -> Int & Str -> Str -> Str\n//│ ╙──       \t         ^\n//│ nothing -> Int\n//│ res\n//│     = <no result>\n//│       app2 is not implemented\n\nfun app2_ (f:'a -> 'a -> 'a)(x) = f(x)(x)\n//│ fun app2_: forall 'a. (f: 'a -> 'a -> 'a) -> 'a -> 'a\n\napp2_(snd)\n//│ 'a -> 'b\n//│   where\n//│     'a <: 'b\n//│     [-'b, -'a, +'a] in {[Int, Int, A & Int], [Str, Str, Str]}\n//│ res\n//│     = <no result>\n//│       snd is not implemented\n\n// * Example from WeirdUnions.mls.\n// * This type merges the input tuples:\nfun f: (Str => Str) & ((Str, Int) => Str)\n//│ fun f: (...Array[Int | Str] & {0: Str}) -> Str\n\nf(\"abc\", \"abc\")\n//│ Str\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\nfun f: (Str => Str) & ((Str, Int) => Int)\n//│ fun f: Str -> Str & (Str, Int) -> Int\n\n// * Different from WeirdUnions.mls:\n:e\nf(\"abc\", \"abc\")\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.621: \tf(\"abc\", \"abc\")\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── type `Str -> Str & (Str, Int) -> Int` is not an instance of `(\"abc\", \"abc\") -> ?a`\n//│ ║  l.616: \tfun f: (Str => Str) & ((Str, Int) => Int)\n//│ ║         \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `(\"abc\", \"abc\") -> ?a`\n//│ ║  l.621: \tf(\"abc\", \"abc\")\n//│ ╙──       \t^\n//│ error\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\nf(\"abcabc\")\n//│ Str\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\n:e\nx => rt([not(x)])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.643: \tx => rt([not(x)])\n//│ ║         \t     ^^^^^^^^^^^^\n//│ ╟── application of type `Bool` does not match type `?a`\n//│ ║  l.643: \tx => rt([not(x)])\n//│ ╙──       \t         ^^^^^^\n//│ forall 'a 'b. Bool -> 'a\n//│   where\n//│     'b :> Bool\n//│     'a :> error\n//│     [-'a, +'b] in {}\n//│ res\n//│     = <no result>\n//│       rt is not implemented\n\n:e\nrt(0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.660: \trt(0)\n//│ ║         \t^^^^^\n//│ ╟── type `{0: Int} -> Int & {0: Str} -> Str` is not an instance of `0 -> ?a`\n//│ ║  l.556: \tfun rt: {0: Int} -> Int & {0: Str} -> Str\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `0 -> ?a`\n//│ ║  l.660: \trt(0)\n//│ ╙──       \t^^\n//│ error\n//│ res\n//│     = <no result>\n//│       rt is not implemented\n\nfun z: {0:Int} -> nothing & Str -> Str\n//│ fun z: {0: Int} -> nothing & Str -> Str\n\nz([1])\n//│ nothing\n//│ res\n//│     = <no result>\n//│       z is not implemented\n"
  },
  {
    "path": "shared/src/test/diff/nu/Huawei1.mls",
    "content": ":NewDefs\n\n\nclass C[out A](x: A) {\n  fun foo = x\n}\n//│ class C[A](x: A) {\n//│   fun foo: A\n//│ }\n\nlet c = C(123)\n//│ let c: C[123]\n//│ c\n//│   = C {}\n\nclass B\n//│ class B {\n//│   constructor()\n//│ }\n\nfun bar(c) = if c is\n  C(y) then y\n  B    then 0\n//│ fun bar: forall 'a. (B | C['a]) -> (0 | 'a)\n\nbar(c)\n//│ 0 | 123\n//│ res\n//│     = 123\n\nfun bar(c) = if c is\n    C(y) then y + 1\n    B    then 0\n  else 1\n//│ fun bar: (C[Int] | Object & ~#C) -> Int\n\nbar(c)\n//│ Int\n//│ res\n//│     = 124\n\n:e\nbar(C(true))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.43: \tbar(C(true))\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Int`\n//│ ║  l.43: \tbar(C(true))\n//│ ║        \t      ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.32: \t    C(y) then y + 1\n//│ ║        \t              ^\n//│ ╟── from field selection:\n//│ ║  l.4: \tclass C[out A](x: A) {\n//│ ║       \t               ^\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.4: \tclass C[out A](x: A) {\n//│ ╙──     \t            ^\n//│ Int | error\n//│ res\n//│     = 2\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ImplicitMethodPolym.mls",
    "content": ":NewDefs\n\n\nmodule M {\n  fun id1(x) = x\n}\n//│ module M {\n//│   fun id1: forall 'a. 'a -> 'a\n//│ }\n\nM.id1\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id1]\n\nM.id1(true)\n//│ true\n//│ res\n//│     = true\n\nM.id1(0)\n//│ 0\n//│ res\n//│     = 0\n\n\nmodule M {\n  fun id1(x) = x\n  let _ = id1(0)\n}\n//│ module M {\n//│   let _: 0\n//│   fun id1: forall 'a. 'a -> 'a\n//│ }\n\nM.id1\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id1]\n\n// :d\nmixin Mx {\n  fun id1(x) = x\n}\n//│ mixin Mx() {\n//│   fun id1: 'a -> 'a\n//│ }\n\n// * Note: the order of freshening matters!\n// * if TV freshened transitively from traversing the `this` refinement at a lower ctx level,\n// * as in the case below, the result is different.\nmodule M extends Mx {\n  val r = this.id1(0)\n}\n//│ module M {\n//│   fun id1: forall 'a. ('b & 'a) -> (0 | 'a)\n//│   val r: 0 | 'b\n//│ }\n\nmixin Mx {\n  fun id1(x) = this.id2(x)\n}\n//│ mixin Mx() {\n//│   this: {id2: 'a -> 'b}\n//│   fun id1: 'a -> 'b\n//│ }\n\n:e\nmodule M extends Mx {\n  this.id1(0)\n}\n//│ ╔══[ERROR] Type `#M & {id1: ?a -> ?b}` does not contain member `id2`\n//│ ║  l.61: \t  fun id1(x) = this.id2(x)\n//│ ╙──      \t                   ^^^^\n//│ module M {\n//│   fun id1: anything -> error\n//│ }\n//│ Runtime error:\n//│   TypeError: qualifier1.id2 is not a function\n\n:e\nmodule M extends Mx {\n  fun id2(x) = [x, x]\n  this.id1(0)\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.61: \t  fun id1(x) = this.id2(x)\n//│ ╙──      \t                   ^^^^\n//│ module M {\n//│   fun id1: anything -> error\n//│   fun id2: forall 'a. 'a -> ['a, 'a]\n//│ }\n\n// * Notice that `id1` is no longer generalized!\nmodule M extends Mx {\n  fun id2: 'a => ['a, 'a]\n  fun id2(x) = [x, x]\n  let _ = this.id1(0)\n}\n//│ module M {\n//│   let _: [0 | 'a, 0 | 'a]\n//│   fun id1: 'a -> [0 | 'a, 0 | 'a]\n//│   fun id2: forall 'a0. 'a0 -> ['a0, 'a0]\n//│ }\n\n\n\n:e // FIXME\nclass C {\n  virtual fun id1(x) = x\n  fun f = [this.id1(true), this.id1(0)]\n  fun id2(x) = x\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.111: \t  fun f = [this.id1(true), this.id1(0)]\n//│ ╙──       \t               ^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.111: \t  fun f = [this.id1(true), this.id1(0)]\n//│ ╙──       \t                               ^^^^\n//│ class C {\n//│   constructor()\n//│   fun f: [error, error]\n//│   fun id1: forall 'a. 'a -> 'a\n//│   fun id2: forall 'b. 'b -> 'b\n//│ }\n\n// TODO support\n// :d\nmodule M extends C {\n  this.id2(true)\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.130: \t  this.id2(true)\n//│ ╙──       \t      ^^^^\n//│ ╔══[ERROR] Cannot access `this` during object initialization\n//│ ║  l.130: \t  this.id2(true)\n//│ ╙──       \t  ^^^^\n//│ module M extends C {\n//│   fun f: [error, error]\n//│   fun id1: forall 'a. 'a -> 'a\n//│   fun id2: forall 'b. 'b -> 'b\n//│ }\n\n// TODO support\nmodule M extends C {\n  fun g = (this.id2(true), this.id2(0))\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.146: \t  fun g = (this.id2(true), this.id2(0))\n//│ ╙──       \t               ^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.146: \t  fun g = (this.id2(true), this.id2(0))\n//│ ╙──       \t                               ^^^^\n//│ module M extends C {\n//│   fun f: [error, error]\n//│   fun g: error\n//│   fun id1: forall 'a. 'a -> 'a\n//│   fun id2: forall 'b. 'b -> 'b\n//│ }\n\nM.id1\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id1]\n\nM.id2\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id2]\n\nM.f\n//│ [error, error]\n//│ res\n//│     = [ true, 0 ]\n\nM.g\n//│ error\n//│ res\n//│     = 0\n\n\n:e\nmodule M extends C {\n  fun id1 = succ\n}\n//│ ╔══[ERROR] Type mismatch in definition of method id1:\n//│ ║  l.184: \t  fun id1 = succ\n//│ ║         \t      ^^^^^^^^^^\n//│ ╙── variable of type `?a` is not an instance of type `Int`\n//│ ╔══[ERROR] Type mismatch in definition of method id1:\n//│ ║  l.184: \t  fun id1 = succ\n//│ ║         \t      ^^^^^^^^^^\n//│ ╟── expression of type `Int` does not match type `?a`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.110: \t  virtual fun id1(x) = x\n//│ ╙──       \t                       ^\n//│ module M extends C {\n//│   fun f: [error, error]\n//│   fun id1: Int -> Int\n//│   fun id2: forall 'a. 'a -> 'a\n//│ }\n\nM.id1\n//│ Int -> Int\n//│ res\n//│     = [Function: succ]\n\n\n(M : C).id1(false)\n//│ false\n//│ res\n//│     = 1\n\n\n// FIXME? parsing/semantics of this, currently treated as a named tuple...\n(M: C)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.216: \t(M: C)\n//│ ╙──       \t ^^^^\n//│ ╔══[ERROR] Construction of unparameterized class C should use the `new` keyword\n//│ ║  l.216: \t(M: C)\n//│ ╙──       \t    ^\n//│ () -> C\n//│ res\n//│     = [class C]\n\n\n\ntype Option[A] = Some[A] | None\nclass Some[out A](val value: A)\nmodule None\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A)\n//│ module None\n\n\n// * TODO support semantics but reject at typing:\n// *  polymophism should be blocked by mutation from distributing/refreshing\n\nmodule M {\n  mut val m = None\n  fun oops(x) = set m = x\n}\n//│ module M {\n//│   mut val m: None\n//│   fun oops: None -> ()\n//│ }\n\n\n:e\nmodule M {\n  mut val m = None\n  fun oops(x) = set this.m = x\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.253: \t  fun oops(x) = set this.m = x\n//│ ╙──       \t                        ^^\n//│ module M {\n//│   mut val m: None\n//│   fun oops: error -> ()\n//│ }\n\n\nmodule M[A] {\n  mut val m: Option[A]\n  m = None\n  fun oops(x) = set this.m = x\n}\n//│ module M[A] {\n//│   mut val m: Option[A]\n//│   fun oops: Option[A] -> ()\n//│ }\n\nM.m\n//│ Option['A]\n//│ res\n//│     = None { class: [class None] }\n\n:re // * FIXME (codegen) member definition should inherit mutability of declaration\nM.oops(Some(123))\n//│ ()\n//│ res\n//│ Runtime error:\n//│   TypeError: Cannot set property m of #<M> which has only a getter\n\nM.m\n//│ Option['A]\n//│ res\n//│     = None { class: [class None] }\n\nmodule M[A] {\n  mut val m: Option[A]\n  mut val m = None\n  fun oops(x) = set this.m = x\n}\n//│ module M[A] {\n//│   mut val m: Option[A]\n//│   fun oops: Option[A] -> ()\n//│ }\n\nM.m\nM.oops(Some(123))\nM.m\n//│ Option['A]\n//│ res\n//│     = None { class: [class None] }\n//│ res\n//│     = undefined\n//│ res\n//│     = Some {}\n\n\nmodule M[A] {\n  mut val m = None\n}\n//│ module M[A] {\n//│   mut val m: None\n//│ }\n\nM.m\n//│ None\n//│ res\n//│     = None { class: [class None] }\n\nset M.m = None\n//│ ()\n//│ res\n//│     = undefined\n\n:e\nset M.m = Some(1)\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.331: \tset M.m = Some(1)\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── application of type `Some[?A]` is not an instance of `None`\n//│ ║  l.331: \tset M.m = Some(1)\n//│ ║         \t          ^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.314: \t  mut val m = None\n//│ ║         \t              ^^^^\n//│ ╟── from assigned selection:\n//│ ║  l.331: \tset M.m = Some(1)\n//│ ╙──       \t    ^^^\n//│ ()\n//│ res\n//│     = undefined\n\n\n// * Another possible syntax, which we didn't go with (for now?)\n:e\nmodule M {\n  mut val m = None\n  fun oops(x) = m := x\n}\n//│ ╔══[ERROR] identifier not found: :=\n//│ ║  l.353: \t  fun oops(x) = m := x\n//│ ╙──       \t                  ^^\n//│ module M {\n//│   mut val m: None\n//│   fun oops: anything -> error\n//│ }\n//│ Code generation encountered an error:\n//│   unresolved symbol :=\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/InferredInheritanceTypeArgs.mls",
    "content": ":NewDefs\n\n\nmixin Test[A] {\n  fun bar: [A, A]\n  fun bar = [this.a, this.a]\n}\n//│ mixin Test[A]() {\n//│   this: {a: A}\n//│   fun bar: [A, A]\n//│ }\n\nclass A(val a: Int) extends Test\n//│ class A(a: Int) {\n//│   fun bar: [Int, Int]\n//│ }\n\n:e\nclass A(a: Int) extends Test\n//│ ╔══[ERROR] Parameter 'a' cannot be accessed as a field\n//│ ║  l.6: \t  fun bar = [this.a, this.a]\n//│ ╙──     \t                         ^^\n//│ ╔══[ERROR] Parameter 'a' cannot be accessed as a field\n//│ ║  l.6: \t  fun bar = [this.a, this.a]\n//│ ╙──     \t                 ^^\n//│ class A(a: Int) {\n//│   fun bar: [Int, Int]\n//│ }\n\nmixin Test2[S, T] {\n  fun x: [S, T]\n  fun x = [this.s, this.t]\n  fun fb: S => [S, S]\n  fun fb(h: S) = [this.s, h]\n}\n//│ mixin Test2[S, T]() {\n//│   this: {s: S, t: T}\n//│   fun fb: S -> [S, S]\n//│   fun x: [S, T]\n//│ }\n\nclass A1[B](val s: Bool, val t: B) extends Test2[Bool, B]\n//│ class A1[B](s: Bool, t: B) {\n//│   fun fb: ('S & Bool) -> [Bool | 'S, Bool | 'S]\n//│   fun x: [Bool | 'S, B]\n//│ }\n\n// * TODO: Investigate type of fb\nclass A2[A](val s: A, val t: Int) extends Test2\n//│ class A2[A](s: A, t: Int) {\n//│   fun fb: 'S -> [A | 'S, A | 'S]\n//│   fun x: [A | 'S, Int]\n//│ }\n\n// * TODO: Investigate type of fb\nclass A3(val s: Int, val t: Bool) extends Test2\n//│ class A3(s: Int, t: Bool) {\n//│   fun fb: 'S -> [Int | 'S, Int | 'S]\n//│   fun x: [Int | 'S, Bool]\n//│ }\n\nclass P(val p: Int) { \n  virtual fun foo(x) = x + p \n}\n//│ class P(p: Int) {\n//│   fun foo: Int -> Int\n//│ }\n\n:e // TODO improve type checking\nclass C1(a: Int) extends P(a) { fun bar = this.foo(0) }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.70: \tclass C1(a: Int) extends P(a) { fun bar = this.foo(0) }\n//│ ╙──      \t                                              ^^^^\n//│ class C1(a: Int) extends P {\n//│   fun bar: error\n//│   fun foo: Int -> Int\n//│ }\n\n:e // TODO improve type checking\nclass C2(a: Int, b: Int) extends P(a + b) {\n  fun foo(x) = x * this.p + a * b\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.81: \t  fun foo(x) = x * this.p + a * b\n//│ ╙──      \t                       ^^\n//│ class C2(a: Int, b: Int) extends P {\n//│   fun foo: Int -> Int\n//│ }\n\nlet c2 =  C2(1, 2)\n//│ let c2: C2\n//│ c2\n//│    = C2 {}\n\nc2.foo(2)\n//│ Int\n//│ res\n//│     = 8\n\nc2.p\n//│ Int\n//│ res\n//│     = 3\n\n\nclass Test[A](val x: A)\n//│ class Test[A](x: A)\n\nclass A(a: Int) extends Test(a)\n//│ class A(a: Int) extends Test\n\nlet a1 = A(1)\n//│ let a1: A\n//│ a1\n//│    = A {}\n\na1: Test['x]\n//│ Test['x]\n//│   where\n//│     'x :> Int\n//│ res\n//│     = A {}\n\na1.x\n//│ Int\n//│ res\n//│     = 1\n\n\n\n\ntrait Foo[A] { fun foo(x: A): A }\n//│ trait Foo[A] {\n//│   fun foo: (x: A) -> A\n//│ }\n\n// * This is pretty funky but it seems sound for now...\n// * Inherited Foo's type arg is left \"unspecified\", and since it is not constrained,\n// * it can be instantiated to any type by downstream callers of the methods!\nmodule B extends Foo { fun foo(x) = x }\n//│ module B extends Foo {\n//│   fun foo: forall 'a. 'a -> 'a\n//│ }\n\nB : Foo['X]\n//│ Foo['X]\n//│ res\n//│     = B { class: [class B extends Object] }\n\nB.foo\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: foo]\n\nB.foo(1)\n//│ 1\n//│ res\n//│     = 1\n\nmodule B extends Foo { fun foo(x) = x + 1 }\n//│ module B extends Foo {\n//│   fun foo: Int -> Int\n//│ }\n\nB : Foo['X]\n//│ Foo[Int]\n//│ res\n//│     = B { class: [class B extends Object] }\n\nB.foo\n//│ Int -> Int\n//│ res\n//│     = [Function: foo]\n\n\n// * TODO: when \n:pe\ntrait Foo[type A] { fun foo(x: A): A }\n//│ ╔══[PARSE ERROR] Unexpected 'type' keyword here\n//│ ║  l.178: \ttrait Foo[type A] { fun foo(x: A): A }\n//│ ╙──       \t          ^^^^\n//│ trait Foo {\n//│   fun foo: (x: A) -> A\n//│ }\n\n\ntrait Foo[A] { fun a: A; fun foo(x: A): A }\n//│ trait Foo[A] {\n//│   fun a: A\n//│   fun foo: (x: A) -> A\n//│ }\n\nclass Bar[out B](val a: B) extends Foo { fun foo(x) = x }\n//│ class Bar[B](a: B) extends Foo {\n//│   fun foo: forall 'a. 'a -> 'a\n//│ }\n\nlet b = Bar(123)\n//│ let b: Bar[123]\n//│ b\n//│   = Bar {}\n\nb : Foo['X]\n//│ Foo['X]\n//│   where\n//│     'X :> 123\n//│ res\n//│     = Bar {}\n\nb.foo\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: foo]\n\n\n// * Note the shadowed type variable `A` in `foo`\ntrait Foo[A] { fun foo[A](x: A): A }\n//│ trait Foo[A] {\n//│   fun foo: forall 'A. (x: 'A) -> 'A\n//│ }\n\nclass B extends Foo { fun foo(x) = x }\n//│ class B extends Foo {\n//│   constructor()\n//│   fun foo: forall 'a. 'a -> 'a\n//│ }\n\n:e\nclass B extends Foo { fun foo(x) = x + 1 }\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.229: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ║         \t                          ^^^^^^^^^^^^^^\n//│ ╟── type `A` is not an instance of type `Int`\n//│ ║  l.217: \ttrait Foo[A] { fun foo[A](x: A): A }\n//│ ║         \t                       ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.229: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ╙──       \t                                   ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.229: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ║         \t                          ^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Int` does not match type `A`\n//│ ║  l.229: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ║         \t                                   ^^^^^\n//│ ╟── Note: constraint arises from method type parameter:\n//│ ║  l.217: \ttrait Foo[A] { fun foo[A](x: A): A }\n//│ ╙──       \t                       ^\n//│ class B extends Foo {\n//│   constructor()\n//│   fun foo: Int -> Int\n//│ }\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/InheritanceLevelMismatches.mls",
    "content": ":NewDefs\n\n:NoJS // TODO\n\n\ntrait T1 { fun x: 0 | 1 }\n//│ trait T1 {\n//│   fun x: 0 | 1\n//│ }\n\nmodule Foo {\n  trait T2 { fun x: 1 | 2 }\n  class C extends T1, T2 { fun x = 1 }\n}\n//│ module Foo {\n//│   class C extends T1, T2 {\n//│     constructor()\n//│     fun x: 1\n//│   }\n//│   trait T2 {\n//│     fun x: 1 | 2\n//│   }\n//│ }\n\n\nmixin Foo { fun f = this.x }\n//│ mixin Foo() {\n//│   this: {x: 'x}\n//│   fun f: 'x\n//│ }\n\nmodule Bar {\n  class C(val x: Int) extends Foo\n}\n//│ module Bar {\n//│   class C(x: Int) {\n//│     fun f: Int\n//│   }\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/IntLit.mls",
    "content": ":NewDefs\n\n// Decimal literals.\n[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\n[-0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]\n//│ [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]\n//│ res\n//│     = [\n//│          0, 1, 2, 3, 4,\n//│          5, 6, 7, 8, 9,\n//│         10\n//│       ]\n//│ res\n//│     = [\n//│           0, -1, -2, -3, -4,\n//│          -5, -6, -7, -8, -9,\n//│         -10\n//│       ]\n\n// Hexadecimal literals.\n[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A]\n[-0x00, -0x01, -0x02, -0x03, -0x04, -0x05, -0x06, -0x07, -0x08, -0x09, -0x0A]\n//│ [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]\n//│ res\n//│     = [\n//│          0, 1, 2, 3, 4,\n//│          5, 6, 7, 8, 9,\n//│         10\n//│       ]\n//│ res\n//│     = [\n//│           0, -1, -2, -3, -4,\n//│          -5, -6, -7, -8, -9,\n//│         -10\n//│       ]\n\n// Octal literals.\n[0o00, 0o01, 0o02, 0o03, 0o04, 0o05, 0o06, 0o07, 0o10, 0o11, 0o12]\n[-0o00, -0o01, -0o02, -0o03, -0o04, -0o05, -0o06, -0o07, -0o10, -0o11, -0o12]\n//│ [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]\n//│ res\n//│     = [\n//│          0, 1, 2, 3, 4,\n//│          5, 6, 7, 8, 9,\n//│         10\n//│       ]\n//│ res\n//│     = [\n//│           0, -1, -2, -3, -4,\n//│          -5, -6, -7, -8, -9,\n//│         -10\n//│       ]\n\n// Binary literals.\n[0b0000, 0b0001, 0b0010, 0b0011, 0b0100, 0b0101, 0b0110, 0b0111, 0b1000, 0b1001, 0b1010]\n[-0b0, -0b1, -0b10, -0b11, -0b100, -0b101, -0b110, -0b111, -0b1000, -0b1001, -0b1010]\n//│ [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]\n//│ res\n//│     = [\n//│          0, 1, 2, 3, 4,\n//│          5, 6, 7, 8, 9,\n//│         10\n//│       ]\n//│ res\n//│     = [\n//│           0, -1, -2, -3, -4,\n//│          -5, -6, -7, -8, -9,\n//│         -10\n//│       ]\n\n:pe\n0b\n//│ ╔══[LEXICAL ERROR] Expect at least one binary digit\n//│ ║  l.72: \t0b\n//│ ╙──      \t  ^^\n//│ 0\n//│ res\n//│     = 0\n\n:pe\n0x\n//│ ╔══[LEXICAL ERROR] Expect at least one hexadecimal digit\n//│ ║  l.81: \t0x\n//│ ╙──      \t  ^^\n//│ 0\n//│ res\n//│     = 0\n\n:pe\n0o\n//│ ╔══[LEXICAL ERROR] Expect at least one octal digit\n//│ ║  l.90: \t0o\n//│ ╙──      \t  ^^\n//│ 0\n//│ res\n//│     = 0\n\n// Underscores as separators in numeric literals.\n1_000_000\n0xDEAD_CAFE\n0b0010_0100_0011_0100\n//│ 9268\n//│ res\n//│     = 1000000\n//│ res\n//│     = 3735931646\n//│ res\n//│     = 9268\n\n// Trailing underscores are not allowed.\n:w\n0b00000000010_\n0xCAFE_____\n//│ ╔══[WARNING] Trailing separator is not allowed\n//│ ║  l.112: \t0b00000000010_\n//│ ╙──       \t             ^\n//│ ╔══[WARNING] Trailing separator is not allowed\n//│ ║  l.113: \t0xCAFE_____\n//│ ╙──       \t          ^\n//│ 51966\n//│ res\n//│     = 2\n//│ res\n//│     = 51966\n\n// Extra leading zeros are discarded.\n0123\n023456\n00\n0\n//│ 0\n//│ res\n//│     = 123\n//│ res\n//│     = 23456\n//│ res\n//│     = 0\n//│ res\n//│     = 0\n"
  },
  {
    "path": "shared/src/test/diff/nu/InterfaceGeneric.mls",
    "content": ":NewDefs\n:NoJS\n\ntrait Into[T] {\n  fun Into: T\n}\n//│ trait Into[T] {\n//│   fun Into: T\n//│ }\n\ntrait Nat extends Into[Int]\n//│ trait Nat extends Into {\n//│   fun Into: 'T\n//│ }\n//│ where\n//│   'T := Int\n\ntrait Product[A, B] extends Into[A] {\n  val pair: [A, B]\n}\n//│ trait Product[A, B] extends Into {\n//│   fun Into: 'T\n//│   val pair: [A, B]\n//│ }\n//│ where\n//│   'T := A\n\nclass TwoInts(val pair: [Int, Int]) extends Product[Int, Int] {\n  fun Into = pair.0 + pair.1\n}\n//│ class TwoInts(pair: [Int, Int]) extends Into, Product {\n//│   fun Into: Int\n//│ }\n\nlet i2 = TwoInts([1, 2])\n//│ let i2: TwoInts\n\ni2: Product[Int, Int]\n//│ Product[Int, Int]\n\ni2: Into[Int]\n//│ Into[Int]\n\ni2.pair\n//│ [Int, Int]\n\ni2.Into\n//│ Int\n\nval p1: Product[Int, Int]\n//│ val p1: Product[Int, Int]\n\n:e\np1: Product[Bool, Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.54: \tp1: Product[Bool, Int]\n//│ ║        \t^^\n//│ ╙── expression of type `Int` does not match type `Bool`\n//│ Product[Bool, Int]\n\np1: Into[Int]\n//│ Into[Int]\n\n:e\np1: Into[Bool]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.65: \tp1: Into[Bool]\n//│ ║        \t^^\n//│ ╙── expression of type `Int` does not match type `Bool`\n//│ Into[Bool]\n"
  },
  {
    "path": "shared/src/test/diff/nu/InterfaceMono.mls",
    "content": ":NewDefs\n\n\ntrait Showable {\n  fun toString: Str\n}\n//│ trait Showable {\n//│   fun toString: Str\n//│ }\n\n:e\ntrait What0 extends woooo\n//│ ╔══[ERROR] Could not find definition `woooo`\n//│ ║  l.12: \ttrait What0 extends woooo\n//│ ╙──      \t                    ^^^^^\n//│ trait What0\n\nclass PoInt(x: Int, y: Int) extends Showable {\n  fun mlen = x + y\n  fun toString = \"I'm a poInt\"\n}\n//│ class PoInt(x: Int, y: Int) extends Showable {\n//│   fun mlen: Int\n//│   fun toString: \"I'm a poInt\"\n//│ }\n\nclass What1(val toString: Str) extends Showable\n//│ class What1(toString: Str) extends Showable\n\n:e\ntrait NoShow extends What1(\"hi\")\n//│ ╔══[ERROR] A trait can only inherit from other traits\n//│ ║  l.31: \ttrait NoShow extends What1(\"hi\")\n//│ ╙──      \t                     ^^^^^^^^^^^\n//│ trait NoShow extends Showable, What1\n\n:e\nclass ErrC1 extends Showable\nclass ErrC2 extends Showable {\n  fun toString = 114\n}\nclass ErrC3(val toString: Str -> Str) extends Showable\n//│ ╔══[ERROR] Member `toString` is declared (or its declaration is inherited) but is not implemented in `ErrC1`\n//│ ║  l.38: \tclass ErrC1 extends Showable\n//│ ║        \t      ^^^^^\n//│ ╟── Declared here:\n//│ ║  l.5: \t  fun toString: Str\n//│ ╙──     \t  ^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in definition of method toString:\n//│ ║  l.40: \t  fun toString = 114\n//│ ║        \t      ^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `114` is not an instance of type `Str`\n//│ ║  l.40: \t  fun toString = 114\n//│ ║        \t                 ^^^\n//│ ╟── but it flows into definition of method toString with expected type `Str`\n//│ ║  l.40: \t  fun toString = 114\n//│ ║        \t      ^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.5: \t  fun toString: Str\n//│ ║       \t                ^^^\n//│ ╟── from signature of member `toString`:\n//│ ║  l.5: \t  fun toString: Str\n//│ ╙──     \t      ^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in function type:\n//│ ║  l.42: \tclass ErrC3(val toString: Str -> Str) extends Showable\n//│ ║        \t                          ^^^^^^^^^^\n//│ ╟── type `Str -> Str` is not an instance of type `Str`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.5: \t  fun toString: Str\n//│ ║       \t                ^^^\n//│ ╟── from signature of member `toString`:\n//│ ║  l.5: \t  fun toString: Str\n//│ ╙──     \t      ^^^^^^^^^^^^^\n//│ class ErrC1 extends Showable {\n//│   constructor()\n//│   fun toString: Str\n//│ }\n//│ class ErrC2 extends Showable {\n//│   constructor()\n//│   fun toString: 114\n//│ }\n//│ class ErrC3(toString: Str -> Str) extends Showable\n\ntrait Stadt {\n  val name: Str\n}\n//│ trait Stadt {\n//│   val name: Str\n//│ }\n\ntrait RefinedStadt extends Stadt {\n  val size: Int\n  fun foo: Bool -> Int\n}\n//│ trait RefinedStadt extends Stadt {\n//│   fun foo: Bool -> Int\n//│   val name: Str\n//│   val size: Int\n//│ }\n\ntrait SizedStadt extends RefinedStadt {\n  val size: 1 | 2 | 3\n  fun bar: Int -> Int\n}\n//│ trait SizedStadt extends RefinedStadt, Stadt {\n//│   fun bar: Int -> Int\n//│   fun foo: Bool -> Int\n//│   val name: Str\n//│   val size: 1 | 2 | 3\n//│ }\n\nclass Goodstatt(val size: 1 | 2) extends RefinedStadt {\n  val name = \"good\"\n  fun bar(x) = x\n  fun foo(t) = if t && true then this.size else 0\n}\n//│ class Goodstatt(size: 1 | 2) extends RefinedStadt, Stadt {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: Bool -> (0 | 1 | 2)\n//│   val name: \"good\"\n//│ }\n\n:e\nclass Errcity(val size: Int) extends SizedStadt {\n  fun bar = \"hahaha\"\n}\n//│ ╔══[ERROR] Type mismatch in definition of method bar:\n//│ ║  l.125: \t  fun bar = \"hahaha\"\n//│ ║         \t      ^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"hahaha\"` is not a function\n//│ ║  l.125: \t  fun bar = \"hahaha\"\n//│ ║         \t            ^^^^^^^^\n//│ ╟── but it flows into definition of method bar with expected type `Int -> Int`\n//│ ║  l.125: \t  fun bar = \"hahaha\"\n//│ ║         \t      ^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.103: \t  fun bar: Int -> Int\n//│ ║         \t           ^^^^^^^^^^\n//│ ╟── from signature of member `bar`:\n//│ ║  l.103: \t  fun bar: Int -> Int\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.124: \tclass Errcity(val size: Int) extends SizedStadt {\n//│ ║         \t                        ^^^\n//│ ╟── type `Int` does not match type `1 | 2 | 3`\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.102: \t  val size: 1 | 2 | 3\n//│ ║         \t            ^^^^^^^^^\n//│ ╟── from signature of member `size`:\n//│ ║  l.102: \t  val size: 1 | 2 | 3\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Member `name` is declared (or its declaration is inherited) but is not implemented in `Errcity`\n//│ ║  l.124: \tclass Errcity(val size: Int) extends SizedStadt {\n//│ ║         \t      ^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.85: \t  val name: Str\n//│ ╙──      \t  ^^^^^^^^^^^^^\n//│ ╔══[ERROR] Member `foo` is declared (or its declaration is inherited) but is not implemented in `Errcity`\n//│ ║  l.124: \tclass Errcity(val size: Int) extends SizedStadt {\n//│ ║         \t      ^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.93: \t  fun foo: Bool -> Int\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^\n//│ class Errcity(size: Int) extends RefinedStadt, SizedStadt, Stadt {\n//│   fun bar: \"hahaha\"\n//│   fun foo: Bool -> Int\n//│   val name: Str\n//│ }\n\nmodule Omg extends Stadt {\n  fun name = \"omg!!!\"\n  fun cool(x) = x + x\n}\n//│ module Omg extends Stadt {\n//│   fun cool: Int -> Int\n//│   fun name: \"omg!!!\"\n//│ }\n\nmixin More {\n  fun more(x) = x == 1\n  fun size = 1\n  fun bar(x) = x\n}\n//│ mixin More() {\n//│   fun bar: 'a -> 'a\n//│   fun more: Num -> Bool\n//│   fun size: 1\n//│ }\n\nmixin Fooo {\n  fun foo(x) = 0\n}\n//│ mixin Fooo() {\n//│   fun foo: anything -> 0\n//│ }\n\nclass Grassberg(val name: \"grass\" | \"GRASS\") extends More, SizedStadt, Fooo\n//│ class Grassberg(name: \"GRASS\" | \"grass\") extends RefinedStadt, SizedStadt, Stadt {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: anything -> 0\n//│   fun more: Num -> Bool\n//│   fun size: 1\n//│ }\n\n:e\nclass Dirtberg extends More, SizedStadt, Fooo {\n  let name = \"dirt\"\n  fun size = 4  // this should not check\n}\n//│ ╔══[ERROR] Cannot implement value member 'name' with a let binding\n//│ ║  l.207: \t  let name = \"dirt\"\n//│ ║         \t      ^^^^^^^^^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.85: \t  val name: Str\n//│ ╙──      \t  ^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in definition of method size:\n//│ ║  l.208: \t  fun size = 4  // this should not check\n//│ ║         \t      ^^^^^^^^\n//│ ╟── integer literal of type `4` does not match type `1 | 2 | 3`\n//│ ║  l.208: \t  fun size = 4  // this should not check\n//│ ║         \t             ^\n//│ ╟── but it flows into definition of method size with expected type `1 | 2 | 3`\n//│ ║  l.208: \t  fun size = 4  // this should not check\n//│ ║         \t      ^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.102: \t  val size: 1 | 2 | 3\n//│ ║         \t            ^^^^^^^^^\n//│ ╟── from signature of member `size`:\n//│ ║  l.102: \t  val size: 1 | 2 | 3\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Member `name` is declared (or its declaration is inherited) but is not implemented in `Dirtberg`\n//│ ║  l.206: \tclass Dirtberg extends More, SizedStadt, Fooo {\n//│ ║         \t      ^^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.85: \t  val name: Str\n//│ ║        \t  ^^^^^^^^^^^^^\n//│ ╟── Note: value member `name` is private and cannot be used as a valid implementation\n//│ ║  l.207: \t  let name = \"dirt\"\n//│ ╙──       \t      ^^^^^^^^^^^^^\n//│ class Dirtberg extends RefinedStadt, SizedStadt, Stadt {\n//│   constructor()\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: anything -> 0\n//│   fun more: Num -> Bool\n//│   let name: \"dirt\"\n//│   fun size: 4\n//│ }\n\nnew Dirtberg().size\n//│ 4\n//│ res\n//│     = 4\n\nclass Iceburg(val name: Str) extends RefinedStadt, More, Fooo\n//│ class Iceburg(name: Str) extends RefinedStadt, Stadt {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: anything -> 0\n//│   fun more: Num -> Bool\n//│   fun size: 1\n//│ }\n\nclass A { virtual fun x: Int = 1 }\n//│ class A {\n//│   constructor()\n//│   fun x: Int\n//│ }\n\n:e\nclass B extends A { fun x = \"A\" }\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.269: \tclass B extends A { fun x = \"A\" }\n//│ ║         \t                        ^^^^^^^\n//│ ╟── string literal of type `\"A\"` is not an instance of type `Int`\n//│ ║  l.269: \tclass B extends A { fun x = \"A\" }\n//│ ║         \t                            ^^^\n//│ ╟── but it flows into definition of method x with expected type `Int`\n//│ ║  l.269: \tclass B extends A { fun x = \"A\" }\n//│ ║         \t                        ^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.262: \tclass A { virtual fun x: Int = 1 }\n//│ ║         \t                         ^^^\n//│ ╟── from definition of method x:\n//│ ║  l.262: \tclass A { virtual fun x: Int = 1 }\n//│ ╙──       \t                      ^^^^^^^^^^\n//│ class B extends A {\n//│   constructor()\n//│   fun x: \"A\"\n//│ }\n\n:e\nclass C1[A] { virtual fun a: A = this.a }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.291: \tclass C1[A] { virtual fun a: A = this.a }\n//│ ╙──       \t                                     ^^\n//│ class C1[A] {\n//│   constructor()\n//│   fun a: A\n//│ }\n\nclass C2 extends C1[Int] { fun a = 1 }\n//│ class C2 extends C1 {\n//│   constructor()\n//│   fun a: 1\n//│ }\n\n// trait MyTrait[A] { type MyTrait#A = A; fun a: A = a }\n// freshen/subst\n// trait MyTrait[Int] { type MyTrait#A = Int; fun a: Int = a }\n\ntrait MyTrait[A] { fun a: A }\n//│ trait MyTrait[A] {\n//│   fun a: A\n//│ }\n\n// :ns\n// :d\n// :ds\nclass C extends MyTrait[Int] { fun a = 1 }\n//│ class C extends MyTrait {\n//│   constructor()\n//│   fun a: 1\n//│ }\n\n:e\nclass C extends MyTrait[Int] { fun a = false }\n//│ ╔══[ERROR] Type mismatch in definition of method a:\n//│ ║  l.325: \tclass C extends MyTrait[Int] { fun a = false }\n//│ ║         \t                                   ^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of `Int`\n//│ ║  l.325: \tclass C extends MyTrait[Int] { fun a = false }\n//│ ║         \t                                       ^^^^^\n//│ ╟── but it flows into definition of method a with expected type `Int`\n//│ ║  l.325: \tclass C extends MyTrait[Int] { fun a = false }\n//│ ║         \t                                   ^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.325: \tclass C extends MyTrait[Int] { fun a = false }\n//│ ║         \t                        ^^^\n//│ ╟── from signature of member `a`:\n//│ ║  l.310: \ttrait MyTrait[A] { fun a: A }\n//│ ╙──       \t                       ^^^^\n//│ class C extends MyTrait {\n//│   constructor()\n//│   fun a: false\n//│ }\n\n\ntrait T1 { \n  val foo : 1 | 2 | 3 \n  fun bar : Str | Bool\n}\ntrait T2 { \n  val foo : 2 | 3 | 4\n  val bar : Int | Bool\n}\n//│ trait T1 {\n//│   fun bar: Str | false | true\n//│   val foo: 1 | 2 | 3\n//│ }\n//│ trait T2 {\n//│   val bar: Int | false | true\n//│   val foo: 2 | 3 | 4\n//│ }\n\ntrait T4 extends T1, T2 {\n  fun foo: 2\n}\n//│ trait T4 extends T1, T2 {\n//│   fun bar: Bool\n//│   fun foo: 2\n//│ }\n\nclass C1(val foo: 2, val bar: true) extends T4\n//│ class C1(foo: 2, bar: true) extends T1, T2, T4\n\n:e\nclass C3 extends T4{\n  fun foo = 3\n  fun bar = false\n}\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.377: \t  fun foo = 3\n//│ ║         \t      ^^^^^^^\n//│ ╟── integer literal of type `3` does not match type `2`\n//│ ║  l.377: \t  fun foo = 3\n//│ ║         \t            ^\n//│ ╟── but it flows into definition of method foo with expected type `2`\n//│ ║  l.377: \t  fun foo = 3\n//│ ║         \t      ^^^^^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.365: \t  fun foo: 2\n//│ ║         \t           ^\n//│ ╟── from signature of member `foo`:\n//│ ║  l.365: \t  fun foo: 2\n//│ ╙──       \t      ^^^^^^\n//│ class C3 extends T1, T2, T4 {\n//│   constructor()\n//│   fun bar: false\n//│   fun foo: 3\n//│ }\n\n:e\nclass C2(val foo: Int, val bar: Str) extends T4\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.402: \tclass C2(val foo: Int, val bar: Str) extends T4\n//│ ║         \t                  ^^^\n//│ ╟── type `Int` does not match type `2`\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.365: \t  fun foo: 2\n//│ ║         \t           ^\n//│ ╟── from signature of member `foo`:\n//│ ║  l.365: \t  fun foo: 2\n//│ ╙──       \t      ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.402: \tclass C2(val foo: Int, val bar: Str) extends T4\n//│ ║         \t                                ^^^\n//│ ╟── type `Str` does not match type `Int | false | true`\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.353: \t  val bar : Int | Bool\n//│ ║         \t            ^^^^^^^^^^\n//│ ╟── from signature of member `bar`:\n//│ ║  l.353: \t  val bar : Int | Bool\n//│ ╙──       \t      ^^^^^^^^^^^^^^^^\n//│ class C2(foo: Int, bar: Str) extends T1, T2, T4\n\n:e\ntrait T5 extends T4 {\n  val foo: 4\n}\n//│ ╔══[ERROR] Type mismatch in signature of member `foo`:\n//│ ║  l.427: \t  val foo: 4\n//│ ║         \t      ^^^^^^\n//│ ╟── type `4` does not match type `2`\n//│ ║  l.427: \t  val foo: 4\n//│ ║         \t           ^\n//│ ╟── but it flows into signature of member `foo` with expected type `2`\n//│ ║  l.427: \t  val foo: 4\n//│ ║         \t      ^^^^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.365: \t  fun foo: 2\n//│ ║         \t           ^\n//│ ╟── from signature of member `foo`:\n//│ ║  l.365: \t  fun foo: 2\n//│ ╙──       \t      ^^^^^^\n//│ trait T5 extends T1, T2, T4 {\n//│   fun bar: Bool\n//│   val foo: 4\n//│ }\n\n:e\ntrait T3 extends T1, T2 {\n  val foo: true\n}\n//│ ╔══[ERROR] Type mismatch in signature of member `foo`:\n//│ ║  l.451: \t  val foo: true\n//│ ║         \t      ^^^^^^^^^\n//│ ╟── type `true` does not match type `1 | 2 | 3`\n//│ ║  l.451: \t  val foo: true\n//│ ║         \t           ^^^^\n//│ ╟── but it flows into signature of member `foo` with expected type `1 | 2 | 3`\n//│ ║  l.451: \t  val foo: true\n//│ ║         \t      ^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.348: \t  val foo : 1 | 2 | 3 \n//│ ║         \t            ^^^^^^^^^\n//│ ╟── from signature of member `foo`:\n//│ ║  l.348: \t  val foo : 1 | 2 | 3 \n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in signature of member `foo`:\n//│ ║  l.451: \t  val foo: true\n//│ ║         \t      ^^^^^^^^^\n//│ ╟── type `true` does not match type `2 | 3 | 4`\n//│ ║  l.451: \t  val foo: true\n//│ ║         \t           ^^^^\n//│ ╟── but it flows into signature of member `foo` with expected type `2 | 3 | 4`\n//│ ║  l.451: \t  val foo: true\n//│ ║         \t      ^^^^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.352: \t  val foo : 2 | 3 | 4\n//│ ║         \t            ^^^^^^^^^\n//│ ╟── from signature of member `foo`:\n//│ ║  l.352: \t  val foo : 2 | 3 | 4\n//│ ╙──       \t      ^^^^^^^^^^^^^^^\n//│ trait T3 extends T1, T2 {\n//│   fun bar: Bool\n//│   val foo: true\n//│ }\n"
  },
  {
    "path": "shared/src/test/diff/nu/Interfaces.mls",
    "content": ":NewDefs\n\n\ntrait Test {\n  fun foo: Int\n  fun bar: Bool -> Bool\n}\n//│ trait Test {\n//│   fun bar: Bool -> Bool\n//│   fun foo: Int\n//│ }\n\nfun ts(x: Test) = x.foo\n//│ fun ts: (x: Test) -> Int\n\n\nmodule M extends Test {\n  fun foo = 0\n  fun bar = not\n}\n//│ module M extends Test {\n//│   fun bar: Bool -> Bool\n//│   fun foo: 0\n//│ }\n\nM: Test\n//│ Test\n//│ res\n//│     = M { class: [class M extends Object] }\n\nts(M)\n//│ Int\n//│ res\n//│     = 0\n\ntrait Oth extends Test {\n  val a : Int\n  fun cool : Int -> Bool\n}\n//│ trait Oth extends Test {\n//│   val a: Int\n//│   fun bar: Bool -> Bool\n//│   fun cool: Int -> Bool\n//│   fun foo: Int\n//│ }\n\nval oth1: Oth\n//│ val oth1: Oth\n//│ oth1\n//│      = <missing implementation>\n\noth1.bar(true)\n//│ Bool\n//│ res\n//│     = <no result>\n//│       oth1 is not implemented\n\noth1: Test\n//│ Test\n//│ res\n//│     = <no result>\n//│       oth1 is not implemented\n\n:e\nM : Oth\noth1: M\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.65: \tM : Oth\n//│ ║        \t^\n//│ ╟── reference of type `M` is not an instance of type `Oth`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.65: \tM : Oth\n//│ ╙──      \t    ^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.66: \toth1: M\n//│ ║        \t^^^^\n//│ ╟── type `#Oth` is not an instance of type `M`\n//│ ║  l.47: \tval oth1: Oth\n//│ ║        \t          ^^^\n//│ ╟── but it flows into reference with expected type `M`\n//│ ║  l.66: \toth1: M\n//│ ║        \t^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.66: \toth1: M\n//│ ╙──      \t      ^\n//│ M\n//│ res\n//│     = M { class: [class M extends Object] }\n//│ res\n//│     = <no result>\n//│       oth1 is not implemented\n\ntrait Geo { \n  val v: 2 | 3 \n  fun get: Int | Bool\n  fun ter: Int\n}\ntrait Anemo { \n  val v: 1 | 2\n  fun get: Bool | string\n  fun ter: Bool\n}\n//│ trait Geo {\n//│   fun get: Int | false | true\n//│   fun ter: Int\n//│   val v: 2 | 3\n//│ }\n//│ trait Anemo {\n//│   fun get: false | string | true\n//│   fun ter: Bool\n//│   val v: 1 | 2\n//│ }\n\ntrait Mixed extends Geo, Anemo\n//│ trait Mixed extends Anemo, Geo {\n//│   fun get: Bool\n//│   fun ter: nothing\n//│   val v: 2\n//│ }\n\n\nclass C() extends Test {\n  fun foo: 1 = 1\n  fun bar(x) = x\n}\n//│ class C() extends Test {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: 1\n//│ }\n\nmixin M {\n  fun m1 = 3\n}\n//│ mixin M() {\n//│   fun m1: 3\n//│ }\n\nclass F() extends Oth, M, Mixed {\n  fun cool(x) = x === 1\n  fun foo = 2\n  fun bar(x) = x\n  fun get = true\n  fun ter = ter\n  val a = 3\n  val v = 2\n}\n//│ class F() extends Anemo, Geo, Mixed, Oth, Test {\n//│   val a: 3\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun cool: Eql[1] -> Bool\n//│   fun foo: 2\n//│   fun get: true\n//│   fun m1: 3\n//│   fun ter: nothing\n//│   val v: 2\n//│ }\n\nval fi = F()\n//│ val fi: F\n//│ fi\n//│    = F {}\n\nfi : Oth & Geo\n//│ Geo & Oth\n//│ res\n//│     = F {}\n\nfi.get\n//│ true\n//│ res\n//│     = true\n\nfi: Test & Anemo\n//│ Anemo & Test\n//│ res\n//│     = F {}\n\nval fog: Oth & Mixed\n//│ val fog: Mixed & Oth\n//│ fog\n//│     = <missing implementation>\n\nfog: Test & Anemo\n//│ Anemo & Test\n//│ res\n//│     = <no result>\n//│       fog is not implemented\n\n:e\nfog: F\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.190: \tfog: F\n//│ ║         \t^^^\n//│ ╟── type `Mixed & Oth` is not an instance of type `F`\n//│ ║  l.178: \tval fog: Oth & Mixed\n//│ ║         \t         ^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `F`\n//│ ║  l.190: \tfog: F\n//│ ║         \t^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.190: \tfog: F\n//│ ╙──       \t     ^\n//│ F\n//│ res\n//│     = <no result>\n//│       fog is not implemented\n\nval c = C()\n//│ val c: C\n//│ c\n//│   = C {}\n\nc: Eql<C>\n//│ Eql[C]\n//│ res\n//│     = C {}\n\nval ct: Test = c\n//│ val ct: Test\n//│ ct\n//│    = C {}\n\nc.foo\n//│ 1\n//│ res\n//│     = 1\n\nc.bar(true)\n//│ true\n//│ res\n//│     = true\n\n// :d\nc: Test\n//│ Test\n//│ res\n//│     = C {}\n\n:e\nc: Oth\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.240: \tc: Oth\n//│ ║         \t^\n//│ ╟── application of type `C` is not an instance of type `Oth`\n//│ ║  l.208: \tval c = C()\n//│ ║         \t        ^^^\n//│ ╟── but it flows into reference with expected type `#Oth`\n//│ ║  l.240: \tc: Oth\n//│ ║         \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.240: \tc: Oth\n//│ ╙──       \t   ^^^\n//│ Oth\n//│ res\n//│     = C {}\n\n// :d\nval c1: Test = C()\n//│ val c1: Test\n//│ c1\n//│    = C {}\n\n// :d\nfun fcc(x: C) = x.foo\n//│ fun fcc: (x: C) -> 1\n\nfun fc(x: Test) = x\nfun ffm(x: F) = x.get\n//│ fun fc: (x: Test) -> Test\n//│ fun ffm: (x: F) -> true\n\n:e\nfun fee(x: Test) = x: Oth\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.273: \tfun fee(x: Test) = x: Oth\n//│ ║         \t                   ^\n//│ ╟── type `#Test` is not an instance of type `Oth`\n//│ ║  l.273: \tfun fee(x: Test) = x: Oth\n//│ ║         \t           ^^^^\n//│ ╟── but it flows into reference with expected type `#Oth`\n//│ ║  l.273: \tfun fee(x: Test) = x: Oth\n//│ ║         \t                   ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.273: \tfun fee(x: Test) = x: Oth\n//│ ╙──       \t                      ^^^\n//│ fun fee: (x: Test) -> Oth\n\nfc(c)\n//│ Test\n//│ res\n//│     = C {}\n\nfun fts['a](x: 'a & Test) = x.foo\nfts(c)\n//│ fun fts: (x: Test) -> Int\n//│ Int\n//│ res\n//│     = 1\n\nfts(oth1)\n//│ Int\n//│ res\n//│     = <no result>\n//│       oth1 is not implemented\n\nfts(c1)\n//│ Int\n//│ res\n//│     = 1\n\ntrait A1 { fun a1: 1 | 2 | 3 }\ntrait A2 { fun a1: 2 | 3 | 4 }\n//│ trait A1 {\n//│   fun a1: 1 | 2 | 3\n//│ }\n//│ trait A2 {\n//│   fun a1: 2 | 3 | 4\n//│ }\n\n:e\nclass Ea1 extends A1, A2 {\n  fun a1 = 4\n}\n//│ ╔══[ERROR] Type mismatch in definition of method a1:\n//│ ║  l.322: \t  fun a1 = 4\n//│ ║         \t      ^^^^^^\n//│ ╟── integer literal of type `4` does not match type `1 | 2 | 3`\n//│ ║  l.322: \t  fun a1 = 4\n//│ ║         \t           ^\n//│ ╟── but it flows into definition of method a1 with expected type `1 | 2 | 3`\n//│ ║  l.322: \t  fun a1 = 4\n//│ ║         \t      ^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.311: \ttrait A1 { fun a1: 1 | 2 | 3 }\n//│ ║         \t                   ^^^^^^^^^\n//│ ╟── from signature of member `a1`:\n//│ ║  l.311: \ttrait A1 { fun a1: 1 | 2 | 3 }\n//│ ╙──       \t               ^^^^^^^^^^^^^\n//│ class Ea1 extends A1, A2 {\n//│   constructor()\n//│   fun a1: 4\n//│ }\n\ntrait Ele {\n  fun ce: Oth -> Test\n}\n//│ trait Ele {\n//│   fun ce: Oth -> Test\n//│ }\n\nclass CE extends Ele {\n  fun ce(x) = x\n}\n//│ class CE extends Ele {\n//│   constructor()\n//│   fun ce: forall 'a. 'a -> 'a\n//│ }\n\n:e\nclass E1 extends Test {\n  fun foo = 2\n}\n//│ ╔══[ERROR] Member `bar` is declared (or its declaration is inherited) but is not implemented in `E1`\n//│ ║  l.360: \tclass E1 extends Test {\n//│ ║         \t      ^^\n//│ ╟── Declared here:\n//│ ║  l.6: \t  fun bar: Bool -> Bool\n//│ ╙──     \t  ^^^^^^^^^^^^^^^^^^^^^\n//│ class E1 extends Test {\n//│   constructor()\n//│   fun bar: Bool -> Bool\n//│   fun foo: 2\n//│ }\n\n:e\ntrait TE1 extends C\ntrait TE2 extends M, Test\n//│ ╔══[ERROR] A trait can only inherit from other traits\n//│ ║  l.376: \ttrait TE1 extends C\n//│ ╙──       \t                  ^\n//│ ╔══[ERROR] A trait can only inherit from other traits\n//│ ║  l.377: \ttrait TE2 extends M, Test\n//│ ╙──       \t                  ^\n//│ trait TE1 extends C, Test\n//│ trait TE2 extends Test {\n//│   fun bar: Bool -> Bool\n//│   fun foo: Int\n//│ }\n\n:e\nclass E2 extends Test {\n  fun foo = true\n  fun bar(x) = x\n}\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.392: \t  fun foo = true\n//│ ║         \t      ^^^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Int`\n//│ ║  l.392: \t  fun foo = true\n//│ ║         \t            ^^^^\n//│ ╟── but it flows into definition of method foo with expected type `Int`\n//│ ║  l.392: \t  fun foo = true\n//│ ║         \t      ^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.5: \t  fun foo: Int\n//│ ║       \t           ^^^\n//│ ╟── from signature of member `foo`:\n//│ ║  l.5: \t  fun foo: Int\n//│ ╙──     \t      ^^^^^^^^\n//│ class E2 extends Test {\n//│   constructor()\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: true\n//│ }\n\n:e\nclass D extends Test[Int], Test[Bool]\n//│ ╔══[ERROR] trait Test expects 0 type parameter(s); got 1\n//│ ║  l.417: \tclass D extends Test[Int], Test[Bool]\n//│ ╙──       \t                ^^^^^^^^\n//│ ╔══[ERROR] trait Test expects 0 type parameter(s); got 1\n//│ ║  l.417: \tclass D extends Test[Int], Test[Bool]\n//│ ╙──       \t                           ^^^^^^^^^\n//│ ╔══[ERROR] Member `foo` is declared (or its declaration is inherited) but is not implemented in `D`\n//│ ║  l.417: \tclass D extends Test[Int], Test[Bool]\n//│ ║         \t      ^\n//│ ╟── Declared here:\n//│ ║  l.5: \t  fun foo: Int\n//│ ╙──     \t      ^^^^^^^^\n//│ ╔══[ERROR] Member `bar` is declared (or its declaration is inherited) but is not implemented in `D`\n//│ ║  l.417: \tclass D extends Test[Int], Test[Bool]\n//│ ║         \t      ^\n//│ ╟── Declared here:\n//│ ║  l.6: \t  fun bar: Bool -> Bool\n//│ ╙──     \t      ^^^^^^^^^^^^^^^^^\n//│ class D extends Test {\n//│   constructor()\n//│   fun bar: Bool -> Bool\n//│   fun foo: Int\n//│ }\n\n\n\ntrait Base: A | B\nclass A() extends Base\nclass B() extends Base\n//│ trait Base: A | B\n//│ class A() extends Base\n//│ class B() extends Base\n\n\nval b: Base = A()\n//│ val b: Base\n//│ b\n//│   = A {}\n\nb: Base & (A | B)\n//│ A & Base | B & Base\n//│ res\n//│     = A {}\n\nif b is\n  A then 0\n  B then 1\n//│ 0 | 1\n//│ res\n//│     = 0\n\n\nfun f(x: Base) = if x is\n  A then 0\n  B then 1\n//│ fun f: (x: Base) -> (0 | 1)\n\ntrait Base: Foo | Bar\nclass Foo[A](val aa: [A, A]) extends Base\nclass Bar[B](f: B => B) extends Base\n//│ trait Base: Bar[?] | Foo[anything]\n//│ class Foo[A](aa: [A, A]) extends Base\n//│ class Bar[B](f: B -> B) extends Base\n\nval f: Foo = Foo([1, 2])\n//│ val f: Foo[anything]\n//│ f\n//│   = Foo {}\n\nf.aa\n//│ [??A, ??A]\n//│ res\n//│     = [ 1, 2 ]\n\nval b: Base = f\n//│ val b: Base\n//│ b\n//│   = Foo {}\n\nif b is Foo(a) then a else 0\n//│ 0 | [??A, ??A]\n//│ res\n//│     = [ 1, 2 ]\n\n:e // * Note: an error is raised in this case and not above because B is invariant so it can't be widened\nif b is Bar(f) then f else 0\n//│ ╔══[ERROR] Type error in `case` expression\n//│ ║  l.503: \tif b is Bar(f) then f else 0\n//│ ║         \t   ^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `B` leaks out of its scope\n//│ ║  l.477: \tclass Bar[B](f: B => B) extends Base\n//│ ╙──       \t          ^\n//│ 0 | ??B -> anything\n//│ res\n//│     = 0\n\n:e\nif b is\n  Foo(a) then a\n  Bar(f) then f\n//│ ╔══[ERROR] Type error in `case` expression\n//│ ║  l.515: \tif b is\n//│ ║         \t   ^^^^\n//│ ║  l.516: \t  Foo(a) then a\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.517: \t  Bar(f) then f\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ╟── type variable `B` leaks out of its scope\n//│ ║  l.477: \tclass Bar[B](f: B => B) extends Base\n//│ ╙──       \t          ^\n//│ anything\n//│ res\n//│     = [ 1, 2 ]\n\n:e\nval tt1 = Test\n//│ ╔══[ERROR] trait Test cannot be used in term position\n//│ ║  l.533: \tval tt1 = Test\n//│ ╙──       \t          ^^^^\n//│ val tt1: error\n//│ Code generation encountered an error:\n//│   trait used in term position\n\n\nfun mt(x) = if x is Test then 1 else 0\n//│ fun mt: nothing -> error\n\n\ntrait Geo\ntrait ZL extends Geo\ntrait GL extends Geo\ntrait WP extends ZL, GL\ntrait EM extends WP, Geo\n//│ trait Geo\n//│ trait ZL extends Geo\n//│ trait GL extends Geo\n//│ trait WP extends GL, Geo, ZL\n//│ trait EM extends GL, Geo, WP, ZL\n\nval g: Geo\nval z: ZL\nval w: WP\nval e: EM\n//│ val e: EM\n//│ val g: Geo\n//│ val w: WP\n//│ val z: ZL\n//│ g\n//│   = <missing implementation>\n//│ z\n//│   = <missing implementation>\n//│ w\n//│   = <missing implementation>\n//│ e\n//│   = <missing implementation>\n\nfun fot(x: EM): Geo = x\nfun fit(x: EM): WP = x\nw: Geo\nz: Geo\ne: WP\nw: ZL & GL\ne: ZL & Geo\n//│ fun fot: (x: EM) -> Geo\n//│ fun fit: (x: EM) -> WP\n//│ Geo & ZL\n//│ res\n//│     = <no result>\n//│       w is not implemented\n//│ res\n//│     = <no result>\n//│       z is not implemented\n//│ res\n//│     = <no result>\n//│       e is not implemented\n//│ res\n//│     = <no result>\n//│       w is not implemented\n//│ res\n//│     = <no result>\n//│       e is not implemented\n\n:e\nfun fto(w: WP): EM = w\nz: WP\ng: ZL\ne: ZL & WP\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.601: \tfun fto(w: WP): EM = w\n//│ ║         \t                     ^\n//│ ╟── type `#WP` is not an instance of type `EM`\n//│ ║  l.601: \tfun fto(w: WP): EM = w\n//│ ║         \t           ^^\n//│ ╟── but it flows into reference with expected type `#EM`\n//│ ║  l.601: \tfun fto(w: WP): EM = w\n//│ ║         \t                     ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.601: \tfun fto(w: WP): EM = w\n//│ ╙──       \t                ^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.602: \tz: WP\n//│ ║         \t^\n//│ ╟── type `#ZL` is not an instance of type `WP`\n//│ ║  l.558: \tval z: ZL\n//│ ║         \t       ^^\n//│ ╟── but it flows into reference with expected type `#WP`\n//│ ║  l.602: \tz: WP\n//│ ║         \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.602: \tz: WP\n//│ ╙──       \t   ^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.603: \tg: ZL\n//│ ║         \t^\n//│ ╟── type `#Geo` is not an instance of type `ZL`\n//│ ║  l.557: \tval g: Geo\n//│ ║         \t       ^^^\n//│ ╟── but it flows into reference with expected type `#ZL`\n//│ ║  l.603: \tg: ZL\n//│ ║         \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.603: \tg: ZL\n//│ ╙──       \t   ^^\n//│ fun fto: (w: WP) -> EM\n//│ WP & ZL\n//│ res\n//│     = <no result>\n//│       z is not implemented\n//│ res\n//│     = <no result>\n//│       g is not implemented\n//│ res\n//│     = <no result>\n//│       e is not implemented\n\nclass Bs(val a: Bool) {\n  virtual fun foo(x) = x + 1\n}\n//│ class Bs(a: Bool) {\n//│   fun foo: Int -> Int\n//│ }\n\nclass Ih() extends Bs(false) {\n  fun bar(x) = x\n  fun foo(x) = 1\n}\n//│ class Ih() extends Bs {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun foo: anything -> 1\n//│ }\n\nval ih1 = Ih()\n//│ val ih1: Ih\n//│ ih1\n//│     = Ih {}\n\nih1.foo(1)\n//│ 1\n//│ res\n//│     = 1\n\nih1: Bs\n//│ Bs\n//│ res\n//│     = Ih {}\n\nih1.a\n//│ false\n//│ res\n//│     = false\n\n:e\nclass Eh2 extends Bs(true), Ele {\n    fun foo(x) = x && false\n    fun ce(x) = x\n}\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `Int & ?a` is not an instance of type `Bool`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ╙──       \t                 ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `Int & ?a` does not match type `Bool`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ╙──       \t                 ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Bool` does not match type `Int | ?a`\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ║         \t                 ^^^^^^^^^^\n//│ ╟── Note: constraint arises from operator application:\n//│ ║  l.654: \t  virtual fun foo(x) = x + 1\n//│ ╙──       \t                       ^^^^^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ║         \t        ^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Bool` does not match type `Int | ?a`\n//│ ║  l.691: \t    fun foo(x) = x && false\n//│ ║         \t                 ^^^^^^^^^^\n//│ ╟── Note: constraint arises from operator application:\n//│ ║  l.654: \t  virtual fun foo(x) = x + 1\n//│ ╙──       \t                       ^^^^^\n//│ class Eh2 extends Bs, Ele {\n//│   constructor()\n//│   fun ce: forall 'a. 'a -> 'a\n//│   fun foo: Bool -> Bool\n//│ }\n\n:e\nclass Eh extends Bs(1)\nclass Eh1 extends Bs\nclass Eh3 extends Bs(false), Test\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.733: \tclass Eh extends Bs(1)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `Bool`\n//│ ║  l.733: \tclass Eh extends Bs(1)\n//│ ║         \t                    ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.653: \tclass Bs(val a: Bool) {\n//│ ╙──       \t                ^^^^\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.733: \tclass Eh extends Bs(1)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `1` does not match type `Bool`\n//│ ║  l.733: \tclass Eh extends Bs(1)\n//│ ║         \t                    ^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.653: \tclass Bs(val a: Bool) {\n//│ ╙──       \t                ^^^^\n//│ ╔══[ERROR] class Bs expects 1 parameter(s); got 0\n//│ ║  l.734: \tclass Eh1 extends Bs\n//│ ╙──       \t                  ^^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.654: \t  virtual fun foo(x) = x + 1\n//│ ║         \t              ^^^^^^^^^^^^^^\n//│ ╟── function of type `?a -> (forall ?b. ?b)` is not an instance of type `Int`\n//│ ║  l.654: \t  virtual fun foo(x) = x + 1\n//│ ║         \t                 ^^^^^^^^^^^\n//│ ╟── but it flows into definition of method foo with expected type `Int`\n//│ ║  l.654: \t  virtual fun foo(x) = x + 1\n//│ ║         \t              ^^^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.5: \t  fun foo: Int\n//│ ║       \t           ^^^\n//│ ╟── from signature of member `foo`:\n//│ ║  l.5: \t  fun foo: Int\n//│ ╙──     \t      ^^^^^^^^\n//│ ╔══[ERROR] Member `bar` is declared (or its declaration is inherited) but is not implemented in `Eh3`\n//│ ║  l.735: \tclass Eh3 extends Bs(false), Test\n//│ ║         \t      ^^^\n//│ ╟── Declared here:\n//│ ║  l.6: \t  fun bar: Bool -> Bool\n//│ ╙──     \t  ^^^^^^^^^^^^^^^^^^^^^\n//│ class Eh extends Bs {\n//│   constructor()\n//│   fun foo: Int -> Int\n//│ }\n//│ class Eh1 extends Bs {\n//│   constructor()\n//│   fun foo: Int -> Int\n//│ }\n//│ class Eh3 extends Bs, Test {\n//│   constructor()\n//│   fun bar: Bool -> Bool\n//│   fun foo: Int -> Int\n//│ }\n\nclass Ca(a0: Int) extends Oth {\n  virtual val a = a0\n  fun foo = 1\n  fun cool(x) = false\n  fun bar(x) = x\n}\n//│ class Ca(a0: Int) extends Oth, Test {\n//│   val a: Int\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun cool: anything -> false\n//│   fun foo: 1\n//│ }\n\nclass Cx(a2: 1 | 2, val b: Bool) extends Ca(a2)\n//│ class Cx(a2: 1 | 2, b: Bool) extends Ca, Oth, Test {\n//│   val a: Int\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun cool: anything -> false\n//│   fun foo: 1\n//│ }\n\nclass Cx(val a: 1 | 2, val b: Bool) extends Ca(a)\n//│ class Cx(a: 1 | 2, b: Bool) extends Ca, Oth, Test {\n//│   fun bar: forall 'a. 'a -> 'a\n//│   fun cool: anything -> false\n//│   fun foo: 1\n//│ }\n\nval cx1 = Cx(2, true)\n//│ val cx1: Cx\n//│ cx1\n//│     = Cx {}\n\ncx1.bar(cx1.b)\n//│ Bool\n//│ res\n//│     = true\n\ncx1: Test\n//│ Test\n//│ res\n//│     = Cx {}\n\ncx1: Ca\n//│ Ca\n//│ res\n//│     = Cx {}\n\nclass Bc1(foo: Int)\nclass Bc2(bar: Bool)\nabstract class Bc3 {\n  val baz : Int\n}\n//│ class Bc1(foo: Int)\n//│ class Bc2(bar: Bool)\n//│ abstract class Bc3 {\n//│   val baz: Int\n//│ }\n\n:e\nclass Bc12() extends Bc1(1), Bc2(true)\n//│ ╔══[ERROR] Cannot inherit from more than one base class: Bc1 and Bc2\n//│ ║  l.852: \tclass Bc12() extends Bc1(1), Bc2(true)\n//│ ╙──       \t                             ^^^^^^^^^\n//│ class Bc12() extends Bc1, Bc2\n//│ Code generation encountered an error:\n//│   unexpected parent symbol new class Bc2.\n\nclass Bc02() extends Bc1(1 : Int) {\n  val foo = 2\n}\n//│ class Bc02() extends Bc1 {\n//│   val foo: 2\n//│ }\n\nBc02().foo\n//│ 2\n//│ res\n//│     = 2\n\n:e\nclass Bc31(val baz: Bool) extends Bc3\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.873: \tclass Bc31(val baz: Bool) extends Bc3\n//│ ║         \t                    ^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.843: \t  val baz : Int\n//│ ║         \t            ^^^\n//│ ╟── from signature of member `baz`:\n//│ ║  l.843: \t  val baz : Int\n//│ ╙──       \t      ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.873: \tclass Bc31(val baz: Bool) extends Bc3\n//│ ║         \t                    ^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.843: \t  val baz : Int\n//│ ║         \t            ^^^\n//│ ╟── from signature of member `baz`:\n//│ ║  l.843: \t  val baz : Int\n//│ ╙──       \t      ^^^^^^^^^\n//│ class Bc31(baz: Bool) extends Bc3\n\nclass Bc11 extends Bc1(1) {\n  val foo = true\n}\n//│ class Bc11 extends Bc1 {\n//│   constructor()\n//│   val foo: true\n//│ }\n\n\ntrait Base[A] { fun f: A -> A }\n//│ trait Base[A] {\n//│   fun f: A -> A\n//│ }\n\nclass Der1 extends Base[Int] { fun f(x) = x + 1 }\n//│ class Der1 extends Base {\n//│   constructor()\n//│   fun f: Int -> Int\n//│ }\n\nclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [x, y] }\n//│ class Der2[A, B] extends Base {\n//│   constructor()\n//│   fun f: forall 'a 'b. (['a, 'b]) -> ['a, 'b]\n//│ }\n\n:e\ntrait BInt extends Base[Int] {\n  fun f = error\n}\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.924: \t  fun f = error\n//│ ╙──       \t  ^^^^^^^^^^^^^\n//│ trait BInt extends Base {\n//│   fun f: nothing\n//│ }\n\ntrait BPar[T] extends Base[[Int, T]]\n//│ trait BPar[T] extends Base {\n//│   fun f: 'A -> 'A\n//│ }\n//│ where\n//│   'A := [Int, T]\n\nval bi: BInt\nval bp: BPar[Bool]\n//│ val bi: BInt\n//│ val bp: BPar[Bool]\n//│ bi\n//│    = <missing implementation>\n//│ bp\n//│    = <missing implementation>\n\nbp: Base[[Int, Bool]]\n//│ Base[[Int, Bool]]\n//│ res\n//│     = <no result>\n//│       bp is not implemented\n\n:e\nbp: Base[[Int, Int]]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.956: \tbp: Base[[Int, Int]]\n//│ ║         \t^^\n//│ ╙── expression of type `true` is not an instance of type `Int`\n//│ Base[[Int, Int]]\n//│ res\n//│     = <no result>\n//│       bp is not implemented\n\nbi.f(1)\n//│ nothing\n//│ res\n//│     = <no result>\n//│       bi is not implemented\n\nbp.f\n//│ ([Int, Bool]) -> [Int, Bool]\n//│ res\n//│     = <no result>\n//│       bp is not implemented\n\nfun fb[T](x: Base[[Int, T]], y: T) = x.f([1, y])\n//│ fun fb: forall 'T. (x: Base[[Int, 'T]], y: 'T) -> [Int, 'T]\n\nfb(bp, false)\n//│ [Int, Bool]\n//│ res\n//│     = <no result>\n//│       bp is not implemented\n\nclass CP() extends BPar[Int] {\n  fun f(x) = [x.1, x.0]\n}\n//│ class CP() extends BPar, Base {\n//│   fun f: forall 'a 'b. {0: 'a, 1: 'b} -> ['b, 'a]\n//│ }\n\nval cp1 = CP()\n//│ val cp1: CP\n//│ cp1\n//│     = CP {}\n\nfb(cp1, 2)\n//│ [Int, Int]\n//│ res\n//│     = [ 2, 1 ]\n\ntrait BInfer1 extends Base\n//│ trait BInfer1 extends Base {\n//│   fun f: 'A -> 'A\n//│ }\n\ntrait BInfer2 extends Base {\n  fun f: Int -> Int\n}\n//│ trait BInfer2 extends Base {\n//│   fun f: Int -> Int\n//│ }\n\n:e\nclass DerBad1 extends Base[Int, Int]\n//│ ╔══[ERROR] trait Base expects 1 type parameter(s); got 2\n//│ ║  l.1017: \tclass DerBad1 extends Base[Int, Int]\n//│ ╙──        \t                      ^^^^^^^^^^^^^\n//│ ╔══[ERROR] Member `f` is declared (or its declaration is inherited) but is not implemented in `DerBad1`\n//│ ║  l.1017: \tclass DerBad1 extends Base[Int, Int]\n//│ ║          \t      ^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.905: \ttrait Base[A] { fun f: A -> A }\n//│ ╙──       \t                ^^^^^^^^^^^^^\n//│ class DerBad1 extends Base {\n//│   constructor()\n//│   fun f: 'A -> 'A\n//│ }\n//│ where\n//│   'A := Int\n\n:e\nclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ╔══[ERROR] Type mismatch in definition of method f:\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ║          \t                                            ^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `B` does not match type `A`\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ║          \t                                                         ^\n//│ ╟── Note: constraint arises from type parameter:\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ║          \t           ^\n//│ ╟── Note: type parameter B is defined at:\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ╙──        \t              ^\n//│ ╔══[ERROR] Type mismatch in definition of method f:\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ║          \t                                            ^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `A` does not match type `B`\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ║          \t                                                            ^\n//│ ╟── Note: constraint arises from type parameter:\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ║          \t              ^\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.1035: \tclass Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] }\n//│ ╙──        \t           ^\n//│ class Der2[A, B] extends Base {\n//│   constructor()\n//│   fun f: forall 'a 'b. (['a, 'b]) -> ['b, 'a]\n//│ }\n\ntrait Ta[T] {\n  val p: Bool\n  val g: T\n}\nclass K[A](val k: Ta[A])\n//│ trait Ta[T] {\n//│   val g: T\n//│   val p: Bool\n//│ }\n//│ class K[A](k: Ta[A])\n\nval ta1: Ta[Int]\n//│ val ta1: Ta[Int]\n//│ ta1\n//│     = <missing implementation>\n\nval k1 = K(ta1)\n//│ val k1: K[Int]\n//│ k1\n//│    = <no result>\n//│      ta1 is not implemented\n\nk1.k : Ta[Int]\n//│ Ta[Int]\n//│ res\n//│     = <no result>\n//│       k1 and ta1 are not implemented\n\nk1.k.g\n//│ Int\n//│ res\n//│     = <no result>\n//│       k1 and ta1 are not implemented\n\nk1.k.p\n//│ Bool\n//│ res\n//│     = <no result>\n//│       k1 and ta1 are not implemented\n\n:e\ntrait Tb extends Ta[Int] {\n  virtual val p = false\n}\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.1107: \t  virtual val p = false\n//│ ╙──        \t          ^^^^^^^^^^^^^\n//│ trait Tb extends Ta {\n//│   val g: 'T\n//│   val p: false\n//│ }\n//│ where\n//│   'T := Int\n\nclass Ctb extends Tb {\n  val p = false\n  val g = 2\n}\n//│ class Ctb extends Ta, Tb {\n//│   constructor()\n//│   val g: 2\n//│   val p: false\n//│ }\n\nclass G1[A](x: A)\n//│ class G1[A](x: A)\n\nclass GI(x2: Int) extends G1[Int](x2)\n//│ class GI(x2: Int) extends G1\n\ntrait Oz {\n  val age: Int\n}\n//│ trait Oz {\n//│   val age: Int\n//│ }\n\n:e\nclass Fischl(val age: Bool) extends Oz\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.1143: \tclass Fischl(val age: Bool) extends Oz\n//│ ║          \t                      ^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.1136: \t  val age: Int\n//│ ║          \t           ^^^\n//│ ╟── from signature of member `age`:\n//│ ║  l.1136: \t  val age: Int\n//│ ╙──        \t      ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.1143: \tclass Fischl(val age: Bool) extends Oz\n//│ ║          \t                      ^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.1136: \t  val age: Int\n//│ ║          \t           ^^^\n//│ ╟── from signature of member `age`:\n//│ ║  l.1136: \t  val age: Int\n//│ ╙──        \t      ^^^^^^^^\n//│ class Fischl(age: Bool) extends Oz\n\nclass Klee(val age: 1 | 2 | 3) extends Oz\n//│ class Klee(age: 1 | 2 | 3) extends Oz\n\nclass Fate {\n    virtual fun foo(x) = x + 1\n}\n//│ class Fate {\n//│   constructor()\n//│   fun foo: Int -> Int\n//│ }\n\n:e\nclass Go extends Fate {\n    fun foo(x) = x && true\n}\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ║          \t        ^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `Int & ?a` is not an instance of type `Bool`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ╙──        \t                 ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ║          \t        ^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `Int & ?a` does not match type `Bool`\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ╙──        \t                 ^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ║          \t        ^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Bool` does not match type `Int | ?a`\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ║          \t                 ^^^^^^^^^\n//│ ╟── Note: constraint arises from operator application:\n//│ ║  l.1170: \t    virtual fun foo(x) = x + 1\n//│ ╙──        \t                         ^^^^^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ║          \t        ^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Bool` does not match type `Int | ?a`\n//│ ║  l.1179: \t    fun foo(x) = x && true\n//│ ║          \t                 ^^^^^^^^^\n//│ ╟── Note: constraint arises from operator application:\n//│ ║  l.1170: \t    virtual fun foo(x) = x + 1\n//│ ╙──        \t                         ^^^^^\n//│ class Go extends Fate {\n//│   constructor()\n//│   fun foo: Bool -> Bool\n//│ }\n\nclass Ha { virtual val x: Int = 1 }\n//│ class Ha {\n//│   constructor()\n//│   val x: Int\n//│ }\n\nclass Haha(x: 1 | 2) extends Ha\n//│ class Haha(x: 1 | 2) extends Ha\n\n:e\nclass Ohhh(x: Bool) extends Ha\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.1228: \tclass Ohhh(x: Bool) extends Ha\n//│ ║          \t              ^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.1218: \tclass Ha { virtual val x: Int = 1 }\n//│ ║          \t                          ^^^\n//│ ╟── from definition of value x:\n//│ ║  l.1218: \tclass Ha { virtual val x: Int = 1 }\n//│ ╙──        \t                       ^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.1228: \tclass Ohhh(x: Bool) extends Ha\n//│ ║          \t              ^^^^\n//│ ╟── type `Bool` is not an instance of type `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.1218: \tclass Ha { virtual val x: Int = 1 }\n//│ ║          \t                          ^^^\n//│ ╟── from definition of value x:\n//│ ║  l.1218: \tclass Ha { virtual val x: Int = 1 }\n//│ ╙──        \t                       ^^^^^^^^^^\n//│ class Ohhh(x: Bool) extends Ha\n\ntrait TA[A] { val a : A }\n//│ trait TA[A] {\n//│   val a: A\n//│ }\n\nclass G1[A, B](val a: A, val b: B) extends TA[A]\n//│ class G1[A, B](a: A, b: B) extends TA\n\nclass G2[T](x: T) extends G1[T, Int](x, 1)\n//│ class G2[T](x: T) extends G1, TA\n\nval g21 = G2(false)\n//│ val g21: G2['T]\n//│   where\n//│     'T :> false\n//│ g21\n//│     = G2 {}\n\ng21: G1[Bool, Int]\n//│ G1[Bool, Int]\n//│ res\n//│     = G2 {}\n\ng21.a\n//│ Bool\n//│ res\n//│     = false\n\ng21: TA[Bool]\n//│ TA[Bool]\n//│ res\n//│     = G2 {}\n"
  },
  {
    "path": "shared/src/test/diff/nu/IntraBlockPolymorphism.mls",
    "content": ":NewDefs\n\n\n// * Note: eventually we should progressively type check every mutually-recursive group\n// *  in topological order, to maximize polymorphism.\n// * But currently we just type check them in srouce code order.\n// * So the following inferred types differ:\n\nfun i(x) = x\nlet a = i(0)\nlet b = i(true)\n//│ fun i: forall 'a. 'a -> 'a\n//│ let a: 0\n//│ let b: true\n//│ a\n//│   = 0\n//│ b\n//│   = true\n\n:re // FIXME shouldn't be a reference error\nlet a = i(0)\nfun i(x) = x\nlet b = i(true)\n//│ let a: 0 | true | 'a\n//│ fun i: forall 'b. ('a & 'b) -> (0 | 'b)\n//│ let b: 0 | true\n//│ a\n//│ Runtime error:\n//│   ReferenceError: i1 is not defined\n//│ b\n//│   = true\n\n:re // FIXME shouldn't be a reference error\nlet a = i(0)\nlet b = i(true)\nfun i(x) = x\n//│ let a: 0 | true | 'a\n//│ let b: 0 | true | 'a\n//│ fun i: forall 'b. ('a & 'b) -> (0 | true | 'b)\n//│ a\n//│ Runtime error:\n//│   ReferenceError: i2 is not defined\n//│ b\n//│ Runtime error:\n//│   ReferenceError: i2 is not defined\n\n\nmodule Test {\n  fun i(x) = x\n  let a = i(0)\n  let b = i(true)\n}\n//│ module Test {\n//│   let a: 0\n//│   let b: true\n//│   fun i: forall 'a. 'a -> 'a\n//│ }\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Jonathan.mls",
    "content": ":NewDefs\n:NoJS\n\n\n// * A monadic effect type, covariant in base type and effect type\nclass Effectful[out A, out E](value: A) {\n  fun flatMap[B](f: A => Effectful[B, E]): Effectful[B, E] =\n    f(value)\n}\nfun pure[A](a: A): Effectful['a, 'e] = Effectful(a)\n//│ class Effectful[A, E](value: A) {\n//│   fun flatMap: forall 'B. (f: A -> Effectful['B, E]) -> Effectful['B, E]\n//│ }\n//│ fun pure: forall 'A. (a: 'A) -> Effectful['A, nothing]\n\n// * Some effect tags\nmodule IO\nmodule Block\n//│ module IO\n//│ module Block\n\n// * Some example functions\nfun println(x: anything): Effectful[(), IO]\nfun readLine: Effectful[Str, IO | Block]\n//│ fun println: (x: anything) -> Effectful[(), IO]\n//│ fun readLine: Effectful[Str, Block | IO]\n\n\n// * Define NonBlocking as an effectful computation that does not block (using type-level difference `\\`)\ntype NonBlocking[out A, out E] = Effectful[A, E \\ Block]\n//│ type NonBlocking[A, E] = Effectful[A, E & ~Block]\n\n// * Example use of NonBlocking in an annotation; the type arguments are inferred\nfun f(x) = x : NonBlocking\n//│ fun f: forall 'a 'b. NonBlocking['a, 'b] -> NonBlocking['a, 'b]\n\n\n// * the `listener` callback should be non-blocking\nfun onMousePressed(listener) =\n  let l(e) = listener(e) : NonBlocking\n  l(0).flatMap of a => l(1).flatMap of b => pure of ()\n//│ fun onMousePressed: forall 'a. ((0 | 1) -> NonBlocking[anything, 'a]) -> Effectful[(), 'a & ~Block]\n\n\n// * OK: `println` does not block\nonMousePressed(event => println(\"Clicked!\"))\n//│ Effectful[(), IO & ~Block]\n\n// * NOT OK: `readLine` blocks\n:e\nonMousePressed(event => readLine.flatMap(println))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.51: \tonMousePressed(event => readLine.flatMap(println))\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Block` does not match type `~Block`\n//│ ║  l.24: \tfun readLine: Effectful[Str, IO | Block]\n//│ ╙──      \t                                  ^^^^^\n//│ Effectful[(), IO & ~Block] | error\n\n\nclass Event\nclass MouseEvent extends Event\nmodule Register\n//│ class Event {\n//│   constructor()\n//│ }\n//│ class MouseEvent extends Event {\n//│   constructor()\n//│ }\n//│ module Register\n\nfun onMousePressed(listener) =\n  let l(e: MouseEvent) = listener(e) : Effectful[(), 'e \\ Block \\ Register]\n  ()\n//│ fun onMousePressed: (MouseEvent -> Effectful[(), ~Block & ~Register]) -> ()\n\n// def onMouseClick ( f : Event -> Unit \\ { ef - Register }): Unit \\ { Register }\nfun onMouseClick(f: Event -> Effectful[(), 'e \\ Register]): Effectful[(), Register]\n//│ fun onMouseClick: (f: Event -> Effectful[(), ~Register]) -> Effectful[(), Register]\n\nonMouseClick of ev => pure of ()\n//│ Effectful[(), Register]\n\n:e\nonMouseClick of ev =>\n  onMouseClick(ev => pure of ()).flatMap of _ =>\n    pure of ()\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.85: \tonMouseClick of ev =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.86: \t  onMouseClick(ev => pure of ()).flatMap of _ =>\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.87: \t    pure of ()\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ╟── type `Register` does not match type `~Register`\n//│ ║  l.78: \tfun onMouseClick(f: Event -> Effectful[(), 'e \\ Register]): Effectful[(), Register]\n//│ ╙──      \t                                                                          ^^^^^^^^\n//│ Effectful[(), Register] | error\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/LamPatterns.mls",
    "content": ":NewDefs\n\n\nclass Some(value: Int)\n//│ class Some(value: Int)\n\n:e // TODO\nSome(x) => x\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.8: \tSome(x) => x\n//│ ╙──     \t^^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.8: \tSome(x) => x\n//│ ╙──     \t           ^\n//│ error -> error\n//│ Code generation encountered an error:\n//│   term App(Var(Some),Tup(List((None,Fld(_,Var(x)))))) is not a valid pattern\n\n:js\n// FIXME type\nlet f = Some => 0\n//│ let f: ((value: Int) -> Some) -> 0\n//│ // Prelude\n//│ class TypingUnit2 {}\n//│ const typing_unit2 = new TypingUnit2;\n//│ // Query 1\n//│ globalThis.f = function f(Some) {\n//│   return 0;\n//│ };\n//│ // End of generated code\n//│ f\n//│   = [Function: f]\n\n// :e // TODO\nf(Some)\n//│ 0\n//│ res\n//│     = 0\n\n// :e // TODO\nf(_ => error)\n//│ 0\n//│ res\n//│     = 0\n\n:e // TODO\nf(Some(0))\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.47: \tf(Some(0))\n//│ ║        \t^^^^^^^^^^\n//│ ╟── application of type `Some` is not a function\n//│ ║  l.47: \tf(Some(0))\n//│ ║        \t  ^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.21: \tlet f = Some => 0\n//│ ╙──      \t        ^^^^\n//│ 0 | error\n//│ res\n//│     = 0\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/LetRec.mls",
    "content": ":NewDefs\n\n\n:js\nfun f(x) = x > 0 && f(x - 1)\n//│ fun f: Int -> Bool\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ globalThis.f = function f(x) {\n//│   return x > 0 && f(x - 1);\n//│ };\n//│ // End of generated code\n\nf(12)\n//│ Bool\n//│ res\n//│     = false\n\n:js\nlet rec f(x) = x > 0 && f(x - 1)\n//│ let rec f: Int -> Bool\n//│ // Prelude\n//│ class TypingUnit2 {}\n//│ const typing_unit2 = new TypingUnit2;\n//│ // Query 1\n//│ globalThis.f1 = function f1(x) {\n//│   return x > 0 && f1(x - 1);\n//│ };\n//│ // End of generated code\n//│ f\n//│   = [Function: f1]\n\nf(12)\n//│ Bool\n//│ res\n//│     = false\n\n:js\nlet rec f() =\n  f()\n//│ let rec f: () -> nothing\n//│ // Prelude\n//│ class TypingUnit4 {}\n//│ const typing_unit4 = new TypingUnit4;\n//│ // Query 1\n//│ globalThis.f2 = function f2() {\n//│   return ((() => {\n//│     return f2();\n//│   })());\n//│ };\n//│ // End of generated code\n//│ f\n//│   = [Function: f2]\n\n:re\nf()\n//│ nothing\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n// :e // TODO this should be rejected by the type checker\n:ge\n:js\nlet rec f =\n  f\n//│ let rec f: nothing\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding f\n\n:re\n:js\nf\n//│ nothing\n//│ // Prelude\n//│ class TypingUnit7 {}\n//│ const typing_unit7 = new TypingUnit7;\n//│ // Query 1\n//│ res = f3;\n//│ // End of generated code\n//│ res\n//│ Runtime error:\n//│   ReferenceError: f3 is not defined\n\n// :e // TODO this should be rejected by the type checker\n:ge\n:js\nfun test =\n  let rec f =\n    f\n//│ fun test: ()\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding f\n\nfun test =\n  let rec f() = f()\n//│ fun test: ()\n\nfun test =\n  let rec lol = () => lol\n//│ fun test: ()\n\nfun test =\n  let rec lol() = lol\n  lol\n//│ fun test: forall 'lol. 'lol\n//│   where\n//│     'lol :> () -> 'lol\n\nfun testWithAsc =\n  let rec aux: Int -> Int = x => if x <= 0 then 1 else x * aux(x - 1)\n  aux(10)\ntestWithAsc\n//│ fun testWithAsc: Int\n//│ Int\n//│ res\n//│     = 3628800\n\nlet rec lol = () => lol\n//│ let rec lol: forall 'lol. 'lol\n//│   where\n//│     'lol :> () -> 'lol\n//│ lol\n//│     = [Function: lol]\n\n:p\nlet rec f = 1\n//│ |#let| |#rec| |f| |#=| |1|\n//│ AST: TypingUnit(List(NuFunDef(Some(true),Var(f),None,List(),Left(IntLit(1)))))\n//│ Parsed: let rec f = 1;\n//│ let rec f: 1\n//│ f\n//│   = 1\n\nlet rec f =\n  1\n//│ let rec f: 1\n//│ f\n//│   = 1\n\n\n// :e // FIXME\n:ge\nlet foo = foo\n//│ let foo: nothing\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding foo\n\n\n// FIXME should work\n// No recursion:\nlet foo = 1\nlet foo = foo + 1\n//│ let foo: 1\n//│ let foo: Int\n//│ foo\n//│     = 1\n//│ foo\n//│     = 2\n\n\n// FIXME\nlet foo = foo.x\n//│ let foo: nothing\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding foo\n\n// :e // FIXME\n:ge\nfoo()()\n//│ nothing\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding foo\n\n\n// :e // FIXME wrong static semantics\n:re\nlet xf = yf()\nlet yf() = xf\n//│ let xf: nothing\n//│ let yf: () -> nothing\n//│ xf\n//│ Runtime error:\n//│   ReferenceError: yf is not defined\n//│ yf\n//│    = [Function: yf]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ListConsNil.mls",
    "content": ":NewDefs\n\n\n\ntype List[out A] = Cons[A] | Nil\nclass Cons[out A](head: A, tail: List[A]) {\n  val size: Int\n  fun map: (A -> 'B) -> List['B]\n  size = 1 + tail.size\n  map(f) = Cons(f(head), tail.map(f))\n}\nmodule Nil {\n  val size = 0\n  fun map(f) = Nil\n}\n//│ type List[A] = Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A]) {\n//│   fun map: forall 'B. (A -> 'B) -> List['B]\n//│   val size: Int\n//│ }\n//│ module Nil {\n//│   fun map: anything -> Nil\n//│   val size: 0\n//│ }\n\nfun (::) cons(x, xs) = Cons(x, xs)\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n\nfun show(xs) =\n  let rec go(xs) = if xs is\n    Cons(h, Nil) then String(h)\n    Cons(h, t)   then join(String(h), \", \", go(t))\n    Nil          then \"\"\n  join(\"[\", go(xs), \"]\")\n//│ fun show: (Cons[anything] | Nil) -> Str\n\nlet xs = 1 :: 2 :: 3 :: Nil\n//│ let xs: Cons[1 | 2 | 3]\n//│ xs\n//│    = Cons {}\n\nxs.size\n//│ Int\n//│ res\n//│     = 3\n\nshow(xs)\n//│ Str\n//│ res\n//│     = '[1, 2, 3]'\n\nshow(xs.map of x => succ of x)\n//│ Str\n//│ res\n//│     = '[2, 3, 4]'\n\n\n\n:e // TODO this should be made to work!\nabstract class List[out A]: (Cons[A] | Nil) {\n  val size: Int\n  fun map: (A -> 'B) -> List['B]\n}\nclass Cons[out A](head: A, tail: List[A]) extends List[A] {\n  val size = 1 + tail.size\n  fun map(f) = Cons(f(head), tail.map(f))\n}\nmodule Nil extends List[nothing] {\n  val size = 0\n  fun map(f) = Nil\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.65: \t  val size = 1 + tail.size\n//│ ╙──      \t                     ^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.66: \t  fun map(f) = Cons(f(head), tail.map(f))\n//│ ╙──      \t                                 ^^^^\n//│ abstract class List[A]: Cons[A] | Nil {\n//│   fun map: forall 'B. (A -> 'B) -> List['B]\n//│   val size: Int\n//│ }\n//│ class Cons[A](head: A, tail: List[A]) extends List {\n//│   fun map: forall 'A. (A -> 'A) -> Cons['A]\n//│   val size: Int\n//│ }\n//│ module Nil extends List {\n//│   fun map: anything -> Nil\n//│   val size: 0\n//│ }\n\n\n\n// TODO should better simplify these types (reduce the List refinement)\n\n:ng\nval test0: Cons[Int] & List[Num]\nval test1: Nil & List[Int]\n//│ val test0: Cons[Int] & List[Num]\n//│ val test1: Nil & List[Int]\n\n\n\nfun list_assoc(s, l) =\n  if l is\n    Cons(h, t) then\n      if eq(s)(h._1) then Cons(h._2, Nil)\n      else list_assoc(s, t)\n    Nil then Nil\n//│ fun list_assoc: forall 'A. (anything, Cons[{_1: anything, _2: 'A}] | Nil) -> (Cons['A] | Nil)\n\nfun test(x, l) = list_assoc(42, Cons(x, l))\n//│ fun test: forall 'A. ({_1: anything, _2: 'A}, List[{_1: anything, _2: 'A}]) -> (Cons['A] | Nil)\n\nfun test(x, l) = if l is\n  Nil then list_assoc(42, Cons(x, l))\n  Cons(h, t) then list_assoc(42, Cons(h, t))\n//│ fun test: forall 'A. ({_1: anything, _2: 'A}, Cons[{_1: anything, _2: 'A}] | Nil) -> (Cons['A] | Nil)\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/LitMatch.mls",
    "content": ":NewDefs\n\n\nlet r = false : Bool\n//│ let r: Bool\n//│ r\n//│   = false\n\nlet b = (if r then true else false) : Bool\n//│ let b: Bool\n//│ b\n//│   = false\n\nlet b = false : Bool\n//│ let b: Bool\n//│ b\n//│   = false\n\nb : true | false\n//│ Bool\n//│ res\n//│     = false\n\nif false is false then 0\n//│ 0\n//│ res\n//│     = 0\n\nfun foo(x) = if x is\n  false then 0\n//│ fun foo: false -> 0\n\nfun foo(x) = if x is\n  false then 0\n  true  then 1\n//│ fun foo: Bool -> (0 | 1)\n\nfun foo(x) = if x is\n  0 then \"zero\"\n  true then \"true\"\n//│ fun foo: (0 | true) -> (\"true\" | \"zero\")\n"
  },
  {
    "path": "shared/src/test/diff/nu/LocalLets.mls",
    "content": ":NewDefs\n\n\nlet f =\n  let tmp = \"ok\"\n  123\n//│ let f: 123\n//│ f\n//│   = 123\n\n\n:e\nlet x : Int | string\nlet x = 1\n//│ ╔══[ERROR] `let` bindings must have a right-hand side\n//│ ║  l.13: \tlet x : Int | string\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^\n//│ let x: 1\n//│ let x: Int | string\n//│ x\n//│   = <missing implementation>\n//│ x\n//│   = 1\n\nval x : Int | string\nval x = 1\n//│ val x: 1\n//│ val x: Int | string\n//│ x\n//│   = <missing implementation>\n//│ x\n//│   = 1\n\n\nclass E(x: Int)\n//│ class E(x: Int)\n\n:e // TODO support (currently parsed as a function definition named E)\nlet E(x) = new E(1)\n//│ ╔══[ERROR] value E cannot be used as a type\n//│ ║  l.39: \tlet E(x) = new E(1)\n//│ ╙──      \t               ^\n//│ ╔══[ERROR] type identifier not found: E\n//│ ║  l.39: \tlet E(x) = new E(1)\n//│ ╙──      \t               ^\n//│ let E: anything -> error\n//│ E\n//│   = [Function: E1]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MIscPoly.mls",
    "content": ":NewDefs\n\n\n\n[(x: 'a) => x]\n//│ [forall 'a. (x: 'a) -> 'a]\n//│ res\n//│     = [ [Function (anonymous)] ]\n\n[forall 'a: (x: 'a) => x]\n//│ [forall 'a. (x: 'a) -> 'a]\n//│ res\n//│     = [ [Function (anonymous)] ]\n\n\n\nabstract class C0[A] {\n  fun use: forall 'r: [A, 'r -> 'r]\n}\n//│ abstract class C0[A] {\n//│   fun use: forall 'r. [A, 'r -> 'r]\n//│ }\n\nclass C1 extends C0[Int] {\n  fun use = [0, id]\n}\n//│ class C1 extends C0 {\n//│   constructor()\n//│   fun use: [0, forall 'a. 'a -> 'a]\n//│ }\n\nclass C1[AA](aa: AA) extends C0[AA] {\n  fun use = [aa, id]\n}\n//│ class C1[AA](aa: AA) extends C0 {\n//│   fun use: [AA, forall 'a. 'a -> 'a]\n//│ }\n\n\n\n// * FIXME currently we always distribute `forall` types;\n// * but this is not sound when distributing into a non-function such as an object type\n// * as long as we perform object type intersection merges (which we want to)\n\nclass C[A](){fun f: A -> A = id}\n//│ class C[A]() {\n//│   fun f: A -> A\n//│ }\n\nlet c = C()\n//│ let c: forall 'A. C['A]\n//│ c\n//│   = C {}\n\n// :e // FIXME\nlet d = c : C[Int] & C[Str]\n//│ let d: C[in Int | Str out nothing]\n//│ d\n//│   = C {}\n\n// :e // FIXME\nlet r = d.f(0)\n//│ let r: nothing\n//│ r\n//│   = 0\n\n:re\nr()\n//│ nothing\n//│ res\n//│ Runtime error:\n//│   TypeError: r is not a function\n\n\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MemberConfusion.mls",
    "content": ":NewDefs\n\n\nmixin T { fun a = \"hi\" }\n//│ mixin T() {\n//│   fun a: \"hi\"\n//│ }\n\nclass C(a: Int) extends T\n//│ class C(a: Int) {\n//│   fun a: \"hi\"\n//│ }\n\nclass B { virtual val a = \"hi\" }\n//│ class B {\n//│   constructor()\n//│   val a: \"hi\"\n//│ }\n\n:e\nclass C(a: Int) extends B\n//│ ╔══[ERROR] Type mismatch in type reference:\n//│ ║  l.21: \tclass C(a: Int) extends B\n//│ ║        \t           ^^^\n//│ ╟── type `Int` does not match type `\"hi\"`\n//│ ╟── Note: constraint arises from string literal:\n//│ ║  l.14: \tclass B { virtual val a = \"hi\" }\n//│ ║        \t                          ^^^^\n//│ ╟── from definition of value a:\n//│ ║  l.14: \tclass B { virtual val a = \"hi\" }\n//│ ╙──      \t                      ^^^^^^^^\n//│ class C(a: Int) extends B\n\n\nmixin M { val b = \"hi\" }\n//│ mixin M() {\n//│   val b: \"hi\"\n//│ }\n\nclass B { virtual val a = 1 : Int }\n//│ class B {\n//│   constructor()\n//│   val a: Int\n//│ }\n\nclass C(val a: Int, val b: Int) extends B, M\n//│ class C(a: Int, b: Int) extends B {\n//│   val b: \"hi\"\n//│ }\n\nlet c = C(2, 3)\n[c.a, c.b]\n//│ let c: C\n//│ [Int, \"hi\"]\n//│ c\n//│   = C {}\n//│ res\n//│     = [ 2, 3 ]\n\nclass C(a: Int) { let a = 1 }\n//│ class C(a: Int) {\n//│   let a: 1\n//│ }\n\nclass C(a: Int) { fun a = 1 }\n//│ class C(a: Int) {\n//│   fun a: 1\n//│ }\n\nclass C(a: Int) { fun a = a }\n//│ class C(a: Int) {\n//│   fun a: nothing\n//│ }\n\nclass C(a: Int, b: Int) extends B, M { let b = \"hi\" }\n//│ class C(a: Int, b: Int) extends B {\n//│   let b: \"hi\"\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MemberIntersections.mls",
    "content": ":NewDefs\n\n:NoJS // TODO\n\n\ntrait T1 { fun f[A]: A -> A }\ntrait T2 { fun f[B, C]: (B, C) -> [B, C] }\ntrait T3 extends T1, T2\n//│ trait T1 {\n//│   fun f: forall 'A. 'A -> 'A\n//│ }\n//│ trait T2 {\n//│   fun f: forall 'B 'C. ('B, 'C) -> ['B, 'C]\n//│ }\n//│ trait T3 extends T1, T2 {\n//│   fun f: forall 'A 'B 'C. 'A -> 'A & ('B, 'C) -> ['B, 'C]\n//│ }\n\n\ntrait S1 { class f }\n//│ trait S1 {\n//│   class f {\n//│     constructor()\n//│   }\n//│ }\n\n:e\ntrait S2 extends T1, S1\n//│ ╔══[ERROR] Intersection of value member and class members currently unsupported\n//│ ║  l.28: \ttrait S2 extends T1, S1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── The value member is defined here:\n//│ ║  l.6: \ttrait T1 { fun f[A]: A -> A }\n//│ ║       \t           ^^^^^^^^^^^^^^^^\n//│ ╟── The class member is defined here:\n//│ ║  l.20: \ttrait S1 { class f }\n//│ ╙──      \t           ^^^^^^^\n//│ trait S2 extends S1, T1\n\ntrait S2 { class f }\n//│ trait S2 {\n//│   class f {\n//│     constructor()\n//│   }\n//│ }\n\n:e\ntrait S3 extends S1, S2\n//│ ╔══[ERROR] Intersection of class member and class members currently unsupported\n//│ ║  l.48: \ttrait S3 extends S1, S2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── The class member is defined here:\n//│ ║  l.20: \ttrait S1 { class f }\n//│ ║        \t           ^^^^^^^\n//│ ╟── The class member is defined here:\n//│ ║  l.40: \ttrait S2 { class f }\n//│ ╙──      \t           ^^^^^^^\n//│ trait S3 extends S1, S2\n\n\ntrait S1 { val f: Int -> Int }\n//│ trait S1 {\n//│   val f: Int -> Int\n//│ }\n\ntrait S2 extends T1, S1\n//│ trait S2 extends S1, T1 {\n//│   fun f: forall 'A. 'A -> 'A & Int -> Int\n//│ }\n\ntrait S3 extends S1, T1\n//│ trait S3 extends S1, T1 {\n//│   fun f: forall 'A. Int -> Int & 'A -> 'A\n//│ }\n\n\nclass C1(val x: Int | Bool)\ntrait T1 { val x: Int | Str }\n//│ class C1(x: Int | false | true)\n//│ trait T1 {\n//│   val x: Int | Str\n//│ }\n\nclass C2() extends C1(0), T1\n//│ class C2() extends C1, T1\n\nC2().x : 0\n//│ 0\n\n:e\nclass C2 extends C1(false), T1\n//│ ╔══[ERROR] Type mismatch in reference:\n//│ ║  l.91: \tclass C2 extends C1(false), T1\n//│ ║        \t                    ^^^^^\n//│ ╟── reference of type `false` does not match type `Int | Str`\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.78: \ttrait T1 { val x: Int | Str }\n//│ ║        \t                  ^^^^^^^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.78: \ttrait T1 { val x: Int | Str }\n//│ ╙──      \t               ^^^^^^^^^^^^\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│ }\n\n:e\nclass C2 extends C1(\"oops\"), T1\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.107: \tclass C2 extends C1(\"oops\"), T1\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` does not match type `Int | false | true`\n//│ ║  l.107: \tclass C2 extends C1(\"oops\"), T1\n//│ ║         \t                    ^^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.77: \tclass C1(val x: Int | Bool)\n//│ ╙──      \t                ^^^^^^^^^^\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│ }\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MetaWrap.mls",
    "content": ":NewDefs\n\n\n// * A test to show how to add meta data to underlying values by wrapping them.\n\n\nmixin Base {\n  fun unwrap(x) = x\n  fun rewrap(x, f) = f(x)\n}\n//│ mixin Base() {\n//│   fun rewrap: ('a, 'a -> 'b) -> 'b\n//│   fun unwrap: 'c -> 'c\n//│ }\n\n\nmixin WithUid {\n  fun unwrap(x) = super.unwrap(x).underlying\n  fun rewrap(x, f) = super.rewrap(x, y => { underlying: f(y.underlying), uid: y.uid })\n  fun getUid(x) = super.unwrap(x).uid\n  fun setUid(x, uid: Int) = super.rewrap(x, y => {\n    underlying: y.underlying,\n    uid\n  })\n}\n//│ mixin WithUid() {\n//│   super: {\n//│     rewrap: ('a, forall 'uid. {uid: 'uid, underlying: 'underlying} -> {uid: 'uid, underlying: 'b}) -> 'c & ('d, forall 'underlying0. {underlying: 'underlying0} -> {uid: Int, underlying: 'underlying0}) -> 'e,\n//│     unwrap: 'f -> {underlying: 'underlying1} & 'g -> {uid: 'uid0}\n//│   }\n//│   fun getUid: 'g -> 'uid0\n//│   fun rewrap: ('a, 'underlying -> 'b) -> 'c\n//│   fun setUid: ('d, uid: Int) -> 'e\n//│   fun unwrap: 'f -> 'underlying1\n//│ }\n\n\nclass Type(val name: Str)\n//│ class Type(name: Str)\n\nmixin WithType {\n  fun unwrap(x) = super.unwrap(x).underlying\n  fun rewrap(x, f) = super.rewrap(x, y => { underlying: f(y.underlying), ty: y.ty })\n  fun getType(x) = super.unwrap(x).ty\n  fun setType(x, ty: Type) = super.rewrap(x, y => {\n    underlying: y.underlying,\n    ty\n  })\n}\n//│ mixin WithType() {\n//│   super: {\n//│     rewrap: ('a, forall 'ty. {ty: 'ty, underlying: 'underlying} -> {ty: 'ty, underlying: 'b}) -> 'c & ('d, forall 'underlying0. {underlying: 'underlying0} -> {ty: Type, underlying: 'underlying0}) -> 'e,\n//│     unwrap: 'f -> {underlying: 'underlying1} & 'g -> {ty: 'ty0}\n//│   }\n//│   fun getType: 'g -> 'ty0\n//│   fun rewrap: ('a, 'underlying -> 'b) -> 'c\n//│   fun setType: ('d, ty: Type) -> 'e\n//│   fun unwrap: 'f -> 'underlying1\n//│ }\n\n\nmodule Test0 extends Base, WithUid\n//│ module Test0 {\n//│   fun getUid: {uid: 'uid, underlying: 'underlying} -> 'uid\n//│   fun rewrap: ({uid: 'uid0, underlying: 'underlying0 & 'underlying1}, 'underlying1 -> 'underlying0) -> {uid: Int | 'uid0, underlying: 'underlying0}\n//│   fun setUid: ({uid: 'uid0, underlying: 'underlying0 & 'underlying1}, uid: Int) -> {uid: Int | 'uid0, underlying: 'underlying0}\n//│   fun unwrap: {uid: 'uid, underlying: 'underlying} -> 'underlying\n//│ }\n\nmodule Test0 extends Base, WithUid, WithUid\n//│ module Test0 {\n//│   fun getUid: {uid: anything, underlying: {uid: 'uid, underlying: 'underlying}} -> 'uid\n//│   fun rewrap: ({\n//│     uid: 'uid0,\n//│     underlying: {uid: 'uid1, underlying: 'underlying0 & 'underlying1} & 'underlying2\n//│   }, 'underlying1 -> 'underlying0) -> {\n//│     uid: Int | 'uid0,\n//│     underlying: {uid: Int | 'uid1, underlying: 'underlying0} | 'underlying2\n//│   }\n//│   fun setUid: ({\n//│     uid: 'uid0,\n//│     underlying: {uid: 'uid1, underlying: 'underlying0 & 'underlying1} & 'underlying2\n//│   }, uid: Int) -> {\n//│     uid: Int | 'uid0,\n//│     underlying: {uid: Int | 'uid1, underlying: 'underlying0} | 'underlying2\n//│   }\n//│   fun unwrap: {uid: anything, underlying: {uid: 'uid, underlying: 'underlying}} -> 'underlying\n//│ }\n\n\nmodule Test1 extends Base, WithUid, WithType\n//│ module Test1 {\n//│   fun getType: {uid: 'uid, underlying: {ty: 'ty, underlying: 'underlying}} -> 'ty\n//│   fun getUid: {uid: 'uid, underlying: {ty: 'ty, underlying: 'underlying}} -> 'uid\n//│   fun rewrap: ({\n//│     uid: 'uid0,\n//│     underlying: {ty: 'ty0, underlying: 'underlying0 & 'underlying1} & 'underlying2\n//│   }, 'underlying1 -> 'underlying0) -> {\n//│     uid: Int | 'uid0,\n//│     underlying: {ty: Type | 'ty0, underlying: 'underlying0} | 'underlying2\n//│   }\n//│   fun setType: ({\n//│     uid: 'uid0,\n//│     underlying: {ty: 'ty0, underlying: 'underlying0 & 'underlying1} & 'underlying2\n//│   }, ty: Type) -> {\n//│     uid: Int | 'uid0,\n//│     underlying: {ty: Type | 'ty0, underlying: 'underlying0} | 'underlying2\n//│   }\n//│   fun setUid: ({\n//│     uid: 'uid0,\n//│     underlying: {ty: 'ty0, underlying: 'underlying0 & 'underlying1} & 'underlying2\n//│   }, uid: Int) -> {\n//│     uid: Int | 'uid0,\n//│     underlying: {ty: Type | 'ty0, underlying: 'underlying0} | 'underlying2\n//│   }\n//│   fun unwrap: {uid: 'uid, underlying: {ty: 'ty, underlying: 'underlying}} -> 'underlying\n//│ }\n\nlet uid = 0\nlet ty = Type(\"A\")\nlet underlying = 42\nlet a = { uid, underlying: { ty, underlying } }\n//│ let uid: 0\n//│ let ty: Type\n//│ let underlying: 42\n//│ let a: {uid: 0, underlying: {ty: Type, underlying: 42}}\n//│ uid\n//│     = 0\n//│ ty\n//│    = Type {}\n//│ underlying\n//│            = 42\n//│ a\n//│   = { uid: 0, underlying: { ty: Type {}, underlying: 42 } }\n\nTest1.unwrap(a)\n//│ 42\n//│ res\n//│     = 42\n\nTest1.getUid(a)\n//│ 0\n//│ res\n//│     = 0\n\nTest1.setUid(a, 1)\n//│ {uid: Int, underlying: {ty: Type, underlying: 42}}\n//│ res\n//│     = { underlying: { ty: Type {}, underlying: 42 }, uid: 1 }\n\nTest1.getType(a).name\n//│ Str\n//│ res\n//│     = 'A'\n\na.underlying.ty.name\n//│ Str\n//│ res\n//│     = 'A'\n\nlet b = Test1.setType(a, Type(\"B\"))\n//│ let b: {uid: Int, underlying: {ty: Type, underlying: 42}}\n//│ b\n//│   = { underlying: { underlying: 42, ty: Type {} }, uid: 0 }\n\nTest1.getType(b).name\n//│ Str\n//│ res\n//│     = 'B'\n\nb.underlying.ty.name\n//│ Str\n//│ res\n//│     = 'B'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Metaprog.mls",
    "content": ":NewDefs\n\n\nclass Code[out A, out Ctx]\n//│ class Code[A, Ctx] {\n//│   constructor()\n//│ }\n\nclass IntLit(value: Int) extends Code[Int, nothing]\n//│ class IntLit(value: Int) extends Code\n\nclass Add[out C](lhs: Code[Int, C], rhs: Code[Int, C]) extends Code[Int, C]\n//│ class Add[C](lhs: Code[Int, C], rhs: Code[Int, C]) extends Code\n\nfun bind(x: Code['a, 'c], k: (forall 'cc: Code['a, 'cc] -> Code['b, 'cc])): Code['b, 'c] = k(x)\n//│ fun bind: forall 'a 'c 'b. (x: Code['a, 'c], k: forall 'cc. Code['a, 'cc] -> Code['b, 'cc]) -> Code['b, 'c]\n\n\n// * Note: extrusion\nfun test(f) =\n  bind of IntLit(42), n =>\n  f(n)\n  Add(n, IntLit(1))\n//│ fun test: (Code[Int, ??cc] -> ()) -> Code[Int, nothing]\n\n\nabstract class Test[C] {\n  // * Represents what happens in \"... ${input} ...\" when a binding of C is in scope\n  fun unquote: (input: Code['a, C | 'c]) -> Code[Int, 'c]\n  fun getVar: Code[Int, C]\n  fun test0 = this.unquote of IntLit(1)\n  fun test1 = this.unquote of Add(this.getVar, IntLit(1))\n}\n//│ abstract class Test[C] {\n//│   fun getVar: Code[Int, C]\n//│   fun test0: Code[Int, nothing]\n//│   fun test1: Code[Int, nothing]\n//│   fun unquote: forall 'c. (input: Code[anything, C | 'c]) -> Code[Int, 'c]\n//│ }\n\n\n:NoJS\n\nfun mkVar(f: forall 'C: Test['C] -> 'a): 'a\n//│ fun mkVar: forall 'a. (f: forall 'C. Test['C] -> 'a) -> 'a\n\nmkVar of t0 =>\n  t0.unquote of Add(t0.getVar, IntLit(1))\n//│ Code[Int, nothing]\n\nmkVar of t0 =>\n  Add(t0.getVar, IntLit(1))\n//│ Add[anything]\n\nmkVar of t0 =>\n  mkVar of t1 =>\n    t1.unquote of t0.unquote of Add(t0.getVar, t1.getVar)\n//│ Code[Int, ??C & ~??C0]\n\nmkVar of t0 =>\n  mkVar of t1 =>\n    t0.unquote of t1.unquote of Add(t0.getVar, t1.getVar)\n//│ Code[Int, nothing]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MethodSignatures.mls",
    "content": ":NewDefs\n\n\n\nmodule Oops {\n  fun a : Int\n  fun a = 2\n}\n//│ module Oops {\n//│   fun a: Int\n//│ }\n\n:e\nmodule Oops {\n  fun a : Int\n}\n//│ ╔══[ERROR] Member `a` is declared (or its declaration is inherited) but is not implemented in `Oops`\n//│ ║  l.14: \tmodule Oops {\n//│ ║        \t       ^^^^\n//│ ╟── Declared here:\n//│ ║  l.15: \t  fun a : Int\n//│ ╙──      \t  ^^^^^^^^^^^\n//│ module Oops {\n//│   fun a: Int\n//│ }\n\n:e\nmodule Oops {\n  fun a : Int\n  fun a : string\n  fun a = a\n}\n//│ ╔══[ERROR] A type signature for 'a' was already given\n//│ ║  l.30: \t  fun a : string\n//│ ╙──      \t  ^^^^^^^^^^^^^^\n//│ module Oops {\n//│   fun a: string\n//│ }\n\n:e\nmodule Oops {\n  fun a : Int\n  fun a = false\n}\n//│ ╔══[ERROR] Type mismatch in definition of method a:\n//│ ║  l.43: \t  fun a = false\n//│ ║        \t      ^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of `Int`\n//│ ║  l.43: \t  fun a = false\n//│ ║        \t          ^^^^^\n//│ ╟── but it flows into definition of method a with expected type `Int`\n//│ ║  l.43: \t  fun a = false\n//│ ║        \t      ^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.42: \t  fun a : Int\n//│ ║        \t          ^^^\n//│ ╟── from signature of member `a`:\n//│ ║  l.42: \t  fun a : Int\n//│ ╙──      \t      ^^^^^^^\n//│ module Oops {\n//│   fun a: Int\n//│ }\n\n:e\nmodule Oops {\n  fun a = 1\n  fun a = 2\n}\n//│ ╔══[ERROR] Redefinition of 'a'\n//│ ║  l.67: \t  fun a = 2\n//│ ╙──      \t      ^^^^^\n//│ module Oops {\n//│   fun a: 1\n//│ }\n\n\n\n// * Without a type signature, the method's inferred type is not generalized\nmodule A {\n  fun i(x) = x\n}\n//│ module A {\n//│   fun i: forall 'a. 'a -> 'a\n//│ }\n\n// * With a type signature, it is generalized and checked against the signature\nmodule A {\n  \n  fun i: forall 'a: 'a -> 'a\n  fun i(x) = x\n  \n  fun j: 'b -> 'b\n  fun j(x) = x\n  \n}\n//│ module A {\n//│   fun i: forall 'a. 'a -> 'a\n//│   fun j: forall 'b. 'b -> 'b\n//│ }\n\n\n:e\nmodule A {\n  fun i : 'a\n  fun i(x) = x\n}\n//│ ╔══[ERROR] Type mismatch in definition of method i:\n//│ ║  l.105: \t  fun i(x) = x\n//│ ║         \t      ^^^^^^^^\n//│ ╟── function of type `?a -> ?a` does not match type `'a`\n//│ ║  l.105: \t  fun i(x) = x\n//│ ║         \t       ^^^^^^^\n//│ ╟── but it flows into definition of method i with expected type `'a`\n//│ ║  l.105: \t  fun i(x) = x\n//│ ║         \t      ^^^^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.104: \t  fun i : 'a\n//│ ║         \t          ^^\n//│ ╟── from signature of member `i`:\n//│ ║  l.104: \t  fun i : 'a\n//│ ╙──       \t      ^^^^^^\n//│ module A {\n//│   fun i: nothing\n//│ }\n\n\n\n// FIXME currently type signatures are typed too early (not in the context where the other defns live)\n// We need to move all the typing unit setup to lazy type info prelude\n// :d\nmodule M {\n  class A\n  fun a: A\n  fun a = 1\n}\n//│ ╔══[ERROR] Type mismatch in definition of method a:\n//│ ║  l.134: \t  fun a = 1\n//│ ║         \t      ^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `A`\n//│ ║  l.134: \t  fun a = 1\n//│ ║         \t          ^\n//│ ╟── but it flows into definition of method a with expected type `A`\n//│ ║  l.134: \t  fun a = 1\n//│ ║         \t      ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.133: \t  fun a: A\n//│ ║         \t         ^\n//│ ╟── from signature of member `a`:\n//│ ║  l.133: \t  fun a: A\n//│ ╙──       \t      ^^^^\n//│ module M {\n//│   class A {\n//│     constructor()\n//│   }\n//│   fun a: A\n//│ }\n\n// FIXME similar\nmodule M {\n  class A\n  fun a: this.A\n  fun a = 1\n}\n//│ ╔══[ERROR] undeclared `this`\n//│ ║  l.161: \t  fun a: this.A\n//│ ╙──       \t         ^^^^\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: an implementation is missing\n\n// FIXME similar\nmodule M {\n  class A\n  fun a: M.A\n  fun a = 1\n}\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: an implementation is missing\n\n\n\n// * This is treated as a signature\nfun f(x: Int): Int\n//│ fun f: (x: Int) -> Int\n\n// * So is this!\nfun f(Int): Int\n//│ fun f: Int -> Int\n\n// * And this doesn't work\n:e\nfun f(x): Int\n//│ ╔══[ERROR] type identifier not found: x\n//│ ║  l.189: \tfun f(x): Int\n//│ ╙──       \t      ^\n//│ fun f: error -> Int\n\n// * But this does! (no longer a signature...)\nfun f(x): Int = 1\n//│ fun f: anything -> Int\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Misc.mls",
    "content": ":NewDefs\n\n\n1\n//│ 1\n//│ res\n//│     = 1\n\n2 + 2\n//│ Int\n//│ res\n//│     = 4\n\nlet r = { x: 1 }\n//│ let r: {x: 1}\n//│ r\n//│   = { x: 1 }\n\nr.x + 1\n//│ Int\n//│ res\n//│     = 2\n\n\nx => x + 1\n//│ Int -> Int\n//│ res\n//│     = [Function: res]\n\n{ y } => y\n//│ forall 'a. {y: 'a} -> 'a\n//│ res\n//│     = [Function: res]\n\nfun f({ y }) = y\n//│ fun f: forall 'a. {y: 'a} -> 'a\n\nfun f of { y } = y\n//│ fun f: forall 'a. {y: 'a} -> 'a\n\nf({y: 1})\n//│ 1\n//│ res\n//│     = 1\n\n\nfun f of x, y = x + y\n//│ fun f: (Int, Int) -> Int\n\nf of 1, 2\n//│ Int\n//│ res\n//│     = 3\n\n\nfun f of [x, y] = x + y\n//│ fun f: ([Int, Int]) -> Int\n\nf of [1, 2]\n//│ Int\n//│ res\n//│     = 3\n\n\nlet f = (x, y) => x + y\n//│ let f: (Int, Int) -> Int\n//│ f\n//│   = [Function: f4]\n\nf(1, 2)\n//│ Int\n//│ res\n//│     = 3\n\n:e\nf([1, 2])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.76: \tf([1, 2])\n//│ ║        \t^^^^^^^^^\n//│ ╟── argument of type `[[1, 2]]` does not match type `[?a, ?b]`\n//│ ║  l.76: \tf([1, 2])\n//│ ║        \t ^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.65: \tlet f = (x, y) => x + y\n//│ ╙──      \t         ^^^^\n//│ Int | error\n//│ res\n//│     = '1,2undefined'\n\n\n\n:e\nlet f = ((x, y)) => x + y\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.93: \tlet f = ((x, y)) => x + y\n//│ ╙──      \t         ^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.93: \tlet f = ((x, y)) => x + y\n//│ ╙──      \t                    ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.93: \tlet f = ((x, y)) => x + y\n//│ ╙──      \t                        ^\n//│ let f: error -> Int\n//│ Code generation encountered an error:\n//│   term App(Var(,),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))) is not a valid pattern\n\n:e\nf(1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.108: \tf(1, 2)\n//│ ║         \t^^^^^^^\n//│ ╟── argument list of type `[1, 2]` does not match type `[error]`\n//│ ║  l.108: \tf(1, 2)\n//│ ╙──       \t ^^^^^^\n//│ Int | error\n//│ res\n//│ Runtime error:\n//│   ReferenceError: f5 is not defined\n\n:re\nf((1, 2))\n//│ Int\n//│ res\n//│ Runtime error:\n//│   ReferenceError: f5 is not defined\n\n:re\nf([1, 2])\n//│ Int\n//│ res\n//│ Runtime error:\n//│   ReferenceError: f5 is not defined\n\n:e\nf[1, 2]\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.135: \tf[1, 2]\n//│ ╙──       \t^^^^^^^\n//│ error -> Int\n//│ res\n//│ Runtime error:\n//│   ReferenceError: f5 is not defined\n\n\n:e\nlet f = (((x, y))) => x + y\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.146: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t          ^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.146: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t                      ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.146: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t                          ^\n//│ let f: error -> Int\n//│ Code generation encountered an error:\n//│   term App(Var(,),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))) is not a valid pattern\n\n\n// * TODO maybe parse as type lambda?\nlet f = [x, y] => x + y\n//│ let f: ([Int, Int]) -> Int\n//│ f\n//│   = [Function: f5]\n\n:e\nf(1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.168: \tf(1, 2)\n//│ ║         \t^^^^^^^\n//│ ╟── argument list of type `[1, 2]` does not match type `[[?a, ?b]]`\n//│ ║  l.168: \tf(1, 2)\n//│ ╙──       \t ^^^^^^\n//│ Int | error\n//│ res\n//│ Runtime error:\n//│   TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))\n\nf([1, 2])\n//│ Int\n//│ res\n//│     = 3\n\n\nlet f = ([x, y]) => x + y\n//│ let f: ([Int, Int]) -> Int\n//│ f\n//│   = [Function: f6]\n\nf([1, 2])\n//│ Int\n//│ res\n//│     = 3\n\n:e\nf(1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.197: \tf(1, 2)\n//│ ║         \t^^^^^^^\n//│ ╟── argument list of type `[1, 2]` does not match type `[[?a, ?b]]`\n//│ ║  l.197: \tf(1, 2)\n//│ ╙──       \t ^^^^^^\n//│ Int | error\n//│ res\n//│ Runtime error:\n//│   TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))\n\n\nlet f = [[[x, y]]] => x + y\n//│ let f: ([[[Int, Int]]]) -> Int\n//│ f\n//│   = [Function: f7]\n\n:e\nf([[1, 2]])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.216: \tf([[1, 2]])\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── tuple literal of type `[1, 2]` does not match type `[[?a, ?b]]`\n//│ ║  l.216: \tf([[1, 2]])\n//│ ╙──       \t   ^^^^^^\n//│ Int | error\n//│ res\n//│ Runtime error:\n//│   TypeError: number 1 is not iterable (cannot read property Symbol(Symbol.iterator))\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MissingImplBug.mls",
    "content": ":NewDefs\n\n\ndeclare fun String: nothing\n//│ fun String: nothing\n\nlet makeString: anything => { length: Int, charCodeAt: Int => Int } = String\nlet StringInstance: { fromCharCode: Int => Str } = String\n//│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int}\n//│ let StringInstance: {fromCharCode: Int -> Str}\n//│ makeString\n//│            = [Function: String]\n//│ StringInstance\n//│                = [Function: String]\n\n// * Why do we get <missing implementation> below and not above??\n\ndeclare fun String: nothing\nlet makeString: anything => { length: Int, charCodeAt: Int => Int } = String\nlet StringInstance: { fromCharCode: Int => Str } = String\n//│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int}\n//│ let StringInstance: {fromCharCode: Int -> Str}\n//│ fun String: nothing\n//│ makeString\n//│            = [Function: String]\n//│ StringInstance\n//│                = [Function: String]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MissingTypeArg.mls",
    "content": "// * This is an example program where the error we get is really not ideal\n\n:NewDefs\n\n\n// * An example recursive definition:\n\nfun test(pt1, pt2) = pt1.color === pt1.color and\n  let p1 = pt1.parent\n  let p2 = pt2.parent\n  if p1 is undefined then true\n  else if p2 is undefined then true\n  else test(p1, p2)\n//│ fun test: forall 'a 'b 'c. ('a, 'c) -> Bool\n//│   where\n//│     'c <: {parent: Object & 'c & ~() | ()}\n//│     'a <: {color: Eql['b] & 'b, parent: Object & 'a & ~() | ()}\n\n\n// * This works out fine:\n\nclass MyPoint1[Col](val color: Col, val parent: MyPoint1[Col] | undefined)\n//│ class MyPoint1[Col](color: Col, parent: MyPoint1[Col] | ())\n\nval p = MyPoint1(0, undefined)\n//│ val p: MyPoint1['Col]\n//│   where\n//│     'Col :> 0\n//│ p\n//│   = MyPoint1 {}\n\ntest(p, p)\n//│ Bool\n//│ res\n//│     = true\n\n\n// * BUT... if we forgot to pass the type argument to MyPoint2 (getting a raw/nominal-tag type),\n// * the error is not helpful at all:\n\nclass MyPoint2[out Col](val color: Col, val parent: MyPoint2 | undefined)\n//│ class MyPoint2[Col](color: Col, parent: MyPoint2[anything] | ())\n\nval p = MyPoint2(0, undefined)\n//│ val p: MyPoint2[0]\n//│ p\n//│   = MyPoint2 {}\n\n:e\ntest(p, p)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.50: \ttest(p, p)\n//│ ║        \t^^^^^^^^^^\n//│ ╟── type variable `Col` leaks out of its scope\n//│ ║  l.41: \tclass MyPoint2[out Col](val color: Col, val parent: MyPoint2 | undefined)\n//│ ║        \t                   ^^^\n//│ ╟── into field selection of type `#Eql`\n//│ ║  l.8: \tfun test(pt1, pt2) = pt1.color === pt1.color and\n//│ ╙──     \t                     ^^^^^^^^^\n//│ error | false | true\n//│ res\n//│     = true\n\n\n\n// TODO[ucs] ideally this should work\n\nfun test(pt1, pt2) = pt1.color === pt1.color and\n  let p1 = pt1.parent\n  let p2 = pt2.parent\n  if p1 is undefined then p2 is undefined\n  else test(p1, p2)\n//│ fun test: forall 'a 'b 'c. ('a, 'c) -> Bool\n//│   where\n//│     'c <: {parent: Object & 'c}\n//│     'a <: {color: Eql['b] & 'b, parent: Object & 'a & ~() | ()}\n\n:e // TODO support\ntest(p, p)\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.79: \ttest(p, p)\n//│ ║        \t^^^^^^^^^^\n//│ ╟── type variable `Col` leaks out of its scope\n//│ ║  l.41: \tclass MyPoint2[out Col](val color: Col, val parent: MyPoint2 | undefined)\n//│ ║        \t                   ^^^\n//│ ╟── into field selection of type `#Eql`\n//│ ║  l.68: \tfun test(pt1, pt2) = pt1.color === pt1.color and\n//│ ╙──      \t                     ^^^^^^^^^\n//│ error\n//│ res\n//│     = true\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Mixin42.mls",
    "content": ":NewDefs\n\n\n\nmixin M1 { fun test = 21 }\nmixin M2 { fun test = super.test * this.factor }\nmixin M3 { val factor = 2 }\nclass C1() extends M1, M2, M3\nC1().test\n//│ mixin M1() {\n//│   fun test: 21\n//│ }\n//│ mixin M2() {\n//│   super: {test: Int}\n//│   this: {factor: Int}\n//│   fun test: Int\n//│ }\n//│ mixin M3() {\n//│   val factor: 2\n//│ }\n//│ class C1() {\n//│   val factor: 2\n//│   fun test: Int\n//│ }\n//│ Int\n//│ res\n//│     = 42\n\n\n\nclass C1(val factor: Int) extends M1, M2\nC1(2).test\n//│ class C1(factor: Int) {\n//│   fun test: Int\n//│ }\n//│ Int\n//│ res\n//│     = 42\n\n\nclass C1(val factor: Int) extends M1, M2\n//│ class C1(factor: Int) {\n//│   fun test: Int\n//│ }\n\n\n\n:e\nclass C1() extends M1, M2 { val factor = 2 }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.6: \tmixin M2 { fun test = super.test * this.factor }\n//│ ╙──     \t                                       ^^^^^^^\n//│ class C1() {\n//│   val factor: 2\n//│   fun test: Int\n//│ }\n\n// * Note that this `val` definition is not yet treated as a type signature/annotation\n:e\nclass C1() extends M1, M2 { val factor: Int = 2 }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.6: \tmixin M2 { fun test = super.test * this.factor }\n//│ ╙──     \t                                       ^^^^^^^\n//│ class C1() {\n//│   val factor: Int\n//│   fun test: Int\n//│ }\n\n\nabstract class C1 extends M1, M2 { val factor: Int }\nmodule C2 extends C1 { val factor = 2 }\nC2.test\n//│ abstract class C1 {\n//│   val factor: Int\n//│   fun test: Int\n//│ }\n//│ module C2 extends C1 {\n//│   val factor: 2\n//│   fun test: Int\n//│ }\n//│ Int\n//│ res\n//│     = 42\n\n\nclass C1() extends M1, M2 { val factor: Int; val factor = 2 }\nC1().test\n//│ class C1() {\n//│   val factor: Int\n//│   fun test: Int\n//│ }\n//│ Int\n//│ res\n//│     = 42\n\n\nabstract class C0 { val factor = 2 }\n//│ abstract class C0 {\n//│   val factor: 2\n//│ }\n\n:e\nclass C1() extends C0, M1, M2\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.6: \tmixin M2 { fun test = super.test * this.factor }\n//│ ╙──     \t                                       ^^^^^^^\n//│ class C1() extends C0 {\n//│   val factor: 2\n//│   fun test: Int\n//│ }\n\n\nabstract class C0 { val factor: Int }\n//│ abstract class C0 {\n//│   val factor: Int\n//│ }\n\n:e // * TODO support\nclass C1() extends C0, M1, M2 { val factor = 2 }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.6: \tmixin M2 { fun test = super.test * this.factor }\n//│ ╙──     \t                                       ^^^^^^^\n//│ class C1() extends C0 {\n//│   val factor: 2\n//│   fun test: Int\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MixinParameters.mls",
    "content": ":NewDefs\n\n\nmixin BaseTest(x: Int) {\n  fun test = x\n}\n//│ mixin BaseTest(x: Int) {\n//│   fun test: Int\n//│ }\n\nmodule Test extends BaseTest(42)\n//│ module Test {\n//│   fun test: Int\n//│ }\n\nTest.test\n//│ Int\n//│ res\n//│     = 42\n\n:e\nTest.x\n//│ ╔══[ERROR] Type `Test` does not contain member `x`\n//│ ║  l.22: \tTest.x\n//│ ╙──      \t    ^^\n//│ error\n//│ res\n//│     = undefined\n\n\nmixin BaseTest(val x: Int -> Int)\n//│ mixin BaseTest(x: Int -> Int)\n\nmodule Test extends BaseTest(id)\n//│ module Test\n\nTest.x(1)\n//│ 1\n//│ res\n//│     = 1\n\n\n:e // TODO support\nmixin BaseTest(x) {\n  fun test = x\n}\n//│ ╔══[ERROR] Mixin parameters currently need type annotations\n//│ ║  l.44: \tmixin BaseTest(x) {\n//│ ╙──      \t               ^\n//│ mixin BaseTest(x: error) {\n//│   fun test: error\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ModuleParameters.mls",
    "content": ":NewDefs\n\n\n:e\nmodule A(x: Int) { fun y = x }\n//│ ╔══[ERROR] Module parameters are not supported\n//│ ║  l.5: \tmodule A(x: Int) { fun y = x }\n//│ ╙──     \t         ^\n//│ module A(x: Int) {\n//│   fun y: Int\n//│ }\n\n:e\nA\n//│ ╔══[ERROR] Parameterized modules are not yet supported\n//│ ║  l.14: \tA\n//│ ╙──      \t^\n//│ (x: Int) -> A\n//│ res\n//│     = A { class: [class A] }\n\n:e\nA(123)\n//│ ╔══[ERROR] Parameterized modules are not yet supported\n//│ ║  l.23: \tA(123)\n//│ ╙──      \t^\n//│ A\n//│ res\n//│ Runtime error:\n//│   TypeError: A is not a function\n\n:e\nA.x\n//│ ╔══[ERROR] Parameterized modules are not yet supported\n//│ ║  l.33: \tA.x\n//│ ╙──      \t^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.33: \tA.x\n//│ ║        \t^^^\n//│ ╟── reference of type `(x: Int) -> A` does not have field 'x'\n//│ ║  l.33: \tA.x\n//│ ╙──      \t^\n//│ error\n//│ res\n//│     = undefined\n\n:e\nA.y\n//│ ╔══[ERROR] Parameterized modules are not yet supported\n//│ ║  l.48: \tA.y\n//│ ╙──      \t^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.48: \tA.y\n//│ ║        \t^^^\n//│ ╟── reference of type `(x: Int) -> A` does not have field 'y'\n//│ ║  l.48: \tA.y\n//│ ╙──      \t^\n//│ error\n//│ res\n//│     = undefined\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Mut.mls",
    "content": ":NewDefs\n\n\n:pe\nval v1: {mut 1}\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.5: \tval v1: {mut 1}\n//│ ╙──     \t             ^\n//│ val v1: {mut <error>: 1}\n//│ v1\n//│    = <missing implementation>\n\n:e\nval v1: {mut Int}\n//│ ╔══[ERROR] Field identifiers must start with a small letter\n//│ ║  l.14: \tval v1: {mut Int}\n//│ ╙──      \t             ^^^\n//│ val v1: {Int = Int}\n//│ v1\n//│    = <missing implementation>\n\n:e\nval v1 = {mut Int: 0}\n//│ ╔══[ERROR] Field identifiers must start with a small letter\n//│ ║  l.23: \tval v1 = {mut Int: 0}\n//│ ╙──      \t                   ^\n//│ val v1: {Int = 'Int}\n//│   where\n//│     'Int :> 0\n//│ v1\n//│    = { Int: 0 }\n\nval v1 = {mut int: 0}\n//│ val v1: {mut int: 'int}\n//│   where\n//│     'int :> 0\n//│ v1\n//│    = { int: 0 }\n\n\nval v1: {mut x: Int}\n//│ val v1: {mut x: Int}\n//│ v1\n//│    = <missing implementation>\n\n:pe\nval v1 = {mut 1}\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.47: \tval v1 = {mut 1}\n//│ ╙──      \t              ^\n//│ val v1: {mut <error>: '<error>}\n//│   where\n//│     '<error> :> 1\n//│ v1\n//│    = { '<error>': 1 }\n\nval v1 = {mut x: 1}\n//│ val v1: {mut x: 'x}\n//│   where\n//│     'x :> 1\n//│ v1\n//│    = { x: 1 }\n\n// * TODO: support this syntax?\n:pe\nv1.x = 1\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' instead\n//│ ║  l.66: \tv1.x = 1\n//│ ╙──      \t     ^\n//│ 1\n//│ res\n//│     = 1\n\n// * TODO: support this syntax?\n:e\n:ng\nv1.x <- 1\n//│ ╔══[ERROR] identifier not found: <-\n//│ ║  l.77: \tv1.x <- 1\n//│ ╙──      \t     ^^\n//│ error\n\n\n:pe\nval v2: (mut Int)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.85: \tval v2: (mut Int)\n//│ ╙──      \t             ^^^\n//│ val v2: Int\n//│ v2\n//│    = <missing implementation>\n\n:pe\nval v2 = (mut 1)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.94: \tval v2 = (mut 1)\n//│ ╙──      \t              ^\n//│ val v2: 1\n//│ v2\n//│    = 1\n\n:pe\nval v2: (mut x: Int)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.103: \tval v2: (mut x: Int)\n//│ ╙──       \t             ^^^^^^\n//│ val v2: Int\n//│ v2\n//│    = <missing implementation>\n\n:pe\nval v2 = (mut 1)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.112: \tval v2 = (mut 1)\n//│ ╙──       \t              ^\n//│ val v2: 1\n//│ v2\n//│    = 1\n\n:pe\nval v2 = (mut x: 1)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.121: \tval v2 = (mut x: 1)\n//│ ╙──       \t              ^^^^\n//│ val v2: 1\n//│ v2\n//│    = 1\n\n:pe\nval v2 = (mut y: 1)\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.130: \tval v2 = (mut y: 1)\n//│ ╙──       \t              ^^^^\n//│ val v2: 1\n//│ v2\n//│    = 1\n\n\nval v2: [mut Int]\n//│ val v2: [mut Int]\n//│ v2\n//│    = <missing implementation>\n\nval v2 = [mut 1]\n//│ val v2: [mut 'a]\n//│   where\n//│     'a :> 1\n//│ v2\n//│    = [ 1 ]\n\nval v2: [mut x: Int]\n//│ val v2: [mut x: Int]\n//│ v2\n//│    = <missing implementation>\n\nval v2 = [mut 1]\n//│ val v2: [mut 'a]\n//│   where\n//│     'a :> 1\n//│ v2\n//│    = [ 1 ]\n\nval v2 = [mut x: 1]\n//│ val v2: [mut x: 'x]\n//│   where\n//│     'x :> 1\n//│ v2\n//│    = [ 1 ]\n\nval v2 = [mut y: 1]\n//│ val v2: [mut y: 'y]\n//│   where\n//│     'y :> 1\n//│ v2\n//│    = [ 1 ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MutLet.mls",
    "content": ":NewDefs\n\n\nmut let i = 0\n//│ mut let i: 0\n//│ i\n//│   = 0\n\nset i = 1\n//│ ()\n//│ res\n//│     = undefined\n\ni\n//│ 0 | 1\n//│ res\n//│     = 1\n\n\nmut let f(x) =\n  set f = _ => x\n  x\n//│ mut let f: 'a -> 'a\n//│ f\n//│   = [Function: f]\n\nf(1)\n//│ 1\n//│ res\n//│     = 1\n\nf(true)\n//│ 1 | true\n//│ res\n//│     = true\n\n\nclass Some[A](value: A)\nmodule None\n//│ class Some[A](value: A)\n//│ module None\n\nmut let oops = None\n//│ mut let oops: None\n//│ oops\n//│      = None { class: [class None] }\n\nfun funny(x) =\n  set oops = Some(x)\n  x\n//│ fun funny: forall 'a. 'a -> 'a\n\nfunny(1)\n//│ 1\n//│ res\n//│     = 1\n\nif oops is\n  None then 0\n  Some(v) then v\n//│ 0 | 1\n//│ res\n//│     = 1\n\nset oops = Some(123)\n//│ ()\n//│ res\n//│     = undefined\n\noops\n//│ None | Some[in 'A out 1 | 123 | 'A]\n//│ res\n//│     = Some {}\n\n\n\nmut let oops = None\n//│ mut let oops: None\n//│ oops\n//│      = None { class: [class None] }\n\nfun funny(x) =\n  let tmp = oops\n  set oops = Some(x)\n  tmp\n//│ fun funny: 'A -> (None | Some['A])\n\nfunny(123)\n//│ None | Some[in 'A out 123 | 'A]\n//│ res\n//│     = None { class: [class None] }\n\nif funny(\"hi\") is\n  Some(v) then v\n  else 0\n//│ \"hi\" | 0 | 123\n//│ res\n//│     = 123\n\n\nmodule None\n//│ module None\n\nmut let m = None\n//│ mut let m: None\n//│ m\n//│   = None { class: [class None] }\n\nmut val m = None\nfun oops(x) = set m = x\n//│ mut val m: None | 'm\n//│ fun oops: 'm -> ()\n//│ m\n//│   = None { class: [class None] }\n\n\n:e\nlet x = 1\nset x = 2\nx\n//│ ╔══[ERROR] definition `x` is not mutable and cannot be reassigned\n//│ ║  l.119: \tset x = 2\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.119: \tset x = 2\n//│ ║         \t^^^^^^^^^\n//│ ╟── integer literal of type `2` does not match type `1`\n//│ ║  l.119: \tset x = 2\n//│ ║         \t        ^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.118: \tlet x = 1\n//│ ║         \t        ^\n//│ ╟── from definition of let binding x:\n//│ ║  l.118: \tlet x = 1\n//│ ╙──       \t    ^^^^^\n//│ let x: 1\n//│ 1\n//│ x\n//│   = 1\n//│ res\n//│     = undefined\n//│ res\n//│     = 2\n\n\nmut let min = 123\n//│ mut let min: 123\n//│ min\n//│     = 123\n\nset min = 42\n//│ ()\n//│ res\n//│     = undefined\n\nmin\n//│ 123 | 42\n//│ res\n//│     = 42\n\n\nfun repmin(t) =\n  mut let min = 123\n  let go(t) = set min = t.value\n  go(t)\n  min\n//│ fun repmin: forall 'min. {value: 'min} -> (123 | 'min)\n\n\nclass Leaf[out A](val value: A)\n//│ class Leaf[A](value: A)\n\nfun repmin(t) =\n  mut let min = 123\n  let go(t) = if t is\n    Leaf(n) then set min = n\n  go(t)\n  min\n//│ fun repmin: forall 'min. Leaf['min] -> (123 | 'min)\n\nfun repmin =\n  mut let min = 123\n  let go(t) = if t is\n    Leaf(n) then set min = n\n  [min, go]\n//│ fun repmin: forall 'min. [123 | 'min, Leaf['min] -> ()]\n\n\n:e\nmut val lol[A] = (x: A) => x\n//│ ╔══[ERROR] Type parameters are not yet supported in this position\n//│ ║  l.190: \tmut val lol[A] = (x: A) => x\n//│ ╙──       \t            ^\n//│ mut val lol: (x: 'A) -> 'A\n//│ lol\n//│     = [Function: lol]\n\n\n\n:NoJS\n\n\nmut let foo_ty = error\n//│ mut let foo_ty: nothing\n\n:ns\nlet rec body(x) =\n  log of x.m + 1\n  set foo_ty = body\n  x\n//│ let rec body: forall 'a 'm. 'a -> 'a\n//│   where\n//│     'a :> 'b\n//│        <: 'c & {m: 'm}\n//│     'm :> 'm0\n//│        <: Int\n//│     'c :> 'b\n//│     'b <: {m: 'm0}\n//│     'm0 <: Int\n\nfoo_ty of {m: 1}\n//│ {m: 1}\n\nfoo_ty of {m: 2}\n//│ {m: 1 | 2}\n\nbody({m: 3})\n//│ {m: 1 | 2 | 3}\n\nbody({m: 4})\n//│ {m: 1 | 2 | 4}\n\nbody\n//│ forall 'a. ({m: Int} & 'a) -> ({m: 1 | 2} | 'a)\n\nfoo_ty\n//│ ({m: Int} & 'a) -> ({m: 1 | 2 | 3 | 4} | 'a)\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/MutualRec.mls",
    "content": ":NewDefs\n\n\n\nclass Foo()\n123\n//│ class Foo()\n//│ 123\n//│ res\n//│     = 123\n\nFoo\n//│ () -> Foo\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Foo],\n//│         unapply: [Function: unapply]\n//│       }\n\n// TODO\nfun fooo(x) =\n  class C(y, z)\n  C(0, x)\n//│ ╔══[ERROR] Class parameters currently need type annotations\n//│ ║  l.22: \t  class C(y, z)\n//│ ╙──      \t          ^\n//│ ╔══[ERROR] Class parameters currently need type annotations\n//│ ║  l.22: \t  class C(y, z)\n//│ ╙──      \t             ^\n//│ fun fooo: error -> C\n\n\n\nfun foo = bar\nfun bar = foo\n//│ fun foo: nothing\n//│ fun bar: nothing\n\n:re\nfoo(bar)\n//│ nothing\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\nfun foo = {x: foo}\n//│ fun foo: forall 'foo. 'foo\n//│   where\n//│     'foo :> {x: 'foo}\n\n\nfun foo = {x: bar}\nfun bar = {y: foo}\n//│ fun foo: forall 'foo. 'foo\n//│ fun bar: forall 'foo. {y: 'foo}\n//│ where\n//│   'foo :> {x: {y: 'foo}}\n\n:re\nfoo\n//│ forall 'foo. 'foo\n//│   where\n//│     'foo :> {x: {y: 'foo}}\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:ns\n:re\nfoo\n//│ forall 'foo. {x: {y: 'foo}}\n//│   where\n//│     'foo :> {x: {y: 'foo}}\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nfoo.x\n//│ {y: 'foo}\n//│   where\n//│     'foo :> {x: {y: 'foo}}\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:re\nfoo.x.y\n//│ 'foo\n//│   where\n//│     'foo :> {x: {y: 'foo}}\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\nfun foo(a) = {h: a, t: bar(a)}\nfun bar(b) = foo(b)\n//│ fun foo: forall 'a 'b. 'a -> 'b\n//│ fun bar: forall 'a 'b. 'a -> 'b\n//│ where\n//│   'b :> {h: 'a, t: 'b}\n\n:ns\nfoo\n//│ forall 'a 'b 'c. 'a -> {h: 'a, t: 'c}\n//│   where\n//│     'c :> {h: 'a, t: 'c}\n//│     'a <: 'b\n//│     'b <: 'a\n//│ res\n//│     = [Function: foo3]\n\n\nfun foo(a) = {h1: a, t1: bar(a)}\nfun bar(b) = {h2: b, t2: foo(b)}\n//│ fun foo: forall 'a 'b 'c. 'a -> {h1: 'a, t1: 'b}\n//│ fun bar: forall 'a 'c. 'a -> {h2: 'a, t2: 'c}\n//│ where\n//│   'b :> {h2: 'a, t2: 'c}\n//│   'c :> {h1: 'a, t1: 'b}\n\n\n\nmodule Test0_1 {\n  fun a = Test0_2.b\n}\nmodule Test0_2 {\n  fun b = 123\n}\n//│ module Test0_1 {\n//│   fun a: 123\n//│ }\n//│ module Test0_2 {\n//│   fun b: 123\n//│ }\n\nTest0_1.a\n//│ 123\n//│ res\n//│     = 123\n\nclass Test0_1 {\n  fun a = Test0_2().b\n}\nclass Test0_2() {\n  fun b = 123\n}\n//│ class Test0_1 {\n//│   constructor()\n//│   fun a: 123\n//│ }\n//│ class Test0_2() {\n//│   fun b: 123\n//│ }\n\n\n:e\nmodule Test1_1 {\n  fun a = Test1_2.b\n}\nmodule Test1_2 {\n  fun b = Test1_1.a\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.164: \t  fun b = Test1_1.a\n//│ ╙──       \t                 ^^\n//│ module Test1_1 {\n//│   fun a: error\n//│ }\n//│ module Test1_2 {\n//│   fun b: error\n//│ }\n\n:re\nTest1_1.a\n//│ error\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n:e\nclass Test1_1 {\n  fun a = Test1_2().b\n}\nclass Test1_2 {\n  fun b = Test1_1().a\n}\n//│ ╔══[ERROR] Class Test1_2 cannot be instantiated as it exposes no constructor\n//│ ║  l.186: \t  fun a = Test1_2().b\n//│ ╙──       \t          ^^^^^^^\n//│ ╔══[ERROR] Class Test1_1 cannot be instantiated as it exposes no constructor\n//│ ║  l.189: \t  fun b = Test1_1().a\n//│ ╙──       \t          ^^^^^^^\n//│ class Test1_1 {\n//│   constructor()\n//│   fun a: error\n//│ }\n//│ class Test1_2 {\n//│   constructor()\n//│   fun b: error\n//│ }\n\n:e\nclass Test1_1() {\n  fun a = Test1_2().b\n}\nclass Test1_2() {\n  fun b = Test1_1().a\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.211: \t  fun b = Test1_1().a\n//│ ╙──       \t                   ^^\n//│ class Test1_1() {\n//│   fun a: error\n//│ }\n//│ class Test1_2() {\n//│   fun b: error\n//│ }\n\n:e\nclass Test1_1 {\n  fun a = (new Test1_2).b\n}\nclass Test1_2 {\n  fun b = (new Test1_1).a\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.228: \t  fun b = (new Test1_1).a\n//│ ╙──       \t                       ^^\n//│ class Test1_1 {\n//│   constructor()\n//│   fun a: error\n//│ }\n//│ class Test1_2 {\n//│   constructor()\n//│   fun b: error\n//│ }\n\nclass Test1_1 {\n  fun a: Int\n  fun a = (new Test1_2).b\n}\nclass Test1_2 {\n  fun b = (new Test1_1).a\n}\n//│ class Test1_1 {\n//│   constructor()\n//│   fun a: Int\n//│ }\n//│ class Test1_2 {\n//│   constructor()\n//│   fun b: Int\n//│ }\n\n\n:e\nmodule Test2_1 {\n  fun t2 = Test2_2\n  fun a = Test2_2.b\n  fun d = Test2_2.e\n  fun n = 456\n}\nmodule Test2_2 {\n  fun b = 123\n  fun c = Test2_1.a\n  fun e = Test2_1.n\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.268: \t  fun c = Test2_1.a\n//│ ╙──       \t                 ^^\n//│ module Test2_1 {\n//│   fun a: 123 | error\n//│   fun d: error\n//│   fun n: 456\n//│   fun t2: Test2_2\n//│ }\n//│ module Test2_2 {\n//│   fun b: 123\n//│   fun c: error\n//│   fun e: error\n//│ }\n\nTest2_1.t2.b\n//│ 123\n//│ res\n//│     = 123\n\nTest2_1.a\n//│ 123 | error\n//│ res\n//│     = 123\n\nTest2_1.d\n//│ error\n//│ res\n//│     = 456\n\nTest2_1.n\n//│ 456\n//│ res\n//│     = 456\n\nmodule Test2_1 {\n  fun t2 = Test2_2\n  fun a: Int\n  fun a = Test2_2.b\n  fun d = Test2_2.e\n  fun n: Int\n  fun n = 456\n}\nmodule Test2_2 {\n  fun b = 123\n  fun c = Test2_1.a\n  fun e = Test2_1.n\n}\n//│ module Test2_1 {\n//│   fun a: Int\n//│   fun d: Int\n//│   fun n: Int\n//│   fun t2: Test2_2\n//│ }\n//│ module Test2_2 {\n//│   fun b: 123\n//│   fun c: Int\n//│   fun e: Int\n//│ }\n\nTest2_1.t2.b\n//│ 123\n//│ res\n//│     = 123\n\nTest2_1.a\n//│ Int\n//│ res\n//│     = 123\n\nTest2_1.d\n//│ Int\n//│ res\n//│     = 456\n\nTest2_1.n\n//│ Int\n//│ res\n//│     = 456\n\n\nclass Test2(val n: Int) {\n  fun inc = Test3.inc(this)\n}\nmodule Test3 {\n  fun inc(t: Test2) = Test2(t.n + 1)\n}\n//│ class Test2(n: Int) {\n//│   fun inc: Test2\n//│ }\n//│ module Test3 {\n//│   fun inc: (t: Test2) -> Test2\n//│ }\n\n\n\nmixin Foo {\n  fun f(x) = x(f)\n}\n//│ mixin Foo() {\n//│   fun f: 'a -> 'b\n//│ }\n//│ where\n//│   'a <: ('a -> 'b) -> 'b\n\nmixin Foo {\n  fun f(x) = g(f), x\n  fun g(y) = y(g)\n}\n//│ mixin Foo() {\n//│   fun f: ('a & 'b) -> ('c -> 'b | 'a)\n//│   fun g: 'c -> 'b\n//│ }\n//│ where\n//│   'b :> 'c -> 'b\n//│   'c <: ('c -> 'b) -> 'b\n\nmixin Foo {\n  fun f(x) = g(x), x\n  fun g(y) = f(y)\n}\n//│ mixin Foo() {\n//│   fun f: 'a -> 'a\n//│   fun g: 'a -> 'a\n//│ }\n\nmodule Foo {\n  fun f(x) = g(x), x\n  fun g(y) = f(y)\n}\n//│ module Foo {\n//│   fun f: forall 'a. 'a -> 'a\n//│   fun g: forall 'a. 'a -> 'a\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NamedArgs.mls",
    "content": ":NewDefs\n\n\nfun test(x: 'a) = if x is undefined then 0 else x + 1\n//│ fun test: (x: Int | ()) -> Int\n\ntest(x: 0)\n//│ Int\n//│ res\n//│     = 1\n\n:e\ntest(x: 0, 1)\n//│ ╔══[ERROR] Unnamed arguments should appear first when using named arguments\n//│ ║  l.13: \ttest(x: 0, 1)\n//│ ╙──      \t    ^^^^^^^^^\n//│ error\n//│ res\n//│     = 1\n\n:e\ntest(y: 0)\n//│ ╔══[ERROR] Argument named 'x' is missing from this function call\n//│ ║  l.22: \ttest(y: 0)\n//│ ╙──      \t    ^^^^^^\n//│ Int\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\nfun test(x: 'a, y: 'b) = [x, y]\n//│ fun test: forall 'a 'b. (x: 'a, y: 'b) -> ['a, 'b]\n\n:e\ntest(x: 1, 2)\n//│ ╔══[ERROR] Unnamed arguments should appear first when using named arguments\n//│ ║  l.36: \ttest(x: 1, 2)\n//│ ╙──      \t    ^^^^^^^^^\n//│ error\n//│ res\n//│     = [ 1, 2 ]\n\n:e\ntest(x: 1, z: 3)\n//│ ╔══[ERROR] Argument named 'y' is missing from this function call\n//│ ║  l.45: \ttest(x: 1, z: 3)\n//│ ╙──      \t    ^^^^^^^^^^^^\n//│ [1, nothing]\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n:e\ntest(y: 0)\n//│ ╔══[ERROR] Number of arguments doesn't match function signature `forall 'a 'b. (x: 'a, y: 'b) -> ['a, 'b]`\n//│ ║  l.55: \ttest(y: 0)\n//│ ╙──      \t    ^^^^^^\n//│ error\n//│ res\n//│     = [ 0, undefined ]\n\n:e\ntest(1, x: 0)\n//│ ╔══[ERROR] Argument for parameter 'x' is duplicated\n//│ ║  l.64: \ttest(1, x: 0)\n//│ ╙──      \t    ^^^^^^^^^\n//│ ╔══[ERROR] Argument named 'y' is missing from this function call\n//│ ║  l.64: \ttest(1, x: 0)\n//│ ╙──      \t    ^^^^^^^^^\n//│ [0, nothing]\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n// * Notice no let binding is generated for the first argument\n:js\ntest(0, y: 1)\n//│ [0, 1]\n//│ // Prelude\n//│ class TypingUnit9 {}\n//│ const typing_unit9 = new TypingUnit9;\n//│ // Query 1\n//│ res = test1(0, 1);\n//│ // End of generated code\n//│ res\n//│     = [ 0, 1 ]\n\nid(test)(0, y: 1)\n//│ [0, 1]\n//│ res\n//│     = [ 0, 1 ]\n\nid(if true then test else error)(0, y: 1)\n//│ [0, 1]\n//│ res\n//│     = [ 0, 1 ]\n\n:e\nid(if true then test else id)(0, y: 1)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.100: \tid(if true then test else id)(0, y: 1)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = [ 0, 1 ]\n\n// * No let binding in that value of argument is a var or literal\n:js\nlet tmp = 2\ntest(0, y: tmp)\ntest(0, y: 200)\n//│ let tmp: 2\n//│ [0, 200]\n//│ // Prelude\n//│ class TypingUnit13 {}\n//│ const typing_unit13 = new TypingUnit13;\n//│ // Query 1\n//│ globalThis.tmp = 2;\n//│ // Query 2\n//│ res = test1(0, tmp);\n//│ // Query 3\n//│ res = test1(0, 200);\n//│ // End of generated code\n//│ tmp\n//│     = 2\n//│ res\n//│     = [ 0, 2 ]\n//│ res\n//│     = [ 0, 200 ]\n\n\n:js\ntest(0, y: 1 + 2)\n//│ [0, Int]\n//│ // Prelude\n//│ class TypingUnit14 {}\n//│ const typing_unit14 = new TypingUnit14;\n//│ // Query 1\n//│ res = ((y_1) => test1(0, y_1))(1 + 2);\n//│ // End of generated code\n//│ res\n//│     = [ 0, 3 ]\n\n\n\nfun fff(x: Int, y: Int, z: Int) = (x - y) * z\n//│ fun fff: (x: Int, y: Int, z: Int) -> Int\n\n// * Testing renaming\n:e\nfff(y: 2, z: y_1 + 1, x: z_1 - 2)\n//│ ╔══[ERROR] identifier not found: y_1\n//│ ║  l.152: \tfff(y: 2, z: y_1 + 1, x: z_1 - 2)\n//│ ╙──       \t             ^^^\n//│ ╔══[ERROR] identifier not found: z_1\n//│ ║  l.152: \tfff(y: 2, z: y_1 + 1, x: z_1 - 2)\n//│ ╙──       \t                         ^^^\n//│ Int\n//│ Code generation encountered an error:\n//│   unresolved symbol z_1\n\n:js\nlet y_1 = 2\nlet z_1 = 3\nfff(y: 2, z: y_1 + 1, x: z_1 - 2)\n//│ let y_1: 2\n//│ let z_1: 3\n//│ Int\n//│ // Prelude\n//│ class TypingUnit17 {}\n//│ const typing_unit17 = new TypingUnit17;\n//│ // Query 1\n//│ globalThis[\"y_1\"] = 2;\n//│ // Query 2\n//│ globalThis[\"z_1\"] = 3;\n//│ // Query 3\n//│ res = ((z_2) => ((x_1) => fff(x_1, 2, z_2))(z_1 - 2))(y_1 + 1);\n//│ // End of generated code\n//│ y_1\n//│     = 2\n//│ z_1\n//│     = 3\n//│ res\n//│     = -3\n\n\nclass A() {\n  fun ma(x: Int, y: Int) = x - y\n  fun mma(x: Int, y: Int) = y - x\n} \n//│ class A() {\n//│   fun ma: (x: Int, y: Int) -> Int\n//│   fun mma: (x: Int, y: Int) -> Int\n//│ }\n\nlet x = A()\nx.ma(y: 2, x: 1)\n//│ let x: A\n//│ Int\n//│ x\n//│   = A {}\n//│ res\n//│     = -1\n\nA().ma(x: 1, y: 2)\n//│ Int\n//│ res\n//│     = -1\n\nid(x).ma(y: 2, x: 1)\n//│ Int\n//│ res\n//│     = -1\n\n\nfun print(x: Int) = (y: Int, z: Int) => log([x, y, z])\nlet p = print(0)\n//│ fun print: (x: Int) -> (y: Int, z: Int) -> ()\n//│ let p: (y: Int, z: Int) -> ()\n//│ p\n//│   = [Function (anonymous)]\n\np(z: 1, y: 2)\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ [ 0, 2, 1 ]\n\n:e\nfun print(x) = (y, z) => log([x, y, z])\nlet p = print(0)\np(z: 1, y: 2)\n//│ ╔══[ERROR] Cannot use named arguments as the function type has untyped arguments\n//│ ║  l.234: \tp(z: 1, y: 2)\n//│ ╙──       \t ^^^^^^^^^^^^\n//│ fun print: anything -> (anything, anything) -> ()\n//│ let p: (anything, anything) -> ()\n//│ error\n//│ p\n//│   = [Function (anonymous)]\n//│ res\n//│     = undefined\n//│ // Output\n//│ [ 0, 1, 2 ]\n\n\nclass Baz() {\n  fun f(x: Int, y: Int) = log([x, y])\n}\nBaz().f(y: 1, x: 2)\n//│ class Baz() {\n//│   fun f: (x: Int, y: Int) -> ()\n//│ }\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ [ 2, 1 ]\n\nlet b = Baz()\nb.f(y: 1, x: 2)\n//│ let b: Baz\n//│ ()\n//│ b\n//│   = Baz {}\n//│ res\n//│     = undefined\n//│ // Output\n//│ [ 2, 1 ]\n\n\nclass A(val x: Int, val y: Int)\n//│ class A(x: Int, y: Int)\n\nlet z = A(y: 2, x: 1)\nz.x\nz.y\n//│ let z: A\n//│ Int\n//│ z\n//│   = A {}\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n\n:e\n(f => f(x: a))\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.290: \t(f => f(x: a))\n//│ ╙──       \t      ^\n//│ anything -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol a\n\n:e\n(f => f)(error)(x: a)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.299: \t(f => f)(error)(x: a)\n//│ ╙──       \t^^^^^^^^^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol a\n\n:e\n(f => f)(42)(x: a)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.308: \t(f => f)(42)(x: a)\n//│ ╙──       \t^^^^^^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol a\n\n:e\n(f => f)(if true then 123 else false)(x: a)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.317: \t(f => f)(if true then 123 else false)(x: a)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol a\n\n(f => f)(if true then (x: Int) => x + 1 else error)(x: 123)\n//│ Int\n//│ res\n//│     = 124\n\n:e\n(f => if true then f else id)(if true then (x: Int) => x + 1 else id)(x: 123)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.331: \t(f => if true then f else id)(if true then (x: Int) => x + 1 else id)(x: 123)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 124\n\n:e\n(f => if true then f else id)(if true then (x: Int) => x + 1 else (x: Int) => x + 1)(x: 123)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.340: \t(f => if true then f else id)(if true then (x: Int) => x + 1 else (x: Int) => x + 1)(x: 123)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 124\n\n\nfun foo(f: (x: Int) => Int) = f(x: 123)\n//│ fun foo: (f: (x: Int) -> Int) -> Int\n\nfun foo(f: ((x: Int) => Int) & 'a) = [f(x: 123), f]\n//│ fun foo: forall 'b 'a. (f: (x: Int) -> Int & 123 -> 'b & 'a) -> ['b, (x: Int) -> Int & 'a]\n\nfoo((x: Int) => 1)\n//│ [1, (x: Int) -> 1]\n//│ res\n//│     = [ 1, [Function (anonymous)] ]\n\n\n:e\nfun foo(f: ((x: Int) => Int) | 'a) = f(x: 123)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `(x: Int) -> Int | 'a` for applying named arguments\n//│ ║  l.362: \tfun foo(f: ((x: Int) => Int) | 'a) = f(x: 123)\n//│ ╙──       \t                                     ^\n//│ fun foo: (f: anything) -> error\n\n\n// * the result of the if-then-else is a TV with two LBs: the type of x and the function type\n:e\nfun foo(x) = (if true then (x: Int) => x + 1 else x)(x: 123)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `(x: Int) -> ?a | ?b` for applying named arguments\n//│ ║  l.371: \tfun foo(x) = (if true then (x: Int) => x + 1 else x)(x: 123)\n//│ ╙──       \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun foo: anything -> error\n\nfoo((y: Int) => y)\n//│ error\n//│ res\n//│     = 124\n\n\n:e // TODO later: this could be made to work...\nfun foo(x) = (if true then (x: Int) => x + 1 else (x: Int) => x + 1)(x: 123)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `(x: Int) -> (?a | ?b)` for applying named arguments\n//│ ║  l.384: \tfun foo(x) = (if true then (x: Int) => x + 1 else (x: Int) => x + 1)(x: 123)\n//│ ╙──       \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun foo: anything -> error\n\n\nfun foo(x) = if true then (x: Int) => x + 1 else x\n//│ fun foo: forall 'a. 'a -> ((x: Int) -> Int | 'a)\n\n:e\nfoo((y: Int) => y)(x: 123)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.395: \tfoo((y: Int) => y)(x: 123)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 124\n\n:e\nfoo((x: Int) => x - 1)(x: 123)\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a` for applying named arguments\n//│ ║  l.404: \tfoo((x: Int) => x - 1)(x: 123)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 124\n\n\nfun foo1(x) = [x + 1, x]\n//│ fun foo1: forall 'a. (Int & 'a) -> [Int, 'a]\n\n:e\nfoo1(x: 123)\n//│ ╔══[ERROR] Cannot use named arguments as the function type has untyped arguments\n//│ ║  l.417: \tfoo1(x: 123)\n//│ ╙──       \t    ^^^^^^^^\n//│ error\n//│ res\n//│     = [ 124, 123 ]\n\n\nfun foo1(x: Int & 'a) = [x + 1, x]\n//│ fun foo1: forall 'a. (x: Int & 'a) -> [Int, Int & 'a]\n\nfoo1(x: 123)\n//│ [Int, 123]\n//│ res\n//│     = [ 124, 123 ]\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NestedClasses.mls",
    "content": ":NewDefs\n\n\nclass C0() {\n  class NC0()\n}\n//│ class C0() {\n//│   class NC0()\n//│ }\n\nlet c = C0()\n//│ let c: C0\n//│ c\n//│   = C0 {}\n\n:e\nc.NC0\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.17: \tc.NC0\n//│ ╙──      \t ^^^^\n//│ error\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class NC0],\n//│         unapply: [Function: unapply]\n//│       }\n\n\nmodule M0 {\n  class NC0\n}\n//│ module M0 {\n//│   class NC0 {\n//│     constructor()\n//│   }\n//│ }\n\n:e\nM0.NC0\n//│ ╔══[ERROR] Access to class member not yet supported\n//│ ║  l.39: \tM0.NC0\n//│ ╙──      \t  ^^^^\n//│ error\n//│ res\n//│     = [class NC0]\n\n\nmodule M1 {\n  module NM1\n}\n//│ module M1 {\n//│   module NM1\n//│ }\n\n:e\nM1.NM1\n//│ ╔══[ERROR] Access to module member not yet supported\n//│ ║  l.56: \tM1.NM1\n//│ ╙──      \t  ^^^^\n//│ error\n//│ res\n//│     = NM1 { class: [class NM1] }\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NestedRecords.mls",
    "content": ":NewDefs\n\n\nlet f(x) = [x, x]\n//│ let f: forall 'a. 'a -> ['a, 'a]\n//│ f\n//│   = [Function: f]\n\nlet a = { u: f(f(f(1))), v: f(f(f(1))) }\n//│ let a: {u: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], v: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]]}\n//│ a\n//│   = {\n//│       u: [ [ [Array], [Array] ], [ [Array], [Array] ] ],\n//│       v: [ [ [Array], [Array] ], [ [Array], [Array] ] ]\n//│     }\n\n{ a }\n//│ {\n//│   a: {u: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], v: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]]}\n//│ }\n//│ res\n//│     = { a: { u: [ [Array], [Array] ], v: [ [Array], [Array] ] } }\n\n{ a, b: a } \n//│ {\n//│   a: {u: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], v: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]]},\n//│   b: {u: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], v: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]]}\n//│ }\n//│ res\n//│     = {\n//│         a: { u: [ [Array], [Array] ], v: [ [Array], [Array] ] },\n//│         b: { u: [ [Array], [Array] ], v: [ [Array], [Array] ] }\n//│       }\n\n{ x: { a, b: a } } \n//│ {\n//│   x: {\n//│     a: {u: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], v: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]]},\n//│     b: {u: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]], v: [[[1, 1], [1, 1]], [[1, 1], [1, 1]]]}\n//│   }\n//│ }\n//│ res\n//│     = { x: { a: { u: [Array], v: [Array] }, b: { u: [Array], v: [Array] } } }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/New.mls",
    "content": ":NewDefs\n\n\nclass Foo[A](x: A)\n//│ class Foo[A](x: A)\n\nlet f = Foo(1)\n//│ let f: Foo['A]\n//│   where\n//│     'A :> 1\n//│ f\n//│   = Foo {}\n\n// let f = new Foo(1)\n\nif f is Foo then 1 else 0\n//│ 0 | 1\n//│ res\n//│     = 1\n\nif f is Foo(a) then a else 0\n//│ 0 | 1\n//│ res\n//│     = 1\n\n// case f of\n//   { Foo ->\n//     let a = f.x\n//     a\n//   | _ -> 0\n//   }\n\n// Foo(A) =:= Foo & { x: A }\n\n\nfun test(x) = if x is Foo(a) then a\n//│ fun test: forall 'a. Foo['a] -> 'a\n\ntest(f)\n//│ 1\n//│ res\n//│     = 1\n\nclass PoInt(x: Int, y: Int)\n//│ class PoInt(x: Int, y: Int)\n\nlet origin = new PoInt(0, 0)\n//│ let origin: PoInt\n//│ origin\n//│        = PoInt {}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NewNew.mls",
    "content": ":NewDefs\n\n\nclass Foo(val x: Int)\n//│ class Foo(x: Int)\n\nlet f = Foo(1)\n//│ let f: Foo\n//│ f\n//│   = Foo {}\n\nf.x\n//│ Int\n//│ res\n//│     = 1\n\nlet f = new Foo(1)\n//│ let f: Foo\n//│ f\n//│   = Foo {}\n\nf.x\n//│ Int\n//│ res\n//│     = 1\n\nnew Foo(1).x\n//│ Int\n//│ res\n//│     = 1\n\nif f is Foo then 1 else 0\n//│ 0 | 1\n//│ res\n//│     = 1\n\nif f is Foo(a) then a else 0\n//│ Int\n//│ res\n//│     = 1\n\nlet f = Foo\n//│ let f: (x: Int) -> Foo\n//│ f\n//│   = [Function (anonymous)] {\n//│       class: [class Foo],\n//│       unapply: [Function: unapply]\n//│     }\n\nf(1)\n//│ Foo\n//│ res\n//│     = Foo {}\n\n\nclass Foo {\n  constructor(x: Int){}\n  val y = 2\n}\n//│ class Foo {\n//│   constructor(x: Int)\n//│   val y: 2\n//│ }\n\nnew Foo(1).y\n//│ 2\n//│ res\n//│     = 2\n\n:e\nlet f = Foo(1)\n//│ ╔══[ERROR] Construction of unparameterized class Foo should use the `new` keyword\n//│ ║  l.71: \tlet f = Foo(1)\n//│ ╙──      \t        ^^^\n//│ let f: Foo\n//│ f\n//│ Runtime error:\n//│   TypeError: Class constructor Foo cannot be invoked without 'new'\n\n:e\nlet f = new Foo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.81: \tlet f = new Foo\n//│ ║        \t            ^^^\n//│ ╟── argument list of type `[]` does not match type `[x: Int]`\n//│ ║  l.81: \tlet f = new Foo\n//│ ╙──      \t               ^\n//│ let f: Foo | error\n//│ f\n//│   = Foo {}\n\n:e\nf(1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.93: \tf(1)\n//│ ║        \t^^^^\n//│ ╟── application of type `Foo` is not a function\n//│ ║  l.81: \tlet f = new Foo\n//│ ║        \t            ^^^\n//│ ╟── but it flows into reference with expected type `1 -> ?a`\n//│ ║  l.93: \tf(1)\n//│ ╙──      \t^\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: f4 is not a function\n\n:e\nnew Foo(\"2\")\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.109: \tnew Foo(\"2\")\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── string literal of type `\"2\"` is not an instance of type `Int`\n//│ ║  l.109: \tnew Foo(\"2\")\n//│ ║         \t        ^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.57: \t  constructor(x: Int){}\n//│ ╙──      \t                 ^^^\n//│ Foo | error\n//│ res\n//│     = Foo {}\n\n:e\nnew Foo()\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.124: \tnew Foo()\n//│ ║         \t^^^^^^^^^\n//│ ╟── argument list of type `[]` does not match type `[x: Int]`\n//│ ║  l.124: \tnew Foo()\n//│ ╙──       \t       ^^\n//│ Foo | error\n//│ res\n//│     = Foo {}\n\n\n\nclass PoInt[out A](x: A, y: A)\n//│ class PoInt[A](x: A, y: A)\n\nnew PoInt(1, 2)\n//│ PoInt[1 | 2]\n//│ res\n//│     = PoInt {}\n\n:e\nnew PoInt\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.146: \tnew PoInt\n//│ ║         \t    ^^^^^\n//│ ╟── argument list of type `[]` does not match type `[x: ?A, y: ?A]`\n//│ ║  l.146: \tnew PoInt\n//│ ╙──       \t         ^\n//│ PoInt[nothing] | error\n//│ res\n//│     = PoInt {}\n\n:e\nnew PoInt['_]\n//│ ╔══[ERROR] Type arguments in `new` expressions are not yet supported\n//│ ║  l.158: \tnew PoInt['_]\n//│ ╙──       \t    ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.158: \tnew PoInt['_]\n//│ ║         \t    ^^^^^^^^^\n//│ ╟── argument list of type `[]` does not match type `[x: ?A, y: ?A]`\n//│ ║  l.158: \tnew PoInt['_]\n//│ ╙──       \t             ^\n//│ PoInt[nothing] | error\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: TyApp(Var(PoInt),List('_))\n\n:e\nnew PoInt[Str](0, 0)\n//│ ╔══[ERROR] Type arguments in `new` expressions are not yet supported\n//│ ║  l.173: \tnew PoInt[Str](0, 0)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^\n//│ PoInt[0]\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: TyApp(Var(PoInt),List(TypeName(Str)))\n\ntype T = PoInt[Str]\n//│ type T = PoInt[Str]\n\n:e\nnew T(0, 0)\n//│ ╔══[ERROR] Type alias T cannot be used in `new` expression\n//│ ║  l.185: \tnew T(0, 0)\n//│ ╙──       \t^^^^^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   type alias T is not a valid expression\n\nlet origin = new PoInt(0, 0)\n//│ let origin: PoInt[0]\n//│ origin\n//│        = PoInt {}\n\n:e // TODO support\nlet origin = PoInt[Int](0, 0)\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.199: \tlet origin = PoInt[Int](0, 0)\n//│ ╙──       \t             ^^^^^^^^^^\n//│ let origin: PoInt[0]\n//│ origin\n//│        = PoInt {}\n\n:e // TODO support\nlet origin = new PoInt[Int](0, 0)\n//│ ╔══[ERROR] Type arguments in `new` expressions are not yet supported\n//│ ║  l.208: \tlet origin = new PoInt[Int](0, 0)\n//│ ╙──       \t             ^^^^^^^^^^^^^^^^^^^^\n//│ let origin: PoInt[0]\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: TyApp(Var(PoInt),List(TypeName(Int)))\n\n\n:e // TODO support\nnew {}\n//│ ╔══[ERROR] Unexpected type `anything` after `new` keyword\n//│ ║  l.218: \tnew {}\n//│ ╙──       \t    ^^\n//│ error\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: Bra(true,Rcd(List()))\n\n:pe\n:e\nnew\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.228: \tnew\n//│ ╙──       \t   ^\n//│ ╔══[ERROR] Unexpected type `()` after `new` keyword\n//│ ║  l.228: \tnew\n//│ ╙──       \t   ^\n//│ error\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: UnitLit(true)\n\n// Support?\n:pe\n:e\nnew\n  x: 0\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.243: \t  x: 0\n//│ ╙──       \t  ^\n//│ ╔══[ERROR] Unexpected type `nothing` after `new` keyword\n//│ ║  l.243: \t  x: 0\n//│ ╙──       \t  ^\n//│ error\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: Blk(List(Asc(Var(x),Literal(IntLit(0)))))\n\n\n\n\nfun f(x) = {x}\n//│ fun f: forall 'a. 'a -> {x: 'a}\n\n:e\nnew f(1)\n//│ ╔══[ERROR] type identifier not found: f\n//│ ║  l.261: \tnew f(1)\n//│ ╙──       \t    ^\n//│ error\n//│ res\n//│     = { x: 1 }\n\n\nmodule Oops\n//│ module Oops\n\n:e\nnew Oops\n//│ ╔══[ERROR] Module Oops cannot be used in `new` expression\n//│ ║  l.274: \tnew Oops\n//│ ╙──       \t    ^^^^\n//│ error\n//│ res\n//│     = Oops {}\n\n\n:e\nnew Oops2\ntrait Oops2\n//│ ╔══[ERROR] Trait Oops2 cannot be used in `new` expression\n//│ ║  l.284: \tnew Oops2\n//│ ╙──       \t    ^^^^^\n//│ trait Oops2\n//│ error\n//│ Code generation encountered an error:\n//│   trait used in term position\n\n\n\nmodule A { class B }\n//│ module A {\n//│   class B {\n//│     constructor()\n//│   }\n//│ }\n\n:ge // TODO support\nnew A.B\n//│ B\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: Sel(Var(A),Var(B))\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NoThisCtor.mls",
    "content": ":NewDefs\n\nclass Base(val base: Int) {\n  fun getBase1 = base\n  fun getBase2 = this.base\n  fun foo(x) = this.base + x\n}\n//│ class Base(base: Int) {\n//│   fun foo: Int -> Int\n//│   fun getBase1: Int\n//│   fun getBase2: Int\n//│ }\n\nclass Foo() {\n  virtual val foo: Int = 42\n}\n//│ class Foo() {\n//│   val foo: Int\n//│ }\n\n:e\nclass Foo1() extends Foo() {\n  val foo: Int\n  virtual val foo = 1\n  log(this.foo)\n}\n//│ ╔══[ERROR] Cannot access `this` during object initialization\n//│ ║  l.25: \t  log(this.foo)\n//│ ╙──      \t      ^^^^\n//│ class Foo1() extends Foo {\n//│   val foo: Int\n//│ }\n\n:e\nclass Foo2() extends Foo() {\n  virtual val foo: Int\n  val foo = 2\n  constructor() {\n    log(this.foo)\n  }\n}\n//│ ╔══[ERROR] Cannot access `this` during object initialization\n//│ ║  l.39: \t    log(this.foo)\n//│ ╙──      \t        ^^^^\n//│ ╔══[ERROR] identifier not found: this\n//│ ║  l.39: \t    log(this.foo)\n//│ ╙──      \t        ^^^^\n//│ class Foo2() extends Foo {\n//│   constructor()\n//│   val foo: Int\n//│ }\n\n:e\nclass Foo3() extends Foo() {\n  val foo: Int\n  virtual val foo = 3\n  val s = this.foo\n}\n//│ ╔══[ERROR] Cannot access `this` while initializing field s\n//│ ║  l.57: \t  val s = this.foo\n//│ ╙──      \t          ^^^^\n//│ class Foo3() extends Foo {\n//│   val foo: Int\n//│   val s: Int\n//│ }\n\n:e\nclass Foo4() extends Foo() {\n  val foo: Int\n  virtual val foo = 4\n  fun bar(x) = this.foo + x // ok\n  let bb = bar(0) // call `this` indirectly\n}\n//│ ╔══[ERROR] Cannot access `this` while initializing field bb\n//│ ║  l.72: \t  let bb = bar(0) // call `this` indirectly\n//│ ║        \t      ^^^^^^^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.71: \t  fun bar(x) = this.foo + x // ok\n//│ ╙──      \t               ^^^^\n//│ class Foo4() extends Foo {\n//│   fun bar: Int -> Int\n//│   let bb: Int\n//│   val foo: Int\n//│ }\n\n:e\nclass Foo5() extends Foo() {\n  val foo: Int\n  val x = bar(0)\n  fun bar(y: Int) = this.foo + y\n}\n//│ ╔══[ERROR] Cannot access `this` while initializing field x\n//│ ║  l.89: \t  val x = bar(0)\n//│ ║        \t      ^^^^^^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.90: \t  fun bar(y: Int) = this.foo + y\n//│ ╙──      \t                    ^^^^\n//│ class Foo5() extends Foo {\n//│   fun bar: (y: Int) -> Int\n//│   val foo: Int\n//│   val x: Int\n//│ }\n\nclass Foo6() extends Foo() {\n  val baz: Int\n  val baz = 0\n  val y = this.baz // baz is final\n}\n//│ class Foo6() extends Foo {\n//│   val baz: Int\n//│   val foo: Int\n//│   val y: Int\n//│ }\n\nclass Bar() {\n  val d: Int\n  val d = 1\n  fun add(x) = x + this.d\n}\n//│ class Bar() {\n//│   fun add: Int -> Int\n//│   val d: Int\n//│ }\n\n:e\nclass Bar2() extends Bar() {\n  val two = this.add(1) // add is final, but it refers to `this`\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.127: \t  val two = this.add(1) // add is final, but it refers to `this`\n//│ ╙──       \t                ^^^^\n//│ ╔══[ERROR] Cannot access `this` while initializing field two\n//│ ║  l.127: \t  val two = this.add(1) // add is final, but it refers to `this`\n//│ ║         \t      ^^^^^^^^^^^^^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.118: \t  fun add(x) = x + this.d\n//│ ╙──       \t                   ^^^^\n//│ class Bar2() extends Bar {\n//│   fun add: Int -> Int\n//│   val d: Int\n//│   val two: error\n//│ }\n\n// it accesses this in an unusual way!\n:e\nabstract class Foo: (Int -> Int) {\n  val x = f\n  fun f = this(0)\n}\n//│ ╔══[ERROR] Cannot access `this` while initializing field x\n//│ ║  l.147: \t  val x = f\n//│ ║         \t      ^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.148: \t  fun f = this(0)\n//│ ╙──       \t          ^^^^\n//│ abstract class Foo: Int -> Int {\n//│   fun f: nothing\n//│   val x: nothing\n//│ }\n"
  },
  {
    "path": "shared/src/test/diff/nu/NuAlexJ.mls",
    "content": ":NewDefs\n\n\nfun foo(x) = [x, x]\n//│ fun foo: forall 'a. 'a -> ['a, 'a]\n\nid\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: id]\n\nlet r = foo(id)\n//│ let r: [forall 'a. 'a -> 'a, forall 'a. 'a -> 'a]\n//│ r\n//│   = [ [Function: id], [Function: id] ]\n\n\nfun fst(x, _) = x\nfun snd(_, x) = x\n//│ fun fst: forall 'a. ('a, anything) -> 'a\n//│ fun snd: forall 'b. (anything, 'b) -> 'b\n\nfst(1, 2)\n//│ 1\n//│ res\n//│     = 1\n\n:e\nfst([1, 2])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.29: \tfst([1, 2])\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── argument of type `[[1, 2]]` does not match type `[?a, ?b]`\n//│ ║  l.29: \tfst([1, 2])\n//│ ║        \t   ^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.18: \tfun fst(x, _) = x\n//│ ╙──      \t       ^^^^^^\n//│ error\n//│ res\n//│     = [ 1, 2 ]\n\n\nfun fst([x, _]) = x\nfun snd([_, x]) = x\n//│ fun fst: forall 'a. (['a, anything]) -> 'a\n//│ fun snd: forall 'b. ([anything, 'b]) -> 'b\n\nlet s = fst(r)\n//│ let s: forall 'a. 'a -> 'a\n//│ s\n//│   = [Function: id]\n\ns(\"hello\")\n//│ \"hello\"\n//│ res\n//│     = 'hello'\n\ns(123)\n//│ 123\n//│ res\n//│     = 123\n\nfst(r)(\"hello\")\n//│ \"hello\"\n//│ res\n//│     = 'hello'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NuForallTerms.mls",
    "content": ":NewDefs\n\n\nforall 'a: (x: 'a) => x\n//│ forall 'a. (x: 'a) -> 'a\n//│ res\n//│     = [Function: res]\n\n\nforall 'a:\n  (x: 'a) => x\n//│ forall 'a. (x: 'a) -> 'a\n//│ res\n//│     = [Function (anonymous)]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NuPolymorphicTypeAliases.mls",
    "content": ":NewDefs\n\n\ntype F[A] = forall 'a: (A, 'a) -> [A, 'a]\n//│ type F[A] = forall 'a. (A, 'a) -> [A, 'a]\n\n\nfun f[B] =\n  ((x: B, y) => [x, y]) : F[B]\n//│ fun f: forall 'B. F['B]\n\nfun f = forall 'B:\n  ((x: 'B, y) => [x, y]) : F['B]\n//│ fun f: forall 'B. F['B]\n\n\nmodule A {\n  type F[A] = forall 'a: (A, 'a) -> [A, 'a]\n}\n//│ module A {\n//│   type F[A] = forall 'a. (A, 'a) -> [A, 'a]\n//│ }\n\n:pe // TODO\nfun f[B] =\n  ((x: B, y) => [x, y]) : A.F[B]\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.26: \t  ((x: B, y) => [x, y]) : A.F[B]\n//│ ╙──      \t                          ^^^^^^\n//│ fun f: anything\n\n\nclass Test[B] {\n  fun f(f: F[B]): F[B] = (x, y) => f(x, y)\n}\n//│ class Test[B] {\n//│   constructor()\n//│   fun f: (f: F[B]) -> F[B]\n//│ }\n\nclass Test[B](f: F[B]) {\n  fun g: F[B] = (x, y) => f(x, y)\n}\n//│ class Test[B](f: F[B]) {\n//│   fun g: F[B]\n//│ }\n\nclass Test[B] {\n  discard of ((x: B, y) => [x, y]) : F[B]\n}\n//│ class Test[B] {\n//│   constructor()\n//│ }\n\n\ntype F[A] = (A, 'a) -> [A, 'a]\n//│ type F[A] = (A, 'a) -> [A, 'a]\n\n\nfun f[B] =\n  ((x: B, y) => [x, y]) : F[B]\n//│ fun f: forall 'B. F['B]\n\nfun f = forall 'B:\n  ((x: 'B, y) => [x, y]) : F['B]\n//│ fun f: forall 'B. F['B]\n\n\nclass Test[B] {\n  fun f(f: F[B]): F[B] = (x, y) => f(x, y)\n}\n//│ class Test[B] {\n//│   constructor()\n//│   fun f: (f: F[B]) -> F[B]\n//│ }\n\n\n\n// * Note: NOT polymorphic!\ntype T = 'a -> 'a\n//│ type T = 'a -> 'a\n\n(id : T)(0)\n//│ 0\n//│ res\n//│     = 0\n\n(id : T)(true)\n//│ 0 | true\n//│ res\n//│     = true\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/NuScratch.mls",
    "content": ":NewDefs\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Numbers.mls",
    "content": ":NewDefs\n\n\nlet n = 123\nlet m = n : Int\nlet o = m : Num\nlet p = o : Object\nlet o = n : Num\nlet p = n : Object\nlet p = m : Object\n//│ let n: 123\n//│ let m: Int\n//│ let o: Num\n//│ let p: Object\n//│ let o: Num\n//│ let p: Object\n//│ let p: Object\n//│ n\n//│   = 123\n//│ m\n//│   = 123\n//│ o\n//│   = 123\n//│ p\n//│   = 123\n//│ o\n//│   = 123\n//│ p\n//│   = 123\n//│ p\n//│   = 123\n\n\nlet x = NaN\n//│ let x: Num\n//│ x\n//│   = NaN\n\n// TODO polymorphic Num operations\nx + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.40: \tx + 1\n//│ ║        \t^^^^^\n//│ ╟── reference of type `Num` is not an instance of type `Int`\n//│ ║  l.34: \tlet x = NaN\n//│ ║        \t        ^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.40: \tx + 1\n//│ ╙──      \t^\n//│ Int | error\n//│ res\n//│     = NaN\n\n\ntrue : Bool\n//│ Bool\n//│ res\n//│     = true\n\ntrue : Bool | Str\n//│ Str | false | true\n//│ res\n//│     = true\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Object.mls",
    "content": ":NewDefs\n\n\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nlet a: Object = A()\n//│ let a: Object\n//│ a\n//│   = A {}\n\n\nmodule M\n//│ module M\n\nM: Object\n//│ Object\n//│ res\n//│     = M { class: [class M] }\n\n\n\nfun foo(x) = if x is A then true\n//│ fun foo: A -> true\n\nfun foo(x) = if x is A then true else false\n//│ fun foo: Object -> Bool\n\n\n:e\nfun foo(x: anything) = if x is A then true\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.34: \tfun foo(x: anything) = if x is A then true\n//│ ║        \t                          ^^^^^^^^^^^^^^^^\n//│ ╟── type `anything` is not an instance of type `Object`\n//│ ║  l.34: \tfun foo(x: anything) = if x is A then true\n//│ ║        \t           ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Object`\n//│ ║  l.34: \tfun foo(x: anything) = if x is A then true\n//│ ╙──      \t                          ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.34: \tfun foo(x: anything) = if x is A then true\n//│ ║        \t                          ^^^^^^^^^^^^^^^^\n//│ ╟── type `anything` is not an instance of type `A`\n//│ ║  l.34: \tfun foo(x: anything) = if x is A then true\n//│ ║        \t           ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `A`\n//│ ║  l.34: \tfun foo(x: anything) = if x is A then true\n//│ ║        \t                          ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.34: \tfun foo(x: anything) = if x is A then true\n//│ ╙──      \t                               ^\n//│ fun foo: (x: anything) -> true\n\n:e\nfun foo(x: anything) = if x is A then true else false\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.59: \tfun foo(x: anything) = if x is A then true else false\n//│ ║        \t                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `anything` is not an instance of type `Object`\n//│ ║  l.59: \tfun foo(x: anything) = if x is A then true else false\n//│ ║        \t           ^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Object`\n//│ ║  l.59: \tfun foo(x: anything) = if x is A then true else false\n//│ ╙──      \t                          ^\n//│ fun foo: (x: anything) -> Bool\n\n\nfun foo(x: Object) = if x is A then true else false\n//│ fun foo: (x: Object) -> Bool\n\n\n// TODO make this a rigid type variable!\n// :e\nfun foo = forall 'a; (x: 'a) => if x is A then true else false\n//│ ╔══[PARSE ERROR] Expected `:` after `forall` section\n//│ ║  l.78: \tfun foo = forall 'a; (x: 'a) => if x is A then true else false\n//│ ╙──      \t                   ^\n//│ fun foo: ()\n//│ (x: Object) -> Bool\n//│ res\n//│     = [Function: res]\n\n\n\n:e\nObject\n//│ ╔══[ERROR] Class Object is abstract and cannot be instantiated\n//│ ║  l.90: \tObject\n//│ ╙──      \t^^^^^^\n//│ ╔══[ERROR] Class Object cannot be instantiated as it exposes no constructor\n//│ ║  l.90: \tObject\n//│ ╙──      \t^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol Object\n\n:e\nObject()\n//│ ╔══[ERROR] Class Object is abstract and cannot be instantiated\n//│ ║  l.102: \tObject()\n//│ ╙──       \t^^^^^^\n//│ ╔══[ERROR] Class Object cannot be instantiated as it exposes no constructor\n//│ ║  l.102: \tObject()\n//│ ╙──       \t^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol Object\n\n:e\nnew Object\n//│ ╔══[ERROR] Class Object is abstract and cannot be instantiated\n//│ ║  l.114: \tnew Object\n//│ ╙──       \t    ^^^^^^\n//│ Object\n//│ Code generation encountered an error:\n//│   unresolved symbol Object\n\n\n\n// TODO\nclass B() extends Object\n//│ class B() extends Object\n//│ Code generation encountered an error:\n//│   unresolved parent Object.\n\nclass C() extends A\n//│ class C() extends A\n\nlet o: Object = C()\n//│ let o: Object\n//│ o\n//│   = C {}\n\nfun foo(x) = if x is\n  A then true\n  B then true\n  else false\n//│ fun foo: Object -> Bool\n\nfoo(0)\n//│ Bool\n//│ res\n//│     = false\n\nfoo(o)\n//│ Bool\n//│ res\n//│     = true\n\n\n(0 : Int) : Object\n//│ Object\n//│ res\n//│     = 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/OpLam.mls",
    "content": ":NewDefs\n\n\nx => x is 42\n//│ Object -> Bool\n//│ res\n//│     = [Function: res]\n\n\n:pe\nfun (|>;) foo(a, b) = [a, b]\n//│ ╔══[PARSE ERROR] Unexpected semicolon after symbolic name\n//│ ║  l.11: \tfun (|>;) foo(a, b) = [a, b]\n//│ ╙──      \t       ^\n//│ fun (|>) foo: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n\n42 |>; x => x\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [ 42, undefined ]\n//│ res\n//│     = [Function: res]\n\n\nfun (>>) compose(f, g) = x => g(f(x))\n//│ fun (>>) compose: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c\n\nsucc >> x => x + 2\n//│ Int -> Int\n//│ res\n//│     = [Function (anonymous)]\n\n:e\nx => x + 2 >> succ\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.34: \tx => x + 2 >> succ\n//│ ║        \t     ^^^^^^^^^^^^^\n//│ ╟── operator application of type `Int` is not a function\n//│ ║  l.34: \tx => x + 2 >> succ\n//│ ║        \t     ^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.25: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ║        \t                                ^^^^\n//│ ╟── from reference:\n//│ ║  l.25: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ╙──      \t                                ^\n//│ Int -> (error | anything -> Int)\n//│ res\n//│     = [Function: res]\n\n(x => x + 2) >> succ\n//│ Int -> Int\n//│ res\n//│     = [Function (anonymous)]\n\n:e\nx => x + 2\n  >> succ\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.57: \tx => x + 2\n//│ ║        \t         ^\n//│ ║  l.58: \t  >> succ\n//│ ║        \t^^^^^^^^^^\n//│ ╟── integer literal of type `2` is not a function\n//│ ║  l.57: \tx => x + 2\n//│ ║        \t         ^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.25: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ║        \t                                ^^^^\n//│ ╟── from reference:\n//│ ║  l.25: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ╙──      \t                                ^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.57: \tx => x + 2\n//│ ║        \t     ^^^^^\n//│ ║  l.58: \t  >> succ\n//│ ║        \t^^^^^^^^^\n//│ ╟── function of type `?a -> ?b` is not an instance of type `Int`\n//│ ║  l.25: \tfun (>>) compose(f, g) = x => g(f(x))\n//│ ║        \t                         ^^^^^^^^^^^^\n//│ ╟── but it flows into operator application with expected type `Int`\n//│ ║  l.57: \tx => x + 2\n//│ ║        \t         ^\n//│ ║  l.58: \t  >> succ\n//│ ╙──      \t^^^^^^^^^^\n//│ Int -> (Int | error)\n//│ res\n//│     = [Function: res]\n\n(x => x + 2)\n  >> succ\n//│ Int -> Int\n//│ res\n//│     = [Function (anonymous)]\n\n:pe\n>> succ\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.97: \t>> succ\n//│ ╙──      \t^^\n//│ Int -> Int\n//│ res\n//│     = [Function: succ]\n\n\n:e\nx => x.y => y\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.107: \tx => x.y => y\n//│ ╙──       \t     ^^^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.107: \tx => x.y => y\n//│ ╙──       \t            ^\n//│ anything -> error -> error\n//│ Code generation encountered an error:\n//│   term Sel(Var(x),Var(y)) is not a valid pattern\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/OptionFilter.mls",
    "content": ":NewDefs\n\n\n// * Minimization of code that used to cause a problem:\n\nabstract class Option[T]: (None | ()) {\n  virtual fun filter: Option[T]\n}\nmodule None extends Option[nothing] {\n  fun filter = None\n}\n//│ abstract class Option[T]: None | () {\n//│   fun filter: Option[T]\n//│ }\n//│ module None extends Option {\n//│   fun filter: None\n//│ }\n\n\n// * Original code:\n\nabstract class Option[out T]: (Some[T] | None) {\n  virtual fun filter: (p: T -> Bool) -> Option[T]\n}\nclass Some[out T](val value: T) extends Option[T] {\n  fun filter(p) = if p of value then Some(value) else None\n}\nmodule None extends Option[nothing] {\n  fun filter(_) = None\n}\n//│ abstract class Option[T]: None | Some[T] {\n//│   fun filter: (p: T -> Bool) -> Option[T]\n//│ }\n//│ class Some[T](value: T) extends Option {\n//│   fun filter: (T -> Bool) -> (None | Some[T])\n//│ }\n//│ module None extends Option {\n//│   fun filter: anything -> None\n//│ }\n\n\n\nabstract class Boxful[T] {\n  virtual fun clone(): Boxful[T]\n}\nclass MetalBox[T](value: T) extends Boxful[T] {\n  fun clone(): Boxful[T] = MetalBox(value)\n}\n//│ abstract class Boxful[T] {\n//│   fun clone: () -> Boxful[T]\n//│ }\n//│ class MetalBox[T](value: T) extends Boxful {\n//│   fun clone: () -> Boxful[T]\n//│ }\n\n\nfun makeMetalBox(value: 'A): Boxful['A] = MetalBox(value)\nabstract class Boxful[T] {\n  virtual fun clone(): Boxful[T]\n}\nclass MetalBox[T](value: T) extends Boxful[T] {\n  fun clone(): Boxful[T] = makeMetalBox(value)\n}\n//│ fun makeMetalBox: forall 'T. (value: 'T) -> Boxful['T]\n//│ abstract class Boxful[T] {\n//│   fun clone: () -> Boxful[T]\n//│ }\n//│ class MetalBox[T](value: T) extends Boxful {\n//│   fun clone: () -> Boxful[T]\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/OverrideShorthand.mls",
    "content": ":NewDefs\n\n\n\nclass Pair(lhs: Int, rhs: Int)\n//│ class Pair(lhs: Int, rhs: Int)\n\n\n:p\n:e\nfun f(override Pair(x, y)) = x + y\n//│ |#fun| |f|(|#override| |Pair|(|x|,| |y|)|)| |#=| |x| |+| |y|\n//│ AST: TypingUnit(List(NuFunDef(None,Var(f),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(_$0))))),If(IfOpApp(Var(_$0),Var(is),IfThen(App(Var(Pair),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))),App(Var(+),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))))),Some(App(Sel(Super(),Var(f)),Tup(List((None,Fld(_,Var(_$0)))))))))))))\n//│ Parsed: fun f = (_$0,) => if _$0 is (Pair(x, y,)) then +(x, y,) else (super).f(_$0,);\n//│ ╔══[ERROR] identifier not found: super\n//│ ║  l.11: \tfun f(override Pair(x, y)) = x + y\n//│ ╙──      \t      ^^^^^^^^\n//│ fun f: Object -> (Int | error)\n//│ Syntax error:\n//│   'super' keyword unexpected here\n\n\nmixin Test {\n  fun f(override Pair(x, y)) = x + y\n}\n//│ mixin Test() {\n//│   super: {f: 'a -> 'b}\n//│   fun f: (Object & 'a & ~#Pair | Pair) -> (Int | 'b)\n//│ }\n\n\n:pe\n:e\nfun f(override Pair(x, y), z) = x + y\n//│ ╔══[PARSE ERROR] Unsupported 'override' parameter list shape\n//│ ║  l.34: \tfun f(override Pair(x, y), z) = x + y\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.34: \tfun f(override Pair(x, y), z) = x + y\n//│ ╙──      \t               ^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.34: \tfun f(override Pair(x, y), z) = x + y\n//│ ╙──      \t                                ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.34: \tfun f(override Pair(x, y), z) = x + y\n//│ ╙──      \t                                    ^\n//│ fun f: (error, anything) -> Int\n//│ Code generation encountered an error:\n//│   term App(Var(Pair),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))) is not a valid pattern\n\n\n// TODO\n// :pe\n// fun f(override Pair(x, y)): Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ParamImplementing.mls",
    "content": ":NewDefs\n\n\ntrait T { fun x: Int }\nmixin M(val x: Bool)\n//│ trait T {\n//│   fun x: Int\n//│ }\n//│ mixin M(x: Bool)\n\n:e\nmodule C extends T, M(false)\nC.x\n//│ ╔══[ERROR] Type mismatch in reference:\n//│ ║  l.12: \tmodule C extends T, M(false)\n//│ ║        \t                      ^^^^^\n//│ ╟── reference of type `false` is not an instance of `Int`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.4: \ttrait T { fun x: Int }\n//│ ║       \t                 ^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.4: \ttrait T { fun x: Int }\n//│ ╙──     \t              ^^^^^^\n//│ module C extends T\n//│ false\n//│ res\n//│     = false\n\n\ntrait T { fun x: Int }\nmixin M(val x: Num)\n//│ trait T {\n//│   fun x: Int\n//│ }\n//│ mixin M(x: Num)\n\nmodule C extends T, M(0)\nC.x\n//│ module C extends T\n//│ 0\n//│ res\n//│     = 0\n\n\ntrait T { fun x: Int }\nmixin M(x: Bool)\n//│ trait T {\n//│   fun x: Int\n//│ }\n//│ mixin M(x: Bool)\n\n:e\nmodule C extends T, M(false)\nC.x\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C`\n//│ ║  l.53: \tmodule C extends T, M(false)\n//│ ║        \t       ^\n//│ ╟── Declared here:\n//│ ║  l.45: \ttrait T { fun x: Int }\n//│ ╙──      \t          ^^^^^^^^^^\n//│ module C extends T {\n//│   fun x: Int\n//│ }\n//│ Int\n//│ res\n//│     = undefined\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ParamOverride.mls",
    "content": ":NewDefs\n\n\nclass Base0(n: Num)\n//│ class Base0(n: Num)\n\n// TODO\nclass Derived0(n: Int) extends Base\n//│ ╔══[ERROR] Could not find definition `Base`\n//│ ║  l.8: \tclass Derived0(n: Int) extends Base\n//│ ╙──     \t                               ^^^^\n//│ class Derived0(n: Int)\n//│ Code generation encountered an error:\n//│   unresolved parent Base.\n\n\nmixin Base1(val n: Num) {\n  fun original = n\n}\n//│ mixin Base1(n: Num) {\n//│   fun original: Num\n//│ }\n\n:e\nmixin DerivedBad(n: Int) extends Base\n//│ ╔══[ERROR] mixin definitions cannot yet extend parents\n//│ ║  l.25: \tmixin DerivedBad(n: Int) extends Base\n//│ ╙──      \t                                 ^^^^\n//│ mixin DerivedBad(n: Int)\n\nmixin Derived1(val n: Int) {\n  fun foo = [n, this.n, super.n]\n}\n//│ mixin Derived1(n: Int) {\n//│   super: {n: 'n}\n//│   this: {n: 'n0}\n//│   fun foo: [Int, 'n0, 'n]\n//│ }\n\n\nclass Test0() extends Base1(1/2), Derived1(1)\n//│ class Test0() {\n//│   fun foo: [Int, 1, Num]\n//│   fun original: Num\n//│ }\n\nlet t = Test0()\n//│ let t: Test0\n//│ t\n//│   = Test0 {}\n\nt.n\n//│ 1\n//│ res\n//│     = 1\n\nt.original\n//│ Num\n//│ res\n//│     = 0.5\n\nt.foo\n//│ [Int, 1, Num]\n//│ res\n//│     = [ 1, 1, 0.5 ]\n\n\nmodule Test1 extends Base1(1/2), Derived1(1) {\n  fun n = this.n\n}\n//│ module Test1 {\n//│   fun foo: [Int, 1, Num]\n//│   fun n: 1\n//│   fun original: Num\n//│ }\n\n:re\nTest1.n\n//│ 1\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\nclass Test2(val n: Str) extends Base1(1/2), Derived1(1) {\n  fun bar = [this.foo, n, this.n, this.original]\n}\n//│ class Test2(n: Str) {\n//│   fun bar: [[Int, Str, Num], Str, Str, Num]\n//│   fun foo: [Int, Str, Num]\n//│   fun original: Num\n//│ }\n\nTest2(\"test\").bar\n//│ [[Int, Str, Num], Str, Str, Num]\n//│ res\n//│     = [ [ 1, 'test', 0.5 ], 'test', 'test', 0.5 ]\n\n\nclass Test3(val n: Str) extends Base1(1/2), Derived1(length(n)) {\n  fun foo = [super.foo, n, this.original]\n}\n//│ class Test3(n: Str) {\n//│   fun foo: [[Int, Str, Num], Str, Num]\n//│   fun original: Num\n//│ }\n\nTest3(\"test\").foo\n//│ [[Int, Str, Num], Str, Num]\n//│ res\n//│     = [ [ 4, 'test', 0.5 ], 'test', 0.5 ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ParamOverriding.mls",
    "content": ":NewDefs\n\n\nmixin Over {\n  fun p = \"hi\"\n}\n//│ mixin Over() {\n//│   fun p: \"hi\"\n//│ }\n\n\nclass Base1(val p: Int) extends Over {\n  fun test = [p, this.p]\n  fun test2 = super.p\n}\n//│ class Base1(p: Int) {\n//│   fun p: \"hi\"\n//│   fun test: [Int, Int]\n//│   fun test2: Int\n//│ }\n\n\nBase1(123).test\n//│ [Int, Int]\n//│ res\n//│     = [ 123, 123 ]\n\nBase1(123).test2\n//│ Int\n//│ res\n//│     = 'hi'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ParamPassing.mls",
    "content": ":NewDefs\n\n\nclass Foo(x: Int)\n//│ class Foo(x: Int)\n\nclass Bar(z: Int, y: Int) extends Foo(z + y)\n//│ class Bar(z: Int, y: Int) extends Foo\n\nclass Bar(x: Int, y: Int) extends Foo(x + y)\n//│ class Bar(x: Int, y: Int) extends Foo\n\n\nclass Foo(val x: Int)\n//│ class Foo(x: Int)\n\nmodule Bar extends Foo(11)\nBar.x\n//│ module Bar extends Foo\n//│ 11\n//│ res\n//│     = 11\n\n:e // FIXME\nmodule Bar extends Foo(11) { fun get = this.x }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.25: \tmodule Bar extends Foo(11) { fun get = this.x }\n//│ ╙──      \t                                           ^^\n//│ module Bar extends Foo {\n//│   fun get: error\n//│ }\n\n\nmixin AA(a: Int) {\n}\n//│ mixin AA(a: Int)\n\nmixin BB {}\n//│ mixin BB()\n\n\nclass C(x: Int) extends BB\n//│ class C(x: Int)\n\nclass D(x: Int) extends AA(x)\n//│ class D(x: Int)\n\nclass E(x: Int) extends BB, AA(x)\n//│ class E(x: Int)\n\n\nclass Foo(x: Int)\n//│ class Foo(x: Int)\n\n:e\nFoo(1).x\n//│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field\n//│ ║  l.56: \tFoo(1).x\n//│ ║        \t      ^^\n//│ ╟── Either make the parameter a `val` or access it through destructuring\n//│ ║  l.52: \tclass Foo(x: Int)\n//│ ╙──      \t          ^\n//│ Int | error\n//│ res\n//│     = undefined\n\n:e\nFoo(1).#x\n//│ ╔══[ERROR] identifier not found: .#\n//│ ║  l.68: \tFoo(1).#x\n//│ ╙──      \t      ^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.68: \tFoo(1).#x\n//│ ╙──      \t        ^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol .#\n\nif Foo(1) is Foo(x) then x\n//│ Int\n//│ res\n//│     = 1\n\n\nclass Foo(val x: Int)\n//│ class Foo(x: Int)\n\nFoo(1).x\n//│ Int\n//│ res\n//│     = 1\n\nif Foo(1) is Foo(x) then x\n//│ Int\n//│ res\n//│     = 1\n\n\n:e\nclass Bar(x: Int) extends Foo(x)\n//│ ╔══[ERROR] Inherited parameter named 'x' is not virtual and cannot be overridden\n//│ ║  l.100: \tclass Bar(x: Int) extends Foo(x)\n//│ ║         \t          ^\n//│ ╟── Originally declared here:\n//│ ║  l.85: \tclass Foo(val x: Int)\n//│ ╙──      \t              ^\n//│ class Bar(x: Int) extends Foo\n\n:e\nBar(11).x\n//│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field\n//│ ║  l.110: \tBar(11).x\n//│ ║         \t       ^^\n//│ ╟── Either make the parameter a `val` or access it through destructuring\n//│ ║  l.100: \tclass Bar(x: Int) extends Foo(x)\n//│ ╙──       \t          ^\n//│ Int | error\n//│ res\n//│     = 11\n\n\n:e\nclass Bar(val x: Int) extends Foo(x + 1)\n//│ ╔══[ERROR] Inherited parameter named 'x' is not virtual and cannot be overridden\n//│ ║  l.123: \tclass Bar(val x: Int) extends Foo(x + 1)\n//│ ║         \t              ^\n//│ ╟── Originally declared here:\n//│ ║  l.85: \tclass Foo(val x: Int)\n//│ ╙──      \t              ^\n//│ class Bar(x: Int) extends Foo\n\nBar(11).x\n//│ Int\n//│ res\n//│     = 11\n\n:e\nclass Bar extends Foo(1) { val x: 2 }\n//│ ╔══[ERROR] Inherited parameter named 'x' is not virtual and cannot be overridden\n//│ ║  l.138: \tclass Bar extends Foo(1) { val x: 2 }\n//│ ║         \t                           ^^^^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.85: \tclass Foo(val x: Int)\n//│ ╙──      \t              ^\n//│ class Bar extends Foo {\n//│   constructor()\n//│   val x: 2\n//│ }\n\n:e\nmodule Bar extends Foo(1) { fun x = 2 }\n//│ ╔══[ERROR] Inherited parameter named 'x' is not virtual and cannot be overridden\n//│ ║  l.151: \tmodule Bar extends Foo(1) { fun x = 2 }\n//│ ║         \t                                ^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.85: \tclass Foo(val x: Int)\n//│ ╙──      \t              ^\n//│ module Bar extends Foo {\n//│   fun x: 2\n//│ }\n\n\nclass A(val x: Int)\n//│ class A(x: Int)\n\nmodule B extends A(42)\n//│ module B extends A\n\nB.x\n//│ 42\n//│ res\n//│     = 42\n\n\nclass A(x: Int)\n//│ class A(x: Int)\n\nmodule B extends A(42)\n//│ module B extends A\n\n:e\nB.x\n//│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field\n//│ ║  l.182: \tB.x\n//│ ║         \t ^^\n//│ ╟── Either make the parameter a `val` or access it through destructuring\n//│ ║  l.175: \tclass A(x: Int)\n//│ ╙──       \t        ^\n//│ Int | error\n//│ res\n//│     = undefined\n\n\n\nabstract class Foo[A](val x: A) { fun y = x; fun i: A -> A }\n//│ abstract class Foo[A](x: A) {\n//│   fun i: A -> A\n//│   fun y: A\n//│ }\n\nabstract class Bar extends Foo(0)\n//│ abstract class Bar extends Foo {\n//│   fun i: 'A -> 'A\n//│   fun y: 'A\n//│ }\n//│ where\n//│   'A :> 0\n\nmodule Baz extends Foo(0) { fun i = id }\n[Baz.x, Baz.i]\n//│ module Baz extends Foo {\n//│   fun i: forall 'a. 'a -> 'a\n//│   fun y: 'A\n//│ }\n//│ [0, forall 'a. 'a -> 'a]\n//│ where\n//│   'A :> 0\n//│ res\n//│     = [ 0, [Function: id] ]\n\n:e\nmodule Bazz extends Foo(0) {\n  val x: 2\n}\n//│ ╔══[ERROR] Inherited parameter named 'x' is not virtual and cannot be overridden\n//│ ║  l.223: \t  val x: 2\n//│ ║         \t  ^^^^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.195: \tabstract class Foo[A](val x: A) { fun y = x; fun i: A -> A }\n//│ ╙──       \t                          ^\n//│ ╔══[ERROR] Member `i` is declared (or its declaration is inherited) but is not implemented in `Bazz`\n//│ ║  l.222: \tmodule Bazz extends Foo(0) {\n//│ ║         \t       ^^^^\n//│ ╟── Declared here:\n//│ ║  l.195: \tabstract class Foo[A](val x: A) { fun y = x; fun i: A -> A }\n//│ ╙──       \t                                             ^^^^^^^^^^^^^\n//│ module Bazz extends Foo {\n//│   fun i: 'A -> 'A\n//│   val x: 2\n//│   fun y: 'A\n//│ }\n//│ where\n//│   'A :> 0\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Parens.mls",
    "content": ":NewDefs\n\n\n()\n//│ ()\n//│ res\n//│     = undefined\n\n:pe\n(,)\n//│ ╔══[PARSE ERROR] Unexpected comma in expression position\n//│ ║  l.10: \t(,)\n//│ ╙──      \t ^\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.10: \t(,)\n//│ ╙──      \t  ^\n//│ ()\n//│ res\n//│     = undefined\n\n(1)\n//│ 1\n//│ res\n//│     = 1\n\n(1,)\n//│ 1\n//│ res\n//│     = 1\n\n(1, 2)\n//│ 2\n//│ res\n//│     = 2\n\n(1, 2,)\n//│ 2\n//│ res\n//│     = 2\n\n\nval x: ()\n//│ val x: ()\n//│ x\n//│   = <missing implementation>\n\n:pe\nval x: (,)\n//│ ╔══[PARSE ERROR] Unexpected comma in expression position\n//│ ║  l.48: \tval x: (,)\n//│ ╙──      \t        ^\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.48: \tval x: (,)\n//│ ╙──      \t         ^\n//│ val x: ()\n//│ x\n//│   = <missing implementation>\n\nval x: (1)\n//│ val x: 1\n//│ x\n//│   = <missing implementation>\n\nval x: (1,)\n//│ val x: 1\n//│ x\n//│   = <missing implementation>\n\n:e\nval x: (1, 2)\n//│ ╔══[ERROR] type identifier not found: ,\n//│ ║  l.70: \tval x: (1, 2)\n//│ ╙──      \t       ^^^^^^\n//│ val x: error\n//│ x\n//│   = <missing implementation>\n\n:e\nval x: (1, 2,)\n//│ ╔══[ERROR] type identifier not found: ,\n//│ ║  l.79: \tval x: (1, 2,)\n//│ ╙──      \t       ^^^^^^^\n//│ val x: error\n//│ x\n//│   = <missing implementation>\n"
  },
  {
    "path": "shared/src/test/diff/nu/PartialApp.mls",
    "content": ":NewDefs\n\n// TODO support partial application syntax\n:AllowTypeErrors\n\n\nfun foo(x, y) = x + y\n//│ fun foo: (Int, Int) -> Int\n\n\nfoo(2, _)\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.11: \tfoo(2, _)\n//│ ╙──      \t       ^\n//│ Int\n\n// * ie\ntmp => foo(2, tmp)\n//│ Int -> Int\n\n\n_.foo(1)\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.22: \t_.foo(1)\n//│ ╙──      \t^\n//│ error\n\n// * ie\nx => x.foo(1)\n//│ forall 'a. {foo: 1 -> 'a} -> 'a\n\n\n_ + _\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.33: \t_ + _\n//│ ╙──      \t^\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.33: \t_ + _\n//│ ╙──      \t    ^\n//│ Int\n\n// * ie\n(x, y) => x + y\n//│ (Int, Int) -> Int\n\n\n_2 + _1\n//│ ╔══[ERROR] identifier not found: _2\n//│ ║  l.47: \t_2 + _1\n//│ ╙──      \t^^\n//│ ╔══[ERROR] identifier not found: _1\n//│ ║  l.47: \t_2 + _1\n//│ ╙──      \t     ^^\n//│ Int\n\n// * ie\n(x, y) => y + x\n//│ (Int, Int) -> Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/PolymorphicVariants_Alt.mls",
    "content": ":NewDefs\n:NoJS\n\n\n// * Adapted example from Code reuse through polymorphic variants (FOSE 2000)\n// * This time with an ML-style List data type encoding.\n\n\n// TODO improvements/things to investigate:\n//  - constraining loop with unannotated `list_assoc` ascription\n//  - still a number of quite ugly types\n\n\nclass List<out A> {\n  fun match: forall 'res: (ifNil: () => 'res, ifCons: (A, List[A]) => 'res) => 'res\n  fun match = error\n}\nval Nil: () => List<'a>\nval Cons: (head: 'a, tail: List<'a>) => List<'a>\n//│ class List[A] {\n//│   constructor()\n//│   fun match: forall 'res. (ifNil: () -> 'res, ifCons: (A, List[A]) -> 'res) -> 'res\n//│ }\n//│ val Nil: () -> List[nothing]\n//│ val Cons: forall 'a. (head: 'a, tail: List['a]) -> List['a]\n\nmodule NotFound\nclass Success<out A>(result: A)\n//│ module NotFound\n//│ class Success[A](result: A)\n\nfun eq(l: Str, r: Str): Bool\n//│ fun eq: (l: Str, r: Str) -> Bool\n\n// * Annotation currently needed to avoid later ascription loop (due to excessive TV refreshing?)\n// fun list_assoc(s, l) =\nfun list_assoc(s, l: List<'a>) =\n  l.match(\n    ifNil: () => NotFound,\n    ifCons: (h, t) =>\n      if eq(s, h.0) then Success(h.1)\n      else list_assoc(s, t)\n  )\n//│ fun list_assoc: forall 'A. (Str, l: List[{0: Str, 1: 'A}]) -> (NotFound | Success['A])\n\nlist_assoc : (Str, List<{ 0: Str, 1: 'b }>) => (NotFound | Success['b])\n//│ (Str, List[{0: Str, 1: 'b}]) -> (NotFound | Success['b])\n\nfun list_assoc(s: Str, l: List<{ 0: Str, 1: 'b }>): NotFound | Success['b]\n//│ fun list_assoc: forall 'b. (s: Str, l: List[{0: Str, 1: 'b}]) -> (NotFound | Success['b])\n\nclass Var(s: Str)\n//│ class Var(s: Str)\n\nmixin EvalVar {\n  fun eval(sub, v) =\n    if v is Var(s) then\n      if list_assoc(s, sub) is\n        NotFound then v\n        Success(r) then r\n}\n//│ mixin EvalVar() {\n//│   fun eval: (List[{0: Str, 1: 'a}], Var) -> (Var | 'a)\n//│ }\n\nclass Abs<out A>(x: Str, t: A)\nclass App<out A>(s: A, t: A)\n//│ class Abs[A](x: Str, t: A)\n//│ class App[A](s: A, t: A)\n\nfun incr(x: {a: Int}): unit\n//│ fun incr: (x: {a: Int}) -> unit\n\nfun gensym(): Str\n//│ fun gensym: () -> Str\n\nfun Int_to_string(x: Int): Str\n//│ fun Int_to_string: (x: Int) -> Str\n\nmixin EvalLambda {\n  fun eval(sub, v) =\n    if v is\n      App(t1, t2) then\n        let l1 = this.eval(sub, t1)\n        let l2 = this.eval(sub, t2)\n        if t1 is\n          Abs(x, t) then this.eval(Cons([x, l2], Nil()), t)\n        else\n          App(l1, l2)\n      Abs(x, t) then\n        let s = gensym()\n        Abs(s, this.eval(Cons([x, Var(s)], sub), t))\n    else\n      super.eval(sub, v)\n}\n//│ mixin EvalLambda() {\n//│   super: {eval: ('b, 'c) -> 'd}\n//│   this: {\n//│     eval: ('b, 'e) -> 'A & (List[[Str, 'A]], 'f) -> 'd & (List[[Str, Var] | 'a], 'g) -> 'A0\n//│   }\n//│   fun eval: (List['a] & 'b, Abs['g] | App['e & (Abs['f] | Object & ~#Abs)] | Object & 'c & ~#Abs & ~#App) -> (Abs['A0] | App['A] | 'd)\n//│ }\n\nmodule Test1 extends EvalVar, EvalLambda\n//│ module Test1 {\n//│   fun eval: (List[{0: Str, 1: 'a}], 'b) -> 'a\n//│ }\n//│ where\n//│   'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Var\n//│   'a :> Abs['a] | App['a] | Var\n\nTest1.eval(Nil(), Var(\"a\"))\n//│ 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n\nTest1.eval(Nil(), Abs(\"b\", Var(\"a\")))\n//│ 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n\nTest1.eval(Cons([\"c\", Var(\"d\")], Nil()), App(Abs(\"b\", Var(\"b\")), Var(\"c\")))\n//│ 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n\nTest1.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil()), App(Abs(\"b\", Var(\"b\")), Var(\"c\")))\n//│ Abs['a] | 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Var\n\nclass Numb(n: Int)\nclass Add<out A>(l: A, r: A)\nclass Mul<out A>(l: A, r: A)\n//│ class Numb(n: Int)\n//│ class Add[A](l: A, r: A)\n//│ class Mul[A](l: A, r: A)\n\nfun map_expr(f, v) =\n  if v is\n    Var then v\n    Numb then v\n    Add(l, r) then Add(f(l), f(r))\n    Mul(l, r) then Mul(f(l), f(r))\n//│ fun map_expr: forall 'a 'A 'b 'A0. ('a -> 'A & 'b -> 'A0, Add['b] | Mul['a] | Numb | Var) -> (Add['A0] | Mul['A] | Numb | Var)\n\nmixin EvalExpr {\n  fun eval(sub, v) =\n    let eta(e) = this.eval(sub, e)\n    let vv = map_expr(eta, v)\n    if vv is\n      Var then super.eval(sub, vv)\n      Add(Numb(l), Numb(r)) then Numb(l + r)\n      Mul(Numb(l), Numb(r)) then Numb(l * r)\n    else v\n}\n//│ mixin EvalExpr() {\n//│   super: {eval: ('a, Var) -> 'b}\n//│   this: {eval: ('a, 'c) -> Object}\n//│   fun eval: ('a, 'b & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | 'b)\n//│ }\n\nmodule Test2 extends EvalVar, EvalExpr\n//│ module Test2 {\n//│   fun eval: forall 'a. (List[{0: Str, 1: Object & 'b}], 'a & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | Var | 'b | 'c | 'a)\n//│ }\n//│ where\n//│   'c <: Add['c] | Mul['c] | Numb | Var\n\nTest2.eval(Nil(), Var(\"a\"))\n//│ Numb | Var\n\nTest2.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil()), Var(\"a\"))\n//│ Abs[Var] | Numb | Var\n\nTest2.eval(Cons([\"a\", Numb(1)], Nil()), Var(\"a\"))\n//│ Numb | Var\n\nTest2.eval(Cons([\"a\", Abs(\"d\", Var(\"d\"))], Nil()), Add(Numb(1), Var(\"a\")))\n//│ Abs[Var] | Add[Numb | Var] | Numb | Var\n\nmodule Test3 extends EvalVar, EvalExpr, EvalLambda\n//│ module Test3 {\n//│   fun eval: (List[{0: Str, 1: 'a}], 'b) -> (Abs['c] | App['c] | 'c)\n//│ }\n//│ where\n//│   'a :> 'c\n//│      <: Object\n//│   'c :> 'a | 'd\n//│   'd <: Add['b] | Mul['b] | Numb | Var\n//│   'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Object & 'd & ~#Abs & ~#App\n\nTest3.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil()), Abs(\"a\", Var(\"a\")))\n//│ Abs['a] | 'a\n//│   where\n//│     'a :> Abs['a] | App['a] | Numb | Var\n\nTest3.eval(Cons([\"c\", Abs(\"d\", Var(\"d\"))], Nil()), App(Abs(\"a\", Var(\"a\")), Add(Numb(1), Var(\"c\"))))\n//│ Abs['a] | 'a\n//│   where\n//│     'a :> Abs['a] | Add[Numb | Var] | App['a] | Numb | Var\n\nmodule Test3 extends EvalVar, EvalLambda, EvalExpr\n//│ module Test3 {\n//│   fun eval: (List[{0: Str, 1: 'a}], 'a & (Add['b] | Mul['b] | Numb | Var)) -> (Numb | 'c | 'a | 'b)\n//│ }\n//│ where\n//│   'a :> 'c | 'b\n//│      <: Object\n//│   'b <: Add['b] | Mul['b] | Numb | Var\n//│   'c :> Abs['c | 'a] | App['c | 'a] | 'a\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/PostHocMixinSignature.mls",
    "content": ":NewDefs\n\n\nmixin Foo {\n  fun foo(x) = if x.a then x else foo(x.b)\n}\n//│ mixin Foo() {\n//│   fun foo: 'a -> 'a\n//│ }\n//│ where\n//│   'a <: {a: Bool, b: 'a}\n\n\nmodule ValA {\n  val a = false\n  val b = ValB\n}\nmodule ValB {\n  val a = true\n  fun b = ValA\n}\n//│ module ValA {\n//│   val a: false\n//│   val b: ValB\n//│ }\n//│ module ValB {\n//│   val a: true\n//│   fun b: ValA\n//│ }\n\n\nmodule Test extends Foo\n//│ module Test {\n//│   fun foo: forall 'a. 'a -> 'a\n//│ }\n//│ where\n//│   'a <: {a: Bool, b: 'a}\n\n[Test.foo(ValA), Test.foo(ValB)]\n//│ [ValA | ValB, ValA | ValB]\n//│ res\n//│     = [ ValB { class: [class ValB] }, ValB { class: [class ValB] } ]\n\n\ntype V = {a: Bool, b: V}\n//│ type V = {a: Bool, b: V}\n\nmodule Test extends Foo {\n  fun foo: V -> anything\n}\n//│ module Test {\n//│   fun foo: V -> anything\n//│ }\n\n[Test.foo(ValA), Test.foo(ValB)]\n//│ [anything, anything]\n//│ res\n//│     = [ ValB { class: [class ValB] }, ValB { class: [class ValB] } ]\n\n\nmodule Test extends Foo {\n  fun foo: V -> V\n}\n//│ module Test {\n//│   fun foo: V -> V\n//│ }\n\n[Test.foo(ValA), Test.foo(ValB)]\n//│ [V, V]\n//│ res\n//│     = [ ValB { class: [class ValB] }, ValB { class: [class ValB] } ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/PrivateMemberOverriding.mls",
    "content": ":NewDefs\n\n\nclass Foo(x: Int)\n//│ class Foo(x: Int)\n\nclass Bar() extends Foo(123) { fun x = true }\n//│ class Bar() extends Foo {\n//│   fun x: true\n//│ }\n\nBar().x\n//│ true\n//│ res\n//│     = true\n\nif Bar() is Foo(a) then a\n//│ Int\n//│ res\n//│     = 123\n\n\nclass Bar(val x: Bool) extends Foo(123)\n//│ class Bar(x: Bool) extends Foo\n\nBar(true).x\n//│ Bool\n//│ res\n//│     = true\n\nif Bar(true) is Foo(a) then a\n//│ Int\n//│ res\n//│     = 123\n\n\nclass Bar(x: Bool) extends Foo(123)\n//│ class Bar(x: Bool) extends Foo\n\n:e // * Expected\nBar(true).x\n//│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field\n//│ ║  l.41: \tBar(true).x\n//│ ║        \t         ^^\n//│ ╟── Either make the parameter a `val` or access it through destructuring\n//│ ║  l.37: \tclass Bar(x: Bool) extends Foo(123)\n//│ ╙──      \t          ^\n//│ error | false | true\n//│ res\n//│     = undefined\n\nif Bar(true) is Foo(a) then a\n//│ Int\n//│ res\n//│     = 123\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/RawUnionTraitSignatures.mls",
    "content": ":NewDefs\n\n\n\ntrait Foo[A] { fun x: A }\n//│ trait Foo[A] {\n//│   fun x: A\n//│ }\n\n\ntrait Base1: Foo\n//│ trait Base1: #Foo\n\n(b: Base1) => b.x\n//│ (b: Base1) -> ??A\n//│ res\n//│     = [Function: res]\n\n(b: Base1) => b : Foo\n//│ (b: Base1) -> #Foo\n//│ res\n//│     = [Function: res]\n\n:e\n(b: Base1) => b : Foo['X]\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.25: \t(b: Base1) => b : Foo['X]\n//│ ║        \t              ^\n//│ ╟── type variable `A` leaks out of its scope\n//│ ║  l.25: \t(b: Base1) => b : Foo['X]\n//│ ║        \t                      ^^\n//│ ╟── back into type variable `A`\n//│ ║  l.5: \ttrait Foo[A] { fun x: A }\n//│ ╙──     \t          ^\n//│ forall 'X. (b: Base1) -> Foo['X]\n//│   where\n//│     'X :> ??A\n//│        <: ??A0\n//│ res\n//│     = [Function: res]\n\n:e\n1 : Foo[Int]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.43: \t1 : Foo[Int]\n//│ ║        \t^\n//│ ╟── integer literal of type `1` is not an instance of type `Foo`\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.43: \t1 : Foo[Int]\n//│ ╙──      \t    ^^^^^^^^\n//│ Foo[Int]\n//│ res\n//│     = 1\n\n\ntrait Base1: Foo { val x: Int }\n//│ trait Base1: #Foo {\n//│   val x: Int\n//│ }\n\n(b: Base1) => b.x\n//│ (b: Base1) -> (Int & ??A)\n//│ res\n//│     = [Function: res]\n\n\ntrait Base1: Foo[1 | 2] { val x: 0 | 1 }\n//│ trait Base1: Foo[1 | 2] {\n//│   val x: 0 | 1\n//│ }\n\n(b: Base1) => b.x\n//│ (b: Base1) -> 1\n//│ res\n//│     = [Function: res]\n\n\ntrait Base2: Foo['FigureItOut]\n//│ trait Base2: Foo[in ??FigureItOut out ??FigureItOut0]\n\n(b: Base2) => b.x\n//│ (b: Base2) -> ??FigureItOut\n//│ res\n//│     = [Function: res]\n\n(b: Base1) => b : Foo\n//│ (b: Base1) -> #Foo\n//│ res\n//│     = [Function: res]\n\n// :e\n(b: Base2) => b : Foo['X]\n//│ forall 'X. (b: Base2) -> Foo['X]\n//│   where\n//│     'X :> ??FigureItOut\n//│        <: ??FigureItOut0\n//│ res\n//│     = [Function: res]\n\n\n:e\nclass Impl extends Base2\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.102: \tclass Impl extends Base2\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#Impl` is not an instance of type `Foo`\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.78: \ttrait Base2: Foo['FigureItOut]\n//│ ╙──      \t             ^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type `#Impl` does not contain member `Foo#A`\n//│ ║  l.5: \ttrait Foo[A] { fun x: A }\n//│ ╙──     \t          ^\n//│ class Impl extends Base2 {\n//│   constructor()\n//│ }\n\n:e\n(x: Impl) => x : Base2\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.118: \t(x: Impl) => x : Base2\n//│ ║         \t             ^\n//│ ╟── type `Impl` is not an instance of type `Foo`\n//│ ║  l.118: \t(x: Impl) => x : Base2\n//│ ║         \t    ^^^^\n//│ ╟── but it flows into reference with expected type `#Foo`\n//│ ║  l.118: \t(x: Impl) => x : Base2\n//│ ║         \t             ^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.78: \ttrait Base2: Foo['FigureItOut]\n//│ ║        \t             ^^^^^^^^^^^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.118: \t(x: Impl) => x : Base2\n//│ ╙──       \t                 ^^^^^\n//│ (x: Impl) -> Base2\n//│ res\n//│     = [Function: res]\n\n:e\nclass Impl() extends Base2, Foo\n//│ ╔══[ERROR] Type error in type declaration\n//│ ║  l.139: \tclass Impl() extends Base2, Foo\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.78: \ttrait Base2: Foo['FigureItOut]\n//│ ╙──      \t                 ^^^^^^^^^^^^\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `Impl`\n//│ ║  l.139: \tclass Impl() extends Base2, Foo\n//│ ║         \t      ^^^^\n//│ ╟── Declared here:\n//│ ║  l.5: \ttrait Foo[A] { fun x: A }\n//│ ╙──     \t               ^^^^^^^^\n//│ class Impl() extends Base2, Foo {\n//│   fun x: 'A\n//│ }\n\n:e\nclass Impl() extends Base2, Foo {\n  fun x = 1\n}\n//│ ╔══[ERROR] Type error in type declaration\n//│ ║  l.157: \tclass Impl() extends Base2, Foo {\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.158: \t  fun x = 1\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.159: \t}\n//│ ║         \t^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.78: \ttrait Base2: Foo['FigureItOut]\n//│ ╙──      \t                 ^^^^^^^^^^^^\n//│ class Impl() extends Base2, Foo {\n//│   fun x: 1\n//│ }\n\nImpl().x\n//│ 1\n//│ res\n//│     = 1\n\n:e\nImpl() : Base2\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.180: \tImpl() : Base2\n//│ ║         \t^^^^^^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.158: \t  fun x = 1\n//│ ╙──       \t          ^\n//│ Base2\n//│ res\n//│     = Impl {}\n\n:e\n(Impl() : Base2).x\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.192: \t(Impl() : Base2).x\n//│ ║         \t ^^^^^^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.158: \t  fun x = 1\n//│ ╙──       \t          ^\n//│ ??FigureItOut\n//│ res\n//│     = 1\n\n:e\nclass Impl2() extends Base2, Foo[Int] {\n  fun x = 1\n}\n//│ ╔══[ERROR] Type error in type declaration\n//│ ║  l.204: \tclass Impl2() extends Base2, Foo[Int] {\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.205: \t  fun x = 1\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.206: \t}\n//│ ║         \t^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.204: \tclass Impl2() extends Base2, Foo[Int] {\n//│ ╙──       \t                                 ^^^\n//│ ╔══[ERROR] Type error in type declaration\n//│ ║  l.204: \tclass Impl2() extends Base2, Foo[Int] {\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.205: \t  fun x = 1\n//│ ║         \t^^^^^^^^^^^\n//│ ║  l.206: \t}\n//│ ║         \t^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.78: \ttrait Base2: Foo['FigureItOut]\n//│ ║        \t                 ^^^^^^^^^^^^\n//│ ╟── into type `Int`\n//│ ║  l.204: \tclass Impl2() extends Base2, Foo[Int] {\n//│ ╙──       \t                                 ^^^\n//│ class Impl2() extends Base2, Foo {\n//│   fun x: 1\n//│ }\n\n:e\n(Impl2() : Base2).x\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.235: \t(Impl2() : Base2).x\n//│ ║         \t ^^^^^^^\n//│ ╟── type variable `'FigureItOut` leaks out of its scope\n//│ ║  l.204: \tclass Impl2() extends Base2, Foo[Int] {\n//│ ╙──       \t                                 ^^^\n//│ ??FigureItOut\n//│ res\n//│     = 1\n\n\n\ntrait Test1[A] { fun x: A }\ntrait Test2[A]: Test1[[A, A]]\n//│ trait Test1[A] {\n//│   fun x: A\n//│ }\n//│ trait Test2[A]: Test1[[A, A]]\n\n(t: Test2[Int]) => t.x\n//│ (t: Test2[Int]) -> [Int, Int]\n//│ res\n//│     = [Function: res]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Ref.mls",
    "content": ":NewDefs\n\n\n:DontDistributeForalls\n\n\n\n// * We should be able to define our own reference type which behaves the same as plain mutable variables, as in:\n\nmut let r = 42\nset r = \"abc\"\nr\n//│ mut let r: \"abc\" | 42\n//│ \"abc\" | 42\n//│ r\n//│   = 42\n//│ res\n//│     = undefined\n//│ res\n//│     = 'abc'\n\n:e\nr + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.23: \tr + 1\n//│ ║        \t^^^^^\n//│ ╟── string literal of type `\"abc\"` is not an instance of type `Int`\n//│ ║  l.11: \tset r = \"abc\"\n//│ ║        \t        ^^^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.23: \tr + 1\n//│ ╙──      \t^\n//│ Int | error\n//│ res\n//│     = 'abc1'\n\n\n// * The definition:\n\nclass Ref[A](init: A) { mut val value: A = init }\n//│ class Ref[A](init: A) {\n//│   mut val value: A\n//│ }\n\nlet r = Ref(42)\n//│ let r: Ref['A]\n//│   where\n//│     'A :> 42\n//│ r\n//│   = Ref {}\n\nset r.value = \"abc\"\n//│ ()\n//│ res\n//│     = undefined\n\nr.value\n//│ \"abc\" | 42\n//│ res\n//│     = 'abc'\n\n:e\nr.value + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.63: \tr.value + 1\n//│ ║        \t^^^^^^^^^^^\n//│ ╟── string literal of type `\"abc\"` is not an instance of type `Int`\n//│ ║  l.52: \tset r.value = \"abc\"\n//│ ║        \t              ^^^^^\n//│ ╟── but it flows into field selection with expected type `Int`\n//│ ║  l.63: \tr.value + 1\n//│ ╙──      \t^^^^^^^\n//│ Int | error\n//│ res\n//│     = 'abc1'\n\n\n\n// * Below are some variations on Ref, for testing purposes.\n\n\nclass Ref() { mut val value = 0 }\n//│ class Ref() {\n//│   mut val value: 0\n//│ }\n\n\nlet r = Ref()\n//│ let r: Ref\n//│ r\n//│   = Ref {}\n\n:e\nset r.value = \"abc\"\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.94: \tset r.value = \"abc\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── string literal of type `\"abc\"` does not match type `0`\n//│ ║  l.94: \tset r.value = \"abc\"\n//│ ║        \t              ^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.82: \tclass Ref() { mut val value = 0 }\n//│ ║        \t                              ^\n//│ ╟── from assigned selection:\n//│ ║  l.94: \tset r.value = \"abc\"\n//│ ╙──      \t    ^^^^^^^\n//│ ()\n//│ res\n//│     = undefined\n\nr.value\n//│ 0\n//│ res\n//│     = 'abc'\n\nclass Ref() { mut val value = 0; fun foo = set value = 42 }\n//│ class Ref() {\n//│   fun foo: ()\n//│   mut val value: 0 | 42\n//│ }\n\nset r.value = 0\n//│ ()\n//│ res\n//│     = undefined\n\nset r.value = 42\n//│ ()\n//│ res\n//│     = undefined\n\n:e\nset r.value = 666\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.133: \tset r.value = 666\n//│ ║         \t^^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `666` does not match type `0 | 42`\n//│ ║  l.133: \tset r.value = 666\n//│ ║         \t              ^^^\n//│ ╟── Note: constraint arises from definition of value value:\n//│ ║  l.116: \tclass Ref() { mut val value = 0; fun foo = set value = 42 }\n//│ ║         \t                      ^^^^^^^^^\n//│ ╟── from assigned selection:\n//│ ║  l.133: \tset r.value = 666\n//│ ╙──       \t    ^^^^^^^\n//│ ()\n//│ res\n//│     = undefined\n\n\n:e // * TODO better error...\nclass Ref() { mut val value = 0; constructor() { set value = 42 } }\n//│ ╔══[ERROR] Illegal assignment\n//│ ║  l.152: \tclass Ref() { mut val value = 0; constructor() { set value = 42 } }\n//│ ║         \t                                                 ^^^^^^^^^^^^^^\n//│ ╟── cannot assign to reference\n//│ ║  l.152: \tclass Ref() { mut val value = 0; constructor() { set value = 42 } }\n//│ ╙──       \t                                                     ^^^^^\n//│ class Ref() {\n//│   constructor()\n//│   mut val value: 0\n//│ }\n\nset r.value = 0\n//│ ()\n//│ res\n//│     = undefined\n\n:e\nset r.value = 42\n//│ ╔══[ERROR] Type mismatch in assignment:\n//│ ║  l.170: \tset r.value = 42\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ╟── integer literal of type `42` does not match type `0`\n//│ ║  l.170: \tset r.value = 42\n//│ ║         \t              ^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.152: \tclass Ref() { mut val value = 0; constructor() { set value = 42 } }\n//│ ║         \t                              ^\n//│ ╟── from assigned selection:\n//│ ║  l.170: \tset r.value = 42\n//│ ╙──       \t    ^^^^^^^\n//│ ()\n//│ res\n//│     = undefined\n\n\nclass Ref() { mut val value = 0; fun foo(x) = set value = x }\n//│ class Ref() {\n//│   fun foo: 0 -> ()\n//│   mut val value: 0\n//│ }\n\nclass Ref[A](init: A) { mut val value = (); fun foo(x) = set value = x }\n//│ class Ref[A](init: A) {\n//│   fun foo: () -> ()\n//│   mut val value: ()\n//│ }\n\nclass Ref[A](init: A) { mut val value = (); fun foo(x: A) = set value = x }\n//│ class Ref[A](init: A) {\n//│   fun foo: (x: A) -> ()\n//│   mut val value: () | A\n//│ }\n\nclass Ref[A](init: A) { mut val value = init; fun foo(x) = set value = x }\n//│ class Ref[A](init: A) {\n//│   fun foo: A -> ()\n//│   mut val value: A\n//│ }\n\n\nabstract class B[A]() { fun value: A; fun get = this.value }\nclass Ref() extends B { mut val value = 0; fun foo = set value = 42 }\n//│ abstract class B[A]() {\n//│   fun get: A\n//│   fun value: A\n//│ }\n//│ class Ref() extends B {\n//│   fun foo: ()\n//│   fun get: 'A\n//│   mut val value: 0 | 42\n//│ }\n//│ where\n//│   'A :> 0 | 42\n\nlet r = Ref()\n//│ let r: Ref\n//│ r\n//│   = Ref {}\n\nr : B['a]\n//│ B['a]\n//│   where\n//│     'a :> 0 | 42\n//│ res\n//│     = Ref {}\n\nr.value\n//│ 0 | 42\n//│ res\n//│     = 0\n\nset r.value = 42\n//│ ()\n//│ res\n//│     = undefined\n\nr.get\n//│ 0 | 42\n//│ res\n//│     = 42\n\n\nabstract class B[A]() { mut val value: A; fun get = this.value }\n//│ abstract class B[A]() {\n//│   fun get: A\n//│   mut val value: A\n//│ }\n\nclass Ref extends B { mut val value = 123 }\n//│ class Ref extends B {\n//│   constructor()\n//│   fun get: 'A\n//│   mut val value: 123\n//│ }\n//│ where\n//│   'A :> 123\n\nlet r = new Ref\n//│ let r: Ref\n//│ r\n//│   = Ref {}\n\nr : B['a]\n//│ B['a]\n//│   where\n//│     'a :> 123\n//│ res\n//│     = Ref {}\n\nr.value\n//│ 123\n//│ res\n//│     = 123\n\nset r.value = 123\n//│ ()\n//│ res\n//│     = undefined\n\nr.get\n//│ 123\n//│ res\n//│     = 123\n\n\nfun g(b: B['a]) = b.get\n//│ fun g: forall 'a. (b: B['a]) -> 'a\n\n// :e // FIXME this should not work...\nclass Ref extends B { mut val value = 123; fun c = g(this) + 1; fun d = set value = \"oops\" }\n//│ class Ref extends B {\n//│   constructor()\n//│   fun c: Int\n//│   fun d: ()\n//│   fun get: 'A\n//│   mut val value: \"oops\" | 123\n//│ }\n//│ where\n//│   'A :> \"oops\" | 123\n\nlet r = new Ref\n//│ let r: Ref\n//│ r\n//│   = Ref {}\n\nr.c\n//│ Int\n//│ res\n//│     = 124\n\nr.d\n//│ ()\n//│ res\n//│     = undefined\n\nr.value\n//│ \"oops\" | 123\n//│ res\n//│     = 'oops'\n\n// * FIXME Runtime type confusion!\nr.c\n//│ Int\n//│ res\n//│     = 'oops1'\n\n\n:e\nclass Ref() extends B\n//│ ╔══[ERROR] Member `value` is declared (or its declaration is inherited) but is not implemented in `Ref`\n//│ ║  l.341: \tclass Ref() extends B\n//│ ║         \t      ^^^\n//│ ╟── Declared here:\n//│ ║  l.255: \tabstract class B[A]() { mut val value: A; fun get = this.value }\n//│ ╙──       \t                            ^^^^^^^^^^^^\n//│ class Ref() extends B {\n//│   fun get: 'A\n//│   mut val value: 'A\n//│ }\n\n:e\nclass Ref extends B { mut val value = 123; fun c = this.get + 1 }\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.354: \tclass Ref extends B { mut val value = 123; fun c = this.get + 1 }\n//│ ╙──       \t                                                       ^^^^\n//│ class Ref extends B {\n//│   constructor()\n//│   fun c: Int\n//│   fun get: 'A\n//│   mut val value: 123\n//│ }\n//│ where\n//│   'A :> 123\n\n\n:e\nabstract class R() { mut val value: _ }\n//│ ╔══[ERROR] type identifier not found: _\n//│ ║  l.369: \tabstract class R() { mut val value: _ }\n//│ ╙──       \t                                    ^\n//│ abstract class R() {\n//│   mut val value: error\n//│ }\n\nabstract class R() { mut val value: Int }\n//│ abstract class R() {\n//│   mut val value: Int\n//│ }\n\nabstract class R() { mut val value: 'a }\n//│ abstract class R() {\n//│   mut val value: nothing\n//│ }\n\n\n:e\ntrait Foo { mut val v = 0 }\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.389: \ttrait Foo { mut val v = 0 }\n//│ ╙──       \t                ^^^^^^^^^\n//│ trait Foo {\n//│   mut val v: 0\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/RefinedPattern.mls",
    "content": ":NewDefs\n\n\nclass C\n//│ class C {\n//│   constructor()\n//│ }\n\n\n:e\nfun test(x) = if x is\n  C then x.a\n//│ ╔══[ERROR] Type `C` does not contain member `a`\n//│ ║  l.12: \t  C then x.a\n//│ ╙──      \t          ^^\n//│ fun test: C -> error\n\nfun test(x) = if x is\n  refined(C) then x.a\n//│ fun test: forall 'a. (C & {a: 'a}) -> 'a\n\nclass D(val a: Int) extends C\n//│ class D(a: Int) extends C\n\ntest(D(123))\n//│ Int\n//│ res\n//│     = 123\n\n\n:e\nrefined\n//│ ╔══[ERROR] Illegal use of reserved operator: refined\n//│ ║  l.32: \trefined\n//│ ╙──      \t^^^^^^^\n//│ ╔══[ERROR] identifier not found: refined\n//│ ║  l.32: \trefined\n//│ ╙──      \t^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol refined\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Refinements.mls",
    "content": ":NewDefs\n\n\nclass D() { fun f = 0 }\n//│ class D() {\n//│   fun f: 0\n//│ }\n\nD() : D & Object\n//│ D\n//│ res\n//│     = D {}\n\nlet d = D() : D & { f: 0 }\n//│ let d: D & {f: 0}\n//│ d\n//│   = D {}\n\nlet c = d with { f: 1 }\n//│ let c: D\\f & {f: 1}\n//│ c\n//│   = D { f: 1 }\n\nc : D & { f: 1 }\n//│ D & {f: 1}\n//│ res\n//│     = D { f: 1 }\n\n\nclass C[A](val a: A) extends D()\n//│ class C[A](a: A) extends D {\n//│   fun f: 0\n//│ }\n\nC(1)\n//│ C['A]\n//│   where\n//│     'A :> 1\n//│ res\n//│     = C {}\n\nlet c: C & {a: 1, f: 0} = C(1)\n//│ let c: C[anything] & {a: 1, f: 0}\n//│ c\n//│   = C {}\n\nc.f\n//│ 0\n//│ res\n//│     = 0\n\n\nlet r = {}\n//│ let r: anything\n//│ r\n//│   = {}\n\n// * Not all records are objects!\n// * Objects are class instances.\n// * But other values, like functions, can also hold record fields...\n// * This is actually important in JS, where some library functions act like modules!\n:e\nr : Object\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.63: \tr : Object\n//│ ║        \t^\n//│ ╟── definition of let binding r of type `anything` is not an instance of type `Object`\n//│ ║  l.53: \tlet r = {}\n//│ ║        \t    ^^^^^^\n//│ ╟── but it flows into reference with expected type `Object`\n//│ ║  l.63: \tr : Object\n//│ ║        \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.63: \tr : Object\n//│ ╙──      \t    ^^^^^^\n//│ Object\n//│ res\n//│     = {}\n\nr with { x: 1 }\n//│ {x: 1}\n//│ res\n//│     = { x: 1 }\n\n\n:e // TODO support\nlet r = new {}\n//│ ╔══[ERROR] Unexpected type `anything` after `new` keyword\n//│ ║  l.87: \tlet r = new {}\n//│ ╙──      \t            ^^\n//│ let r: error\n//│ Code generation encountered an error:\n//│   Unsupported `new` class term: Bra(true,Rcd(List()))\n\n:ge\nr : Object\n//│ Object\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding r\n\n:ge\nr with { x: 1 }\n//│ error & {x: 1}\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding r\n\n\nlet r = { x: 0 }\n//│ let r: {x: 0}\n//│ r\n//│   = { x: 0 }\n\n:e\nr : Object\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.114: \tr : Object\n//│ ║         \t^\n//│ ╟── record literal of type `{x: 0}` is not an instance of type `Object`\n//│ ║  l.108: \tlet r = { x: 0 }\n//│ ║         \t             ^\n//│ ╟── but it flows into reference with expected type `Object`\n//│ ║  l.114: \tr : Object\n//│ ║         \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.114: \tr : Object\n//│ ╙──       \t    ^^^^^^\n//│ Object\n//│ res\n//│     = { x: 0 }\n\nr with { x: 1 }\n//│ {x: 1}\n//│ res\n//│     = { x: 1 }\n\n\n\n:NoJS\n\n\nfun o : {}\n//│ fun o: anything\n\no : {}\n//│ anything\n\n:e\no : Object\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.148: \to : Object\n//│ ║         \t^\n//│ ╟── type `anything` is not an instance of type `Object`\n//│ ║  l.141: \tfun o : {}\n//│ ║         \t        ^^\n//│ ╟── but it flows into reference with expected type `Object`\n//│ ║  l.148: \to : Object\n//│ ║         \t^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.148: \to : Object\n//│ ╙──       \t    ^^^^^^\n//│ Object\n\n\nfun o : Object & {}\n//│ fun o: Object\n\no : {}\n//│ anything\n\no : Object\n//│ Object\n\n\n\n// === //\n\n\n:e\nlet d = D & { f: 0 }\n//│ ╔══[ERROR] Illegal use of reserved operator: &\n//│ ║  l.179: \tlet d = D & { f: 0 }\n//│ ╙──       \t          ^\n//│ ╔══[ERROR] identifier not found: &\n//│ ║  l.179: \tlet d = D & { f: 0 }\n//│ ╙──       \t          ^\n//│ let d: error\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Res.mls",
    "content": ":NewDefs\n\n\nx => x + 2\n//│ Int -> Int\n//│ res\n//│     = [Function: res]\n\n:e\nres(1)\n//│ ╔══[ERROR] identifier not found: res\n//│ ║  l.10: \tres(1)\n//│ ╙──      \t^^^\n//│ error\n//│ res\n//│     = 3\n\n\nlet res = x => x + 2\n//│ let res: Int -> Int\n//│ res\n//│     = [Function: res1]\n\nres(1)\n//│ Int\n//│ res\n//│     = 3\n\n// FIXME `res` not accounted in type context\n:re\nres(1)\n//│ Int\n//│ res\n//│ Runtime error:\n//│   TypeError: res is not a function\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/RightAssocOps.mls",
    "content": ":NewDefs\n\n\n// * Operators that end with `:` are right-associative\n\n\nfun (+:) pre(x: Int, xs) = [[x], xs]\nfun (:+) post(xs, x: Int) = [xs, [x]]\nfun (++) conc(xs, ys) = [xs, ys]\n//│ fun (+:) pre: forall 'a. (x: Int, 'a) -> [[Int], 'a]\n//│ fun (:+) post: forall 'b. ('b, x: Int) -> ['b, [Int]]\n//│ fun (++) conc: forall 'c 'd. ('c, 'd) -> ['c, 'd]\n\n\n1 +: 2 +: 3 +: []\n//│ [[Int], [[Int], [[Int], []]]]\n//│ res\n//│     = [ [ 1 ], [ [ 2 ], [ [Array], [] ] ] ]\n\n[] :+ 1 :+ 2 :+ 3\n//│ [[[[], [Int]], [Int]], [Int]]\n//│ res\n//│     = [ [ [ [], [Array] ], [ 2 ] ], [ 3 ] ]\n\n[1, 2, 3] ++ [4, 5, 6]\n//│ [[1, 2, 3], [4, 5, 6]]\n//│ res\n//│     = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]\n\n:p\n1 +: \"a\" ++ \"b\" :+ 2\n//│ |1| |+:| |\"a\"| |++| |\"b\"| |:+| |2|\n//│ AST: TypingUnit(List(App(Var(+:),Tup(List((None,Fld(_,IntLit(1))), (None,Fld(_,App(Var(:+),Tup(List((None,Fld(_,App(Var(++),Tup(List((None,Fld(_,StrLit(a))), (None,Fld(_,StrLit(b)))))))), (None,Fld(_,IntLit(2)))))))))))))\n//│ Parsed: +:(1, :+(++(\"a\", \"b\",), 2,),);\n//│ [[Int], [[\"a\", \"b\"], [Int]]]\n//│ res\n//│     = [ [ 1 ], [ [ 'a', 'b' ], [ 2 ] ] ]\n\n:p\n1 +: \"a\" :+ 2 ++ \"b\"\n//│ |1| |+:| |\"a\"| |:+| |2| |++| |\"b\"|\n//│ AST: TypingUnit(List(App(Var(+:),Tup(List((None,Fld(_,IntLit(1))), (None,Fld(_,App(Var(++),Tup(List((None,Fld(_,App(Var(:+),Tup(List((None,Fld(_,StrLit(a))), (None,Fld(_,IntLit(2)))))))), (None,Fld(_,StrLit(b)))))))))))))\n//│ Parsed: +:(1, ++(:+(\"a\", 2,), \"b\",),);\n//│ [[Int], [[\"a\", [Int]], \"b\"]]\n//│ res\n//│     = [ [ 1 ], [ [ 'a', [Array] ], 'b' ] ]\n\n:p\n:e\n1 +: \"a\" ++ 2 +: \"b\"\n//│ |1| |+:| |\"a\"| |++| |2| |+:| |\"b\"|\n//│ AST: TypingUnit(List(App(Var(+:),Tup(List((None,Fld(_,IntLit(1))), (None,Fld(_,App(Var(+:),Tup(List((None,Fld(_,App(Var(++),Tup(List((None,Fld(_,StrLit(a))), (None,Fld(_,IntLit(2)))))))), (None,Fld(_,StrLit(b)))))))))))))\n//│ Parsed: +:(1, +:(++(\"a\", 2,), \"b\",),);\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.50: \t1 +: \"a\" ++ 2 +: \"b\"\n//│ ║        \t     ^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `[?a, ?b]` is not an instance of type `Int`\n//│ ║  l.9: \tfun (++) conc(xs, ys) = [xs, ys]\n//│ ║       \t                        ^^^^^^^^\n//│ ╟── but it flows into operator application with expected type `Int`\n//│ ║  l.50: \t1 +: \"a\" ++ 2 +: \"b\"\n//│ ║        \t     ^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.7: \tfun (+:) pre(x: Int, xs) = [[x], xs]\n//│ ╙──     \t                ^^^\n//│ [[Int], error | [[Int], \"b\"]]\n//│ res\n//│     = [ [ 1 ], [ [ [Array] ], 'b' ] ]\n\n1 +: \"a\" ++ (2 +: \"b\")\n//│ [[Int], [\"a\", [[Int], \"b\"]]]\n//│ res\n//│     = [ [ 1 ], [ 'a', [ [Array], 'b' ] ] ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/RigidVariables.mls",
    "content": ":NewDefs\n\n\n// * Flexible\n\nfun f(x: 'test) = [x.b, x]\n//│ fun f: forall 'b 'test. (x: {b: 'b} & 'test) -> ['b, 'test]\n\n\n// * Rigid\n\n:e\nfun f[A](x: A) = x.b\n//│ ╔══[ERROR] Type `A` does not contain member `b`\n//│ ║  l.13: \tfun f[A](x: A) = x.b\n//│ ╙──      \t                  ^^\n//│ fun f: (x: anything) -> error\n\nfun f[A](x: A & { b: ' }) = x.b\n//│ fun f: forall 'b. (x: {b: 'b}) -> 'b\n\n:e\nmodule Foo {\n  fun f[A](x: A) = x.b\n}\n//│ ╔══[ERROR] Type `A` does not contain member `b`\n//│ ║  l.24: \t  fun f[A](x: A) = x.b\n//│ ╙──      \t                    ^^\n//│ module Foo {\n//│   fun f: (x: anything) -> error\n//│ }\n\n:e\nclass Foo[A](x: A) {\n  fun f = x.b\n}\n//│ ╔══[ERROR] Type `A` does not contain member `b`\n//│ ║  l.35: \t  fun f = x.b\n//│ ╙──      \t           ^^\n//│ class Foo[A](x: A) {\n//│   fun f: error\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/SelfAppMethods.mls",
    "content": ":NewDefs\n\n\nclass A {\n  \n  fun f = f(f)\n  \n  fun g : A\n  fun g = g(g) // * FIXME not using the signature\n  \n}\n//│ class A {\n//│   constructor()\n//│   fun f: nothing\n//│   fun g: A\n//│ }\n\n:e\nmodule A {\n  fun i(x) = x\n  fun f = f(f)\n  fun g(x) = x(x)\n  fun h = g(g)\n}\n//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required\n//│ ║  l.23: \t  fun h = g(g)\n//│ ║        \t          ^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ module A {\n//│   fun f: nothing\n//│   fun g: forall 'a 'b. ('a -> 'b & 'a) -> 'b\n//│   fun h: error\n//│   fun i: forall 'c. 'c -> 'c\n//│ }\n\n// * Note this permutation works: currently we generalize check functions in the source code order...\nmodule A {\n  fun i(x) = x\n  fun f = f(f)\n  fun h = g(g)\n  fun g(x) = x(x)\n}\n//│ module A {\n//│   fun f: nothing\n//│   fun g: forall 'a 'b. 'b -> 'a\n//│   fun h: forall 'a. 'a\n//│   fun i: forall 'c. 'c -> 'c\n//│ }\n//│ where\n//│   'b := 'b -> 'a\n\n:ns\nA.i\n//│ 'i\n//│   where\n//│     'i :> forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: i]\n\n:re\n:ns\nA.f\n//│ 'f\n//│   where\n//│     'f :> forall 'f0 'a. 'a\n//│     'a <: 'f0\n//│     'f0 <: 'f0 -> 'a\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n:ns\nA.g\n//│ 'g\n//│   where\n//│     'g :> forall 'a 'b 'c 'h. 'a -> 'b\n//│     'a := 'a -> 'b\n//│     'b <: 'c\n//│     'c <: 'h\n//│ res\n//│     = [Function: g]\n\n:ns\n:re\nA.h\n//│ 'h\n//│   where\n//│     'h :> forall 'a 'h0. 'a\n//│     'a <: 'h0\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/SelfRec.mls",
    "content": ":NewDefs\n\n\n\nclass Foo1(val x: Int) {\n  fun test = Foo1(1).x\n}\n//│ class Foo1(x: Int) {\n//│   fun test: Int\n//│ }\n\n:e\nclass Foo1X(x: 0 | 1) extends Foo1(x) {\n  fun test2 = Foo1X(1).x\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.14: \t  fun test2 = Foo1X(1).x\n//│ ╙──      \t                      ^^\n//│ ╔══[ERROR] Inherited parameter named 'x' is not virtual and cannot be overridden\n//│ ║  l.13: \tclass Foo1X(x: 0 | 1) extends Foo1(x) {\n//│ ║        \t            ^\n//│ ╟── Originally declared here:\n//│ ║  l.5: \tclass Foo1(val x: Int) {\n//│ ╙──     \t               ^\n//│ class Foo1X(x: 0 | 1) extends Foo1 {\n//│   fun test: Int\n//│   fun test2: error\n//│ }\n\n\nclass Foo2[A](val x: A) {\n  fun test = Foo2(1).x\n}\n//│ class Foo2[A](x: A) {\n//│   fun test: 1\n//│ }\n\n:e\nclass Foo2X(x: 0 | 1) extends Foo2(x) {\n  fun test2 = Foo2X(1).x\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.40: \t  fun test2 = Foo2X(1).x\n//│ ╙──      \t                      ^^\n//│ ╔══[ERROR] Inherited parameter named 'x' is not virtual and cannot be overridden\n//│ ║  l.39: \tclass Foo2X(x: 0 | 1) extends Foo2(x) {\n//│ ║        \t            ^\n//│ ╟── Originally declared here:\n//│ ║  l.31: \tclass Foo2[A](val x: A) {\n//│ ╙──      \t                  ^\n//│ class Foo2X(x: 0 | 1) extends Foo2 {\n//│   fun test: 1\n//│   fun test2: error\n//│ }\n\n:e\nFoo2X(1).x\n//│ ╔══[ERROR] Parameter 'x' cannot be accessed as a field\n//│ ║  l.57: \tFoo2X(1).x\n//│ ║        \t        ^^\n//│ ╟── Either make the parameter a `val` or access it through destructuring\n//│ ║  l.39: \tclass Foo2X(x: 0 | 1) extends Foo2(x) {\n//│ ╙──      \t            ^\n//│ 0 | 1 | error\n//│ res\n//│     = 1\n\n:e // TODO improve type checking\nclass Foo2X(a: 0 | 1) extends Foo2(a) {\n  fun test2 = Foo2X(1).x\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.70: \t  fun test2 = Foo2X(1).x\n//│ ╙──      \t                      ^^\n//│ class Foo2X(a: 0 | 1) extends Foo2 {\n//│   fun test: 1\n//│   fun test2: error\n//│ }\n\nFoo2X(1).x\n//│ 0 | 1\n//│ res\n//│     = 1\n\n\nclass Foo3[A](val x: A) {\n  fun test = Foo3(1)\n  fun foo = Foo3\n}\n//│ class Foo3[A](x: A) {\n//│   fun foo: (x: A) -> Foo3[A]\n//│   fun test: forall 'A. Foo3['A]\n//│ }\n//│ where\n//│   'A :> 1\n\nFoo3\n//│ forall 'A. (x: 'A) -> Foo3['A]\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Foo3],\n//│         unapply: [Function: unapply]\n//│       }\n\nFoo3(1)\n//│ Foo3['A]\n//│   where\n//│     'A :> 1\n//│ res\n//│     = Foo3 {}\n\nFoo3(1).x\n//│ 1\n//│ res\n//│     = 1\n\nFoo3(1).foo\n//│ forall 'A. (x: 'A) -> Foo3['A]\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Foo3],\n//│         unapply: [Function: unapply]\n//│       }\n\n:e\nclass Foo4 {\n  fun test = [Foo4.test]\n}\n//│ ╔══[ERROR] Class Foo4 cannot be instantiated as it exposes no constructor\n//│ ║  l.127: \t  fun test = [Foo4.test]\n//│ ╙──       \t              ^^^^\n//│ class Foo4 {\n//│   constructor()\n//│   fun test: [error]\n//│ }\n\n:e\nclass Foo5(x: Int) {\n  fun test = [Foo5(5).test]\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.139: \t  fun test = [Foo5(5).test]\n//│ ╙──       \t                     ^^^^^\n//│ class Foo5(x: Int) {\n//│   fun test: [error]\n//│ }\n\n:e\nclass Foo6[A](x: A) {\n  fun test1 = [Foo6(x).test1]\n  fun test2 = [Foo6(123).test2]\n  fun test3 = [Foo6([x]).test3]\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.150: \t  fun test1 = [Foo6(x).test1]\n//│ ╙──       \t                      ^^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.151: \t  fun test2 = [Foo6(123).test2]\n//│ ╙──       \t                        ^^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.152: \t  fun test3 = [Foo6([x]).test3]\n//│ ╙──       \t                        ^^^^^^\n//│ class Foo6[A](x: A) {\n//│   fun test1: [error]\n//│   fun test2: [error]\n//│   fun test3: [error]\n//│ }\n\nmodule N\n//│ module N\n\n:e\nclass Foo7[A](head: A, tail: Foo7[A] | N) {\n  fun test1 = if tail is\n    N then head\n    _ then tail.test1\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.176: \t    _ then tail.test1\n//│ ╙──       \t               ^^^^^^\n//│ class Foo7[A](head: A, tail: Foo7[A] | N) {\n//│   fun test1: error | A\n//│ }\n\nclass Foo7_A[A](head: A, tail: Foo7_A[A] | N) {\n  fun test1: A\n  fun test1 = if tail is\n    N then head\n    _ then tail.test1\n}\n//│ class Foo7_A[A](head: A, tail: Foo7_A[A] | N) {\n//│   fun test1: A\n//│ }\n\nclass Foo7_A2[A](head: A, tail: Foo7_A[A] | N) {\n  fun test1: A = if tail is\n    N then head\n    _ then tail.test1\n}\n//│ class Foo7_A2[A](head: A, tail: Foo7_A[A] | N) {\n//│   fun test1: A\n//│ }\n\nclass Foo7_2_A[A](head: A, tail: Foo7_A[Int] | N) {\n  fun test1: Int | A = if tail is\n    N then head\n    _ then tail.test1\n}\n//│ class Foo7_2_A[A](head: A, tail: Foo7_A[Int] | N) {\n//│   fun test1: Int | A\n//│ }\n\n:e\nclass Foo8[A](x: A) {\n  fun test1[B](y: B): A =\n    let tmp = Foo8(y).test1(x)\n    x\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.216: \t    let tmp = Foo8(y).test1(x)\n//│ ╙──       \t                     ^^^^^^\n//│ class Foo8[A](x: A) {\n//│   fun test1: (y: anything) -> A\n//│ }\n\n\n\n\n:e // * FIXME this is caused by the self-annotation...\nabstract class List(val length: Int): Cons\nclass Cons(tail: List) extends List(tail.length + 1)\n//│ ╔══[ERROR] Unhandled cyclic parent specification\n//│ ║  l.231: \tclass Cons(tail: List) extends List(tail.length + 1)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.231: \tclass Cons(tail: List) extends List(tail.length + 1)\n//│ ╙──       \t                                        ^^^^^^^\n//│ abstract class List(length: Int): Cons\n//│ class Cons(tail: List) extends List\n\n// * Note: full (non-minimized) definitions:\n\n:e // * FIXME\nabstract class List[out A](val length: Int): Cons[A] | Nil\nclass Cons[out A](val head: A, val tail: List[A]) extends List[A](tail.length + 1)\nmodule Nil extends List[nothing](0)\n//│ ╔══[ERROR] Unhandled cyclic parent specification\n//│ ║  l.245: \tclass Cons[out A](val head: A, val tail: List[A]) extends List[A](tail.length + 1)\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.245: \tclass Cons[out A](val head: A, val tail: List[A]) extends List[A](tail.length + 1)\n//│ ╙──       \t                                                                      ^^^^^^^\n//│ abstract class List[A](length: Int): Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A]) extends List\n//│ module Nil extends List\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Sidney.mls",
    "content": ":NewDefs\n\n\nfun swapMaybe(x, y) =\n  if true then [x, y] else [y, x]\n//│ fun swapMaybe: forall 'a. ('a, 'a) -> ['a, 'a]\n\nswapMaybe : forall 'a, 'b: ('a, 'b) -> ['a | 'b, 'b | 'a]\n//│ forall 'a. ('a, 'a) -> ['a, 'a]\n//│ res\n//│     = [Function: swapMaybe]\n\n\nfun test(x, y, z) =\n  let xy = swapMaybe(x, y)\n  let yz = swapMaybe(xy.1, z)\n  [xy.0, yz.0, yz.1]\n//│ fun test: forall 'a 'b. ('a, 'a, 'b) -> ['a, 'a | 'b, 'b | 'a]\n\n:e\ntest : forall 'a, 'b: ('a, 'b, 'b) -> ['a | 'b, 'a | 'b, 'b]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.21: \ttest : forall 'a, 'b: ('a, 'b, 'b) -> ['a | 'b, 'a | 'b, 'b]\n//│ ║        \t^^^^\n//│ ╟── type `'a` does not match type `'b`\n//│ ║  l.21: \ttest : forall 'a, 'b: ('a, 'b, 'b) -> ['a | 'b, 'a | 'b, 'b]\n//│ ║        \t                       ^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.21: \ttest : forall 'a, 'b: ('a, 'b, 'b) -> ['a | 'b, 'a | 'b, 'b]\n//│ ║        \t                                                         ^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.21: \ttest : forall 'a, 'b: ('a, 'b, 'b) -> ['a | 'b, 'a | 'b, 'b]\n//│ ╙──      \t              ^^\n//│ forall 'a 'b. ('a, 'b, 'b) -> ['a | 'b, 'a | 'b, 'b]\n//│ res\n//│     = [Function: test]\n\n\nfun test(x, y, z) =\n  if true then\n    let xy = swapMaybe(x, y)\n    [xy.0, xy.1, z]\n  else\n    let yz = swapMaybe(y, z)\n    [x, yz.0, yz.1]\n//│ fun test: forall 'a 'b. ('a, 'a & 'b, 'b) -> ['a, 'a | 'b, 'b]\n\ntest : forall 'a: ('a, 'a, 'a) -> ['a, 'a, 'a]\n//│ forall 'a. ('a, 'a, 'a) -> ['a, 'a, 'a]\n//│ res\n//│     = [Function: test1]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/SimpleSymbolicOps.mls",
    "content": ":NewDefs\n\n\nfun (-) i(x, y) = x\n//│ fun (-) i: forall 'a. ('a, anything) -> 'a\n\n1 - 1\n//│ 1\n//│ res\n//│     = 1\n\n\nfun (-) i(x, y) = x\n[i(1,1), i(2,1), 1 - 1, 2 - 1]\n//│ fun (-) i: forall 'a. ('a, anything) -> 'a\n//│ [1, 2, 1, 2]\n//│ res\n//│     = [ 1, 2, 1, 2 ]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/SimpleTraitImpl.mls",
    "content": ":NewDefs\n\n:NoJS // TODO enable JS\n\n\n\ntrait T1 { fun x: 0 | 1 }\ntrait T2 { fun x: 1 | 2 }\n//│ trait T1 {\n//│   fun x: 0 | 1\n//│ }\n//│ trait T2 {\n//│   fun x: 1 | 2\n//│ }\n\nabstract class C1 { fun x: 0 | 2 }\n//│ abstract class C1 {\n//│   fun x: 0 | 2\n//│ }\n\n:e\nmodule M extends C1, T1 {\n  fun x = 2\n}\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.23: \t  fun x = 2\n//│ ║        \t      ^^^^^\n//│ ╟── integer literal of type `2` does not match type `0 | 1`\n//│ ║  l.23: \t  fun x = 2\n//│ ║        \t          ^\n//│ ╟── but it flows into definition of method x with expected type `0 | 1`\n//│ ║  l.23: \t  fun x = 2\n//│ ║        \t      ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ║       \t                  ^^^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ╙──     \t               ^^^^^^^^\n//│ module M extends C1, T1 {\n//│   fun x: 2\n//│ }\n\nabstract class C2 extends C1, T1\n//│ abstract class C2 extends C1, T1 {\n//│   fun x: 0\n//│ }\n\n:e\nmodule M extends C2 {\n  fun x = 2\n}\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.51: \t  fun x = 2\n//│ ║        \t      ^^^^^\n//│ ╟── integer literal of type `2` does not match type `0 | 1`\n//│ ║  l.51: \t  fun x = 2\n//│ ║        \t          ^\n//│ ╟── but it flows into definition of method x with expected type `0 | 1`\n//│ ║  l.51: \t  fun x = 2\n//│ ║        \t      ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ║       \t                  ^^^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ╙──     \t               ^^^^^^^^\n//│ module M extends C1, C2, T1 {\n//│   fun x: 2\n//│ }\n\nclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ class C1 {\n//│   constructor()\n//│   fun x: 0 | 2\n//│ }\n\n\n\n:e\nmodule M extends C1, T1\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                       ^^^^^^^^^^^^\n//│ ╟── type `2` does not match type `0 | 1`\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                              ^\n//│ ╟── but it flows into union type with expected type `0 | 1`\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                          ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ║       \t                  ^^^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ╙──     \t               ^^^^^^^^\n//│ module M extends C1, T1 {\n//│   fun x: 0 | 2\n//│ }\n\n:e\nmodule M extends T1, C1\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                       ^^^^^^^^^^^^\n//│ ╟── type `2` does not match type `0 | 1`\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                              ^\n//│ ╟── but it flows into union type with expected type `0 | 1`\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                          ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ║       \t                  ^^^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ╙──     \t               ^^^^^^^^\n//│ module M extends C1, T1 {\n//│   fun x: 0 | 2\n//│ }\n\n:e\nmodule M extends T1, T2, C1 {\n  fun x = this.x\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.124: \t  fun x = this.x\n//│ ╙──       \t              ^^\n//│ module M extends C1, T1, T2 {\n//│   fun x: error\n//│ }\n\n:e\nmodule M extends T1, T2, C1 {\n  fun x: 0\n  fun x = this.x\n}\n//│ ╔══[ERROR] Type mismatch in signature of member `x`:\n//│ ║  l.135: \t  fun x: 0\n//│ ║         \t      ^^^^\n//│ ╟── type `0` does not match type `1 | 2`\n//│ ║  l.135: \t  fun x: 0\n//│ ║         \t         ^\n//│ ╟── but it flows into signature of member `x` with expected type `1 | 2`\n//│ ║  l.135: \t  fun x: 0\n//│ ║         \t      ^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.8: \ttrait T2 { fun x: 1 | 2 }\n//│ ║       \t                  ^^^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.8: \ttrait T2 { fun x: 1 | 2 }\n//│ ╙──     \t               ^^^^^^^^\n//│ module M extends C1, T1, T2 {\n//│   fun x: 0\n//│ }\n\nclass C extends C1, T2 {\n  virtual fun x: 2\n  fun x = this.x\n}\n//│ class C extends C1, T2 {\n//│   constructor()\n//│   fun x: 2\n//│ }\n\nmodule M extends C {\n  fun x = 2\n}\nM.x\n//│ module M extends C, C1, T2 {\n//│   fun x: 2\n//│ }\n//│ 2\n\n\n:e\nclass C2 extends T1\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C2`\n//│ ║  l.177: \tclass C2 extends T1\n//│ ║         \t      ^^\n//│ ╟── Declared here:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ╙──     \t           ^^^^^^^^^^^^\n//│ class C2 extends T1 {\n//│   constructor()\n//│   fun x: 0 | 1\n//│ }\n\nabstract class C2 extends T1\n//│ abstract class C2 extends T1 {\n//│   fun x: 0 | 1\n//│ }\n\n:e\nclass C3 extends C2\n//│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C3`\n//│ ║  l.195: \tclass C3 extends C2\n//│ ║         \t      ^^\n//│ ╟── Declared here:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ╙──     \t           ^^^^^^^^^^^^\n//│ class C3 extends C2, T1 {\n//│   constructor()\n//│   fun x: 0 | 1\n//│ }\n\nabstract class C3 extends C2\n//│ abstract class C3 extends C2, T1 {\n//│   fun x: 0 | 1\n//│ }\n\nclass C2 extends T1 { fun x = 1 }\n//│ class C2 extends T1 {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\n:e\nclass C2 extends T1, T2 { fun x = 2 }\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.219: \tclass C2 extends T1, T2 { fun x = 2 }\n//│ ║         \t                              ^^^^^\n//│ ╟── integer literal of type `2` does not match type `0 | 1`\n//│ ║  l.219: \tclass C2 extends T1, T2 { fun x = 2 }\n//│ ║         \t                                  ^\n//│ ╟── but it flows into definition of method x with expected type `0 | 1`\n//│ ║  l.219: \tclass C2 extends T1, T2 { fun x = 2 }\n//│ ║         \t                              ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ║       \t                  ^^^^^\n//│ ╟── from signature of member `x`:\n//│ ║  l.7: \ttrait T1 { fun x: 0 | 1 }\n//│ ╙──     \t               ^^^^^^^^\n//│ class C2 extends T1, T2 {\n//│   constructor()\n//│   fun x: 2\n//│ }\n\nclass C2 extends T1, T2 { virtual fun x = 1 }\n//│ class C2 extends T1, T2 {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\n:e\nclass C3 extends C2 { virtual fun x = 111 }\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.247: \tclass C3 extends C2 { virtual fun x = 111 }\n//│ ║         \t                                  ^^^^^^^\n//│ ╟── integer literal of type `111` does not match type `1`\n//│ ║  l.247: \tclass C3 extends C2 { virtual fun x = 111 }\n//│ ║         \t                                      ^^^\n//│ ╟── but it flows into definition of method x with expected type `1`\n//│ ║  l.247: \tclass C3 extends C2 { virtual fun x = 111 }\n//│ ║         \t                                  ^^^^^^^\n//│ ╟── Note: constraint arises from integer literal:\n//│ ║  l.240: \tclass C2 extends T1, T2 { virtual fun x = 1 }\n//│ ║         \t                                          ^\n//│ ╟── from definition of method x:\n//│ ║  l.240: \tclass C2 extends T1, T2 { virtual fun x = 1 }\n//│ ╙──       \t                                      ^^^^^\n//│ class C3 extends C2, T1, T2 {\n//│   constructor()\n//│   fun x: 111\n//│ }\n\nclass C3 extends C2 { fun x = 1 }\n//│ class C3 extends C2, T1, T2 {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\nclass C2 extends C1, T1 { fun x = 0 }\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│   fun x: 0\n//│ }\n\nclass C2 extends T1, C1 { fun x = 0 }\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│   fun x: 0\n//│ }\n\n:e\nclass C2 extends C1, T1 { fun x = 1 }\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.287: \tclass C2 extends C1, T1 { fun x = 1 }\n//│ ║         \t                              ^^^^^\n//│ ╟── integer literal of type `1` does not match type `0 | 2`\n//│ ║  l.287: \tclass C2 extends C1, T1 { fun x = 1 }\n//│ ║         \t                                  ^\n//│ ╟── but it flows into definition of method x with expected type `0 | 2`\n//│ ║  l.287: \tclass C2 extends C1, T1 { fun x = 1 }\n//│ ║         \t                              ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                          ^^^^^\n//│ ╟── from definition of method x:\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ╙──      \t                       ^^^^^^^^^^^^\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\n:e\nclass C2 extends T1, C1 { fun x = 1 }\n//│ ╔══[ERROR] Type mismatch in definition of method x:\n//│ ║  l.309: \tclass C2 extends T1, C1 { fun x = 1 }\n//│ ║         \t                              ^^^^^\n//│ ╟── integer literal of type `1` does not match type `0 | 2`\n//│ ║  l.309: \tclass C2 extends T1, C1 { fun x = 1 }\n//│ ║         \t                                  ^\n//│ ╟── but it flows into definition of method x with expected type `0 | 2`\n//│ ║  l.309: \tclass C2 extends T1, C1 { fun x = 1 }\n//│ ║         \t                              ^^^^^\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ║        \t                          ^^^^^\n//│ ╟── from definition of method x:\n//│ ║  l.72: \tclass C1 { virtual fun x: 0 | 2 = 0 }\n//│ ╙──      \t                       ^^^^^^^^^^^^\n//│ class C2 extends C1, T1 {\n//│   constructor()\n//│   fun x: 1\n//│ }\n\n\n\n:e\ntrait T2 { val r = 1(1) }\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.333: \ttrait T2 { val r = 1(1) }\n//│ ╙──       \t           ^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.333: \ttrait T2 { val r = 1(1) }\n//│ ║         \t                   ^^^^\n//│ ╟── integer literal of type `1` is not a function\n//│ ║  l.333: \ttrait T2 { val r = 1(1) }\n//│ ╙──       \t                   ^\n//│ trait T2 {\n//│   val r: error\n//│ }\n\nclass C2 extends T2\n//│ class C2 extends T2 {\n//│   constructor()\n//│   val r: error\n//│ }\n\n\n:e\ntrait T3[A] {\n  val r = C2().x\n}\nclass C2 extends T3[Int]\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.356: \t  val r = C2().x\n//│ ╙──       \t  ^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Class C2 cannot be instantiated as it exposes no constructor\n//│ ║  l.356: \t  val r = C2().x\n//│ ╙──       \t          ^^\n//│ trait T3[A] {\n//│   val r: error\n//│ }\n//│ class C2 extends T3 {\n//│   constructor()\n//│   val r: error\n//│ }\n\n:e // * Note: lack of hygiene... happens only if class shadows previous C2 and is part of the error-throwing block\nC2() : T3['X]\n//│ ╔══[ERROR] Construction of unparameterized class C2 should use the `new` keyword\n//│ ║  l.374: \tC2() : T3['X]\n//│ ╙──       \t^^\n//│ T3[Int]\n\nclass C3 extends T3[Int]\n//│ class C3 extends T3 {\n//│   constructor()\n//│   val r: error\n//│ }\n\nnew C3 : T3['X]\n//│ T3[Int]\n\n\n\ntrait Foo { fun foo: forall 'A: (x: 'A) -> 'A }\n//│ trait Foo {\n//│   fun foo: forall 'A. (x: 'A) -> 'A\n//│ }\n\nclass B extends Foo { fun foo = error }\n//│ class B extends Foo {\n//│   constructor()\n//│   fun foo: nothing\n//│ }\n\nclass B extends Foo { fun foo(x) = x }\n//│ class B extends Foo {\n//│   constructor()\n//│   fun foo: forall 'a. 'a -> 'a\n//│ }\n\n:e\nclass B extends Foo { fun foo(x) = x + 1 }\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.409: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ║         \t                          ^^^^^^^^^^^^^^\n//│ ╟── type `'A` is not an instance of type `Int`\n//│ ║  l.391: \ttrait Foo { fun foo: forall 'A: (x: 'A) -> 'A }\n//│ ║         \t                                    ^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.409: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ║         \t                                   ^\n//│ ╟── Note: quantified type variable 'A is defined at:\n//│ ║  l.391: \ttrait Foo { fun foo: forall 'A: (x: 'A) -> 'A }\n//│ ╙──       \t                            ^^\n//│ ╔══[ERROR] Type mismatch in definition of method foo:\n//│ ║  l.409: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ║         \t                          ^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Int` does not match type `'A`\n//│ ║  l.409: \tclass B extends Foo { fun foo(x) = x + 1 }\n//│ ║         \t                                   ^^^^^\n//│ ╟── Note: constraint arises from type variable:\n//│ ║  l.391: \ttrait Foo { fun foo: forall 'A: (x: 'A) -> 'A }\n//│ ╙──       \t                                           ^^\n//│ class B extends Foo {\n//│   constructor()\n//│   fun foo: Int -> Int\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Splices.mls",
    "content": ":NewDefs\n\n\nlet bs = [1, 2, 3]\n//│ let bs: [1, 2, 3]\n//│ bs\n//│    = [ 1, 2, 3 ]\n\n:pe // TODO\nlet t = [0, ...bs]\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.10: \tlet t = [0, ...bs]\n//│ ╙──      \t            ^^^\n//│ let t: [0]\n//│ t\n//│   = [ 0 ]\n\nt.0\n//│ 0\n//│ res\n//│     = 0\n\n:e // TODO\nt.1\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.24: \tt.1\n//│ ║        \t^^^\n//│ ╟── definition of let binding t of type `{0: 0}` does not have field '1'\n//│ ║  l.10: \tlet t = [0, ...bs]\n//│ ║        \t    ^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{1: ?a}`\n//│ ║  l.24: \tt.1\n//│ ╙──      \t^\n//│ error\n//│ res\n//│     = undefined\n\n:e // TODO\nt.2\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.39: \tt.2\n//│ ║        \t^^^\n//│ ╟── definition of let binding t of type `{0: 0}` does not have field '2'\n//│ ║  l.10: \tlet t = [0, ...bs]\n//│ ║        \t    ^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{2: ?a}`\n//│ ║  l.39: \tt.2\n//│ ╙──      \t^\n//│ error\n//│ res\n//│     = undefined\n\n:e\nt.3\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.54: \tt.3\n//│ ║        \t^^^\n//│ ╟── definition of let binding t of type `{0: 0}` does not have field '3'\n//│ ║  l.10: \tlet t = [0, ...bs]\n//│ ║        \t    ^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{3: ?a}`\n//│ ║  l.54: \tt.3\n//│ ╙──      \t^\n//│ error\n//│ res\n//│     = undefined\n\n\nlet cs: Array[Int] = bs\n//│ let cs: Array[Int]\n//│ cs\n//│    = [ 1, 2, 3 ]\n\n:pe  // TODO\nlet t = [0, ...cs]\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.75: \tlet t = [0, ...cs]\n//│ ╙──      \t            ^^^\n//│ let t: [0]\n//│ t\n//│   = [ 0 ]\n\nt.0\n//│ 0\n//│ res\n//│     = 0\n\n:e\nt.1\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.89: \tt.1\n//│ ║        \t^^^\n//│ ╟── definition of let binding t of type `{0: 0}` does not have field '1'\n//│ ║  l.75: \tlet t = [0, ...cs]\n//│ ║        \t    ^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{1: ?a}`\n//│ ║  l.89: \tt.1\n//│ ╙──      \t^\n//│ error\n//│ res\n//│     = undefined\n\n\n:pe // TODO\nfun f(x, y, ...zs) = x\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.105: \tfun f(x, y, ...zs) = x\n//│ ╙──       \t            ^^^\n//│ fun f: forall 'a. ('a, anything) -> 'a\n\nf(0, 1)\n//│ 0\n//│ res\n//│     = 0\n\n:e // TODO\nf(0, 1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.117: \tf(0, 1, 2)\n//│ ║         \t^^^^^^^^^^\n//│ ╟── argument list of type `[0, 1, 2]` does not match type `[?a, ?b]`\n//│ ║  l.117: \tf(0, 1, 2)\n//│ ║         \t ^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.105: \tfun f(x, y, ...zs) = x\n//│ ╙──       \t     ^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 0\n\n:e // TODO\nf(0, 1, 2, 3)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.132: \tf(0, 1, 2, 3)\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── argument list of type `[0, 1, 2, 3]` does not match type `[?a, ?b]`\n//│ ║  l.132: \tf(0, 1, 2, 3)\n//│ ║         \t ^^^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.105: \tfun f(x, y, ...zs) = x\n//│ ╙──       \t     ^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 0\n\n:e // TODO\nf(0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.147: \tf(0)\n//│ ║         \t^^^^\n//│ ╟── argument of type `[0]` does not match type `[?a, ?b]`\n//│ ║  l.147: \tf(0)\n//│ ║         \t ^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.105: \tfun f(x, y, ...zs) = x\n//│ ╙──       \t     ^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 0\n\n:pe // TODO\n:e // TODO\nf(...bs)\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.163: \tf(...bs)\n//│ ╙──       \t  ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.163: \tf(...bs)\n//│ ║         \t^^^^^^^^\n//│ ╟── argument of type `[]` does not match type `[?a, ?b]`\n//│ ║  l.163: \tf(...bs)\n//│ ║         \t ^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.105: \tfun f(x, y, ...zs) = x\n//│ ╙──       \t     ^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = undefined\n\n:pe // TODO\n:e // TODO\nf(0, ...bs)\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.182: \tf(0, ...bs)\n//│ ╙──       \t     ^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.182: \tf(0, ...bs)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── argument of type `[0]` does not match type `[?a, ?b]`\n//│ ║  l.182: \tf(0, ...bs)\n//│ ║         \t ^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.105: \tfun f(x, y, ...zs) = x\n//│ ╙──       \t     ^^^^^^^^^^^^^\n//│ error\n//│ res\n//│     = 0\n\n:pe // TODO\nf(0, 1, ...bs)\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.200: \tf(0, 1, ...bs)\n//│ ╙──       \t        ^^^\n//│ 0\n//│ res\n//│     = 0\n\n\n:pe // TODO\nfun f: 'xs -> [1, 2, ...'xs]\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.210: \tfun f: 'xs -> [1, 2, ...'xs]\n//│ ╙──       \t                     ^^^\n//│ fun f: anything -> [1, 2]\n\nf([])\n//│ [1, 2]\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\nf([1])\n//│ [1, 2]\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\nf([1, 2])\n//│ [1, 2]\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\nf(bs)\n//│ [1, 2]\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\nf(cs)\n//│ [1, 2]\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\n:e\nf()\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.247: \tf()\n//│ ║         \t^^^\n//│ ╟── argument of type `[]` does not match type `['xs]`\n//│ ║  l.247: \tf()\n//│ ║         \t ^^\n//│ ╟── Note: constraint arises from tuple type:\n//│ ║  l.210: \tfun f: 'xs -> [1, 2, ...'xs]\n//│ ╙──       \t       ^^^\n//│ error | [1, 2]\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\n// :e // TODO\nf(0)\n//│ [1, 2]\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/StupidJS.mls",
    "content": ":NewDefs\n\n\nmodule C { fun f() = this }\n//│ module C {\n//│   fun f: () -> C\n//│ }\n\nC.f()\n//│ C\n//│ res\n//│     = C { class: [class C] }\n\n\n// * In JS semantics, C.f will return a plain method **without capturing `this`**!!\n// * This is very dumb. In Python for example, one gets a closure that captures `this`.\n// * We can't easily work around this without incurring either bad performance overhead\n// * or JS/TS interoperability woes.\n// * Therefore, we'll make sure to reflecy the wonky semantics in the typer\n// * (or maybe just make it fail type checking altogether.)\n\n// :e // TODO prevent unapplied method selections in the type system...\nlet r = id(C.f)()\n//│ let r: C\n//│ r\n//│   = undefined\n\n:re\nr.f\n//│ () -> C\n//│ res\n//│ Runtime error:\n//│   TypeError: Cannot read properties of undefined (reading 'f')\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Subscripts.mls",
    "content": ":NewDefs\n\n\nlet xs = [0, 1, 2]\n//│ let xs: [0, 1, 2]\n//│ xs\n//│    = [ 0, 1, 2 ]\n\nif xs.[0] is\n  undefined then 0\n  x then x\n//│ 0 | 1 | 2\n//│ res\n//│     = 0\n\n\n:e\nxs.[0] + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.18: \txs.[0] + 1\n//│ ║        \t  ^^^^^^^^\n//│ ╟── possibly-undefined array access of type `()` is not an instance of type `Int`\n//│ ║  l.18: \txs.[0] + 1\n//│ ╙──      \t  ^^^^\n//│ Int | error\n//│ res\n//│     = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TODO_Classes.mls",
    "content": ":NewDefs\n\n\n\n// *** First-class classes *** //\n\n\nclass C\n//│ class C {\n//│   constructor()\n//│ }\n\nclass D(x: Int)\n//│ class D(x: Int)\n\n:e\nfun foo(c) = new c\n//│ ╔══[ERROR] type identifier not found: c\n//│ ║  l.17: \tfun foo(c) = new c\n//│ ╙──      \t                 ^\n//│ fun foo: anything -> error\n\n:re\nfoo(() => 123)\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: c is not a constructor\n\n:e\nfoo(C)\n//│ ╔══[ERROR] Construction of unparameterized class C should use the `new` keyword\n//│ ║  l.31: \tfoo(C)\n//│ ╙──      \t    ^\n//│ error\n//│ res\n//│     = C {}\n\n\n:e\nfun bar(c) = new c(123)\n//│ ╔══[ERROR] type identifier not found: c\n//│ ║  l.41: \tfun bar(c) = new c(123)\n//│ ╙──      \t                 ^\n//│ fun bar: anything -> error\n\n:re\nbar(D)\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: c is not a constructor\n\n:e // TODO accept when we have first-class classes\nbar(D.class)\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.55: \tbar(D.class)\n//│ ║        \t    ^^^^^^^\n//│ ╟── reference of type `(x: Int) -> D` does not have field 'class'\n//│ ║  l.55: \tbar(D.class)\n//│ ╙──      \t    ^\n//│ error\n//│ res\n//│     = D {}\n\n\n\n// *** Refinements *** //\n\n\nclass C\n//│ class C {\n//│   constructor()\n//│ }\n\n:e // TODO support\nnew C { val x = 1 }\n//│ ╔══[ERROR] Refinement terms are not yet supported\n//│ ║  l.77: \tnew C { val x = 1 }\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   cannot generate code for term Rft(NuNew(Var(C)),TypingUnit(List(NuFunDef(Some(false),Var(x),None,List(),Left(IntLit(1))))))\n\n\n\n// *** Path-dependent types *** //\n\n\nclass Cls[out A] { fun x: A = x }\n//│ class Cls[A] {\n//│   constructor()\n//│   fun x: A\n//│ }\n\nlet c = new Cls\n//│ let c: Cls[nothing]\n//│ c\n//│   = Cls {}\n\n// FIXME\nlet y: c.A = c.x\n//│ ╔══[ERROR] type identifier not found: c\n//│ ║  l.102: \tlet y: c.A = c.x\n//│ ╙──       \t       ^\n//│ /!!!\\ Uncaught error: scala.NotImplementedError: an implementation is missing\n\n\n\n// *** GADTs *** //\n\n\nclass Cls[A] { fun x: A = x; fun g: A -> Int; fun g = g }\n//│ class Cls[A] {\n//│   constructor()\n//│   fun g: A -> Int\n//│   fun x: A\n//│ }\n\n\n:e // TODO\nfun test(a: Object) = if a is\n  Cls then a.x\n  else error\n//│ ╔══[ERROR] Type error in `case` expression\n//│ ║  l.122: \tfun test(a: Object) = if a is\n//│ ║         \t                         ^^^^\n//│ ║  l.123: \t  Cls then a.x\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.124: \t  else error\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── type variable `A` leaks out of its scope\n//│ ║  l.113: \tclass Cls[A] { fun x: A = x; fun g: A -> Int; fun g = g }\n//│ ╙──       \t          ^\n//│ fun test: (a: Object) -> anything\n\n:e // TODO\nfun test(a: Object) = if a is\n  Cls then a.g(a.x) // a.x : a.A ; a.g : a.A -> a.A\n  else 0\n//│ ╔══[ERROR] Type error in `case` expression\n//│ ║  l.138: \tfun test(a: Object) = if a is\n//│ ║         \t                         ^^^^\n//│ ║  l.139: \t  Cls then a.g(a.x) // a.x : a.A ; a.g : a.A -> a.A\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.140: \t  else 0\n//│ ║         \t^^^^^^^^\n//│ ╟── type variable `A` leaks out of its scope\n//│ ║  l.113: \tclass Cls[A] { fun x: A = x; fun g: A -> Int; fun g = g }\n//│ ╙──       \t          ^\n//│ fun test: (a: Object) -> Int\n\n\nclass Cls[out A] { fun x: A = x }\n//│ class Cls[A] {\n//│   constructor()\n//│   fun x: A\n//│ }\n\nfun test(a: Object) = if a is\n  Cls then a.x\n  else error\n//│ fun test: (a: Object) -> ??A\n\nfun test(a: Object) = if a is\n  Cls then a\n  else error\n//│ fun test: (a: Object) -> Cls[??A]\n\n:re\ntest(0).x\n//│ ??A\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n// class Expr[T] {\n//   constructor\n//     IntLit(n: Int) { T = Int }\n//     BoolLit(b: Bool) { T = Bool }\n// }\n// \n// fun foo(x) = if x is\n//    IntLit then x.n as x.T\n//    BoolLit then x.b\n// foo: (x: IntLit | BoolLit) -> x.T | Bool\n// \n// fun foo(x) = if x is\n//    IntLit then x.n as x.T\n//    BoolLit then x.b as x.T\n// foo: (x: IntLit | BoolLit) -> x.T\n//   <: Expr['a] -> 'a\n// \n// fun foo(x: Expr[T]): T = if x is\n//    IntLit then x.n // in Scala, compiler sees x.n : Int = x.T <: T\n//    BoolLit then x.b\n\nabstract class Expr[A]: (IntLit | BoolLit) {}\nclass IntLit() extends Expr[Int]\nclass BoolLit() extends Expr[Bool]\n//│ abstract class Expr[A]: BoolLit | IntLit\n//│ class IntLit() extends Expr\n//│ class BoolLit() extends Expr\n\nfun test(f: ((IntLit | BoolLit) -> Int)) =\n  f : Expr[anything] -> Int\n//│ fun test: (f: (BoolLit | IntLit) -> Int) -> Expr[anything] -> Int\n\n:e\nclass OopsLit() extends Expr[Bool]\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.211: \tclass OopsLit() extends Expr[Bool]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#OopsLit` does not match type `BoolLit | IntLit`\n//│ ╟── Note: constraint arises from union type:\n//│ ║  l.199: \tabstract class Expr[A]: (IntLit | BoolLit) {}\n//│ ╙──       \t                        ^^^^^^^^^^^^^^^^^^\n//│ class OopsLit() extends Expr\n\nfun test(a) = if a is\n  IntLit then 0\n  OopsLit then 1\n//│ fun test: (IntLit | OopsLit) -> (0 | 1)\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/ThisRefinedClasses.mls",
    "content": ":NewDefs\n\n\n\n// * I don't think it's a good idea to generate `this` refinements for classes,\n// * as this could easily lead to typos and delayed error reporting.\n// * Instead, we should require explicit `this` annotations by users when needed.\n\n\n:e\nclass Foo { fun test = this.x }\n//│ ╔══[ERROR] Type `#Foo` does not contain member `x`\n//│ ║  l.11: \tclass Foo { fun test = this.x }\n//│ ╙──      \t                           ^^\n//│ class Foo {\n//│   constructor()\n//│   fun test: error\n//│ }\n\n\n:e\nclass Foo(n: Int) { fun test = this.x }\n//│ ╔══[ERROR] Type `#Foo & {n: Int}` does not contain member `x`\n//│ ║  l.22: \tclass Foo(n: Int) { fun test = this.x }\n//│ ╙──      \t                                   ^^\n//│ class Foo(n: Int) {\n//│   fun test: error\n//│ }\n\n\n:e\nclass Foo<A>(n: A) { fun test = this.x }\n//│ ╔══[ERROR] Type `#Foo & {Foo#A = A, n: A}` does not contain member `x`\n//│ ║  l.32: \tclass Foo<A>(n: A) { fun test = this.x }\n//│ ╙──      \t                                    ^^\n//│ class Foo[A](n: A) {\n//│   fun test: error\n//│ }\n\n\n\n// TODO support: (treat `this` annot not like a term ascription)\nclass Foo {\n  this: { x: 'a }\n  // fun test = this.x\n}\n//│ ╔══[ERROR] Type `#Foo` does not contain member `x`\n//│ ║  l.44: \t  this: { x: 'a }\n//│ ╙──      \t          ^\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in type ascription:\n//│ ║  l.44: \t  this: { x: 'a }\n//│ ║        \t  ^^^^\n//│ ╟── type `{x: 'a}` does not match type `()`\n//│ ║  l.44: \t  this: { x: 'a }\n//│ ║        \t        ^^^^^^^^^\n//│ ╟── but it flows into expression in statement position with expected type `()`\n//│ ║  l.44: \t  this: { x: 'a }\n//│ ╙──      \t  ^^^^\n//│ class Foo {\n//│   constructor()\n//│ }\n\n\n// TODO\n// * All on one line:\nclass Test { this: { x: Int}; fun test = this.x }\n//│ ╔══[ERROR] Type `#Test` does not contain member `x`\n//│ ║  l.68: \tclass Test { this: { x: Int}; fun test = this.x }\n//│ ╙──      \t                                             ^^\n//│ ╔══[ERROR] Type `#Test` does not contain member `x`\n//│ ║  l.68: \tclass Test { this: { x: Int}; fun test = this.x }\n//│ ╙──      \t                     ^\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in type ascription:\n//│ ║  l.68: \tclass Test { this: { x: Int}; fun test = this.x }\n//│ ║        \t             ^^^^\n//│ ╟── type `{x: Int}` does not match type `()`\n//│ ║  l.68: \tclass Test { this: { x: Int}; fun test = this.x }\n//│ ║        \t                   ^^^^^^^^^\n//│ ╟── but it flows into expression in statement position with expected type `()`\n//│ ║  l.68: \tclass Test { this: { x: Int}; fun test = this.x }\n//│ ╙──      \t             ^^^^\n//│ class Test {\n//│   constructor()\n//│   fun test: error\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TraitParameters.mls",
    "content": ":NewDefs\n\n\n:e\ntrait Base1(x: Int)\n//│ ╔══[ERROR] trait parameters are not yet supported\n//│ ║  l.5: \ttrait Base1(x: Int)\n//│ ╙──     \t           ^^^^^^^^\n//│ trait Base1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TraitSignatures.mls",
    "content": ":NewDefs\n\n\n\ntrait C\ntrait Foo: C\n//│ trait C\n//│ trait Foo: C\n\nclass D() extends C, Foo\nD() : Foo\n//│ class D() extends C, Foo\n//│ Foo\n//│ res\n//│     = D {}\n\nclass E extends C\nclass F() extends E, Foo\nF() : Foo\n//│ class E extends C {\n//│   constructor()\n//│ }\n//│ class F() extends C, E, Foo\n//│ Foo\n//│ res\n//│     = F {}\n\nabstract class H extends Foo\nclass I() extends H, C\nI() : Foo\n//│ abstract class H: C extends Foo\n//│ class I() extends C, Foo, H\n//│ Foo\n//│ res\n//│     = I {}\n\n:e\nclass J extends Foo\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.38: \tclass J extends Foo\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#J` is not an instance of type `C`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.6: \ttrait Foo: C\n//│ ╙──     \t           ^\n//│ class J extends Foo {\n//│   constructor()\n//│ }\n\n\nclass C1\ntrait T1: C1\ntrait T2 extends T1\n//│ class C1 {\n//│   constructor()\n//│ }\n//│ trait T1: C1\n//│ trait T2: C1 extends T1\n\n:e\nclass C2 extends T1\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.61: \tclass C2 extends T1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#C2` is not an instance of type `C1`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.52: \ttrait T1: C1\n//│ ╙──      \t          ^^\n//│ class C2 extends T1 {\n//│   constructor()\n//│ }\n\n:e\nclass C2 extends T2\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.74: \tclass C2 extends T2\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#C2` is not an instance of type `C1`\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.52: \ttrait T1: C1\n//│ ╙──      \t          ^^\n//│ class C2 extends T1, T2 {\n//│   constructor()\n//│ }\n\nclass C2 extends C1, T2\n//│ class C2 extends C1, T1, T2 {\n//│   constructor()\n//│ }\n\n\n\n// * Interfaces that are \"callable\" are important to support for TS/JS interop\n\n\ndeclare trait Foo: ((x: Num) => Num) {\n  val y: Str\n}\n//│ declare trait Foo: (x: Num) -> Num {\n//│   val y: Str\n//│ }\n\n(f: Foo) => [f.y, f(0)]\n//│ (f: Foo) -> [Str, Num]\n//│ res\n//│     = [Function: res]\n\n\ndeclare trait FooPoly: forall 'a: (x: 'a) => 'a\n//│ declare trait FooPoly: forall 'a. (x: 'a) -> 'a\n\n(f: FooPoly) => [f(0), f(true)]\n//│ (f: FooPoly) -> [0, true]\n//│ res\n//│     = [Function: res]\n\n\n:e\nclass Oops(val y: Str) extends Foo\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.119: \tclass Oops(val y: Str) extends Foo\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#Oops & {y: Str}` is not a function\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.96: \tdeclare trait Foo: ((x: Num) => Num) {\n//│ ╙──      \t                   ^^^^^^^^^^^^^^^^^\n//│ class Oops(y: Str) extends Foo\n\n:e\nOops(\"\")(1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.130: \tOops(\"\")(1)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── application of type `Oops` is not a function\n//│ ║  l.130: \tOops(\"\")(1)\n//│ ╙──       \t^^^^^^^^\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: Oops(...) is not a function\n\n:e\nmodule Oops extends FooPoly\n//│ ╔══[ERROR] Type mismatch in type declaration:\n//│ ║  l.143: \tmodule Oops extends FooPoly\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── expression of type `#Oops` is not a function\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.109: \tdeclare trait FooPoly: forall 'a: (x: 'a) => 'a\n//│ ╙──       \t                                  ^^^^^^^\n//│ module Oops extends FooPoly\n\n:e\nOops(123)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.154: \tOops(123)\n//│ ║         \t^^^^^^^^^\n//│ ╟── reference of type `Oops` is not a function\n//│ ║  l.154: \tOops(123)\n//│ ╙──       \t^^^^\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: Oops is not a function\n\n:e\n(Oops : FooPoly)(123)\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.167: \t(Oops : FooPoly)(123)\n//│ ║         \t ^^^^\n//│ ╟── reference of type `Oops` is not a function\n//│ ╟── Note: constraint arises from function type:\n//│ ║  l.109: \tdeclare trait FooPoly: forall 'a: (x: 'a) => 'a\n//│ ║         \t                                  ^^^^^^^\n//│ ╟── from type reference:\n//│ ║  l.167: \t(Oops : FooPoly)(123)\n//│ ╙──       \t        ^^^^^^^\n//│ 123\n//│ res\n//│ Runtime error:\n//│   TypeError: Oops is not a function\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TrickyExtrusion2.mls",
    "content": ":NewDefs\n\n:DontDistributeForalls\n\n\n// * This test reproduces a situation where ?A <: ?B <: ?A and we extrude both ?A and ?B to a lower level.\n// * The goal was to check how the resulting approximants were related.\n// * It turns out that in the current implementation,\n// * since we (arbitrarily) only register upper bounds in this case (i.e., ?B ∈ UB(?A) and ?A ∈ UB(?B))\n// * then the lower approximants end up being subtypes of each other,\n// * which happens when they are extruded negatively and their corresponding bounds are copied,\n// * but the upper approximants remain unrelated.\n// * This is sound, but the extra lower approximants bounds are not necessary,\n// * and indeed the SuperF constraining specification will not add them.\n\n\nclass Invar[X, Y] { fun x: X -> X = id; fun y: Y -> Y = id }\n//│ class Invar[X, Y] {\n//│   constructor()\n//│   fun x: X -> X\n//│   fun y: Y -> Y\n//│ }\n\nfun bar[A, B]: () -> [A -> A, (B -> B) -> Invar[A, B]] = () => [id, _ => new Invar]\n//│ fun bar: forall 'A 'B. () -> ['A -> 'A, ('B -> 'B) -> Invar['A, 'B]]\n\n// :d\n:ns\nfun foo(x) =\n  let inner() =\n    let tmp = bar()\n    let r = tmp.1(tmp.0)\n    x(r)\n    r\n//│ fun foo: forall 'a 'b 'A 'B 'A0 'B0 'c. 'a -> ()\n//│   where\n//│     'a <: 'b -> 'c\n//│     'c <: ()\n//│     'b :> Invar[in 'A out 'A0, in 'B out 'B0]\n//│     'B0 :> 'B\n//│     'A0 :> 'A\n//│     'A <: 'B\n//│     'B <: 'A\n\n// * Above, 'A and 'B are the lower approximants and 'A0 and 'B0 are the upper approximants.\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TrickyGenericInheritance.mls",
    "content": ":NewDefs\n\n\n\ntrait T1[A] {\n  fun f: A -> A\n}\n//│ trait T1[A] {\n//│   fun f: A -> A\n//│ }\n\nclass C1 extends T1 {\n  fun f(x: Int) = x\n}\n//│ class C1 extends T1 {\n//│   constructor()\n//│   fun f: (x: Int) -> Int\n//│ }\n\nclass C1 extends T1['FigureItOut] {\n  fun f(x: Int) = x\n}\n//│ class C1 extends T1 {\n//│   constructor()\n//│   fun f: (x: Int) -> Int\n//│ }\n\nlet c1 = new C1\n//│ let c1: C1\n//│ c1\n//│    = C1 {}\n\nc1.f\n//│ (x: Int) -> Int\n//│ res\n//│     = [Function: f]\n\n(c1 : T1).f\n//│ ??A -> ??A0\n//│ res\n//│     = [Function: f]\n\n(c1 : T1['X]).f\n//│ Int -> Int\n//│ res\n//│     = [Function: f]\n\n:ns\n(c1 : T1).f\n//│ 'f\n//│   where\n//│     'f :> in ??A out ??A0 -> in ??A out ??A0\n//│ res\n//│     = [Function: f]\n\n:ns\n(c1 : T1['X]).f\n//│ 'f\n//│   where\n//│     'f :> 'X -> 'X\n//│     'X :> Int\n//│        <: 'FigureItOut\n//│     'FigureItOut :> Int\n//│                  <: 'X & Int\n//│ res\n//│     = [Function: f]\n\n:e\n(c1 : T1['X]).f(false)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.69: \t(c1 : T1['X]).f(false)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── reference of type `false` is not an instance of `Int`\n//│ ║  l.69: \t(c1 : T1['X]).f(false)\n//│ ║        \t                ^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.21: \t  fun f(x: Int) = x\n//│ ║        \t           ^^^\n//│ ╟── from type variable:\n//│ ║  l.69: \t(c1 : T1['X]).f(false)\n//│ ╙──      \t         ^^\n//│ Int | error | false\n//│ res\n//│     = false\n\n\n\n// * The more tricky case:\n\n// * TODO better error (cf. \"exposes no constructor\")\n:e\ntrait T2[A] {\n  fun f: A -> A\n  val r = C2().f(false)\n}\nclass C2 extends T2['FigureItOut] {\n  fun f(x: Int) = x\n}\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.94: \t  val r = C2().f(false)\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Class C2 cannot be instantiated as it exposes no constructor\n//│ ║  l.94: \t  val r = C2().f(false)\n//│ ╙──      \t          ^^\n//│ trait T2[A] {\n//│   fun f: A -> A\n//│   val r: error\n//│ }\n//│ class C2 extends T2 {\n//│   constructor()\n//│   fun f: (x: Int) -> Int\n//│   val r: error\n//│ }\n\n:e\ntrait T3[A] {\n  fun f: A -> A\n  val r = (C3() : T3['X]).f(false)\n}\nclass C3 extends T3['FigureItOut] {\n  fun f(x: Int) = x\n}\n//│ ╔══[ERROR] Method implementations in traits are not yet supported\n//│ ║  l.118: \t  val r = (C3() : T3['X]).f(false)\n//│ ╙──       \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Class C3 cannot be instantiated as it exposes no constructor\n//│ ║  l.118: \t  val r = (C3() : T3['X]).f(false)\n//│ ╙──       \t           ^^\n//│ trait T3[A] {\n//│   fun f: A -> A\n//│   val r: false\n//│ }\n//│ class C3 extends T3 {\n//│   constructor()\n//│   fun f: (x: Int) -> Int\n//│   val r: false\n//│ }\n\n:e // FIXME\nC3() : T3['X]\n//│ ╔══[ERROR] Construction of unparameterized class C3 should use the `new` keyword\n//│ ║  l.140: \tC3() : T3['X]\n//│ ╙──       \t^^\n//│ T3[Int]\n//│ res\n//│ Runtime error:\n//│   TypeError: Class constructor C3 cannot be invoked without 'new'\n\n\n\n// FIXME\nabstract class IO[A] {\n  fun test = Bind(this) : IO[Int]\n}\nclass Bind[A](underlying: IO[A]) extends IO[Int]\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.152: \tabstract class IO[A] {\n//│ ║         \t         ^^^^^^^^^^^^^\n//│ ║  l.153: \t  fun test = Bind(this) : IO[Int]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.154: \t}\n//│ ╙──       \t^\n//│ ╔══[ERROR] Type `Bind[?A]` does not contain member `IO#A`\n//│ ║  l.152: \tabstract class IO[A] {\n//│ ╙──       \t                  ^\n//│ abstract class IO[A] {\n//│   fun test: IO[Int]\n//│ }\n//│ class Bind[A](underlying: IO[A]) extends IO\n\n// FIXME\nabstract class IO[A] {\n  fun map[B]: (A -> B) -> IO[B] // * Removing this works...\n  fun map(f) = Map(this, f)\n  fun run: A\n}\nclass Map[A, B](underlying: IO[A], f: A -> B) extends IO[B] {\n  fun run: B = error\n}\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.172: \tabstract class IO[A] {\n//│ ║         \t         ^^^^^^^^^^^^^\n//│ ║  l.173: \t  fun map[B]: (A -> B) -> IO[B] // * Removing this works...\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.174: \t  fun map(f) = Map(this, f)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.175: \t  fun run: A\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.176: \t}\n//│ ╙──       \t^\n//│ ╔══[ERROR] Type `Map[?A, ?B]` does not contain member `IO#A`\n//│ ║  l.172: \tabstract class IO[A] {\n//│ ╙──       \t                  ^\n//│ abstract class IO[A] {\n//│   fun map: forall 'B. (A -> 'B) -> IO['B]\n//│   fun run: A\n//│ }\n//│ class Map[A, B](underlying: IO[A], f: A -> B) extends IO {\n//│   fun run: B\n//│ }\n\n// FIXME\nabstract class IO[A] {\n  fun bind[B]: (A -> IO[B]) -> IO[B] // * FIXME: causes cycle error\n  fun bind(f) = Bind(this, f)\n  fun run: A\n}\nclass Bind[A, B](underlying: IO[A], f: A -> IO[B]) extends IO[B] {\n  fun run = f(underlying.run).run\n}\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.203: \tabstract class IO[A] {\n//│ ║         \t         ^^^^^^^^^^^^^\n//│ ║  l.204: \t  fun bind[B]: (A -> IO[B]) -> IO[B] // * FIXME: causes cycle error\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.205: \t  fun bind(f) = Bind(this, f)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.206: \t  fun run: A\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.207: \t}\n//│ ╙──       \t^\n//│ ╔══[ERROR] Type `Bind[?A, ?B]` does not contain member `IO#A`\n//│ ║  l.203: \tabstract class IO[A] {\n//│ ╙──       \t                  ^\n//│ abstract class IO[A] {\n//│   fun bind: forall 'B. (A -> IO['B]) -> IO['B]\n//│   fun run: A\n//│ }\n//│ class Bind[A, B](underlying: IO[A], f: A -> IO[B]) extends IO {\n//│   fun run: B\n//│ }\n\n\n// TODO support\nabstract class IO[A] {\n  class Bind[B]() extends IO[B]\n}\n//│ ╔══[ERROR] Unhandled cyclic definition\n//│ ║  l.235: \tabstract class IO[A] {\n//│ ║         \t         ^^^^^^^^^^^^^\n//│ ║  l.236: \t  class Bind[B]() extends IO[B]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.237: \t}\n//│ ╙──       \t^\n//│ abstract class IO[A] {\n//│   class Bind[B]() extends IO\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TupleParamBlunder.mls",
    "content": ":NewDefs\n\n\n// * TODO fix the parsing of this tuple-taking function signature!\nfun f: [Int, Int] -> Int\nfun f(a, b) = a + b  // should not be a valid implementation\n//│ fun f: (Int, Int) -> Int\n//│ fun f: (Int, Int) -> Int\n\nfun f: (Int, Int) -> Int\nfun f(a, b) = a + b\n//│ fun f: (Int, Int) -> Int\n//│ fun f: (Int, Int) -> Int\n\n:e\nfun f: [Int, Int] => Int\nfun f(a, b) = a + b\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.17: \tfun f(a, b) = a + b\n//│ ║        \t    ^^^^^^^^^^^^^^^\n//│ ╟── type `[[Int, Int]]` does not match type `[?a, ?b]`\n//│ ║  l.16: \tfun f: [Int, Int] => Int\n//│ ║        \t       ^^^^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.17: \tfun f(a, b) = a + b\n//│ ╙──      \t     ^^^^^^\n//│ fun f: (Int, Int) -> Int\n//│ fun f: ([Int, Int]) -> Int\n\nfun f: (Int, Int) => Int\nfun f(a, b) = a + b\n//│ fun f: (Int, Int) -> Int\n//│ fun f: (Int, Int) -> Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Tuples.mls",
    "content": ":NewDefs\n\n\n// Tuple literals use square brackets.\nlet t = [0, 1, 2]\n//│ let t: [0, 1, 2]\n//│ t\n//│   = [ 0, 1, 2 ]\n\n\n// Tuple indices are zero-based.\nt.0\nt.1\nt.2\n//│ 2\n//│ res\n//│     = 0\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n\n\n// Tuple indices cannot be negative.\n:e\nt.-1\n//│ ╔══[ERROR] identifier not found: .-\n//│ ║  l.26: \tt.-1\n//│ ╙──      \t ^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol .-\n\n\n// Non-zero tuple indices cannot start with a zero.\n:e\nt.01\n//│ ╔══[ERROR] identifier not found: .\n//│ ║  l.37: \tt.01\n//│ ╙──      \t ^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol .\n\n\n// Out of bounds indices cause type errors.\n:e\nt.3\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.48: \tt.3\n//│ ║        \t^^^\n//│ ╟── tuple literal of type `{0: 0, 1: 1, 2: 2}` does not have field '3'\n//│ ║  l.5: \tlet t = [0, 1, 2]\n//│ ║       \t        ^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `{3: ?a}`\n//│ ║  l.48: \tt.3\n//│ ╙──      \t^\n//│ error\n//│ res\n//│     = undefined\n\n\n// Note that record fields can be integers with leading zeros.\n{ 000000: \"just zero\" }\n{ 042: \"cuarenta y dos\" }\n//│ {42: \"cuarenta y dos\"}\n//│ res\n//│     = { '0': 'just zero' }\n//│ res\n//│     = { '42': 'cuarenta y dos' }\n\n\n// Negative integer record fields are disallowed, which aligns with JavaScript.\n:pe\n:e\n{ -1: \"oh no\" }\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ╙──\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ╟── integer literal of type `-1` does not match type `\"oh no\"`\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.76: \t{ -1: \"oh no\" }\n//│ ╙──      \t      ^^^^^^^\n//│ {<error>: \"oh no\"}\n//│ res\n//│     = { '<error>': -1 }\n\n\n// Note that leading zeros of integer record fields are ignored.\n// And duplicate fields lead to errors.\n:e\n{ 0: \"oh\", 00: \"no\" }\n//│ ╔══[ERROR] Multiple declarations of field name 0 in record literal\n//│ ║  l.92: \t{ 0: \"oh\", 00: \"no\" }\n//│ ║        \t     ^^^^^^^^^^^^^^\n//│ ╟── Declared at\n//│ ║  l.92: \t{ 0: \"oh\", 00: \"no\" }\n//│ ║        \t  ^\n//│ ╟── Declared at\n//│ ║  l.92: \t{ 0: \"oh\", 00: \"no\" }\n//│ ╙──      \t           ^^\n//│ {0: \"oh\", 0: \"no\"}\n//│ res\n//│     = { '0': 'no' }\n\n\n// Fields that are integers or start with an underscore should not be used as name hints.\nfun f(x) = x._q\nfun g(x) = x._1\nfun h(x) = x.1\n//│ fun f: forall 'a. {_q: 'a} -> 'a\n//│ fun g: forall 'b. {_1: 'b} -> 'b\n//│ fun h: forall 'c. {1: 'c} -> 'c\n\n\n// Other fields should be used as name hints.\nfun p(x) = x.y\n//│ fun p: forall 'y. {y: 'y} -> 'y\n"
  },
  {
    "path": "shared/src/test/diff/nu/TypeAliases.mls",
    "content": ":NewDefs\n\n\ntype I = Int\n//│ type I = Int\n\nclass CI1\n//│ class CI1 {\n//│   constructor()\n//│ }\n\n// :e\ntype AI1 = Array[Int]\n//│ type AI1 = Array[Int]\n\ntype AI2 = Array<Int>\n//│ type AI2 = Array[Int]\n\n:e\ntype AI3(n) = Array[Int]\n//│ ╔══[ERROR] Type alias definitions cannot have value parameters\n//│ ║  l.20: \ttype AI3(n) = Array[Int]\n//│ ╙──      \t        ^^^\n//│ type AI3 = Array[Int]\n\n// :e\ntype AI3[A] = Array<A>\n//│ type AI3[A] = Array[A]\n\ntype AI4<A> = Array<A>\n//│ type AI4[A] = Array[A]\n\nlet r = 123\n//│ let r: 123\n//│ r\n//│   = 123\n\nr: I\n//│ I\n//│ res\n//│     = 123\n\nlet a = [r, r, r]\n//│ let a: [123, 123, 123]\n//│ a\n//│   = [ 123, 123, 123 ]\n\na : AI1\n//│ AI1\n//│ res\n//│     = [ 123, 123, 123 ]\n\na : AI2\n//│ AI2\n//│ res\n//│     = [ 123, 123, 123 ]\n\na : AI3[Int]\n//│ AI3[Int]\n//│ res\n//│     = [ 123, 123, 123 ]\n\na : AI4<Int>\n//│ AI4[Int]\n//│ res\n//│     = [ 123, 123, 123 ]\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TypeOps.mls",
    "content": ":NewDefs\n\n\ntype *[A, B] = [A, B]\n//│ type *[A, B] = [A, B]\n\n\nfun x : Int * Int\nfun x = [0, 1]\n//│ fun x: [0, 1]\n//│ fun x: *[Int, Int]\n\nfun x : Int * [Int]\nfun x = [0, [1]]\n//│ fun x: [0, [1]]\n//│ fun x: *[Int, [Int]]\n\nfun x : [Int] * Int\nfun x = [[0], 1]\n//│ fun x: [[0], 1]\n//│ fun x: *[[Int], Int]\n\n\ntype Id[A] = A\n//│ type Id[A] = A\n\n:e\nfun x: Id[Int, Int]\n//│ ╔══[ERROR] Wrong number of type arguments – expected 1, found 2\n//│ ║  l.28: \tfun x: Id[Int, Int]\n//│ ╙──      \t       ^^^^^^^^^^^^\n//│ fun x: Id[Int]\n\nfun x: Id[[Int, Int]]\n//│ fun x: Id[[Int, Int]]\n\nfun x: Id[[[Int, Int]]]\n//│ fun x: Id[[[Int, Int]]]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TypeSelections.mls",
    "content": ":NewDefs\n\n\nmodule M {\n  type T = Int -> Int\n  class C(n: Int)\n  fun mkC = C\n}\n//│ module M {\n//│   class C(n: Int)\n//│   type T = Int -> Int\n//│   fun mkC: (n: Int) -> C\n//│ }\n\nlet x: M.T = id\n//│ let x: Int -> Int\n//│ x\n//│   = [Function: id]\n\nfun foo(x: M.C) = x\n//│ fun foo: (x: C) -> C\n\n\nfoo(M.mkC(42))\n//│ C\n//│ res\n//│     = C {}\n\n\n:e\n42 : M.mkC\n//│ ╔══[ERROR] Illegal selection of value member in type position\n//│ ║  l.31: \t42 : M.mkC\n//│ ╙──      \t      ^^^^\n//│ error\n//│ res\n//│     = 42\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TypeVariables.mls",
    "content": ":NewDefs\n\n\nfun x: 'a -> 'a = succ\n//│ fun x: Int -> Int\n\n:e\nfun x: forall 'a: 'a -> 'a = succ\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.8: \tfun x: forall 'a: 'a -> 'a = succ\n//│ ║       \t                             ^^^^\n//│ ╟── type `'a` is not an instance of type `Int`\n//│ ║  l.8: \tfun x: forall 'a: 'a -> 'a = succ\n//│ ║       \t                  ^^\n//│ ╟── Note: quantified type variable 'a is defined at:\n//│ ║  l.8: \tfun x: forall 'a: 'a -> 'a = succ\n//│ ╙──     \t              ^^\n//│ fun x: forall 'a. 'a -> 'a\n\nfun x: [Int -> Int] = [id : forall 'a: 'a -> 'a]\n//│ fun x: [Int -> Int]\n\n:pe\n:e\nfun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,]\n//│ ╔══[PARSE ERROR] Unexpected end of square bracket section; an expression was expected here\n//│ ║  l.25: \tfun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,]\n//│ ╙──      \t                                                ^\n//│ ╔══[ERROR] type identifier not found: ,\n//│ ║  l.25: \tfun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,]\n//│ ╙──      \t                                       ^^^^^^^^^\n//│ fun x: [Int -> Int]\n\nfun x: [Int -> Int,] = [id : forall 'a: 'a -> 'a]\n//│ fun x: [Int -> Int]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TypingUnitTerms.mls",
    "content": ":NewDefs\n\n\n:e\nfun test =\n  let x = 0(0)\n  1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.6: \t  let x = 0(0)\n//│ ║       \t          ^^^^\n//│ ╟── integer literal of type `0` is not a function\n//│ ║  l.6: \t  let x = 0(0)\n//│ ╙──     \t          ^\n//│ fun test: 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/TypreMembers.mls",
    "content": ":NewDefs\n\n\nclass Test { type T = Int }\n//│ class Test {\n//│   constructor()\n//│   type T = Int\n//│ }\n\n1 : Test.T\n//│ Int\n//│ res\n//│     = 1\n\n\ntrait Test { type T = Int }\n//│ trait Test {\n//│   type T = Int\n//│ }\n\n:e\n1 : Test.T\n//│ ╔══[ERROR] Illegal prefix of type selection: Test\n//│ ║  l.22: \t1 : Test.T\n//│ ╙──      \t    ^^^^\n//│ error\n//│ res\n//│     = 1\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Unapply.mls",
    "content": "// *** Explicit unapply tests *** //\n\n:NewDefs\n\n\n// * Unapply's current compilation strategy:\n// function D ...\n// D.class = class D { #x; static unapply(self) { return [self.#x] } }\n// D.unapply = D.class.unapply\n\nclass D(x: Int)\n//│ class D(x: Int)\n\nD.unapply\n//│ forall '#x. (D & {#x: '#x}) -> ['#x]\n//│ res\n//│     = [Function: unapply]\n\nD.unapply(D(42))\n//│ [Int]\n//│ res\n//│     = [ 42 ]\n\n:e\nD.unapply({ x: 42 })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.25: \tD.unapply({ x: 42 })\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{x: 42}` does not have field '#x'\n//│ ║  l.25: \tD.unapply({ x: 42 })\n//│ ║        \t               ^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.11: \tclass D(x: Int)\n//│ ╙──      \t        ^\n//│ error | [nothing]\n//│ res\n//│ Runtime error:\n//│   TypeError: Cannot read private member #x from an object whose class did not declare it\n\nclass DT[T](x: T)\nDT.unapply\n//│ class DT[T](x: T)\n//│ forall '#x. (DT[anything] & {#x: '#x}) -> ['#x]\n//│ res\n//│     = [Function: unapply]\n\nDT.unapply(DT(42))\n//│ [42]\n//│ res\n//│     = [ 42 ]\n\n:e\nDT.unapply({ x: 42 })\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.53: \tDT.unapply({ x: 42 })\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{x: 42}` does not have field '#x'\n//│ ║  l.53: \tDT.unapply({ x: 42 })\n//│ ║        \t                ^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.40: \tclass DT[T](x: T)\n//│ ╙──      \t            ^\n//│ error | [nothing]\n//│ res\n//│ Runtime error:\n//│   TypeError: Cannot read private member #x from an object whose class did not declare it\n\n\n// * Currently, support for unapply is pretty broken: it accesses an _unqualified_ private field\n// * although the same private field may be defined in different classes of the same hierarchy,\n// * which leads to unsoundness:\n\nclass DS(x: Int) extends DT[Str](\"a\")\n//│ class DS(x: Int) extends DT\n\n// * Wrong type!\nDT.unapply(DS(42))\n//│ [Int]\n//│ res\n//│     = [ 'a' ]\n\n\n// * TODO improve `unapply` logic: currently it picks up shadowing fields/methods\n\nclass Foo(x: Int) {\n  val x = toString(x)\n}\n//│ class Foo(x: Int) {\n//│   val x: Str\n//│ }\n\n// * Current hack: use `scrut.#x` to access a private field while passing the typer...\nFoo.unapply\n//│ forall '#x. (Foo & {#x: '#x}) -> ['#x]\n//│ res\n//│     = [Function: unapply]\n\nFoo.unapply(Foo(123))\n//│ [Str]\n//│ res\n//│     = [ '123' ]\n\nif Foo(123) is Foo(a) then a\n//│ Str\n//│ res\n//│     = '123'\n\n\n\n// * Eventually we'll want to support this sort of overloading:\n:e\nfun D(x: Int) = {x}\nmodule D { fun unapply(a) = [a.x] }\n//│ ╔══[ERROR] Redefinition of 'D'\n//│ ║  l.113: \tmodule D { fun unapply(a) = [a.x] }\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun D: (x: Int) -> {x: Int}\n//│ module D {\n//│   fun unapply: forall 'x. {x: 'x} -> ['x]\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/UnaryMinus.mls",
    "content": ":NewDefs\n\n-1\n//│ -1\n//│ res\n//│     = -1\n\n- 1\n//│ -1\n//│ res\n//│     = -1\n\n1+1\n//│ Int\n//│ res\n//│     = 2\n\n1-3\n//│ Int\n//│ res\n//│     = -2\n\n3-1\n//│ Int\n//│ res\n//│     = 2\n\n1 - (3 - 5)\n//│ Int\n//│ res\n//│     = 3\n\n3 - 1\n//│ Int\n//│ res\n//│     = 2\n\n1 -1\n//│ Int\n//│ res\n//│     = 0\n\n1-1\n//│ Int\n//│ res\n//│     = 0\n\n1+ -1\n//│ Int\n//│ res\n//│     = 0\n\n1 - (1 - 1)\n//│ Int\n//│ res\n//│     = 1\n\n1 - 1\n//│ Int\n//│ res\n//│     = 0\n\n1 - - 1\n//│ Int\n//│ res\n//│     = 2\n\n1 - - - - 1\n//│ Int\n//│ res\n//│     = 2\n\nfun f() = 6\n-f()\n//│ fun f: () -> 6\n//│ Int\n//│ res\n//│     = -6\n\nfun inv(x: Int) = -x\ninv(15)\ninv(inv(15))\n//│ fun inv: (x: Int) -> Int\n//│ Int\n//│ res\n//│     = -15\n//│ res\n//│     = 15\n\ninv(f())\n//│ Int\n//│ res\n//│     = -6\n"
  },
  {
    "path": "shared/src/test/diff/nu/UndefMatching.mls",
    "content": ":NewDefs\n\n\n\nfun foo(x: 'a | undefined) = if x is undefined then error else x\n//│ fun foo: forall 'a. (x: Object & 'a & ~() | ()) -> 'a\n\n\nclass Abstract[A] {\n  // * Below, 'a in `foo` is basically `A & ~undefined`\n  \n  fun bar0(x: (A | undefined) & Object) =\n    if x is undefined then error else x\n  \n  fun bar1(x: (A | undefined) & Object) =\n    foo(x)\n  \n  fun bar2(x: (A | undefined) & Object) =\n    x : Object & 'a & ~undefined | undefined\n  \n  fun baz(a: A & Object) = [bar0(a), bar1(a), bar2(a)]\n}\n//│ class Abstract[A] {\n//│   constructor()\n//│   fun bar0: (x: Object & A | ()) -> (Object & A & ~())\n//│   fun bar1: (x: Object & A | ()) -> (Object & A & ~())\n//│   fun bar2: (x: Object & A | ()) -> (Object & A & ~() | ())\n//│   fun baz: (a: Object & A) -> [Object & A & ~(), Object & A & ~(), Object & A & ~() | ()]\n//│ }\n\n\n:e\nclass Abstract[A] {\n  fun bar(x: A & ~undefined | undefined) =\n    if x is undefined then error else x\n}\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.35: \t    if x is undefined then error else x\n//│ ║        \t       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `A & ~()` is not an instance of type `Object`\n//│ ║  l.34: \t  fun bar(x: A & ~undefined | undefined) =\n//│ ║        \t             ^^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Object`\n//│ ║  l.35: \t    if x is undefined then error else x\n//│ ╙──      \t       ^\n//│ class Abstract[A] {\n//│   constructor()\n//│   fun bar: (x: () | A & ~()) -> (A & ~())\n//│ }\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Uninstantiable.mls",
    "content": ":NewDefs\n\n\n:e\nInt\n//│ ╔══[ERROR] Class Int is abstract and cannot be instantiated\n//│ ║  l.5: \tInt\n//│ ╙──     \t^^^\n//│ ╔══[ERROR] Class Int cannot be instantiated as it exposes no constructor\n//│ ║  l.5: \tInt\n//│ ╙──     \t^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol Int\n\n:e\nInt()\n//│ ╔══[ERROR] Class Int is abstract and cannot be instantiated\n//│ ║  l.17: \tInt()\n//│ ╙──      \t^^^\n//│ ╔══[ERROR] Class Int cannot be instantiated as it exposes no constructor\n//│ ║  l.17: \tInt()\n//│ ╙──      \t^^^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol Int\n\n:e\nnew Int\n//│ ╔══[ERROR] Class Int is abstract and cannot be instantiated\n//│ ║  l.29: \tnew Int\n//│ ╙──      \t    ^^^\n//│ Int\n//│ Code generation encountered an error:\n//│   unresolved symbol Int\n\n\n// FIXME forbid statically\nmodule A extends Int\n//│ module A extends Int, Num\n//│ Code generation encountered an error:\n//│   unresolved parent Int.\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/UnionReordering.mls",
    "content": ":NewDefs\n:NoJS\n\n\ntype a = 0 | \"0\" | 2 | \"2\" | 10\n//│ type a = \"0\" | \"2\" | 0 | 10 | 2\n\ntype a = \"0\" | 0 | 2 | \"2\" | 10\n//│ type a = \"0\" | \"2\" | 0 | 10 | 2\n\n\nclass C[A]()\nclass D[A]()\n//│ class C[A]()\n//│ class D[A]()\n\nlet b = if true then C() else D()\n//│ let b: forall 'A 'A0. C['A] | D['A0]\n\nlet b = if true then D() else C()\n//│ let b: forall 'A 'A0. C['A] | D['A0]\n\n// :ds\nlet f(x) = if true then x else C()\n//│ let f: forall 'a. 'a -> (forall 'A. C['A] | 'a)\n\n\ntype ExtLang[T] = T -> T\ntype BaseLang[T] = T -> T\n//│ type ExtLang[T] = T -> T\n//│ type BaseLang[T] = T -> T\n\ntype RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang]\n//│ type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang]\n\n// * Notice that the type components are reordered to be the same:\ntype RegionLang1 = ExtLang[RegionLang] | BaseLang[RegionLang]\ntype RegionLang2 = ExtLang[C] | ExtLang[D]\n//│ type RegionLang1 = BaseLang[RegionLang] | ExtLang[RegionLang]\n//│ type RegionLang2 = ExtLang[out C[?] | D[?]]\n\n// * There is currently no deep reordering, though:\ntype RegionLang1 = ExtLang[C] -> Int & ExtLang[D] -> Str\ntype RegionLang2 = ExtLang[D] -> Int & ExtLang[C] -> Str\n//│ type RegionLang1 = ExtLang[C[?]] -> Int & ExtLang[D[?]] -> Str\n//│ type RegionLang2 = ExtLang[D[?]] -> Int & ExtLang[C[?]] -> Str\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Unit.mls",
    "content": ":NewDefs\n\n\n()\n//│ ()\n//│ res\n//│     = undefined\n\nfun x: ()\nfun x = ()\n//│ fun x: ()\n//│ fun x: ()\n\nx\n//│ ()\n//│ res\n//│     = undefined\n\n\n:e // we used to treat () as an empty array; should in fact be JS's `undefined`\nx : Array['a]\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.21: \tx : Array['a]\n//│ ║        \t^\n//│ ╟── type `()` does not match type `Array['a]`\n//│ ║  l.9: \tfun x: ()\n//│ ║       \t       ^^\n//│ ╟── but it flows into reference with expected type `Array['a]`\n//│ ║  l.21: \tx : Array['a]\n//│ ║        \t^\n//│ ╟── Note: constraint arises from applied type reference:\n//│ ║  l.21: \tx : Array['a]\n//│ ╙──      \t    ^^^^^^^^^\n//│ Array[nothing]\n//│ res\n//│     = undefined\n\nx : undefined\n//│ ()\n//│ res\n//│     = undefined\n\nfun x: ()\nfun x = undefined\n//│ fun x: ()\n//│ fun x: ()\n\n\n:e\nfun x: ()\nfun x = 1\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.51: \tfun x = 1\n//│ ║        \t    ^^^^^\n//│ ╟── integer literal of type `1` does not match type `()`\n//│ ║  l.51: \tfun x = 1\n//│ ║        \t        ^\n//│ ╟── but it flows into definition of method x with expected type `()`\n//│ ║  l.51: \tfun x = 1\n//│ ║        \t    ^^^^^\n//│ ╟── Note: constraint arises from literal type:\n//│ ║  l.50: \tfun x: ()\n//│ ╙──      \t       ^^\n//│ fun x: 1\n//│ fun x: ()\n\n\n(1)\n//│ 1\n//│ res\n//│     = 1\n\n// :pe // TODO?\n(1,)\n//│ 1\n//│ res\n//│     = 1\n\n(1,2)\n//│ 2\n//│ res\n//│     = 2\n\n(let x = 1)\n//│ ()\n//│ res\n//│     = undefined\n\n:pe\n(let x = 1 in)\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.90: \t(let x = 1 in)\n//│ ╙──      \t             ^\n//│ ()\n//│ res\n//│     = undefined\n\n(log(1))\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ 1\n\n:pe\n(log(1);)\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.106: \t(log(1);)\n//│ ╙──       \t       ^\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ 1\n\n:pe // support?\n(log(1); 2)\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.117: \t(log(1); 2)\n//│ ╙──       \t       ^\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ 1\n\n:pe // support?\n(log(1); ())\n//│ ╔══[PARSE ERROR] Unexpected semicolon here\n//│ ║  l.128: \t(log(1); ())\n//│ ╙──       \t       ^\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ 1\n\n(((log((())))))\n//│ ()\n//│ res\n//│     = undefined\n//│ // Output\n//│ undefined\n\n\n\n(1, 2)\n//│ 2\n//│ res\n//│     = 2\n\n\nx => x\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: res]\n\n(x) => x\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = [Function: res]\n\n(x, y) => x + y\n//│ (Int, Int) -> Int\n//│ res\n//│     = [Function: res]\n\n\n(1, 2) => 3\n//│ (1, 2) -> 3\n//│ res\n//│     = [Function: res]\n\n\n1 => (2, 3)\n//│ 1 -> 3\n//│ res\n//│     = [Function: res]\n\n\nfun f(x, y) = x + y\n//│ fun f: (Int, Int) -> Int\n\nf(1, 2)\n//│ Int\n//│ res\n//│     = 3\n\nf of 1, 2\n//│ Int\n//│ res\n//│     = 3\n\n:e\nf of (1, 2)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.195: \tf of (1, 2)\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── argument of type `[?a]` does not match type `[?b, ?c]`\n//│ ║  l.195: \tf of (1, 2)\n//│ ║         \t     ^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.181: \tfun f(x, y) = x + y\n//│ ╙──       \t     ^^^^^^\n//│ Int | error\n//│ res\n//│     = NaN\n\n\n\n0; 0\n//│ 0\n//│ res\n//│     = 0\n//│ res\n//│     = 0\n\n:w\nfun f =\n  0; 0\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.220: \t  0; 0\n//│ ╙──       \t  ^\n//│ fun f: 0\n\n:w\nfun f =\n  succ(0); 0\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in application:\n//│ ║  l.228: \t  succ(0); 0\n//│ ║         \t  ^^^^^^^\n//│ ╙── application of type `Int` does not match type `()`\n//│ fun f: 0\n\nfun f =\n  discard(succ(0)); 0\n//│ fun f: 0\n\nfun f =\n  discard of succ(0); 0\n//│ fun f: 0\n\nfun f =\n  let _ = succ(0); 0\n//│ fun f: 0\n\nfun f =\n  succ(0), 0\n//│ fun f: 0\n\n\nx => x; ()\n//│ ()\n//│ res\n//│     = [Function: res]\n//│ res\n//│     = undefined\n\nx => x; ()\n//│ ()\n//│ res\n//│     = [Function: res]\n//│ res\n//│     = undefined\n\n:w\nfun f =\n  x => x; ()\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.270: \t  x => x; ()\n//│ ╙──       \t  ^^^^^^\n//│ fun f: ()\n\nfun f =\n  discard of x => x; ()\n//│ fun f: ()\n\n:w\nfun f =\n  x => x\n  ()\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.282: \t  x => x\n//│ ╙──       \t  ^^^^^^\n//│ fun f: ()\n\n\n:w\nmodule Test {\n  123\n}\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.292: \t  123\n//│ ╙──       \t  ^^^\n//│ module Test\n\n:w\nmodule Test {\n  123\n  456\n}\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.301: \t  123\n//│ ╙──       \t  ^^^\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.302: \t  456\n//│ ╙──       \t  ^^^\n//│ module Test\n\n:w\nmodule Test {\n  x => x\n}\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.314: \t  x => x\n//│ ╙──       \t  ^^^^^^\n//│ module Test\n\n\n\n:e\nfun foo =\n  let tmp = 0\nfoo + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.326: \tfoo + 1\n//│ ║         \t^^^^^^^\n//│ ╟── definition of method foo of type `()` is not an instance of type `Int`\n//│ ║  l.324: \tfun foo =\n//│ ║         \t    ^^^^^\n//│ ║  l.325: \t  let tmp = 0\n//│ ║         \t^^^^^^^^^^^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.326: \tfoo + 1\n//│ ╙──       \t^^^\n//│ fun foo: ()\n//│ Int | error\n//│ res\n//│     = NaN\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/UserDefinedAnnotations.mls",
    "content": ":NewDefs\n\nmodule tailrec2 extends Annotation\n//│ module tailrec2 extends Annotation\n\n@tailrec2\nfun foo = 0\n//│ fun foo: 0\n\n\nclass tailrec2() extends Annotation\n//│ class tailrec2() extends Annotation\n\n:e\n@tailrec2\nfun foo = 0\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.16: \tfun foo = 0\n//│ ║        \t    ^^^^^^^\n//│ ╟── reference of type `() -> tailrec2` is not an instance of type `Annotation`\n//│ ║  l.15: \t@tailrec2\n//│ ╙──      \t ^^^^^^^^\n//│ fun foo: 0\n\n:e\n@hello\nfun foo = 0\n//│ ╔══[ERROR] identifier not found: hello\n//│ ║  l.26: \t@hello\n//│ ╙──      \t ^^^^^\n//│ fun foo: 0\n\nmodule hello extends Annotation\n//│ module hello extends Annotation\n\n@hello\nclass Triple[A](a: A, b: A, c: A)\n//│ class Triple[A](a: A, b: A, c: A)\n\n:e\n@helloa\nclass Triple[A](a: A, b: A, c: A)\n//│ ╔══[ERROR] identifier not found: helloa\n//│ ║  l.41: \t@helloa\n//│ ╙──      \t ^^^^^^\n//│ class Triple[A](a: A, b: A, c: A)\n\n@hello\nmodule dummy\n//│ module dummy\n\n:e\n@helloa\nmodule dummy\n//│ ╔══[ERROR] identifier not found: helloa\n//│ ║  l.53: \t@helloa\n//│ ╙──      \t ^^^^^^\n//│ module dummy\n\n:e // TODO: In the future, we should still support annotations that require a constructor.\n@tailrec2()\nfun foo = 0\n//│ ╔══[ERROR] Type mismatch in annotated undefined literal:\n//│ ║  l.61: \t@tailrec2()\n//│ ║        \t ^^^^^^^^^^\n//│ ╟── reference of type `() -> tailrec2` is not an instance of type `Annotation`\n//│ ║  l.61: \t@tailrec2()\n//│ ╙──      \t ^^^^^^^^\n//│ fun foo: 0\n//│ ()\n//│ res\n//│     = undefined\n"
  },
  {
    "path": "shared/src/test/diff/nu/ValSigs.mls",
    "content": ":NewDefs\n\n\nval x: Int\n//│ val x: Int\n//│ x\n//│   = <missing implementation>\n\n// * Note that this counts as a completely new `val` since it's in a new block\nval x = \"hi\"\n//│ val x: \"hi\"\n//│ x\n//│   = 'hi'\n\n\nval x: Int\nval x = 1\n//│ val x: 1\n//│ val x: Int\n//│ x\n//│   = <missing implementation>\n//│ x\n//│   = 1\nval x = 1\n//│ val x: 1\n//│ x\n//│   = 1\n\nx\n//│ 1\n//│ res\n//│     = 1\n\n\n:e\nval x: Int\nval x = \"oops\"\n//│ ╔══[ERROR] Type mismatch in definition:\n//│ ║  l.37: \tval x = \"oops\"\n//│ ║        \t    ^^^^^^^^^^\n//│ ╟── string literal of type `\"oops\"` is not an instance of type `Int`\n//│ ║  l.37: \tval x = \"oops\"\n//│ ║        \t        ^^^^^^\n//│ ╟── but it flows into definition of value x with expected type `Int`\n//│ ║  l.37: \tval x = \"oops\"\n//│ ║        \t    ^^^^^^^^^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.36: \tval x: Int\n//│ ╙──      \t       ^^^\n//│ val x: \"oops\"\n//│ val x: Int\n//│ x\n//│   = <missing implementation>\n//│ x\n//│   = 'oops'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Vals.mls",
    "content": ":NewDefs\n\n\nval a = 1\nval b = a + 1\n//│ val a: 1\n//│ val b: Int\n//│ a\n//│   = 1\n//│ b\n//│   = 2\n\n\n// :e // FIXME should not type check\n:ge\nval c = d + 1\nval d = 1\n//│ val c: Int\n//│ val d: 1\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding d\n\n\n// :e // FIXME should not type check\n:ge\nval a = a\n//│ val a: nothing\n//│ Code generation encountered an error:\n//│   unguarded recursive use of by-value binding a\n\n\nval f(x) = x\n//│ val f: forall 'a. 'a -> 'a\n//│ f\n//│   = [Function: f]\n\nf(123)\n//│ 123\n//│ res\n//│     = 123\n\n\nmodule M {\n  let tmp = 2\n  val f(x) = x + tmp\n}\n//│ module M {\n//│   val f: Int -> Int\n//│   let tmp: 2\n//│ }\n\nM.f(123)\n//│ Int\n//│ res\n//│     = 125\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Varargs.mls",
    "content": ":NewDefs\n\n\n// * Built-in vararg\n\n:js\njoin\n//│ (...Array[Str]) -> Str\n//│ // Prelude\n//│ function join(...xs) {\n//│   return xs.join(\"\");\n//│ }\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ res = join;\n//│ // End of generated code\n//│ res\n//│     = [Function: join]\n\njoin(\"Hello\", \",\", \" \", \"World\", \"!\")\n//│ Str\n//│ res\n//│     = 'Hello, World!'\n\n\n// * TODO It's currently not possible to define vararg-taking functions manually...\n\n:pe\n:e\nfun test(...xs) = xs.length\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.32: \tfun test(...xs) = xs.length\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] identifier not found: xs\n//│ ║  l.32: \tfun test(...xs) = xs.length\n//│ ╙──      \t                  ^^\n//│ fun test: () -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol xs\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/Virtual.mls",
    "content": ":NewDefs\n\nclass Foo() {\n  virtual fun f(x: Int) = x + 1\n  val g: Int = 0\n}\n//│ class Foo() {\n//│   fun f: (x: Int) -> Int\n//│   val g: Int\n//│ }\n\nclass Bar() extends Foo {\n  fun f(x: Int) = x + 2\n}\n//│ class Bar() extends Foo {\n//│   fun f: (x: Int) -> Int\n//│   val g: Int\n//│ }\n\nBar().f(40)\n//│ Int\n//│ res\n//│     = 42\n\n:e\nclass Baz() extends Bar() {\n  fun f(x: Int) = x + 3\n}\n//│ ╔══[ERROR] Value member 'f' is not virtual and cannot be overridden\n//│ ║  l.27: \t  fun f(x: Int) = x + 3\n//│ ║        \t      ^^^^^^^^^^^^^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.13: \t  fun f(x: Int) = x + 2\n//│ ╙──      \t      ^^^^^^^^^^^^^^^^^\n//│ class Baz() extends Bar, Foo {\n//│   fun f: (x: Int) -> Int\n//│   val g: Int\n//│ }\n\n:e\nclass Baz() extends Foo {\n  val g = 1\n}\n//│ ╔══[ERROR] Value member 'g' is not virtual and cannot be overridden\n//│ ║  l.42: \t  val g = 1\n//│ ║        \t      ^^^^^\n//│ ╟── Originally declared here:\n//│ ║  l.5: \t  val g: Int = 0\n//│ ╙──     \t      ^^^^^^^^^^\n//│ class Baz() extends Foo {\n//│   fun f: (x: Int) -> Int\n//│   val g: 1\n//│ }\n\nmixin X {\n  fun f(x) = x + 42\n}\nmixin XX {\n  fun f(x) = super.f(x) + 42\n}\nclass T() extends X, XX\n//│ mixin X() {\n//│   fun f: Int -> Int\n//│ }\n//│ mixin XX() {\n//│   super: {f: 'a -> Int}\n//│   fun f: 'a -> Int\n//│ }\n//│ class T() {\n//│   fun f: Int -> Int\n//│ }\n\nT().f(0 - 42)\n//│ Int\n//│ res\n//│     = 42\n\nabstract class M1() {\n  val foo: Str\n}\nclass M2(s: Str) extends M1 {\n  val foo = s\n}\nM2(\"foo\").foo\n//│ abstract class M1() {\n//│   val foo: Str\n//│ }\n//│ class M2(s: Str) extends M1 {\n//│   val foo: Str\n//│ }\n//│ Str\n//│ res\n//│     = 'foo'\n\nclass U() {\n  fun f: Int -> Int\n  fun f(x) = x + 1\n}\n//│ class U() {\n//│   fun f: Int -> Int\n//│ }\n\n:e\nclass V1() {\n  virtual val x = 42\n  fun foo = x // unqualified access!\n}\n//│ ╔══[ERROR] Unqualified access to virtual member x\n//│ ║  l.106: \t  fun foo = x // unqualified access!\n//│ ║         \t      ^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.105: \t  virtual val x = 42\n//│ ╙──       \t              ^^^^^^\n//│ class V1() {\n//│   fun foo: 42\n//│   val x: 42\n//│ }\n\nclass V2() {\n  val x: Int\n  virtual val x = 42\n  fun foo: Int = this.x\n}\n//│ class V2() {\n//│   fun foo: Int\n//│   val x: Int\n//│ }\n\n\n:e\nclass C() {\n  virtual fun x : Int\n  fun x = 1\n  fun foo0 = x // should error\n}\nC().x\n//│ ╔══[ERROR] Unqualified access to virtual member x\n//│ ║  l.134: \t  fun foo0 = x // should error\n//│ ║         \t      ^^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.133: \t  fun x = 1\n//│ ╙──       \t      ^^^^^\n//│ class C() {\n//│   fun foo0: 1\n//│   fun x: Int\n//│ }\n//│ Int\n//│ res\n//│     = 1\n\nmodule D extends C {\n  fun x = 2\n}\nD.x\n//│ module D extends C {\n//│   fun foo0: 1\n//│   fun x: 2\n//│ }\n//│ 2\n//│ res\n//│     = 2\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/WeirdDefs.mls",
    "content": ":NewDefs\n\n\nfun fst[x, _] = error : x -> x\n//│ fun fst: forall 'x. 'x -> 'x\n\n:e\nfun fst[x, _] = x\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.8: \tfun fst[x, _] = x\n//│ ╙──     \t                ^\n//│ fun fst: error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/WeirdUnions.mls",
    "content": ":NewDefs\n\n\n\nfun f: Str | [Str, Int]\n//│ fun f: Str | [Str, Int]\n\nfun f: [Str] | [Str, Int]\n//│ fun f: Array[Int | Str] & {0: Str}\n\nfun f: (Str | [Str, Int])\n//│ fun f: Str | [Str, Int]\n\n:e\nfun f: Str | (Str, Int)\n//│ ╔══[ERROR] type identifier not found: ,\n//│ ║  l.15: \tfun f: Str | (Str, Int)\n//│ ╙──      \t             ^^^^^^^^^^\n//│ fun f: Str | error\n\n\nfun f: Str | ([Str, Int])\n//│ fun f: Str | [Str, Int]\n\n:e\nfun f: Str | ((Str, Int))\n//│ ╔══[ERROR] type identifier not found: ,\n//│ ║  l.26: \tfun f: Str | ((Str, Int))\n//│ ╙──      \t             ^^^^^^^^^^^^\n//│ fun f: Str | error\n\n\n\n// * This type merges the input tuples, resulting in the union seen above:\nfun f: (Str => Str) & ((Str, Int) => Str)\n//│ fun f: (...Array[Int | Str] & {0: Str}) -> Str\n\nf(\"abc\", \"abc\")\n//│ Str\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\n\n// * Note: the merge doesn't happen when the result type is different...\nfun f: (Str => Str) & ((Str, Int) => Int)\n//│ fun f: Str -> Str & (Str, Int) -> Int\n\n// * ...resulting in approximation at call sites (we don't handle overloading)\nf(\"abc\", \"abc\")\n//│ Int | Str\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\nf(\"abcabc\")\n//│ Int | Str\n//│ res\n//│     = <no result>\n//│       f is not implemented\n\n\n\n// * Mismatched argument list sizes yields surprising results:\nlet r = if true then id else (x, y) => [y, x]\n//│ let r: (...nothing) -> [nothing, nothing]\n//│ r\n//│   = [Function: id]\n\n:e // * Expected: the function is uncallable until we implement syntax `r(...error)`\nr(error)\nr(error, error)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.71: \tr(error)\n//│ ║        \t^^^^^^^^\n//│ ╟── argument of type `[nothing]` does not match type `[?a, ?b]`\n//│ ║  l.71: \tr(error)\n//│ ║        \t ^^^^^^^\n//│ ╟── Note: constraint arises from tuple literal:\n//│ ║  l.65: \tlet r = if true then id else (x, y) => [y, x]\n//│ ╙──      \t                              ^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.72: \tr(error, error)\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── argument list of type `[nothing, nothing]` does not match type `[?a]`\n//│ ║  l.72: \tr(error, error)\n//│ ╙──      \t ^^^^^^^^^^^^^^\n//│ error | [nothing, nothing]\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\n// * Note: the correct version:\nlet r = if true then id else ([x, y]) => [y, x]\n//│ let r: forall 'a 'b 'c. (['a, 'b] & 'c) -> (['b, 'a] | 'c)\n//│ r\n//│   = [Function: id]\n\nr of [0, 1]\n//│ [0 | 1, 0 | 1]\n//│ res\n//│     = [ 0, 1 ]\n\n// Also currently parses the same:\nlet r = if true then id else [x, y] => [y, x]\n//│ let r: forall 'a 'b 'c. (['a, 'b] & 'c) -> (['b, 'a] | 'c)\n//│ r\n//│   = [Function: id]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/With.mls",
    "content": ":NewDefs\n\n\n{} with {}\n//│ anything\n//│ res\n//│     = {}\n\n{x: 1} with {y: 2}\n//│ {x: 1, y: 2}\n//│ res\n//│     = { x: 1, y: 2 }\n\n{x: 1} with {x: 2}\n//│ {x: 2}\n//│ res\n//│     = { x: 2 }\n\n\n:pe\n{x: 1} with 123\n//│ ╔══[PARSE ERROR] record literal expected here; found integer literal\n//│ ║  l.21: \t{x: 1} with 123\n//│ ╙──      \t            ^^^\n//│ {x: 1}\n//│ res\n//│     = { x: 1 }\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/i180.mls",
    "content": ":NewDefs\n\n\nfun (++) stringConcat(a, b) = concat(a)(b)\n//│ fun (++) stringConcat: (Str, Str) -> Str\n\ntype List[out A] = Cons[A] | Nil\nclass Cons[out A](head: A, tail: List[A]) {\n  fun join(sep: Str): Str\n  fun join(sep) =\n    if tail is\n      Nil then toString(head)\n      Cons(x, Nil) then toString(head) ++ sep ++ toString(x)\n      Cons(x, xs) then toString(head) ++ sep ++ toString(x) ++ sep ++ xs.join(sep)\n}\nmodule Nil {\n  fun join(sep: Str): Str = \"\"\n  fun contains(x): Bool = false\n}\n//│ type List[A] = Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A]) {\n//│   fun join: (sep: Str) -> Str\n//│ }\n//│ module Nil {\n//│   fun contains: anything -> Bool\n//│   fun join: (sep: Str) -> Str\n//│ }\n\n\nfun (::) cons[A](x: A, xs: List[A]): List[A] = Cons(x, xs)\n//│ fun (::) cons: forall 'A. (x: 'A, xs: List['A]) -> List['A]\n\n(1 :: Nil).join(\", \")\n(1 :: (2 :: Nil)).join(\", \")\n(1 :: (2 :: (3 :: Nil))).join(\", \")\n(1 :: (2 :: (3 :: (4 :: Nil)))).join(\", \")\n(1 :: (2 :: (3 :: (4 :: (5 :: Nil))))).join(\", \")\n//│ Str\n//│ res\n//│     = '1'\n//│ res\n//│     = '1, 2'\n//│ res\n//│     = '1, 2, 3'\n//│ res\n//│     = '1, 2, 3, 4'\n//│ res\n//│     = '1, 2, 3, 4, 5'\n\n\nfun (:-) listExclude(xs, x) =\n  if xs is\n    Nil then Nil\n    Cons(x', xs') and\n      x === x' then xs' :- x\n      else x' :: (xs' :- x)\n//│ fun (:-) listExclude: forall 'A. (Cons['A] | Nil, Eql['A]) -> (Nil | List['A])\n\n(Nil :- 0).join(\", \")\n((0 :: Nil) :- 0).join(\", \")\n((1 :: Nil) :- 0).join(\", \")\n((1 :: (2 :: Nil)) :- 0).join(\", \")\n//│ Str\n//│ res\n//│     = ''\n//│ res\n//│     = ''\n//│ res\n//│     = '1'\n//│ res\n//│     = '1, 2'\n\n\n(\"x\" :: Nil).join(\", \")\n//│ Str\n//│ res\n//│     = 'x'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/i191.mls",
    "content": ":NewDefs\n\n\nclass demo() { constructor(param1: Int) }\nval invalidConstruction = new demo(1)\n//│ class demo() {\n//│   constructor(param1: Int)\n//│ }\n//│ val invalidConstruction: demo\n//│ invalidConstruction\n//│                     = demo {}\n\n:e\nclass demo() { constructor(param1: Int) }\nval invalidConstruction = demo()\n//│ ╔══[ERROR] Construction of class with auxiliary constructor should use the `new` keyword\n//│ ║  l.15: \tval invalidConstruction = demo()\n//│ ╙──      \t                          ^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.15: \tval invalidConstruction = demo()\n//│ ║        \t                          ^^^^^^\n//│ ╟── argument of type `[]` does not match type `[param1: Int]`\n//│ ║  l.15: \tval invalidConstruction = demo()\n//│ ╙──      \t                              ^^\n//│ class demo() {\n//│   constructor(param1: Int)\n//│ }\n//│ val invalidConstruction: demo | error\n//│ invalidConstruction\n//│                     = demo {}\n\n:e\nval invalidConstruction = demo(1)\n//│ ╔══[ERROR] Construction of class with auxiliary constructor should use the `new` keyword\n//│ ║  l.33: \tval invalidConstruction = demo(1)\n//│ ╙──      \t                          ^^^^\n//│ val invalidConstruction: demo\n//│ invalidConstruction\n//│                     = demo {}\n\n:e\nval invalidConstruction = new demo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.42: \tval invalidConstruction = new demo\n//│ ║        \t                              ^^^^\n//│ ╟── argument list of type `[]` does not match type `[param1: Int]`\n//│ ║  l.42: \tval invalidConstruction = new demo\n//│ ╙──      \t                                  ^\n//│ val invalidConstruction: demo | error\n//│ invalidConstruction\n//│                     = demo {}\n\n:e\nclass demo { constructor(param1: Int) }\nval invalidConstruction = demo()\n//│ ╔══[ERROR] Construction of unparameterized class demo should use the `new` keyword\n//│ ║  l.55: \tval invalidConstruction = demo()\n//│ ╙──      \t                          ^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.55: \tval invalidConstruction = demo()\n//│ ║        \t                          ^^^^^^\n//│ ╟── argument of type `[]` does not match type `[param1: Int]`\n//│ ║  l.55: \tval invalidConstruction = demo()\n//│ ╙──      \t                              ^^\n//│ class demo {\n//│   constructor(param1: Int)\n//│ }\n//│ val invalidConstruction: demo | error\n//│ invalidConstruction\n//│ Runtime error:\n//│   TypeError: Class constructor demo cannot be invoked without 'new'\n\n:e\nval invalidConstruction = demo\n//│ ╔══[ERROR] Construction of unparameterized class demo should use the `new` keyword\n//│ ║  l.74: \tval invalidConstruction = demo\n//│ ╙──      \t                          ^^^^\n//│ val invalidConstruction: (param1: Int) -> demo\n//│ invalidConstruction\n//│                     = [class demo]\n\n:e\nval invalidConstruction = new demo\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.83: \tval invalidConstruction = new demo\n//│ ║        \t                              ^^^^\n//│ ╟── argument list of type `[]` does not match type `[param1: Int]`\n//│ ║  l.83: \tval invalidConstruction = new demo\n//│ ╙──      \t                                  ^\n//│ val invalidConstruction: demo | error\n//│ invalidConstruction\n//│                     = demo {}\n\nval invalidConstruction = new demo(1)\n//│ val invalidConstruction: demo\n//│ invalidConstruction\n//│                     = demo {}\n\n:e\nval invalidConstruction = demo()\n//│ ╔══[ERROR] Construction of unparameterized class demo should use the `new` keyword\n//│ ║  l.100: \tval invalidConstruction = demo()\n//│ ╙──       \t                          ^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.100: \tval invalidConstruction = demo()\n//│ ║         \t                          ^^^^^^\n//│ ╟── argument of type `[]` does not match type `[param1: Int]`\n//│ ║  l.100: \tval invalidConstruction = demo()\n//│ ╙──       \t                              ^^\n//│ val invalidConstruction: demo | error\n//│ invalidConstruction\n//│ Runtime error:\n//│   TypeError: Class constructor demo cannot be invoked without 'new'\n\n\nclass demo(x: Int) {\n  constructor(param1: Int, param2: Int) {\n    log(param1)\n    log(param2)\n    x = param1*param2\n  }\n}\n//│ class demo(x: Int) {\n//│   constructor(param1: Int, param2: Int)\n//│ }\n\nval validConstruction = new demo(5, 10)\n//│ val validConstruction: demo\n//│ validConstruction\n//│                   = demo {}\n//│ // Output\n//│ 5\n//│ 10\n\n:e\nval invalidConstruction = demo(5)\n//│ ╔══[ERROR] Construction of class with auxiliary constructor should use the `new` keyword\n//│ ║  l.136: \tval invalidConstruction = demo(5)\n//│ ╙──       \t                          ^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.136: \tval invalidConstruction = demo(5)\n//│ ║         \t                          ^^^^^^^\n//│ ╟── argument of type `[5]` does not match type `[param1: Int, param2: Int]`\n//│ ║  l.136: \tval invalidConstruction = demo(5)\n//│ ╙──       \t                              ^^^\n//│ val invalidConstruction: demo | error\n//│ invalidConstruction\n//│                     = demo {}\n//│ // Output\n//│ 5\n//│ undefined\n\n:e\nval invalidConstruction = new demo(5)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.154: \tval invalidConstruction = new demo(5)\n//│ ║         \t                          ^^^^^^^^^^^\n//│ ╟── argument list of type `[5]` does not match type `[param1: Int, param2: Int]`\n//│ ║  l.154: \tval invalidConstruction = new demo(5)\n//│ ╙──       \t                                  ^^^\n//│ val invalidConstruction: demo | error\n//│ invalidConstruction\n//│                     = demo {}\n//│ // Output\n//│ 5\n//│ undefined\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/repro0.mls",
    "content": ":NewDefs\n:NoJS\n\n\nclass Add[out E](val lhs: E)\nval add11 = Add(add11)\nmodule EvalAddLit {\n  fun eval(e: Add['A]) =\n    if e is Add then eval(e.lhs)\n}\nlet res = EvalAddLit.eval(add11)\n//│ class Add[E](lhs: E)\n//│ val add11: 'E\n//│ module EvalAddLit {\n//│   fun eval: forall 'A. (e: 'A) -> nothing\n//│ }\n//│ let res: nothing\n//│ where\n//│   'A <: Add['A]\n//│   'E :> Add['E]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/repro1.mls",
    "content": ":NewDefs\n:NoJS\n\n\nclass Union[out Region](val a: Region)\n// class Union[Region](a: Region)\n//│ class Union[Region](a: Region)\n\nfun go(x) = Union(go(x))\nlet circles = go(2)\n//│ fun go: forall 'Region. anything -> 'Region\n//│ let circles: forall 'Region0. 'Region0\n//│ where\n//│   'Region0 :> Union['Region0]\n//│   'Region :> Union['Region]\n\n\nfun contains(a) =\n  if a is Union then contains(a.a)\n//│ fun contains: forall 'a. 'a -> nothing\n//│   where\n//│     'a <: Union['a]\n\ncontains(circles)\n//│ nothing\n\n\nmixin Contains {\n  fun contains(a) =\n    if a is Union then this.contains(a.a)\n}\n//│ mixin Contains() {\n//│   this: {contains: 'a -> 'b}\n//│   fun contains: Union['a] -> 'b\n//│ }\n\nmodule TestContains extends Contains\n//│ module TestContains {\n//│   fun contains: 'a -> nothing\n//│ }\n//│ where\n//│   'a <: Union['a]\n\nTestContains.contains(circles)\n//│ nothing\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/repro_EvalNegNeg.mls",
    "content": ":NewDefs\n\n\nclass Add<out E>(lhs: E, rhs: E)\nclass Lit(n: Int)\nclass Neg<out A>(expr: A)\n//│ class Add[E](lhs: E, rhs: E)\n//│ class Lit(n: Int)\n//│ class Neg[A](expr: A)\n\n\n// Note the inferred type because of current UCS limitation\nmixin EvalBase {\n  fun eval(e) =\n    if e is Neg(Neg(d)) then this.eval(d)\n    else if e is Neg(d) then 0 - this.eval(d)\n    else if e is\n      Lit(n) then n\n      Add(l, r) then this.eval(l) + this.eval(r)\n}\n//│ mixin EvalBase() {\n//│   this: {eval: 'a -> 'b & 'c -> Int}\n//│   fun eval: (Add['c] | Lit | Neg['c & (Neg['a] | Object & ~#Neg)]) -> (Int | 'b)\n//│ }\n\n// module TestLang extends EvalBase, EvalNeg\nmodule TestLang extends EvalBase\n//│ module TestLang {\n//│   fun eval: 'a -> Int\n//│ }\n//│ where\n//│   'a <: Add['a] | Lit | Neg['a & (Neg['a] | Object & ~#Neg)]\n\n\nfun mk(n) = if n is\n  0 then Lit(0)\n  1 then Neg(mk(n))\n  _ then Add(mk(n), mk(n))\n//│ fun mk: forall 'a. Object -> (Lit | 'a)\n//│   where\n//│     'a :> Add[Lit | 'a] | Neg[Lit | 'a]\n\n:stats\nTestLang.eval(mk(0))\n//│ Int\n//│ res\n//│     = 0\n//│ constrain calls  : 254\n//│ annoying  calls  : 106\n//│ subtyping calls  : 1430\n\n\n"
  },
  {
    "path": "shared/src/test/diff/nu/repro_PolymorphicVariants.mls",
    "content": ":NewDefs\n\n// Test that reprduces subtle type simplification bug\n\nclass Cons[out A](head: A, tail: Cons[A] | Nil)\nmodule Nil\n//│ class Cons[A](head: A, tail: Cons[A] | Nil)\n//│ module Nil\n\nclass Abs[A](x: string, t: A)\nclass App[A](s: A, t: A)\n//│ class Abs[A](x: string, t: A)\n//│ class App[A](s: A, t: A)\n\nfun eval(sub, v) =\n  if v is\n    Abs(x, t) then\n      eval(Cons([error, error], Nil), error)\n      eval(Cons(error, sub), error)\n      error\n//│ fun eval: (Cons[anything] | Nil, Abs[anything]) -> nothing\n\nmixin EvalLambda {\n  fun eval(sub, v) =\n    if v is\n      Abs(x, t) then\n        this.eval(Cons([error, error], Nil), error)\n        this.eval(Cons([x, error], sub), error)\n        error\n}\n//│ mixin EvalLambda() {\n//│   this: {eval: (Cons[[string, nothing] | 'A], nothing) -> ()}\n//│   fun eval: (Cons['A] | Nil, Abs[anything]) -> nothing\n//│ }\n\n// * Note: this used to crash because of a current type simplification bug: analyze2 does not traverse TVs witht he correct PolMap\n// *  The original unreduced version in PolymorphicVariants.mls still crashes...\n// :ds\nmodule Test1 extends EvalLambda\n//│ module Test1 {\n//│   fun eval: (Cons[anything] | Nil, Abs[anything]) -> nothing\n//│ }\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Annot.mls",
    "content": "\n:p\n@hello\nfun hello(x) = \n    @a\n    @b\n    let rec x = @hello 2\n//│ |@|hello|↵|#fun| |hello|(|x|)| |#=| |→|@|a|↵|@|b|↵|#let| |#rec| |x| |#=| |@|hello| |2|←|\n//│ Parsed: {fun hello = (x,) => {let rec x = @hello 2}}\n//│ AST: TypingUnit(List(NuFunDef(None,Var(hello),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(x))))),Blk(List(NuFunDef(Some(true),Var(x),None,List(),Left(Ann(Var(hello),IntLit(2)))))))))))\n//│ Parsed: \n\n:p\n@tailrec 2\n//│ |@|tailrec| |2|\n//│ Parsed: {@tailrec 2}\n//│ AST: TypingUnit(List(Ann(Var(tailrec),IntLit(2))))\n//│ Parsed: \n\n:p\nif @hello true then 2 else 3\n//│ |#if| |@|hello| |true| |#then| |2| |#else| |3|\n//│ Parsed: {if (@hello true) then 2 else 3}\n//│ AST: TypingUnit(List(If(IfThen(Ann(Var(hello),Var(true)),IntLit(2)),Some(IntLit(3)))))\n//│ Parsed: \n\n:pe\nif @test x\n    is Foo then 2\n//│ |#if| |@|test| |x|→|is| |Foo| |#then| |2|←|\n//│ ╔══[PARSE ERROR] Unexpected annotation\n//│ ║  l.28: \tif @test x\n//│ ╙──      \t    ^^^^\n//│ Parsed: {if x ‹· is (Foo) then 2›}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Arrays.mls",
    "content": ":AllowParseErrors\n\n\n[]\n//│ |[||]|\n//│ Parsed: {[]}\n\n[1]\n//│ |[|1|]|\n//│ Parsed: {[1,]}\n\n[1,]\n//│ |[|1|,|]|\n//│ Parsed: {[1,]}\n\n[1, 2, 3]\n//│ |[|1|,| |2|,| |3|]|\n//│ Parsed: {[1, 2, 3,]}\n\n()\n//│ |(||)|\n//│ Parsed: {undefined}\n\n(1)\n//│ |(|1|)|\n//│ Parsed: {'(' 1 ')'}\n\n(1,)\n//│ |(|1|,|)|\n//│ Parsed: {'(' 1 ')'}\n\n(1, 2, 3)\n//│ |(|1|,| |2|,| |3|)|\n//│ Parsed: {,(1, ,(2, 3,),)}\n\n\n1\n//│ |1|\n//│ Parsed: {1}\n\n1,\n//│ |1|,|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.41: \t1,\n//│ ╙──      \t  ^\n//│ Parsed: {,(1, undefined,)}\n\n1, 2, 3\n//│ |1|,| |2|,| |3|\n//│ Parsed: {,(1, ,(2, 3,),)}\n\nf of 1, 2, 3\n//│ |f| |#of| |1|,| |2|,| |3|\n//│ Parsed: {f(1, 2, 3,)}\n\nf of\n  1, 2, 3\n//│ |f| |#of|→|1|,| |2|,| |3|←|\n//│ Parsed: {f(1, 2, 3,)}\n\nf of\n  1,\n  2,\n  3\n//│ |f| |#of|→|1|,|↵|2|,|↵|3|←|\n//│ Parsed: {f(1, 2, 3,)}\n\n\nlet arr = []\n//│ |#let| |arr| |#=| |[||]|\n//│ Parsed: {let arr = []}\n\nlet arr = [\n]\n//│ |#let| |arr| |#=| |[|↵|]|\n//│ Parsed: {let arr = []}\n\nlet arr =\n[\n]\n//│ |#let| |arr| |#=|↵|[|↵|]|\n//│ ╔══[PARSE ERROR] Unexpected newline in expression position\n//│ ║  l.78: \tlet arr =\n//│ ║        \t         ^\n//│ ║  l.79: \t[\n//│ ╙──      \t\n//│ Parsed: {let arr = []}\n\nlet arr = [\n  1\n]\n//│ |#let| |arr| |#=| |[|→|1|←|↵|]|\n//│ Parsed: {let arr = [1,]}\n\nlet arr = [\n  1, 2\n]\n//│ |#let| |arr| |#=| |[|→|1|,| |2|←|↵|]|\n//│ Parsed: {let arr = [1, 2,]}\n\nlet arr = [\n  1,\n  2\n]\n//│ |#let| |arr| |#=| |[|→|1|,|↵|2|←|↵|]|\n//│ Parsed: {let arr = [1, 2,]}\n\n// :pe\nf [1, 2, 3]\n//│ |f| |[|1|,| |2|,| |3|]|\n//│ Parsed: {f‹1, 2, 3›}\n\nf([1, 2, 3])\n//│ |f|(|[|1|,| |2|,| |3|]|)|\n//│ Parsed: {f([1, 2, 3,],)}\n\nf of [1, 2, 3]\n//│ |f| |#of| |[|1|,| |2|,| |3|]|\n//│ Parsed: {f([1, 2, 3,],)}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/BasicSyntax.mls",
    "content": ":AllowParseErrors\n\n1\n//│ |1|\n//│ Parsed: {1}\n\nf 1\n//│ |f| |1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.7: \tf 1\n//│ ╙──     \t^^^\n//│ Parsed: {f(1,)}\n\n()\n//│ |(||)|\n//│ Parsed: {undefined}\n\nf()\n//│ |f|(||)|\n//│ Parsed: {f()}\n\nf(1)\n//│ |f|(|1|)|\n//│ Parsed: {f(1,)}\n\nf (1)\n//│ |f| |(|1|)|\n//│ Parsed: {f(1,)}\n\nf of 1\n//│ |f| |#of| |1|\n//│ Parsed: {f(1,)}\n\n1 + 1\n//│ |1| |+| |1|\n//│ Parsed: {+(1,)(1,)}\n\nf 1 + 1\n//│ |f| |1| |+| |1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.38: \tf 1 + 1\n//│ ╙──      \t^^^^^^^\n//│ Parsed: {f(+(1,)(1,),)}\n\nf(1 + 1)\n//│ |f|(|1| |+| |1|)|\n//│ Parsed: {f(+(1,)(1,),)}\n\nf of 1 + 1\n//│ |f| |#of| |1| |+| |1|\n//│ Parsed: {f(+(1,)(1,),)}\n\nf(1) + 1\n//│ |f|(|1|)| |+| |1|\n//│ Parsed: {+(f(1,),)(1,)}\n\n1 2 3\n//│ |1| |2| |3|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.57: \t1 2 3\n//│ ╙──      \t  ^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.57: \t1 2 3\n//│ ╙──      \t^^^^^\n//│ Parsed: {1(2(3,),)}\n\n12  3\n//│ |12| |3|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.67: \t12  3\n//│ ╙──      \t^^^^^\n//│ Parsed: {12(3,)}\n\n3 + 2 4 - 1\n//│ |3| |+| |2| |4| |-| |1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.74: \t3 + 2 4 - 1\n//│ ╙──      \t    ^^^^^^^\n//│ Parsed: {+(3,)(2(-(4,)(1,),),)}\n\nfoo bar\n  baz 1\n  2 3\n//│ |foo| |bar|→|baz| |1|↵|2| |3|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.82: \t  baz 1\n//│ ╙──      \t  ^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.83: \t  2 3\n//│ ╙──      \t  ^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.81: \tfoo bar\n//│ ║        \t    ^^^\n//│ ║  l.82: \t  baz 1\n//│ ║        \t^^^^^^^\n//│ ║  l.83: \t  2 3\n//│ ╙──      \t^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.81: \tfoo bar\n//│ ║        \t^^^^^^^\n//│ ║  l.82: \t  baz 1\n//│ ║        \t^^^^^^^\n//│ ║  l.83: \t  2 3\n//│ ╙──      \t^^^^^\n//│ Parsed: {foo(bar({baz(1,); 2(3,)},),)}\n\nfoo bar\n  baz 1\n    2 3\n  4 v5\n//│ |foo| |bar|→|baz| |1|→|2| |3|←|↵|4| |v5|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.109: \t    2 3\n//│ ╙──       \t    ^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.108: \t  baz 1\n//│ ║         \t      ^\n//│ ║  l.109: \t    2 3\n//│ ╙──       \t^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.108: \t  baz 1\n//│ ║         \t  ^^^^^\n//│ ║  l.109: \t    2 3\n//│ ╙──       \t^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.110: \t  4 v5\n//│ ╙──       \t  ^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.107: \tfoo bar\n//│ ║         \t    ^^^\n//│ ║  l.108: \t  baz 1\n//│ ║         \t^^^^^^^\n//│ ║  l.109: \t    2 3\n//│ ║         \t^^^^^^^\n//│ ║  l.110: \t  4 v5\n//│ ╙──       \t^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.107: \tfoo bar\n//│ ║         \t^^^^^^^\n//│ ║  l.108: \t  baz 1\n//│ ║         \t^^^^^^^\n//│ ║  l.109: \t    2 3\n//│ ║         \t^^^^^^^\n//│ ║  l.110: \t  4 v5\n//│ ╙──       \t^^^^^^\n//│ Parsed: {foo(bar({baz(1(2(3,),),); 4(v5,)},),)}\n\nfoo of bar of\n  baz of 1 of\n    2 of 3\n  4 of v5\n//│ |foo| |#of| |bar| |#of|→|baz| |#of| |1| |#of|→|2| |#of| |3|←|↵|4| |#of| |v5|←|\n//│ Parsed: {foo(bar({baz(1(2(3,),),); 4(v5,)},),)}\n\nfoo\n  1\n//│ |foo|→|1|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.155: \tfoo\n//│ ║         \t^^^\n//│ ║  l.156: \t  1\n//│ ╙──       \t^^^\n//│ Parsed: {foo(1,)}\n\nfoo of\n  1\n//│ |foo| |#of|→|1|←|\n//│ Parsed: {foo(1,)}\n\nfoo\n  of 1\n//│ |foo|→|#of| |1|←|\n//│ Parsed: {foo(1,)}\n\nfoo\n  of 1, 2, 3\n//│ |foo|→|#of| |1|,| |2|,| |3|←|\n//│ Parsed: {foo(1, 2, 3,)}\n\nfoo\n  of (1, 2, 3)\n//│ |foo|→|#of| |(|1|,| |2|,| |3|)|←|\n//│ Parsed: {foo(,(1, ,(2, 3,),),)}\n\nfoo\n  of\n    1\n//│ |foo|→|#of|→|1|←|←|\n//│ Parsed: {foo(1,)}\n\n// TODO\nfoo\n  of 1\n  of 2\n//│ |foo|→|#of| |1|↵|#of| |2|←|\n//│ Parsed: {foo(1,)(2,)}\n\nfoo\n  of f\n    of 2\n//│ |foo|→|#of| |f|→|#of| |2|←|←|\n//│ Parsed: {foo(f(2,),)}\n\nfoo\n    of 1\n  of 2\n//│ |foo|→|#of| |1|←|→|#of| |2|←|\n//│ Parsed: {foo(1,)(2,)}\n\n  \n//│ | |\n//│ Parsed: {}\n\n  1\n//│ | |1|\n//│ Parsed: {1}\n\n  \n  1\n//│ | |→|1|←|\n//│ Parsed: {{1}}\n\n(1)\n//│ |(|1|)|\n//│ Parsed: {'(' 1 ')'}\n\n(1\n//│ ╔══[PARSE ERROR] Unmatched opening parenthesis\n//│ ║  l.227: \t(1\n//│ ╙──       \t^\n//│ |1|\n//│ Parsed: {1}\n\n(1))\n//│ ╔══[PARSE ERROR] Unexpected closing parenthesis\n//│ ║  l.234: \t(1))\n//│ ╙──       \t   ^\n//│ |(|1|)|\n//│ Parsed: {'(' 1 ')'}\n\n(\n//│ ╔══[PARSE ERROR] Unmatched opening parenthesis\n//│ ║  l.241: \t(\n//│ ╙──       \t^\n//│ ||\n//│ Parsed: {}\n\n)\n//│ ╔══[PARSE ERROR] Unexpected closing parenthesis\n//│ ║  l.248: \t)\n//│ ╙──       \t^\n//│ ||\n//│ Parsed: {}\n\n1+\n//│ |1|+|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.255: \t1+\n//│ ╙──       \t  ^\n//│ Parsed: {+(1,)(undefined,)}\n\n*\n//│ |*|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.262: \t*\n//│ ╙──       \t^\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.262: \t*\n//│ ╙──       \t ^\n//│ Parsed: {undefined}\n\n\nf 1\n//│ |f| |1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.273: \tf 1\n//│ ╙──       \t^^^\n//│ Parsed: {f(1,)}\n\nf(1)\n//│ |f|(|1|)|\n//│ Parsed: {f(1,)}\n\nf (1)\n//│ |f| |(|1|)|\n//│ Parsed: {f(1,)}\n\n\nf 1, 2, 3\n//│ |f| |1|,| |2|,| |3|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.289: \tf 1, 2, 3\n//│ ╙──       \t^^^^^^^^^\n//│ Parsed: {f(1, 2, 3,)}\n\nf (1, 2, 3)\n//│ |f| |(|1|,| |2|,| |3|)|\n//│ Parsed: {f(1, 2, 3,)}\n\nf(1, 2, 3)\n//│ |f|(|1|,| |2|,| |3|)|\n//│ Parsed: {f(1, 2, 3,)}\n\n// :pe\nf[]\n//│ |f|[||]|\n//│ Parsed: {f‹›}\n\nf[1]\n//│ |f|[|1|]|\n//│ Parsed: {f‹1›}\n\nf[1, 2, 3]\n//│ |f|[|1|,| |2|,| |3|]|\n//│ Parsed: {f‹1, 2, 3›}\n\nf{}\n//│ |f|{||}|\n//│ Parsed: {f {}}\n\nf{1}\n//│ |f|{|1|}|\n//│ Parsed: {f {1}}\n\nf{1, 2, 3}\n//│ |f|{|1|,| |2|,| |3|}|\n//│ Parsed: {f {,(1, ,(2, 3,),)}}\n\n\nf 1,, 2\n//│ |f| |1|,|,| |2|\n//│ ╔══[PARSE ERROR] Unexpected comma in expression position\n//│ ║  l.330: \tf 1,, 2\n//│ ╙──       \t    ^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.330: \tf 1,, 2\n//│ ╙──       \t^^^^^^^\n//│ Parsed: {f(1, 2,)}\n\n\nf of x\n//│ |f| |#of| |x|\n//│ Parsed: {f(x,)}\n\nf g x\n//│ |f| |g| |x|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.345: \tf g x\n//│ ╙──       \t  ^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.345: \tf g x\n//│ ╙──       \t^^^^^\n//│ Parsed: {f(g(x,),)}\n\nf of g of x\n//│ |f| |#of| |g| |#of| |x|\n//│ Parsed: {f(g(x,),)}\n\nf of of g\n//│ |f| |#of| |#of| |g|\n//│ ╔══[PARSE ERROR] Unexpected 'of' keyword in expression position\n//│ ║  l.359: \tf of of g\n//│ ╙──       \t     ^^\n//│ Parsed: {f(g,)}\n\n\nf x: 1\n//│ |f| |x|#:| |1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.367: \tf x: 1\n//│ ╙──       \t^^^^^^\n//│ Parsed: {f(x: 1,)}\n\nf x: 1,\n//│ |f| |x|#:| |1|,|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.374: \tf x: 1,\n//│ ╙──       \t^^^^^^\n//│ Parsed: {f(x: 1,)}\n\nf x : 1\n//│ |f| |x| |#:| |1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.381: \tf x : 1\n//│ ╙──       \t^^^\n//│ Parsed: {f(x : 1,)}\n\nf x: 1, y: 2\n//│ |f| |x|#:| |1|,| |y|#:| |2|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.388: \tf x: 1, y: 2\n//│ ╙──       \t^^^^^^^^^^^^\n//│ Parsed: {f(x: 1, y: 2,)}\n\nf x : 1, y: 2\n//│ |f| |x| |#:| |1|,| |y|#:| |2|\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.395: \tf x : 1, y: 2\n//│ ╙──       \t         ^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.395: \tf x : 1, y: 2\n//│ ╙──       \t^^^\n//│ Parsed: {f(x : anything,)}\n\nf x: 1, y: 2, z: 3\n//│ |f| |x|#:| |1|,| |y|#:| |2|,| |z|#:| |3|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.405: \tf x: 1, y: 2, z: 3\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^\n//│ Parsed: {f(x: 1, y: 2, z: 3,)}\n\nf x: 1, y: g 2, z: 3\n//│ |f| |x|#:| |1|,| |y|#:| |g| |2|,| |z|#:| |3|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.412: \tf x: 1, y: g 2, z: 3\n//│ ╙──       \t           ^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.412: \tf x: 1, y: g 2, z: 3\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^\n//│ Parsed: {f(x: 1, y: g(2, z: 3,),)}\n\nf(x: 1, y: g(2, z: 3))\n//│ |f|(|x|#:| |1|,| |y|#:| |g|(|2|,| |z|#:| |3|)|)|\n//│ Parsed: {f(x: 1, y: g(2, z: 3,),)}\n\nf(x: 1, y: g(2), z: 3)\n//│ |f|(|x|#:| |1|,| |y|#:| |g|(|2|)|,| |z|#:| |3|)|\n//│ Parsed: {f(x: 1, y: g(2,), z: 3,)}\n\nf  x: 1,  y:  g  2, z: 3\n//│ |f| |x|#:| |1|,| |y|#:| |g| |2|,| |z|#:| |3|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.430: \tf  x: 1,  y:  g  2, z: 3\n//│ ╙──       \t              ^^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.430: \tf  x: 1,  y:  g  2, z: 3\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^\n//│ Parsed: {f(x: 1, y: g(2, z: 3,),)}\n\nf of x: 1, y: g of 2, z: 3\n//│ |f| |#of| |x|#:| |1|,| |y|#:| |g| |#of| |2|,| |z|#:| |3|\n//│ Parsed: {f(x: 1, y: g(2, z: 3,),)}\n\nf x: 1 + 1, y: 2 2, z: 3 + 2 4 - 1\n//│ |f| |x|#:| |1| |+| |1|,| |y|#:| |2| |2|,| |z|#:| |3| |+| |2| |4| |-| |1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.444: \tf x: 1 + 1, y: 2 2, z: 3 + 2 4 - 1\n//│ ╙──       \t                           ^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.444: \tf x: 1 + 1, y: 2 2, z: 3 + 2 4 - 1\n//│ ╙──       \t               ^^^^^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.444: \tf x: 1 + 1, y: 2 2, z: 3 + 2 4 - 1\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ Parsed: {f(x: +(1,)(1,), y: 2(2, z: +(3,)(2(-(4,)(1,),),),),)}\n\n\nx.y\n//│ |x|.y|\n//│ Parsed: {(x).y}\n\n.y\n//│ |.y|\n//│ ╔══[PARSE ERROR] Unexpected selector in expression position\n//│ ║  l.462: \t.y\n//│ ╙──       \t^^\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.462: \t.y\n//│ ╙──       \t  ^\n//│ Parsed: {undefined}\n\n\n2 + f of 3 + 3\n//│ |2| |+| |f| |#of| |3| |+| |3|\n//│ Parsed: {+(2,)(f(+(3,)(3,),),)}\n\n2 + 2\n  of 3 + 3\n//│ |2| |+| |2|→|#of| |3| |+| |3|←|\n//│ Parsed: {+(2,)(2,)(+(3,)(3,),)}\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Binds.mls",
    "content": ":AllowParseErrors\n\n\nf(x) is True\n//│ |f|(|x|)| |is| |True|\n//│ Parsed: {is(f(x,),)(True,)}\n\n// Precedence of 'of'/'is' may be surprising!\nf of x is True\n//│ |f| |#of| |x| |is| |True|\n//│ Parsed: {f(is(x,)(True,),)}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Blocks.mls",
    "content": ":AllowParseErrors\n\n\na\nb\n//│ |a|↵|b|\n//│ Parsed: {a; b}\n\na,\nb\n//│ |a|,|↵|b|\n//│ Parsed: {,(a, b,)}\n\na,\nb,\n//│ |a|,|↵|b|,|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.15: \tb,\n//│ ╙──      \t  ^\n//│ Parsed: {,(a, ,(b, undefined,),)}\n\na,\nb,\nc\n//│ |a|,|↵|b|,|↵|c|\n//│ Parsed: {,(a, ,(b, c,),)}\n\nfoo\n  a\n  b\n//│ |foo|→|a|↵|b|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.28: \tfoo\n//│ ║        \t^^^\n//│ ║  l.29: \t  a\n//│ ║        \t^^^\n//│ ║  l.30: \t  b\n//│ ╙──      \t^^^\n//│ Parsed: {foo({a; b},)}\n\nfoo(\n  a,\n  b\n)\n//│ |foo|(|→|a|,|↵|b|←|↵|)|\n//│ Parsed: {foo(a, b,)}\n\nfoo(\n  a,\n  b,\n)\n//│ |foo|(|→|a|,|↵|b|,|←|↵|)|\n//│ Parsed: {foo(a, b,)}\n\nfoo(\n  a\n  b\n)\n//│ |foo|(|→|a|↵|b|←|↵|)|\n//│ Parsed: {foo({a; b},)}\n\nfoo(\n    a\n  b\n)\n//│ |foo|(|→|a|←|→|b|←|↵|)|\n//│ ╔══[PARSE ERROR] Unexpected indented block here\n//│ ║  l.64: \t  b\n//│ ║        \t^^^\n//│ ║  l.65: \t)\n//│ ╙──      \t^\n//│ Parsed: {foo(a,)}\n\n// TODO\nfoo of\n  a\n  fun f = 1\n  b\n//│ |foo| |#of|→|a|↵|#fun| |f| |#=| |1|↵|b|←|\n//│ ╔══[PARSE ERROR] Unexpected 'fun' keyword in expression position\n//│ ║  l.77: \t  fun f = 1\n//│ ╙──      \t  ^^^\n//│ ╔══[PARSE ERROR] Unexpected '=' here\n//│ ║  l.77: \t  fun f = 1\n//│ ╙──      \t        ^\n//│ Parsed: {foo({a; f},)}\n\nfoo +\n  a\n  b\n//│ |foo| |+|→|a|↵|b|←|\n//│ Parsed: {+(foo,)({a; b},)}\n\n\nfoo(a, b, c)\nfoo of a, b, c\n//│ |foo|(|a|,| |b|,| |c|)|↵|foo| |#of| |a|,| |b|,| |c|\n//│ Parsed: {foo(a, b, c,); foo(a, b, c,)}\n\nfoo of\n  aaaaa,\n  bbbbb,\n  ccccc\n//│ |foo| |#of|→|aaaaa|,|↵|bbbbb|,|↵|ccccc|←|\n//│ Parsed: {foo(aaaaa, bbbbb, ccccc,)}\n\nfoo of\n  a\n  boo\n    x\n    y\n  c\n//│ |foo| |#of|→|a|↵|boo|→|x|↵|y|←|↵|c|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.109: \t  boo\n//│ ║         \t  ^^^\n//│ ║  l.110: \t    x\n//│ ║         \t^^^^^\n//│ ║  l.111: \t    y\n//│ ╙──       \t^^^^^\n//│ Parsed: {foo({a; boo({x; y},); c},)}\n\n\nfun foo =\n  print(\"ok\")\n  print(\"ko\")\n//│ |#fun| |foo| |#=|→|print|(|\"ok\"|)|↵|print|(|\"ko\"|)|←|\n//│ Parsed: {fun foo = {print(\"ok\",); print(\"ko\",)}}\n\nfun foo =\n  \n  print(\"ok\")\n  \n  print(\"ko\")\n  \n//│ |#fun| |foo| |#=|→|print|(|\"ok\"|)|↵|print|(|\"ko\"|)|↵|←|\n//│ Parsed: {fun foo = {print(\"ok\",); print(\"ko\",)}}\n\nfun foo =\n  fun local(x) = x + 1\n  print(local(1))\n  class Foo\n//│ |#fun| |foo| |#=|→|#fun| |local|(|x|)| |#=| |x| |+| |1|↵|print|(|local|(|1|)|)|↵|#class| |Foo|←|\n//│ Parsed: {fun foo = {fun local = (x,) => +(x,)(1,); print(local(1,),); class Foo {}}}\n\nfun foo =\n  fun local(x) =\n    class Foo {\n      fun bar = x + 1\n    }\n    Foo().bar\n  print of local(0) + local(1)\n  print of (local of 0) + local of 1\n  fun tmp = 1\n  print of local of 0 + local of 1\n  fun tmp = 2\n//│ |#fun| |foo| |#=|→|#fun| |local|(|x|)| |#=|→|#class| |Foo| |{|→|#fun| |bar| |#=| |x| |+| |1|←|↵|}|↵|Foo|(||)|.bar|←|↵|print| |#of| |local|(|0|)| |+| |local|(|1|)|↵|print| |#of| |(|local| |#of| |0|)| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |1|↵|print| |#of| |local| |#of| |0| |+| |local| |#of| |1|↵|#fun| |tmp| |#=| |2|←|\n//│ Parsed: {fun foo = {fun local = (x,) => {class Foo {fun bar = +(x,)(1,)}; (Foo()).bar}; print(+(local(0,),)(local(1,),),); print(+('(' local(0,) ')',)(local(1,),),); fun tmp = 1; print(local(+(0,)(local(1,),),),); fun tmp = 2}}\n\n\n\nlog(1); log(a)\n//│ |log|(|1|)|;| |log|(|a|)|\n//│ Parsed: {log(1,); log(a,)}\n\nconstructor(){\n  a = 1\n  a = 2\n}\n//│ |#constructor|(||)|{|→|a| |#=| |1|↵|a| |#=| |2|←|↵|}|\n//│ Parsed: {constructor() {a = 1; a = 2}}\n\na = 1; log(a)\n//│ |a| |#=| |1|;| |log|(|a|)|\n//│ Parsed: {a = 1; log(a,)}\n\nf(a) = 1\n//│ |f|(|a|)| |#=| |1|\n//│ Parsed: {f = (a,) => 1}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Brackets.mls",
    "content": "\n()\n//│ |(||)|\n//│ Parsed: {undefined}\n\n[]\n//│ |[||]|\n//│ Parsed: {[]}\n\n{}\n//│ |{||}|\n//│ Parsed: {'{' {} '}'}\n\n:pe\n(}\n//│ ╔══[PARSE ERROR] Mistmatched closing curly brace\n//│ ║  l.15: \t(}\n//│ ║        \t ^\n//│ ╟── does not correspond to opening parenthesis\n//│ ║  l.15: \t(}\n//│ ╙──      \t^\n//│ |(||)|\n//│ Parsed: {undefined}\n\n(([{}]))\n//│ |(|(|[|{||}|]|)|)|\n//│ Parsed: {'(' '(' ['{' {} '}',] ')' ')'}\n\n:pe\n(([{})])\n//│ ╔══[PARSE ERROR] Mistmatched closing parenthesis\n//│ ║  l.30: \t(([{})])\n//│ ║        \t     ^\n//│ ╟── does not correspond to opening square bracket\n//│ ║  l.30: \t(([{})])\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Mistmatched closing square bracket\n//│ ║  l.30: \t(([{})])\n//│ ║        \t      ^\n//│ ╟── does not correspond to opening parenthesis\n//│ ║  l.30: \t(([{})])\n//│ ╙──      \t ^\n//│ |(|(|[|{||}|]|)|)|\n//│ Parsed: {'(' '(' ['{' {} '}',] ')' ')'}\n\n\nfun f = ()\n//│ |#fun| |f| |#=| |(||)|\n//│ Parsed: {fun f = undefined}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Classes.mls",
    "content": "\n\nclass Foo\n//│ |#class| |Foo|\n//│ Parsed: {class Foo {}}\n\nclass Foo {}\n//│ |#class| |Foo| |{||}|\n//│ Parsed: {class Foo {}}\n\nclass Foo {\n  fun foo: int\n}\n//│ |#class| |Foo| |{|→|#fun| |foo|#:| |int|←|↵|}|\n//│ Parsed: {class Foo {fun foo: int}}\n\nclass Foo {\n  class Bar {\n    class Baz\n  }\n}\n//│ |#class| |Foo| |{|→|#class| |Bar| |{|→|#class| |Baz|←|↵|}|←|↵|}|\n//│ Parsed: {class Foo {class Bar {class Baz {}}}}\n\nclass Foo: Bar\n//│ |#class| |Foo|#:| |Bar|\n//│ Parsed: {class Foo: Bar {}}\n\nclass Foo extends Bar, Baz\n//│ |#class| |Foo| |#extends| |Bar|,| |Baz|\n//│ Parsed: {class Foo: Bar, Baz {}}\n\nclass Foo: Bar, Baz\n//│ |#class| |Foo|#:| |Bar|,| |Baz|\n//│ Parsed: {class Foo: ,[Bar, Baz] {}}\n\nclass Foo: Bar { fun f = 0 }\n//│ |#class| |Foo|#:| |Bar| |{| |#fun| |f| |#=| |0| |}|\n//│ Parsed: {class Foo: Bar {fun f = 0}}\n\nclass Foo extends Bar, Baz { fun f = 0 }\n//│ |#class| |Foo| |#extends| |Bar|,| |Baz| |{| |#fun| |f| |#=| |0| |}|\n//│ Parsed: {class Foo: Bar, Baz {fun f = 0}}\n\n:pe\nclass Foo: Bar, Baz { fun f = 0 }\n//│ |#class| |Foo|#:| |Bar|,| |Baz| |{| |#fun| |f| |#=| |0| |}|\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.46: \tclass Foo: Bar, Baz { fun f = 0 }\n//│ ╙──      \t                ^^^^^^^^^^^^^^^^^\n//│ Parsed: {class Foo: anything {}}\n\n// * Pretty confusing... better reject this:\n:pe\n:w\nclass Foo: Bar { fun f = 0\n  fun bar = 1\n}\n//│ |#class| |Foo|#:| |Bar| |{| |#fun| |f| |#=| |0|→|#fun| |bar| |#=| |1|←|↵|}|\n//│ ╔══[PARSE ERROR] Unexpected 'fun' keyword in expression position\n//│ ║  l.57: \t  fun bar = 1\n//│ ╙──      \t  ^^^\n//│ ╔══[PARSE ERROR] Unexpected '=' here\n//│ ║  l.57: \t  fun bar = 1\n//│ ╙──      \t          ^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.56: \tclass Foo: Bar { fun f = 0\n//│ ║        \t                         ^\n//│ ║  l.57: \t  fun bar = 1\n//│ ╙──      \t^^^^^^^^^\n//│ Parsed: {class Foo: Bar {fun f = 0(bar,)}}\n\n// TODO disallow? (i.e., require unindent before closing brace)\n// :e\nclass Foo: Bar {\n  fun f = 0\n  fun bar = 1\n  }\n//│ |#class| |Foo|#:| |Bar| |{|→|#fun| |f| |#=| |0|↵|#fun| |bar| |#=| |1|↵|←|}|\n//│ Parsed: {class Foo: Bar {fun f = 0; fun bar = 1}}\n\nclass Foo: Bar {\n  fun f = 0\n  fun bar = 1\n}\n//│ |#class| |Foo|#:| |Bar| |{|→|#fun| |f| |#=| |0|↵|#fun| |bar| |#=| |1|←|↵|}|\n//│ Parsed: {class Foo: Bar {fun f = 0; fun bar = 1}}\n\nclass Foo: Bar {\n  \n  fun f = 0\n  \n  fun bar = 1\n  \n}\n//│ |#class| |Foo|#:| |Bar| |{|→|#fun| |f| |#=| |0|↵|#fun| |bar| |#=| |1|←|↵|}|\n//│ Parsed: {class Foo: Bar {fun f = 0; fun bar = 1}}\n\nclass Foo: Bar {\n  \n}\n//│ |#class| |Foo|#:| |Bar| |{|↵|}|\n//│ Parsed: {class Foo: Bar {}}\n\nfun foo =\n  class Foo: Bar {\n  \n  }\n//│ |#fun| |foo| |#=|→|#class| |Foo|#:| |Bar| |{|↵|}|←|\n//│ Parsed: {fun foo = {class Foo: Bar {}}}\n\nclass Foo()\n//│ |#class| |Foo|(||)|\n//│ Parsed: {class Foo() {}}\n\nclass Foo(x, y, z)\n//│ |#class| |Foo|(|x|,| |y|,| |z|)|\n//│ Parsed: {class Foo(x, y, z,) {}}\n\n\nclass Foo(x, y, z): Bar(z, x)\n//│ |#class| |Foo|(|x|,| |y|,| |z|)|#:| |Bar|(|z|,| |x|)|\n//│ Parsed: {class Foo(x, y, z,): Bar[z, x] {}}\n\nclass Foo(x, y, z): Bar(z, x) {\n  fun blah(x) = x + y\n}\n//│ |#class| |Foo|(|x|,| |y|,| |z|)|#:| |Bar|(|z|,| |x|)| |{|→|#fun| |blah|(|x|)| |#=| |x| |+| |y|←|↵|}|\n//│ Parsed: {class Foo(x, y, z,): Bar[z, x] {fun blah = (x,) => +(x,)(y,)}}\n\nclass Foo(x, y) extends Bar(y, x), Baz(x + y)\n//│ |#class| |Foo|(|x|,| |y|)| |#extends| |Bar|(|y|,| |x|)|,| |Baz|(|x| |+| |y|)|\n//│ Parsed: {class Foo(x, y,): Bar(y, x,), Baz(+(x,)(y,),) {}}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Comments.mls",
    "content": "\n1 // whoops\n//│ |1| |/* whoops*/|\n//│ Parsed: {1}\n\n2 /* whoops */\n//│ |2| |/* whoops */|\n//│ Parsed: {2}\n\n1\n// A\n2\n//│ |1|↵|/* A*/|↵|2|\n//│ Parsed: {1; 2}\n\n:w\n1\n  // A\n2\n//│ |1|→|/* A*/|←|↵|2|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.17: \t1\n//│ ╙──      \t^\n//│ Parsed: {1(); 2}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/ControversialIfSplits.mls",
    "content": ":AllowParseErrors\n\n\nif f of\n  0 then \"ok\"\n  1 then \"ko\"\n//│ |#if| |f| |#of|→|0| |#then| |\"ok\"|↵|1| |#then| |\"ko\"|←|\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.5: \t  0 then \"ok\"\n//│ ╙──     \t    ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.4: \tif f of\n//│ ║       \t   ^^^^\n//│ ║  l.5: \t  0 then \"ok\"\n//│ ║       \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.4: \tif f of\n//│ ╙──     \t^^\n//│ Parsed: {if (f(0,)) then undefined}\n\nif f (\n  0 then \"ok\"\n  1 then \"ko\"\n)\n//│ |#if| |f| |(|→|0| |#then| |\"ok\"|↵|1| |#then| |\"ko\"|←|↵|)|\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.22: \t  0 then \"ok\"\n//│ ╙──      \t    ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.21: \tif f (\n//│ ║        \t   ^^^\n//│ ║  l.22: \t  0 then \"ok\"\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.23: \t  1 then \"ko\"\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.24: \t)\n//│ ║        \t^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.21: \tif f (\n//│ ╙──      \t^^\n//│ Parsed: {if (f(0,)) then undefined}\n\nif f of\n  0 then \"ok\"\n  1 then \"ko\"\n  else \"?\"\n//│ |#if| |f| |#of|→|0| |#then| |\"ok\"|↵|1| |#then| |\"ko\"|↵|#else| |\"?\"|←|\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.44: \t  0 then \"ok\"\n//│ ╙──      \t    ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.43: \tif f of\n//│ ║        \t   ^^^^\n//│ ║  l.44: \t  0 then \"ok\"\n//│ ║        \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.43: \tif f of\n//│ ╙──      \t^^\n//│ Parsed: {if (f(0,)) then undefined}\n\nif f of\n  0 is 0 then \"ok\"\n  1 is 1 then \"ko\"\n//│ |#if| |f| |#of|→|0| |is| |0| |#then| |\"ok\"|↵|1| |is| |1| |#then| |\"ko\"|←|\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.62: \t  0 is 0 then \"ok\"\n//│ ╙──      \t         ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.61: \tif f of\n//│ ║        \t   ^^^^\n//│ ║  l.62: \t  0 is 0 then \"ok\"\n//│ ║        \t^^^^^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.61: \tif f of\n//│ ╙──      \t^^\n//│ Parsed: {if (f(is(0,)(0,),)) then undefined}\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/FatArrows.mls",
    "content": ":AllowParseErrors\n\n\nfun f: (x: Int) => Int\n//│ |#fun| |f|#:| |(|x|#:| |Int|)| |#=>| |Int|\n//│ Parsed: {fun f: (x: Int) -> Int}\n\nfun f: (x: Int => Int, y: Int) => Int\n//│ |#fun| |f|#:| |(|x|#:| |Int| |#=>| |Int|,| |y|#:| |Int|)| |#=>| |Int|\n//│ Parsed: {fun f: (x: Int -> Int, y: Int) -> Int}\n\nfun f: (x: Int, y: Int => Int) => Int\n//│ |#fun| |f|#:| |(|x|#:| |Int|,| |y|#:| |Int| |#=>| |Int|)| |#=>| |Int|\n//│ Parsed: {fun f: (x: Int, y: Int -> Int) -> Int}\n\nfun f: (x: Int, y: (Int, Int) => Int) => Int\n//│ |#fun| |f|#:| |(|x|#:| |Int|,| |y|#:| |(|Int|,| |Int|)| |#=>| |Int|)| |#=>| |Int|\n//│ Parsed: {fun f: (x: Int, y: (Int, Int) -> Int) -> Int}\n\nfun f: (x: Int)\n//│ |#fun| |f|#:| |(|x|#:| |Int|)|\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.20: \tfun f: (x: Int)\n//│ ╙──      \t        ^^^^^^\n//│ Parsed: {fun f: Int}\n\nfun f: (x: Int, y: Int)\n//│ |#fun| |f|#:| |(|x|#:| |Int|,| |y|#:| |Int|)|\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.27: \tfun f: (x: Int, y: Int)\n//│ ╙──      \t        ^^^^^^\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.27: \tfun f: (x: Int, y: Int)\n//│ ╙──      \t                ^^^^^^\n//│ Parsed: {fun f: ,[Int, Int]}\n\nfun match: forall 'res: (() -> Int, ifCons: Int) => Int\n//│ |#fun| |match|#:| |#forall| |'res|#:| |(|(||)| |->| |Int|,| |ifCons|#:| |Int|)| |#=>| |Int|\n//│ Parsed: {fun match: forall 'res. (() -> Int, ifCons: Int) -> Int}\n\nfun match: forall 'res: (() => Int, ifCons: Int) => Int\n//│ |#fun| |match|#:| |#forall| |'res|#:| |(|(||)| |#=>| |Int|,| |ifCons|#:| |Int|)| |#=>| |Int|\n//│ Parsed: {fun match: forall 'res. (() -> Int, ifCons: Int) -> Int}\n\nfun match: forall 'res: (() => Int, Int) => Int\n//│ |#fun| |match|#:| |#forall| |'res|#:| |(|(||)| |#=>| |Int|,| |Int|)| |#=>| |Int|\n//│ Parsed: {fun match: forall 'res. (() -> Int, Int) -> Int}\n\nf(x => x, a)\n//│ |f|(|x| |#=>| |x|,| |a|)|\n//│ Parsed: {f((x,) => x, a,)}\n\nf(x => x, y: a)\n//│ |f|(|x| |#=>| |x|,| |y|#:| |a|)|\n//│ Parsed: {f((x,) => x, y: a,)}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/FlatMultiArgLams.mls",
    "content": ":NewDefs\n\n\n// Extracted frrom JSON.mls\n\nparseNegative(state).flatMap of (negative, state) =>\nparseIntegral(state).flatMap of (integral, state) =>\nparseFraction(state).flatMap of (fraction, state) =>\nparseExponent(state).flatMap of (exponent, state) =>\nlet value = (integral +. fraction) *. exponent\nSuccess of (if negative then (0 -. value) else value), state\n//│ |parseNegative|(|state|)|.flatMap| |#of| |(|negative|,| |state|)| |#=>|↵|parseIntegral|(|state|)|.flatMap| |#of| |(|integral|,| |state|)| |#=>|↵|parseFraction|(|state|)|.flatMap| |#of| |(|fraction|,| |state|)| |#=>|↵|parseExponent|(|state|)|.flatMap| |#of| |(|exponent|,| |state|)| |#=>|↵|#let| |value| |#=| |(|integral| |+.| |fraction|)| |*.| |exponent|↵|Success| |#of| |(|#if| |negative| |#then| |(|0| |-.| |value|)| |#else| |value|)|,| |state|\n//│ Parsed: {(parseNegative(state,)).flatMap((negative, state,) => {(parseIntegral(state,)).flatMap((integral, state,) => {(parseFraction(state,)).flatMap((fraction, state,) => {(parseExponent(state,)).flatMap((exponent, state,) => {let value = *.('(' +.(integral, fraction,) ')', exponent,); Success('(' if (negative) then '(' -.(0, value,) ')' else value ')', state,)},)},)},)},)}\n//│ \n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Forall.mls",
    "content": "\nforall 'a: 'a => 'a\n//│ |#forall| |'a|#:| |'a| |#=>| |'a|\n//│ Parsed: {forall 'a. ('a,) => 'a}\n\nforall 'a, 'b: ['a, 'b] => ['b, 'a]\n//│ |#forall| |'a|,| |'b|#:| |[|'a|,| |'b|]| |#=>| |[|'b|,| |'a|]|\n//│ Parsed: {forall 'a, 'b. (['a, 'b,],) => ['b, 'a,]}\n\nfun f: forall 'a: 'a => 'a\n//│ |#fun| |f|#:| |#forall| |'a|#:| |'a| |#=>| |'a|\n//│ Parsed: {fun f: forall 'a. 'a -> 'a}\n\nfun f: forall 'a, 'b: ['a, 'b] => ['b, 'a]\n//│ |#fun| |f|#:| |#forall| |'a|,| |'b|#:| |[|'a|,| |'b|]| |#=>| |[|'b|,| |'a|]|\n//│ Parsed: {fun f: forall 'a 'b. (['a, 'b]) -> ['b, 'a]}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Fun.mls",
    "content": ":AllowParseErrors\n\n\nfun f = 1\n//│ |#fun| |f| |#=| |1|\n//│ Parsed: {fun f = 1}\n\nfun f(x) = x\n//│ |#fun| |f|(|x|)| |#=| |x|\n//│ Parsed: {fun f = (x,) => x}\n\nfun f x = x\n//│ |#fun| |f| |x| |#=| |x|\n//│ ╔══[PARSE ERROR] Expected function parameter list; found identifier instead\n//│ ║  l.12: \tfun f x = x\n//│ ╙──      \t      ^\n//│ Parsed: {fun f = x}\n\nfun f = x => x\n//│ |#fun| |f| |#=| |x| |#=>| |x|\n//│ Parsed: {fun f = (x,) => x}\n\n// TODO\nfun x => x\n//│ |#fun| |x| |#=>| |x|\n//│ ╔══[PARSE ERROR] Expected function parameter list; found '=>' instead\n//│ ║  l.24: \tfun x => x\n//│ ╙──      \t      ^^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found identifier instead\n//│ ║  l.24: \tfun x => x\n//│ ╙──      \t         ^\n//│ Parsed: {fun x = undefined}\n\nlet f = x => x\n//│ |#let| |f| |#=| |x| |#=>| |x|\n//│ Parsed: {let f = (x,) => x}\n\n// TODO\nlet f = fun x => x\n//│ |#let| |f| |#=| |#fun| |x| |#=>| |x|\n//│ ╔══[PARSE ERROR] Unexpected 'fun' keyword in expression position\n//│ ║  l.39: \tlet f = fun x => x\n//│ ╙──      \t        ^^^\n//│ Parsed: {let f = (x,) => x}\n\n\nf(x) + x\n//│ |f|(|x|)| |+| |x|\n//│ Parsed: {+(f(x,),)(x,)}\n\n\nfun f(x, y) = x\n//│ |#fun| |f|(|x|,| |y|)| |#=| |x|\n//│ Parsed: {fun f = (x, y,) => x}\n\nfun f of x = x\n//│ |#fun| |f| |#of| |x| |#=| |x|\n//│ Parsed: {fun f = (x,) => x}\n\nfun f of x, y = x\n//│ |#fun| |f| |#of| |x|,| |y| |#=| |x|\n//│ Parsed: {fun f = (x, y,) => x}\n\nfun f x, y = x\n//│ |#fun| |f| |x|,| |y| |#=| |x|\n//│ ╔══[PARSE ERROR] Expected function parameter list; found identifier instead\n//│ ║  l.64: \tfun f x, y = x\n//│ ╙──      \t      ^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found comma instead\n//│ ║  l.64: \tfun f x, y = x\n//│ ╙──      \t       ^\n//│ ╔══[PARSE ERROR] Expected end of input; found identifier instead\n//│ ║  l.64: \tfun f x, y = x\n//│ ╙──      \t         ^\n//│ Parsed: {fun f = undefined}\n\nfun f x y = x\n//│ |#fun| |f| |x| |y| |#=| |x|\n//│ ╔══[PARSE ERROR] Expected function parameter list; found identifier instead\n//│ ║  l.77: \tfun f x y = x\n//│ ╙──      \t      ^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found identifier instead\n//│ ║  l.77: \tfun f x y = x\n//│ ╙──      \t        ^\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' instead\n//│ ║  l.77: \tfun f x y = x\n//│ ╙──      \t          ^\n//│ Parsed: {fun f = undefined}\n\n\nfun f(x, y)(a, b) = x + y * a / b\n//│ |#fun| |f|(|x|,| |y|)|(|a|,| |b|)| |#=| |x| |+| |y| |*| |a| |/| |b|\n//│ Parsed: {fun f = (x, y,) => (a, b,) => /(+(x,)(*(y,)(a,),),)(b,)}\n\nfun f(x, y) of a, b = x + y * a / b\n//│ |#fun| |f|(|x|,| |y|)| |#of| |a|,| |b| |#=| |x| |+| |y| |*| |a| |/| |b|\n//│ Parsed: {fun f = (x, y,) => (a, b,) => /(+(x,)(*(y,)(a,),),)(b,)}\n\nfun f of x, y of a, b = x + y * a / b\n//│ |#fun| |f| |#of| |x|,| |y| |#of| |a|,| |b| |#=| |x| |+| |y| |*| |a| |/| |b|\n//│ Parsed: {fun f = (x, y(a, b,),) => /(+(x,)(*(y,)(a,),),)(b,)}\n\n\nfun f(Some(x)) = x\n//│ |#fun| |f|(|Some|(|x|)|)| |#=| |x|\n//│ Parsed: {fun f = (Some(x,),) => x}\n\nfun f(Some of x) = x\n//│ |#fun| |f|(|Some| |#of| |x|)| |#=| |x|\n//│ Parsed: {fun f = (Some(x,),) => x}\n\nfun f of Some of x = x\n//│ |#fun| |f| |#of| |Some| |#of| |x| |#=| |x|\n//│ Parsed: {fun f = (Some(x,),) => x}\n\nfun f(Some(x), Some(y)) = x\n//│ |#fun| |f|(|Some|(|x|)|,| |Some|(|y|)|)| |#=| |x|\n//│ Parsed: {fun f = (Some(x,), Some(y,),) => x}\n\nfun f(Some of x, Some of y) = x + y\n//│ |#fun| |f|(|Some| |#of| |x|,| |Some| |#of| |y|)| |#=| |x| |+| |y|\n//│ Parsed: {fun f = (Some(x, Some(y,),),) => +(x,)(y,)}\n\nfun f of Some of x, Some of y = x + y\n//│ |#fun| |f| |#of| |Some| |#of| |x|,| |Some| |#of| |y| |#=| |x| |+| |y|\n//│ Parsed: {fun f = (Some(x, Some(y,),),) => +(x,)(y,)}\n\n\nfun f(x: Int, y: Int) = x\n//│ |#fun| |f|(|x|#:| |Int|,| |y|#:| |Int|)| |#=| |x|\n//│ Parsed: {fun f = (x: Int, y: Int,) => x}\n\nfun f(x: Int, y: Int): Int = x\n//│ |#fun| |f|(|x|#:| |Int|,| |y|#:| |Int|)|#:| |Int| |#=| |x|\n//│ Parsed: {fun f = (x: Int, y: Int,) => x : Int}\n\n\n\nfun 1\n//│ |#fun| |1|\n//│ ╔══[PARSE ERROR] Expected a function name; found literal instead\n//│ ║  l.139: \tfun 1\n//│ ╙──       \t    ^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found end of input instead\n//│ ║  l.139: \tfun 1\n//│ ╙──       \t     ^\n//│ Parsed: {fun <error> = undefined}\n\nfun 1 = 1\n//│ |#fun| |1| |#=| |1|\n//│ ╔══[PARSE ERROR] Expected a function name; found literal instead\n//│ ║  l.149: \tfun 1 = 1\n//│ ╙──       \t    ^\n//│ Parsed: {fun <error> = 1}\n\nfun\n//│ |#fun|\n//│ ╔══[PARSE ERROR] Expected a function name; found end of input instead\n//│ ║  l.156: \tfun\n//│ ╙──       \t   ^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found end of input instead\n//│ ║  l.156: \tfun\n//│ ╙──       \t   ^\n//│ Parsed: {fun <error> = undefined}\n\nfun = 1\n//│ |#fun| |#=| |1|\n//│ ╔══[PARSE ERROR] Expected a function name; found '=' instead\n//│ ║  l.166: \tfun = 1\n//│ ╙──       \t    ^\n//│ ╔══[PARSE ERROR] Expected function parameter list; found literal instead\n//│ ║  l.166: \tfun = 1\n//│ ╙──       \t      ^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found end of input instead\n//│ ║  l.166: \tfun = 1\n//│ ╙──       \t       ^\n//│ Parsed: {fun <error> = undefined}\n\n\nfun add(x: number, y: number): number\n//│ |#fun| |add|(|x|#:| |number|,| |y|#:| |number|)|#:| |number|\n//│ Parsed: {fun add: (x: number, y: number) -> number}\n\nfun apply(x: int, f: int => int): int\n//│ |#fun| |apply|(|x|#:| |int|,| |f|#:| |int| |#=>| |int|)|#:| |int|\n//│ Parsed: {fun apply: (x: int, f: int -> int) -> int}\n\nfun apply2(x: number, f: int => number => number): number\n//│ |#fun| |apply2|(|x|#:| |number|,| |f|#:| |int| |#=>| |number| |#=>| |number|)|#:| |number|\n//│ Parsed: {fun apply2: (x: number, f: int -> number -> number) -> number}\n\nfun apply3(x: number, f: (int => number) => number): number\n//│ |#fun| |apply3|(|x|#:| |number|,| |f|#:| |(|int| |#=>| |number|)| |#=>| |number|)|#:| |number|\n//│ Parsed: {fun apply3: (x: number, f: (int -> number) -> number) -> number}\n"
  },
  {
    "path": "shared/src/test/diff/parser/IfThenElse.mls",
    "content": "\n\nif true then 1 else 2\n//│ |#if| |true| |#then| |1| |#else| |2|\n//│ Parsed: {if (true) then 1 else 2}\n\nif a == 0\nthen \"false\" else 2\n//│ |#if| |a| |==| |0|↵|#then| |\"false\"| |#else| |2|\n//│ Parsed: {if (==(a,)(0,)) then \"false\" else 2}\n\nif a == 0\nthen \"false\"\nelse 2\n//│ |#if| |a| |==| |0|↵|#then| |\"false\"|↵|#else| |2|\n//│ Parsed: {if (==(a,)(0,)) then \"false\" else 2}\n\nif a == 0\n  then \"false\"\n  else 2\n//│ |#if| |a| |==| |0|→|#then| |\"false\"|↵|#else| |2|←|\n//│ Parsed: {if (==(a,)(0,)) then \"false\" else 2}\n\nif a == 0\nthen \"false\"\n  else 2\n//│ |#if| |a| |==| |0|↵|#then| |\"false\"|→|#else| |2|←|\n//│ Parsed: {if (==(a,)(0,)) then \"false\" else 2}\n\n:pe\nif a == 0\n  then \"false\"\nelse 2\n//│ |#if| |a| |==| |0|→|#then| |\"false\"|←|↵|#else| |2|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.33: \telse 2\n//│ ╙──      \t^^^^^^\n//│ Parsed: {if (==(a,)(0,)) then \"false\"; undefined}\n\nif a == 0\n  then \"false\"\nprint of \"ok!\"\n//│ |#if| |a| |==| |0|→|#then| |\"false\"|←|↵|print| |#of| |\"ok!\"|\n//│ Parsed: {if (==(a,)(0,)) then \"false\"; print(\"ok!\",)}\n\nif a == 0 then \"false\"\n  else 2\nprint of \"ok!\"\n//│ |#if| |a| |==| |0| |#then| |\"false\"|→|#else| |2|←|↵|print| |#of| |\"ok!\"|\n//│ Parsed: {if (==(a,)(0,)) then \"false\" else 2; print(\"ok!\",)}\n\nif\n  true  then \"true\"\n  false then \"false\"\n//│ |#if|→|true| |#then| |\"true\"|↵|false| |#then| |\"false\"|←|\n//│ Parsed: {if ‹(true) then \"true\"; (false) then \"false\"›}\n\nif\n  a == 1 then \"true\"\n  b == 2 then \"false\"\n//│ |#if|→|a| |==| |1| |#then| |\"true\"|↵|b| |==| |2| |#then| |\"false\"|←|\n//│ Parsed: {if ‹(==(a,)(1,)) then \"true\"; (==(b,)(2,)) then \"false\"›}\n\nif\n  a == 0 then \"false\"\n  a == 1 then \"true\"\n//│ |#if|→|a| |==| |0| |#then| |\"false\"|↵|a| |==| |1| |#then| |\"true\"|←|\n//│ Parsed: {if ‹(==(a,)(0,)) then \"false\"; (==(a,)(1,)) then \"true\"›}\n\nif a ==\n  0 then \"false\"\n  1 then \"true\"\n//│ |#if| |a| |==|→|0| |#then| |\"false\"|↵|1| |#then| |\"true\"|←|\n//│ Parsed: {if a == ‹(0) then \"false\"; (1) then \"true\"›}\n\nif a ==\n  0 then \"false\"\n  _ then \"true\"\n//│ |#if| |a| |==|→|0| |#then| |\"false\"|↵|_| |#then| |\"true\"|←|\n//│ Parsed: {if a == ‹(0) then \"false\"; (_) then \"true\"›}\n\nif a ==\n  0 then \"false\"\n  1 then \"true\"\n  else \"true\"\n//│ |#if| |a| |==|→|0| |#then| |\"false\"|↵|1| |#then| |\"true\"|↵|#else| |\"true\"|←|\n//│ Parsed: {if a == ‹(0) then \"false\"; (1) then \"true\"; else \"true\"›}\n\nif a ==\n  0 then \"false\"\n  1 then \"true\"\nelse \"true\"\n//│ |#if| |a| |==|→|0| |#then| |\"false\"|↵|1| |#then| |\"true\"|←|↵|#else| |\"true\"|\n//│ Parsed: {if a == ‹(0) then \"false\"; (1) then \"true\"› else \"true\"}\n\nif a ==\n    0 then \"false\"\n    1 then \"true\"\n  else \"true\"\n//│ |#if| |a| |==|→|0| |#then| |\"false\"|↵|1| |#then| |\"true\"|←|→|#else| |\"true\"|←|\n//│ Parsed: {if a == ‹(0) then \"false\"; (1) then \"true\"› else \"true\"}\n\n// TODO?\n:pe\nif a ==\n  0 then \"false\" else \"true\"\n//│ |#if| |a| |==|→|0| |#then| |\"false\"| |#else| |\"true\"|←|\n//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here\n//│ ║  l.106: \t  0 then \"false\" else \"true\"\n//│ ╙──       \t                 ^^^^\n//│ Parsed: {if a == ‹(0) then \"false\"›}\n\nif a ==\n  0 then \"false\"\n  else \"true\"\n//│ |#if| |a| |==|→|0| |#then| |\"false\"|↵|#else| |\"true\"|←|\n//│ Parsed: {if a == ‹(0) then \"false\"; else \"true\"›}\n\nif a\n  > 0  then \"false\"\n  == 1 then \"true\"\n//│ |#if| |a|→|>| |0| |#then| |\"false\"|↵|==| |1| |#then| |\"true\"|←|\n//│ Parsed: {if a ‹· > (0) then \"false\"; · == (1) then \"true\"›}\n\n// TODO\nif a\n  > 0  then \"false\"\n  == 1 then \"true\"\n  _    then \"true\"\n//│ |#if| |a|→|>| |0| |#then| |\"false\"|↵|==| |1| |#then| |\"true\"|↵|_| |#then| |\"true\"|←|\n//│ Parsed: {if ‹a ‹· > (0) then \"false\"; · == (1) then \"true\"›; else \"true\"›}\n\nif a ==\n  0 then \"false\"\n  1 then \"true\"\nelse 2\n//│ |#if| |a| |==|→|0| |#then| |\"false\"|↵|1| |#then| |\"true\"|←|↵|#else| |2|\n//│ Parsed: {if a == ‹(0) then \"false\"; (1) then \"true\"› else 2}\n\nif a ==\n  0 and b ==\n    2 then \"false\"\n    3 then \"oops\"\n  1 then \"true\"\n//│ |#if| |a| |==|→|0| |and| |b| |==|→|2| |#then| |\"false\"|↵|3| |#then| |\"oops\"|←|↵|1| |#then| |\"true\"|←|\n//│ Parsed: {if a == ‹0 and b == ‹(2) then \"false\"; (3) then \"oops\"›; (1) then \"true\"›}\n\nif a is\n  Some(x) then \"defined\"\n  None    then \"undefined\"\n//│ |#if| |a| |is|→|Some|(|x|)| |#then| |\"defined\"|↵|None| |#then| |\"undefined\"|←|\n//│ Parsed: {if a is ‹(Some(x,)) then \"defined\"; (None) then \"undefined\"›}\n\nif a is\n  Some(x) and x is\n    Left(a)  then \"left-defined\"\n    Right(b) then \"right-defined\"\n  None       then \"undefined\"\n//│ |#if| |a| |is|→|Some|(|x|)| |and| |x| |is|→|Left|(|a|)| |#then| |\"left-defined\"|↵|Right|(|b|)| |#then| |\"right-defined\"|←|↵|None| |#then| |\"undefined\"|←|\n//│ Parsed: {if a is ‹Some(x,) and x is ‹(Left(a,)) then \"left-defined\"; (Right(b,)) then \"right-defined\"›; (None) then \"undefined\"›}\n\nif a is\n  Some of x then \"defined\"\n  None      then \"undefined\"\n//│ |#if| |a| |is|→|Some| |#of| |x| |#then| |\"defined\"|↵|None| |#then| |\"undefined\"|←|\n//│ Parsed: {if a is ‹(Some(x,)) then \"defined\"; (None) then \"undefined\"›}\n\nif a is\n  Some(x) then \"defined\"\n  _       then \"unknown\"\n//│ |#if| |a| |is|→|Some|(|x|)| |#then| |\"defined\"|↵|_| |#then| |\"unknown\"|←|\n//│ Parsed: {if a is ‹(Some(x,)) then \"defined\"; (_) then \"unknown\"›}\n\nif a is\n  Some(x) then \"defined\"\n  else \"unknown\"\n//│ |#if| |a| |is|→|Some|(|x|)| |#then| |\"defined\"|↵|#else| |\"unknown\"|←|\n//│ Parsed: {if a is ‹(Some(x,)) then \"defined\"; else \"unknown\"›}\n\nif a is\n  Some(x) then \"defined\"\n  else \"unknown\"\n  else \"unreachable?!\"\n//│ |#if| |a| |is|→|Some|(|x|)| |#then| |\"defined\"|↵|#else| |\"unknown\"|↵|#else| |\"unreachable?!\"|←|\n//│ Parsed: {if a is ‹(Some(x,)) then \"defined\"; else \"unknown\"; else \"unreachable?!\"›}\n\na == 1 and b == 2\n//│ |a| |==| |1| |and| |b| |==| |2|\n//│ Parsed: {and(==(a,)(1,),)(==(b,)(2,),)}\n\n\n:pe\nif lol\n//│ |#if| |lol|\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found reference instead\n//│ ║  l.193: \tif lol\n//│ ║         \t   ^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.193: \tif lol\n//│ ╙──       \t^^\n//│ Parsed: {if (lol) then undefined}\n\n:pe\nif lol then\n//│ |#if| |lol| |#then|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.204: \tif lol then\n//│ ╙──       \t           ^\n//│ Parsed: {if (lol) then undefined}\n\n:pe\nif lol then else\n//│ |#if| |lol| |#then| |#else|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.212: \tif lol then else\n//│ ╙──       \t                ^\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.212: \tif lol then else\n//│ ╙──       \t            ^^^^\n//│ Parsed: {if (lol) then undefined}\n\n:pe\na then b\n//│ |a| |#then| |b|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.223: \ta then b\n//│ ╙──       \t^^^^^^^^\n//│ Parsed: {undefined}\n\n:pe\nif lol\nthen\nelse\n//│ |#if| |lol|↵|#then|↵|#else|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.233: \telse\n//│ ╙──       \t    ^\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.233: \telse\n//│ ╙──       \t^^^^\n//│ Parsed: {if (lol) then {undefined}}\n\n:pe\nif lol else 2\n//│ |#if| |lol| |#else| |2|\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found reference followed by 'else' keyword instead\n//│ ║  l.244: \tif lol else 2\n//│ ║         \t   ^^^^^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.244: \tif lol else 2\n//│ ╙──       \t^^\n//│ ╔══[PARSE ERROR] Expected end of input; found 'else' keyword instead\n//│ ║  l.244: \tif lol else 2\n//│ ╙──       \t       ^^^^\n//│ Parsed: {if (lol) then undefined}\n\n\nx = if true then false else maybe\n//│ |x| |#=| |#if| |true| |#then| |false| |#else| |maybe|\n//│ Parsed: {x = if (true) then false else maybe}\n\n:pe\nx =\n  if true then\ny = 1\n//│ |x| |#=|→|#if| |true| |#then|←|↵|y| |#=| |1|\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.264: \t  if true then\n//│ ╙──       \t              ^\n//│ Parsed: {x = {if (true) then undefined}; y = 1}\n\nif a ==\n  0 and b ==\n    2 then \"false\"\n    else \"1\"\n  1 then \"true\"\n  else \"2\"\n//│ |#if| |a| |==|→|0| |and| |b| |==|→|2| |#then| |\"false\"|↵|#else| |\"1\"|←|↵|1| |#then| |\"true\"|↵|#else| |\"2\"|←|\n//│ Parsed: {if a == ‹0 and b == ‹(2) then \"false\"; else \"1\"›; (1) then \"true\"; else \"2\"›}\n\n:pe\n2 and b then \"\"\n//│ |2| |and| |b| |#then| |\"\"|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.282: \t2 and b then \"\"\n//│ ╙──       \t^^^^^^^^^^^^^^^\n//│ Parsed: {undefined}\n\n2 and b == 0\n//│ |2| |and| |b| |==| |0|\n//│ Parsed: {and(2,)(==(b,)(0,),)}\n\nif x ==\n  2 and b then \"\"\n//│ |#if| |x| |==|→|2| |and| |b| |#then| |\"\"|←|\n//│ Parsed: {if x == ‹(and(2,)(b,)) then \"\"›}\n\nif x ==\n  2 and b == 1 then \"\"\n//│ |#if| |x| |==|→|2| |and| |b| |==| |1| |#then| |\"\"|←|\n//│ Parsed: {if x == ‹(and(2,)(==(b,)(1,),)) then \"\"›}\n\nif\n  x == 0 then \"x\"\n  y ==\n    1 then \"y = 1\"\n    2 and z == 0 then \"z = 0\"\n    3 then \"y = 3\"\n//│ |#if|→|x| |==| |0| |#then| |\"x\"|↵|y| |==|→|1| |#then| |\"y = 1\"|↵|2| |and| |z| |==| |0| |#then| |\"z = 0\"|↵|3| |#then| |\"y = 3\"|←|←|\n//│ Parsed: {if ‹(==(x,)(0,)) then \"x\"; y == ‹(1) then \"y = 1\"; (and(2,)(==(z,)(0,),)) then \"z = 0\"; (3) then \"y = 3\"››}\n\n:pe\nelse 1\n//│ |#else| |1|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.313: \telse 1\n//│ ╙──       \t^^^^^^\n//│ Parsed: {undefined}\n\n:pe\n1 else 2\n//│ |1| |#else| |2|\n//│ ╔══[PARSE ERROR] Expected end of input; found 'else' keyword instead\n//│ ║  l.321: \t1 else 2\n//│ ╙──       \t  ^^^^\n//│ Parsed: {1}\n\n\nif a then if b then c else d\n//│ |#if| |a| |#then| |#if| |b| |#then| |c| |#else| |d|\n//│ Parsed: {if (a) then if (b) then c else d}\n\nif a then if b then c else d else e\n//│ |#if| |a| |#then| |#if| |b| |#then| |c| |#else| |d| |#else| |e|\n//│ Parsed: {if (a) then if (b) then c else d else e}\n\n\nif a is\n  Left(x) then x\n  let y = a + 1\n  Right(0) then y\n//│ |#if| |a| |is|→|Left|(|x|)| |#then| |x|↵|#let| |y| |#=| |a| |+| |1|↵|Right|(|0|)| |#then| |y|←|\n//│ Parsed: {if a is ‹(Left(x,)) then x; let y = +(a,)(1,); (Right(0,)) then y›}\n\nif a is\n  Some(v) and v is\n    Left(x) then x\n    let y = v + 1\n    Right(0) then y\n    Right(x) then x + y\n  else 0\n//│ |#if| |a| |is|→|Some|(|v|)| |and| |v| |is|→|Left|(|x|)| |#then| |x|↵|#let| |y| |#=| |v| |+| |1|↵|Right|(|0|)| |#then| |y|↵|Right|(|x|)| |#then| |x| |+| |y|←|↵|#else| |0|←|\n//│ Parsed: {if a is ‹Some(v,) and v is ‹(Left(x,)) then x; let y = +(v,)(1,); (Right(0,)) then y; (Right(x,)) then +(x,)(y,)›; else 0›}\n\nif a is\n  Some(x) and x is\n    Left(a)  then \"left-defined\"\n    let y = x + 1\n    Right(b) then \"right-defined\"\n  None       then \"undefined\"\n//│ |#if| |a| |is|→|Some|(|x|)| |and| |x| |is|→|Left|(|a|)| |#then| |\"left-defined\"|↵|#let| |y| |#=| |x| |+| |1|↵|Right|(|b|)| |#then| |\"right-defined\"|←|↵|None| |#then| |\"undefined\"|←|\n//│ Parsed: {if a is ‹Some(x,) and x is ‹(Left(a,)) then \"left-defined\"; let y = +(x,)(1,); (Right(b,)) then \"right-defined\"›; (None) then \"undefined\"›}\n\n:w\nif a is\n  Left x then x\n//│ |#if| |a| |is|→|Left| |x| |#then| |x|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.366: \t  Left x then x\n//│ ╙──       \t  ^^^^^^\n//│ Parsed: {if a is ‹(Left(x,)) then x›}\n\n// TODO\nif a is\n  Left(x) then x\n  let y = a + 1\n  then y\n//│ |#if| |a| |is|→|Left|(|x|)| |#then| |x|↵|#let| |y| |#=| |a| |+| |1|↵|#then| |y|←|\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.376: \t  let y = a + 1\n//│ ║         \t          ^^^^^\n//│ ║  l.377: \t  then y\n//│ ╙──       \t^^^^^^^^\n//│ Parsed: {if a is ‹(Left(x,)) then x; let y = undefined›}\n\n\n\n// --- // COMPARISONS // --- //\n\n// Rust/Swift:\n:pe\nif let Some(x) = v then 123\n//│ |#if| |#let| |Some|(|x|)| |#=| |v| |#then| |123|\n//│ ╔══[PARSE ERROR] Expected '='; found parenthesis section instead\n//│ ║  l.392: \tif let Some(x) = v then 123\n//│ ╙──       \t           ^^^\n//│ ╔══[PARSE ERROR] Unexpected '=' in expression position\n//│ ║  l.392: \tif let Some(x) = v then 123\n//│ ╙──       \t               ^\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.392: \tif let Some(x) = v then 123\n//│ ╙──       \t                 ^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found let binding instead\n//│ ║  l.392: \tif let Some(x) = v then 123\n//│ ║         \t                           ^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.392: \tif let Some(x) = v then 123\n//│ ╙──       \t^^\n//│ Parsed: {if (let Some = undefined in undefined) then undefined}\n\n// Swift:\n:pe\nif let Some(x) = v and cond then 123\n//│ |#if| |#let| |Some|(|x|)| |#=| |v| |and| |cond| |#then| |123|\n//│ ╔══[PARSE ERROR] Expected '='; found parenthesis section instead\n//│ ║  l.413: \tif let Some(x) = v and cond then 123\n//│ ╙──       \t           ^^^\n//│ ╔══[PARSE ERROR] Unexpected '=' in expression position\n//│ ║  l.413: \tif let Some(x) = v and cond then 123\n//│ ╙──       \t               ^\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.413: \tif let Some(x) = v and cond then 123\n//│ ╙──       \t                 ^^^^^^^^^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found let binding instead\n//│ ║  l.413: \tif let Some(x) = v and cond then 123\n//│ ║         \t                                    ^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.413: \tif let Some(x) = v and cond then 123\n//│ ╙──       \t^^\n//│ Parsed: {if (let Some = undefined in undefined) then undefined}\n\n// MLscript:\nif v is Some(x) and x is Left(y) then 123\n//│ |#if| |v| |is| |Some|(|x|)| |and| |x| |is| |Left|(|y|)| |#then| |123|\n//│ Parsed: {if (and(is(v,)(Some(x,),),)(is(x,)(Left(y,),),)) then 123}\n\n// ML:\nlet Some(x) = v\n//│ |#let| |Some|(|x|)| |#=| |v|\n//│ Parsed: {let Some = (x,) => v}\n\nv as Some(x)\n//│ |v| |as| |Some|(|x|)|\n//│ Parsed: {as(v,)(Some(x,),)}\n\n\n\n\n:pe\nif true\n  then 0\n  + 1\n//│ |#if| |true|→|#then| |0|↵|+| |1|←|\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.452: \t  + 1\n//│ ╙──       \t  ^\n//│ Parsed: {if (true) then 0}\n\nif true\n  then 0\n    + 1\n//│ |#if| |true|→|#then| |0|→|+| |1|←|←|\n//│ Parsed: {if (true) then +(0, 1,)}\n\nif true\n  then 0\n  else 0\n//│ |#if| |true|→|#then| |0|↵|#else| |0|←|\n//│ Parsed: {if (true) then 0 else 0}\n\nif true\n  then 0\n  else 0\n    + 1\n//│ |#if| |true|→|#then| |0|↵|#else| |0|→|+| |1|←|←|\n//│ Parsed: {if (true) then 0 else +(0, 1,)}\n\n:pe\nif true\n    then 0\n  + 1\n//│ |#if| |true|→|#then| |0|←|→|+| |1|←|\n//│ ╔══[PARSE ERROR] Expected end of input; found indented block instead\n//│ ║  l.481: \t  + 1\n//│ ╙──       \t^^\n//│ Parsed: {if (true) then 0}\n\n:pe\nif true\n    then 0\n    else 0\n  + 1\n//│ |#if| |true|→|#then| |0|↵|#else| |0|←|→|+| |1|←|\n//│ ╔══[PARSE ERROR] Expected end of input; found indented block instead\n//│ ║  l.492: \t  + 1\n//│ ╙──       \t^^\n//│ Parsed: {if (true) then 0 else 0}\n\nif true then 0\n  + 1\n//│ |#if| |true| |#then| |0|→|+| |1|←|\n//│ Parsed: {if (true) then +(0, 1,)}\n\nif true then 0 else 0\n  + 1\n//│ |#if| |true| |#then| |0| |#else| |0|→|+| |1|←|\n//│ Parsed: {if (true) then 0 else +(0, 1,)}\n\n\n// TODO deal with meaningless whitespace:\n\nif true\n  then 0\n  \n//│ |#if| |true|→|#then| |0|↵|←|\n//│ Parsed: {if (true) then 0}\n\n// TODO ignore empty indented blocks/lines\nif true\n  then 0\n    \n//│ |#if| |true|→|#then| |0|←|\n//│ Parsed: {if (true) then 0}\n\n\n:pe\n(if true)\n//│ |(|#if| |true|)|\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found reference instead\n//│ ║  l.527: \t(if true)\n//│ ║         \t    ^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.527: \t(if true)\n//│ ╙──       \t ^^\n//│ Parsed: {'(' if (true) then undefined ')'}\n\n:pe\n(if true then)\n//│ |(|#if| |true| |#then|)|\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.538: \t(if true then)\n//│ ╙──       \t             ^\n//│ Parsed: {'(' if (true) then undefined ')'}\n\nif true then;\n//│ |#if| |true| |#then|;|\n//│ Parsed: {if (true) then undefined}\n\nif true then;\n//│ |#if| |true| |#then|;|\n//│ Parsed: {if (true) then undefined}\n\n:pe\nif true then; else;\n//│ |#if| |true| |#then|;| |#else|;|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.554: \tif true then; else;\n//│ ╙──       \t              ^^^^^\n//│ Parsed: {if (true) then undefined; undefined}\n\nif true then () else;\n//│ |#if| |true| |#then| |(||)| |#else|;|\n//│ Parsed: {if (true) then undefined else undefined}\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Lambdas.mls",
    "content": ":AllowParseErrors\n\n\nx => x\n//│ |x| |#=>| |x|\n//│ Parsed: {(x,) => x}\n\n(x) => x\n//│ |(|x|)| |#=>| |x|\n//│ Parsed: {('(' x ')',) => x}\n\n// TODO\nfun x => x\n//│ |#fun| |x| |#=>| |x|\n//│ ╔══[PARSE ERROR] Expected function parameter list; found '=>' instead\n//│ ║  l.13: \tfun x => x\n//│ ╙──      \t      ^^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found identifier instead\n//│ ║  l.13: \tfun x => x\n//│ ╙──      \t         ^\n//│ Parsed: {fun x = undefined}\n\n// TODO\nlet f = fun x => x\n//│ |#let| |f| |#=| |#fun| |x| |#=>| |x|\n//│ ╔══[PARSE ERROR] Unexpected 'fun' keyword in expression position\n//│ ║  l.24: \tlet f = fun x => x\n//│ ╙──      \t        ^^^\n//│ Parsed: {let f = (x,) => x}\n\n\nfun f x = x\n//│ |#fun| |f| |x| |#=| |x|\n//│ ╔══[PARSE ERROR] Expected function parameter list; found identifier instead\n//│ ║  l.32: \tfun f x = x\n//│ ╙──      \t      ^\n//│ Parsed: {fun f = x}\n\n\n(x, y) => x\n//│ |(|x|,| |y|)| |#=>| |x|\n//│ Parsed: {(x, y,) => x}\n\n\n=> 1\n//│ |#=>| |1|\n//│ ╔══[PARSE ERROR] Unexpected '=>' in expression position\n//│ ║  l.45: \t=> 1\n//│ ╙──      \t^^\n//│ Parsed: {1}\n\nx =>\n//│ |x| |#=>|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.52: \tx =>\n//│ ╙──      \t    ^\n//│ Parsed: {(x,) => undefined}\n\n(x =>)\n//│ |(|x| |#=>|)|\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.59: \t(x =>)\n//│ ╙──      \t     ^\n//│ Parsed: {'(' (x,) => undefined ')'}\n\na --> b --> c\n//│ |a| |-->| |b| |-->| |c|\n//│ Parsed: {-->(a,)(-->(b,)(c,),)}\n\na => b => c\n//│ |a| |#=>| |b| |#=>| |c|\n//│ Parsed: {(a,) => (b,) => c}\n\n(a => b) => c\n//│ |(|a| |#=>| |b|)| |#=>| |c|\n//│ Parsed: {('(' (a,) => b ')',) => c}\n\na => (b => c)\n//│ |a| |#=>| |(|b| |#=>| |c|)|\n//│ Parsed: {(a,) => '(' (b,) => c ')'}\n\nxs.forall(x => x > 0)\n//│ |xs|.forall|(|x| |#=>| |x| |>| |0|)|\n//│ Parsed: {(xs).forall((x,) => >(x,)(0,),)}\n\nxs.forall of x => x > 0\n//│ |xs|.forall| |#of| |x| |#=>| |x| |>| |0|\n//│ Parsed: {(xs).forall((x,) => >(x,)(0,),)}\n\n:pe\na => b then c\n//│ |a| |#=>| |b| |#then| |c|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.91: \ta => b then c\n//│ ╙──      \t^^^^^^^^^^^^^\n//│ Parsed: {undefined}\n\nif a => b then c\n//│ |#if| |a| |#=>| |b| |#then| |c|\n//│ Parsed: {if ((a,) => b) then c}\n\nif xs.forall(a => b) then c\n//│ |#if| |xs|.forall|(|a| |#=>| |b|)| |#then| |c|\n//│ Parsed: {if ((xs).forall((a,) => b,)) then c}\n\nif xs.forall of a => b then c\n//│ |#if| |xs|.forall| |#of| |a| |#=>| |b| |#then| |c|\n//│ Parsed: {if ((xs).forall((a,) => b,)) then c}\n\n\nid + of x => x + 1\n//│ |id| |+| |#of| |x| |#=>| |x| |+| |1|\n//│ ╔══[PARSE ERROR] Unexpected 'of' keyword in expression position\n//│ ║  l.111: \tid + of x => x + 1\n//│ ╙──       \t     ^^\n//│ Parsed: {+(id,)((x,) => +(x,)(1,),)}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Lets.mls",
    "content": ":AllowParseErrors\n\n\nlet x = 1\n//│ |#let| |x| |#=| |1|\n//│ Parsed: {let x = 1}\n\nlet x = 1, y = 2\n//│ |#let| |x| |#=| |1|,| |y| |#=| |2|\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' instead\n//│ ║  l.8: \tlet x = 1, y = 2\n//│ ╙──     \t             ^\n//│ Parsed: {let x = ,(1, y,)}\n\nlet x = 1, y = 2\nx + y\n//│ |#let| |x| |#=| |1|,| |y| |#=| |2|↵|x| |+| |y|\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' instead\n//│ ║  l.15: \tlet x = 1, y = 2\n//│ ╙──      \t             ^\n//│ Parsed: {let x = ,(1, y,)}\n\nlet x = 1 in x + 1\n//│ |#let| |x| |#=| |1| |#in| |x| |+| |1|\n//│ Parsed: {let x = 1 in +(x,)(1,)}\n\nlet x = 1, y = 2 in x + y\n//│ |#let| |x| |#=| |1|,| |y| |#=| |2| |#in| |x| |+| |y|\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' instead\n//│ ║  l.27: \tlet x = 1, y = 2 in x + y\n//│ ╙──      \t             ^\n//│ Parsed: {let x = ,(1, y,)}\n\nlet in 123\n//│ |#let| |#in| |123|\n//│ ╔══[PARSE ERROR] Expected a function name; found 'in' keyword instead\n//│ ║  l.34: \tlet in 123\n//│ ╙──      \t    ^^\n//│ ╔══[PARSE ERROR] Expected function parameter list; found literal instead\n//│ ║  l.34: \tlet in 123\n//│ ╙──      \t       ^^^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found end of input instead\n//│ ║  l.34: \tlet in 123\n//│ ╙──      \t          ^\n//│ Parsed: {let <error> = undefined}\n\nlet x = 1; x + 1\n//│ |#let| |x| |#=| |1|;| |x| |+| |1|\n//│ Parsed: {let x = 1; +(x,)(1,)}\n\nlet x = 1, y = 2; x + y\n//│ |#let| |x| |#=| |1|,| |y| |#=| |2|;| |x| |+| |y|\n//│ ╔══[PARSE ERROR] Expected end of input; found '=' instead\n//│ ║  l.51: \tlet x = 1, y = 2; x + y\n//│ ╙──      \t             ^\n//│ Parsed: {let x = ,(1, y,)}\n\n\n\n\nlet in person be the default in following meetings\n//│ |#let| |#in| |person| |be| |the| |default| |#in| |following| |meetings|\n//│ ╔══[PARSE ERROR] Expected a function name; found 'in' keyword instead\n//│ ║  l.61: \tlet in person be the default in following meetings\n//│ ╙──      \t    ^^\n//│ ╔══[PARSE ERROR] Expected function parameter list; found identifier instead\n//│ ║  l.61: \tlet in person be the default in following meetings\n//│ ╙──      \t       ^^^^^^\n//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found identifier instead\n//│ ║  l.61: \tlet in person be the default in following meetings\n//│ ╙──      \t              ^^\n//│ ╔══[PARSE ERROR] Expected end of input; found identifier instead\n//│ ║  l.61: \tlet in person be the default in following meetings\n//│ ╙──      \t                 ^^^\n//│ Parsed: {let <error> = undefined}\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Misc.mls",
    "content": ":AllowParseErrors\n\n\nfun discard(x) = ()\n//│ |#fun| |discard|(|x|)| |#=| |(||)|\n//│ Parsed: {fun discard = (x,) => undefined}\n\n// FIXME parses wrong:\nfoo of\n  discard of if f of x is\n    Some(v) then v + 1\n    None    then 0\n  if g of y is\n    Some(v) then v + 1\n    None    then 0,  \n//│ |foo| |#of|→|discard| |#of| |#if| |f| |#of| |x| |is|→|Some|(|v|)| |#then| |v| |+| |1|↵|None| |#then| |0|←|↵|#if| |g| |#of| |y| |is|→|Some|(|v|)| |#then| |v| |+| |1|↵|None| |#then| |0|,| |←|←|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.10: \t  discard of if f of x is\n//│ ║        \t                     ^^^^\n//│ ║  l.11: \t    Some(v) then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.12: \t    None    then 0\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application followed by newline instead\n//│ ║  l.10: \t  discard of if f of x is\n//│ ║        \t                ^^^^^^^^^\n//│ ║  l.11: \t    Some(v) then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.12: \t    None    then 0\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.13: \t  if g of y is\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.14: \t    Some(v) then v + 1\n//│ ║        \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.10: \t  discard of if f of x is\n//│ ╙──      \t             ^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.15: \t    None    then 0,  \n//│ ╙──      \t                     ^\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.13: \t  if g of y is\n//│ ║        \t          ^^^^\n//│ ║  l.14: \t    Some(v) then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.15: \t    None    then 0,  \n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.13: \t  if g of y is\n//│ ║        \t     ^^^^^^^^^\n//│ ║  l.14: \t    Some(v) then v + 1\n//│ ║        \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.13: \t  if g of y is\n//│ ╙──      \t  ^^\n//│ Parsed: {foo({discard(if (f(undefined,)) then undefined,); if (g(undefined,)) then undefined},)}\n\nfoo of\n  if f of x is\n    Some v then v + 1\n    None   then 0,\n  if g of y is\n    Some v then v + 1\n    None   then 0,\n  \n//│ |foo| |#of|→|#if| |f| |#of| |x| |is|→|Some| |v| |#then| |v| |+| |1|↵|None| |#then| |0|,|←|↵|#if| |g| |#of| |y| |is|→|Some| |v| |#then| |v| |+| |1|↵|None| |#then| |0|,|←|↵|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.60: \t    Some v then v + 1\n//│ ╙──      \t    ^^^^^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.61: \t    None   then 0,\n//│ ╙──      \t                  ^\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.59: \t  if f of x is\n//│ ║        \t          ^^^^\n//│ ║  l.60: \t    Some v then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.61: \t    None   then 0,\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application followed by newline instead\n//│ ║  l.59: \t  if f of x is\n//│ ║        \t     ^^^^^^^^^\n//│ ║  l.60: \t    Some v then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.61: \t    None   then 0,\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.62: \t  if g of y is\n//│ ║        \t^^^^^^^^^^^^^^\n//│ ║  l.63: \t    Some v then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.64: \t    None   then 0,\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.65: \t  \n//│ ║        \t^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.59: \t  if f of x is\n//│ ╙──      \t  ^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.63: \t    Some v then v + 1\n//│ ╙──      \t    ^^^^^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.64: \t    None   then 0,\n//│ ╙──      \t                  ^\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.62: \t  if g of y is\n//│ ║        \t          ^^^^\n//│ ║  l.63: \t    Some v then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.64: \t    None   then 0,\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application followed by newline instead\n//│ ║  l.62: \t  if g of y is\n//│ ║        \t     ^^^^^^^^^\n//│ ║  l.63: \t    Some v then v + 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.64: \t    None   then 0,\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.65: \t  \n//│ ║        \t^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.62: \t  if g of y is\n//│ ╙──      \t  ^^\n//│ Parsed: {foo({if (f(undefined,)) then undefined; if (g(undefined,)) then undefined},)}\n\nprint of Foo(x) is Some\n//│ |print| |#of| |Foo|(|x|)| |is| |Some|\n//│ Parsed: {print(is(Foo(x,),)(Some,),)}\n\n// FIXME parses wrong:\nif f of x is Some then 1 else 0\n//│ |#if| |f| |#of| |x| |is| |Some| |#then| |1| |#else| |0|\n//│ Parsed: {if (f(is(x,)(Some,),)) then 1 else 0}\n\nif f of 0 and g of 1 then \"ok\"\n//│ |#if| |f| |#of| |0| |and| |g| |#of| |1| |#then| |\"ok\"|\n//│ Parsed: {if (f(and(0,)(g(1,),),)) then \"ok\"}\n\nA and B or C and D\n//│ |A| |and| |B| |or| |C| |and| |D|\n//│ Parsed: {or(and(A,)(B,),)(and(C,)(D,),)}\n"
  },
  {
    "path": "shared/src/test/diff/parser/MultiLineCalls.mls",
    "content": ":AllowParseErrors\n\n\nf (\n  0\n)\n//│ |f| |(|→|0|←|↵|)|\n//│ Parsed: {f(0,)}\n\nf (\n  0,\n  1\n)\n//│ |f| |(|→|0|,|↵|1|←|↵|)|\n//│ Parsed: {f(0, 1,)}\n\nf (\n  0,\n  1,\n)\n//│ |f| |(|→|0|,|↵|1|,|←|↵|)|\n//│ Parsed: {f(0, 1,)}\n\nf (0, 1)\n//│ |f| |(|0|,| |1|)|\n//│ Parsed: {f(0, 1,)}\n\nf (0, 1,)\n//│ |f| |(|0|,| |1|,|)|\n//│ Parsed: {f(0, 1,)}\n\nf (0, 1,\n)\n//│ |f| |(|0|,| |1|,|↵|)|\n//│ Parsed: {f(0, 1,)}\n\nf(,)\n//│ |f|(|,|)|\n//│ ╔══[PARSE ERROR] Unexpected comma in expression position\n//│ ║  l.37: \tf(,)\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.37: \tf(,)\n//│ ╙──      \t   ^\n//│ Parsed: {f(undefined,)}\n\nf (\n  0\n  1\n)\n//│ |f| |(|→|0|↵|1|←|↵|)|\n//│ Parsed: {f({0; 1},)}\n\nf of\n  0,\n  1\n//│ |f| |#of|→|0|,|↵|1|←|\n//│ Parsed: {f(0, 1,)}\n\nf of\n  0\n  1\n//│ |f| |#of|→|0|↵|1|←|\n//│ Parsed: {f({0; 1},)}\n\n// :pe\nf\nof  0\n//│ |f|↵|#of| |0|\n//│ ╔══[PARSE ERROR] Unexpected 'of' keyword in expression position\n//│ ║  l.68: \tof  0\n//│ ╙──      \t^^\n//│ Parsed: {f; 0}\n\nf\n  (0)\n//│ |f|→|(|0|)|←|\n//│ Parsed: {f(0,)}\n\n// TODO\nf\n  of 0\n  of 1\n//│ |f|→|#of| |0|↵|#of| |1|←|\n//│ Parsed: {f(0,)(1,)}\n\nf\n  (0)\n  (1)\n//│ |f|→|(|0|)|↵|(|1|)|←|\n//│ Parsed: {f(0,)(1,)}\n\nf\n  of\n    0,\n    1\n//│ |f|→|#of|→|0|,|↵|1|←|←|\n//│ Parsed: {f(0, 1,)}\n\n2 + 2\n  (0)\n//│ |2| |+| |2|→|(|0|)|←|\n//│ Parsed: {+(2,)(2,)(0,)}\n\n2 + 2\n  of 0\n//│ |2| |+| |2|→|#of| |0|←|\n//│ Parsed: {+(2,)(2,)(0,)}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/MultilineFun.mls",
    "content": ":AllowParseErrors\n\n\nfun f(\n  x\n) = x\n//│ |#fun| |f|(|→|x|←|↵|)| |#=| |x|\n//│ Parsed: {fun f = (x,) => x}\n\nfun f(x\n) = x\n//│ |#fun| |f|(|x|↵|)| |#=| |x|\n//│ Parsed: {fun f = (x,) => x}\n\nfun f(\n  x) = x\n//│ |#fun| |f|(|→|x|←|)| |#=| |x|\n//│ Parsed: {fun f = (x,) => x}\n\nfun f(\nx) = x\n//│ |#fun| |f|(|↵|x|)| |#=| |x|\n//│ ╔══[PARSE ERROR] Unexpected identifier here\n//│ ║  l.21: \tx) = x\n//│ ╙──      \t^\n//│ Parsed: {fun f = () => x}\n\nfun f(x,\n  y) = x + y\n//│ |#fun| |f|(|x|,|→|y|←|)| |#=| |x| |+| |y|\n//│ Parsed: {fun f = (x, {y},) => +(x,)(y,)}\n\nfun f(\n  x,\n  y) = x + y\n//│ |#fun| |f|(|→|x|,|↵|y|←|)| |#=| |x| |+| |y|\n//│ Parsed: {fun f = (x, y,) => +(x,)(y,)}\n\nfun f(\n  x,\n  y\n) = x + y\n//│ |#fun| |f|(|→|x|,|↵|y|←|↵|)| |#=| |x| |+| |y|\n//│ Parsed: {fun f = (x, y,) => +(x,)(y,)}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/NamedArrays.mls",
    "content": ":AllowParseErrors\n\n\n[]\n//│ |[||]|\n//│ Parsed: {[]}\n\n[x: 1]\n//│ |[|x|#:| |1|]|\n//│ Parsed: {[x: 1,]}\n\n[x : 1]\n//│ |[|x| |#:| |1|]|\n//│ Parsed: {[x : 1,]}\n\n[x: 1,]\n//│ |[|x|#:| |1|,|]|\n//│ Parsed: {[x: 1,]}\n\n[x: 1, y:]\n//│ |[|x|#:| |1|,| |y|#:|]|\n//│ ╔══[PARSE ERROR] Unexpected end of square bracket section; an expression was expected here\n//│ ║  l.20: \t[x: 1, y:]\n//│ ╙──      \t         ^\n//│ Parsed: {[x: 1, y: undefined,]}\n\n[x:, y: 1]\n//│ |[|x|#:|,| |y|#:| |1|]|\n//│ ╔══[PARSE ERROR] Unexpected comma in expression position\n//│ ║  l.27: \t[x:, y: 1]\n//│ ╙──      \t   ^\n//│ Parsed: {[x: y : 1,]}\n\n[x:, y:]\n//│ |[|x|#:|,| |y|#:|]|\n//│ ╔══[PARSE ERROR] Unexpected comma in expression position\n//│ ║  l.34: \t[x:, y:]\n//│ ╙──      \t   ^\n//│ ╔══[PARSE ERROR] Unexpected end of square bracket section; an expression was expected here\n//│ ║  l.34: \t[x:, y:]\n//│ ╙──      \t       ^\n//│ Parsed: {[x: y : (),]}\n\n[x: 1, 2, 3]\n//│ |[|x|#:| |1|,| |2|,| |3|]|\n//│ Parsed: {[x: 1, 2, 3,]}\n\n[1, y: 2, 3]\n//│ |[|1|,| |y|#:| |2|,| |3|]|\n//│ Parsed: {[1, y: 2, 3,]}\n\n[x: 1, y: 2, z: 3]\n//│ |[|x|#:| |1|,| |y|#:| |2|,| |z|#:| |3|]|\n//│ Parsed: {[x: 1, y: 2, z: 3,]}\n\n()\n//│ |(||)|\n//│ Parsed: {undefined}\n\n(x: 1)\n//│ |(|x|#:| |1|)|\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.60: \t(x: 1)\n//│ ╙──      \t ^^^^\n//│ Parsed: {1}\n\n(x:)\n//│ |(|x|#:|)|\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.67: \t(x:)\n//│ ╙──      \t   ^\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.67: \t(x:)\n//│ ╙──      \t ^^\n//│ Parsed: {undefined}\n\n(x: 1,)\n//│ |(|x|#:| |1|,|)|\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.77: \t(x: 1,)\n//│ ╙──      \t ^^^^\n//│ Parsed: {1}\n\n(x: 1, 2, 3)\n//│ |(|x|#:| |1|,| |2|,| |3|)|\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.84: \t(x: 1, 2, 3)\n//│ ╙──      \t ^^^^\n//│ Parsed: {,(1, ,(2, 3,),)}\n\n(1, y: 2, 3)\n//│ |(|1|,| |y|#:| |2|,| |3|)|\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.91: \t(1, y: 2, 3)\n//│ ╙──      \t    ^^^^\n//│ Parsed: {,(1, ,(2, 3,),)}\n\n(x: 1, y: 2, z: 3)\n//│ |(|x|#:| |1|,| |y|#:| |2|,| |z|#:| |3|)|\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.98: \t(x: 1, y: 2, z: 3)\n//│ ╙──      \t ^^^^\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.98: \t(x: 1, y: 2, z: 3)\n//│ ╙──      \t       ^^^^\n//│ ╔══[PARSE ERROR] Illegal position for field specification\n//│ ║  l.98: \t(x: 1, y: 2, z: 3)\n//│ ╙──      \t             ^^^^\n//│ Parsed: {,(1, ,(2, 3,),)}\n\n\n1\n//│ |1|\n//│ Parsed: {1}\n\nx: 1\n//│ |x|#:| |1|\n//│ Parsed: {x : 1}\n\n1,\n//│ |1|,|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.120: \t1,\n//│ ╙──       \t  ^\n//│ Parsed: {,(1, undefined,)}\n\nx: 1,\n//│ |x|#:| |1|,|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.127: \tx: 1,\n//│ ╙──       \t     ^\n//│ Parsed: {x : ,[1, ()]}\n\n1, 2, 3\n//│ |1|,| |2|,| |3|\n//│ Parsed: {,(1, ,(2, 3,),)}\n\nf of 1, 2, 3\n//│ |f| |#of| |1|,| |2|,| |3|\n//│ Parsed: {f(1, 2, 3,)}\n\nf of x: 1, y: 2, z: 3\n//│ |f| |#of| |x|#:| |1|,| |y|#:| |2|,| |z|#:| |3|\n//│ Parsed: {f(x: 1, y: 2, z: 3,)}\n\nf of x: 1, 2, z: 3\n//│ |f| |#of| |x|#:| |1|,| |2|,| |z|#:| |3|\n//│ Parsed: {f(x: 1, 2, z: 3,)}\n\nf of\n  x: 1, 2, 3\n//│ |f| |#of|→|x|#:| |1|,| |2|,| |3|←|\n//│ Parsed: {f(x: 1, 2, 3,)}\n\nf of\n  x: 1,\n  y: 2,\n  z: 3\n//│ |f| |#of|→|x|#:| |1|,|↵|y|#:| |2|,|↵|z|#:| |3|←|\n//│ Parsed: {f(x: 1, y: 2, z: 3,)}\n\nf of\n  x: 1\n  y: 2\n  z: 3\n//│ |f| |#of|→|x|#:| |1|↵|y|#:| |2|↵|z|#:| |3|←|\n//│ ╔══[PARSE ERROR] Unexpected named argument name here\n//│ ║  l.163: \t  x: 1\n//│ ╙──       \t  ^\n//│ ╔══[PARSE ERROR] Unexpected named argument name here\n//│ ║  l.164: \t  y: 2\n//│ ╙──       \t  ^\n//│ Parsed: {f(z: {1; 2; 3},)}\n\nf of\n  x: 1\n  2\n  z: 3\n//│ |f| |#of|→|x|#:| |1|↵|2|↵|z|#:| |3|←|\n//│ ╔══[PARSE ERROR] Unexpected named argument name here\n//│ ║  l.176: \t  x: 1\n//│ ╙──       \t  ^\n//│ Parsed: {f(z: {1; 2; 3},)}\n\nf of\n  x: 1\n  y: 2\n  3\n//│ |f| |#of|→|x|#:| |1|↵|y|#:| |2|↵|3|←|\n//│ ╔══[PARSE ERROR] Unexpected named argument name here\n//│ ║  l.186: \t  x: 1\n//│ ╙──       \t  ^\n//│ ╔══[PARSE ERROR] Unexpected named argument name here\n//│ ║  l.187: \t  y: 2\n//│ ╙──       \t  ^\n//│ Parsed: {f({1; 2; 3},)}\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/NegativeLits.mls",
    "content": ":NewParser\n:ParseOnly\n\ntype MinusOne = -1\n//│ |#type| |MinusOne| |#=| |-|1|\n//│ Parsed: {type alias MinusOne: -1 {}}\n\nfun f(x: MinusOne) = x\n//│ |#fun| |f|(|x|#:| |MinusOne|)| |#=| |x|\n//│ Parsed: {fun f = (x: MinusOne,) => x}\n\nf(-1)\n//│ |f|(|-|1|)|\n//│ Parsed: {f(-1,)}\n"
  },
  {
    "path": "shared/src/test/diff/parser/New.mls",
    "content": "\n\n:pe\nnew\n//│ |#new|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.4: \tnew\n//│ ╙──     \t   ^\n//│ Parsed: {new undefined}\n\n:pe\n(new)\n//│ |(|#new|)|\n//│ ╔══[PARSE ERROR] Unexpected end of parenthesis section; an expression was expected here\n//│ ║  l.12: \t(new)\n//│ ╙──      \t    ^\n//│ Parsed: {'(' new undefined ')'}\n\nnew {}\n//│ |#new| |{||}|\n//│ Parsed: {new '{' {} '}'}\n\nnew A\n//│ |#new| |A|\n//│ Parsed: {new A}\n\nnew A()\n//│ |#new| |A|(||)|\n//│ Parsed: {(new A)()}\n\nnew A(1, 2, 3)\n//│ |#new| |A|(|1|,| |2|,| |3|)|\n//│ Parsed: {(new A)(1, 2, 3,)}\n\nnew A of 1, 2, 3\n//│ |#new| |A| |#of| |1|,| |2|,| |3|\n//│ Parsed: {new A(1, 2, 3,)}\n\nnew A { fun x = 1 }\n//│ |#new| |A| |{| |#fun| |x| |#=| |1| |}|\n//│ Parsed: {new A {fun x = 1}}\n\nnew A() { fun x = 1 }\n//│ |#new| |A|(||)| |{| |#fun| |x| |#=| |1| |}|\n//│ Parsed: {(new A)() {fun x = 1}}\n\nnew A(1, 2, 3) { fun x = 1 }\n//│ |#new| |A|(|1|,| |2|,| |3|)| |{| |#fun| |x| |#=| |1| |}|\n//│ Parsed: {(new A)(1, 2, 3,) {fun x = 1}}\n\nnew A of 1, 2, 3 { fun x = 1 }\n//│ |#new| |A| |#of| |1|,| |2|,| |3| |{| |#fun| |x| |#=| |1| |}|\n//│ Parsed: {new A(1, 2, 3 {fun x = 1},)}\n\n\n:pe\nnew new\n//│ |#new| |#new|\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.57: \tnew new\n//│ ╙──      \t       ^\n//│ Parsed: {new new undefined}\n\nnew new {}\n//│ |#new| |#new| |{||}|\n//│ Parsed: {new new '{' {} '}'}\n\n:pe\nnew {new}\n//│ |#new| |{|#new|}|\n//│ ╔══[PARSE ERROR] Unexpected end of curly brace section; an expression was expected here\n//│ ║  l.69: \tnew {new}\n//│ ╙──      \t        ^\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.69: \tnew {new}\n//│ ╙──      \t     ^^^\n//│ Parsed: {new '{' {<error>: new undefined} '}'}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Ops.mls",
    "content": ":AllowParseErrors\n\n\nacc + 1\n//│ |acc| |+| |1|\n//│ Parsed: {+(acc,)(1,)}\n\nacc\n+ 1\n//│ |acc|↵|+| |1|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.9: \t+ 1\n//│ ╙──     \t^\n//│ Parsed: {acc; 1}\n\nacc\n  + 1\n//│ |acc|→|+| |1|←|\n//│ Parsed: {+(acc, 1,)}\n\nacc +\n  1\n//│ |acc| |+|→|1|←|\n//│ Parsed: {+(acc,)({1},)}\n\nacc\n  +\n  1\n//│ |acc|→|+|↵|1|←|\n//│ ╔══[PARSE ERROR] Unexpected newline in expression position\n//│ ║  l.27: \t  +\n//│ ║        \t   ^\n//│ ║  l.28: \t  1\n//│ ╙──      \t^^\n//│ Parsed: {+(acc, 1,)}\n\nacc\n  +\n    1\n//│ |acc|→|+|→|1|←|←|\n//│ Parsed: {+(acc, {1},)}\n\nacc\n  + 1\n  * 3\n//│ |acc|→|+| |1|↵|*| |3|←|\n//│ Parsed: {*(+(acc, 1,), 3,)}\n\nacc\n  + 1\n  + 2\n  * 3\n//│ |acc|→|+| |1|↵|+| |2|↵|*| |3|←|\n//│ Parsed: {*(+(+(acc, 1,), 2,), 3,)}\n\nacc + 1 + 2 * 3\n//│ |acc| |+| |1| |+| |2| |*| |3|\n//│ Parsed: {+(+(acc,)(1,),)(*(2,)(3,),)}\n\nacc+1+2*3\n//│ |acc|+|1|+|2|*|3|\n//│ Parsed: {+(+(acc,)(1,),)(*(2,)(3,),)}\n\nacc +\n  foo bar\n  baz\n//│ |acc| |+|→|foo| |bar|↵|baz|←|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.65: \t  foo bar\n//│ ╙──      \t  ^^^^^^^\n//│ Parsed: {+(acc,)({foo(bar,); baz},)}\n\na+\n  b\n  c\n//│ |a|+|→|b|↵|c|←|\n//│ Parsed: {+(a,)({b; c},)}\n\na+\n  b\nc\n//│ |a|+|→|b|←|↵|c|\n//│ Parsed: {+(a,)({b},); c}\n\na\n  +b\nc\n//│ |a|→|+|b|←|↵|c|\n//│ Parsed: {+(a, b,); c}\n\n\na + b\n  * 2\n//│ |a| |+| |b|→|*| |2|←|\n//│ Parsed: {+(a,)(*(b, 2,),)}\n\na(b)\n  * 2\n//│ |a|(|b|)|→|*| |2|←|\n//│ Parsed: {*(a(b,), 2,)}\n\na of b\n  * 2\n//│ |a| |#of| |b|→|*| |2|←|\n//│ Parsed: {a(*(b, 2,),)}\n\na then b\n  * 2\n//│ |a| |#then| |b|→|*| |2|←|\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.107: \ta then b\n//│ ║         \t^^^^^^^^\n//│ ║  l.108: \t  * 2\n//│ ╙──       \t^^^^^\n//│ Parsed: {undefined}\n\na + b\n  * 2\n  + 1\n  * 3\n//│ |a| |+| |b|→|*| |2|↵|+| |1|↵|*| |3|←|\n//│ Parsed: {+(a,)(*(+(*(b, 2,), 1,), 3,),)}\n\na + b\n  * 2\n    + 1\n//│ |a| |+| |b|→|*| |2|→|+| |1|←|←|\n//│ Parsed: {+(a,)(*(b, +(2, 1,),),)}\n\na + b\n    * 2\n  - 1\n//│ |a| |+| |b|→|*| |2|←|→|-| |1|←|\n//│ Parsed: {-(+(a,)(*(b, 2,),), 1,)}\n\na + b\n  * 2\n    + 1\n  * 3\n//│ |a| |+| |b|→|*| |2|→|+| |1|←|↵|*| |3|←|\n//│ Parsed: {+(a,)(*(*(b, +(2, 1,),), 3,),)}\n\na +\n  b\n    * 2\n  + 1\n  * 3\n//│ |a| |+|→|b|→|*| |2|←|↵|+| |1|↵|*| |3|←|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.146: \t  + 1\n//│ ╙──       \t  ^\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.147: \t  * 3\n//│ ╙──       \t  ^\n//│ Parsed: {+(a,)({*(b, 2,); 1; 3},)}\n\na +\n    b\n      * 2\n    + 1\n  * 3\n//│ |a| |+|→|b|→|*| |2|←|↵|+| |1|←|→|*| |3|←|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.160: \t    + 1\n//│ ╙──       \t    ^\n//│ Parsed: {*(+(a,)({*(b, 2,); 1},), 3,)}\n\na +\n  b\n    * 2\n  +\n    1\n      * 3\n//│ |a| |+|→|b|→|*| |2|←|↵|+|→|1|→|*| |3|←|←|←|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.171: \t  +\n//│ ╙──       \t  ^\n//│ Parsed: {+(a,)({*(b, 2,); {*(1, 3,)}},)}\n\na +\n  b\n    * 2\n    +\n      1\n        * 3\n//│ |a| |+|→|b|→|*| |2|↵|+|→|1|→|*| |3|←|←|←|←|\n//│ Parsed: {+(a,)({+(*(b, 2,), {*(1, 3,)},)},)}\n\na +\n  b\n    * 2\n  + 1\n    * 3\n//│ |a| |+|→|b|→|*| |2|←|↵|+| |1|→|*| |3|←|←|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.192: \t  + 1\n//│ ╙──       \t  ^\n//│ Parsed: {+(a,)({*(b, 2,); *(1, 3,)},)}\n\na +\n  b\n    * 2\n    + 1\n      * 3\n//│ |a| |+|→|b|→|*| |2|↵|+| |1|→|*| |3|←|←|←|\n//│ Parsed: {+(a,)({+(*(b, 2,), *(1, 3,),)},)}\n\n\na +\n  b *\n    c\n//│ |a| |+|→|b| |*|→|c|←|←|\n//│ Parsed: {+(a,)({*(b,)({c},)},)}\n\na *\n  b +\n    c\n//│ |a| |*|→|b| |+|→|c|←|←|\n//│ Parsed: {*(a,)({+(b,)({c},)},)}\n\na *\n  let x = 1\n  b +\n    c\n//│ |a| |*|→|#let| |x| |#=| |1|↵|b| |+|→|c|←|←|\n//│ Parsed: {*(a,)({let x = 1; +(b,)({c},)},)}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Records.mls",
    "content": "\n\n{}\n//│ |{||}|\n//│ Parsed: {'{' {} '}'}\n\n{x: 1}\n//│ |{|x|#:| |1|}|\n//│ Parsed: {'{' {x: 1} '}'}\n\n{x: 1,}\n//│ |{|x|#:| |1|,|}|\n//│ Parsed: {'{' {x: 1} '}'}\n\n{x:1,y:2}\n//│ |{|x|#:|1|,|y|#:|2|}|\n//│ Parsed: {'{' {x: 1, y: 2} '}'}\n\n{x: 1, y: 2}\n//│ |{|x|#:| |1|,| |y|#:| |2|}|\n//│ Parsed: {'{' {x: 1, y: 2} '}'}\n\n{ x: 1, y: 2, }\n//│ |{| |x|#:| |1|,| |y|#:| |2|,| |}|\n//│ Parsed: {'{' {x: 1, y: 2} '}'}\n\n{\n  x: 1,\n  y: 2,\n  z: 3,\n}\n//│ |{|→|x|#:| |1|,|↵|y|#:| |2|,|↵|z|#:| |3|,|←|↵|}|\n//│ Parsed: {'{' {x: 1, y: 2, z: 3} '}'}\n\n{x: 1, y, z}\n//│ |{|x|#:| |1|,| |y|,| |z|}|\n//│ Parsed: {'{' {x: 1, y: y, z: z} '}'}\n\n:pe\n{1}\n//│ |{|1|}|\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.40: \t{1}\n//│ ╙──      \t ^\n//│ Parsed: {'{' {<error>: 1} '}'}\n\n:pe\n{1,}\n//│ |{|1|,|}|\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.48: \t{1,}\n//│ ╙──      \t ^\n//│ Parsed: {'{' {<error>: 1} '}'}\n\n:pe\n{1,2}\n//│ |{|1|,|2|}|\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.56: \t{1,2}\n//│ ╙──      \t ^\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.56: \t{1,2}\n//│ ╙──      \t   ^\n//│ Parsed: {'{' {<error>: 1, <error>: 2} '}'}\n\n:pe\n{1,2,}\n//│ |{|1|,|2|,|}|\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.67: \t{1,2,}\n//│ ╙──      \t ^\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.67: \t{1,2,}\n//│ ╙──      \t   ^\n//│ Parsed: {'{' {<error>: 1, <error>: 2} '}'}\n\n:pe\n{\n  1,\n  2,\n  3,\n}\n//│ |{|→|1|,|↵|2|,|↵|3|,|←|↵|}|\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.79: \t  1,\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.80: \t  2,\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.81: \t  3,\n//│ ╙──      \t  ^\n//│ Parsed: {'{' {<error>: 1, <error>: 2, <error>: 3} '}'}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Select.mls",
    "content": "\nx.a\n//│ |x|.a|\n//│ Parsed: {(x).a}\n\nx . a\n//│ |x| |.| |a|\n//│ Parsed: {.(x,)(a,)}\n\nx. a\n//│ |x|.| |a|\n//│ Parsed: {.(x,)(a,)}\n\nx .a\n//│ |x| |.a|\n//│ Parsed: {(x).a}\n\nx\n  .a\n//│ |x|→|.a|←|\n//│ Parsed: {(x).a}\n\n:pe\nx\n.a\n//│ |x|↵|.a|\n//│ ╔══[PARSE ERROR] Unexpected selector in expression position\n//│ ║  l.25: \t.a\n//│ ╙──      \t^^\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.25: \t.a\n//│ ╙──      \t  ^\n//│ Parsed: {x; undefined}\n\nx.a.b\n//│ |x|.a|.b|\n//│ Parsed: {((x).a).b}\n\nx\n  .a\n  .b\n//│ |x|→|.a|↵|.b|←|\n//│ Parsed: {((x).a).b}\n\nx\n  .a.b\n//│ |x|→|.a|.b|←|\n//│ Parsed: {((x).a).b}\n\n// Perhaps surprising:\nx\n  .a\n    .b\n//│ |x|→|.a|→|.b|←|←|\n//│ Parsed: {((x).a).b}\n\nx\n  .a\n    .b\n    .c\n  .d\n//│ |x|→|.a|→|.b|↵|.c|←|↵|.d|←|\n//│ Parsed: {((((x).a).b).c).d}\n\nx\n  .a\n    .b\n      .d\n      .e\n    .c\n  .d\n    .a\n//│ |x|→|.a|→|.b|→|.d|↵|.e|←|↵|.c|←|↵|.d|→|.a|←|←|\n//│ Parsed: {(((((((x).a).b).d).e).c).d).a}\n\n:pe\n.\n//│ |.|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.77: \t.\n//│ ╙──      \t^\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.77: \t.\n//│ ╙──      \t ^\n//│ Parsed: {undefined}\n\n(.)\n//│ |(|.|)|\n//│ Parsed: {.}\n\na, b\n//│ |a|,| |b|\n//│ Parsed: {,(a, b,)}\n\n\na .b .c\n//│ |a| |.b| |.c|\n//│ Parsed: {((a).b).c}\n\na + 1 .c\n//│ |a| |+| |1| |.c|\n//│ Parsed: {+(a,)((1).c,)}\n\na + f(1) .c\n//│ |a| |+| |f|(|1|)| |.c|\n//│ Parsed: {+(a,)((f(1,)).c,)}\n\na + f (1) .c\n//│ |a| |+| |f| |(|1|)| |.c|\n//│ Parsed: {+(a,)((f(1,)).c,)}\n\na + f (1).c\n//│ |a| |+| |f| |(|1|)|.c|\n//│ Parsed: {+(a,)((f(1,)).c,)}\n\nf of x . y\n//│ |f| |#of| |x| |.| |y|\n//│ Parsed: {f(.(x,)(y,),)}\n\nf of x .y\n//│ |f| |#of| |x| |.y|\n//│ Parsed: {f((x).y,)}\n\na + b\n  .c\n//│ |a| |+| |b|→|.c|←|\n//│ Parsed: {(+(a,)(b,)).c}\n\n:pe\na +\n  b\n  .c\n//│ |a| |+|→|b|↵|.c|←|\n//│ ╔══[PARSE ERROR] Unexpected selector in expression position\n//│ ║  l.132: \t  .c\n//│ ╙──       \t  ^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.132: \t  .c\n//│ ╙──       \t    ^\n//│ Parsed: {+(a,)({b; undefined},)}\n\na +\n  b\n    .c\n//│ |a| |+|→|b|→|.c|←|←|\n//│ Parsed: {+(a,)({(b).c},)}\n\na + b\n  .c * 2\n    .d - 1\n//│ |a| |+| |b|→|.c| |*| |2|→|.d| |-| |1|←|←|\n//│ Parsed: {-((*((+(a,)(b,)).c,)(2,)).d,)(1,)}\n\na + b\n  .c * 2\n  .d - 1\n//│ |a| |+| |b|→|.c| |*| |2|↵|.d| |-| |1|←|\n//│ Parsed: {-((*((+(a,)(b,)).c,)(2,)).d,)(1,)}\n\n\na\n  .b\n  of c\n//│ |a|→|.b|↵|#of| |c|←|\n//│ Parsed: {(a).b(c,)}\n\na\n  .b + 1\n  of c\n//│ |a|→|.b| |+| |1|↵|#of| |c|←|\n//│ Parsed: {+((a).b,)(1,)(c,)}\n\na\n  .b + 1\n    of c\n//│ |a|→|.b| |+| |1|→|#of| |c|←|←|\n//│ Parsed: {+((a).b,)(1,)(c,)}\n\n:pe\na\n  .b +\n    1\n    of c\n//│ |a|→|.b| |+|→|1|↵|#of| |c|←|←|\n//│ ╔══[PARSE ERROR] Unexpected 'of' keyword in expression position\n//│ ║  l.183: \t    of c\n//│ ╙──       \t    ^^\n//│ Parsed: {+((a).b,)({1; c},)}\n\na\n  .b +\n    1\n      of c\n//│ |a|→|.b| |+|→|1|→|#of| |c|←|←|←|\n//│ Parsed: {+((a).b,)({1(c,)},)}\n\na\n  .b\n  of c\n  .d\n//│ |a|→|.b|↵|#of| |c|↵|.d|←|\n//│ Parsed: {((a).b(c,)).d}\n\na\n  .b\n    of c\n  .d\n//│ |a|→|.b|→|#of| |c|←|↵|.d|←|\n//│ Parsed: {((a).b(c,)).d}\n\na\n  .b\n  +1\n  *2\n//│ |a|→|.b|↵|+|1|↵|*|2|←|\n//│ Parsed: {*(+((a).b,)(1,),)(2,)}\n\n// TODO we should find a more uniform way of typing indented operator/selector/of blocks\na\n  +1\n  *2\n  .b\n//│ |a|→|+|1|↵|*|2|↵|.b|←|\n//│ ╔══[PARSE ERROR] Unexpected selector in operator block\n//│ ║  l.222: \t  .b\n//│ ╙──       \t  ^^\n//│ Parsed: {*(+(a, 1,), 2,)}\n\n\n1 .+ 2\n//│ |1| |.+| |2|\n//│ Parsed: {.+(1,)(2,)}\n\n1 +. 2\n//│ |1| |+.| |2|\n//│ Parsed: {+.(1,)(2,)}\n\n1 .+! 2\n//│ |1| |.+!| |2|\n//│ Parsed: {.+!(1,)(2,)}\n\n0 * 1 .+. 2 * 3\n//│ |0| |*| |1| |.+.| |2| |*| |3|\n//│ Parsed: {*(*(0,)(.+.(1,)(2,),),)(3,)}\n\n:w\n1 .+a 2\n//│ |1| |.+|a| |2|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.247: \t1 .+a 2\n//│ ╙──       \t    ^^^\n//│ Parsed: {.+(1,)(a(2,),)}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/SpecParams.mls",
    "content": ":ParseOnly\n\n\nfun Foo(#x, y) = x + y\n//│ |#fun| |Foo|(|##|x|,| |y|)| |#=| |x| |+| |y|\n//│ Parsed: {fun Foo = (#x, y,) => +(x,)(y,)}\n\nfun Foo(x, #y) = x + y\n//│ |#fun| |Foo|(|x|,| |##|y|)| |#=| |x| |+| |y|\n//│ Parsed: {fun Foo = (x, #y,) => +(x,)(y,)}\n\nfun Foo(#x, #y, #z) = if z then x + y else z\n//│ |#fun| |Foo|(|##|x|,| |##|y|,| |##|z|)| |#=| |#if| |z| |#then| |x| |+| |y| |#else| |z|\n//│ Parsed: {fun Foo = (#x, #y, #z,) => if (z) then +(x,)(y,) else z}\n\n\nclass Foo(x, #y, z)\n//│ |#class| |Foo|(|x|,| |##|y|,| |z|)|\n//│ Parsed: {class Foo(x, #y, z,) {}}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Subscripts.mls",
    "content": "\na[0]\n//│ |a|[|0|]|\n//│ Parsed: {a‹0›}\n\na[0][1]\n//│ |a|[|0|]|[|1|]|\n//│ Parsed: {a‹0›‹1›}\n\na.x[0].y[1].z\n//│ |a|.x|[|0|]|.y|[|1|]|.z|\n//│ Parsed: {(((a).x‹0›).y‹1›).z}\n\na + b [0] * 2\n//│ |a| |+| |b| |[|0|]| |*| |2|\n//│ Parsed: {+(a,)(*(b‹0›,)(2,),)}\n\nfoo\n  [1]\n//│ |foo|→|[|1|]|←|\n//│ Parsed: {foo‹1›}\n\nFoo(bar) + 1\n  [\"hello\"]\n//│ |Foo|(|bar|)| |+| |1|→|[|\"hello\"|]|←|\n//│ Parsed: {+(Foo(bar,),)(1,)‹\"hello\"›}\n\nFoo(bar) +\n  1[\"hello\"]\n//│ |Foo|(|bar|)| |+|→|1|[|\"hello\"|]|←|\n//│ Parsed: {+(Foo(bar,),)({1‹\"hello\"›},)}\n\nFoo(bar) +\n  1\n    [\"hello\"]\n//│ |Foo|(|bar|)| |+|→|1|→|[|\"hello\"|]|←|←|\n//│ Parsed: {+(Foo(bar,),)({1‹\"hello\"›},)}\n\nFoo(bar) + 1\n  [1]\n  [2]\n//│ |Foo|(|bar|)| |+| |1|→|[|1|]|↵|[|2|]|←|\n//│ Parsed: {+(Foo(bar,),)(1,)‹1›‹2›}\n\nFoo(bar) + 1\n  [1]\n    [2]\n//│ |Foo|(|bar|)| |+| |1|→|[|1|]|→|[|2|]|←|←|\n//│ Parsed: {+(Foo(bar,),)(1,)‹1›‹2›}\n\na +\n  111\n    [22]\n  [333]\n//│ |a| |+|→|111|→|[|22|]|←|↵|[|333|]|←|\n//│ Parsed: {+(a,)({111‹22›; [333,]},)}\n\nFoo(bar) +\n  1\n    [1]\n  [2]\n//│ |Foo|(|bar|)| |+|→|1|→|[|1|]|←|↵|[|2|]|←|\n//│ Parsed: {+(Foo(bar,),)({1‹1›; [2,]},)}\n\na of [333]\n//│ |a| |#of| |[|333|]|\n//│ Parsed: {a([333,],)}\n\na of\n  [333]\n//│ |a| |#of|→|[|333|]|←|\n//│ Parsed: {a([333,],)}\n\na of\n  111\n    [22]\n  [333]\n//│ |a| |#of|→|111|→|[|22|]|←|↵|[|333|]|←|\n//│ Parsed: {a({111‹22›; [333,]},)}\n\na(\n  111\n    [22]\n  [333]\n)\n//│ |a|(|→|111|→|[|22|]|←|↵|[|333|]|←|↵|)|\n//│ Parsed: {a({111‹22›; [333,]},)}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/TypeParams.mls",
    "content": "\n\nclass Foo<A>\n//│ |#class| |Foo|‹|A|›|\n//│ Parsed: {class Foo‹A› {}}\n\n\n\nclass Foo‹A›\n//│ |#class| |Foo|‹|A|›|\n//│ Parsed: {class Foo‹A› {}}\n\n\n(1)\n//│ |(|1|)|\n//│ Parsed: {'(' 1 ')'}\n\n\nfoo<1,2,3>\n//│ |foo|‹|1|,|2|,|3|›|\n//│ Parsed: {foo‹1, 2, 3›}\n\nfoo<1, 2, 3>\n//│ |foo|‹|1|,| |2|,| |3|›|\n//│ Parsed: {foo‹1, 2, 3›}\n\nfoo<1, 2, 3>()\n//│ |foo|‹|1|,| |2|,| |3|›|(||)|\n//│ Parsed: {foo‹1, 2, 3›()}\n\nfoo<1, 2, 3>(1, 2, 3)\n//│ |foo|‹|1|,| |2|,| |3|›|(|1|,| |2|,| |3|)|\n//│ Parsed: {foo‹1, 2, 3›(1, 2, 3,)}\n\n1 < 2 > 4\n//│ |1| |<| |2| |>| |4|\n//│ Parsed: {>(<(1,)(2,),)(4,)}\n\n:w\n1 < 2> 4\n//│ ╔══[WARNING] This looks like an angle bracket, but it does not close any angle bracket section\n//│ ║  l.40: \t1 < 2> 4\n//│ ║        \t     ^\n//│ ╙── Add spaces around it if you intended to use `<` as an operator\n//│ |1| |<| |2|>| |4|\n//│ Parsed: {>(<(1,)(2,),)(4,)}\n\n:pe\n:w\n1< 2 > 4\n//│ ╔══[PARSE ERROR] Unmatched opening angle bracket\n//│ ║  l.50: \t1< 2 > 4\n//│ ║        \t ^\n//│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator\n//│ | |2| |>| |4|1|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.50: \t1< 2 > 4\n//│ ╙──      \t^^^^^^^^\n//│ Parsed: {>(2,)(4(1,),)}\n\n:w\n1< 2> 4\n//│ |1|‹| |2|›| |4|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.62: \t1< 2> 4\n//│ ╙──      \t^^^^^^^\n//│ Parsed: {1‹2›(4,)}\n\n1< 2> (4)\n//│ |1|‹| |2|›| |(|4|)|\n//│ Parsed: {1‹2›(4,)}\n\n1<2>(4)\n//│ |1|‹|2|›|(|4|)|\n//│ Parsed: {1‹2›(4,)}\n\n1<>2\n//│ |1|<>|2|\n//│ Parsed: {<>(1,)(2,)}\n\n:pe\n1< >2\n//│ ╔══[PARSE ERROR] Unmatched opening angle bracket\n//│ ║  l.82: \t1< >2\n//│ ║        \t ^\n//│ ╙── Note that `<` without spaces around it is considered as an angle bracket and not as an operator\n//│ | |>|2|1|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.82: \t1< >2\n//│ ╙──      \t   ^\n//│ Parsed: {2(1,)}\n\n:pe\n1 < >2\n//│ |1| |<| |>|2|\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.94: \t1 < >2\n//│ ╙──      \t    ^\n//│ Parsed: {<(1,)(2,)}\n\n\nfoo<S, T>(1, 2, 3) & Bar<U>(\"ok\")\n//│ |foo|‹|S|,| |T|›|(|1|,| |2|,| |3|)| |&| |Bar|‹|U|›|(|\"ok\"|)|\n//│ Parsed: {&(foo‹S, T›(1, 2, 3,),)(Bar‹U›(\"ok\",),)}\n\nfoo<Str, Int>(2 + 3) & Bar<MyClass>(\"ok\")\n//│ |foo|‹|Str|,| |Int|›|(|2| |+| |3|)| |&| |Bar|‹|MyClass|›|(|\"ok\"|)|\n//│ Parsed: {&(foo‹Str, Int›(+(2,)(3,),),)(Bar‹MyClass›(\"ok\",),)}\n\n// :pe\nfoo[S, T](1, 2, 3) & Bar[U](\"ok\")\n//│ |foo|[|S|,| |T|]|(|1|,| |2|,| |3|)| |&| |Bar|[|U|]|(|\"ok\"|)|\n//│ Parsed: {&(foo‹S, T›(1, 2, 3,),)(Bar‹U›(\"ok\",),)}\n\nclass Foo<T> {}\n//│ |#class| |Foo|‹|T|›| |{||}|\n//│ Parsed: {class Foo‹T› {}}\n\nfun foo<T>(x: T): string = \"rua\"\n//│ |#fun| |foo|‹|T|›|(|x|#:| |T|)|#:| |string| |#=| |\"rua\"|\n//│ Parsed: {fun foo = (x: T,) => \"rua\" : string}\n\nfoo<int>(42)\n//│ |foo|‹|int|›|(|42|)|\n//│ Parsed: {foo‹int›(42,)}\n"
  },
  {
    "path": "shared/src/test/diff/parser/UserDefinedOpsMaybe.mls",
    "content": ":AllowParseErrors\n\n\n1 div 2\n//│ |1| |div| |2|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.4: \t1 div 2\n//│ ╙──     \t  ^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.4: \t1 div 2\n//│ ╙──     \t^^^^^^^\n//│ Parsed: {1(div(2,),)}\n\n1 mod 2\n//│ |1| |mod| |2|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.14: \t1 mod 2\n//│ ╙──      \t  ^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.14: \t1 mod 2\n//│ ╙──      \t^^^^^^^\n//│ Parsed: {1(mod(2,),)}\n\n3 eq 4\n//│ |3| |eq| |4|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.24: \t3 eq 4\n//│ ╙──      \t  ^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.24: \t3 eq 4\n//│ ╙──      \t^^^^^^\n//│ Parsed: {3(eq(4,),)}\n\nxs map f map g map h\n//│ |xs| |map| |f| |map| |g| |map| |h|\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.34: \txs map f map g map h\n//│ ╙──      \t               ^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.34: \txs map f map g map h\n//│ ╙──      \t             ^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.34: \txs map f map g map h\n//│ ╙──      \t         ^^^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.34: \txs map f map g map h\n//│ ╙──      \t       ^^^^^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.34: \txs map f map g map h\n//│ ╙──      \t   ^^^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.34: \txs map f map g map h\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^\n//│ Parsed: {xs(map(f(map(g(map(h,),),),),),)}\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/WeirdIfs.mls",
    "content": "\nif else e\n//│ |#if| |#else| |e|\n//│ Parsed: {if else e}\n\nif x is else e\n//│ |#if| |x| |is| |#else| |e|\n//│ Parsed: {if x is else e}\n\n:pe\nif x is\n  else e\n//│ |#if| |x| |is|→|#else| |e|←|\n//│ ╔══[PARSE ERROR] Unexpected indented block in expression position\n//│ ║  l.12: \t  else e\n//│ ╙──      \t^^\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.12: \t  else e\n//│ ╙──      \t  ^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.11: \tif x is\n//│ ║        \t   ^^^^\n//│ ║  l.12: \t  else e\n//│ ║        \t^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.11: \tif x is\n//│ ╙──      \t^^\n//│ Parsed: {if (is(x,)(undefined,)) then undefined}\n\n:pe\nif x is\n  P else e\n//│ |#if| |x| |is|→|P| |#else| |e|←|\n//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here\n//│ ║  l.32: \t  P else e\n//│ ╙──      \t    ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.31: \tif x is\n//│ ║        \t   ^^^^\n//│ ║  l.32: \t  P else e\n//│ ║        \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.31: \tif x is\n//│ ╙──      \t^^\n//│ Parsed: {if (is(x,)({P},)) then undefined}\n\n\n// TODO(Luyu): move to another test file\nif x is\n  Some(xv) and y is Left(yv) then xv + yv\n  Some(xv) and y is Right(yv2) then xv + yv2\n  else els\n//│ |#if| |x| |is|→|Some|(|xv|)| |and| |y| |is| |Left|(|yv|)| |#then| |xv| |+| |yv|↵|Some|(|xv|)| |and| |y| |is| |Right|(|yv2|)| |#then| |xv| |+| |yv2|↵|#else| |els|←|\n//│ Parsed: {if x is ‹(and(Some(xv,),)(is(y,)(Left(yv,),),)) then +(xv,)(yv,); (and(Some(xv,),)(is(y,)(Right(yv2,),),)) then +(xv,)(yv2,); else els›}\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Where.mls",
    "content": "\n1 + 1 where 1\n//│ |1| |+| |1| |#where| |1|\n//│ Parsed: {+(1,)(1,) where {1}}\n\na => a + 1 where foo\n//│ |a| |#=>| |a| |+| |1| |#where| |foo|\n//│ Parsed: {(a,) => +(a,)(1,) where {foo}}\n\na + 1 where let a = 1\n//│ |a| |+| |1| |#where| |#let| |a| |#=| |1|\n//│ Parsed: {+(a,)(1,) where {let a = 1}}\n\nfun foo: 'a => 'a => 'a where 'a : int\n//│ |#fun| |foo|#:| |'a| |#=>| |'a| |#=>| |'a| |#where| |'a| |#:| |int|\n//│ Parsed: {fun foo: 'a -> 'a -> ('a\n//│   where\n//│     'a <: int)}\n\n:pe\nfun foo: 'a + 'a + 'a where 'a : int\n//│ |#fun| |foo|#:| |'a| |+| |'a| |+| |'a| |#where| |'a| |#:| |int|\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.21: \tfun foo: 'a + 'a + 'a where 'a : int\n//│ ╙──      \t         ^^^^^^^\n//│ Parsed: {fun foo: anything}\n\n:pe\nfun foo: 'a -> 'a -> 'a where 'a : int\n//│ |#fun| |foo|#:| |'a| |->| |'a| |->| |'a| |#where| |'a| |#:| |int|\n//│ ╔══[PARSE ERROR] Not a recognized type\n//│ ║  l.29: \tfun foo: 'a -> 'a -> 'a where 'a : int\n//│ ╙──      \t         ^^^^^^^^^^^^^^\n//│ Parsed: {fun foo: anything}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/Whitespace.mls",
    "content": ":AllowParseErrors\n\n \n//│ | |\n//│ Parsed: {}\n\n  \n//│ | |\n//│ Parsed: {}\n\n  \n \n//│ | |\n//│ Parsed: {}\n\n\nfalse(1 , 2 , 3)\n//│ |false|(|1| |,| |2| |,| |3|)|\n//│ Parsed: {false(1, 2, 3,)}\n\nfalse (1 ,2 ,3)\n//│ |false| |(|1| |,|2| |,|3|)|\n//│ Parsed: {false(1, 2, 3,)}\n\nfalse( 1 , 2 , 3 )\n//│ |false|(| |1| |,| |2| |,| |3| |)|\n//│ Parsed: {false(1, 2, 3,)}\n\n"
  },
  {
    "path": "shared/src/test/diff/parser/boolops.mls",
    "content": "\ntrue and false\n//│ |true| |and| |false|\n//│ Parsed: {and(true,)(false,)}\n\na and b or c\n//│ |a| |and| |b| |or| |c|\n//│ Parsed: {or(and(a,)(b,),)(c,)}\n\na or b and c\n//│ |a| |or| |b| |and| |c|\n//│ Parsed: {or(a,)(and(b,)(c,),)}\n\na + 1 or b + 2 and c + 3\n//│ |a| |+| |1| |or| |b| |+| |2| |and| |c| |+| |3|\n//│ Parsed: {or(+(a,)(1,),)(and(+(b,)(2,),)(+(c,)(3,),),)}\n\n\nany of a, b, c\n//│ |any| |#of| |a|,| |b|,| |c|\n//│ Parsed: {any(a, b, c,)}\n\nany of\n  a\n  b\n  c\n//│ |any| |#of|→|a|↵|b|↵|c|←|\n//│ Parsed: {any({a; b; c},)}\n\nall of\n  x\n  any of\n    a\n    b\n    c\n  y\n//│ |all| |#of|→|x|↵|any| |#of|→|a|↵|b|↵|c|←|↵|y|←|\n//│ Parsed: {all({x; any({a; b; c},); y},)}\n\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/Errors.mls",
    "content": ":NewDefs\n:NoJS\n:ShowPreTyperErrors\n:AllowParseErrors\n:AllowTypeErrors\n\n// This file is used to test the error messages of the _unfinished_ `PreTyper`.\n// The goal is to document `PreTyper` behavior and to make sure that the error\n// messages are clear and helpful. We can delete this file after it is done.\n\n// codegen\n// -------\n\n// Nested\nfun main =\n  let f(x: Int): Int = if x is\n    0 then 1\n    else g(x - 1)\n  let g(x: Int): Int = f(x)\n  f\n//│ ╔══[ERROR] identifier `g` not found\n//│ ║  l.18: \t    else g(x - 1)\n//│ ╙──      \t         ^\n//│ fun main: (x: Int) -> Int\n\n// SymbolicOps\nfun (>>)(f, g) = x => g(f(x))\n//│ ╔══[PARSE ERROR] Expected a function name; found parenthesis section instead\n//│ ║  l.27: \tfun (>>)(f, g) = x => g(f(x))\n//│ ╙──      \t        ^^^^^^\n//│ ╔══[ERROR] identifier `g` not found\n//│ ║  l.27: \tfun (>>)(f, g) = x => g(f(x))\n//│ ╙──      \t                      ^\n//│ ╔══[ERROR] identifier `f` not found\n//│ ║  l.27: \tfun (>>)(f, g) = x => g(f(x))\n//│ ╙──      \t                        ^\n//│ fun (>>) <error>: Int -> Int\n\n// mlscript\n// --------\n\n// Sequence\nlet test(x) = log(x); x + 1\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.43: \tlet test(x) = log(x); x + 1\n//│ ╙──      \t                      ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.43: \tlet test(x) = log(x); x + 1\n//│ ╙──      \t                      ^\n//│ let test: anything -> ()\n//│ Int\n\n// nu\n// --\n\n// Ascription\nfoo(123: Int): Int\n//│ ╔══[ERROR] identifier `foo` not found\n//│ ║  l.57: \tfoo(123: Int): Int\n//│ ╙──      \t^^^\n//│ ╔══[ERROR] identifier `Int` is resolved to a type\n//│ ║  l.57: \tfoo(123: Int): Int\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] identifier not found: foo\n//│ ║  l.57: \tfoo(123: Int): Int\n//│ ╙──      \t^^^\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `error` for applying named arguments\n//│ ║  l.57: \tfoo(123: Int): Int\n//│ ╙──      \t^^^\n//│ Int\n\n// Ascription\nfoo(123:Int):Int\n//│ ╔══[ERROR] identifier `foo` not found\n//│ ║  l.73: \tfoo(123:Int):Int\n//│ ╙──      \t^^^\n//│ ╔══[ERROR] identifier `Int` is resolved to a type\n//│ ║  l.73: \tfoo(123:Int):Int\n//│ ╙──      \t        ^^^\n//│ ╔══[ERROR] identifier not found: foo\n//│ ║  l.73: \tfoo(123:Int):Int\n//│ ╙──      \t^^^\n//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `error` for applying named arguments\n//│ ║  l.73: \tfoo(123:Int):Int\n//│ ╙──      \t^^^\n//│ Int\n\n// BadBlocks\nfun test =\n  let a = b\n  let b = 1\n  a\n//│ ╔══[ERROR] identifier `b` not found\n//│ ║  l.90: \t  let a = b\n//│ ╙──      \t          ^\n//│ fun test: 1\n\n// BadBlocks\nfun test =\n  let a() = b\n  let b = 1\n  a()\n//│ ╔══[ERROR] identifier `b` not found\n//│ ║  l.100: \t  let a() = b\n//│ ╙──       \t            ^\n//│ fun test: 1\n\n// BadClasses\nhello\n//│ ╔══[ERROR] identifier `hello` not found\n//│ ║  l.109: \thello\n//│ ╙──       \t^^^^^\n//│ ╔══[ERROR] identifier not found: hello\n//│ ║  l.109: \thello\n//│ ╙──       \t^^^^^\n//│ error\n\n// BadFieldInit\nmodule A {\n  val x = y\n  val y = x\n}\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.120: \t  val x = y\n//│ ╙──       \t          ^\n//│ module A {\n//│   val x: nothing\n//│   val y: nothing\n//│ }\n\n// BadFieldInit\nmodule A {\n  val x = y\n  val y = 1\n}\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.133: \t  val x = y\n//│ ╙──       \t          ^\n//│ module A {\n//│   val x: 1\n//│   val y: 1\n//│ }\n\n// BadMixin\nmixin M0\nM0\n//│ ╔══[ERROR] identifier `M0` is resolved to a type\n//│ ║  l.146: \tM0\n//│ ╙──       \t^^\n//│ ╔══[ERROR] mixin M0 cannot be used in term position\n//│ ║  l.146: \tM0\n//│ ╙──       \t^^\n//│ mixin M0()\n//│ error\n\n// BadScopes\nmixin Foo(x: Int)\nx\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.158: \tx\n//│ ╙──       \t^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.158: \tx\n//│ ╙──       \t^\n//│ mixin Foo(x: Int)\n//│ error\n\n// BadScopes\nclass Foo(x: Int)\nx\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.170: \tx\n//│ ╙──       \t^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.170: \tx\n//│ ╙──       \t^\n//│ class Foo(x: Int)\n//│ error\n\n// BadScopes\nclass Bar { x }\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.181: \tclass Bar { x }\n//│ ╙──       \t            ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.181: \tclass Bar { x }\n//│ ╙──       \t            ^\n//│ class Bar {\n//│   constructor()\n//│ }\n\n// BadTraits\ntrait Foo\nFoo\n//│ ╔══[ERROR] identifier `Foo` is resolved to a type\n//│ ║  l.194: \tFoo\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] trait Foo cannot be used in term position\n//│ ║  l.194: \tFoo\n//│ ╙──       \t^^^\n//│ trait Foo\n//│ error\n\n// FunPatterns\nfun f3([(x, y,),],) = x + y\n//│ ╔══[ERROR] unsupported pattern shape\n//│ ║  l.205: \tfun f3([(x, y,),],) = x + y\n//│ ╙──       \t        ^^^^^^^\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.205: \tfun f3([(x, y,),],) = x + y\n//│ ╙──       \t                      ^\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.205: \tfun f3([(x, y,),],) = x + y\n//│ ╙──       \t                          ^\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.205: \tfun f3([(x, y,),],) = x + y\n//│ ╙──       \t        ^^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.205: \tfun f3([(x, y,),],) = x + y\n//│ ╙──       \t                      ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.205: \tfun f3([(x, y,),],) = x + y\n//│ ╙──       \t                          ^\n//│ fun f3: ([error]) -> Int\n\n// GenericClassInheritance\nclass C1[A] extends C0[A] { val a = a }\n//│ ╔══[ERROR] could not find definition `C0`\n//│ ║  l.227: \tclass C1[A] extends C0[A] { val a = a }\n//│ ╙──       \t                    ^^\n//│ ╔══[ERROR] identifier `a` not found\n//│ ║  l.227: \tclass C1[A] extends C0[A] { val a = a }\n//│ ╙──       \t                                    ^\n//│ ╔══[ERROR] Could not find definition `C0`\n//│ ║  l.227: \tclass C1[A] extends C0[A] { val a = a }\n//│ ╙──       \t                    ^^\n//│ class C1[A] {\n//│   constructor()\n//│   val a: nothing\n//│ }\n\n// GenericMethods\nfun foo1 = forall 'A: (x: 'A) => x\n//│ fun foo1: forall 'A. (x: 'A) -> 'A\n\n// GenericMethods\nfoo1[Int](42)\n//│ ╔══[ERROR] type application syntax is not yet supported\n//│ ║  l.247: \tfoo1[Int](42)\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.247: \tfoo1[Int](42)\n//│ ╙──       \t^^^^^^^^^\n//│ 42\n\n// GenericMethods\nfun foo2<A>(x: A) = x\n//│ fun foo2: forall 'A. (x: 'A) -> 'A\n\n// GenericMethods\nfoo2<Int>(42)\n//│ ╔══[ERROR] type application syntax is not yet supported\n//│ ║  l.261: \tfoo2<Int>(42)\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.261: \tfoo2<Int>(42)\n//│ ╙──       \t^^^^^^^^^\n//│ 42\n\n// GenericMethods\nfun foo3[A](x: A) = x\n//│ fun foo3: forall 'A. (x: 'A) -> 'A\n\n// GenericMethods\nfoo3[Int](42)\n//│ ╔══[ERROR] type application syntax is not yet supported\n//│ ║  l.275: \tfoo3[Int](42)\n//│ ╙──       \t^^^^^^^^^\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.275: \tfoo3[Int](42)\n//│ ╙──       \t^^^^^^^^^\n//│ 42\n\n// ImplicitMethodPolym\nmodule None\nmodule M {\n  mut val m = None\n  fun oops(x) = m := x\n}\n//│ ╔══[ERROR] identifier `:=` not found\n//│ ║  l.288: \t  fun oops(x) = m := x\n//│ ╙──       \t                  ^^\n//│ ╔══[ERROR] identifier not found: :=\n//│ ║  l.288: \t  fun oops(x) = m := x\n//│ ╙──       \t                  ^^\n//│ module None\n//│ module M {\n//│   mut val m: None\n//│   fun oops: anything -> error\n//│ }\n\n// InterfaceMono\ntrait What0 extends woooo\n//│ ╔══[ERROR] could not find definition `woooo`\n//│ ║  l.303: \ttrait What0 extends woooo\n//│ ╙──       \t                    ^^^^^\n//│ ╔══[ERROR] Could not find definition `woooo`\n//│ ║  l.303: \ttrait What0 extends woooo\n//│ ╙──       \t                    ^^^^^\n//│ trait What0\n\n// Misc\nlet f = ((x, y)) => x + y\n//│ ╔══[ERROR] unsupported pattern shape\n//│ ║  l.313: \tlet f = ((x, y)) => x + y\n//│ ╙──       \t         ^^^^^^\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.313: \tlet f = ((x, y)) => x + y\n//│ ╙──       \t                    ^\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.313: \tlet f = ((x, y)) => x + y\n//│ ╙──       \t                        ^\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.313: \tlet f = ((x, y)) => x + y\n//│ ╙──       \t         ^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.313: \tlet f = ((x, y)) => x + y\n//│ ╙──       \t                    ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.313: \tlet f = ((x, y)) => x + y\n//│ ╙──       \t                        ^\n//│ let f: error -> Int\n\n// Misc\nf[1, 2]\n//│ ╔══[ERROR] type application syntax is not yet supported\n//│ ║  l.335: \tf[1, 2]\n//│ ╙──       \t^^^^^^^\n//│ ╔══[ERROR] Type application syntax is not yet supported\n//│ ║  l.335: \tf[1, 2]\n//│ ╙──       \t^^^^^^^\n//│ error -> Int\n\n// Misc\nlet f = (((x, y))) => x + y\n//│ ╔══[ERROR] unsupported pattern shape\n//│ ║  l.345: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t          ^^^^^^\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.345: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t                      ^\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.345: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t                          ^\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.345: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t          ^^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.345: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t                      ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.345: \tlet f = (((x, y))) => x + y\n//│ ╙──       \t                          ^\n//│ let f: error -> Int\n\n// Mut\nlet v1 = {mut 1}\nv1.x <- 1\n//│ ╔══[PARSE ERROR] Record field should have a name\n//│ ║  l.367: \tlet v1 = {mut 1}\n//│ ╙──       \t              ^\n//│ ╔══[ERROR] identifier `<-` not found\n//│ ║  l.368: \tv1.x <- 1\n//│ ╙──       \t     ^^\n//│ ╔══[ERROR] identifier not found: <-\n//│ ║  l.368: \tv1.x <- 1\n//│ ╙──       \t     ^^\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ║  l.368: \tv1.x <- 1\n//│ ║         \t^^^^\n//│ ╟── record literal of type `{mut <error>: ?<error>}` does not have field 'x'\n//│ ║  l.367: \tlet v1 = {mut 1}\n//│ ║         \t              ^\n//│ ╟── but it flows into reference with expected type `{x: ?x}`\n//│ ║  l.368: \tv1.x <- 1\n//│ ╙──       \t^^\n//│ let v1: {mut <error>: '<error>}\n//│ error\n//│ where\n//│   '<error> :> 1\n\n// Mut\nlet v2 = [mut x: 1]\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.393: \tlet v2 = [mut x: 1]\n//│ ╙──       \t              ^\n//│ let v2: [mut x: 'x]\n//│   where\n//│     'x :> 1\n\n// Mut\nlet v2 = [mut y: 1]\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.402: \tlet v2 = [mut y: 1]\n//│ ╙──       \t              ^\n//│ let v2: [mut y: 'y]\n//│   where\n//│     'y :> 1\n\n// NoThisCtor\nclass Foo() {\n  virtual val foo: Int = 42\n}\n//│ class Foo() {\n//│   val foo: Int\n//│ }\n\n// NoThisCtor\nclass Foo5() extends Foo() {\n  val foo: Int\n  val x = bar(0)\n  fun bar(y: Int) = this.foo + y\n}\n//│ ╔══[ERROR] identifier `bar` not found\n//│ ║  l.421: \t  val x = bar(0)\n//│ ╙──       \t          ^^^\n//│ ╔══[ERROR] Cannot access `this` while initializing field x\n//│ ║  l.421: \t  val x = bar(0)\n//│ ║         \t      ^^^^^^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.422: \t  fun bar(y: Int) = this.foo + y\n//│ ╙──       \t                    ^^^^\n//│ class Foo5() extends Foo {\n//│   fun bar: (y: Int) -> Int\n//│   val foo: Int\n//│   val x: Int\n//│ }\n\n// NoThisCtor\nabstract class Foo: (Int -> Int) {\n  val x = f\n  fun f = this(0)\n}\n//│ ╔══[ERROR] Cannot access `this` while initializing field x\n//│ ║  l.441: \t  val x = f\n//│ ║         \t      ^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.442: \t  fun f = this(0)\n//│ ╙──       \t          ^^^^\n//│ abstract class Foo: Int -> Int {\n//│   fun f: nothing\n//│   val x: nothing\n//│ }\n\n// Object\nObject\n//│ ╔══[ERROR] identifier `Object` is resolved to a type\n//│ ║  l.456: \tObject\n//│ ╙──       \t^^^^^^\n//│ ╔══[ERROR] Class Object is abstract and cannot be instantiated\n//│ ║  l.456: \tObject\n//│ ╙──       \t^^^^^^\n//│ ╔══[ERROR] Class Object cannot be instantiated as it exposes no constructor\n//│ ║  l.456: \tObject\n//│ ╙──       \t^^^^^^\n//│ error\n\n// OpLam\nx => x.y => y\n//│ ╔══[ERROR] unsupported pattern shape\n//│ ║  l.469: \tx => x.y => y\n//│ ╙──       \t     ^^^\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.469: \tx => x.y => y\n//│ ╙──       \t            ^\n//│ ╔══[ERROR] Unsupported pattern shape:\n//│ ║  l.469: \tx => x.y => y\n//│ ╙──       \t     ^^^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.469: \tx => x.y => y\n//│ ╙──       \t            ^\n//│ anything -> error -> error\n\n// ParamOverride\nclass Base0(n: Num)\n//│ class Base0(n: Num)\n\n// ParamOverride\nclass Derived0(n: Int) extends Base\n//│ ╔══[ERROR] could not find definition `Base`\n//│ ║  l.489: \tclass Derived0(n: Int) extends Base\n//│ ╙──       \t                               ^^^^\n//│ ╔══[ERROR] Could not find definition `Base`\n//│ ║  l.489: \tclass Derived0(n: Int) extends Base\n//│ ╙──       \t                               ^^^^\n//│ class Derived0(n: Int)\n\n// ParamOverride\nmixin DerivedBad(n: Int) extends Base\n//│ ╔══[ERROR] mixin definitions cannot yet extend parents\n//│ ║  l.499: \tmixin DerivedBad(n: Int) extends Base\n//│ ╙──       \t                                 ^^^^\n//│ mixin DerivedBad(n: Int)\n\n// PartialApp\nfun foo(x, y) = x + y\n//│ fun foo: (Int, Int) -> Int\n\n// PartialApp\nfoo(2, _)\n//│ ╔══[ERROR] identifier `_` not found\n//│ ║  l.510: \tfoo(2, _)\n//│ ╙──       \t       ^\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.510: \tfoo(2, _)\n//│ ╙──       \t       ^\n//│ Int\n\n// PartialApp\n_.foo(1)\n//│ ╔══[ERROR] identifier `_` not found\n//│ ║  l.520: \t_.foo(1)\n//│ ╙──       \t^\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.520: \t_.foo(1)\n//│ ╙──       \t^\n//│ error\n\n// PartialApp\n_ + _\n//│ ╔══[ERROR] identifier `_` not found\n//│ ║  l.530: \t_ + _\n//│ ╙──       \t^\n//│ ╔══[ERROR] identifier `_` not found\n//│ ║  l.530: \t_ + _\n//│ ╙──       \t    ^\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.530: \t_ + _\n//│ ╙──       \t^\n//│ ╔══[ERROR] Widlcard in expression position.\n//│ ║  l.530: \t_ + _\n//│ ╙──       \t    ^\n//│ Int\n\n// PartialApp\n_2 + _1\n//│ ╔══[ERROR] identifier `_2` not found\n//│ ║  l.546: \t_2 + _1\n//│ ╙──       \t^^\n//│ ╔══[ERROR] identifier `_1` not found\n//│ ║  l.546: \t_2 + _1\n//│ ╙──       \t     ^^\n//│ ╔══[ERROR] identifier not found: _2\n//│ ║  l.546: \t_2 + _1\n//│ ╙──       \t^^\n//│ ╔══[ERROR] identifier not found: _1\n//│ ║  l.546: \t_2 + _1\n//│ ╙──       \t     ^^\n//│ Int\n\n// RefinedPatterns\nrefined\n//│ ╔══[ERROR] identifier `refined` not found\n//│ ║  l.562: \trefined\n//│ ╙──       \t^^^^^^^\n//│ ╔══[ERROR] Illegal use of reserved operator: refined\n//│ ║  l.562: \trefined\n//│ ╙──       \t^^^^^^^\n//│ ╔══[ERROR] identifier not found: refined\n//│ ║  l.562: \trefined\n//│ ╙──       \t^^^^^^^\n//│ error\n\n// Refinements\nclass D() { fun f = 0 }\n//│ class D() {\n//│   fun f: 0\n//│ }\n\n// Refinements\nlet d = D & { f: 0 }\n//│ ╔══[ERROR] identifier `&` not found\n//│ ║  l.581: \tlet d = D & { f: 0 }\n//│ ╙──       \t          ^\n//│ ╔══[ERROR] Illegal use of reserved operator: &\n//│ ║  l.581: \tlet d = D & { f: 0 }\n//│ ╙──       \t          ^\n//│ ╔══[ERROR] identifier not found: &\n//│ ║  l.581: \tlet d = D & { f: 0 }\n//│ ╙──       \t          ^\n//│ let d: error\n\n// Res\nx => x + 2\n//│ Int -> Int\n\n// Res\nres(1)\n//│ ╔══[ERROR] identifier `res` not found\n//│ ║  l.598: \tres(1)\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] identifier not found: res\n//│ ║  l.598: \tres(1)\n//│ ╙──       \t^^^\n//│ error\n\n// Uninstantiable\nInt\n//│ ╔══[ERROR] identifier `Int` is resolved to a type\n//│ ║  l.608: \tInt\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Class Int is abstract and cannot be instantiated\n//│ ║  l.608: \tInt\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Class Int cannot be instantiated as it exposes no constructor\n//│ ║  l.608: \tInt\n//│ ╙──       \t^^^\n//│ error\n\n// Uninstantiable\nInt()\n//│ ╔══[ERROR] identifier `Int` is resolved to a type\n//│ ║  l.621: \tInt()\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Class Int is abstract and cannot be instantiated\n//│ ║  l.621: \tInt()\n//│ ╙──       \t^^^\n//│ ╔══[ERROR] Class Int cannot be instantiated as it exposes no constructor\n//│ ║  l.621: \tInt()\n//│ ╙──       \t^^^\n//│ error\n\n// Uninstantiable\nnew Int\n//│ ╔══[ERROR] identifier `Int` is resolved to a type\n//│ ║  l.634: \tnew Int\n//│ ╙──       \t    ^^^\n//│ ╔══[ERROR] Class Int is abstract and cannot be instantiated\n//│ ║  l.634: \tnew Int\n//│ ╙──       \t    ^^^\n//│ Int\n\n// Unit\n(1, 2) => 3\n//│ ╔══[WARNING] literal patterns are ignored\n//│ ║  l.644: \t(1, 2) => 3\n//│ ╙──       \t ^\n//│ ╔══[WARNING] literal patterns are ignored\n//│ ║  l.644: \t(1, 2) => 3\n//│ ╙──       \t    ^\n//│ (1, 2) -> 3\n\n// Unit\n1 => (2, 3)\n//│ ╔══[WARNING] literal patterns are ignored\n//│ ║  l.654: \t1 => (2, 3)\n//│ ╙──       \t^\n//│ 1 -> 3\n\n// Vals\nval c = d + 1\nval d = 1\n//│ val c: Int\n//│ val d: 1\n\n// Varargs\nfun test(...xs) = xs.length\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.667: \tfun test(...xs) = xs.length\n//│ ╙──       \t         ^^^\n//│ ╔══[ERROR] identifier `xs` not found\n//│ ║  l.667: \tfun test(...xs) = xs.length\n//│ ╙──       \t                  ^^\n//│ ╔══[ERROR] identifier not found: xs\n//│ ║  l.667: \tfun test(...xs) = xs.length\n//│ ╙──       \t                  ^^\n//│ fun test: () -> error\n\n// WeirdDefs\nfun fst[x, _] = x\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.680: \tfun fst[x, _] = x\n//│ ╙──       \t                ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.680: \tfun fst[x, _] = x\n//│ ╙──       \t                ^\n//│ fun fst: error\n\n// repro0\nclass Add[out E](val lhs: E)\nval add11 = Add(add11)\nmodule EvalAddLit {\n  fun eval(e: Add['A]) =\n    if e is Add then eval(e.lhs)\n}\nlet res = EvalAddLit.eval(add11)\n//│ ╔══[ERROR] identifier `add11` not found\n//│ ║  l.691: \tval add11 = Add(add11)\n//│ ╙──       \t                ^^^^^\n//│ class Add[E](lhs: E)\n//│ val add11: 'E\n//│ module EvalAddLit {\n//│   fun eval: forall 'A. (e: 'A) -> nothing\n//│ }\n//│ let res: nothing\n//│ where\n//│   'A <: Add['A]\n//│   'E :> Add['E]\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/Repro.mls",
    "content": ":NewDefs\n:ShowPreTyperErrors\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/SymbolKind.mls",
    "content": ":NewDefs\n:ShowPreTyperErrors\n\ntype Type = Int\nmixin Mixin1\nmixin Mixin2()\ntrait Trait // Trait doesn't have parameters.\nclass Class1\nclass Class2()\nmodule Module\n//│ type Type = Int\n//│ mixin Mixin1()\n//│ mixin Mixin2()\n//│ trait Trait\n//│ class Class1 {\n//│   constructor()\n//│ }\n//│ class Class2()\n//│ module Module\n\nfun f(g) = g()\n//│ fun f: forall 'a. (() -> 'a) -> 'a\n\n:e\nf(Type)\n//│ ╔══[ERROR] identifier `Type` is resolved to a type\n//│ ║  l.25: \tf(Type)\n//│ ╙──      \t  ^^^^\n//│ ╔══[ERROR] type alias Type cannot be used in term position\n//│ ║  l.25: \tf(Type)\n//│ ╙──      \t  ^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   type alias Type is not a valid expression\n\n:e\nid(Mixin1)\n//│ ╔══[ERROR] identifier `Mixin1` is resolved to a type\n//│ ║  l.37: \tid(Mixin1)\n//│ ╙──      \t   ^^^^^^\n//│ ╔══[ERROR] mixin Mixin1 cannot be used in term position\n//│ ║  l.37: \tid(Mixin1)\n//│ ╙──      \t   ^^^^^^\n//│ error\n//│ res\n//│     = [Function (anonymous)]\n\n:e\nf(Mixin2)\n//│ ╔══[ERROR] identifier `Mixin2` is resolved to a type\n//│ ║  l.49: \tf(Mixin2)\n//│ ╙──      \t  ^^^^^^\n//│ ╔══[ERROR] mixin Mixin2 cannot be used in term position\n//│ ║  l.49: \tf(Mixin2)\n//│ ╙──      \t  ^^^^^^\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: Class extends value undefined is not a constructor or null\n\n:e\nf(Trait)\n//│ ╔══[ERROR] identifier `Trait` is resolved to a type\n//│ ║  l.62: \tf(Trait)\n//│ ╙──      \t  ^^^^^\n//│ ╔══[ERROR] trait Trait cannot be used in term position\n//│ ║  l.62: \tf(Trait)\n//│ ╙──      \t  ^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   trait used in term position\n\n:e\nf(Class1)\n//│ ╔══[ERROR] Construction of unparameterized class Class1 should use the `new` keyword\n//│ ║  l.74: \tf(Class1)\n//│ ╙──      \t  ^^^^^^\n//│ Class1\n//│ res\n//│ Runtime error:\n//│   TypeError: Class constructor Class1 cannot be invoked without 'new'\n\nf(Class2)\n//│ Class2\n//│ res\n//│     = Class2 {}\n\nid(Class2)\n//│ () -> Class2\n//│ res\n//│     = [Function (anonymous)] {\n//│         class: [class Class2],\n//│         unapply: [Function: unapply]\n//│       }\n\n:e\nf(Module)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.97: \tf(Module)\n//│ ║        \t^^^^^^^^^\n//│ ╟── reference of type `Module` is not a function\n//│ ║  l.97: \tf(Module)\n//│ ║        \t  ^^^^^^\n//│ ╟── Note: constraint arises from application:\n//│ ║  l.21: \tfun f(g) = g()\n//│ ║        \t           ^^^\n//│ ╟── from reference:\n//│ ║  l.21: \tfun f(g) = g()\n//│ ╙──      \t           ^\n//│ error\n//│ res\n//│ Runtime error:\n//│   TypeError: g is not a function\n\nid(Module)\n//│ Module\n//│ res\n//│     = Module { class: [class Module] }\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/DualOption.mls",
    "content": ":NewDefs\n\n\nabstract class Option[T]\nclass Some[T](value: T) extends Option[T]\nmodule None extends Option[nothing]\nclass Pair[A, B](x: A, y: B)\n//│ abstract class Option[T]\n//│ class Some[T](value: T) extends Option\n//│ module None extends Option\n//│ class Pair[A, B](x: A, y: B)\n\n// All `add_n` functions should be inferred to have the same type.\n\nfun add_1(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n//│ fun add_1: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\nadd_1(None, None)\nadd_1(Some(5), None)\nadd_1(None, Some(9))\nadd_1(Some(5), Some(9))\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 5\n//│ res\n//│     = 9\n//│ res\n//│     = 14\n\nfun add_2(x, y) =\n  if x is\n    Some(xv) and y is\n      Some(yv) then xv + yv\n      None     then xv\n    None and y is\n      Some(yv) then yv\n      None     then 0\n//│ fun add_2: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\nadd_2(None, None)\nadd_2(Some(5), None)\nadd_2(None, Some(9))\nadd_2(Some(5), Some(9))\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 5\n//│ res\n//│     = 9\n//│ res\n//│     = 14\n\n\nfun add_3(x, y) =\n  if Pair(x, y) is\n    Pair(Some(xv), Some(yv)) then xv + yv\n    Pair(Some(xv), None)     then xv\n    Pair(None,     Some(yv)) then yv\n    Pair(None,     None)     then 0\n//│ fun add_3: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\nadd_3(None, None)\nadd_3(Some(5), None)\nadd_3(None, Some(9))\nadd_3(Some(5), Some(9))\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 5\n//│ res\n//│     = 9\n//│ res\n//│     = 14\n\n\nfun add_4(x, y) =\n  if\n    x\n      is\n        Some(xv) and\n          y\n            is\n              Some(yv) then xv + yv\n            is\n              None     then xv\n        None and\n          y\n            is\n              Some(yv) then yv\n            is\n              None     then 0\n//│ fun add_4: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\n\nadd_4(None, None)\nadd_4(Some(5), None)\nadd_4(None, Some(9))\nadd_4(Some(5), Some(9))\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 5\n//│ res\n//│     = 9\n//│ res\n//│     = 14\n\n\nfun add_5(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    y is None     and x is Some(xv) then xv\n    x is None     and y is Some(yv) then yv\n    y is None     and x is None     then 0\n//│ fun add_5: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\n\nadd_5(None, None)\nadd_5(Some(5), None)\nadd_5(None, Some(9))\nadd_5(Some(5), Some(9))\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 5\n//│ res\n//│     = 9\n//│ res\n//│     = 14\n\n\nfun add_6(x, y) =\n  if [x, y] is\n    [Some(xv), Some(yv)] then xv + yv\n    [Some(xv), None]     then xv\n    [None,     Some(yv)] then yv\n    [None,     None]     then 0\n//│ fun add_6: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\n\nadd_6(None, None)\nadd_6(Some(5), None)\nadd_6(None, Some(9))\nadd_6(Some(5), Some(9))\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 5\n//│ res\n//│     = 9\n//│ res\n//│     = 14\n\n\nfun p(x) = true\n//│ fun p: anything -> true\n\n\n// FIXME Remove `case p(x) of true -> 0; _ -> 0`\n:ducs:postprocess.result\nfun add_6(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    y is None     and p(x) and x is Some(xv) then 42\n    y is None     and x is Some(xv) then xv\n    x is None     and y is Some(yv) then yv\n    y is None     and x is None     then 0\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_x$Some*† = (Some).unapply(x,)\n//│     let xv*‡ = (ucs$args_x$Some).0\n//│     case y*‡ of\n//│       Some*◊ ->\n//│         let ucs$args_y$Some*† = (Some).unapply(y,)\n//│         let yv*‡ = (ucs$args_y$Some).0\n//│         +(xv, yv,)\n//│       None*† ->\n//│         let ucs$test$0*† = p(x,) : Bool\n//│         case ucs$test$0*† of\n//│           true*† -> 42\n//│           _ -> xv\n//│   None*† ->\n//│     case y*‡ of\n//│       None*† ->\n//│         let ucs$test$0*† = p(x,) : Bool\n//│         case ucs$test$0*† of\n//│           true -> 0\n//│           _ -> 0\n//│       Some*◊ ->\n//│         let ucs$args_y$Some*† = (Some).unapply(y,)\n//│         let yv*‡ = (ucs$args_y$Some).0\n//│         yv\n//│ fun add_6: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\n\n:ducs:postprocess.result\nfun add_7(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    // y is None    and p(x) and x is Some(xv) then 42\n    y is None     and x is Some(xv) then xv\n    y is Some(yv) and p(yv) and x is None then 36\n    y is Some(yv) and x is None then yv\n    y is None     and x is None     then 0\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_x$Some*† = (Some).unapply(x,)\n//│     let xv*‡ = (ucs$args_x$Some).0\n//│     case y*‡ of\n//│       Some*◊ ->\n//│         let ucs$args_y$Some*† = (Some).unapply(y,)\n//│         let yv*‡ = (ucs$args_y$Some).0\n//│         +(xv, yv,)\n//│       None*† -> xv\n//│   None*† ->\n//│     case y*‡ of\n//│       None*† -> 0\n//│       Some*◊ ->\n//│         let ucs$args_y$Some*† = (Some).unapply(y,)\n//│         let yv*‡ = (ucs$args_y$Some).0\n//│         let ucs$test$0*† = p(yv,) : Bool\n//│         case ucs$test$0*† of\n//│           true -> 36\n//│           _ -> yv\n//│ fun add_7: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\n\n// FIXME Remove `case p(x) of true -> 0; _ -> 0`\n:ducs:postprocess.result\nfun add_8(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    y is None    and p(x) and x is Some(xv) then 42\n    y is None     and x is Some(xv) then xv\n    y is Some(yv) and p(yv) and x is None then 36\n    y is Some(yv) and x is None then yv\n    y is None     and x is None     then 0\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_x$Some*† = (Some).unapply(x,)\n//│     let xv*‡ = (ucs$args_x$Some).0\n//│     case y*‡ of\n//│       Some*◊ ->\n//│         let ucs$args_y$Some*† = (Some).unapply(y,)\n//│         let yv*‡ = (ucs$args_y$Some).0\n//│         +(xv, yv,)\n//│       None*† ->\n//│         let ucs$test$0*† = p(x,) : Bool\n//│         case ucs$test$0*† of\n//│           true*† -> 42\n//│           _ -> xv\n//│   None*† ->\n//│     case y*‡ of\n//│       None*† ->\n//│         let ucs$test$0*† = p(x,) : Bool\n//│         case ucs$test$0*† of\n//│           true -> 0\n//│           _ -> 0\n//│       Some*◊ ->\n//│         let ucs$args_y$Some*† = (Some).unapply(y,)\n//│         let yv*‡ = (ucs$args_y$Some).0\n//│         let ucs$test$1*† = p(yv,) : Bool\n//│         case ucs$test$1*† of\n//│           true -> 36\n//│           _ -> yv\n//│ fun add_8: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/NamePattern.mls",
    "content": ":NewDefs\n\nfun id(x) = x\n//│ fun id: forall 'a. 'a -> 'a\n\nif id(0) is t then t\n//│ 0\n//│ res\n//│     = 0\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/RecordPattern.mls",
    "content": ":NewDefs\n\n:e\n:w\nfun take_1(p) =\n  if p is\n    { x, y } then x + y\n    else 0\n//│ ╔══[ERROR] unknown pattern '{' {x: x, y: y} '}'\n//│ ║  l.7: \t    { x, y } then x + y\n//│ ╙──     \t    ^^^^^^^^\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.8: \t    else 0\n//│ ║       \t         ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.7: \t    { x, y } then x + y\n//│ ╙──     \t                  ^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.7: \t    { x, y } then x + y\n//│ ╙──     \t                  ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.7: \t    { x, y } then x + y\n//│ ╙──     \t                      ^\n//│ fun take_1: anything -> Int\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/Refinement.mls",
    "content": ":NewDefs\n\nmodule None\nclass Some[out A](val value: A)\n//│ module None\n//│ class Some[A](value: A)\n\n// OK\n:ducs:desugar.result,postprocess.result\nx => if x is\n  refined(None) then x\n//│ Desugared UCS term:\n//│ if x*‡ is refined None then x\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined None*† -> x\n//│ forall 'a. (None & 'a) -> (None & 'a)\n//│ res\n//│     = [Function: res]\n\n// OK\n:ducs:desugar.result,postprocess.result\nx => if x is\n  refined(Some) then x\n//│ Desugared UCS term:\n//│ if x*‡ is refined Some then x\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined Some*◊ -> x\n//│ forall 'a. (Some[anything] & 'a) -> (Some[anything] & 'a)\n//│ res\n//│     = [Function: res]\n\n:w\n:ducs:desugar.result,postprocess.result\nx => if x is\n  refined(None) then x\n  Some then x\n//│ Desugared UCS term:\n//│ if\n//│   x*‡ is refined None then x\n//│   x*‡ is Some then x\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined None*† -> x\n//│   Some*◊ -> x\n//│ ╔══[WARNING] inconsistent refined pattern\n//│ ║  l.37: \t  refined(None) then x\n//│ ║        \t          ^^^^\n//│ ╟── pattern `Some` is not refined\n//│ ║  l.38: \t  Some then x\n//│ ║        \t  ^^^^\n//│ ╟── but pattern `None` is refined\n//│ ║  l.37: \t  refined(None) then x\n//│ ╙──      \t          ^^^^\n//│ (None | Some[anything]) -> Some[nothing]\n//│ res\n//│     = [Function: res]\n\n:ducs:desugar.result,postprocess.result\nx => if x is\n  refined(None) then x\n  refined(Some) then x\n//│ Desugared UCS term:\n//│ if\n//│   x*‡ is refined None then x\n//│   x*‡ is refined Some then x\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined None*† -> x\n//│   refined Some*◊ -> x\n//│ (None | Some[anything]) -> nothing\n//│ res\n//│     = [Function: res]\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/SpecilizationCollision.mls",
    "content": ":NewDefs\n\n// This test file is to track possible name collision during specialization.\n\nfun (~~>) check(x, y) = if x === y then \"passed\" else error\nclass Pair[out A, out B](val first: A, val second: B)\n//│ fun (~~>) check: forall 'a. (Eql['a], 'a) -> \"passed\"\n//│ class Pair[A, B](first: A, second: B)\n\nfun p1(x) = x < 0\nfun p2(x) = x > 0\nfun p3(x) = x == 0\n//│ fun p1: Num -> Bool\n//│ fun p2: Num -> Bool\n//│ fun p3: Num -> Bool\n\nfun example1(p) =\n  if p is\n    Pair(x, y) and p1(x) and p1(y) then \"both negative\"\n    Pair(a, b) and p2(a) and p2(b) then \"both positive\"\n    else \"nah\"\n//│ fun example1: (Object & ~#Pair | Pair[Num, Num]) -> (\"both negative\" | \"both positive\" | \"nah\")\n\n// FIXME: The following test case should fail, but it doesn't. The reason is\n// `x` and `y` are in the desugared lexical scope, although they don't in the\n// original lexical scope.\nfun example2(p) =\n  if p is\n    Pair(x, y) and p1(x) and p1(y) then \"both negative\"\n    Pair(a, b) and p2(a) and p2(b) then x + y\n    else \"nah\"\n//│ fun example2: (Object & ~#Pair | Pair[Int, Int]) -> (\"both negative\" | \"nah\" | Int)\n\n// Next, let's check the name collision between a class and its super class.\n\nclass Base(x: Int)\nclass Derived(y: Int) extends Base(y + 1)\n//│ class Base(x: Int)\n//│ class Derived(y: Int) extends Base\n\n// Notice that Derived is not in the inferred type.\n:ducs:postprocess.result\nfun example3(t) =\n  if t is\n    Base(x) and p1(x) then x\n    Derived(y) then y\n    else 42\n//│ Post-processed UCS term:\n//│ case t*‡ of\n//│   refined Base*◊ ->\n//│     let ucs$args_t$Base*† = (Base).unapply(t,)\n//│     let x*‡ = (ucs$args_t$Base).0\n//│     let ucs$test$0*† = p1(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> x\n//│       _ ->\n//│         case t*‡ of\n//│           Derived*◊ ->\n//│             let ucs$args_t$Derived*† = (Derived).unapply(t,)\n//│             let y*‡ = (ucs$args_t$Derived).0\n//│             y\n//│           _ -> 42\n//│   _ -> 42\n//│ fun example3: forall 'a. (Base & {#x: Num & 'a} | Object & ~#Base) -> (Int | 'a)\n\nexample3(Derived(1))\n//│ Int\n//│ res\n//│     = 1\n\nfun example4(t, x) =\n  if t is\n    Base(x) and p1(x) then x\n    Derived(y) then y + x\n    //                  ^\n    // Note that this branch will be absorbed by the previous one. As the\n    // previous branch shadows the variable `x`, a correct implementation\n    // should restore the original value of `x` in this branch.\n    else 42\n//│ fun example4: forall 'a. (Base & {#x: Num & 'a} | Object & ~#Base, Int) -> (Int | 'a)\n\nexample4(Base(-1), 0) ~~> -1\nexample4(Base(1), 2) ~~> 42\n//│ \"passed\"\n//│ res\n//│     = 'passed'\n//│ res\n//│     = 'passed'\n\nexample4(Derived(1), 4) ~~> 5\n//│ \"passed\"\n//│ res\n//│     = 'passed'\n\nclass Base(x: Int)\nclass Derived[A](y: A) extends Base(1)\n//│ class Base(x: Int)\n//│ class Derived[A](y: A) extends Base\n\n// Notice that now Derived is generic, so it's appear in the inferred type.\nfun example5(t) =\n  if t is\n    Base(x) and p1(x) then x\n    Derived(y) then y\n    else 42\n//│ fun example5: forall 'a 'b. (Base & {#x: Num & 'a} & ~#Derived | Derived['b] & {#x: Num & 'a} | Object & ~#Base) -> (42 | 'a | 'b)\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/Symbol.mls",
    "content": ":NewDefs\n\ntype List[A] = Cons[A] | Nil\nclass Cons[A](head: A, tail: List[A])\nmodule Nil\n//│ type List[A] = Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A])\n//│ module Nil\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n\nfun map(f, xs) = if xs is\n  Cons(head, tail) then f(head) :: map(f, tail)\n  Nil then Nil\n//│ fun map: forall 'A 'A0. ('A -> 'A0, Cons['A] | Nil) -> (Cons['A0] | Nil)\n\n// fun main$$5 = () =>\n//   let obj =\n//     let obj = '(' (new List$1)(1, (new List$1)(2, (new Nil$2)(),),) ')' in\n//       if obj is ‹(List$1) then map$List$1(obj, {Lambda1$2$3()},); else error›\n//     in\n//       if obj is ‹(List$1) then map$List$1(obj, {Lambda1$3$4()},); else error›\n// Got: Internal Error: Symbol already set for obj\nfun main(f) =\n  let obj = (let obj = Cons(1, Cons(2, Nil)) in (if obj is Cons(head, tail) then f(head) :: tail else Nil)) in\n    if obj is Cons(head, tail) then f(head) :: tail else Nil\n//│ fun main: forall 'A 'A0. ((1 | 2 | 'A) -> 'A) -> (Cons['A0] | Nil)\n//│   where\n//│     'A <: 'A0\n//│     'A0 :> 1 | 2\n//│         <: 'A\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/Unapply.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int, z: Int)\n//│ class Point(x: Int, y: Int, z: Int)\n\nfun f_0(p) = if p is Point(x, _, z) then x + z\n//│ fun f_0: Point -> Int\n\nf_0(Point(1, 2, 3))\n//│ Int\n//│ res\n//│     = 4\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/Unconditional.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int)\nclass Rectangle(x: Int, y: Int, width: Int, height: Int)\n//│ class Point(x: Int, y: Int)\n//│ class Rectangle(x: Int, y: Int, width: Int, height: Int)\n\nfun sum(p) = if p is Point(x, y) then x + y\n//│ fun sum: Point -> Int\n\nsum(Point(1, 2))\n//│ Int\n//│ res\n//│     = 3\n\nfun abs(x) = if x < 0 then -x else x\n//│ fun abs: Int -> Int\n\nfun dist(p, q) = if p is Point(x1, y1) and q is Point(x2, y2) then\n  abs(x1 - x2) + abs(y1 - y2)\n//│ fun dist: (Point, Point) -> Int\n\ndist(Point(1, 2), Point(3, 4))\n//│ Int\n//│ res\n//│     = 4\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/ConflictedCoveredCases.mls",
    "content": ":NewDefs\n\nclass A()\nclass B() extends A()\n//│ class A()\n//│ class B() extends A\n\nfun p(x) = true\n//│ fun p: anything -> true\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is B and\n    x is A then 1\n  x is A then 31\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   B*◊ -> 1\n//│   _ ->\n//│     case x*‡ of\n//│       A*◊ -> 31\n//│ ╔══[WARNING] the pattern always matches\n//│ ║  l.15: \t    x is A then 1\n//│ ║        \t         ^\n//│ ╟── the scrutinee was matched against B\n//│ ║  l.14: \t  x is B and\n//│ ║        \t       ^\n//│ ╟── which is a subtype of A\n//│ ║  l.4: \tclass B() extends A()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^\n//│ fun f: (A & ~#B | B) -> (1 | 31)\n\n// FIXME: wrong missing cases\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is 1 and\n    x is Int then true\n  x is 2 then false\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   1 -> true\n//│   _ ->\n//│     case x*‡ of\n//│       2 -> false\n//│ ╔══[WARNING] the pattern always matches\n//│ ║  l.39: \t    x is Int then true\n//│ ║        \t         ^^^\n//│ ╟── the scrutinee was matched against 1\n//│ ║  l.38: \t  x is 1 and\n//│ ║        \t       ^\n//│ ╟── which is a subtype of Int\n//│ ║  l.39: \t    x is Int then true\n//│ ╙──      \t         ^^^\n//│ ╔══[ERROR] `x` has 1 missing case\n//│ ║  l.38: \t  x is 1 and\n//│ ║        \t  ^\n//│ ╟── it can be class `Int`\n//│ ║  l.39: \t    x is Int then true\n//│ ╙──      \t         ^^^\n//│ fun f: (1 | 2) -> Bool\n\n:w\nfun f(x) = if\n  x is B and\n    x is A then 1\n    p(x) then 2\n  x is A then 31\n  x is B then 3\n  else 4\n//│ ╔══[WARNING] the pattern always matches\n//│ ║  l.67: \t    x is A then 1\n//│ ║        \t         ^\n//│ ╟── the scrutinee was matched against B\n//│ ║  l.66: \t  x is B and\n//│ ║        \t       ^\n//│ ╟── which is a subtype of A\n//│ ║  l.4: \tclass B() extends A()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^\n//│ fun f: (B | Object & ~#B) -> (1 | 31 | 4)\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/ConflictedPatterns.mls",
    "content": ":NewDefs\n\n// This test file contains the cases where inner cases are conflicting with outer cases.\n\nclass X\nclass Y\nclass Z\n//│ class X {\n//│   constructor()\n//│ }\n//│ class Y {\n//│   constructor()\n//│ }\n//│ class Z {\n//│   constructor()\n//│ }\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and x is Y then 1\n  else 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 2\n//│   _ -> 2\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.21: \t  x is X and x is Y then 1\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.21: \t  x is X and x is Y then 1\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.21: \t  x is X and x is Y then 1\n//│ ╙──      \t                  ^\n//│ fun f: Object -> 2\n\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and\n    x is Y then 1\n    x is Y then 2\n  else 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 3\n//│   _ -> 3\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.42: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.42: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.43: \t    x is Y then 1\n//│ ╙──      \t         ^\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.42: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.42: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.44: \t    x is Y then 2\n//│ ╙──      \t         ^\n//│ fun f: Object -> 3\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and\n    x is Y then 1\n    x is Z then 2\n  else 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 3\n//│   _ -> 3\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.73: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.73: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.74: \t    x is Y then 1\n//│ ╙──      \t         ^\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.73: \t  x is X and\n//│ ║        \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.73: \t  x is X and\n//│ ║        \t       ^\n//│ ╟── which is unrelated with Z\n//│ ║  l.75: \t    x is Z then 2\n//│ ╙──      \t         ^\n//│ fun f: Object -> 3\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is X and\n    x is Y and\n      x is Z then 1\n  else 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 2\n//│   _ -> 2\n//│ ╔══[WARNING] possibly conflicting patterns for this scrutinee\n//│ ║  l.104: \t  x is X and\n//│ ║         \t  ^\n//│ ╟── the scrutinee was matched against X\n//│ ║  l.104: \t  x is X and\n//│ ║         \t       ^\n//│ ╟── which is unrelated with Y\n//│ ║  l.105: \t    x is Y and\n//│ ╙──       \t         ^\n//│ fun f: Object -> 2\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/CoveredCases.mls",
    "content": ":NewDefs\n\n// This test file contains the cases where latter cases are covered by the former cases.\n\n// B <: A\nclass A()\nclass B() extends A()\n//│ class A()\n//│ class B() extends A\n\n:w\nfun f(x) = if\n  x is A then 1\n  x is A then 2\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.14: \t  x is A then 2\n//│ ║        \t       ^\n//│ ╟── there is an identical pattern A\n//│ ║  l.13: \t  x is A then 1\n//│ ╙──      \t       ^\n//│ fun f: A -> 1\n\n:w\n:ducs:normalize.result\nfun f(x) = if\n  x is A then 1\n  x is B then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   A*◊ -> 1\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.27: \t  x is B then 2\n//│ ║        \t       ^\n//│ ╟── the case is covered by pattern A\n//│ ║  l.26: \t  x is A then 1\n//│ ║        \t       ^\n//│ ╟── due to the subtyping relation\n//│ ║  l.7: \tclass B() extends A()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^\n//│ fun f: A -> 1\n\n:ducs:normalize.result\nfun f(x) = if\n  x is A and\n    x is B then 1\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined A*◊ ->\n//│     case x*‡ of\n//│       B*◊ -> 1\n//│ fun f: B -> 1\n\n// :w\n// FIXME\n:ducs:normalize.result\nfun f(x) = if\n  x is A and\n    x is B then 1\n  x is B then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined A*◊ ->\n//│     case x*‡ of\n//│       B*◊ -> 1\n//│ fun f: B -> 1\n\nfun p(x) = true: Bool\n//│ fun p: anything -> Bool\n\n// :w\n// FIXME\n:ducs:normalize.result\nfun f(x) = if\n  x is A and\n    x is B then 1\n    p(x) then 2\n  x is B then 3\n  else 4\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined A*◊ ->\n//│     case x*‡ of\n//│       B*◊ -> 1\n//│       _ ->\n//│         let ucs$test$0*† = p(x,) : Bool\n//│         case ucs$test$0*† of\n//│           true*† -> 2\n//│           _ -> 4\n//│   _ -> 4\n//│ fun f: Object -> (1 | 2 | 4)\n\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/DuplicatedCases.mls",
    "content": ":NewDefs\n\n// This test file contains the cases containing cases with identical patterns.\n\n:w\n:ducs:normalize.result\nfun f(x) = if x is\n  \"a\" then 1\n  \"b\" then 2\n  \"a\" then 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   \"a\" -> 1\n//│   _ ->\n//│     case x*‡ of\n//│       \"b\" -> 2\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.10: \t  \"a\" then 3\n//│ ║        \t  ^^^\n//│ ╟── there is an identical pattern \"a\"\n//│ ║  l.8: \t  \"a\" then 1\n//│ ╙──     \t  ^^^\n//│ fun f: (\"a\" | \"b\") -> (1 | 2)\n\nclass X\nclass Y\n//│ class X {\n//│   constructor()\n//│ }\n//│ class Y {\n//│   constructor()\n//│ }\n\n:w\n:ducs:normalize.result\nfun f(x) = if x is\n  X then 1\n  X then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 1\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.38: \t  X then 2\n//│ ║        \t  ^\n//│ ╟── there is an identical pattern X\n//│ ║  l.37: \t  X then 1\n//│ ╙──      \t  ^\n//│ fun f: X -> 1\n\n:w\n:ducs:normalize.result\nfun f(x) = if x is\n  X then 1\n  Y then 2\n  X then 3\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   X*◊ -> 1\n//│   _ ->\n//│     case x*‡ of\n//│       Y*◊ -> 2\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.55: \t  X then 3\n//│ ║        \t  ^\n//│ ╟── there is an identical pattern X\n//│ ║  l.53: \t  X then 1\n//│ ╙──      \t  ^\n//│ fun f: (X | Y) -> (1 | 2)\n\nclass Box[T](value: T)\n//│ class Box[T](value: T)\n\n:ducs:normalize.result\nfun f(x) = if x is\n  Box(1) then true\n  Box then false\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Box*◊ ->\n//│     let ucs$args_x$Box*† = (Box).unapply(x,)\n//│     let x$Box_0*‡ = (ucs$args_x$Box).0\n//│     case x$Box_0*‡ of\n//│       1 -> true\n//│       _ -> false\n//│ fun f: Box[Object] -> Bool\n\nf(Box(0))\nf(Box(1))\n//│ Bool\n//│ res\n//│     = false\n//│ res\n//│     = true\n\n:ducs:postprocess.result\nfun a_tale_of_scrutinees(x, y) =\n  if\n    x is \"A\" and y is \"B\" then \"AB\"\n    y is \"A\" and x is \"B\" then \"BA\"\n    y is \"A\" and x is \"A\" then \"AA\"\n    x is \"B\" and y is \"B\" then \"BB\"\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   \"A\" ->\n//│     case y*‡ of\n//│       \"B\" -> \"AB\"\n//│       \"A\" -> \"AA\"\n//│   \"B\" ->\n//│     case y*‡ of\n//│       \"A\" -> \"BA\"\n//│       \"B\" -> \"BB\"\n//│ fun a_tale_of_scrutinees: (\"A\" | \"B\", \"A\" | \"B\") -> (\"AA\" | \"AB\" | \"BA\" | \"BB\")\n\n:ducs:normalize.result\nfun test(x, p) = if x is\n  Bool and p(x) then \"great\"\n  true then \"false\"\n  false then \"true\"\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   refined Bool*◊ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> \"great\"\n//│       _ ->\n//│         case x*‡ of\n//│           true*† -> \"false\"\n//│           _ ->\n//│             case x*‡ of\n//│               false*† -> \"true\"\n//│ fun test: forall 'a. ('a & Bool, (Bool & 'a) -> Bool) -> (\"false\" | \"great\" | \"true\")\n\nclass P[A](x: A)\nclass Q[A, B](x: A, y: B)\n//│ class P[A](x: A)\n//│ class Q[A, B](x: A, y: B)\n\nfun f(x) =\n  if x is\n    P(1) then 1\n    P(y) then 2\n//│ fun f: P[Object] -> (1 | 2)\n\n:ducs:normalize.result\nfun f(x) =\n  if x is\n    Q(a, b) and a is 1 and b is 1 then 1\n    Q(a, b) and b is 1 then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Q*◊ ->\n//│     let ucs$args_x$Q*† = (Q).unapply(x,)\n//│     let a*‡ = (ucs$args_x$Q).0\n//│     let b*‡ = (ucs$args_x$Q).1\n//│     case a*‡ of\n//│       1 ->\n//│         case b*‡ of\n//│           1 -> 1\n//│       _ ->\n//│         case b*‡ of\n//│           1 -> 2\n//│ fun f: Q[Object, 1] -> (1 | 2)\n\n:e\nfun f(x) =\n  if x is\n    Q(a, b) and a is 1 and b is 2 then 1\n    Q(a, b) and b is 1 then 2\n//│ ╔══[ERROR] when `x` is `Q`\n//│ ║  l.167: \t    Q(a, b) and a is 1 and b is 2 then 1\n//│ ║         \t    ^\n//│ ╟── the second argument of `Q` has 1 missing case\n//│ ║  l.168: \t    Q(a, b) and b is 1 then 2\n//│ ║         \t                ^\n//│ ╟── it can be literal 2\n//│ ║  l.167: \t    Q(a, b) and a is 1 and b is 2 then 1\n//│ ╙──       \t                                ^\n//│ fun f: Q[Object, 1] -> (1 | 2)\n\n:ducs:normalize.result\nfun f(x) =\n  if x is\n    Q(1, 1) then 1\n    Q(y, 1) then 2\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Q*◊ ->\n//│     let ucs$args_x$Q*† = (Q).unapply(x,)\n//│     let x$Q_0*‡ = (ucs$args_x$Q).0\n//│     let x$Q_1*‡ = (ucs$args_x$Q).1\n//│     case x$Q_0*‡ of\n//│       1 ->\n//│         case x$Q_1*‡ of\n//│           1 -> 1\n//│           _ -> (ucs$args_x$Q).0\n//│       _ ->\n//│         let y*‡ = (ucs$args_x$Q).0\n//│         case x$Q_1*‡ of\n//│           1 -> 2\n//│ fun f: forall 'a. Q[Object & 'a, 1] -> (1 | 2 | 'a)\n\nfun f(x) =\n  if x is\n    Q(0, 0) then 1\n    Q(1, 1) then 2\n    Q(y, 1) then 3\n    _       then 4\n//│ fun f: (Object & ~#Q | Q[Object, Object]) -> (1 | 2 | 3 | 4)\n\nfun f(x) =\n  if x is\n    P(P(P(1))) then 1\n    P(P(1)) then 2\n    P(1) then 3\n//│ fun f: P[1 | P[1 | P[1]]] -> (1 | 2 | 3)\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/MissingCases.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\nclass Pair[A, B](x: A, y: B)\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n//│ class Pair[A, B](x: A, y: B)\n\nfun good_add_1(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n//│ fun good_add_1: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\n:e\nfun bad_add_missing_SS(x, y) =\n  if\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.23: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.23: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.24: \t    x is None     and y is Some(yv) then yv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_SS: forall 'a. (None | Some['a], None) -> (0 | 'a)\n\n:e\nfun bad_add_missing_SN(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is None     and y is Some(yv) then yv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.40: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.40: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║        \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.42: \t    x is None     and y is None     then 0\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_SN: forall 'a. (None | Some[Int], Some[Int & 'a]) -> (Int | 'a)\n\n:e\nfun bad_add_missing_NS(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.59: \t    x is None     and y is None     then 0\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.59: \t    x is None     and y is None     then 0\n//│ ║        \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.57: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_NS: (None | Some[Int], None) -> Int\n\n:e\nfun bad_add_missing_NN(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.76: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.76: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.75: \t    x is Some(xv) and y is None     then xv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_NN: forall 'a. (None | Some[Int], Some[Int & 'a]) -> (Int | 'a)\n\n:e\nfun bad_add_missing_SS_NN(x, y) =\n  if\n    x is Some(xv) and y is None     then xv\n    x is None     and y is Some(yv) then yv\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.91: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.91: \t    x is Some(xv) and y is None     then xv\n//│ ║        \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.92: \t    x is None     and y is Some(yv) then yv\n//│ ╙──      \t                           ^^^^\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.92: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.92: \t    x is None     and y is Some(yv) then yv\n//│ ║        \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.91: \t    x is Some(xv) and y is None     then xv\n//│ ╙──      \t                           ^^^^\n//│ fun bad_add_missing_SS_NN: forall 'a. (None | Some['a], nothing) -> 'a\n\n:e\nfun bad_add_missing_SN_NS(x, y) =\n  if\n    x is Some(xv) and y is Some(yv) then xv + yv\n    x is None     and y is None     then 0\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.116: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║         \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.116: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ║         \t                      ^\n//│ ╟── it can be module `None`\n//│ ║  l.117: \t    x is None     and y is None     then 0\n//│ ╙──       \t                           ^^^^\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.117: \t    x is None     and y is None     then 0\n//│ ║         \t         ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.117: \t    x is None     and y is None     then 0\n//│ ║         \t                      ^\n//│ ╟── it can be class `Some`\n//│ ║  l.116: \t    x is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──       \t                           ^^^^\n//│ fun bad_add_missing_SN_NS: (None | Some[Int], nothing) -> Int\n\nfun actually_fine_add(x, y) =\n  if\n    x is Some(xv) and y is None then xv\n//│ fun actually_fine_add: forall 'a. (Some['a], None) -> 'a\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/Refinement.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int)\nabstract class Shape: (Circle | Rectangle | LineSegment)\nclass Circle(center: Point, radius: Int) extends Shape\nclass Rectangle(position: Point, width: Int, height: Int) extends Shape\nclass LineSegment(start: Point, end: Point) extends Shape\n//│ class Point(x: Int, y: Int)\n//│ abstract class Shape: Circle | LineSegment | Rectangle\n//│ class Circle(center: Point, radius: Int) extends Shape\n//│ class Rectangle(position: Point, width: Int, height: Int) extends Shape\n//│ class LineSegment(start: Point, end: Point) extends Shape\n\nfun hidden(p) = if p is Circle then true else false\n//│ fun hidden: Object -> Bool\n\nfun this_is_sealed(x: Shape) =\n  if x is\n    Circle(_, _) then \"Circle\"\n    Rectangle(_, _, _) then \"Rectangle\"\n    LineSegment(_, _) then \"LineSegment\"\n//│ fun this_is_sealed: (x: Shape) -> (\"Circle\" | \"LineSegment\" | \"Rectangle\")\n\n// The error message here makes some sense right now.\n:e\nfun missing_a_case(x: Shape) =\n  if x is\n    Circle(_, _) then \"Circle\"\n    Rectangle(_, _, _) then \"Rectangle\"\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.27: \t  if x is\n//│ ║        \t     ^^^^\n//│ ║  l.28: \t    Circle(_, _) then \"Circle\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.29: \t    Rectangle(_, _, _) then \"Rectangle\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `Circle | LineSegment | Rectangle` does not match type `Circle | Rectangle`\n//│ ║  l.26: \tfun missing_a_case(x: Shape) =\n//│ ║        \t                      ^^^^^\n//│ ╟── but it flows into reference with expected type `Circle | Rectangle`\n//│ ║  l.27: \t  if x is\n//│ ╙──      \t     ^\n//│ fun missing_a_case: (x: Shape) -> (\"Circle\" | \"Rectangle\")\n\nfun missing_a_case(x: Shape) =\n  if x is\n    Circle(_, _) then \"Circle\"\n    Rectangle(_, _, _) then \"Rectangle\"\n    else x\n//│ fun missing_a_case: (x: Shape) -> (\"Circle\" | \"Rectangle\" | LineSegment)\n\nfun countLineSegments(x) =\n  if x is\n    Shape and hidden(x) then \"1\"\n    Rectangle(_, _, _) then \"2\"\n    LineSegment(_, _) then \"3\"\n    Circle(_, _) then \"4\"\n//│ fun countLineSegments: (Circle | LineSegment | Rectangle) -> (\"1\" | \"2\" | \"3\" | \"4\")\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/SealedClasses.mls",
    "content": ":NewDefs\n\nabstract class Term: Abs | App | Var\nclass Var(name: Str) extends Term\nclass Abs(param: Str, body: Term) extends Term\nclass App(func: Term, arg: Term) extends Term\n//│ abstract class Term: Abs | App | Var\n//│ class Var(name: Str) extends Term\n//│ class Abs(param: Str, body: Term) extends Term\n//│ class App(func: Term, arg: Term) extends Term\n\n:ducs:desugar.result\nfun is_value_explicit_refinement(term) =\n  if term is refined(Term) and term is\n    Abs(_, _) then true\n    Var(_) then false\n    App(_, _) then false\n//│ Desugared UCS term:\n//│ if term*‡ is refined Term\n//│   term*‡ is Abs then true\n//│   term*‡ is Var then false\n//│   term*‡ is App then false\n//│ fun is_value_explicit_refinement: (Abs | App | Var) -> Bool\n\n:ducs:normalize.result,postprocess.result\nfun is_value_automatic_refinement(term) =\n  if term is Term and term is\n    Abs(_, _) then true\n    Var(_) then false\n    App(_, _) then false\n//│ Normalized UCS term:\n//│ case term*‡ of\n//│   refined Term*◊ ->\n//│     case term*‡ of\n//│       Abs*◊ -> true\n//│       _ ->\n//│         case term*‡ of\n//│           Var*◊ -> false\n//│           _ ->\n//│             case term*‡ of\n//│               App*◊ -> false\n//│ Post-processed UCS term:\n//│ case term*‡ of\n//│   refined Term*◊ ->\n//│     case term*‡ of\n//│       Abs*◊ -> true\n//│       Var*◊ -> false\n//│       App*◊ -> false\n//│ fun is_value_automatic_refinement: (Abs | App | Var) -> Bool\n\nfun is_value'(term) =\n  if term is Term and term is\n    Abs(_, _) then true\n    Var(_) then false\n//│ fun is_value': (Abs | Var) -> Bool\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/Tautology.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\nclass Pair[A, B](x: A, y: B)\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n//│ class Pair[A, B](x: A, y: B)\n\nfun useless_negate_1(x) =\n  if\n    x is Some(y) and x is Some(z) then y + z\n//│ fun useless_negate_1: Some[Int] -> Int\n\nuseless_negate_1(Some(1))\n//│ Int\n//│ res\n//│     = 2\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/coverage/Unreachable.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\nclass Pair[A, B](x: A, y: B)\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n//│ class Pair[A, B](x: A, y: B)\n\nfun f(x) = if x is Some(xv) and xv === 1 then true else false\n//│ fun f: (Object & ~#Some | Some[Eql[1]]) -> Bool\n\nf(Some(1))\nf(Some(2))\nf(None)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n\nfun reachable_1(x) =\n  if x is\n    _ and f(x) then \"cos\"\n    Some(xv) then \"sin\"\n    None then \"tan\"\n//│ fun reachable_1: (None | Some[anything] & ~#Some | Some[Eql[1]]) -> (\"cos\" | \"sin\" | \"tan\")\n\nreachable_1(Some(1))\nreachable_1(Some(2))\nreachable_1(None)\n//│ \"cos\" | \"sin\" | \"tan\"\n//│ res\n//│     = 'cos'\n//│ res\n//│     = 'sin'\n//│ res\n//│     = 'tan'\n\n:w\nfun unreachable_1(x) =\n  if x is\n    _ and\n      f(x) then \"tmux\"\n      else \"screen\"\n    Some(xv) then \"sin\"\n    None then \"tan\"\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.46: \t  if x is\n//│ ║        \t     ^^^^\n//│ ║  l.47: \t    _ and\n//│ ║        \t^^^^^^^^^\n//│ ║  l.48: \t      f(x) then \"tmux\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.49: \t      else \"screen\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ║  l.50: \t    Some(xv) then \"sin\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.51: \t    None then \"tan\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.49: \t      else \"screen\"\n//│ ╙──      \t           ^^^^^^^^\n//│ fun unreachable_1: (Object & ~#Some | Some[Eql[1]]) -> (\"screen\" | \"tmux\")\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/AVLTree.mls",
    "content": ":NewDefs\n\nfun (|>) pipe(x, f) = f(x)\nfun (~~>) toBe(x, y) = if x === y then () else error\nfun (<?) min(x, y) = if x < y then x else y\nfun (>?) max(x, y) = if x > y then x else y\nfun abs(x) = if x < 0 then -x else x\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (~~>) toBe: forall 'c. (Eql['c], 'c) -> ()\n//│ fun (<?) min: forall 'd. (Num & 'd, Num & 'd) -> 'd\n//│ fun (>?) max: forall 'e. (Num & 'e, Num & 'e) -> 'e\n//│ fun abs: Int -> Int\n\nabstract class Option[out T]: (Some[T] | None)\nclass Some[out T](val value: T) extends Option[T]\nmodule None extends Option[nothing]\n//│ abstract class Option[T]: None | Some[T]\n//│ class Some[T](value: T) extends Option\n//│ module None extends Option\n\nfun (??) getOrElse(o, v) = if o is\n  Some(v') then v'\n  None then v\n//│ fun (??) getOrElse: forall 'a. (None | Some['a], 'a) -> 'a\n\nfun (++) strcat(s1, s2) = concat(s1)(s2)\n//│ fun (++) strcat: (Str, Str) -> Str\n\nlet anyToString = toString\n//│ let anyToString: anything -> Str\n//│ anyToString\n//│             = [Function: toString]\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List[nothing]\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\nabstract class Tree[out A]: (Empty | Node[A])\nclass Node[out A](value: A, left: Tree[A], right: Tree[A], height: Int) extends Tree[A]\nmodule Empty extends Tree[nothing]\n//│ abstract class Tree[A]: Empty | Node[A]\n//│ class Node[A](value: A, left: Tree[A], right: Tree[A], height: Int) extends Tree\n//│ module Empty extends Tree\n\nfun showTree(t: Tree[anything]): Str = if t is\n  Node(v, l, r, _) then\n    \"(\" ++ showTree(l) ++ \" \" ++ toString(v) ++ \" \" ++ showTree(r) ++ \")\"\n  Empty then \"•\"\n//│ fun showTree: (t: Tree[anything]) -> Str\n\nfun showTreeWithHeight(t: Tree[anything]): Str = if t is\n  Node(v, l, r, h) then\n    \"(\" ++ showTreeWithHeight(l) ++ \" \" ++ toString(v) ++ \" [\" ++ toString(h) ++ \"]\" ++ \" \" ++ showTreeWithHeight(r) ++ \")\"\n  Empty then \"•\"\n//│ fun showTreeWithHeight: (t: Tree[anything]) -> Str\n\nfun height(t) =\n  if t is\n    Node(_, _, _, h) then h\n    Empty then 0\n//│ fun height: (Empty | Node[anything]) -> Int\n\nlet nil = Empty\nfun node(v, l, r) = Node(v, l, r, max(height(l), height(r)) + 1)\nfun single(v) = Node(v, Empty, Empty, 1)\n//│ let nil: Empty\n//│ fun node: forall 'A. ('A, Empty & Tree['A] | Node[anything] & Tree['A], Empty & Tree['A] | Node[anything] & Tree['A]) -> Node['A]\n//│ fun single: forall 'A0. 'A0 -> Node['A0]\n//│ nil\n//│     = Empty { class: [class Empty extends Tree] }\n\nfun isBalanced(t) =\n  if t is\n    Node(t, l, r, _) then\n      (abs(height(l) - height(r)) <= 1) && isBalanced(l) && isBalanced(r)\n    Empty then true\n//│ fun isBalanced: (Empty | Node[anything]) -> Bool\n\nisBalanced(nil) ~~> true\n//│ ()\n//│ res\n//│     = undefined\n\n//      _             _                    _        _\n//  ___(_)_ __   __ _| | ___     _ __ ___ | |_ __ _| |_ ___\n// / __| | '_ \\ / _` | |/ _ \\   | '__/ _ \\| __/ _` | __/ _ \\\n// \\__ \\ | | | | (_| | |  __/   | | | (_) | || (_| | ||  __/\n// |___/_|_| |_|\\__, |_|\\___|   |_|  \\___/ \\__\\__,_|\\__\\___|\n//              |___/\n\nfun rotateLeft(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, l, Node(v', l', r', _), _) and\n      max(height(l), height(l')) + 1 is h and\n        max(h, height(r')) + 1 is h' then\n          Node(v', Node(v, l, l', h), r', h')\n    _ then t\n//│ fun rotateLeft: forall 'A. (t: Tree['A]) -> Tree['A]\n\nrotateLeft(nil) |> showTree\nrotateLeft(single(0)) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n\nlet unbalanced1 = node(0, nil, node(1, nil, single(2)))\nisBalanced(unbalanced1) ~~> false\nunbalanced1 |> showTree\nrotateLeft(unbalanced1) |> showTree\n//│ let unbalanced1: Node[0 | 1 | 2]\n//│ Str\n//│ unbalanced1\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n//│ res\n//│     = '((• 0 •) 1 (• 2 •))'\n\nfun rotateRight(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, Node(v', l', r', _), r, _) then\n      Node(v', l', Node(v, r', r, 0), 0)\n    _ then t\n//│ fun rotateRight: forall 'A. (t: Tree['A]) -> Tree['A]\n\nrotateRight(nil) |> showTree\nrotateRight(single(0)) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n\nlet unbalanced2 = node(2, node(1, single(0), nil), nil)\nisBalanced(unbalanced2) ~~> false\nunbalanced2 |> showTree\nrotateRight(unbalanced2) |> showTree\n//│ let unbalanced2: Node[0 | 1 | 2]\n//│ Str\n//│ unbalanced2\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '(((• 0 •) 1 •) 2 •)'\n//│ res\n//│     = '((• 0 •) 1 (• 2 •))'\n\n//      _             _     _                    _        _\n//   __| | ___  _   _| |__ | | ___     _ __ ___ | |_ __ _| |_ ___\n//  / _` |/ _ \\| | | | '_ \\| |/ _ \\   | '__/ _ \\| __/ _` | __/ _ \\\n// | (_| | (_) | |_| | |_) | |  __/   | | | (_) | || (_| | ||  __/\n//  \\__,_|\\___/ \\__,_|_.__/|_|\\___|   |_|  \\___/ \\__\\__,_|\\__\\___|\n//\n\nfun rotateRightLeft(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, t1, Node(v', Node(v'', t2, t3, _), t4, _), _) then\n      Node(v'', Node(v, t1, t2, 0), Node(v', t3, t4, 0), 0)\n    else t\n//│ fun rotateRightLeft: forall 'A. (t: Tree['A]) -> Tree['A]\n\n// Should remain the same.\nrotateRightLeft(nil) |> showTree\nrotateRightLeft(single(0)) |> showTree\nrotateRightLeft(unbalanced1) |> showTree\nrotateRightLeft(unbalanced2) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n//│ res\n//│     = '(((• 0 •) 1 •) 2 •)'\n\nlet unbalanced3 = node(0, nil, node(3, node(1, nil, single(2)), nil))\nisBalanced(unbalanced3) ~~> false\nunbalanced3 |> showTree\nrotateRightLeft(unbalanced3) |> showTree\n//│ let unbalanced3: Node[0 | 1 | 2 | 3]\n//│ Str\n//│ unbalanced3\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '(• 0 ((• 1 (• 2 •)) 3 •))'\n//│ res\n//│     = '((• 0 •) 1 ((• 2 •) 3 •))'\n\nfun rotateLeftRight(t: Tree['A]): Tree['A] =\n  if t is\n    Node(v, Node(v', t1, Node(v'', t2, t3, _), _), t4, _) then\n      Node(v'', Node(v', t1, t2, 0), Node(v, t3, t4, 0), 0)\n    else t\n//│ fun rotateLeftRight: forall 'A. (t: Tree['A]) -> Tree['A]\n\n// Should remain the same.\nrotateLeftRight(nil) |> showTree\nrotateLeftRight(single(0)) |> showTree\nrotateLeftRight(unbalanced1) |> showTree\nrotateLeftRight(unbalanced2) |> showTree\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n//│ res\n//│     = '(((• 0 •) 1 •) 2 •)'\n\nlet unbalanced4 = node(3, node(0, nil, node(2, single(1), nil)), nil)\nisBalanced(unbalanced4) ~~> false\nunbalanced4 |> showTree\nrotateRightLeft(unbalanced4) |> showTree\n//│ let unbalanced4: Node[0 | 1 | 2 | 3]\n//│ Str\n//│ unbalanced4\n//│             = Node {}\n//│ res\n//│     = undefined\n//│ res\n//│     = '((• 0 ((• 1 •) 2 •)) 3 •)'\n//│ res\n//│     = '((• 0 ((• 1 •) 2 •)) 3 •)'\n\nfun bf(t) =\n  if t is\n    Node(_, l, r, _) then height(l) - height(r)\n    Empty then 0\n//│ fun bf: (Empty | Node[anything]) -> Int\n\n//  _                     _\n// (_)_ __  ___  ___ _ __| |_\n// | | '_ \\/ __|/ _ \\ '__| __|\n// | | | | \\__ \\  __/ |  | |_\n// |_|_| |_|___/\\___|_|   \\__|\n//\n\n// This function does not work for now as it exposed a lot of problems we have\n// in desugaring and normalization. For example:\n// \n// - [x] We need to mark the Boolean scrutinees and skip the specialization of\n//   these scrutinees in the normalization process, otherwise, it would result\n//   in many futile computations.\n// - [x] We should cache the expressions that are broken by conditional splits,\n//   otherwise, they will be evaluated for more than one time.\n// - [ ] The branches of an operator split should be \"chained\" rather\n//   than placed in parallel, otherwise, the later branches will appear in the\n//   else branch of all its previous branches. **WORK IN PROGRESS**\n//\n// :ducs:postprocess\nfun balance(t: Tree['A]): Tree['A] =\n  if t is\n    Node(x, l, r, _) and height(r) - height(l)\n      > 1 and r is Node(y, l', r', _) and height(r') - height(l')\n        > 0 then rotateLeft(t)\n        < 0 and l' is Node then rotateRightLeft(t)\n      < 1 and l is Node(y, l', r', _) and height(r') - height(l')\n        > 0 and r' is Node then rotateLeftRight(t)\n        < 0 then rotateRight(t)\n    _ then t\n//│ fun balance: forall 'A. (t: Tree['A]) -> Tree['A]\n\nfun insert(t: Tree[Num], v: Num) = if t is\n  Node(v', l, r, h) and\n    v < v' then Node(v', insert(l, v), r, h) |> balance\n    v > v' then Node(v', l, insert(r, v), h) |> balance\n    _ then t\n  Empty then Node(v, Empty, Empty, 1)\n//│ fun insert: (t: Tree[Num], v: Num) -> (Node[Num] | Tree[Num])\n\n\ninsert(nil, 0) |> showTree\ninsert(single(0), 1) |> showTree\ninsert(single(0), -1) |> showTree\n//│ Str\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 (• 1 •))'\n//│ res\n//│     = '((• -1 •) 0 •)'\n\ninsert(node(0, nil, single(1)), 2) |> showTreeWithHeight\ninsert(node(0, nil, single(1)), 2) |> showTree\n//│ Str\n//│ res\n//│     = '(• 0 [2] (• 1 [1] (• 2 [1] •)))'\n//│ res\n//│     = '(• 0 (• 1 (• 2 •)))'\n\ninsert(unbalanced1, 3) |> showTree\n//│ Str\n//│ res\n//│     = '((• 0 •) 1 (• 2 (• 3 •)))'\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/BinarySearchTree.mls",
    "content": ":NewDefs\n\nfun (|>) pipe(x, f) = f(x)\nfun (~~>) toBe(x, y) = if x === y then () else error\nfun (<?) min(x, y) = if x < y then x else y\nfun (>?) max(x, y) = if x > y then x else y\nfun abs(x) = if x < 0 then -x else x\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (~~>) toBe: forall 'c. (Eql['c], 'c) -> ()\n//│ fun (<?) min: forall 'd. (Num & 'd, Num & 'd) -> 'd\n//│ fun (>?) max: forall 'e. (Num & 'e, Num & 'e) -> 'e\n//│ fun abs: Int -> Int\n\n\nabstract class Option[T]: (Some[T] | None)\nclass Some[T](val value: T) extends Option[T]\nmodule None extends Option[nothing]\n//│ abstract class Option[T]: None | Some[T]\n//│ class Some[T](value: T) extends Option\n//│ module None extends Option\n\nfun (??) getOrElse(o, v) = if o is\n  Some(v') then v'\n  None then v\n//│ fun (??) getOrElse: forall 'a. (None | Some['a], 'a) -> 'a\n\nfun (++) strcat(s1, s2) = concat(s1)(s2)\n//│ fun (++) strcat: (Str, Str) -> Str\n\nlet anyToString = toString\n//│ let anyToString: anything -> Str\n//│ anyToString\n//│             = [Function: toString]\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List[nothing]\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\n1 :: 2 :: 3 :: 4 :: Nil\n//│ Cons[1 | 2 | 3 | 4]\n//│ res\n//│     = Cons {}\n\nabstract class Tree[out A]: (Empty | Node[A])\nclass Node[out A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A]\nmodule Empty extends Tree\n//│ abstract class Tree[A]: Empty | Node[A]\n//│ class Node[A](value: A, left: Tree[A], right: Tree[A]) extends Tree\n//│ module Empty extends Tree\n\nfun single(v) = Node(v, Empty, Empty)\n//│ fun single: forall 'A. 'A -> Node['A]\n\nfun show(t: Tree['A]): Str = if t is\n  Node(v, l, r) then\n    \"(\" ++ show(l) ++ \" \" ++ toString(v) ++ \" \" ++ show(r) ++ \")\"\n  Empty then \"•\"\n//│ fun show: (t: Tree[anything]) -> Str\n\nshow(Empty)\nshow(Node(0, Empty, Empty))\nshow(Node(1, Node(0, Empty, Empty), Empty))\nshow(Node(1, Node(0, Empty, Empty), Node(2, Empty, Empty)))\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '((• 0 •) 1 •)'\n//│ res\n//│     = '((• 0 •) 1 (• 2 •))'\n\nfun insert(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then Node(v', insert(l, v), r)\n    v > v' then Node(v', l, insert(r, v))\n    _ then t\n  Empty then Node(v, Empty, Empty)\n//│ fun insert: forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A])\n\nfun insert'(t, v) = if t is\n  Node(v', l, r) and v\n    < v' then Node(v', insert(l, v), r)\n    > v' then Node(v', l, insert(r, v))\n    else t\n  Empty then Node(v, Empty, Empty)\n//│ fun insert': forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A])\n\ninsert(Empty, 0) |> show\ninsert(Node(0, Empty, Empty), 0) |> show\ninsert(Node(1, Empty, Empty), 0) |> show\ninsert(Node(1, Node(0, Empty, Empty), Empty), 0) |> show\ninsert(Node(1, Node(0, Empty, Empty), Empty), 2) |> show\n//│ Str\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '((• 0 •) 1 •)'\n//│ res\n//│     = '((• 0 •) 1 •)'\n//│ res\n//│     = '((• 0 •) 1 (• 2 •))'\n\n\nfun fromList(l) =\n  let rec fromList'(t, xs) =\n    if xs is\n      Cons(x, xs') then fromList'(insert(t, x), xs')\n      Nil then t\n  fromList'(Empty, l)\n//│ fun fromList: forall 'A. (Cons[Num & 'A] | Nil) -> (Empty | Node['A])\n\nfromList(1 :: 2 :: 3 :: 4 :: Nil) |> show\nfromList(2 :: 1 :: 4 :: 3 :: Nil) |> show\nfromList(4 :: 3 :: 2 :: 1 :: Nil) |> show\nlet example1 = fromList(1 :: 3 :: 2 :: 4 :: Nil)\nexample1 |> show\n//│ let example1: Empty | Node[1 | 2 | 3 | 4]\n//│ Str\n//│ res\n//│     = '(• 1 (• 2 (• 3 (• 4 •))))'\n//│ res\n//│     = '((• 1 •) 2 ((• 3 •) 4 •))'\n//│ res\n//│     = '((((• 1 •) 2 •) 3 •) 4 •)'\n//│ example1\n//│          = Node {}\n//│ res\n//│     = '(• 1 ((• 2 •) 3 (• 4 •)))'\n\nfun contains(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then contains(l, v)\n    v > v' then contains(r, v)\n    _ then true\n  Empty then false\n//│ fun contains: (Empty | Node[Num], Num) -> Bool\n\n// Writing tests like this is very interesting.\ncontains(Empty, 0) ~~> false\ncontains(Node(0, Empty, Empty), 0) ~~> true\ncontains(Node(1, Empty, Empty), 0) ~~> false\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n\nfun minValue(t) = if t is\n  Empty then None\n  Node(v, Empty, _) then Some(v)\n  Node(_, l, _) then minValue(l)\n//│ fun minValue: forall 'T. (Empty | Node['T]) -> (None | Some['T])\n\nminValue(Empty) ?? \"not found\"\nminValue(Node(0, Empty, Empty)) ?? \"not found\"\nminValue(example1) ?? \"not found\"\n//│ \"not found\" | 1 | 2 | 3 | 4\n//│ res\n//│     = 'not found'\n//│ res\n//│     = 0\n//│ res\n//│     = 1\n\nfun maxValue(t) = if t is\n  Empty then None\n  Node(v, _, Empty) then Some(v)\n  Node(_, _, r) then maxValue(r)\n//│ fun maxValue: forall 'T. (Empty | Node['T]) -> (None | Some['T])\n\nmaxValue(Empty) ?? \"not found\"\nmaxValue(Node(0, Empty, Empty)) ?? \"not found\"\nmaxValue(example1) ?? \"not found\"\n//│ \"not found\" | 1 | 2 | 3 | 4\n//│ res\n//│     = 'not found'\n//│ res\n//│     = 0\n//│ res\n//│     = 4\n\nfun lowerBound(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then lowerBound(l, v)\n    v > v' then Some(lowerBound(r, v) ?? v')\n    _ then Some(v')\n  Empty then None\n//│ fun lowerBound: forall 'T. (Empty | Node[Num & 'T], Num) -> (None | Some['T])\n\nlowerBound(Empty, 0) ?? \"not found\"\nlowerBound(Node(0, Empty, Empty), 0) ?? \"not found\"\nlowerBound(Node(1, Empty, Empty), 0) ?? \"not found\"\nlowerBound(Node(-1, Empty, Empty), 0) ?? \"not found\"\n//│ \"not found\" | -1\n//│ res\n//│     = 'not found'\n//│ res\n//│     = 0\n//│ res\n//│     = 'not found'\n//│ res\n//│     = -1\n\nlowerBound(example1, 0) ?? \"not found\"\nlowerBound(example1, 1) ?? \"not found\"\nlowerBound(example1, 2) ?? \"not found\"\nlowerBound(example1, 3) ?? \"not found\"\nlowerBound(example1, 4) ?? \"not found\"\nlowerBound(example1, 5) ?? \"not found\"\n//│ \"not found\" | 1 | 2 | 3 | 4\n//│ res\n//│     = 'not found'\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n//│ res\n//│     = 3\n//│ res\n//│     = 4\n//│ res\n//│     = 4\n\nlet example2 = fromList(1 :: 5 :: 42 :: 10 :: 23 :: 59 :: 81 :: Nil)\nlowerBound(example2, 0) ?? \"not found\"\nlowerBound(example2, 25) ?? \"not found\"\nlowerBound(example2, 99) ?? \"not found\"\nlowerBound(example2, 7) ?? \"not found\"\nlowerBound(example2, 32) ?? \"not found\"\nlowerBound(example2, 41) ?? \"not found\"\n//│ let example2: Empty | Node[1 | 10 | 23 | 42 | 5 | 59 | 81]\n//│ \"not found\" | 1 | 10 | 23 | 42 | 5 | 59 | 81\n//│ example2\n//│          = Node {}\n//│ res\n//│     = 'not found'\n//│ res\n//│     = 23\n//│ res\n//│     = 81\n//│ res\n//│     = 5\n//│ res\n//│     = 23\n//│ res\n//│     = 23\n\nfun upperBound(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then Some(upperBound(l, v) ?? v')\n    v > v' then upperBound(r, v)\n    _ then Some(v')\n  Empty then None\n//│ fun upperBound: forall 'T. (Empty | Node[Num & 'T], Num) -> (None | Some['T])\n\nupperBound(example2, 0) ?? \"not found\"\nupperBound(example2, 25) ?? \"not found\"\nupperBound(example2, 99) ?? \"not found\"\nupperBound(example2, 7) ?? \"not found\"\nupperBound(example2, 32) ?? \"not found\"\nupperBound(example2, 41) ?? \"not found\"\n//│ \"not found\" | 1 | 10 | 23 | 42 | 5 | 59 | 81\n//│ res\n//│     = 1\n//│ res\n//│     = 42\n//│ res\n//│     = 'not found'\n//│ res\n//│     = 10\n//│ res\n//│     = 42\n//│ res\n//│     = 42\n\nfun remove(t, v) =\n  if t is\n    Node(v', l, r) and\n      v < v' then Node(v', remove(l, v), r)\n      v > v' then Node(v', l, remove(r, v))\n      minValue(r) is\n        None then l\n        Some(v'') then Node(v'', l, remove(r, v''))\n    Empty then Empty\n//│ fun remove: forall 'A. (Empty | Node[Num & 'A], Num) -> (Empty | Node['A] | Tree['A])\n\nremove(Empty, 0) |> show\nremove(Node(0, Empty, Empty), 0) |> show\nremove(Node(1, Empty, Empty), 0) |> show\nremove(Node(1, Node(0, Empty, Empty), Empty), 0) |> show\nremove(Node(1, Empty, Node(2, Empty, Empty)), 2) |> show\nremove(Node(1, Node(0, Empty, Empty), Node(2, Empty, Empty)), 1) |> show\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 1 •)'\n//│ res\n//│     = '(• 1 •)'\n//│ res\n//│     = '(• 1 •)'\n//│ res\n//│     = '((• 0 •) 2 •)'\n\nexample1 |> show\nremove(example1, 0) |> show\nremove(example1, 1) |> show\nremove(example1, 2) |> show\nremove(example1, 3) |> show\nremove(example1, 4) |> show\n//│ Str\n//│ res\n//│     = '(• 1 ((• 2 •) 3 (• 4 •)))'\n//│ res\n//│     = '(• 1 ((• 2 •) 3 (• 4 •)))'\n//│ res\n//│     = '(• 2 (• 3 (• 4 •)))'\n//│ res\n//│     = '(• 1 (• 3 (• 4 •)))'\n//│ res\n//│     = '(• 1 ((• 2 •) 4 •))'\n//│ res\n//│     = '(• 1 ((• 2 •) 3 •))'\n\nclass Pair[A, B](val first: A, val second: B) {\n  fun mapFirst(f) = Pair(f(first), second)\n  fun mapSecond(f) = Pair(first, f(second))\n}\n//│ class Pair[A, B](first: A, second: B) {\n//│   fun mapFirst: forall 'A 'B. (A -> 'A) -> Pair['A, 'B]\n//│   fun mapSecond: forall 'B0 'A0. (B -> 'B0) -> Pair['A0, 'B0]\n//│ }\n//│ where\n//│   'A0 :> A\n//│   'B :> B\n\nfun extractMin(t) =\n  if t is\n    Node(v, Empty, r) then Pair(Some(v), r)\n    Node(v, l, r) and\n      extractMin(l) is Pair(m, l') then\n        Pair(m, Node(v, l', r))\n    Empty then Pair(None, Empty)\n//│ fun extractMin: forall 'A 'T 'A0 'A1 'B. (Empty | Node['A & 'T & 'A0]) -> Pair[in 'A1 out 'A1 | None, in Tree['A0] & 'B out Empty | 'B | Node['A0] | Tree['A]]\n//│   where\n//│     'A1 :> None | Some['T]\n\nextractMin(example1).first ?? \"not found\"\nextractMin(example1).second |> show\n//│ Str\n//│ res\n//│     = 1\n//│ res\n//│     = '((• 2 •) 3 (• 4 •))'\n\nfun merge(l, r) =\n  if extractMin(r) is\n    Pair(None, _) then l\n    Pair(Some(m), r') then Node(m, l, r')\n//│ fun merge: forall 'A 'a. (Tree['A] & 'a, Empty | Node['A]) -> (Node['A] | 'a)\n\nmerge(Empty, Empty) |> show\nmerge(Empty, Node(0, Empty, Empty)) |> show\nmerge(Node(0, Empty, Empty), Empty) |> show\nmerge(Node(0, Empty, Empty), Node(1, Empty, Empty)) |> show\nmerge(Node(0, Empty, Empty), Node(2, Node(1, Empty, Empty), Empty)) |> show\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '((• 0 •) 1 •)'\n//│ res\n//│     = '((• 0 •) 1 (• 2 •))'\n\nfun removeGte(t, v) =\n  if t is\n    Node(v', l, r) and\n      v < v' then removeGte(l, v)\n      v > v' then Node(v', l, removeGte(r, v))\n      _ then l // lucky case\n    Empty then Empty\n//│ fun removeGte: forall 'A. (Empty | Node[Num & 'A], Num) -> (Empty | Node['A] | Tree['A])\n\nremoveGte(Empty, 0) |> show\nremoveGte(example1, 0) |> show\nremoveGte(example1, 1) |> show\nremoveGte(example1, 2) |> show\nremoveGte(example1, 3) |> show\nremoveGte(example1, 4) |> show\nremoveGte(example1, 5) |> show\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '•'\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 1 •)'\n//│ res\n//│     = '(• 1 (• 2 •))'\n//│ res\n//│     = '(• 1 ((• 2 •) 3 •))'\n//│ res\n//│     = '(• 1 ((• 2 •) 3 (• 4 •)))'\n\nexample2 |> show\nremoveGte(example2, 10) |> show\nremoveGte(example2, 22) |> show\nremoveGte(example2, 23) |> show\nremoveGte(example2, 24) |> show\nremoveGte(example2, 70) |> show\nremoveGte(example2, 99) |> show\n//│ Str\n//│ res\n//│     = '(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))'\n//│ res\n//│     = '(• 1 (• 5 •))'\n//│ res\n//│     = '(• 1 (• 5 (• 10 •)))'\n//│ res\n//│     = '(• 1 (• 5 (• 10 •)))'\n//│ res\n//│     = '(• 1 (• 5 (• 10 (• 23 •))))'\n//│ res\n//│     = '(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 •))))'\n//│ res\n//│     = '(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))'\n\nfun removeLt(t, v) =\n  if t is\n    Node(v', l, r) and\n      v' < v then removeLt(r, v)\n      else Node(v', removeLt(l, v), r)\n    Empty then Empty\n//│ fun removeLt: forall 'A. (Empty | Node[Num & 'A], Num) -> (Empty | Node['A])\n\nexample2 |> show\nremoveLt(example2, 10) |> show\nremoveLt(example2, 22) |> show\nremoveLt(example2, 23) |> show\nremoveLt(example2, 24) |> show\nremoveLt(example2, 70) |> show\nremoveLt(example2, 99) |> show\n//│ Str\n//│ res\n//│     = '(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))'\n//│ res\n//│     = '((• 10 (• 23 •)) 42 (• 59 (• 81 •)))'\n//│ res\n//│     = '((• 23 •) 42 (• 59 (• 81 •)))'\n//│ res\n//│     = '((• 23 •) 42 (• 59 (• 81 •)))'\n//│ res\n//│     = '(• 42 (• 59 (• 81 •)))'\n//│ res\n//│     = '(• 81 •)'\n//│ res\n//│     = '•'\n\n// Remove elements from `begin` until `end`.\nfun removeRange(t, begin, end) =\n  if t is\n    Node(v, l, r) and\n      begin > v then Node(v, l, removeRange(r, begin, end))\n      end <= v then Node(v, removeRange(l, begin, end), r)\n      _ then merge(removeGte(l, begin), removeLt(r, end))\n    Empty then Empty\n//│ fun removeRange: forall 'A. (Empty | Node[Num & 'A], Num, Num) -> (Empty | Node['A] | Tree['A])\n\nexample2 |> show\nremoveRange(example2, 1, 82) |> show\nremoveRange(example2, 1, 50) |> show\nremoveRange(example2, 50, 81) |> show\nremoveRange(example2, 20, 60) |> show\nremoveRange(example2, 20, 24) |> show\nremoveRange(example2, 59, 60) |> show\n//│ Str\n//│ res\n//│     = '(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 59 (• 81 •)))))'\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 59 (• 81 •))'\n//│ res\n//│     = '(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 81 •))))'\n//│ res\n//│     = '(• 1 (• 5 ((• 10 •) 81 •)))'\n//│ res\n//│     = '(• 1 (• 5 ((• 10 •) 42 (• 59 (• 81 •)))))'\n//│ res\n//│     = '(• 1 (• 5 ((• 10 (• 23 •)) 42 (• 81 •))))'\n\nfun size(t) =\n  if t is\n    Node(_, l, r) then 1 + size(l) + size(r)\n    Empty then 0\n//│ fun size: (Empty | Node[anything]) -> Int\n\nsize(Empty) ~~> 0\nsize(Node(0, Empty, Empty)) ~~> 1\nsize(example1) ~~> 4\nsize(example2) ~~> 7\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n\nfun inverse(t) =\n  if t is\n    Node(v, l, r) then Node(v, inverse(r), inverse(l))\n    Empty then Empty\n//│ fun inverse: (Empty | Node[anything]) -> (Empty | Node[nothing])\n\ninverse(Empty) |> show\ninverse(Node(0, Empty, Empty)) |> show\ninverse(example1) |> show\ninverse(example2) |> show\n//│ Str\n//│ res\n//│     = '•'\n//│ res\n//│     = '(• 0 •)'\n//│ res\n//│     = '(((• 4 •) 3 (• 2 •)) 1 •)'\n//│ res\n//│     = '(((((• 81 •) 59 •) 42 ((• 23 •) 10 •)) 5 •) 1 •)'\n\nfun height(t) =\n  if t is\n    Node(_, l, r) then 1 + max(height(l), height(r))\n    Empty then 0\n//│ fun height: (Empty | Node[anything]) -> Int\n\nheight(Empty) ~~> 0\nheight(Node(0, Empty, Empty)) ~~> 1\nheight(example1) ~~> 3\nheight(example2) ~~> 5\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n\nfun isBalanced(t) =\n  if t is\n    Empty then true\n    Node(_, l, r) and height(l) is hl and height(r) is hr then\n      // The precedence of `<=` seems to be broken.\n      (abs(hl - hr) <= 1) && isBalanced(l) && isBalanced(r)\n//│ fun isBalanced: (Empty | Node[anything]) -> Bool\n\nisBalanced(Empty) ~~> true\nisBalanced(Node(0, Empty, Empty)) ~~> true\nisBalanced(example1) ~~> false\nisBalanced(example2) ~~> false\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n\nisBalanced(Node(1, single(-1), single(3))) ~~> true\nisBalanced(Node(1, single(-1), Node(3, single(2), Empty))) ~~> true\nisBalanced(Node(1, single(-1), Node(3, Empty, single(4)))) ~~> true\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/Calculator.mls",
    "content": ":NewDefs\n\n// This test file explores implementing a calculator using UCS.\n\nfun (++) concatOp(a, b) = concat(a)(b)\nfun (|>) pipe(a, f) = f(a)\nfun (!==) notEqual(x, y) = not(x === y)\nlet anyToString = toString\n//│ fun (++) concatOp: (Str, Str) -> Str\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (!==) notEqual: forall 'c. (Eql['c], 'c) -> Bool\n//│ let anyToString: anything -> Str\n//│ anyToString\n//│             = [Function: toString]\n\nfun par(s, p) = if p then \"(\" ++ s ++ \")\" else s\n//│ fun par: (Str, Bool) -> Str\n\ntype StringOps = {\n  length: Int,\n  charAt: Int => Str,\n  charCodeAt: Int => Int,\n  slice: Int => Str\n}\ndeclare fun String: nothing\nlet toStringOps: anything => StringOps = String\n//│ type StringOps = {charAt: Int -> Str, charCodeAt: Int -> Int, length: Int, slice: Int -> Str}\n//│ let toStringOps: anything -> StringOps\n//│ fun String: nothing\n//│ toStringOps\n//│             = [Function: String]\n\ntype Option[A] = Some[A] | None\nclass Some[A](value: A)\nmodule None\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A)\n//│ module None\n\nfun showOption(x) = if x is\n  Some(value) then \"Some(\" ++ toString(value) ++ \")\"\n  None then \"None\"\nfun mapOption(f, x) = if x is\n  Some(value) then Some(f(value))\n  None then None\nfun (??) getOrElse(x, default) = if x is\n  Some(value) then value\n  None then default\nfun flatten(x) = if x is\n  Some(value) then value\n  other then other\n//│ fun showOption: (None | Some[anything]) -> Str\n//│ fun mapOption: forall 'a 'A. ('a -> 'A, None | Some['a]) -> (None | Some['A])\n//│ fun (??) getOrElse: forall 'b. (None | Some['b], 'b) -> 'b\n//│ fun flatten: forall 'c. (Object & 'c & ~#Some | Some['c]) -> 'c\n\ntype List[A] = Cons[A] | Nil\nclass Cons[A](head: A, tail: List[A])\nmodule Nil\nfun (::) cons(head, tail) = Cons(head, tail)\nfun reverse(xs) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(x :: acc, xs')\n  aux(Nil, xs)\nfun join(sep) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(acc ++ sep ++ toString(x), xs')\n  (xs) =>\n    if xs is\n      Cons(x, xs') then aux(toString(x), xs')\n      Nil then \"\"\nfun showList(xs) = \"[\" ++ join(\", \")(xs) ++ \"]\"\n//│ type List[A] = Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A])\n//│ module Nil\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n//│ fun reverse: forall 'A0 'A1. (Cons['A0] | Nil) -> (Cons['A1] | Nil)\n//│ fun join: Str -> (forall 'A2. (Cons['A2] | Nil) -> Str)\n//│ fun showList: forall 'A3. (Cons['A3] | Nil) -> Str\n//│ where\n//│   'A0 <: 'A1\n\n//  _\n// | |    _____  _____ _ __\n// | |   / _ \\ \\/ / _ \\ '__|\n// | |__|  __/>  <  __/ |\n// |_____\\___/_/\\_\\___|_|\n// \n\nfun isDigit(n) = (48 <= n) && (n <= 57)\nfun isBlank(n) = (n === 32) || (n === 9) || (n === 10) || (n === 13)\n//│ fun isDigit: Num -> Bool\n//│ fun isBlank: Eql[10 | 13 | 32 | 9] -> Bool\n\nfun scanInt(text: StringOps, at: Int): Option[[Int, Int]] =\n  let rec aux(acc, i: Int): Option[[Int, Int]] = if\n    i < 0 then None\n    i >= text.length then mapOption(n => [n, i], acc)\n    let c = text.charCodeAt(i)\n    isDigit(c) then aux(Some((acc ?? 0) * 10 + c - 48), i + 1)\n    else mapOption(n => [n, i], acc)\n  aux(None, at)\n//│ fun scanInt: (text: StringOps, at: Int) -> Option[[Int, Int]]\n\nscanInt(\"a123\" |> toStringOps, 0) |> showOption\nscanInt(\"a123\" |> toStringOps, 1) |> showOption\nscanInt(\"a123\" |> toStringOps, 2) |> showOption\nscanInt(\"a123\" |> toStringOps, 3) |> showOption\nscanInt(\"a123\" |> toStringOps, 4) |> showOption\n//│ Str\n//│ res\n//│     = 'None'\n//│ res\n//│     = 'Some(123,4)'\n//│ res\n//│     = 'Some(23,4)'\n//│ res\n//│     = 'Some(3,4)'\n//│ res\n//│     = 'None'\n\nfun skipBlank(text: StringOps, at: Int): Int =\n  let rec aux(i: Int): Int = if\n    i >= text.length then i\n    isBlank(text.charCodeAt(i)) then aux(i + 1)\n    else i\n  aux(at)\n//│ fun skipBlank: (text: StringOps, at: Int) -> Int\n\nskipBlank(\"abc\" |> toStringOps, 0)\nskipBlank(\"abc\" |> toStringOps, 1)\nskipBlank(\"abc\" |> toStringOps, 2)\nskipBlank(\"  \\t\\n\\r123\" |> toStringOps, 0)\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n//│ res\n//│     = 5\n\nclass Span(val start: Int, val end: Int)\n//│ class Span(start: Int, end: Int)\n\nabstract class Token(val span: Span)\nclass IntegerLiteral(value: Int, span2: Span) extends Token(span2) { // It seems that constructor parameters is not sanitized\n  fun toString(): Str = \"IntegerLiteral(\" ++ anyToString(value) ++ \")\"\n}\nclass LeftParen(at: Int) extends Token(Span(at, at + 1)) {\n  fun toString(): Str = \"LeftParen\"\n}\nclass RightParen(at: Int) extends Token(Span(at, at + 1)) {\n  fun toString(): Str = \"RightParen\"\n}\nclass BinaryOperator(value: Str, val bp: Int, at: Int) extends Token(Span(at, at + 1)) {\n  fun toString(): Str = \"BinaryOperator(\" ++ value ++ \", \" ++ anyToString(bp) ++ \")\"\n}\nclass EndOfInput(at: Int) extends Token(Span(at, at)) {\n  fun toString(): Str = \"EndOfInput\"\n}\nclass UnknownInput(rest: Str, at: Int, length: Int) extends Token(Span(at, at + length)) {\n  fun toString(): Str = \"UnknownInput(\" ++ rest ++ \")\"\n}\n//│ abstract class Token(span: Span)\n//│ class IntegerLiteral(value: Int, span2: Span) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class LeftParen(at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class RightParen(at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class BinaryOperator(value: Str, bp: Int, at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class EndOfInput(at: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n//│ class UnknownInput(rest: Str, at: Int, length: Int) extends Token {\n//│   fun toString: () -> Str\n//│ }\n\nfun scanToken(text: StringOps, at: Int): [Token, Int] =\n  if\n    let at' = skipBlank(text, at)\n    at' >= text.length then [EndOfInput(at'), at']\n    let head = text.charCodeAt(at')\n    head ===\n      37 then [BinaryOperator(\"%\", 20, at'), at' + 1]\n      40 then [LeftParen(at'), at' + 1]\n      41 then [RightParen(at'), at' + 1]\n      42 then [BinaryOperator(\"*\", 20, at'), at' + 1]\n      43 then [BinaryOperator(\"+\", 10, at'), at' + 1]\n      45 then [BinaryOperator(\"-\", 10, at'), at' + 1]\n      47 then [BinaryOperator(\"/\", 20, at'), at' + 1]\n    (48 <= head) && (head <= 57) and\n      scanInt(text, at') is Some([n, at'']) then\n        [IntegerLiteral(n, Span(at', at'')), at'']\n    else [UnknownInput(text.slice(at'), at', text.length - at'), at']\n//│ fun scanToken: (text: StringOps, at: Int) -> [Token, Int]\n\nscanToken(\"bruh\" |> toStringOps, 0)\nscanToken(\"1\" |> toStringOps, 0)\nscanToken(\"+\" |> toStringOps, 0)\nscanToken(\"  42\" |> toStringOps, 0)\n//│ [Token, Int]\n//│ res\n//│     = [ UnknownInput {}, 0 ]\n//│ res\n//│     = [ IntegerLiteral {}, 1 ]\n//│ res\n//│     = [ BinaryOperator {}, 1 ]\n//│ res\n//│     = [ IntegerLiteral {}, 4 ]\n\nfun tokenize(str: Str): List[Token] =\n  let text = str |> toStringOps\n  let rec aux(acc, at) =\n    if scanToken(text, at) is [token, at'] and token is\n      UnknownInput then (token :: acc) |> reverse\n      EndOfInput then acc |> reverse\n      else aux(token :: acc, at')\n  aux(Nil, 0)\n//│ fun tokenize: (str: Str) -> List[Token]\n\ntokenize(\"0\") |> showList\ntokenize(\"1 + 2 * 3\") |> showList\ntokenize(\"bruh\") |> showList\n//│ Str\n//│ res\n//│     = '[IntegerLiteral(0)]'\n//│ res\n//│     = '[IntegerLiteral(1), BinaryOperator(+, 10), IntegerLiteral(2), BinaryOperator(*, 20), IntegerLiteral(3)]'\n//│ res\n//│     = '[UnknownInput(bruh)]'\n\n//  ____                _\n// |  _ \\ __ _ _ __ ___(_)_ __   __ _\n// | |_) / _` | '__/ __| | '_ \\ / _` |\n// |  __/ (_| | |  \\__ \\ | | | | (_| |\n// |_|   \\__,_|_|  |___/_|_| |_|\\__, |\n//                              |___/\n\ntype Expression = IntegerLiteral | BinaryExpression\nclass BinaryExpression(op: BinaryOperator, left: Expression, right: Expression)\n//│ type Expression = BinaryExpression | IntegerLiteral\n//│ class BinaryExpression(op: BinaryOperator, left: Expression, right: Expression)\n\nfun bindingPower(t: Expression): Int =\n  if t is\n    IntegerLiteral then 30\n    BinaryExpression(op, _, _) then op.bp\n//│ fun bindingPower: (t: Expression) -> Int\n\nfun showExpression(t: Expression): Str =\n  if t is\n    IntegerLiteral(n) then anyToString(n)\n    BinaryExpression(BinaryOperator(op, bp), left, right) then\n      let lbp = bindingPower of left\n      let rbp = bindingPower of right\n      par(showExpression(left), lbp < bp) ++ \" \" ++ op ++ \" \" ++ par(showExpression(right), rbp < bp)\n//│ fun showExpression: (t: Expression) -> Str\n\nlet s = Span(0, 0)\nIntegerLiteral(42, s) |> showExpression\nlet t1 = BinaryExpression(BinaryOperator(\"+\", 10, 0), IntegerLiteral(1, s), IntegerLiteral(2, s))\nt1 |> showExpression\nlet t2 = BinaryExpression(BinaryOperator(\"*\", 20, 0), t1, IntegerLiteral(3, s))\nt2 |> showExpression\nlet t3 = BinaryExpression(BinaryOperator(\"*\", 20, 0), t2, IntegerLiteral(4, s))\nt3 |> showExpression\n//│ let s: Span\n//│ let t1: BinaryExpression\n//│ let t2: BinaryExpression\n//│ let t3: BinaryExpression\n//│ Str\n//│ s\n//│   = Span {}\n//│ res\n//│     = '42'\n//│ t1\n//│    = BinaryExpression {}\n//│ res\n//│     = '1 + 2'\n//│ t2\n//│    = BinaryExpression {}\n//│ res\n//│     = '(1 + 2) * 3'\n//│ t3\n//│    = BinaryExpression {}\n//│ res\n//│     = '(1 + 2) * 3 * 4'\n\ntype ParseResult[A] = Some[A] | Failed\nclass Failed(message: Str)\nfun showParseResult(r: ParseResult['A]) = if r is\n  Some(value) then \"Some(\" ++ toString(value) ++ \")\"\n  Failed(message) then \"Failed(\" ++ message ++ \")\"\nfun (?>) mapParseResult(x, f) = if x is\n  Some(value) then Some(f(value))\n  failed then failed\n//│ type ParseResult[A] = Failed | Some[A]\n//│ class Failed(message: Str)\n//│ fun showParseResult: forall 'A. (r: ParseResult['A]) -> Str\n//│ fun (?>) mapParseResult: forall 'a 'b 'A0. (Object & 'a & ~#Some | Some['b], 'b -> 'A0) -> (Some['A0] | 'a)\n\nfun showParsedExpression(r: ParseResult[Expression]) = if r is\n  Some(value) then \"Some(\" ++ showExpression(value) ++ \")\"\n  Failed(message) then \"Failed(\" ++ message ++ \")\"\n//│ fun showParsedExpression: (r: ParseResult[Expression]) -> Str\n\nfun lastPosition(t: Expression): Int =\n  if t is\n    IntegerLiteral(_, span) then span.end\n    BinaryExpression(_, _, right) then lastPosition(right)\n//│ fun lastPosition: (t: Expression) -> Int\n\nfun parseAtom(ts: List[Token]): ParseResult[[Expression, List[Token]]] =\n  if ts is\n    Cons(IntegerLiteral(n, span), ts') then Some([IntegerLiteral(n, span), ts'])\n    Cons(LeftParen, ts') and parseExpression(0, ts') is\n      Some([body, Cons(RightParen, ts'')]) then Some([body, ts''])\n      Some([body, _]) then Failed(\"Expected a right parenthesis at \" ++ toString(lastPosition of body))\n      failed then failed\n    Cons(token, _) then Failed(\"Unexpected token \" ++ toString(token) ++ \" at \" ++ toString(token.span.start))\n    Nil then Failed(\"Unexpected end of input\")\nfun parseExpression(bp: Int, ts: List[Token]): ParseResult[[Expression, List[Token]]] =\n  if parseAtom(ts) is\n    Some([leftmost, ts']) then\n      let rec aux(left, ts) = if ts is\n        Cons(BinaryOperator(op, bp', opAt), ts') and bp < bp' and\n          parseExpression(bp', ts') is\n            Some([right, ts'']) then\n              aux(BinaryExpression(BinaryOperator(op, bp', opAt), left, right), ts'')\n            failed then failed\n        else Some([left, ts])\n      aux(leftmost, ts')\n    failed then failed\nfun parse(source: Str): ParseResult[Expression] =\n  if parseExpression(0, tokenize(source)) is\n    Some([expr, Nil]) then Some(expr)\n    Some([expr, rest]) then Failed(\"Unexpected token: \" ++ showList(rest) ++ \" at \" ++ toString(lastPosition of expr))\n    failed then failed\n//│ fun parseAtom: (ts: List[Token]) -> ParseResult[[Expression, List[Token]]]\n//│ fun parseExpression: (bp: Int, ts: List[Token]) -> ParseResult[[Expression, List[Token]]]\n//│ fun parse: (source: Str) -> ParseResult[Expression]\n\nparse(\"1 + 2 * 3\") |> showParsedExpression\nparse(\"(1 + 2) * 3\") |> showParsedExpression\nparse(\"2 * (1 + 3 + 5 + 7 + 9 + 11) - 2 - 4 - 6\") |> showParsedExpression\nparse(\"2 * (1 + 3) * (5 + 7) * (9 - 11)\") |> showParsedExpression\nparse(\"(((((((((42)))))))))\") |> showParsedExpression\n//│ Str\n//│ res\n//│     = 'Some(1 + 2 * 3)'\n//│ res\n//│     = 'Some((1 + 2) * 3)'\n//│ res\n//│     = 'Some(2 * (1 + 3 + 5 + 7 + 9 + 11) - 2 - 4 - 6)'\n//│ res\n//│     = 'Some(2 * (1 + 3) * (5 + 7) * (9 - 11))'\n//│ res\n//│     = 'Some(42)'\n\nparse(\"1 + \") |> showParsedExpression\nparse(\"1 bruh\") |> showParsedExpression\nparse(\"1 * (2 + 3\") |> showParsedExpression\nparse(\"1 - bruh\") |> showParsedExpression\n//│ Str\n//│ res\n//│     = 'Failed(Unexpected end of input)'\n//│ res\n//│     = 'Failed(Unexpected token: [UnknownInput(bruh)] at 1)'\n//│ res\n//│     = 'Failed(Expected a right parenthesis at 10)'\n//│ res\n//│     = 'Failed(Unexpected token UnknownInput(bruh) at 4)'\n\n//  _____            _             _   _\n// | ____|_   ____ _| |_   _  __ _| |_(_) ___  _ __\n// |  _| \\ \\ / / _` | | | | |/ _` | __| |/ _ \\| '_ \\\n// | |___ \\ V / (_| | | |_| | (_| | |_| | (_) | | | |\n// |_____| \\_/ \\__,_|_|\\__,_|\\__,_|\\__|_|\\___/|_| |_|\n//\n\nfun evaluate(t: Expression): Option[Int] =\n  if t is\n    IntegerLiteral(n) then Some(n)\n    BinaryExpression(BinaryOperator(op, _, _), left, right) and\n      evaluate(left) is Some(leftResult) and\n        evaluate(right) is Some(rightResult) and op ===\n          \"+\" then Some(leftResult + rightResult)\n          \"-\" then Some(leftResult - rightResult)\n          \"*\" then Some(leftResult * rightResult)\n          // \"/\" then Some(leftResult / rightResult)\n          \"%\" then Some(leftResult % rightResult)\n    else None\n//│ fun evaluate: (t: Expression) -> Option[Int]\n\nfun evaluation(source: Str): Str =\n  if parse(source) is\n    Some(expression) and evaluate(expression) is\n      Some(result) then toString(result)\n      None then \"Evaluation failed\"\n    Failed(message) then \"Parsing failed: \" ++ message\n//│ fun evaluation: (source: Str) -> Str\n\nevaluation(\"1 + 2 * 3\")\nevaluation(\"(((((42)))))\")\nevaluation(\"1 * (3 + 4) - 5\")\nevaluation(\"1 + \")\nevaluation(\"1 bruh\")\n//│ Str\n//│ res\n//│     = '7'\n//│ res\n//│     = '42'\n//│ res\n//│     = '2'\n//│ res\n//│     = 'Parsing failed: Unexpected end of input'\n//│ res\n//│     = 'Parsing failed: Unexpected token: [UnknownInput(bruh)] at 1'\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/EitherOrBoth.mls",
    "content": ":NewDefs\n\nabstract class Option[out T]: (Some[T] | None)\nclass Some[out T](value: T) extends Option[T]\nmodule None extends Option[nothing]\n//│ abstract class Option[T]: None | Some[T]\n//│ class Some[T](value: T) extends Option\n//│ module None extends Option\n\nabstract class EitherOrBoth[out A, out B]: (Left[A, B] | Right[A, B] | Both[A, B])\nclass Left[out A, out B](value: A) extends EitherOrBoth[A, B]\nclass Right[out A, out B](value: B) extends EitherOrBoth[A, B]\nclass Both[out A, out B](left: A, right: B) extends EitherOrBoth[A, B] \n//│ abstract class EitherOrBoth[A, B]: Both[A, B] | Left[A, B] | Right[A, B]\n//│ class Left[A, B](value: A) extends EitherOrBoth\n//│ class Right[A, B](value: B) extends EitherOrBoth\n//│ class Both[A, B](left: A, right: B) extends EitherOrBoth\n\ntype Either[A, B] = Left[A, B] | Right[A, B]\n//│ type Either[A, B] = Left[A, B] | Right[A, B]\n\nfun getLeft[A, B](eob: EitherOrBoth[A, B]): Option[A] =\n  if eob is\n    Left(left) then Some(left)\n    Right(_) then None\n    Both(left, _) then Some(left)\n//│ fun getLeft: forall 'A. (eob: EitherOrBoth['A, anything]) -> Option['A]\n\nfun getRight[A, B](eob: EitherOrBoth[A, B]): Option[B] =\n  if eob is\n    Left(_) then None\n    Right(right) then Some(right)\n    Both(_, right) then Some(right)\n//│ fun getRight: forall 'B. (eob: EitherOrBoth[anything, 'B]) -> Option['B]\n\nfun getBoth[A, B](eob: EitherOrBoth[A, B]): Option[[A, B]] =\n  if eob is\n    Left(_) then None\n    Right(_) then None\n    Both(left, right) then Some([left, right])\n//│ fun getBoth: forall 'A 'B. (eob: EitherOrBoth['A, 'B]) -> Option[['A, 'B]]\n\nfun mapLeft[A, B, C](eob: EitherOrBoth[A, B], f: A -> C): EitherOrBoth[C, B] =\n  if eob is\n    Left(left) then Left(f(left))\n    Right(right) then Right(right)\n    Both(left, right) then Both(f(left), right)\n//│ fun mapLeft: forall 'A 'B 'C. (eob: EitherOrBoth['A, 'B], f: 'A -> 'C) -> EitherOrBoth['C, 'B]\n\nfun mapRight[A, B, C](eob: EitherOrBoth[A, B], f: B -> C): EitherOrBoth[A, C] =\n  if eob is\n    Left(left) then Left(left)\n    Right(right) then Right(f(right))\n    Both(left, right) then Both(left, f(right))\n//│ fun mapRight: forall 'A 'B 'C. (eob: EitherOrBoth['A, 'B], f: 'B -> 'C) -> EitherOrBoth['A, 'C]\n\nfun map[A, B, C, D](eob: EitherOrBoth[A, B], f: A -> C, g: B -> D): EitherOrBoth[C, D] =\n  if eob is\n    Left(left) then Left(f(left))\n    Right(right) then Right(g(right))\n    Both(left, right) then Both(f(left), g(right))\n//│ fun map: forall 'A 'B 'C 'D. (eob: EitherOrBoth['A, 'B], f: 'A -> 'C, g: 'B -> 'D) -> EitherOrBoth['C, 'D]\n\nfun fold[A, B, C](eob: EitherOrBoth[A, B], f: A -> C, g: B -> C, h: [A, B] -> C): C =\n  if eob is\n    Left(left) then f(left)\n    Right(right) then g(right)\n    Both(left, right) then h(left, right)\n//│ fun fold: forall 'A 'B 'C. (eob: EitherOrBoth['A, 'B], f: 'A -> 'C, g: 'B -> 'C, h: ('A, 'B) -> 'C) -> 'C\n\nfun isLeft[A, B](eob: EitherOrBoth[A, B]): Bool =\n  if eob is\n    Left(_) then true\n    Right(_) then false\n    Both(_, _) then false\n//│ fun isLeft: (eob: EitherOrBoth[anything, anything]) -> Bool\n\nfun isRight[A, B](eob: EitherOrBoth[A, B]): Bool =\n  if eob is\n    Left(_) then false\n    Right(_) then true\n    Both(_, _) then false\n//│ fun isRight: (eob: EitherOrBoth[anything, anything]) -> Bool\n\nfun isBoth[A, B](eob: EitherOrBoth[A, B]): Bool =\n  if eob is\n    Left(_) then false\n    Right(_) then false\n    Both(_, _) then true\n//│ fun isBoth: (eob: EitherOrBoth[anything, anything]) -> Bool\n\nfun (++) strcat(a: Str, b: Str): Str = concat(a)(b)\n//│ fun (++) strcat: (a: Str, b: Str) -> Str\n\nfun eobToString[A, B](eob: EitherOrBoth[A, B]): Str =\n  if eob is\n    Left(left) then \"Left(\" ++ toString(left) ++ \")\"\n    Right(right) then \"Right(\" ++ toString(right) ++ \")\"\n    Both(left, right) then \"Both(\" ++ toString(left) ++ \", \" ++ toString(right) ++ \")\"\n//│ fun eobToString: (eob: EitherOrBoth[anything, anything]) -> Str\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/JSON.mls",
    "content": ":NewDefs\n\n\ntype NStr = Str & {\n  length: Int,\n  at: Int -> NStr,\n  charAt: Int -> NStr,\n  charCodeAt: Int -> Int,\n  slice: (Int, Int) -> NStr,\n  startsWith: (Str, Int) -> Bool,\n  endsWith: Str -> Bool,\n  split: Str -> Array[NStr],\n  trim: () -> NStr,\n  trimStart: () -> NStr,\n  trimEnd: () -> NStr,\n  padStart: (Int, Str) -> NStr,\n  padEnd: (Int, Str) -> NStr,\n  repeat: Int -> NStr,\n  indexOf: Str -> Int,\n  lastIndexOf: Str -> Int,\n  includes: Str -> Bool,\n  localeCompare: Str -> Int\n}\ndeclare fun String: (anything -> NStr) & { fromCodePoint: Int -> NStr }\nfun (++) strcat(a, b) = String of concat(a)(b)\nfun (<*) strlt(a: NStr, b: NStr) = a.localeCompare(b) < 0\nfun (*>) strgt(a: NStr, b: NStr) = a.localeCompare(b) > 0\n//│ type NStr = Str & {\n//│   at: Int -> NStr,\n//│   charAt: Int -> NStr,\n//│   charCodeAt: Int -> Int,\n//│   endsWith: Str -> Bool,\n//│   includes: Str -> Bool,\n//│   indexOf: Str -> Int,\n//│   lastIndexOf: Str -> Int,\n//│   length: Int,\n//│   localeCompare: Str -> Int,\n//│   padEnd: (Int, Str) -> NStr,\n//│   padStart: (Int, Str) -> NStr,\n//│   repeat: Int -> NStr,\n//│   slice: (Int, Int) -> NStr,\n//│   split: Str -> Array[NStr],\n//│   startsWith: (Str, Int) -> Bool,\n//│   trim: () -> NStr,\n//│   trimEnd: () -> NStr,\n//│   trimStart: () -> NStr\n//│ }\n//│ fun (++) strcat: (Str, Str) -> NStr\n//│ fun (<*) strlt: (a: NStr, b: NStr) -> Bool\n//│ fun (*>) strgt: (a: NStr, b: NStr) -> Bool\n//│ fun String: anything -> NStr & {fromCodePoint: Int -> NStr}\n\ndeclare fun Math: { log10: Num -> Num, floor: Num -> Num, ceil: Num -> Num }\n//│ fun Math: {ceil: Num -> Num, floor: Num -> Num, log10: Num -> Num}\n\nfun (!==) notEqual(x, y) = not(x === y)\ndeclare fun parseInt: (Str, Int) -> Int\n//│ fun (!==) notEqual: forall 'a. (Eql['a], 'a) -> Bool\n//│ fun parseInt: (Str, Int) -> Int\n\n// `List` and its utilities:\nabstract class List[out T]: Cons[T] | Nil\nclass Cons[out T](head: T, tail: List[T]) extends List[T]\nmodule Nil extends List\nfun (::) cons(head: 'T, tail: List['T]): List['T] = Cons(head, tail)\nfun reverse(l: List['A]): List['A] =\n  let rec r(l', l) = if l is Cons(x, xs) then r(x :: l', xs) else l'\n  r(Nil, l)\nfun join(sep: Str, xs: List['B]) = if xs is\n  Cons(x, Nil) then toString(x)\n  Cons(x, xs) then toString(x) ++ sep ++ join(sep, xs)\n  Nil then \"\"\nfun showList(xs: List['C]) = \"[\" ++ join(\", \", xs) ++ \"]\"\nfun map(f: 'D -> 'E, xs: List['D]): List['E] = if xs is\n  Cons(x, xs) then f(x) :: map(f, xs)\n  Nil then Nil\nfun equalList(xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool): Bool = if xs is\n  Cons(x, xs') and ys is Cons(y, ys') then equal(x, y) and equalList(xs', ys', equal)\n  Nil and ys is Nil then true\n  else false\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n//│ fun (::) cons: forall 'T. (head: 'T, tail: List['T]) -> List['T]\n//│ fun reverse: forall 'T0. (l: List['T0]) -> List['T0]\n//│ fun join: (sep: Str, xs: List[anything]) -> (Str | NStr)\n//│ fun showList: (xs: List[anything]) -> NStr\n//│ fun map: forall 'D 'T1. (f: 'D -> 'T1, xs: List['D]) -> List['T1]\n//│ fun equalList: forall 'A. (xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool) -> Bool\n\n// `Option` and its utilities:\nabstract class Option[out A]: Some[A] | None\nclass Some[out A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nfun (->) makePair(a, b) = [a, b]\n//│ fun (->) makePair: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n\nabstract class ListMap[K, out V]: (ConsMap[K, V] | NilMap)\nclass ConsMap[K, out V](head: [K, V], tail: ListMap[K, V]) extends ListMap[K, V]\nmodule NilMap extends ListMap\n  \nfun containsKey(map: ListMap['K, 'V], key: 'K): Bool = if map is\n  ConsMap([k, _], _) and k === key then true\n  ConsMap(_, tail) then containsKey(tail, key)\n  NilMap then false\n  \nfun (:+) insert(map, entry) = if map is\n  ConsMap(entry', map) and\n    entry'.0 === entry.0 then ConsMap(entry, map)\n    else ConsMap(entry', insert(map, entry))\n  NilMap then ConsMap(entry, NilMap)\n  \nfun showMap(map) =\n  let showEntry([k, v]) = toString(k) ++ \" -> \" ++ toString(v)\n  let rec aux(map) = if map is\n    ConsMap(last, NilMap) then showEntry(last)\n    ConsMap(head, tail) then showEntry(head) ++ \", \" ++ aux(tail)\n    NilMap then \"\"\n  if map is NilMap then String(\"{}\") else \"{ \" ++ aux(map) ++ \" }\"\n//│ abstract class ListMap[K, V]: ConsMap[K, V] | NilMap\n//│ class ConsMap[K, V](head: [K, V], tail: ListMap[K, V]) extends ListMap\n//│ module NilMap extends ListMap\n//│ fun containsKey: forall 'K 'a. (map: ListMap['K, anything], key: 'a) -> Bool\n//│ fun (:+) insert: forall 'K0 'b 'V. (ConsMap['K0, 'V] | NilMap, ['K0 & 'b, 'V]) -> ConsMap['K0, 'V]\n//│ fun showMap: forall 'K1. (ConsMap['K1, anything] | NilMap) -> NStr\n//│ where\n//│   'K0 <: Eql['b]\n//│   'K <: Eql['a]\n\nshowMap of NilMap\nshowMap of NilMap :+ [\"b\", 2]\nshowMap of NilMap :+ [1, \"a\"] :+ [2, \"b\"]\nshowMap of NilMap :+ [1, \"a\"] :+ [2, \"b\"] :+ [1, \"c\"]\n//│ NStr\n//│ res\n//│     = '{}'\n//│ res\n//│     = '{ b -> 2 }'\n//│ res\n//│     = '{ 1 -> a, 2 -> b }'\n//│ res\n//│     = '{ 1 -> c, 2 -> b }'\n\nabstract class JsonValue: JsonNumber | JsonString | JsonArray | JsonObject | JsonBoolean | JsonNull\nclass JsonNumber(value: Num) extends JsonValue\nclass JsonString(value: Str) extends JsonValue\nclass JsonArray(value: List[JsonValue]) extends JsonValue\nclass JsonObject(value: ListMap[Str, JsonValue]) extends JsonValue\nclass JsonBoolean(value: Bool) extends JsonValue\nmodule JsonNull extends JsonValue\n//│ abstract class JsonValue: JsonArray | JsonBoolean | JsonNull | JsonNumber | JsonObject | JsonString\n//│ class JsonNumber(value: Num) extends JsonValue\n//│ class JsonString(value: Str) extends JsonValue\n//│ class JsonArray(value: List[JsonValue]) extends JsonValue\n//│ class JsonObject(value: ListMap[Str, JsonValue]) extends JsonValue\n//│ class JsonBoolean(value: Bool) extends JsonValue\n//│ module JsonNull extends JsonValue\n\nclass ParserState(val text: NStr, val at: Int) {\n  fun drained: Bool = at === text.length\n  fun peek: Option[NStr] = if drained then None else Some(text.charAt(at))\n  fun peekCode: Option[Int] = if drained then None else Some(text.charCodeAt(at))\n  fun next: ParserState = if drained then this else ParserState(text, at + 1)\n  fun nextDigit: Option[[Num, ParserState]] = if peekCode is\n    Some(ch) and 48 <= ch and ch <= 57 then Some([ch - 48, next])\n    else None\n  fun match(prefix: Str): Option[ParserState] =\n    let prefix' = String(prefix)\n    if\n      prefix'.length > text.length - at then None\n      text.startsWith(prefix', at) then Some(ParserState(text, at + prefix'.length))\n      else None\n  fun rest: NStr = text.slice(at, text.length)\n}\nfun showParserState(state) = \"ParserState(_, \" ++ toString(state.at) ++ \")\"\nfun success: forall 't: ('t, ParserState) -> ParseResult['t]\nfun success = (value, state) => Success(value, state)\nfun failure: forall 't: Str -> ParseResult[nothing]\nfun failure = error => Failure(error)\n  \nabstract class ParseResult[out T]: (Success[T] | Failure) {\n  virtual fun flatMap(f: (T, ParserState) -> ParseResult['U]): ParseResult['U]\n  virtual fun map(f: T -> 'U): ParseResult['U]\n}\nclass Success[out T](value: T, state: ParserState) extends ParseResult[T] {\n  fun flatMap(f) = f(value, state)\n  fun map(f) = success(f(value), state)\n}\nclass Failure(error: Str) extends ParseResult[nothing] {\n  fun flatMap(_) = failure(error)\n  fun map(_) = failure(error)\n}\nfun showParseResult(result) = if result is\n  Success(value, state) then \"Success after \" ++ toString(state.at) ++ \": \" ++ toString(value)\n  Failure(error) then \"Failure: \" ++ toString(error)\n//│ class ParserState(text: NStr, at: Int) {\n//│   fun drained: Bool\n//│   fun match: (prefix: Str) -> Option[ParserState]\n//│   fun next: ParserState\n//│   fun nextDigit: Option[[Num, ParserState]]\n//│   fun peek: Option[NStr]\n//│   fun peekCode: Option[Int]\n//│   fun rest: NStr\n//│ }\n//│ fun showParserState: {at: anything} -> NStr\n//│ fun success: forall 'T. ('T, ParserState) -> Success['T]\n//│ fun failure: Str -> Failure\n//│ abstract class ParseResult[T]: Failure | Success[T] {\n//│   fun flatMap: forall 'U. (f: (T, ParserState) -> ParseResult['U]) -> ParseResult['U]\n//│   fun map: forall 'U0. (f: T -> 'U0) -> ParseResult['U0]\n//│ }\n//│ class Success[T](value: T, state: ParserState) extends ParseResult {\n//│   fun flatMap: forall 'a. ((T, ParserState) -> 'a) -> 'a\n//│   fun map: forall 't. (T -> 't) -> ParseResult['t]\n//│ }\n//│ class Failure(error: Str) extends ParseResult {\n//│   fun flatMap: anything -> ParseResult[nothing]\n//│   fun map: anything -> ParseResult[nothing]\n//│ }\n//│ fun showParseResult: (Failure | Success[anything]) -> NStr\n//│ fun success: forall 't0. ('t0, ParserState) -> ParseResult['t0]\n//│ fun failure: Str -> ParseResult[nothing]\n\nfun isWhiteSpace(ch: NStr): Bool =\n  (ch === \" \") || (ch === \"\\n\") || (ch === \"\\r\") || (ch === \"\\t\")\nfun skipWhiteSpace(state: ParserState): ParserState = if state.peek is\n  Some(ch) and isWhiteSpace(ch) then skipWhiteSpace(state.next)\n  else state\n//│ fun isWhiteSpace: (ch: NStr) -> Bool\n//│ fun skipWhiteSpace: (state: ParserState) -> ParserState\n\n(skipWhiteSpace of ParserState(String(\" \\n\\r\\t\"), 0)).at\n//│ Int\n//│ res\n//│     = 4\n\nfun isDigit(ch) = sge(ch, \"0\") && sle(ch, \"9\")\n//│ fun isDigit: Str -> Bool\n\nfun parseNumber(state: ParserState): ParseResult[Num] =\n  let toFraction(n) = n / (10 ** Math.ceil of Math.log10 of n)\n  let parseNegative(state): ParseResult[Bool] = if state.peek is\n    Some(\"-\") then Success(true, state.next)\n    else Success(false, state)\n  \n  // Parse one or more decimal digits\n  // --------------------------------\n  let parseDigits(state): ParseResult[Num] =\n    // Parse remaining digits\n    let rec aux(acc, state) = if state.nextDigit is\n      Some([digit, state']) then aux((acc *. 10) +. digit, state')\n      None then [acc, state]\n    // Parse the first digit\n    if state.nextDigit is\n      Some([digit, state']) and aux(digit, state') is\n        [num, state''] then Success(num, state'')\n      None then Failure(\"expected one or more decimal digits\")\n  \n  // Parse the integral part of the number\n  // -------------------------------------\n  let parseIntegral(state): ParseResult[Num] = if state.nextDigit is\n    Some([0, state']) then Success(0, state')\n    else parseDigits(state)\n  \n  // Parse the fractional part of the number\n  // ---------------------------------------\n  let parseFraction(state): ParseResult[Num] = if state.peek is\n    Some(\".\") then parseDigits(state.next).map of toFraction\n    else Success(0, state)\n  let parseExponent(state): ParseResult[Num] =\n    let parseSign(state): ParseResult[Bool] = if state.peek is\n      Some(\"-\") then Success(true, state.next)\n      Some(\"+\") then Success(false, state.next)\n      else Success(false, state)\n    if state.peek is Some(e) and (e === \"e\") || (e === \"E\")\n    then parseSign(state.next).flatMap of (sign, state) =>\n      parseDigits(state).map of exponent =>\n      if sign then 10 ** (0 -. exponent) else 10 ** exponent\n    else Success(1, state)\n  \n  parseNegative(state).flatMap of (negative, state) =>\n  parseIntegral(state).flatMap of (integral, state) =>\n  parseFraction(state).flatMap of (fraction, state) =>\n  parseExponent(state).flatMap of (exponent, state) =>\n  let value = (integral +. fraction) *. exponent\n  Success of (if negative then (0 -. value) else value), state\n//│ fun parseNumber: (state: ParserState) -> ParseResult[Num]\n\nshowParseResult of parseNumber of ParserState of String(\"0\"), 0\nshowParseResult of parseNumber of ParserState of String(\"0234\"), 0\nshowParseResult of parseNumber of ParserState of String(\"123\"), 0\nshowParseResult of parseNumber of ParserState of String(\"12.34\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1e10\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1E5\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1E-1\"), 0\nshowParseResult of parseNumber of ParserState of String(\"1E+1\"), 0\n//│ NStr\n//│ res\n//│     = 'Success after 1: 0'\n//│ res\n//│     = 'Success after 1: 0'\n//│ res\n//│     = 'Success after 3: 123'\n//│ res\n//│     = 'Success after 5: 12.34'\n//│ res\n//│     = 'Success after 4: 10000000000'\n//│ res\n//│     = 'Success after 3: 100000'\n//│ res\n//│     = 'Success after 4: 0.1'\n//│ res\n//│     = 'Success after 4: 10'\n\nfun parseString(state: ParserState): ParseResult[Str] =\n  \n  let rec parseCodePoint(n, acc, state) = if\n    n === 0 then Success(acc, state)\n    state.peekCode is Some(code) and\n      48 <= code and code <= 57 then parseCodePoint(n - 1, acc * 16 + code - 48, state.next)\n      65 <= code and code <= 70 then parseCodePoint(n - 1, acc * 16 + code - 55, state.next)\n      97 <= code and code <= 102 then parseCodePoint(n - 1, acc * 16 + code - 87, state.next)\n      else Failure(\"expect \" ++ toString(n) ++ \" hex digit(s) instead of '\" ++ String.fromCodePoint(code) ++ \"'\")\n    else Failure(\"expect \" ++ toString(n) ++ \" hex digit(s) instead of end of input\")\n  \n  let rec parseContent(acc, state) = if state.peek is\n    Some(\"\\\"\") then Success(acc, state.next)\n    Some(\"\\\\\") and\n      let state' = state.next\n      state'.peek is\n        Some(\"\\\"\") then parseContent(acc ++ \"\\\"\", state'.next)\n        Some(\"\\\\\") then parseContent(acc ++ \"\\\\\", state'.next)\n        Some(\"/\") then parseContent(acc ++ \"/\", state'.next)\n        Some(\"b\") then parseContent(acc ++ \"\\b\", state'.next)\n        Some(\"f\") then parseContent(acc ++ \"\\f\", state'.next)\n        Some(\"n\") then parseContent(acc ++ \"\\n\", state'.next)\n        Some(\"r\") then parseContent(acc ++ \"\\r\", state'.next)\n        Some(\"t\") then parseContent(acc ++ \"\\t\", state'.next)\n        Some(\"u\") then\n          parseCodePoint(4, 0, state'.next).flatMap of (codePoint, state) =>\n          if codePoint < 0xD800 || 0xDFFF < codePoint\n          then parseContent(acc ++ String.fromCodePoint(codePoint), state)\n          else Failure(\"invalid code point\")\n        else Failure(\"invalid escape sequence\")\n    Some(ch) then parseContent(acc ++ ch, state.next)\n    None then Failure(\"expected '\\\"' instead of end of input\")\n  \n  if state.peek is\n    Some(\"\\\"\") then parseContent(\"\", state.next)\n    Some(ch) then Failure(\"expected '\\\"' instead of '\" ++ ch ++ \"'\")\n    else Failure(\"expected '\\\"' instead of end of input\")\n//│ fun parseString: (state: ParserState) -> ParseResult[Str]\n\nshowParseResult of parseString of ParserState of String(\"\\\"\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"abc\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\\\\"\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\\\\\\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\/\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\b\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\u\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\u0\\\"\"), 0\nshowParseResult of parseString of ParserState of String(\"\\\"\\\\u004c\\\"\"), 0\n//│ NStr\n//│ res\n//│     = 'Success after 2: '\n//│ res\n//│     = 'Success after 5: abc'\n//│ res\n//│     = 'Success after 4: \"'\n//│ res\n//│     = 'Success after 4: \\\\'\n//│ res\n//│     = 'Success after 4: /'\n//│ res\n//│     = 'Success after 4: \\b'\n//│ res\n//│     = `Failure: expected '\"' instead of end of input`\n//│ res\n//│     = `Failure: expect 4 hex digit(s) instead of '\"'`\n//│ res\n//│     = `Failure: expect 3 hex digit(s) instead of '\"'`\n//│ res\n//│     = 'Success after 8: L'\n\nfun parseTrue(state: ParserState): ParseResult[Bool] =\n  if state.match(\"true\") is\n    Some(state) then Success(true, state)\n    None then Failure(\"expected 'true'\")\n  \nfun parseFalse(state: ParserState): ParseResult[Bool] =\n  if state.match(\"false\") is\n    Some(state) then Success(false, state)\n    None then Failure(\"expected 'false'\")\n  \nfun parseNull(state: ParserState): ParseResult[()] =\n  if state.match(\"null\") is\n    Some(state) then Success((), state)\n    None then Failure(\"expected 'null'\")\n//│ fun parseTrue: (state: ParserState) -> ParseResult[Bool]\n//│ fun parseFalse: (state: ParserState) -> ParseResult[Bool]\n//│ fun parseNull: (state: ParserState) -> ParseResult[()]\n\nfun parseObjectEntry(state: ParserState): ParseResult[[Str, JsonValue]] =\n  let state' = skipWhiteSpace(state)\n  parseString(state').flatMap of (key, state) =>\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(\":\") then\n      parseValue(state'.next).flatMap of (value, state') =>\n      Success([key, value], state')\n    Some(ch) then Failure(\"expected ':' instead of '\" ++ ch ++ \"'\")\n    None then Failure(\"expected ':' instead of end of input\")\n  else Failure(\"expected ':' instead of end of input\")\n  \nfun parseObject(state: ParserState): ParseResult[ListMap[Str, JsonValue]] =\n  let rec parseObjectTail(acc: ListMap[Str, JsonValue], state: ParserState) =\n    let state' = skipWhiteSpace(state)\n    if state'.peek is\n      Some(\",\") then\n        parseObjectEntry(state'.next).flatMap of (entry, state') =>\n        if containsKey(acc, entry.0) then\n          Failure(\"duplicate key '\" ++ toString(entry.0) ++ \"'\")\n        else\n          parseObjectTail(ConsMap(entry, acc), state')\n      Some(\"}\") then Success(acc, state'.next)\n      Some(ch) then Failure(\"expected ',' or ']' instead of \" ++ ch)\n      None then Failure(\"expected ',' or ']' instead of end of input\")\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(\"}\") then Success(NilMap, state'.next)\n    None then Failure(\"expected ',' or ']' instead of end of input\")\n    else\n      parseObjectEntry(state').flatMap of (head, state) =>\n      parseObjectTail(ConsMap(head, NilMap), state)\n  \nfun parseArray(state: ParserState): ParseResult[List[JsonValue]] =\n  let rec parseArrayTail(acc, state) =\n    let state' = skipWhiteSpace(state)\n    if state'.peek is\n      Some(\",\") then\n        parseValue(state'.next).flatMap of (value, state') =>\n        parseArrayTail(value :: acc, state')\n      Some(\"]\") then Success(reverse(acc), state'.next)\n      Some(ch) then Failure(\"expected ',' or ']' instead of \" ++ ch)\n      None then Failure(\"expected ',' or ']' instead of end of input\")\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(\"]\") then Success(Nil, state'.next)\n    None then Failure(\"expected ',' or ']' instead of end of input\")\n    else\n      parseValue(state').flatMap of (head, state) =>\n      parseArrayTail(head :: Nil, state)\n  \nfun parseValue(state: ParserState): ParseResult[JsonValue] =\n  let state' = skipWhiteSpace(state)\n  if state'.peek is\n    Some(ch) and\n      ch === \"\\\"\" then parseString(state').map of JsonString\n      (ch === \"-\") || isDigit(ch) then parseNumber(state').map of JsonNumber\n      ch === \"[\" then parseArray(state'.next).map of JsonArray\n      ch === \"{\" then parseObject(state'.next).map of JsonObject\n      ch === \"t\" then parseTrue(state').map of JsonBoolean\n      ch === \"f\" then parseFalse(state').map of JsonBoolean\n      ch === \"n\" then parseNull(state').map of _ => JsonNull\n      else Failure(\"cannot recognize \" ++ ch ++ \" as the beginning of a JSON value\")\n    None then Failure(\"expected a JSON value instead of end of input\")\n//│ fun parseObjectEntry: (state: ParserState) -> ParseResult[[Str, JsonValue]]\n//│ fun parseObject: (state: ParserState) -> ParseResult[ListMap[Str, JsonValue]]\n//│ fun parseArray: (state: ParserState) -> ParseResult[List[JsonValue]]\n//│ fun parseValue: (state: ParserState) -> ParseResult[JsonValue]\n\nfun parse(source: Str): ParseResult[JsonValue] =\n  (parseValue of ParserState of String(source), 0).flatMap of (value, finalState) =>\n    let shouldBeEnd = skipWhiteSpace of finalState\n    if shouldBeEnd.drained then\n      Success(value, shouldBeEnd)\n    else\n      Failure(\"expected end of input instead of: \" ++ shouldBeEnd.rest)\n//│ fun parse: (source: Str) -> ParseResult[JsonValue]\n\nfun stringify(value: JsonValue): Str =\n  let stringifyObject(map) =\n    let showEntry([k, v]) = \"\\\"\" ++ toString(k) ++ \"\\\": \" ++ stringify(v)\n    let rec aux(map) = if map is\n      ConsMap(last, NilMap) then showEntry(last)\n      ConsMap(head, tail) then showEntry(head) ++ \", \" ++ aux(tail)\n      NilMap then \"\"\n    if map is NilMap then String(\"{}\") else \"{ \" ++ aux(map) ++ \" }\"\n  \n  if value is\n    JsonNumber(n) then toString(n)\n    JsonString(s) then \"\\\"\" ++ s ++ \"\\\"\"\n    JsonArray(xs) then \"[\" ++ join(\", \", map(stringify, xs)) ++ \"]\"\n    JsonObject(m) then stringifyObject(m)\n    JsonBoolean(b) then if b then \"true\" else \"false\"\n    JsonNull then \"null\"\n//│ fun stringify: (value: JsonValue) -> Str\n\nfun showResult(result) = if result is\n  Success(value, state) then \"Success after \" ++ toString(state.at) ++ \": \" ++ stringify(value)\n  Failure(error) then \"Failure: \" ++ toString(error)\n//│ fun showResult: (Failure | Success[JsonValue]) -> NStr\n\n// Simple tests.\nshowResult of parse of \"null\"\nshowResult of parse of \"true\"\nshowResult of parse of \"false\"\nshowResult of parse of \"123\"\nshowResult of parse of \"\\\"abc\\\"\"\nshowResult of parse of \"[1, 2, 3]\"\nshowResult of parse of \"{\\\"a\\\": 1, \\\"b\\\": 2}\"\nshowResult of parse of \"nul\"\nshowResult of parse of \"[1, 3, 5\"\nshowResult of parse of \"[1, 3, 5]\"\n//│ NStr\n//│ res\n//│     = 'Success after 4: null'\n//│ res\n//│     = 'Success after 4: true'\n//│ res\n//│     = 'Success after 5: false'\n//│ res\n//│     = 'Success after 3: 123'\n//│ res\n//│     = 'Success after 5: \"abc\"'\n//│ res\n//│     = 'Success after 9: [1, 2, 3]'\n//│ res\n//│     = 'Success after 16: { \"b\": 2, \"a\": 1 }'\n//│ res\n//│     = \"Failure: expected 'null'\"\n//│ res\n//│     = \"Failure: expected ',' or ']' instead of end of input\"\n//│ res\n//│     = 'Success after 9: [1, 3, 5]'\n\n// Complicated tests.\nshowResult of parse of \"{ \\\"origin\\\": { \\\"x\\\": 0, \\\"y\\\": 0 } }\"\nshowResult of parse of \"[   { \\\"origin\\\": { \\\"x\\\": 0, \\\"y\\\": 0 } , \\\"size\\\": { \\\"width\\\": 100, \\\"height\\\": 100 } }   ]\"\nshowResult of parse of \"{\\\"id\\\":\\\"658f34f88882211aa8679240\\\",\\\"children\\\":[{\\\"name\\\":\\\"Jo Rosales\\\",\\\"age\\\":8},{\\\"name\\\":\\\"Shawn Burke\\\",\\\"age\\\":7},{\\\"name\\\":\\\"Gomez Guthrie\\\",\\\"age\\\":10},{\\\"name\\\":\\\"Tandy Christensen\\\",\\\"age\\\":9},{\\\"name\\\":\\\"Jody Langley\\\",\\\"age\\\":3}],\\\"currentJob\\\":{\\\"title\\\":\\\"Developer\\\",\\\"salary\\\":\\\"mask;\\\"},\\\"jobs\\\":[{\\\"title\\\":\\\"medic\\\",\\\"salary\\\":\\\"R$ 6.400,90\\\"},{\\\"title\\\":\\\"teacher\\\",\\\"salary\\\":\\\"R$ 7.960,31\\\"}],\\\"maxRunDistance\\\":14.7,\\\"cpf\\\":\\\"713.763.356-03\\\",\\\"cnpj\\\":\\\"33.385.435/0001-50\\\",\\\"pretendSalary\\\":\\\"R$ 9.247,29\\\",\\\"age\\\":63,\\\"gender\\\":\\\"male\\\",\\\"firstName\\\":\\\"Parker\\\",\\\"lastName\\\":\\\"Case\\\",\\\"phone\\\":\\\"+55 (83) 95023-7077\\\",\\\"address\\\":\\\"14 Orient Avenue - Harmon, Northern Mariana Islands, Myanmar.\\\",\\\"hairColor\\\":\\\"yellow\\\"}\"\n//│ NStr\n//│ res\n//│     = 'Success after 32: { \"origin\": { \"y\": 0, \"x\": 0 } }'\n//│ res\n//│     = 'Success after 82: [{ \"size\": { \"height\": 100, \"width\": 100 }, \"origin\": { \"y\": 0, \"x\": 0 } }]'\n//│ res\n//│     = 'Success after 647: { \"hairColor\": \"yellow\", \"address\": \"14 Orient Avenue - Harmon, Northern Mariana Islands, Myanmar.\", \"phone\": \"+55 (83) 95023-7077\", \"lastName\": \"Case\", \"firstName\": \"Parker\", \"gender\": \"male\", \"age\": 63, \"pretendSalary\": \"R$ 9.247,29\", \"cnpj\": \"33.385.435/0001-50\", \"cpf\": \"713.763.356-03\", \"maxRunDistance\": 14.7, \"jobs\": [{ \"salary\": \"R$ 6.400,90\", \"title\": \"medic\" }, { \"salary\": \"R$ 7.960,31\", \"title\": \"teacher\" }], \"currentJob\": { \"salary\": \"mask;\", \"title\": \"Developer\" }, \"children\": [{ \"age\": 8, \"name\": \"Jo Rosales\" }, { \"age\": 7, \"name\": \"Shawn Burke\" }, { \"age\": 10, \"name\": \"Gomez Guthrie\" }, { \"age\": 9, \"name\": \"Tandy Christensen\" }, { \"age\": 3, \"name\": \"Jody Langley\" }], \"id\": \"658f34f88882211aa8679240\" }'\n\n// Nice.\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/LeftistTree.mls",
    "content": ":NewDefs\n\nfun (|>) pipe(x, f) = f(x)\nfun (~~>) toBe(x, y) = if x === y then () else error\nfun (<?) min(x, y) = if x < y then x else y\nfun (>?) max(x, y) = if x > y then x else y\nfun abs(x) = if x < 0 then -x else x\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (~~>) toBe: forall 'c. (Eql['c], 'c) -> ()\n//│ fun (<?) min: forall 'd. (Num & 'd, Num & 'd) -> 'd\n//│ fun (>?) max: forall 'e. (Num & 'e, Num & 'e) -> 'e\n//│ fun abs: Int -> Int\n\n\nabstract class Option[out T]: (Some[T] | None)\nclass Some[out T](val value: T) extends Option[T]\nmodule None extends Option[nothing]\n//│ abstract class Option[T]: None | Some[T]\n//│ class Some[T](value: T) extends Option\n//│ module None extends Option\n\nfun (??) getOrElse(o, v) = if o is\n  Some(v') then v'\n  None then v\n//│ fun (??) getOrElse: forall 'a. (None | Some['a], 'a) -> 'a\n\nfun (++) strcat(s1, s2) = concat(s1)(s2)\n//│ fun (++) strcat: (Str, Str) -> Str\n\nlet anyToString = toString\n//│ let anyToString: anything -> Str\n//│ anyToString\n//│             = [Function: toString]\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List[nothing]\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\nabstract class Tree[out A]: (Empty | Node[A])\nclass Node[out A](value: A, left: Tree[A], right: Tree[A], rank: Int) extends Tree[A]\nmodule Empty extends Tree[nothing]\n//│ abstract class Tree[A]: Empty | Node[A]\n//│ class Node[A](value: A, left: Tree[A], right: Tree[A], rank: Int) extends Tree\n//│ module Empty extends Tree\n\nfun show(t: Tree[anything]): Str = if t is\n  Node(v, l, r, _) then\n    \"(\" ++ show(l) ++ \" \" ++ toString(v) ++ \" \" ++ show(r) ++ \")\"\n  Empty then \"•\"\n//│ fun show: (t: Tree[anything]) -> Str\n\nfun singleton(x) = Node(x, Empty, Empty, 1)\nfun rank(t) = if t is\n  Empty then 0\n  Node(_, _, _, r) then r\n//│ fun singleton: forall 'A. 'A -> Node['A]\n//│ fun rank: (Empty | Node[anything]) -> Int\n\n// This can be improved. This can be better.\nfun merge(t1: Tree[Num], t2: Tree[Num]): Tree[Num] =\n  if\n    t1 is Node(v1, l1, r1, _) and t2 is Node(v2, _, _, _) and\n      v1 > v2 then merge(t2, t1)\n      _ and merge(r1, t2) is merged and\n        rank(l1) is rank_left and rank(r1) is rank_right and\n          rank_left >= rank_right then Node(v1, l1, merged, rank_right + 1)\n          else Node(v1, merged, l1, rank_left + 1)\n    t1 is Empty and t2 is Node then t2\n    t1 is Node and t2 is Empty then t1\n    t1 is Empty and t2 is Empty then Empty\n//│ fun merge: (t1: Tree[Num], t2: Tree[Num]) -> Tree[Num]\n\nfun insert(t, v) = merge(t, singleton(v))\n//│ fun insert: (Tree[Num], Num) -> Tree[Num]\n\nfun getMin(t) =\n  if t is\n    Empty then None\n    Node(x, _, _, _) then Some(x)\n//│ fun getMin: forall 'T. (Empty | Node['T]) -> (None | Some['T])\n\nfun deleteMin(t) =\n  if t is\n    Empty then Empty\n    Node(_, l, r, _) then merge(l, r)\n//│ fun deleteMin: (Empty | Node[Num]) -> (Empty | Tree[Num])\n\nfun fromList(t, xs) =\n  if xs is\n    Cons(x, xs') then fromList(insert(t, x), xs')\n    Nil then t\n//│ fun fromList: (Tree[Num], Cons[Num] | Nil) -> Tree[Num]\n\nlet tree1 = fromList(Empty, 3 :: 4 :: 1 :: 2 :: Nil)\ntree1 |> show\n//│ let tree1: Empty | Tree[Num]\n//│ Str\n//│ tree1\n//│       = Node {}\n//│ res\n//│     = '((• 2 (• 3 (• 4 •))) 1 •)'\n\n// Remove the smallest element. It should be 1.\ngetMin(tree1) ?? \"nothing\"\nlet tree1' = deleteMin(tree1)\ntree1' |> show\n//│ let tree1': Empty | Tree[Num]\n//│ Str\n//│ res\n//│     = 1\n//│ tree1'\n//│        = Node {}\n//│ res\n//│     = '(• 2 (• 3 (• 4 •)))'\n\n// Remove one more element. It should be 2.\ngetMin(tree1') ?? \"nothing\"\nlet tree1'' = deleteMin(tree1')\ntree1'' |> show\n//│ let tree1'': Empty | Tree[Num]\n//│ Str\n//│ res\n//│     = 2\n//│ tree1''\n//│         = Node {}\n//│ res\n//│     = '(• 3 (• 4 •))'\n\n// Remove one more element. It should be 3.\ngetMin(tree1'') ?? \"nothing\"\nlet tree1''' = deleteMin(tree1'')\ntree1''' |> show\n//│ let tree1''': Empty | Tree[Num]\n//│ Str\n//│ res\n//│     = 3\n//│ tree1'''\n//│          = Node {}\n//│ res\n//│     = '(• 4 •)'\n\n// Remove the last element. It should be 4.\ngetMin(tree1''') ?? \"nothing\"\nlet tree1'''' = deleteMin(tree1''')\ntree1'''' |> show\n//│ let tree1'''': Empty | Tree[Num]\n//│ Str\n//│ res\n//│     = 4\n//│ tree1''''\n//│           = Empty { class: [class Empty extends Tree] }\n//│ res\n//│     = '•'\n\n// ===========================================================================\n\nfun drain(t) =\n  if getMin(t) is\n    None then Nil\n    Some(x) then x :: drain(deleteMin(t))\n//│ fun drain: (Empty | Node[Num]) -> (Cons[Num] | Nil)\n\nfun sorted(xs) = fromList(Empty, xs) |> drain\n//│ fun sorted: (Cons[Num] | Nil) -> (Cons[Num] | Nil)\n\nfun showList(xs) =\n  if xs is\n    Cons(x, Nil) then toString(x)\n    Cons(x, xs') then toString(x) ++ \", \" ++ showList(xs')\n    Nil then \"\"\n//│ fun showList: (Cons[anything] | Nil) -> Str\n\nsorted(3 :: 4 :: 1 :: 2 :: Nil) |> showList\nsorted(42 :: 58 :: 19 :: 37 :: 44 :: 99 :: 68 :: 60 :: 77 :: 61 :: Nil) |> showList\n//│ Str\n//│ res\n//│     = '1, 2, 3, 4'\n//│ res\n//│     = '19, 37, 42, 44, 58, 60, 61, 68, 77, 99'\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/LispInterpreter.mls",
    "content": ":NewDefs\n\n// Summon the underlying JavaScript `Object.is` function so that we can compare\n// any objects. For example, functions do not conforms to `Eql` so we cannot\n// compare them with `===` directly. But, we can use `Object.is`.\ndeclare fun Object: nothing\nlet (=:=) objectEqual: (anything, anything) -> Bool = Object.is\nfun (=/=) objectNotEqual(x, y) = not(x =:= y)\n//│ let (=:=) objectEqual: (anything, anything) -> Bool\n//│ fun (=/=) objectNotEqual: (anything, anything) -> Bool\n//│ fun Object: nothing\n//│ objectEqual\n//│             = [Function: is]\n\ntype NStr = Str & {\n  length: Int,\n  at: Int -> NStr,\n  charAt: Int -> NStr,\n  charCodeAt: Int -> Int,\n  slice: (Int, Int) -> NStr,\n  startsWith: Str -> Bool,\n  endsWith: Str -> Bool,\n  split: Str -> Array[NStr],\n  trim: () -> NStr,\n  trimStart: () -> NStr,\n  trimEnd: () -> NStr,\n  padStart: (Int, Str) -> NStr,\n  padEnd: (Int, Str) -> NStr,\n  repeat: Int -> NStr,\n  indexOf: Str -> Int,\n  lastIndexOf: Str -> Int,\n  includes: Str -> Bool,\n}\ndeclare fun String: anything -> NStr\nfun (++) strcat(a, b) = String of concat(a)(b)\n//│ type NStr = Str & {\n//│   at: Int -> NStr,\n//│   charAt: Int -> NStr,\n//│   charCodeAt: Int -> Int,\n//│   endsWith: Str -> Bool,\n//│   includes: Str -> Bool,\n//│   indexOf: Str -> Int,\n//│   lastIndexOf: Str -> Int,\n//│   length: Int,\n//│   padEnd: (Int, Str) -> NStr,\n//│   padStart: (Int, Str) -> NStr,\n//│   repeat: Int -> NStr,\n//│   slice: (Int, Int) -> NStr,\n//│   split: Str -> Array[NStr],\n//│   startsWith: Str -> Bool,\n//│   trim: () -> NStr,\n//│   trimEnd: () -> NStr,\n//│   trimStart: () -> NStr\n//│ }\n//│ fun (++) strcat: (Str, Str) -> NStr\n//│ fun String: anything -> NStr\n\nfun (!==) notEqual(x, y) = not(x === y)\ndeclare fun parseInt: (Str, Int) -> Int\n//│ fun (!==) notEqual: forall 'a. (Eql['a], 'a) -> Bool\n//│ fun parseInt: (Str, Int) -> Int\n\n// `List` and its utilities:\nabstract class List[out T]: Cons[T] | Nil\nclass Cons[out T](head: T, tail: List[T]) extends List[T]\nmodule Nil extends List\nfun (::) cons(head: 'T, tail: List['T]): List['T] = Cons(head, tail)\nfun reverse(l: List['A]): List['A] =\n  let rec r(l', l) = if l is Cons(x, xs) then r(x :: l', xs) else l'\n  r(Nil, l)\nfun join(sep: Str, xs: List['B]) = if xs is\n  Cons(x, Nil) then toString(x)\n  Cons(x, xs) then toString(x) ++ sep ++ join(sep, xs)\n  Nil then \"\"\nfun showList(xs: List['C]) = \"[\" ++ join(\", \", xs) ++ \"]\"\nfun map(f: 'D -> 'E, xs: List['D]): List['E] = if xs is\n  Cons(x, xs) then f(x) :: map(f, xs)\n  Nil then Nil\nfun equalList(xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool): Bool = if xs is\n  Cons(x, xs') and ys is Cons(y, ys') then equal(x, y) and equalList(xs', ys', equal)\n  Nil and ys is Nil then true\n  else false\n// `Option` and its utilities:\nabstract class Option[out A]: Some[A] | None\nclass Some[out A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n//│ fun (::) cons: forall 'T. (head: 'T, tail: List['T]) -> List['T]\n//│ fun reverse: forall 'T0. (l: List['T0]) -> List['T0]\n//│ fun join: (sep: Str, xs: List[anything]) -> (Str | NStr)\n//│ fun showList: (xs: List[anything]) -> NStr\n//│ fun map: forall 'D 'T1. (f: 'D -> 'T1, xs: List['D]) -> List['T1]\n//│ fun equalList: forall 'A. (xs: List['A], ys: List['A], equal: ('A, 'A) -> Bool) -> Bool\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\n//     _    ____ _____\n//    / \\  / ___|_   _|\n//   / _ \\ \\___ \\ | |\n//  / ___ \\ ___) || |\n// /_/   \\_\\____/ |_|\n//\n\nabstract class Expr: Lambda | BuiltIn | Instance | Thunk | StrLit | IntLit | ExprList\nclass Lambda(f: List[Data] -> Data) extends Expr\nclass BuiltIn(e: List[Data] -> Data) extends Expr\nclass Instance(n: Str, m: List[[Str, Expr]]) extends Expr\nclass Thunk(e: () -> Data) extends Expr\nclass StrLit(s: Str) extends Expr\nclass IntLit(n: Int) extends Expr\nclass ExprList(l: List[Expr]) extends Expr\nfun (=@=) equalExpr(x: Expr, y: Expr): Bool = if x is\n  Lambda(f) and y is Lambda(g) then f =:= g\n  BuiltIn(f) and y is BuiltIn(g) then f =:= g\n  Instance(n, m) and y is Instance(n', m') then\n    let equalPair = ([k, v], [k', v']) => k =:= k' and equalExpr(v, v')\n    n === n' and equalList(m, m', equalPair)\n  Thunk(e) and y is Thunk(e') then e =:= e'\n  StrLit(s) and y is StrLit(s') then s === s'\n  IntLit(n) and y is IntLit(n') then n === n'\n  ExprList(l) and y is ExprList(l') then equalList(l, l', equalExpr)\n  else false\nfun showExpr(e: Expr): Str = if e is\n  Lambda(f) then \"<lambda>\"\n  BuiltIn(f) then \"<built-in>\"\n  Instance(n, m) then \"<object \" ++ n ++ \">\"\n  Thunk(e) then \"<thunk>\"\n  // StrLit(s) then \"str:\" ++ s\n  // IntLit(n) then \"int:\" ++ toString(n)\n  StrLit(s) then s\n  IntLit(n) then toString(n)\n  ExprList(l) then showList(map(showExpr, l))\nabstract class Data: Literal | DataList | Symbol\nclass Literal(e: Expr) extends Data\nclass DataList(l: List[Data]) extends Data\nclass Symbol(s: Str) extends Data\nfun (=#=) equalData(x: Data, y: Data): Bool = if x is\n  Literal(e) and y is Literal(e') then e =@= e'\n  DataList(l) and y is DataList(l') then equalList(l, l', equalData)\n  Symbol(s) and y is Symbol(s') then s === s'\n  else false\nfun showData(d: Data): Str = if d is\n  Literal(e) then showExpr(e)\n  DataList(l) then \"(\" ++ join(\", \", map(showData, l)) ++ \")\"\n  // Symbol(s) then \"sym:\" ++ s\n  Symbol(s) then s\n//│ abstract class Expr: BuiltIn | ExprList | Instance | IntLit | Lambda | StrLit | Thunk\n//│ class Lambda(f: List[Data] -> Data) extends Expr\n//│ class BuiltIn(e: List[Data] -> Data) extends Expr\n//│ class Instance(n: Str, m: List[[Str, Expr]]) extends Expr\n//│ class Thunk(e: () -> Data) extends Expr\n//│ class StrLit(s: Str) extends Expr\n//│ class IntLit(n: Int) extends Expr\n//│ class ExprList(l: List[Expr]) extends Expr\n//│ fun (=@=) equalExpr: (x: Expr, y: Expr) -> Bool\n//│ fun showExpr: (e: Expr) -> Str\n//│ abstract class Data: DataList | Literal | Symbol\n//│ class Literal(e: Expr) extends Data\n//│ class DataList(l: List[Data]) extends Data\n//│ class Symbol(s: Str) extends Data\n//│ fun (=#=) equalData: (x: Data, y: Data) -> Bool\n//│ fun showData: (d: Data) -> Str\n\n//  _____       _                 _\n// |_   _|___  | | __ ___  _ __  (_) ____ ___  _ __\n//   | | / _ \\ | |/ // _ \\| '_ \\ | ||_  // _ \\| '__|\n//   | || (_) ||   <|  __/| | | || | / /|  __/| |\n//   |_| \\___/ |_|\\_\\\\___||_| |_||_|/___|\\___||_|\n//\n\nfun skipBlank(s: NStr, i: Int): Int =\n  if\n    i < 0 then skipBlank(s, 0)\n    i >= s.length then s.length\n    s.charCodeAt(i) == 32 then skipBlank(s, i + 1)\n    else i\n//│ fun skipBlank: (s: NStr, i: Int) -> Int\n\nfun scanWhile(s: NStr, i: Int, p: Str -> Bool): Option[[Str, Int]] =\n  let rec aux(acc, i) =\n    if i < s.length and s.charAt(i) is ch and p of ch\n      then aux(acc ++ ch, i + 1)\n      else [acc, i]\n  if aux(\"\", i) is\n    [\"\", _] then None\n    [acc, i] then Some([acc, i])\n//│ fun scanWhile: (s: NStr, i: Int, p: Str -> Bool) -> Option[[Str, Int]]\n\nfun isDelimiter(ch) = ch !== \" \" and ch !== \"(\" and ch !== \")\"\n//│ fun isDelimiter: Eql[\" \" | \"(\" | \")\"] -> Bool\n\nfun nextToken(s: NStr, i: Int): Option[[Str, Int]] =\n  let i' = skipBlank(s, i)\n  if s.charAt(i') is\n    \"(\" then Some([\"(\", i' + 1])\n    \")\" then Some([\")\", i' + 1])\n    else scanWhile(s, i', isDelimiter)\n//│ fun nextToken: (s: NStr, i: Int) -> Option[[Str, Int]]\n\nfun tokenize(s: Str): List[Str] =\n  let s' = String(s)\n  let rec aux(acc, i) =\n    if nextToken(s', i) is\n      None then reverse(acc)\n      Some([token, i']) then aux(token :: acc, i')\n  aux(Nil, 0)\n//│ fun tokenize: (s: Str) -> List[Str]\n\nshowList of tokenize(\"\")\nshowList of tokenize(\"12\")\nshowList of tokenize(\"x\")\nshowList of tokenize(\"(quote (cons 1 nil))\")\nshowList of tokenize(\"(+ 1 2)\")\n//│ NStr\n//│ res\n//│     = '[]'\n//│ res\n//│     = '[12]'\n//│ res\n//│     = '[x]'\n//│ res\n//│     = '[(, quote, (, cons, 1, nil, ), )]'\n//│ res\n//│     = '[(, +, 1, 2, )]'\n\n//  ____\n// |  _ \\  __ _  _ __  ___   ___  _ __\n// | |_) |/ _` || '__|/ __| / _ \\| '__|\n// |  __/| (_| || |   \\__ \\|  __/| |\n// |_|    \\__,_||_|   |___/ \\___||_|\n//\n\nfun isDigit(n) = 48 <= n and n <= 57\nfun isDigits(s: Str): Bool =\n  let s' = String(s)\n  let rec aux(i) =\n    if i < s'.length and isDigit of s'.charCodeAt(i)\n      then aux(i + 1)\n      else i === s'.length\n  aux(0)\nisDigits(\"123\")\nisDigits(\"123jump\")\nisDigits(\"bruh\")\n//│ fun isDigit: Num -> Bool\n//│ fun isDigits: (s: Str) -> Bool\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n\nabstract class ParseResult[out A]: Success[A] | Failure\nclass Success[out A](value: A) extends ParseResult[A]\nclass Failure(error: Str) extends ParseResult[nothing]\n//│ abstract class ParseResult[A]: Failure | Success[A]\n//│ class Success[A](value: A) extends ParseResult\n//│ class Failure(error: Str) extends ParseResult\n\n// Notes\n// =====\n// Sometimes, the precedence of comma is less than `of`.\n// For example, in `[Success of DataList of reverse of acc, tail]`.\nfun parseExpr(tokens: List[Str]): [ParseResult[Data], List[Str]] =\n  if tokens is\n    Cons(\"(\", tail) then parseList(tail)\n    Cons(\")\", _) then [Failure(\"Unmatched closing parenthesis.\"), tokens]\n    Cons(token, tail) and\n      isDigits(token) then [(Success of Literal of IntLit of parseInt(token, 10)), tail]\n      else [(Success of Symbol of token), tail]\n    Nil then [Failure(\"Unexpected end of input, expect either `)` or more tokens.\"), Nil]\n  \nfun parseList(tokens: List[Str]): [ParseResult[DataList], List[Str]] =\n  let rec collect(acc, ts) = if ts is\n    Cons(\")\", tail) then [(Success of DataList of reverse of acc), tail]\n    Cons and parseExpr(ts) is\n      [Success(data), rest] then collect(data :: acc, rest)\n      [Failure(_) as failure, rest] then [failure, rest]\n    Nil then [Failure(\"Unexpected end of input, expect either `)` or more tokens.\"), Nil]\n  collect(Nil, tokens)\n//│ fun parseExpr: (tokens: List[Str]) -> [ParseResult[Data], List[Str]]\n//│ fun parseList: (tokens: List[Str]) -> [ParseResult[DataList], List[Str]]\n\nfun showParse(source: Str): Str =\n  if parseExpr(tokenize(source)) is\n    [Success(data), _] then \"Ok: \" ++ showData(data)\n    [Failure(error), _] then \"Error: \" ++ error\n//│ fun showParse: (source: Str) -> Str\n\nshowParse(\"(cons 1 nil)\")\nshowParse(\"(cons 1 (cons 2 nil))\")\nshowParse(\"(cons 1 (cons 2 (cons 3 nil)))\")\nshowParse(\"(+ 1 2)\")\nshowParse(\"(car (cons 1 nil))\")\n//│ Str\n//│ res\n//│     = 'Ok: (cons, 1, nil)'\n//│ res\n//│     = 'Ok: (cons, 1, (cons, 2, nil))'\n//│ res\n//│     = 'Ok: (cons, 1, (cons, 2, (cons, 3, nil)))'\n//│ res\n//│     = 'Ok: (+, 1, 2)'\n//│ res\n//│     = 'Ok: (car, (cons, 1, nil))'\n\n//  _____\n// | ____| _ __ __   __\n// |  _|  | '_ \\\\ \\ / /\n// | |___ | | | |\\ V /\n// |_____||_| |_| \\_/\n//\n\n// As of the time I wrote this code, MLscript did not yet support term\n// refinement, so I used lambda expression to implement `Env` first.\ntype Env[T] = Str -> T\nlet emptyEnv: Str -> nothing = _ => error\n// The lookup function becomes useless because we can just call the `Env`.\nfun lookup(env, name: Str): 'A = env(name)\n//│ type Env[T] = Str -> T\n//│ let emptyEnv: Str -> nothing\n//│ fun lookup: forall 'A. (Str -> 'A, name: Str) -> 'A\n//│ emptyEnv\n//│          = [Function: emptyEnv]\n\n// It is tricky to write an annotation that simplifies the inferred type.\nfun (+:) extend(env, [name, expr]: [Str, 'A]) =\n  (name': Str) => if name' === name then expr else env(name')\n//│ fun (+:) extend: forall 'A. (Str -> 'A, [Str, 'A]) -> (name': Str) -> 'A\n\nfun extendRec(env, name: Str, expr: (Str -> 'A) -> 'A) =\n  let rec env'(name': Str): 'A = if name' === name then expr(env') else env(name')\n  env'\n//│ fun extendRec: forall 'A. (Str -> 'A, name: Str, expr: (Str -> 'A) -> 'A) -> (name': Str) -> 'A\n\nfun extendParameters(env: Str -> 'A, ps: List[Str], vs: List['A]) =\n  if [ps, vs] is\n    [Nil, Nil] then env\n    [Cons(p, ps'), Cons(v, vs')] then extendParameters(extend(env, [p, v]), ps', vs')\n    else error\n//│ fun extendParameters: forall 'A. (env: Str -> 'A, ps: List[Str], vs: List['A]) -> Str -> 'A\n\nfun (++:) extendEntries(env, ps: List[[Str, 'A]]) =\n  if ps is\n    Nil then env\n    Cons(p, ps') then extendEntries(extend(env, p), ps')\n    else error\n//│ fun (++:) extendEntries: forall 'A 'a. (Str -> 'A & 'a, ps: List[[Str, 'A]]) -> ((name': Str) -> 'A | 'a)\n\nlet intEnv1 = extend(emptyEnv, [\"one\", 1])\nlet intEnv2 = extend(intEnv1, [\"two\", 2])\nlet intEnv3 = extend(intEnv2, [\"three\", 3])\n//│ let intEnv1: (name': Str) -> 1\n//│ let intEnv2: (name': Str) -> (1 | 2)\n//│ let intEnv3: (name': Str) -> (1 | 2 | 3)\n//│ intEnv1\n//│         = [Function (anonymous)]\n//│ intEnv2\n//│         = [Function (anonymous)]\n//│ intEnv3\n//│         = [Function (anonymous)]\n\n// Make a tuple to save some lines.\n[intEnv1(\"one\"), intEnv2(\"one\"), intEnv3(\"one\"), intEnv2(\"two\"), intEnv3(\"two\"), intEnv3(\"three\")]\n//│ [1, 1 | 2, 1 | 2 | 3, 1 | 2, 1 | 2 | 3, 1 | 2 | 3]\n//│ res\n//│     = [ 1, 1, 1, 2, 2, 3 ]\n\n:re\nintEnv1(\"two\")\nintEnv2(\"three\")\nintEnv3(\"bruh\")\n//│ 1 | 2 | 3\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\nlet intEnv6 = intEnv3 ++: ([\"four\", 4] :: [\"five\", 5] :: [\"six\", 6] :: Nil)\n//│ let intEnv6: (name': Str) -> (1 | 2 | 3 | 4 | 5 | 6)\n//│ intEnv6\n//│         = [Function (anonymous)]\n\n[intEnv6(\"one\"), intEnv6(\"two\"), intEnv6(\"three\"), intEnv6(\"four\"), intEnv6(\"five\"), intEnv6(\"six\")]\n//│ [1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6, 1 | 2 | 3 | 4 | 5 | 6]\n//│ res\n//│     = [ 1, 2, 3, 4, 5, 6 ]\n\n:re\nintEnv6(\"seven\")\n//│ 1 | 2 | 3 | 4 | 5 | 6\n//│ res\n//│ Runtime error:\n//│   Error: an error was thrown\n\nfun builtinEq(args: List[Data]): Data = if args is\n  Cons(x, Cons(y, Nil)) and\n    x =#= y then Literal(IntLit(1))\n    else Literal(IntLit(0))\n  else error\nfun builtinAdd(args: List[Data]): Data = if args is\n  Cons(Literal(IntLit(x)), Cons(Literal(IntLit(y)), Nil)) then Literal(IntLit(x + y))\n  else error\nfun builtinSub(args: List[Data]): Data = if args is\n  Cons(Literal(IntLit(x)), Cons(Literal(IntLit(y)), Nil)) then Literal(IntLit(x - y))\n  else error\nfun builtinMul(args: List[Data]): Data = if args is\n  Cons(Literal(IntLit(x)), Cons(Literal(IntLit(y)), Nil)) then Literal(IntLit(x * y))\n  else error\nlet builtinNil = DataList(Nil)\nfun builtinCons(args: List[Data]): Data = if args is\n  Cons(x, Cons(DataList(xs), Nil)) then DataList(x :: xs)\n  else error\nfun builtinCar(args: List[Data]): Data = if args is\n  Cons(DataList(Cons(x, _)), Nil) then x\n  else error\nfun builtinCdr(args: List[Data]): Data = if args is\n  Cons(DataList(Cons(_, xs)), Nil) then DataList(xs)\n  else error\nfun builtinNull(args: List[Data]): Data = if args is\n  Cons(DataList(Nil), Nil) then Literal(IntLit(1))\n  else Literal(IntLit(0))\n//│ fun builtinEq: (args: List[Data]) -> Data\n//│ fun builtinAdd: (args: List[Data]) -> Data\n//│ fun builtinSub: (args: List[Data]) -> Data\n//│ fun builtinMul: (args: List[Data]) -> Data\n//│ let builtinNil: DataList\n//│ fun builtinCons: (args: List[Data]) -> Data\n//│ fun builtinCar: (args: List[Data]) -> Data\n//│ fun builtinCdr: (args: List[Data]) -> Data\n//│ fun builtinNull: (args: List[Data]) -> Data\n//│ builtinNil\n//│            = DataList {}\n\nlet globalEnv = emptyEnv ++:\n  [\"eq\", Literal(Lambda(builtinEq))] :: [\"+\", Literal(Lambda(builtinAdd))] ::\n  [\"-\", Literal(Lambda(builtinSub))] :: [\"*\", Literal(Lambda(builtinMul))] ::\n  [\"nil\", builtinNil] :: [\"cons\", Literal(Lambda(builtinCons))] ::\n  [\"car\", Literal(Lambda(builtinCar))] :: [\"cdr\", Literal(Lambda(builtinCdr))] ::\n  [\"null\", Literal(Lambda(builtinNull))] :: Nil\n//│ let globalEnv: (name': Str) -> (DataList | Literal)\n//│ globalEnv\n//│           = [Function (anonymous)]\n\nfun toName(x: Data): Str = if x is Symbol(s) then s else error\n//│ fun toName: (x: Data) -> Str\n\nfun asList(x: Data): List[Data] = if x is DataList(ys) then ys else error\n//│ fun asList: (x: Data) -> List[Data]\n\nfun eval(x: Data, env: Str -> Data): Data = if x is\n  Literal(StrLit(_)) as lit then lit\n  Literal(IntLit(_)) as lit then lit\n  Symbol(name) then env(name)\n  DataList(Cons(Symbol(\"val\"), tail)) and tail is\n    Cons(param, Cons(expr, Cons(rest, Nil))) then\n      eval(rest, env +: [toName(param), eval(expr, env)])\n    else error\n  DataList(Cons(Symbol(\"def\"), Cons(param, Cons(body, Cons(rest, Nil))))) then\n    let env' = extendRec of env, toName(param), (env => eval(body, env))\n    eval(rest, env')\n  DataList(Cons(Symbol(\"if\"), Cons(cond, Cons(thenPart, Cons(elsePart, Nil))))) and\n    eval(cond, env) is Literal(IntLit(0)) then eval(elsePart, env)\n    else eval(thenPart, env)\n  DataList(Cons(Symbol(\"quote\"), Cons(y, Nil))) then y\n  DataList(Cons(Symbol(\"lambda\"), Cons(params, Cons(body, Nil)))) then\n    let ps = map(toName, asList(params))\n    Literal(Lambda(args => eval(body, extendParameters(env, ps, args))))\n  DataList(Cons(operator, operands)) and eval(operator, env) is\n    Literal(Lambda(f)) then f of map((x) => eval(x, env), operands)\n    else error // application of a non-function\n  else error // unrecognized program\n//│ fun eval: (x: Data, env: Str -> Data) -> Data\n\nfun showEval(source: Str): Str =\n  if parseExpr(tokenize(source)) is\n    [Success(data), _] then \"Ok: \" ++ showData of eval(data, globalEnv)\n    [Failure(error), _] then \"Error: \" ++ error\n//│ fun showEval: (source: Str) -> Str\n\nshowEval(\"1\")\nshowEval(\"(+ 1 2)\")\nshowEval(\"(val x 7 (val y 6 (* x y)))\")\nshowEval(\"(quote x)\")\nshowEval(\"(cons 1 nil)\")\nshowEval(\"(car (cons 1 nil))\")\nshowEval(\"(null 0)\")\nshowEval(\"(null nil)\")\nshowEval(\"(def id (lambda (x) x) (id 42))\")\n//│ Str\n//│ res\n//│     = 'Ok: 1'\n//│ res\n//│     = 'Ok: 3'\n//│ res\n//│     = 'Ok: 42'\n//│ res\n//│     = 'Ok: x'\n//│ res\n//│     = 'Ok: (1)'\n//│ res\n//│     = 'Ok: 1'\n//│ res\n//│     = 'Ok: 0'\n//│ res\n//│     = 'Ok: 1'\n//│ res\n//│     = 'Ok: 42'\n\nshowEval(\"(def fact (lambda (n) (if (eq n 0) 1 (* n (fact (- n 1))))) (fact 5))\")\nshowEval(\"(def fib (lambda (n) (if (eq n 0) 0 (if (eq n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))) (fib 10))\")\nshowEval(\"(def sum (lambda (n) (if (eq n 0) 0 (+ n (sum (- n 1))))) (sum 50))\")\nshowEval(\"(def ack (lambda (m n) (if (eq m 0) (+ n 1) (if (eq n 0) (ack (- m 1) 1) (ack (- m 1) (ack m (- n 1)))))) (ack 3 2))\")\n//│ Str\n//│ res\n//│     = 'Ok: 120'\n//│ res\n//│     = 'Ok: 55'\n//│ res\n//│     = 'Ok: 1275'\n//│ res\n//│     = 'Ok: 29'\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/List.mls",
    "content": ":NewDefs\n\n// TODO\nabstract class List[out A]: (Cons[A] | Nil) {\n  fun isEmpty: Bool\n  fun map[B]: (A -> B) -> List[B]\n}\nclass Cons[out A](head: A, tail: List[A]) extends List[A] {\n  fun isEmpty: Bool = false\n  fun map(f) = Cons(f(head), tail.map(f))\n}\nmodule Nil extends List {\n  fun isEmpty: Bool = true\n  fun map(f) = Nil\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.10: \t  fun map(f) = Cons(f(head), tail.map(f))\n//│ ╙──      \t                                 ^^^^\n//│ abstract class List[A]: Cons[A] | Nil {\n//│   fun isEmpty: Bool\n//│   fun map: forall 'B. (A -> 'B) -> List['B]\n//│ }\n//│ class Cons[A](head: A, tail: List[A]) extends List {\n//│   fun isEmpty: Bool\n//│   fun map: forall 'A. (A -> 'A) -> Cons['A]\n//│ }\n//│ module Nil extends List {\n//│   fun isEmpty: Bool\n//│   fun map: anything -> Nil\n//│ }\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/ListFold.mls",
    "content": ":NewDefs\n\nfun (|>) pipe(x, f) = f(x)\nfun (++) strcat(s1, s2) = concat(s1)(s2)\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (++) strcat: (Str, Str) -> Str\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List[nothing]\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\nlet oneTwoThree = 1 :: 2 :: 3 :: Nil\n//│ let oneTwoThree: Cons[1 | 2 | 3]\n//│ oneTwoThree\n//│             = Cons {}\n\n// Note that JavaScript doesn't have tail call optimization. Therefore, this\n// implementation is still inefficient in practice.\nfun join(sep) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(acc ++ sep ++ toString(x), xs')\n  (xs) =>\n    if xs is\n      Cons(x, xs') then aux(toString(x), xs')\n      Nil then \"\"\n//│ fun join: Str -> (Cons[anything] | Nil) -> Str\n\njoin(\", \")(1 :: 2 :: 3 :: Nil)\n(1 :: 2 :: 3 :: Nil) |> join(\", \")\n//│ Str\n//│ res\n//│     = '1, 2, 3'\n//│ res\n//│     = '1, 2, 3'\n\nfun showList(xs) = \"[\" ++ join(\", \")(xs) ++ \"]\"\n//│ fun showList: (Cons[anything] | Nil) -> Str\n\nfun (:::) appendAll(xs, ys) =\n  if xs is\n    Nil then ys\n    Cons(x, xs') then x :: (xs' ::: ys)\n//│ fun (:::) appendAll: forall 'T 'a. (Cons['T] | Nil, List['T] & 'a) -> (Cons['T] | 'a)\n\n((1 :: 2 :: 3 :: Nil) ::: (4 :: 5 :: 6 :: Nil)) |> showList\n//│ Str\n//│ res\n//│     = '[1, 2, 3, 4, 5, 6]'\n\nfun reverse(xs) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(x :: acc, xs')\n  aux(Nil, xs)\n//│ fun reverse: (Cons[anything] | Nil) -> (Cons[nothing] | Nil)\n\n(1 :: 2 :: 3 :: Nil) |> showList\nreverse(1 :: 2 :: 3 :: Nil) |> showList\n//│ Str\n//│ res\n//│     = '[1, 2, 3]'\n//│ res\n//│     = '[3, 2, 1]'\n\n//   __       _     _ _          __ _\n//  / _| ___ | | __| | |    ___ / _| |_\n// | |_ / _ \\| |/ _` | |   / _ \\ |_| __|\n// |  _| (_) | | (_| | |__|  __/  _| |_\n// |_|  \\___/|_|\\__,_|_____\\___|_|  \\__|\n//\n\nfun foldLeft(f)(z) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(f(acc, x), xs')\n  (xs) => aux(z, xs)\n//│ fun foldLeft: forall 'a 'b. (('a, 'b) -> 'a) -> 'a -> (Cons['b] | Nil) -> 'a\n\nlet sum = foldLeft((acc, x) => acc + x)(0)\nsum(Nil)\nsum(1 :: 2 :: 3 :: Nil)\n//│ let sum: (Cons[Int] | Nil) -> Int\n//│ Int\n//│ sum\n//│     = [Function (anonymous)]\n//│ res\n//│     = 0\n//│ res\n//│     = 6\n\nlet product = foldLeft((acc, x) => acc * x)(1)\nproduct(Nil)\nproduct(1 :: 2 :: 3 :: Nil)\n//│ let product: (Cons[Int] | Nil) -> Int\n//│ Int\n//│ product\n//│         = [Function (anonymous)]\n//│ res\n//│     = 1\n//│ res\n//│     = 6\n\nlet length = foldLeft((acc, _) => acc + 1)(0)\nlength(Nil)\nlength(1 :: 2 :: 3 :: Nil)\n//│ let length: (Cons[anything] | Nil) -> Int\n//│ Int\n//│ length\n//│        = [Function (anonymous)]\n//│ res\n//│     = 0\n//│ res\n//│     = 3\n\nlet reverse' = foldLeft((acc, x) => x :: acc)(Nil)\nreverse'(Nil)\nreverse'(1 :: 2 :: 3 :: Nil) |> showList\n//│ let reverse': (Cons['T] | Nil) -> (Cons[1 | 2 | 3 | 'T] | Nil)\n//│ Str\n//│ reverse'\n//│          = [Function (anonymous)]\n//│ res\n//│     = Nil { class: [class Nil extends List] }\n//│ res\n//│     = '[3, 2, 1]'\n\n\n//   __       _     _ ____  _       _     _\n//  / _| ___ | | __| |  _ \\(_) __ _| |__ | |_\n// | |_ / _ \\| |/ _` | |_) | |/ _` | '_ \\| __|\n// |  _| (_) | | (_| |  _ <| | (_| | | | | |_\n// |_|  \\___/|_|\\__,_|_| \\_\\_|\\__, |_| |_|\\__|\n//                            |___/\n\nfun foldRight(f)(z) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then f(x, aux(acc, xs'))\n  (xs) => aux(z, xs)\n//│ fun foldRight: forall 'a 'b. (('a, 'b) -> 'b) -> 'b -> (Cons['a] | Nil) -> 'b\n\nlet double = foldRight((x, acc) => x :: x :: acc)(Nil)\ndouble(Nil) |> showList\ndouble(1 :: 2 :: 3 :: Nil) |> showList\n//│ let double: (Cons[anything] | Nil) -> (Cons[1 | 2 | 3] | Nil)\n//│ Str\n//│ double\n//│        = [Function (anonymous)]\n//│ res\n//│     = '[]'\n//│ res\n//│     = '[1, 1, 2, 2, 3, 3]'\n\nlet flatten = foldRight((xs, acc) => xs ::: acc)(Nil)\nflatten(Nil) |> showList\nflatten(oneTwoThree :: oneTwoThree :: oneTwoThree :: Nil) |> showList\n//│ let flatten: (Cons[Cons['T] | Nil] | Nil) -> (Cons[1 | 2 | 3 | 'T] | Nil)\n//│ Str\n//│ flatten\n//│         = [Function (anonymous)]\n//│ res\n//│     = '[]'\n//│ res\n//│     = '[1, 2, 3, 1, 2, 3, 1, 2, 3]'\n\nfun id(x) = x\n//│ fun id: forall 'a. 'a -> 'a\n\nfun foldLeft'(f: ('A, 'B) -> 'A)(z: 'A) =\n  let g(x, y)(z) = y(f(z, x))\n  (xs) => foldRight(g)(id)(xs)(z)\n//│ fun foldLeft': forall 'A 'B. (f: ('A, 'B) -> 'A) -> (z: 'A) -> (Cons['B] | Nil) -> 'A\n\nlet minus = foldLeft'((acc, x) => acc - x)(0)\nminus(Nil)\nminus(1 :: 2 :: 3 :: Nil)\n//│ let minus: (Cons[Int] | Nil) -> Int\n//│ Int\n//│ minus\n//│       = [Function (anonymous)]\n//│ res\n//│     = 0\n//│ res\n//│     = -6\n\nlet reverse'' = foldLeft'((acc, x) => x :: acc)(Nil)\nreverse(Nil)\nreverse(1 :: 2 :: 3 :: Nil) |> showList\n//│ let reverse'': (Cons[anything] | Nil) -> (Cons[nothing] | Nil)\n//│ Str\n//│ reverse''\n//│           = [Function (anonymous)]\n//│ res\n//│     = Nil { class: [class Nil extends List] }\n//│ res\n//│     = '[3, 2, 1]'\n\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/Option.mls",
    "content": ":NewDefs\n\nabstract class MyOption[out T]: (MySome[T] | MyNone) {\n  virtual fun filter: (p: T -> Bool) -> MyOption[T]\n}\nclass MySome[out T](val value: T) extends MyOption[T] {\n  fun filter(p) = if p of value then MySome(value) else MyNone\n}\nmodule MyNone extends MyOption[nothing] {\n  fun filter(_) = MyNone\n}\n//│ abstract class MyOption[T]: MyNone | MySome[T] {\n//│   fun filter: (p: T -> Bool) -> MyOption[T]\n//│ }\n//│ class MySome[T](value: T) extends MyOption {\n//│   fun filter: (T -> Bool) -> (MyNone | MySome[T])\n//│ }\n//│ module MyNone extends MyOption {\n//│   fun filter: anything -> MyNone\n//│ }\n\n// The following code aims to find a workaround that allows the functions\n// operating ADT to be defined as member functions of classes, and also ensures\n// the correct generation of JavaScript code.\n\n// Create an alias constructor for `Some`\n// ======================================\n// // This works:\nfun some: forall 'a: 'a -> Option['a]\nfun some = x => Some(x)\n// // This doesn't work with `map`:\n// let some: forall 'a: 'a -> Option['a] = x => Some(x)\n//\n// Create an alias constructor for `None`\n// ======================================\n// // This works:\n// fun none: forall 'a: () -> Option['a]\n// fun none = () => None\n// // This also works:\n// fun none: Option[nothing]\n// fun none = None\n// This also works:\nlet none: () -> Option[nothing] = () => None\n// // This also works but failed in code generation:\n// let none: Option[nothing] = None\n//\n// The class definitions\n// =====================\nabstract class Option[out T]: (Some[T] | None) {\n  virtual fun isEmpty: Bool\n  virtual fun isDefined: Bool\n  virtual fun map: forall 'b: (T -> 'b) -> Option['b]\n  virtual fun flatMap: forall 'b: (T -> Option['b]) -> Option['b]\n  virtual fun filter: (p: T -> Bool) -> Option[T]\n  virtual fun get: T\n}\nclass Some[out T](val value: T) extends Option[T] {\n  fun isEmpty = false\n  fun isDefined = true\n  fun map(f) = some(f(value))\n  fun flatMap(f) = f(value)\n  fun filter(p) = if p of value then some(value) else none()\n  fun get = value\n}\nmodule None extends Option[nothing] {\n  fun isEmpty = true\n  fun isDefined = false\n  fun map(_) = none()\n  fun flatMap(_) = none()\n  fun filter(_) = none()\n  fun get = error\n}\n//│ fun some: forall 'T. 'T -> Some['T]\n//│ let none: () -> Option[nothing]\n//│ abstract class Option[T]: None | Some[T] {\n//│   fun filter: (p: T -> Bool) -> Option[T]\n//│   fun flatMap: forall 'b. (T -> Option['b]) -> Option['b]\n//│   fun get: T\n//│   fun isDefined: Bool\n//│   fun isEmpty: Bool\n//│   fun map: forall 'b0. (T -> 'b0) -> Option['b0]\n//│ }\n//│ class Some[T](value: T) extends Option {\n//│   fun filter: (T -> Bool) -> Option[T]\n//│   fun flatMap: forall 'c. (T -> 'c) -> 'c\n//│   fun get: T\n//│   fun isDefined: true\n//│   fun isEmpty: false\n//│   fun map: forall 'a. (T -> 'a) -> Option['a]\n//│ }\n//│ module None extends Option {\n//│   fun filter: anything -> Option[nothing]\n//│   fun flatMap: anything -> Option[nothing]\n//│   fun get: nothing\n//│   fun isDefined: false\n//│   fun isEmpty: true\n//│   fun map: anything -> Option[nothing]\n//│ }\n//│ fun some: forall 'a0. 'a0 -> Option['a0]\n//│ none\n//│      = [Function: none]\n\nsome(0).map(x => x + 1).get\n//│ Int\n//│ res\n//│     = 1\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/Permutations.mls",
    "content": ":NewDefs\n\nfun (|>) pipe(x, f) = f(x)\nfun (++) strcat(s1, s2) = concat(s1)(s2)\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (++) strcat: (Str, Str) -> Str\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List[nothing]\nfun (::) cons(head, tail) = Cons(head, tail)\nfun (:::) appendAll(xs: List['A], ys: List['A]): List['A] =\n  if xs is\n    Nil then ys\n    Cons(x, xs') then x :: (xs' ::: ys)\nfun (:+) append(xs, x): List['A] = xs ::: (x :: Nil)\nfun reverse(xs) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(x :: acc, xs')\n  aux(Nil, xs)\nfun join(sep) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(acc ++ sep ++ toString(x), xs')\n  (xs) =>\n    if xs is\n      Cons(x, xs') then aux(toString(x), xs')\n      Nil then \"\"\nfun showList(xs) = \"[\" ++ join(\", \")(xs) ++ \"]\"\nfun foldLeft(f)(z) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(f(acc, x), xs')\n  (xs) => aux(z, xs)\nfun map(f, xs) =\n  if xs is\n    Nil then Nil\n    Cons(x, xs') then f(x) :: map(f, xs')\nfun showListList(xs) = \"[\" ++ join(\", \")(map(showList, xs)) ++ \"]\"\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n//│ fun (:::) appendAll: forall 'T0. (xs: List['T0], ys: List['T0]) -> List['T0]\n//│ fun (:+) append: forall 'T1. (List['T1], 'T1) -> List['T1]\n//│ fun reverse: (Cons[anything] | Nil) -> (Cons[nothing] | Nil)\n//│ fun join: Str -> (Cons[anything] | Nil) -> Str\n//│ fun showList: (Cons[anything] | Nil) -> Str\n//│ fun foldLeft: forall 'a 'b. (('a, 'b) -> 'a) -> 'a -> (Cons['b] | Nil) -> 'a\n//│ fun map: forall 'c 'T2. ('c -> 'T2, Cons['c] | Nil) -> (Cons['T2] | Nil)\n//│ fun showListList: (Cons[Cons[anything] | Nil] | Nil) -> Str\n\nfun insertAllPositions(z) =\n  let rec aux(prev, acc, xs) =\n    if xs is\n      Nil then ((prev :+ z) :: acc) |> reverse\n      Cons(head, tail) then\n        let nu = ((prev :+ z) ::: xs)\n        aux(prev :+ head, nu :: acc, tail)\n  xs => aux(Nil, Nil, xs)\n//│ fun insertAllPositions: forall 'a. 'a -> (forall 'A 'A0. (Cons['A & 'A0] | Nil) -> (Cons[List['a | 'A0]] | Nil))\n//│   where\n//│     'A <: 'A0\n//│     'A0 :> 'a\n//│         <: 'A\n\ninsertAllPositions(0)(1 :: 2 :: 3 :: Nil) |> showListList\n//│ Str\n//│ res\n//│     = '[[0, 1, 2, 3], [1, 0, 2, 3], [1, 2, 0, 3], [1, 2, 3, 0]]'\n\n:js\nfun permutations(xs) =\n  if xs is\n    Nil then Nil\n    Cons(x, Nil) then (x :: Nil) :: Nil\n    Cons(x, xs') then foldLeft((acc, ys) => acc ::: insertAllPositions(x)(ys))(Nil)(permutations(xs'))\n//│ fun permutations: forall 'T 'A. (Cons['T] | Nil) -> (Cons[Cons['T]] | List[List['A]] | Nil)\n//│   where\n//│     'T <: 'A\n//│     'A := 'T\n//│ // Prelude\n//│ class TypingUnit4 {}\n//│ const typing_unit4 = new TypingUnit4;\n//│ // Query 1\n//│ globalThis.permutations = function permutations(xs) {\n//│   return ((() => {\n//│     let a;\n//│     return (a = xs, a instanceof Nil.class ? Nil : a instanceof Cons.class ? ((ucs$args_xs$Cons) => ((x) => ((xs$Cons_1) => xs$Cons_1 instanceof Nil.class ? cons(cons(x, Nil), Nil) : ((xs$) => foldLeft((acc, ys) => appendAll(acc, insertAllPositions(x)(ys)))(Nil)(permutations(xs$)))(ucs$args_xs$Cons[1]))(ucs$args_xs$Cons[1]))(ucs$args_xs$Cons[0]))(Cons.unapply(xs)) : (() => {\n//│       throw new Error(\"non-exhaustive case expression\");\n//│     })());\n//│   })());\n//│ };\n//│ // End of generated code\n\npermutations(Nil) |> showListList\npermutations(1 :: Nil) |> showListList\npermutations(1 :: 2 :: Nil) |> showListList\npermutations(1 :: 2 :: 3 :: Nil) |> showListList\n//│ Str\n//│ res\n//│     = '[]'\n//│ res\n//│     = '[[1]]'\n//│ res\n//│     = '[[1, 2], [2, 1]]'\n//│ res\n//│     = '[[1, 2, 3], [2, 1, 3], [2, 3, 1], [1, 3, 2], [3, 1, 2], [3, 2, 1]]'\n\nfun filterNot(f, xs) =\n  if xs is\n    Nil then Nil\n    Cons(x, xs') then\n      if f(x) then filterNot(f, xs')\n      else x :: filterNot(f, xs')\n//│ fun filterNot: forall 'T. ('T -> Bool, Cons['T] | Nil) -> (Cons['T] | Nil)\n\nfun permutations'(xs) =\n  if xs is\n    Nil then Nil\n    Cons(x, Nil) then (x :: Nil) :: Nil\n    else\n      let f(acc, x) = acc ::: map((ys) => x :: ys, permutations'(filterNot((y) => x === y, xs)))\n      foldLeft(f)(Nil)(xs)\n//│ fun permutations': forall 'T. (Cons['T] | Nil) -> (Cons[Cons['T]] | List[Cons['T]] | Nil)\n//│   where\n//│     'T <: Eql['T]\n\npermutations'(Nil) |> showListList\npermutations'(1 :: Nil) |> showListList\npermutations'(1 :: 2 :: Nil) |> showListList\npermutations'(1 :: 2 :: 3 :: Nil) |> showListList\n//│ Str\n//│ res\n//│     = '[]'\n//│ res\n//│     = '[[1]]'\n//│ res\n//│     = '[[1, 2], [2, 1]]'\n//│ res\n//│     = '[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]'\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/STLC.mls",
    "content": ":NewDefs\n\nfun (++) concatOp(a, b) = concat(a)(b)\n//│ fun (++) concatOp: (Str, Str) -> Str\n\nfun par(a) = \"(\" ++ a ++ \")\"\n//│ fun par: Str -> Str\n\ntype Option[out A] = Some[A] | None\nclass Some[out A](value: A)\nmodule None\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A)\n//│ module None\n\ntype Result[A, B] = Ok[A] | Err[B]\nclass Ok[A](value: A)\nclass Err[A](message: A)\n//│ type Result[A, B] = Err[B] | Ok[A]\n//│ class Ok[A](value: A)\n//│ class Err[A](message: A)\n\ntype Type = FunctionType | PrimitiveType\nclass PrimitiveType(name: Str)\nclass FunctionType(lhs: Type, rhs: Type)\n//│ type Type = FunctionType | PrimitiveType\n//│ class PrimitiveType(name: Str)\n//│ class FunctionType(lhs: Type, rhs: Type)\n\n// Helpers.\nfun _f(lhs, rhs) = FunctionType(lhs, rhs)\nfun _t(name) = PrimitiveType(name)\n//│ fun _f: (Type, Type) -> FunctionType\n//│ fun _t: Str -> PrimitiveType\n\ntype Term = Lit | Var | Abs | App\nclass Lit(tag: Str, ty: Type)\nclass Var(name: Str)\nclass Abs(lhs: Var, lty: Type, rhs: Term)\nclass App(lhs: Term, rhs: Term)\n// class App(lhs: Term, rhs: Term): Term\n//│ type Term = Abs | App | Lit | Var\n//│ class Lit(tag: Str, ty: Type)\n//│ class Var(name: Str)\n//│ class Abs(lhs: Var, lty: Type, rhs: Term)\n//│ class App(lhs: Term, rhs: Term)\n\ntype TreeMap[A] = Node[A] | Empty\nclass Node[A](key: Str, value: A, left: TreeMap[A], right: TreeMap[A])\nmodule Empty\n//│ type TreeMap[A] = Empty | Node[A]\n//│ class Node[A](key: Str, value: A, left: TreeMap[A], right: TreeMap[A])\n//│ module Empty\n\nfun insert(t, k, v) =\n  if t is\n    Node(k', _, l, r) and\n      slt(k, k') then Node(k', v, insert(l, k, v), r)\n      sgt(k, k') then Node(k', v, l, insert(r, k, v))\n      _ then Node(k, v, l, r)\n    Empty then Node(k, v, Empty, Empty)\nfun find(t, k) =\n  if t is\n    Node(k', v, l, r) and\n      slt(k, k') then find(l, k)\n      sgt(k, k') then find(r, k)\n      _ then Some(v)\n    Empty then None\n//│ fun insert: forall 'A. (Empty | Node['A], Str, 'A) -> Node['A]\n//│ fun find: forall 'A0. (Empty | Node['A0], Str) -> (None | Some['A0])\n\nfun showType(ty) =\n  if ty is\n    FunctionType(PrimitiveType(name), rhs) then name ++ \" -> \" ++ showType(rhs)\n    FunctionType(lhs, rhs) then \"(\" ++ showType(lhs) ++ \") -> \" ++ showType(rhs)\n    PrimitiveType(name) then name\n//│ fun showType: (FunctionType | PrimitiveType) -> Str\n\nshowType(_t(\"int\"))\nshowType(_f(_t(\"int\"), _t(\"bool\")))\nshowType(_f(_f(_t(\"int\"), _t(\"bool\")), _t(\"bool\")))\nshowType(_f(_t(\"bool\"), _f(_t(\"int\"), _t(\"bool\"))))\n//│ Str\n//│ res\n//│     = 'int'\n//│ res\n//│     = 'int -> bool'\n//│ res\n//│     = '(int -> bool) -> bool'\n//│ res\n//│     = 'bool -> int -> bool'\n\nfun typeEqual(t1, t2) =\n  if\n    t1 is PrimitiveType(name1) and t2 is PrimitiveType(name2) then eq(name1)(name2)\n    t1 is FunctionType(lhs1, rhs1) and t2 is FunctionType(lhs2, rhs2) then\n      typeEqual(lhs1, lhs2) and typeEqual(rhs1, rhs2)\n    _ then false\n//│ fun typeEqual: (Object, Object) -> Bool\n\nfun showTerm(t) =\n  if t is\n    Lit(tag, _) then tag\n    Var(name) then name\n    Abs(lhs, ty, rhs) then \"&\" ++ showTerm(lhs) ++ \": \" ++ showType(ty) ++ \" => \" ++ showTerm(rhs)\n    App(Abs(lhs0, ty, lhs1), rhs) then\n      \"((\" ++ showTerm(Abs(lhs0, ty, rhs)) ++ \") \" ++ showTerm(rhs) ++ \")\"\n    App(lhs, rhs) then par(showTerm(lhs) ++ \" \" ++ showTerm(rhs))\n//│ fun showTerm: (Abs | App | Lit | Var) -> Str\n\nshowTerm(Var(\"x\"))\nshowTerm(Abs(Var(\"x\"), _t(\"int\"), Var(\"y\")))\nshowTerm(App(Var(\"x\"), Var(\"y\")))\nshowTerm(App(Abs(Var(\"x\"), _t(\"int\"), Var(\"y\")), Var(\"z\")))\n//│ Str\n//│ res\n//│     = 'x'\n//│ res\n//│     = '&x: int => y'\n//│ res\n//│     = '(x y)'\n//│ res\n//│     = '((&x: int => z) z)'\n\n// Removing the return type annotation causes stack overflow.\nfun typeTerm(t: Term, ctx: TreeMap[Type]): Result[Type, Str] =\n  if t is\n    Lit(_, ty) then Ok(ty)\n    Var(name) and find(ctx, name) is\n      Some(ty) then Ok(ty)\n      None then Err(\"unbound variable `\" ++ name ++ \"`\")\n    Abs(Var(name), ty, body) and typeTerm(body, insert(ctx, name, ty)) is\n      Ok(resTy) then Ok(FunctionType(ty, resTy))\n      Err(message) then Err(message)\n    App(lhs, rhs) and typeTerm(lhs, ctx) is\n      Ok(FunctionType(pTy, resTy)) and typeTerm(rhs, ctx) is\n        Ok(aTy) and\n          typeEqual(pTy, aTy) then Ok(resTy)\n          else Err(\"expect the argument to be of type `\" ++ showType(pTy) ++ \"` but found `\" ++ showType(aTy) ++ \"`\")\n        Err(message) then Err(message)\n      Ok(PrimitiveType(name)) then Err(\"cannot apply primitive type `\" ++ name ++ \"`\")\n      Err(message) then Err(message)\n//│ fun typeTerm: (t: Term, ctx: TreeMap[Type]) -> Result[Type, Str]\n\nfun showTypeTerm(t, ctx) =\n  if typeTerm(t, ctx) is\n    Ok(ty) then showTerm(t) ++ \" : \" ++ showType(ty)\n    Err(message) then \"Type error: \" ++ message\n//│ fun showTypeTerm: (Term, TreeMap[Type]) -> Str\n\nshowTypeTerm(Var(\"x\"), Empty)\nshowTypeTerm(Abs(Var(\"x\"), _t(\"int\"), Var(\"x\")), Empty)\nshowTypeTerm(App(Var(\"f\"), Lit(\"0\", _t(\"int\"))), insert(Empty, \"f\", _f(_t(\"int\"), _t(\"int\"))))\nshowTypeTerm(App(Var(\"f\"), Lit(\"0.2\", _t(\"float\"))), insert(Empty, \"f\", _f(_t(\"int\"), _t(\"int\"))))\nshowTypeTerm(App(Var(\"f\"), Lit(\"0\", _t(\"int\"))), insert(Empty, \"f\", _t(\"Str\")))\n//│ Str\n//│ res\n//│     = 'Type error: unbound variable `x`'\n//│ res\n//│     = '&x: int => x : int -> int'\n//│ res\n//│     = '(f 0) : int'\n//│ res\n//│     = 'Type error: expect the argument to be of type `int` but found `float`'\n//│ res\n//│     = 'Type error: cannot apply primitive type `Str`'\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/SimpleLisp.mls",
    "content": ":NewDefs\n\nfun (++) strcat(a: Str, b: Str): Str = concat(a)(b)\n//│ fun (++) strcat: (a: Str, b: Str) -> Str\n\ndeclare module JSON {\n  fun stringify: (data: anything) -> Str\n}\ndeclare class Function(source: Str) {\n  fun call: () -> nothing\n}\nfun fatal(message: Str): nothing =\n  let raise = Function(\"throw new Error(\" ++ JSON.stringify(message) ++ \")\")\n  raise.call()\n//│ declare module JSON {\n//│   fun stringify: (data: anything) -> Str\n//│ }\n//│ declare class Function(source: Str) {\n//│   fun call: () -> nothing\n//│ }\n//│ fun fatal: (message: Str) -> nothing\n\nabstract class List[A]: Nil | Cons[A]\nclass Cons[A](head: A, tail: List[A]) extends List[A]\nmodule Nil extends List\nfun (::) cons[A](head: A, tail: List[A]): List[A] = Cons(head, tail)\nfun map(f: 'A -> 'B, list: List['A]): List['B] =\n  if list is\n    Nil then Nil\n    Cons(head, tail) then Cons(f(head), map(f, tail))\nfun showList(sep: Str, showItem: 'A -> Str) =\n  let rec aux(list: List['A]) =\n    if list is\n      Nil then \"\"\n      Cons(head, Nil) then showItem(head)\n      Cons(head, tail) then showItem(head) ++ sep ++ aux(tail)\n  aux\n//│ abstract class List[A]: Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A]) extends List\n//│ module Nil extends List\n//│ fun (::) cons: forall 'A. (head: 'A, tail: List['A]) -> List['A]\n//│ fun map: forall 'A0 'A1. (f: 'A0 -> 'A1, list: List['A0]) -> List['A1]\n//│ fun showList: forall 'A2. (sep: Str, showItem: 'A2 -> Str) -> (forall 'A3. (list: List['A3]) -> Str)\n//│ where\n//│   'A3 <: 'A2\n\nabstract class Context: Empty | Bind\nmodule Empty extends Context\nclass Bind(name: Str, data: Data, tail: Context) extends Context\nfun find(name: Str, context: Context): Data =\n  if context is\n    Empty then fatal(\"undefined symbol \" ++ name)\n    Bind(name', data, t) then\n      if name' === name then data\n      else find(name, t)\nabstract class Data: ListData | Quote | Symbol | Literal | Builtin | Thunk\nclass ListData(list: List[Data]) extends Data\nclass Quote(data: Data) extends Data\nclass Symbol(name: Str) extends Data\nclass Literal(value: Int) extends Data\nclass Builtin(impl: (List[Data], Context) -> Data) extends Data\nclass Thunk(impl: (Context) -> Data) extends Data\n//│ abstract class Context: Bind | Empty\n//│ module Empty extends Context\n//│ class Bind(name: Str, data: Data, tail: Context) extends Context\n//│ fun find: (name: Str, context: Context) -> Data\n//│ abstract class Data: Builtin | ListData | Literal | Quote | Symbol | Thunk\n//│ class ListData(list: List[Data]) extends Data\n//│ class Quote(data: Data) extends Data\n//│ class Symbol(name: Str) extends Data\n//│ class Literal(value: Int) extends Data\n//│ class Builtin(impl: (List[Data], Context) -> Data) extends Data\n//│ class Thunk(impl: Context -> Data) extends Data\n\nfun showData(data: Data): Str =\n  if data is\n    ListData(list) then \"(\" ++ showList(\" \", showData)(list) ++ \")\"\n    Quote(data) then \"'\" ++ showData(data)\n    Symbol(name) then name\n    Literal(value) then toString(value)\n    Builtin(impl) then \"<builtin>\"\n    Thunk(impl) then \"<thunk>\"\n//│ fun showData: (data: Data) -> Str\n\nfun add(arguments: List[Data], context: Context): Data =\n  if arguments is Cons(Literal(a), Cons(Literal(b), Nil)) then Literal(a + b) else fatal(\"invalid arguments\")\n//│ fun add: (arguments: List[Data], context: Context) -> Data\n\nlet context = Bind(\"+\", Builtin(add), Empty)\n//│ let context: Bind\n//│ context\n//│         = Bind {}\n\nfun eval(program: Data, context: Context): Data =\n  if program is\n    Literal(value) then Literal(value)\n    Symbol(name) then find(name, context)\n    Thunk(impl) then impl(context)\n    ListData(Cons(Symbol(\"let\"), Cons(Symbol(name), Cons(data, Cons(rest, Nil))))) then\n      let data' = eval(data, context)\n      let context' = Bind(name, data', context)\n      eval(rest, context')\n    ListData(Cons(Symbol(\"val\"), Cons(Symbol(name), Cons(data, Cons(rest, Nil))))) then\n      let data' = Thunk((context) => eval(data, context))\n      let context' = Bind(name, data', context)\n      eval(rest, context')\n    ListData(Cons(Symbol(\"if\"), Cons(test, Cons(thenPart, Cons(elsePart, Nil))))) and\n      eval(test, context) is Literal(0) then eval(elsePart, context)\n      else eval(thenPart, context)\n    ListData(Cons(Symbol(\"quote\"), Cons(data, Nil))) then data\n    ListData(Cons(Symbol(callee), arguments)) and\n      let callee' = find(callee, context)\n      let arguments' = map(argument => eval(argument, context), arguments)\n      callee' is Builtin(impl) then impl(arguments', context)\n      else fatal(\"callee is not callable\")\n    else fatal(\"unknown program\")\n//│ fun eval: (program: Data, context: Context) -> Data\n\nlet data1 = ListData of Symbol(\"+\") :: Literal(1) :: Literal(2) :: Nil\nshowData of data1\nshowData of eval(data1, context)\n//│ let data1: ListData\n//│ Str\n//│ data1\n//│       = ListData {}\n//│ res\n//│     = '(+ 1 2)'\n//│ res\n//│     = '3'\n\nlet data2 = ListData of Symbol(\"let\") :: Symbol(\"x\") :: Literal(1) :: (ListData of Symbol(\"+\") :: Symbol(\"x\") :: Literal(2) :: Nil) :: Nil\nshowData of data2\nshowData of eval(data2, context)\n//│ let data2: ListData\n//│ Str\n//│ data2\n//│       = ListData {}\n//│ res\n//│     = '(let x 1 (+ x 2))'\n//│ res\n//│     = '3'\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/SimpleList.mls",
    "content": ":NewDefs\n\nabstract class List[T]: (Cons[T] | Nil)\nclass Cons[T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\n1 :: 2 :: 3 :: 4 :: 5 :: 6 :: 7 :: 8 :: Nil\n//│ Cons['T]\n//│   where\n//│     'T :> 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8\n//│ res\n//│     = Cons {}\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/SimpleTree.mls",
    "content": ":NewDefs\n\n// abstract class Tree[out A]: (Empty | Node[A])\n// class Node[out A](value: A, left: Tree[A], right: Tree[A]) extends Tree[A]\n// module Empty extends Tree\n// //│ abstract class Tree[A]: Empty | Node[A]\n// //│ class Node[A](value: A, left: Tree[A], right: Tree[A]) extends Tree\n// //│ module Empty extends Tree\n\n// fun insert(t, v) = if t is\n//   Node(v', l, r) and\n//     v < v' then Node(v', insert(l, v), r)\n//     v > v' then Node(v', l, insert(r, v))\n//     _ then t\n//   Empty then Node(v, Empty, Empty)\n// //│ fun insert: forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A])\n\nabstract class List[out T]: (Cons[T] | Nil)\nclass Cons[out T](val head: T, val tail: List[T]) extends List[T]\nmodule Nil extends List\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'T. ('T, List['T]) -> Cons['T]\n\n1 :: 2 :: 3 :: 4 :: Nil\n//│ Cons[1 | 2 | 3 | 4]\n//│ res\n//│     = Cons {}\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/examples/ULC.mls",
    "content": ":NewDefs\n\nfun (++) concatOp(a, b) = concat(a)(b)\nfun (|>) pipe(a, f) = f(a)\nfun (!==) notEqual(x, y) = not(x === y)\n//│ fun (++) concatOp: (Str, Str) -> Str\n//│ fun (|>) pipe: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n//│ fun (!==) notEqual: forall 'c. (Eql['c], 'c) -> Bool\n\nfun par(a) = \"(\" ++ a ++ \")\"\n//│ fun par: Str -> Str\n\ndeclare fun String: nothing\n//│ fun String: nothing\n\nlet makeString: anything => { length: Int, charCodeAt: Int => Int } = String\nlet StringInstance: { fromCharCode: Int => Str } = String\n//│ let makeString: anything -> {charCodeAt: Int -> Int, length: Int}\n//│ let StringInstance: {fromCharCode: Int -> Str}\n//│ makeString\n//│            = [Function: String]\n//│ StringInstance\n//│                = [Function: String]\n\nlet anythingToString = toString\nfun fromCharCode(n: Int) = StringInstance.fromCharCode(n)\nfun stringCharCodeAt(s: Str, i) = makeString(s).charCodeAt(i)\nfun stringLength(s: Str) = makeString(s).length\n//│ let anythingToString: anything -> Str\n//│ fun fromCharCode: (n: Int) -> Str\n//│ fun stringCharCodeAt: (s: Str, Int) -> Int\n//│ fun stringLength: (s: Str) -> Int\n//│ anythingToString\n//│                  = [Function: toString]\n\ntype Option[A] = Some[A] | None\nclass Some[A](value: A) {\n  fun toString() = \"Some(\" ++ anythingToString(value) ++ \")\"\n}\nmodule None {\n  fun toString() = \"None\"\n}\nfun showOption(opt) =\n  if opt is\n    Some(x) then \"Some(\" ++ toString(x) ++ \")\"\n    None then \"None\"\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A) {\n//│   fun toString: () -> Str\n//│ }\n//│ module None {\n//│   fun toString: () -> \"None\"\n//│ }\n//│ fun showOption: (None | Some[anything]) -> Str\n\ntype List[A] = Cons[A] | Nil\nclass Cons[A](head: A, tail: List[A])\nmodule Nil\n//│ type List[A] = Cons[A] | Nil\n//│ class Cons[A](head: A, tail: List[A])\n//│ module Nil\n\nfun (::) cons(head, tail) = Cons(head, tail)\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n\nfun join(sep) =\n  let rec aux(acc, xs) =\n    if xs is\n      Nil then acc\n      Cons(x, xs') then aux(acc ++ sep ++ toString(x), xs')\n  (xs) =>\n    if xs is\n      Cons(x, xs') then aux(toString(x), xs')\n      Nil then \"\"\n//│ fun join: Str -> (forall 'A. (Cons['A] | Nil) -> Str)\n\nfun showList(xs) = \"[\" ++ join(\", \")(xs) ++ \"]\"\n//│ fun showList: forall 'A. (Cons['A] | Nil) -> Str\n\nfun findFirst(list, p) =\n  if list is\n    Nil then None\n    Cons(x, xs) and\n      p(x) then Some(x)\n      else findFirst(xs, p)\n//│ fun findFirst: forall 'A 'A0. (Cons['A] | Nil, 'A -> Bool) -> (None | Some['A0])\n//│   where\n//│     'A <: 'A0\n\nfun (:::) listConcat(xs, ys) =\n  if xs is\n    Nil then ys\n    Cons(x, xs') then Cons(x, listConcat(xs', ys))\n//│ fun (:::) listConcat: forall 'A 'A0 'a. (Cons['A] | Nil, List['A0] & 'a) -> (Cons['A0] | 'a)\n//│   where\n//│     'A <: 'A0\n\nfun contains(xs, x) =\n  if xs is\n    Nil then false\n    Cons(x', xs') and\n      x === x' then true\n      else contains(xs', x)\n//│ fun contains: forall 'A. (Cons['A] | Nil, Eql['A]) -> Bool\n\ncontains(\"x\" :: \"y\" :: \"z\" :: Nil, \"y\")\ncontains(\"x\" :: \"y\" :: \"z\" :: Nil, \"w\")\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n\nfun exclude(xs, x) =\n  if xs is\n    Nil then Nil\n    Cons(x', xs') and\n      x === x' then exclude(xs', x)\n      else Cons(x', exclude(xs', x))\n//│ fun exclude: forall 'A 'A0. (Cons['A] | Nil, Eql['A]) -> (Cons['A0] | Nil)\n//│   where\n//│     'A <: 'A0\n\nexclude(\"x\" :: \"y\" :: \"z\" :: Nil, \"y\") |> showList\nexclude(\"x\" :: \"y\" :: \"z\" :: Nil, \"w\") |> showList\n//│ Str\n//│ res\n//│     = '[x, z]'\n//│ res\n//│     = '[x, y, z]'\n\nfun reverse(xs: List['B]): List['B] =\n  let rec aux(acc: List['B], ys: List['B]): List['B] =\n    if ys is\n      Nil then acc\n      Cons(y, ys') then aux(Cons(y, acc), ys')\n  aux(Nil, xs)\n//│ fun reverse: forall 'B 'A. (xs: List['B]) -> List['A]\n//│   where\n//│     'B <: 'A\n\nreverse(1 :: 2 :: 3 :: Nil) |> showList\nreverse(3 :: 2 :: 1 :: Nil) |> showList\n//│ Str\n//│ res\n//│     = '[3, 2, 1]'\n//│ res\n//│     = '[1, 2, 3]'\n\n//  _____\n// |_   _|___  _ __  _ __ ___\n//   | | / _ \\| '__|| '_ ` _ \\\n//   | ||  __/| |   | | | | | |\n//   |_| \\___||_|   |_| |_| |_|\n//\n\ntype Term = Var | Abs | App\nclass Var(name: Str)\nclass Abs(lhs: Var, rhs: Term)\nclass App(lhs: Term, rhs: Term)\n//│ type Term = Abs | App | Var\n//│ class Var(name: Str)\n//│ class Abs(lhs: Var, rhs: Term)\n//│ class App(lhs: Term, rhs: Term)\n\nfun showTerm(t) =\n  if t is\n    Var(name) then toString(name)\n    Abs(lhs, rhs) then \"λ\" ++ showTerm(lhs) ++ \". \" ++ showTerm(rhs)\n    App(Abs(lhs0, lhs1), rhs) then\n      \"((\" ++ \"λ\" ++ showTerm(lhs0) ++ \". \" ++ showTerm(lhs1) ++ \") \" ++ showTerm(rhs) ++ \")\"\n    App(lhs, rhs) then par(showTerm(lhs) ++ \" \" ++ showTerm(rhs))\n//│ fun showTerm: (Abs | App | Var) -> Str\n\nshowTerm(Var(\"x\"))\nshowTerm(Abs(Var(\"x\"), Var(\"y\")))\nshowTerm(App(Var(\"x\"), Var(\"y\")))\nshowTerm(App(Abs(Var(\"x\"), Var(\"y\")), Var(\"z\")))\n//│ Str\n//│ res\n//│     = 'x'\n//│ res\n//│     = 'λx. y'\n//│ res\n//│     = '(x y)'\n//│ res\n//│     = '((λx. y) z)'\n\nfun (=:=) equalTerm(t1: Term, t2: Term) =\n  if t1 is\n    Var(x1)        and t2 is Var(x2)        then x1 === x2\n    Abs(x1, t1')   and t2 is Abs(x2, t2')   then (x1 =:= x2) && (t1' =:= t2')\n    App(t1', t1'') and t2 is App(t2', t2'') then (t1' =:= t2') && (t1'' =:= t2'')\n    else false\n//│ fun (=:=) equalTerm: (t1: Term, t2: Term) -> Bool\n\nVar(\"x\") =:= Var(\"x\")\nVar(\"x\") =:= Var(\"y\")\nAbs(Var(\"x\"), Var(\"x\")) =:= Abs(Var(\"x\"), Var(\"x\"))\nAbs(Var(\"x\"), Var(\"x\")) =:= Abs(Var(\"x\"), Var(\"y\"))\nAbs(Var(\"x\"), Var(\"y\")) =:= Abs(Var(\"x\"), Var(\"x\"))\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n\nfun isValue(t) =\n  if t is\n    Abs then true\n    Var then false\n    App then false\n//│ fun isValue: (Abs | App | Var) -> Bool\n\nisValue(Var(\"x\"))\nisValue(Abs(Var(\"x\"), Var(\"y\")))\nisValue(App(Var(\"x\"), Var(\"y\")))\n//│ Bool\n//│ res\n//│     = false\n//│ res\n//│     = true\n//│ res\n//│     = false\n\nfun hasFree(t, x) =\n  if t is\n    Var(x') then x === x'\n    Abs(Var(x'), body) and x === x' then false\n    Abs(Var(_), body) then hasFree(body, x)\n    App(lhs, rhs) then hasFree(lhs, x) || hasFree(rhs, x)\n    _ then false\n//│ fun hasFree: (Object, Eql[Str]) -> Bool\n\nfun showHasFree(t, n) =\n  showTerm(t) ++ (if hasFree(t, n) then \" has \" else \" DOES NOT have \") ++ \"free variable \" ++ n\n//│ fun showHasFree: (Abs | App | Var, Eql[Str] & Str) -> Str\n\nshowHasFree(Var(\"x\"), \"x\")\nshowHasFree(Var(\"x\"), \"y\")\nshowHasFree(Abs(Var(\"x\"), Var(\"x\")), \"x\")\nshowHasFree(Abs(Var(\"x\"), Var(\"x\")), \"y\")\nshowHasFree(Abs(Var(\"x\"), Var(\"y\")), \"x\")\nshowHasFree(Abs(Var(\"x\"), Var(\"y\")), \"y\")\nshowHasFree(App(Var(\"x\"), Var(\"y\")), \"x\")\nshowHasFree(App(Var(\"x\"), Var(\"y\")), \"y\")\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"x\")\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"y\")\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"y\")), \"y\")\nshowHasFree(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"y\")\n//│ Str\n//│ res\n//│     = 'x has free variable x'\n//│ res\n//│     = 'x DOES NOT have free variable y'\n//│ res\n//│     = 'λx. x DOES NOT have free variable x'\n//│ res\n//│     = 'λx. x DOES NOT have free variable y'\n//│ res\n//│     = 'λx. y DOES NOT have free variable x'\n//│ res\n//│     = 'λx. y has free variable y'\n//│ res\n//│     = '(x y) has free variable x'\n//│ res\n//│     = '(x y) has free variable y'\n//│ res\n//│     = '((λx. x) x) has free variable x'\n//│ res\n//│     = '((λx. x) x) DOES NOT have free variable y'\n//│ res\n//│     = '((λx. x) y) has free variable y'\n//│ res\n//│     = '((λx. x) x) DOES NOT have free variable y'\n\nfun freeVars(t) =\n  if t is\n    Var(x) then x :: Nil\n    Abs(Var(x), body) then exclude(freeVars(body), x)\n    App(lhs, rhs) then freeVars(lhs) ::: freeVars(rhs)\n//│ fun freeVars: forall 'A. (Abs | App | Var) -> (Cons['A] | Nil)\n//│   where\n//│     'A :> Str\n\n(freeVars of Var(\"x\")) |> showList\n(freeVars of Abs(Var(\"x\"), Var(\"x\"))) |> showList\n(freeVars of Abs(Var(\"x\"), Var(\"y\"))) |> showList\n(freeVars of App(Var(\"x\"), Var(\"y\"))) |> showList\n(freeVars of App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\"))) |> showList\n//│ Str\n//│ res\n//│     = '[x]'\n//│ res\n//│     = '[]'\n//│ res\n//│     = '[y]'\n//│ res\n//│     = '[x, y]'\n//│ res\n//│     = '[x]'\n\nlet alphabet: List[Str] = \"a\" :: \"b\" :: \"c\" :: \"d\" :: \"e\" :: \"f\" :: \"g\" :: \"h\" :: \"i\" :: \"j\" :: \"k\" :: \"l\" :: \"m\" :: \"n\" :: \"o\" :: \"p\" :: \"q\" :: \"r\" :: \"s\" :: \"t\" :: \"u\" :: \"v\" :: \"w\" :: \"x\" :: \"y\" :: \"z\" :: Nil\n//│ let alphabet: List[Str]\n//│ alphabet\n//│          = Cons {}\n\nfun search(f: 'A -> Option['B], xs: List['A]): Option['B] =\n  if xs is\n    Nil then None\n    Cons(x, xs') and\n      f(x) is\n        Some(x') then Some(x')\n        None then search(f, xs')\n//│ fun search: forall 'A 'B 'A0. (f: 'A -> Option['B], xs: List['A]) -> Option['A0]\n//│   where\n//│     'B <: 'A0\n\n// =============================================================================\n// TO BE INVESTIGATED: The following version does not have a stable type.\n// The desugared term look like this:\n// let ucs$test$0 = <=(n, 0,) : Bool in\n// case ucs$test$0 of {\n//   true =>\n//     let x = |>(reverse(acc,), join(\"\",),) in\n//     let ucs$test$1 = contains(xs, x,) : Bool in\n//     case ucs$test$1 of {\n//       true => None;\n//       _ => Some(x,)\n//     };\n//   _ => {\n//     search(('(' x ')',) => combinations(-(n, 1,), ::(x, acc,), alphabet, xs,), alphabet,)\n//   }\n// }\n// fun combinations(n: Int, acc: List['T], alphabet: List['T], xs: List[Str]): Option[Str] =\n//   if\n//     n <= 0 and\n//       let x = reverse(acc) |> join(\"\")\n//       contains(xs, x) then None\n//       else Some(x)\n//     else\n//       search((x) => combinations(n - 1, x :: acc, alphabet, xs), alphabet)\n// //│ fun combinations: forall 'T 'A 'T0. (n: Int, acc: List['T], alphabet: List['T0], xs: List[Str]) -> Option[Str]\n// //│   where\n// //│     'T0 <: 'T & 'A\n// //│     'T :> 'A\n// //│     'A := 'T\n// =============================================================================\n\nfun combinations: forall 'a: (Int, List['a], List['a], List[Str]) -> Option[Str]\nfun combinations(n: Int, acc: List['T], alphabet: List['T], xs: List[Str]): Option[Str] =\n  if n <= 0 then\n    let x = reverse(acc) |> join(\"\")\n    if contains(xs, x) then None else Some(x)\n  else\n    search((x) => combinations(n - 1, x :: acc, alphabet, xs), alphabet)\n//│ fun combinations: forall 'T. (n: Int, acc: List['T], alphabet: List['T], xs: List[Str]) -> Option[Str]\n//│ fun combinations: forall 'a. (Int, List['a], List['a], List[Str]) -> Option[Str]\n\ncombinations(1, Nil, 1 :: 2 :: 3 :: Nil, Nil) |> showOption\ncombinations(2, Nil, 1 :: 2 :: 3 :: Nil, Nil) |> showOption\ncombinations(3, Nil, 1 :: 2 :: 3 :: Nil, Nil) |> showOption\ncombinations(1, Nil, 1 :: 2 :: 3 :: Nil, \"1\" :: \"3\" :: Nil) |> showOption\ncombinations(2, Nil, 1 :: 2 :: 3 :: Nil, \"11\" :: \"12\" :: \"13\" :: Nil) |> showOption\ncombinations(3, Nil, 1 :: 2 :: 3 :: Nil, \"111\" :: \"112\" :: \"113\" :: \"121\" :: Nil) |> showOption\n//│ Str\n//│ res\n//│     = 'Some(1)'\n//│ res\n//│     = 'Some(11)'\n//│ res\n//│     = 'Some(111)'\n//│ res\n//│     = 'Some(2)'\n//│ res\n//│     = 'Some(21)'\n//│ res\n//│     = 'Some(122)'\n\nfun freshVar(t: Term): Str =\n  let fvs = freeVars(t)\n  let rec aux(n: Int): Str =\n    if combinations(n, Nil, alphabet, fvs) is\n      Some(x) then x\n      None then aux(n + 1)\n  aux(1)\n//│ fun freshVar: (t: Term) -> Str\n\nfreshVar(Var(\"x\"))\nfreshVar(App(Var(\"a\"), Var(\"b\")))\nfreshVar(App(Abs(Var(\"a\"), Var(\"a\")), Var(\"b\")))\n//│ Str\n//│ res\n//│     = 'a'\n//│ res\n//│     = 'c'\n//│ res\n//│     = 'a'\n\nfun subst(t: Term, x: Str, v: Term): Term =\n  if t is\n    Var(y) and x === y then v\n    Abs(Var(y), t') and x !== y and\n      hasFree(v, y) then\n        let y' = freshVar(t')\n        let t'' = subst(t', y, Var(y'))\n        Abs(Var(y'), subst(t'', x, v))\n      else\n        Abs(Var(y), subst(t', x, v))\n    App(lhs, rhs) then App(subst(lhs, x, v), subst(rhs, x, v))\n    else t\n//│ fun subst: (t: Term, x: Str, v: Term) -> Term\n\nfun showSubst(t, n, v) =\n  showTerm(t) ++ \" [\" ++ n ++ \" / \" ++ showTerm(v) ++ \"]\" ++ \" = \" ++ showTerm(subst(t, n, v))\n//│ fun showSubst: (Abs & Term | App & Term | Var & Term, Str, Abs & Term | App & Term | Var & Term) -> Str\n\nshowSubst(Var(\"x\"), \"x\", Var(\"y\"))\nshowSubst(Abs(Var(\"x\"), Var(\"x\")), \"x\", Var(\"z\"))\nshowSubst(App(Var(\"x\"), Var(\"y\")), \"x\", Abs(Var(\"x\"), Var(\"x\")))\nshowSubst(App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\")), \"x\", Abs(Var(\"y\"), Var(\"y\")))\nshowSubst(Abs(Var(\"x\"), App(Var(\"x\"), Var(\"y\"))), \"y\", Var(\"x\"))\nshowSubst(Abs(Var(\"z\"), Abs(Var(\"x\"), App(Var(\"z\"), App(Var(\"x\"), Var(\"y\"))))), \"y\", Var(\"x\"))\nshowSubst(Abs(Var(\"z\"), Abs(Var(\"x\"), App(Var(\"z\"), App(Var(\"x\"), Var(\"y\"))))), \"y\", App(Var(\"x\"), Var(\"z\")))\n//│ Str\n//│ res\n//│     = 'x [x / y] = y'\n//│ res\n//│     = 'λx. x [x / z] = λx. x'\n//│ res\n//│     = '(x y) [x / λx. x] = ((λx. x) y)'\n//│ res\n//│     = '((λx. x) x) [x / λy. y] = ((λx. x) λy. y)'\n//│ res\n//│     = 'λx. (x y) [y / x] = λa. (a x)'\n//│ res\n//│     = 'λz. λx. (z (x y)) [y / x] = λz. λa. (z (a x))'\n//│ res\n//│     = 'λz. λx. (z (x y)) [y / (x z)] = λa. λb. (a (b (x z)))'\n\n//  ____                     _  _   ____   _\n// / ___|  _ __ ___    __ _ | || | / ___| | |_  ___  _ __\n// \\___ \\ | '_ ` _ \\  / _` || || | \\___ \\ | __|/ _ \\| '_ \\\n//  ___) || | | | | || (_| || || |  ___) || |_|  __/| |_) |\n// |____/ |_| |_| |_| \\__,_||_||_| |____/  \\__|\\___|| .__/\n//                                                  |_|\n\ntype Result = Normal | Stuck | Stepped\nclass Normal(term: Term) {\n  fun toString() = \"Normal form: \" ++ showTerm(term)\n}\nclass Stuck(term: Term, part: Term) {\n  fun toString() = \"Stuck: \" ++ showTerm(part) ++ \" in \" ++ showTerm(term)\n}\nclass Stepped(from: Term, to: Term) {\n  fun toString() = showTerm(from) ++ \" => \" ++ showTerm(to)\n}\n//│ type Result = Normal | Stepped | Stuck\n//│ class Normal(term: Term) {\n//│   fun toString: () -> Str\n//│ }\n//│ class Stuck(term: Term, part: Term) {\n//│   fun toString: () -> Str\n//│ }\n//│ class Stepped(from: Term, to: Term) {\n//│   fun toString: () -> Str\n//│ }\n\nfun stepByValue(t) =\n  if t is\n    Var then Stuck(t, t)\n    Abs then Normal(t)\n    App(lhs, rhs) and stepByValue(lhs) is\n      Stepped(_, lhs) then Stepped(t, App(lhs, rhs))\n      Stuck(_, part) then Stuck(t, part)\n      Normal and stepByValue(rhs) is\n        Stepped(_, rhs) then Stepped(t, App(lhs, rhs))\n        Stuck(_, part) then Stuck(t, part)\n        Normal and lhs is\n          Abs(Var(name), body) then Stepped(t, subst(body, name, rhs))\n          _ then Stuck(t, lhs)\n//│ fun stepByValue: (Abs | App | Var) -> (Normal | Stepped | Stuck)\n\ntoString of stepByValue of Var(\"x\")\ntoString of stepByValue of Abs(Var(\"x\"), Var(\"y\"))\ntoString of stepByValue of App(Var(\"x\"), Var(\"y\"))\ntoString of stepByValue of App(Abs(Var(\"x\"), Var(\"x\")), Var(\"x\"))\ntoString of stepByValue of App(Abs(Var(\"x\"), Var(\"x\")), Abs(Var(\"y\"), Var(\"y\")))\n//│ Str\n//│ res\n//│     = 'Stuck: x in x'\n//│ res\n//│     = 'Normal form: λx. y'\n//│ res\n//│     = 'Stuck: x in (x y)'\n//│ res\n//│     = 'Stuck: x in ((λx. x) x)'\n//│ res\n//│     = '((λx. x) λy. y) => λy. y'\n\n//  _____               _                _    _\n// | ____|__   __ __ _ | | _   _   __ _ | |_ (_)  ___   _ __\n// |  _|  \\ \\ / // _` || || | | | / _` || __|| | / _ \\ | '_ \\\n// | |___  \\ V /| (_| || || |_| || (_| || |_ | || (_) || | | |\n// |_____|  \\_/  \\__,_||_| \\__,_| \\__,_| \\__||_| \\___/ |_| |_|\n//\n\nfun eval(step) =\n  let rec aux(t) =\n    if step(t) is result and result is\n      Stepped(_, t') then aux(t')\n      else result\n  aux\n//│ fun eval: forall 'a 'b. ((Term | 'a) -> (Object & 'b & ~#Stepped | Stepped)) -> 'a -> 'b\n\nlet evalByValue = eval(stepByValue)\n//│ let evalByValue: (Abs | App | Var) -> (Normal | Stuck)\n//│ evalByValue\n//│             = [Function: aux]\n\n// Let's program with Church encoding!\nlet zero = Abs(Var(\"f\"), Abs(Var(\"x\"), Var(\"x\")))\nlet one = Abs(Var(\"f\"), Abs(Var(\"x\"), App(Var(\"f\"), Var(\"x\"))))\ntoString of stepByValue of zero\ntoString of stepByValue of one\nlet succ = Abs(Var(\"n\"), Abs(Var(\"f\"), Abs(Var(\"x\"), App(Var(\"f\"), App(App(Var(\"n\"), Var(\"f\")), Var(\"x\"))))))\ntoString of stepByValue of succ\ntoString of stepByValue of App(succ, zero)\n//│ let zero: Abs\n//│ let one: Abs\n//│ let succ: Abs\n//│ Str\n//│ zero\n//│      = Abs {}\n//│ one\n//│     = Abs {}\n//│ res\n//│     = 'Normal form: λf. λx. x'\n//│ res\n//│     = 'Normal form: λf. λx. (f x)'\n//│ succ\n//│      = Abs {}\n//│ res\n//│     = 'Normal form: λn. λf. λx. (f ((n f) x))'\n//│ res\n//│     = '((λn. λf. λx. (f ((n f) x))) λf. λx. x) => λf. λx. (f (((λf. λx. x) f) x))'\n\ntoString of evalByValue of App(succ, App(succ, zero))\ntoString of evalByValue of App(succ, App(succ, App(succ, App(succ, zero))))\n//│ Str\n//│ res\n//│     = 'Normal form: λf. λx. (f (((λf. λx. (f (((λf. λx. x) f) x))) f) x))'\n//│ res\n//│     = 'Normal form: λf. λx. (f (((λf. λx. (f (((λf. λx. (f (((λf. λx. (f (((λf. λx. x) f) x))) f) x))) f) x))) f) x))'\n\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/patterns/AliasPattern.mls",
    "content": ":NewDefs\n\nabstract class Option[out A]\nclass Some[out A](val value: A) extends Option[A]\nmodule None extends Option[nothing]\n//│ abstract class Option[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\n:ducs:postprocess.result\nfun map(f) = case\n  Some(x)   then Some(f(x))\n  None as n then n\n//│ Post-processed UCS term:\n//│ case case$scrut*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_case$scrut$Some*† = (Some).unapply(case$scrut,)\n//│     let x*‡ = (ucs$args_case$scrut$Some).0\n//│     Some(f(x,),)\n//│   None*† ->\n//│     let n*† = case$scrut\n//│     n\n//│ fun map: forall 'a 'A. ('a -> 'A) -> (None | Some['a]) -> (None | Some['A])\n\n:ducs:postprocess.result\nfun map(f) = case\n  Some(x as n) then Some of f(n)\n  None as n then n\n//│ Post-processed UCS term:\n//│ case case$scrut*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_case$scrut$Some*† = (Some).unapply(case$scrut,)\n//│     let x*‡ = (ucs$args_case$scrut$Some).0\n//│     let n*‡ = x\n//│     Some(f(n,),)\n//│   None*† ->\n//│     let n*† = case$scrut\n//│     n\n//│ fun map: forall 'a 'A. ('a -> 'A) -> (None | Some['a]) -> (None | Some['A])\n\n:ducs:postprocess.result\nfun foo = case\n  Some(Some(a as b) as c) as d then [a, b, c, d]\n//│ Post-processed UCS term:\n//│ let d*† = case$scrut\n//│ case case$scrut*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_case$scrut$Some*† = (Some).unapply(case$scrut,)\n//│     let case$scrut$Some_0*‡ = (ucs$args_case$scrut$Some).0\n//│     case case$scrut$Some_0*‡ of\n//│       Some*◊ ->\n//│         let ucs$args_case$scrut$Some_0$Some*† = (Some).unapply(case$scrut$Some_0,)\n//│         let a*‡ = (ucs$args_case$scrut$Some_0$Some).0\n//│         let b*‡ = a\n//│         let c*‡ = case$scrut$Some_0\n//│         [a, b, c, d,]\n//│ fun foo: forall 'A 'a. (Some[Some['A]] & 'a) -> ['A, 'A, Some['A], 'a]\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/patterns/Literals.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\nclass Pair[A, B](x: A, y: B)\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n//│ class Pair[A, B](x: A, y: B)\n\nfun f(x) = if x is Some(1) then true else false\n//│ fun f: (Object & ~#Some | Some[Object]) -> Bool\n\n[f(Some(1)), f(None), f(Some(2)), f(Some(-1))]\n//│ [Bool, Bool, Bool, Bool]\n//│ res\n//│     = [ true, false, false, false ]\n\nfun f(x) = if x is Some(1) then true\n//│ fun f: Some[1] -> true\n\nfun f(x) = if x is\n  Some(1) then true\n  Some(2) then false\n//│ fun f: Some[1 | 2] -> Bool\n\n[f(Some(1)), f(Some(2))]\n//│ [Bool, Bool]\n//│ res\n//│     = [ true, false ]\n\nfun g(x) = if x then 1 else 2\n//│ fun g: Bool -> (1 | 2)\n\n:e\nfun test_must_be_boolean(x) = if 0 then 1 else 2\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.37: \tfun test_must_be_boolean(x) = if 0 then 1 else 2\n//│ ║        \t                                 ^\n//│ ╙── integer literal of type `0` is not an instance of type `Bool`\n//│ fun test_must_be_boolean: anything -> (1 | 2)\n\nfun g(x) = if x is true then 1 else 2\n//│ fun g: Object -> (1 | 2)\n\n[g(true), g(false), g(None)]\n//│ [1 | 2, 1 | 2, 1 | 2]\n//│ res\n//│     = [ 1, 2, 2 ]\n\nfun g(x) = if x && true is true then 1 else 2\n//│ fun g: Bool -> (1 | 2)\n\nfun h(x) = if (x : Bool) then 1 else 2\n//│ fun h: Bool -> (1 | 2)\n\n// Currently post-processing cannot handle this case. The desugared term is not\n// perfect. Also, is the inferred type wrong?\nfun mix(x) = if x is\n  true then \"true\"\n  Some(value) then \"Some\"\n  0 then \"zero\"\n//│ fun mix: (0 | Some[anything] | true) -> (\"Some\" | \"true\" | \"zero\")\n\n[mix(true), mix(Some(1)), mix(0)]\n//│ [\"Some\" | \"true\" | \"zero\", \"Some\" | \"true\" | \"zero\", \"Some\" | \"true\" | \"zero\"]\n//│ res\n//│     = [ 'true', 'Some', 'zero' ]\n\n:e\n[mix(false), mix(None)]\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.72: \t[mix(false), mix(None)]\n//│ ║        \t ^^^^^^^^^^\n//│ ╟── reference of type `false` does not match type `0 | Some[?T] | true`\n//│ ║  l.72: \t[mix(false), mix(None)]\n//│ ║        \t     ^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.60: \tfun mix(x) = if x is\n//│ ╙──      \t                ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.72: \t[mix(false), mix(None)]\n//│ ║        \t             ^^^^^^^^^\n//│ ╟── reference of type `None` does not match type `0 | Some[?T] | true`\n//│ ║  l.72: \t[mix(false), mix(None)]\n//│ ║        \t                 ^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.60: \tfun mix(x) = if x is\n//│ ╙──      \t                ^\n//│ [\"Some\" | \"true\" | \"zero\" | error, \"Some\" | \"true\" | \"zero\" | error]\n//│ res\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\nfun string_literals(x) =\n  if x is\n    \"foo\" then 0\n    \"bar\" then 1\n    \"qax\" then 2\n//│ fun string_literals: (\"bar\" | \"foo\" | \"qax\") -> (0 | 1 | 2)\n\nclass Foo\n//│ class Foo {\n//│   constructor()\n//│ }\n\nfun mixed_patterns(x) =\n  if x is\n    Foo then 1\n    23 then 2\n    \"test\" then 3\n//│ fun mixed_patterns: (\"test\" | 23 | Foo) -> (1 | 2 | 3)\n\nfun bool_patterns(x) =\n  if x is\n    true then 1\n    false then 2\n//│ fun bool_patterns: Bool -> (1 | 2)\n\nfun dual_patterns(x, y) =\n  if\n    x is \"some\" and y is \"none\" then 0\n    x is \"none\" and y is \"some\" then 1\n    x is \"some\" and y is \"some\" then 2\n    x is \"none\" and y is \"none\" then 3\n//│ fun dual_patterns: (\"none\" | \"some\", \"none\" | \"some\") -> (0 | 1 | 2 | 3)\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/patterns/SimpleTuple.mls",
    "content": ":NewDefs\n\n// We test the support for simple tuple patterns in this file.\n// Splice tuple patterns will be implement in the future.\n\nfun sum(x, y) = x + y\nsum(1, 2)\n//│ fun sum: (Int, Int) -> Int\n//│ Int\n//│ res\n//│     = 3\n\nfun sum'([x, y]) = x + y\nsum'([1, 2])\n//│ fun sum': ([Int, Int]) -> Int\n//│ Int\n//│ res\n//│     = 3\n\nfun sum''(pair) =\n  if pair is [x, y] then x + y\nsum'([1, 2])\n//│ fun sum'': {0: Int, 1: Int} -> Int\n//│ Int\n//│ res\n//│     = 3\n\n// We need native support for tuple patterns in MLscript syntax.\n// Otherwise the following cases work.\n\nfun test(thing) =\n  if thing is [] then 0\ntest(\"\")\ntest(12)\n//│ fun test: anything -> 0\n//│ 0\n//│ res\n//│     = 0\n//│ res\n//│     = 0\n\n:w\n// Since pattern destruction is desugared to let bindings, matching with other\n// classes after the tuple pattern will not work.\nclass Point(x: Int, y: Int)\nfun discarded_cases(thing) =\n  if thing is\n    [x, y] then x + y\n    Point(x, y) then x + y\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.47: \t  if thing is\n//│ ║        \t     ^^^^^^^^\n//│ ║  l.48: \t    [x, y] then x + y\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.49: \t    Point(x, y) then x + y\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.48: \t    [x, y] then x + y\n//│ ╙──      \t                ^^^^^\n//│ class Point(x: Int, y: Int)\n//│ fun discarded_cases: {0: Int, 1: Int} -> Int\n\n:e\ndiscarded_cases(Point(0, 0))\n//│ ╔══[ERROR] Type `Point` does not contain member `1`\n//│ ║  l.48: \t    [x, y] then x + y\n//│ ╙──      \t        ^\n//│ Int | error\n//│ res\n//│     = NaN\n\n// A workaround is to move the tuple pattern to the last case.\nfun working_cases(thing) =\n  if thing is\n    Point(x, y) then x + y\n    [x, y] then x + y\n//│ fun working_cases: (Object & {0: Int, 1: Int} & ~#Point | Point) -> Int\n\nworking_cases(Point(0, 0))\n//│ Int\n//│ res\n//│     = 0\n\n// However, the `Object` type forbids tuples to be used.\n:e\nworking_cases([0, 0])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.86: \tworking_cases([0, 0])\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `[0, 0]` is not an instance of type `Object`\n//│ ║  l.86: \tworking_cases([0, 0])\n//│ ║        \t              ^^^^^^\n//│ ╟── Note: constraint arises from `case` expression:\n//│ ║  l.74: \t  if thing is\n//│ ║        \t     ^^^^^^^^\n//│ ║  l.75: \t    Point(x, y) then x + y\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.76: \t    [x, y] then x + y\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.74: \t  if thing is\n//│ ╙──      \t     ^^^^^\n//│ Int | error\n//│ res\n//│     = 0\n\n:w\nfun not_working(x) =\n  if x is\n    [a, b, c] then\n      a + b + c\n    else\n      0\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.113: \t      0\n//│ ║         \t      ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.111: \t      a + b + c\n//│ ╙──       \t      ^^^^^^^^^\n//│ fun not_working: {0: Int, 1: Int, 2: Int} -> Int\n\nnot_working([1, 2, 3])\n//│ Int\n//│ res\n//│     = 6\n\n:e\nnot_working([1, 2])\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.128: \tnot_working([1, 2])\n//│ ║         \t^^^^^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `{0: 1, 1: 2}` does not have field '2'\n//│ ║  l.128: \tnot_working([1, 2])\n//│ ║         \t            ^^^^^^\n//│ ╟── Note: constraint arises from field selection:\n//│ ║  l.109: \t  if x is\n//│ ║         \t     ^^^^\n//│ ║  l.110: \t    [a, b, c] then\n//│ ║         \t^^^^^^^^^^^^\n//│ ╟── from reference:\n//│ ║  l.109: \t  if x is\n//│ ╙──       \t     ^\n//│ Int | error\n//│ res\n//│     = NaN\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/stages/Normalization.mls",
    "content": ":NewDefs\n\nabstract class Option[out T]: Some[T] | None\nclass Some[out T](value: T) extends Option[T]\nmodule None extends Option[nothing]\n//│ abstract class Option[T]: None | Some[T]\n//│ class Some[T](value: T) extends Option\n//│ module None extends Option\n\nabstract class List[out T]: Cons[T] | Nil\nclass Cons[out T](head: T, tail: List[T]) extends List[T]\nmodule Nil extends List[nothing]\n//│ abstract class List[T]: Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T]) extends List\n//│ module Nil extends List\n\nfun sum(acc, xs) = \n  if xs is\n    Cons(x, xs) then sum(acc + x, xs)\n    Nil then acc\n//│ fun sum: (Int, Cons[Int] | Nil) -> Int\n\n:ducs:postprocess.result\nfun test(xs) =\n  if xs is\n    Some(Cons(\"add\", Cons(x, Cons(y, Nil)))) then x + y\n    Some(Cons(\"mul\", Cons(x, Cons(y, Nil)))) then x * y\n    Some(Cons(\"sum\", xs)) then sum(0, xs)\n    Some(Nil) then \"nothing\"\n    None then \"nothing\"\n//│ Post-processed UCS term:\n//│ case xs*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_xs$Some*† = (Some).unapply(xs,)\n//│     let xs$Some_0*‡ = (ucs$args_xs$Some).0\n//│     case xs$Some_0*‡ of\n//│       Cons*◊ ->\n//│         let ucs$args_xs$Some_0$Cons*† = (Cons).unapply(xs$Some_0,)\n//│         let xs$Some_0$Cons_0*‡ = (ucs$args_xs$Some_0$Cons).0\n//│         let xs$Some_0$Cons_1*‡ = (ucs$args_xs$Some_0$Cons).1\n//│         case xs$Some_0$Cons_0*‡ of\n//│           \"add\" ->\n//│             case xs$Some_0$Cons_1*‡ of\n//│               Cons*◊ ->\n//│                 let ucs$args_xs$Some_0$Cons_1$Cons*† = (Cons).unapply(xs$Some_0$Cons_1,)\n//│                 let x*‡ = (ucs$args_xs$Some_0$Cons_1$Cons).0\n//│                 let xs$Some_0$Cons_1$Cons_1*‡ = (ucs$args_xs$Some_0$Cons_1$Cons).1\n//│                 case xs$Some_0$Cons_1$Cons_1*‡ of\n//│                   Cons*◊ ->\n//│                     let ucs$args_xs$Some_0$Cons_1$Cons_1$Cons*† = (Cons).unapply(xs$Some_0$Cons_1$Cons_1,)\n//│                     let y*‡ = (ucs$args_xs$Some_0$Cons_1$Cons_1$Cons).0\n//│                     let xs$Some_0$Cons_1$Cons_1$Cons_1*‡ = (ucs$args_xs$Some_0$Cons_1$Cons_1$Cons).1\n//│                     case xs$Some_0$Cons_1$Cons_1$Cons_1*‡ of\n//│                       Nil*† -> +(x, y,)\n//│                       _ -> (ucs$args_xs$Some_0$Cons).1\n//│                   _ -> (ucs$args_xs$Some_0$Cons).1\n//│               _ -> (ucs$args_xs$Some_0$Cons).1\n//│           \"sum\" ->\n//│             let xs*‡ = (ucs$args_xs$Some_0$Cons).1\n//│             sum(0, xs,)\n//│           \"mul\" ->\n//│             case xs$Some_0$Cons_1*‡ of\n//│               Cons*◊ ->\n//│                 let ucs$args_xs$Some_0$Cons_1$Cons*† = (Cons).unapply(xs$Some_0$Cons_1,)\n//│                 let x*‡ = (ucs$args_xs$Some_0$Cons_1$Cons).0\n//│                 let xs$Some_0$Cons_1$Cons_1*‡ = (ucs$args_xs$Some_0$Cons_1$Cons).1\n//│                 case xs$Some_0$Cons_1$Cons_1*‡ of\n//│                   Cons*◊ ->\n//│                     let ucs$args_xs$Some_0$Cons_1$Cons_1$Cons*† = (Cons).unapply(xs$Some_0$Cons_1$Cons_1,)\n//│                     let y*‡ = (ucs$args_xs$Some_0$Cons_1$Cons_1$Cons).0\n//│                     let xs$Some_0$Cons_1$Cons_1$Cons_1*‡ = (ucs$args_xs$Some_0$Cons_1$Cons_1$Cons).1\n//│                     case xs$Some_0$Cons_1$Cons_1$Cons_1*‡ of\n//│                       Nil*† -> *(x, y,)\n//│                       _ -> (ucs$args_xs$Some_0$Cons).1\n//│                   _ -> (ucs$args_xs$Some_0$Cons).1\n//│               _ -> (ucs$args_xs$Some_0$Cons).1\n//│       Nil*† -> \"nothing\"\n//│   None*† -> \"nothing\"\n//│ fun test: (None | Some[Cons[nothing] | Nil]) -> (\"nothing\" | Int | List[nothing])\n\n:ducs:postprocess.result\nfun test(x, p) = if x is\n  Int and p(x) then \"foo\"\n  0 then \"bar\"\n  else \"qax\"\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined Int*◊ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> \"foo\"\n//│       _ ->\n//│         case x*‡ of\n//│           0 -> \"bar\"\n//│           _ -> \"qax\"\n//│   _ -> \"qax\"\n//│ fun test: forall 'a. (Int & 'a | Object & ~Int, (Int & 'a) -> Bool) -> (\"bar\" | \"foo\" | \"qax\")\n\n:ducs:postprocess.result\nfun test(x, p) = if x is\n  Str and p(x) then \"foo\"\n  \"lol\" then \"bar\"\n  else \"qax\"\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined Str*◊ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> \"foo\"\n//│       _ ->\n//│         case x*‡ of\n//│           \"lol\" -> \"bar\"\n//│           _ -> \"qax\"\n//│   _ -> \"qax\"\n//│ fun test: forall 'a. (Object & ~Str | Str & 'a, (Str & 'a) -> Bool) -> (\"bar\" | \"foo\" | \"qax\")\n\ntest(0, _ => true)\n//│ \"bar\" | \"foo\" | \"qax\"\n//│ res\n//│     = 'qax'\n\n:ducs:postprocess.result\nfun test(x, p) = if x is\n  Num and p(x) then \"great\"\n  2.71828 then \"E\"\n  3.14159 then \"PI\"\n  else \"other\"\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined Num*◊ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> \"great\"\n//│       _ ->\n//│         case x*‡ of\n//│           2.71828 -> \"E\"\n//│           3.14159 -> \"PI\"\n//│           _ -> \"other\"\n//│   _ -> \"other\"\n//│ fun test: forall 'a. (Object & ~Num | 'a & (2.71828 | 3.14159 | Num & ~2.71828 & ~3.14159), (Num & 'a) -> Bool) -> (\"E\" | \"PI\" | \"great\" | \"other\")\n\n:ducs:postprocess.result\nfun test(x, p) = if x is\n  Bool and p(x) then \"great\"\n  true then \"false\"\n  false then \"true\"\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined Bool*◊ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> \"great\"\n//│       _ ->\n//│         case x*‡ of\n//│           true*† -> \"false\"\n//│           false*† -> \"true\"\n//│ fun test: forall 'a. ('a & Bool, (Bool & 'a) -> Bool) -> (\"false\" | \"great\" | \"true\")\n\n:ducs:postprocess.result\n:ge\nfun test(x, p) = if x is\n  Object and p(x) then \"great\"\n  Bool and p(x) then \"great, again\"\n  true then \"false\"\n  false then \"true\"\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   refined Object*◊ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> \"great\"\n//│       _ ->\n//│         case x*‡ of\n//│           refined Bool*◊ ->\n//│             let ucs$test$1*† = p(x,) : Bool\n//│             case ucs$test$1*† of\n//│               true*† -> \"great, again\"\n//│               _ ->\n//│                 case x*‡ of\n//│                   true*† -> \"false\"\n//│                   false*† -> \"true\"\n//│ fun test: forall 'a. ('a & Bool, (Object & 'a) -> Bool) -> (\"false\" | \"great\" | \"great, again\" | \"true\")\n//│ Code generation encountered an error:\n//│   unknown match case: Object\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/stages/PostProcessing.mls",
    "content": ":NewDefs\n\n:ducs:postprocess.result,desugared\nfun mixed_literals(v) =\n  if v is\n    true then \"true\"\n    false then \"false\"\n    1 then \"1\"\n    2 then \"2\"\n//│ Post-processed UCS term:\n//│ case v*‡ of\n//│   true*† -> \"true\"\n//│   2 -> \"2\"\n//│   1 -> \"1\"\n//│   false*† -> \"false\"\n//│ Desugared term: case v of { true => \"true\"; 2 => \"2\"; 1 => \"1\"; false => \"false\" }\n//│ fun mixed_literals: (1 | 2 | false | true) -> (\"1\" | \"2\" | \"false\" | \"true\")\n\n:ducs:postprocess.result\nfun separated_by_and(v) =\n  if v is\n    true then \"true\"\n    _ and v is\n      false then \"false\"\n//│ Post-processed UCS term:\n//│ case v*‡ of\n//│   true*† -> \"true\"\n//│   false*† -> \"false\"\n//│ fun separated_by_and: Bool -> (\"false\" | \"true\")\n\n:ducs:postprocess.result\nfun dual_patterns(x, y) =\n  if\n    x is \"some\" and y is \"none\" then 0\n    x is \"none\" and y is \"some\" then 1\n    x is \"some\" and y is \"some\" then 2\n    x is \"none\" and y is \"none\" then 3\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   \"some\" ->\n//│     case y*‡ of\n//│       \"none\" -> 0\n//│       \"some\" -> 2\n//│   \"none\" ->\n//│     case y*‡ of\n//│       \"some\" -> 1\n//│       \"none\" -> 3\n//│ fun dual_patterns: (\"none\" | \"some\", \"none\" | \"some\") -> (0 | 1 | 2 | 3)\n\n:ducs:postprocess.result\nfun unordered_dual_patterns(x, y) =\n  if\n    x is \"some\" and y is \"none\" then 0\n    y is \"some\" and x is \"none\" then 1\n    y is \"some\" and x is \"some\" then 2\n    x is \"none\" and y is \"none\" then 3\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   \"some\" ->\n//│     case y*‡ of\n//│       \"none\" -> 0\n//│       \"some\" -> 2\n//│   \"none\" ->\n//│     case y*‡ of\n//│       \"some\" -> 1\n//│       \"none\" -> 3\n//│ fun unordered_dual_patterns: (\"none\" | \"some\", \"none\" | \"some\") -> (0 | 1 | 2 | 3)\n"
  },
  {
    "path": "shared/src/test/diff/pretyper/ucs/stages/Transformation.mls",
    "content": ":NewDefs\n\nclass Some[T](value: T)\nmodule None\ntype Option[T] = Some[T] | None\n//│ class Some[T](value: T)\n//│ module None\n//│ type Option[T] = None | Some[T]\n\nclass Cons[T](head: T, tail: List[T])\nmodule Nil\ntype List[T] = Cons[T] | Nil\n//│ class Cons[T](head: T, tail: List[T])\n//│ module Nil\n//│ type List[T] = Cons[T] | Nil\n\nabstract class Either[out A, out B]\nclass Left[out A, out B](value: A) extends Either[A, B]\nclass Right[out A, out B](value: B) extends Either[A, B]\n//│ abstract class Either[A, B]\n//│ class Left[A, B](value: A) extends Either\n//│ class Right[A, B](value: B) extends Either\n\nclass Pair[A, B](x: A, y: B) {\n  fun mapFirst[C](f: A -> C): Pair[C, B] = Pair(f(x), y)\n  fun mapSecond[C](f: B -> C): Pair[A, C] = Pair(x, f(y))\n}\n//│ class Pair[A, B](x: A, y: B) {\n//│   fun mapFirst: forall 'C. (f: A -> 'C) -> Pair['C, B]\n//│   fun mapSecond: forall 'C0. (f: B -> 'C0) -> Pair[A, 'C0]\n//│ }\n\n:ducs:transform.result\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    Nil and ys is Nil then Some(Nil)\n  else None\n//│ Transformed UCS term:\n//│ if\n//│   xs is\n//│     Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys,) is Some(tail) then Some(Cons(f(x, y,), tail,),)\n//│     Nil and ys is Nil then Some(Nil,)\n//│   else None\n//│ fun zipWith: forall 'T 'T0 'T1 'T2. (('T, 'T0) -> 'T1, Cons['T] | Object & ~#Cons, Cons['T0] | Object & ~#Cons) -> (None | Some[in List['T1] & 'T2 out Nil | 'T2 | Cons['T1]])\n\n:ducs:transform.result\nfun getOrElse[T](x: Option[T], default: T): T =\n  if x is\n    Some(value) then value\n    None then default\n//│ Transformed UCS term:\n//│ if x is\n//│   Some(value) then value\n//│   None then default\n//│ fun getOrElse: forall 'T. (x: Option['T], default: 'T) -> 'T\n\nfun m3(x: Int): Bool = x % 3 == 0\nfun m5(x: Int): Bool = x % 5 == 0\n//│ fun m3: (x: Int) -> Bool\n//│ fun m5: (x: Int) -> Bool\n\n:ducs:transform.result\nfun f(x) =\n  if x is\n    Some(v) and m3(v) and m5(v) then \"FizzBuzz\"\n    Some(v) and m3(v) then \"Fizz\"\n    Some(v) and m5(v) then \"Buzz\"\n    else \"meh\"\n//│ Transformed UCS term:\n//│ if x is\n//│   Some(v) and m3(v,) and m5(v,) then \"FizzBuzz\"\n//│   Some(v) and m3(v,) then \"Fizz\"\n//│   Some(v) and m5(v,) then \"Buzz\"\n//│   else \"meh\"\n//│ fun f: (Object & ~#Some | Some[Int]) -> (\"Buzz\" | \"Fizz\" | \"FizzBuzz\" | \"meh\")\n"
  },
  {
    "path": "shared/src/test/diff/qq/BadConst.mls",
    "content": ":NewDefs\n:NoJS\n\n\n:e\n// :ge\ncode\"x => y => 100 + ${Const(x + y)}\"\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.7: \tcode\"x => y => 100 + ${Const(x + y)}\"\n//│ ║       \t                             ^^^^^\n//│ ╟── reference of type `Var[?a, ?x]` is not an instance of type `Int`\n//│ ║  l.7: \tcode\"x => y => 100 + ${Const(x + y)}\"\n//│ ╙──     \t                             ^\n//│ Code[anything -> anything -> Int, nothing]\n\n:e\ncode\"x => y => 100 + code\"${Const(x + y)}\"\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.17: \tcode\"x => y => 100 + code\"${Const(x + y)}\"\"\n//│ ╙──      \t                     ^^^^^^^^^^^^^^^^^^^^^\n//│ Code[anything -> anything -> Int, nothing]\n\n:e\nlet res = code\"x => code\"${x}\"\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.24: \tlet res = code\"x => code\"${x}\"\"\n//│ ╙──      \t                    ^^^^^^^^^^\n//│ let res: Code[anything -> error, nothing]\n"
  },
  {
    "path": "shared/src/test/diff/qq/Basic.mls",
    "content": ":NewDefs\n:NoJS\n\n\n:e\nlet c = code\"x\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.6: \tlet c = code\"x\"\n//│ ╙──     \t             ^\n//│ let c: Code[error, nothing]\n\n\nlet r = code\"x => ${c}\"\n//│ let r: Code[anything -> error, nothing]\n\nrun(r)(1)\n//│ error\n\n\n// Bra, Rcd, Sel \nlet rcd = code\"{x: 10, y: 100, z: 1000}.z\"\n//│ let rcd: Code[1000, nothing]\n\nrun(rcd)\n//│ 1000\n\n\n// Let, Var, App -> evaluates to 3\nlet let_var = code\"let y = 1 in y + 1 * 2\"\n//│ let let_var: Code[Int, nothing]\n\nrun(let_var)\n//│ Int\n\n// Fun, If\nfun id(x) = x \n//│ fun id: forall 'a. 'a -> 'a\n\nlet global_fun = code\"id(4)\"\n//│ let global_fun: Code[4, nothing]\n\nrun(global_fun)\n//│ 4\n\nlet local_fun = code\"let plus1 = x => x + 1 in plus1(if true then 1 else 2)\"\n//│ let local_fun: Code[Int, nothing]\n\nrun(local_fun)\n//│ Int\n\nlet res = code\"let id = x => x in id(3)\"\n//│ let res: Code[3, nothing]\nrun(res)\n//│ 3\n\n// Tup, Subs\nlet tup = code\"let x = 1 in let y = 2 in [x, y].1\"\n//│ let tup: Code[2, nothing]\n\nrun(tup)\n//│ 2\n\n// Quasiquote \n:e\nlet code_in_code = code\"let x = code\"1\" in x\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.65: \tlet code_in_code = code\"let x = code\"1\" in x\"\n//│ ╙──      \t                                ^^^^^^^\n//│ let code_in_code: Code[error, nothing]\n\n\n// Unquoted - Const function\nlet unquoted = code\"let x = 3 in ${Const(10)} * x\"\n//│ let unquoted: Code[Int, nothing]\nrun(unquoted)\n//│ Int\n\ncode\"0.5 *. 2\"\n//│ Code[Num, nothing]\n\ncode\"[(), null]\"\n//│ Code[[(), null], nothing]\n\nlet str_lit = code\"\"\" \"hello\" \"\"\"\n//│ let str_lit: Code[\"hello\", nothing]\n\n\nlet y = 1\nlet free = code\"y\"\n//│ let y: 1\n//│ let free: Code[1, nothing]\n\nlet code_nested = code\"let a = 1 in let b = 2 in ${code\"a + b\"}\"\n//│ let code_nested: Code[Int, nothing]\n\nrun(code_nested)\n//│ Int\n\n// We don't support non-lexically-bound free variables\n:e\nlet y = code\"x\"\ncode\"let id = x => ${y} in id(true)\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.101: \tlet y = code\"x\"\n//│ ╙──       \t             ^\n//│ let y: Code[error, nothing]\n//│ Code[error, nothing]\n\nrun(res)\n//│ 3\n\nlet y = 1\nlet free_y = code\"y\"\n//│ let y: 1\n//│ let free_y: Code[1, nothing]\n\nlet use_free = code\"let y = 3 in ${code\"let y = 5 in ${code\"let y = 100 in ${free_y}\"} + y\"} + y\"\n//│ let use_free: Code[Int, nothing]\n\n\nrun(use_free)\n//│ Int\n\nlet res = code\"let z = x => ${let c = code\"x + 1\" in c} in z\"\n//│ let res: Code[Int -> Int, nothing]\n\n\nrun(res)(100)\n//│ Int\n\n\nlet f = 0\n//│ let f: 0\n\nfun f(x) = x\n//│ fun f: forall 'a. 'a -> 'a\n\n\nlet res = code\"f(1)\"\n//│ let res: Code[1, nothing]\n\n\nrun(res)\n//│ 1\n\n\nclass Foo(n: Int)\n//│ class Foo(n: Int)\n\n\nlet res = code\"Foo(1)\"\n//│ let res: Code[Foo, nothing]\n\n\nrun(res)\n//│ Foo\n\nlet codeA = code\"let y = 2 in y\"\nlet codeB = code\"y + y\"\n//│ let codeA: Code[2, nothing]\n//│ let codeB: Code[Int, nothing]\n\n\nlet both = code\"${codeA}, ${codeB}\"\n//│ let both: Code[Int, nothing]\n\n:e\nlet a = code\"let x = 0 in x\"\nlet b = code\"x\"\nlet c = code\"${a} + ${b}\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.169: \tlet b = code\"x\"\n//│ ╙──       \t             ^\n//│ let a: Code[0, nothing]\n//│ let b: Code[error, nothing]\n//│ let c: Code[Int, nothing]\n\n\nrun(c)\n//│ Int\n\nlet res = code\"{x: y} => y\"\n//│ let res: Code[forall 'a. {x: 'a} -> 'a, nothing]\n\nrun(res)({x:1})\n//│ 1\n\ncode\"x => ${ code\"x\" }\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n\n\nrun(code\"x => x + ${x}\")(1)\n//│ Int\n\nrun(code\"x => x + ${code\"x\"}\")(1)\n//│ Int\n\nval v: Var[Int, nothing]\n//│ val v: Var[Int, nothing]\n\nrun(v)\n//│ Int\n\nval v: Var[Int, anything]\n//│ val v: Var[Int, anything]\n\n:e\nrun(v)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.208: \trun(v)\n//│ ║         \t^^^^^^\n//│ ╙── expression of type `anything` does not match type `nothing`\n//│ Int | error\n\n\nlet x = code\"1\"\ncode\"$x + 1\"\n//│ let x: Code[1, nothing]\n//│ Code[Int, nothing]\n\n\n:pe\ncode\"$\"\n//│ ╔══[LEXICAL ERROR] unexpected character '$'\n//│ ║  l.223: \tcode\"$\"\n//│ ╙──       \t     ^\n//│ ╔══[PARSE ERROR] Unexpected error in expression position\n//│ ║  l.223: \tcode\"$\"\n//│ ╙──       \t     ^\n//│ ╔══[PARSE ERROR] Unexpected end of quasiquote section; an expression was expected here\n//│ ║  l.223: \tcode\"$\"\n//│ ╙──       \t      ^\n//│ Code[(), nothing]\n"
  },
  {
    "path": "shared/src/test/diff/qq/Basic2.mls",
    "content": ":NewDefs\n:NoJS\n\n// More specific checks from parser folder\n\nlet res = code\"[]\"\n//│ let res: Code[[], nothing]\nrun(res)\n//│ []\n\nlet res = code\"()\"\nrun(res)\n//│ let res: Code[(), nothing]\n//│ ()\n\nlet res = code\"(1,)\"\nrun(res)\n//│ let res: Code[1, nothing]\n//│ 1\n\nlet res = code\"let f = (x, y, z) => x + y + x in f of 1,2,3\"\nrun(res)\n//│ let res: Code[Int, nothing]\n//│ Int\n\n:pe\ncode\"// Can I comment?\"\n//│ ╔══[PARSE ERROR] Unmatched opening quasiquote\n//│ ║  l.27: \tcode\"// Can I comment?\"\n//│ ╙──      \t^^^^^\n//│ \n\nlet res = code\"[x: 1,]\"\n//│ let res: Code[[x: 1], nothing]\nrun(res)\n//│ [x: 1]\n\n// :ge\n:e\ncode\"let x = {a: 100} in x . a\" // \".\" ?\n//│ ╔══[ERROR] identifier not found: .\n//│ ║  l.40: \tcode\"let x = {a: 100} in x . a\" // \".\" ?\n//│ ╙──      \t                           ^\n//│ ╔══[ERROR] identifier not found: a\n//│ ║  l.40: \tcode\"let x = {a: 100} in x . a\" // \".\" ?\n//│ ╙──      \t                             ^\n//│ Code[error, nothing]\n\n\ncode\"let x = {a: 100} in x.a\"\n//│ Code[100, nothing]\n\n\n// should be ok\nlet res = code\"let x = {a: 100} in x .a\"\n//│ let res: Code[100, nothing]\n\nrun(res)\n//│ 100\n\nlet app = code\"f => x => f(x)\"\nrun(app)(id)(1)\n//│ let app: Code[forall 'a 'b. ('a -> 'b) -> 'a -> 'b, nothing]\n//│ 1\n\n:e\ncode\"f => x => f(${run(x)})\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.67: \tcode\"f => x => f(${run(x)})\"\n//│ ║        \t                   ^^^^^^\n//│ ╙── expression of type `?x` does not match type `nothing`\n//│ Code[forall 'a 'b. ('a -> 'b) -> Code['a, anything] -> 'b, nothing]\n\n\nrun(code\"(x => x + 1)(${Const(42)})\")\n//│ Int\n"
  },
  {
    "path": "shared/src/test/diff/qq/Codegen.mls",
    "content": ":NewDefs\n\n\n:js\n:e\ncode\"x\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.6: \tcode\"x\"\n//│ ╙──     \t     ^\n//│ Code[error, nothing]\n//│ Code generation encountered an error:\n//│   unbound free variable x is not supported yet.\n\n\n:js\n:ne\ncode\"x => x\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), Var(x1)))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"x => ${code\"x\"}\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n//│ // Prelude\n//│ class TypingUnit2 {}\n//│ const typing_unit2 = new TypingUnit2;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), Var(x1)))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"x => ${id(code\"x\")}\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n//│ // Prelude\n//│ function id(x) {\n//│   return x;\n//│ }\n//│ class TypingUnit3 {}\n//│ const typing_unit3 = new TypingUnit3;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), id(Var(x1))))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"1 + 2\"\n//│ Code[Int, nothing]\n//│ // Prelude\n//│ class TypingUnit4 {}\n//│ const typing_unit4 = new TypingUnit4;\n//│ // Query 1\n//│ res = App(Var(\"+\"), IntLit(1), IntLit(2));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"f => f(114)\"\n//│ Code[forall 'a. (114 -> 'a) -> 'a, nothing]\n//│ // Prelude\n//│ class TypingUnit5 {}\n//│ const typing_unit5 = new TypingUnit5;\n//│ // Query 1\n//│ res = ((f1) => Lam(Var(f1), App(Var(f1), Tup(Fld(IntLit(114), false, false, false)))))(freshName(\"f\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"\"\" \"come on! roach!\" \"\"\"\n//│ Code[\"come on! roach!\", nothing]\n//│ // Prelude\n//│ class TypingUnit6 {}\n//│ const typing_unit6 = new TypingUnit6;\n//│ // Query 1\n//│ res = StrLit(\"come on! roach!\");\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"{x: 114, y: 514}\"\n//│ Code[{x: 114, y: 514}, nothing]\n//│ // Prelude\n//│ class TypingUnit7 {}\n//│ const typing_unit7 = new TypingUnit7;\n//│ // Query 1\n//│ res = Bra(Rcd(Var(\"x\"), IntLit(114), Var(\"y\"), IntLit(514)));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"{x: 114}.x\"\n//│ Code[114, nothing]\n//│ // Prelude\n//│ class TypingUnit8 {}\n//│ const typing_unit8 = new TypingUnit8;\n//│ // Query 1\n//│ res = Sel(Bra(Rcd(Var(\"x\"), IntLit(114))), Var(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"let x = 42 in x\"\n//│ Code[42, nothing]\n//│ // Prelude\n//│ class TypingUnit9 {}\n//│ const typing_unit9 = new TypingUnit9;\n//│ // Query 1\n//│ res = ((x1) => Let(Var(x1), IntLit(42), Var(x1)))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"(x => x + 1)(41)\"\n//│ Code[Int, nothing]\n//│ // Prelude\n//│ class TypingUnit10 {}\n//│ const typing_unit10 = new TypingUnit10;\n//│ // Query 1\n//│ res = App(Bra(((x1) => Lam(Var(x1), App(Var(\"+\"), Var(x1), IntLit(1))))(freshName(\"x\"))), Tup(Fld(IntLit(41), false, false, false)));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"let x = ${Const(42)} in ${code\"x\"}\"\n//│ Code[Int, nothing]\n//│ // Prelude\n//│ class TypingUnit11 {}\n//│ const typing_unit11 = new TypingUnit11;\n//│ // Query 1\n//│ res = ((x1) => Let(Var(x1), Const(42), Var(x1)))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"let x = 1 in (x + 1, x + 2)\"\n//│ Code[Int, nothing]\n//│ // Prelude\n//│ class TypingUnit12 {}\n//│ const typing_unit12 = new TypingUnit12;\n//│ // Query 1\n//│ res = ((x1) => Let(Var(x1), IntLit(1), App(Var(\",\"), App(Var(\"+\"), Var(x1), IntLit(1)), App(Var(\"+\"), Var(x1), IntLit(2)))))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"[1, 2, 3]\"\n//│ Code[[1, 2, 3], nothing]\n//│ // Prelude\n//│ class TypingUnit13 {}\n//│ const typing_unit13 = new TypingUnit13;\n//│ // Query 1\n//│ res = Tup(Fld(IntLit(1), false, false, false), Fld(IntLit(2), false, false, false), Fld(IntLit(3), false, false, false));\n//│ // End of generated code\n\n:js\n:ne\ncode\"[1, 2, 3].1\"\n//│ Code[2, nothing]\n//│ // Prelude\n//│ class TypingUnit14 {}\n//│ const typing_unit14 = new TypingUnit14;\n//│ // Query 1\n//│ res = Sel(Tup(Fld(IntLit(1), false, false, false), Fld(IntLit(2), false, false, false), Fld(IntLit(3), false, false, false)), Var(\"1\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"true\"\n//│ Code[true, nothing]\n//│ // Prelude\n//│ class TypingUnit15 {}\n//│ const typing_unit15 = new TypingUnit15;\n//│ // Query 1\n//│ res = Var(\"true\");\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"42: Int\"\n//│ Code[Int, nothing]\n//│ // Prelude\n//│ class TypingUnit16 {}\n//│ const typing_unit16 = new TypingUnit16;\n//│ // Query 1\n//│ res = IntLit(42);\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"(x: Int) => x + 1\"\n//│ Code[(x: Int) -> Int, nothing]\n//│ // Prelude\n//│ class TypingUnit17 {}\n//│ const typing_unit17 = new TypingUnit17;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), App(Var(\"+\"), Var(x1), IntLit(1))))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"{x: 42} with {y: true}\"\n//│ Code[{x: 42, y: true}, nothing]\n//│ // Prelude\n//│ class TypingUnit18 {}\n//│ const typing_unit18 = new TypingUnit18;\n//│ // Query 1\n//│ res = With(Bra(Rcd(Var(\"x\"), IntLit(42))), Rcd(Var(\"y\"), Var(\"true\")));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"${Const(42)}\"\n//│ Code[Int, nothing]\n//│ // Prelude\n//│ class TypingUnit19 {}\n//│ const typing_unit19 = new TypingUnit19;\n//│ // Query 1\n//│ res = Const(42);\n//│ // End of generated code\n\n\n:js\n:ne\n:e\ncode\"code\"42\"\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.249: \tcode\"code\"42\"\"\n//│ ╙──       \t     ^^^^^^^^\n//│ Code[error, nothing]\n//│ Code generation encountered an error:\n//│   nested quotation is not allowed.\n\n\n:js\n:ne\ncode\"Const(42)\"\n//│ Code[Code[Int, nothing], nothing]\n//│ // Prelude\n//│ class TypingUnit21 {}\n//│ const typing_unit21 = new TypingUnit21;\n//│ // Query 1\n//│ res = App(Var(\"Const\"), Tup(Fld(IntLit(42), false, false, false)));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"if (1 == 2) then false else true\"\n//│ Code[Bool, nothing]\n//│ // Prelude\n//│ class TypingUnit22 {}\n//│ const typing_unit22 = new TypingUnit22;\n//│ // Query 1\n//│ res = ((ucs$test$01) => Let(Var(ucs$test$01), Bra(App(Var(\"==\"), IntLit(1), IntLit(2))), CaseOf(Var(ucs$test$01), Case(Var(\"true\"), Var(\"false\"), Wildcard(Var(\"true\"))))))(freshName(\"ucs$test$0\"));\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"if 3 is\n  1 then 114\n  2 then 514\n  _ then 0\n\"\n//│ Code[0 | 114 | 514, nothing]\n//│ // Prelude\n//│ class TypingUnit23 {}\n//│ const typing_unit23 = new TypingUnit23;\n//│ // Query 1\n//│ res = ((ucs$scrut$01) => Let(Var(ucs$scrut$01), IntLit(3), CaseOf(Var(ucs$scrut$01), Case(IntLit(1), IntLit(114), Case(IntLit(2), IntLit(514), Wildcard(IntLit(0)))))))(freshName(\"ucs$scrut$0\"));\n//│ // End of generated code\n\n\n:js\n:ne\nlet zero = Const(0)\nlet one = Const(1)\ncode\"p => if p.x ===\n    ${zero} then true\n    ${one} then false\n  else false\n\"\n//│ let zero: Code[Int, nothing]\n//│ let one: Code[Int, nothing]\n//│ Code[{x: Eql[Int]} -> Bool, nothing]\n//│ // Prelude\n//│ class TypingUnit24 {}\n//│ const typing_unit24 = new TypingUnit24;\n//│ // Query 1\n//│ globalThis.zero = Const(0);\n//│ // Query 2\n//│ globalThis.one = Const(1);\n//│ // Query 3\n//│ res = ((p1) => Lam(Var(p1), ((ucs$cache$01) => Let(Var(ucs$cache$01), Sel(Var(p1), Var(\"x\")), ((ucs$test$01) => Let(Var(ucs$test$01), App(Var(\"===\"), Var(ucs$cache$01), zero), CaseOf(Var(ucs$test$01), Case(Var(\"true\"), Var(\"true\"), Wildcard(((ucs$test$11) => Let(Var(ucs$test$11), App(Var(\"===\"), Var(ucs$cache$01), one), CaseOf(Var(ucs$test$11), Case(Var(\"true\"), Var(\"false\"), Wildcard(Var(\"false\"))))))(freshName(\"ucs$test$1\")))))))(freshName(\"ucs$test$0\"))))(freshName(\"ucs$cache$0\"))))(freshName(\"p\"));\n//│ // End of generated code\n\n\n:js\n:ne\nfun test(cde, f) =\n  code\"x => x + ${f(cde)}\"\n//│ fun test: forall 'a 'b. ('a, 'a -> Code[Int, 'b]) -> Code[Int -> Int, 'b]\n//│ // Prelude\n//│ class TypingUnit25 {}\n//│ const typing_unit25 = new TypingUnit25;\n//│ // Query 1\n//│ globalThis.test = function test(cde, f) {\n//│   return ((() => {\n//│     return ((x1) => Lam(Var(x1), App(Var(\"+\"), Var(x1), f(cde))))(freshName(\"x\"));\n//│   })());\n//│ };\n//│ // End of generated code\n\n\n:js\n:ne\ncode\"\"\"let x = ${log(\"foo\"), Const(0)} in x + 1\"\"\"\n//│ Code[Int, nothing]\n//│ // Prelude\n//│ function log(x) {\n//│   return console.info(x);\n//│ }\n//│ class TypingUnit26 {}\n//│ const typing_unit26 = new TypingUnit26;\n//│ // Query 1\n//│ res = ((x1) => Let(Var(x1), (log(\"foo\") , Const(0)), App(Var(\"+\"), Var(x1), IntLit(1))))(freshName(\"x\"));\n//│ // End of generated code\n\n:ne\nfun foo(dbg) =\n  code\"x => ${let c = code\"x\" in dbg(c)}\"\n//│ fun foo: forall 'a 'b 'c. (Code['a, ??x] -> Code['b, 'c]) -> Code['a -> 'b, 'c]\n\n:ne\ncode\"x => let c = 42 in ${code\"x\"}\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n\nclass Ref[A](init: A) { mut val value: A = init }\n//│ class Ref[A](init: A) {\n//│   mut val value: A\n//│ }\n\n:ne\n:js\nx `=>\n  let v = Ref(x)\n  let _ = y `=>\n    set v.value = y\n    `0\n  v.value\n//│ Code[forall 'a. 'a -> 'a, ??y & ~??x]\n//│ // Prelude\n//│ class TypingUnit30 {}\n//│ const typing_unit30 = new TypingUnit30;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), (() => {\n//│   let v = Ref(Var(x1));\n//│   let _ = ((y1) => Lam(Var(y1), (() => {\n//│     void(v.value = Var(y1));\n//│     return IntLit(0);\n//│   })()))(freshName(\"y\"));\n//│   return v.value;\n//│ })()))(freshName(\"x\"));\n//│ // End of generated code\n\n:ne\n:js\nx `=>\n  class A(y: Code[Int, nothing]) {\n    val z = x `+ y\n  }\n  A(`0).z\n//│ Code[Int -> Int, nothing]\n//│ // Prelude\n//│ class TypingUnit31 {}\n//│ const typing_unit31 = new TypingUnit31;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), (() => {\n//│   const A = (() => {\n//│     class A {\n//│       #y;\n//│       #z;\n//│       get z() { return this.#z; }\n//│       constructor(y) {\n//│         this.#y = y;\n//│         this.#z = App(Var(\"+\"), Var(x1), y);\n//│         const z = this.#z;\n//│       }\n//│     static\n//│       unapply(x) {\n//│         return [x.#y];\n//│       }\n//│     }\n//│     let ctor;\n//│     ctor = ((y) => new A(y));\n//│     ctor.class = A;\n//│     return ctor;\n//│   })();\n//│   return A(IntLit(0)).z;\n//│ })()))(freshName(\"x\"));\n//│ // End of generated code\n\n:ne\n:js\nx `=>\n  class A() {\n    constructor() {\n      log(x)\n    }\n  }\n  new A(), x\n//│ Code[forall 'a. 'a -> 'a, nothing]\n//│ // Prelude\n//│ class TypingUnit32 {}\n//│ const typing_unit32 = new TypingUnit32;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), (() => {\n//│   const A = (() => {\n//│     class A {\n//│       constructor() {\n//│         log(Var(x1));\n//│       }\n//│     static\n//│       unapply(x) {\n//│         return [];\n//│       }\n//│     }\n//│     let ctor;\n//│     ctor = (() => new A());\n//│     ctor.class = A;\n//│     return ctor;\n//│   })();\n//│   return new A.class() , Var(x1);\n//│ })()))(freshName(\"x\"));\n//│ // End of generated code\n\nclass Foo(x: Code[Int, anything])\n//│ class Foo(x: Code[Int, anything])\n\n:ne\n:js\nx `=>\n  class B() extends Foo(x)\n  `x\n//│ Code[forall 'a. (Int & 'a) -> 'a, nothing]\n//│ // Prelude\n//│ class TypingUnit34 {}\n//│ const typing_unit34 = new TypingUnit34;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), (() => {\n//│   const B = (() => {\n//│     class B extends Foo.class {\n//│       constructor() {\n//│         super(Var(x1));\n//│       }\n//│     static\n//│       unapply(x) {\n//│         return [];\n//│       }\n//│     }\n//│     let ctor;\n//│     ctor = (() => new B());\n//│     ctor.class = B;\n//│     return ctor;\n//│   })();\n//│   return Var(x1);\n//│ })()))(freshName(\"x\"));\n//│ // End of generated code\n"
  },
  {
    "path": "shared/src/test/diff/qq/EffectfulLetInsertion.mls",
    "content": ":NewDefs\n\n:NoJS\n\n\n\ndeclare class Scope[OuterCtx, InnerCtx] {\n  fun bind(code: Code['a, InnerCtx | OuterCtx]): Code['a, InnerCtx]\n}\ndeclare fun scope(body: forall 'in: Scope['in, 'out] -> Code['a, 'in | 'out]): Code['a, 'out]\n//│ declare class Scope[OuterCtx, InnerCtx] {\n//│   constructor()\n//│   fun bind: forall 'a. (code: Code['a, InnerCtx | OuterCtx]) -> Code['a, InnerCtx]\n//│ }\n//│ fun scope: forall 'out 'a0. (body: forall 'in. Scope['in, 'out] -> Code['a0, 'in | 'out]) -> Code['a0, 'out]\n\n\nscope of scp =>\n  let a = scp.bind(code\"123\")\n  let b = scp.bind(code\"${a} + 1\")\n  code\"${a} * ${b}\"\n//│ Code[Int, nothing]\n\n\nscope of outer =>\n  let a = outer.bind(code\"123\")\n  code\"x => ${\n    code\"${a} * x\"\n  }\"\n//│ Code[Int -> Int, nothing]\n\n\n// * Note: expected extrusion!\nscope of outer =>\nlet a = outer.bind(code\"123\")\ncode\"x => ${\n  scope of inner =>\n  let b = outer.bind(code\"${a} + ${code\"x\"}\")\n  code\"${b} * 2\"\n}\"\n//│ Code[Int -> Int, ??x & ~??in]\n\n\nscope of outer =>\nlet a = outer.bind(code\"123\")\ncode\"x => ${\n  scope of inner =>\n  let b = inner.bind(code\"${a} + ${code\"x\"}\")\n  code\"${b} * 2\"\n}\"\n//│ Code[Int -> Int, nothing]\n\n\nfun (<|) via(f, x) = f(x)\n//│ fun (<|) via: forall 'a 'b. ('a -> 'b, 'a) -> 'b\n\nscope <| outer =>\nlet a = outer.bind(code\"123\")\ncode\"x => ${\n  scope <| inner =>\n  let b = inner.bind(code\"${a} + ${code\"x\"}\")\n  code\"${b} * 2\"\n}\"\n//│ Code[Int -> Int, nothing]\n\n\n\n// * Note: a failed alternative interface:\n\ndeclare class Scope[Res, OuterCtx, InnerCtx] {\n  fun bind: (nameHint: Str, value: Code['a, InnerCtx | OuterCtx]) -> Code['a, InnerCtx]\n  virtual fun result: Code[Res, InnerCtx]\n}\ndeclare fun reify(scope: forall 'in: () -> Scope['a, 'in, 'out]): Code['a, 'out]\n//│ declare class Scope[Res, OuterCtx, InnerCtx] {\n//│   constructor()\n//│   fun bind: forall 'a. (nameHint: Str, value: Code['a, InnerCtx | OuterCtx]) -> Code['a, InnerCtx]\n//│   fun result: Code[Res, InnerCtx]\n//│ }\n//│ fun reify: forall 'a0 'out. (scope: forall 'in. () -> Scope['a0, 'in, 'out]) -> Code['a0, 'out]\n\n:e\nclass Example() extends Scope {\n  let c0 = this.bind(\"a\", code\"123\")\n  let c1 = this.bind(\"b\", code\"${c0} + 1\")\n  val result = code\"${c1} * ${c1}\"\n}\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.84: \t  let c0 = this.bind(\"a\", code\"123\")\n//│ ╙──      \t               ^^^^^\n//│ ╔══[ERROR] Indirectly-recursive member should have a type signature\n//│ ║  l.85: \t  let c1 = this.bind(\"b\", code\"${c0} + 1\")\n//│ ╙──      \t               ^^^^^\n//│ ╔══[ERROR] Cannot access `this` while initializing field c0\n//│ ║  l.84: \t  let c0 = this.bind(\"a\", code\"123\")\n//│ ╙──      \t           ^^^^\n//│ ╔══[ERROR] Cannot access `this` while initializing field c1\n//│ ║  l.85: \t  let c1 = this.bind(\"b\", code\"${c0} + 1\")\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.84: \t  let c0 = this.bind(\"a\", code\"123\")\n//│ ╙──      \t           ^^^^\n//│ ╔══[ERROR] Cannot access `this` while initializing field result\n//│ ║  l.86: \t  val result = code\"${c1} * ${c1}\"\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── The access to `this` is here\n//│ ║  l.84: \t  let c0 = this.bind(\"a\", code\"123\")\n//│ ╙──      \t           ^^^^\n//│ ╔══[ERROR] Member `bind` is declared (or its declaration is inherited) but is not implemented in `Example`\n//│ ║  l.83: \tclass Example() extends Scope {\n//│ ║        \t      ^^^^^^^\n//│ ╟── Declared here:\n//│ ║  l.71: \t  fun bind: (nameHint: Str, value: Code['a, InnerCtx | OuterCtx]) -> Code['a, InnerCtx]\n//│ ╙──      \t  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ class Example() extends Scope {\n//│   fun bind: forall 'a. (nameHint: Str, value: Code['a, 'InnerCtx | 'OuterCtx]) -> Code['a, 'InnerCtx]\n//│   let c0: error\n//│   let c1: error\n//│   val result: Code[Int, nothing]\n//│ }\n\nreify(Example)\n//│ Code[Int, nothing]\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/qq/Extrusions.mls",
    "content": ":NewDefs\n:NoJS\n\n\n\n// * This definition is not good as it leads to extrusion; we need `k` to be polymorphic (which requires annotation)\nfun (%>) bind(rhs, k) = code\"let x = ${rhs} in ${k(code\"x\")}\"\n//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Code['a, ??x] -> Code['c, 'b]) -> Code['c, 'b]\n\nfun (%>) bind(rhs, k) = code\"let x = ${rhs} in ${k(x)}\"\n//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Var['a, in ??x out ??x0] -> Code['c, 'b]) -> Code['c, 'b]\n\n// * Notice the extrusion\nfun foo(k) = code\"x => ${k(code\"x\")}\"\n//│ fun foo: forall 'a 'b 'c. (Code['a, ??x] -> Code['b, 'c]) -> Code['a -> 'b, 'c]\n\nfun (%>) bind(rhs, k) = code\"(x => ${k(code\"x\")})(${rhs})\"\n//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Code['a, ??x] -> Code['c, 'b]) -> Code['c, 'b]\n\nfun app = code\"(f, x) => f(x)\"\nfun (%>) bind(rhs, k) = code\"${app}(x => ${k(code\"x\")}, ${rhs})\"\n//│ fun app: forall 'a 'b. Code[('a -> 'b, 'a) -> 'b, nothing]\n//│ fun (%>) bind: forall 'c 'd 'e. (Code['c, 'd], Code['c, ??x] -> Code['e, 'd]) -> Code['e, 'd]\n\n\nfun app(f, x) = f(x)\nfun bind2(rhs, k) = code\"app(x => ${k(code\"x\")}, ${rhs})\"\n//│ fun app: forall 'a 'b. ('a -> 'b, 'a) -> 'b\n//│ fun bind2: forall 'c 'd 'e. (Code['c, 'd], Code['c, ??x] -> Code['e, 'd]) -> Code['e, 'd]\n\n:e\nfun foo() =\n  let bar = 42 // not at top level\n  code\"bar\"\n//│ ╔══[ERROR] identifier not found: bar\n//│ ║  l.34: \t  code\"bar\"\n//│ ╙──      \t       ^^^\n//│ fun foo: () -> Code[error, nothing]\n\nfun (++) myadd(x, y) = x + y\ncode\"1 ++ 2\"\n//│ fun (++) myadd: (Int, Int) -> Int\n//│ Code[Int, nothing]\n\n// G <: ??x | 'a\nfun bind(rhs, k: forall 'C: Code['A, 'C] -> Code['B, 'C | 'G]) = code\"let x = ${rhs} in ${k(code\"x\")}\"\n//│ fun bind: forall 'A 'a 'B. (Code['A, 'a], k: forall 'C. Code['A, 'C] -> Code['B, 'C | 'a]) -> Code['B, 'a]\n\nbind : forall 'a, 'c, 'g: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n//│ forall 'a 'g. (Code['a, 'g], k: forall 'c. Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n\n\nfun foo(dbg) =\n  code\"x => ${let c = code\"(${x}, ${foo(dbg)})\" in dbg(c)}\"\n//│ fun foo: forall 'a 'b. (Code[anything -> 'a, anything] -> Code['a, 'b]) -> Code[anything -> 'a, 'b]\n\nfun power(x) = case\n  0 then `1.0\n  n then x `*. power(x)(n - 1)\n//│ fun power: forall 'a. Code[Num, 'a] -> (0 | Int & ~0) -> Code[Num, 'a]\n\n:e\nlet p3 = y `=>\n  discard(run(x `=> power(x `+ y)(3)))\n  y\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.64: \t  discard(run(x `=> power(x `+ y)(3)))\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `?y & ~??x` does not match type `nothing`\n//│ let p3: Code[forall 'a. (Int & 'a) -> 'a, nothing]\n"
  },
  {
    "path": "shared/src/test/diff/qq/Hygiene.mls",
    "content": ":NewDefs\n:NoJS\n\n\n// Test 1\nlet code_test = code\"let x0 = 1 in let x1 = 10 in let x2 = 100 in x0 + x1 + x2\"\n//│ let code_test: Code[Int, nothing]\n\nrun(code_test)\n//│ Int\n\n\n// Test 2\nfun test: forall 'c: (Int, cde: Code[Int, 'c]) => Code[Int, 'c]\nfun test(n, cde) = if n > 0 then code\"let x = ${Const(n)} in ${test(n - 1, code\"${cde} + x\")}\" else cde\n//│ fun test: forall 'a. (Int, Code[Int, 'a]) -> Code[Int, 'a]\n//│ fun test: forall 'c. (Int, cde: Code[Int, 'c]) -> Code[Int, 'c]\n\nrun(test(3, code\"0\"))\n//│ Int\n\nfun test(n, cde) = if n > 0 then code\"${test(n - 1, code\"${cde} + ${Const(n)}\")}\" else cde\n//│ fun test: forall 'a 'b. (Int, Code[Int, 'a] & 'b) -> (Code[Int, 'a] | 'b)\n\n\nrun(test(3, code\"0\"))\n//│ Int\n\n\n// Test 3: note that the free variable makes this unhygienic, which is intended\n:e\nfun cde_template(cde) = code\"${cde} + x\"\nfun test(n, cde) = if n > 0 then code\"let x = ${Const(n)} in ${test(n - 1, cde_template(cde))}\" else cde\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.32: \tfun cde_template(cde) = code\"${cde} + x\"\n//│ ╙──      \t                                      ^\n//│ fun cde_template: forall 'a. Code[Int, 'a] -> Code[Int, 'a]\n//│ fun test: forall 'b 'c. (Int, Code[Int, 'b] & 'c) -> (Code[Int, 'b] | 'c)\n\nlet c = test(3, code\"0\")\n//│ let c: Code[Int, nothing]\n\n\nrun(c)\n//│ Int\n\n\ncode\"x => ${ code\"x\" }\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n\n\nlet x4 = code\"x => x => x => x\"\nrun(x4)(1)(2)(3)\n//│ let x4: Code[forall 'a. anything -> anything -> 'a -> 'a, nothing]\n//│ 3\n\nlet y4 = code\"let y = 1 in let y = 2 in let y = 3 in y\"\nrun(y4)\n//│ let y4: Code[3, nothing]\n//│ 3\n\ncode\"x => ${let x = code\"42\" in run(x), x}\"\n//│ Code[anything -> 42, nothing]\n"
  },
  {
    "path": "shared/src/test/diff/qq/LetInsertion.mls",
    "content": ":NewDefs\n:NoJS\n\n\n\nfun (%>) bind: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\nfun bind[g](rhs, k: forall 'c: Code['a, 'c] -> Code['b, 'c | g]) = code\"let x = ${rhs} in ${k(code\"x\")}\"\n//│ fun bind: forall 'a 'd 'b 'g. (Code['a, 'd], k: forall 'c. Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'd | 'g & ~??x]\n//│ fun (%>) bind: forall 'a0 'g0 'b0. (Code['a0, 'g0], k: forall 'c0. Code['a0, 'c0] -> Code['b0, 'c0 | 'g0]) -> Code['b0, 'g0]\n\n\nlet f(k) = bind of code\"123\", k\n//│ let f: forall 'b 'g. (forall 'c. Code[123, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n\nf(id)\n//│ Code[123, nothing]\n\nbind of code\"123\", x => x\n//│ Code[123, nothing]\n\nbind of code\"123\", x =>\nbind of code\"${x} + 1\", y =>\ncode\"${y} + ${y}\"\n//│ Code[Int, nothing]\n\ncode\"123\" %> x =>\ncode\"${x} + 1\" %> y =>\ncode\"${y} + ${y}\"\n//│ Code[Int, nothing]\n\n\nfun test(x, y) = code\"${x} + ${y}\"\n//│ fun test: forall 'a. (Code[Int, 'a], Code[Int, 'a]) -> Code[Int, 'a]\n\nfun test2(x, y, f) = code\"${x} + ${y}\" %> f\n//│ fun test2: forall 'g 'b. (Code[Int, 'g], Code[Int, 'g], forall 'c. Code[Int, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n\ncode\"(x, y) => ${test2(code\"x + 1\", code\"y * 2\", tmp => code\"[${tmp}, ${tmp}]\") }\"\n//│ Code[(Int, Int) -> [Int, Int], nothing]\n\n\n\n// * Naive version\n\n:w\nfun gib_naive(n) =\n  let rec body(x, y) = case\n    0 then x\n    1 then y\n    n then code\"${body(x, code\"${x} + ${y}\")(n - 1)}\"\n  code\"(x, y) => ${body(code\"x\", code\"y\")(n)}\"\n//│ ╔══[WARNING] the outer binding `n`\n//│ ║  l.46: \tfun gib_naive(n) =\n//│ ║        \t              ^\n//│ ╟── is shadowed by name pattern `n`\n//│ ║  l.50: \t    n then code\"${body(x, code\"${x} + ${y}\")(n - 1)}\"\n//│ ╙──      \t    ^\n//│ fun gib_naive: (0 | 1 | Int & ~0 & ~1) -> Code[(Int, Int) -> Int, nothing]\n\nlet gn5 = gib_naive(5)\nrun(gn5)\n//│ let gn5: Code[(Int, Int) -> Int, nothing]\n//│ (Int, Int) -> Int\n\n\n// * Expected: needs polymorphic recursion\n:w\nfun gib(n) =\n  let rec body(x, y) = case\n    0 then x\n    1 then y\n    n then code\"${x} + ${y}\" %> z => body(x, z)(n - 1)\n  code\"(x, y) => ${body(code\"x\", code\"y\")(n)}\"\n//│ ╔══[WARNING] the outer binding `n`\n//│ ║  l.68: \tfun gib(n) =\n//│ ║        \t        ^\n//│ ╟── is shadowed by name pattern `n`\n//│ ║  l.72: \t    n then code\"${x} + ${y}\" %> z => body(x, z)(n - 1)\n//│ ╙──      \t    ^\n//│ fun gib: (0 | 1 | Int & ~0 & ~1) -> Code[(Int, Int) -> Int, ??c & ~??y]\n\n\n\n// * Better version\n\nfun body: forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then code\"${x} + ${y}\" %> z => body(x, z)(n - 1)\n//│ fun body: forall 'g. (Code[Int, 'g], Code[Int, 'g]) -> (0 | 1 | Int & ~0 & ~1) -> Code[Int, 'g]\n//│ fun body: forall 'g0. (Code[Int, 'g0], Code[Int, 'g0]) -> Int -> Code[Int, 'g0]\n\nfun gib(n) =\n  code\"(x, y) => ${body(code\"x\", code\"y\")(n)}\"\n//│ fun gib: Int -> Code[(Int, Int) -> Int, nothing]\n\nlet gn5 = gib(5)\nrun(gn5)\n//│ let gn5: Code[(Int, Int) -> Int, nothing]\n//│ (Int, Int) -> Int\n\n\n// * Alternative version:\nfun body: forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then code\"let tmp = ${x} + ${y} in ${body(x, code\"tmp\")(n - 1)}\"\n//│ fun body: forall 'a. (Code[Int, 'a], Code[Int, 'a]) -> (0 | 1 | Int & ~0 & ~1) -> Code[Int, 'a]\n//│ fun body: forall 'g. (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n\nfun gib(n) =\n  code\"(x, y) => ${body(code\"x\", code\"y\")(n)}\"\n//│ fun gib: Int -> Code[(Int, Int) -> Int, nothing]\n\nlet gn5 = gib(5)\nrun(gn5)\n//│ let gn5: Code[(Int, Int) -> Int, nothing]\n//│ (Int, Int) -> Int\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/qq/LetInsertion_repro.mls",
    "content": ":NewDefs\n:NoJS\n\n\n\nfun (%>) bind: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n//│ fun (%>) bind: forall 'a 'g 'b. (Code['a, 'g], k: forall 'c. Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n\n// fun (%>) bind(rhs, k: forall 'c: Code['a, 'c] -> Code['b, 'c]) = code\"let x = ${rhs} in ${k(code\"x\")}\"\n\n\n\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then code\"${x} + ${y}\" %> z => body(x, z)(n - 1)\n//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, anything] | 'a)\n\n:e\nbody : forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.20: \tbody : forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n//│ ║        \t^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.6: \tfun (%>) bind: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n//│ ║       \t                                                     ^^\n//│ ╟── into type `'g`\n//│ ║  l.20: \tbody : forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n//│ ║        \t                                                                     ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.16: \t  n then code\"${x} + ${y}\" %> z => body(x, z)(n - 1)\n//│ ║        \t                              ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.16: \t  n then code\"${x} + ${y}\" %> z => body(x, z)(n - 1)\n//│ ╙──      \t                           ^^\n//│ forall 'g. (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n\nlet c = code\"(x, y) => ${body(code\"x\", code\"y\")(0)}\"\n//│ let c: Code[(Int, Int) -> Int, ??c & ~??y]\n\n:e\nrun(c)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.43: \trun(c)\n//│ ║        \t^^^^^^\n//│ ╙── expression of type `??c & ~??y` does not match type `nothing`\n//│ error | (Int, Int) -> Int\n\n\n\n// * An unnecessary complication, just for testing purposes:\n\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then code\"${x} + ${y}\" %> z => code\"${body(x, z)(n - 1)}\"\n//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, anything] | 'a)\n\ncode\"(x, y) => ${body(code\"x\", code\"y\")(0)}\"\n//│ Code[(Int, Int) -> Int, ??c & ~??y]\n\n:e\nbody : forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n//│ ╔══[ERROR] Type error in type ascription\n//│ ║  l.64: \tbody : forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n//│ ║        \t^^^^\n//│ ╟── type variable `'c` leaks out of its scope\n//│ ║  l.6: \tfun (%>) bind: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n//│ ║       \t                                                     ^^\n//│ ╟── into type `'g`\n//│ ║  l.64: \tbody : forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n//│ ║        \t                                                                     ^^\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this function:\n//│ ║  l.57: \t  n then code\"${x} + ${y}\" %> z => code\"${body(x, z)(n - 1)}\"\n//│ ║        \t                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── • this reference:\n//│ ║  l.57: \t  n then code\"${x} + ${y}\" %> z => code\"${body(x, z)(n - 1)}\"\n//│ ╙──      \t                           ^^\n//│ forall 'g. (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n\nlet c = code\"(x, y) => ${body(code\"x\", code\"y\")(0)}\"\n//│ let c: Code[(Int, Int) -> Int, ??c & ~??y]\n\n:e\nrun(c)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.87: \trun(c)\n//│ ║        \t^^^^^^\n//│ ╙── expression of type `??c & ~??y` does not match type `nothing`\n//│ error | (Int, Int) -> Int\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/qq/Multiline.mls",
    "content": ":NewDefs\n:NoJS\n\n\ncode\"let arr = [\n  1\n] in arr\"\n//│ Code[[1], nothing]\n\nlet res = code\"let foo = (x, y) => x * y\nfoo(\n  2,\n  3\n)\"\nrun(res)\n//│ let res: Code[Int, nothing]\n//│ Int\n\n\nlet res = code\"let a = 0\nlet b = 1\nif a == 0\nthen true\nelse false\n\"\nrun(res)\n//│ let res: Code[Bool, nothing]\n//│ Bool\n\nlet res = code\"if 1 == 0\n  then false\n  else true\n\"\nrun(res)\n//│ let res: Code[Bool, nothing]\n//│ Bool\n\nlet res = code\"if 1 == 0\nthen false\n  else true\n\"\nrun(res)\n//│ let res: Code[Bool, nothing]\n//│ Bool\n\nlet res = code\"{\n  x: 1,\n  y: 2,\n  z: 3,\n}\n\"\nrun(res)\n//│ let res: Code[{x: 1, y: 2, z: 3}, nothing]\n//│ {x: 1, y: 2, z: 3}\n\n\nlet res = code\"let x = {a: 100}\nx \n  .a\n\"\nrun(res)\n//│ let res: Code[100, nothing]\n//│ 100\n"
  },
  {
    "path": "shared/src/test/diff/qq/Nested.mls",
    "content": ":NewDefs\n:NoJS\n\n\n:e\nlet t = code\"id(code\"123\")\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.6: \tlet t = code\"id(code\"123\")\"\n//│ ╙──     \t                ^^^^^^^^^\n//│ let t: Code[error, nothing]\n\nlet inner0 = code\"123\"\nlet t = code\"id(inner0)\"\n//│ let inner0: Code[123, nothing]\n//│ let t: Code[Code[123, nothing], nothing]\n\nlet r = run(t)\nlet rr = run(r)\n//│ let r: Code[123, nothing]\n//│ let rr: 123\n\n:e\nlet t = code\"let x = code\"1\" in code\"y => ${x} + 1\"\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.23: \tlet t = code\"let x = code\"1\" in code\"y => ${x} + 1\"\"\n//│ ╙──      \t                     ^^^^^^^\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.23: \tlet t = code\"let x = code\"1\" in code\"y => ${x} + 1\"\"\n//│ ╙──      \t                                ^^^^^^^^^^^^^^^^^^^\n//│ let t: Code[error, nothing]\n\nlet inner1 = code\"1\"\nlet inner2(x) = code\"y => ${x} + 1\"\nlet t = code\"let x = inner1 in inner2(x)\"\n//│ let inner1: Code[1, nothing]\n//│ let inner2: forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a]\n//│ let t: Code[Code[anything -> Int, nothing], nothing]\n\nrun(run(t))(0)\n//│ Int\n\nlet r = run(t)\n//│ let r: Code[anything -> Int, nothing]\nrun(r)\n//│ anything -> Int\n\nlet inner3 = code\"2\"\nlet t = code\"let x = inner1 in let y = inner3 in x\"\n//│ let inner3: Code[2, nothing]\n//│ let t: Code[Code[1, nothing], nothing]\nrun(r)\n//│ anything -> Int\n\nlet c1 = code\"let y = inner1 in x => y\"\n//│ let c1: Code[anything -> Code[1, nothing], nothing]\n\nlet r = run(c1)(0)\n//│ let r: Code[1, nothing]\n\nlet t = code\"x => x\"\n//│ let t: Code[forall 'a. 'a -> 'a, nothing]\nrun(t)(0)\n//│ 0\n\nlet y = code\"1\"\nlet r = code\"\"\"x => x + ${y}\"\"\"\n//│ let y: Code[1, nothing]\n//│ let r: Code[Int -> Int, nothing]\n\nrun(r)(3)\n//│ Int\n\nlet x = code\"1\"\nlet r = code\"\"\"x => x + ${x}\"\"\"\n//│ let x: Code[1, nothing]\n//│ let r: Code[Int -> Int, nothing]\n\nrun(r)(0)\n//│ Int\n\nlet x = code\"2\"\n//│ let x: Code[2, nothing]\n\nlet r = code\"\"\"x => (let x = 1 in x + ${x})\"\"\"\n//│ let r: Code[anything -> Int, nothing]\n\nrun(r)(\"happy\")\n//│ Int\n\nlet inner4(x) = code\"let x = inner2 in ${x}\"\nlet c2 = code\"let x = inner1 in inner4(x)\"\n//│ let inner4: anything -> Code[forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a], nothing]\n//│ let c2: Code[Code[forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a], nothing], nothing]\nlet r = run(c2)\n//│ let r: Code[forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a], nothing]\nlet rr = run(r)\n//│ let rr: forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a]\nrr(code\"123\")\n//│ Code[anything -> Int, nothing]\n\nlet inner4(x) = code\"let y = 100 in ${x}\"\nlet c3 = code\"let x1 = inner1 in let x2 = inner2 in inner4(x)\"\n//│ let inner4: forall 'a 'b. Code['a, 'b] -> Code['a, 'b]\n//│ let c3: Code[Code[2, nothing], nothing]\nlet r = run(c3)\n//│ let r: Code[2, nothing]\nrun(r)\n//│ 2\n\n\nlet r = code\"x => ${code\"x + 1\"}\"\n//│ let r: Code[Int -> Int, nothing]\n\nrun(r)(1)\n//│ Int\n\n\nlet r = code\"x => ${ x }\"\nrun(r)\nrun(code\"x => ${ x }\")\n//│ let r: Code[forall 'a. 'a -> 'a, nothing]\n//│ forall 'b. 'b -> 'b\n\nf => code\"x => ${ let tmp = f(x) in x }\"\n//│ forall 'a 'b 'c. (Var[in 'a out 'a | 'b, in ??x out ??x0] -> anything) -> Code[('b & 'c) -> ('a | 'c), nothing]\n\nlet inner5(x) = code\"${x}\"\nlet r = code\"x => inner5(x)\"\n//│ let inner5: forall 'a 'b. Code['a, 'b] -> Code['a, 'b]\n//│ let r: Code[forall 'c 'd. Code['c, 'd] -> Code['c, 'd], nothing]\nrun(r)(code\"1\")\n//│ Code[1, nothing]\n\n:e\ncode\"code\"code\"x => ${x}\"\"\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.135: \tcode\"code\"code\"x => ${x}\"\"\"\n//│ ╙──       \t     ^^^^^^^^^^^^^^^^^^^^^\n//│ Code[error, nothing]\n\ncode\"r\"\n//│ Code[Code[forall 'a 'b. Code['a, 'b] -> Code['a, 'b], nothing], nothing]\n\n\ncode\"x => ${code\"${code\"${code\"x\"}\"}\"}\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n\nfun f(cde) = code\"x => ${code\"${code\"${code\"x + ${cde}\"}\"}\"}\"\nrun(f(Const(114)))(514)\n//│ fun f: forall 'a. Code[Int, 'a] -> Code[Int -> Int, 'a]\n//│ Int\n\nfun f(x) = code\"${run(x)} + 1\"\n//│ fun f: forall 'a. Code[Code[Int, 'a], nothing] -> Code[Int, 'a]\n\n:e\ncode\"x => ${code\"code\"code\"${x}\"\"\"}\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.157: \tcode\"x => ${code\"code\"code\"${x}\"\"\"}\"\n//│ ╙──       \t                 ^^^^^^^^^^^^^^^^\n//│ Code[anything -> error, nothing]\n\n:e\ncode\"xxx => ${code\"code\"code\"${xxx}\"\"\"}\"\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.164: \tcode\"xxx => ${code\"code\"code\"${xxx}\"\"\"}\"\n//│ ╙──       \t                   ^^^^^^^^^^^^^^^^^^\n//│ Code[anything -> error, nothing]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/qq/NuSyntax.mls",
    "content": ":NewDefs\n:NoJS\n\n`42\n//│ Code[42, nothing]\n\nx `=> x\n//│ Code[forall 'a. 'a -> 'a, nothing]\n\nx `=>\n  x\n//│ Code[forall 'a. 'a -> 'a, nothing]\n\nrun(x `=> x)(42)\n//│ 42\n\n`1 `+ `1\n//│ Code[Int, nothing]\n\n`(1 + 1)\n//│ Code[Int, nothing]\n\n\n`1 `< `2\n//│ Code[Bool, nothing]\n\n`1 `<= `2\n//│ Code[Bool, nothing]\n\n:p\n`1 `* `2 `+ `3\n//│ |`|1| |`|*| |`|2| |`|+| |`|3|\n//│ AST: TypingUnit(List(Quoted(App(Var(+),Tup(List((None,Fld(_,Unquoted(Quoted(App(Var(*),Tup(List((None,Fld(_,Unquoted(Quoted(IntLit(1))))), (None,Fld(_,Unquoted(Quoted(IntLit(2)))))))))))), (None,Fld(_,Unquoted(Quoted(IntLit(3)))))))))))\n//│ Parsed: code\"+(${code\"*(${code\"1\"}, ${code\"2\"},)\"}, ${code\"3\"},)\";\n//│ Code[Int, nothing]\n\n:p\n`1 `* `2 `+ `3 `- `4\n//│ |`|1| |`|*| |`|2| |`|+| |`|3| |`|-| |`|4|\n//│ AST: TypingUnit(List(Quoted(App(Var(-),Tup(List((None,Fld(_,Unquoted(Quoted(App(Var(+),Tup(List((None,Fld(_,Unquoted(Quoted(App(Var(*),Tup(List((None,Fld(_,Unquoted(Quoted(IntLit(1))))), (None,Fld(_,Unquoted(Quoted(IntLit(2)))))))))))), (None,Fld(_,Unquoted(Quoted(IntLit(3)))))))))))), (None,Fld(_,Unquoted(Quoted(IntLit(4)))))))))))\n//│ Parsed: code\"-(${code\"+(${code\"*(${code\"1\"}, ${code\"2\"},)\"}, ${code\"3\"},)\"}, ${code\"4\"},)\";\n//│ Code[Int, nothing]\n\n:p\n`1 `+ `2 `* `3\n//│ |`|1| |`|+| |`|2| |`|*| |`|3|\n//│ AST: TypingUnit(List(Quoted(App(Var(+),Tup(List((None,Fld(_,Unquoted(Quoted(IntLit(1))))), (None,Fld(_,Unquoted(Quoted(App(Var(*),Tup(List((None,Fld(_,Unquoted(Quoted(IntLit(2))))), (None,Fld(_,Unquoted(Quoted(IntLit(3))))))))))))))))))\n//│ Parsed: code\"+(${code\"1\"}, ${code\"*(${code\"2\"}, ${code\"3\"},)\"},)\";\n//│ Code[Int, nothing]\n\n:p\n`1 `+ `2 `* `3 `+ `4\n//│ |`|1| |`|+| |`|2| |`|*| |`|3| |`|+| |`|4|\n//│ AST: TypingUnit(List(Quoted(App(Var(+),Tup(List((None,Fld(_,Unquoted(Quoted(App(Var(+),Tup(List((None,Fld(_,Unquoted(Quoted(IntLit(1))))), (None,Fld(_,Unquoted(Quoted(App(Var(*),Tup(List((None,Fld(_,Unquoted(Quoted(IntLit(2))))), (None,Fld(_,Unquoted(Quoted(IntLit(3))))))))))))))))))), (None,Fld(_,Unquoted(Quoted(IntLit(4)))))))))))\n//│ Parsed: code\"+(${code\"+(${code\"1\"}, ${code\"*(${code\"2\"}, ${code\"3\"},)\"},)\"}, ${code\"4\"},)\";\n//│ Code[Int, nothing]\n\n:e\n:p\n1 + `2 `+ `3\n//│ |1| |+| |`|2| |`|+| |`|3|\n//│ AST: TypingUnit(List(Quoted(App(Var(+),Tup(List((None,Fld(_,Unquoted(App(Var(+),Tup(List((None,Fld(_,IntLit(1))), (None,Fld(_,Quoted(IntLit(2)))))))))), (None,Fld(_,Unquoted(Quoted(IntLit(3)))))))))))\n//│ Parsed: code\"+(${+(1, code\"2\",)}, ${code\"3\"},)\";\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.60: \t1 + `2 `+ `3\n//│ ║        \t^^^^^^\n//│ ╟── code fragment of type `Code[2, nothing]` is not an instance of type `Int`\n//│ ║  l.60: \t1 + `2 `+ `3\n//│ ╙──      \t    ^^\n//│ ╔══[ERROR] Type mismatch in unquote:\n//│ ║  l.60: \t1 + `2 `+ `3\n//│ ║        \t^^^^^^\n//│ ╙── operator application of type `Int` is not an instance of type `Code`\n//│ Code[Int, error]\n\n:e\n:p\n`1 `+ `2 + 3\n//│ |`|1| |`|+| |`|2| |+| |3|\n//│ AST: TypingUnit(List(App(Var(+),Tup(List((None,Fld(_,Quoted(App(Var(+),Tup(List((None,Fld(_,Unquoted(Quoted(IntLit(1))))), (None,Fld(_,Unquoted(Quoted(IntLit(2))))))))))), (None,Fld(_,IntLit(3))))))))\n//│ Parsed: +(code\"+(${code\"1\"}, ${code\"2\"},)\", 3,);\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.78: \t`1 `+ `2 + 3\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── code fragment of type `Code[?a, ?b | ?c]` is not an instance of type `Int`\n//│ ║  l.78: \t`1 `+ `2 + 3\n//│ ╙──      \t^^^^^^^^\n//│ Int | error\n\nx `=> x `+ `1\n//│ Code[Int -> Int, nothing]\n\ny `=> `0 `- y\n//│ Code[Int -> Int, nothing]\n\n:e\nz `=> z + 1\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.97: \tz `=> z + 1\n//│ ║        \t      ^^^^^\n//│ ╟── reference of type `Var[?a, ?z]` is not an instance of type `Int`\n//│ ║  l.97: \tz `=> z + 1\n//│ ╙──      \t      ^\n//│ ╔══[ERROR] Type mismatch in unquote:\n//│ ║  l.97: \tz `=> z + 1\n//│ ║        \t      ^^^^^\n//│ ╙── operator application of type `Int` is not an instance of type `Code`\n//│ Code[anything -> error, nothing]\n\n\n(x, y) `=> x `+ y\n//│ Code[(Int, Int) -> Int, nothing]\n\nrun((x, y) `=> x `+ y)(1, 2)\n//│ Int\n\n\n`let x = `42 `in x `+ `1\n//│ Code[Int, nothing]\n\n\nfun f(x: Code[Int, nothing]) =\n  `let t = x `in t\n//│ fun f: (x: Code[Int, nothing]) -> Code[Int, nothing]\n\n:e\n`let x = `0 `in `let y = 1 `in x `+ y\n//│ ╔══[ERROR] Type mismatch in unquote:\n//│ ║  l.127: \t`let x = `0 `in `let y = 1 `in x `+ y\n//│ ║         \t                         ^\n//│ ╙── integer literal of type `1` is not an instance of type `Code`\n//│ Code[Int, nothing]\n\n\nf `=> a `=> f`(a)\n//│ Code[forall 'a 'b. ('a -> 'b) -> 'a -> 'b, nothing]\n\n`let app = (f, a) `=> f`(a) `in `let id = x `=> x `in app`(id, `42)\n//│ Code[42, nothing]\n\n\n`if `(1 == 1) then `1 else `2\n//│ Code[1 | 2, nothing]\n\nfun foo(x) =\n  `if x `== `1 then `1 else `2\n//│ fun foo: forall 'a. Code[Num, 'a] -> Code[1 | 2, 'a]\n\nfun foo(x) =\n  `if `(1 == 1) then x else `2\n//│ fun foo: forall 'a 'b. Code['a, 'b] -> Code[2 | 'a, 'b]\n\n\n`if `1 `< `2 `and `1 `> `2 then `0 else `1\n//│ Code[0 | 1, nothing]\n\n:e\n`(`42)\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.158: \t`(`42)\n//│ ╙──       \t  ^^^\n//│ Code[error, nothing]\n\n:e\n`(x `=> x)\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.165: \t`(x `=> x)\n//│ ╙──       \t  ^^^^^^^\n//│ Code[error, nothing]\n\n:pe\n`fun foo = 42\n`val bar = 0\n//│ ╔══[PARSE ERROR] This quote syntax is not supported yet\n//│ ║  l.172: \t`fun foo = 42\n//│ ╙──       \t^\n//│ ╔══[PARSE ERROR] Expected end of input; found 'fun' keyword instead\n//│ ║  l.172: \t`fun foo = 42\n//│ ╙──       \t ^^^\n//│ ()\n\n\nlet x = `42\n//│ let x: Code[42, nothing]\n\n:pe\n:w\n:e\n`if x\n  `> `1 then `0\n  `== `1 then `1\n  _ then `2\n//│ ╔══[PARSE ERROR] This quote syntax is not supported yet\n//│ ║  l.190: \t  `> `1 then `0\n//│ ╙──       \t  ^\n//│ ╔══[PARSE ERROR] Unexpected operator here\n//│ ║  l.190: \t  `> `1 then `0\n//│ ╙──       \t   ^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.189: \t`if x\n//│ ║         \t    ^\n//│ ║  l.190: \t  `> `1 then `0\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.191: \t  `== `1 then `1\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ║  l.192: \t  _ then `2\n//│ ╙──       \t^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.189: \t`if x\n//│ ║         \t    ^\n//│ ║  l.190: \t  `> `1 then `0\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.191: \t  `== `1 then `1\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ║  l.192: \t  _ then `2\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.189: \t`if x\n//│ ╙──       \t ^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.190: \t  `> `1 then `0\n//│ ╙──       \t  ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.189: \t`if x\n//│ ║         \t    ^\n//│ ║  l.190: \t  `> `1 then `0\n//│ ║         \t^^^^^^^^^^^^^^^\n//│ ║  l.191: \t  `== `1 then `1\n//│ ║         \t^^^^^^^^^^^^^^^^\n//│ ║  l.192: \t  _ then `2\n//│ ║         \t^^^^^^^^^^^\n//│ ╟── code fragment of type `Code[42, nothing]` is not a function\n//│ ║  l.183: \tlet x = `42\n//│ ║         \t        ^^^\n//│ ╟── but it flows into reference with expected type `() -> ?a`\n//│ ║  l.189: \t`if x\n//│ ╙──       \t    ^\n//│ ╔══[ERROR] Type mismatch in unquote:\n//│ ║  l.190: \t  `> `1 then `0\n//│ ║         \t  ^\n//│ ╙── undefined literal of type `()` is not an instance of type `Code`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.190: \t  `> `1 then `0\n//│ ║         \t  ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ Code[error, nothing]\n\n:pe\n`(x: Int) => x `+ `2\n//│ ╔══[PARSE ERROR] This quote syntax is not supported yet\n//│ ║  l.249: \t`(x: Int) => x `+ `2\n//│ ╙──       \t ^^^^^^^^\n//│ () -> Code[Int, nothing]\n\n:pe\n`\n//│ ╔══[PARSE ERROR] This quote syntax is not supported yet\n//│ ║  l.256: \t`\n//│ ╙──       \t^\n//│ ()\n\n\n:pe\n`42 `\n//│ ╔══[PARSE ERROR] This quote syntax is not supported yet\n//│ ║  l.264: \t`42 `\n//│ ╙──       \t^^^\n//│ Code[42, nothing]\n"
  },
  {
    "path": "shared/src/test/diff/qq/PEPM.mls",
    "content": ":NewDefs\n\n:ne\n:js\nlet a = code\"1 + 1\"\nlet b = code\"40 + ${a}\"\n//│ let a: Code[Int, nothing]\n//│ let b: Code[Int, nothing]\n//│ // Prelude\n//│ let res;\n//│ class TypingUnit {}\n//│ const typing_unit = new TypingUnit;\n//│ // Query 1\n//│ globalThis.a = App(Var(\"+\"), IntLit(1), IntLit(1));\n//│ // Query 2\n//│ globalThis.b = App(Var(\"+\"), IntLit(40), a);\n//│ // End of generated code\n\n:ne\nrun(b)\n//│ Int\n\n:ne\nlet one = Const(42)\nlet one' = code\"42\"\nlet one'' = let tmp = 42 in Const(tmp)\n//│ let one: Code[Int, nothing]\n//│ let one': Code[42, nothing]\n//│ let one'': Code[Int, nothing]\n\ndeclare module Math {\n  declare fun floor(x: Num): Int\n}\n//│ declare module Math {\n//│   fun floor: (x: Num) -> Int\n//│ }\n\nfun even(n) = n % 2 == 0\n//│ fun even: Int -> Bool\n\n// x^n\nfun power(x, n) =\n  if (n == 0) then 1\n  else if (even(n)) then let t = power(x, Math.floor(n / 2)) in t * t\n  else x * power(x, n - 1)\n//│ fun power: (Int, Int) -> Int\n\npower(3, 3)\npower(2, 10)\n//│ Int\n//│ res\n//│     = 27\n//│ res\n//│     = 1024\n\n\n// x^n\n:js\nfun power'(x, n) =\n  if (n == 0) then Const(1)\n  else if (even(n)) then code\"let t = ${power'(x, Math.floor(n / 2))} in t * t\"\n  else code\"${x} * ${power'(x, n - 1)}\"\n//│ fun power': forall 'a. (Code[Int, 'a], Int) -> Code[Int, 'a]\n//│ // Prelude\n//│ class TypingUnit7 {}\n//│ const typing_unit7 = new TypingUnit7;\n//│ // Query 1\n//│ globalThis.power$ = function power$(x, n) {\n//│   return ((() => {\n//│     return ((ucs$test$0) => ucs$test$0 === true ? Const(1) : ((ucs$test$0) => ucs$test$0 === true ? ((t1) => Let(Var(t1), power$(x, Math.floor(n / 2)), App(Var(\"*\"), Var(t1), Var(t1))))(freshName(\"t\")) : App(Var(\"*\"), x, power$(x, n - 1)))(even(n)))((n == 0));\n//│   })());\n//│ };\n//│ // End of generated code\n\n:ne\n:js\nlet power10 = run(code\"x => ${power'(code\"x\", 10)}\")\n//│ let power10: Int -> Int\n//│ // Prelude\n//│ class TypingUnit8 {}\n//│ const typing_unit8 = new TypingUnit8;\n//│ // Query 1\n//│ globalThis.power10 = run(((x1) => Lam(Var(x1), power$(Var(x1), 10)))(freshName(\"x\")));\n//│ // End of generated code\n\n\n:ne\n:js\ncode\"x => x\"\n//│ Code[forall 'a. 'a -> 'a, nothing]\n//│ // Prelude\n//│ class TypingUnit9 {}\n//│ const typing_unit9 = new TypingUnit9;\n//│ // Query 1\n//│ res = ((x1) => Lam(Var(x1), Var(x1)))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:ne\n:js\ncode\"let x = 42 in x\"\n//│ Code[42, nothing]\n//│ // Prelude\n//│ class TypingUnit10 {}\n//│ const typing_unit10 = new TypingUnit10;\n//│ // Query 1\n//│ res = ((x1) => Let(Var(x1), IntLit(42), Var(x1)))(freshName(\"x\"));\n//│ // End of generated code\n\n\n:ne\nfun test(f) =\n  code\"x => x + ${f(code\"x + 1\")}\"\n//│ fun test: forall 'a. (Code[Int, ??x] -> Code[Int, 'a]) -> Code[Int -> Int, 'a]\n\n:ne\n:e\ncode\"x => ${ test(run) }\"\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.118: \tcode\"x => ${ test(run) }\"\n//│ ║         \t             ^^^^^^^^^\n//│ ╟── type variable `?x` leaks out of its scope\n//│ ╟── into type `nothing`\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.113: \t  code\"x => x + ${f(code\"x + 1\")}\"\n//│ ╙──       \t                  ^\n//│ Code[anything -> nothing, nothing]\n\n:ne\nfun assertNotZero(x) =\n  code\"if (${x} == 0) then error else ${x}\"\n//│ fun assertNotZero: forall 'a 'b. Code[Num & 'a, 'b] -> Code['a, 'b]\n\n:ne\nfun safeDiv = run(code\"x => y => let t = ${assertNotZero(code\"y\")} in x / t\")\n//│ fun safeDiv: Num -> Num -> Num\n\n:ne\nassertNotZero(Const(42))\n//│ Code[Int, nothing]\n\n:ne\nsafeDiv(10)(2)\n//│ Num\n\n:ne\nfun fac(n, dbg) =\n  if (n > 0) then code\"let x = ${Const(n)} in ${dbg(code\"x\")} * ${fac(n - 1, dbg)}\" else Const(1)\n//│ fun fac: forall 'a. (Int, Code[Int, ??x] -> Code[Int, 'a]) -> Code[Int, 'a]\n\nfun showAndRet(n: Code['a, anything]) =\n  log(n)\n  n\n//│ fun showAndRet: forall 'a. (n: Code['a, anything]) -> Code['a, anything]\n\n:ne\nfun bar(x: Code['a, 'b]) = x\n//│ fun bar: forall 'a 'b. (x: Code['a, 'b]) -> Code['a, 'b]\n\n\n:ne\nfac(10, showAndRet)\n//│ Code[Int, anything]\n\n\nfun inc(x, dbg) =\n  dbg(x); inc(code\"${x} + 1\", dbg)\n//│ fun inc: forall 'a. (Code[Int, 'a], Code[Int, 'a] -> ()) -> nothing\n"
  },
  {
    "path": "shared/src/test/diff/qq/PEPM2.mls",
    "content": ":NewDefs\n:QQ\n\n\nfun power(x) = case\n  0 then `1.0\n  n then x `*. power(x)(n - 1)\n//│ fun power: forall 'a. Code[Num, 'a] -> (0 | Int & ~0) -> Code[Num, 'a]\n\nrun(x `=> id(x) `* x)\n//│ Int -> Int\n//│ res\n//│     = Quoted:\n//│       (x_0) =>\n//│         (x_0 * x_0)\n//│       undefined\n\nrun(`(x => x + x))\n//│ Int -> Int\n//│ res\n//│     = Quoted:\n//│       ((x_1) =>\n//│         (x_1 + x_1))\n//│       undefined\n\n\nfun assertNotZero(x) =\n  `if (x `== `0.0) then `error else x\nfun checkedDiv = x `=> y `=> x `/ assertNotZero(y)\nrun(checkedDiv)\n//│ fun assertNotZero: forall 'a 'b. Code[Num & 'a, 'b] -> Code['a, 'b]\n//│ fun checkedDiv: Code[Num -> Num -> Num, nothing]\n//│ Num -> Num -> Num\n//│ res\n//│     = Quoted:\n//│       (x_2) =>\n//│         (y_0) =>\n//│           (x_2 / let ucs$test$0_0 =\n//│             (y_0 == 0)\n//│             in match ucs$test$0_0:\n//│               case true => error\n//│               _ => y_0))\n//│       undefined\n\nfun show: Code[anything, anything] -> Str = _ => \"debug\"\nfun inc(dbg) =\n  x `=> let c = x `+ `1 in dbg(c), c\ninc(c => log(show(c)))\n//│ fun show: Code[anything, anything] -> Str\n//│ fun inc: (Code[Int, anything] -> anything) -> Code[Int -> Int, nothing]\n//│ Code[Int -> Int, nothing]\n//│ res\n//│     = '(x_3) =>\\n  (x_3 + 1)'\n//│ // Output\n//│ debug\n\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then body(y, x `+ y)(n - 1)\nfun gib_naive(n) =\n  (x, y) `=> body(x, y)(n)\nlet gn5 = run(gib_naive(5))\n//│ fun body: forall 'a. (Code[Int, 'a], Code[Int, 'a]) -> (0 | 1 | Int & ~0 & ~1) -> Code[Int, 'a]\n//│ fun gib_naive: (0 | 1 | Int & ~0 & ~1) -> Code[(Int, Int) -> Int, nothing]\n//│ let gn5: (Int, Int) -> Int\n//│ gn5\n//│     = Quoted:\n//│       (x_4) =>\n//│         (y_1) =>\n//│           ((y_1 + (x_4 + y_1)) + ((x_4 + y_1) + (y_1 + (x_4 + y_1))))\n//│       undefined\n\nfun bind(rhs, k) = `let x = rhs `in k(x)\n//│ fun bind: forall 'a 'b 'c. (Code['a, 'b], Var['a, in ??x out ??x0] -> Code['c, 'b]) -> Code['c, 'b]\n\nfun bind(rhs, k: forall 'g : Code['a, 'g] -> Code['b, 'c | 'g]) =\n  `let x = rhs `in k(x)\n//│ fun bind: forall 'a 'c 'b. (Code['a, 'c], k: forall 'g. Code['a, 'g] -> Code['b, 'c | 'g]) -> Code['b, 'c]\n\nbind : forall 'a, 'c, 'g: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n//│ forall 'a 'g. (Code['a, 'g], k: forall 'c. Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g]\n//│ res\n//│     = [Function: bind1]\n\nfun body: forall 'g : (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then bind of x `+ y, z => body(y, z)(n - 1)\nfun gib(n) = ((x, y) `=> body(x, y)(n))\nlet g5 = run(gib(5))\n//│ fun body: forall 'a. (Code[Int, 'a], Code[Int, 'a]) -> (0 | 1 | Int & ~0 & ~1) -> Code[Int, 'a]\n//│ fun gib: Int -> Code[(Int, Int) -> Int, nothing]\n//│ let g5: (Int, Int) -> Int\n//│ fun body: forall 'g. (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\n//│ g5\n//│    = Quoted:\n//│      (x_5) =>\n//│        (y_2) =>\n//│          let x_6 =\n//│            (x_5 + y_2)\n//│            in let x_7 =\n//│              (y_2 + x_6)\n//│              in let x_8 =\n//│                (x_6 + x_7)\n//│                in let x_9 =\n//│                  (x_7 + x_8)\n//│                  in x_9\n//│      undefined\n"
  },
  {
    "path": "shared/src/test/diff/qq/PseudoCod.mls",
    "content": "// * A testbed to reproduce potential QQ problems with simpler types\n\n:NewDefs\n:NoJS\n\n\nclass Cod[out A, out C]\n//│ class Cod[A, C] {\n//│   constructor()\n//│ }\n\n// * Plain code with C context requirements\nclass Plain[out A, out C]\n//│ class Plain[A, C] {\n//│   constructor()\n//│ }\n\nfun run: Cod['a, nothing] -> 'a\n//│ fun run: forall 'a. Cod['a, nothing] -> 'a\n\nval const: Cod[Int, nothing]\nfun quote: Array[Plain['a, 'c]] -> Cod['a, 'c]\nfun unquote: Cod['a, 'c] -> Plain['a, 'c]\nfun lam: (forall 'c: Cod['a, 'c] -> Cod['b, 'c | 'g]) -> Cod['a -> 'b, 'g]\n//│ fun quote: forall 'a 'c. Array[Plain['a, 'c]] -> Cod['a, 'c]\n//│ val const: Cod[Int, nothing]\n//│ fun lam: forall 'a0 'b 'g. (forall 'c0. Cod['a0, 'c0] -> Cod['b, 'c0 | 'g]) -> Cod['a0 -> 'b, 'g]\n//│ fun unquote: forall 'a1 'c1. Cod['a1, 'c1] -> Plain['a1, 'c1]\n\nfun (%>) bind: (Cod['a, 'g], k: forall 'c: Cod['a, 'c] -> Cod['b, 'c | 'g]) -> Cod['b, 'g]\n//│ fun (%>) bind: forall 'a 'g 'b. (Cod['a, 'g], k: forall 'c. Cod['a, 'c] -> Cod['b, 'c | 'g]) -> Cod['b, 'g]\n\nlet f = k => bind of const, k\n//│ let f: forall 'b 'g. (forall 'c. Cod[Int, 'c] -> Cod['b, 'c | 'g]) -> Cod['b, 'g]\n\nf(id)\n//│ Cod[Int, nothing]\n\n\n// * Note: expected extrusion (needs polymorphic recursion)\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then quote([unquote(x), unquote(y)]) %> z => body(x, z)(n - 1)\n//│ fun body: forall 'b 'a. (Cod['b, anything] & 'a, Cod['b, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Cod['b, anything] | 'a)\n\n// code\"(x, y) => ${body(code\"x\", code\"y\")(0)}\"\n\nlet l = lam(x => lam(y => body(x, y)(0)))\n//│ let l: Cod['a -> 'a -> 'a, ??c & ~??c0]\n\n// * Expected error: `body` needed polymorphic recursion\n// * TODO improve error locations!\n:e\nrun(l)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.55: \trun(l)\n//│ ║        \t^^^^^^\n//│ ╟── type `??c & ~??c0` does not match type `nothing`\n//│ ║  l.24: \tfun lam: (forall 'c: Cod['a, 'c] -> Cod['b, 'c | 'g]) -> Cod['a -> 'b, 'g]\n//│ ║        \t                                                                       ^^\n//│ ╟── Note: constraint arises from type reference:\n//│ ║  l.18: \tfun run: Cod['a, nothing] -> 'a\n//│ ╙──      \t                 ^^^^^^^\n//│ error | 'a -> 'a -> 'a\n\n\nfun body: forall 'g: (Cod[Int, 'g], Cod[Int, 'g]) -> Int -> Cod[Int, 'g]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then quote([unquote(x), unquote(y)]) %> z => body(x, z)(n - 1)\n//│ fun body: forall 'g. (Cod[Int, 'g], Cod[Int, 'g]) -> (0 | 1 | Int & ~0 & ~1) -> Cod[Int, 'g]\n//│ fun body: forall 'g0. (Cod[Int, 'g0], Cod[Int, 'g0]) -> Int -> Cod[Int, 'g0]\n\nlet l = lam(x => lam(y => body(x, y)(0)))\nrun(l)\n//│ let l: Cod[Int -> Int -> Int, nothing]\n//│ Int -> Int -> Int\n\n\n// * An unnecessary complication, just for testing purposes:\n\nfun body: forall 'g: (Cod[Int, 'g], Cod[Int, 'g]) -> Int -> Cod[Int, 'g]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then quote([unquote(x), unquote(y)]) %> z => quote([unquote(body(x, z)(n - 1))])\n//│ fun body: forall 'g. (Cod[Int, 'g], Cod[Int, 'g]) -> (0 | 1 | Int & ~0 & ~1) -> Cod[Int, 'g]\n//│ fun body: forall 'g0. (Cod[Int, 'g0], Cod[Int, 'g0]) -> Int -> Cod[Int, 'g0]\n\nlet l = lam(x => lam(y => body(x, y)(0)))\nrun(l)\n//│ let l: Cod[Int -> Int -> Int, nothing]\n//│ Int -> Int -> Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/qq/QQFlag.mls",
    "content": ":NewDefs\n:QQ\n\n\nrun(code\"42\")\n//│ 42\n//│ res\n//│     = Quoted:\n//│       42\n//│       undefined\n\n:js\nrun(code\"x => x\")\n//│ forall 'a. 'a -> 'a\n//│ // Prelude\n//│ class TypingUnit1 {}\n//│ const typing_unit1 = new TypingUnit1;\n//│ // Query 1\n//│ res = run(((x1) => Lam(Var(x1), Var(x1)))(freshName(\"x\")));\n//│ // End of generated code\n//│ res\n//│     = Quoted:\n//│       (x_0) =>\n//│         x_0\n//│       undefined\n\n\nrun(code\"x => y => x + y\")\n//│ Int -> Int -> Int\n//│ res\n//│     = Quoted:\n//│       (x_1) =>\n//│         (y_0) =>\n//│           (x_1 + y_0)\n//│       undefined\n\n\nrun(code\"(x => x + 1)(2)\")\n//│ Int\n//│ res\n//│     = Quoted:\n//│       ((x_2) =>\n//│         (x_2 + 1))(2)\n//│       undefined\n\n\nrun(code\"x => x\")\n//│ forall 'a. 'a -> 'a\n//│ res\n//│     = Quoted:\n//│       (x_3) =>\n//│         x_3\n//│       undefined\n\n\nrun(code\"let x = 42 in x + 0\")\n//│ Int\n//│ res\n//│     = Quoted:\n//│       let x_4 =\n//│         42\n//│         in (x_4 + 0)\n//│       undefined\n\n:e\nrun(code\"code\"114\"\")\n//│ ╔══[ERROR] Nested quotation is not allowed.\n//│ ║  l.66: \trun(code\"code\"114\"\")\n//│ ╙──      \t         ^^^^^^^^^\n//│ error\n//│ Code generation encountered an error:\n//│   nested quotation is not allowed.\n\n\ndeclare module Math {\n  declare fun floor(x: Num): Int\n}\nfun even(n) = n % 2 == 0\nfun power'(x, n) =\n  if (n == 0) then Const(1)\n  else if (even(n)) then code\"let t = ${power'(x, Math.floor(n / 2))} in t * t\"\n  else code\"${x} * ${power'(x, n - 1)}\"\nrun(code\"x => ${power'(code\"x\", 10)}\")\n//│ declare module Math {\n//│   fun floor: (x: Num) -> Int\n//│ }\n//│ fun even: Int -> Bool\n//│ fun power': forall 'a. (Code[Int, 'a], Int) -> Code[Int, 'a]\n//│ Int -> Int\n//│ res\n//│     = Quoted:\n//│       (x_5) =>\n//│         let t_0 =\n//│           (x_5 * let t_1 =\n//│             let t_2 =\n//│               (x_5 * 1)\n//│               in (t_2 * t_2)\n//│             in (t_1 * t_1))\n//│           in (t_0 * t_0)\n//│       undefined\n\nrun(code\"x => if (x == 42) then 42 else 0\")\n//│ Num -> (0 | 42)\n//│ res\n//│     = Quoted:\n//│       (x_6) =>\n//│         let ucs$test$0_0 =\n//│           ((x_6 == 42))\n//│           in match ucs$test$0_0:\n//│             case true => 42\n//│             _ => 0)\n//│       undefined\n"
  },
  {
    "path": "shared/src/test/diff/qq/ScopeTypes.mls",
    "content": ":NewDefs\n:NoJS\n\n\nrun\n//│ forall 'a. Code['a, nothing] -> 'a\n\n:e\ncode\"x => ${run(code\"x\")}\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.9: \tcode\"x => ${run(code\"x\")}\"\n//│ ║       \t            ^^^^^^^^^^^^\n//│ ╙── expression of type `?x` does not match type `nothing`\n//│ Code[forall 'a. Code['a, anything] -> 'a, nothing]\n\n\nfun test(cde) =\n  code\"x => x + ${cde}\"\n//│ fun test: forall 'a. Code[Int, 'a] -> Code[Int -> Int, 'a]\n\n:e\ncode\"y => ${ run(test(code\"y\")), code\"0\" }\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.22: \tcode\"y => ${ run(test(code\"y\")), code\"0\" }\"\n//│ ║        \t             ^^^^^^^^^^^^^^^^^^\n//│ ╟── code fragment context type of type `?y` does not match type `nothing`\n//│ ║  l.18: \t  code\"x => x + ${cde}\"\n//│ ╙──      \t                  ^^^\n//│ Code[Int -> 0, nothing]\n\n\nfun test(cde, f) =\n  code\"x => x + ${f(cde)}\"\n//│ fun test: forall 'a 'b. ('a, 'a -> Code[Int, 'b]) -> Code[Int -> Int, 'b]\n\nrun(test(code\"1\", id))\n//│ Int -> Int\n\n\nfun test(cde: Code[Int, 'a], f: forall 'c: Code[Int, 'c] -> Code[Int, 'c]) =\n  code\"x => x + ${f(cde)}\"\n//│ fun test: forall 'a. (cde: Code[Int, 'a], f: forall 'c. Code[Int, 'c] -> Code[Int, 'c]) -> Code[Int -> Int, 'a]\n\nrun(test(code\"1\", id))\n//│ Int -> Int\n\n:e\ncode\"x => ${ run(test(code\"x\", id)), code\"x\" }\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.48: \tcode\"x => ${ run(test(code\"x\", id)), code\"x\" }\"\n//│ ║        \t             ^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── type `?x` does not match type `nothing`\n//│ ║  l.40: \tfun test(cde: Code[Int, 'a], f: forall 'c: Code[Int, 'c] -> Code[Int, 'c]) =\n//│ ╙──      \t                        ^^\n//│ Code[forall 'a. (Int & 'a) -> 'a, nothing]\n\n:e\ncode\"x => ${ let c = code\"x\" in run(test(c, id)), c }\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.58: \tcode\"x => ${ let c = code\"x\" in run(test(c, id)), c }\"\n//│ ║        \t                                ^^^^^^^^^^^^^^^^\n//│ ╟── type `?x` does not match type `nothing`\n//│ ║  l.40: \tfun test(cde: Code[Int, 'a], f: forall 'c: Code[Int, 'c] -> Code[Int, 'c]) =\n//│ ╙──      \t                        ^^\n//│ Code[forall 'a. (Int & 'a) -> 'a, nothing]\n\n\nfun test(f) =\n  code\"x => x + ${f(code\"x + 1\")}\"\n//│ fun test: forall 'a. (Code[Int, ??x] -> Code[Int, 'a]) -> Code[Int -> Int, 'a]\n\n\nlet myrun = c => run(c)\n//│ let myrun: forall 'a. Code['a, nothing] -> 'a\n\n:e\ncode\"x => ${ test(myrun) }\"\n//│ ╔══[ERROR] Type error in application\n//│ ║  l.77: \tcode\"x => ${ test(myrun) }\"\n//│ ║        \t             ^^^^^^^^^^^\n//│ ╟── type variable `?x` leaks out of its scope\n//│ ╟── into type `nothing`\n//│ ╟── adding a type annotation to any of the following terms may help resolve the problem\n//│ ╟── • this reference:\n//│ ║  l.69: \t  code\"x => x + ${f(code\"x + 1\")}\"\n//│ ╙──      \t                  ^\n//│ Code[anything -> nothing, nothing]\n\n:e\ncode\"x => ${ test(c => run(c), code\"0\") }\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.90: \tcode\"x => ${ test(c => run(c), code\"0\") }\"\n//│ ║        \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument list of type `[forall ?a ?b. ?b -> ?a, Code[0, nothing]]` does not match type `[?c]`\n//│ ║  l.90: \tcode\"x => ${ test(c => run(c), code\"0\") }\"\n//│ ╙──      \t                 ^^^^^^^^^^^^^^^^^^^^^^\n//│ Code[anything -> Int -> Int, nothing]\n\n\n:e\ncode\"x => ${ test(c => run(c), code\"x\") }\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.101: \tcode\"x => ${ test(c => run(c), code\"x\") }\"\n//│ ║         \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument list of type `[forall ?a ?b. ?b -> ?a, Code[?c, ?x]]` does not match type `[?d]`\n//│ ║  l.101: \tcode\"x => ${ test(c => run(c), code\"x\") }\"\n//│ ╙──       \t                 ^^^^^^^^^^^^^^^^^^^^^^\n//│ Code[anything -> Int -> Int, nothing]\n\n\n:e\nfun test2(a) = code\"x => ${ test(c => run(c), a) }\"\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.112: \tfun test2(a) = code\"x => ${ test(c => run(c), a) }\"\n//│ ║         \t                            ^^^^^^^^^^^^^^^^^^^^\n//│ ╟── argument list of type `[forall ?a ?b. ?b -> ?a, ?c]` does not match type `[?d]`\n//│ ║  l.112: \tfun test2(a) = code\"x => ${ test(c => run(c), a) }\"\n//│ ╙──       \t                                ^^^^^^^^^^^^^^^^\n//│ fun test2: anything -> Code[anything -> Int -> Int, nothing]\n\ntype Hide[C] = C & (C | Int)\n//│ type Hide[C] = C\n\nlet r = code\"y => ${ code\"x => ${ code\"x + y\": Code[Int, Hide['a]] }\" }\"\nrun(r)\n//│ let r: Code[Int -> Int -> Int, nothing]\n//│ Int -> Int -> Int\n\nfun f[A](x: Code[Int, A]): Code[Int, A] = code\"${x} + 1\"\n//│ fun f: forall 'A. (x: Code[Int, 'A]) -> Code[Int, 'A]\n\nrun(f(Const(42)))\n//│ Int\n\nrun(code\"x => x + 1 + ${f(code\"x\")}\")\n//│ Int -> Int\n"
  },
  {
    "path": "shared/src/test/diff/qq/Triple.mls",
    "content": ":NewDefs\n:NoJS\n\n\n\"normal string\"\n//│ \"normal string\"\n\n\"\"\"hello world\"\"\"\n//│ \"hello world\"\n\n\"\"\"hello\nworld\"\"\"\n//│ \"hello\n//│ world\"\n\n\ncode\"\"\" \"hello world\" \"\"\"\n//│ Code[\"hello world\", nothing]\n\n\ncode\"\"\"if 0 == 0 then 1\nelse 0\n\"\"\"\n//│ Code[0 | 1, nothing]\n\n:pe\n:w\n:e\ncode\"\"wrong example\"\"\n//│ ╔══[PARSE ERROR] Unexpected end of quasiquote section; an expression was expected here\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ╙──      \t     ^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ╙──      \t            ^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ╙──      \t      ^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] identifier not found: wrong\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ╙──      \t      ^^^^^\n//│ ╔══[ERROR] identifier not found: example\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ╙──      \t            ^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── code fragment of type `Code[(), nothing]` is not a function\n//│ ║  l.29: \tcode\"\"wrong example\"\"\n//│ ╙──      \t^^^^^^\n//│ error\n\ncode\"\"\"\"hello world\"\"\"\"\n//│ Code[\"hello world\", nothing]\n\n:pe\ncode\"\"\" \"HKUST\"\n//│ ╔══[PARSE ERROR] Unmatched opening quasiquote triple\n//│ ║  l.60: \tcode\"\"\" \"HKUST\"\n//│ ╙──      \t^^^^^^^\n//│ \"HKUST\"\n"
  },
  {
    "path": "shared/src/test/diff/qq/Unquote.mls",
    "content": ":NewDefs\n:NoJS\n\n\n:e\nlet res = code\"x\"\ncode\"(x) => ${res}\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.6: \tlet res = code\"x\"\n//│ ╙──     \t               ^\n//│ let res: Code[error, nothing]\n//│ Code[anything -> error, nothing]\n\n\n:e\nlet res = code\"x\"\ncode\"let y = 1 in ${res}\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.16: \tlet res = code\"x\"\n//│ ╙──      \t               ^\n//│ let res: Code[error, nothing]\n//│ Code[error, nothing]\n\n\n:e\nlet a = code\"x\"\nlet b = code\"y\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.26: \tlet a = code\"x\"\n//│ ╙──      \t             ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.27: \tlet b = code\"y\"\n//│ ╙──      \t             ^\n//│ let a: Code[error, nothing]\n//│ let b: Code[error, nothing]\n\n\n:e\ncode\"a + a\"\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.39: \tcode\"a + a\"\n//│ ║        \t     ^^^^^\n//│ ╟── code fragment of type `Code[error, nothing]` is not an instance of type `Int`\n//│ ║  l.26: \tlet a = code\"x\"\n//│ ║        \t        ^^^^^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.39: \tcode\"a + a\"\n//│ ╙──      \t     ^\n//│ Code[Int | error, nothing]\n\n\n:e\ncode\"a + b\"\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.53: \tcode\"a + b\"\n//│ ║        \t     ^^^^^\n//│ ╟── code fragment of type `Code[error, nothing]` is not an instance of type `Int`\n//│ ║  l.26: \tlet a = code\"x\"\n//│ ║        \t        ^^^^^^^\n//│ ╟── but it flows into reference with expected type `Int`\n//│ ║  l.53: \tcode\"a + b\"\n//│ ╙──      \t     ^\n//│ Code[Int | error, nothing]\n\n\n:e\ncode\"x + (let x = 2 in x * x)\"\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.67: \tcode\"x + (let x = 2 in x * x)\"\n//│ ╙──      \t     ^\n//│ Code[Int, nothing]\n\n\n:e\nlet a = code\"x\"\nlet b = code\"y\"\nlet x = 1\ncode\"let x = 1\n${a} + (let y = 1 in ${b})\n\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.76: \tlet b = code\"y\"\n//│ ╙──      \t             ^\n//│ let a: Code[1, nothing]\n//│ let b: Code[error, nothing]\n//│ let x: 1\n//│ Code[Int, nothing]\n\n\n\nlet cde = code\"a\"\n//│ let cde: Code[Code[1, nothing], nothing]\n\nlet cde_w_unquote = code\"${cde}\"\n//│ let cde_w_unquote: Code[Code[1, nothing], nothing]\n\n\n:e\nlet cde_w_free_vars = code\"let x = 1 in x + y\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.99: \tlet cde_w_free_vars = code\"let x = 1 in x + y\"\n//│ ╙──      \t                                            ^\n//│ let cde_w_free_vars: Code[Int, nothing]\n\n\nlet cde_w_unquote_w_free_vars = code\"${cde_w_free_vars}\"\n//│ let cde_w_unquote_w_free_vars: Code[Int, nothing]\n\n\n:e\nlet cde_w_unquote_w_local_free_vars = code\"[z, ${cde_w_unquote_w_free_vars}]\"\n//│ ╔══[ERROR] identifier not found: z\n//│ ║  l.111: \tlet cde_w_unquote_w_local_free_vars = code\"[z, ${cde_w_unquote_w_free_vars}]\"\n//│ ╙──       \t                                            ^\n//│ let cde_w_unquote_w_local_free_vars: Code[[error, Int], nothing]\n\n\n:e\nlet free_var1 = code\"let x = 1 in x + y\"\nlet free_var2 = code\"let i = 1 in i + x\"\nlet cde_w_mutli_unquote = code\"${free_var2} + ${free_var1}\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.119: \tlet free_var1 = code\"let x = 1 in x + y\"\n//│ ╙──       \t                                      ^\n//│ let free_var1: Code[Int, nothing]\n//│ let free_var2: Code[Int, nothing]\n//│ let cde_w_mutli_unquote: Code[Int, nothing]\n\nfun f(x, y) = code\"[${x}, ${y}]\"\n//│ fun f: forall 'a 'b 'c. (Code['a, 'b], Code['c, 'b]) -> Code[['a, 'c], 'b]\n\n\n:e\nlet x = code\"y\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.134: \tlet x = code\"y\"\n//│ ╙──       \t             ^\n//│ let x: Code[error, nothing]\n\nlet c = f(x, x)\n//│ let c: Code[[error, error], nothing]\n\n\n:e\nlet cde_arr = code\"[${code\"y\"}, ${code\"y\"}]\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.145: \tlet cde_arr = code\"[${code\"y\"}, ${code\"y\"}]\"\n//│ ╙──       \t                           ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.145: \tlet cde_arr = code\"[${code\"y\"}, ${code\"y\"}]\"\n//│ ╙──       \t                                       ^\n//│ let cde_arr: Code[[error, error], nothing]\n\ncode\"let y = 1 in ${cde_arr}\"\n//│ Code[[error, error], nothing]\n\n\n:e\ny => code\"[${code\"y\"}, ${code\"y\"}]\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.159: \ty => code\"[${code\"y\"}, ${code\"y\"}]\"\n//│ ╙──       \t                  ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.159: \ty => code\"[${code\"y\"}, ${code\"y\"}]\"\n//│ ╙──       \t                              ^\n//│ anything -> Code[[error, error], nothing]\n\ncode\"y => ${c}\"\n//│ Code[anything -> [error, error], nothing]\n\n\nfun f(x, y) = [code\"[${x}, ${y}]\", x, y]\n//│ fun f: forall 'a 'b 'c 'd 'e. (Code['a, 'b] & 'c, Code['d, 'b] & 'e) -> [Code[['a, 'd], 'b], 'c, 'e]\n\n\n\nfun f(x) = x\n//│ fun f: forall 'a. 'a -> 'a\n\nlet built_in_binding_test = code\"let f = x => x + 1 in f(if true then 1 else 2)\"\n//│ let built_in_binding_test: Code[Int, nothing]\n\ncode\"f(0)\"\n//│ Code[0, nothing]\n\n:e\n// :ge\ncode\"${code\"${code\"${z}\"}\"}\"\n//│ ╔══[ERROR] identifier not found: z\n//│ ║  l.188: \tcode\"${code\"${code\"${z}\"}\"}\"\n//│ ╙──       \t                     ^\n//│ Code[nothing, nothing]\n\nlet z = code\"1\"\ncode\"${code\"${z}\"}\"\n//│ let z: Code[1, nothing]\n//│ Code[1, nothing]\n\n\n:e\ncode\"let x = 1 in let z = 1 in ${code\"x + y\"}\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.201: \tcode\"let x = 1 in let z = 1 in ${code\"x + y\"}\"\n//│ ╙──       \t                                          ^\n//│ Code[Int, nothing]\n\n\ncode\"let z = 0 in ${code\"z + 1\"}\"\n//│ Code[Int, nothing]\n\n:e\ncode\"let x = 1 in ${code\"x + y\"}\"\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.212: \tcode\"let x = 1 in ${code\"x + y\"}\"\n//│ ╙──       \t                             ^\n//│ Code[Int, nothing]\n\nlet n = 1\ncode\"${Const(n)} + 1\"\n//│ let n: 1\n//│ Code[Int, nothing]\n\ncode\"let x = 42 in x\"\n//│ Code[42, nothing]\n\ncode\"let x = 42 in ${code\"x\"}\"\n//│ Code[42, nothing]\n\ncode\"let x = 42 in ${code\"x\"}\"\n//│ Code[42, nothing]\n\n\ncode\"let a = 1 in let b = 2 in ${a}\"\n//│ Code[1, nothing]\n"
  },
  {
    "path": "shared/src/test/diff/qq/Weird.mls",
    "content": ":NewDefs\n:NoJS\n\nfun power(x) = case\n  0 then `1.0\n  n then x `*. power(x)(n - 1)\n//│ fun power: forall 'a. Code[Num, 'a] -> (0 | Int & ~0) -> Code[Num, 'a]\n\n\n:e\nlet p3 = y `=>\n  discard(run(x `=> power(x `+ y)(3)))\n  y\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.12: \t  discard(run(x `=> power(x `+ y)(3)))\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `?y & ~??x` does not match type `nothing`\n//│ let p3: Code[forall 'a. (Int & 'a) -> 'a, nothing]\n\n\n:e\n`let y = `42 `in\n  discard(run(x `=> power(x `+ y)(3)))\n  y\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.23: \t  discard(run(x `=> power(x `+ y)(3)))\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `?y & ~??x` does not match type `nothing`\n//│ Code[42, nothing]\n\n\n:e\n`let y = `42 `in\n  discard(run(`let x = `0 `in power(x `+ y)(3)))\n  y\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.34: \t  discard(run(`let x = `0 `in power(x `+ y)(3)))\n//│ ║        \t          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `?y & ~??x` does not match type `nothing`\n//│ Code[42, nothing]\n\n\nfun bind(rhs, k: forall 'g : Code['a, 'g] -> Code['b, 'c | 'g]) =\n  `let x = rhs `in k(x)\n//│ fun bind: forall 'a 'c 'b. (Code['a, 'c], k: forall 'g. Code['a, 'g] -> Code['b, 'c | 'g]) -> Code['b, 'c]\n\n\n// fun body: forall 'g : (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g]\nfun body(x, y) = case\n  0 then x\n  1 then y\n  n then bind of x `+ y, z => body(y, z)(n - 1)\n//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, anything] | 'a)\n\n\nn => (x, y) `=> body(x, y)(n)\n//│ (0 | 1 | Int & ~0 & ~1) -> Code[(Int, Int) -> Int, ??g & ~??y]\n\nfun gib(n) = ((x, y) `=> body(x, y)(n))\n//│ fun gib: (0 | 1 | Int & ~0 & ~1) -> Code[(Int, Int) -> Int, ??g & ~??y]\n\n\nlet g5 = gib(5)\n//│ let g5: Code[(Int, Int) -> Int, ??g & ~??y]\n\n:e\nrun(g5)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.67: \trun(g5)\n//│ ║        \t^^^^^^^\n//│ ╙── expression of type `??g & ~??y` does not match type `nothing`\n//│ error | (Int, Int) -> Int\n\nx `=> x `+ (x `=> x)`(`42)\n//│ Code[Int -> Int, nothing]\n\n\nfun foo =\n  `let x = `1\n  mut let v = x\n  `let x = `true\n  x\n//│ fun foo: Code[true, nothing]\n\n:pe\n:e\n`let x = `1 `if\n//│ ╔══[PARSE ERROR] This quote syntax is not supported yet\n//│ ║  l.87: \t`let x = `1 `if\n//│ ╙──      \t         ^^\n//│ ╔══[PARSE ERROR] Expected '`in'; found 'if' keyword instead\n//│ ║  l.87: \t`let x = `1 `if\n//│ ╙──      \t             ^^\n//│ ╔══[PARSE ERROR] Expected end of input; found 'if' keyword instead\n//│ ║  l.87: \t`let x = `1 `if\n//│ ╙──      \t             ^^\n//│ ╔══[ERROR] Type mismatch in unquote:\n//│ ║  l.87: \t`let x = `1 `if\n//│ ║        \t               ^\n//│ ╙── undefined literal of type `()` is not an instance of type `Code`\n//│ Code[error, nothing]\n\n:pe\n:e\n`let x = `1 `in\n//│ ╔══[PARSE ERROR] Unexpected end of input; an expression was expected here\n//│ ║  l.105: \t`let x = `1 `in\n//│ ╙──       \t               ^\n//│ ╔══[ERROR] Type mismatch in unquote:\n//│ ║  l.105: \t`let x = `1 `in\n//│ ║         \t               ^\n//│ ╙── undefined literal of type `()` is not an instance of type `Code`\n//│ Code[error, nothing]\n\n\nclass Ref[A](init: A) { mut val value: A = init }\n//│ class Ref[A](init: A) {\n//│   mut val value: A\n//│ }\n\n\nx `=>\n  let v = Ref(x)\n  let _ = y `=>\n    set v.value = y\n    `0\n  v.value\n//│ Code[forall 'a. 'a -> 'a, ??y & ~??x]\n\nlet foo =\n  mut let r = `0\n  x `=> ((set r = x), `0), r\n//│ let foo: Code[0, nothing] | Var['a, in ??x out ??x0]\n\n\nfun foo =\n  `let x = `1\n  let v = Ref(x)\n  `let x = `true\n  set v.value = x\n  x\n//│ fun foo: Code[true, nothing]\n\nlet a = `42\n//│ let a: Code[42, nothing]\n\n:w\n`let x = a `in\n  `log`(x)\n  x\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in quasiquote:\n//│ ║  l.149: \t  `log`(x)\n//│ ║         \t  ^^^^^^^^\n//│ ╙── code fragment of type `Code[?a, ?b | ?c]` does not match type `()`\n//│ Code[42, nothing]\n\n:w\n`let x = a\n`log`(x)\nx\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in quasiquote:\n//│ ║  l.161: \t`log`(x)\n//│ ║         \t^^^^^^^^\n//│ ╙── code fragment of type `Code[?a, ?b | ?c]` does not match type `()`\n//│ Code[42, nothing]\n\n:w\n`let x = a `in\n  run of\n    `log`(x)\n    `1\n  x\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in quasiquote:\n//│ ║  l.174: \t    `log`(x)\n//│ ║         \t    ^^^^^^^^\n//│ ╙── code fragment of type `Code[?a, ?b | ?c]` does not match type `()`\n//│ ╔══[WARNING] Expression in statement position should have type `()`.\n//│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer.\n//│ ╟── Type mismatch in application:\n//│ ║  l.173: \t  run of\n//│ ║         \t  ^^^^^^\n//│ ║  l.174: \t    `log`(x)\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.175: \t    `1\n//│ ║         \t^^^^^^\n//│ ╟── integer literal of type `1` does not match type `()`\n//│ ║  l.175: \t    `1\n//│ ║         \t     ^\n//│ ╟── but it flows into application with expected type `()`\n//│ ║  l.173: \t  run of\n//│ ║         \t  ^^^^^^\n//│ ║  l.174: \t    `log`(x)\n//│ ║         \t^^^^^^^^^^^^\n//│ ║  l.175: \t    `1\n//│ ╙──       \t^^^^^^\n//│ Code[42, nothing]\n\n:e\n`let x = a `in\n  let _ = run of\n    `let _ = `log`(x)\n    `1\n  x\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.206: \t  let _ = run of\n//│ ║         \t          ^^^^^^\n//│ ║  l.207: \t    `let _ = `log`(x)\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.208: \t    `1\n//│ ║         \t^^^^^^\n//│ ╟── code fragment context type of type `?x` does not match type `nothing`\n//│ ║  l.207: \t    `let _ = `log`(x)\n//│ ║         \t                   ^\n//│ ╟── but it flows into code fragment context type with expected type `nothing`\n//│ ║  l.207: \t    `let _ = `log`(x)\n//│ ╙──       \t             ^^^^^^^^\n//│ Code[42, nothing]\n\n\n`let x = `1 `in\n  `let _ = `log`(x)\n  x\n//│ Code[1, nothing]\n\nfun foo =\n  `let x = `1\n  `let _ = `log`(x)\n  x\n//│ fun foo: Code[1, nothing]\n"
  },
  {
    "path": "shared/src/test/diff/qq/WillfulExtrusion.mls",
    "content": ":NewDefs\n:NoJS\n\n\nfun foo(dbg) =\n  code\"x => ${let c = code\"x + 1\" in dbg(c), c}\"\n//│ fun foo: (Code[Int, ??x] -> anything) -> Code[Int -> Int, nothing]\n\nfoo(log)\n//│ Code[Int -> Int, nothing]\n\n\nfun (>>) compose(f, g) = x => g(f(x))\nfun show: Code[anything, anything] -> Str\n//│ fun (>>) compose: forall 'a 'b 'c. ('a -> 'b, 'b -> 'c) -> 'a -> 'c\n//│ fun show: Code[anything, anything] -> Str\n\nfoo(show >> log)\n//│ Code[Int -> Int, nothing]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/scalac/i13162.mls",
    "content": ":NewDefs\n\n\n// https://github.com/lampepfl/dotty/issues/13162\n\nfun method =\n  class Person(val name: Str)\n  module Person_ { // TODO change when module overloading is supported\n    val me = Person(\"Cameron\")\n  }\n  let m = Person_.me\n  m\nmethod.name\n//│ fun method: Person\n//│ Str\n//│ res\n//│     = 'Cameron'\n\n\n// https://github.com/lampepfl/dotty/issues/13162#issuecomment-887557311\n\n// * We don't currently have self bindings\n\n// def method(): Unit = {\n//   final case class Person(name: String)\n//   object Person { self =>\n//     val me = self.apply(\"Cameron\")\n//   }\n//   val _ = Person.me\n// }\n// method()\n\n:w\n:e\nfun method: () =\n  class Person(val name: Str)\n  module Person_ { self => // * defines a useless lambda!\n    val me = self.apply(\"Cameron\")\n  }\n  let m = Person_.me\n  m\nmethod\n//│ ╔══[WARNING] Pure expression does nothing in statement position.\n//│ ║  l.37: \t  module Person_ { self => // * defines a useless lambda!\n//│ ║        \t                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.38: \t    val me = self.apply(\"Cameron\")\n//│ ╙──      \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type `Person_` does not contain member `me`\n//│ ║  l.40: \t  let m = Person_.me\n//│ ╙──      \t                 ^^^\n//│ fun method: ()\n//│ ()\n//│ res\n//│     = undefined\n\n\n// https://github.com/lampepfl/dotty/issues/13162#issuecomment-888188804\n\n:re\nmodule Person {\n  fun f: ()\n  fun f = Person2.f\n}\nmodule Person2 {\n  fun f = ()\n  val me = Person.f\n}\n//│ module Person {\n//│   fun f: ()\n//│ }\n//│ module Person2 {\n//│   fun f: ()\n//│   val me: ()\n//│ }\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\nfun test = Person2.me\n//│ fun test: ()\n\n\n// * FIXME initialization check? or different codegen?\nfun test =\n  module Person {\n    fun f: ()\n    fun f = Person2.f\n  }\n  module Person2 {\n    fun f = ()\n    val me = Person.f\n  }\n  Person2.me\n//│ fun test: ()\n\n:re\ntest\n//│ ()\n//│ res\n//│ Runtime error:\n//│   ReferenceError: Cannot access 'Person2' before initialization\n\nmodule Test {\n  module Person {\n    fun f: ()\n    fun f = Person2.f\n  }\n  module Person2 {\n    fun f = ()\n    val me = Person.f\n  }\n  fun test = Person2.me\n}\n//│ module Test {\n//│   module Person {\n//│     fun f: ()\n//│   }\n//│   module Person2 {\n//│     fun f: ()\n//│     val me: ()\n//│   }\n//│   fun test: ()\n//│ }\n\n:re\nTest.test\n//│ ()\n//│ res\n//│ Runtime error:\n//│   RangeError: Maximum call stack size exceeded\n\n\n"
  },
  {
    "path": "shared/src/test/diff/tricky/IrregularSubtypes.mls",
    "content": ":IrregularTypes\n\n\ntype Foo[A] = A -> Foo[Foo[A]]\n//│ Defined type alias Foo[=A]\n\ntype Bar[A] = A -> Bar[Bar[A]]\n//│ Defined type alias Bar[=A]\n\n\n:e\nerror: Foo[int]: Bar[int]\n//│ ╔══[ERROR] Subtyping constraint of the form `Foo[int] <: Bar[int]` exceeded recursion depth limit (250)\n//│ ║  l.12: \terror: Foo[int]: Bar[int]\n//│ ║        \t^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: Bar[int]\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n// * Interestingly, this is caught by the cycle checker when rectypes are disabled:\n:NoRecursiveTypes\n\n:e\nerror: Foo[int]: Bar[int]\n//│ ╔══[ERROR] Cyclic-looking constraint while typing type ascription; a type annotation may be required\n//│ ║  l.26: \terror: Foo[int]: Bar[int]\n//│ ║        \t^^^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: Bar[int]\n//│ Runtime error:\n//│   Error: an error was thrown\n\n\n"
  },
  {
    "path": "shared/src/test/diff/tricky/IrregularSubtypes2.mls",
    "content": ":NoRecursiveTypes\n:IrregularTypes\n\n\ntype Lol = forall 'a. int -> ('a, Lol)\n//│ Defined type alias Lol\n\ndef lol: Lol\n//│ lol: Lol\n//│    = <missing implementation>\n\n:w\ntype Oops[A] = int -> (anything, Oops[Oops[A]])\n//│ Defined type alias Oops[±A]\n//│ ╔══[WARNING] Type definition Oops has bivariant type parameters:\n//│ ║  l.13: \ttype Oops[A] = int -> (anything, Oops[Oops[A]])\n//│ ║        \t     ^^^^\n//│ ╟── A is irrelevant and may be removed\n//│ ║  l.13: \ttype Oops[A] = int -> (anything, Oops[Oops[A]])\n//│ ╙──      \t          ^\n\n// * The cycle is due to irregular types, which are not yet shadowed\n:e\nlol: Oops[int]\n//│ ╔══[ERROR] Subtyping constraint of the form `Lol <: Oops[?]` exceeded recursion depth limit (250)\n//│ ║  l.24: \tlol: Oops[int]\n//│ ║        \t^^^\n//│ ╙── Note: use flag `:ex` to see internal error info.\n//│ res: Oops[?]\n//│    = <no result>\n//│      lol is not implemented\n\n\n"
  },
  {
    "path": "shared/src/test/diff/tricky/Pottier.fun",
    "content": "\n\n// Inspired by [Pottier 98, chap 13.4]\n\nlet rec f = x => y => add (f x.tail y) (f x y)\nlet rec f = x => y => add (f x.tail y) (f y x)\nlet rec f = x => y => add (f x.tail y) (f x y.tail)\nlet rec f = x => y => add (f x.tail y.tail) (f x.tail y.tail)\nlet rec f = x => y => add (f x.tail x.tail) (f y.tail y.tail)\nlet rec f = x => y => add (f x.tail x) (f y.tail y)\nlet rec f = x => y => add (f x.tail y) (f y.tail x)\n//│ f: 'a -> anything -> int\n//│   where\n//│     'a <: {tail: 'a}\n//│ f: 'a -> 'a -> int\n//│   where\n//│     'a <: {tail: 'a}\n//│ f: 'a -> 'b -> int\n//│   where\n//│     'b <: {tail: 'b}\n//│     'a <: {tail: 'a}\n//│ f: 'a -> 'b -> int\n//│   where\n//│     'b <: {tail: 'b}\n//│     'a <: {tail: 'a}\n//│ f: 'a -> 'a -> int\n//│   where\n//│     'a <: {tail: 'a}\n//│ f: 'a -> 'b -> int\n//│   where\n//│     'a <: {tail: 'a} & 'b\n//│     'b <: {tail: 'a}\n//│ f: 'a -> 'b -> int\n//│   where\n//│     'a <: {tail: 'a} & 'b\n//│     'b <: {tail: 'a}\n\nlet f = x => y => if true then { l: x; r: y } else { l: y; r: x } // 2-crown\n//│ f: 'a -> 'a -> {l: 'a, r: 'a}\n\n\n// Inspired by [Pottier 98, chap 13.5]\n\nlet rec f = x => y => if true then x else { t: f x.t y.t }\n//│ f: 'a -> 'b -> 'c\n//│   where\n//│     'b <: {t: 'b}\n//│     'a <: {t: 'a} & 'c\n//│     'c :> {t: 'c}\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/typegen/TypegenTerms.mls",
    "content": ":NoJS\n\n:ts\n{ a = \"hello\"; b = \"world\" }\n1 + 2 - 5\nlet t = { a = 5; b = \"world\"} in if t.a == 1 then 1 else (fun f -> f.b )\ndef x = 1\ndef y = 2\ndef z = x + y\n(1, 3, { a = { b = { c = \"d\"}}}, \"hello hello\")\n// common values\n//│ res: {a: \"hello\", b: \"world\"}\n//│ res: int\n//│ res: 1 | {b: 'b} -> 'b\n//│ x: 1\n//│ y: 2\n//│ z: int\n//│ res: (1, 3, {a: {b: {c: \"d\"}}}, \"hello hello\",)\n//│ // start ts\n//│ export declare const res: {readonly a: \"hello\", readonly b: \"world\"}\n//│ export declare const res: int\n//│ export declare const res<b>: 1 | ((arg: {readonly b: b}) => b)\n//│ export declare const x: 1\n//│ export declare const y: 2\n//│ export declare const z: int\n//│ export declare const res: readonly [1, 3, {readonly a: {readonly b: {readonly c: \"d\"}}}, \"hello hello\"]\n//│ // end ts\n\n:ts\ndef rcd = { x = 1 }\nrcd.x\ndef funky f r = let t = r with { y = \"nah\" } in f t\ndef cool g r = let t = r with { a = \"apple\"; b = \"ball\" } in g t\ndef g = rcd with { y = \"yeah\" }\n// records\n//│ rcd: {x: 1}\n//│ res: 1\n//│ funky: (('a\\y & {y: \"nah\"}) -> 'b) -> 'a -> 'b\n//│ cool: (('a\\a\\b & {a: \"apple\", b: \"ball\"}) -> 'b) -> 'a -> 'b\n//│ g: {x: 1, y: \"yeah\"}\n//│ // start ts\n//│ export declare const rcd: {readonly x: 1}\n//│ export declare const res: 1\n//│ export declare const funky<a, b>: (arg: (arg1: Omit<a, \"y\"> & {readonly y: \"nah\"}) => b) => (arg2: a) => b\n//│ export declare const cool<a, b>: (arg: (arg1: Omit<a, \"a\" | \"b\"> & {readonly a: \"apple\", readonly b: \"ball\"}) => b) => (arg2: a) => b\n//│ export declare const g: {readonly x: 1, readonly y: \"yeah\"}\n//│ // end ts\n\n:ts\ndef f (a: int) (b: string) (c: bool) = if c then a else b\nrec def fact x = if x == 1 then 1 else x * fact (x - 1)\ndef g x y = if x.b == 1 then x else x.a\n// miscellaneous functions\n//│ f: int -> string -> bool -> (int | string)\n//│ fact: int -> int\n//│ g: ({a: 'a, b: number} & 'a) -> anything -> 'a\n//│ // start ts\n//│ export declare const f: (arg: int) => (arg1: string) => (arg2: bool) => int | string\n//│ export declare const fact: (arg: int) => int\n//│ export declare const g<a>: (arg: {readonly a: a, readonly b: number} & a) => (arg1: unknown) => a\n//│ // end ts\n\n// FIXME\n// :ts\n// rec def l (a: int) = l\n// rec def m (a: int) (b: int) = m\n// def f: ('c -> 'a as 'a) -> 'c -> int\n// recursion type functions\n\n:ts\n:e\n1: ?\n{ a = \"hello\" }: { a: string } & { b: int }\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.72: \t1: ?\n//│ ║        \t^\n//│ ╟── integer literal of type `1` does not match type `nothing`\n//│ ╟── Note: constraint arises from type wildcard:\n//│ ║  l.72: \t1: ?\n//│ ╙──      \t   ^\n//│ res: anything\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.73: \t{ a = \"hello\" }: { a: string } & { b: int }\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╟── record literal of type `{a: \"hello\"}` does not have field 'b'\n//│ ╟── Note: constraint arises from intersection type:\n//│ ║  l.73: \t{ a = \"hello\" }: { a: string } & { b: int }\n//│ ╙──      \t                 ^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ res: {a: string, b: int}\n//│ // start ts\n//│ export declare const res: unknown\n//│ export declare const res: {readonly a: string, readonly b: int}\n//│ // end ts\n\n:ts\ndef nonsense x y = if x.a == y.b then x y else fun y -> x\ndef g = fun x -> fun y -> if x == y then x y else y x\n// complex types\n//│ nonsense: ('a -> 'b & {a: number} & 'c) -> ({b: number} & 'a) -> (anything -> 'c | 'b)\n//│ g: nothing -> nothing -> nothing\n//│ // start ts\n//│ export declare const nonsense<a, b, c>: (arg: ((arg1: a) => b) & {readonly a: number} & c) => (arg2: {readonly b: number} & a) => ((arg3: unknown) => c) | b\n//│ export declare const g: (arg: never) => (arg1: never) => never\n//│ // end ts\n\n:ts\ndef x: int | ~string\ndef y: \"a\" | \"b\" | ~string\n// negative types\n//│ x: int | ~string\n//│ y: \"a\" | \"b\" | ~string\n//│ // start ts\n//│ type Neg<NegatedType, FromType> = FromType extends NegatedType ? never: FromType\n//│ export declare const x: int | Neg<string, a>\n//│ export declare const y: \"a\" | \"b\" | Neg<string, a>\n//│ // end ts\n\n:ts\ndef cont x = x + 1\ndef app y k = k (y - 1)\napp 2 cont\n//│ cont: int -> int\n//│ app: int -> (int -> 'a) -> 'a\n//│ res: int\n//│ // start ts\n//│ export declare const cont: (arg: int) => int\n//│ export declare const app<a>: (arg: int) => (arg1: (arg2: int) => a) => a\n//│ export declare const res: int\n//│ // end ts\n\n:ts\ndef g (x, y) = x + y\ndef h (x, (y, z)) = y z + x\ndef k (x, (y, z)) (l, (m), (n)) = (m (n + l)) (y (z + x))\ndef l: ((1, 2), (3, 4)) -> 5\n//│ g: (int, int,) -> int\n//│ h: (int, ('a -> int, 'a,),) -> int\n//│ k: (int, (int -> 'a, int,),) -> (int, int -> 'a -> 'b, int,) -> 'b\n//│ l: ((1, 2,), (3, 4,),) -> 5\n//│ // start ts\n//│ export declare const g: (arg: int, arg1: int) => int\n//│ export declare const h<a>: (arg: int, arg1: readonly [(arg2: a) => int, a]) => int\n//│ export declare const k<a, b>: (arg: int, arg1: readonly [(arg2: int) => a, int]) => (arg3: int, arg4: (arg5: int) => (arg6: a) => b, arg7: int) => b\n//│ export declare const l: (arg: readonly [1, 2], arg1: readonly [3, 4]) => 5\n//│ // end ts\n\n\n// FIXME\n// :ts\n// def weird: ((int, int) -> 'a) as 'a\n// def weird: ('a -> (int, int)) as 'a\n// def weird: ((int, 'a) as 'a) -> int\n// def weird: ((int, bool) | 'a) -> 'a\n\n\n"
  },
  {
    "path": "shared/src/test/diff/typegen/TypegenTypedefs.mls",
    "content": ":NoJS\n:ts\ntype G[T] = { a : T }\ntype H = int | ~string\nclass Box[T]: { length: T }\nclass RectangleBox[T]: Box[T] & { breadth: T }\nclass StackedRectangleBoxes[T, N]: RectangleBox[T] & { size: N }\n//│ Defined type alias G[+T]\n//│ Defined type alias H\n//│ Defined class Box[+T]\n//│ Defined class RectangleBox[+T]\n//│ Defined class StackedRectangleBoxes[+T, +N]\n//│ // start ts\n//│ export type G = {readonly a: T}\n//│ type Neg<NegatedType, FromType> = FromType extends NegatedType ? never: FromType\n//│ export type H = int | Neg<string, a>\n//│ export declare class Box<T> {\n//│     length: T\n//│     constructor(fields: {length: T})\n//│ }\n//│ export declare class RectangleBox<T> extends Box<T> {\n//│     breadth: T\n//│     constructor(fields: {breadth: T, length: T})\n//│ }\n//│ export declare class StackedRectangleBoxes<N, T> extends RectangleBox<T> {\n//│     size: N\n//│     constructor(fields: {size: N, breadth: T, length: T})\n//│ }\n//│ // end ts\n\n\n// FIXME\n:ts\nclass Lock[T]: { pins: T }\n  method Map: (T -> 'a) -> Lock['a]\n  method Map f = Lock { pins = f this.pins }\ndef Lock pins = Lock { pins = pins }\nclass Bank: { lock: Lock[int]; cash: int }\n  method Potential: number\n  method Potential = this.cash / this.lock.pins\n  method Better: Bank -> bool\n  method Better other = this.Potential > other.Potential\ndef Bank lock cash = Bank { lock = lock; cash = cash }\nlet lockA = Lock 20 in let lockB = Lock 30 in (Bank lockA 2000).Better(Bank lockB 30000)\n//│ Defined class Lock[+T]\n//│ Declared Lock.Map: Lock['T] -> ('T -> 'a) -> Lock['a]\n//│ Defined Lock.Map: Lock['T] -> ('T -> 'pins) -> Lock['pins]\n//│ Defined class Bank\n//│ Declared Bank.Potential: Bank -> number\n//│ Declared Bank.Better: Bank -> Bank -> bool\n//│ Defined Bank.Potential: Bank -> number\n//│ Defined Bank.Better: Bank -> Bank -> bool\n//│ Lock: 'pins -> Lock['pins]\n//│ Bank: (Lock[int] & 'lock) -> (int & 'cash) -> (Bank with {cash: 'cash, lock: 'lock})\n//│ res: bool\n//│ // start ts\n//│ export declare class Lock<T> {\n//│     pins: T\n//│     constructor(fields: {pins: T})\n//│     Map<'a>(arg: (arg1: T) => 'a): Lock<'a>\n//│ }\n//│ export declare class Bank {\n//│     lock: Lock<int>\n//│     cash: int\n//│     constructor(fields: {lock: Lock<int>, cash: int})\n//│     readonly Potential: number\n//│     Better(arg: Bank): bool\n//│ }\n//│ export declare const Lock<pins>: (arg: pins) => Lock<pins>\n//│ export declare const Bank<lock, cash>: (arg: Lock<int> & lock) => (arg1: int & cash) => Omit<Bank, \"cash\" | \"lock\"> & {readonly cash: cash, readonly lock: lock}\n//│ export declare const res: bool\n//│ // end ts\n\n\n// FIXME\n:ts\nclass None: {}\nclass Some[T]: { value: T }\ntype Option[T] = Some[T] | None\nclass LinkedList[T]: { head: T; tail: Option[LinkedList[T]] }\n  method Append: T -> LinkedList[T]\n  method Append elem = LinkedList { head = elem; tail = Some { value = this } }\ndef None = None {}\ndef Some v = Some { value = v }\n//│ Defined class None\n//│ Defined class Some[+T]\n//│ Defined type alias Option[+T]\n//│ Defined class LinkedList[=T]\n//│ Declared LinkedList.Append: LinkedList['T] -> 'T -> LinkedList['T]\n//│ Defined LinkedList.Append: (LinkedList['T] & 'this) -> ('T & 'head) -> (LinkedList['T] with {head: 'head, tail: Some[LinkedList['T]] & {value: LinkedList['T] & 'this}})\n//│ None: None\n//│ Some: 'value -> Some['value]\n//│ // start ts\n//│ export declare class None {\n//│     constructor(fields: {})\n//│ }\n//│ export declare class Some<T> {\n//│     value: T\n//│     constructor(fields: {value: T})\n//│ }\n//│ export type Option = Some<T> | None\n//│ export declare class LinkedList<T> {\n//│     head: T\n//│     tail: Option<LinkedList<T>>\n//│     constructor(fields: {head: T, tail: Option<LinkedList<T>>})\n//│     Append(arg: T): LinkedList<T>\n//│ }\n//│ export declare const None: None\n//│ export declare const Some<value>: (arg: value) => Some<value>\n//│ // end ts\n\n:ts\ntrait A: { x: int }\ntrait B: { y: string } & A\nclass C: { x: 0 | 1 }\n//│ Defined trait A\n//│ Defined trait B\n//│ Defined class C\n//│ // start ts\n//│ export interface A {\n//│     x: int\n//│ }\n//│ export interface B extends A {\n//│     y: string\n//│ }\n//│ export declare class C {\n//│     x: 0 | 1\n//│     constructor(fields: {x: 0 | 1})\n//│ }\n//│ // end ts\n\n:ts\nclass LL[T]: { head: T; tail: LL[T] -> int }\n  method Append: T -> LL[T]\n//│ Defined class LL[=T]\n//│ Declared LL.Append: LL['T] -> 'T -> LL['T]\n//│ // start ts\n//│ export declare class LL<T> {\n//│     head: T\n//│     tail: (arg: LL<T>) => int\n//│     constructor(fields: {head: T, tail: (arg: LL<T>) => int})\n//│     Append(arg: T): LL<T>\n//│ }\n//│ // end ts\n\n:ts\ntrait A1: { x: int -> int }\ntrait B2: { y: int }\ntrait D3: { y: int }\nclass E: { x: \"hello\"; y: int } & A1 & B2 & D3\n//│ Defined trait A1\n//│ Defined trait B2\n//│ Defined trait D3\n//│ Defined class E\n//│ // start ts\n//│ export interface A1 {\n//│     x: (arg: int) => int\n//│ }\n//│ export interface B2 {\n//│     y: int\n//│ }\n//│ export interface D3 {\n//│     y: int\n//│ }\n//│ export declare class E {\n//│     y: int\n//│     x: \"hello\" & ((arg: int) => int)\n//│     constructor(fields: {y: int, x: \"hello\" & ((arg: int) => int)})\n//│ }\n//│ // end ts\n\n:ts\ntype VarArg[T] = (T, T)\nclass Program[T]\n  method Run: VarArg[T] -> number\n//│ Defined type alias VarArg[+T]\n//│ Defined class Program[-T]\n//│ Declared Program.Run: Program['T] -> VarArg['T] -> number\n//│ // start ts\n//│ export type VarArg = readonly [T, T]\n//│ export declare class Program<T> {\n//│     constructor(fields: {})\n//│     Run(arg: VarArg<T>): number\n//│ }\n//│ // end ts\n\n:ts\n:e\n:w\nclass Arg[T]: (T, T)\nclass Prog[T]\n  method Run: Arg[T] -> number\n//│ ╔══[ERROR] cannot inherit from a tuple type\n//│ ║  l.190: \tclass Arg[T]: (T, T)\n//│ ╙──       \t      ^^^^^^^^^^^^^^\n//│ ╔══[ERROR] type identifier not found: Arg\n//│ ║  l.192: \t  method Run: Arg[T] -> number\n//│ ╙──       \t              ^^^^^^\n//│ Defined class Prog[±T]\n//│ Declared Prog.Run: Prog[?] -> error -> number\n//│ ╔══[WARNING] Type definition Prog has bivariant type parameters:\n//│ ║  l.191: \tclass Prog[T]\n//│ ║         \t      ^^^^\n//│ ╟── T is irrelevant and may be removed\n//│ ║  l.191: \tclass Prog[T]\n//│ ╙──       \t           ^\n//│ // start ts\n//│ export declare class Prog<T> {\n//│     constructor(fields: {})\n//│     Run(arg: error): number\n//│ }\n//│ // end ts\n"
  },
  {
    "path": "shared/src/test/diff/ucs/AppSplits.mls",
    "content": ":NewDefs\n\n\nfun foo(x) = x > 1\n//│ fun foo: Num -> Bool\n\n:pe // TODO\n:e\nif foo of\n  0 then \"a\"\n  1 then \"b\"\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.10: \t  0 then \"a\"\n//│ ╙──      \t    ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.9: \tif foo of\n//│ ║       \t   ^^^^^^\n//│ ║  l.10: \t  0 then \"a\"\n//│ ║        \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.9: \tif foo of\n//│ ╙──     \t^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.10: \t  0 then \"a\"\n//│ ╙──      \t  ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.10: \t  0 then \"a\"\n//│ ║        \t  ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ()\n//│ res\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n:pe // TODO\n:e\nif foo of 1,\n  0 then \"a\"\n  1 then \"b\"\n//│ ╔══[PARSE ERROR] Unexpected 'then'/'else' clause\n//│ ║  l.38: \t  0 then \"a\"\n//│ ║        \t  ^^^^^^^^^^\n//│ ║  l.39: \t  1 then \"b\"\n//│ ╙──      \t^^^^^^^^^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found application instead\n//│ ║  l.37: \tif foo of 1,\n//│ ║        \t   ^^^^^^^^^\n//│ ║  l.38: \t  0 then \"a\"\n//│ ║        \t^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.37: \tif foo of 1,\n//│ ╙──      \t^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.38: \t  0 then \"a\"\n//│ ╙──      \t  ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.37: \tif foo of 1,\n//│ ║        \t   ^^^^^^^^^\n//│ ║  l.38: \t  0 then \"a\"\n//│ ║        \t^^\n//│ ╟── argument list of type `[1, ()]` does not match type `[?a]`\n//│ ║  l.37: \tif foo of 1,\n//│ ║        \t          ^^\n//│ ║  l.38: \t  0 then \"a\"\n//│ ╙──      \t^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.38: \t  0 then \"a\"\n//│ ║        \t  ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ()\n//│ res\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n:pe // TODO\n:e\nif foo\n  (0) then \"a\"\n  (1) then \"b\"\n//│ ╔══[PARSE ERROR] Unexpected parenthesis section here\n//│ ║  l.79: \t  (1) then \"b\"\n//│ ╙──      \t  ^^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.78: \t  (0) then \"a\"\n//│ ╙──      \t           ^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.78: \t  (0) then \"a\"\n//│ ║        \t           ^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ \"a\"\n//│ res\n//│ Runtime error:\n//│   Error: non-exhaustive case expression\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/CrossBranchCapture.mls",
    "content": ":NewDefs\n\nfun (~~>) expect(a, b) = if a === b then () else error\n//│ fun (~~>) expect: forall 'a. (Eql['a], 'a) -> ()\n\nclass Numb(n: Int)\n//│ class Numb(n: Int)\n\n\n// FIXME: The following test case should fail, but it doesn't. The reason is\n// `x` and `y` are in the desugared lexical scope, although they don't in the\n// original lexical scope.\nfun process(e) =\n  if e is\n    Numb(n) and n > 0 then n\n    Numb(m) then n\n//│ fun process: Numb -> Int\n\n\nprocess(Numb(-10))\n//│ Int\n//│ res\n//│     = -10\n\n\n\nfun process(e, n) =\n  if e is\n    Numb(n) and n > 0 then n\n    Numb(m) then n + m\n//│ fun process: (Numb, Int) -> Int\n\nprocess(Numb(0), 10) ~~> 10\nprocess(Numb(-1), 10) ~~> 9\nprocess(Numb(1), 10) ~~> 1\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n\n\nclass Vec(xs: Array[Numb | Vec])\nclass Pair[A,B](a: A, b: B)\n//│ class Vec(xs: Array[Numb | Vec])\n//│ class Pair[A, B](a: A, b: B)\n\n\n:e\n:ge\nfun process(e) =\n  if e is\n    Pair(Numb(n), Numb(m)) then Numb(n + m)\n    Pair(Vec(xs), Vec(ys))  then n\n    Pair(Vec(n),  Numb(n)) then n\n    Pair(Numb(n), Vec(n))  then n\n//│ ╔══[ERROR] identifier not found: n\n//│ ║  l.56: \t    Pair(Vec(xs), Vec(ys))  then n\n//│ ╙──      \t                                 ^\n//│ fun process: Pair[Numb | Vec, Numb | Vec] -> (Int | Numb | error)\n//│ Code generation encountered an error:\n//│   unresolved symbol n\n\n\n// * FIXME should warn, be rejected, or compare both values for equality\nfun process(e) =\n  if e is\n    Pair(Numb(n), Numb(n)) then n\n//│ fun process: Pair[Numb, Numb] -> Int\n\nprocess(Pair(Numb(1), Numb(2)))\n//│ Int\n//│ res\n//│     = 2\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/DirectLines.mls",
    "content": ":NewDefs\n\nfun f(x, y) =\n  if\n    x == 0 then \"x\"\n    y == 0 then \"y\"\n    _      then \"nah\"\n//│ fun f: (Num, Num) -> (\"nah\" | \"x\" | \"y\")\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nfun isValid(x) = if x then false else true\n//│ fun isValid: Bool -> Bool\n\nfun f(x, allowNone) =\n  if x\n    is Some(x) and isValid(x) then \"good\"\n    is None and allowNone then \"okay\"\n    is _ then \"bad\"\n//│ fun f: (Object & ~#Some | Some[Bool], Bool) -> (\"bad\" | \"good\" | \"okay\")\n\nfun f(x, y, z) =\n  if\n    x == 0 then \"x\"\n    y ==\n      1 then \"y = 1\"\n      2 and z ==\n        0 then \"z = 0\"\n        9 then \"z = 9\"\n        _ then \"bruh\"\n      3 then \"y = 3\"\n      _ then \"bruh\"\n//│ fun f: (Num, Num, Num) -> (\"bruh\" | \"x\" | \"y = 1\" | \"y = 3\" | \"z = 0\" | \"z = 9\")\n\n:w\nfun f(a, b) =\n  if\n    a == 0 then 0\n    b ==\n      1 then 1\n      2 then 2\n      _ then 7\n    else 3\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.48: \t    else 3\n//│ ║        \t         ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.47: \t      _ then 7\n//│ ╙──      \t             ^\n//│ fun f: (Num, Num) -> (0 | 1 | 2 | 7)\n"
  },
  {
    "path": "shared/src/test/diff/ucs/ElseIf.mls",
    "content": ":NewDefs\n\n\n\nfun f(x, y) = if x ===\n    0 then true\n    1 then false\n  else if y ===\n    0 then true\n    1 then false\n  else false\n//│ fun f: (Eql[0 | 1], Eql[0 | 1]) -> Bool\n\nfun f(x, y) = if x ===\n    0 then true\n    1 then false\n  else if y ===\n    0 then true\n    _ then false\n//│ fun f: (Eql[0 | 1], Eql[0]) -> Bool\n\nmodule Tru\nmodule Fals\n//│ module Tru\n//│ module Fals\n\n:e\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n//│ ╔══[ERROR] when `x` is `Tru`\n//│ ║  l.29: \t    Tru and y is Tru then true\n//│ ║        \t    ^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.29: \t    Tru and y is Tru then true\n//│ ║        \t            ^\n//│ ╟── it can be module `Fals`\n//│ ║  l.30: \t    Fals and y is Fals then false\n//│ ╙──      \t                  ^^^^\n//│ ╔══[ERROR] when `x` is `Fals`\n//│ ║  l.30: \t    Fals and y is Fals then false\n//│ ║        \t    ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.30: \t    Fals and y is Fals then false\n//│ ║        \t             ^\n//│ ╟── it can be module `Tru`\n//│ ║  l.29: \t    Tru and y is Tru then true\n//│ ╙──      \t                 ^^^\n//│ fun f: (Fals | Tru, nothing) -> Bool\n\n// The base case.\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n    Tru and y is Fals then true\n    Fals and y is Tru then true\n//│ fun f: (Fals | Tru, Fals | Tru) -> Bool\n\n// Replace the `x is Fals` with `_`\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n    _ and y is\n      Tru then true\n      Fals then false\n//│ fun f: (Object, Fals | Tru) -> Bool\n\nf(Tru, Tru)\nf(Tru, Fals)\nf(Fals, Tru)\nf(Fals, Fals)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = true\n//│ res\n//│     = false\n\n:e\nfun g(x, y) = if x is\n  true and y is true then true\n  false and y is false then false\n//│ ╔══[ERROR] `y` has 1 missing case\n//│ ║  l.84: \t  true and y is true then true\n//│ ║        \t           ^\n//│ ╟── it can be Boolean value `false`\n//│ ║  l.85: \t  false and y is false then false\n//│ ╙──      \t                 ^^^^^\n//│ ╔══[ERROR] `y` has 1 missing case\n//│ ║  l.85: \t  false and y is false then false\n//│ ║        \t            ^\n//│ ╟── it can be Boolean value `true`\n//│ ║  l.84: \t  true and y is true then true\n//│ ╙──      \t                ^^^^\n//│ fun g: (Bool, nothing) -> Bool\n\n// Test with real booleans\nfun g(x, y) = if x is\n  true and y is true then true\n  false and y is false then false\n  _ and y is\n    true then true\n    false then false\n//│ fun g: (Object, Bool) -> Bool\n\n// Chained UCS terms\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n  else if y is\n    Tru then true\n    Fals then false\n//│ fun f: (Object, Fals | Tru) -> Bool\n\n:e\nfun f(x, y) = if x is\n    Tru and y is Tru then true\n    Fals and y is Fals then false\n  else if y is\n    Tru and x is Fals then true\n    Fals and x is Tru then false\n//│ ╔══[ERROR] when `y` is `Tru`\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t    ^^^\n//│ ╟── `x` has 1 missing case\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t            ^\n//│ ╟── it can be module `Tru`\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ╙──       \t                  ^^^\n//│ ╔══[ERROR] when `y` is `Fals`\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t    ^^^^\n//│ ╟── `x` has 1 missing case\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t             ^\n//│ ╟── it can be module `Fals`\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ╙──       \t                 ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t            ^^^^^^^^^^^^^^^^^^^\n//│ ╟── class pattern of type `Tru` is not an instance of type `Fals`\n//│ ║  l.120: \t    Tru and y is Tru then true\n//│ ║         \t    ^^^\n//│ ╟── but it flows into reference with expected type `Fals`\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ║         \t            ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.123: \t    Tru and x is Fals then true\n//│ ╙──       \t                 ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t             ^^^^^^^^^^^^^^^^^^^\n//│ ╟── class pattern of type `Fals` is not an instance of type `Tru`\n//│ ║  l.121: \t    Fals and y is Fals then false\n//│ ║         \t    ^^^^\n//│ ╟── but it flows into reference with expected type `Tru`\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ║         \t             ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.124: \t    Fals and x is Tru then false\n//│ ╙──       \t                  ^^^\n//│ fun f: (Fals | Tru, Fals | Tru) -> Bool\n\nfun h(x, y, p) = if\n  x and p(x) then 0\n  y is\n    Tru then 1\n    Fals then 2\n//│ fun h: forall 'a. ('a & Bool, Fals | Tru, 'a -> Bool) -> (0 | 1 | 2)\n"
  },
  {
    "path": "shared/src/test/diff/ucs/ErrorMessage.mls",
    "content": ":NewDefs\n\nclass Point(x: Int, y: Int)\n//│ class Point(x: Int, y: Int)\n\n:e\nfun f(p) =\n  if p is\n    Point(x, y, z) then x + y + z\n//│ ╔══[ERROR] Type mismatch in field selection:\n//│ ╟── tuple literal of type `{0: ?#x, 1: ?#y}` does not have field '2'\n//│ ║  l.3: \tclass Point(x: Int, y: Int)\n//│ ║       \t            ^^^^^^^^^\n//│ ╟── but it flows into operator application with expected type `{2: ?a}`\n//│ ║  l.8: \t  if p is\n//│ ║       \t     ^^^^\n//│ ║  l.9: \t    Point(x, y, z) then x + y + z\n//│ ╙──     \t^^^^^^^^^\n//│ fun f: Point -> Int\n\n:e\n:ge\nfun g(xs) =\n  if xs is\n    head :: _ then head\n//│ ╔══[ERROR] type identifier `::` not found\n//│ ║  l.25: \t    head :: _ then head\n//│ ╙──      \t         ^^\n//│ ╔══[ERROR] type identifier not found: ::\n//│ ║  l.25: \t    head :: _ then head\n//│ ╙──      \t         ^^\n//│ fun g: nothing -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol ::\n"
  },
  {
    "path": "shared/src/test/diff/ucs/Exhaustiveness.mls",
    "content": ":NewDefs\n:NoJS\n\nclass A()\nclass B()\nclass C()\n//│ class A()\n//│ class B()\n//│ class C()\n\n:e\nfun f(x, y) =\n  if\n    y is A and\n      x is\n        A then 0\n        B then 1\n        C then 2\n    y is B and\n      x is\n        A then 4\n//│ ╔══[ERROR] when `y` is `B`\n//│ ║  l.19: \t    y is B and\n//│ ║        \t         ^\n//│ ╟── `x` has 2 missing cases\n//│ ║  l.20: \t      x is\n//│ ║        \t      ^\n//│ ╟── it can be class `B`\n//│ ║  l.17: \t        B then 1\n//│ ║        \t        ^\n//│ ╟── it can be class `C`\n//│ ║  l.18: \t        C then 2\n//│ ╙──      \t        ^\n//│ fun f: (A, A | B) -> (0 | 1 | 2 | 4)\n\n:e\n// These operators are uninterpreted. So, it's impossible to reason the\n// exhaustiveness without SMT solvers.\ntype Tree[A] = Node[A] | Empty\nmodule Empty {\n  fun contains(wanted) = false\n}\nclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n  fun contains(wanted) = if wanted\n    <= value then left.find(wanted)\n    >= value then right.find(wanted)\n    == value then true\n}\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.47: \t    == value then true\n//│ ╙──      \t                  ^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.44: \t  fun contains(wanted) = if wanted\n//│ ║        \t                            ^^^^^^\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `Num`\n//│ ║  l.43: \tclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│ ║        \t                     ^^^\n//│ ╟── but it flows into reference with expected type `Num`\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] Type `#Node & {Node#A = A}` does not contain member `find`\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ╙──      \t                      ^^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.44: \t  fun contains(wanted) = if wanted\n//│ ║        \t                            ^^^^^^\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `Num`\n//│ ║  l.43: \tclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│ ║        \t                     ^^^\n//│ ╟── but it flows into reference with expected type `Num`\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] Type `#Node & {Node#A = A}` does not contain member `find`\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ╙──      \t                       ^^^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.44: \t  fun contains(wanted) = if wanted\n//│ ║        \t                            ^^^^^^\n//│ ║  l.45: \t    <= value then left.find(wanted)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.46: \t    >= value then right.find(wanted)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.47: \t    == value then true\n//│ ║        \t^^^^^^^^^^^^\n//│ ╟── type `int` is not an instance of type `Num`\n//│ ║  l.43: \tclass Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│ ║        \t                     ^^^\n//│ ╟── but it flows into reference with expected type `Num`\n//│ ║  l.47: \t    == value then true\n//│ ╙──      \t       ^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.47: \t    == value then true\n//│ ║        \t                  ^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ type Tree[A] = Empty | Node[A]\n//│ module Empty {\n//│   fun contains: anything -> false\n//│ }\n//│ class Node[A](value: int, left: Tree[A], right: Tree[A]) {\n//│   fun contains: Num -> (error | true)\n//│ }\n"
  },
  {
    "path": "shared/src/test/diff/ucs/Humiliation.mls",
    "content": ":NewDefs\n\n\nclass Foo[T](x: T)\n//│ class Foo[T](x: T)\n\nif 1 is 1 then 1 else 0\n//│ 0 | 1\n//│ res\n//│     = 1\n\nfun test(x) = if x is 1 then 0 else 1\n//│ fun test: Object -> (0 | 1)\n\n:w\nfun testF(x) = if x is\n  Foo(a) then a\n  Foo(a) then a\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.18: \t  Foo(a) then a\n//│ ║        \t  ^^^\n//│ ╟── there is an identical pattern Foo\n//│ ║  l.17: \t  Foo(a) then a\n//│ ╙──      \t  ^^^\n//│ fun testF: forall 'a. Foo['a] -> 'a\n\nclass Bar[Y, Z](y: Y, z: Z)\n//│ class Bar[Y, Z](y: Y, z: Z)\n\nfun test(f) = if f is\n  Foo(a) then a\n  Bar(b, c) then b + c\n//│ fun test: forall 'a. (Bar[Int, Int] | Foo['a]) -> (Int | 'a)\n\n\nclass Pair[A, B](fst: A, snd: B)\n//│ class Pair[A, B](fst: A, snd: B)\n\nfun f(x) =\n  if x is\n    Pair(0, 0) then \"zeros\"\n    Pair(1, 1) then \"ones\"\n    Pair(y, 1) then x\n    _          then \"nah\"\n//│ fun f: (Object & ~#Pair | Pair[Object, Object]) -> (\"nah\" | \"ones\" | \"zeros\" | Pair[nothing, nothing])\n\nclass Z()\nclass O()\n//│ class Z()\n//│ class O()\n\n// This is not exhaustive.\n:e\nfun foo(x) = if x is\n  Pair(Z(), Z()) then \"zeros\"\n  Pair(O(), O()) then \"ones\"\n//│ ╔══[ERROR] when `x` is `Pair`, and\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║        \t  ^^^^\n//│ ╟── the first argument of `Pair` is `Z`,\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║        \t       ^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `O`\n//│ ║  l.56: \t  Pair(O(), O()) then \"ones\"\n//│ ╙──      \t            ^\n//│ ╔══[ERROR] when `x` is `Pair`, and\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║        \t  ^^^^\n//│ ╟── the first argument of `Pair` is `O`,\n//│ ║  l.56: \t  Pair(O(), O()) then \"ones\"\n//│ ║        \t       ^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `Z`\n//│ ║  l.55: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ╙──      \t            ^\n//│ fun foo: Pair[O | Z, nothing] -> (\"ones\" | \"zeros\")\n\n// Change `Pair` to a real pair.\n:e\nfun foo(x) = if x is\n  [Z(), Z()] then \"zeros\"\n  [O(), O()] then \"ones\"\n//│ ╔══[ERROR] when `x$Tuple$2_0` is `O`\n//│ ║  l.83: \t  [O(), O()] then \"ones\"\n//│ ║        \t   ^\n//│ ╟── `x$Tuple$2_1` has 1 missing case\n//│ ╟── it can be class `Z`\n//│ ║  l.82: \t  [Z(), Z()] then \"zeros\"\n//│ ╙──      \t        ^\n//│ fun foo: forall 'a. {0: O | Z, 1: O & 'a} -> (\"ones\" | \"zeros\" | 'a)\n\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      Z() then \"zeros\"\n    O() then if b is\n      O() then \"ones\"\n//│ fun foo: Pair[O | Z, nothing] -> (\"ones\" | \"zeros\")\n\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      Z() then \"zeros\"\n      else \"???\"\n    O() then if b is\n      O() then \"ones\"\n//│ fun foo: Pair[O | Z, O] -> (\"???\" | \"ones\" | \"zeros\")\n\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      Z() then \"zeros\"\n      else \"???\"\n    O() then if b is\n      O() then \"zeros\"\n      else \"???\"\n//│ fun foo: Pair[O | Z, Object] -> (\"???\" | \"zeros\")\n\nclass S(pred: S | Z | O)\n//│ class S(pred: O | S | Z)\n\n// TODO: Cannot check exhaustiveness of nested UCS yet.\nfun foo(x) = if x is\n  Pair(a, b) then if a is\n    Z() then if b is\n      S(x) then x\n      else \"???\"\n    O() then if b is\n      O() then \"zeros\"\n      else \"???\"\n//│ fun foo: Pair[O | Z, Object] -> (\"???\" | \"zeros\" | O | S | Z)\n\nfoo(Pair(Z(), Z()))\n//│ \"???\" | \"zeros\" | O | S | Z\n//│ res\n//│     = '???'\n\n:e\nfun foo(x) = if x is\n  Pair(Z(), Z()) then \"zeros\"\n  Pair(O(), O()) then \"ones\"\n  Pair(y, O()) then x\n//│ ╔══[ERROR] when `x` is `Pair`\n//│ ║  l.141: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ║         \t  ^^^^\n//│ ╟── the second argument of `Pair` has 1 missing case\n//│ ╟── it can be class `Z`\n//│ ║  l.141: \t  Pair(Z(), Z()) then \"zeros\"\n//│ ╙──       \t            ^\n//│ fun foo: forall 'A 'B. Pair['A, O & 'B] -> (\"ones\" | \"zeros\" | Pair['A, 'B] | 'A)\n//│   where\n//│     'A <: Object\n\nfun foo(x, y) = if x is Z() and y is O() then 0 else 1\n//│ fun foo: (Object, Object) -> (0 | 1)\n\nfun foo(x, y) =\n  if x is\n    Z() and y is O() then 0\n    else 1\n//│ fun foo: (Object, Object) -> (0 | 1)\n"
  },
  {
    "path": "shared/src/test/diff/ucs/Hygiene.mls",
    "content": ":NewDefs\n\nclass Some[out T](value: T)\nclass Left[out T](value: T)\nclass Right[out T](value: T)\n//│ class Some[T](value: T)\n//│ class Left[T](value: T)\n//│ class Right[T](value: T)\n\n:ducs:postprocess.result\nfun foo(x) = if x is\n  Some(Left(y)) then x\n  Some(x) then x\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_x$Some*† = (Some).unapply(x,)\n//│     let x$Some_0*‡ = (ucs$args_x$Some).0\n//│     case x$Some_0*‡ of\n//│       Left*◊ ->\n//│         let ucs$args_x$Some_0$Left*† = (Left).unapply(x$Some_0,)\n//│         let y*‡ = (ucs$args_x$Some_0$Left).0\n//│         x\n//│       _ ->\n//│         let x*‡ = (ucs$args_x$Some).0\n//│         x\n//│ fun foo: forall 'T. Some[(Left[anything] | Object & ~#Left) & 'T] -> (Some['T] | 'T)\n\nfoo(Some(Left(1)))\n//│ Left[1] | Some[Left[1]]\n//│ res\n//│     = Some {}\n\nfoo(Some(2))\n//│ 2 | Some[2]\n//│ res\n//│     = 2\n"
  },
  {
    "path": "shared/src/test/diff/ucs/HygienicBindings.mls",
    "content": ":NewDefs\n\nfun (~~>) expect(a, b) = if a === b then () else error\n//│ fun (~~>) expect: forall 'a. (Eql['a], 'a) -> ()\n\ntype Option[out T] = None | Some[T]\nmodule None\nclass Some[out T](val value: T)\n//│ type Option[T] = None | Some[T]\n//│ module None\n//│ class Some[T](value: T)\n\ntype Either[A, B] = Left[A] | Right[B]\nclass Left[A](val leftValue: A)\nclass Right[B](val rightValue: B)\n//│ type Either[A, B] = Left[A] | Right[B]\n//│ class Left[A](leftValue: A)\n//│ class Right[B](rightValue: B)\n\ntype List[out A] = Nil | Cons[A]\nmodule Nil\nclass Cons[out A](head: A, tail: List[A])\n//│ type List[A] = Cons[A] | Nil\n//│ module Nil\n//│ class Cons[A](head: A, tail: List[A])\n\nfun justTrue(_) = true\nfun justFalse(_) = false\n//│ fun justTrue: anything -> true\n//│ fun justFalse: anything -> false\n\nfun h0(a) =\n  if\n    a is Some(Left(y)) then y\n    a is Some(Right(z)) then z\n    a is None then 0\n//│ fun h0: forall 'a. (None | Some[Left['a] | Right['a]]) -> (0 | 'a)\n\n// If a class parameter is bound to the same variable in different branches,\n// the bindings can be merged and can be typed and coverage checked. See the\n// desugared version below.\n:ducs:postprocess.result\nfun h0'(a) =\n  if\n    a is Some(x) and x is Left(y) then y\n    a is Some(x) and x is Right(z) then z\n    a is None then 0\n//│ Post-processed UCS term:\n//│ case a*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_a$Some*† = (Some).unapply(a,)\n//│     let x*‡ = (ucs$args_a$Some).0\n//│     case x*‡ of\n//│       Left*◊ ->\n//│         let ucs$args_x$Left*† = (Left).unapply(x,)\n//│         let y*‡ = (ucs$args_x$Left).0\n//│         y\n//│       Right*◊ ->\n//│         let ucs$args_x$Right*† = (Right).unapply(x,)\n//│         let z*‡ = (ucs$args_x$Right).0\n//│         z\n//│   None*† -> 0\n//│ fun h0': forall 'a. (None | Some[Left['a] | Right['a]]) -> (0 | 'a)\n\n// However, if the class parameter is bound to different variables in different\n// branches, the bindings cannot be merged and the type will miss the latter\n// branch. See the desugared version below.\nfun h1(a) =\n  if\n    a is Some(x) and x is Left(y) then y\n    a is Some(y) and y is Right(z) then z\n    a is None then 0\n//│ fun h1: forall 'a. (None | Some[Right[anything] & {#rightValue: 'a}]) -> (0 | 'a)\n\n// FIXME\nh1(Some(Left(0)))\n//│ ╔══[ERROR] Type `Left[?A]` does not contain member `rightValue`\n//│ ║  l.15: \tclass Right[B](val rightValue: B)\n//│ ╙──      \t                   ^^^^^^^^^^\n//│ 0 | error\n//│ res\n//│     = 0\n\n// FIXME: It is also impossible to merge bindings of different variables if one\n// of them is bound via a let binding.\nfun h2(a) =\n  if\n    a is Some(x) and x is x' and x' is Left(y) then y\n    a is Some(y) and\n      let y' = y\n      y' is Right(z) then z\n    a is None then 0\n//│ fun h2: forall 'a. (None | Some[Left['a]]) -> (0 | 'a)\n\n:ducs:postprocess.result\n:w\nfun h3(x, y, f, p) =\n  if x is\n    _ and f(x) is y and p(x) then y\n    None then y\n    _ then \"anyway\"\n//│ Post-processed UCS term:\n//│ let ucs$scrut$0*‡ = f(x,)\n//│ let ucs$shadow$0 = y\n//│ let y*‡ = ucs$scrut$0\n//│ let ucs$test$0*† = p(x,) : Bool\n//│ case ucs$test$0*† of\n//│   true*† -> y\n//│   _ ->\n//│     let y*‡ = ucs$shadow$0\n//│     case x*‡ of\n//│       None*† -> y\n//│       _ -> \"anyway\"\n//│ ╔══[WARNING] the outer binding `y`\n//│ ║  l.97: \tfun h3(x, y, f, p) =\n//│ ║        \t          ^\n//│ ╟── is shadowed by name pattern `y`\n//│ ║  l.99: \t    _ and f(x) is y and p(x) then y\n//│ ╙──      \t                  ^\n//│ fun h3: forall 'a 'b. (Object & 'a, 'b, 'a -> 'b, 'a -> Bool) -> (\"anyway\" | 'b)\n\n\nh3(\"anything\", \"not me\", _ => \"should be me\", _ => true) ~~> \"should be me\"\nh3(None, \"should be me\", _ => \"not me\", _ => false) ~~> \"should be me\"\nh3(\"anything\", \"anything\", _ => \"not me\", _ => false) ~~> \"anyway\"\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n\n\n:ducs:postprocess.result\n:w\nfun h4(x, y, p) =\n  if x is\n    y and p(x) then y\n    None then y\n    _ then \"default\"\n//│ Post-processed UCS term:\n//│ let ucs$shadow$0 = y\n//│ let y*‡ = x\n//│ let ucs$test$0*† = p(x,) : Bool\n//│ case ucs$test$0*† of\n//│   true*† -> y\n//│   _ ->\n//│     let y*‡ = ucs$shadow$0\n//│     case x*‡ of\n//│       None*† -> y\n//│       _ -> \"default\"\n//│ ╔══[WARNING] the outer binding `y`\n//│ ║  l.137: \tfun h4(x, y, p) =\n//│ ║         \t          ^\n//│ ╟── is shadowed by name pattern `y`\n//│ ║  l.139: \t    y and p(x) then y\n//│ ╙──       \t    ^\n//│ fun h4: forall 'a 'b. (Object & 'a, 'b, 'a -> Bool) -> (\"default\" | 'a | 'b)\n\nh4(\"should be me\", \"not me\", _ => true)\nh4(None, \"not me\", _ => true)\nh4(None, \"should be me\", _ => false)\nh4(\"anything\", \"not me\", _ => false)\n//│ \"anything\" | \"default\" | \"not me\"\n//│ res\n//│     = 'should be me'\n//│ res\n//│     = None { class: [class None] }\n//│ res\n//│     = 'should be me'\n//│ res\n//│     = 'default'\n\n:ducs:postprocess.result\nfun h5(x, y, p) =\n  if x is\n    Some(y) and p(x) then y\n    None then y\n    _ then y\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ ->\n//│     let ucs$args_x$Some*† = (Some).unapply(x,)\n//│     let ucs$shadow$0 = y\n//│     let y*‡ = (ucs$args_x$Some).0\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> y\n//│       _ ->\n//│         let y*‡ = ucs$shadow$0\n//│         y\n//│   None*† -> y\n//│   _ -> y\n//│ fun h5: forall 'a. (Object & ~#Some | Some['a], 'a, Some[nothing] -> Bool) -> 'a\n\nh5(Some(1), 2, justTrue) ~~> 1\nh5(Some(1), 2, justFalse) ~~> 2\nh5(None, 0, justTrue) ~~> 0\nh5(None, 0, justFalse) ~~> 0\nh5(\"foo\", 42, justTrue) ~~> 42\nh5(\"foo\", 42, justFalse) ~~> 42\n//│ ()\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n//│ res\n//│     = undefined\n"
  },
  {
    "path": "shared/src/test/diff/ucs/InterleavedLet.mls",
    "content": ":NewDefs\n\nfun f(x) =\n  if x ==\n    let v = 0\n    v then v\n    else 0\n//│ fun f: Num -> 0\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\nclass Left[A](leftValue: A) extends Either[A, nothing]\nclass Right[B](rightValue: B) extends Either[nothing, B]\n//│ abstract class Either[A, B]: Left[A] | Right[B]\n//│ class Left[A](leftValue: A) extends Either\n//│ class Right[B](rightValue: B) extends Either\n\n:ducs:normalize.result\nfun q(x) =\n  if\n    x is Some and x is Some and x is Some then 0\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 0\n//│ fun q: Some[anything] -> 0\n\n:e\n// FIXME: Unexpected empty split.\nfun p(x, y) =\n  if\n    x is Some and y is None then 0\n    y is Some and x is Some then 1\n    x is Some and y is Some then 0\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.39: \t    x is Some and y is Some then 0\n//│ ║        \t                       ^^^^\n//│ ╟── there is an identical pattern Some\n//│ ║  l.38: \t    y is Some and x is Some then 1\n//│ ╙──      \t         ^^^^\n//│ ╔══[ERROR] `y` has 1 missing case\n//│ ║  l.38: \t    y is Some and x is Some then 1\n//│ ║        \t    ^\n//│ ╟── it can be module `None`\n//│ ║  l.37: \t    x is Some and y is None then 0\n//│ ╙──      \t                       ^^^^\n//│ fun p: (Object & ~#Some | Some[anything], Some[anything]) -> (0 | 1)\n\nfun h(x, y) =\n  if x is\n    None then y\n    let y_square = y * y\n    Some(z) then z + y_square\n//│ fun h: (None | Some[Int], Int) -> Int\n\nh(Some(5), 6)\n//│ Int\n//│ res\n//│     = 41\n\nfun h(x, y) =\n  if x is\n    None then y\n    let y_square = y * y\n    Some(y_square) then 0\n//│ fun h: forall 'a. (None | Some[anything], Int & 'a) -> (0 | 'a)\n\n:e\nfun f(a, y) =\n  if a is\n    Some(v) and v is\n      Left(x) then x\n      let y = v + 1\n      Right(x) then x + y\n    else 0\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.78: \t      let y = v + 1\n//│ ║        \t              ^^^^^\n//│ ╟── reference of type `Right[?B]` is not an instance of type `Int`\n//│ ║  l.78: \t      let y = v + 1\n//│ ╙──      \t              ^\n//│ fun f: forall 'a. (Object & ~#Some | Some[Int | Left['a] | Right[Int]], anything) -> (Int | 'a)\n\n:pe\nfun q(a) =\n  if a is\n    Left(x) then x\n    let y = a + 1\n    then y\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.93: \t    let y = a + 1\n//│ ║        \t            ^^^^^\n//│ ║  l.94: \t    then y\n//│ ╙──      \t^^^^^^^^^^\n//│ fun q: forall 'a. (Left['a] | Object & ~#Left) -> (() | 'a)\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\n:e\nfun w() =\n  if\n    A then \"A\"\n    let y = 0\n    B then \"B\"\n    else \"?\"\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.110: \t    A then \"A\"\n//│ ║         \t    ^\n//│ ╙── reference of type `() -> A` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.112: \t    B then \"B\"\n//│ ║         \t    ^\n//│ ╙── reference of type `() -> B` is not an instance of type `Bool`\n//│ fun w: () -> (\"?\" | \"A\" | \"B\")\n\nw()\n//│ \"?\" | \"A\" | \"B\"\n//│ res\n//│     = '?'\n\nfun i(x) =\n  if x is\n    A() then \"A\"\n    let y = 0\n    B() then \"B\"\n//│ fun i: (A | B) -> (\"A\" | \"B\")\n\nfun inc(x) = x + 1\n//│ fun inc: Int -> Int\n\nfun qq(x, z) =\n  if x ==\n    let y = inc(z)\n    y * y then 0\n    else 0\n//│ fun qq: (Num, Int) -> 0\n\nfun bruh(x) =\n  if\n    x == 0 then 0\n    let y = 1\n    else y\n//│ fun bruh: Num -> (0 | 1)\n\nfun f1(x) = x + 1\nfun f2(x, y) = x + y\n//│ fun f1: Int -> Int\n//│ fun f2: (Int, Int) -> Int\n\nfun ff(x) =\n  if\n    x == 0 then 0\n    let y = f1(x)\n    let z = f2(x, y)\n    z == 1 then 1\n    z == 2 then 2\n    else 0\n//│ fun ff: Int -> (0 | 1 | 2)\n\n:e\n// FIXME: Should warn missing else branches.\nfun ip(y) =\n  if q(y) and\n    let z = inc(y)\n    y == z * z then \"bruh\"\n  else \"rocks\"\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.171: \t  if q(y) and\n//│ ║         \t     ^^^^\n//│ ╟── undefined literal of type `()` is not an instance of type `Bool`\n//│ ║  l.94: \t    then y\n//│ ║        \t          ^\n//│ ╟── but it flows into application with expected type `Bool`\n//│ ║  l.171: \t  if q(y) and\n//│ ╙──       \t     ^^^^\n//│ fun ip: Int -> (\"bruh\" | \"rocks\")\n\nfun tr(x) =\n  if x is\n    Some(v) then v\n    let tmp = 1\n    None then tmp\n//│ fun tr: forall 'a. (None | Some['a]) -> (1 | 'a)\n\nclass Pair[A, B](val fst: A, val snd: B)\nabstract class List[out A]: Nil | Cons[A]\nmodule Nil extends List[nothing]\nclass Cons[out A](head: A, tail: List[A]) extends List[A]\n//│ class Pair[A, B](fst: A, snd: B)\n//│ abstract class List[A]: Cons[A] | Nil\n//│ module Nil extends List\n//│ class Cons[A](head: A, tail: List[A]) extends List\n\nfun (::) cons(h, t) = Cons(h, t)\nfun (++) strcat(a, b) = concat(a)(b)\n//│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A]\n//│ fun (++) strcat: (Str, Str) -> Str\n\nfun showList(xs) =\n  if xs is\n    Nil              then \"\"\n    Cons(head, Nil)  then toString(head)\n    Cons(head, tail) then toString(head) ++ \", \" ++ showList(tail)\n//│ fun showList: (Cons[anything] | Nil) -> Str\n\nlet zeroToThree = 0 :: 1 :: 2 :: 3 :: Nil\n//│ let zeroToThree: Cons[0 | 1 | 2 | 3]\n//│ zeroToThree\n//│             = Cons {}\n\nshowList(zeroToThree)\n//│ Str\n//│ res\n//│     = '0, 1, 2, 3'\n\nfun evenness(x) = if x % 2 is 0 then Left(x) else Right(x)\n//│ fun evenness: forall 'A 'B. (Int & 'A & 'B) -> (Left['A] | Right['B])\n\nfun mapPartition(f, xs) =\n  if xs is\n    Nil then Pair(Nil, Nil)\n    Cons(x, xs) and mapPartition(f, xs) is Pair(l, r) and f(x) is\n      Left(v) then Pair(Cons(v, l), r)\n      Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0 'A1 'A2 'B 'B0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[in 'A1 & 'A2 out 'A2, in 'B & 'B0 out 'B0 | Cons['A0]]\n//│   where\n//│     'B <: List['A0] & 'B0\n//│     'B0 :> Cons['A0] | Nil\n//│         <: 'B\n//│     'A1 <: List['A] & 'A2\n//│     'A2 :> Cons['A] | Nil\n//│         <: 'A1\n\nmapPartition(x => (if x % 2 == 0 then Left(x) else Right(x)), zeroToThree)\n//│ forall 'A 'A0 'B 'B0. Pair[in 'A & 'A0 out 'A0, in 'B & 'B0 out 'B0 | Cons[0 | 1 | 2 | 3 | 'A1]]\n//│   where\n//│     'B <: List['A1] & 'B0\n//│     'B0 :> Cons[0 | 1 | 2 | 3 | 'A1] | Nil\n//│         <: 'B\n//│     'A <: List['A2] & 'A0\n//│     'A0 :> Cons[0 | 1 | 2 | 3 | 'A2] | Nil\n//│         <: 'A\n//│ res\n//│     = Pair {}\n\n// This should be the desugaring of the above:\nfun mapPartition'(f, xs) =\n  if xs is\n    Nil then Pair(Nil, Nil)\n    Cons(x, xs) and mapPartition(f, xs) is res and res.fst is l and res.snd is r and f(x) is\n      Left(v)  then Pair(Cons(v, l), r)\n      Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition': forall 'a 'A 'A0 'A1 'A2 'A3 'B. ('a -> (Left['A & 'A0] | Right['A1 & 'A2]), Cons['a] | Nil) -> Pair[in 'A3 out Cons['A] | Nil | 'A3 | Cons['A0], in 'B out Cons['A2] | 'B | Cons['A1] | Nil]\n\nmapPartition'(x => (if x % 2 == 0 then Left(x) else Right(x)), zeroToThree)\n//│ forall 'A 'B. Pair[in 'A out Cons[0 | 1 | 2 | 3] | Nil | 'A, in 'B out Cons[0 | 1 | 2 | 3] | 'B | Nil]\n//│ res\n//│     = Pair {}\n\n// This is a very interesting side-effect example!\n\nfun mn(a) =\n  if a is\n    Some(x) and x is\n      Left(b) and b is\n        0 then \"b is 1\"\n        let _ = log(b)\n        1 then \"b is 2\"\n        2 then \"b is 3\"\n      Right(b) then \"right-defined\"\n    None       then \"undefined\"\n//│ fun mn: (None | Some[Left[0 | 1 | 2] | Right[anything]]) -> (\"b is 1\" | \"b is 2\" | \"b is 3\" | \"right-defined\" | \"undefined\")\n\nmn of None\nmn of Some of Left of 0\nmn of Some of Left of 1\nmn of Some of Left of 2\nmn of Some of Right of ()\n//│ \"b is 1\" | \"b is 2\" | \"b is 3\" | \"right-defined\" | \"undefined\"\n//│ res\n//│     = 'undefined'\n//│ res\n//│     = 'b is 1'\n//│ res\n//│     = 'b is 2'\n//│ // Output\n//│ 1\n//│ res\n//│     = 'b is 3'\n//│ // Output\n//│ 2\n//│ res\n//│     = 'right-defined'\n"
  },
  {
    "path": "shared/src/test/diff/ucs/LeadingAnd.mls",
    "content": ":NewDefs\n\n\n\nclass Some[T](value: T)\n//│ class Some[T](value: T)\n\n\n\nfun f(a, b) = if a is\n  Some(av)\n    and b is Some(bv) then av + bv\n//│ fun f: (Some[Int], Some[Int]) -> Int\n\nfun f(a, b) = if a is Some(av)\n    and b is Some(bv)\n    then av + bv\n//│ fun f: (Some[Int], Some[Int]) -> Int\n\nfun f(a, b) = if a is\n  Some(av)\n    and b is Some(bv)\n    then av + bv\n//│ fun f: (Some[Int], Some[Int]) -> Int\n\n\n\n// FIXME (parser)\nfun f(a, b) = if a is\n  Some(av)\n    and b is Some(bv) then av + bv\n    \n//│ fun f: (Some[Int], Some[Int]) -> Int\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/LitUCS.mls",
    "content": ":NewDefs\n\nmodule A\n//│ module A\n\n// This one is easy to fix but what about the next one?\n// The following example can better reveal the essence of the problem.\nfun test(x: 0 | A) = if x is\n  0 then 0\n  A then A\n//│ fun test: (x: 0 | A) -> (0 | A)\n\n:e\n// case === (x,) (0,) of { true => 0; _ => case x of { A => A } }\nfun test(x: 0 | A) =\n  if\n    x === 0 then 0\n    x is A then A\n//│ ╔══[ERROR] Module 'A' does not support equality comparison because it does not have a parameter list\n//│ ║  l.17: \t    x === 0 then 0\n//│ ╙──      \t    ^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.18: \t    x is A then A\n//│ ║        \t    ^^^^^^^^^^^^^\n//│ ╟── type `0` is not an instance of type `A`\n//│ ║  l.15: \tfun test(x: 0 | A) =\n//│ ║        \t            ^\n//│ ╟── but it flows into reference with expected type `A`\n//│ ║  l.18: \t    x is A then A\n//│ ║        \t    ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.18: \t    x is A then A\n//│ ╙──      \t         ^\n//│ fun test: (x: 0 | A) -> (0 | A)\n\nfun test2(x) =\n  if\n    x === 0 then 0\n    x is A then A\n//│ fun test2: (A & Eql[0]) -> (0 | A)\n\n:e\ntest2(0)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.43: \ttest2(0)\n//│ ║        \t^^^^^^^^\n//│ ╟── integer literal of type `0` is not an instance of type `A`\n//│ ║  l.43: \ttest2(0)\n//│ ║        \t      ^\n//│ ╟── Note: constraint arises from class pattern:\n//│ ║  l.39: \t    x is A then A\n//│ ║        \t         ^\n//│ ╟── from reference:\n//│ ║  l.39: \t    x is A then A\n//│ ╙──      \t    ^\n//│ 0 | A | error\n//│ res\n//│     = 0\n\n:e\ntest2(A)\n//│ ╔══[ERROR] Module 'A' does not support equality comparison because it does not have a parameter list\n//│ ║  l.61: \ttest2(A)\n//│ ╙──      \t^^^^^^^^\n//│ 0 | A | error\n//│ res\n//│     = A { class: [class A] }\n"
  },
  {
    "path": "shared/src/test/diff/ucs/MultiwayIf.mls",
    "content": ":NewDefs\n\n\nfun f(x) =\n  if\n    x > 0  then 0\n    x == 0 then 1\n    _      then 2\n//│ fun f: Num -> (0 | 1 | 2)\n\n\nfun f(x) =\n  if\n    x > 0  and\n      x % 2 === 0 then true\n      _           then false\n    x == 0 then true\n    _      then false\n//│ fun f: Int -> Bool\n\nf(0)\nf(2)\nf(3)\nf(0 - 1)\nf(0 - 2)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n//│ res\n//│     = false\n\nfun f(x) =\n  if\n    x > 0  and\n      x % 2 === 0 then true\n      else false\n    x == 0 then true\n  else false\n//│ fun f: Int -> Bool\n\nf(0)\nf(2)\nf(1)\nf(0 - 1)\n//│ Bool\n//│ res\n//│     = true\n//│ res\n//│     = true\n//│ res\n//│     = false\n//│ res\n//│     = false\n"
  },
  {
    "path": "shared/src/test/diff/ucs/NestedBranches.mls",
    "content": ":NewDefs\n\n\nclass Some[out A](val value: A)\nmodule None\nclass Left[out A](val leftValue: A)\nclass Right[out A](val rightValue: A)\nmodule Nil\nclass Cons[out A](val head: A, val tail: Cons[A] | Nil)\nclass Pair[out A, out B](val fst: A, val snd: B)\n//│ class Some[A](value: A)\n//│ module None\n//│ class Left[A](leftValue: A)\n//│ class Right[A](rightValue: A)\n//│ module Nil\n//│ class Cons[A](head: A, tail: Cons[A] | Nil)\n//│ class Pair[A, B](fst: A, snd: B)\n\n\nfun optionApply(x, y, f) =\n  if x is\n    Some(xv) and y is\n      Some(yv) then Some(f(xv, yv))\n      None then None\n    None then None\n//│ fun optionApply: forall 'a 'b 'A. (None | Some['a], None | Some['b], ('a, 'b) -> 'A) -> (None | Some['A])\n\nfun (::) cons(h, t) = Cons(h, t)\n//│ fun (::) cons: forall 'A. ('A, Cons['A] | Nil) -> Cons['A]\n\nlet zeroToThree = 0 :: 1 :: 2 :: 3 :: Nil\n//│ let zeroToThree: Cons[0 | 1 | 2 | 3]\n//│ zeroToThree\n//│             = Cons {}\n\nfun f(x) = if x % 2 == 0 then Left(x) else Right(x)\n//│ fun f: forall 'A. (Int & 'A) -> (Left['A] | Right['A])\n\n\nfun mapPartition(f, xs) = if xs is\n  Nil then Pair(Nil, Nil)\n  Cons(x, xs) and mapPartition(f, xs) is Pair(l, r) and f(x) is\n    Left(v)  then Pair(Cons(v, l), r)\n    Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil]\n\n\nmapPartition(x => Left(x + 1), zeroToThree)\n//│ Pair[Cons[Int] | Nil, Cons[nothing] | Nil]\n//│ res\n//│     = Pair {}\n\n\nmapPartition(f, zeroToThree)\n//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = Pair {}\n\n\nfun mapPartition(f, xs) = if xs is\n  Nil then Pair(Nil, Nil)\n  Cons(x, xs) and\n    mapPartition(f, xs) is Pair(l, r) and f(x) is\n      Left(v)  then Pair(Cons(v, l), r)\n      Right(v) then Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil]\n\nmapPartition(f, zeroToThree)\n//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = Pair {}\n\n\nfun mapPartition(f, xs) = if xs is\n  Nil then\n    Pair(Nil, Nil)\n  Cons(x, xs) and\n    mapPartition(f, xs) is\n      Pair(l, r) and\n        f(x) is\n          Left(v)  then\n            Pair(Cons(v, l), r)\n          Right(v) then\n            Pair(l, Cons(v, r))\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil]\n\nmapPartition(f, zeroToThree)\n//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = Pair {}\n\nfun mapPartition(f, xs) = if xs is\n  Nil then [Nil, Nil]\n  Cons(x, xs) and mapPartition(f, xs) is [l, r] and f(x) is\n    Left(v)  then [Cons(v, l), r]\n    Right(v) then [l, Cons(v, r)]\n//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> [Cons['A] | Nil, Cons['A0] | Nil]\n\n\nmapPartition(f, zeroToThree)\n//│ [Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil]\n//│ res\n//│     = [ Cons {}, Cons {} ]\n\n// * Vertical alignment is not allowed! (good)\n:pe\n:w\n:e\nfun mapPartition(f, xs) = if xs is\n  Nil then [Nil, Nil]\n  Cons(x, xs) and mapPartition(f, xs) is [l, r]\n          and f(x) is Left(v)  then [Cons(v, l), r]\n                      Right(v) then [l, Cons(v, r)]\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.113: \t                      Right(v) then [l, Cons(v, r)]\n//│ ╙──       \t                               ^^^^\n//│ ╔══[WARNING] Paren-less applications should use the 'of' keyword\n//│ ║  l.112: \t          and f(x) is Left(v)  then [Cons(v, l), r]\n//│ ║         \t                                    ^^^^^^^^^^^^^^^\n//│ ║  l.113: \t                      Right(v) then [l, Cons(v, r)]\n//│ ╙──       \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.112: \t          and f(x) is Left(v)  then [Cons(v, l), r]\n//│ ║         \t                                    ^^^^^^^^^^^^^^^\n//│ ║  l.113: \t                      Right(v) then [l, Cons(v, r)]\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── tuple literal of type `[?a, ?b]` is not a function\n//│ ║  l.112: \t          and f(x) is Left(v)  then [Cons(v, l), r]\n//│ ╙──       \t                                    ^^^^^^^^^^^^^^^\n//│ fun mapPartition: forall 'a. ('a -> Left[anything], Cons['a] | Nil) -> (error | [Nil, Nil])\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/NestedOpSplits.mls",
    "content": ":NewDefs\n\n\n// * Note that this always to the left\n:e\nfun f(x) =\n  if x ==\n    1 +\n      2 then 0\n      _ then 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.8: \t    1 +\n//│ ║       \t      ^\n//│ ║  l.9: \t      2 then 0\n//│ ║       \t^^^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.7: \t  if x ==\n//│ ║       \t     ^^^^\n//│ ║  l.8: \t    1 +\n//│ ╙──     \t^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.8: \t    1 +\n//│ ║       \t      ^\n//│ ║  l.9: \t      2 then 0\n//│ ║       \t^^^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ fun f: Num -> (0 | 1)\n\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/NestedPattern.mls",
    "content": ":NewDefs\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\nclass Left[A](leftValue: A) extends Either[A, nothing]\nclass Right[B](rightValue: B) extends Either[nothing, B]\n//│ abstract class Either[A, B]: Left[A] | Right[B]\n//│ class Left[A](leftValue: A) extends Either\n//│ class Right[B](rightValue: B) extends Either\n\nfun compute(v) =\n  if v is\n    Left(Some(x)) then x * 5\n    Left(None()) then 1\n    Right(Some(x)) then x * 3\n    Right(None()) then 0\n//│ fun compute: (Left[None | Some[Int]] | Right[None | Some[Int]]) -> Int\n\nfun crazy(v) =\n  if v is\n    Some(Some(Some(Some(Some(Some(None())))))) then \"bruh!\"\n    _ then \"lol\"\n//│ fun crazy: (Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object & ~#Some | Some[Object]]]]]]) -> (\"bruh!\" | \"lol\")\n\n\n// * TODO(@chengluyu) fix these missing locations\n\nfun f(x) =\n  if x is\n    [0, 0] then \"zeros\"\n    [1, 1] then \"ones\"\n    _      then \"bruh\"\n//│ fun f: {0: Object, 1: Object} -> (\"bruh\" | \"ones\" | \"zeros\")\n\nf([0, 0])\nf([1, 1])\nf([1, 0])\n//│ \"bruh\" | \"ones\" | \"zeros\"\n//│ res\n//│     = 'zeros'\n//│ res\n//│     = 'ones'\n//│ res\n//│     = 'bruh'\n\nfun f(x) =\n  if x is\n    [0, 0] then \"zeros\"\n    [1, 1] then \"ones\"\n    [y, 1] then x\n    _      then \"que?\"\n//│ fun f: forall 'a. ({0: Object, 1: Object} & 'a) -> (\"ones\" | \"que?\" | \"zeros\" | 'a)\n\nf([0, 0])\nf([1, 1])\nf([0, 1])\nf([1, 0])\n//│ \"ones\" | \"que?\" | \"zeros\" | [1, 0]\n//│ res\n//│     = 'zeros'\n//│ res\n//│     = 'ones'\n//│ res\n//│     = [ 0, 1 ]\n//│ res\n//│     = 'que?'\n\nfun f(p) =\n  if p is\n    Some([x, y]) then x + y\n    None()       then 0\n//│ fun f: (None | Some[{0: Int, 1: Int}]) -> Int\n\nclass Union[A, B](a: A, b: B)\n//│ class Union[A, B](a: A, b: B)\n\n// Name conflict between the scrutinee and the positionals.\n// Desugar result: let tmp13 = x in case tmp13 of { Union => let x = (tmp13).a in let y = (tmp13).b in x }\nfun hmm(x) =\n  if x is Union(x, y) then x\n//│ fun hmm: forall 'a. Union['a, anything] -> 'a\n\nhmm(Union(1, 2))\n//│ 1\n//│ res\n//│     = 1\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/NuPlainConditionals.mls",
    "content": ":NewDefs\n\n\nclass Pair[A](fst: A, snd: A)\n//│ class Pair[A](fst: A, snd: A)\n\n\n\nPair(0, 1) is Pair\n//│ Bool\n//│ res\n//│     = true\n\nPair(0, 1) is Pair(a, b)\n//│ Bool\n//│ res\n//│     = true\n\nPair(0, 1) is Pair(0, _)\n//│ Bool\n//│ res\n//│     = true\n\nif Pair(0, 1) is Pair(a, b) then true else false\n//│ Bool\n//│ res\n//│     = true\n\n\nfun foo(x) = x is Pair(a, b)\n//│ fun foo: (Object & ~#Pair | Pair[anything]) -> Bool\n\n\nPair(0, 1) is Pair(a, b) and a > b\n//│ Bool\n//│ res\n//│     = false\n\nif Pair(0, 1) is Pair(a, b) then a > b else false\n//│ Bool\n//│ res\n//│     = false\n\n\nfun foo(x) = x is Pair(a, b) and a > b\n//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool\n\nfun foo(x) = if x is Pair(a, b) then a > b else false\n//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool\n\n\n// TODO proper error\nfun foo(x) = x is\n  Pair\n  Int\n//│ ╔══[ERROR] unknown pattern {Pair; Int}\n//│ ║  l.54: \t  Pair\n//│ ║        \t  ^^^^\n//│ ║  l.55: \t  Int\n//│ ╙──      \t^^^^^\n//│ ╔══[WARNING] this case is unreachable\n//│ ╙── because it is subsumed by the branch\n//│ fun foo: anything -> true\n\n// TODO proper error\nfun foo(x) = x is\n  Pair(a, b) and a > b\n  Int\n//│ ╔══[ERROR] unknown pattern {and(Pair(a, b,), >(a, b,),); Int}\n//│ ║  l.67: \t  Pair(a, b) and a > b\n//│ ║        \t  ^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.68: \t  Int\n//│ ╙──      \t^^^^^\n//│ ╔══[WARNING] this case is unreachable\n//│ ╙── because it is subsumed by the branch\n//│ fun foo: anything -> true\n\n// TODO support `|`\nfun foo1(x) = x is Pair(a, b) | Int\nfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╔══[ERROR] type identifier `|` not found\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                          ^\n//│ ╔══[ERROR] type identifier `and` not found\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                               ^^^\n//│ ╔══[ERROR] type identifier `>` not found\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                     ^\n//│ ╔══[ERROR] type identifier `|` not found\n//│ ║  l.79: \tfun foo1(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                              ^\n//│ ╔══[ERROR] type identifier not found: |\n//│ ║  l.79: \tfun foo1(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                              ^\n//│ ╔══[ERROR] type identifier not found: |\n//│ ║  l.80: \tfun foo2(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                          ^\n//│ fun foo1: nothing -> error\n//│ fun foo2: nothing -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol |\n\n\n\nclass A(arg: Int)\n//│ class A(arg: Int)\n\n// TODO make `is` lower precedence than `=>`\nx => (x is A(_))\n//│ Object -> Bool\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/Or.mls",
    "content": ":NewDefs\n\n\nclass Some[T](value: T)\n//│ class Some[T](value: T)\n\n\n// TODO support `or` in UCS\nfun f(a, b) = if a is\n  Some(v)\n    and b is Some(v') then v + v'\n    or  b is Some(v)  then v\n  else 0\n//│ ╔══[ERROR] cannot transform due to an illegal split operator or\n//│ ║  l.12: \t    or  b is Some(v)  then v\n//│ ║        \t    ^^\n//│ ╟── the following branch will be discarded\n//│ ║  l.12: \t    or  b is Some(v)  then v\n//│ ╙──      \t        ^^^^^^^^^^^^^^^^^^^^\n//│ fun f: (Object & ~#Some | Some[Int], Object & ~#Some | Some[Int]) -> Int\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/OverlappedBranches.mls",
    "content": ":NewDefs\n\nclass Base()\nclass Derived1() extends Base()\nclass Derived2() extends Base()\nclass Derived3() extends Derived2()\n//│ class Base()\n//│ class Derived1() extends Base\n//│ class Derived2() extends Base\n//│ class Derived3() extends Base, Derived2\n\n// The very basic case.\n// It should warn about that the last two cases are unreachable.\n:w\n:ducs:normalize.result\nfun f1(x) = if x is\n  Base then \"b\"\n  Derived1 then \"d1\"\n  Derived2 then \"d2\"\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Base*◊ -> \"b\"\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.18: \t  Derived1 then \"d1\"\n//│ ║        \t  ^^^^^^^^\n//│ ╟── the case is covered by pattern Base\n//│ ║  l.17: \t  Base then \"b\"\n//│ ║        \t  ^^^^\n//│ ╟── due to the subtyping relation\n//│ ║  l.4: \tclass Derived1() extends Base()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[WARNING] found a duplicated case\n//│ ║  l.19: \t  Derived2 then \"d2\"\n//│ ║        \t  ^^^^^^^^\n//│ ╟── the case is covered by pattern Base\n//│ ║  l.17: \t  Base then \"b\"\n//│ ║        \t  ^^^^\n//│ ╟── due to the subtyping relation\n//│ ║  l.5: \tclass Derived2() extends Base()\n//│ ╙──     \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ fun f1: Base -> \"b\"\n\nf1(Base())\nf1(Derived1())\nf1(Derived2())\n//│ \"b\"\n//│ res\n//│     = 'b'\n//│ res\n//│     = 'b'\n//│ res\n//│     = 'b'\n\n// Decision paths:\n// + «x is Base» and «p (x,)» => \"b and p\"\n// + «x is Derived1» => \"d1\"\n// + «x is Derived2» => \"d2\"\n// +  => \"otherwise\"\n// The case tree:\n//    «x» match\n//      case Base =>\n//        if «p (x,)»\n//          «\"b and p\"»\n//        else\n//          «x» match\n//            case Derived1 =>\n//              «\"d1\"»\n//            case Derived2 =>\n//              «\"d2\"»\n//            default\n//              «\"otherwise\"»\n//      default\n//        «\"otherwise\"»\nfun f2(x, p) = if x is\n  Base and p(x) then \"b and p\"\n  Derived1 then \"d1\"\n  Derived2 then \"d2\"\n  else \"otherwise\"\n//│ fun f2: forall 'a. (Object & ~#Base | 'a & (Base & ~#Derived1 & ~#Derived2 | Derived1 | Derived2), (Base & 'a) -> Bool) -> (\"b and p\" | \"d1\" | \"d2\" | \"otherwise\")\n\nf2(Base(), _ => true) // => b and p\nf2(Base(), _ => false) // otherwise\n//│ \"b and p\" | \"d1\" | \"d2\" | \"otherwise\"\n//│ res\n//│     = 'b and p'\n//│ res\n//│     = 'otherwise'\n\nf2(Derived1(), _ => true) // => b and p\nf2(Derived2(), _ => true) // => b and p\n//│ \"b and p\" | \"d1\" | \"d2\" | \"otherwise\"\n//│ res\n//│     = 'b and p'\n//│ res\n//│     = 'b and p'\n\nf2(Derived1(), _ => false) // => d1\nf2(Derived2(), _ => false) // => d2\n//│ \"b and p\" | \"d1\" | \"d2\" | \"otherwise\"\n//│ res\n//│     = 'd1'\n//│ res\n//│     = 'd2'\n"
  },
  {
    "path": "shared/src/test/diff/ucs/ParseFailures.mls",
    "content": ":NewDefs\n:NoJS\n\ntype Tree[A] = Node[A] | Empty\nmodule Empty\nclass Node[A](value: Int, left: Tree[A], right: Tree[A])\n//│ type Tree[A] = Empty | Node[A]\n//│ module Empty\n//│ class Node[A](value: Int, left: Tree[A], right: Tree[A])\n\nfun contains(node, wanted) =\n  if node is\n    Node(value, left, right) and wanted\n      <= value then contains(left, wanted)\n      >= value then contains(right, wanted)\n      else true\n    Empty then false\n//│ fun contains: forall 'A. (Empty | Node['A], Num) -> Bool\n\nfun contains'(node, wanted) =\n  if node is\n    Node(value, left, right) and wanted\n      <= value then contains'(left, wanted)\n      >= value then contains'(right, wanted)\n      _ then true\n    Empty then false\n//│ fun contains': forall 'A. (Empty | Node['A], Num) -> Bool\n\n:pe\nclass Z()\nclass O()\nfun foo(x, y) = if x is\n  Z() and y is O() then 0 else 1\n//│ ╔══[PARSE ERROR] Unexpected 'else' keyword here\n//│ ║  l.33: \t  Z() and y is O() then 0 else 1\n//│ ╙──      \t                          ^^^^\n//│ class Z()\n//│ class O()\n//│ fun foo: (Z, O) -> 0\n"
  },
  {
    "path": "shared/src/test/diff/ucs/ParserFailures.mls",
    "content": ":NewDefs\n:NoJS\n\n// FIXME: Interleaved let bindings are not implemented in `IfOpsApp`.\nif x\n  == 0 then \"bad\"\n  let y = f(z)\n  == y * y then 0\n//│ ╔══[PARSE ERROR] expect an operator\n//│ ║  l.7: \t  let y = f(z)\n//│ ╙──     \t  ^^^\n//│ ╔══[PARSE ERROR] Unexpected 'let' keyword here\n//│ ║  l.7: \t  let y = f(z)\n//│ ╙──     \t  ^^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t  == 0 then \"bad\"\n//│ ╙──     \t            ^^^^^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.5: \tif x\n//│ ╙──     \t   ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t  == 0 then \"bad\"\n//│ ║       \t            ^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ \"bad\"\n\n// FIXME: Interleaved let bindings are not implemented in `IfOpsApp`.\nfun tt(x) =\n  if x\n    is A() then \"A\"\n    let y = 0\n    is B() then \"B\"\n//│ ╔══[PARSE ERROR] expect an operator\n//│ ║  l.31: \t    let y = 0\n//│ ╙──      \t    ^^^\n//│ ╔══[PARSE ERROR] Unexpected 'let' keyword here\n//│ ║  l.31: \t    let y = 0\n//│ ╙──      \t    ^^^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.30: \t    is A() then \"A\"\n//│ ╙──      \t       ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.30: \t    is A() then \"A\"\n//│ ╙──      \t       ^\n//│ fun tt: nothing -> error\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/PlainConditionals.mls",
    "content": ":NewDefs\n\n\nclass Pair[A, B](fst: A, snd: B)\n//│ class Pair[A, B](fst: A, snd: B)\n\n\n\nPair(0, 1) is Pair\n//│ Bool\n//│ res\n//│     = true\n\nPair(0, 1) is Pair(a, b)\n//│ Bool\n//│ res\n//│     = true\n\nPair(0, 1) is Pair(0, _)\n//│ Bool\n//│ res\n//│     = true\n\nif Pair(0, 1) is Pair(a, b) then true else false\n//│ Bool\n//│ res\n//│     = true\n\n\nfun foo(x) = x is Pair(a, b)\n//│ fun foo: (Object & ~#Pair | Pair[anything, anything]) -> Bool\n\n\nPair(0, 1) is Pair(a, b) and a > b\n//│ Bool\n//│ res\n//│     = false\n\nif Pair(0, 1) is Pair(a, b) then a > b else false\n//│ Bool\n//│ res\n//│     = false\n\n\nfun foo(x) = x is Pair(a, b) and a > b\n//│ fun foo: (Object & ~#Pair | Pair[Num, Num]) -> Bool\n\nfun foo(x) = if x is Pair(a, b) then a > b else false\n//│ fun foo: (Object & ~#Pair | Pair[Num, Num]) -> Bool\n\n\n// TODO proper error\nfun foo(x) = x is\n  Pair\n  Int\n//│ ╔══[ERROR] unknown pattern {Pair; Int}\n//│ ║  l.54: \t  Pair\n//│ ║        \t  ^^^^\n//│ ║  l.55: \t  Int\n//│ ╙──      \t^^^^^\n//│ ╔══[WARNING] this case is unreachable\n//│ ╙── because it is subsumed by the branch\n//│ fun foo: anything -> true\n\n// TODO proper error\nfun foo(x) = x is\n  Pair(a, b) and a > b\n  Int\n//│ ╔══[ERROR] unknown pattern {and(Pair(a, b,), >(a, b,),); Int}\n//│ ║  l.67: \t  Pair(a, b) and a > b\n//│ ║        \t  ^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.68: \t  Int\n//│ ╙──      \t^^^^^\n//│ ╔══[WARNING] this case is unreachable\n//│ ╙── because it is subsumed by the branch\n//│ fun foo: anything -> true\n\n// TODO support `|`\nfun foo(x) = x is Pair(a, b) | Int\nfun foo(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╔══[ERROR] type identifier `|` not found\n//│ ║  l.80: \tfun foo(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                         ^\n//│ ╔══[ERROR] type identifier `and` not found\n//│ ║  l.80: \tfun foo(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                              ^^^\n//│ ╔══[ERROR] type identifier `>` not found\n//│ ║  l.80: \tfun foo(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                    ^\n//│ ╔══[ERROR] type identifier `|` not found\n//│ ║  l.79: \tfun foo(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                             ^\n//│ ╔══[ERROR] Redefinition of 'foo'\n//│ ║  l.80: \tfun foo(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] type identifier not found: |\n//│ ║  l.79: \tfun foo(x) = x is Pair(a, b) | Int\n//│ ╙──      \t                             ^\n//│ ╔══[ERROR] type identifier not found: |\n//│ ║  l.80: \tfun foo(x) = x is (Pair(a, b) and a > b) | Int\n//│ ╙──      \t                                         ^\n//│ fun foo: nothing -> error\n//│ fun foo: nothing -> error\n//│ Code generation encountered an error:\n//│   unresolved symbol |\n\n\n\nclass A[T](arg: T)\n//│ class A[T](arg: T)\n\n\nx => (x is A(_))\n//│ (A[anything] | Object & ~#A) -> Bool\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/SimpleUCS.mls",
    "content": ":NewDefs\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\nclass Left[A](leftValue: A) extends Either[A, nothing]\nclass Right[B](rightValue: B) extends Either[nothing, B]\n//│ abstract class Either[A, B]: Left[A] | Right[B]\n//│ class Left[A](leftValue: A) extends Either\n//│ class Right[B](rightValue: B) extends Either\n\n:e\nfun f(x, y) =\n  if x is\n    Left(xv) and y is Left(yv) then xv + yv\n    Right(xv) and y is Right(yv) then xv * yv\n    None and y is None then 0\n//│ ╔══[ERROR] when `x` is `Left`\n//│ ║  l.20: \t    Left(xv) and y is Left(yv) then xv + yv\n//│ ║        \t    ^^^^\n//│ ╟── `y` has 2 missing cases\n//│ ║  l.20: \t    Left(xv) and y is Left(yv) then xv + yv\n//│ ║        \t                 ^\n//│ ╟── it can be module `None`\n//│ ║  l.22: \t    None and y is None then 0\n//│ ║        \t                  ^^^^\n//│ ╟── it can be class `Right`\n//│ ║  l.21: \t    Right(xv) and y is Right(yv) then xv * yv\n//│ ╙──      \t                       ^^^^^\n//│ ╔══[ERROR] when `x` is `Right`\n//│ ║  l.21: \t    Right(xv) and y is Right(yv) then xv * yv\n//│ ║        \t    ^^^^^\n//│ ╟── `y` has 2 missing cases\n//│ ║  l.21: \t    Right(xv) and y is Right(yv) then xv * yv\n//│ ║        \t                  ^\n//│ ╟── it can be class `Left`\n//│ ║  l.20: \t    Left(xv) and y is Left(yv) then xv + yv\n//│ ║        \t                      ^^^^\n//│ ╟── it can be module `None`\n//│ ║  l.22: \t    None and y is None then 0\n//│ ╙──      \t                  ^^^^\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.22: \t    None and y is None then 0\n//│ ║        \t    ^^^^\n//│ ╟── `y` has 2 missing cases\n//│ ║  l.22: \t    None and y is None then 0\n//│ ║        \t             ^\n//│ ╟── it can be class `Left`\n//│ ║  l.20: \t    Left(xv) and y is Left(yv) then xv + yv\n//│ ║        \t                      ^^^^\n//│ ╟── it can be class `Right`\n//│ ║  l.21: \t    Right(xv) and y is Right(yv) then xv * yv\n//│ ╙──      \t                       ^^^^^\n//│ fun f: (Left[Int] | None | Right[Int], nothing) -> Int\n\nfun f(x, y) =\n  if x is\n    Left(xv) and y is Left(yv) then xv + yv\n    None then 0\n//│ fun f: (Left[Int] | None, Left[Int]) -> Int\n\nfun f(x, y) =\n  if x is\n    Left(xv) and y is\n      Left(yv) then xv + yv\n      Right(yv) then xv * yv\n    None then 0\n//│ fun f: (Left[Int] | None, Left[Int] | Right[Int]) -> Int\n\nfun f(x) =\n  if x is\n    Some(v) and\n      v < 0 then \"negative\"\n      v > 0 then \"positive\"\n      _     then \"zero\"\n    None then \"nothing\"\n//│ fun f: (None | Some[Num]) -> (\"negative\" | \"nothing\" | \"positive\" | \"zero\")\n\nfun f(x, y) =\n  if x is\n    Some(x) and y is\n      Some(y) then 0\n//│ fun f: (Some[anything], Some[anything]) -> 0\n\nclass A[T](value: T)\nclass B[T](value: T)\n//│ class A[T](value: T)\n//│ class B[T](value: T)\n\nfun f(x, y, u, v) =\n  if x is\n    A(a) and y ==\n      u then 0\n      v then 1\n    A(a) and y is\n      B(0) then 0\n      B(1) then 1\n    A(_) then 99\n//│ fun f: (A[anything], Num, Num, Num) -> (0 | 1 | 99)\n\nfun f(x) =\n  if x is\n    A(_) then \"A\"\n    B(_) then \"B\"\n//│ fun f: (A[anything] | B[anything]) -> (\"A\" | \"B\")\n\n:e\nfun f(x, y) =\n  if x is\n    Some(xv) and y is Some(yv) then xv + yv\n    None and y is None then 0\n//│ ╔══[ERROR] when `x` is `Some`\n//│ ║  l.115: \t    Some(xv) and y is Some(yv) then xv + yv\n//│ ║         \t    ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.115: \t    Some(xv) and y is Some(yv) then xv + yv\n//│ ║         \t                 ^\n//│ ╟── it can be module `None`\n//│ ║  l.116: \t    None and y is None then 0\n//│ ╙──       \t                  ^^^^\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.116: \t    None and y is None then 0\n//│ ║         \t    ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.116: \t    None and y is None then 0\n//│ ║         \t             ^\n//│ ╟── it can be class `Some`\n//│ ║  l.115: \t    Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──       \t                      ^^^^\n//│ fun f: (None | Some[Int], nothing) -> Int\n\n:e\nfun f(x, y) =\n  if x is\n    Some(xv) and y is\n      Some(yv) then xv + yv\n      None then xv * 2\n    None and y is\n      Some(yv) then yv * 3\n//│ ╔══[ERROR] when `x` is `None`\n//│ ║  l.143: \t    None and y is\n//│ ║         \t    ^^^^\n//│ ╟── `y` has 1 missing case\n//│ ║  l.143: \t    None and y is\n//│ ║         \t             ^\n//│ ╟── it can be module `None`\n//│ ║  l.142: \t      None then xv * 2\n//│ ╙──       \t      ^^^^\n//│ fun f: (None | Some[Int], Some[Int]) -> Int\n\nfun f(x, y) =\n  if x is\n    A and y is\n      B then \"bruh\"\n//│ fun f: (A[anything], B[anything]) -> \"bruh\"\n\nfun f(x, y, z) =\n  if x is\n    A and z == 0 and y == 0 and y is\n      B then \"bruh\"\n    A then \"oui\"\n//│ fun f: (A[anything], Num, Num) -> (\"bruh\" | \"oui\")\n\n// We do need a syntax to specify default branch in IfOpsApp...\n:e\nfun f(x, y) =\n  if x is\n    Some(x) and y\n      >  0 then \"gt\"\n      <  0 then \"le\"\n      == 0 then \"eq\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.176: \t      == 0 then \"eq\"\n//│ ╙──       \t                ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.176: \t      == 0 then \"eq\"\n//│ ║         \t                ^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Some[anything], Num) -> (\"eq\" | \"gt\" | \"le\")\n\nfun isValid(x) = if x then false else true\n//│ fun isValid: Bool -> Bool\n\nfun f(x, allowNone) =\n  if x is\n    Some(x) and isValid(x) then \"good\"\n    None and allowNone then \"okay\"\n    else \"bad\"\n//│ fun f: (Object & ~#Some | Some[Bool], Bool) -> (\"bad\" | \"good\" | \"okay\")\n\nfun f(x) =\n  if x is\n    None then \"bruh\"\n    Some(x) then \"roll\"\n    _ and x == 0 then 0\n    _ then \"rock\"\n//│ fun f: (None | Num | Some[anything]) -> (\"bruh\" | \"rock\" | \"roll\" | 0)\n\nfun f(x, a, b) =\n  if x is\n    A(aa) and a then aa\n    B(bb) and b then bb\n    _           then 0\n//│ fun f: forall 'a. (A['a] | B['a] | Object & ~#A & ~#B, Bool, Bool) -> (0 | 'a)\n\nfun f(x, y, b) =\n  if x is\n    Some(xv) and y\n      is Some(yv) then \"bruh\"\n      is None then \"bruh\"\n    Some(xv) and b then xv + b\n    _ then \"roll\"\n//│ fun f: (Object & ~#Some | Some[Int], Object & ~#Some | Some[anything], nothing) -> (\"bruh\" | \"roll\" | Int)\n\nfun g(x, y, b) =\n  if x is\n    Some(xv) and y\n      is Some(yv) then yv\n      is None then \"bruh\"\n    Some(xv) and b then xv + b\n    _ then \"roll\"\n//│ fun g: forall 'a. (Object & ~#Some | Some[Int], Object & ~#Some | Some['a], nothing) -> (\"bruh\" | \"roll\" | Int | 'a)\n\nfun foo(x, y, z) =\n  if x - y > 0 then Some(x + y + z) else None\n//│ fun foo: forall 'A. (Int, Int, Int) -> (None | Some['A])\n//│   where\n//│     'A :> Int\n\n// Uncomment this block to make the following block work.\n// fun foo(x, y, z) =\n//   if x - y > 0 then Some(\n//     if x % 2 == 0 then Left(x) else Right(x)\n//   ) else None\n\n:e\nfun f(u, v, w) =\n  if foo(u, v, w) is\n    Some(x) and x is\n      Left(_) then \"left-defined\"\n      Right(_) then \"right-defined\"\n    None then \"undefined\"\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.244: \t    Some(x) and x is\n//│ ║         \t    ^^^^^^^^^^^^^^^^\n//│ ║  l.245: \t      Left(_) then \"left-defined\"\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.246: \t      Right(_) then \"right-defined\"\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.247: \t    None then \"undefined\"\n//│ ║         \t^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╟── operator application of type `Int` does not match type `Left[?A] | Right[?B]`\n//│ ║  l.230: \t  if x - y > 0 then Some(x + y + z) else None\n//│ ║         \t                         ^^^^^^^^^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.244: \t    Some(x) and x is\n//│ ║         \t                ^\n//│ ╟── from field selection:\n//│ ║  l.4: \tclass Some[A](value: A) extends Option[A]\n//│ ║       \t              ^^^^^\n//│ ╟── Note: type parameter A is defined at:\n//│ ║  l.4: \tclass Some[A](value: A) extends Option[A]\n//│ ╙──     \t           ^\n//│ fun f: (Int, Int, Int) -> (\"left-defined\" | \"right-defined\" | \"undefined\")\n\nfun p(x) = if x >= 0 then Right(x) else Left(x)\n//│ fun p: forall 'B 'A. (Num & 'B & 'A) -> (Left['A] | Right['B])\n\nfun g(a, b) =\n  if p(a) is\n    Left(x) and b is\n      Some(y) then x + y\n      None    then x * a\n    Right(x) and b is\n      Some(y) then x * y\n      None    then x\n//│ fun g: (Int, None | Some[Int]) -> Int\n\ng(5, None)\ng(5, Some(7))\ng(0 - 5, None)\ng(0 - 5, Some(9))\n//│ Int\n//│ res\n//│     = 5\n//│ res\n//│     = 35\n//│ res\n//│     = 25\n//│ res\n//│     = 4\n\nclass Var(name: Str)\nabstract class ValBase: (IntVal | BoolVal)\nclass IntVal(value: Int) extends ValBase\nclass BoolVal(value: Bool) extends ValBase\nclass Lit(value: ValBase)\n//│ class Var(name: Str)\n//│ abstract class ValBase: BoolVal | IntVal\n//│ class IntVal(value: Int) extends ValBase\n//│ class BoolVal(value: Bool) extends ValBase\n//│ class Lit(value: ValBase)\n\nfun p(e, context) =\n  if e is\n    Var(x) and context.get(x) is\n      Some(IntVal(v)) then Left(v)\n      Some(BoolVal(v)) then Right(v)\n    Lit(IntVal(v)) then Left(v)\n    Lit(BoolVal(v)) then Right(v)\n//│ fun p: forall 'A 'B. (Lit | Var, {get: Str -> Some[BoolVal | IntVal]}) -> (Left[in 'A out Int | 'A] | Right[in 'B out Bool | 'B])\n\nclass Nil()\n//│ class Nil()\n\n// Support operator constructor like ::\n:e\nfun f(x) =\n  if x is\n    0 ::\n      Nil() then \"oh\"\n//│ ╔══[ERROR] Syntactic split of patterns are not supported\n//│ ║  l.325: \t    0 ::\n//│ ╙──       \t      ^^\n//│ fun f: anything -> nothing\n\nfun f(x) =\n  if x == 0 and x is\n    A(_) then \"A\"\n    B(_) then \"B\"\n  else \"bruh\"\n//│ fun f: Num -> (\"A\" | \"B\" | \"bruh\")\n\nfun helper(x) =\n  if x == 0 then None else Some(x)\n//│ fun helper: forall 'A. (Num & 'A) -> (None | Some['A])\n\nfun g(x, y) =\n  if x == 0 and helper(x) is\n    Some(a) and helper(y) is\n      Some(b) then a + b\n      None then a + 1\n    None and helper(y) is\n      Some(b) then 2 + b\n      None then 1\n  else\n    0\n//│ fun g: (Int, Int) -> Int\n\n\nfun test(x) = if x then 0 else \"oops\"\n//│ fun test: Bool -> (\"oops\" | 0)\n\ntest(true)\ntest(false)\n//│ \"oops\" | 0\n//│ res\n//│     = 0\n//│ res\n//│     = 'oops'\n\n:e\ntest(0)\ntest(1)\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.368: \ttest(0)\n//│ ║         \t^^^^^^^\n//│ ╟── integer literal of type `0` is not an instance of type `Bool`\n//│ ║  l.368: \ttest(0)\n//│ ║         \t     ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.356: \tfun test(x) = if x then 0 else \"oops\"\n//│ ╙──       \t                 ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.369: \ttest(1)\n//│ ║         \t^^^^^^^\n//│ ╟── integer literal of type `1` is not an instance of type `Bool`\n//│ ║  l.369: \ttest(1)\n//│ ║         \t     ^\n//│ ╟── Note: constraint arises from reference:\n//│ ║  l.356: \tfun test(x) = if x then 0 else \"oops\"\n//│ ╙──       \t                 ^\n//│ \"oops\" | 0 | error\n//│ res\n//│     = 'oops'\n//│ res\n//│     = 'oops'\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/SplitAfterOp.mls",
    "content": ":NewDefs\n\n:e\nfun f(x, b) =\n  if x == \n    0 and b then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t    0 and b then 0\n//│ ╙──     \t          ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t    0 and b then 0\n//│ ║       \t                 ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t    0 and b then 0\n//│ ║       \t          ^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Bool) -> 0\n\n:e\nfun f(x, y) =\n  if x == y +\n    5 then 0\n    7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.24: \t    7 then 0\n//│ ╙──      \t           ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.22: \t  if x == y +\n//│ ║        \t            ^\n//│ ║  l.23: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.22: \t  if x == y +\n//│ ╙──      \t     ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.22: \t  if x == y +\n//│ ║        \t            ^\n//│ ║  l.23: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.22: \t  if x == y +\n//│ ║        \t            ^\n//│ ║  l.23: \t    5 then 0\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.24: \t    7 then 0\n//│ ║        \t^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.24: \t    7 then 0\n//│ ║        \t           ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> 0\n\n:e\nfun f(x, y) =\n  if x == y *\n    5 then 0\n    6 + 7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ╙──      \t               ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.58: \t  if x == y *\n//│ ╙──      \t     ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ║        \t^^^^^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.58: \t  if x == y *\n//│ ╙──      \t     ^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.58: \t  if x == y *\n//│ ║        \t            ^\n//│ ║  l.59: \t    5 then 0\n//│ ║        \t^^^^^^^^^^^^^\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ║        \t^^^^^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.60: \t    6 + 7 then 0\n//│ ║        \t               ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> 0\n\n:e\nfun f(x, y) =\n  if x ==\n    y +\n      5 then 0\n      7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.107: \t      7 then 0\n//│ ╙──       \t             ^\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.105: \t    y +\n//│ ║         \t      ^\n//│ ║  l.106: \t      5 then 0\n//│ ║         \t^^^^^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.104: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.105: \t    y +\n//│ ╙──       \t^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.105: \t    y +\n//│ ║         \t      ^\n//│ ║  l.106: \t      5 then 0\n//│ ║         \t^^^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.105: \t    y +\n//│ ║         \t      ^\n//│ ║  l.106: \t      5 then 0\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.107: \t      7 then 0\n//│ ║         \t^^^^^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.107: \t      7 then 0\n//│ ║         \t             ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> 0\n\n:e\nfun f(x, b) =\n  if x ==\n    1 and b then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.144: \t    1 and b then 0\n//│ ╙──       \t          ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.144: \t    1 and b then 0\n//│ ║         \t                 ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.144: \t    1 and b then 0\n//│ ║         \t          ^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Bool) -> 0\n\n\n:e\nfun toEnglish(x) =\n  if x ==\n    true then \"t\"\n    0 then \"z\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.163: \t    0 then \"z\"\n//│ ╙──       \t           ^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.161: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.162: \t    true then \"t\"\n//│ ║         \t^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Num`\n//│ ║  l.162: \t    true then \"t\"\n//│ ╙──       \t    ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.163: \t    0 then \"z\"\n//│ ║         \t           ^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> (\"t\" | \"z\")\n\n:e\nfun toEnglish(x) =\n  if x ==\n    0 then \"z\"\n    true then \"t\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.185: \t    true then \"t\"\n//│ ╙──       \t              ^^^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.183: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.184: \t    0 then \"z\"\n//│ ║         \t^^^^^^^^^^^^^^\n//│ ║  l.185: \t    true then \"t\"\n//│ ║         \t^^^^^^^^\n//│ ╟── reference of type `true` is not an instance of `Num`\n//│ ║  l.185: \t    true then \"t\"\n//│ ╙──       \t    ^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.185: \t    true then \"t\"\n//│ ║         \t              ^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> (\"t\" | \"z\")\n\n:e\nfun toEnglish(x) =\n  if x ==\n    1 then \"o\"\n    0 then \"z\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.209: \t    0 then \"z\"\n//│ ╙──       \t           ^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.209: \t    0 then \"z\"\n//│ ║         \t           ^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> (\"o\" | \"z\")\n\nfun toEnglish(x) =\n  if x ==\n    0 then 1\n    else 1\n//│ fun toEnglish: Num -> 1\n\n:pe\n:e\nfun toEnglish(x) =\n  if x ==\n    else 1\n//│ ╔══[PARSE ERROR] Unexpected indented block in expression position\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t^^^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t    ^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.228: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.229: \t    else 1\n//│ ║         \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.228: \t  if x ==\n//│ ╙──       \t  ^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t    ^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.228: \t  if x ==\n//│ ║         \t     ^^^^\n//│ ║  l.229: \t    else 1\n//│ ║         \t^^^^\n//│ ╟── undefined literal of type `()` is not an instance of type `Num`\n//│ ║  l.229: \t    else 1\n//│ ╙──       \t    ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.229: \t    else 1\n//│ ║         \t    ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun toEnglish: Num -> ()\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/SplitAnd.mls",
    "content": ":NewDefs\n\nfun f(x, y) =\n  if x == 0 and\n    y == 0 then \"bruh\"\n    y == 1 then \"lol\"\n  else \"okay\"\n//│ fun f: (Num, Num) -> (\"bruh\" | \"lol\" | \"okay\")\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\n:e\nfun f(x) =\n  if x == 0 and\n    x is\n      A() then \"A\"\n      B() then \"B\"\n    x == 0 then \"lol\"\n    else \"bruh\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.18: \t    x is\n//│ ║        \t    ^^^^\n//│ ║  l.19: \t      A() then \"A\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.20: \t      B() then \"B\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.21: \t    x == 0 then \"lol\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.22: \t    else \"bruh\"\n//│ ╙──      \t^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.18: \t    x is\n//│ ║        \t    ^^^^\n//│ ║  l.19: \t      A() then \"A\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.20: \t      B() then \"B\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^\n//│ ║  l.21: \t    x == 0 then \"lol\"\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.22: \t    else \"bruh\"\n//│ ║        \t^^^^^^^^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: Num -> (\"A\" | \"B\" | \"bruh\" | \"lol\")\n\n:e\nfun f(x, y) =\n  if\n    x == 0 and\n      y == 0 then \"bruh\"\n      else \"lol\"\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.52: \t      y == 0 then \"bruh\"\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^\n//│ ║  l.53: \t      else \"lol\"\n//│ ╙──      \t^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.52: \t      y == 0 then \"bruh\"\n//│ ║        \t      ^^^^^^^^^^^^^^^^^^\n//│ ║  l.53: \t      else \"lol\"\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Num) -> (\"bruh\" | \"lol\")\n"
  },
  {
    "path": "shared/src/test/diff/ucs/SplitAroundOp.mls",
    "content": ":NewDefs\n\nfun f(x, b) =\n  if x\n    ===\n      0 and b then \"n0\"\n      1 and b then \"n1\"\n      2 then \"n2\"\n    ===\n      \"0\" then \"s0\"\n      \"1\" then \"s1\"\n      \"2\" then \"s2\"\n  else \":p\"  \n//│ fun f: (Eql[\"0\" | \"1\" | \"2\" | 0 | 1 | 2], Bool) -> (\":p\" | \"n0\" | \"n1\" | \"n2\" | \"s0\" | \"s1\" | \"s2\")\n\nfun f(x, y, a, b) =\n  if x === 0\n    and\n      y === 0 then \"x, y\"\n      a === 0 then \"x, a\"\n      b === 0 then \"x, b\"\n  else \"nah\"\n//│ fun f: (Eql[0], Eql[0], Eql[0], Eql[0]) -> (\"nah\" | \"x, a\" | \"x, b\" | \"x, y\")\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nfun f(x) =\n  if x\n    is\n      A() then 0\n      B() then 1\n//│ fun f: (A | B) -> (0 | 1)\n\n:e // FIXME\nif x is\n  A()\n    === 0 then 0\n    > 0 then 1\n    < 0 then 2\n//│ ╔══[ERROR] cannot transform due to an illegal split operator ===\n//│ ║  l.40: \t    === 0 then 0\n//│ ║        \t    ^^^\n//│ ╟── the following branch will be discarded\n//│ ║  l.40: \t    === 0 then 0\n//│ ╙──      \t        ^^^^^^^^\n//│ ╔══[ERROR] cannot transform due to an illegal split operator >\n//│ ║  l.41: \t    > 0 then 1\n//│ ║        \t    ^\n//│ ╟── the following branch will be discarded\n//│ ║  l.41: \t    > 0 then 1\n//│ ╙──      \t      ^^^^^^^^\n//│ ╔══[ERROR] cannot transform due to an illegal split operator <\n//│ ║  l.42: \t    < 0 then 2\n//│ ║        \t    ^\n//│ ╟── the following branch will be discarded\n//│ ║  l.42: \t    < 0 then 2\n//│ ╙──      \t      ^^^^^^^^\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.38: \tif x is\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.38: \tif x is\n//│ ╙──      \t   ^\n//│ nothing\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n"
  },
  {
    "path": "shared/src/test/diff/ucs/SplitBeforeOp.mls",
    "content": ":NewDefs\n\n:e\n:ge\nif x\n  == 0 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t  == 0 then 0\n//│ ╙──     \t            ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.5: \tif x\n//│ ╙──     \t   ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t  == 0 then 0\n//│ ║       \t            ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ 0\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\n:ge\nif x\n  is A and\n    y then 0\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.23: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.24: \t  is A and\n//│ ╙──      \t     ^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.25: \t    y then 0\n//│ ╙──      \t           ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.23: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.24: \t  is A and\n//│ ╙──      \t     ^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\n:ge\nif x\n  is A and\n    y then 0\nelse 1\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.47: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.48: \t  is A and\n//│ ╙──      \t     ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.47: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.48: \t  is A and\n//│ ╙──      \t     ^\n//│ error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n\n:e\n:ge\nif x\n  == 0 then 0\n  is\n    A() then \"A\"\n    B() then \"B\"\n//│ ╔══[ERROR] identifier `x` not found\n//│ ║  l.69: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier `A` not found\n//│ ║  l.72: \t    A() then \"A\"\n//│ ╙──      \t    ^\n//│ ╔══[ERROR] type identifier `B` not found\n//│ ║  l.73: \t    B() then \"B\"\n//│ ╙──      \t    ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.69: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] identifier not found: x\n//│ ║  l.69: \tif x\n//│ ╙──      \t   ^\n//│ ╔══[ERROR] type identifier not found: A\n//│ ║  l.72: \t    A() then \"A\"\n//│ ╙──      \t    ^\n//│ 0 | error\n//│ Code generation encountered an error:\n//│   unresolved symbol x\n"
  },
  {
    "path": "shared/src/test/diff/ucs/SplitOps.mls",
    "content": ":NewDefs\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nabstract class Either[out A, out B]: Left[A] | Right[B]\nclass Left[A](leftValue: A) extends Either[A, nothing]\nclass Right[B](rightValue: B) extends Either[nothing, B]\n//│ abstract class Either[A, B]: Left[A] | Right[B]\n//│ class Left[A](leftValue: A) extends Either\n//│ class Right[B](rightValue: B) extends Either\n\n:e\n:ge\nfun f(x) =\n  if x\n    is Left(v) then 0\n    is Right(v) then 1\n    <> undefined then 2\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.23: \t    <> undefined then 2\n//│ ╙──      \t                      ^\n//│ ╔══[ERROR] Type mismatch in operator application:\n//│ ║  l.20: \t  if x\n//│ ║        \t     ^\n//│ ║  l.21: \t    is Left(v) then 0\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.22: \t    is Right(v) then 1\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.23: \t    <> undefined then 2\n//│ ║        \t^^^^^^^^^^^^^^^^\n//│ ╟── undefined literal of type `()` is not an instance of type `Num`\n//│ ║  l.23: \t    <> undefined then 2\n//│ ╙──      \t       ^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.23: \t    <> undefined then 2\n//│ ║        \t                      ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Left[anything] | Num | Right[anything]) -> (0 | 1 | 2)\n//│ Code generation encountered an error:\n//│   unresolved symbol <>\n\n:e\n:ge\nfun f(x) =\n  if x\n    is Some(xv) and y is Some(yv) then xv + yv\n    is None() and y is None() then 0\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.51: \t    is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──      \t                    ^\n//│ ╔══[ERROR] identifier `y` not found\n//│ ║  l.52: \t    is None() and y is None() then 0\n//│ ╙──      \t                  ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.51: \t    is Some(xv) and y is Some(yv) then xv + yv\n//│ ╙──      \t                    ^\n//│ ╔══[ERROR] identifier not found: y\n//│ ║  l.52: \t    is None() and y is None() then 0\n//│ ╙──      \t                  ^\n//│ fun f: (None | Some[Int]) -> Int\n//│ Code generation encountered an error:\n//│   unresolved symbol y\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nfun f(a, b) =\n  if a\n    is A() and b is B() then 0\n//│ fun f: (A, B) -> 0\n\nclass C()\n//│ class C()\n\n:e\nfun f(a, b, c) =\n  if a\n    == 0 and b is B() and c is C() then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.85: \t    == 0 and b is B() and c is C() then 0\n//│ ╙──      \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.85: \t    == 0 and b is B() and c is C() then 0\n//│ ║        \t             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, B, C) -> 0\n\nfun f(x) =\n  if x\n    is A() then \"A\"\n    is B() then \"B\"\n//│ fun f: (A | B) -> (\"A\" | \"B\")\n\nfun sumOpt(x, y) =\n  if x\n    is Some(xv) and y is\n      Some(yv) then xv + yv\n      None() then xv\n    is None() and y is\n      Some(yv) then yv\n      None() then 0\n//│ fun sumOpt: forall 'a. (None | Some[Int], None | Some[Int & 'a]) -> (Int | 'a)\n\nfun f(x, y, z) =\n  if x is A() and y\n    == z then 1\n    is B() then 0\n//│ fun f: (A, nothing, Num) -> (0 | 1)\n"
  },
  {
    "path": "shared/src/test/diff/ucs/SplitScrutinee.mls",
    "content": ":NewDefs\n\nfun f(x) =\n  if x +\n    1 is\n      2 then 1\n      3 then 2\n      _ then \"I don't know.\"\n//│ fun f: Int -> (\"I don't know.\" | 1 | 2)\n\n[f(0), f(1), f(2), f(3)]\n//│ [\"I don't know.\" | 1 | 2, \"I don't know.\" | 1 | 2, \"I don't know.\" | 1 | 2, \"I don't know.\" | 1 | 2]\n//│ res\n//│     = [ \"I don't know.\", 1, 2, \"I don't know.\" ]\n"
  },
  {
    "path": "shared/src/test/diff/ucs/ThenIndent.mls",
    "content": ":NewDefs\n\n\n// FIXME\nx => if x ==\n  0\n    then \"a\"\n  _ then \"b\"\n//│ ╔══[PARSE ERROR] Unexpected indented block here\n//│ ║  l.7: \t    then \"a\"\n//│ ║       \t^^^^^^^^^^^^\n//│ ║  l.8: \t  _ then \"b\"\n//│ ╙──     \t^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.5: \tx => if x ==\n//│ ║       \t        ^^^^\n//│ ║  l.6: \t  0\n//│ ║       \t^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.5: \tx => if x ==\n//│ ╙──     \t     ^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.6: \t  0\n//│ ╙──     \t  ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.6: \t  0\n//│ ║       \t  ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ Num -> ()\n//│ res\n//│     = [Function: res]\n\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/Tree.mls",
    "content": ":NewDefs\n\ntype Option[out A] = Some[A] | None\nclass Some[out A](value: A)\nmodule None\n//│ type Option[A] = None | Some[A]\n//│ class Some[A](value: A)\n//│ module None\n\ntype Tree[out A] = Node[A] | Empty\nmodule Empty\nclass Node[out A](value: A, left: Tree[A], right: Tree[A])\n//│ type Tree[A] = Empty | Node[A]\n//│ module Empty\n//│ class Node[A](value: A, left: Tree[A], right: Tree[A])\n\nfun find(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then find(l, v)\n    v > v' then find(r, v)\n    _ then Some(v)\n  Empty then None\n//│ fun find: forall 'A. (Empty | Node[Num], Num & 'A) -> (None | Some['A])\n\nfun insert(t, v) = if t is\n  Node(v', l, r) and\n    v < v' then Node(v', insert(l, v), r)\n    v > v' then Node(v', l, insert(r, v))\n    _ then t\n  Empty then Node(v, Empty, Empty)\n//│ fun insert: forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A])\n\nfind(Empty, 0)\nfind(Node(0, Empty, Empty), 0)\nfind(Node(1, Empty, Empty), 0)\n//│ None | Some[0]\n//│ res\n//│     = None { class: [class None] }\n//│ res\n//│     = Some {}\n//│ res\n//│     = None { class: [class None] }\n"
  },
  {
    "path": "shared/src/test/diff/ucs/TrivialIf.mls",
    "content": ":NewDefs\n:NoJS\n\nfun abs(x) = if x < 0 then 0 - x else x\n//│ fun abs: Int -> Int\n\nabstract class Option[A]: Some[A] | None\nclass Some[A](value: A) extends Option[A]\nmodule None extends Option\n//│ abstract class Option[A]: None | Some[A]\n//│ class Some[A](value: A) extends Option\n//│ module None extends Option\n\nfun getOrElse(opt, default) =\n  if opt is\n    Some(value) then value\n    None then default\n//│ fun getOrElse: forall 'a. (None | Some['a], 'a) -> 'a\n\ngetOrElse(None, 0)\n//│ 0\n\ngetOrElse(Some(42), 0)\n//│ 0 | 42\n\nfun map(v, f) =\n  if v is\n    Some(x) then Some(f(x))\n    None then None\n//│ fun map: forall 'a 'A. (None | Some['a], 'a -> 'A) -> (None | Some['A])\n\nfun inc(x) = x + 5\n//│ fun inc: Int -> Int\n\nmap(Some(5), x => x + 5)\n//│ None | Some['A]\n//│   where\n//│     'A :> Int\n\nmap(None, inc)\n//│ None | Some['A]\n//│   where\n//│     'A :> Int\n\n:e\nfun f(a, b) = if a and b then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.46: \tfun f(a, b) = if a and b then 0\n//│ ╙──      \t                       ^^^^^^^^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.46: \tfun f(a, b) = if a and b then 0\n//│ ║        \t                              ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.46: \tfun f(a, b) = if a and b then 0\n//│ ║        \t                       ^^^^^^^^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Bool, Bool) -> 0\n\n:e\nfun f(x, y) =\n  if x == y + 5 then 0\n  else if x == y + 7 then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.63: \t  else if x == y + 7 then 0\n//│ ╙──      \t                          ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.63: \t  else if x == y + 7 then 0\n//│ ║        \t                          ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: (Num, Int) -> 0\n\n// TODO support\nfun foo(x) = if x is Some\n  (0) then 0\n  (1) then 1\n//│ ╔══[PARSE ERROR] Unexpected parenthesis section here\n//│ ║  l.76: \t  (1) then 1\n//│ ╙──      \t  ^^^\n//│ /!!!\\ Uncaught error: java.lang.StackOverflowError\n\n// TODO support\nfun foo(x) = if x is Some of\n  0 then 0\n  1 then 1\n//│ ╔══[PARSE ERROR] Unexpected 'then' keyword here\n//│ ║  l.84: \t  0 then 0\n//│ ╙──      \t    ^^^^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.83: \tfun foo(x) = if x is Some of\n//│ ║        \t                ^^^^^^^^^^^^\n//│ ║  l.84: \t  0 then 0\n//│ ║        \t^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.83: \tfun foo(x) = if x is Some of\n//│ ╙──      \t             ^^\n//│ fun foo: Some[0] -> ()\n\n"
  },
  {
    "path": "shared/src/test/diff/ucs/WeirdIf.mls",
    "content": ":NewDefs\n\n:w\nif\n  _ then 0\n  else 0\nelse 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.6: \t  else 0\n//│ ║       \t       ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.5: \t  _ then 0\n//│ ╙──     \t         ^\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.7: \telse 1\n//│ ║       \t     ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.5: \t  _ then 0\n//│ ╙──     \t         ^\n//│ 0\n//│ res\n//│     = 0\n\n:w\nif else 0 else 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.25: \tif else 0 else 1\n//│ ║        \t               ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.25: \tif else 0 else 1\n//│ ╙──      \t        ^\n//│ 0\n//│ res\n//│     = 0\n\n:w\nfun f(x) = if x is else 0 else 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.37: \tfun f(x) = if x is else 0 else 1\n//│ ║        \t                               ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.37: \tfun f(x) = if x is else 0 else 1\n//│ ╙──      \t                        ^\n//│ fun f: anything -> 0\n\nfun f(x) = if x is else 0 \n//│ fun f: anything -> 0\n\n:e\nif true\n  then 0\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.51: \t  then 0\n//│ ╙──      \t       ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.51: \t  then 0\n//│ ║        \t       ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ 0\n//│ res\n//│     = 0\n\n// This cannot be parsed. But the next one works.\n:pe\n:e\nfun f(x) =\n  if x ===\n    else \"bruh\"\n//│ ╔══[PARSE ERROR] Unexpected indented block in expression position\n//│ ║  l.68: \t    else \"bruh\"\n//│ ╙──      \t^^^^\n//│ ╔══[PARSE ERROR] Unexpected end of indented block; an expression was expected here\n//│ ║  l.68: \t    else \"bruh\"\n//│ ╙──      \t    ^\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application instead\n//│ ║  l.67: \t  if x ===\n//│ ║        \t     ^^^^^\n//│ ║  l.68: \t    else \"bruh\"\n//│ ║        \t^^^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.67: \t  if x ===\n//│ ╙──      \t  ^^\n//│ ╔══[ERROR] missing else branch\n//│ ║  l.68: \t    else \"bruh\"\n//│ ╙──      \t    ^\n//│ ╔══[ERROR] Type mismatch in `case` expression:\n//│ ║  l.68: \t    else \"bruh\"\n//│ ║        \t    ^\n//│ ╙── expression of type `Bool` is not an instance of type `true`\n//│ fun f: Eql[()] -> ()\n\n// But this works.\nfun f(x) =\n  if x ===\n    _ then \"bruh\"\n//│ fun f: anything -> \"bruh\"\n\nfun boolToStr(x) =\n  if x is\n    true then \"yah\"\n    false then \"nah\"\n//│ fun boolToStr: Bool -> (\"nah\" | \"yah\")\n\nboolToStr of true\nboolToStr of false\n//│ \"nah\" | \"yah\"\n//│ res\n//│     = 'yah'\n//│ res\n//│     = 'nah'\n"
  },
  {
    "path": "shared/src/test/diff/ucs/WeirdSplit.mls",
    "content": ":NewDefs\n\nclass A()\nclass B()\n//│ class A()\n//│ class B()\n\nfun f(x) =\n  if x\n    is\n      A then 0\n      B then 1\n//│ fun f: (A | B) -> (0 | 1)\n\n// Precedence problem: should we restruct terms when push them to the stack?\n:e\nfun f(x) =\n  if x ==\n    1\n      + 2 then 0\n      + _ then 1\n//│ ╔══[ERROR] Type mismatch in application:\n//│ ║  l.20: \t      + 2 then 0\n//│ ║        \t      ^^^\n//│ ╟── operator application of type `Bool` is not an instance of type `Int`\n//│ ║  l.18: \t  if x ==\n//│ ║        \t     ^^^^\n//│ ║  l.19: \t    1\n//│ ╙──      \t^^^^^^\n//│ ╔══[ERROR] Type mismatch in type ascription:\n//│ ║  l.20: \t      + 2 then 0\n//│ ║        \t      ^^^\n//│ ╙── application of type `Int` is not an instance of type `Bool`\n//│ fun f: Num -> (0 | 1)\n\nfun f(x, s, t) =\n  if x\n    is A()\n      and t then 0\n      and s then 0\n    is _ then 1\n//│ fun f: (Object, Bool, Bool) -> (0 | 1)\n"
  },
  {
    "path": "shared/src/test/diff/ucs/Wildcard.mls",
    "content": ":NewDefs\n\nfun (++) strcat(a, b) = concat(a)(b)\n//│ fun (++) strcat: (Str, Str) -> Str\n\ntype Option[T] = None | Some[T]\nmodule None\nclass Some[T](val value: T)\n//│ type Option[T] = None | Some[T]\n//│ module None\n//│ class Some[T](value: T)\n\ntype Either[A, B] = Left[A] | Right[B]\nclass Left[A](val leftValue: A)\nclass Right[B](val rightValue: B)\n//│ type Either[A, B] = Left[A] | Right[B]\n//│ class Left[A](leftValue: A)\n//│ class Right[B](rightValue: B)\n\n\nfun w1(x, e_0, e_1) =\n  if x is\n    Left(None) then \"Left of None\"\n    Right(None) then \"Right of None\"\n    _ and e_0 is y_0 and x is\n      Left(Some(lv)) then \"Left of Some of \" ++ toString(lv)\n      _ and e_1 is y_1 and x is\n        Right(Some(rv)) then \"Right of Some of \" ++ toString(rv)\n//│ fun w1: forall 'a. (Left[None | Object & ~#None & ~#Some | Some[anything]] | Object & ~#Left & ~#Right | Right[None | Some[anything]], anything, 'a) -> (Str | 'a)\n\nw1(Left(None), \"a\", \"b\")\nw1(Right(None), \"a\", \"b\")\nw1(Left(Some(0)), \"a\", \"b\")\nw1(Right(Some(0)), \"a\", \"b\")\n//│ Str\n//│ res\n//│     = 'Left of None'\n//│ res\n//│     = 'Right of None'\n//│ res\n//│     = 'Left of Some of 0'\n//│ res\n//│     = 'Right of Some of 0'\n\n//  Should be\n//  case x of\n//    Some -> 1\n//    None ->\n//      case p(x) of\n//        true -> 2\n//        _ -> 4\n//    _ ->\n//      case p(x) of\n//        true -> 3\n//        _ -> 5\n:ducs:normalize.result,postprocess.result\nfun w2(x, p) =\n  if x is\n    Some then 1\n    _ and p(x) and\n      x is None then 2\n      _ then 3\n    None then 4\n    _ then 5\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† ->\n//│         case x*‡ of\n//│           None*† -> 2\n//│           _ -> 3\n//│       _ ->\n//│         case x*‡ of\n//│           None*† -> 4\n//│           _ -> 5\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   None*† ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 2\n//│       _ -> 4\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 3\n//│       _ -> 5\n//│ fun w2: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], (None | 'a) -> Bool) -> (1 | 2 | 3 | 4 | 5)\n\n//  Should be\n//  case x of\n//    Some -> 1\n//    None ->\n//      case p(x) of\n//        true -> 2\n//        _ -> 3\n//    _ ->\n//      case p(x) of\n//        true -> 2\n//        _ -> 4\n:ducs:normalize.result,postprocess.result\nfun w2(x, p) =\n  if x is\n    Some then 1\n    _ and p(x) then 2\n    None then 3\n    _ then 4\n//│ Normalized UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true*† -> 2\n//│       _ ->\n//│         case x*‡ of\n//│           None*† -> 3\n//│           _ -> 4\n//│ Post-processed UCS term:\n//│ case x*‡ of\n//│   Some*◊ -> 1\n//│   None*† ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 2\n//│       _ -> 3\n//│   _ ->\n//│     let ucs$test$0*† = p(x,) : Bool\n//│     case ucs$test$0*† of\n//│       true -> 2\n//│       _ -> 4\n//│ fun w2: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], (None | 'a) -> Bool) -> (1 | 2 | 3 | 4)\n\nw2(Some(0), x => true)\nw2(None, x => true)\nw2(None, x => false)\nw2(0, x => false)\n//│ 1 | 2 | 3 | 4\n//│ res\n//│     = 1\n//│ res\n//│     = 2\n//│ res\n//│     = 3\n//│ res\n//│     = 4\n\nfun w3(x, p) = if x is\n  _ and p(x) then \"r1\"\n  Some(xv) then \"r2: \" ++ toString(xv)\n  None then \"r3\"\n  _ then \"r4\"\n//│ fun w3: forall 'a. ('a & (Object & ~#Some | Some[anything]), 'a -> Bool) -> Str\n\n// Expect \"r1\"\nw3(0, _ => true)\nw3(None, _ => true)\nw3(Some(0), _ => true)\n//│ Str\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n\n// Expect \"r2\"\nw3(Some(0), _ => false)\n//│ Str\n//│ res\n//│     = 'r2: 0'\n\n// Expect \"r3\"\nw3(None, _ => false)\n//│ Str\n//│ res\n//│     = 'r3'\n\n// Expect \"r4\"\nw3(0, _ => false)\n//│ Str\n//│ res\n//│     = 'r4'\n\n:w\n// Decision paths:\n// + «tmp2 @ f (x,) is any => 0\n// +  => 1\nfun w3_1(x, f) =\n  if f(x) is _ then 0 else 1\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.194: \t  if f(x) is _ then 0 else 1\n//│ ║         \t                           ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.194: \t  if f(x) is _ then 0 else 1\n//│ ╙──       \t                    ^\n//│ fun w3_1: forall 'a. ('a, 'a -> anything) -> 0\n\nw3_1(0, _ => true)\nw3_1(0, _ => false)\n//│ 0\n//│ res\n//│     = 0\n//│ res\n//│     = 0\n\n:w\nfun w3_1_1(x, f) =\n  if f(x) is a then a else 0\n//│ ╔══[WARNING] this case is unreachable\n//│ ║  l.213: \t  if f(x) is a then a else 0\n//│ ║         \t                           ^\n//│ ╟── because it is subsumed by the branch\n//│ ║  l.213: \t  if f(x) is a then a else 0\n//│ ╙──       \t                    ^\n//│ fun w3_1_1: forall 'a 'b. ('a, 'a -> 'b) -> 'b\n\nw3_1_1(0, x => x)\nw3_1_1(0, x => x + 1)\n//│ Int\n//│ res\n//│     = 0\n//│ res\n//│     = 1\n\n// Decision paths:\n// + «a = x» and «p (x,)» => \"r1\"\n// + «x is Some» => concat (\"r2: \",) (toString (xv,),)\n// + «x is None» => \"r3\"\nfun w4(x, p) = if x is\n  a and p(x) then \"r1\"\n  Some(xv) then \"r2: \" ++ toString(xv)\n  None then \"r3\"\n  _ then \"r4\"\n//│ fun w4: forall 'a. ('a & (Object & ~#Some | Some[anything]), 'a -> Bool) -> Str\n\n\n// Expect \"r1\"\nw4(0, _ => true)\nw4(None, _ => true)\nw4(Some(0), _ => true)\n//│ Str\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n//│ res\n//│     = 'r1'\n\n// Expect \"r2\"\nw4(Some(0), _ => false)\n//│ Str\n//│ res\n//│     = 'r2: 0'\n\n// Expect \"r3\"\nw4(None, _ => false)\n//│ Str\n//│ res\n//│     = 'r3'\n\n// Expect \"r4\"\nw4(0, _ => false)\n//│ Str\n//│ res\n//│     = 'r4'\n\nclass Alpha()\nclass Beta()\nclass Gamma()\nclass Delta()\n//│ class Alpha()\n//│ class Beta()\n//│ class Gamma()\n//│ class Delta()\n\n// This should generate only one case expression instead of a chain of case\n// expressions. DO check the desugared term!\n:ducs:postprocess.result\nfun w5(y) =\n  if y is\n    Alpha then \"alpha\"\n    _ and y is\n      Beta then \"beta\"\n      _ and y is\n        Gamma then \"gamma\"\n        _ and y is\n          Delta then \"delta\"\n          _ then \"unknown\"\n//│ Post-processed UCS term:\n//│ case y*‡ of\n//│   Alpha*◊ -> \"alpha\"\n//│   Gamma*◊ -> \"gamma\"\n//│   Delta*◊ -> \"delta\"\n//│   Beta*◊ -> \"beta\"\n//│   _ -> \"unknown\"\n//│ fun w5: Object -> (\"alpha\" | \"beta\" | \"delta\" | \"gamma\" | \"unknown\")\n\nw5(0)\nw5(Alpha())\nw5(Beta())\nw5(Gamma())\nw5(Delta())\n//│ \"alpha\" | \"beta\" | \"delta\" | \"gamma\" | \"unknown\"\n//│ res\n//│     = 'unknown'\n//│ res\n//│     = 'alpha'\n//│ res\n//│     = 'beta'\n//│ res\n//│     = 'gamma'\n//│ res\n//│     = 'delta'\n\nfun w6(x, y) =\n  if x is\n    _ and y is\n      Some(z) then z\n      None then 0\n    else x\n//│ fun w6: forall 'a. ('a, Object & ~#Some | Some['a]) -> (0 | 'a)\n\nw6(\"42\", Some(42))\nw6(\"42\", None)\nw6(\"42\", \"42\")\n//│ \"42\" | 0\n//│ res\n//│     = 42\n//│ res\n//│     = 0\n//│ res\n//│     = '42'\n\n\nfun w7(x, f) =\n  if x is\n    _ and f(x) is\n      Some(v) then v\n      None then x\n    Left(x) then x + 1\n    Right(x) then x + 2\n//│ fun w7: forall 'a 'b. ('a & (Left[Int] | Right[Int]), 'a -> (Object & ~#Some | Some['b])) -> (Int | 'b | 'a)\n\n// The results are wrong:\nw7(Left(99), _ => Some(0)) // => 0\nw7(Left(99), _ => None) // => Left(99)\nw7(Right(99), _ => Some(0)) // => 0\nw7(Right(99), _ => None) // => Right(99)\n//│ Int | Right['B]\n//│   where\n//│     'B :> 99\n//│        <: Int\n//│ res\n//│     = 0\n//│ res\n//│     = Left {}\n//│ res\n//│     = 0\n//│ res\n//│     = Right {}\n\nw7(Left(99), _ => \"test\")\nw7(Right(99), _ => \"test\")\n//│ Int | Right['B]\n//│   where\n//│     'B :> 99\n//│        <: Int\n//│ res\n//│     = 100\n//│ res\n//│     = 101\n"
  },
  {
    "path": "shared/src/test/diff/ucs/zipWith.mls",
    "content": ":NewDefs\n\n\n\ndeclare val nothing: nothing\n//│ val nothing: nothing\n//│ nothing\n//│         = <missing implementation>\n\nmodule None {\n  fun value = nothing\n}\nclass Some[out A](val value: A)\n//│ module None {\n//│   fun value: nothing\n//│ }\n//│ class Some[A](value: A)\n\ntype List[out A] = Cons[A] | Nil\nmodule Nil {\n  fun toArray = []\n}\nclass Cons[out A](val head: A, val tail: List[A]) {\n  fun toArray: Array[anything]\n  fun toArray = [head, tail.toArray]\n}\n//│ type List[A] = Cons[A] | Nil\n//│ module Nil {\n//│   fun toArray: []\n//│ }\n//│ class Cons[A](head: A, tail: List[A]) {\n//│   fun toArray: Array[anything]\n//│ }\n\nfun pairup(x, y) = [x, y]\n//│ fun pairup: forall 'a 'b. ('a, 'b) -> ['a, 'b]\n\n\n\n// FIXME parsing\nfun zipWith_wrong(f, xs, ys) =\n  if  xs is Cons(x, xs)\n  and ys is Cons(y, ys)\n  and zipWith_wrong(f, xs, ys) is Some(tail)\n  then Some(Cons(f(x, y), tail))\n  else None\n//│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'if'; found operator application followed by newline instead\n//│ ║  l.42: \t  if  xs is Cons(x, xs)\n//│ ║        \t      ^^^^^^^^^^^^^^^^^\n//│ ║  l.43: \t  and ys is Cons(y, ys)\n//│ ║        \t^^\n//│ ╟── Note: 'if' expression starts here:\n//│ ║  l.42: \t  if  xs is Cons(x, xs)\n//│ ╙──      \t  ^^\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.43: \t  and ys is Cons(y, ys)\n//│ ╙──      \t  ^^^\n//│ ╔══[PARSE ERROR] Unexpected operator in expression position\n//│ ║  l.44: \t  and zipWith_wrong(f, xs, ys) is Some(tail)\n//│ ╙──      \t  ^^^\n//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead\n//│ ║  l.42: \t  if  xs is Cons(x, xs)\n//│ ║        \t      ^^^^^^^^^^^^^^^^^\n//│ ║  l.43: \t  and ys is Cons(y, ys)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.44: \t  and zipWith_wrong(f, xs, ys) is Some(tail)\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.45: \t  then Some(Cons(f(x, y), tail))\n//│ ║        \t^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n//│ ║  l.46: \t  else None\n//│ ╙──      \t^^^^^^^^^^^\n//│ fun zipWith_wrong: (anything, anything, anything) -> ()\n\n\nfun zipWith_wrong(f, xs, ys) =\n  if  xs is Cons(x, xs)\n    and ys is Cons(y, ys)\n    and zipWith_wrong(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n  else None\n//│ fun zipWith_wrong: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A]])\n\n\nfun zipWith_wrong(f, xs, ys) =\n  if  xs is Cons(x, xs)\n    and ys is Cons(y, ys) and zipWith_wrong(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n  else None\n//│ fun zipWith_wrong: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A]])\n\n// * Notice the result is wrong (duh)\nzipWith_wrong(pairup, Nil, Nil)\n//│ None | Some[Cons[[nothing, nothing]]]\n//│ res\n//│     = None { class: [class None] }\n\n\n\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n  else if xs is Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is Cons(x, xs) and ys is Cons(y, ys) then\n    if zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail))\n    else None\n  else if xs is Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\n\nfun zipWith(f, xs, ys) =\n  if xs is\n    Cons(x, xs) then\n      if ys is\n        Cons(y, ys) then\n          if zipWith(f, xs, ys) is\n            Some(tail) then Some(Cons(f(x, y), tail))\n            None then None\n        Nil then None\n    Nil then\n      if ys is Nil then Some(Nil) else None\n//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Nil, Cons['b] | Nil) -> (None | Some[Cons['A] | Nil])\n\nzipWith(pairup, Nil, Nil).value.toArray\n//│ Array[anything]\n//│ res\n//│     = []\n\n:re\nzipWith(pairup, Nil, Cons(0, Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│ Runtime error:\n//│   ReferenceError: nothing is not defined\n\nzipWith(pairup, Cons(0, Nil), Cons(\"0\", Nil)).value.toArray\n//│ Array[anything]\n//│ res\n//│     = [ [ 0, '0' ], [] ]\n\nlet ls = zipWith(pairup, Cons(0, Cons(1, Nil)), Cons(\"0\", Cons(\"1\", Nil)))\nls.value.toArray\n//│ let ls: None | Some[Cons[[0 | 1, \"0\" | \"1\"]] | Nil]\n//│ Array[anything]\n//│ ls\n//│    = Some {}\n//│ res\n//│     = [ [ 0, '0' ], [ [ 1, '1' ], [] ] ]\n\n\n\nfun zipWith_wrong2(f, xs, ys) =\n  if xs is Cons(x, xs) and ys is Cons(y, ys) and zipWith_wrong2(f, xs, ys) is Some(tail) then Cons(Some(f(x, y)), tail)\n  else if xs is Nil and ys is Nil then Some(Nil)\n  else None\n//│ fun zipWith_wrong2: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (Cons[Some['A]] | None | Some[Nil])\n\n// * No type error! The definition and use are well-typed...\nzipWith_wrong2(pairup, Cons(0, Cons(1, Nil)), Cons(\"0\", Cons(\"1\", Nil)))\n//│ Cons[Some[[0 | 1, \"0\" | \"1\"]]] | None | Some[Nil]\n//│ res\n//│     = None { class: [class None] }\n\n\n"
  },
  {
    "path": "shared/src/test/scala/mlscript/CodeGenTestHelpers.scala",
    "content": "package mlscript\n\nimport mlscript.utils._\nimport mlscript.utils.shorthands._\n\nclass CodeGenTestHelpers(file: os.Path, output: String => Unit) {\n  def showGeneratedCode(testCode: JSTestBackend.TestCode): Unit = {\n    val JSTestBackend.TestCode(prelude, queries) = testCode\n    if (!prelude.isEmpty) {\n      output(\"// Prelude\")\n      prelude foreach { line =>\n        output(line)\n      }\n    }\n    queries.zipWithIndex foreach {\n      case (JSTestBackend.CodeQuery(prelude, code, _), i) =>\n        output(s\"// Query ${i + 1}\")\n        prelude foreach { output(_) }\n        code foreach { output(_) }\n      case (JSTestBackend.AbortedQuery(reason), i) =>\n        output(s\"// Query ${i + 1} aborted: $reason\")\n      case (JSTestBackend.EmptyQuery, i) =>\n        output(s\"// Query ${i + 1} is empty\")\n    }\n    output(\"// End of generated code\")\n  }\n  def showReplPrelude(\n    sourceLines: List[String],\n    preludeReply: Option[ReplHost.Reply],\n    blockLineNum: Int,\n  ): Unit = {\n    output(s\"┌ Block at ${file.last}:${blockLineNum}\")\n    if (sourceLines.isEmpty) {\n      output(s\"├── No prelude\")\n    } else {\n      output(s\"├─┬ Prelude\")\n      output(s\"│ ├── Code\")\n      sourceLines.iterator.foreach { line => output(s\"│ │   $line\") }\n    }\n    preludeReply.foreach {\n      // Display successful results in multiple lines.\n      // Display other results in single line.\n      case ReplHost.Result(content, intermediate) =>\n        intermediate.foreach { value =>\n          output(s\"│ ├── Intermediate\")\n          value.linesIterator.foreach { line => output(s\"│ │   $line\") }  \n        }\n        output(s\"│ └── Reply\")\n        content.linesIterator.foreach { line => output(s\"│     $line\") }  \n      case other => output(s\"│ └── Reply $other\")\n    }\n  }\n  def showReplContent(\n    queries: List[JSTestBackend.Query],\n    replies: List[(ReplHost.Reply, Str)],\n  ): Unit = {\n    if (queries.isEmpty) {\n      output(s\"└── No queries\")\n    } else {\n      val length = queries.length // We assume that queries.length === replies.length\n      queries.iterator.zip(replies).zipWithIndex.foreach {\n        case ((JSTestBackend.CodeQuery(preludeLines, codeLines, res), (reply, log)), i) =>\n          val p0 = if (i + 1 === length) \"  \" else \"│ \"\n          val p1 = if (i + 1 === length) \"└─\" else \"├─\"\n          output(s\"$p1┬ Query ${i + 1}/${queries.length}\")\n          if (preludeLines.isEmpty) {\n            output(s\"$p0├── Prelude: <empty>\")\n          } else {\n            output(s\"$p0├── Prelude:\")\n            preludeLines.foreach { line => output(s\"$p0├──   $line\") }\n          }\n          output(s\"$p0├── Code:\")\n          codeLines.foreach { line => output(s\"$p0├──   $line\") }\n          // Show the intermediate reply if possible.\n          reply match {\n            case ReplHost.Result(_, Some(intermediate)) =>\n              output(s\"$p0├── Intermediate: $intermediate\")\n            case _ => ()\n          }\n          val p2 = if (i + 1 === length) \"  └──\" else s\"$p0└──\"\n          output(s\"$p2 Reply: $reply\")\n        case ((JSTestBackend.AbortedQuery(reason), _), i) =>\n          val prefix = if (i + 1 === queries.length) \"└──\" else \"├──\"\n          output(s\"$prefix Query ${i + 1}/${queries.length}: <aborted: $reason>\")\n        case ((JSTestBackend.EmptyQuery, _), i) =>\n          val prefix = if (i + 1 === queries.length) \"└──\" else \"├──\"\n          output(s\"$prefix Query ${i + 1}/${queries.length}: <empty>\")\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "shared/src/test/scala/mlscript/DiffTests.scala",
    "content": "package mlscript\n\nimport fastparse._\nimport fastparse.Parsed.Failure\nimport fastparse.Parsed.Success\nimport sourcecode.Line\nimport scala.collection.mutable\nimport scala.collection.mutable.{Map => MutMap}\nimport mlscript.utils._, shorthands._\nimport mlscript.codegen.typescript.TsTypegenCodeBuilder\nimport org.scalatest.{funsuite, ParallelTestExecution}\nimport org.scalatest.time._\nimport org.scalatest.concurrent.{TimeLimitedTests, Signaler}\nimport pretyper.PreTyper\nimport os.Path\n\nabstract class ModeType {\n  def expectTypeErrors: Bool\n  def expectWarnings: Bool\n  def expectParseErrors: Bool\n  def fixme: Bool\n  def showParse: Bool\n  def verbose: Bool\n  def noSimplification: Bool\n  def explainErrors: Bool\n  def dbg: Bool\n  def dbgParsing: Bool\n  def dbgSimplif: Bool\n  def dbgUCS: Opt[Set[Str]]\n  def dbgLifting: Bool\n  def dbgDefunc: Bool\n  def dbgSimpledef: Bool\n  def fullExceptionStack: Bool\n  def stats: Bool\n  def stdout: Bool\n  def noExecution: Bool\n  def noGeneration: Bool\n  def showGeneratedJS: Bool\n  def generateTsDeclarations: Bool\n  def debugVariance: Bool\n  def expectRuntimeErrors: Bool\n  def expectCodeGenErrors: Bool\n  def showRepl: Bool\n  def allowEscape: Bool\n  def useIR: Bool\n  def interpIR: Bool\n  def irVerbose: Bool\n  def genCpp: Bool\n  def showCpp: Bool\n  def runCpp: Bool\n  def writeCpp: Bool\n  def noTailRecOpt: Bool\n  def simpledef: Bool\n  def lift: Bool\n  def nolift: Bool\n  def prelude: Bool\n}\n\nclass DiffTests(state: DiffTests.State)\n  extends funsuite.AnyFunSuite\n  with ParallelTestExecution\n  with TimeLimitedTests\n{\n  \n  def this() = this(DiffTests.State)\n  \n  import state._\n  \n  /**  Hook for dependent projects, like the monomorphizer. */\n  def postProcess(mode: ModeType, basePath: Ls[Str], testName: Str, unit: TypingUnit, output: Str => Unit, raise: Diagnostic => Unit): (Ls[Str], Option[TypingUnit]) = (Nil, None)\n  def postTypingProcess(mode: ModeType, basePath: Ls[Str], testName: Str, unit: TypingUnit, output: Str => Unit): Option[TypingUnit] = None\n  \n  \n  @SuppressWarnings(Array(\"org.wartremover.warts.RedundantIsInstanceOf\"))\n  private val inParallel = isInstanceOf[ParallelTestExecution]\n  \n  // scala test will not execute a test if the test class has constructor parameters.\n  // override this to get the correct paths of test files.\n  protected lazy val files = allFiles.filter { file =>\n      val fileName = file.baseName\n      // validExt(file.ext) && filter(fileName)\n      validExt(file.ext) && filter(file.relativeTo(DiffTests.pwd))\n  }\n  \n  val timeLimit = TimeLimit\n  \n  override val defaultTestSignaler: Signaler = new Signaler {\n    @annotation.nowarn(\"msg=method stop in class Thread is deprecated\") def apply(testThread: Thread): Unit = {\n      println(s\"!! Test at $testThread has run out out time !! stopping...\" +\n        \"\\n\\tNote: you can increase this limit by changing DiffTests.TimeLimit\")\n      // * Thread.stop() is considered bad practice because normally it's better to implement proper logic\n      // * to terminate threads gracefully, avoiding leaving applications in a bad state.\n      // * But here we DGAF since all the test is doing is runnign a type checker and some Node REPL,\n      // * which would be a much bigger pain to make receptive to \"gentle\" interruption.\n      // * It would feel extremely wrong to intersperse the pure type checker algorithms\n      // * with ugly `Thread.isInterrupted` checks everywhere...\n      testThread.stop()\n    }\n  }\n  \n  files.foreach { file =>\n        val basePath = file.segments.drop(dir.segmentCount).toList.init\n        val testName = basePath.map(_ + \"/\").mkString + file.baseName\n        test(testName) {\n    \n    val baseStr = basePath.mkString(\"/\")\n    \n    val testStr = \" \" * (8 - baseStr.length) + baseStr + \": \" + file.baseName\n    \n    if (!inParallel) print(s\"Processing $testStr\")\n    \n    // * For some reason, the color is sometimes wiped out when the line is later updated not in iTerm3:\n    // if (!inParallel) print(s\"${Console.CYAN}Processing${Console.RESET} $testStr ... \")\n    \n    val beginTime = System.nanoTime()\n    \n    val outputMarker = \"//│ \"\n    // val oldOutputMarker = \"/// \"\n    \n    val diffBegMarker = \"<<<<<<<\"\n    val diffMidMarker = \"=======\"\n    val diff3MidMarker = \"|||||||\" // * Appears under `git config merge.conflictstyle diff3` (https://stackoverflow.com/a/18131595/1518588)\n    val diffEndMarker = \">>>>>>>\"\n    \n    val exitMarker = \"=\" * 100\n    \n    var occursCheck = false\n    \n    val fileContents = os.read(file)\n    val allLines = fileContents.splitSane('\\n').toList\n    val strw = new java.io.StringWriter\n    val out = new java.io.PrintWriter(strw) {\n      override def println(): Unit = print('\\n') // to avoid inserting CRLF on Windows\n    }\n    var stdout = false\n    def output(str: String) =\n      // out.println(outputMarker + str)\n      if (stdout) System.out.println(str) else\n      str.splitSane('\\n').foreach(l => out.println(outputMarker + l))\n    def outputSourceCode(code: SourceCode) = code.lines.foreach{line => out.println(outputMarker + line.toString())}\n    val allStatements = mutable.Buffer.empty[DesugaredStatement]\n    var newDefs = false\n    trait MyTyper extends Typer { var ctx: Ctx }\n    lazy val typer =\n      new Typer(dbg = false, verbose = false, explainErrors = false, newDefs = newDefs) with MyTyper {\n        var ctx: Ctx = Ctx.init\n        override def recordTypeVars = occursCheck\n        override def funkyTuples = file.ext =:= \"fun\"\n        // override def emitDbg(str: String): Unit = if (stdout) System.out.println(str) else output(str)\n        override def emitDbg(str: String): Unit = output(str)\n        createdTypeVars.clear()\n      }\n    def ctx = typer.ctx\n    var declared: Map[Str, typer.ST] = Map.empty\n    val failures = mutable.Buffer.empty[Int]\n    val unmergedChanges = mutable.Buffer.empty[Int]\n    var preTyperScope = mlscript.pretyper.Scope.global\n    \n    case class Mode(\n      expectTypeErrors: Bool = false,\n      expectCompileErrors: Bool = false,\n      expectWarnings: Bool = false,\n      expectParseErrors: Bool = false,\n      fixme: Bool = false,\n      showParse: Bool = false,\n      verbose: Bool = false,\n      noSimplification: Bool = false,\n      explainErrors: Bool = false,\n      dbg: Bool = false,\n      dbgParsing: Bool = false,\n      dbgSimplif: Bool = false,\n      dbgUCS: Opt[Set[Str]] = N,\n      dbgLifting: Bool = false,\n      dbgDefunc: Bool = false,\n      dbgSimpledef: Bool = false,\n      fullExceptionStack: Bool = false,\n      stats: Bool = false,\n      stdout: Bool = false,\n      preciselyTypeRecursion: Bool = false,\n      noExecution: Bool = false,\n      noGeneration: Bool = false,\n      showGeneratedJS: Bool = false,\n      generateTsDeclarations: Bool = false,\n      debugVariance: Bool = false,\n      expectRuntimeErrors: Bool = false,\n      expectCodeGenErrors: Bool = false,\n      showRepl: Bool = false,\n      allowEscape: Bool = false,\n      simpledef: Bool = false,\n      lift: Bool = false,\n      nolift: Bool = false,\n      // noProvs: Bool = false,\n      useIR: Bool = false,\n      interpIR: Bool = false,\n      irVerbose: Bool = false,\n      irOpt: Bool = false,\n      irOptFuel: Int = 10,\n      genCpp: Bool = false,\n      showCpp: Bool = false,\n      runCpp: Bool = false,\n      writeCpp: Bool = false,\n      noTailRecOpt: Bool = false,\n      prelude: Bool = false,\n    ) extends ModeType {\n      def isDebugging: Bool = dbg || dbgSimplif\n    }\n    val defaultMode = Mode()\n    \n    var parseOnly = basePath.headOption.contains(\"parser\")\n    var allowTypeErrors = false\n    var allowCompileErrors = false\n    var allowParseErrors = false\n    var showRelativeLineNums = false\n    var noJavaScript = false\n    var noProvs = false\n    var allowRuntimeErrors = false\n    var generalizeCurriedFunctions = false\n    // var generalizeCurriedFunctions = true\n    var distributeForalls = true\n    // var distributeForalls = false\n    var approximateNegativeFunction = false\n    var noCycleCheck = false\n    var noRecursiveTypes = false\n    var constrainedTypes = false\n    var irregularTypes = false\n    var prettyPrintQQ = false\n    var useIR = false\n    // Enable this to see the errors from unfinished `PreTyper`.\n    var showPreTyperErrors = false\n    var noTailRec = false\n    var noApproximateOverload = false\n    \n    // * This option makes some test cases pass which assume generalization should happen in arbitrary arguments\n    // * but it's way too aggressive to be ON by default, as it leads to more extrusion, cycle errors, etc.\n    var generalizeArguments = false\n    \n    var newParser = basePath.headOption.contains(\"parser\") || basePath.headOption.contains(\"compiler\")\n    \n    val backend = new JSTestBackend {\n      override def oldDefs: Bool = !newDefs\n    }\n    var hostCreated = false\n    lazy val host = { hostCreated = true; ReplHost() }\n    val codeGenTestHelpers = new CodeGenTestHelpers(file, output)\n    \n    def rec(lines: List[String], mode: Mode): Unit = lines match {\n      case \"\" :: Nil =>\n      case line :: ls if line.startsWith(\":\") =>\n        out.println(line)\n        val newMode = line.tail.takeWhile(!_.isWhitespace) match {\n          case \"e\" => mode.copy(expectTypeErrors = true)\n          case \"ce\" => mode.copy(expectCompileErrors = true)\n          case \"w\" => mode.copy(expectWarnings = true)\n          case \"pe\" => mode.copy(expectParseErrors = true)\n          case \"p\" => mode.copy(showParse = true)\n          case \"d\" => mode.copy(dbg = true)\n          case \"dp\" => mode.copy(dbgParsing = true)\n          case DiffTests.DebugUCSFlags(x) => mode.copy(dbgUCS = mode.dbgUCS.fold(S(x))(y => S(y ++ x)))\n          case \"ds\" => mode.copy(dbgSimplif = true)\n          case \"dl\" => mode.copy(dbgLifting = true)\n          case \"dd\" => mode.copy(dbgDefunc = true)\n          case \"dsd\" => mode.copy(dbgSimpledef = true)\n          case \"s\" => mode.copy(fullExceptionStack = true)\n          case \"v\" | \"verbose\" => mode.copy(verbose = true)\n          case \"ex\" | \"explain\" => mode.copy(expectTypeErrors = true, explainErrors = true)\n          case \"ns\" | \"no-simpl\" => mode.copy(noSimplification = true)\n          // case \"limit-errors\" => mode.copy(limitErrors = true)\n          case \"stats\" => mode.copy(stats = true)\n          case \"stdout\" => mode.copy(stdout = true)\n          case \"precise-rec-typing\" => mode.copy(preciselyTypeRecursion = true)\n          case \"ParseOnly\" => parseOnly = true; mode\n          case \"AllowTypeErrors\" => allowTypeErrors = true; mode\n          case \"AllowCompileErrors\" => allowCompileErrors = true; mode\n          case \"AllowParseErrors\" => allowParseErrors = true; mode\n          case \"AllowRuntimeErrors\" => allowRuntimeErrors = true; mode\n          case \"ShowRelativeLineNums\" => showRelativeLineNums = true; mode\n          case \"NewParser\" => newParser = true; mode\n          case \"NewDefs\" => newParser = true; newDefs = true; mode\n          case \"NoJS\" => noJavaScript = true; mode\n          case \"NoTailRec\" => noTailRec = true; mode\n          case \"NoProvs\" => noProvs = true; mode\n          case \"GeneralizeCurriedFunctions\" => generalizeCurriedFunctions = true; mode\n          case \"DontGeneralizeCurriedFunctions\" => generalizeCurriedFunctions = false; mode\n          case \"DistributeForalls\" =>\n            distributeForalls = true\n            generalizeCurriedFunctions = false\n            mode\n          case \"DontDistributeForalls\" =>\n            distributeForalls = false\n            generalizeCurriedFunctions = true\n            mode\n          case \"ApproximateNegativeFunction\" => approximateNegativeFunction = true; mode\n          case \"NoCycleCheck\" => noCycleCheck = true; mode\n          case \"CycleCheck\" => noCycleCheck = false; mode\n          case \"OccursCheck\" => occursCheck = true; mode\n          case \"RecursiveTypes\" => noRecursiveTypes = false; occursCheck = false; mode\n          case \"NoRecursiveTypes\" => noRecursiveTypes = true; occursCheck = true; mode\n          case \"ConstrainedTypes\" => constrainedTypes = true; mode\n          case \"NoConstrainedTypes\" => constrainedTypes = false; mode\n          case \"GeneralizeArguments\" => generalizeArguments = true; mode\n          case \"DontGeneralizeArguments\" => generalizeArguments = false; mode\n          case \"IrregularTypes\" => irregularTypes = true; mode\n          case \"NoApproximateOverload\" => noApproximateOverload = true; mode\n          case str @ \"Fuel\" =>\n            // println(\"'\"+line.drop(str.length + 2)+\"'\")\n            typer.startingFuel = line.drop(str.length + 2).toInt; mode\n          case \"ResetFuel\" => typer.startingFuel = typer.defaultStartingFuel; mode\n          case \"QQ\" => prettyPrintQQ = true; mode\n          // Enable this to see the errors from unfinished `PreTyper`.\n          case \"ShowPreTyperErrors\" => newParser = true; newDefs = true; showPreTyperErrors = true; mode\n          case \"ne\" => mode.copy(noExecution = true)\n          case \"ng\" => mode.copy(noGeneration = true)\n          case \"js\" => mode.copy(showGeneratedJS = true)\n          case \"ts\" => mode.copy(generateTsDeclarations = true)\n          case \"dv\" => mode.copy(debugVariance = true)\n          case \"ge\" => mode.copy(expectCodeGenErrors = true)\n          case \"re\" => mode.copy(expectRuntimeErrors = true)\n          case \"r\" | \"showRepl\" => mode.copy(showRepl = true)\n          case \"escape\" => mode.copy(allowEscape = true)\n          case \"sd\" => {mode.copy(simpledef = true)}\n          case \"lift\" => {mode.copy(lift = true)}\n          case \"noTailRec\" => mode.copy(noTailRecOpt = true)\n          case \"nolift\" => {mode.copy(nolift = true)}\n          case \"exit\" =>\n            out.println(exitMarker)\n            ls.dropWhile(_ =:= exitMarker).tails.foreach {\n              case Nil =>\n              case lastLine :: Nil => out.print(lastLine)\n              case l :: _ => out.println(l)\n            }\n            return ()\n          case \"UseIR\" => useIR = true; mode\n          case \"useIR\" => mode.copy(useIR = true)\n          case \"interpIR\" => mode.copy(interpIR = true)\n          case \"irVerbose\" => mode.copy(irVerbose = true)\n          case \"genCpp\" => mode.copy(genCpp = true)\n          case \"showCpp\" => mode.copy(showCpp = true)\n          case \"runCpp\" => mode.copy(runCpp = true)\n          case \"writeCpp\" => mode.copy(writeCpp = true)\n          case \"prelude\" => mode.copy(prelude = true)\n          case _ =>\n            failures += allLines.size - lines.size\n            output(\"/!\\\\ Unrecognized option \" + line)\n            mode\n        }\n        rec(ls, newMode)\n      case line :: ls if line.startsWith(\"// FIXME\") || line.startsWith(\"// TODO\") =>\n        out.println(line)\n        rec(ls, mode.copy(fixme = true))\n      case line :: ls if line.startsWith(outputMarker) //|| line.startsWith(oldOutputMarker)\n        => rec(ls, defaultMode)\n      case line :: ls if line.isEmpty =>\n        out.println(line)\n        rec(ls, defaultMode)\n      case line :: ls if line.startsWith(\"//\") =>\n        out.println(line)\n        rec(ls, mode)\n      case line :: ls if line.startsWith(diffBegMarker) => // Check if there are unmerged git conflicts\n        val diff = ls.takeWhile(l => !l.startsWith(diffEndMarker))\n        assert(diff.exists(_.startsWith(diffMidMarker)), diff)\n        val rest = ls.drop(diff.length)\n        val hdo = rest.headOption\n        assert(hdo.exists(_.startsWith(diffEndMarker)), hdo)\n        val blankLines = diff.count(_.isEmpty)\n        val hasBlankLines = diff.exists(_.isEmpty)\n        if (diff.forall(l => l.startsWith(outputMarker) || l.startsWith(diffMidMarker) || l.startsWith(diff3MidMarker) || l.isEmpty)) {\n          for (_ <- 1 to blankLines) out.println()\n        } else {\n          unmergedChanges += allLines.size - lines.size + 1\n          out.println(diffBegMarker)\n          diff.foreach(out.println)\n          out.println(diffEndMarker)\n        }\n        rec(rest.tail, if (hasBlankLines) defaultMode else mode)\n      // process block of text and show output - type, expressions, errors\n      case l :: ls =>\n        val blockLineNum = (allLines.size - lines.size) + 1\n        \n        val block = (l :: ls.takeWhile(l => l.nonEmpty && !(\n          l.startsWith(outputMarker)\n          || l.startsWith(diffBegMarker)\n          // || l.startsWith(oldOutputMarker)\n        ))).toIndexedSeq\n        block.foreach(out.println)\n        val processedBlock = if (file.ext =:= \"fun\") block.map(_ + \"\\n\") else MLParser.addTopLevelSeparators(block)\n        val processedBlockStr = processedBlock.mkString\n        val fph = new FastParseHelpers(block)\n        val globalStartLineNum = allLines.size - lines.size + 1\n        \n        var totalTypeErrors = 0\n        var totalParseErrors = 0\n        var totalCompileErrors = 0\n        var totalWarnings = 0\n        var totalRuntimeErrors = 0\n        var totalCodeGenErrors = 0\n        \n        // report errors and warnings\n        def report(diags: Ls[mlscript.Diagnostic], output: Str => Unit = output): Unit = {\n          diags.foreach { diag =>\n            val sctx = Message.mkCtx(diag.allMsgs.iterator.map(_._1), newDefs, \"?\")\n            val headStr = diag match {\n              case ErrorReport(msg, loco, src) =>\n                src match {\n                  case Diagnostic.Lexing =>\n                    totalParseErrors += 1\n                    s\"╔══[LEXICAL ERROR] \"\n                  case Diagnostic.Parsing =>\n                    totalParseErrors += 1\n                    s\"╔══[PARSE ERROR] \"\n                  case Diagnostic.Compilation =>\n                    totalCompileErrors += 1\n                    s\"╔══[COMPILATION ERROR] \"\n                  case _ => // TODO customize too\n                    totalTypeErrors += 1\n                    s\"╔══[ERROR] \"\n                }\n              case WarningReport(msg, loco, src) =>\n                totalWarnings += 1\n                s\"╔══[WARNING] \"\n            }\n            val lastMsgNum = diag.allMsgs.size - 1\n            var globalLineNum = blockLineNum  // solely used for reporting useful test failure messages\n            diag.allMsgs.zipWithIndex.foreach { case ((msg, loco), msgNum) =>\n              val isLast = msgNum =:= lastMsgNum\n              val msgStr = msg.showIn(sctx)\n              if (msgNum =:= 0) output(headStr + msgStr)\n              else output(s\"${if (isLast && loco.isEmpty) \"╙──\" else \"╟──\"} ${msgStr}\")\n              if (loco.isEmpty && diag.allMsgs.size =:= 1) output(\"╙──\")\n              loco.foreach { loc =>\n                val (startLineNum, startLineStr, startLineCol) =\n                  loc.origin.fph.getLineColAt(loc.spanStart)\n                if (globalLineNum =:= 0) globalLineNum += startLineNum - 1\n                val (endLineNum, endLineStr, endLineCol) =\n                  loc.origin.fph.getLineColAt(loc.spanEnd)\n                var l = startLineNum\n                var c = startLineCol\n                while (l <= endLineNum) {\n                  val globalLineNum = loc.origin.startLineNum + l - 1\n                  val relativeLineNum = globalLineNum - blockLineNum + 1\n                  val shownLineNum =\n                    if (showRelativeLineNums && relativeLineNum > 0) s\"l.+$relativeLineNum\"\n                    else \"l.\" + globalLineNum\n                  val prepre = \"║  \"\n                  val pre = s\"$shownLineNum: \"\n                  val curLine = loc.origin.fph.lines(l - 1)\n                  output(prepre + pre + \"\\t\" + curLine)\n                  val tickBuilder = new StringBuilder()\n                  tickBuilder ++= (\n                    (if (isLast && l =:= endLineNum) \"╙──\" else prepre)\n                    + \" \" * pre.length + \"\\t\" + \" \" * (c - 1))\n                  val lastCol = if (l =:= endLineNum) endLineCol else curLine.length + 1\n                  while (c < lastCol) { tickBuilder += ('^'); c += 1 }\n                  if (c =:= startLineCol) tickBuilder += ('^')\n                  output(tickBuilder.toString)\n                  c = 1\n                  l += 1\n                }\n              }\n            }\n            if (diag.allMsgs.isEmpty) output(\"╙──\")\n            \n            if (!mode.fixme) {\n              if (!allowTypeErrors\n                  && !mode.expectTypeErrors && diag.isInstanceOf[ErrorReport] && diag.source =:= Diagnostic.Typing)\n                { output(\"TEST CASE FAILURE: There was an unexpected type error\"); failures += globalLineNum }\n              if (!allowParseErrors\n                  && !mode.expectParseErrors && diag.isInstanceOf[ErrorReport] && (diag.source =:= Diagnostic.Lexing || diag.source =:= Diagnostic.Parsing))\n                { output(\"TEST CASE FAILURE: There was an unexpected parse error\"); failures += globalLineNum }\n              if (!allowCompileErrors\n                  && !mode.expectCompileErrors && diag.isInstanceOf[ErrorReport] && diag.source =:= Diagnostic.Compilation)\n                { output(\"TEST CASE FAILURE: There was an unexpected compilation error\"); failures += globalLineNum }\n              if (!allowTypeErrors && !allowParseErrors\n                  && !mode.expectWarnings && diag.isInstanceOf[WarningReport])\n                { output(\"TEST CASE FAILURE: There was an unexpected warning\"); failures += globalLineNum }\n            }\n            \n            ()\n          }\n        }\n        \n        val raise: Raise = d => report(d :: Nil)\n        \n        val legacyParser = file.ext =:= \"fun\"\n        \n        // try to parse block of text into mlscript ast\n        val ans = try {\n          if (newParser) {\n            \n            val origin = Origin(testName, globalStartLineNum, fph)\n            val lexer = new NewLexer(origin, raise, dbg = mode.dbgParsing)\n            \n            val tokens = lexer.bracketedTokens\n            \n            if (mode.showParse || mode.dbgParsing || parseOnly)\n              output(NewLexer.printTokens(tokens))\n            \n            val p = new NewParser(origin, tokens, newDefs, raise, dbg = mode.dbgParsing, N) {\n              def doPrintDbg(msg: => Str): Unit = if (dbg) output(msg)\n            }\n            val res = p.parseAll(p.typingUnit)\n            \n            if (parseOnly)\n              output(s\"Parsed: ${res.showDbg}\")\n            \n            if (mode.showParse)\n              output(s\"AST: $res\")\n            \n            val newMode = if (useIR) { mode.copy(useIR = true) } else mode\n            val newNewMode = if (noTailRec) { newMode.copy(noTailRecOpt = true) } else newMode\n\n            val (postLines, nuRes) = postProcess(newNewMode, basePath, testName, res, output, raise)\n            postLines.foreach(output)\n\n            if (parseOnly)\n              Success(Pgrm(Nil), 0)\n            else if (mode.lift) {\n              import Message._\n              Success(Pgrm(nuRes.getOrElse({\n                raise(ErrorReport(msg\"Post-process failed to produce AST.\" -> None :: Nil, true, Diagnostic.Compilation))\n                TypingUnit(Nil)\n              }).entities), 0)\n            }\n            else\n              Success(Pgrm(res.entities), 0)\n            \n          }\n          else parse(processedBlockStr, p =>\n            if (legacyParser) new Parser(Origin(testName, globalStartLineNum, fph)).pgrm(p)\n            else new MLParser(Origin(testName, globalStartLineNum, fph)).pgrm(p),\n            verboseFailures = true\n          )\n        } match {\n          case f: Failure =>\n            val Failure(lbl, index, extra) = f\n            val (lineNum, lineStr, col) = fph.getLineColAt(index)\n            val globalLineNum = (allLines.size - lines.size) + lineNum\n            if (!mode.expectParseErrors && !mode.fixme)\n              { output(\"TEST CASE FAILURE: There was an unexpected parse error\"); failures += globalLineNum }\n            output(\"/!\\\\ Parse error: \" + extra.trace().msg +\n              s\" at l.$globalLineNum:$col: $lineStr\")\n            \n          // successfully parsed block into a valid syntactically valid program\n          case Success(p, index) =>\n            if (mode.expectParseErrors && !newParser && !legacyParser)\n              { output(\"TEST CASE FAILURE: There was an unexpected parse success\"); failures += blockLineNum }\n            if (mode.showParse || mode.dbgParsing) output(\"Parsed: \" + p.showDbg)\n            // if (mode.isDebugging) typer.resetState()\n            if (mode.stats) typer.resetStats()\n            typer.dbg = mode.dbg\n            // typer.recordProvenances = !noProvs\n            typer.recordProvenances = !noProvs && !mode.dbg && !mode.dbgSimplif || mode.explainErrors\n            typer.generalizeCurriedFunctions = generalizeCurriedFunctions\n            typer.approximateNegativeFunction = approximateNegativeFunction\n            typer.distributeForalls = distributeForalls\n            typer.noCycleCheck = noCycleCheck\n            typer.noRecursiveTypes = noRecursiveTypes\n            typer.constrainedTypes = constrainedTypes\n            typer.generalizeArguments = generalizeArguments\n            typer.irregularTypes = irregularTypes\n            typer.verbose = mode.verbose\n            typer.explainErrors = mode.explainErrors\n            stdout = mode.stdout\n            typer.preciselyTypeRecursion = mode.preciselyTypeRecursion\n            typer.noApproximateOverload = noApproximateOverload\n            \n            val oldCtx = ctx\n            \n            def getType(ty: typer.SimpleType, pol: Opt[Bool], removePolarVars: Bool = true): Type =\n              getTypeLike(ty, pol, removePolarVars) match {\n                case ty: Type => ty\n                case _ => die\n              }\n            def getTypeLike(ty: typer.SimpleType, pol: Opt[Bool], removePolarVars: Bool): TypeLike = {\n              if (mode.isDebugging) output(s\"⬤ Typed as: $ty\")\n              if (mode.isDebugging) output(s\" where: ${ty.showBounds}\")\n              typer.dbg = mode.dbgSimplif\n              if (mode.noSimplification) typer.expandType(ty)(ctx)\n              else {\n                object SimplifyPipeline extends typer.SimplifyPipeline {\n                  def debugOutput(msg: => Str): Unit =\n                    if (mode.dbgSimplif) output(msg)\n                }\n                val sim = SimplifyPipeline(ty, pol, removePolarVars)(ctx)\n                val exp = typer.expandType(sim)(ctx)\n                if (mode.dbgSimplif) output(s\"⬤ Expanded: ${exp}\")\n                def stripPoly(pt: PolyType): Type =\n                  pt.targs.filterNot(_.isRight) match {\n                    case Nil => pt.body\n                    case tps => PolyType(tps, pt.body)\n                  }\n                exp match {\n                  // * Strip top-level implicitly-quantified type variables\n                  case pt: PolyType => stripPoly(pt)\n                  case Constrained(pt: PolyType, bs, cs, tscs) => Constrained(stripPoly(pt), bs, cs, tscs)\n                  case ty => ty\n                }\n              }\n            }\n            \n            val (typeDefs, stmts, newDefsResults) = if (newDefs) {\n              val vars: Map[Str, typer.SimpleType] = Map.empty\n              val rootTypingUnit = TypingUnit(p.tops)\n              val preTyper = new PreTyper {\n                override def debugTopicFilters = mode.dbgUCS\n                override def emitString(str: String): Unit = output(str)\n              }\n              // This scope will be passed to typer and code generator after\n              // pretyper is completed.\n              preTyperScope = preTyper(rootTypingUnit, preTyperScope, \"<root>\")\n              report(preTyper.filterDiagnostics(_.source is Diagnostic.Desugaring))\n              if (showPreTyperErrors) report(preTyper.filterDiagnostics(_.source is Diagnostic.PreTyping))\n              val tpd = typer.typeTypingUnit(rootTypingUnit, N)(ctx, raise, vars)\n              \n              def showTTU(ttu: typer.TypedTypingUnit, ind: Int): Unit = {\n                val indStr = \"  \" * ind\n                ttu.implementedMembers.foreach {\n                  // case p: typer.NuTypeParam =>\n                  //   output(s\"${indStr}${p.name}: ${p.ty}\")\n                  case p: typer.NuParam =>\n                    output(s\"${indStr}${p.name}: ${p.ty}\")\n                  case tc: typer.TypedNuAls =>\n                    output(s\"${indStr}type ${tc.name} = ${tc.body}\")\n                  case tt: typer.TypedNuTrt =>\n                    output(s\"${indStr}trait ${tt.name}\")\n                    output(s\"${indStr}  this: ${tt.thisTy} ${tt.thisTy.showBounds\n                      .indentNewLines(indStr+\"  |\")}\")\n                  case tc: typer.TypedNuCls =>\n                    output(s\"${indStr}class ${tc.name}\")\n                    output(s\"${indStr}  this: ${tc.thisTy} ${tc.thisTy.showBounds\n                      .indentNewLines(indStr+\"  |\")}\")\n                    // showTTU(tc.ttu, ind + 1)\n                  case tm: typer.TypedNuMxn =>\n                    output(s\"${indStr}mixin ${tm.name}\")\n                    output(s\"${indStr}  this: ${tm.thisTy} ${tm.thisTy.showBounds\n                      .indentNewLines(indStr+\"  |\")}\")\n                    output(s\"${indStr}  super: ${tm.superTy} ${tm.superTy.showBounds\n                      .indentNewLines(indStr+\"  |\")}\")\n                    // showTTU(tm.ttu, ind + 1)\n                  case tf: typer.TypedNuFun =>\n                    output(s\"${indStr}${tf.fd.isLetRec match {\n                      case S(false) => \"let\"\n                      case S(true) => \"let rec\"\n                      case N => \"fun\"\n                    }} ${tf.name}: ${tf.typeSignature} where ${tf.typeSignature.showBounds\n                      .indentNewLines(indStr+\"|\")}\")\n                  case typer.TypedNuDummy(d) =>\n                    output(s\"${indStr}<dummy> ${d.name}\")\n                }\n              }\n              if (mode.dbg || mode.explainErrors) {\n                output(\"======== TYPED ========\")\n                showTTU(tpd, 0)\n                tpd.result.foreach { res_ty =>\n                  output(\"res: \" + tpd.result + \" where \" + res_ty.showBounds)\n                }\n              }\n              \n              val oldDbg = typer.dbg\n              val sim = if (mode.noSimplification) tpd else try {\n                typer.dbg = mode.dbgSimplif\n                object SimplifyPipeline extends typer.SimplifyPipeline {\n                  def debugOutput(msg: => Str): Unit =\n                    if (mode.dbgSimplif) output(msg)\n                }\n                SimplifyPipeline(tpd, pol = S(true))(ctx)\n              } finally typer.dbg = oldDbg\n              \n              val exp = typer.expandType(sim)(ctx)\n              \n              val expStr =\n                exp.showIn(0)(ShowCtx.mk(exp :: Nil, newDefs))// .copy(newDefs = true) // TODO later\n              \n              output(expStr.stripSuffix(\"\\n\"))\n              \n              (Nil, Nil, S(p.tops.collect {\n                case NuFunDef(isLet, nme, snme, tparams, bod) =>\n                  (nme.name + \" \", nme.name :: Nil, Nil, false, isLet.isEmpty)\n                case t: Term => (\"res \", \"res\" :: Nil, Nil, false, false)\n              }))\n              \n            } else {\n              \n              val (diags, (typeDefs, stmts)) = p.desugared\n              report(diags)\n              \n              if (mode.showParse) {\n                typeDefs.foreach(td => output(\"Desugared: \" + td.showDbg))\n                stmts.foreach { s =>\n                  output(\"Desugared: \" + s.showDbg)\n                  output(s\"AST: $s\")\n                }\n              }\n              \n              typer.ctx = typer.processTypeDefs(typeDefs)(ctx, raise)\n              \n              (typeDefs, stmts, N)\n            }\n            \n            // initialize ts typegen code builder and\n            // declare all type definitions for current block\n            val tsTypegenCodeBuilder = new TsTypegenCodeBuilder()\n            if (mode.generateTsDeclarations) {\n              typeDefs.iterator.filter(td =>\n                ctx.tyDefs.contains(td.nme.name) && !oldCtx.tyDefs.contains(td.nme.name)\n              ).foreach(td => tsTypegenCodeBuilder.declareTypeDef(td))\n            }\n\n            val curBlockTypeDefs = typeDefs\n              // add check from process type def block below\n              .flatMap(td => if (!oldCtx.tyDefs.contains(td.nme.name)) ctx.tyDefs.get(td.nme.name) else None)\n            \n            // activate typer tracing if variance debugging is on and then set it back\n            // this makes it possible to debug variance in isolation\n            var temp = typer.dbg\n            typer.dbg = mode.debugVariance\n            typer.computeVariances(curBlockTypeDefs, ctx)\n            typer.dbg = temp\n            val varianceWarnings: MutMap[TypeName, Ls[TypeName]] = MutMap()\n\n            // show the result of type inference for each processed type def\n            typeDefs.foreach(td =>\n              // check if type def is not previously defined\n              if (ctx.tyDefs.contains(td.nme.name)\n                  && !oldCtx.tyDefs.contains(td.nme.name)) {\n                  // ^ it may not end up being defined if there's an error\n\n                val tn = td.nme.name\n                val ttd = ctx.tyDefs(tn)\n                val tvv = ttd.tvarVariances.getOrElse(die)\n\n                // generate warnings for bivariant type variables\n                val bivariantTypeVars = ttd.tparamsargs.iterator.filter{ case (tname, tvar) =>\n                  tvv.get(tvar).contains(VarianceInfo.bi)\n                }.map(_._1).toList\n                if (!bivariantTypeVars.isEmpty) {\n                  varianceWarnings.put(td.nme, bivariantTypeVars)\n                }\n                \n                val params = if (!ttd.tparamsargs.isEmpty)\n                    SourceCode.horizontalArray(ttd.tparamsargs.map{ case (tname, tvar) =>\n                      val tvarVariance = tvv.getOrElse(tvar, throw new Exception(\n                        s\"Type variable $tvar not found in variance store ${ttd.tvarVariances} for $ttd\"))\n                      SourceCode(s\"${tvarVariance.show}${tname.name}\")\n                    })\n                  else\n                    SourceCode(\"\")\n                output(s\"Defined \" + td.kind.str + \" \" + tn + params)\n\n                // calculate types for all method definitions and declarations\n                // only once and reuse for pretty printing and type generation\n                val methodsAndTypes = (ttd.mthDecls ++ ttd.mthDefs).flatMap {\n                  case m@MethodDef(_, _, Var(mn), _, rhs) =>\n                    rhs.fold(\n                      _ => ctx.getMthDefn(tn, mn).map(mthTy => (m, getType(mthTy.toPT, S(true)))),\n                      _ => ctx.getMth(S(tn), mn).map(mthTy => (m, getType(mthTy.toPT, N)))\n                    )\n                }\n\n                // pretty print method definitions\n                methodsAndTypes.foreach {\n                  case (MethodDef(_, _, Var(mn), _, rhs), res) =>\n                    output(s\"${rhs.fold(\n                      _ => \"Defined\",  // the method has been defined\n                      _ => \"Declared\"  // the method type has just been declared\n                    )} ${tn}.${mn}: ${res.show(newDefs)}\")\n                }\n\n                // start typegen, declare methods if any and complete typegen block\n                if (mode.generateTsDeclarations) {\n                  val mthDeclSet = ttd.mthDecls.iterator.map(_.nme.name).toSet\n                  val methods = methodsAndTypes\n                    // filter method declarations and definitions\n                    // without declarations\n                    .withFilter { case (mthd, _) =>\n                      mthd.rhs.isRight || !mthDeclSet.contains(mthd.nme.name)\n                    }\n                    .map {\n                      case (mthd, mthdTy: Type) => (mthd.nme.name, mthdTy)\n                      case _ => die\n                    }\n\n                  tsTypegenCodeBuilder.addTypeDef(td, methods)\n                }\n              }\n            )\n            \n            if (!varianceWarnings.isEmpty) {\n              import Message._\n              val diags = varianceWarnings.iterator.map { case (tname, biVars) =>\n                val warnings = biVars.map( tname => msg\"${tname.name} is irrelevant and may be removed\" -> tname.toLoc)\n                WarningReport(\n                  msg\"Type definition ${tname.name} has bivariant type parameters:\" -> tname.toLoc :: warnings,\n                  newDefs)\n              }.toList\n              report(diags)\n            }\n            \n            // process statements and output mlscript types\n            // all `Def`s and `Term`s are processed here\n            // generate typescript types if generateTsDeclarations flag is\n            // set in the mode\n            // The tuple type means: (<stmt name>, <type>, <diagnosis>, <order>, <hide>)\n            val typerResults: Ls[(Str, Ls[Str], Ls[Str], Bool, Bool)] = newDefsResults getOrElse stmts.map { stmt =>\n              // Because diagnostic lines are after the typing results,\n              // we need to cache the diagnostic blocks and add them to the\n              // `typerResults` buffer after the statement has been processed.\n              val diagnosticLines = mutable.Buffer.empty[Str]\n              // We put diagnosis to the buffer in the following `Typer` routines.\n              val raiseToBuffer: Raise = d => {\n                report(d :: Nil, diagnosticLines += _)\n              }\n              // Typing results are before diagnostic messages in the subsumption case.\n              // We use this flag to prevent too much changes in PR #150.\n              var typeBeforeDiags = false\n              val typingResults: Opt[(Str, Ls[Str])] = stmt match {\n                // statement only declares a new term with its type\n                // but does not give a body/definition to it\n                case Def(isrec, nme, R(PolyType(tps, rhs)), isByname) =>\n                  typer.dbg = mode.dbg\n                  \n                  implicit val prov: typer.TP = typer.NoProv // TODO\n                  implicit val r: Raise = raise\n                  \n                  val ty_sch = ctx.poly { ctx =>\n                    typer.typeType(rhs)(ctx, raise, vars = tps.collect {\n                        case L(tp: TypeName) => tp.name -> typer.freshVar(typer.noProv/*FIXME*/, N)(1)\n                      }.toMap)\n                  }\n                  \n                  ctx += nme.name -> typer.VarSymbol(ty_sch, nme)\n                  declared += nme.name -> ty_sch\n                  val exp = getType(ty_sch, N)\n                  if (mode.generateTsDeclarations) tsTypegenCodeBuilder.addTypeGenTermDefinition(exp, Some(nme.name))\n                  S(nme.name -> (s\"${nme.name}: ${exp.show(newDefs)}\" :: Nil))\n                  \n                // statement is defined and has a body/definition\n                case d @ Def(isrec, nme, L(rhs), isByname) =>\n                  typer.dbg = mode.dbg\n                  val ty_sch = typer.typeLetRhs2(isrec, nme.name, rhs)(ctx, raiseToBuffer, vars = Map.empty)\n                  val exp = getType(ty_sch, S(true))\n                  // statement does not have a declared type for the body\n                  // the inferred type must be used and stored for lookup\n                  S(nme.name -> (declared.get(nme.name) match {\n                    // statement has a body but it's type was not declared\n                    // infer it's type and store it for lookup and type gen\n                    case N =>\n                      ctx += nme.name -> typer.VarSymbol(ty_sch, nme)\n                      if (mode.generateTsDeclarations) tsTypegenCodeBuilder.addTypeGenTermDefinition(exp, Some(nme.name))\n                      s\"${nme.name}: ${exp.show(newDefs)}\" :: Nil\n                      \n                    // statement has a body and a declared type\n                    // both are used to compute a subsumption (What is this??)\n                    // the inferred type is used to for ts type gen\n                    case S(sign) =>\n                      ctx += nme.name -> typer.VarSymbol(sign, nme)\n                      val sign_exp = getType(sign, S(false))\n                      typer.dbg = mode.dbg\n                      typer.subsume(ty_sch, sign)(ctx, raiseToBuffer, typer.TypeProvenance(d.toLoc, \"def definition\"))\n                      if (mode.generateTsDeclarations) tsTypegenCodeBuilder.addTypeGenTermDefinition(exp, Some(nme.name))\n                      typeBeforeDiags = true\n                      exp.show(newDefs) :: s\"  <:  ${nme.name}:\" :: sign_exp.show(newDefs) :: Nil\n                  }))\n                case desug: DesugaredStatement =>\n                  typer.dbg = mode.dbg\n                  typer.typeStatement(desug, allowPure = true)(ctx, raiseToBuffer, Map.empty, genLambdas = true) match {\n                    case R(binds) =>\n                      binds.map { case nme -> pty =>\n                        val ptType = getType(pty, S(true))\n                        ctx += nme -> typer.VarSymbol(pty, Var(nme))\n                        if (mode.generateTsDeclarations) tsTypegenCodeBuilder.addTypeGenTermDefinition(ptType, Some(nme))\n                        nme -> (s\"$nme: ${ptType.show(newDefs)}\" :: Nil)\n                      }\n                    \n                    // statements for terms that compute to a value\n                    // and are not bound to a variable name\n                    case L(pty) =>\n                      val exp = getType(pty, S(true))\n                      S(if (exp =/= TypeName(\"unit\")) {\n                        val res = \"res\"\n                        ctx += res -> typer.VarSymbol(pty, Var(res))\n                        if (mode.generateTsDeclarations) tsTypegenCodeBuilder.addTypeGenTermDefinition(exp, None)\n                        res -> (s\"res: ${exp.show(newDefs)}\" :: Nil)\n                      } else (\n                        \"\" -> Nil\n                      ))\n                }\n              }\n              typingResults match {\n                case N => (\"\", Nil, diagnosticLines.toList, false, false)\n                case S(name -> typingLines) =>\n                  (name, typingLines, diagnosticLines.toList, typeBeforeDiags, false)\n              }\n            }\n            \n            \n            if (occursCheck) {\n              typer.dbg = mode.dbg\n              val tvs = typer.createdTypeVars.toList\n              \n              implicit val _ctx: typer.Ctx = ctx // Mostly for `typer.AliasOf`\n              \n              // if (mode.dbg)\n              //   output(s\"REC? ${\n              //     tvs.map(tv => tv -> tv.isRecursive_$(omitTopLevel = true)(ctx))\n              //       .mkString(\" \")}\")\n              \n              // * Does not keep track of recursion polarity:\n              // val recs = tvs.filter(_.isRecursive_$(omitTopLevel = true)(ctx))\n              \n              val recs = tvs.flatMap { tv =>\n                val fromLB = tv.lbRecOccs_$(omitIrrelevantVars = true) match {\n                  case S(pol @ (S(true) | N)) => (tv, pol) :: Nil\n                  case _ => Nil\n                }\n                val fromUB = tv.ubRecOccs_$(omitIrrelevantVars = true) match {\n                  case S(pol @ (S(false) | N)) => (tv, pol) :: Nil\n                  case _ => Nil\n                }\n                fromLB ::: fromUB\n              }\n              \n              if (mode.dbg) output(s\"RECs: ${recs.mkString(\" \")}\")\n              \n              val withLocs = recs.filter(_._1.prov.loco.isDefined)\n              \n              withLocs.find {\n                case (typer.AliasOf(typer.AssignedVariable(_)), _) => false\n                case _ => true\n              }.orElse(withLocs.headOption).orElse(recs.headOption).foreach { case (tv, pol) =>\n                import Message._\n                if (mode.dbg) output(\"REC: \" + tv + tv.showBounds)\n                report(ErrorReport(\n                  msg\"Inferred recursive type: ${\n                    getType(tv, pol = pol, removePolarVars = false).show(newDefs)\n                  }\" -> tv.prov.loco :: Nil, newDefs) :: Nil)\n              }\n              \n              typer.dbg = false\n            }\n            \n            typer.createdTypeVars.clear()\n            \n            \n            import JSTestBackend._\n            \n            val executionResults: Result \\/ Ls[(ReplHost.Reply, Str)] = if (!allowTypeErrors &&\n                file.ext =:= \"mls\" && !mode.noGeneration && !noJavaScript) {\n              import codeGenTestHelpers._\n              val pp = \n                postTypingProcess(mode, basePath, testName, TypingUnit(p.tops), output) match {\n                  case Some(stmts) => Pgrm(stmts.entities)\n                  case _ => p\n                }\n              backend(p, mode.allowEscape, newDefs && newParser, prettyPrintQQ) match {\n                case testCode @ TestCode(prelude, queries) => {\n                  // Display the generated code.\n                  if (mode.showGeneratedJS) showGeneratedCode(testCode)\n                  // Execute code.\n                  if (!mode.noExecution) {\n                    val preludeReply = if (prelude.isEmpty) N else S(host.execute(prelude.mkString(\" \")))\n                    preludeReply match {\n                      case S(ue: ReplHost.Unexecuted) => R((ue, \"\") :: Nil)\n                      case S(err: ReplHost.Error) => R((err, \"\") :: Nil)\n                      case _ => {\n                        if (mode.showRepl) showReplPrelude(prelude, preludeReply, blockLineNum)\n                        val replies = queries.map {\n                          case CodeQuery(preludeLines, codeLines, resultName) =>\n                            host.query(preludeLines.mkString, codeLines.mkString, resultName)\n                          case AbortedQuery(reason) => (ReplHost.Unexecuted(reason), \"\")\n                          case EmptyQuery => (ReplHost.Empty, \"\")\n                        }\n                        if (mode.showRepl) showReplContent(queries, replies)\n                        R(replies)\n                      }\n                    }\n                  } else {\n                    L(ResultNotExecuted)\n                  }\n                }\n                case t => L(t)\n              }\n            } else {\n              L(ResultNotExecuted)\n            }\n\n            def outputLog(log: String): Unit = {\n              val loglines = log.split('\\n').iterator.filter(_.nonEmpty)\n              if (loglines.nonEmpty) {\n                output(\"// Output\")\n                loglines.foreach(output)\n              }\n            }\n\n            def checkReply(\n                replyQueue: mutable.Queue[(ReplHost.Reply, Str)],\n                prefixLength: Int,\n                hide: Boolean, // Show nothing except errors if `hide` is true.\n                errorOnly: Boolean\n            ): Unit = {\n              val indent = \" \" * prefixLength\n              replyQueue.headOption.foreach { case (head, log) =>\n                head match {\n                  case ReplHost.Error(isSyntaxError, content) =>\n                    // We don't expect type errors nor FIXME.\n                    if (!mode.expectTypeErrors && !mode.fixme) {\n                      // We don't expect code generation errors and it is.\n                      if (!mode.expectCodeGenErrors && isSyntaxError)\n                        { output(\"TEST CASE FAILURE: There was an unexpected codegen error\"); failures += blockLineNum }\n                      // We don't expect runtime errors and it's a runtime error.\n                      if (!mode.expectRuntimeErrors && !allowRuntimeErrors && !isSyntaxError)\n                        { output(\"TEST CASE FAILURE: There was an unexpected runtime error\"); failures += blockLineNum }\n                    }\n                    if (isSyntaxError) {\n                      // If there is a syntax error in the generated code,\n                      // it should be a code generation error.\n                      output(\"Syntax error:\")\n                      totalCodeGenErrors += 1\n                    } else { // Otherwise, it is a runtime error.\n                      output(\"Runtime error:\")\n                      totalRuntimeErrors += 1\n                    }\n                    content.linesIterator.foreach { s => output(\"  \" + s) }\n                  case ReplHost.Unexecuted(reason) if (!hide) =>\n                    output(indent + \"= <no result>\")\n                    output(indent + \"  \" + reason)\n                  case ReplHost.Result(result, _) if (!errorOnly && !hide) =>\n                    result.linesIterator.zipWithIndex.foreach { case (line, i) =>\n                      if (i =:= 0) output(indent + \"= \" + line)\n                      else output(indent + \"  \" + line)\n                    }\n                  case ReplHost.Empty if (!errorOnly && !hide) =>\n                    output(indent + \"= <missing implementation>\")\n                  case _ => ()\n                }\n                outputLog(log)\n                replyQueue.dequeue()\n              }\n            }\n            \n            // If code generation fails, show the error message.\n            executionResults match {\n              case R(replies) =>\n                val replyQueue = mutable.Queue.from(replies)\n                if (typerResults.isEmpty)\n                  checkReply(replyQueue, 0, false, true)\n                else {\n                  typerResults.foreach { case (name, typingLines, diagnosticLines, typeBeforeDiags, hide) =>\n                    if (!hide) {\n                      if (typeBeforeDiags) {\n                        typingLines.foreach(output)\n                        diagnosticLines.foreach(output)\n                      } else {\n                        diagnosticLines.foreach(output)\n                        typingLines.foreach(output)\n                      }\n                    }\n                    checkReply(replyQueue, name.length, hide, false)\n                  }\n                }\n              case L(other) =>\n                // Print type checking results first.\n                if (!newDefs) typerResults.foreach { case (_, typingLines, diagnosticLines, typeBeforeDiags, _) =>\n                  if (typeBeforeDiags) {\n                    typingLines.foreach(output)\n                    diagnosticLines.foreach(output)\n                  } else {\n                    diagnosticLines.foreach(output)\n                    typingLines.foreach(output)\n                  }\n                }\n                other match {\n                  case _: TestCode => () // Impossible case.\n                  case e @ IllFormedCode(message) =>\n                    totalCodeGenErrors += 1\n                    if (!mode.expectCodeGenErrors && !mode.fixme && !mode.expectTypeErrors)\n                      failures += blockLineNum\n                    output(\"Code generation encountered an error:\")\n                    output(s\"  ${message}\")\n                  case Unimplemented(message) =>\n                    output(\"Unable to execute the code:\")\n                    output(s\"  ${message}\")\n                  // case UnexpectedCrash(name, message) =>\n                  //   if (!mode.fixme)\n                  //     failures += blockLineNum\n                  //   output(\"Code generation crashed:\")\n                  //   output(s\"  $name: $message\")\n                  case ResultNotExecuted => ()\n                }\n            }\n            // generate typescript typegen block\n            if (mode.generateTsDeclarations) outputSourceCode(tsTypegenCodeBuilder.toSourceCode())\n            \n            if (mode.stats) {\n              val (co, an, su, ty) = typer.stats\n              output(s\"constrain calls  : \" + co)\n              output(s\"annoying  calls  : \" + an)\n              output(s\"subtyping calls  : \" + su)\n              // output(s\"constructed types: \" + ty)\n            }\n            \n            if (mode.expectParseErrors && totalParseErrors =:= 0)\n              { output(\"TEST CASE FAILURE: There was an unexpected lack of parse error\"); failures += blockLineNum }\n            if (mode.expectTypeErrors && totalTypeErrors =:= 0)\n              { output(\"TEST CASE FAILURE: There was an unexpected lack of type error\"); failures += blockLineNum }\n            if (mode.expectCompileErrors && totalCompileErrors =:= 0)\n              { output(\"TEST CASE FAILURE: There was an unexpected lack of compilation error\"); failures += blockLineNum }\n            if (mode.expectWarnings && totalWarnings =:= 0)\n              { output(\"TEST CASE FAILURE: There was an unexpected lack of warning\"); failures += blockLineNum }\n            if (mode.expectCodeGenErrors && totalCodeGenErrors =:= 0)\n              { output(\"TEST CASE FAILURE: There was an unexpected lack of codegen error\"); failures += blockLineNum }\n            if (mode.expectRuntimeErrors && totalRuntimeErrors =:= 0)\n              { output(\"TEST CASE FAILURE: There was an unexpected lack of runtime error\"); failures += blockLineNum }\n        } catch {\n          case oh_noes: ThreadDeath => throw oh_noes\n          case err: Throwable =>\n            if (!mode.fixme)\n              failures += allLines.size - lines.size\n            // err.printStackTrace(out)\n            output(\"/!!!\\\\ Uncaught error: \" + err +\n              err.getStackTrace().take(\n                if (mode.fullExceptionStack) Int.MaxValue\n                else if (mode.fixme || err.isInstanceOf[StackOverflowError]) 0\n                else 10\n              ).map(\"\\n\" + \"\\tat: \" + _).mkString)\n        } finally {\n          typer.dbg = false\n          typer.verbose = false\n        }\n        rec(lines.drop(block.size), mode)\n      case Nil =>\n    }\n\n    try rec(allLines, defaultMode) finally {\n      out.close()\n      if (hostCreated) host.terminate()\n    }\n    val testFailed = failures.nonEmpty || unmergedChanges.nonEmpty\n    val result = strw.toString\n    val endTime = System.nanoTime()\n    val timeStr = (((endTime - beginTime) / 1000 / 100).toDouble / 10.0).toString\n    val testColor = if (testFailed) Console.RED else Console.GREEN\n    \n    val resStr = s\"${\" \" * (35 - testStr.length)}${testColor}${\n      \" \" * (6 - timeStr.length)}$timeStr  ms${Console.RESET}\"\n    \n    if (inParallel) println(s\"${Console.CYAN}Processed${Console.RESET}  $testStr$resStr\")\n    else println(resStr)\n    \n    if (result =/= fileContents) {\n      println(s\"! Updated $file\")\n      os.write.over(file, result)\n    }\n    \n    if (testFailed)\n      if (unmergedChanges.nonEmpty)\n        fail(s\"Unmerged non-output changes around: \" + unmergedChanges.map(\"\\n\\t\"+file.segments.toList.last+\":\"+_).mkString(\", \"))\n      else fail(s\"Unexpected diagnostics (or lack thereof) at: \" + failures.distinct.map(\"\\n\\t\"+file.segments.toList.last+\":\"+_).mkString(\", \"))\n    \n  }}\n}\n\nobject DiffTests {\n  \n  val pwd: Path = os.pwd\n  \n  lazy val State = new State(pwd/\"shared\"/\"src\"/\"test\"/\"diff\")\n  \n  class State(val dir: Path) {\n      \n    val TimeLimit: Span =\n      if (sys.env.contains(\"CI\")) Span(60, Seconds)\n      else Span(30, Seconds)\n    \n    val allFiles: IndexedSeq[Path] = os.walk(dir).filter(_.toIO.isFile)\n    \n    val validExt: Set[String] = Set(\"fun\", \"mls\")\n    \n    // Aggregate unstaged modified files to only run the tests on them, if there are any\n    val modified: Set[os.RelPath] =\n      try os.proc(\"git\", \"status\", \"--porcelain\", dir).call().out.lines().iterator.flatMap { gitStr =>\n        println(\" [git] \" + gitStr)\n        val prefix = gitStr.take(2)\n        val filePath = os.RelPath(gitStr.drop(3))\n        if (prefix =:= \"A \" || prefix =:= \"M \" || prefix =:= \"R \" || prefix =:= \"D \")\n          N // * Disregard modified files that are staged\n        else S(filePath)\n      }.toSet catch {\n        case err: Throwable => System.err.println(\"/!\\\\ git command failed with: \" + err)\n        Set.empty\n      }\n    \n    // private def filter(name: Str): Bool =\n    def filter(file: os.RelPath): Bool =\n      modified(file) || modified.isEmpty\n    \n  }\n  \n  object DebugUCSFlags {\n    // E.g. \"ducs\", \"ducs:foo\", \"ducs:foo,bar\", \"ducs:a.b.c,foo\"\n    private val pattern = \"^ducs(?::(\\\\s*(?:[A-Za-z\\\\.-]+)(?:,\\\\s*[A-Za-z\\\\.-]+)*))?$\".r\n    def unapply(flagsString: Str): Opt[Set[Str]] =\n      flagsString match {\n        case \"ducs\" => S(Set.empty)\n        case pattern(flags) => Option(flags).map(_.split(\",\\\\s*\").toSet)\n        case _ => N\n      }\n  }\n}\n"
  },
  {
    "path": "shared/src/test/scala/mlscript/NodeTest.scala",
    "content": "package mlscript\n\nclass NodeTests extends org.scalatest.funsuite.AnyFunSuite {\n  \n  test(\"node version\") {\n    \n    val v = os.proc(\"node\", \"-v\").call().out.lines().head\n    \n    println(s\"Detected node version: \" + v)\n    \n    assert(\n          v.startsWith(\"v16.14\")\n      ||  v.startsWith(\"v16.15\")\n      ||  v.startsWith(\"v16.16\")\n      ||  v.startsWith(\"v16.17\")\n      ||  v.startsWith(\"v17\")\n      ||  v.startsWith(\"v18\")\n      ||  v.startsWith(\"v19\")\n      ||  v.startsWith(\"v20\")\n      ||  v.startsWith(\"v21\")\n      ||  v.startsWith(\"v22\")\n    )\n    \n  }\n  \n}\n"
  },
  {
    "path": "shared/src/test/scala/mlscript/ReplHost.scala",
    "content": "package mlscript\n\nimport mlscript.utils._, shorthands._\n\n/**\n * A helper class to manipulate an interactive Node.js process.\n */\nfinal case class ReplHost() {\n  import java.io.{BufferedWriter, BufferedReader, InputStreamReader, OutputStreamWriter}\n  private val builder = new java.lang.ProcessBuilder()\n  // `--interactive` always enters the REPL even if stdin is not a terminal\n  builder.command(\"node\", \"--interactive\")\n  private val proc = builder.start()\n\n  private val stdin = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream))\n  private val stdout = new BufferedReader(new InputStreamReader(proc.getInputStream))\n  private val stderr = new BufferedReader(new InputStreamReader(proc.getErrorStream))\n\n  // Skip the welcome message.\n  collectUntilPrompt()\n  execute(\"console.info = console.error\")\n\n  /**\n   * This function simply collect output from Node.js until meet `\"\\n> \"`.\n   * It is useful to skip the welcome message and collect REPL reply from\n   * interactive Node.js. It also filters out syntax errors.\n   * \n   * @return when there are syntax errors, returns `Error` where `syntax` is \n   *         `true`; otherwise, returns `Result`\n   */\n  private def collectUntilPrompt(): ReplHost.Reply = {\n    val buffer = new StringBuilder()\n    while (!buffer.endsWith(\"\\n> \")) {\n      val c = stdout.read()\n      if (c === -1) lastWords(s\"ReplHost could not read more from NodeJS stdout.\")\n      buffer.append(c.toChar)\n    }\n    // Remove the trailing `\"\\n> \"`\n    buffer.delete(buffer.length - 3, buffer.length)\n    val reply = buffer.toString()\n    reply.linesIterator.find(_.startsWith(ReplHost.syntaxErrorHead)) match {\n      case None => reply.linesIterator.find(_.startsWith(ReplHost.uncaughtErrorHead)) match {\n        case None => ReplHost.Result(reply, None)\n        case Some(uncaughtErrorLine) => {\n          val message = uncaughtErrorLine.substring(ReplHost.uncaughtErrorHead.length)\n          ReplHost.Error(false, message)\n        }\n      }\n      case Some(syntaxErrorLine) =>\n        val message = syntaxErrorLine.substring(ReplHost.syntaxErrorHead.length)\n        ReplHost.Error(true, message)\n    }\n  }\n\n  private def consumeStderr(): String = {\n    val buffer = new StringBuilder()\n    while (stderr.ready())\n      buffer.append(stderr.read().toChar)\n    buffer.toString()\n  }\n\n  /**\n   * Parse query results from collected output from Node.js.\n   * \n   * - If there is line begins with `\"Uncaught SyntaxError: \"`, returns\n   *   the syntax error indicated in that line.\n   * - If character `0x200B` presents in the output, returns the trimmed\n   *   error message.\n   * - Otherwise, returns the result as a successfully reply.\n   */\n  private def parseQueryResult(): ReplHost.Reply = {\n    collectUntilPrompt().map { reply =>\n      // Find error boundaries.\n      val begin = reply.indexOf(0x200b)\n      val end = reply.lastIndexOf(0x200b)\n      // If there is an error, returns `ReplHost.Error`.\n      if (begin >= 0 && end >= 0)\n        // `console.log` inserts a space between every two arguments,\n        // so + 1 and - 1 is necessary to get correct length.\n        ReplHost.Error(false, reply.substring(begin + 1, end))\n      else\n        ReplHost.Result(reply, None)\n    }\n  }\n\n  /**\n    * Send code to Node.js process.\n    *\n    * @param code the code to execute\n    */\n  private def send(code: Str): Unit = {\n    stdin.write(if (code endsWith \"\\n\") code else code + \"\\n\")\n    stdin.flush()\n  }\n\n  /**\n    * Send code to the Node.js process.\n    *\n    * @param prelude the prelude code\n    * @param code the main code\n    * @param res the result identifier name\n    * @return\n    */\n  def query(prelude: Str, code: Str, res: Str): (ReplHost.Reply, Str) = {\n    // For empty queries, returns empty.\n    if (prelude.isEmpty && code.isEmpty)\n      (ReplHost.Empty, \"\")\n    else {\n      // Warp the code with `try`-`catch` block.\n      val wrapped = s\"$prelude try { $code } catch (e) { console.log('\\\\u200B' + e + '\\\\u200B'); }\"\n      // Send the code\n      send(wrapped)\n      // If succeed, retrieve the result.\n      (parseQueryResult().map { intermediate =>\n        // Since the result might not be the result of the expression, we need\n        // to retrieve the value again.\n        send(res match {\n          case \"res\" => res\n          case _     => s\"globalThis[\\\"${res}\\\"]\"\n        })\n        parseQueryResult().map { result =>\n          // Add the intermediate result to the reply.\n          ReplHost.Result(result, Some(intermediate))\n        }\n      }, consumeStderr())\n    }\n  }\n\n  /**\n    * Execute class and function declarations.\n    *\n    * @param code the code to execute\n    * @return\n    */\n  def execute(code: Str): ReplHost.Reply = {\n    send(code)\n    collectUntilPrompt()\n  }\n\n  /**\n    * Kills the Node.js process.\n    */\n  def terminate(): Unit = proc.destroy()\n}\n\nobject ReplHost {\n\n  /**\n    * The syntax error beginning text from Node.js.\n    */\n  private val syntaxErrorHead = \"Uncaught SyntaxError: \"\n  private val uncaughtErrorHead = \"Uncaught \"\n\n  /**\n    * The base class of all kinds of REPL replies.\n    */\n  sealed abstract class Reply {\n\n    /**\n      * Maps the successful part. Like `Option[T].map`.\n      *\n      * @param f the function over\n      * @return\n      */\n    def map(f: Str => Reply): Reply\n  }\n\n  /**\n    * Represents a successful reply from Node.js.\n    *\n    * @param content the reply content, i.e. the final result\n    * @param intermediate the intermediate evaluation results\n    */\n  final case class Result(content: Str, intermediate: Opt[Str]) extends Reply {\n    override def map(f: Str => Reply): Reply = f(content)\n    override def toString(): Str = s\"[success] $content\"\n  }\n\n  /**\n    * If the query is `Empty`, we will receive this.\n    */\n  final object Empty extends Reply {\n    override def map(f: Str => Reply): Reply = this\n    override def toString(): Str = \"[empty]\"\n  }\n\n  /**\n    * If the query is `Unexecuted`, we will receive this.\n    * @param message the error message\n    */\n  final case class Unexecuted(message: Str) extends Reply {\n    override def map(f: Str => Reply): Reply = this\n    override def toString(): Str = s\"[unexecuted] $message\"\n  }\n\n  /**\n    * If the `ReplHost` captured errors, it will response with `Error`.\n    * @param syntax if `true`, this is a syntax error; otherwise, this is a\n    *               runtime error\n    * @param message the error message\n    */\n  final case class Error(syntax: Bool, message: Str) extends Reply {\n    override def map(f: Str => Reply): Reply = this\n    override def toString(): Str =\n      if (syntax)\n        s\"[syntax error] $message\"\n      else\n        s\"[runtime error] $message\"\n  }\n}\n"
  },
  {
    "path": "ts/dummy.ts",
    "content": "// This is just to work around vscode being overly needy (it reports errors in 'tsconfig.json' otherwise).\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/JSWriter.scala",
    "content": "package ts2mls\n\nimport scala.scalajs.js\nimport js.Dynamic.{global => g}\nimport js.DynamicImplicits._\nimport mlscript.utils._\n\nclass JSWriter(filename: String) {\n  import JSWriter._\n  \n  // Create an empty file if it does not exists.\n  if (!fs.existsSync(filename)) fs.writeFileSync(filename, \"\")\n\n  // r+: Open file for reading and writing. An exception occurs if the file does not exist.\n  // See https://nodejs.org/api/fs.html#file-system-flags to get more details.\n  private val out = fs.openSync(filename, \"r+\")\n  \n  private var fileSize = 0 // how many bytes we've written in the file\n  private var needTruncate = false\n\n  writeln(\":NewDefs\\n:ParseOnly\")\n\n  def writeln(str: String) = {\n    val strln = str + \"\\n\"\n    val buffer = createBuffer(strln.length)\n    fs.readSync(out, buffer, 0, strln.length)\n    \n    // override when the content is different\n    if (strln =/= buffer.toString()) {\n      fs.writeSync(out, strln, fileSize) // `fileSize` is the offset from the beginning of the file\n      needTruncate = true // if the file has been modified, we need to truncate the file to keep it clean\n    }\n\n    fileSize += strln.length\n  }\n\n  def close() = {\n    if (needTruncate) fs.truncateSync(out, fileSize) // remove other content to keep the file from chaos\n\n    fs.closeSync(out)\n  }\n}\n\nobject JSWriter {\n  private val fs = g.require(\"fs\") // must use fs module to manipulate files in JS\n\n  def apply(filename: String) = new JSWriter(filename)\n\n  private def createBuffer(length: Int) = g.Buffer.alloc(length)\n}\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/TSCompilerInfo.scala",
    "content": "package ts2mls\n\nimport scala.scalajs.js\nimport js.Dynamic.{global => g}\nimport js.DynamicImplicits._\nimport js.JSConverters._\nimport ts2mls.types._\n\nobject TypeScript {\n  private val ts: js.Dynamic = try g.require(\"typescript\") catch {\n    case _ : Throwable => {\n      System.err.println(\"Cannot find typescript in the current directory. Please install by running \\\"npm install\\\".\")\n      val process = g.require(\"process\")\n      process.exit(-1)\n    }\n  }\n\n  val typeFlagsEnumLike = ts.TypeFlags.EnumLike\n  val typeFlagsObject = ts.TypeFlags.Object\n  val typeFlagsTypeParameter = ts.TypeFlags.TypeParameter\n  val syntaxKindPrivate = ts.SyntaxKind.PrivateKeyword\n  val syntaxKindProtected = ts.SyntaxKind.ProtectedKeyword\n  val syntaxKindStatic = ts.SyntaxKind.StaticKeyword\n  val objectFlagsAnonymous = ts.ObjectFlags.Anonymous\n  val symbolFlagsOptional = ts.SymbolFlags.Optional // this flag is only for checking optional members of interfaces\n\n  def isToken(node: js.Dynamic) = ts.isToken(node)\n  def isClassDeclaration(node: js.Dynamic) = ts.isClassDeclaration(node)\n  def isInterfaceDeclaration(node: js.Dynamic) = ts.isInterfaceDeclaration(node)\n  def isFunctionLike(node: js.Dynamic) = ts.isFunctionLike(node)\n  def isModuleDeclaration(node: js.Dynamic) = ts.isModuleDeclaration(node)\n  def isArrayTypeNode(node: js.Dynamic) = ts.isArrayTypeNode(node)\n  def isTupleTypeNode(node: js.Dynamic) = ts.isTupleTypeNode(node)\n  def isTypeAliasDeclaration(node: js.Dynamic) = ts.isTypeAliasDeclaration(node)\n  def isObjectLiteralExpression(node: js.Dynamic) = ts.isObjectLiteralExpression(node)\n  def isLiteralTypeNode(node: js.Dynamic) = ts.isLiteralTypeNode(node)\n  def isStringLiteral(node: js.Dynamic) = ts.isStringLiteral(node)\n  def isVariableDeclaration(node: js.Dynamic) = ts.isVariableDeclaration(node)\n\n  def forEachChild(root: js.Dynamic, func: js.Dynamic => Unit) = ts.forEachChild(root, func)\n  def createProgram(filenames: Seq[String]) =\n    ts.createProgram(filenames.toJSArray, js.Dictionary(\"maxNodeModuleJsDepth\" -> 0, \"target\" -> ts.ScriptTarget.ES5, \"module\" -> ts.ModuleKind.CommonJS))\n}\n\nclass TSTypeChecker(checker: js.Dynamic) {\n  def getReturnTypeOfSignature(node: js.Dynamic) = checker.getReturnTypeOfSignature(checker.getSignatureFromDeclaration(node))\n  def getTypeFromTypeNode(node: js.Dynamic) = checker.getTypeFromTypeNode(node)\n  def getTypeOfSymbolAtLocation(sym: js.Dynamic, node: js.Dynamic) = checker.getTypeOfSymbolAtLocation(sym, node)\n  def getPropertiesOfType(tp: js.Dynamic) = checker.getPropertiesOfType(tp)\n\n  def isImplementationOfOverload(node: js.Dynamic) = checker.isImplementationOfOverload(node)\n  def typeToTypeNode(tp: js.Dynamic) = checker.typeToTypeNode(tp)\n  def getTypeArguments(tp: js.Dynamic) = checker.getTypeArguments(tp)\n  def getElementTypeOfArrayType(tp: js.Dynamic) = checker.getElementTypeOfArrayType(tp)\n  def isOptionalParameter(node: js.Dynamic) = checker.isOptionalParameter(node)\n  def getTypeAtLocation(node: js.Dynamic) = checker.getTypeAtLocation(node)\n  def getBaseType(tp: js.Dynamic) = checker.getBaseTypeOfLiteralType(tp)\n}\n\nobject TSTypeChecker {\n  def apply(checker: js.Dynamic) = new TSTypeChecker(checker)\n}\n\nclass TSSymbolObject(sym: js.Dynamic)(implicit checker: TSTypeChecker) extends TSAny(sym) {\n  private lazy val parent = TSSymbolObject(sym.parent)\n  private lazy val flags = sym.flags\n\n  // the first declaration of this symbol\n  // if there is no overloading, there is only one declaration\n  lazy val declaration =\n    if (declarations.isUndefined) TSNodeObject(g.undefined)\n    else declarations.get(0)\n  lazy val escapedName: String = sym.escapedName.toString\n  lazy val declarations = TSNodeArray(sym.declarations)\n  lazy val `type` = TSTypeObject(sym.selectDynamic(\"type\"))\n\n  lazy val isOptionalMember = (flags & TypeScript.symbolFlagsOptional) > 0\n\n  // get the full name of the reference symbol\n  // e.g. class A extends B => class A extends SomeNamespace'B\n  lazy val fullName: String =\n    if (parent.isUndefined || !parent.declaration.isNamespace) escapedName\n    else s\"${parent.fullName}.$escapedName\"\n}\n\nobject TSSymbolObject {\n  def apply(node: js.Dynamic)(implicit checker: TSTypeChecker) = new TSSymbolObject(node)\n}\n\nclass TSNodeObject(node: js.Dynamic)(implicit checker: TSTypeChecker) extends TSAny(node) {\n  private lazy val modifiers = TSTokenArray(node.modifiers)\n\n  lazy val isToken = TypeScript.isToken(node)\n  lazy val isClassDeclaration = TypeScript.isClassDeclaration(node)\n  lazy val isInterfaceDeclaration = TypeScript.isInterfaceDeclaration(node)\n  lazy val isFunctionLike = TypeScript.isFunctionLike(node)\n  lazy val isTypeAliasDeclaration = TypeScript.isTypeAliasDeclaration(node)\n  lazy val isLiteralTypeNode = TypeScript.isLiteralTypeNode(node)\n  lazy val isVariableDeclaration = TypeScript.isVariableDeclaration(node)\n  lazy val isObjectLiteral = !initializer.isUndefined && !initializer.isToken &&\n                             TypeScript.isObjectLiteralExpression(node.initializer)\n\n  // `TypeScript.isModuleDeclaration` works on both namespaces and modules\n  // but namespaces are more recommended, so we merely use `isNamespace` here\n  lazy val isNamespace = TypeScript.isModuleDeclaration(node)\n  lazy val isArrayTypeNode = TypeScript.isArrayTypeNode(node)\n  lazy val isTupleTypeNode = TypeScript.isTupleTypeNode(node)\n  lazy val isImplementationOfOverload = checker.isImplementationOfOverload(node)\n\n  // if a node has an initializer or is marked by a question notation it is optional\n  // e.g. `function f(x?: int) {}`, we can use it directly: `f()`.\n  // in this case, there would be a question token.\n  // e.g. `function f(x: int = 42) {}`, we can use it directly: `f()`.\n  // in this case, the initializer would store the default value and be non-empty.\n  lazy val isOptionalParameter = checker.isOptionalParameter(node)\n  lazy val isStatic = if (modifiers.isUndefined) false\n                     else modifiers.foldLeft(false)((s, t) => t.isStatic)\n\n  lazy val typeNode = TSTypeObject(checker.getTypeFromTypeNode(node))\n  lazy val typeAtLocation = TSTypeObject(checker.getTypeAtLocation(node))\n  lazy val symbol = TSSymbolObject(node.symbol)\n  lazy val parameters = TSNodeArray(node.parameters)\n  lazy val typeParameters = TSNodeArray(node.typeParameters)\n  lazy val constraint = TSTokenObject(node.constraint)\n  lazy val members = TSNodeArray(node.members)\n  lazy val properties = TSNodeArray(node.properties)\n  lazy val types = TSNodeArray(node.types)\n  lazy val heritageClauses = TSNodeArray(node.heritageClauses)\n  lazy val initializer = TSNodeObject(node.initializer)\n  lazy val initToken = TSTokenObject(node.initializer) // for object literal, the initializer is a token.\n  lazy val modifier =\n    if (modifiers.isUndefined) Public\n    else modifiers.foldLeft[TSAccessModifier](Public)(\n      (m, t) => if (t.isPrivate) Private else if (t.isProtected) Protected else m)\n\n  lazy val declarationList = TSNodeObject(node.declarationList)\n  lazy val declarations = TSNodeArray(node.declarations)\n  lazy val declaration =\n    if (declarations.isUndefined) TSNodeObject(g.undefined)\n    else declarations.get(0)\n\n  lazy val locals = TSSymbolMap(node.locals)\n  lazy val returnType = TSTypeObject(checker.getReturnTypeOfSignature(node))\n  lazy val `type` = TSNodeObject(node.selectDynamic(\"type\"))\n\n  lazy val symbolType = TSTypeObject(checker.getTypeOfSymbolAtLocation(node.symbol, node))\n  lazy val literal = TSTokenObject(node.literal)\n  lazy val name = TSIdentifierObject(node.name)\n}\n\nobject TSNodeObject {\n  def apply(node: js.Dynamic)(implicit checker: TSTypeChecker) = new TSNodeObject(node)\n}\n\nclass TSTokenObject(token: js.Dynamic)(implicit checker: TSTypeChecker) extends TSAny(token) {\n  private lazy val kind = token.kind\n\n  lazy val isPrivate = kind == TypeScript.syntaxKindPrivate\n  lazy val isProtected = kind == TypeScript.syntaxKindProtected\n  lazy val isStatic = kind == TypeScript.syntaxKindStatic\n\n  lazy val typeNode = TSTypeObject(checker.getTypeFromTypeNode(token))\n  lazy val text = token.text.toString()\n  lazy val isStringLiteral = TypeScript.isStringLiteral(token)\n}\n\nobject TSTokenObject {\n  def apply(token: js.Dynamic)(implicit checker: TSTypeChecker) = new TSTokenObject(token)\n}\n\nclass TSTypeObject(obj: js.Dynamic)(implicit checker: TSTypeChecker) extends TSAny(obj) {\n  private lazy val flags = obj.flags\n  private lazy val objectFlags = if (IsUndefined(obj.objectFlags)) 0 else obj.objectFlags\n  private lazy val baseType = TSTypeObject(checker.getBaseType(obj))\n\n  lazy val symbol = TSSymbolObject(obj.symbol)\n  lazy val typeArguments = TSTypeArray(checker.getTypeArguments(obj))\n  lazy val intrinsicName: String =\n    if (!IsUndefined(obj.intrinsicName)) obj.intrinsicName.toString\n    else baseType.intrinsicName\n\n  lazy val types = TSTypeArray(obj.types)\n  lazy val properties = TSSymbolArray(checker.getPropertiesOfType(obj))\n  lazy val node = TSNodeObject(checker.typeToTypeNode(obj))\n  lazy val elementTypeOfArray = TSTypeObject(checker.getElementTypeOfArrayType(obj))\n\n  lazy val isTupleType = node.isTupleTypeNode\n  lazy val isArrayType = node.isArrayTypeNode\n  lazy val isEnumType = (flags & TypeScript.typeFlagsEnumLike) > 0\n  lazy val isUnionType = obj.isUnion()\n  lazy val isIntersectionType = obj.isIntersection()\n  lazy val isFunctionLike = node.isFunctionLike\n  lazy val isAnonymous = objectFlags == TypeScript.objectFlagsAnonymous\n  lazy val isTypeParameter = flags == TypeScript.typeFlagsTypeParameter\n  lazy val isObject = flags == TypeScript.typeFlagsObject\n  lazy val isTypeParameterSubstitution = isObject && typeArguments.length > 0\n}\n\nobject TSTypeObject {\n  def apply(obj: js.Dynamic)(implicit checker: TSTypeChecker) = new TSTypeObject(obj)\n}\n\nclass TSIdentifierObject(id: js.Dynamic) extends TSAny(id) {\n  lazy val escapedText: String = id.escapedText.toString()\n}\n\nobject TSIdentifierObject {\n  def apply(id: js.Dynamic) = new TSIdentifierObject(id)\n}\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/TSData.scala",
    "content": "package ts2mls\n\nimport scala.scalajs.js\nimport js.DynamicImplicits._\nimport js.JSConverters._\n\nabstract class TSAny(v: js.Dynamic) {\n  val isUndefined: Boolean = IsUndefined(v)\n}\n\nobject IsUndefined {\n  def apply(v: js.Dynamic): Boolean = js.isUndefined(v)\n}\n\n// array for information object in tsc\nabstract class TSArray[T <: TSAny](arr: js.Dynamic) extends TSAny(arr) {\n  def get(index: Int): T = ???\n  lazy val length = arr.length\n\n  def foldLeft[U](init: U, index: Int = 0)(implicit f: (U, T) => U): U =\n    if (!isUndefined && index < length) foldLeft(f(init, get(index)), index + 1)\n    else init\n\n  def foldLeftIndexed[U](init: U, index: Int = 0)(implicit f: (U, T, Int) => U): U =\n    if (!isUndefined && index < length) foldLeftIndexed(f(init, get(index), index), index + 1)\n    else init\n\n  def foreach(f: T => Unit, index: Int = 0): Unit =\n    if (!isUndefined && index < length) {\n      f(get(index))\n      foreach(f, index + 1)\n    }\n}\n\nclass TSNodeArray(arr: js.Dynamic)(implicit checker: TSTypeChecker) extends TSArray[TSNodeObject](arr) {\n  override def get(index: Int) = TSNodeObject(arr.selectDynamic(index.toString))\n}\n\nobject TSNodeArray {\n  def apply(arr: js.Dynamic)(implicit checker: TSTypeChecker) = new TSNodeArray(arr)\n}\n\nclass TSSymbolArray(arr: js.Dynamic)(implicit checker: TSTypeChecker) extends TSArray[TSSymbolObject](arr) {\n  override def get(index: Int) = TSSymbolObject(arr.selectDynamic(index.toString))\n}\n\nobject TSSymbolArray {\n  def apply(arr: js.Dynamic)(implicit checker: TSTypeChecker) = new TSSymbolArray(arr)\n}\n\nclass TSTokenArray(arr: js.Dynamic)(implicit checker: TSTypeChecker) extends TSArray[TSTokenObject](arr) {\n  override def get(index: Int) = TSTokenObject(arr.selectDynamic(index.toString))\n}\n\nobject TSTokenArray {\n  def apply(arr: js.Dynamic)(implicit checker: TSTypeChecker) = new TSTokenArray(arr)\n}\n\nclass TSTypeArray(arr: js.Dynamic)(implicit checker: TSTypeChecker) extends TSArray[TSTypeObject](arr) {\n  override def get(index: Int) = TSTypeObject(arr.selectDynamic(index.toString))\n}\n\nobject TSTypeArray {\n  def apply(arr: js.Dynamic)(implicit checker: TSTypeChecker) = new TSTypeArray(arr)\n}\n\nclass TSSymbolMap(map: js.Dynamic)(implicit checker: TSTypeChecker) extends TSAny(map) {\n  def foreach(f: TSSymbolObject => Unit): Unit =\n    if (!isUndefined)\n      map.forEach({(s: js.Dynamic) => f(TSSymbolObject(s))})\n}\n\nobject TSSymbolMap {\n  def apply(map: js.Dynamic)(implicit checker: TSTypeChecker) = new TSSymbolMap(map)\n}\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/TSNamespace.scala",
    "content": "package ts2mls\n\nimport scala.collection.mutable.{HashMap, ListBuffer}\nimport types._\nimport mlscript.utils._\n\nclass TSNamespace(name: String, parent: Option[TSNamespace]) {\n  private val subSpace = HashMap[String, TSNamespace]()\n  private val members = HashMap[String, TSType]()\n\n  // write down the order of members\n  // easier to check the output one by one\n  private val order = ListBuffer.empty[Either[String, String]]\n\n  def derive(name: String): TSNamespace =\n    if (subSpace.contains(name)) subSpace(name) // if the namespace has appeared in another file, just return it\n    else {\n      val sub = new TSNamespace(name, Some(this))\n      subSpace.put(name, sub)\n      order += Left(name)\n      sub\n    }\n\n  def put(name: String, tp: TSType): Unit =\n    if (!members.contains(name)) {\n      order += Right(name)\n      members.put(name, tp)\n    }\n    else members.update(name, tp)\n\n  def get(name: String): TSType =\n    members.getOrElse(name,\n      if (!parent.isEmpty) parent.get.get(name) else throw new Exception(s\"member $name not found.\"))\n\n  def containsMember(name: String, searchParent: Boolean = true): Boolean =\n    if (parent.isEmpty) members.contains(name) else (members.contains(name) || (searchParent && parent.get.containsMember(name)))\n\n  def generate(writer: JSWriter, indent: String): Unit =\n    order.toList.foreach((p) => p match {\n      case Left(subName) => {\n        writer.writeln(s\"${indent}module $subName {\")\n        subSpace(subName).generate(writer, indent + \"  \")\n        writer.writeln(s\"$indent}\")\n      }\n      case Right(name) => {\n        val mem = members(name)\n        mem match {\n          case inter: TSIntersectionType => // overloaded functions\n            writer.writeln(Converter.generateFunDeclaration(inter, name)(indent))\n          case f: TSFunctionType =>\n            writer.writeln(Converter.generateFunDeclaration(f, name)(indent))\n          case overload: TSIgnoredOverload =>\n            writer.writeln(Converter.generateFunDeclaration(overload, name)(indent))\n          case _: TSClassType => writer.writeln(Converter.convert(mem)(indent))\n          case TSInterfaceType(name, _, _, _) if (name =/= \"\") =>\n            writer.writeln(Converter.convert(mem)(indent))\n          case _: TSTypeAlias => writer.writeln(Converter.convert(mem)(indent))\n          case _ => writer.writeln(s\"${indent}let $name: ${Converter.convert(mem)(\"\")}\")\n        }\n      }\n    })\n}\n\nobject TSNamespace {\n  def apply() = new TSNamespace(\"\", None) // global namespace\n}\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/TSProgram.scala",
    "content": "package ts2mls\n\nimport scala.scalajs.js\nimport js.DynamicImplicits._\nimport ts2mls.types._\n\nclass TSProgram(filenames: Seq[String]) {\n  private val program = TypeScript.createProgram(filenames)\n\n  // check if files exist\n  filenames.foreach((fn) => if (!program.fileExists(fn)) throw new Exception(s\"file ${fn} doesn't exist.\"))\n\n  val globalNamespace = TSNamespace()\n  \n  implicit val checker: TSTypeChecker = TSTypeChecker(program.getTypeChecker())\n  filenames.foreach(filename => TSSourceFile(program.getSourceFile(filename), globalNamespace))\n\n  def generate(writer: JSWriter): Unit = globalNamespace.generate(writer, \"\")\n}\n\nobject TSProgram {\n  def apply(filenames: Seq[String]) = new TSProgram(filenames)\n}\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/TSSourceFile.scala",
    "content": "package ts2mls\n\nimport scala.scalajs.js\nimport js.DynamicImplicits._\nimport types._\nimport mlscript.utils._\n\nobject TSSourceFile {\n  def apply(sf: js.Dynamic, global: TSNamespace)(implicit checker: TSTypeChecker) =\n    TypeScript.forEachChild(sf, (node: js.Dynamic) => {\n      val nodeObject = TSNodeObject(node)\n      if (!nodeObject.isToken) {\n        if (!nodeObject.symbol.isUndefined) // for functions/classes/interfaces\n          addNodeIntoNamespace(nodeObject, nodeObject.symbol.escapedName)(global)\n        else if (!nodeObject.declarationList.isUndefined) { // for variables\n          val decNode = nodeObject.declarationList.declaration\n          addNodeIntoNamespace(decNode, decNode.symbol.escapedName)(global)\n        }\n      }\n    })\n\n  private def getSubstitutionArguments[T <: TSAny](args: TSArray[T]): List[TSType] =\n    args.foldLeft(List[TSType]())((lst, arg) => arg match {\n      case token: TSTokenObject => lst :+ getObjectType(token.typeNode)\n      case tp: TSTypeObject => lst :+ getObjectType(tp)\n    })\n\n  private def getObjectType(obj: TSTypeObject): TSType =\n    if (obj.isEnumType) TSEnumType\n    else if (obj.isFunctionLike) getFunctionType(obj.symbol.declaration)\n    else if (obj.isTupleType) TSTupleType(getTupleElements(obj.typeArguments))\n    else if (obj.isUnionType) getStructuralType(obj.types, true)\n    else if (obj.isIntersectionType) getStructuralType(obj.types, false)\n    else if (obj.isArrayType) TSArrayType(getObjectType(obj.elementTypeOfArray))\n    else if (obj.isTypeParameterSubstitution) TSSubstitutionType(obj.symbol.escapedName, getSubstitutionArguments(obj.typeArguments))\n    else if (obj.isObject)\n      if (obj.isAnonymous) TSInterfaceType(\"\", getAnonymousPropertiesType(obj.properties), List(), List())\n      else TSReferenceType(obj.symbol.fullName)\n    else if (obj.isTypeParameter) TSTypeParameter(obj.symbol.escapedName)\n    else TSPrimitiveType(obj.intrinsicName)\n\n  // the function `getMemberType` can't process function/tuple type alias correctly\n  private def getTypeAlias(tn: TSNodeObject): TSType =\n    if (tn.isFunctionLike) getFunctionType(tn)\n    else if (tn.isTupleTypeNode) TSTupleType(getTupleElements(tn.typeNode.typeArguments))\n    else getObjectType(tn.typeNode)\n\n  // parse string/numeric literal types. we need to add quotes if it is a string literal\n  private def getLiteralType(tp: TSNodeObject) =\n    TSLiteralType(tp.literal.text, tp.literal.isStringLiteral)\n\n  // parse object literal types\n  private def getObjectLiteralMembers(props: TSNodeArray) =\n    props.foldLeft(Map[String, TSMemberType]())((mp, p) => {\n      mp ++ Map(p.name.escapedText -> TSMemberType(TSLiteralType(p.initToken.text, p.initToken.isStringLiteral)))\n    })\n\n  // get the type of variables in classes/named interfaces/anonymous interfaces\n  private def getMemberType(node: TSNodeObject): TSType = {\n    val res: TSType =\n      if (node.isFunctionLike) getFunctionType(node)\n      else if (node.`type`.isUndefined) getObjectType(node.typeAtLocation)\n      else if (node.`type`.isLiteralTypeNode) getLiteralType(node.`type`)\n      else getObjectType(node.`type`.typeNode)\n    if (node.symbol.isOptionalMember) TSUnionType(res, TSPrimitiveType(\"undefined\"))\n    else res\n  }\n\n  private def getTypeParameters(node: TSNodeObject): List[TSTypeParameter] =\n    node.typeParameters.foldLeft(List[TSTypeParameter]())((lst, tp) =>\n      if (tp.constraint.isUndefined) lst :+ TSTypeParameter(tp.symbol.escapedName, None)\n      else lst :+ TSTypeParameter(tp.symbol.escapedName, Some(getObjectType(tp.constraint.typeNode)))\n    )\n\n  private def getFunctionType(node: TSNodeObject): TSFunctionType = {\n    val pList = node.parameters.foldLeft(List[TSParameterType]())((lst, p) => (\n      // in typescript, you can use `this` to explicitly specifies the callee\n      // but it never appears in the final javascript file\n      if (p.symbol.escapedName === \"this\") lst\n      else if (p.isOptionalParameter)\n        lst :+ TSParameterType(p.symbol.escapedName, TSUnionType(getObjectType(p.symbolType), TSPrimitiveType(\"undefined\")))\n      else lst :+ TSParameterType(p.symbol.escapedName, getObjectType(p.symbolType)))\n    )\n    TSFunctionType(pList, getObjectType(node.returnType), getTypeParameters(node))\n  }\n\n  private def getStructuralType(types: TSTypeArray, isUnion: Boolean): TSType =\n    types.foldLeft[Option[TSType]](None)((prev, cur) => prev match {\n      case None => Some(getObjectType(cur))\n      case Some(p) =>\n        if (isUnion) Some(TSUnionType(p, getObjectType(cur))) else Some(TSIntersectionType(p, getObjectType(cur)))\n    }).get\n\n  private def getTupleElements(elements: TSTypeArray): List[TSType] =\n    elements.foldLeft(List[TSType]())((lst, ele) => lst :+ getObjectType(ele))\n\n  private def getHeritageList(node: TSNodeObject): List[TSType] =\n    node.heritageClauses.foldLeftIndexed(List[TSType]())((lst, h, index) =>\n      lst :+ getObjectType(h.types.get(index).typeNode)\n    )\n\n  private def getClassMembersType(list: TSNodeArray, requireStatic: Boolean): Map[String, TSMemberType] =\n    list.foldLeft(Map[String, TSMemberType]())((mp, p) => {\n      val name = p.symbol.escapedName\n\n      if (name =/= \"__constructor\" && p.isStatic == requireStatic) {\n        val mem =\n          if (!p.isStatic) getMemberType(p)\n          else parseMembers(name, p.initializer, true)\n\n        mem match {\n          case func: TSFunctionType => {\n            if (!mp.contains(name)) mp ++ Map(name -> TSMemberType(func, p.modifier))\n            else { // deal with functions overloading\n              val old = mp(name)\n              val res = old.base match {\n                case f @ TSFunctionType(_, _, tv) =>\n                  if (!tv.isEmpty || !func.typeVars.isEmpty) TSIgnoredOverload(func, name)\n                  else if (!p.isImplementationOfOverload) TSIntersectionType(f, func)\n                  else f\n                case int: TSIntersectionType =>\n                  if (!func.typeVars.isEmpty) TSIgnoredOverload(func, name)\n                  else if (!p.isImplementationOfOverload) TSIntersectionType(int, func)\n                  else int\n                case TSIgnoredOverload(_, name) => TSIgnoredOverload(func, name) // the implementation is always after declarations\n                case _ => old.base\n              }\n\n              mp.removed(name) ++ Map(name -> TSMemberType(res, p.modifier))\n            }\n          }\n          case _ => mp ++ Map(name -> TSMemberType(mem, p.modifier))\n        }\n      }\n      else mp\n    })\n\n  private def getConstructorList(members: TSNodeArray): List[TSParameterType] =\n    members.foldLeft(List[TSParameterType]())((lst, mem) => {\n      val name = mem.symbol.escapedName\n\n      if (name =/= \"__constructor\") lst\n      else mem.parameters.foldLeft(List[TSParameterType]())((res, p) =>\n        res :+ TSParameterType(p.symbol.escapedName, getMemberType(p)))\n    })\n\n  private def getInterfacePropertiesType(list: TSNodeArray): Map[String, TSMemberType] =\n    list.foldLeft(Map[String, TSMemberType]())((mp, p) => mp ++ Map(p.symbol.escapedName -> TSMemberType(getMemberType(p))))\n\n  private def getAnonymousPropertiesType(list: TSSymbolArray): Map[String, TSMemberType] =\n    list.foldLeft(Map[String, TSMemberType]())((mp, p) =>\n      mp ++ Map(p.escapedName -> TSMemberType(if (p.`type`.isUndefined) getMemberType(p.declaration) else getObjectType(p.`type`))))\n\n  private def parseMembers(name: String, node: TSNodeObject, isClass: Boolean): TSType =\n    if (isClass)\n      TSClassType(name, getClassMembersType(node.members, false), getClassMembersType(node.members, true),\n        getTypeParameters(node), getHeritageList(node), getConstructorList(node.members))\n    else TSInterfaceType(name, getInterfacePropertiesType(node.members), getTypeParameters(node), getHeritageList(node))\n\n  private def parseNamespaceLocals(map: TSSymbolMap)(implicit ns: TSNamespace) =\n    map.foreach((sym) => {\n      val node = sym.declaration\n      if (!node.isToken)\n        addNodeIntoNamespace(node, sym.escapedName, if (node.isFunctionLike) Some(sym.declarations) else None)\n    })\n\n  private def addFunctionIntoNamespace(fun: TSFunctionType, node: TSNodeObject, name: String)(implicit ns: TSNamespace) =\n    if (!ns.containsMember(name, false)) ns.put(name, fun)\n    else {\n      val old = ns.get(name)\n      val res = old match {\n        case f @ TSFunctionType(_, _, tv) =>\n          if (!tv.isEmpty || !fun.typeVars.isEmpty) TSIgnoredOverload(fun, name)\n          else if (!node.isImplementationOfOverload) TSIntersectionType(f, fun)\n          else f\n        case int: TSIntersectionType =>\n          if (!fun.typeVars.isEmpty) TSIgnoredOverload(fun, name)\n          else if (!node.isImplementationOfOverload) TSIntersectionType(int, fun)\n          else old\n        case TSIgnoredOverload(_, name) => TSIgnoredOverload(fun, name) // the implementation is always after declarations\n        case _ => old\n      }\n      \n      ns.put(name, res)\n    } \n\n  // overload functions in a sub-namespace need to provide an overload array\n  // because the namespace merely exports symbols rather than node objects themselves\n  private def addNodeIntoNamespace(node: TSNodeObject, name: String, overload: Option[TSNodeArray] = None)(implicit ns: TSNamespace) =\n    if (node.isFunctionLike) overload match {\n      case None =>\n        addFunctionIntoNamespace(getFunctionType(node), node, name)\n      case Some(decs) => {\n        decs.foreach((d) =>\n          addFunctionIntoNamespace(getFunctionType(d), d, name)\n        )\n      }\n    }\n    else if (node.isClassDeclaration)\n      ns.put(name, parseMembers(name, node, true))\n    else if (node.isInterfaceDeclaration)\n      ns.put(name, parseMembers(name, node, false))\n    else if (node.isTypeAliasDeclaration)\n      ns.put(name, TSTypeAlias(name, getTypeAlias(node.`type`), getTypeParameters(node)))\n    else if (node.isObjectLiteral)\n      ns.put(name, TSInterfaceType(\"\", getObjectLiteralMembers(node.initializer.properties), List(), List()))\n    else if (node.isVariableDeclaration)\n      ns.put(name, getMemberType(node))\n    else if (node.isNamespace)\n      parseNamespace(node)\n\n  private def parseNamespace(node: TSNodeObject)(implicit ns: TSNamespace): Unit =\n    parseNamespaceLocals(node.locals)(ns.derive(node.symbol.escapedName))\n}\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/types/Converter.scala",
    "content": "package ts2mls.types\n\nimport mlscript.utils._\n\nobject Converter {\n  private val primitiveName = Map[String, String](\n    \"boolean\" -> \"bool\",\n    \"number\" -> \"number\",\n    \"string\" -> \"string\",\n    \"any\" -> \"anything\",\n    \"unknown\" -> \"anything\",\n    \"void\" -> \"unit\",\n    \"null\" -> \"null\",\n    \"undefined\" -> \"undefined\",\n    \"never\" -> \"nothing\",\n    \"object\" -> \"object\",\n    \"true\" -> \"true\",\n    \"false\" -> \"false\"\n  )\n\n  def generateFunDeclaration(tsType: TSType, name: String)(implicit indent: String = \"\"): String = tsType match {\n    case TSFunctionType(params, res, typeVars) => {\n      val pList = if (params.isEmpty) \"\" else params.map(p => s\"${convert(p)(\"\")}\").reduceLeft((r, p) => s\"$r, $p\")\n      val tpList = if (typeVars.isEmpty) \"\" else s\"<${typeVars.map(p => convert(p)(\"\")).reduceLeft((r, p) => s\"$r, $p\")}>\"\n      s\"${indent}fun $name$tpList($pList): ${convert(res)(\"\")}\"\n    }\n    case overload @ TSIgnoredOverload(base, _) => s\"${generateFunDeclaration(base, name)} ${overload.warning}\"\n    case inter: TSIntersectionType => s\"${indent}fun ${name}: ${Converter.convert(inter)}\"\n    case _ => throw new AssertionError(\"non-function type is not allowed.\")\n  }\n\n  def convert(tsType: TSType)(implicit indent: String = \"\"): String = tsType match {\n    case TSPrimitiveType(typeName) => primitiveName(typeName)\n    case TSReferenceType(name) => name\n    case TSFunctionType(params, res, _) =>\n      if (params.length == 0) s\"${primitiveName(\"void\")} => ${convert(res)}\"\n      else\n        params.foldRight(convert(res))((p, f) => s\"(${convert(p.tp)}) => $f\")\n    case TSUnionType(lhs, rhs) => s\"(${convert(lhs)}) | (${convert(rhs)})\"\n    case TSIntersectionType(lhs, rhs) => s\"(${convert(lhs)}) & (${convert(rhs)})\"\n    case TSTypeParameter(name, _) => name // constraints should be translated where the type parameters were created rather than be used\n    case TSTupleType(lst) => s\"[${lst.map(convert).mkString(\", \")}]\"\n    case TSArrayType(element) => s\"MutArray<${convert(element)}>\"\n    case TSEnumType => \"int\"\n    case TSMemberType(base, _) => convert(base) // TODO: support private/protected members\n    case TSInterfaceType(name, members, typeVars, parents) =>\n      convertRecord(s\"trait $name\", members, typeVars, parents, Map(), List())(indent)\n    case TSClassType(name, members, statics, typeVars, parents, cons) =>\n      convertRecord(s\"class $name\", members, typeVars, parents, statics, cons)(indent)\n    case TSSubstitutionType(base, applied) => s\"${base}<${applied.map((app) => convert(app)).reduceLeft((res, s) => s\"$res, $s\")}>\"\n    case overload @ TSIgnoredOverload(base, _) => s\"${convert(base)} ${overload.warning}\"\n    case TSParameterType(name, tp) => s\"${name}: ${convert(tp)}\"\n    case TSTypeAlias(name, ori, tp) =>\n      if (tp.isEmpty) s\"${indent}type $name = ${convert(ori)}\"\n      else s\"${indent}type $name<${tp.map(t => convert(t)).reduceLeft((s, t) => s\"$s, $t\")}> = ${convert(ori)}\"\n    case TSLiteralType(value, isString) => if (isString) s\"\\\"$value\\\"\" else value\n  }\n\n  private def convertRecord(typeName: String, members: Map[String, TSMemberType], typeVars: List[TSTypeParameter],\n    parents: List[TSType], statics: Map[String, TSMemberType], constructorList: List[TSType])(implicit indent: String) = {\n    val allRecs = members.toList.map((m) => m._2.modifier match {\n      case Public =>\n        if (typeName === \"trait \") s\"${m._1}: ${convert(m._2)},\"\n        else m._2.base match {\n          case _: TSFunctionType => s\"${generateFunDeclaration(m._2.base, m._1)(indent + \"  \")}\\n\"\n          case _: TSIgnoredOverload => s\"${generateFunDeclaration(m._2.base, m._1)(indent + \"  \")}\\n\"\n          case _ => s\"${indent}  let ${m._1}: ${convert(m._2)}\\n\"\n        }\n      case _ => \"\" // TODO: deal with private/protected members\n    }) :::\n      statics.toList.map((s) => s._2.modifier match {\n        case Public => s._2.base match {\n          case _: TSClassType => convert(s._2)(indent + \"  \") + \"\\n\"\n          case _ => \"\" // TODO: deal with other static type\n        }\n        case _ => \"\" // TODO: deal with private/protected static members\n      })\n\n    val body = { // members without independent type parameters, translate them directly\n      val lst = allRecs.filter((s) => !s.isEmpty())\n      if (lst.isEmpty) \"{}\"\n      else if (typeName === \"trait \") s\"{${lst.reduceLeft((bd, m) => s\"$bd$m\")}}\"\n      else s\"{\\n${lst.reduceLeft((bd, m) => s\"$bd$m\")}$indent}\"\n    }\n    \n    if (typeName === \"trait \") body // anonymous interfaces\n    else { // named interfaces and classes\n      val constructor =\n        if (constructorList.isEmpty) \"()\"\n        else s\"(${constructorList.map(p => s\"${convert(p)(\"\")}\").reduceLeft((res, p) => s\"$res, $p\")})\"\n\n      val inheritance =\n        if (parents.isEmpty) constructor\n        else parents.foldLeft(s\"$constructor: \")((b, p) => s\"$b${convert(p)}, \").dropRight(2)\n      if (typeVars.isEmpty) s\"${indent}$typeName$inheritance $body\"\n      else\n        s\"${indent}$typeName<${typeVars.map((tv) => tv.name).reduceLeft((p, s) => s\"$p, $s\")}>$inheritance $body\" // TODO: add constraints\n    }\n  }\n}\n"
  },
  {
    "path": "ts2mls/js/src/main/scala/ts2mls/types/TSType.scala",
    "content": "package ts2mls.types\n\nsealed abstract class TSAccessModifier\ncase object Public extends TSAccessModifier\ncase object Private extends TSAccessModifier\ncase object Protected extends TSAccessModifier\n\nsealed abstract class TSType\ncase class TSParameterType(name: String, val tp: TSType) extends TSType // record both parameter's name and parameter's type\ncase class TSMemberType(val base: TSType, val modifier: TSAccessModifier = Public) extends TSType\ncase class TSTypeParameter(val name: String, constraint: Option[TSType] = None) extends TSType\ncase class TSPrimitiveType(typeName: String) extends TSType\ncase class TSReferenceType(name: String) extends TSType\ncase object TSEnumType extends TSType\ncase class TSTupleType(types: List[TSType]) extends TSType\ncase class TSFunctionType(params: List[TSParameterType], res: TSType, val typeVars: List[TSTypeParameter]) extends TSType\ncase class TSArrayType(eleType: TSType) extends TSType\ncase class TSSubstitutionType(base: String, applied: List[TSType]) extends TSType\n\ncase class TSClassType(\n    name: String,\n    members: Map[String, TSMemberType],\n    statics: Map[String, TSMemberType],\n    typeVars: List[TSTypeParameter],\n    parents: List[TSType],\n    constructor: List[TSParameterType]\n  ) extends TSType\n\ncase class TSInterfaceType(\n    name: String,\n    members: Map[String, TSMemberType],\n    typeVars: List[TSTypeParameter],\n    parents: List[TSType],\n  ) extends TSType\n\nsealed abstract class TSStructuralType(lhs: TSType, rhs: TSType, notion: String) extends TSType\ncase class TSUnionType(lhs: TSType, rhs: TSType) extends TSStructuralType(lhs, rhs, \"|\")\ncase class TSIntersectionType(lhs: TSType, rhs: TSType) extends TSStructuralType(lhs, rhs, \"&\")\n\n// ts2mls doesn't support overloading functions with type parameters\n// TSIgnoredOverload is used to store these functions and raise a warning later\n// only the most general overloading form would be stored\ncase class TSIgnoredOverload(base: TSFunctionType, name: String) extends TSType {\n  val warning = s\"/* warning: the overload of function $name is not supported yet. */\"\n}\n\ncase class TSTypeAlias(name: String, original: TSType, tp: List[TSType]) extends TSType\ncase class TSLiteralType(value: String, isString: Boolean) extends TSType\n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Array.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun first(x: MutArray<string>): string\nfun getZero3(): MutArray<number>\nfun first2(fs: MutArray<(number) => number>): (number) => number\nfun doEs(e: MutArray<int>): MutArray<int>\nclass C() {}\ntrait I() {\n  let i: number\n}\nfun doCs(c: MutArray<C>): MutArray<C>\nfun doIs(i: MutArray<I>): MutArray<I>\nfun inter<U, T>(x: MutArray<(U) & (T)>): MutArray<(U) & (T)>\nfun clean(x: MutArray<[string, number]>): MutArray<[string, number]>\nfun translate<T, U>(x: MutArray<T>): MutArray<U>\nfun uu(x: MutArray<((number) | (false)) | (true)>): MutArray<((number) | (false)) | (true)>\nclass Temp<T>() {\n  let x: T\n}\nfun ta(ts: MutArray<Temp<(false) | (true)>>): MutArray<Temp<(false) | (true)>>\nfun tat<T>(ts: MutArray<Temp<T>>): MutArray<Temp<T>>\n//│ |#fun| |first|(|x|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |getZero3|(||)|#:| |MutArray|‹|number|›|↵|#fun| |first2|(|fs|#:| |MutArray|‹|(|number|)| |#=>| |number|›|)|#:| |(|number|)| |#=>| |number|↵|#fun| |doEs|(|e|#:| |MutArray|‹|int|›|)|#:| |MutArray|‹|int|›|↵|#class| |C|(||)| |{||}|↵|#trait| |I|(||)| |{|→|#let| |i|#:| |number|←|↵|}|↵|#fun| |doCs|(|c|#:| |MutArray|‹|C|›|)|#:| |MutArray|‹|C|›|↵|#fun| |doIs|(|i|#:| |MutArray|‹|I|›|)|#:| |MutArray|‹|I|›|↵|#fun| |inter|‹|U|,| |T|›|(|x|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|)|#:| |MutArray|‹|(|U|)| |&| |(|T|)|›|↵|#fun| |clean|(|x|#:| |MutArray|‹|[|string|,| |number|]|›|)|#:| |MutArray|‹|[|string|,| |number|]|›|↵|#fun| |translate|‹|T|,| |U|›|(|x|#:| |MutArray|‹|T|›|)|#:| |MutArray|‹|U|›|↵|#fun| |uu|(|x|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|)|#:| |MutArray|‹|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|›|↵|#class| |Temp|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#fun| |ta|(|ts|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|)|#:| |MutArray|‹|Temp|‹|(|false|)| ||| |(|true|)|›|›|↵|#fun| |tat|‹|T|›|(|ts|#:| |MutArray|‹|Temp|‹|T|›|›|)|#:| |MutArray|‹|Temp|‹|T|›|›|\n//│ Parsed: {fun first: (x: MutArray[string]) -> string; fun getZero3: () -> MutArray[number]; fun first2: (fs: MutArray[number -> number]) -> number -> number; fun doEs: (e: MutArray[int]) -> MutArray[int]; class C() {}; trait I() {let i: number}; fun doCs: (c: MutArray[C]) -> MutArray[C]; fun doIs: (i: MutArray[I]) -> MutArray[I]; fun inter: (x: MutArray[U & T]) -> MutArray[U & T]; fun clean: (x: MutArray[[string, number]]) -> MutArray[[string, number]]; fun translate: (x: MutArray[T]) -> MutArray[U]; fun uu: (x: MutArray[number | false | true]) -> MutArray[number | false | true]; class Temp‹T›() {let x: T}; fun ta: (ts: MutArray[Temp[bool]]) -> MutArray[Temp[bool]]; fun tat: (ts: MutArray[Temp[T]]) -> MutArray[Temp[T]]}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/BasicFunctions.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun hello(): unit\nfun add(x: number, y: number): number\nfun sub(x: number, y: number): number\nfun foo(): number\nfun id(x: anything): anything\nfun odd(x: number): (false) | (true)\nfun isnull(x: anything): (false) | (true)\nfun bar(): anything\nfun nu(n: null): null\nfun un(n: undefined): undefined\nfun fail(): nothing\nfun create(): object\nfun pa(x: number): number\nfun wtf(x: anything): unit\nclass Foooooo() {\n  let ooooooo: number\n}\nfun inn(f: Foooooo): unit\nfun out1(): Foooooo\ntrait Barrrrrrrrr() {\n  let rrrrrrr: number\n}\nfun inn2(b: Barrrrrrrrr): unit\nfun out2(): Barrrrrrrrr\n//│ |#fun| |hello|(||)|#:| |unit|↵|#fun| |add|(|x|#:| |number|,| |y|#:| |number|)|#:| |number|↵|#fun| |sub|(|x|#:| |number|,| |y|#:| |number|)|#:| |number|↵|#fun| |foo|(||)|#:| |number|↵|#fun| |id|(|x|#:| |anything|)|#:| |anything|↵|#fun| |odd|(|x|#:| |number|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |isnull|(|x|#:| |anything|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |bar|(||)|#:| |anything|↵|#fun| |nu|(|n|#:| |#null|)|#:| |#null|↵|#fun| |un|(|n|#:| |#undefined|)|#:| |#undefined|↵|#fun| |fail|(||)|#:| |nothing|↵|#fun| |create|(||)|#:| |object|↵|#fun| |pa|(|x|#:| |number|)|#:| |number|↵|#fun| |wtf|(|x|#:| |anything|)|#:| |unit|↵|#class| |Foooooo|(||)| |{|→|#let| |ooooooo|#:| |number|←|↵|}|↵|#fun| |inn|(|f|#:| |Foooooo|)|#:| |unit|↵|#fun| |out1|(||)|#:| |Foooooo|↵|#trait| |Barrrrrrrrr|(||)| |{|→|#let| |rrrrrrr|#:| |number|←|↵|}|↵|#fun| |inn2|(|b|#:| |Barrrrrrrrr|)|#:| |unit|↵|#fun| |out2|(||)|#:| |Barrrrrrrrr|\n//│ Parsed: {fun hello: () -> unit; fun add: (x: number, y: number) -> number; fun sub: (x: number, y: number) -> number; fun foo: () -> number; fun id: (x: anything) -> anything; fun odd: (x: number) -> bool; fun isnull: (x: anything) -> bool; fun bar: () -> anything; fun nu: (n: null) -> null; fun un: (n: ()) -> (); fun fail: () -> nothing; fun create: () -> object; fun pa: (x: number) -> number; fun wtf: (x: anything) -> unit; class Foooooo() {let ooooooo: number}; fun inn: (f: Foooooo) -> unit; fun out1: () -> Foooooo; trait Barrrrrrrrr() {let rrrrrrr: number}; fun inn2: (b: Barrrrrrrrr) -> unit; fun out2: () -> Barrrrrrrrr}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/ClassMember.d.mls",
    "content": ":NewDefs\n:ParseOnly\nclass Student(s: string, age: number) {\n  let name: string\n  fun isFriend(other: Student): (false) | (true)\n  fun addScore(sub: string, score: number): unit\n  fun getID(): number\n}\nclass Foo<T>() {\n  fun bar(x: T): unit\n}\nclass EZ() {\n  fun inc(x: number): number\n}\nclass Outer() {\n  class Inner() {\n    let a: number\n  }\n}\nclass TTT<T>() {\n  fun ttt(x: T): T\n  fun ttt2(x: T): T\n}\n//│ |#class| |Student|(|s|#:| |string|,| |age|#:| |number|)| |{|→|#let| |name|#:| |string|↵|#fun| |isFriend|(|other|#:| |Student|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |addScore|(|sub|#:| |string|,| |score|#:| |number|)|#:| |unit|↵|#fun| |getID|(||)|#:| |number|←|↵|}|↵|#class| |Foo|‹|T|›|(||)| |{|→|#fun| |bar|(|x|#:| |T|)|#:| |unit|←|↵|}|↵|#class| |EZ|(||)| |{|→|#fun| |inc|(|x|#:| |number|)|#:| |number|←|↵|}|↵|#class| |Outer|(||)| |{|→|#class| |Inner|(||)| |{|→|#let| |a|#:| |number|←|↵|}|←|↵|}|↵|#class| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|↵|#fun| |ttt2|(|x|#:| |T|)|#:| |T|←|↵|}|\n//│ Parsed: {class Student(s: string, age: number,) {let name: string; fun isFriend: (other: Student) -> bool; fun addScore: (sub: string, score: number) -> unit; fun getID: () -> number}; class Foo‹T›() {fun bar: (x: T) -> unit}; class EZ() {fun inc: (x: number) -> number}; class Outer() {class Inner() {let a: number}}; class TTT‹T›() {fun ttt: (x: T) -> T; fun ttt2: (x: T) -> T}}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Dec.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun getName(id: (string) | (number)): string\nfun render(callback: (unit => unit) | (undefined)): string\ntrait Get() {\n  fun __call(id: string): string\n}\nclass Person(name: string, age: number) {\n  fun getName(id: number): string\n}\nmodule OOO {\n}\n//│ |#fun| |getName|(|id|#:| |(|string|)| ||| |(|number|)|)|#:| |string|↵|#fun| |render|(|callback|#:| |(|unit| |#=>| |unit|)| ||| |(|#undefined|)|)|#:| |string|↵|#trait| |Get|(||)| |{|→|#fun| |__call|(|id|#:| |string|)|#:| |string|←|↵|}|↵|#class| |Person|(|name|#:| |string|,| |age|#:| |number|)| |{|→|#fun| |getName|(|id|#:| |number|)|#:| |string|←|↵|}|↵|#module| |OOO| |{|↵|}|\n//│ Parsed: {fun getName: (id: string | number) -> string; fun render: (callback: unit -> unit | ()) -> string; trait Get() {fun __call: (id: string) -> string}; class Person(name: string, age: number,) {fun getName: (id: number) -> string}; module OOO {}}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Enum.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun pass(c: int): (false) | (true)\nfun stop(): int\nfun g(x: int): int\n//│ |#fun| |pass|(|c|#:| |int|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |stop|(||)|#:| |int|↵|#fun| |g|(|x|#:| |int|)|#:| |int|\n//│ Parsed: {fun pass: (c: int) -> bool; fun stop: () -> int; fun g: (x: int) -> int}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Heritage.d.mls",
    "content": ":NewDefs\n:ParseOnly\nclass A() {\n  fun foo(): unit\n}\nclass B(): A {}\nclass C<T>() {\n  fun sett(x: T): unit\n  fun get(): T\n}\nclass D(): C<number> {}\ntrait Wu() {\n  let x: (false) | (true)\n}\nclass WuWu(): Wu {\n  let y: (false) | (true)\n}\ntrait WuWuWu(): WuWu {\n  let z: (false) | (true)\n}\ntrait Never(): WuWuWu {\n  fun w(): nothing\n}\nclass VG<T>() {\n  let x: T\n}\nclass Home<T>(): VG<string> {\n  let y: T\n}\ntrait O<I>() {\n  fun xx(x: I): I\n}\nclass OR<R>(): O<R> {\n  fun xx(x: R): R\n}\nmodule Five {\n  class ROTK() {\n    let wu: string\n  }\n  class Y(): Five.ROTK {}\n}\nclass Y(): Five.ROTK {}\n//│ |#class| |A|(||)| |{|→|#fun| |foo|(||)|#:| |unit|←|↵|}|↵|#class| |B|(||)|#:| |A| |{||}|↵|#class| |C|‹|T|›|(||)| |{|→|#fun| |sett|(|x|#:| |T|)|#:| |unit|↵|#fun| |get|(||)|#:| |T|←|↵|}|↵|#class| |D|(||)|#:| |C|‹|number|›| |{||}|↵|#trait| |Wu|(||)| |{|→|#let| |x|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#class| |WuWu|(||)|#:| |Wu| |{|→|#let| |y|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |WuWuWu|(||)|#:| |WuWu| |{|→|#let| |z|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |Never|(||)|#:| |WuWuWu| |{|→|#fun| |w|(||)|#:| |nothing|←|↵|}|↵|#class| |VG|‹|T|›|(||)| |{|→|#let| |x|#:| |T|←|↵|}|↵|#class| |Home|‹|T|›|(||)|#:| |VG|‹|string|›| |{|→|#let| |y|#:| |T|←|↵|}|↵|#trait| |O|‹|I|›|(||)| |{|→|#fun| |xx|(|x|#:| |I|)|#:| |I|←|↵|}|↵|#class| |OR|‹|R|›|(||)|#:| |O|‹|R|›| |{|→|#fun| |xx|(|x|#:| |R|)|#:| |R|←|↵|}|↵|#module| |Five| |{|→|#class| |ROTK|(||)| |{|→|#let| |wu|#:| |string|←|↵|}|↵|#class| |Y|(||)|#:| |Five|.ROTK| |{||}|←|↵|}|↵|#class| |Y|(||)|#:| |Five|.ROTK| |{||}|\n//│ Parsed: {class A() {fun foo: () -> unit}; class B(): A {}; class C‹T›() {fun sett: (x: T) -> unit; fun get: () -> T}; class D(): C[number] {}; trait Wu() {let x: bool}; class WuWu(): Wu {let y: bool}; trait WuWuWu(): WuWu {let z: bool}; trait Never(): WuWuWu {fun w: () -> nothing}; class VG‹T›() {let x: T}; class Home‹T›(): VG[string] {let y: T}; trait O‹I›() {fun xx: (x: I) -> I}; class OR‹R›(): O[R] {fun xx: (x: R) -> R}; module Five {class ROTK() {let wu: string}; class Y(): Five.ROTK {}}; class Y(): Five.ROTK {}}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/HighOrderFunc.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun h1(inc: (number) => number, num: number): number\nfun h2(hint: string): unit => string\nfun h3(f: (number) => number, g: (number) => number): (number) => number\n//│ |#fun| |h1|(|inc|#:| |(|number|)| |#=>| |number|,| |num|#:| |number|)|#:| |number|↵|#fun| |h2|(|hint|#:| |string|)|#:| |unit| |#=>| |string|↵|#fun| |h3|(|f|#:| |(|number|)| |#=>| |number|,| |g|#:| |(|number|)| |#=>| |number|)|#:| |(|number|)| |#=>| |number|\n//│ Parsed: {fun h1: (inc: number -> number, num: number) -> number; fun h2: (hint: string) -> unit -> string; fun h3: (f: number -> number, g: number -> number) -> number -> number}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/InterfaceMember.d.mls",
    "content": ":NewDefs\n:ParseOnly\ntrait IFoo() {\n  let a: string\n  fun b(x: number): number\n  fun c(): (false) | (true)\n  fun d(x: string): unit\n}\ntrait II<T>() {\n  fun test(x: T): number\n}\nfun create(): {v: number,}\nfun get(x: {t: string,}): string\ntrait IEvent() {\n  fun callback(): (number) => unit\n}\ntrait SearchFunc() {\n  fun __call(source: string, subString: string): (false) | (true)\n}\ntrait StringArray() {\n  fun __index(index: number): string\n}\ntrait Counter() {\n  fun __call(start: number): string\n  let interval: number\n  fun reset(): unit\n}\ntrait Simple() {\n  let a: number\n  fun b(x: (false) | (true)): string\n}\ntrait Simple2<T>() {\n  let abc: T\n}\ntrait Next(): Simple {}\ntrait TTT<T>() {\n  fun ttt(x: T): T\n}\n//│ |#trait| |IFoo|(||)| |{|→|#let| |a|#:| |string|↵|#fun| |b|(|x|#:| |number|)|#:| |number|↵|#fun| |c|(||)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |d|(|x|#:| |string|)|#:| |unit|←|↵|}|↵|#trait| |II|‹|T|›|(||)| |{|→|#fun| |test|(|x|#:| |T|)|#:| |number|←|↵|}|↵|#fun| |create|(||)|#:| |{|v|#:| |number|,|}|↵|#fun| |get|(|x|#:| |{|t|#:| |string|,|}|)|#:| |string|↵|#trait| |IEvent|(||)| |{|→|#fun| |callback|(||)|#:| |(|number|)| |#=>| |unit|←|↵|}|↵|#trait| |SearchFunc|(||)| |{|→|#fun| |__call|(|source|#:| |string|,| |subString|#:| |string|)|#:| |(|false|)| ||| |(|true|)|←|↵|}|↵|#trait| |StringArray|(||)| |{|→|#fun| |__index|(|index|#:| |number|)|#:| |string|←|↵|}|↵|#trait| |Counter|(||)| |{|→|#fun| |__call|(|start|#:| |number|)|#:| |string|↵|#let| |interval|#:| |number|↵|#fun| |reset|(||)|#:| |unit|←|↵|}|↵|#trait| |Simple|(||)| |{|→|#let| |a|#:| |number|↵|#fun| |b|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |string|←|↵|}|↵|#trait| |Simple2|‹|T|›|(||)| |{|→|#let| |abc|#:| |T|←|↵|}|↵|#trait| |Next|(||)|#:| |Simple| |{||}|↵|#trait| |TTT|‹|T|›|(||)| |{|→|#fun| |ttt|(|x|#:| |T|)|#:| |T|←|↵|}|\n//│ Parsed: {trait IFoo() {let a: string; fun b: (x: number) -> number; fun c: () -> bool; fun d: (x: string) -> unit}; trait II‹T›() {fun test: (x: T) -> number}; fun create: () -> {v: number}; fun get: (x: {t: string}) -> string; trait IEvent() {fun callback: () -> number -> unit}; trait SearchFunc() {fun __call: (source: string, subString: string) -> bool}; trait StringArray() {fun __index: (index: number) -> string}; trait Counter() {fun __call: (start: number) -> string; let interval: number; fun reset: () -> unit}; trait Simple() {let a: number; fun b: (x: bool) -> string}; trait Simple2‹T›() {let abc: T}; trait Next(): Simple {}; trait TTT‹T›() {fun ttt: (x: T) -> T}}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Intersection.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun extend<T, U>(first: T, second: U): (T) & (U)\nfun foo<T, U>(x: (T) & (U)): unit\nfun over(f: ((number) => string) & ((object) => string)): string\ntrait IA() {\n  let x: number\n}\ntrait IB() {\n  let y: number\n}\nfun iii(x: (IA) & (IB)): (IA) & (IB)\nfun uu<U, V, T, P>(x: ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))): ((((U) & (T)) | ((U) & (P))) | ((V) & (T))) | ((V) & (P))\nfun iiii<U, T, V>(x: ((U) & (T)) & (V)): ((U) & (T)) & (V)\nfun arr<U, T>(a: (MutArray<U>) & (MutArray<T>)): (MutArray<U>) & (MutArray<T>)\nfun tt<U, T, V>(x: ([U, T]) & ([V, V])): ([U, T]) & ([V, V])\nclass A() {}\nclass B() {}\nfun inter(c: (A) & (B)): (A) & (B)\n//│ |#fun| |extend|‹|T|,| |U|›|(|first|#:| |T|,| |second|#:| |U|)|#:| |(|T|)| |&| |(|U|)|↵|#fun| |foo|‹|T|,| |U|›|(|x|#:| |(|T|)| |&| |(|U|)|)|#:| |unit|↵|#fun| |over|(|f|#:| |(|(|number|)| |#=>| |string|)| |&| |(|(|object|)| |#=>| |string|)|)|#:| |string|↵|#trait| |IA|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#trait| |IB|(||)| |{|→|#let| |y|#:| |number|←|↵|}|↵|#fun| |iii|(|x|#:| |(|IA|)| |&| |(|IB|)|)|#:| |(|IA|)| |&| |(|IB|)|↵|#fun| |uu|‹|U|,| |V|,| |T|,| |P|›|(|x|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|)|#:| |(|(|(|(|U|)| |&| |(|T|)|)| ||| |(|(|U|)| |&| |(|P|)|)|)| ||| |(|(|V|)| |&| |(|T|)|)|)| ||| |(|(|V|)| |&| |(|P|)|)|↵|#fun| |iiii|‹|U|,| |T|,| |V|›|(|x|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|)|#:| |(|(|U|)| |&| |(|T|)|)| |&| |(|V|)|↵|#fun| |arr|‹|U|,| |T|›|(|a|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|)|#:| |(|MutArray|‹|U|›|)| |&| |(|MutArray|‹|T|›|)|↵|#fun| |tt|‹|U|,| |T|,| |V|›|(|x|#:| |(|[|U|,| |T|]|)| |&| |(|[|V|,| |V|]|)|)|#:| |(|[|U|,| |T|]|)| |&| |(|[|V|,| |V|]|)|↵|#class| |A|(||)| |{||}|↵|#class| |B|(||)| |{||}|↵|#fun| |inter|(|c|#:| |(|A|)| |&| |(|B|)|)|#:| |(|A|)| |&| |(|B|)|\n//│ Parsed: {fun extend: (first: T, second: U) -> (T & U); fun foo: (x: T & U) -> unit; fun over: (f: number -> string & object -> string) -> string; trait IA() {let x: number}; trait IB() {let y: number}; fun iii: (x: IA & IB) -> (IA & IB); fun uu: (x: U & T | U & P | V & T | V & P) -> (U & T | U & P | V & T | V & P); fun iiii: (x: U & T & V) -> (U & T & V); fun arr: (a: MutArray[U] & MutArray[T]) -> (MutArray[U] & MutArray[T]); fun tt: (x: [U, T] & [V, V]) -> ([U, T] & [V, V]); class A() {}; class B() {}; fun inter: (c: A & B) -> (A & B)}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Literal.d.mls",
    "content": ":NewDefs\n:ParseOnly\nlet a: {a: \"A\",b: \"B\",}\nlet num: {y: 114,}\nfun foo(x: {xx: \"X\",}): {yy: \"Y\",}\n//│ |#let| |a|#:| |{|a|#:| |\"A\"|,|b|#:| |\"B\"|,|}|↵|#let| |num|#:| |{|y|#:| |114|,|}|↵|#fun| |foo|(|x|#:| |{|xx|#:| |\"X\"|,|}|)|#:| |{|yy|#:| |\"Y\"|,|}|\n//│ Parsed: {let a: {a: \"A\", b: \"B\"}; let num: {y: 114}; fun foo: (x: {xx: \"X\"}) -> {yy: \"Y\"}}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/MultiFiles.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun multi1(x: number): number\nfun multi3(): unit\nclass Foo(): Base {}\ntrait AnotherBase() {\n  let y: string\n}\nmodule N {\n  fun f(): unit\n  fun g(): unit\n  fun h(): unit\n}\nfun multi2(x: string): string\nfun multi4(): unit\ntrait Base() {\n  let a: number\n}\nclass AnotherFoo(): AnotherBase {}\nfun multi5(): unit\n//│ |#fun| |multi1|(|x|#:| |number|)|#:| |number|↵|#fun| |multi3|(||)|#:| |unit|↵|#class| |Foo|(||)|#:| |Base| |{||}|↵|#trait| |AnotherBase|(||)| |{|→|#let| |y|#:| |string|←|↵|}|↵|#module| |N| |{|→|#fun| |f|(||)|#:| |unit|↵|#fun| |g|(||)|#:| |unit|↵|#fun| |h|(||)|#:| |unit|←|↵|}|↵|#fun| |multi2|(|x|#:| |string|)|#:| |string|↵|#fun| |multi4|(||)|#:| |unit|↵|#trait| |Base|(||)| |{|→|#let| |a|#:| |number|←|↵|}|↵|#class| |AnotherFoo|(||)|#:| |AnotherBase| |{||}|↵|#fun| |multi5|(||)|#:| |unit|\n//│ Parsed: {fun multi1: (x: number) -> number; fun multi3: () -> unit; class Foo(): Base {}; trait AnotherBase() {let y: string}; module N {fun f: () -> unit; fun g: () -> unit; fun h: () -> unit}; fun multi2: (x: string) -> string; fun multi4: () -> unit; trait Base() {let a: number}; class AnotherFoo(): AnotherBase {}; fun multi5: () -> unit}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Namespace.d.mls",
    "content": ":NewDefs\n:ParseOnly\nmodule N1 {\n  fun f(x: anything): number\n  fun ff(y: anything): number\n  class C() {\n    fun f(): unit\n  }\n  trait I() {\n    fun f(): number\n  }\n  module N2 {\n    fun fff(x: (false) | (true)): number\n    fun gg(c: N1.C): N1.C\n    class BBB(): N1.C {}\n  }\n}\nmodule AA {\n  fun f(x: anything): string\n  class C() {\n    fun f(): unit\n  }\n  trait I() {\n    fun f(): number\n  }\n  module N2 {\n  }\n}\nfun f1(x: N1.C): N1.C\nfun f2(x: AA.C): AA.C\n//│ |#module| |N1| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |number|↵|#fun| |ff|(|y|#:| |anything|)|#:| |number|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#module| |N2| |{|→|#fun| |fff|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |number|↵|#fun| |gg|(|c|#:| |N1|.C|)|#:| |N1|.C|↵|#class| |BBB|(||)|#:| |N1|.C| |{||}|←|↵|}|←|↵|}|↵|#module| |AA| |{|→|#fun| |f|(|x|#:| |anything|)|#:| |string|↵|#class| |C|(||)| |{|→|#fun| |f|(||)|#:| |unit|←|↵|}|↵|#trait| |I|(||)| |{|→|#fun| |f|(||)|#:| |number|←|↵|}|↵|#module| |N2| |{|↵|}|←|↵|}|↵|#fun| |f1|(|x|#:| |N1|.C|)|#:| |N1|.C|↵|#fun| |f2|(|x|#:| |AA|.C|)|#:| |AA|.C|\n//│ Parsed: {module N1 {fun f: (x: anything) -> number; fun ff: (y: anything) -> number; class C() {fun f: () -> unit}; trait I() {fun f: () -> number}; module N2 {fun fff: (x: bool) -> number; fun gg: (c: N1.C) -> N1.C; class BBB(): N1.C {}}}; module AA {fun f: (x: anything) -> string; class C() {fun f: () -> unit}; trait I() {fun f: () -> number}; module N2 {}}; fun f1: (x: N1.C) -> N1.C; fun f2: (x: AA.C) -> AA.C}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Optional.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun buildName(firstName: string, lastName: (string) | (undefined)): string\nfun buildName2(firstName: string, lastName: (string) | (undefined)): string\nfun buildName3(firstName: string, lastName: MutArray<string>): string\nfun buildName4(firstName: string, lastName: MutArray<anything>): string\ntrait SquareConfig() {\n  let color: (string) | (undefined)\n  let width: (number) | (undefined)\n}\nfun did(x: number, f: ((number) => number) | (undefined)): number\nfun getOrElse(arr: (MutArray<object>) | (undefined)): object\nclass ABC() {}\nfun testABC(abc: (ABC) | (undefined)): unit\nfun testSquareConfig(conf: (SquareConfig) | (undefined)): unit\nfun err(msg: ([number, string]) | (undefined)): unit\nfun toStr(x: (((number) | (false)) | (true)) | (undefined)): string\nfun boo<T, U>(x: ((T) & (U)) | (undefined)): unit\nclass B<T>() {\n  let b: T\n}\nfun boom(b: (B<nothing>) | (undefined)): anything\n//│ |#fun| |buildName|(|firstName|#:| |string|,| |lastName|#:| |(|string|)| ||| |(|#undefined|)|)|#:| |string|↵|#fun| |buildName2|(|firstName|#:| |string|,| |lastName|#:| |(|string|)| ||| |(|#undefined|)|)|#:| |string|↵|#fun| |buildName3|(|firstName|#:| |string|,| |lastName|#:| |MutArray|‹|string|›|)|#:| |string|↵|#fun| |buildName4|(|firstName|#:| |string|,| |lastName|#:| |MutArray|‹|anything|›|)|#:| |string|↵|#trait| |SquareConfig|(||)| |{|→|#let| |color|#:| |(|string|)| ||| |(|#undefined|)|↵|#let| |width|#:| |(|number|)| ||| |(|#undefined|)|←|↵|}|↵|#fun| |did|(|x|#:| |number|,| |f|#:| |(|(|number|)| |#=>| |number|)| ||| |(|#undefined|)|)|#:| |number|↵|#fun| |getOrElse|(|arr|#:| |(|MutArray|‹|object|›|)| ||| |(|#undefined|)|)|#:| |object|↵|#class| |ABC|(||)| |{||}|↵|#fun| |testABC|(|abc|#:| |(|ABC|)| ||| |(|#undefined|)|)|#:| |unit|↵|#fun| |testSquareConfig|(|conf|#:| |(|SquareConfig|)| ||| |(|#undefined|)|)|#:| |unit|↵|#fun| |err|(|msg|#:| |(|[|number|,| |string|]|)| ||| |(|#undefined|)|)|#:| |unit|↵|#fun| |toStr|(|x|#:| |(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| ||| |(|#undefined|)|)|#:| |string|↵|#fun| |boo|‹|T|,| |U|›|(|x|#:| |(|(|T|)| |&| |(|U|)|)| ||| |(|#undefined|)|)|#:| |unit|↵|#class| |B|‹|T|›|(||)| |{|→|#let| |b|#:| |T|←|↵|}|↵|#fun| |boom|(|b|#:| |(|B|‹|nothing|›|)| ||| |(|#undefined|)|)|#:| |anything|\n//│ Parsed: {fun buildName: (firstName: string, lastName: string | ()) -> string; fun buildName2: (firstName: string, lastName: string | ()) -> string; fun buildName3: (firstName: string, lastName: MutArray[string]) -> string; fun buildName4: (firstName: string, lastName: MutArray[anything]) -> string; trait SquareConfig() {let color: string | (); let width: number | ()}; fun did: (x: number, f: number -> number | ()) -> number; fun getOrElse: (arr: MutArray[object] | ()) -> object; class ABC() {}; fun testABC: (abc: ABC | ()) -> unit; fun testSquareConfig: (conf: SquareConfig | ()) -> unit; fun err: (msg: [number, string] | ()) -> unit; fun toStr: (x: number | false | true | ()) -> string; fun boo: (x: T & U | ()) -> unit; class B‹T›() {let b: T}; fun boom: (b: B[nothing] | ()) -> anything}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Overload.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun f: ((number) => string) & ((string) => string)\nclass M() {\n  let foo: ((number) => string) & ((string) => string)\n}\nfun app: (((string) => unit) => (number) => unit) & (((string) => unit) => (string) => unit)\nfun create: ((number) => unit => (false) | (true)) & (((false) | (true)) => unit => (false) | (true))\nfun g0: ((MutArray<string>) => string) & ((MutArray<object>) => string)\nfun db: ((number) => MutArray<number>) & ((object) => MutArray<number>)\nclass N() {}\nfun id: ((M) => unit) & ((N) => unit)\nfun tst: (({z: number,}) => {y: string,}) & (({z: (false) | (true),}) => {y: string,})\nfun op: ((number) => ((number) | (undefined)) => unit) & ((number) => (((false) | (true)) | (undefined)) => unit)\nfun swap: (([number, string]) => [number, string]) & (([string, number]) => [number, string])\nfun u: ((((number) | (false)) | (true)) => string) & ((object) => string)\nfun doSome<T, U>(x: anything): unit /* warning: the overload of function doSome is not supported yet. */\nmodule XX {\n  fun f<T>(x: T, n: anything): string /* warning: the overload of function f is not supported yet. */\n}\nclass WWW() {\n  fun F<T>(x: T): anything /* warning: the overload of function F is not supported yet. */\n}\nfun baz(): anything /* warning: the overload of function baz is not supported yet. */\n//│ |#fun| |f|#:| |(|(|number|)| |#=>| |string|)| |&| |(|(|string|)| |#=>| |string|)|↵|#class| |M|(||)| |{|→|#let| |foo|#:| |(|(|number|)| |#=>| |string|)| |&| |(|(|string|)| |#=>| |string|)|←|↵|}|↵|#fun| |app|#:| |(|(|(|string|)| |#=>| |unit|)| |#=>| |(|number|)| |#=>| |unit|)| |&| |(|(|(|string|)| |#=>| |unit|)| |#=>| |(|string|)| |#=>| |unit|)|↵|#fun| |create|#:| |(|(|number|)| |#=>| |unit| |#=>| |(|false|)| ||| |(|true|)|)| |&| |(|(|(|false|)| ||| |(|true|)|)| |#=>| |unit| |#=>| |(|false|)| ||| |(|true|)|)|↵|#fun| |g0|#:| |(|(|MutArray|‹|string|›|)| |#=>| |string|)| |&| |(|(|MutArray|‹|object|›|)| |#=>| |string|)|↵|#fun| |db|#:| |(|(|number|)| |#=>| |MutArray|‹|number|›|)| |&| |(|(|object|)| |#=>| |MutArray|‹|number|›|)|↵|#class| |N|(||)| |{||}|↵|#fun| |id|#:| |(|(|M|)| |#=>| |unit|)| |&| |(|(|N|)| |#=>| |unit|)|↵|#fun| |tst|#:| |(|(|{|z|#:| |number|,|}|)| |#=>| |{|y|#:| |string|,|}|)| |&| |(|(|{|z|#:| |(|false|)| ||| |(|true|)|,|}|)| |#=>| |{|y|#:| |string|,|}|)|↵|#fun| |op|#:| |(|(|number|)| |#=>| |(|(|number|)| ||| |(|#undefined|)|)| |#=>| |unit|)| |&| |(|(|number|)| |#=>| |(|(|(|false|)| ||| |(|true|)|)| ||| |(|#undefined|)|)| |#=>| |unit|)|↵|#fun| |swap|#:| |(|(|[|number|,| |string|]|)| |#=>| |[|number|,| |string|]|)| |&| |(|(|[|string|,| |number|]|)| |#=>| |[|number|,| |string|]|)|↵|#fun| |u|#:| |(|(|(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|)| |#=>| |string|)| |&| |(|(|object|)| |#=>| |string|)|↵|#fun| |doSome|‹|T|,| |U|›|(|x|#:| |anything|)|#:| |unit| |/* warning: the overload of function doSome is not supported yet. */|↵|#module| |XX| |{|→|#fun| |f|‹|T|›|(|x|#:| |T|,| |n|#:| |anything|)|#:| |string| |/* warning: the overload of function f is not supported yet. */|←|↵|}|↵|#class| |WWW|(||)| |{|→|#fun| |F|‹|T|›|(|x|#:| |T|)|#:| |anything| |/* warning: the overload of function F is not supported yet. */|←|↵|}|↵|#fun| |baz|(||)|#:| |anything| |/* warning: the overload of function baz is not supported yet. */|\n//│ Parsed: {fun f: number -> string & string -> string; class M() {let foo: number -> string & string -> string}; fun app: (string -> unit) -> number -> unit & (string -> unit) -> string -> unit; fun create: number -> unit -> bool & bool -> unit -> bool; fun g0: MutArray[string] -> string & MutArray[object] -> string; fun db: number -> MutArray[number] & object -> MutArray[number]; class N() {}; fun id: M -> unit & N -> unit; fun tst: {z: number} -> {y: string} & {z: bool} -> {y: string}; fun op: number -> (number | ()) -> unit & number -> (false | true | ()) -> unit; fun swap: ([number, string]) -> [number, string] & ([string, number]) -> [number, string]; fun u: (number | false | true) -> string & object -> string; fun doSome: (x: anything) -> unit; module XX {fun f: (x: T, n: anything) -> string}; class WWW() {fun F: (x: T) -> anything}; fun baz: () -> anything}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Tuple.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun key(x: [string, (false) | (true)]): string\nfun value(x: [string, (false) | (true)]): (false) | (true)\nfun third(x: [number, number, number]): number\nfun vec2(x: number, y: number): [number, number]\nfun twoFunctions(ff: [(number) => number, (number) => number], x: number): number\nfun tupleIt(x: string): [unit => string]\nfun s(flag: (false) | (true)): [(string) | (number), ((number) | (false)) | (true)]\nfun s2(t: [(false) | (true), (string) | (number)]): (string) | (number)\nfun ex<T, U>(x: T, y: U): [T, U, (T) & (U)]\nfun foo<T, U>(x: [(T) & (U)]): unit\nfun conv(x: {y: number,}): [{y: number,}, {z: string,}]\nclass A() {\n  let x: number\n}\nclass B() {}\nfun swap(x: [A, B]): [B, A]\n//│ |#fun| |key|(|x|#:| |[|string|,| |(|false|)| ||| |(|true|)|]|)|#:| |string|↵|#fun| |value|(|x|#:| |[|string|,| |(|false|)| ||| |(|true|)|]|)|#:| |(|false|)| ||| |(|true|)|↵|#fun| |third|(|x|#:| |[|number|,| |number|,| |number|]|)|#:| |number|↵|#fun| |vec2|(|x|#:| |number|,| |y|#:| |number|)|#:| |[|number|,| |number|]|↵|#fun| |twoFunctions|(|ff|#:| |[|(|number|)| |#=>| |number|,| |(|number|)| |#=>| |number|]|,| |x|#:| |number|)|#:| |number|↵|#fun| |tupleIt|(|x|#:| |string|)|#:| |[|unit| |#=>| |string|]|↵|#fun| |s|(|flag|#:| |(|false|)| ||| |(|true|)|)|#:| |[|(|string|)| ||| |(|number|)|,| |(|(|number|)| ||| |(|false|)|)| ||| |(|true|)|]|↵|#fun| |s2|(|t|#:| |[|(|false|)| ||| |(|true|)|,| |(|string|)| ||| |(|number|)|]|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |ex|‹|T|,| |U|›|(|x|#:| |T|,| |y|#:| |U|)|#:| |[|T|,| |U|,| |(|T|)| |&| |(|U|)|]|↵|#fun| |foo|‹|T|,| |U|›|(|x|#:| |[|(|T|)| |&| |(|U|)|]|)|#:| |unit|↵|#fun| |conv|(|x|#:| |{|y|#:| |number|,|}|)|#:| |[|{|y|#:| |number|,|}|,| |{|z|#:| |string|,|}|]|↵|#class| |A|(||)| |{|→|#let| |x|#:| |number|←|↵|}|↵|#class| |B|(||)| |{||}|↵|#fun| |swap|(|x|#:| |[|A|,| |B|]|)|#:| |[|B|,| |A|]|\n//│ Parsed: {fun key: (x: [string, bool]) -> string; fun value: (x: [string, bool]) -> bool; fun third: (x: [number, number, number]) -> number; fun vec2: (x: number, y: number) -> [number, number]; fun twoFunctions: (ff: [number -> number, number -> number], x: number) -> number; fun tupleIt: (x: string) -> [unit -> string]; fun s: (flag: bool) -> [string | number, number | false | true]; fun s2: (t: [bool, string | number]) -> (string | number); fun ex: (x: T, y: U) -> [T, U, T & U]; fun foo: (x: [T & U]) -> unit; fun conv: (x: {y: number}) -> [{y: number}, {z: string}]; class A() {let x: number}; class B() {}; fun swap: (x: [A, B]) -> [B, A]}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Type.d.mls",
    "content": ":NewDefs\n:ParseOnly\ntrait None() {\n  let _tag: \"None\"\n}\ntrait Some<A>() {\n  let _tag: \"Some\"\n  let value: A\n}\ntype Option<A> = (None) | (Some<A>)\ntype Func = (number) => number\ntype S2 = [string, string]\ntrait I1() {}\ntrait I2() {}\ntype I3 = (I1) & (I2)\ntype StringArray = Array<string>\ntype SomeInterface = {x: number,y: number,}\nclass ABC() {}\ntype DEF = ABC\ntype TP<A, B, C> = [A, B, C]\nmodule NA {\n  fun fb(b: string): unit\n  type B = string\n}\nclass NC() {\n  let b: string\n}\ntype G = ABC\nlet none: {_tag: \"None\",}\nfun some<A>(a: A): (None) | (Some<A>)\n//│ |#trait| |None|(||)| |{|→|#let| |_tag|#:| |\"None\"|←|↵|}|↵|#trait| |Some|‹|A|›|(||)| |{|→|#let| |_tag|#:| |\"Some\"|↵|#let| |value|#:| |A|←|↵|}|↵|#type| |Option|‹|A|›| |#=| |(|None|)| ||| |(|Some|‹|A|›|)|↵|#type| |Func| |#=| |(|number|)| |#=>| |number|↵|#type| |S2| |#=| |[|string|,| |string|]|↵|#trait| |I1|(||)| |{||}|↵|#trait| |I2|(||)| |{||}|↵|#type| |I3| |#=| |(|I1|)| |&| |(|I2|)|↵|#type| |StringArray| |#=| |Array|‹|string|›|↵|#type| |SomeInterface| |#=| |{|x|#:| |number|,|y|#:| |number|,|}|↵|#class| |ABC|(||)| |{||}|↵|#type| |DEF| |#=| |ABC|↵|#type| |TP|‹|A|,| |B|,| |C|›| |#=| |[|A|,| |B|,| |C|]|↵|#module| |NA| |{|→|#fun| |fb|(|b|#:| |string|)|#:| |unit|↵|#type| |B| |#=| |string|←|↵|}|↵|#class| |NC|(||)| |{|→|#let| |b|#:| |string|←|↵|}|↵|#type| |G| |#=| |ABC|↵|#let| |none|#:| |{|_tag|#:| |\"None\"|,|}|↵|#fun| |some|‹|A|›|(|a|#:| |A|)|#:| |(|None|)| ||| |(|Some|‹|A|›|)|\n//│ Parsed: {trait None() {let _tag: \"None\"}; trait Some‹A›() {let _tag: \"Some\"; let value: A}; type alias Option‹A›: None | Some[A] {}; type alias Func: number -> number {}; type alias S2: [string, string] {}; trait I1() {}; trait I2() {}; type alias I3: I1 & I2 {}; type alias StringArray: Array[string] {}; type alias SomeInterface: {x: number, y: number} {}; class ABC() {}; type alias DEF: ABC {}; type alias TP‹A, B, C›: [A, B, C] {}; module NA {fun fb: (b: string) -> unit; type alias B: string {}}; class NC() {let b: string}; type alias G: ABC {}; let none: {_tag: \"None\"}; fun some: (a: A) -> (None | Some[A])}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/TypeParameter.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun inc<T>(x: T): number\nclass CC<T>() {\n  fun print(s: T): unit\n}\nfun con<U, T>(t: T): U\nclass Printer<T>() {\n  fun print(t: T): unit\n}\nfun setStringPrinter(p: Printer<string>): unit\nfun getStringPrinter(): Printer<string>\nfun foo<T>(p: Printer<T>, x: T): T\nfun foo2<T>(p: Printer<T>, x: T): T\nclass F<T>() {\n  let x: T\n  fun GG<U>(y: U): T\n}\ntrait I<T>() {\n  let x: T\n  fun GG<U>(y: U): T\n}\nclass FFF<T>() {\n  fun fff(x: T): unit\n}\nfun fff(p: FFF<string>, s: string): unit\nfun getFFF(): FFF<number>\n//│ |#fun| |inc|‹|T|›|(|x|#:| |T|)|#:| |number|↵|#class| |CC|‹|T|›|(||)| |{|→|#fun| |print|(|s|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |con|‹|U|,| |T|›|(|t|#:| |T|)|#:| |U|↵|#class| |Printer|‹|T|›|(||)| |{|→|#fun| |print|(|t|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |setStringPrinter|(|p|#:| |Printer|‹|string|›|)|#:| |unit|↵|#fun| |getStringPrinter|(||)|#:| |Printer|‹|string|›|↵|#fun| |foo|‹|T|›|(|p|#:| |Printer|‹|T|›|,| |x|#:| |T|)|#:| |T|↵|#fun| |foo2|‹|T|›|(|p|#:| |Printer|‹|T|›|,| |x|#:| |T|)|#:| |T|↵|#class| |F|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|y|#:| |U|)|#:| |T|←|↵|}|↵|#trait| |I|‹|T|›|(||)| |{|→|#let| |x|#:| |T|↵|#fun| |GG|‹|U|›|(|y|#:| |U|)|#:| |T|←|↵|}|↵|#class| |FFF|‹|T|›|(||)| |{|→|#fun| |fff|(|x|#:| |T|)|#:| |unit|←|↵|}|↵|#fun| |fff|(|p|#:| |FFF|‹|string|›|,| |s|#:| |string|)|#:| |unit|↵|#fun| |getFFF|(||)|#:| |FFF|‹|number|›|\n//│ Parsed: {fun inc: (x: T) -> number; class CC‹T›() {fun print: (s: T) -> unit}; fun con: (t: T) -> U; class Printer‹T›() {fun print: (t: T) -> unit}; fun setStringPrinter: (p: Printer[string]) -> unit; fun getStringPrinter: () -> Printer[string]; fun foo: (p: Printer[T], x: T) -> T; fun foo2: (p: Printer[T], x: T) -> T; class F‹T›() {let x: T; fun GG: (y: U) -> T}; trait I‹T›() {let x: T; fun GG: (y: U) -> T}; class FFF‹T›() {fun fff: (x: T) -> unit}; fun fff: (p: FFF[string], s: string) -> unit; fun getFFF: () -> FFF[number]}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Union.d.mls",
    "content": ":NewDefs\n:ParseOnly\nfun getString(x: (((string) | (number)) | (false)) | (true)): string\nfun test(x: (false) | (true)): (string) | (number)\nfun run(f: ((number) => number) | ((number) => string)): anything\nfun get(arr: (MutArray<number>) | (MutArray<string>)): unit\nfun get2(t: ([string, string]) | ([number, string])): string\nfun typeVar<T, U>(x: (T) | (U)): (T) | (U)\nfun uuuu(x: (((string) | (number)) | (false)) | (true)): (((string) | (number)) | (false)) | (true)\n//│ |#fun| |getString|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |string|↵|#fun| |test|(|x|#:| |(|false|)| ||| |(|true|)|)|#:| |(|string|)| ||| |(|number|)|↵|#fun| |run|(|f|#:| |(|(|number|)| |#=>| |number|)| ||| |(|(|number|)| |#=>| |string|)|)|#:| |anything|↵|#fun| |get|(|arr|#:| |(|MutArray|‹|number|›|)| ||| |(|MutArray|‹|string|›|)|)|#:| |unit|↵|#fun| |get2|(|t|#:| |(|[|string|,| |string|]|)| ||| |(|[|number|,| |string|]|)|)|#:| |string|↵|#fun| |typeVar|‹|T|,| |U|›|(|x|#:| |(|T|)| ||| |(|U|)|)|#:| |(|T|)| ||| |(|U|)|↵|#fun| |uuuu|(|x|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|)|#:| |(|(|(|string|)| ||| |(|number|)|)| ||| |(|false|)|)| ||| |(|true|)|\n//│ Parsed: {fun getString: (x: string | number | false | true) -> string; fun test: (x: bool) -> (string | number); fun run: (f: number -> number | number -> string) -> anything; fun get: (arr: MutArray[number] | MutArray[string]) -> unit; fun get2: (t: [string, string] | [number, string]) -> string; fun typeVar: (x: T | U) -> (T | U); fun uuuu: (x: string | number | false | true) -> (string | number | false | true)}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/diff/Variables.d.mls",
    "content": ":NewDefs\n:ParseOnly\nlet URI: string\nlet URI2: string\nlet foo: number\nlet bar: false\nclass FooBar() {}\nlet fb: FooBar\nmodule ABC {\n  class DEF() {}\n}\nlet d: ABC.DEF\nmodule DD {\n  let foo: number\n  let bar: number\n}\n//│ |#let| |URI|#:| |string|↵|#let| |URI2|#:| |string|↵|#let| |foo|#:| |number|↵|#let| |bar|#:| |false|↵|#class| |FooBar|(||)| |{||}|↵|#let| |fb|#:| |FooBar|↵|#module| |ABC| |{|→|#class| |DEF|(||)| |{||}|←|↵|}|↵|#let| |d|#:| |ABC|.DEF|↵|#module| |DD| |{|→|#let| |foo|#:| |number|↵|#let| |bar|#:| |number|←|↵|}|\n//│ Parsed: {let URI: string; let URI2: string; let foo: number; let bar: false; class FooBar() {}; let fb: FooBar; module ABC {class DEF() {}}; let d: ABC.DEF; module DD {let foo: number; let bar: number}}\n//│ \n"
  },
  {
    "path": "ts2mls/js/src/test/scala/ts2mls/TSTypeGenerationTests.scala",
    "content": "package ts2mls\n\nimport org.scalatest.funsuite.AnyFunSuite\n\nclass TSTypeGenerationTest extends AnyFunSuite {\n  import TSTypeGenerationTest._\n  \n  testsData.foreach((data) => test(data._2) {\n    val program = TSProgram(tsPath(data._1))\n    var writer = JSWriter(diffPath(data._2))\n    program.generate(writer)\n    writer.close()\n  })\n}\n\nobject TSTypeGenerationTest {\n  private def tsPath(filenames: Seq[String]) = filenames.map((fn) => s\"ts2mls/js/src/test/typescript/$fn\")\n  private def diffPath(filename: String) = s\"ts2mls/js/src/test/diff/$filename\"\n\n  private val testsData = List(\n    (Seq(\"Array.ts\"), \"Array.d.mls\"),\n    (Seq(\"BasicFunctions.ts\"), \"BasicFunctions.d.mls\"),\n    (Seq(\"ClassMember.ts\"), \"ClassMember.d.mls\"),\n    (Seq(\"Dec.d.ts\"), \"Dec.d.mls\"),\n    (Seq(\"Enum.ts\"), \"Enum.d.mls\"),\n    (Seq(\"Heritage.ts\"), \"Heritage.d.mls\"),\n    (Seq(\"HighOrderFunc.ts\"), \"HighOrderFunc.d.mls\"),\n    (Seq(\"InterfaceMember.ts\"), \"InterfaceMember.d.mls\"),\n    (Seq(\"Intersection.ts\"), \"Intersection.d.mls\"),\n    (Seq(\"Literal.ts\"), \"Literal.d.mls\"),\n    (Seq(\"Multi1.ts\", \"Multi2.ts\", \"Multi3.ts\"), \"MultiFiles.d.mls\"),\n    (Seq(\"Namespace.ts\"), \"Namespace.d.mls\"),\n    (Seq(\"Optional.ts\"), \"Optional.d.mls\"),\n    (Seq(\"Overload.ts\"), \"Overload.d.mls\"),\n    (Seq(\"Tuple.ts\"), \"Tuple.d.mls\"),\n    (Seq(\"Type.ts\"), \"Type.d.mls\"),\n    (Seq(\"TypeParameter.ts\"), \"TypeParameter.d.mls\"),\n    (Seq(\"Union.ts\"), \"Union.d.mls\"),\n    (Seq(\"Variables.ts\"), \"Variables.d.mls\"),\n  )\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Array.ts",
    "content": "function first(x: string[]) {\n  return x[0];\n}\n\nfunction getZero3() : number[] {\n  return [0, 0, 0];\n}\n\nfunction first2(fs: ((x: number) => number)[]): ((x: number) => number) {\n  return fs[0];\n}\n\nenum E {\n  E, EE, EEE\n}\n\nfunction doEs(e: E[]): E[] {\n  return e;\n}\n\nclass C {}\ninterface I {i: number}\n\nfunction doCs(c: C[]): C[] {\n  return c;\n}\n\nfunction doIs(i: I[]): I[] {\n  return i;\n}\n\nfunction inter<U, T>(x: (U & T)[]): (U & T)[] {\n  return x;\n}\n\nfunction clean(x: [string, number][]): [string, number][] {\n  return [];\n}\n\nfunction translate<T, U>(x: T[]): U[] {\n  return [];\n}\n\nfunction uu(x: (number | boolean)[]): (number | boolean)[] {\n  return x;\n}\n\nclass Temp<T> {\n  x: T\n}\n\nfunction ta(ts: Temp<boolean>[]): Temp<boolean>[] {\n  return [];\n}\n\nfunction tat<T>(ts: Temp<T>[]): Temp<T>[] {\n  return [];\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/BasicFunctions.ts",
    "content": "function hello() {\n  console.log(\"hello\")\n}\n\nfunction add(x: number, y: number): number {\n  return x + y\n}\n\nfunction sub(x: number, y: number) {\n  return x - y\n}\n\nfunction foo() {\n  return 42;\n}\n\nfunction id(x) {\n  return x;\n}\n\nfunction odd(x: number) {\n  return (x % 2) !== 0;\n}\n\nfunction isnull(x) {\n  return x == null;\n}\n\nfunction bar() {\n  return undefined;\n}\n\nfunction nu(n: null): null {\n  return n;\n}\n\nfunction un(n: undefined): undefined {\n  return n;\n}\n\nfunction fail() : never {\n  throw new Error(\"wuwuwu\");\n}\n\nfunction create(): object {\n  return {v: 0};\n}\n\nfunction pa(x: ((number))): number {\n  return x + 42;\n}\n\nfunction wtf(x: unknown) {}\n\nclass Foooooo {\n  ooooooo: number\n}\n\nfunction inn(f: Foooooo) {\n  console.log(f.ooooooo)\n}\n\nfunction out1(): Foooooo {\n  return new Foooooo();\n}\n\ninterface Barrrrrrrrr {\n  rrrrrrr: number\n}\n\nfunction inn2(b: Barrrrrrrrr) {\n  console.log(b.rrrrrrr)\n}\n\nfunction out2(): Barrrrrrrrr {\n  return {rrrrrrr: 42};\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/ClassMember.ts",
    "content": "class Student {\n  name: string\n\n  constructor(s: string, age: number) {}\n\n  \n  getID() { return 114514; }\n\n  addScore(sub: string, score: number) {}\n  isFriend(other: Student) { return true; }\n\n  private a: number\n  protected b: string\n}\n\nclass Foo<T extends Student> {\n  constructor() {}\n\n  bar(x: T) {}\n}\n\nclass EZ {\n  inc(x: number) {\n    return x + 1;\n  }\n\n  private foo() {}\n  protected bar: undefined\n}\n\nclass Outer {\n  static Inner = class Inner {\n   a: number\n  } \n}\n\nclass TTT<T> {\n  ttt(x: T): T {\n    return x;\n  }\n\n  ttt2: (x: T) => T\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Dec.d.ts",
    "content": "decalre function getName(id: number | string): string\ndeclare function render(callback?: ()=>void): string\n\ndeclare interface Get{\n  (id: string): string\n}\n\ndeclare class Person {\n  constructor(name: string, age: number)\n  getName(id: number): string \n}\n\ndeclare namespace OOO{\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Enum.ts",
    "content": "enum Color {Red, Yellow, Green}\n\nfunction pass(c: Color): boolean {\n  return c == Color.Green;\n}\n\nfunction stop(): Color {\n  return Color.Red;\n}\n\nenum Empty {}\n\nfunction g(x: Empty): Empty {\n  return x;\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Heritage.ts",
    "content": "class A {\n  constructor() {}\n\n  foo() {\n      console.log(\"foo\")\n  }\n}\n\nclass B extends A {}\n\nclass C<T> {\n  constructor() {}\n\n  private t: T\n\n  sett(x: T) { this.t = x; } // FIXME support `set` methods...\n  get() { return this.t; } \n}\n\nclass D extends C<number> {\n}\n\ninterface Wu {\n  x: boolean\n}\n\nclass WuWu extends Wu {\n  y: boolean\n}\n\ninterface WuWuWu extends WuWu {\n  z: boolean\n}\n\ninterface Never extends WuWuWu {\n  w: () => never\n}\n\nclass VG<T> {\n  x: T\n}\n\nclass Home<T> extends VG<string> {\n  y: T\n}\n\ninterface O<I> {\n  xx: (x: I) => I\n}\n\nclass OR<R> implements O<R> {\n  xx(x: R): R {\n    return x;\n  }\n}\n\nnamespace Five {\n  export class ROTK {\n    wu: string\n  }\n\n  export class Y extends Five.ROTK {}\n}\n\nclass Y extends Five.ROTK {}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/HighOrderFunc.ts",
    "content": "function h1(inc: (n: number) => number, num: number) {\n  return inc(num)\n}\n\nfunction h2(hint: string) {\n  return function() {\n    return \"hint: \" + hint\n  }\n}\n\nfunction h3(f: (x: number) => number, g: (x: number) => number) {\n  return function(x: number) {\n    return f(g(x))\n  }\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/InterfaceMember.ts",
    "content": "interface IFoo {\n  a: string\n  b: (x: number) => number\n  c: () => boolean\n  d: (x: string) => void\n}\n\ninterface II<T extends number> {\n  test: (x: T) => number\n}\n\nfunction create() {\n  return {v: 114};\n}\n\nfunction get(x: {t: string}): string {\n  return x.t;\n}\n\ninterface IEvent {\n  callback(this: IEvent): (x: number) => void;\n}\n\ninterface SearchFunc {\n  (source: string, subString: string): boolean;\n}\n\ninterface StringArray {\n  [index: number]: string;\n}\n\ninterface Counter {\n  (start: number): string;\n  interval: number;\n  reset(): void;\n}\n\ninterface Simple {\n  a: number\n  b: (x: boolean) => string\n}\n\ninterface Simple2<T extends number> {\n  abc: T\n}\n\ninterface Next extends Simple {}\n\ninterface TTT<T> {\n  ttt: (x: T) => T\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Intersection.ts",
    "content": "function extend<T, U>(first: T, second: U): T & U {\n  let result = <T & U>{};\n  return result;\n}\n\nfunction foo<T, U>(x: T & U) {\n  console.log(x)\n}\n\nfunction over(f: ((x: number) => string) & ((x: object) => string)): string {\n  return f(42);\n}\n\ninterface IA{\n  x: number\n}\n\ninterface IB{\n  y: number\n}\n\nfunction iii(x: IA & IB): IA & IB {\n  return x;\n}\n\nfunction uu<U, V, T, P>(x: (U | V) & (T | P)): (U | V) & (T | P) {\n  return x;\n}\n\nfunction iiii<U, T, V>(x: U & (T & V)): U & (T & V) {\n  return x;\n}\n\nfunction arr<U, T>(a: U[] & T[]): U[] & T[] {\n  return a;\n}\n\nfunction tt<U, T, V>(x: [U, T] & [V, V]): [U, T] & [V, V] {\n  return x;\n}\n\nclass A{}\nclass B{}\n\nfunction inter(c: A & B): A & B {\n  return c;\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Literal.ts",
    "content": "const a = { a: \"A\", b: \"B\" }\nconst num = { y: 114 }\n\nfunction foo(x: {xx: \"X\"}): {yy: \"Y\"} {\n  const y = {yy: \"Y\"}\n  return y\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Multi1.ts",
    "content": "function multi1(x: number) {\n  return x;\n}\n\nfunction multi3() {}\n\nclass Foo extends Base {}\n\ninterface AnotherBase {\n  y: string\n}\n\nnamespace N {\n  export function f() {}\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Multi2.ts",
    "content": "function multi2(x: string) {\n  return x;\n}\n\nfunction multi4() {\n  multi3()\n}\n\ninterface Base {\n  a: number\n}\n\nclass AnotherFoo extends AnotherBase {}\n\nnamespace N {\n  export function g() {}\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Multi3.ts",
    "content": "function multi5() {\n  console.log(\"wuwuwu\")\n}\n\nnamespace N {\n  export function h() {}\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Namespace.ts",
    "content": "namespace N1 {\n  export function f(x) {\n    return 42;\n  }\n\n  function ff(y) {\n    return 42;\n  }\n\n  export class C {\n    f() {}\n  }\n\n  interface I {\n    f: () => number\n  }\n\n  export namespace N2 {\n    export function fff(x: boolean) {\n      return 42;\n    }\n\n    class BBB extends C {}\n\n    function gg(c: C): C {\n      return new C;\n    }\n  }\n}\n\nnamespace AA {\n  export function f(x) {\n    return \"42\";\n  }\n\n  export class C {\n    f() {}\n  }\n\n  export interface I {\n    f: () => number\n  }\n\n  export namespace N2 {}\n}\n\nfunction f1(x: N1.C): N1.C {\n  return x;\n}\n\nfunction f2(x: AA.C): AA.C {\n  return x;\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Optional.ts",
    "content": "function buildName(firstName: string, lastName?: string) {\n  return firstName + lastName;\n}\n\nfunction buildName2(firstName: string, lastName = \"DIO\") {\n  return firstName + lastName;\n}\n\nfunction buildName3(firstName: string, ...lastName: string[]) {\n  console.log(lastName)\n  return firstName;\n}\n\nfunction buildName4(firstName: string, ...lastName) {\n  console.log(lastName)\n  return firstName;\n}\n\ninterface SquareConfig {\n  color?: string;\n  width?: number;\n}\n\nfunction did(x: number, f?: (x: number) => number): number {\n  if (f === undefined) return x;\n  else return f(x);\n}\n\nfunction getOrElse(arr?: object[]): object {\n  if (arr === undefined) return {};\n  else return arr[0];\n}\n\nclass ABC {}\nfunction testABC(abc?: ABC) {}\n\nfunction testSquareConfig(conf?: SquareConfig) {}\n\nfunction err(msg?: [number, string]): void {\n  if (msg === undefined) return;\n  else throw msg;\n}\n\nfunction toStr(x?: number | boolean): string {\n  if (x === undefined) return \"undefined\";\n  else return x.toString();\n}\n\nfunction boo<T, U>(x?: T & U) {}\n\nclass B<T> {\n  b: T\n}\n\nfunction boom(b?: B<never>): any {}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Overload.ts",
    "content": "function f(x: number): string;\nfunction f(x: string): string;\n\nfunction f(x) {\n  if (typeof x == \"number\") return \"42\";\n  else return \"->\" + x;\n}\n\nclass M {\n  foo(x: number): string;\n  foo(x: string): string;\n\n  foo(x) {\n    return x.toString();\n  }\n}\n\nfunction app(f: (x: string) => void, x: number): void;\nfunction app(f: (x: string) => void, x: string): void;\n\nfunction app(f, x): void {\n  f(x.toString())\n}\n\nfunction create(x: number): () => boolean;\nfunction create(x: boolean): () => boolean;\n\nfunction create(x) {\n  return function() { return x == 0; }\n}\n\nfunction g0(x: string[]): string;\nfunction g0(x: object[]): string;\n\nfunction g0(x) {\n  return x[0].toString();\n}\n\nfunction db(x: number): number[];\nfunction db(x: object): number[];\n\nfunction db(x) {\n  return [0, 1];\n}\n\nclass N {}\n\nfunction id(x: M): void;\nfunction id(x: N): void;\n\nfunction id(x) {}\n\nfunction tst(x: {z: number}): {y: string};\nfunction tst(x: {z: boolean}): {y: string};\n\nfunction tst(x) {\n  return {y: x.z.toString()}\n}\n\nfunction op(x: number, y?: number): void;\nfunction op(x: number, y?: boolean): void;\n\nfunction op(x, y) {}\n\nfunction swap(x: [number, string]): [number, string];\nfunction swap(x: [string, number]): [number, string];\n\nfunction swap(x) {\n  return [x[1], x[0]];\n}\n\nfunction u(x: number | boolean): string;\nfunction u(x: object): string;\n\nfunction u(x) {\n  return x.toString();\n}\n\nfunction doSome<T, U>(x: T & U): never;\nfunction doSome<T, U>(x: string): never;\n\nfunction doSome<T, U>(x) {\n  while (true);\n}\n\nnamespace XX {\n  export function f<T>(x: T, n: number): string;\n  export function f<T>(x: T, n: boolean): string;\n\n  export function f<T>(x: T, n) {\n    return \"\";\n  }\n}\n\nclass WWW {\n  F<T>(x: string): T;\n  F<T>(x: number): T;\n\n  F<T>(x: T) {\n    return null;\n  }\n}\n\nfunction baz<T>(): T;\nfunction baz<U, T>(): U;\nfunction baz<U, T, P>(): P;\nfunction baz() {\n  return null;\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Tuple.ts",
    "content": "function key(x: [string, boolean]): string {\n  return x[0];\n}\n\nfunction value(x: [string, boolean]): boolean {\n  return x[1];\n}\n\nfunction third(x: [number, number, number]): number {\n  return x[2];\n}\n\nfunction vec2(x: number, y: number): [number, number] {\n  return [x, y];\n}\n\nfunction twoFunctions(ff: [(x: number) => number, (x: number) => number], x: number): number {\n  return ff[0](x) + ff[1](x);\n}\n\nfunction tupleIt(x: string): [() => string] {\n  return [function() { return x }]\n}\n\nfunction s(flag: boolean): [string | number, number | boolean] {\n  if (flag) {\n      return [\"abc\", 12];\n  }\n  else {\n      return [24, false];\n  }\n}\n\nfunction s2(t: [boolean, string | number]): string | number {\n  if (t[0]) return t[1]\n  else return 0\n}\n\nfunction ex<T, U>(x: T, y: U): [T, U, T & U] {\n  return [x, y , <T & U>{}];\n}\n\nfunction foo<T, U>(x: [T & U]) {}\n\nfunction conv(x: {y: number}): [{y: number}, {z: string}] {\n  return [x, {z: x.y.toString()}];\n}\n\nclass A {\n  x: number\n}\nclass B {}\n\nfunction swap(x: [A, B]): [B, A] {\n  return [x[1], x[0]];\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Type.ts",
    "content": "interface None {\n  readonly _tag: 'None'\n}\n\ninterface Some<A> {\n  readonly _tag: 'Some'\n  readonly value: A\n}\n\ntype Option<A> = None | Some<A>\ntype Func = (x: number) => number\ntype S2 = [string, string]\n\ninterface I1 {}\ninterface I2 {}\n\ntype I3 = I1 & I2\ntype StringArray = string[]\ntype SomeInterface = { x: number, y: number }\n\nclass ABC {}\ntype DEF = ABC\ntype TP<A, B, C> = [A, B, C]\n\nnamespace NA {\n\texport type B = string\n\tfunction fb(b: B) {}\n}\n\nclass NC {\n\tconstructor() {}\n\tb: NA.B\n}\n\ntype G = DEF\n\nconst none: Option<never> = { _tag: 'None' }\nconst some = <A>(a: A): Option<A> => ({ _tag: 'Some', value: a })\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/TypeParameter.ts",
    "content": "function inc<T extends number>(x: T) {\n  return x + 1\n}\n\nclass CC<T extends string> {\n  constructor() {}\n\n  print(s: T) { console.log(s) }\n}\n\nfunction con<U, T extends U>(t: T): U {\n  return t;\n}\n\nclass Printer<T> {\n  constructor() {}\n\n  print(t: T) { console.log(t) }\n}\n\nfunction setStringPrinter(p: Printer<string>) {}\n\nfunction getStringPrinter(): Printer<string> { return new Printer<string>(); }\n\nfunction foo<T>(p: Printer<T>, x: T): T {\n  return null;\n}\n\n// TODO: `extends` is still not supported yet.\nfunction foo2<T extends number[]>(p: Printer<T>, x: T): T {\n  return null;\n}\n\nclass F<T> {\n  x: T\n\n  GG<U>(y: U): T {\n    return this.x;\n  }\n}\n\ninterface I<T> {\n  x: T\n  GG<U>(y: U): T\n}\n\nclass FFF<T> {\n  constructor() {}\n  fff(x: T) {}\n}\n\nfunction fff(p: FFF<string>, s: string) {\n  p.fff(s);\n}\n\nfunction getFFF(): FFF<number> {\n  return new FFF<number>();\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Union.ts",
    "content": "function getString(x: string | number | boolean): string {\n  return x.toString()\n}\n\nfunction test(x: boolean): (string | number) {\n  if (x) return \"foo\";\n  else return 42;\n}\n\nfunction run(f: ((x: number) => number) | ((x: number) => string)): any {\n  return f(42);\n}\n\nfunction get(arr: number[] | string[]) {\n  console.log(arr[0])\n}\n\nfunction get2(t: [string, string] | [number, string]): string {\n  return t[1];\n}\n\nfunction typeVar<T, U>(x: T | U): T | U {\n  return x\n}\n\nfunction uuuu(x: string | (number | boolean)): string | (number | boolean) {\n  return x;\n}\n"
  },
  {
    "path": "ts2mls/js/src/test/typescript/Variables.ts",
    "content": "const URI: string = \"Option\"\nlet URI2: string = \"Option\"\nlet foo: number\nconst bar = false\n\nclass FooBar {}\nconst fb = new FooBar\n\nnamespace ABC {\n  export class DEF {}\n}\n\nconst d = new ABC.DEF\n\nnamespace DD {\n  export const foo: number = 42\n  const bar = 42\n}\n"
  },
  {
    "path": "ts2mls/jvm/src/test/scala/ts2mls/TsTypeDiffTests.scala",
    "content": "package ts2mls\n\nimport mlscript.DiffTests\n\nclass TsTypeDiffTests extends DiffTests {\n  override protected lazy val files =\n    os.walk(os.pwd/\"ts2mls\"/\"js\"/\"src\"/\"test\"/\"diff\").filter(_.toIO.isFile)\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n        \"module\": \"commonjs\",\n        \"target\": \"es2016\",\n        \"jsx\": \"preserve\",\n        \"sourceMap\": true\n    },\n    \"include\": [\n        \"ts\"\n    ],\n    \"exclude\": [\n        \"node_modules\",\n        \"**/node_modules/*\"\n    ],\n    \"[typescript]\": {\n        \"editor.showUnused\":  false\n    },\n    \"[typescriptreact]\": {\n        \"editor.showUnused\":  false\n    },\n}\n"
  },
  {
    "path": "vim/mlscript.vim",
    "content": "\" Language:     MLScript\n\nif exists(\"b:current_syntax\")\n  finish\nendif\n\n\" keywords and constants\nsyn keyword     mlsKeyword      let set fun val rec mut declare\nsyn keyword     mlsKeyword      override super new of forall exists\nsyn keyword     mlsKeyword      class object module pattern trait mixin\nsyn keyword     mlsKeyword      interface extends namespace type where with\nsyn keyword     mlsKeyword      break return continue as in out\nsyn keyword     mlsKeyword      constructor abstract virtual throw\nsyn keyword     mlsKeyword      case and or enum data\nsyn keyword     mlsConditional  if then else\nsyn keyword     mlsRepeat       while for do\nsyn keyword     mlsExternal     import\nsyn keyword     mlsExternal     open\nsyn keyword     mlsConstant     null true false undefined\n\n\" number constants\nsyn match  mlsNumbers     display transparent \"\\<\\d\\|\\.\\d\" contains=mlsNumber,mlsNumberError\nsyn match  mlsNumber      display contained \"\\(\\d\\|_\\)*\\.\\=\\d*\\(e[-+]\\=\\d\\+\\)\\=\"\n\n\" compiler flags\nsyn match    mlsFlag           \"^:\\w\\+\"\n\n\" function names\nsyn match    mlsCustomFunc     \"\\w\\+\\s*(\\@=\"\nsyn match    mlsCustomFunc     \"\\w\\+\\s*\\(of\\)\\@=\"\nsyn match    mlsCustomFunc     \"\\(\\.\\.\\)\\@<!\\.\\@<=\\w\\+\"\n\n\" module names\nsyn match  mlsModuleName  display \"\\<[A-Z]\\+\\w*\\>\"\n\n\" operators\nsyn match    mlsOperator   \"+\"\nsyn match    mlsOperator   \"*\"\nsyn match    mlsOperator   \"/\"\nsyn match    mlsOperator   \"|>\"\nsyn match    mlsOperator   \"<|\"\nsyn match    mlsOperator   \"\\.>\"\nsyn match    mlsOperator   \"<\\.\"\nsyn match    mlsOperator   \"!>\"\nsyn match    mlsOperator   \"<!\"\nsyn match    mlsOperator   \"|!\"\nsyn match    mlsOperator   \">>\"\nsyn match    mlsOperator   \"<<\"\nsyn match    mlsOperator   \"\\\\\"\nsyn match    mlsOperator   \"|\\.\"\nsyn match    mlsOperator   \"|>\\.\"\nsyn match    mlsOperator   \"@\"\nsyn match    mlsOperator   \"::\"\nsyn match    mlsOperator   \":::\"\nsyn match    mlsOperator   \"++\"\nsyn match    mlsOperator   \"\\*\\*\"\n\n\" strings\nsyn region mlsString   start=+\"+ end=+\"+ skip=+\\\\\\\\\\|\\\\\"+ contains=mlsSpecial\nsyn match  mlsSpecial  display contained +\\(\\\\\\)\\@1<!\\(\\\\\\\\\\)*\\zs\\\\\"+\n\n\" multiline strings\nsyn region mlsLongString start=+\"\"\"+ end=+\"\"\"+ \" contains=@Spell\n\n\" comments and comment strings\nsyn keyword  mlsTodo          contained TODO FIXME XXX NOTE\nsyn region mlsCommentL        start=\"//\" skip=\"\\\\$\" end=\"$\" keepend contains=mlsTodo\nsyn region mlsComment         matchgroup=mlsComment start=\"/\\*\" end=\"\\*/\" contains=mlsTodo\n\n\" linking highlight colors\nhi link mlsCommentL             Comment\nhi link mlsComment              Comment\nhi link mlsConditional          Conditional\nhi link mlsKeyword              Keyword\nhi link mlsRepeat               Repeat\nhi link mlsNumber               Number\nhi link mlsOperator             Operator\nhi link mlsExternal             Include\nhi link mlsType                 Type\nhi link mlsModuleName           Type\nhi link mlsConstant             Constant\nhi link mlsString               String\nhi link mlsLongString           String\nhi link mlsSpecial              SpecialChar\nhi link mlsTodo                 Todo\nhi link mlsFlag                 Debug\nhi link mlsOperator             Operator\nhi link mlsCustomFunc           Function\nhi link mlsConst                Constant\n\nlet b:current_syntax = \"mlscript\"\n"
  }
]